[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