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