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