From: Alex Deucher <alexander.deuc...@amd.com>

For DP we can use the same PPLL for all active DP
encoders.  Take advantage of that to prevent cases
where we may end up sharing a PPLL between DP and
non-DP which won't work.  Also clean up the code
a bit.

Signed-off-by: Alex Deucher <alexander.deuc...@amd.com>
---
 drivers/gpu/drm/radeon/atombios_crtc.c |  100 +++++++++++++++++++++----------
 1 files changed, 68 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c 
b/drivers/gpu/drm/radeon/atombios_crtc.c
index 9dc0220..6c300f1 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -1503,6 +1503,24 @@ static void radeon_legacy_atom_fixup(struct drm_crtc 
*crtc)
        }
 }
 
+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;
+}
+
 static int radeon_atom_pick_pll(struct drm_crtc *crtc)
 {
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
@@ -1510,7 +1528,7 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
        struct radeon_device *rdev = dev->dev_private;
        struct drm_encoder *test_encoder;
        struct drm_crtc *test_crtc;
-       uint32_t pll_in_use = 0;
+       u32 pll_in_use;
 
        if (ASIC_IS_DCE61(rdev)) {
                list_for_each_entry(test_encoder, 
&dev->mode_config.encoder_list, head) {
@@ -1522,32 +1540,45 @@ 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)
+                                               return ATOM_PPLL_INVALID;
+                                       else {
+                                               list_for_each_entry(test_crtc, 
&dev->mode_config.crtc_list, head) {
+                                                       struct radeon_crtc 
*radeon_test_crtc;
+
+                                                       if (crtc == test_crtc)
+                                                               continue;
+
+                                                       /* for DP use the same 
PLL for all */
+                                                       radeon_test_crtc = 
to_radeon_crtc(test_crtc);
+                                                       if 
(radeon_test_crtc->pll_id != ATOM_PPLL_INVALID)
+                                                               return 
radeon_test_crtc->pll_id;
+                                               }
+                                       }
+                               }
                        }
                }
                /* UNIPHY B/C/D/E/F */
-               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))
+               pll_in_use = radeon_get_pll_use_mask(crtc);
+               if (!(pll_in_use & (1 << ATOM_PPLL0)))
                        return ATOM_PPLL0;
-               return ATOM_PPLL1;
+               if (!(pll_in_use & (1 << ATOM_PPLL1)))
+                       return ATOM_PPLL1;
+               DRM_ERROR("unable to allocate a PPLL\n");
+               return ATOM_PPLL_INVALID;
        } 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: DCPLL or ext clock
+                                * DCE5: PPLL, DCPLL, or ext clock
+                                * DCE6: PPLL, PPLL0, or ext clock
                                 *
                                 * Setting ATOM_PPLL_INVALID will cause 
SetPixelClock to skip
                                 * PPLL/DCPLL programming and only program the 
DP DTO for the
@@ -1560,25 +1591,30 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
                                                return ATOM_PPLL0;
                                        else if (ASIC_IS_DCE5(rdev))
                                                return ATOM_DCPLL;
+                                       else {
+                                               list_for_each_entry(test_crtc, 
&dev->mode_config.crtc_list, head) {
+                                                       struct radeon_crtc 
*radeon_test_crtc;
+
+                                                       if (crtc == test_crtc)
+                                                               continue;
+
+                                                       /* for DP use the same 
PLL for all */
+                                                       radeon_test_crtc = 
to_radeon_crtc(test_crtc);
+                                                       if 
(radeon_test_crtc->pll_id != ATOM_PPLL_INVALID)
+                                                               return 
radeon_test_crtc->pll_id;
+                                               }
+                                       }
                                }
                        }
                }
-
-               /* 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))
+               /* non DP */
+               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)))
                        return ATOM_PPLL1;
-               return ATOM_PPLL2;
+               DRM_ERROR("unable to allocate a PPLL\n");
+               return ATOM_PPLL_INVALID;
        } else
                return radeon_crtc->crtc_id;
 
@@ -1721,7 +1757,7 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)
                break;
        }
 done:
-       radeon_crtc->pll_id = -1;
+       radeon_crtc->pll_id = ATOM_PPLL_INVALID;
 }
 
 static const struct drm_crtc_helper_funcs atombios_helper_funcs = {
-- 
1.7.7.5

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to