summaryrefslogtreecommitdiff
path: root/src/nv_driver.c
diff options
context:
space:
mode:
authorDeron Johnson <deron.johnson@sun.com>2005-02-17 22:44:41 +0000
committerDeron Johnson <deron.johnson@sun.com>2005-02-17 22:44:41 +0000
commitf8a8feb0e89949217e34560abd53134b70624c79 (patch)
tree91ab46128ce82e27c7d23c348acfc0f4f84d0ab5 /src/nv_driver.c
parentbbafc6d2fcb21671de3cfb4ff973409405162e7a (diff)
Diffstat (limited to 'src/nv_driver.c')
-rw-r--r--src/nv_driver.c241
1 files changed, 207 insertions, 34 deletions
diff --git a/src/nv_driver.c b/src/nv_driver.c
index b55ece9..a1d2cb6 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.5.2.2 2004/12/16 01:42:35 gisburn 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.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);
}