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