xf86-video-ati: Branch 'master'

Alex Deucher agd5f at kemper.freedesktop.org
Wed Dec 9 09:58:08 PST 2009


 src/atombios_crtc.c   |    8 ++++-
 src/radeon.h          |   11 ++++++-
 src/radeon_atombios.c |    7 +++-
 src/radeon_crtc.c     |   75 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/radeon_driver.c   |    1 
 5 files changed, 98 insertions(+), 4 deletions(-)

New commits:
commit 46630da5fd6f45bb8ea150b870162997480d69c7
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Wed Dec 9 12:55:25 2009 -0500

    AVIVO: add new PLL code
    
    This should hopefully help the problems with flickering
    and blinking monitors reported on some systems.  If there
    are problems, the old PLL algorithm can be selected with:
    Option "NewPLL" "FALSE"
    in the device section of your X config.
    
    Signed-off-by: Alex Deucher <alexdeucher at gmail.com>

diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index f9698f3..8cccba6 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -407,7 +407,13 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
 	ErrorF("after %d\n", adjust_pll_param.usPixelClock);
     }
 
-    RADEONComputePLL(&info->pll, sclock, &temp, &fb_div, &frac_fb_div, &ref_div, &post_div, pll_flags);
+    if (IS_AVIVO_VARIANT) {
+	if (xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, TRUE))
+	    RADEONComputePLL_AVIVO(&info->pll, sclock, &temp, &fb_div, &frac_fb_div, &ref_div, &post_div, pll_flags);
+	else
+	    RADEONComputePLL(&info->pll, sclock, &temp, &fb_div, &frac_fb_div, &ref_div, &post_div, pll_flags);
+    } else
+	RADEONComputePLL(&info->pll, sclock, &temp, &fb_div, &frac_fb_div, &ref_div, &post_div, pll_flags);
     sclock = temp; /* 10 khz */
 
     xf86DrvMsg(crtc->scrn->scrnIndex, X_INFO,
diff --git a/src/radeon.h b/src/radeon.h
index 182e946..10710a8 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -222,7 +222,8 @@ typedef enum {
     OPTION_ATOM_TVOUT,
     OPTION_R4XX_ATOM,
     OPTION_FORCE_LOW_POWER,
-    OPTION_DYNAMIC_PM
+    OPTION_DYNAMIC_PM,
+    OPTION_NEW_PLL
 } RADEONOpts;
 
 
@@ -1164,6 +1165,14 @@ extern void RADEONComputePLL(RADEONPLLPtr pll, unsigned long freq,
 			     uint32_t *chosen_frac_feedback_div,
 			     uint32_t *chosen_reference_div,
 			     uint32_t *chosen_post_div, int flags);
+extern void RADEONComputePLL_AVIVO(RADEONPLLPtr pll,
+				   unsigned long freq,
+				   uint32_t *chosen_dot_clock_freq,
+				   uint32_t *chosen_feedback_div,
+				   uint32_t *chosen_frac_feedback_div,
+				   uint32_t *chosen_reference_div,
+				   uint32_t *chosen_post_div,
+				   int flags);
 extern DisplayModePtr RADEONCrtcFindClosestMode(xf86CrtcPtr crtc,
 						DisplayModePtr pMode);
 extern void RADEONUnblank(ScrnInfoPtr pScrn);
diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c
index 72fbe21..c272c9a 100644
--- a/src/radeon_atombios.c
+++ b/src/radeon_atombios.c
@@ -2204,14 +2204,17 @@ RADEONGetATOMClockInfo(ScrnInfoPtr pScrn)
     if (pll->pll_out_min == 0)
 	pll->pll_out_min = 64800;
 
+
     /* limiting the range is a good thing in most cases
      * as it limits the number of matching pll combinations,
      * however, some duallink DVI monitors seem to prefer combinations that
      * would be limited by this.  This may need to be revisited
      * per chip family.
      */
-    if (pll->pll_out_min > 64800)
-	pll->pll_out_min = 64800;
+    if (!xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, TRUE)) {
+	if (pll->pll_out_min > 64800)
+	    pll->pll_out_min = 64800;
+    }
 
     return TRUE;
 }
diff --git a/src/radeon_crtc.c b/src/radeon_crtc.c
index 3899064..4e8b490 100644
--- a/src/radeon_crtc.c
+++ b/src/radeon_crtc.c
@@ -301,6 +301,81 @@ RADEONComputePLL(RADEONPLLPtr pll,
 
 }
 
+void
+RADEONComputePLL_AVIVO(RADEONPLLPtr pll,
+		       unsigned long freq,
+		       uint32_t *chosen_dot_clock_freq,
+		       uint32_t *chosen_feedback_div,
+		       uint32_t *chosen_frac_feedback_div,
+		       uint32_t *chosen_reference_div,
+		       uint32_t *chosen_post_div,
+		       int flags)
+{
+    float m, n, frac_n, p, f_vco, f_pclk, best_freq;
+    float pll_out_max = pll->pll_out_max;
+    float pll_out_min = pll->pll_out_min;
+    float reference_freq = pll->reference_freq;
+    float pll_in_max = pll->pll_in_max;
+    float pll_in_min = pll->pll_in_min;
+    float ffreq = freq / 10;
+    float error = 100;
+
+    ErrorF("ffreq: %f\n", ffreq * 10);
+
+    /* 1 - max p */
+    p = floor(pll_out_max / ffreq);
+
+    /* 2 - min m */
+    m = ceil(reference_freq / pll_in_max);
+
+    while (error > 0.25) {
+	/* 3 - n */
+	n = (ffreq / reference_freq) * m * p;
+
+	/* 4 - vco out freq */
+	f_vco = (n / m) * reference_freq;
+
+	/* 5 - pclk freq */
+	f_pclk = f_vco / p;
+
+	/* 6 - error */
+	error = (abs(f_pclk - ffreq) / f_pclk) * 100;
+
+	best_freq = reference_freq * (n / (m * p));
+
+	/* min error 0.25% */
+	if (error < 0.25)
+	    break;
+
+	/* 7 - check m */
+	m++;
+	if ((reference_freq / m) >= pll_in_min)
+	    continue;
+
+	/* 8 - check p */
+	m = ceil(reference_freq / pll_in_max);
+	p--;
+	if ((p * ffreq) >= pll_out_min)
+	    continue;
+	else
+	    FatalError("Couldn't find valid PLL dividers\n");
+    }
+
+    frac_n = (n - (int)n) * 10;
+
+    ErrorF("best_freq: %u\n", (unsigned int)best_freq * 10);
+    ErrorF("best_feedback_div: %d.%d\n", (int)n, (int)frac_n);
+    ErrorF("best_ref_div: %d\n", (int)m);
+    ErrorF("best_post_div: %d\n", (int)p);
+
+    *chosen_dot_clock_freq = best_freq;
+    *chosen_feedback_div = (uint32_t)n;
+    *chosen_frac_feedback_div = (uint32_t)frac_n;
+    *chosen_reference_div = (uint32_t)m;
+    *chosen_post_div = (uint32_t)p;
+
+}
+
 static void
 radeon_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
 		     DisplayModePtr adjusted_mode, int x, int y)
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index bf560f7..ae4993b 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -205,6 +205,7 @@ static const OptionInfoRec RADEONOptions[] = {
     { OPTION_R4XX_ATOM,	        "R4xxATOM",	   OPTV_BOOLEAN, {0}, FALSE },
     { OPTION_FORCE_LOW_POWER,	"ForceLowPowerMode", OPTV_BOOLEAN, {0}, FALSE },
     { OPTION_DYNAMIC_PM,	"DynamicPM",       OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_NEW_PLL,	        "NewPLL",        OPTV_BOOLEAN, {0}, FALSE },
     { -1,                    NULL,               OPTV_NONE,    {0}, FALSE }
 };
 


More information about the xorg-commit mailing list