smi_driver.c revision eee1ded1
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 87static Bool SMI_driverFunc(ScrnInfoPtr, xorgDriverFuncOp, pointer); 88 89/* 90 * xf86VDrvMsgVerb prints up to 14 characters prefix, where prefix has the 91 * format "%s(%d): " so, use name "SMI" instead of "Silicon Motion" 92 */ 93#define SILICONMOTION_NAME "SMI" 94#define SILICONMOTION_DRIVER_NAME "siliconmotion" 95#define SILICONMOTION_VERSION_NAME PACKAGE_VERSION 96#define SILICONMOTION_VERSION_MAJOR PACKAGE_VERSION_MAJOR 97#define SILICONMOTION_VERSION_MINOR PACKAGE_VERSION_MINOR 98#define SILICONMOTION_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL 99#define SILICONMOTION_DRIVER_VERSION ((SILICONMOTION_VERSION_MAJOR << 24) | \ 100 (SILICONMOTION_VERSION_MINOR << 16) | \ 101 (SILICONMOTION_PATCHLEVEL)) 102 103#if SMI_DEBUG 104int smi_indent = 1; 105#endif 106 107/* for dualhead */ 108int gSMIEntityIndex = -1; 109 110/* 111 * This contains the functions needed by the server after loading the 112 * driver module. It must be supplied, and gets added the driver list by 113 * the Module Setup funtion in the dynamic case. In the static case a 114 * reference to this is compiled in, and this requires that the name of 115 * this DriverRec be an upper-case version of the driver name. 116 */ 117 118_X_EXPORT DriverRec SILICONMOTION = 119{ 120 SILICONMOTION_DRIVER_VERSION, 121 SILICONMOTION_DRIVER_NAME, 122 SMI_Identify, 123 SMI_Probe, 124 SMI_AvailableOptions, 125 NULL, 126 0, 127 SMI_driverFunc 128}; 129 130/* Supported chipsets */ 131static SymTabRec SMIChipsets[] = 132{ 133 { PCI_CHIP_SMI910, "Lynx" }, 134 { PCI_CHIP_SMI810, "LynxE" }, 135 { PCI_CHIP_SMI820, "Lynx3D" }, 136 { PCI_CHIP_SMI710, "LynxEM" }, 137 { PCI_CHIP_SMI712, "LynxEM+" }, 138 { PCI_CHIP_SMI720, "Lynx3DM" }, 139 { PCI_CHIP_SMI731, "Cougar3DR" }, 140 { PCI_CHIP_SMI501, "MSOC" }, 141 { -1, NULL } 142}; 143 144static PciChipsets SMIPciChipsets[] = 145{ 146 /* numChipset, PciID, Resource */ 147 { PCI_CHIP_SMI910, PCI_CHIP_SMI910, RES_SHARED_VGA }, 148 { PCI_CHIP_SMI810, PCI_CHIP_SMI810, RES_SHARED_VGA }, 149 { PCI_CHIP_SMI820, PCI_CHIP_SMI820, RES_SHARED_VGA }, 150 { PCI_CHIP_SMI710, PCI_CHIP_SMI710, RES_SHARED_VGA }, 151 { PCI_CHIP_SMI712, PCI_CHIP_SMI712, RES_SHARED_VGA }, 152 { PCI_CHIP_SMI720, PCI_CHIP_SMI720, RES_SHARED_VGA }, 153 { PCI_CHIP_SMI731, PCI_CHIP_SMI731, RES_SHARED_VGA }, 154 { PCI_CHIP_SMI501, PCI_CHIP_SMI501, RES_UNDEFINED }, 155 { -1, -1, RES_UNDEFINED } 156}; 157 158typedef enum 159{ 160 OPTION_PCI_BURST, 161 OPTION_PCI_RETRY, 162 OPTION_NOACCEL, 163 OPTION_MCLK, 164 OPTION_MXCLK, 165 OPTION_SWCURSOR, 166 OPTION_HWCURSOR, 167 OPTION_VIDEOKEY, 168 OPTION_BYTESWAP, 169 /* CZ 26.10.2001: interlaced video */ 170 OPTION_INTERLACED, 171 /* end CZ */ 172 OPTION_USEBIOS, 173 OPTION_DUALHEAD, 174 OPTION_ACCELMETHOD, 175 OPTION_PANEL_SIZE, 176 OPTION_USE_FBDEV, 177 OPTION_CSCVIDEO, 178 NUMBER_OF_OPTIONS 179} SMIOpts; 180 181static const OptionInfoRec SMIOptions[] = 182{ 183 { OPTION_PCI_BURST, "pci_burst", OPTV_BOOLEAN, {0}, TRUE }, 184 { OPTION_PCI_RETRY, "pci_retry", OPTV_BOOLEAN, {0}, TRUE }, 185 { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 186 { OPTION_MCLK, "MCLK", OPTV_FREQ, {0}, FALSE }, 187 { OPTION_MXCLK, "MXCLK", OPTV_FREQ, {0}, FALSE }, 188 { OPTION_HWCURSOR, "HWCursor", OPTV_BOOLEAN, {0}, TRUE }, 189 { OPTION_SWCURSOR, "SWCursor", OPTV_BOOLEAN, {0}, FALSE }, 190 { OPTION_VIDEOKEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, 191 { OPTION_BYTESWAP, "ByteSwap", OPTV_BOOLEAN, {0}, FALSE }, 192 /* CZ 26.10.2001: interlaced video */ 193 { OPTION_INTERLACED, "Interlaced", OPTV_BOOLEAN, {0}, FALSE }, 194 /* end CZ */ 195 { OPTION_USEBIOS, "UseBIOS", OPTV_BOOLEAN, {0}, FALSE }, 196 { OPTION_DUALHEAD, "Dualhead", OPTV_BOOLEAN, {0}, TRUE }, 197 { OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING, {0}, FALSE }, 198 { OPTION_PANEL_SIZE, "PanelSize", OPTV_ANYSTR, {0}, FALSE }, 199 { OPTION_USE_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE }, 200 { OPTION_CSCVIDEO, "CSCVideo", OPTV_BOOLEAN, {0}, TRUE }, 201 { -1, NULL, OPTV_NONE, {0}, FALSE } 202}; 203 204static MODULESETUPPROTO(siliconmotionSetup); 205 206static XF86ModuleVersionInfo SMIVersRec = 207{ 208 "siliconmotion", 209 MODULEVENDORSTRING, 210 MODINFOSTRING1, 211 MODINFOSTRING2, 212 XORG_VERSION_CURRENT, 213 SILICONMOTION_VERSION_MAJOR, 214 SILICONMOTION_VERSION_MINOR, 215 SILICONMOTION_PATCHLEVEL, 216 ABI_CLASS_VIDEODRV, 217 ABI_VIDEODRV_VERSION, 218 MOD_CLASS_VIDEODRV, 219 {0, 0, 0, 0} 220}; 221 222/* 223 * This is the module init data for XFree86 modules. 224 * 225 * Its name has to be the driver name followed by ModuleData. 226 */ 227_X_EXPORT XF86ModuleData siliconmotionModuleData = 228{ 229 &SMIVersRec, 230 siliconmotionSetup, 231 NULL 232}; 233 234static pointer 235siliconmotionSetup(pointer module, pointer opts, int *errmaj, int *errmin) 236{ 237 static Bool setupDone = FALSE; 238 239 if (!setupDone) { 240 setupDone = TRUE; 241 xf86AddDriver(&SILICONMOTION, module, HaveDriverFuncs); 242 243 /* 244 * The return value must be non-NULL on success even though there 245 * is no TearDownProc. 246 */ 247 return (pointer) 1; 248 249 } else { 250 if (errmaj) { 251 *errmaj = LDR_ONCEONLY; 252 } 253 return NULL; 254 } 255} 256 257static Bool 258SMI_GetRec(ScrnInfoPtr pScrn) 259{ 260 ENTER(); 261 262 /* 263 * Allocate an 'Chip'Rec, and hook it into pScrn->driverPrivate. 264 * pScrn->driverPrivate is initialised to NULL, so we can check if 265 * the allocation has already been done. 266 */ 267 if (pScrn->driverPrivate == NULL) { 268 pScrn->driverPrivate = xnfcalloc(sizeof(SMIRec), 1); 269 } 270 271 LEAVE(TRUE); 272} 273 274static void 275SMI_FreeRec(ScrnInfoPtr pScrn) 276{ 277 SMIPtr pSmi = SMIPTR(pScrn); 278 279 ENTER(); 280 281 if (pSmi) { 282 free(pSmi->save); 283 free(pSmi->mode); 284 free(pScrn->driverPrivate); 285 pScrn->driverPrivate = NULL; 286 } 287 288 LEAVE(); 289} 290 291static const OptionInfoRec * 292SMI_AvailableOptions(int chipid, int busid) 293{ 294 ENTER(); 295 296 LEAVE(SMIOptions); 297} 298 299static void 300SMI_Identify(int flags) 301{ 302 ENTER(); 303 304 xf86PrintChipsets(SILICONMOTION_NAME, "driver (version " 305 SILICONMOTION_VERSION_NAME ") for Silicon Motion Lynx chipsets", 306 SMIChipsets); 307 308 LEAVE(); 309} 310 311static Bool 312SMI_Probe(DriverPtr drv, int flags) 313{ 314 int i; 315 GDevPtr *devSections; 316 int *usedChips; 317 int numDevSections; 318 int numUsed; 319 Bool foundScreen = FALSE; 320 321 ENTER(); 322 323 numDevSections = xf86MatchDevice(SILICONMOTION_DRIVER_NAME, &devSections); 324 325 if (numDevSections <= 0) 326 /* There's no matching device section in the config file, so quit now. */ 327 LEAVE(FALSE); 328 329#ifndef XSERVER_LIBPCIACCESS 330 if (xf86GetPciVideoInfo() == NULL) 331 LEAVE(FALSE); 332#endif 333 334 numUsed = xf86MatchPciInstances(SILICONMOTION_NAME, PCI_SMI_VENDOR_ID, 335 SMIChipsets, SMIPciChipsets, devSections, 336 numDevSections, drv, &usedChips); 337 338 /* Free it since we don't need that list after this */ 339 free(devSections); 340 if (numUsed <= 0) 341 LEAVE(FALSE); 342 343 if (flags & PROBE_DETECT) 344 foundScreen = TRUE; 345 else { 346 ScrnInfoPtr pScrn; 347 EntityInfoPtr pEnt; 348 349 for (i = 0; i < numUsed; i++) { 350 if ((pScrn = xf86ConfigPciEntity(NULL, 0, usedChips[i], 351 SMIPciChipsets, NULL, 352 NULL, NULL, NULL, NULL))) { 353 pScrn->driverVersion = SILICONMOTION_DRIVER_VERSION; 354 pScrn->driverName = SILICONMOTION_DRIVER_NAME; 355 pScrn->name = SILICONMOTION_NAME; 356 pScrn->Probe = SMI_Probe; 357 pScrn->PreInit = SMI_PreInit; 358 pScrn->ScreenInit = SMI_ScreenInit; 359 pScrn->SwitchMode = SMI_SwitchMode; 360 pScrn->AdjustFrame = SMI_AdjustFrame; 361 362 if ((pEnt = xf86GetEntityInfo(usedChips[i]))) { 363 pScrn->EnterVT = SMI_EnterVT; 364 pScrn->LeaveVT = SMI_LeaveVT; 365 free(pEnt); 366 } 367 pScrn->FreeScreen = SMI_FreeScreen; 368 foundScreen = TRUE; 369 } 370 } 371 } 372 free(usedChips); 373 374 LEAVE(foundScreen); 375} 376 377static Bool 378SMI_PreInit(ScrnInfoPtr pScrn, int flags) 379{ 380 EntityInfoPtr pEnt; 381 SMIPtr pSmi; 382 MessageType from; 383 vgaHWPtr hwp; 384 385 ENTER(); 386 387 /* Ignoring the Type list for now. It might be needed when multiple cards 388 * are supported. 389 */ 390 if (pScrn->numEntities > 1) 391 LEAVE(FALSE); 392 393 /* Allocate the SMIRec driverPrivate */ 394 if (!SMI_GetRec(pScrn)) 395 LEAVE(FALSE); 396 pSmi = SMIPTR(pScrn); 397 398 /* Find the PCI slot for this screen */ 399 pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 400 401 pSmi->PciInfo = xf86GetPciInfoForEntity(pEnt->index); 402 pSmi->Chipset = PCI_DEV_DEVICE_ID(pSmi->PciInfo); 403 404 if (IS_MSOC(pSmi)) { 405 pSmi->Save = SMI501_Save; 406 pSmi->save = xnfcalloc(sizeof(MSOCRegRec), 1); 407 pSmi->mode = xnfcalloc(sizeof(MSOCRegRec), 1); 408 } 409 else { 410 pSmi->Save = SMILynx_Save; 411 pSmi->save = xnfcalloc(sizeof(SMIRegRec), 1); 412 pSmi->mode = xnfcalloc(sizeof(SMIRegRec), 1); 413 } 414 415 if (flags & PROBE_DETECT) { 416 if (!IS_MSOC(pSmi)) 417 SMI_ProbeDDC(pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index); 418 LEAVE(TRUE); 419 } 420 421 if (pEnt->location.type != BUS_PCI) { 422 free(pEnt); 423 SMI_FreeRec(pScrn); 424 LEAVE(FALSE); 425 } 426 pSmi->PciInfo = xf86GetPciInfoForEntity(pEnt->index); 427 428 /* Set pScrn->monitor */ 429 pScrn->monitor = pScrn->confScreen->monitor; 430 431 if (!IS_MSOC(pSmi)) { 432 /* The vgahw module should be loaded here when needed */ 433 if (!xf86LoadSubModule(pScrn, "vgahw")) 434 LEAVE(FALSE); 435 436 /* 437 * Allocate a vgaHWRec 438 */ 439 if (!vgaHWGetHWRec(pScrn)) 440 LEAVE(FALSE); 441 442 hwp = VGAHWPTR(pScrn); 443 vgaHWSetStdFuncs(hwp); 444#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 445 pSmi->PIOBase = hwp->PIOOffset; 446#else 447 pSmi->PIOBase = 0; 448#endif 449 450 xf86ErrorFVerb(VERBLEV, "\tSMI_PreInit vgaCRIndex=%x, vgaIOBase=%x, " 451 "MMIOBase=%p\n", hwp->IOBase + VGA_CRTC_INDEX_OFFSET, 452 hwp->IOBase, hwp->MMIOBase); 453 } 454 455 /* 456 * The first thing we should figure out is the depth, bpp, etc. 457 */ 458 if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb)) 459 LEAVE(FALSE); 460 461 /* Check that the returned depth is one we support */ 462 if (pScrn->depth != 8 && pScrn->depth != 16 && pScrn->depth != 24) { 463 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 464 "Given depth (%d) is not supported by this driver\n", 465 pScrn->depth); 466 LEAVE(FALSE); 467 } 468 469 470 if(pScrn->bitsPerPixel != 8 && pScrn->bitsPerPixel != 16 && 471 pScrn->bitsPerPixel != 24 && pScrn->bitsPerPixel != 32){ 472 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 473 "Given bpp (%d) is not supported by this driver\n", 474 pScrn->bitsPerPixel); 475 LEAVE(FALSE); 476 } 477 478 xf86PrintDepthBpp(pScrn); 479 480 pSmi->Bpp = pScrn->bitsPerPixel >> 3; 481 482 /* 483 * This must happen after pScrn->display has been set because 484 * xf86SetWeight references it. 485 */ 486 if (pScrn->depth > 8) { 487 /* The defaults are OK for us */ 488 rgb zeros = {0, 0, 0}; 489#if X_BYTE_ORDER == X_BIG_ENDIAN 490 rgb masks = {0xff00,0xff0000,0xff000000}; 491#else 492 rgb masks = {0, 0, 0}; 493#endif 494 495 if (!xf86SetWeight(pScrn, zeros, masks)) 496 LEAVE(FALSE); 497 } 498 499 if (!xf86SetDefaultVisual(pScrn, -1)) 500 LEAVE(FALSE); 501 502 /* We don't currently support DirectColor at > 8bpp */ 503 if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { 504 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual (%s) " 505 "is not supported at depth %d\n", 506 xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); 507 LEAVE(FALSE); 508 } 509 510 /* We use a programmable clock */ 511 pScrn->progClock = TRUE; 512 513 /* Collect all of the relevant option flags (fill in pScrn->options) */ 514 xf86CollectOptions(pScrn, NULL); 515 516 /* Set the bits per RGB for 8bpp mode */ 517 if (pScrn->depth == 8){ 518 pScrn->rgbBits = IS_MSOC(pSmi) ? 8 : 6; 519 }else if(pScrn->depth == 16){ 520 /* Use 8 bit LUT for gamma correction*/ 521 pScrn->rgbBits = 8; 522 } 523 524 /* Process the options */ 525 if (!(pSmi->Options = malloc(sizeof(SMIOptions)))) 526 LEAVE(FALSE); 527 528 memcpy(pSmi->Options, SMIOptions, sizeof(SMIOptions)); 529 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pSmi->Options); 530 531 /* Enable pci burst by default */ 532 from = X_DEFAULT; 533 pSmi->PCIBurst = TRUE; 534 if (xf86GetOptValBool(pSmi->Options, OPTION_PCI_BURST, &pSmi->PCIBurst)) 535 from = X_CONFIG; 536 xf86DrvMsg(pScrn->scrnIndex, from, "PCI Burst %sabled\n", 537 pSmi->PCIBurst ? "en" : "dis"); 538 539 /* Pci retry enabled by default if pci burst also enabled */ 540 from = X_DEFAULT; 541 pSmi->PCIRetry = pSmi->PCIBurst ? TRUE : FALSE; 542 if (xf86GetOptValBool(pSmi->Options, OPTION_PCI_RETRY, &pSmi->PCIRetry)) { 543 from = X_CONFIG; 544 if (pSmi->PCIRetry && !pSmi->PCIBurst) { 545 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 546 "\"pci_retry\" option requires \"pci_burst\".\n"); 547 pSmi->PCIRetry = FALSE; 548 } 549 } 550 xf86DrvMsg(pScrn->scrnIndex, from, "PCI Retry %sabled\n", 551 pSmi->PCIRetry ? "en" : "dis"); 552 553 if (xf86ReturnOptValBool(pSmi->Options, OPTION_NOACCEL, FALSE)) { 554 pSmi->NoAccel = TRUE; 555 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: NoAccel - Acceleration " 556 "disabled\n"); 557 } else { 558 pSmi->NoAccel = FALSE; 559 } 560 561 if (IS_MSOC(pSmi)) { 562 from = X_DEFAULT; 563 if (xf86GetOptValBool(pSmi->Options, OPTION_USE_FBDEV, &pSmi->UseFBDev)) 564 from = X_CONFIG; 565 xf86DrvMsg(pScrn->scrnIndex, from, "UseFBDev %s.\n", 566 pSmi->UseFBDev ? "enabled" : "disabled"); 567 } 568 569 from = X_CONFIG; 570 pSmi->HwCursor = TRUE; 571 /* SWCursor overrides HWCusor if both specified */ 572 if (xf86ReturnOptValBool(pSmi->Options, OPTION_SWCURSOR, FALSE)) 573 pSmi->HwCursor = FALSE; 574 else if (!xf86GetOptValBool(pSmi->Options, OPTION_HWCURSOR, &pSmi->HwCursor)) 575 from = X_DEFAULT; 576 577 xf86DrvMsg(pScrn->scrnIndex, from, "Using %sware Cursor\n", 578 pSmi->HwCursor ? "Hard" : "Soft"); 579 580 if (xf86GetOptValInteger(pSmi->Options, OPTION_VIDEOKEY, &pSmi->videoKey)) { 581 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: Video key set to " 582 "0x%08X\n", pSmi->videoKey); 583 } else { 584 pSmi->videoKey = (1 << pScrn->offset.red) | 585 (1 << pScrn->offset.green) | 586 (((pScrn->mask.blue >> pScrn->offset.blue) - 1) 587 << pScrn->offset.blue); 588 } 589 590 if (xf86ReturnOptValBool(pSmi->Options, OPTION_BYTESWAP, FALSE)) { 591 pSmi->ByteSwap = TRUE; 592 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: ByteSwap enabled.\n"); 593 } else { 594 pSmi->ByteSwap = FALSE; 595 } 596 597 /* CZ 26.10.2001: interlaced video */ 598 if (xf86ReturnOptValBool(pSmi->Options, OPTION_INTERLACED, FALSE)) { 599 pSmi->interlaced = TRUE; 600 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: Interlaced enabled.\n"); 601 } else { 602 pSmi->interlaced = FALSE; 603 } 604 /* end CZ */ 605 606 if (IS_MSOC(pSmi)) 607 pSmi->useBIOS = FALSE; 608 else if (xf86GetOptValBool(pSmi->Options, OPTION_USEBIOS, &pSmi->useBIOS)) { 609 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: UseBIOS %s.\n", 610 pSmi->useBIOS ? "enabled" : "disabled"); 611 } 612 else if(pSmi->Chipset == SMI_LYNX3DM){ 613 /* Default to UseBIOS disabled. */ 614 pSmi->useBIOS = FALSE; 615 } 616 else { 617 /* Default to UseBIOS enabled. */ 618 pSmi->useBIOS = TRUE; 619 } 620 621 if (pSmi->useBIOS) { 622 if (xf86LoadSubModule(pScrn,"int10")) { 623 pSmi->pInt10 = xf86InitInt10(pEnt->index); 624 } 625 626 if (pSmi->pInt10 && xf86LoadSubModule(pScrn, "vbe")) { 627 pSmi->pVbe = VBEInit(pSmi->pInt10, pEnt->index); 628 } 629 630 if(!pSmi->pVbe){ 631 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VBE initialization failed: falling back to UseBIOS disabled.\n"); 632 pSmi->useBIOS = FALSE; 633 } 634 } 635 636#ifndef XSERVER_LIBPCIACCESS 637 xf86RegisterResources(pEnt->index, NULL, ResExclusive); 638#endif 639 /* 640 * Set the Chipset and ChipRev, allowing config file entries to 641 * override. 642 */ 643 if (pEnt->device->chipset && *pEnt->device->chipset) { 644 pScrn->chipset = pEnt->device->chipset; 645 pSmi->Chipset = xf86StringToToken(SMIChipsets, pScrn->chipset); 646 from = X_CONFIG; 647 } 648 else if (pEnt->device->chipID >= 0) { 649 pSmi->Chipset = pEnt->device->chipID; 650 pScrn->chipset = (char *) xf86TokenToString(SMIChipsets, pSmi->Chipset); 651 from = X_CONFIG; 652 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", 653 pSmi->Chipset); 654 } 655 else { 656 from = X_PROBED; 657 pSmi->Chipset = PCI_DEV_DEVICE_ID(pSmi->PciInfo); 658 pScrn->chipset = (char *) xf86TokenToString(SMIChipsets, pSmi->Chipset); 659 } 660 661 if (pEnt->device->chipRev >= 0) { 662 pSmi->ChipRev = pEnt->device->chipRev; 663 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 664 pSmi->ChipRev); 665 } 666 else 667 pSmi->ChipRev = PCI_DEV_REVISION(pSmi->PciInfo); 668 free(pEnt); 669 670 /* 671 * This shouldn't happen because such problems should be caught in 672 * SMI_Probe(), but check it just in case. 673 */ 674 if (pScrn->chipset == NULL) { 675 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ChipID 0x%04X is not " 676 "recognised\n", pSmi->Chipset); 677 LEAVE(FALSE); 678 } 679 680 if (pSmi->Chipset < 0) { 681 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Chipset \"%s\" is not " 682 "recognised\n", pScrn->chipset); 683 LEAVE(FALSE); 684 } 685 686 xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset); 687 688#ifndef XSERVER_LIBPCIACCESS 689 pSmi->PciTag = pciTag(pSmi->PciInfo->bus, pSmi->PciInfo->device, 690 pSmi->PciInfo->func); 691#endif 692 693 from = X_DEFAULT; 694 if(pSmi->Chipset == SMI_LYNX3DM && 695 pScrn->bitsPerPixel == 16) 696 pSmi->Dualhead = TRUE; 697 else 698 pSmi->Dualhead = FALSE; 699 700 if (xf86GetOptValBool(pSmi->Options, OPTION_DUALHEAD, &pSmi->Dualhead)) 701 from = X_CONFIG; 702 703 if (IS_MSOC(pSmi)) { 704 pSmi->lcd = TRUE; 705 if (pSmi->Dualhead && pSmi->UseFBDev) { 706 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 707 "Dual head disabled in fbdev mode\n"); 708 pSmi->Dualhead = FALSE; 709 } 710 /* FIXME Randr cursor code only works properly when argb cursors 711 * are also supported. 712 * FIXME This probably is a randr cursor bug, and since access to 713 * hw/xfree86/ramdac/xf86CursorPriv.h:xf86CursorScreenRec.SWCursor 714 * field is not available, one cannot easily workaround the problem, 715 * so, just disable it... 716 * TODO Check with a X Server newer then 1.4.0.90 (that is being 717 * used in the 502 OEM image). 718 * */ 719 if (pSmi->Dualhead && pSmi->HwCursor) { 720 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 721 "HW Cursor disabled in dual head mode\n"); 722 pSmi->HwCursor = FALSE; 723 } 724 } 725 else if (SMI_LYNXM_SERIES(pSmi->Chipset)) { 726 /* tweak options for dualhead */ 727 if (pSmi->Dualhead) { 728 pSmi->useBIOS = FALSE; 729 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "UseBIOS disabled in dualhead mode\n"); 730 pSmi->HwCursor = FALSE; 731 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No hardware cursor in dualhead mode\n"); 732 if (pScrn->bitsPerPixel != 16) { 733 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Dualhead only supported at " 734 "depth 16\n"); 735 LEAVE(FALSE); 736 } 737 } 738 } 739 xf86DrvMsg(pScrn->scrnIndex, from, "Dual head %sabled\n", 740 pSmi->Dualhead ? "en" : "dis"); 741 742 if (!pSmi->NoAccel) { 743 char *strptr; 744 745 from = X_DEFAULT; 746 pSmi->useEXA = TRUE; 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#if !defined(__mips__) 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#endif 2043} 2044 2045void 2046SMI_DisableMmio(ScrnInfoPtr pScrn) 2047{ 2048#if !defined(__mips__) 2049 SMIPtr pSmi = SMIPTR(pScrn); 2050 2051 ENTER(); 2052 2053 if (!IS_MSOC(pSmi)) { 2054 vgaHWPtr hwp = VGAHWPTR(pScrn); 2055 2056 vgaHWSetStdFuncs(hwp); 2057 2058 /* Disable 2D/3D Engine and Video Processor */ 2059 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21); 2060 outb(pSmi->PIOBase + VGA_SEQ_DATA, pSmi->SR21Value); /* PDR#521 */ 2061 2062 /* Disable linear mode */ 2063 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18); 2064 outb(pSmi->PIOBase + VGA_SEQ_DATA, pSmi->SR18Value); /* PDR#521 */ 2065 } 2066 2067 LEAVE(); 2068#endif 2069} 2070 2071static void 2072SMI_ProbeDDC(ScrnInfoPtr pScrn, int index) 2073{ 2074 vbeInfoPtr pVbe; 2075 if (xf86LoadSubModule(pScrn, "vbe")) { 2076 pVbe = VBEInit(NULL, index); 2077 ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 2078 vbeFree(pVbe); 2079 } 2080} 2081 2082static Bool 2083SMI_HWInit(ScrnInfoPtr pScrn) 2084{ 2085 SMIPtr pSmi = SMIPTR(pScrn); 2086 2087 ENTER(); 2088 2089 if(IS_MSOC(pSmi)) 2090 LEAVE(SMI501_HWInit(pScrn)); 2091 else 2092 LEAVE(SMILynx_HWInit(pScrn)); 2093} 2094 2095void 2096SMI_PrintRegs(ScrnInfoPtr pScrn) 2097{ 2098 SMIPtr pSmi = SMIPTR(pScrn); 2099 int i; 2100 2101 ENTER(); 2102 2103 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 2104 "START register dump ------------------\n"); 2105 2106 if(IS_MSOC(pSmi)) 2107 SMI501_PrintRegs(pScrn); 2108 else 2109 SMILynx_PrintRegs(pScrn); 2110 2111 2112 xf86ErrorFVerb(VERBLEV, "\n\nDPR x0 x4 x8 xC"); 2113 for (i = 0x00; i <= 0x44; i += 4) { 2114 if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i); 2115 xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_DPR(pSmi, i)); 2116 } 2117 2118 xf86ErrorFVerb(VERBLEV, "\n\nVPR x0 x4 x8 xC"); 2119 for (i = 0x00; i <= 0x60; i += 4) { 2120 if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i); 2121 xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_VPR(pSmi, i)); 2122 } 2123 2124 xf86ErrorFVerb(VERBLEV, "\n\nCPR x0 x4 x8 xC"); 2125 for (i = 0x00; i <= 0x18; i += 4) { 2126 if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i); 2127 xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_CPR(pSmi, i)); 2128 } 2129 2130 xf86ErrorFVerb(VERBLEV, "\n\n"); 2131 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 2132 "END register dump --------------------\n"); 2133 2134 LEAVE(); 2135} 2136 2137static Bool 2138SMI_driverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op, 2139 pointer ptr) 2140{ 2141 xorgHWFlags *flag; 2142 2143 switch (op) { 2144 case GET_REQUIRED_HW_INTERFACES: 2145 flag = (CARD32*)ptr; 2146 (*flag) = HW_MMIO; 2147 return TRUE; 2148 default: 2149 return FALSE; 2150 } 2151} 2152