]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/radeon/atombios_crtc.c
drm/radeon: work around KMS modeset limitations in PLL allocation (v2)
[karo-tx-linux.git] / drivers / gpu / drm / radeon / atombios_crtc.c
index 721f80e9568dfd5766179a698ad229b6576dffe5..8e32c5891be10f757fc18d2ba326c82bc3b2d4a4 100644 (file)
@@ -1492,16 +1492,16 @@ static u32 radeon_get_pll_use_mask(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_crtc *test_crtc;
-       struct radeon_crtc *radeon_test_crtc;
+       struct radeon_crtc *test_radeon_crtc;
        u32 pll_in_use = 0;
 
        list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) {
                if (crtc == test_crtc)
                        continue;
 
-               radeon_test_crtc = to_radeon_crtc(test_crtc);
-               if (radeon_test_crtc->pll_id != ATOM_PPLL_INVALID)
-                       pll_in_use |= (1 << radeon_test_crtc->pll_id);
+               test_radeon_crtc = to_radeon_crtc(test_crtc);
+               if (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID)
+                       pll_in_use |= (1 << test_radeon_crtc->pll_id);
        }
        return pll_in_use;
 }
@@ -1518,17 +1518,18 @@ static u32 radeon_get_pll_use_mask(struct drm_crtc *crtc)
 static int radeon_get_shared_dp_ppll(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
-       struct drm_encoder *test_encoder;
+       struct drm_crtc *test_crtc;
        struct radeon_crtc *test_radeon_crtc;
 
-       list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
-               if (test_encoder->crtc && (test_encoder->crtc != crtc)) {
-                       if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) {
-                               /* for DP use the same PLL for all */
-                               test_radeon_crtc = to_radeon_crtc(test_encoder->crtc);
-                               if (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID)
-                                       return test_radeon_crtc->pll_id;
-                       }
+       list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) {
+               if (crtc == test_crtc)
+                       continue;
+               test_radeon_crtc = to_radeon_crtc(test_crtc);
+               if (test_radeon_crtc->encoder &&
+                   ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_radeon_crtc->encoder))) {
+                       /* for DP use the same PLL for all */
+                       if (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID)
+                               return test_radeon_crtc->pll_id;
                }
        }
        return ATOM_PPLL_INVALID;
@@ -1547,10 +1548,8 @@ static int radeon_get_shared_nondp_ppll(struct drm_crtc *crtc)
 {
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct drm_device *dev = crtc->dev;
-       struct drm_encoder *test_encoder;
        struct drm_crtc *test_crtc;
        struct radeon_crtc *test_radeon_crtc;
-       struct radeon_encoder *test_radeon_encoder;
        u32 adjusted_clock, test_adjusted_clock;
 
        adjusted_clock = radeon_crtc->adjusted_clock;
@@ -1558,20 +1557,25 @@ static int radeon_get_shared_nondp_ppll(struct drm_crtc *crtc)
        if (adjusted_clock == 0)
                return ATOM_PPLL_INVALID;
 
-       list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
-               if (test_encoder->crtc && (test_encoder->crtc != crtc)) {
-                       if (!ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) {
-                               test_radeon_encoder = to_radeon_encoder(test_encoder);
-                               test_crtc = test_encoder->crtc;
-                               test_radeon_crtc = to_radeon_crtc(test_crtc);
-                               /* for non-DP check the clock */
-                               test_adjusted_clock = test_radeon_crtc->adjusted_clock;
-                               if ((crtc->mode.clock == test_crtc->mode.clock) &&
-                                   (adjusted_clock == test_adjusted_clock) &&
-                                   (radeon_crtc->ss_enabled == test_radeon_crtc->ss_enabled) &&
-                                   (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID))
+       list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) {
+               if (crtc == test_crtc)
+                       continue;
+               test_radeon_crtc = to_radeon_crtc(test_crtc);
+               if (test_radeon_crtc->encoder &&
+                   !ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_radeon_crtc->encoder))) {
+                       /* check if we are already driving this connector with another crtc */
+                       if (test_radeon_crtc->connector == radeon_crtc->connector) {
+                               /* if we are, return that pll */
+                               if (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID)
                                        return test_radeon_crtc->pll_id;
                        }
+                       /* for non-DP check the clock */
+                       test_adjusted_clock = test_radeon_crtc->adjusted_clock;
+                       if ((crtc->mode.clock == test_crtc->mode.clock) &&
+                           (adjusted_clock == test_adjusted_clock) &&
+                           (radeon_crtc->ss_enabled == test_radeon_crtc->ss_enabled) &&
+                           (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID))
+                               return test_radeon_crtc->pll_id;
                }
        }
        return ATOM_PPLL_INVALID;
@@ -1793,11 +1797,15 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
                if (encoder->crtc == crtc) {
                        radeon_crtc->encoder = encoder;
+                       radeon_crtc->connector = radeon_get_connector_for_encoder(encoder);
                        break;
                }
        }
-       if (radeon_crtc->encoder == NULL)
+       if ((radeon_crtc->encoder == NULL) || (radeon_crtc->connector == NULL)) {
+               radeon_crtc->encoder = NULL;
+               radeon_crtc->connector = NULL;
                return false;
+       }
        if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
                return false;
        if (!atombios_crtc_prepare_pll(crtc, adjusted_mode))
@@ -1874,6 +1882,7 @@ done:
        radeon_crtc->pll_id = ATOM_PPLL_INVALID;
        radeon_crtc->adjusted_clock = 0;
        radeon_crtc->encoder = NULL;
+       radeon_crtc->connector = NULL;
 }
 
 static const struct drm_crtc_helper_funcs atombios_helper_funcs = {
@@ -1925,5 +1934,6 @@ void radeon_atombios_init_crtc(struct drm_device *dev,
        radeon_crtc->pll_id = ATOM_PPLL_INVALID;
        radeon_crtc->adjusted_clock = 0;
        radeon_crtc->encoder = NULL;
+       radeon_crtc->connector = NULL;
        drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs);
 }