smi_driver.c revision 5805b606
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 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 pSmi->useEXA = TRUE; 748 if ((strptr = (char *)xf86GetOptValString(pSmi->Options, 749 OPTION_ACCELMETHOD))) { 750 if (!xf86NameCmp(strptr,"XAA")) { 751 from = X_CONFIG; 752 pSmi->useEXA = FALSE; 753 } else if(!xf86NameCmp(strptr,"EXA")) { 754 from = X_CONFIG; 755 pSmi->useEXA = TRUE; 756 } 757 } 758 759 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration architecture\n", 760 pSmi->useEXA ? "EXA" : "XAA"); 761 } 762 763 if (IS_MSOC(pSmi)) { 764 pSmi->CSCVideo = !pSmi->useEXA || !pSmi->Dualhead; 765 from = X_DEFAULT; 766 if (xf86GetOptValBool(pSmi->Options, OPTION_CSCVIDEO, &pSmi->CSCVideo)) { 767 from = X_CONFIG; 768 769 /* FIXME */ 770 if (pSmi->CSCVideo && pSmi->useEXA && pSmi->Dualhead) { 771 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 772 "CSCVideo requires XAA or EXA in single head mode.\n"); 773 pSmi->CSCVideo = FALSE; 774 } 775 } 776 777 xf86DrvMsg(pScrn->scrnIndex, from, "CSC Video %sabled\n", 778 pSmi->CSCVideo ? "en" : "dis"); 779 } 780 781 SMI_MapMmio(pScrn); 782 SMI_DetectMem(pScrn); 783 SMI_MapMem(pScrn); 784 SMI_DisableVideo(pScrn); 785 786 /* detect the panel size */ 787 SMI_DetectPanelSize(pScrn); 788 789 if(!IS_MSOC(pSmi)){ 790 if (xf86LoadSubModule(pScrn, "i2c")) { 791 SMI_I2CInit(pScrn); 792 } 793 xf86LoadSubModule(pScrn, "ddc"); 794 } 795 796 /* 797 * If the driver can do gamma correction, it should call xf86SetGamma() 798 */ 799 { 800 Gamma zeros = { 0.0, 0.0, 0.0 }; 801 802 if (!xf86SetGamma(pScrn, zeros)) { 803 SMI_EnableVideo(pScrn); 804 SMI_UnmapMem(pScrn); 805 LEAVE(FALSE); 806 } 807 } 808 809 SMI_DetectMCLK(pScrn); 810 811 /* 812 * Setup the ClockRanges, which describe what clock ranges are available, 813 * and what sort of modes they can be used for. 814 */ 815 pSmi->clockRange.next = NULL; 816 pSmi->clockRange.minClock = 20000; 817 818 if (SMI_LYNXM_SERIES(pSmi->Chipset) || 819 IS_MSOC(pSmi)) 820 pSmi->clockRange.maxClock = 200000; 821 else 822 pSmi->clockRange.maxClock = 135000; 823 824 pSmi->clockRange.clockIndex = -1; 825 pSmi->clockRange.interlaceAllowed = FALSE; 826 pSmi->clockRange.doubleScanAllowed = FALSE; 827 828 if(!SMI_CrtcPreInit(pScrn)) 829 LEAVE(FALSE); 830 831 if(!SMI_OutputPreInit(pScrn)) 832 LEAVE(FALSE); 833 834 /* Only allow growing the screen dimensions if EXA is being used */ 835 if (!xf86InitialConfiguration (pScrn, !pSmi->NoAccel && pSmi->useEXA)){ 836 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 837 838 SMI_EnableVideo(pScrn); 839 SMI_UnmapMem(pScrn); 840 LEAVE(FALSE); 841 } 842 843 /* Ensure that the framebuffer size just set fits in video memory. */ 844 { 845 int aligned_pitch = (pScrn->virtualX*pSmi->Bpp + 15) & ~15; 846 847 if(aligned_pitch * pScrn->virtualY > pSmi->FBReserved){ 848 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Not enough video memory " 849 "for the configured screen size (%dx%d) and color depth.\n", 850 pScrn->virtualX, pScrn->virtualY); 851 852 SMI_EnableVideo(pScrn); 853 SMI_UnmapMem(pScrn); 854 LEAVE(FALSE); 855 } 856 } 857 858 859 SMI_EnableVideo(pScrn); 860 SMI_UnmapMem(pScrn); 861 862 if(pSmi->pVbe){ 863 vbeFree(pSmi->pVbe); 864 pSmi->pVbe = NULL; 865 } 866 if(pSmi->pInt10){ 867 xf86FreeInt10(pSmi->pInt10); 868 pSmi->pInt10 = NULL; 869 } 870 871 /* Set display resolution */ 872 xf86SetDpi(pScrn, 0, 0); 873 874 if (xf86LoadSubModule(pScrn, "fb") == NULL) { 875 SMI_FreeRec(pScrn); 876 LEAVE(FALSE); 877 } 878 879 /* Load XAA or EXA if needed */ 880 if (!pSmi->NoAccel) { 881 if (!pSmi->useEXA) { 882 if (!xf86LoadSubModule(pScrn, "xaa")) { 883 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No acceleration\n"); 884 pSmi->NoAccel = 1; 885 } 886 } else { 887 XF86ModReqInfo req; 888 int errmaj, errmin; 889 890 memset(&req, 0, sizeof(XF86ModReqInfo)); 891 req.majorversion = 2; 892 req.minorversion = 1; 893 894 if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, 895 &req, &errmaj, &errmin)) { 896 LoaderErrorMsg(NULL, "exa", errmaj, errmin); 897 SMI_FreeRec(pScrn); 898 LEAVE(FALSE); 899 } 900 } 901 } 902 903 /* Load ramdac if needed */ 904 if (pSmi->HwCursor) { 905 if (!xf86LoadSubModule(pScrn, "ramdac")) { 906 SMI_FreeRec(pScrn); 907 LEAVE(FALSE); 908 } 909 } 910 911 LEAVE(TRUE); 912} 913 914/* 915 * This is called when VT switching back to the X server. Its job is to 916 * reinitialise the video mode. We may wish to unmap video/MMIO memory too. 917 */ 918 919static Bool 920SMI_EnterVT(VT_FUNC_ARGS_DECL) 921{ 922 SCRN_INFO_PTR(arg); 923 SMIPtr pSmi = SMIPTR(pScrn); 924 925 ENTER(); 926 927 /* Enable MMIO and map memory */ 928 SMI_MapMem(pScrn); 929 930 pSmi->Save(pScrn); 931 932 /* FBBase may have changed after remapping the memory */ 933 pScrn->pScreen->ModifyPixmapHeader(pScrn->pScreen->GetScreenPixmap(pScrn->pScreen), 934 -1,-1,-1,-1,-1, pSmi->FBBase + pSmi->FBOffset); 935#if (XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 9, 99, 1, 0)) 936 pScrn->pixmapPrivate.ptr=pSmi->FBBase + pSmi->FBOffset; 937#endif 938 939 if(pSmi->useEXA) 940 pSmi->EXADriverPtr->memoryBase=pSmi->FBBase; 941 942 /* Do the CRTC independent initialization */ 943 if(!SMI_HWInit(pScrn)) 944 LEAVE(FALSE); 945 946 /* Initialize the chosen modes */ 947 if (!xf86SetDesiredModes(pScrn)) 948 LEAVE(FALSE); 949 950 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 951 "Done writing mode. Register dump:\n"); 952 SMI_PrintRegs(pScrn); 953 954 /* Reset the grapics engine */ 955 if (!pSmi->NoAccel) 956 SMI_EngineReset(pScrn); 957 958 LEAVE(TRUE); 959} 960 961/* 962 * This is called when VT switching away from the X server. Its job is to 963 * restore the previous (text) mode. We may wish to remap video/MMIO memory 964 * too. 965 */ 966 967static void 968SMI_LeaveVT(VT_FUNC_ARGS_DECL) 969{ 970 SCRN_INFO_PTR(arg); 971 SMIPtr pSmi = SMIPTR(pScrn); 972 973 ENTER(); 974 975 SMI_AccelSync(pScrn); 976 977 /* Ensure that the rotation BlockHandler is unwrapped, and the shadow 978 pixmaps are deallocated, as the video memory is going to be 979 unmapped. */ 980 xf86RotateCloseScreen(pScrn->pScreen); 981 982 /* Pixmaps that by chance get allocated near the former aperture 983 address shouldn't be considered offscreen. */ 984 if(pSmi->useEXA) 985 pSmi->EXADriverPtr->memoryBase=NULL; 986 987 /* Clear frame buffer */ 988 memset(pSmi->FBBase, 0, pSmi->videoRAMBytes); 989 990 if (!IS_MSOC(pSmi)) { 991 vgaHWPtr hwp = VGAHWPTR(pScrn); 992 993 SMILynx_WriteMode(pScrn, &hwp->SavedReg, pSmi->save); 994 } 995 else 996 SMI501_WriteMode(pScrn, pSmi->save); 997 998 SMI_UnmapMem(pScrn); 999 1000 LEAVE(); 1001} 1002 1003static void 1004SMI_DetectPanelSize(ScrnInfoPtr pScrn) 1005{ 1006 const char *s; 1007 int width, height; 1008 SMIPtr pSmi = SMIPTR(pScrn); 1009 1010 pSmi->lcdWidth = 0; 1011 pSmi->lcdHeight = 0; 1012 if ((s = xf86GetOptValString(pSmi->Options, OPTION_PANEL_SIZE)) != NULL) { 1013 if (sscanf(s, "%dx%d", &width, &height) != 2) 1014 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1015 "Invalid PanelSize option: %s\n", s); 1016 else { 1017 pSmi->lcdWidth = width; 1018 pSmi->lcdHeight = height; 1019 } 1020 } 1021 1022 if (pSmi->lcdWidth == 0 || pSmi->lcdHeight == 0) { 1023 /* panel size detection ... requires BIOS call on 730 hardware */ 1024#ifdef USE_INT10 1025 if (pSmi->Chipset == SMI_COUGAR3DR) { 1026 if (pSmi->pInt10 != NULL) { 1027 pSmi->pInt10->num = 0x10; 1028 pSmi->pInt10->ax = 0x5F00; 1029 pSmi->pInt10->bx = 0; 1030 pSmi->pInt10->cx = 0; 1031 pSmi->pInt10->dx = 0; 1032 xf86ExecX86int10(pSmi->pInt10); 1033 if (pSmi->pInt10->ax == 0x005F) { 1034 switch (pSmi->pInt10->cx & 0x0F) { 1035 case PANEL_640x480: 1036 pSmi->lcdWidth = 640; 1037 pSmi->lcdHeight = 480; 1038 break; 1039 case PANEL_800x600: 1040 pSmi->lcdWidth = 800; 1041 pSmi->lcdHeight = 600; 1042 break; 1043 case PANEL_1024x768: 1044 pSmi->lcdWidth = 1024; 1045 pSmi->lcdHeight = 768; 1046 break; 1047 case PANEL_1280x1024: 1048 pSmi->lcdWidth = 1280; 1049 pSmi->lcdHeight = 1024; 1050 break; 1051 case PANEL_1600x1200: 1052 pSmi->lcdWidth = 1600; 1053 pSmi->lcdHeight = 1200; 1054 break; 1055 case PANEL_1400x1050: 1056 pSmi->lcdWidth = 1400; 1057 pSmi->lcdHeight = 1050; 1058 break; 1059 } 1060 1061 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1062 "Detected panel size via BIOS: %d x %d\n", 1063 pSmi->lcdWidth, pSmi->lcdHeight); 1064 } 1065 else 1066 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1067 "BIOS error during 730 panel detection!\n"); 1068 } 1069 else { 1070 /* int10 support isn't setup on the second call to this function, 1071 o if this is the second call, don't do detection again */ 1072 if (pSmi->lcd == 0) 1073 /* If we get here, int10 support is not loaded or not working */ 1074 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1075 "No BIOS support for 730 panel detection!\n"); 1076 } 1077 1078 /* Set this to indicate that we've done the detection */ 1079 pSmi->lcd = 1; 1080 } 1081 else 1082#endif /* USE_INT10 */ 1083 if (IS_MSOC(pSmi)) { 1084 pSmi->lcdWidth = (READ_SCR(pSmi, PANEL_WWIDTH) >> 16) & 2047; 1085 pSmi->lcdHeight = (READ_SCR(pSmi, PANEL_WHEIGHT) >> 16) & 2047; 1086 } 1087 else { 1088 /* panel size detection for hardware other than 730 */ 1089 pSmi->lcd = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 1090 0x31) & 0x01; 1091 1092 if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 1093 0x30) & 0x01) { 1094 pSmi->lcd <<= 1; 1095 } 1096 switch (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 1097 0x30) & 0x0C) { 1098 case 0x00: 1099 pSmi->lcdWidth = 640; 1100 pSmi->lcdHeight = 480; 1101 break; 1102 case 0x04: 1103 pSmi->lcdWidth = 800; 1104 pSmi->lcdHeight = 600; 1105 break; 1106 case 0x08: 1107 if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 1108 0x74) & 0x02) { 1109 pSmi->lcdWidth = 1024; 1110 pSmi->lcdHeight = 600; 1111 } 1112 else { 1113 pSmi->lcdWidth = 1024; 1114 pSmi->lcdHeight = 768; 1115 } 1116 break; 1117 case 0x0C: 1118 pSmi->lcdWidth = 1280; 1119 pSmi->lcdHeight = 1024; 1120 break; 1121 } 1122 } 1123 } 1124 1125 if (!pSmi->lcdWidth && (pSmi->lcdWidth = pScrn->virtualX) == 0) 1126 pSmi->lcdWidth = 1024; 1127 if (!pSmi->lcdHeight && (pSmi->lcdHeight = pScrn->virtualY) == 0) 1128 pSmi->lcdHeight = 768; 1129 1130 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s Panel Size = %dx%d\n", 1131 (pSmi->lcd == 0) ? "OFF" : (pSmi->lcd == 1) ? "TFT" : "DSTN", 1132 pSmi->lcdWidth, pSmi->lcdHeight); 1133 1134} 1135 1136static void 1137SMI_DetectMCLK(ScrnInfoPtr pScrn) 1138{ 1139 double real; 1140 MSOCClockRec clock; 1141 int mclk, mxclk; 1142 SMIPtr pSmi = SMIPTR(pScrn); 1143 1144 /* MCLK defaults */ 1145 if (pSmi->Chipset == SMI_LYNXEMplus){ 1146 /* The SM712 can be safely clocked up to 157MHz, according to 1147 Silicon Motion engineers. */ 1148 pSmi->MCLK = 157000; 1149 1150 } else if (IS_MSOC(pSmi)) { 1151 /* Set some sane defaults for the clock settings if we are on a 1152 SM502 and it's likely to be uninitialized. */ 1153 1154 if (!xf86IsPrimaryPci(pSmi->PciInfo) && 1155 (READ_SCR(pSmi, DEVICE_ID) & 0xFF) >= 0xC0) { 1156 pSmi->MCLK = 112000; 1157 pSmi->MXCLK = 144000; 1158 } 1159 1160 } else { 1161 pSmi->MCLK = 0; 1162 pSmi->MXCLK = 0; 1163 } 1164 1165 /* MCLK from user settings */ 1166 if (xf86GetOptValFreq(pSmi->Options, OPTION_MCLK, OPTUNITS_MHZ, &real)) { 1167 if (IS_MSOC(pSmi) || (int)real <= 120) { 1168 pSmi->MCLK = (int)(real * 1000.0); 1169 } else { 1170 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1171 "Memory Clock %1.3f MHz larger than limit of 120 MHz\n", 1172 real); 1173 } 1174 } 1175 mclk = pSmi->MCLK; 1176 1177 if (IS_MSOC(pSmi)) { 1178 clock.value = READ_SCR(pSmi, CURRENT_CLOCK); 1179 if (xf86GetOptValFreq(pSmi->Options, OPTION_MXCLK, 1180 OPTUNITS_MHZ, &real)) 1181 pSmi->MXCLK = (int)(real * 1000.0); 1182 } 1183 1184 /* Already programmed MCLK */ 1185 if (pSmi->MCLK == 0) { 1186 if (IS_MSOC(pSmi)) 1187 mclk = ((clock.f.m_select ? 336 : 288) / 1188 ((clock.f.m_divider ? 3 : 1) << 1189 (unsigned)clock.f.m_shift)) * 1000; 1190 else { 1191 unsigned char shift, m, n; 1192 1193 m = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A); 1194 n = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B); 1195 switch (n >> 6) { 1196 case 1: 1197 shift = 4; 1198 break; 1199 case 2: 1200 shift = 2; 1201 break; 1202 default: 1203 shift = 1; 1204 break; 1205 } 1206 n &= 0x3F; 1207 mclk = ((1431818 * m) / n / shift + 50) / 100; 1208 } 1209 } 1210 1211 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MCLK = %1.3f\n", mclk / 1000.0); 1212 if (IS_MSOC(pSmi)) { 1213 if (pSmi->MXCLK == 0) { 1214 mxclk = ((clock.f.m1_select ? 336 : 288) / 1215 ((clock.f.m1_divider ? 3 : 1) << 1216 (unsigned)clock.f.m1_shift)) * 1000; 1217 } 1218 else 1219 mxclk = pSmi->MXCLK; 1220 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MXCLK = %1.3f\n", mxclk / 1000.0); 1221 } 1222} 1223 1224static Bool 1225SMI_MapMmio(ScrnInfoPtr pScrn) 1226{ 1227 SMIPtr pSmi = SMIPTR(pScrn); 1228 CARD32 memBase; 1229 1230 SMI_EnableMmio(pScrn); 1231 1232 switch (pSmi->Chipset) { 1233 case SMI_COUGAR3DR: 1234 memBase = PCI_REGION_BASE(pSmi->PciInfo, 1, REGION_MEM); 1235 pSmi->MapSize = 0x200000; 1236 break; 1237 case SMI_LYNX3D: 1238 memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x680000; 1239 pSmi->MapSize = 0x180000; 1240 break; 1241 case SMI_LYNXEM: 1242 case SMI_LYNXEMplus: 1243 memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x400000; 1244 pSmi->MapSize = 0x400000; 1245 break; 1246 case SMI_LYNX3DM: 1247 memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM); 1248 pSmi->MapSize = 0x200000; 1249 break; 1250 case SMI_MSOC: 1251 memBase = PCI_REGION_BASE(pSmi->PciInfo, 1, REGION_MEM); 1252 pSmi->MapSize = 0x200000; 1253 break; 1254 default: 1255 memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x400000; 1256 pSmi->MapSize = 0x10000; 1257 break; 1258 } 1259 1260#ifndef XSERVER_LIBPCIACCESS 1261 pSmi->MapBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, pSmi->PciTag, 1262 memBase, pSmi->MapSize); 1263#else 1264 { 1265 void **result = (void**)&pSmi->MapBase; 1266 int err = pci_device_map_range(pSmi->PciInfo, 1267 memBase, 1268 pSmi->MapSize, 1269 PCI_DEV_MAP_FLAG_WRITABLE, 1270 result); 1271 1272 if (err) 1273 pSmi->MapBase = NULL; 1274 } 1275#endif 1276 1277 if (pSmi->MapBase == NULL) { 1278 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Internal error: could not map " 1279 "MMIO registers.\n"); 1280 return (FALSE); 1281 } 1282 1283 switch (pSmi->Chipset) { 1284 case SMI_COUGAR3DR: 1285 pSmi->DPRBase = pSmi->MapBase + 0x000000; 1286 pSmi->VPRBase = pSmi->MapBase + 0x000800; 1287 pSmi->CPRBase = pSmi->MapBase + 0x001000; 1288 pSmi->FPRBase = pSmi->MapBase + 0x005800; 1289 pSmi->IOBase = pSmi->MapBase + 0x0C0000; 1290 pSmi->DataPortBase = pSmi->MapBase + 0x100000; 1291 pSmi->DataPortSize = 0x100000; 1292 break; 1293 case SMI_LYNX3D: 1294 pSmi->DPRBase = pSmi->MapBase + 0x000000; 1295 pSmi->VPRBase = pSmi->MapBase + 0x000800; 1296 pSmi->CPRBase = pSmi->MapBase + 0x001000; 1297 pSmi->IOBase = pSmi->MapBase + 0x040000; 1298 pSmi->DataPortBase = pSmi->MapBase + 0x080000; 1299 pSmi->DataPortSize = 0x100000; 1300 break; 1301 case SMI_LYNXEM: 1302 case SMI_LYNXEMplus: 1303 pSmi->DPRBase = pSmi->MapBase + 0x008000; 1304 pSmi->VPRBase = pSmi->MapBase + 0x00C000; 1305 pSmi->CPRBase = pSmi->MapBase + 0x00E000; 1306 pSmi->IOBase = pSmi->MapBase + 0x300000; 1307 pSmi->DataPortBase = pSmi->MapBase /*+ 0x100000*/; 1308 pSmi->DataPortSize = 0x8000 /*0x200000*/; 1309 break; 1310 case SMI_LYNX3DM: 1311 pSmi->DPRBase = pSmi->MapBase + 0x000000; 1312 pSmi->VPRBase = pSmi->MapBase + 0x000800; 1313 pSmi->CPRBase = pSmi->MapBase + 0x001000; 1314 pSmi->IOBase = pSmi->MapBase + 0x0C0000; 1315 pSmi->DataPortBase = pSmi->MapBase + 0x100000; 1316 pSmi->DataPortSize = 0x100000; 1317 break; 1318 case SMI_MSOC: 1319 pSmi->DPRBase = pSmi->MapBase + 0x100000; 1320 pSmi->VPRBase = pSmi->MapBase + 0x000000; 1321 pSmi->CPRBase = pSmi->MapBase + 0x090000; 1322 pSmi->DCRBase = pSmi->MapBase + 0x080000; 1323 pSmi->SCRBase = pSmi->MapBase + 0x000000; 1324 pSmi->IOBase = 0; 1325 pSmi->DataPortBase = pSmi->MapBase + 0x110000; 1326 pSmi->DataPortSize = 0x10000; 1327 break; 1328 default: 1329 pSmi->DPRBase = pSmi->MapBase + 0x8000; 1330 pSmi->VPRBase = pSmi->MapBase + 0xC000; 1331 pSmi->CPRBase = pSmi->MapBase + 0xE000; 1332 pSmi->IOBase = NULL; 1333 pSmi->DataPortBase = pSmi->MapBase; 1334 pSmi->DataPortSize = 0x8000; 1335 break; 1336 } 1337 1338 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1339 "Physical MMIO at 0x%08lX\n", (unsigned long)memBase); 1340 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1341 "Logical MMIO at %p - %p\n", pSmi->MapBase, 1342 pSmi->MapBase + pSmi->MapSize - 1); 1343 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1344 "DPR=%p, VPR=%p, IOBase=%p\n", 1345 pSmi->DPRBase, pSmi->VPRBase, pSmi->IOBase); 1346 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1347 "DataPort=%p - %p\n", pSmi->DataPortBase, 1348 pSmi->DataPortBase + pSmi->DataPortSize - 1); 1349 1350 return (TRUE); 1351} 1352 1353/* HACK - In some cases the BIOS hasn't filled in the "scratchpad 1354 registers" (SR71) with the right amount of memory installed (e.g. MIPS 1355 platform). Probe it manually. */ 1356static unsigned long 1357SMI_ProbeMem(ScrnInfoPtr pScrn, unsigned long mem_skip, unsigned long mem_max) 1358{ 1359 SMIPtr pSmi = SMIPTR(pScrn); 1360 unsigned long mem_probe = 1024*1024; 1361 unsigned long aperture_base; 1362 void* mem; 1363 1364 ENTER(); 1365 1366 aperture_base = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + mem_skip; 1367 mem_max = min(mem_max , PCI_REGION_SIZE(pSmi->PciInfo, 0) - mem_skip); 1368 1369#ifndef XSERVER_LIBPCIACCESS 1370 mem = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, pSmi->PciTag, 1371 aperture_base, mem_max); 1372 1373 if(!mem) 1374 LEAVE(0); 1375#else 1376 if(pci_device_map_range(pSmi->PciInfo, aperture_base, mem_max, 1377 PCI_DEV_MAP_FLAG_WRITABLE, &mem)) 1378 LEAVE(0); 1379#endif 1380 1381 while(mem_probe <= mem_max){ 1382 MMIO_OUT32(mem, mem_probe-4, 0x55555555); 1383 if(MMIO_IN32(mem, mem_probe-4) != 0x55555555) 1384 break; 1385 1386 MMIO_OUT32(mem, mem_probe-4, 0xAAAAAAAA); 1387 if(MMIO_IN32(mem, mem_probe-4) != 0xAAAAAAAA) 1388 break; 1389 1390 mem_probe <<= 1; 1391 } 1392 1393#ifndef XSERVER_LIBPCIACCESS 1394 xf86UnMapVidMem(pScrn->scrnIndex, mem, mem_max); 1395#else 1396 pci_device_unmap_range(pSmi->PciInfo, mem, mem_max); 1397#endif 1398 1399 LEAVE(mem_probe >> 1); 1400} 1401 1402static Bool 1403SMI_DetectMem(ScrnInfoPtr pScrn) 1404{ 1405 SMIPtr pSmi = SMIPTR(pScrn); 1406 MessageType from; 1407 1408 if ((pScrn->videoRam = pScrn->confScreen->device->videoRam)){ 1409 pSmi->videoRAMKBytes = pScrn->videoRam; 1410 from = X_CONFIG; 1411 } 1412 else { 1413 unsigned char config; 1414 static int lynx3d_table[4] = { 0, 2, 4, 6 }; 1415 static int lynx3dm_table[4] = { 16, 2, 4, 8 }; 1416 static int msoc_table[8] = { 4, 8, 16, 32, 64, 2, 0, 0 }; 1417 static int default_table[4] = { 1, 2, 4, 0 }; 1418 1419 if (IS_MSOC(pSmi)) { 1420 config = (READ_SCR(pSmi, DRAM_CTL) >> 13) & 7; 1421 pSmi->videoRAMKBytes = msoc_table[config] * 1024 - 1422 SHARED_USB_DMA_BUFFER_SIZE; 1423 } 1424 else { 1425 config = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x71); 1426 switch (pSmi->Chipset) { 1427 case SMI_LYNX3D: 1428 pSmi->videoRAMKBytes = lynx3d_table[config >> 6] * 1024 + 1429 512; 1430 break; 1431 case SMI_LYNXEMplus: 1432 pSmi->videoRAMKBytes = SMI_ProbeMem(pScrn, 0, 0x400000) / 1024; 1433 break; 1434 case SMI_LYNX3DM: 1435 pSmi->videoRAMKBytes = lynx3dm_table[config >> 6] * 1024; 1436 break; 1437 case SMI_COUGAR3DR: 1438 /* DANGER - Cougar3DR BIOS is broken - hardcode video ram 1439 * size per instructions from Silicon Motion engineers */ 1440 pSmi->videoRAMKBytes = 16 * 1024; 1441 break; 1442 default: 1443 pSmi->videoRAMKBytes = default_table[config >> 6] * 1024; 1444 break; 1445 } 1446 } 1447 from = X_PROBED; 1448 } 1449 1450 pSmi->videoRAMBytes = pSmi->videoRAMKBytes * 1024; 1451 pScrn->videoRam = pSmi->videoRAMKBytes; 1452 xf86DrvMsg(pScrn->scrnIndex, from, 1453 "videoram: %dkB\n", pSmi->videoRAMKBytes); 1454 1455 return (TRUE); 1456} 1457 1458Bool 1459SMI_MapMem(ScrnInfoPtr pScrn) 1460{ 1461 SMIPtr pSmi = SMIPTR(pScrn); 1462 vgaHWPtr hwp; 1463 1464 ENTER(); 1465 1466 if (pSmi->MapBase == NULL && SMI_MapMmio(pScrn) == FALSE) 1467 LEAVE(FALSE); 1468 1469 pScrn->memPhysBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM); 1470 1471 if (pSmi->Chipset == SMI_LYNX3DM) 1472 pSmi->fbMapOffset = 0x200000; 1473 else 1474 pSmi->fbMapOffset = 0x0; 1475 1476#ifndef XSERVER_LIBPCIACCESS 1477 pSmi->FBBase = xf86MapPciMem(pScrn->scrnIndex, 1478 VIDMEM_FRAMEBUFFER, 1479 pSmi->PciTag, 1480 pScrn->memPhysBase + pSmi->fbMapOffset, 1481 pSmi->videoRAMBytes); 1482#else 1483 { 1484 void **result = (void**)&pSmi->FBBase; 1485 int err = pci_device_map_range(pSmi->PciInfo, 1486 pScrn->memPhysBase + 1487 pSmi->fbMapOffset, 1488 pSmi->videoRAMBytes, 1489 PCI_DEV_MAP_FLAG_WRITABLE | 1490 PCI_DEV_MAP_FLAG_WRITE_COMBINE, 1491 result); 1492 1493 if (err) 1494 LEAVE(FALSE); 1495 } 1496#endif 1497 1498 if (pSmi->FBBase == NULL) { 1499 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1500 "Internal error: could not map framebuffer.\n"); 1501 LEAVE(FALSE); 1502 } 1503 1504 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1505 "Physical frame buffer at 0x%08lX offset: 0x%08lX\n", 1506 pScrn->memPhysBase, (unsigned long)pSmi->fbMapOffset); 1507 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1508 "Logical frame buffer at %p - %p\n", pSmi->FBBase, 1509 pSmi->FBBase + pSmi->videoRAMBytes - 1); 1510 1511 if (IS_MSOC(pSmi)) { 1512 /* Reserve space for panel cursr, and crt if in dual head mode */ 1513#if SMI_CURSOR_ALPHA_PLANE 1514 pSmi->FBReserved = pSmi->FBCursorOffset = pSmi->videoRAMBytes - 1515 (pSmi->Dualhead ? SMI501_CURSOR_SIZE << 1 : SMI501_ARGB_CURSOR_SIZE); 1516#else 1517 pSmi->FBReserved = pSmi->FBCursorOffset = pSmi->videoRAMBytes - 1518 (pSmi->Dualhead ? SMI501_CURSOR_SIZE << 1 : SMI501_CURSOR_SIZE); 1519 1520# if SMI501_CLI_DEBUG 1521 if (pSmi->useEXA) { 1522 pSmi->batch_active = FALSE; 1523 pSmi->batch_length = 4096; 1524 pSmi->FBReserved -= pSmi->batch_length << 3; 1525 pSmi->batch_offset = pSmi->FBReserved; 1526 pSmi->batch_handle = (int64_t *)(pSmi->FBBase + pSmi->batch_offset); 1527 pSmi->batch_finish = -1; 1528 pSmi->batch_index = 0; 1529 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1530 "Using command list interpreter debug code\n"); 1531 } 1532# endif 1533 1534#endif 1535 } 1536 else { 1537 /* Set up offset to hwcursor memory area, at the end of 1538 * the frame buffer. 1539 */ 1540 pSmi->FBCursorOffset = pSmi->videoRAMBytes - SMILYNX_CURSOR_SIZE; 1541 /* set up the fifo reserved space */ 1542 if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x30) & 0x01)/* #1074 */ { 1543 CARD32 fifoOffset = 0; 1544 fifoOffset |= VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 1545 0x46) << 3; 1546 fifoOffset |= VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 1547 0x47) << 11; 1548 fifoOffset |= (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 1549 0x49) & 0x1C) << 17; 1550 pSmi->FBReserved = fifoOffset; /* PDR#1074 */ 1551 } 1552 else 1553 pSmi->FBReserved = pSmi->videoRAMBytes - 2048; 1554 1555 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Cursor Offset: %08lX\n", 1556 (unsigned long)pSmi->FBCursorOffset); 1557 1558 /* Assign hwp->MemBase & IOBase here */ 1559 hwp = VGAHWPTR(pScrn); 1560 if (pSmi->IOBase != NULL) 1561 vgaHWSetMmioFuncs(hwp, pSmi->MapBase, pSmi->IOBase - pSmi->MapBase); 1562 vgaHWGetIOBase(hwp); 1563 1564 /* Map the VGA memory when the primary video */ 1565 if (xf86IsPrimaryPci(pSmi->PciInfo)) { 1566 hwp->MapSize = 0x10000; 1567 if (!vgaHWMapMem(pScrn)) 1568 LEAVE(FALSE); 1569 pSmi->PrimaryVidMapped = TRUE; 1570 } 1571 } 1572 1573 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reserved: %08lX\n", 1574 (unsigned long)pSmi->FBReserved); 1575 1576 LEAVE(TRUE); 1577} 1578 1579/* UnMapMem - contains half of pre-4.0 EnterLeave function. The EnterLeave 1580 * function which en/disable access to IO ports and ext. regs 1581 */ 1582 1583void 1584SMI_UnmapMem(ScrnInfoPtr pScrn) 1585{ 1586 SMIPtr pSmi = SMIPTR(pScrn); 1587 1588 ENTER(); 1589 1590 /* Unmap VGA mem if mapped. */ 1591 if (pSmi->PrimaryVidMapped) { 1592 vgaHWUnmapMem(pScrn); 1593 pSmi->PrimaryVidMapped = FALSE; 1594 } 1595 1596 SMI_DisableMmio(pScrn); 1597 1598 if (pSmi->MapBase) { 1599#ifndef XSERVER_LIBPCIACCESS 1600 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSmi->MapBase, 1601 pSmi->MapSize); 1602#else 1603 pci_device_unmap_range(pSmi->PciInfo, (pointer)pSmi->MapBase, 1604 pSmi->MapSize); 1605#endif 1606 pSmi->MapBase = NULL; 1607 } 1608 1609 if (pSmi->FBBase) { 1610#ifndef XSERVER_LIBPCIACCESS 1611 xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pSmi->FBBase, 1612 pSmi->videoRAMBytes); 1613#else 1614 pci_device_unmap_range(pSmi->PciInfo, (pointer)pSmi->FBBase, 1615 pSmi->videoRAMBytes); 1616#endif 1617 pSmi->FBBase = NULL; 1618 } 1619 1620 LEAVE(); 1621} 1622 1623/* This gets called at the start of each server generation. */ 1624 1625static Bool 1626SMI_ScreenInit(SCREEN_INIT_ARGS_DECL) 1627{ 1628 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1629 SMIPtr pSmi = SMIPTR(pScrn); 1630 EntityInfoPtr pEnt; 1631 1632 ENTER(); 1633 1634 /* Map MMIO regs and framebuffer */ 1635 if (!SMI_MapMem(pScrn)) 1636 LEAVE(FALSE); 1637 1638 pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 1639 1640 if (!pSmi->pInt10 && pSmi->useBIOS) { 1641 pSmi->pInt10 = xf86InitInt10(pEnt->index); 1642 } 1643 if (!pSmi->pVbe && pSmi->pInt10 && xf86LoaderCheckSymbol("VBEInit")) { 1644 pSmi->pVbe = VBEInit(pSmi->pInt10, pEnt->index); 1645 } 1646 1647 /* Save the chip/graphics state */ 1648 pSmi->Save(pScrn); 1649 1650 /* Fill in some needed pScrn fields */ 1651 pScrn->vtSema = TRUE; 1652 pScrn->pScreen = pScreen; 1653 1654 pScrn->displayWidth = ((pScrn->virtualX * pSmi->Bpp + 15) & ~15) / pSmi->Bpp; 1655 1656 pSmi->fbArea = NULL; 1657 pSmi->FBOffset = 0; 1658 pScrn->fbOffset = pSmi->FBOffset + pSmi->fbMapOffset; 1659 1660 /* Clear frame buffer */ 1661 memset(pSmi->FBBase, 0, pSmi->videoRAMBytes); 1662 1663 /* 1664 * The next step is to setup the screen's visuals, and initialise the 1665 * framebuffer code. In cases where the framebuffer's default choises for 1666 * things like visual layouts and bits per RGB are OK, this may be as simple 1667 * as calling the framebuffer's ScreenInit() function. If not, the visuals 1668 * will need to be setup before calling a fb ScreenInit() function and fixed 1669 * up after. 1670 */ 1671 1672 /* 1673 * Reset the visual list. 1674 */ 1675 miClearVisualTypes(); 1676 1677 /* Setup the visuals we support. */ 1678 1679 if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth), 1680 pScrn->rgbBits, pScrn->defaultVisual)) 1681 LEAVE(FALSE); 1682 1683 if (!miSetPixmapDepths ()) 1684 LEAVE(FALSE); 1685 1686 /* 1687 * Call the framebuffer layer's ScreenInit function 1688 */ 1689 1690 DEBUG("\tInitializing FB @ 0x%08X for %dx%d (%d)\n", 1691 pSmi->FBBase, pScrn->virtualX, pScrn->virtualY, pScrn->displayWidth); 1692 if(!fbScreenInit(pScreen, pSmi->FBBase, pScrn->virtualX, pScrn->virtualY, pScrn->xDpi, 1693 pScrn->yDpi, pScrn->displayWidth, pScrn->bitsPerPixel)) 1694 LEAVE(FALSE); 1695 1696 xf86SetBlackWhitePixels(pScreen); 1697 1698 if (pScrn->bitsPerPixel > 8) { 1699 VisualPtr visual; 1700 /* Fixup RGB ordering */ 1701 visual = pScreen->visuals + pScreen->numVisuals; 1702 while (--visual >= pScreen->visuals) { 1703 if ((visual->class | DynamicClass) == DirectColor) { 1704 visual->offsetRed = pScrn->offset.red; 1705 visual->offsetGreen = pScrn->offset.green; 1706 visual->offsetBlue = pScrn->offset.blue; 1707 visual->redMask = pScrn->mask.red; 1708 visual->greenMask = pScrn->mask.green; 1709 visual->blueMask = pScrn->mask.blue; 1710 } 1711 } 1712 } 1713 1714 /* must be after RGB ordering fixed */ 1715 fbPictureInit(pScreen, 0, 0); 1716 1717 /* Do the CRTC independent initialization */ 1718 if(!SMI_HWInit(pScrn)) 1719 LEAVE(FALSE); 1720 1721 /* Unless using EXA, regardless or using XAA or not, needs offscreen 1722 * management at least for video. */ 1723 if (pSmi->NoAccel || !pSmi->useEXA) { 1724 int numLines; 1725 BoxRec AvailFBArea; 1726 1727 numLines = pSmi->FBReserved / (pScrn->displayWidth * pSmi->Bpp); 1728 AvailFBArea.x1 = 0; 1729 AvailFBArea.y1 = 0; 1730 AvailFBArea.x2 = pScrn->virtualX; 1731 AvailFBArea.y2 = numLines; 1732 1733 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1734 "FrameBuffer Box: %d,%d - %d,%d\n", 1735 AvailFBArea.x1, AvailFBArea.y1, AvailFBArea.x2, 1736 AvailFBArea.y2); 1737 1738 xf86InitFBManager(pScreen, &AvailFBArea); 1739 } 1740 1741 /* Initialize acceleration layer */ 1742 if (!pSmi->NoAccel) { 1743 if (pSmi->useEXA && !SMI_EXAInit(pScreen)) 1744 LEAVE(FALSE); 1745 else if (!pSmi->useEXA && !SMI_XAAInit(pScreen)) 1746 LEAVE(FALSE); 1747 } 1748 1749 /* Initialize the chosen modes */ 1750 if (!xf86SetDesiredModes(pScrn)) 1751 LEAVE(FALSE); 1752 1753 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1754 "Done writing mode. Register dump:\n"); 1755 SMI_PrintRegs(pScrn); 1756 1757#ifdef HAVE_XMODES 1758 xf86DiDGAInit(pScreen, (unsigned long)(pSmi->FBBase + pScrn->fbOffset)); 1759#endif 1760 1761 /* Initialise cursor functions */ 1762 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1763 1764 /* Initialize HW cursor layer. Must follow software cursor 1765 * initialization. 1766 */ 1767 if (pSmi->HwCursor) { 1768 int size, flags; 1769 1770 if (IS_MSOC(pSmi)) { 1771 size = SMI501_MAX_CURSOR; 1772 flags = (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 | 1773 HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK); 1774#if SMI_CURSOR_ALPHA_PLANE 1775 if (!pSmi->Dualhead) 1776 flags |= HARDWARE_CURSOR_ARGB; 1777#endif 1778 } 1779 else { 1780 size = SMILYNX_MAX_CURSOR; 1781 flags = (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 | 1782 HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | 1783 HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | 1784 HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | 1785 HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 1786 HARDWARE_CURSOR_INVERT_MASK); 1787 } 1788 1789 if (!xf86_cursors_init(pScreen, size, size, flags)) 1790 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1791 "Hardware cursor initialization failed\n"); 1792 } 1793 1794 /* Initialise default colormap */ 1795 if (!miCreateDefColormap(pScreen)) 1796 LEAVE(FALSE); 1797 1798 /* Initialize colormap layer. Must follow initialization of the default 1799 * colormap. And SetGamma call, else it will load palette with solid white. 1800 */ 1801 if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits,SMI_LoadPalette, NULL, 1802 CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR)) 1803 LEAVE(FALSE); 1804 1805 pScreen->SaveScreen = SMI_SaveScreen; 1806 pSmi->CloseScreen = pScreen->CloseScreen; 1807 pScreen->CloseScreen = SMI_CloseScreen; 1808 1809 if ((IS_MSOC(pSmi) && 1810 !xf86DPMSInit(pScreen, SMI501_DisplayPowerManagementSet, 0)) || 1811 (!IS_MSOC(pSmi) && 1812 !xf86DPMSInit(pScreen, SMILynx_DisplayPowerManagementSet, 0))) 1813 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DPMS initialization failed!\n"); 1814 1815 SMI_InitVideo(pScreen); 1816 1817 if(!xf86CrtcScreenInit(pScreen)) 1818 LEAVE(FALSE); 1819 1820 /* Report any unused options (only for the first generation) */ 1821 if (serverGeneration == 1) { 1822 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1823 } 1824 1825 LEAVE(TRUE); 1826} 1827 1828/* 1829 * This is called at the end of each server generation. It restores the 1830 * original (text) mode. It should also unmap the video memory, and free any 1831 * per-generation data allocated by the driver. It should finish by unwrapping 1832 * and calling the saved CloseScreen function. 1833 */ 1834 1835static Bool 1836SMI_CloseScreen(CLOSE_SCREEN_ARGS_DECL) 1837{ 1838 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1839 SMIPtr pSmi = SMIPTR(pScrn); 1840 Bool ret; 1841 1842 ENTER(); 1843 1844 if (pSmi->HwCursor) 1845 xf86_cursors_fini(pScreen); 1846 1847 if (pScrn->vtSema) 1848 /* Restore console mode and unmap framebuffer */ 1849 SMI_LeaveVT(VT_FUNC_ARGS); 1850 1851#ifdef HAVE_XAA_H 1852 if (pSmi->XAAInfoRec != NULL) { 1853 XAADestroyInfoRec(pSmi->XAAInfoRec); 1854 } 1855#endif 1856 if (pSmi->EXADriverPtr) { 1857 exaDriverFini(pScreen); 1858 pSmi->EXADriverPtr = NULL; 1859 } 1860 if (pSmi->pVbe != NULL) { 1861 vbeFree(pSmi->pVbe); 1862 pSmi->pVbe = NULL; 1863 } 1864 if (pSmi->pInt10 != NULL) { 1865 xf86FreeInt10(pSmi->pInt10); 1866 pSmi->pInt10 = NULL; 1867 } 1868 if (pSmi->ptrAdaptor != NULL) { 1869 free(pSmi->ptrAdaptor); 1870 } 1871 if (pSmi->BlockHandler != NULL) { 1872 pScreen->BlockHandler = pSmi->BlockHandler; 1873 } 1874 1875 pScrn->vtSema = FALSE; 1876 pScreen->CloseScreen = pSmi->CloseScreen; 1877 ret = (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); 1878 1879 LEAVE(ret); 1880} 1881 1882static void 1883SMI_FreeScreen(FREE_SCREEN_ARGS_DECL) 1884{ 1885 SCRN_INFO_PTR(arg); 1886 SMI_FreeRec(pScrn); 1887} 1888 1889static Bool 1890SMI_SaveScreen(ScreenPtr pScreen, int mode) 1891{ 1892 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1893 1894 ENTER(); 1895 1896 if(xf86IsUnblank(mode)){ 1897 pScrn->DPMSSet(pScrn, DPMSModeOn, 0); 1898 }else{ 1899 pScrn->DPMSSet(pScrn, DPMSModeOff, 0); 1900 } 1901 1902 LEAVE(TRUE); 1903} 1904 1905void 1906SMI_AdjustFrame(ADJUST_FRAME_ARGS_DECL) 1907{ 1908 SCRN_INFO_PTR(arg); 1909 xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn); 1910 xf86CrtcPtr compat_crtc = crtcConf->output[crtcConf->compat_output]->crtc; 1911 1912 ENTER(); 1913 1914 SMICRTC(compat_crtc)->adjust_frame(compat_crtc,x,y); 1915 1916 LEAVE(); 1917} 1918 1919Bool 1920SMI_SwitchMode(SWITCH_MODE_ARGS_DECL) 1921{ 1922 Bool ret; 1923 SCRN_INFO_PTR(arg); 1924 SMIPtr pSmi = SMIPTR(pScrn); 1925 1926 ENTER(); 1927 1928 ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0); 1929 1930 if (!pSmi->NoAccel) 1931 SMI_EngineReset(pScrn); 1932 1933 LEAVE(ret); 1934} 1935 1936void 1937SMI_LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies, 1938 LOCO *colors, VisualPtr pVisual) 1939{ 1940 xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn); 1941 int crtc_idx,i,j; 1942 1943 ENTER(); 1944 1945 if(pScrn->bitsPerPixel == 16){ 1946 /* Expand the RGB 565 palette into the 256-elements LUT */ 1947 1948 for(crtc_idx=0; crtc_idx<crtcConf->num_crtc; crtc_idx++){ 1949 SMICrtcPrivatePtr crtcPriv = SMICRTC(crtcConf->crtc[crtc_idx]); 1950 1951 for(i=0; i<numColors; i++){ 1952 int idx = indicies[i]; 1953 1954 if(idx<32){ 1955 for(j=0; j<8; j++){ 1956 crtcPriv->lut_r[idx*8 + j] = colors[idx].red << 8; 1957 crtcPriv->lut_b[idx*8 + j] = colors[idx].blue << 8; 1958 } 1959 } 1960 1961 for(j=0; j<4; j++) 1962 crtcPriv->lut_g[idx*4 + j] = colors[idx].green << 8; 1963 } 1964 1965 crtcPriv->load_lut(crtcConf->crtc[crtc_idx]); 1966 } 1967 }else{ 1968 for(crtc_idx=0; crtc_idx<crtcConf->num_crtc; crtc_idx++){ 1969 SMICrtcPrivatePtr crtcPriv = SMICRTC(crtcConf->crtc[crtc_idx]); 1970 1971 for(i = 0; i < numColors; i++) { 1972 int idx = indicies[i]; 1973 1974 crtcPriv->lut_r[idx] = colors[idx].red << 8; 1975 crtcPriv->lut_g[idx] = colors[idx].green << 8; 1976 crtcPriv->lut_b[idx] = colors[idx].blue << 8; 1977 } 1978 1979 crtcPriv->load_lut(crtcConf->crtc[crtc_idx]); 1980 } 1981 } 1982 1983 LEAVE(); 1984} 1985 1986static void 1987SMI_DisableVideo(ScrnInfoPtr pScrn) 1988{ 1989 SMIPtr pSmi = SMIPTR(pScrn); 1990 CARD8 tmp; 1991 1992 if (!IS_MSOC(pSmi)) { 1993 if (!(tmp = VGAIN8(pSmi, VGA_DAC_MASK))) 1994 return; 1995 pSmi->DACmask = tmp; 1996 VGAOUT8(pSmi, VGA_DAC_MASK, 0); 1997 } 1998} 1999 2000static void 2001SMI_EnableVideo(ScrnInfoPtr pScrn) 2002{ 2003 SMIPtr pSmi = SMIPTR(pScrn); 2004 2005 if (!IS_MSOC(pSmi)) { 2006 VGAOUT8(pSmi, VGA_DAC_MASK, pSmi->DACmask); 2007 } 2008} 2009 2010 2011void 2012SMI_EnableMmio(ScrnInfoPtr pScrn) 2013{ 2014#if !defined(__mips__) 2015 SMIPtr pSmi = SMIPTR(pScrn); 2016 2017 ENTER(); 2018 2019 if (!IS_MSOC(pSmi)) { 2020 vgaHWPtr hwp = VGAHWPTR(pScrn); 2021 CARD8 tmp; 2022 2023 /* 2024 * Enable chipset (seen on uninitialized secondary cards) might not be 2025 * needed once we use the VGA softbooter 2026 */ 2027 vgaHWSetStdFuncs(hwp); 2028 2029 /* Enable linear mode */ 2030 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18); 2031 tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA); 2032 pSmi->SR18Value = tmp; /* PDR#521 */ 2033 outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp | 0x11); 2034 2035 /* Enable 2D/3D Engine and Video Processor */ 2036 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21); 2037 tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA); 2038 pSmi->SR21Value = tmp; /* PDR#521 */ 2039 outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp & ~0x03); 2040 } 2041 2042 LEAVE(); 2043#endif 2044} 2045 2046void 2047SMI_DisableMmio(ScrnInfoPtr pScrn) 2048{ 2049#if !defined(__mips__) 2050 SMIPtr pSmi = SMIPTR(pScrn); 2051 2052 ENTER(); 2053 2054 if (!IS_MSOC(pSmi)) { 2055 vgaHWPtr hwp = VGAHWPTR(pScrn); 2056 2057 vgaHWSetStdFuncs(hwp); 2058 2059 /* Disable 2D/3D Engine and Video Processor */ 2060 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21); 2061 outb(pSmi->PIOBase + VGA_SEQ_DATA, pSmi->SR21Value); /* PDR#521 */ 2062 2063 /* Disable linear mode */ 2064 outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18); 2065 outb(pSmi->PIOBase + VGA_SEQ_DATA, pSmi->SR18Value); /* PDR#521 */ 2066 } 2067 2068 LEAVE(); 2069#endif 2070} 2071 2072static void 2073SMI_ProbeDDC(ScrnInfoPtr pScrn, int index) 2074{ 2075 vbeInfoPtr pVbe; 2076 if (xf86LoadSubModule(pScrn, "vbe")) { 2077 pVbe = VBEInit(NULL, index); 2078 ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 2079 vbeFree(pVbe); 2080 } 2081} 2082 2083static Bool 2084SMI_HWInit(ScrnInfoPtr pScrn) 2085{ 2086 SMIPtr pSmi = SMIPTR(pScrn); 2087 2088 ENTER(); 2089 2090 if(IS_MSOC(pSmi)) 2091 LEAVE(SMI501_HWInit(pScrn)); 2092 else 2093 LEAVE(SMILynx_HWInit(pScrn)); 2094} 2095 2096void 2097SMI_PrintRegs(ScrnInfoPtr pScrn) 2098{ 2099 SMIPtr pSmi = SMIPTR(pScrn); 2100 int i; 2101 2102 ENTER(); 2103 2104 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 2105 "START register dump ------------------\n"); 2106 2107 if(IS_MSOC(pSmi)) 2108 SMI501_PrintRegs(pScrn); 2109 else 2110 SMILynx_PrintRegs(pScrn); 2111 2112 2113 xf86ErrorFVerb(VERBLEV, "\n\nDPR x0 x4 x8 xC"); 2114 for (i = 0x00; i <= 0x44; i += 4) { 2115 if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i); 2116 xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_DPR(pSmi, i)); 2117 } 2118 2119 xf86ErrorFVerb(VERBLEV, "\n\nVPR x0 x4 x8 xC"); 2120 for (i = 0x00; i <= 0x60; i += 4) { 2121 if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i); 2122 xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_VPR(pSmi, i)); 2123 } 2124 2125 xf86ErrorFVerb(VERBLEV, "\n\nCPR x0 x4 x8 xC"); 2126 for (i = 0x00; i <= 0x18; i += 4) { 2127 if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i); 2128 xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_CPR(pSmi, i)); 2129 } 2130 2131 xf86ErrorFVerb(VERBLEV, "\n\n"); 2132 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 2133 "END register dump --------------------\n"); 2134 2135 LEAVE(); 2136} 2137 2138static Bool 2139SMI_driverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op, 2140 pointer ptr) 2141{ 2142 xorgHWFlags *flag; 2143 2144 switch (op) { 2145 case GET_REQUIRED_HW_INTERFACES: 2146 flag = (CARD32*)ptr; 2147 (*flag) = HW_MMIO; 2148 return TRUE; 2149 default: 2150 return FALSE; 2151 } 2152} 2153