smi_driver.c revision 621ff18c
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 const 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#ifdef HAVE_XMODES 1757 xf86DiDGAInit(pScreen, (unsigned long)(pSmi->FBBase + pScrn->fbOffset)); 1758#endif 1759 1760 /* Initialise cursor functions */ 1761 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1762 1763 /* Initialize HW cursor layer. Must follow software cursor 1764 * initialization. 1765 */ 1766 if (pSmi->HwCursor) { 1767 int size, flags; 1768 1769 if (IS_MSOC(pSmi)) { 1770 size = SMI501_MAX_CURSOR; 1771 flags = (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 | 1772 HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK); 1773#if SMI_CURSOR_ALPHA_PLANE 1774 if (!pSmi->Dualhead) 1775 flags |= HARDWARE_CURSOR_ARGB; 1776#endif 1777 } 1778 else { 1779 size = SMILYNX_MAX_CURSOR; 1780 flags = (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 | 1781 HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | 1782 HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | 1783 HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | 1784 HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 1785 HARDWARE_CURSOR_INVERT_MASK); 1786 } 1787 1788 if (!xf86_cursors_init(pScreen, size, size, flags)) 1789 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1790 "Hardware cursor initialization failed\n"); 1791 } 1792 1793 /* Initialise default colormap */ 1794 if (!miCreateDefColormap(pScreen)) 1795 LEAVE(FALSE); 1796 1797 /* Initialize colormap layer. Must follow initialization of the default 1798 * colormap. And SetGamma call, else it will load palette with solid white. 1799 */ 1800 if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits,SMI_LoadPalette, NULL, 1801 CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR)) 1802 LEAVE(FALSE); 1803 1804 pScreen->SaveScreen = SMI_SaveScreen; 1805 pSmi->CloseScreen = pScreen->CloseScreen; 1806 pScreen->CloseScreen = SMI_CloseScreen; 1807 1808 if ((IS_MSOC(pSmi) && 1809 !xf86DPMSInit(pScreen, SMI501_DisplayPowerManagementSet, 0)) || 1810 (!IS_MSOC(pSmi) && 1811 !xf86DPMSInit(pScreen, SMILynx_DisplayPowerManagementSet, 0))) 1812 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DPMS initialization failed!\n"); 1813 1814 SMI_InitVideo(pScreen); 1815 1816 if(!xf86CrtcScreenInit(pScreen)) 1817 LEAVE(FALSE); 1818 1819 /* Report any unused options (only for the first generation) */ 1820 if (serverGeneration == 1) { 1821 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1822 } 1823 1824 LEAVE(TRUE); 1825} 1826 1827/* 1828 * This is called at the end of each server generation. It restores the 1829 * original (text) mode. It should also unmap the video memory, and free any 1830 * per-generation data allocated by the driver. It should finish by unwrapping 1831 * and calling the saved CloseScreen function. 1832 */ 1833 1834static Bool 1835SMI_CloseScreen(CLOSE_SCREEN_ARGS_DECL) 1836{ 1837 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1838 SMIPtr pSmi = SMIPTR(pScrn); 1839 Bool ret; 1840 1841 ENTER(); 1842 1843 if (pSmi->HwCursor) 1844 xf86_cursors_fini(pScreen); 1845 1846 if (pScrn->vtSema) 1847 /* Restore console mode and unmap framebuffer */ 1848 SMI_LeaveVT(VT_FUNC_ARGS); 1849 1850#ifdef HAVE_XAA_H 1851 if (pSmi->XAAInfoRec != NULL) { 1852 XAADestroyInfoRec(pSmi->XAAInfoRec); 1853 } 1854#endif 1855 if (pSmi->EXADriverPtr) { 1856 exaDriverFini(pScreen); 1857 pSmi->EXADriverPtr = NULL; 1858 } 1859 if (pSmi->pVbe != NULL) { 1860 vbeFree(pSmi->pVbe); 1861 pSmi->pVbe = NULL; 1862 } 1863 if (pSmi->pInt10 != NULL) { 1864 xf86FreeInt10(pSmi->pInt10); 1865 pSmi->pInt10 = NULL; 1866 } 1867 if (pSmi->ptrAdaptor != NULL) { 1868 free(pSmi->ptrAdaptor); 1869 } 1870 if (pSmi->BlockHandler != NULL) { 1871 pScreen->BlockHandler = pSmi->BlockHandler; 1872 } 1873 1874 pScrn->vtSema = FALSE; 1875 pScreen->CloseScreen = pSmi->CloseScreen; 1876 ret = (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); 1877 1878 LEAVE(ret); 1879} 1880 1881static void 1882SMI_FreeScreen(FREE_SCREEN_ARGS_DECL) 1883{ 1884 SCRN_INFO_PTR(arg); 1885 SMI_FreeRec(pScrn); 1886} 1887 1888static Bool 1889SMI_SaveScreen(ScreenPtr pScreen, int mode) 1890{ 1891 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1892 1893 ENTER(); 1894 1895 if(xf86IsUnblank(mode)){ 1896 pScrn->DPMSSet(pScrn, DPMSModeOn, 0); 1897 }else{ 1898 pScrn->DPMSSet(pScrn, DPMSModeOff, 0); 1899 } 1900 1901 LEAVE(TRUE); 1902} 1903 1904void 1905SMI_AdjustFrame(ADJUST_FRAME_ARGS_DECL) 1906{ 1907 SCRN_INFO_PTR(arg); 1908 xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn); 1909 xf86CrtcPtr compat_crtc = crtcConf->output[crtcConf->compat_output]->crtc; 1910 1911 ENTER(); 1912 1913 SMICRTC(compat_crtc)->adjust_frame(compat_crtc,x,y); 1914 1915 LEAVE(); 1916} 1917 1918Bool 1919SMI_SwitchMode(SWITCH_MODE_ARGS_DECL) 1920{ 1921 Bool ret; 1922 SCRN_INFO_PTR(arg); 1923 SMIPtr pSmi = SMIPTR(pScrn); 1924 1925 ENTER(); 1926 1927 ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0); 1928 1929 if (!pSmi->NoAccel) 1930 SMI_EngineReset(pScrn); 1931 1932 LEAVE(ret); 1933} 1934 1935void 1936SMI_LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies, 1937 LOCO *colors, VisualPtr pVisual) 1938{ 1939 xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn); 1940 int crtc_idx,i,j; 1941 1942 ENTER(); 1943 1944 if(pScrn->bitsPerPixel == 16){ 1945 /* Expand the RGB 565 palette into the 256-elements LUT */ 1946 1947 for(crtc_idx=0; crtc_idx<crtcConf->num_crtc; crtc_idx++){ 1948 SMICrtcPrivatePtr crtcPriv = SMICRTC(crtcConf->crtc[crtc_idx]); 1949 1950 for(i=0; i<numColors; i++){ 1951 int idx = indicies[i]; 1952 1953 if(idx<32){ 1954 for(j=0; j<8; j++){ 1955 crtcPriv->lut_r[idx*8 + j] = colors[idx].red << 8; 1956 crtcPriv->lut_b[idx*8 + j] = colors[idx].blue << 8; 1957 } 1958 } 1959 1960 for(j=0; j<4; j++) 1961 crtcPriv->lut_g[idx*4 + j] = colors[idx].green << 8; 1962 } 1963 1964 crtcPriv->load_lut(crtcConf->crtc[crtc_idx]); 1965 } 1966 }else{ 1967 for(crtc_idx=0; crtc_idx<crtcConf->num_crtc; crtc_idx++){ 1968 SMICrtcPrivatePtr crtcPriv = SMICRTC(crtcConf->crtc[crtc_idx]); 1969 1970 for(i = 0; i < numColors; i++) { 1971 int idx = indicies[i]; 1972 1973 crtcPriv->lut_r[idx] = colors[idx].red << 8; 1974 crtcPriv->lut_g[idx] = colors[idx].green << 8; 1975 crtcPriv->lut_b[idx] = colors[idx].blue << 8; 1976 } 1977 1978 crtcPriv->load_lut(crtcConf->crtc[crtc_idx]); 1979 } 1980 } 1981 1982 LEAVE(); 1983} 1984 1985static void 1986SMI_DisableVideo(ScrnInfoPtr pScrn) 1987{ 1988 SMIPtr pSmi = SMIPTR(pScrn); 1989 CARD8 tmp; 1990 1991 if (!IS_MSOC(pSmi)) { 1992 if (!(tmp = VGAIN8(pSmi, VGA_DAC_MASK))) 1993 return; 1994 pSmi->DACmask = tmp; 1995 VGAOUT8(pSmi, VGA_DAC_MASK, 0); 1996 } 1997} 1998 1999static void 2000SMI_EnableVideo(ScrnInfoPtr pScrn) 2001{ 2002 SMIPtr pSmi = SMIPTR(pScrn); 2003 2004 if (!IS_MSOC(pSmi)) { 2005 VGAOUT8(pSmi, VGA_DAC_MASK, pSmi->DACmask); 2006 } 2007} 2008 2009 2010void 2011SMI_EnableMmio(ScrnInfoPtr pScrn) 2012{ 2013 SMIPtr pSmi = SMIPTR(pScrn); 2014 2015 ENTER(); 2016 2017 if (!IS_MSOC(pSmi)) { 2018 vgaHWPtr hwp = VGAHWPTR(pScrn); 2019 CARD8 tmp; 2020 2021 /* 2022 * Enable chipset (seen on uninitialized secondary cards) might not be 2023 * needed once we use the VGA softbooter 2024 */ 2025 vgaHWSetStdFuncs(hwp); 2026 2027 /* Enable linear mode */ 2028 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18); 2029 tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA); 2030 pSmi->SR18Value = tmp; /* PDR#521 */ 2031 outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp | 0x11); 2032 2033 /* Enable 2D/3D Engine and Video Processor */ 2034 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21); 2035 tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA); 2036 pSmi->SR21Value = tmp; /* PDR#521 */ 2037 outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp & ~0x03); 2038 } 2039 2040 LEAVE(); 2041} 2042 2043void 2044SMI_DisableMmio(ScrnInfoPtr pScrn) 2045{ 2046 SMIPtr pSmi = SMIPTR(pScrn); 2047 2048 ENTER(); 2049 2050 if (!IS_MSOC(pSmi)) { 2051 vgaHWPtr hwp = VGAHWPTR(pScrn); 2052 2053 vgaHWSetStdFuncs(hwp); 2054 2055 /* Disable 2D/3D Engine and Video Processor */ 2056 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21); 2057 outb(pSmi->PIOBase + VGA_SEQ_DATA, pSmi->SR21Value); /* PDR#521 */ 2058 2059 /* Disable linear mode */ 2060 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18); 2061 outb(pSmi->PIOBase + VGA_SEQ_DATA, pSmi->SR18Value); /* PDR#521 */ 2062 } 2063 2064 LEAVE(); 2065} 2066 2067static void 2068SMI_ProbeDDC(ScrnInfoPtr pScrn, int index) 2069{ 2070 vbeInfoPtr pVbe; 2071 if (xf86LoadSubModule(pScrn, "vbe")) { 2072 pVbe = VBEInit(NULL, index); 2073 ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 2074 vbeFree(pVbe); 2075 } 2076} 2077 2078static Bool 2079SMI_HWInit(ScrnInfoPtr pScrn) 2080{ 2081 SMIPtr pSmi = SMIPTR(pScrn); 2082 2083 ENTER(); 2084 2085 if(IS_MSOC(pSmi)) 2086 LEAVE(SMI501_HWInit(pScrn)); 2087 else 2088 LEAVE(SMILynx_HWInit(pScrn)); 2089} 2090 2091void 2092SMI_PrintRegs(ScrnInfoPtr pScrn) 2093{ 2094 SMIPtr pSmi = SMIPTR(pScrn); 2095 int i; 2096 2097 ENTER(); 2098 2099 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 2100 "START register dump ------------------\n"); 2101 2102 if(IS_MSOC(pSmi)) 2103 SMI501_PrintRegs(pScrn); 2104 else 2105 SMILynx_PrintRegs(pScrn); 2106 2107 2108 xf86ErrorFVerb(VERBLEV, "\n\nDPR x0 x4 x8 xC"); 2109 for (i = 0x00; i <= 0x44; i += 4) { 2110 if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i); 2111 xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_DPR(pSmi, i)); 2112 } 2113 2114 xf86ErrorFVerb(VERBLEV, "\n\nVPR x0 x4 x8 xC"); 2115 for (i = 0x00; i <= 0x60; i += 4) { 2116 if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i); 2117 xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_VPR(pSmi, i)); 2118 } 2119 2120 xf86ErrorFVerb(VERBLEV, "\n\nCPR x0 x4 x8 xC"); 2121 for (i = 0x00; i <= 0x18; i += 4) { 2122 if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i); 2123 xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_CPR(pSmi, i)); 2124 } 2125 2126 xf86ErrorFVerb(VERBLEV, "\n\n"); 2127 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 2128 "END register dump --------------------\n"); 2129 2130 LEAVE(); 2131} 2132