# --- T2-COPYRIGHT-NOTE-BEGIN --- # This copyright note is auto-generated by ./scripts/Create-CopyPatch. # # T2 SDE: package/.../xorg/radeon-ibook.patch # Copyright (C) 2004 - 2005 The T2 SDE Project # # More information can be found in the files COPYING and README. # # This patch file is dual-licensed. It is available under the license the # patched project is licensed under, as long as it is an OpenSource license # as defined at http://www.opensource.org/ (e.g. BSD, X11) or under the terms # of the GNU General Public License as published by the Free Software # Foundation; either version 2 of the License, or (at your option) any later # version. # --- T2-COPYRIGHT-NOTE-END --- My, BenH's and others Radeon on non-x86 and 2nd CRT output work pulled from X.org CVS. - Rene Rebe diff -u xc/programs/Xserver/hw/xfree86/drivers/ati-orig/radeon.h xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h --- xc/programs/Xserver/hw/xfree86/drivers/ati-orig/radeon.h 2004-08-12 07:00:22.000000000 +0200 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h 2004-12-24 02:28:49.105217904 +0100 @@ -595,6 +595,12 @@ /* special handlings for DELL triple-head server */ Bool IsDellServer; + + /* enable bios hotkey output switching */ + Bool BiosHotkeys; + + Bool VGAAccess; + } RADEONInfoRec, *RADEONInfoPtr; diff -u xc/programs/Xserver/hw/xfree86/drivers/ati-orig/radeon.man xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.man --- xc/programs/Xserver/hw/xfree86/drivers/ati-orig/radeon.man 2004-09-04 01:26:19.000000000 +0200 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.man 2004-12-24 02:28:49.116216232 +0100 @@ -494,6 +494,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 \*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 +.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 .SH SEE ALSO __xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__) diff -u xc/programs/Xserver/hw/xfree86/drivers/ati-orig/radeon_accel.c xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c --- xc/programs/Xserver/hw/xfree86/drivers/ati-orig/radeon_accel.c 2004-08-12 07:00:22.000000000 +0200 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c 2004-12-24 02:28:49.118215928 +0100 @@ -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 -u xc/programs/Xserver/hw/xfree86/drivers/ati-orig/radeon_driver.c xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c --- xc/programs/Xserver/hw/xfree86/drivers/ati-orig/radeon_driver.c 2004-08-25 02:30:41.000000000 +0200 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c 2004-12-24 02:56:08.677964960 +0100 @@ -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 */ @@ -164,7 +165,11 @@ OPTION_SUBPIXEL_ORDER, #endif OPTION_SHOWCACHE, - OPTION_DYNAMIC_CLOCKS + OPTION_DYNAMIC_CLOCKS, + OPTION_BIOS_HOTKEYS, + OPTION_VGA_ACCESS, + OPTION_REVERSE_DDC, + OPTION_LVDS_PROBE_PLL } RADEONOpts; static const OptionInfoRec RADEONOptions[] = { @@ -209,6 +214,10 @@ #endif { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_DYNAMIC_CLOCKS, "DynamicClocks", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_BIOS_HOTKEYS, "BIOSHotkeys", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_VGA_ACCESS, "VGAAccess", OPTV_BOOLEAN, {0}, TRUE }, + { OPTION_REVERSE_DDC, "ReverseDDC", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_LVDS_PROBE_PLL, "LVDSProbePLL", OPTV_BOOLEAN, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; @@ -1183,38 +1192,56 @@ 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); @@ -1279,23 +1306,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) { @@ -1320,7 +1418,25 @@ 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" "If not, use PanelSize option to overwrite this setting\n", @@ -1334,17 +1450,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) && @@ -1415,6 +1538,8 @@ RADEONGetTMDSInfo(pScrn); if (!pScrn->monitor->DDC) RADEONGetHardCodedEDIDFromBIOS(pScrn); + else if (!info->IsSecondary) + RADEONUpdatePanelSize(pScrn); } } } @@ -1447,17 +1572,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; @@ -1609,6 +1741,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*/ @@ -2595,10 +2776,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) && @@ -2620,26 +2815,14 @@ 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. @@ -2760,6 +2943,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) && @@ -2849,19 +3034,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); @@ -3552,7 +3728,8 @@ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Invalid PanelSize value: %s\n", s); } - } + } else + RADEONGetPanelInfo(pScrn); } if (pScrn->monitor->DDC) { @@ -4119,14 +4296,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", @@ -4155,6 +4324,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; @@ -4213,7 +4408,6 @@ RADEONGetBIOSInfo(pScrn, pInt10); if (!RADEONQueryConnectedMonitors(pScrn)) goto fail; RADEONGetClockInfo(pScrn); - RADEONGetPanelInfo(pScrn); /* collect MergedFB options */ /* only parse mergedfb options on the primary head. @@ -4269,7 +4463,8 @@ if (pInt10) xf86FreeInt10(pInt10); - vgaHWFreeHWRec(pScrn); + if (info->VGAAccess) + vgaHWFreeHWRec(pScrn); fail2: if(info->MMIO) RADEONUnmapMMIO(pScrn); @@ -5705,7 +5902,6 @@ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; RADEONSavePtr save = &info->SavedReg; - vgaHWPtr hwp = VGAHWPTR(pScrn); RADEONTRACE(("RADEONSave\n")); if (info->FBDev) { @@ -5714,19 +5910,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); @@ -5742,7 +5942,6 @@ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; RADEONSavePtr restore = &info->SavedReg; - vgaHWPtr hwp = VGAHWPTR(pScrn); RADEONTRACE(("RADEONRestore\n")); @@ -5784,27 +5983,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); @@ -5952,7 +6160,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; @@ -6433,8 +6641,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) + @@ -6476,6 +6689,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)); @@ -6664,7 +6894,18 @@ } } - if (info->IsMobility) { + info->BiosHotkeys = FALSE; + /* + * Allow the bios to toggle outputs. see below for more. + */ + if (xf86ReturnOptValBool(info->Options, OPTION_BIOS_HOTKEYS, FALSE)) { + info->BiosHotkeys = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS HotKeys Enabled\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS HotKeys Disabled\n"); + } + + if (info->IsMobility && (!info->BiosHotkeys)) { RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); /* To work correctly with laptop hotkeys. @@ -6692,6 +6933,21 @@ } save->bios_4_scratch = 0x4; save->bios_6_scratch = orig->bios_6_scratch | 0x40000000; + + } else if (info->IsMobility && (info->DisplayType == MT_LCD)) { + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + + /* BIOS will use this setting to reset displays upon lid close/open. + * Here we let BIOS controls LCD, but the driver will control the external CRT. + */ + if (info->MergedFB || pRADEONEnt->HasSecondary) + save->bios_5_scratch = 0x01020201; + else + save->bios_5_scratch = orig->bios_5_scratch; + + save->bios_4_scratch = orig->bios_4_scratch; + save->bios_6_scratch = orig->bios_6_scratch; + } save->fp_crtc_h_total_disp = save->crtc_h_total_disp; @@ -6701,8 +6957,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; @@ -6726,6 +6982,14 @@ { 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; @@ -6760,7 +7024,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; @@ -6787,6 +7051,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; @@ -6887,7 +7156,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, @@ -6895,7 +7164,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; @@ -6904,19 +7173,13 @@ 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; @@ -7307,7 +7570,7 @@ } } - if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) + if (info->VGAAccess && xf86LoaderCheckSymbol("vgaHWFreeHWRec")) vgaHWFreeHWRec(pScrn); RADEONFreeRec(pScrn); }