diff mbox

radeon: fix pll/ctrc mapping on dce2 and dce3 hardware

Message ID 1354050749-3133-1-git-send-email-j.glisse@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jerome Glisse Nov. 27, 2012, 9:12 p.m. UTC
From: Jerome Glisse <jglisse@redhat.com>

This fix black screen on resume issue that some people are
experiencing. There is a bug in the atombios code regarding
pll/crtc mapping. The atombios code reverse the logic for
the pll and crtc mapping.

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
---
 drivers/gpu/drm/radeon/atombios_crtc.c | 54 +++++++++++++---------------------
 1 file changed, 20 insertions(+), 34 deletions(-)

Comments

Alex Deucher Nov. 27, 2012, 9:33 p.m. UTC | #1
On Tue, Nov 27, 2012 at 4:12 PM,  <j.glisse@gmail.com> wrote:
> From: Jerome Glisse <jglisse@redhat.com>
>
> This fix black screen on resume issue that some people are
> experiencing. There is a bug in the atombios code regarding
> pll/crtc mapping. The atombios code reverse the logic for
> the pll and crtc mapping.
>
> Signed-off-by: Jerome Glisse <jglisse@redhat.com>
> ---
>  drivers/gpu/drm/radeon/atombios_crtc.c | 54 +++++++++++++---------------------
>  1 file changed, 20 insertions(+), 34 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
> index 3bce029..7c1f080 100644
> --- a/drivers/gpu/drm/radeon/atombios_crtc.c
> +++ b/drivers/gpu/drm/radeon/atombios_crtc.c
> @@ -1696,42 +1696,28 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
>                         return ATOM_PPLL2;
>                 DRM_ERROR("unable to allocate a PPLL\n");
>                 return ATOM_PPLL_INVALID;
> -       } else if (ASIC_IS_AVIVO(rdev)) {
> -               /* in DP mode, the DP ref clock can come from either PPLL
> -                * depending on the asic:
> -                * DCE3: PPLL1 or PPLL2
> -                */
> -               if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) {
> -                       /* use the same PPLL for all DP monitors */
> -                       pll = radeon_get_shared_dp_ppll(crtc);
> -                       if (pll != ATOM_PPLL_INVALID)
> -                               return pll;
> -               } else {
> -                       /* use the same PPLL for all monitors with the same clock */
> -                       pll = radeon_get_shared_nondp_ppll(crtc);
> -                       if (pll != ATOM_PPLL_INVALID)
> -                               return pll;
> -               }
> -               /* all other cases */
> -               pll_in_use = radeon_get_pll_use_mask(crtc);
> -               /* the order shouldn't matter here, but we probably
> -                * need this until we have atomic modeset
> -                */
> -               if (rdev->flags & RADEON_IS_IGP) {
> -                       if (!(pll_in_use & (1 << ATOM_PPLL1)))
> -                               return ATOM_PPLL1;
> -                       if (!(pll_in_use & (1 << ATOM_PPLL2)))
> -                               return ATOM_PPLL2;
> -               } else {
> -                       if (!(pll_in_use & (1 << ATOM_PPLL2)))
> -                               return ATOM_PPLL2;
> -                       if (!(pll_in_use & (1 << ATOM_PPLL1)))
> -                               return ATOM_PPLL1;
> -               }
> -               DRM_ERROR("unable to allocate a PPLL\n");
> -               return ATOM_PPLL_INVALID;
>         } else {
>                 /* on pre-R5xx asics, the crtc to pll mapping is hardcoded */
> +               /* some atombios (observed in some DCE2/DCE3) code have a bug,
> +                * the matching btw pll and crtc is done through
> +                * PCLK_CRTC[1|2]_CNTL (0x480/0x484) but atombios code use the
> +                * pll (1 or 2) to select which register to write. ie if using
> +                * pll1 it will use PCLK_CRTC1_CNTL (0x480) and if using pll2
> +                * it will use PCLK_CRTC2_CNTL (0x484), it then use crtc id to
> +                * choose which value to write. Which is reverse order from
> +                * register logic. So only case that works is when pllid is
> +                * same as crtcid or when both pll and crtc are enabled and
> +                * both use same clock.
> +                *
> +                * So just return crtc id as if crtc and pll were hard linked
> +                * together even if they aren't
> +                */
> +               if (radeon_crtc->crtc_id > 1) {
> +                       /* crtc other than crtc1 and crtc2 can only be use for
> +                        * DP those doesn't need a valid pll to work.
> +                        */
> +                       return ATOM_PPLL_INVALID;
> +               }

We can drop the check above as pre-DCE4 asics never have more than 2
crtcs.  Other than that, looks good.

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>

>                 return radeon_crtc->crtc_id;
>         }
>  }
> --
> 1.7.11.7
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
diff mbox

Patch

diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index 3bce029..7c1f080 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -1696,42 +1696,28 @@  static int radeon_atom_pick_pll(struct drm_crtc *crtc)
 			return ATOM_PPLL2;
 		DRM_ERROR("unable to allocate a PPLL\n");
 		return ATOM_PPLL_INVALID;
-	} else if (ASIC_IS_AVIVO(rdev)) {
-		/* in DP mode, the DP ref clock can come from either PPLL
-		 * depending on the asic:
-		 * DCE3: PPLL1 or PPLL2
-		 */
-		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) {
-			/* use the same PPLL for all DP monitors */
-			pll = radeon_get_shared_dp_ppll(crtc);
-			if (pll != ATOM_PPLL_INVALID)
-				return pll;
-		} else {
-			/* use the same PPLL for all monitors with the same clock */
-			pll = radeon_get_shared_nondp_ppll(crtc);
-			if (pll != ATOM_PPLL_INVALID)
-				return pll;
-		}
-		/* all other cases */
-		pll_in_use = radeon_get_pll_use_mask(crtc);
-		/* the order shouldn't matter here, but we probably
-		 * need this until we have atomic modeset
-		 */
-		if (rdev->flags & RADEON_IS_IGP) {
-			if (!(pll_in_use & (1 << ATOM_PPLL1)))
-				return ATOM_PPLL1;
-			if (!(pll_in_use & (1 << ATOM_PPLL2)))
-				return ATOM_PPLL2;
-		} else {
-			if (!(pll_in_use & (1 << ATOM_PPLL2)))
-				return ATOM_PPLL2;
-			if (!(pll_in_use & (1 << ATOM_PPLL1)))
-				return ATOM_PPLL1;
-		}
-		DRM_ERROR("unable to allocate a PPLL\n");
-		return ATOM_PPLL_INVALID;
 	} else {
 		/* on pre-R5xx asics, the crtc to pll mapping is hardcoded */
+		/* some atombios (observed in some DCE2/DCE3) code have a bug,
+		 * the matching btw pll and crtc is done through
+		 * PCLK_CRTC[1|2]_CNTL (0x480/0x484) but atombios code use the
+		 * pll (1 or 2) to select which register to write. ie if using
+		 * pll1 it will use PCLK_CRTC1_CNTL (0x480) and if using pll2
+		 * it will use PCLK_CRTC2_CNTL (0x484), it then use crtc id to
+		 * choose which value to write. Which is reverse order from
+		 * register logic. So only case that works is when pllid is
+		 * same as crtcid or when both pll and crtc are enabled and
+		 * both use same clock.
+		 *
+		 * So just return crtc id as if crtc and pll were hard linked
+		 * together even if they aren't
+		 */
+		if (radeon_crtc->crtc_id > 1) {
+			/* crtc other than crtc1 and crtc2 can only be use for
+			 * DP those doesn't need a valid pll to work.
+			 */
+			return ATOM_PPLL_INVALID;
+		}
 		return radeon_crtc->crtc_id;
 	}
 }