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