smi_driver.c revision 09885543
1/* Header: //Mercury/Projects/archives/XFree86/4.0/smi_driver.c-arc 1.42 03 Jan 2001 13:52:16 Frido $ */ 2 3/* 4Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved. 5Copyright (C) 2000 Silicon Motion, Inc. All Rights Reserved. 6 7Permission is hereby granted, free of charge, to any person obtaining a copy of 8this software and associated documentation files (the "Software"), to deal in 9the Software without restriction, including without limitation the rights to 10use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 11of the Software, and to permit persons to whom the Software is furnished to do 12so, subject to the following conditions: 13 14The above copyright notice and this permission notice shall be included in all 15copies or substantial portions of the Software. 16 17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- 19NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 24Except as contained in this notice, the names of The XFree86 Project and 25Silicon Motion shall not be used in advertising or otherwise to promote the 26sale, use or other dealings in this Software without prior written 27authorization from The XFree86 Project or Silicon Motion. 28*/ 29/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/siliconmotion/smi_driver.c,v 1.36tsi Exp $ */ 30 31#ifdef HAVE_CONFIG_H 32#include "config.h" 33#endif 34 35#include "xf86Resources.h" 36#include "xf86RAC.h" 37#include "xf86DDC.h" 38#include "xf86int10.h" 39#include "vbe.h" 40#include "shadowfb.h" 41 42#include "smi.h" 43 44#include "globals.h" 45#define DPMS_SERVER 46#include <X11/extensions/dpms.h> 47 48/* 49 * Internals 50 */ 51static void SMI_EnableMmio(ScrnInfoPtr pScrn); 52static void SMI_DisableMmio(ScrnInfoPtr pScrn); 53 54/* 55 * Forward definitions for the functions that make up the driver. 56 */ 57 58static const OptionInfoRec * SMI_AvailableOptions(int chipid, int busid); 59static void SMI_Identify(int flags); 60static Bool SMI_Probe(DriverPtr drv, int flags); 61static Bool SMI_PreInit(ScrnInfoPtr pScrn, int flags); 62static Bool SMI_EnterVT(int scrnIndex, int flags); 63static void SMI_LeaveVT(int scrnIndex, int flags); 64static void SMI_Save (ScrnInfoPtr pScrn); 65static void SMI_WriteMode (ScrnInfoPtr pScrn, vgaRegPtr, SMIRegPtr); 66static Bool SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, 67 char **argv); 68static int SMI_InternalScreenInit(int scrnIndex, ScreenPtr pScreen); 69static void SMI_PrintRegs(ScrnInfoPtr); 70static ModeStatus SMI_ValidMode(int scrnIndex, DisplayModePtr mode, 71 Bool verbose, int flags); 72static void SMI_DisableVideo(ScrnInfoPtr pScrn); 73static void SMI_EnableVideo(ScrnInfoPtr pScrn); 74static Bool SMI_MapMem(ScrnInfoPtr pScrn); 75static void SMI_UnmapMem(ScrnInfoPtr pScrn); 76static Bool SMI_ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); 77static Bool SMI_CloseScreen(int scrnIndex, ScreenPtr pScreen); 78static Bool SMI_SaveScreen(ScreenPtr pScreen, int mode); 79static void SMI_LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies, 80 LOCO *colors, VisualPtr pVisual); 81static void SMI_DisplayPowerManagementSet(ScrnInfoPtr pScrn, 82 int PowerManagementMode, int flags); 83static Bool SMI_ddc1(int scrnIndex); 84static unsigned int SMI_ddc1Read(ScrnInfoPtr pScrn); 85static void SMI_FreeScreen(int ScrnIndex, int flags); 86static void SMI_ProbeDDC(ScrnInfoPtr pScrn, int index); 87static void SMI_DetectPanelSize(ScrnInfoPtr pScrn); 88 89 90#define SILICONMOTION_NAME "Silicon Motion" 91#define SILICONMOTION_DRIVER_NAME "siliconmotion" 92#define SILICONMOTION_VERSION_NAME "1.4.1" 93#define SILICONMOTION_VERSION_MAJOR 1 94#define SILICONMOTION_VERSION_MINOR 4 95#define SILICONMOTION_PATCHLEVEL 1 96#define SILICONMOTION_DRIVER_VERSION ((SILICONMOTION_VERSION_MAJOR << 24) | \ 97 (SILICONMOTION_VERSION_MINOR << 16) | \ 98 (SILICONMOTION_PATCHLEVEL)) 99 100/* 101 * This contains the functions needed by the server after loading the 102 * driver module. It must be supplied, and gets added the driver list by 103 * the Module Setup funtion in the dynamic case. In the static case a 104 * reference to this is compiled in, and this requires that the name of 105 * this DriverRec be an upper-case version of the driver name. 106 */ 107 108_X_EXPORT DriverRec SILICONMOTION = 109{ 110 SILICONMOTION_DRIVER_VERSION, 111 SILICONMOTION_DRIVER_NAME, 112 SMI_Identify, 113 SMI_Probe, 114 SMI_AvailableOptions, 115 NULL, 116 0 117}; 118 119/* Supported chipsets */ 120static SymTabRec SMIChipsets[] = 121{ 122 { PCI_CHIP_SMI910, "Lynx" }, 123 { PCI_CHIP_SMI810, "LynxE" }, 124 { PCI_CHIP_SMI820, "Lynx3D" }, 125 { PCI_CHIP_SMI710, "LynxEM" }, 126 { PCI_CHIP_SMI712, "LynxEM+" }, 127 { PCI_CHIP_SMI720, "Lynx3DM" }, 128 { PCI_CHIP_SMI731, "Cougar3DR" }, 129 { -1, NULL } 130}; 131 132static PciChipsets SMIPciChipsets[] = 133{ 134 /* numChipset, PciID, Resource */ 135 { PCI_CHIP_SMI910, PCI_CHIP_SMI910, RES_SHARED_VGA }, 136 { PCI_CHIP_SMI810, PCI_CHIP_SMI810, RES_SHARED_VGA }, 137 { PCI_CHIP_SMI820, PCI_CHIP_SMI820, RES_SHARED_VGA }, 138 { PCI_CHIP_SMI710, PCI_CHIP_SMI710, RES_SHARED_VGA }, 139 { PCI_CHIP_SMI712, PCI_CHIP_SMI712, RES_SHARED_VGA }, 140 { PCI_CHIP_SMI720, PCI_CHIP_SMI720, RES_SHARED_VGA }, 141 { PCI_CHIP_SMI731, PCI_CHIP_SMI731, RES_SHARED_VGA }, 142 { -1, -1, RES_UNDEFINED } 143}; 144 145typedef enum 146{ 147 OPTION_PCI_BURST, 148 OPTION_FIFO_CONSERV, 149 OPTION_FIFO_MODERATE, 150 OPTION_FIFO_AGGRESSIVE, 151 OPTION_PCI_RETRY, 152 OPTION_NOACCEL, 153 OPTION_MCLK, 154 OPTION_SHOWCACHE, 155 OPTION_SWCURSOR, 156 OPTION_HWCURSOR, 157 OPTION_SHADOW_FB, 158 OPTION_ROTATE, 159 OPTION_VIDEOKEY, 160 OPTION_BYTESWAP, 161 /* CZ 26.10.2001: interlaced video */ 162 OPTION_INTERLACED, 163 /* end CZ */ 164 OPTION_USEBIOS, 165 OPTION_ZOOMONLCD, 166 OPTION_DUALHEAD, 167 OPTION_ACCELMETHOD, 168 NUMBER_OF_OPTIONS 169} SMIOpts; 170 171static const OptionInfoRec SMIOptions[] = 172{ 173 { OPTION_PCI_BURST, "pci_burst", OPTV_BOOLEAN, {0}, FALSE }, 174 { OPTION_FIFO_CONSERV, "fifo_conservative", OPTV_BOOLEAN, {0}, FALSE }, 175 { OPTION_FIFO_MODERATE, "fifo_moderate", OPTV_BOOLEAN, {0}, FALSE }, 176 { OPTION_FIFO_AGGRESSIVE, "fifo_aggressive", OPTV_BOOLEAN, {0}, FALSE }, 177 { OPTION_PCI_RETRY, "pci_retry", OPTV_BOOLEAN, {0}, FALSE }, 178 { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 179 { OPTION_MCLK, "set_mclk", OPTV_FREQ, {0}, FALSE }, 180 { OPTION_SHOWCACHE, "show_cache", OPTV_BOOLEAN, {0}, FALSE }, 181 { OPTION_HWCURSOR, "HWCursor", OPTV_BOOLEAN, {0}, FALSE }, 182 { OPTION_SWCURSOR, "SWCursor", OPTV_BOOLEAN, {0}, FALSE }, 183 { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, 184 { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, 185 { OPTION_VIDEOKEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, 186 { OPTION_BYTESWAP, "ByteSwap", OPTV_BOOLEAN, {0}, FALSE }, 187 /* CZ 26.10.2001: interlaced video */ 188 { OPTION_INTERLACED, "Interlaced", OPTV_BOOLEAN, {0}, FALSE }, 189 /* end CZ */ 190 { OPTION_USEBIOS, "UseBIOS", OPTV_BOOLEAN, {0}, FALSE }, 191 { OPTION_ZOOMONLCD, "ZoomOnLCD", OPTV_BOOLEAN, {0}, FALSE }, 192 { OPTION_DUALHEAD, "Dualhead", OPTV_BOOLEAN, {0}, FALSE }, 193 { OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING, {0}, FALSE }, 194 { -1, NULL, OPTV_NONE, {0}, FALSE } 195}; 196 197/* 198 * Lists of symbols that may/may not be required by this driver. 199 * This allows the loader to know which ones to issue warnings for. 200 * 201 * Note that vgahwSymbols and xaaSymbols are referenced outside the 202 * XFree86LOADER define in later code, so are defined outside of that 203 * define here also. 204 */ 205 206static const char *vgahwSymbols[] = 207{ 208 "vgaHWCopyReg", 209 "vgaHWGetHWRec", 210 "vgaHWGetIOBase", 211 "vgaHWGetIndex", 212 "vgaHWInit", 213 "vgaHWLock", 214 "vgaHWMapMem", 215 "vgaHWProtect", 216 "vgaHWRestore", 217 "vgaHWSave", 218 "vgaHWSaveScreen", 219 "vgaHWSetMmioFuncs", 220 "vgaHWSetStdFuncs", 221 "vgaHWUnmapMem", 222 "vgaHWddc1SetSpeedWeak", 223 NULL 224}; 225 226static const char *xaaSymbols[] = 227{ 228 "XAAGetCopyROP", 229 "XAACreateInfoRec", 230 "XAADestroyInfoRec", 231 "XAAGetFallbackOps", 232 "XAAInit", 233 "XAAGetPatternROP", 234 NULL 235}; 236 237static const char *exaSymbols[] = 238{ 239 "exaDriverAlloc", 240 "exaDriverInit", 241 "exaDriverFini", 242 "exaOffscreenAlloc", 243 "exaOffscreenFree", 244 "exaGetPixmapPitch", 245 "exaGetPixmapOffset", 246 "exaGetPixmapSize", 247 NULL 248}; 249 250static const char *ramdacSymbols[] = 251{ 252 "xf86CreateCursorInfoRec", 253 "xf86DestroyCursorInfoRec", 254 "xf86InitCursor", 255 NULL 256}; 257 258static const char *ddcSymbols[] = 259{ 260 "xf86PrintEDID", 261 "xf86DoEDID_DDC1", 262 "xf86DoEDID_DDC2", 263 "xf86SetDDCproperties", 264 NULL 265}; 266 267static const char *i2cSymbols[] = 268{ 269 "xf86CreateI2CBusRec", 270 "xf86CreateI2CDevRec", 271 "xf86DestroyI2CBusRec", 272 "xf86DestroyI2CDevRec", 273 "xf86I2CBusInit", 274 "xf86I2CDevInit", 275 "xf86I2CReadBytes", 276 "xf86I2CWriteByte", 277 NULL 278}; 279 280static const char *shadowSymbols[] = 281{ 282 "ShadowFBInit", 283 NULL 284}; 285 286static const char *int10Symbols[] = 287{ 288 "xf86ExecX86int10", 289 "xf86FreeInt10", 290 "xf86InitInt10", 291 NULL 292}; 293 294static const char *vbeSymbols[] = 295{ 296 "VBEInit", 297 "vbeDoEDID", 298 "vbeFree", 299 NULL 300}; 301 302static const char *fbSymbols[] = 303{ 304 "fbPictureInit", 305 "fbScreenInit", 306 NULL 307}; 308 309#ifdef XFree86LOADER 310 311static MODULESETUPPROTO(siliconmotionSetup); 312 313static XF86ModuleVersionInfo SMIVersRec = 314{ 315 "siliconmotion", 316 MODULEVENDORSTRING, 317 MODINFOSTRING1, 318 MODINFOSTRING2, 319 XORG_VERSION_CURRENT, 320 SILICONMOTION_VERSION_MAJOR, 321 SILICONMOTION_VERSION_MINOR, 322 SILICONMOTION_PATCHLEVEL, 323 ABI_CLASS_VIDEODRV, 324 ABI_VIDEODRV_VERSION, 325 MOD_CLASS_VIDEODRV, 326 {0, 0, 0, 0} 327}; 328 329/* 330 * This is the module init data for XFree86 modules. 331 * 332 * Its name has to be the driver name followed by ModuleData. 333 */ 334_X_EXPORT XF86ModuleData siliconmotionModuleData = 335{ 336 &SMIVersRec, 337 siliconmotionSetup, 338 NULL 339}; 340 341static pointer 342siliconmotionSetup(pointer module, pointer opts, int *errmaj, int *errmin) 343{ 344 static Bool setupDone = FALSE; 345 346 if (!setupDone) { 347 setupDone = TRUE; 348 xf86AddDriver(&SILICONMOTION, module, 0); 349 350 /* 351 * Modules that this driver always requires can be loaded here 352 * by calling LoadSubModule(). 353 */ 354 355 /* 356 * Tell the loader about symbols from other modules that this module 357 * might refer to. 358 */ 359 LoaderRefSymLists(vgahwSymbols, fbSymbols, xaaSymbols, exaSymbols, ramdacSymbols, 360 ddcSymbols, i2cSymbols, int10Symbols, vbeSymbols, 361 shadowSymbols, NULL); 362 363 /* 364 * The return value must be non-NULL on success even though there 365 * is no TearDownProc. 366 */ 367 return (pointer) 1; 368 369 } else { 370 if (errmaj) { 371 *errmaj = LDR_ONCEONLY; 372 } 373 return NULL; 374 } 375} 376 377#endif /* XFree86LOADER */ 378 379static Bool 380SMI_GetRec(ScrnInfoPtr pScrn) 381{ 382 ENTER_PROC("SMI_GetRec"); 383 384 /* 385 * Allocate an 'Chip'Rec, and hook it into pScrn->driverPrivate. 386 * pScrn->driverPrivate is initialised to NULL, so we can check if 387 * the allocation has already been done. 388 */ 389 if (pScrn->driverPrivate == NULL) { 390 pScrn->driverPrivate = xnfcalloc(sizeof(SMIRec), 1); 391 } 392 393 LEAVE_PROC("SMI_GetRec"); 394 return TRUE; 395} 396 397static void 398SMI_FreeRec(ScrnInfoPtr pScrn) 399{ 400 ENTER_PROC("SMI_FreeRec"); 401 402 if (pScrn->driverPrivate != NULL) { 403 xfree(pScrn->driverPrivate); 404 pScrn->driverPrivate = NULL; 405 } 406 407 LEAVE_PROC("SMI_FreeRec"); 408} 409 410static const OptionInfoRec * 411SMI_AvailableOptions(int chipid, int busid) 412{ 413 ENTER_PROC("SMI_AvailableOptions"); 414 LEAVE_PROC("SMI_AvailableOptions"); 415 return SMIOptions; 416} 417 418static void 419SMI_Identify(int flags) 420{ 421 ENTER_PROC("SMI_Identify"); 422 423 xf86PrintChipsets(SILICONMOTION_NAME, "driver (version " 424 SILICONMOTION_VERSION_NAME ") for Silicon Motion Lynx chipsets", 425 SMIChipsets); 426 427 LEAVE_PROC("SMI_Identify"); 428} 429 430static Bool 431SMI_Probe(DriverPtr drv, int flags) 432{ 433 int i; 434 GDevPtr *devSections; 435 int *usedChips; 436 int numDevSections; 437 int numUsed; 438 Bool foundScreen = FALSE; 439 440 ENTER_PROC("SMI_Probe"); 441 442 numDevSections = xf86MatchDevice(SILICONMOTION_DRIVER_NAME, &devSections); 443 444 if (numDevSections <= 0) { 445 /* There's no matching device section in the config file, so quit now. */ 446 LEAVE_PROC("SMI_Probe"); 447 return FALSE; 448 } 449 450 if (xf86GetPciVideoInfo() == NULL) { 451 LEAVE_PROC("SMI_Probe"); 452 return FALSE; 453 } 454 455 numUsed = xf86MatchPciInstances(SILICONMOTION_NAME, PCI_SMI_VENDOR_ID, 456 SMIChipsets, SMIPciChipsets, devSections, 457 numDevSections, drv, &usedChips); 458 459 /* Free it since we don't need that list after this */ 460 xfree(devSections); 461 if (numUsed <= 0) { 462 LEAVE_PROC("SMI_Probe"); 463 return FALSE; 464 } 465 466 if (flags & PROBE_DETECT) { 467 foundScreen = TRUE; 468 } else { 469 for (i = 0; i < numUsed; i++) { 470 /* Allocate a ScrnInfoRec and claim the slot */ 471 ScrnInfoPtr pScrn = xf86AllocateScreen(drv, 0); 472 473 /* Fill in what we can of the ScrnInfoRec */ 474 pScrn->driverVersion = SILICONMOTION_DRIVER_VERSION; 475 pScrn->driverName = SILICONMOTION_DRIVER_NAME; 476 pScrn->name = SILICONMOTION_NAME; 477 pScrn->Probe = SMI_Probe; 478 pScrn->PreInit = SMI_PreInit; 479 pScrn->ScreenInit = SMI_ScreenInit; 480 pScrn->SwitchMode = SMI_SwitchMode; 481 pScrn->AdjustFrame = SMI_AdjustFrame; 482 pScrn->EnterVT = SMI_EnterVT; 483 pScrn->LeaveVT = SMI_LeaveVT; 484 pScrn->FreeScreen = SMI_FreeScreen; 485 pScrn->ValidMode = SMI_ValidMode; 486 foundScreen = TRUE; 487 488 xf86ConfigActivePciEntity(pScrn, usedChips[i], SMIPciChipsets, NULL, 489 NULL, NULL, NULL, NULL); 490 } 491 } 492 xfree(usedChips); 493 494 LEAVE_PROC("SMI_Probe"); 495 return foundScreen; 496} 497 498static Bool 499SMI_PreInit(ScrnInfoPtr pScrn, int flags) 500{ 501 EntityInfoPtr pEnt; 502 SMIPtr pSmi; 503 MessageType from; 504 int i; 505 double real; 506 ClockRangePtr clockRanges; 507 char *s; 508 unsigned char config, m, n, shift; 509 int mclk; 510 vgaHWPtr hwp; 511 int vgaCRIndex, vgaIOBase; 512 vbeInfoPtr pVbe = NULL; 513 514 ENTER_PROC("SMI_PreInit"); 515 516 if (flags & PROBE_DETECT) { 517 SMI_ProbeDDC(pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index); 518 LEAVE_PROC("SMI_PreInit"); 519 return TRUE; 520 } 521 522 /* Ignoring the Type list for now. It might be needed when multiple cards 523 * are supported. 524 */ 525 if (pScrn->numEntities > 1) { 526 LEAVE_PROC("SMI_PreInit"); 527 return FALSE; 528 } 529 530 /* The vgahw module should be loaded here when needed */ 531 if (!xf86LoadSubModule(pScrn, "vgahw")) { 532 LEAVE_PROC("SMI_PreInit"); 533 return FALSE; 534 } 535 536 xf86LoaderReqSymLists(vgahwSymbols, NULL); 537 538 /* 539 * Allocate a vgaHWRec 540 */ 541 if (!vgaHWGetHWRec(pScrn)) { 542 LEAVE_PROC("SMI_PreInit"); 543 return FALSE; 544 } 545 546 /* Allocate the SMIRec driverPrivate */ 547 if (!SMI_GetRec(pScrn)) { 548 LEAVE_PROC("SMI_PreInit"); 549 return FALSE; 550 } 551 pSmi = SMIPTR(pScrn); 552 553 /* Set pScrn->monitor */ 554 pScrn->monitor = pScrn->confScreen->monitor; 555 556 /* 557 * The first thing we should figure out is the depth, bpp, etc. 558 */ 559 if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb)) { 560 LEAVE_PROC("SMI_PreInit"); 561 return FALSE; 562 } 563 564 /* Check that the returned depth is one we support */ 565 switch (pScrn->depth) { 566 case 8: 567 case 16: 568 case 24: 569 /* OK */ 570 break; 571 572 default: 573 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 574 "Given depth (%d) is not supported by this driver\n", 575 pScrn->depth); 576 LEAVE_PROC("SMI_PreInit"); 577 return FALSE; 578 } 579 580 xf86PrintDepthBpp(pScrn); 581 582 /* 583 * This must happen after pScrn->display has been set because 584 * xf86SetWeight references it. 585 */ 586 if (pScrn->depth > 8) { 587 /* The defaults are OK for us */ 588 rgb zeros = {0, 0, 0}; 589 590 if (!xf86SetWeight(pScrn, zeros, zeros)) { 591 LEAVE_PROC("SMI_PreInit"); 592 return FALSE; 593 } 594 } 595 596 if (!xf86SetDefaultVisual(pScrn, -1)) { 597 LEAVE_PROC("SMI_PreInit"); 598 return FALSE; 599 } 600 601 /* We don't currently support DirectColor at > 8bpp */ 602 if ((pScrn->depth > 8) && (pScrn->defaultVisual != TrueColor)) { 603 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual (%s) " 604 "is not supported at depth %d\n", 605 xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); 606 LEAVE_PROC("SMI_PreInit"); 607 return FALSE; 608 } 609 610 /* We use a programmable clock */ 611 pScrn->progClock = TRUE; 612 613 /* Collect all of the relevant option flags (fill in pScrn->options) */ 614 xf86CollectOptions(pScrn, NULL); 615 616 /* Set the bits per RGB for 8bpp mode */ 617 if (pScrn->depth == 8) { 618 pScrn->rgbBits = 6; 619 } 620 621 /* Process the options */ 622 if (!(pSmi->Options = xalloc(sizeof(SMIOptions)))) 623 return FALSE; 624 memcpy(pSmi->Options, SMIOptions, sizeof(SMIOptions)); 625 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pSmi->Options); 626 627 if (xf86ReturnOptValBool(pSmi->Options, OPTION_PCI_BURST, FALSE)) { 628 pSmi->pci_burst = TRUE; 629 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: pci_burst - PCI burst " 630 "read enabled\n"); 631 } else { 632 pSmi->pci_burst = FALSE; 633 } 634 635 pSmi->NoPCIRetry = TRUE; 636 if (xf86ReturnOptValBool(pSmi->Options, OPTION_PCI_RETRY, FALSE)) { 637 if (xf86ReturnOptValBool(pSmi->Options, OPTION_PCI_BURST, FALSE)) { 638 pSmi->NoPCIRetry = FALSE; 639 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: pci_retry\n"); 640 } else { 641 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"pci_retry\" option " 642 "requires \"pci_burst\".\n"); 643 } 644 } 645 646 if (xf86IsOptionSet(pSmi->Options, OPTION_FIFO_CONSERV)) { 647 pSmi->fifo_conservative = TRUE; 648 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: fifo_conservative " 649 "set\n"); 650 } else { 651 pSmi->fifo_conservative = FALSE; 652 } 653 654 if (xf86IsOptionSet(pSmi->Options, OPTION_FIFO_MODERATE)) { 655 pSmi->fifo_moderate = TRUE; 656 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: fifo_moderate set\n"); 657 } else { 658 pSmi->fifo_moderate = FALSE; 659 } 660 661 if (xf86IsOptionSet(pSmi->Options, OPTION_FIFO_AGGRESSIVE)) { 662 pSmi->fifo_aggressive = TRUE; 663 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: fifo_aggressive set\n"); 664 } else { 665 pSmi->fifo_aggressive = FALSE; 666 } 667 668 if (xf86ReturnOptValBool(pSmi->Options, OPTION_NOACCEL, FALSE)) { 669 pSmi->NoAccel = TRUE; 670 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: NoAccel - Acceleration " 671 "disabled\n"); 672 } else { 673 pSmi->NoAccel = FALSE; 674 } 675 676 if (xf86ReturnOptValBool(pSmi->Options, OPTION_SHOWCACHE, FALSE)) { 677 pSmi->ShowCache = TRUE; 678 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: show_cache set\n"); 679 } else { 680 pSmi->ShowCache = FALSE; 681 } 682 683 if (xf86GetOptValFreq(pSmi->Options, OPTION_MCLK, OPTUNITS_MHZ, &real)) { 684 pSmi->MCLK = (int)(real * 1000.0); 685 if (pSmi->MCLK <= 120000) { 686 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: set_mclk set to " 687 "%1.3f MHz\n", pSmi->MCLK / 1000.0); 688 } else { 689 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Memory Clock value of " 690 "%1.3f MHz is larger than limit of 120 MHz\n", 691 pSmi->MCLK / 1000.0); 692 pSmi->MCLK = 0; 693 } 694 } else { 695 pSmi->MCLK = 0; 696 } 697 698 from = X_DEFAULT; 699 pSmi->hwcursor = TRUE; 700 if (xf86GetOptValBool(pSmi->Options, OPTION_HWCURSOR, &pSmi->hwcursor)) { 701 from = X_CONFIG; 702 } 703 if (xf86ReturnOptValBool(pSmi->Options, OPTION_SWCURSOR, FALSE)) { 704 pSmi->hwcursor = FALSE; 705 from = X_CONFIG; 706 } 707 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s Cursor\n", 708 pSmi->hwcursor ? "Hardware" : "Software"); 709 710 if (xf86GetOptValBool(pSmi->Options, OPTION_SHADOW_FB, &pSmi->shadowFB)) { 711 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowFB %s.\n", 712 pSmi->shadowFB ? "enabled" : "disabled"); 713 } 714 715#if 1 /* PDR#932 */ 716 if ((pScrn->depth == 8) || (pScrn->depth == 16)) 717#endif /* PDR#932 */ 718 if ((s = xf86GetOptValString(pSmi->Options, OPTION_ROTATE))) { 719 if (!xf86NameCmp(s, "CW")) { 720 pSmi->shadowFB = TRUE; 721 pSmi->rotate = SMI_ROTATE_CCW; 722 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen " 723 "clockwise\n"); 724 } else if (!xf86NameCmp(s, "CCW")) { 725 pSmi->shadowFB = TRUE; 726 pSmi->rotate = SMI_ROTATE_CW; 727 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen counter " 728 "clockwise\n"); 729 } else { 730 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid " 731 "value for Option \"Rotate\"\n", s); 732 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Valid options are \"CW\" or " 733 "\"CCW\"\n"); 734 } 735 } 736 737 if (pSmi->rotate) { 738 /* Disable the RandR extension, it messes up the internal rotation stuff */ 739 xf86DisableRandR(); 740 } 741 742 if (xf86GetOptValInteger(pSmi->Options, OPTION_VIDEOKEY, &pSmi->videoKey)) { 743 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: Video key set to " 744 "0x%08X\n", pSmi->videoKey); 745 } else { 746 pSmi->videoKey = (1 << pScrn->offset.red) | 747 (1 << pScrn->offset.green) | 748 (((pScrn->mask.blue >> pScrn->offset.blue) - 1) 749 << pScrn->offset.blue); 750 } 751 752 if (xf86ReturnOptValBool(pSmi->Options, OPTION_BYTESWAP, FALSE)) { 753 pSmi->ByteSwap = TRUE; 754 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: ByteSwap enabled.\n"); 755 } else { 756 pSmi->ByteSwap = FALSE; 757 } 758 759 /* CZ 26.10.2001: interlaced video */ 760 if (xf86ReturnOptValBool(pSmi->Options, OPTION_INTERLACED, FALSE)) { 761 pSmi->interlaced = TRUE; 762 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: Interlaced enabled.\n"); 763 } else { 764 pSmi->interlaced = FALSE; 765 } 766 /* end CZ */ 767 768 if (xf86GetOptValBool(pSmi->Options, OPTION_USEBIOS, &pSmi->useBIOS)) { 769 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: UseBIOS %s.\n", 770 pSmi->useBIOS ? "enabled" : "disabled"); 771 } else { 772 /* Default to UseBIOS enabled. */ 773 pSmi->useBIOS = TRUE; 774 } 775 776 if (xf86GetOptValBool(pSmi->Options, OPTION_ZOOMONLCD, &pSmi->zoomOnLCD)) { 777 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: ZoomOnLCD %s.\n", 778 pSmi->zoomOnLCD ? "enabled" : "disabled"); 779 } else { 780 /* Default to ZoomOnLCD enabled. */ 781 pSmi->zoomOnLCD = TRUE; 782 } 783 784 /* Find the PCI slot for this screen */ 785 pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 786 if ((pEnt->location.type != BUS_PCI) || (pEnt->resources)) { 787 xfree(pEnt); 788 SMI_FreeRec(pScrn); 789 LEAVE_PROC("SMI_PreInit"); 790 return FALSE; 791 } 792 793 if (xf86LoadSubModule(pScrn,"int10")) { 794 xf86LoaderReqSymLists(int10Symbols,NULL); 795 pSmi->pInt10 = xf86InitInt10(pEnt->index); 796 } 797 798 if (pSmi->pInt10 && xf86LoadSubModule(pScrn, "vbe")) { 799 xf86LoaderReqSymLists(vbeSymbols, NULL); 800 pVbe = VBEInit(pSmi->pInt10, pEnt->index); 801 } 802 803 pSmi->PciInfo = xf86GetPciInfoForEntity(pEnt->index); 804 xf86RegisterResources(pEnt->index, NULL, ResExclusive); 805/* xf86SetOperatingState(resVgaIo, pEnt->index, ResUnusedOpr); */ 806/* xf86SetOperatingState(resVgaMem, pEnt->index, ResDisableOpr); */ 807 808 /* 809 * Set the Chipset and ChipRev, allowing config file entries to 810 * override. 811 */ 812 if (pEnt->device->chipset && *pEnt->device->chipset) { 813 pScrn->chipset = pEnt->device->chipset; 814 pSmi->Chipset = xf86StringToToken(SMIChipsets, pScrn->chipset); 815 from = X_CONFIG; 816 } else if (pEnt->device->chipID >= 0) { 817 pSmi->Chipset = pEnt->device->chipID; 818 pScrn->chipset = (char *) xf86TokenToString(SMIChipsets, pSmi->Chipset); 819 from = X_CONFIG; 820 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", 821 pSmi->Chipset); 822 } else { 823 from = X_PROBED; 824 pSmi->Chipset = pSmi->PciInfo->chipType; 825 pScrn->chipset = (char *) xf86TokenToString(SMIChipsets, pSmi->Chipset); 826 } 827 828 if (pEnt->device->chipRev >= 0) { 829 pSmi->ChipRev = pEnt->device->chipRev; 830 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 831 pSmi->ChipRev); 832 } else { 833 pSmi->ChipRev = pSmi->PciInfo->chipRev; 834 } 835 xfree(pEnt); 836 837 /* 838 * This shouldn't happen because such problems should be caught in 839 * SMI_Probe(), but check it just in case. 840 */ 841 if (pScrn->chipset == NULL) { 842 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ChipID 0x%04X is not " 843 "recognised\n", pSmi->Chipset); 844 LEAVE_PROC("SMI_PreInit"); 845 return FALSE; 846 } 847 848 if (pSmi->Chipset < 0) { 849 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Chipset \"%s\" is not " 850 "recognised\n", pScrn->chipset); 851 LEAVE_PROC("SMI_PreInit"); 852 return FALSE; 853 } 854 855 xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset); 856 857 pSmi->PciTag = pciTag(pSmi->PciInfo->bus, pSmi->PciInfo->device, 858 pSmi->PciInfo->func); 859 860 pSmi->Dualhead = FALSE; 861 if (xf86ReturnOptValBool(pSmi->Options, OPTION_DUALHEAD, FALSE) && 862 SMI_LYNXM_SERIES(pSmi->Chipset)) { 863 pSmi->Dualhead = TRUE; 864 } 865 866 /* tweak options for dualhead */ 867 if (pSmi->Dualhead) { 868 pSmi->useBIOS = FALSE; 869 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "UseBIOS disabled in dualhead mode\n"); 870 pSmi->hwcursor = FALSE; 871 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No hardware cursor in dualhead mode\n"); 872 if (pScrn->bitsPerPixel != 16) { 873 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Dualhead only supported at " 874 "depth 16\n"); 875 return FALSE; 876 } 877 } 878 879 SMI_MapMem(pScrn); 880 SMI_DisableVideo(pScrn); 881 882 hwp = VGAHWPTR(pScrn); 883 vgaIOBase = hwp->IOBase; 884 vgaCRIndex = vgaIOBase + VGA_CRTC_INDEX_OFFSET; 885 pSmi->PIOBase = hwp->PIOOffset; 886 887 xf86ErrorFVerb(VERBLEV, "\tSMI_PreInit vgaCRIndex=%x, vgaIOBase=%x, " 888 "MMIOBase=%p\n", vgaCRIndex, vgaIOBase, hwp->MMIOBase); 889 890 /* detect the panel size */ 891 SMI_DetectPanelSize(pScrn); 892 893 if (xf86LoadSubModule(pScrn, "i2c")) { 894 xf86LoaderReqSymLists(i2cSymbols, NULL); 895 SMI_I2CInit(pScrn); 896 } 897 898 if (xf86LoadSubModule(pScrn, "ddc")) { 899 xf86MonPtr pMon = NULL; 900 901 xf86LoaderReqSymLists(ddcSymbols, NULL); 902#if 1 /* PDR#579 */ 903 if (pVbe) { 904 pMon = vbeDoEDID(pVbe, NULL); 905 if (pMon != NULL) { 906 if ((pMon->rawData[0] == 0x00) && 907 (pMon->rawData[1] == 0xFF) && 908 (pMon->rawData[2] == 0xFF) && 909 (pMon->rawData[3] == 0xFF) && 910 (pMon->rawData[4] == 0xFF) && 911 (pMon->rawData[5] == 0xFF) && 912 (pMon->rawData[6] == 0xFF) && 913 (pMon->rawData[7] == 0x00)) { 914 pMon = xf86PrintEDID(pMon); 915 if (pMon != NULL) { 916 xf86SetDDCproperties(pScrn, pMon); 917 } 918 } 919 } 920#else 921 if ((pVbe) && 922 ((pMon = xf86PrintEDID(vbeDoEDID(pVbe, NULL))) != NULL)) { 923 xf86SetDDCproperties(pScrn, pMon); 924#endif 925 } else if (!SMI_ddc1(pScrn->scrnIndex)) { 926 if (pSmi->I2C) { 927 xf86SetDDCproperties(pScrn, 928 xf86PrintEDID(xf86DoEDID_DDC2(pScrn->scrnIndex, 929 pSmi->I2C))); 930 } 931 } 932 } 933 934 vbeFree(pVbe); 935 xf86FreeInt10(pSmi->pInt10); 936 pSmi->pInt10 = NULL; 937 938 /* 939 * If the driver can do gamma correction, it should call xf86SetGamma() 940 * here. (from MGA, no ViRGE gamma support yet, but needed for 941 * xf86HandleColormaps support.) 942 */ 943 { 944 Gamma zeros = { 0.0, 0.0, 0.0 }; 945 946 if (!xf86SetGamma(pScrn, zeros)) { 947 LEAVE_PROC("SMI_PreInit"); 948 SMI_EnableVideo(pScrn); 949 SMI_UnmapMem(pScrn); 950 return FALSE; 951 } 952 } 953 954 955 /* Next go on to detect amount of installed ram */ 956 config = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x71); 957 958 /* And compute the amount of video memory and offscreen memory */ 959 pSmi->videoRAMKBytes = 0; 960 961 if (!pScrn->videoRam) { 962 switch (pSmi->Chipset) { 963 default: 964 { 965 int mem_table[4] = { 1, 2, 4, 0 }; 966 pSmi->videoRAMKBytes = mem_table[(config >> 6)] * 1024; 967 break; 968 } 969 case SMI_LYNX3D: 970 { 971 int mem_table[4] = { 0, 2, 4, 6 }; 972 pSmi->videoRAMKBytes = mem_table[(config >> 6)] * 1024 + 512; 973 break; 974 } 975 case SMI_LYNX3DM: 976 { 977 int mem_table[4] = { 16, 2, 4, 8 }; 978 pSmi->videoRAMKBytes = mem_table[(config >> 6)] * 1024; 979 break; 980 } 981 case SMI_COUGAR3DR: 982 { 983 /* DANGER - Cougar3DR BIOS is broken - hardcode video ram size */ 984 /* per instructions from Silicon Motion engineers */ 985 pSmi->videoRAMKBytes = 16 * 1024; 986 break; 987 } 988 } 989 pSmi->videoRAMBytes = pSmi->videoRAMKBytes * 1024; 990 pScrn->videoRam = pSmi->videoRAMKBytes; 991 992 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "videoram: %dkB\n", 993 pSmi->videoRAMKBytes); 994 } else { 995 pSmi->videoRAMKBytes = pScrn->videoRam; 996 pSmi->videoRAMBytes = pScrn->videoRam * 1024; 997 998 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "videoram: %dk\n", 999 pSmi->videoRAMKBytes); 1000 } 1001 1002 /* Detect current MCLK and print it for user */ 1003 m = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A); 1004 n = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B); 1005 switch (n >> 6) { 1006 default: 1007 shift = 1; 1008 break; 1009 case 1: 1010 shift = 4; 1011 break; 1012 case 2: 1013 shift = 2; 1014 break; 1015 } 1016 n &= 0x3F; 1017 mclk = ((1431818 * m) / n / shift + 50) / 100; 1018 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected current MCLK value of " 1019 "%1.3f MHz\n", mclk / 1000.0); 1020 1021 SMI_EnableVideo(pScrn); 1022 SMI_UnmapMem(pScrn); 1023 1024 pSmi->IsSwitching = FALSE; 1025 1026 if (pSmi->Dualhead) { 1027 pScrn->display->virtualX = 2 * pSmi->lcdWidth; 1028 pScrn->display->virtualY = pSmi->lcdHeight; 1029 } 1030 1031 pScrn->virtualX = pScrn->display->virtualX; 1032 1033 /* 1034 * Setup the ClockRanges, which describe what clock ranges are available, 1035 * and what sort of modes they can be used for. 1036 */ 1037 clockRanges = xnfcalloc(sizeof(ClockRange),1); 1038 clockRanges->next = NULL; 1039 clockRanges->minClock = 20000; 1040 1041 if ((pSmi->Chipset == SMI_LYNX3DM) || (pSmi->Chipset == SMI_COUGAR3DR)) 1042 clockRanges->maxClock = 200000; 1043 else 1044 clockRanges->maxClock = 135000; 1045 1046 clockRanges->clockIndex = -1; 1047 clockRanges->interlaceAllowed = FALSE; 1048 clockRanges->doubleScanAllowed = FALSE; 1049 1050 i = xf86ValidateModes( 1051 pScrn, /* Screen pointer */ 1052 pScrn->monitor->Modes, /* Available monitor modes */ 1053 pScrn->display->modes, /* req mode names for screen */ 1054 clockRanges, /* list of clock ranges allowed */ 1055 NULL, /* use min/max below */ 1056 128, /* min line pitch (width) */ 1057 4096, /* maximum line pitch (width) */ 1058 128, /* bits of granularity for line pitch */ 1059 /* (width) above */ 1060 128, /* min virtual height */ 1061 4096, /* max virtual height */ 1062 pScrn->display->virtualX, /* force virtual x */ 1063 pScrn->display->virtualY, /* force virtual Y */ 1064 pSmi->videoRAMBytes, /* size of aperture used to access */ 1065 /* video memory */ 1066 LOOKUP_BEST_REFRESH); /* how to pick modes */ 1067 1068 if (i == -1) { 1069 SMI_FreeRec(pScrn); 1070 LEAVE_PROC("SMI_PreInit"); 1071 return FALSE; 1072 } 1073 1074 /* Prune the modes marked as invalid */ 1075 xf86PruneDriverModes(pScrn); 1076 1077 if ((i == 0) || (pScrn->modes == NULL)) { 1078 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 1079 SMI_FreeRec(pScrn); 1080 LEAVE_PROC("SMI_PreInit"); 1081 return FALSE; 1082 } 1083 xf86SetCrtcForModes(pScrn, 0); 1084 1085 /* Set the current mode to the first in the list */ 1086 pScrn->currentMode = pScrn->modes; 1087 1088 /* Print the list of modes being used */ 1089 xf86PrintModes(pScrn); 1090 1091 /* Set display resolution */ 1092 xf86SetDpi(pScrn, 0, 0); 1093 1094 if ((xf86LoadSubModule(pScrn, "fb") == NULL)) { 1095 SMI_FreeRec(pScrn); 1096 LEAVE_PROC("SMI_PreInit"); 1097 return FALSE; 1098 } 1099 1100 if (!pSmi->NoAccel) { 1101 from = X_DEFAULT; 1102 char *strptr; 1103 1104 if ((strptr = (char *)xf86GetOptValString(pSmi->Options, OPTION_ACCELMETHOD))) { 1105 if (!xf86NameCmp(strptr,"XAA")) { 1106 from = X_CONFIG; 1107 pSmi->useEXA = FALSE; 1108 } else if(!xf86NameCmp(strptr,"EXA")) { 1109 from = X_CONFIG; 1110 pSmi->useEXA = TRUE; 1111 } 1112 } 1113 1114 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration architecture\n", 1115 pSmi->useEXA ? "EXA" : "XAA"); 1116 } 1117 1118 xf86LoaderReqSymLists(fbSymbols, NULL); 1119 1120 /* Load XAA or EXA if needed */ 1121 if (!pSmi->NoAccel) { 1122 if (!pSmi->useEXA) { 1123 if (!xf86LoadSubModule(pScrn, "xaa")) { 1124 SMI_FreeRec(pScrn); 1125 LEAVE_PROC("SMI_PreInit"); 1126 return FALSE; 1127 } 1128 xf86LoaderReqSymLists(xaaSymbols, NULL); 1129 } else { 1130 XF86ModReqInfo req; 1131 int errmaj, errmin; 1132 1133 memset(&req, 0, sizeof(XF86ModReqInfo)); 1134 req.majorversion = 2; 1135 req.minorversion = 0; 1136 1137 if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, 1138 &req, &errmaj, &errmin)) { 1139 LoaderErrorMsg(NULL, "exa", errmaj, errmin); 1140 SMI_FreeRec(pScrn); 1141 LEAVE_PROC("SMI_PreInit"); 1142 return FALSE; 1143 } 1144 xf86LoaderReqSymLists(exaSymbols, NULL); 1145 } 1146 } 1147 1148 /* Load ramdac if needed */ 1149 if (pSmi->hwcursor) { 1150 if (!xf86LoadSubModule(pScrn, "ramdac")) { 1151 SMI_FreeRec(pScrn); 1152 LEAVE_PROC("SMI_PreInit"); 1153 return FALSE; 1154 } 1155 xf86LoaderReqSymLists(ramdacSymbols, NULL); 1156 } 1157 1158 if (pSmi->shadowFB) { 1159 if (!xf86LoadSubModule(pScrn, "shadowfb")) { 1160 SMI_FreeRec(pScrn); 1161 LEAVE_PROC("SMI_PreInit"); 1162 return FALSE; 1163 } 1164 xf86LoaderReqSymLists(shadowSymbols, NULL); 1165 } 1166 1167 LEAVE_PROC("SMI_PreInit"); 1168 return TRUE; 1169} 1170 1171/* 1172 * This is called when VT switching back to the X server. Its job is to 1173 * reinitialise the video mode. We may wish to unmap video/MMIO memory too. 1174 */ 1175 1176static Bool 1177SMI_EnterVT(int scrnIndex, int flags) 1178{ 1179 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1180 SMIPtr pSmi = SMIPTR(pScrn); 1181 Bool ret; 1182 1183 ENTER_PROC("SMI_EnterVT"); 1184 1185 /* Enable MMIO and map memory */ 1186 SMI_MapMem(pScrn); 1187 SMI_Save(pScrn); 1188 1189 /* #670 */ 1190 if (pSmi->shadowFB) { 1191 pSmi->FBOffset = pSmi->savedFBOffset; 1192 pSmi->FBReserved = pSmi->savedFBReserved; 1193 } 1194 1195 ret = SMI_ModeInit(pScrn, pScrn->currentMode); 1196 1197 /* #670 */ 1198 if (ret && pSmi->shadowFB) { 1199 BoxRec box; 1200 1201 /* #920 */ 1202 if (pSmi->paletteBuffer) { 1203 int i; 1204 1205 VGAOUT8(pSmi, VGA_DAC_WRITE_ADDR, 0); 1206 for (i = 0; i < 256 * 3; i++) { 1207 VGAOUT8(pSmi, VGA_DAC_DATA, pSmi->paletteBuffer[i]); 1208 } 1209 xfree(pSmi->paletteBuffer); 1210 pSmi->paletteBuffer = NULL; 1211 } 1212 1213 if (pSmi->pSaveBuffer) { 1214 memcpy(pSmi->FBBase, pSmi->pSaveBuffer, pSmi->saveBufferSize); 1215 xfree(pSmi->pSaveBuffer); 1216 pSmi->pSaveBuffer = NULL; 1217 } 1218 1219 box.x1 = 0; 1220 box.y1 = 0; 1221 box.x2 = pScrn->virtualY; 1222 box.y2 = pScrn->virtualX; 1223 if (pSmi->Chipset == SMI_COUGAR3DR) { 1224 SMI_RefreshArea730(pScrn, 1, &box); 1225 } else { 1226 SMI_RefreshArea(pScrn, 1, &box); 1227 } 1228 } 1229 1230 /* Reset the grapics engine */ 1231 if (!pSmi->NoAccel) 1232 SMI_EngineReset(pScrn); 1233 1234 LEAVE_PROC("SMI_EnterVT"); 1235 return ret; 1236} 1237 1238/* 1239 * This is called when VT switching away from the X server. Its job is to 1240 * restore the previous (text) mode. We may wish to remap video/MMIO memory 1241 * too. 1242 */ 1243 1244static void 1245SMI_LeaveVT(int scrnIndex, int flags) 1246{ 1247 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1248 vgaHWPtr hwp = VGAHWPTR(pScrn); 1249 SMIPtr pSmi = SMIPTR(pScrn); 1250 vgaRegPtr vgaSavePtr = &hwp->SavedReg; 1251 SMIRegPtr SMISavePtr = &pSmi->SavedReg; 1252 1253 ENTER_PROC("SMI_LeaveVT"); 1254 1255 /* #670 */ 1256 if (pSmi->shadowFB) { 1257 pSmi->pSaveBuffer = xnfalloc(pSmi->saveBufferSize); 1258 if (pSmi->pSaveBuffer) { 1259 memcpy(pSmi->pSaveBuffer, pSmi->FBBase, pSmi->saveBufferSize); 1260 } 1261 1262 pSmi->savedFBOffset = pSmi->FBOffset; 1263 pSmi->savedFBReserved = pSmi->FBReserved; 1264 1265 /* #920 */ 1266 if (pSmi->Bpp == 1) { 1267 pSmi->paletteBuffer = xnfalloc(256 * 3); 1268 if (pSmi->paletteBuffer) { 1269 int i; 1270 1271 VGAOUT8(pSmi, VGA_DAC_READ_ADDR, 0); 1272 for (i = 0; i < 256 * 3; i++) { 1273 pSmi->paletteBuffer[i] = VGAIN8(pSmi, VGA_DAC_DATA); 1274 } 1275 } 1276 } 1277 } 1278 1279 memset(pSmi->FBBase, 0, 256 * 1024); /* #689 */ 1280 SMI_WriteMode(pScrn, vgaSavePtr, SMISavePtr); 1281 SMI_UnmapMem(pScrn); 1282 1283 LEAVE_PROC("SMI_LeaveVT"); 1284} 1285 1286/* 1287 * This function performs the inverse of the restore function: It saves all the 1288 * standard and extended registers that we are going to modify to set up a video 1289 * mode. 1290 */ 1291 1292static void 1293SMI_Save(ScrnInfoPtr pScrn) 1294{ 1295 int i; 1296 CARD32 offset; 1297 1298 vgaHWPtr hwp = VGAHWPTR(pScrn); 1299 vgaRegPtr vgaSavePtr = &hwp->SavedReg; 1300 SMIPtr pSmi = SMIPTR(pScrn); 1301 SMIRegPtr save = &pSmi->SavedReg; 1302 1303 int vgaIOBase = hwp->IOBase; 1304 int vgaCRIndex = vgaIOBase + VGA_CRTC_INDEX_OFFSET; 1305 int vgaCRData = vgaIOBase + VGA_CRTC_DATA_OFFSET; 1306 1307 ENTER_PROC("SMI_Save"); 1308 1309 /* Save the standard VGA registers */ 1310 vgaHWSave(pScrn, vgaSavePtr, VGA_SR_ALL); 1311 save->smiDACMask = VGAIN8(pSmi, VGA_DAC_MASK); 1312 VGAOUT8(pSmi, VGA_DAC_READ_ADDR, 0); 1313 for (i = 0; i < 256; i++) { 1314 save->smiDacRegs[i][0] = VGAIN8(pSmi, VGA_DAC_DATA); 1315 save->smiDacRegs[i][1] = VGAIN8(pSmi, VGA_DAC_DATA); 1316 save->smiDacRegs[i][2] = VGAIN8(pSmi, VGA_DAC_DATA); 1317 } 1318 for (i = 0, offset = 2; i < 8192; i++, offset += 8) { 1319 save->smiFont[i] = *(pSmi->FBBase + offset); 1320 } 1321 1322 /* Now we save all the extended registers we need. */ 1323 save->SR17 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x17); 1324 save->SR18 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x18); 1325 save->SR21 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21); 1326 save->SR31 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31); 1327 save->SR32 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x32); 1328 save->SR6A = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A); 1329 save->SR6B = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B); 1330 save->SR81 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81); 1331 save->SRA0 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0xA0); 1332 1333 /* vclk1 */ 1334 save->SR6C = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6C); 1335 save->SR6D = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6D); 1336 /* vclk1 control */ 1337 save->SR68 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x68); 1338 1339 if (pSmi->Dualhead) { 1340 /* dualhead stuff */ 1341 save->SR22 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x22); 1342 save->SR40 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x40); 1343 save->SR41 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x41); 1344 save->SR42 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x42); 1345 save->SR43 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x43); 1346 save->SR44 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x44); 1347 save->SR45 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x45); 1348 save->SR48 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x48); 1349 save->SR49 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x49); 1350 save->SR4A = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4A); 1351 save->SR4B = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4B); 1352 save->SR4C = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4C); 1353 /* PLL2 stuff */ 1354 save->SR69 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x69); 1355 save->SR6E = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6E); 1356 save->SR6F = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6F); 1357 } 1358 1359 if (SMI_LYNXM_SERIES(pSmi->Chipset)) { 1360 /* Save primary registers */ 1361 save->CR90[14] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E); 1362 VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E, save->CR90[14] & ~0x20); 1363 1364 for (i = 0; i < 16; i++) { 1365 save->CR90[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x90 + i); 1366 } 1367 save->CR33 = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33); 1368 save->CR3A = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x3A); 1369 for (i = 0; i < 14; i++) { 1370 save->CR40[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i); 1371 } 1372 1373 /* Save secondary registers */ 1374 VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E, save->CR90[14] | 0x20); 1375 save->CR33_2 = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33); 1376 for (i = 0; i < 14; i++) { 1377 save->CR40_2[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i); 1378 } 1379 save->CR9F_2 = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9F); 1380 1381 /* Save common registers */ 1382 for (i = 0; i < 14; i++) { 1383 save->CRA0[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0xA0 + i); 1384 } 1385 1386 /* PDR#1069 */ 1387 VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E, save->CR90[14]); 1388 } else { 1389 save->CR33 = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33); 1390 save->CR3A = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x3A); 1391 for (i = 0; i < 14; i++) { 1392 save->CR40[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i); 1393 } 1394 } 1395 1396 /* CZ 2.11.2001: for gamma correction (TODO: other chipsets?) */ 1397 if ((pSmi->Chipset == SMI_LYNX3DM) || (pSmi->Chipset == SMI_COUGAR3DR)) { 1398 save->CCR66 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x66); 1399 } 1400 /* end CZ */ 1401 1402 save->DPR10 = READ_DPR(pSmi, 0x10); 1403 save->DPR1C = READ_DPR(pSmi, 0x1C); 1404 save->DPR20 = READ_DPR(pSmi, 0x20); 1405 save->DPR24 = READ_DPR(pSmi, 0x24); 1406 save->DPR28 = READ_DPR(pSmi, 0x28); 1407 save->DPR2C = READ_DPR(pSmi, 0x2C); 1408 save->DPR30 = READ_DPR(pSmi, 0x30); 1409 save->DPR3C = READ_DPR(pSmi, 0x3C); 1410 save->DPR40 = READ_DPR(pSmi, 0x40); 1411 save->DPR44 = READ_DPR(pSmi, 0x44); 1412 1413 save->VPR00 = READ_VPR(pSmi, 0x00); 1414 save->VPR0C = READ_VPR(pSmi, 0x0C); 1415 save->VPR10 = READ_VPR(pSmi, 0x10); 1416 1417 if (pSmi->Chipset == SMI_COUGAR3DR) { 1418 save->FPR00_ = READ_FPR(pSmi, FPR00); 1419 save->FPR0C_ = READ_FPR(pSmi, FPR0C); 1420 save->FPR10_ = READ_FPR(pSmi, FPR10); 1421 } 1422 1423 save->CPR00 = READ_CPR(pSmi, 0x00); 1424 1425 if (!pSmi->ModeStructInit) { 1426 /* XXX Should check the return value of vgaHWCopyReg() */ 1427 vgaHWCopyReg(&hwp->ModeReg, vgaSavePtr); 1428 memcpy(&pSmi->ModeReg, save, sizeof(SMIRegRec)); 1429 pSmi->ModeStructInit = TRUE; 1430 } 1431 1432 if (pSmi->useBIOS && (pSmi->pInt10 != NULL)) { 1433 pSmi->pInt10->num = 0x10; 1434 pSmi->pInt10->ax = 0x0F00; 1435 xf86ExecX86int10(pSmi->pInt10); 1436 save->mode = pSmi->pInt10->ax & 0x007F; 1437 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Current mode 0x%02X.\n", 1438 save->mode); 1439 } 1440 1441 if (xf86GetVerbosity() > 1) { 1442 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1443 "Saved current video mode. Register dump:\n"); 1444 SMI_PrintRegs(pScrn); 1445 } 1446 1447 LEAVE_PROC("SMI_Save"); 1448} 1449 1450/* 1451 * This function is used to restore a video mode. It writes out all of the 1452 * standard VGA and extended registers needed to setup a video mode. 1453 */ 1454 1455static void 1456SMI_WriteMode(ScrnInfoPtr pScrn, vgaRegPtr vgaSavePtr, SMIRegPtr restore) 1457{ 1458 int i; 1459 CARD8 tmp; 1460 CARD32 offset; 1461 1462 vgaHWPtr hwp = VGAHWPTR(pScrn); 1463 SMIPtr pSmi = SMIPTR(pScrn); 1464 int vgaIOBase = hwp->IOBase; 1465 int vgaCRIndex = vgaIOBase + VGA_CRTC_INDEX_OFFSET; 1466 int vgaCRData = vgaIOBase + VGA_CRTC_DATA_OFFSET; 1467 1468 ENTER_PROC("SMI_WriteMode"); 1469 1470 vgaHWProtect(pScrn, TRUE); 1471 1472 /* Wait for engine to become idle */ 1473 if (pSmi->IsSwitching) 1474 WaitIdle(); 1475 1476 if (pSmi->useBIOS && (pSmi->pInt10 != NULL) && (restore->mode != 0)) { 1477 pSmi->pInt10->num = 0x10; 1478 pSmi->pInt10->ax = restore->mode | 0x80; 1479 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting mode 0x%02X\n", 1480 restore->mode); 1481 xf86ExecX86int10(pSmi->pInt10); 1482 1483 /* Enable linear mode. */ 1484 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18); 1485 tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA); 1486 outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp | 0x01); 1487 1488 /* Enable DPR/VPR registers. */ 1489 tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21); 1490 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, tmp & ~0x03); 1491 } else { 1492 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x17, restore->SR17); 1493 tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x18) & ~0x1F; 1494 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x18, tmp | 1495 (restore->SR18 & 0x1F)); 1496 tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21); 1497 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, tmp & ~0x03); 1498 tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31) & ~0xC0; 1499 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31, tmp | 1500 (restore->SR31 & 0xC0)); 1501 tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x32) & ~0x07; 1502 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x32, tmp | 1503 (restore->SR32 & 0x07)); 1504 if (restore->SR6B != 0xFF) { 1505 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A, restore->SR6A); 1506 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B, restore->SR6B); 1507 } 1508 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81, restore->SR81); 1509 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0xA0, restore->SRA0); 1510 1511 /* Restore the standard VGA registers */ 1512 vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_ALL); 1513 if (restore->smiDACMask) { 1514 VGAOUT8(pSmi, VGA_DAC_MASK, restore->smiDACMask); 1515 } else { 1516 VGAOUT8(pSmi, VGA_DAC_MASK, 0xFF); 1517 } 1518 VGAOUT8(pSmi, VGA_DAC_WRITE_ADDR, 0); 1519 for (i = 0; i < 256; i++) { 1520 VGAOUT8(pSmi, VGA_DAC_DATA, restore->smiDacRegs[i][0]); 1521 VGAOUT8(pSmi, VGA_DAC_DATA, restore->smiDacRegs[i][1]); 1522 VGAOUT8(pSmi, VGA_DAC_DATA, restore->smiDacRegs[i][2]); 1523 } 1524 for (i = 0, offset = 2; i < 8192; i++, offset += 8) { 1525 *(pSmi->FBBase + offset) = restore->smiFont[i]; 1526 } 1527 1528 if (SMI_LYNXM_SERIES(pSmi->Chipset)) { 1529 /* Restore secondary registers */ 1530 VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E, 1531 restore->CR90[14] | 0x20); 1532 1533 VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33, restore->CR33_2); 1534 for (i = 0; i < 14; i++) { 1535 VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i, 1536 restore->CR40_2[i]); 1537 } 1538 VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9F, restore->CR9F_2); 1539 1540 /* Restore primary registers */ 1541 VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E, 1542 restore->CR90[14] & ~0x20); 1543 1544 VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33, restore->CR33); 1545 VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x3A, restore->CR3A); 1546 for (i = 0; i < 14; i++) { 1547 VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i, 1548 restore->CR40[i]); 1549 } 1550 for (i = 0; i < 16; i++) { 1551 if (i != 14) { 1552 VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x90 + i, 1553 restore->CR90[i]); 1554 } 1555 } 1556 VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E, restore->CR90[14]); 1557 1558 /* Restore common registers */ 1559 for (i = 0; i < 14; i++) { 1560 VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0xA0 + i, 1561 restore->CRA0[i]); 1562 } 1563 } 1564 1565 /* Restore the standard VGA registers */ 1566 if (xf86IsPrimaryPci(pSmi->PciInfo)) { 1567 vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_CMAP | VGA_SR_FONTS); 1568 } 1569 1570 if (restore->modeInit) 1571 vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_ALL); 1572 1573 if (!SMI_LYNXM_SERIES(pSmi->Chipset)) { 1574 VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33, restore->CR33); 1575 VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x3A, restore->CR3A); 1576 for (i = 0; i < 14; i++) { 1577 VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i, 1578 restore->CR40[i]); 1579 } 1580 } 1581 1582 /* vclk1 */ 1583 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x68, restore->SR68); 1584 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6C, restore->SR6C); 1585 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6D, restore->SR6D); 1586 1587 if (pSmi->Dualhead) { 1588 1589 /* TFT panel uses FIFO1, DSTN panel uses FIFO1 for upper panel and 1590 * FIFO2 for lower panel. I don't have a DSTN panel, so it's untested. 1591 * -- AGD 1592 */ 1593 1594 /* PLL2 regs */ 1595 1596 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x69, restore->SR69); 1597 1598 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6E, restore->SR6E); 1599 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6F, restore->SR6F); 1600 1601 /* setting SR21 bit 2 disables ZV circuitry, 1602 * if ZV is needed, SR21 = 0x20 1603 */ 1604 /* enable DAC, PLL, etc. */ 1605 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, restore->SR21); 1606 1607 /* clear DPMS state */ 1608 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x22, restore->SR22); 1609 1610 /* enable virtual refresh and LCD and CRT outputs */ 1611 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31, restore->SR31); 1612 1613 /* FIFO1 Read Offset */ 1614 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x44, restore->SR44); 1615 /* FIFO2 Read Offset */ 1616 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4B, restore->SR4B); 1617 /* FIFO1/2 Read Offset overflow */ 1618 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4C, restore->SR4C); 1619 1620 /* FIFO Write Offset */ 1621 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x48, restore->SR48); 1622 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x49, restore->SR49); 1623 1624 /* set FIFO levels */ 1625 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4A, restore->SR4A); 1626 1627 VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33, restore->CR33); 1628 1629 } 1630 } 1631 1632 /* CZ 2.11.2001: for gamma correction (TODO: other chipsets?) */ 1633 if ((pSmi->Chipset == SMI_LYNX3DM) || (pSmi->Chipset == SMI_COUGAR3DR)) { 1634 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x66, restore->CCR66); 1635 } 1636 /* end CZ */ 1637 1638 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81, 0x00); 1639 1640 /* Reset the graphics engine */ 1641 WRITE_DPR(pSmi, 0x10, restore->DPR10); 1642 WRITE_DPR(pSmi, 0x1C, restore->DPR1C); 1643 WRITE_DPR(pSmi, 0x20, restore->DPR20); 1644 WRITE_DPR(pSmi, 0x24, restore->DPR24); 1645 WRITE_DPR(pSmi, 0x28, restore->DPR28); 1646 WRITE_DPR(pSmi, 0x2C, restore->DPR2C); 1647 WRITE_DPR(pSmi, 0x30, restore->DPR30); 1648 WRITE_DPR(pSmi, 0x3C, restore->DPR3C); 1649 WRITE_DPR(pSmi, 0x40, restore->DPR40); 1650 WRITE_DPR(pSmi, 0x44, restore->DPR44); 1651 1652 /* write video controller regs */ 1653 WRITE_VPR(pSmi, 0x00, restore->VPR00); 1654 WRITE_VPR(pSmi, 0x0C, restore->VPR0C); 1655 WRITE_VPR(pSmi, 0x10, restore->VPR10); 1656 1657 if(pSmi->Chipset == SMI_COUGAR3DR) { 1658 WRITE_FPR(pSmi, FPR00, restore->FPR00_); 1659 WRITE_FPR(pSmi, FPR0C, restore->FPR0C_); 1660 WRITE_FPR(pSmi, FPR10, restore->FPR10_); 1661 } 1662 1663 WRITE_CPR(pSmi, 0x00, restore->CPR00); 1664 1665 if (xf86GetVerbosity() > 1) { 1666 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1667 "Done restoring mode. Register dump:\n"); 1668 SMI_PrintRegs(pScrn); 1669 } 1670 1671 vgaHWProtect(pScrn, FALSE); 1672 1673 LEAVE_PROC("SMI_WriteMode"); 1674} 1675 1676static void 1677SMI_DetectPanelSize(ScrnInfoPtr pScrn) 1678{ 1679 SMIPtr pSmi = SMIPTR(pScrn); 1680 1681 /* panel size detection ... requires BIOS call on 730 hardware */ 1682 if (pSmi->Chipset == SMI_COUGAR3DR) { 1683 if (pSmi->pInt10 != NULL) { 1684 pSmi->pInt10->num = 0x10; 1685 pSmi->pInt10->ax = 0x5F00; 1686 pSmi->pInt10->bx = 0; 1687 pSmi->pInt10->cx = 0; 1688 pSmi->pInt10->dx = 0; 1689 xf86ExecX86int10(pSmi->pInt10); 1690 if (pSmi->pInt10->ax == 0x005F) { 1691 switch (pSmi->pInt10->cx & 0x0F) { 1692 case PANEL_640x480: 1693 pSmi->lcdWidth = 640; 1694 pSmi->lcdHeight = 480; 1695 break; 1696 case PANEL_800x600: 1697 pSmi->lcdWidth = 800; 1698 pSmi->lcdHeight = 600; 1699 break; 1700 case PANEL_1024x768: 1701 pSmi->lcdWidth = 1024; 1702 pSmi->lcdHeight = 768; 1703 break; 1704 case PANEL_1280x1024: 1705 pSmi->lcdWidth = 1280; 1706 pSmi->lcdHeight = 1024; 1707 break; 1708 case PANEL_1600x1200: 1709 pSmi->lcdWidth = 1600; 1710 pSmi->lcdHeight = 1200; 1711 break; 1712 case PANEL_1400x1050: 1713 pSmi->lcdWidth = 1400; 1714 pSmi->lcdHeight = 1050; 1715 break; 1716 } 1717 1718 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Detected panel size via BIOS: %d x %d\n", 1719 pSmi->lcdWidth, pSmi->lcdHeight); 1720 } else { 1721 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS error during 730 panel detection!\n"); 1722 pSmi->lcdWidth = pScrn->virtualX; 1723 pSmi->lcdHeight = pScrn->virtualY; 1724 } 1725 } else { 1726 /* int10 support isn't setup on the second call to this function, 1727 so if this is the second call, don't do detection again */ 1728 if (pSmi->lcd == 0) { 1729 /* If we get here, int10 support is not loaded or not working */ 1730 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No BIOS support for 730 panel detection!\n"); 1731 pSmi->lcdWidth = pScrn->virtualX; 1732 pSmi->lcdHeight = pScrn->virtualY; 1733 } 1734 } 1735 1736 /* Set this to indicate that we've done the detection */ 1737 pSmi->lcd = 1; 1738 } else { 1739 /* panel size detection for hardware other than 730 */ 1740 pSmi->lcd = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31) & 0x01; 1741 1742 if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x30) & 0x01) { 1743 pSmi->lcd <<= 1; 1744 } 1745 switch (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x30) & 0x0C) { 1746 case 0x00: 1747 pSmi->lcdWidth = 640; 1748 pSmi->lcdHeight = 480; 1749 break; 1750 case 0x04: 1751 pSmi->lcdWidth = 800; 1752 pSmi->lcdHeight = 600; 1753 break; 1754 case 0x08: 1755 if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x74) & 0x02) { 1756 pSmi->lcdWidth = 1024; 1757 pSmi->lcdHeight = 600; 1758 } else { 1759 pSmi->lcdWidth = 1024; 1760 pSmi->lcdHeight = 768; 1761 } 1762 break; 1763 case 0x0C: 1764 pSmi->lcdWidth = 1280; 1765 pSmi->lcdHeight = 1024; 1766 break; 1767 } 1768 } 1769 1770 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s Panel Size = %dx%d\n", 1771 (pSmi->lcd == 0) ? "OFF" : (pSmi->lcd == 1) ? "TFT" : "DSTN", 1772 pSmi->lcdWidth, pSmi->lcdHeight); 1773 1774} 1775 1776static Bool 1777SMI_MapMem(ScrnInfoPtr pScrn) 1778{ 1779 SMIPtr pSmi = SMIPTR(pScrn); 1780 vgaHWPtr hwp; 1781 CARD32 memBase; 1782 1783 ENTER_PROC("SMI_MapMem"); 1784 1785 /* Map the Lynx register space */ 1786 switch (pSmi->Chipset) { 1787 default: 1788 memBase = pSmi->PciInfo->memBase[0] + 0x400000; 1789 pSmi->MapSize = 0x10000; 1790 break; 1791 case SMI_COUGAR3DR: 1792 memBase = pSmi->PciInfo->memBase[1]; 1793 pSmi->MapSize = 0x200000; 1794 break; 1795 case SMI_LYNX3D: 1796 memBase = pSmi->PciInfo->memBase[0] + 0x680000; 1797 pSmi->MapSize = 0x180000; 1798 break; 1799 case SMI_LYNXEM: 1800 case SMI_LYNXEMplus: 1801 memBase = pSmi->PciInfo->memBase[0] + 0x400000; 1802 pSmi->MapSize = 0x400000; 1803 break; 1804 case SMI_LYNX3DM: 1805 memBase = pSmi->PciInfo->memBase[0]; 1806 pSmi->MapSize = 0x200000; 1807 break; 1808 } 1809 pSmi->MapBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, pSmi->PciTag, 1810 memBase, pSmi->MapSize); 1811 1812 if (pSmi->MapBase == NULL) { 1813 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Internal error: could not map " 1814 "MMIO registers.\n"); 1815 LEAVE_PROC("SMI_MapMem"); 1816 return FALSE; 1817 } 1818 1819 switch (pSmi->Chipset) { 1820 default: 1821 pSmi->DPRBase = pSmi->MapBase + 0x8000; 1822 pSmi->VPRBase = pSmi->MapBase + 0xC000; 1823 pSmi->CPRBase = pSmi->MapBase + 0xE000; 1824 pSmi->IOBase = NULL; 1825 pSmi->DataPortBase = pSmi->MapBase; 1826 pSmi->DataPortSize = 0x8000; 1827 break; 1828 case SMI_COUGAR3DR: 1829 pSmi->DPRBase = pSmi->MapBase + 0x000000; 1830 pSmi->VPRBase = pSmi->MapBase + 0x000800; 1831 pSmi->CPRBase = pSmi->MapBase + 0x001000; 1832 pSmi->FPRBase = pSmi->MapBase + 0x005800; 1833 pSmi->IOBase = pSmi->MapBase + 0x0C0000; 1834 pSmi->DataPortBase = pSmi->MapBase + 0x100000; 1835 pSmi->DataPortSize = 0x100000; 1836 break; 1837 case SMI_LYNX3D: 1838 pSmi->DPRBase = pSmi->MapBase + 0x000000; 1839 pSmi->VPRBase = pSmi->MapBase + 0x000800; 1840 pSmi->CPRBase = pSmi->MapBase + 0x001000; 1841 pSmi->IOBase = pSmi->MapBase + 0x040000; 1842 pSmi->DataPortBase = pSmi->MapBase + 0x080000; 1843 pSmi->DataPortSize = 0x100000; 1844 break; 1845 case SMI_LYNXEM: 1846 case SMI_LYNXEMplus: 1847 pSmi->DPRBase = pSmi->MapBase + 0x008000; 1848 pSmi->VPRBase = pSmi->MapBase + 0x00C000; 1849 pSmi->CPRBase = pSmi->MapBase + 0x00E000; 1850 pSmi->IOBase = pSmi->MapBase + 0x300000; 1851 pSmi->DataPortBase = pSmi->MapBase /*+ 0x100000*/; 1852 pSmi->DataPortSize = 0x8000 /*0x200000*/; 1853 break; 1854 case SMI_LYNX3DM: 1855 pSmi->DPRBase = pSmi->MapBase + 0x000000; 1856 pSmi->VPRBase = pSmi->MapBase + 0x000800; 1857 pSmi->CPRBase = pSmi->MapBase + 0x001000; 1858 pSmi->IOBase = pSmi->MapBase + 0x0C0000; 1859 pSmi->DataPortBase = pSmi->MapBase + 0x100000; 1860 pSmi->DataPortSize = 0x100000; 1861 break; 1862 } 1863 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1864 "Physical MMIO at 0x%08lX\n", (unsigned long)memBase); 1865 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1866 "Logical MMIO at %p - %p\n", pSmi->MapBase, 1867 pSmi->MapBase + pSmi->MapSize - 1); 1868 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1869 "DPR=%p, VPR=%p, IOBase=%p\n", 1870 pSmi->DPRBase, pSmi->VPRBase, pSmi->IOBase); 1871 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1872 "DataPort=%p - %p\n", pSmi->DataPortBase, 1873 pSmi->DataPortBase + pSmi->DataPortSize - 1); 1874 1875 pScrn->memPhysBase = pSmi->PciInfo->memBase[0]; 1876 1877 SMI_EnableMmio(pScrn); 1878 1879 if (pSmi->videoRAMBytes) { 1880 /* Map the frame buffer */ 1881 if (pSmi->Chipset == SMI_LYNX3DM) 1882 pSmi->fbMapOffset = 0x200000; 1883 else 1884 pSmi->fbMapOffset = 0x0; 1885 1886 pSmi->FBOffset = 0; 1887 1888 pScrn->fbOffset = pSmi->FBOffset + pSmi->fbMapOffset; 1889 1890 pSmi->FBBase = xf86MapPciMem(pScrn->scrnIndex, 1891 VIDMEM_FRAMEBUFFER, 1892 pSmi->PciTag, 1893 pScrn->memPhysBase + pSmi->fbMapOffset, 1894 pSmi->videoRAMBytes); 1895 1896 if (pSmi->FBBase == NULL) { 1897 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Internal error: could not " 1898 "map framebuffer.\n"); 1899 LEAVE_PROC("SMI_MapMem"); 1900 return FALSE; 1901 } 1902 1903 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1904 "Physical frame buffer at 0x%08lX offset: 0x%08lX\n", 1905 pScrn->memPhysBase, pScrn->fbOffset); 1906 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1907 "Logical frame buffer at %p - %p\n", pSmi->FBBase, 1908 pSmi->FBBase + pSmi->videoRAMBytes - 1); 1909 1910 /* Set up offset to hwcursor memory area. It's a 1K chunk at the end of 1911 * the frame buffer. 1912 */ 1913 pSmi->FBCursorOffset = pSmi->videoRAMBytes - 1024; 1914 1915 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1916 "Cursor Offset: %08lX\n", 1917 (unsigned long)pSmi->FBCursorOffset); 1918 1919 /* set up the fifo reserved space */ 1920 if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x30) & 0x01)/* #1074 */ { 1921 CARD32 fifoOffset = 0; 1922 fifoOffset |= VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x46) << 3; 1923 fifoOffset |= VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x47) << 11; 1924 fifoOffset |= (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x49) 1925 & 0x1C) << 17; 1926 pSmi->FBReserved = fifoOffset; /* PDR#1074 */ 1927 } else { 1928 pSmi->FBReserved = pSmi->videoRAMBytes - 2048; 1929 } 1930 1931 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reserved: %08lX\n", 1932 (unsigned long)pSmi->FBReserved); 1933 1934 } 1935 1936 /* Assign hwp->MemBase & IOBase here */ 1937 hwp = VGAHWPTR(pScrn); 1938 if (pSmi->IOBase != NULL) { 1939 vgaHWSetMmioFuncs(hwp, pSmi->MapBase, pSmi->IOBase - pSmi->MapBase); 1940 } 1941 vgaHWGetIOBase(hwp); 1942 1943 /* Map the VGA memory when the primary video */ 1944 if (xf86IsPrimaryPci(pSmi->PciInfo)) { 1945 hwp->MapSize = 0x10000; 1946 if (!vgaHWMapMem(pScrn)) { 1947 LEAVE_PROC("SMI_MapMem"); 1948 return FALSE; 1949 } 1950 pSmi->PrimaryVidMapped = TRUE; 1951 } 1952 1953 LEAVE_PROC("SMI_MapMem"); 1954 return TRUE; 1955} 1956 1957/* UnMapMem - contains half of pre-4.0 EnterLeave function. The EnterLeave 1958 * function which en/disable access to IO ports and ext. regs 1959 */ 1960 1961static void 1962SMI_UnmapMem(ScrnInfoPtr pScrn) 1963{ 1964 SMIPtr pSmi = SMIPTR(pScrn); 1965 1966 ENTER_PROC("SMI_UnmapMem"); 1967 1968 /* Unmap VGA mem if mapped. */ 1969 if (pSmi->PrimaryVidMapped) { 1970 vgaHWUnmapMem(pScrn); 1971 pSmi->PrimaryVidMapped = FALSE; 1972 } 1973 1974 SMI_DisableMmio(pScrn); 1975 1976 xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pSmi->MapBase, pSmi->MapSize); 1977 if (pSmi->FBBase != NULL) { 1978 xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pSmi->FBBase, 1979 pSmi->videoRAMBytes); 1980 } 1981 1982 LEAVE_PROC("SMI_UnmapMem"); 1983} 1984 1985/* This gets called at the start of each server generation. */ 1986 1987static Bool 1988SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) 1989{ 1990 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1991 SMIPtr pSmi = SMIPTR(pScrn); 1992 EntityInfoPtr pEnt; 1993 1994 ENTER_PROC("SMI_ScreenInit"); 1995 1996 /* Map MMIO regs and framebuffer */ 1997 if (!SMI_MapMem(pScrn)) { 1998 LEAVE_PROC("SMI_ScreenInit"); 1999 return FALSE; 2000 } 2001 2002 pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 2003 2004 if (!pSmi->pInt10) { 2005 pSmi->pInt10 = xf86InitInt10(pEnt->index); 2006 } 2007 2008 /* Save the chip/graphics state */ 2009 SMI_Save(pScrn); 2010 2011 /* Zero the frame buffer, #258 */ 2012 memset(pSmi->FBBase, 0, pSmi->videoRAMBytes); 2013 2014 /* Initialize the first mode */ 2015 if (!SMI_ModeInit(pScrn, pScrn->currentMode)) { 2016 LEAVE_PROC("SMI_ScreenInit"); 2017 return FALSE; 2018 } 2019 2020 /* 2021 * The next step is to setup the screen's visuals, and initialise the 2022 * framebuffer code. In cases where the framebuffer's default choises for 2023 * things like visual layouts and bits per RGB are OK, this may be as simple 2024 * as calling the framebuffer's ScreenInit() function. If not, the visuals 2025 * will need to be setup before calling a fb ScreenInit() function and fixed 2026 * up after. 2027 */ 2028 2029 /* 2030 * Reset the visual list. 2031 */ 2032 miClearVisualTypes(); 2033 2034 /* Setup the visuals we support. */ 2035 2036 if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth), 2037 pScrn->rgbBits, pScrn->defaultVisual)) { 2038 LEAVE_PROC("SMI_ScreenInit"); 2039 return FALSE; 2040 } 2041 if (!miSetPixmapDepths ()) return FALSE; 2042 2043 if (!SMI_InternalScreenInit(scrnIndex, pScreen)) { 2044 LEAVE_PROC("SMI_ScreenInit"); 2045 return FALSE; 2046 } 2047 2048 xf86SetBlackWhitePixels(pScreen); 2049 2050 if (pScrn->bitsPerPixel > 8) { 2051 VisualPtr visual; 2052 /* Fixup RGB ordering */ 2053 visual = pScreen->visuals + pScreen->numVisuals; 2054 while (--visual >= pScreen->visuals) { 2055 if ((visual->class | DynamicClass) == DirectColor) { 2056 visual->offsetRed = pScrn->offset.red; 2057 visual->offsetGreen = pScrn->offset.green; 2058 visual->offsetBlue = pScrn->offset.blue; 2059 visual->redMask = pScrn->mask.red; 2060 visual->greenMask = pScrn->mask.green; 2061 visual->blueMask = pScrn->mask.blue; 2062 } 2063 } 2064 } 2065 2066 /* must be after RGB ordering fixed */ 2067 fbPictureInit(pScreen, 0, 0); 2068 2069 /* CZ 18.06.2001: moved here from smi_accel.c to have offscreen 2070 framebuffer in NoAccel mode */ 2071 if (!pSmi->useEXA) { 2072 int numLines, maxLines; 2073 BoxRec AvailFBArea; 2074 2075 maxLines = pSmi->FBReserved / (pSmi->width * pSmi->Bpp); 2076 if (pSmi->rotate) { 2077 numLines = maxLines; 2078 } else { 2079 /* CZ 3.11.2001: What does the following code? see also smi_video.c aaa line 1226 */ 2080/*#if SMI_USE_VIDEO */ 2081#if 0 2082 numLines = ((pSmi->FBReserved - pSmi->width * pSmi->Bpp 2083 * pSmi->height) * 25 / 100 + pSmi->width 2084 * pSmi->Bpp - 1) / (pSmi->width * pSmi->Bpp); 2085 numLines += pSmi->height; 2086#else 2087 numLines = maxLines; 2088#endif 2089 } 2090 2091 AvailFBArea.x1 = 0; 2092 AvailFBArea.y1 = 0; 2093 AvailFBArea.x2 = pSmi->width; 2094 AvailFBArea.y2 = numLines; 2095 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2096 "FrameBuffer Box: %d,%d - %d,%d\n", 2097 AvailFBArea.x1, AvailFBArea.y1, AvailFBArea.x2, 2098 AvailFBArea.y2); 2099 xf86InitFBManager(pScreen, &AvailFBArea); 2100 } 2101 /* end CZ */ 2102 2103 2104 /* Initialize acceleration layer */ 2105 if (!pSmi->NoAccel) { 2106 if (!pSmi->useEXA) { 2107 if (!SMI_XAAInit(pScreen)) { 2108 LEAVE_PROC("SMI_ScreenInit"); 2109 return FALSE; 2110 } 2111 } else { 2112 if (!SMI_EXAInit(pScreen)) { 2113 LEAVE_PROC("SMI_ScreenInit"); 2114 return FALSE; 2115 } 2116 } 2117 } 2118 2119 miInitializeBackingStore(pScreen); 2120 2121 /* hardware cursor needs to wrap this layer */ 2122 if(!pSmi->NoAccel && !pSmi->useEXA) 2123 SMI_DGAInit(pScreen); 2124 2125 /* Initialise cursor functions */ 2126 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 2127 2128 /* Initialize HW cursor layer. Must follow software cursor 2129 * initialization. 2130 */ 2131 if (pSmi->hwcursor) { 2132 if (!SMI_HWCursorInit(pScreen)) { 2133 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Hardware cursor " 2134 "initialization failed\n"); 2135 } 2136 } 2137 2138 if (pSmi->shadowFB) { 2139 RefreshAreaFuncPtr refreshArea; 2140 2141 if (pSmi->Chipset == SMI_COUGAR3DR) { 2142 refreshArea = SMI_RefreshArea730; 2143 } else { 2144 refreshArea = SMI_RefreshArea; 2145 } 2146 2147 if (pSmi->rotate) { 2148 if (pSmi->PointerMoved == NULL) { 2149 pSmi->PointerMoved = pScrn->PointerMoved; 2150 pScrn->PointerMoved = SMI_PointerMoved; 2151 } 2152 } 2153 2154 ShadowFBInit(pScreen, refreshArea); 2155 } 2156 2157 /* Initialise default colormap */ 2158 if (!miCreateDefColormap(pScreen)) { 2159 LEAVE_PROC("SMI_ScreenInit"); 2160 return FALSE; 2161 } 2162 2163 /* Initialize colormap layer. Must follow initialization of the default 2164 * colormap. And SetGamma call, else it will load palette with solid white. 2165 */ 2166 /* CZ 2.11.2001: CMAP_PALETTED_TRUECOLOR for gamma correction */ 2167 if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, SMI_LoadPalette, NULL, 2168 CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR)) { 2169 LEAVE_PROC("SMI_ScreenInit"); 2170 return FALSE; 2171 } 2172 2173 pScreen->SaveScreen = SMI_SaveScreen; 2174 pSmi->CloseScreen = pScreen->CloseScreen; 2175 pScreen->CloseScreen = SMI_CloseScreen; 2176 2177 if (!xf86DPMSInit(pScreen, SMI_DisplayPowerManagementSet, 0)) { 2178 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DPMS initialization failed!\n"); 2179 } 2180 2181 if (!pSmi->Dualhead) 2182 SMI_InitVideo(pScreen); 2183 else 2184 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No overlay in dualhead mode\n"); 2185 2186 /* Report any unused options (only for the first generation) */ 2187 if (serverGeneration == 1) { 2188 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 2189 } 2190 2191 LEAVE_PROC("SMI_ScreenInit"); 2192 return TRUE; 2193} 2194 2195/* Common init routines needed in EnterVT and ScreenInit */ 2196 2197static int 2198SMI_InternalScreenInit(int scrnIndex, ScreenPtr pScreen) 2199{ 2200 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 2201 SMIPtr pSmi = SMIPTR(pScrn); 2202 int width, height, displayWidth; 2203 int bytesPerPixel = pScrn->bitsPerPixel / 8; 2204 int xDpi, yDpi; 2205 int ret; 2206 2207 ENTER_PROC("SMI_InternalScreenInit"); 2208 2209 if (pSmi->rotate) { 2210 width = pScrn->virtualY; 2211 height = pScrn->virtualX; 2212 xDpi = pScrn->yDpi; 2213 yDpi = pScrn->xDpi; 2214 displayWidth = ((width * bytesPerPixel + 15) & ~15) / bytesPerPixel; 2215 } else { 2216 width = pScrn->virtualX; 2217 height = pScrn->virtualY; 2218 xDpi = pScrn->xDpi; 2219 yDpi = pScrn->yDpi; 2220 displayWidth = pScrn->displayWidth; 2221 } 2222 2223 if (pSmi->shadowFB) { 2224 pSmi->ShadowWidth = width; 2225 pSmi->ShadowHeight = height; 2226 pSmi->ShadowWidthBytes = (width * bytesPerPixel + 15) & ~15; 2227 if (bytesPerPixel == 3) { 2228 pSmi->ShadowPitch = ((height * 3) << 16) 2229 | pSmi->ShadowWidthBytes; 2230 } else { 2231 pSmi->ShadowPitch = (height << 16) 2232 | (pSmi->ShadowWidthBytes / bytesPerPixel); 2233 } 2234 2235 pSmi->saveBufferSize = pSmi->ShadowWidthBytes * pSmi->ShadowHeight; 2236 pSmi->FBReserved -= pSmi->saveBufferSize; 2237 pSmi->FBReserved &= ~0x15; 2238 WRITE_VPR(pSmi, 0x0C, (pSmi->FBOffset = pSmi->FBReserved) >> 3); 2239 if (pSmi->Chipset == SMI_COUGAR3DR) { 2240 WRITE_FPR(pSmi, FPR0C, (pSmi->FBOffset = pSmi->FBReserved) >> 3); 2241 } 2242 pScrn->fbOffset = pSmi->FBOffset + pSmi->fbMapOffset; 2243 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2244 "Shadow: width=%d height=%d " 2245 "offset=0x%08lX pitch=0x%08X\n", 2246 pSmi->ShadowWidth, pSmi->ShadowHeight, 2247 (unsigned long)pSmi->FBOffset, 2248 pSmi->ShadowPitch); 2249 } else { 2250 pSmi->FBOffset = 0; 2251 pScrn->fbOffset = pSmi->FBOffset + pSmi->fbMapOffset; 2252 } 2253 2254 /* 2255 * Call the framebuffer layer's ScreenInit function, and fill in other 2256 * pScreen fields. 2257 */ 2258 2259 DEBUG((VERBLEV, "\tInitializing FB @ 0x%08X for %dx%d (%d)\n", 2260 pSmi->FBBase, width, height, displayWidth)); 2261 switch (pScrn->bitsPerPixel) { 2262 case 8: 2263 case 16: 2264 case 24: 2265 case 32: 2266 ret = fbScreenInit(pScreen, pSmi->FBBase, width, height, xDpi, 2267 yDpi, displayWidth, pScrn->bitsPerPixel); 2268 break; 2269 default: 2270 xf86DrvMsg(scrnIndex, X_ERROR, "Internal error: invalid bpp (%d) " 2271 "in SMI_InternalScreenInit\n", pScrn->bitsPerPixel); 2272 LEAVE_PROC("SMI_InternalScreenInit"); 2273 return FALSE; 2274 } 2275 2276 LEAVE_PROC("SMI_InternalScreenInit"); 2277 return ret; 2278} 2279 2280/* Checks if a mode is suitable for the selected configuration. */ 2281static ModeStatus 2282SMI_ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) 2283{ 2284 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 2285 SMIPtr pSmi = SMIPTR(pScrn); 2286 float refresh; 2287 2288 ENTER_PROC("SMI_ValidMode"); 2289 refresh = (mode->VRefresh > 0) ? mode->VRefresh 2290 : mode->Clock * 1000.0 / mode->VTotal / mode->HTotal; 2291 xf86DrvMsg(scrnIndex, X_INFO, "Mode: %dx%d %d-bpp, %fHz\n", mode->HDisplay, 2292 mode->VDisplay, pScrn->bitsPerPixel, refresh); 2293 2294 if (pSmi->shadowFB) { 2295 int mem; 2296 2297 if (pScrn->bitsPerPixel == 24) { 2298 LEAVE_PROC("SMI_ValidMode"); 2299 return MODE_BAD; 2300 } 2301 2302 mem = (pScrn->virtualX * pScrn->bitsPerPixel / 8 + 15) & ~15; 2303 mem *= pScrn->virtualY * 2; 2304 2305 if (mem > pSmi->FBReserved) /* PDR#1074 */ { 2306 LEAVE_PROC("SMI_ValidMode"); 2307 return MODE_MEM; 2308 } 2309 } 2310 2311 if (!pSmi->useBIOS || pSmi->lcd) { 2312#if 1 /* PDR#983 */ 2313 if (pSmi->zoomOnLCD) { 2314 if ((mode->HDisplay > pSmi->lcdWidth) || 2315 (mode->VDisplay > pSmi->lcdHeight)) { 2316 LEAVE_PROC("SMI_ValidMode"); 2317 return MODE_PANEL; 2318 } 2319 } else 2320#endif 2321 { 2322 if ((mode->HDisplay != pSmi->lcdWidth) || 2323 (mode->VDisplay != pSmi->lcdHeight)) { 2324 LEAVE_PROC("SMI_ValidMode"); 2325 return MODE_PANEL; 2326 } 2327 } 2328 } 2329 2330#if 1 /* PDR#944 */ 2331 if (pSmi->rotate) { 2332 if ((mode->HDisplay != pSmi->lcdWidth) || 2333 (mode->VDisplay != pSmi->lcdHeight)) { 2334 LEAVE_PROC("SMI_ValidMode"); 2335 return MODE_PANEL; 2336 } 2337 } 2338#endif 2339 2340 LEAVE_PROC("SMI_ValidMode"); 2341 return MODE_OK; 2342} 2343 2344static void 2345SMI_DPRInit(ScrnInfoPtr pScrn) 2346{ 2347 SMIPtr pSmi = SMIPTR(pScrn); 2348 int i; 2349 int xyAddress[] = { 320, 400, 512, 640, 800, 1024, 1280, 1600, 2048 }; 2350 CARD32 DEDataFormat = 0; 2351 2352 /* Store values to current mode register structs */ 2353 SMIRegPtr new = &pSmi->ModeReg; 2354 2355 /* Set DPR registers */ 2356 pSmi->Stride = (pSmi->width * pSmi->Bpp + 15) & ~15; 2357 switch (pScrn->bitsPerPixel) { 2358 case 8: 2359 DEDataFormat = 0x00000000; 2360 break; 2361 case 16: 2362 pSmi->Stride >>= 1; 2363 DEDataFormat = 0x00100000; 2364 break; 2365 case 24: 2366 DEDataFormat = 0x00300000; 2367 break; 2368 case 32: 2369 pSmi->Stride >>= 2; 2370 DEDataFormat = 0x00200000; 2371 break; 2372 } 2373 2374 for (i = 0; i < sizeof(xyAddress) / sizeof(xyAddress[0]); i++) { 2375 if (pSmi->rotate) { 2376 if (xyAddress[i] == pSmi->height) { 2377 DEDataFormat |= i << 16; 2378 break; 2379 } 2380 } else { 2381 if (xyAddress[i] == pSmi->width) { 2382 DEDataFormat |= i << 16; 2383 break; 2384 } 2385 } 2386 } 2387 2388 new->DPR10 = (pSmi->Stride << 16) | pSmi->Stride; 2389 new->DPR1C = DEDataFormat; 2390 new->DPR20 = 0; 2391 new->DPR24 = 0xFFFFFFFF; 2392 new->DPR28 = 0xFFFFFFFF; 2393 new->DPR2C = 0; 2394 new->DPR30 = 0; 2395 new->DPR3C = (pSmi->Stride << 16) | pSmi->Stride; 2396 new->DPR40 = pSmi->FBOffset >> 3; 2397 new->DPR44 = pSmi->FBOffset >> 3; 2398 2399} 2400 2401static Bool 2402SMI_ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 2403{ 2404 vgaHWPtr hwp = VGAHWPTR(pScrn); 2405 SMIPtr pSmi = SMIPTR(pScrn); 2406 unsigned char tmp; 2407 int panelIndex, modeIndex, i, vclk; 2408 2409 /* Store values to current mode register structs */ 2410 SMIRegPtr new = &pSmi->ModeReg; 2411 vgaRegPtr vganew = &hwp->ModeReg; 2412 2413 ENTER_PROC("SMI_ModeInit"); 2414 2415 if (!vgaHWInit(pScrn, mode)) { 2416 LEAVE_PROC("SMI_ModeInit"); 2417 return FALSE; 2418 } 2419 2420 new->modeInit = TRUE; 2421 2422 if (pSmi->rotate) { 2423 pSmi->width = pScrn->virtualY; 2424 pSmi->height = pScrn->virtualX; 2425 } else { 2426 pSmi->width = pScrn->virtualX; 2427 pSmi->height = pScrn->virtualY; 2428 } 2429 pSmi->Bpp = pScrn->bitsPerPixel / 8; 2430 2431 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x17); 2432 tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA); 2433 if (pSmi->pci_burst) { 2434 new->SR17 = tmp | 0x20; 2435 } else { 2436 new->SR17 = tmp & ~0x20; 2437 } 2438 2439 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18); 2440 new->SR18 = inb(pSmi->PIOBase + VGA_SEQ_DATA) | 0x11; 2441 2442 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21); 2443 new->SR21 = inb(pSmi->PIOBase + VGA_SEQ_DATA) & ~0x03; 2444 2445 if (pSmi->Chipset != SMI_COUGAR3DR) { 2446 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x31); 2447 new->SR31 = inb(pSmi->PIOBase + VGA_SEQ_DATA) & ~0xC0; 2448 2449 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x32); 2450 new->SR32 = inb(pSmi->PIOBase + VGA_SEQ_DATA) & ~0x07; 2451 2452 if (SMI_LYNXM_SERIES(pSmi->Chipset)) { 2453 new->SR32 |= 0x04; 2454 } 2455 } 2456 2457 new->SRA0 = new->CR33 = new->CR3A = 0x00; 2458 2459 if (pSmi->lcdWidth == 640) { 2460 panelIndex = 0; 2461 } else if (pSmi->lcdWidth == 800) { 2462 panelIndex = 1; 2463 } else { 2464 panelIndex = 2; 2465 } 2466 2467 if (mode->HDisplay == 640) { 2468 modeIndex = 0; 2469 } else if (mode->HDisplay == 800) { 2470 modeIndex = 1; 2471 } else { 2472 modeIndex = 2; 2473 } 2474 2475 if (SMI_LYNXM_SERIES(pSmi->Chipset)) { 2476 static unsigned char PanelTable[3][14] = 2477 { 2478 { 0x5F, 0x4F, 0x00, 0x52, 0x1E, 0x0B, 0xDF, 0x00, 0xE9, 0x0B, 0x2E, 2479 0x00, 0x4F, 0xDF }, 2480 { 0x7F, 0x63, 0x00, 0x69, 0x19, 0x72, 0x57, 0x00, 0x58, 0x0C, 0xA2, 2481 0x20, 0x4F, 0xDF }, 2482 { 0xA3, 0x7F, 0x00, 0x83, 0x14, 0x24, 0xFF, 0x00, 0x02, 0x08, 0xA7, 2483 0xE0, 0x4F, 0xDF }, 2484 }; 2485 2486 for (i = 0; i < 14; i++) { 2487 new->CR40[i] = PanelTable[panelIndex][i]; 2488 } 2489 new->CR90[14] = 0x03; 2490 new->CR90[15] = 0x00; 2491 if (mode->VDisplay < pSmi->lcdHeight) { 2492 new->CRA0[6] = (pSmi->lcdHeight - mode->VDisplay) / 8; 2493 } else { 2494 new->CRA0[6] = 0; 2495 } 2496 2497 if (mode->HDisplay < pSmi->lcdWidth) { 2498 new->CRA0[7] = (pSmi->lcdWidth - mode->HDisplay) / 16; 2499 } else { 2500 new->CRA0[7] = 0; 2501 } 2502 } else { 2503 static unsigned char PanelTable[3][3][14] = 2504 { 2505 { /* 640x480 panel */ 2506 { 0x5F, 0x4F, 0x00, 0x53, 0x00, 0x0B, 0xDF, 0x00, 0xEA, 0x0C, 2507 0x2E, 0x00, 0x4F, 0xDF }, 2508 { 0x5F, 0x4F, 0x00, 0x53, 0x00, 0x0B, 0xDF, 0x00, 0xEA, 0x0C, 2509 0x2E, 0x00, 0x4F, 0xDF }, 2510 { 0x5F, 0x4F, 0x00, 0x53, 0x00, 0x0B, 0xDF, 0x00, 0xEA, 0x0C, 2511 0x2E, 0x00, 0x4F, 0xDF }, 2512 }, 2513 { /* 800x600 panel */ 2514 { 0x7F, 0x59, 0x19, 0x5E, 0x8E, 0x72, 0x1C, 0x37, 0x1D, 0x00, 2515 0xA2, 0x20, 0x4F, 0xDF }, 2516 { 0x7F, 0x63, 0x00, 0x68, 0x18, 0x72, 0x58, 0x00, 0x59, 0x0C, 2517 0xE0, 0x20, 0x63, 0x57 }, 2518 { 0x7F, 0x63, 0x00, 0x68, 0x18, 0x72, 0x58, 0x00, 0x59, 0x0C, 2519 0xE0, 0x20, 0x63, 0x57 }, 2520 }, 2521 { /* 1024x768 panel */ 2522 { 0xA3, 0x67, 0x0F, 0x6D, 0x1D, 0x24, 0x70, 0x95, 0x72, 0x07, 2523 0xA3, 0x20, 0x4F, 0xDF }, 2524 { 0xA3, 0x71, 0x19, 0x77, 0x07, 0x24, 0xAC, 0xD1, 0xAE, 0x03, 2525 0xE1, 0x20, 0x63, 0x57 }, 2526 { 0xA3, 0x7F, 0x00, 0x85, 0x15, 0x24, 0xFF, 0x00, 0x01, 0x07, 2527 0xE5, 0x20, 0x7F, 0xFF }, 2528 }, 2529 }; 2530 2531 for (i = 0; i < 14; i++) { 2532 new->CR40[i] = PanelTable[panelIndex][modeIndex][i]; 2533 } 2534 } 2535 2536 /* CZ 2.11.2001: for gamma correction (TODO: other chipsets?) */ 2537 new->CCR66 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x66); 2538 if ((pSmi->Chipset == SMI_LYNX3DM) || (pSmi->Chipset == SMI_COUGAR3DR)) { 2539 switch (pScrn->bitsPerPixel) { 2540 case 8: 2541 new->CCR66 = (new->CCR66 & 0xF3) | 0x00; /* 6 bits-RAM */ 2542 break; 2543 case 16: 2544 new->CCR66 = (new->CCR66 & 0xF3) | 0x00; /* 6 bits-RAM */ 2545 /* no Gamma correction in 16 Bit mode (s. Release.txt 1.3.1) */ 2546 break; 2547 case 24: 2548 case 32: 2549 new->CCR66 = (new->CCR66 & 0xF3) | 0x04; /* Gamma correct ON */ 2550 break; 2551 default: 2552 LEAVE_PROC("SMI_ModeInit"); 2553 return FALSE; 2554 } 2555 } 2556 2557 if (pSmi->Chipset != SMI_COUGAR3DR) { 2558 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x30); 2559 if (inb(pSmi->PIOBase + VGA_SEQ_DATA) & 0x01) { 2560 new->SR21 = 0x00; 2561 } 2562 } 2563 2564 if (pSmi->MCLK > 0) { 2565 SMI_CommonCalcClock(pScrn->scrnIndex, pSmi->MCLK, 2566 1, 1, 63, 0, 2, 2567 pScrn->clockRanges->minClock, 2568 pScrn->clockRanges->maxClock, 2569 &new->SR6A, &new->SR6B); 2570 } else { 2571 new->SR6B = 0xFF; 2572 } 2573 2574 if ((mode->HDisplay == 640) && SMI_LYNXM_SERIES(pSmi->Chipset)) { 2575 vganew->MiscOutReg &= ~0x0C; 2576 } else { 2577 vganew->MiscOutReg |= 0x0C; 2578 } 2579 vganew->MiscOutReg |= 0xE0; 2580 if (mode->HDisplay == 800) { 2581 vganew->MiscOutReg &= ~0xC0; 2582 } 2583 if ((mode->HDisplay == 1024) && SMI_LYNXM_SERIES(pSmi->Chipset)) { 2584 vganew->MiscOutReg &= ~0xC0; 2585 } 2586 2587 /* calculate vclk1 */ 2588 vclk = mode->Clock; 2589 if (SMI_LYNX_SERIES(pSmi->Chipset)) { 2590 SMI_CommonCalcClock(pScrn->scrnIndex, vclk, 2591 1, 1, 63, 0, 2, 2592 pScrn->clockRanges->minClock, 2593 pScrn->clockRanges->maxClock, 2594 &new->SR6C, &new->SR6D); 2595 } else { 2596 SMI_CommonCalcClock(pScrn->scrnIndex, vclk, 2597 1, 1, 63, 0, 1, 2598 pScrn->clockRanges->minClock, 2599 pScrn->clockRanges->maxClock, 2600 &new->SR6C, &new->SR6D); 2601 } 2602 2603 /* use vclk1 */ 2604 new->SR68 = 0x54; 2605 2606 /* dualhead */ 2607 if (pSmi->Dualhead) { 2608 /* PLL controls */ 2609 /* set LCD to vclk2 */ 2610 new->SR69 = 0x04; 2611 2612 if (pSmi->lcdWidth == 640) { 2613 /* vclk */ 2614 new->SR6C = 0x07; 2615 new->SR6D = 0x04; 2616 2617 /* vclk2 */ 2618 new->SR6E = 0x07; 2619 new->SR6F = 0x04; 2620 } else if (pSmi->lcdWidth == 800) { 2621 /* vclk */ 2622 new->SR6C = 0x0B; 2623 new->SR6D = 0x82; 2624 2625 /* vclk2 */ 2626 new->SR6E = 0x0B; 2627 new->SR6F = 0x82; 2628 } else { 2629 /* vclk */ 2630 new->SR6C = 0x52; 2631 new->SR6D = 0x89; 2632 2633 /* vclk2 */ 2634 new->SR6E = 0x52; 2635 new->SR6F = 0x89; 2636 } 2637 2638 /* TFT panel uses FIFO1, DSTN panel uses FIFO1 for upper panel and 2639 * FIFO2 for lower panel. I don't have a DSTN panel, so it's untested. 2640 * -- AGD 2641 */ 2642 CARD32 fifo1_readoffset, fifo2_readoffset, fifo_writeoffset; 2643 2644 /* setting SR21 bit 2 disables ZV circuitry, 2645 * if ZV is needed, SR21 = 0x20 2646 */ 2647 /* enable DAC, PLL, etc. */ 2648 new->SR21 = 0x24; 2649 2650 /* clear DPMS state */ 2651 new->SR22 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x22) & ~0x30; 2652 2653 /* enable virtual refresh and LCD and CRT outputs */ 2654 if (pScrn->bitsPerPixel > 8) 2655 new->SR31 = /*0xCB*/ 0xC3; /* 16 bpp */ 2656 else 2657 new->SR31 = /*0x8B*/ 0x83; /* 8 bpp */ 2658 2659 /* FIFO1 Read Offset */ 2660 fifo1_readoffset = pSmi->lcdWidth / 2; 2661 fifo2_readoffset = pSmi->lcdWidth / 2; 2662 new->SR44 = fifo1_readoffset & 0x000000FF; 2663 /* FIFO2 Read Offset */ 2664 new->SR4B = fifo2_readoffset & 0x000000FF; 2665 /* FIFO1/2 Read Offset overflow */ 2666 new->SR4C = (((fifo1_readoffset & 0x00000300) >> 8) << 2) | 2667 (((fifo2_readoffset & 0x00000300) >> 8) << 6); 2668 2669 /* FIFO Write Offset */ 2670 fifo_writeoffset = pSmi->lcdWidth / 4; 2671 new->SR48 = fifo_writeoffset & 0x000000FF; 2672 new->SR49 = (fifo_writeoffset & 0x00000300) >> 8; 2673 2674 /* set FIFO levels */ 2675 new->SR4A = 0x41; 2676 2677 /* something related to tv... */ 2678 new->CR33 |= 0x07; 2679 2680 } 2681 2682 /* init graphics engine regs */ 2683 SMI_DPRInit(pScrn); 2684 2685 /* Set VPR registers (and FPR registers for SM731) */ 2686 switch (pScrn->bitsPerPixel) { 2687 case 8: 2688 new->VPR00 = 0x00000000; 2689 new->FPR00_= 0x00080000; 2690 break; 2691 case 16: 2692 new->VPR00 = 0x00020000; 2693 new->FPR00_= 0x000A0000; 2694 break; 2695 case 24: 2696 new->VPR00 = 0x00040000; 2697 new->FPR00_= 0x000C0000; 2698 break; 2699 case 32: 2700 new->VPR00 = 0x00030000; 2701 new->FPR00_= 0x000B0000; 2702 break; 2703 } 2704 new->VPR0C = pSmi->FBOffset >> 3; 2705 if (pSmi->rotate) { 2706 new->VPR10 = (((( pSmi->height * pSmi->Bpp) >> 3) + 2) << 16) | 2707 ((pSmi->height * pSmi->Bpp) >> 3); 2708 } else { 2709 new->VPR10 = ((((pSmi->width * pSmi->Bpp) >> 3) + 2) << 16) | 2710 ((pSmi->width * pSmi->Bpp) >> 3); 2711 } 2712 2713 new->FPR0C_ = new->VPR0C; 2714 new->FPR10_ = new->VPR10; 2715 2716 /* Set CPR registers */ 2717 new->CPR00 = 0x00000000; 2718 2719 pScrn->vtSema = TRUE; 2720 2721 /* Find the INT 10 mode number */ 2722 { 2723 static struct { 2724 int x, y, bpp; 2725 CARD16 mode; 2726 } modeTable[] = 2727 { 2728 { 640, 480, 8, 0x50 }, 2729 { 640, 480, 16, 0x52 }, 2730 { 640, 480, 24, 0x53 }, 2731 { 640, 480, 32, 0x54 }, 2732 { 800, 480, 8, 0x4A }, 2733 { 800, 480, 16, 0x4C }, 2734 { 800, 480, 24, 0x4D }, 2735 { 800, 600, 8, 0x55 }, 2736 { 800, 600, 16, 0x57 }, 2737 { 800, 600, 24, 0x58 }, 2738 { 800, 600, 32, 0x59 }, 2739 { 1024, 768, 8, 0x60 }, 2740 { 1024, 768, 16, 0x62 }, 2741 { 1024, 768, 24, 0x63 }, 2742 { 1024, 768, 32, 0x64 }, 2743 { 1280, 1024, 8, 0x65 }, 2744 { 1280, 1024, 16, 0x67 }, 2745 { 1280, 1024, 24, 0x68 }, 2746 { 1280, 1024, 32, 0x69 }, 2747 }; 2748 2749 new->mode = 0; 2750 for (i = 0; i < sizeof(modeTable) / sizeof(modeTable[0]); i++) { 2751 if ((modeTable[i].x == mode->HDisplay) && 2752 (modeTable[i].y == mode->VDisplay) && 2753 (modeTable[i].bpp == pScrn->bitsPerPixel)) { 2754 new->mode = modeTable[i].mode; 2755 break; 2756 } 2757 } 2758 } 2759 2760 /* Zero the font memory */ 2761 memset(new->smiFont, 0, sizeof(new->smiFont)); 2762 2763 /* Write the mode registers to hardware */ 2764 SMI_WriteMode(pScrn, vganew, new); 2765 2766 /* Adjust the viewport */ 2767 SMI_AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 2768 2769 LEAVE_PROC("SMI_ModeInit"); 2770 return TRUE; 2771} 2772 2773/* 2774 * This is called at the end of each server generation. It restores the 2775 * original (text) mode. It should also unmap the video memory, and free any 2776 * per-generation data allocated by the driver. It should finish by unwrapping 2777 * and calling the saved CloseScreen function. 2778 */ 2779 2780static Bool 2781SMI_CloseScreen(int scrnIndex, ScreenPtr pScreen) 2782{ 2783 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 2784 vgaHWPtr hwp = VGAHWPTR(pScrn); 2785 SMIPtr pSmi = SMIPTR(pScrn); 2786 vgaRegPtr vgaSavePtr = &hwp->SavedReg; 2787 SMIRegPtr SMISavePtr = &pSmi->SavedReg; 2788 Bool ret; 2789 2790 ENTER_PROC("SMI_CloseScreen"); 2791 2792 if (pScrn->vtSema) { 2793 SMI_WriteMode(pScrn, vgaSavePtr, SMISavePtr); 2794 vgaHWLock(hwp); 2795 SMI_UnmapMem(pScrn); 2796 } 2797 2798 if (pSmi->XAAInfoRec != NULL) { 2799 XAADestroyInfoRec(pSmi->XAAInfoRec); 2800 } 2801 if (pSmi->EXADriverPtr) { 2802 exaDriverFini(pScreen); 2803 pSmi->EXADriverPtr = NULL; 2804 } 2805 if (pSmi->CursorInfoRec != NULL) { 2806 xf86DestroyCursorInfoRec(pSmi->CursorInfoRec); 2807 } 2808 if (pSmi->DGAModes != NULL) { 2809 xfree(pSmi->DGAModes); 2810 } 2811 if (pSmi->pInt10 != NULL) { 2812 xf86FreeInt10(pSmi->pInt10); 2813 pSmi->pInt10 = NULL; 2814 } 2815 if (pSmi->ptrAdaptor != NULL) { 2816 xfree(pSmi->ptrAdaptor); 2817 } 2818 if (pSmi->BlockHandler != NULL) { 2819 pScreen->BlockHandler = pSmi->BlockHandler; 2820 } 2821 /* #670 */ 2822 if (pSmi->pSaveBuffer) { 2823 xfree(pSmi->pSaveBuffer); 2824 } 2825/* #920 */ 2826 if (pSmi->paletteBuffer) { 2827 xfree(pSmi->paletteBuffer); 2828 } 2829 2830 pScrn->vtSema = FALSE; 2831 pScreen->CloseScreen = pSmi->CloseScreen; 2832 ret = (*pScreen->CloseScreen)(scrnIndex, pScreen); 2833 2834 LEAVE_PROC("SMI_CloseScreen"); 2835 return ret; 2836} 2837 2838static void 2839SMI_FreeScreen(int scrnIndex, int flags) 2840{ 2841 SMI_FreeRec(xf86Screens[scrnIndex]); 2842} 2843 2844static Bool 2845SMI_SaveScreen(ScreenPtr pScreen, int mode) 2846{ 2847 Bool ret; 2848 2849 ENTER_PROC("SMI_SaveScreen"); 2850 2851 ret = vgaHWSaveScreen(pScreen, mode); 2852 2853 LEAVE_PROC("SMI_SaveScreen"); 2854 return ret; 2855} 2856 2857void 2858SMI_AdjustFrame(int scrnIndex, int x, int y, int flags) 2859{ 2860 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 2861 SMIPtr pSmi = SMIPTR(pScrn); 2862 CARD32 Base, lcdBase; 2863 2864 ENTER_PROC("SMI_AdjustFrame"); 2865 2866 if (pSmi->ShowCache && y) { 2867 y += pScrn->virtualY - 1; 2868 } 2869 2870 if (pSmi->Dualhead) { 2871 lcdBase = 0; 2872 x = pSmi->lcdWidth; 2873 y = 0; 2874 } 2875 2876 Base = pSmi->FBOffset + (x + y * pScrn->virtualX) * pSmi->Bpp; 2877 if (SMI_LYNX3D_SERIES(pSmi->Chipset) || 2878 SMI_COUGAR_SERIES(pSmi->Chipset)) { 2879 Base = (Base + 15) & ~15; 2880#if 1 /* PDR#1058 */ 2881 while ((Base % pSmi->Bpp) > 0) { 2882 Base -= 16; 2883 } 2884#endif 2885 } else { 2886 Base = (Base + 7) & ~7; 2887#if 1 /* PDR#1058 */ 2888 while ((Base % pSmi->Bpp) > 0) { 2889 Base -= 8; 2890 } 2891#endif 2892 } 2893 2894 if (pSmi->Dualhead) { 2895 2896 /* FIFO1 read start address */ 2897 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x40, 2898 (lcdBase & 0x000000FF)); 2899 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x41, 2900 ((lcdBase & 0x0000FF00) >> 8)); 2901 2902 /* FIFO2 read start address */ 2903 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x42, 2904 (lcdBase & 0x000000FF)); 2905 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x43, 2906 ((lcdBase & 0x0000FF00) >> 8)); 2907 2908 /* FIFO1/2 read start address overflow */ 2909 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x45, 2910 ((lcdBase & 0x000F0000) >> 12) | (((lcdBase & 0x000F0000) >> 12) << 4)); 2911 2912 } 2913 2914 WRITE_VPR(pSmi, 0x0C, Base >> 3); 2915 if (pSmi->Chipset == SMI_COUGAR3DR) { 2916 WRITE_FPR(pSmi, FPR0C, Base >> 3); 2917 } 2918 2919 LEAVE_PROC("SMI_AdjustFrame"); 2920} 2921 2922Bool 2923SMI_SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) 2924{ 2925 Bool ret; 2926 SMIPtr pSmi = SMIPTR(xf86Screens[scrnIndex]); 2927 2928 ENTER_PROC("SMI_SwitchMode"); 2929 2930 pSmi->IsSwitching = TRUE; 2931 ret = SMI_ModeInit(xf86Screens[scrnIndex], mode); 2932 pSmi->IsSwitching = FALSE; 2933 2934 LEAVE_PROC("SMI_SwitchMode"); 2935 return ret; 2936} 2937 2938void 2939SMI_LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies, LOCO *colors, 2940 VisualPtr pVisual) 2941{ 2942 SMIPtr pSmi = SMIPTR(pScrn); 2943 int i; 2944 2945 ENTER_PROC("SMI_LoadPalette"); 2946 2947 /* Enable both the CRT and LCD DAC RAM paths, so both palettes are updated */ 2948 if ((pSmi->Chipset == SMI_LYNX3DM) || 2949 (pSmi->Chipset == SMI_COUGAR3DR)) { 2950 CARD8 ccr66; 2951 2952 ccr66 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x66); 2953 ccr66 &= 0x0f; 2954 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x66, ccr66); 2955 } 2956 2957 for(i = 0; i < numColors; i++) { 2958 DEBUG((VERBLEV, "pal[%d] = %d %d %d\n", indicies[i], 2959 colors[indicies[i]].red, colors[indicies[i]].green, colors[indicies[i]].blue)); 2960 VGAOUT8(pSmi, VGA_DAC_WRITE_ADDR, indicies[i]); 2961 VGAOUT8(pSmi, VGA_DAC_DATA, colors[indicies[i]].red); 2962 VGAOUT8(pSmi, VGA_DAC_DATA, colors[indicies[i]].green); 2963 VGAOUT8(pSmi, VGA_DAC_DATA, colors[indicies[i]].blue); 2964 } 2965 2966 LEAVE_PROC("SMI_LoadPalette"); 2967} 2968 2969static void 2970SMI_DisableVideo(ScrnInfoPtr pScrn) 2971{ 2972 SMIPtr pSmi = SMIPTR(pScrn); 2973 CARD8 tmp; 2974 2975 if (!(tmp = VGAIN8(pSmi, VGA_DAC_MASK))) 2976 return; 2977 pSmi->DACmask = tmp; 2978 VGAOUT8(pSmi, VGA_DAC_MASK, 0); 2979} 2980 2981static void 2982SMI_EnableVideo(ScrnInfoPtr pScrn) 2983{ 2984 SMIPtr pSmi = SMIPTR(pScrn); 2985 2986 VGAOUT8(pSmi, VGA_DAC_MASK, pSmi->DACmask); 2987} 2988 2989 2990void 2991SMI_EnableMmio(ScrnInfoPtr pScrn) 2992{ 2993 vgaHWPtr hwp = VGAHWPTR(pScrn); 2994 SMIPtr pSmi = SMIPTR(pScrn); 2995 CARD8 tmp; 2996 2997 ENTER_PROC("SMI_EnableMmio"); 2998 2999 /* 3000 * Enable chipset (seen on uninitialized secondary cards) might not be 3001 * needed once we use the VGA softbooter 3002 */ 3003 vgaHWSetStdFuncs(hwp); 3004 3005 /* Enable linear mode */ 3006 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18); 3007 tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA); 3008 pSmi->SR18Value = tmp; /* PDR#521 */ 3009 outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp | 0x11); 3010 3011 /* Enable 2D/3D Engine and Video Processor */ 3012 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21); 3013 tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA); 3014 pSmi->SR21Value = tmp; /* PDR#521 */ 3015 outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp & ~0x03); 3016 3017 LEAVE_PROC("SMI_EnableMmio"); 3018} 3019 3020void 3021SMI_DisableMmio(ScrnInfoPtr pScrn) 3022{ 3023 vgaHWPtr hwp = VGAHWPTR(pScrn); 3024 SMIPtr pSmi = SMIPTR(pScrn); 3025 3026 ENTER_PROC("SMI_DisableMmio"); 3027 3028 vgaHWSetStdFuncs(hwp); 3029 3030 /* Disable 2D/3D Engine and Video Processor */ 3031 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21); 3032 outb(pSmi->PIOBase + VGA_SEQ_DATA, pSmi->SR21Value); /* PDR#521 */ 3033 3034 /* Disable linear mode */ 3035 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18); 3036 outb(pSmi->PIOBase + VGA_SEQ_DATA, pSmi->SR18Value); /* PDR#521 */ 3037 3038 LEAVE_PROC("SMI_DisableMmio"); 3039} 3040 3041/* This function is used to debug, it prints out the contents of Lynx regs */ 3042static void 3043SMI_PrintRegs(ScrnInfoPtr pScrn) 3044{ 3045 unsigned char i; 3046 vgaHWPtr hwp = VGAHWPTR(pScrn); 3047 SMIPtr pSmi = SMIPTR(pScrn); 3048 int vgaCRIndex = hwp->IOBase + VGA_CRTC_INDEX_OFFSET; 3049 int vgaCRReg = hwp->IOBase + VGA_CRTC_DATA_OFFSET; 3050 int vgaStatus = hwp->IOBase + VGA_IN_STAT_1_OFFSET; 3051 3052 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 3053 "START register dump ------------------\n"); 3054 3055 xf86ErrorFVerb(VERBLEV, "MISCELLANEOUS OUTPUT\n %02X\n", 3056 VGAIN8(pSmi, VGA_MISC_OUT_R)); 3057 3058 xf86ErrorFVerb(VERBLEV, "\nSEQUENCER\n" 3059 " x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF"); 3060 for (i = 0x00; i <= 0xAF; i++) { 3061 if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i); 3062 if ((i & 0x3) == 0x0) xf86ErrorFVerb(VERBLEV, " "); 3063 xf86ErrorFVerb(VERBLEV, "%02X ", 3064 VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, i)); 3065 } 3066 3067 xf86ErrorFVerb(VERBLEV, "\n\nCRT CONTROLLER\n" 3068 " x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF"); 3069 for (i = 0x00; i <= 0xAD; i++) { 3070 if (i == 0x20) i = 0x30; 3071 if (i == 0x50) i = 0x90; 3072 if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i); 3073 if ((i & 0x3) == 0x0) xf86ErrorFVerb(VERBLEV, " "); 3074 xf86ErrorFVerb(VERBLEV, "%02X ", 3075 VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRReg, i)); 3076 } 3077 3078 xf86ErrorFVerb(VERBLEV, "\n\nGRAPHICS CONTROLLER\n" 3079 " x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF"); 3080 for (i = 0x00; i <= 0x08; i++) { 3081 if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i); 3082 if ((i & 0x3) == 0x0) xf86ErrorFVerb(VERBLEV, " "); 3083 xf86ErrorFVerb(VERBLEV, "%02X ", 3084 VGAIN8_INDEX(pSmi, VGA_GRAPH_INDEX, VGA_GRAPH_DATA, i)); 3085 } 3086 3087 xf86ErrorFVerb(VERBLEV, "\n\nATTRIBUTE 0CONTROLLER\n" 3088 " x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF"); 3089 for (i = 0x00; i <= 0x14; i++) { 3090 (void) VGAIN8(pSmi, vgaStatus); 3091 if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i); 3092 if ((i & 0x3) == 0x0) xf86ErrorFVerb(VERBLEV, " "); 3093 xf86ErrorFVerb(VERBLEV, "%02X ", 3094 VGAIN8_INDEX(pSmi, VGA_ATTR_INDEX, VGA_ATTR_DATA_R, i)); 3095 } 3096 (void) VGAIN8(pSmi, vgaStatus); 3097 VGAOUT8(pSmi, VGA_ATTR_INDEX, 0x20); 3098 3099 xf86ErrorFVerb(VERBLEV, "\n\nDPR x0 x4 x8 xC"); 3100 for (i = 0x00; i <= 0x44; i += 4) { 3101 if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i); 3102 xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_DPR(pSmi, i)); 3103 } 3104 3105 xf86ErrorFVerb(VERBLEV, "\n\nVPR x0 x4 x8 xC"); 3106 for (i = 0x00; i <= 0x60; i += 4) { 3107 if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i); 3108 xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_VPR(pSmi, i)); 3109 } 3110 3111 xf86ErrorFVerb(VERBLEV, "\n\nCPR x0 x4 x8 xC"); 3112 for (i = 0x00; i <= 0x18; i += 4) { 3113 if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i); 3114 xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_CPR(pSmi, i)); 3115 } 3116 3117 xf86ErrorFVerb(VERBLEV, "\n\n"); 3118 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 3119 "END register dump --------------------\n"); 3120} 3121 3122/* 3123 * SMI_DisplayPowerManagementSet -- Sets VESA Display Power Management 3124 * Signaling (DPMS) Mode. 3125 */ 3126static void 3127SMI_DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, 3128 int flags) 3129{ 3130 vgaHWPtr hwp = VGAHWPTR(pScrn); 3131 SMIPtr pSmi = SMIPTR(pScrn); 3132 CARD8 SR01, SR20, SR21, SR22, SR23, SR24, SR31, SR34; 3133 3134 ENTER_PROC("SMI_DisplayPowerManagementSet"); 3135 3136 /* If we already are in the requested DPMS mode, just return */ 3137 if (pSmi->CurrentDPMS == PowerManagementMode) { 3138 LEAVE_PROC("SMI_DisplayPowerManagementSet"); 3139 return; 3140 } 3141 3142#if 1 /* PDR#735 */ 3143 if (pSmi->useBIOS && pSmi->pInt10 != NULL) { 3144 pSmi->pInt10->ax = 0x4F10; 3145 switch (PowerManagementMode) { 3146 case DPMSModeOn: 3147 pSmi->pInt10->bx = 0x0001; 3148 break; 3149 case DPMSModeStandby: 3150 pSmi->pInt10->bx = 0x0101; 3151 break; 3152 case DPMSModeSuspend: 3153 pSmi->pInt10->bx = 0x0201; 3154 break; 3155 case DPMSModeOff: 3156 pSmi->pInt10->bx = 0x0401; 3157 break; 3158 } 3159 pSmi->pInt10->cx = 0x0000; 3160 pSmi->pInt10->num = 0x10; 3161 xf86ExecX86int10(pSmi->pInt10); 3162 if (pSmi->pInt10->ax == 0x004F) { 3163 pSmi->CurrentDPMS = PowerManagementMode; 3164#if 1 /* PDR#835 */ 3165 if (PowerManagementMode == DPMSModeOn) { 3166 SR01 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x01); 3167 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x01, 3168 SR01 & ~0x20); 3169 } 3170#endif 3171 LEAVE_PROC("SMI_DisplayPowerManagementSet"); 3172 return; 3173 } 3174 } 3175#endif 3176 3177 /* Save the current SR registers */ 3178 if (pSmi->CurrentDPMS == DPMSModeOn) { 3179 pSmi->DPMS_SR20 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x20); 3180 pSmi->DPMS_SR21 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21); 3181 pSmi->DPMS_SR31 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31); 3182 pSmi->DPMS_SR34 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x34); 3183 } 3184 3185 /* Read the required SR registers for the DPMS handler */ 3186 SR01 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x01); 3187 SR20 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x20); 3188 SR21 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21); 3189 SR22 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x22); 3190 SR23 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x23); 3191 SR24 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x24); 3192 SR31 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31); 3193 SR34 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x34); 3194 3195 switch (PowerManagementMode) { 3196 case DPMSModeOn: 3197 /* Screen On: HSync: On, VSync : On */ 3198 SR01 &= ~0x20; 3199 SR20 = pSmi->DPMS_SR20; 3200 SR21 = pSmi->DPMS_SR21; 3201 SR22 &= ~0x30; 3202 SR23 &= ~0xC0; 3203 SR24 |= 0x01; 3204 SR31 = pSmi->DPMS_SR31; 3205 SR34 = pSmi->DPMS_SR34; 3206 break; 3207 case DPMSModeStandby: 3208 /* Screen: Off; HSync: Off, VSync: On */ 3209 SR01 |= 0x20; 3210 SR20 = (SR20 & ~0xB0) | 0x10; 3211 SR21 |= 0x88; 3212 SR22 = (SR22 & ~0x30) | 0x10; 3213 SR23 = (SR23 & ~0x07) | 0xD8; 3214 SR24 &= ~0x01; 3215 SR31 = (SR31 & ~0x07) | 0x00; 3216 SR34 |= 0x80; 3217 break; 3218 case DPMSModeSuspend: 3219 /* Screen: Off; HSync: On, VSync: Off */ 3220 SR01 |= 0x20; 3221 SR20 = (SR20 & ~0xB0) | 0x10; 3222 SR21 |= 0x88; 3223 SR22 = (SR22 & ~0x30) | 0x20; 3224 SR23 = (SR23 & ~0x07) | 0xD8; 3225 SR24 &= ~0x01; 3226 SR31 = (SR31 & ~0x07) | 0x00; 3227 SR34 |= 0x80; 3228 break; 3229 case DPMSModeOff: 3230 /* Screen: Off; HSync: Off, VSync: Off */ 3231 SR01 |= 0x20; 3232 SR20 = (SR20 & ~0xB0) | 0x10; 3233 SR21 |= 0x88; 3234 SR22 = (SR22 & ~0x30) | 0x30; 3235 SR23 = (SR23 & ~0x07) | 0xD8; 3236 SR24 &= ~0x01; 3237 SR31 = (SR31 & ~0x07) | 0x00; 3238 SR34 |= 0x80; 3239 break; 3240 default: 3241 xf86ErrorFVerb(VERBLEV, "Invalid PowerManagementMode %d passed to " 3242 "SMI_DisplayPowerManagementSet\n", PowerManagementMode); 3243 LEAVE_PROC("SMI_DisplayPowerManagementSet"); 3244 return; 3245 } 3246 3247 /* Wait for vertical retrace */ 3248 while (hwp->readST01(hwp) & 0x8) ; 3249 while (!(hwp->readST01(hwp) & 0x8)) ; 3250 3251 /* Write the registers */ 3252 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x01, SR01); 3253 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x34, SR34); 3254 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31, SR31); 3255 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x20, SR20); 3256 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x22, SR22); 3257 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x23, SR23); 3258 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, SR21); 3259 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x24, SR24); 3260 3261 /* Save the current power state */ 3262 pSmi->CurrentDPMS = PowerManagementMode; 3263 3264 LEAVE_PROC("SMI_DisplayPowerManagementSet"); 3265} 3266 3267static void 3268SMI_ProbeDDC(ScrnInfoPtr pScrn, int index) 3269{ 3270 vbeInfoPtr pVbe; 3271 if (xf86LoadSubModule(pScrn, "vbe")) { 3272 pVbe = VBEInit(NULL, index); 3273 ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 3274 vbeFree(pVbe); 3275 } 3276} 3277 3278static unsigned int 3279SMI_ddc1Read(ScrnInfoPtr pScrn) 3280{ 3281 register vgaHWPtr hwp = VGAHWPTR(pScrn); 3282 SMIPtr pSmi = SMIPTR(pScrn); 3283 unsigned int ret; 3284 3285 ENTER_PROC("SMI_ddc1Read"); 3286 3287 while (hwp->readST01(hwp) & 0x8) ; 3288 while (!(hwp->readST01(hwp) & 0x8)) ; 3289 3290 ret = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x72) & 0x08; 3291 3292 LEAVE_PROC("SMI_ddc1Read"); 3293 return ret; 3294} 3295 3296static Bool 3297SMI_ddc1(int scrnIndex) 3298{ 3299 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 3300 SMIPtr pSmi = SMIPTR(pScrn); 3301 Bool success = FALSE; 3302 xf86MonPtr pMon; 3303 unsigned char tmp; 3304 3305 ENTER_PROC("SMI_ddc1"); 3306 3307 tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x72); 3308 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x72, tmp | 0x20); 3309 3310 pMon = xf86PrintEDID(xf86DoEDID_DDC1(scrnIndex, 3311 vgaHWddc1SetSpeedWeak(), 3312 SMI_ddc1Read)); 3313 if (pMon != NULL) { 3314 success = TRUE; 3315 } 3316 xf86SetDDCproperties(pScrn, pMon); 3317 3318 VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x72, tmp); 3319 3320 LEAVE_PROC("SMI_ddc1"); 3321 return success; 3322} 3323 3324