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