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