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