g80_driver.c revision f3561b8b
1fc5a983dSmrg/* 2fc5a983dSmrg * Copyright (c) 2007 NVIDIA, Corporation 3fc5a983dSmrg * 4fc5a983dSmrg * Permission is hereby granted, free of charge, to any person obtaining a 5fc5a983dSmrg * copy of this software and associated documentation files (the 6fc5a983dSmrg * "Software"), to deal in the Software without restriction, including 7fc5a983dSmrg * without limitation the rights to use, copy, modify, merge, publish, 8fc5a983dSmrg * distribute, sublicense, and/or sell copies of the Software, and to 9fc5a983dSmrg * permit persons to whom the Software is furnished to do so, subject to 10fc5a983dSmrg * the following conditions: 11fc5a983dSmrg * 12fc5a983dSmrg * The above copyright notice and this permission notice shall be included 13fc5a983dSmrg * in all copies or substantial portions of the Software. 14fc5a983dSmrg * 15fc5a983dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16fc5a983dSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17fc5a983dSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18fc5a983dSmrg * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19fc5a983dSmrg * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20fc5a983dSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21fc5a983dSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22fc5a983dSmrg */ 23fc5a983dSmrg 24fc5a983dSmrg 25fc5a983dSmrg#ifdef HAVE_CONFIG_H 26fc5a983dSmrg#include "config.h" 27fc5a983dSmrg#endif 28fc5a983dSmrg 29fc5a983dSmrg#include <string.h> 30fc5a983dSmrg 31fc5a983dSmrg#include <xf86_OSproc.h> 32fc5a983dSmrg#include <xf86Resources.h> 33fc5a983dSmrg#include <xf86RandR12.h> 34fc5a983dSmrg#include <mipointer.h> 35fc5a983dSmrg#include <mibstore.h> 36fc5a983dSmrg#include <micmap.h> 37fc5a983dSmrg#include <xf86cmap.h> 38fc5a983dSmrg#include <fb.h> 39fc5a983dSmrg#define DPMS_SERVER 40fc5a983dSmrg#include <X11/extensions/dpms.h> 41fc5a983dSmrg 42fc5a983dSmrg#include "nv_const.h" 43fc5a983dSmrg#include "g80_type.h" 44fc5a983dSmrg#include "g80_cursor.h" 45fc5a983dSmrg#include "g80_display.h" 46fc5a983dSmrg#include "g80_dma.h" 47fc5a983dSmrg#include "g80_output.h" 48fc5a983dSmrg#include "g80_exa.h" 49fc5a983dSmrg#include "g80_xaa.h" 50fc5a983dSmrg 51fc5a983dSmrg#define G80_REG_SIZE (1024 * 1024 * 16) 52fc5a983dSmrg#define G80_RESERVED_VIDMEM 0xd000 53fc5a983dSmrg 54fc5a983dSmrgstatic const char *fbSymbols[] = { 55fc5a983dSmrg "fbPictureInit", 56fc5a983dSmrg "fbScreenInit", 57fc5a983dSmrg NULL 58fc5a983dSmrg}; 59fc5a983dSmrg 60fc5a983dSmrgstatic const char *xaaSymbols[] = { 61fc5a983dSmrg "XAACopyROP", 62fc5a983dSmrg "XAACreateInfoRec", 63fc5a983dSmrg "XAADestroyInfoRec", 64fc5a983dSmrg "XAAFallbackOps", 65fc5a983dSmrg "XAAInit", 66fc5a983dSmrg "XAAPatternROP", 67fc5a983dSmrg NULL 68fc5a983dSmrg}; 69fc5a983dSmrg 70fc5a983dSmrgstatic const char *exaSymbols[] = { 71fc5a983dSmrg "exaDriverAlloc", 72fc5a983dSmrg "exaDriverInit", 73fc5a983dSmrg "exaDriverFini", 74fc5a983dSmrg NULL 75fc5a983dSmrg}; 76fc5a983dSmrg 77fc5a983dSmrgstatic const char *i2cSymbols[] = { 78fc5a983dSmrg "xf86CreateI2CBusRec", 79fc5a983dSmrg "xf86I2CBusInit", 80fc5a983dSmrg NULL 81fc5a983dSmrg}; 82fc5a983dSmrg 83fc5a983dSmrgstatic const char *ramdacSymbols[] = { 84fc5a983dSmrg "xf86CreateCursorInfoRec", 85fc5a983dSmrg "xf86DestroyCursorInfoRec", 86fc5a983dSmrg "xf86InitCursor", 87fc5a983dSmrg NULL 88fc5a983dSmrg}; 89fc5a983dSmrg 90fc5a983dSmrgstatic const char *ddcSymbols[] = { 91fc5a983dSmrg "xf86PrintEDID", 92fc5a983dSmrg "xf86DoEDID_DDC2", 93fc5a983dSmrg "xf86SetDDCproperties", 94fc5a983dSmrg NULL 95fc5a983dSmrg}; 96fc5a983dSmrg 97fc5a983dSmrgstatic const char *int10Symbols[] = { 98fc5a983dSmrg "xf86FreeInt10", 99fc5a983dSmrg "xf86InitInt10", 100fc5a983dSmrg "xf86ExecX86int10", 101fc5a983dSmrg NULL 102fc5a983dSmrg}; 103fc5a983dSmrg 104fc5a983dSmrgtypedef enum { 105fc5a983dSmrg OPTION_HW_CURSOR, 106fc5a983dSmrg OPTION_NOACCEL, 107fc5a983dSmrg OPTION_ACCEL_METHOD, 108fc5a983dSmrg OPTION_FP_DITHER, 109fc5a983dSmrg OPTION_ALLOW_DUAL_LINK, 110fc5a983dSmrg} G80Opts; 111fc5a983dSmrg 112fc5a983dSmrgstatic const OptionInfoRec G80Options[] = { 113fc5a983dSmrg { OPTION_HW_CURSOR, "HWCursor", OPTV_BOOLEAN, {0}, FALSE }, 114fc5a983dSmrg { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 115fc5a983dSmrg { OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE }, 116fc5a983dSmrg { OPTION_FP_DITHER, "FPDither", OPTV_BOOLEAN, {0}, FALSE }, 117fc5a983dSmrg { OPTION_ALLOW_DUAL_LINK, "AllowDualLinkModes", OPTV_BOOLEAN, {0}, FALSE }, 118fc5a983dSmrg { -1, NULL, OPTV_NONE, {0}, FALSE } 119fc5a983dSmrg}; 120fc5a983dSmrg 121fc5a983dSmrgstatic Bool 122fc5a983dSmrgG80GetRec(ScrnInfoPtr pScrn) 123fc5a983dSmrg{ 124fc5a983dSmrg if(pScrn->driverPrivate == NULL) 125fc5a983dSmrg pScrn->driverPrivate = xcalloc(sizeof(G80Rec), 1); 126fc5a983dSmrg 127fc5a983dSmrg return (pScrn->driverPrivate != NULL); 128fc5a983dSmrg} 129fc5a983dSmrg 130fc5a983dSmrgstatic void 131fc5a983dSmrgG80FreeRec(ScrnInfoPtr pScrn) 132fc5a983dSmrg{ 133fc5a983dSmrg xfree(pScrn->driverPrivate); 134fc5a983dSmrg pScrn->driverPrivate = NULL; 135fc5a983dSmrg} 136fc5a983dSmrg 137fc5a983dSmrgstatic Bool 138fc5a983dSmrgG80ResizeScreen(ScrnInfoPtr pScrn, int width, int height) 139fc5a983dSmrg{ 140fc5a983dSmrg ScreenPtr pScreen = pScrn->pScreen; 141fc5a983dSmrg G80Ptr pNv = G80PTR(pScrn); 142fc5a983dSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 143fc5a983dSmrg int pitch = width * (pScrn->bitsPerPixel / 8); 144fc5a983dSmrg int i; 145fc5a983dSmrg 146fc5a983dSmrg pitch = (pitch + 255) & ~255; 147fc5a983dSmrg 148fc5a983dSmrg pScrn->virtualX = width; 149fc5a983dSmrg pScrn->virtualY = height; 150fc5a983dSmrg 151fc5a983dSmrg /* Can resize if XAA is disabled or EXA is enabled */ 152fc5a983dSmrg if(!pNv->xaa || pNv->exa) { 153fc5a983dSmrg (*pScrn->pScreen->GetScreenPixmap)(pScrn->pScreen)->devKind = pitch; 154fc5a983dSmrg pScrn->displayWidth = pitch / (pScrn->bitsPerPixel / 8); 155fc5a983dSmrg 156fc5a983dSmrg /* Re-set the modes so the new pitch is taken into account */ 157fc5a983dSmrg for(i = 0; i < xf86_config->num_crtc; i++) { 158fc5a983dSmrg xf86CrtcPtr crtc = xf86_config->crtc[i]; 159fc5a983dSmrg if(crtc->enabled) 160fc5a983dSmrg xf86CrtcSetMode(crtc, &crtc->mode, crtc->rotation, crtc->x, crtc->y); 161fc5a983dSmrg } 162fc5a983dSmrg } 163fc5a983dSmrg 164fc5a983dSmrg /* 165fc5a983dSmrg * If EXA is enabled, use exaOffscreenAlloc to carve out a chunk of memory 166fc5a983dSmrg * for the screen. 167fc5a983dSmrg */ 168fc5a983dSmrg if(pNv->exa) { 169fc5a983dSmrg if(pNv->exaScreenArea) 170fc5a983dSmrg exaOffscreenFree(pScreen, pNv->exaScreenArea); 171fc5a983dSmrg pNv->exaScreenArea = exaOffscreenAlloc(pScreen, pitch * pScrn->virtualY, 172fc5a983dSmrg 256, TRUE, NULL, NULL); 173fc5a983dSmrg if(!pNv->exaScreenArea || pNv->exaScreenArea->offset != 0) { 174fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 175fc5a983dSmrg "Failed to reserve EXA memory for the screen or EXA " 176fc5a983dSmrg "returned an area with a nonzero offset. Don't be " 177fc5a983dSmrg "surprised if your screen is corrupt.\n"); 178fc5a983dSmrg } 179fc5a983dSmrg } 180fc5a983dSmrg 181fc5a983dSmrg return TRUE; 182fc5a983dSmrg} 183fc5a983dSmrg 184fc5a983dSmrgstatic const xf86CrtcConfigFuncsRec randr12_screen_funcs = { 185fc5a983dSmrg .resize = G80ResizeScreen, 186fc5a983dSmrg}; 187fc5a983dSmrg 188fc5a983dSmrgstatic Bool 189fc5a983dSmrgG80PreInit(ScrnInfoPtr pScrn, int flags) 190fc5a983dSmrg{ 191fc5a983dSmrg G80Ptr pNv; 192fc5a983dSmrg EntityInfoPtr pEnt; 193fc5a983dSmrg#if XSERVER_LIBPCIACCESS 194fc5a983dSmrg struct pci_device *pPci; 195fc5a983dSmrg int err; 196fc5a983dSmrg void *p; 197fc5a983dSmrg#else 198fc5a983dSmrg pciVideoPtr pPci; 199fc5a983dSmrg PCITAG pcitag; 200fc5a983dSmrg#endif 201fc5a983dSmrg MessageType from; 202fc5a983dSmrg Bool primary; 203fc5a983dSmrg const rgb zeros = {0, 0, 0}; 204fc5a983dSmrg const Gamma gzeros = {0.0, 0.0, 0.0}; 205fc5a983dSmrg char *s; 206fc5a983dSmrg CARD32 tmp; 207fc5a983dSmrg memType BAR1sizeKB; 208fc5a983dSmrg 209f3561b8bSmrg if(flags & PROBE_DETECT) 210f3561b8bSmrg return TRUE; 211fc5a983dSmrg 212fc5a983dSmrg /* Check the number of entities, and fail if it isn't one. */ 213fc5a983dSmrg if(pScrn->numEntities != 1) 214fc5a983dSmrg return FALSE; 215fc5a983dSmrg 216fc5a983dSmrg /* Allocate the NVRec driverPrivate */ 217fc5a983dSmrg if(!G80GetRec(pScrn)) { 218fc5a983dSmrg return FALSE; 219fc5a983dSmrg } 220fc5a983dSmrg pNv = G80PTR(pScrn); 221fc5a983dSmrg 222fc5a983dSmrg /* Get the entity, and make sure it is PCI. */ 223fc5a983dSmrg pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 224fc5a983dSmrg if(pEnt->location.type != BUS_PCI) goto fail; 225fc5a983dSmrg pPci = xf86GetPciInfoForEntity(pEnt->index); 226fc5a983dSmrg#if XSERVER_LIBPCIACCESS 227fc5a983dSmrg /* Need this to unmap */ 228fc5a983dSmrg pNv->pPci = pPci; 229fc5a983dSmrg#endif 230fc5a983dSmrg primary = xf86IsPrimaryPci(pPci); 231fc5a983dSmrg 232fc5a983dSmrg /* The ROM size sometimes isn't read correctly, so fix it up here. */ 233fc5a983dSmrg#if XSERVER_LIBPCIACCESS 234fc5a983dSmrg if(pPci->rom_size == 0) 235fc5a983dSmrg /* The BIOS is 64k */ 236fc5a983dSmrg pPci->rom_size = 64 * 1024; 237fc5a983dSmrg#else 238fc5a983dSmrg if(pPci->biosSize == 0) 239fc5a983dSmrg /* The BIOS is 64k */ 240fc5a983dSmrg pPci->biosSize = 16; 241fc5a983dSmrg#endif 242fc5a983dSmrg 243fc5a983dSmrg pNv->int10 = NULL; 244fc5a983dSmrg pNv->int10Mode = 0; 245fc5a983dSmrg if(xf86LoadSubModule(pScrn, "int10")) { 246fc5a983dSmrg xf86LoaderReqSymLists(int10Symbols, NULL); 247fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing int10\n"); 248fc5a983dSmrg pNv->int10 = xf86InitInt10(pEnt->index); 249fc5a983dSmrg } 250fc5a983dSmrg 251fc5a983dSmrg if(!pNv->int10) { 252fc5a983dSmrg if(primary) { 253fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 254fc5a983dSmrg "Failed to initialize the int10 module; the console " 255fc5a983dSmrg "will not be restored.\n"); 256fc5a983dSmrg } else { 257fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 258fc5a983dSmrg "Failed to initialize the int10 module; this screen " 259fc5a983dSmrg "will not be initialized.\n"); 260fc5a983dSmrg goto fail; 261fc5a983dSmrg } 262fc5a983dSmrg } 263fc5a983dSmrg 264fc5a983dSmrg if(primary && pNv->int10) { 265fc5a983dSmrg const xf86Int10InfoPtr int10 = pNv->int10; 266fc5a983dSmrg 267fc5a983dSmrg /* Get the current video mode */ 268fc5a983dSmrg int10->num = 0x10; 269fc5a983dSmrg int10->ax = 0x4f03; 270fc5a983dSmrg int10->bx = int10->cx = int10->dx = 0; 271fc5a983dSmrg xf86ExecX86int10(int10); 272fc5a983dSmrg pNv->int10Mode = int10->bx & 0x3fff; 273fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Console is VGA mode 0x%x\n", 274fc5a983dSmrg pNv->int10Mode); 275fc5a983dSmrg } 276fc5a983dSmrg 277fc5a983dSmrg /* Disable VGA access */ 278fc5a983dSmrg xf86SetOperatingState(resVgaIo, pEnt->index, ResUnusedOpr); 279fc5a983dSmrg xf86SetOperatingState(resVgaMem, pEnt->index, ResDisableOpr); 280fc5a983dSmrg 281fc5a983dSmrg pScrn->monitor = pScrn->confScreen->monitor; 282fc5a983dSmrg 283fc5a983dSmrg if(!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb)) goto fail; 284fc5a983dSmrg switch (pScrn->depth) { 285fc5a983dSmrg case 8: 286fc5a983dSmrg case 15: 287fc5a983dSmrg case 16: 288fc5a983dSmrg case 24: 289fc5a983dSmrg /* OK */ 290fc5a983dSmrg break; 291fc5a983dSmrg default: 292fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 293fc5a983dSmrg "Given depth (%d) is not supported by this driver\n", 294fc5a983dSmrg pScrn->depth); 295fc5a983dSmrg goto fail; 296fc5a983dSmrg } 297fc5a983dSmrg xf86PrintDepthBpp(pScrn); 298fc5a983dSmrg 299fc5a983dSmrg if(!xf86SetWeight(pScrn, zeros, zeros)) goto fail; 300fc5a983dSmrg if(!xf86SetDefaultVisual(pScrn, -1)) goto fail; 301fc5a983dSmrg 302fc5a983dSmrg /* We use a programmable clock */ 303fc5a983dSmrg pScrn->progClock = TRUE; 304fc5a983dSmrg 305fc5a983dSmrg /* Process options */ 306fc5a983dSmrg xf86CollectOptions(pScrn, NULL); 307fc5a983dSmrg if(!(pNv->Options = xalloc(sizeof(G80Options)))) goto fail; 308fc5a983dSmrg memcpy(pNv->Options, G80Options, sizeof(G80Options)); 309fc5a983dSmrg xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pNv->Options); 310fc5a983dSmrg 311fc5a983dSmrg from = X_DEFAULT; 312fc5a983dSmrg pNv->HWCursor = TRUE; 313fc5a983dSmrg if(xf86GetOptValBool(pNv->Options, OPTION_HW_CURSOR, &pNv->HWCursor)) 314fc5a983dSmrg from = X_CONFIG; 315fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", 316fc5a983dSmrg pNv->HWCursor ? "hardware" : "software"); 317fc5a983dSmrg if(xf86ReturnOptValBool(pNv->Options, OPTION_NOACCEL, FALSE)) { 318fc5a983dSmrg pNv->NoAccel = TRUE; 319fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); 320fc5a983dSmrg } 321fc5a983dSmrg s = xf86GetOptValString(pNv->Options, OPTION_ACCEL_METHOD); 322fc5a983dSmrg if(!s || !strcasecmp(s, "xaa")) 323fc5a983dSmrg pNv->AccelMethod = XAA; 324fc5a983dSmrg else if(!strcasecmp(s, "exa")) 325fc5a983dSmrg pNv->AccelMethod = EXA; 326fc5a983dSmrg else { 327fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unrecognized AccelMethod " 328fc5a983dSmrg "\"%s\".\n", s); 329fc5a983dSmrg goto fail; 330fc5a983dSmrg } 331fc5a983dSmrg 332fc5a983dSmrg pNv->Dither = xf86ReturnOptValBool(pNv->Options, OPTION_FP_DITHER, FALSE); 333fc5a983dSmrg pNv->AllowDualLink = xf86ReturnOptValBool(pNv->Options, OPTION_ALLOW_DUAL_LINK, FALSE); 334fc5a983dSmrg 335fc5a983dSmrg /* Set the bits per RGB for 8bpp mode */ 336fc5a983dSmrg if(pScrn->depth == 8) 337fc5a983dSmrg pScrn->rgbBits = 8; 338fc5a983dSmrg 339fc5a983dSmrg if(!xf86SetGamma(pScrn, gzeros)) goto fail; 340fc5a983dSmrg 341fc5a983dSmrg /* Map memory */ 342fc5a983dSmrg pScrn->memPhysBase = MEMBASE(pPci, 1); 343fc5a983dSmrg pScrn->fbOffset = 0; 344fc5a983dSmrg 345fc5a983dSmrg#if XSERVER_LIBPCIACCESS 346fc5a983dSmrg err = pci_device_map_range(pPci, pPci->regions[0].base_addr, G80_REG_SIZE, 347fc5a983dSmrg PCI_DEV_MAP_FLAG_WRITABLE, &p); 348fc5a983dSmrg if(err) { 349fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 350fc5a983dSmrg "Failed to map MMIO registers: %s\n", strerror(err)); 351fc5a983dSmrg goto fail; 352fc5a983dSmrg } 353fc5a983dSmrg pNv->reg = p; 354fc5a983dSmrg#else 355fc5a983dSmrg pcitag = pciTag(pPci->bus, pPci->device, pPci->func); 356fc5a983dSmrg pNv->reg = xf86MapPciMem(pScrn->scrnIndex, 357fc5a983dSmrg VIDMEM_MMIO | VIDMEM_READSIDEEFFECT, 358fc5a983dSmrg pcitag, pPci->memBase[0], G80_REG_SIZE); 359fc5a983dSmrg#endif 360fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MMIO registers mapped at %p\n", 361fc5a983dSmrg (void*)pNv->reg); 362fc5a983dSmrg 363fc5a983dSmrg if(xf86RegisterResources(pEnt->index, NULL, ResExclusive)) { 364fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86RegisterResources() found " 365fc5a983dSmrg "resource conflicts\n"); 366fc5a983dSmrg goto fail; 367fc5a983dSmrg } 368fc5a983dSmrg 369fc5a983dSmrg pNv->architecture = pNv->reg[0] >> 20 & 0x1ff; 370fc5a983dSmrg tmp = pNv->reg[0x0010020C/4]; 371fc5a983dSmrg pNv->videoRam = pNv->RamAmountKBytes = tmp >> 10 | (tmp & 1) << 22; 372fc5a983dSmrg 373fc5a983dSmrg /* Determine the size of BAR1 */ 374fc5a983dSmrg /* Some configs have BAR1 < total RAM < 256 MB */ 375fc5a983dSmrg#if XSERVER_LIBPCIACCESS 376fc5a983dSmrg BAR1sizeKB = pPci->regions[1].size / 1024; 377fc5a983dSmrg#else 378fc5a983dSmrg BAR1sizeKB = 1UL << (pPci->size[1] - 10); 379fc5a983dSmrg#endif 380fc5a983dSmrg if(BAR1sizeKB > 256 * 1024) { 381fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "BAR1 is > 256 MB, which is " 382fc5a983dSmrg "probably wrong. Clamping to 256 MB.\n"); 383fc5a983dSmrg BAR1sizeKB = 256 * 1024; 384fc5a983dSmrg } 385fc5a983dSmrg 386fc5a983dSmrg /* Limit videoRam to the size of BAR1 */ 387fc5a983dSmrg if(pNv->videoRam <= 1024 || BAR1sizeKB == 0) { 388fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to determine the amount of " 389fc5a983dSmrg "available video memory\n"); 390fc5a983dSmrg goto fail; 391fc5a983dSmrg } 392fc5a983dSmrg pNv->videoRam -= 1024; 393fc5a983dSmrg if(pNv->videoRam > BAR1sizeKB) 394fc5a983dSmrg pNv->videoRam = BAR1sizeKB; 395fc5a983dSmrg 396fc5a983dSmrg pScrn->videoRam = pNv->videoRam; 397fc5a983dSmrg 398fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Total video RAM: %.1f MB\n", 399fc5a983dSmrg pNv->RamAmountKBytes / 1024.0); 400fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, " BAR1 size: %.1f MB\n", 401fc5a983dSmrg BAR1sizeKB / 1024.0); 402fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, " Mapped memory: %.1f MB\n", 403fc5a983dSmrg pScrn->videoRam / 1024.0); 404fc5a983dSmrg 405fc5a983dSmrg#if XSERVER_LIBPCIACCESS 406fc5a983dSmrg err = pci_device_map_range(pPci, pPci->regions[1].base_addr, 407fc5a983dSmrg pScrn->videoRam * 1024, 408fc5a983dSmrg PCI_DEV_MAP_FLAG_WRITABLE | 409fc5a983dSmrg PCI_DEV_MAP_FLAG_WRITE_COMBINE, 410fc5a983dSmrg &p); 411fc5a983dSmrg if(err) { 412fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 413fc5a983dSmrg "Failed to map framebuffer: %s\n", strerror(err)); 414fc5a983dSmrg goto fail; 415fc5a983dSmrg } 416fc5a983dSmrg pNv->mem = p; 417fc5a983dSmrg#else 418fc5a983dSmrg pNv->mem = xf86MapPciMem(pScrn->scrnIndex, 419fc5a983dSmrg VIDMEM_MMIO | VIDMEM_READSIDEEFFECT, 420fc5a983dSmrg pcitag, pPci->memBase[1], pScrn->videoRam * 1024); 421fc5a983dSmrg#endif 422fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Linear framebuffer mapped at %p\n", 423fc5a983dSmrg (void*)pNv->mem); 424fc5a983dSmrg 425fc5a983dSmrg pNv->table1 = (unsigned const char*)&pNv->reg[0x00800000/4]; 426fc5a983dSmrg tmp = pNv->reg[0x00619F04/4] >> 8; 427fc5a983dSmrg if(tmp) 428fc5a983dSmrg pNv->table1 -= ((pNv->RamAmountKBytes << 10) - (tmp << 16)); 429fc5a983dSmrg else 430fc5a983dSmrg pNv->table1 -= 0x10000; 431fc5a983dSmrg 432fc5a983dSmrg xf86CrtcConfigInit(pScrn, &randr12_screen_funcs); 433fc5a983dSmrg xf86CrtcSetSizeRange(pScrn, 320, 200, 8192, 8192); 434fc5a983dSmrg 435fc5a983dSmrg if(!xf86LoadSubModule(pScrn, "i2c")) goto fail; 436fc5a983dSmrg if(!xf86LoadSubModule(pScrn, "ddc")) goto fail; 437fc5a983dSmrg xf86LoaderReqSymLists(i2cSymbols, ddcSymbols, NULL); 438fc5a983dSmrg 439fc5a983dSmrg if(!G80DispPreInit(pScrn)) goto fail; 440fc5a983dSmrg /* Read the DDC routing table and create outputs */ 441fc5a983dSmrg if(!G80CreateOutputs(pScrn)) goto fail; 442fc5a983dSmrg /* Create the crtcs */ 443fc5a983dSmrg G80DispCreateCrtcs(pScrn); 444fc5a983dSmrg 445fc5a983dSmrg /* We can grow the desktop if XAA is disabled */ 446fc5a983dSmrg if(!xf86InitialConfiguration(pScrn, pNv->NoAccel || pNv->AccelMethod == EXA)) { 447fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 448fc5a983dSmrg "No valid initial configuration found\n"); 449fc5a983dSmrg goto fail; 450fc5a983dSmrg } 451fc5a983dSmrg pScrn->displayWidth = (pScrn->virtualX + 255) & ~255; 452fc5a983dSmrg 453fc5a983dSmrg if(!xf86RandR12PreInit(pScrn)) { 454fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n"); 455fc5a983dSmrg goto fail; 456fc5a983dSmrg } 457fc5a983dSmrg if(!pScrn->modes) { 458fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes\n"); 459fc5a983dSmrg goto fail; 460fc5a983dSmrg } 461fc5a983dSmrg 462fc5a983dSmrg pScrn->currentMode = pScrn->modes; 463fc5a983dSmrg xf86PrintModes(pScrn); 464fc5a983dSmrg xf86SetDpi(pScrn, 0, 0); 465fc5a983dSmrg 466fc5a983dSmrg /* Load fb */ 467fc5a983dSmrg if(!xf86LoadSubModule(pScrn, "fb")) goto fail; 468fc5a983dSmrg xf86LoaderReqSymLists(fbSymbols, NULL); 469fc5a983dSmrg 470fc5a983dSmrg if(!pNv->NoAccel) { 471fc5a983dSmrg switch(pNv->AccelMethod) { 472fc5a983dSmrg case XAA: 473fc5a983dSmrg if(!xf86LoadSubModule(pScrn, "xaa")) goto fail; 474fc5a983dSmrg xf86LoaderReqSymLists(xaaSymbols, NULL); 475fc5a983dSmrg break; 476fc5a983dSmrg case EXA: 477fc5a983dSmrg if(!xf86LoadSubModule(pScrn, "exa")) goto fail; 478fc5a983dSmrg xf86LoaderReqSymLists(exaSymbols, NULL); 479fc5a983dSmrg break; 480fc5a983dSmrg } 481fc5a983dSmrg } 482fc5a983dSmrg 483fc5a983dSmrg /* Load ramdac if needed */ 484fc5a983dSmrg if(pNv->HWCursor) { 485fc5a983dSmrg if(!xf86LoadSubModule(pScrn, "ramdac")) { 486fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to load ramdac. " 487fc5a983dSmrg "Falling back to software cursor.\n"); 488fc5a983dSmrg pNv->HWCursor = FALSE; 489fc5a983dSmrg } else { 490fc5a983dSmrg xf86LoaderReqSymLists(ramdacSymbols, NULL); 491fc5a983dSmrg } 492fc5a983dSmrg } 493fc5a983dSmrg 494fc5a983dSmrg return TRUE; 495fc5a983dSmrg 496fc5a983dSmrgfail: 497fc5a983dSmrg if(pNv->int10) xf86FreeInt10(pNv->int10); 498fc5a983dSmrg G80FreeRec(pScrn); 499fc5a983dSmrg return FALSE; 500fc5a983dSmrg} 501fc5a983dSmrg 502fc5a983dSmrg/* 503fc5a983dSmrg * Initialize the display and set the current mode. 504fc5a983dSmrg */ 505fc5a983dSmrgstatic Bool 506fc5a983dSmrgAcquireDisplay(ScrnInfoPtr pScrn) 507fc5a983dSmrg{ 508fc5a983dSmrg if(!G80DispInit(pScrn)) 509fc5a983dSmrg return FALSE; 510fc5a983dSmrg if(!G80CursorAcquire(pScrn)) 511fc5a983dSmrg return FALSE; 512fc5a983dSmrg xf86SetDesiredModes(pScrn); 513fc5a983dSmrg 514fc5a983dSmrg return TRUE; 515fc5a983dSmrg} 516fc5a983dSmrg 517fc5a983dSmrg/* 518fc5a983dSmrg * Tear down the display and restore the console mode. 519fc5a983dSmrg */ 520fc5a983dSmrgstatic Bool 521fc5a983dSmrgReleaseDisplay(ScrnInfoPtr pScrn) 522fc5a983dSmrg{ 523fc5a983dSmrg G80Ptr pNv = G80PTR(pScrn); 524fc5a983dSmrg 525fc5a983dSmrg G80CursorRelease(pScrn); 526fc5a983dSmrg G80DispShutdown(pScrn); 527fc5a983dSmrg 528fc5a983dSmrg if(pNv->int10 && pNv->int10Mode) { 529fc5a983dSmrg xf86Int10InfoPtr int10 = pNv->int10; 530fc5a983dSmrg 531fc5a983dSmrg /* Use int10 to restore the console mode */ 532fc5a983dSmrg int10->num = 0x10; 533fc5a983dSmrg int10->ax = 0x4f02; 534fc5a983dSmrg int10->bx = pNv->int10Mode | 0x8000; 535fc5a983dSmrg int10->cx = int10->dx = 0; 536fc5a983dSmrg xf86ExecX86int10(int10); 537fc5a983dSmrg } 538fc5a983dSmrg 539fc5a983dSmrg return TRUE; 540fc5a983dSmrg} 541fc5a983dSmrg 542fc5a983dSmrgstatic Bool 543fc5a983dSmrgG80CloseScreen(int scrnIndex, ScreenPtr pScreen) 544fc5a983dSmrg{ 545fc5a983dSmrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 546fc5a983dSmrg G80Ptr pNv = G80PTR(pScrn); 547fc5a983dSmrg 548fc5a983dSmrg if(pScrn->vtSema) 549fc5a983dSmrg ReleaseDisplay(pScrn); 550fc5a983dSmrg 551fc5a983dSmrg if(pNv->xaa) 552fc5a983dSmrg XAADestroyInfoRec(pNv->xaa); 553fc5a983dSmrg if(pNv->exa) { 554fc5a983dSmrg if(pNv->exaScreenArea) { 555fc5a983dSmrg exaOffscreenFree(pScreen, pNv->exaScreenArea); 556fc5a983dSmrg pNv->exaScreenArea = NULL; 557fc5a983dSmrg } 558fc5a983dSmrg exaDriverFini(pScrn->pScreen); 559fc5a983dSmrg } 560fc5a983dSmrg xf86_cursors_fini(pScreen); 561fc5a983dSmrg 562fc5a983dSmrg if(xf86ServerIsExiting()) { 563fc5a983dSmrg if(pNv->int10) xf86FreeInt10(pNv->int10); 564fc5a983dSmrg#if XSERVER_LIBPCIACCESS 565fc5a983dSmrg pci_device_unmap_range(pNv->pPci, pNv->mem, pNv->videoRam * 1024); 566fc5a983dSmrg pci_device_unmap_range(pNv->pPci, (void*)pNv->reg, G80_REG_SIZE); 567fc5a983dSmrg#else 568fc5a983dSmrg xf86UnMapVidMem(pScrn->scrnIndex, pNv->mem, pNv->videoRam * 1024); 569fc5a983dSmrg xf86UnMapVidMem(pScrn->scrnIndex, (void*)pNv->reg, G80_REG_SIZE); 570fc5a983dSmrg#endif 571fc5a983dSmrg pNv->reg = NULL; 572fc5a983dSmrg pNv->mem = NULL; 573fc5a983dSmrg } 574fc5a983dSmrg 575fc5a983dSmrg pScrn->vtSema = FALSE; 576fc5a983dSmrg pScreen->CloseScreen = pNv->CloseScreen; 577fc5a983dSmrg pScreen->BlockHandler = pNv->BlockHandler; 578fc5a983dSmrg return (*pScreen->CloseScreen)(scrnIndex, pScreen); 579fc5a983dSmrg} 580fc5a983dSmrg 581fc5a983dSmrgstatic void 582fc5a983dSmrgG80BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask) 583fc5a983dSmrg{ 584fc5a983dSmrg ScreenPtr pScreen = screenInfo.screens[i]; 585fc5a983dSmrg ScrnInfoPtr pScrnInfo = xf86Screens[i]; 586fc5a983dSmrg G80Ptr pNv = G80PTR(pScrnInfo); 587fc5a983dSmrg 588fc5a983dSmrg if(pNv->DMAKickoffCallback) 589fc5a983dSmrg (*pNv->DMAKickoffCallback)(pScrnInfo); 590fc5a983dSmrg 591fc5a983dSmrg G80OutputResetCachedStatus(pScrnInfo); 592fc5a983dSmrg 593fc5a983dSmrg pScreen->BlockHandler = pNv->BlockHandler; 594fc5a983dSmrg (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); 595fc5a983dSmrg pScreen->BlockHandler = G80BlockHandler; 596fc5a983dSmrg} 597fc5a983dSmrg 598fc5a983dSmrgstatic Bool 599fc5a983dSmrgG80SaveScreen(ScreenPtr pScreen, int mode) 600fc5a983dSmrg{ 601fc5a983dSmrg return FALSE; 602fc5a983dSmrg} 603fc5a983dSmrg 604fc5a983dSmrgstatic void 605fc5a983dSmrgG80InitHW(ScrnInfoPtr pScrn) 606fc5a983dSmrg{ 607fc5a983dSmrg G80Ptr pNv = G80PTR(pScrn); 608fc5a983dSmrg CARD32 bar0_pramin = 0; 609fc5a983dSmrg const int pitch = pScrn->displayWidth * (pScrn->bitsPerPixel / 8); 610fc5a983dSmrg volatile CARD32 *p; 611fc5a983dSmrg 612fc5a983dSmrg /* Clear registers */ 613fc5a983dSmrg for(p = &pNv->reg[0x00700000/4]; p < (const CARD32*)pNv->table1; p++) 614fc5a983dSmrg *p = 0; 615fc5a983dSmrg 616fc5a983dSmrg bar0_pramin = pNv->reg[0x00001700/4] << 16; 617fc5a983dSmrg 618fc5a983dSmrg pNv->reg[0x00000200/4] = 0xffff00ff; 619fc5a983dSmrg pNv->reg[0x00000200/4] = 0xffffffff; 620fc5a983dSmrg pNv->reg[0x00002100/4] = 0xffffffff; 621fc5a983dSmrg pNv->reg[0x0000250c/4] = 0x6f3cfc34; 622fc5a983dSmrg pNv->reg[0x00400804/4] = 0xc0000000; 623fc5a983dSmrg pNv->reg[0x00406800/4] = 0xc0000000; 624fc5a983dSmrg pNv->reg[0x00400c04/4] = 0xc0000000; 625fc5a983dSmrg pNv->reg[0x00401800/4] = 0xc0000000; 626fc5a983dSmrg pNv->reg[0x00405018/4] = 0xc0000000; 627fc5a983dSmrg pNv->reg[0x00402000/4] = 0xc0000000; 628fc5a983dSmrg pNv->reg[0x00400108/4] = 0xffffffff; 629fc5a983dSmrg pNv->reg[0x00400100/4] = 0xffffffff; 630fc5a983dSmrg 631fc5a983dSmrg if(pNv->architecture != 0x50) { 632fc5a983dSmrg pNv->reg[0x00700000/4] = 0x00000001; 633fc5a983dSmrg pNv->reg[0x00700004/4] = bar0_pramin + 0x00200; 634fc5a983dSmrg pNv->reg[0x00700020/4] = 0x00190002; 635fc5a983dSmrg pNv->reg[0x00700024/4] = bar0_pramin + 0x7ffff; 636fc5a983dSmrg pNv->reg[0x00700028/4] = bar0_pramin + 0x20000; 637fc5a983dSmrg pNv->reg[0x00700034/4] = 0x00010000; 638fc5a983dSmrg } else { 639fc5a983dSmrg pNv->reg[0x00700200/4] = 0x00190002; 640fc5a983dSmrg pNv->reg[0x00700204/4] = bar0_pramin + 0x7ffff; 641fc5a983dSmrg pNv->reg[0x00700208/4] = bar0_pramin + 0x20000; 642fc5a983dSmrg pNv->reg[0x00700214/4] = 0x00010000; 643fc5a983dSmrg } 644fc5a983dSmrg 645fc5a983dSmrg pNv->reg[0x00710004/4] = 0x00100642; 646fc5a983dSmrg pNv->reg[0x00710008/4] = 0x80000011; 647fc5a983dSmrg pNv->reg[0x0071000c/4] = 0x00000644; 648fc5a983dSmrg pNv->reg[0x00710010/4] = 0x80000012; 649fc5a983dSmrg pNv->reg[0x00710014/4] = 0x00100646; 650fc5a983dSmrg pNv->reg[0x00710018/4] = 0x80000013; 651fc5a983dSmrg pNv->reg[0x0071001c/4] = 0x00100648; 652fc5a983dSmrg pNv->reg[0x00710020/4] = 0x80000014; 653fc5a983dSmrg pNv->reg[0x00710024/4] = 0x0000064a; 654fc5a983dSmrg pNv->reg[0x00706420/4] = 0x00190030; 655fc5a983dSmrg pNv->reg[0x00706434/4] = 0x00010000; 656fc5a983dSmrg pNv->reg[0x00706440/4] = 0x0019003d; 657fc5a983dSmrg pNv->reg[0x00706444/4] = (pNv->videoRam << 10) - 0x4001; 658fc5a983dSmrg pNv->reg[0x00706448/4] = (pNv->videoRam << 10) - G80_RESERVED_VIDMEM; 659fc5a983dSmrg pNv->reg[0x00706454/4] = 0x00010000; 660fc5a983dSmrg pNv->reg[0x00706460/4] = 0x0000502d; 661fc5a983dSmrg pNv->reg[0x00706474/4] = 0x00010000; 662fc5a983dSmrg pNv->reg[0x00706480/4] = 0x0019003d; 663fc5a983dSmrg pNv->reg[0x00706484/4] = (pNv->videoRam << 10) - G80_RESERVED_VIDMEM; 664fc5a983dSmrg pNv->reg[0x00706494/4] = 0x00010000; 665fc5a983dSmrg pNv->reg[0x007064a0/4] = 0x0019003d; 666fc5a983dSmrg pNv->reg[0x007064a4/4] = bar0_pramin + 0x1100f; 667fc5a983dSmrg pNv->reg[0x007064a8/4] = bar0_pramin + 0x11000; 668fc5a983dSmrg pNv->reg[0x007064b4/4] = 0x00010000; 669fc5a983dSmrg 670fc5a983dSmrg if(pNv->architecture != 0x50) { 671fc5a983dSmrg pNv->reg[0x00002604/4] = 0x80000002 | (bar0_pramin >> 8); 672fc5a983dSmrg } else { 673fc5a983dSmrg pNv->reg[0x00002604/4] = 0x80000000 | (bar0_pramin >> 12); 674fc5a983dSmrg } 675fc5a983dSmrg 676fc5a983dSmrg pNv->reg[0x00003224/4] = 0x000f0078; 677fc5a983dSmrg pNv->reg[0x0000322c/4] = 0x00000644; 678fc5a983dSmrg pNv->reg[0x00003234/4] = G80_RESERVED_VIDMEM - 0x5001; 679fc5a983dSmrg pNv->reg[0x00003254/4] = 0x00000001; 680fc5a983dSmrg pNv->reg[0x00002210/4] = 0x1c001000; 681fc5a983dSmrg 682fc5a983dSmrg if(pNv->architecture != 0x50) { 683fc5a983dSmrg pNv->reg[0x0000340c/4] = (bar0_pramin + 0x1000) >> 10; 684fc5a983dSmrg pNv->reg[0x00003410/4] = (bar0_pramin >> 12); 685fc5a983dSmrg } 686fc5a983dSmrg 687fc5a983dSmrg pNv->reg[0x00400824/4] = 0x00004000; 688fc5a983dSmrg pNv->reg[0x00400784/4] = 0x80000000 | (bar0_pramin >> 12); 689fc5a983dSmrg pNv->reg[0x00400320/4] = 0x00000004; 690fc5a983dSmrg pNv->reg[0x0040032C/4] = 0x80000000 | (bar0_pramin >> 12); 691fc5a983dSmrg pNv->reg[0x00400500/4] = 0x00010001; 692fc5a983dSmrg pNv->reg[0x00003250/4] = 0x00000001; 693fc5a983dSmrg pNv->reg[0x00003200/4] = 0x00000001; 694fc5a983dSmrg pNv->reg[0x00003220/4] = 0x00001001; 695fc5a983dSmrg pNv->reg[0x00003204/4] = 0x00010001; 696fc5a983dSmrg 697fc5a983dSmrg pNv->dmaBase = (CARD32*)(pNv->mem + (pNv->videoRam << 10) - 698fc5a983dSmrg G80_RESERVED_VIDMEM); 699fc5a983dSmrg memset(pNv->dmaBase, 0, SKIPS*4); 700fc5a983dSmrg 701fc5a983dSmrg pNv->dmaPut = 0; 702fc5a983dSmrg pNv->dmaCurrent = SKIPS; 703fc5a983dSmrg pNv->dmaMax = (G80_RESERVED_VIDMEM - 0x5000) / 4 - 2; 704fc5a983dSmrg pNv->dmaFree = pNv->dmaMax - pNv->dmaCurrent; 705fc5a983dSmrg 706fc5a983dSmrg G80DmaStart(pNv, 0, 1); 707fc5a983dSmrg G80DmaNext (pNv, 0x80000012); 708fc5a983dSmrg G80DmaStart(pNv, 0x180, 3); 709fc5a983dSmrg G80DmaNext (pNv, 0x80000014); 710fc5a983dSmrg G80DmaNext (pNv, 0x80000013); 711fc5a983dSmrg G80DmaNext (pNv, 0x80000013); 712fc5a983dSmrg G80DmaStart(pNv, 0x200, 2); 713fc5a983dSmrg switch(pScrn->depth) { 714fc5a983dSmrg case 8: G80DmaNext (pNv, 0x000000f3); break; 715fc5a983dSmrg case 15: G80DmaNext (pNv, 0x000000f8); break; 716fc5a983dSmrg case 16: G80DmaNext (pNv, 0x000000e8); break; 717fc5a983dSmrg case 24: G80DmaNext (pNv, 0x000000e6); break; 718fc5a983dSmrg } 719fc5a983dSmrg G80DmaNext (pNv, 0x00000001); 720fc5a983dSmrg G80DmaStart(pNv, 0x214, 5); 721fc5a983dSmrg G80DmaNext (pNv, pitch); 722fc5a983dSmrg G80DmaNext (pNv, pitch); 723fc5a983dSmrg G80DmaNext (pNv, pNv->offscreenHeight); 724fc5a983dSmrg G80DmaNext (pNv, 0x00000000); 725fc5a983dSmrg G80DmaNext (pNv, 0x00000000); 726fc5a983dSmrg G80DmaStart(pNv, 0x230, 2); 727fc5a983dSmrg switch(pScrn->depth) { 728fc5a983dSmrg case 8: G80DmaNext (pNv, 0x000000f3); break; 729fc5a983dSmrg case 15: G80DmaNext (pNv, 0x000000f8); break; 730fc5a983dSmrg case 16: G80DmaNext (pNv, 0x000000e8); break; 731fc5a983dSmrg case 24: G80DmaNext (pNv, 0x000000e6); break; 732fc5a983dSmrg } 733fc5a983dSmrg G80DmaNext (pNv, 0x00000001); 734fc5a983dSmrg G80DmaStart(pNv, 0x244, 5); 735fc5a983dSmrg G80DmaNext (pNv, pitch); 736fc5a983dSmrg G80DmaNext (pNv, pitch); 737fc5a983dSmrg G80DmaNext (pNv, pNv->offscreenHeight); 738fc5a983dSmrg G80DmaNext (pNv, 0x00000000); 739fc5a983dSmrg G80DmaNext (pNv, 0x00000000); 740fc5a983dSmrg G80DmaStart(pNv, 0x260, 1); 741fc5a983dSmrg G80DmaNext (pNv, 0x00000001); 742fc5a983dSmrg G80DmaStart(pNv, 0x290, 1); 743fc5a983dSmrg G80DmaNext (pNv, 1); 744fc5a983dSmrg G80DmaStart(pNv, 0x29c, 1); 745fc5a983dSmrg G80DmaNext (pNv, 0); 746fc5a983dSmrg G80DmaStart(pNv, 0x2e8, 2); 747fc5a983dSmrg switch(pScrn->depth) { 748fc5a983dSmrg case 8: G80DmaNext (pNv, 3); break; 749fc5a983dSmrg case 15: G80DmaNext (pNv, 1); break; 750fc5a983dSmrg case 16: G80DmaNext (pNv, 0); break; 751fc5a983dSmrg case 24: G80DmaNext (pNv, 2); break; 752fc5a983dSmrg } 753fc5a983dSmrg G80DmaNext (pNv, 1); 754fc5a983dSmrg G80DmaStart(pNv, 0x584, 1); 755fc5a983dSmrg switch(pScrn->depth) { 756fc5a983dSmrg case 8: G80DmaNext (pNv, 0xf3); break; 757fc5a983dSmrg case 15: G80DmaNext (pNv, 0xf8); break; 758fc5a983dSmrg case 16: G80DmaNext (pNv, 0xe8); break; 759fc5a983dSmrg case 24: G80DmaNext (pNv, 0xe6); break; 760fc5a983dSmrg } 761fc5a983dSmrg G80DmaStart(pNv, 0x58c, 1); 762fc5a983dSmrg G80DmaNext (pNv, 0x111); 763fc5a983dSmrg G80DmaStart(pNv, 0x804, 1); 764fc5a983dSmrg switch(pScrn->depth) { 765fc5a983dSmrg case 8: G80DmaNext (pNv, 0xf3); break; 766fc5a983dSmrg case 15: G80DmaNext (pNv, 0xf8); break; 767fc5a983dSmrg case 16: G80DmaNext (pNv, 0xe8); break; 768fc5a983dSmrg case 24: G80DmaNext (pNv, 0xe6); break; 769fc5a983dSmrg } 770fc5a983dSmrg 771fc5a983dSmrg pNv->currentRop = ~0; /* Set to something invalid */ 772fc5a983dSmrg} 773fc5a983dSmrg 774fc5a983dSmrg#define DEPTH_SHIFT(val, w) ((val << (8 - w)) | (val >> ((w << 1) - 8))) 775fc5a983dSmrg#define COLOR(c) (unsigned int)(0x3fff * ((c)/255.0)) 776fc5a983dSmrgstatic void 777fc5a983dSmrgG80LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, 778fc5a983dSmrg VisualPtr pVisual) 779fc5a983dSmrg{ 780fc5a983dSmrg G80Ptr pNv = G80PTR(pScrn); 781fc5a983dSmrg int i, index; 782fc5a983dSmrg volatile struct { 783fc5a983dSmrg unsigned short red, green, blue, unused; 784fc5a983dSmrg } *lut = (void*)&pNv->mem[pNv->videoRam * 1024 - 0x5000]; 785fc5a983dSmrg 786fc5a983dSmrg switch(pScrn->depth) { 787fc5a983dSmrg case 15: 788fc5a983dSmrg for(i = 0; i < numColors; i++) { 789fc5a983dSmrg index = indices[i]; 790fc5a983dSmrg lut[DEPTH_SHIFT(index, 5)].red = COLOR(colors[index].red); 791fc5a983dSmrg lut[DEPTH_SHIFT(index, 5)].green = COLOR(colors[index].green); 792fc5a983dSmrg lut[DEPTH_SHIFT(index, 5)].blue = COLOR(colors[index].blue); 793fc5a983dSmrg } 794fc5a983dSmrg break; 795fc5a983dSmrg case 16: 796fc5a983dSmrg for(i = 0; i < numColors; i++) { 797fc5a983dSmrg index = indices[i]; 798fc5a983dSmrg lut[DEPTH_SHIFT(index, 6)].green = COLOR(colors[index].green); 799fc5a983dSmrg if(index < 32) { 800fc5a983dSmrg lut[DEPTH_SHIFT(index, 5)].red = COLOR(colors[index].red); 801fc5a983dSmrg lut[DEPTH_SHIFT(index, 5)].blue = COLOR(colors[index].blue); 802fc5a983dSmrg } 803fc5a983dSmrg } 804fc5a983dSmrg break; 805fc5a983dSmrg default: 806fc5a983dSmrg for(i = 0; i < numColors; i++) { 807fc5a983dSmrg index = indices[i]; 808fc5a983dSmrg lut[index].red = COLOR(colors[index].red); 809fc5a983dSmrg lut[index].green = COLOR(colors[index].green); 810fc5a983dSmrg lut[index].blue = COLOR(colors[index].blue); 811fc5a983dSmrg } 812fc5a983dSmrg break; 813fc5a983dSmrg } 814fc5a983dSmrg} 815fc5a983dSmrg 816fc5a983dSmrgstatic Bool 817fc5a983dSmrgG80ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) 818fc5a983dSmrg{ 819fc5a983dSmrg ScrnInfoPtr pScrn; 820fc5a983dSmrg G80Ptr pNv; 821fc5a983dSmrg CARD32 pitch; 822fc5a983dSmrg int visualMask, i; 823fc5a983dSmrg BoxRec AvailFBArea; 824fc5a983dSmrg 825fc5a983dSmrg /* First get the ScrnInfoRec */ 826fc5a983dSmrg pScrn = xf86Screens[pScreen->myNum]; 827fc5a983dSmrg pNv = G80PTR(pScrn); 828fc5a983dSmrg 829fc5a983dSmrg pScrn->vtSema = TRUE; 830fc5a983dSmrg 831fc5a983dSmrg /* DIX visual init */ 832fc5a983dSmrg miClearVisualTypes(); 833fc5a983dSmrg visualMask = miGetDefaultVisualMask(pScrn->depth); 834fc5a983dSmrg if(!miSetVisualTypes(pScrn->depth, visualMask, 8, pScrn->defaultVisual)) 835fc5a983dSmrg return FALSE; 836fc5a983dSmrg if(!miSetPixmapDepths()) 837fc5a983dSmrg return FALSE; 838fc5a983dSmrg 839fc5a983dSmrg /* pad the screen pitch to 256 bytes */ 840fc5a983dSmrg pitch = pScrn->displayWidth * (pScrn->bitsPerPixel / 8); 841fc5a983dSmrg 842fc5a983dSmrg /* fb init */ 843fc5a983dSmrg if(!fbScreenInit(pScreen, pNv->mem, 844fc5a983dSmrg pScrn->virtualX, pScrn->virtualY, 845fc5a983dSmrg pScrn->xDpi, pScrn->yDpi, 846fc5a983dSmrg pScrn->displayWidth, pScrn->bitsPerPixel)) 847fc5a983dSmrg return FALSE; 848fc5a983dSmrg 849fc5a983dSmrg if(pScrn->bitsPerPixel > 8) { 850fc5a983dSmrg VisualPtr visual; 851fc5a983dSmrg 852fc5a983dSmrg /* Fixup RGB ordering */ 853fc5a983dSmrg visual = pScreen->visuals + pScreen->numVisuals; 854fc5a983dSmrg while(--visual >= pScreen->visuals) { 855fc5a983dSmrg if((visual->class | DynamicClass) == DirectColor) { 856fc5a983dSmrg visual->offsetRed = pScrn->offset.red; 857fc5a983dSmrg visual->offsetGreen = pScrn->offset.green; 858fc5a983dSmrg visual->offsetBlue = pScrn->offset.blue; 859fc5a983dSmrg visual->redMask = pScrn->mask.red; 860fc5a983dSmrg visual->greenMask = pScrn->mask.green; 861fc5a983dSmrg visual->blueMask = pScrn->mask.blue; 862fc5a983dSmrg } 863fc5a983dSmrg } 864fc5a983dSmrg } 865fc5a983dSmrg 866fc5a983dSmrg fbPictureInit(pScreen, 0, 0); 867fc5a983dSmrg 868fc5a983dSmrg xf86SetBlackWhitePixels(pScreen); 869fc5a983dSmrg 870fc5a983dSmrg pNv->offscreenHeight = ((pNv->videoRam << 10) - G80_RESERVED_VIDMEM) / pitch; 871fc5a983dSmrg if(pNv->offscreenHeight > 32767) pNv->offscreenHeight = 32767; 872fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 873fc5a983dSmrg "%.2f MB available for offscreen pixmaps\n", 874fc5a983dSmrg (pNv->offscreenHeight - pScrn->virtualY) * pitch / 1024.0 / 1024.0); 875fc5a983dSmrg 876fc5a983dSmrg AvailFBArea.x1 = 0; 877fc5a983dSmrg AvailFBArea.y1 = 0; 878fc5a983dSmrg AvailFBArea.x2 = pScrn->displayWidth; 879fc5a983dSmrg AvailFBArea.y2 = pNv->offscreenHeight; 880fc5a983dSmrg xf86InitFBManager(pScreen, &AvailFBArea); 881fc5a983dSmrg 882fc5a983dSmrg pNv->reg[0x00001708/4] = 0; 883fc5a983dSmrg for(i = 0; i < 8; i++) 884fc5a983dSmrg pNv->reg[0x00001900/4 + i] = 0; 885fc5a983dSmrg 886fc5a983dSmrg if(!pNv->NoAccel) { 887fc5a983dSmrg G80InitHW(pScrn); 888fc5a983dSmrg switch(pNv->AccelMethod) { 889fc5a983dSmrg case XAA: 890fc5a983dSmrg if(!G80XAAInit(pScreen)) { 891fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 892fc5a983dSmrg "XAA hardware acceleration initialization failed\n"); 893fc5a983dSmrg return FALSE; 894fc5a983dSmrg } 895fc5a983dSmrg break; 896fc5a983dSmrg case EXA: 897fc5a983dSmrg if(!G80ExaInit(pScreen, pScrn)) { 898fc5a983dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 899fc5a983dSmrg "EXA hardware acceleration initialization failed\n"); 900fc5a983dSmrg return FALSE; 901fc5a983dSmrg } 902fc5a983dSmrg break; 903fc5a983dSmrg } 904fc5a983dSmrg } 905fc5a983dSmrg 906fc5a983dSmrg miInitializeBackingStore(pScreen); 907fc5a983dSmrg xf86SetBackingStore(pScreen); 908fc5a983dSmrg xf86SetSilkenMouse(pScreen); 909fc5a983dSmrg 910fc5a983dSmrg /* Initialize software cursor. 911fc5a983dSmrg Must precede creation of the default colormap */ 912fc5a983dSmrg miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 913fc5a983dSmrg 914fc5a983dSmrg /* Initialize default colormap */ 915fc5a983dSmrg if(!miCreateDefColormap(pScreen)) 916fc5a983dSmrg return FALSE; 917fc5a983dSmrg 918fc5a983dSmrg /* Initialize colormap layer. 919fc5a983dSmrg Must follow initialization of the default colormap */ 920fc5a983dSmrg if(!xf86HandleColormaps(pScreen, 256, 8, G80LoadPalette, NULL, 921fc5a983dSmrg CMAP_PALETTED_TRUECOLOR)) 922fc5a983dSmrg return FALSE; 923fc5a983dSmrg 924fc5a983dSmrg xf86DPMSInit(pScreen, xf86DPMSSet, 0); 925fc5a983dSmrg 926fc5a983dSmrg /* Clear the screen */ 927fc5a983dSmrg if(pNv->xaa) { 928fc5a983dSmrg /* Use the acceleration engine */ 929fc5a983dSmrg pNv->xaa->SetupForSolidFill(pScrn, 0, GXcopy, ~0); 930fc5a983dSmrg pNv->xaa->SubsequentSolidFillRect(pScrn, 931fc5a983dSmrg 0, 0, pScrn->displayWidth, pNv->offscreenHeight); 932fc5a983dSmrg G80DmaKickoff(pNv); 933fc5a983dSmrg } else { 934fc5a983dSmrg /* Use a slow software clear path */ 935fc5a983dSmrg memset(pNv->mem, 0, pitch * pNv->offscreenHeight); 936fc5a983dSmrg } 937fc5a983dSmrg 938fc5a983dSmrg /* Initialize the display */ 939fc5a983dSmrg if(!AcquireDisplay(pScrn)) 940fc5a983dSmrg return FALSE; 941fc5a983dSmrg 942f3561b8bSmrg /* Initialize hardware cursor. Must follow software cursor initialization. */ 943f3561b8bSmrg if(pNv->HWCursor && !G80CursorInit(pScreen)) { 944f3561b8bSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 945f3561b8bSmrg "Hardware cursor initialization failed\n"); 946f3561b8bSmrg pNv->HWCursor = FALSE; 947f3561b8bSmrg } 948f3561b8bSmrg 949fc5a983dSmrg pScreen->SaveScreen = G80SaveScreen; 950fc5a983dSmrg 951fc5a983dSmrg pNv->CloseScreen = pScreen->CloseScreen; 952fc5a983dSmrg pScreen->CloseScreen = G80CloseScreen; 953fc5a983dSmrg 954fc5a983dSmrg pNv->BlockHandler = pScreen->BlockHandler; 955fc5a983dSmrg pScreen->BlockHandler = G80BlockHandler; 956fc5a983dSmrg 957fc5a983dSmrg if(!xf86CrtcScreenInit(pScreen)) 958fc5a983dSmrg return FALSE; 959fc5a983dSmrg 960fc5a983dSmrg return TRUE; 961fc5a983dSmrg} 962fc5a983dSmrg 963fc5a983dSmrgstatic void 964fc5a983dSmrgG80FreeScreen(int scrnIndex, int flags) 965fc5a983dSmrg{ 966fc5a983dSmrg G80FreeRec(xf86Screens[scrnIndex]); 967fc5a983dSmrg} 968fc5a983dSmrg 969fc5a983dSmrgstatic Bool 970fc5a983dSmrgG80SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) 971fc5a983dSmrg{ 972fc5a983dSmrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 973fc5a983dSmrg return xf86SetSingleMode(pScrn, mode, RR_Rotate_0); 974fc5a983dSmrg} 975fc5a983dSmrg 976fc5a983dSmrgstatic void 977fc5a983dSmrgG80AdjustFrame(int scrnIndex, int x, int y, int flags) 978fc5a983dSmrg{ 979fc5a983dSmrg} 980fc5a983dSmrg 981fc5a983dSmrgstatic Bool 982fc5a983dSmrgG80EnterVT(int scrnIndex, int flags) 983fc5a983dSmrg{ 984fc5a983dSmrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 985fc5a983dSmrg G80Ptr pNv = G80PTR(pScrn); 986fc5a983dSmrg 987fc5a983dSmrg /* Reinit the hardware */ 988fc5a983dSmrg if(pNv->xaa) 989fc5a983dSmrg G80InitHW(pScrn); 990fc5a983dSmrg 991fc5a983dSmrg if(!AcquireDisplay(pScrn)) 992fc5a983dSmrg return FALSE; 993fc5a983dSmrg 994fc5a983dSmrg return TRUE; 995fc5a983dSmrg} 996fc5a983dSmrg 997fc5a983dSmrgstatic void 998fc5a983dSmrgG80LeaveVT(int scrnIndex, int flags) 999fc5a983dSmrg{ 1000fc5a983dSmrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1001fc5a983dSmrg 1002fc5a983dSmrg ReleaseDisplay(pScrn); 1003fc5a983dSmrg} 1004fc5a983dSmrg 1005fc5a983dSmrgBool G80GetScrnInfoRec(PciChipsets *chips, int chip) 1006fc5a983dSmrg{ 1007fc5a983dSmrg ScrnInfoPtr pScrn; 1008fc5a983dSmrg 1009fc5a983dSmrg pScrn = xf86ConfigPciEntity(NULL, 0, chip, 1010fc5a983dSmrg chips, NULL, NULL, NULL, 1011fc5a983dSmrg NULL, NULL); 1012fc5a983dSmrg 1013fc5a983dSmrg if(!pScrn) return FALSE; 1014fc5a983dSmrg 1015fc5a983dSmrg pScrn->driverVersion = NV_VERSION; 1016fc5a983dSmrg pScrn->driverName = NV_DRIVER_NAME; 1017fc5a983dSmrg pScrn->name = NV_NAME; 1018fc5a983dSmrg 1019fc5a983dSmrg pScrn->PreInit = G80PreInit; 1020fc5a983dSmrg pScrn->ScreenInit = G80ScreenInit; 1021fc5a983dSmrg pScrn->SwitchMode = G80SwitchMode; 1022fc5a983dSmrg pScrn->AdjustFrame = G80AdjustFrame; 1023fc5a983dSmrg pScrn->EnterVT = G80EnterVT; 1024fc5a983dSmrg pScrn->LeaveVT = G80LeaveVT; 1025fc5a983dSmrg pScrn->FreeScreen = G80FreeScreen; 1026fc5a983dSmrg // pScrn->ValidMode = G80ValidMode; 1027fc5a983dSmrg 1028fc5a983dSmrg return TRUE; 1029fc5a983dSmrg} 1030