diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:55 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:55 +0000 |
commit | 2f223903fba2bdee1623f3442d7580c809b428cc (patch) | |
tree | 7418fc4a54112e8215ef7f8e42dec557d7cad8bc | |
parent | 542d57ea12b5461891a13a339e01ca9e1add124d (diff) |
Initial revision
-rw-r--r-- | man/nv.man | 115 | ||||
-rw-r--r-- | src/nv_const.h | 20 | ||||
-rw-r--r-- | src/nv_cursor.c | 301 | ||||
-rw-r--r-- | src/nv_dac.c | 415 | ||||
-rw-r--r-- | src/nv_dga.c | 312 | ||||
-rw-r--r-- | src/nv_driver.c | 1934 | ||||
-rw-r--r-- | src/nv_include.h | 59 | ||||
-rw-r--r-- | src/nv_local.h | 74 | ||||
-rw-r--r-- | src/nv_proto.h | 46 | ||||
-rw-r--r-- | src/nv_setup.c | 551 | ||||
-rw-r--r-- | src/nv_shadow.c | 194 | ||||
-rw-r--r-- | src/nv_type.h | 135 | ||||
-rw-r--r-- | src/nv_video.c | 1160 | ||||
-rw-r--r-- | src/nv_xaa.c | 573 | ||||
-rw-r--r-- | src/riva_hw.c | 2100 | ||||
-rw-r--r-- | src/riva_hw.h | 428 | ||||
-rw-r--r-- | src/riva_tbl.h | 826 |
17 files changed, 9243 insertions, 0 deletions
diff --git a/man/nv.man b/man/nv.man new file mode 100644 index 0000000..7856227 --- /dev/null +++ b/man/nv.man @@ -0,0 +1,115 @@ +.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv.man,v 1.17 2003/02/11 00:00:18 mvojkovi Exp $ +.\" shorthand for double quote that works everywhere. +.ds q \N'34' +.TH NV __drivermansuffix__ __vendorversion__ +.SH NAME +nv \- NVIDIA video driver +.SH SYNOPSIS +.nf +.B "Section \*qDevice\*q" +.BI " Identifier \*q" devname \*q +.B " Driver \*qnv\*q" +\ \ ... +.B EndSection +.fi +.SH DESCRIPTION +.B nv +is an XFree86 driver for NVIDIA video cards. The driver supports full 2D +acceleration and provides support for the following framebuffer depths: +8, 15, 16 (except Riva128) and 24. All +visual types are supported for depth 8, TrueColor and DirectColor +visuals are supported for the other depths with the exception of +the Riva128 which only supports TrueColor in the higher depths. + +.SH SUPPORTED HARDWARE +The +.B nv +driver supports PCI and AGP video cards based on the following NVIDIA chips: +.TP 22 +.B RIVA 128 +NV3 +.TP 22 +.B RIVA TNT +NV4 +.TP 22 +.B RIVA TNT2 +NV5 +.TP 22 +.B GeForce 256, QUADRO +NV10 +.TP 22 +.B GeForce2, QUADRO2 +NV11 & NV15 +.TP 22 +.B GeForce3, QUADRO DCC +NV20 +.TP 22 +.B nForce, nForce2 +NV1A, NV1F +.TP 22 +.B GeForce4, QUADRO4 +NV17, NV18, NV25, NV28 +.TP 22 +.B GeForce FX, QUADRO FX +NV30 +.SH CONFIGURATION DETAILS +Please refer to XF86Config(__filemansuffix__) for general configuration +details. This section only covers configuration details specific to this +driver. +.PP +The driver auto-detects the chipset type and the amount of video memory +present for all chips. +.PP +The following driver +.B Options +are supported: +.TP +.BI "Option \*qHWCursor\*q \*q" boolean \*q +Enable or disable the HW cursor. Default: on. +.TP +.BI "Option \*qNoAccel\*q \*q" boolean \*q +Disable or enable acceleration. Default: acceleration is enabled. +.TP +.BI "Option \*qUseFBDev\*q \*q" boolean \*q +Enable or disable use of on OS-specific fb interface (and is not supported +on all OSs). See fbdevhw(__drivermansuffix__) for further information. +Default: off. +.TP +.BI "Option \*qCrtcNumber\*q \*q" integer \*q +nForce2, Quadro4, GeForce4 and NV30 may have two video outputs. +The driver attempts to autodetect +which one the monitor is connected to. In the case that autodetection picks +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 \*qFlatPanel\*q \*q" boolean \*q +The driver usually cannot autodetect the presence of a flat panel so +this option should be set when used with a flat panel. With this driver +a flat panel will only work if it was POSTed by the BIOS, that is, the +machine must have booted to the panel. +Default: off. +.TP +.BI "Option \*qFPDither\*q \*q" boolean \*q +Most digital flat panels have only 6 bits per component color resolution. +This option tells the driver to dither from 8 bits per component to 6 before +the flat panel truncates it. This is only suported in depth 24 on NV11, +nForce2, GeForce4, Quadro4 and NV30. +Default: off. +.TP +.BI "Option \*qRotate\*q \*qCW\*q" +.TP +.BI "Option \*qRotate\*q \*qCCW\*q" +Rotate the display clockwise or counterclockwise. This mode is unaccelerated. +Default: no rotation. + +Note: Option Rotate does not work unless the Resize and Rotate extension has +been turned off. +.TP +.BI "Option \*qShadowFB\*q \*q" boolean \*q +Enable or disable use of the shadow framebuffer layer. Default: off. +.SH "SEE ALSO" +XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__) +.SH AUTHORS +Authors include: David McKay, Jarno Paananen, Chas Inman, Dave Schmenk, +Mark Vojkovich diff --git a/src/nv_const.h b/src/nv_const.h new file mode 100644 index 0000000..14ba134 --- /dev/null +++ b/src/nv_const.h @@ -0,0 +1,20 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_const.h,v 1.6 2001/12/07 00:09:55 mvojkovi Exp $ */ + +#ifndef __NV_CONST_H__ +#define __NV_CONST_H__ + +#define VERSION 4000 +#define NV_NAME "NV" +#define NV_DRIVER_NAME "nv" +#define NV_MAJOR_VERSION 1 +#define NV_MINOR_VERSION 0 +#define NV_PATCHLEVEL 1 + +#ifdef DEBUG_PRINT +#define DEBUG(x) x +#else +#define DEBUG(x) +#endif + +#endif /* __NV_CONST_H__ */ + diff --git a/src/nv_cursor.c b/src/nv_cursor.c new file mode 100644 index 0000000..04107ee --- /dev/null +++ b/src/nv_cursor.c @@ -0,0 +1,301 @@ +/* $XConsortium: nv_driver.c /main/3 1996/10/28 05:13:37 kaleb $ */ +/* + * Copyright 1996-1997 David J. McKay + * + * 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 + * DAVID J. MCKAY 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. + */ + +/* Rewritten with reference from mga driver and 3.3.4 NVIDIA driver by + Jarno Paananen <jpaana@s2.org> */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_cursor.c,v 1.11 2002/11/26 23:41:58 mvojkovi Exp $ */ + +#include "nv_include.h" + +#include "cursorstr.h" + +/****************************************************************************\ +* * +* HW Cursor Entrypoints * +* * +\****************************************************************************/ + +#define TRANSPARENT_PIXEL 0 + +#define ConvertToRGB555(c) \ +(((c & 0xf80000) >> 9 ) | ((c & 0xf800) >> 6 ) | ((c & 0xf8) >> 3 ) | 0x8000) + +#define ConvertToRGB888(c) (c | 0xff000000) + +#define BYTE_SWAP_32(c) ((c & 0xff000000) >> 24) | \ + ((c & 0xff0000) >> 8) | \ + ((c & 0xff00) << 8) | \ + ((c & 0xff) << 24) + + +static void +ConvertCursor1555(NVPtr pNv, CARD32 *src, CARD16 *dst) +{ + CARD32 b, m; + int i, j; + + for ( i = 0; i < 32; i++ ) { + b = *src++; + m = *src++; + for ( j = 0; j < 32; j++ ) { +#if X_BYTE_ORDER == X_BIG_ENDIAN + if ( m & 0x80000000) + *dst = ( b & 0x80000000) ? pNv->curFg : pNv->curBg; + else + *dst = TRANSPARENT_PIXEL; + b <<= 1; + m <<= 1; +#else + if ( m & 1 ) + *dst = ( b & 1) ? pNv->curFg : pNv->curBg; + else + *dst = TRANSPARENT_PIXEL; + b >>= 1; + m >>= 1; +#endif + dst++; + } + } +} + + +static void +ConvertCursor8888(NVPtr pNv, CARD32 *src, CARD32 *dst) +{ + CARD32 b, m; + int i, j; + + for ( i = 0; i < 128; i++ ) { + b = *src++; + m = *src++; + for ( j = 0; j < 32; j++ ) { +#if X_BYTE_ORDER == X_BIG_ENDIAN + if ( m & 0x80000000) + *dst = ( b & 0x80000000) ? pNv->curFg : pNv->curBg; + else + *dst = TRANSPARENT_PIXEL; + b <<= 1; + m <<= 1; +#else + if ( m & 1 ) + *dst = ( b & 1) ? pNv->curFg : pNv->curBg; + else + *dst = TRANSPARENT_PIXEL; + b >>= 1; + m >>= 1; +#endif + dst++; + } + } +} + + +static void +TransformCursor (NVPtr pNv) +{ + CARD32 *tmp; + int i, dwords; + + /* convert to color cursor */ + if(pNv->alphaCursor) { + dwords = 64 * 64; + if(!(tmp = ALLOCATE_LOCAL(dwords * 4))) return; + ConvertCursor8888(pNv, pNv->curImage, tmp); + } else { + dwords = (32 * 32) >> 1; + if(!(tmp = ALLOCATE_LOCAL(dwords * 4))) return; + ConvertCursor1555(pNv, pNv->curImage, (CARD16*)tmp); + } + + for(i = 0; i < dwords; i++) + pNv->riva.CURSOR[i] = tmp[i]; + + DEALLOCATE_LOCAL(tmp); +} + +static void +NVLoadCursorImage( ScrnInfoPtr pScrn, unsigned char *src ) +{ + NVPtr pNv = NVPTR(pScrn); + + /* save copy of image for color changes */ + memcpy(pNv->curImage, src, (pNv->alphaCursor) ? 1024 : 256); + + TransformCursor(pNv); +} + +static void +NVSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) +{ + NVPtr pNv = NVPTR(pScrn); + + pNv->riva.PRAMDAC[0x0000300/4] = (x & 0xFFFF) | (y << 16); +} + +static void +NVSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) +{ + NVPtr pNv = NVPTR(pScrn); + CARD32 fore, back; + + if(pNv->alphaCursor) { + fore = ConvertToRGB888(fg); + back = ConvertToRGB888(bg); +#if X_BYTE_ORDER == X_BIG_ENDIAN + if((pNv->Chipset & 0x0ff0) == 0x0110) { + fore = BYTE_SWAP_32(fore); + back = BYTE_SWAP_32(back); + } +#endif + } else { + fore = ConvertToRGB555(fg); + back = ConvertToRGB555(bg); +#if X_BYTE_ORDER == X_BIG_ENDIAN + if((pNv->Chipset & 0x0ff0) == 0x0110) { + fore = ((fore & 0xff) << 8) | (fore >> 8); + back = ((back & 0xff) << 8) | (back >> 8); + } +#endif + } + + if ((pNv->curFg != fore) || (pNv->curBg != back)) { + pNv->curFg = fore; + pNv->curBg = back; + + TransformCursor(pNv); + } +} + + +static void +NVShowCursor(ScrnInfoPtr pScrn) +{ + NVPtr pNv = NVPTR(pScrn); + /* Enable cursor - X-Windows mode */ + pNv->riva.ShowHideCursor(&pNv->riva, 1); +} + +static void +NVHideCursor(ScrnInfoPtr pScrn) +{ + NVPtr pNv = NVPTR(pScrn); + /* Disable cursor */ + pNv->riva.ShowHideCursor(&pNv->riva, 0); +} + +static Bool +NVUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) +{ + return TRUE; +} + +#ifdef ARGB_CURSOR +static Bool +NVUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs) +{ + if((pCurs->bits->width <= 64) && (pCurs->bits->height <= 64)) + return TRUE; + + return FALSE; +} + +static void +NVLoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs) +{ + NVPtr pNv = NVPTR(pScrn); + CARD32 *image = pCurs->bits->argb; + CARD32 *dst = (CARD32*)pNv->riva.CURSOR; + int x, y, w, h; + + w = pCurs->bits->width; + h = pCurs->bits->height; + +#if X_BYTE_ORDER == X_BIG_ENDIAN + if((pNv->Chipset & 0x0ff0) == 0x0110) { + CARD32 tmp; + + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + tmp = *image++; + *dst++ = BYTE_SWAP_32(tmp); + } + for(; x < 64; x++) + *dst++ = 0; + } + } else +#endif + { + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) + *dst++ = *image++; + for(; x < 64; x++) + *dst++ = 0; + } + } + + if(y < 64) + memset(dst, 0, 64 * (64 - y) * 4); +} +#endif + +Bool +NVCursorInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + NVPtr pNv = NVPTR(pScrn); + xf86CursorInfoPtr infoPtr; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVCursorInit\n")); + + infoPtr = xf86CreateCursorInfoRec(); + if(!infoPtr) return FALSE; + + pNv->CursorInfoRec = infoPtr; + + if(pNv->alphaCursor) + infoPtr->MaxWidth = infoPtr->MaxHeight = 64; + else + infoPtr->MaxWidth = infoPtr->MaxHeight = 32; + + infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | + HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32; + infoPtr->SetCursorColors = NVSetCursorColors; + infoPtr->SetCursorPosition = NVSetCursorPosition; + infoPtr->LoadCursorImage = NVLoadCursorImage; + infoPtr->HideCursor = NVHideCursor; + infoPtr->ShowCursor = NVShowCursor; + infoPtr->UseHWCursor = NVUseHWCursor; + +#ifdef ARGB_CURSOR + if(pNv->alphaCursor && + (((pNv->Chipset & 0x0ff0) != 0x0110) || + !(pNv->riva.flatPanel & FP_DITHER))) + { + infoPtr->UseHWCursorARGB = NVUseHWCursorARGB; + infoPtr->LoadCursorARGB = NVLoadCursorARGB; + } +#endif + + return(xf86InitCursor(pScreen, infoPtr)); +} diff --git a/src/nv_dac.c b/src/nv_dac.c new file mode 100644 index 0000000..90d75da --- /dev/null +++ b/src/nv_dac.c @@ -0,0 +1,415 @@ +/* $XConsortium: nv_driver.c /main/3 1996/10/28 05:13:37 kaleb $ */ +/* + * Copyright 1996-1997 David J. McKay + * + * 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 + * DAVID J. MCKAY 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. + */ + +/* 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_dac.c,v 1.31 2003/01/02 20:44:56 mvojkovi Exp $ */ + +#include "nv_include.h" + +Bool +NVDACInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + int i; + int horizDisplay = (mode->CrtcHDisplay/8) - 1; + int horizStart = (mode->CrtcHSyncStart/8) - 1; + int horizEnd = (mode->CrtcHSyncEnd/8) - 1; + int horizTotal = (mode->CrtcHTotal/8) - 5; + int horizBlankStart = (mode->CrtcHDisplay/8) - 1; + int horizBlankEnd = (mode->CrtcHTotal/8) - 1; + int vertDisplay = mode->CrtcVDisplay - 1; + int vertStart = mode->CrtcVSyncStart - 1; + int vertEnd = mode->CrtcVSyncEnd - 1; + int vertTotal = mode->CrtcVTotal - 2; + int vertBlankStart = mode->CrtcVDisplay - 1; + int vertBlankEnd = mode->CrtcVTotal - 1; + + + NVPtr pNv = NVPTR(pScrn); + NVRegPtr nvReg = &pNv->ModeReg; + NVFBLayout *pLayout = &pNv->CurrentLayout; + vgaRegPtr pVga; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVDACInit\n")); + + /* + * This will initialize all of the generic VGA registers. + */ + if (!vgaHWInit(pScrn, mode)) + return(FALSE); + + pVga = &VGAHWPTR(pScrn)->ModeReg; + + /* + * Set all CRTC values. + */ + + if(mode->Flags & V_INTERLACE) + vertTotal |= 1; + + if(pNv->FlatPanel == 1) { + vertStart = vertTotal - 3; + vertEnd = vertTotal - 2; + vertBlankStart = vertStart; + horizStart = horizTotal - 3; + horizEnd = horizTotal - 2; + horizBlankEnd = horizTotal + 4; + } + + pVga->CRTC[0x0] = Set8Bits(horizTotal); + pVga->CRTC[0x1] = Set8Bits(horizDisplay); + pVga->CRTC[0x2] = Set8Bits(horizBlankStart); + pVga->CRTC[0x3] = SetBitField(horizBlankEnd,4:0,4:0) + | SetBit(7); + pVga->CRTC[0x4] = Set8Bits(horizStart); + pVga->CRTC[0x5] = SetBitField(horizBlankEnd,5:5,7:7) + | SetBitField(horizEnd,4:0,4:0); + pVga->CRTC[0x6] = SetBitField(vertTotal,7:0,7:0); + pVga->CRTC[0x7] = SetBitField(vertTotal,8:8,0:0) + | SetBitField(vertDisplay,8:8,1:1) + | SetBitField(vertStart,8:8,2:2) + | SetBitField(vertBlankStart,8:8,3:3) + | SetBit(4) + | SetBitField(vertTotal,9:9,5:5) + | SetBitField(vertDisplay,9:9,6:6) + | SetBitField(vertStart,9:9,7:7); + pVga->CRTC[0x9] = SetBitField(vertBlankStart,9:9,5:5) + | SetBit(6) + | ((mode->Flags & V_DBLSCAN) ? 0x80 : 0x00); + pVga->CRTC[0x10] = Set8Bits(vertStart); + pVga->CRTC[0x11] = SetBitField(vertEnd,3:0,3:0) | SetBit(5); + pVga->CRTC[0x12] = Set8Bits(vertDisplay); + pVga->CRTC[0x13] = ((pLayout->displayWidth/8)*(pLayout->bitsPerPixel/8)); + pVga->CRTC[0x15] = Set8Bits(vertBlankStart); + pVga->CRTC[0x16] = Set8Bits(vertBlankEnd); + + pVga->Attribute[0x10] = 0x01; + + nvReg->screen = SetBitField(horizBlankEnd,6:6,4:4) + | SetBitField(vertBlankStart,10:10,3:3) + | SetBitField(vertStart,10:10,2:2) + | SetBitField(vertDisplay,10:10,1:1) + | SetBitField(vertTotal,10:10,0:0); + + nvReg->horiz = SetBitField(horizTotal,8:8,0:0) + | SetBitField(horizDisplay,8:8,1:1) + | SetBitField(horizBlankStart,8:8,2:2) + | SetBitField(horizStart,8:8,3:3); + + nvReg->extra = SetBitField(vertTotal,11:11,0:0) + | SetBitField(vertDisplay,11:11,2:2) + | SetBitField(vertStart,11:11,4:4) + | SetBitField(vertBlankStart,11:11,6:6); + + if(mode->Flags & V_INTERLACE) { + horizTotal = (horizTotal >> 1) & ~1; + nvReg->interlace = Set8Bits(horizTotal); + nvReg->horiz |= SetBitField(horizTotal,8:8,4:4); + } else { + nvReg->interlace = 0xff; /* interlace off */ + } + + + /* + * Initialize DAC palette. + */ + if(pLayout->bitsPerPixel != 8 ) + { + for (i = 0; i < 256; i++) + { + pVga->DAC[i*3] = i; + pVga->DAC[(i*3)+1] = i; + pVga->DAC[(i*3)+2] = i; + } + } + + /* + * Calculate the extended registers. + */ + + if(pLayout->depth < 24) + i = pLayout->depth; + else i = 32; + + if(pNv->riva.Architecture >= NV_ARCH_10) + pNv->riva.CURSOR = (U032 *)(pNv->FbStart + pNv->riva.CursorStart); + + pNv->riva.LockUnlock(&pNv->riva, 0); + + pNv->riva.CalcStateExt(&pNv->riva, + nvReg, + i, + pLayout->displayWidth, + mode->CrtcHDisplay, + pScrn->virtualY, + mode->Clock, + mode->Flags); + + nvReg->scale = pNv->riva.PRAMDAC[0x00000848/4] & 0xfff000ff; + if(pNv->FlatPanel == 1) { + nvReg->pixel |= (1 << 7); + nvReg->scale |= (1 << 8) ; + } + if(pNv->SecondCRTC) { + nvReg->head = pNv->riva.PCRTC0[0x00000860/4] & ~0x00001000; + nvReg->head2 = pNv->riva.PCRTC0[0x00002860/4] | 0x00001000; + nvReg->crtcOwner = 3; + nvReg->pllsel |= 0x20000800; + nvReg->vpll2 = nvReg->vpll; + } else + if(pNv->riva.twoHeads) { + nvReg->head = pNv->riva.PCRTC0[0x00000860/4] | 0x00001000; + nvReg->head2 = pNv->riva.PCRTC0[0x00002860/4] & ~0x00001000; + nvReg->crtcOwner = 0; + nvReg->vpll2 = pNv->riva.PRAMDAC0[0x00000520/4]; + } + + nvReg->cursorConfig = 0x00000100; + if(mode->Flags & V_DBLSCAN) + nvReg->cursorConfig |= (1 << 4); + if(pNv->alphaCursor) { + nvReg->cursorConfig |= 0x04011000; + nvReg->general |= (1 << 29); + + if((pNv->Chipset & 0x0ff0) == 0x0110) { + nvReg->dither = pNv->riva.PRAMDAC[0x0528/4] & ~0x00010000; + if(pNv->riva.flatPanel & FP_DITHER) + nvReg->dither |= 0x00010000; + else + nvReg->cursorConfig |= (1 << 28); + } else + if((pNv->riva.Chipset & 0x0ff0) >= 0x0170) { + nvReg->dither = pNv->riva.PRAMDAC[0x083C/4] & ~1; + nvReg->cursorConfig |= (1 << 28); + if(pNv->riva.flatPanel & FP_DITHER) + nvReg->dither |= 1; + } else { + nvReg->cursorConfig |= (1 << 28); + } + } else + nvReg->cursorConfig |= 0x02000000; + + nvReg->vpllB = 0; + nvReg->vpll2B = 0; + + return (TRUE); +} + +void +NVDACRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, NVRegPtr nvReg, + Bool primary) +{ + NVPtr pNv = NVPTR(pScrn); + int restore = VGA_SR_MODE; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVDACRestore\n")); + + if(primary) restore |= VGA_SR_CMAP | VGA_SR_FONTS; + else if((pNv->Chipset & 0xffff) == 0x0018) + restore |= VGA_SR_CMAP; + pNv->riva.LoadStateExt(&pNv->riva, nvReg); +#if defined(__powerpc__) + restore &= ~VGA_SR_FONTS; +#endif + vgaHWRestore(pScrn, vgaReg, restore); +} + +/* + * NVDACSave + * + * This function saves the video state. + */ +void +NVDACSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, NVRegPtr nvReg, + Bool saveFonts) +{ + NVPtr pNv = NVPTR(pScrn); + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVDACSave\n")); + +#if defined(__powerpc__) + saveFonts = FALSE; +#endif + + vgaHWSave(pScrn, vgaReg, VGA_SR_CMAP | VGA_SR_MODE | + (saveFonts? VGA_SR_FONTS : 0)); + pNv->riva.UnloadStateExt(&pNv->riva, nvReg); + + if((pNv->Chipset & 0x0ff0) == 0x0110) + nvReg->crtcOwner = ((pNv->Chipset & 0x0fff) == 0x0112) ? 3 : 0; +} + +#define DEPTH_SHIFT(val, w) ((val << (8 - w)) | (val >> ((w << 1) - 8))) +#define MAKE_INDEX(in, w) (DEPTH_SHIFT(in, w) * 3) + +void +NVDACLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, + VisualPtr pVisual ) +{ + int i, index; + NVPtr pNv = NVPTR(pScrn); + vgaRegPtr pVga; + + pVga = &VGAHWPTR(pScrn)->ModeReg; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVDACLoadPalette\n")); + + if((pNv->riva.Architecture == NV_ARCH_03) && + (pNv->CurrentLayout.depth != 8)) + return; + + switch(pNv->CurrentLayout.depth) { + case 15: + for(i = 0; i < numColors; i++) { + index = indices[i]; + pVga->DAC[MAKE_INDEX(index, 5) + 0] = colors[index].red; + pVga->DAC[MAKE_INDEX(index, 5) + 1] = colors[index].green; + pVga->DAC[MAKE_INDEX(index, 5) + 2] = colors[index].blue; + } + break; + case 16: + for(i = 0; i < numColors; i++) { + index = indices[i]; + pVga->DAC[MAKE_INDEX(index, 6) + 1] = colors[index].green; + if(index < 32) { + pVga->DAC[MAKE_INDEX(index, 5) + 0] = colors[index].red; + pVga->DAC[MAKE_INDEX(index, 5) + 2] = colors[index].blue; + } + } + break; + default: + for(i = 0; i < numColors; i++) { + index = indices[i]; + pVga->DAC[index*3] = colors[index].red; + pVga->DAC[(index*3)+1] = colors[index].green; + pVga->DAC[(index*3)+2] = colors[index].blue; + } + break; + } + vgaHWRestore(pScrn, pVga, VGA_SR_CMAP); +} + +/* + * DDC1 support only requires DDC_SDA_MASK, + * DDC2 support requires DDC_SDA_MASK and DDC_SCL_MASK + */ +#define DDC_SDA_READ_MASK (1 << 3) +#define DDC_SCL_READ_MASK (1 << 2) +#define DDC_SDA_WRITE_MASK (1 << 4) +#define DDC_SCL_WRITE_MASK (1 << 5) + +static unsigned int +NV_ddc1Read(ScrnInfoPtr pScrn) +{ + NVPtr pNv = NVPTR(pScrn); + unsigned char val; + + /* wait for Vsync */ + while(VGA_RD08(pNv->riva.PCIO, 0x3da) & 0x08); + while(!(VGA_RD08(pNv->riva.PCIO, 0x3da) & 0x08)); + + /* Get the result */ + VGA_WR08(pNv->riva.PCIO, 0x3d4, pNv->DDCBase); + val = VGA_RD08(pNv->riva.PCIO, 0x3d5); + DEBUG(ErrorF("NV_ddc1Read(%p,...) returns %d\n", + pScrn, val)); + return (val & DDC_SDA_READ_MASK) != 0; +} + +static void +NV_I2CGetBits(I2CBusPtr b, int *clock, int *data) +{ + NVPtr pNv = NVPTR(xf86Screens[b->scrnIndex]); + unsigned char val; + + /* Get the result. */ + VGA_WR08(pNv->riva.PCIO, 0x3d4, pNv->DDCBase); + val = VGA_RD08(pNv->riva.PCIO, 0x3d5); + + *clock = (val & DDC_SCL_READ_MASK) != 0; + *data = (val & DDC_SDA_READ_MASK) != 0; + DEBUG(ErrorF("NV_I2CGetBits(%p,...) val=0x%x, returns clock %d, data %d\n", + b, val, *clock, *data)); +} + +static void +NV_I2CPutBits(I2CBusPtr b, int clock, int data) +{ + NVPtr pNv = NVPTR(xf86Screens[b->scrnIndex]); + unsigned char val; + + VGA_WR08(pNv->riva.PCIO, 0x3d4, pNv->DDCBase + 1); + val = VGA_RD08(pNv->riva.PCIO, 0x3d5) & 0xf0; + if (clock) + val |= DDC_SCL_WRITE_MASK; + else + val &= ~DDC_SCL_WRITE_MASK; + + if (data) + val |= DDC_SDA_WRITE_MASK; + else + val &= ~DDC_SDA_WRITE_MASK; + + VGA_WR08(pNv->riva.PCIO, 0x3d4, pNv->DDCBase + 1); + VGA_WR08(pNv->riva.PCIO, 0x3d5, val | 0x1); + + DEBUG(ErrorF("NV_I2CPutBits(%p, %d, %d) val=0x%x\n", b, clock, data, val)); +} + +static Bool +NV_i2cInit(ScrnInfoPtr pScrn) +{ + NVPtr pNv = NVPTR(pScrn); + I2CBusPtr I2CPtr; + + I2CPtr = xf86CreateI2CBusRec(); + if(!I2CPtr) return FALSE; + + pNv->I2C = I2CPtr; + + I2CPtr->BusName = "DDC"; + I2CPtr->scrnIndex = pScrn->scrnIndex; + I2CPtr->I2CPutBits = NV_I2CPutBits; + I2CPtr->I2CGetBits = NV_I2CGetBits; + I2CPtr->AcknTimeout = 5; + + if (!xf86I2CBusInit(I2CPtr)) { + return FALSE; + } + return TRUE; +} + +/* + * NVRamdacInit + */ +void +NVRamdacInit(ScrnInfoPtr pScrn) +{ + NVPtr pNv = NVPTR(pScrn); + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVRamdacInit\n")); + pNv->ddc1Read = NV_ddc1Read; + /* vgaHWddc1SetSpeed will only work if the card is in VGA mode */ + pNv->DDC1SetSpeed = vgaHWddc1SetSpeed; + pNv->i2cInit = NV_i2cInit; +} + diff --git a/src/nv_dga.c b/src/nv_dga.c new file mode 100644 index 0000000..714467a --- /dev/null +++ b/src/nv_dga.c @@ -0,0 +1,312 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_dga.c,v 1.11 2002/01/25 21:56:06 tsi Exp $ */ + +#include "nv_local.h" +#include "nv_include.h" +#include "nv_type.h" +#include "nv_proto.h" +#include "xaalocal.h" +#include "dgaproc.h" + + +static Bool NV_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, + int *, int *, int *); +static Bool NV_SetMode(ScrnInfoPtr, DGAModePtr); +static int NV_GetViewport(ScrnInfoPtr); +static void NV_SetViewport(ScrnInfoPtr, int, int, int); +static void NV_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long); +static void NV_BlitRect(ScrnInfoPtr, int, int, int, int, int, int); +static void NV_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int, + unsigned long); + +static +DGAFunctionRec NV_DGAFuncs = { + NV_OpenFramebuffer, + NULL, + NV_SetMode, + NV_SetViewport, + NV_GetViewport, + NVSync, + NV_FillRect, + NV_BlitRect, + NV_BlitTransRect +}; + + + +static DGAModePtr +NVSetupDGAMode( + ScrnInfoPtr pScrn, + DGAModePtr modes, + int *num, + int bitsPerPixel, + int depth, + Bool pixmap, + int secondPitch, + unsigned long red, + unsigned long green, + unsigned long blue, + short visualClass +){ + DisplayModePtr firstMode, pMode; + NVPtr pNv = NVPTR(pScrn); + DGAModePtr mode, newmodes; + int size, pitch, Bpp = bitsPerPixel >> 3; + +SECOND_PASS: + + pMode = firstMode = pScrn->modes; + + while(1) { + + pitch = (pMode->HDisplay + 31) & ~31; + size = pitch * Bpp * pMode->VDisplay; + + if((!secondPitch || (pitch != secondPitch)) && + (size <= pNv->FbUsableSize)) { + + if(secondPitch) + pitch = secondPitch; + + if(!(newmodes = xrealloc(modes, (*num + 1) * sizeof(DGAModeRec)))) + break; + + modes = newmodes; + mode = modes + *num; + + mode->mode = pMode; + mode->flags = DGA_CONCURRENT_ACCESS; + + if(pixmap) + mode->flags |= DGA_PIXMAP_AVAILABLE; + if(!pNv->NoAccel) + mode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT; + if(pMode->Flags & V_DBLSCAN) + mode->flags |= DGA_DOUBLESCAN; + if(pMode->Flags & V_INTERLACE) + mode->flags |= DGA_INTERLACED; + mode->byteOrder = pScrn->imageByteOrder; + mode->depth = depth; + mode->bitsPerPixel = bitsPerPixel; + mode->red_mask = red; + mode->green_mask = green; + mode->blue_mask = blue; + mode->visualClass = visualClass; + mode->viewportWidth = pMode->HDisplay; + mode->viewportHeight = pMode->VDisplay; + mode->xViewportStep = 4 / Bpp; + mode->yViewportStep = 1; + mode->viewportFlags = DGA_FLIP_RETRACE; + mode->offset = 0; + mode->address = pNv->FbStart; + mode->bytesPerScanline = pitch * Bpp; + mode->imageWidth = pitch; + mode->imageHeight = pNv->FbUsableSize / mode->bytesPerScanline; + mode->pixmapWidth = mode->imageWidth; + mode->pixmapHeight = mode->imageHeight; + mode->maxViewportX = mode->imageWidth - mode->viewportWidth; + mode->maxViewportY = mode->imageHeight - mode->viewportHeight; + (*num)++; + } + + pMode = pMode->next; + if(pMode == firstMode) + break; + } + + if(secondPitch) { + secondPitch = 0; + goto SECOND_PASS; + } + + return modes; +} + + +Bool +NVDGAInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + NVPtr pNv = NVPTR(pScrn); + DGAModePtr modes = NULL; + int num = 0; + + /* 8 */ + modes = NVSetupDGAMode (pScrn, modes, &num, 8, 8, + (pScrn->bitsPerPixel == 8), + (pScrn->bitsPerPixel != 8) ? 0 : pScrn->displayWidth, + 0, 0, 0, PseudoColor); + + /* 15 */ + modes = NVSetupDGAMode (pScrn, modes, &num, 16, 15, + (pScrn->bitsPerPixel == 16), + (pScrn->depth != 15) ? 0 : pScrn->displayWidth, + 0x7c00, 0x03e0, 0x001f, TrueColor); + + /* 16 */ + if(pNv->riva.Architecture != 3) + modes = NVSetupDGAMode (pScrn, modes, &num, 16, 16, + (pScrn->bitsPerPixel == 16), + (pScrn->depth != 16) ? 0 : pScrn->displayWidth, + 0xf800, 0x07e0, 0x001f, TrueColor); + + /* 32 */ + modes = NVSetupDGAMode (pScrn, modes, &num, 32, 24, + (pScrn->bitsPerPixel == 32), + (pScrn->bitsPerPixel != 32) ? 0 : pScrn->displayWidth, + 0xff0000, 0x00ff00, 0x0000ff, TrueColor); + + pNv->numDGAModes = num; + pNv->DGAModes = modes; + + return DGAInit(pScreen, &NV_DGAFuncs, modes, num); +} + + +static int +BitsSet(unsigned long data) +{ + unsigned long mask; + int set = 0; + + for(mask = 1; mask; mask <<= 1) + if(mask & data) set++; + + return set; +} + +static Bool +NV_SetMode( + ScrnInfoPtr pScrn, + DGAModePtr pMode +){ + static NVFBLayout SavedLayouts[MAXSCREENS]; + int index = pScrn->pScreen->myNum; + + NVPtr pNv = NVPTR(pScrn); + + if(!pMode) { /* restore the original mode */ + if(pNv->DGAactive) + memcpy(&pNv->CurrentLayout, &SavedLayouts[index], sizeof(NVFBLayout)); + + pScrn->currentMode = pNv->CurrentLayout.mode; + NVSwitchMode(index, pScrn->currentMode, 0); + NVAdjustFrame(index, pScrn->frameX0, pScrn->frameY0, 0); + pNv->DGAactive = FALSE; + } else { + if(!pNv->DGAactive) { /* save the old parameters */ + memcpy(&SavedLayouts[index], &pNv->CurrentLayout, sizeof(NVFBLayout)); + pNv->DGAactive = TRUE; + } + + /* update CurrentLayout */ + pNv->CurrentLayout.bitsPerPixel = pMode->bitsPerPixel; + pNv->CurrentLayout.depth = pMode->depth; + pNv->CurrentLayout.displayWidth = pMode->bytesPerScanline / + (pMode->bitsPerPixel >> 3); + pNv->CurrentLayout.weight.red = BitsSet(pMode->red_mask); + pNv->CurrentLayout.weight.green = BitsSet(pMode->green_mask); + pNv->CurrentLayout.weight.blue = BitsSet(pMode->blue_mask); + /* NVModeInit() will set the mode field */ + NVSwitchMode(index, pMode->mode, 0); + } + + return TRUE; +} + + + +static int +NV_GetViewport( + ScrnInfoPtr pScrn +){ + NVPtr pNv = NVPTR(pScrn); + + return pNv->DGAViewportStatus; +} + +static void +NV_SetViewport( + ScrnInfoPtr pScrn, + int x, int y, + int flags +){ + NVPtr pNv = NVPTR(pScrn); + + NVAdjustFrame(pScrn->pScreen->myNum, x, y, flags); + + while(VGA_RD08(pNv->riva.PCIO, 0x3da) & 0x08); + while(!(VGA_RD08(pNv->riva.PCIO, 0x3da) & 0x08)); + + pNv->DGAViewportStatus = 0; +} + +static void +NV_FillRect ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned long color +){ + NVPtr pNv = NVPTR(pScrn); + + if(!pNv->AccelInfoRec) return; + + (*pNv->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0); + (*pNv->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); + + SET_SYNC_FLAG(pNv->AccelInfoRec); +} + +static void +NV_BlitRect( + ScrnInfoPtr pScrn, + int srcx, int srcy, + int w, int h, + int dstx, int dsty +){ + NVPtr pNv = NVPTR(pScrn); + int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; + int ydir = (srcy < dsty) ? -1 : 1; + + if(!pNv->AccelInfoRec) return; + + (*pNv->AccelInfoRec->SetupForScreenToScreenCopy)( + pScrn, xdir, ydir, GXcopy, ~0, -1); + + (*pNv->AccelInfoRec->SubsequentScreenToScreenCopy)( + pScrn, srcx, srcy, dstx, dsty, w, h); + + SET_SYNC_FLAG(pNv->AccelInfoRec); +} + + +static void +NV_BlitTransRect( + ScrnInfoPtr pScrn, + int srcx, int srcy, + int w, int h, + int dstx, int dsty, + unsigned long color +){ + /* not implemented... yet */ +} + + +static Bool +NV_OpenFramebuffer( + ScrnInfoPtr pScrn, + char **name, + unsigned char **mem, + int *size, + int *offset, + int *flags +){ + NVPtr pNv = NVPTR(pScrn); + + *name = NULL; /* no special device */ + *mem = (unsigned char*)pNv->FbAddress; + *size = pNv->FbMapSize; + *offset = 0; + *flags = DGA_NEED_ROOT; + + return TRUE; +} diff --git a/src/nv_driver.c b/src/nv_driver.c new file mode 100644 index 0000000..92d4599 --- /dev/null +++ b/src/nv_driver.c @@ -0,0 +1,1934 @@ +/* $XConsortium: nv_driver.c /main/3 1996/10/28 05:13:37 kaleb $ */ +/* + * Copyright 1996-1997 David J. McKay + * + * 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 + * DAVID J. MCKAY 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. + */ + +/* 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.101 2003/02/10 23:42:51 mvojkovi Exp $ */ + +#include "nv_include.h" + +#include "xf86int10.h" + +/* + * Forward definitions for the functions that make up the driver. + */ +/* Mandatory functions */ +static const OptionInfoRec * NVAvailableOptions(int chipid, int busid); +static void NVIdentify(int flags); +static Bool NVProbe(DriverPtr drv, int flags); +static Bool NVPreInit(ScrnInfoPtr pScrn, int flags); +static Bool NVScreenInit(int Index, ScreenPtr pScreen, int argc, + char **argv); +static Bool NVEnterVT(int scrnIndex, int flags); +static Bool NVEnterVTFBDev(int scrnIndex, int flags); +static void NVLeaveVT(int scrnIndex, int flags); +static Bool NVCloseScreen(int scrnIndex, ScreenPtr pScreen); +static Bool NVSaveScreen(ScreenPtr pScreen, int mode); + +/* Optional functions */ +static void NVFreeScreen(int scrnIndex, int flags); +static int NVValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, + int flags); + +/* Internally used functions */ + +static Bool NVMapMem(ScrnInfoPtr pScrn); +static Bool NVMapMemFBDev(ScrnInfoPtr pScrn); +static Bool NVUnmapMem(ScrnInfoPtr pScrn); +static void NVSave(ScrnInfoPtr pScrn); +static void NVRestore(ScrnInfoPtr pScrn); +static Bool NVModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); + + +/* + * This contains the functions needed by the server after loading the + * driver module. It must be supplied, and gets added the driver list by + * the Module Setup funtion in the dynamic case. In the static case a + * reference to this is compiled in, and this requires that the name of + * this DriverRec be an upper-case version of the driver name. + */ + +DriverRec NV = { + VERSION, + NV_DRIVER_NAME, + NVIdentify, + NVProbe, + NVAvailableOptions, + NULL, + 0 +}; + +static SymTabRec NVKnownChipsets[] = +{ + { 0x12D20018, "RIVA 128" }, + { 0x10DE0020, "RIVA TNT" }, + { 0x10DE0028, "RIVA TNT2" }, + { 0x10DE002C, "Vanta" }, + { 0x10DE0029, "RIVA TNT2 Ultra" }, + { 0x10DE002D, "RIVA TNT2 Model 64" }, + { 0x10DE00A0, "Aladdin TNT2" }, + { 0x10DE0100, "GeForce 256" }, + { 0x10DE0101, "GeForce DDR" }, + { 0x10DE0103, "Quadro" }, + { 0x10DE0110, "GeForce2 MX/MX 400" }, + { 0x10DE0111, "GeForce2 MX 100/200" }, + { 0x10DE0112, "GeForce2 Go" }, + { 0x10DE0113, "Quadro2 MXR/EX/Go" }, + { 0x10DE01A0, "GeForce2 Integrated GPU" }, + { 0x10DE0150, "GeForce2 GTS" }, + { 0x10DE0151, "GeForce2 Ti" }, + { 0x10DE0152, "GeForce2 Ultra" }, + { 0x10DE0153, "Quadro2 Pro" }, + { 0x10DE0170, "GeForce4 MX 460" }, + { 0x10DE0171, "GeForce4 MX 440" }, + { 0x10DE0172, "GeForce4 MX 420" }, + { 0x10DE0173, "GeForce4 MX 440-SE" }, + { 0x10DE0174, "GeForce4 440 Go" }, + { 0x10DE0175, "GeForce4 420 Go" }, + { 0x10DE0176, "GeForce4 420 Go 32M" }, + { 0x10DE0177, "GeForce4 460 Go" }, + { 0x10DE0179, "GeForce4 440 Go 64M" }, + { 0x10DE017D, "GeForce4 410 Go 16M" }, + { 0x10DE017C, "Quadro4 500 GoGL" }, + { 0x10DE0178, "Quadro4 550 XGL" }, + { 0x10DE017A, "Quadro4 NVS" }, + { 0x10DE0181, "GeForce4 MX 440 with AGP8X" }, + { 0x10DE0182, "GeForce4 MX 440SE with AGP8X" }, + { 0x10DE0183, "GeForce4 MX 420 with AGP8X" }, + { 0x10DE0186, "GeForce4 448 Go" }, + { 0x10DE0187, "GeForce4 488 Go" }, + { 0x10DE0188, "Quadro4 580 XGL" }, + { 0x10DE018A, "Quadro4 280 NVS" }, + { 0x10DE018B, "Quadro4 380 XGL" }, + { 0x10DE01F0, "GeForce4 MX Integrated GPU" }, + { 0x10DE0200, "GeForce3" }, + { 0x10DE0201, "GeForce3 Ti 200" }, + { 0x10DE0202, "GeForce3 Ti 500" }, + { 0x10DE0203, "Quadro DCC" }, + { 0x10DE0250, "GeForce4 Ti 4600" }, + { 0x10DE0251, "GeForce4 Ti 4400" }, + { 0x10DE0252, "0x0252" }, + { 0x10DE0253, "GeForce4 Ti 4200" }, + { 0x10DE0258, "Quadro4 900 XGL" }, + { 0x10DE0259, "Quadro4 750 XGL" }, + { 0x10DE025B, "Quadro4 700 XGL" }, + { 0x10DE0280, "GeForce4 Ti 4800" }, + { 0x10DE0281, "GeForce4 Ti 4200 with AGP8X" }, + { 0x10DE0282, "GeForce4 Ti 4800 SE" }, + { 0x10DE0286, "GeForce4 4200 Go" }, + { 0x10DE028C, "Quadro4 700 GoGL" }, + { 0x10DE0288, "Quadro4 980 XGL" }, + { 0x10DE0289, "Quadro4 780 XGL" }, + { 0x10DE0300, "0x0300" }, + { 0x10DE0301, "GeForce FX 5800 Ultra" }, + { 0x10DE0302, "GeForce FX 5800" }, + { 0x10DE0308, "Quadro FX 2000" }, + { 0x10DE0309, "Quadro FX 1000" }, + { 0x10DE0311, "0x0311" }, + { 0x10DE0312, "0x0312" }, + { 0x10DE0316, "0x0316" }, + { 0x10DE0317, "0x0317" }, + { 0x10DE0318, "0x0318" }, + { 0x10DE0319, "0x0319" }, + { 0x10DE031A, "0x031A" }, + { 0x10DE031B, "0x031B" }, + { 0x10DE031C, "0x031C" }, + { 0x10DE031D, "0x031D" }, + { 0x10DE031E, "0x031E" }, + { 0x10DE031F, "0x031F" }, + { 0x10DE0321, "0x0321" }, + { 0x10DE0322, "0x0322" }, + { 0x10DE0323, "0x0323" }, + { 0x10DE0326, "0x0326" }, + { 0x10DE032A, "0x032A" }, + { 0x10DE032B, "0x032B" }, + { 0x10DE032E, "0x032E" }, + {-1, NULL} +}; + + +/* + * List of symbols from other modules that this module references. This + * list is used to tell the loader that it is OK for symbols here to be + * unresolved providing that it hasn't been told that they haven't been + * told that they are essential via a call to xf86LoaderReqSymbols() or + * xf86LoaderReqSymLists(). The purpose is this is to avoid warnings about + * unresolved symbols that are not required. + */ + +static const char *vgahwSymbols[] = { + "vgaHWDPMSSet", + "vgaHWFreeHWRec", + "vgaHWGetHWRec", + "vgaHWGetIndex", + "vgaHWInit", + "vgaHWMapMem", + "vgaHWProtect", + "vgaHWRestore", + "vgaHWSave", + "vgaHWSaveScreen", + "vgaHWddc1SetSpeed", + NULL +}; + +static const char *fbSymbols[] = { + "fbPictureInit", + "fbScreenInit", + NULL +}; + +static const char *xaaSymbols[] = { + "XAACopyROP", + "XAACreateInfoRec", + "XAADestroyInfoRec", + "XAAFallbackOps", + "XAAInit", + "XAAPatternROP", + NULL +}; + +static const char *ramdacSymbols[] = { + "xf86CreateCursorInfoRec", + "xf86DestroyCursorInfoRec", + "xf86InitCursor", + NULL +}; + +#define NVuseI2C 1 + +static const char *ddcSymbols[] = { + "xf86PrintEDID", + "xf86DoEDID_DDC1", +#if NVuseI2C + "xf86DoEDID_DDC2", +#endif + "xf86SetDDCproperties", + NULL +}; + +static const char *vbeSymbols[] = { + "VBEInit", + "vbeDoEDID", + "vbeFree", + NULL +}; + +static const char *i2cSymbols[] = { + "xf86CreateI2CBusRec", + "xf86I2CBusInit", + NULL +}; + +static const char *shadowSymbols[] = { + "ShadowFBInit", + NULL +}; + +static const char *fbdevHWSymbols[] = { + "fbdevHWInit", + "fbdevHWUseBuildinMode", + + "fbdevHWGetVidmem", + + /* colormap */ + "fbdevHWLoadPalette", + + /* ScrnInfo hooks */ + "fbdevHWAdjustFrame", + "fbdevHWEnterVT", + "fbdevHWLeaveVT", + "fbdevHWModeInit", + "fbdevHWSave", + "fbdevHWSwitchMode", + "fbdevHWValidMode", + + "fbdevHWMapMMIO", + "fbdevHWMapVidmem", + + NULL +}; + +static const char *int10Symbols[] = { + "xf86FreeInt10", + "xf86InitInt10", + NULL +}; + + +#ifdef XFree86LOADER + +static MODULESETUPPROTO(nvSetup); + +static XF86ModuleVersionInfo nvVersRec = +{ + "nv", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XF86_VERSION_CURRENT, + NV_MAJOR_VERSION, NV_MINOR_VERSION, NV_PATCHLEVEL, + ABI_CLASS_VIDEODRV, /* This is a video driver */ + ABI_VIDEODRV_VERSION, + MOD_CLASS_VIDEODRV, + {0,0,0,0} +}; + +XF86ModuleData nvModuleData = { &nvVersRec, nvSetup, NULL }; +#endif + + +typedef enum { + OPTION_SW_CURSOR, + OPTION_HW_CURSOR, + OPTION_NOACCEL, + OPTION_SHOWCACHE, + OPTION_SHADOW_FB, + OPTION_FBDEV, + OPTION_ROTATE, + OPTION_VIDEO_KEY, + OPTION_FLAT_PANEL, + OPTION_FP_DITHER, + OPTION_CRTC_NUMBER +} NVOpts; + + +static const OptionInfoRec NVOptions[] = { + { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, + { OPTION_FLAT_PANEL, "FlatPanel", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_FP_DITHER, "FPDither", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_CRTC_NUMBER, "CrtcNumber", OPTV_INTEGER, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + +/* + * This is intentionally screen-independent. It indicates the binding + * choice made in the first PreInit. + */ +static int pix24bpp = 0; + +/* + * ramdac info structure initialization + */ +static NVRamdacRec DacInit = { + FALSE, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL, NULL +}; + + + +static Bool +NVGetRec(ScrnInfoPtr pScrn) +{ + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVGetRec\n")); + /* + * Allocate an NVRec, and hook it into pScrn->driverPrivate. + * pScrn->driverPrivate is initialised to NULL, so we can check if + * the allocation has already been done. + */ + if (pScrn->driverPrivate != NULL) + return TRUE; + + pScrn->driverPrivate = xnfcalloc(sizeof(NVRec), 1); + /* Initialise it */ + + NVPTR(pScrn)->Dac = DacInit; + return TRUE; +} + +static void +NVFreeRec(ScrnInfoPtr pScrn) +{ + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVFreeRec\n")); + + if (pScrn->driverPrivate == NULL) + return; + xfree(pScrn->driverPrivate); + pScrn->driverPrivate = NULL; +} + + +#ifdef XFree86LOADER + +static pointer +nvSetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = FALSE; + + /* This module should be loaded only once, but check to be sure. */ + + if (!setupDone) { + setupDone = TRUE; + xf86AddDriver(&NV, module, 0); + + /* + * Modules that this driver always requires may be loaded here + * by calling LoadSubModule(). + */ + + /* + * Tell the loader about symbols from other modules that this module + * might refer to. + */ + LoaderRefSymLists(vgahwSymbols, xaaSymbols, fbSymbols, + ramdacSymbols, shadowSymbols, + i2cSymbols, ddcSymbols, vbeSymbols, + fbdevHWSymbols, int10Symbols, NULL); + + /* + * The return value must be non-NULL on success even though there + * is no TearDownProc. + */ + return (pointer)1; + } else { + if (errmaj) *errmaj = LDR_ONCEONLY; + return NULL; + } +} + + +#endif /* XFree86LOADER */ + +static const OptionInfoRec * +NVAvailableOptions(int chipid, int busid) +{ + return NVOptions; +} + +/* Mandatory */ +static void +NVIdentify(int flags) +{ + xf86PrintChipsets(NV_NAME, "driver for NVIDIA chipsets", NVKnownChipsets); +} + + +#define MAX_CHIPS MAXSCREENS + +/* Mandatory */ +static Bool +NVProbe(DriverPtr drv, int flags) +{ + int i; + GDevPtr *devSections; + int *usedChips; + SymTabRec NVChipsets[MAX_CHIPS + 1]; + PciChipsets NVPciChipsets[MAX_CHIPS + 1]; + pciVideoPtr *ppPci; + int numDevSections; + int numUsed; + Bool foundScreen = FALSE; + + + if ((numDevSections = xf86MatchDevice(NV_DRIVER_NAME, &devSections)) <= 0) + return FALSE; /* no matching device section */ + + if (!(ppPci = xf86GetPciVideoInfo())) + return FALSE; /* no PCI cards found */ + + numUsed = 0; + + /* Create the NVChipsets and NVPciChipsets from found devices */ + while (*ppPci && (numUsed < MAX_CHIPS)) { + if(((*ppPci)->vendor == PCI_VENDOR_NVIDIA_SGS) || + ((*ppPci)->vendor == PCI_VENDOR_NVIDIA)) + { + SymTabRec *nvchips = NVKnownChipsets; + int token = ((*ppPci)->vendor << 16) | (*ppPci)->chipType; + + while(nvchips->name) { + if(token == nvchips->token) + break; + nvchips++; + } + + if(nvchips->name) { /* found one */ + NVChipsets[numUsed].token = nvchips->token; + NVChipsets[numUsed].name = nvchips->name; + NVPciChipsets[numUsed].numChipset = nvchips->token; + NVPciChipsets[numUsed].PCIid = nvchips->token; + 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: + NVChipsets[numUsed].token = token; + NVChipsets[numUsed].name = "Unknown NVIDIA chip"; + NVPciChipsets[numUsed].numChipset = token; + NVPciChipsets[numUsed].PCIid = token; + NVPciChipsets[numUsed].resList = RES_SHARED_VGA; + numUsed++; + break; + default: break; /* we don't recognize it */ + } + } + } + ppPci++; + } + + /* terminate the list */ + NVChipsets[numUsed].token = -1; + NVChipsets[numUsed].name = NULL; + NVPciChipsets[numUsed].numChipset = -1; + NVPciChipsets[numUsed].PCIid = -1; + NVPciChipsets[numUsed].resList = RES_UNDEFINED; + + numUsed = xf86MatchPciInstances(NV_NAME, 0, NVChipsets, NVPciChipsets, + devSections, numDevSections, drv, + &usedChips); + + if (numUsed <= 0) + return FALSE; + + if (flags & PROBE_DETECT) + foundScreen = TRUE; + else for (i = 0; i < numUsed; i++) { + ScrnInfoPtr pScrn = NULL; + + /* Allocate a ScrnInfoRec and claim the slot */ + if ((pScrn = xf86ConfigPciEntity(pScrn, 0,usedChips[i], + NVPciChipsets, NULL, NULL, NULL, + NULL, NULL))) { + + /* Fill in what we can of the ScrnInfoRec */ + pScrn->driverVersion = VERSION; + pScrn->driverName = NV_DRIVER_NAME; + pScrn->name = NV_NAME; + pScrn->Probe = NVProbe; + pScrn->PreInit = NVPreInit; + pScrn->ScreenInit = NVScreenInit; + pScrn->SwitchMode = NVSwitchMode; + pScrn->AdjustFrame = NVAdjustFrame; + pScrn->EnterVT = NVEnterVT; + pScrn->LeaveVT = NVLeaveVT; + pScrn->FreeScreen = NVFreeScreen; + pScrn->ValidMode = NVValidMode; + foundScreen = TRUE; + } + } + + xfree(devSections); + xfree(usedChips); + + return foundScreen; +} + +/* Usually mandatory */ +Bool +NVSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) +{ + DEBUG(xf86DrvMsg(scrnIndex, X_INFO, "NVSwitchMode\n")); + return NVModeInit(xf86Screens[scrnIndex], mode); +} + +/* + * This function is used to initialize the Start Address - the first + * displayed location in the video memory. + */ +/* Usually mandatory */ +void +NVAdjustFrame(int scrnIndex, int x, int y, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + int startAddr; + NVPtr pNv = NVPTR(pScrn); + NVFBLayout *pLayout = &pNv->CurrentLayout; + + DEBUG(xf86DrvMsg(scrnIndex, X_INFO, "NVAdjustFrame\n")); + + if(pNv->ShowCache && y && pScrn->vtSema) + y += pScrn->virtualY - 1; + + startAddr = (((y*pLayout->displayWidth)+x)*(pLayout->bitsPerPixel/8)); + pNv->riva.SetStartAddress(&pNv->riva, startAddr); +} + + +/* + * This is called when VT switching back to the X server. Its job is + * to reinitialise the video mode. + * + * We may wish to unmap video/MMIO memory too. + */ + +/* Mandatory */ +static Bool +NVEnterVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + NVPtr pNv = NVPTR(pScrn); + + DEBUG(xf86DrvMsg(scrnIndex, X_INFO, "NVEnterVT\n")); + + if (!NVModeInit(pScrn, pScrn->currentMode)) + return FALSE; + NVAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + + if(pNv->overlayAdaptor) + NVResetVideo(pScrn); + return TRUE; +} + +static Bool +NVEnterVTFBDev(int scrnIndex, int flags) +{ + DEBUG(xf86DrvMsg(scrnIndex, X_INFO, "NVEnterVTFBDev\n")); + + fbdevHWEnterVT(scrnIndex,flags); + return TRUE; +} + +/* + * This is called when VT switching away from the X server. Its job is + * to restore the previous (text) mode. + * + * We may wish to remap video/MMIO memory too. + */ + +/* Mandatory */ +static void +NVLeaveVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + NVPtr pNv = NVPTR(pScrn); + + DEBUG(xf86DrvMsg(scrnIndex, X_INFO, "NVLeaveVT\n")); + + NVRestore(pScrn); + pNv->riva.LockUnlock(&pNv->riva, 1); +} + + + +static void +NVBlockHandler ( + int i, + pointer blockData, + pointer pTimeout, + pointer pReadmask +) +{ + ScreenPtr pScreen = screenInfo.screens[i]; + ScrnInfoPtr pScrnInfo = xf86Screens[i]; + NVPtr pNv = NVPTR(pScrnInfo); + + pScreen->BlockHandler = pNv->BlockHandler; + (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); + pScreen->BlockHandler = NVBlockHandler; + + if (pNv->VideoTimerCallback) + (*pNv->VideoTimerCallback)(pScrnInfo, currentTime.milliseconds); + +} + + +/* + * This is called at the end of each server generation. It restores the + * original (text) mode. It should also unmap the video memory, and free + * any per-generation data allocated by the driver. It should finish + * by unwrapping and calling the saved CloseScreen function. + */ + +/* Mandatory */ +static Bool +NVCloseScreen(int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + NVPtr pNv = NVPTR(pScrn); + + DEBUG(xf86DrvMsg(scrnIndex, X_INFO, "NVCloseScreen\n")); + + if (pScrn->vtSema) { + NVRestore(pScrn); + pNv->riva.LockUnlock(&pNv->riva, 1); + } + + NVUnmapMem(pScrn); + vgaHWUnmapMem(pScrn); + if (pNv->AccelInfoRec) + XAADestroyInfoRec(pNv->AccelInfoRec); + if (pNv->CursorInfoRec) + xf86DestroyCursorInfoRec(pNv->CursorInfoRec); + if (pNv->ShadowPtr) + xfree(pNv->ShadowPtr); + if (pNv->DGAModes) + xfree(pNv->DGAModes); + if ( pNv->expandBuffer ) + xfree(pNv->expandBuffer); + if (pNv->overlayAdaptor) + xfree(pNv->overlayAdaptor); + + pScrn->vtSema = FALSE; + pScreen->CloseScreen = pNv->CloseScreen; + pScreen->BlockHandler = pNv->BlockHandler; + return (*pScreen->CloseScreen)(scrnIndex, pScreen); +} + +/* Free up any persistent data structures */ + +/* Optional */ +static void +NVFreeScreen(int scrnIndex, int flags) +{ + DEBUG(xf86DrvMsg(scrnIndex, X_INFO, "NVFreeScreen\n")); + /* + * This only gets called when a screen is being deleted. It does not + * get called routinely at the end of a server generation. + */ + if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) + vgaHWFreeHWRec(xf86Screens[scrnIndex]); + NVFreeRec(xf86Screens[scrnIndex]); +} + + +/* Checks if a mode is suitable for the selected chipset. */ + +/* Optional */ +static int +NVValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) +{ + DEBUG(xf86DrvMsg(scrnIndex, X_INFO, "NVValidMode\n")); + /* HACK HACK HACK */ + return (MODE_OK); +} + +static xf86MonPtr +nvDoDDC2(ScrnInfoPtr pScrn) +{ + NVPtr pNv = NVPTR(pScrn); + xf86MonPtr MonInfo = NULL; + + if (!pNv->i2cInit) return NULL; + + /* - DDC can use I2C bus */ + /* Load I2C if we have the code to use it */ + if ( xf86LoadSubModule(pScrn, "i2c") ) { + xf86LoaderReqSymLists(i2cSymbols,NULL); + if (pNv->i2cInit(pScrn)) { + DEBUG(ErrorF("I2C initialized on %p\n",pNv->I2C)); + if ((MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,pNv->I2C))) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DDC Monitor info: %p\n", + MonInfo); + xf86PrintEDID( MonInfo ); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of DDC Monitor " + "info\n\n"); + xf86SetDDCproperties(pScrn,MonInfo); + } + } + } + return MonInfo; +} + +#if 0 +static xf86MonPtr +nvDoDDC1(ScrnInfoPtr pScrn) +{ + NVPtr pNv = NVPTR(pScrn); + xf86MonPtr MonInfo = NULL; + + if (!pNv->ddc1Read || !pNv->DDC1SetSpeed) return NULL; + if (!pNv->Primary + && (pNv->DDC1SetSpeed == vgaHWddc1SetSpeed)) return NULL; + + if ((MonInfo = xf86DoEDID_DDC1(pScrn->scrnIndex, pNv->DDC1SetSpeed, + pNv->ddc1Read ))) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DDC Monitor info: %p\n", + MonInfo); + xf86PrintEDID( MonInfo ); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of DDC Monitor info\n\n"); + xf86SetDDCproperties(pScrn,MonInfo); + } + return MonInfo; +} +#endif + +/* +static xf86MonPtr +nvDoDDCVBE(ScrnInfoPtr pScrn) +{ + NVPtr pNv = NVPTR(pScrn); + xf86MonPtr MonInfo = NULL; + vbeInfoPtr pVbe; + + if (xf86LoadSubModule(pScrn, "vbe")) { + xf86LoaderReqSymLists(vbeSymbols,NULL); + pVbe = VBEInit(pNv->pInt,pNv->pEnt->index); + if (pVbe) { + if ((MonInfo = vbeDoEDID(pVbe,NULL))) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DDC Monitor info: %p\n", + MonInfo); + xf86PrintEDID( MonInfo ); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of DDC Monitor info\n\n"); + xf86SetDDCproperties(pScrn,MonInfo); + } + vbeFree(pVbe); + } + } + return MonInfo; +} +*/ + +/* Internally used */ +xf86MonPtr +NVdoDDC(ScrnInfoPtr pScrn) +{ + NVPtr pNv; + NVRamdacPtr NVdac; + xf86MonPtr MonInfo = NULL; + + pNv = NVPTR(pScrn); + NVdac = &pNv->Dac; + + /* Load DDC if we have the code to use it */ + + if (!xf86LoadSubModule(pScrn, "ddc")) return NULL; + + xf86LoaderReqSymLists(ddcSymbols, NULL); + + /* if ((MonInfo = nvDoDDCVBE(pScrn))) return MonInfo; */ + + /* Enable access to extended registers */ + pNv->riva.LockUnlock(&pNv->riva, 0); + /* Save the current state */ + NVSave(pScrn); + + if ((MonInfo = nvDoDDC2(pScrn))) goto done; +#if 0 /* disable for now - causes problems on AXP */ + if ((MonInfo = nvDoDDC1(pScrn))) goto done; +#endif + + done: + /* Restore previous state */ + NVRestore(pScrn); + pNv->riva.LockUnlock(&pNv->riva, 1); + + return MonInfo; +} + +static void +nvProbeDDC(ScrnInfoPtr pScrn, int index) +{ + vbeInfoPtr pVbe; + + if (xf86LoadSubModule(pScrn, "vbe")) { + pVbe = VBEInit(NULL,index); + ConfiguredMonitor = vbeDoEDID(pVbe, NULL); + vbeFree(pVbe); + } +} + +/* Mandatory */ +Bool +NVPreInit(ScrnInfoPtr pScrn, int flags) +{ + NVPtr pNv; + MessageType from; + int i; + int bytesPerPixel; + ClockRangePtr clockRanges; + const char *s; + + if (flags & PROBE_DETECT) { + nvProbeDDC( pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index ); + return TRUE; + } + + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVPreInit\n")); + /* + * Note: This function is only called once at server startup, and + * not at the start of each server generation. This means that + * only things that are persistent across server generations can + * be initialised here. xf86Screens[] is (pScrn is a pointer to one + * of these). Privates allocated using xf86AllocateScrnInfoPrivateIndex() + * are too, and should be used for data that must persist across + * server generations. + * + * Per-generation data should be allocated with + * AllocateScreenPrivateIndex() from the ScreenInit() function. + */ + + /* Check the number of entities, and fail if it isn't one. */ + if (pScrn->numEntities != 1) + return FALSE; + + /* Allocate the NVRec driverPrivate */ + if (!NVGetRec(pScrn)) { + return FALSE; + } + pNv = NVPTR(pScrn); + + /* Get the entity, and make sure it is PCI. */ + pNv->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + if (pNv->pEnt->location.type != BUS_PCI) + return FALSE; + + /* Find the PCI info for this screen */ + pNv->PciInfo = xf86GetPciInfoForEntity(pNv->pEnt->index); + pNv->PciTag = pciTag(pNv->PciInfo->bus, pNv->PciInfo->device, + pNv->PciInfo->func); + + pNv->Primary = xf86IsPrimaryPci(pNv->PciInfo); + + /* Initialize the card through int10 interface if needed */ + if (xf86LoadSubModule(pScrn, "int10")) { + xf86LoaderReqSymLists(int10Symbols, NULL); +#if !defined(__alpha__) && !defined(__powerpc__) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing int10\n"); + pNv->pInt = xf86InitInt10(pNv->pEnt->index); +#endif + } + + xf86SetOperatingState(resVgaIo, pNv->pEnt->index, ResUnusedOpr); + xf86SetOperatingState(resVgaMem, pNv->pEnt->index, ResDisableOpr); + + /* Set pScrn->monitor */ + pScrn->monitor = pScrn->confScreen->monitor; + + /* + * Set the Chipset and ChipRev, allowing config file entries to + * override. + */ + if (pNv->pEnt->device->chipset && *pNv->pEnt->device->chipset) { + pScrn->chipset = pNv->pEnt->device->chipset; + pNv->Chipset = xf86StringToToken(NVKnownChipsets, pScrn->chipset); + from = X_CONFIG; + } else if (pNv->pEnt->device->chipID >= 0) { + pNv->Chipset = pNv->pEnt->device->chipID; + pScrn->chipset = (char *)xf86TokenToString(NVKnownChipsets, + pNv->Chipset); + from = X_CONFIG; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", + pNv->Chipset); + } else { + from = X_PROBED; + pNv->Chipset = (pNv->PciInfo->vendor << 16) | pNv->PciInfo->chipType; + pScrn->chipset = (char *)xf86TokenToString(NVKnownChipsets, + pNv->Chipset); + if(!pScrn->chipset) + pScrn->chipset = "Unknown NVIDIA chipset"; + } + if (pNv->pEnt->device->chipRev >= 0) { + pNv->ChipRev = pNv->pEnt->device->chipRev; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", + pNv->ChipRev); + } else { + pNv->ChipRev = pNv->PciInfo->chipRev; + } + + /* + * This shouldn't happen because such problems should be caught in + * NVProbe(), but check it just in case. + */ + if (pScrn->chipset == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "ChipID 0x%04X is not recognised\n", pNv->Chipset); + xf86FreeInt10(pNv->pInt); + return FALSE; + } + if (pNv->Chipset < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Chipset \"%s\" is not recognised\n", pScrn->chipset); + xf86FreeInt10(pNv->pInt); + return FALSE; + } + + xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset); + + + /* + * The first thing we should figure out is the depth, bpp, etc. + * Our default depth is 8, so pass it to the helper function. + */ + + if (!xf86SetDepthBpp(pScrn, 8, 8, 8, Support32bppFb)) { + xf86FreeInt10(pNv->pInt); + return FALSE; + } else { + /* Check that the returned depth is one we support */ + switch (pScrn->depth) { + case 8: + case 15: + case 24: + /* OK */ + break; + case 16: + if((pNv->Chipset & 0xffff) == 0x0018) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "The Riva 128 chipset does not support depth 16. " + "Using depth 15 instead\n"); + pScrn->depth = 15; + } + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Given depth (%d) is not supported by this driver\n", + pScrn->depth); + xf86FreeInt10(pNv->pInt); + return FALSE; + } + } + xf86PrintDepthBpp(pScrn); + + /* Get the depth24 pixmap format */ + if (pScrn->depth == 24 && pix24bpp == 0) + pix24bpp = xf86GetBppFromDepth(pScrn, 24); + + /* + * This must happen after pScrn->display has been set because + * xf86SetWeight references it. + */ + if (pScrn->depth > 8) { + /* The defaults are OK for us */ + rgb zeros = {0, 0, 0}; + + if (!xf86SetWeight(pScrn, zeros, zeros)) { + xf86FreeInt10(pNv->pInt); + return FALSE; + } + } + + if (!xf86SetDefaultVisual(pScrn, -1)) { + xf86FreeInt10(pNv->pInt); + return FALSE; + } else { + /* We don't currently support DirectColor at > 8bpp */ + if (pScrn->depth > 8 && (pScrn->defaultVisual != TrueColor)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual" + " (%s) is not supported at depth %d\n", + xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); + xf86FreeInt10(pNv->pInt); + return FALSE; + } + } + + bytesPerPixel = pScrn->bitsPerPixel / 8; + + /* The vgahw module should be loaded here when needed */ + if (!xf86LoadSubModule(pScrn, "vgahw")) { + xf86FreeInt10(pNv->pInt); + return FALSE; + } + + xf86LoaderReqSymLists(vgahwSymbols, NULL); + + /* + * Allocate a vgaHWRec + */ + if (!vgaHWGetHWRec(pScrn)) { + xf86FreeInt10(pNv->pInt); + return FALSE; + } + + /* We use a programmable clock */ + pScrn->progClock = TRUE; + + /* Collect all of the relevant option flags (fill in pScrn->options) */ + xf86CollectOptions(pScrn, NULL); + + /* Process the options */ + if (!(pNv->Options = xalloc(sizeof(NVOptions)))) + return FALSE; + memcpy(pNv->Options, NVOptions, sizeof(NVOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pNv->Options); + + /* Set the bits per RGB for 8bpp mode */ + if (pScrn->depth == 8) + pScrn->rgbBits = 8; + + from = X_DEFAULT; + pNv->HWCursor = TRUE; + /* + * The preferred method is to use the "hw cursor" option as a tri-state + * option, with the default set above. + */ + if (xf86GetOptValBool(pNv->Options, OPTION_HW_CURSOR, &pNv->HWCursor)) { + from = X_CONFIG; + } + /* For compatibility, accept this too (as an override) */ + if (xf86ReturnOptValBool(pNv->Options, OPTION_SW_CURSOR, FALSE)) { + from = X_CONFIG; + pNv->HWCursor = FALSE; + } + xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", + pNv->HWCursor ? "HW" : "SW"); + if (xf86ReturnOptValBool(pNv->Options, OPTION_NOACCEL, FALSE)) { + pNv->NoAccel = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); + } + if (xf86ReturnOptValBool(pNv->Options, OPTION_SHOWCACHE, FALSE)) { + pNv->ShowCache = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShowCache enabled\n"); + } + if (xf86ReturnOptValBool(pNv->Options, OPTION_SHADOW_FB, FALSE)) { + pNv->ShadowFB = TRUE; + pNv->NoAccel = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using \"Shadow Framebuffer\" - acceleration disabled\n"); + } + if (xf86ReturnOptValBool(pNv->Options, OPTION_FBDEV, FALSE)) { + pNv->FBDev = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using framebuffer device\n"); + } + if (pNv->FBDev) { + /* check for linux framebuffer device */ + if (!xf86LoadSubModule(pScrn, "fbdevhw")) { + xf86FreeInt10(pNv->pInt); + return FALSE; + } + + xf86LoaderReqSymLists(fbdevHWSymbols, NULL); + if (!fbdevHWInit(pScrn, pNv->PciInfo, NULL)) { + xf86FreeInt10(pNv->pInt); + return FALSE; + } + pScrn->SwitchMode = fbdevHWSwitchMode; + pScrn->AdjustFrame = fbdevHWAdjustFrame; + pScrn->EnterVT = NVEnterVTFBDev; + pScrn->LeaveVT = fbdevHWLeaveVT; + pScrn->ValidMode = fbdevHWValidMode; + } + pNv->Rotate = 0; + if ((s = xf86GetOptValString(pNv->Options, OPTION_ROTATE))) { + if(!xf86NameCmp(s, "CW")) { + pNv->ShadowFB = TRUE; + pNv->NoAccel = TRUE; + pNv->HWCursor = FALSE; + pNv->Rotate = 1; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Rotating screen clockwise - acceleration disabled\n"); + } else + if(!xf86NameCmp(s, "CCW")) { + pNv->ShadowFB = TRUE; + pNv->NoAccel = TRUE; + pNv->HWCursor = FALSE; + pNv->Rotate = -1; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Rotating screen counter clockwise - acceleration disabled\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "\"%s\" is not a valid value for Option \"Rotate\"\n", s); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid options are \"CW\" or \"CCW\"\n"); + } + } + if(xf86GetOptValInteger(pNv->Options, OPTION_VIDEO_KEY, &(pNv->videoKey))) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n", + pNv->videoKey); + } else { + pNv->videoKey = (1 << pScrn->offset.red) | + (1 << pScrn->offset.green) | + (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue); + } + + if (xf86GetOptValBool(pNv->Options, OPTION_FLAT_PANEL, &(pNv->FlatPanel))) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "forcing %s usage\n", + pNv->FlatPanel ? "DFP" : "CRTC"); + } else { + pNv->FlatPanel = -1; /* autodetect later */ + } + + pNv->FPDither = FALSE; + if (xf86GetOptValBool(pNv->Options, OPTION_FP_DITHER, &(pNv->FPDither))) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "enabling flat panel dither\n"); + + if (xf86GetOptValInteger(pNv->Options, OPTION_CRTC_NUMBER, + &pNv->forceCRTC)) + { + if((pNv->forceCRTC < 0) || (pNv->forceCRTC > 1)) { + pNv->forceCRTC = -1; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Invalid CRTC number. Must be 0 or 1\n"); + } + } else pNv->forceCRTC = -1; + + + 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)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "MemBase 0x%08lX doesn't match any PCI base register.\n", + pNv->pEnt->device->MemBase); + xf86FreeInt10(pNv->pInt); + NVFreeRec(pScrn); + return FALSE; + } + pNv->FbAddress = pNv->pEnt->device->MemBase; + from = X_CONFIG; + } else { + int i = 1; + pNv->FbBaseReg = i; + if (pNv->PciInfo->memBase[i] != 0) { + pNv->FbAddress = pNv->PciInfo->memBase[i] & 0xff800000; + from = X_PROBED; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No valid FB address in PCI config space\n"); + xf86FreeInt10(pNv->pInt); + NVFreeRec(pScrn); + return FALSE; + } + } + xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", + (unsigned long)pNv->FbAddress); + + if (pNv->pEnt->device->IOBase != 0) { + /* Require that the config file value matches one of the PCI values. */ + if (!xf86CheckPciMemBase(pNv->PciInfo, pNv->pEnt->device->IOBase)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "IOBase 0x%08lX doesn't match any PCI base register.\n", + pNv->pEnt->device->IOBase); + xf86FreeInt10(pNv->pInt); + NVFreeRec(pScrn); + return FALSE; + } + pNv->IOAddress = pNv->pEnt->device->IOBase; + from = X_CONFIG; + } else { + int i = 0; + if (pNv->PciInfo->memBase[i] != 0) { + pNv->IOAddress = pNv->PciInfo->memBase[i] & 0xffffc000; + from = X_PROBED; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No valid MMIO address in PCI config space\n"); + xf86FreeInt10(pNv->pInt); + NVFreeRec(pScrn); + return FALSE; + } + } + xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX\n", + (unsigned long)pNv->IOAddress); + + if (xf86RegisterResources(pNv->pEnt->index, NULL, ResExclusive)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "xf86RegisterResources() found resource conflicts\n"); + xf86FreeInt10(pNv->pInt); + NVFreeRec(pScrn); + return FALSE; + } + + pNv->alphaCursor = ((pNv->Chipset & 0x0ff0) >= 0x0110); + + switch (pNv->Chipset & 0x0ff0) { + case 0x0010: + NV3Setup(pScrn); + break; + case 0x0020: + case 0x00A0: + NV4Setup(pScrn); + break; + case 0x0100: + case 0x0110: + case 0x0150: + case 0x0170: + case 0x0180: + case 0x01A0: + case 0x01F0: + NV10Setup(pScrn); + break; + case 0x0200: + case 0x0250: + case 0x0280: + case 0x0300: + case 0x0310: + case 0x0320: + case 0x0330: + case 0x0340: + NV20Setup(pScrn); + break; + } + + /* + * If the user has specified the amount of memory in the XF86Config + * file, we respect that setting. + */ + if (pNv->pEnt->device->videoRam != 0) { + pScrn->videoRam = pNv->pEnt->device->videoRam; + from = X_CONFIG; + } else { + if (pNv->FBDev) { + pScrn->videoRam = fbdevHWGetVidmem(pScrn)/1024; + } else { + pScrn->videoRam = pNv->riva.RamAmountKBytes; + } + from = X_PROBED; + } + xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kBytes\n", + pScrn->videoRam); + + pNv->FbMapSize = pScrn->videoRam * 1024; + + /* + * If the driver can do gamma correction, it should call xf86SetGamma() + * here. + */ + + { + Gamma zeros = {0.0, 0.0, 0.0}; + + if (!xf86SetGamma(pScrn, zeros)) { + xf86FreeInt10(pNv->pInt); + return FALSE; + } + } + + pNv->FbUsableSize = pNv->FbMapSize; + + /* Remove reserved memory from end of buffer */ + switch( pNv->riva.Architecture ) { + case NV_ARCH_03: + pNv->FbUsableSize -= 32 * 1024; + break; + case NV_ARCH_04: + case NV_ARCH_10: + case NV_ARCH_20: + default: + pNv->FbUsableSize -= 128 * 1024; + break; + } + + + /* + * Setup the ClockRanges, which describe what clock ranges are available, + * and what sort of modes they can be used for. + */ + + pNv->MinClock = 12000; + pNv->MaxClock = pNv->riva.MaxVClockFreqKHz; + + clockRanges = xnfcalloc(sizeof(ClockRange), 1); + clockRanges->next = NULL; + clockRanges->minClock = pNv->MinClock; + clockRanges->maxClock = pNv->MaxClock; + clockRanges->clockIndex = -1; /* programmable */ + if(((pNv->Chipset & 0x0ff0) <= 0x0100) || + ((pNv->Chipset & 0x0ff0) == 0x0150)) + { + clockRanges->interlaceAllowed = TRUE; + } else /* Chips after NV15 (including NV11) do not support interlaced */ + clockRanges->interlaceAllowed = FALSE; + clockRanges->doubleScanAllowed = TRUE; + + if(pNv->FlatPanel == 1) { + clockRanges->interlaceAllowed = FALSE; + clockRanges->doubleScanAllowed = FALSE; + } + + /* + * 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, 2048, + 32 * pScrn->bitsPerPixel, 128, 2048, + pScrn->display->virtualX, + pScrn->display->virtualY, + pNv->FbUsableSize, + LOOKUP_BEST_REFRESH); + + if (i < 1 && pNv->FBDev) { + fbdevHWUseBuildinMode(pScrn); + pScrn->displayWidth = pScrn->virtualX; /* FIXME: might be wrong */ + i = 1; + } + if (i == -1) { + xf86FreeInt10(pNv->pInt); + NVFreeRec(pScrn); + return FALSE; + } + + /* Prune the modes marked as invalid */ + xf86PruneDriverModes(pScrn); + + if (i == 0 || pScrn->modes == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); + xf86FreeInt10(pNv->pInt); + NVFreeRec(pScrn); + return FALSE; + } + + /* + * Set the CRTC parameters for all of the modes based on the type + * of mode, and the chipset's interlace requirements. + * + * Calling this is required if the mode->Crtc* values are used by the + * driver and if the driver doesn't provide code to set them. They + * are not pre-initialised at all. + */ + xf86SetCrtcForModes(pScrn, 0); + + /* Set the current mode to the first in the list */ + pScrn->currentMode = pScrn->modes; + + /* Print the list of modes being used */ + xf86PrintModes(pScrn); + + /* Set display resolution */ + xf86SetDpi(pScrn, 0, 0); + + + /* + * XXX This should be taken into account in some way in the mode valdation + * section. + */ + + if (xf86LoadSubModule(pScrn, "fb") == NULL) { + xf86FreeInt10(pNv->pInt); + NVFreeRec(pScrn); + return FALSE; + } + + xf86LoaderReqSymLists(fbSymbols, NULL); + + /* Load XAA if needed */ + if (!pNv->NoAccel) { + if (!xf86LoadSubModule(pScrn, "xaa")) { + xf86FreeInt10(pNv->pInt); + NVFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(xaaSymbols, NULL); + } + + /* Load ramdac if needed */ + if (pNv->HWCursor) { + if (!xf86LoadSubModule(pScrn, "ramdac")) { + xf86FreeInt10(pNv->pInt); + NVFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(ramdacSymbols, NULL); + } + + /* Load shadowfb if needed */ + if (pNv->ShadowFB) { + if (!xf86LoadSubModule(pScrn, "shadowfb")) { + xf86FreeInt10(pNv->pInt); + NVFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(shadowSymbols, NULL); + } + + pNv->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel; + pNv->CurrentLayout.depth = pScrn->depth; + pNv->CurrentLayout.displayWidth = pScrn->displayWidth; + pNv->CurrentLayout.weight.red = pScrn->weight.red; + pNv->CurrentLayout.weight.green = pScrn->weight.green; + pNv->CurrentLayout.weight.blue = pScrn->weight.blue; + pNv->CurrentLayout.mode = pScrn->currentMode; + + xf86FreeInt10(pNv->pInt); + + pNv->pInt = NULL; + return TRUE; +} + + +/* + * Map the framebuffer and MMIO memory. + */ + +static Bool +NVMapMem(ScrnInfoPtr pScrn) +{ + NVPtr pNv; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVMapMem\n")); + pNv = NVPTR(pScrn); + + /* + * Map IO registers to virtual address space + */ + pNv->IOBase = xf86MapPciMem(pScrn->scrnIndex, + VIDMEM_MMIO | VIDMEM_READSIDEEFFECT, + pNv->PciTag, pNv->IOAddress, 0x1000000); + if (pNv->IOBase == NULL) + return FALSE; + + pNv->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, + pNv->PciTag, pNv->FbAddress, + pNv->FbMapSize); + if (pNv->FbBase == NULL) + return FALSE; + + pNv->FbStart = pNv->FbBase; + + return TRUE; +} + +Bool +NVMapMemFBDev(ScrnInfoPtr pScrn) +{ + NVPtr pNv; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVMamMemFBDev\n")); + pNv = NVPTR(pScrn); + + pNv->FbBase = fbdevHWMapVidmem(pScrn); + if (pNv->FbBase == NULL) + return FALSE; + + pNv->IOBase = fbdevHWMapMMIO(pScrn); + if (pNv->IOBase == NULL) + return FALSE; + + pNv->FbStart = pNv->FbBase; + + return TRUE; +} + +/* + * Unmap the framebuffer and MMIO memory. + */ + +static Bool +NVUnmapMem(ScrnInfoPtr pScrn) +{ + NVPtr pNv; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVUnmapMem\n")); + pNv = NVPTR(pScrn); + + /* + * Unmap IO registers to virtual address space + */ + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pNv->IOBase, 0x1000000); + pNv->IOBase = NULL; + + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pNv->FbBase, pNv->FbMapSize); + pNv->FbBase = NULL; + pNv->FbStart = NULL; + + return TRUE; +} + + +/* + * Initialise a new mode. + */ + +static Bool +NVModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + vgaRegPtr vgaReg; + NVPtr pNv = NVPTR(pScrn); + NVRegPtr nvReg; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVModeInit\n")); + + /* Initialise the ModeReg values */ + if (!vgaHWInit(pScrn, mode)) + return FALSE; + pScrn->vtSema = TRUE; + + if(!(*pNv->ModeInit)(pScrn, mode)) + return FALSE; + + /* Program the registers */ + vgaHWProtect(pScrn, TRUE); + vgaReg = &hwp->ModeReg; + nvReg = &pNv->ModeReg; + + (*pNv->Restore)(pScrn, vgaReg, nvReg, FALSE); + +#if X_BYTE_ORDER == X_BIG_ENDIAN + /* turn on LFB swapping */ + { + unsigned char tmp; + + VGA_WR08(pNv->riva.PCIO, 0x3d4, 0x46); + tmp = VGA_RD08(pNv->riva.PCIO, 0x3d5); + tmp |= (1 << 7); + VGA_WR08(pNv->riva.PCIO, 0x3d5, tmp); + } +#endif + + NVResetGraphics(pScrn); + + vgaHWProtect(pScrn, FALSE); + + pNv->CurrentLayout.mode = mode; + + return TRUE; +} + +/* + * Restore the initial (text) mode. + */ +static void +NVRestore(ScrnInfoPtr pScrn) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + vgaRegPtr vgaReg = &hwp->SavedReg; + NVPtr pNv = NVPTR(pScrn); + NVRegPtr nvReg = &pNv->SavedReg; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVRestore\n")); + /* Only restore text mode fonts/text for the primary card */ + vgaHWProtect(pScrn, TRUE); + (*pNv->Restore)(pScrn, vgaReg, nvReg, pNv->Primary); + vgaHWProtect(pScrn, FALSE); +} + +static void +NVDPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags) +{ + unsigned char crtc1A; + vgaHWPtr hwp = VGAHWPTR(pScrn); + + if (!pScrn->vtSema) return; + + crtc1A = hwp->readCrtc(hwp, 0x1A) & ~0xC0; + + switch (PowerManagementMode) { + case DPMSModeStandby: /* HSync: Off, VSync: On */ + crtc1A |= 0x80; + break; + case DPMSModeSuspend: /* HSync: On, VSync: Off */ + crtc1A |= 0x40; + break; + case DPMSModeOff: /* HSync: Off, VSync: Off */ + crtc1A |= 0xC0; + break; + case DPMSModeOn: /* HSync: On, VSync: On */ + default: + break; + } + + hwp->writeCrtc(hwp, 0x1A, crtc1A); +} + + +/* Mandatory */ + +/* This gets called at the start of each server generation */ + +static Bool +NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) +{ + ScrnInfoPtr pScrn; + vgaHWPtr hwp; + NVPtr pNv; + NVRamdacPtr NVdac; + int ret; + VisualPtr visual; + unsigned char *FBStart; + int width, height, displayWidth; + BoxRec AvailFBArea; + + /* + * First get the ScrnInfoRec + */ + pScrn = xf86Screens[pScreen->myNum]; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVScreenInit\n")); + + hwp = VGAHWPTR(pScrn); + pNv = NVPTR(pScrn); + NVdac = &pNv->Dac; + + /* Map the NV memory and MMIO areas */ + if (pNv->FBDev) { + if (!NVMapMemFBDev(pScrn)) + return FALSE; + } else { + if (!NVMapMem(pScrn)) + return FALSE; + } + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Mem Mapped\n")); + + /* Map the VGA memory when the primary video */ + if (pNv->Primary && !pNv->FBDev) { + hwp->MapSize = 0x10000; + if (!vgaHWMapMem(pScrn)) + return FALSE; + } + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- VGA Mapped\n")); + + if (pNv->FBDev) { + fbdevHWSave(pScrn); + if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) + return FALSE; + } else { + /* Save the current state */ + pNv->riva.LockUnlock(&pNv->riva, 0); + NVSave(pScrn); + /* Initialise the first mode */ + if (!NVModeInit(pScrn, pScrn->currentMode)) + return FALSE; + } + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- State saved\n")); + + /* Darken the screen for aesthetic reasons and set the viewport */ + NVSaveScreen(pScreen, SCREEN_SAVER_ON); + pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Blanked\n")); + + /* + * The next step is to setup the screen's visuals, and initialise the + * framebuffer code. In cases where the framebuffer's default + * choices for things like visual layouts and bits per RGB are OK, + * this may be as simple as calling the framebuffer's ScreenInit() + * function. If not, the visuals will need to be setup before calling + * a fb ScreenInit() function and fixed up after. + * + * For most PC hardware at depths >= 8, the defaults that cfb uses + * are not appropriate. In this driver, we fixup the visuals after. + */ + + /* + * Reset the visual list. + */ + miClearVisualTypes(); + + /* Setup the visuals we support. */ + + if ((pScrn->bitsPerPixel > 8) && (pNv->riva.Architecture == NV_ARCH_03)) { + if (!miSetVisualTypes(pScrn->depth, TrueColorMask, 8, + pScrn->defaultVisual)) + return FALSE; + } else { + if (!miSetVisualTypes(pScrn->depth, + miGetDefaultVisualMask(pScrn->depth), 8, + pScrn->defaultVisual)) + return FALSE; + } + if (!miSetPixmapDepths ()) return FALSE; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Visuals set up\n")); + + /* + * Call the framebuffer layer's ScreenInit function, and fill in other + * pScreen fields. + */ + + width = pScrn->virtualX; + height = pScrn->virtualY; + displayWidth = pScrn->displayWidth; + + + if(pNv->Rotate) { + height = pScrn->virtualX; + width = pScrn->virtualY; + } + + if(pNv->ShadowFB) { + pNv->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); + pNv->ShadowPtr = xalloc(pNv->ShadowPitch * height); + displayWidth = pNv->ShadowPitch / (pScrn->bitsPerPixel >> 3); + FBStart = pNv->ShadowPtr; + } else { + pNv->ShadowPtr = NULL; + FBStart = pNv->FbStart; + } + + switch (pScrn->bitsPerPixel) { + case 8: + case 16: + case 32: + ret = fbScreenInit(pScreen, FBStart, width, height, + pScrn->xDpi, pScrn->yDpi, + displayWidth, pScrn->bitsPerPixel); + break; + default: + xf86DrvMsg(scrnIndex, X_ERROR, + "Internal error: invalid bpp (%d) in NVScreenInit\n", + pScrn->bitsPerPixel); + ret = FALSE; + break; + } + if (!ret) + return FALSE; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- cfb set up\n")); + + if (pScrn->bitsPerPixel > 8) { + /* Fixup RGB ordering */ + visual = pScreen->visuals + pScreen->numVisuals; + while (--visual >= pScreen->visuals) { + if ((visual->class | DynamicClass) == DirectColor) { + visual->offsetRed = pScrn->offset.red; + visual->offsetGreen = pScrn->offset.green; + visual->offsetBlue = pScrn->offset.blue; + visual->redMask = pScrn->mask.red; + visual->greenMask = pScrn->mask.green; + visual->blueMask = pScrn->mask.blue; + } + } + } + + fbPictureInit (pScreen, 0, 0); + + xf86SetBlackWhitePixels(pScreen); + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- B & W\n")); + + if(!pNv->ShadowFB) /* hardware cursor needs to wrap this layer */ + NVDGAInit(pScreen); + + AvailFBArea.x1 = 0; + AvailFBArea.y1 = 0; + AvailFBArea.x2 = pScrn->displayWidth; + AvailFBArea.y2 = (min(pNv->FbUsableSize, 32*1024*1024)) / + (pScrn->displayWidth * pScrn->bitsPerPixel / 8); + xf86InitFBManager(pScreen, &AvailFBArea); + + if (!pNv->NoAccel) + NVAccelInit(pScreen); + + miInitializeBackingStore(pScreen); + xf86SetBackingStore(pScreen); + xf86SetSilkenMouse(pScreen); + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Backing store set up\n")); + + /* Initialize software cursor. + Must precede creation of the default colormap */ + miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- SW cursor set up\n")); + + /* Initialize HW cursor layer. + Must follow software cursor initialization*/ + if (pNv->HWCursor) { + if(!NVCursorInit(pScreen)) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Hardware cursor initialization failed\n"); + } + + /* Initialise default colourmap */ + if (!miCreateDefColormap(pScreen)) + return FALSE; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Def Color map set up\n")); + + /* Initialize colormap layer. + Must follow initialization of the default colormap */ + if(!xf86HandleColormaps(pScreen, 256, 8, + (pNv->FBDev ? fbdevHWLoadPalette : NVdac->LoadPalette), + NULL, CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR)) + return FALSE; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Palette loaded\n")); + + if(pNv->ShadowFB) { + RefreshAreaFuncPtr refreshArea = NVRefreshArea; + + if(pNv->Rotate) { + pNv->PointerMoved = pScrn->PointerMoved; + pScrn->PointerMoved = NVPointerMoved; + + switch(pScrn->bitsPerPixel) { + case 8: refreshArea = NVRefreshArea8; break; + case 16: refreshArea = NVRefreshArea16; break; + case 32: refreshArea = NVRefreshArea32; break; + } + } + + ShadowFBInit(pScreen, refreshArea); + } + + /* Call the vgaHW DPMS function directly. + XXX There must be a way to get all the DPMS modes. */ +#if 0 + xf86DPMSInit(pScreen, vgaHWDPMSSet, 0); +#else + xf86DPMSInit(pScreen, NVDPMSSet, 0); +#endif + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- DPMS set up\n")); + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Color maps etc. set up\n")); + + pScrn->memPhysBase = pNv->FbAddress; + pScrn->fbOffset = 0; + + NVInitVideo(pScreen); + + pScreen->SaveScreen = NVSaveScreen; + + /* Wrap the current CloseScreen function */ + pNv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = NVCloseScreen; + + pNv->BlockHandler = pScreen->BlockHandler; + pScreen->BlockHandler = NVBlockHandler; + + /* Report any unused options (only for the first generation) */ + if (serverGeneration == 1) { + xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); + } + /* Done */ + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Done\n")); + return TRUE; +} + +/* Free up any persistent data structures */ + + +/* Do screen blanking */ + +/* Mandatory */ +static Bool +NVSaveScreen(ScreenPtr pScreen, int mode) +{ + return vgaHWSaveScreen(pScreen, mode); +} + +static void +NVSave(ScrnInfoPtr pScrn) +{ + NVPtr pNv = NVPTR(pScrn); + NVRegPtr nvReg = &pNv->SavedReg; + vgaHWPtr pVga = VGAHWPTR(pScrn); + vgaRegPtr vgaReg = &pVga->SavedReg; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVSave\n")); + (*pNv->Save)(pScrn, vgaReg, nvReg, pNv->Primary); +} + diff --git a/src/nv_include.h b/src/nv_include.h new file mode 100644 index 0000000..2d4465b --- /dev/null +++ b/src/nv_include.h @@ -0,0 +1,59 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_include.h,v 1.11 2001/12/07 00:09:56 mvojkovi Exp $ */ + +#ifndef __NV_INCLUDE_H__ +#define __NV_INCLUDE_H__ + +/* All drivers should typically include these */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "xf86_ansic.h" +#include "compiler.h" + +/* Drivers for PCI hardware need this */ +#include "xf86PciInfo.h" + +/* Drivers that need to access the PCI config space directly need this */ +#include "xf86Pci.h" + +/* All drivers initialising the SW cursor need this */ +#include "mipointer.h" + +/* All drivers implementing backing store need this */ +#include "mibstore.h" + +#include "micmap.h" + +#include "xf86DDC.h" + +#include "vbe.h" + +#include "xf86RAC.h" + +#include "nv_const.h" + +#include "dixstruct.h" +#include "scrnintstr.h" + +#include "fb.h" + +#include "xaa.h" +#include "xf86cmap.h" +#include "shadowfb.h" +#include "fbdevhw.h" + +#include "xf86xv.h" +#include "Xv.h" + +#include "vgaHW.h" + +#include "xf86Cursor.h" +#include "xf86DDC.h" + +#include "region.h" + +#include "nv_local.h" +#include "nv_type.h" +#include "nv_proto.h" + +#endif /* __NV_INCLUDE_H__ */ diff --git a/src/nv_local.h b/src/nv_local.h new file mode 100644 index 0000000..50ec06a --- /dev/null +++ b/src/nv_local.h @@ -0,0 +1,74 @@ + /***************************************************************************\ +|* *| +|* Copyright 1993-1999 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 *| +|* hereby granted a nonexclusive, royalty-free copyright license to *| +|* use this code in individual and commercial software. *| +|* *| +|* Any use of this source code must include, in the user documenta- *| +|* tion and internal comments to the code, notices to the end user *| +|* as follows: *| +|* *| +|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| +|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| +|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| +|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| +|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| +|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| +|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| +|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| +|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| +|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| +|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| +|* *| +|* U.S. Government End Users. This source code is a "commercial *| +|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| +|* consisting of "commercial computer software" and "commercial *| +|* computer software documentation," as such terms are used in *| +|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| +|* ment only as a commercial end item. Consistent with 48 C.F.R. *| +|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| +|* all U.S. Government End Users acquire the source code with only *| +|* those rights set forth herein. *| +|* *| + \***************************************************************************/ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_local.h,v 1.7 2002/01/25 21:56:06 tsi Exp $ */ + +#ifndef __NV_LOCAL_H__ +#define __NV_LOCAL_H__ + +/* + * This file includes any environment or machine specific values to access the + * HW. Put all affected includes, typdefs, etc. here so the riva_hw.* files + * can stay generic in nature. + */ +#include "xf86_ansic.h" +#include "compiler.h" +#include "xf86_OSproc.h" + +/* + * Typedefs to force certain sized values. + */ +typedef unsigned char U008; +typedef unsigned short U016; +typedef unsigned int U032; + +/* + * HW access macros. These assume memory-mapped I/O, and not normal I/O space. + */ +#define NV_WR08(p,i,d) MMIO_OUT8((volatile pointer)(p), (i), (d)) +#define NV_RD08(p,i) MMIO_IN8((volatile pointer)(p), (i)) +#define NV_WR16(p,i,d) MMIO_OUT16((volatile pointer)(p), (i), (d)) +#define NV_RD16(p,i) MMIO_IN16((volatile pointer)(p), (i)) +#define NV_WR32(p,i,d) MMIO_OUT32((volatile pointer)(p), (i), (d)) +#define NV_RD32(p,i) MMIO_IN32((volatile pointer)(p), (i)) + +/* VGA I/O is now always done through MMIO */ +#define VGA_WR08(p,i,d) NV_WR08(p,i,d) +#define VGA_RD08(p,i) NV_RD08(p,i) + +#endif /* __NV_LOCAL_H__ */ diff --git a/src/nv_proto.h b/src/nv_proto.h new file mode 100644 index 0000000..013f57a --- /dev/null +++ b/src/nv_proto.h @@ -0,0 +1,46 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_proto.h,v 1.8 2002/11/26 23:41:59 mvojkovi Exp $ */ + +#ifndef __NV_PROTO_H__ +#define __NV_PROTO_H__ + +/* in nv_driver.c */ +Bool NVSwitchMode(int scrnIndex, DisplayModePtr mode, int flags); +void NVAdjustFrame(int scrnIndex, int x, int y, int flags); +xf86MonPtr NVdoDDC(ScrnInfoPtr pScrn); + + +/* in nv_dac.c */ +void NVRamdacInit(ScrnInfoPtr pScrn); +Bool NVDACInit(ScrnInfoPtr pScrn, DisplayModePtr mode); +void NVDACSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, + NVRegPtr nvReg, Bool saveFonts); +void NVDACRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, + NVRegPtr nvReg, Bool restoreFonts); +void NVDACLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, + LOCO *colors, VisualPtr pVisual ); + +/* in nv_video.c */ +void NVInitVideo(ScreenPtr); +void NVResetVideo (ScrnInfoPtr pScrnInfo); + +/* in nv_setup.c */ +void RivaEnterLeave(ScrnInfoPtr pScrn, Bool enter); +void NV1Setup(ScrnInfoPtr pScrn); +void NV3Setup(ScrnInfoPtr pScrn); +void NV4Setup(ScrnInfoPtr pScrn); +void NV10Setup(ScrnInfoPtr pScrn); +void NV20Setup(ScrnInfoPtr pScrn); + +/* in nv_cursor.c */ +Bool NVCursorInit(ScreenPtr pScreen); + +/* in nv_xaa.c */ +Bool NVAccelInit(ScreenPtr pScreen); +void NVSync(ScrnInfoPtr pScrn); +void NVResetGraphics(ScrnInfoPtr pScrn); + +/* in nv_dga.c */ +Bool NVDGAInit(ScreenPtr pScreen); + +#endif /* __NV_PROTO_H__ */ + diff --git a/src/nv_setup.c b/src/nv_setup.c new file mode 100644 index 0000000..cdb0ade --- /dev/null +++ b/src/nv_setup.c @@ -0,0 +1,551 @@ +/* $XConsortium: nv_driver.c /main/3 1996/10/28 05:13:37 kaleb $ */ +/* + * Copyright 1996-1997 David J. McKay + * + * 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 + * DAVID J. MCKAY 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. + */ + +/* 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_setup.c,v 1.27.2.1 2003/05/09 02:17:49 dawes Exp $ */ + +#include "nv_include.h" + +/* + * Override VGA I/O routines. + */ +static void NVWriteCrtc(vgaHWPtr pVga, CARD8 index, CARD8 value) +{ + NVPtr pNv = (NVPtr)pVga->MMIOBase; + VGA_WR08(pNv->riva.PCIO, pVga->IOBase + VGA_CRTC_INDEX_OFFSET, index); + VGA_WR08(pNv->riva.PCIO, pVga->IOBase + VGA_CRTC_DATA_OFFSET, value); +} +static CARD8 NVReadCrtc(vgaHWPtr pVga, CARD8 index) +{ + NVPtr pNv = (NVPtr)pVga->MMIOBase; + VGA_WR08(pNv->riva.PCIO, pVga->IOBase + VGA_CRTC_INDEX_OFFSET, index); + return (VGA_RD08(pNv->riva.PCIO, pVga->IOBase + VGA_CRTC_DATA_OFFSET)); +} +static void NVWriteGr(vgaHWPtr pVga, CARD8 index, CARD8 value) +{ + NVPtr pNv = (NVPtr)pVga->MMIOBase; + VGA_WR08(pNv->riva.PVIO, VGA_GRAPH_INDEX, index); + VGA_WR08(pNv->riva.PVIO, VGA_GRAPH_DATA, value); +} +static CARD8 NVReadGr(vgaHWPtr pVga, CARD8 index) +{ + NVPtr pNv = (NVPtr)pVga->MMIOBase; + VGA_WR08(pNv->riva.PVIO, VGA_GRAPH_INDEX, index); + return (VGA_RD08(pNv->riva.PVIO, VGA_GRAPH_DATA)); +} +static void NVWriteSeq(vgaHWPtr pVga, CARD8 index, CARD8 value) +{ + NVPtr pNv = (NVPtr)pVga->MMIOBase; + VGA_WR08(pNv->riva.PVIO, VGA_SEQ_INDEX, index); + VGA_WR08(pNv->riva.PVIO, VGA_SEQ_DATA, value); +} +static CARD8 NVReadSeq(vgaHWPtr pVga, CARD8 index) +{ + NVPtr pNv = (NVPtr)pVga->MMIOBase; + VGA_WR08(pNv->riva.PVIO, VGA_SEQ_INDEX, index); + return (VGA_RD08(pNv->riva.PVIO, VGA_SEQ_DATA)); +} +static void NVWriteAttr(vgaHWPtr pVga, CARD8 index, CARD8 value) +{ + NVPtr pNv = (NVPtr)pVga->MMIOBase; + volatile CARD8 tmp; + + tmp = VGA_RD08(pNv->riva.PCIO, pVga->IOBase + VGA_IN_STAT_1_OFFSET); + if (pVga->paletteEnabled) + index &= ~0x20; + else + index |= 0x20; + VGA_WR08(pNv->riva.PCIO, VGA_ATTR_INDEX, index); + VGA_WR08(pNv->riva.PCIO, VGA_ATTR_DATA_W, value); +} +static CARD8 NVReadAttr(vgaHWPtr pVga, CARD8 index) +{ + NVPtr pNv = (NVPtr)pVga->MMIOBase; + volatile CARD8 tmp; + + tmp = VGA_RD08(pNv->riva.PCIO, pVga->IOBase + VGA_IN_STAT_1_OFFSET); + if (pVga->paletteEnabled) + index &= ~0x20; + else + index |= 0x20; + VGA_WR08(pNv->riva.PCIO, VGA_ATTR_INDEX, index); + return (VGA_RD08(pNv->riva.PCIO, VGA_ATTR_DATA_R)); +} +static void NVWriteMiscOut(vgaHWPtr pVga, CARD8 value) +{ + NVPtr pNv = (NVPtr)pVga->MMIOBase; + VGA_WR08(pNv->riva.PVIO, VGA_MISC_OUT_W, value); +} +static CARD8 NVReadMiscOut(vgaHWPtr pVga) +{ + NVPtr pNv = (NVPtr)pVga->MMIOBase; + return (VGA_RD08(pNv->riva.PVIO, VGA_MISC_OUT_R)); +} +static void NVEnablePalette(vgaHWPtr pVga) +{ + NVPtr pNv = (NVPtr)pVga->MMIOBase; + volatile CARD8 tmp; + + tmp = VGA_RD08(pNv->riva.PCIO, pVga->IOBase + VGA_IN_STAT_1_OFFSET); + VGA_WR08(pNv->riva.PCIO, VGA_ATTR_INDEX, 0x00); + pVga->paletteEnabled = TRUE; +} +static void NVDisablePalette(vgaHWPtr pVga) +{ + NVPtr pNv = (NVPtr)pVga->MMIOBase; + volatile CARD8 tmp; + + tmp = VGA_RD08(pNv->riva.PCIO, pVga->IOBase + VGA_IN_STAT_1_OFFSET); + VGA_WR08(pNv->riva.PCIO, VGA_ATTR_INDEX, 0x20); + pVga->paletteEnabled = FALSE; +} +static void NVWriteDacMask(vgaHWPtr pVga, CARD8 value) +{ + NVPtr pNv = (NVPtr)pVga->MMIOBase; + VGA_WR08(pNv->riva.PDIO, VGA_DAC_MASK, value); +} +static CARD8 NVReadDacMask(vgaHWPtr pVga) +{ + NVPtr pNv = (NVPtr)pVga->MMIOBase; + return (VGA_RD08(pNv->riva.PDIO, VGA_DAC_MASK)); +} +static void NVWriteDacReadAddr(vgaHWPtr pVga, CARD8 value) +{ + NVPtr pNv = (NVPtr)pVga->MMIOBase; + VGA_WR08(pNv->riva.PDIO, VGA_DAC_READ_ADDR, value); +} +static void NVWriteDacWriteAddr(vgaHWPtr pVga, CARD8 value) +{ + NVPtr pNv = (NVPtr)pVga->MMIOBase; + VGA_WR08(pNv->riva.PDIO, VGA_DAC_WRITE_ADDR, value); +} +static void NVWriteDacData(vgaHWPtr pVga, CARD8 value) +{ + NVPtr pNv = (NVPtr)pVga->MMIOBase; + VGA_WR08(pNv->riva.PDIO, VGA_DAC_DATA, value); +} +static CARD8 NVReadDacData(vgaHWPtr pVga) +{ + NVPtr pNv = (NVPtr)pVga->MMIOBase; + return (VGA_RD08(pNv->riva.PDIO, VGA_DAC_DATA)); +} + +static Bool +NVIsConnected (ScrnInfoPtr pScrn, Bool second) +{ + NVPtr pNv = NVPTR(pScrn); + volatile U032 *PRAMDAC = pNv->riva.PRAMDAC0; + CARD32 reg52C, reg608; + Bool present; + + if(second) PRAMDAC += 0x800; + + reg52C = PRAMDAC[0x052C/4]; + reg608 = PRAMDAC[0x0608/4]; + + PRAMDAC[0x0608/4] = reg608 & ~0x00010000; + + PRAMDAC[0x052C/4] = reg52C & 0x0000FEEE; + usleep(1000); + PRAMDAC[0x052C/4] |= 1; + + pNv->riva.PRAMDAC0[0x0610/4] = 0x94050140; + pNv->riva.PRAMDAC0[0x0608/4] |= 0x00001000; + + usleep(1000); + + present = (PRAMDAC[0x0608/4] & (1 << 28)) ? TRUE : FALSE; + + pNv->riva.PRAMDAC0[0x0608/4] &= 0x0000EFFF; + + PRAMDAC[0x052C/4] = reg52C; + PRAMDAC[0x0608/4] = reg608; + + return present; +} + +static void +NVOverrideCRTC(ScrnInfoPtr pScrn) +{ + NVPtr pNv = NVPTR(pScrn); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Detected CRTC controller %i being used\n", + pNv->SecondCRTC ? 1 : 0); + + if(pNv->forceCRTC != -1) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Forcing usage of CRTC %i\n", pNv->forceCRTC); + pNv->SecondCRTC = pNv->forceCRTC; + } +} + +static void +NVIsSecond (ScrnInfoPtr pScrn) +{ + NVPtr pNv = NVPTR(pScrn); + + if(pNv->FlatPanel == 1) { + switch(pNv->Chipset & 0xffff) { + case 0x0174: + case 0x0175: + case 0x0176: + case 0x0177: + case 0x0179: + case 0x017C: + case 0x017D: + case 0x0186: + case 0x0187: + /* this might not be a good default for the chips below */ + case 0x0286: + case 0x028C: + case 0x0316: + case 0x0317: + case 0x031A: + case 0x031B: + case 0x031C: + case 0x031D: + case 0x031E: + case 0x031F: + case 0x0326: + case 0x032E: + pNv->SecondCRTC = TRUE; + break; + default: + pNv->SecondCRTC = FALSE; + break; + } + } else { + if(NVIsConnected(pScrn, 0)) { + if(pNv->riva.PRAMDAC0[0x0000052C/4] & 0x100) + pNv->SecondCRTC = TRUE; + else + pNv->SecondCRTC = FALSE; + } else + if (NVIsConnected(pScrn, 1)) { + pNv->DDCBase = 0x36; + if(pNv->riva.PRAMDAC0[0x0000252C/4] & 0x100) + pNv->SecondCRTC = TRUE; + else + pNv->SecondCRTC = FALSE; + } else /* default */ + pNv->SecondCRTC = FALSE; + } + + NVOverrideCRTC(pScrn); +} + +static void +NVCommonSetup(ScrnInfoPtr pScrn) +{ + NVPtr pNv = NVPTR(pScrn); + vgaHWPtr pVga = VGAHWPTR(pScrn); + CARD32 regBase = pNv->IOAddress; + int mmioFlags; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVCommonSetup\n")); + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Regbase %x\n", regBase)); + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- riva %x\n", &pNv->riva)); + + pNv->Save = NVDACSave; + pNv->Restore = NVDACRestore; + pNv->ModeInit = NVDACInit; + + pNv->Dac.LoadPalette = NVDACLoadPalette; + + /* + * Override VGA I/O routines. + */ + pVga->writeCrtc = NVWriteCrtc; + pVga->readCrtc = NVReadCrtc; + pVga->writeGr = NVWriteGr; + pVga->readGr = NVReadGr; + pVga->writeAttr = NVWriteAttr; + pVga->readAttr = NVReadAttr; + pVga->writeSeq = NVWriteSeq; + pVga->readSeq = NVReadSeq; + pVga->writeMiscOut = NVWriteMiscOut; + pVga->readMiscOut = NVReadMiscOut; + pVga->enablePalette = NVEnablePalette; + pVga->disablePalette = NVDisablePalette; + pVga->writeDacMask = NVWriteDacMask; + pVga->readDacMask = NVReadDacMask; + pVga->writeDacWriteAddr = NVWriteDacWriteAddr; + pVga->writeDacReadAddr = NVWriteDacReadAddr; + pVga->writeDacData = NVWriteDacData; + pVga->readDacData = NVReadDacData; + /* + * Note: There are different pointers to the CRTC/AR and GR/SEQ registers. + * Bastardize the intended uses of these to make it work. + */ + pVga->MMIOBase = (CARD8 *)pNv; + pVga->MMIOOffset = 0; + + /* + * No IRQ in use. + */ + pNv->riva.EnableIRQ = 0; + /* + * Map remaining registers. This MUST be done in the OS specific driver code. + */ + pNv->riva.IO = VGA_IOBASE_COLOR; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- IO %x\n", pNv->riva.IO)); + + mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT; + + pNv->riva.PRAMDAC0 = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pNv->PciTag, + regBase+0x00680000, 0x00003000); + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- PRAMDAC %x\n", pNv->riva.PRAMDAC0)); + pNv->riva.PFB = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pNv->PciTag, + regBase+0x00100000, 0x00001000); + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- PFB %x\n", pNv->riva.PFB)); + pNv->riva.PFIFO = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pNv->PciTag, + regBase+0x00002000, 0x00002000); + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- PFIFO %x\n", pNv->riva.PFIFO)); + pNv->riva.PGRAPH = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pNv->PciTag, + regBase+0x00400000, 0x00002000); + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- PGRAPH %x\n", pNv->riva.PGRAPH)); + pNv->riva.PEXTDEV = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pNv->PciTag, + regBase+0x00101000, 0x00001000); + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- PEXTDEV %x\n", pNv->riva.PEXTDEV)); + pNv->riva.PTIMER = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pNv->PciTag, + regBase+0x00009000, 0x00001000); + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- PTIMER %x\n", pNv->riva.PTIMER)); + pNv->riva.PMC = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pNv->PciTag, + regBase+0x00000000, 0x00009000); + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- PMC %x\n", pNv->riva.PMC)); + pNv->riva.FIFO = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pNv->PciTag, + regBase+0x00800000, 0x00010000); + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- FIFO %x\n", pNv->riva.FIFO)); + + /* + * These registers are read/write as 8 bit values. Probably have to map + * sparse on alpha. + */ + pNv->riva.PCIO0 = (U008 *)xf86MapPciMem(pScrn->scrnIndex, mmioFlags, + pNv->PciTag, regBase+0x00601000, + 0x00003000); + pNv->riva.PDIO0 = (U008 *)xf86MapPciMem(pScrn->scrnIndex, mmioFlags, + pNv->PciTag, regBase+0x00681000, + 0x00003000); + pNv->riva.PVIO = (U008 *)xf86MapPciMem(pScrn->scrnIndex, mmioFlags, + pNv->PciTag, regBase+0x000C0000, + 0x00001000); + + if(pNv->FlatPanel == -1) { + switch(pNv->Chipset & 0xffff) { + case 0x0112: /* known laptop chips */ + case 0x0174: + case 0x0175: + case 0x0176: + case 0x0177: + case 0x0179: + case 0x017C: + case 0x017D: + case 0x0186: + case 0x0187: + case 0x0286: + case 0x028C: + case 0x0316: + case 0x0317: + case 0x031A: + case 0x031B: + case 0x031C: + case 0x031D: + case 0x031E: + case 0x031F: + case 0x0326: + case 0x032E: + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "On a laptop. Assuming Digital Flat Panel\n"); + pNv->FlatPanel = 1; + break; + default: + break; + } + } + + pNv->DDCBase = 0x3e; + + switch(pNv->Chipset & 0x0ff0) { + case 0x0110: + if((pNv->Chipset & 0xffff) == 0x0112) + pNv->SecondCRTC = TRUE; +#if defined(__powerpc__) + else if(pNv->FlatPanel == 1) + pNv->SecondCRTC = TRUE; +#endif + NVOverrideCRTC(pScrn); + break; + case 0x0170: + case 0x0180: + case 0x01F0: + case 0x0250: + case 0x0280: + case 0x0300: + case 0x0310: + case 0x0320: + case 0x0330: + case 0x0340: + NVIsSecond(pScrn); + break; + default: + break; + } + + if(pNv->riva.Architecture == 3) + pNv->riva.PCRTC0 = pNv->riva.PGRAPH; + + if(pNv->SecondCRTC) { + pNv->riva.PCIO = pNv->riva.PCIO0 + 0x2000; + pNv->riva.PCRTC = pNv->riva.PCRTC0 + 0x800; + pNv->riva.PRAMDAC = pNv->riva.PRAMDAC0 + 0x800; + pNv->riva.PDIO = pNv->riva.PDIO0 + 0x2000; + } else { + pNv->riva.PCIO = pNv->riva.PCIO0; + pNv->riva.PCRTC = pNv->riva.PCRTC0; + pNv->riva.PRAMDAC = pNv->riva.PRAMDAC0; + pNv->riva.PDIO = pNv->riva.PDIO0; + } + + RivaGetConfig(pNv); + + pNv->Dac.maxPixelClock = pNv->riva.MaxVClockFreqKHz; + + pNv->riva.LockUnlock(&pNv->riva, 0); + + NVRamdacInit(pScrn); + +#if !defined(__powerpc__) + /* Read and print the Monitor DDC info */ + pScrn->monitor->DDC = NVdoDDC(pScrn); +#endif + if(pNv->FlatPanel == -1) { + pNv->FlatPanel = 0; + if(pScrn->monitor->DDC) { + xf86MonPtr ddc = (xf86MonPtr)pScrn->monitor->DDC; + + if(ddc->features.input_type) { + pNv->FlatPanel = 1; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "autodetected Digital Flat Panel\n"); + } + } + } + pNv->riva.flatPanel = (pNv->FlatPanel > 0) ? FP_ENABLE : 0; + if(pNv->riva.flatPanel && pNv->FPDither && (pScrn->depth == 24)) + pNv->riva.flatPanel |= FP_DITHER; + +} + +void +NV1Setup(ScrnInfoPtr pScrn) +{ +} + +void +NV3Setup(ScrnInfoPtr pScrn) +{ + NVPtr pNv = NVPTR(pScrn); + CARD32 frameBase = pNv->FbAddress; + int mmioFlags; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV3Setup\n")); + + /* + * Record chip architecture based in PCI probe. + */ + pNv->riva.Architecture = 3; + /* + * Map chip-specific memory-mapped registers. This MUST be done in the OS specific driver code. + */ + mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT; + pNv->riva.PRAMIN = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pNv->PciTag, + frameBase+0x00C00000, 0x00008000); + + NVCommonSetup(pScrn); +} + +void +NV4Setup(ScrnInfoPtr pScrn) +{ + NVPtr pNv = NVPTR(pScrn); + CARD32 regBase = pNv->IOAddress; + int mmioFlags; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV4Setup\n")); + + pNv->riva.Architecture = 4; + /* + * Map chip-specific memory-mapped registers. This MUST be done in the OS specific driver code. + */ + mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT; + pNv->riva.PRAMIN = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pNv->PciTag, + regBase+0x00710000, 0x00010000); + pNv->riva.PCRTC0 = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pNv->PciTag, + regBase+0x00600000, 0x00001000); + + NVCommonSetup(pScrn); +} + +void +NV10Setup(ScrnInfoPtr pScrn) +{ + NVPtr pNv = NVPTR(pScrn); + CARD32 regBase = pNv->IOAddress; + int mmioFlags; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV10Setup\n")); + + pNv->riva.Architecture = 0x10; + mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT; + pNv->riva.PRAMIN = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pNv->PciTag, + regBase+0x00710000, 0x00010000); + pNv->riva.PCRTC0 = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pNv->PciTag, + regBase+0x00600000, 0x00003000); + + NVCommonSetup(pScrn); +} + +void +NV20Setup(ScrnInfoPtr pScrn) +{ + NVPtr pNv = NVPTR(pScrn); + CARD32 regBase = pNv->IOAddress; + int mmioFlags; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV20Setup\n")); + + pNv->riva.Architecture = 0x20; + mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT; + pNv->riva.PRAMIN = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pNv->PciTag, + regBase+0x00710000, 0x00010000); + pNv->riva.PCRTC0 = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, pNv->PciTag, + regBase+0x00600000, 0x00003000); + + NVCommonSetup(pScrn); +} + diff --git a/src/nv_shadow.c b/src/nv_shadow.c new file mode 100644 index 0000000..5effc79 --- /dev/null +++ b/src/nv_shadow.c @@ -0,0 +1,194 @@ +/* + Copyright (c) 1999, The XFree86 Project Inc. + Written by Mark Vojkovich <markv@valinux.com> +*/ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_shadow.c,v 1.6 2001/01/22 21:32:36 dawes Exp $ */ + +#include "nv_local.h" +#include "nv_include.h" +#include "nv_type.h" +#include "shadowfb.h" +#include "servermd.h" + + +void +NVRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + NVPtr pNv = NVPTR(pScrn); + int width, height, Bpp, FBPitch; + unsigned char *src, *dst; + + Bpp = pScrn->bitsPerPixel >> 3; + FBPitch = BitmapBytePad(pScrn->displayWidth * pScrn->bitsPerPixel); + + while(num--) { + width = (pbox->x2 - pbox->x1) * Bpp; + height = pbox->y2 - pbox->y1; + src = pNv->ShadowPtr + (pbox->y1 * pNv->ShadowPitch) + + (pbox->x1 * Bpp); + dst = pNv->FbStart + (pbox->y1 * FBPitch) + (pbox->x1 * Bpp); + + while(height--) { + memcpy(dst, src, width); + dst += FBPitch; + src += pNv->ShadowPitch; + } + + pbox++; + } +} + +void +NVPointerMoved(int index, int x, int y) +{ + ScrnInfoPtr pScrn = xf86Screens[index]; + NVPtr pNv = NVPTR(pScrn); + int newX, newY; + + if(pNv->Rotate == 1) { + newX = pScrn->pScreen->height - y - 1; + newY = x; + } else { + newX = y; + newY = pScrn->pScreen->width - x - 1; + } + + (*pNv->PointerMoved)(index, newX, newY); +} + +void +NVRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + NVPtr pNv = NVPTR(pScrn); + int count, width, height, y1, y2, dstPitch, srcPitch; + CARD8 *dstPtr, *srcPtr, *src; + CARD32 *dst; + + dstPitch = pScrn->displayWidth; + srcPitch = -pNv->Rotate * pNv->ShadowPitch; + + while(num--) { + width = pbox->x2 - pbox->x1; + y1 = pbox->y1 & ~3; + y2 = (pbox->y2 + 3) & ~3; + height = (y2 - y1) >> 2; /* in dwords */ + + if(pNv->Rotate == 1) { + dstPtr = pNv->FbStart + + (pbox->x1 * dstPitch) + pScrn->virtualX - y2; + srcPtr = pNv->ShadowPtr + ((1 - y2) * srcPitch) + pbox->x1; + } else { + dstPtr = pNv->FbStart + + ((pScrn->virtualY - pbox->x2) * dstPitch) + y1; + srcPtr = pNv->ShadowPtr + (y1 * srcPitch) + pbox->x2 - 1; + } + + while(width--) { + src = srcPtr; + dst = (CARD32*)dstPtr; + count = height; + while(count--) { + *(dst++) = src[0] | (src[srcPitch] << 8) | + (src[srcPitch * 2] << 16) | + (src[srcPitch * 3] << 24); + src += srcPitch * 4; + } + srcPtr += pNv->Rotate; + dstPtr += dstPitch; + } + + pbox++; + } +} + + +void +NVRefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + NVPtr pNv = NVPTR(pScrn); + int count, width, height, y1, y2, dstPitch, srcPitch; + CARD16 *dstPtr, *srcPtr, *src; + CARD32 *dst; + + dstPitch = pScrn->displayWidth; + srcPitch = -pNv->Rotate * pNv->ShadowPitch >> 1; + + while(num--) { + width = pbox->x2 - pbox->x1; + y1 = pbox->y1 & ~1; + y2 = (pbox->y2 + 1) & ~1; + height = (y2 - y1) >> 1; /* in dwords */ + + if(pNv->Rotate == 1) { + dstPtr = (CARD16*)pNv->FbStart + + (pbox->x1 * dstPitch) + pScrn->virtualX - y2; + srcPtr = (CARD16*)pNv->ShadowPtr + + ((1 - y2) * srcPitch) + pbox->x1; + } else { + dstPtr = (CARD16*)pNv->FbStart + + ((pScrn->virtualY - pbox->x2) * dstPitch) + y1; + srcPtr = (CARD16*)pNv->ShadowPtr + + (y1 * srcPitch) + pbox->x2 - 1; + } + + while(width--) { + src = srcPtr; + dst = (CARD32*)dstPtr; + count = height; + while(count--) { + *(dst++) = src[0] | (src[srcPitch] << 16); + src += srcPitch * 2; + } + srcPtr += pNv->Rotate; + dstPtr += dstPitch; + } + + pbox++; + } +} + + +void +NVRefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + NVPtr pNv = NVPTR(pScrn); + int count, width, height, dstPitch, srcPitch; + CARD32 *dstPtr, *srcPtr, *src, *dst; + + dstPitch = pScrn->displayWidth; + srcPitch = -pNv->Rotate * pNv->ShadowPitch >> 2; + + while(num--) { + width = pbox->x2 - pbox->x1; + height = pbox->y2 - pbox->y1; + + if(pNv->Rotate == 1) { + dstPtr = (CARD32*)pNv->FbStart + + (pbox->x1 * dstPitch) + pScrn->virtualX - pbox->y2; + srcPtr = (CARD32*)pNv->ShadowPtr + + ((1 - pbox->y2) * srcPitch) + pbox->x1; + } else { + dstPtr = (CARD32*)pNv->FbStart + + ((pScrn->virtualY - pbox->x2) * dstPitch) + pbox->y1; + srcPtr = (CARD32*)pNv->ShadowPtr + + (pbox->y1 * srcPitch) + pbox->x2 - 1; + } + + while(width--) { + src = srcPtr; + dst = dstPtr; + count = height; + while(count--) { + *(dst++) = *src; + src += srcPitch; + } + srcPtr += pNv->Rotate; + dstPtr += dstPitch; + } + + pbox++; + } +} + + + diff --git a/src/nv_type.h b/src/nv_type.h new file mode 100644 index 0000000..9e9e2bd --- /dev/null +++ b/src/nv_type.h @@ -0,0 +1,135 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_type.h,v 1.39 2002/11/28 23:02:13 mvojkovi Exp $ */ + +#ifndef __NV_STRUCT_H__ +#define __NV_STRUCT_H__ + +#include "riva_hw.h" +#include "colormapst.h" +#include "vgaHW.h" +#include "xaa.h" +#include "xf86Cursor.h" +#include "xf86int10.h" + + +#define BITMASK(t,b) (((unsigned)(1U << (((t)-(b)+1)))-1) << (b)) +#define MASKEXPAND(mask) BITMASK(1?mask,0?mask) +#define SetBF(mask,value) ((value) << (0?mask)) +#define GetBF(var,mask) (((unsigned)((var) & MASKEXPAND(mask))) >> (0?mask) ) +#define SetBitField(value,from,to) SetBF(to, GetBF(value,from)) +#define SetBit(n) (1<<(n)) +#define Set8Bits(value) ((value)&0xff) + +typedef RIVA_HW_STATE* NVRegPtr; + +typedef struct { + Bool isHwCursor; + int CursorMaxWidth; + int CursorMaxHeight; + int CursorFlags; + int CursorOffscreenMemSize; + Bool (*UseHWCursor)(ScreenPtr, CursorPtr); + void (*LoadCursorImage)(ScrnInfoPtr, unsigned char*); + void (*ShowCursor)(ScrnInfoPtr); + void (*HideCursor)(ScrnInfoPtr); + void (*SetCursorPosition)(ScrnInfoPtr, int, int); + void (*SetCursorColors)(ScrnInfoPtr, int, int); + long maxPixelClock; + void (*LoadPalette)(ScrnInfoPtr, int, int*, LOCO*, VisualPtr); + void (*Save)(ScrnInfoPtr, vgaRegPtr, NVRegPtr, Bool); + void (*Restore)(ScrnInfoPtr, vgaRegPtr, NVRegPtr, Bool); + Bool (*ModeInit)(ScrnInfoPtr, DisplayModePtr); +} NVRamdacRec, *NVRamdacPtr; + +typedef struct { + int bitsPerPixel; + int depth; + int displayWidth; + rgb weight; + DisplayModePtr mode; +} NVFBLayout; + +typedef struct { + RIVA_HW_INST riva; + RIVA_HW_STATE SavedReg; + RIVA_HW_STATE ModeReg; + EntityInfoPtr pEnt; + pciVideoPtr PciInfo; + PCITAG PciTag; + xf86AccessRec Access; + int Chipset; + int ChipRev; + Bool Primary; + CARD32 IOAddress; + unsigned long FbAddress; + int FbBaseReg; + unsigned char * IOBase; + unsigned char * FbBase; + unsigned char * FbStart; + long FbMapSize; + long FbUsableSize; + NVRamdacRec Dac; + Bool NoAccel; + Bool HWCursor; + Bool ShowCache; + Bool ShadowFB; + unsigned char * ShadowPtr; + int ShadowPitch; + int MinClock; + int MaxClock; + XAAInfoRecPtr AccelInfoRec; + xf86CursorInfoPtr CursorInfoRec; + DGAModePtr DGAModes; + int numDGAModes; + Bool DGAactive; + int DGAViewportStatus; + void (*Save)(ScrnInfoPtr, vgaRegPtr, NVRegPtr, Bool); + void (*Restore)(ScrnInfoPtr, vgaRegPtr, NVRegPtr, Bool); + Bool (*ModeInit)(ScrnInfoPtr, DisplayModePtr); + void (*PointerMoved)(int index, int x, int y); + ScreenBlockHandlerProcPtr BlockHandler; + CloseScreenProcPtr CloseScreen; + Bool FBDev; + /* Color expansion */ + unsigned char *expandBuffer; + unsigned char *expandFifo; + int expandWidth; + int expandRows; + CARD32 FgColor; + CARD32 BgColor; + int Rotate; + NVFBLayout CurrentLayout; + /* Cursor */ + CARD32 curFg, curBg; + CARD32 curImage[256]; + /* Misc flags */ + unsigned int opaqueMonochrome; + int currentRop; + /* I2C / DDC */ + unsigned int (*ddc1Read)(ScrnInfoPtr); + void (*DDC1SetSpeed)(ScrnInfoPtr, xf86ddcSpeed); + Bool (*i2cInit)(ScrnInfoPtr); + I2CBusPtr I2C; + xf86Int10InfoPtr pInt; + void (*VideoTimerCallback)(ScrnInfoPtr, Time); + XF86VideoAdaptorPtr overlayAdaptor; + int videoKey; + int FlatPanel; + Bool FPDither; + Bool SecondCRTC; + int forceCRTC; + OptionInfoPtr Options; + Bool alphaCursor; + unsigned char DDCBase; +} NVRec, *NVPtr; + +#define NVPTR(p) ((NVPtr)((p)->driverPrivate)) + +void NVRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox); +void NVRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox); +void NVRefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox); +void NVRefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox); +void NVPointerMoved(int index, int x, int y); + +int RivaGetConfig(NVPtr); + +#endif /* __NV_STRUCT_H__ */ diff --git a/src/nv_video.c b/src/nv_video.c new file mode 100644 index 0000000..e2010a9 --- /dev/null +++ b/src/nv_video.c @@ -0,0 +1,1160 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_video.c,v 1.11 2002/11/26 23:41:59 mvojkovi Exp $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "xf86_ansic.h" +#include "compiler.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" +#include "xf86fbman.h" +#include "regionstr.h" + +#include "xf86xv.h" +#include "Xv.h" +#include "xaa.h" +#include "xaalocal.h" +#include "dixstruct.h" +#include "fourcc.h" + +#include "nv_include.h" + + +#define OFF_DELAY 450 /* milliseconds */ +#define FREE_DELAY 10000 + +#define OFF_TIMER 0x01 +#define FREE_TIMER 0x02 +#define CLIENT_VIDEO_ON 0x04 + +#define TIMER_MASK (OFF_TIMER | FREE_TIMER) + + + +#ifndef XvExtension +void NVInitVideo(ScreenPtr pScreen) {} +#else + +typedef struct _NVPortPrivRec { + short brightness; + short contrast; + short saturation; + short hue; + RegionRec clip; + CARD32 colorKey; + Bool autopaintColorKey; + Bool doubleBuffer; + CARD32 videoStatus; + int currentBuffer; + Time videoTime; + Bool grabbedByV4L; + Bool iturbt_709; + FBLinearPtr linear; + int pitch; + int offset; +} NVPortPrivRec, *NVPortPrivPtr; + + +static XF86VideoAdaptorPtr NVSetupImageVideo(ScreenPtr); + +static void NVStopOverlay (ScrnInfoPtr); +static void NVPutOverlayImage(ScrnInfoPtr pScrnInfo, + int offset, + int id, + int dstPitch, + BoxPtr dstBox, + int x1, int y1, int x2, int y2, + short width, short height, + short src_w, short src_h, + short dst_w, short dst_h, + RegionPtr cliplist); + +static int NVSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); +static int NVGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); + +static void NVStopOverlayVideo(ScrnInfoPtr, pointer, Bool); + +static int NVPutImage( ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer); +static void NVQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, unsigned int *, unsigned int *, pointer); +static int NVQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, unsigned short *, int *, int *); + +static void NVVideoTimerCallback(ScrnInfoPtr, Time); + +static void NVInitOffscreenImages (ScreenPtr pScreen); + + +#define GET_OVERLAY_PRIVATE(pNv) \ + (NVPortPrivPtr)((pNv)->overlayAdaptor->pPortPrivates[0].ptr) + +#define GET_BLIT_PRIVATE(pNv) \ + (NVPortPrivPtr)((pNv)->blitAdaptor->pPortPrivates[0].ptr) + +#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) + +static Atom xvBrightness, xvContrast, xvColorKey, xvSaturation, + xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer, + xvITURBT709; + +/* client libraries expect an encoding */ +static XF86VideoEncodingRec DummyEncoding = +{ + 0, + "XV_IMAGE", + 2046, 2046, + {1, 1} +}; + +#define NUM_FORMATS_ALL 6 + +XF86VideoFormatRec NVFormats[NUM_FORMATS_ALL] = +{ + {15, TrueColor}, {16, TrueColor}, {24, TrueColor}, + {15, DirectColor}, {16, DirectColor}, {24, DirectColor} +}; + +#define NUM_ATTRIBUTES 9 + +XF86AttributeRec NVAttributes[NUM_ATTRIBUTES] = +{ + {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"}, + {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, + {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"}, + {XvSettable , 0, 0, "XV_SET_DEFAULTS"}, + {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"}, + {XvSettable | XvGettable, 0, 8191, "XV_CONTRAST"}, + {XvSettable | XvGettable, 0, 8191, "XV_SATURATION"}, + {XvSettable | XvGettable, 0, 360, "XV_HUE"}, + {XvSettable | XvGettable, 0, 1, "XV_ITURBT_709"} +}; + +#define NUM_IMAGES_ALL 4 + +static XF86ImageRec NVImages[NUM_IMAGES_ALL] = +{ + XVIMAGE_YUY2, + XVIMAGE_YV12, + XVIMAGE_UYVY, + XVIMAGE_I420 +}; + +static void +NVSetPortDefaults (ScrnInfoPtr pScrnInfo, NVPortPrivPtr pPriv) +{ + NVPtr pNv = NVPTR(pScrnInfo); + + pPriv->brightness = 0; + pPriv->contrast = 4096; + pPriv->saturation = 4096; + pPriv->hue = 0; + pPriv->colorKey = pNv->videoKey; + pPriv->autopaintColorKey = TRUE; + pPriv->doubleBuffer = TRUE; + pPriv->iturbt_709 = FALSE; +} + + +void +NVResetVideo (ScrnInfoPtr pScrnInfo) +{ + NVPtr pNv = NVPTR(pScrnInfo); + NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); + RIVA_HW_INST *pRiva = &(pNv->riva); + int satSine, satCosine; + double angle; + + angle = (double)pPriv->hue * 3.1415927 / 180.0; + + satSine = pPriv->saturation * sin(angle); + if (satSine < -1024) + satSine = -1024; + satCosine = pPriv->saturation * cos(angle); + if (satCosine < -1024) + satCosine = -1024; + + pRiva->PMC[0x00008910/4] = (pPriv->brightness << 16) | pPriv->contrast; + pRiva->PMC[0x00008914/4] = (pPriv->brightness << 16) | pPriv->contrast; + pRiva->PMC[0x00008918/4] = (satSine << 16) | (satCosine & 0xffff); + pRiva->PMC[0x0000891C/4] = (satSine << 16) | (satCosine & 0xffff); + pRiva->PMC[0x00008b00/4] = pPriv->colorKey; +} + + + +static void +NVStopOverlay (ScrnInfoPtr pScrnInfo) +{ + NVPtr pNv = NVPTR(pScrnInfo); + RIVA_HW_INST *pRiva = &(pNv->riva); + + pRiva->PMC[0x00008704/4] = 1; +} + +static FBLinearPtr +NVAllocateOverlayMemory( + ScrnInfoPtr pScrn, + FBLinearPtr linear, + int size +){ + ScreenPtr pScreen; + FBLinearPtr new_linear; + + if(linear) { + if(linear->size >= size) + return linear; + + if(xf86ResizeOffscreenLinear(linear, size)) + return linear; + + xf86FreeOffscreenLinear(linear); + } + + pScreen = screenInfo.screens[pScrn->scrnIndex]; + + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 32, + NULL, NULL, NULL); + + if(!new_linear) { + int max_size; + + xf86QueryLargestOffscreenLinear(pScreen, &max_size, 32, + PRIORITY_EXTREME); + + if(max_size < size) + return NULL; + + xf86PurgeUnlockedOffscreenAreas(pScreen); + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 32, + NULL, NULL, NULL); + } + + return new_linear; +} + +static void NVFreeOverlayMemory(ScrnInfoPtr pScrnInfo) +{ + NVPtr pNv = NVPTR(pScrnInfo); + NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); + + if(pPriv->linear) { + xf86FreeOffscreenLinear(pPriv->linear); + pPriv->linear = NULL; + } +} + + +void NVInitVideo (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; + XF86VideoAdaptorPtr overlayAdaptor = NULL; + NVPtr pNv = NVPTR(pScrn); + int num_adaptors; + + if((pScrn->bitsPerPixel != 8) && (pNv->riva.Architecture >= NV_ARCH_10)) + { + overlayAdaptor = NVSetupImageVideo(pScreen); + + if(overlayAdaptor) + NVInitOffscreenImages(pScreen); + } + + num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); + + if(overlayAdaptor) { + int size = num_adaptors + 1; + + if((newAdaptors = xalloc(size * sizeof(XF86VideoAdaptorPtr*)))) { + if(num_adaptors) + memcpy(newAdaptors, adaptors, + num_adaptors * sizeof(XF86VideoAdaptorPtr)); + + if(overlayAdaptor) { + newAdaptors[num_adaptors] = overlayAdaptor; + num_adaptors++; + } + adaptors = newAdaptors; + } + } + + if (num_adaptors) + xf86XVScreenInit(pScreen, adaptors, num_adaptors); + + if (newAdaptors) + xfree(newAdaptors); +} + + +static XF86VideoAdaptorPtr +NVSetupImageVideo (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrnInfo = xf86Screens[pScreen->myNum]; + NVPtr pNv = NVPTR(pScrnInfo); + XF86VideoAdaptorPtr adapt; + NVPortPrivPtr pPriv; + + if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + + sizeof(NVPortPrivRec) + + sizeof(DevUnion)))) + { + return NULL; + } + + adapt->type = XvWindowMask | XvInputMask | XvImageMask; + adapt->flags = VIDEO_OVERLAID_IMAGES|VIDEO_CLIP_TO_VIEWPORT; + adapt->name = "NV Video Overlay"; + adapt->nEncodings = 1; + adapt->pEncodings = &DummyEncoding; + adapt->nFormats = NUM_FORMATS_ALL; + adapt->pFormats = NVFormats; + adapt->nPorts = 1; + adapt->pPortPrivates = (DevUnion*)(&adapt[1]); + pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]); + adapt->pPortPrivates[0].ptr = (pointer)(pPriv); + adapt->pAttributes = NVAttributes; + adapt->nAttributes = NUM_ATTRIBUTES; + adapt->pImages = NVImages; + adapt->nImages = NUM_IMAGES_ALL; + adapt->PutVideo = NULL; + adapt->PutStill = NULL; + adapt->GetVideo = NULL; + adapt->GetStill = NULL; + adapt->StopVideo = NVStopOverlayVideo; + adapt->SetPortAttribute = NVSetPortAttribute; + adapt->GetPortAttribute = NVGetPortAttribute; + adapt->QueryBestSize = NVQueryBestSize; + adapt->PutImage = NVPutImage; + adapt->QueryImageAttributes = NVQueryImageAttributes; + + pPriv->videoStatus = 0; + pPriv->currentBuffer = 0; + pPriv->grabbedByV4L = FALSE; + + NVSetPortDefaults (pScrnInfo, pPriv); + + /* gotta uninit this someplace */ + REGION_INIT(pScreen, &pPriv->clip, NullBox, 0); + + pNv->overlayAdaptor = adapt; + + xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); + xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER"); + xvContrast = MAKE_ATOM("XV_CONTRAST"); + xvColorKey = MAKE_ATOM("XV_COLORKEY"); + xvSaturation = MAKE_ATOM("XV_SATURATION"); + xvHue = MAKE_ATOM("XV_HUE"); + xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); + xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS"); + xvITURBT709 = MAKE_ATOM("XV_ITURBT_709"); + + NVResetVideo(pScrnInfo); + + return adapt; +} + +/* + * RegionsEqual + */ +static Bool RegionsEqual +( + RegionPtr A, + RegionPtr B +) +{ + int *dataA, *dataB; + int num; + + num = REGION_NUM_RECTS(A); + if (num != REGION_NUM_RECTS(B)) + return FALSE; + + if ((A->extents.x1 != B->extents.x1) || + (A->extents.x2 != B->extents.x2) || + (A->extents.y1 != B->extents.y1) || + (A->extents.y2 != B->extents.y2)) + return FALSE; + + dataA = (int*)REGION_RECTS(A); + dataB = (int*)REGION_RECTS(B); + + while(num--) + { + if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1])) + return FALSE; + dataA += 2; + dataB += 2; + } + return TRUE; +} + +static void +NVPutOverlayImage ( + ScrnInfoPtr pScrnInfo, + int offset, + int id, + int dstPitch, + BoxPtr dstBox, + int x1, + int y1, + int x2, + int y2, + short width, + short height, + short src_w, + short src_h, + short drw_w, + short drw_h, + RegionPtr clipBoxes +) +{ + NVPtr pNv = NVPTR(pScrnInfo); + NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); + RIVA_HW_INST *pRiva = &(pNv->riva); + int buffer = pPriv->currentBuffer; + + /* paint the color key */ + if(pPriv->autopaintColorKey && + (pPriv->grabbedByV4L || !RegionsEqual(&pPriv->clip, clipBoxes))) + { + /* we always paint V4L's color key */ + if(!pPriv->grabbedByV4L) + REGION_COPY(pScrnInfo->pScreen, &pPriv->clip, clipBoxes); + xf86XVFillKeyHelper(pScrnInfo->pScreen, pPriv->colorKey, clipBoxes); + } + + pRiva->PMC[(0x8900/4) + buffer] = offset; + pRiva->PMC[(0x8928/4) + buffer] = (height << 16) | width; + pRiva->PMC[(0x8930/4) + buffer] = ((y1 << 4) & 0xffff0000) | (x1 >> 12); + pRiva->PMC[(0x8938/4) + buffer] = (src_w << 20) / drw_w; + pRiva->PMC[(0x8940/4) + buffer] = (src_h << 20) / drw_h; + pRiva->PMC[(0x8948/4) + buffer] = (dstBox->y1 << 16) | dstBox->x1; + pRiva->PMC[(0x8950/4) + buffer] = ((dstBox->y2 - dstBox->y1) << 16) | + (dstBox->x2 - dstBox->x1); + + dstPitch |= 1 << 20; /* use color key */ + + if(id != FOURCC_UYVY) + dstPitch |= 1 << 16; + if(pPriv->iturbt_709) + dstPitch |= 1 << 24; + + pRiva->PMC[(0x8958/4) + buffer] = dstPitch; + pRiva->PMC[0x00008704/4] = 0; + pRiva->PMC[0x8700/4] = 1 << (buffer << 2); + + pPriv->videoStatus = CLIENT_VIDEO_ON; +} + + + +/* + * StopVideo + */ +static void NVStopOverlayVideo +( + ScrnInfoPtr pScrnInfo, + pointer data, + Bool Exit +) +{ + NVPtr pNv = NVPTR(pScrnInfo); + NVPortPrivPtr pPriv = (NVPortPrivPtr)data; + + if(pPriv->grabbedByV4L) return; + + REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip); + + if(Exit) + { + if(pPriv->videoStatus & CLIENT_VIDEO_ON) + NVStopOverlay(pScrnInfo); + NVFreeOverlayMemory(pScrnInfo); + pPriv->videoStatus = 0; + pNv->VideoTimerCallback = NULL; + } + else + { + if(pPriv->videoStatus & CLIENT_VIDEO_ON) + { + pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON; + pPriv->videoTime = currentTime.milliseconds + OFF_DELAY; + pNv->VideoTimerCallback = NVVideoTimerCallback; + } + } +} + + + +static int NVSetPortAttribute +( + ScrnInfoPtr pScrnInfo, + Atom attribute, + INT32 value, + pointer data +) +{ + NVPortPrivPtr pPriv = (NVPortPrivPtr)data; + + if (attribute == xvBrightness) + { + if ((value < -512) || (value > 512)) + return BadValue; + pPriv->brightness = value; + } + else if (attribute == xvDoubleBuffer) + { + if ((value < 0) || (value > 1)) + return BadValue; + pPriv->doubleBuffer = value; + } + else if (attribute == xvContrast) + { + if ((value < 0) || (value > 8191)) + return BadValue; + pPriv->contrast = value; + } + else if (attribute == xvHue) + { + value %= 360; + if (value < 0) + value += 360; + pPriv->hue = value; + } + else if (attribute == xvSaturation) + { + if ((value < 0) || (value > 8191)) + return BadValue; + pPriv->saturation = value; + } + else if (attribute == xvColorKey) + { + pPriv->colorKey = value; + REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip); + } + else if (attribute == xvAutopaintColorKey) + { + if ((value < 0) || (value > 1)) + return BadValue; + pPriv->autopaintColorKey = value; + } + else if (attribute == xvITURBT709) + { + if ((value < 0) || (value > 1)) + return BadValue; + pPriv->iturbt_709 = value; + } + else if (attribute == xvSetDefaults) + { + NVSetPortDefaults(pScrnInfo, pPriv); + } + else + return BadMatch; + + NVResetVideo(pScrnInfo); + return Success; +} + + + + +static int NVGetPortAttribute +( + ScrnInfoPtr pScrnInfo, + Atom attribute, + INT32 *value, + pointer data +) +{ + NVPortPrivPtr pPriv = (NVPortPrivPtr)data; + + if (attribute == xvBrightness) + *value = pPriv->brightness; + else if (attribute == xvDoubleBuffer) + *value = (pPriv->doubleBuffer) ? 1 : 0; + else if (attribute == xvContrast) + *value = pPriv->contrast; + else if (attribute == xvSaturation) + *value = pPriv->saturation; + else if (attribute == xvHue) + *value = pPriv->hue; + else if (attribute == xvColorKey) + *value = pPriv->colorKey; + else if (attribute == xvAutopaintColorKey) + *value = (pPriv->autopaintColorKey) ? 1 : 0; + else if (attribute == xvITURBT709) + *value = (pPriv->iturbt_709) ? 1 : 0; + else + return BadMatch; + + return Success; +} + + +/* + * QueryBestSize + */ +static void NVQueryBestSize +( + ScrnInfoPtr pScrnInfo, + Bool motion, + short vid_w, + short vid_h, + short drw_w, + short drw_h, + unsigned int *p_w, + unsigned int *p_h, + pointer data +) +{ + if(vid_w > (drw_w << 3)) + drw_w = vid_w >> 3; + if(vid_h > (drw_h << 3)) + drw_h = vid_h >> 3; + + *p_w = drw_w; + *p_h = drw_h; +} +/* + * CopyData + */ +static void NVCopyData422 +( + unsigned char *src, + unsigned char *dst, + int srcPitch, + int dstPitch, + int h, + int w +) +{ + w <<= 1; + while(h--) + { + memcpy(dst, src, w); + src += srcPitch; + dst += dstPitch; + } +} +/* + * CopyMungedData + */ +static void NVCopyData420 +( + unsigned char *src1, + unsigned char *src2, + unsigned char *src3, + unsigned char *dst1, + int srcPitch, + int srcPitch2, + int dstPitch, + int h, + int w +) +{ + CARD32 *dst; + CARD8 *s1, *s2, *s3; + int i, j; + + w >>= 1; + + for(j = 0; j < h; j++) { + dst = (CARD32*)dst1; + s1 = src1; s2 = src2; s3 = src3; + i = w; + while(i > 4) { +#if X_BYTE_ORDER == X_BIG_ENDIAN + dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0]; + dst[1] = (s1[2] << 24) | (s1[3] << 8) | (s3[1] << 16) | s2[1]; + dst[2] = (s1[4] << 24) | (s1[5] << 8) | (s3[2] << 16) | s2[2]; + dst[3] = (s1[6] << 24) | (s1[7] << 8) | (s3[3] << 16) | s2[3]; +#else + dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24); + dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24); + dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24); + dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24); +#endif + dst += 4; s2 += 4; s3 += 4; s1 += 8; + i -= 4; + } + + while(i--) { +#if X_BYTE_ORDER == X_BIG_ENDIAN + dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0]; +#else + dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24); +#endif + dst++; s2++; s3++; + s1 += 2; + } + + dst1 += dstPitch; + src1 += srcPitch; + if(j & 1) { + src2 += srcPitch2; + src3 += srcPitch2; + } + } +} +/* + * PutImage + */ +static int NVPutImage +( + ScrnInfoPtr pScrnInfo, + short src_x, + short src_y, + short drw_x, + short drw_y, + short src_w, + short src_h, + short drw_w, + short drw_h, + int id, + unsigned char *buf, + short width, + short height, + Bool Sync, + RegionPtr clipBoxes, + pointer data +) +{ + NVPortPrivPtr pPriv = (NVPortPrivPtr)data; + NVPtr pNv = NVPTR(pScrnInfo); + INT32 xa, xb, ya, yb; + unsigned char *dst_start; + int pitch, newSize, offset, s2offset, s3offset; + int srcPitch, srcPitch2, dstPitch; + int top, left, npixels, nlines, bpp; + Bool skip = FALSE; + BoxRec dstBox; + CARD32 tmp; + + /* + * s2offset, s3offset - byte offsets into U and V plane of the + * source where copying starts. Y plane is + * done by editing "buf". + * + * offset - byte offset to the first line of the destination. + * + * dst_start - byte address to the first displayed pel. + * + */ + + if(pPriv->grabbedByV4L) return Success; + + /* make the compiler happy */ + s2offset = s3offset = srcPitch2 = 0; + + if(src_w > (drw_w << 3)) + drw_w = src_w >> 3; + if(src_h > (drw_h << 3)) + drw_h = src_h >> 3; + + /* Clip */ + xa = src_x; + xb = src_x + src_w; + ya = src_y; + yb = src_y + src_h; + + dstBox.x1 = drw_x; + dstBox.x2 = drw_x + drw_w; + dstBox.y1 = drw_y; + dstBox.y2 = drw_y + drw_h; + + if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, + width, height)) + return Success; + + dstBox.x1 -= pScrnInfo->frameX0; + dstBox.x2 -= pScrnInfo->frameX0; + dstBox.y1 -= pScrnInfo->frameY0; + dstBox.y2 -= pScrnInfo->frameY0; + + bpp = pScrnInfo->bitsPerPixel >> 3; + pitch = bpp * pScrnInfo->displayWidth; + + dstPitch = ((width << 1) + 63) & ~63; + + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + srcPitch = (width + 3) & ~3; /* of luma */ + s2offset = srcPitch * height; + srcPitch2 = ((width >> 1) + 3) & ~3; + s3offset = (srcPitch2 * (height >> 1)) + s2offset; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + srcPitch = (width << 1); + break; + } + + newSize = height * dstPitch / bpp; + + if(pPriv->doubleBuffer) + newSize <<= 1; + + pPriv->linear = NVAllocateOverlayMemory(pScrnInfo, + pPriv->linear, + newSize); + + if(!pPriv->linear) return BadAlloc; + + offset = pPriv->linear->offset * bpp; + + if(pPriv->doubleBuffer) { + RIVA_HW_INST *pRiva = &(pNv->riva); + int mask = 1 << (pPriv->currentBuffer << 2); + +#if 0 + /* burn the CPU until the next buffer is available */ + while(pRiva->PMC[0x00008700/4] & mask); +#else + /* overwrite the newest buffer if there's not one free */ + if(pRiva->PMC[0x00008700/4] & mask) { + if(!pPriv->currentBuffer) + offset += (newSize * bpp) >> 1; + skip = TRUE; + } else +#endif + if(pPriv->currentBuffer) + offset += (newSize * bpp) >> 1; + } + + dst_start = pNv->FbStart + offset; + + /* copy data */ + top = ya >> 16; + left = (xa >> 16) & ~1; + npixels = ((((xb + 0xffff) >> 16) + 1) & ~1) - left; + + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + top &= ~1; + dst_start += (left << 1) + (top * dstPitch); + tmp = ((top >> 1) * srcPitch2) + (left >> 1); + s2offset += tmp; + s3offset += tmp; + if(id == FOURCC_I420) { + tmp = s2offset; + s2offset = s3offset; + s3offset = tmp; + } + nlines = ((((yb + 0xffff) >> 16) + 1) & ~1) - top; + NVCopyData420(buf + (top * srcPitch) + left, buf + s2offset, + buf + s3offset, dst_start, srcPitch, srcPitch2, + dstPitch, nlines, npixels); + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + left <<= 1; + buf += (top * srcPitch) + left; + nlines = ((yb + 0xffff) >> 16) - top; + dst_start += left + (top * dstPitch); + NVCopyData422(buf, dst_start, srcPitch, dstPitch, nlines, npixels); + break; + } + + if(!skip) { + NVPutOverlayImage(pScrnInfo, offset, id, dstPitch, &dstBox, + xa, ya, xb, yb, + width, height, src_w, src_h, drw_w, drw_h, clipBoxes); + pPriv->currentBuffer ^= 1; + } + + return Success; +} +/* + * QueryImageAttributes + */ +static int NVQueryImageAttributes +( + ScrnInfoPtr pScrnInfo, + int id, + unsigned short *w, + unsigned short *h, + int *pitches, + int *offsets +) +{ + int size, tmp; + + if(*w > 2046) + *w = 2046; + if(*h > 2046) + *h = 2046; + + *w = (*w + 1) & ~1; + if (offsets) + offsets[0] = 0; + + switch (id) + { + case FOURCC_YV12: + case FOURCC_I420: + *h = (*h + 1) & ~1; + size = (*w + 3) & ~3; + if (pitches) + pitches[0] = size; + size *= *h; + if (offsets) + offsets[1] = size; + tmp = ((*w >> 1) + 3) & ~3; + if (pitches) + pitches[1] = pitches[2] = tmp; + tmp *= (*h >> 1); + size += tmp; + if (offsets) + offsets[2] = size; + size += tmp; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + size = *w << 1; + if (pitches) + pitches[0] = size; + size *= *h; + break; + } + return size; +} + +static void NVVideoTimerCallback +( + ScrnInfoPtr pScrnInfo, + Time currentTime +) +{ + NVPtr pNv = NVPTR(pScrnInfo); + NVPortPrivPtr pOverPriv = NULL; + + pNv->VideoTimerCallback = NULL; + + if(!pScrnInfo->vtSema) return; + + if(pNv->overlayAdaptor) { + pOverPriv = GET_OVERLAY_PRIVATE(pNv); + if(!pOverPriv->videoStatus) + pOverPriv = NULL; + } + + if(pOverPriv) { + if(pOverPriv->videoTime < currentTime) { + if(pOverPriv->videoStatus & OFF_TIMER) { + NVStopOverlay(pScrnInfo); + pOverPriv->videoStatus = FREE_TIMER; + pOverPriv->videoTime = currentTime + FREE_DELAY; + pNv->VideoTimerCallback = NVVideoTimerCallback; + } else + if(pOverPriv->videoStatus & FREE_TIMER) { + NVFreeOverlayMemory(pScrnInfo); + pOverPriv->videoStatus = 0; + } + } else + pNv->VideoTimerCallback = NVVideoTimerCallback; + } +} + + +/***** Exported offscreen surface stuff ****/ + + +static int +NVAllocSurface ( + ScrnInfoPtr pScrnInfo, + int id, + unsigned short w, + unsigned short h, + XF86SurfacePtr surface +) +{ + NVPtr pNv = NVPTR(pScrnInfo); + NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); + CARD8 *address; + int size, bpp; + + bpp = pScrnInfo->bitsPerPixel >> 3; + + if(pPriv->grabbedByV4L) return BadAlloc; + + if((w > 2046) || (h > 2046)) return BadValue; + + w = (w + 1) & ~1; + pPriv->pitch = ((w << 1) + 63) & ~63; + size = h * pPriv->pitch / bpp; + + pPriv->linear = NVAllocateOverlayMemory(pScrnInfo, pPriv->linear, + size); + + if(!pPriv->linear) return BadAlloc; + + pPriv->offset = pPriv->linear->offset * bpp; + address = pPriv->offset + pNv->FbStart; + + surface->width = w; + surface->height = h; + surface->pScrn = pScrnInfo; + surface->pitches = &pPriv->pitch; + surface->offsets = &pPriv->offset; + surface->devPrivate.ptr = (pointer)pPriv; + surface->id = id; + + /* grab the video */ + NVStopOverlay(pScrnInfo); + pPriv->videoStatus = 0; + REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip); + pNv->VideoTimerCallback = NULL; + pPriv->grabbedByV4L = TRUE; + + return Success; +} + +static int +NVStopSurface (XF86SurfacePtr surface) +{ + NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr); + + if(pPriv->grabbedByV4L && pPriv->videoStatus) { + NVStopOverlay(surface->pScrn); + pPriv->videoStatus = 0; + } + + return Success; +} + +static int +NVFreeSurface (XF86SurfacePtr surface) +{ + NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr); + + if(pPriv->grabbedByV4L) { + NVStopSurface(surface); + NVFreeOverlayMemory(surface->pScrn); + pPriv->grabbedByV4L = FALSE; + } + + return Success; +} + +static int +NVGetSurfaceAttribute ( + ScrnInfoPtr pScrnInfo, + Atom attribute, + INT32 *value +) +{ + NVPtr pNv = NVPTR(pScrnInfo); + NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); + + return NVGetPortAttribute(pScrnInfo, attribute, value, (pointer)pPriv); +} + +static int +NVSetSurfaceAttribute( + ScrnInfoPtr pScrnInfo, + Atom attribute, + INT32 value +) +{ + NVPtr pNv = NVPTR(pScrnInfo); + NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); + + return NVSetPortAttribute(pScrnInfo, attribute, value, (pointer)pPriv); +} + +static int +NVDisplaySurface ( + XF86SurfacePtr surface, + short src_x, short src_y, + short drw_x, short drw_y, + short src_w, short src_h, + short drw_w, short drw_h, + RegionPtr clipBoxes +) +{ + ScrnInfoPtr pScrnInfo = surface->pScrn; + NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr); + INT32 xa, xb, ya, yb; + BoxRec dstBox; + + if(!pPriv->grabbedByV4L) return Success; + + if(src_w > (drw_w << 3)) + drw_w = src_w >> 3; + if(src_h > (drw_h << 3)) + drw_h = src_h >> 3; + + /* Clip */ + xa = src_x; + xb = src_x + src_w; + ya = src_y; + yb = src_y + src_h; + + dstBox.x1 = drw_x; + dstBox.x2 = drw_x + drw_w; + dstBox.y1 = drw_y; + dstBox.y2 = drw_y + drw_h; + + if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, + surface->width, surface->height)) + { + return Success; + } + + dstBox.x1 -= pScrnInfo->frameX0; + dstBox.x2 -= pScrnInfo->frameX0; + dstBox.y1 -= pScrnInfo->frameY0; + dstBox.y2 -= pScrnInfo->frameY0; + + pPriv->currentBuffer = 0; + + NVPutOverlayImage (pScrnInfo, surface->offsets[0], surface->id, + surface->pitches[0], &dstBox, xa, ya, xb, yb, + surface->width, surface->height, src_w, src_h, + drw_w, drw_h, clipBoxes); + + return Success; +} + +XF86OffscreenImageRec NVOffscreenImages[2] = +{ + { + &NVImages[0], + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, + NVAllocSurface, + NVFreeSurface, + NVDisplaySurface, + NVStopSurface, + NVGetSurfaceAttribute, + NVSetSurfaceAttribute, + 2046, 2046, + NUM_ATTRIBUTES - 1, + &NVAttributes[1] + }, + { + &NVImages[2], + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, + NVAllocSurface, + NVFreeSurface, + NVDisplaySurface, + NVStopSurface, + NVGetSurfaceAttribute, + NVSetSurfaceAttribute, + 2046, 2046, + NUM_ATTRIBUTES - 1, + &NVAttributes[1] + }, +}; + +static void +NVInitOffscreenImages (ScreenPtr pScreen) +{ + xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2); +} + +#endif + + diff --git a/src/nv_xaa.c b/src/nv_xaa.c new file mode 100644 index 0000000..e4400b6 --- /dev/null +++ b/src/nv_xaa.c @@ -0,0 +1,573 @@ +/* $XConsortium: nv_driver.c /main/3 1996/10/28 05:13:37 kaleb $ */ + /***************************************************************************\ +|* *| +|* Copyright 1993-1999 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 *| +|* hereby granted a nonexclusive, royalty-free copyright license to *| +|* use this code in individual and commercial software. *| +|* *| +|* Any use of this source code must include, in the user documenta- *| +|* tion and internal comments to the code, notices to the end user *| +|* as follows: *| +|* *| +|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| +|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| +|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| +|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| +|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| +|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| +|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| +|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| +|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| +|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| +|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| +|* *| +|* U.S. Government End Users. This source code is a "commercial *| +|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| +|* consisting of "commercial computer software" and "commercial *| +|* computer software documentation," as such terms are used in *| +|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| +|* ment only as a commercial end item. Consistent with 48 C.F.R. *| +|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| +|* all U.S. Government End Users acquire the source code with only *| +|* those rights set forth herein. *| +|* *| + \***************************************************************************/ + +/* 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_xaa.c,v 1.29 2003/02/12 21:26:27 mvojkovi Exp $ */ + +#include "nv_include.h" +#include "xaalocal.h" +#include "xaarop.h" + +#include "miline.h" + +static void +NVSetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2) +{ + int height = y2-y1 + 1; + int width = x2-x1 + 1; + NVPtr pNv = NVPTR(pScrn); + + RIVA_FIFO_FREE(pNv->riva, Clip, 2); + pNv->riva.Clip->TopLeft = (y1 << 16) | (x1 & 0xffff); + pNv->riva.Clip->WidthHeight = (height << 16) | width; +} + + +static void +NVDisableClipping(ScrnInfoPtr pScrn) +{ + NVSetClippingRectangle(pScrn, 0, 0, 0x7fff, 0x7fff); +} + +/* + * Set pattern. Internal routine. The upper bits of the colors + * are the ALPHA bits. 0 == transparency. + */ +static void +NVSetPattern(NVPtr pNv, int clr0, int clr1, int pat0, int pat1) +{ + RIVA_FIFO_FREE(pNv->riva, Patt, 5); + pNv->riva.Patt->Shape = 0; /* 0 = 8X8, 1 = 64X1, 2 = 1X64 */ + pNv->riva.Patt->Color0 = clr0; + pNv->riva.Patt->Color1 = clr1; + pNv->riva.Patt->Monochrome[0] = pat0; + pNv->riva.Patt->Monochrome[1] = pat1; +} + +/* + * Set ROP. Translate X rop into ROP3. Internal routine. + */ +static void +NVSetRopSolid(NVPtr pNv, int rop) +{ + if (pNv->currentRop != rop) + { + if (pNv->currentRop > 16) + NVSetPattern(pNv, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); + pNv->currentRop = rop; + RIVA_FIFO_FREE(pNv->riva, Rop, 1); + pNv->riva.Rop->Rop3 = XAACopyROP[rop]; + } +} + +static void +NVSetRopPattern(NVPtr pNv, int rop) +{ + if (pNv->currentRop != rop + 16) + { + pNv->currentRop = rop + 16; /* +16 is important */ + RIVA_FIFO_FREE(pNv->riva, Rop, 1); + pNv->riva.Rop->Rop3 = XAAPatternROP[rop]; + } +} + +/* + * Fill solid rectangles. + */ +static +void NVSetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, + unsigned planemask) +{ + NVPtr pNv = NVPTR(pScrn); + + NVSetRopSolid(pNv, rop); + RIVA_FIFO_FREE(pNv->riva, Bitmap, 1); + pNv->riva.Bitmap->Color1A = color; +} + +static void +NVSubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) +{ + NVPtr pNv = NVPTR(pScrn); + + RIVA_FIFO_FREE(pNv->riva, Bitmap, 2); + pNv->riva.Bitmap->UnclippedRectangle[0].TopLeft = (x << 16) | y; + write_mem_barrier(); + pNv->riva.Bitmap->UnclippedRectangle[0].WidthHeight = (w << 16) | h; + write_mem_barrier(); +} + +/* + * Screen to screen BLTs. + */ +static void +NVSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, + unsigned planemask, int transparency_color) +{ + NVSetRopSolid(NVPTR(pScrn), rop); +} + +static void +NVSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, + int x2, int y2, int w, int h) +{ + NVPtr pNv = NVPTR(pScrn); + + RIVA_FIFO_FREE(pNv->riva, Blt, 3); + pNv->riva.Blt->TopLeftSrc = (y1 << 16) | x1; + pNv->riva.Blt->TopLeftDst = (y2 << 16) | x2; + write_mem_barrier(); + pNv->riva.Blt->WidthHeight = (h << 16) | w; + write_mem_barrier(); +} + + +/* + * Fill 8x8 monochrome pattern rectangles. patternx and patterny are + * the overloaded pattern bits themselves. The pattern colors don't + * support 565, only 555. Hack around it. + */ +static void +NVSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patternx, int patterny, + int fg, int bg, int rop, unsigned planemask) +{ + NVPtr pNv = NVPTR(pScrn); + + NVSetRopPattern(pNv, rop); + if (pScrn->depth == 16) + { + fg = ((fg & 0x0000F800) << 8) + | ((fg & 0x000007E0) << 5) + | ((fg & 0x0000001F) << 3) + | 0xFF000000; + if (bg != -1) + bg = ((bg & 0x0000F800) << 8) + | ((bg & 0x000007E0) << 5) + | ((bg & 0x0000001F) << 3) + | 0xFF000000; + else + bg = 0; + } + else + { + fg |= pNv->opaqueMonochrome; + bg = (bg == -1) ? 0 : bg | pNv->opaqueMonochrome; + }; + NVSetPattern(pNv, bg, fg, patternx, patterny); + RIVA_FIFO_FREE(pNv->riva, Bitmap, 1); + pNv->riva.Bitmap->Color1A = fg; +} + +static void +NVSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, + int patternx, int patterny, + int x, int y, int w, int h) +{ + NVPtr pNv = NVPTR(pScrn); + + RIVA_FIFO_FREE(pNv->riva, Bitmap, 2); + pNv->riva.Bitmap->UnclippedRectangle[0].TopLeft = (x << 16) | y; + write_mem_barrier(); + pNv->riva.Bitmap->UnclippedRectangle[0].WidthHeight = (w << 16) | h; + write_mem_barrier(); +} + + +void +NVResetGraphics(ScrnInfoPtr pScrn) +{ + NVPtr pNv = NVPTR(pScrn); + + if(pNv->NoAccel) return; + + pNv->currentRop = -1; + NVSetRopPattern(pNv, GXcopy); +} + + + +/* + * Synchronise with graphics engine. Make sure it is idle before returning. + * Should attempt to yield CPU if busy for awhile. + */ +void NVSync(ScrnInfoPtr pScrn) +{ + NVPtr pNv = NVPTR(pScrn); + RIVA_BUSY(pNv->riva); +} + +/* Color expansion */ +static void +NVSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask) +{ + NVPtr pNv = NVPTR(pScrn); + + NVSetRopSolid(pNv, rop); + + if ( bg == -1 ) + { + /* Transparent case */ + bg = 0x80000000; + pNv->expandFifo = (unsigned char*)&pNv->riva.Bitmap->MonochromeData1C; + } + else + { + pNv->expandFifo = (unsigned char*)&pNv->riva.Bitmap->MonochromeData01E; + if (pScrn->depth == 16) + { + bg = ((bg & 0x0000F800) << 8) + | ((bg & 0x000007E0) << 5) + | ((bg & 0x0000001F) << 3) + | 0xFF000000; + } + else + { + bg |= pNv->opaqueMonochrome; + }; + } + pNv->FgColor = fg; + pNv->BgColor = bg; +} + +static void +NVSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) +{ + NVPtr pNv = NVPTR(pScrn); + + int t = pNv->expandWidth; + CARD32 *pbits = (CARD32*)pNv->expandBuffer; + CARD32 *d = (CARD32*)pNv->expandFifo; + + while(t >= 16) + { + RIVA_FIFO_FREE(pNv->riva, Bitmap, 16); + d[0] = pbits[0]; + d[1] = pbits[1]; + d[2] = pbits[2]; + d[3] = pbits[3]; + d[4] = pbits[4]; + d[5] = pbits[5]; + d[6] = pbits[6]; + d[7] = pbits[7]; + d[8] = pbits[8]; + d[9] = pbits[9]; + d[10] = pbits[10]; + d[11] = pbits[11]; + d[12] = pbits[12]; + d[13] = pbits[13]; + d[14] = pbits[14]; + d[15] = pbits[15]; + t -= 16; pbits += 16; + } + if(t) { + RIVA_FIFO_FREE(pNv->riva, Bitmap, t); + while(t >= 4) + { + d[0] = pbits[0]; + d[1] = pbits[1]; + d[2] = pbits[2]; + d[3] = pbits[3]; + t -= 4; pbits += 4; + } + while(t--) + *(d++) = *(pbits++); + } + + if (!(--pNv->expandRows)) { /* hardware bug workaround */ + RIVA_FIFO_FREE(pNv->riva, Blt, 1); + write_mem_barrier(); + pNv->riva.Blt->TopLeftSrc = 0; + } + write_mem_barrier(); +} + +static void +NVSubsequentColorExpandScanlineFifo(ScrnInfoPtr pScrn, int bufno) +{ + NVPtr pNv = NVPTR(pScrn); + + if ( --pNv->expandRows ) { + RIVA_FIFO_FREE(pNv->riva, Bitmap, pNv->expandWidth); + } else { /* hardware bug workaround */ + RIVA_FIFO_FREE(pNv->riva, Blt, 1); + write_mem_barrier(); + pNv->riva.Blt->TopLeftSrc = 0; + } + write_mem_barrier(); +} + +static void +NVSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int x, + int y, int w, int h, + int skipleft) +{ + int bw; + NVPtr pNv = NVPTR(pScrn); + + bw = (w + 31) & ~31; + pNv->expandWidth = bw >> 5; + + if ( pNv->BgColor == 0x80000000 ) + { + /* Use faster transparent method */ + RIVA_FIFO_FREE(pNv->riva, Bitmap, 5); + pNv->riva.Bitmap->ClipC.TopLeft = (y << 16) | ((x+skipleft) + & 0xFFFF); + pNv->riva.Bitmap->ClipC.BottomRight = ((y+h) << 16) | ((x+w)&0xffff); + pNv->riva.Bitmap->Color1C = pNv->FgColor; + pNv->riva.Bitmap->WidthHeightC = (h << 16) | bw; + write_mem_barrier(); + pNv->riva.Bitmap->PointC = (y << 16) | (x & 0xFFFF); + write_mem_barrier(); + } + else + { + /* Opaque */ + RIVA_FIFO_FREE(pNv->riva, Bitmap, 7); + pNv->riva.Bitmap->ClipE.TopLeft = (y << 16) | ((x+skipleft) + & 0xFFFF); + pNv->riva.Bitmap->ClipE.BottomRight = ((y+h) << 16) | ((x+w)&0xffff); + pNv->riva.Bitmap->Color0E = pNv->BgColor; + pNv->riva.Bitmap->Color1E = pNv->FgColor; + pNv->riva.Bitmap->WidthHeightInE = (h << 16) | bw; + pNv->riva.Bitmap->WidthHeightOutE = (h << 16) | bw; + write_mem_barrier(); + pNv->riva.Bitmap->PointE = (y << 16) | (x & 0xFFFF); + write_mem_barrier(); + } + + pNv->expandRows = h; + + if(pNv->expandWidth > (pNv->riva.FifoEmptyCount >> 2)) { + pNv->AccelInfoRec->ScanlineColorExpandBuffers = &pNv->expandBuffer; + pNv->AccelInfoRec->SubsequentColorExpandScanline = + NVSubsequentColorExpandScanline; + } else { + pNv->AccelInfoRec->ScanlineColorExpandBuffers = &pNv->expandFifo; + pNv->AccelInfoRec->SubsequentColorExpandScanline = + NVSubsequentColorExpandScanlineFifo; + RIVA_FIFO_FREE(pNv->riva, Bitmap, pNv->expandWidth); + } +} + +static void +NVSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop, unsigned planemask) +{ + NVPtr pNv = NVPTR(pScrn); + + NVSetRopSolid(pNv, rop); + pNv->FgColor = color; +} + +static void +NVSubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len, int dir) +{ + NVPtr pNv = NVPTR(pScrn); + + RIVA_FIFO_FREE(pNv->riva, Line, 3); + pNv->riva.Line->Color = pNv->FgColor; + pNv->riva.Line->Lin[0].point0 = ((y << 16) | ( x & 0xffff)); + write_mem_barrier(); + if ( dir ==DEGREES_0 ) + pNv->riva.Line->Lin[0].point1 = ((y << 16) | (( x + len ) & 0xffff)); + else + pNv->riva.Line->Lin[0].point1 = (((y + len) << 16) | ( x & 0xffff)); + write_mem_barrier(); +} + +static void +NVSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1, + int x2, int y2, int flags) +{ + NVPtr pNv = NVPTR(pScrn); + Bool lastPoint = !(flags & OMIT_LAST); + + RIVA_FIFO_FREE(pNv->riva, Line, lastPoint ? 5 : 3); + pNv->riva.Line->Color = pNv->FgColor; + pNv->riva.Line->Lin[0].point0 = ((y1 << 16) | (x1 & 0xffff)); + write_mem_barrier(); + pNv->riva.Line->Lin[0].point1 = ((y2 << 16) | (x2 & 0xffff)); + write_mem_barrier(); + if (lastPoint) + { + pNv->riva.Line->Lin[1].point0 = ((y2 << 16) | (x2 & 0xffff)); + write_mem_barrier(); + pNv->riva.Line->Lin[1].point1 = (((y2 + 1) << 16) | (x2 & 0xffff)); + write_mem_barrier(); + } +} + +static void +NVValidatePolyArc( + GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw +){ + if(pGC->planemask != ~0) return; + + if(!pGC->lineWidth && + ((pGC->alu != GXcopy) || (pGC->lineStyle != LineSolid))) + { + pGC->ops->PolyArc = miZeroPolyArc; + } +} + +static void +NVValidatePolyPoint( + GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw +){ + pGC->ops->PolyPoint = XAAFallbackOps.PolyPoint; + + if(pGC->planemask != ~0) return; + + if(pGC->alu != GXcopy) + pGC->ops->PolyPoint = miPolyPoint; +} + +/* Initialize XAA acceleration info */ +Bool +NVAccelInit(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoPtr; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + NVPtr pNv = NVPTR(pScrn); + Bool lowClocks; + + /* The hardware POSTs with clocks too low to support some acceleration + on NV20 and higher and we don't know enough about timing particulars + to raise them */ + + lowClocks = ((pNv->Chipset & 0x0ff0) >= 0x0200); + + pNv->AccelInfoRec = infoPtr = XAACreateInfoRec(); + if(!infoPtr) return FALSE; + + /* fill out infoPtr here */ + infoPtr->Flags = LINEAR_FRAMEBUFFER | PIXMAP_CACHE | OFFSCREEN_PIXMAPS; + + /* sync */ + infoPtr->Sync = NVSync; + + /* solid fills */ + infoPtr->SolidFillFlags = NO_PLANEMASK; + infoPtr->SetupForSolidFill = NVSetupForSolidFill; + infoPtr->SubsequentSolidFillRect = NVSubsequentSolidFillRect; + + if(lowClocks) + infoPtr->SolidFillFlags |= GXCOPY_ONLY; + + /* screen to screen copy */ + infoPtr->ScreenToScreenCopyFlags = NO_TRANSPARENCY | NO_PLANEMASK; + infoPtr->SetupForScreenToScreenCopy = NVSetupForScreenToScreenCopy; + infoPtr->SubsequentScreenToScreenCopy = NVSubsequentScreenToScreenCopy; + + /* 8x8 mono patterns */ + /* + * Set pattern opaque bits based on pixel format. + */ + pNv->opaqueMonochrome = ~((1 << pScrn->depth) - 1); + + pNv->currentRop = -1; + + infoPtr->Mono8x8PatternFillFlags = HARDWARE_PATTERN_SCREEN_ORIGIN | + HARDWARE_PATTERN_PROGRAMMED_BITS | + NO_PLANEMASK; + infoPtr->SetupForMono8x8PatternFill = NVSetupForMono8x8PatternFill; + infoPtr->SubsequentMono8x8PatternFillRect = + NVSubsequentMono8x8PatternFillRect; + + /* Color expansion */ + infoPtr->ScanlineCPUToScreenColorExpandFillFlags = +#if X_BYTE_ORDER == X_BIG_ENDIAN + BIT_ORDER_IN_BYTE_MSBFIRST | +#else + BIT_ORDER_IN_BYTE_LSBFIRST | +#endif + NO_PLANEMASK | + CPU_TRANSFER_PAD_DWORD | + LEFT_EDGE_CLIPPING | + LEFT_EDGE_CLIPPING_NEGATIVE_X; + + infoPtr->NumScanlineColorExpandBuffers = 1; + + if(!lowClocks) { + infoPtr->SetupForScanlineCPUToScreenColorExpandFill = + NVSetupForScanlineCPUToScreenColorExpandFill; + infoPtr->SubsequentScanlineCPUToScreenColorExpandFill = + NVSubsequentScanlineCPUToScreenColorExpandFill; + } + + pNv->expandFifo = (unsigned char*)&pNv->riva.Bitmap->MonochromeData01E; + + /* Allocate buffer for color expansion and also image writes in the + future */ + pNv->expandBuffer = xnfalloc(((pScrn->virtualX*pScrn->bitsPerPixel)/8) + 8); + + + infoPtr->ScanlineColorExpandBuffers = &pNv->expandBuffer; + infoPtr->SubsequentColorExpandScanline = NVSubsequentColorExpandScanline; + + infoPtr->SolidLineFlags = infoPtr->SolidFillFlags; + infoPtr->SetupForSolidLine = NVSetupForSolidLine; + infoPtr->SubsequentSolidHorVertLine = + NVSubsequentSolidHorVertLine; + infoPtr->SubsequentSolidTwoPointLine = + NVSubsequentSolidTwoPointLine; + infoPtr->SetClippingRectangle = NVSetClippingRectangle; + infoPtr->DisableClipping = NVDisableClipping; + infoPtr->ClippingFlags = HARDWARE_CLIP_SOLID_LINE; + miSetZeroLineBias(pScreen, OCTANT1 | OCTANT3 | OCTANT4 | OCTANT6); + + infoPtr->ValidatePolyArc = NVValidatePolyArc; + infoPtr->PolyArcMask = GCFunction | GCLineWidth | GCPlaneMask; + infoPtr->ValidatePolyPoint = NVValidatePolyPoint; + infoPtr->PolyPointMask = GCFunction | GCPlaneMask; + + NVDisableClipping(pScrn); + + return(XAAInit(pScreen, infoPtr)); +} + diff --git a/src/riva_hw.c b/src/riva_hw.c new file mode 100644 index 0000000..bbb515f --- /dev/null +++ b/src/riva_hw.c @@ -0,0 +1,2100 @@ + /***************************************************************************\ +|* *| +|* Copyright 1993-1999 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 *| +|* hereby granted a nonexclusive, royalty-free copyright license to *| +|* use this code in individual and commercial software. *| +|* *| +|* Any use of this source code must include, in the user documenta- *| +|* tion and internal comments to the code, notices to the end user *| +|* as follows: *| +|* *| +|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| +|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| +|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| +|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| +|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| +|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| +|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| +|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| +|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| +|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| +|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| +|* *| +|* U.S. Government End Users. This source code is a "commercial *| +|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| +|* consisting of "commercial computer software" and "commercial *| +|* computer software documentation," as such terms are used in *| +|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| +|* ment only as a commercial end item. Consistent with 48 C.F.R. *| +|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| +|* all U.S. Government End Users acquire the source code with only *| +|* those rights set forth herein. *| +|* *| + \***************************************************************************/ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_hw.c,v 1.47 2003/02/10 23:42:51 mvojkovi Exp $ */ + +#include "nv_local.h" +#include "compiler.h" +#include "nv_include.h" +#include "riva_hw.h" +#include "riva_tbl.h" + +/* + * This file is an OS-agnostic file used to make RIVA 128 and RIVA TNT + * operate identically (except TNT has more memory and better 3D quality. + */ +static int nv3Busy +( + RIVA_HW_INST *chip +) +{ + return ((chip->Rop->FifoFree < chip->FifoEmptyCount) || (chip->PGRAPH[0x000006B0/4] & 0x01)); +} +static int nv4Busy +( + RIVA_HW_INST *chip +) +{ + return ((chip->Rop->FifoFree < chip->FifoEmptyCount) || (chip->PGRAPH[0x00000700/4] & 0x01)); +} +static int nv10Busy +( + RIVA_HW_INST *chip +) +{ + return ((chip->Rop->FifoFree < chip->FifoEmptyCount) || (chip->PGRAPH[0x00000700/4] & 0x01)); +} +static void vgaLockUnlock +( + RIVA_HW_INST *chip, + Bool Lock +) +{ + CARD8 cr11; + VGA_WR08(chip->PCIO, 0x3D4, 0x11); + cr11 = VGA_RD08(chip->PCIO, 0x3D5); + if(Lock) cr11 |= 0x80; + else cr11 &= ~0x80; + VGA_WR08(chip->PCIO, 0x3D5, cr11); +} + +static void nv3LockUnlock +( + RIVA_HW_INST *chip, + Bool Lock +) +{ + VGA_WR08(chip->PVIO, 0x3C4, 0x06); + VGA_WR08(chip->PVIO, 0x3C5, Lock ? 0x99 : 0x57); + vgaLockUnlock(chip, Lock); +} +static void nv4LockUnlock +( + RIVA_HW_INST *chip, + Bool Lock +) +{ + VGA_WR08(chip->PCIO, 0x3D4, 0x1F); + VGA_WR08(chip->PCIO, 0x3D5, Lock ? 0x99 : 0x57); + vgaLockUnlock(chip, Lock); +} +static int ShowHideCursor +( + RIVA_HW_INST *chip, + int ShowHide +) +{ + int current; + current = chip->CurrentState->cursor1; + chip->CurrentState->cursor1 = (chip->CurrentState->cursor1 & 0xFE) | + (ShowHide & 0x01); + VGA_WR08(chip->PCIO, 0x3D4, 0x31); + VGA_WR08(chip->PCIO, 0x3D5, chip->CurrentState->cursor1); + return (current & 0x01); +} + +/****************************************************************************\ +* * +* The video arbitration routines calculate some "magic" numbers. Fixes * +* the snow seen when accessing the framebuffer without it. * +* It just works (I hope). * +* * +\****************************************************************************/ + +#define DEFAULT_GR_LWM 100 +#define DEFAULT_VID_LWM 100 +#define DEFAULT_GR_BURST_SIZE 256 +#define DEFAULT_VID_BURST_SIZE 128 +#define VIDEO 0 +#define GRAPHICS 1 +#define MPORT 2 +#define ENGINE 3 +#define GFIFO_SIZE 320 +#define GFIFO_SIZE_128 256 +#define MFIFO_SIZE 120 +#define VFIFO_SIZE 256 +#define ABS(a) (a>0?a:-a) +typedef struct { + int gdrain_rate; + int vdrain_rate; + int mdrain_rate; + int gburst_size; + int vburst_size; + char vid_en; + char gr_en; + int wcmocc, wcgocc, wcvocc, wcvlwm, wcglwm; + int by_gfacc; + char vid_only_once; + char gr_only_once; + char first_vacc; + char first_gacc; + char first_macc; + int vocc; + int gocc; + int mocc; + char cur; + char engine_en; + char converged; + int priority; +} nv3_arb_info; +typedef struct { + int graphics_lwm; + int video_lwm; + int graphics_burst_size; + int video_burst_size; + int graphics_hi_priority; + int media_hi_priority; + int rtl_values; + int valid; +} nv3_fifo_info; +typedef struct { + char pix_bpp; + char enable_video; + char gr_during_vid; + char enable_mp; + int memory_width; + int video_scale; + int pclk_khz; + int mclk_khz; + int mem_page_miss; + int mem_latency; + char mem_aligned; +} nv3_sim_state; +typedef struct { + int graphics_lwm; + int video_lwm; + int graphics_burst_size; + int video_burst_size; + int valid; +} nv4_fifo_info; +typedef struct { + int pclk_khz; + int mclk_khz; + int nvclk_khz; + char mem_page_miss; + char mem_latency; + int memory_width; + char enable_video; + char gr_during_vid; + char pix_bpp; + char mem_aligned; + char enable_mp; +} nv4_sim_state; +typedef struct { + int graphics_lwm; + int video_lwm; + int graphics_burst_size; + int video_burst_size; + int valid; +} nv10_fifo_info; +typedef struct { + int pclk_khz; + int mclk_khz; + int nvclk_khz; + char mem_page_miss; + char mem_latency; + int memory_type; + int memory_width; + char enable_video; + char gr_during_vid; + char pix_bpp; + char mem_aligned; + char enable_mp; +} nv10_sim_state; +static int nv3_iterate(nv3_fifo_info *res_info, nv3_sim_state * state, nv3_arb_info *ainfo) +{ + int iter = 0; + int tmp; + int vfsize, mfsize, gfsize; + int mburst_size = 32; + int mmisses, gmisses, vmisses; + int misses; + int vlwm, glwm, mlwm; + int last, next, cur; + int max_gfsize ; + long ns; + + vlwm = 0; + glwm = 0; + mlwm = 0; + vfsize = 0; + gfsize = 0; + cur = ainfo->cur; + mmisses = 2; + gmisses = 2; + vmisses = 2; + if (ainfo->gburst_size == 128) max_gfsize = GFIFO_SIZE_128; + else max_gfsize = GFIFO_SIZE; + max_gfsize = GFIFO_SIZE; + while (1) + { + if (ainfo->vid_en) + { + if (ainfo->wcvocc > ainfo->vocc) ainfo->wcvocc = ainfo->vocc; + if (ainfo->wcvlwm > vlwm) ainfo->wcvlwm = vlwm ; + ns = 1000000 * ainfo->vburst_size/(state->memory_width/8)/state->mclk_khz; + vfsize = ns * ainfo->vdrain_rate / 1000000; + vfsize = ainfo->wcvlwm - ainfo->vburst_size + vfsize; + } + if (state->enable_mp) + { + if (ainfo->wcmocc > ainfo->mocc) ainfo->wcmocc = ainfo->mocc; + } + if (ainfo->gr_en) + { + if (ainfo->wcglwm > glwm) ainfo->wcglwm = glwm ; + if (ainfo->wcgocc > ainfo->gocc) ainfo->wcgocc = ainfo->gocc; + ns = 1000000 * (ainfo->gburst_size/(state->memory_width/8))/state->mclk_khz; + gfsize = (ns * (long) ainfo->gdrain_rate)/1000000; + gfsize = ainfo->wcglwm - ainfo->gburst_size + gfsize; + } + mfsize = 0; + if (!state->gr_during_vid && ainfo->vid_en) + if (ainfo->vid_en && (ainfo->vocc < 0) && !ainfo->vid_only_once) + next = VIDEO; + else if (ainfo->mocc < 0) + next = MPORT; + else if (ainfo->gocc< ainfo->by_gfacc) + next = GRAPHICS; + else return (0); + else switch (ainfo->priority) + { + case VIDEO: + if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once) + next = VIDEO; + else if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once) + next = GRAPHICS; + else if (ainfo->mocc<0) + next = MPORT; + else return (0); + break; + case GRAPHICS: + if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once) + next = GRAPHICS; + else if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once) + next = VIDEO; + else if (ainfo->mocc<0) + next = MPORT; + else return (0); + break; + default: + if (ainfo->mocc<0) + next = MPORT; + else if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once) + next = GRAPHICS; + else if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once) + next = VIDEO; + else return (0); + break; + } + last = cur; + cur = next; + iter++; + switch (cur) + { + case VIDEO: + if (last==cur) misses = 0; + else if (ainfo->first_vacc) misses = vmisses; + else misses = 1; + ainfo->first_vacc = 0; + if (last!=cur) + { + ns = 1000000 * (vmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz; + vlwm = ns * ainfo->vdrain_rate/ 1000000; + vlwm = ainfo->vocc - vlwm; + } + ns = 1000000*(misses*state->mem_page_miss + ainfo->vburst_size)/(state->memory_width/8)/state->mclk_khz; + ainfo->vocc = ainfo->vocc + ainfo->vburst_size - ns*ainfo->vdrain_rate/1000000; + ainfo->gocc = ainfo->gocc - ns*ainfo->gdrain_rate/1000000; + ainfo->mocc = ainfo->mocc - ns*ainfo->mdrain_rate/1000000; + break; + case GRAPHICS: + if (last==cur) misses = 0; + else if (ainfo->first_gacc) misses = gmisses; + else misses = 1; + ainfo->first_gacc = 0; + if (last!=cur) + { + ns = 1000000*(gmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz ; + glwm = ns * ainfo->gdrain_rate/1000000; + glwm = ainfo->gocc - glwm; + } + ns = 1000000*(misses*state->mem_page_miss + ainfo->gburst_size/(state->memory_width/8))/state->mclk_khz; + ainfo->vocc = ainfo->vocc + 0 - ns*ainfo->vdrain_rate/1000000; + ainfo->gocc = ainfo->gocc + ainfo->gburst_size - ns*ainfo->gdrain_rate/1000000; + ainfo->mocc = ainfo->mocc + 0 - ns*ainfo->mdrain_rate/1000000; + break; + default: + if (last==cur) misses = 0; + else if (ainfo->first_macc) misses = mmisses; + else misses = 1; + ainfo->first_macc = 0; + ns = 1000000*(misses*state->mem_page_miss + mburst_size/(state->memory_width/8))/state->mclk_khz; + ainfo->vocc = ainfo->vocc + 0 - ns*ainfo->vdrain_rate/1000000; + ainfo->gocc = ainfo->gocc + 0 - ns*ainfo->gdrain_rate/1000000; + ainfo->mocc = ainfo->mocc + mburst_size - ns*ainfo->mdrain_rate/1000000; + break; + } + if (iter>100) + { + ainfo->converged = 0; + return (1); + } + ns = 1000000*ainfo->gburst_size/(state->memory_width/8)/state->mclk_khz; + tmp = ns * ainfo->gdrain_rate/1000000; + if (ABS(ainfo->gburst_size) + ((ABS(ainfo->wcglwm) + 16 ) & ~0x7) - tmp > max_gfsize) + { + ainfo->converged = 0; + return (1); + } + ns = 1000000*ainfo->vburst_size/(state->memory_width/8)/state->mclk_khz; + tmp = ns * ainfo->vdrain_rate/1000000; + if (ABS(ainfo->vburst_size) + (ABS(ainfo->wcvlwm + 32) & ~0xf) - tmp> VFIFO_SIZE) + { + ainfo->converged = 0; + return (1); + } + if (ABS(ainfo->gocc) > max_gfsize) + { + ainfo->converged = 0; + return (1); + } + if (ABS(ainfo->vocc) > VFIFO_SIZE) + { + ainfo->converged = 0; + return (1); + } + if (ABS(ainfo->mocc) > MFIFO_SIZE) + { + ainfo->converged = 0; + return (1); + } + if (ABS(vfsize) > VFIFO_SIZE) + { + ainfo->converged = 0; + return (1); + } + if (ABS(gfsize) > max_gfsize) + { + ainfo->converged = 0; + return (1); + } + if (ABS(mfsize) > MFIFO_SIZE) + { + ainfo->converged = 0; + return (1); + } + } +} +static char nv3_arb(nv3_fifo_info * res_info, nv3_sim_state * state, nv3_arb_info *ainfo) +{ + long ens, vns, mns, gns; + int mmisses, gmisses, vmisses, eburst_size, mburst_size; + int refresh_cycle; + + refresh_cycle = 0; + refresh_cycle = 2*(state->mclk_khz/state->pclk_khz) + 5; + mmisses = 2; + if (state->mem_aligned) gmisses = 2; + else gmisses = 3; + vmisses = 2; + eburst_size = state->memory_width * 1; + mburst_size = 32; + gns = 1000000 * (gmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz; + ainfo->by_gfacc = gns*ainfo->gdrain_rate/1000000; + ainfo->wcmocc = 0; + ainfo->wcgocc = 0; + ainfo->wcvocc = 0; + ainfo->wcvlwm = 0; + ainfo->wcglwm = 0; + ainfo->engine_en = 1; + ainfo->converged = 1; + if (ainfo->engine_en) + { + ens = 1000000*(state->mem_page_miss + eburst_size/(state->memory_width/8) +refresh_cycle)/state->mclk_khz; + ainfo->mocc = state->enable_mp ? 0-ens*ainfo->mdrain_rate/1000000 : 0; + ainfo->vocc = ainfo->vid_en ? 0-ens*ainfo->vdrain_rate/1000000 : 0; + ainfo->gocc = ainfo->gr_en ? 0-ens*ainfo->gdrain_rate/1000000 : 0; + ainfo->cur = ENGINE; + ainfo->first_vacc = 1; + ainfo->first_gacc = 1; + ainfo->first_macc = 1; + nv3_iterate(res_info, state,ainfo); + } + if (state->enable_mp) + { + mns = 1000000 * (mmisses*state->mem_page_miss + mburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz; + ainfo->mocc = state->enable_mp ? 0 : mburst_size - mns*ainfo->mdrain_rate/1000000; + ainfo->vocc = ainfo->vid_en ? 0 : 0- mns*ainfo->vdrain_rate/1000000; + ainfo->gocc = ainfo->gr_en ? 0: 0- mns*ainfo->gdrain_rate/1000000; + ainfo->cur = MPORT; + ainfo->first_vacc = 1; + ainfo->first_gacc = 1; + ainfo->first_macc = 0; + nv3_iterate(res_info, state,ainfo); + } + if (ainfo->gr_en) + { + ainfo->first_vacc = 1; + ainfo->first_gacc = 0; + ainfo->first_macc = 1; + gns = 1000000*(gmisses*state->mem_page_miss + ainfo->gburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz; + ainfo->gocc = ainfo->gburst_size - gns*ainfo->gdrain_rate/1000000; + ainfo->vocc = ainfo->vid_en? 0-gns*ainfo->vdrain_rate/1000000 : 0; + ainfo->mocc = state->enable_mp ? 0-gns*ainfo->mdrain_rate/1000000: 0; + ainfo->cur = GRAPHICS; + nv3_iterate(res_info, state,ainfo); + } + if (ainfo->vid_en) + { + ainfo->first_vacc = 0; + ainfo->first_gacc = 1; + ainfo->first_macc = 1; + vns = 1000000*(vmisses*state->mem_page_miss + ainfo->vburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz; + ainfo->vocc = ainfo->vburst_size - vns*ainfo->vdrain_rate/1000000; + ainfo->gocc = ainfo->gr_en? (0-vns*ainfo->gdrain_rate/1000000) : 0; + ainfo->mocc = state->enable_mp? 0-vns*ainfo->mdrain_rate/1000000 :0 ; + ainfo->cur = VIDEO; + nv3_iterate(res_info, state, ainfo); + } + if (ainfo->converged) + { + res_info->graphics_lwm = (int)ABS(ainfo->wcglwm) + 16; + res_info->video_lwm = (int)ABS(ainfo->wcvlwm) + 32; + res_info->graphics_burst_size = ainfo->gburst_size; + res_info->video_burst_size = ainfo->vburst_size; + res_info->graphics_hi_priority = (ainfo->priority == GRAPHICS); + res_info->media_hi_priority = (ainfo->priority == MPORT); + if (res_info->video_lwm > 160) + { + res_info->graphics_lwm = 256; + res_info->video_lwm = 128; + res_info->graphics_burst_size = 64; + res_info->video_burst_size = 64; + res_info->graphics_hi_priority = 0; + res_info->media_hi_priority = 0; + ainfo->converged = 0; + return (0); + } + if (res_info->video_lwm > 128) + { + res_info->video_lwm = 128; + } + return (1); + } + else + { + res_info->graphics_lwm = 256; + res_info->video_lwm = 128; + res_info->graphics_burst_size = 64; + res_info->video_burst_size = 64; + res_info->graphics_hi_priority = 0; + res_info->media_hi_priority = 0; + return (0); + } +} +static char nv3_get_param(nv3_fifo_info *res_info, nv3_sim_state * state, nv3_arb_info *ainfo) +{ + int done, g,v, p; + + done = 0; + for (p=0; p < 2; p++) + { + for (g=128 ; g > 32; g= g>> 1) + { + for (v=128; v >=32; v = v>> 1) + { + ainfo->priority = p; + ainfo->gburst_size = g; + ainfo->vburst_size = v; + done = nv3_arb(res_info, state,ainfo); + if (done && (g==128)) + if ((res_info->graphics_lwm + g) > 256) + done = 0; + if (done) + goto Done; + } + } + } + + Done: + return done; +} +static void nv3CalcArbitration +( + nv3_fifo_info * res_info, + nv3_sim_state * state +) +{ + nv3_fifo_info save_info; + nv3_arb_info ainfo; + char res_gr, res_vid; + + ainfo.gr_en = 1; + ainfo.vid_en = state->enable_video; + ainfo.vid_only_once = 0; + ainfo.gr_only_once = 0; + ainfo.gdrain_rate = (int) state->pclk_khz * (state->pix_bpp/8); + ainfo.vdrain_rate = (int) state->pclk_khz * 2; + if (state->video_scale != 0) + ainfo.vdrain_rate = ainfo.vdrain_rate/state->video_scale; + ainfo.mdrain_rate = 33000; + res_info->rtl_values = 0; + if (!state->gr_during_vid && state->enable_video) + { + ainfo.gr_only_once = 1; + ainfo.gr_en = 1; + ainfo.gdrain_rate = 0; + res_vid = nv3_get_param(res_info, state, &ainfo); + res_vid = ainfo.converged; + save_info.video_lwm = res_info->video_lwm; + save_info.video_burst_size = res_info->video_burst_size; + ainfo.vid_en = 1; + ainfo.vid_only_once = 1; + ainfo.gr_en = 1; + ainfo.gdrain_rate = (int) state->pclk_khz * (state->pix_bpp/8); + ainfo.vdrain_rate = 0; + res_gr = nv3_get_param(res_info, state, &ainfo); + res_gr = ainfo.converged; + res_info->video_lwm = save_info.video_lwm; + res_info->video_burst_size = save_info.video_burst_size; + res_info->valid = res_gr & res_vid; + } + else + { + if (!ainfo.gr_en) ainfo.gdrain_rate = 0; + if (!ainfo.vid_en) ainfo.vdrain_rate = 0; + res_gr = nv3_get_param(res_info, state, &ainfo); + res_info->valid = ainfo.converged; + } +} +static void nv3UpdateArbitrationSettings +( + unsigned VClk, + unsigned pixelDepth, + unsigned *burst, + unsigned *lwm, + RIVA_HW_INST *chip +) +{ + nv3_fifo_info fifo_data; + nv3_sim_state sim_data; + unsigned int M, N, P, pll, MClk; + + pll = chip->PRAMDAC0[0x00000504/4]; + M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; + MClk = (N * chip->CrystalFreqKHz / M) >> P; + sim_data.pix_bpp = (char)pixelDepth; + sim_data.enable_video = 0; + sim_data.enable_mp = 0; + sim_data.video_scale = 1; + sim_data.memory_width = (chip->PEXTDEV[0x00000000/4] & 0x10) ? 128 : 64; + sim_data.memory_width = 128; + + sim_data.mem_latency = 9; + sim_data.mem_aligned = 1; + sim_data.mem_page_miss = 11; + sim_data.gr_during_vid = 0; + sim_data.pclk_khz = VClk; + sim_data.mclk_khz = MClk; + nv3CalcArbitration(&fifo_data, &sim_data); + if (fifo_data.valid) + { + int b = fifo_data.graphics_burst_size >> 4; + *burst = 0; + while (b >>= 1) (*burst)++; + *lwm = fifo_data.graphics_lwm >> 3; + } + else + { + *lwm = 0x24; + *burst = 0x2; + } +} +static void nv4CalcArbitration +( + nv4_fifo_info *fifo, + nv4_sim_state *arb +) +{ + int data, pagemiss, cas,width, video_enable, color_key_enable, bpp, align; + int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs; + int found, mclk_extra, mclk_loop, cbs, m1, p1; + int mclk_freq, pclk_freq, nvclk_freq, mp_enable; + int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate; + int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt,clwm; + int craw, vraw; + + fifo->valid = 1; + pclk_freq = arb->pclk_khz; + mclk_freq = arb->mclk_khz; + nvclk_freq = arb->nvclk_khz; + pagemiss = arb->mem_page_miss; + cas = arb->mem_latency; + width = arb->memory_width >> 6; + video_enable = arb->enable_video; + color_key_enable = arb->gr_during_vid; + bpp = arb->pix_bpp; + align = arb->mem_aligned; + mp_enable = arb->enable_mp; + clwm = 0; + vlwm = 0; + cbs = 128; + pclks = 2; + nvclks = 2; + nvclks += 2; + nvclks += 1; + mclks = 5; + mclks += 3; + mclks += 1; + mclks += cas; + mclks += 1; + mclks += 1; + mclks += 1; + mclks += 1; + mclk_extra = 3; + nvclks += 2; + nvclks += 1; + nvclks += 1; + nvclks += 1; + if (mp_enable) + mclks+=4; + nvclks += 0; + pclks += 0; + found = 0; + vbs = 0; + while (found != 1) + { + fifo->valid = 1; + found = 1; + mclk_loop = mclks+mclk_extra; + us_m = mclk_loop *1000*1000 / mclk_freq; + us_n = nvclks*1000*1000 / nvclk_freq; + us_p = nvclks*1000*1000 / pclk_freq; + if (video_enable) + { + video_drain_rate = pclk_freq * 2; + crtc_drain_rate = pclk_freq * bpp/8; + vpagemiss = 2; + vpagemiss += 1; + crtpagemiss = 2; + vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq; + if (nvclk_freq * 2 > mclk_freq * width) + video_fill_us = cbs*1000*1000 / 16 / nvclk_freq ; + else + video_fill_us = cbs*1000*1000 / (8 * width) / mclk_freq; + us_video = vpm_us + us_m + us_n + us_p + video_fill_us; + vlwm = us_video * video_drain_rate/(1000*1000); + vlwm++; + vbs = 128; + if (vlwm > 128) vbs = 64; + if (vlwm > (256-64)) vbs = 32; + if (nvclk_freq * 2 > mclk_freq * width) + video_fill_us = vbs *1000*1000/ 16 / nvclk_freq ; + else + video_fill_us = vbs*1000*1000 / (8 * width) / mclk_freq; + cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq; + us_crt = + us_video + +video_fill_us + +cpm_us + +us_m + us_n +us_p + ; + clwm = us_crt * crtc_drain_rate/(1000*1000); + clwm++; + } + else + { + crtc_drain_rate = pclk_freq * bpp/8; + crtpagemiss = 2; + crtpagemiss += 1; + cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq; + us_crt = cpm_us + us_m + us_n + us_p ; + clwm = us_crt * crtc_drain_rate/(1000*1000); + clwm++; + } + m1 = clwm + cbs - 512; + p1 = m1 * pclk_freq / mclk_freq; + p1 = p1 * bpp / 8; + if ((p1 < m1) && (m1 > 0)) + { + fifo->valid = 0; + found = 0; + if (mclk_extra ==0) found = 1; + mclk_extra--; + } + else if (video_enable) + { + if ((clwm > 511) || (vlwm > 255)) + { + fifo->valid = 0; + found = 0; + if (mclk_extra ==0) found = 1; + mclk_extra--; + } + } + else + { + if (clwm > 519) + { + fifo->valid = 0; + found = 0; + if (mclk_extra ==0) found = 1; + mclk_extra--; + } + } + craw = clwm; + vraw = vlwm; + if (clwm < 384) clwm = 384; + if (vlwm < 128) vlwm = 128; + data = (int)(clwm); + fifo->graphics_lwm = data; + fifo->graphics_burst_size = 128; + data = (int)((vlwm+15)); + fifo->video_lwm = data; + fifo->video_burst_size = vbs; + } +} +static void nv4UpdateArbitrationSettings +( + unsigned VClk, + unsigned pixelDepth, + unsigned *burst, + unsigned *lwm, + RIVA_HW_INST *chip +) +{ + nv4_fifo_info fifo_data; + nv4_sim_state sim_data; + unsigned int M, N, P, pll, MClk, NVClk, cfg1; + + pll = chip->PRAMDAC0[0x00000504/4]; + M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; + MClk = (N * chip->CrystalFreqKHz / M) >> P; + pll = chip->PRAMDAC0[0x00000500/4]; + M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; + NVClk = (N * chip->CrystalFreqKHz / M) >> P; + cfg1 = chip->PFB[0x00000204/4]; + sim_data.pix_bpp = (char)pixelDepth; + sim_data.enable_video = 0; + sim_data.enable_mp = 0; + sim_data.memory_width = (chip->PEXTDEV[0x00000000/4] & 0x10) ? 128 : 64; + sim_data.mem_latency = (char)cfg1 & 0x0F; + sim_data.mem_aligned = 1; + sim_data.mem_page_miss = (char)(((cfg1 >> 4) &0x0F) + ((cfg1 >> 31) & 0x01)); + sim_data.gr_during_vid = 0; + sim_data.pclk_khz = VClk; + sim_data.mclk_khz = MClk; + sim_data.nvclk_khz = NVClk; + nv4CalcArbitration(&fifo_data, &sim_data); + if (fifo_data.valid) + { + int b = fifo_data.graphics_burst_size >> 4; + *burst = 0; + while (b >>= 1) (*burst)++; + *lwm = fifo_data.graphics_lwm >> 3; + } +} +static void nv10CalcArbitration +( + nv10_fifo_info *fifo, + nv10_sim_state *arb +) +{ + int data, pagemiss, cas,width, video_enable, color_key_enable, bpp, align; + int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs; + int nvclk_fill, us_extra; + int found, mclk_extra, mclk_loop, cbs, m1; + int mclk_freq, pclk_freq, nvclk_freq, mp_enable; + int us_m, us_m_min, us_n, us_p, video_drain_rate, crtc_drain_rate; + int vus_m, vus_n, vus_p; + int vpm_us, us_video, vlwm, cpm_us, us_crt,clwm; + int clwm_rnd_down; + int craw, m2us, us_pipe, us_pipe_min, vus_pipe, p1clk, p2; + int pclks_2_top_fifo, min_mclk_extra; + int us_min_mclk_extra; + + fifo->valid = 1; + pclk_freq = arb->pclk_khz; /* freq in KHz */ + mclk_freq = arb->mclk_khz; + nvclk_freq = arb->nvclk_khz; + pagemiss = arb->mem_page_miss; + cas = arb->mem_latency; + width = arb->memory_width/64; + video_enable = arb->enable_video; + color_key_enable = arb->gr_during_vid; + bpp = arb->pix_bpp; + align = arb->mem_aligned; + mp_enable = arb->enable_mp; + clwm = 0; + vlwm = 1024; + + cbs = 512; + vbs = 512; + + pclks = 4; /* lwm detect. */ + + nvclks = 3; /* lwm -> sync. */ + nvclks += 2; /* fbi bus cycles (1 req + 1 busy) */ + + mclks = 1; /* 2 edge sync. may be very close to edge so just put one. */ + + mclks += 1; /* arb_hp_req */ + mclks += 5; /* ap_hp_req tiling pipeline */ + + mclks += 2; /* tc_req latency fifo */ + mclks += 2; /* fb_cas_n_ memory request to fbio block */ + mclks += 7; /* sm_d_rdv data returned from fbio block */ + + /* fb.rd.d.Put_gc need to accumulate 256 bits for read */ + if (arb->memory_type == 0) + if (arb->memory_width == 64) /* 64 bit bus */ + mclks += 4; + else + mclks += 2; + else + if (arb->memory_width == 64) /* 64 bit bus */ + mclks += 2; + else + mclks += 1; + + if ((!video_enable) && (arb->memory_width == 128)) + { + mclk_extra = (bpp == 32) ? 31 : 42; /* Margin of error */ + min_mclk_extra = 17; + } + else + { + mclk_extra = (bpp == 32) ? 8 : 4; /* Margin of error */ + /* mclk_extra = 4; */ /* Margin of error */ + min_mclk_extra = 18; + } + + nvclks += 1; /* 2 edge sync. may be very close to edge so just put one. */ + nvclks += 1; /* fbi_d_rdv_n */ + nvclks += 1; /* Fbi_d_rdata */ + nvclks += 1; /* crtfifo load */ + + if(mp_enable) + mclks+=4; /* Mp can get in with a burst of 8. */ + /* Extra clocks determined by heuristics */ + + nvclks += 0; + pclks += 0; + found = 0; + while(found != 1) { + fifo->valid = 1; + found = 1; + mclk_loop = mclks+mclk_extra; + us_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */ + us_m_min = mclks * 1000*1000 / mclk_freq; /* Minimum Mclk latency in us */ + us_min_mclk_extra = min_mclk_extra *1000*1000 / mclk_freq; + us_n = nvclks*1000*1000 / nvclk_freq;/* nvclk latency in us */ + us_p = pclks*1000*1000 / pclk_freq;/* nvclk latency in us */ + us_pipe = us_m + us_n + us_p; + us_pipe_min = us_m_min + us_n + us_p; + us_extra = 0; + + vus_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */ + vus_n = (4)*1000*1000 / nvclk_freq;/* nvclk latency in us */ + vus_p = 0*1000*1000 / pclk_freq;/* pclk latency in us */ + vus_pipe = vus_m + vus_n + vus_p; + + if(video_enable) { + video_drain_rate = pclk_freq * 4; /* MB/s */ + crtc_drain_rate = pclk_freq * bpp/8; /* MB/s */ + + vpagemiss = 1; /* self generating page miss */ + vpagemiss += 1; /* One higher priority before */ + + crtpagemiss = 2; /* self generating page miss */ + if(mp_enable) + crtpagemiss += 1; /* if MA0 conflict */ + + vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq; + + us_video = vpm_us + vus_m; /* Video has separate read return path */ + + cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq; + us_crt = + us_video /* Wait for video */ + +cpm_us /* CRT Page miss */ + +us_m + us_n +us_p /* other latency */ + ; + + clwm = us_crt * crtc_drain_rate/(1000*1000); + clwm++; /* fixed point <= float_point - 1. Fixes that */ + } else { + crtc_drain_rate = pclk_freq * bpp/8; /* bpp * pclk/8 */ + + crtpagemiss = 1; /* self generating page miss */ + crtpagemiss += 1; /* MA0 page miss */ + if(mp_enable) + crtpagemiss += 1; /* if MA0 conflict */ + cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq; + us_crt = cpm_us + us_m + us_n + us_p ; + clwm = us_crt * crtc_drain_rate/(1000*1000); + clwm++; /* fixed point <= float_point - 1. Fixes that */ + + /* + // + // Another concern, only for high pclks so don't do this + // with video: + // What happens if the latency to fetch the cbs is so large that + // fifo empties. In that case we need to have an alternate clwm value + // based off the total burst fetch + // + us_crt = (cbs * 1000 * 1000)/ (8*width)/mclk_freq ; + us_crt = us_crt + us_m + us_n + us_p + (4 * 1000 * 1000)/mclk_freq; + clwm_mt = us_crt * crtc_drain_rate/(1000*1000); + clwm_mt ++; + if(clwm_mt > clwm) + clwm = clwm_mt; + */ + /* Finally, a heuristic check when width == 64 bits */ + if(width == 1){ + nvclk_fill = nvclk_freq * 8; + if(crtc_drain_rate * 100 >= nvclk_fill * 102) + clwm = 0xfff; /*Large number to fail */ + + else if(crtc_drain_rate * 100 >= nvclk_fill * 98) { + clwm = 1024; + cbs = 512; + us_extra = (cbs * 1000 * 1000)/ (8*width)/mclk_freq ; + } + } + } + + + /* + Overfill check: + + */ + + clwm_rnd_down = ((int)clwm/8)*8; + if (clwm_rnd_down < clwm) + clwm += 8; + + m1 = clwm + cbs - 1024; /* Amount of overfill */ + m2us = us_pipe_min + us_min_mclk_extra; + pclks_2_top_fifo = (1024-clwm)/(8*width); + + /* pclk cycles to drain */ + p1clk = m2us * pclk_freq/(1000*1000); + p2 = p1clk * bpp / 8; /* bytes drained. */ + + if((p2 < m1) && (m1 > 0)) { + fifo->valid = 0; + found = 0; + if(min_mclk_extra == 0) { + if(cbs <= 32) { + found = 1; /* Can't adjust anymore! */ + } else { + cbs = cbs/2; /* reduce the burst size */ + } + } else { + min_mclk_extra--; + } + } else { + if (clwm > 1023){ /* Have some margin */ + fifo->valid = 0; + found = 0; + if(min_mclk_extra == 0) + found = 1; /* Can't adjust anymore! */ + else + min_mclk_extra--; + } + } + craw = clwm; + + if(clwm < (1024-cbs+8)) clwm = 1024-cbs+8; + data = (int)(clwm); + /* printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n", clwm, data ); */ + fifo->graphics_lwm = data; fifo->graphics_burst_size = cbs; + + /* printf("VID LWM: %f bytes, prog: 0x%x, bs: %d\n, ", vlwm, data, vbs ); */ + fifo->video_lwm = 1024; fifo->video_burst_size = 512; + } +} +static void nv10UpdateArbitrationSettings +( + unsigned VClk, + unsigned pixelDepth, + unsigned *burst, + unsigned *lwm, + RIVA_HW_INST *chip +) +{ + nv10_fifo_info fifo_data; + nv10_sim_state sim_data; + unsigned int M, N, P, pll, MClk, NVClk, cfg1; + + pll = chip->PRAMDAC0[0x00000504/4]; + M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; + MClk = (N * chip->CrystalFreqKHz / M) >> P; + pll = chip->PRAMDAC0[0x00000500/4]; + M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; + NVClk = (N * chip->CrystalFreqKHz / M) >> P; + cfg1 = chip->PFB[0x00000204/4]; + sim_data.pix_bpp = (char)pixelDepth; + sim_data.enable_video = 0; + sim_data.enable_mp = 0; + sim_data.memory_type = (chip->PFB[0x00000200/4] & 0x01) ? 1 : 0; + sim_data.memory_width = (chip->PEXTDEV[0x00000000/4] & 0x10) ? 128 : 64; + sim_data.mem_latency = (char)cfg1 & 0x0F; + sim_data.mem_aligned = 1; + sim_data.mem_page_miss = (char)(((cfg1 >> 4) &0x0F) + ((cfg1 >> 31) & 0x01)); + sim_data.gr_during_vid = 0; + sim_data.pclk_khz = VClk; + sim_data.mclk_khz = MClk; + sim_data.nvclk_khz = NVClk; + nv10CalcArbitration(&fifo_data, &sim_data); + if (fifo_data.valid) + { + int b = fifo_data.graphics_burst_size >> 4; + *burst = 0; + while (b >>= 1) (*burst)++; + *lwm = fifo_data.graphics_lwm >> 3; + } +} + +static void nForceUpdateArbitrationSettings +( + unsigned VClk, + unsigned pixelDepth, + unsigned *burst, + unsigned *lwm, + RIVA_HW_INST *chip +) +{ + nv10_fifo_info fifo_data; + nv10_sim_state sim_data; + unsigned int M, N, P, pll, MClk, NVClk; + unsigned int uMClkPostDiv, memctrl; + + uMClkPostDiv = (pciReadLong(pciTag(0, 0, 3), 0x6C) >> 8) & 0xf; + if(!uMClkPostDiv) uMClkPostDiv = 4; + MClk = 400000 / uMClkPostDiv; + + pll = chip->PRAMDAC0[0x00000500/4]; + M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F; + NVClk = (N * chip->CrystalFreqKHz / M) >> P; + sim_data.pix_bpp = (char)pixelDepth; + sim_data.enable_video = 0; + sim_data.enable_mp = 0; + sim_data.memory_type = (pciReadLong(pciTag(0, 0, 1), 0x7C) >> 12) & 1; + sim_data.memory_width = 64; + + memctrl = pciReadLong(pciTag(0, 0, 3), 0x00) >> 16; + + if((memctrl == 0x1A9) || (memctrl == 0x1AB) || (memctrl == 0x1ED)) { + int dimm[3]; + + dimm[0] = (pciReadLong(pciTag(0, 0, 2), 0x40) >> 8) & 0x4F; + dimm[1] = (pciReadLong(pciTag(0, 0, 2), 0x44) >> 8) & 0x4F; + dimm[2] = (pciReadLong(pciTag(0, 0, 2), 0x48) >> 8) & 0x4F; + + if((dimm[0] + dimm[1]) != dimm[2]) { + ErrorF("WARNING: " + "your nForce DIMMs are not arranged in optimal banks!\n"); + } + } + + sim_data.mem_latency = 3; + sim_data.mem_aligned = 1; + sim_data.mem_page_miss = 10; + sim_data.gr_during_vid = 0; + sim_data.pclk_khz = VClk; + sim_data.mclk_khz = MClk; + sim_data.nvclk_khz = NVClk; + nv10CalcArbitration(&fifo_data, &sim_data); + if (fifo_data.valid) + { + int b = fifo_data.graphics_burst_size >> 4; + *burst = 0; + while (b >>= 1) (*burst)++; + *lwm = fifo_data.graphics_lwm >> 3; + } +} + + +/****************************************************************************\ +* * +* RIVA Mode State Routines * +* * +\****************************************************************************/ + +/* + * Calculate the Video Clock parameters for the PLL. + */ +static int CalcVClock +( + int clockIn, + int *clockOut, + int *mOut, + int *nOut, + int *pOut, + RIVA_HW_INST *chip +) +{ + unsigned lowM, highM, highP; + unsigned DeltaNew, DeltaOld; + unsigned VClk, Freq; + unsigned M, N, P; + + DeltaOld = 0xFFFFFFFF; + + VClk = (unsigned)clockIn; + + if (chip->CrystalFreqKHz == 13500) + { + lowM = 7; + highM = 13 - (chip->Architecture == NV_ARCH_03); + } + else + { + lowM = 8; + highM = 14 - (chip->Architecture == NV_ARCH_03); + } + + highP = 4 - (chip->Architecture == NV_ARCH_03); + for (P = 0; P <= highP; P ++) + { + Freq = VClk << P; + if ((Freq >= 128000) && (Freq <= chip->MaxVClockFreqKHz)) + { + for (M = lowM; M <= highM; M++) + { + N = (VClk << P) * M / chip->CrystalFreqKHz; + if(N <= 255) { + Freq = (chip->CrystalFreqKHz * N / M) >> P; + if (Freq > VClk) + DeltaNew = Freq - VClk; + else + DeltaNew = VClk - Freq; + if (DeltaNew < DeltaOld) + { + *mOut = M; + *nOut = N; + *pOut = P; + *clockOut = Freq; + DeltaOld = DeltaNew; + } + } + } + } + } + return (DeltaOld != 0xFFFFFFFF); +} +/* + * Calculate extended mode parameters (SVGA) and save in a + * mode state structure. + */ +static void CalcStateExt +( + RIVA_HW_INST *chip, + RIVA_HW_STATE *state, + int bpp, + int width, + int hDisplaySize, + int height, + int dotClock, + int flags +) +{ + int pixelDepth, VClk, m, n, p; + /* + * Save mode parameters. + */ + state->bpp = bpp; /* this is not bitsPerPixel, it's 8,15,16,32 */ + state->width = width; + state->height = height; + /* + * Extended RIVA registers. + */ + pixelDepth = (bpp + 1)/8; + CalcVClock(dotClock, &VClk, &m, &n, &p, chip); + + switch (chip->Architecture) + { + case NV_ARCH_03: + nv3UpdateArbitrationSettings(VClk, + pixelDepth * 8, + &(state->arbitration0), + &(state->arbitration1), + chip); + state->cursor0 = 0x00; + state->cursor1 = 0x78; + if (flags & V_DBLSCAN) + state->cursor1 |= 2; + state->cursor2 = 0x00000000; + state->pllsel = 0x10010100; + state->config = ((width + 31)/32) + | (((pixelDepth > 2) ? 3 : pixelDepth) << 8) + | 0x1000; + state->general = 0x00100100; + state->repaint1 = hDisplaySize < 1280 ? 0x06 : 0x02; + break; + case NV_ARCH_04: + nv4UpdateArbitrationSettings(VClk, + pixelDepth * 8, + &(state->arbitration0), + &(state->arbitration1), + chip); + state->cursor0 = 0x00; + state->cursor1 = 0xFC; + if (flags & V_DBLSCAN) + state->cursor1 |= 2; + state->cursor2 = 0x00000000; + state->pllsel = 0x10000700; + state->config = 0x00001114; + state->general = bpp == 16 ? 0x00101100 : 0x00100100; + state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00; + break; + case NV_ARCH_10: + case NV_ARCH_20: + if(((chip->Chipset & 0xffff) == 0x01A0) || + ((chip->Chipset & 0xffff) == 0x01f0)) + { + nForceUpdateArbitrationSettings(VClk, + pixelDepth * 8, + &(state->arbitration0), + &(state->arbitration1), + chip); + } else { + nv10UpdateArbitrationSettings(VClk, + pixelDepth * 8, + &(state->arbitration0), + &(state->arbitration1), + chip); + } + state->cursor0 = 0x80 | (chip->CursorStart >> 17); + state->cursor1 = (chip->CursorStart >> 11) << 2; + state->cursor2 = chip->CursorStart >> 24; + if (flags & V_DBLSCAN) + state->cursor1 |= 2; + state->pllsel = 0x10000700; + state->config = chip->PFB[0x00000200/4]; + state->general = bpp == 16 ? 0x00101100 : 0x00100100; + state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00; + break; + } + + if((bpp != 8) && (chip->Architecture != NV_ARCH_03)) /* DirectColor */ + state->general |= 0x00000030; + + state->vpll = (p << 16) | (n << 8) | m; + state->repaint0 = (((width/8)*pixelDepth) & 0x700) >> 3; + state->pixel = pixelDepth > 2 ? 3 : pixelDepth; + state->offset = 0; + state->pitch = pixelDepth * width; +} +/* + * Load fixed function state and pre-calculated/stored state. + */ +#define LOAD_FIXED_STATE(tbl,dev) \ + for (i = 0; i < sizeof(tbl##Table##dev)/8; i++) \ + chip->dev[tbl##Table##dev[i][0]] = tbl##Table##dev[i][1] +#define LOAD_FIXED_STATE_8BPP(tbl,dev) \ + for (i = 0; i < sizeof(tbl##Table##dev##_8BPP)/8; i++) \ + chip->dev[tbl##Table##dev##_8BPP[i][0]] = tbl##Table##dev##_8BPP[i][1] +#define LOAD_FIXED_STATE_15BPP(tbl,dev) \ + for (i = 0; i < sizeof(tbl##Table##dev##_15BPP)/8; i++) \ + chip->dev[tbl##Table##dev##_15BPP[i][0]] = tbl##Table##dev##_15BPP[i][1] +#define LOAD_FIXED_STATE_16BPP(tbl,dev) \ + for (i = 0; i < sizeof(tbl##Table##dev##_16BPP)/8; i++) \ + chip->dev[tbl##Table##dev##_16BPP[i][0]] = tbl##Table##dev##_16BPP[i][1] +#define LOAD_FIXED_STATE_32BPP(tbl,dev) \ + for (i = 0; i < sizeof(tbl##Table##dev##_32BPP)/8; i++) \ + chip->dev[tbl##Table##dev##_32BPP[i][0]] = tbl##Table##dev##_32BPP[i][1] +static void UpdateFifoState +( + RIVA_HW_INST *chip +) +{ + int i; + + switch (chip->Architecture) + { + case NV_ARCH_04: + LOAD_FIXED_STATE(nv4,FIFO); + break; + case NV_ARCH_10: + case NV_ARCH_20: + LOAD_FIXED_STATE(nv10,FIFO); + break; + } +} +static void LoadStateExt +( + RIVA_HW_INST *chip, + RIVA_HW_STATE *state +) +{ + int i, format; + + /* + * Load HW fixed function state. + */ + LOAD_FIXED_STATE(Riva,PMC); + LOAD_FIXED_STATE(Riva,PTIMER); + switch (chip->Architecture) + { + case NV_ARCH_03: + /* + * Make sure frame buffer config gets set before loading PRAMIN. + */ + chip->PFB[0x00000200/4] = state->config; + LOAD_FIXED_STATE(nv3,PFIFO); + LOAD_FIXED_STATE(nv3,PRAMIN); + LOAD_FIXED_STATE(nv3,PGRAPH); + switch (state->bpp) + { + case 15: + case 16: + LOAD_FIXED_STATE_15BPP(nv3,PRAMIN); + LOAD_FIXED_STATE_15BPP(nv3,PGRAPH); + break; + case 24: + case 32: + LOAD_FIXED_STATE_32BPP(nv3,PRAMIN); + LOAD_FIXED_STATE_32BPP(nv3,PGRAPH); + break; + case 8: + default: + LOAD_FIXED_STATE_8BPP(nv3,PRAMIN); + LOAD_FIXED_STATE_8BPP(nv3,PGRAPH); + break; + } + for (i = 0x00000; i < 0x00800; i++) + chip->PRAMIN[0x00000502 + i] = (i << 12) | 0x03; + chip->PGRAPH[0x00000630/4] = state->offset; + chip->PGRAPH[0x00000634/4] = state->offset; + chip->PGRAPH[0x00000638/4] = state->offset; + chip->PGRAPH[0x0000063C/4] = state->offset; + chip->PGRAPH[0x00000650/4] = state->pitch; + chip->PGRAPH[0x00000654/4] = state->pitch; + chip->PGRAPH[0x00000658/4] = state->pitch; + chip->PGRAPH[0x0000065C/4] = state->pitch; + break; + case NV_ARCH_04: + /* + * Make sure frame buffer config gets set before loading PRAMIN. + */ + chip->PFB[0x00000200/4] = state->config; + LOAD_FIXED_STATE(nv4,PFIFO); + LOAD_FIXED_STATE(nv4,PRAMIN); + LOAD_FIXED_STATE(nv4,PGRAPH); + switch (state->bpp) + { + case 15: + LOAD_FIXED_STATE_15BPP(nv4,PRAMIN); + LOAD_FIXED_STATE_15BPP(nv4,PGRAPH); + break; + case 16: + LOAD_FIXED_STATE_16BPP(nv4,PRAMIN); + LOAD_FIXED_STATE_16BPP(nv4,PGRAPH); + break; + case 24: + case 32: + LOAD_FIXED_STATE_32BPP(nv4,PRAMIN); + LOAD_FIXED_STATE_32BPP(nv4,PGRAPH); + break; + case 8: + default: + LOAD_FIXED_STATE_8BPP(nv4,PRAMIN); + LOAD_FIXED_STATE_8BPP(nv4,PGRAPH); + break; + } + chip->PGRAPH[0x00000640/4] = state->offset; + chip->PGRAPH[0x00000644/4] = state->offset; + chip->PGRAPH[0x00000648/4] = state->offset; + chip->PGRAPH[0x0000064C/4] = state->offset; + chip->PGRAPH[0x00000670/4] = state->pitch; + chip->PGRAPH[0x00000674/4] = state->pitch; + chip->PGRAPH[0x00000678/4] = state->pitch; + chip->PGRAPH[0x0000067C/4] = state->pitch; + break; + case NV_ARCH_10: + case NV_ARCH_20: + if(chip->twoHeads) { + VGA_WR08(chip->PCIO, 0x03D4, 0x44); + VGA_WR08(chip->PCIO, 0x03D5, state->crtcOwner); + chip->LockUnlock(chip, 0); + } + + LOAD_FIXED_STATE(nv10,PFIFO); + LOAD_FIXED_STATE(nv10,PRAMIN); + LOAD_FIXED_STATE(nv10,PGRAPH); + switch (state->bpp) + { + case 15: + format = 2; + LOAD_FIXED_STATE_15BPP(nv10,PRAMIN); + LOAD_FIXED_STATE_15BPP(nv10,PGRAPH); + break; + case 16: + format = 5; + LOAD_FIXED_STATE_16BPP(nv10,PRAMIN); + LOAD_FIXED_STATE_16BPP(nv10,PGRAPH); + break; + case 32: + format = 7; + LOAD_FIXED_STATE_32BPP(nv10,PRAMIN); + LOAD_FIXED_STATE_32BPP(nv10,PGRAPH); + break; + default: + format = 1; + LOAD_FIXED_STATE_8BPP(nv10,PRAMIN); + LOAD_FIXED_STATE_8BPP(nv10,PGRAPH); + break; + } + + if(chip->Architecture == NV_ARCH_10) { + chip->PGRAPH[0x00000640/4] = state->offset; + chip->PGRAPH[0x00000644/4] = state->offset; + chip->PGRAPH[0x00000648/4] = state->offset; + chip->PGRAPH[0x0000064C/4] = state->offset; + chip->PGRAPH[0x00000670/4] = state->pitch; + chip->PGRAPH[0x00000674/4] = state->pitch; + chip->PGRAPH[0x00000678/4] = state->pitch; + chip->PGRAPH[0x0000067C/4] = state->pitch; + chip->PGRAPH[0x00000680/4] = state->pitch; + } else { + chip->PGRAPH[0x00000864/4] = 0x01ffffff; + chip->PGRAPH[0x00000868/4] = 0x01ffffff; + chip->PGRAPH[0x0000086c/4] = 0x01ffffff; + chip->PGRAPH[0x00000870/4] = 0x01ffffff; + + chip->PGRAPH[0x00000820/4] = state->offset; + chip->PGRAPH[0x00000824/4] = state->offset; + chip->PGRAPH[0x00000828/4] = state->offset; + chip->PGRAPH[0x0000082C/4] = state->offset; + chip->PGRAPH[0x00000850/4] = state->pitch; + chip->PGRAPH[0x00000854/4] = state->pitch; + chip->PGRAPH[0x00000858/4] = state->pitch; + chip->PGRAPH[0x0000085C/4] = state->pitch; + chip->PGRAPH[0x000009A4/4] = chip->PFB[0x00000200/4]; + chip->PGRAPH[0x000009A8/4] = chip->PFB[0x00000204/4]; + + if((chip->Chipset & 0x0ff0) >= 0x0300) { + if(!chip->flatPanel) { + chip->PRAMDAC0[0x0578/4] = state->vpllB; + chip->PRAMDAC0[0x057C/4] = state->vpll2B; + } + chip->PGRAPH[0x00000724/4] = format | (format << 5); + chip->PGRAPH[0x0000008C/4] |= 1; + chip->PGRAPH[0x00000890/4] |= 0x00040000; + } + } + if(chip->twoHeads) { + chip->PCRTC0[0x00000860/4] = state->head; + chip->PCRTC0[0x00002860/4] = state->head2; + } + chip->PRAMDAC[0x00000404/4] |= (1 << 25); + + chip->PMC[0x00008704/4] = 1; + chip->PMC[0x00008140/4] = 0; + chip->PMC[0x00008920/4] = 0; + chip->PMC[0x00008924/4] = 0; + chip->PMC[0x00008908/4] = 0x01ffffff; + chip->PMC[0x0000890C/4] = 0x01ffffff; + chip->PMC[0x00001588/4] = 0; + + chip->PFB[0x00000240/4] = 0; + chip->PFB[0x00000250/4] = 0; + chip->PFB[0x00000260/4] = 0; + chip->PFB[0x00000270/4] = 0; + chip->PFB[0x00000280/4] = 0; + chip->PFB[0x00000290/4] = 0; + chip->PFB[0x000002A0/4] = 0; + chip->PFB[0x000002B0/4] = 0; + + chip->PGRAPH[0x00000B00/4] = chip->PFB[0x00000240/4]; + chip->PGRAPH[0x00000B04/4] = chip->PFB[0x00000244/4]; + chip->PGRAPH[0x00000B08/4] = chip->PFB[0x00000248/4]; + chip->PGRAPH[0x00000B0C/4] = chip->PFB[0x0000024C/4]; + chip->PGRAPH[0x00000B10/4] = chip->PFB[0x00000250/4]; + chip->PGRAPH[0x00000B14/4] = chip->PFB[0x00000254/4]; + chip->PGRAPH[0x00000B18/4] = chip->PFB[0x00000258/4]; + chip->PGRAPH[0x00000B1C/4] = chip->PFB[0x0000025C/4]; + chip->PGRAPH[0x00000B20/4] = chip->PFB[0x00000260/4]; + chip->PGRAPH[0x00000B24/4] = chip->PFB[0x00000264/4]; + chip->PGRAPH[0x00000B28/4] = chip->PFB[0x00000268/4]; + chip->PGRAPH[0x00000B2C/4] = chip->PFB[0x0000026C/4]; + chip->PGRAPH[0x00000B30/4] = chip->PFB[0x00000270/4]; + chip->PGRAPH[0x00000B34/4] = chip->PFB[0x00000274/4]; + chip->PGRAPH[0x00000B38/4] = chip->PFB[0x00000278/4]; + chip->PGRAPH[0x00000B3C/4] = chip->PFB[0x0000027C/4]; + chip->PGRAPH[0x00000B40/4] = chip->PFB[0x00000280/4]; + chip->PGRAPH[0x00000B44/4] = chip->PFB[0x00000284/4]; + chip->PGRAPH[0x00000B48/4] = chip->PFB[0x00000288/4]; + chip->PGRAPH[0x00000B4C/4] = chip->PFB[0x0000028C/4]; + chip->PGRAPH[0x00000B50/4] = chip->PFB[0x00000290/4]; + chip->PGRAPH[0x00000B54/4] = chip->PFB[0x00000294/4]; + chip->PGRAPH[0x00000B58/4] = chip->PFB[0x00000298/4]; + chip->PGRAPH[0x00000B5C/4] = chip->PFB[0x0000029C/4]; + chip->PGRAPH[0x00000B60/4] = chip->PFB[0x000002A0/4]; + chip->PGRAPH[0x00000B64/4] = chip->PFB[0x000002A4/4]; + chip->PGRAPH[0x00000B68/4] = chip->PFB[0x000002A8/4]; + chip->PGRAPH[0x00000B6C/4] = chip->PFB[0x000002AC/4]; + chip->PGRAPH[0x00000B70/4] = chip->PFB[0x000002B0/4]; + chip->PGRAPH[0x00000B74/4] = chip->PFB[0x000002B4/4]; + chip->PGRAPH[0x00000B78/4] = chip->PFB[0x000002B8/4]; + chip->PGRAPH[0x00000B7C/4] = chip->PFB[0x000002BC/4]; + chip->PGRAPH[0x00000F40/4] = 0x10000000; + chip->PGRAPH[0x00000F44/4] = 0x00000000; + chip->PGRAPH[0x00000F50/4] = 0x00000040; + chip->PGRAPH[0x00000F54/4] = 0x00000008; + chip->PGRAPH[0x00000F50/4] = 0x00000200; + for (i = 0; i < (3*16); i++) + chip->PGRAPH[0x00000F54/4] = 0x00000000; + chip->PGRAPH[0x00000F50/4] = 0x00000040; + chip->PGRAPH[0x00000F54/4] = 0x00000000; + chip->PGRAPH[0x00000F50/4] = 0x00000800; + for (i = 0; i < (16*16); i++) + chip->PGRAPH[0x00000F54/4] = 0x00000000; + chip->PGRAPH[0x00000F40/4] = 0x30000000; + chip->PGRAPH[0x00000F44/4] = 0x00000004; + chip->PGRAPH[0x00000F50/4] = 0x00006400; + for (i = 0; i < (59*4); i++) + chip->PGRAPH[0x00000F54/4] = 0x00000000; + chip->PGRAPH[0x00000F50/4] = 0x00006800; + for (i = 0; i < (47*4); i++) + chip->PGRAPH[0x00000F54/4] = 0x00000000; + chip->PGRAPH[0x00000F50/4] = 0x00006C00; + for (i = 0; i < (3*4); i++) + chip->PGRAPH[0x00000F54/4] = 0x00000000; + chip->PGRAPH[0x00000F50/4] = 0x00007000; + for (i = 0; i < (19*4); i++) + chip->PGRAPH[0x00000F54/4] = 0x00000000; + chip->PGRAPH[0x00000F50/4] = 0x00007400; + for (i = 0; i < (12*4); i++) + chip->PGRAPH[0x00000F54/4] = 0x00000000; + chip->PGRAPH[0x00000F50/4] = 0x00007800; + for (i = 0; i < (12*4); i++) + chip->PGRAPH[0x00000F54/4] = 0x00000000; + chip->PGRAPH[0x00000F50/4] = 0x00004400; + for (i = 0; i < (8*4); i++) + chip->PGRAPH[0x00000F54/4] = 0x00000000; + chip->PGRAPH[0x00000F50/4] = 0x00000000; + for (i = 0; i < 16; i++) + chip->PGRAPH[0x00000F54/4] = 0x00000000; + chip->PGRAPH[0x00000F50/4] = 0x00000040; + for (i = 0; i < 4; i++) + chip->PGRAPH[0x00000F54/4] = 0x00000000; + + chip->PCRTC[0x00000810/4] = state->cursorConfig; + + if(chip->flatPanel) { + if((chip->Chipset & 0x0ff0) == 0x0110) { + chip->PRAMDAC[0x0528/4] = state->dither; + } else + if((chip->Chipset & 0x0ff0) >= 0x0170) { + chip->PRAMDAC[0x083C/4] = state->dither; + } + + + VGA_WR08(chip->PCIO, 0x03D4, 0x53); + VGA_WR08(chip->PCIO, 0x03D5, 0); + VGA_WR08(chip->PCIO, 0x03D4, 0x54); + VGA_WR08(chip->PCIO, 0x03D5, 0); + VGA_WR08(chip->PCIO, 0x03D4, 0x21); + VGA_WR08(chip->PCIO, 0x03D5, 0xfa); + } + + VGA_WR08(chip->PCIO, 0x03D4, 0x41); + VGA_WR08(chip->PCIO, 0x03D5, state->extra); + } + + LOAD_FIXED_STATE(Riva,FIFO); + UpdateFifoState(chip); + + /* + * Load HW mode state. + */ + VGA_WR08(chip->PCIO, 0x03D4, 0x19); + VGA_WR08(chip->PCIO, 0x03D5, state->repaint0); + VGA_WR08(chip->PCIO, 0x03D4, 0x1A); + VGA_WR08(chip->PCIO, 0x03D5, state->repaint1); + VGA_WR08(chip->PCIO, 0x03D4, 0x25); + VGA_WR08(chip->PCIO, 0x03D5, state->screen); + VGA_WR08(chip->PCIO, 0x03D4, 0x28); + VGA_WR08(chip->PCIO, 0x03D5, state->pixel); + VGA_WR08(chip->PCIO, 0x03D4, 0x2D); + VGA_WR08(chip->PCIO, 0x03D5, state->horiz); + VGA_WR08(chip->PCIO, 0x03D4, 0x1B); + VGA_WR08(chip->PCIO, 0x03D5, state->arbitration0); + VGA_WR08(chip->PCIO, 0x03D4, 0x20); + VGA_WR08(chip->PCIO, 0x03D5, state->arbitration1); + VGA_WR08(chip->PCIO, 0x03D4, 0x30); + VGA_WR08(chip->PCIO, 0x03D5, state->cursor0); + VGA_WR08(chip->PCIO, 0x03D4, 0x31); + VGA_WR08(chip->PCIO, 0x03D5, state->cursor1); + VGA_WR08(chip->PCIO, 0x03D4, 0x2F); + VGA_WR08(chip->PCIO, 0x03D5, state->cursor2); + VGA_WR08(chip->PCIO, 0x03D4, 0x39); + VGA_WR08(chip->PCIO, 0x03D5, state->interlace); + + if(!chip->flatPanel) { + chip->PRAMDAC0[0x00000508/4] = state->vpll; + chip->PRAMDAC0[0x0000050C/4] = state->pllsel; + if(chip->twoHeads) + chip->PRAMDAC0[0x00000520/4] = state->vpll2; + } else { + chip->PRAMDAC[0x00000848/4] = state->scale; + } + chip->PRAMDAC[0x00000600/4] = state->general; + + /* + * Turn off VBlank enable and reset. + */ + chip->PCRTC[0x00000140/4] = 0; + chip->PCRTC[0x00000100/4] = chip->VBlankBit; + /* + * Set interrupt enable. + */ + chip->PMC[0x00000140/4] = chip->EnableIRQ & 0x01; + /* + * Set current state pointer. + */ + chip->CurrentState = state; + /* + * Reset FIFO free and empty counts. + */ + chip->FifoFreeCount = 0; + /* Free count from first subchannel */ + chip->FifoEmptyCount = chip->Rop->FifoFree; +} + +static void UnloadStateExt +( + RIVA_HW_INST *chip, + RIVA_HW_STATE *state +) +{ + /* + * Save current HW state. + */ + VGA_WR08(chip->PCIO, 0x03D4, 0x19); + state->repaint0 = VGA_RD08(chip->PCIO, 0x03D5); + VGA_WR08(chip->PCIO, 0x03D4, 0x1A); + state->repaint1 = VGA_RD08(chip->PCIO, 0x03D5); + VGA_WR08(chip->PCIO, 0x03D4, 0x25); + state->screen = VGA_RD08(chip->PCIO, 0x03D5); + VGA_WR08(chip->PCIO, 0x03D4, 0x28); + state->pixel = VGA_RD08(chip->PCIO, 0x03D5); + VGA_WR08(chip->PCIO, 0x03D4, 0x2D); + state->horiz = VGA_RD08(chip->PCIO, 0x03D5); + VGA_WR08(chip->PCIO, 0x03D4, 0x1B); + state->arbitration0 = VGA_RD08(chip->PCIO, 0x03D5); + VGA_WR08(chip->PCIO, 0x03D4, 0x20); + state->arbitration1 = VGA_RD08(chip->PCIO, 0x03D5); + VGA_WR08(chip->PCIO, 0x03D4, 0x30); + state->cursor0 = VGA_RD08(chip->PCIO, 0x03D5); + VGA_WR08(chip->PCIO, 0x03D4, 0x31); + state->cursor1 = VGA_RD08(chip->PCIO, 0x03D5); + VGA_WR08(chip->PCIO, 0x03D4, 0x2F); + state->cursor2 = VGA_RD08(chip->PCIO, 0x03D5); + VGA_WR08(chip->PCIO, 0x03D4, 0x39); + state->interlace = VGA_RD08(chip->PCIO, 0x03D5); + state->vpll = chip->PRAMDAC0[0x00000508/4]; + state->vpll2 = chip->PRAMDAC0[0x00000520/4]; + state->vpllB = chip->PRAMDAC0[0x00000578/4]; + state->vpll2B = chip->PRAMDAC0[0x0000057C/4]; + state->pllsel = chip->PRAMDAC0[0x0000050C/4]; + state->general = chip->PRAMDAC[0x00000600/4]; + state->scale = chip->PRAMDAC[0x00000848/4]; + state->config = chip->PFB[0x00000200/4]; + + switch (chip->Architecture) + { + case NV_ARCH_03: + state->offset = chip->PGRAPH[0x00000630/4]; + state->pitch = chip->PGRAPH[0x00000650/4]; + break; + case NV_ARCH_04: + state->offset = chip->PGRAPH[0x00000640/4]; + state->pitch = chip->PGRAPH[0x00000670/4]; + break; + case NV_ARCH_10: + case NV_ARCH_20: + state->offset = chip->PGRAPH[0x00000640/4]; + state->pitch = chip->PGRAPH[0x00000670/4]; + if(chip->twoHeads) { + state->head = chip->PCRTC0[0x00000860/4]; + state->head2 = chip->PCRTC0[0x00002860/4]; + VGA_WR08(chip->PCIO, 0x03D4, 0x44); + state->crtcOwner = VGA_RD08(chip->PCIO, 0x03D5); + } + VGA_WR08(chip->PCIO, 0x03D4, 0x41); + state->extra = VGA_RD08(chip->PCIO, 0x03D5); + state->cursorConfig = chip->PCRTC[0x00000810/4]; + + if((chip->Chipset & 0x0ff0) == 0x0110) { + state->dither = chip->PRAMDAC[0x0528/4]; + } else + if((chip->Chipset & 0x0ff0) >= 0x0170) { + state->dither = chip->PRAMDAC[0x083C/4]; + } + + break; + } +} +static void SetStartAddress +( + RIVA_HW_INST *chip, + unsigned start +) +{ + chip->PCRTC[0x800/4] = start; +} + +static void SetStartAddress3 +( + RIVA_HW_INST *chip, + unsigned start +) +{ + int offset = start >> 2; + int pan = (start & 3) << 1; + unsigned char tmp; + + /* + * Unlock extended registers. + */ + chip->LockUnlock(chip, 0); + /* + * Set start address. + */ + VGA_WR08(chip->PCIO, 0x3D4, 0x0D); VGA_WR08(chip->PCIO, 0x3D5, offset); + offset >>= 8; + VGA_WR08(chip->PCIO, 0x3D4, 0x0C); VGA_WR08(chip->PCIO, 0x3D5, offset); + offset >>= 8; + VGA_WR08(chip->PCIO, 0x3D4, 0x19); tmp = VGA_RD08(chip->PCIO, 0x3D5); + VGA_WR08(chip->PCIO, 0x3D5, (offset & 0x01F) | (tmp & ~0x1F)); + VGA_WR08(chip->PCIO, 0x3D4, 0x2D); tmp = VGA_RD08(chip->PCIO, 0x3D5); + VGA_WR08(chip->PCIO, 0x3D5, (offset & 0x60) | (tmp & ~0x60)); + /* + * 4 pixel pan register. + */ + offset = VGA_RD08(chip->PCIO, chip->IO + 0x0A); + VGA_WR08(chip->PCIO, 0x3C0, 0x13); + VGA_WR08(chip->PCIO, 0x3C0, pan); +} +/****************************************************************************\ +* * +* Probe RIVA Chip Configuration * +* * +\****************************************************************************/ + +static void nv3GetConfig +( + RIVA_HW_INST *chip +) +{ + /* + * Fill in chip configuration. + */ + if (chip->PFB[0x00000000/4] & 0x00000020) + { + if (((chip->PMC[0x00000000/4] & 0xF0) == 0x20) + && ((chip->PMC[0x00000000/4] & 0x0F) >= 0x02)) + { + /* + * SDRAM 128 ZX. + */ + chip->RamBandwidthKBytesPerSec = 800000; + switch (chip->PFB[0x00000000/4] & 0x03) + { + case 2: + chip->RamAmountKBytes = 1024 * 4; + break; + case 1: + chip->RamAmountKBytes = 1024 * 2; + break; + default: + chip->RamAmountKBytes = 1024 * 8; + break; + } + } + else + { + chip->RamBandwidthKBytesPerSec = 1000000; + chip->RamAmountKBytes = 1024 * 8; + } + } + else + { + /* + * SGRAM 128. + */ + chip->RamBandwidthKBytesPerSec = 1000000; + switch (chip->PFB[0x00000000/4] & 0x00000003) + { + case 0: + chip->RamAmountKBytes = 1024 * 8; + break; + case 2: + chip->RamAmountKBytes = 1024 * 4; + break; + default: + chip->RamAmountKBytes = 1024 * 2; + break; + } + } + chip->CrystalFreqKHz = (chip->PEXTDEV[0x00000000/4] & 0x00000040) ? 14318 : 13500; + chip->CURSOR = &(chip->PRAMIN[0x00008000/4 - 0x0800/4]); + chip->VBlankBit = 0x00000100; + chip->MaxVClockFreqKHz = 256000; + /* + * Set chip functions. + */ + chip->Busy = nv3Busy; + chip->ShowHideCursor = ShowHideCursor; + chip->CalcStateExt = CalcStateExt; + chip->LoadStateExt = LoadStateExt; + chip->UnloadStateExt = UnloadStateExt; + chip->SetStartAddress = SetStartAddress3; + chip->LockUnlock = nv3LockUnlock; +} +static void nv4GetConfig +( + RIVA_HW_INST *chip +) +{ + /* + * Fill in chip configuration. + */ + if (chip->PFB[0x00000000/4] & 0x00000100) + { + chip->RamAmountKBytes = ((chip->PFB[0x00000000/4] >> 12) & 0x0F) * 1024 * 2 + + 1024 * 2; + } + else + { + switch (chip->PFB[0x00000000/4] & 0x00000003) + { + case 0: + chip->RamAmountKBytes = 1024 * 32; + break; + case 1: + chip->RamAmountKBytes = 1024 * 4; + break; + case 2: + chip->RamAmountKBytes = 1024 * 8; + break; + case 3: + default: + chip->RamAmountKBytes = 1024 * 16; + break; + } + } + switch ((chip->PFB[0x00000000/4] >> 3) & 0x00000003) + { + case 3: + chip->RamBandwidthKBytesPerSec = 800000; + break; + default: + chip->RamBandwidthKBytesPerSec = 1000000; + break; + } + chip->CrystalFreqKHz = (chip->PEXTDEV[0x00000000/4] & 0x00000040) ? 14318 : 13500; + chip->CURSOR = &(chip->PRAMIN[0x00010000/4 - 0x0800/4]); + chip->VBlankBit = 0x00000001; + chip->MaxVClockFreqKHz = 350000; + /* + * Set chip functions. + */ + chip->Busy = nv4Busy; + chip->ShowHideCursor = ShowHideCursor; + chip->CalcStateExt = CalcStateExt; + chip->LoadStateExt = LoadStateExt; + chip->UnloadStateExt = UnloadStateExt; + chip->SetStartAddress = SetStartAddress; + chip->LockUnlock = nv4LockUnlock; +} +static void nv10GetConfig +( + NVPtr pNv +) +{ + RIVA_HW_INST *chip = &pNv->riva; + +#if X_BYTE_ORDER == X_BIG_ENDIAN + /* turn on big endian register access */ + if(!(chip->PMC[0x00000004/4] & 0x01000001)) + chip->PMC[0x00000004/4] = 0x01000001; +#endif + + /* + * Fill in chip configuration. + */ + if((pNv->Chipset && 0xffff) == 0x01a0) { + int amt = pciReadLong(pciTag(0, 0, 1), 0x7C); + + chip->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024; + } else if((pNv->Chipset & 0xffff) == 0x01f0) { + int amt = pciReadLong(pciTag(0, 0, 1), 0x84); + + chip->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024; + } else { + switch ((chip->PFB[0x0000020C/4] >> 20) & 0x000000FF) + { + case 0x02: + chip->RamAmountKBytes = 1024 * 2; + break; + case 0x04: + chip->RamAmountKBytes = 1024 * 4; + break; + case 0x08: + chip->RamAmountKBytes = 1024 * 8; + break; + case 0x10: + chip->RamAmountKBytes = 1024 * 16; + break; + case 0x20: + chip->RamAmountKBytes = 1024 * 32; + break; + case 0x40: + chip->RamAmountKBytes = 1024 * 64; + break; + case 0x80: + chip->RamAmountKBytes = 1024 * 128; + break; + default: + chip->RamAmountKBytes = 1024 * 16; + break; + } + } + switch ((chip->PFB[0x00000000/4] >> 3) & 0x00000003) + { + case 3: + chip->RamBandwidthKBytesPerSec = 800000; + break; + default: + chip->RamBandwidthKBytesPerSec = 1000000; + break; + } + + chip->CrystalFreqKHz = (chip->PEXTDEV[0x0000/4] & (1 << 6)) ? 14318 : + 13500; + switch(pNv->Chipset & 0x0ff0) { + case 0x0170: + case 0x0180: + case 0x01F0: + case 0x0250: + case 0x0280: + case 0x0300: + case 0x0310: + case 0x0320: + case 0x0330: + case 0x0340: + if(chip->PEXTDEV[0x0000/4] & (1 << 22)) + chip->CrystalFreqKHz = 27000; + break; + default: + break; + } + + chip->CursorStart = (chip->RamAmountKBytes - 128) * 1024; + chip->CURSOR = NULL; /* can't set this here */ + chip->VBlankBit = 0x00000001; + chip->MaxVClockFreqKHz = 350000; + /* + * Set chip functions. + */ + chip->Busy = nv10Busy; + chip->ShowHideCursor = ShowHideCursor; + chip->CalcStateExt = CalcStateExt; + chip->LoadStateExt = LoadStateExt; + chip->UnloadStateExt = UnloadStateExt; + chip->SetStartAddress = SetStartAddress; + chip->LockUnlock = nv4LockUnlock; + + switch(pNv->Chipset & 0x0ff0) { + case 0x0110: + case 0x0170: + case 0x0180: + case 0x01F0: + case 0x0250: + case 0x0280: + case 0x0300: + case 0x0310: + case 0x0320: + case 0x0330: + case 0x0340: + chip->twoHeads = TRUE; + break; + default: + chip->twoHeads = FALSE; + break; + } +} +int RivaGetConfig +( + NVPtr pNv +) +{ + RIVA_HW_INST *chip = &pNv->riva; + /* + * Save this so future SW know whats it's dealing with. + */ + chip->Version = RIVA_SW_VERSION; + /* + * Chip specific configuration. + */ + switch (chip->Architecture) + { + case NV_ARCH_03: + nv3GetConfig(chip); + break; + case NV_ARCH_04: + nv4GetConfig(chip); + break; + case NV_ARCH_10: + case NV_ARCH_20: + nv10GetConfig(pNv); + break; + default: + return (-1); + } + chip->Chipset = pNv->Chipset; + /* + * Fill in FIFO pointers. + */ + chip->Rop = (RivaRop *)&(chip->FIFO[0x00000000/4]); + chip->Clip = (RivaClip *)&(chip->FIFO[0x00002000/4]); + chip->Patt = (RivaPattern *)&(chip->FIFO[0x00004000/4]); + chip->Pixmap = (RivaPixmap *)&(chip->FIFO[0x00006000/4]); + chip->Blt = (RivaScreenBlt *)&(chip->FIFO[0x00008000/4]); + chip->Bitmap = (RivaBitmap *)&(chip->FIFO[0x0000A000/4]); + chip->Line = (RivaLine *)&(chip->FIFO[0x0000C000/4]); + return (0); +} + diff --git a/src/riva_hw.h b/src/riva_hw.h new file mode 100644 index 0000000..8d53d4f --- /dev/null +++ b/src/riva_hw.h @@ -0,0 +1,428 @@ +/***************************************************************************\ +|* *| +|* Copyright 1993-1999 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 *| +|* hereby granted a nonexclusive, royalty-free copyright license to *| +|* use this code in individual and commercial software. *| +|* *| +|* Any use of this source code must include, in the user documenta- *| +|* tion and internal comments to the code, notices to the end user *| +|* as follows: *| +|* *| +|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| +|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| +|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| +|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| +|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| +|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| +|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| +|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| +|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| +|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| +|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| +|* *| +|* U.S. Government End Users. This source code is a "commercial *| +|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| +|* consisting of "commercial computer software" and "commercial *| +|* computer software documentation," as such terms are used in *| +|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| +|* ment only as a commercial end item. Consistent with 48 C.F.R. *| +|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| +|* all U.S. Government End Users acquire the source code with only *| +|* those rights set forth herein. *| +|* *| +\***************************************************************************/ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_hw.h,v 1.24 2003/02/10 23:42:51 mvojkovi Exp $ */ +#ifndef __RIVA_HW_H__ +#define __RIVA_HW_H__ +#define RIVA_SW_VERSION 0x00010003 + +/* + * Define supported architectures. + */ +#define NV_ARCH_03 0x03 +#define NV_ARCH_04 0x04 +#define NV_ARCH_10 0x10 +#define NV_ARCH_20 0x20 +/***************************************************************************\ +* * +* FIFO registers. * +* * +\***************************************************************************/ + +/* + * Raster OPeration. Windows style ROP3. + */ +typedef volatile struct +{ + U032 reserved00[4]; +#if X_BYTE_ORDER == X_BIG_ENDIAN + U032 FifoFree; +#else + U016 FifoFree; + U016 Nop; +#endif + U032 reserved01[0x0BB]; + U032 Rop3; +} RivaRop; +/* + * 8X8 Monochrome pattern. + */ +typedef volatile struct +{ + U032 reserved00[4]; +#if X_BYTE_ORDER == X_BIG_ENDIAN + U032 FifoFree; +#else + U016 FifoFree; + U016 Nop; +#endif + U032 reserved01[0x0BD]; + U032 Shape; + U032 reserved03[0x001]; + U032 Color0; + U032 Color1; + U032 Monochrome[2]; +} RivaPattern; +/* + * Scissor clip rectangle. + */ +typedef volatile struct +{ + U032 reserved00[4]; +#if X_BYTE_ORDER == X_BIG_ENDIAN + U032 FifoFree; +#else + U016 FifoFree; + U016 Nop; +#endif + U032 reserved01[0x0BB]; + U032 TopLeft; + U032 WidthHeight; +} RivaClip; +/* + * 2D filled rectangle. + */ +typedef volatile struct +{ + U032 reserved00[4]; +#if X_BYTE_ORDER == X_BIG_ENDIAN + U032 FifoFree; +#else + U016 FifoFree; + U016 Nop[1]; +#endif + U032 reserved01[0x0BC]; + U032 Color; + U032 reserved03[0x03E]; + U032 TopLeft; + U032 WidthHeight; +} RivaRectangle; +/* + * 2D screen-screen BLT. + */ +typedef volatile struct +{ + U032 reserved00[4]; +#if X_BYTE_ORDER == X_BIG_ENDIAN + U032 FifoFree; +#else + U016 FifoFree; + U016 Nop; +#endif + U032 reserved01[0x0BB]; + U032 TopLeftSrc; + U032 TopLeftDst; + U032 WidthHeight; +} RivaScreenBlt; +/* + * 2D pixel BLT. + */ +typedef volatile struct +{ + U032 reserved00[4]; +#if X_BYTE_ORDER == X_BIG_ENDIAN + U032 FifoFree; +#else + U016 FifoFree; + U016 Nop[1]; +#endif + U032 reserved01[0x0BC]; + U032 TopLeft; + U032 WidthHeight; + U032 WidthHeightIn; + U032 reserved02[0x03C]; + U032 Pixels; +} RivaPixmap; +/* + * Filled rectangle combined with monochrome expand. Useful for glyphs. + */ +typedef volatile struct +{ + U032 reserved00[4]; +#if X_BYTE_ORDER == X_BIG_ENDIAN + U032 FifoFree; +#else + U016 FifoFree; + U016 Nop; +#endif + U032 reserved01[0x0BB]; + U032 reserved03[(0x040)-1]; + U032 Color1A; + struct + { + U032 TopLeft; + U032 WidthHeight; + } UnclippedRectangle[64]; + U032 reserved04[(0x080)-3]; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClipB; + U032 Color1B; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClippedRectangle[64]; + U032 reserved05[(0x080)-5]; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClipC; + U032 Color1C; + U032 WidthHeightC; + U032 PointC; + U032 MonochromeData1C; + U032 reserved06[(0x080)+121]; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClipD; + U032 Color1D; + U032 WidthHeightInD; + U032 WidthHeightOutD; + U032 PointD; + U032 MonochromeData1D; + U032 reserved07[(0x080)+120]; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClipE; + U032 Color0E; + U032 Color1E; + U032 WidthHeightInE; + U032 WidthHeightOutE; + U032 PointE; + U032 MonochromeData01E; +} RivaBitmap; +/* + * 2D line. + */ +typedef volatile struct +{ + U032 reserved00[4]; +#if X_BYTE_ORDER == X_BIG_ENDIAN + U032 FifoFree; +#else + U016 FifoFree; + U016 Nop[1]; +#endif + U032 reserved01[0x0BC]; + U032 Color; /* source color 0304-0307*/ + U032 Reserved02[0x03e]; + struct { /* start aliased methods in array 0400- */ + U032 point0; /* y_x S16_S16 in pixels 0- 3*/ + U032 point1; /* y_x S16_S16 in pixels 4- 7*/ + } Lin[16]; /* end of aliased methods in array -047f*/ + struct { /* start aliased methods in array 0480- */ + U032 point0X; /* in pixels, 0 at left 0- 3*/ + U032 point0Y; /* in pixels, 0 at top 4- 7*/ + U032 point1X; /* in pixels, 0 at left 8- b*/ + U032 point1Y; /* in pixels, 0 at top c- f*/ + } Lin32[8]; /* end of aliased methods in array -04ff*/ + U032 PolyLin[32]; /* y_x S16_S16 in pixels 0500-057f*/ + struct { /* start aliased methods in array 0580- */ + U032 x; /* in pixels, 0 at left 0- 3*/ + U032 y; /* in pixels, 0 at top 4- 7*/ + } PolyLin32[16]; /* end of aliased methods in array -05ff*/ + struct { /* start aliased methods in array 0600- */ + U032 color; /* source color 0- 3*/ + U032 point; /* y_x S16_S16 in pixels 4- 7*/ + } ColorPolyLin[16]; /* end of aliased methods in array -067f*/ +} RivaLine; +/* + * 2D/3D surfaces + */ +typedef volatile struct +{ + U032 reserved00[4]; +#if X_BYTE_ORDER == X_BIG_ENDIAN + U032 FifoFree; +#else + U016 FifoFree; + U016 Nop; +#endif + U032 reserved01[0x0BE]; + U032 Offset; +} RivaSurface; +typedef volatile struct +{ + U032 reserved00[4]; +#if X_BYTE_ORDER == X_BIG_ENDIAN + U032 FifoFree; +#else + U016 FifoFree; + U016 Nop; +#endif + U032 reserved01[0x0BD]; + U032 Pitch; + U032 RenderBufferOffset; + U032 ZBufferOffset; +} RivaSurface3D; + +/***************************************************************************\ +* * +* Virtualized RIVA H/W interface. * +* * +\***************************************************************************/ + +#define FP_ENABLE 1 +#define FP_DITHER 2 + +struct _riva_hw_inst; +struct _riva_hw_state; +/* + * Virtialized chip interface. Makes RIVA 128 and TNT look alike. + */ +typedef struct _riva_hw_inst +{ + /* + * Chip specific settings. + */ + U032 Architecture; + U032 Version; + U032 Chipset; + U032 CrystalFreqKHz; + U032 RamAmountKBytes; + U032 MaxVClockFreqKHz; + U032 RamBandwidthKBytesPerSec; + U032 EnableIRQ; + U032 IO; + U032 VBlankBit; + U032 FifoFreeCount; + U032 FifoEmptyCount; + U032 CursorStart; + U032 flatPanel; + Bool twoHeads; + /* + * Non-FIFO registers. + */ + volatile U032 *PCRTC0; + volatile U032 *PCRTC; + volatile U032 *PRAMDAC0; + volatile U032 *PFB; + volatile U032 *PFIFO; + volatile U032 *PGRAPH; + volatile U032 *PEXTDEV; + volatile U032 *PTIMER; + volatile U032 *PMC; + volatile U032 *PRAMIN; + volatile U032 *FIFO; + volatile U032 *CURSOR; + volatile U008 *PCIO0; + volatile U008 *PCIO; + volatile U008 *PVIO; + volatile U008 *PDIO0; + volatile U008 *PDIO; + volatile U032 *PRAMDAC; + /* + * Common chip functions. + */ + int (*Busy)(struct _riva_hw_inst *); + void (*CalcStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *,int,int,int,int,int,int); + void (*LoadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *); + void (*UnloadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *); + void (*SetStartAddress)(struct _riva_hw_inst *,U032); + int (*ShowHideCursor)(struct _riva_hw_inst *,int); + void (*LockUnlock)(struct _riva_hw_inst *, int); + /* + * Current extended mode settings. + */ + struct _riva_hw_state *CurrentState; + /* + * FIFO registers. + */ + RivaRop *Rop; + RivaPattern *Patt; + RivaClip *Clip; + RivaPixmap *Pixmap; + RivaScreenBlt *Blt; + RivaBitmap *Bitmap; + RivaLine *Line; +} RIVA_HW_INST; +/* + * Extended mode state information. + */ +typedef struct _riva_hw_state +{ + U032 bpp; + U032 width; + U032 height; + U032 interlace; + U032 repaint0; + U032 repaint1; + U032 screen; + U032 scale; + U032 dither; + U032 extra; + U032 pixel; + U032 horiz; + U032 arbitration0; + U032 arbitration1; + U032 vpll; + U032 vpll2; + U032 vpllB; + U032 vpll2B; + U032 pllsel; + U032 general; + U032 crtcOwner; + U032 head; + U032 head2; + U032 config; + U032 cursorConfig; + U032 cursor0; + U032 cursor1; + U032 cursor2; + U032 offset; + U032 pitch; +} RIVA_HW_STATE; + +/* + * FIFO Free Count. Should attempt to yield processor if RIVA is busy. + */ + +#define RIVA_FIFO_FREE(hwinst,hwptr,cnt) \ +{ \ + while ((hwinst).FifoFreeCount < (cnt)) { \ + mem_barrier(); \ + mem_barrier(); \ + (hwinst).FifoFreeCount = (hwinst).hwptr->FifoFree >> 2; \ + } \ + (hwinst).FifoFreeCount -= (cnt); \ +} +#define RIVA_BUSY(hwinst) \ +{ \ + mem_barrier(); \ + while ((hwinst).Busy(&(hwinst))); \ +} +#endif /* __RIVA_HW_H__ */ + diff --git a/src/riva_tbl.h b/src/riva_tbl.h new file mode 100644 index 0000000..bc86c75 --- /dev/null +++ b/src/riva_tbl.h @@ -0,0 +1,826 @@ + /***************************************************************************\ +|* *| +|* Copyright 1993-1999 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 *| +|* hereby granted a nonexclusive, royalty-free copyright license to *| +|* use this code in individual and commercial software. *| +|* *| +|* Any use of this source code must include, in the user documenta- *| +|* tion and internal comments to the code, notices to the end user *| +|* as follows: *| +|* *| +|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| +|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| +|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| +|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| +|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| +|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| +|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| +|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| +|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| +|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| +|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| +|* *| +|* U.S. Government End Users. This source code is a "commercial *| +|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| +|* consisting of "commercial computer software" and "commercial *| +|* computer software documentation," as such terms are used in *| +|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| +|* ment only as a commercial end item. Consistent with 48 C.F.R. *| +|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| +|* all U.S. Government End Users acquire the source code with only *| +|* those rights set forth herein. *| +|* *| + \***************************************************************************/ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_tbl.h,v 1.9 2002/01/30 01:35:03 mvojkovi Exp $ */ + + +/* + * RIVA Fixed Functionality Init Tables. + */ +static unsigned RivaTablePMC[][2] = +{ + {0x00000050, 0x00000000}, + {0x00000080, 0xFFFF00FF}, + {0x00000080, 0xFFFFFFFF} +}; +static unsigned RivaTablePTIMER[][2] = +{ + {0x00000080, 0x00000008}, + {0x00000084, 0x00000003}, + {0x00000050, 0x00000000}, + {0x00000040, 0xFFFFFFFF} +}; +static unsigned RivaTableFIFO[][2] = +{ + {0x00000000, 0x80000000}, + {0x00000800, 0x80000001}, + {0x00001000, 0x80000002}, + {0x00001800, 0x80000010}, + {0x00002000, 0x80000011}, + {0x00002800, 0x80000012}, + {0x00003000, 0x80000016}, + {0x00003800, 0x80000013} +}; +static unsigned nv3TablePFIFO[][2] = +{ + {0x00000140, 0x00000000}, + {0x00000480, 0x00000000}, + {0x00000490, 0x00000000}, + {0x00000494, 0x00000000}, + {0x00000481, 0x00000000}, + {0x00000084, 0x00000000}, + {0x00000086, 0x00002000}, + {0x00000085, 0x00002200}, + {0x00000484, 0x00000000}, + {0x0000049C, 0x00000000}, + {0x00000104, 0x00000000}, + {0x00000108, 0x00000000}, + {0x00000100, 0x00000000}, + {0x000004A0, 0x00000000}, + {0x000004A4, 0x00000000}, + {0x000004A8, 0x00000000}, + {0x000004AC, 0x00000000}, + {0x000004B0, 0x00000000}, + {0x000004B4, 0x00000000}, + {0x000004B8, 0x00000000}, + {0x000004BC, 0x00000000}, + {0x00000050, 0x00000000}, + {0x00000040, 0xFFFFFFFF}, + {0x00000480, 0x00000001}, + {0x00000490, 0x00000001}, + {0x00000140, 0x00000001} +}; +static unsigned nv3TablePGRAPH[][2] = +{ + {0x00000020, 0x1230001F}, + {0x00000021, 0x10113000}, + {0x00000022, 0x1131F101}, + {0x00000023, 0x0100F531}, + {0x00000060, 0x00000000}, + {0x00000065, 0x00000000}, + {0x00000068, 0x00000000}, + {0x00000069, 0x00000000}, + {0x0000006A, 0x00000000}, + {0x0000006B, 0x00000000}, + {0x0000006C, 0x00000000}, + {0x0000006D, 0x00000000}, + {0x0000006E, 0x00000000}, + {0x0000006F, 0x00000000}, + {0x000001A8, 0x00000000}, + {0x00000440, 0xFFFFFFFF}, + {0x00000480, 0x00000001}, + {0x000001A0, 0x00000000}, + {0x000001A2, 0x00000000}, + {0x0000018A, 0xFFFFFFFF}, + {0x00000190, 0x00000000}, + {0x00000142, 0x00000000}, + {0x00000154, 0x00000000}, + {0x00000155, 0xFFFFFFFF}, + {0x00000156, 0x00000000}, + {0x00000157, 0xFFFFFFFF}, + {0x00000064, 0x10010002}, + {0x00000050, 0x00000000}, + {0x00000051, 0x00000000}, + {0x00000040, 0xFFFFFFFF}, + {0x00000041, 0xFFFFFFFF}, + {0x00000440, 0xFFFFFFFF}, + {0x000001A9, 0x00000001} +}; +static unsigned nv3TablePGRAPH_8BPP[][2] = +{ + {0x000001AA, 0x00001111} +}; +static unsigned nv3TablePGRAPH_15BPP[][2] = +{ + {0x000001AA, 0x00002222} +}; +static unsigned nv3TablePGRAPH_32BPP[][2] = +{ + {0x000001AA, 0x00003333} +}; +static unsigned nv3TablePRAMIN[][2] = +{ + {0x00000500, 0x00010000}, + {0x00000501, 0x007FFFFF}, + {0x00000200, 0x80000000}, + {0x00000201, 0x00C20341}, + {0x00000204, 0x80000001}, + {0x00000205, 0x00C50342}, + {0x00000208, 0x80000002}, + {0x00000209, 0x00C60343}, + {0x0000020C, 0x80000003}, + {0x0000020D, 0x00DC0348}, + {0x00000210, 0x80000004}, + {0x00000211, 0x00DC0349}, + {0x00000214, 0x80000005}, + {0x00000215, 0x00DC034A}, + {0x00000218, 0x80000006}, + {0x00000219, 0x00DC034B}, + {0x00000240, 0x80000010}, + {0x00000241, 0x00D10344}, + {0x00000244, 0x80000011}, + {0x00000245, 0x00D00345}, + {0x00000248, 0x80000012}, + {0x00000249, 0x00CC0346}, + {0x0000024C, 0x80000013}, + {0x0000024D, 0x00D70347}, + {0x00000258, 0x80000016}, + {0x00000259, 0x00CA034C}, + {0x00000D05, 0x00000000}, + {0x00000D06, 0x00000000}, + {0x00000D07, 0x00000000}, + {0x00000D09, 0x00000000}, + {0x00000D0A, 0x00000000}, + {0x00000D0B, 0x00000000}, + {0x00000D0D, 0x00000000}, + {0x00000D0E, 0x00000000}, + {0x00000D0F, 0x00000000}, + {0x00000D11, 0x00000000}, + {0x00000D12, 0x00000000}, + {0x00000D13, 0x00000000}, + {0x00000D15, 0x00000000}, + {0x00000D16, 0x00000000}, + {0x00000D17, 0x00000000}, + {0x00000D19, 0x00000000}, + {0x00000D1A, 0x00000000}, + {0x00000D1B, 0x00000000}, + {0x00000D1D, 0x00000140}, + {0x00000D1E, 0x00000000}, + {0x00000D1F, 0x00000000}, + {0x00000D20, 0x10100200}, + {0x00000D21, 0x00000000}, + {0x00000D22, 0x00000000}, + {0x00000D23, 0x00000000}, + {0x00000D24, 0x10210200}, + {0x00000D25, 0x00000000}, + {0x00000D26, 0x00000000}, + {0x00000D27, 0x00000000}, + {0x00000D28, 0x10420200}, + {0x00000D29, 0x00000000}, + {0x00000D2A, 0x00000000}, + {0x00000D2B, 0x00000000}, + {0x00000D2C, 0x10830200}, + {0x00000D2D, 0x00000000}, + {0x00000D2E, 0x00000000}, + {0x00000D2F, 0x00000000}, + {0x00000D31, 0x00000000}, + {0x00000D32, 0x00000000}, + {0x00000D33, 0x00000000} +}; +static unsigned nv3TablePRAMIN_8BPP[][2] = +{ + /* 0xXXXXX3XX For MSB mono format */ + /* 0xXXXXX2XX For LSB mono format */ + {0x00000D04, 0x10110203}, + {0x00000D08, 0x10110203}, + {0x00000D0C, 0x1011020B}, + {0x00000D10, 0x10118203}, + {0x00000D14, 0x10110203}, + {0x00000D18, 0x10110203}, + {0x00000D1C, 0x10419208}, + {0x00000D30, 0x10118203} +}; +static unsigned nv3TablePRAMIN_15BPP[][2] = +{ + /* 0xXXXXX2XX For MSB mono format */ + /* 0xXXXXX3XX For LSB mono format */ + {0x00000D04, 0x10110200}, + {0x00000D08, 0x10110200}, + {0x00000D0C, 0x10110208}, + {0x00000D10, 0x10118200}, + {0x00000D14, 0x10110200}, + {0x00000D18, 0x10110200}, + {0x00000D1C, 0x10419208}, + {0x00000D30, 0x10118200} +}; +static unsigned nv3TablePRAMIN_32BPP[][2] = +{ + /* 0xXXXXX3XX For MSB mono format */ + /* 0xXXXXX2XX For LSB mono format */ + {0x00000D04, 0x10110201}, + {0x00000D08, 0x10110201}, + {0x00000D0C, 0x10110209}, + {0x00000D10, 0x10118201}, + {0x00000D14, 0x10110201}, + {0x00000D18, 0x10110201}, + {0x00000D1C, 0x10419208}, + {0x00000D30, 0x10118201} +}; +static unsigned nv4TableFIFO[][2] = +{ + {0x00003800, 0x80000014} +}; +static unsigned nv4TablePFIFO[][2] = +{ + {0x00000140, 0x00000000}, + {0x00000480, 0x00000000}, + {0x00000494, 0x00000000}, + {0x00000481, 0x00000000}, + {0x0000048B, 0x00000000}, + {0x00000400, 0x00000000}, + {0x00000414, 0x00000000}, + {0x00000084, 0x03000100}, + {0x00000085, 0x00000110}, + {0x00000086, 0x00000112}, + {0x00000143, 0x0000FFFF}, + {0x00000496, 0x0000FFFF}, + {0x00000050, 0x00000000}, + {0x00000040, 0xFFFFFFFF}, + {0x00000415, 0x00000001}, + {0x00000480, 0x00000001}, + {0x00000494, 0x00000001}, + {0x00000495, 0x00000001}, + {0x00000140, 0x00000001} +}; +static unsigned nv4TablePGRAPH[][2] = +{ + {0x00000020, 0x1231C001}, + {0x00000021, 0x72111101}, + {0x00000022, 0x11D5F071}, + {0x00000023, 0x10D4FF31}, + {0x00000060, 0x00000000}, + {0x00000068, 0x00000000}, + {0x00000070, 0x00000000}, + {0x00000078, 0x00000000}, + {0x00000061, 0x00000000}, + {0x00000069, 0x00000000}, + {0x00000071, 0x00000000}, + {0x00000079, 0x00000000}, + {0x00000062, 0x00000000}, + {0x0000006A, 0x00000000}, + {0x00000072, 0x00000000}, + {0x0000007A, 0x00000000}, + {0x00000063, 0x00000000}, + {0x0000006B, 0x00000000}, + {0x00000073, 0x00000000}, + {0x0000007B, 0x00000000}, + {0x00000064, 0x00000000}, + {0x0000006C, 0x00000000}, + {0x00000074, 0x00000000}, + {0x0000007C, 0x00000000}, + {0x00000065, 0x00000000}, + {0x0000006D, 0x00000000}, + {0x00000075, 0x00000000}, + {0x0000007D, 0x00000000}, + {0x00000066, 0x00000000}, + {0x0000006E, 0x00000000}, + {0x00000076, 0x00000000}, + {0x0000007E, 0x00000000}, + {0x00000067, 0x00000000}, + {0x0000006F, 0x00000000}, + {0x00000077, 0x00000000}, + {0x0000007F, 0x00000000}, + {0x00000058, 0x00000000}, + {0x00000059, 0x00000000}, + {0x0000005A, 0x00000000}, + {0x0000005B, 0x00000000}, + {0x00000196, 0x00000000}, + {0x000001A1, 0x01FFFFFF}, + {0x00000197, 0x00000000}, + {0x000001A2, 0x01FFFFFF}, + {0x00000198, 0x00000000}, + {0x000001A3, 0x01FFFFFF}, + {0x00000199, 0x00000000}, + {0x000001A4, 0x01FFFFFF}, + {0x00000050, 0x00000000}, + {0x00000040, 0xFFFFFFFF}, + {0x0000005C, 0x10010100}, + {0x000001C4, 0xFFFFFFFF}, + {0x000001C8, 0x00000001}, + {0x00000204, 0x00000000}, + {0x000001C3, 0x00000001} +}; +static unsigned nv4TablePGRAPH_8BPP[][2] = +{ + {0x000001C9, 0x00111111}, + {0x00000186, 0x00001010}, + {0x0000020C, 0x03020202} +}; +static unsigned nv4TablePGRAPH_15BPP[][2] = +{ + {0x000001C9, 0x00226222}, + {0x00000186, 0x00002071}, + {0x0000020C, 0x09080808} +}; +static unsigned nv4TablePGRAPH_16BPP[][2] = +{ + {0x000001C9, 0x00556555}, + {0x00000186, 0x000050C2}, + {0x0000020C, 0x0C0B0B0B} +}; +static unsigned nv4TablePGRAPH_32BPP[][2] = +{ + {0x000001C9, 0x0077D777}, + {0x00000186, 0x000070E5}, + {0x0000020C, 0x0E0D0D0D} +}; +static unsigned nv4TablePRAMIN[][2] = +{ + {0x00000000, 0x80000010}, + {0x00000001, 0x80011145}, + {0x00000002, 0x80000011}, + {0x00000003, 0x80011146}, + {0x00000004, 0x80000012}, + {0x00000005, 0x80011147}, + {0x00000006, 0x80000013}, + {0x00000007, 0x80011148}, + {0x00000008, 0x80000014}, + {0x00000009, 0x80011149}, + {0x0000000A, 0x80000015}, + {0x0000000B, 0x8001114A}, + {0x0000000C, 0x80000016}, + {0x0000000D, 0x8001114F}, + {0x00000020, 0x80000000}, + {0x00000021, 0x80011142}, + {0x00000022, 0x80000001}, + {0x00000023, 0x80011143}, + {0x00000024, 0x80000002}, + {0x00000025, 0x80011144}, + {0x00000026, 0x80000003}, + {0x00000027, 0x8001114B}, + {0x00000028, 0x80000004}, + {0x00000029, 0x8001114C}, + {0x0000002A, 0x80000005}, + {0x0000002B, 0x8001114D}, + {0x0000002C, 0x80000006}, + {0x0000002D, 0x8001114E}, + {0x00000500, 0x00003000}, + {0x00000501, 0x01FFFFFF}, + {0x00000502, 0x00000002}, + {0x00000503, 0x00000002}, + {0x00000508, 0x01008043}, + {0x0000050A, 0x00000000}, + {0x0000050B, 0x00000000}, + {0x0000050C, 0x01008019}, + {0x0000050E, 0x00000000}, + {0x0000050F, 0x00000000}, +#if 1 + {0x00000510, 0x01008018}, +#else + {0x00000510, 0x01008044}, +#endif + {0x00000512, 0x00000000}, + {0x00000513, 0x00000000}, + {0x00000514, 0x01008021}, + {0x00000516, 0x00000000}, + {0x00000517, 0x00000000}, + {0x00000518, 0x0100805F}, + {0x0000051A, 0x00000000}, + {0x0000051B, 0x00000000}, +#if 1 + {0x0000051C, 0x0100804B}, +#else + {0x0000051C, 0x0100804A}, +#endif + {0x0000051E, 0x00000000}, + {0x0000051F, 0x00000000}, + {0x00000520, 0x0100A048}, + {0x00000521, 0x00000D01}, + {0x00000522, 0x11401140}, + {0x00000523, 0x00000000}, + {0x00000524, 0x0300A054}, + {0x00000525, 0x00000D01}, + {0x00000526, 0x11401140}, + {0x00000527, 0x00000000}, + {0x00000528, 0x0300A055}, + {0x00000529, 0x00000D01}, + {0x0000052A, 0x11401140}, + {0x0000052B, 0x00000000}, + {0x0000052C, 0x00000058}, + {0x0000052E, 0x11401140}, + {0x0000052F, 0x00000000}, + {0x00000530, 0x00000059}, + {0x00000532, 0x11401140}, + {0x00000533, 0x00000000}, + {0x00000534, 0x0000005A}, + {0x00000536, 0x11401140}, + {0x00000537, 0x00000000}, + {0x00000538, 0x0000005B}, + {0x0000053A, 0x11401140}, + {0x0000053B, 0x00000000}, + {0x0000053C, 0x0300A01C}, + {0x0000053E, 0x11401140}, + {0x0000053F, 0x00000000} +}; +static unsigned nv4TablePRAMIN_8BPP[][2] = +{ + /* 0xXXXXXX01 For MSB mono format */ + /* 0xXXXXXX02 For LSB mono format */ + {0x00000509, 0x00000302}, + {0x0000050D, 0x00000302}, + {0x00000511, 0x00000202}, + {0x00000515, 0x00000302}, + {0x00000519, 0x00000302}, + {0x0000051D, 0x00000302}, + {0x0000052D, 0x00000302}, + {0x0000052E, 0x00000302}, + {0x00000535, 0x00000000}, + {0x00000539, 0x00000000}, + {0x0000053D, 0x00000302} +}; +static unsigned nv4TablePRAMIN_15BPP[][2] = +{ + /* 0xXXXXXX01 For MSB mono format */ + /* 0xXXXXXX02 For LSB mono format */ + {0x00000509, 0x00000902}, + {0x0000050D, 0x00000902}, + {0x00000511, 0x00000802}, + {0x00000515, 0x00000902}, + {0x00000519, 0x00000902}, + {0x0000051D, 0x00000902}, + {0x0000052D, 0x00000902}, + {0x0000052E, 0x00000902}, + {0x00000535, 0x00000702}, + {0x00000539, 0x00000702}, + {0x0000053D, 0x00000902} +}; +static unsigned nv4TablePRAMIN_16BPP[][2] = +{ + /* 0xXXXXXX01 For MSB mono format */ + /* 0xXXXXXX02 For LSB mono format */ + {0x00000509, 0x00000C02}, + {0x0000050D, 0x00000C02}, + {0x00000511, 0x00000B02}, + {0x00000515, 0x00000C02}, + {0x00000519, 0x00000C02}, + {0x0000051D, 0x00000C02}, + {0x0000052D, 0x00000C02}, + {0x0000052E, 0x00000C02}, + {0x00000535, 0x00000702}, + {0x00000539, 0x00000702}, + {0x0000053D, 0x00000C02} +}; +static unsigned nv4TablePRAMIN_32BPP[][2] = +{ + /* 0xXXXXXX01 For MSB mono format */ + /* 0xXXXXXX02 For LSB mono format */ + {0x00000509, 0x00000E02}, + {0x0000050D, 0x00000E02}, + {0x00000511, 0x00000D02}, + {0x00000515, 0x00000E02}, + {0x00000519, 0x00000E02}, + {0x0000051D, 0x00000E02}, + {0x0000052D, 0x00000E02}, + {0x0000052E, 0x00000E02}, + {0x00000535, 0x00000E02}, + {0x00000539, 0x00000E02}, + {0x0000053D, 0x00000E02} +}; +static unsigned nv10TableFIFO[][2] = +{ + {0x00003800, 0x80000014} +}; +static unsigned nv10TablePFIFO[][2] = +{ + {0x00000140, 0x00000000}, + {0x00000480, 0x00000000}, + {0x00000494, 0x00000000}, + {0x00000481, 0x00000000}, + {0x0000048B, 0x00000000}, + {0x00000400, 0x00000000}, + {0x00000414, 0x00000000}, + {0x00000084, 0x03000100}, + {0x00000085, 0x00000110}, + {0x00000086, 0x00000112}, + {0x00000143, 0x0000FFFF}, + {0x00000496, 0x0000FFFF}, + {0x00000050, 0x00000000}, + {0x00000040, 0xFFFFFFFF}, + {0x00000415, 0x00000001}, + {0x00000480, 0x00000001}, + {0x00000494, 0x00000001}, + {0x00000495, 0x00000001}, + {0x00000140, 0x00000001} +}; +static unsigned nv10TablePGRAPH[][2] = +{ + {0x00000020, 0x0003FFFF}, + {0x00000021, 0x00118701}, + {0x00000022, 0x24F82AD9}, + {0x00000023, 0x55DE0030}, + {0x00000020, 0x00000000}, + {0x00000024, 0x00000000}, + {0x00000058, 0x00000000}, + {0x00000060, 0x00000000}, + {0x00000068, 0x00000000}, + {0x00000070, 0x00000000}, + {0x00000078, 0x00000000}, + {0x00000059, 0x00000000}, + {0x00000061, 0x00000000}, + {0x00000069, 0x00000000}, + {0x00000071, 0x00000000}, + {0x00000079, 0x00000000}, + {0x0000005A, 0x00000000}, + {0x00000062, 0x00000000}, + {0x0000006A, 0x00000000}, + {0x00000072, 0x00000000}, + {0x0000007A, 0x00000000}, + {0x0000005B, 0x00000000}, + {0x00000063, 0x00000000}, + {0x0000006B, 0x00000000}, + {0x00000073, 0x00000000}, + {0x0000007B, 0x00000000}, + {0x0000005C, 0x00000000}, + {0x00000064, 0x00000000}, + {0x0000006C, 0x00000000}, + {0x00000074, 0x00000000}, + {0x0000007C, 0x00000000}, + {0x0000005D, 0x00000000}, + {0x00000065, 0x00000000}, + {0x0000006D, 0x00000000}, + {0x00000075, 0x00000000}, + {0x0000007D, 0x00000000}, + {0x0000005E, 0x00000000}, + {0x00000066, 0x00000000}, + {0x0000006E, 0x00000000}, + {0x00000076, 0x00000000}, + {0x0000007E, 0x00000000}, + {0x0000005F, 0x00000000}, + {0x00000067, 0x00000000}, + {0x0000006F, 0x00000000}, + {0x00000077, 0x00000000}, + {0x0000007F, 0x00000000}, + {0x00000053, 0x00000000}, + {0x00000054, 0x00000000}, + {0x00000055, 0x00000000}, + {0x00000056, 0x00000000}, + {0x00000057, 0x00000000}, + {0x00000196, 0x00000000}, + {0x000001A1, 0x01FFFFFF}, + {0x00000197, 0x00000000}, + {0x000001A2, 0x01FFFFFF}, + {0x00000198, 0x00000000}, + {0x000001A3, 0x01FFFFFF}, + {0x00000199, 0x00000000}, + {0x000001A4, 0x01FFFFFF}, + {0x0000019A, 0x00000000}, + {0x000001A5, 0x01FFFFFF}, + {0x0000019B, 0x00000000}, + {0x000001A6, 0x01FFFFFF}, + {0x00000050, 0x01111111}, + {0x00000040, 0xFFFFFFFF}, + {0x00000051, 0x10010100}, + {0x000001C5, 0xFFFFFFFF}, + {0x000001C8, 0x00000001}, + {0x00000204, 0x00000000}, + {0x000001C4, 0x00000001} +}; +static unsigned nv10TablePGRAPH_8BPP[][2] = +{ + {0x000001C9, 0x00111111}, + {0x00000186, 0x00001010}, + {0x0000020C, 0x03020202} +}; +static unsigned nv10TablePGRAPH_15BPP[][2] = +{ + {0x000001C9, 0x00226222}, + {0x00000186, 0x00002071}, + {0x0000020C, 0x09080808} +}; +static unsigned nv10TablePGRAPH_16BPP[][2] = +{ + {0x000001C9, 0x00556555}, + {0x00000186, 0x000050C2}, + {0x0000020C, 0x000B0B0C} +}; +static unsigned nv10TablePGRAPH_32BPP[][2] = +{ + {0x000001C9, 0x0077D777}, + {0x00000186, 0x000070E5}, + {0x0000020C, 0x0E0D0D0D} +}; +static unsigned nv10TablePRAMIN[][2] = +{ + {0x00000000, 0x80000010}, + {0x00000001, 0x80011145}, + {0x00000002, 0x80000011}, + {0x00000003, 0x80011146}, + {0x00000004, 0x80000012}, + {0x00000005, 0x80011147}, + {0x00000006, 0x80000013}, + {0x00000007, 0x80011148}, + {0x00000008, 0x80000014}, + {0x00000009, 0x80011149}, + {0x0000000A, 0x80000015}, + {0x0000000B, 0x8001114A}, + {0x0000000C, 0x80000016}, + {0x0000000D, 0x80011150}, + {0x00000020, 0x80000000}, + {0x00000021, 0x80011142}, + {0x00000022, 0x80000001}, + {0x00000023, 0x80011143}, + {0x00000024, 0x80000002}, + {0x00000025, 0x80011144}, + {0x00000026, 0x80000003}, + {0x00000027, 0x8001114B}, + {0x00000028, 0x80000004}, + {0x00000029, 0x8001114C}, + {0x0000002A, 0x80000005}, + {0x0000002B, 0x8001114D}, + {0x0000002C, 0x80000006}, + {0x0000002D, 0x8001114E}, + {0x0000002E, 0x80000007}, + {0x0000002F, 0x8001114F}, + {0x00000500, 0x00003000}, + {0x00000501, 0x01FFFFFF}, + {0x00000502, 0x00000002}, + {0x00000503, 0x00000002}, +#if X_BYTE_ORDER == X_BIG_ENDIAN + {0x00000508, 0x01088043}, +#else + {0x00000508, 0x01008043}, +#endif + {0x0000050A, 0x00000000}, + {0x0000050B, 0x00000000}, +#if X_BYTE_ORDER == X_BIG_ENDIAN + {0x0000050C, 0x01088019}, +#else + {0x0000050C, 0x01008019}, +#endif + {0x0000050E, 0x00000000}, + {0x0000050F, 0x00000000}, +#if X_BYTE_ORDER == X_BIG_ENDIAN + {0x00000510, 0x01088018}, +#else + {0x00000510, 0x01008018}, +#endif + {0x00000512, 0x00000000}, + {0x00000513, 0x00000000}, +#if X_BYTE_ORDER == X_BIG_ENDIAN + {0x00000514, 0x01088021}, +#else + {0x00000514, 0x01008021}, +#endif + {0x00000516, 0x00000000}, + {0x00000517, 0x00000000}, +#if X_BYTE_ORDER == X_BIG_ENDIAN + {0x00000518, 0x0108805F}, +#else + {0x00000518, 0x0100805F}, +#endif + {0x0000051A, 0x00000000}, + {0x0000051B, 0x00000000}, +#if X_BYTE_ORDER == X_BIG_ENDIAN + {0x0000051C, 0x0108804B}, +#else + {0x0000051C, 0x0100804B}, +#endif + {0x0000051E, 0x00000000}, + {0x0000051F, 0x00000000}, + {0x00000520, 0x0100A048}, + {0x00000521, 0x00000D01}, + {0x00000522, 0x11401140}, + {0x00000523, 0x00000000}, + {0x00000524, 0x0300A094}, + {0x00000525, 0x00000D01}, + {0x00000526, 0x11401140}, + {0x00000527, 0x00000000}, + {0x00000528, 0x0300A095}, + {0x00000529, 0x00000D01}, + {0x0000052A, 0x11401140}, + {0x0000052B, 0x00000000}, +#if X_BYTE_ORDER == X_BIG_ENDIAN + {0x0000052C, 0x00080058}, +#else + {0x0000052C, 0x00000058}, +#endif + {0x0000052E, 0x11401140}, + {0x0000052F, 0x00000000}, +#if X_BYTE_ORDER == X_BIG_ENDIAN + {0x00000530, 0x00080059}, +#else + {0x00000530, 0x00000059}, +#endif + {0x00000532, 0x11401140}, + {0x00000533, 0x00000000}, + {0x00000534, 0x0000005A}, + {0x00000536, 0x11401140}, + {0x00000537, 0x00000000}, + {0x00000538, 0x0000005B}, + {0x0000053A, 0x11401140}, + {0x0000053B, 0x00000000}, + {0x0000053C, 0x00000093}, + {0x0000053E, 0x11401140}, + {0x0000053F, 0x00000000}, +#if X_BYTE_ORDER == X_BIG_ENDIAN + {0x00000540, 0x0308A01C}, +#else + {0x00000540, 0x0300A01C}, +#endif + {0x00000542, 0x11401140}, + {0x00000543, 0x00000000} +}; +static unsigned nv10TablePRAMIN_8BPP[][2] = +{ + /* 0xXXXXXX01 For MSB mono format */ + /* 0xXXXXXX02 For LSB mono format */ + {0x00000509, 0x00000302}, + {0x0000050D, 0x00000302}, + {0x00000511, 0x00000202}, + {0x00000515, 0x00000302}, + {0x00000519, 0x00000302}, + {0x0000051D, 0x00000302}, + {0x0000052D, 0x00000302}, + {0x0000052E, 0x00000302}, + {0x00000535, 0x00000000}, + {0x00000539, 0x00000000}, + {0x0000053D, 0x00000000}, + {0x00000541, 0x00000302} +}; +static unsigned nv10TablePRAMIN_15BPP[][2] = +{ + /* 0xXXXXXX01 For MSB mono format */ + /* 0xXXXXXX02 For LSB mono format */ + {0x00000509, 0x00000902}, + {0x0000050D, 0x00000902}, + {0x00000511, 0x00000802}, + {0x00000515, 0x00000902}, + {0x00000519, 0x00000902}, + {0x0000051D, 0x00000902}, + {0x0000052D, 0x00000902}, + {0x0000052E, 0x00000902}, + {0x00000535, 0x00000902}, + {0x00000539, 0x00000902}, + {0x0000053D, 0x00000902}, + {0x00000541, 0x00000902} +}; +static unsigned nv10TablePRAMIN_16BPP[][2] = +{ + /* 0xXXXXXX01 For MSB mono format */ + /* 0xXXXXXX02 For LSB mono format */ + {0x00000509, 0x00000C02}, + {0x0000050D, 0x00000C02}, + {0x00000511, 0x00000B02}, + {0x00000515, 0x00000C02}, + {0x00000519, 0x00000C02}, + {0x0000051D, 0x00000C02}, + {0x0000052D, 0x00000C02}, + {0x0000052E, 0x00000C02}, + {0x00000535, 0x00000C02}, + {0x00000539, 0x00000C02}, + {0x0000053D, 0x00000C02}, + {0x00000541, 0x00000C02} +}; +static unsigned nv10TablePRAMIN_32BPP[][2] = +{ + /* 0xXXXXXX01 For MSB mono format */ + /* 0xXXXXXX02 For LSB mono format */ + {0x00000509, 0x00000E02}, + {0x0000050D, 0x00000E02}, + {0x00000511, 0x00000D02}, + {0x00000515, 0x00000E02}, + {0x00000519, 0x00000E02}, + {0x0000051D, 0x00000E02}, + {0x0000052D, 0x00000E02}, + {0x0000052E, 0x00000E02}, + {0x00000535, 0x00000E02}, + {0x00000539, 0x00000E02}, + {0x0000053D, 0x00000E02}, + {0x00000541, 0x00000E02} +}; + |