smi_driver.c revision 7104f784
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 30#ifdef HAVE_CONFIG_H 31#include "config.h" 32#endif 33 34#include "xf86Resources.h" 35#include "xf86RAC.h" 36#include "xf86DDC.h" 37#include "xf86int10.h" 38#include "vbe.h" 39 40#include "smi.h" 41#include "smi_501.h" 42#include "smilynx.h" 43#include "smi_crtc.h" 44 45#include "globals.h" 46#define DPMS_SERVER 47#include <X11/extensions/dpms.h> 48 49/* 50 * Internals 51 */ 52static Bool SMI_MapMmio(ScrnInfoPtr pScrn); 53static Bool SMI_DetectMem(ScrnInfoPtr pScrn); 54static void SMI_EnableMmio(ScrnInfoPtr pScrn); 55static void SMI_DisableMmio(ScrnInfoPtr pScrn); 56static Bool SMI_HWInit(ScrnInfoPtr pScrn); 57 58/* 59 * Forward definitions for the functions that make up the driver. 60 */ 61 62static const OptionInfoRec * SMI_AvailableOptions(int chipid, int busid); 63static void SMI_Identify(int flags); 64static Bool SMI_Probe(DriverPtr drv, int flags); 65static Bool SMI_PreInit(ScrnInfoPtr pScrn, int flags); 66static Bool SMI_EnterVT(int scrnIndex, int flags); 67static void SMI_LeaveVT(int scrnIndex, int flags); 68static Bool SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, 69 char **argv); 70static void SMI_DisableVideo(ScrnInfoPtr pScrn); 71static void SMI_EnableVideo(ScrnInfoPtr pScrn); 72static Bool SMI_CloseScreen(int scrnIndex, ScreenPtr pScreen); 73static Bool SMI_SaveScreen(ScreenPtr pScreen, int mode); 74static void SMI_FreeScreen(int ScrnIndex, int flags); 75static void SMI_ProbeDDC(ScrnInfoPtr pScrn, int index); 76static void SMI_DetectPanelSize(ScrnInfoPtr pScrn); 77static void SMI_DetectMCLK(ScrnInfoPtr pScrn); 78 79/* 80 * xf86VDrvMsgVerb prints up to 14 characters prefix, where prefix has the 81 * format "%s(%d): " so, use name "SMI" instead of "Silicon Motion" 82 */ 83#define SILICONMOTION_NAME "SMI" 84#define SILICONMOTION_DRIVER_NAME "siliconmotion" 85#define SILICONMOTION_VERSION_NAME PACKAGE_VERSION 86#define SILICONMOTION_VERSION_MAJOR PACKAGE_VERSION_MAJOR 87#define SILICONMOTION_VERSION_MINOR PACKAGE_VERSION_MINOR 88#define SILICONMOTION_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL 89#define SILICONMOTION_DRIVER_VERSION ((SILICONMOTION_VERSION_MAJOR << 24) | \ 90 (SILICONMOTION_VERSION_MINOR << 16) | \ 91 (SILICONMOTION_PATCHLEVEL)) 92 93#if SMI_DEBUG 94int smi_indent = 1; 95#endif 96 97/* for dualhead */ 98int gSMIEntityIndex = -1; 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 { PCI_CHIP_SMI501, "MSOC" }, 130 { -1, NULL } 131}; 132 133static PciChipsets SMIPciChipsets[] = 134{ 135 /* numChipset, PciID, Resource */ 136 { PCI_CHIP_SMI910, PCI_CHIP_SMI910, RES_SHARED_VGA }, 137 { PCI_CHIP_SMI810, PCI_CHIP_SMI810, RES_SHARED_VGA }, 138 { PCI_CHIP_SMI820, PCI_CHIP_SMI820, RES_SHARED_VGA }, 139 { PCI_CHIP_SMI710, PCI_CHIP_SMI710, RES_SHARED_VGA }, 140 { PCI_CHIP_SMI712, PCI_CHIP_SMI712, RES_SHARED_VGA }, 141 { PCI_CHIP_SMI720, PCI_CHIP_SMI720, RES_SHARED_VGA }, 142 { PCI_CHIP_SMI731, PCI_CHIP_SMI731, RES_SHARED_VGA }, 143 { PCI_CHIP_SMI501, PCI_CHIP_SMI501, RES_UNDEFINED }, 144 { -1, -1, RES_UNDEFINED } 145}; 146 147typedef enum 148{ 149 OPTION_PCI_BURST, 150 OPTION_PCI_RETRY, 151 OPTION_NOACCEL, 152 OPTION_MCLK, 153 OPTION_MXCLK, 154 OPTION_SWCURSOR, 155 OPTION_HWCURSOR, 156 OPTION_VIDEOKEY, 157 OPTION_BYTESWAP, 158 /* CZ 26.10.2001: interlaced video */ 159 OPTION_INTERLACED, 160 /* end CZ */ 161 OPTION_USEBIOS, 162 OPTION_DUALHEAD, 163 OPTION_ACCELMETHOD, 164 OPTION_PANEL_SIZE, 165 OPTION_USE_FBDEV, 166 OPTION_CSCVIDEO, 167 NUMBER_OF_OPTIONS 168} SMIOpts; 169 170static const OptionInfoRec SMIOptions[] = 171{ 172 { OPTION_PCI_BURST, "pci_burst", OPTV_BOOLEAN, {0}, TRUE }, 173 { OPTION_PCI_RETRY, "pci_retry", OPTV_BOOLEAN, {0}, TRUE }, 174 { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 175 { OPTION_MCLK, "MCLK", OPTV_FREQ, {0}, FALSE }, 176 { OPTION_MXCLK, "MXCLK", OPTV_FREQ, {0}, FALSE }, 177 { OPTION_HWCURSOR, "HWCursor", OPTV_BOOLEAN, {0}, TRUE }, 178 { OPTION_SWCURSOR, "SWCursor", OPTV_BOOLEAN, {0}, FALSE }, 179 { OPTION_VIDEOKEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, 180 { OPTION_BYTESWAP, "ByteSwap", OPTV_BOOLEAN, {0}, FALSE }, 181 /* CZ 26.10.2001: interlaced video */ 182 { OPTION_INTERLACED, "Interlaced", OPTV_BOOLEAN, {0}, FALSE }, 183 /* end CZ */ 184 { OPTION_USEBIOS, "UseBIOS", OPTV_BOOLEAN, {0}, FALSE }, 185 { OPTION_DUALHEAD, "Dualhead", OPTV_BOOLEAN, {0}, TRUE }, 186 { OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING, {0}, FALSE }, 187 { OPTION_PANEL_SIZE, "PanelSize", OPTV_ANYSTR, {0}, FALSE }, 188 { OPTION_USE_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE }, 189 { OPTION_CSCVIDEO, "CSCVideo", OPTV_BOOLEAN, {0}, TRUE }, 190 { -1, NULL, OPTV_NONE, {0}, FALSE } 191}; 192 193/* 194 * Lists of symbols that may/may not be required by this driver. 195 * This allows the loader to know which ones to issue warnings for. 196 * 197 * Note that vgahwSymbols and xaaSymbols are referenced outside the 198 * XFree86LOADER define in later code, so are defined outside of that 199 * define here also. 200 */ 201 202static const char *vgahwSymbols[] = 203{ 204 "vgaHWCopyReg", 205 "vgaHWGetHWRec", 206 "vgaHWGetIOBase", 207 "vgaHWGetIndex", 208 "vgaHWInit", 209 "vgaHWLock", 210 "vgaHWMapMem", 211 "vgaHWProtect", 212 "vgaHWRestore", 213 "vgaHWSave", 214 "vgaHWSaveScreen", 215 "vgaHWSetMmioFuncs", 216 "vgaHWSetStdFuncs", 217 "vgaHWUnmapMem", 218 "vgaHWddc1SetSpeedWeak", 219 NULL 220}; 221 222static const char *xaaSymbols[] = 223{ 224 "XAAGetCopyROP", 225 "XAACreateInfoRec", 226 "XAADestroyInfoRec", 227 "XAAGetFallbackOps", 228 "XAAInit", 229 "XAAGetPatternROP", 230 NULL 231}; 232 233static const char *exaSymbols[] = 234{ 235 "exaDriverAlloc", 236 "exaDriverInit", 237 "exaDriverFini", 238 "exaOffscreenAlloc", 239 "exaOffscreenFree", 240 "exaGetPixmapPitch", 241 "exaGetPixmapOffset", 242 "exaGetPixmapSize", 243 NULL 244}; 245 246static const char *ddcSymbols[] = 247{ 248 "xf86PrintEDID", 249 "xf86DoEDID_DDC1", 250 "xf86DoEDID_DDC2", 251 "xf86SetDDCproperties", 252 NULL 253}; 254 255static const char *i2cSymbols[] = 256{ 257 "xf86CreateI2CBusRec", 258 "xf86CreateI2CDevRec", 259 "xf86DestroyI2CBusRec", 260 "xf86DestroyI2CDevRec", 261 "xf86I2CBusInit", 262 "xf86I2CDevInit", 263 "xf86I2CReadBytes", 264 "xf86I2CWriteByte", 265 NULL 266}; 267 268static const char *int10Symbols[] = 269{ 270 "xf86ExecX86int10", 271 "xf86FreeInt10", 272 "xf86InitInt10", 273 NULL 274}; 275 276static const char *vbeSymbols[] = 277{ 278 "VBEInit", 279 "vbeDoEDID", 280 "vbeFree", 281 NULL 282}; 283 284static const char *fbSymbols[] = 285{ 286 "fbPictureInit", 287 "fbScreenInit", 288 NULL 289}; 290 291#ifdef XFree86LOADER 292 293static MODULESETUPPROTO(siliconmotionSetup); 294 295static XF86ModuleVersionInfo SMIVersRec = 296{ 297 "siliconmotion", 298 MODULEVENDORSTRING, 299 MODINFOSTRING1, 300 MODINFOSTRING2, 301 XORG_VERSION_CURRENT, 302 SILICONMOTION_VERSION_MAJOR, 303 SILICONMOTION_VERSION_MINOR, 304 SILICONMOTION_PATCHLEVEL, 305 ABI_CLASS_VIDEODRV, 306 ABI_VIDEODRV_VERSION, 307 MOD_CLASS_VIDEODRV, 308 {0, 0, 0, 0} 309}; 310 311/* 312 * This is the module init data for XFree86 modules. 313 * 314 * Its name has to be the driver name followed by ModuleData. 315 */ 316_X_EXPORT XF86ModuleData siliconmotionModuleData = 317{ 318 &SMIVersRec, 319 siliconmotionSetup, 320 NULL 321}; 322 323static pointer 324siliconmotionSetup(pointer module, pointer opts, int *errmaj, int *errmin) 325{ 326 static Bool setupDone = FALSE; 327 328 if (!setupDone) { 329 setupDone = TRUE; 330 xf86AddDriver(&SILICONMOTION, module, 0); 331 332 /* 333 * Modules that this driver always requires can be loaded here 334 * by calling LoadSubModule(). 335 */ 336 337 /* 338 * Tell the loader about symbols from other modules that this module 339 * might refer to. 340 */ 341 LoaderRefSymLists(vgahwSymbols, fbSymbols, xaaSymbols, exaSymbols, 342 ddcSymbols, i2cSymbols, int10Symbols, vbeSymbols, 343 NULL); 344 345 /* 346 * The return value must be non-NULL on success even though there 347 * is no TearDownProc. 348 */ 349 return (pointer) 1; 350 351 } else { 352 if (errmaj) { 353 *errmaj = LDR_ONCEONLY; 354 } 355 return NULL; 356 } 357} 358 359#endif /* XFree86LOADER */ 360 361static Bool 362SMI_GetRec(ScrnInfoPtr pScrn) 363{ 364 ENTER(); 365 366 /* 367 * Allocate an 'Chip'Rec, and hook it into pScrn->driverPrivate. 368 * pScrn->driverPrivate is initialised to NULL, so we can check if 369 * the allocation has already been done. 370 */ 371 if (pScrn->driverPrivate == NULL) { 372 pScrn->driverPrivate = xnfcalloc(sizeof(SMIRec), 1); 373 } 374 375 LEAVE(TRUE); 376} 377 378static void 379SMI_FreeRec(ScrnInfoPtr pScrn) 380{ 381 SMIPtr pSmi = SMIPTR(pScrn); 382 383 ENTER(); 384 385 if (pSmi) { 386 xfree(pSmi->save); 387 xfree(pSmi->mode); 388 xfree(pScrn->driverPrivate); 389 pScrn->driverPrivate = NULL; 390 } 391 392 LEAVE(); 393} 394 395static const OptionInfoRec * 396SMI_AvailableOptions(int chipid, int busid) 397{ 398 ENTER(); 399 400 LEAVE(SMIOptions); 401} 402 403static void 404SMI_Identify(int flags) 405{ 406 ENTER(); 407 408 xf86PrintChipsets(SILICONMOTION_NAME, "driver (version " 409 SILICONMOTION_VERSION_NAME ") for Silicon Motion Lynx chipsets", 410 SMIChipsets); 411 412 LEAVE(); 413} 414 415static Bool 416SMI_Probe(DriverPtr drv, int flags) 417{ 418 int i; 419 GDevPtr *devSections; 420 int *usedChips; 421 int numDevSections; 422 int numUsed; 423 Bool foundScreen = FALSE; 424 425 ENTER(); 426 427 numDevSections = xf86MatchDevice(SILICONMOTION_DRIVER_NAME, &devSections); 428 429 if (numDevSections <= 0) 430 /* There's no matching device section in the config file, so quit now. */ 431 LEAVE(FALSE); 432 433#ifndef XSERVER_LIBPCIACCESS 434 if (xf86GetPciVideoInfo() == NULL) 435 LEAVE(FALSE); 436#endif 437 438 numUsed = xf86MatchPciInstances(SILICONMOTION_NAME, PCI_SMI_VENDOR_ID, 439 SMIChipsets, SMIPciChipsets, devSections, 440 numDevSections, drv, &usedChips); 441 442 /* Free it since we don't need that list after this */ 443 xfree(devSections); 444 if (numUsed <= 0) 445 LEAVE(FALSE); 446 447 if (flags & PROBE_DETECT) 448 foundScreen = TRUE; 449 else { 450 ScrnInfoPtr pScrn; 451 EntityInfoPtr pEnt; 452 453 for (i = 0; i < numUsed; i++) { 454 if ((pScrn = xf86ConfigPciEntity(NULL, 0, usedChips[i], 455 SMIPciChipsets, NULL, 456 NULL, NULL, NULL, NULL))) { 457 pScrn->driverVersion = SILICONMOTION_DRIVER_VERSION; 458 pScrn->driverName = SILICONMOTION_DRIVER_NAME; 459 pScrn->name = SILICONMOTION_NAME; 460 pScrn->Probe = SMI_Probe; 461 pScrn->PreInit = SMI_PreInit; 462 pScrn->ScreenInit = SMI_ScreenInit; 463 pScrn->SwitchMode = SMI_SwitchMode; 464 pScrn->AdjustFrame = SMI_AdjustFrame; 465 466 if ((pEnt = xf86GetEntityInfo(usedChips[i]))) { 467 pScrn->EnterVT = SMI_EnterVT; 468 pScrn->LeaveVT = SMI_LeaveVT; 469 xfree(pEnt); 470 } 471 pScrn->FreeScreen = SMI_FreeScreen; 472 foundScreen = TRUE; 473 } 474 } 475 } 476 xfree(usedChips); 477 478 LEAVE(foundScreen); 479} 480 481static Bool 482SMI_PreInit(ScrnInfoPtr pScrn, int flags) 483{ 484 EntityInfoPtr pEnt; 485 SMIPtr pSmi; 486 MessageType from; 487 vgaHWPtr hwp; 488 489 ENTER(); 490 491 /* Ignoring the Type list for now. It might be needed when multiple cards 492 * are supported. 493 */ 494 if (pScrn->numEntities > 1) 495 LEAVE(FALSE); 496 497 /* Allocate the SMIRec driverPrivate */ 498 if (!SMI_GetRec(pScrn)) 499 LEAVE(FALSE); 500 pSmi = SMIPTR(pScrn); 501 502 /* Find the PCI slot for this screen */ 503 pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 504 505 pSmi->PciInfo = xf86GetPciInfoForEntity(pEnt->index); 506 pSmi->Chipset = PCI_DEV_DEVICE_ID(pSmi->PciInfo); 507 508 if (IS_MSOC(pSmi)) { 509 pSmi->Save = SMI501_Save; 510 pSmi->save = xnfcalloc(sizeof(MSOCRegRec), 1); 511 pSmi->mode = xnfcalloc(sizeof(MSOCRegRec), 1); 512 } 513 else { 514 pSmi->Save = SMILynx_Save; 515 pSmi->save = xnfcalloc(sizeof(SMIRegRec), 1); 516 pSmi->mode = xnfcalloc(sizeof(SMIRegRec), 1); 517 } 518 519 if (flags & PROBE_DETECT) { 520 if (!IS_MSOC(pSmi)) 521 SMI_ProbeDDC(pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index); 522 LEAVE(TRUE); 523 } 524 525 if (pEnt->location.type != BUS_PCI || pEnt->resources) { 526 xfree(pEnt); 527 SMI_FreeRec(pScrn); 528 LEAVE(FALSE); 529 } 530 pSmi->PciInfo = xf86GetPciInfoForEntity(pEnt->index); 531 532 /* Set pScrn->monitor */ 533 pScrn->monitor = pScrn->confScreen->monitor; 534 535 if (!IS_MSOC(pSmi)) { 536 /* The vgahw module should be loaded here when needed */ 537 if (!xf86LoadSubModule(pScrn, "vgahw")) 538 LEAVE(FALSE); 539 540 xf86LoaderReqSymLists(vgahwSymbols, NULL); 541 542 /* 543 * Allocate a vgaHWRec 544 */ 545 if (!vgaHWGetHWRec(pScrn)) 546 LEAVE(FALSE); 547 548 hwp = VGAHWPTR(pScrn); 549 pSmi->PIOBase = hwp->PIOOffset; 550 551 xf86ErrorFVerb(VERBLEV, "\tSMI_PreInit vgaCRIndex=%x, vgaIOBase=%x, " 552 "MMIOBase=%p\n", hwp->IOBase + VGA_CRTC_INDEX_OFFSET, 553 hwp->IOBase, hwp->MMIOBase); 554 } 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(FALSE); 561 562 /* Check that the returned depth is one we support */ 563 if (pScrn->depth != 8 && pScrn->depth != 16 && pScrn->depth != 24) { 564 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 565 "Given depth (%d) is not supported by this driver\n", 566 pScrn->depth); 567 LEAVE(FALSE); 568 } 569 570 571 if(pScrn->bitsPerPixel != 8 && pScrn->bitsPerPixel != 16 && 572 pScrn->bitsPerPixel != 24 && pScrn->bitsPerPixel != 32){ 573 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 574 "Given bpp (%d) is not supported by this driver\n", 575 pScrn->bitsPerPixel); 576 LEAVE(FALSE); 577 } 578 579 xf86PrintDepthBpp(pScrn); 580 581 /* 582 * This must happen after pScrn->display has been set because 583 * xf86SetWeight references it. 584 */ 585 if (pScrn->depth > 8) { 586 /* The defaults are OK for us */ 587 rgb zeros = {0, 0, 0}; 588#if __BYTE_ORDER == __BIG_ENDIAN 589 rgb masks = {0xff00,0xff0000,0xff000000}; 590#else 591 rgb masks = {0, 0, 0}; 592#endif 593 594 if (!xf86SetWeight(pScrn, zeros, masks)) 595 LEAVE(FALSE); 596 } 597 598 if (!xf86SetDefaultVisual(pScrn, -1)) 599 LEAVE(FALSE); 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(FALSE); 607 } 608 609 /* We use a programmable clock */ 610 pScrn->progClock = TRUE; 611 612 /* Collect all of the relevant option flags (fill in pScrn->options) */ 613 xf86CollectOptions(pScrn, NULL); 614 615 /* Set the bits per RGB for 8bpp mode */ 616 if (pScrn->depth == 8){ 617 pScrn->rgbBits = IS_MSOC(pSmi) ? 8 : 6; 618 }else if(pScrn->depth == 16){ 619 /* Use 8 bit LUT for gamma correction*/ 620 pScrn->rgbBits = 8; 621 } 622 623 /* Process the options */ 624 if (!(pSmi->Options = xalloc(sizeof(SMIOptions)))) 625 LEAVE(FALSE); 626 627 memcpy(pSmi->Options, SMIOptions, sizeof(SMIOptions)); 628 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pSmi->Options); 629 630 /* Enable pci burst by default */ 631 from = X_DEFAULT; 632 pSmi->PCIBurst = TRUE; 633 if (xf86GetOptValBool(pSmi->Options, OPTION_PCI_BURST, &pSmi->PCIBurst)) 634 from = X_CONFIG; 635 xf86DrvMsg(pScrn->scrnIndex, from, "PCI Burst %sabled\n", 636 pSmi->PCIBurst ? "en" : "dis"); 637 638 /* Pci retry enabled by default if pci burst also enabled */ 639 from = X_DEFAULT; 640 pSmi->PCIRetry = pSmi->PCIBurst ? TRUE : FALSE; 641 if (xf86GetOptValBool(pSmi->Options, OPTION_PCI_RETRY, &pSmi->PCIRetry)) { 642 from = X_CONFIG; 643 if (pSmi->PCIRetry && !pSmi->PCIBurst) { 644 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 645 "\"pci_retry\" option requires \"pci_burst\".\n"); 646 pSmi->PCIRetry = FALSE; 647 } 648 } 649 xf86DrvMsg(pScrn->scrnIndex, from, "PCI Retry %sabled\n", 650 pSmi->PCIRetry ? "en" : "dis"); 651 652 if (xf86ReturnOptValBool(pSmi->Options, OPTION_NOACCEL, FALSE)) { 653 pSmi->NoAccel = TRUE; 654 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: NoAccel - Acceleration " 655 "disabled\n"); 656 } else { 657 pSmi->NoAccel = FALSE; 658 } 659 660 if (IS_MSOC(pSmi)) { 661 from = X_DEFAULT; 662 if (xf86GetOptValBool(pSmi->Options, OPTION_USE_FBDEV, &pSmi->UseFBDev)) 663 from = X_CONFIG; 664 xf86DrvMsg(pScrn->scrnIndex, from, "UseFBDev %s.\n", 665 pSmi->UseFBDev ? "enabled" : "disabled"); 666 } 667 668 from = X_CONFIG; 669 pSmi->HwCursor = TRUE; 670 /* SWCursor overrides HWCusor if both specified */ 671 if (xf86ReturnOptValBool(pSmi->Options, OPTION_SWCURSOR, FALSE)) 672 pSmi->HwCursor = FALSE; 673 else if (!xf86GetOptValBool(pSmi->Options, OPTION_HWCURSOR, &pSmi->HwCursor)) 674 from = X_DEFAULT; 675 676 xf86DrvMsg(pScrn->scrnIndex, from, "Using %sware Cursor\n", 677 pSmi->HwCursor ? "Hard" : "Soft"); 678 679 if (xf86GetOptValInteger(pSmi->Options, OPTION_VIDEOKEY, &pSmi->videoKey)) { 680 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: Video key set to " 681 "0x%08X\n", pSmi->videoKey); 682 } else { 683 pSmi->videoKey = (1 << pScrn->offset.red) | 684 (1 << pScrn->offset.green) | 685 (((pScrn->mask.blue >> pScrn->offset.blue) - 1) 686 << pScrn->offset.blue); 687 } 688 689 if (xf86ReturnOptValBool(pSmi->Options, OPTION_BYTESWAP, FALSE)) { 690 pSmi->ByteSwap = TRUE; 691 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: ByteSwap enabled.\n"); 692 } else { 693 pSmi->ByteSwap = FALSE; 694 } 695 696 /* CZ 26.10.2001: interlaced video */ 697 if (xf86ReturnOptValBool(pSmi->Options, OPTION_INTERLACED, FALSE)) { 698 pSmi->interlaced = TRUE; 699 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: Interlaced enabled.\n"); 700 } else { 701 pSmi->interlaced = FALSE; 702 } 703 /* end CZ */ 704 705 if (IS_MSOC(pSmi)) 706 pSmi->useBIOS = FALSE; 707 else if (xf86GetOptValBool(pSmi->Options, OPTION_USEBIOS, &pSmi->useBIOS)) { 708 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: UseBIOS %s.\n", 709 pSmi->useBIOS ? "enabled" : "disabled"); 710 } 711 else if(pSmi->Chipset == SMI_LYNX3DM){ 712 /* Default to UseBIOS disabled. */ 713 pSmi->useBIOS = FALSE; 714 } 715 else { 716 /* Default to UseBIOS enabled. */ 717 pSmi->useBIOS = TRUE; 718 } 719 720 if (pSmi->useBIOS) { 721 if (xf86LoadSubModule(pScrn,"int10")) { 722 xf86LoaderReqSymLists(int10Symbols,NULL); 723 pSmi->pInt10 = xf86InitInt10(pEnt->index); 724 } 725 726 if (pSmi->pInt10 && xf86LoadSubModule(pScrn, "vbe")) { 727 xf86LoaderReqSymLists(vbeSymbols, NULL); 728 pSmi->pVbe = VBEInit(pSmi->pInt10, pEnt->index); 729 } 730 731 if(!pSmi->pVbe){ 732 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VBE initialization failed: falling back to UseBIOS disabled.\n"); 733 pSmi->useBIOS = FALSE; 734 } 735 } 736 737 xf86RegisterResources(pEnt->index, NULL, ResExclusive); 738/* xf86SetOperatingState(resVgaIo, pEnt->index, ResUnusedOpr); */ 739/* xf86SetOperatingState(resVgaMem, pEnt->index, ResDisableOpr); */ 740 741 /* 742 * Set the Chipset and ChipRev, allowing config file entries to 743 * override. 744 */ 745 if (pEnt->device->chipset && *pEnt->device->chipset) { 746 pScrn->chipset = pEnt->device->chipset; 747 pSmi->Chipset = xf86StringToToken(SMIChipsets, pScrn->chipset); 748 from = X_CONFIG; 749 } 750 else if (pEnt->device->chipID >= 0) { 751 pSmi->Chipset = pEnt->device->chipID; 752 pScrn->chipset = (char *) xf86TokenToString(SMIChipsets, pSmi->Chipset); 753 from = X_CONFIG; 754 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", 755 pSmi->Chipset); 756 } 757 else { 758 from = X_PROBED; 759 pSmi->Chipset = PCI_DEV_DEVICE_ID(pSmi->PciInfo); 760 pScrn->chipset = (char *) xf86TokenToString(SMIChipsets, pSmi->Chipset); 761 } 762 763 if (pEnt->device->chipRev >= 0) { 764 pSmi->ChipRev = pEnt->device->chipRev; 765 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 766 pSmi->ChipRev); 767 } 768 else 769 pSmi->ChipRev = PCI_DEV_REVISION(pSmi->PciInfo); 770 xfree(pEnt); 771 772 /* 773 * This shouldn't happen because such problems should be caught in 774 * SMI_Probe(), but check it just in case. 775 */ 776 if (pScrn->chipset == NULL) { 777 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ChipID 0x%04X is not " 778 "recognised\n", pSmi->Chipset); 779 LEAVE(FALSE); 780 } 781 782 if (pSmi->Chipset < 0) { 783 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Chipset \"%s\" is not " 784 "recognised\n", pScrn->chipset); 785 LEAVE(FALSE); 786 } 787 788 xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset); 789 790#ifndef XSERVER_LIBPCIACCESS 791 pSmi->PciTag = pciTag(pSmi->PciInfo->bus, pSmi->PciInfo->device, 792 pSmi->PciInfo->func); 793#endif 794 795 from = X_DEFAULT; 796 if(pSmi->Chipset == SMI_LYNX3DM && 797 pScrn->bitsPerPixel == 16) 798 pSmi->Dualhead = TRUE; 799 else 800 pSmi->Dualhead = FALSE; 801 802 if (xf86GetOptValBool(pSmi->Options, OPTION_DUALHEAD, &pSmi->Dualhead)) 803 from = X_CONFIG; 804 805 if (IS_MSOC(pSmi)) { 806 pSmi->lcd = TRUE; 807 if (pSmi->Dualhead && pSmi->UseFBDev) { 808 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 809 "Dual head disabled in fbdev mode\n"); 810 pSmi->Dualhead = FALSE; 811 } 812 /* FIXME Randr cursor code only works properly when argb cursors 813 * are also supported. 814 * FIXME This probably is a randr cursor bug, and since access to 815 * hw/xfree86/ramdac/xf86CursorPriv.h:xf86CursorScreenRec.SWCursor 816 * field is not available, one cannot easily workaround the problem, 817 * so, just disable it... 818 * TODO Check with a X Server newer then 1.4.0.90 (that is being 819 * used in the 502 OEM image). 820 * */ 821 if (pSmi->Dualhead && pSmi->HwCursor) { 822 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 823 "HW Cursor disabled in dual head mode\n"); 824 pSmi->HwCursor = FALSE; 825 } 826 } 827 else if (SMI_LYNXM_SERIES(pSmi->Chipset)) { 828 /* tweak options for dualhead */ 829 if (pSmi->Dualhead) { 830 pSmi->useBIOS = FALSE; 831 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "UseBIOS disabled in dualhead mode\n"); 832 pSmi->HwCursor = FALSE; 833 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No hardware cursor in dualhead mode\n"); 834 if (pScrn->bitsPerPixel != 16) { 835 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Dualhead only supported at " 836 "depth 16\n"); 837 LEAVE(FALSE); 838 } 839 } 840 } 841 xf86DrvMsg(pScrn->scrnIndex, from, "Dual head %sabled\n", 842 pSmi->Dualhead ? "en" : "dis"); 843 844 if (!pSmi->NoAccel) { 845 char *strptr; 846 847 from = X_DEFAULT; 848 if ((strptr = (char *)xf86GetOptValString(pSmi->Options, 849 OPTION_ACCELMETHOD))) { 850 if (!xf86NameCmp(strptr,"XAA")) { 851 from = X_CONFIG; 852 pSmi->useEXA = FALSE; 853 } else if(!xf86NameCmp(strptr,"EXA")) { 854 from = X_CONFIG; 855 pSmi->useEXA = TRUE; 856 } 857 } 858 859 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration architecture\n", 860 pSmi->useEXA ? "EXA" : "XAA"); 861 } 862 863 if (IS_MSOC(pSmi)) { 864 pSmi->CSCVideo = !pSmi->useEXA || !pSmi->Dualhead; 865 from = X_DEFAULT; 866 if (xf86GetOptValBool(pSmi->Options, OPTION_CSCVIDEO, &pSmi->CSCVideo)) { 867 from = X_CONFIG; 868 869 /* FIXME */ 870 if (pSmi->CSCVideo && pSmi->useEXA && pSmi->Dualhead) { 871 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 872 "CSCVideo requires XAA or EXA in single head mode.\n"); 873 pSmi->CSCVideo = FALSE; 874 } 875 } 876 877 xf86DrvMsg(pScrn->scrnIndex, from, "CSC Video %sabled\n", 878 pSmi->CSCVideo ? "en" : "dis"); 879 } 880 881 SMI_MapMmio(pScrn); 882 SMI_DetectMem(pScrn); 883 SMI_MapMem(pScrn); 884 SMI_DisableVideo(pScrn); 885 886 /* detect the panel size */ 887 SMI_DetectPanelSize(pScrn); 888 889 if(!IS_MSOC(pSmi)){ 890 if (xf86LoadSubModule(pScrn, "i2c")) { 891 xf86LoaderReqSymLists(i2cSymbols, NULL); 892 SMI_I2CInit(pScrn); 893 } 894 if (xf86LoadSubModule(pScrn, "ddc")) { 895 xf86LoaderReqSymLists(ddcSymbols, NULL); 896 } 897 } 898 899 /* 900 * If the driver can do gamma correction, it should call xf86SetGamma() 901 */ 902 { 903 Gamma zeros = { 0.0, 0.0, 0.0 }; 904 905 if (!xf86SetGamma(pScrn, zeros)) { 906 SMI_EnableVideo(pScrn); 907 SMI_UnmapMem(pScrn); 908 LEAVE(FALSE); 909 } 910 } 911 912 SMI_DetectMCLK(pScrn); 913 914 /* 915 * Setup the ClockRanges, which describe what clock ranges are available, 916 * and what sort of modes they can be used for. 917 */ 918 pSmi->clockRange.next = NULL; 919 pSmi->clockRange.minClock = 20000; 920 921 if (SMI_LYNXM_SERIES(pSmi->Chipset) || 922 IS_MSOC(pSmi)) 923 pSmi->clockRange.maxClock = 200000; 924 else 925 pSmi->clockRange.maxClock = 135000; 926 927 pSmi->clockRange.clockIndex = -1; 928 pSmi->clockRange.interlaceAllowed = FALSE; 929 pSmi->clockRange.doubleScanAllowed = FALSE; 930 931 if(!SMI_CrtcPreInit(pScrn)) 932 LEAVE(FALSE); 933 934 if(!SMI_OutputPreInit(pScrn)) 935 LEAVE(FALSE); 936 937 /* Only allow growing the screen dimensions if EXA is being used */ 938 if (!xf86InitialConfiguration (pScrn, !pSmi->NoAccel && pSmi->useEXA)){ 939 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 940 LEAVE(FALSE); 941 } 942 943 944 SMI_EnableVideo(pScrn); 945 SMI_UnmapMem(pScrn); 946 947 if(pSmi->pVbe){ 948 vbeFree(pSmi->pVbe); 949 pSmi->pVbe = NULL; 950 } 951 if(pSmi->pInt10){ 952 xf86FreeInt10(pSmi->pInt10); 953 pSmi->pInt10 = NULL; 954 } 955 956 /* Set display resolution */ 957 xf86SetDpi(pScrn, 0, 0); 958 959 if (xf86LoadSubModule(pScrn, "fb") == NULL) { 960 SMI_FreeRec(pScrn); 961 LEAVE(FALSE); 962 } 963 964 xf86LoaderReqSymLists(fbSymbols, NULL); 965 966 /* Load XAA or EXA if needed */ 967 if (!pSmi->NoAccel) { 968 if (!pSmi->useEXA) { 969 if (!xf86LoadSubModule(pScrn, "xaa")) { 970 SMI_FreeRec(pScrn); 971 LEAVE(FALSE); 972 } 973 xf86LoaderReqSymLists(xaaSymbols, NULL); 974 } else { 975 XF86ModReqInfo req; 976 int errmaj, errmin; 977 978 memset(&req, 0, sizeof(XF86ModReqInfo)); 979 req.majorversion = 2; 980 req.minorversion = 1; 981 982 if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, 983 &req, &errmaj, &errmin)) { 984 LoaderErrorMsg(NULL, "exa", errmaj, errmin); 985 SMI_FreeRec(pScrn); 986 LEAVE(FALSE); 987 } 988 xf86LoaderReqSymLists(exaSymbols, NULL); 989 } 990 } 991 992 /* Load ramdac if needed */ 993 if (pSmi->HwCursor) { 994 if (!xf86LoadSubModule(pScrn, "ramdac")) { 995 SMI_FreeRec(pScrn); 996 LEAVE(FALSE); 997 } 998 } 999 1000 LEAVE(TRUE); 1001} 1002 1003/* 1004 * This is called when VT switching back to the X server. Its job is to 1005 * reinitialise the video mode. We may wish to unmap video/MMIO memory too. 1006 */ 1007 1008static Bool 1009SMI_EnterVT(int scrnIndex, int flags) 1010{ 1011 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1012 SMIPtr pSmi = SMIPTR(pScrn); 1013 1014 ENTER(); 1015 1016 /* Enable MMIO and map memory */ 1017 SMI_MapMem(pScrn); 1018 1019 pSmi->Save(pScrn); 1020 1021 /* FBBase may have changed after remapping the memory */ 1022 pScrn->pScreen->ModifyPixmapHeader(pScrn->pScreen->GetScreenPixmap(pScrn->pScreen), 1023 -1,-1,-1,-1,-1, pSmi->FBBase + pSmi->FBOffset); 1024 pScrn->pixmapPrivate.ptr=pSmi->FBBase + pSmi->FBOffset; 1025 1026 if(pSmi->useEXA) 1027 pSmi->EXADriverPtr->memoryBase=pSmi->FBBase; 1028 1029 /* Do the CRTC independent initialization */ 1030 if(!SMI_HWInit(pScrn)) 1031 LEAVE(FALSE); 1032 1033 /* Initialize the chosen modes */ 1034 if (!xf86SetDesiredModes(pScrn)) 1035 LEAVE(FALSE); 1036 1037 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1038 "Done writing mode. Register dump:\n"); 1039 SMI_PrintRegs(pScrn); 1040 1041 /* Reset the grapics engine */ 1042 if (!pSmi->NoAccel) 1043 SMI_EngineReset(pScrn); 1044 1045 LEAVE(TRUE); 1046} 1047 1048/* 1049 * This is called when VT switching away from the X server. Its job is to 1050 * restore the previous (text) mode. We may wish to remap video/MMIO memory 1051 * too. 1052 */ 1053 1054static void 1055SMI_LeaveVT(int scrnIndex, int flags) 1056{ 1057 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1058 SMIPtr pSmi = SMIPTR(pScrn); 1059 1060 ENTER(); 1061 1062 SMI_AccelSync(pScrn); 1063 1064 /* Ensure that the rotation BlockHandler is unwrapped, and the shadow 1065 pixmaps are deallocated, as the video memory is going to be 1066 unmapped. */ 1067 xf86RotateCloseScreen(pScrn->pScreen); 1068 1069 /* Pixmaps that by chance get allocated near the former aperture 1070 address shouldn't be considered offscreen. */ 1071 if(pSmi->useEXA) 1072 pSmi->EXADriverPtr->memoryBase=NULL; 1073 1074 /* Clear frame buffer */ 1075 memset(pSmi->FBBase, 0, pSmi->videoRAMBytes); 1076 1077 if (!IS_MSOC(pSmi)) { 1078 vgaHWPtr hwp = VGAHWPTR(pScrn); 1079 1080 SMILynx_WriteMode(pScrn, &hwp->SavedReg, pSmi->save); 1081 } 1082 else 1083 SMI501_WriteMode(pScrn, pSmi->save); 1084 1085 SMI_UnmapMem(pScrn); 1086 1087 LEAVE(); 1088} 1089 1090static void 1091SMI_DetectPanelSize(ScrnInfoPtr pScrn) 1092{ 1093 char *s; 1094 int width, height; 1095 SMIPtr pSmi = SMIPTR(pScrn); 1096 1097 pSmi->lcdWidth = 0; 1098 pSmi->lcdHeight = 0; 1099 if ((s = xf86GetOptValString(pSmi->Options, OPTION_PANEL_SIZE)) != NULL) { 1100 if (sscanf(s, "%dx%d", &width, &height) != 2) 1101 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1102 "Invalid PanelSize option: %s\n", s); 1103 else { 1104 pSmi->lcdWidth = width; 1105 pSmi->lcdHeight = height; 1106 } 1107 } 1108 1109 if (pSmi->lcdWidth == 0 || pSmi->lcdHeight == 0) { 1110 /* panel size detection ... requires BIOS call on 730 hardware */ 1111 if (pSmi->Chipset == SMI_COUGAR3DR) { 1112 if (pSmi->pInt10 != NULL) { 1113 pSmi->pInt10->num = 0x10; 1114 pSmi->pInt10->ax = 0x5F00; 1115 pSmi->pInt10->bx = 0; 1116 pSmi->pInt10->cx = 0; 1117 pSmi->pInt10->dx = 0; 1118 xf86ExecX86int10(pSmi->pInt10); 1119 if (pSmi->pInt10->ax == 0x005F) { 1120 switch (pSmi->pInt10->cx & 0x0F) { 1121 case PANEL_640x480: 1122 pSmi->lcdWidth = 640; 1123 pSmi->lcdHeight = 480; 1124 break; 1125 case PANEL_800x600: 1126 pSmi->lcdWidth = 800; 1127 pSmi->lcdHeight = 600; 1128 break; 1129 case PANEL_1024x768: 1130 pSmi->lcdWidth = 1024; 1131 pSmi->lcdHeight = 768; 1132 break; 1133 case PANEL_1280x1024: 1134 pSmi->lcdWidth = 1280; 1135 pSmi->lcdHeight = 1024; 1136 break; 1137 case PANEL_1600x1200: 1138 pSmi->lcdWidth = 1600; 1139 pSmi->lcdHeight = 1200; 1140 break; 1141 case PANEL_1400x1050: 1142 pSmi->lcdWidth = 1400; 1143 pSmi->lcdHeight = 1050; 1144 break; 1145 } 1146 1147 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1148 "Detected panel size via BIOS: %d x %d\n", 1149 pSmi->lcdWidth, pSmi->lcdHeight); 1150 } 1151 else 1152 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1153 "BIOS error during 730 panel detection!\n"); 1154 } 1155 else { 1156 /* int10 support isn't setup on the second call to this function, 1157 o if this is the second call, don't do detection again */ 1158 if (pSmi->lcd == 0) 1159 /* If we get here, int10 support is not loaded or not working */ 1160 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1161 "No BIOS support for 730 panel detection!\n"); 1162 } 1163 1164 /* Set this to indicate that we've done the detection */ 1165 pSmi->lcd = 1; 1166 } 1167 else if (IS_MSOC(pSmi)) { 1168 pSmi->lcdWidth = (READ_SCR(pSmi, PANEL_WWIDTH) >> 16) & 2047; 1169 pSmi->lcdHeight = (READ_SCR(pSmi, PANEL_WHEIGHT) >> 16) & 2047; 1170 } 1171 else { 1172 /* panel size detection for hardware other than 730 */ 1173 pSmi->lcd = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 1174 0x31) & 0x01; 1175 1176 if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 1177 0x30) & 0x01) { 1178 pSmi->lcd <<= 1; 1179 } 1180 switch (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 1181 0x30) & 0x0C) { 1182 case 0x00: 1183 pSmi->lcdWidth = 640; 1184 pSmi->lcdHeight = 480; 1185 break; 1186 case 0x04: 1187 pSmi->lcdWidth = 800; 1188 pSmi->lcdHeight = 600; 1189 break; 1190 case 0x08: 1191 if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 1192 0x74) & 0x02) { 1193 pSmi->lcdWidth = 1024; 1194 pSmi->lcdHeight = 600; 1195 } 1196 else { 1197 pSmi->lcdWidth = 1024; 1198 pSmi->lcdHeight = 768; 1199 } 1200 break; 1201 case 0x0C: 1202 pSmi->lcdWidth = 1280; 1203 pSmi->lcdHeight = 1024; 1204 break; 1205 } 1206 } 1207 } 1208 1209 if (!pSmi->lcdWidth && (pSmi->lcdWidth = pScrn->virtualX) == 0) 1210 pSmi->lcdWidth = 1024; 1211 if (!pSmi->lcdHeight && (pSmi->lcdHeight = pScrn->virtualY) == 0) 1212 pSmi->lcdHeight = 768; 1213 1214 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s Panel Size = %dx%d\n", 1215 (pSmi->lcd == 0) ? "OFF" : (pSmi->lcd == 1) ? "TFT" : "DSTN", 1216 pSmi->lcdWidth, pSmi->lcdHeight); 1217 1218} 1219 1220static void 1221SMI_DetectMCLK(ScrnInfoPtr pScrn) 1222{ 1223 double real; 1224 MSOCClockRec clock; 1225 int mclk, mxclk; 1226 SMIPtr pSmi = SMIPTR(pScrn); 1227 1228 /* MCLK defaults */ 1229 if (pSmi->Chipset == SMI_LYNXEMplus){ 1230 /* The SM712 can be safely clocked up to 157MHz, according to 1231 Silicon Motion engineers. */ 1232 pSmi->MCLK = 157000; 1233 }else 1234 pSmi->MCLK = 0; 1235 1236 pSmi->MXCLK = 0; 1237 1238 /* MCLK from user settings */ 1239 if (xf86GetOptValFreq(pSmi->Options, OPTION_MCLK, OPTUNITS_MHZ, &real)) { 1240 if (IS_MSOC(pSmi) || (int)real <= 120) { 1241 pSmi->MCLK = (int)(real * 1000.0); 1242 } else { 1243 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1244 "Memory Clock %1.3f MHz larger than limit of 120 MHz\n", 1245 real); 1246 } 1247 } 1248 mclk = pSmi->MCLK; 1249 1250 if (IS_MSOC(pSmi)) { 1251 clock.value = READ_SCR(pSmi, CURRENT_CLOCK); 1252 if (xf86GetOptValFreq(pSmi->Options, OPTION_MXCLK, 1253 OPTUNITS_MHZ, &real)) 1254 pSmi->MXCLK = (int)(real * 1000.0); 1255 } 1256 1257 /* Already programmed MCLK */ 1258 if (pSmi->MCLK == 0) { 1259 if (IS_MSOC(pSmi)) 1260 mclk = ((clock.f.m_select ? 336 : 288) / 1261 ((clock.f.m_divider ? 3 : 1) << 1262 (unsigned)clock.f.m_shift)) * 1000; 1263 else { 1264 unsigned char shift, m, n; 1265 1266 m = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A); 1267 n = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B); 1268 switch (n >> 6) { 1269 case 1: 1270 shift = 4; 1271 break; 1272 case 2: 1273 shift = 2; 1274 break; 1275 default: 1276 shift = 1; 1277 break; 1278 } 1279 n &= 0x3F; 1280 mclk = ((1431818 * m) / n / shift + 50) / 100; 1281 } 1282 } 1283 1284 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MCLK = %1.3f\n", mclk / 1000.0); 1285 if (IS_MSOC(pSmi)) { 1286 if (pSmi->MXCLK == 0) { 1287 mxclk = ((clock.f.m1_select ? 336 : 288) / 1288 ((clock.f.m1_divider ? 3 : 1) << 1289 (unsigned)clock.f.m1_shift)) * 1000; 1290 } 1291 else 1292 mxclk = pSmi->MXCLK; 1293 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MXCLK = %1.3f\n", mxclk / 1000.0); 1294 } 1295} 1296 1297static Bool 1298SMI_MapMmio(ScrnInfoPtr pScrn) 1299{ 1300 SMIPtr pSmi = SMIPTR(pScrn); 1301 CARD32 memBase; 1302 1303 SMI_EnableMmio(pScrn); 1304 1305 switch (pSmi->Chipset) { 1306 case SMI_COUGAR3DR: 1307 memBase = PCI_REGION_BASE(pSmi->PciInfo, 1, REGION_MEM); 1308 pSmi->MapSize = 0x200000; 1309 break; 1310 case SMI_LYNX3D: 1311 memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x680000; 1312 pSmi->MapSize = 0x180000; 1313 break; 1314 case SMI_LYNXEM: 1315 case SMI_LYNXEMplus: 1316 memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x400000; 1317 pSmi->MapSize = 0x400000; 1318 break; 1319 case SMI_LYNX3DM: 1320 memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM); 1321 pSmi->MapSize = 0x200000; 1322 break; 1323 case SMI_MSOC: 1324 memBase = PCI_REGION_BASE(pSmi->PciInfo, 1, REGION_MEM); 1325 pSmi->MapSize = 0x200000; 1326 break; 1327 default: 1328 memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x400000; 1329 pSmi->MapSize = 0x10000; 1330 break; 1331 } 1332 1333#ifndef XSERVER_LIBPCIACCESS 1334 pSmi->MapBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, pSmi->PciTag, 1335 memBase, pSmi->MapSize); 1336#else 1337 { 1338 void **result = (void**)&pSmi->MapBase; 1339 int err = pci_device_map_range(pSmi->PciInfo, 1340 memBase, 1341 pSmi->MapSize, 1342 PCI_DEV_MAP_FLAG_WRITABLE, 1343 result); 1344 1345 if (err) 1346 return (FALSE); 1347 } 1348#endif 1349 1350 if (pSmi->MapBase == NULL) { 1351 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Internal error: could not map " 1352 "MMIO registers.\n"); 1353 return (FALSE); 1354 } 1355 1356 switch (pSmi->Chipset) { 1357 case SMI_COUGAR3DR: 1358 pSmi->DPRBase = pSmi->MapBase + 0x000000; 1359 pSmi->VPRBase = pSmi->MapBase + 0x000800; 1360 pSmi->CPRBase = pSmi->MapBase + 0x001000; 1361 pSmi->FPRBase = pSmi->MapBase + 0x005800; 1362 pSmi->IOBase = pSmi->MapBase + 0x0C0000; 1363 pSmi->DataPortBase = pSmi->MapBase + 0x100000; 1364 pSmi->DataPortSize = 0x100000; 1365 break; 1366 case SMI_LYNX3D: 1367 pSmi->DPRBase = pSmi->MapBase + 0x000000; 1368 pSmi->VPRBase = pSmi->MapBase + 0x000800; 1369 pSmi->CPRBase = pSmi->MapBase + 0x001000; 1370 pSmi->IOBase = pSmi->MapBase + 0x040000; 1371 pSmi->DataPortBase = pSmi->MapBase + 0x080000; 1372 pSmi->DataPortSize = 0x100000; 1373 break; 1374 case SMI_LYNXEM: 1375 case SMI_LYNXEMplus: 1376 pSmi->DPRBase = pSmi->MapBase + 0x008000; 1377 pSmi->VPRBase = pSmi->MapBase + 0x00C000; 1378 pSmi->CPRBase = pSmi->MapBase + 0x00E000; 1379 pSmi->IOBase = pSmi->MapBase + 0x300000; 1380 pSmi->DataPortBase = pSmi->MapBase /*+ 0x100000*/; 1381 pSmi->DataPortSize = 0x8000 /*0x200000*/; 1382 break; 1383 case SMI_LYNX3DM: 1384 pSmi->DPRBase = pSmi->MapBase + 0x000000; 1385 pSmi->VPRBase = pSmi->MapBase + 0x000800; 1386 pSmi->CPRBase = pSmi->MapBase + 0x001000; 1387 pSmi->IOBase = pSmi->MapBase + 0x0C0000; 1388 pSmi->DataPortBase = pSmi->MapBase + 0x100000; 1389 pSmi->DataPortSize = 0x100000; 1390 break; 1391 case SMI_MSOC: 1392 pSmi->DPRBase = pSmi->MapBase + 0x100000; 1393 pSmi->VPRBase = pSmi->MapBase + 0x000000; 1394 pSmi->CPRBase = pSmi->MapBase + 0x090000; 1395 pSmi->DCRBase = pSmi->MapBase + 0x080000; 1396 pSmi->SCRBase = pSmi->MapBase + 0x000000; 1397 pSmi->IOBase = 0; 1398 pSmi->DataPortBase = pSmi->MapBase + 0x110000; 1399 pSmi->DataPortSize = 0x10000; 1400 break; 1401 default: 1402 pSmi->DPRBase = pSmi->MapBase + 0x8000; 1403 pSmi->VPRBase = pSmi->MapBase + 0xC000; 1404 pSmi->CPRBase = pSmi->MapBase + 0xE000; 1405 pSmi->IOBase = NULL; 1406 pSmi->DataPortBase = pSmi->MapBase; 1407 pSmi->DataPortSize = 0x8000; 1408 break; 1409 } 1410 1411 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1412 "Physical MMIO at 0x%08lX\n", (unsigned long)memBase); 1413 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1414 "Logical MMIO at %p - %p\n", pSmi->MapBase, 1415 pSmi->MapBase + pSmi->MapSize - 1); 1416 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1417 "DPR=%p, VPR=%p, IOBase=%p\n", 1418 pSmi->DPRBase, pSmi->VPRBase, pSmi->IOBase); 1419 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1420 "DataPort=%p - %p\n", pSmi->DataPortBase, 1421 pSmi->DataPortBase + pSmi->DataPortSize - 1); 1422 1423 return (TRUE); 1424} 1425 1426static Bool 1427SMI_DetectMem(ScrnInfoPtr pScrn) 1428{ 1429 SMIPtr pSmi = SMIPTR(pScrn); 1430 MessageType from; 1431 1432 if ((pScrn->videoRam = pScrn->confScreen->device->videoRam)){ 1433 pSmi->videoRAMKBytes = pScrn->videoRam; 1434 from = X_CONFIG; 1435 } 1436 else { 1437 unsigned char config; 1438 static int lynx3d_table[4] = { 0, 2, 4, 6 }; 1439 static int lynx3dm_table[4] = { 16, 2, 4, 8 }; 1440 static int msoc_table[8] = { 4, 8, 16, 32, 64, 2, 0, 0 }; 1441 static int default_table[4] = { 1, 2, 4, 0 }; 1442 1443 if (IS_MSOC(pSmi)) { 1444 config = (READ_SCR(pSmi, DRAM_CTL) >> 13) & 7; 1445 pSmi->videoRAMKBytes = msoc_table[config] * 1024 - 1446 SHARED_USB_DMA_BUFFER_SIZE; 1447 } 1448 else { 1449 config = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x71); 1450 switch (pSmi->Chipset) { 1451 case SMI_LYNX3D: 1452 pSmi->videoRAMKBytes = lynx3d_table[config >> 6] * 1024 + 1453 512; 1454 break; 1455 case SMI_LYNX3DM: 1456 pSmi->videoRAMKBytes = lynx3dm_table[config >> 6] * 1024; 1457 break; 1458 case SMI_COUGAR3DR: 1459 /* DANGER - Cougar3DR BIOS is broken - hardcode video ram 1460 * size per instructions from Silicon Motion engineers */ 1461 pSmi->videoRAMKBytes = 16 * 1024; 1462 break; 1463 default: 1464 pSmi->videoRAMKBytes = default_table[config >> 6] * 1024; 1465 break; 1466 } 1467 } 1468 from = X_PROBED; 1469 } 1470 1471 pSmi->videoRAMBytes = pSmi->videoRAMKBytes * 1024; 1472 pScrn->videoRam = pSmi->videoRAMKBytes; 1473 xf86DrvMsg(pScrn->scrnIndex, from, 1474 "videoram: %dkB\n", pSmi->videoRAMKBytes); 1475 1476 return (TRUE); 1477} 1478 1479Bool 1480SMI_MapMem(ScrnInfoPtr pScrn) 1481{ 1482 SMIPtr pSmi = SMIPTR(pScrn); 1483 vgaHWPtr hwp; 1484 1485 ENTER(); 1486 1487 if (pSmi->MapBase == NULL && SMI_MapMmio(pScrn) == FALSE) 1488 LEAVE(FALSE); 1489 1490 pScrn->memPhysBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM); 1491 1492 if (pSmi->Chipset == SMI_LYNX3DM) 1493 pSmi->fbMapOffset = 0x200000; 1494 else 1495 pSmi->fbMapOffset = 0x0; 1496 1497#ifndef XSERVER_LIBPCIACCESS 1498 pSmi->FBBase = xf86MapPciMem(pScrn->scrnIndex, 1499 VIDMEM_FRAMEBUFFER, 1500 pSmi->PciTag, 1501 pScrn->memPhysBase + pSmi->fbMapOffset, 1502 pSmi->videoRAMBytes); 1503#else 1504 { 1505 void **result = (void**)&pSmi->FBBase; 1506 int err = pci_device_map_range(pSmi->PciInfo, 1507 pScrn->memPhysBase + 1508 pSmi->fbMapOffset, 1509 pSmi->videoRAMBytes, 1510 PCI_DEV_MAP_FLAG_WRITABLE | 1511 PCI_DEV_MAP_FLAG_WRITE_COMBINE, 1512 result); 1513 1514 if (err) 1515 LEAVE(FALSE); 1516 } 1517#endif 1518 1519 if (pSmi->FBBase == NULL) { 1520 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1521 "Internal error: could not map framebuffer.\n"); 1522 LEAVE(FALSE); 1523 } 1524 1525 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1526 "Physical frame buffer at 0x%08lX offset: 0x%08lX\n", 1527 pScrn->memPhysBase, pSmi->fbMapOffset); 1528 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1529 "Logical frame buffer at %p - %p\n", pSmi->FBBase, 1530 pSmi->FBBase + pSmi->videoRAMBytes - 1); 1531 1532 if (IS_MSOC(pSmi)) { 1533 /* Reserve space for panel cursr, and crt if in dual head mode */ 1534#if SMI_CURSOR_ALPHA_PLANE 1535 pSmi->FBReserved = pSmi->FBCursorOffset = pSmi->videoRAMBytes - 1536 (pSmi->Dualhead ? SMI501_CURSOR_SIZE << 1 : SMI501_ARGB_CURSOR_SIZE); 1537#else 1538 pSmi->FBReserved = pSmi->FBCursorOffset = pSmi->videoRAMBytes - 1539 (pSmi->Dualhead ? SMI501_CURSOR_SIZE << 1 : SMI501_CURSOR_SIZE); 1540 1541# if SMI501_CLI_DEBUG 1542 if (pSmi->useEXA) { 1543 pSmi->batch_active = FALSE; 1544 pSmi->batch_length = 4096; 1545 pSmi->FBReserved -= pSmi->batch_length << 3; 1546 pSmi->batch_offset = pSmi->FBReserved; 1547 pSmi->batch_handle = (int64_t *)(pSmi->FBBase + pSmi->batch_offset); 1548 pSmi->batch_finish = -1; 1549 pSmi->batch_index = 0; 1550 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1551 "Using command list interpreter debug code\n"); 1552 } 1553# endif 1554 1555#endif 1556 } 1557 else { 1558 /* Set up offset to hwcursor memory area, at the end of 1559 * the frame buffer. 1560 */ 1561 pSmi->FBCursorOffset = pSmi->videoRAMBytes - SMILYNX_CURSOR_SIZE; 1562 /* set up the fifo reserved space */ 1563 if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x30) & 0x01)/* #1074 */ { 1564 CARD32 fifoOffset = 0; 1565 fifoOffset |= VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 1566 0x46) << 3; 1567 fifoOffset |= VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 1568 0x47) << 11; 1569 fifoOffset |= (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 1570 0x49) & 0x1C) << 17; 1571 pSmi->FBReserved = fifoOffset; /* PDR#1074 */ 1572 } 1573 else 1574 pSmi->FBReserved = pSmi->videoRAMBytes - 2048; 1575 1576 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Cursor Offset: %08lX\n", 1577 (unsigned long)pSmi->FBCursorOffset); 1578 1579 /* Assign hwp->MemBase & IOBase here */ 1580 hwp = VGAHWPTR(pScrn); 1581 if (pSmi->IOBase != NULL) 1582 vgaHWSetMmioFuncs(hwp, pSmi->MapBase, pSmi->IOBase - pSmi->MapBase); 1583 vgaHWGetIOBase(hwp); 1584 1585 /* Map the VGA memory when the primary video */ 1586 if (xf86IsPrimaryPci(pSmi->PciInfo)) { 1587 hwp->MapSize = 0x10000; 1588 if (!vgaHWMapMem(pScrn)) 1589 LEAVE(FALSE); 1590 pSmi->PrimaryVidMapped = TRUE; 1591 } 1592 } 1593 1594 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reserved: %08lX\n", 1595 (unsigned long)pSmi->FBReserved); 1596 1597 LEAVE(TRUE); 1598} 1599 1600/* UnMapMem - contains half of pre-4.0 EnterLeave function. The EnterLeave 1601 * function which en/disable access to IO ports and ext. regs 1602 */ 1603 1604void 1605SMI_UnmapMem(ScrnInfoPtr pScrn) 1606{ 1607 SMIPtr pSmi = SMIPTR(pScrn); 1608 1609 ENTER(); 1610 1611 /* Unmap VGA mem if mapped. */ 1612 if (pSmi->PrimaryVidMapped) { 1613 vgaHWUnmapMem(pScrn); 1614 pSmi->PrimaryVidMapped = FALSE; 1615 } 1616 1617 SMI_DisableMmio(pScrn); 1618 1619 if (pSmi->MapBase) { 1620#ifndef XSERVER_LIBPCIACCESS 1621 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSmi->MapBase, 1622 pSmi->MapSize); 1623#else 1624 pci_device_unmap_range(pSmi->PciInfo, (pointer)pSmi->MapBase, 1625 pSmi->MapSize); 1626#endif 1627 pSmi->MapBase = NULL; 1628 } 1629 1630 if (pSmi->FBBase) { 1631#ifndef XSERVER_LIBPCIACCESS 1632 xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pSmi->FBBase, 1633 pSmi->videoRAMBytes); 1634#else 1635 pci_device_unmap_range(pSmi->PciInfo, (pointer)pSmi->FBBase, 1636 pSmi->videoRAMBytes); 1637#endif 1638 pSmi->FBBase = NULL; 1639 } 1640 1641 LEAVE(); 1642} 1643 1644/* This gets called at the start of each server generation. */ 1645 1646static Bool 1647SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) 1648{ 1649 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1650 SMIPtr pSmi = SMIPTR(pScrn); 1651 EntityInfoPtr pEnt; 1652 1653 ENTER(); 1654 1655 /* Map MMIO regs and framebuffer */ 1656 if (!SMI_MapMem(pScrn)) 1657 LEAVE(FALSE); 1658 1659 pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 1660 1661 if (!pSmi->pInt10 && pSmi->useBIOS) { 1662 pSmi->pInt10 = xf86InitInt10(pEnt->index); 1663 } 1664 if (!pSmi->pVbe && pSmi->pInt10 && xf86LoaderCheckSymbol("VBEInit")) { 1665 pSmi->pVbe = VBEInit(pSmi->pInt10, pEnt->index); 1666 } 1667 1668 /* Save the chip/graphics state */ 1669 pSmi->Save(pScrn); 1670 1671 /* Fill in some needed pScrn fields */ 1672 pScrn->vtSema = TRUE; 1673 pScrn->pScreen = pScreen; 1674 1675 pSmi->Bpp = pScrn->bitsPerPixel >> 3; 1676 pScrn->displayWidth = ((pScrn->virtualX * pSmi->Bpp + 15) & ~15) / pSmi->Bpp; 1677 1678 pSmi->fbArea = NULL; 1679 pSmi->FBOffset = 0; 1680 pScrn->fbOffset = pSmi->FBOffset + pSmi->fbMapOffset; 1681 1682 /* Clear frame buffer */ 1683 memset(pSmi->FBBase, 0, pSmi->videoRAMBytes); 1684 1685 /* 1686 * The next step is to setup the screen's visuals, and initialise the 1687 * framebuffer code. In cases where the framebuffer's default choises for 1688 * things like visual layouts and bits per RGB are OK, this may be as simple 1689 * as calling the framebuffer's ScreenInit() function. If not, the visuals 1690 * will need to be setup before calling a fb ScreenInit() function and fixed 1691 * up after. 1692 */ 1693 1694 /* 1695 * Reset the visual list. 1696 */ 1697 miClearVisualTypes(); 1698 1699 /* Setup the visuals we support. */ 1700 1701 if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth), 1702 pScrn->rgbBits, pScrn->defaultVisual)) 1703 LEAVE(FALSE); 1704 1705 if (!miSetPixmapDepths ()) 1706 LEAVE(FALSE); 1707 1708 /* 1709 * Call the framebuffer layer's ScreenInit function 1710 */ 1711 1712 DEBUG("\tInitializing FB @ 0x%08X for %dx%d (%d)\n", 1713 pSmi->FBBase, pScrn->virtualX, pScrn->virtualY, pScrn->displayWidth); 1714 if(!fbScreenInit(pScreen, pSmi->FBBase, pScrn->virtualX, pScrn->virtualY, pScrn->xDpi, 1715 pScrn->yDpi, pScrn->displayWidth, pScrn->bitsPerPixel)) 1716 LEAVE(FALSE); 1717 1718 xf86SetBlackWhitePixels(pScreen); 1719 1720 if (pScrn->bitsPerPixel > 8) { 1721 VisualPtr visual; 1722 /* Fixup RGB ordering */ 1723 visual = pScreen->visuals + pScreen->numVisuals; 1724 while (--visual >= pScreen->visuals) { 1725 if ((visual->class | DynamicClass) == DirectColor) { 1726 visual->offsetRed = pScrn->offset.red; 1727 visual->offsetGreen = pScrn->offset.green; 1728 visual->offsetBlue = pScrn->offset.blue; 1729 visual->redMask = pScrn->mask.red; 1730 visual->greenMask = pScrn->mask.green; 1731 visual->blueMask = pScrn->mask.blue; 1732 } 1733 } 1734 } 1735 1736 /* must be after RGB ordering fixed */ 1737 fbPictureInit(pScreen, 0, 0); 1738 1739 /* Do the CRTC independent initialization */ 1740 if(!SMI_HWInit(pScrn)) 1741 LEAVE(FALSE); 1742 1743 /* Unless using EXA, regardless or using XAA or not, needs offscreen 1744 * management at least for video. */ 1745 if (pSmi->NoAccel || !pSmi->useEXA) { 1746 int numLines; 1747 BoxRec AvailFBArea; 1748 1749 numLines = pSmi->FBReserved / (pScrn->displayWidth * pSmi->Bpp); 1750 AvailFBArea.x1 = 0; 1751 AvailFBArea.y1 = 0; 1752 AvailFBArea.x2 = pScrn->virtualX; 1753 AvailFBArea.y2 = numLines; 1754 1755 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1756 "FrameBuffer Box: %d,%d - %d,%d\n", 1757 AvailFBArea.x1, AvailFBArea.y1, AvailFBArea.x2, 1758 AvailFBArea.y2); 1759 1760 xf86InitFBManager(pScreen, &AvailFBArea); 1761 } 1762 1763 /* Initialize acceleration layer */ 1764 if (!pSmi->NoAccel) { 1765 if (pSmi->useEXA && !SMI_EXAInit(pScreen)) 1766 LEAVE(FALSE); 1767 else if (!pSmi->useEXA && !SMI_XAAInit(pScreen)) 1768 LEAVE(FALSE); 1769 } 1770 1771 /* Initialize the chosen modes */ 1772 if (!xf86SetDesiredModes(pScrn)) 1773 LEAVE(FALSE); 1774 1775 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1776 "Done writing mode. Register dump:\n"); 1777 SMI_PrintRegs(pScrn); 1778 1779 miInitializeBackingStore(pScreen); 1780 1781#ifdef HAVE_XMODES 1782 xf86DiDGAInit(pScreen, (unsigned long)(pSmi->FBBase + pScrn->fbOffset)); 1783#endif 1784 1785 /* Initialise cursor functions */ 1786 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1787 1788 /* Initialize HW cursor layer. Must follow software cursor 1789 * initialization. 1790 */ 1791 if (pSmi->HwCursor) { 1792 int size, flags; 1793 1794 if (IS_MSOC(pSmi)) { 1795 size = SMI501_MAX_CURSOR; 1796 flags = (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 | 1797 HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK); 1798#if SMI_CURSOR_ALPHA_PLANE 1799 if (!pSmi->Dualhead) 1800 flags |= HARDWARE_CURSOR_ARGB; 1801#endif 1802 } 1803 else { 1804 size = SMILYNX_MAX_CURSOR; 1805 flags = (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 | 1806 HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | 1807 HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | 1808 HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | 1809 HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 1810 HARDWARE_CURSOR_INVERT_MASK); 1811 } 1812 1813 if (!xf86_cursors_init(pScreen, size, size, flags)) 1814 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1815 "Hardware cursor initialization failed\n"); 1816 } 1817 1818 /* Initialise default colormap */ 1819 if (!miCreateDefColormap(pScreen)) 1820 LEAVE(FALSE); 1821 1822 /* Initialize colormap layer. Must follow initialization of the default 1823 * colormap. And SetGamma call, else it will load palette with solid white. 1824 */ 1825 if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits,SMI_LoadPalette, NULL, 1826 CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR)) 1827 LEAVE(FALSE); 1828 1829 pScreen->SaveScreen = SMI_SaveScreen; 1830 pSmi->CloseScreen = pScreen->CloseScreen; 1831 pScreen->CloseScreen = SMI_CloseScreen; 1832 1833 if ((IS_MSOC(pSmi) && 1834 !xf86DPMSInit(pScreen, SMI501_DisplayPowerManagementSet, 0)) || 1835 (!IS_MSOC(pSmi) && 1836 !xf86DPMSInit(pScreen, SMILynx_DisplayPowerManagementSet, 0))) 1837 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DPMS initialization failed!\n"); 1838 1839 SMI_InitVideo(pScreen); 1840 1841 if(!xf86CrtcScreenInit(pScreen)) 1842 LEAVE(FALSE); 1843 1844 /* Report any unused options (only for the first generation) */ 1845 if (serverGeneration == 1) { 1846 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1847 } 1848 1849 LEAVE(TRUE); 1850} 1851 1852/* 1853 * This is called at the end of each server generation. It restores the 1854 * original (text) mode. It should also unmap the video memory, and free any 1855 * per-generation data allocated by the driver. It should finish by unwrapping 1856 * and calling the saved CloseScreen function. 1857 */ 1858 1859static Bool 1860SMI_CloseScreen(int scrnIndex, ScreenPtr pScreen) 1861{ 1862 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1863 SMIPtr pSmi = SMIPTR(pScrn); 1864 Bool ret; 1865 1866 ENTER(); 1867 1868 if (pSmi->HwCursor) 1869 xf86_cursors_fini(pScreen); 1870 1871 if (pScrn->vtSema) 1872 /* Restore console mode and unmap framebuffer */ 1873 SMI_LeaveVT(scrnIndex, 0); 1874 1875 if (pSmi->XAAInfoRec != NULL) { 1876 XAADestroyInfoRec(pSmi->XAAInfoRec); 1877 } 1878 if (pSmi->EXADriverPtr) { 1879 exaDriverFini(pScreen); 1880 pSmi->EXADriverPtr = NULL; 1881 } 1882 if (pSmi->pVbe != NULL) { 1883 vbeFree(pSmi->pVbe); 1884 pSmi->pVbe = NULL; 1885 } 1886 if (pSmi->pInt10 != NULL) { 1887 xf86FreeInt10(pSmi->pInt10); 1888 pSmi->pInt10 = NULL; 1889 } 1890 if (pSmi->ptrAdaptor != NULL) { 1891 xfree(pSmi->ptrAdaptor); 1892 } 1893 if (pSmi->BlockHandler != NULL) { 1894 pScreen->BlockHandler = pSmi->BlockHandler; 1895 } 1896 1897 pScrn->vtSema = FALSE; 1898 pScreen->CloseScreen = pSmi->CloseScreen; 1899 ret = (*pScreen->CloseScreen)(scrnIndex, pScreen); 1900 1901 LEAVE(ret); 1902} 1903 1904static void 1905SMI_FreeScreen(int scrnIndex, int flags) 1906{ 1907 SMI_FreeRec(xf86Screens[scrnIndex]); 1908} 1909 1910static Bool 1911SMI_SaveScreen(ScreenPtr pScreen, int mode) 1912{ 1913 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1914 1915 ENTER(); 1916 1917 if(xf86IsUnblank(mode)){ 1918 pScrn->DPMSSet(pScrn, DPMSModeOn, 0); 1919 }else{ 1920 pScrn->DPMSSet(pScrn, DPMSModeOff, 0); 1921 } 1922 1923 LEAVE(TRUE); 1924} 1925 1926void 1927SMI_AdjustFrame(int scrnIndex, int x, int y, int flags) 1928{ 1929 xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(xf86Screens[scrnIndex]); 1930 xf86CrtcPtr compat_crtc = crtcConf->output[crtcConf->compat_output]->crtc; 1931 1932 ENTER(); 1933 1934 SMICRTC(compat_crtc)->adjust_frame(compat_crtc,x,y); 1935 1936 LEAVE(); 1937} 1938 1939Bool 1940SMI_SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) 1941{ 1942 Bool ret; 1943 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1944 SMIPtr pSmi = SMIPTR(pScrn); 1945 1946 ENTER(); 1947 1948 ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0); 1949 1950 if (!pSmi->NoAccel) 1951 SMI_EngineReset(pScrn); 1952 1953 LEAVE(ret); 1954} 1955 1956void 1957SMI_LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies, 1958 LOCO *colors, VisualPtr pVisual) 1959{ 1960 xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn); 1961 int crtc_idx,i,j; 1962 1963 ENTER(); 1964 1965 if(pScrn->bitsPerPixel == 16){ 1966 /* Expand the RGB 565 palette into the 256-elements LUT */ 1967 1968 for(crtc_idx=0; crtc_idx<crtcConf->num_crtc; crtc_idx++){ 1969 SMICrtcPrivatePtr crtcPriv = SMICRTC(crtcConf->crtc[crtc_idx]); 1970 1971 for(i=0; i<numColors; i++){ 1972 int idx = indicies[i]; 1973 1974 if(idx<32){ 1975 for(j=0; j<8; j++){ 1976 crtcPriv->lut_r[idx*8 + j] = colors[idx].red << 8; 1977 crtcPriv->lut_b[idx*8 + j] = colors[idx].blue << 8; 1978 } 1979 } 1980 1981 for(j=0; j<4; j++) 1982 crtcPriv->lut_g[idx*4 + j] = colors[idx].green << 8; 1983 } 1984 1985 crtcPriv->load_lut(crtcConf->crtc[crtc_idx]); 1986 } 1987 }else{ 1988 for(crtc_idx=0; crtc_idx<crtcConf->num_crtc; crtc_idx++){ 1989 SMICrtcPrivatePtr crtcPriv = SMICRTC(crtcConf->crtc[crtc_idx]); 1990 1991 for(i = 0; i < numColors; i++) { 1992 int idx = indicies[i]; 1993 1994 crtcPriv->lut_r[idx] = colors[idx].red << 8; 1995 crtcPriv->lut_g[idx] = colors[idx].green << 8; 1996 crtcPriv->lut_b[idx] = colors[idx].blue << 8; 1997 } 1998 1999 crtcPriv->load_lut(crtcConf->crtc[crtc_idx]); 2000 } 2001 } 2002 2003 LEAVE(); 2004} 2005 2006static void 2007SMI_DisableVideo(ScrnInfoPtr pScrn) 2008{ 2009 SMIPtr pSmi = SMIPTR(pScrn); 2010 CARD8 tmp; 2011 2012 if (!IS_MSOC(pSmi)) { 2013 if (!(tmp = VGAIN8(pSmi, VGA_DAC_MASK))) 2014 return; 2015 pSmi->DACmask = tmp; 2016 VGAOUT8(pSmi, VGA_DAC_MASK, 0); 2017 } 2018} 2019 2020static void 2021SMI_EnableVideo(ScrnInfoPtr pScrn) 2022{ 2023 SMIPtr pSmi = SMIPTR(pScrn); 2024 2025 if (!IS_MSOC(pSmi)) { 2026 VGAOUT8(pSmi, VGA_DAC_MASK, pSmi->DACmask); 2027 } 2028} 2029 2030 2031void 2032SMI_EnableMmio(ScrnInfoPtr pScrn) 2033{ 2034 SMIPtr pSmi = SMIPTR(pScrn); 2035 2036 ENTER(); 2037 2038 if (!IS_MSOC(pSmi)) { 2039 vgaHWPtr hwp = VGAHWPTR(pScrn); 2040 CARD8 tmp; 2041 2042 /* 2043 * Enable chipset (seen on uninitialized secondary cards) might not be 2044 * needed once we use the VGA softbooter 2045 */ 2046 vgaHWSetStdFuncs(hwp); 2047 2048 /* Enable linear mode */ 2049 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18); 2050 tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA); 2051 pSmi->SR18Value = tmp; /* PDR#521 */ 2052 outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp | 0x11); 2053 2054 /* Enable 2D/3D Engine and Video Processor */ 2055 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21); 2056 tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA); 2057 pSmi->SR21Value = tmp; /* PDR#521 */ 2058 outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp & ~0x03); 2059 } 2060 2061 LEAVE(); 2062} 2063 2064void 2065SMI_DisableMmio(ScrnInfoPtr pScrn) 2066{ 2067 SMIPtr pSmi = SMIPTR(pScrn); 2068 2069 ENTER(); 2070 2071 if (!IS_MSOC(pSmi)) { 2072 vgaHWPtr hwp = VGAHWPTR(pScrn); 2073 2074 vgaHWSetStdFuncs(hwp); 2075 2076 /* Disable 2D/3D Engine and Video Processor */ 2077 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21); 2078 outb(pSmi->PIOBase + VGA_SEQ_DATA, pSmi->SR21Value); /* PDR#521 */ 2079 2080 /* Disable linear mode */ 2081 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18); 2082 outb(pSmi->PIOBase + VGA_SEQ_DATA, pSmi->SR18Value); /* PDR#521 */ 2083 } 2084 2085 LEAVE(); 2086} 2087 2088static void 2089SMI_ProbeDDC(ScrnInfoPtr pScrn, int index) 2090{ 2091 vbeInfoPtr pVbe; 2092 if (xf86LoadSubModule(pScrn, "vbe")) { 2093 pVbe = VBEInit(NULL, index); 2094 ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 2095 vbeFree(pVbe); 2096 } 2097} 2098 2099static Bool 2100SMI_HWInit(ScrnInfoPtr pScrn) 2101{ 2102 SMIPtr pSmi = SMIPTR(pScrn); 2103 2104 ENTER(); 2105 2106 if(IS_MSOC(pSmi)) 2107 LEAVE(SMI501_HWInit(pScrn)); 2108 else 2109 LEAVE(SMILynx_HWInit(pScrn)); 2110} 2111 2112void 2113SMI_PrintRegs(ScrnInfoPtr pScrn) 2114{ 2115 SMIPtr pSmi = SMIPTR(pScrn); 2116 int i; 2117 2118 ENTER(); 2119 2120 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 2121 "START register dump ------------------\n"); 2122 2123 if(IS_MSOC(pSmi)) 2124 SMI501_PrintRegs(pScrn); 2125 else 2126 SMILynx_PrintRegs(pScrn); 2127 2128 2129 xf86ErrorFVerb(VERBLEV, "\n\nDPR x0 x4 x8 xC"); 2130 for (i = 0x00; i <= 0x44; i += 4) { 2131 if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i); 2132 xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_DPR(pSmi, i)); 2133 } 2134 2135 xf86ErrorFVerb(VERBLEV, "\n\nVPR x0 x4 x8 xC"); 2136 for (i = 0x00; i <= 0x60; i += 4) { 2137 if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i); 2138 xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_VPR(pSmi, i)); 2139 } 2140 2141 xf86ErrorFVerb(VERBLEV, "\n\nCPR x0 x4 x8 xC"); 2142 for (i = 0x00; i <= 0x18; i += 4) { 2143 if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i); 2144 xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_CPR(pSmi, i)); 2145 } 2146 2147 xf86ErrorFVerb(VERBLEV, "\n\n"); 2148 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 2149 "END register dump --------------------\n"); 2150 2151 LEAVE(); 2152} 2153