Makefile.am | 2 README.G80 | 5 compat/.gitignore | 2 compat/Makefile.am | 15 + compat/README | 7 configure.ac | 72 +++++-- man/Makefile.am | 9 man/nv.man | 29 +- src/Makefile.am | 31 ++- src/g80_cursor.c | 150 +++------------ src/g80_cursor.h | 8 src/g80_dac.c | 199 ++++++++++++++++++++ src/g80_ddc.c | 230 ----------------------- src/g80_ddc.h | 1 src/g80_display.c | 485 +++++++++++++++++++++++++------------------------ src/g80_display.h | 22 +- src/g80_driver.c | 239 ++++++++++++++---------- src/g80_exa.c | 329 +++++++++++++++++++++++++++++++++ src/g80_exa.h | 1 src/g80_output.c | 350 +++++++++++++++++++++++++++++++++++ src/g80_output.h | 31 +++ src/g80_sor.c | 301 ++++++++++++++++++++++++++++++ src/g80_type.h | 40 ++-- src/g80_xaa.c | 10 - src/g80_xaa.h | 5 src/local_xf86Rename.h | 23 ++ src/nv_dac.c | 3 src/nv_driver.c | 236 ++++++++++++++++++++--- src/nv_hw.c | 19 + src/nv_include.h | 5 src/nv_local.h | 3 src/nv_setup.c | 3 src/nv_type.h | 11 + src/nv_video.c | 13 - src/riva_hw.c | 2 src/riva_include.h | 5 src/riva_local.h | 3 37 files changed, 2070 insertions(+), 829 deletions(-)
New commits: commit 209c84e788faf3c4d0ce053e5f29ff5f5b798628 Author: Aaron Plattner <[EMAIL PROTECTED]> Date: Mon Jun 18 13:08:31 2007 -0700 Bump to 2.1.0. diff --git a/configure.ac b/configure.ac index 66a1efb..0b5c14b 100644 --- a/configure.ac +++ b/configure.ac @@ -22,7 +22,7 @@ AC_PREREQ(2.57) AC_INIT([xf86-video-nv], - 2.0.96, + 2.1.0, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xf86-video-nv) commit 24770ccf880f056bc0db9464249caca10692fb56 Author: Aaron Plattner <[EMAIL PROTECTED]> Date: Mon Jun 18 12:36:29 2007 -0700 Fix some random colormap corruption on DFPs with certain pre-G80 GPUs. diff --git a/src/nv_dac.c b/src/nv_dac.c index 3fb687f..e1f0740 100644 --- a/src/nv_dac.c +++ b/src/nv_dac.c @@ -1,6 +1,6 @@ /***************************************************************************\ |* *| -|* Copyright 2003 NVIDIA, Corporation. All rights reserved. *| +|* Copyright 2007 NVIDIA, Corporation. All rights reserved. *| |* *| |* NOTICE TO USER: The source code is copyrighted under U.S. and *| |* international laws. Users and possessors of this source code are *| @@ -221,6 +221,7 @@ NVDACInit(ScrnInfoPtr pScrn, DisplayModePtr mode) } nvReg->crtcSync = pNv->PRAMDAC[0x0828/4]; nvReg->crtcSync += NVDACPanelTweaks(pNv, nvReg); + nvReg->crtcVSync = pNv->fpVTotal - 6; } nvReg->vpll = nvReg->pll; diff --git a/src/nv_hw.c b/src/nv_hw.c index ae499fa..63f9067 100644 --- a/src/nv_hw.c +++ b/src/nv_hw.c @@ -1501,6 +1501,7 @@ void NVLoadStateExt ( } else { pNv->PRAMDAC[0x0848/4] = state->scale; pNv->PRAMDAC[0x0828/4] = state->crtcSync; + pNv->PRAMDAC[0x0808/4] = state->crtcVSync; } pNv->PRAMDAC[0x0600/4] = state->general; @@ -1588,6 +1589,7 @@ void NVUnloadStateExt if(pNv->FlatPanel) { state->crtcSync = pNv->PRAMDAC[0x0828/4]; + state->crtcVSync = pNv->PRAMDAC[0x0808/4]; } } diff --git a/src/nv_setup.c b/src/nv_setup.c index 71d7955..1bf58e0 100644 --- a/src/nv_setup.c +++ b/src/nv_setup.c @@ -687,6 +687,7 @@ NVCommonSetup(ScrnInfoPtr pScrn) if(pNv->FlatPanel && !pNv->Television) { pNv->fpWidth = pNv->PRAMDAC[0x0820/4] + 1; pNv->fpHeight = pNv->PRAMDAC[0x0800/4] + 1; + pNv->fpVTotal = pNv->PRAMDAC[0x804/4] + 1; pNv->fpSyncs = pNv->PRAMDAC[0x0848/4] & 0x30000033; xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %i x %i\n", pNv->fpWidth, pNv->fpHeight); diff --git a/src/nv_type.h b/src/nv_type.h index b10babc..b4f1cd3 100644 --- a/src/nv_type.h +++ b/src/nv_type.h @@ -70,6 +70,7 @@ typedef struct _riva_hw_state U032 timingV; U032 displayV; U032 crtcSync; + U032 crtcVSync; } RIVA_HW_STATE, *NVRegPtr; @@ -161,6 +162,7 @@ typedef struct { Bool fpScaler; int fpWidth; int fpHeight; + CARD32 fpVTotal; CARD32 fpSyncs; Bool usePanelTweak; int PanelTweak; commit 4e56465a79587c4df6bf1dfd7cc87a4f22707a8f Author: Aaron Plattner <[EMAIL PROTECTED]> Date: Thu Jun 7 18:28:56 2007 -0700 G80: Mode validation. Disable LVDS modes larger than the native resolution. Disable dual-link TMDS modes for now since they don't work reliably. diff --git a/src/g80_output.c b/src/g80_output.c index 6a2723b..11bdb25 100644 --- a/src/g80_output.c +++ b/src/g80_output.c @@ -164,8 +164,10 @@ G80OutputSetPClk(xf86OutputPtr output, int pclk) int G80OutputModeValid(xf86OutputPtr output, DisplayModePtr mode) { - if(mode->Clock > 400000 || mode->Clock < 25000) - return MODE_CLOCK_RANGE; + if(mode->Clock > 400000) + return MODE_CLOCK_HIGH; + if(mode->Clock < 25000) + return MODE_CLOCK_LOW; return MODE_OK; } diff --git a/src/g80_sor.c b/src/g80_sor.c index a51e5e0..2ab9f2e 100644 --- a/src/g80_sor.c +++ b/src/g80_sor.c @@ -65,6 +65,30 @@ G80SorDPMSSet(xf86OutputPtr output, int mode) while((pNv->reg[(0x61C030+off)/4] & 0x10000000)); } +static int +G80TMDSModeValid(xf86OutputPtr output, DisplayModePtr mode) +{ + // Disable dual-link modes until I can find a way to make them work + // reliably. + if (mode->Clock > 165000) + return MODE_CLOCK_HIGH; + + return G80OutputModeValid(output, mode); +} + +static int +G80LVDSModeValid(xf86OutputPtr output, DisplayModePtr mode) +{ + G80OutputPrivPtr pPriv = output->driver_private; + DisplayModePtr native = pPriv->nativeMode; + + // Ignore modes larger than the native res. + if (mode->HDisplay > native->HDisplay || mode->VDisplay > native->VDisplay) + return MODE_PANEL; + + return G80OutputModeValid(output, mode); +} + static void G80SorModeSet(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) @@ -180,7 +204,7 @@ static const xf86OutputFuncsRec G80SorTMDSOutputFuncs = { .dpms = G80SorDPMSSet, .save = NULL, .restore = NULL, - .mode_valid = G80OutputModeValid, + .mode_valid = G80TMDSModeValid, .mode_fixup = G80OutputModeFixup, .prepare = G80OutputPrepare, .commit = G80OutputCommit, @@ -194,7 +218,7 @@ static const xf86OutputFuncsRec G80SorLVDSOutputFuncs = { .dpms = G80SorDPMSSet, .save = NULL, .restore = NULL, - .mode_valid = G80OutputModeValid, + .mode_valid = G80LVDSModeValid, .mode_fixup = G80SorModeFixupScale, .prepare = G80OutputPrepare, .commit = G80OutputCommit, commit 6b71721439802bffd715602af3036083ff442449 Author: Aaron Plattner <[EMAIL PROTECTED]> Date: Mon Jun 4 23:15:42 2007 -0700 G80: LVDS support. diff --git a/src/g80_output.c b/src/g80_output.c index d68250f..6a2723b 100644 --- a/src/g80_output.c +++ b/src/g80_output.c @@ -85,6 +85,7 @@ static Bool G80ReadPortMapping(int scrnIndex, G80Ptr pNv) "for port %i\n", or, pNv->i2cMap[port].sor, port); pNv->i2cMap[port].sor = or; + pNv->i2cMap[port].panelType = (type == 2) ? TMDS : LVDS; break; } } @@ -317,7 +318,8 @@ G80CreateOutputs(ScrnInfoPtr pScrn) if(pNv->i2cMap[i].dac != -1) dac = G80CreateDac(pScrn, pNv->i2cMap[i].dac); if(pNv->i2cMap[i].sor != -1) - sor = G80CreateSor(pScrn, pNv->i2cMap[i].sor); + sor = G80CreateSor(pScrn, pNv->i2cMap[i].sor, + pNv->i2cMap[i].panelType); if(dac) { G80OutputPrivPtr pPriv = dac->driver_private; diff --git a/src/g80_output.h b/src/g80_output.h index 0b666f5..900b76d 100644 --- a/src/g80_output.h +++ b/src/g80_output.h @@ -1,6 +1,8 @@ typedef struct G80OutputPrivRec { ORType type; ORNum or; + PanelType panelType; + DisplayModePtr nativeMode; xf86OutputPtr partner; I2CBusPtr i2c; @@ -26,4 +28,4 @@ xf86OutputPtr G80CreateDac(ScrnInfoPtr, ORNum); Bool G80DacLoadDetect(xf86OutputPtr); /* g80_sor.c */ -xf86OutputPtr G80CreateSor(ScrnInfoPtr, ORNum); +xf86OutputPtr G80CreateSor(ScrnInfoPtr, ORNum, PanelType); diff --git a/src/g80_sor.c b/src/g80_sor.c index ea7e015..a51e5e0 100644 --- a/src/g80_sor.c +++ b/src/g80_sor.c @@ -38,8 +38,9 @@ G80SorSetPClk(xf86OutputPtr output, int pclk) G80Ptr pNv = G80PTR(output->scrn); G80OutputPrivPtr pPriv = output->driver_private; const int orOff = 0x800 * pPriv->or; + const int limit = pPriv->panelType == LVDS ? 112000 : 165000; - pNv->reg[(0x00614300+orOff)/4] = (pclk > 165000) ? 0x101 : 0; + pNv->reg[(0x00614300+orOff)/4] = (pclk > limit) ? 0x101 : 0; } static void @@ -61,6 +62,7 @@ G80SorDPMSSet(xf86OutputPtr output, int mode) tmp &= ~1; pNv->reg[(0x0061C004+off)/4] = tmp; + while((pNv->reg[(0x61C030+off)/4] & 0x10000000)); } static void @@ -70,6 +72,7 @@ G80SorModeSet(xf86OutputPtr output, DisplayModePtr mode, ScrnInfoPtr pScrn = output->scrn; G80OutputPrivPtr pPriv = output->driver_private; const int sorOff = 0x40 * pPriv->or; + CARD32 type; if(!adjusted_mode) { /* Disconnect the SOR */ @@ -77,6 +80,13 @@ G80SorModeSet(xf86OutputPtr output, DisplayModePtr mode, return; } + if(pPriv->panelType == LVDS) + type = 0; + else if(adjusted_mode->Clock > 165000) + type = 0x500; + else + type = 0x100; + // This wouldn't be necessary, but the server is stupid and calls // G80SorDPMSSet after the output is disconnected, even though the hardware // turns it off automatically. @@ -84,7 +94,7 @@ G80SorModeSet(xf86OutputPtr output, DisplayModePtr mode, C(0x00000600 + sorOff, (G80CrtcGetHead(output->crtc) == HEAD0 ? 1 : 2) | - (adjusted_mode->Clock > 165000 ? 0x500 : 0x100) | + type | ((adjusted_mode->Flags & V_NHSYNC) ? 0x1000 : 0) | ((adjusted_mode->Flags & V_NVSYNC) ? 0x2000 : 0)); } @@ -92,7 +102,6 @@ G80SorModeSet(xf86OutputPtr output, DisplayModePtr mode, static xf86OutputStatus G80SorDetect(xf86OutputPtr output) { - G80OutputPrivPtr pPriv = output->driver_private; /* Assume physical status isn't going to change before the BlockHandler */ @@ -103,16 +112,71 @@ G80SorDetect(xf86OutputPtr output) return pPriv->cached_status; } +static xf86OutputStatus +G80SorLVDSDetect(xf86OutputPtr output) +{ + /* Assume LVDS is always connected */ + return XF86OutputStatusConnected; +} + static void G80SorDestroy(xf86OutputPtr output) { + G80OutputPrivPtr pPriv = output->driver_private; + G80OutputDestroy(output); + if(pPriv->nativeMode) { + if(pPriv->nativeMode->name) + xfree(pPriv->nativeMode->name); + xfree(pPriv->nativeMode); + } + xfree(output->driver_private); output->driver_private = NULL; } -static const xf86OutputFuncsRec G80SorOutputFuncs = { +/******************** LVDS ********************/ +static Bool +G80SorModeFixupScale(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + G80OutputPrivPtr pPriv = output->driver_private; + DisplayModePtr native = pPriv->nativeMode; + + // Stash the saved mode timings in adjusted_mode + adjusted_mode->Clock = native->Clock; + adjusted_mode->Flags = native->Flags; + adjusted_mode->CrtcHDisplay = native->CrtcHDisplay; + adjusted_mode->CrtcHBlankStart = native->CrtcHBlankStart; + adjusted_mode->CrtcHSyncStart = native->CrtcHSyncStart; + adjusted_mode->CrtcHSyncEnd = native->CrtcHSyncEnd; + adjusted_mode->CrtcHBlankEnd = native->CrtcHBlankEnd; + adjusted_mode->CrtcHTotal = native->CrtcHTotal; + adjusted_mode->CrtcHSkew = native->CrtcHSkew; + adjusted_mode->CrtcVDisplay = native->CrtcVDisplay; + adjusted_mode->CrtcVBlankStart = native->CrtcVBlankStart; + adjusted_mode->CrtcVSyncStart = native->CrtcVSyncStart; + adjusted_mode->CrtcVSyncEnd = native->CrtcVSyncEnd; + adjusted_mode->CrtcVBlankEnd = native->CrtcVBlankEnd; + adjusted_mode->CrtcVTotal = native->CrtcVTotal; + adjusted_mode->CrtcHAdjusted = native->CrtcHAdjusted; + adjusted_mode->CrtcVAdjusted = native->CrtcVAdjusted; + + // This mode is already "fixed" + G80CrtcSkipModeFixup(output->crtc); + + return TRUE; +} + +static DisplayModePtr +G80SorGetLVDSModes(xf86OutputPtr output) +{ + G80OutputPrivPtr pPriv = output->driver_private; + return xf86DuplicateMode(pPriv->nativeMode); +} + +static const xf86OutputFuncsRec G80SorTMDSOutputFuncs = { .dpms = G80SorDPMSSet, .save = NULL, .restore = NULL, @@ -126,33 +190,88 @@ static const xf86OutputFuncsRec G80SorOutputFuncs = { .destroy = G80SorDestroy, }; +static const xf86OutputFuncsRec G80SorLVDSOutputFuncs = { + .dpms = G80SorDPMSSet, + .save = NULL, + .restore = NULL, + .mode_valid = G80OutputModeValid, + .mode_fixup = G80SorModeFixupScale, + .prepare = G80OutputPrepare, + .commit = G80OutputCommit, + .mode_set = G80SorModeSet, + .detect = G80SorLVDSDetect, + .get_modes = G80SorGetLVDSModes, + .destroy = G80SorDestroy, +}; + +static DisplayModePtr +GetLVDSNativeMode(G80Ptr pNv) +{ + DisplayModePtr mode = xnfcalloc(1, sizeof(DisplayModeRec)); + const CARD32 size = pNv->reg[0x00610B4C/4]; + const int width = size & 0x3fff; + const int height = (size >> 16) & 0x3fff; + + mode->HDisplay = mode->CrtcHDisplay = width; + mode->VDisplay = mode->CrtcVDisplay = height; + mode->Clock = pNv->reg[0x610AD4/4] & 0x3fffff; + mode->CrtcHBlankStart = pNv->reg[0x610AFC/4]; + mode->CrtcHSyncEnd = pNv->reg[0x610B04/4]; + mode->CrtcHBlankEnd = pNv->reg[0x610AE8/4]; + mode->CrtcHTotal = pNv->reg[0x610AF4/4]; + + mode->next = mode->prev = NULL; + mode->status = MODE_OK; + mode->type = M_T_DRIVER | M_T_PREFERRED; + + xf86SetModeDefaultName(mode); + + return mode; +} + xf86OutputPtr -G80CreateSor(ScrnInfoPtr pScrn, ORNum or) +G80CreateSor(ScrnInfoPtr pScrn, ORNum or, PanelType panelType) { G80Ptr pNv = G80PTR(pScrn); G80OutputPrivPtr pPriv = xnfcalloc(sizeof(*pPriv), 1); const int off = 0x800 * or; xf86OutputPtr output; char orName[5]; + const xf86OutputFuncsRec *funcs; if(!pPriv) return FALSE; - pNv->reg[(0x61C00C+off)/4] = 0x03010700; - pNv->reg[(0x61C010+off)/4] = 0x0000152f; - pNv->reg[(0x61C014+off)/4] = 0x00000000; - pNv->reg[(0x61C018+off)/4] = 0x00245af8; + if(panelType == LVDS) { + strcpy(orName, "LVDS"); + funcs = &G80SorLVDSOutputFuncs; + } else { + snprintf(orName, 5, "DVI%d", or); + pNv->reg[(0x61C00C+off)/4] = 0x03010700; + pNv->reg[(0x61C010+off)/4] = 0x0000152f; + pNv->reg[(0x61C014+off)/4] = 0x00000000; + pNv->reg[(0x61C018+off)/4] = 0x00245af8; + funcs = &G80SorTMDSOutputFuncs; + } - snprintf(orName, 5, "DVI%i", or); - output = xf86OutputCreate(pScrn, &G80SorOutputFuncs, orName); + output = xf86OutputCreate(pScrn, funcs, orName); pPriv->type = SOR; pPriv->or = or; + pPriv->panelType = panelType; pPriv->cached_status = XF86OutputStatusUnknown; pPriv->set_pclk = G80SorSetPClk; output->driver_private = pPriv; output->interlaceAllowed = TRUE; output->doubleScanAllowed = TRUE; + if(panelType == LVDS) { + pPriv->nativeMode = GetLVDSNativeMode(pNv); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s native size %dx%d\n", + orName, pPriv->nativeMode->HDisplay, + pPriv->nativeMode->VDisplay); + } + return output; } diff --git a/src/g80_type.h b/src/g80_type.h index 15b8792..819a9f6 100644 --- a/src/g80_type.h +++ b/src/g80_type.h @@ -25,6 +25,11 @@ typedef enum ORNum { SOR1 = 1 } ORNum; +typedef enum PanelType { + TMDS, + LVDS, +} PanelType; + typedef enum AccelMethod { XAA, EXA, @@ -41,8 +46,9 @@ typedef struct G80Rec { const unsigned char*table1; int offscreenHeight; struct { - ORNum dac; - ORNum sor; + ORNum dac; + ORNum sor; + PanelType panelType; } i2cMap[4]; xf86Int10InfoPtr int10; commit 70b304cd0df0af515ce8414559f28a7ca7825517 Author: Aaron Plattner <[EMAIL PROTECTED]> Date: Mon Jun 4 22:38:14 2007 -0700 G80: Rearrange HW video timing computations. Compute the HW parameters in G80CrtcModeFixup and stash them in adjusted_mode. Move some register writes into G80CreateSor. diff --git a/src/g80_display.c b/src/g80_display.c index 652a5a9..d10f2d6 100644 --- a/src/g80_display.c +++ b/src/g80_display.c @@ -40,6 +40,7 @@ typedef struct G80CrtcPrivRec { Head head; int pclk; /* Target pixel clock in kHz */ Bool cursorVisible; + Bool skipModeFixup; } G80CrtcPrivRec, *G80CrtcPrivPtr; static void G80CrtcShowHideCursor(xf86CrtcPtr crtc, Bool show, Bool update); @@ -234,14 +235,6 @@ G80DispPreInit(ScrnInfoPtr pScrn) pNv->reg[0x006101D8/4] = pNv->reg[0x0061B000/4]; pNv->reg[0x006101E0/4] = pNv->reg[0x0061C000/4]; pNv->reg[0x006101E4/4] = pNv->reg[0x0061C800/4]; - pNv->reg[0x0061c00c/4] = 0x03010700; - pNv->reg[0x0061c010/4] = 0x0000152f; - pNv->reg[0x0061c014/4] = 0x00000000; - pNv->reg[0x0061c018/4] = 0x00245af8; - pNv->reg[0x0061c80c/4] = 0x03010700; - pNv->reg[0x0061c810/4] = 0x0000152f; - pNv->reg[0x0061c814/4] = 0x00000000; - pNv->reg[0x0061c818/4] = 0x00245af8; pNv->reg[0x0061A004/4] = 0x80550000; pNv->reg[0x0061A010/4] = 0x00000001; pNv->reg[0x0061A804/4] = 0x80550000; @@ -308,13 +301,35 @@ G80DispShutdown(ScrnInfoPtr pScrn) pNv->reg[0x00610200/4] = 0; pNv->reg[0x00610300/4] = 0; while((pNv->reg[0x00610200/4] & 0x1e0000) != 0); + while((pNv->reg[0x61C030/4] & 0x10000000)); + while((pNv->reg[0x61C830/4] & 0x10000000)); } static Bool G80CrtcModeFixup(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_mode) { - // TODO: Fix up the mode here + G80CrtcPrivPtr pPriv = crtc->driver_private; + int interlaceDiv, fudge; + + if(pPriv->skipModeFixup) + return TRUE; + + /* Magic mode timing fudge factor */ + fudge = ((adjusted_mode->Flags & V_INTERLACE) && (adjusted_mode->Flags & V_DBLSCAN)) ? 2 : 1; + interlaceDiv = (adjusted_mode->Flags & V_INTERLACE) ? 2 : 1; + + /* Stash the mode timings in the Crtc fields in adjusted_mode */ + adjusted_mode->CrtcHBlankStart = mode->CrtcVTotal << 16 | mode->CrtcHTotal; + adjusted_mode->CrtcHSyncEnd = ((mode->CrtcVSyncEnd - mode->CrtcVSyncStart) / interlaceDiv - 1) << 16 | + (mode->CrtcHSyncEnd - mode->CrtcHSyncStart - 1); + adjusted_mode->CrtcHBlankEnd = ((mode->CrtcVBlankEnd - mode->CrtcVSyncStart) / interlaceDiv - fudge) << 16 | + (mode->CrtcHBlankEnd - mode->CrtcHSyncStart - 1); + adjusted_mode->CrtcHTotal = ((mode->CrtcVTotal - mode->CrtcVSyncStart + mode->CrtcVBlankStart) / interlaceDiv - fudge) << 16 | + (mode->CrtcHTotal - mode->CrtcHSyncStart + mode->CrtcHBlankStart - 1); + adjusted_mode->CrtcHSkew = ((mode->CrtcVTotal + mode->CrtcVBlankEnd - mode->CrtcVSyncStart) / 2 - 2) << 16 | + ((2*mode->CrtcVTotal - mode->CrtcVSyncStart + mode->CrtcVBlankStart) / 2 - 2); + return TRUE; } @@ -324,36 +339,21 @@ G80CrtcModeSet(xf86CrtcPtr crtc, DisplayModePtr mode, { ScrnInfoPtr pScrn = crtc->scrn; G80CrtcPrivPtr pPriv = crtc->driver_private; - const int HDisplay = mode->HDisplay, VDisplay = mode->VDisplay; + const int HDisplay = adjusted_mode->HDisplay, VDisplay = adjusted_mode->VDisplay; const int headOff = 0x400 * G80CrtcGetHead(crtc); - int interlaceDiv, fudge; - // TODO: Use adjusted_mode and fix it up in G80CrtcModeFixup - pPriv->pclk = mode->Clock; - - /* Magic mode timing fudge factor */ - fudge = ((mode->Flags & V_INTERLACE) && (mode->Flags & V_DBLSCAN)) ? 2 : 1; - interlaceDiv = (mode->Flags & V_INTERLACE) ? 2 : 1; + pPriv->pclk = adjusted_mode->Clock; - C(0x00000804 + headOff, mode->Clock | 0x800000); - C(0x00000808 + headOff, (mode->Flags & V_INTERLACE) ? 2 : 0); + C(0x00000804 + headOff, adjusted_mode->Clock | 0x800000); + C(0x00000808 + headOff, (adjusted_mode->Flags & V_INTERLACE) ? 2 : 0); C(0x00000810 + headOff, 0); C(0x0000082C + headOff, 0); - C(0x00000814 + headOff, mode->CrtcVTotal << 16 | mode->CrtcHTotal); - C(0x00000818 + headOff, - ((mode->CrtcVSyncEnd - mode->CrtcVSyncStart) / interlaceDiv - 1) << 16 | - (mode->CrtcHSyncEnd - mode->CrtcHSyncStart - 1)); - C(0x0000081C + headOff, - ((mode->CrtcVBlankEnd - mode->CrtcVSyncStart) / interlaceDiv - fudge) << 16 | - (mode->CrtcHBlankEnd - mode->CrtcHSyncStart - 1)); - C(0x00000820 + headOff, - ((mode->CrtcVTotal - mode->CrtcVSyncStart + mode->CrtcVBlankStart) / interlaceDiv - fudge) << 16 | - (mode->CrtcHTotal - mode->CrtcHSyncStart + mode->CrtcHBlankStart - 1)); - if(mode->Flags & V_INTERLACE) { - C(0x00000824 + headOff, - ((mode->CrtcVTotal + mode->CrtcVBlankEnd - mode->CrtcVSyncStart) / 2 - 2) << 16 | - ((2*mode->CrtcVTotal - mode->CrtcVSyncStart + mode->CrtcVBlankStart) / 2 - 2)); - } + C(0x00000814 + headOff, adjusted_mode->CrtcHBlankStart); + C(0x00000818 + headOff, adjusted_mode->CrtcHSyncEnd); + C(0x0000081C + headOff, adjusted_mode->CrtcHBlankEnd); + C(0x00000820 + headOff, adjusted_mode->CrtcHTotal); + if(adjusted_mode->Flags & V_INTERLACE) + C(0x00000824 + headOff, adjusted_mode->CrtcHSkew); C(0x00000868 + headOff, pScrn->virtualY << 16 | pScrn->virtualX); C(0x0000086C + headOff, pScrn->displayWidth * (pScrn->bitsPerPixel / 8) | 0x100000); switch(pScrn->depth) { @@ -362,9 +362,8 @@ G80CrtcModeSet(xf86CrtcPtr crtc, DisplayModePtr mode, case 16: C(0x00000870 + headOff, 0xE800); break; case 24: C(0x00000870 + headOff, 0xCF00); break; } - C(0x000008A0 + headOff, 0); - if((mode->Flags & V_DBLSCAN) || (mode->Flags & V_INTERLACE) || - mode->CrtcHDisplay != HDisplay || mode->CrtcVDisplay != VDisplay) { + if((adjusted_mode->Flags & V_DBLSCAN) || (adjusted_mode->Flags & V_INTERLACE) || + adjusted_mode->CrtcHDisplay != HDisplay || adjusted_mode->CrtcVDisplay != VDisplay) { C(0x000008A4 + headOff, 9); } else { C(0x000008A4 + headOff, 0); @@ -373,8 +372,8 @@ G80CrtcModeSet(xf86CrtcPtr crtc, DisplayModePtr mode, C(0x000008C0 + headOff, y << 16 | x); C(0x000008C8 + headOff, VDisplay << 16 | HDisplay); C(0x000008D4 + headOff, 0); - C(0x000008D8 + headOff, mode->CrtcVDisplay << 16 | mode->CrtcHDisplay); - C(0x000008DC + headOff, mode->CrtcVDisplay << 16 | mode->CrtcHDisplay); + C(0x000008D8 + headOff, adjusted_mode->CrtcVDisplay << 16 | adjusted_mode->CrtcHDisplay); + C(0x000008DC + headOff, adjusted_mode->CrtcVDisplay << 16 | adjusted_mode->CrtcHDisplay); G80CrtcBlankScreen(crtc, FALSE); } @@ -458,6 +457,7 @@ static void G80CrtcPrepare(xf86CrtcPtr crtc) { ScrnInfoPtr pScrn = crtc->scrn; + G80CrtcPrivPtr pPriv = crtc->driver_private; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int i; @@ -467,6 +467,15 @@ G80CrtcPrepare(xf86CrtcPtr crtc) if(!output->crtc) output->funcs->mode_set(output, NULL, NULL); } + + pPriv->skipModeFixup = FALSE; +} + +void +G80CrtcSkipModeFixup(xf86CrtcPtr crtc) +{ + G80CrtcPrivPtr pPriv = crtc->driver_private; + pPriv->skipModeFixup = TRUE; } static void diff --git a/src/g80_display.h b/src/g80_display.h index fac7877..d6f24f4 100644 --- a/src/g80_display.h +++ b/src/g80_display.h @@ -11,5 +11,6 @@ void G80CrtcBlankScreen(xf86CrtcPtr, Bool blank); void G80CrtcEnableCursor(xf86CrtcPtr, Bool update); void G80CrtcDisableCursor(xf86CrtcPtr, Bool update); void G80CrtcSetCursorPosition(xf86CrtcPtr, int x, int y); +void G80CrtcSkipModeFixup(xf86CrtcPtr); void G80DispCreateCrtcs(ScrnInfoPtr pScrn); diff --git a/src/g80_sor.c b/src/g80_sor.c index 90119f0..ea7e015 100644 --- a/src/g80_sor.c +++ b/src/g80_sor.c @@ -129,13 +129,20 @@ static const xf86OutputFuncsRec G80SorOutputFuncs = { xf86OutputPtr G80CreateSor(ScrnInfoPtr pScrn, ORNum or) { + G80Ptr pNv = G80PTR(pScrn); G80OutputPrivPtr pPriv = xnfcalloc(sizeof(*pPriv), 1); + const int off = 0x800 * or; xf86OutputPtr output; char orName[5]; if(!pPriv) return FALSE; + pNv->reg[(0x61C00C+off)/4] = 0x03010700; + pNv->reg[(0x61C010+off)/4] = 0x0000152f; + pNv->reg[(0x61C014+off)/4] = 0x00000000; + pNv->reg[(0x61C018+off)/4] = 0x00245af8; + snprintf(orName, 5, "DVI%i", or); output = xf86OutputCreate(pScrn, &G80SorOutputFuncs, orName); commit 1f4790adcafd402c84a4a761c870a26a5178a4ff Author: Benjamin Herrenschmidt <[EMAIL PROTECTED]> Date: Sun Jun 3 11:16:55 2007 +1000 Fix build. Including xf86DDC.h before we include xf86.h doesn't fly and it's not necessary anyway as it's pulled in by g80_type.h Signed-off-by: Benjamin Herrenschmidt <[EMAIL PROTECTED]> diff --git a/src/g80_output.c b/src/g80_output.c index 354d39a..d68250f 100644 --- a/src/g80_output.c +++ b/src/g80_output.c @@ -27,7 +27,6 @@ #endif #include <strings.h> -#include <xf86DDC.h> #include "g80_type.h" #include "g80_output.h" commit 9b8470e9c81e6ce2c8cd69942fb2ffd2d4c06102 Author: Aaron Plattner <[EMAIL PROTECTED]> Date: Wed May 16 14:45:36 2007 -0700 Bump to 2.0.96. diff --git a/configure.ac b/configure.ac index 3adb00b..66a1efb 100644 --- a/configure.ac +++ b/configure.ac @@ -22,7 +22,7 @@ AC_PREREQ(2.57) AC_INIT([xf86-video-nv], - 2.0.95, + 2.0.96, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xf86-video-nv) commit 51c6425bea6e4ef02f7b76e58e759f99b0e993e8 Author: Aaron Plattner <[EMAIL PROTECTED]> Date: Thu May 10 17:09:36 2007 -0700 Add rudimentary VBE-based dual head support for pre-G80. diff --git a/man/nv.man b/man/nv.man index 9f5917f..e9bcec9 100644 --- a/man/nv.man +++ b/man/nv.man @@ -93,6 +93,11 @@ the wrong one, this option may be used to force usage of a particular output. The options are "0" or "1". Default: autodetected. .TP +.BI "Option \*qDualhead\*q \*q" boolean \*q +Enables simple VBE-based dual head mode. +This sets the same resolution on both outputs and lays them out side-by-side. +The screens will be panned together as one big metamode if the virtual desktop is larger than both screens combined. +.TP .BI "Option \*qFlatPanel\*q \*q" boolean \*q The driver usually can autodetect the presence of a digital flat panel. In the case that this fails, this option can be used to force the driver to diff --git a/src/nv_driver.c b/src/nv_driver.c index a20bf64..4c2a395 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -34,6 +34,7 @@ #include "nv_include.h" #include "xf86int10.h" +#include "vbeModes.h" const OptionInfoRec * RivaAvailableOptions(int chipid, int busid); Bool RivaGetScrnInfoRec(PciChipsets *chips, int chip); @@ -70,8 +71,10 @@ 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); /* @@ -410,6 +413,17 @@ static const char *vbeSymbols[] = { "vbeDoEDID", NULL }; + +static const char *vbeModeSymbols[] = { + "VBEExtendedInit", + "VBEGetVBEInfo", + "VBEGetModePool", + "VBEValidateModes", + "VBESetModeParameters", + "VBEGetVBEMode", + "VBESetVBEMode", + NULL +}; #endif static const char *i2cSymbols[] = { @@ -488,7 +502,8 @@ typedef enum { OPTION_FP_DITHER, OPTION_CRTC_NUMBER, OPTION_FP_SCALE, - OPTION_FP_TWEAK + OPTION_FP_TWEAK, + OPTION_DUALHEAD, } NVOpts; @@ -505,6 +520,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 } }; @@ -821,6 +837,27 @@ NVSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) 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; +} + /* * This function is used to initialize the Start Address - the first * displayed location in the video memory. @@ -869,6 +906,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. @@ -888,7 +936,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 ( @@ -930,9 +985,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); @@ -956,6 +1017,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 */ @@ -1404,7 +1475,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)) { @@ -1622,14 +1729,31 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) * 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, -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]