Revert "drm/radeon: rework pll selection (v3)"
authorAlex Deucher <alexander.deucher@amd.com>
Mon, 17 Sep 2012 21:26:24 +0000 (17:26 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 17 Sep 2012 21:26:24 +0000 (17:26 -0400)
This reverts commit 985f61f7ee647ad570c05eab0b74915da2ac8e19.

This commit fixed certain cases, but ended up regressing others
due to limitations in the current KMS API.  A proper fix is too
invasive for 3.6.  Push it back to 3.7.

Reported-by: Andres Freund <andres@anarazel.de>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/radeon/atombios_crtc.c

index e721e3087b99d88556c39701605faf37e99fbc8b..2817101fb167eb1f70ac36d88e2f4f1c58dd2427 100644 (file)
@@ -1479,98 +1479,14 @@ static void radeon_legacy_atom_fixup(struct drm_crtc *crtc)
        }
 }
 
-/**
- * radeon_get_pll_use_mask - look up a mask of which pplls are in use
- *
- * @crtc: drm crtc
- *
- * Returns the mask of which PPLLs (Pixel PLLs) are in use.
- */
-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;
-       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);
-       }
-       return pll_in_use;
-}
-
-/**
- * radeon_get_shared_dp_ppll - return the PPLL used by another crtc for DP
- *
- * @crtc: drm crtc
- *
- * Returns the PPLL (Pixel PLL) used by another crtc/encoder which is
- * also in DP mode.  For DP, a single PPLL can be used for all DP
- * crtcs/encoders.
- */
-static int radeon_get_shared_dp_ppll(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_encoder *test_encoder;
-       struct radeon_crtc *radeon_test_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 */
-                               radeon_test_crtc = to_radeon_crtc(test_encoder->crtc);
-                               if (radeon_test_crtc->pll_id != ATOM_PPLL_INVALID)
-                                       return radeon_test_crtc->pll_id;
-                       }
-               }
-       }
-       return ATOM_PPLL_INVALID;
-}
-
-/**
- * radeon_atom_pick_pll - Allocate a PPLL for use by the crtc.
- *
- * @crtc: drm crtc
- *
- * Returns the PPLL (Pixel PLL) to be used by the crtc.  For DP monitors
- * a single PPLL can be used for all DP crtcs/encoders.  For non-DP
- * monitors a dedicated PPLL must be used.  If a particular board has
- * an external DP PLL, return ATOM_PPLL_INVALID to skip PLL programming
- * as there is no need to program the PLL itself.  If we are not able to
- * allocate a PLL, return ATOM_PPLL_INVALID to skip PLL programming to
- * avoid messing up an existing monitor.
- *
- * Asic specific PLL information
- *
- * DCE 6.1
- * - PPLL2 is only available to UNIPHYA (both DP and non-DP)
- * - PPLL0, PPLL1 are available for UNIPHYB/C/D/E/F (both DP and non-DP)
- *
- * DCE 6.0
- * - PPLL0 is available to all UNIPHY (DP only)
- * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC
- *
- * DCE 5.0
- * - DCPLL is available to all UNIPHY (DP only)
- * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC
- *
- * DCE 3.0/4.0/4.1
- * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC
- *
- */
 static int radeon_atom_pick_pll(struct drm_crtc *crtc)
 {
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct radeon_device *rdev = dev->dev_private;
        struct drm_encoder *test_encoder;
-       u32 pll_in_use;
-       int pll;
+       struct drm_crtc *test_crtc;
+       uint32_t pll_in_use = 0;
 
        if (ASIC_IS_DCE61(rdev)) {
                list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
@@ -1582,40 +1498,32 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
 
                                if ((test_radeon_encoder->encoder_id ==
                                     ENCODER_OBJECT_ID_INTERNAL_UNIPHY) &&
-                                   (dig->linkb == false))
-                                       /* UNIPHY A uses PPLL2 */
+                                   (dig->linkb == false)) /* UNIPHY A uses PPLL2 */
                                        return ATOM_PPLL2;
-                               else if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) {
-                                       /* UNIPHY B/C/D/E/F */
-                                       if (rdev->clock.dp_extclk)
-                                               /* skip PPLL programming if using ext clock */
-                                               return ATOM_PPLL_INVALID;
-                                       else {
-                                               /* use the same PPLL for all DP monitors */
-                                               pll = radeon_get_shared_dp_ppll(crtc);
-                                               if (pll != ATOM_PPLL_INVALID)
-                                                       return pll;
-                                       }
-                               }
-                               break;
                        }
                }
                /* UNIPHY B/C/D/E/F */
-               pll_in_use = radeon_get_pll_use_mask(crtc);
-               if (!(pll_in_use & (1 << ATOM_PPLL0)))
+               list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) {
+                       struct radeon_crtc *radeon_test_crtc;
+
+                       if (crtc == test_crtc)
+                               continue;
+
+                       radeon_test_crtc = to_radeon_crtc(test_crtc);
+                       if ((radeon_test_crtc->pll_id == ATOM_PPLL0) ||
+                           (radeon_test_crtc->pll_id == ATOM_PPLL1))
+                               pll_in_use |= (1 << radeon_test_crtc->pll_id);
+               }
+               if (!(pll_in_use & 4))
                        return ATOM_PPLL0;
-               if (!(pll_in_use & (1 << ATOM_PPLL1)))
-                       return ATOM_PPLL1;
-               DRM_ERROR("unable to allocate a PPLL\n");
-               return ATOM_PPLL_INVALID;
+               return ATOM_PPLL1;
        } else if (ASIC_IS_DCE4(rdev)) {
                list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
                        if (test_encoder->crtc && (test_encoder->crtc == crtc)) {
                                /* in DP mode, the DP ref clock can come from PPLL, DCPLL, or ext clock,
                                 * depending on the asic:
                                 * DCE4: PPLL or ext clock
-                                * DCE5: PPLL, DCPLL, or ext clock
-                                * DCE6: PPLL, PPLL0, or ext clock
+                                * DCE5: DCPLL or ext clock
                                 *
                                 * Setting ATOM_PPLL_INVALID will cause SetPixelClock to skip
                                 * PPLL/DCPLL programming and only program the DP DTO for the
@@ -1623,34 +1531,31 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
                                 */
                                if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) {
                                        if (rdev->clock.dp_extclk)
-                                               /* skip PPLL programming if using ext clock */
                                                return ATOM_PPLL_INVALID;
                                        else if (ASIC_IS_DCE6(rdev))
-                                               /* use PPLL0 for all DP */
                                                return ATOM_PPLL0;
                                        else if (ASIC_IS_DCE5(rdev))
-                                               /* use DCPLL for all DP */
                                                return ATOM_DCPLL;
-                                       else {
-                                               /* use the same PPLL for all DP monitors */
-                                               pll = radeon_get_shared_dp_ppll(crtc);
-                                               if (pll != ATOM_PPLL_INVALID)
-                                                       return pll;
-                                       }
                                }
-                               break;
                        }
                }
-               /* all other cases */
-               pll_in_use = radeon_get_pll_use_mask(crtc);
-               if (!(pll_in_use & (1 << ATOM_PPLL2)))
-                       return ATOM_PPLL2;
-               if (!(pll_in_use & (1 << ATOM_PPLL1)))
+
+               /* otherwise, pick one of the plls */
+               list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) {
+                       struct radeon_crtc *radeon_test_crtc;
+
+                       if (crtc == test_crtc)
+                               continue;
+
+                       radeon_test_crtc = to_radeon_crtc(test_crtc);
+                       if ((radeon_test_crtc->pll_id >= ATOM_PPLL1) &&
+                           (radeon_test_crtc->pll_id <= ATOM_PPLL2))
+                               pll_in_use |= (1 << radeon_test_crtc->pll_id);
+               }
+               if (!(pll_in_use & 1))
                        return ATOM_PPLL1;
-               DRM_ERROR("unable to allocate a PPLL\n");
-               return ATOM_PPLL_INVALID;
+               return ATOM_PPLL2;
        } else
-               /* use PPLL1 or PPLL2 */
                return radeon_crtc->crtc_id;
 
 }
@@ -1792,7 +1697,7 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)
                break;
        }
 done:
-       radeon_crtc->pll_id = ATOM_PPLL_INVALID;
+       radeon_crtc->pll_id = -1;
 }
 
 static const struct drm_crtc_helper_funcs atombios_helper_funcs = {
@@ -1841,6 +1746,6 @@ void radeon_atombios_init_crtc(struct drm_device *dev,
                else
                        radeon_crtc->crtc_offset = 0;
        }
-       radeon_crtc->pll_id = ATOM_PPLL_INVALID;
+       radeon_crtc->pll_id = -1;
        drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs);
 }