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