xf86-video-ati: Branch 'atombios-support'

Alex Deucher agd5f at kemper.freedesktop.org
Thu Dec 13 15:46:09 PST 2007


 src/atombios_crtc.c |   89 ++++------------------------------------------------
 src/radeon.h        |   10 +++--
 src/radeon_bios.c   |   28 ++++++++++++----
 src/radeon_crtc.c   |   12 ++-----
 src/radeon_driver.c |   34 ++++++++++++-------
 5 files changed, 60 insertions(+), 113 deletions(-)

New commits:
commit 814c6c48aebba2e45ce257289b922cd7e92caf2a
Author: Alex Deucher <alex at samba.(none)>
Date:   Thu Dec 13 18:45:09 2007 -0500

    RADEON: rework PLL calculation
    
    - Take into account the limits from the bios tables
    - Unify the PLL calculation between legacy and avivo chips

diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index 5b09107..2297316 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -148,82 +148,6 @@ atombios_set_crtc_timing(atomBiosHandlePtr atomBIOS, SET_CRTC_TIMING_PARAMETERS_
     return ATOM_NOT_IMPLEMENTED;
 }
 
-/*
- * Calculate the PLL parameters for a given dotclock.
- */
-#define RADEON_PLL_DEFAULT_PLLOUT_MIN  64800 /* experimental. - taken from rhd divided by 10 */
-
-static Bool
-PLLCalculate(ScrnInfoPtr pScrn, CARD32 PixelClock,
-	     CARD16 *RefDivider, CARD16 *FBDivider, CARD8 *PostDivider)
-{
-/* limited by the number of bits available */
-#define FB_DIV_LIMIT 1024 /* rv6x0 doesn't like 2048 */
-#define REF_DIV_LIMIT 1024
-#define POST_DIV_LIMIT 128
-    RADEONInfoPtr info = RADEONPTR (pScrn);
-    RADEONPLLPtr pll = &info->pll;
-    CARD32 FBDiv, RefDiv, PostDiv, BestDiff = 0xFFFFFFFF;
-    float Ratio;
-
-    Ratio = ((float) PixelClock) / ((float) pll->reference_freq * 10);
-
-    if (pll->min_pll_freq == 0)
-      pll->min_pll_freq = RADEON_PLL_DEFAULT_PLLOUT_MIN;
-    for (PostDiv = 2; PostDiv < POST_DIV_LIMIT; PostDiv++) {
-	CARD32 VCOOut = PixelClock * PostDiv;
-
-	/* we are conservative and avoid the limits */
-	if (VCOOut <= pll->min_pll_freq * 10)
-	    continue;
-	if (VCOOut >= pll->max_pll_freq * 10)
-	    break;
-
-        for (RefDiv = 1; RefDiv <= REF_DIV_LIMIT; RefDiv++)
-	{
-	    CARD32 Diff;
-
-	    FBDiv = (CARD32) ((Ratio * PostDiv * RefDiv) + 0.5);
-
-	    if (FBDiv >= FB_DIV_LIMIT)
-	      break;
-
-	    if (FBDiv > (500 + (13 * RefDiv))) /* rv6x0 limit */
-		break;
-
-	    Diff = abs( PixelClock - (FBDiv * pll->reference_freq * 10) / (PostDiv * RefDiv) );
-
-	    if (Diff < BestDiff) {
-		*FBDivider = FBDiv;
-		*RefDivider = RefDiv;
-		*PostDivider = PostDiv;
-		BestDiff = Diff;
-	    }
-
-	    if (BestDiff == 0)
-		break;
-	}
-	if (BestDiff == 0)
-	    break;
-    }
-
-    if (BestDiff != 0xFFFFFFFF) {
-	ErrorF("PLL Calculation: %dkHz = "
-		   "(((0x%X / 0x%X) * 0x%X) / 0x%X) (%dkHz off)\n",
-		   (int) PixelClock, (unsigned int) pll->reference_freq * 10, *RefDivider,
-		   *FBDivider, *PostDivider, (int) BestDiff);
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PLL for %dkHz uses %dkHz internally.\n",
-		   (int) PixelClock,
-		   (int) (pll->reference_freq * 10 * *FBDivider) / *RefDivider);
-	return TRUE;
-    } else { /* Should never happen */
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "%s: Failed to get a valid PLL setting for %dkHz\n",
-		   __func__, (int) PixelClock);
-	return FALSE;
-    }
-}
-
 void
 atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
 {
@@ -231,7 +155,7 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
     RADEONInfoPtr  info = RADEONPTR(crtc->scrn);
     unsigned char *RADEONMMIO = info->MMIO;
     int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
-    int sclock = mode->Clock;
+    CARD32 sclock = mode->Clock;
     uint16_t ref_div = 0, fb_div = 0;
     uint8_t post_div = 0;
     int major, minor;
@@ -240,10 +164,11 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
     AtomBiosArgRec data;
     unsigned char *space;
     RADEONSavePtr save = info->ModeReg;
-    
+
     if (IS_AVIVO_VARIANT) {
-        CARD32 temp;
-        PLLCalculate(crtc->scrn, sclock, &ref_div, &fb_div, &post_div);
+	CARD32 temp;
+	RADEONComputePLL(&info->pll, mode->Clock * 1000, &sclock, &fb_div, &ref_div, &post_div);
+	sclock /= 1000;
 
 	/* disable spread spectrum clocking for now -- thanks Hedy Lamarr */
 	if (radeon_crtc->crtc_id == 0) {
@@ -268,7 +193,7 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
 	       radeon_crtc->crtc_id, ref_div, fb_div, fb_div, post_div);
 
     atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
-    
+
     ErrorF("table is %d %d\n", major, minor);
     switch(major) {
     case 1:
@@ -304,7 +229,7 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
 	ErrorF("Set CRTC PLL success\n");
 	return;
     }
-  
+
     ErrorF("Set CRTC PLL failed\n");
     return;
 }
diff --git a/src/radeon.h b/src/radeon.h
index 038fcc7..6c38826 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -203,16 +203,18 @@ typedef struct {
 typedef struct {
     CARD16            reference_freq;
     CARD16            reference_div;
-    CARD32            min_pll_freq;
-    CARD32            max_pll_freq;
+    CARD32            pll_in_min;
+    CARD32            pll_in_max;
+    CARD32            pll_out_min;
+    CARD32            pll_out_max;
     CARD16            xclk;
 
     CARD32            min_ref_div;
     CARD32            max_ref_div;
+    CARD32            min_post_div;
+    CARD32            max_post_div;
     CARD32            min_feedback_div;
     CARD32            max_feedback_div;
-    CARD32            pll_in_min;
-    CARD32            pll_in_max;
     CARD32            best_vco;
 } RADEONPLLRec, *RADEONPLLPtr;
 
diff --git a/src/radeon_bios.c b/src/radeon_bios.c
index 7b4eafb..9730119 100644
--- a/src/radeon_bios.c
+++ b/src/radeon_bios.c
@@ -611,8 +611,19 @@ Bool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn)
 					or use a new algorithm to calculate
 					from min_input and max_input
 				     */
-	    pll->min_pll_freq = RADEON_BIOS16 (pll_info_block + 78);
-	    pll->max_pll_freq = RADEON_BIOS32 (pll_info_block + 32);
+	    pll->pll_out_min = RADEON_BIOS16 (pll_info_block + 78);
+	    pll->pll_out_max = RADEON_BIOS32 (pll_info_block + 32);
+
+	    if (pll->pll_out_min == 0) {
+		if (IS_AVIVO_VARIANT)
+		    pll->pll_out_min = 64800;
+		else
+		    pll->pll_out_min = 20000;
+	    }
+
+	    pll->pll_in_min = RADEON_BIOS16 (pll_info_block + 74);
+	    pll->pll_in_max = RADEON_BIOS16 (pll_info_block + 76);
+
 	    pll->xclk = RADEON_BIOS16 (pll_info_block + 72);
 
 	    info->sclk = RADEON_BIOS32(pll_info_block + 8) / 100.0;
@@ -622,8 +633,13 @@ Bool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn)
 
 	    pll->reference_freq = RADEON_BIOS16 (pll_info_block + 0x0e);
 	    pll->reference_div = RADEON_BIOS16 (pll_info_block + 0x10);
-	    pll->min_pll_freq = RADEON_BIOS32 (pll_info_block + 0x12);
-	    pll->max_pll_freq = RADEON_BIOS32 (pll_info_block + 0x16);
+	    pll->pll_out_min = RADEON_BIOS32 (pll_info_block + 0x12);
+	    pll->pll_out_max = RADEON_BIOS32 (pll_info_block + 0x16);
+
+	    /* not available in the bios */
+	    pll->pll_in_min = 40;
+	    pll->pll_in_max = 100;
+
 	    pll->xclk = RADEON_BIOS16 (pll_info_block + 0x08);
 
 	    info->sclk = RADEON_BIOS16(pll_info_block + 8) / 100.0;
@@ -636,8 +652,8 @@ Bool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn)
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ref_freq: %d, min_pll: %u, "
 	       "max_pll: %u, xclk: %d, sclk: %f, mclk: %f\n",
-	       pll->reference_freq, (unsigned)pll->min_pll_freq,
-	       (unsigned)pll->max_pll_freq, pll->xclk, info->sclk,
+	       pll->reference_freq, (unsigned)pll->pll_out_min,
+	       (unsigned)pll->pll_out_max, pll->xclk, info->sclk,
 	       info->mclk);
 
     return TRUE;
diff --git a/src/radeon_crtc.c b/src/radeon_crtc.c
index cf78e2c..45eb1ac 100644
--- a/src/radeon_crtc.c
+++ b/src/radeon_crtc.c
@@ -631,7 +631,7 @@ static CARD32 RADEONDiv64(CARD64 n, CARD32 d)
     return (n + (d / 2)) / d;
 }
 
-static void
+void
 RADEONComputePLL(RADEONPLLPtr pll,
 		 unsigned long freq,
 		 CARD32 *chosen_dot_clock_freq,
@@ -639,10 +639,6 @@ RADEONComputePLL(RADEONPLLPtr pll,
 		 CARD32 *chosen_reference_div,
 		 CARD32 *chosen_post_div)
 {
-    int post_divs[] = {1, 2, 4, 8, 3, 6, 12, 0};
-
-    int i;
-
     CARD32 best_vco = pll->best_vco;
     CARD32 best_post_div = 1;
     CARD32 best_ref_div = 1;
@@ -650,15 +646,15 @@ RADEONComputePLL(RADEONPLLPtr pll,
     CARD32 best_freq = 1;
     CARD32 best_error = 0xffffffff;
     CARD32 best_vco_diff = 1;
+    CARD32 post_div;
 
     ErrorF("freq: %lu\n", freq);
 
-    for (i = 0; post_divs[i]; i++) {
-	int post_div = post_divs[i];
+    for (post_div = pll->min_post_div; post_div <= pll->max_post_div; ++post_div) {
 	CARD32 ref_div;
 	CARD32 vco = (freq / 10000) * post_div;
 
-	if (vco < pll->min_pll_freq || vco > pll->max_pll_freq)
+	if (vco < pll->pll_out_min || vco > pll->pll_out_max)
 	    continue;
 
 	for (ref_div = pll->min_ref_div; ref_div <= pll->max_ref_div; ++ref_div) {
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 2c5e64f..16d758b 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -1162,22 +1162,25 @@ static void RADEONGetClockInfo(ScrnInfoPtr pScrn)
 
 	    if (pll->reference_div < 2) pll->reference_div = 12;
 	}
-	
     } else {
 	xf86DrvMsg (pScrn->scrnIndex, X_WARNING,
 		    "Video BIOS not detected, using default clock settings!\n");
 
        /* Default min/max PLL values */
        if (info->ChipFamily == CHIP_FAMILY_R420 || info->ChipFamily == CHIP_FAMILY_RV410) {
-           pll->min_pll_freq = 20000;
-           pll->max_pll_freq = 50000;
+	   pll->pll_in_min = 100;
+	   pll->pll_in_max = 1350;
+	   pll->pll_out_min = 20000;
+	   pll->pll_out_max = 50000;
        } else {
-           pll->min_pll_freq = 12500;
-           pll->max_pll_freq = 35000;
+	   pll->pll_in_min = 40;
+	   pll->pll_in_max = 100;
+	   pll->pll_out_min = 12500;
+	   pll->pll_out_max = 35000;
        }
 
        if (RADEONProbePLLParameters(pScrn))
-            return;
+	   return;
 
 	if (info->IsIGP)
 	    pll->reference_freq = 1432;
@@ -1198,25 +1201,30 @@ static void RADEONGetClockInfo(ScrnInfoPtr pScrn)
 	 * Empirical value changed to 24 to raise pixel clock limit and
 	 * allow higher resolution modes on capable monitors
 	 */
-        pll->max_pll_freq = min(pll->max_pll_freq,
+        pll->pll_out_max = min(pll->pll_out_max,
                                24 * info->mclk * 100 / pScrn->bitsPerPixel *
                                info->RamWidth / 16);
     }
 
     /* card limits for computing PLLs */
+    if (IS_AVIVO_VARIANT) {
+	pll->min_post_div = 2;
+	pll->max_post_div = 0x7f;
+    } else {
+	pll->min_post_div = 2;
+	pll->max_post_div = 12; //16 on crtc0
+    }
     pll->min_ref_div = 2;
     pll->max_ref_div = 0x3ff;
     pll->min_feedback_div = 4;
     pll->max_feedback_div = 0x7ff;
-    pll->pll_in_min = 40;
-    pll->pll_in_max = 100;
     pll->best_vco = 0;
 
     xf86DrvMsg (pScrn->scrnIndex, X_INFO,
 		"PLL parameters: rf=%u rd=%u min=%u max=%u; xclk=%u\n",
 		pll->reference_freq,
 		pll->reference_div,
-		(unsigned)pll->min_pll_freq, (unsigned)pll->max_pll_freq,
+		(unsigned)pll->pll_out_min, (unsigned)pll->pll_out_max,
 		pll->xclk);
 
     /* (Some?) Radeon BIOSes seem too lie about their minimum dot
@@ -1225,7 +1233,7 @@ static void RADEONGetClockInfo(ScrnInfoPtr pScrn)
      */
     if (xf86GetOptValFreq(info->Options, OPTION_MIN_DOTCLOCK,
 			  OPTUNITS_MHZ, &min_dotclock)) {
-	if (min_dotclock < 12 || min_dotclock*100 >= pll->max_pll_freq) {
+	if (min_dotclock < 12 || min_dotclock*100 >= pll->pll_out_max) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		       "Illegal minimum dotclock specified %.2f MHz "
 		       "(option ignored)\n",
@@ -1234,8 +1242,8 @@ static void RADEONGetClockInfo(ScrnInfoPtr pScrn)
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		       "Forced minimum dotclock to %.2f MHz "
 		       "(instead of detected %.2f MHz)\n",
-		       min_dotclock, ((double)pll->min_pll_freq/1000));
-	    pll->min_pll_freq = min_dotclock * 1000;
+		       min_dotclock, ((double)pll->pll_out_min/1000));
+	    pll->pll_out_min = min_dotclock * 1000;
 	}
     }
 }


More information about the xorg-commit mailing list