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