diff options
Diffstat (limited to 'src/nv_driver.c')
-rw-r--r-- | src/nv_driver.c | 241 |
1 files changed, 207 insertions, 34 deletions
diff --git a/src/nv_driver.c b/src/nv_driver.c index 11e29b0..f155e41 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.5 2004/08/16 09:13:14 ajax Exp $ */ +/* $XdotOrg$ */ /* $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.130 2004/12/09 00:21:04 mvojkovi Exp $ */ #include "nv_include.h" @@ -113,18 +113,19 @@ static SymTabRec NVKnownChipsets[] = { 0x10DE0175, "GeForce4 420 Go" }, { 0x10DE0176, "GeForce4 420 Go 32M" }, { 0x10DE0177, "GeForce4 460 Go" }, + { 0x10DE0178, "Quadro4 550 XGL" }, #if defined(__powerpc__) { 0x10DE0179, "GeForce4 MX (Mac)" }, #else { 0x10DE0179, "GeForce4 440 Go 64M" }, #endif - { 0x10DE017D, "GeForce4 410 Go 16M" }, - { 0x10DE017C, "Quadro4 500 GoGL" }, - { 0x10DE0178, "Quadro4 550 XGL" }, { 0x10DE017A, "Quadro4 NVS" }, + { 0x10DE017C, "Quadro4 500 GoGL" }, + { 0x10DE017D, "GeForce4 410 Go 16M" }, { 0x10DE0181, "GeForce4 MX 440 with AGP8X" }, { 0x10DE0182, "GeForce4 MX 440SE with AGP8X" }, { 0x10DE0183, "GeForce4 MX 420 with AGP8X" }, + { 0x10DE0185, "GeForce4 MX 4000" }, { 0x10DE0186, "GeForce4 448 Go" }, { 0x10DE0187, "GeForce4 488 Go" }, { 0x10DE0188, "Quadro4 580 XGL" }, @@ -133,6 +134,8 @@ static SymTabRec NVKnownChipsets[] = #endif { 0x10DE018A, "Quadro4 280 NVS" }, { 0x10DE018B, "Quadro4 380 XGL" }, + { 0x10DE018C, "Quadro NVS 50 PCI" }, + { 0x10DE018D, "GeForce4 448 Go" }, { 0x10DE01F0, "GeForce4 MX Integrated GPU" }, { 0x10DE0200, "GeForce3" }, { 0x10DE0201, "GeForce3 Ti 200" }, @@ -174,6 +177,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 +186,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 +209,42 @@ 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" }, + { 0x10DE004D, "Quadro FX 4400" }, + { 0x10DE00C0, "0x00C0" }, + { 0x10DE00C1, "0x00C1" }, + { 0x10DE00C2, "GeForce 6800 LE" }, + { 0x10DE00C8, "0x00C8" }, + { 0x10DE00C9, "0x00C9" }, + { 0x10DE00CC, "0x00CC" }, + { 0x10DE00CE, "0x00CE" }, + { 0x10DE0140, "GeForce 6600 GT" }, + { 0x10DE0141, "GeForce 6600" }, + { 0x10DE0142, "0x0142" }, + { 0x10DE0143, "0x0143" }, + { 0x10DE0144, "GeForce Go 6600" }, + { 0x10DE0145, "GeForce 6610 XL" }, + { 0x10DE0146, "GeForce Go 6600 TE/6200 TE" }, + { 0x10DE0147, "0x0147" }, + { 0x10DE0148, "GeForce Go 6600" }, + { 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 +392,9 @@ typedef enum { OPTION_VIDEO_KEY, OPTION_FLAT_PANEL, OPTION_FP_DITHER, - OPTION_CRTC_NUMBER + OPTION_CRTC_NUMBER, + OPTION_FP_SCALE, + OPTION_FP_TWEAK } NVOpts; @@ -365,6 +409,8 @@ 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 }, + { OPTION_FP_TWEAK, "FPTweak", OPTV_INTEGER, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; @@ -494,6 +540,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 +599,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 +612,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 +631,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 +857,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 +987,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 +1131,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"); @@ -1115,6 +1226,14 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) pNv->CRTCnumber = -1; /* autodetect later */ } + + if (xf86GetOptValInteger(pNv->Options, OPTION_FP_TWEAK, + &pNv->PanelTweak)) + { + pNv->usePanelTweak = TRUE; + } else { + pNv->usePanelTweak = FALSE; + } if (pNv->pEnt->device->MemBase != 0) { /* Require that the config file value matches one of the PCI values. */ @@ -1178,12 +1297,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 +1378,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 +1641,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 +1683,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 +1698,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 +1711,6 @@ NVDPMSSetLCD(ScrnInfoPtr pScrn, int PowerManagementMode, int flags) default: break; } - vgaHWDPMSSet(pScrn, PowerManagementMode, flags); } @@ -1646,7 +1812,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 +1996,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); } |