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