The attached kms patch is for testing.  Please let me know if it fixes
any flickering or blinking problems or causes any.  The patch uses the
stricter pll_out_min in the bios rather than the less strict limited
currently used.  This limits the available divider selections except
in cases known to need a wider range (some duallink monitors).

Alex
From 9a08f099ae01de8e6e6511dbda556b1584d0fd0e Mon Sep 17 00:00:00 2001
From: Alex Deucher <alexdeuc...@gmail.com>
Date: Wed, 2 Dec 2009 19:03:52 -0500
Subject: [PATCH] drm/radeon/kms: tighten the pll range when selecting dividers

We use the pll in/out min/max values in the bios to limit our
pll divider selection.  In most cases the values in the bios
for pll_out_min are higher than the default value we were using
(64800) which gives us a more limited range of dividers.  However,
using the bios pll_out_min limit caused a problem on at least one
2560x1600 monitor.  So, use the bios pll_out_min for everything
except modes with clocks over 200 Mhz.  This should provide the
best of both worlds.

Signed-off-by: Alex Deucher <alexdeuc...@gmail.com>
---
 drivers/gpu/drm/radeon/atombios_crtc.c   |    6 ++++++
 drivers/gpu/drm/radeon/radeon_atombios.c |   10 ----------
 drivers/gpu/drm/radeon/radeon_display.c  |   13 +++++++++++--
 drivers/gpu/drm/radeon/radeon_mode.h     |    1 +
 4 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index 7a8cd93..c128e13 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -441,6 +441,12 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
 			pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
 		else
 			pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+
+		/* some duallink monitors seem to prefer dividers calculated with a wider
+		 * pll range
+		 */
+		if (mode->clock > 200000)
+			pll_flags |= RADEON_PLL_USE_DEFAULT_OUT_MIN;
 	} else {
 		pll_flags |= RADEON_PLL_LEGACY;
 
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 76825ad..a45b251 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -851,16 +851,6 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)
 				p1pll->pll_out_min = 64800;
 			else
 				p1pll->pll_out_min = 20000;
-		} else if (p1pll->pll_out_min > 64800) {
-			/* Limiting the pll output range is a good thing generally as
-			 * it limits the number of possible pll combinations for a given
-			 * frequency presumably to the ones that work best on each card.
-			 * However, certain duallink DVI monitors seem to like
-			 * pll combinations that would be limited by this at least on
-			 * pre-DCE 3.0 r6xx hardware.  This might need to be adjusted per
-			 * family.
-			 */
-			p1pll->pll_out_min = 64800;
 		}
 
 		p1pll->pll_in_min =
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index d4f4fb1..89f99c9 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -409,6 +409,8 @@ void radeon_compute_pll(struct radeon_pll *pll,
 {
 	uint32_t min_ref_div = pll->min_ref_div;
 	uint32_t max_ref_div = pll->max_ref_div;
+	uint32_t pll_out_min = pll->pll_out_min;
+	uint32_t pll_out_max = pll->pll_out_max;
 	uint32_t min_fractional_feed_div = 0;
 	uint32_t max_fractional_feed_div = 0;
 	uint32_t best_vco = pll->best_vco;
@@ -444,6 +446,13 @@ void radeon_compute_pll(struct radeon_pll *pll,
 		max_fractional_feed_div = pll->max_frac_feedback_div;
 	}
 
+	if (flags & RADEON_PLL_USE_DEFAULT_OUT_MIN) {
+		if (flags & RADEON_PLL_LEGACY)
+			pll_out_min = 20000;
+		else
+			pll_out_min = 64800;
+	}
+
 	for (post_div = pll->min_post_div; post_div <= pll->max_post_div; ++post_div) {
 		uint32_t ref_div;
 
@@ -484,10 +493,10 @@ void radeon_compute_pll(struct radeon_pll *pll,
 				tmp = (uint64_t)pll->reference_freq * feedback_div;
 				vco = radeon_div(tmp, ref_div);
 
-				if (vco < pll->pll_out_min) {
+				if (vco < pll_out_min) {
 					min_feed_div = feedback_div + 1;
 					continue;
-				} else if (vco > pll->pll_out_max) {
+				} else if (vco > pll_out_max) {
 					max_feed_div = feedback_div;
 					continue;
 				}
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 174e4a4..24c2016 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -150,6 +150,7 @@ struct radeon_tmds_pll {
 #define RADEON_PLL_PREFER_HIGH_POST_DIV (1 << 9)
 #define RADEON_PLL_USE_FRAC_FB_DIV      (1 << 10)
 #define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11)
+#define RADEON_PLL_USE_DEFAULT_OUT_MIN  (1 << 12)
 
 struct radeon_pll {
 	uint16_t reference_freq;
-- 
1.5.6.3

------------------------------------------------------------------------------
Join us December 9, 2009 for the Red Hat Virtual Experience,
a free event focused on virtualization and cloud computing. 
Attend in-depth sessions from your desk. Your couch. Anywhere.
http://p.sf.net/sfu/redhat-sfdev2dev
--
_______________________________________________
Dri-devel mailing list
Dri-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to