i810_driver.c revision 03b705cf
1 2/************************************************************************** 3 4Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 5All Rights Reserved. 6 7Permission is hereby granted, free of charge, to any person obtaining a 8copy of this software and associated documentation files (the 9"Software"), to deal in the Software without restriction, including 10without limitation the rights to use, copy, modify, merge, publish, 11distribute, sub license, and/or sell copies of the Software, and to 12permit persons to whom the Software is furnished to do so, subject to 13the following conditions: 14 15The above copyright notice and this permission notice (including the 16next paragraph) shall be included in all copies or substantial portions 17of the Software. 18 19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 23ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 27**************************************************************************/ 28 29#ifdef HAVE_CONFIG_H 30#include "config.h" 31#endif 32 33/* 34 * Authors: 35 * Keith Whitwell <keith@tungstengraphics.com> 36 * 37 * Add ARGB HW cursor support: 38 * Alan Hourihane <alanh@tungstengraphics.com> 39 * 40 */ 41 42/* 43 * This server does not support these XFree86 4.0 features yet 44 * shadowFb (if requested or acceleration is off) 45 * Overlay planes 46 * DGA 47 */ 48 49#include <math.h> 50#include <string.h> 51#include <unistd.h> 52 53/* 54 * These are X and server generic header files. 55 */ 56#include "xf86.h" 57#include "xf86_OSproc.h" 58#include "xf86cmap.h" 59 60#include "compiler.h" 61#include "vgaHW.h" 62#include "mipointer.h" 63#include "micmap.h" 64 65#include "fb.h" 66#include "miscstruct.h" 67#include "xf86xv.h" 68#include <X11/extensions/Xv.h> 69#include "vbe.h" 70#include "xf86fbman.h" 71 72#include "i810.h" 73 74#ifdef HAVE_DRI1 75#include "dri.h" 76#endif 77 78#include "../legacy.h" 79 80static Bool I810PreInit(ScrnInfoPtr pScrn, int flags); 81static Bool I810ScreenInit(SCREEN_INIT_ARGS_DECL); 82static Bool I810EnterVT(VT_FUNC_ARGS_DECL); 83static void I810LeaveVT(VT_FUNC_ARGS_DECL); 84static Bool I810CloseScreen(CLOSE_SCREEN_ARGS_DECL); 85static Bool I810SaveScreen(ScreenPtr pScreen, Bool unblank); 86static void I810FreeScreen(FREE_SCREEN_ARGS_DECL); 87static void I810DisplayPowerManagementSet(ScrnInfoPtr pScrn, 88 int PowerManagermentMode, 89 int flags); 90static ModeStatus I810ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, 91 Bool verbose, int flags); 92 93typedef enum { 94 OPTION_NOACCEL, 95 OPTION_SW_CURSOR, 96 OPTION_COLOR_KEY, 97 OPTION_CACHE_LINES, 98 OPTION_DAC_6BIT, 99 OPTION_DRI, 100 OPTION_NO_DDC, 101 OPTION_SHOW_CACHE, 102 OPTION_XVMC_SURFACES, 103 OPTION_PAGEFLIP 104} I810Opts; 105 106static const OptionInfoRec I810Options[] = { 107 {OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE}, 108 {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, 109 {OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE}, 110 {OPTION_CACHE_LINES, "CacheLines", OPTV_INTEGER, {0}, FALSE}, 111 {OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE}, 112 {OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE}, 113 {OPTION_NO_DDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE}, 114 {OPTION_SHOW_CACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE}, 115 {OPTION_XVMC_SURFACES, "XvMCSurfaces", OPTV_INTEGER, {0}, FALSE}, 116 {OPTION_PAGEFLIP, "PageFlip", OPTV_BOOLEAN, {0}, FALSE}, 117 {-1, NULL, OPTV_NONE, {0}, FALSE} 118}; 119/* *INDENT-ON* */ 120 121#ifndef I810_DEBUG 122int I810_DEBUG = (0 123/* | DEBUG_ALWAYS_SYNC */ 124/* | DEBUG_VERBOSE_ACCEL */ 125/* | DEBUG_VERBOSE_SYNC */ 126/* | DEBUG_VERBOSE_VGA */ 127/* | DEBUG_VERBOSE_RING */ 128/* | DEBUG_VERBOSE_OUTREG */ 129/* | DEBUG_VERBOSE_MEMORY */ 130/* | DEBUG_VERBOSE_CURSOR */ 131 ); 132#endif 133 134#ifdef HAVE_DRI1 135static int i810_pitches[] = { 136 512, 137 1024, 138 2048, 139 4096, 140 0 141}; 142#endif 143 144/* 145 * I810GetRec and I810FreeRec -- 146 * 147 * Private data for the driver is stored in the screen structure. 148 * These two functions create and destroy that private data. 149 * 150 */ 151static Bool 152I810GetRec(ScrnInfoPtr scrn) 153{ 154 if (((uintptr_t)scrn->driverPrivate & 1) == 0) 155 return TRUE; 156 157 scrn->driverPrivate = xnfcalloc(sizeof(I810Rec), 1); 158 return TRUE; 159} 160 161static void 162I810FreeRec(ScrnInfoPtr scrn) 163{ 164 if (!scrn) 165 return; 166 if (!scrn->driverPrivate) 167 return; 168 free(scrn->driverPrivate); 169 scrn->driverPrivate = NULL; 170} 171 172struct pci_device * 173intel_host_bridge (void) 174{ 175 static const struct pci_slot_match bridge_match = { 176 0, 0, 0, PCI_MATCH_ANY, 0 177 }; 178 struct pci_device_iterator *slot_iterator; 179 struct pci_device *bridge; 180 181 slot_iterator = pci_slot_match_iterator_create (&bridge_match); 182 bridge = pci_device_next (slot_iterator); 183 pci_iterator_destroy (slot_iterator); 184 return bridge; 185} 186 187static void 188I810ProbeDDC(ScrnInfoPtr scrn, int index) 189{ 190 vbeInfoPtr pVbe; 191 192 if (xf86LoadSubModule(scrn, "vbe")) { 193 pVbe = VBEInit(NULL, index); 194 ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 195 vbeFree(pVbe); 196 } 197} 198 199static xf86MonPtr 200I810DoDDC(ScrnInfoPtr scrn, int index) 201{ 202 vbeInfoPtr pVbe; 203 xf86MonPtr MonInfo = NULL; 204 I810Ptr pI810 = I810PTR(scrn); 205 206 /* Honour Option "noDDC" */ 207 if (xf86ReturnOptValBool(pI810->Options, OPTION_NO_DDC, FALSE)) { 208 return MonInfo; 209 } 210 211 if (xf86LoadSubModule(scrn, "vbe") && (pVbe = VBEInit(NULL, index))) { 212 MonInfo = vbeDoEDID(pVbe, NULL); 213 xf86PrintEDID(MonInfo); 214 xf86SetDDCproperties(scrn, MonInfo); 215 vbeFree(pVbe); 216 } else { 217 xf86DrvMsg(scrn->scrnIndex, X_INFO, 218 "this driver cannot do DDC without VBE\n"); 219 } 220 221 return MonInfo; 222} 223 224/* 225 * I810PreInit -- 226 * 227 * Do initial setup of the board before we know what resolution we will 228 * be running at. 229 * 230 */ 231static Bool 232I810PreInit(ScrnInfoPtr scrn, int flags) 233{ 234 I810Ptr pI810; 235 ClockRangePtr clockRanges; 236 int i; 237 MessageType from; 238 int flags24; 239 rgb defaultWeight = { 0, 0, 0 }; 240 int mem; 241 Bool enable; 242 243 if (scrn->numEntities != 1) 244 return FALSE; 245 246 /* Allocate driverPrivate */ 247 if (!I810GetRec(scrn)) 248 return FALSE; 249 250 pI810 = I810PTR(scrn); 251 252 pI810->pEnt = xf86GetEntityInfo(scrn->entityList[0]); 253 if (pI810->pEnt == NULL || pI810->pEnt->location.type != BUS_PCI) 254 return FALSE; 255 256 if (flags & PROBE_DETECT) { 257 I810ProbeDDC(scrn, pI810->pEnt->index); 258 return TRUE; 259 } 260 261 /* The vgahw module should be loaded here when needed */ 262 if (!xf86LoadSubModule(scrn, "vgahw")) 263 return FALSE; 264 265 /* Allocate a vgaHWRec */ 266 if (!vgaHWGetHWRec(scrn)) 267 return FALSE; 268 269 pI810->PciInfo = xf86GetPciInfoForEntity(pI810->pEnt->index); 270 271 /* Set scrn->monitor */ 272 scrn->monitor = scrn->confScreen->monitor; 273 274 flags24 = Support24bppFb | PreferConvert32to24 | SupportConvert32to24; 275 if (!xf86SetDepthBpp(scrn, 16, 0, 16, flags24)) { 276 return FALSE; 277 } else { 278 switch (scrn->depth) { 279 case 8: 280 case 15: 281 case 16: 282 case 24: 283 break; 284 default: 285 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 286 "Given depth (%d) is not supported by i810 driver\n", 287 scrn->depth); 288 return FALSE; 289 } 290 } 291 xf86PrintDepthBpp(scrn); 292 293 switch (scrn->bitsPerPixel) { 294 case 8: 295 case 16: 296 case 24: 297 break; 298 default: 299 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 300 "Given bpp (%d) is not supported by i810 driver\n", 301 scrn->bitsPerPixel); 302 return FALSE; 303 } 304 305 if (!xf86SetWeight(scrn, defaultWeight, defaultWeight)) 306 return FALSE; 307 308 if (!xf86SetDefaultVisual(scrn, -1)) 309 return FALSE; 310 311 /* We use a programmable clock */ 312 scrn->progClock = TRUE; 313 314 pI810->cpp = scrn->bitsPerPixel / 8; 315 316 /* Process the options */ 317 xf86CollectOptions(scrn, NULL); 318 if (!(pI810->Options = malloc(sizeof(I810Options)))) 319 return FALSE; 320 memcpy(pI810->Options, I810Options, sizeof(I810Options)); 321 xf86ProcessOptions(scrn->scrnIndex, scrn->options, pI810->Options); 322 323 scrn->rgbBits = 8; 324 if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE)) 325 scrn->rgbBits = 6; 326 327 if (xf86ReturnOptValBool(pI810->Options, OPTION_SHOW_CACHE, FALSE)) 328 pI810->showCache = TRUE; 329 else 330 pI810->showCache = FALSE; 331 332 /* 6-BIT dac isn't reasonable for modes with > 8bpp */ 333 if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE) && 334 scrn->bitsPerPixel > 8) { 335 OptionInfoPtr ptr; 336 337 ptr = xf86TokenToOptinfo(pI810->Options, OPTION_DAC_6BIT); 338 ptr->found = FALSE; 339 } 340 341 if (xf86ReturnOptValBool(pI810->Options, OPTION_NOACCEL, FALSE)) 342 pI810->noAccel = TRUE; 343 344 if (!pI810->noAccel && !xf86LoadSubModule(scrn, "xaa")) 345 pI810->noAccel = TRUE; 346 347#ifdef HAVE_DRI1 348 pI810->directRenderingDisabled = 349 !xf86ReturnOptValBool(pI810->Options, OPTION_DRI, TRUE); 350 351 if (!pI810->directRenderingDisabled) { 352 if (scrn->depth!=16) { 353 xf86DrvMsg(scrn->scrnIndex, X_WARNING, "DRI is disabled because it " 354 "runs only at 16-bit depth.\n"); 355 pI810->directRenderingDisabled=TRUE; 356 } 357 } 358#endif 359 360 /* Get DDC info from monitor */ 361 /* after xf86ProcessOptions, 362 * because it is controlled by options [no]vbe and [no]ddc 363 */ 364 I810DoDDC(scrn, pI810->pEnt->index); 365 366 intel_detect_chipset(scrn, pI810->pEnt, pI810->PciInfo); 367 368 pI810->LinearAddr = pI810->PciInfo->regions[0].base_addr; 369 xf86DrvMsg(scrn->scrnIndex, X_PROBED, "Linear framebuffer at 0x%lX\n", 370 (unsigned long)pI810->LinearAddr); 371 372 pI810->MMIOAddr = pI810->PciInfo->regions[1].base_addr; 373 xf86DrvMsg(scrn->scrnIndex, X_PROBED, "IO registers at addr 0x%lX\n", 374 (unsigned long)pI810->MMIOAddr); 375 376 /* AGP GART support is required. Don't proceed any further if it isn't 377 * present. 378 */ 379 if (!xf86AgpGARTSupported()) { 380 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 381 "AGP GART support is not available. Make sure your kernel has\n" 382 "\tagpgart support or that the agpgart kernel module is loaded.\n"); 383 return FALSE; 384 } 385 386 /* Find out memory bus frequency. 387 */ 388 { 389 uint32_t whtcfg_pamr_drp; 390 391 pci_device_cfg_read_u32(pI810->PciInfo, & whtcfg_pamr_drp, WHTCFG_PAMR_DRP); 392 393 /* Need this for choosing watermarks. 394 */ 395 if ((whtcfg_pamr_drp & LM_FREQ_MASK) == LM_FREQ_133) 396 pI810->LmFreqSel = 133; 397 else 398 pI810->LmFreqSel = 100; 399 } 400 401 /* Default to 4MB framebuffer, which is sufficient for all 402 * supported 2d resolutions. If the user has specified a different 403 * size in the XF86Config, use that amount instead. 404 * 405 * Changed to 8 Meg so we can have acceleration by default (Mark). 406 */ 407 mem = I810CheckAvailableMemory(scrn); 408 if (pI810->directRenderingDisabled || mem < 131072) /* < 128 MB */ 409 scrn->videoRam = 8192; 410 else if (mem < 196608) 411 scrn->videoRam = 16384; /* < 192 MB */ 412 else 413 scrn->videoRam = 24576; 414 415 from = X_DEFAULT; 416 417 if (pI810->pEnt->device->videoRam) { 418 scrn->videoRam = pI810->pEnt->device->videoRam; 419 from = X_CONFIG; 420 } 421 422 if (mem > 0 && mem < scrn->videoRam) { 423 xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%dk of memory was requested," 424 " but the\n\t maximum AGP memory available is %dk.\n", 425 scrn->videoRam, mem); 426 from = X_PROBED; 427 if (mem > (6 * 1024)) { 428 xf86DrvMsg(scrn->scrnIndex, X_INFO, 429 "Reducing video memory to 4MB\n"); 430 scrn->videoRam = 4096; 431 } else { 432 xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Less than 6MB of AGP memory" 433 " is available. Cannot proceed.\n"); 434 I810FreeRec(scrn); 435 return FALSE; 436 } 437 } 438 439 xf86DrvMsg(scrn->scrnIndex, from, 440 "Will alloc AGP framebuffer: %d kByte\n", scrn->videoRam); 441 442 /* Calculate Fixed Offsets depending on graphics aperture size */ 443 { 444 struct pci_device *bridge = intel_host_bridge (); 445 uint32_t smram_miscc; 446 447 pci_device_cfg_read_u32 (bridge, & smram_miscc, SMRAM_MISCC); 448 449 if ((smram_miscc & GFX_MEM_WIN_SIZE) == GFX_MEM_WIN_32M) { 450 pI810->FbMapSize = 0x1000000; 451 pI810->DepthOffset = 0x1000000; 452 pI810->BackOffset = 0x1800000; 453 } else { 454 pI810->FbMapSize = 0x3000000; 455 pI810->DepthOffset = 0x3000000; 456 pI810->BackOffset = 0x3800000; 457 } 458 } 459 460 /* 461 * If the driver can do gamma correction, it should call xf86SetGamma() 462 * here. 463 */ 464 { 465 Gamma zeros = { 0.0, 0.0, 0.0 }; 466 467 if (!xf86SetGamma(scrn, zeros)) { 468 return FALSE; 469 } 470 } 471 472 pI810->MaxClock = 0; 473 if (pI810->pEnt->device->dacSpeeds[0]) { 474 switch (scrn->bitsPerPixel) { 475 case 8: 476 pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP8]; 477 break; 478 case 16: 479 pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP16]; 480 break; 481 case 24: 482 pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP24]; 483 break; 484 case 32: /* not supported */ 485 pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP32]; 486 break; 487 } 488 if (!pI810->MaxClock) 489 pI810->MaxClock = pI810->pEnt->device->dacSpeeds[0]; 490 } else { 491 switch (scrn->bitsPerPixel) { 492 case 8: 493 pI810->MaxClock = 203000; 494 break; 495 case 16: 496 pI810->MaxClock = 163000; 497 break; 498 case 24: 499 pI810->MaxClock = 136000; 500 break; 501 case 32: /* not supported */ 502 pI810->MaxClock = 86000; 503 } 504 } 505 clockRanges = xnfcalloc(sizeof(ClockRange), 1); 506 clockRanges->next = NULL; 507 /* 9.4MHz appears to be the smallest that works. */ 508 clockRanges->minClock = 9500; 509 clockRanges->maxClock = pI810->MaxClock; 510 clockRanges->clockIndex = -1; 511 clockRanges->interlaceAllowed = TRUE; 512 clockRanges->doubleScanAllowed = FALSE; 513 514 i = xf86ValidateModes(scrn, scrn->monitor->Modes, 515 scrn->display->modes, clockRanges, 516#ifndef HAVE_DRI1 517 0, 320, 1600, 64 * scrn->bitsPerPixel, 518#else 519 i810_pitches, 0, 0, 64 * scrn->bitsPerPixel, 520#endif 521 200, 1200, 522 scrn->display->virtualX, scrn->display->virtualY, 523 scrn->videoRam * 1024, LOOKUP_BEST_REFRESH); 524 525 if (i == -1) { 526 I810FreeRec(scrn); 527 return FALSE; 528 } 529 530 xf86PruneDriverModes(scrn); 531 532 if (!i || !scrn->modes) { 533 xf86DrvMsg(scrn->scrnIndex, X_ERROR, "No valid modes found\n"); 534 I810FreeRec(scrn); 535 return FALSE; 536 } 537 538 xf86SetCrtcForModes(scrn, INTERLACE_HALVE_V); 539 540 scrn->currentMode = scrn->modes; 541 542 xf86PrintModes(scrn); 543 544 xf86SetDpi(scrn, 0, 0); 545 546 if (!xf86LoadSubModule(scrn, "fb")) { 547 I810FreeRec(scrn); 548 return FALSE; 549 } 550 551 if (!xf86ReturnOptValBool(pI810->Options, OPTION_SW_CURSOR, FALSE)) { 552 if (!xf86LoadSubModule(scrn, "ramdac")) { 553 I810FreeRec(scrn); 554 return FALSE; 555 } 556 } 557 558 if (xf86GetOptValInteger 559 (pI810->Options, OPTION_COLOR_KEY, &(pI810->colorKey))) { 560 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, 561 "video overlay key set to 0x%x\n", pI810->colorKey); 562 } else { 563 pI810->colorKey = (1 << scrn->offset.red) | 564 (1 << scrn->offset.green) | 565 (((scrn->mask.blue >> scrn->offset.blue) - 566 1) << scrn->offset.blue); 567 } 568 569 pI810->allowPageFlip=FALSE; 570 enable = xf86ReturnOptValBool(pI810->Options, OPTION_PAGEFLIP, FALSE); 571 572#ifdef HAVE_DRI1 573 if (!pI810->directRenderingDisabled) { 574 pI810->allowPageFlip = enable; 575 if (pI810->allowPageFlip == TRUE) 576 { 577 if (!xf86LoadSubModule(scrn, "shadowfb")) { 578 pI810->allowPageFlip = 0; 579 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 580 "Couldn't load shadowfb module:\n"); 581 } 582 } 583 584 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "page flipping %s\n", 585 enable ? "enabled" : "disabled"); 586 587 } 588#endif 589 590 if (xf86GetOptValInteger(pI810->Options, OPTION_XVMC_SURFACES, 591 &(pI810->numSurfaces))) { 592 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "%d XvMC Surfaces Requested.\n", 593 pI810->numSurfaces); 594 if (pI810->numSurfaces > 7) { 595 xf86DrvMsg(scrn->scrnIndex, X_PROBED, 596 "Using 7 XvMC Surfaces (Maximum Allowed).\n"); 597 pI810->numSurfaces = 7; 598 } 599 if (pI810->numSurfaces < 6) { 600 xf86DrvMsg(scrn->scrnIndex, X_PROBED, 601 "Using 6 XvMC Surfaces (Minimum Allowed).\n"); 602 pI810->numSurfaces = 6; 603 } 604 } else { 605 xf86DrvMsg(scrn->scrnIndex, X_INFO, 606 "XvMC is Disabled: use XvMCSurfaces config option to enable.\n"); 607 pI810->numSurfaces = 0; 608 } 609 610#ifdef HAVE_DRI1 611 /* Load the dri module if requested. */ 612 if (xf86ReturnOptValBool(pI810->Options, OPTION_DRI, FALSE)) { 613 xf86LoadSubModule(scrn, "dri"); 614 } 615#endif 616 617 return TRUE; 618} 619 620static Bool 621I810MapMMIO(ScrnInfoPtr scrn) 622{ 623 I810Ptr pI810 = I810PTR(scrn); 624 struct pci_device *const device = pI810->PciInfo; 625 int err; 626 627 err = pci_device_map_range (device, 628 pI810->MMIOAddr, 629 I810_REG_SIZE, 630 PCI_DEV_MAP_FLAG_WRITABLE, 631 (void **) &pI810->MMIOBase); 632 if (err) 633 { 634 xf86DrvMsg (scrn->scrnIndex, X_ERROR, 635 "Unable to map mmio BAR. %s (%d)\n", 636 strerror (err), err); 637 return FALSE; 638 } 639 return TRUE; 640} 641 642static Bool 643I810MapMem(ScrnInfoPtr scrn) 644{ 645 I810Ptr pI810 = I810PTR(scrn); 646 struct pci_device *const device = pI810->PciInfo; 647 int err; 648 649 if (!I810MapMMIO(scrn)) 650 return FALSE; 651 652 err = pci_device_map_range (device, 653 pI810->LinearAddr, 654 pI810->FbMapSize, 655 PCI_DEV_MAP_FLAG_WRITABLE | PCI_DEV_MAP_FLAG_WRITE_COMBINE, 656 (void **) &pI810->FbBase); 657 if (err) 658 { 659 xf86DrvMsg (scrn->scrnIndex, X_ERROR, 660 "Unable to map frame buffer BAR. %s (%d)\n", 661 strerror (err), err); 662 return FALSE; 663 } 664 665 pI810->LpRing->virtual_start = pI810->FbBase + pI810->LpRing->mem.Start; 666 667 return TRUE; 668} 669 670static void 671I810UnmapMMIO(ScrnInfoPtr scrn) 672{ 673 I810Ptr pI810 = I810PTR(scrn); 674 675 pci_device_unmap_range (pI810->PciInfo, pI810->MMIOBase, I810_REG_SIZE); 676 pI810->MMIOBase = NULL; 677} 678 679static Bool 680I810UnmapMem(ScrnInfoPtr scrn) 681{ 682 I810Ptr pI810 = I810PTR(scrn); 683 684 pci_device_unmap_range (pI810->PciInfo, pI810->FbBase, pI810->FbMapSize); 685 pI810->FbBase = NULL; 686 I810UnmapMMIO(scrn); 687 return TRUE; 688} 689 690/* Famous last words 691 */ 692void 693I810PrintErrorState(ScrnInfoPtr scrn) 694{ 695 I810Ptr pI810 = I810PTR(scrn); 696 697 ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n", 698 (unsigned long) INREG(PGETBL_CTL), (unsigned long) INREG(PGE_ERR)); 699 700 ErrorF("ipeir: %lx iphdr: %lx\n", (unsigned long) INREG(IPEIR), 701 (unsigned long) INREG(IPEHR)); 702 703 ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n", 704 (unsigned long) INREG(LP_RING + RING_TAIL), 705 (unsigned long) INREG(LP_RING + RING_HEAD) & HEAD_ADDR, 706 (unsigned long) INREG(LP_RING + RING_LEN), 707 (unsigned long) INREG(LP_RING + RING_START)); 708 709 ErrorF("eir: %x esr: %x emr: %x\n", 710 INREG16(EIR), INREG16(ESR), INREG16(EMR)); 711 712 ErrorF("instdone: %x instpm: %x\n", INREG16(INST_DONE), INREG8(INST_PM)); 713 714 ErrorF("memmode: %lx instps: %lx\n", (unsigned long) INREG(MEMMODE), 715 (unsigned long) INREG(INST_PS)); 716 717 ErrorF("hwstam: %x ier: %x imr: %x iir: %x\n", 718 INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR)); 719} 720 721/* 722 * I810Save -- 723 * 724 * This function saves the video state. It reads all of the SVGA registers 725 * into the vgaI810Rec data structure. There is in general no need to 726 * mask out bits here - just read the registers. 727 */ 728static void 729DoSave(ScrnInfoPtr scrn, vgaRegPtr vgaReg, I810RegPtr i810Reg, 730 Bool saveFonts) 731{ 732 I810Ptr pI810; 733 vgaHWPtr hwp; 734 int i; 735 736 pI810 = I810PTR(scrn); 737 hwp = VGAHWPTR(scrn); 738 739 /* 740 * This function will handle creating the data structure and filling 741 * in the generic VGA portion. 742 */ 743 if (saveFonts) 744 vgaHWSave(scrn, vgaReg, VGA_SR_MODE | VGA_SR_FONTS | VGA_SR_CMAP); 745 else 746 vgaHWSave(scrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP); 747 748 /* 749 * The port I/O code necessary to read in the extended registers 750 * into the fields of the vgaI810Rec structure goes here. 751 */ 752 i810Reg->IOControl = hwp->readCrtc(hwp, IO_CTNL); 753 i810Reg->AddressMapping = hwp->readGr(hwp, ADDRESS_MAPPING); 754 i810Reg->BitBLTControl = INREG8(BITBLT_CNTL); 755 i810Reg->VideoClk2_M = INREG16(VCLK2_VCO_M); 756 i810Reg->VideoClk2_N = INREG16(VCLK2_VCO_N); 757 i810Reg->VideoClk2_DivisorSel = INREG8(VCLK2_VCO_DIV_SEL); 758 759 i810Reg->ExtVertTotal = hwp->readCrtc(hwp, EXT_VERT_TOTAL); 760 i810Reg->ExtVertDispEnd = hwp->readCrtc(hwp, EXT_VERT_DISPLAY); 761 i810Reg->ExtVertSyncStart = hwp->readCrtc(hwp, EXT_VERT_SYNC_START); 762 i810Reg->ExtVertBlankStart = hwp->readCrtc(hwp, EXT_VERT_BLANK_START); 763 i810Reg->ExtHorizTotal = hwp->readCrtc(hwp, EXT_HORIZ_TOTAL); 764 i810Reg->ExtHorizBlank = hwp->readCrtc(hwp, EXT_HORIZ_BLANK); 765 i810Reg->ExtOffset = hwp->readCrtc(hwp, EXT_OFFSET); 766 i810Reg->InterlaceControl = hwp->readCrtc(hwp, INTERLACE_CNTL); 767 768 i810Reg->PixelPipeCfg0 = INREG8(PIXPIPE_CONFIG_0); 769 i810Reg->PixelPipeCfg1 = INREG8(PIXPIPE_CONFIG_1); 770 i810Reg->PixelPipeCfg2 = INREG8(PIXPIPE_CONFIG_2); 771 i810Reg->DisplayControl = INREG8(DISPLAY_CNTL); 772 i810Reg->LMI_FIFO_Watermark = INREG(FWATER_BLC); 773 774 for (i = 0; i < 8; i++) 775 i810Reg->Fence[i] = INREG(FENCE + i * 4); 776 777 i810Reg->LprbTail = INREG(LP_RING + RING_TAIL); 778 i810Reg->LprbHead = INREG(LP_RING + RING_HEAD); 779 i810Reg->LprbStart = INREG(LP_RING + RING_START); 780 i810Reg->LprbLen = INREG(LP_RING + RING_LEN); 781 782 if ((i810Reg->LprbTail & TAIL_ADDR) != (i810Reg->LprbHead & HEAD_ADDR) && 783 i810Reg->LprbLen & RING_VALID) { 784 I810PrintErrorState(scrn); 785 FatalError("Active ring not flushed\n"); 786 } 787} 788 789static void 790I810Save(ScrnInfoPtr scrn) 791{ 792 vgaHWPtr hwp; 793 I810Ptr pI810; 794 uint32_t temp; 795 796 hwp = VGAHWPTR(scrn); 797 pI810 = I810PTR(scrn); 798 DoSave(scrn, &hwp->SavedReg, &pI810->SavedReg, TRUE); 799 800 temp = INREG(MEMMODE); 801 temp |= 4; 802 OUTREG(MEMMODE, temp); 803} 804 805static void 806i810PrintMode(vgaRegPtr vgaReg, I810RegPtr mode) 807{ 808 int i; 809 810 ErrorF(" MiscOut: %x\n", vgaReg->MiscOutReg); 811 812 ErrorF("SEQ: "); 813 for (i = 0; i < vgaReg->numSequencer; i++) { 814 if ((i & 7) == 0) 815 ErrorF("\n"); 816 ErrorF(" %d: %x", i, vgaReg->Sequencer[i]); 817 } 818 ErrorF("\n"); 819 820 ErrorF("CRTC: "); 821 for (i = 0; i < vgaReg->numCRTC; i++) { 822 if ((i & 3) == 0) 823 ErrorF("\n"); 824 ErrorF(" %d: %x", i, vgaReg->CRTC[i]); 825 } 826 ErrorF("\n"); 827 828 ErrorF("GFX: "); 829 for (i = 0; i < vgaReg->numGraphics; i++) { 830 if ((i & 7) == 0) 831 ErrorF("\n"); 832 ErrorF(" %d: %x", i, vgaReg->Graphics[i]); 833 } 834 ErrorF("\n"); 835 836 ErrorF("ATTR: "); 837 for (i = 0; i < vgaReg->numAttribute; i++) { 838 if ((i & 7) == 0) 839 ErrorF("\n"); 840 ErrorF(" %d: %x", i, vgaReg->Attribute[i]); 841 } 842 ErrorF("\n"); 843 844 ErrorF(" DisplayControl: %x\n", mode->DisplayControl); 845 ErrorF(" PixelPipeCfg0: %x\n", mode->PixelPipeCfg0); 846 ErrorF(" PixelPipeCfg1: %x\n", mode->PixelPipeCfg1); 847 ErrorF(" PixelPipeCfg2: %x\n", mode->PixelPipeCfg2); 848 ErrorF(" VideoClk2_M: %x\n", mode->VideoClk2_M); 849 ErrorF(" VideoClk2_N: %x\n", mode->VideoClk2_N); 850 ErrorF(" VideoClk2_DivisorSel: %x\n", mode->VideoClk2_DivisorSel); 851 ErrorF(" AddressMapping: %x\n", mode->AddressMapping); 852 ErrorF(" IOControl: %x\n", mode->IOControl); 853 ErrorF(" BitBLTControl: %x\n", mode->BitBLTControl); 854 ErrorF(" ExtVertTotal: %x\n", mode->ExtVertTotal); 855 ErrorF(" ExtVertDispEnd: %x\n", mode->ExtVertDispEnd); 856 ErrorF(" ExtVertSyncStart: %x\n", mode->ExtVertSyncStart); 857 ErrorF(" ExtVertBlankStart: %x\n", mode->ExtVertBlankStart); 858 ErrorF(" ExtHorizTotal: %x\n", mode->ExtHorizTotal); 859 ErrorF(" ExtHorizBlank: %x\n", mode->ExtHorizBlank); 860 ErrorF(" ExtOffset: %x\n", mode->ExtOffset); 861 ErrorF(" InterlaceControl: %x\n", mode->InterlaceControl); 862 ErrorF(" LMI_FIFO_Watermark: %x\n", mode->LMI_FIFO_Watermark); 863 ErrorF(" LprbTail: %x\n", mode->LprbTail); 864 ErrorF(" LprbHead: %x\n", mode->LprbHead); 865 ErrorF(" LprbStart: %x\n", mode->LprbStart); 866 ErrorF(" LprbLen: %x\n", mode->LprbLen); 867} 868 869static void 870DoRestore(ScrnInfoPtr scrn, vgaRegPtr vgaReg, I810RegPtr i810Reg, 871 Bool restoreFonts) 872{ 873 I810Ptr pI810; 874 vgaHWPtr hwp; 875 unsigned char temp; 876 unsigned int itemp; 877 int i; 878 879 pI810 = I810PTR(scrn); 880 hwp = VGAHWPTR(scrn); 881 882 if (I810_DEBUG & DEBUG_VERBOSE_VGA) { 883 ErrorF("Setting mode in I810Restore:\n"); 884 i810PrintMode(vgaReg, i810Reg); 885 } 886 887 vgaHWProtect(scrn, TRUE); 888 889 usleep(50000); 890 891 /* Turn off DRAM Refresh */ 892 temp = INREG8(DRAM_ROW_CNTL_HI); 893 temp &= ~DRAM_REFRESH_RATE; 894 temp |= DRAM_REFRESH_DISABLE; 895 OUTREG8(DRAM_ROW_CNTL_HI, temp); 896 897 usleep(1000); /* Wait 1 ms */ 898 899 /* Write the M, N and P values */ 900 OUTREG16(VCLK2_VCO_M, i810Reg->VideoClk2_M); 901 OUTREG16(VCLK2_VCO_N, i810Reg->VideoClk2_N); 902 OUTREG8(VCLK2_VCO_DIV_SEL, i810Reg->VideoClk2_DivisorSel); 903 904 /* 905 * Turn on 8 bit dac mode, if requested. This is needed to make 906 * sure that vgaHWRestore writes the values into the DAC properly. 907 * The problem occurs if 8 bit dac mode is requested and the HW is 908 * in 6 bit dac mode. If this happens, all the values are 909 * automatically shifted left twice by the HW and incorrect colors 910 * will be displayed on the screen. The only time this can happen 911 * is at server startup time and when switching back from a VT. 912 */ 913 temp = INREG8(PIXPIPE_CONFIG_0); 914 temp &= 0x7F; /* Save all but the 8 bit dac mode bit */ 915 temp |= (i810Reg->PixelPipeCfg0 & DAC_8_BIT); 916 OUTREG8(PIXPIPE_CONFIG_0, temp); 917 918 /* 919 * Code to restore any SVGA registers that have been saved/modified 920 * goes here. Note that it is allowable, and often correct, to 921 * only modify certain bits in a register by a read/modify/write cycle. 922 * 923 * A special case - when using an external clock-setting program, 924 * this function must not change bits associated with the clock 925 * selection. This condition can be checked by the condition: 926 * 927 * if (i810Reg->std.NoClock >= 0) 928 * restore clock-select bits. 929 */ 930 if (restoreFonts) 931 vgaHWRestore(scrn, vgaReg, VGA_SR_FONTS | VGA_SR_MODE | VGA_SR_CMAP); 932 else 933 vgaHWRestore(scrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP); 934 935 hwp->writeCrtc(hwp, EXT_VERT_TOTAL, i810Reg->ExtVertTotal); 936 hwp->writeCrtc(hwp, EXT_VERT_DISPLAY, i810Reg->ExtVertDispEnd); 937 hwp->writeCrtc(hwp, EXT_VERT_SYNC_START, i810Reg->ExtVertSyncStart); 938 hwp->writeCrtc(hwp, EXT_VERT_BLANK_START, i810Reg->ExtVertBlankStart); 939 hwp->writeCrtc(hwp, EXT_HORIZ_TOTAL, i810Reg->ExtHorizTotal); 940 hwp->writeCrtc(hwp, EXT_HORIZ_BLANK, i810Reg->ExtHorizBlank); 941 hwp->writeCrtc(hwp, EXT_OFFSET, i810Reg->ExtOffset); 942 943 temp = hwp->readCrtc(hwp, INTERLACE_CNTL); 944 temp &= ~INTERLACE_ENABLE; 945 temp |= i810Reg->InterlaceControl; 946 hwp->writeCrtc(hwp, INTERLACE_CNTL, temp); 947 948 temp = hwp->readGr(hwp, ADDRESS_MAPPING); 949 temp &= 0xE0; /* Save reserved bits 7:5 */ 950 temp |= i810Reg->AddressMapping; 951 hwp->writeGr(hwp, ADDRESS_MAPPING, temp); 952 953 /* Setting the OVRACT Register for video overlay */ 954 { 955 uint32_t LCD_TV_Control = INREG(LCD_TV_C); 956 uint32_t TV_HTotal = INREG(LCD_TV_HTOTAL); 957 uint32_t ActiveStart, ActiveEnd; 958 959 if((LCD_TV_Control & LCD_TV_ENABLE) 960 && !(LCD_TV_Control & LCD_TV_VGAMOD) 961 && TV_HTotal) { 962 ActiveStart = ((TV_HTotal >> 16) & 0xfff) - 31; 963 ActiveEnd = (TV_HTotal & 0x3ff) - 31; 964 } else { 965 ActiveStart = i810Reg->OverlayActiveStart; 966 ActiveEnd = i810Reg->OverlayActiveEnd; 967 } 968 OUTREG(LCD_TV_OVRACT, 969 (ActiveEnd << 16) | ActiveStart); 970 } 971 972 /* Turn on DRAM Refresh */ 973 temp = INREG8(DRAM_ROW_CNTL_HI); 974 temp &= ~DRAM_REFRESH_RATE; 975 temp |= DRAM_REFRESH_60HZ; 976 OUTREG8(DRAM_ROW_CNTL_HI, temp); 977 978 temp = INREG8(BITBLT_CNTL); 979 temp &= ~COLEXP_MODE; 980 temp |= i810Reg->BitBLTControl; 981 OUTREG8(BITBLT_CNTL, temp); 982 983 temp = INREG8(DISPLAY_CNTL); 984 temp &= ~(VGA_WRAP_MODE | GUI_MODE); 985 temp |= i810Reg->DisplayControl; 986 OUTREG8(DISPLAY_CNTL, temp); 987 988 temp = INREG8(PIXPIPE_CONFIG_0); 989 temp &= 0x64; /* Save reserved bits 6:5,2 */ 990 temp |= i810Reg->PixelPipeCfg0; 991 OUTREG8(PIXPIPE_CONFIG_0, temp); 992 993 temp = INREG8(PIXPIPE_CONFIG_2); 994 temp &= 0xF3; /* Save reserved bits 7:4,1:0 */ 995 temp |= i810Reg->PixelPipeCfg2; 996 OUTREG8(PIXPIPE_CONFIG_2, temp); 997 998 temp = INREG8(PIXPIPE_CONFIG_1); 999 temp &= ~DISPLAY_COLOR_MODE; 1000 temp &= 0xEF; /* Restore the CRT control bit */ 1001 temp |= i810Reg->PixelPipeCfg1; 1002 OUTREG8(PIXPIPE_CONFIG_1, temp); 1003 1004 OUTREG16(EIR, 0); 1005 1006 itemp = INREG(FWATER_BLC); 1007 itemp &= ~(LM_BURST_LENGTH | LM_FIFO_WATERMARK | 1008 MM_BURST_LENGTH | MM_FIFO_WATERMARK); 1009 itemp |= i810Reg->LMI_FIFO_Watermark; 1010 OUTREG(FWATER_BLC, itemp); 1011 1012 for (i = 0; i < 8; i++) { 1013 OUTREG(FENCE + i * 4, i810Reg->Fence[i]); 1014 if (I810_DEBUG & DEBUG_VERBOSE_VGA) 1015 ErrorF("Fence Register : %x\n", i810Reg->Fence[i]); 1016 } 1017 1018 /* First disable the ring buffer (Need to wait for empty first?, if so 1019 * should probably do it before entering this section) 1020 */ 1021 itemp = INREG(LP_RING + RING_LEN); 1022 itemp &= ~RING_VALID_MASK; 1023 OUTREG(LP_RING + RING_LEN, itemp); 1024 1025 /* Set up the low priority ring buffer. 1026 */ 1027 OUTREG(LP_RING + RING_TAIL, 0); 1028 OUTREG(LP_RING + RING_HEAD, 0); 1029 1030 pI810->LpRing->head = 0; 1031 pI810->LpRing->tail = 0; 1032 1033 itemp = INREG(LP_RING + RING_START); 1034 itemp &= ~(START_ADDR); 1035 itemp |= i810Reg->LprbStart; 1036 OUTREG(LP_RING + RING_START, itemp); 1037 1038 itemp = INREG(LP_RING + RING_LEN); 1039 itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK); 1040 itemp |= i810Reg->LprbLen; 1041 OUTREG(LP_RING + RING_LEN, itemp); 1042 1043 if (!(vgaReg->Attribute[0x10] & 0x1)) { 1044 usleep(50000); 1045 if (restoreFonts) 1046 vgaHWRestore(scrn, vgaReg, 1047 VGA_SR_FONTS | VGA_SR_MODE | VGA_SR_CMAP); 1048 else 1049 vgaHWRestore(scrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP); 1050 } 1051 1052 vgaHWProtect(scrn, FALSE); 1053 1054 temp = hwp->readCrtc(hwp, IO_CTNL); 1055 temp &= ~(EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL); 1056 temp |= i810Reg->IOControl; 1057 hwp->writeCrtc(hwp, IO_CTNL, temp); 1058} 1059 1060static void 1061I810SetRingRegs(ScrnInfoPtr scrn) 1062{ 1063 unsigned int itemp; 1064 I810Ptr pI810 = I810PTR(scrn); 1065 1066 OUTREG(LP_RING + RING_TAIL, 0); 1067 OUTREG(LP_RING + RING_HEAD, 0); 1068 1069 itemp = INREG(LP_RING + RING_START); 1070 itemp &= ~(START_ADDR); 1071 itemp |= pI810->LpRing->mem.Start; 1072 OUTREG(LP_RING + RING_START, itemp); 1073 1074 itemp = INREG(LP_RING + RING_LEN); 1075 itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK); 1076 itemp |= ((pI810->LpRing->mem.Size - 4096) | RING_NO_REPORT | RING_VALID); 1077 OUTREG(LP_RING + RING_LEN, itemp); 1078} 1079 1080static void 1081I810Restore(ScrnInfoPtr scrn) 1082{ 1083 vgaHWPtr hwp; 1084 I810Ptr pI810; 1085 1086 hwp = VGAHWPTR(scrn); 1087 pI810 = I810PTR(scrn); 1088 1089 DoRestore(scrn, &hwp->SavedReg, &pI810->SavedReg, TRUE); 1090} 1091 1092/* 1093 * I810CalcVCLK -- 1094 * 1095 * Determine the closest clock frequency to the one requested. 1096 */ 1097 1098#define MAX_VCO_FREQ 600.0 1099#define TARGET_MAX_N 30 1100#define REF_FREQ 24.0 1101 1102#define CALC_VCLK(m,n,p) \ 1103 (double)m / ((double)n * (1 << p)) * 4 * REF_FREQ 1104 1105static void 1106I810CalcVCLK(ScrnInfoPtr scrn, double freq) 1107{ 1108 I810Ptr pI810 = I810PTR(scrn); 1109 I810RegPtr i810Reg = &pI810->ModeReg; 1110 int m, n, p; 1111 double f_out; 1112 double f_err; 1113 double f_vco; 1114 int m_best = 0, n_best = 0, p_best = 0; 1115 double f_target = freq; 1116 double err_max = 0.005; 1117 double err_target = 0.001; 1118 double err_best = 999999.0; 1119 1120 p_best = p = log(MAX_VCO_FREQ / f_target) / log((double)2); 1121 /* Make sure p is within range. */ 1122 if (p_best > 5) { 1123 p_best = p = 5; 1124 } 1125 1126 f_vco = f_target * (1 << p); 1127 1128 n = 2; 1129 do { 1130 n++; 1131 m = f_vco / (REF_FREQ / (double)n) / (double)4.0 + 0.5; 1132 if (m < 3) 1133 m = 3; 1134 f_out = CALC_VCLK(m, n, p); 1135 f_err = 1.0 - (f_target / f_out); 1136 if (fabs(f_err) < err_max) { 1137 m_best = m; 1138 n_best = n; 1139 err_best = f_err; 1140 } 1141 } while ((fabs(f_err) >= err_target) && 1142 ((n <= TARGET_MAX_N) || (fabs(err_best) > err_max))); 1143 1144 if (fabs(f_err) < err_target) { 1145 m_best = m; 1146 n_best = n; 1147 } 1148 1149 i810Reg->VideoClk2_M = (m_best - 2) & 0x3FF; 1150 i810Reg->VideoClk2_N = (n_best - 2) & 0x3FF; 1151 i810Reg->VideoClk2_DivisorSel = (p_best << 4); 1152 1153 xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, 3, 1154 "Setting dot clock to %.1f MHz " "[ 0x%x 0x%x 0x%x ] " 1155 "[ %d %d %d ]\n", CALC_VCLK(m_best, n_best, p_best), 1156 i810Reg->VideoClk2_M, i810Reg->VideoClk2_N, 1157 i810Reg->VideoClk2_DivisorSel, m_best, n_best, p_best); 1158} 1159 1160static Bool 1161I810SetMode(ScrnInfoPtr scrn, DisplayModePtr mode) 1162{ 1163 I810Ptr pI810 = I810PTR(scrn); 1164 I810RegPtr i810Reg = &pI810->ModeReg; 1165 vgaRegPtr pVga = &VGAHWPTR(scrn)->ModeReg; 1166 double dclk = mode->Clock / 1000.0; 1167 1168 switch (scrn->bitsPerPixel) { 1169 case 8: 1170 pVga->CRTC[0x13] = scrn->displayWidth >> 3; 1171 i810Reg->ExtOffset = scrn->displayWidth >> 11; 1172 i810Reg->PixelPipeCfg1 = DISPLAY_8BPP_MODE; 1173 i810Reg->BitBLTControl = COLEXP_8BPP; 1174 break; 1175 case 16: 1176 if (scrn->weight.green == 5) { 1177 i810Reg->PixelPipeCfg1 = DISPLAY_15BPP_MODE; 1178 } else { 1179 i810Reg->PixelPipeCfg1 = DISPLAY_16BPP_MODE; 1180 } 1181 pVga->CRTC[0x13] = scrn->displayWidth >> 2; 1182 i810Reg->ExtOffset = scrn->displayWidth >> 10; 1183 i810Reg->BitBLTControl = COLEXP_16BPP; 1184 1185 /* Enable Palette Programming for Direct Color visuals. -jens */ 1186 i810Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE; 1187 break; 1188 case 24: 1189 pVga->CRTC[0x13] = (scrn->displayWidth * 3) >> 3; 1190 i810Reg->ExtOffset = (scrn->displayWidth * 3) >> 11; 1191 1192 i810Reg->PixelPipeCfg1 = DISPLAY_24BPP_MODE; 1193 i810Reg->BitBLTControl = COLEXP_24BPP; 1194 1195 /* Enable Palette Programming for Direct Color visuals. -jens */ 1196 i810Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE; 1197 break; 1198 default: 1199 break; 1200 } 1201 1202 /* Turn on 8 bit dac if requested */ 1203 if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE)) 1204 i810Reg->PixelPipeCfg0 = DAC_6_BIT; 1205 else 1206 i810Reg->PixelPipeCfg0 = DAC_8_BIT; 1207 1208 /* Do not delay CRT Blank: needed for video overlay */ 1209 i810Reg->PixelPipeCfg1 |= 0x10; 1210 1211 /* Turn on Extended VGA Interpretation */ 1212 i810Reg->IOControl = EXTENDED_CRTC_CNTL; 1213 1214 /* Turn on linear and page mapping */ 1215 i810Reg->AddressMapping = (LINEAR_MODE_ENABLE | GTT_MEM_MAP_ENABLE); 1216 1217 /* Turn on GUI mode */ 1218 i810Reg->DisplayControl = HIRES_MODE; 1219 1220 /* Calculate the extended CRTC regs */ 1221 i810Reg->ExtVertTotal = (mode->CrtcVTotal - 2) >> 8; 1222 i810Reg->ExtVertDispEnd = (mode->CrtcVDisplay - 1) >> 8; 1223 i810Reg->ExtVertSyncStart = mode->CrtcVSyncStart >> 8; 1224 i810Reg->ExtVertBlankStart = mode->CrtcVBlankStart >> 8; 1225 i810Reg->ExtHorizTotal = ((mode->CrtcHTotal >> 3) - 5) >> 8; 1226 i810Reg->ExtHorizBlank = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 6; 1227 1228 /* 1229 * the KGA fix in vgaHW.c results in the first 1230 * scanline and the first character clock (8 pixels) 1231 * of each scanline thereafter on display with an i810 1232 * to be blank. Restoring CRTC 3, 5, & 22 to their 1233 * "theoretical" values corrects the problem. KAO. 1234 */ 1235 pVga->CRTC[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80; 1236 pVga->CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2) 1237 | (((mode->CrtcHSyncEnd >> 3)) & 0x1F); 1238 pVga->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF; 1239 1240 i810Reg->ExtHorizBlank = vgaHWHBlankKGA(mode, pVga, 7, 0); 1241 vgaHWVBlankKGA(mode, pVga, 8, 0); 1242 1243 /* 1244 * The following workarounds are needed to get video overlay working 1245 * at 1024x768 and 1280x1024 display resolutions. 1246 */ 1247 if ((mode->CrtcVDisplay == 768) && (i810Reg->ExtVertBlankStart == 3)) { 1248 i810Reg->ExtVertBlankStart = 2; 1249 } 1250 if ((mode->CrtcVDisplay == 1024) && (i810Reg->ExtVertBlankStart == 4)) { 1251 i810Reg->ExtVertBlankStart = 3; 1252 } 1253 1254 /* OVRACT Register */ 1255 i810Reg->OverlayActiveStart = mode->CrtcHTotal - 32; 1256 i810Reg->OverlayActiveEnd = mode->CrtcHDisplay - 32; 1257 1258 /* Turn on interlaced mode if necessary */ 1259 if (mode->Flags & V_INTERLACE) { 1260 i810Reg->InterlaceControl = INTERLACE_ENABLE; 1261 i810Reg->ExtVertDispEnd *= 2; 1262 } else 1263 i810Reg->InterlaceControl = INTERLACE_DISABLE; 1264 1265 /* 1266 * Set the overscan color to 0. 1267 * NOTE: This only affects >8bpp mode. 1268 */ 1269 pVga->Attribute[0x11] = 0; 1270 1271 /* 1272 * Calculate the VCLK that most closely matches the requested dot 1273 * clock. 1274 */ 1275 I810CalcVCLK(scrn, dclk); 1276 1277 /* Since we program the clocks ourselves, always use VCLK2. */ 1278 pVga->MiscOutReg |= 0x0C; 1279 1280 /* Calculate the FIFO Watermark and Burst Length. */ 1281 i810Reg->LMI_FIFO_Watermark = I810CalcWatermark(scrn, dclk, FALSE); 1282 1283 /* Setup the ring buffer */ 1284 i810Reg->LprbTail = 0; 1285 i810Reg->LprbHead = 0; 1286 i810Reg->LprbStart = pI810->LpRing->mem.Start; 1287 1288 if (i810Reg->LprbStart) 1289 i810Reg->LprbLen = ((pI810->LpRing->mem.Size - 4096) | 1290 RING_NO_REPORT | RING_VALID); 1291 else 1292 i810Reg->LprbLen = RING_INVALID; 1293 1294 return TRUE; 1295} 1296 1297static Bool 1298I810ModeInit(ScrnInfoPtr scrn, DisplayModePtr mode) 1299{ 1300 vgaHWPtr hwp; 1301 I810Ptr pI810; 1302 1303 hwp = VGAHWPTR(scrn); 1304 pI810 = I810PTR(scrn); 1305 1306 vgaHWUnlock(hwp); 1307 1308 if (!vgaHWInit(scrn, mode)) 1309 return FALSE; 1310 1311 scrn->vtSema = TRUE; 1312 1313 if (!I810SetMode(scrn, mode)) 1314 return FALSE; 1315 1316#ifdef HAVE_DRI1 1317 if (pI810->directRenderingEnabled) { 1318 DRILock(xf86ScrnToScreen(scrn), 0); 1319 pI810->LockHeld = 1; 1320 } 1321#endif 1322 1323 DoRestore(scrn, &hwp->ModeReg, &pI810->ModeReg, FALSE); 1324 1325#ifdef HAVE_DRI1 1326 if (pI810->directRenderingEnabled) { 1327 DRIUnlock(xf86ScrnToScreen(scrn)); 1328 pI810->LockHeld = 0; 1329 } 1330#endif 1331 1332 return TRUE; 1333} 1334 1335static void 1336I810LoadPalette15(ScrnInfoPtr scrn, int numColors, int *indices, 1337 LOCO * colors, VisualPtr pVisual) 1338{ 1339 vgaHWPtr hwp; 1340 int i, j, index; 1341 unsigned char r, g, b; 1342 1343 hwp = VGAHWPTR(scrn); 1344 1345 for (i = 0; i < numColors; i++) { 1346 index = indices[i]; 1347 r = colors[index].red; 1348 g = colors[index].green; 1349 b = colors[index].blue; 1350 for (j = 0; j < 8; j++) { 1351 hwp->writeDacWriteAddr(hwp, (index << 3) + j); 1352 hwp->writeDacData(hwp, r); 1353 hwp->writeDacData(hwp, g); 1354 hwp->writeDacData(hwp, b); 1355 } 1356 } 1357} 1358 1359static void 1360I810LoadPalette16(ScrnInfoPtr scrn, int numColors, int *indices, 1361 LOCO * colors, VisualPtr pVisual) 1362{ 1363 vgaHWPtr hwp; 1364 int i, index; 1365 unsigned char r, g, b; 1366 1367 hwp = VGAHWPTR(scrn); 1368 1369 /* Load all four entries in each of the 64 color ranges. -jens */ 1370 for (i = 0; i < numColors; i++) { 1371 index = indices[i / 2]; 1372 r = colors[index].red; 1373 b = colors[index].blue; 1374 index = indices[i]; 1375 g = colors[index].green; 1376 1377 hwp->writeDacWriteAddr(hwp, index << 2); 1378 hwp->writeDacData(hwp, r); 1379 hwp->writeDacData(hwp, g); 1380 hwp->writeDacData(hwp, b); 1381 1382 hwp->writeDacWriteAddr(hwp, (index << 2) + 1); 1383 hwp->writeDacData(hwp, r); 1384 hwp->writeDacData(hwp, g); 1385 hwp->writeDacData(hwp, b); 1386 1387 hwp->writeDacWriteAddr(hwp, (index << 2) + 2); 1388 hwp->writeDacData(hwp, r); 1389 hwp->writeDacData(hwp, g); 1390 hwp->writeDacData(hwp, b); 1391 1392 hwp->writeDacWriteAddr(hwp, (index << 2) + 3); 1393 hwp->writeDacData(hwp, r); 1394 hwp->writeDacData(hwp, g); 1395 hwp->writeDacData(hwp, b); 1396 1397 i++; 1398 index = indices[i]; 1399 g = colors[index].green; 1400 1401 hwp->writeDacWriteAddr(hwp, index << 2); 1402 hwp->writeDacData(hwp, r); 1403 hwp->writeDacData(hwp, g); 1404 hwp->writeDacData(hwp, b); 1405 1406 hwp->writeDacWriteAddr(hwp, (index << 2) + 1); 1407 hwp->writeDacData(hwp, r); 1408 hwp->writeDacData(hwp, g); 1409 hwp->writeDacData(hwp, b); 1410 1411 hwp->writeDacWriteAddr(hwp, (index << 2) + 2); 1412 hwp->writeDacData(hwp, r); 1413 hwp->writeDacData(hwp, g); 1414 hwp->writeDacData(hwp, b); 1415 1416 hwp->writeDacWriteAddr(hwp, (index << 2) + 3); 1417 hwp->writeDacData(hwp, r); 1418 hwp->writeDacData(hwp, g); 1419 hwp->writeDacData(hwp, b); 1420 } 1421} 1422 1423static void 1424I810LoadPalette24(ScrnInfoPtr scrn, int numColors, int *indices, 1425 LOCO * colors, VisualPtr pVisual) 1426{ 1427 vgaHWPtr hwp; 1428 int i, index; 1429 unsigned char r, g, b; 1430 1431 hwp = VGAHWPTR(scrn); 1432 1433 for (i = 0; i < numColors; i++) { 1434 index = indices[i]; 1435 r = colors[index].red; 1436 g = colors[index].green; 1437 b = colors[index].blue; 1438 hwp->writeDacWriteAddr(hwp, index); 1439 hwp->writeDacData(hwp, r); 1440 hwp->writeDacData(hwp, g); 1441 hwp->writeDacData(hwp, b); 1442 } 1443} 1444 1445Bool 1446I810AllocateFront(ScrnInfoPtr scrn) 1447{ 1448 I810Ptr pI810 = I810PTR(scrn); 1449 int cache_lines = -1; 1450 1451 if (pI810->DoneFrontAlloc) 1452 return TRUE; 1453 1454 memset(&(pI810->FbMemBox), 0, sizeof(BoxRec)); 1455 /* Alloc FrontBuffer/Ring/Accel memory */ 1456 pI810->FbMemBox.x1 = 0; 1457 pI810->FbMemBox.x2 = scrn->displayWidth; 1458 pI810->FbMemBox.y1 = 0; 1459 pI810->FbMemBox.y2 = scrn->virtualY; 1460 1461 xf86GetOptValInteger(pI810->Options, OPTION_CACHE_LINES, &cache_lines); 1462 1463 if (cache_lines < 0) { 1464 /* make sure there is enough for two DVD sized YUV buffers */ 1465 cache_lines = (scrn->depth == 24) ? 256 : 384; 1466 if (scrn->displayWidth <= 1024) 1467 cache_lines *= 2; 1468 } 1469 /* Make sure there's enough space for cache_lines. 1470 * 1471 * Had a bug here where maxCacheLines was computed to be less than 0. 1472 * Not sure why 256 was initially subtracted from videoRam in the 1473 * maxCacheLines calculation, but that was causing a problem 1474 * for configurations that have exactly enough Ram for the framebuffer. 1475 * Common code should catch the case where there isn't enough space for 1476 * framebuffer, we'll just check for no space for cache_lines. -jens 1477 * 1478 */ 1479 { 1480 int maxCacheLines; 1481 1482 maxCacheLines = (scrn->videoRam * 1024 / 1483 (scrn->bitsPerPixel / 8) / 1484 scrn->displayWidth) - scrn->virtualY; 1485 if (maxCacheLines < 0) 1486 maxCacheLines = 0; 1487 if (cache_lines > maxCacheLines) 1488 cache_lines = maxCacheLines; 1489 } 1490 pI810->FbMemBox.y2 += cache_lines; 1491 1492 xf86DrvMsg(scrn->scrnIndex, X_INFO, 1493 "Adding %i scanlines for pixmap caching\n", cache_lines); 1494 1495 /* Reserve room for the framebuffer and pixcache. Put at the top 1496 * of memory so we can have nice alignment for the tiled regions at 1497 * the start of memory. 1498 */ 1499 1500 if (!I810AllocLow(&(pI810->FrontBuffer), 1501 &(pI810->SysMem), 1502 ALIGN((pI810->FbMemBox.x2 * pI810->FbMemBox.y2 * pI810->cpp), 4096))) { 1503 xf86DrvMsg(scrn->scrnIndex, 1504 X_WARNING, "Framebuffer allocation failed\n"); 1505 return FALSE; 1506 } 1507 1508 memset(pI810->LpRing, 0, sizeof(I810RingBuffer)); 1509 if (I810AllocLow(&(pI810->LpRing->mem), &(pI810->SysMem), 16 * 4096)) { 1510 pI810->LpRing->tail_mask = pI810->LpRing->mem.Size - 1; 1511 pI810->LpRing->virtual_start = pI810->FbBase + pI810->LpRing->mem.Start; 1512 pI810->LpRing->head = 0; 1513 pI810->LpRing->tail = 0; 1514 pI810->LpRing->space = 0; 1515 } else { 1516 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 1517 "Ring buffer allocation failed\n"); 1518 return (FALSE); 1519 } 1520 1521 if (I810AllocLow(&pI810->Scratch, &(pI810->SysMem), 64 * 1024) || 1522 I810AllocLow(&pI810->Scratch, &(pI810->SysMem), 16 * 1024)) { 1523 xf86DrvMsg(scrn->scrnIndex, X_INFO, "Allocated Scratch Memory\n"); 1524 } else { 1525 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 1526 "Scratch memory allocation failed\n"); 1527 return (FALSE); 1528 } 1529 1530 pI810->DoneFrontAlloc = TRUE; 1531 return TRUE; 1532} 1533 1534static Bool 1535I810ScreenInit(SCREEN_INIT_ARGS_DECL) 1536{ 1537 ScrnInfoPtr scrn; 1538 vgaHWPtr hwp; 1539 I810Ptr pI810; 1540 VisualPtr visual; 1541 1542 scrn = xf86ScreenToScrn(screen); 1543 pI810 = I810PTR(scrn); 1544 hwp = VGAHWPTR(scrn); 1545 1546 pI810->LpRing = calloc(sizeof(I810RingBuffer),1); 1547 if (!pI810->LpRing) { 1548 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 1549 "Could not allocate lpring data structure.\n"); 1550 return FALSE; 1551 } 1552 1553 miClearVisualTypes(); 1554 1555 /* Re-implemented Direct Color support, -jens */ 1556 if (!miSetVisualTypes(scrn->depth, miGetDefaultVisualMask(scrn->depth), 1557 scrn->rgbBits, scrn->defaultVisual)) 1558 return FALSE; 1559 1560 if (!miSetPixmapDepths()) 1561 return FALSE; 1562 1563 { 1564 I810RegPtr i810Reg = &pI810->ModeReg; 1565 int i; 1566 1567 for (i = 0; i < 8; i++) 1568 i810Reg->Fence[i] = 0; 1569 } 1570 1571 /* Have to init the DRM earlier than in other drivers to get agp 1572 * memory. Wonder if this is going to be a problem... 1573 */ 1574 1575#ifdef HAVE_DRI1 1576 /* 1577 * Setup DRI after visuals have been established, but before fbScreenInit 1578 * is called. fbScreenInit will eventually call into the drivers 1579 * InitGLXVisuals call back. 1580 */ 1581 /* 1582 * pI810->directRenderingDisabled is set once in PreInit. Reinitialise 1583 * pI810->directRenderingEnabled based on it each generation. 1584 */ 1585 pI810->directRenderingEnabled = !pI810->directRenderingDisabled; 1586 1587 if (pI810->directRenderingEnabled==TRUE) 1588 pI810->directRenderingEnabled = I810DRIScreenInit(screen); 1589 1590#else 1591 pI810->directRenderingEnabled = FALSE; 1592 if (!I810AllocateGARTMemory(scrn)) 1593 return FALSE; 1594 if (!I810AllocateFront(scrn)) 1595 return FALSE; 1596#endif 1597 1598 if (!I810MapMem(scrn)) 1599 return FALSE; 1600 1601 scrn->memPhysBase = (unsigned long)pI810->LinearAddr; 1602 scrn->fbOffset = 0; 1603 1604 vgaHWSetMmioFuncs(hwp, pI810->MMIOBase, 0); 1605 vgaHWGetIOBase(hwp); 1606 if (!vgaHWMapMem(scrn)) 1607 return FALSE; 1608 1609 I810Save(scrn); 1610 if (!I810ModeInit(scrn, scrn->currentMode)) 1611 return FALSE; 1612 1613 I810SaveScreen(screen, FALSE); 1614 I810AdjustFrame(ADJUST_FRAME_ARGS(scrn, scrn->frameX0, scrn->frameY0)); 1615 1616 if (!fbScreenInit(screen, pI810->FbBase + scrn->fbOffset, 1617 scrn->virtualX, scrn->virtualY, 1618 scrn->xDpi, scrn->yDpi, 1619 scrn->displayWidth, scrn->bitsPerPixel)) 1620 return FALSE; 1621 1622 if (scrn->bitsPerPixel > 8) { 1623 /* Fixup RGB ordering */ 1624 visual = screen->visuals + screen->numVisuals; 1625 while (--visual >= screen->visuals) { 1626 if ((visual->class | DynamicClass) == DirectColor) { 1627 visual->offsetRed = scrn->offset.red; 1628 visual->offsetGreen = scrn->offset.green; 1629 visual->offsetBlue = scrn->offset.blue; 1630 visual->redMask = scrn->mask.red; 1631 visual->greenMask = scrn->mask.green; 1632 visual->blueMask = scrn->mask.blue; 1633 } 1634 } 1635 } 1636 1637 fbPictureInit(screen, NULL, 0); 1638 1639 xf86SetBlackWhitePixels(screen); 1640 1641#ifdef HAVE_DRI1 1642 if (pI810->LpRing->mem.Start == 0 && pI810->directRenderingEnabled) { 1643 pI810->directRenderingEnabled = FALSE; 1644 I810DRICloseScreen(screen); 1645 } 1646 1647 if (!pI810->directRenderingEnabled) { 1648 pI810->DoneFrontAlloc = FALSE; 1649 if (!I810AllocateGARTMemory(scrn)) 1650 return FALSE; 1651 if (!I810AllocateFront(scrn)) 1652 return FALSE; 1653 } 1654#endif 1655 1656#ifdef HAVE_DGAPROC_H 1657 I810DGAInit(screen); 1658#endif 1659 1660 if (!xf86InitFBManager(screen, &(pI810->FbMemBox))) { 1661 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 1662 "Failed to init memory manager\n"); 1663 return FALSE; 1664 } 1665 1666 if (pI810->LpRing->mem.Size != 0) { 1667 I810SetRingRegs(scrn); 1668 1669 if (!pI810->noAccel && !I810AccelInit(screen)) { 1670 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 1671 "Hardware acceleration initialization failed\n"); 1672 } 1673 1674 I810EmitFlush(scrn); 1675 } 1676 1677 xf86SetBackingStore(screen); 1678 xf86SetSilkenMouse(screen); 1679 1680 miDCInitialize(screen, xf86GetPointerScreenFuncs()); 1681 1682 if (!xf86ReturnOptValBool(pI810->Options, OPTION_SW_CURSOR, FALSE)) { 1683 if (!I810CursorInit(screen)) { 1684 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 1685 "Hardware cursor initialization failed\n"); 1686 } 1687 } 1688 1689 if (!miCreateDefColormap(screen)) 1690 return FALSE; 1691 1692 /* Use driver specific palette load routines for Direct Color support. -jens */ 1693 if (scrn->bitsPerPixel == 16) { 1694 if (scrn->depth == 15) { 1695 if (!xf86HandleColormaps(screen, 256, 8, I810LoadPalette15, NULL, 1696 CMAP_PALETTED_TRUECOLOR | 1697 CMAP_RELOAD_ON_MODE_SWITCH)) 1698 return FALSE; 1699 } else { 1700 if (!xf86HandleColormaps(screen, 256, 8, I810LoadPalette16, NULL, 1701 CMAP_PALETTED_TRUECOLOR | 1702 CMAP_RELOAD_ON_MODE_SWITCH)) 1703 return FALSE; 1704 } 1705 } else { 1706 if (!xf86HandleColormaps(screen, 256, 8, I810LoadPalette24, NULL, 1707 CMAP_PALETTED_TRUECOLOR | 1708 CMAP_RELOAD_ON_MODE_SWITCH)) 1709 return FALSE; 1710 } 1711 1712 xf86DPMSInit(screen, I810DisplayPowerManagementSet, 0); 1713 1714 I810InitVideo(screen); 1715 1716#ifdef HAVE_DRI1 1717 if (pI810->directRenderingEnabled) { 1718 /* Now that mi, fb, drm and others have done their thing, 1719 * complete the DRI setup. 1720 */ 1721 pI810->directRenderingEnabled = I810DRIFinishScreenInit(screen); 1722 } 1723#ifdef XvMCExtension 1724 if ((pI810->directRenderingEnabled) && (pI810->numSurfaces)) { 1725 /* Initialize the hardware motion compensation code */ 1726 I810InitMC(screen); 1727 } 1728#endif 1729#endif 1730 1731 if (pI810->directRenderingEnabled) { 1732 xf86DrvMsg(scrn->scrnIndex, X_INFO, "Direct rendering enabled\n"); 1733 } else { 1734 xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Direct rendering disabled\n"); 1735 } 1736 1737 screen->SaveScreen = I810SaveScreen; 1738 pI810->CloseScreen = screen->CloseScreen; 1739 screen->CloseScreen = I810CloseScreen; 1740 1741 if (serverGeneration == 1) 1742 xf86ShowUnusedOptions(scrn->scrnIndex, scrn->options); 1743 1744 return TRUE; 1745} 1746 1747Bool 1748I810SwitchMode(SWITCH_MODE_ARGS_DECL) 1749{ 1750 SCRN_INFO_PTR(arg); 1751#if 0 1752 I810Ptr pI810 = I810PTR(scrn); 1753#endif 1754 if (I810_DEBUG & DEBUG_VERBOSE_CURSOR) 1755 ErrorF("I810SwitchMode %p\n", (void *)mode); 1756 1757#if 0 1758/* 1759 * This has been added to prevent lockups on mode switch by modeling 1760 * it after I810Leave()/I810Enter() but the call to I810DRILeave() 1761 * was missing so it caused the opposite. 1762 * The version below works but it is doubtful it does any good. 1763 * If lockups on mode switch are still seen revisit this code. (EE) 1764 */ 1765 1766# ifdef HAVE_DRI1 1767 if (pI810->directRenderingEnabled) { 1768 if (I810_DEBUG & DEBUG_VERBOSE_DRI) 1769 ErrorF("calling dri lock\n"); 1770 DRILock(screenInfo.screens[scrnIndex], 0); 1771 pI810->LockHeld = 1; 1772 } 1773# endif 1774 if (pI810->AccelInfoRec != NULL) { 1775 I810RefreshRing(scrn); 1776 I810Sync(scrn); 1777 pI810->AccelInfoRec->NeedToSync = FALSE; 1778 } 1779 I810Restore(scrn); 1780 1781# ifdef HAVE_DRI1 1782 if (pI810->directRenderingEnabled) { 1783 if (!I810DRILeave(scrn)) 1784 return FALSE; 1785 if (!I810DRIEnter(scrn)) 1786 return FALSE; 1787 1788 if (I810_DEBUG & DEBUG_VERBOSE_DRI) 1789 ErrorF("calling dri unlock\n"); 1790 DRIUnlock(screenInfo.screens[scrnIndex]); 1791 pI810->LockHeld = 0; 1792 } 1793# endif 1794#endif 1795 return I810ModeInit(scrn, mode); 1796} 1797 1798void 1799I810AdjustFrame(ADJUST_FRAME_ARGS_DECL) 1800{ 1801 SCRN_INFO_PTR(arg); 1802 I810Ptr pI810 = I810PTR(scrn); 1803 vgaHWPtr hwp = VGAHWPTR(scrn); 1804 int Base; 1805 1806#if 1 1807 if (pI810->showCache) { 1808 int lastline = pI810->FbMapSize / 1809 ((scrn->displayWidth * scrn->bitsPerPixel) / 8); 1810 lastline -= scrn->currentMode->VDisplay; 1811 if (y > 0) 1812 y += scrn->currentMode->VDisplay; 1813 if (y > lastline) y = lastline; 1814 } 1815#endif 1816 Base = (y * scrn->displayWidth + x) >> 2; 1817 1818 if (I810_DEBUG & DEBUG_VERBOSE_CURSOR) 1819 ErrorF("I810AdjustFrame %d,%d\n", x, y); 1820 1821 switch (scrn->bitsPerPixel) { 1822 case 8: 1823 break; 1824 case 16: 1825 Base *= 2; 1826 break; 1827 case 24: 1828 /* KW: Need to do 16-pixel alignment for i810, otherwise you 1829 * get bad watermark problems. Need to fixup the mouse 1830 * pointer positioning to take this into account. 1831 */ 1832 pI810->CursorOffset = (Base & 0x3) * 4; 1833 Base &= ~0x3; 1834 Base *= 3; 1835 break; 1836 case 32: 1837 Base *= 4; 1838 break; 1839 } 1840 1841 hwp->writeCrtc(hwp, START_ADDR_LO, Base & 0xFF); 1842 hwp->writeCrtc(hwp, START_ADDR_HI, (Base & 0xFF00) >> 8); 1843 hwp->writeCrtc(hwp, EXT_START_ADDR_HI, (Base & 0x3FC00000) >> 22); 1844 hwp->writeCrtc(hwp, EXT_START_ADDR, 1845 ((Base & 0x00eF0000) >> 16 | EXT_START_ADDR_ENABLE)); 1846} 1847 1848/* These functions are usually called with the lock **not held**. 1849 */ 1850static Bool 1851I810EnterVT(VT_FUNC_ARGS_DECL) 1852{ 1853 SCRN_INFO_PTR(arg); 1854 1855#ifdef HAVE_DRI1 1856 I810Ptr pI810 = I810PTR(scrn); 1857#endif 1858 1859 if (I810_DEBUG & DEBUG_VERBOSE_DRI) 1860 ErrorF("\n\nENTER VT\n"); 1861 1862 if (!I810BindGARTMemory(scrn)) { 1863 return FALSE; 1864 } 1865#ifdef HAVE_DRI1 1866 if (!I810DRIEnter(scrn)) { 1867 return FALSE; 1868 } 1869 if (pI810->directRenderingEnabled) { 1870 if (I810_DEBUG & DEBUG_VERBOSE_DRI) 1871 ErrorF("calling dri unlock\n"); 1872 DRIUnlock(xf86ScrnToScreen(scrn)); 1873 pI810->LockHeld = 0; 1874 } 1875#endif 1876 1877 if (!I810ModeInit(scrn, scrn->currentMode)) 1878 return FALSE; 1879 I810AdjustFrame(ADJUST_FRAME_ARGS(scrn, scrn->frameX0, scrn->frameY0)); 1880 return TRUE; 1881} 1882 1883static void 1884I810LeaveVT(VT_FUNC_ARGS_DECL) 1885{ 1886 SCRN_INFO_PTR(arg); 1887 vgaHWPtr hwp = VGAHWPTR(scrn); 1888 I810Ptr pI810 = I810PTR(scrn); 1889 1890 if (I810_DEBUG & DEBUG_VERBOSE_DRI) 1891 ErrorF("\n\n\nLeave VT\n"); 1892 1893#ifdef HAVE_DRI1 1894 if (pI810->directRenderingEnabled) { 1895 if (I810_DEBUG & DEBUG_VERBOSE_DRI) 1896 ErrorF("calling dri lock\n"); 1897 DRILock(xf86ScrnToScreen(scrn), 0); 1898 pI810->LockHeld = 1; 1899 } 1900#endif 1901 1902#ifdef HAVE_XAA_H 1903 if (pI810->AccelInfoRec != NULL) { 1904 I810RefreshRing(scrn); 1905 I810Sync(scrn); 1906 pI810->AccelInfoRec->NeedToSync = FALSE; 1907 } 1908#endif 1909 I810Restore(scrn); 1910 1911 if (!I810UnbindGARTMemory(scrn)) 1912 return; 1913#ifdef HAVE_DRI1 1914 if (!I810DRILeave(scrn)) 1915 return; 1916#endif 1917 1918 vgaHWLock(hwp); 1919} 1920 1921static Bool 1922I810CloseScreen(CLOSE_SCREEN_ARGS_DECL) 1923{ 1924 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1925 vgaHWPtr hwp = VGAHWPTR(scrn); 1926 I810Ptr pI810 = I810PTR(scrn); 1927#ifdef HAVE_XAA_H 1928 XAAInfoRecPtr infoPtr = pI810->AccelInfoRec; 1929#endif 1930 1931 if (scrn->vtSema == TRUE) { 1932#ifdef HAVE_XAA_H 1933 if (pI810->AccelInfoRec != NULL) { 1934 I810RefreshRing(scrn); 1935 I810Sync(scrn); 1936 pI810->AccelInfoRec->NeedToSync = FALSE; 1937 } 1938#endif 1939 I810Restore(scrn); 1940 vgaHWLock(hwp); 1941 } 1942#ifdef HAVE_DRI1 1943 if (pI810->directRenderingEnabled) { 1944 I810DRICloseScreen(screen); 1945 pI810->directRenderingEnabled = FALSE; 1946 } 1947#endif 1948 1949 if (scrn->vtSema == TRUE) { 1950 I810UnbindGARTMemory(scrn); 1951 I810Restore(scrn); 1952 vgaHWLock(hwp); 1953 } 1954 1955 I810UnmapMem(scrn); 1956 vgaHWUnmapMem(scrn); 1957 1958 if (pI810->ScanlineColorExpandBuffers) { 1959 free(pI810->ScanlineColorExpandBuffers); 1960 pI810->ScanlineColorExpandBuffers = NULL; 1961 } 1962 1963#ifdef HAVE_XAA_H 1964 if (infoPtr) { 1965 if (infoPtr->ScanlineColorExpandBuffers) 1966 free(infoPtr->ScanlineColorExpandBuffers); 1967 XAADestroyInfoRec(infoPtr); 1968 pI810->AccelInfoRec = NULL; 1969 } 1970#endif 1971 1972 if (pI810->CursorInfoRec) { 1973 xf86DestroyCursorInfoRec(pI810->CursorInfoRec); 1974 pI810->CursorInfoRec = NULL; 1975 } 1976 1977 /* Free all allocated video ram. 1978 */ 1979 pI810->SysMem = pI810->SavedSysMem; 1980 pI810->DcacheMem = pI810->SavedDcacheMem; 1981 pI810->DoneFrontAlloc = FALSE; 1982 1983 /* Need to actually close the gart fd, or the unbound memory will just sit 1984 * around. Will prevent the Xserver from recycling. 1985 */ 1986 xf86GARTCloseScreen(scrn->scrnIndex); 1987 1988 free(pI810->LpRing); 1989 pI810->LpRing = NULL; 1990 1991 scrn->vtSema = FALSE; 1992 screen->CloseScreen = pI810->CloseScreen; 1993 return (*screen->CloseScreen) (CLOSE_SCREEN_ARGS); 1994} 1995 1996static void 1997I810FreeScreen(FREE_SCREEN_ARGS_DECL) 1998{ 1999 SCRN_INFO_PTR(arg); 2000 I810FreeRec(scrn); 2001 if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) 2002 vgaHWFreeHWRec(scrn); 2003} 2004 2005static ModeStatus 2006I810ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 2007{ 2008 SCRN_INFO_PTR(arg); 2009 if (mode->Flags & V_INTERLACE) { 2010 if (verbose) { 2011 xf86DrvMsg(scrn->scrnIndex, X_PROBED, 2012 "Removing interlaced mode \"%s\"\n", mode->name); 2013 } 2014 return MODE_BAD; 2015 } 2016 return MODE_OK; 2017} 2018 2019static Bool 2020I810SaveScreen(ScreenPtr screen, Bool unblack) 2021{ 2022 return vgaHWSaveScreen(screen, unblack); 2023} 2024 2025static void 2026I810DisplayPowerManagementSet(ScrnInfoPtr scrn, int PowerManagementMode, 2027 int flags) 2028{ 2029 I810Ptr pI810; 2030 unsigned char SEQ01 = 0; 2031 int DPMSSyncSelect = 0; 2032 vgaHWPtr hwp; 2033 2034 pI810 = I810PTR(scrn); 2035 switch (PowerManagementMode) { 2036 case DPMSModeOn: 2037 /* Screen: On; HSync: On, VSync: On */ 2038 SEQ01 = 0x00; 2039 DPMSSyncSelect = HSYNC_ON | VSYNC_ON; 2040 break; 2041 case DPMSModeStandby: 2042 /* Screen: Off; HSync: Off, VSync: On */ 2043 SEQ01 = 0x20; 2044 DPMSSyncSelect = HSYNC_OFF | VSYNC_ON; 2045 break; 2046 case DPMSModeSuspend: 2047 /* Screen: Off; HSync: On, VSync: Off */ 2048 SEQ01 = 0x20; 2049 DPMSSyncSelect = HSYNC_ON | VSYNC_OFF; 2050 break; 2051 case DPMSModeOff: 2052 /* Screen: Off; HSync: Off, VSync: Off */ 2053 SEQ01 = 0x20; 2054 DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF; 2055 break; 2056 } 2057 2058 hwp = VGAHWPTR(scrn); 2059 2060 /* Turn the screen on/off */ 2061 SEQ01 |= hwp->readSeq(hwp, 0x01) & ~0x20; 2062 hwp->writeSeq(hwp, 0x01, SEQ01); 2063 2064 /* Set the DPMS mode */ 2065 OUTREG8(DPMS_SYNC_SELECT, DPMSSyncSelect); 2066} 2067 2068const OptionInfoRec * 2069lg_i810_available_options(int chipid, int busid) 2070{ 2071 return I810Options; 2072} 2073 2074 2075Bool lg_i810_init(ScrnInfoPtr scrn) 2076{ 2077 scrn->PreInit = I810PreInit; 2078 scrn->ScreenInit = I810ScreenInit; 2079 scrn->SwitchMode = I810SwitchMode; 2080 scrn->AdjustFrame = I810AdjustFrame; 2081 scrn->EnterVT = I810EnterVT; 2082 scrn->LeaveVT = I810LeaveVT; 2083 scrn->FreeScreen = I810FreeScreen; 2084 scrn->ValidMode = I810ValidMode; 2085 return TRUE; 2086} 2087