diff options
author | Alan Coopersmith <Alan.Coopersmith@sun.com> | 2004-11-14 18:13:27 +0000 |
---|---|---|
committer | Alan Coopersmith <Alan.Coopersmith@sun.com> | 2004-11-14 18:13:27 +0000 |
commit | 2b3cb71eb2cdd71bda3e3e0072fc3df9f111e0a4 (patch) | |
tree | aa18cc2d85832737cedd3a1f08f9e996cb9cfd33 /src/nv_driver.c | |
parent | bbafc6d2fcb21671de3cfb4ff973409405162e7a (diff) |
(Bugzilla #1777) Import Mark Vojkovich's changes to NV driver since last
sync with XFree86, including: Support for new NVIDIA chips. Egbert has
a laptop that needs some DPMS ordering reversed. New chip support and
workaround for Toshiba M30 laptop issue. PCI-Xpress chip support. DPMS
support for DVI. Cursor changes for NV11 so that alpha blended cursors
will work in conjunction with dithering (laptop panels). It previously
did not. HW support for alpha blended stretch blits on NV5 and higher,
though nothing is using them at this point. Add support for VBlank
syncing the Xv Blit adaptor on hardware that supports it (NV11 and
higher). Make console restoration a little more robust. We were making
an assumption that failed on a newer laptop. Workaround for some NV31
DVI artifacts.
Also add nVidia license statement to nv man page to comply with requirement
that it appear in "user documentation"
Diffstat (limited to 'src/nv_driver.c')
-rw-r--r-- | src/nv_driver.c | 221 |
1 files changed, 190 insertions, 31 deletions
diff --git a/src/nv_driver.c b/src/nv_driver.c index b55ece9..77c72a7 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -1,4 +1,4 @@ -/* $XdotOrg: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_driver.c,v 1.4 2004/07/31 01:21:19 ajax Exp $ */ +/* $XdotOrg: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_driver.c,v 1.8 2004/11/10 02:53:44 alanc Exp $ */ /* $XConsortium: nv_driver.c /main/3 1996/10/28 05:13:37 kaleb $ */ /* * Copyright 1996-1997 David J. McKay @@ -25,7 +25,7 @@ /* Hacked together from mga driver and 3.3.4 NVIDIA driver by Jarno Paananen <jpaana@s2.org> */ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_driver.c,v 1.122 2004/01/10 22:31:53 mvojkovi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_driver.c,v 1.128 2004/10/09 22:53:25 mvojkovi Exp $ */ #include "nv_include.h" @@ -174,6 +174,8 @@ static SymTabRec NVKnownChipsets[] = { 0x10DE0323, "GeForce FX 5200SE" }, { 0x10DE0324, "GeForce FX Go5200" }, { 0x10DE0325, "GeForce FX Go5250" }, + { 0x10DE0326, "GeForce FX 5500" }, + { 0x10DE0327, "GeForce FX 5100" }, { 0x10DE0328, "GeForce FX Go5200 32M/64M" }, #if defined(__powerpc__) { 0x10DE0329, "GeForce FX 5200 (Mac)" }, @@ -181,15 +183,16 @@ static SymTabRec NVKnownChipsets[] = { 0x10DE0329, "0x0329" }, #endif { 0x10DE032A, "Quadro NVS 280 PCI" }, - { 0x10DE032B, "Quadro FX 500" }, - { 0x10DE032C, "GeForce FX Go5300" }, + { 0x10DE032B, "Quadro FX 500/600 PCI" }, + { 0x10DE032C, "GeForce FX Go53xx Series" }, { 0x10DE032D, "GeForce FX Go5100" }, { 0x10DE032F, "0x032F" }, { 0x10DE0330, "GeForce FX 5900 Ultra" }, { 0x10DE0331, "GeForce FX 5900" }, { 0x10DE0332, "GeForce FX 5900XT" }, { 0x10DE0333, "GeForce FX 5950 Ultra" }, - { 0x10DE0334, "0x0334" }, + { 0x10DE033F, "Quadro FX 700" }, + { 0x10DE0334, "GeForce FX 5900ZT" }, { 0x10DE0338, "Quadro FX 3000" }, { 0x10DE0341, "GeForce FX 5700 Ultra" }, { 0x10DE0342, "GeForce FX 5700" }, @@ -203,6 +206,41 @@ static SymTabRec NVKnownChipsets[] = { 0x10DE034C, "Quadro FX Go1000" }, { 0x10DE034E, "Quadro FX 1100" }, { 0x10DE034F, "0x034F" }, + { 0x10DE0040, "GeForce 6800 Ultra" }, + { 0x10DE0041, "GeForce 6800" }, + { 0x10DE0042, "GeForce 6800 LE" }, + { 0x10DE0043, "0x0043" }, + { 0x10DE0045, "GeForce 6800 GT" }, + { 0x10DE0049, "0x0049" }, + { 0x10DE004E, "Quadro FX 4000" }, + { 0x10DE00C0, "0x00C0" }, + { 0x10DE00C1, "0x00C1" }, + { 0x10DE00C2, "0x00C2" }, + { 0x10DE00C8, "0x00C8" }, + { 0x10DE00C9, "0x00C9" }, + { 0x10DE00CC, "0x00CC" }, + { 0x10DE00CE, "0x00CE" }, + { 0x10DE0140, "GeForce 6600 GT" }, + { 0x10DE0141, "GeForce 6600" }, + { 0x10DE0142, "0x0142" }, + { 0x10DE0143, "0x0143" }, + { 0x10DE0144, "0x0144" }, + { 0x10DE0145, "GeForce 6610 XL" }, + { 0x10DE0146, "0x0146" }, + { 0x10DE0147, "0x0147" }, + { 0x10DE0148, "0x0148" }, + { 0x10DE0149, "0x0149" }, + { 0x10DE014B, "0x014B" }, + { 0x10DE014C, "0x014C" }, + { 0x10DE014D, "0x014D" }, + { 0x10DE014E, "Quadro FX 540" }, + { 0x10DE014F, "GeForce 6200" }, + { 0x10DE0160, "0x0160" }, + { 0x10DE0166, "0x0166" }, + { 0x10DE0210, "0x0210" }, + { 0x10DE0211, "0x0211" }, + { 0x10DE021D, "0x021D" }, + { 0x10DE021E, "0x021E" }, {-1, NULL} }; @@ -350,7 +388,8 @@ typedef enum { OPTION_VIDEO_KEY, OPTION_FLAT_PANEL, OPTION_FP_DITHER, - OPTION_CRTC_NUMBER + OPTION_CRTC_NUMBER, + OPTION_FP_SCALE } NVOpts; @@ -365,6 +404,7 @@ static const OptionInfoRec NVOptions[] = { { OPTION_FLAT_PANEL, "FlatPanel", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_FP_DITHER, "FPDither", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_CRTC_NUMBER, "CrtcNumber", OPTV_INTEGER, {0}, FALSE }, + { OPTION_FP_SCALE, "FPScale", OPTV_BOOLEAN, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; @@ -494,6 +534,36 @@ NVGetScrnInfoRec(PciChipsets *chips, int chip) #define MAX_CHIPS MAXSCREENS + +static CARD32 +NVGetPCIXpressChip (pciVideoPtr pVideo) +{ + volatile CARD32 *regs; + CARD32 pciid, pcicmd; + PCITAG Tag = ((pciConfigPtr)(pVideo->thisCard))->tag; + + pcicmd = pciReadLong(Tag, PCI_CMD_STAT_REG); + pciWriteLong(Tag, PCI_CMD_STAT_REG, pcicmd | PCI_CMD_MEM_ENABLE); + + regs = xf86MapPciMem(-1, VIDMEM_MMIO, Tag, pVideo->memBase[0], 0x2000); + + pciid = regs[0x1800/4]; + + xf86UnMapVidMem(-1, (pointer)regs, 0x2000); + + pciWriteLong(Tag, PCI_CMD_STAT_REG, pcicmd); + + if((pciid & 0x0000ffff) == 0x000010DE) + pciid = 0x10DE0000 | (pciid >> 16); + else + if((pciid & 0xffff0000) == 0xDE100000) /* wrong endian */ + pciid = 0x10DE0000 | ((pciid << 8) & 0x0000ff00) | + ((pciid >> 8) & 0x000000ff); + + return pciid; +} + + /* Mandatory */ static Bool NVProbe(DriverPtr drv, int flags) @@ -523,7 +593,11 @@ NVProbe(DriverPtr drv, int flags) ((*ppPci)->vendor == PCI_VENDOR_NVIDIA)) { SymTabRec *nvchips = NVKnownChipsets; - int token = ((*ppPci)->vendor << 16) | (*ppPci)->chipType; + int pciid = ((*ppPci)->vendor << 16) | (*ppPci)->chipType; + int token = pciid; + + if((token & 0xfff0) == 0x00F0) + token = NVGetPCIXpressChip(*ppPci); while(nvchips->name) { if(token == nvchips->token) @@ -532,10 +606,10 @@ NVProbe(DriverPtr drv, int flags) } if(nvchips->name) { /* found one */ - NVChipsets[numUsed].token = nvchips->token; + NVChipsets[numUsed].token = pciid; NVChipsets[numUsed].name = nvchips->name; - NVPciChipsets[numUsed].numChipset = nvchips->token; - NVPciChipsets[numUsed].PCIid = nvchips->token; + NVPciChipsets[numUsed].numChipset = pciid; + NVPciChipsets[numUsed].PCIid = pciid; NVPciChipsets[numUsed].resList = RES_SHARED_VGA; numUsed++; } else if ((*ppPci)->vendor == PCI_VENDOR_NVIDIA) { @@ -551,10 +625,19 @@ NVProbe(DriverPtr drv, int flags) case 0x0320: case 0x0330: case 0x0340: - NVChipsets[numUsed].token = token; + case 0x0040: + case 0x00C0: + case 0x0120: + case 0x0140: + case 0x0160: + case 0x0130: + case 0x01D0: + case 0x0090: + case 0x0210: + NVChipsets[numUsed].token = pciid; NVChipsets[numUsed].name = "Unknown NVIDIA chip"; - NVPciChipsets[numUsed].numChipset = token; - NVPciChipsets[numUsed].PCIid = token; + NVPciChipsets[numUsed].numChipset = pciid; + NVPciChipsets[numUsed].PCIid = pciid; NVPciChipsets[numUsed].resList = RES_SHARED_VGA; numUsed++; break; @@ -768,6 +851,17 @@ NVFreeScreen(int scrnIndex, int flags) static ModeStatus NVValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) { + NVPtr pNv = NVPTR(xf86Screens[scrnIndex]); + + if(pNv->fpWidth && pNv->fpHeight) { + if((pNv->fpWidth < mode->HDisplay) || (pNv->fpHeight < mode->VDisplay)) { + xf86DrvMsg(scrnIndex, X_INFO, "Mode \"%s\" is larger than " + "BIOS programmed panel size of %d x %d. Removing.\n", + mode->name, pNv->fpWidth, pNv->fpHeight); + return (MODE_BAD); + } + } + return (MODE_OK); } @@ -887,11 +981,16 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) } else { from = X_PROBED; pNv->Chipset = (pNv->PciInfo->vendor << 16) | pNv->PciInfo->chipType; + + if((pNv->Chipset & 0xfff0) == 0x00F0) + pNv->Chipset = NVGetPCIXpressChip(pNv->PciInfo); + pScrn->chipset = (char *)xf86TokenToString(NVKnownChipsets, pNv->Chipset); if(!pScrn->chipset) pScrn->chipset = "Unknown NVIDIA chipset"; } + if (pNv->pEnt->device->chipRev >= 0) { pNv->ChipRev = pNv->pEnt->device->chipRev; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", @@ -1026,6 +1125,12 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) } xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", pNv->HWCursor ? "HW" : "SW"); + + pNv->FpScale = TRUE; + if (xf86GetOptValBool(pNv->Options, OPTION_FP_SCALE, &pNv->FpScale)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Flat panel scaling %s\n", + pNv->FpScale ? "on" : "off"); + } if (xf86ReturnOptValBool(pNv->Options, OPTION_NOACCEL, FALSE)) { pNv->NoAccel = TRUE; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); @@ -1178,12 +1283,46 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) return FALSE; } - pNv->alphaCursor = ((pNv->Chipset & 0x0ff0) >= 0x0110); - - pNv->Architecture = (pNv->Chipset & 0x0f00) >> 4; + switch (pNv->Chipset & 0x0ff0) { + case 0x0100: /* GeForce 256 */ + case 0x0110: /* GeForce2 MX */ + case 0x0150: /* GeForce2 */ + case 0x0170: /* GeForce4 MX */ + case 0x0180: /* GeForce4 MX (8x AGP) */ + case 0x01A0: /* nForce */ + case 0x01F0: /* nForce2 */ + pNv->Architecture = NV_ARCH_10; + break; + case 0x0200: /* GeForce3 */ + case 0x0250: /* GeForce4 Ti */ + case 0x0280: /* GeForce4 Ti (8x AGP) */ + pNv->Architecture = NV_ARCH_20; + break; + case 0x0300: /* GeForceFX 5800 */ + case 0x0310: /* GeForceFX 5600 */ + case 0x0320: /* GeForceFX 5200 */ + case 0x0330: /* GeForceFX 5900 */ + case 0x0340: /* GeForceFX 5700 */ + pNv->Architecture = NV_ARCH_30; + break; + case 0x0040: + case 0x00C0: + case 0x0120: + case 0x0130: + case 0x0140: + case 0x0160: + case 0x01D0: + case 0x0090: + case 0x0210: + pNv->Architecture = NV_ARCH_40; + break; + default: + pNv->Architecture = NV_ARCH_04; + break; + } - if(pNv->Architecture < NV_ARCH_10) - pNv->Architecture = NV_ARCH_04; + pNv->alphaCursor = (pNv->Architecture >= NV_ARCH_10) && + ((pNv->Chipset & 0x0ff0) != 0x0100); NVCommonSetup(pScrn); @@ -1225,17 +1364,17 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) clockRanges->minClock = pNv->MinVClockFreqKHz; clockRanges->maxClock = pNv->MaxVClockFreqKHz; clockRanges->clockIndex = -1; /* programmable */ - if(((pNv->Chipset & 0x0ff0) <= 0x0100) || - ((pNv->Chipset & 0x0ff0) == 0x0150) || - ((pNv->Chipset & 0x0ff0) >= 0x0300)) + clockRanges->doubleScanAllowed = TRUE; + if((pNv->Architecture == NV_ARCH_20) || + ((pNv->Architecture == NV_ARCH_10) && + ((pNv->Chipset & 0x0ff0) != 0x0100) && + ((pNv->Chipset & 0x0ff0) != 0x0150))) { - clockRanges->interlaceAllowed = TRUE; - } else { - /* No NV2x chips support interlaced modes and the only - NV1x chips that do are NV10 and NV15 */ + /* HW is broken */ clockRanges->interlaceAllowed = FALSE; + } else { + clockRanges->interlaceAllowed = TRUE; } - clockRanges->doubleScanAllowed = TRUE; if(pNv->FlatPanel == 1) { clockRanges->interlaceAllowed = FALSE; @@ -1488,22 +1627,28 @@ NVRestore(ScrnInfoPtr pScrn) NVPtr pNv = NVPTR(pScrn); NVRegPtr nvReg = &pNv->SavedReg; + NVLockUnlock(pNv, 0); + if(pNv->twoHeads) { VGA_WR08(pNv->PCIO, 0x03D4, 0x44); - VGA_WR08(pNv->PCIO, 0x03D5, nvReg->crtcOwner); + VGA_WR08(pNv->PCIO, 0x03D5, pNv->CRTCnumber * 0x3); NVLockUnlock(pNv, 0); } - NVLockUnlock(pNv, 0); - /* Only restore text mode fonts/text for the primary card */ vgaHWProtect(pScrn, TRUE); NVDACRestore(pScrn, vgaReg, nvReg, pNv->Primary); + if(pNv->twoHeads) { + VGA_WR08(pNv->PCIO, 0x03D4, 0x44); + VGA_WR08(pNv->PCIO, 0x03D5, nvReg->crtcOwner); + } vgaHWProtect(pScrn, FALSE); } static void NVBacklightEnable(NVPtr pNv, Bool on) { + CARD32 fpcontrol = pNv->PRAMDAC[0x0848/4] & 0xCfffffCC; + /* This is done differently on each laptop. Here we define the ones we know for sure. */ @@ -1524,6 +1669,12 @@ static void NVBacklightEnable(NVPtr pNv, Bool on) pNv->PCRTC0[0x081C/4] = tmp_pcrt; } #endif + + /* cut the TMDS output */ + if(on) fpcontrol |= pNv->fpSyncs; + else fpcontrol |= 0x20000022; + + pNv->PRAMDAC[0x0848/4] = fpcontrol; } static void @@ -1533,6 +1684,8 @@ NVDPMSSetLCD(ScrnInfoPtr pScrn, int PowerManagementMode, int flags) if (!pScrn->vtSema) return; + vgaHWDPMSSet(pScrn, PowerManagementMode, flags); + switch (PowerManagementMode) { case DPMSModeStandby: /* HSync: Off, VSync: On */ case DPMSModeSuspend: /* HSync: On, VSync: Off */ @@ -1544,7 +1697,6 @@ NVDPMSSetLCD(ScrnInfoPtr pScrn, int PowerManagementMode, int flags) default: break; } - vgaHWDPMSSet(pScrn, PowerManagementMode, flags); } @@ -1646,7 +1798,7 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) * function. If not, the visuals will need to be setup before calling * a fb ScreenInit() function and fixed up after. * - * For most PC hardware at depths >= 8, the defaults that cfb uses + * For most PC hardware at depths >= 8, the defaults that fb uses * are not appropriate. In this driver, we fixup the visuals after. */ @@ -1830,6 +1982,13 @@ NVSave(ScrnInfoPtr pScrn) vgaHWPtr pVga = VGAHWPTR(pScrn); vgaRegPtr vgaReg = &pVga->SavedReg; + NVLockUnlock(pNv, 0); + if(pNv->twoHeads) { + VGA_WR08(pNv->PCIO, 0x03D4, 0x44); + VGA_WR08(pNv->PCIO, 0x03D5, pNv->CRTCnumber * 0x3); + NVLockUnlock(pNv, 0); + } + NVDACSave(pScrn, vgaReg, nvReg, pNv->Primary); } |