diff options
author | root <root@treble.(none)> | 2007-03-11 00:38:11 -0800 |
---|---|---|
committer | root <root@treble.(none)> | 2007-03-11 00:43:11 -0800 |
commit | 7e0e5c1fb38922add99db33f282baf2ee1531685 (patch) | |
tree | 1688eda2548ade19ab19fc5e56cb5c25cb9c2447 | |
parent | 636adcd57f1c5b33edf2d8fbf9e7fa9aac1ccb1a (diff) |
Initial RandR 1.2 support for G80.
Mostly just rearranging code.
-rw-r--r-- | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/g80_dac.c | 156 | ||||
-rw-r--r-- | src/g80_display.c | 357 | ||||
-rw-r--r-- | src/g80_display.h | 22 | ||||
-rw-r--r-- | src/g80_driver.c | 140 | ||||
-rw-r--r-- | src/g80_output.c (renamed from src/g80_ddc.c) | 157 | ||||
-rw-r--r-- | src/g80_output.h | 24 | ||||
-rw-r--r-- | src/g80_sor.c | 140 | ||||
-rw-r--r-- | src/g80_type.h | 14 |
9 files changed, 739 insertions, 277 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index b7c1128..d024283 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -70,13 +70,15 @@ if SUPPORT_G80 g80_sources = \ g80_cursor.c \ g80_cursor.h \ - g80_ddc.c \ - g80_ddc.h \ + g80_dac.c \ g80_display.c \ g80_display.h \ g80_dma.c \ g80_dma.h \ g80_driver.c \ + g80_output.c \ + g80_output.h \ + g80_sor.c \ g80_type.h \ g80_xaa.c \ g80_xaa.h diff --git a/src/g80_dac.c b/src/g80_dac.c new file mode 100644 index 0000000..991e3be --- /dev/null +++ b/src/g80_dac.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2007 NVIDIA, Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <unistd.h> + +#include "g80_type.h" +#include "g80_display.h" +#include "g80_output.h" + +static void +G80DacSetPClk(xf86OutputPtr output, int pclk) +{ + G80Ptr pNv = G80PTR(output->scrn); + G80OutputPrivPtr pPriv = output->driver_private; + const int orOff = 0x800 * pPriv->or; + + pNv->reg[(0x00614280+orOff)/4] = 0; +} + +static void +G80DacDPMSSet(xf86OutputPtr output, int mode) +{ + ErrorF("DAC dpms unimplemented\n"); +} + +static void +G80DacModeSet(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + ScrnInfoPtr pScrn = output->scrn; + G80OutputPrivPtr pPriv = output->driver_private; + const int dacOff = 0x80 * pPriv->or; + + if(adjusted_mode) + ErrorF("DAC%i mode %s -> HEAD%i\n", pPriv->or, adjusted_mode->name, G80CrtcGetHead(output->crtc)); + + if(!adjusted_mode) { + C(0x00000400 + dacOff, 0); + return; + } + + C(0x00000400 + dacOff, + (G80CrtcGetHead(output->crtc) == HEAD0 ? 1 : 2) | 0x40); + C(0x00000404 + dacOff, + (adjusted_mode->Flags & V_NHSYNC) ? 1 : 0 | + (adjusted_mode->Flags & V_NVSYNC) ? 2 : 0); +} + +/* + * Perform DAC load detection to determine if there is a connected display. + */ +static xf86OutputStatus +G80DacDetect(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + G80Ptr pNv = G80PTR(pScrn); + G80OutputPrivPtr pPriv = output->driver_private; + const int scrnIndex = pScrn->scrnIndex; + const int dacOff = 2048 * pPriv->or; + CARD32 load, tmp; + + xf86DrvMsg(scrnIndex, X_PROBED, "Trying load detection on VGA%i ... ", + pPriv->or); + + pNv->reg[(0x0061A010+dacOff)/4] = 0x00000001; + pNv->reg[(0x0061A004+dacOff)/4] = 0x80150000; + while(pNv->reg[(0x0061A004+dacOff)/4] & 0x80000000); + tmp = pNv->architecture == 0x50 ? 420 : 340; + pNv->reg[(0x0061A00C+dacOff)/4] = tmp | 0x100000; + usleep(4500); + load = pNv->reg[(0x0061A00C+dacOff)/4]; + pNv->reg[(0x0061A00C+dacOff)/4] = 0; + pNv->reg[(0x0061A004+dacOff)/4] = 0x80550000; + + // Use this DAC if all three channels show load. + if((load & 0x38000000) == 0x38000000) { + xf86ErrorF("found one!\n"); + return XF86OutputStatusConnected; + } + + xf86ErrorF("nothing.\n"); + return XF86OutputStatusDisconnected; +} + +static void +G80DacDestroy(xf86OutputPtr output) +{ + G80OutputDestroy(output); + + xfree(output->driver_private); + output->driver_private = NULL; +} + +static const xf86OutputFuncsRec G80DacOutputFuncs = { + .dpms = G80DacDPMSSet, + .save = NULL, + .restore = NULL, + .mode_valid = G80OutputModeValid, + .mode_fixup = G80OutputModeFixup, + .prepare = G80OutputPrepare, + .commit = G80OutputCommit, + .mode_set = G80DacModeSet, + .detect = G80DacDetect, + .get_modes = G80OutputGetDDCModes, + .destroy = G80DacDestroy, +}; + +xf86OutputPtr +G80CreateDac(ScrnInfoPtr pScrn, ORNum or, int i2cPort) +{ + G80OutputPrivPtr pPriv = xnfcalloc(sizeof(*pPriv), 1); + xf86OutputPtr output; + char orName[5]; + + if(!pPriv) + return FALSE; + + snprintf(orName, 5, "VGA%i", or); + output = xf86OutputCreate(pScrn, &G80DacOutputFuncs, orName); + + pPriv->type = DAC; + pPriv->or = or; + pPriv->set_pclk = G80DacSetPClk; + output->driver_private = pPriv; + output->interlaceAllowed = TRUE; + output->doubleScanAllowed = TRUE; + + /* Create an I2C object */ + G80I2CInit(output, i2cPort); + + return output; +} diff --git a/src/g80_display.c b/src/g80_display.c index 95c3d34..b9882da 100644 --- a/src/g80_display.c +++ b/src/g80_display.c @@ -33,10 +33,16 @@ #include "g80_type.h" #include "g80_display.h" +#include "g80_output.h" #define DPMS_SERVER #include <X11/extensions/dpms.h> +typedef struct G80CrtcPrivRec { + Head head; + int pclk; /* Target pixel clock in kHz */ +} G80CrtcPrivRec, *G80CrtcPrivPtr; + /* * PLL calculation. pclk is in kHz. */ @@ -137,8 +143,42 @@ G80CalcPLL(float pclk, int *pNA, int *pMA, int *pNB, int *pMB, int *pP) } static void -G80DispCommand(G80Ptr pNv, CARD32 addr, CARD32 data) +G80CrtcSetPClk(xf86CrtcPtr crtc) { + G80Ptr pNv = G80PTR(crtc->scrn); + G80CrtcPrivPtr pPriv = crtc->driver_private; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); + const int headOff = 0x800 * pPriv->head; + int lo_n, lo_m, hi_n, hi_m, p, i; + CARD32 lo = pNv->reg[(0x00614104+headOff)/4]; + CARD32 hi = pNv->reg[(0x00614108+headOff)/4]; + + pNv->reg[(0x00614100+headOff)/4] = 0x10000610; + lo &= 0xff00ff00; + hi &= 0x8000ff00; + + G80CalcPLL(pPriv->pclk, &lo_n, &lo_m, &hi_n, &hi_m, &p); + + lo |= (lo_m << 16) | lo_n; + hi |= (p << 28) | (hi_m << 16) | hi_n; + pNv->reg[(0x00614104+headOff)/4] = lo; + pNv->reg[(0x00614108+headOff)/4] = hi; + pNv->reg[(0x00614200+headOff)/4] = 0; + + for(i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + + if(output->crtc != crtc) + continue; + G80OutputSetPClk(output, pPriv->pclk); + } +} + +void +G80DispCommand(ScrnInfoPtr pScrn, CARD32 addr, CARD32 data) +{ + G80Ptr pNv = G80PTR(pScrn); + pNv->reg[0x00610304/4] = data; pNv->reg[0x00610300/4] = addr | 0x80010001; @@ -147,35 +187,17 @@ G80DispCommand(G80Ptr pNv, CARD32 addr, CARD32 data) if(super) { if(super == 2) { - const int headOff = 0x800 * pNv->head; - const int orOff = 0x800 * pNv->or; - - if(pNv->reg[0x00610030/4] & 0x600) { - int lo_n, lo_m, hi_n, hi_m, p; - CARD32 lo = pNv->reg[(0x00614104+headOff)/4]; - CARD32 hi = pNv->reg[(0x00614108+headOff)/4]; - - pNv->reg[(0x00614100+headOff)/4] = 0x10000610; - lo &= 0xff00ff00; - hi &= 0x8000ff00; - - G80CalcPLL(pNv->pclk, &lo_n, &lo_m, &hi_n, &hi_m, &p); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + const CARD32 r = pNv->reg[0x00610030/4]; + int i; - lo |= (lo_m << 16) | lo_n; - hi |= (p << 28) | (hi_m << 16) | hi_n; - pNv->reg[(0x00614104+headOff)/4] = lo; - pNv->reg[(0x00614108+headOff)/4] = hi; - } + for(i = 0; i < xf86_config->num_crtc; i++) + { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + G80CrtcPrivPtr pPriv = crtc->driver_private; - pNv->reg[(0x00614200+headOff)/4] = 0; - switch(pNv->orType) { - case DAC: - pNv->reg[(0x00614280+orOff)/4] = 0; - break; - case SOR: - pNv->reg[(0x00614300+orOff)/4] = - (pNv->pclk > 165000) ? 0x101 : 0; - break; + if(r & (0x200 << pPriv->head)) + G80CrtcSetPClk(crtc); } } @@ -184,59 +206,16 @@ G80DispCommand(G80Ptr pNv, CARD32 addr, CARD32 data) } } } -#define C(mthd, data) G80DispCommand(pNv, (mthd), (data)) -/* - * Performs load detection on a single DAC. - */ -Bool G80DispDetectLoad(ScrnInfoPtr pScrn, ORNum or) +Head +G80CrtcGetHead(xf86CrtcPtr crtc) { - G80Ptr pNv = G80PTR(pScrn); - const int dacOff = 2048 * or; - CARD32 load, tmp; - - pNv->reg[(0x0061A010+dacOff)/4] = 0x00000001; - pNv->reg[(0x0061A004+dacOff)/4] = 0x80150000; - while(pNv->reg[(0x0061A004+dacOff)/4] & 0x80000000); - tmp = pNv->architecture == 0x50 ? 420 : 340; - pNv->reg[(0x0061A00C+dacOff)/4] = tmp | 0x100000; - usleep(4500); - load = pNv->reg[(0x0061A00C+dacOff)/4]; - pNv->reg[(0x0061A00C+dacOff)/4] = 0; - pNv->reg[(0x0061A004+dacOff)/4] = 0x80550000; - - return (load & 0x38000000) == 0x38000000; -} - -/* - * Performs load detection on the DACs. Sets pNv->orType and pNv->or - * accordingly. - */ -Bool G80LoadDetect(ScrnInfoPtr pScrn) -{ - G80Ptr pNv = G80PTR(pScrn); - const int scrnIndex = pScrn->scrnIndex; - ORNum or; - - pNv->orType = DAC; - - for(or = DAC0; or <= DAC2; or++) { - xf86DrvMsg(scrnIndex, X_PROBED, "Trying load detection on DAC%i ... ", or); - - if(G80DispDetectLoad(pScrn, or)) { - xf86ErrorF("found one!\n"); - pNv->or = or; - return TRUE; - } - - xf86ErrorF("nothing.\n"); - } - - return FALSE; + G80CrtcPrivPtr pPriv = crtc->driver_private; + return pPriv->head; } Bool -G80DispInit(ScrnInfoPtr pScrn) +G80DispPreInit(ScrnInfoPtr pScrn) { G80Ptr pNv = G80PTR(pScrn); @@ -269,6 +248,14 @@ G80DispInit(ScrnInfoPtr pScrn) pNv->reg[0x0061B004/4] = 0x80550000; pNv->reg[0x0061B010/4] = 0x00000001; + return TRUE; +} + +Bool +G80DispInit(ScrnInfoPtr pScrn) +{ + G80Ptr pNv = G80PTR(pScrn); + if(pNv->reg[0x00610024/4] & 0x100) { pNv->reg[0x00610024/4] = 0x100; pNv->reg[0x006194E8/4] &= ~1; @@ -295,65 +282,60 @@ void G80DispShutdown(ScrnInfoPtr pScrn) { G80Ptr pNv = G80PTR(pScrn); - CARD32 mask; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; - G80DispBlankScreen(pScrn, TRUE); + for(i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + + G80CrtcBlankScreen(crtc, TRUE); + } + + C(0x00000080, 0); + + for(i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + + if(crtc->enabled) { + const CARD32 mask = 4 << G80CrtcGetHead(crtc); + + pNv->reg[0x00610024/4] = mask; + while(!(pNv->reg[0x00610024/4] & mask)); + } + } - mask = 4 << pNv->head; - pNv->reg[0x00610024/4] = mask; - while(!(pNv->reg[0x00610024/4] & mask)); pNv->reg[0x00610200/4] = 0; pNv->reg[0x00610300/4] = 0; while((pNv->reg[0x00610200/4] & 0x1e0000) != 0); } -static void -setupDAC(G80Ptr pNv, Head head, ORNum or, DisplayModePtr mode) +static Bool +G80CrtcModeFixup(xf86CrtcPtr crtc, + DisplayModePtr mode, DisplayModePtr adjusted_mode) { - const int dacOff = 0x80 * pNv->or; - - C(0x00000400 + dacOff, (head == HEAD0 ? 1 : 2) | 0x40); - C(0x00000404 + dacOff, - (mode->Flags & V_NHSYNC) ? 1 : 0 | - (mode->Flags & V_NVSYNC) ? 2 : 0); + // TODO: Fix up the mode here + return TRUE; } static void -setupSOR(G80Ptr pNv, Head head, ORNum or, DisplayModePtr mode) -{ - const int sorOff = 0x40 * pNv->or; - - C(0x00000600 + sorOff, - (head == HEAD0 ? 1 : 2) | - (mode->SynthClock > 165000 ? 0x500 : 0x100) | - ((mode->Flags & V_NHSYNC) ? 0x1000 : 0) | - ((mode->Flags & V_NVSYNC) ? 0x2000 : 0)); -} - -Bool -G80DispSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode) +G80CrtcModeSet(xf86CrtcPtr crtc, DisplayModePtr mode, + DisplayModePtr adjusted_mode, int x, int y) { + ScrnInfoPtr pScrn = crtc->scrn; G80Ptr pNv = G80PTR(pScrn); + G80CrtcPrivPtr pPriv = crtc->driver_private; const int HDisplay = mode->HDisplay, VDisplay = mode->VDisplay; - const int headOff = 0x400 * pNv->head; + const int headOff = 0x400 * G80CrtcGetHead(crtc); int interlaceDiv, fudge; - pNv->pclk = mode->SynthClock; + // 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; - switch(pNv->orType) { - case DAC: - setupDAC(pNv, pNv->head, pNv->or, mode); - break; - case SOR: - setupSOR(pNv, pNv->head, pNv->or, mode); - break; - } - - C(0x00000804 + headOff, mode->SynthClock | 0x800000); + C(0x00000804 + headOff, mode->Clock | 0x800000); C(0x00000808 + headOff, (mode->Flags & V_INTERLACE) ? 2 : 0); C(0x00000810 + headOff, 0); C(0x0000082C + headOff, 0); @@ -388,41 +370,24 @@ G80DispSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode) C(0x000008A4 + headOff, 0); } C(0x000008A8 + headOff, 0x40000); - /* Use the screen's panning, but not if it's bogus */ - if(pScrn->frameX0 >= 0 && pScrn->frameY0 >= 0 && - pScrn->frameX0 + HDisplay <= pScrn->virtualX && - pScrn->frameY0 + VDisplay <= pScrn->virtualY) { - C(0x000008C0 + headOff, pScrn->frameY0 << 16 | pScrn->frameX0); - } else { - C(0x000008C0 + headOff, 0); - } + 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); - G80DispBlankScreen(pScrn, FALSE); - - return TRUE; + G80CrtcBlankScreen(crtc, FALSE); } void -G80DispAdjustFrame(G80Ptr pNv, int x, int y) -{ - const int headOff = 0x400 * pNv->head; - - C(0x000008C0 + headOff, y << 16 | x); - C(0x00000080, 0); -} - -void -G80DispBlankScreen(ScrnInfoPtr pScrn, Bool blank) +G80CrtcBlankScreen(xf86CrtcPtr crtc, Bool blank) { + ScrnInfoPtr pScrn = crtc->scrn; G80Ptr pNv = G80PTR(pScrn); - const int headOff = 0x400 * pNv->head; + const int headOff = 0x400 * G80CrtcGetHead(crtc); if(blank) { - G80DispHideCursor(pNv, FALSE); + // G80DispHideCursor(pNv, FALSE); C(0x00000840 + headOff, 0); C(0x00000844 + headOff, 0); @@ -441,21 +406,21 @@ G80DispBlankScreen(ScrnInfoPtr pScrn, Bool blank) C(0x00000884 + headOff, (pNv->videoRam << 2) - 0x40); if(pNv->architecture != 0x50) C(0x0000089C + headOff, 1); - if(pNv->cursorVisible) - G80DispShowCursor(pNv, FALSE); + // if(pNv->cursorVisible) + // G80DispShowCursor(pNv, FALSE); C(0x00000840 + headOff, pScrn->depth == 8 ? 0x80000000 : 0xc0000000); C(0x00000844 + headOff, (pNv->videoRam * 1024 - 0x5000) >> 8); if(pNv->architecture != 0x50) C(0x0000085C + headOff, 1); C(0x00000874 + headOff, 1); } - - C(0x00000080, 0); } void -G80DispDPMSSet(ScrnInfoPtr pScrn, int mode, int flags) +G80CrtcDPMSSet(xf86CrtcPtr crtc, int mode) { + ErrorF("CRTC dpms unimplemented\n"); +#if 0 G80Ptr pNv = G80PTR(pScrn); const int off = 0x800 * pNv->or; CARD32 tmp; @@ -502,21 +467,121 @@ G80DispDPMSSet(ScrnInfoPtr pScrn, int mode, int flags) break; } +#endif } /******************************** Cursor stuff ********************************/ -void G80DispShowCursor(G80Ptr pNv, Bool update) +void G80CrtcShowCursor(xf86CrtcPtr crtc, Bool update) { - const int headOff = 0x400 * pNv->head; + ScrnInfoPtr pScrn = crtc->scrn; + const int headOff = 0x400 * G80CrtcGetHead(crtc); C(0x00000880 + headOff, 0x85000000); if(update) C(0x00000080, 0); } -void G80DispHideCursor(G80Ptr pNv, Bool update) +void G80CrtcHideCursor(xf86CrtcPtr crtc, Bool update) { - const int headOff = 0x400 * pNv->head; + ScrnInfoPtr pScrn = crtc->scrn; + const int headOff = 0x400 * G80CrtcGetHead(crtc); C(0x00000880 + headOff, 0x5000000); if(update) C(0x00000080, 0); } + +void G80CrtcSetCursorPosition(xf86CrtcPtr crtc, int x, int y) +{ + G80Ptr pNv = G80PTR(crtc->scrn); + const int headOff = 0x647000 + 0x1000*G80CrtcGetHead(crtc); + + x &= 0xffff; + y &= 0xffff; + pNv->reg[(0x84 + headOff)/4] = y << 16 | x; + pNv->reg[(0x80 + headOff)/4] = 0; +} + +/******************************** CRTC stuff ********************************/ + +static Bool +G80CrtcLock(xf86CrtcPtr crtc) +{ + return FALSE; +} + +static void +G80CrtcPrepare(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + + ErrorF("Outputs:\n"); + for(i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + + if(output->crtc) { + G80CrtcPrivPtr pPriv = output->crtc->driver_private; + ErrorF("\t%s -> HEAD%i\n", output->name, pPriv->head); + } else { + ErrorF("\t%s disconnected\n", output->name); + output->funcs->mode_set(output, NULL, NULL); + } + } +} + +static void +G80CrtcCommit(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); + int i, crtc_mask = 0; + + /* If any heads are unused, blank them */ + for(i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + + if(output->crtc) + /* XXXagp: This assumes that xf86_config->crtc[i] is HEADi */ + crtc_mask |= 1 << G80CrtcGetHead(output->crtc); + } + + for(i = 0; i < xf86_config->num_crtc; i++) + if(!((1 << i) & crtc_mask)) + G80CrtcBlankScreen(xf86_config->crtc[i], TRUE); + + C(0x00000080, 0); +} + +static const xf86CrtcFuncsRec g80_crtc_funcs = { + .dpms = G80CrtcDPMSSet, + .save = NULL, + .restore = NULL, + .lock = G80CrtcLock, + .unlock = NULL, + .mode_fixup = G80CrtcModeFixup, + .prepare = G80CrtcPrepare, + .mode_set = G80CrtcModeSet, + // .gamma_set = G80DispGammaSet, + .commit = G80CrtcCommit, + .shadow_create = NULL, + .shadow_destroy = NULL, + .destroy = NULL, +}; + +void +G80DispCreateCrtcs(ScrnInfoPtr pScrn) +{ + Head head; + xf86CrtcPtr crtc; + G80CrtcPrivPtr g80_crtc; + + /* Create a "crtc" object for each head */ + for(head = HEAD0; head <= HEAD1; head++) { + crtc = xf86CrtcCreate(pScrn, &g80_crtc_funcs); + if(!crtc) return; + + g80_crtc = xnfcalloc(sizeof(*g80_crtc), 1); + g80_crtc->head = head; + crtc->driver_private = g80_crtc; + } +} diff --git a/src/g80_display.h b/src/g80_display.h index cbe312f..99436be 100644 --- a/src/g80_display.h +++ b/src/g80_display.h @@ -1,10 +1,16 @@ -Bool G80LoadDetect(ScrnInfoPtr); -Bool G80DispLoadDetect(ScrnInfoPtr, ORNum or); +Bool G80DispPreInit(ScrnInfoPtr); Bool G80DispInit(ScrnInfoPtr); -Bool G80DispSetMode(ScrnInfoPtr, DisplayModePtr); void G80DispShutdown(ScrnInfoPtr); -void G80DispAdjustFrame(G80Ptr pNv, int x, int y); -void G80DispBlankScreen(ScrnInfoPtr, Bool blank); -void G80DispDPMSSet(ScrnInfoPtr, int mode, int flags); -void G80DispShowCursor(G80Ptr, Bool update); -void G80DispHideCursor(G80Ptr, Bool update); + +void G80DispCommand(ScrnInfoPtr, CARD32 addr, CARD32 data); +#define C(mthd, data) G80DispCommand(pScrn, (mthd), (data)) + +Head G80CrtcGetHead(xf86CrtcPtr); + +void G80CrtcBlankScreen(xf86CrtcPtr, Bool blank); +void G80CrtcEnableCursor(xf86CrtcPtr, Bool update); +void G80CrtcDisableCursor(xf86CrtcPtr, Bool update); +void G80CrtcSetCursorPosition(xf86CrtcPtr, int x, int y); +void G80CrtcSetDither(xf86CrtcPtr, CARD32 mask, CARD32 val); + +void G80DispCreateCrtcs(ScrnInfoPtr pScrn); diff --git a/src/g80_driver.c b/src/g80_driver.c index 4bef070..6d19cce 100644 --- a/src/g80_driver.c +++ b/src/g80_driver.c @@ -119,6 +119,39 @@ G80FreeRec(ScrnInfoPtr pScrn) pScrn->driverPrivate = NULL; } +G80ResizeScreen(ScrnInfoPtr pScrn, int width, int height) +{ + G80Ptr pNv = G80PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int pitch = width * (pScrn->bitsPerPixel / 8); + int i; + + pitch = (pitch + 255) & ~255; + + ErrorF("Resizing screen to %ix%i\n", width, height); + pScrn->virtualX = width; + pScrn->virtualY = height; + + /* Can resize if XAA is disabled */ + if(!pNv->xaa) { + (*pScrn->pScreen->GetScreenPixmap)(pScrn->pScreen)->devKind = pitch; + pScrn->displayWidth = pitch / (pScrn->bitsPerPixel / 8); + + /* Re-set the modes so the new pitch is taken into account */ + for(i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + if(crtc->enabled) + xf86CrtcSetMode(crtc, &crtc->mode, crtc->rotation, crtc->x, crtc->y); + } + } + + return TRUE; +} + +static const xf86CrtcConfigFuncsRec randr12_screen_funcs = { + .resize = G80ResizeScreen, +}; + static Bool G80PreInit(ScrnInfoPtr pScrn, int flags) { @@ -126,10 +159,8 @@ G80PreInit(ScrnInfoPtr pScrn, int flags) EntityInfoPtr pEnt; pciVideoPtr pPci; PCITAG pcitag; - ClockRangePtr clockRanges; MessageType from; Bool primary; - int i; char *s; const rgb zeros = {0, 0, 0}; const Gamma gzeros = {0.0, 0.0, 0.0}; @@ -248,18 +279,6 @@ G80PreInit(ScrnInfoPtr pScrn, int flags) if(!xf86SetGamma(pScrn, gzeros)) goto fail; - /* - * Setup the ClockRanges, which describe what clock ranges are available, - * and what sort of modes they can be used for. - */ - clockRanges = xnfcalloc(sizeof(ClockRange), 1); - clockRanges->next = NULL; - clockRanges->minClock = 0; - clockRanges->maxClock = 400000; - clockRanges->clockIndex = -1; /* programmable */ - clockRanges->doubleScanAllowed = TRUE; - clockRanges->interlaceAllowed = TRUE; - /* Map memory */ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "MMIO registers at 0x%lx\n", pPci->memBase[0]); @@ -308,33 +327,35 @@ G80PreInit(ScrnInfoPtr pScrn, int flags) else pNv->table1 -= 0x10000; - /* Probe DDC */ - /* If no DDC info found, try DAC load detection */ + xf86CrtcConfigInit(pScrn, &randr12_screen_funcs); + xf86CrtcSetSizeRange(pScrn, 320, 200, 8192, 8192); + if(!xf86LoadSubModule(pScrn, "i2c")) goto fail; if(!xf86LoadSubModule(pScrn, "ddc")) goto fail; xf86LoaderReqSymLists(i2cSymbols, ddcSymbols, NULL); - if(!G80ProbeDDC(pScrn) && !G80LoadDetect(pScrn)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No display devices found\n"); + + if(!G80DispPreInit(pScrn)) goto fail; + /* Read the DDC routing table and create outputs */ + if(!G80CreateOutputs(pScrn)) goto fail; + /* Create the crtcs */ + G80DispCreateCrtcs(pScrn); + + /* We can grow the desktop if XAA is disabled */ + if(!xf86InitialConfiguration(pScrn, pNv->NoAccel)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No valid initial configuration found\n"); + goto fail; + } + pScrn->displayWidth = (pScrn->virtualX + 255) & ~255; + + if(!xf86RandR12PreInit(pScrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n"); goto fail; } - /* Hardcode HEAD0 for now. RandR 1.2 will move this into a Crtc struct. */ - pNv->head = 0; - - i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, - pScrn->display->modes, clockRanges, - NULL, 256, 8192, - 512, 128, 8192, - pScrn->display->virtualX, - pScrn->display->virtualY, - pNv->videoRam * 1024 - G80_RESERVED_VIDMEM, - LOOKUP_BEST_REFRESH); - if(i == -1) goto fail; - xf86PruneDriverModes(pScrn); - if(i == 0 || !pScrn->modes) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); + if(!pScrn->modes) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes\n"); goto fail; } - xf86SetCrtcForModes(pScrn, 0); pScrn->currentMode = pScrn->modes; xf86PrintModes(pScrn); @@ -381,10 +402,12 @@ AcquireDisplay(ScrnInfoPtr pScrn) #if 0 if(!G80CursorAcquire(pNv)) return FALSE; -#endif if(!G80DispSetMode(pScrn, pScrn->currentMode)) return FALSE; G80DispDPMSSet(pScrn, DPMSModeOn, 0); +#endif + ErrorF("TODO: Set the current config, rather than using xf86SetSingleMode\n"); + xf86SetSingleMode(pScrn, pScrn->currentMode, RR_Rotate_0); return TRUE; } @@ -443,6 +466,7 @@ G80CloseScreen(int scrnIndex, ScreenPtr pScreen) pScrn->vtSema = FALSE; pScreen->CloseScreen = pNv->CloseScreen; pScreen->BlockHandler = pNv->BlockHandler; + pScreen->CreateScreenResources = pNv->CreateScreenResources; return (*pScreen->CloseScreen)(scrnIndex, pScreen); } @@ -468,11 +492,26 @@ G80SaveScreen(ScreenPtr pScreen, int mode) if(!pScrn->vtSema) return FALSE; - G80DispBlankScreen(pScrn, !xf86IsUnblank(mode)); + ErrorF("SaveScreen unimplemented\n"); - return TRUE; + return FALSE; } +static Bool +G80CreateScreenResources(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + G80Ptr pNv = G80PTR(pScrn); + + pScreen->CreateScreenResources = pNv->CreateScreenResources; + if(!(*pScreen->CreateScreenResources)(pScreen)) + return FALSE; + + if(!xf86RandR12CreateScreenResources(pScreen)) + return FALSE; + return TRUE; + } + static void G80InitHW(ScrnInfoPtr pScrn) { @@ -710,8 +749,6 @@ G80ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) /* pad the screen pitch to 256 bytes */ pitch = pScrn->displayWidth * (pScrn->bitsPerPixel / 8); - pitch = (pitch + 0xff) & ~0xff; - pScrn->displayWidth = pitch / (pScrn->bitsPerPixel / 8); /* fb init */ if(!fbScreenInit(pScreen, pNv->mem, @@ -758,7 +795,7 @@ G80ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if(!G80XAAInit(pScreen)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Hardware acceleration initialization failed\n"); - pNv->NoAccel = FALSE; + return FALSE; } } @@ -789,7 +826,7 @@ G80ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) CMAP_PALETTED_TRUECOLOR)) return FALSE; - xf86DPMSInit(pScreen, G80DispDPMSSet, 0); + xf86DPMSInit(pScreen, xf86DPMSSet, 0); /* Clear the screen */ if(pNv->xaa) { @@ -809,12 +846,20 @@ G80ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pScreen->SaveScreen = G80SaveScreen; + pNv->CreateScreenResources = pScreen->CreateScreenResources; + pScreen->CreateScreenResources = G80CreateScreenResources; + pNv->CloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = G80CloseScreen; pNv->BlockHandler = pScreen->BlockHandler; pScreen->BlockHandler = G80BlockHandler; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RandR 1.2 enabled. Please ignore the following RandR disabled message.\n"); + xf86DisableRandR(); + xf86RandR12Init(pScreen); + xf86RandR12SetRotations(pScreen, RR_Rotate_0); + return TRUE; } @@ -828,22 +873,13 @@ static Bool G80SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - - return G80DispSetMode(pScrn, mode); + return xf86SetSingleMode(pScrn, mode, RR_Rotate_0); } static void G80AdjustFrame(int scrnIndex, int x, int y, int flags) { - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - G80Ptr pNv = G80PTR(pScrn); - - if(x + pScrn->currentMode->HDisplay > pScrn->virtualX || - y + pScrn->currentMode->VDisplay > pScrn->virtualY || - x < 0 || y < 0) - /* Ignore bogus panning */ - return; - G80DispAdjustFrame(pNv, x, y); + ErrorF("AdjustFrame unimplemented\n"); } static Bool diff --git a/src/g80_ddc.c b/src/g80_output.c index bcc4bff..481dd85 100644 --- a/src/g80_ddc.c +++ b/src/g80_output.c @@ -31,6 +31,7 @@ #include "g80_type.h" #include "g80_ddc.h" +#include "g80_output.h" static Bool G80ReadPortMapping(int scrnIndex, G80Ptr pNv) { @@ -110,7 +111,7 @@ fail: static void G80_I2CPutBits(I2CBusPtr b, int clock, int data) { G80Ptr pNv = G80PTR(xf86Screens[b->scrnIndex]); - const int off = b->DriverPrivate.val; + const int off = b->DriverPrivate.val * 0x18; pNv->reg[(0x0000E138+off)/4] = 4 | clock | data << 1; } @@ -118,7 +119,7 @@ static void G80_I2CPutBits(I2CBusPtr b, int clock, int data) static void G80_I2CGetBits(I2CBusPtr b, int *clock, int *data) { G80Ptr pNv = G80PTR(xf86Screens[b->scrnIndex]); - const int off = b->DriverPrivate.val; + const int off = b->DriverPrivate.val * 0x18; unsigned char val; val = pNv->reg[(0x0000E138+off)/4]; @@ -126,19 +127,18 @@ static void G80_I2CGetBits(I2CBusPtr b, int *clock, int *data) *data = !!(val & 2); } -static xf86MonPtr G80ProbeDDCBus(ScrnInfoPtr pScrn, int bus) +Bool +G80I2CInit(xf86OutputPtr output, const int port) { - G80Ptr pNv = G80PTR(pScrn); + G80OutputPrivPtr pPriv = output->driver_private; I2CBusPtr i2c; - xf86MonPtr monInfo = NULL; - const int off = bus * 0x18; /* Allocate the I2C bus structure */ i2c = xf86CreateI2CBusRec(); - if(!i2c) return NULL; + if(!i2c) return FALSE; - i2c->BusName = "DDC"; - i2c->scrnIndex = pScrn->scrnIndex; + i2c->BusName = output->name; + i2c->scrnIndex = output->scrn->scrnIndex; i2c->I2CPutBits = G80_I2CPutBits; i2c->I2CGetBits = G80_I2CGetBits; i2c->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */ @@ -146,17 +146,70 @@ static xf86MonPtr G80ProbeDDCBus(ScrnInfoPtr pScrn, int bus) i2c->BitTimeout = 40; i2c->ByteTimeout = 40; i2c->AcknTimeout = 40; - i2c->DriverPrivate.val = off; + i2c->DriverPrivate.val = port; + + if(xf86I2CBusInit(i2c)) { + pPriv->i2c = i2c; + return TRUE; + } else { + xfree(i2c); + return FALSE; + } +} - if(!xf86I2CBusInit(i2c)) goto done; +void +G80OutputSetPClk(xf86OutputPtr output, int pclk) +{ + G80OutputPrivPtr pPriv = output->driver_private; + pPriv->set_pclk(output, pclk); +} + +int +G80OutputModeValid(xf86OutputPtr output, DisplayModePtr mode) +{ + if(mode->Clock > 400000 || mode->Clock < 25000) + return MODE_CLOCK_RANGE; + + return MODE_OK; +} + +Bool +G80OutputModeFixup(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + return TRUE; +} + +void +G80OutputPrepare(xf86OutputPtr output) +{ +} + +void +G80OutputCommit(xf86OutputPtr output) +{ +} + +DisplayModePtr +G80OutputGetDDCModes(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + G80Ptr pNv = G80PTR(pScrn); + G80OutputPrivPtr pPriv = output->driver_private; + I2CBusPtr i2c = pPriv->i2c; + xf86MonPtr monInfo = NULL; + DisplayModePtr modes; + const int bus = i2c->DriverPrivate.val, off = bus * 0x18; - pNv->reg[(0x0000E138+off)/4] = 7; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Probing for EDID on I2C bus %i...\n", bus); - monInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, i2c); - + pNv->reg[(0x0000E138+off)/4] = 7; + monInfo = xf86OutputGetEDID(output, i2c); pNv->reg[(0x0000E138+off)/4] = 3; + xf86OutputSetEDID(output, monInfo); + modes = xf86OutputGetEDIDModes(output); + if(monInfo) { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DDC detected a %s:\n", monInfo->features.input_type ? @@ -166,64 +219,46 @@ static xf86MonPtr G80ProbeDDCBus(ScrnInfoPtr pScrn, int bus) xf86DrvMsg(pScrn->scrnIndex, X_INFO, " ... none found\n"); } -done: - xf86DestroyI2CBusRec(i2c, TRUE, TRUE); + return modes; +} + +void +G80OutputDestroy(xf86OutputPtr output) +{ + G80OutputPrivPtr pPriv = output->driver_private; - return monInfo; + xf86DestroyI2CBusRec(pPriv->i2c, TRUE, TRUE); + pPriv->i2c = NULL; } -/* - * Try DDC on each bus until we find one that works. - */ -Bool G80ProbeDDC(ScrnInfoPtr pScrn) +Bool +G80CreateOutputs(ScrnInfoPtr pScrn) { G80Ptr pNv = G80PTR(pScrn); - xf86MonPtr monInfo; - int port; - Bool flatPanel; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i, count = 0; if(!G80ReadPortMapping(pScrn->scrnIndex, pNv)) return FALSE; - for(port = 0; port < 4; port++) { - if(pNv->i2cMap[port].dac == -1 && pNv->i2cMap[port].sor == -1) - /* No outputs on this port. Skip it. */ - continue; - - monInfo = G80ProbeDDCBus(pScrn, port); - if(!monInfo) - /* No EDID on this port. */ - continue; - - flatPanel = (monInfo->features.input_type == 1); - - if(pNv->i2cMap[port].dac != -1 && - G80DispDetectLoad(pScrn, pNv->i2cMap[port].dac)) { - pNv->orType = DAC; - pNv->or = pNv->i2cMap[port].dac; - } else if(pNv->i2cMap[port].sor != -1) { - pNv->orType = SOR; - pNv->or = pNv->i2cMap[port].sor; - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Saw an EDID on I2C port %i but no DAC load was " - "detected and no SOR is connected to this port. Using " - "DAC%i.\n", port, - pNv->or); - pNv->orType = DAC; - pNv->or = pNv->i2cMap[port].dac; - } - - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, - "Found a %s on I2C port %i, assigning %s%i\n", - flatPanel ? "flat panel" : "CRT", - port, pNv->orType == SOR ? "SOR" : "DAC", pNv->or); + /* For each DDC port, create an output for the attached ORs */ + for(i = 0; i < 4; i++) { + if(pNv->i2cMap[i].dac != -1) + G80CreateDac(pScrn, pNv->i2cMap[i].dac, i); + if(pNv->i2cMap[i].sor != -1) + G80CreateSor(pScrn, pNv->i2cMap[i].sor, i); + } - pScrn->monitor->DDC = monInfo; - xf86SetDDCproperties(pScrn, monInfo); + /* For each output, set the crtc and clone masks */ + for(i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + G80OutputPrivPtr pPriv = output->driver_private; - return TRUE; + /* Any output can connect to any head */ + output->possible_crtcs = 0x3; + output->possible_clones = 0; } - return FALSE; + return TRUE; } + diff --git a/src/g80_output.h b/src/g80_output.h new file mode 100644 index 0000000..efc9a16 --- /dev/null +++ b/src/g80_output.h @@ -0,0 +1,24 @@ +typedef struct G80OutputPrivRec { + ORType type; + ORNum or; + + I2CBusPtr i2c; + + void (*set_pclk)(xf86OutputPtr, int pclk); +} G80OutputPrivRec, *G80OutputPrivPtr; + +Bool G80I2CInit(xf86OutputPtr, const int port); +void G80OutputSetPClk(xf86OutputPtr, int pclk); +int G80OutputModeValid(xf86OutputPtr, DisplayModePtr); +Bool G80OutputModeFixup(xf86OutputPtr, DisplayModePtr mode, DisplayModePtr adjusted_mode); +void G80OutputPrepare(xf86OutputPtr); +void G80OutputCommit(xf86OutputPtr); +DisplayModePtr G80OutputGetDDCModes(xf86OutputPtr); +void G80OutputDestroy(xf86OutputPtr); +Bool G80CreateOutputs(ScrnInfoPtr); + +/* g80_dac.c */ +xf86OutputPtr G80CreateDac(ScrnInfoPtr, ORNum, int i2cPort); + +/* g80_sor.c */ +xf86OutputPtr G80CreateSor(ScrnInfoPtr, ORNum, int i2cPort); diff --git a/src/g80_sor.c b/src/g80_sor.c new file mode 100644 index 0000000..7d377a8 --- /dev/null +++ b/src/g80_sor.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2007 NVIDIA, Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <X11/Xatom.h> + +#include "g80_type.h" +#include "g80_display.h" +#include "g80_output.h" + +static void +G80SorSetPClk(xf86OutputPtr output, int pclk) +{ + G80Ptr pNv = G80PTR(output->scrn); + G80OutputPrivPtr pPriv = output->driver_private; + const int orOff = 0x800 * pPriv->or; + + pNv->reg[(0x00614300+orOff)/4] = (pclk > 165000) ? 0x101 : 0; +} + +static void +G80SorDPMSSet(xf86OutputPtr output, int mode) +{ + ErrorF("SOR dpms unimplemented\n"); +} + +static void +G80SorModeSet(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + ScrnInfoPtr pScrn = output->scrn; + G80OutputPrivPtr pPriv = output->driver_private; + const int sorOff = 0x40 * pPriv->or; + + if(adjusted_mode) + ErrorF("SOR%i mode %s -> HEAD%i\n", pPriv->or, adjusted_mode->name, G80CrtcGetHead(output->crtc)); + + if(!adjusted_mode) { + /* Disconnect the SOR */ + C(0x00000600 + sorOff, 0); + return; + } + + C(0x00000600 + sorOff, + (G80CrtcGetHead(output->crtc) == HEAD0 ? 1 : 2) | + (mode->SynthClock > 165000 ? 0x500 : 0x100) | + ((mode->Flags & V_NHSYNC) ? 0x1000 : 0) | + ((mode->Flags & V_NVSYNC) ? 0x2000 : 0)); +} + +static xf86OutputStatus +G80SorDetect(xf86OutputPtr output) +{ + return XF86OutputStatusUnknown; + +#if 0 + DisplayModePtr modes = output->funcs->get_modes(output); + xf86OutputStatus status; + + if(modes) + status = XF86OutputStatusConnected; + else + status = XF86OutputStatusDisconnected; + xfree(modes); + + return status; +#endif +} + +static void +G80SorDestroy(xf86OutputPtr output) +{ + G80OutputDestroy(output); + + xfree(output->driver_private); + output->driver_private = NULL; +} + +static const xf86OutputFuncsRec G80SorOutputFuncs = { + .dpms = G80SorDPMSSet, + .save = NULL, + .restore = NULL, + .mode_valid = G80OutputModeValid, + .mode_fixup = G80OutputModeFixup, + .prepare = G80OutputPrepare, + .commit = G80OutputCommit, + .mode_set = G80SorModeSet, + .detect = G80SorDetect, + .get_modes = G80OutputGetDDCModes, + .destroy = G80SorDestroy, +}; + +xf86OutputPtr +G80CreateSor(ScrnInfoPtr pScrn, ORNum or, int i2cPort) +{ + G80OutputPrivPtr pPriv = xnfcalloc(sizeof(*pPriv), 1); + xf86OutputPtr output; + char orName[5]; + + if(!pPriv) + return FALSE; + + snprintf(orName, 5, "DVI%i", or); + output = xf86OutputCreate(pScrn, &G80SorOutputFuncs, orName); + + pPriv->type = SOR; + pPriv->or = or; + pPriv->set_pclk = G80SorSetPClk; + output->driver_private = pPriv; + output->interlaceAllowed = TRUE; + output->doubleScanAllowed = TRUE; + + /* Create an I2C object */ + G80I2CInit(output, i2cPort); + + return output; +} diff --git a/src/g80_type.h b/src/g80_type.h index 20b5e8b..6c031c4 100644 --- a/src/g80_type.h +++ b/src/g80_type.h @@ -2,6 +2,9 @@ #include <xf86.h> #include <xf86int10.h> #include <xf86Cursor.h> +#include <xf86DDC.h> +#include <xf86Crtc.h> +#include <xf86int10.h> typedef enum Head { HEAD0 = 0, @@ -36,12 +39,6 @@ typedef struct G80Rec { ORNum sor; } i2cMap[4]; - float pclk; /* Current mode pclk in kHz */ - - Head head; - ORType orType; - ORNum or; - xf86Int10InfoPtr int10; int int10Mode; /* Console mode to restore */ @@ -67,8 +64,9 @@ typedef struct G80Rec { CARD32 * dmaBase; void (*DMAKickoffCallback)(ScrnInfoPtr); - CloseScreenProcPtr CloseScreen; - ScreenBlockHandlerProcPtr BlockHandler; + CreateScreenResourcesProcPtr CreateScreenResources; + CloseScreenProcPtr CloseScreen; + ScreenBlockHandlerProcPtr BlockHandler; } G80Rec, *G80Ptr; #define G80PTR(p) ((G80Ptr)((p)->driverPrivate)) |