[PATCH] Radeon: All my fixes in one patch

Benjamin Herrenschmidt benh at kernel.crashing.org
Sun Dec 5 02:10:29 PST 2004


And here's the "combo" version of my fixes for convenience.

diff -urN xc.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon.h xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h
--- xc.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon.h	2004-10-03 10:01:13.000000000 +1000
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h	2004-12-05 20:16:30.000000000 +1100
@@ -615,6 +615,7 @@
     Bool		AtLeastOneNonClone;
     int			MergedFBXDPI, MergedFBYDPI;
     Bool		NoVirtual;
+    Bool		VGAAccess;
 
     /* special handlings for DELL triple-head server */
     Bool		IsDellServer; 
diff -urN xc.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon.man xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.man
--- xc.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon.man	2004-11-28 02:14:15.000000000 +1100
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.man	2004-12-05 20:49:58.000000000 +1100
@@ -496,6 +496,34 @@
 with this enabled.  The default is
 .B off.
 .TP
+.BI "Option \*qVGAAccess\*q \*q" boolean \*q
+Tell the driver if it can do legacy VGA IOs to the card. This is
+necessary for properly resuming consoles when in VGA text mode, but
+shouldn't be if the console is using radeonfb or some other graphic
+mode driver. Some platforms like PowerPC have issues with those, and they aren't
+necessary unless you have a real text mode in console. The default is
+.B off 
+on PowerPC and
+.B on 
+on other architectures.
+.TP
+.BI "Option \*qLVDSProbePLL\*q \*q" boolean \*q
+When BIOS panel informations aren't available (like on PowerBooks), it
+may still be necessary to use the firmware provided PLL values for the
+panel or flickering will happen. This option will force probing of
+the current value programmed in the chip when X is launched in that
+case.  This is only useful for LVDS panels (laptop internal panels).
+The default is
+.B on.
+.TP
+.BI "Option \*qReverseDDC\*q \*q" boolean \*q
+When BIOS connector informations aren't available, use this option to
+reverse the mapping of the 2 main DDC ports. Use this if the X serve
+obviously detects the wrong display for each connector. This is
+typically needed on the Radeon 9600 cards bundled with Apple G5s. The
+default is
+.B off.
+.TP
 
 .SH SEE ALSO
 __xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
diff -urN xc.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c
--- xc.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c	2004-08-12 15:00:22.000000000 +1000
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c	2004-12-05 20:22:00.000000000 +1100
@@ -291,10 +291,8 @@
     OUTREGP(RADEON_DP_DATATYPE, 0, ~RADEON_HOST_BIG_ENDIAN_EN);
 #endif
 
-    /* Restore SURFACE_CNTL - only the first head contains valid data -ReneR */
-    if (!info->IsSecondary) {
-	OUTREG(RADEON_SURFACE_CNTL, info->ModeReg.surface_cntl);
-    }
+    /* Restore SURFACE_CNTL */
+    OUTREG(RADEON_SURFACE_CNTL, info->ModeReg.surface_cntl);
 
     RADEONWaitForFifo(pScrn, 1);
     OUTREG(RADEON_DEFAULT_SC_BOTTOM_RIGHT, (RADEON_DEFAULT_SC_RIGHT_MAX
diff -urN xc.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c
--- xc.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c	2004-11-24 08:27:43.000000000 +1100
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c	2004-12-05 20:50:01.000000000 +1100
@@ -118,6 +118,7 @@
 static void RADEONGetMergedFBOptions(ScrnInfoPtr pScrn);
 static int RADEONValidateMergeModes(ScrnInfoPtr pScrn);
 static void RADEONSetDynamicClock(ScrnInfoPtr pScrn, int mode);
+static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn);
 
 /* psuedo xinerama support */
 
@@ -171,7 +172,10 @@
     OPTION_SUBPIXEL_ORDER,
 #endif
     OPTION_SHOWCACHE,
-    OPTION_DYNAMIC_CLOCKS
+    OPTION_DYNAMIC_CLOCKS,
+    OPTION_VGA_ACCESS,
+    OPTION_LVDS_PROBE_PLL,
+    OPTION_REVERSE_DDC,
 } RADEONOpts;
 
 static const OptionInfoRec RADEONOptions[] = {
@@ -223,6 +227,9 @@
 #endif
     { OPTION_SHOWCACHE,      "ShowCache",        OPTV_BOOLEAN, {0}, FALSE },
     { OPTION_DYNAMIC_CLOCKS, "DynamicClocks",    OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_VGA_ACCESS,     "VGAAccess",        OPTV_BOOLEAN, {0}, TRUE  },
+    { OPTION_LVDS_PROBE_PLL, "LVDSProbePLL",     OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_REVERSE_DDC,    "ReverseDDC",       OPTV_BOOLEAN, {0}, FALSE },
     { -1,                    NULL,               OPTV_NONE,    {0}, FALSE }
 };
 
@@ -1197,41 +1204,59 @@
     return(bConnected ? MT_CRT : MT_NONE);
 }
 
-#if defined(__powerpc__)
 static Bool RADEONProbePLLParameters(ScrnInfoPtr pScrn)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
     RADEONPLLPtr  pll  = &info->pll;
     unsigned char *RADEONMMIO = info->MMIO;
     unsigned char ppll_div_sel;
-    unsigned Nx, M;
+    unsigned mpll_fb_div, spll_fb_div, M;
     unsigned xclk, tmp, ref_div;
     int hTotal, vTotal, num, denom, m, n;
-    float hz, vclk, xtal;
+    float hz, prev_xtal, vclk, xtal, mpll, spll;
     long start_secs, start_usecs, stop_secs, stop_usecs, total_usecs;
-    int i;
-
-    for(i=0; i<1000000; i++)
-	if (((INREG(RADEON_CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) == 0)
+    long to1_secs, to1_usecs, to2_secs, to2_usecs;
+    unsigned int f1, f2, f3;
+    int i, tries = 0;
+
+    prev_xtal = 0;
+ again:
+    xtal = 0;
+    if (++tries > 10)
+	    goto failed;
+
+    xf86getsecs(&to1_secs, &to1_usecs);
+    f1 = INREG(RADEON_CRTC_CRNT_FRAME);
+    for (;;) {
+	f2 = INREG(RADEON_CRTC_CRNT_FRAME);
+	if (f1 != f2)
 	    break;
-
+	xf86getsecs(&to2_secs, &to2_usecs);
+	if ((to2_secs - to1_secs) > 1) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Clock not counting...\n");
+	    goto failed;
+	}
+    }
     xf86getsecs(&start_secs, &start_usecs);
-
-    for(i=0; i<1000000; i++)
-	if (((INREG(RADEON_CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) != 0)
-	    break;
-
-    for(i=0; i<1000000; i++)
-	if (((INREG(RADEON_CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) == 0)
+    for(;;) {
+	f3 = INREG(RADEON_CRTC_CRNT_FRAME);
+	if (f3 != f2)
 	    break;
-
+	xf86getsecs(&to2_secs, &to2_usecs);
+	if ((to2_secs - start_secs) > 1)
+	    goto failed;
+    }
     xf86getsecs(&stop_secs, &stop_usecs);
 
+    if ((stop_secs - start_secs) != 0)
+	    goto again;
     total_usecs = abs(stop_usecs - start_usecs);
-    hz = 1000000/total_usecs;
+    if (total_usecs == 0)
+	    goto again;
+    hz = 1000000.0/(float)total_usecs;
 
-    hTotal = ((INREG(RADEON_CRTC_H_TOTAL_DISP) & 0x1ff) + 1) * 8;
-    vTotal = ((INREG(RADEON_CRTC_V_TOTAL_DISP) & 0x3ff) + 1);
+    hTotal = ((INREG(RADEON_CRTC_H_TOTAL_DISP) & 0x3ff) + 1) * 8;
+    vTotal = ((INREG(RADEON_CRTC_V_TOTAL_DISP) & 0xfff) + 1);
     vclk = (float)(hTotal * (float)(vTotal * hz));
 
     switch((INPLL(pScrn, RADEON_PPLL_REF_DIV) & 0x30000) >> 16) {
@@ -1293,23 +1318,94 @@
     else if ((xtal > 29400000) && (xtal < 29600000))
         xtal = 2950;
     else
-	return FALSE;
+	goto again;
+ failed:
+    if (xtal == 0) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to probe xtal value ! "
+		   "Using default 27Mhz\n");
+	xtal = 2700;
+    } else {
+	if (prev_xtal == 0) {
+	    prev_xtal = xtal;
+	    tries = 0;
+	    goto again;
+	} else if (prev_xtal != xtal) {
+	    prev_xtal = 0;
+	    goto again;
+	}
+    }
 
     tmp = INPLL(pScrn, RADEON_X_MPLL_REF_FB_DIV);
     ref_div = INPLL(pScrn, RADEON_PPLL_REF_DIV) & 0x3ff;
 
-    Nx = (tmp & 0xff00) >> 8;
+    /* Some sanity check based on the BIOS code .... */
+    if (ref_div < 2) {
+	CARD32 tmp;
+	tmp = INPLL(pScrn, RADEON_PPLL_REF_DIV);
+	if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_RS300))
+	    ref_div = (tmp & R300_PPLL_REF_DIV_ACC_MASK) >>
+		    R300_PPLL_REF_DIV_ACC_SHIFT;
+	else
+	    ref_div = tmp & RADEON_PPLL_REF_DIV_MASK;
+	if (ref_div < 2)
+	    ref_div = 12;
+    }
+
+    /* Calculate "base" xclk straight from MPLL, though that isn't
+     * really useful (hopefully)
+     */
+    mpll_fb_div = (tmp & 0xff00) >> 8;
+    spll_fb_div = (tmp & 0xff0000) >> 16;
     M = (tmp & 0xff);
-    xclk = RADEONDiv((2 * Nx * xtal), (2 * M));
+    xclk = RADEONDiv((2 * mpll_fb_div * xtal), (2 * M));
+
+    /*
+     * Calculate MCLK based on MCLK-A and SCLK
+     *
+     * NOTE: It is not clear at this point wether we should put in sclk and
+     * mclk the raw SPLL and MPLL output values, or the divided values according
+     * to the source selection iN MCLK_CNTL and SCLK_CNTL. I'm putting the divided
+     * values for now, waiting for a definitive answer from ATI
+     */
+    mpll = ((float)mpll_fb_div * (float)(xtal / 100.0)) / (float)M;
+    spll = ((float)spll_fb_div * (float)(xtal / 100.0)) / (float)M;
+
+    tmp = INPLL(pScrn, RADEON_MCLK_CNTL) & 0x7;
+    switch(tmp) {
+    case 1: info->mclk = mpll; break;
+    case 2: info->mclk = mpll / 2.0; break;
+    case 3: info->mclk = mpll / 4.0; break;
+    case 4: info->mclk = mpll / 8.0; break;
+    case 7: info->mclk = spll; break;
+    default:
+	    info->mclk = 200.00;
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unsupported MCLKA source"
+		       " setting %d, can't probe MCLK value !\n", tmp);
+    }
+
+    tmp = INPLL(pScrn, RADEON_SCLK_CNTL) & 0x7;
+    switch(tmp) {
+    case 1: info->sclk = spll; break;
+    case 2: info->sclk = spll / 2.0; break;
+    case 3: info->sclk = spll / 4.0; break;
+    case 4: info->sclk = spll / 8.0; break;
+    case 7: info->sclk = mpll;
+    default:
+	    info->sclk = 200.00;
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unsupported SCLK source"
+		       " setting %d, can't probe SCLK value !\n", tmp);
+    }
 
     /* we're done, hopefully these are sane values */
     pll->reference_div = ref_div;
     pll->xclk = xclk;
     pll->reference_freq = xtal;
 
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Probed PLL values: xtal: %f Mhz, "
+	       "sclk: %f Mhz, mclk: %f Mhz\n", xtal/100.0, info->sclk, info->mclk);
+
     return TRUE;
 }
-#endif
 
 static void RADEONGetPanelInfoFromReg (ScrnInfoPtr pScrn)
 {
@@ -1334,6 +1430,24 @@
 	info->PanelXRes = 640;
 	info->PanelYRes = 480;
     }
+
+    if (xf86ReturnOptValBool(info->Options, OPTION_LVDS_PROBE_PLL, TRUE)) {
+	    CARD32 ppll_div_sel, ppll_val;
+
+	    OUTREG(RADEON_CLOCK_CNTL_INDEX, 1);
+	    ppll_div_sel = INREG8(RADEON_CLOCK_CNTL_DATA + 1) & 0x3;
+            ppll_val = INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel);
+	    if ((ppll_val & 0x000707ff) == 0x1bb)
+		goto noprobe;
+            info->FeedbackDivider = ppll_val & 0x7ff;
+            info->PostDivider = (ppll_val >> 16) & 0x7;
+	    info->RefDivider = info->pll.reference_div;
+            info->UseBiosDividers = TRUE;
+
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "Existing panel PLL dividers will be used.\n");
+    }
+ noprobe:
     
     xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 
 	       "Panel size %dx%d is derived, this may not be correct.\n"
@@ -1348,17 +1462,24 @@
     if (!RADEONGetLVDSInfoFromBIOS(pScrn))
         RADEONGetPanelInfoFromReg(pScrn);
 
+    /* The panel size we collected from BIOS may not be the
+     * maximum size supported by the panel.  If not, we update
+     * it now.  These will be used if no matching mode can be
+     * found from EDID data.
+     */
+    RADEONUpdatePanelSize(pScrn);
+
+    /* No timing information for the native mode,
+     * use whatever specified in the Modeline.
+     * If no Modeline specified, we'll just pick
+     * the VESA mode at 60Hz refresh rate which
+     * is likely to be the best for a flat panel.
+     */
     if (info->DotClock == 0) {
         RADEONEntPtr pRADEONEnt   = RADEONEntPriv(pScrn);
         DisplayModePtr  tmp_mode = NULL;
         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
                    "No valid timing info from BIOS.\n");
-        /* No timing information for the native mode,
-           use whatever specified in the Modeline.
-           If no Modeline specified, we'll just pick
-           the VESA mode at 60Hz refresh rate which
-           is likely to be the best for a flat panel.
-	*/
         tmp_mode = pScrn->monitor->Modes;
         while(tmp_mode) {
             if ((tmp_mode->HDisplay == info->PanelXRes) &&
@@ -1429,6 +1550,8 @@
             RADEONGetTMDSInfo(pScrn);
             if (!pScrn->monitor->DDC)
                 RADEONGetHardCodedEDIDFromBIOS(pScrn);
+	    else if (!info->IsSecondary)
+		RADEONUpdatePanelSize(pScrn);
         }
     }
 }
@@ -1461,17 +1584,24 @@
 	xf86DrvMsg (pScrn->scrnIndex, X_WARNING,
 		    "Video BIOS not detected, using default clock settings!\n");
 
-#if defined(__powerpc__)
-	if (RADEONProbePLLParameters(pScrn)) return;
-#endif
+	/* Default min/max PLL values */
+	if (info->ChipFamily == CHIP_FAMILY_R420) {
+	    pll->min_pll_freq = 20000;
+	    pll->max_pll_freq = 50000;
+	} else {
+	    pll->min_pll_freq = 12500;
+	    pll->max_pll_freq = 35000;
+	}
+
+	if (RADEONProbePLLParameters(pScrn))
+            return;
+
 	if (info->IsIGP)
 	    pll->reference_freq = 1432;
 	else
 	    pll->reference_freq = 2700;
 
 	pll->reference_div = 12;
-	pll->min_pll_freq = 12500;
-	pll->max_pll_freq = 35000;
 	pll->xclk = 10300;
 
         info->sclk = 200.00;
@@ -1623,6 +1753,14 @@
 	pRADEONEnt->PortInfo[1].DACType = DAC_PRIMARY;
 	pRADEONEnt->PortInfo[1].TMDSType = TMDS_EXT;
 	pRADEONEnt->PortInfo[1].ConnectorType = CONNECTOR_CRT;
+
+	/* Some cards have the DDC lines swapped and we have no way to
+	 * detect it yet (Mac cards)
+	 */
+	if (xf86ReturnOptValBool(info->Options, OPTION_REVERSE_DDC, FALSE)) {
+	    pRADEONEnt->PortInfo[0].DDCType = DDC_VGA;
+	    pRADEONEnt->PortInfo[1].DDCType = DDC_DVI;
+        }
     }
 
     /* always make TMDS_INT port first*/
@@ -2596,14 +2734,35 @@
     xf86MonPtr      ddc  = pScrn->monitor->DDC;
     DisplayModePtr  p;
 
+    if (info->UseBiosDividers && info->DotClock != 0)
+	return;
+
     /* Go thru detailed timing table first */
     for (j = 0; j < 4; j++) {
 	if (ddc->det_mon[j].type == 0) {
 	    struct detailed_timings *d_timings =
 		&ddc->det_mon[j].section.d_timings;
+	    int match = 0;
+
+	    /* If we didn't get a panel clock or guessed one, try to match the
+	     * mode with the panel size. We do that because we _need_ a panel
+	     * clock, or ValidateFPModes will fail, even when UseBiosDividers
+	     * is set.
+	     */
+	    if (info->DotClock == 0 &&
+		info->PanelXRes == d_timings->h_active &&
+		info->PanelYRes == d_timings->v_active)
+	        match = 1;
+	    
+	    /* If we don't have a BIOS provided panel data with fixed dividers,
+	     * check for a larger panel size
+	     */
 	    if (info->PanelXRes < d_timings->h_active &&
-		info->PanelYRes < d_timings->v_active) {
+		info->PanelYRes < d_timings->v_active &&
+		!info->UseBiosDividers)
+	        match = 1;
 
+	    if (match) {
 		info->PanelXRes  = d_timings->h_active;
 		info->PanelYRes  = d_timings->v_active;
 		info->DotClock   = d_timings->clock / 1000;
@@ -2613,10 +2772,24 @@
 		info->VOverPlus  = d_timings->v_sync_off;
 		info->VSyncWidth = d_timings->v_sync_width;
 		info->VBlank     = d_timings->v_blanking;
+		info->Flags      = (d_timings->interlaced ? V_INTERLACE : 0);
+		if (d_timings->sync == 3) {
+		    switch (d_timings->misc) {
+		    case 0: info->Flags |= V_NHSYNC | V_NVSYNC; break;
+		    case 1: info->Flags |= V_PHSYNC | V_NVSYNC; break;
+		    case 2: info->Flags |= V_NHSYNC | V_PVSYNC; break;
+		    case 3: info->Flags |= V_PHSYNC | V_PVSYNC; break;
+		    }
+	        }
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel infos found from DDC detailed: %dx%d\n",
+			   info->PanelXRes, info->PanelYRes);
 	    }
 	}
     }
 
+    if (info->UseBiosDividers && info->DotClock != 0)
+	return;
+
     /* Search thru standard VESA modes from EDID */
     for (j = 0; j < 8; j++) {
 	if ((info->PanelXRes < ddc->timings2[j].hsize) &&
@@ -2638,28 +2811,16 @@
 			info->VOverPlus  = p->VSyncStart - p->VDisplay;
 			info->VSyncWidth = p->VSyncEnd - p->VSyncStart;
 			info->DotClock   = p->Clock;
-			info->Flags      =
-			    (ddc->det_mon[j].section.d_timings.interlaced
-			     ? V_INTERLACE
-			     : 0);
-			if (ddc->det_mon[j].section.d_timings.sync == 3) {
-			    switch (ddc->det_mon[j].section.d_timings.misc) {
-			    case 0: info->Flags |= V_NHSYNC | V_NVSYNC; break;
-			    case 1: info->Flags |= V_PHSYNC | V_NVSYNC; break;
-			    case 2: info->Flags |= V_NHSYNC | V_PVSYNC; break;
-			    case 3: info->Flags |= V_PHSYNC | V_PVSYNC; break;
-			    }
-			}
+			info->Flags	 = p->Flags;
+			xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel infos found from DDC VESA/EDID: %dx%d\n",
+				   info->PanelXRes, info->PanelYRes);
 		    }
 		}
 	    }
 	}
     }
-
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel size found from DDC: %dx%d\n",
-	       info->PanelXRes, info->PanelYRes);
-}
-
+ }
+ 
 /* This function will sort all modes according to their resolution.
  * Highest resolution first.
  */
@@ -2778,6 +2939,8 @@
 
     /* Search thru standard VESA modes from EDID */
     for (j = 0; j < 8; j++) {
+	if (ddc->timings2[j].hsize == 0 || ddc->timings2[j].vsize == 0)
+		continue;
 	for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) {
 	    /* Ignore all double scan modes */
 	    if ((ddc->timings2[j].hsize == p->HDisplay) &&
@@ -2867,19 +3030,10 @@
     pScrn->virtualX = pScrn1->display->virtualX;
     pScrn->virtualY = pScrn1->display->virtualY;
 
-    if (pScrn->monitor->DDC && !info->UseBiosDividers) {
+    if (pScrn->monitor->DDC) {
 	int  maxVirtX = pScrn->virtualX;
 	int  maxVirtY = pScrn->virtualY;
 
-	if ((DisplayType != MT_CRT) && (!info->IsSecondary) && (!crtc2)) {
-	    /* The panel size we collected from BIOS may not be the
-	     * maximum size supported by the panel.  If not, we update
-	     * it now.  These will be used if no matching mode can be
-	     * found from EDID data.
-	     */
-	    RADEONUpdatePanelSize(pScrn);
-	}
-
 	/* Collect all of the DDC modes */
 	first = last = ddcModes = RADEONDDCModes(pScrn);
 
@@ -3175,8 +3329,9 @@
 		new->next       = NULL;
 		new->prev       = last;
 
-		last->next = new;
+		if (last) last->next = new;
 		last = new;
+		if (!first) first = new;
 	    }
 	}
     }
@@ -3570,7 +3725,8 @@
 		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
 			   "Invalid PanelSize value: %s\n", s);
 	    }
-	}
+	} else
+		RADEONGetPanelInfo(pScrn);
     }
 
     if (pScrn->monitor->DDC) {
@@ -4201,15 +4357,6 @@
 	return TRUE;
     }
 
-    if (!xf86LoadSubModule(pScrn, "vgahw")) return FALSE;
-    xf86LoaderReqSymLists(vgahwSymbols, NULL);
-    if (!vgaHWGetHWRec(pScrn)) {
-	RADEONFreeRec(pScrn);
-	goto fail2;
-    }
-
-    vgaHWGetIOBase(VGAHWPTR(pScrn));
-
     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	       "PCI bus %d card %d func %d\n",
 	       info->PciInfo->bus,
@@ -4237,6 +4384,32 @@
     memcpy(info->Options, RADEONOptions, sizeof(RADEONOptions));
     xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options);
 
+    /* By default, don't do VGA IOs on ppc */
+#ifdef __powerpc__
+    info->VGAAccess = FALSE;
+#else
+    info->VGAAccess = TRUE;
+#endif
+
+    xf86GetOptValBool(info->Options, OPTION_VGA_ACCESS, &info->VGAAccess);
+    if (info->VGAAccess) {
+	if (!xf86LoadSubModule(pScrn, "vgahw"))
+	    info->VGAAccess = FALSE;
+        else {
+	    xf86LoaderReqSymLists(vgahwSymbols, NULL);
+            if (!vgaHWGetHWRec(pScrn))
+		info->VGAAccess = FALSE;
+	}
+	if (!info->VGAAccess)
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Loading VGA module failed,"
+		       " trying to run without it\n");
+    } else
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VGAAccess option set to FALSE,"
+		       " VGA module load skipped\n");
+    if (info->VGAAccess)
+	 vgaHWGetIOBase(VGAHWPTR(pScrn));	    
+
+
     if (!RADEONPreInitWeight(pScrn))
 	goto fail;
 
@@ -4352,7 +4525,6 @@
     RADEONGetBIOSInfo(pScrn, pInt10);
     if (!RADEONQueryConnectedMonitors(pScrn))    goto fail;
     RADEONGetClockInfo(pScrn);
-    RADEONGetPanelInfo(pScrn);
 
     /* collect MergedFB options */
     /* only parse mergedfb options on the primary head. 
@@ -4410,7 +4582,8 @@
     if (pInt10)
 	xf86FreeInt10(pInt10);
 
-    vgaHWFreeHWRec(pScrn);
+    if (info->VGAAccess)
+	    vgaHWFreeHWRec(pScrn);
 
  fail2:
     if(info->MMIO) RADEONUnmapMMIO(pScrn);
@@ -4612,10 +4785,12 @@
 
     RADEONSave(pScrn);
 
-    if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) {
-	RADEONSetDynamicClock(pScrn, 1);
-    } else {
-	RADEONSetDynamicClock(pScrn, 0);
+    if ((!info->IsSecondary) && info->IsMobility) {
+        if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) {
+	    RADEONSetDynamicClock(pScrn, 1);
+        } else {
+	    RADEONSetDynamicClock(pScrn, 0);
+        }
     }
 
     if (info->FBDev) {
@@ -5846,7 +6021,6 @@
     RADEONInfoPtr  info       = RADEONPTR(pScrn);
     unsigned char *RADEONMMIO = info->MMIO;
     RADEONSavePtr  save       = &info->SavedReg;
-    vgaHWPtr       hwp        = VGAHWPTR(pScrn);
 
     RADEONTRACE(("RADEONSave\n"));
     if (info->FBDev) {
@@ -5855,19 +6029,23 @@
     }
 
     if (!info->IsSecondary) {
-	vgaHWUnlock(hwp);
+        if (info->VGAAccess) {
+    	    vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+            vgaHWUnlock(hwp);
 #if defined(__powerpc__)
-	/* temporary hack to prevent crashing on PowerMacs when trying to
-	 * read VGA fonts and colormap, will find a better solution
-	 * in the future
-	 */
-	vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE); /* Save mode only */
+	    /* temporary hack to prevent crashing on PowerMacs when trying to
+	     * read VGA fonts and colormap, will find a better solution
+	     * in the future. TODO: Check if there's actually some VGA stuff
+	     * setup in the card at all !!
+	     */
+	    vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE); /* Save mode only */
 #else
-	vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS); /* Save mode
-						       * & fonts & cmap
-						       */
+	    /* Save mode * & fonts & cmap */
+	    vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS); 
 #endif
-	vgaHWLock(hwp);
+	    vgaHWLock(hwp);
+	}
 	save->dp_datatype      = INREG(RADEON_DP_DATATYPE);
 	save->rbbm_soft_reset  = INREG(RADEON_RBBM_SOFT_RESET);
 	save->clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX);
@@ -5883,7 +6061,6 @@
     RADEONInfoPtr  info       = RADEONPTR(pScrn);
     unsigned char *RADEONMMIO = info->MMIO;
     RADEONSavePtr  restore    = &info->SavedReg;
-    vgaHWPtr       hwp        = VGAHWPTR(pScrn);
 
     RADEONTRACE(("RADEONRestore\n"));
 
@@ -5925,27 +6102,36 @@
     usleep(100000);
 #endif
 
-    if (!info->IsSecondary) {
-	vgaHWUnlock(hwp);
+    if (info->VGAAccess) {
+    	vgaHWPtr hwp = VGAHWPTR(pScrn);
+        if (!info->IsSecondary) {
+            vgaHWUnlock(hwp);
 #if defined(__powerpc__)
-	/* Temporary hack to prevent crashing on PowerMacs when trying to
-	 * write VGA fonts, will find a better solution in the future
-	 */
-	vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE );
+	    /* Temporary hack to prevent crashing on PowerMacs when trying to
+	     * write VGA fonts, will find a better solution in the future
+	     */
+	    vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE );
 #else
-	vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS );
+	    vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS );
 #endif
-	vgaHWLock(hwp);
-    } else {
-        RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
-	ScrnInfoPtr   pScrn0;
-	vgaHWPtr      hwp0;
-
-	pScrn0 = pRADEONEnt->pPrimaryScrn;
-	hwp0   = VGAHWPTR(pScrn0);
-	vgaHWUnlock(hwp0);
-	vgaHWRestore(pScrn0, &hwp0->SavedReg, VGA_SR_MODE | VGA_SR_FONTS );
-	vgaHWLock(hwp0);
+	    vgaHWLock(hwp);
+        } else {
+            RADEONEntPtr  pRADEONEnt = RADEONEntPriv(pScrn);
+	    ScrnInfoPtr   pScrn0 = pRADEONEnt->pPrimaryScrn;
+            RADEONInfoPtr info0 = RADEONPTR(pScrn0);
+	    vgaHWPtr      hwp0;
+
+	    if (info0->VGAAccess) {
+ 	        hwp0 = VGAHWPTR(pScrn0);
+	        vgaHWUnlock(hwp0);
+#if defined(__powerpc__)
+	        vgaHWRestore(pScrn0, &hwp0->SavedReg, VGA_SR_MODE);
+#else
+	        vgaHWRestore(pScrn0, &hwp0->SavedReg, VGA_SR_MODE | VGA_SR_FONTS );
+#endif
+	        vgaHWLock(hwp0);
+	    }
+	}
     }
     RADEONUnblank(pScrn);
 
@@ -6093,7 +6279,7 @@
 	*/
 	temp = INREG(RADEON_MEM_CNTL);
 	data = (R300_MEM_NUM_CHANNELS_MASK & temp);
-	if (data == 2) {
+	if (data == 1) {
 	    if (R300_MEM_USE_CD_CH_ONLY & temp) {
 		temp  = INREG(R300_MC_IND_INDEX);
 		temp &= ~R300_MC_IND_ADDR_MASK;
@@ -6574,8 +6760,13 @@
 				      ? RADEON_CRTC2_V_SYNC_POL
 				      : 0));
 
+    /* We must make sure Tiling is disabled. It seem all other fancy
+     * options in there can be safely disabled too
+     */
     save->crtc2_offset      = 0;
-    save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL);
+    save->crtc2_offset_cntl = 0;
+    
+
     /* this should be right */
     if (info->MergedFB) {
     save->crtc2_pitch  = (((info->CRT2pScrn->displayWidth * pScrn->bitsPerPixel) +
@@ -6618,6 +6809,23 @@
 
     }
 
+    /* We must set SURFACE_CNTL properly on the second screen too */
+    save->surface_cntl = 0;
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+    /* Alhought we current onlu use aperture 0, also setting aperture 1 should not harm -ReneR */
+    switch (pScrn->bitsPerPixel) {
+    case 16:
+	save->surface_cntl |= RADEON_NONSURF_AP0_SWP_16BPP;
+	save->surface_cntl |= RADEON_NONSURF_AP1_SWP_16BPP;
+	break;
+
+    case 32:
+	save->surface_cntl |= RADEON_NONSURF_AP0_SWP_32BPP;
+	save->surface_cntl |= RADEON_NONSURF_AP1_SWP_32BPP;
+	break;
+    }
+#endif
+
     RADEONTRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n",
 		 save->crtc2_pitch, pScrn->virtualX,
 		 info->CurrentLayout.displayWidth));
@@ -6843,8 +7051,8 @@
 }
 
 /* Define PLL registers for requested video mode */
-static void RADEONInitPLLRegisters(RADEONSavePtr save, RADEONPLLPtr pll,
-				   double dot_clock)
+static void RADEONInitPLLRegisters(RADEONInfoPtr info, RADEONSavePtr save,
+				   RADEONPLLPtr pll, double dot_clock)
 {
     unsigned long  freq = dot_clock * 100;
 
@@ -6868,6 +7076,13 @@
 	{  0, 0 }
     };
 
+    if (info->UseBiosDividers) {
+	save->ppll_ref_div = info->RefDivider;
+	save->ppll_div_3   = info->FeedbackDivider | (info->PostDivider << 16);
+	save->htotal_cntl  = 0;
+	return;    
+    }
+
     if (freq > pll->max_pll_freq)      freq = pll->max_pll_freq;
     if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12;
 
@@ -6902,7 +7117,7 @@
 
 /* Define PLL2 registers for requested video mode */
 static void RADEONInitPLL2Registers(RADEONSavePtr save, RADEONPLLPtr pll,
-				    double dot_clock)
+				    double dot_clock, int no_odd_postdiv)
 {
     unsigned long  freq = dot_clock * 100;
 
@@ -6929,6 +7144,11 @@
     if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12;
 
     for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
+	/* Odd post divider value don't work properly on the second digital
+         * output
+         */
+	if (no_odd_postdiv && (post_div->divider & 1))
+	    continue;
 	save->pll_output_freq_2 = post_div->divider * freq;
 	if (save->pll_output_freq_2 >= pll->min_pll_freq
 	    && save->pll_output_freq_2 <= pll->max_pll_freq) break;
@@ -7029,7 +7249,7 @@
     if (info->IsSecondary) {
 	if (!RADEONInitCrtc2Registers(pScrn, save, mode, info))
 	    return FALSE;
-	RADEONInitPLL2Registers(save, &info->pll, dot_clock);
+	RADEONInitPLL2Registers(save, &info->pll, dot_clock, info->DisplayType != MT_CRT);
     } else if (info->MergedFB) {
         RADEONInitCommonRegisters(save, info);
         if (!RADEONInitCrtcRegisters(pScrn, save, 
@@ -7037,7 +7257,7 @@
             return FALSE;
         dot_clock = (((RADEONMergedDisplayModePtr)mode->Private)->CRT1)->Clock / 1000.0;
         if (dot_clock) {
-            RADEONInitPLLRegisters(save, &info->pll, dot_clock);
+	    RADEONInitPLLRegisters(info, save, &info->pll, dot_clock);
         } else {
             save->ppll_ref_div = info->SavedReg.ppll_ref_div;
             save->ppll_div_3   = info->SavedReg.ppll_div_3;
@@ -7046,19 +7266,14 @@
         RADEONInitCrtc2Registers(pScrn, save, 
 			((RADEONMergedDisplayModePtr)mode->Private)->CRT2, info);
         dot_clock = (((RADEONMergedDisplayModePtr)mode->Private)->CRT2)->Clock / 1000.0;
-        RADEONInitPLL2Registers(save, &info->pll, dot_clock);
+        RADEONInitPLL2Registers(save, &info->pll, dot_clock, 
+				info->MergeType != MT_CRT);
     } else {
 	if (!RADEONInitCrtcRegisters(pScrn, save, mode, info))
 	    return FALSE;
 	dot_clock = mode->Clock/1000.0;
 	if (dot_clock) {
-            if (info->UseBiosDividers) {
-                save->ppll_ref_div = info->RefDivider;
-                save->ppll_div_3   = info->FeedbackDivider | (info->PostDivider << 16);
-                save->htotal_cntl  = 0;
-            }
-            else
-		RADEONInitPLLRegisters(save, &info->pll, dot_clock);
+	    RADEONInitPLLRegisters(info, save, &info->pll, dot_clock);
 	} else {
 	    save->ppll_ref_div = info->SavedReg.ppll_ref_div;
 	    save->ppll_div_3   = info->SavedReg.ppll_div_3;
@@ -7450,7 +7665,7 @@
        }
     }
 
-    if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
+    if (info->VGAAccess && xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
 	vgaHWFreeHWRec(pScrn);
     RADEONFreeRec(pScrn);
 }
diff -urN xc.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h
--- xc.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h	2004-10-25 04:17:36.000000000 +1000
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h	2004-12-05 20:50:01.000000000 +1100
@@ -821,7 +821,7 @@
 #       define RADEON_MC_MCLK_MAX_DYN_STOP_LAT (1<<12)
 #       define RADEON_IO_MCLK_MAX_DYN_STOP_LAT (1<<13)
 #       define RADEON_MC_MCLK_DYN_ENABLE    (1 << 14)
-#       define RADEON_IO_MCLK_DYN_ENABLE    (1 << 14)
+#       define RADEON_IO_MCLK_DYN_ENABLE    (1 << 15)
 #define RADEON_MDGPIO_A_REG                 0x01ac
 #define RADEON_MDGPIO_EN_REG                0x01b0
 #define RADEON_MDGPIO_MASK                  0x0198





More information about the xorg mailing list