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