savage_driver.c revision 38770048
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#ifdef HAVE_XAA_H 1270 if((strptr = (char *)xf86GetOptValString(psav->Options, OPTION_ACCELMETHOD))) { 1271 if(!xf86NameCmp(strptr,"XAA")) { 1272 from = X_CONFIG; 1273 psav->useEXA = FALSE; 1274 } else if(!xf86NameCmp(strptr,"EXA")) { 1275 from = X_CONFIG; 1276 psav->useEXA = TRUE; 1277 } 1278 } 1279#else 1280 psav->useEXA = TRUE; 1281#endif 1282 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration architecture\n", 1283 psav->useEXA ? "EXA" : "XAA"); 1284 } 1285 1286 if ((s = xf86GetOptValString(psav->Options, OPTION_OVERLAY))) { 1287 1288 if (psav->shadowFB) { 1289 xf86DrvMsg(pScrn->scrnIndex,X_INFO, 1290 "Option \"Overlay\" not supported with shadowFB\n"); 1291 } else { 1292 if (pScrn->depth == 8) { 1293 if (!*s || !xf86NameCmp(s, "24")) { 1294 psav->overlayDepth = 24; 1295 psav->NoAccel = TRUE; /* Preliminary */ 1296 pScrn->colorKey = TRANSPARENCY_KEY; 1297 pScrn->overlayFlags = OVERLAY_8_32_DUALFB; 1298 } else if (!xf86NameCmp(s, "16")) { 1299 psav->overlayDepth = 16; 1300 psav->NoAccel = TRUE; /* Preliminary */ 1301 pScrn->colorKey = TRANSPARENCY_KEY; 1302 pScrn->overlayFlags = OVERLAY_8_32_DUALFB; 1303 } else { 1304 xf86DrvMsg(pScrn->scrnIndex,X_WARNING,"Wrong argument: " 1305 "\"%s\" Ingnoring\n",s); 1306 } 1307 } else if (pScrn->depth != 15) { 1308 psav->overlayDepth = 8; 1309 psav->NoAccel = TRUE; /* Preliminary */ 1310 pScrn->colorKey = TRANSPARENCY_KEY; 1311 pScrn->overlayFlags = OVERLAY_8_32_DUALFB; 1312 if (*s && (xf86NameCmp(s, "8"))) 1313 xf86DrvMsg(pScrn->scrnIndex,X_WARNING,"Wrong argument: " 1314 "\"%s\" for depth %i overlay depth must be 8\n", 1315 s,pScrn->depth); 1316 } else { 1317 xf86DrvMsg(pScrn->scrnIndex,X_WARNING,"Overlay not " 1318 "supported for depth 15\n"); 1319 } 1320 if (psav->overlayDepth) { 1321 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"%i/%i Overlay enabled\n", 1322 pScrn->depth,psav->overlayDepth); 1323 psav->primStreamBpp = 8; 1324 } 1325 } 1326 } 1327 1328 if (pScrn->bitsPerPixel == 24 && !psav->NoAccel) { 1329 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1330 "HW acceleration not possible with depth 32 and bpp 24.\n"); 1331 psav->NoAccel = TRUE; 1332 } 1333 1334 /* 1335 * The SWCursor setting takes priority over HWCursor. The default 1336 * if neither is specified is HW, unless ShadowFB is specified, 1337 * then SW. 1338 */ 1339 1340 from = X_DEFAULT; 1341 psav->hwcursor = psav->shadowFB ? FALSE : TRUE; 1342 if (xf86GetOptValBool(psav->Options, OPTION_HWCURSOR, &psav->hwcursor)) 1343 from = X_CONFIG; 1344 if (xf86ReturnOptValBool(psav->Options, OPTION_SWCURSOR, FALSE)) { 1345 psav->hwcursor = FALSE; 1346 from = X_CONFIG; 1347 } 1348 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", 1349 psav->hwcursor ? "HW" : "SW"); 1350 1351 from = X_DEFAULT; 1352 psav->UseBIOS = TRUE; 1353 if (xf86GetOptValBool(psav->Options, OPTION_USEBIOS, &psav->UseBIOS) ) 1354 from = X_CONFIG; 1355 xf86DrvMsg(pScrn->scrnIndex, from, "%ssing video BIOS to set modes\n", 1356 psav->UseBIOS ? "U" : "Not u" ); 1357 1358 psav->LCDClock = 0.0; 1359 if( xf86GetOptValFreq( psav->Options, OPTION_LCDCLOCK, OPTUNITS_MHZ, &psav->LCDClock ) ) 1360 xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, 1361 "Option: LCDClock %1.2f MHz\n", psav->LCDClock ); 1362 1363 if( xf86GetOptValBool( psav->Options, OPTION_SHADOW_STATUS, &psav->ShadowStatus)) { 1364 xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, 1365 "Option: ShadowStatus %sabled\n", psav->ShadowStatus ? "en" : "dis" ); 1366 psav->ForceShadowStatus = TRUE; 1367 } else 1368 psav->ForceShadowStatus = FALSE; 1369 /* If ShadowStatus is off it will be automatically enabled for DRI. 1370 * If DRI initialization fails fall back to ConfigShadowStatus. */ 1371 psav->ConfigShadowStatus = psav->ShadowStatus; 1372 1373 if( xf86GetOptValBool( psav->Options, OPTION_CRT_ONLY, &psav->CrtOnly)) 1374 xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, 1375 "Option: CrtOnly enabled\n" ); 1376 1377 if( xf86GetOptValBool( psav->Options, OPTION_TV_ON, &psav->TvOn)) { 1378 psav->PAL = FALSE; 1379 SavageGetTvMaxSize(psav); 1380 } 1381 1382 if( xf86GetOptValBool( psav->Options, OPTION_TV_PAL, &psav->PAL)) { 1383 SavageGetTvMaxSize(psav); 1384 psav->TvOn = TRUE; 1385 } 1386 1387 if( psav->TvOn ) 1388 xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, 1389 "TV enabled in %s format\n", 1390 psav->PAL ? "PAL" : "NTSC" ); 1391 1392 psav->ForceInit = 0; 1393 if( xf86GetOptValBool( psav->Options, OPTION_FORCE_INIT, &psav->ForceInit)) 1394 xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, 1395 "Option: ForceInit enabled\n" ); 1396 1397 if (pScrn->numEntities > 1) { 1398 SavageFreeRec(pScrn); 1399 return FALSE; 1400 } 1401 1402 pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 1403#ifndef XSERVER_LIBPCIACCESS 1404 if (pEnt->resources) { 1405 free(pEnt); 1406 SavageFreeRec(pScrn); 1407 return FALSE; 1408 } 1409#endif 1410 psav->EntityIndex = pEnt->index; 1411 1412 if (xf86LoadSubModule(pScrn, "vbe")) { 1413 psav->pVbe = VBEInit(NULL, pEnt->index); 1414 } 1415 1416#ifndef XSERVER_LIBPCIACCESS 1417 xf86RegisterResources(pEnt->index, NULL, ResNone); 1418 xf86SetOperatingState(resVgaIo, pEnt->index, ResUnusedOpr); 1419 xf86SetOperatingState(resVgaMem, pEnt->index, ResDisableOpr); 1420#endif 1421 1422 from = X_DEFAULT; 1423 if (pEnt->device->chipset && *pEnt->device->chipset) { 1424 pScrn->chipset = pEnt->device->chipset; 1425 psav->ChipId = pEnt->device->chipID; 1426 from = X_CONFIG; 1427 } else if (pEnt->device->chipID >= 0) { 1428 psav->ChipId = pEnt->device->chipID; 1429 pScrn->chipset = (char *)xf86TokenToString(SavageChipsets, 1430 psav->Chipset); 1431 from = X_CONFIG; 1432 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", 1433 pEnt->device->chipID); 1434 } else { 1435 from = X_PROBED; 1436 psav->ChipId = DEVICE_ID(psav->PciInfo); 1437 pScrn->chipset = (char *)xf86TokenToString(SavageChipsets, 1438 psav->Chipset); 1439 } 1440 1441 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Chip: id %04x, \"%s\"\n", 1442 psav->ChipId, xf86TokenToString( SavageChips, psav->ChipId ) ); 1443 1444 if (pEnt->device->chipRev >= 0) { 1445 psav->ChipRev = pEnt->device->chipRev; 1446 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 1447 psav->ChipRev); 1448 } else 1449 psav->ChipRev = CHIP_REVISION(psav->PciInfo); 1450 1451 xf86DrvMsg(pScrn->scrnIndex, from, "Engine: \"%s\"\n", pScrn->chipset); 1452 1453 if (pEnt->device->videoRam != 0) 1454 pScrn->videoRam = pEnt->device->videoRam; 1455 1456 free(pEnt); 1457 1458#ifndef XSERVER_LIBPCIACCESS 1459 psav->PciTag = pciTag(psav->PciInfo->bus, psav->PciInfo->device, 1460 psav->PciInfo->func); 1461#endif 1462 1463 1464 /* Set AGP Mode from config */ 1465 /* We support 1X 2X and 4X */ 1466#ifdef SAVAGEDRI 1467#ifdef XSERVER_LIBPCIACCESS 1468 /* Try to read the AGP capabilty block from the device. If there is 1469 * no AGP info, the device is PCI. 1470 */ 1471 1472 psav->IsPCI = (pci_device_get_agp_info(psav->PciInfo) == NULL); 1473#else 1474 /* AGP/PCI (FK: copied from radeon_driver.c) */ 1475 /* Proper autodetection of an AGP capable device requires examining 1476 * PCI config registers to determine if the device implements extended 1477 * PCI capabilities, and then walking the capability list as indicated 1478 * in the PCI 2.2 and AGP 2.0 specifications, to determine if AGP 1479 * capability is present. The procedure is outlined as follows: 1480 * 1481 * 1) Test bit 4 (CAP_LIST) of the PCI status register of the device 1482 * to determine wether or not this device implements any extended 1483 * capabilities. If this bit is zero, then the device is a PCI 2.1 1484 * or earlier device and is not AGP capable, and we can conclude it 1485 * to be a PCI device. 1486 * 1487 * 2) If bit 4 of the status register is set, then the device implements 1488 * extended capabilities. There is an 8 bit wide capabilities pointer 1489 * register located at offset 0x34 in PCI config space which points to 1490 * the first capability in a linked list of extended capabilities that 1491 * this device implements. The lower two bits of this register are 1492 * reserved and MBZ so must be masked out. 1493 * 1494 * 3) The extended capabilities list is formed by one or more extended 1495 * capabilities structures which are aligned on DWORD boundaries. 1496 * The first byte of the structure is the capability ID (CAP_ID) 1497 * indicating what extended capability this structure refers to. The 1498 * second byte of the structure is an offset from the beginning of 1499 * PCI config space pointing to the next capability in the linked 1500 * list (NEXT_PTR) or NULL (0x00) at the end of the list. The lower 1501 * two bits of this pointer are reserved and MBZ. By examining the 1502 * CAP_ID of each capability and walking through the list, we will 1503 * either find the AGP_CAP_ID (0x02) indicating this device is an 1504 * AGP device, or we'll reach the end of the list, indicating it is 1505 * a PCI device. 1506 * 1507 * Mike A. Harris <mharris@redhat.com> 1508 * 1509 * References: 1510 * - PCI Local Bus Specification Revision 2.2, Chapter 6 1511 * - AGP Interface Specification Revision 2.0, Section 6.1.5 1512 */ 1513 1514 psav->IsPCI = TRUE; 1515 1516 if (pciReadLong(psav->PciTag, PCI_CMD_STAT_REG) & SAVAGE_CAP_LIST) { 1517 CARD32 cap_ptr, cap_id; 1518 1519 cap_ptr = pciReadLong(psav->PciTag, 1520 SAVAGE_CAPABILITIES_PTR_PCI_CONFIG) 1521 & SAVAGE_CAP_PTR_MASK; 1522 1523 while(cap_ptr != SAVAGE_CAP_ID_NULL) { 1524 cap_id = pciReadLong(psav->PciTag, cap_ptr); 1525 if ((cap_id & 0xff) == SAVAGE_CAP_ID_AGP) { 1526 psav->IsPCI = FALSE; 1527 break; 1528 } 1529 cap_ptr = (cap_id >> 8) & SAVAGE_CAP_PTR_MASK; 1530 } 1531 } 1532#endif 1533 1534 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "%s card detected\n", 1535 (psav->IsPCI) ? "PCI" : "AGP"); 1536 1537 if ((s = xf86GetOptValString(psav->Options, OPTION_BUS_TYPE))) { 1538 if (strcmp(s, "AGP") == 0) { 1539 if (psav->IsPCI) { 1540 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1541 "BusType AGP not available on PCI card\n"); 1542 } else { 1543 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "BusType set to AGP\n"); 1544 } 1545 } else if (strcmp(s, "PCI") == 0) { 1546 psav->IsPCI = TRUE; 1547 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "BusType set to PCI\n"); 1548 } else { 1549 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1550 "Invalid BusType option, using %s DMA\n", 1551 psav->IsPCI ? "PCI" : "AGP"); 1552 } 1553 } 1554 1555 psav->AgpDMA = !psav->IsPCI; 1556 if ((s = xf86GetOptValString(psav->Options, OPTION_DMA_TYPE))) { 1557 if (strcmp(s, "AGP") == 0) { 1558 if (psav->IsPCI) { 1559 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1560 "AGP DMA not available on PCI card, using PCI DMA\n"); 1561 } else { 1562 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using AGP DMA\n"); 1563 } 1564 } else if (strcmp(s, "PCI") == 0) { 1565 psav->AgpDMA = FALSE; 1566 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using PCI DMA\n"); 1567 } else { 1568 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1569 "Invalid DmaType option, using %s DMA\n", 1570 psav->AgpDMA ? "AGP" : "PCI"); 1571 } 1572 } else { 1573 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, 1574 "Using %s DMA\n", psav->AgpDMA ? "AGP" : "PCI"); 1575 } 1576 1577 psav->CommandDMA = TRUE; 1578 psav->VertexDMA = TRUE; 1579 from = X_DEFAULT; 1580 if ((s = xf86GetOptValString(psav->Options, OPTION_DMA_MODE))) { 1581 from = X_CONFIG; 1582 if (strcmp(s, "Command") == 0) 1583 psav->VertexDMA = FALSE; 1584 else if (strcmp(s, "Vertex") == 0) 1585 psav->CommandDMA = FALSE; 1586 else if (strcmp(s, "None") == 0) 1587 psav->VertexDMA = psav->CommandDMA = FALSE; 1588 else if (strcmp(s, "Any") != 0) { 1589 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Invalid DmaMode option\n"); 1590 from = X_DEFAULT; 1591 } 1592 } 1593 if (psav->CommandDMA && S3_SAVAGE3D_SERIES(psav->Chipset)) { 1594 xf86DrvMsg(pScrn->scrnIndex, from == X_CONFIG ? X_WARNING : X_INFO, 1595 "Savage3D/MX/IX does not support command DMA.\n"); 1596 psav->CommandDMA = FALSE; 1597 } 1598 if ((psav->CommandDMA || psav->VertexDMA) && 1599 psav->Chipset == S3_SUPERSAVAGE) { 1600 xf86DrvMsg(pScrn->scrnIndex, from == X_CONFIG ? X_WARNING : X_INFO, 1601 "DMA is not supported on SuperSavages.\n"); 1602 psav->CommandDMA = psav->VertexDMA = FALSE; 1603 } 1604 if (psav->CommandDMA && psav->VertexDMA) 1605 xf86DrvMsg(pScrn->scrnIndex, from, 1606 "Will try command and vertex DMA mode\n"); 1607 else if (psav->CommandDMA && !psav->VertexDMA) 1608 xf86DrvMsg(pScrn->scrnIndex, from, 1609 "Will try only command DMA mode\n"); 1610 else if (!psav->CommandDMA && psav->VertexDMA) 1611 xf86DrvMsg(pScrn->scrnIndex, from, 1612 "Will try only vertex DMA mode\n"); 1613 else 1614 xf86DrvMsg(pScrn->scrnIndex, from, 1615 "DMA disabled\n"); 1616 1617 if (!psav->IsPCI) { 1618 from = X_DEFAULT; 1619 psav->agpMode = SAVAGE_DEFAULT_AGP_MODE; 1620 /*psav->agpMode = SAVAGE_MAX_AGP_MODE;*/ 1621 psav->agpSize = 16; 1622 1623 if (xf86GetOptValInteger(psav->Options, 1624 OPTION_AGP_MODE, &(psav->agpMode))) { 1625 if (psav->agpMode < 1) { 1626 psav->agpMode = 1; 1627 } 1628 if (psav->agpMode > SAVAGE_MAX_AGP_MODE) { 1629 psav->agpMode = SAVAGE_MAX_AGP_MODE; 1630 } 1631 if ((psav->agpMode > 2) && 1632 (psav->Chipset == S3_SAVAGE3D || 1633 psav->Chipset == S3_SAVAGE_MX)) 1634 psav->agpMode = 2; /* old savages only support 2x */ 1635 from = X_CONFIG; 1636 } 1637 1638 xf86DrvMsg(pScrn->scrnIndex, from, "Using AGP %dx mode\n", 1639 psav->agpMode); 1640 1641 from = X_DEFAULT; 1642 if (xf86GetOptValInteger(psav->Options, 1643 OPTION_AGP_SIZE, (int *)&(psav->agpSize))) { 1644 switch (psav->agpSize) { 1645 case 4: 1646 case 8: 1647 case 16: 1648 case 32: 1649 case 64: 1650 case 128: 1651 case 256: 1652 from = X_CONFIG; 1653 break; 1654 default: 1655 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1656 "Illegal AGP size: %d MB, defaulting to 16 MB\n", psav->agpSize); 1657 psav->agpSize = 16; 1658 } 1659 } 1660 1661 xf86DrvMsg(pScrn->scrnIndex, from, 1662 "Using %d MB AGP aperture\n", psav->agpSize); 1663 } else { 1664 psav->agpMode = 0; 1665 psav->agpSize = 0; 1666 } 1667 1668#endif 1669 1670 /* we can use Option "DisableTile TRUE" to disable tile mode */ 1671 psav->bDisableTile = FALSE; 1672 if (xf86GetOptValBool(psav->Options, OPTION_DISABLE_TILE,&psav->bDisableTile)) { 1673 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1674 "Option: %s Tile Mode and Program it \n",(psav->bDisableTile?"Disable":"Enable")); 1675 } 1676 1677#ifdef SAVAGEDRI 1678 /* disabled by default...doesn't seem to work */ 1679 psav->bDisableXvMC = TRUE; /* if you want to free up more mem for DRI,etc. */ 1680 if (xf86GetOptValBool(psav->Options, OPTION_DISABLE_XVMC, &psav->bDisableXvMC)) { 1681 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1682 "Option: %s Hardware XvMC support\n",(psav->bDisableXvMC?"Disable":"Enable")); 1683 } 1684#endif 1685 1686 psav->disableCOB = FALSE; /* if you are having problems on savage4+ */ 1687 if (xf86GetOptValBool(psav->Options, OPTION_DISABLE_COB, &psav->disableCOB)) { 1688 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1689 "Option: %s the COB\n",(psav->disableCOB?"Disable":"Enable")); 1690 } 1691 if (psav->Chipset == S3_PROSAVAGE || 1692 psav->Chipset == S3_TWISTER || 1693 psav->Chipset == S3_PROSAVAGEDDR) 1694 psav->BCIforXv = TRUE; 1695 else 1696 psav->BCIforXv = FALSE; /* use the BCI for Xv */ 1697 if (xf86GetOptValBool(psav->Options, OPTION_BCI_FOR_XV, &psav->BCIforXv)) { 1698 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1699 "Option: %s use of the BCI for Xv\n",(psav->BCIforXv?"Enable":"Disable")); 1700 } 1701 psav->dvi = FALSE; 1702 if (xf86GetOptValBool(psav->Options, OPTION_DVI, &psav->dvi)) { 1703 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1704 "%s DVI port support (Savage4 only)\n",(psav->dvi?"Force":"Disable")); 1705 } 1706 1707#ifdef SAVAGEDRI 1708 psav->AGPforXv = FALSE; 1709 if (xf86GetOptValBool(psav->Options, OPTION_AGP_FOR_XV, &psav->AGPforXv)) { 1710 if (psav->AGPforXv) { 1711 if (psav->agpSize == 0) { 1712 psav->AGPforXv = FALSE; 1713 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "AGP not available, cannot use AGP for Xv\n"); 1714 } 1715 } 1716 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1717 "Option: %s use of AGP buffer for Xv\n",(psav->AGPforXv?"Enable":"Disable")); 1718 } 1719#endif 1720 1721 /* Add more options here. */ 1722 1723 1724 psav = SAVPTR(pScrn); 1725 psav->IsSecondary = FALSE; 1726 psav->IsPrimary = FALSE; 1727 psav->pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]); 1728 1729 if (xf86IsEntityShared(psav->pEnt->index)) { 1730 if (xf86IsPrimInitDone(psav->pEnt->index)) { 1731 1732 SavageEntPtr pSavageEnt = SavageEntPriv(pScrn); 1733 1734 psav->IsSecondary = TRUE; 1735 pSavageEnt->pSecondaryScrn = pScrn; 1736 psav->TvOn = pSavageEnt->TvOn; 1737 } else { 1738 SavageEntPtr pSavageEnt = SavageEntPriv(pScrn); 1739 1740 xf86SetPrimInitDone(psav->pEnt->index); 1741 1742 psav->IsPrimary = TRUE; 1743 pSavageEnt->pPrimaryScrn = pScrn; 1744 pSavageEnt->TvOn = psav->TvOn; 1745 } 1746 } 1747 1748 switch(psav->Chipset) { 1749 case S3_SAVAGE_MX: 1750 case S3_SUPERSAVAGE: 1751 psav->HasCRTC2 = TRUE; 1752 break; 1753 default: 1754 psav->HasCRTC2 = FALSE; 1755 } 1756 1757 if ((psav->IsSecondary || psav->IsPrimary) && !psav->UseBIOS) { 1758 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "BIOS currently required for Dualhead mode setting.\n"); 1759 return FALSE; 1760 } 1761 1762 if (psav->IsSecondary && 1763 (pScrn->bitsPerPixel > 16) && 1764 !psav->NoAccel && 1765 (psav->Chipset == S3_SAVAGE_MX)) { 1766 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No acceleration in Dualhead mode at depth 24\n"); 1767 return FALSE; 1768 } 1769 1770 /* maybe throw in some more sanity checks here */ 1771 1772 if (!SavageMapMem(pScrn)) { 1773 SavageFreeRec(pScrn); 1774 vbeFree(psav->pVbe); 1775 psav->pVbe = NULL; 1776 return FALSE; 1777 } 1778 1779 vgaCRIndex = psav->vgaIOBase + 4; 1780 vgaCRReg = psav->vgaIOBase + 5; 1781 1782 xf86EnableIO(); 1783 /* unprotect CRTC[0-7] */ 1784 VGAOUT8(vgaCRIndex, 0x11); 1785 tmp = VGAIN8(vgaCRReg); 1786 VGAOUT8(vgaCRReg, tmp & 0x7f); 1787 1788 /* unlock extended regs */ 1789 VGAOUT16(vgaCRIndex, 0x4838); 1790 VGAOUT16(vgaCRIndex, 0xa039); 1791 VGAOUT16(0x3c4, 0x0608); 1792 1793 VGAOUT8(vgaCRIndex, 0x40); 1794 tmp = VGAIN8(vgaCRReg); 1795 VGAOUT8(vgaCRReg, tmp & ~0x01); 1796 1797 /* unlock sys regs */ 1798 VGAOUT8(vgaCRIndex, 0x38); 1799 VGAOUT8(vgaCRReg, 0x48); 1800 1801 { 1802 Gamma zeros = {0.0, 0.0, 0.0}; 1803 1804 if (!xf86SetGamma(pScrn, zeros)) { 1805 vbeFree(psav->pVbe); 1806 psav->pVbe = NULL; 1807 SavageFreeRec(pScrn); 1808 return FALSE; 1809 } 1810 } 1811 1812 /* Unlock system registers. */ 1813 VGAOUT16(vgaCRIndex, 0x4838); 1814 1815 /* Next go on to detect amount of installed ram */ 1816 1817 VGAOUT8(vgaCRIndex, 0x36); /* for register CR36 (CONFG_REG1), */ 1818 config1 = VGAIN8(vgaCRReg); /* get amount of vram installed */ 1819 1820 /* Compute the amount of video memory and offscreen memory. */ 1821 1822 if (!pScrn->videoRam) { 1823 static const unsigned char RamSavage3D[] = { 8, 4, 4, 2 }; 1824 static unsigned char RamSavage4[] = { 2, 4, 8, 12, 16, 32, 64, 32 }; 1825 static const unsigned char RamSavageMX[] = { 2, 8, 4, 16, 8, 16, 4, 16 }; 1826 static const unsigned char RamSavageNB[] = { 0, 2, 4, 8, 16, 32, 16, 2 }; 1827 1828 switch( psav->Chipset ) { 1829 case S3_SAVAGE3D: 1830 pScrn->videoRam = RamSavage3D[ (config1 & 0xC0) >> 6 ] * 1024; 1831 break; 1832 1833 case S3_SAVAGE4: 1834 /* 1835 * The Savage4 has one ugly special case to consider. On 1836 * systems with 4 banks of 2Mx32 SDRAM, the BIOS says 4MB 1837 * when it really means 8MB. Why do it the same when you 1838 * can do it different... 1839 */ 1840 VGAOUT8(vgaCRIndex, 0x68); /* memory control 1 */ 1841 if( (VGAIN8(vgaCRReg) & 0xC0) == (0x01 << 6) ) 1842 RamSavage4[1] = 8; 1843 1844 /*FALLTHROUGH*/ 1845 1846 case S3_SAVAGE2000: 1847 pScrn->videoRam = RamSavage4[ (config1 & 0xE0) >> 5 ] * 1024; 1848 break; 1849 1850 case S3_SAVAGE_MX: 1851 case S3_SUPERSAVAGE: 1852 pScrn->videoRam = RamSavageMX[ (config1 & 0x0E) >> 1 ] * 1024; 1853 break; 1854 1855 case S3_PROSAVAGE: 1856 case S3_PROSAVAGEDDR: 1857 case S3_TWISTER: 1858 pScrn->videoRam = RamSavageNB[ (config1 & 0xE0) >> 5 ] * 1024; 1859 break; 1860 1861 default: 1862 /* How did we get here? */ 1863 pScrn->videoRam = 0; 1864 break; 1865 } 1866 1867 psav->videoRambytes = pScrn->videoRam * 1024; 1868 1869 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1870 "probed videoram: %dk\n", 1871 pScrn->videoRam); 1872 } else { 1873 psav->videoRambytes = pScrn->videoRam * 1024; 1874 1875 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1876 "videoram = %dk\n", 1877 pScrn->videoRam); 1878 } 1879 1880 /* Get video RAM */ 1881 if( !pScrn->videoRam && psav->pVbe ) 1882 { 1883 /* If VBE is available, ask it about onboard memory. */ 1884 1885 VbeInfoBlock* vib; 1886 1887 vib = VBEGetVBEInfo( psav->pVbe ); 1888 pScrn->videoRam = vib->TotalMemory * 64; 1889 VBEFreeVBEInfo( vib ); 1890 1891 /* VBE often cuts 64k off of the RAM total. */ 1892 1893 if( pScrn->videoRam & 64 ) 1894 pScrn->videoRam += 64; 1895 1896 psav->videoRambytes = pScrn->videoRam * 1024; 1897 } 1898 1899 1900 /* 1901 * If we're running with acceleration, compute the command overflow 1902 * buffer location. The command overflow buffer must END at a 1903 * 4MB boundary; for all practical purposes, that means the very 1904 * end of the frame buffer. 1905 */ 1906 if (psav->NoAccel) { 1907 psav->cobIndex = 0; 1908 psav->cobSize = 0; 1909 } 1910 else if( ((S3_SAVAGE4_SERIES(psav->Chipset)) || 1911 (S3_SUPERSAVAGE == psav->Chipset)) && psav->disableCOB ) { 1912 /* 1913 * The Savage4 and ProSavage have COB coherency bugs which render 1914 * the buffer useless. 1915 */ 1916 /* 1917 psav->cobIndex = 2; 1918 psav->cobSize = 0x8000 << psav->cobIndex; 1919 */ 1920 psav->cobIndex = 0; 1921 psav->cobSize = 0; 1922 psav->bciThresholdHi = 32; 1923 psav->bciThresholdLo = 0; 1924 } else { 1925 /* We use 128kB for the COB on all other chips. */ 1926 psav->cobSize = 0x20000; 1927 if (S3_SAVAGE3D_SERIES(psav->Chipset) || 1928 psav->Chipset == S3_SAVAGE2000) { 1929 psav->cobIndex = 7; /* rev.A savage4 apparently also uses 7 */ 1930 } else { 1931 psav->cobIndex = 2; 1932 } 1933 /* max command size: 2560 entries */ 1934 psav->bciThresholdHi = psav->cobSize/4 + 32 - 2560; 1935 psav->bciThresholdLo = psav->bciThresholdHi - 2560; 1936 } 1937 1938 /* align cob to 128k */ 1939 psav->cobOffset = (psav->videoRambytes - psav->cobSize) & ~0x1ffff; 1940 1941 /* The cursor must be aligned on a 4k boundary. */ 1942 psav->CursorKByte = (psav->cobOffset >> 10) - 4; 1943 psav->endfb = (psav->CursorKByte << 10) - 1; 1944 1945 if (psav->IsPrimary) { 1946 pScrn->videoRam /= 2; 1947 psav->videoRambytes = pScrn->videoRam * 1024; 1948 psav->CursorKByte = (psav->videoRambytes >> 10) - 4; 1949 psav->endfb = (psav->CursorKByte << 10) - 1; 1950 psav->videoRambytes *= 2; 1951 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1952 "Using %dk of videoram for primary head\n", 1953 pScrn->videoRam); 1954 } 1955 1956 if(psav->IsSecondary) 1957 { 1958 pScrn->videoRam /= 2; 1959 /*psav->videoRambytes = pScrn->videoRam * 1024;*/ 1960 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1961 "Using %dk of videoram for secondary head\n", 1962 pScrn->videoRam); 1963 } 1964 1965 pScrn->fbOffset = (psav->IsSecondary) 1966 ? pScrn->videoRam * 1024 : 0; 1967 1968 /* reset graphics engine to avoid memory corruption */ 1969 VGAOUT8(vgaCRIndex, 0x66); 1970 cr66 = VGAIN8(vgaCRReg); 1971 VGAOUT8(vgaCRReg, cr66 | 0x02); 1972 usleep(10000); 1973 1974 VGAOUT8(vgaCRIndex, 0x66); 1975 VGAOUT8(vgaCRReg, cr66 & ~0x02); /* clear reset flag */ 1976 usleep(10000); 1977 1978 /* Set status word positions based on chip type. */ 1979 SavageInitStatus(pScrn); 1980 1981 /* check for DVI/flat panel */ 1982 dvi = FALSE; 1983 if (psav->Chipset == S3_SAVAGE4) { 1984 unsigned char sr30 = 0x00; 1985 VGAOUT8(0x3c4, 0x30); 1986 /* clear bit 1 */ 1987 VGAOUT8(0x3c5, VGAIN8(0x3c5) & ~0x02); 1988 sr30 = VGAIN8(0x3c5); 1989 if (sr30 & 0x02 /*0x04 */) { 1990 dvi = TRUE; 1991 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Digital Flat Panel Detected\n"); 1992 } 1993 } 1994 1995 if( (S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || 1996 S3_MOBILE_TWISTER_SERIES(psav->Chipset)) && !psav->CrtOnly ) { 1997 psav->DisplayType = MT_LCD; 1998 } else if (dvi || ((psav->Chipset == S3_SAVAGE4) && psav->dvi)) { 1999 psav->DisplayType = MT_DFP; 2000 } else { 2001 psav->DisplayType = MT_CRT; 2002 } 2003 2004 if (psav->IsSecondary) 2005 psav->DisplayType = MT_CRT; 2006 2007 /* Do the DDC dance. */ 2008 SavageDoDDC(pScrn); 2009 2010 /* set up ramdac max clock - might be altered by SavageGetPanelInfo */ 2011 if (pScrn->bitsPerPixel >= 24) 2012 psav->maxClock = 220000; 2013 else 2014 psav->maxClock = 250000; 2015 2016 /* detect current mclk */ 2017 VGAOUT8(0x3c4, 0x08); 2018 sr8 = VGAIN8(0x3c5); 2019 VGAOUT8(0x3c5, 0x06); 2020 VGAOUT8(0x3c4, 0x10); 2021 n = VGAIN8(0x3c5); 2022 VGAOUT8(0x3c4, 0x11); 2023 m = VGAIN8(0x3c5); 2024 VGAOUT8(0x3c4, 0x08); 2025 VGAOUT8(0x3c5, sr8); 2026 m &= 0x7f; 2027 n1 = n & 0x1f; 2028 n2 = (n >> 5) & 0x03; 2029 mclk = ((1431818 * (m+2)) / (n1+2) / (1 << n2) + 50) / 100; 2030 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected current MCLK value of %1.3f MHz\n", 2031 mclk / 1000.0); 2032 2033 pScrn->maxHValue = 2048 << 3; /* 11 bits of h_total 8-pixel units */ 2034 pScrn->maxVValue = 2048; /* 11 bits of v_total */ 2035 pScrn->virtualX = pScrn->display->virtualX; 2036 pScrn->virtualY = pScrn->display->virtualY; 2037 2038 /* Check LCD panel information */ 2039 2040 if(psav->DisplayType == MT_LCD) 2041 SavageGetPanelInfo(pScrn); 2042 2043 /* DisplayType will be reset if panel is not active */ 2044 if(psav->DisplayType == MT_LCD) 2045 SavageAddPanelMode(pScrn); 2046 2047#if 0 2048 if (psav->CrtOnly && !psav->UseBIOS) { 2049 VGAOUT8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */ 2050 VGAOUT8(0x3c5, VGAIN8(0x3c5) & ~0x10); /* disable FP */ 2051 if (S3_SAVAGE_MOBILE_SERIES(psav->Chipset) /*|| 2052 S3_MOBILE_TWISTER_SERIES(psav->Chipset)*/) { /* not sure this works on mobile prosavage */ 2053 VGAOUT8(0x3c4, 0x31); 2054 VGAOUT8(0x3c5, VGAIN8(0x3c5) & ~0x04); /* make sure crtc1 is crt source */ 2055 } 2056 } 2057#endif 2058 2059 if( psav->UseBIOS ) 2060 { 2061 /* Go probe the BIOS for all the modes and refreshes at this depth. */ 2062 2063 if( psav->ModeTable ) 2064 { 2065 SavageFreeBIOSModeTable( psav, &psav->ModeTable ); 2066 } 2067 2068 psav->ModeTable = SavageGetBIOSModeTable( psav, psav->primStreamBpp ); 2069 2070 if( !psav->ModeTable || !psav->ModeTable->NumModes ) { 2071 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2072 "Failed to fetch any BIOS modes. Disabling BIOS.\n"); 2073 psav->UseBIOS = FALSE; 2074 } 2075 else 2076 /*if( xf86Verbose )*/ 2077 { 2078 SavageModeEntryPtr pmt; 2079 2080 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2081 "Found %d modes at this depth:\n", 2082 psav->ModeTable->NumModes); 2083 2084 for( 2085 i = 0, pmt = psav->ModeTable->Modes; 2086 i < psav->ModeTable->NumModes; 2087 i++, pmt++ ) 2088 { 2089 int j; 2090 ErrorF( " [%03x] %d x %d", 2091 pmt->VesaMode, pmt->Width, pmt->Height ); 2092 for( j = 0; j < pmt->RefreshCount; j++ ) 2093 { 2094 ErrorF( ", %dHz", pmt->RefreshRate[j] ); 2095 } 2096 ErrorF( "\n"); 2097 } 2098 } 2099 } 2100 2101 clockRanges = xnfalloc(sizeof(ClockRange)); 2102 clockRanges->next = NULL; 2103 clockRanges->minClock = 10000; 2104 clockRanges->maxClock = psav->maxClock; 2105 clockRanges->clockIndex = -1; 2106 clockRanges->interlaceAllowed = TRUE; 2107 clockRanges->doubleScanAllowed = TRUE; 2108 clockRanges->ClockDivFactor = 1.0; 2109 clockRanges->ClockMulFactor = 1.0; 2110 2111 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 2112 pScrn->display->modes, clockRanges, NULL, 2113 256, 2048, 16 * pScrn->bitsPerPixel, 2114 128, 2048, 2115 pScrn->virtualX, pScrn->virtualY, 2116 psav->videoRambytes, LOOKUP_BEST_REFRESH); 2117 2118 if (i == -1) { 2119 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86ValidateModes failure\n"); 2120 SavageFreeRec(pScrn); 2121 vbeFree(psav->pVbe); 2122 psav->pVbe = NULL; 2123 return FALSE; 2124 } 2125 2126 xf86PruneDriverModes(pScrn); 2127 2128 if (i == 0 || pScrn->modes == NULL) { 2129 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 2130 SavageFreeRec(pScrn); 2131 vbeFree(psav->pVbe); 2132 psav->pVbe = NULL; 2133 return FALSE; 2134 } 2135 2136 xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 2137 pScrn->currentMode = pScrn->modes; 2138 xf86PrintModes(pScrn); 2139 xf86SetDpi(pScrn, 0, 0); 2140 2141 if (xf86LoadSubModule(pScrn, "fb") == NULL) { 2142 SavageFreeRec(pScrn); 2143 vbeFree(psav->pVbe); 2144 psav->pVbe = NULL; 2145 return FALSE; 2146 } 2147 2148 if( !psav->NoAccel ) { 2149 char *modName = NULL; 2150 2151 if (psav->useEXA) { 2152 modName = "exa"; 2153 XF86ModReqInfo req; 2154 int errmaj, errmin; 2155 memset(&req, 0, sizeof(req)); 2156 req.majorversion = 2; 2157 req.minorversion = 0; 2158 2159 if( !LoadSubModule(pScrn->module, modName, 2160 NULL, NULL, NULL, &req, &errmaj, &errmin) ) { 2161 LoaderErrorMsg(NULL, modName, errmaj, errmin); 2162 SavageFreeRec(pScrn); 2163 vbeFree(psav->pVbe); 2164 psav->pVbe = NULL; 2165 return FALSE; 2166 } 2167 } else { 2168 modName = "xaa"; 2169 if( !xf86LoadSubModule(pScrn, modName) ) { 2170 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2171 "Falling back to shadowfb\n"); 2172 psav->NoAccel = 1; 2173 psav->shadowFB = 1; 2174 } 2175 } 2176 } 2177 2178 if (psav->hwcursor) { 2179 if (!xf86LoadSubModule(pScrn, "ramdac")) { 2180 SavageFreeRec(pScrn); 2181 vbeFree(psav->pVbe); 2182 psav->pVbe = NULL; 2183 return FALSE; 2184 } 2185 } 2186 2187 if (psav->shadowFB) { 2188 if (!xf86LoadSubModule(pScrn, "shadowfb")) { 2189 SavageFreeRec(pScrn); 2190 vbeFree(psav->pVbe); 2191 psav->pVbe = NULL; 2192 return FALSE; 2193 } 2194 } 2195 vbeFree(psav->pVbe); 2196 2197 psav->pVbe = NULL; 2198 2199 return TRUE; 2200} 2201 2202 2203static Bool SavageEnterVT(VT_FUNC_ARGS_DECL) 2204{ 2205 SCRN_INFO_PTR(arg); 2206#ifdef SAVAGEDRI 2207 SavagePtr psav = SAVPTR(pScrn); 2208 ScreenPtr pScreen; 2209#endif 2210 2211 gpScrn = pScrn; 2212 SavageEnableMMIO(pScrn); 2213 2214#ifdef SAVAGEDRI 2215 if (psav->directRenderingEnabled) { 2216 pScreen = xf86ScrnToScreen(pScrn); 2217 SAVAGEDRIResume(pScreen); 2218 DRIUnlock(pScreen); 2219 psav->LockHeld = 0; 2220 } 2221#endif 2222 if (!SAVPTR(pScrn)->IsSecondary) 2223 SavageSave(pScrn); 2224 if(SavageModeInit(pScrn, pScrn->currentMode)) { 2225 /* some BIOSes seem to enable HW cursor on PM resume */ 2226 if (!SAVPTR(pScrn)->hwc_on) 2227 SavageHideCursor( pScrn ); 2228 return TRUE; 2229 } 2230 2231 return FALSE; 2232} 2233 2234 2235static void SavageLeaveVT(VT_FUNC_ARGS_DECL) 2236{ 2237 SCRN_INFO_PTR(arg); 2238 vgaHWPtr hwp = VGAHWPTR(pScrn); 2239 SavagePtr psav = SAVPTR(pScrn); 2240 vgaRegPtr vgaSavePtr = &hwp->SavedReg; 2241 SavageRegPtr SavageSavePtr = &psav->SavedReg; 2242#ifdef SAVAGEDRI 2243 ScreenPtr pScreen; 2244#endif 2245 2246 TRACE(("SavageLeaveVT()\n")); 2247 gpScrn = pScrn; 2248 2249#ifdef SAVAGEDRI 2250 if (psav->directRenderingEnabled) { 2251 pScreen = xf86ScrnToScreen(pScrn); 2252 DRILock(pScreen, 0); 2253 psav->LockHeld = 1; 2254 } 2255#endif 2256 if (psav->FBStart2nd || (psav->videoFlags & VF_STREAMS_ON)) 2257 SavageStreamsOff(pScrn); 2258 SavageWriteMode(pScrn, vgaSavePtr, SavageSavePtr, FALSE); 2259 SavageResetStreams(pScrn); 2260 SavageDisableMMIO(pScrn); 2261 2262} 2263 2264 2265static void SavageSave(ScrnInfoPtr pScrn) 2266{ 2267 unsigned char cr3a, cr53, cr66; 2268 vgaHWPtr hwp = VGAHWPTR(pScrn); 2269 vgaRegPtr vgaSavePtr = &hwp->SavedReg; 2270 SavagePtr psav = SAVPTR(pScrn); 2271 SavageRegPtr save = &psav->SavedReg; 2272 unsigned short vgaCRReg = psav->vgaIOBase + 5; 2273 unsigned short vgaCRIndex = psav->vgaIOBase + 4; 2274 2275 TRACE(("SavageSave()\n")); 2276 2277 VGAOUT16(vgaCRIndex, 0x4838); 2278 VGAOUT16(vgaCRIndex, 0xa039); 2279 VGAOUT16(0x3c4, 0x0608); 2280 2281 VGAOUT8(vgaCRIndex, 0x66); 2282 cr66 = VGAIN8(vgaCRReg); 2283 VGAOUT8(vgaCRReg, cr66 | 0x80); 2284 VGAOUT8(vgaCRIndex, 0x3a); 2285 cr3a = VGAIN8(vgaCRReg); 2286 VGAOUT8(vgaCRReg, cr3a | 0x80); 2287 VGAOUT8(vgaCRIndex, 0x53); 2288 cr53 = VGAIN8(vgaCRReg); 2289 VGAOUT8(vgaCRReg, cr53 & 0x7f); 2290 2291 if (xf86IsPrimaryPci(psav->PciInfo)) 2292 vgaHWSave(pScrn, vgaSavePtr, VGA_SR_ALL); 2293 else 2294 vgaHWSave(pScrn, vgaSavePtr, VGA_SR_MODE); 2295 2296 VGAOUT8(vgaCRIndex, 0x66); 2297 VGAOUT8(vgaCRReg, cr66); 2298 VGAOUT8(vgaCRIndex, 0x3a); 2299 VGAOUT8(vgaCRReg, cr3a); 2300 2301 VGAOUT8(vgaCRIndex, 0x66); 2302 VGAOUT8(vgaCRReg, cr66); 2303 VGAOUT8(vgaCRIndex, 0x3a); 2304 VGAOUT8(vgaCRReg, cr3a); 2305 2306 /* unlock extended seq regs */ 2307 VGAOUT8(0x3c4, 0x08); 2308 save->SR08 = VGAIN8(0x3c5); 2309 VGAOUT8(0x3c5, 0x06); 2310 2311 /* now save all the extended regs we need */ 2312 VGAOUT8(vgaCRIndex, 0x31); 2313 save->CR31 = VGAIN8(vgaCRReg); 2314 VGAOUT8(vgaCRIndex, 0x32); 2315 save->CR32 = VGAIN8(vgaCRReg); 2316 VGAOUT8(vgaCRIndex, 0x34); 2317 save->CR34 = VGAIN8(vgaCRReg); 2318 VGAOUT8(vgaCRIndex, 0x36); 2319 save->CR36 = VGAIN8(vgaCRReg); 2320 VGAOUT8(vgaCRIndex, 0x3a); 2321 save->CR3A = VGAIN8(vgaCRReg); 2322 VGAOUT8(vgaCRIndex, 0x40); 2323 save->CR40 = VGAIN8(vgaCRReg); 2324 VGAOUT8(vgaCRIndex, 0x42); 2325 save->CR42 = VGAIN8(vgaCRReg); 2326 VGAOUT8(vgaCRIndex, 0x45); 2327 save->CR45 = VGAIN8(vgaCRReg); 2328 VGAOUT8(vgaCRIndex, 0x50); 2329 save->CR50 = VGAIN8(vgaCRReg); 2330 VGAOUT8(vgaCRIndex, 0x51); 2331 save->CR51 = VGAIN8(vgaCRReg); 2332 VGAOUT8(vgaCRIndex, 0x53); 2333 save->CR53 = VGAIN8(vgaCRReg); 2334 VGAOUT8(vgaCRIndex, 0x58); 2335 save->CR58 = VGAIN8(vgaCRReg); 2336 VGAOUT8(vgaCRIndex, 0x60); 2337 save->CR60 = VGAIN8(vgaCRReg); 2338 VGAOUT8(vgaCRIndex, 0x66); 2339 save->CR66 = VGAIN8(vgaCRReg); 2340 VGAOUT8(vgaCRIndex, 0x67); 2341 save->CR67 = VGAIN8(vgaCRReg); 2342 VGAOUT8(vgaCRIndex, 0x68); 2343 save->CR68 = VGAIN8(vgaCRReg); 2344 VGAOUT8(vgaCRIndex, 0x69); 2345 save->CR69 = VGAIN8(vgaCRReg); 2346 VGAOUT8(vgaCRIndex, 0x6f); 2347 save->CR6F = VGAIN8(vgaCRReg); 2348 2349 VGAOUT8(vgaCRIndex, 0x33); 2350 save->CR33 = VGAIN8(vgaCRReg); 2351 VGAOUT8(vgaCRIndex, 0x86); 2352 save->CR86 = VGAIN8(vgaCRReg); 2353 VGAOUT8(vgaCRIndex, 0x88); 2354 save->CR88 = VGAIN8(vgaCRReg); 2355 VGAOUT8(vgaCRIndex, 0x90); 2356 save->CR90 = VGAIN8(vgaCRReg); 2357 VGAOUT8(vgaCRIndex, 0x91); 2358 save->CR91 = VGAIN8(vgaCRReg); 2359 VGAOUT8(vgaCRIndex, 0xb0); 2360 save->CRB0 = VGAIN8(vgaCRReg) | 0x80; 2361 2362 /* extended mode timing regs */ 2363 VGAOUT8(vgaCRIndex, 0x3b); 2364 save->CR3B = VGAIN8(vgaCRReg); 2365 VGAOUT8(vgaCRIndex, 0x3c); 2366 save->CR3C = VGAIN8(vgaCRReg); 2367 VGAOUT8(vgaCRIndex, 0x43); 2368 save->CR43 = VGAIN8(vgaCRReg); 2369 VGAOUT8(vgaCRIndex, 0x5d); 2370 save->CR5D = VGAIN8(vgaCRReg); 2371 VGAOUT8(vgaCRIndex, 0x5e); 2372 save->CR5E = VGAIN8(vgaCRReg); 2373 VGAOUT8(vgaCRIndex, 0x65); 2374 save->CR65 = VGAIN8(vgaCRReg); 2375 2376 /* save seq extended regs for DCLK PLL programming */ 2377 VGAOUT8(0x3c4, 0x0e); 2378 save->SR0E = VGAIN8(0x3c5); 2379 VGAOUT8(0x3c4, 0x0f); 2380 save->SR0F = VGAIN8(0x3c5); 2381 VGAOUT8(0x3c4, 0x10); 2382 save->SR10 = VGAIN8(0x3c5); 2383 VGAOUT8(0x3c4, 0x11); 2384 save->SR11 = VGAIN8(0x3c5); 2385 VGAOUT8(0x3c4, 0x12); 2386 save->SR12 = VGAIN8(0x3c5); 2387 VGAOUT8(0x3c4, 0x13); 2388 save->SR13 = VGAIN8(0x3c5); 2389 VGAOUT8(0x3c4, 0x29); 2390 save->SR29 = VGAIN8(0x3c5); 2391 2392 VGAOUT8(0x3c4, 0x15); 2393 save->SR15 = VGAIN8(0x3c5); 2394 VGAOUT8(0x3c4, 0x30); 2395 save->SR30 = VGAIN8(0x3c5); 2396 VGAOUT8(0x3c4, 0x18); 2397 save->SR18 = VGAIN8(0x3c5); 2398 VGAOUT8(0x3c4, 0x1b); 2399 save->SR1B = VGAIN8(0x3c5); 2400 2401 /* Save flat panel expansion registers. */ 2402 2403 if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || 2404 S3_MOBILE_TWISTER_SERIES(psav->Chipset)) { 2405 int i; 2406 for( i = 0; i < 8; i++ ) { 2407 VGAOUT8(0x3c4, 0x54+i); 2408 save->SR54[i] = VGAIN8(0x3c5); 2409 } 2410 } 2411 2412 VGAOUT8(vgaCRIndex, 0x66); 2413 cr66 = VGAIN8(vgaCRReg); 2414 VGAOUT8(vgaCRReg, cr66 | 0x80); 2415 VGAOUT8(vgaCRIndex, 0x3a); 2416 cr3a = VGAIN8(vgaCRReg); 2417 VGAOUT8(vgaCRReg, cr3a | 0x80); 2418 2419 /* now save MIU regs */ 2420 if( ! S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) { 2421 save->MMPR0 = INREG(FIFO_CONTROL_REG); 2422 save->MMPR1 = INREG(MIU_CONTROL_REG); 2423 save->MMPR2 = INREG(STREAMS_TIMEOUT_REG); 2424 save->MMPR3 = INREG(MISC_TIMEOUT_REG); 2425 } 2426 2427 VGAOUT8(vgaCRIndex, 0x3a); 2428 VGAOUT8(vgaCRReg, cr3a); 2429 VGAOUT8(vgaCRIndex, 0x66); 2430 VGAOUT8(vgaCRReg, cr66); 2431 2432 if (!psav->ModeStructInit) { 2433 vgaHWCopyReg(&hwp->ModeReg, vgaSavePtr); 2434 memcpy(&psav->ModeReg, save, sizeof(SavageRegRec)); 2435 psav->ModeStructInit = TRUE; 2436 } 2437 2438#if 0 2439 if (xf86GetVerbosity() > 1) 2440 SavagePrintRegs(pScrn); 2441#endif 2442 2443 return; 2444} 2445 2446 2447static void SavageWriteMode(ScrnInfoPtr pScrn, vgaRegPtr vgaSavePtr, 2448 SavageRegPtr restore, Bool Entering) 2449{ 2450 unsigned char tmp, cr3a, cr66; 2451 vgaHWPtr hwp = VGAHWPTR(pScrn); 2452 SavagePtr psav = SAVPTR(pScrn); 2453 int vgaCRIndex, vgaCRReg, vgaIOBase; 2454 2455 2456 vgaIOBase = hwp->IOBase; 2457 vgaCRIndex = vgaIOBase + 4; 2458 vgaCRReg = vgaIOBase + 5; 2459 2460 TRACE(("SavageWriteMode(%x)\n", restore->mode)); 2461 2462#ifdef SAVAGEDRI 2463 if (psav->directRenderingEnabled) { 2464 DRILock(xf86ScrnToScreen(pScrn), 0); 2465 psav->LockHeld = 1; 2466 } 2467#endif 2468 2469 if (psav->IsSecondary) { 2470 /* Set up the mode. Don't clear video RAM. */ 2471 SavageSetVESAMode( psav, restore->mode | 0x8000, restore->refresh ); 2472 SavageSetGBD(pScrn); 2473 return; 2474 } 2475 2476 if( Entering && 2477 (!S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || (psav->ForceInit)) 2478 ) 2479 SavageInitialize2DEngine(pScrn); 2480 2481 /* 2482 * If we figured out a VESA mode number for this timing, just use 2483 * the S3 BIOS to do the switching, with a few additional tweaks. 2484 */ 2485 2486 if( psav->UseBIOS && restore->mode > 0x13 ) 2487 { 2488 int width; 2489 unsigned short cr6d; 2490 unsigned short cr79 = 0; 2491 2492 /* Set up the mode. Don't clear video RAM. */ 2493 SavageSetVESAMode( psav, restore->mode | 0x8000, restore->refresh ); 2494 2495 /* Restore the DAC. */ 2496 vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_CMAP); 2497 2498 /* Unlock the extended registers. */ 2499 2500#if 0 2501 /* Which way is better? */ 2502 hwp->writeCrtc( hwp, 0x38, 0x48 ); 2503 hwp->writeCrtc( hwp, 0x39, 0xa0 ); 2504 hwp->writeSeq( hwp, 0x08, 0x06 ); 2505#endif 2506 2507 VGAOUT16(vgaCRIndex, 0x4838); 2508 VGAOUT16(vgaCRIndex, 0xA039); 2509 VGAOUT16(0x3c4, 0x0608); 2510 2511 /* Enable linear addressing. */ 2512 2513 VGAOUT16(vgaCRIndex, 0x1358); 2514 2515 /* Disable old MMIO. */ 2516 2517 VGAOUT8(vgaCRIndex, 0x53); 2518 VGAOUT8(vgaCRReg, VGAIN8(vgaCRReg) & ~0x10); 2519 2520 /* Disable HW cursor */ 2521 2522 VGAOUT16(vgaCRIndex, 0x0045); 2523 2524 /* Set the color mode. */ 2525 2526 VGAOUT8(vgaCRIndex, 0x67); 2527 VGAOUT8(vgaCRReg, restore->CR67); 2528 2529 /* Enable gamma correction, set CLUT to 8 bit */ 2530 2531 VGAOUT8(0x3c4, 0x1b); 2532 if( (pScrn->bitsPerPixel == 32) && !psav->DGAactive 2533 && ! psav->FBStart2nd ) 2534 VGAOUT8(0x3c5, 0x18 ); 2535 else 2536 VGAOUT8(0x3c5, 0x10 ); 2537 2538 /* We may need TV/panel fixups here. See s3bios.c line 2904. */ 2539 2540 /* Set FIFO fetch delay. */ 2541 VGAOUT8(vgaCRIndex, 0x85); 2542 VGAOUT8(vgaCRReg, (VGAIN8(vgaCRReg) & 0xf8) | 0x03); 2543 2544 /* Patch CR79. These values are magical. */ 2545 2546 if( !S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) 2547 { 2548 VGAOUT8(vgaCRIndex, 0x6d); 2549 cr6d = VGAIN8(vgaCRReg); 2550 2551 cr79 = 0x04; 2552 2553 if( pScrn->displayWidth >= 1024 ) 2554 { 2555 if(psav->primStreamBpp == 32 ) 2556 { 2557 if( restore->refresh >= 130 ) 2558 cr79 = 0x03; 2559 else if( pScrn->displayWidth >= 1280 ) 2560 cr79 = 0x02; 2561 else if( 2562 (pScrn->displayWidth == 1024) && 2563 (restore->refresh >= 75) 2564 ) 2565 { 2566 if( cr6d & LCD_ACTIVE ) 2567 cr79 = 0x05; 2568 else 2569 cr79 = 0x08; 2570 } 2571 } 2572 else if( psav->primStreamBpp == 16) 2573 { 2574 2575/* The windows driver uses 0x13 for 16-bit 130Hz, but I see terrible 2576 * screen artifacts with that value. Let's keep it low for now. 2577 * if( restore->refresh >= 130 ) 2578 * cr79 = 0x13; 2579 * else 2580 */ 2581 if( pScrn->displayWidth == 1024 ) 2582 { 2583 if( cr6d & LCD_ACTIVE ) 2584 cr79 = 0x08; 2585 else 2586 cr79 = 0x0e; 2587 } 2588 } 2589 } 2590 } 2591 2592 if( (psav->Chipset != S3_SAVAGE2000) && 2593 !S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) 2594 VGAOUT16(vgaCRIndex, (cr79 << 8) | 0x79); 2595 2596 /* Make sure 16-bit memory access is enabled. */ 2597 2598 VGAOUT16(vgaCRIndex, 0x0c31); 2599 2600 /* Enable the graphics engine. */ 2601 2602 VGAOUT16(vgaCRIndex, 0x0140); 2603 2604 /* Handle the pitch. */ 2605 2606 VGAOUT8(vgaCRIndex, 0x50); 2607 VGAOUT8(vgaCRReg, VGAIN8(vgaCRReg) | 0xC1); 2608 2609 width = (pScrn->displayWidth * (psav->primStreamBpp / 8)) >> 3; 2610 VGAOUT16(vgaCRIndex, ((width & 0xff) << 8) | 0x13 ); 2611 VGAOUT16(vgaCRIndex, ((width & 0x300) << 4) | 0x51 ); 2612 2613 /* Some non-S3 BIOSes enable block write even on non-SGRAM devices. */ 2614 2615 switch( psav->Chipset ) 2616 { 2617 case S3_SAVAGE2000: 2618 VGAOUT8(vgaCRIndex, 0x73); 2619 VGAOUT8(vgaCRReg, VGAIN8(vgaCRReg) & 0xdf ); 2620 break; 2621 2622 case S3_SAVAGE3D: 2623 case S3_SAVAGE4: 2624 VGAOUT8(vgaCRIndex, 0x68); 2625 if( !(VGAIN8(vgaCRReg) & 0x80) ) 2626 { 2627 /* Not SGRAM; disable block write. */ 2628 VGAOUT8(vgaCRIndex, 0x88); 2629 VGAOUT8(vgaCRReg, VGAIN8(vgaCRReg) | 0x10); 2630 } 2631 break; 2632 } 2633 2634 /* set the correct clock for some BIOSes */ 2635 VGAOUT8(VGA_MISC_OUT_W, 2636 VGAIN8(VGA_MISC_OUT_R) | 0x0C); 2637 /* Some BIOSes turn on clock doubling on non-doubled modes */ 2638 if (pScrn->bitsPerPixel < 24) { 2639 VGAOUT8(vgaCRIndex, 0x67); 2640 if (!(VGAIN8(vgaCRReg) & 0x10)) { 2641 VGAOUT8(0x3c4, 0x15); 2642 VGAOUT8(0x3c5, VGAIN8(0x3C5) & ~0x10); 2643 VGAOUT8(0x3c4, 0x18); 2644 VGAOUT8(0x3c5, VGAIN8(0x3c5) & ~0x80); 2645 } 2646 } 2647 2648 SavageInitialize2DEngine(pScrn); 2649 2650 VGAOUT16(vgaCRIndex, 0x0140); 2651 2652 SavageSetGBD(pScrn); 2653 2654 2655#ifdef SAVAGEDRI 2656 if (psav->directRenderingEnabled) 2657 DRIUnlock(xf86ScrnToScreen(pScrn)); 2658 psav->LockHeld = 0; 2659#endif 2660 2661 return; 2662 } 2663 2664 VGAOUT8(0x3c2, 0x23); 2665 VGAOUT16(vgaCRIndex, 0x4838); 2666 VGAOUT16(vgaCRIndex, 0xa039); 2667 VGAOUT16(0x3c4, 0x0608); 2668 2669 vgaHWProtect(pScrn, TRUE); 2670 2671 /* will we be reenabling STREAMS for the new mode? */ 2672 psav->STREAMSRunning = 0; 2673 2674 /* reset GE to make sure nothing is going on */ 2675 VGAOUT8(vgaCRIndex, 0x66); 2676 if(VGAIN8(vgaCRReg) & 0x01) 2677 SavageGEReset(pScrn,0,__LINE__,__FILE__); 2678 2679 /* 2680 * Some Savage/MX and /IX systems go nuts when trying to exit the 2681 * server after WindowMaker has displayed a gradient background. I 2682 * haven't been able to find what causes it, but a non-destructive 2683 * switch to mode 3 here seems to eliminate the issue. 2684 */ 2685 2686 if( ((restore->CR31 & 0x0a) == 0) && psav->pVbe ) { 2687 SavageSetTextMode( psav ); 2688 } 2689 2690 VGAOUT8(vgaCRIndex, 0x67); 2691 (void) VGAIN8(vgaCRReg); 2692 /*VGAOUT8(vgaCRReg, restore->CR67 & ~0x0c);*/ /* no STREAMS yet */ 2693 VGAOUT8(vgaCRReg, restore->CR67 & ~0x0e); /* no STREAMS yet old and new */ 2694 2695 /* restore extended regs */ 2696 VGAOUT8(vgaCRIndex, 0x66); 2697 VGAOUT8(vgaCRReg, restore->CR66); 2698 VGAOUT8(vgaCRIndex, 0x3a); 2699 VGAOUT8(vgaCRReg, restore->CR3A); 2700 VGAOUT8(vgaCRIndex, 0x31); 2701 VGAOUT8(vgaCRReg, restore->CR31); 2702 VGAOUT8(vgaCRIndex, 0x32); 2703 VGAOUT8(vgaCRReg, restore->CR32); 2704 VGAOUT8(vgaCRIndex, 0x58); 2705 VGAOUT8(vgaCRReg, restore->CR58); 2706 VGAOUT8(vgaCRIndex, 0x53); 2707 VGAOUT8(vgaCRReg, restore->CR53 & 0x7f); 2708 2709 VGAOUT16(0x3c4, 0x0608); 2710 2711 /* Restore DCLK registers. */ 2712 2713 VGAOUT8(0x3c4, 0x0e); 2714 VGAOUT8(0x3c5, restore->SR0E); 2715 VGAOUT8(0x3c4, 0x0f); 2716 VGAOUT8(0x3c5, restore->SR0F); 2717 VGAOUT8(0x3c4, 0x29); 2718 VGAOUT8(0x3c5, restore->SR29); 2719 VGAOUT8(0x3c4, 0x15); 2720 VGAOUT8(0x3c5, restore->SR15); 2721 2722 /* Restore flat panel expansion registers. */ 2723 if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || 2724 S3_MOBILE_TWISTER_SERIES(psav->Chipset)) { 2725 int i; 2726 for( i = 0; i < 8; i++ ) { 2727 VGAOUT8(0x3c4, 0x54+i); 2728 VGAOUT8(0x3c5, restore->SR54[i]); 2729 } 2730 } 2731 2732 /* restore the standard vga regs */ 2733 if (xf86IsPrimaryPci(psav->PciInfo)) 2734 vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_ALL); 2735 else 2736 vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_MODE); 2737 2738 /* extended mode timing registers */ 2739 VGAOUT8(vgaCRIndex, 0x53); 2740 VGAOUT8(vgaCRReg, restore->CR53); 2741 VGAOUT8(vgaCRIndex, 0x5d); 2742 VGAOUT8(vgaCRReg, restore->CR5D); 2743 VGAOUT8(vgaCRIndex, 0x5e); 2744 VGAOUT8(vgaCRReg, restore->CR5E); 2745 VGAOUT8(vgaCRIndex, 0x3b); 2746 VGAOUT8(vgaCRReg, restore->CR3B); 2747 VGAOUT8(vgaCRIndex, 0x3c); 2748 VGAOUT8(vgaCRReg, restore->CR3C); 2749 VGAOUT8(vgaCRIndex, 0x43); 2750 VGAOUT8(vgaCRReg, restore->CR43); 2751 VGAOUT8(vgaCRIndex, 0x65); 2752 VGAOUT8(vgaCRReg, restore->CR65); 2753 2754 /* restore the desired video mode with cr67 */ 2755 VGAOUT8(vgaCRIndex, 0x67); 2756 /*VGAOUT8(vgaCRReg, restore->CR67 & ~0x0c);*/ /* no STREAMS yet */ 2757 VGAOUT8(vgaCRReg, restore->CR67 & ~0x0e); /* no streams for new and old streams engines */ 2758 2759 /* other mode timing and extended regs */ 2760 VGAOUT8(vgaCRIndex, 0x34); 2761 VGAOUT8(vgaCRReg, restore->CR34); 2762 VGAOUT8(vgaCRIndex, 0x40); 2763 VGAOUT8(vgaCRReg, restore->CR40); 2764 VGAOUT8(vgaCRIndex, 0x42); 2765 VGAOUT8(vgaCRReg, restore->CR42); 2766 VGAOUT8(vgaCRIndex, 0x45); 2767 VGAOUT8(vgaCRReg, restore->CR45); 2768 VGAOUT8(vgaCRIndex, 0x50); 2769 VGAOUT8(vgaCRReg, restore->CR50); 2770 VGAOUT8(vgaCRIndex, 0x51); 2771 VGAOUT8(vgaCRReg, restore->CR51); 2772 2773 /* memory timings */ 2774 VGAOUT8(vgaCRIndex, 0x36); 2775 VGAOUT8(vgaCRReg, restore->CR36); 2776 VGAOUT8(vgaCRIndex, 0x60); 2777 VGAOUT8(vgaCRReg, restore->CR60); 2778 VGAOUT8(vgaCRIndex, 0x68); 2779 VGAOUT8(vgaCRReg, restore->CR68); 2780 VerticalRetraceWait(); 2781 VGAOUT8(vgaCRIndex, 0x69); 2782 VGAOUT8(vgaCRReg, restore->CR69); 2783 VGAOUT8(vgaCRIndex, 0x6f); 2784 VGAOUT8(vgaCRReg, restore->CR6F); 2785 2786 VGAOUT8(vgaCRIndex, 0x33); 2787 VGAOUT8(vgaCRReg, restore->CR33); 2788 VGAOUT8(vgaCRIndex, 0x86); 2789 VGAOUT8(vgaCRReg, restore->CR86); 2790 VGAOUT8(vgaCRIndex, 0x88); 2791 VGAOUT8(vgaCRReg, restore->CR88); 2792 VGAOUT8(vgaCRIndex, 0x90); 2793 VGAOUT8(vgaCRReg, restore->CR90); 2794 VGAOUT8(vgaCRIndex, 0x91); 2795 VGAOUT8(vgaCRReg, restore->CR91); 2796 if( psav->Chipset == S3_SAVAGE4 ) 2797 { 2798 VGAOUT8(vgaCRIndex, 0xb0); 2799 VGAOUT8(vgaCRReg, restore->CRB0); 2800 } 2801 2802 VGAOUT8(vgaCRIndex, 0x32); 2803 VGAOUT8(vgaCRReg, restore->CR32); 2804 2805 /* unlock extended seq regs */ 2806 VGAOUT8(0x3c4, 0x08); 2807 VGAOUT8(0x3c5, 0x06); 2808 2809 /* Restore extended sequencer regs for MCLK. SR10 == 255 indicates that 2810 * we should leave the default SR10 and SR11 values there. 2811 */ 2812 if (restore->SR10 != 255) { 2813 VGAOUT8(0x3c4, 0x10); 2814 VGAOUT8(0x3c5, restore->SR10); 2815 VGAOUT8(0x3c4, 0x11); 2816 VGAOUT8(0x3c5, restore->SR11); 2817 } 2818 2819 /* restore extended seq regs for dclk */ 2820 VGAOUT8(0x3c4, 0x0e); 2821 VGAOUT8(0x3c5, restore->SR0E); 2822 VGAOUT8(0x3c4, 0x0f); 2823 VGAOUT8(0x3c5, restore->SR0F); 2824 VGAOUT8(0x3c4, 0x12); 2825 VGAOUT8(0x3c5, restore->SR12); 2826 VGAOUT8(0x3c4, 0x13); 2827 VGAOUT8(0x3c5, restore->SR13); 2828 VGAOUT8(0x3c4, 0x29); 2829 VGAOUT8(0x3c5, restore->SR29); 2830 2831 VGAOUT8(0x3c4, 0x18); 2832 VGAOUT8(0x3c5, restore->SR18); 2833 VGAOUT8(0x3c4, 0x1b); 2834 if( psav->DGAactive ) 2835 VGAOUT8(0x3c5, restore->SR1B & ~0x08 ); 2836 else 2837 VGAOUT8(0x3c5, restore->SR1B); 2838 2839 /* load new m, n pll values for dclk & mclk */ 2840 VGAOUT8(0x3c4, 0x15); 2841 tmp = VGAIN8(0x3c5) & ~0x21; 2842 2843 VGAOUT8(0x3c5, tmp | 0x03); 2844 VGAOUT8(0x3c5, tmp | 0x23); 2845 VGAOUT8(0x3c5, tmp | 0x03); 2846 VGAOUT8(0x3c5, restore->SR15); 2847 usleep( 100 ); 2848 2849 VGAOUT8(0x3c4, 0x30); 2850 VGAOUT8(0x3c5, restore->SR30); 2851 VGAOUT8(0x3c4, 0x08); 2852 VGAOUT8(0x3c5, restore->SR08); 2853 2854 /* now write out cr67 in full, possibly starting STREAMS */ 2855 VerticalRetraceWait(); 2856 VGAOUT8(vgaCRIndex, 0x67); 2857#if 0 2858 VGAOUT8(vgaCRReg, 0x50); 2859 usleep(10000); 2860 VGAOUT8(vgaCRIndex, 0x67); 2861#endif 2862 VGAOUT8(vgaCRReg, restore->CR67); 2863 2864 VGAOUT8(vgaCRIndex, 0x66); 2865 cr66 = VGAIN8(vgaCRReg); 2866 VGAOUT8(vgaCRReg, cr66 | 0x80); 2867 VGAOUT8(vgaCRIndex, 0x3a); 2868 cr3a = VGAIN8(vgaCRReg); 2869 VGAOUT8(vgaCRReg, cr3a | 0x80); 2870 2871 if (Entering) 2872 SavageGEReset(pScrn,0,__LINE__,__FILE__); 2873 2874 if( !S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) 2875 { 2876 VerticalRetraceWait(); 2877 OUTREG(FIFO_CONTROL_REG, restore->MMPR0); 2878 OUTREG(MIU_CONTROL_REG, restore->MMPR1); 2879 OUTREG(STREAMS_TIMEOUT_REG, restore->MMPR2); 2880 OUTREG(MISC_TIMEOUT_REG, restore->MMPR3); 2881 } 2882 2883 /* If we're going into graphics mode and acceleration was enabled, */ 2884 /* go set up the BCI buffer and the global bitmap descriptor. */ 2885 2886#if 0 2887 if( Entering && (!psav->NoAccel) ) 2888 { 2889 VGAOUT8(vgaCRIndex, 0x50); 2890 VGAOUT8(vgaCRReg, VGAIN8(vgaCRReg) | 0xC1); 2891 SavageInitialize2DEngine(pScrn); 2892 } 2893#endif 2894 2895 VGAOUT8(vgaCRIndex, 0x66); 2896 VGAOUT8(vgaCRReg, cr66); 2897 VGAOUT8(vgaCRIndex, 0x3a); 2898 VGAOUT8(vgaCRReg, cr3a); 2899 2900 if( Entering ) { 2901 SavageInitialize2DEngine(pScrn); 2902 2903 VGAOUT16(vgaCRIndex, 0x0140); 2904 2905 SavageSetGBD(pScrn); 2906 } 2907 2908 vgaHWProtect(pScrn, FALSE); 2909 2910 2911#ifdef SAVAGEDRI 2912 if (psav->directRenderingEnabled) 2913 DRIUnlock(xf86ScrnToScreen(pScrn)); 2914 psav->LockHeld = 0; 2915#endif 2916 2917 return; 2918} 2919 2920 2921static Bool SavageMapMem(ScrnInfoPtr pScrn) 2922{ 2923 SavagePtr psav = SAVPTR(pScrn); 2924 int err; 2925 2926 TRACE(("SavageMapMem()\n")); 2927 2928 if( S3_SAVAGE3D_SERIES(psav->Chipset) ) { 2929#ifdef XSERVER_LIBPCIACCESS 2930 psav->MmioRegion.base = SAVAGE_NEWMMIO_REGBASE_S3 2931 + psav->PciInfo->regions[0].base_addr; 2932 psav->FbRegion.base = psav->PciInfo->regions[0].base_addr; 2933#else 2934 psav->MmioRegion.base = SAVAGE_NEWMMIO_REGBASE_S3 2935 + psav->PciInfo->memBase[0]; 2936 psav->FbRegion.base = psav->PciInfo->memBase[0]; 2937#endif 2938 } else { 2939#ifdef XSERVER_LIBPCIACCESS 2940 psav->MmioRegion.base = SAVAGE_NEWMMIO_REGBASE_S4 2941 + psav->PciInfo->regions[0].base_addr; 2942 psav->FbRegion.base = psav->PciInfo->regions[1].base_addr; 2943#else 2944 psav->MmioRegion.base = SAVAGE_NEWMMIO_REGBASE_S4 2945 + psav->PciInfo->memBase[0]; 2946 psav->FbRegion.base = psav->PciInfo->memBase[1]; 2947#endif 2948 } 2949 2950 psav->MmioRegion.size = SAVAGE_NEWMMIO_REGSIZE; 2951 psav->FbRegion.size = psav->videoRambytes; 2952 2953 /* On Paramount and Savage 2000, aperture 0 is PCI base 2. On other 2954 * chipsets it's in the same BAR as the framebuffer. 2955 */ 2956 2957 psav->ApertureRegion.size = (psav->IsPrimary || psav->IsSecondary) 2958 ? (0x01000000 * 2) : (0x01000000 * 5); 2959 2960 if ((psav->Chipset == S3_SUPERSAVAGE) 2961 || (psav->Chipset == S3_SAVAGE2000)) { 2962#ifdef XSERVER_LIBPCIACCESS 2963 psav->ApertureRegion.base = psav->PciInfo->regions[2].base_addr; 2964 if (psav->ApertureRegion.size > psav->PciInfo->regions[2].size) 2965 psav->ApertureRegion.size = psav->PciInfo->regions[2].size; 2966#else 2967 psav->ApertureRegion.base = psav->PciInfo->memBase[2]; 2968#endif 2969 } else { 2970 psav->ApertureRegion.base = psav->FbRegion.base + 0x02000000; 2971 } 2972 2973 2974 2975 if (psav->FbRegion.size != 0) { 2976#ifdef XSERVER_LIBPCIACCESS 2977 err = pci_device_map_range(psav->PciInfo, psav->FbRegion.base, 2978 psav->FbRegion.size, 2979 (PCI_DEV_MAP_FLAG_WRITABLE 2980 | PCI_DEV_MAP_FLAG_WRITE_COMBINE), 2981 & psav->FbRegion.memory); 2982#else 2983 psav->FbRegion.memory = 2984 xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 2985 psav->PciTag, psav->FbRegion.base, 2986 psav->FbRegion.size); 2987 err = (psav->FbRegion.memory == NULL) ? errno : 0; 2988#endif 2989 if (err) { 2990 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2991 "Internal error: could not map framebuffer range (%d, %s).\n", 2992 err, strerror(err)); 2993 return FALSE; 2994 } 2995 2996 psav->FBBase = psav->FbRegion.memory; 2997 psav->FBStart = (psav->IsSecondary) 2998 ? psav->FBBase + 0x1000000 : psav->FBBase; 2999 } 3000 3001 if (psav->ApertureRegion.memory == NULL) { 3002#ifdef XSERVER_LIBPCIACCESS 3003 err = pci_device_map_range(psav->PciInfo, psav->ApertureRegion.base, 3004 psav->ApertureRegion.size, 3005 (PCI_DEV_MAP_FLAG_WRITABLE 3006 | PCI_DEV_MAP_FLAG_WRITE_COMBINE), 3007 & psav->ApertureRegion.memory); 3008#else 3009 psav->ApertureRegion.memory = 3010 xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 3011 psav->PciTag, psav->ApertureRegion.base, 3012 psav->ApertureRegion.size); 3013 err = (psav->ApertureRegion.memory == NULL) ? errno : 0; 3014#endif 3015 if (err) { 3016 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 3017 "Internal error: could not map aperture range (%d, %s).\n", 3018 err, strerror(err)); 3019 return FALSE; 3020 } 3021 3022 psav->ApertureMap = (psav->IsSecondary) 3023 ? psav->ApertureRegion.memory + 0x1000000 3024 : psav->ApertureRegion.memory; 3025 } 3026 3027 if (psav->MmioRegion.memory == NULL) { 3028#ifdef XSERVER_LIBPCIACCESS 3029 err = pci_device_map_range(psav->PciInfo, psav->MmioRegion.base, 3030 psav->MmioRegion.size, 3031 (PCI_DEV_MAP_FLAG_WRITABLE), 3032 & psav->MmioRegion.memory); 3033#else 3034 psav->MmioRegion.memory = 3035 xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 3036 psav->PciTag, psav->MmioRegion.base, 3037 psav->MmioRegion.size); 3038 err = (psav->MmioRegion.memory == NULL) ? errno : 0; 3039#endif 3040 if (err) { 3041 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 3042 "Internal error: could not map MMIO range (%d, %s).\n", 3043 err, strerror(err)); 3044 return FALSE; 3045 } 3046 3047 psav->MapBase = psav->MmioRegion.memory; 3048 psav->BciMem = psav->MapBase + 0x10000; 3049 3050 SavageEnableMMIO(pScrn); 3051 } 3052 3053 pScrn->memPhysBase = psav->FbRegion.base; 3054 return TRUE; 3055} 3056 3057 3058static void SavageUnmapMem(ScrnInfoPtr pScrn, int All) 3059{ 3060 SavagePtr psav = SAVPTR(pScrn); 3061 3062 TRACE(("SavageUnmapMem(%p,%p)\n", psav->MapBase, psav->FBBase)); 3063 3064 if (psav->PrimaryVidMapped) { 3065 vgaHWUnmapMem(pScrn); 3066 psav->PrimaryVidMapped = FALSE; 3067 } 3068 3069 SavageDisableMMIO(pScrn); 3070 3071 if (All && (psav->MmioRegion.memory != NULL)) { 3072#ifdef XSERVER_LIBPCIACCESS 3073 pci_device_unmap_range(psav->PciInfo, 3074 psav->MmioRegion.memory, 3075 psav->MmioRegion.size); 3076#else 3077 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)psav->MapBase, 3078 SAVAGE_NEWMMIO_REGSIZE); 3079#endif 3080 3081 psav->MmioRegion.memory = NULL; 3082 psav->MapBase = 0; 3083 psav->BciMem = 0; 3084 } 3085 3086 if (psav->FbRegion.memory != NULL) { 3087#ifdef XSERVER_LIBPCIACCESS 3088 pci_device_unmap_range(psav->PciInfo, 3089 psav->FbRegion.memory, 3090 psav->FbRegion.size); 3091#else 3092 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)psav->FbRegion.base, 3093 psav->FbRegion.size); 3094#endif 3095 } 3096 3097 if (psav->ApertureRegion.memory != NULL) { 3098#ifdef XSERVER_LIBPCIACCESS 3099 pci_device_unmap_range(psav->PciInfo, 3100 psav->ApertureRegion.memory, 3101 psav->ApertureRegion.size); 3102#else 3103 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)psav->ApertureRegion.base, 3104 psav->ApertureRegion.size); 3105#endif 3106 } 3107 3108 psav->FbRegion.memory = NULL; 3109 psav->ApertureRegion.memory = NULL; 3110 psav->FBBase = 0; 3111 psav->FBStart = 0; 3112 psav->ApertureMap = 0; 3113 3114 return; 3115} 3116 3117#ifdef SAVAGEDRI 3118static Bool SavageCheckAvailableRamFor3D(ScrnInfoPtr pScrn) 3119{ 3120 SavagePtr psav = SAVPTR(pScrn); 3121 int cpp = pScrn->bitsPerPixel / 8; 3122 int tiledBufferSize, RamNeededFor3D; 3123 3124 if (cpp == 2) { 3125 tiledBufferSize = ((pScrn->virtualX+63)/64)*((pScrn->virtualY+15)/16) * 2048; 3126 } else { 3127 tiledBufferSize = ((pScrn->virtualX+31)/32)*((pScrn->virtualY+15)/16) * 2048; 3128 } 3129 3130 RamNeededFor3D = 4096 + /* hw cursor*/ 3131 psav->cobSize + /*COB*/ 3132 tiledBufferSize + /* front buffer */ 3133 tiledBufferSize + /* back buffer */ 3134 tiledBufferSize; /* depth buffer */ 3135 3136 xf86DrvMsg(pScrn->scrnIndex,X_INFO, 3137 "%d kB of Videoram needed for 3D; %d kB of Videoram available\n", 3138 RamNeededFor3D/1024, psav->videoRambytes/1024); 3139 3140 if (RamNeededFor3D <= psav->videoRambytes) { 3141 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Sufficient Videoram available for 3D\n"); 3142 return TRUE; 3143 } else { 3144 xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Insufficient Videoram available for 3D -- " 3145 "Try a lower color depth or smaller desktop. " 3146 "For integrated savages try increasing the videoram in the BIOS.\n"); 3147 return FALSE; 3148 } 3149} 3150#endif 3151 3152static void SavageInitStatus(ScrnInfoPtr pScrn) 3153{ 3154 SavagePtr psav = SAVPTR(pScrn); 3155 3156 switch( psav->Chipset ) { 3157 case S3_SAVAGE3D: 3158 case S3_SAVAGE_MX: 3159 psav->WaitQueue = WaitQueue3D; 3160 psav->WaitIdle = WaitIdle3D; 3161 psav->WaitIdleEmpty = WaitIdleEmpty3D; 3162 psav->bciUsedMask = 0x1ffff; 3163 psav->eventStatusReg= 1; 3164 break; 3165 3166 case S3_SAVAGE4: 3167 case S3_PROSAVAGE: 3168 case S3_SUPERSAVAGE: 3169 case S3_PROSAVAGEDDR: 3170 case S3_TWISTER: 3171 psav->WaitQueue = WaitQueue4; 3172 psav->WaitIdle = WaitIdle4; 3173 psav->WaitIdleEmpty = WaitIdleEmpty4; 3174 psav->bciUsedMask = 0x1fffff; 3175 psav->eventStatusReg= 1; 3176 break; 3177 3178 case S3_SAVAGE2000: 3179 psav->WaitQueue = WaitQueue2K; 3180 psav->WaitIdle = WaitIdle2K; 3181 psav->WaitIdleEmpty = WaitIdleEmpty2K; 3182 psav->bciUsedMask = 0xfffff; 3183 psav->eventStatusReg= 2; 3184 break; 3185 } 3186} 3187 3188static void SavageInitShadowStatus(ScrnInfoPtr pScrn) 3189{ 3190 SavagePtr psav = SAVPTR(pScrn); 3191 3192 psav->ShadowStatus = psav->ConfigShadowStatus; 3193 3194 SavageInitStatus(pScrn); 3195 3196 if( psav->ShadowStatus ) { 3197 psav->ShadowPhysical = 3198 psav->FbRegion.base + psav->CursorKByte*1024 + 4096 - 32; 3199 3200 psav->ShadowVirtual = (CARD32 *) 3201 (psav->FBBase + psav->CursorKByte*1024 + 4096 - 32); 3202 3203 xf86DrvMsg( pScrn->scrnIndex, X_PROBED, 3204 "Shadow area physical %08lx, linear %p\n", 3205 psav->ShadowPhysical, (void *)psav->ShadowVirtual ); 3206 3207 psav->WaitQueue = ShadowWaitQueue; 3208 psav->WaitIdle = ShadowWait; 3209 psav->WaitIdleEmpty = ShadowWait; 3210 } 3211 3212 if( psav->Chipset == S3_SAVAGE2000 ) 3213 psav->dwBCIWait2DIdle = 0xc0040000; 3214 else 3215 psav->dwBCIWait2DIdle = 0xc0020000; 3216} 3217 3218static Bool SavageScreenInit(SCREEN_INIT_ARGS_DECL) 3219{ 3220 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 3221 SavagePtr psav; 3222 EntityInfoPtr pEnt; 3223 int ret; 3224 int colormapFlags; 3225 3226 TRACE(("SavageScreenInit()\n")); 3227 3228 psav = SAVPTR(pScrn); 3229 3230 pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 3231 if (!psav->pVbe) 3232 psav->pVbe = VBEInit(NULL, pEnt->index); 3233 3234 SavageEnableMMIO(pScrn); 3235 3236 if (!SavageMapMem(pScrn)) 3237 return FALSE; 3238 3239 psav->FBStart2nd = 0; 3240 3241 if (psav->overlayDepth) { 3242 if ((pScrn->virtualX * pScrn->virtualY * 3243 (DEPTH_BPP(DEPTH_2ND(pScrn))) >> 3) 3244 > (psav->CursorKByte * 1024)) 3245 xf86DrvMsg(pScrn->scrnIndex,X_WARNING, 3246 "Not enough memory for overlay mode: disabling\n"); 3247 else psav->FBStart2nd = psav->FBStart 3248 + ((pScrn->virtualX * pScrn->virtualY + 0xff) & ~0xff); 3249 3250 } 3251 3252 SavageInitShadowStatus(pScrn); 3253 psav->ShadowCounter = 0; 3254 3255 SavageSave(pScrn); 3256 3257 vgaHWBlankScreen(pScrn, TRUE); 3258 3259#ifdef SAVAGEDRI 3260 if (!xf86ReturnOptValBool(psav->Options, OPTION_DRI, TRUE)) { 3261 psav->directRenderingEnabled = FALSE; 3262 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3263 "Direct rendering forced off\n"); 3264 } else if (psav->IsSecondary) { 3265 psav->directRenderingEnabled = FALSE; 3266 } else if (xf86IsEntityShared(psav->pEnt->index)) { 3267 /* Xinerama has sync problem with DRI, disable it for now */ 3268 psav->directRenderingEnabled = FALSE; 3269 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3270 "Direct Rendering Disabled -- " 3271 "Dual-head configuration is not working with " 3272 "DRI at present.\n"); 3273 } else if (/*!psav->bTiled*/psav->bDisableTile) { 3274 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3275 "Direct Rendering requires a tiled framebuffer -- " 3276 "Set Option \"DisableTile\" \"false\"\n"); 3277 } else if (psav->cobSize == 0) { 3278 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3279 "Direct Rendering requires the COB -- " 3280 "Set Option \"DisableCOB\" \"false\"\n"); 3281 } else if (((psav->Chipset == S3_TWISTER) 3282 || (psav->Chipset == S3_PROSAVAGE) 3283 || (psav->Chipset == S3_SAVAGE4) 3284 || (psav->Chipset == S3_SAVAGE_MX) 3285 || (psav->Chipset == S3_SAVAGE3D) 3286 || (psav->Chipset == S3_SUPERSAVAGE) 3287 || (psav->Chipset == S3_PROSAVAGEDDR)) 3288 && (!psav->NoAccel) 3289 && (SavageCheckAvailableRamFor3D(pScrn))) { 3290 /* Setup DRI after visuals have been established */ 3291 psav->directRenderingEnabled = SAVAGEDRIScreenInit(pScreen); 3292 /* If DRI init failed, reset shadow status. */ 3293 if (!psav->directRenderingEnabled && 3294 psav->ShadowStatus != psav->ConfigShadowStatus) { 3295 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Resetting ShadowStatus.\n"); 3296 SavageInitShadowStatus(pScrn); 3297 } 3298 /* If shadow status was enabled for DRI, hook up the shadow 3299 * waiting functions now. */ 3300 else if (psav->ShadowStatus && !psav->ConfigShadowStatus) { 3301 psav->WaitQueue = ShadowWaitQueue; 3302 psav->WaitIdle = ShadowWait; 3303 psav->WaitIdleEmpty = ShadowWait; 3304 } 3305 } else 3306 psav->directRenderingEnabled = FALSE; 3307 3308 if(psav->directRenderingEnabled) { 3309 xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"DRI is enabled\n"); 3310 } 3311 else { 3312 xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"DRI isn't enabled\n"); 3313 } 3314#endif 3315 3316 if (!SavageModeInit(pScrn, pScrn->currentMode)) 3317 return FALSE; 3318 3319 miClearVisualTypes(); 3320 3321 { 3322 int visual; 3323 3324 visual = ((psav->FBStart2nd && pScrn->bitsPerPixel > 8) 3325 || pScrn->bitsPerPixel == 16) ? TrueColorMask 3326 : miGetDefaultVisualMask(DEPTH_BPP(pScrn->depth)); 3327 if (!miSetVisualTypes(pScrn->depth, visual, 3328 pScrn->rgbBits, pScrn->defaultVisual)) 3329 return FALSE; 3330 3331 if (psav->FBStart2nd) {/* we have overlay */ 3332 visual = psav->overlayDepth > 8 ? TrueColorMask : 3333 miGetDefaultVisualMask(DEPTH_BPP(psav->overlayDepth)); 3334 if (!miSetVisualTypes(psav->overlayDepth, visual, 3335 psav->overlayDepth > 8 ? 8 : 6, 3336 pScrn->defaultVisual)) 3337 return FALSE; 3338 } 3339 } 3340 if (!miSetPixmapDepths ()) 3341 return FALSE; 3342 3343 ret = SavageInternalScreenInit(pScreen); 3344 if (!ret) 3345 return FALSE; 3346 3347 xf86SetBlackWhitePixels(pScreen); 3348 3349 { 3350 VisualPtr visual; 3351 visual = pScreen->visuals + pScreen->numVisuals; 3352 while (--visual >= pScreen->visuals) { 3353 if ((visual->class | DynamicClass) == DirectColor 3354 && visual->nplanes > MAX_PSEUDO_DEPTH) { 3355 if (visual->nplanes == pScrn->depth) { 3356 visual->offsetRed = pScrn->offset.red; 3357 visual->offsetGreen = pScrn->offset.green; 3358 visual->offsetBlue = pScrn->offset.blue; 3359 visual->redMask = pScrn->mask.red; 3360 visual->greenMask = pScrn->mask.green; 3361 visual->blueMask = pScrn->mask.blue; 3362 } else if (visual->offsetRed > 8 3363 || visual->offsetGreen > 8 3364 || visual->offsetBlue > 8) { 3365 /* 3366 * mi has set these wrong. fix it here -- we cannot use pScrn 3367 * as this is set up for the default depth 8. 3368 */ 3369 int tmp; 3370 int c_s = 0; 3371 3372 tmp = visual->offsetBlue; 3373 visual->offsetBlue = visual->offsetRed; 3374 visual->offsetRed = tmp; 3375 tmp = visual->blueMask; 3376 visual->blueMask = visual->redMask; 3377 visual->redMask = tmp; 3378 switch (DEPTH_2ND(pScrn)) { 3379 case 16: 3380 visual->offsetRed = 11; 3381 visual->offsetGreen = 5; 3382 visual->offsetBlue = 0; 3383 visual->redMask = 0xF800; 3384 visual->greenMask = 0x7E0; 3385 visual->blueMask = 0x1F; 3386 break; 3387 case 24: 3388 visual->offsetRed = 16; 3389 visual->offsetGreen = 8; 3390 visual->offsetBlue = 0; 3391 visual->redMask = 0xFF0000; 3392 visual->greenMask = 0xFF00; 3393 visual->blueMask = 0xFF; 3394 c_s = 2; 3395 break; 3396 } 3397 psav->overlay.redMask = visual->redMask; 3398 psav->overlay.greenMask = visual->greenMask; 3399 psav->overlay.blueMask = visual->blueMask; 3400 psav->overlay.redShift = visual->offsetRed + c_s; 3401 psav->overlay.greenShift = visual->offsetGreen + c_s; 3402 psav->overlay.blueShift = visual->offsetBlue + c_s; 3403 } 3404 } 3405 } 3406 } 3407 3408 /* must be after RGB ordering fixed */ 3409 fbPictureInit (pScreen, 0, 0); 3410 3411 if( !psav->NoAccel ) { 3412 SavageInitAccel(pScreen); 3413 } 3414 3415 xf86SetBackingStore(pScreen); 3416 3417 if( !psav->shadowFB && !psav->useEXA ) 3418 SavageDGAInit(pScreen); 3419 3420 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 3421 3422 if (psav->hwcursor) 3423 if (!SavageHWCursorInit(pScreen)) 3424 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 3425 "Hardware cursor initialization failed\n"); 3426 3427 if (psav->shadowFB) { 3428 RefreshAreaFuncPtr refreshArea = SavageRefreshArea; 3429 3430 if(psav->rotate) { 3431 if (!psav->PointerMoved) { 3432 psav->PointerMoved = pScrn->PointerMoved; 3433 pScrn->PointerMoved = SavagePointerMoved; 3434 } 3435 3436 switch(pScrn->bitsPerPixel) { 3437 case 8: refreshArea = SavageRefreshArea8; break; 3438 case 16: refreshArea = SavageRefreshArea16; break; 3439 case 24: refreshArea = SavageRefreshArea24; break; 3440 case 32: refreshArea = SavageRefreshArea32; break; 3441 } 3442 } 3443 3444 ShadowFBInit(pScreen, refreshArea); 3445 } 3446 3447 if (!miCreateDefColormap(pScreen)) 3448 return FALSE; 3449 3450 colormapFlags = CMAP_RELOAD_ON_MODE_SWITCH 3451 | ((psav->FBStart2nd) ? 0 : CMAP_PALETTED_TRUECOLOR); 3452 3453 if (psav->Chipset == S3_SAVAGE4) { 3454 if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, SavageLoadPaletteSavage4, 3455 NULL, colormapFlags )) 3456 return FALSE; 3457 } else { 3458 if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, SavageLoadPalette, NULL, 3459 colormapFlags )) 3460 return FALSE; 3461 } 3462 3463 vgaHWBlankScreen(pScrn, FALSE); 3464 3465 psav->CloseScreen = pScreen->CloseScreen; 3466 pScreen->SaveScreen = SavageSaveScreen; 3467 pScreen->CloseScreen = SavageCloseScreen; 3468 3469 if (xf86DPMSInit(pScreen, SavageDPMS, 0) == FALSE) 3470 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DPMS initialization failed\n"); 3471 3472#ifdef SAVAGEDRI 3473 if (psav->directRenderingEnabled) { 3474 /* complete the DRI setup.*/ 3475 psav->directRenderingEnabled = SAVAGEDRIFinishScreenInit(pScreen); 3476 /* If DRI initialization failed, reset shadow status and 3477 * reinitialize 2D engine. */ 3478 if (!psav->directRenderingEnabled && 3479 psav->ShadowStatus != psav->ConfigShadowStatus) { 3480 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Resetting ShadowStatus.\n"); 3481 SavageInitShadowStatus(pScrn); 3482 SavageInitialize2DEngine(pScrn); 3483 } 3484 } 3485 if (psav->directRenderingEnabled) { 3486 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n"); 3487 } else { 3488 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Direct rendering disabled\n"); 3489 } 3490#endif 3491 3492 SavagePanningCheck(pScrn, pScrn->currentMode); 3493#ifdef XvExtension 3494 if( !psav->FBStart2nd && !psav->NoAccel /*&& !SavagePanningCheck(pScrn)*/ ) { 3495 if (psav->IsSecondary) 3496 /* Xv should work on crtc2, but I haven't gotten there yet. -- AGD */ 3497 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Xv currently disabled for crtc2.\n"); 3498 else 3499 SavageInitVideo( pScreen ); 3500 } 3501#endif 3502 3503#ifdef SAVAGEDRI 3504 if ((psav->directRenderingEnabled) && (!psav->bDisableXvMC)) { 3505 if (SAVAGEInitMC(pScreen)) 3506 xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"XvMC is enabled\n"); 3507 else 3508 xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"XvMC is not enabled\n"); 3509 } 3510 3511 if (!psav->directRenderingEnabled && psav->AGPforXv) { 3512 xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"AGPforXV requires DRI to be enabled.\n"); 3513 psav->AGPforXv = FALSE; 3514 } 3515#endif 3516 3517 if (serverGeneration == 1) 3518 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 3519 3520 return TRUE; 3521} 3522 3523 3524static int SavageInternalScreenInit(ScreenPtr pScreen) 3525{ 3526 int ret = TRUE; 3527 ScrnInfoPtr pScrn; 3528 SavagePtr psav; 3529 int width, height, displayWidth; 3530 unsigned char *FBStart; 3531 3532 TRACE(("SavageInternalScreenInit()\n")); 3533 3534 pScrn = xf86ScreenToScrn(pScreen); 3535 psav = SAVPTR(pScrn); 3536 3537 displayWidth = pScrn->displayWidth; 3538 3539 if (psav->rotate) { 3540 height = pScrn->virtualX; 3541 width = pScrn->virtualY; 3542 } else { 3543 width = pScrn->virtualX; 3544 height = pScrn->virtualY; 3545 } 3546 3547 3548 if(psav->shadowFB) { 3549 psav->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); 3550 psav->ShadowPtr = malloc(psav->ShadowPitch * height); 3551 displayWidth = psav->ShadowPitch / (pScrn->bitsPerPixel >> 3); 3552 FBStart = psav->ShadowPtr; 3553 } else { 3554 psav->ShadowPtr = NULL; 3555 FBStart = psav->FBStart; 3556 } 3557 3558 if (!psav->FBStart2nd) { 3559 3560 ret = fbScreenInit(pScreen, FBStart, width, height, 3561 pScrn->xDpi, pScrn->yDpi, 3562 psav->ulAperturePitch / (pScrn->bitsPerPixel >> 3), /*displayWidth,*/ 3563 pScrn->bitsPerPixel); 3564 3565 } else { 3566 FbOverlayScrPrivPtr pScrPriv; 3567 int Depth2nd = DEPTH_2ND(pScrn); 3568 if (!fbSetupScreen (pScreen, FBStart, width, height, 3569 pScrn->xDpi, pScrn->yDpi, displayWidth, 8)) 3570 return FALSE; 3571 if (pScrn->depth == 8) { 3572 ret = fbOverlayFinishScreenInit (pScreen, FBStart, 3573 psav->FBStart2nd, width, 3574 height,pScrn->xDpi, pScrn->yDpi, 3575 displayWidth,displayWidth, 3576 8, DEPTH_BPP(Depth2nd), 3577 8, Depth2nd); 3578 pScrPriv = fbOverlayGetScrPriv(pScreen); 3579 pScrPriv->layer[0].key = pScrn->colorKey; 3580 } else { 3581 ret = fbOverlayFinishScreenInit (pScreen, psav->FBStart2nd, 3582 FBStart, 3583 width, height,pScrn->xDpi, 3584 pScrn->yDpi, 3585 displayWidth,displayWidth, 3586 DEPTH_BPP(Depth2nd), 8, 3587 Depth2nd, 8); 3588 pScrPriv = fbOverlayGetScrPriv(pScreen); 3589 pScrPriv->layer[1].key = pScrn->colorKey; 3590 } 3591 } 3592 return ret; 3593} 3594 3595 3596static int SavageGetRefresh(DisplayModePtr mode) 3597{ 3598 int refresh = (mode->Clock * 1000) / (mode->HTotal * mode->VTotal); 3599 if (mode->Flags & V_INTERLACE) 3600 refresh *= 2.0; 3601 if (mode->Flags & V_DBLSCAN) 3602 refresh /= 2.0; 3603 if (mode->VScan > 1) 3604 refresh /= mode->VScan; 3605 return refresh; 3606} 3607 3608 3609static ModeStatus SavageValidMode(SCRN_ARG_TYPE arg, DisplayModePtr pMode, 3610 Bool verbose, int flags) 3611{ 3612 SCRN_INFO_PTR(arg); 3613 SavagePtr psav = SAVPTR(pScrn); 3614 int refresh; 3615 3616 TRACE(("SavageValidMode\n")); 3617 3618 /* We prohibit modes bigger than the LCD panel. */ 3619 /* TODO We should do this only if the panel is active. */ 3620 3621 if( psav->TvOn ) 3622 { 3623 if( pMode->HDisplay > psav->TVSizeX ) 3624 return MODE_VIRTUAL_X; 3625 3626 if( pMode->VDisplay > psav->TVSizeY ) 3627 return MODE_VIRTUAL_Y; 3628 3629 } 3630 3631 if((psav->DisplayType == MT_LCD) && 3632 ((pMode->HDisplay > psav->PanelX) || 3633 (pMode->VDisplay > psav->PanelY))) 3634 return MODE_PANEL; 3635 3636 if (psav->UseBIOS) { 3637 refresh = SavageGetRefresh(pMode); 3638 return (SavageMatchBiosMode(pScrn,pMode->HDisplay, 3639 pMode->VDisplay, 3640 refresh,NULL,NULL)); 3641 } 3642 3643 return MODE_OK; 3644} 3645 3646static Bool SavageModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 3647{ 3648 vgaHWPtr hwp = VGAHWPTR(pScrn); 3649 SavagePtr psav = SAVPTR(pScrn); 3650 int width, dclk, i, j; /*, refresh; */ 3651 unsigned int m, n, r; 3652 unsigned char tmp = 0; 3653 SavageRegPtr new = &psav->ModeReg; 3654 vgaRegPtr vganew = &hwp->ModeReg; 3655 int vgaCRIndex, vgaCRReg, vgaIOBase; 3656 int refresh; 3657 unsigned int newmode=0, newrefresh=0; 3658 3659 vgaIOBase = hwp->IOBase; 3660 vgaCRIndex = vgaIOBase + 4; 3661 vgaCRReg = vgaIOBase + 5; 3662 3663 TRACE(("SavageModeInit(%dx%d, %dkHz)\n", 3664 mode->HDisplay, mode->VDisplay, mode->Clock)); 3665 3666#if 0 3667 ErrorF("Clock = %d, HDisplay = %d, HSStart = %d\n", 3668 mode->Clock, mode->HDisplay, mode->HSyncStart); 3669 ErrorF("HSEnd = %d, HSkew = %d\n", 3670 mode->HSyncEnd, mode->HSkew); 3671 ErrorF("VDisplay - %d, VSStart = %d, VSEnd = %d\n", 3672 mode->VDisplay, mode->VSyncStart, mode->VSyncEnd); 3673 ErrorF("VTotal = %d\n", 3674 mode->VTotal); 3675 ErrorF("HDisplay = %d, HSStart = %d\n", 3676 mode->CrtcHDisplay, mode->CrtcHSyncStart); 3677 ErrorF("HSEnd = %d, HSkey = %d\n", 3678 mode->CrtcHSyncEnd, mode->CrtcHSkew); 3679 ErrorF("VDisplay - %d, VSStart = %d, VSEnd = %d\n", 3680 mode->CrtcVDisplay, mode->CrtcVSyncStart, mode->CrtcVSyncEnd); 3681 ErrorF("VTotal = %d\n", 3682 mode->CrtcVTotal); 3683#endif 3684 3685 if (psav->IsSecondary) { 3686 refresh = SavageGetRefresh(mode); 3687 3688 SavageMatchBiosMode(pScrn,mode->HDisplay,mode->VDisplay,refresh, 3689 &newmode,&newrefresh); 3690 new->mode = newmode; 3691 new->refresh = newrefresh; 3692 3693 /* do it! */ 3694 SavageWriteMode(pScrn, vganew, new, TRUE); 3695 3696 if (psav->FBStart2nd) { 3697 SavageStreamsOn(pScrn); 3698 SavageInitSecondaryStream(pScrn); 3699 } 3700 3701 SavageAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 3702 return TRUE; 3703 } 3704 3705 3706 if (pScrn->bitsPerPixel == 8) 3707 psav->HorizScaleFactor = 1; 3708 else if (pScrn->bitsPerPixel == 16) 3709 psav->HorizScaleFactor = 1; /* I don't think we ever want 2 */ 3710 else 3711 psav->HorizScaleFactor = 1; 3712 3713 if (psav->HorizScaleFactor == 2) 3714 if (!mode->CrtcHAdjusted) { 3715 mode->CrtcHDisplay *= 2; 3716 mode->CrtcHSyncStart *= 2; 3717 mode->CrtcHSyncEnd *= 2; 3718 mode->CrtcHBlankStart *= 2; 3719 mode->CrtcHBlankEnd *= 2; 3720 mode->CrtcHTotal *= 2; 3721 mode->CrtcHSkew *= 2; 3722 mode->CrtcHAdjusted = TRUE; 3723 } 3724 3725 if (!vgaHWInit(pScrn, mode)) 3726 return FALSE; 3727 3728 new->mode = 0; 3729 3730 /* We need to set CR67 whether or not we use the BIOS. */ 3731 3732 dclk = mode->Clock; 3733 new->CR67 = 0x00; 3734 3735 switch( pScrn->depth ) { 3736 case 8: 3737 if( (psav->Chipset == S3_SAVAGE2000) && (dclk >= 230000) ) 3738 new->CR67 = 0x10; /* 8bpp, 2 pixels/clock */ 3739 else 3740 new->CR67 = 0x00; /* 8bpp, 1 pixel/clock */ 3741 break; 3742 case 15: 3743 if( 3744 S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || 3745 ((psav->Chipset == S3_SAVAGE2000) && (dclk >= 230000)) 3746 ) 3747 new->CR67 = 0x30; /* 15bpp, 2 pixel/clock */ 3748 else 3749 new->CR67 = 0x20; /* 15bpp, 1 pixels/clock */ 3750 break; 3751 case 16: 3752 if( 3753 S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || 3754 ((psav->Chipset == S3_SAVAGE2000) && (dclk >= 230000)) 3755 ) 3756 new->CR67 = 0x50; /* 16bpp, 2 pixel/clock */ 3757 else 3758 new->CR67 = 0x40; /* 16bpp, 1 pixels/clock */ 3759 break; 3760 case 24: 3761 if (psav->primStreamBpp == 24 ) 3762 new->CR67 = 0x70; 3763 else 3764 new->CR67 = 0xd0; 3765 break; 3766 } 3767 3768 3769 if( psav->UseBIOS ) { 3770 int refresh; 3771 unsigned int newmode=0, newrefresh=0; 3772 3773 refresh = SavageGetRefresh(mode); 3774 3775 SavageMatchBiosMode(pScrn,mode->HDisplay,mode->VDisplay,refresh, 3776 &newmode,&newrefresh); 3777 new->mode = newmode; 3778 new->refresh = newrefresh; 3779 } 3780 3781 if( !new->mode ) { 3782 /* 3783 * Either BIOS use is disabled, or we failed to find a suitable 3784 * match. Fall back to traditional register-crunching. 3785 */ 3786 3787 VGAOUT8(vgaCRIndex, 0x3a); 3788 tmp = VGAIN8(vgaCRReg); 3789 if (psav->pci_burst) 3790 new->CR3A = (tmp & 0x7f) | 0x15; 3791 else 3792 new->CR3A = tmp | 0x95; 3793 3794 new->CR53 = 0x00; 3795 new->CR31 = 0x8c; 3796 new->CR66 = 0x89; 3797 3798 VGAOUT8(vgaCRIndex, 0x58); 3799 new->CR58 = VGAIN8(vgaCRReg) & 0x80; 3800 new->CR58 |= 0x13; 3801 3802#if 0 3803 VGAOUT8(vgaCRIndex, 0x55); 3804 new->CR55 = VGAIN8(vgaCRReg); 3805 if (psav->hwcursor) 3806 new->CR55 |= 0x10; 3807#endif 3808 3809 new->SR15 = 0x03 | 0x80; 3810 new->SR18 = 0x00; 3811 3812 3813 /* enable gamma correction */ 3814 if( pScrn->depth == 24 ) 3815 new->SR1B = 0x18; 3816 else 3817 new->SR1B = 0x00; 3818 3819 /* set 8-bit CLUT */ 3820 new->SR1B |= 0x10; 3821 3822 new->CR43 = new->CR45 = new->CR65 = 0x00; 3823 3824 VGAOUT8(vgaCRIndex, 0x40); 3825 new->CR40 = VGAIN8(vgaCRReg) & ~0x01; 3826 3827 new->MMPR0 = 0x010400; 3828 new->MMPR1 = 0x00; 3829 new->MMPR2 = 0x0808; 3830 new->MMPR3 = 0x08080810; 3831 3832 if (psav->fifo_aggressive || psav->fifo_moderate || 3833 psav->fifo_conservative) { 3834 new->MMPR1 = 0x0200; 3835 new->MMPR2 = 0x1808; 3836 new->MMPR3 = 0x08081810; 3837 } 3838 3839 if (psav->MCLK <= 0) { 3840 new->SR10 = 255; 3841 new->SR11 = 255; 3842 } 3843 3844 psav->NeedSTREAMS = FALSE; 3845 3846 SavageCalcClock(dclk, 1, 1, 127, 0, 4, 180000, 360000, 3847 &m, &n, &r); 3848 new->SR12 = (r << 6) | (n & 0x3f); 3849 new->SR13 = m & 0xff; 3850 new->SR29 = (r & 4) | (m & 0x100) >> 5 | (n & 0x40) >> 2; 3851 3852 if (psav->fifo_moderate) { 3853 if (psav->primStreamBpp < 24) 3854 new->MMPR0 -= 0x8000; 3855 else 3856 new->MMPR0 -= 0x4000; 3857 } else if (psav->fifo_aggressive) { 3858 if (psav->primStreamBpp < 24) 3859 new->MMPR0 -= 0xc000; 3860 else 3861 new->MMPR0 -= 0x6000; 3862 } 3863 3864 if (mode->Flags & V_INTERLACE) 3865 new->CR42 = 0x20; 3866 else 3867 new->CR42 = 0x00; 3868 3869 new->CR34 = 0x10; 3870 3871 i = ((((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8) | 3872 ((((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) | 3873 ((((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) | 3874 ((mode->CrtcHSyncStart & 0x800) >> 7); 3875 3876 if ((mode->CrtcHSyncEnd >> 3) - (mode->CrtcHSyncStart >> 3) > 64) 3877 i |= 0x08; 3878 if ((mode->CrtcHSyncEnd >> 3) - (mode->CrtcHSyncStart >> 3) > 32) 3879 i |= 0x20; 3880 j = (vganew->CRTC[0] + ((i & 0x01) << 8) + 3881 vganew->CRTC[4] + ((i & 0x10) << 4) + 1) / 2; 3882 if (j - (vganew->CRTC[4] + ((i & 0x10) << 4)) < 4) { 3883 if (vganew->CRTC[4] + ((i & 0x10) << 4) + 4 <= 3884 vganew->CRTC[0] + ((i & 0x01) << 8)) 3885 j = vganew->CRTC[4] + ((i & 0x10) << 4) + 4; 3886 else 3887 j = vganew->CRTC[0] + ((i & 0x01) << 8) + 1; 3888 } 3889 3890 new->CR3B = j & 0xff; 3891 i |= (j & 0x100) >> 2; 3892 new->CR3C = (vganew->CRTC[0] + ((i & 0x01) << 8)) / 2 ; 3893 new->CR5D = i; 3894 new->CR5E = (((mode->CrtcVTotal - 2) & 0x400) >> 10) | 3895 (((mode->CrtcVDisplay - 1) & 0x400) >> 9) | 3896 (((mode->CrtcVSyncStart) & 0x400) >> 8) | 3897 (((mode->CrtcVSyncStart) & 0x400) >> 6) | 0x40; 3898 width = (pScrn->displayWidth * (psav->primStreamBpp / 8)) >> 3; 3899 new->CR91 = vganew->CRTC[19] = 0xff & width; 3900 new->CR51 = (0x300 & width) >> 4; 3901 new->CR90 = 0x80 | (width >> 8); 3902 vganew->MiscOutReg |= 0x0c; 3903 3904 /* Set frame buffer description. */ 3905 3906 if (psav->primStreamBpp <= 8) 3907 new->CR50 = 0; 3908 else if (psav->primStreamBpp <= 16) 3909 new->CR50 = 0x10; 3910 else 3911 new->CR50 = 0x30; 3912 3913 if (pScrn->displayWidth == 640) 3914 new->CR50 |= 0x40; 3915 else if (pScrn->displayWidth == 800) 3916 new->CR50 |= 0x80; 3917 else if (pScrn->displayWidth == 1024) 3918 new->CR50 |= 0x00; 3919 else if (pScrn->displayWidth == 1152) 3920 new->CR50 |= 0x01; 3921 else if (pScrn->displayWidth == 1280) 3922 new->CR50 |= 0xc0; 3923 else if (pScrn->displayWidth == 1600) 3924 new->CR50 |= 0x81; 3925 else 3926 new->CR50 |= 0xc1; /* Use GBD */ 3927 3928 if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) 3929 new->CR33 = 0x00; 3930 else 3931 new->CR33 = 0x08; 3932 3933 vganew->CRTC[0x17] = 0xeb; 3934 3935 new->CR67 |= 1; 3936 3937 VGAOUT8(vgaCRIndex, 0x36); 3938 new->CR36 = VGAIN8(vgaCRReg); 3939 VGAOUT8(vgaCRIndex, 0x68); 3940 new->CR68 = VGAIN8(vgaCRReg); 3941 3942 new->CR69 = 0; 3943 VGAOUT8(vgaCRIndex, 0x6f); 3944 new->CR6F = VGAIN8(vgaCRReg); 3945 VGAOUT8(vgaCRIndex, 0x86); 3946 new->CR86 = VGAIN8(vgaCRReg) | 0x08; 3947 VGAOUT8(vgaCRIndex, 0x88); 3948 new->CR88 = VGAIN8(vgaCRReg) | DISABLE_BLOCK_WRITE_2D; 3949 VGAOUT8(vgaCRIndex, 0xb0); 3950 new->CRB0 = VGAIN8(vgaCRReg) | 0x80; 3951 } 3952 3953 pScrn->vtSema = TRUE; 3954 3955 /* do it! */ 3956 SavageWriteMode(pScrn, vganew, new, TRUE); 3957 3958 if (psav->FBStart2nd) { 3959 SavageStreamsOn(pScrn); 3960 SavageInitSecondaryStream(pScrn); 3961 } 3962 3963 SavageAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 3964 3965 return TRUE; 3966} 3967 3968 3969static Bool SavageCloseScreen(CLOSE_SCREEN_ARGS_DECL) 3970{ 3971 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 3972 vgaHWPtr hwp = VGAHWPTR(pScrn); 3973 SavagePtr psav = SAVPTR(pScrn); 3974 vgaRegPtr vgaSavePtr = &hwp->SavedReg; 3975 SavageRegPtr SavageSavePtr = &psav->SavedReg; 3976 3977 TRACE(("SavageCloseScreen\n")); 3978 3979#ifdef SAVAGEDRI 3980 if (psav->directRenderingEnabled) { 3981 SAVAGEDRICloseScreen(pScreen); 3982 /* reset shadow values */ 3983 SavageInitShadowStatus(pScrn); 3984 psav->directRenderingEnabled=FALSE; 3985 } 3986#endif 3987 3988 if (psav->EXADriverPtr) { 3989 exaDriverFini(pScreen); 3990 psav->EXADriverPtr = NULL; 3991 } 3992 3993#ifdef HAVE_XAA_H 3994 if( psav->AccelInfoRec ) { 3995 XAADestroyInfoRec( psav->AccelInfoRec ); 3996 psav->AccelInfoRec = NULL; 3997 } 3998#endif 3999 4000 if( psav->DGAModes ) { 4001 free( psav->DGAModes ); 4002 psav->DGAModes = NULL; 4003 psav->numDGAModes = 0; 4004 } 4005 4006 if (pScrn->vtSema) { 4007 if (psav->FBStart2nd) 4008 SavageStreamsOff(pScrn); 4009 SavageWriteMode(pScrn, vgaSavePtr, SavageSavePtr, FALSE); 4010 SavageResetStreams(pScrn); 4011 vgaHWLock(hwp); 4012 SavageUnmapMem(pScrn, 0); 4013 } 4014 4015 if (psav->pVbe) 4016 vbeFree(psav->pVbe); 4017 psav->pVbe = NULL; 4018 4019 pScrn->vtSema = FALSE; 4020 pScreen->CloseScreen = psav->CloseScreen; 4021 4022 return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); 4023} 4024 4025 4026static Bool SavageSaveScreen(ScreenPtr pScreen, int mode) 4027{ 4028 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 4029 4030 TRACE(("SavageSaveScreen(0x%x)\n", mode)); 4031 4032 if( pScrn->vtSema && SAVPTR(pScrn)->hwcursor && SAVPTR(pScrn)->hwc_on ) 4033 { 4034 if( xf86IsUnblank(mode) ) 4035 SavageShowCursor( pScrn ); 4036 else 4037 SavageHideCursor( pScrn ); 4038 SAVPTR(pScrn)->hwc_on = TRUE; /*restore */ 4039 } 4040 4041 return vgaHWSaveScreen(pScreen, mode); 4042} 4043 4044void SavageAdjustFrame(ADJUST_FRAME_ARGS_DECL) 4045{ 4046 SCRN_INFO_PTR(arg); 4047 SavagePtr psav = SAVPTR(pScrn); 4048 4049 if (psav->IsSecondary) { 4050 SavageDoAdjustFrame(pScrn, x, y, TRUE); 4051 } else { 4052 SavageDoAdjustFrame(pScrn, x, y, FALSE); 4053 } 4054 4055} 4056 4057void 4058SavageDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int crtc2) 4059{ 4060 SavagePtr psav = SAVPTR(pScrn); 4061 int address=0,top=0,left=0,tile_height,tile_size; 4062 4063 TRACE(("SavageDoAdjustFrame(%d,%d,%d)\n", x, y, crtc2)); 4064 4065 if (psav->Chipset == S3_SAVAGE2000) { 4066 tile_height = TILEHEIGHT_2000; /* 32 */ 4067 tile_size = TILE_SIZE_BYTE_2000; /* 4096 */ 4068 } else { 4069 tile_height = TILEHEIGHT; /* 16 */ 4070 tile_size = TILE_SIZE_BYTE; /* 2048 */ 4071 } 4072 4073 if (!psav->bTiled) { 4074 left = x - x % 64; 4075 top = y; 4076 address = (top * psav->lDelta) + left * (pScrn->bitsPerPixel >> 3); 4077 address = (address >> 5) << 5; 4078 } else { 4079 top = y - y % tile_height; 4080 if (pScrn->bitsPerPixel == 16) { 4081 left = x - x % TILEWIDTH_16BPP; 4082 address = top * psav->lDelta + left * tile_size / TILEWIDTH_16BPP; 4083 } else if (pScrn->bitsPerPixel == 32) { 4084 left = x - x % TILEWIDTH_32BPP; 4085 address = top * psav->lDelta + left * tile_size / TILEWIDTH_32BPP; 4086 } 4087 } 4088 4089 address += pScrn->fbOffset; 4090 4091 if (psav->Chipset == S3_SAVAGE_MX) { 4092 if (!crtc2) { 4093 OUTREG32(PRI_STREAM_FBUF_ADDR0, address & 0xFFFFFFFC); 4094 OUTREG32(PRI_STREAM_FBUF_ADDR1, address & 0xFFFFFFFC);/* IGA1 */ 4095 } else { 4096 OUTREG32(PRI_STREAM2_FBUF_ADDR0, address & 0xFFFFFFFC);/* IGA2 */ 4097 OUTREG32(PRI_STREAM2_FBUF_ADDR1, address & 0xFFFFFFFC); 4098 } 4099 } else if (psav->Chipset == S3_SUPERSAVAGE) { 4100 if (!crtc2) { 4101 /* IGA1 */ 4102 OUTREG32(PRI_STREAM_FBUF_ADDR0, 0x80000000); 4103 OUTREG32(PRI_STREAM_FBUF_ADDR1, address & 0xFFFFFFF8); 4104 } else { 4105 /* IGA2 */ 4106 OUTREG32(PRI_STREAM2_FBUF_ADDR0, ((address & 0xFFFFFFF8) | 0x80000000)); 4107 OUTREG32(PRI_STREAM2_FBUF_ADDR1, address & 0xFFFFFFF8); 4108 } 4109 } else if (psav->Chipset == S3_SAVAGE2000) { 4110 /* certain Y values seems to cause havoc, not sure why */ 4111 OUTREG32(PRI_STREAM_FBUF_ADDR0, (address & 0xFFFFFFF8)); 4112 OUTREG32(PRI_STREAM2_FBUF_ADDR0, (address & 0xFFFFFFF8)); 4113 } else { 4114 OUTREG32(PRI_STREAM_FBUF_ADDR0,address | 0xFFFFFFFC); 4115 OUTREG32(PRI_STREAM_FBUF_ADDR1,address | 0x80000000); 4116 } 4117 4118 return; 4119} 4120 4121Bool SavageSwitchMode(SWITCH_MODE_ARGS_DECL) 4122{ 4123 SCRN_INFO_PTR(arg); 4124 SavagePtr psav = SAVPTR(pScrn); 4125 Bool success; 4126 4127 TRACE(("SavageSwitchMode\n")); 4128 4129 if (psav->FBStart2nd || (psav->videoFlags & VF_STREAMS_ON)) 4130 SavageStreamsOff(pScrn); 4131 4132 success = SavageModeInit(pScrn, mode); 4133 4134 /* switching mode on primary will reset secondary. it needs to be reset as well*/ 4135 if (psav->IsPrimary) { 4136 DevUnion* pPriv; 4137 SavageEntPtr pSavEnt; 4138 pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 4139 gSavageEntityIndex); 4140 pSavEnt = pPriv->ptr; 4141 SavageModeInit(pSavEnt->pSecondaryScrn, pSavEnt->pSecondaryScrn->currentMode); 4142 } 4143 SavagePanningCheck(pScrn, mode); 4144 4145 return success; 4146} 4147 4148 4149void SavageEnableMMIO(ScrnInfoPtr pScrn) 4150{ 4151 vgaHWPtr hwp = VGAHWPTR(pScrn); 4152 SavagePtr psav = SAVPTR(pScrn); 4153 int vgaCRIndex, vgaCRReg; 4154 unsigned char val; 4155 4156 TRACE(("SavageEnableMMIO\n")); 4157 4158 vgaHWSetStdFuncs(hwp); 4159 vgaHWSetMmioFuncs(hwp, psav->MapBase, 0x8000); 4160 val = VGAIN8(0x3c3); 4161 VGAOUT8(0x3c3, val | 0x01); 4162 val = VGAIN8(VGA_MISC_OUT_R); 4163 VGAOUT8(VGA_MISC_OUT_W, val | 0x01); 4164 vgaCRIndex = psav->vgaIOBase + 4; 4165 vgaCRReg = psav->vgaIOBase + 5; 4166 4167 if( psav->Chipset >= S3_SAVAGE4 ) 4168 { 4169 VGAOUT8(vgaCRIndex, 0x40); 4170 val = VGAIN8(vgaCRReg); 4171 VGAOUT8(vgaCRReg, val | 1); 4172 } 4173 4174 return; 4175} 4176 4177 4178void SavageDisableMMIO(ScrnInfoPtr pScrn) 4179{ 4180 vgaHWPtr hwp = VGAHWPTR(pScrn); 4181 SavagePtr psav = SAVPTR(pScrn); 4182 int vgaCRIndex, vgaCRReg; 4183 unsigned char val; 4184 4185 TRACE(("SavageDisableMMIO\n")); 4186 4187 vgaCRIndex = psav->vgaIOBase + 4; 4188 vgaCRReg = psav->vgaIOBase + 5; 4189 4190 if( psav->Chipset >= S3_SAVAGE4 ) 4191 { 4192 VGAOUT8(vgaCRIndex, 0x40); 4193 val = VGAIN8(vgaCRReg); 4194 VGAOUT8(vgaCRReg, val | 1); 4195 } 4196 4197 vgaHWSetStdFuncs(hwp); 4198 4199 return; 4200} 4201 4202void SavageLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies, 4203 LOCO *colors, VisualPtr pVisual) 4204{ 4205 SavagePtr psav = SAVPTR(pScrn); 4206 int i, index; 4207 int updateKey = -1; 4208 unsigned char byte = 0; 4209 4210 /* choose CLUT */ 4211 if (psav->IsPrimary) { 4212 /* enable CLUT 1 */ 4213 VGAOUT8(0x3c4, 0x21); 4214 byte = VGAIN8(0x3c5); 4215 VGAOUT8(0x3c5, (byte & ~0x01)); 4216 /* select CLUT 1 */ 4217 VGAOUT8(0x3c4, 0x47); 4218 byte = VGAIN8(0x3c5); 4219 VGAOUT8(0x3c5, (byte & ~0x03) | 0x01); /* CLUT 1 */ 4220 } else if (psav->IsSecondary) { 4221 /* enable CLUT 2 */ 4222 VGAOUT8(0x3c4, 0x21); 4223 byte = VGAIN8(0x3c5); 4224 VGAOUT8(0x3c5, (byte & ~0x10)); 4225 /* select CLUT 2 */ 4226 VGAOUT8(0x3c4, 0x47); 4227 byte = VGAIN8(0x3c5); 4228 VGAOUT8(0x3c5, (byte & ~0x03) | 0x02); /* CLUT 2 */ 4229 } 4230 4231 for (i=0; i<numColors; i++) { 4232 index = indicies[i]; 4233 if (index == pScrn->colorKey) updateKey = index; 4234 VGAOUT8(0x3c8, index); 4235 VGAOUT8(0x3c9, colors[index].red); 4236 VGAOUT8(0x3c9, colors[index].green); 4237 VGAOUT8(0x3c9, colors[index].blue); 4238 } 4239 4240 /* restore saved CLUT index value */ 4241 if (psav->IsPrimary || psav->IsSecondary) { 4242 VGAOUT8(0x3c4, 0x47); 4243 VGAOUT8(0x3c5, byte); 4244 } 4245 4246 if (updateKey != -1) 4247 SavageUpdateKey(pScrn, colors[updateKey].red, colors[updateKey].green, 4248 colors[updateKey].blue); 4249} 4250 4251#define Shift(v,d) ((d) < 0 ? ((v) >> (-d)) : ((v) << (d))) 4252 4253static void 4254SavageUpdateKey(ScrnInfoPtr pScrn, int r, int g, int b) 4255{ 4256 ScreenPtr pScreen; 4257 SavagePtr psav = SAVPTR(pScrn); 4258 FbOverlayScrPrivPtr pScrOvlPriv; 4259 CARD32 key; 4260 int ul = 0, ol = 1; 4261 4262 if (pScrn->depth != 8) { 4263 ul = 1; 4264 ol = 0; 4265 } 4266 if (!(pScreen = pScrn->pScreen) 4267 || !psav->FBStart2nd 4268 || !(pScrOvlPriv = fbOverlayGetScrPriv(pScreen))) 4269 return; 4270 key = ((Shift(r,psav->overlay.redShift) & psav->overlay.redMask) 4271 | (Shift(g,psav->overlay.greenShift) & psav->overlay.greenMask) 4272 | (Shift(b,psav->overlay.blueShift) & psav->overlay.blueMask)); 4273 if (pScrOvlPriv->layer[ol].key != key) { 4274 pScrOvlPriv->layer[ol].key = key; 4275 (*pScrOvlPriv->PaintKey) (&pScrOvlPriv->layer[ol].u.run.pixmap->drawable, 4276 &pScrOvlPriv->layer[ul].u.run.region, 4277 pScrOvlPriv->layer[ol].key, ol); 4278 } 4279} 4280 4281#if 0 4282#define inStatus1() (hwp->readST01( hwp )) 4283#endif 4284 4285void SavageLoadPaletteSavage4(ScrnInfoPtr pScrn, int numColors, int *indicies, 4286 LOCO *colors, VisualPtr pVisual) 4287{ 4288 SavagePtr psav = SAVPTR(pScrn); 4289 int i, index; 4290 int updateKey = -1; 4291 4292 VerticalRetraceWait(); 4293 4294 for (i=0; i<numColors; i++) { 4295 if (!(inStatus1() & 0x08)) 4296 VerticalRetraceWait(); 4297 index = indicies[i]; 4298 VGAOUT8(0x3c8, index); 4299 VGAOUT8(0x3c9, colors[index].red); 4300 VGAOUT8(0x3c9, colors[index].green); 4301 VGAOUT8(0x3c9, colors[index].blue); 4302 if (index == pScrn->colorKey) updateKey = index; 4303 } 4304 if (updateKey != -1) 4305 SavageUpdateKey(pScrn, colors[updateKey].red, colors[updateKey].green, 4306 colors[updateKey].blue); 4307} 4308 4309static void SavageCalcClock(long freq, int min_m, int min_n1, int max_n1, 4310 int min_n2, int max_n2, long freq_min, 4311 long freq_max, unsigned int *mdiv, 4312 unsigned int *ndiv, unsigned int *r) 4313{ 4314 double ffreq, ffreq_min, ffreq_max; 4315 double div, diff, best_diff; 4316 unsigned int m; 4317 unsigned char n1, n2, best_n1=16+2, best_n2=2, best_m=125+2; 4318 4319 ffreq = freq / 1000.0 / BASE_FREQ; 4320 ffreq_max = freq_max / 1000.0 / BASE_FREQ; 4321 ffreq_min = freq_min / 1000.0 / BASE_FREQ; 4322 4323 if (ffreq < ffreq_min / (1 << max_n2)) { 4324 ErrorF("invalid frequency %1.3f Mhz\n", 4325 ffreq*BASE_FREQ); 4326 ffreq = ffreq_min / (1 << max_n2); 4327 } 4328 if (ffreq > ffreq_max / (1 << min_n2)) { 4329 ErrorF("invalid frequency %1.3f Mhz\n", 4330 ffreq*BASE_FREQ); 4331 ffreq = ffreq_max / (1 << min_n2); 4332 } 4333 4334 /* work out suitable timings */ 4335 4336 best_diff = ffreq; 4337 4338 for (n2=min_n2; n2<=max_n2; n2++) { 4339 for (n1=min_n1+2; n1<=max_n1+2; n1++) { 4340 m = (int)(ffreq * n1 * (1 << n2) + 0.5); 4341 if (m < min_m+2 || m > 127+2) 4342 continue; 4343 div = (double)(m) / (double)(n1); 4344 if ((div >= ffreq_min) && 4345 (div <= ffreq_max)) { 4346 diff = ffreq - div / (1 << n2); 4347 if (diff < 0.0) 4348 diff = -diff; 4349 if (diff < best_diff) { 4350 best_diff = diff; 4351 best_m = m; 4352 best_n1 = n1; 4353 best_n2 = n2; 4354 } 4355 } 4356 } 4357 } 4358 4359 *ndiv = best_n1 - 2; 4360 *r = best_n2; 4361 *mdiv = best_m - 2; 4362} 4363 4364 4365void SavageGEReset(ScrnInfoPtr pScrn, int from_timeout, int line, char *file) 4366{ 4367 unsigned char cr66; 4368 int r, success = 0; 4369 CARD32 fifo_control = 0, miu_control = 0; 4370 CARD32 streams_timeout = 0, misc_timeout = 0; 4371 vgaHWPtr hwp = VGAHWPTR(pScrn); 4372 SavagePtr psav = SAVPTR(pScrn); 4373 int vgaCRIndex, vgaCRReg, vgaIOBase; 4374 4375 TRACE(("SavageGEReset(%d,%s)\n", line, file)); 4376 4377 vgaIOBase = hwp->IOBase; 4378 vgaCRIndex = vgaIOBase + 4; 4379 vgaCRReg = vgaIOBase + 5; 4380 4381 if (from_timeout) { 4382 if (psav->GEResetCnt++ < 10 || xf86GetVerbosity() > 1) 4383 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4384 "SavageGEReset called from %s line %d\n", file, line); 4385 } else 4386 psav->WaitIdleEmpty(psav); 4387 4388 if (from_timeout && !S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) { 4389 fifo_control = INREG(FIFO_CONTROL_REG); 4390 miu_control = INREG(MIU_CONTROL_REG); 4391 streams_timeout = INREG(STREAMS_TIMEOUT_REG); 4392 misc_timeout = INREG(MISC_TIMEOUT_REG); 4393 } 4394 4395 VGAOUT8(vgaCRIndex, 0x66); 4396 cr66 = VGAIN8(vgaCRReg); 4397 4398 usleep(10000); 4399 for (r=1; r<10; r++) { 4400 VGAOUT8(vgaCRReg, cr66 | 0x02); 4401 usleep(10000); 4402 VGAOUT8(vgaCRReg, cr66 & ~0x02); 4403 usleep(10000); 4404 4405 if (!from_timeout) 4406 psav->WaitIdleEmpty(psav); 4407 OUTREG(DEST_SRC_STR, psav->Bpl << 16 | psav->Bpl); 4408 4409 usleep(10000); 4410 switch(psav->Chipset) { 4411 case S3_SAVAGE3D: 4412 case S3_SAVAGE_MX: 4413 success = (STATUS_WORD0 & 0x0008ffff) == 0x00080000; 4414 break; 4415 case S3_SAVAGE4: 4416 case S3_PROSAVAGE: 4417 case S3_PROSAVAGEDDR: 4418 case S3_TWISTER: 4419 case S3_SUPERSAVAGE: 4420 success = (ALT_STATUS_WORD0 & 0x0081ffff) == 0x00800000; 4421 break; 4422 case S3_SAVAGE2000: 4423 success = (ALT_STATUS_WORD0 & 0x008fffff) == 0; 4424 break; 4425 } 4426 if(!success) { 4427 usleep(10000); 4428 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4429 "restarting S3 graphics engine reset %2d ...\n", r); 4430 } 4431 else 4432 break; 4433 } 4434 4435 /* At this point, the FIFO is empty and the engine is idle. */ 4436 4437 if (from_timeout && !S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) { 4438 OUTREG(FIFO_CONTROL_REG, fifo_control); 4439 OUTREG(MIU_CONTROL_REG, miu_control); 4440 OUTREG(STREAMS_TIMEOUT_REG, streams_timeout); 4441 OUTREG(MISC_TIMEOUT_REG, misc_timeout); 4442 } 4443 4444 OUTREG(SRC_BASE, 0); 4445 OUTREG(DEST_BASE, 0); 4446 OUTREG(CLIP_L_R, ((0) << 16) | pScrn->displayWidth); 4447 OUTREG(CLIP_T_B, ((0) << 16) | psav->ScissB); 4448 OUTREG(MONO_PAT_0, ~0); 4449 OUTREG(MONO_PAT_1, ~0); 4450 4451 SavageSetGBD(pScrn); 4452 4453} 4454 4455 4456 4457/* This function is used to debug, it prints out the contents of s3 regs */ 4458 4459void 4460SavagePrintRegs(ScrnInfoPtr pScrn) 4461{ 4462 SavagePtr psav = SAVPTR(pScrn); 4463 unsigned char i; 4464 int vgaCRIndex = 0x3d4; 4465 int vgaCRReg = 0x3d5; 4466 4467 ErrorF( "SR x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF" ); 4468 4469 for( i = 0; i < 0x70; i++ ) { 4470 if( !(i % 16) ) 4471 ErrorF( "\nSR%xx ", i >> 4 ); 4472 VGAOUT8( 0x3c4, i ); 4473 ErrorF( " %02x", VGAIN8(0x3c5) ); 4474 } 4475 4476 ErrorF( "\n\nCR x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF" ); 4477 4478 for( i = 0; i < 0xB7; i++ ) { 4479 if( !(i % 16) ) 4480 ErrorF( "\nCR%xx ", i >> 4 ); 4481 VGAOUT8( vgaCRIndex, i ); 4482 ErrorF( " %02x", VGAIN8(vgaCRReg) ); 4483 } 4484 4485 ErrorF("\n\n"); 4486} 4487 4488static void SavageDPMS(ScrnInfoPtr pScrn, int mode, int flags) 4489{ 4490 SavagePtr psav = SAVPTR(pScrn); 4491 unsigned char sr8 = 0x00, srd = 0x00; 4492 4493 TRACE(("SavageDPMS(%d,%x)\n", mode, flags)); 4494 4495 if (psav->DisplayType == MT_CRT) { 4496 VGAOUT8(0x3c4, 0x08); 4497 sr8 = VGAIN8(0x3c5); 4498 sr8 |= 0x06; 4499 VGAOUT8(0x3c5, sr8); 4500 4501 VGAOUT8(0x3c4, 0x0d); 4502 srd = VGAIN8(0x3c5); 4503 4504 srd &= 0x03; 4505 4506 switch (mode) { 4507 case DPMSModeOn: 4508 break; 4509 case DPMSModeStandby: 4510 srd |= 0x10; 4511 break; 4512 case DPMSModeSuspend: 4513 srd |= 0x40; 4514 break; 4515 case DPMSModeOff: 4516 srd |= 0x50; 4517 break; 4518 default: 4519 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid DPMS mode %d\n", mode); 4520 break; 4521 } 4522 4523 VGAOUT8(0x3c4, 0x0d); 4524 VGAOUT8(0x3c5, srd); 4525 } 4526 4527 if (psav->DisplayType == MT_LCD || psav->DisplayType == MT_DFP) { 4528 if (S3_MOBILE_TWISTER_SERIES(psav->Chipset) && psav->UseBIOS) { 4529 SavageSetPanelEnabled(psav, (mode == DPMSModeOn)); 4530 } else { 4531 switch (mode) { 4532 case DPMSModeOn: 4533 VGAOUT8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */ 4534 VGAOUT8(0x3c5, VGAIN8(0x3c5) | 0x10); 4535 break; 4536 case DPMSModeStandby: 4537 case DPMSModeSuspend: 4538 case DPMSModeOff: 4539 VGAOUT8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */ 4540 VGAOUT8(0x3c5, VGAIN8(0x3c5) & ~0x10); 4541 break; 4542 default: 4543 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid DPMS mode %d\n", mode); 4544 break; 4545 } 4546 } 4547 } 4548 4549 return; 4550} 4551 4552static void 4553SavageProbeDDC(ScrnInfoPtr pScrn, int index) 4554{ 4555 vbeInfoPtr pVbe; 4556 4557 if (xf86LoadSubModule(pScrn, "vbe")) { 4558 pVbe = VBEInit(NULL, index); 4559 ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 4560 vbeFree(pVbe); 4561 } 4562} 4563 4564static unsigned int 4565SavageDDC1Read(ScrnInfoPtr pScrn) 4566{ 4567 register unsigned char tmp; 4568 SavagePtr psav = SAVPTR(pScrn); 4569 4570 UnLockExtRegs(); 4571 4572 VerticalRetraceWait(); 4573 4574 InI2CREG(tmp,psav->I2CPort); 4575 4576 return ((unsigned int) (tmp & 0x08)); 4577} 4578 4579static Bool 4580SavageDDC1(ScrnInfoPtr pScrn) 4581{ 4582 SavagePtr psav = SAVPTR(pScrn); 4583 unsigned char byte; 4584 xf86MonPtr pMon; 4585 4586 UnLockExtRegs(); 4587 4588 /* initialize chipset */ 4589 InI2CREG(byte,psav->I2CPort); 4590 OutI2CREG(byte | 0x12,psav->I2CPort); 4591 4592 pMon = xf86DoEDID_DDC1(XF86_SCRN_ARG(pScrn),vgaHWddc1SetSpeedWeak(),SavageDDC1Read); 4593 if (!pMon) 4594 return FALSE; 4595 4596 xf86PrintEDID(pMon); 4597 4598 if (!psav->IgnoreEDID) 4599 xf86SetDDCproperties(pScrn,pMon); 4600 4601 /* undo initialization */ 4602 OutI2CREG(byte,psav->I2CPort); 4603 4604 return TRUE; 4605} 4606 4607static void 4608SavageGetTvMaxSize(SavagePtr psav) 4609{ 4610 if( psav->PAL ) { 4611 psav->TVSizeX = 800; 4612 psav->TVSizeY = 600; 4613 } 4614 else { 4615 psav->TVSizeX = 640; 4616 psav->TVSizeY = 480; 4617 } 4618} 4619 4620 4621static Bool 4622SavagePanningCheck(ScrnInfoPtr pScrn, DisplayModePtr pMode) 4623{ 4624 SavagePtr psav = SAVPTR(pScrn); 4625 psav->iResX = pMode->CrtcHDisplay; 4626 psav->iResY = pMode->CrtcVDisplay; 4627 4628 if ((psav->iResX < psav->PanelX || psav->iResY < psav->PanelY)) 4629 psav->FPExpansion = TRUE; 4630 else 4631 psav->FPExpansion = FALSE; 4632 4633 if( psav->iResX < pScrn->virtualX || psav->iResY < pScrn->virtualY ) 4634 return TRUE; 4635 else 4636 return FALSE; 4637} 4638 4639static void 4640SavageResetStreams(ScrnInfoPtr pScrn) 4641{ 4642 SavagePtr psav = SAVPTR(pScrn); 4643 unsigned char cr67; 4644 unsigned char cr69; 4645 4646 /* disable streams */ 4647 switch (psav->Chipset) { 4648 case S3_SAVAGE_MX: 4649 case S3_SUPERSAVAGE: 4650 OUTREG32(PRI_STREAM_STRIDE,0); 4651 OUTREG32(PRI_STREAM2_STRIDE, 0); 4652 OUTREG32(PRI_STREAM_FBUF_ADDR0,0x00000000); 4653 OUTREG32(PRI_STREAM_FBUF_ADDR1,0x00000000); 4654 OUTREG32(PRI_STREAM2_FBUF_ADDR0,0x00000000); 4655 OUTREG32(PRI_STREAM2_FBUF_ADDR1,0x00000000); 4656 OUTREG8(CRT_ADDRESS_REG, 0x67); 4657 cr67 = INREG8(CRT_DATA_REG); 4658 cr67 &= ~0x08; /* CR67[3] = 1 : Mem-mapped regs */ 4659 cr67 &= ~0x04; /* CR67[2] = 1 : enable stream 1 */ 4660 cr67 &= ~0x02; /* CR67[1] = 1 : enable stream 2 */ 4661 OUTREG8(CRT_DATA_REG, cr67); 4662 break; 4663 case S3_SAVAGE3D: 4664 case S3_SAVAGE4: 4665 case S3_TWISTER: 4666 case S3_PROSAVAGE: 4667 case S3_PROSAVAGEDDR: 4668 OUTREG32(PRI_STREAM_STRIDE,0); 4669 OUTREG32(PRI_STREAM_FBUF_ADDR0,0); 4670 OUTREG32(PRI_STREAM_FBUF_ADDR1,0); 4671 OUTREG8(CRT_ADDRESS_REG, 0x67); 4672 cr67 = INREG8(CRT_DATA_REG); 4673 cr67 &= ~0x0c; /* CR67[2] = 1 : enable stream 1 */ 4674 OUTREG8(CRT_DATA_REG, cr67); 4675 OUTREG8(CRT_ADDRESS_REG, 0x69); 4676 cr69 = INREG8(CRT_DATA_REG); 4677 cr69 &= ~0x80; /* CR69[0] = 1 : Mem-mapped regs */ 4678 OUTREG8(CRT_DATA_REG, cr69); 4679 break; 4680 case S3_SAVAGE2000: 4681 OUTREG32(PRI_STREAM_STRIDE,0); 4682 OUTREG32(PRI_STREAM_FBUF_ADDR0,0x00000000); 4683 OUTREG32(PRI_STREAM_FBUF_ADDR1,0x00000000); 4684 OUTREG8(CRT_ADDRESS_REG, 0x67); 4685 cr67 = INREG8(CRT_DATA_REG); 4686 cr67 &= ~0x08; /* CR67[3] = 1 : Mem-mapped regs */ 4687 cr67 &= ~0x04; /* CR67[2] = 1 : enable stream 1 */ 4688 cr67 &= ~0x02; /* CR67[1] = 1 : enable stream 2 */ 4689 OUTREG8(CRT_DATA_REG, cr67); 4690 break; 4691 default: 4692 break; 4693 } 4694 4695} 4696