xf86-video-ati: Branch 'master' - 2 commits

Alex Deucher agd5f at kemper.freedesktop.org
Mon Feb 22 15:04:21 PST 2010


 src/atombios_crtc.c |   11 --
 src/legacy_crtc.c   |    4 
 src/radeon.h        |   11 --
 src/radeon_crtc.c   |  229 +++++++++++++++++++++++++++++++++++++---------------
 4 files changed, 172 insertions(+), 83 deletions(-)

New commits:
commit 0c3468d812e3790ce03d9e76779ae81e7b7b82d5
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Mon Feb 22 17:34:51 2010 -0500

    AVIVO: set frac fb divider pll flag
    
    matches previous behavior

diff --git a/src/radeon_crtc.c b/src/radeon_crtc.c
index 5deff8d..79ea4df 100644
--- a/src/radeon_crtc.c
+++ b/src/radeon_crtc.c
@@ -460,11 +460,13 @@ RADEONComputePLL(ScrnInfoPtr pScrn,
     RADEONInfoPtr info = RADEONPTR(pScrn);
 
     if (IS_AVIVO_VARIANT) {
-	if (xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, TRUE))
+	if (xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, TRUE)) {
+	    /* to match previous behavior */
+	    flags |= RADEON_PLL_USE_FRAC_FB_DIV;
 	    RADEONComputePLL_new(pll, freq, chosen_dot_clock_freq,
 				 chosen_feedback_div, chosen_frac_feedback_div,
 				 chosen_reference_div, chosen_post_div, flags);
-	else
+	} else
 	    RADEONComputePLL_old(pll, freq, chosen_dot_clock_freq,
 				 chosen_feedback_div, chosen_frac_feedback_div,
 				 chosen_reference_div, chosen_post_div, flags);
commit 212e152536c4325e6799018891d9aee132681f48
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Mon Feb 22 17:27:24 2010 -0500

    radeon: update new pll algo
    
    - add support for pre-avivo chips
    - add support for fixed post/ref dividers
    - add support for non-fractional fb dividers
    
    By default avivo chips use the new algo and
    pre-avivo chips use the old algo.  Use the
    "NewPLL" option to toggle between them (set to
    TRUE for the new algo, FALSE for the old).

diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index 07fa807..1d86643 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -437,7 +437,8 @@ static void
 atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
 {
     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
-    RADEONInfoPtr  info = RADEONPTR(crtc->scrn);
+    ScrnInfoPtr pScrn = crtc->scrn;
+    RADEONInfoPtr  info = RADEONPTR(pScrn);
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
     unsigned char *RADEONMMIO = info->MMIO;
     int index;
@@ -613,13 +614,7 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
 	}
     }
 
-    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);
+    RADEONComputePLL(pScrn, &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/legacy_crtc.c b/src/legacy_crtc.c
index 0ad762b..e4c1f04 100644
--- a/src/legacy_crtc.c
+++ b/src/legacy_crtc.c
@@ -1223,7 +1223,7 @@ RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
        return;
     }
 
-    RADEONComputePLL(pll, mode->Clock, &freq, &feedback_div, &frac_fb_div, &reference_div, &post_divider, flags);
+    RADEONComputePLL(pScrn, pll, mode->Clock, &freq, &feedback_div, &frac_fb_div, &reference_div, &post_divider, flags);
 
     for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
 	if (post_div->divider == post_divider)
@@ -1303,7 +1303,7 @@ RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
        return;
     }
 
-    RADEONComputePLL(pll, mode->Clock, &freq, &feedback_div, &frac_fb_div, &reference_div, &post_divider, flags);
+    RADEONComputePLL(pScrn, pll, mode->Clock, &freq, &feedback_div, &frac_fb_div, &reference_div, &post_divider, flags);
 
     for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
 	if (post_div->divider == post_divider)
diff --git a/src/radeon.h b/src/radeon.h
index 36b2d8b..c0b5d7a 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -1173,20 +1173,13 @@ extern void radeon_crtc_load_lut(xf86CrtcPtr crtc);
 extern void radeon_crtc_modeset_ioctl(xf86CrtcPtr crtc, Bool post);
 extern Bool RADEONAllocateControllers(ScrnInfoPtr pScrn, int mask);
 extern void RADEONBlank(ScrnInfoPtr pScrn);
-extern void RADEONComputePLL(RADEONPLLPtr pll, unsigned long freq,
+extern void RADEONComputePLL(ScrnInfoPtr pScrn,
+			     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 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_crtc.c b/src/radeon_crtc.c
index 764839c..5deff8d 100644
--- a/src/radeon_crtc.c
+++ b/src/radeon_crtc.c
@@ -132,15 +132,15 @@ static uint32_t RADEONDiv(CARD64 n, uint32_t d)
     return (n + (d / 2)) / d;
 }
 
-void
-RADEONComputePLL(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)
+static void
+RADEONComputePLL_old(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)
 {
     uint32_t min_ref_div = pll->min_ref_div;
     uint32_t max_ref_div = pll->max_ref_div;
@@ -306,79 +306,178 @@ 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)
+static Bool
+calc_fb_div(RADEONPLLPtr pll,
+            unsigned long freq,
+            int flags,
+            int post_div,
+	    int ref_div,
+            int *fb_div,
+            int *fb_div_frac)
 {
-    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);
+    float vco_freq = ffreq * post_div;
+    float feedback_divider = vco_freq * ref_div / pll->reference_freq;
 
-    /* 1 - max p */
-    p = floor(pll_out_max / ffreq);
+    if (flags & RADEON_PLL_USE_FRAC_FB_DIV) {
+        feedback_divider = floor((feedback_divider * 10.0) + 0.5) * 0.1;
 
-    /* 2 - min m */
-    m = ceil(reference_freq / pll_in_max);
+	*fb_div = floor(feedback_divider);
+        *fb_div_frac = fmod(feedback_divider, 1.0) * 10.0;
 
-    while (error > 0.25) {
-	/* 3 - n */
-	n = (ffreq / reference_freq) * m * p;
+    } else {
+        *fb_div = floor(feedback_divider + 0.5);
+        *fb_div_frac = 0;
+    }
+    if ((*fb_div < pll->min_feedback_div) || (*fb_div > pll->max_feedback_div))
+        return FALSE;
+    else
+        return TRUE;
+}
 
-	/* 4 - vco out freq */
-	f_vco = (n / m) * reference_freq;
+static Bool
+calc_fb_ref_div(RADEONPLLPtr pll,
+                unsigned long freq,
+                int flags,
+                int post_div,
+                int *fb_div,
+                int *fb_div_frac,
+                int *ref_div)
+{
+    float ffreq = freq / 10;
+    float max_error = ffreq * 0.0025;
+    float vco, error, pll_out;
 
-	/* 5 - pclk freq */
-	f_pclk = f_vco / p;
+    for ((*ref_div) = pll->min_ref_div; (*ref_div) < pll->max_ref_div; ++(*ref_div)) {
+        if (calc_fb_div(pll, freq, flags, post_div, (*ref_div), fb_div, fb_div_frac)) {
+            vco = pll->reference_freq * ((*fb_div) + ((*fb_div_frac) * 0.1)) / (*ref_div);
 
-	/* 6 - error */
-	error = (abs(f_pclk - ffreq) / f_pclk) * 100;
+            if ((vco < pll->pll_out_min) || (vco > pll->pll_out_max))
+                continue;
 
-	best_freq = reference_freq * (n / (m * p));
+            pll_out = vco / post_div;
 
-	/* min error 0.25% */
-	if (error < 0.25)
-	    break;
+            error = pll_out - ffreq;
+            if ((fabs(error) <= max_error) && (error >= 0))
+                return TRUE;
+        }
+    }
+    return FALSE;
+}
 
-	/* 7 - check m */
-	m++;
-	if ((reference_freq / m) >= pll_in_min)
-	    continue;
+static void
+RADEONComputePLL_new(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 ffreq = freq / 10;
+    float vco_frequency;
+    int fb_div = 0, fb_div_frac = 0, post_div = 0, ref_div = 0;
+    uint32_t best_freq = 0;
+
+    if (flags & RADEON_PLL_USE_POST_DIV) {
+        post_div = pll->post_div;
+        if ((post_div < pll->min_post_div) || (post_div > pll->max_post_div))
+            goto done;
+        vco_frequency = ffreq * post_div;
+        if ((vco_frequency < pll->pll_out_min) || (vco_frequency > pll->pll_out_max))
+            goto done;
+
+        if (flags & RADEON_PLL_USE_REF_DIV) {
+            ref_div = pll->reference_div;
+            if ((ref_div < pll->min_ref_div) || (ref_div > pll->max_ref_div))
+                goto done;
+            if (!calc_fb_div(pll, freq, flags, post_div, ref_div, &fb_div, &fb_div_frac))
+                goto done;
+        }
+    } else {
+	for (post_div = pll->max_post_div; post_div >= pll->min_post_div; --post_div) {
+	    if (flags & RADEON_PLL_LEGACY) {
+		if ((post_div == 5) ||
+		    (post_div == 7) ||
+		    (post_div == 9) ||
+		    (post_div == 10) ||
+		    (post_div == 11))
+		    continue;
+	    }
+	    if ((flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1))
+		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");
+	    vco_frequency = ffreq * post_div;
+	    if ((vco_frequency < pll->pll_out_min) || (vco_frequency > pll->pll_out_max))
+		continue;
+	    if (flags & RADEON_PLL_USE_REF_DIV) {
+		ref_div = pll->reference_div;
+		if ((ref_div < pll->min_ref_div) || (ref_div > pll->max_ref_div))
+		    goto done;
+		if (calc_fb_div(pll, freq, flags, post_div, ref_div, &fb_div, &fb_div_frac))
+		    break;
+	    } else {
+		if (calc_fb_ref_div(pll, freq, flags, post_div, &fb_div, &fb_div_frac, &ref_div))
+		    break;
+	    }
+	}
     }
 
-    frac_n = (n - (int)n) * 10;
+    best_freq = pll->reference_freq * 10 * fb_div;
+    best_freq += pll->reference_freq * fb_div_frac;
+    best_freq = best_freq / (ref_div * post_div);
+
+    ErrorF("best_freq: %u\n", (unsigned int)best_freq);
+    ErrorF("best_feedback_div: %u\n", (unsigned int)fb_div);
+    ErrorF("best_frac_feedback_div: %u\n", (unsigned int)fb_div_frac);
+    ErrorF("best_ref_div: %u\n", (unsigned int)ref_div);
+    ErrorF("best_post_div: %u\n", (unsigned int)post_div);
 
-    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);
+done:
+    if (best_freq == 0)
+	FatalError("Couldn't find valid PLL dividers\n");
 
     *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;
+    *chosen_feedback_div = fb_div;
+    *chosen_frac_feedback_div = fb_div_frac;
+    *chosen_reference_div = ref_div;
+    *chosen_post_div = post_div;
+
+}
+
+void
+RADEONComputePLL(ScrnInfoPtr pScrn,
+		 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)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
 
+    if (IS_AVIVO_VARIANT) {
+	if (xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, TRUE))
+	    RADEONComputePLL_new(pll, freq, chosen_dot_clock_freq,
+				 chosen_feedback_div, chosen_frac_feedback_div,
+				 chosen_reference_div, chosen_post_div, flags);
+	else
+	    RADEONComputePLL_old(pll, freq, chosen_dot_clock_freq,
+				 chosen_feedback_div, chosen_frac_feedback_div,
+				 chosen_reference_div, chosen_post_div, flags);
+    } else {
+	if (xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, FALSE))
+	    RADEONComputePLL_new(pll, freq, chosen_dot_clock_freq,
+				 chosen_feedback_div, chosen_frac_feedback_div,
+				 chosen_reference_div, chosen_post_div, flags);
+	else
+	    RADEONComputePLL_old(pll, freq, chosen_dot_clock_freq,
+				 chosen_feedback_div, chosen_frac_feedback_div,
+				 chosen_reference_div, chosen_post_div, flags);
+    }
 }
 
 static void


More information about the xorg-commit mailing list