savage_driver.c revision ab47cfaa
1/* 2 * Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. 3 * Copyright (c) 2003-2006, X.Org Foundation 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 * COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 * 23 * Except as contained in this notice, the name of the copyright holder(s) 24 * and author(s) shall not be used in advertising or otherwise to promote 25 * the sale, use or other dealings in this Software without prior written 26 * authorization from the copyright holder(s) and author(s). 27 */ 28 29/** 30 * \file savage_driver.c 31 * 32 * \author Tim Roberts <timr@probo.com> 33 * \author Ani Joshi <ajoshi@unixbox.com> 34 * 35 * \todo Add credits for the 3.3.x authors. 36 */ 37 38#ifdef HAVE_CONFIG_H 39#include "config.h" 40#endif 41 42#include "xf86RAC.h" 43#include "shadowfb.h" 44 45#include "globals.h" 46#define DPMS_SERVER 47#include <X11/extensions/dpms.h> 48 49#include "xf86xv.h" 50 51#include "savage_driver.h" 52#include "savage_regs.h" 53#include "savage_bci.h" 54#include "savage_streams.h" 55 56#define TRANSPARENCY_KEY 0xff; 57 58#ifdef XF86DRI 59#define _XF86DRI_SERVER_ 60#include "savage_dri.h" 61#include "savage_sarea.h" 62#endif 63 64 65/* 66 * prototypes 67 */ 68static void SavageEnableMMIO(ScrnInfoPtr pScrn); 69static void SavageDisableMMIO(ScrnInfoPtr pScrn); 70 71static const OptionInfoRec * SavageAvailableOptions(int chipid, int busid); 72static void SavageIdentify(int flags); 73static Bool SavageProbe(DriverPtr drv, int flags); 74static Bool SavagePreInit(ScrnInfoPtr pScrn, int flags); 75 76static Bool SavageEnterVT(int scrnIndex, int flags); 77static void SavageLeaveVT(int scrnIndex, int flags); 78static void SavageSave(ScrnInfoPtr pScrn); 79static void SavageWriteMode(ScrnInfoPtr pScrn, vgaRegPtr, SavageRegPtr, Bool); 80 81static void SavageInitStatus(ScrnInfoPtr pScrn); 82static void SavageInitShadowStatus(ScrnInfoPtr pScrn); 83 84static Bool SavageScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, 85 char **argv); 86static int SavageInternalScreenInit(int scrnIndex, ScreenPtr pScreen); 87static ModeStatus SavageValidMode(int index, DisplayModePtr mode, 88 Bool verbose, int flags); 89 90void SavageDGAInit(ScreenPtr); 91static Bool SavageMapMem(ScrnInfoPtr pScrn); 92static void SavageUnmapMem(ScrnInfoPtr pScrn, int All); 93static Bool SavageModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); 94static Bool SavageCloseScreen(int scrnIndex, ScreenPtr pScreen); 95static Bool SavageSaveScreen(ScreenPtr pScreen, int mode); 96static void SavageLoadPalette(ScrnInfoPtr pScrn, int numColors, 97 int *indicies, LOCO *colors, 98 VisualPtr pVisual); 99static void SavageLoadPaletteSavage4(ScrnInfoPtr pScrn, int numColors, 100 int *indicies, LOCO *colors, 101 VisualPtr pVisual); 102static void SavageUpdateKey(ScrnInfoPtr pScrn, int r, int g, int b); 103static void SavageCalcClock(long freq, int min_m, int min_n1, int max_n1, 104 int min_n2, int max_n2, long freq_min, 105 long freq_max, unsigned int *mdiv, 106 unsigned int *ndiv, unsigned int *r); 107void SavageGEReset(ScrnInfoPtr pScrn, int from_timeout, int line, char *file); 108void SavagePrintRegs(ScrnInfoPtr pScrn); 109static void SavageDPMS(ScrnInfoPtr pScrn, int mode, int flags); 110static Bool SavageDDC1(int scrnIndex); 111static unsigned int SavageDDC1Read(ScrnInfoPtr pScrn); 112static void SavageProbeDDC(ScrnInfoPtr pScrn, int index); 113static void SavageGetTvMaxSize(SavagePtr psav); 114static Bool SavagePanningCheck(ScrnInfoPtr pScrn); 115#ifdef XF86DRI 116static Bool SavageCheckAvailableRamFor3D(ScrnInfoPtr pScrn); 117#endif 118static void SavageResetStreams(ScrnInfoPtr pScrn); 119 120extern ScrnInfoPtr gpScrn; 121 122#define iabs(a) ((int)(a)>0?(a):(-(a))) 123 124/*#define TRACEON*/ 125#ifdef TRACEON 126#define TRACE(prms) ErrorF prms 127#else 128#define TRACE(prms) 129#endif 130 131int gSavageEntityIndex = -1; 132 133_X_EXPORT DriverRec SAVAGE = 134{ 135 SAVAGE_VERSION, 136 SAVAGE_DRIVER_NAME, 137 SavageIdentify, 138 SavageProbe, 139 SavageAvailableOptions, 140 NULL, 141 0, 142 NULL 143}; 144 145 146/* Supported chipsets */ 147 148static SymTabRec SavageChips[] = { 149 { PCI_CHIP_SAVAGE4, "Savage4" }, 150 { PCI_CHIP_SAVAGE3D, "Savage3D" }, 151 { PCI_CHIP_SAVAGE3D_MV, "Savage3D-MV" }, 152 { PCI_CHIP_SAVAGE2000, "Savage2000" }, 153 { PCI_CHIP_SAVAGE_MX_MV, "Savage/MX-MV" }, 154 { PCI_CHIP_SAVAGE_MX, "Savage/MX" }, 155 { PCI_CHIP_SAVAGE_IX_MV, "Savage/IX-MV" }, 156 { PCI_CHIP_SAVAGE_IX, "Savage/IX" }, 157 { PCI_CHIP_PROSAVAGE_PM, "ProSavage PM133" }, 158 { PCI_CHIP_PROSAVAGE_KM, "ProSavage KM133" }, 159 { PCI_CHIP_S3TWISTER_P, "Twister PN133" }, 160 { PCI_CHIP_S3TWISTER_K, "Twister KN133" }, 161 { PCI_CHIP_SUPSAV_MX128, "SuperSavage/MX 128" }, 162 { PCI_CHIP_SUPSAV_MX64, "SuperSavage/MX 64" }, 163 { PCI_CHIP_SUPSAV_MX64C, "SuperSavage/MX 64C" }, 164 { PCI_CHIP_SUPSAV_IX128SDR, "SuperSavage/IX 128" }, 165 { PCI_CHIP_SUPSAV_IX128DDR, "SuperSavage/IX 128" }, 166 { PCI_CHIP_SUPSAV_IX64SDR, "SuperSavage/IX 64" }, 167 { PCI_CHIP_SUPSAV_IX64DDR, "SuperSavage/IX 64" }, 168 { PCI_CHIP_SUPSAV_IXCSDR, "SuperSavage/IXC 64" }, 169 { PCI_CHIP_SUPSAV_IXCDDR, "SuperSavage/IXC 64" }, 170 { PCI_CHIP_PROSAVAGE_DDR, "ProSavage DDR" }, 171 { PCI_CHIP_PROSAVAGE_DDRK, "ProSavage DDR-K" }, 172 { -1, NULL } 173}; 174 175static SymTabRec SavageChipsets[] = { 176 { S3_SAVAGE3D, "Savage3D" }, 177 { S3_SAVAGE4, "Savage4" }, 178 { S3_SAVAGE2000, "Savage2000" }, 179 { S3_SAVAGE_MX, "MobileSavage" }, 180 { S3_PROSAVAGE, "ProSavage" }, 181 { S3_TWISTER, "Twister"}, 182 { S3_PROSAVAGEDDR, "ProSavageDDR"}, 183 { S3_SUPERSAVAGE, "SuperSavage" }, 184 { -1, NULL } 185}; 186 187/* This table maps a PCI device ID to a chipset family identifier. */ 188 189static PciChipsets SavagePciChipsets[] = { 190 { S3_SAVAGE3D, PCI_CHIP_SAVAGE3D, RES_SHARED_VGA }, 191 { S3_SAVAGE3D, PCI_CHIP_SAVAGE3D_MV, RES_SHARED_VGA }, 192 { S3_SAVAGE4, PCI_CHIP_SAVAGE4, RES_SHARED_VGA }, 193 { S3_SAVAGE2000, PCI_CHIP_SAVAGE2000, RES_SHARED_VGA }, 194 { S3_SAVAGE_MX, PCI_CHIP_SAVAGE_MX_MV, RES_SHARED_VGA }, 195 { S3_SAVAGE_MX, PCI_CHIP_SAVAGE_MX, RES_SHARED_VGA }, 196 { S3_SAVAGE_MX, PCI_CHIP_SAVAGE_IX_MV, RES_SHARED_VGA }, 197 { S3_SAVAGE_MX, PCI_CHIP_SAVAGE_IX, RES_SHARED_VGA }, 198 { S3_PROSAVAGE, PCI_CHIP_PROSAVAGE_PM, RES_SHARED_VGA }, 199 { S3_PROSAVAGE, PCI_CHIP_PROSAVAGE_KM, RES_SHARED_VGA }, 200 { S3_TWISTER, PCI_CHIP_S3TWISTER_P, RES_SHARED_VGA }, 201 { S3_TWISTER, PCI_CHIP_S3TWISTER_K, RES_SHARED_VGA }, 202 { S3_PROSAVAGEDDR, PCI_CHIP_PROSAVAGE_DDR, RES_SHARED_VGA }, 203 { S3_PROSAVAGEDDR, PCI_CHIP_PROSAVAGE_DDRK, RES_SHARED_VGA }, 204 { S3_SUPERSAVAGE, PCI_CHIP_SUPSAV_MX128, RES_SHARED_VGA }, 205 { S3_SUPERSAVAGE, PCI_CHIP_SUPSAV_MX64, RES_SHARED_VGA }, 206 { S3_SUPERSAVAGE, PCI_CHIP_SUPSAV_MX64C, RES_SHARED_VGA }, 207 { S3_SUPERSAVAGE, PCI_CHIP_SUPSAV_IX128SDR, RES_SHARED_VGA }, 208 { S3_SUPERSAVAGE, PCI_CHIP_SUPSAV_IX128DDR, RES_SHARED_VGA }, 209 { S3_SUPERSAVAGE, PCI_CHIP_SUPSAV_IX64SDR, RES_SHARED_VGA }, 210 { S3_SUPERSAVAGE, PCI_CHIP_SUPSAV_IX64DDR, RES_SHARED_VGA }, 211 { S3_SUPERSAVAGE, PCI_CHIP_SUPSAV_IXCSDR, RES_SHARED_VGA }, 212 { S3_SUPERSAVAGE, PCI_CHIP_SUPSAV_IXCDDR, RES_SHARED_VGA }, 213 { -1, -1, RES_UNDEFINED } 214}; 215 216typedef enum { 217 OPTION_PCI_BURST 218 ,OPTION_PCI_RETRY 219 ,OPTION_NOACCEL 220 ,OPTION_ACCELMETHOD 221 ,OPTION_LCD_CENTER 222 ,OPTION_LCDCLOCK 223 ,OPTION_MCLK 224 ,OPTION_REFCLK 225 ,OPTION_SHOWCACHE 226 ,OPTION_SWCURSOR 227 ,OPTION_HWCURSOR 228 ,OPTION_SHADOW_FB 229 ,OPTION_ROTATE 230 ,OPTION_USEBIOS 231 ,OPTION_SHADOW_STATUS 232 ,OPTION_CRT_ONLY 233 ,OPTION_TV_ON 234 ,OPTION_TV_PAL 235 ,OPTION_FORCE_INIT 236 ,OPTION_OVERLAY 237 ,OPTION_T_KEY 238 ,OPTION_DISABLE_XVMC 239 ,OPTION_DISABLE_TILE 240 ,OPTION_DISABLE_COB 241 ,OPTION_BCI_FOR_XV 242 ,OPTION_DVI 243 ,OPTION_BUS_TYPE 244 ,OPTION_DMA_TYPE 245 ,OPTION_DMA_MODE 246 ,OPTION_AGP_MODE 247 ,OPTION_AGP_SIZE 248 ,OPTION_DRI 249} SavageOpts; 250 251 252static const OptionInfoRec SavageOptions[] = 253{ 254 { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 255 { OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING, {0}, FALSE }, 256 { OPTION_HWCURSOR, "HWCursor", OPTV_BOOLEAN, {0}, FALSE }, 257 { OPTION_SWCURSOR, "SWCursor", OPTV_BOOLEAN, {0}, FALSE }, 258 { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, 259 { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, 260 { OPTION_USEBIOS, "UseBIOS", OPTV_BOOLEAN, {0}, FALSE }, 261 { OPTION_LCDCLOCK, "LCDClock", OPTV_FREQ, {0}, FALSE }, 262 { OPTION_SHADOW_STATUS, "ShadowStatus", OPTV_BOOLEAN, {0}, FALSE }, 263 { OPTION_CRT_ONLY, "CrtOnly", OPTV_BOOLEAN, {0}, FALSE }, 264 { OPTION_TV_ON, "TvOn", OPTV_BOOLEAN, {0}, FALSE }, 265 { OPTION_TV_PAL, "PAL", OPTV_BOOLEAN, {0}, FALSE }, 266 { OPTION_FORCE_INIT,"ForceInit", OPTV_BOOLEAN, {0}, FALSE }, 267 { OPTION_OVERLAY, "Overlay", OPTV_ANYSTR, {0}, FALSE }, 268 { OPTION_T_KEY, "TransparencyKey", OPTV_ANYSTR, {0}, FALSE }, 269 { OPTION_FORCE_INIT, "ForceInit", OPTV_BOOLEAN, {0}, FALSE }, 270 { OPTION_DISABLE_XVMC, "DisableXVMC", OPTV_BOOLEAN, {0}, FALSE }, 271 { OPTION_DISABLE_TILE, "DisableTile", OPTV_BOOLEAN, {0}, FALSE }, 272 { OPTION_DISABLE_COB, "DisableCOB", OPTV_BOOLEAN, {0}, FALSE }, 273 { OPTION_BCI_FOR_XV, "BCIforXv", OPTV_BOOLEAN, {0}, FALSE }, 274 { OPTION_DVI, "DVI", OPTV_BOOLEAN, {0}, FALSE }, 275#ifdef XF86DRI 276 { OPTION_BUS_TYPE, "BusType", OPTV_ANYSTR, {0}, FALSE }, 277 { OPTION_DMA_TYPE, "DmaType", OPTV_ANYSTR, {0}, FALSE }, 278 { OPTION_DMA_MODE, "DmaMode", OPTV_ANYSTR, {0}, FALSE }, 279 { OPTION_AGP_MODE, "AGPMode", OPTV_INTEGER, {0}, FALSE }, 280 { OPTION_AGP_SIZE, "AGPSize", OPTV_INTEGER, {0}, FALSE }, 281 { OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, TRUE }, 282#endif 283 { -1, NULL, OPTV_NONE, {0}, FALSE } 284}; 285 286 287static const char *vgaHWSymbols[] = { 288 "vgaHWBlankScreen", 289 "vgaHWCopyReg", 290 "vgaHWGetHWRec", 291 "vgaHWGetIOBase", 292 "vgaHWGetIndex", 293 "vgaHWInit", 294 "vgaHWLock", 295 "vgaHWProtect", 296 "vgaHWRestore", 297 "vgaHWSave", 298 "vgaHWSaveScreen", 299 "vgaHWSetMmioFuncs", 300 "vgaHWSetStdFuncs", 301 "vgaHWUnmapMem", 302 "vgaHWddc1SetSpeedWeak", 303#if 0 304 "vgaHWFreeHWRec", 305 "vgaHWMapMem", 306 "vgaHWUnlock", 307#endif 308 NULL 309}; 310 311#ifdef XF86DRI 312static const char *drmSymbols[] = { 313 "drmAvailable", 314 "drmAddBufs", 315 "drmAddMap", 316 "drmCtlInstHandler", 317 "drmGetInterruptFromBusID", 318 "drmFreeVersion", 319 "drmGetVersion", 320 "drmMap", 321 "drmUnmap", 322 "drmMapBufs", 323 "drmUnmapBufs", 324 "drmAgpAcquire", 325 "drmAgpRelease", 326 "drmAgpEnable", 327 "drmAgpAlloc", 328 "drmAgpFree", 329 "drmAgpBind", 330 "drmAgpUnbind", 331 "drmAgpGetMode", 332 "drmAgpBase", 333 "drmAgpSize", 334 "drmAgpVendorId", 335 "drmAgpDeviceId", 336 "drmMGAInitDMA", 337 "drmMGACleanupDMA", 338 "drmMGAFlushDMA", 339 "drmMGAEngineReset", 340 NULL 341}; 342 343static const char *driSymbols[] = { 344 "DRIGetDrawableIndex", 345 "DRIFinishScreenInit", 346 "DRIDestroyInfoRec", 347 "DRICloseScreen", 348 "DRIDestroyInfoRec", 349 "DRIScreenInit", 350 "DRIDestroyInfoRec", 351 "DRICreateInfoRec", 352 "DRILock", 353 "DRIUnlock", 354 "DRIGetSAREAPrivate", 355 "DRIGetContext", 356 "DRIQueryVersion", 357 "DRIAdjustFrame", 358 "DRIOpenFullScreen", 359 "DRICloseFullScreen", 360 "GlxSetVisualConfigs", 361 NULL 362}; 363#endif 364 365 366static const char *ramdacSymbols[] = { 367 "xf86CreateCursorInfoRec", 368#if 0 369 "xf86DestroyCursorInfoRec", 370#endif 371 "xf86InitCursor", 372 NULL 373}; 374 375static const char *int10Symbols[] = { 376 "xf86ExecX86int10", 377 "xf86Int10AllocPages", 378 "xf86int10Addr", 379 "xf86Int10FreePages" 380}; 381 382static const char *vbeSymbols[] = { 383 "VBEInit", 384 "vbeDoEDID", 385#if 0 386 "vbeFree", 387#endif 388 NULL 389}; 390 391static const char *vbeOptSymbols[] = { 392 "vbeModeInit", 393 "VBESetVBEMode", 394 "VBEGetVBEInfo", 395 "VBEFreeVBEInfo", 396 NULL 397}; 398 399static const char *ddcSymbols[] = { 400 "xf86DoEDID_DDC1", 401 "xf86DoEDID_DDC2", 402 "xf86PrintEDID", 403 "xf86SetDDCproperties", 404 NULL 405}; 406 407static const char *i2cSymbols[] = { 408 "xf86CreateI2CBusRec", 409 "xf86I2CBusInit", 410 "xf86CreateI2CDevRec", 411 "xf86I2CDevInit", 412 "xf86I2CWriteByte", 413 "xf86I2CWriteBytes", 414 "xf86I2CReadByte", 415 "xf86I2CReadBytes", 416 "xf86I2CWriteRead", 417 "xf86DestroyI2CDevRec", 418 NULL 419}; 420 421static const char *xaaSymbols[] = { 422 "XAAGetCopyROP", 423 "XAAGetCopyROP_PM", 424 "XAACreateInfoRec", 425 "XAADestroyInfoRec", 426 "XAAFillSolidRects", 427 "XAAHelpPatternROP", 428 "XAAHelpSolidROP", 429 "XAAInit", 430 "XAAScreenIndex", 431 NULL 432}; 433 434static const char *exaSymbols[] = { 435 "exaDriverAlloc", 436 "exaDriverInit", 437 "exaDriverFini", 438 "exaOffscreenAlloc", 439 "exaOffscreenFree", 440 "exaGetPixmapOffset", 441 "exaGetPixmapPitch", 442 "exaGetPixmapSize", 443 NULL 444}; 445 446static const char *shadowSymbols[] = { 447 "ShadowFBInit", 448 NULL 449}; 450 451static const char *fbSymbols[] = { 452 "fbPictureInit", 453 "fbScreenInit", 454 NULL 455}; 456 457#ifdef XFree86LOADER 458 459static MODULESETUPPROTO(SavageSetup); 460 461static XF86ModuleVersionInfo SavageVersRec = { 462 "savage", 463 MODULEVENDORSTRING, 464 MODINFOSTRING1, 465 MODINFOSTRING2, 466 XORG_VERSION_CURRENT, 467 SAVAGE_VERSION_MAJOR, SAVAGE_VERSION_MINOR, SAVAGE_PATCHLEVEL, 468 ABI_CLASS_VIDEODRV, 469 ABI_VIDEODRV_VERSION, 470 MOD_CLASS_VIDEODRV, 471 {0, 0, 0, 0} 472}; 473 474_X_EXPORT XF86ModuleData savageModuleData = { 475 &SavageVersRec, 476 SavageSetup, 477 NULL 478}; 479 480static pointer SavageSetup(pointer module, pointer opts, int *errmaj, 481 int *errmin) 482{ 483 static Bool setupDone = FALSE; 484 485 if (!setupDone) { 486 setupDone = TRUE; 487 xf86AddDriver(&SAVAGE, module, 1); 488 LoaderRefSymLists(vgaHWSymbols, fbSymbols, ramdacSymbols, 489 xaaSymbols, 490 exaSymbols, 491 shadowSymbols, vbeSymbols, vbeOptSymbols, 492#ifdef XF86DRI 493 drmSymbols, driSymbols, 494#endif 495 int10Symbols, i2cSymbols, ddcSymbols, NULL); 496 return (pointer) 1; 497 } else { 498 if (errmaj) 499 *errmaj = LDR_ONCEONLY; 500 return NULL; 501 } 502} 503 504#endif /* XFree86LOADER */ 505 506static SavageEntPtr SavageEntPriv(ScrnInfoPtr pScrn) 507{ 508 DevUnion *pPriv; 509 SavagePtr psav = SAVPTR(pScrn); 510 pPriv = xf86GetEntityPrivate(psav->pEnt->index, 511 gSavageEntityIndex); 512 return pPriv->ptr; 513} 514 515 516/* 517 * I'd rather have these wait macros be inline, but S3 has made it 518 * darned near impossible. The bit fields are in a different place in 519 * all three families, the status register has a different address in the 520 * three families, and even the idle vs busy sense flipped in the Sav2K. 521 */ 522 523static void 524ResetBCI2K( SavagePtr psav ) 525{ 526 CARD32 cob = INREG( 0x48c18 ); 527 /* if BCI is enabled and BCI is busy... */ 528 529 if( 530 (cob & 0x00000008) && 531 ! (ALT_STATUS_WORD0 & 0x00200000) 532 ) 533 { 534 ErrorF( "Resetting BCI, stat = %08lx...\n", 535 (unsigned long) ALT_STATUS_WORD0); 536 /* Turn off BCI */ 537 OUTREG( 0x48c18, cob & ~8 ); 538 usleep(10000); 539 /* Turn it back on */ 540 OUTREG( 0x48c18, cob ); 541 usleep(10000); 542 } 543} 544 545static Bool 546ShadowWait( SavagePtr psav ) 547{ 548 BCI_GET_PTR; 549 int loop = 0; 550 551 if( !psav->NoPCIRetry ) 552 return 0; 553 554 psav->ShadowCounter = (psav->ShadowCounter + 1) & 0xffff; 555 if (psav->ShadowCounter == 0) 556 psav->ShadowCounter++; /* 0 is reserved for the BIOS 557 to avoid confusion in the DRM */ 558 BCI_SEND( psav->dwBCIWait2DIdle ); 559 BCI_SEND( 0x98000000 + psav->ShadowCounter ); 560 561 while( 562 (int)(psav->ShadowVirtual[psav->eventStatusReg] & 0xffff) != 563 psav->ShadowCounter && (loop++ < MAXLOOP) 564 ) 565 ; 566 567 return loop >= MAXLOOP; 568} 569 570static Bool 571ShadowWaitQueue( SavagePtr psav, int v ) 572{ 573 int loop = 0; 574 CARD32 slots = MAXFIFO - v; 575 576 if (slots >= psav->bciThresholdHi) 577 slots = psav->bciThresholdHi; 578 else 579 return ShadowWait( psav ); 580 581 /* Savage 2000 reports only entries filled in the COB, not the on-chip 582 * queue. Also it reports in qword units instead of dwords. */ 583 if (psav->Chipset == S3_SAVAGE2000) 584 slots = (slots - 32) / 4; 585 586 while( ((psav->ShadowVirtual[0] & psav->bciUsedMask) >= slots) && (loop++ < MAXLOOP)) 587 ; 588 589 return loop >= MAXLOOP; 590} 591 592/* Wait until "v" queue entries are free */ 593 594static int 595WaitQueue3D( SavagePtr psav, int v ) 596{ 597 int loop = 0; 598 CARD32 slots = MAXFIFO - v; 599 600 mem_barrier(); 601 if( psav->ShadowVirtual ) 602 { 603 psav->WaitQueue = ShadowWaitQueue; 604 return ShadowWaitQueue(psav, v); 605 } 606 else 607 { 608 loop &= STATUS_WORD0; 609 while( ((STATUS_WORD0 & 0x0000ffff) > slots) && (loop++ < MAXLOOP)) 610 ; 611 } 612 return loop >= MAXLOOP; 613} 614 615static int 616WaitQueue4( SavagePtr psav, int v ) 617{ 618 int loop = 0; 619 CARD32 slots = MAXFIFO - v; 620 621 if( !psav->NoPCIRetry ) 622 return 0; 623 mem_barrier(); 624 if( psav->ShadowVirtual ) 625 { 626 psav->WaitQueue = ShadowWaitQueue; 627 return ShadowWaitQueue(psav, v); 628 } 629 else 630 while( ((ALT_STATUS_WORD0 & 0x001fffff) > slots) && (loop++ < MAXLOOP)); 631 return loop >= MAXLOOP; 632} 633 634static int 635WaitQueue2K( SavagePtr psav, int v ) 636{ 637 int loop = 0; 638 CARD32 slots = (MAXFIFO - v) / 4; 639 640 if( !psav->NoPCIRetry ) 641 return 0; 642 mem_barrier(); 643 if( psav->ShadowVirtual ) 644 { 645 psav->WaitQueue = ShadowWaitQueue; 646 return ShadowWaitQueue(psav, v); 647 } 648 else 649 while( ((ALT_STATUS_WORD0 & 0x000fffff) > slots) && (loop++ < MAXLOOP)) 650 ; 651 if( loop >= MAXLOOP ) 652 ResetBCI2K(psav); 653 return loop >= MAXLOOP; 654} 655 656/* Wait until GP is idle and queue is empty */ 657 658static int 659WaitIdleEmpty3D(SavagePtr psav) 660{ 661 int loop = 0; 662 mem_barrier(); 663 if( psav->ShadowVirtual ) 664 { 665 psav->WaitIdleEmpty = ShadowWait; 666 return ShadowWait(psav); 667 } 668 loop &= STATUS_WORD0; 669 while( ((STATUS_WORD0 & 0x0008ffff) != 0x80000) && (loop++ < MAXLOOP) ); 670 return loop >= MAXLOOP; 671} 672 673static int 674WaitIdleEmpty4(SavagePtr psav) 675{ 676 int loop = 0; 677 mem_barrier(); 678 if( psav->ShadowVirtual ) 679 { 680 psav->WaitIdleEmpty = ShadowWait; 681 return ShadowWait(psav); 682 } 683 /* which is right?*/ 684 /*while( ((ALT_STATUS_WORD0 & 0x00a1ffff) != 0x00a00000) && (loop++ < MAXLOOP) );*/ /* tim */ 685 while (((ALT_STATUS_WORD0 & 0x00e1ffff) != 0x00e00000) && (loop++ < MAXLOOP)); /* S3 */ 686 return loop >= MAXLOOP; 687} 688 689static int 690WaitIdleEmpty2K(SavagePtr psav) 691{ 692 int loop = 0; 693 mem_barrier(); 694 if( psav->ShadowVirtual ) 695 { 696 psav->WaitIdleEmpty = ShadowWait; 697 return ShadowWait(psav); 698 } 699 loop &= ALT_STATUS_WORD0; 700 while( ((ALT_STATUS_WORD0 & 0x009fffff) != 0) && (loop++ < MAXLOOP) ); 701 if( loop >= MAXLOOP ) 702 ResetBCI2K(psav); 703 return loop >= MAXLOOP; 704} 705 706/* Wait until GP is idle */ 707 708static int 709WaitIdle3D(SavagePtr psav) 710{ 711 int loop = 0; 712 mem_barrier(); 713 if( psav->ShadowVirtual ) 714 { 715 psav->WaitIdle = ShadowWait; 716 return ShadowWait(psav); 717 } 718 while( (!(STATUS_WORD0 & 0x00080000)) && (loop++ < MAXLOOP) ); 719 return loop >= MAXLOOP; 720} 721 722static int 723WaitIdle4(SavagePtr psav) 724{ 725 int loop = 0; 726 mem_barrier(); 727 if( psav->ShadowVirtual ) 728 { 729 psav->WaitIdle = ShadowWait; 730 return ShadowWait(psav); 731 } 732 /* which is right?*/ 733 /*while( (!(ALT_STATUS_WORD0 & 0x00800000)) && (loop++ < MAXLOOP) );*/ /* tim */ 734 while (((ALT_STATUS_WORD0 & 0x00E00000)!=0x00E00000) && (loop++ < MAXLOOP)); /* S3 */ 735 return loop >= MAXLOOP; 736} 737 738static int 739WaitIdle2K(SavagePtr psav) 740{ 741 int loop = 0; 742 mem_barrier(); 743 if( psav->ShadowVirtual ) 744 { 745 psav->WaitIdle = ShadowWait; 746 return ShadowWait(psav); 747 } 748 loop &= ALT_STATUS_WORD0; 749 while( (ALT_STATUS_WORD0 & 0x00900000) && (loop++ < MAXLOOP) ); 750 return loop >= MAXLOOP; 751} 752 753 754static Bool SavageGetRec(ScrnInfoPtr pScrn) 755{ 756 if (pScrn->driverPrivate) 757 return TRUE; 758 759 pScrn->driverPrivate = xnfcalloc(sizeof(SavageRec), 1); 760 return TRUE; 761} 762 763 764static void SavageFreeRec(ScrnInfoPtr pScrn) 765{ 766 TRACE(( "SavageFreeRec(%x)\n", pScrn->driverPrivate )); 767 if (!pScrn->driverPrivate) 768 return; 769 SavageUnmapMem(pScrn, 1); 770 xfree(pScrn->driverPrivate); 771 pScrn->driverPrivate = NULL; 772} 773 774 775static const OptionInfoRec * SavageAvailableOptions(int chipid, int busid) 776{ 777 return SavageOptions; 778} 779 780 781static void SavageIdentify(int flags) 782{ 783 xf86PrintChipsets("SAVAGE", 784 "driver (version " SAVAGE_DRIVER_VERSION ") for S3 Savage chipsets", 785 SavageChips); 786} 787 788 789static Bool SavageProbe(DriverPtr drv, int flags) 790{ 791 int i; 792 GDevPtr *devSections = NULL; 793 int *usedChips; 794 int numDevSections; 795 int numUsed; 796 Bool foundScreen = FALSE; 797 798 /* sanity checks */ 799 if ((numDevSections = xf86MatchDevice("savage", &devSections)) <= 0) 800 return FALSE; 801 if (xf86GetPciVideoInfo() == NULL) { 802 if (devSections) 803 xfree(devSections); 804 return FALSE; 805 } 806 807 numUsed = xf86MatchPciInstances("SAVAGE", PCI_VENDOR_S3, 808 SavageChipsets, SavagePciChipsets, 809 devSections, numDevSections, drv, 810 &usedChips); 811 if (devSections) 812 xfree(devSections); 813 devSections = NULL; 814 if (numUsed <= 0) 815 return FALSE; 816 817 if (flags & PROBE_DETECT) 818 foundScreen = TRUE; 819 else 820 for (i=0; i<numUsed; i++) { 821 EntityInfoPtr pEnt = xf86GetEntityInfo(usedChips[i]);; 822 ScrnInfoPtr pScrn = xf86ConfigPciEntity(NULL, 0, usedChips[i], 823 NULL, RES_SHARED_VGA, 824 NULL, NULL, NULL, NULL); 825 826 if (pScrn != NULL) { 827 pScrn->driverVersion = SAVAGE_VERSION; 828 pScrn->driverName = SAVAGE_DRIVER_NAME; 829 pScrn->name = "SAVAGE"; 830 pScrn->Probe = SavageProbe; 831 pScrn->PreInit = SavagePreInit; 832 pScrn->ScreenInit = SavageScreenInit; 833 pScrn->SwitchMode = SavageSwitchMode; 834 pScrn->AdjustFrame = SavageAdjustFrame; 835 pScrn->EnterVT = SavageEnterVT; 836 pScrn->LeaveVT = SavageLeaveVT; 837 pScrn->FreeScreen = NULL; 838 pScrn->ValidMode = SavageValidMode; 839 foundScreen = TRUE; 840 } 841 842 pEnt = xf86GetEntityInfo(usedChips[i]); 843 844 /* MX, IX, SuperSavage cards support Dual-Head, mark the entity as sharable*/ 845 if(pEnt->chipset == S3_SAVAGE_MX || pEnt->chipset == S3_SUPERSAVAGE) 846 { 847 DevUnion *pPriv; 848 SavageEntPtr pSavageEnt; 849 850 xf86SetEntitySharable(usedChips[i]); 851 852 if (gSavageEntityIndex == -1) 853 gSavageEntityIndex = xf86AllocateEntityPrivateIndex(); 854 855 pPriv = xf86GetEntityPrivate(pEnt->index, 856 gSavageEntityIndex); 857 858 if (!pPriv->ptr) { 859 int j; 860 int instance = xf86GetNumEntityInstances(pEnt->index); 861 862 for (j = 0; j < instance; j++) 863 xf86SetEntityInstanceForScreen(pScrn, pEnt->index, j); 864 865 pPriv->ptr = xnfcalloc(sizeof(SavageEntRec), 1); 866 pSavageEnt = pPriv->ptr; 867 pSavageEnt->HasSecondary = FALSE; 868 } else { 869 pSavageEnt = pPriv->ptr; 870 pSavageEnt->HasSecondary = TRUE; 871 } 872 } 873 xfree(pEnt); 874 } 875 876 877 xfree(usedChips); 878 return foundScreen; 879} 880 881static int LookupChipID( PciChipsets* pset, int ChipID ) 882{ 883 /* Is there a function to do this for me? */ 884 while( pset->numChipset >= 0 ) 885 { 886 if( pset->PCIid == ChipID ) 887 return pset->numChipset; 888 pset++; 889 } 890 891 return -1; 892} 893 894static void SavageDoDDC(ScrnInfoPtr pScrn) 895{ 896 SavagePtr psav= SAVPTR(pScrn); 897 pointer ddc; 898 899 /* Do the DDC dance. */ /* S3/VIA's DDC code */ 900 ddc = xf86LoadSubModule(pScrn, "ddc"); 901 if (ddc) { 902 xf86LoaderReqSymLists(ddcSymbols, NULL); 903 switch( psav->Chipset ) { 904 case S3_SAVAGE3D: 905 case S3_SAVAGE_MX: 906 case S3_SUPERSAVAGE: 907 case S3_SAVAGE2000: 908 psav->DDCPort = 0xAA; 909 psav->I2CPort = 0xA0; 910 break; 911 912 case S3_SAVAGE4: 913 case S3_PROSAVAGE: 914 case S3_TWISTER: 915 case S3_PROSAVAGEDDR: 916 psav->DDCPort = 0xB1; 917 psav->I2CPort = 0xA0; 918 break; 919 } 920 921 if (!SavageDDC1(pScrn->scrnIndex)) { 922 /* DDC1 failed,switch to DDC2 */ 923 if (xf86LoadSubModule(pScrn, "i2c")) { 924 xf86LoaderReqSymLists(i2cSymbols,NULL); 925 if (SavageI2CInit(pScrn)) { 926 unsigned char tmp; 927 928 InI2CREG(tmp,psav->DDCPort); 929 OutI2CREG(tmp | 0x13,psav->DDCPort); 930 xf86SetDDCproperties(pScrn,xf86PrintEDID( 931 xf86DoEDID_DDC2(pScrn->scrnIndex,psav->I2C))); 932 OutI2CREG(tmp,psav->DDCPort); 933 } 934 } 935 } 936 } 937} 938 939/* Copied from ddc/Property.c via nv */ 940static DisplayModePtr 941SavageModesAdd(DisplayModePtr Modes, DisplayModePtr Additions) 942{ 943 if (!Modes) { 944 if (Additions) 945 return Additions; 946 else 947 return NULL; 948 } 949 950 if (Additions) { 951 DisplayModePtr Mode = Modes; 952 953 while (Mode->next) 954 Mode = Mode->next; 955 956 Mode->next = Additions; 957 Additions->prev = Mode; 958 } 959 960 return Modes; 961} 962 963/* borrowed from nv */ 964static void 965SavageAddPanelMode(ScrnInfoPtr pScrn) 966{ 967 SavagePtr psav= SAVPTR(pScrn); 968 DisplayModePtr Mode = NULL; 969 970 Mode = xf86CVTMode(psav->PanelX, psav->PanelY, 60.00, TRUE, FALSE); 971 Mode->type = M_T_DRIVER | M_T_PREFERRED; 972 pScrn->monitor->Modes = SavageModesAdd(pScrn->monitor->Modes, Mode); 973 974 if ((pScrn->monitor->nHsync == 0) && 975 (pScrn->monitor->nVrefresh == 0)) { 976 if (!Mode->HSync) 977 Mode->HSync = ((float) Mode->Clock ) / ((float) Mode->HTotal); 978 if (!Mode->VRefresh) 979 Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) / 980 ((float) (Mode->HTotal * Mode->VTotal)); 981 982 if (Mode->HSync < pScrn->monitor->hsync[0].lo) 983 pScrn->monitor->hsync[0].lo = Mode->HSync; 984 if (Mode->HSync > pScrn->monitor->hsync[0].hi) 985 pScrn->monitor->hsync[0].hi = Mode->HSync; 986 if (Mode->VRefresh < pScrn->monitor->vrefresh[0].lo) 987 pScrn->monitor->vrefresh[0].lo = Mode->VRefresh; 988 if (Mode->VRefresh > pScrn->monitor->vrefresh[0].hi) 989 pScrn->monitor->vrefresh[0].hi = Mode->VRefresh; 990 991 pScrn->monitor->nHsync = 1; 992 pScrn->monitor->nVrefresh = 1; 993 } 994} 995 996static void SavageGetPanelInfo(ScrnInfoPtr pScrn) 997{ 998 SavagePtr psav= SAVPTR(pScrn); 999 vgaHWPtr hwp; 1000 unsigned char cr6b; 1001 int panelX, panelY; 1002 char * sTechnology = "Unknown"; 1003 enum ACTIVE_DISPLAYS { /* These are the bits in CR6B */ 1004 ActiveCRT = 0x01, 1005 ActiveLCD = 0x02, 1006 ActiveTV = 0x04, 1007 ActiveCRT2 = 0x20, 1008 ActiveDUO = 0x80 1009 }; 1010 1011 hwp = VGAHWPTR(pScrn); 1012 1013 /* Check LCD panel information */ 1014 1015 cr6b = hwp->readCrtc( hwp, 0x6b ); 1016 1017 panelX = (hwp->readSeq(hwp, 0x61) + 1018 ((hwp->readSeq(hwp, 0x66) & 0x02) << 7) + 1) * 8; 1019 panelY = hwp->readSeq(hwp, 0x69) + 1020 ((hwp->readSeq(hwp, 0x6e) & 0x70) << 4) + 1; 1021 1022 1023 /* OK, I admit it. I don't know how to limit the max dot clock 1024 * for LCD panels of various sizes. I thought I copied the formula 1025 * from the BIOS, but many users have informed me of my folly. 1026 * 1027 * Instead, I'll abandon any attempt to automatically limit the 1028 * clock, and add an LCDClock option to XF86Config. Some day, 1029 * I should come back to this. 1030 */ 1031 1032 1033 if( (hwp->readSeq( hwp, 0x39 ) & 0x03) == 0 ) 1034 { 1035 sTechnology = "TFT"; 1036 } 1037 else if( (hwp->readSeq( hwp, 0x30 ) & 0x01) == 0 ) 1038 { 1039 sTechnology = "DSTN"; 1040 } 1041 else 1042 { 1043 sTechnology = "STN"; 1044 } 1045 1046 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1047 "%dx%d %s LCD panel detected %s\n", 1048 panelX, panelY, sTechnology, 1049 cr6b & ActiveLCD ? "and active" : "but not active"); 1050 1051 if( cr6b & ActiveLCD ) { 1052 /* If the LCD is active and panel expansion is enabled, */ 1053 /* we probably want to kill the HW cursor. */ 1054 1055 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1056 "- Limiting video mode to %dx%d\n", 1057 panelX, panelY ); 1058 1059 psav->PanelX = panelX; 1060 psav->PanelY = panelY; 1061 1062 if( psav->LCDClock > 0.0 ) 1063 { 1064 psav->maxClock = psav->LCDClock * 1000.0; 1065 xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, 1066 "- Limiting dot clock to %1.2f MHz\n", 1067 psav->LCDClock ); 1068 } 1069 } else { 1070 psav->DisplayType = MT_CRT; 1071 } 1072} 1073 1074 1075static Bool SavagePreInit(ScrnInfoPtr pScrn, int flags) 1076{ 1077 EntityInfoPtr pEnt; 1078 SavagePtr psav; 1079 MessageType from = X_DEFAULT; 1080 int i; 1081 ClockRangePtr clockRanges; 1082 char *s = NULL; 1083 unsigned char config1, m, n, n1, n2, sr8, cr66 = 0, tmp; 1084 int mclk; 1085 vgaHWPtr hwp; 1086 int vgaCRIndex, vgaCRReg; 1087 Bool dvi; 1088 1089 TRACE(("SavagePreInit(%d)\n", flags)); 1090 1091 gpScrn = pScrn; 1092 1093 if (flags & PROBE_DETECT) { 1094 SavageProbeDDC( pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index ); 1095 return TRUE; 1096 } 1097 1098 if (!xf86LoadSubModule(pScrn, "vgahw")) 1099 return FALSE; 1100 1101 xf86LoaderReqSymLists(vgaHWSymbols, NULL); 1102 if (!vgaHWGetHWRec(pScrn)) 1103 return FALSE; 1104 1105#if 0 1106 /* Here we can alter the number of registers saved and restored by the 1107 * standard vgaHWSave and Restore routines. 1108 */ 1109 vgaHWSetRegCounts( pScrn, VGA_NUM_CRTC, VGA_NUM_SEQ, VGA_NUM_GFX, VGA_NUM_ATTR ); 1110#endif 1111 1112 pScrn->monitor = pScrn->confScreen->monitor; 1113 1114 /* 1115 * We support depths of 8, 15, 16 and 24. 1116 * We support bpp of 8, 16, and 32. 1117 */ 1118 1119 if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb)) 1120 return FALSE; 1121 else { 1122 int requiredBpp; 1123 int altBpp = 0; 1124 1125 switch (pScrn->depth) { 1126 case 8: 1127 case 16: 1128 requiredBpp = pScrn->depth; 1129 break; 1130 case 15: 1131 requiredBpp = 16; 1132 break; 1133 case 24: 1134 requiredBpp = 32; 1135 altBpp = 24; 1136 break; 1137 1138 default: 1139 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1140 "Given depth (%d) is not supported by this driver\n", 1141 pScrn->depth); 1142 return FALSE; 1143 } 1144 1145 if( 1146 (pScrn->bitsPerPixel != requiredBpp) && 1147 (pScrn->bitsPerPixel != altBpp) 1148 ) { 1149 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1150 "Depth %d must specify %d bpp; %d was given\n", 1151 pScrn->depth, requiredBpp, pScrn->bitsPerPixel ); 1152 return FALSE; 1153 } 1154 } 1155 1156 xf86PrintDepthBpp(pScrn); 1157 1158 if (pScrn->depth > 8) { 1159 rgb zeros = {0, 0, 0}; 1160 1161 if (!xf86SetWeight(pScrn, zeros, zeros)) 1162 return FALSE; 1163 else { 1164 /* TODO check weight returned is supported */ 1165 ; 1166 } 1167 } 1168 1169 if (!xf86SetDefaultVisual(pScrn, -1)) { 1170 return FALSE; 1171 } else { 1172 /* We don't currently support DirectColor at 16bpp */ 1173 if (pScrn->bitsPerPixel == 16 && pScrn->defaultVisual != TrueColor) { 1174 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual" 1175 " (%s) is not supported at depth %d\n", 1176 xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); 1177 return FALSE; 1178 } 1179 } 1180 1181 pScrn->progClock = TRUE; 1182 1183 if (!SavageGetRec(pScrn)) 1184 return FALSE; 1185 psav = SAVPTR(pScrn); 1186 1187 hwp = VGAHWPTR(pScrn); 1188 vgaHWGetIOBase(hwp); 1189 psav->vgaIOBase = hwp->IOBase; 1190 1191 xf86CollectOptions(pScrn, NULL); 1192 1193 if (pScrn->depth == 8) 1194 pScrn->rgbBits = 8; 1195 1196 if (!(psav->Options = xalloc(sizeof(SavageOptions)))) 1197 return FALSE; 1198 memcpy(psav->Options, SavageOptions, sizeof(SavageOptions)); 1199 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, psav->Options); 1200 1201 xf86GetOptValBool(psav->Options, OPTION_PCI_BURST, &psav->pci_burst); 1202 1203 if (psav->pci_burst) { 1204 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1205 "Option: pci_burst - PCI burst read enabled\n"); 1206 } 1207 1208 psav->NoPCIRetry = 1; /* default */ 1209 if (xf86ReturnOptValBool(psav->Options, OPTION_PCI_RETRY, FALSE)) { 1210 if (xf86ReturnOptValBool(psav->Options, OPTION_PCI_BURST, FALSE)) { 1211 psav->NoPCIRetry = 0; 1212 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: pci_retry\n"); 1213 } else 1214 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"pci_retry\" option requires \"pci_burst\"\n"); 1215 } 1216 1217 xf86GetOptValBool( psav->Options, OPTION_SHADOW_FB, &psav->shadowFB ); 1218 if (psav->shadowFB) { 1219 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: shadow FB enabled\n"); 1220 } 1221 1222 psav->primStreamBpp = pScrn->bitsPerPixel; 1223 1224 if ((s = xf86GetOptValString(psav->Options, OPTION_ROTATE))) { 1225 if(!xf86NameCmp(s, "CW")) { 1226 /* accel is disabled below for shadowFB */ 1227 /* RandR is disabled when the Rotate option is used (does 1228 * not work well together and scrambles the screen) */ 1229 1230 psav->shadowFB = TRUE; 1231 psav->rotate = 1; 1232 xf86DisableRandR(); 1233 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1234 "Rotating screen clockwise" 1235 "- acceleration and RandR disabled\n"); 1236 } else if(!xf86NameCmp(s, "CCW")) { 1237 psav->shadowFB = TRUE; 1238 psav->rotate = -1; 1239 xf86DisableRandR(); 1240 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1241 "Rotating screen counter clockwise" 1242 " - acceleration and RandR disabled\n"); 1243 1244 } else { 1245 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid" 1246 "value for Option \"Rotate\"\n", s); 1247 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1248 "Valid options are \"CW\" or \"CCW\"\n"); 1249 } 1250 } 1251 1252 if (xf86GetOptValBool(psav->Options, OPTION_NOACCEL, &psav->NoAccel)) 1253 xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, 1254 "Option: NoAccel - Acceleration Disabled\n"); 1255 1256 if (psav->shadowFB && !psav->NoAccel) { 1257 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1258 "HW acceleration not supported with \"shadowFB\".\n"); 1259 psav->NoAccel = TRUE; 1260 } 1261 1262 if(!psav->NoAccel) { 1263 from = X_DEFAULT; 1264 char *strptr; 1265 if((strptr = (char *)xf86GetOptValString(psav->Options, OPTION_ACCELMETHOD))) { 1266 if(!xf86NameCmp(strptr,"XAA")) { 1267 from = X_CONFIG; 1268 psav->useEXA = FALSE; 1269 } else if(!xf86NameCmp(strptr,"EXA")) { 1270 from = X_CONFIG; 1271 psav->useEXA = TRUE; 1272 } 1273 } 1274 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration architecture\n", 1275 psav->useEXA ? "EXA" : "XAA"); 1276 } 1277 1278 if ((s = xf86GetOptValString(psav->Options, OPTION_OVERLAY))) { 1279 1280 if (psav->shadowFB) { 1281 xf86DrvMsg(pScrn->scrnIndex,X_INFO, 1282 "Option \"Overlay\" not supported with shadowFB\n"); 1283 } else { 1284 if (pScrn->depth == 8) { 1285 if (!*s || !xf86NameCmp(s, "24")) { 1286 psav->overlayDepth = 24; 1287 psav->NoAccel = TRUE; /* Preliminary */ 1288 pScrn->colorKey = TRANSPARENCY_KEY; 1289 pScrn->overlayFlags = OVERLAY_8_32_DUALFB; 1290 } else if (!xf86NameCmp(s, "16")) { 1291 psav->overlayDepth = 16; 1292 psav->NoAccel = TRUE; /* Preliminary */ 1293 pScrn->colorKey = TRANSPARENCY_KEY; 1294 pScrn->overlayFlags = OVERLAY_8_32_DUALFB; 1295 } else { 1296 xf86DrvMsg(pScrn->scrnIndex,X_WARNING,"Wrong argument: " 1297 "\"%s\" Ingnoring\n",s); 1298 } 1299 } else if (pScrn->depth != 15) { 1300 psav->overlayDepth = 8; 1301 psav->NoAccel = TRUE; /* Preliminary */ 1302 pScrn->colorKey = TRANSPARENCY_KEY; 1303 pScrn->overlayFlags = OVERLAY_8_32_DUALFB; 1304 if (*s && (xf86NameCmp(s, "8"))) 1305 xf86DrvMsg(pScrn->scrnIndex,X_WARNING,"Wrong argument: " 1306 "\"%s\" for depth %i overlay depth must be 8\n", 1307 s,pScrn->depth); 1308 } else { 1309 xf86DrvMsg(pScrn->scrnIndex,X_WARNING,"Overlay not " 1310 "supported for depth 15\n"); 1311 } 1312 if (psav->overlayDepth) { 1313 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"%i/%i Overlay enabled\n", 1314 pScrn->depth,psav->overlayDepth); 1315 psav->primStreamBpp = 8; 1316 } 1317 } 1318 } 1319 1320 if (pScrn->bitsPerPixel == 24 && !psav->NoAccel) { 1321 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1322 "HW acceleration not possible with depth 32 and bpp 24.\n"); 1323 psav->NoAccel = TRUE; 1324 } 1325 1326 /* 1327 * The SWCursor setting takes priority over HWCursor. The default 1328 * if neither is specified is HW, unless ShadowFB is specified, 1329 * then SW. 1330 */ 1331 1332 from = X_DEFAULT; 1333 psav->hwcursor = psav->shadowFB ? FALSE : TRUE; 1334 if (xf86GetOptValBool(psav->Options, OPTION_HWCURSOR, &psav->hwcursor)) 1335 from = X_CONFIG; 1336 if (xf86ReturnOptValBool(psav->Options, OPTION_SWCURSOR, FALSE)) { 1337 psav->hwcursor = FALSE; 1338 from = X_CONFIG; 1339 } 1340 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", 1341 psav->hwcursor ? "HW" : "SW"); 1342 1343 from = X_DEFAULT; 1344 psav->UseBIOS = TRUE; 1345 if (xf86GetOptValBool(psav->Options, OPTION_USEBIOS, &psav->UseBIOS) ) 1346 from = X_CONFIG; 1347 xf86DrvMsg(pScrn->scrnIndex, from, "%ssing video BIOS to set modes\n", 1348 psav->UseBIOS ? "U" : "Not u" ); 1349 1350 psav->LCDClock = 0.0; 1351 if( xf86GetOptValFreq( psav->Options, OPTION_LCDCLOCK, OPTUNITS_MHZ, &psav->LCDClock ) ) 1352 xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, 1353 "Option: LCDClock %1.2f MHz\n", psav->LCDClock ); 1354 1355 if( xf86GetOptValBool( psav->Options, OPTION_SHADOW_STATUS, &psav->ShadowStatus)) { 1356 xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, 1357 "Option: ShadowStatus %sabled\n", psav->ShadowStatus ? "en" : "dis" ); 1358 psav->ForceShadowStatus = TRUE; 1359 } else 1360 psav->ForceShadowStatus = FALSE; 1361 /* If ShadowStatus is off it will be automatically enabled for DRI. 1362 * If DRI initialization fails fall back to ConfigShadowStatus. */ 1363 psav->ConfigShadowStatus = psav->ShadowStatus; 1364 1365 if( xf86GetOptValBool( psav->Options, OPTION_CRT_ONLY, &psav->CrtOnly)) 1366 xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, 1367 "Option: CrtOnly enabled\n" ); 1368 1369 if( xf86GetOptValBool( psav->Options, OPTION_TV_ON, &psav->TvOn)) { 1370 psav->PAL = FALSE; 1371 SavageGetTvMaxSize(psav); 1372 } 1373 1374 if( xf86GetOptValBool( psav->Options, OPTION_TV_PAL, &psav->PAL)) { 1375 SavageGetTvMaxSize(psav); 1376 psav->TvOn = TRUE; 1377 } 1378 1379 if( psav->TvOn ) 1380 xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, 1381 "TV enabled in %s format\n", 1382 psav->PAL ? "PAL" : "NTSC" ); 1383 1384 psav->ForceInit = 0; 1385 if( xf86GetOptValBool( psav->Options, OPTION_FORCE_INIT, &psav->ForceInit)) 1386 xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, 1387 "Option: ForceInit enabled\n" ); 1388 1389 if (pScrn->numEntities > 1) { 1390 SavageFreeRec(pScrn); 1391 return FALSE; 1392 } 1393 1394 pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 1395 if (pEnt->resources) { 1396 xfree(pEnt); 1397 SavageFreeRec(pScrn); 1398 return FALSE; 1399 } 1400 psav->EntityIndex = pEnt->index; 1401 1402 if (xf86LoadSubModule(pScrn, "vbe")) { 1403 xf86LoaderReqSymLists(vbeSymbols, NULL); 1404 psav->pVbe = VBEInit(NULL, pEnt->index); 1405 } 1406 1407 psav->PciInfo = xf86GetPciInfoForEntity(pEnt->index); 1408 xf86RegisterResources(pEnt->index, NULL, ResNone); 1409 xf86SetOperatingState(resVgaIo, pEnt->index, ResUnusedOpr); 1410 xf86SetOperatingState(resVgaMem, pEnt->index, ResDisableOpr); 1411 1412 from = X_DEFAULT; 1413 if (pEnt->device->chipset && *pEnt->device->chipset) { 1414 pScrn->chipset = pEnt->device->chipset; 1415 psav->ChipId = pEnt->device->chipID; 1416 psav->Chipset = xf86StringToToken(SavageChipsets, pScrn->chipset); 1417 from = X_CONFIG; 1418 } else if (pEnt->device->chipID >= 0) { 1419 psav->ChipId = pEnt->device->chipID; 1420 psav->Chipset = LookupChipID(SavagePciChipsets, psav->ChipId); 1421 pScrn->chipset = (char *)xf86TokenToString(SavageChipsets, 1422 psav->Chipset); 1423 from = X_CONFIG; 1424 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", 1425 pEnt->device->chipID); 1426 } else { 1427 from = X_PROBED; 1428 psav->ChipId = psav->PciInfo->chipType; 1429 psav->Chipset = LookupChipID(SavagePciChipsets, psav->ChipId); 1430 pScrn->chipset = (char *)xf86TokenToString(SavageChipsets, 1431 psav->Chipset); 1432 } 1433 1434 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Chip: id %04x, \"%s\"\n", 1435 psav->ChipId, xf86TokenToString( SavageChips, psav->ChipId ) ); 1436 1437 if (pEnt->device->chipRev >= 0) { 1438 psav->ChipRev = pEnt->device->chipRev; 1439 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 1440 psav->ChipRev); 1441 } else 1442 psav->ChipRev = psav->PciInfo->chipRev; 1443 1444 xf86DrvMsg(pScrn->scrnIndex, from, "Engine: \"%s\"\n", pScrn->chipset); 1445 1446 if (pEnt->device->videoRam != 0) 1447 pScrn->videoRam = pEnt->device->videoRam; 1448 1449 xfree(pEnt); 1450 1451 psav->PciTag = pciTag(psav->PciInfo->bus, psav->PciInfo->device, 1452 psav->PciInfo->func); 1453 1454 1455 /* Set AGP Mode from config */ 1456 /* We support 1X 2X and 4X */ 1457#ifdef XF86DRI 1458 /* AGP/PCI (FK: copied from radeon_driver.c) */ 1459 /* Proper autodetection of an AGP capable device requires examining 1460 * PCI config registers to determine if the device implements extended 1461 * PCI capabilities, and then walking the capability list as indicated 1462 * in the PCI 2.2 and AGP 2.0 specifications, to determine if AGP 1463 * capability is present. The procedure is outlined as follows: 1464 * 1465 * 1) Test bit 4 (CAP_LIST) of the PCI status register of the device 1466 * to determine wether or not this device implements any extended 1467 * capabilities. If this bit is zero, then the device is a PCI 2.1 1468 * or earlier device and is not AGP capable, and we can conclude it 1469 * to be a PCI device. 1470 * 1471 * 2) If bit 4 of the status register is set, then the device implements 1472 * extended capabilities. There is an 8 bit wide capabilities pointer 1473 * register located at offset 0x34 in PCI config space which points to 1474 * the first capability in a linked list of extended capabilities that 1475 * this device implements. The lower two bits of this register are 1476 * reserved and MBZ so must be masked out. 1477 * 1478 * 3) The extended capabilities list is formed by one or more extended 1479 * capabilities structures which are aligned on DWORD boundaries. 1480 * The first byte of the structure is the capability ID (CAP_ID) 1481 * indicating what extended capability this structure refers to. The 1482 * second byte of the structure is an offset from the beginning of 1483 * PCI config space pointing to the next capability in the linked 1484 * list (NEXT_PTR) or NULL (0x00) at the end of the list. The lower 1485 * two bits of this pointer are reserved and MBZ. By examining the 1486 * CAP_ID of each capability and walking through the list, we will 1487 * either find the AGP_CAP_ID (0x02) indicating this device is an 1488 * AGP device, or we'll reach the end of the list, indicating it is 1489 * a PCI device. 1490 * 1491 * Mike A. Harris <mharris@redhat.com> 1492 * 1493 * References: 1494 * - PCI Local Bus Specification Revision 2.2, Chapter 6 1495 * - AGP Interface Specification Revision 2.0, Section 6.1.5 1496 */ 1497 1498 psav->IsPCI = TRUE; 1499 1500 if (pciReadLong(psav->PciTag, PCI_CMD_STAT_REG) & SAVAGE_CAP_LIST) { 1501 CARD32 cap_ptr, cap_id; 1502 1503 cap_ptr = pciReadLong(psav->PciTag, 1504 SAVAGE_CAPABILITIES_PTR_PCI_CONFIG) 1505 & SAVAGE_CAP_PTR_MASK; 1506 1507 while(cap_ptr != SAVAGE_CAP_ID_NULL) { 1508 cap_id = pciReadLong(psav->PciTag, cap_ptr); 1509 if ((cap_id & 0xff) == SAVAGE_CAP_ID_AGP) { 1510 psav->IsPCI = FALSE; 1511 break; 1512 } 1513 cap_ptr = (cap_id >> 8) & SAVAGE_CAP_PTR_MASK; 1514 } 1515 } 1516 1517 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "%s card detected\n", 1518 (psav->IsPCI) ? "PCI" : "AGP"); 1519 1520 if ((s = xf86GetOptValString(psav->Options, OPTION_BUS_TYPE))) { 1521 if (strcmp(s, "AGP") == 0) { 1522 if (psav->IsPCI) { 1523 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1524 "BusType AGP not available on PCI card\n"); 1525 } else { 1526 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "BusType set to AGP\n"); 1527 } 1528 } else if (strcmp(s, "PCI") == 0) { 1529 psav->IsPCI = TRUE; 1530 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "BusType set to PCI\n"); 1531 } else { 1532 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1533 "Invalid BusType option, using %s DMA\n", 1534 psav->IsPCI ? "PCI" : "AGP"); 1535 } 1536 } 1537 1538 psav->AgpDMA = !psav->IsPCI; 1539 if ((s = xf86GetOptValString(psav->Options, OPTION_DMA_TYPE))) { 1540 if (strcmp(s, "AGP") == 0) { 1541 if (psav->IsPCI) { 1542 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1543 "AGP DMA not available on PCI card, using PCI DMA\n"); 1544 } else { 1545 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using AGP DMA\n"); 1546 } 1547 } else if (strcmp(s, "PCI") == 0) { 1548 psav->AgpDMA = FALSE; 1549 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using PCI DMA\n"); 1550 } else { 1551 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1552 "Invalid DmaType option, using %s DMA\n", 1553 psav->AgpDMA ? "AGP" : "PCI"); 1554 } 1555 } else { 1556 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, 1557 "Using %s DMA\n", psav->AgpDMA ? "AGP" : "PCI"); 1558 } 1559 1560 psav->CommandDMA = TRUE; 1561 psav->VertexDMA = TRUE; 1562 from = X_DEFAULT; 1563 if ((s = xf86GetOptValString(psav->Options, OPTION_DMA_MODE))) { 1564 from = X_CONFIG; 1565 if (strcmp(s, "Command") == 0) 1566 psav->VertexDMA = FALSE; 1567 else if (strcmp(s, "Vertex") == 0) 1568 psav->CommandDMA = FALSE; 1569 else if (strcmp(s, "None") == 0) 1570 psav->VertexDMA = psav->CommandDMA = FALSE; 1571 else if (strcmp(s, "Any") != 0) { 1572 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Invalid DmaMode option\n"); 1573 from = X_DEFAULT; 1574 } 1575 } 1576 if (psav->CommandDMA && S3_SAVAGE3D_SERIES(psav->Chipset)) { 1577 xf86DrvMsg(pScrn->scrnIndex, from == X_CONFIG ? X_WARNING : X_INFO, 1578 "Savage3D/MX/IX does not support command DMA.\n"); 1579 psav->CommandDMA = FALSE; 1580 } 1581 if ((psav->CommandDMA || psav->VertexDMA) && 1582 psav->Chipset == S3_SUPERSAVAGE) { 1583 xf86DrvMsg(pScrn->scrnIndex, from == X_CONFIG ? X_WARNING : X_INFO, 1584 "DMA is not supported on SuperSavages.\n"); 1585 psav->CommandDMA = psav->VertexDMA = FALSE; 1586 } 1587 if (psav->CommandDMA && psav->VertexDMA) 1588 xf86DrvMsg(pScrn->scrnIndex, from, 1589 "Will try command and vertex DMA mode\n"); 1590 else if (psav->CommandDMA && !psav->VertexDMA) 1591 xf86DrvMsg(pScrn->scrnIndex, from, 1592 "Will try only command DMA mode\n"); 1593 else if (!psav->CommandDMA && psav->VertexDMA) 1594 xf86DrvMsg(pScrn->scrnIndex, from, 1595 "Will try only vertex DMA mode\n"); 1596 else 1597 xf86DrvMsg(pScrn->scrnIndex, from, 1598 "DMA disabled\n"); 1599 1600 if (!psav->IsPCI) { 1601 from = X_DEFAULT; 1602 psav->agpMode = SAVAGE_DEFAULT_AGP_MODE; 1603 /*psav->agpMode = SAVAGE_MAX_AGP_MODE;*/ 1604 psav->agpSize = 16; 1605 1606 if (xf86GetOptValInteger(psav->Options, 1607 OPTION_AGP_MODE, &(psav->agpMode))) { 1608 if (psav->agpMode < 1) { 1609 psav->agpMode = 1; 1610 } 1611 if (psav->agpMode > SAVAGE_MAX_AGP_MODE) { 1612 psav->agpMode = SAVAGE_MAX_AGP_MODE; 1613 } 1614 if ((psav->agpMode > 2) && 1615 (psav->Chipset == S3_SAVAGE3D || 1616 psav->Chipset == S3_SAVAGE_MX)) 1617 psav->agpMode = 2; /* old savages only support 2x */ 1618 from = X_CONFIG; 1619 } 1620 1621 xf86DrvMsg(pScrn->scrnIndex, from, "Using AGP %dx mode\n", 1622 psav->agpMode); 1623 1624 from = X_DEFAULT; 1625 if (xf86GetOptValInteger(psav->Options, 1626 OPTION_AGP_SIZE, (int *)&(psav->agpSize))) { 1627 switch (psav->agpSize) { 1628 case 4: 1629 case 8: 1630 case 16: 1631 case 32: 1632 case 64: 1633 case 128: 1634 case 256: 1635 from = X_CONFIG; 1636 break; 1637 default: 1638 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1639 "Illegal AGP size: %d MB, defaulting to 16 MB\n", psav->agpSize); 1640 psav->agpSize = 16; 1641 } 1642 } 1643 1644 xf86DrvMsg(pScrn->scrnIndex, from, 1645 "Using %d MB AGP aperture\n", psav->agpSize); 1646 } else { 1647 psav->agpMode = 0; 1648 psav->agpSize = 0; 1649 } 1650 1651#endif 1652 1653 /* we can use Option "DisableTile TRUE" to disable tile mode */ 1654 psav->bDisableTile = FALSE; 1655 if (xf86GetOptValBool(psav->Options, OPTION_DISABLE_TILE,&psav->bDisableTile)) { 1656 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1657 "Option: %s Tile Mode and Program it \n",(psav->bDisableTile?"Disable":"Enable")); 1658 } 1659 1660#ifdef XF86DRI 1661 /* disabled by default...doesn't seem to work */ 1662 psav->bDisableXvMC = TRUE; /* if you want to free up more mem for DRI,etc. */ 1663 if (xf86GetOptValBool(psav->Options, OPTION_DISABLE_XVMC, &psav->bDisableXvMC)) { 1664 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1665 "Option: %s Hardware XvMC support\n",(psav->bDisableXvMC?"Disable":"Enable")); 1666 } 1667#endif 1668 1669 psav->disableCOB = FALSE; /* if you are having problems on savage4+ */ 1670 if (xf86GetOptValBool(psav->Options, OPTION_DISABLE_COB, &psav->disableCOB)) { 1671 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1672 "Option: %s the COB\n",(psav->disableCOB?"Disable":"Enable")); 1673 } 1674 if (psav->Chipset == S3_PROSAVAGE || 1675 psav->Chipset == S3_TWISTER || 1676 psav->Chipset == S3_PROSAVAGEDDR) 1677 psav->BCIforXv = TRUE; 1678 else 1679 psav->BCIforXv = FALSE; /* use the BCI for Xv */ 1680 if (xf86GetOptValBool(psav->Options, OPTION_BCI_FOR_XV, &psav->BCIforXv)) { 1681 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1682 "Option: %s use of the BCI for Xv\n",(psav->BCIforXv?"Enable":"Disable")); 1683 } 1684 psav->dvi = FALSE; 1685 if (xf86GetOptValBool(psav->Options, OPTION_DVI, &psav->dvi)) { 1686 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1687 "%s DVI port support (Savage4 only)\n",(psav->dvi?"Force":"Disable")); 1688 } 1689 1690 /* Add more options here. */ 1691 1692 1693 psav = SAVPTR(pScrn); 1694 psav->IsSecondary = FALSE; 1695 psav->IsPrimary = FALSE; 1696 psav->pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]); 1697 1698 if (xf86IsEntityShared(psav->pEnt->index)) { 1699 if (xf86IsPrimInitDone(psav->pEnt->index)) { 1700 1701 SavageEntPtr pSavageEnt = SavageEntPriv(pScrn); 1702 1703 psav->IsSecondary = TRUE; 1704 pSavageEnt->pSecondaryScrn = pScrn; 1705 psav->TvOn = pSavageEnt->TvOn; 1706 } else { 1707 SavageEntPtr pSavageEnt = SavageEntPriv(pScrn); 1708 1709 xf86SetPrimInitDone(psav->pEnt->index); 1710 1711 psav->IsPrimary = TRUE; 1712 pSavageEnt->pPrimaryScrn = pScrn; 1713 pSavageEnt->TvOn = psav->TvOn; 1714 } 1715 } 1716 1717 switch(psav->Chipset) { 1718 case S3_SAVAGE_MX: 1719 case S3_SUPERSAVAGE: 1720 psav->HasCRTC2 = TRUE; 1721 break; 1722 default: 1723 psav->HasCRTC2 = FALSE; 1724 } 1725 1726 if ((psav->IsSecondary || psav->IsPrimary) && !psav->UseBIOS) { 1727 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "BIOS currently required for Dualhead mode setting.\n"); 1728 return FALSE; 1729 } 1730 1731 if (psav->IsSecondary && 1732 (pScrn->bitsPerPixel > 16) && 1733 !psav->NoAccel && 1734 (psav->Chipset == S3_SAVAGE_MX)) { 1735 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No acceleration in Dualhead mode at depth 24\n"); 1736 return FALSE; 1737 } 1738 1739 /* maybe throw in some more sanity checks here */ 1740 1741 if (!SavageMapMem(pScrn)) { 1742 SavageFreeRec(pScrn); 1743 vbeFree(psav->pVbe); 1744 psav->pVbe = NULL; 1745 return FALSE; 1746 } 1747 1748 vgaCRIndex = psav->vgaIOBase + 4; 1749 vgaCRReg = psav->vgaIOBase + 5; 1750 1751 xf86EnableIO(); 1752 /* unprotect CRTC[0-7] */ 1753 VGAOUT8(vgaCRIndex, 0x11); 1754 tmp = VGAIN8(vgaCRReg); 1755 VGAOUT8(vgaCRReg, tmp & 0x7f); 1756 1757 /* unlock extended regs */ 1758 VGAOUT16(vgaCRIndex, 0x4838); 1759 VGAOUT16(vgaCRIndex, 0xa039); 1760 VGAOUT16(0x3c4, 0x0608); 1761 1762 VGAOUT8(vgaCRIndex, 0x40); 1763 tmp = VGAIN8(vgaCRReg); 1764 VGAOUT8(vgaCRReg, tmp & ~0x01); 1765 1766 /* unlock sys regs */ 1767 VGAOUT8(vgaCRIndex, 0x38); 1768 VGAOUT8(vgaCRReg, 0x48); 1769 1770 { 1771 Gamma zeros = {0.0, 0.0, 0.0}; 1772 1773 if (!xf86SetGamma(pScrn, zeros)) { 1774 vbeFree(psav->pVbe); 1775 psav->pVbe = NULL; 1776 SavageFreeRec(pScrn); 1777 return FALSE; 1778 } 1779 } 1780 1781 /* Unlock system registers. */ 1782 VGAOUT16(vgaCRIndex, 0x4838); 1783 1784 /* Next go on to detect amount of installed ram */ 1785 1786 VGAOUT8(vgaCRIndex, 0x36); /* for register CR36 (CONFG_REG1), */ 1787 config1 = VGAIN8(vgaCRReg); /* get amount of vram installed */ 1788 1789 /* Compute the amount of video memory and offscreen memory. */ 1790 1791 if (!pScrn->videoRam) { 1792 static const unsigned char RamSavage3D[] = { 8, 4, 4, 2 }; 1793 static unsigned char RamSavage4[] = { 2, 4, 8, 12, 16, 32, 64, 32 }; 1794 static const unsigned char RamSavageMX[] = { 2, 8, 4, 16, 8, 16, 4, 16 }; 1795 static const unsigned char RamSavageNB[] = { 0, 2, 4, 8, 16, 32, 16, 2 }; 1796 1797 switch( psav->Chipset ) { 1798 case S3_SAVAGE3D: 1799 pScrn->videoRam = RamSavage3D[ (config1 & 0xC0) >> 6 ] * 1024; 1800 break; 1801 1802 case S3_SAVAGE4: 1803 /* 1804 * The Savage4 has one ugly special case to consider. On 1805 * systems with 4 banks of 2Mx32 SDRAM, the BIOS says 4MB 1806 * when it really means 8MB. Why do it the same when you 1807 * can do it different... 1808 */ 1809 VGAOUT8(vgaCRIndex, 0x68); /* memory control 1 */ 1810 if( (VGAIN8(vgaCRReg) & 0xC0) == (0x01 << 6) ) 1811 RamSavage4[1] = 8; 1812 1813 /*FALLTHROUGH*/ 1814 1815 case S3_SAVAGE2000: 1816 pScrn->videoRam = RamSavage4[ (config1 & 0xE0) >> 5 ] * 1024; 1817 break; 1818 1819 case S3_SAVAGE_MX: 1820 case S3_SUPERSAVAGE: 1821 pScrn->videoRam = RamSavageMX[ (config1 & 0x0E) >> 1 ] * 1024; 1822 break; 1823 1824 case S3_PROSAVAGE: 1825 case S3_PROSAVAGEDDR: 1826 case S3_TWISTER: 1827 pScrn->videoRam = RamSavageNB[ (config1 & 0xE0) >> 5 ] * 1024; 1828 break; 1829 1830 default: 1831 /* How did we get here? */ 1832 pScrn->videoRam = 0; 1833 break; 1834 } 1835 1836 psav->videoRambytes = pScrn->videoRam * 1024; 1837 1838 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1839 "probed videoram: %dk\n", 1840 pScrn->videoRam); 1841 } else { 1842 psav->videoRambytes = pScrn->videoRam * 1024; 1843 1844 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1845 "videoram = %dk\n", 1846 pScrn->videoRam); 1847 } 1848 1849 /* Get video RAM */ 1850 if( !pScrn->videoRam && psav->pVbe ) 1851 { 1852 /* If VBE is available, ask it about onboard memory. */ 1853 1854 VbeInfoBlock* vib; 1855 1856 vib = VBEGetVBEInfo( psav->pVbe ); 1857 pScrn->videoRam = vib->TotalMemory * 64; 1858 VBEFreeVBEInfo( vib ); 1859 1860 /* VBE often cuts 64k off of the RAM total. */ 1861 1862 if( pScrn->videoRam & 64 ) 1863 pScrn->videoRam += 64; 1864 1865 psav->videoRambytes = pScrn->videoRam * 1024; 1866 } 1867 1868 1869 /* 1870 * If we're running with acceleration, compute the command overflow 1871 * buffer location. The command overflow buffer must END at a 1872 * 4MB boundary; for all practical purposes, that means the very 1873 * end of the frame buffer. 1874 */ 1875 if (psav->NoAccel) { 1876 psav->cobIndex = 0; 1877 psav->cobSize = 0; 1878 } 1879 else if( ((S3_SAVAGE4_SERIES(psav->Chipset)) || 1880 (S3_SUPERSAVAGE == psav->Chipset)) && psav->disableCOB ) { 1881 /* 1882 * The Savage4 and ProSavage have COB coherency bugs which render 1883 * the buffer useless. 1884 */ 1885 /* 1886 psav->cobIndex = 2; 1887 psav->cobSize = 0x8000 << psav->cobIndex; 1888 */ 1889 psav->cobIndex = 0; 1890 psav->cobSize = 0; 1891 psav->bciThresholdHi = 32; 1892 psav->bciThresholdLo = 0; 1893 } else { 1894 /* We use 128kB for the COB on all other chips. */ 1895 psav->cobSize = 0x20000; 1896 if (S3_SAVAGE3D_SERIES(psav->Chipset) || 1897 psav->Chipset == S3_SAVAGE2000) { 1898 psav->cobIndex = 7; /* rev.A savage4 apparently also uses 7 */ 1899 } else { 1900 psav->cobIndex = 2; 1901 } 1902 /* max command size: 2560 entries */ 1903 psav->bciThresholdHi = psav->cobSize/4 + 32 - 2560; 1904 psav->bciThresholdLo = psav->bciThresholdHi - 2560; 1905 } 1906 1907 /* align cob to 128k */ 1908 psav->cobOffset = (psav->videoRambytes - psav->cobSize) & ~0x1ffff; 1909 1910 /* The cursor must be aligned on a 4k boundary. */ 1911 psav->CursorKByte = (psav->cobOffset >> 10) - 4; 1912 psav->endfb = (psav->CursorKByte << 10) - 1; 1913 1914 if (psav->IsPrimary) { 1915 pScrn->videoRam /= 2; 1916 psav->videoRambytes = pScrn->videoRam * 1024; 1917 psav->CursorKByte = (psav->videoRambytes >> 10) - 4; 1918 psav->endfb = (psav->CursorKByte << 10) - 1; 1919 psav->videoRambytes *= 2; 1920 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1921 "Using %dk of videoram for primary head\n", 1922 pScrn->videoRam); 1923 } 1924 1925 if(psav->IsSecondary) 1926 { 1927 pScrn->videoRam /= 2; 1928 /*psav->videoRambytes = pScrn->videoRam * 1024;*/ 1929 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1930 "Using %dk of videoram for secondary head\n", 1931 pScrn->videoRam); 1932 } 1933 1934 pScrn->fbOffset = (psav->IsSecondary) 1935 ? pScrn->videoRam * 1024 : 0; 1936 1937 /* reset graphics engine to avoid memory corruption */ 1938 VGAOUT8(vgaCRIndex, 0x66); 1939 cr66 = VGAIN8(vgaCRReg); 1940 VGAOUT8(vgaCRReg, cr66 | 0x02); 1941 usleep(10000); 1942 1943 VGAOUT8(vgaCRIndex, 0x66); 1944 VGAOUT8(vgaCRReg, cr66 & ~0x02); /* clear reset flag */ 1945 usleep(10000); 1946 1947 /* Set status word positions based on chip type. */ 1948 SavageInitStatus(pScrn); 1949 1950 /* check for DVI/flat panel */ 1951 dvi = FALSE; 1952 if (psav->Chipset == S3_SAVAGE4) { 1953 unsigned char sr30 = 0x00; 1954 VGAOUT8(0x3c4, 0x30); 1955 /* clear bit 1 */ 1956 VGAOUT8(0x3c5, VGAIN8(0x3c5) & ~0x02); 1957 sr30 = VGAIN8(0x3c5); 1958 if (sr30 & 0x02 /*0x04 */) { 1959 dvi = TRUE; 1960 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Digital Flat Panel Detected\n"); 1961 } 1962 } 1963 1964 if( (S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || 1965 S3_MOBILE_TWISTER_SERIES(psav->Chipset)) && !psav->CrtOnly ) { 1966 psav->DisplayType = MT_LCD; 1967 } else if (dvi || ((psav->Chipset == S3_SAVAGE4) && psav->dvi)) { 1968 psav->DisplayType = MT_DFP; 1969 } else { 1970 psav->DisplayType = MT_CRT; 1971 } 1972 1973 if (psav->IsSecondary) 1974 psav->DisplayType = MT_CRT; 1975 1976 /* Do the DDC dance. */ 1977 SavageDoDDC(pScrn); 1978 1979 /* set up ramdac max clock - might be altered by SavageGetPanelInfo */ 1980 if (pScrn->bitsPerPixel >= 24) 1981 psav->maxClock = 220000; 1982 else 1983 psav->maxClock = 250000; 1984 1985 /* detect current mclk */ 1986 VGAOUT8(0x3c4, 0x08); 1987 sr8 = VGAIN8(0x3c5); 1988 VGAOUT8(0x3c5, 0x06); 1989 VGAOUT8(0x3c4, 0x10); 1990 n = VGAIN8(0x3c5); 1991 VGAOUT8(0x3c4, 0x11); 1992 m = VGAIN8(0x3c5); 1993 VGAOUT8(0x3c4, 0x08); 1994 VGAOUT8(0x3c5, sr8); 1995 m &= 0x7f; 1996 n1 = n & 0x1f; 1997 n2 = (n >> 5) & 0x03; 1998 mclk = ((1431818 * (m+2)) / (n1+2) / (1 << n2) + 50) / 100; 1999 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected current MCLK value of %1.3f MHz\n", 2000 mclk / 1000.0); 2001 2002 pScrn->maxHValue = 2048 << 3; /* 11 bits of h_total 8-pixel units */ 2003 pScrn->maxVValue = 2048; /* 11 bits of v_total */ 2004 pScrn->virtualX = pScrn->display->virtualX; 2005 pScrn->virtualY = pScrn->display->virtualY; 2006 2007 /* Check LCD panel information */ 2008 2009 if(psav->DisplayType == MT_LCD) 2010 { 2011 SavageGetPanelInfo(pScrn); 2012 SavageAddPanelMode(pScrn); 2013 } 2014 2015#if 0 2016 if (psav->CrtOnly && !psav->UseBIOS) { 2017 VGAOUT8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */ 2018 VGAOUT8(0x3c5, VGAIN8(0x3c5) & ~0x10); /* disable FP */ 2019 if (S3_SAVAGE_MOBILE_SERIES(psav->Chipset) /*|| 2020 S3_MOBILE_TWISTER_SERIES(psav->Chipset)*/) { /* not sure this works on mobile prosavage */ 2021 VGAOUT8(0x3c4, 0x31); 2022 VGAOUT8(0x3c5, VGAIN8(0x3c5) & ~0x04); /* make sure crtc1 is crt source */ 2023 } 2024 } 2025#endif 2026 2027 if( psav->UseBIOS ) 2028 { 2029 /* Go probe the BIOS for all the modes and refreshes at this depth. */ 2030 2031 if( psav->ModeTable ) 2032 { 2033 SavageFreeBIOSModeTable( psav, &psav->ModeTable ); 2034 } 2035 2036 psav->ModeTable = SavageGetBIOSModeTable( psav, psav->primStreamBpp ); 2037 2038 if( !psav->ModeTable || !psav->ModeTable->NumModes ) { 2039 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2040 "Failed to fetch any BIOS modes. Disabling BIOS.\n"); 2041 psav->UseBIOS = FALSE; 2042 } 2043 else 2044 /*if( xf86Verbose )*/ 2045 { 2046 SavageModeEntryPtr pmt; 2047 2048 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2049 "Found %d modes at this depth:\n", 2050 psav->ModeTable->NumModes); 2051 2052 for( 2053 i = 0, pmt = psav->ModeTable->Modes; 2054 i < psav->ModeTable->NumModes; 2055 i++, pmt++ ) 2056 { 2057 int j; 2058 ErrorF( " [%03x] %d x %d", 2059 pmt->VesaMode, pmt->Width, pmt->Height ); 2060 for( j = 0; j < pmt->RefreshCount; j++ ) 2061 { 2062 ErrorF( ", %dHz", pmt->RefreshRate[j] ); 2063 } 2064 ErrorF( "\n"); 2065 } 2066 } 2067 } 2068 2069 clockRanges = xnfalloc(sizeof(ClockRange)); 2070 clockRanges->next = NULL; 2071 clockRanges->minClock = 10000; 2072 clockRanges->maxClock = psav->maxClock; 2073 clockRanges->clockIndex = -1; 2074 clockRanges->interlaceAllowed = TRUE; 2075 clockRanges->doubleScanAllowed = TRUE; 2076 clockRanges->ClockDivFactor = 1.0; 2077 clockRanges->ClockMulFactor = 1.0; 2078 2079 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 2080 pScrn->display->modes, clockRanges, NULL, 2081 256, 2048, 16 * pScrn->bitsPerPixel, 2082 128, 2048, 2083 pScrn->virtualX, pScrn->virtualY, 2084 psav->videoRambytes, LOOKUP_BEST_REFRESH); 2085 2086 if (i == -1) { 2087 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86ValidateModes failure\n"); 2088 SavageFreeRec(pScrn); 2089 vbeFree(psav->pVbe); 2090 psav->pVbe = NULL; 2091 return FALSE; 2092 } 2093 2094 xf86PruneDriverModes(pScrn); 2095 2096 if (i == 0 || pScrn->modes == NULL) { 2097 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 2098 SavageFreeRec(pScrn); 2099 vbeFree(psav->pVbe); 2100 psav->pVbe = NULL; 2101 return FALSE; 2102 } 2103 2104 xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 2105 pScrn->currentMode = pScrn->modes; 2106 xf86PrintModes(pScrn); 2107 xf86SetDpi(pScrn, 0, 0); 2108 2109 if (xf86LoadSubModule(pScrn, "fb") == NULL) { 2110 SavageFreeRec(pScrn); 2111 vbeFree(psav->pVbe); 2112 psav->pVbe = NULL; 2113 return FALSE; 2114 } 2115 2116 xf86LoaderReqSymLists(fbSymbols, NULL); 2117 2118 if( !psav->NoAccel ) { 2119 2120 char *modName = NULL; 2121 const char **symNames = NULL; 2122 2123 if (psav->useEXA) { 2124 modName = "exa"; 2125 symNames = exaSymbols; 2126 XF86ModReqInfo req; 2127 int errmaj, errmin; 2128 memset(&req, 0, sizeof(req)); 2129 req.majorversion = 2; 2130 req.minorversion = 0; 2131 2132 if( !LoadSubModule(pScrn->module, modName, 2133 NULL, NULL, NULL, &req, &errmaj, &errmin) ) { 2134 LoaderErrorMsg(NULL, modName, errmaj, errmin); 2135 SavageFreeRec(pScrn); 2136 vbeFree(psav->pVbe); 2137 psav->pVbe = NULL; 2138 return FALSE; 2139 } 2140 } else { 2141 modName = "xaa"; 2142 symNames = xaaSymbols; 2143 if( !xf86LoadSubModule(pScrn, modName) ) { 2144 SavageFreeRec(pScrn); 2145 vbeFree(psav->pVbe); 2146 psav->pVbe = NULL; 2147 return FALSE; 2148 } 2149 } 2150 2151 xf86LoaderReqSymLists(symNames, NULL ); 2152 2153 } 2154 2155 if (psav->hwcursor) { 2156 if (!xf86LoadSubModule(pScrn, "ramdac")) { 2157 SavageFreeRec(pScrn); 2158 vbeFree(psav->pVbe); 2159 psav->pVbe = NULL; 2160 return FALSE; 2161 } 2162 xf86LoaderReqSymLists(ramdacSymbols, NULL); 2163 } 2164 2165 if (psav->shadowFB) { 2166 if (!xf86LoadSubModule(pScrn, "shadowfb")) { 2167 SavageFreeRec(pScrn); 2168 vbeFree(psav->pVbe); 2169 psav->pVbe = NULL; 2170 return FALSE; 2171 } 2172 xf86LoaderReqSymLists(shadowSymbols, NULL); 2173 } 2174 vbeFree(psav->pVbe); 2175 2176 psav->pVbe = NULL; 2177 2178 return TRUE; 2179} 2180 2181 2182static Bool SavageEnterVT(int scrnIndex, int flags) 2183{ 2184 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 2185#ifdef XF86DRI 2186 SavagePtr psav= SAVPTR(pScrn); 2187 ScreenPtr pScreen; 2188 SAVAGESAREAPrivPtr pSAREAPriv; 2189#endif 2190 2191 TRACE(("SavageEnterVT(%d)\n", flags)); 2192 2193 gpScrn = pScrn; 2194 SavageEnableMMIO(pScrn); 2195 2196#ifdef XF86DRI 2197 if (psav->directRenderingEnabled) { 2198 pScreen = screenInfo.screens[scrnIndex]; 2199 pSAREAPriv = (SAVAGESAREAPrivPtr)DRIGetSAREAPrivate(pScreen); 2200 /* Assume that 3D state was clobbered, invalidate it by 2201 * changing ctxOwner in the sarea. */ 2202 pSAREAPriv->ctxOwner = DRIGetContext(pScreen); 2203 DRIUnlock(pScreen); 2204 psav->LockHeld = 0; 2205 } 2206#endif 2207 if (!SAVPTR(pScrn)->IsSecondary) 2208 SavageSave(pScrn); 2209 if(SavageModeInit(pScrn, pScrn->currentMode)) { 2210 /* some BIOSes seem to enable HW cursor on PM resume */ 2211 if (!SAVPTR(pScrn)->hwc_on) 2212 SavageHideCursor( pScrn ); 2213 return TRUE; 2214 } 2215 2216 return FALSE; 2217} 2218 2219 2220static void SavageLeaveVT(int scrnIndex, int flags) 2221{ 2222 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 2223 vgaHWPtr hwp = VGAHWPTR(pScrn); 2224 SavagePtr psav = SAVPTR(pScrn); 2225 vgaRegPtr vgaSavePtr = &hwp->SavedReg; 2226 SavageRegPtr SavageSavePtr = &psav->SavedReg; 2227#ifdef XF86DRI 2228 ScreenPtr pScreen; 2229#endif 2230 2231 TRACE(("SavageLeaveVT(%d)\n", flags)); 2232 gpScrn = pScrn; 2233 2234#ifdef XF86DRI 2235 if (psav->directRenderingEnabled) { 2236 pScreen = screenInfo.screens[scrnIndex]; 2237 DRILock(pScreen, 0); 2238 psav->LockHeld = 1; 2239 } 2240#endif 2241 if (psav->FBStart2nd || (psav->videoFlags & VF_STREAMS_ON)) 2242 SavageStreamsOff(pScrn); 2243 SavageWriteMode(pScrn, vgaSavePtr, SavageSavePtr, FALSE); 2244 SavageResetStreams(pScrn); 2245 SavageDisableMMIO(pScrn); 2246 2247} 2248 2249 2250static void SavageSave(ScrnInfoPtr pScrn) 2251{ 2252 unsigned char cr3a, cr53, cr66; 2253 vgaHWPtr hwp = VGAHWPTR(pScrn); 2254 vgaRegPtr vgaSavePtr = &hwp->SavedReg; 2255 SavagePtr psav = SAVPTR(pScrn); 2256 SavageRegPtr save = &psav->SavedReg; 2257 unsigned short vgaCRReg = psav->vgaIOBase + 5; 2258 unsigned short vgaCRIndex = psav->vgaIOBase + 4; 2259 2260 TRACE(("SavageSave()\n")); 2261 2262 VGAOUT16(vgaCRIndex, 0x4838); 2263 VGAOUT16(vgaCRIndex, 0xa039); 2264 VGAOUT16(0x3c4, 0x0608); 2265 2266 VGAOUT8(vgaCRIndex, 0x66); 2267 cr66 = VGAIN8(vgaCRReg); 2268 VGAOUT8(vgaCRReg, cr66 | 0x80); 2269 VGAOUT8(vgaCRIndex, 0x3a); 2270 cr3a = VGAIN8(vgaCRReg); 2271 VGAOUT8(vgaCRReg, cr3a | 0x80); 2272 VGAOUT8(vgaCRIndex, 0x53); 2273 cr53 = VGAIN8(vgaCRReg); 2274 VGAOUT8(vgaCRReg, cr53 & 0x7f); 2275 2276 if (xf86IsPrimaryPci(psav->PciInfo)) 2277 vgaHWSave(pScrn, vgaSavePtr, VGA_SR_ALL); 2278 else 2279 vgaHWSave(pScrn, vgaSavePtr, VGA_SR_MODE); 2280 2281 VGAOUT8(vgaCRIndex, 0x66); 2282 VGAOUT8(vgaCRReg, cr66); 2283 VGAOUT8(vgaCRIndex, 0x3a); 2284 VGAOUT8(vgaCRReg, cr3a); 2285 2286 VGAOUT8(vgaCRIndex, 0x66); 2287 VGAOUT8(vgaCRReg, cr66); 2288 VGAOUT8(vgaCRIndex, 0x3a); 2289 VGAOUT8(vgaCRReg, cr3a); 2290 2291 /* unlock extended seq regs */ 2292 VGAOUT8(0x3c4, 0x08); 2293 save->SR08 = VGAIN8(0x3c5); 2294 VGAOUT8(0x3c5, 0x06); 2295 2296 /* now save all the extended regs we need */ 2297 VGAOUT8(vgaCRIndex, 0x31); 2298 save->CR31 = VGAIN8(vgaCRReg); 2299 VGAOUT8(vgaCRIndex, 0x32); 2300 save->CR32 = VGAIN8(vgaCRReg); 2301 VGAOUT8(vgaCRIndex, 0x34); 2302 save->CR34 = VGAIN8(vgaCRReg); 2303 VGAOUT8(vgaCRIndex, 0x36); 2304 save->CR36 = VGAIN8(vgaCRReg); 2305 VGAOUT8(vgaCRIndex, 0x3a); 2306 save->CR3A = VGAIN8(vgaCRReg); 2307 VGAOUT8(vgaCRIndex, 0x40); 2308 save->CR40 = VGAIN8(vgaCRReg); 2309 VGAOUT8(vgaCRIndex, 0x42); 2310 save->CR42 = VGAIN8(vgaCRReg); 2311 VGAOUT8(vgaCRIndex, 0x45); 2312 save->CR45 = VGAIN8(vgaCRReg); 2313 VGAOUT8(vgaCRIndex, 0x50); 2314 save->CR50 = VGAIN8(vgaCRReg); 2315 VGAOUT8(vgaCRIndex, 0x51); 2316 save->CR51 = VGAIN8(vgaCRReg); 2317 VGAOUT8(vgaCRIndex, 0x53); 2318 save->CR53 = VGAIN8(vgaCRReg); 2319 VGAOUT8(vgaCRIndex, 0x58); 2320 save->CR58 = VGAIN8(vgaCRReg); 2321 VGAOUT8(vgaCRIndex, 0x60); 2322 save->CR60 = VGAIN8(vgaCRReg); 2323 VGAOUT8(vgaCRIndex, 0x66); 2324 save->CR66 = VGAIN8(vgaCRReg); 2325 VGAOUT8(vgaCRIndex, 0x67); 2326 save->CR67 = VGAIN8(vgaCRReg); 2327 VGAOUT8(vgaCRIndex, 0x68); 2328 save->CR68 = VGAIN8(vgaCRReg); 2329 VGAOUT8(vgaCRIndex, 0x69); 2330 save->CR69 = VGAIN8(vgaCRReg); 2331 VGAOUT8(vgaCRIndex, 0x6f); 2332 save->CR6F = VGAIN8(vgaCRReg); 2333 2334 VGAOUT8(vgaCRIndex, 0x33); 2335 save->CR33 = VGAIN8(vgaCRReg); 2336 VGAOUT8(vgaCRIndex, 0x86); 2337 save->CR86 = VGAIN8(vgaCRReg); 2338 VGAOUT8(vgaCRIndex, 0x88); 2339 save->CR88 = VGAIN8(vgaCRReg); 2340 VGAOUT8(vgaCRIndex, 0x90); 2341 save->CR90 = VGAIN8(vgaCRReg); 2342 VGAOUT8(vgaCRIndex, 0x91); 2343 save->CR91 = VGAIN8(vgaCRReg); 2344 VGAOUT8(vgaCRIndex, 0xb0); 2345 save->CRB0 = VGAIN8(vgaCRReg) | 0x80; 2346 2347 /* extended mode timing regs */ 2348 VGAOUT8(vgaCRIndex, 0x3b); 2349 save->CR3B = VGAIN8(vgaCRReg); 2350 VGAOUT8(vgaCRIndex, 0x3c); 2351 save->CR3C = VGAIN8(vgaCRReg); 2352 VGAOUT8(vgaCRIndex, 0x43); 2353 save->CR43 = VGAIN8(vgaCRReg); 2354 VGAOUT8(vgaCRIndex, 0x5d); 2355 save->CR5D = VGAIN8(vgaCRReg); 2356 VGAOUT8(vgaCRIndex, 0x5e); 2357 save->CR5E = VGAIN8(vgaCRReg); 2358 VGAOUT8(vgaCRIndex, 0x65); 2359 save->CR65 = VGAIN8(vgaCRReg); 2360 2361 /* save seq extended regs for DCLK PLL programming */ 2362 VGAOUT8(0x3c4, 0x0e); 2363 save->SR0E = VGAIN8(0x3c5); 2364 VGAOUT8(0x3c4, 0x0f); 2365 save->SR0F = VGAIN8(0x3c5); 2366 VGAOUT8(0x3c4, 0x10); 2367 save->SR10 = VGAIN8(0x3c5); 2368 VGAOUT8(0x3c4, 0x11); 2369 save->SR11 = VGAIN8(0x3c5); 2370 VGAOUT8(0x3c4, 0x12); 2371 save->SR12 = VGAIN8(0x3c5); 2372 VGAOUT8(0x3c4, 0x13); 2373 save->SR13 = VGAIN8(0x3c5); 2374 VGAOUT8(0x3c4, 0x29); 2375 save->SR29 = VGAIN8(0x3c5); 2376 2377 VGAOUT8(0x3c4, 0x15); 2378 save->SR15 = VGAIN8(0x3c5); 2379 VGAOUT8(0x3c4, 0x30); 2380 save->SR30 = VGAIN8(0x3c5); 2381 VGAOUT8(0x3c4, 0x18); 2382 save->SR18 = VGAIN8(0x3c5); 2383 VGAOUT8(0x3c4, 0x1b); 2384 save->SR1B = VGAIN8(0x3c5); 2385 2386 /* Save flat panel expansion registers. */ 2387 2388 if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || 2389 S3_MOBILE_TWISTER_SERIES(psav->Chipset)) { 2390 int i; 2391 for( i = 0; i < 8; i++ ) { 2392 VGAOUT8(0x3c4, 0x54+i); 2393 save->SR54[i] = VGAIN8(0x3c5); 2394 } 2395 } 2396 2397 VGAOUT8(vgaCRIndex, 0x66); 2398 cr66 = VGAIN8(vgaCRReg); 2399 VGAOUT8(vgaCRReg, cr66 | 0x80); 2400 VGAOUT8(vgaCRIndex, 0x3a); 2401 cr3a = VGAIN8(vgaCRReg); 2402 VGAOUT8(vgaCRReg, cr3a | 0x80); 2403 2404 /* now save MIU regs */ 2405 if( ! S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) { 2406 save->MMPR0 = INREG(FIFO_CONTROL_REG); 2407 save->MMPR1 = INREG(MIU_CONTROL_REG); 2408 save->MMPR2 = INREG(STREAMS_TIMEOUT_REG); 2409 save->MMPR3 = INREG(MISC_TIMEOUT_REG); 2410 } 2411 2412 VGAOUT8(vgaCRIndex, 0x3a); 2413 VGAOUT8(vgaCRReg, cr3a); 2414 VGAOUT8(vgaCRIndex, 0x66); 2415 VGAOUT8(vgaCRReg, cr66); 2416 2417 if (!psav->ModeStructInit) { 2418 vgaHWCopyReg(&hwp->ModeReg, vgaSavePtr); 2419 memcpy(&psav->ModeReg, save, sizeof(SavageRegRec)); 2420 psav->ModeStructInit = TRUE; 2421 } 2422 2423#if 0 2424 if (xf86GetVerbosity() > 1) 2425 SavagePrintRegs(pScrn); 2426#endif 2427 2428 return; 2429} 2430 2431 2432static void SavageWriteMode(ScrnInfoPtr pScrn, vgaRegPtr vgaSavePtr, 2433 SavageRegPtr restore, Bool Entering) 2434{ 2435 unsigned char tmp, cr3a, cr66; 2436 vgaHWPtr hwp = VGAHWPTR(pScrn); 2437 SavagePtr psav = SAVPTR(pScrn); 2438 int vgaCRIndex, vgaCRReg, vgaIOBase; 2439 2440 2441 vgaIOBase = hwp->IOBase; 2442 vgaCRIndex = vgaIOBase + 4; 2443 vgaCRReg = vgaIOBase + 5; 2444 2445 TRACE(("SavageWriteMode(%x)\n", restore->mode)); 2446 2447#ifdef XF86DRI 2448 if (psav->directRenderingEnabled) { 2449 DRILock(screenInfo.screens[pScrn->scrnIndex], 0); 2450 psav->LockHeld = 1; 2451 } 2452#endif 2453 2454 if (psav->IsSecondary) { 2455 /* Set up the mode. Don't clear video RAM. */ 2456 SavageSetVESAMode( psav, restore->mode | 0x8000, restore->refresh ); 2457 SavageSetGBD(pScrn); 2458 return; 2459 } 2460 2461 if( Entering && 2462 (!S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || (psav->ForceInit)) 2463 ) 2464 SavageInitialize2DEngine(pScrn); 2465 2466 /* 2467 * If we figured out a VESA mode number for this timing, just use 2468 * the S3 BIOS to do the switching, with a few additional tweaks. 2469 */ 2470 2471 if( psav->UseBIOS && restore->mode > 0x13 ) 2472 { 2473 int width; 2474 unsigned short cr6d; 2475 unsigned short cr79 = 0; 2476 2477 /* Set up the mode. Don't clear video RAM. */ 2478 SavageSetVESAMode( psav, restore->mode | 0x8000, restore->refresh ); 2479 2480 /* Restore the DAC. */ 2481 vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_CMAP); 2482 2483 /* Unlock the extended registers. */ 2484 2485#if 0 2486 /* Which way is better? */ 2487 hwp->writeCrtc( hwp, 0x38, 0x48 ); 2488 hwp->writeCrtc( hwp, 0x39, 0xa0 ); 2489 hwp->writeSeq( hwp, 0x08, 0x06 ); 2490#endif 2491 2492 VGAOUT16(vgaCRIndex, 0x4838); 2493 VGAOUT16(vgaCRIndex, 0xA039); 2494 VGAOUT16(0x3c4, 0x0608); 2495 2496 /* Enable linear addressing. */ 2497 2498 VGAOUT16(vgaCRIndex, 0x1358); 2499 2500 /* Disable old MMIO. */ 2501 2502 VGAOUT8(vgaCRIndex, 0x53); 2503 VGAOUT8(vgaCRReg, VGAIN8(vgaCRReg) & ~0x10); 2504 2505 /* Disable HW cursor */ 2506 2507 VGAOUT16(vgaCRIndex, 0x0045); 2508 2509 /* Set the color mode. */ 2510 2511 VGAOUT8(vgaCRIndex, 0x67); 2512 VGAOUT8(vgaCRReg, restore->CR67); 2513 2514 /* Enable gamma correction, set CLUT to 8 bit */ 2515 2516 VGAOUT8(0x3c4, 0x1b); 2517 if( (pScrn->bitsPerPixel == 32) && !psav->DGAactive 2518 && ! psav->FBStart2nd ) 2519 VGAOUT8(0x3c5, 0x18 ); 2520 else 2521 VGAOUT8(0x3c5, 0x10 ); 2522 2523 /* We may need TV/panel fixups here. See s3bios.c line 2904. */ 2524 2525 /* Set FIFO fetch delay. */ 2526 VGAOUT8(vgaCRIndex, 0x85); 2527 VGAOUT8(vgaCRReg, (VGAIN8(vgaCRReg) & 0xf8) | 0x03); 2528 2529 /* Patch CR79. These values are magical. */ 2530 2531 if( !S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) 2532 { 2533 VGAOUT8(vgaCRIndex, 0x6d); 2534 cr6d = VGAIN8(vgaCRReg); 2535 2536 cr79 = 0x04; 2537 2538 if( pScrn->displayWidth >= 1024 ) 2539 { 2540 if(psav->primStreamBpp == 32 ) 2541 { 2542 if( restore->refresh >= 130 ) 2543 cr79 = 0x03; 2544 else if( pScrn->displayWidth >= 1280 ) 2545 cr79 = 0x02; 2546 else if( 2547 (pScrn->displayWidth == 1024) && 2548 (restore->refresh >= 75) 2549 ) 2550 { 2551 if( cr6d && LCD_ACTIVE ) 2552 cr79 = 0x05; 2553 else 2554 cr79 = 0x08; 2555 } 2556 } 2557 else if( psav->primStreamBpp == 16) 2558 { 2559 2560/* The windows driver uses 0x13 for 16-bit 130Hz, but I see terrible 2561 * screen artifacts with that value. Let's keep it low for now. 2562 * if( restore->refresh >= 130 ) 2563 * cr79 = 0x13; 2564 * else 2565 */ 2566 if( pScrn->displayWidth == 1024 ) 2567 { 2568 if( cr6d && LCD_ACTIVE ) 2569 cr79 = 0x08; 2570 else 2571 cr79 = 0x0e; 2572 } 2573 } 2574 } 2575 } 2576 2577 if( (psav->Chipset != S3_SAVAGE2000) && 2578 !S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) 2579 VGAOUT16(vgaCRIndex, (cr79 << 8) | 0x79); 2580 2581 /* Make sure 16-bit memory access is enabled. */ 2582 2583 VGAOUT16(vgaCRIndex, 0x0c31); 2584 2585 /* Enable the graphics engine. */ 2586 2587 VGAOUT16(vgaCRIndex, 0x0140); 2588 2589 /* Handle the pitch. */ 2590 2591 VGAOUT8(vgaCRIndex, 0x50); 2592 VGAOUT8(vgaCRReg, VGAIN8(vgaCRReg) | 0xC1); 2593 2594 width = (pScrn->displayWidth * (psav->primStreamBpp / 8)) >> 3; 2595 VGAOUT16(vgaCRIndex, ((width & 0xff) << 8) | 0x13 ); 2596 VGAOUT16(vgaCRIndex, ((width & 0x300) << 4) | 0x51 ); 2597 2598 /* Some non-S3 BIOSes enable block write even on non-SGRAM devices. */ 2599 2600 switch( psav->Chipset ) 2601 { 2602 case S3_SAVAGE2000: 2603 VGAOUT8(vgaCRIndex, 0x73); 2604 VGAOUT8(vgaCRReg, VGAIN8(vgaCRReg) & 0xdf ); 2605 break; 2606 2607 case S3_SAVAGE3D: 2608 case S3_SAVAGE4: 2609 VGAOUT8(vgaCRIndex, 0x68); 2610 if( !(VGAIN8(vgaCRReg) & 0x80) ) 2611 { 2612 /* Not SGRAM; disable block write. */ 2613 VGAOUT8(vgaCRIndex, 0x88); 2614 VGAOUT8(vgaCRReg, VGAIN8(vgaCRReg) | 0x10); 2615 } 2616 break; 2617 } 2618 2619 /* set the correct clock for some BIOSes */ 2620 VGAOUT8(VGA_MISC_OUT_W, 2621 VGAIN8(VGA_MISC_OUT_R) | 0x0C); 2622 /* Some BIOSes turn on clock doubling on non-doubled modes */ 2623 if (pScrn->bitsPerPixel < 24) { 2624 VGAOUT8(vgaCRIndex, 0x67); 2625 if (!(VGAIN8(vgaCRReg) & 0x10)) { 2626 VGAOUT8(0x3c4, 0x15); 2627 VGAOUT8(0x3c5, VGAIN8(0x3C5) & ~0x10); 2628 VGAOUT8(0x3c4, 0x18); 2629 VGAOUT8(0x3c5, VGAIN8(0x3c5) & ~0x80); 2630 } 2631 } 2632 2633 SavageInitialize2DEngine(pScrn); 2634 2635 VGAOUT16(vgaCRIndex, 0x0140); 2636 2637 SavageSetGBD(pScrn); 2638 2639 2640#ifdef XF86DRI 2641 if (psav->directRenderingEnabled) 2642 DRIUnlock(screenInfo.screens[pScrn->scrnIndex]); 2643 psav->LockHeld = 0; 2644#endif 2645 2646 return; 2647 } 2648 2649 VGAOUT8(0x3c2, 0x23); 2650 VGAOUT16(vgaCRIndex, 0x4838); 2651 VGAOUT16(vgaCRIndex, 0xa039); 2652 VGAOUT16(0x3c4, 0x0608); 2653 2654 vgaHWProtect(pScrn, TRUE); 2655 2656 /* will we be reenabling STREAMS for the new mode? */ 2657 psav->STREAMSRunning = 0; 2658 2659 /* reset GE to make sure nothing is going on */ 2660 VGAOUT8(vgaCRIndex, 0x66); 2661 if(VGAIN8(vgaCRReg) & 0x01) 2662 SavageGEReset(pScrn,0,__LINE__,__FILE__); 2663 2664 /* 2665 * Some Savage/MX and /IX systems go nuts when trying to exit the 2666 * server after WindowMaker has displayed a gradient background. I 2667 * haven't been able to find what causes it, but a non-destructive 2668 * switch to mode 3 here seems to eliminate the issue. 2669 */ 2670 2671 if( ((restore->CR31 & 0x0a) == 0) && psav->pVbe ) { 2672 SavageSetTextMode( psav ); 2673 } 2674 2675 VGAOUT8(vgaCRIndex, 0x67); 2676 (void) VGAIN8(vgaCRReg); 2677 /*VGAOUT8(vgaCRReg, restore->CR67 & ~0x0c);*/ /* no STREAMS yet */ 2678 VGAOUT8(vgaCRReg, restore->CR67 & ~0x0e); /* no STREAMS yet old and new */ 2679 2680 /* restore extended regs */ 2681 VGAOUT8(vgaCRIndex, 0x66); 2682 VGAOUT8(vgaCRReg, restore->CR66); 2683 VGAOUT8(vgaCRIndex, 0x3a); 2684 VGAOUT8(vgaCRReg, restore->CR3A); 2685 VGAOUT8(vgaCRIndex, 0x31); 2686 VGAOUT8(vgaCRReg, restore->CR31); 2687 VGAOUT8(vgaCRIndex, 0x32); 2688 VGAOUT8(vgaCRReg, restore->CR32); 2689 VGAOUT8(vgaCRIndex, 0x58); 2690 VGAOUT8(vgaCRReg, restore->CR58); 2691 VGAOUT8(vgaCRIndex, 0x53); 2692 VGAOUT8(vgaCRReg, restore->CR53 & 0x7f); 2693 2694 VGAOUT16(0x3c4, 0x0608); 2695 2696 /* Restore DCLK registers. */ 2697 2698 VGAOUT8(0x3c4, 0x0e); 2699 VGAOUT8(0x3c5, restore->SR0E); 2700 VGAOUT8(0x3c4, 0x0f); 2701 VGAOUT8(0x3c5, restore->SR0F); 2702 VGAOUT8(0x3c4, 0x29); 2703 VGAOUT8(0x3c5, restore->SR29); 2704 VGAOUT8(0x3c4, 0x15); 2705 VGAOUT8(0x3c5, restore->SR15); 2706 2707 /* Restore flat panel expansion registers. */ 2708 if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || 2709 S3_MOBILE_TWISTER_SERIES(psav->Chipset)) { 2710 int i; 2711 for( i = 0; i < 8; i++ ) { 2712 VGAOUT8(0x3c4, 0x54+i); 2713 VGAOUT8(0x3c5, restore->SR54[i]); 2714 } 2715 } 2716 2717 /* restore the standard vga regs */ 2718 if (xf86IsPrimaryPci(psav->PciInfo)) 2719 vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_ALL); 2720 else 2721 vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_MODE); 2722 2723 /* extended mode timing registers */ 2724 VGAOUT8(vgaCRIndex, 0x53); 2725 VGAOUT8(vgaCRReg, restore->CR53); 2726 VGAOUT8(vgaCRIndex, 0x5d); 2727 VGAOUT8(vgaCRReg, restore->CR5D); 2728 VGAOUT8(vgaCRIndex, 0x5e); 2729 VGAOUT8(vgaCRReg, restore->CR5E); 2730 VGAOUT8(vgaCRIndex, 0x3b); 2731 VGAOUT8(vgaCRReg, restore->CR3B); 2732 VGAOUT8(vgaCRIndex, 0x3c); 2733 VGAOUT8(vgaCRReg, restore->CR3C); 2734 VGAOUT8(vgaCRIndex, 0x43); 2735 VGAOUT8(vgaCRReg, restore->CR43); 2736 VGAOUT8(vgaCRIndex, 0x65); 2737 VGAOUT8(vgaCRReg, restore->CR65); 2738 2739 /* restore the desired video mode with cr67 */ 2740 VGAOUT8(vgaCRIndex, 0x67); 2741 /*VGAOUT8(vgaCRReg, restore->CR67 & ~0x0c);*/ /* no STREAMS yet */ 2742 VGAOUT8(vgaCRReg, restore->CR67 & ~0x0e); /* no streams for new and old streams engines */ 2743 2744 /* other mode timing and extended regs */ 2745 VGAOUT8(vgaCRIndex, 0x34); 2746 VGAOUT8(vgaCRReg, restore->CR34); 2747 VGAOUT8(vgaCRIndex, 0x40); 2748 VGAOUT8(vgaCRReg, restore->CR40); 2749 VGAOUT8(vgaCRIndex, 0x42); 2750 VGAOUT8(vgaCRReg, restore->CR42); 2751 VGAOUT8(vgaCRIndex, 0x45); 2752 VGAOUT8(vgaCRReg, restore->CR45); 2753 VGAOUT8(vgaCRIndex, 0x50); 2754 VGAOUT8(vgaCRReg, restore->CR50); 2755 VGAOUT8(vgaCRIndex, 0x51); 2756 VGAOUT8(vgaCRReg, restore->CR51); 2757 2758 /* memory timings */ 2759 VGAOUT8(vgaCRIndex, 0x36); 2760 VGAOUT8(vgaCRReg, restore->CR36); 2761 VGAOUT8(vgaCRIndex, 0x60); 2762 VGAOUT8(vgaCRReg, restore->CR60); 2763 VGAOUT8(vgaCRIndex, 0x68); 2764 VGAOUT8(vgaCRReg, restore->CR68); 2765 VerticalRetraceWait(); 2766 VGAOUT8(vgaCRIndex, 0x69); 2767 VGAOUT8(vgaCRReg, restore->CR69); 2768 VGAOUT8(vgaCRIndex, 0x6f); 2769 VGAOUT8(vgaCRReg, restore->CR6F); 2770 2771 VGAOUT8(vgaCRIndex, 0x33); 2772 VGAOUT8(vgaCRReg, restore->CR33); 2773 VGAOUT8(vgaCRIndex, 0x86); 2774 VGAOUT8(vgaCRReg, restore->CR86); 2775 VGAOUT8(vgaCRIndex, 0x88); 2776 VGAOUT8(vgaCRReg, restore->CR88); 2777 VGAOUT8(vgaCRIndex, 0x90); 2778 VGAOUT8(vgaCRReg, restore->CR90); 2779 VGAOUT8(vgaCRIndex, 0x91); 2780 VGAOUT8(vgaCRReg, restore->CR91); 2781 if( psav->Chipset == S3_SAVAGE4 ) 2782 { 2783 VGAOUT8(vgaCRIndex, 0xb0); 2784 VGAOUT8(vgaCRReg, restore->CRB0); 2785 } 2786 2787 VGAOUT8(vgaCRIndex, 0x32); 2788 VGAOUT8(vgaCRReg, restore->CR32); 2789 2790 /* unlock extended seq regs */ 2791 VGAOUT8(0x3c4, 0x08); 2792 VGAOUT8(0x3c5, 0x06); 2793 2794 /* Restore extended sequencer regs for MCLK. SR10 == 255 indicates that 2795 * we should leave the default SR10 and SR11 values there. 2796 */ 2797 if (restore->SR10 != 255) { 2798 VGAOUT8(0x3c4, 0x10); 2799 VGAOUT8(0x3c5, restore->SR10); 2800 VGAOUT8(0x3c4, 0x11); 2801 VGAOUT8(0x3c5, restore->SR11); 2802 } 2803 2804 /* restore extended seq regs for dclk */ 2805 VGAOUT8(0x3c4, 0x0e); 2806 VGAOUT8(0x3c5, restore->SR0E); 2807 VGAOUT8(0x3c4, 0x0f); 2808 VGAOUT8(0x3c5, restore->SR0F); 2809 VGAOUT8(0x3c4, 0x12); 2810 VGAOUT8(0x3c5, restore->SR12); 2811 VGAOUT8(0x3c4, 0x13); 2812 VGAOUT8(0x3c5, restore->SR13); 2813 VGAOUT8(0x3c4, 0x29); 2814 VGAOUT8(0x3c5, restore->SR29); 2815 2816 VGAOUT8(0x3c4, 0x18); 2817 VGAOUT8(0x3c5, restore->SR18); 2818 VGAOUT8(0x3c4, 0x1b); 2819 if( psav->DGAactive ) 2820 VGAOUT8(0x3c5, restore->SR1B & ~0x08 ); 2821 else 2822 VGAOUT8(0x3c5, restore->SR1B); 2823 2824 /* load new m, n pll values for dclk & mclk */ 2825 VGAOUT8(0x3c4, 0x15); 2826 tmp = VGAIN8(0x3c5) & ~0x21; 2827 2828 VGAOUT8(0x3c5, tmp | 0x03); 2829 VGAOUT8(0x3c5, tmp | 0x23); 2830 VGAOUT8(0x3c5, tmp | 0x03); 2831 VGAOUT8(0x3c5, restore->SR15); 2832 usleep( 100 ); 2833 2834 VGAOUT8(0x3c4, 0x30); 2835 VGAOUT8(0x3c5, restore->SR30); 2836 VGAOUT8(0x3c4, 0x08); 2837 VGAOUT8(0x3c5, restore->SR08); 2838 2839 /* now write out cr67 in full, possibly starting STREAMS */ 2840 VerticalRetraceWait(); 2841 VGAOUT8(vgaCRIndex, 0x67); 2842#if 0 2843 VGAOUT8(vgaCRReg, 0x50); 2844 usleep(10000); 2845 VGAOUT8(vgaCRIndex, 0x67); 2846#endif 2847 VGAOUT8(vgaCRReg, restore->CR67); 2848 2849 VGAOUT8(vgaCRIndex, 0x66); 2850 cr66 = VGAIN8(vgaCRReg); 2851 VGAOUT8(vgaCRReg, cr66 | 0x80); 2852 VGAOUT8(vgaCRIndex, 0x3a); 2853 cr3a = VGAIN8(vgaCRReg); 2854 VGAOUT8(vgaCRReg, cr3a | 0x80); 2855 2856 if (Entering) 2857 SavageGEReset(pScrn,0,__LINE__,__FILE__); 2858 2859 if( !S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) 2860 { 2861 VerticalRetraceWait(); 2862 OUTREG(FIFO_CONTROL_REG, restore->MMPR0); 2863 OUTREG(MIU_CONTROL_REG, restore->MMPR1); 2864 OUTREG(STREAMS_TIMEOUT_REG, restore->MMPR2); 2865 OUTREG(MISC_TIMEOUT_REG, restore->MMPR3); 2866 } 2867 2868 /* If we're going into graphics mode and acceleration was enabled, */ 2869 /* go set up the BCI buffer and the global bitmap descriptor. */ 2870 2871#if 0 2872 if( Entering && (!psav->NoAccel) ) 2873 { 2874 VGAOUT8(vgaCRIndex, 0x50); 2875 VGAOUT8(vgaCRReg, VGAIN8(vgaCRReg) | 0xC1); 2876 SavageInitialize2DEngine(pScrn); 2877 } 2878#endif 2879 2880 VGAOUT8(vgaCRIndex, 0x66); 2881 VGAOUT8(vgaCRReg, cr66); 2882 VGAOUT8(vgaCRIndex, 0x3a); 2883 VGAOUT8(vgaCRReg, cr3a); 2884 2885 if( Entering ) { 2886 SavageInitialize2DEngine(pScrn); 2887 2888 VGAOUT16(vgaCRIndex, 0x0140); 2889 2890 SavageSetGBD(pScrn); 2891 } 2892 2893 vgaHWProtect(pScrn, FALSE); 2894 2895 2896#ifdef XF86DRI 2897 if (psav->directRenderingEnabled) 2898 DRIUnlock(screenInfo.screens[pScrn->scrnIndex]); 2899 psav->LockHeld = 0; 2900#endif 2901 2902 return; 2903} 2904 2905 2906static Bool SavageMapMem(ScrnInfoPtr pScrn) 2907{ 2908 SavagePtr psav = SAVPTR(pScrn); 2909 int mode; 2910 unsigned i; 2911 2912 TRACE(("SavageMapMem()\n")); 2913 2914 if( S3_SAVAGE3D_SERIES(psav->Chipset) ) { 2915 psav->MmioRegion.bar = 0; 2916 psav->MmioRegion.offset = SAVAGE_NEWMMIO_REGBASE_S3; 2917 2918 psav->FbRegion.bar = 0; 2919 psav->FbRegion.offset = 0; 2920 2921 psav->last_bar = 0; 2922 } else { 2923 psav->MmioRegion.bar = 0; 2924 psav->MmioRegion.offset = SAVAGE_NEWMMIO_REGBASE_S4; 2925 2926 psav->FbRegion.bar = 1; 2927 psav->FbRegion.offset = 0; 2928 2929 psav->last_bar = 1; 2930 } 2931 2932 /* On Paramount and Savage 2000, aperture 0 is PCI base 2. On other 2933 * chipsets it's in the same BAR as the framebuffer. 2934 */ 2935 if ((psav->Chipset == S3_SUPERSAVAGE) 2936 || (psav->Chipset == S3_SAVAGE2000)) { 2937 psav->ApertureRegion.bar = 2; 2938 psav->ApertureRegion.offset = 0; 2939 2940 psav->last_bar = 2; 2941 } else { 2942 psav->ApertureRegion.bar = psav->FbRegion.bar; 2943 psav->ApertureRegion.offset = 0x02000000; 2944 } 2945 2946 2947 psav->MmioBase = psav->PciInfo->memBase[ psav->MmioRegion.bar ] 2948 + psav->MmioRegion.offset; 2949 2950 psav->FrameBufferBase = psav->PciInfo->memBase[ psav->FbRegion.bar ] 2951 + psav->FbRegion.offset; 2952 2953 psav->ApertureBase = psav->PciInfo->memBase[ psav->FbRegion.bar ] 2954 + psav->ApertureRegion.offset; 2955 2956 2957 /* FIXME: This seems fine even on Savage3D where the same BAR contains the 2958 * FIXME: MMIO space and the framebuffer. Write-combining gets fixed up 2959 * FIXME: later. Someone should investigate this, though. And kick S3 2960 * FIXME: for doing something so silly. 2961 */ 2962 mode = VIDMEM_MMIO; 2963 for (i = 0; i <= psav->last_bar; i++) { 2964 psav->bar_mappings[i] = xf86MapPciMem(pScrn->scrnIndex, mode, 2965 psav->PciTag, 2966 psav->PciInfo->memBase[i], 2967 (1U << psav->PciInfo->size[i])); 2968 if (!psav->bar_mappings[i]) { 2969 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2970 "Internal error: cound not map PCI region %u, last BAR = %u\n", 2971 i, psav->last_bar); 2972 return FALSE; 2973 } 2974 2975 mode = VIDMEM_FRAMEBUFFER; 2976 } 2977 2978 psav->MapBase = psav->bar_mappings[ psav->MmioRegion.bar ] 2979 + psav->MmioRegion.offset; 2980 2981 psav->BciMem = psav->MapBase + 0x10000; 2982 2983 SavageEnableMMIO(pScrn); 2984 2985 psav->FBBase = psav->bar_mappings[ psav->FbRegion.bar ] 2986 + psav->FbRegion.offset; 2987 2988 psav->FBStart = (psav->IsSecondary) 2989 ? psav->FBBase + 0x1000000 : psav->FBBase; 2990 2991 psav->ApertureMap = psav->bar_mappings[ psav->ApertureRegion.bar ] 2992 + psav->ApertureRegion.offset; 2993 2994 if (psav->IsSecondary) { 2995 psav->ApertureMap += 0x1000000; 2996 } 2997 2998 pScrn->memPhysBase = psav->PciInfo->memBase[0]; 2999 3000 return TRUE; 3001} 3002 3003 3004static void SavageUnmapMem(ScrnInfoPtr pScrn, int All) 3005{ 3006 SavagePtr psav = SAVPTR(pScrn); 3007 unsigned i; 3008 3009 TRACE(("SavageUnmapMem(%x,%x)\n", psav->MapBase, psav->FBBase)); 3010 3011 if (psav->PrimaryVidMapped) { 3012 vgaHWUnmapMem(pScrn); 3013 psav->PrimaryVidMapped = FALSE; 3014 } 3015 3016 SavageDisableMMIO(pScrn); 3017 3018 for (i = (All) ? 0 : 1; i <= psav->last_bar; i++) { 3019 if (psav->bar_mappings[i]) { 3020 xf86UnMapVidMem(pScrn->scrnIndex, psav->bar_mappings[i], 3021 (1U << psav->PciInfo->size[i])); 3022 psav->bar_mappings[i] = NULL; 3023 } 3024 } 3025 3026 if (All) { 3027 psav->MapBase = 0; 3028 psav->BciMem = 0; 3029 } 3030 3031 psav->FBBase = 0; 3032 psav->FBStart = 0; 3033 psav->ApertureMap = 0; 3034 3035 return; 3036} 3037 3038#ifdef XF86DRI 3039static Bool SavageCheckAvailableRamFor3D(ScrnInfoPtr pScrn) 3040{ 3041 SavagePtr psav = SAVPTR(pScrn); 3042 int cpp = pScrn->bitsPerPixel / 8; 3043 int tiledBufferSize, RamNeededFor3D; 3044 3045 if (cpp == 2) { 3046 tiledBufferSize = ((pScrn->virtualX+63)/64)*((pScrn->virtualY+15)/16) * 2048; 3047 } else { 3048 tiledBufferSize = ((pScrn->virtualX+31)/32)*((pScrn->virtualY+15)/16) * 2048; 3049 } 3050 3051 RamNeededFor3D = 4096 + /* hw cursor*/ 3052 psav->cobSize + /*COB*/ 3053 tiledBufferSize + /* front buffer */ 3054 tiledBufferSize + /* back buffer */ 3055 tiledBufferSize; /* depth buffer */ 3056 3057 xf86DrvMsg(pScrn->scrnIndex,X_INFO, 3058 "%d kB of Videoram needed for 3D; %d kB of Videoram available\n", 3059 RamNeededFor3D/1024, psav->videoRambytes/1024); 3060 3061 if (RamNeededFor3D <= psav->videoRambytes) { 3062 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Sufficient Videoram available for 3D\n"); 3063 return TRUE; 3064 } else { 3065 xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Insufficient Videoram available for 3D -- " 3066 "Try a lower color depth or smaller desktop. " 3067 "For integrated savages try increasing the videoram in the BIOS.\n"); 3068 return FALSE; 3069 } 3070} 3071#endif 3072 3073static void SavageInitStatus(ScrnInfoPtr pScrn) 3074{ 3075 SavagePtr psav = SAVPTR(pScrn); 3076 3077 switch( psav->Chipset ) { 3078 case S3_SAVAGE3D: 3079 case S3_SAVAGE_MX: 3080 psav->WaitQueue = WaitQueue3D; 3081 psav->WaitIdle = WaitIdle3D; 3082 psav->WaitIdleEmpty = WaitIdleEmpty3D; 3083 psav->bciUsedMask = 0x1ffff; 3084 psav->eventStatusReg= 1; 3085 break; 3086 3087 case S3_SAVAGE4: 3088 case S3_PROSAVAGE: 3089 case S3_SUPERSAVAGE: 3090 case S3_PROSAVAGEDDR: 3091 case S3_TWISTER: 3092 psav->WaitQueue = WaitQueue4; 3093 psav->WaitIdle = WaitIdle4; 3094 psav->WaitIdleEmpty = WaitIdleEmpty4; 3095 psav->bciUsedMask = 0x1fffff; 3096 psav->eventStatusReg= 1; 3097 break; 3098 3099 case S3_SAVAGE2000: 3100 psav->WaitQueue = WaitQueue2K; 3101 psav->WaitIdle = WaitIdle2K; 3102 psav->WaitIdleEmpty = WaitIdleEmpty2K; 3103 psav->bciUsedMask = 0xfffff; 3104 psav->eventStatusReg= 2; 3105 break; 3106 } 3107} 3108 3109static void SavageInitShadowStatus(ScrnInfoPtr pScrn) 3110{ 3111 SavagePtr psav = SAVPTR(pScrn); 3112 3113 psav->ShadowStatus = psav->ConfigShadowStatus; 3114 3115 SavageInitStatus(pScrn); 3116 3117 if( psav->ShadowStatus ) { 3118 psav->ShadowPhysical = 3119 psav->FrameBufferBase + psav->CursorKByte*1024 + 4096 - 32; 3120 3121 psav->ShadowVirtual = (CARD32 *) 3122 (psav->FBBase + psav->CursorKByte*1024 + 4096 - 32); 3123 3124 xf86DrvMsg( pScrn->scrnIndex, X_PROBED, 3125 "Shadow area physical %08lx, linear %p\n", 3126 psav->ShadowPhysical, (void *)psav->ShadowVirtual ); 3127 3128 psav->WaitQueue = ShadowWaitQueue; 3129 psav->WaitIdle = ShadowWait; 3130 psav->WaitIdleEmpty = ShadowWait; 3131 } 3132 3133 if( psav->Chipset == S3_SAVAGE2000 ) 3134 psav->dwBCIWait2DIdle = 0xc0040000; 3135 else 3136 psav->dwBCIWait2DIdle = 0xc0020000; 3137} 3138 3139static Bool SavageScreenInit(int scrnIndex, ScreenPtr pScreen, 3140 int argc, char **argv) 3141{ 3142 ScrnInfoPtr pScrn; 3143 SavagePtr psav; 3144 EntityInfoPtr pEnt; 3145 int ret; 3146 int colormapFlags; 3147 3148 TRACE(("SavageScreenInit()\n")); 3149 3150 pScrn = xf86Screens[pScreen->myNum]; 3151 psav = SAVPTR(pScrn); 3152 3153 pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 3154 if (!psav->pVbe) 3155 psav->pVbe = VBEInit(NULL, pEnt->index); 3156 3157 SavageEnableMMIO(pScrn); 3158 3159 if (!SavageMapMem(pScrn)) 3160 return FALSE; 3161 3162 psav->FBStart2nd = 0; 3163 3164 if (psav->overlayDepth) { 3165 if ((pScrn->virtualX * pScrn->virtualY * 3166 (DEPTH_BPP(DEPTH_2ND(pScrn))) >> 3) 3167 > (psav->CursorKByte * 1024)) 3168 xf86DrvMsg(pScrn->scrnIndex,X_WARNING, 3169 "Not enough memory for overlay mode: disabling\n"); 3170 else psav->FBStart2nd = psav->FBStart 3171 + ((pScrn->virtualX * pScrn->virtualY + 0xff) & ~0xff); 3172 3173 } 3174 3175 SavageInitShadowStatus(pScrn); 3176 psav->ShadowCounter = 0; 3177 3178 SavageSave(pScrn); 3179 3180 vgaHWBlankScreen(pScrn, TRUE); 3181 3182#ifdef XF86DRI 3183 if (!xf86ReturnOptValBool(psav->Options, OPTION_DRI, TRUE)) { 3184 psav->directRenderingEnabled = FALSE; 3185 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3186 "Direct rendering forced off\n"); 3187 } else if (psav->IsSecondary) { 3188 psav->directRenderingEnabled = FALSE; 3189 } else if (xf86IsEntityShared(psav->pEnt->index)) { 3190 /* Xinerama has sync problem with DRI, disable it for now */ 3191 psav->directRenderingEnabled = FALSE; 3192 xf86DrvMsg(scrnIndex, X_WARNING, 3193 "Direct Rendering Disabled -- " 3194 "Dual-head configuration is not working with " 3195 "DRI at present.\n"); 3196 } else if (/*!psav->bTiled*/psav->bDisableTile) { 3197 xf86DrvMsg(scrnIndex, X_WARNING, 3198 "Direct Rendering requires a tiled framebuffer -- " 3199 "Set Option \"DisableTile\" \"false\"\n"); 3200 } else if (psav->cobSize == 0) { 3201 xf86DrvMsg(scrnIndex, X_WARNING, 3202 "Direct Rendering requires the COB -- " 3203 "Set Option \"DisableCOB\" \"false\"\n"); 3204 } else if (((psav->Chipset == S3_TWISTER) 3205 || (psav->Chipset == S3_PROSAVAGE) 3206 || (psav->Chipset == S3_SAVAGE4) 3207 || (psav->Chipset == S3_SAVAGE_MX) 3208 || (psav->Chipset == S3_SAVAGE3D) 3209 || (psav->Chipset == S3_SUPERSAVAGE) 3210 || (psav->Chipset == S3_PROSAVAGEDDR)) 3211 && (!psav->NoAccel) 3212 && (SavageCheckAvailableRamFor3D(pScrn))) { 3213 /* Setup DRI after visuals have been established */ 3214 psav->directRenderingEnabled = SAVAGEDRIScreenInit(pScreen); 3215 /* If DRI init failed, reset shadow status. */ 3216 if (!psav->directRenderingEnabled && 3217 psav->ShadowStatus != psav->ConfigShadowStatus) { 3218 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Resetting ShadowStatus.\n"); 3219 SavageInitShadowStatus(pScrn); 3220 } 3221 /* If shadow status was enabled for DRI, hook up the shadow 3222 * waiting functions now. */ 3223 else if (psav->ShadowStatus && !psav->ConfigShadowStatus) { 3224 psav->WaitQueue = ShadowWaitQueue; 3225 psav->WaitIdle = ShadowWait; 3226 psav->WaitIdleEmpty = ShadowWait; 3227 } 3228 } else 3229 psav->directRenderingEnabled = FALSE; 3230 3231 if(psav->directRenderingEnabled) { 3232 xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"DRI is enabled\n"); 3233 } 3234 else { 3235 xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"DRI isn't enabled\n"); 3236 } 3237#endif 3238 3239 if (!SavageModeInit(pScrn, pScrn->currentMode)) 3240 return FALSE; 3241 3242 miClearVisualTypes(); 3243 3244 { 3245 int visual; 3246 3247 visual = ((psav->FBStart2nd && pScrn->bitsPerPixel > 8) 3248 || pScrn->bitsPerPixel == 16) ? TrueColorMask 3249 : miGetDefaultVisualMask(DEPTH_BPP(pScrn->depth)); 3250 if (!miSetVisualTypes(pScrn->depth, visual, 3251 pScrn->rgbBits, pScrn->defaultVisual)) 3252 return FALSE; 3253 3254 if (psav->FBStart2nd) {/* we have overlay */ 3255 visual = psav->overlayDepth > 8 ? TrueColorMask : 3256 miGetDefaultVisualMask(DEPTH_BPP(psav->overlayDepth)); 3257 if (!miSetVisualTypes(psav->overlayDepth, visual, 3258 psav->overlayDepth > 8 ? 8 : 6, 3259 pScrn->defaultVisual)) 3260 return FALSE; 3261 } 3262 } 3263 if (!miSetPixmapDepths ()) 3264 return FALSE; 3265 3266 ret = SavageInternalScreenInit(scrnIndex, pScreen); 3267 if (!ret) 3268 return FALSE; 3269 3270 xf86SetBlackWhitePixels(pScreen); 3271 3272 { 3273 VisualPtr visual; 3274 visual = pScreen->visuals + pScreen->numVisuals; 3275 while (--visual >= pScreen->visuals) { 3276 if ((visual->class | DynamicClass) == DirectColor 3277 && visual->nplanes > MAX_PSEUDO_DEPTH) { 3278 if (visual->nplanes == pScrn->depth) { 3279 visual->offsetRed = pScrn->offset.red; 3280 visual->offsetGreen = pScrn->offset.green; 3281 visual->offsetBlue = pScrn->offset.blue; 3282 visual->redMask = pScrn->mask.red; 3283 visual->greenMask = pScrn->mask.green; 3284 visual->blueMask = pScrn->mask.blue; 3285 } else if (visual->offsetRed > 8 3286 || visual->offsetGreen > 8 3287 || visual->offsetBlue > 8) { 3288 /* 3289 * mi has set these wrong. fix it here -- we cannot use pScrn 3290 * as this is set up for the default depth 8. 3291 */ 3292 int tmp; 3293 int c_s = 0; 3294 3295 tmp = visual->offsetBlue; 3296 visual->offsetBlue = visual->offsetRed; 3297 visual->offsetRed = tmp; 3298 tmp = visual->blueMask; 3299 visual->blueMask = visual->redMask; 3300 visual->redMask = tmp; 3301 switch (DEPTH_2ND(pScrn)) { 3302 case 16: 3303 visual->offsetRed = 11; 3304 visual->offsetGreen = 5; 3305 visual->offsetBlue = 0; 3306 visual->redMask = 0xF800; 3307 visual->greenMask = 0x7E0; 3308 visual->blueMask = 0x1F; 3309 break; 3310 case 24: 3311 visual->offsetRed = 16; 3312 visual->offsetGreen = 8; 3313 visual->offsetBlue = 0; 3314 visual->redMask = 0xFF0000; 3315 visual->greenMask = 0xFF00; 3316 visual->blueMask = 0xFF; 3317 c_s = 2; 3318 break; 3319 } 3320 psav->overlay.redMask = visual->redMask; 3321 psav->overlay.greenMask = visual->greenMask; 3322 psav->overlay.blueMask = visual->blueMask; 3323 psav->overlay.redShift = visual->offsetRed + c_s; 3324 psav->overlay.greenShift = visual->offsetGreen + c_s; 3325 psav->overlay.blueShift = visual->offsetBlue + c_s; 3326 } 3327 } 3328 } 3329 } 3330 3331 /* must be after RGB ordering fixed */ 3332 fbPictureInit (pScreen, 0, 0); 3333 3334 if( !psav->NoAccel ) { 3335 SavageInitAccel(pScreen); 3336 } 3337 3338 miInitializeBackingStore(pScreen); 3339 xf86SetBackingStore(pScreen); 3340 3341 if( !psav->shadowFB && !psav->useEXA ) 3342 SavageDGAInit(pScreen); 3343 3344 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 3345 3346 if (psav->hwcursor) 3347 if (!SavageHWCursorInit(pScreen)) 3348 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 3349 "Hardware cursor initialization failed\n"); 3350 3351 if (psav->shadowFB) { 3352 RefreshAreaFuncPtr refreshArea = SavageRefreshArea; 3353 3354 if(psav->rotate) { 3355 if (!psav->PointerMoved) { 3356 psav->PointerMoved = pScrn->PointerMoved; 3357 pScrn->PointerMoved = SavagePointerMoved; 3358 } 3359 3360 switch(pScrn->bitsPerPixel) { 3361 case 8: refreshArea = SavageRefreshArea8; break; 3362 case 16: refreshArea = SavageRefreshArea16; break; 3363 case 24: refreshArea = SavageRefreshArea24; break; 3364 case 32: refreshArea = SavageRefreshArea32; break; 3365 } 3366 } 3367 3368 ShadowFBInit(pScreen, refreshArea); 3369 } 3370 3371 if (!miCreateDefColormap(pScreen)) 3372 return FALSE; 3373 3374 colormapFlags = CMAP_RELOAD_ON_MODE_SWITCH 3375 | ((psav->FBStart2nd) ? 0 : CMAP_PALETTED_TRUECOLOR); 3376 3377 if (psav->Chipset == S3_SAVAGE4) { 3378 if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, SavageLoadPaletteSavage4, 3379 NULL, colormapFlags )) 3380 return FALSE; 3381 } else { 3382 if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, SavageLoadPalette, NULL, 3383 colormapFlags )) 3384 return FALSE; 3385 } 3386 3387 vgaHWBlankScreen(pScrn, FALSE); 3388 3389 psav->CloseScreen = pScreen->CloseScreen; 3390 pScreen->SaveScreen = SavageSaveScreen; 3391 pScreen->CloseScreen = SavageCloseScreen; 3392 3393 if (xf86DPMSInit(pScreen, SavageDPMS, 0) == FALSE) 3394 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DPMS initialization failed\n"); 3395 3396#ifdef XF86DRI 3397 if (psav->directRenderingEnabled) { 3398 /* complete the DRI setup.*/ 3399 psav->directRenderingEnabled = SAVAGEDRIFinishScreenInit(pScreen); 3400 /* If DRI initialization failed, reset shadow status and 3401 * reinitialize 2D engine. */ 3402 if (!psav->directRenderingEnabled && 3403 psav->ShadowStatus != psav->ConfigShadowStatus) { 3404 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Resetting ShadowStatus.\n"); 3405 SavageInitShadowStatus(pScrn); 3406 SavageInitialize2DEngine(pScrn); 3407 } 3408 } 3409 if (psav->directRenderingEnabled) { 3410 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n"); 3411 } else { 3412 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Direct rendering disabled\n"); 3413 } 3414#endif 3415 3416 SavagePanningCheck(pScrn); 3417#ifdef XvExtension 3418 if( !psav->FBStart2nd && !psav->NoAccel /*&& !SavagePanningCheck(pScrn)*/ ) { 3419 if (psav->IsSecondary) 3420 /* Xv should work on crtc2, but I haven't gotten there yet. -- AGD */ 3421 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Xv currently disabled for crtc2.\n"); 3422 else 3423 SavageInitVideo( pScreen ); 3424 } 3425#endif 3426 3427#ifdef XF86DRI 3428 if ((psav->directRenderingEnabled) && (!psav->bDisableXvMC)) { 3429 if (SAVAGEInitMC(pScreen)) 3430 xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"XvMC is enabled\n"); 3431 else 3432 xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"XvMC is not enabled\n"); 3433 } 3434#endif 3435 3436 if (serverGeneration == 1) 3437 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 3438 3439 return TRUE; 3440} 3441 3442 3443static int SavageInternalScreenInit(int scrnIndex, ScreenPtr pScreen) 3444{ 3445 int ret = TRUE; 3446 ScrnInfoPtr pScrn; 3447 SavagePtr psav; 3448 int width, height, displayWidth; 3449 unsigned char *FBStart; 3450 3451 TRACE(("SavageInternalScreenInit()\n")); 3452 3453 pScrn = xf86Screens[pScreen->myNum]; 3454 psav = SAVPTR(pScrn); 3455 3456 displayWidth = pScrn->displayWidth; 3457 3458 if (psav->rotate) { 3459 height = pScrn->virtualX; 3460 width = pScrn->virtualY; 3461 } else { 3462 width = pScrn->virtualX; 3463 height = pScrn->virtualY; 3464 } 3465 3466 3467 if(psav->shadowFB) { 3468 psav->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); 3469 psav->ShadowPtr = xalloc(psav->ShadowPitch * height); 3470 displayWidth = psav->ShadowPitch / (pScrn->bitsPerPixel >> 3); 3471 FBStart = psav->ShadowPtr; 3472 } else { 3473 psav->ShadowPtr = NULL; 3474 FBStart = psav->FBStart; 3475 } 3476 3477 if (!psav->FBStart2nd) { 3478 3479 ret = fbScreenInit(pScreen, FBStart, width, height, 3480 pScrn->xDpi, pScrn->yDpi, 3481 psav->ulAperturePitch / (pScrn->bitsPerPixel >> 3), /*displayWidth,*/ 3482 pScrn->bitsPerPixel); 3483 3484 } else { 3485 FbOverlayScrPrivPtr pScrPriv; 3486 int Depth2nd = DEPTH_2ND(pScrn); 3487 if (!fbSetupScreen (pScreen, FBStart, width, height, 3488 pScrn->xDpi, pScrn->yDpi, displayWidth, 8)) 3489 return FALSE; 3490 if (pScrn->depth == 8) { 3491 ret = fbOverlayFinishScreenInit (pScreen, FBStart, 3492 psav->FBStart2nd, width, 3493 height,pScrn->xDpi, pScrn->yDpi, 3494 displayWidth,displayWidth, 3495 8, DEPTH_BPP(Depth2nd), 3496 8, Depth2nd); 3497 pScrPriv = fbOverlayGetScrPriv(pScreen); 3498 pScrPriv->layer[0].key = pScrn->colorKey; 3499 } else { 3500 ret = fbOverlayFinishScreenInit (pScreen, psav->FBStart2nd, 3501 FBStart, 3502 width, height,pScrn->xDpi, 3503 pScrn->yDpi, 3504 displayWidth,displayWidth, 3505 DEPTH_BPP(Depth2nd), 8, 3506 Depth2nd, 8); 3507 pScrPriv = fbOverlayGetScrPriv(pScreen); 3508 pScrPriv->layer[1].key = pScrn->colorKey; 3509 } 3510 } 3511 return ret; 3512} 3513 3514 3515static int SavageGetRefresh(DisplayModePtr mode) 3516{ 3517 int refresh = (mode->Clock * 1000) / (mode->HTotal * mode->VTotal); 3518 if (mode->Flags & V_INTERLACE) 3519 refresh *= 2.0; 3520 if (mode->Flags & V_DBLSCAN) 3521 refresh /= 2.0; 3522 if (mode->VScan > 1) 3523 refresh /= mode->VScan; 3524 return refresh; 3525} 3526 3527 3528static ModeStatus SavageValidMode(int index, DisplayModePtr pMode, 3529 Bool verbose, int flags) 3530{ 3531 ScrnInfoPtr pScrn = xf86Screens[index]; 3532 SavagePtr psav = SAVPTR(pScrn); 3533 int refresh; 3534 3535 TRACE(("SavageValidMode\n")); 3536 3537 /* We prohibit modes bigger than the LCD panel. */ 3538 /* TODO We should do this only if the panel is active. */ 3539 3540 if( psav->TvOn ) 3541 { 3542 if( pMode->HDisplay > psav->TVSizeX ) 3543 return MODE_VIRTUAL_X; 3544 3545 if( pMode->VDisplay > psav->TVSizeY ) 3546 return MODE_VIRTUAL_Y; 3547 3548 } 3549 3550 if((psav->DisplayType == MT_LCD) && 3551 ((pMode->HDisplay > psav->PanelX) || 3552 (pMode->VDisplay > psav->PanelY))) 3553 return MODE_PANEL; 3554 3555 if (psav->UseBIOS) { 3556 refresh = SavageGetRefresh(pMode); 3557 return (SavageMatchBiosMode(pScrn,pMode->HDisplay, 3558 pMode->VDisplay, 3559 refresh,NULL,NULL)); 3560 } 3561 3562 return MODE_OK; 3563} 3564 3565static Bool SavageModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 3566{ 3567 vgaHWPtr hwp = VGAHWPTR(pScrn); 3568 SavagePtr psav = SAVPTR(pScrn); 3569 int width, dclk, i, j; /*, refresh; */ 3570 unsigned int m, n, r; 3571 unsigned char tmp = 0; 3572 SavageRegPtr new = &psav->ModeReg; 3573 vgaRegPtr vganew = &hwp->ModeReg; 3574 int vgaCRIndex, vgaCRReg, vgaIOBase; 3575 int refresh; 3576 unsigned int newmode=0, newrefresh=0; 3577 3578 vgaIOBase = hwp->IOBase; 3579 vgaCRIndex = vgaIOBase + 4; 3580 vgaCRReg = vgaIOBase + 5; 3581 3582 TRACE(("SavageModeInit(%dx%d, %dHz)\n", 3583 mode->HDisplay, mode->VDisplay, mode->Clock)); 3584 3585#if 0 3586 ErrorF("Clock = %d, HDisplay = %d, HSStart = %d\n", 3587 mode->Clock, mode->HDisplay, mode->HSyncStart); 3588 ErrorF("HSEnd = %d, HSkew = %d\n", 3589 mode->HSyncEnd, mode->HSkew); 3590 ErrorF("VDisplay - %d, VSStart = %d, VSEnd = %d\n", 3591 mode->VDisplay, mode->VSyncStart, mode->VSyncEnd); 3592 ErrorF("VTotal = %d\n", 3593 mode->VTotal); 3594 ErrorF("HDisplay = %d, HSStart = %d\n", 3595 mode->CrtcHDisplay, mode->CrtcHSyncStart); 3596 ErrorF("HSEnd = %d, HSkey = %d\n", 3597 mode->CrtcHSyncEnd, mode->CrtcHSkew); 3598 ErrorF("VDisplay - %d, VSStart = %d, VSEnd = %d\n", 3599 mode->CrtcVDisplay, mode->CrtcVSyncStart, mode->CrtcVSyncEnd); 3600 ErrorF("VTotal = %d\n", 3601 mode->CrtcVTotal); 3602#endif 3603 3604 if (psav->IsSecondary) { 3605 refresh = SavageGetRefresh(mode); 3606 3607 SavageMatchBiosMode(pScrn,mode->HDisplay,mode->VDisplay,refresh, 3608 &newmode,&newrefresh); 3609 new->mode = newmode; 3610 new->refresh = newrefresh; 3611 3612 /* do it! */ 3613 SavageWriteMode(pScrn, vganew, new, TRUE); 3614 3615 if (psav->FBStart2nd) { 3616 SavageStreamsOn(pScrn); 3617 SavageInitSecondaryStream(pScrn); 3618 } 3619 3620 SavageAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 3621 return TRUE; 3622 } 3623 3624 3625 if (pScrn->bitsPerPixel == 8) 3626 psav->HorizScaleFactor = 1; 3627 else if (pScrn->bitsPerPixel == 16) 3628 psav->HorizScaleFactor = 1; /* I don't think we ever want 2 */ 3629 else 3630 psav->HorizScaleFactor = 1; 3631 3632 if (psav->HorizScaleFactor == 2) 3633 if (!mode->CrtcHAdjusted) { 3634 mode->CrtcHDisplay *= 2; 3635 mode->CrtcHSyncStart *= 2; 3636 mode->CrtcHSyncEnd *= 2; 3637 mode->CrtcHBlankStart *= 2; 3638 mode->CrtcHBlankEnd *= 2; 3639 mode->CrtcHTotal *= 2; 3640 mode->CrtcHSkew *= 2; 3641 mode->CrtcHAdjusted = TRUE; 3642 } 3643 3644 if (!vgaHWInit(pScrn, mode)) 3645 return FALSE; 3646 3647 new->mode = 0; 3648 3649 /* We need to set CR67 whether or not we use the BIOS. */ 3650 3651 dclk = mode->Clock; 3652 new->CR67 = 0x00; 3653 3654 switch( pScrn->depth ) { 3655 case 8: 3656 if( (psav->Chipset == S3_SAVAGE2000) && (dclk >= 230000) ) 3657 new->CR67 = 0x10; /* 8bpp, 2 pixels/clock */ 3658 else 3659 new->CR67 = 0x00; /* 8bpp, 1 pixel/clock */ 3660 break; 3661 case 15: 3662 if( 3663 S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || 3664 ((psav->Chipset == S3_SAVAGE2000) && (dclk >= 230000)) 3665 ) 3666 new->CR67 = 0x30; /* 15bpp, 2 pixel/clock */ 3667 else 3668 new->CR67 = 0x20; /* 15bpp, 1 pixels/clock */ 3669 break; 3670 case 16: 3671 if( 3672 S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || 3673 ((psav->Chipset == S3_SAVAGE2000) && (dclk >= 230000)) 3674 ) 3675 new->CR67 = 0x50; /* 16bpp, 2 pixel/clock */ 3676 else 3677 new->CR67 = 0x40; /* 16bpp, 1 pixels/clock */ 3678 break; 3679 case 24: 3680 if (psav->primStreamBpp == 24 ) 3681 new->CR67 = 0x70; 3682 else 3683 new->CR67 = 0xd0; 3684 break; 3685 } 3686 3687 3688 if( psav->UseBIOS ) { 3689 int refresh; 3690 unsigned int newmode=0, newrefresh=0; 3691 3692 refresh = SavageGetRefresh(mode); 3693 3694 SavageMatchBiosMode(pScrn,mode->HDisplay,mode->VDisplay,refresh, 3695 &newmode,&newrefresh); 3696 new->mode = newmode; 3697 new->refresh = newrefresh; 3698 } 3699 3700 if( !new->mode ) { 3701 /* 3702 * Either BIOS use is disabled, or we failed to find a suitable 3703 * match. Fall back to traditional register-crunching. 3704 */ 3705 3706 VGAOUT8(vgaCRIndex, 0x3a); 3707 tmp = VGAIN8(vgaCRReg); 3708 if (psav->pci_burst) 3709 new->CR3A = (tmp & 0x7f) | 0x15; 3710 else 3711 new->CR3A = tmp | 0x95; 3712 3713 new->CR53 = 0x00; 3714 new->CR31 = 0x8c; 3715 new->CR66 = 0x89; 3716 3717 VGAOUT8(vgaCRIndex, 0x58); 3718 new->CR58 = VGAIN8(vgaCRReg) & 0x80; 3719 new->CR58 |= 0x13; 3720 3721#if 0 3722 VGAOUT8(vgaCRIndex, 0x55); 3723 new->CR55 = VGAIN8(vgaCRReg); 3724 if (psav->hwcursor) 3725 new->CR55 |= 0x10; 3726#endif 3727 3728 new->SR15 = 0x03 | 0x80; 3729 new->SR18 = 0x00; 3730 3731 3732 /* enable gamma correction */ 3733 if( pScrn->depth == 24 ) 3734 new->SR1B = 0x18; 3735 else 3736 new->SR1B = 0x00; 3737 3738 /* set 8-bit CLUT */ 3739 new->SR1B |= 0x10; 3740 3741 new->CR43 = new->CR45 = new->CR65 = 0x00; 3742 3743 VGAOUT8(vgaCRIndex, 0x40); 3744 new->CR40 = VGAIN8(vgaCRReg) & ~0x01; 3745 3746 new->MMPR0 = 0x010400; 3747 new->MMPR1 = 0x00; 3748 new->MMPR2 = 0x0808; 3749 new->MMPR3 = 0x08080810; 3750 3751 if (psav->fifo_aggressive || psav->fifo_moderate || 3752 psav->fifo_conservative) { 3753 new->MMPR1 = 0x0200; 3754 new->MMPR2 = 0x1808; 3755 new->MMPR3 = 0x08081810; 3756 } 3757 3758 if (psav->MCLK <= 0) { 3759 new->SR10 = 255; 3760 new->SR11 = 255; 3761 } 3762 3763 psav->NeedSTREAMS = FALSE; 3764 3765 SavageCalcClock(dclk, 1, 1, 127, 0, 4, 180000, 360000, 3766 &m, &n, &r); 3767 new->SR12 = (r << 6) | (n & 0x3f); 3768 new->SR13 = m & 0xff; 3769 new->SR29 = (r & 4) | (m & 0x100) >> 5 | (n & 0x40) >> 2; 3770 3771 if (psav->fifo_moderate) { 3772 if (psav->primStreamBpp < 24) 3773 new->MMPR0 -= 0x8000; 3774 else 3775 new->MMPR0 -= 0x4000; 3776 } else if (psav->fifo_aggressive) { 3777 if (psav->primStreamBpp < 24) 3778 new->MMPR0 -= 0xc000; 3779 else 3780 new->MMPR0 -= 0x6000; 3781 } 3782 3783 if (mode->Flags & V_INTERLACE) 3784 new->CR42 = 0x20; 3785 else 3786 new->CR42 = 0x00; 3787 3788 new->CR34 = 0x10; 3789 3790 i = ((((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8) | 3791 ((((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) | 3792 ((((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) | 3793 ((mode->CrtcHSyncStart & 0x800) >> 7); 3794 3795 if ((mode->CrtcHSyncEnd >> 3) - (mode->CrtcHSyncStart >> 3) > 64) 3796 i |= 0x08; 3797 if ((mode->CrtcHSyncEnd >> 3) - (mode->CrtcHSyncStart >> 3) > 32) 3798 i |= 0x20; 3799 j = (vganew->CRTC[0] + ((i & 0x01) << 8) + 3800 vganew->CRTC[4] + ((i & 0x10) << 4) + 1) / 2; 3801 if (j - (vganew->CRTC[4] + ((i & 0x10) << 4)) < 4) { 3802 if (vganew->CRTC[4] + ((i & 0x10) << 4) + 4 <= 3803 vganew->CRTC[0] + ((i & 0x01) << 8)) 3804 j = vganew->CRTC[4] + ((i & 0x10) << 4) + 4; 3805 else 3806 j = vganew->CRTC[0] + ((i & 0x01) << 8) + 1; 3807 } 3808 3809 new->CR3B = j & 0xff; 3810 i |= (j & 0x100) >> 2; 3811 new->CR3C = (vganew->CRTC[0] + ((i & 0x01) << 8)) / 2 ; 3812 new->CR5D = i; 3813 new->CR5E = (((mode->CrtcVTotal - 2) & 0x400) >> 10) | 3814 (((mode->CrtcVDisplay - 1) & 0x400) >> 9) | 3815 (((mode->CrtcVSyncStart) & 0x400) >> 8) | 3816 (((mode->CrtcVSyncStart) & 0x400) >> 6) | 0x40; 3817 width = (pScrn->displayWidth * (psav->primStreamBpp / 8)) >> 3; 3818 new->CR91 = vganew->CRTC[19] = 0xff & width; 3819 new->CR51 = (0x300 & width) >> 4; 3820 new->CR90 = 0x80 | (width >> 8); 3821 vganew->MiscOutReg |= 0x0c; 3822 3823 /* Set frame buffer description. */ 3824 3825 if (psav->primStreamBpp <= 8) 3826 new->CR50 = 0; 3827 else if (psav->primStreamBpp <= 16) 3828 new->CR50 = 0x10; 3829 else 3830 new->CR50 = 0x30; 3831 3832 if (pScrn->displayWidth == 640) 3833 new->CR50 |= 0x40; 3834 else if (pScrn->displayWidth == 800) 3835 new->CR50 |= 0x80; 3836 else if (pScrn->displayWidth == 1024) 3837 new->CR50 |= 0x00; 3838 else if (pScrn->displayWidth == 1152) 3839 new->CR50 |= 0x01; 3840 else if (pScrn->displayWidth == 1280) 3841 new->CR50 |= 0xc0; 3842 else if (pScrn->displayWidth == 1600) 3843 new->CR50 |= 0x81; 3844 else 3845 new->CR50 |= 0xc1; /* Use GBD */ 3846 3847 if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) 3848 new->CR33 = 0x00; 3849 else 3850 new->CR33 = 0x08; 3851 3852 vganew->CRTC[0x17] = 0xeb; 3853 3854 new->CR67 |= 1; 3855 3856 VGAOUT8(vgaCRIndex, 0x36); 3857 new->CR36 = VGAIN8(vgaCRReg); 3858 VGAOUT8(vgaCRIndex, 0x68); 3859 new->CR68 = VGAIN8(vgaCRReg); 3860 3861 new->CR69 = 0; 3862 VGAOUT8(vgaCRIndex, 0x6f); 3863 new->CR6F = VGAIN8(vgaCRReg); 3864 VGAOUT8(vgaCRIndex, 0x86); 3865 new->CR86 = VGAIN8(vgaCRReg) | 0x08; 3866 VGAOUT8(vgaCRIndex, 0x88); 3867 new->CR88 = VGAIN8(vgaCRReg) | DISABLE_BLOCK_WRITE_2D; 3868 VGAOUT8(vgaCRIndex, 0xb0); 3869 new->CRB0 = VGAIN8(vgaCRReg) | 0x80; 3870 } 3871 3872 pScrn->vtSema = TRUE; 3873 3874 /* do it! */ 3875 SavageWriteMode(pScrn, vganew, new, TRUE); 3876 3877 if (psav->FBStart2nd) { 3878 SavageStreamsOn(pScrn); 3879 SavageInitSecondaryStream(pScrn); 3880 } 3881 3882 SavageAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 3883 3884 return TRUE; 3885} 3886 3887 3888static Bool SavageCloseScreen(int scrnIndex, ScreenPtr pScreen) 3889{ 3890 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 3891 vgaHWPtr hwp = VGAHWPTR(pScrn); 3892 SavagePtr psav = SAVPTR(pScrn); 3893 vgaRegPtr vgaSavePtr = &hwp->SavedReg; 3894 SavageRegPtr SavageSavePtr = &psav->SavedReg; 3895 3896 TRACE(("SavageCloseScreen\n")); 3897 3898#ifdef XF86DRI 3899 if (psav->directRenderingEnabled) { 3900 SAVAGEDRICloseScreen(pScreen); 3901 /* reset shadow values */ 3902 SavageInitShadowStatus(pScrn); 3903 psav->directRenderingEnabled=FALSE; 3904 } 3905#endif 3906 3907 if (psav->EXADriverPtr) { 3908 exaDriverFini(pScreen); 3909 psav->EXADriverPtr = NULL; 3910 } 3911 3912 if( psav->AccelInfoRec ) { 3913 XAADestroyInfoRec( psav->AccelInfoRec ); 3914 psav->AccelInfoRec = NULL; 3915 } 3916 3917 if( psav->DGAModes ) { 3918 xfree( psav->DGAModes ); 3919 psav->DGAModes = NULL; 3920 psav->numDGAModes = 0; 3921 } 3922 3923 if (pScrn->vtSema) { 3924 if (psav->FBStart2nd) 3925 SavageStreamsOff(pScrn); 3926 SavageWriteMode(pScrn, vgaSavePtr, SavageSavePtr, FALSE); 3927 SavageResetStreams(pScrn); 3928 vgaHWLock(hwp); 3929 SavageUnmapMem(pScrn, 0); 3930 } 3931 3932 if (psav->pVbe) 3933 vbeFree(psav->pVbe); 3934 psav->pVbe = NULL; 3935 3936 pScrn->vtSema = FALSE; 3937 pScreen->CloseScreen = psav->CloseScreen; 3938 3939 return (*pScreen->CloseScreen)(scrnIndex, pScreen); 3940} 3941 3942 3943static Bool SavageSaveScreen(ScreenPtr pScreen, int mode) 3944{ 3945 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 3946 3947 TRACE(("SavageSaveScreen(0x%x)\n", mode)); 3948 3949 if( pScrn->vtSema && SAVPTR(pScrn)->hwcursor && SAVPTR(pScrn)->hwc_on ) 3950 { 3951 if( xf86IsUnblank(mode) ) 3952 SavageShowCursor( pScrn ); 3953 else 3954 SavageHideCursor( pScrn ); 3955 SAVPTR(pScrn)->hwc_on = TRUE; /*restore */ 3956 } 3957 3958 return vgaHWSaveScreen(pScreen, mode); 3959} 3960 3961void SavageAdjustFrame(int scrnIndex, int x, int y, int flags) 3962{ 3963 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 3964 SavagePtr psav = SAVPTR(pScrn); 3965 3966 if (psav->IsSecondary) { 3967 SavageDoAdjustFrame(pScrn, x, y, TRUE); 3968 } else { 3969 SavageDoAdjustFrame(pScrn, x, y, FALSE); 3970 } 3971 3972} 3973 3974void 3975SavageDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int crtc2) 3976{ 3977 SavagePtr psav = SAVPTR(pScrn); 3978 int address=0,top=0,left=0,tile_height,tile_size; 3979 3980 TRACE(("SavageDoAdjustFrame(%d,%d,%x)\n", x, y, flags)); 3981 3982 if (psav->Chipset == S3_SAVAGE2000) { 3983 tile_height = TILEHEIGHT_2000; /* 32 */ 3984 tile_size = TILE_SIZE_BYTE_2000; /* 4096 */ 3985 } else { 3986 tile_height = TILEHEIGHT; /* 16 */ 3987 tile_size = TILE_SIZE_BYTE; /* 2048 */ 3988 } 3989 3990 if (!psav->bTiled) { 3991 left = x - x % 64; 3992 top = y; 3993 address = (top * psav->lDelta) + left * (pScrn->bitsPerPixel >> 3); 3994 address = (address >> 5) << 5; 3995 } else { 3996 top = y - y % tile_height; 3997 if (pScrn->bitsPerPixel == 16) { 3998 left = x - x % TILEWIDTH_16BPP; 3999 address = top * psav->lDelta + left * tile_size / TILEWIDTH_16BPP; 4000 } else if (pScrn->bitsPerPixel == 32) { 4001 left = x - x % TILEWIDTH_32BPP; 4002 address = top * psav->lDelta + left * tile_size / TILEWIDTH_32BPP; 4003 } 4004 } 4005 4006 address += pScrn->fbOffset; 4007 4008 if (psav->Chipset == S3_SAVAGE_MX) { 4009 if (!crtc2) { 4010 OUTREG32(PRI_STREAM_FBUF_ADDR0, address & 0xFFFFFFFC); 4011 OUTREG32(PRI_STREAM_FBUF_ADDR1, address & 0xFFFFFFFC);/* IGA1 */ 4012 } else { 4013 OUTREG32(PRI_STREAM2_FBUF_ADDR0, address & 0xFFFFFFFC);/* IGA2 */ 4014 OUTREG32(PRI_STREAM2_FBUF_ADDR1, address & 0xFFFFFFFC); 4015 } 4016 } else if (psav->Chipset == S3_SUPERSAVAGE) { 4017 if (!crtc2) { 4018 /* IGA1 */ 4019 OUTREG32(PRI_STREAM_FBUF_ADDR0, 0x80000000); 4020 OUTREG32(PRI_STREAM_FBUF_ADDR1, address & 0xFFFFFFF8); 4021 } else { 4022 /* IGA2 */ 4023 OUTREG32(PRI_STREAM2_FBUF_ADDR0, ((address & 0xFFFFFFF8) | 0x80000000)); 4024 OUTREG32(PRI_STREAM2_FBUF_ADDR1, address & 0xFFFFFFF8); 4025 } 4026 } else if (psav->Chipset == S3_SAVAGE2000) { 4027 /* certain Y values seems to cause havoc, not sure why */ 4028 OUTREG32(PRI_STREAM_FBUF_ADDR0, (address & 0xFFFFFFF8)); 4029 OUTREG32(PRI_STREAM2_FBUF_ADDR0, (address & 0xFFFFFFF8)); 4030 } else { 4031 OUTREG32(PRI_STREAM_FBUF_ADDR0,address | 0xFFFFFFFC); 4032 OUTREG32(PRI_STREAM_FBUF_ADDR1,address | 0x80000000); 4033 } 4034 4035 return; 4036} 4037 4038Bool SavageSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) 4039{ 4040 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 4041 SavagePtr psav = SAVPTR(pScrn); 4042 Bool success; 4043 4044 TRACE(("SavageSwitchMode\n")); 4045 4046 if (psav->FBStart2nd || (psav->videoFlags & VF_STREAMS_ON)) 4047 SavageStreamsOff(xf86Screens[scrnIndex]); 4048 4049 success = SavageModeInit(xf86Screens[scrnIndex], mode); 4050 4051 /* switching mode on primary will reset secondary. it needs to be reset as well*/ 4052 if (psav->IsPrimary) { 4053 DevUnion* pPriv; 4054 SavageEntPtr pSavEnt; 4055 pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 4056 gSavageEntityIndex); 4057 pSavEnt = pPriv->ptr; 4058 SavageModeInit(pSavEnt->pSecondaryScrn, pSavEnt->pSecondaryScrn->currentMode); 4059 } 4060 SavagePanningCheck(pScrn); 4061 4062 return success; 4063} 4064 4065 4066void SavageEnableMMIO(ScrnInfoPtr pScrn) 4067{ 4068 vgaHWPtr hwp = VGAHWPTR(pScrn); 4069 SavagePtr psav = SAVPTR(pScrn); 4070 int vgaCRIndex, vgaCRReg; 4071 unsigned char val; 4072 4073 TRACE(("SavageEnableMMIO\n")); 4074 4075 vgaHWSetStdFuncs(hwp); 4076 vgaHWSetMmioFuncs(hwp, psav->MapBase, 0x8000); 4077 val = VGAIN8(0x3c3); 4078 VGAOUT8(0x3c3, val | 0x01); 4079 val = VGAIN8(VGA_MISC_OUT_R); 4080 VGAOUT8(VGA_MISC_OUT_W, val | 0x01); 4081 vgaCRIndex = psav->vgaIOBase + 4; 4082 vgaCRReg = psav->vgaIOBase + 5; 4083 4084 if( psav->Chipset >= S3_SAVAGE4 ) 4085 { 4086 VGAOUT8(vgaCRIndex, 0x40); 4087 val = VGAIN8(vgaCRReg); 4088 VGAOUT8(vgaCRReg, val | 1); 4089 } 4090 4091 return; 4092} 4093 4094 4095void SavageDisableMMIO(ScrnInfoPtr pScrn) 4096{ 4097 vgaHWPtr hwp = VGAHWPTR(pScrn); 4098 SavagePtr psav = SAVPTR(pScrn); 4099 int vgaCRIndex, vgaCRReg; 4100 unsigned char val; 4101 4102 TRACE(("SavageDisableMMIO\n")); 4103 4104 vgaCRIndex = psav->vgaIOBase + 4; 4105 vgaCRReg = psav->vgaIOBase + 5; 4106 4107 if( psav->Chipset >= S3_SAVAGE4 ) 4108 { 4109 VGAOUT8(vgaCRIndex, 0x40); 4110 val = VGAIN8(vgaCRReg); 4111 VGAOUT8(vgaCRReg, val | 1); 4112 } 4113 4114 vgaHWSetStdFuncs(hwp); 4115 4116 return; 4117} 4118 4119void SavageLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies, 4120 LOCO *colors, VisualPtr pVisual) 4121{ 4122 SavagePtr psav = SAVPTR(pScrn); 4123 int i, index; 4124 int updateKey = -1; 4125 unsigned char byte = 0; 4126 4127 /* choose CLUT */ 4128 if (psav->IsPrimary) { 4129 /* enable CLUT 1 */ 4130 VGAOUT8(0x3c4, 0x21); 4131 byte = VGAIN8(0x3c5); 4132 VGAOUT8(0x3c5, (byte & ~0x01)); 4133 /* select CLUT 1 */ 4134 VGAOUT8(0x3c4, 0x47); 4135 byte = VGAIN8(0x3c5); 4136 VGAOUT8(0x3c5, (byte & ~0x03) | 0x01); /* CLUT 1 */ 4137 } else if (psav->IsSecondary) { 4138 /* enable CLUT 2 */ 4139 VGAOUT8(0x3c4, 0x21); 4140 byte = VGAIN8(0x3c5); 4141 VGAOUT8(0x3c5, (byte & ~0x10)); 4142 /* select CLUT 2 */ 4143 VGAOUT8(0x3c4, 0x47); 4144 byte = VGAIN8(0x3c5); 4145 VGAOUT8(0x3c5, (byte & ~0x03) | 0x02); /* CLUT 2 */ 4146 } 4147 4148 for (i=0; i<numColors; i++) { 4149 index = indicies[i]; 4150 if (index == pScrn->colorKey) updateKey = index; 4151 VGAOUT8(0x3c8, index); 4152 VGAOUT8(0x3c9, colors[index].red); 4153 VGAOUT8(0x3c9, colors[index].green); 4154 VGAOUT8(0x3c9, colors[index].blue); 4155 } 4156 4157 /* restore saved CLUT index value */ 4158 if (psav->IsPrimary || psav->IsSecondary) { 4159 VGAOUT8(0x3c4, 0x47); 4160 VGAOUT8(0x3c5, byte); 4161 } 4162 4163 if (updateKey != -1) 4164 SavageUpdateKey(pScrn, colors[updateKey].red, colors[updateKey].green, 4165 colors[updateKey].blue); 4166} 4167 4168#define Shift(v,d) ((d) < 0 ? ((v) >> (-d)) : ((v) << (d))) 4169 4170static void 4171SavageUpdateKey(ScrnInfoPtr pScrn, int r, int g, int b) 4172{ 4173 ScreenPtr pScreen; 4174 SavagePtr psav = SAVPTR(pScrn); 4175 FbOverlayScrPrivPtr pScrOvlPriv; 4176 CARD32 key; 4177 int ul = 0, ol = 1; 4178 4179 if (pScrn->depth != 8) { 4180 ul = 1; 4181 ol = 0; 4182 } 4183 if (!(pScreen = pScrn->pScreen) 4184 || !(pScrOvlPriv = fbOverlayGetScrPriv(pScreen))) 4185 return; 4186 key = ((Shift(r,psav->overlay.redShift) & psav->overlay.redMask) 4187 | (Shift(g,psav->overlay.greenShift) & psav->overlay.greenMask) 4188 | (Shift(b,psav->overlay.blueShift) & psav->overlay.blueMask)); 4189 if (pScrOvlPriv->layer[ol].key != key) { 4190 pScrOvlPriv->layer[ol].key = key; 4191 (*pScrOvlPriv->PaintKey) (&pScrOvlPriv->layer[ol].u.run.pixmap->drawable, 4192 &pScrOvlPriv->layer[ul].u.run.region, 4193 pScrOvlPriv->layer[ol].key, ol); 4194 } 4195} 4196 4197#if 0 4198#define inStatus1() (hwp->readST01( hwp )) 4199#endif 4200 4201void SavageLoadPaletteSavage4(ScrnInfoPtr pScrn, int numColors, int *indicies, 4202 LOCO *colors, VisualPtr pVisual) 4203{ 4204 SavagePtr psav = SAVPTR(pScrn); 4205 int i, index; 4206 int updateKey = -1; 4207 4208 VerticalRetraceWait(); 4209 4210 for (i=0; i<numColors; i++) { 4211 if (!(inStatus1()) & 0x08) 4212 VerticalRetraceWait(); 4213 index = indicies[i]; 4214 VGAOUT8(0x3c8, index); 4215 VGAOUT8(0x3c9, colors[index].red); 4216 VGAOUT8(0x3c9, colors[index].green); 4217 VGAOUT8(0x3c9, colors[index].blue); 4218 if (index == pScrn->colorKey) updateKey = index; 4219 } 4220 if (updateKey != -1) 4221 SavageUpdateKey(pScrn, colors[updateKey].red, colors[updateKey].green, 4222 colors[updateKey].blue); 4223} 4224 4225static void SavageCalcClock(long freq, int min_m, int min_n1, int max_n1, 4226 int min_n2, int max_n2, long freq_min, 4227 long freq_max, unsigned int *mdiv, 4228 unsigned int *ndiv, unsigned int *r) 4229{ 4230 double ffreq, ffreq_min, ffreq_max; 4231 double div, diff, best_diff; 4232 unsigned int m; 4233 unsigned char n1, n2, best_n1=16+2, best_n2=2, best_m=125+2; 4234 4235 ffreq = freq / 1000.0 / BASE_FREQ; 4236 ffreq_max = freq_max / 1000.0 / BASE_FREQ; 4237 ffreq_min = freq_min / 1000.0 / BASE_FREQ; 4238 4239 if (ffreq < ffreq_min / (1 << max_n2)) { 4240 ErrorF("invalid frequency %1.3f Mhz\n", 4241 ffreq*BASE_FREQ); 4242 ffreq = ffreq_min / (1 << max_n2); 4243 } 4244 if (ffreq > ffreq_max / (1 << min_n2)) { 4245 ErrorF("invalid frequency %1.3f Mhz\n", 4246 ffreq*BASE_FREQ); 4247 ffreq = ffreq_max / (1 << min_n2); 4248 } 4249 4250 /* work out suitable timings */ 4251 4252 best_diff = ffreq; 4253 4254 for (n2=min_n2; n2<=max_n2; n2++) { 4255 for (n1=min_n1+2; n1<=max_n1+2; n1++) { 4256 m = (int)(ffreq * n1 * (1 << n2) + 0.5); 4257 if (m < min_m+2 || m > 127+2) 4258 continue; 4259 div = (double)(m) / (double)(n1); 4260 if ((div >= ffreq_min) && 4261 (div <= ffreq_max)) { 4262 diff = ffreq - div / (1 << n2); 4263 if (diff < 0.0) 4264 diff = -diff; 4265 if (diff < best_diff) { 4266 best_diff = diff; 4267 best_m = m; 4268 best_n1 = n1; 4269 best_n2 = n2; 4270 } 4271 } 4272 } 4273 } 4274 4275 *ndiv = best_n1 - 2; 4276 *r = best_n2; 4277 *mdiv = best_m - 2; 4278} 4279 4280 4281void SavageGEReset(ScrnInfoPtr pScrn, int from_timeout, int line, char *file) 4282{ 4283 unsigned char cr66; 4284 int r, success = 0; 4285 CARD32 fifo_control = 0, miu_control = 0; 4286 CARD32 streams_timeout = 0, misc_timeout = 0; 4287 vgaHWPtr hwp = VGAHWPTR(pScrn); 4288 SavagePtr psav = SAVPTR(pScrn); 4289 int vgaCRIndex, vgaCRReg, vgaIOBase; 4290 4291 TRACE(("SavageGEReset(%d,%s)\n", line, file)); 4292 4293 vgaIOBase = hwp->IOBase; 4294 vgaCRIndex = vgaIOBase + 4; 4295 vgaCRReg = vgaIOBase + 5; 4296 4297 if (from_timeout) { 4298 if (psav->GEResetCnt++ < 10 || xf86GetVerbosity() > 1) 4299 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4300 "SavageGEReset called from %s line %d\n", file, line); 4301 } else 4302 psav->WaitIdleEmpty(psav); 4303 4304 if (from_timeout && !S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) { 4305 fifo_control = INREG(FIFO_CONTROL_REG); 4306 miu_control = INREG(MIU_CONTROL_REG); 4307 streams_timeout = INREG(STREAMS_TIMEOUT_REG); 4308 misc_timeout = INREG(MISC_TIMEOUT_REG); 4309 } 4310 4311 VGAOUT8(vgaCRIndex, 0x66); 4312 cr66 = VGAIN8(vgaCRReg); 4313 4314 usleep(10000); 4315 for (r=1; r<10; r++) { 4316 VGAOUT8(vgaCRReg, cr66 | 0x02); 4317 usleep(10000); 4318 VGAOUT8(vgaCRReg, cr66 & ~0x02); 4319 usleep(10000); 4320 4321 if (!from_timeout) 4322 psav->WaitIdleEmpty(psav); 4323 OUTREG(DEST_SRC_STR, psav->Bpl << 16 | psav->Bpl); 4324 4325 usleep(10000); 4326 switch(psav->Chipset) { 4327 case S3_SAVAGE3D: 4328 case S3_SAVAGE_MX: 4329 success = (STATUS_WORD0 & 0x0008ffff) == 0x00080000; 4330 break; 4331 case S3_SAVAGE4: 4332 case S3_PROSAVAGE: 4333 case S3_PROSAVAGEDDR: 4334 case S3_TWISTER: 4335 case S3_SUPERSAVAGE: 4336 success = (ALT_STATUS_WORD0 & 0x0081ffff) == 0x00800000; 4337 break; 4338 case S3_SAVAGE2000: 4339 success = (ALT_STATUS_WORD0 & 0x008fffff) == 0; 4340 break; 4341 } 4342 if(!success) { 4343 usleep(10000); 4344 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4345 "restarting S3 graphics engine reset %2d ...\n", r); 4346 } 4347 else 4348 break; 4349 } 4350 4351 /* At this point, the FIFO is empty and the engine is idle. */ 4352 4353 if (from_timeout && !S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) { 4354 OUTREG(FIFO_CONTROL_REG, fifo_control); 4355 OUTREG(MIU_CONTROL_REG, miu_control); 4356 OUTREG(STREAMS_TIMEOUT_REG, streams_timeout); 4357 OUTREG(MISC_TIMEOUT_REG, misc_timeout); 4358 } 4359 4360 OUTREG(SRC_BASE, 0); 4361 OUTREG(DEST_BASE, 0); 4362 OUTREG(CLIP_L_R, ((0) << 16) | pScrn->displayWidth); 4363 OUTREG(CLIP_T_B, ((0) << 16) | psav->ScissB); 4364 OUTREG(MONO_PAT_0, ~0); 4365 OUTREG(MONO_PAT_1, ~0); 4366 4367 SavageSetGBD(pScrn); 4368 4369} 4370 4371 4372 4373/* This function is used to debug, it prints out the contents of s3 regs */ 4374 4375void 4376SavagePrintRegs(ScrnInfoPtr pScrn) 4377{ 4378 SavagePtr psav = SAVPTR(pScrn); 4379 unsigned char i; 4380 int vgaCRIndex = 0x3d4; 4381 int vgaCRReg = 0x3d5; 4382 4383 ErrorF( "SR x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF" ); 4384 4385 for( i = 0; i < 0x70; i++ ) { 4386 if( !(i % 16) ) 4387 ErrorF( "\nSR%xx ", i >> 4 ); 4388 VGAOUT8( 0x3c4, i ); 4389 ErrorF( " %02x", VGAIN8(0x3c5) ); 4390 } 4391 4392 ErrorF( "\n\nCR x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF" ); 4393 4394 for( i = 0; i < 0xB7; i++ ) { 4395 if( !(i % 16) ) 4396 ErrorF( "\nCR%xx ", i >> 4 ); 4397 VGAOUT8( vgaCRIndex, i ); 4398 ErrorF( " %02x", VGAIN8(vgaCRReg) ); 4399 } 4400 4401 ErrorF("\n\n"); 4402} 4403 4404static void SavageDPMS(ScrnInfoPtr pScrn, int mode, int flags) 4405{ 4406 SavagePtr psav = SAVPTR(pScrn); 4407 unsigned char sr8 = 0x00, srd = 0x00; 4408 4409 TRACE(("SavageDPMS(%d,%x)\n", mode, flags)); 4410 4411 if (psav->DisplayType == MT_CRT) { 4412 VGAOUT8(0x3c4, 0x08); 4413 sr8 = VGAIN8(0x3c5); 4414 sr8 |= 0x06; 4415 VGAOUT8(0x3c5, sr8); 4416 4417 VGAOUT8(0x3c4, 0x0d); 4418 srd = VGAIN8(0x3c5); 4419 4420 srd &= 0x03; 4421 4422 switch (mode) { 4423 case DPMSModeOn: 4424 break; 4425 case DPMSModeStandby: 4426 srd |= 0x10; 4427 break; 4428 case DPMSModeSuspend: 4429 srd |= 0x40; 4430 break; 4431 case DPMSModeOff: 4432 srd |= 0x50; 4433 break; 4434 default: 4435 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid DPMS mode %d\n", mode); 4436 break; 4437 } 4438 4439 VGAOUT8(0x3c4, 0x0d); 4440 VGAOUT8(0x3c5, srd); 4441 } 4442 4443 if (psav->DisplayType == MT_LCD || psav->DisplayType == MT_DFP) { 4444 if (S3_MOBILE_TWISTER_SERIES(psav->Chipset) && psav->UseBIOS) { 4445 SavageSetPanelEnabled(psav, (mode == DPMSModeOn)); 4446 } else { 4447 switch (mode) { 4448 case DPMSModeOn: 4449 VGAOUT8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */ 4450 VGAOUT8(0x3c5, VGAIN8(0x3c5) | 0x10); 4451 break; 4452 case DPMSModeStandby: 4453 case DPMSModeSuspend: 4454 case DPMSModeOff: 4455 VGAOUT8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */ 4456 VGAOUT8(0x3c5, VGAIN8(0x3c5) & ~0x10); 4457 break; 4458 default: 4459 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid DPMS mode %d\n", mode); 4460 break; 4461 } 4462 } 4463 } 4464 4465 return; 4466} 4467 4468static void 4469SavageProbeDDC(ScrnInfoPtr pScrn, int index) 4470{ 4471 vbeInfoPtr pVbe; 4472 4473 if (xf86LoadSubModule(pScrn, "vbe")) { 4474 xf86LoaderReqSymLists(vbeSymbols, NULL); 4475 pVbe = VBEInit(NULL, index); 4476 ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 4477 vbeFree(pVbe); 4478 } 4479} 4480 4481static unsigned int 4482SavageDDC1Read(ScrnInfoPtr pScrn) 4483{ 4484 register unsigned char tmp; 4485 SavagePtr psav = SAVPTR(pScrn); 4486 4487 UnLockExtRegs(); 4488 4489 VerticalRetraceWait(); 4490 4491 InI2CREG(tmp,psav->I2CPort); 4492 4493 return ((unsigned int) (tmp & 0x08)); 4494} 4495 4496static Bool 4497SavageDDC1(int scrnIndex) 4498{ 4499 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 4500 SavagePtr psav = SAVPTR(pScrn); 4501 unsigned char byte; 4502 xf86MonPtr pMon; 4503 4504 UnLockExtRegs(); 4505 4506 /* initialize chipset */ 4507 InI2CREG(byte,psav->I2CPort); 4508 OutI2CREG(byte | 0x12,psav->I2CPort); 4509 4510 pMon = xf86DoEDID_DDC1(scrnIndex,vgaHWddc1SetSpeedWeak(),SavageDDC1Read); 4511 if (!pMon) 4512 return FALSE; 4513 4514 xf86PrintEDID(pMon); 4515 4516 xf86SetDDCproperties(pScrn,pMon); 4517 4518 /* undo initialization */ 4519 OutI2CREG(byte,psav->I2CPort); 4520 4521 return TRUE; 4522} 4523 4524static void 4525SavageGetTvMaxSize(SavagePtr psav) 4526{ 4527 if( psav->PAL ) { 4528 psav->TVSizeX = 800; 4529 psav->TVSizeY = 600; 4530 } 4531 else { 4532 psav->TVSizeX = 640; 4533 psav->TVSizeY = 480; 4534 } 4535} 4536 4537 4538static Bool 4539SavagePanningCheck(ScrnInfoPtr pScrn) 4540{ 4541 SavagePtr psav = SAVPTR(pScrn); 4542 DisplayModePtr pMode; 4543 4544 pMode = pScrn->currentMode; 4545 psav->iResX = pMode->CrtcHDisplay; 4546 psav->iResY = pMode->CrtcVDisplay; 4547 4548 if ((psav->iResX < psav->PanelX || psav->iResY < psav->PanelY)) 4549 psav->FPExpansion = TRUE; 4550 else 4551 psav->FPExpansion = FALSE; 4552 4553 if( psav->iResX < pScrn->virtualX || psav->iResY < pScrn->virtualY ) 4554 return TRUE; 4555 else 4556 return FALSE; 4557} 4558 4559static void 4560SavageResetStreams(ScrnInfoPtr pScrn) 4561{ 4562 SavagePtr psav = SAVPTR(pScrn); 4563 unsigned char cr67; 4564 unsigned char cr69; 4565 4566 /* disable streams */ 4567 switch (psav->Chipset) { 4568 case S3_SAVAGE_MX: 4569 case S3_SUPERSAVAGE: 4570 OUTREG32(PRI_STREAM_STRIDE,0); 4571 OUTREG32(PRI_STREAM2_STRIDE, 0); 4572 OUTREG32(PRI_STREAM_FBUF_ADDR0,0x00000000); 4573 OUTREG32(PRI_STREAM_FBUF_ADDR1,0x00000000); 4574 OUTREG32(PRI_STREAM2_FBUF_ADDR0,0x00000000); 4575 OUTREG32(PRI_STREAM2_FBUF_ADDR1,0x00000000); 4576 OUTREG8(CRT_ADDRESS_REG, 0x67); 4577 cr67 = INREG8(CRT_DATA_REG); 4578 cr67 &= ~0x08; /* CR67[3] = 1 : Mem-mapped regs */ 4579 cr67 &= ~0x04; /* CR67[2] = 1 : enable stream 1 */ 4580 cr67 &= ~0x02; /* CR67[1] = 1 : enable stream 2 */ 4581 OUTREG8(CRT_DATA_REG, cr67); 4582 break; 4583 case S3_SAVAGE3D: 4584 case S3_SAVAGE4: 4585 case S3_TWISTER: 4586 case S3_PROSAVAGE: 4587 case S3_PROSAVAGEDDR: 4588 OUTREG32(PRI_STREAM_STRIDE,0); 4589 OUTREG32(PRI_STREAM_FBUF_ADDR0,0); 4590 OUTREG32(PRI_STREAM_FBUF_ADDR1,0); 4591 OUTREG8(CRT_ADDRESS_REG, 0x67); 4592 cr67 = INREG8(CRT_DATA_REG); 4593 cr67 &= ~0x0c; /* CR67[2] = 1 : enable stream 1 */ 4594 OUTREG8(CRT_DATA_REG, cr67); 4595 OUTREG8(CRT_ADDRESS_REG, 0x69); 4596 cr69 = INREG8(CRT_DATA_REG); 4597 cr69 &= ~0x80; /* CR69[0] = 1 : Mem-mapped regs */ 4598 OUTREG8(CRT_DATA_REG, cr69); 4599 break; 4600 case S3_SAVAGE2000: 4601 OUTREG32(PRI_STREAM_STRIDE,0); 4602 OUTREG32(PRI_STREAM_FBUF_ADDR0,0x00000000); 4603 OUTREG32(PRI_STREAM_FBUF_ADDR1,0x00000000); 4604 OUTREG8(CRT_ADDRESS_REG, 0x67); 4605 cr67 = INREG8(CRT_DATA_REG); 4606 cr67 &= ~0x08; /* CR67[3] = 1 : Mem-mapped regs */ 4607 cr67 &= ~0x04; /* CR67[2] = 1 : enable stream 1 */ 4608 cr67 &= ~0x02; /* CR67[1] = 1 : enable stream 2 */ 4609 OUTREG8(CRT_DATA_REG, cr67); 4610 break; 4611 default: 4612 break; 4613 } 4614 4615} 4616