s3_driver.c revision 96cdd0b9
1/* 2 * Copyright 2001 Ani Joshi <ajoshi@unixbox.com> 3 * 4 * XFree86 4.x driver for S3 chipsets 5 * 6 * 7 * Permission to use, copy, modify, distribute, and sell this software and its 8 * documentation for any purpose is hereby granted without fee, provided that 9 * the above copyright notice appear in all copies and that both that copyright 10 * notice and this permission notice appear in supporting documentation and 11 * that the name of Ani Joshi not be used in advertising or 12 * publicity pertaining to distribution of the software without specific, 13 * written prior permission. Ani Joshi makes no representations 14 * about the suitability of this software for any purpose. It is provided 15 * "as-is" without express or implied warranty. 16 * 17 * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 19 * EVENT SHALL ANI JOSHI BE LIABLE FOR ANY SPECIAL, INDIRECT OR 20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 23 * PERFORMANCE OF THIS SOFTWARE. 24 * 25 * 26 * Credits: 27 * Thomas Roell <roell@informatik.tu-muenchen.de> 28 * Mark Vojkovich <markv@valinux.com> 29 * Kevin E. Martin <martin@valinux.com> 30 * - and others for their work on the 3.x S3 driver 31 * 32 * Dominik Behr 33 * - for various hardware donations 34 * 35 * 36 */ 37 38#ifdef HAVE_CONFIG_H 39#include "config.h" 40#endif 41 42#include "xf86.h" 43#include "xf86_OSproc.h" 44#include "xf86Pci.h" 45#include "xf86PciInfo.h" 46#include "xf86fbman.h" 47#include "xf86cmap.h" 48#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 49#include "xf86Resources.h" 50#include "xf86RAC.h" 51#endif 52#include "compiler.h" 53#include "xaa.h" 54#include "mipointer.h" 55#include "micmap.h" 56#include "mibstore.h" 57#include "fb.h" 58#include "inputstr.h" 59#include "shadowfb.h" 60#include "IBM.h" 61#include "TI.h" 62 63#include "s3.h" 64#include "s3_reg.h" 65 66#define TRIO64_RAMDAC 0x8811 67 68 69short s3alu[16] = 70{ 71 MIX_0, 72 MIX_AND, 73 MIX_SRC_AND_NOT_DST, 74 MIX_SRC, 75 MIX_NOT_SRC_AND_DST, 76 MIX_DST, 77 MIX_XOR, 78 MIX_OR, 79 MIX_NOR, 80 MIX_XNOR, 81 MIX_NOT_DST, 82 MIX_SRC_OR_NOT_DST, 83 MIX_NOT_SRC, 84 MIX_NOT_SRC_OR_DST, 85 MIX_NAND, 86 MIX_1, 87}; 88 89 90/* 91 * Prototypes 92 */ 93static const OptionInfoRec * S3AvailableOptions(int chipid, int busid); 94static void S3Identify(int flags); 95static Bool S3Probe(DriverPtr drv, int flags); 96static Bool S3PreInit(ScrnInfoPtr pScrn, int flags); 97static Bool S3EnterVT(int scrnIndex, int flags); 98static void S3LeaveVT(int scrnIndex, int flags); 99static void S3Save(ScrnInfoPtr pScrn); 100static Bool S3ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, 101 char **argv); 102static Bool S3MapMem(ScrnInfoPtr pScrn); 103static void S3UnmapMem(ScrnInfoPtr pScrn); 104static Bool S3ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); 105static void S3AdjustFrame(int scrnIndex, int x, int y, int flags); 106Bool S3CloseScreen(int scrnIndex, ScreenPtr pScreen); 107Bool S3SaveScreen(ScreenPtr pScreen, int mode); 108static void S3FreeScreen(int scrnIndex, int flags); 109static void S3GenericLoadPalette(ScrnInfoPtr pScrn, int numColors, 110 int *indicies, LOCO *colors, 111 VisualPtr pVisual); 112static void S3Restore(ScrnInfoPtr pScrn); 113void S3BankZero(ScrnInfoPtr pScrn); 114void S3Regdump(ScrnInfoPtr pScrn); 115static void S3DisplayPowerManagementSet(ScrnInfoPtr pScrn, 116 int PowerManagementMode, int flags); 117 118 119 120_X_EXPORT DriverRec S3 = 121{ 122 S3_VERSION, 123 DRIVER_NAME, 124 S3Identify, 125 S3Probe, 126 S3AvailableOptions, 127 NULL, 128 0 129}; 130 131/* supported chipsets */ 132static SymTabRec S3Chipsets[] = { 133 { PCI_CHIP_864_0, "864-0"}, 134 { PCI_CHIP_864_1, "864-1"}, 135 { PCI_CHIP_964_0, "964-0"}, 136 { PCI_CHIP_964_1, "964-1"}, 137 { PCI_CHIP_968, "968" }, 138 { PCI_CHIP_TRIO, "Trio32/64" }, 139 { PCI_CHIP_AURORA64VP, "Aurora64V+" }, 140 { PCI_CHIP_TRIO64UVP, "Trio64UV+" }, 141 { PCI_CHIP_TRIO64V2_DXGX, "Trio64V2/DX/GX" }, 142 { -1, NULL } 143}; 144 145 146static PciChipsets S3PciChipsets[] = { 147 { PCI_CHIP_864_0, PCI_CHIP_864_0, RES_SHARED_VGA }, 148 { PCI_CHIP_864_1, PCI_CHIP_864_1, RES_SHARED_VGA }, 149 { PCI_CHIP_964_0, PCI_CHIP_964_0, RES_SHARED_VGA }, 150 { PCI_CHIP_964_1, PCI_CHIP_964_1, RES_SHARED_VGA }, 151 { PCI_CHIP_968, PCI_CHIP_968, RES_SHARED_VGA }, 152 { PCI_CHIP_TRIO, PCI_CHIP_TRIO, RES_SHARED_VGA }, 153 { PCI_CHIP_AURORA64VP, PCI_CHIP_AURORA64VP, RES_SHARED_VGA }, 154 { PCI_CHIP_TRIO64UVP, PCI_CHIP_TRIO64UVP, RES_SHARED_VGA }, 155 { PCI_CHIP_TRIO64V2_DXGX, PCI_CHIP_TRIO64V2_DXGX, RES_SHARED_VGA }, 156 { -1, -1, RES_UNDEFINED } 157}; 158 159typedef enum { 160 OPTION_NOACCEL, 161 OPTION_HWCURS, 162 OPTION_SLOW_DRAM_REFRESH, 163 OPTION_SLOW_DRAM, 164 OPTION_SLOW_EDODRAM, 165 OPTION_SLOW_VRAM, 166 OPTION_XVIDEO, 167 OPTION_SHADOW_FB, 168 OPTION_ROTATE 169} S3Opts; 170 171static OptionInfoRec S3Options[] = { 172 { OPTION_NOACCEL, "noaccel", OPTV_BOOLEAN, {0}, FALSE }, 173 { OPTION_HWCURS, "hwcursor", OPTV_BOOLEAN, {0}, FALSE }, 174 { OPTION_SLOW_DRAM_REFRESH, "slow_dram_refresh", OPTV_BOOLEAN, {0}, FALSE }, 175 { OPTION_SLOW_DRAM, "slow_dram", OPTV_BOOLEAN, {0}, FALSE }, 176 { OPTION_SLOW_EDODRAM, "slow_edodram", OPTV_BOOLEAN, {0}, FALSE }, 177 { OPTION_SLOW_VRAM, "slow_vram", OPTV_BOOLEAN, {0}, FALSE }, 178 { OPTION_XVIDEO, "XVideo", OPTV_BOOLEAN, {0}, FALSE }, 179 { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, 180 { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, 181 { -1, NULL, OPTV_NONE, {0}, FALSE } 182}; 183 184RamDacSupportedInfoRec S3IBMRamdacs[] = { 185 { IBM524_RAMDAC }, 186 { IBM524A_RAMDAC }, 187 { IBM526_RAMDAC }, 188 { IBM526DB_RAMDAC }, 189 { -1 } 190}; 191 192static int s3AccelLinePitches[] = { 640, 800, 1024, 1280, 1600 }; 193 194#ifdef XFree86LOADER 195 196MODULESETUPPROTO(S3Setup); 197 198static XF86ModuleVersionInfo S3VersRec = { 199 "s3", 200 MODULEVENDORSTRING, 201 MODINFOSTRING1, 202 MODINFOSTRING2, 203 XORG_VERSION_CURRENT, 204 VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL, 205 ABI_CLASS_VIDEODRV, 206 ABI_VIDEODRV_VERSION, 207 MOD_CLASS_VIDEODRV, 208 {0, 0, 0, 0} 209}; 210 211 212_X_EXPORT XF86ModuleData s3ModuleData = { &S3VersRec, S3Setup, NULL }; 213 214pointer S3Setup (pointer module, pointer opts, int *errmaj, int *errmin) 215{ 216 static Bool setupDone = FALSE; 217 218 if (!setupDone) { 219 setupDone = TRUE; 220 xf86AddDriver(&S3, module, 0); 221 return (pointer) 1; 222 } else { 223 if (errmaj) 224 *errmaj = LDR_ONCEONLY; 225 return NULL; 226 } 227} 228 229#endif /* XFree86LOADER */ 230 231 232static Bool S3GetRec(ScrnInfoPtr pScrn) 233{ 234 if (pScrn->driverPrivate) 235 return TRUE; 236 237 pScrn->driverPrivate = xnfcalloc(sizeof(S3Rec), 1); 238 239 return TRUE; 240} 241 242static void S3FreeRec(ScrnInfoPtr pScrn) 243{ 244 if (!pScrn->driverPrivate) 245 return; 246 247 xfree(pScrn->driverPrivate); 248 pScrn->driverPrivate = NULL; 249} 250 251static const OptionInfoRec * S3AvailableOptions(int chipid, int busid) 252{ 253 return S3Options; 254} 255 256static void S3Identify(int flags) 257{ 258 xf86PrintChipsets("S3", "driver (version " DRIVER_VERSION " for S3 chipset", 259 S3Chipsets); 260} 261 262static Bool S3Probe(DriverPtr drv, int flags) 263{ 264 GDevPtr *devSections; 265 int i, *usedChips, numDevSections, numUsed; 266 Bool foundScreen = FALSE; 267 268 /* sanity check */ 269 if ((numDevSections = xf86MatchDevice("s3", &devSections)) <= 0) 270 return FALSE; 271 272 /* XXX do ISA later... some day in the distant future... */ 273 numUsed = xf86MatchPciInstances("s3", PCI_VENDOR_S3, 274 S3Chipsets, S3PciChipsets, 275 devSections, numDevSections, 276 drv, &usedChips); 277 278 xfree(devSections); 279 280 if (numUsed <= 0) 281 return FALSE; 282 283 if (flags & PROBE_DETECT) 284 foundScreen = TRUE; 285 else for (i=0; i<numUsed; i++) { 286 ScrnInfoPtr pScrn = NULL; 287 pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], S3PciChipsets, 288 NULL, NULL, NULL, NULL, NULL); 289 290 pScrn->driverVersion = VERSION_MAJOR; 291 pScrn->driverName = DRIVER_NAME; 292 pScrn->name = "s3"; 293 pScrn->Probe = S3Probe; 294 pScrn->PreInit = S3PreInit; 295 pScrn->ScreenInit = S3ScreenInit; 296 pScrn->SwitchMode = S3SwitchMode; 297 pScrn->AdjustFrame = S3AdjustFrame; 298 pScrn->EnterVT = S3EnterVT; 299 pScrn->LeaveVT = S3LeaveVT; 300 pScrn->FreeScreen = S3FreeScreen; 301 302 foundScreen = TRUE; 303 } 304 305 xfree(usedChips); 306 307 return foundScreen; 308} 309 310static Bool S3PreInit(ScrnInfoPtr pScrn, int flags) 311{ 312 EntityInfoPtr pEnt; 313 S3Ptr pS3; 314 vgaHWPtr hwp; 315 ClockRangePtr clockRanges; 316 rgb zeros = {0, 0, 0}; 317 Gamma gzeros = {0.0, 0.0, 0.0}; 318 int i, vgaCRIndex, vgaCRReg; 319 unsigned char tmp; 320 char *s; 321 322 if (flags & PROBE_DETECT) 323 return FALSE; 324 325 if (!xf86LoadSubModule(pScrn, "vgahw")) 326 return FALSE; 327 328 if (!vgaHWGetHWRec(pScrn)) 329 return FALSE; 330 331 hwp = VGAHWPTR(pScrn); 332 vgaHWGetIOBase(hwp); 333 334 pScrn->monitor = pScrn->confScreen->monitor; 335 336 if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb)) 337 return FALSE; 338 339 switch (pScrn->depth) { 340 case 8: 341 case 15: 342 case 16: 343 case 24: 344 /* OK */ 345 break; 346 default: 347 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 348 "Given depth (%d) is not supported by this driver\n", 349 pScrn->depth); 350 return FALSE; 351 } 352 353 xf86PrintDepthBpp(pScrn); 354 355 if (pScrn->depth > 8) { 356 if (!xf86SetWeight(pScrn, zeros, zeros)) 357 return FALSE; 358 } 359 360 if (!xf86SetDefaultVisual(pScrn, -1)) 361 return FALSE; 362 363 pScrn->progClock = TRUE; 364 365 if (!S3GetRec(pScrn)) 366 return FALSE; 367 368 pS3 = S3PTR(pScrn); 369 370 pS3->s3Bpp = (pScrn->bitsPerPixel >> 3); 371 372 xf86CollectOptions(pScrn, NULL); 373 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, S3Options); 374 375 pS3->XVideo = xf86ReturnOptValBool(S3Options, OPTION_XVIDEO, TRUE); 376 pS3->NoAccel = xf86ReturnOptValBool(S3Options, OPTION_NOACCEL, FALSE); 377 pS3->HWCursor = xf86ReturnOptValBool(S3Options, OPTION_HWCURS, FALSE); 378 pS3->SlowDRAMRefresh = xf86ReturnOptValBool(S3Options, OPTION_SLOW_DRAM_REFRESH, FALSE); 379 pS3->SlowDRAM = xf86ReturnOptValBool(S3Options, OPTION_SLOW_DRAM, FALSE); 380 pS3->SlowEDODRAM = xf86ReturnOptValBool(S3Options, OPTION_SLOW_EDODRAM, FALSE); 381 pS3->SlowVRAM = xf86ReturnOptValBool(S3Options, OPTION_SLOW_VRAM, FALSE); 382 383 384 385 if (xf86GetOptValBool(S3Options, OPTION_SHADOW_FB, &pS3->shadowFB)) 386 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowFB %s.\n", 387 pS3->shadowFB ? "enabled" : "disabled"); 388 389 pS3->rotate = 0; 390 if ((s = xf86GetOptValString(S3Options, OPTION_ROTATE))) { 391 if(!xf86NameCmp(s, "CW")) { 392 /* accel is disabled below for shadowFB */ 393 pS3->shadowFB = TRUE; 394 pS3->rotate = 1; 395 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 396 "Rotating screen clockwise - acceleration disabled\n"); 397 } else if(!xf86NameCmp(s, "CCW")) { 398 pS3->shadowFB = TRUE; 399 pS3->rotate = -1; 400 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen" 401 "counter clockwise - acceleration disabled\n"); 402 } else { 403 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid" 404 "value for Option \"Rotate\"\n", s); 405 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 406 "Valid options are \"CW\" or \"CCW\"\n"); 407 } 408 } 409 410 if(pS3->shadowFB && !pS3->NoAccel) { 411 pS3->NoAccel = TRUE; 412 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 413 "HW acceleration not supported with \"shadowFB\".\n"); 414 } 415 416 417 if (pS3->rotate && pS3->HWCursor) { 418 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 419 "HW cursor not supported with \"rotate\".\n"); 420 pS3->HWCursor = FALSE; 421 } 422 423 424 if (pScrn->numEntities > 1) { 425 S3FreeRec(pScrn); 426 return FALSE; 427 } 428 429 pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 430#ifndef XSERVER_LIBPCIACCESS 431 if (pEnt->resources) { 432 xfree(pEnt); 433 S3FreeRec(pScrn); 434 return FALSE; 435 } 436#endif 437 438 if (xf86LoadSubModule(pScrn, "int10")) { 439 pS3->pInt10 = xf86InitInt10(pEnt->index); 440 } 441 442 if (xf86LoadSubModule(pScrn, "vbe")) { 443 pS3->pVBE = VBEInit(pS3->pInt10, pEnt->index); 444 } 445 446 if (pS3->shadowFB) { 447 if (!xf86LoadSubModule(pScrn, "shadowfb")) { 448 S3FreeRec(pScrn); 449 return FALSE; 450 } 451 } 452 453 if (!xf86SetGamma(pScrn, gzeros)) 454 return FALSE; 455 456 pS3->PciInfo = xf86GetPciInfoForEntity(pEnt->index); 457#ifndef XSERVER_LIBPCIACCESS 458 /* don't disable PIO funcs */ 459 xf86SetOperatingState(resVgaMemShared, pEnt->index, ResDisableOpr); 460#endif 461 if (pEnt->device->chipset && *pEnt->device->chipset) { 462 pScrn->chipset = pEnt->device->chipset; 463 pS3->Chipset = xf86StringToToken(S3Chipsets, pScrn->chipset); 464 } else if (pEnt->device->chipID >= 0) { 465 pS3->Chipset = pEnt->device->chipID; 466 pScrn->chipset = (char *)xf86TokenToString(S3Chipsets, 467 pS3->Chipset); 468 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 469 "ChipID override: 0x%04X\n", pS3->Chipset); 470 } else { 471 pS3->Chipset = PCI_DEV_DEVICE_ID(pS3->PciInfo); 472 pScrn->chipset = (char *)xf86TokenToString(S3Chipsets, 473 pS3->Chipset); 474 } 475 if (pEnt->device->chipRev >= 0) { 476 pS3->ChipRev = pEnt->device->chipRev; 477 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 478 pS3->ChipRev); 479 } else 480 pS3->ChipRev = PCI_DEV_REVISION(pS3->PciInfo); 481 482 xfree(pEnt); 483 484 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Chipset: \"%s\"\n", 485 pScrn->chipset); 486 487#ifndef XSERVER_LIBPCIACCESS 488 pS3->PciTag = pciTag(pS3->PciInfo->bus, pS3->PciInfo->device, 489 pS3->PciInfo->func); 490#endif 491 492 switch (pS3->Chipset) { 493 case PCI_CHIP_864_0: 494 case PCI_CHIP_864_1: 495 case PCI_CHIP_964_0: 496 case PCI_CHIP_964_1: 497 case PCI_CHIP_TRIO: 498 if (pS3->ChipRev >= 0x40) { /* S3 Trio64V+ has the New MMIO */ 499 pS3->S3NewMMIO = TRUE; 500 break; 501 } 502 case PCI_CHIP_AURORA64VP: /* ??? */ 503 pS3->S3NewMMIO = FALSE; 504 break; 505 case PCI_CHIP_TRIO64V2_DXGX: 506 case PCI_CHIP_TRIO64UVP: 507 case PCI_CHIP_968: 508 pS3->S3NewMMIO = TRUE; 509 break; 510 } 511 512 /* TODO: Streams Processor and Xv for Old MMIO */ 513 514 if (((pS3->Chipset == PCI_CHIP_AURORA64VP) || 515 (pS3->Chipset == PCI_CHIP_TRIO64UVP) || 516 (pS3->Chipset == PCI_CHIP_TRIO64V2_DXGX) || 517 ((pS3->Chipset == PCI_CHIP_TRIO) && (pS3->ChipRev >= 0x40))) 518 && (pS3->S3NewMMIO)) 519 pS3->hasStreams = TRUE; 520 else 521 pS3->hasStreams = FALSE; 522 523 pS3->FBAddress = PCI_REGION_BASE(pS3->PciInfo, 0, REGION_MEM); 524 pScrn->memPhysBase = pS3->FBAddress; 525 pScrn->fbOffset = 0; 526 527 if (pS3->S3NewMMIO) 528 pS3->IOAddress = pS3->FBAddress + S3_NEWMMIO_REGBASE; 529 530 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Framebuffer @ 0x%lx\n", 531 pS3->FBAddress); 532 if (pS3->S3NewMMIO) 533 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "MMIO @ 0x%lx\n", 534 pS3->IOAddress); 535 536 pS3->PCIRetry = FALSE; /* not supported yet */ 537 538 pS3->vgaCRIndex = vgaCRIndex = hwp->IOBase + 4; 539 pS3->vgaCRReg = vgaCRReg = hwp->IOBase + 5; 540 541 /* unlock sys regs */ 542 outb(vgaCRIndex, 0x38); 543 outb(vgaCRReg, 0x48); 544 outb(vgaCRIndex, 0x39); 545 outb(vgaCRReg, 0xa5); 546 547 outb(vgaCRIndex, 0x40); 548 tmp = inb(vgaCRReg) | 0x01; 549 outb(vgaCRReg, tmp); 550 outb(vgaCRIndex, 0x35); 551 tmp = inb(vgaCRReg) & ~0x30; 552 outb(vgaCRReg, tmp); 553 554 outb(0x3c4, 0x08); 555 outb(0x3c5, 0x06); 556 outb(vgaCRIndex, 0x33); 557 tmp = (inb(vgaCRReg) & ~(0x2 | 0x10 | 0x40)) | 0x20; 558 outb(vgaCRReg, tmp); 559 560 /* unprotect CRTC[0-7] */ 561 outb(vgaCRIndex, 0x11); 562 tmp = inb(vgaCRReg) & 0x7f; 563 outb(vgaCRReg, tmp); 564 565 /* wake up */ 566 outb(0x46e8, 0x10); 567 outb(0x102, 0x01); 568 outb(0x46e8, 0x08); 569 570 if (pS3->Chipset == PCI_CHIP_TRIO64V2_DXGX) 571 { 572 /* disable DAC power saving to avoid bright left edge */ 573 outb (0x3d4, 0x86); 574 outb (0x3d5, 0x80); 575 /* disable the stream display fetch length control */ 576 outb (0x3d4, 0x90); 577 outb (0x3d5, 0x00); 578 } 579 580 if (!pScrn->videoRam) { 581 /* probe videoram */ 582 outb(vgaCRIndex, 0x36); 583 tmp = inb(vgaCRReg); 584 585 switch ((tmp & 0xe0) >> 5) { 586 case 0: 587 pScrn->videoRam = 4096; 588 break; 589 case 2: 590 pScrn->videoRam = 3072; 591 break; 592 case 3: 593 pScrn->videoRam = 8192; 594 break; 595 case 4: 596 pScrn->videoRam = 2048; 597 break; 598 case 5: 599 pScrn->videoRam = 6144; 600 break; 601 case 6: 602 pScrn->videoRam = 1024; 603 break; 604 } 605 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 606 "videoRam = %d Kb\n", pScrn->videoRam); 607 } else { 608 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 609 "videoRam = %d Kb\n", pScrn->videoRam); 610 } 611 612 if (!xf86LoadSubModule(pScrn, "ramdac")) 613 return FALSE; 614 615 pScrn->rgbBits = 8; /* set default */ 616 617 /* probe for dac */ 618 if (S3GENDACProbe(pScrn)) { 619 pS3->DacPreInit = S3GENDAC_PreInit; 620 pS3->DacSave = S3GENDAC_Save; 621 pS3->DacRestore = S3GENDAC_Restore; 622 if (pS3->RamDac->RamDacType == GENDAC_RAMDAC) { 623 pS3->DacInit = S3GENDAC_Init; 624 switch(pScrn->bitsPerPixel) { 625 case 8: 626#if 0 627 pS3->MaxClock = 110000; 628#else 629 pS3->MaxClock = 95000; 630#endif 631 break; 632 case 16: 633 pS3->MaxClock = 55000; 634 break; 635 case 24: 636 case 32: 637 pS3->MaxClock = 27500; 638 break; 639 } 640 } else { /* SDAC */ 641 pS3->DacInit = S3SDAC_Init; 642 switch(pScrn->bitsPerPixel) { 643 case 8: 644 pS3->MaxClock = 135000; 645 break; 646 case 16: 647#if 0 648 pS3->MaxClock = 110000; 649#else 650 pS3->MaxClock = 95000; 651#endif 652 break; 653 case 24: 654 case 32: 655#if 0 656 pS3->MaxClock = 55000; 657#else 658 pS3->MaxClock = 50000; 659#endif 660 break; 661 } 662 } 663 pScrn->rgbBits = 6; 664 pS3->LoadPalette = S3GenericLoadPalette; 665 } 666 if (S3TiDACProbe(pScrn)) { 667 pS3->DacPreInit = S3TiDAC_PreInit; 668 pS3->DacInit = S3TiDAC_Init; 669 pS3->DacSave = S3TiDAC_Save; 670 pS3->DacRestore = S3TiDAC_Restore; 671#if 0 672 /* FIXME, cursor is drawn in wrong position */ 673 pS3->CursorInit = S3Ti_CursorInit; 674#endif 675 pS3->MaxClock = 135000; 676 pScrn->rgbBits = 8; 677 if (pScrn->bitsPerPixel > 8) 678 pS3->LoadPalette = S3TiLoadPalette; 679 else 680 pS3->LoadPalette = S3GenericLoadPalette; 681 } 682 if (S3ProbeIBMramdac(pScrn)) { 683 pS3->DacPreInit = S3IBMRGB_PreInit; 684 pS3->DacInit = S3IBMRGB_Init; 685 pS3->DacSave = S3IBMRGB_Save; 686 pS3->DacRestore = S3IBMRGB_Restore; 687 pS3->CursorInit = S3IBMRGB_CursorInit; 688 pS3->RamDac->SetBpp = IBMramdac526SetBppWeak(); 689 pS3->MaxClock = 170000; 690 pScrn->rgbBits = 8; 691 pS3->LoadPalette = S3GenericLoadPalette; 692 } 693 if (S3Trio64DACProbe(pScrn)) { 694 pS3->DacPreInit = S3Trio64DAC_PreInit; 695 pS3->DacInit = S3Trio64DAC_Init; 696 pS3->DacSave = S3Trio64DAC_Save; 697 pS3->DacRestore = S3Trio64DAC_Restore; 698#if 0 699 pS3->CursorInit = S3_CursorInit; /* FIXME broken */ 700#endif 701 switch(pScrn->bitsPerPixel) { 702 case 8: 703 if (pS3->Chipset == PCI_CHIP_TRIO64V2_DXGX) 704 pS3->MaxClock = 170000; 705 else 706 pS3->MaxClock = 135000; 707 708 pScrn->rgbBits = 6; 709 break; 710 case 16: 711 pS3->MaxClock = 80000; 712 pScrn->rgbBits = 6; 713 break; 714 case 24: 715 case 32: 716 if (pS3->Chipset == PCI_CHIP_TRIO64V2_DXGX) 717 pS3->MaxClock = 56700; 718 else 719 pS3->MaxClock = 50000; 720 721 pScrn->rgbBits = 8; 722 break; 723 } 724 725 pS3->LoadPalette = S3GenericLoadPalette; 726 } 727 728 if (pS3->RamDac == NULL) { 729 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 730 "Ramdac probe failed\n"); 731 return FALSE; 732 } 733 734 if (!pS3->HWCursor) 735 pS3->CursorInit = NULL; 736 737 pS3->RefClock = S3GetRefClock(pScrn); 738 739 if (pS3->DacPreInit) 740 pS3->DacPreInit(pScrn); 741 742 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "RefClock: %d\n", 743 pS3->RefClock); 744 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Max pixel clock at this depth is %d Mhz\n", 745 pS3->MaxClock / 1000); 746 747 clockRanges = xnfcalloc(sizeof(ClockRange), 1); 748 clockRanges->next = NULL; 749 clockRanges->minClock = 15600; 750 clockRanges->maxClock = pS3->MaxClock; 751 clockRanges->clockIndex = -1; 752 clockRanges->interlaceAllowed = TRUE; /* not yet */ 753 clockRanges->doubleScanAllowed = TRUE; /* not yet */ 754 755 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 756 pScrn->display->modes, clockRanges, 757 pS3->NoAccel ? NULL : s3AccelLinePitches, 758 256, 2048, 759 pScrn->bitsPerPixel, 128, 2048, 760 pScrn->display->virtualX, 761 pScrn->display->virtualY, pScrn->videoRam * 1024, 762 LOOKUP_BEST_REFRESH); 763 764 if (i == -1) { 765 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "no valid modes left\n"); 766 S3FreeRec(pScrn); 767 return FALSE; 768 } 769 770 xf86PruneDriverModes(pScrn); 771 772 if (i == 0 || pScrn->modes == NULL) { 773 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "no valid modes found\n"); 774 S3FreeRec(pScrn); 775 return FALSE; 776 } 777 778 xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 779 pScrn->currentMode = pScrn->modes; 780 xf86PrintModes(pScrn); 781 xf86SetDpi(pScrn, 0, 0); 782 783 xf86LoadSubModule(pScrn, "fb"); 784 785 if (!xf86LoadSubModule(pScrn, "xaa")) 786 return FALSE; 787 788 return TRUE; 789} 790 791 792static Bool S3ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, 793 char **argv) 794{ 795 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 796 S3Ptr pS3 = S3PTR(pScrn); 797 BoxRec ScreenArea; 798 int width, height, displayWidth; 799 800 if (pS3->rotate) { 801 height = pScrn->virtualX; 802 width = pScrn->virtualY; 803 } else { 804 width = pScrn->virtualX; 805 height = pScrn->virtualY; 806 } 807 808 809 pScrn->fbOffset = 0; 810 811 if (!S3MapMem(pScrn)) { 812 S3FreeRec(pScrn); 813 return FALSE; 814 } 815 816 S3Save(pScrn); 817 818 vgaHWBlankScreen(pScrn, TRUE); 819 820 if (!S3ModeInit(pScrn, pScrn->currentMode)) 821 return FALSE; 822#if 0 823 S3Regdump(pScrn); 824#endif 825 pScrn->vtSema = TRUE; 826 827 S3SaveScreen(pScreen, SCREEN_SAVER_ON); 828 829 miClearVisualTypes(); 830 if (pScrn->bitsPerPixel > 8) { 831 if (!miSetVisualTypes(pScrn->depth, TrueColorMask, 832 pScrn->rgbBits, pScrn->defaultVisual)) 833 return FALSE; 834 } else { 835 if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth), 836 pScrn->rgbBits, pScrn->defaultVisual)) 837 return FALSE; 838 } 839 840 miSetPixmapDepths (); 841 842 /* no screen rotation assumed */ 843 if(pS3->shadowFB) { 844 pS3->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); 845 pS3->ShadowPtr = xalloc(pS3->ShadowPitch * height); 846 displayWidth = pS3->ShadowPitch / (pScrn->bitsPerPixel >> 3); 847 } else { 848 pS3->ShadowPtr = NULL; 849 displayWidth = pScrn->displayWidth; 850 } 851 852 if (!fbScreenInit(pScreen, (pS3->shadowFB ? pS3->ShadowPtr : pS3->FBBase), 853 pScrn->virtualX, 854 pScrn->virtualY, pScrn->xDpi, pScrn->yDpi, 855 pScrn->displayWidth, pScrn->bitsPerPixel)) 856 return FALSE; 857 858 xf86SetBlackWhitePixels(pScreen); 859 860 if (pScrn->bitsPerPixel > 8) { 861 VisualPtr pVis; 862 863 pVis = pScreen->visuals + pScreen->numVisuals; 864 while (--pVis >= pScreen->visuals) { 865 if ((pVis->class | DynamicClass) == DirectColor) { 866 pVis->offsetRed = pScrn->offset.red; 867 pVis->offsetGreen = pScrn->offset.green; 868 pVis->offsetBlue = pScrn->offset.blue; 869 pVis->redMask = pScrn->mask.red; 870 pVis->greenMask = pScrn->mask.green; 871 pVis->blueMask = pScrn->mask.blue; 872 } 873 } 874 } 875 fbPictureInit (pScreen, 0, 0); 876 S3DGAInit(pScreen); 877 878 miInitializeBackingStore(pScreen); 879 xf86SetBackingStore(pScreen); 880 881 /* framebuffer manager setup */ 882 ScreenArea.x1 = 0; 883 ScreenArea.y1 = 0; 884 ScreenArea.x2 = pScrn->displayWidth; 885 ScreenArea.y2 = (pScrn->videoRam * 1024) / pS3->s3BppDisplayWidth; 886 887 if (!xf86InitFBManager(pScreen, &ScreenArea)) { 888 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 889 "Memory manager initialization to (%d,%d) (%d,%d) failed\n", 890 ScreenArea.x1, ScreenArea.y1, 891 ScreenArea.x2, ScreenArea.y2); 892 return FALSE; 893 } else 894 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 895 "Memory manager initialized to (%d,%d) (%d,%d)\n", 896 ScreenArea.x1, ScreenArea.y1, 897 ScreenArea.x2, ScreenArea.y2); 898 899 /* 2D acceleration setup */ 900 901 if (pS3->NoAccel) 902 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 903 "Acceleration disabled (by option)\n"); 904 905 /* It seems that acceleration isn't supported for 24-bit packed 906 colour. So disable it. Using shadowFB is recommended in this mode. */ 907 if (!pS3->NoAccel && (pScrn->bitsPerPixel == 24)) { 908 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "HW acceleration isn't supported for 24 bpp. Disabled.\n"); 909 pS3->NoAccel = TRUE; 910 } 911 912 913 if (!pS3->NoAccel) { 914 if (pS3->S3NewMMIO) 915 if (S3AccelInitNewMMIO(pScreen)) { 916 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 917 "Acceleration enabled\n"); 918 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 919 "Using NewMMIO\n"); 920 } else { 921 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 922 "Acceleration initialization failed\n"); 923 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 924 "Acceleration disabled\n"); 925 } 926 else { 927 if (S3AccelInitPIO(pScreen)) { 928 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 929 "Acceleration enabled\n"); 930 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 931 "Using PIO\n"); 932 } else { 933 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 934 "Acceleration initialization failed\n"); 935 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 936 "Acceleration disabled\n"); 937 } 938 } 939 } 940 941 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 942 943 /* HW cursor setup */ 944 945 if (pS3->CursorInit) { 946 if (pS3->CursorInit(pScreen)) 947 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using HW cursor\n"); 948 else { 949 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "HW cursor initialization failed\n"); 950 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using SW cursor\n"); 951 } 952 } else 953 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using SW cursor\n"); 954 955 956 /* Shadow framebuffer setup */ 957 958 if (pS3->shadowFB) { 959 RefreshAreaFuncPtr refreshArea = S3RefreshArea; 960 961 if (pS3->rotate) { 962 if (!pS3->PointerMoved) { 963 pS3->PointerMoved = pScrn->PointerMoved; 964 pScrn->PointerMoved = S3PointerMoved; 965 } 966 967 switch (pScrn->bitsPerPixel) { 968 case 8: refreshArea = S3RefreshArea8; break; 969 case 16: refreshArea = S3RefreshArea16; break; 970 case 24: refreshArea = S3RefreshArea24; break; 971 case 32: refreshArea = S3RefreshArea32; break; 972 } 973 } 974 975 ShadowFBInit(pScreen, refreshArea); 976 } 977 978 979 980 if (!miCreateDefColormap(pScreen)) 981 return FALSE; 982 983 if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, 984 pS3->LoadPalette, NULL, 985 CMAP_RELOAD_ON_MODE_SWITCH)) 986 return FALSE; 987 988 vgaHWBlankScreen(pScrn, FALSE); 989 990 pScreen->SaveScreen = S3SaveScreen; 991 pS3->CloseScreen = pScreen->CloseScreen; 992 pScreen->CloseScreen = S3CloseScreen; 993 994 xf86DPMSInit(pScreen, S3DisplayPowerManagementSet, 0); 995 996#ifndef XSERVER_LIBPCIACCESS 997 /* XXX Check if I/O and Mem flags need to be the same. */ 998 pScrn->racIoFlags = pScrn->racMemFlags = RAC_COLORMAP 999 | RAC_FB | RAC_VIEWPORT | RAC_CURSOR; 1000#endif 1001 1002 if (pS3->SlowEDODRAM) 1003 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1004 "SlowEDODRAM: Setting 2-cycle EDO\n"); 1005 1006 if (pS3->SlowVRAM) 1007 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1008 "SlowVRAM: -RAS low time is 4.5 MCLKs\n"); 1009 1010 if (pS3->SlowDRAM) 1011 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1012 "SlowDRAM: -RAS precharge time is 3.5 MCLKs\n"); 1013 1014 if (pS3->SlowDRAMRefresh) 1015 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1016 "SlowDRAMRefresh: three refresh cycles per scanline\n"); 1017 1018 /* XVideo setup */ 1019 1020 if (pS3->XVideo) { 1021 if (!pS3->hasStreams) { 1022 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Overlay video isn't supported by video hardware. Disabled.\n"); 1023 pS3->XVideo = FALSE; 1024 } else if (pScrn->bitsPerPixel < 16) { 1025 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Overlay video isn't supported for %d bpp. Disabled.\n", pScrn->bitsPerPixel); 1026 pS3->XVideo = FALSE; 1027 } 1028 } else 1029 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1030 "Overlay video disabled by option\n"); 1031 1032 /* At present time we support XV only for chips with New MMIO */ 1033 if ((pS3->XVideo) && (pS3->S3NewMMIO)) 1034 S3InitVideo(pScreen); 1035 1036 switch (pScrn->bitsPerPixel) { 1037 case 8: 1038 pS3->Streams_FIFO = FIFO_PS16_SS8; 1039 break; 1040 case 15: 1041 case 16: 1042 pS3->Streams_FIFO = FIFO_PS12_SS12; 1043 break; 1044 case 24: 1045 case 32: 1046 pS3->Streams_FIFO = FIFO_PS8_SS16; 1047 break; 1048 } 1049 1050 return TRUE; 1051} 1052 1053 1054 1055 1056static void S3Save(ScrnInfoPtr pScrn) 1057{ 1058 S3Ptr pS3 = S3PTR(pScrn); 1059 S3RegPtr save = &pS3->SavedRegs; 1060 vgaHWPtr hwp = VGAHWPTR(pScrn); 1061 vgaRegPtr pVga = &hwp->SavedReg; 1062 int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; 1063 int i; 1064 unsigned char cr5c = 0; 1065 1066 S3BankZero(pScrn); 1067 1068 save->clock = inb(0x3cc); 1069 1070 vgaHWSave(pScrn, pVga, VGA_SR_ALL); 1071 1072 if (pS3->RamDac->RamDacType == TI3025_RAMDAC) { 1073 outb(vgaCRIndex, 0x5c); 1074 cr5c = inb(vgaCRReg); 1075 } 1076 1077 pS3->DacSave(pScrn); 1078 1079 for(i=0; i<5; i++) { 1080 outb(vgaCRIndex, 0x30 + i); 1081 save->s3save[i] = inb(vgaCRReg); 1082 outb(vgaCRIndex, 0x38 + i); 1083 save->s3save[5 + i] = inb(vgaCRReg); 1084 } 1085 1086 for (i=0; i<16; i++) { 1087 outb(vgaCRIndex, 0x40 + i); 1088 save->s3syssave[i] = inb(vgaCRReg); 1089 } 1090 1091 outb(vgaCRIndex, 0x45); 1092 inb(vgaCRReg); 1093 outb(vgaCRIndex, 0x4a); 1094 for(i=0; i<4; i++) { 1095 save->color_stack[i] = inb(vgaCRReg); 1096 outb(vgaCRReg, save->color_stack[i]); 1097 } 1098 1099 outb(vgaCRIndex, 0x45); 1100 inb(vgaCRReg); 1101 outb(vgaCRIndex, 0x4b); 1102 for(i=4; i<8; i++) { 1103 save->color_stack[i] = inb(vgaCRReg); 1104 outb(vgaCRReg, save->color_stack[i]); 1105 } 1106 1107 for(i=0; i<16; i++) { 1108 for (i=0; i<16; i++) { 1109 if (!((1 << i) & 0x673b)) 1110 continue; 1111 outb(vgaCRIndex, 0x50 + i); 1112 save->s3syssave[i + 16] = inb(vgaCRReg); 1113 } 1114 } 1115 1116 if (pS3->RamDac->RamDacType == TI3025_RAMDAC) 1117 save->s3syssave[0x0c + 16] = cr5c; 1118 1119 for(i=32; i<46; i++) { 1120 outb(vgaCRIndex, 0x40 + i); 1121 save->s3syssave[i] = inb(vgaCRReg); 1122 } 1123} 1124 1125 1126Bool S3SaveScreen(ScreenPtr pScreen, int mode) 1127{ 1128 return vgaHWSaveScreen(pScreen, mode); 1129} 1130 1131 1132static void S3FreeScreen(int scrnIndex, int flags) 1133{ 1134 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1135 1136 vgaHWFreeHWRec(pScrn); 1137 1138 S3FreeRec(pScrn); 1139} 1140 1141 1142Bool S3CloseScreen(int scrnIndex, ScreenPtr pScreen) 1143{ 1144 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1145 S3Ptr pS3 = S3PTR(pScrn); 1146 vgaHWPtr hwp = VGAHWPTR(pScrn); 1147 1148 if (pScrn->vtSema) { 1149 vgaHWUnlock(hwp); 1150 S3Restore(pScrn); 1151 vgaHWLock(hwp); 1152 S3UnmapMem(pScrn); 1153 } 1154 1155 if (pS3->DGAModes) 1156 xfree(pS3->DGAModes); 1157 pS3->DGAModes = NULL; 1158 1159 pScrn->vtSema = FALSE; 1160 pScreen->CloseScreen = pS3->CloseScreen; 1161 1162 return (*pScreen->CloseScreen)(scrnIndex, pScreen); 1163} 1164 1165 1166Bool S3SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) 1167{ 1168 return S3ModeInit(xf86Screens[scrnIndex], mode); 1169 1170} 1171 1172 1173static void S3GenericLoadPalette(ScrnInfoPtr pScrn, int numColors, 1174 int *indicies, LOCO *colors, 1175 VisualPtr pVisual) 1176{ 1177 int i, index; 1178 1179 for (i=0; i<numColors; i++) { 1180 index = indicies[i]; 1181 outb(0x3c8, index); 1182 outb(0x3c9, colors[index].red); 1183 outb(0x3c9, colors[index].green); 1184 outb(0x3c9, colors[index].blue); 1185 } 1186} 1187 1188 1189static Bool S3MapMem(ScrnInfoPtr pScrn) 1190{ 1191 S3Ptr pS3 = S3PTR(pScrn); 1192 1193 if (pS3->S3NewMMIO) { 1194 1195 1196#ifndef XSERVER_LIBPCIACCESS 1197 pS3->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 1198 pS3->PciTag, pS3->IOAddress, 1199 S3_NEWMMIO_REGSIZE); 1200#else 1201 { 1202 void** result = (void**)&pS3->MMIOBase; 1203 int err = pci_device_map_range(pS3->PciInfo, 1204 pS3->IOAddress, 1205 S3_NEWMMIO_REGSIZE, 1206 PCI_DEV_MAP_FLAG_WRITABLE, 1207 result); 1208 1209 if (err) 1210 return FALSE; 1211 } 1212#endif 1213 if (!pS3->MMIOBase) { 1214 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1215 "Could not map MMIO\n"); 1216 return FALSE; 1217 } 1218 } 1219 1220#ifndef XSERVER_LIBPCIACCESS 1221 pS3->FBBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 1222 pS3->PciTag, pS3->FBAddress, 1223 pScrn->videoRam * 1024); 1224 1225#else 1226 { 1227 void** result = (void**)&pS3->FBBase; 1228 int err = pci_device_map_range(pS3->PciInfo, 1229 pS3->FBAddress, 1230 pScrn->videoRam * 1024, 1231 PCI_DEV_MAP_FLAG_WRITABLE | 1232 PCI_DEV_MAP_FLAG_WRITE_COMBINE, 1233 result); 1234 1235 if (err) 1236 return FALSE; 1237 } 1238#endif 1239 if (!pS3->FBBase) { 1240 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1241 "Could not map framebuffer\n"); 1242 return FALSE; 1243 } 1244 1245 pS3->FBCursorOffset = pScrn->videoRam - 1; 1246 1247 return TRUE; 1248} 1249 1250 1251static void S3UnmapMem(ScrnInfoPtr pScrn) 1252{ 1253 S3Ptr pS3 = S3PTR(pScrn); 1254 1255 if (pS3->S3NewMMIO) { 1256#ifndef XSERVER_LIBPCIACCESS 1257 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pS3->MMIOBase, 1258 S3_NEWMMIO_REGSIZE); 1259#else 1260 pci_device_unmap_range(pS3->PciInfo, pS3->MMIOBase, S3_NEWMMIO_REGSIZE); 1261#endif 1262 } 1263 1264#ifndef XSERVER_LIBPCIACCESS 1265 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pS3->FBBase, 1266 pScrn->videoRam * 1024); 1267#else 1268 pci_device_unmap_range(pS3->PciInfo, pS3->FBBase, pScrn->videoRam * 1024); 1269#endif 1270 1271 return; 1272} 1273 1274 1275static int S3GetPixMuxShift(ScrnInfoPtr pScrn) 1276{ 1277 S3Ptr pS3 = S3PTR(pScrn); 1278 int shift = 0; 1279 1280 if (pS3->Chipset == PCI_CHIP_968) 1281 shift = 1; /* XXX IBMRGB */ 1282 else if (pS3->Chipset == PCI_CHIP_TRIO || 1283 pS3->Chipset == PCI_CHIP_TRIO64UVP || 1284 pS3->Chipset == PCI_CHIP_TRIO64V2_DXGX) { 1285 if (pS3->s3Bpp == 2) 1286 shift = -1; 1287 else 1288 shift = 0; 1289 } 1290 1291 return shift; 1292} 1293 1294static Bool S3ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 1295{ 1296 S3Ptr pS3 = S3PTR(pScrn); 1297 S3RegPtr new = &pS3->ModeRegs; 1298 vgaHWPtr hwp = VGAHWPTR(pScrn); 1299 vgaRegPtr pVga = &hwp->ModeReg; 1300 int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; 1301 int vgaIOBase = hwp->IOBase; 1302 int r, n, m; 1303 unsigned char tmp; 1304 1305 pS3->pixMuxShift = S3GetPixMuxShift(pScrn); 1306 1307 pS3->s3BppDisplayWidth = pScrn->displayWidth * pS3->s3Bpp; 1308 pS3->hwCursor = (mode->Flags & V_DBLSCAN) ? FALSE : TRUE; 1309 pS3->HDisplay = mode->HDisplay; 1310 1311 pS3->s3ScissB = ((pScrn->videoRam * 1024) / pS3->s3BppDisplayWidth) - 1; 1312 pS3->s3ScissR = pScrn->displayWidth - 1; 1313 1314 /* 1315 Set correct blanking for S3 Trio64V2. It's also needed 1316 to clear cr33_5. 1317 */ 1318 if (pS3->Chipset == PCI_CHIP_TRIO64V2_DXGX) 1319 mode->CrtcHBlankStart = mode->CrtcHDisplay + 8; 1320 1321 if ((mode->HTotal == mode->CrtcHTotal) && (pS3->pixMuxShift != 0)) { 1322 if (pS3->pixMuxShift > 0) { 1323 mode->CrtcHTotal >>= pS3->pixMuxShift; 1324 mode->CrtcHDisplay >>= pS3->pixMuxShift; 1325 mode->CrtcHBlankStart >>= pS3->pixMuxShift; 1326 mode->CrtcHBlankEnd >>= pS3->pixMuxShift; 1327 mode->CrtcHSyncStart >>= pS3->pixMuxShift; 1328 mode->CrtcHSyncEnd >>= pS3->pixMuxShift; 1329 mode->CrtcHSkew >>= pS3->pixMuxShift; 1330 } else if (pS3->pixMuxShift < 0) { 1331 mode->CrtcHTotal <<= -pS3->pixMuxShift; 1332 mode->CrtcHDisplay <<= -pS3->pixMuxShift; 1333 mode->CrtcHBlankStart <<= -pS3->pixMuxShift; 1334 mode->CrtcHBlankEnd <<= -pS3->pixMuxShift; 1335 mode->CrtcHSyncStart <<= -pS3->pixMuxShift; 1336 mode->CrtcHSyncEnd <<= -pS3->pixMuxShift; 1337 mode->CrtcHSkew <<= -pS3->pixMuxShift; 1338 } 1339 } 1340 1341 if (!vgaHWInit(pScrn, mode)) 1342 return FALSE; 1343 1344 1345 1346 pVga->MiscOutReg |= 0x0c; 1347 pVga->Sequencer[0] = 0x03; 1348 pVga->CRTC[19] = pS3->s3BppDisplayWidth >> 3; 1349 pVga->CRTC[23] = 0xe3; 1350 pVga->Attribute[0x11] = 0xff; 1351 1352 if (vgaIOBase == 0x3b0) 1353 pVga->MiscOutReg &= 0xfe; 1354 else 1355 pVga->MiscOutReg |= 0x01; 1356 1357 /* ok i give up also, i'm writing in here */ 1358 1359 vgaHWProtect(pScrn, TRUE); 1360 1361 1362 if (pS3->RamDac->RamDacType == TI3025_RAMDAC) { 1363 outb(vgaCRIndex, 0x5c); 1364 tmp = inb(vgaCRReg); 1365 outb(vgaCRReg, tmp & 0xdf); 1366 1367 S3OutTiIndReg(pScrn, TIDAC_ind_curs_ctrl, 0x7f, 0x00); 1368 } 1369 1370 pS3->DacInit(pScrn, mode); 1371 1372 outb(0x3c2, pVga->MiscOutReg); 1373 1374 for(r=1; r<5; r++) { 1375 outw(0x3c4, (pVga->Sequencer[r] << 8) | r); 1376 } 1377 1378 /* We need to set this first - S3 *is* broken */ 1379 outw(vgaCRIndex, (pVga->CRTC[17] << 8) | 17); 1380 for(r=0; r<25; r++) 1381 outw(vgaCRIndex, (pVga->CRTC[r] << 8) | r); 1382 1383 for(r=0; r<9; r++) 1384 outw(0x3ce, (pVga->Graphics[r] << 8) | r); 1385 1386 inb(vgaIOBase + 0x0a); 1387 1388 for(r=0; r<16; r++) { 1389 outb(0x3c0, r); 1390 outb(0x3c0, pVga->Attribute[r]); 1391 } 1392 for(r=16; r<21; r++) { 1393 outb(0x3c0, r | 0x20); 1394 outb(0x3c0, pVga->Attribute[r]); 1395 } 1396 1397 1398 new->cr31 = 0x8d; 1399 outb(vgaCRIndex, 0x31); 1400 outb(vgaCRReg, new->cr31); 1401 1402 new->cr32 = 0x00; 1403 outb(vgaCRIndex, 0x32); 1404 outb(vgaCRReg, new->cr32); 1405 1406 outb(vgaCRIndex, 0x33); 1407 new->cr33 = inb(vgaCRReg) | 0x20; 1408 if (S3_864_SERIES () || 1409 S3_964_SERIES()) 1410 new->cr33 = 0x20; 1411 else if (pS3->Chipset == PCI_CHIP_TRIO64V2_DXGX) 1412 new->cr33 &= ~0x20; 1413 outb(vgaCRReg, new->cr33); 1414 1415 new->cr34 = 0x10; 1416 outb(vgaCRIndex, 0x34); 1417 outb(vgaCRReg, new->cr34); 1418 1419 if (pS3->Chipset != PCI_CHIP_AURORA64VP) { 1420 new->cr3b = (pVga->CRTC[0] + pVga->CRTC[4] + 1) / 2; 1421 outb(vgaCRIndex, 0x3b); 1422 outb(vgaCRReg, new->cr3b); 1423 } 1424 1425 new->cr3c = pVga->CRTC[0] / 2; 1426 outb(vgaCRIndex, 0x3c); 1427 outb(vgaCRReg, new->cr3c); 1428 1429 outb(vgaCRIndex, 0x40); 1430 tmp = inb(vgaCRReg); 1431 new->cr40 = (tmp & 0xf2) | 0x05; 1432 outb(vgaCRReg, new->cr40); 1433 1434 outb(vgaCRIndex, 0x43); 1435 switch (pScrn->bitsPerPixel) { 1436 case 24: 1437 case 32: 1438 if (S3_864_SERIES()) 1439 new->cr43 = 0x08; 1440 else 1441 new->cr43 = inb(vgaCRReg); 1442 break; 1443 case 15: 1444 case 16: 1445 if ((pS3->RamDac->RamDacType == IBM524_RAMDAC) || 1446 (pS3->RamDac->RamDacType == IBM524A_RAMDAC) || 1447 (pS3->RamDac->RamDacType == TI3025_RAMDAC)) 1448 new->cr43 = 0x10; 1449 else if (pS3->RamDac->RamDacType == TRIO64_RAMDAC) 1450 new->cr43 = 0x09; 1451 else if (pS3->RamDac->RamDacType == GENDAC_RAMDAC) 1452 new->cr43 = 0x80; 1453 else if (S3_864_SERIES()) 1454 new->cr43 = 0x08; 1455 break; 1456 case 8: 1457 default: 1458 new->cr43 = 0x00; 1459 break; 1460 } 1461 outb(vgaCRReg, new->cr43); 1462 1463 new->cr44 = 0x00; 1464 outb(vgaCRIndex, 0x44); 1465 outb(vgaCRReg, new->cr44); 1466 1467 outb(vgaCRIndex, 0x45); 1468 new->cr45 = inb(vgaCRReg) & 0xf2; 1469 outb(vgaCRReg, new->cr45); 1470 1471 outb(vgaCRIndex, 0x50); 1472 tmp = inb(vgaCRReg) & ~0xf1; 1473 switch (pScrn->bitsPerPixel) { 1474 case 8: 1475 break; 1476 case 16: 1477 tmp |= 0x10; 1478 break; 1479 case 24: 1480 tmp |= 0x20; /* there is no such value in spec s3.txt */ 1481 break; 1482 case 32: 1483 tmp |= 0x30; 1484 break; 1485 } 1486 1487 switch (pScrn->displayWidth) { 1488 case 640: 1489 tmp |= 0x40; 1490 break; 1491 case 800: 1492 tmp |= 0x80; 1493 break; 1494 case 1152: 1495 tmp |= 0x01; 1496 break; 1497 case 1280: 1498 tmp |= 0xc0; 1499 break; 1500 case 1600: 1501 tmp |= 0x81; 1502 break; 1503 } 1504 new->cr50 = tmp; 1505 outb(vgaCRReg, new->cr50); 1506 1507 1508 outb(vgaCRIndex, 0x51); 1509 new->cr51 = (inb(vgaCRReg) & 0xc0) | 1510 ((pS3->s3BppDisplayWidth >> 7) & 0x30); 1511 outb(vgaCRReg, new->cr51); 1512 1513 outb(vgaCRIndex, 0x53); 1514 new->cr53 = inb(vgaCRReg); 1515 if (pS3->S3NewMMIO) 1516 new->cr53 |= 0x18; 1517 else 1518 new->cr53 &= ~0x18; 1519 outb(vgaCRReg, new->cr53); 1520 1521 n = 255; 1522 outb(vgaCRIndex, 0x54); 1523 { 1524 int clock2, mclk; 1525 1526 clock2 = mode->Clock * pS3->s3Bpp; 1527 if (pScrn->videoRam < 2048) 1528 clock2 *= 2; 1529 mclk = pS3->mclk; 1530 m = (int)((mclk/1000.0*.72+16.867)*89.736/(clock2/1000.0+39)-21.1543); 1531 if (pScrn->videoRam < 2048) 1532 m /= 2; 1533 if (m >31) 1534 m = 31; 1535 else if (m < 0) { 1536 m = 0; 1537 n = 16; 1538 } 1539 } 1540 new->cr54 = m << 3; 1541 outb(vgaCRReg, new->cr54); 1542 1543 if (n < 0) 1544 n = 0; 1545 else if (n > 255) 1546 n = 255; 1547 outb(vgaCRIndex, 0x60); 1548 new->cr60 = n; 1549 outb(vgaCRReg, new->cr60); 1550 1551 if (pS3->hasStreams) { 1552 new->cr60 = 255; 1553 outb(vgaCRIndex, 0x60); 1554 outb(vgaCRReg, new->cr60); 1555 1556 new->cr54 = 31 << 3; 1557 outb(vgaCRIndex, 0x54); 1558 outb(vgaCRReg, new->cr54); 1559 } 1560 1561 outb(vgaCRIndex, 0x55); 1562 new->cr55 = (inb(vgaCRReg) & 0x08) | 0x40; 1563 outb(vgaCRReg, new->cr55); 1564 1565 outb(vgaCRIndex, 0x5e); 1566 new->cr5e = (((mode->CrtcVTotal - 2) & 0x400) >> 10) | 1567 (((mode->CrtcVDisplay - 1) & 0x400) >> 9) | 1568 (((mode->CrtcVSyncStart) & 0x400) >> 8) | 1569 (((mode->CrtcVSyncStart) & 0x400) >> 6) | 0x40; 1570 outb(vgaCRReg, new->cr5e); 1571 1572 { 1573 int i; 1574 unsigned int j; 1575 1576 i = ((((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8) | 1577 ((((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) | 1578 ((((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) | 1579 ((mode->CrtcHSyncStart & 0x800) >> 7); 1580 if ((mode->CrtcHSyncEnd >> 3) - (mode->CrtcHSyncStart >> 3) > 64) 1581 i |= 0x08; 1582 if ((mode->CrtcHSyncEnd >> 3) - (mode->CrtcHSyncStart >> 3) > 32) 1583 i |= 0x20; 1584 1585 outb(vgaCRIndex, 0x3b); 1586 j = ((pVga->CRTC[0] + ((i & 0x01) << 8) + 1587 pVga->CRTC[4] + ((i & 0x10) << 4) + 1) / 2); 1588 1589 if (j - (pVga->CRTC[4] + ((i & 0x10) << 4)) < 4) { 1590 if (pVga->CRTC[4] + ((i & 0x10) << 4) + 4 <= pVga->CRTC[0] + ((i & 0x01) << 8)) 1591 j = pVga->CRTC[4] + ((i & 0x10) << 4) + 4; 1592 else 1593 j = pVga->CRTC[0] + ((i & 0x01) << 8) + 1; 1594 } 1595 if (pS3->Chipset == PCI_CHIP_AURORA64VP) { 1596 outb(vgaCRReg, 0x00); 1597 i &= ~0x40; 1598 } else { 1599 new->cr3b = j & 0xff; 1600 outb(vgaCRReg, new->cr3b); 1601 i |= (j & 0x100) >> 2; 1602 } 1603 1604 outb(vgaCRIndex, 0x3c); 1605 new->cr3c = (pVga->CRTC[0] + ((i & 0x01) << 8)) / 2; 1606 outb(vgaCRReg, new->cr3c); 1607 1608 outb(vgaCRIndex, 0x5d); 1609 new->cr5d = (inb(vgaCRReg) & 0x80) | i; 1610 outb(vgaCRReg, new->cr5d); 1611 } 1612 1613 { 1614 int i; 1615 1616 if (pScrn->videoRam > 1024) 1617 i = mode->HDisplay * pS3->s3Bpp / 8 + 1; 1618 else 1619 i = mode->HDisplay * pS3->s3Bpp / 4 + 1; 1620 1621 outb(vgaCRIndex, 0x61); 1622 tmp = 0x80 | (inb(vgaCRReg) & 0x60) | (i >> 8); 1623 new->cr61 = tmp; 1624 outb(vgaCRReg, new->cr61); 1625 outb(vgaCRIndex, 0x62); 1626 new->cr62 = i & 0xff; 1627 outb(vgaCRReg, new->cr62); 1628 } 1629 1630 if (mode->Flags & V_INTERLACE) { 1631 outb(vgaCRIndex, 0x42); 1632 new->cr42 = inb(vgaCRReg) | 0x20; 1633 outb(vgaCRReg, new->cr42); 1634 } else { 1635 outb(vgaCRIndex, 0x42); 1636 new->cr42 = inb(vgaCRReg) & ~0x20; 1637 outb(vgaCRReg, new->cr42); 1638 } 1639 1640 if (pS3->hasStreams) { 1641 unsigned char a; 1642 1643 outb(vgaCRIndex, 0x67); 1644 a = inb(vgaCRReg) & 0xfe; 1645 1646 switch (pScrn->depth) { 1647 case 8: 1648 break; 1649 case 15: 1650 a |= (3 << 4); 1651 break; 1652 case 16: 1653 a |= (5 << 4); 1654 break; 1655 case 24: 1656 a |= (13 << 4); 1657 break; 1658 } 1659 1660 if (pS3->hasStreams) 1661 a |= (3 << 2); 1662 1663 WaitVSync(); /* Wait for VSync before setting mode */ 1664 outb(vgaCRReg, a); 1665 } 1666 1667 if (pS3->Chipset == PCI_CHIP_968) { 1668 unsigned char a; 1669 1670 outb(vgaCRIndex, 0x67); 1671 a = inb(vgaCRReg) & 0xfe; 1672#if 0 1673 switch (pScrn->depth) { 1674 case 8: 1675 break; 1676 case 15: 1677 a |= (3 << 4); 1678 break; 1679 case 16: 1680 a |= (5 << 4); 1681 a |= (3 << 2); /* streams */ 1682 break; 1683 case 24: 1684 a |= (13 << 4); 1685 a |= (3 << 2); /* streams */ 1686 break; 1687 } 1688#endif 1689 outb(vgaCRReg, a); 1690 1691 outb(vgaCRIndex, 0x6d); 1692 outb(vgaCRReg, 0x00); 1693 } 1694 1695 if ((pS3->Chipset == PCI_CHIP_964_0) || 1696 (pS3->Chipset == PCI_CHIP_964_1)) { 1697 unsigned char bdelay; 1698 1699 outb(vgaCRIndex, 0x6d); 1700 bdelay = inb(vgaCRReg); 1701 1702 if (pS3->RamDac->RamDacType == TI3025_RAMDAC) { 1703 if (pS3->s3Bpp == 1) { 1704 if (mode->Clock > 80000) 1705 bdelay = 0x02; 1706 else 1707 bdelay = 0x03; 1708 } else if (pS3->s3Bpp == 2) { 1709 if (mode->Clock > 80000) 1710 bdelay = 0x00; 1711 else 1712 bdelay = 0x01; 1713 } else 1714 bdelay = 0x00; 1715 } 1716 1717 outb(vgaCRReg, bdelay); 1718 } 1719 1720 outb(vgaCRIndex, 0x66); 1721 new->cr66 = inb(vgaCRReg); 1722 if (pS3->S3NewMMIO) 1723 new->cr66 |= 0x88; 1724 else 1725 new->cr66 |= 0x80; 1726 outb(vgaCRReg, new->cr66); 1727 1728 1729 if (pS3->SlowDRAMRefresh) 1730 new->cr3a = 0xb7; 1731 else 1732 new->cr3a = 0xb5; 1733 outb(vgaCRIndex, 0x3a); 1734 outb(vgaCRReg, new->cr3a); 1735 1736 if (pS3->SlowVRAM) { 1737 /* 1738 * some Diamond Stealth 64 VRAM cards have a problem with 1739 * VRAM timing, increas -RAS low timing from 3.5 MCLKs 1740 * to 4.5 MCLKs 1741 */ 1742 outb(vgaCRIndex, 0x39); 1743 outb(vgaCRReg, 0xa5); 1744 outb(vgaCRIndex, 0x68); 1745 tmp = inb(vgaCRReg); 1746 if (tmp & 0x30) /* 3.5 MCLKs */ 1747 outb(vgaCRReg, tmp & 0xef); /* 4.5 MCLKs */ 1748 } 1749 1750 if (pS3->SlowDRAM) { 1751 /* 1752 * fixes some pixel errors for a SPEA Trio64V+ card 1753 * increase -RAS precharge timing from 2.5 MCLKs 1754 * to 3.5 MCLKs 1755 */ 1756 outb(vgaCRIndex, 0x39); 1757 outb(vgaCRReg, 0xa5); 1758 outb(vgaCRIndex, 0x68); 1759 tmp = inb(vgaCRReg) & 0xf7; 1760 outb(vgaCRReg, tmp); /* 3.5 MCLKs */ 1761 } 1762 1763 if (pS3->SlowEDODRAM) { 1764 /* 1765 * fixes some pixel errors for a SPEA Trio64V+ card 1766 * increase from 1-cycle to 2-cycle EDO mode 1767 */ 1768 outb(vgaCRIndex, 0x39); 1769 1770 outb(vgaCRReg, 0xa5); 1771 outb(vgaCRIndex, 0x36); 1772 tmp = inb(vgaCRReg); 1773 if (!(tmp & 0x0c)) /* 1-cycle EDO */ 1774 outb(vgaCRReg, tmp | 0x08); /* 2-cycle EDO */ 1775 } 1776 1777 if (pS3->Chipset == PCI_CHIP_AURORA64VP) { 1778 outb(0x3c4, 0x08); 1779 outb(0x3c5, 0x06); 1780#if 0 1781 outb(0x3c4, 0x54); 1782 outb(0x3c5, 0x10); 1783 outb(0x3c4, 0x55); 1784 outb(0x3c5, 0x00); 1785 outb(0x3c4, 0x56); 1786 outb(0x3c5, 0x1c); 1787 outb(0x3c4, 0x57); 1788 outb(0x3c5, 0x00); 1789#else 1790 outb(0x3c4, 0x54); 1791 outb(0x3c5, 0x1f); 1792 outb(0x3c4, 0x55); 1793 outb(0x3c5, 0x1f); 1794 outb(0x3c4, 0x56); 1795 outb(0x3c5, 0x1f); 1796 outb(0x3c4, 0x57); 1797 outb(0x3c5, 0x1f); 1798#endif 1799 1800 outb(0x3c4, 0x08); 1801 outb(0x3c5, 0x00); 1802 } 1803 1804 pScrn->AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 1805 1806 vgaHWProtect(pScrn, FALSE); 1807 1808 if (pScrn->displayWidth == 1024) 1809 outw(ADVFUNC_CNTL, 0x0007); 1810 else 1811 outw(ADVFUNC_CNTL, 0x0003); 1812 1813 outb(0x3c6, 0x00); 1814 1815 outw(SUBSYS_CNTL, 0x8000 | 0x1000); 1816 outw(SUBSYS_CNTL, 0x4000 | 0x1000); 1817 1818 inw(SUBSYS_STAT); 1819 1820 outw(0xbee8, 0x5000 | 0x0004 | 0x000c); 1821 1822 outb(0x3c6, 0xff); 1823 1824 new->cr59 = pS3->FBAddress >> 24; 1825 new->cr5a = pS3->FBAddress >> 16; 1826 1827 if (pScrn->videoRam <= 1024) 1828 new->cr58 = 0x15; 1829 else if (pScrn->videoRam <= 2048) 1830 new->cr58 = 0x16; 1831 else 1832 new->cr58 = 0x17; 1833 1834 if ((pS3->Chipset == PCI_CHIP_968) || 1835 (pS3->Chipset == PCI_CHIP_964_0) || 1836 (pS3->Chipset == PCI_CHIP_964_1)) 1837 new->cr58 |= 0x40; 1838 1839 outb(vgaCRIndex, 0x59); 1840 outb(vgaCRReg, new->cr59); 1841 outb(vgaCRIndex, 0x5a); 1842 outb(vgaCRReg, new->cr5a); 1843 outb(vgaCRIndex, 0x58); 1844 outb(vgaCRReg, new->cr58); 1845 1846 WaitQueue(5); 1847 SET_SCISSORS(0, 0, pS3->s3ScissR, pS3->s3ScissB); 1848 1849 if (pS3->hasStreams) 1850 S3InitStreams(pScrn, mode); 1851 1852 return TRUE; 1853} 1854 1855 1856static Bool S3EnterVT(int scrnIndex, int flags) 1857{ 1858 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1859 vgaHWPtr hwp = VGAHWPTR(pScrn); 1860 1861 vgaHWUnlock(hwp); 1862 if (!S3ModeInit(pScrn, pScrn->currentMode)) 1863 return FALSE; 1864 1865 return TRUE; 1866} 1867 1868 1869static void S3Restore(ScrnInfoPtr pScrn) 1870{ 1871 S3Ptr pS3 = S3PTR(pScrn); 1872 S3RegPtr restore = &pS3->SavedRegs; 1873 vgaHWPtr hwp = VGAHWPTR(pScrn); 1874 int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; 1875 int i; 1876 1877 vgaHWProtect(pScrn, TRUE); 1878 WaitQueue(8); 1879 1880 S3BankZero(pScrn); 1881 1882 outw(ADVFUNC_CNTL, 0x0000); 1883 1884 if (pS3->S3NewMMIO) { 1885 outb(vgaCRIndex, 0x53); 1886 outb(vgaCRReg, 0x00); 1887 } 1888 1889 pS3->DacRestore(pScrn); 1890 1891 if (pS3->RamDac->RamDacType == TI3025_RAMDAC) { 1892 outb(vgaCRIndex, 0x5c); 1893 outb(vgaCRReg, restore->s3syssave[0x0c + 16]); 1894 } 1895 1896 for(i=32; i<46; i++) { 1897 outb(vgaCRIndex, 0x40 + i); 1898 outb(vgaCRReg, restore->s3syssave[i]); 1899 } 1900 1901 for(i=0; i<16; i++) { 1902 if (!((1 << i) & 0x673b)) 1903 continue; 1904 outb(vgaCRIndex, 0x50 + i); 1905 outb(vgaCRReg, restore->s3syssave[i+16]); 1906 } 1907 1908 for(i=0; i<5; i++) { 1909 outb(vgaCRIndex, 0x30 + i); 1910 outb(vgaCRReg, restore->s3save[i]); 1911 outb(vgaCRIndex, 0x38 + i); 1912 outb(vgaCRReg, restore->s3save[i + 5]); 1913 } 1914 1915 for(i=0; i<16; i++) { 1916 outb(vgaCRIndex, 0x40 + i); 1917 outb(vgaCRReg, restore->s3syssave[i]); 1918 } 1919 1920 outb(vgaCRIndex, 0x45); 1921 inb(vgaCRReg); 1922 outb(vgaCRIndex, 0x4a); 1923 for(i=0; i<4; i++) 1924 outb(vgaCRReg, restore->color_stack[i]); 1925 1926 outb(vgaCRIndex, 0x45); 1927 inb(vgaCRReg); 1928 outb(vgaCRIndex, 0x4b); 1929 for(i=4; i<8; i++) 1930 outb(vgaCRReg, restore->color_stack[i]); 1931 1932 vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_ALL); 1933 1934 outb(0x3c2, restore->clock); 1935 1936 vgaHWProtect(pScrn, FALSE); 1937 1938} 1939 1940 1941static void S3LeaveVT(int scrnIndex, int flags) 1942{ 1943 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1944 vgaHWPtr hwp = VGAHWPTR(pScrn); 1945 1946 S3Restore(pScrn); 1947 vgaHWLock(hwp); 1948 1949 return; 1950} 1951 1952 1953static void S3AdjustFrame(int scrnIndex, int x, int y, int flags) 1954{ 1955 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1956 S3Ptr pS3 = S3PTR(pScrn); 1957 S3RegPtr regs = &pS3->ModeRegs; 1958 int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; 1959 int base, orig_base; 1960 unsigned char tmp; 1961 1962 if (x > pScrn->displayWidth - pS3->HDisplay) 1963 x = pScrn->displayWidth - pS3->HDisplay; 1964 1965 orig_base = (y * pScrn->displayWidth + x) * pS3->s3Bpp; 1966 base = (orig_base >> 2) & ~1; 1967 1968 /* for IBMRGB and TI only */ 1969 if (pS3->RamDac->RamDacType == IBM524A_RAMDAC) 1970 { 1971 int px, py, a; 1972 1973 miPointerGetPosition(inputInfo.pointer, &px, &py); 1974 1975 if (pS3->s3Bpp == 1) 1976 a = 4 - 1; 1977 else 1978 a = 8 - 1; 1979 if (px-x > pS3->HDisplay/2) 1980 base = ((orig_base + a*4) >> 2) & ~1; 1981 base &= ~a; 1982 } 1983 1984 outb(vgaCRIndex, 0x31); 1985 outb(vgaCRReg, ((base & 0x030000) >> 12) | regs->cr31); 1986 regs->cr51 &= ~0x03; 1987 regs->cr51 |= ((base & 0x0c0000) >> 18); 1988 outb(vgaCRIndex, 0x51); 1989 tmp = (inb(vgaCRReg) & ~0x03) | (regs->cr51 & 0x03); 1990 outb(vgaCRReg, tmp); 1991 1992 outw(vgaCRIndex, (base & 0x00ff00) | 0x0c); 1993 outw(vgaCRIndex, ((base & 0x00ff) << 8) | 0x0d); 1994} 1995 1996 1997void S3Regdump(ScrnInfoPtr pScrn) 1998{ 1999 S3Ptr pS3 = S3PTR(pScrn); 2000 int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; 2001 { 2002 int j; 2003 2004 for(j=0; j<0x100; j++) { 2005 outb(vgaCRIndex, j); 2006 ErrorF("CRTC 0x%x = 0x%x\n", j, inb(vgaCRReg)); 2007 } 2008 } 2009#if 0 2010 ErrorF("DAC regs\n"); 2011 2012 { 2013 int j; 2014 2015 for(j=0; j<0x100; j++) 2016 ErrorF("0x%x = 0x%x\n", j, S3InTiIndReg(pScrn, j)); 2017#if 0 2018 outb(vgaCRIndex, 0x22); 2019 ErrorF("cr22 = 0x%x\n", inb(vgaCRReg)); 2020#endif 2021 } 2022#endif 2023} 2024 2025 2026void S3BankZero(ScrnInfoPtr pScrn) 2027{ 2028 S3Ptr pS3 = S3PTR(pScrn); 2029 unsigned char tmp; 2030 int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; 2031 2032 outb(vgaCRIndex, 0x35); 2033 tmp = inb(vgaCRReg) & 0xf0; 2034 outb(vgaCRReg, tmp); 2035 2036 outb(vgaCRIndex, 0x51); 2037 tmp = inb(vgaCRReg) & 0xf3; 2038 outb(vgaCRReg, tmp); 2039} 2040 2041static void 2042S3DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, 2043 int flags) 2044{ 2045 S3Ptr pS3 = S3PTR(pScrn); 2046 switch (pS3->Chipset) { 2047 case PCI_CHIP_TRIO64V2_DXGX: 2048 case PCI_CHIP_TRIO: 2049 case PCI_CHIP_AURORA64VP: 2050 case PCI_CHIP_TRIO64UVP: 2051 { 2052 int srd; 2053 2054 outb(0x3c4, 0x08); 2055 outb(0x3c5, 0x06); /* unlock extended sequence registers */ 2056 2057 outb(0x3c4, 0x0d); 2058 srd = inb(0x3c5) & 0xf; /* clear the sync control bits */ 2059 2060 switch (PowerManagementMode) { 2061 case DPMSModeOn: 2062 /* Screen: On; HSync: On, VSync: On */ 2063 break; 2064 case DPMSModeStandby: 2065 /* Screen: Off; HSync: Off, VSync: On */ 2066 srd |= 0x10; 2067 break; 2068 case DPMSModeSuspend: 2069 /* Screen: Off; HSync: On, VSync: Off */ 2070 srd |= 0x40; 2071 break; 2072 case DPMSModeOff: 2073 /* Screen: Off; HSync: Off, VSync: Off */ 2074 srd |= 0x50; 2075 break; 2076 } 2077 outb(0x3c4, 0x0d); 2078 outb(0x3c5, srd); 2079 break; 2080 } 2081 default: 2082 vgaHWDPMSSet(pScrn, PowerManagementMode, flags); 2083 } 2084} 2085