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