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