summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--driver/xf86-video-nv/src/nv_driver.c575
1 files changed, 481 insertions, 94 deletions
diff --git a/driver/xf86-video-nv/src/nv_driver.c b/driver/xf86-video-nv/src/nv_driver.c
index f094e6bfc..265979e51 100644
--- a/driver/xf86-video-nv/src/nv_driver.c
+++ b/driver/xf86-video-nv/src/nv_driver.c
@@ -1,5 +1,3 @@
-/* $XdotOrg: driver/xf86-video-nv/src/nv_driver.c,v 1.21 2006/01/24 16:45:29 aplattner Exp $ */
-/* $XConsortium: nv_driver.c /main/3 1996/10/28 05:13:37 kaleb $ */
/*
* Copyright 1996-1997 David J. McKay
*
@@ -29,14 +27,14 @@
/* 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.144 2006/06/16 00:19:32 mvojkovi Exp $ */
-
#include "nv_include.h"
#include "xf86int10.h"
+#include "vbeModes.h"
const OptionInfoRec * RivaAvailableOptions(int chipid, int busid);
Bool RivaGetScrnInfoRec(PciChipsets *chips, int chip);
+Bool G80GetScrnInfoRec(PciChipsets *chips, int chip);
/*
* Forward definitions for the functions that make up the driver.
@@ -44,7 +42,11 @@ Bool RivaGetScrnInfoRec(PciChipsets *chips, int chip);
/* Mandatory functions */
static const OptionInfoRec * NVAvailableOptions(int chipid, int busid);
static void NVIdentify(int flags);
+#if XSERVER_LIBPCIACCESS
+static Bool NVPciProbe(DriverPtr, int entity, struct pci_device*, intptr_t data);
+#else
static Bool NVProbe(DriverPtr drv, int flags);
+#endif
static Bool NVPreInit(ScrnInfoPtr pScrn, int flags);
static Bool NVScreenInit(int Index, ScreenPtr pScreen, int argc,
char **argv);
@@ -69,9 +71,20 @@ static Bool NVMapMem(ScrnInfoPtr pScrn);
static Bool NVMapMemFBDev(ScrnInfoPtr pScrn);
static Bool NVUnmapMem(ScrnInfoPtr pScrn);
static void NVSave(ScrnInfoPtr pScrn);
+static void NVSaveRestoreVBE(ScrnInfoPtr, vbeSaveRestoreFunction);
static void NVRestore(ScrnInfoPtr pScrn);
static Bool NVModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
-
+static Bool NVSetModeVBE(ScrnInfoPtr pScrn, DisplayModePtr pMode);
+
+#if XSERVER_LIBPCIACCESS
+/* For now, just match any NVIDIA PCI device and sort through them in the probe
+ * routine */
+static const struct pci_id_match NVPciIdMatchList[] = {
+ { PCI_VENDOR_NVIDIA, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0 },
+ { PCI_VENDOR_NVIDIA_SGS, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0},
+ { 0, 0, 0 }
+};
+#endif
/*
* This contains the functions needed by the server after loading the
@@ -85,13 +98,22 @@ _X_EXPORT DriverRec NV = {
NV_VERSION,
NV_DRIVER_NAME,
NVIdentify,
+#if XSERVER_LIBPCIACCESS
+ NULL,
+#else
NVProbe,
+#endif
NVAvailableOptions,
NULL,
- 0
+ 0,
+ NULL,
+#if XSERVER_LIBPCIACCESS
+ NVPciIdMatchList,
+ NVPciProbe,
+#endif
};
-/* Known cards as of 2006/06/16 */
+/* Known cards as of 2007/07/24 */
static SymTabRec NVKnownChipsets[] =
{
@@ -332,6 +354,37 @@ static SymTabRec NVKnownChipsets[] =
{ 0x10DE0244, "GeForce Go 6150" },
{ 0x10DE0247, "GeForce Go 6100" },
+/*************** G8x ***************/
+ { 0x10DE0191, "GeForce 8800 GTX" },
+ { 0x10DE0193, "GeForce 8800 GTS" },
+ { 0x10DE0194, "GeForce 8800 Ultra" },
+ { 0x10DE019D, "Quadro FX 5600" },
+ { 0x10DE019E, "Quadro FX 4600" },
+ { 0x10DE0400, "GeForce 8600 GTS" },
+ { 0x10DE0402, "GeForce 8600 GT" },
+ { 0x10DE0404, "GeForce 8400 GS" },
+ { 0x10DE0407, "GeForce 8600M GT" },
+ { 0x10DE0409, "GeForce 8700M GT" },
+ { 0x10DE040A, "Quadro FX 370" },
+ { 0x10DE040B, "Quadro NVS 320M" },
+ { 0x10DE040C, "Quadro FX 570M" },
+ { 0x10DE040D, "Quadro FX 1600M" },
+ { 0x10DE040E, "Quadro FX 570" },
+ { 0x10DE040F, "Quadro FX 1700" },
+ { 0x10DE0421, "GeForce 8500 GT" },
+ { 0x10DE0422, "GeForce 8400 GS" },
+ { 0x10DE0423, "GeForce 8300 GS" },
+ { 0x10DE0425, "GeForce 8600M GS" },
+ { 0x10DE0426, "GeForce 8400M GT" },
+ { 0x10DE0427, "GeForce 8400M GS" },
+ { 0x10DE0428, "GeForce 8400M G" },
+ { 0x10DE0429, "Quadro NVS 140M" },
+ { 0x10DE042A, "Quadro NVS 130M" },
+ { 0x10DE042B, "Quadro NVS 135M" },
+ { 0x10DE042D, "Quadro FX 360M" },
+ { 0x10DE042F, "Quadro NVS 290" },
+ { 0x10DE0611, "GeForce 8800 GT" },
+
{-1, NULL}
};
@@ -397,6 +450,17 @@ static const char *vbeSymbols[] = {
"vbeDoEDID",
NULL
};
+
+static const char *vbeModeSymbols[] = {
+ "VBEExtendedInit",
+ "VBEGetVBEInfo",
+ "VBEGetModePool",
+ "VBEValidateModes",
+ "VBESetModeParameters",
+ "VBEGetVBEMode",
+ "VBESetVBEMode",
+ NULL
+};
#endif
static const char *i2cSymbols[] = {
@@ -440,12 +504,6 @@ static const char *int10Symbols[] = {
NULL
};
-static const char *rivaSymbols[] = {
- "RivaGetScrnInfoRec",
- "RivaAvailableOptions",
- NULL
-};
-
#ifdef XFree86LOADER
@@ -458,7 +516,7 @@ static XF86ModuleVersionInfo nvVersRec =
MODINFOSTRING1,
MODINFOSTRING2,
XORG_VERSION_CURRENT,
- NV_MAJOR_VERSION, NV_MINOR_VERSION, NV_PATCHLEVEL,
+ PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
ABI_CLASS_VIDEODRV, /* This is a video driver */
ABI_VIDEODRV_VERSION,
MOD_CLASS_VIDEODRV,
@@ -481,7 +539,8 @@ typedef enum {
OPTION_FP_DITHER,
OPTION_CRTC_NUMBER,
OPTION_FP_SCALE,
- OPTION_FP_TWEAK
+ OPTION_FP_TWEAK,
+ OPTION_DUALHEAD,
} NVOpts;
@@ -498,6 +557,7 @@ static const OptionInfoRec NVOptions[] = {
{ OPTION_CRTC_NUMBER, "CrtcNumber", OPTV_INTEGER, {0}, FALSE },
{ OPTION_FP_SCALE, "FPScale", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_FP_TWEAK, "FPTweak", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_DUALHEAD, "DualHead", OPTV_BOOLEAN, {0}, FALSE },
{ -1, NULL, OPTV_NONE, {0}, FALSE }
};
@@ -546,7 +606,13 @@ nvSetup(pointer module, pointer opts, int *errmaj, int *errmin)
if (!setupDone) {
setupDone = TRUE;
- xf86AddDriver(&NV, module, 0);
+ xf86AddDriver(&NV, module,
+#if XSERVER_LIBPCIACCESS
+ HaveDriverFuncs
+#else
+ 0
+#endif
+ );
/*
* Modules that this driver always requires may be loaded here
@@ -558,7 +624,7 @@ nvSetup(pointer module, pointer opts, int *errmaj, int *errmin)
* might refer to.
*/
LoaderRefSymLists(vgahwSymbols, xaaSymbols, fbSymbols,
- ramdacSymbols, shadowSymbols, rivaSymbols,
+ ramdacSymbols, shadowSymbols,
i2cSymbols, ddcSymbols, vbeSymbols,
fbdevHWSymbols, int10Symbols, NULL);
@@ -580,10 +646,7 @@ static const OptionInfoRec *
NVAvailableOptions(int chipid, int busid)
{
if(chipid == 0x12D20018) {
- if (!xf86LoadOneModule("riva128", NULL)) {
- return NULL;
- } else
- return RivaAvailableOptions(chipid, busid);
+ return RivaAvailableOptions(chipid, busid);
}
return NVOptions;
@@ -612,7 +675,9 @@ NVGetScrnInfoRec(PciChipsets *chips, int chip)
pScrn->driverName = NV_DRIVER_NAME;
pScrn->name = NV_NAME;
+#if !XSERVER_LIBPCIACCESS
pScrn->Probe = NVProbe;
+#endif
pScrn->PreInit = NVPreInit;
pScrn->ScreenInit = NVScreenInit;
pScrn->SwitchMode = NVSwitchMode;
@@ -629,9 +694,29 @@ NVGetScrnInfoRec(PciChipsets *chips, int chip)
static CARD32
+#if XSERVER_LIBPCIACCESS
+NVGetPCIXpressChip (struct pci_device *dev)
+#else
NVGetPCIXpressChip (pciVideoPtr pVideo)
+#endif
{
volatile CARD32 *regs;
+#if XSERVER_LIBPCIACCESS
+ uint32_t pciid, pcicmd;
+ void *tmp;
+
+ pci_device_cfg_read_u32(dev, &pcicmd, PCI_CMD_STAT_REG);
+ pci_device_cfg_write_u32(dev, pcicmd | PCI_CMD_MEM_ENABLE,
+ PCI_CMD_STAT_REG);
+
+ pci_device_map_range(dev, dev->regions[0].base_addr, 0x2000,
+ PCI_DEV_MAP_FLAG_WRITABLE, &tmp);
+ regs = tmp;
+ pciid = regs[0x1800/4];
+ pci_device_unmap_range(dev, tmp, 0x2000);
+
+ pci_device_cfg_write_u32(dev, pcicmd, PCI_CMD_STAT_REG);
+#else
CARD32 pciid, pcicmd;
PCITAG Tag = ((pciConfigPtr)(pVideo->thisCard))->tag;
@@ -645,6 +730,7 @@ NVGetPCIXpressChip (pciVideoPtr pVideo)
xf86UnMapVidMem(-1, (pointer)regs, 0x2000);
pciWriteLong(Tag, PCI_CMD_STAT_REG, pcicmd);
+#endif
if((pciid & 0x0000ffff) == 0x000010DE)
pciid = 0x10DE0000 | (pciid >> 16);
@@ -656,8 +742,96 @@ NVGetPCIXpressChip (pciVideoPtr pVideo)
return pciid;
}
+static Bool
+NVIsG80(int chipType)
+{
+ switch(chipType & 0xfff0) {
+ case 0x0190:
+ case 0x0400:
+ case 0x0420:
+ case 0x0610:
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static Bool
+NVIsSupported(CARD32 id)
+{
+ /* look for a compatible devices which may be newer than
+ the NVKnownChipsets list above. */
+ switch(id & 0xfff0) {
+ case 0x0170:
+ case 0x0180:
+ case 0x0250:
+ case 0x0280:
+ case 0x0300:
+ case 0x0310:
+ case 0x0320:
+ case 0x0330:
+ case 0x0340:
+ case 0x0040:
+ case 0x00C0:
+ case 0x0120:
+ case 0x0140:
+ case 0x0160:
+ case 0x01D0:
+ case 0x0090:
+ case 0x0210:
+ case 0x0220:
+ case 0x0240:
+ case 0x0290:
+ case 0x0390:
+ case 0x03D0:
+ return TRUE;
+ }
+
+ return FALSE;
+}
/* Mandatory */
+#if XSERVER_LIBPCIACCESS
+static Bool
+NVPciProbe(DriverPtr drv, int entity, struct pci_device *dev, intptr_t data)
+{
+ const CARD32 id = ((dev->device_id & 0xfff0) == 0x00F0 ||
+ (dev->device_id & 0xfff0) == 0x02E0) ?
+ NVGetPCIXpressChip(dev) : dev->vendor_id << 16 | dev->device_id;
+ const char *name = xf86TokenToString(NVKnownChipsets, id);
+
+ if(dev->vendor_id == PCI_VENDOR_NVIDIA && !name &&
+ !NVIsSupported(id) && !NVIsG80(id)) {
+ /* See if pci.ids knows what the heck this thing is */
+ name = pci_device_get_device_name(dev);
+ if(name)
+ xf86DrvMsg(0, X_WARNING,
+ NV_NAME ": Ignoring unsupported device 0x%x (%s) at %2.2x@%2.2x:%2.2x:%1.1x\n",
+ id, name, dev->bus, dev->domain, dev->dev, dev->func);
+ else
+ xf86DrvMsg(0, X_WARNING,
+ NV_NAME ": Ignoring unsupported device 0x%x at %2.2x@%2.2x:%2.2x:%1.1x\n",
+ id, dev->bus, dev->domain, dev->dev, dev->func);
+ return FALSE;
+ }
+
+ if(!name)
+ name = pci_device_get_device_name(dev);
+ if(!name)
+ name = "Unknown GPU";
+
+ xf86DrvMsg(0, X_PROBED,
+ NV_NAME ": Found NVIDIA %s at %2.2x@%2.2x:%2.2x:%1.1x\n",
+ name, dev->bus, dev->domain, dev->dev, dev->func);
+
+ if(NVIsG80(id))
+ return G80GetScrnInfoRec(NULL, entity);
+ else if(dev->vendor_id == PCI_VENDOR_NVIDIA_SGS)
+ return RivaGetScrnInfoRec(NULL, entity);
+ else
+ return NVGetScrnInfoRec(NULL, entity);
+}
+#else
static Bool
NVProbe(DriverPtr drv, int flags)
{
@@ -701,48 +875,15 @@ NVProbe(DriverPtr drv, int flags)
nvchips++;
}
- if(nvchips->name) { /* found one */
+ if(nvchips->name ||
+ ((*ppPci)->vendor == PCI_VENDOR_NVIDIA &&
+ (NVIsSupported(token) || NVIsG80((*ppPci)->chipType)))) {
NVChipsets[numUsed].token = pciid;
- NVChipsets[numUsed].name = nvchips->name;
- NVPciChipsets[numUsed].numChipset = pciid;
+ NVChipsets[numUsed].name = nvchips->name ? nvchips->name : "Unknown NVIDIA chip";
+ NVPciChipsets[numUsed].numChipset = pciid;
NVPciChipsets[numUsed].PCIid = pciid;
NVPciChipsets[numUsed].resList = RES_SHARED_VGA;
numUsed++;
- } else if ((*ppPci)->vendor == PCI_VENDOR_NVIDIA) {
- /* look for a compatible devices which may be newer than
- the NVKnownChipsets list above. */
- switch(token & 0xfff0) {
- case 0x0170:
- case 0x0180:
- case 0x0250:
- case 0x0280:
- case 0x0300:
- case 0x0310:
- case 0x0320:
- case 0x0330:
- case 0x0340:
- case 0x0040:
- case 0x00C0:
- case 0x0120:
- case 0x0140:
- case 0x0160:
- case 0x01D0:
- case 0x0090:
- case 0x0210:
- case 0x0220:
- case 0x0240:
- case 0x0290:
- case 0x0390:
- case 0x03D0:
- NVChipsets[numUsed].token = pciid;
- NVChipsets[numUsed].name = "Unknown NVIDIA chip";
- NVPciChipsets[numUsed].numChipset = pciid;
- NVPciChipsets[numUsed].PCIid = pciid;
- NVPciChipsets[numUsed].resList = RES_SHARED_VGA;
- numUsed++;
- break;
- default: break; /* we don't recognize it */
- }
}
}
ppPci++;
@@ -769,12 +910,11 @@ NVProbe(DriverPtr drv, int flags)
pPci = xf86GetPciInfoForEntity(usedChips[i]);
if(pPci->vendor == PCI_VENDOR_NVIDIA_SGS) {
- if (!xf86LoadDrvSubModule(drv, "riva128")) {
- continue;
- }
- xf86LoaderReqSymLists(rivaSymbols, NULL);
if(RivaGetScrnInfoRec(NVPciChipsets, usedChips[i]))
foundScreen = TRUE;
+ } else if (NVIsG80(pPci->chipType)) {
+ if(G80GetScrnInfoRec(NVPciChipsets, usedChips[i]))
+ foundScreen = TRUE;
} else {
if(NVGetScrnInfoRec(NVPciChipsets, usedChips[i]))
foundScreen = TRUE;
@@ -786,12 +926,37 @@ NVProbe(DriverPtr drv, int flags)
return foundScreen;
}
+#endif /* XSERVER_LIBPCIACCESS */
/* Usually mandatory */
Bool
NVSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
{
- return NVModeInit(xf86Screens[scrnIndex], mode);
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+
+ NVSync(pScrn);
+ return NVModeInit(pScrn, mode);
+}
+
+Bool
+NVSwitchModeVBE(int scrnIndex, DisplayModePtr mode, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ NVPtr pNv = NVPTR(pScrn);
+ const Bool disableAccess = pNv->accessEnabled;
+
+ if(disableAccess)
+ pScrn->EnableDisableFBAccess(scrnIndex, FALSE);
+
+ NVSync(pScrn);
+ if (!NVSetModeVBE(pScrn, mode))
+ return FALSE;
+ NVAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+
+ if(disableAccess)
+ pScrn->EnableDisableFBAccess(scrnIndex, TRUE);
+
+ return TRUE;
}
/*
@@ -842,6 +1007,17 @@ NVEnterVTFBDev(int scrnIndex, int flags)
return TRUE;
}
+static Bool
+NVEnterVTVBE(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+
+ if (!NVSetModeVBE(pScrn, pScrn->currentMode))
+ return FALSE;
+ NVAdjustFrame(scrnIndex, 0, 0, 0);
+ return TRUE;
+}
+
/*
* This is called when VT switching away from the X server. Its job is
* to restore the previous (text) mode.
@@ -861,7 +1037,14 @@ NVLeaveVT(int scrnIndex, int flags)
NVLockUnlock(pNv, 1);
}
+static void
+NVLeaveVTVBE(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ NVSync(pScrn);
+ NVSaveRestoreVBE(pScrn, MODE_RESTORE);
+}
static void
NVBlockHandler (
@@ -903,9 +1086,15 @@ NVCloseScreen(int scrnIndex, ScreenPtr pScreen)
NVPtr pNv = NVPTR(pScrn);
if (pScrn->vtSema) {
- NVSync(pScrn);
- NVRestore(pScrn);
- NVLockUnlock(pNv, 1);
+ if (!pNv->NoAccel)
+ NVSync(pScrn);
+
+ if (pNv->VBEDualhead) {
+ NVSaveRestoreVBE(pScrn, MODE_RESTORE);
+ } else {
+ NVRestore(pScrn);
+ NVLockUnlock(pNv, 1);
+ }
}
NVUnmapMem(pScrn);
@@ -929,6 +1118,16 @@ NVCloseScreen(int scrnIndex, ScreenPtr pScreen)
return (*pScreen->CloseScreen)(scrnIndex, pScreen);
}
+static void
+NVEnableDisableFBAccess(int scrnIndex, Bool enable)
+{
+ NVPtr pNv = NVPTR(xf86Screens[scrnIndex]);
+
+ pNv->accessEnabled = enable;
+ pNv->EnableDisableFBAccess(scrnIndex, enable);
+}
+
+
/* Free up any persistent data structures */
/* Optional */
@@ -953,14 +1152,9 @@ 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);
- }
- }
+ if(pNv->fpWidth && pNv->fpHeight)
+ if((pNv->fpWidth < mode->HDisplay) || (pNv->fpHeight < mode->VDisplay))
+ return (MODE_PANEL);
return (MODE_OK);
}
@@ -998,6 +1192,31 @@ Bool NVI2CInit(ScrnInfoPtr pScrn)
return FALSE;
}
+
+/* Copied from ddc/Property.c */
+static DisplayModePtr
+NVModesAdd(DisplayModePtr Modes, DisplayModePtr Additions)
+{
+ if (!Modes) {
+ if (Additions)
+ return Additions;
+ else
+ return NULL;
+ }
+
+ if (Additions) {
+ DisplayModePtr Mode = Modes;
+
+ while (Mode->next)
+ Mode = Mode->next;
+
+ Mode->next = Additions;
+ Additions->prev = Mode;
+ }
+
+ return Modes;
+}
+
/* Mandatory */
Bool
NVPreInit(ScrnInfoPtr pScrn, int flags)
@@ -1007,6 +1226,7 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
int i, max_width, max_height;
ClockRangePtr clockRanges;
const char *s;
+ Bool config_mon_rates;
if (flags & PROBE_DETECT) {
EntityInfoPtr pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
@@ -1051,8 +1271,10 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
/* Find the PCI info for this screen */
pNv->PciInfo = xf86GetPciInfoForEntity(pNv->pEnt->index);
+#if !XSERVER_LIBPCIACCESS
pNv->PciTag = pciTag(pNv->PciInfo->bus, pNv->PciInfo->device,
pNv->PciInfo->func);
+#endif
pNv->Primary = xf86IsPrimaryPci(pNv->PciInfo);
@@ -1088,7 +1310,7 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
pNv->Chipset);
} else {
from = X_PROBED;
- pNv->Chipset = (pNv->PciInfo->vendor << 16) | pNv->PciInfo->chipType;
+ pNv->Chipset = VENDOR_ID(pNv->PciInfo) << 16 | DEVICE_ID(pNv->PciInfo);
if(((pNv->Chipset & 0xfff0) == 0x00F0) ||
((pNv->Chipset & 0xfff0) == 0x02E0))
@@ -1107,7 +1329,7 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
pNv->ChipRev);
} else {
- pNv->ChipRev = pNv->PciInfo->chipRev;
+ pNv->ChipRev = CHIP_REVISION(pNv->PciInfo);
}
/*
@@ -1356,7 +1578,43 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
} else {
pNv->usePanelTweak = FALSE;
}
-
+
+ if (xf86ReturnOptValBool(pNv->Options, OPTION_DUALHEAD, FALSE)) {
+ if (pNv->FBDev)
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "FBDev and Dualhead are incompatible.\n");
+ else
+ pNv->VBEDualhead = TRUE;
+ }
+
+ if (pNv->VBEDualhead) {
+ if (!xf86LoadSubModule(pScrn, "vbe")) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Couldn't load the VBE module and Dualhead is "
+ "enabled.\n");
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(vbeModeSymbols, NULL);
+ pNv->pVbe = VBEExtendedInit(NULL, pNv->pEnt->index,
+ SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH);
+ if (!pNv->pVbe) return FALSE;
+
+ pNv->pVbeInfo = VBEGetVBEInfo(pNv->pVbe);
+ if (!pNv->pVbeInfo) return FALSE;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Using VBE dual-head mode.\n");
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Using software cursor.\n");
+ pNv->HWCursor = FALSE;
+
+ pScrn->SwitchMode = NVSwitchModeVBE;
+ pScrn->EnterVT = NVEnterVTVBE;
+ pScrn->LeaveVT = NVLeaveVTVBE;
+ pScrn->ValidMode = NULL;
+ }
+
if (pNv->pEnt->device->MemBase != 0) {
/* Require that the config file value matches one of the PCI values. */
if (!xf86CheckPciMemBase(pNv->PciInfo, pNv->pEnt->device->MemBase)) {
@@ -1370,8 +1628,8 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
pNv->FbAddress = pNv->pEnt->device->MemBase;
from = X_CONFIG;
} else {
- if (pNv->PciInfo->memBase[1] != 0) {
- pNv->FbAddress = pNv->PciInfo->memBase[1] & 0xff800000;
+ if (MEMBASE(pNv->PciInfo, 1) != 0) {
+ pNv->FbAddress = MEMBASE(pNv->PciInfo, 1) & 0xff800000;
from = X_PROBED;
} else {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -1397,8 +1655,8 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
pNv->IOAddress = pNv->pEnt->device->IOBase;
from = X_CONFIG;
} else {
- if (pNv->PciInfo->memBase[0] != 0) {
- pNv->IOAddress = pNv->PciInfo->memBase[0] & 0xffffc000;
+ if (MEMBASE(pNv->PciInfo, 0) != 0) {
+ pNv->IOAddress = MEMBASE(pNv->PciInfo, 0) & 0xffffc000;
from = X_PROBED;
} else {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -1464,6 +1722,12 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
pNv->alphaCursor = (pNv->Architecture >= NV_ARCH_10) &&
((pNv->Chipset & 0x0ff0) != 0x0100);
+ if ((pScrn->monitor->nHsync == 0) &&
+ (pScrn->monitor->nVrefresh == 0))
+ config_mon_rates = FALSE;
+ else
+ config_mon_rates = TRUE;
+
NVCommonSetup(pScrn);
if (pNv->FBDev) {
@@ -1533,20 +1797,66 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
max_height = 4096;
}
+ /* If DFP, add a modeline corresponding to its panel size */
+ if (pNv->FlatPanel && !pNv->Television && pNv->fpWidth && pNv->fpHeight) {
+ DisplayModePtr Mode;
+
+ Mode = xf86CVTMode(pNv->fpWidth, pNv->fpHeight, 60.00, TRUE, FALSE);
+ Mode->type = M_T_DRIVER;
+ pScrn->monitor->Modes = NVModesAdd(pScrn->monitor->Modes, Mode);
+
+ if (!config_mon_rates) {
+ if (!Mode->HSync)
+ Mode->HSync = ((float) Mode->Clock ) / ((float) Mode->HTotal);
+ if (!Mode->VRefresh)
+ Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) /
+ ((float) (Mode->HTotal * Mode->VTotal));
+
+ if (Mode->HSync < pScrn->monitor->hsync[0].lo)
+ pScrn->monitor->hsync[0].lo = Mode->HSync;
+ if (Mode->HSync > pScrn->monitor->hsync[0].hi)
+ pScrn->monitor->hsync[0].hi = Mode->HSync;
+ if (Mode->VRefresh < pScrn->monitor->vrefresh[0].lo)
+ pScrn->monitor->vrefresh[0].lo = Mode->VRefresh;
+ if (Mode->VRefresh > pScrn->monitor->vrefresh[0].hi)
+ pScrn->monitor->vrefresh[0].hi = Mode->VRefresh;
+
+ pScrn->monitor->nHsync = 1;
+ pScrn->monitor->nVrefresh = 1;
+ }
+ }
+
/*
* xf86ValidateModes will check that the mode HTotal and VTotal values
* don't exceed the chipset's limit if pScrn->maxHValue and
* pScrn->maxVValue are set. Since our NVValidMode() already takes
* care of this, we don't worry about setting them here.
*/
- i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
- pScrn->display->modes, clockRanges,
- NULL, 256, max_width,
- 512, 128, max_height,
- pScrn->display->virtualX,
- pScrn->display->virtualY,
- pNv->ScratchBufferStart,
- LOOKUP_BEST_REFRESH);
+ if (pNv->VBEDualhead) {
+ pScrn->modePool = VBEGetModePool(pScrn, pNv->pVbe, pNv->pVbeInfo,
+ V_MODETYPE_VBE);
+
+ VBESetModeNames(pScrn->modePool);
+ i = VBEValidateModes(pScrn, pScrn->monitor->Modes,
+ pScrn->display->modes, clockRanges,
+ NULL, 256, max_width,
+ 512, 128, max_height,
+ pScrn->display->virtualX,
+ pScrn->display->virtualY,
+ pNv->ScratchBufferStart,
+ LOOKUP_BEST_REFRESH);
+ if (i > 0)
+ VBESetModeParameters(pScrn, pNv->pVbe);
+ } else {
+ i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
+ pScrn->display->modes, clockRanges,
+ NULL, 256, max_width,
+ 512, 128, max_height,
+ pScrn->display->virtualX,
+ pScrn->display->virtualY,
+ pNv->ScratchBufferStart,
+ LOOKUP_BEST_REFRESH);
+ }
if (i < 1 && pNv->FBDev) {
fbdevHWUseBuildinMode(pScrn);
@@ -1579,6 +1889,22 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
*/
xf86SetCrtcForModes(pScrn, 0);
+ if (pNv->VBEDualhead) {
+ DisplayModePtr p = pScrn->modes;
+
+ /*
+ * Loop through modes and double their widths. Stash the real width in
+ * CrtcHDisplay. Also adjust the screen dimensions.
+ */
+ do {
+ p->CrtcHDisplay = p->HDisplay;
+ p->HDisplay *= 2;
+ } while ((p = p->next) != pScrn->modes);
+
+ pScrn->virtualX *= 2;
+ pScrn->displayWidth *= 2;
+ }
+
/* Set the current mode to the first in the list */
pScrn->currentMode = pScrn->modes;
@@ -1654,13 +1980,20 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
static Bool
NVMapMem(ScrnInfoPtr pScrn)
{
- NVPtr pNv;
-
- pNv = NVPTR(pScrn);
+ NVPtr pNv = NVPTR(pScrn);
+#if XSERVER_LIBPCIACCESS
+ void *tmp;
+
+ pci_device_map_range(pNv->PciInfo, pNv->FbAddress, pNv->FbMapSize,
+ PCI_DEV_MAP_FLAG_WRITABLE |
+ PCI_DEV_MAP_FLAG_WRITE_COMBINE, &tmp);
+ pNv->FbBase = tmp;
+#else
pNv->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
pNv->PciTag, pNv->FbAddress,
pNv->FbMapSize);
+#endif
if (pNv->FbBase == NULL)
return FALSE;
@@ -1696,7 +2029,11 @@ NVUnmapMem(ScrnInfoPtr pScrn)
pNv = NVPTR(pScrn);
+#if XSERVER_LIBPCIACCESS
+ pci_device_unmap_range(pNv->PciInfo, pNv->FbBase, pNv->FbMapSize);
+#else
xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pNv->FbBase, pNv->FbMapSize);
+#endif
pNv->FbBase = NULL;
pNv->FbStart = NULL;
@@ -1760,6 +2097,32 @@ NVModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
return TRUE;
}
+static Bool
+NVSetModeVBE(ScrnInfoPtr pScrn, DisplayModePtr pMode)
+{
+ NVPtr pNv = NVPTR(pScrn);
+ VbeModeInfoData *data;
+ int mode;
+
+ data = (VbeModeInfoData*)pMode->Private;
+ mode = data->mode | 1 << 14;
+
+ if(!VBESetVBEMode(pNv->pVbe, mode, data->block))
+ return FALSE;
+ pNv->PCRTC0[0x820/4] = pNv->PCRTC0[0x2820/4] =
+ pScrn->displayWidth * (pScrn->bitsPerPixel / 8);
+ pNv->vbeCRTC1Offset = pMode->CrtcHDisplay * (pScrn->bitsPerPixel / 8);
+
+ pScrn->vtSema = TRUE;
+
+ NVLoadStateExt(pNv, NULL);
+ NVResetGraphics(pScrn);
+
+ pNv->CurrentLayout.mode = pMode;
+
+ return TRUE;
+}
+
/*
* Restore the initial (text) mode.
*/
@@ -1771,6 +2134,8 @@ NVRestore(ScrnInfoPtr pScrn)
NVPtr pNv = NVPTR(pScrn);
NVRegPtr nvReg = &pNv->SavedReg;
+ if(pNv->HWCursor)
+ NVShowHideCursor(pNv, 0);
NVLockUnlock(pNv, 0);
if(pNv->twoHeads) {
@@ -1930,6 +2295,10 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
fbdevHWSave(pScrn);
if (!fbdevHWModeInit(pScrn, pScrn->currentMode))
return FALSE;
+ } else if (pNv->VBEDualhead) {
+ NVSaveRestoreVBE(pScrn, MODE_SAVE);
+ if (!NVSetModeVBE(pScrn, pScrn->currentMode))
+ return FALSE;
} else {
/* Save the current state */
NVSave(pScrn);
@@ -2125,6 +2494,10 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
pNv->BlockHandler = pScreen->BlockHandler;
pScreen->BlockHandler = NVBlockHandler;
+ pNv->accessEnabled = TRUE;
+ pNv->EnableDisableFBAccess = pScrn->EnableDisableFBAccess;
+ pScrn->EnableDisableFBAccess = NVEnableDisableFBAccess;
+
#ifdef RANDR
/* Install our DriverFunc. We have to do it this way instead of using the
* HaveDriverFuncs argument to xf86AddDriver, because InitOutput clobbers
@@ -2163,6 +2536,20 @@ NVSave(ScrnInfoPtr pScrn)
NVDACSave(pScrn, vgaReg, nvReg, pNv->Primary);
}
+static void
+NVSaveRestoreVBE(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function)
+{
+ NVPtr pNv = NVPTR(pScrn);
+
+ if (function == MODE_SAVE) {
+ VBEGetVBEMode(pNv->pVbe, &pNv->vbeMode);
+ NVSave(pScrn);
+ } else if (function == MODE_RESTORE) {
+ NVRestore(pScrn);
+ VBESetVBEMode(pNv->pVbe, pNv->vbeMode, NULL);
+ }
+}
+
#ifdef RANDR
static Bool
NVRandRGetInfo(ScrnInfoPtr pScrn, Rotation *rotations)
@@ -2223,4 +2610,4 @@ NVDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op, pointer data)
return FALSE;
}
-#endif
+#endif /* RANDR */