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