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