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