summaryrefslogtreecommitdiff
path: root/src/nv_driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nv_driver.c')
-rw-r--r--src/nv_driver.c221
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);
}