s3v_driver.c revision ba85709e
1 2/* 3Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved. 4 5Permission is hereby granted, free of charge, to any person obtaining a copy of 6this software and associated documentation files (the "Software"), to deal in 7the Software without restriction, including without limitation the rights to 8use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9of the Software, and to permit persons to whom the Software is furnished to do 10so, subject to the following conditions: 11 12The above copyright notice and this permission notice shall be included in all 13copies or substantial portions of the Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- 17NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of the XFree86 Project shall not 23be used in advertising or otherwise to promote the sale, use or other dealings 24in this Software without prior written authorization from the XFree86 Project. 25*/ 26 27#ifdef HAVE_CONFIG_H 28#include "config.h" 29#endif 30 31#include <unistd.h> 32#include "xf86Resources.h" 33/* Needed by Resources Access Control (RAC) */ 34#include "xf86RAC.h" 35 36#include "xf86DDC.h" 37#include "vbe.h" 38 39/* Needed by the Shadow Framebuffer */ 40#include "shadowfb.h" 41 42/* 43 * s3v_driver.c 44 * Port to 4.0 design level 45 * 46 * S3 ViRGE driver 47 * 48 * 10/98 - 3/99 Kevin Brosius 49 * based largely on the SVGA ViRGE driver from 3.3.3x, 50 * Started 09/03/97 by S. Marineau 51 * 52 * 53 */ 54 55 56 /* Most xf86 commons are already in s3v.h */ 57#include "s3v.h" 58 59 60#include "globals.h" 61#define DPMS_SERVER 62#include <X11/extensions/dpms.h> 63 64#ifndef USE_INT10 65#define USE_INT10 0 66#endif 67 68/* 69 * Internals 70 */ 71static void S3VEnableMmio(ScrnInfoPtr pScrn); 72static void S3VDisableMmio(ScrnInfoPtr pScrn); 73 74/* 75 * Forward definitions for the functions that make up the driver. 76 */ 77 78/* Mandatory functions */ 79static const OptionInfoRec * S3VAvailableOptions(int chipid, int busid); 80static void S3VIdentify(int flags); 81static Bool S3VProbe(DriverPtr drv, int flags); 82static Bool S3VPreInit(ScrnInfoPtr pScrn, int flags); 83 84static Bool S3VEnterVT(int scrnIndex, int flags); 85static void S3VLeaveVT(int scrnIndex, int flags); 86static void S3VSave (ScrnInfoPtr pScrn); 87static void S3VWriteMode (ScrnInfoPtr pScrn, vgaRegPtr, S3VRegPtr); 88 89static void S3VSaveSTREAMS(ScrnInfoPtr pScrn, unsigned int *streams); 90static void S3VRestoreSTREAMS(ScrnInfoPtr pScrn, unsigned int *streams); 91static void S3VDisableSTREAMS(ScrnInfoPtr pScrn); 92static Bool S3VScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv); 93static int S3VInternalScreenInit( int scrnIndex, ScreenPtr pScreen); 94static void S3VPrintRegs(ScrnInfoPtr); 95static ModeStatus S3VValidMode(int index, DisplayModePtr mode, Bool verbose, int flags); 96 97static Bool S3VMapMem(ScrnInfoPtr pScrn); 98static void S3VUnmapMem(ScrnInfoPtr pScrn); 99static Bool S3VModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); 100static Bool S3VCloseScreen(int scrnIndex, ScreenPtr pScreen); 101static Bool S3VSaveScreen(ScreenPtr pScreen, int mode); 102static void S3VInitSTREAMS(ScrnInfoPtr pScrn, unsigned int *streams, DisplayModePtr mode); 103/* s3v.h - static void S3VAdjustFrame(int scrnIndex, int x, int y, int flags); */ 104/* s3v.h - static Bool S3VSwitchMode(int scrnIndex, DisplayModePtr mode, int flags); */ 105static void S3VLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies, LOCO *colors, VisualPtr pVisual); 106 107static void S3VDisplayPowerManagementSet(ScrnInfoPtr pScrn, 108 int PowerManagementMode, 109 int flags); 110static Bool S3Vddc1(int scrnIndex); 111static Bool S3Vddc2(int scrnIndex); 112 113static unsigned int S3Vddc1Read(ScrnInfoPtr pScrn); 114static void S3VProbeDDC(ScrnInfoPtr pScrn, int index); 115 116/* 117 * This is intentionally screen-independent. It indicates the binding 118 * choice made in the first PreInit. 119 */ 120static int pix24bpp = 0; 121 122#define S3VIRGE_NAME "S3VIRGE" 123#define S3VIRGE_DRIVER_NAME "s3virge" 124#define S3VIRGE_VERSION_NAME PACKAGE_VERSION 125#define S3VIRGE_VERSION_MAJOR PACKAGE_VERSION_MAJOR 126#define S3VIRGE_VERSION_MINOR PACKAGE_VERSION_MINOR 127#define S3VIRGE_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL 128#define S3VIRGE_DRIVER_VERSION ((S3VIRGE_VERSION_MAJOR << 24) | \ 129 (S3VIRGE_VERSION_MINOR << 16) | \ 130 S3VIRGE_PATCHLEVEL) 131 132/* 133 * This contains the functions needed by the server after loading the 134 * driver module. It must be supplied, and gets added the driver list by 135 * the Module Setup funtion in the dynamic case. In the static case a 136 * reference to this is compiled in, and this requires that the name of 137 * this DriverRec be an upper-case version of the driver name. 138 */ 139 140_X_EXPORT DriverRec S3VIRGE = 141{ 142 S3VIRGE_DRIVER_VERSION, 143 S3VIRGE_DRIVER_NAME, 144 S3VIdentify, 145 S3VProbe, 146 S3VAvailableOptions, 147 NULL, 148 0 149}; 150 151 152/* Supported chipsets */ 153static SymTabRec S3VChipsets[] = { 154 /* base (86C325) */ 155 { PCI_CHIP_VIRGE, "virge" }, 156 { PCI_CHIP_VIRGE, "86C325" }, 157 /* VX (86C988) */ 158 { PCI_CHIP_VIRGE_VX, "virge vx" }, 159 { PCI_CHIP_VIRGE_VX, "86C988" }, 160 /* DX (86C375) GX (86C385) */ 161 { PCI_CHIP_VIRGE_DXGX, "virge dx" }, 162 { PCI_CHIP_VIRGE_DXGX, "virge gx" }, 163 { PCI_CHIP_VIRGE_DXGX, "86C375" }, 164 { PCI_CHIP_VIRGE_DXGX, "86C385" }, 165 /* GX2 (86C357) */ 166 { PCI_CHIP_VIRGE_GX2, "virge gx2" }, 167 { PCI_CHIP_VIRGE_GX2, "86C357" }, 168 /* MX (86C260) */ 169 { PCI_CHIP_VIRGE_MX, "virge mx" }, 170 { PCI_CHIP_VIRGE_MX, "86C260" }, 171 /* MX+ (86C280) */ 172 { PCI_CHIP_VIRGE_MXP, "virge mx+" }, 173 { PCI_CHIP_VIRGE_MXP, "86C280" }, 174 /* Trio3D (86C365) */ 175 { PCI_CHIP_Trio3D, "trio 3d" }, 176 { PCI_CHIP_Trio3D, "86C365" }, 177 /* Trio3D/2x (86C362/86C368) */ 178 { PCI_CHIP_Trio3D_2X, "trio 3d/2x" }, 179 { PCI_CHIP_Trio3D_2X, "86C362" }, 180 { PCI_CHIP_Trio3D_2X, "86C368" }, 181 {-1, NULL } 182}; 183 184static PciChipsets S3VPciChipsets[] = { 185 /* numChipset, PciID, Resource */ 186 { PCI_CHIP_VIRGE, PCI_CHIP_VIRGE, RES_SHARED_VGA }, 187 { PCI_CHIP_VIRGE_VX, PCI_CHIP_VIRGE_VX, RES_SHARED_VGA }, 188 { PCI_CHIP_VIRGE_DXGX, PCI_CHIP_VIRGE_DXGX, RES_SHARED_VGA }, 189 { PCI_CHIP_VIRGE_GX2, PCI_CHIP_VIRGE_GX2, RES_SHARED_VGA }, 190 { PCI_CHIP_VIRGE_MX, PCI_CHIP_VIRGE_MX, RES_SHARED_VGA }, 191 { PCI_CHIP_VIRGE_MXP, PCI_CHIP_VIRGE_MXP, RES_SHARED_VGA }, 192 { PCI_CHIP_Trio3D, PCI_CHIP_Trio3D, RES_SHARED_VGA }, 193 { PCI_CHIP_Trio3D_2X, PCI_CHIP_Trio3D_2X, RES_SHARED_VGA }, 194 { -1, -1, RES_UNDEFINED } 195}; 196 197typedef enum { 198 OPTION_SLOW_EDODRAM, 199 OPTION_SLOW_DRAM, 200 OPTION_FAST_DRAM, 201 OPTION_FPM_VRAM, 202 OPTION_PCI_BURST, 203 OPTION_FIFO_CONSERV, 204 OPTION_FIFO_MODERATE, 205 OPTION_FIFO_AGGRESSIVE, 206 OPTION_PCI_RETRY, 207 OPTION_NOACCEL, 208 OPTION_EARLY_RAS_PRECHARGE, 209 OPTION_LATE_RAS_PRECHARGE, 210 OPTION_LCD_CENTER, 211 OPTION_LCDCLOCK, 212 OPTION_MCLK, 213 OPTION_REFCLK, 214 OPTION_SHOWCACHE, 215 OPTION_SWCURSOR, 216 OPTION_HWCURSOR, 217 OPTION_SHADOW_FB, 218 OPTION_ROTATE, 219 OPTION_FB_DRAW, 220 OPTION_MX_CR3A_FIX, 221 OPTION_XVIDEO 222} S3VOpts; 223 224static const OptionInfoRec S3VOptions[] = 225{ 226 /* int token, const char* name, OptionValueType type, 227 ValueUnion value, Bool found. 228 */ 229 { OPTION_SLOW_EDODRAM, "slow_edodram", OPTV_BOOLEAN, {0}, FALSE }, 230 { OPTION_SLOW_DRAM, "slow_dram", OPTV_BOOLEAN, {0}, FALSE }, 231 { OPTION_FAST_DRAM, "fast_dram", OPTV_BOOLEAN, {0}, FALSE }, 232 { OPTION_FPM_VRAM, "fpm_vram", OPTV_BOOLEAN, {0}, FALSE }, 233 { OPTION_PCI_BURST, "pci_burst", OPTV_BOOLEAN, {0}, FALSE }, 234 { OPTION_FIFO_CONSERV, "fifo_conservative", OPTV_BOOLEAN, {0}, FALSE }, 235 { OPTION_FIFO_MODERATE, "fifo_moderate", OPTV_BOOLEAN, {0}, FALSE }, 236 { OPTION_FIFO_AGGRESSIVE, "fifo_aggressive", OPTV_BOOLEAN, {0}, FALSE }, 237 { OPTION_PCI_RETRY, "pci_retry", OPTV_BOOLEAN, {0}, FALSE }, 238 { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 239 { OPTION_EARLY_RAS_PRECHARGE, "early_ras_precharge", OPTV_BOOLEAN, {0}, FALSE }, 240 { OPTION_LATE_RAS_PRECHARGE, "late_ras_precharge", OPTV_BOOLEAN, {0}, FALSE }, 241 { OPTION_LCD_CENTER, "lcd_center", OPTV_BOOLEAN, {0}, FALSE }, 242 { OPTION_LCDCLOCK, "set_lcdclk", OPTV_INTEGER, {0}, FALSE }, 243 { OPTION_MCLK, "set_mclk", OPTV_FREQ, {0}, FALSE }, 244 { OPTION_REFCLK, "set_refclk", OPTV_FREQ, {0}, FALSE }, 245 { OPTION_SHOWCACHE, "show_cache", OPTV_BOOLEAN, {0}, FALSE }, 246 { OPTION_HWCURSOR, "HWCursor", OPTV_BOOLEAN, {0}, FALSE }, 247 { OPTION_SWCURSOR, "SWCursor", OPTV_BOOLEAN, {0}, FALSE }, 248 { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, 249 { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, 250 { OPTION_MX_CR3A_FIX, "mxcr3afix", OPTV_BOOLEAN, {0}, FALSE }, 251 { OPTION_XVIDEO, "XVideo", OPTV_BOOLEAN, {0}, FALSE }, 252 {-1, NULL, OPTV_NONE, {0}, FALSE} 253}; 254 255 256/* 257 * Lists of symbols that may/may not be required by this driver. 258 * This allows the loader to know which ones to issue warnings for. 259 * 260 * Note that vgahwSymbols and xaaSymbols are referenced outside the 261 * XFree86LOADER define in later code, so are defined outside of that 262 * define here also. 263 */ 264 265static const char *vgahwSymbols[] = { 266 "vgaHWBlankScreen", 267 "vgaHWCopyReg", 268 "vgaHWGetHWRec", 269 "vgaHWGetIOBase", 270 "vgaHWGetIndex", 271 "vgaHWInit", 272 "vgaHWLock", 273 "vgaHWMapMem", 274 "vgaHWProtect", 275 "vgaHWRestore", 276 "vgaHWSave", 277 "vgaHWSaveScreen", 278 "vgaHWSetMmioFuncs", 279 "vgaHWSetStdFuncs", 280 "vgaHWUnmapMem", 281 "vgaHWddc1SetSpeedWeak", 282 /* not used by ViRGE (at the moment :( ) */ 283 /* 284 "vgaHWUnlock", 285 "vgaHWFreeHWRec", 286 */ 287 NULL 288}; 289 290static const char *xaaSymbols[] = { 291 "XAAGetCopyROP", 292 "XAAGetCopyROP_PM", 293 "XAADestroyInfoRec", 294 "XAACreateInfoRec", 295 "XAAHelpPatternROP", 296 "XAAHelpSolidROP", 297 "XAAInit", 298 NULL 299}; 300 301static const char *ramdacSymbols[] = { 302 "xf86CreateCursorInfoRec", 303 "xf86InitCursor", 304#if 0 305 "xf86DestroyCursorInfoRec", 306#endif 307 NULL 308}; 309 310static const char *ddcSymbols[] = { 311 "xf86PrintEDID", 312 "xf86DoEDID_DDC1", 313 "xf86DoEDID_DDC2", 314 "xf86SetDDCproperties", 315 NULL 316}; 317 318static const char *i2cSymbols[] = { 319 "xf86CreateI2CBusRec", 320 "xf86I2CBusInit", 321 NULL 322}; 323 324static const char *shadowSymbols[] = { 325 "ShadowFBInit", 326 NULL 327}; 328 329static const char *vbeSymbols[] = { 330 "VBEInit", 331 "vbeDoEDID", 332 "vbeFree", 333 NULL 334}; 335 336static const char *fbSymbols[] = { 337 "fbPictureInit", 338 "fbScreenInit", 339 NULL 340}; 341 342#if USE_INT10 343static const char *int10Symbols[] = { 344 "xf86InitInt10", 345 "xf86FreeInt10", 346 NULL 347}; 348#endif 349 350#ifdef XFree86LOADER 351 352static MODULESETUPPROTO(s3virgeSetup); 353 354static XF86ModuleVersionInfo S3VVersRec = 355{ 356 "s3virge", 357 MODULEVENDORSTRING, 358 MODINFOSTRING1, 359 MODINFOSTRING2, 360 XORG_VERSION_CURRENT, 361 S3VIRGE_VERSION_MAJOR, S3VIRGE_VERSION_MINOR, S3VIRGE_PATCHLEVEL, 362 ABI_CLASS_VIDEODRV, /* This is a video driver */ 363 ABI_VIDEODRV_VERSION, 364 MOD_CLASS_VIDEODRV, 365 {0, 0, 0, 0} 366}; 367 368 369/* 370 * This is the module init data for XFree86 modules. 371 * 372 * Its name has to be the driver name followed by ModuleData. 373 */ 374_X_EXPORT XF86ModuleData s3virgeModuleData = { 375 &S3VVersRec, 376 s3virgeSetup, 377 NULL 378}; 379 380static pointer 381s3virgeSetup(pointer module, pointer opts, int *errmaj, int *errmin) 382{ 383 static Bool setupDone = FALSE; 384 385 if (!setupDone) { 386 setupDone = TRUE; 387 xf86AddDriver(&S3VIRGE, module, 0); 388 389 /* 390 * Modules that this driver always requires can be loaded here 391 * by calling LoadSubModule(). 392 */ 393 394 /* 395 * Tell the loader about symbols from other modules that this module 396 * might refer to. 397 */ 398 LoaderRefSymLists(vgahwSymbols, xaaSymbols, ramdacSymbols, 399 ddcSymbols, i2cSymbols, 400#if USE_INT10 401 int10Symbols, 402#endif 403 vbeSymbols, shadowSymbols, fbSymbols, NULL); 404 405 /* 406 * The return value must be non-NULL on success even though there 407 * is no TearDownProc. 408 */ 409 return (pointer) 1; 410 } else { 411 if (errmaj) 412 *errmaj = LDR_ONCEONLY; 413 return NULL; 414 } 415} 416 417#endif /* XFree86LOADER */ 418 419 420static unsigned char *find_bios_string(S3VPtr ps3v, int BIOSbase, char *match1, char *match2) 421{ 422#define BIOS_BSIZE 1024 423#define BIOS_BASE 0xc0000 424 425 static unsigned char bios[BIOS_BSIZE]; 426 static int init=0; 427 int i,j,l1,l2; 428 429 if (!init) { 430 init = 1; 431#ifndef XSERVER_LIBPCIACCESS 432 if (xf86ReadDomainMemory(ps3v->PciTag, BIOSbase, BIOS_BSIZE, bios) != BIOS_BSIZE) 433 return NULL; 434#else 435 if (pci_device_read_rom(ps3v->PciInfo, bios)) 436 return NULL; 437#endif 438 if ((bios[0] != 0x55) || (bios[1] != 0xaa)) 439 return NULL; 440 } 441 if (match1 == NULL) 442 return NULL; 443 444 l1 = strlen(match1); 445 if (match2 != NULL) 446 l2 = strlen(match2); 447 else /* for compiler-warnings */ 448 l2 = 0; 449 450 for (i=0; i<BIOS_BSIZE-l1; i++) 451 if (bios[i] == match1[0] && !memcmp(&bios[i],match1,l1)) { 452 if (match2 == NULL) 453 return &bios[i+l1]; 454 else 455 for(j=i+l1; (j<BIOS_BSIZE-l2) && bios[j]; j++) 456 if (bios[j] == match2[0] && !memcmp(&bios[j],match2,l2)) 457 return &bios[j+l2]; 458 } 459 460 return NULL; 461} 462 463 464static Bool 465S3VGetRec(ScrnInfoPtr pScrn) 466{ 467 PVERB5(" S3VGetRec\n"); 468 /* 469 * Allocate an 'Chip'Rec, and hook it into pScrn->driverPrivate. 470 * pScrn->driverPrivate is initialised to NULL, so we can check if 471 * the allocation has already been done. 472 */ 473 if (pScrn->driverPrivate != NULL) 474 return TRUE; 475 476 pScrn->driverPrivate = xnfcalloc(sizeof(S3VRec), 1); 477 /* Initialise it here when needed (or possible) */ 478 479 return TRUE; 480} 481 482static void 483S3VFreeRec(ScrnInfoPtr pScrn) 484{ 485 PVERB5(" S3VFreeRec\n"); 486 if (pScrn->driverPrivate == NULL) 487 return; 488 xfree(pScrn->driverPrivate); 489 pScrn->driverPrivate = NULL; 490} 491 492static const OptionInfoRec * 493S3VAvailableOptions(int chipid, int busid) 494{ 495 return S3VOptions; 496} 497 498static void 499S3VIdentify(int flags) 500{ 501 PVERB5(" S3VIdentify\n"); 502 xf86PrintChipsets(S3VIRGE_NAME, 503 "driver (version " S3VIRGE_VERSION_NAME ") for S3 ViRGE chipsets", 504 S3VChipsets); 505} 506 507 508static Bool 509S3VProbe(DriverPtr drv, int flags) 510{ 511 int i; 512 GDevPtr *devSections; 513 int *usedChips; 514 int numDevSections; 515 int numUsed; 516 Bool foundScreen = FALSE; 517 518 PVERB5(" S3VProbe begin\n"); 519 520 if ((numDevSections = xf86MatchDevice(S3VIRGE_DRIVER_NAME, 521 &devSections)) <= 0) { 522 /* 523 * There's no matching device section in the config file, so quit 524 * now. 525 */ 526 return FALSE; 527 } 528 529#ifndef XSERVER_LIBPCIACCESS 530 if (xf86GetPciVideoInfo() == NULL) { 531 return FALSE; 532 } 533#endif 534 535 numUsed = xf86MatchPciInstances(S3VIRGE_NAME, PCI_S3_VENDOR_ID, 536 S3VChipsets, S3VPciChipsets, devSections, 537 numDevSections, drv, &usedChips); 538 539 /* Free it since we don't need that list after this */ 540 xfree(devSections); 541 if (numUsed <= 0) 542 return FALSE; 543 544 if (flags & PROBE_DETECT) 545 foundScreen = TRUE; 546 else for (i = 0; i < numUsed; i++) { 547 /* Allocate a ScrnInfoRec and claim the slot */ 548 ScrnInfoPtr pScrn = NULL; 549 if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i], 550 S3VPciChipsets,NULL,NULL, NULL, 551 NULL,NULL))) { 552 /* Fill in what we can of the ScrnInfoRec */ 553 pScrn->driverVersion = S3VIRGE_DRIVER_VERSION; 554 pScrn->driverName = S3VIRGE_DRIVER_NAME; 555 pScrn->name = S3VIRGE_NAME; 556 pScrn->Probe = S3VProbe; 557 pScrn->PreInit = S3VPreInit; 558 pScrn->ScreenInit = S3VScreenInit; 559 pScrn->SwitchMode = S3VSwitchMode; 560 pScrn->AdjustFrame = S3VAdjustFrame; 561 pScrn->EnterVT = S3VEnterVT; 562 pScrn->LeaveVT = S3VLeaveVT; 563 pScrn->FreeScreen = NULL; /*S3VFreeScreen;*/ 564 pScrn->ValidMode = S3VValidMode; 565 foundScreen = TRUE; 566 } 567 } 568 xfree(usedChips); 569 PVERB5(" S3VProbe end\n"); 570 return foundScreen; 571} 572 573 574/* Mandatory */ 575static Bool 576S3VPreInit(ScrnInfoPtr pScrn, int flags) 577{ 578 EntityInfoPtr pEnt; 579 S3VPtr ps3v; 580 MessageType from; 581 int i; 582 double real; 583 ClockRangePtr clockRanges; 584 char *mod = NULL; 585 const char *reqSym = NULL; 586 char *s; 587 588 unsigned char config1, config2, m, n, n1, n2, cr66 = 0; 589 int mclk; 590 591 vgaHWPtr hwp; 592 int vgaCRIndex, vgaCRReg, vgaIOBase; 593 594 PVERB5(" S3VPreInit 1\n"); 595 596 if (flags & PROBE_DETECT) { 597 S3VProbeDDC( pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index ); 598 return TRUE; 599 } 600 601 /* 602 * Note: This function is only called once at server startup, and 603 * not at the start of each server generation. This means that 604 * only things that are persistent across server generations can 605 * be initialised here. xf86Screens[] is (pScrn is a pointer to one 606 * of these). Privates allocated using xf86AllocateScrnInfoPrivateIndex() 607 * are too, and should be used for data that must persist across 608 * server generations. 609 * 610 * Per-generation data should be allocated with 611 * AllocateScreenPrivateIndex() from the ScreenInit() function. 612 */ 613 614 /* The vgahw module should be loaded here when needed */ 615 616 if (!xf86LoadSubModule(pScrn, "vgahw")) 617 return FALSE; 618 619 xf86LoaderReqSymLists(vgahwSymbols, NULL); 620 621 /* 622 * Allocate a vgaHWRec 623 */ 624 if (!vgaHWGetHWRec(pScrn)) 625 return FALSE; 626 627 628 /* Set pScrn->monitor */ 629 pScrn->monitor = pScrn->confScreen->monitor; 630 631 /* 632 * The first thing we should figure out is the depth, bpp, etc. 633 * We support both 24bpp and 32bpp layouts, so indicate that. 634 */ 635 if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb | 636 SupportConvert32to24 | PreferConvert32to24)) { 637 return FALSE; 638 } else { 639 /* Check that the returned depth is one we support */ 640 switch (pScrn->depth) { 641 case 8: 642 case 15: 643 case 16: 644 case 24: 645 /* OK */ 646 break; 647 default: 648 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 649 "Given depth (%d) is not supported by this driver\n", 650 pScrn->depth); 651 return FALSE; 652 } 653 } 654 xf86PrintDepthBpp(pScrn); 655 656 /* Get the depth24 pixmap format */ 657 if (pScrn->depth == 24 && pix24bpp == 0) 658 pix24bpp = xf86GetBppFromDepth(pScrn, 24); 659 660 /* 661 * This must happen after pScrn->display has been set because 662 * xf86SetWeight references it. 663 */ 664 if (pScrn->depth > 8) { 665 /* The defaults are OK for us */ 666 rgb zeros = {0, 0, 0}; 667 668 if (!xf86SetWeight(pScrn, zeros, zeros)) { 669 return FALSE; 670 } else { 671 /* XXX check that weight returned is supported */ 672 ; 673 } 674 } 675 676 if (!xf86SetDefaultVisual(pScrn, -1)) { 677 return FALSE; 678 } else { /* editme - from MGA, does ViRGE? */ 679 /* We don't currently support DirectColor at > 8bpp */ 680 if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { 681 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual" 682 " (%s) is not supported at depth %d\n", 683 xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); 684 return FALSE; 685 } 686 } 687 688 /* We use a programmable clock */ 689 pScrn->progClock = TRUE; 690 691 /* Allocate the S3VRec driverPrivate */ 692 if (!S3VGetRec(pScrn)) { 693 return FALSE; 694 } 695 ps3v = S3VPTR(pScrn); 696 697 /* Collect all of the relevant option flags (fill in pScrn->options) */ 698 xf86CollectOptions(pScrn, NULL); 699 700 /* Set the bits per RGB for 8bpp mode */ 701 if (pScrn->depth == 8) { 702 /* ViRGE supports 6 RGB bits in depth 8 */ 703 /* modes (with 256 entry LUT) */ 704 pScrn->rgbBits = 6; 705 } 706 707 /* Process the options */ 708 if (!(ps3v->Options = xalloc(sizeof(S3VOptions)))) 709 return FALSE; 710 memcpy(ps3v->Options, S3VOptions, sizeof(S3VOptions)); 711 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ps3v->Options); 712 713 714 if (xf86ReturnOptValBool(ps3v->Options, OPTION_PCI_BURST, FALSE)) { 715 ps3v->pci_burst = TRUE; 716 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: pci_burst - PCI burst read enabled\n"); 717 } else 718 ps3v->pci_burst = FALSE; 719 /* default */ 720 ps3v->NoPCIRetry = 1; 721 /* Set option */ 722 if (xf86ReturnOptValBool(ps3v->Options, OPTION_PCI_RETRY, FALSE)) { 723 if (xf86ReturnOptValBool(ps3v->Options, OPTION_PCI_BURST, FALSE)) { 724 ps3v->NoPCIRetry = 0; 725 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: pci_retry\n"); 726 } 727 else { 728 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 729 "\"pci_retry\" option requires \"pci_burst\".\n"); 730 } 731 } 732 if (xf86IsOptionSet(ps3v->Options, OPTION_FIFO_CONSERV)) { 733 ps3v->fifo_conservative = TRUE; 734 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: fifo_conservative set\n"); 735 } else 736 ps3v->fifo_conservative = FALSE; 737 738 if (xf86IsOptionSet(ps3v->Options, OPTION_FIFO_MODERATE)) { 739 ps3v->fifo_moderate = TRUE; 740 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: fifo_moderate set\n"); 741 } else 742 ps3v->fifo_moderate = FALSE; 743 744 if (xf86IsOptionSet(ps3v->Options, OPTION_FIFO_AGGRESSIVE)) { 745 ps3v->fifo_aggressive = TRUE; 746 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: fifo_aggressive set\n"); 747 } else 748 ps3v->fifo_aggressive = FALSE; 749 750 if (xf86IsOptionSet(ps3v->Options, OPTION_SLOW_EDODRAM)) { 751 ps3v->slow_edodram = TRUE; 752 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: slow_edodram set\n"); 753 } else 754 ps3v->slow_edodram = FALSE; 755 756 if (xf86IsOptionSet(ps3v->Options, OPTION_SLOW_DRAM)) { 757 ps3v->slow_dram = TRUE; 758 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: slow_dram set\n"); 759 } else 760 ps3v->slow_dram = FALSE; 761 762 if (xf86IsOptionSet(ps3v->Options, OPTION_FAST_DRAM)) { 763 ps3v->fast_dram = TRUE; 764 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: fast_dram set\n"); 765 } else 766 ps3v->fast_dram = FALSE; 767 768 if (xf86IsOptionSet(ps3v->Options, OPTION_FPM_VRAM)) { 769 ps3v->fpm_vram = TRUE; 770 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: fpm_vram set\n"); 771 } else 772 ps3v->fpm_vram = FALSE; 773 774 if (xf86ReturnOptValBool(ps3v->Options, OPTION_NOACCEL, FALSE)) { 775 ps3v->NoAccel = TRUE; 776 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: NoAccel - Acceleration disabled\n"); 777 } else 778 ps3v->NoAccel = FALSE; 779 780 if (xf86ReturnOptValBool(ps3v->Options, OPTION_EARLY_RAS_PRECHARGE, FALSE)) { 781 ps3v->early_ras_precharge = TRUE; 782 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: early_ras_precharge set\n"); 783 } else 784 ps3v->early_ras_precharge = FALSE; 785 786 if (xf86ReturnOptValBool(ps3v->Options, OPTION_LATE_RAS_PRECHARGE, FALSE)) { 787 ps3v->late_ras_precharge = TRUE; 788 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: late_ras_precharge set\n"); 789 } else 790 ps3v->late_ras_precharge = FALSE; 791 792 if (xf86ReturnOptValBool(ps3v->Options, OPTION_LCD_CENTER, FALSE)) { 793 ps3v->lcd_center = TRUE; 794 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: lcd_center set\n"); 795 } else 796 ps3v->lcd_center = FALSE; 797 798 if (xf86ReturnOptValBool(ps3v->Options, OPTION_SHOWCACHE, FALSE)) { 799 ps3v->ShowCache = TRUE; 800 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: show_cache set\n"); 801 } else 802 ps3v->ShowCache = FALSE; 803 804 if (xf86GetOptValInteger(ps3v->Options, OPTION_LCDCLOCK, &ps3v->LCDClk)) { 805 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: lcd_setclk set to %1.3f Mhz\n", 806 ps3v->LCDClk / 1000.0 ); 807 } else 808 ps3v->LCDClk = 0; 809 810 if (xf86GetOptValFreq(ps3v->Options, OPTION_MCLK, OPTUNITS_MHZ, &real)) { 811 ps3v->MCLK = (int)(real * 1000.0); 812 if (ps3v->MCLK <= 100000) { 813 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: set_mclk set to %1.3f Mhz\n", 814 ps3v->MCLK / 1000.0 ); 815 } else { 816 xf86DrvMsg(pScrn->scrnIndex, X_WARNING 817 , "Memory Clock value of %1.3f MHz is larger than limit of 100 MHz\n" 818 , ps3v->MCLK/1000.0); 819 ps3v->MCLK = 0; 820 } 821 } else 822 ps3v->MCLK = 0; 823 824 if (xf86GetOptValFreq(ps3v->Options, OPTION_REFCLK, OPTUNITS_MHZ, &real)) { 825 ps3v->REFCLK = (int)(real * 1000.0); 826 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: set_refclk set to %1.3f Mhz\n", 827 ps3v->REFCLK / 1000.0 ); 828 } else 829 ps3v->REFCLK = 0; 830 831 from = X_DEFAULT; 832 ps3v->hwcursor = TRUE; 833 if (xf86GetOptValBool(ps3v->Options, OPTION_HWCURSOR, &ps3v->hwcursor)) 834 from = X_CONFIG; 835 if (xf86ReturnOptValBool(ps3v->Options, OPTION_SWCURSOR, FALSE)) { 836 ps3v->hwcursor = FALSE; 837 from = X_CONFIG; 838 } 839 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s Cursor\n", 840 ps3v->hwcursor ? "HW" : "SW"); 841 842 if (xf86GetOptValBool(ps3v->Options, OPTION_SHADOW_FB,&ps3v->shadowFB)) 843 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowFB %s.\n", 844 ps3v->shadowFB ? "enabled" : "disabled"); 845 846 if ((s = xf86GetOptValString(ps3v->Options, OPTION_ROTATE))) { 847 if(!xf86NameCmp(s, "CW")) { 848 /* accel is disabled below for shadowFB */ 849 ps3v->shadowFB = TRUE; 850 ps3v->rotate = 1; 851 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 852 "Rotating screen clockwise - acceleration disabled\n"); 853 } else if(!xf86NameCmp(s, "CCW")) { 854 ps3v->shadowFB = TRUE; 855 ps3v->rotate = -1; 856 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen" 857 "counter clockwise - acceleration disabled\n"); 858 } else { 859 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid" 860 "value for Option \"Rotate\"\n", s); 861 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 862 "Valid options are \"CW\" or \"CCW\"\n"); 863 } 864 } 865 866 if (ps3v->shadowFB && !ps3v->NoAccel) { 867 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 868 "HW acceleration not supported with \"shadowFB\".\n"); 869 ps3v->NoAccel = TRUE; 870 } 871 872 if (ps3v->rotate && ps3v->hwcursor) { 873 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 874 "HW cursor not supported with \"rotate\".\n"); 875 ps3v->hwcursor = FALSE; 876 } 877 878 if (xf86IsOptionSet(ps3v->Options, OPTION_MX_CR3A_FIX)) 879 { 880 if (xf86GetOptValBool(ps3v->Options, OPTION_MX_CR3A_FIX ,&ps3v->mx_cr3a_fix)) 881 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "%s mx_cr3a_fix.\n", 882 ps3v->mx_cr3a_fix ? "Enabling (default)" : "Disabling"); 883 } 884 else 885 { 886 ps3v->mx_cr3a_fix = TRUE; 887 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "mx_cr3a_fix.\n"); 888 } 889 890 /* Find the PCI slot for this screen */ 891 /* 892 * XXX Ignoring the Type list for now. It might be needed when 893 * multiple cards are supported. 894 */ 895 if (pScrn->numEntities > 1) { 896 S3VFreeRec(pScrn); 897 return FALSE; 898 } 899 900 pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 901 902 if (pEnt->resources) { 903 xfree(pEnt); 904 S3VFreeRec(pScrn); 905 return FALSE; 906 } 907 908#if USE_INT10 909 if (xf86LoadSubModule(pScrn, "int10")) { 910 xf86Int10InfoPtr pInt; 911 xf86LoaderReqSymLists(int10Symbols, NULL); 912#if 1 913 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n"); 914 pInt = xf86InitInt10(pEnt->index); 915 xf86FreeInt10(pInt); 916#endif 917 } 918#endif 919 if (xf86LoadSubModule(pScrn, "vbe")) { 920 xf86LoaderReqSymLists(vbeSymbols, NULL); 921 ps3v->pVbe = VBEInit(NULL,pEnt->index); 922 } 923 924 ps3v->PciInfo = xf86GetPciInfoForEntity(pEnt->index); 925 xf86RegisterResources(pEnt->index,NULL,ResNone); 926 xf86SetOperatingState(resVgaIo, pEnt->index, ResUnusedOpr); 927 xf86SetOperatingState(resVgaMem, pEnt->index, ResDisableOpr); 928 929 /* 930 * Set the Chipset and ChipRev, allowing config file entries to 931 * override. 932 */ 933 if (pEnt->device->chipset && *pEnt->device->chipset) { 934 pScrn->chipset = pEnt->device->chipset; 935 ps3v->Chipset = xf86StringToToken(S3VChipsets, pScrn->chipset); 936 from = X_CONFIG; 937 } else if (pEnt->device->chipID >= 0) { 938 ps3v->Chipset = pEnt->device->chipID; 939 pScrn->chipset = (char *)xf86TokenToString(S3VChipsets, ps3v->Chipset); 940 from = X_CONFIG; 941 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", 942 ps3v->Chipset); 943 } else { 944 from = X_PROBED; 945 ps3v->Chipset = PCI_DEV_DEVICE_ID(ps3v->PciInfo); 946 pScrn->chipset = (char *)xf86TokenToString(S3VChipsets, ps3v->Chipset); 947 } 948 949 if (pEnt->device->chipRev >= 0) { 950 ps3v->ChipRev = pEnt->device->chipRev; 951 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 952 ps3v->ChipRev); 953 } else { 954 ps3v->ChipRev = PCI_DEV_REVISION(ps3v->PciInfo); 955 } 956 xfree(pEnt); 957 958 /* 959 * This shouldn't happen because such problems should be caught in 960 * S3VProbe(), but check it just in case. 961 */ 962 if (pScrn->chipset == NULL) { 963 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 964 "ChipID 0x%04X is not recognised\n", ps3v->Chipset); 965 vbeFree(ps3v->pVbe); 966 ps3v->pVbe = NULL; 967 return FALSE; 968 } 969 if (ps3v->Chipset < 0) { 970 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 971 "Chipset \"%s\" is not recognised\n", pScrn->chipset); 972 vbeFree(ps3v->pVbe); 973 ps3v->pVbe = NULL; 974 return FALSE; 975 } 976 977 xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset); 978 979#ifndef XSERVER_LIBPCIACCESS 980 ps3v->PciTag = pciTag(ps3v->PciInfo->bus, ps3v->PciInfo->device, 981 ps3v->PciInfo->func); 982#endif 983 984 /* Handle XVideo after we know chipset, so we can give an */ 985 /* intelligent comment about support */ 986 if (xf86IsOptionSet(ps3v->Options, OPTION_XVIDEO)) 987 { 988 if(S3VQueryXvCapable(pScrn)) 989 { 990 if (xf86GetOptValBool(ps3v->Options, OPTION_XVIDEO ,&ps3v->XVideo)) 991 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "%s XVideo.\n", 992 ps3v->XVideo ? "Enabling (default)" : "Disabling"); 993 } 994 else 995 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "XVideo not supported.\n"); 996 } 997 else 998 { 999 ps3v->XVideo = S3VQueryXvCapable(pScrn); 1000 if(ps3v->XVideo) 1001 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "XVideo supported.\n"); 1002 else 1003 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "XVideo not supported.\n"); 1004 } 1005 1006 1007 S3VMapMem(pScrn); 1008 hwp = VGAHWPTR(pScrn); 1009 vgaIOBase = hwp->IOBase; 1010 vgaCRIndex = vgaIOBase + 4; 1011 vgaCRReg = vgaIOBase + 5; 1012 1013 xf86ErrorFVerb(VERBLEV, 1014 " S3VPreInit vgaCRIndex=%x, vgaIOBase=%x, MMIOBase=%p\n", 1015 vgaCRIndex, vgaIOBase, hwp->MMIOBase ); 1016 1017 1018#if 0 /* Not needed in 4.0 flavors */ 1019 /* Unlock sys regs */ 1020 VGAOUT8(vgaCRIndex, 0x38); 1021 VGAOUT8(vgaCRReg, 0x48); 1022#endif 1023 1024 /* Next go on to detect amount of installed ram */ 1025 1026 VGAOUT8(vgaCRIndex, 0x36); /* for register CR36 (CONFG_REG1),*/ 1027 config1 = VGAIN8(vgaCRReg); /* get amount of vram installed */ 1028 1029 VGAOUT8(vgaCRIndex, 0x37); /* for register CR37 (CONFG_REG2),*/ 1030 config2 = VGAIN8(vgaCRReg); /* get amount of off-screen ram */ 1031 1032 if (xf86LoadSubModule(pScrn, "ddc")) { 1033 xf86MonPtr pMon = NULL; 1034 1035 xf86LoaderReqSymLists(ddcSymbols, NULL); 1036 if ((ps3v->pVbe) 1037 && ((pMon = xf86PrintEDID(vbeDoEDID(ps3v->pVbe, NULL))) != NULL)) 1038 xf86SetDDCproperties(pScrn,pMon); 1039 else if (!S3Vddc1(pScrn->scrnIndex)) { 1040 S3Vddc2(pScrn->scrnIndex); 1041 } 1042 } 1043 if (ps3v->pVbe) { 1044 vbeFree(ps3v->pVbe); 1045 ps3v->pVbe = NULL; 1046 } 1047 1048 /* 1049 * If the driver can do gamma correction, it should call xf86SetGamma() 1050 * here. (from MGA, no ViRGE gamma support yet, but needed for 1051 * xf86HandleColormaps support.) 1052 */ 1053 { 1054 Gamma zeros = {0.0, 0.0, 0.0}; 1055 1056 if (!xf86SetGamma(pScrn, zeros)) { 1057 return FALSE; 1058 } 1059 } 1060 1061 /* And compute the amount of video memory and offscreen memory */ 1062 ps3v->MemOffScreen = 0; 1063 1064 if (!pScrn->videoRam) { 1065 if (ps3v->Chipset == S3_ViRGE_VX) { 1066 switch((config2 & 0x60) >> 5) { 1067 case 1: 1068 ps3v->MemOffScreen = 4 * 1024; 1069 break; 1070 case 2: 1071 ps3v->MemOffScreen = 2 * 1024; 1072 break; 1073 } 1074 switch ((config1 & 0x60) >> 5) { 1075 case 0: 1076 ps3v->videoRamKbytes = 2 * 1024; 1077 break; 1078 case 1: 1079 ps3v->videoRamKbytes = 4 * 1024; 1080 break; 1081 case 2: 1082 ps3v->videoRamKbytes = 6 * 1024; 1083 break; 1084 case 3: 1085 ps3v->videoRamKbytes = 8 * 1024; 1086 break; 1087 } 1088 ps3v->videoRamKbytes -= ps3v->MemOffScreen; 1089 } 1090 else if (S3_TRIO_3D_2X_SERIES(ps3v->Chipset)) { 1091 switch((config1 & 0xE0) >> 5) { 1092 case 0: /* 8MB -- only 4MB usable for display/cursor */ 1093 ps3v->videoRamKbytes = 4 * 1024; 1094 ps3v->MemOffScreen = 4 * 1024; 1095 break; 1096 case 1: /* 32 bit interface -- yuck */ 1097 xf86ErrorFVerb(VERBLEV, 1098 " found 32 bit interface for video memory -- yuck:(\n"); 1099 case 2: 1100 ps3v->videoRamKbytes = 4 * 1024; 1101 break; 1102 case 6: 1103 ps3v->videoRamKbytes = 2 * 1024; 1104 break; 1105 } 1106 } 1107 else if (S3_TRIO_3D_SERIES(ps3v->Chipset)) { 1108 switch((config1 & 0xE0) >> 5) { 1109 case 0: 1110 case 2: 1111 ps3v->videoRamKbytes = 4 * 1024; 1112 break; 1113 case 4: 1114 ps3v->videoRamKbytes = 2 * 1024; 1115 break; 1116 } 1117 } 1118 else if (S3_ViRGE_GX2_SERIES(ps3v->Chipset) || S3_ViRGE_MX_SERIES(ps3v->Chipset)) { 1119 switch((config1 & 0xC0) >> 6) { 1120 case 1: 1121 ps3v->videoRamKbytes = 4 * 1024; 1122 break; 1123 case 3: 1124 ps3v->videoRamKbytes = 2 * 1024; 1125 break; 1126 } 1127 } 1128 else { 1129 switch((config1 & 0xE0) >> 5) { 1130 case 0: 1131 ps3v->videoRamKbytes = 4 * 1024; 1132 break; 1133 case 4: 1134 ps3v->videoRamKbytes = 2 * 1024; 1135 break; 1136 case 6: 1137 ps3v->videoRamKbytes = 1 * 1024; 1138 break; 1139 } 1140 } 1141 /* And save a byte value also */ 1142 ps3v->videoRambytes = ps3v->videoRamKbytes * 1024; 1143 /* Make sure the screen also */ 1144 /* has correct videoRam setting */ 1145 pScrn->videoRam = ps3v->videoRamKbytes; 1146 1147 if (ps3v->MemOffScreen) 1148 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1149 "videoram: %dk (plus %dk off-screen)\n", 1150 ps3v->videoRamKbytes, ps3v->MemOffScreen); 1151 else 1152 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "videoram: %dk\n", 1153 ps3v->videoRamKbytes); 1154 } else { 1155 /* Note: if ram is not probed then */ 1156 /* ps3v->videoRamKbytes will not be init'd */ 1157 /* should we? can do it here... */ 1158 1159 1160 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "videoram: %dk\n", 1161 ps3v->videoRamKbytes); 1162 } 1163 1164 /* reset S3 graphics engine to avoid memory corruption */ 1165 if (ps3v->Chipset != S3_ViRGE_VX) { 1166 VGAOUT8(vgaCRIndex, 0x66); 1167 cr66 = VGAIN8(vgaCRReg); 1168 VGAOUT8(vgaCRReg, cr66 | 0x02); 1169 usleep(10000); /* wait a little bit... */ 1170 } 1171 1172 /* 1173 * There was a lot of plainly wrong code here. pScrn->clock is just a list 1174 * of supported _dotclocks_ used when you don't have a programmable clock. 1175 * 1176 * S3V and Savage seem to think that this is the max ramdac speed. This 1177 * driver just ignores the whole mess done before and sets 1178 * clockRange->maxClock differently slightly later. 1179 * 1180 * In order to not ditch information, here is a table of what the dacspeeds 1181 * "were" before the cleanup. 1182 * 1183 * Chipset ### >= 24bpp ### lower 1184 * 1185 * S3_ViRGE_VX 135000 220000 1186 * S3_TRIO_3D_2X_SERIES 135000 230000 1187 * S3_ViRGE_DXGX 135000 170000 1188 * S3_ViRGE_GX2_SERIES 135000 170000 1189 * S3_ViRGE_MX_SERIES 100000 135000 1190 * 1191 * Others devices get: 1192 * > 24bpp: 57000 1193 * = 24bpp: 95000 1194 * < 24bpp: 135000 1195 * 1196 * Special case is the MELCO BIOS: 1197 * > 24bpp: 83500 1198 * = 24bpp: 111500 1199 * > 8bpp: 162500 1200 * <= 8bpp: 191500 1201 */ 1202 1203 if (find_bios_string(ps3v, BIOS_BASE, "S3 86C325", 1204 "MELCO WGP-VG VIDEO BIOS") != NULL) { 1205 if (xf86GetVerbosity()) 1206 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "MELCO BIOS found\n"); 1207 if (ps3v->MCLK <= 0) 1208 ps3v->MCLK = 74000; 1209 } 1210 1211 if (ps3v->Chipset != S3_ViRGE_VX) { 1212 VGAOUT8(vgaCRIndex, 0x66); 1213 VGAOUT8(vgaCRReg, cr66 & ~0x02); /* clear reset flag */ 1214 usleep(10000); /* wait a little bit... */ 1215 } 1216 1217 /* Detect current MCLK and print it for user */ 1218 VGAOUT8(0x3c4, 0x08); 1219 VGAOUT8(0x3c5, 0x06); 1220 VGAOUT8(0x3c4, 0x10); 1221 n = VGAIN8(0x3c5); 1222 VGAOUT8(0x3c4, 0x11); 1223 m = VGAIN8(0x3c5); 1224 m &= 0x7f; 1225 n1 = n & 0x1f; 1226 n2 = (n>>5) & 0x03; 1227 mclk = ((1431818 * (m+2)) / (n1+2) / (1 << n2) + 50) / 100; 1228 if (S3_ViRGE_MX_SERIES(ps3v->Chipset)) { 1229 MessageType is_probed = X_PROBED; 1230 /* 1231 * try to figure out which reference clock is used: 1232 * Toshiba Tecra 5x0/7x0 seems to use 28.636 MHz 1233 * Compaq Armada 7x00 uses 14.318 MHz 1234 */ 1235 if (find_bios_string(ps3v, BIOS_BASE, "COMPAQ M5 BIOS", NULL) != NULL) { 1236 if (xf86GetVerbosity()) 1237 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "COMPAQ M5 BIOS found\n"); 1238 /* ps3v->refclk_fact = 1.0; */ 1239 } 1240 else if (find_bios_string(ps3v, BIOS_BASE, "TOSHIBA Video BIOS", NULL) != NULL) { 1241 if (xf86GetVerbosity()) 1242 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "TOSHIBA Video BIOS found\n"); 1243 /* ps3v->refclk_fact = 2.0; */ 1244 } 1245 /* else */ { /* always use guessed value... */ 1246 if (mclk > 60000) 1247 ps3v->refclk_fact = 1.0; 1248 else 1249 ps3v->refclk_fact = 2.0; /* don't know why ??? */ 1250 } 1251 if (ps3v->REFCLK != 0) { 1252 ps3v->refclk_fact = ps3v->REFCLK / 14318.0; 1253 is_probed = X_CONFIG; 1254 } 1255 else 1256 ps3v->REFCLK = (int)(14318.18 * ps3v->refclk_fact); 1257 1258 mclk = (int)(mclk * ps3v->refclk_fact); 1259 xf86DrvMsg(pScrn->scrnIndex, is_probed, "assuming RefCLK value of %1.3f MHz\n", 1260 ps3v->REFCLK / 1000.0); 1261 } 1262 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected current MCLK value of %1.3f MHz\n", 1263 mclk / 1000.0); 1264 1265 if (S3_ViRGE_MX_SERIES(ps3v->Chipset) && xf86GetVerbosity()) { 1266 int lcdclk, h_lcd, v_lcd; 1267 if (ps3v->LCDClk) { 1268 lcdclk = ps3v->LCDClk; 1269 } else { 1270 unsigned char sr12, sr13, sr29; 1271 VGAOUT8(0x3c4, 0x12); 1272 sr12 = VGAIN8(0x3c5); 1273 VGAOUT8(0x3c4, 0x13); 1274 sr13 = VGAIN8(0x3c5) & 0x7f; 1275 VGAOUT8(0x3c4, 0x29); 1276 sr29 = VGAIN8(0x3c5); 1277 n1 = sr12 & 0x1f; 1278 n2 = ((sr12>>6) & 0x03) | ((sr29 & 0x01) << 2); 1279 lcdclk = ((int)(ps3v->refclk_fact * 1431818 * (sr13+2)) / (n1+2) / (1 << n2) + 50) / 100; 1280 } 1281 VGAOUT8(0x3c4, 0x61); 1282 h_lcd = VGAIN8(0x3c5); 1283 VGAOUT8(0x3c4, 0x66); 1284 h_lcd |= ((VGAIN8(0x3c5) & 0x02) << 7); 1285 h_lcd = (h_lcd+1) * 8; 1286 VGAOUT8(0x3c4, 0x69); 1287 v_lcd = VGAIN8(0x3c5); 1288 VGAOUT8(0x3c4, 0x6e); 1289 v_lcd |= ((VGAIN8(0x3c5) & 0x70) << 4); 1290 v_lcd++; 1291 xf86DrvMsg(pScrn->scrnIndex 1292 , ps3v->LCDClk ? X_CONFIG : X_PROBED 1293 , "LCD size %dx%d, clock %1.3f MHz\n" 1294 , h_lcd, v_lcd 1295 , lcdclk / 1000.0); 1296 } 1297 1298 S3VDisableMmio(pScrn); 1299 S3VUnmapMem(pScrn); 1300 1301 /* And finally set various possible option flags */ 1302 1303 ps3v->bankedMono = FALSE; 1304 1305 1306#if 0 1307 vga256InfoRec.directMode = XF86DGADirectPresent; 1308#endif 1309 1310 /* 1311 * xf86ValidateModes will check that the mode HTotal and VTotal values 1312 * don't exceed the chipset's limit if pScrn->maxHValue and 1313 * pScrn->maxVValue are set. 1314 */ 1315 1316 /* todo - The virge limit is 2048 vertical & horizontal */ 1317 /* pixels, not clock register settings. */ 1318 /* true for all ViRGE? */ 1319 pScrn->maxHValue = 2048; 1320 pScrn->maxVValue = 2048; 1321 1322 /* Lower depths default to config file */ 1323 pScrn->virtualX = pScrn->display->virtualX; 1324 /* Adjust the virtualX to meet ViRGE hardware */ 1325 /* limits for depth 24, bpp 24 & 32. This is */ 1326 /* mostly for 32 bpp as 1024x768 is one pixel */ 1327 /* larger than supported. */ 1328 if (pScrn->depth == 24) 1329 if ( ((pScrn->bitsPerPixel/8) * pScrn->display->virtualX) > 4095 ) { 1330 pScrn->virtualX = 4095 / (pScrn->bitsPerPixel / 8); 1331 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1332 "Virtual width adjusted, max for this depth & bpp is %d.\n", 1333 pScrn->virtualX ); 1334 } 1335 1336 /* 1337 * Setup the ClockRanges, which describe what clock ranges are available, 1338 * and what sort of modes they can be used for. 1339 */ 1340 clockRanges = xnfcalloc(sizeof(ClockRange), 1); 1341 clockRanges->next = NULL; 1342 clockRanges->minClock = 10000; 1343 if (ps3v->Chipset == S3_ViRGE_VX ) 1344 clockRanges->maxClock = 440000; 1345 else 1346 clockRanges->maxClock = 270000; 1347 clockRanges->clockIndex = -1; /* programmable */ 1348 clockRanges->interlaceAllowed = TRUE; /* yes, S3V SVGA 3.3.2 */ 1349 clockRanges->doubleScanAllowed = TRUE; 1350 1351 /* Screen pointer */ 1352 i = xf86ValidateModes(pScrn, 1353 /* Available monitor modes */ 1354 /* (DisplayModePtr availModes) */ 1355 pScrn->monitor->Modes, 1356 /* req mode names for screen */ 1357 /* (char **modesNames) */ 1358 pScrn->display->modes, 1359 /* list of clock ranges allowed */ 1360 /* (ClockRangePtr clockRanges) */ 1361 clockRanges, 1362 /* list of driver line pitches, */ 1363 /* supply or NULL and use min/ */ 1364 /* max below */ 1365 /* (int *linePitches) */ 1366 NULL, 1367 /* min lin pitch (width) */ 1368 /* (int minPitch) */ 1369 256, 1370 /* max line pitch (width) */ 1371 /* (int maxPitch) */ 1372 2048, 1373 /* bits of granularity for line */ 1374 /* pitch (width) above, reguired*/ 1375 /* (int pitchInc) */ 1376 pScrn->bitsPerPixel, 1377 /* min virt height, 0 no limit */ 1378 /* (int minHeight) */ 1379 128, 1380 /* max virt height, 0 no limit */ 1381 /* (int maxHeight) */ 1382 2048, 1383 /* force virtX, 0 for auto */ 1384 /* (int VirtualX) */ 1385 /* value is adjusted above for */ 1386 /* hardware limits */ 1387 pScrn->virtualX, 1388 /* force virtY, 0 for auto */ 1389 /* (int VirtualY) */ 1390 pScrn->display->virtualY, 1391 /* size (bytes) of aper used to */ 1392 /* access video memory */ 1393 /* (unsigned long apertureSize) */ 1394 ps3v->videoRambytes, 1395 /* how to pick mode */ 1396 /* (LookupModeFlags strategy) */ 1397 LOOKUP_BEST_REFRESH); 1398 1399 if (i == -1) { 1400 S3VFreeRec(pScrn); 1401 return FALSE; 1402 } 1403 /* Prune the modes marked as invalid */ 1404 xf86PruneDriverModes(pScrn); 1405 1406 if (i == 0 || pScrn->modes == NULL) { 1407 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 1408 S3VFreeRec(pScrn); 1409 return FALSE; 1410 } 1411 1412 xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 1413 /*xf86SetCrtcForModes(pScrn, 0);*/ 1414 1415 /* Set the current mode to the first in the list */ 1416 pScrn->currentMode = pScrn->modes; 1417 1418 /* Print the list of modes being used */ 1419 xf86PrintModes(pScrn); 1420 1421 /* Set display resolution */ 1422 xf86SetDpi(pScrn, 0, 0); 1423 1424 /* Load bpp-specific modules */ 1425 if( xf86LoadSubModule(pScrn, "fb") == NULL ) 1426 { 1427 S3VFreeRec(pScrn); 1428 return FALSE; 1429 } 1430 xf86LoaderReqSymLists(fbSymbols, NULL); 1431 1432 /* Load XAA if needed */ 1433 if (!ps3v->NoAccel || ps3v->hwcursor ) { 1434 if (!xf86LoadSubModule(pScrn, "xaa")) { 1435 S3VFreeRec(pScrn); 1436 return FALSE; 1437 } 1438 xf86LoaderReqSymLists(xaaSymbols, NULL); 1439 } 1440 1441 /* Load ramdac if needed */ 1442 if (ps3v->hwcursor) { 1443 if (!xf86LoadSubModule(pScrn, "ramdac")) { 1444 S3VFreeRec(pScrn); 1445 return FALSE; 1446 } 1447 xf86LoaderReqSymLists(ramdacSymbols, NULL); 1448 } 1449 1450 if (ps3v->shadowFB) { 1451 if (!xf86LoadSubModule(pScrn, "shadowfb")) { 1452 S3VFreeRec(pScrn); 1453 return FALSE; 1454 } 1455 xf86LoaderReqSymLists(shadowSymbols, NULL); 1456 } 1457 1458 /* Setup WAITFIFO() for accel and ModeInit() */ 1459 /* Needs to be done prior to first ModeInit call */ 1460 /* and any accel activity. */ 1461 switch(ps3v->Chipset) 1462 { 1463 /* GX2_SERIES chips, GX2 & TRIO_3D_2X */ 1464 case S3_ViRGE_GX2: 1465 case S3_TRIO_3D_2X: 1466 ps3v->pWaitFifo = S3VWaitFifoGX2; 1467 ps3v->pWaitCmd = S3VWaitCmdGX2; 1468 break; 1469 case S3_ViRGE: 1470 case S3_ViRGE_VX: 1471 default: 1472 ps3v->pWaitFifo = S3VWaitFifoMain; 1473 /* Do nothing... */ 1474 ps3v->pWaitCmd = S3VWaitDummy; 1475 break; 1476 } 1477 1478 return TRUE; 1479} 1480 1481 1482/* 1483 * This is called when VT switching back to the X server. Its job is 1484 * to reinitialise the video mode. 1485 * 1486 * We may wish to unmap video/MMIO memory too. 1487 */ 1488 1489 1490/* Mandatory */ 1491static Bool 1492S3VEnterVT(int scrnIndex, int flags) 1493{ 1494 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1495/* ScreenPtr pScreen = xf86Screens[scrnIndex]->pScreen; */ 1496 /*vgaHWPtr hwp = VGAHWPTR(pScrn);*/ 1497 1498 PVERB5(" S3VEnterVT\n"); 1499 /*vgaHWUnlockMMIO(hwp);*/ 1500 /* Enable MMIO and map memory */ 1501#ifdef unmap_always 1502 S3VMapMem(pScrn); 1503#endif 1504 S3VEnableMmio(pScrn); 1505 1506 S3VSave(pScrn); 1507 return S3VModeInit(pScrn, pScrn->currentMode); 1508} 1509 1510 1511/* 1512 * This is called when VT switching away from the X server. Its job is 1513 * to restore the previous (text) mode. 1514 * 1515 * We may wish to remap video/MMIO memory too. 1516 * 1517 */ 1518 1519/* Mandatory */ 1520static void 1521S3VLeaveVT(int scrnIndex, int flags) 1522{ 1523 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1524 vgaHWPtr hwp = VGAHWPTR(pScrn); 1525 S3VPtr ps3v = S3VPTR(pScrn); 1526 vgaRegPtr vgaSavePtr = &hwp->SavedReg; 1527 S3VRegPtr S3VSavePtr = &ps3v->SavedReg; 1528 1529 PVERB5(" S3VLeaveVT\n"); 1530 /* Like S3VRestore, but uses passed */ 1531 /* mode registers. */ 1532 S3VWriteMode(pScrn, vgaSavePtr, S3VSavePtr); 1533 /* Restore standard register access */ 1534 /* and unmap memory. */ 1535 S3VDisableMmio(pScrn); 1536#ifdef unmap_always 1537 S3VUnmapMem(pScrn); 1538#endif 1539 /*vgaHWLockMMIO(hwp);*/ 1540 1541} 1542 1543 1544/* 1545 * This function performs the inverse of the restore function: It saves all 1546 * the standard and extended registers that we are going to modify to set 1547 * up a video mode. Again, we also save the STREAMS context if it is needed. 1548 * 1549 * prototype 1550 * void ChipSave(ScrnInfoPtr pScrn) 1551 * 1552 */ 1553 1554static void 1555S3VSave (ScrnInfoPtr pScrn) 1556{ 1557 unsigned char cr3a, cr66; 1558 vgaHWPtr hwp = VGAHWPTR(pScrn); 1559 vgaRegPtr vgaSavePtr = &hwp->SavedReg; 1560 S3VPtr ps3v = S3VPTR(pScrn); 1561 S3VRegPtr save = &ps3v->SavedReg; 1562 int vgaCRIndex, vgaCRReg, vgaIOBase; 1563 vgaIOBase = hwp->IOBase; 1564 vgaCRIndex = 0; 1565 1566 vgaCRReg = 0; 1567 1568 vgaCRReg = vgaIOBase + 5; 1569 vgaCRIndex = vgaIOBase + 4; 1570 1571 PVERB5(" S3VSave\n"); 1572 1573 /* 1574 * This function will handle creating the data structure and filling 1575 * in the generic VGA portion. 1576 */ 1577 1578 VGAOUT8(vgaCRIndex, 0x66); 1579 cr66 = VGAIN8(vgaCRReg); 1580 VGAOUT8(vgaCRReg, cr66 | 0x80); 1581 VGAOUT8(vgaCRIndex, 0x3a); 1582 cr3a = VGAIN8(vgaCRReg); 1583 save->CR3A = cr3a; 1584 1585 VGAOUT8(vgaCRReg, cr3a | 0x80); 1586 1587 /* VGA_SR_MODE saves mode info only, no fonts, no colormap */ 1588 /* Save all for primary, anything */ 1589 /* for secondary cards?, do MODE */ 1590 /* for the moment. */ 1591 if (xf86IsPrimaryPci(ps3v->PciInfo)) 1592 vgaHWSave(pScrn, vgaSavePtr, VGA_SR_ALL); 1593 else 1594 vgaHWSave(pScrn, vgaSavePtr, VGA_SR_MODE); 1595 1596 VGAOUT8(vgaCRIndex, 0x66); 1597 VGAOUT8(vgaCRReg, cr66); 1598 VGAOUT8(vgaCRIndex, 0x3a); 1599 VGAOUT8(vgaCRReg, cr3a); 1600 1601 /* First unlock extended sequencer regs */ 1602 VGAOUT8(0x3c4, 0x08); 1603 save->SR08 = VGAIN8(0x3c5); 1604 VGAOUT8(0x3c5, 0x06); 1605 1606 /* Now we save all the s3 extended regs we need */ 1607 VGAOUT8(vgaCRIndex, 0x31); 1608 save->CR31 = VGAIN8(vgaCRReg); 1609 VGAOUT8(vgaCRIndex, 0x34); 1610 save->CR34 = VGAIN8(vgaCRReg); 1611 VGAOUT8(vgaCRIndex, 0x36); 1612 save->CR36 = VGAIN8(vgaCRReg); 1613 1614 /* workaround cr3a corruption */ 1615 if( !(ps3v->mx_cr3a_fix)) 1616 { 1617 VGAOUT8(vgaCRIndex, 0x3a); 1618 save->CR3A = VGAIN8(vgaCRReg); 1619 } 1620 1621 if (!S3_TRIO_3D_SERIES(ps3v->Chipset)) { 1622 VGAOUT8(vgaCRIndex, 0x40); 1623 save->CR40 = VGAIN8(vgaCRReg); 1624 } 1625 if (S3_ViRGE_MX_SERIES(ps3v->Chipset)) { 1626 VGAOUT8(vgaCRIndex, 0x41); 1627 save->CR41 = VGAIN8(vgaCRReg); 1628 } 1629 VGAOUT8(vgaCRIndex, 0x42); 1630 save->CR42 = VGAIN8(vgaCRReg); 1631 VGAOUT8(vgaCRIndex, 0x45); 1632 save->CR45 = VGAIN8(vgaCRReg); 1633 VGAOUT8(vgaCRIndex, 0x51); 1634 save->CR51 = VGAIN8(vgaCRReg); 1635 VGAOUT8(vgaCRIndex, 0x53); 1636 save->CR53 = VGAIN8(vgaCRReg); 1637 VGAOUT8(vgaCRIndex, 0x54); 1638 save->CR54 = VGAIN8(vgaCRReg); 1639 VGAOUT8(vgaCRIndex, 0x55); 1640 save->CR55 = VGAIN8(vgaCRReg); 1641 VGAOUT8(vgaCRIndex, 0x58); 1642 save->CR58 = VGAIN8(vgaCRReg); 1643 VGAOUT8(vgaCRIndex, 0x63); 1644 save->CR63 = VGAIN8(vgaCRReg); 1645 VGAOUT8(vgaCRIndex, 0x66); 1646 save->CR66 = VGAIN8(vgaCRReg); 1647 VGAOUT8(vgaCRIndex, 0x67); 1648 save->CR67 = VGAIN8(vgaCRReg); 1649 VGAOUT8(vgaCRIndex, 0x68); 1650 save->CR68 = VGAIN8(vgaCRReg); 1651 VGAOUT8(vgaCRIndex, 0x69); 1652 save->CR69 = VGAIN8(vgaCRReg); 1653 1654 VGAOUT8(vgaCRIndex, 0x33); 1655 save->CR33 = VGAIN8(vgaCRReg); 1656 if (S3_TRIO_3D_2X_SERIES(ps3v->Chipset) || S3_ViRGE_GX2_SERIES(ps3v->Chipset) 1657 /* MXTESTME */ || S3_ViRGE_MX_SERIES(ps3v->Chipset) ) 1658 { 1659 VGAOUT8(vgaCRIndex, 0x85); 1660 save->CR85 = VGAIN8(vgaCRReg); 1661 } 1662 if (ps3v->Chipset == S3_ViRGE_DXGX) { 1663 VGAOUT8(vgaCRIndex, 0x86); 1664 save->CR86 = VGAIN8(vgaCRReg); 1665 } 1666 if ((ps3v->Chipset == S3_ViRGE_GX2) || 1667 S3_ViRGE_MX_SERIES(ps3v->Chipset) ) { 1668 VGAOUT8(vgaCRIndex, 0x7B); 1669 save->CR7B = VGAIN8(vgaCRReg); 1670 VGAOUT8(vgaCRIndex, 0x7D); 1671 save->CR7D = VGAIN8(vgaCRReg); 1672 VGAOUT8(vgaCRIndex, 0x87); 1673 save->CR87 = VGAIN8(vgaCRReg); 1674 VGAOUT8(vgaCRIndex, 0x92); 1675 save->CR92 = VGAIN8(vgaCRReg); 1676 VGAOUT8(vgaCRIndex, 0x93); 1677 save->CR93 = VGAIN8(vgaCRReg); 1678 } 1679 if (ps3v->Chipset == S3_ViRGE_DXGX || S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 1680 S3_ViRGE_MX_SERIES(ps3v->Chipset) || S3_TRIO_3D_SERIES(ps3v->Chipset)) { 1681 VGAOUT8(vgaCRIndex, 0x90); 1682 save->CR90 = VGAIN8(vgaCRReg); 1683 VGAOUT8(vgaCRIndex, 0x91); 1684 save->CR91 = VGAIN8(vgaCRReg); 1685 } 1686 1687 /* Extended mode timings regs */ 1688 1689 VGAOUT8(vgaCRIndex, 0x3b); 1690 save->CR3B = VGAIN8(vgaCRReg); 1691 VGAOUT8(vgaCRIndex, 0x3c); 1692 save->CR3C = VGAIN8(vgaCRReg); 1693 VGAOUT8(vgaCRIndex, 0x43); 1694 save->CR43 = VGAIN8(vgaCRReg); 1695 VGAOUT8(vgaCRIndex, 0x5d); 1696 save->CR5D = VGAIN8(vgaCRReg); 1697 VGAOUT8(vgaCRIndex, 0x5e); 1698 save->CR5E = VGAIN8(vgaCRReg); 1699 VGAOUT8(vgaCRIndex, 0x65); 1700 save->CR65 = VGAIN8(vgaCRReg); 1701 VGAOUT8(vgaCRIndex, 0x6d); 1702 save->CR6D = VGAIN8(vgaCRReg); 1703 1704 1705 /* Save sequencer extended regs for DCLK PLL programming */ 1706 1707 VGAOUT8(0x3c4, 0x10); 1708 save->SR10 = VGAIN8(0x3c5); 1709 VGAOUT8(0x3c4, 0x11); 1710 save->SR11 = VGAIN8(0x3c5); 1711 1712 VGAOUT8(0x3c4, 0x12); 1713 save->SR12 = VGAIN8(0x3c5); 1714 VGAOUT8(0x3c4, 0x13); 1715 save->SR13 = VGAIN8(0x3c5); 1716 if (S3_ViRGE_GX2_SERIES(ps3v->Chipset) || S3_ViRGE_MX_SERIES(ps3v->Chipset)) { 1717 VGAOUT8(0x3c4, 0x29); 1718 save->SR29 = VGAIN8(0x3c5); 1719 } 1720 /* SR 54,55,56,57 undocumented for GX2. Was this supposed to be CR? */ 1721 /* (These used to be part of the above if() */ 1722 if (S3_ViRGE_MX_SERIES(ps3v->Chipset)) { 1723 VGAOUT8(0x3c4, 0x54); 1724 save->SR54 = VGAIN8(0x3c5); 1725 VGAOUT8(0x3c4, 0x55); 1726 save->SR55 = VGAIN8(0x3c5); 1727 VGAOUT8(0x3c4, 0x56); 1728 save->SR56 = VGAIN8(0x3c5); 1729 VGAOUT8(0x3c4, 0x57); 1730 save->SR57 = VGAIN8(0x3c5); 1731 } 1732 1733 VGAOUT8(0x3c4, 0x15); 1734 save->SR15 = VGAIN8(0x3c5); 1735 VGAOUT8(0x3c4, 0x18); 1736 save->SR18 = VGAIN8(0x3c5); 1737 if (S3_TRIO_3D_SERIES(ps3v->Chipset)) { 1738 VGAOUT8(0x3c4, 0x0a); 1739 save->SR0A = VGAIN8(0x3c5); 1740 VGAOUT8(0x3c4, 0x0F); 1741 save->SR0F = VGAIN8(0x3c5); 1742 } 1743 1744 VGAOUT8(vgaCRIndex, 0x66); 1745 cr66 = VGAIN8(vgaCRReg); 1746 VGAOUT8(vgaCRReg, cr66 | 0x80); 1747 VGAOUT8(vgaCRIndex, 0x3a); 1748 cr3a = VGAIN8(vgaCRReg); 1749 VGAOUT8(vgaCRReg, cr3a | 0x80); 1750 1751 /* And if streams is to be used, save that as well */ 1752 1753 if(ps3v->NeedSTREAMS) { 1754 S3VSaveSTREAMS(pScrn, save->STREAMS); 1755 } 1756 1757 /* Now save Memory Interface Unit registers */ 1758 if( S3_ViRGE_GX2_SERIES(ps3v->Chipset) 1759 /* MXTESTME */ || S3_ViRGE_MX_SERIES(ps3v->Chipset) ) 1760 { 1761 /* No MMPR regs on MX & GX2 */ 1762 } 1763 else 1764 { 1765 save->MMPR0 = INREG(FIFO_CONTROL_REG); 1766 save->MMPR1 = INREG(MIU_CONTROL_REG); 1767 save->MMPR2 = INREG(STREAMS_TIMEOUT_REG); 1768 save->MMPR3 = INREG(MISC_TIMEOUT_REG); 1769 } 1770 1771 if (xf86GetVerbosity() > 1) { 1772 /* Debug */ 1773 /* Which chipsets? */ 1774 if ( 1775 /* virge */ 1776 ps3v->Chipset == S3_ViRGE || 1777 /* VX */ 1778 S3_ViRGE_VX_SERIES(ps3v->Chipset) || 1779 /* DX & GX */ 1780 ps3v->Chipset == S3_ViRGE_DXGX || 1781 /* GX2 & Trio3D_2X */ 1782 /* S3_ViRGE_GX2_SERIES(ps3v->Chipset) || */ 1783 /* Trio3D_2X */ 1784 /* S3_TRIO_3D_2X_SERIES(ps3v->Chipset) */ 1785 /* MX & MX+ */ 1786 /* S3_ViRGE_MX_SERIES(ps3v->Chipset) || */ 1787 /* MX+ only */ 1788 /* S3_ViRGE_MXP_SERIES(ps3v->Chipset) || */ 1789 /* Trio3D */ 1790 ps3v->Chipset == S3_TRIO_3D 1791 ) 1792 { 1793 1794 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 1795 "MMPR regs: %08lx %08lx %08lx %08lx\n", 1796 (unsigned long)INREG(FIFO_CONTROL_REG), 1797 (unsigned long)INREG(MIU_CONTROL_REG), 1798 (unsigned long)INREG(STREAMS_TIMEOUT_REG), 1799 (unsigned long)INREG(MISC_TIMEOUT_REG)); 1800 } 1801 1802 PVERB5("\n\nViRGE driver: saved current video mode. Register dump:\n\n"); 1803 } 1804 1805 VGAOUT8(vgaCRIndex, 0x3a); 1806 VGAOUT8(vgaCRReg, cr3a); 1807 VGAOUT8(vgaCRIndex, 0x66); 1808 VGAOUT8(vgaCRReg, cr66); 1809 /* Dup the VGA & S3V state to the */ 1810 /* new mode state, but only first time. */ 1811 if( !ps3v->ModeStructInit ) { 1812 /* XXX Should check the return value of vgaHWCopyReg() */ 1813 vgaHWCopyReg( &hwp->ModeReg, vgaSavePtr ); 1814 memcpy( &ps3v->ModeReg, save, sizeof(S3VRegRec) ); 1815 ps3v->ModeStructInit = TRUE; 1816 } 1817 1818 if (xf86GetVerbosity() > 1) S3VPrintRegs(pScrn); 1819 1820 return; 1821} 1822 1823 1824/* This function saves the STREAMS registers to our private structure */ 1825 1826static void 1827S3VSaveSTREAMS(ScrnInfoPtr pScrn, unsigned int *streams) 1828{ 1829 S3VPtr ps3v = S3VPTR(pScrn); 1830 1831 streams[0] = INREG(PSTREAM_CONTROL_REG); 1832 streams[1] = INREG(COL_CHROMA_KEY_CONTROL_REG); 1833 streams[2] = INREG(SSTREAM_CONTROL_REG); 1834 streams[3] = INREG(CHROMA_KEY_UPPER_BOUND_REG); 1835 streams[4] = INREG(SSTREAM_STRETCH_REG); 1836 streams[5] = INREG(BLEND_CONTROL_REG); 1837 streams[6] = INREG(PSTREAM_FBADDR0_REG); 1838 streams[7] = INREG(PSTREAM_FBADDR1_REG); 1839 streams[8] = INREG(PSTREAM_STRIDE_REG); 1840 streams[9] = INREG(DOUBLE_BUFFER_REG); 1841 streams[10] = INREG(SSTREAM_FBADDR0_REG); 1842 streams[11] = INREG(SSTREAM_FBADDR1_REG); 1843 streams[12] = INREG(SSTREAM_STRIDE_REG); 1844 streams[13] = INREG(OPAQUE_OVERLAY_CONTROL_REG); 1845 streams[14] = INREG(K1_VSCALE_REG); 1846 streams[15] = INREG(K2_VSCALE_REG); 1847 streams[16] = INREG(DDA_VERT_REG); 1848 streams[17] = INREG(STREAMS_FIFO_REG); 1849 streams[18] = INREG(PSTREAM_START_REG); 1850 streams[19] = INREG(PSTREAM_WINDOW_SIZE_REG); 1851 streams[20] = INREG(SSTREAM_START_REG); 1852 streams[21] = INREG(SSTREAM_WINDOW_SIZE_REG); 1853 1854} 1855 1856 1857/* 1858 * This function is used to restore a video mode. It writes out all 1859 * of the standard VGA and extended S3 registers needed to setup a 1860 * video mode. 1861 * 1862 * Note that our life is made more difficult because of the STREAMS 1863 * processor which must be used for 24bpp. We need to disable STREAMS 1864 * before we switch video modes, or we risk locking up the machine. 1865 * We also have to follow a certain order when reenabling it. 1866 */ 1867/* let's try restoring in the same order as in the 3.3.2.3 driver */ 1868static void 1869S3VWriteMode (ScrnInfoPtr pScrn, vgaRegPtr vgaSavePtr, S3VRegPtr restore) 1870{ 1871 unsigned char tmp, cr3a=0, cr66, cr67; 1872 1873 vgaHWPtr hwp = VGAHWPTR(pScrn); 1874 S3VPtr ps3v = S3VPTR(pScrn); 1875 int vgaCRIndex, vgaCRReg, vgaIOBase; 1876 vgaIOBase = hwp->IOBase; 1877 vgaCRIndex = vgaIOBase + 4; 1878 vgaCRReg = vgaIOBase + 5; 1879 1880 PVERB5(" S3VWriteMode\n"); 1881 1882 vgaHWProtect(pScrn, TRUE); 1883 1884 /* Are we going to reenable STREAMS in this new mode? */ 1885 ps3v->STREAMSRunning = restore->CR67 & 0x0c; 1886 1887 /* First reset GE to make sure nothing is going on */ 1888 if(ps3v->Chipset == S3_ViRGE_VX) { 1889 VGAOUT8(vgaCRIndex, 0x63); 1890 if(VGAIN8(vgaCRReg) & 0x01) S3VGEReset(pScrn,0,__LINE__,__FILE__); 1891 } 1892 else { 1893 VGAOUT8(vgaCRIndex, 0x66); 1894 if(VGAIN8(vgaCRReg) & 0x01) S3VGEReset(pScrn,0,__LINE__,__FILE__); 1895 } 1896 1897 /* As per databook, always disable STREAMS before changing modes */ 1898 VGAOUT8(vgaCRIndex, 0x67); 1899 cr67 = VGAIN8(vgaCRReg); 1900 if ((cr67 & 0x0c) == 0x0c) { 1901 S3VDisableSTREAMS(pScrn); /* If STREAMS was running, disable it */ 1902 } 1903 1904 /* Restore S3 extended regs */ 1905 VGAOUT8(vgaCRIndex, 0x63); 1906 VGAOUT8(vgaCRReg, restore->CR63); 1907 VGAOUT8(vgaCRIndex, 0x66); 1908 VGAOUT8(vgaCRReg, restore->CR66); 1909 VGAOUT8(vgaCRIndex, 0x3a); 1910 VGAOUT8(vgaCRReg, restore->CR3A); 1911 VGAOUT8(vgaCRIndex, 0x31); 1912 VGAOUT8(vgaCRReg, restore->CR31); 1913 VGAOUT8(vgaCRIndex, 0x58); 1914 VGAOUT8(vgaCRReg, restore->CR58); 1915 VGAOUT8(vgaCRIndex, 0x55); 1916 VGAOUT8(vgaCRReg, restore->CR55); 1917 1918 /* Extended mode timings registers */ 1919 VGAOUT8(vgaCRIndex, 0x53); 1920 VGAOUT8(vgaCRReg, restore->CR53); 1921 VGAOUT8(vgaCRIndex, 0x5d); 1922 VGAOUT8(vgaCRReg, restore->CR5D); 1923 VGAOUT8(vgaCRIndex, 0x5e); 1924 VGAOUT8(vgaCRReg, restore->CR5E); 1925 VGAOUT8(vgaCRIndex, 0x3b); 1926 VGAOUT8(vgaCRReg, restore->CR3B); 1927 VGAOUT8(vgaCRIndex, 0x3c); 1928 VGAOUT8(vgaCRReg, restore->CR3C); 1929 VGAOUT8(vgaCRIndex, 0x43); 1930 VGAOUT8(vgaCRReg, restore->CR43); 1931 VGAOUT8(vgaCRIndex, 0x65); 1932 VGAOUT8(vgaCRReg, restore->CR65); 1933 VGAOUT8(vgaCRIndex, 0x6d); 1934 VGAOUT8(vgaCRReg, restore->CR6D); 1935 1936 /* Restore the desired video mode with CR67 */ 1937 1938 VGAOUT8(vgaCRIndex, 0x67); 1939 cr67 = VGAIN8(vgaCRReg) & 0xf; /* Possible hardware bug on VX? */ 1940 VGAOUT8(vgaCRReg, 0x50 | cr67); 1941 usleep(10000); 1942 VGAOUT8(vgaCRIndex, 0x67); 1943 VGAOUT8(vgaCRReg, restore->CR67 & ~0x0c); /* Don't enable STREAMS yet */ 1944 1945 /* Other mode timing and extended regs */ 1946 VGAOUT8(vgaCRIndex, 0x34); 1947 VGAOUT8(vgaCRReg, restore->CR34); 1948 if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 1949 /* S3_ViRGE_MX_SERIES(ps3v->Chipset) || CR40 reserved on MX */ 1950 S3_ViRGE_MXP_SERIES(ps3v->Chipset) || 1951 S3_ViRGE_VX_SERIES(ps3v->Chipset) || 1952 /* S3_TRIO_3D_2X_SERIES(ps3v->Chipset) * included in GX2 series */ 1953 ps3v->Chipset == S3_ViRGE_DXGX || 1954 ps3v->Chipset == S3_ViRGE 1955 ) 1956 { 1957 VGAOUT8(vgaCRIndex, 0x40); 1958 VGAOUT8(vgaCRReg, restore->CR40); 1959 } 1960 if (S3_ViRGE_MX_SERIES(ps3v->Chipset)) { 1961 VGAOUT8(vgaCRIndex, 0x41); 1962 VGAOUT8(vgaCRReg, restore->CR41); 1963 } 1964 VGAOUT8(vgaCRIndex, 0x42); 1965 VGAOUT8(vgaCRReg, restore->CR42); 1966 VGAOUT8(vgaCRIndex, 0x45); 1967 VGAOUT8(vgaCRReg, restore->CR45); 1968 VGAOUT8(vgaCRIndex, 0x51); 1969 VGAOUT8(vgaCRReg, restore->CR51); 1970 VGAOUT8(vgaCRIndex, 0x54); 1971 VGAOUT8(vgaCRReg, restore->CR54); 1972 1973 /* Memory timings */ 1974 VGAOUT8(vgaCRIndex, 0x36); 1975 VGAOUT8(vgaCRReg, restore->CR36); 1976 VGAOUT8(vgaCRIndex, 0x68); 1977 VGAOUT8(vgaCRReg, restore->CR68); 1978 VGAOUT8(vgaCRIndex, 0x69); 1979 VGAOUT8(vgaCRReg, restore->CR69); 1980 1981 VGAOUT8(vgaCRIndex, 0x33); 1982 VGAOUT8(vgaCRReg, restore->CR33); 1983 if (S3_TRIO_3D_2X_SERIES(ps3v->Chipset) || S3_ViRGE_GX2_SERIES(ps3v->Chipset) 1984 /* MXTESTME */ || S3_ViRGE_MX_SERIES(ps3v->Chipset) ) 1985 { 1986 VGAOUT8(vgaCRIndex, 0x85); 1987 VGAOUT8(vgaCRReg, restore->CR85); 1988 } 1989 if (ps3v->Chipset == S3_ViRGE_DXGX) { 1990 VGAOUT8(vgaCRIndex, 0x86); 1991 VGAOUT8(vgaCRReg, restore->CR86); 1992 } 1993 if ( (ps3v->Chipset == S3_ViRGE_GX2) || 1994 S3_ViRGE_MX_SERIES(ps3v->Chipset) ) { 1995 VGAOUT8(vgaCRIndex, 0x7B); 1996 VGAOUT8(vgaCRReg, restore->CR7B); 1997 VGAOUT8(vgaCRIndex, 0x7D); 1998 VGAOUT8(vgaCRReg, restore->CR7D); 1999 VGAOUT8(vgaCRIndex, 0x87); 2000 VGAOUT8(vgaCRReg, restore->CR87); 2001 VGAOUT8(vgaCRIndex, 0x92); 2002 VGAOUT8(vgaCRReg, restore->CR92); 2003 VGAOUT8(vgaCRIndex, 0x93); 2004 VGAOUT8(vgaCRReg, restore->CR93); 2005 } 2006 if (ps3v->Chipset == S3_ViRGE_DXGX || S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 2007 S3_ViRGE_MX_SERIES(ps3v->Chipset) || S3_TRIO_3D_SERIES(ps3v->Chipset)) { 2008 VGAOUT8(vgaCRIndex, 0x90); 2009 VGAOUT8(vgaCRReg, restore->CR90); 2010 VGAOUT8(vgaCRIndex, 0x91); 2011 VGAOUT8(vgaCRReg, restore->CR91); 2012 } 2013 2014 /* Unlock extended sequencer regs */ 2015 VGAOUT8(0x3c4, 0x08); 2016 VGAOUT8(0x3c5, 0x06); 2017 2018 2019 /* Restore extended sequencer regs for MCLK. SR10 == 255 indicates that 2020 * we should leave the default SR10 and SR11 values there. 2021 */ 2022 2023 if (restore->SR10 != 255) { 2024 VGAOUT8(0x3c4, 0x10); 2025 VGAOUT8(0x3c5, restore->SR10); 2026 VGAOUT8(0x3c4, 0x11); 2027 VGAOUT8(0x3c5, restore->SR11); 2028 } 2029 2030 /* Restore extended sequencer regs for DCLK */ 2031 VGAOUT8(0x3c4, 0x12); 2032 VGAOUT8(0x3c5, restore->SR12); 2033 VGAOUT8(0x3c4, 0x13); 2034 VGAOUT8(0x3c5, restore->SR13); 2035 if (S3_ViRGE_GX2_SERIES(ps3v->Chipset) || S3_ViRGE_MX_SERIES(ps3v->Chipset)) { 2036 VGAOUT8(0x3c4, 0x29); 2037 VGAOUT8(0x3c5, restore->SR29); 2038 } 2039 if (S3_ViRGE_MX_SERIES(ps3v->Chipset)) { 2040 VGAOUT8(0x3c4, 0x54); 2041 VGAOUT8(0x3c5, restore->SR54); 2042 VGAOUT8(0x3c4, 0x55); 2043 VGAOUT8(0x3c5, restore->SR55); 2044 VGAOUT8(0x3c4, 0x56); 2045 VGAOUT8(0x3c5, restore->SR56); 2046 VGAOUT8(0x3c4, 0x57); 2047 VGAOUT8(0x3c5, restore->SR57); 2048 } 2049 2050 VGAOUT8(0x3c4, 0x18); 2051 VGAOUT8(0x3c5, restore->SR18); 2052 2053 /* Load new m,n PLL values for DCLK & MCLK */ 2054 VGAOUT8(0x3c4, 0x15); 2055 tmp = VGAIN8(0x3c5) & ~0x21; 2056 2057 /* databook either 0x3 or 0x20, but not both?? */ 2058 VGAOUT8(0x3c5, tmp | 0x03); 2059 VGAOUT8(0x3c5, tmp | 0x23); 2060 VGAOUT8(0x3c5, tmp | 0x03); 2061 VGAOUT8(0x3c5, restore->SR15); 2062 if (S3_TRIO_3D_SERIES(ps3v->Chipset)) { 2063 VGAOUT8(0x3c4, 0x0a); 2064 VGAOUT8(0x3c5, restore->SR0A); 2065 VGAOUT8(0x3c4, 0x0f); 2066 VGAOUT8(0x3c5, restore->SR0F); 2067 } 2068 2069 VGAOUT8(0x3c4, 0x08); 2070 VGAOUT8(0x3c5, restore->SR08); 2071 2072 2073 /* Now write out CR67 in full, possibly starting STREAMS */ 2074 2075 VerticalRetraceWait(); 2076 VGAOUT8(vgaCRIndex, 0x67); 2077 VGAOUT8(vgaCRReg, 0x50); /* For possible bug on VX?! */ 2078 usleep(10000); 2079 VGAOUT8(vgaCRIndex, 0x67); 2080 VGAOUT8(vgaCRReg, restore->CR67); 2081 2082 VGAOUT8(vgaCRIndex, 0x66); 2083 cr66 = VGAIN8(vgaCRReg); 2084 VGAOUT8(vgaCRReg, cr66 | 0x80); 2085 VGAOUT8(vgaCRIndex, 0x3a); 2086 2087 /* workaround cr3a corruption */ 2088 if( ps3v->mx_cr3a_fix ) 2089 { 2090 VGAOUT8(vgaCRReg, restore->CR3A | 0x80); 2091 } 2092 else 2093 { 2094 cr3a = VGAIN8(vgaCRReg); 2095 VGAOUT8(vgaCRReg, cr3a | 0x80); 2096 } 2097 2098 /* And finally, we init the STREAMS processor if we have CR67 indicate 24bpp 2099 * We also restore FIFO and TIMEOUT memory controller registers. (later...) 2100 */ 2101 2102 if (ps3v->NeedSTREAMS) { 2103 if(ps3v->STREAMSRunning) S3VRestoreSTREAMS(pScrn, restore->STREAMS); 2104 } 2105 2106 /* Now, before we continue, check if this mode has the graphic engine ON 2107 * If yes, then we reset it. 2108 * This fixes some problems with corruption at 24bpp with STREAMS 2109 * Also restore the MIU registers. 2110 */ 2111 2112#ifndef MetroLink 2113 if(ps3v->Chipset == S3_ViRGE_VX) { 2114 if(restore->CR63 & 0x01) S3VGEReset(pScrn,0,__LINE__,__FILE__); 2115 } 2116 else { 2117 if(restore->CR66 & 0x01) S3VGEReset(pScrn,0,__LINE__,__FILE__); 2118 } 2119#else 2120 S3VGEReset(pScrn,0,__LINE__,__FILE__); 2121#endif 2122 2123 VerticalRetraceWait(); 2124 if (S3_ViRGE_GX2_SERIES(ps3v->Chipset) 2125 /* MXTESTME */ || S3_ViRGE_MX_SERIES(ps3v->Chipset) ) 2126 { 2127 VGAOUT8(vgaCRIndex, 0x85); 2128 /* primary stream threshold */ 2129 VGAOUT8(vgaCRReg, 0x1f ); 2130 } 2131 else 2132 { 2133 OUTREG(FIFO_CONTROL_REG, restore->MMPR0); 2134 } 2135 if( !( S3_ViRGE_GX2_SERIES(ps3v->Chipset) 2136 /* MXTESTME */ || S3_ViRGE_MX_SERIES(ps3v->Chipset) )) 2137 { 2138 WaitIdle(); /* Don't ask... */ 2139 OUTREG(MIU_CONTROL_REG, restore->MMPR1); 2140 WaitIdle(); 2141 OUTREG(STREAMS_TIMEOUT_REG, restore->MMPR2); 2142 WaitIdle(); 2143 OUTREG(MISC_TIMEOUT_REG, restore->MMPR3); 2144 } 2145 2146 /* Restore the standard VGA registers */ 2147 /* False indicates no fontinfo restore. */ 2148 /* VGA_SR_MODE restores mode info only, no font, no colormap */ 2149 /* Do all for primary video */ 2150 if (xf86IsPrimaryPci(ps3v->PciInfo)) 2151 vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_ALL); 2152 /* Mode only for non-primary? */ 2153 else 2154 vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_MODE); 2155 /* moved from before vgaHWRestore, to prevent segfault? */ 2156 VGAOUT8(vgaCRIndex, 0x66); 2157 VGAOUT8(vgaCRReg, cr66); 2158 VGAOUT8(vgaCRIndex, 0x3a); 2159 2160 /* workaround cr3a corruption */ 2161 if( ps3v->mx_cr3a_fix ) 2162 VGAOUT8(vgaCRReg, restore->CR3A); 2163 else 2164 VGAOUT8(vgaCRReg, cr3a); 2165 2166 if (xf86GetVerbosity() > 1) { 2167 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, 2168 "ViRGE driver: done restoring mode, dumping CR registers:\n"); 2169 S3VPrintRegs(pScrn); 2170 } 2171 2172 vgaHWProtect(pScrn, FALSE); 2173 2174 return; 2175 2176} 2177 2178 2179/* This function restores the saved STREAMS registers */ 2180 2181static void 2182S3VRestoreSTREAMS(ScrnInfoPtr pScrn, unsigned int *streams) 2183{ 2184 S3VPtr ps3v = S3VPTR(pScrn); 2185 2186 2187/* For now, set most regs to their default values for 24bpp 2188 * Restore only those that are needed for width/height/stride 2189 * Otherwise, we seem to get lockups because some registers 2190 * when saved have some reserved bits set. 2191 */ 2192 2193 OUTREG(PSTREAM_CONTROL_REG, streams[0] & 0x77000000); 2194 OUTREG(COL_CHROMA_KEY_CONTROL_REG, 0x00); 2195 OUTREG(SSTREAM_CONTROL_REG, 0x03000000); 2196 OUTREG(CHROMA_KEY_UPPER_BOUND_REG, 0x00); 2197 OUTREG(SSTREAM_STRETCH_REG, 0x00); 2198 OUTREG(BLEND_CONTROL_REG, 0x01000000); 2199 OUTREG(PSTREAM_FBADDR0_REG, 0x00); 2200 OUTREG(PSTREAM_FBADDR1_REG, 0x00); 2201 OUTREG(PSTREAM_STRIDE_REG, streams[8] & 0x0fff); 2202 OUTREG(DOUBLE_BUFFER_REG, 0x00); 2203 OUTREG(SSTREAM_FBADDR0_REG, 0x00); 2204 OUTREG(SSTREAM_FBADDR1_REG, 0x00); 2205 OUTREG(SSTREAM_STRIDE_REG, 0x01); 2206 OUTREG(OPAQUE_OVERLAY_CONTROL_REG, 0x40000000); 2207 OUTREG(K1_VSCALE_REG, 0x00); 2208 OUTREG(K2_VSCALE_REG, 0x00); 2209 OUTREG(DDA_VERT_REG, 0x00); 2210 OUTREG(PSTREAM_START_REG, 0x00010001); 2211 OUTREG(PSTREAM_WINDOW_SIZE_REG, streams[19] & 0x07ff07ff); 2212 OUTREG(SSTREAM_START_REG, 0x07ff07ff); 2213 OUTREG(SSTREAM_WINDOW_SIZE_REG, 0x00010001); 2214 2215 2216} 2217 2218 2219 2220 2221/* And this function disables the STREAMS processor as per databook. 2222 * This is usefull before we do a mode change 2223 */ 2224 2225static void 2226S3VDisableSTREAMS(ScrnInfoPtr pScrn) 2227{ 2228unsigned char tmp; 2229 vgaHWPtr hwp = VGAHWPTR(pScrn); 2230 S3VPtr ps3v = S3VPTR(pScrn); 2231 int vgaCRIndex, vgaCRReg, vgaIOBase; 2232 vgaIOBase = hwp->IOBase; 2233 vgaCRIndex = vgaIOBase + 4; 2234 vgaCRReg = vgaIOBase + 5; 2235 2236 VerticalRetraceWait(); 2237 OUTREG(FIFO_CONTROL_REG, 0xC000); 2238 VGAOUT8(vgaCRIndex, 0x67); 2239 tmp = VGAIN8(vgaCRReg); 2240 /* Disable STREAMS processor */ 2241 VGAOUT8( vgaCRReg, tmp & ~0x0C ); 2242 2243 return; 2244} 2245 2246 2247 2248/* MapMem - contains half of pre-4.0 EnterLeave function */ 2249/* The EnterLeave function which en/dis access to IO ports and ext. regs */ 2250 /********************************************************/ 2251 /* Aaagh... So many locations! On my machine (KJB) the*/ 2252 /* following is true. */ 2253 /* PciInfo->memBase[0] returns e400 0000 */ 2254 /* From my ViRGE manual, the memory map looks like */ 2255 /* Linear mem - 16M 000 0000 - 0ff ffff */ 2256 /* Image xfer - 32k 100 0000 - 100 7fff */ 2257 /* PCI cnfg 100 8000 - 100 8043 */ 2258 /* ... */ 2259 /* CRT VGA 3b? reg 100 83b0 - */ 2260 /* And S3_NEWMMIO_VGABASE = S3_NEWMMIO_REGBASE + 0x8000 */ 2261 /* where S3_NEWMMIO_REGBASE = 0x100 0000 ( 16MB ) */ 2262 /* S3_NEWMMIO_REGSIZE = 0x1 0000 ( 64KB ) */ 2263 /* S3V_MMIO_REGSIZE = 0x8000 ( 32KB ) - above includes */ 2264 /* the image transfer area, so this one is used instead.*/ 2265 /* ps3v->IOBase is assinged the virtual address returned*/ 2266 /* from MapPciMem, it is the address to base all */ 2267 /* register access. (It is a pointer.) */ 2268 /* hwp->MemBase is a CARD32, containing the register */ 2269 /* base. (It's a conversion from IOBase above.) */ 2270 /********************************************************/ 2271 2272 2273static Bool 2274S3VMapMem(ScrnInfoPtr pScrn) 2275{ 2276 S3VPtr ps3v; 2277 vgaHWPtr hwp; 2278 2279 PVERB5(" S3VMapMem\n"); 2280 2281 ps3v = S3VPTR(pScrn); 2282 2283 /* Map the ViRGE register space */ 2284 /* Starts with Image Transfer area */ 2285 /* so that we can use registers map */ 2286 /* structure - see newmmio.h */ 2287 /* around 0x10000 from MemBase */ 2288#ifndef XSERVER_LIBPCIACCESS 2289 ps3v->MapBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, ps3v->PciTag, 2290 PCI_REGION_BASE(ps3v->PciInfo, 0, REGION_MEM) + S3_NEWMMIO_REGBASE, 2291 S3_NEWMMIO_REGSIZE); 2292 2293 ps3v->MapBaseDense = xf86MapPciMem(pScrn->scrnIndex, 2294 VIDMEM_MMIO_32BIT, 2295 ps3v->PciTag, 2296 PCI_REGION_BASE(ps3v->PciInfo, 0, REGION_MEM) + S3_NEWMMIO_REGBASE, 2297 0x8000); 2298#else 2299 { 2300 void** result = (void**)&ps3v->MapBase; 2301 int err = pci_device_map_range(ps3v->PciInfo, 2302 PCI_REGION_BASE(ps3v->PciInfo, 0, REGION_MEM) + S3_NEWMMIO_REGBASE, 2303 S3_NEWMMIO_REGSIZE, 2304 PCI_DEV_MAP_FLAG_WRITABLE, 2305 result); 2306 2307 if (err) 2308 return FALSE; 2309 } 2310 ps3v->MapBaseDense = ps3v->MapBase; 2311#endif 2312 2313 if( !ps3v->MapBase ) { 2314 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2315 "Internal error: could not map registers.\n"); 2316 return FALSE; 2317 } 2318 /* Map the framebuffer */ 2319 if (ps3v->videoRambytes) { /* not set in PreInit() */ 2320#ifndef XSERVER_LIBPCIACCESS 2321 ps3v->FBBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 2322 ps3v->PciTag, PCI_REGION_BASE(ps3v->PciInfo, 0, REGION_MEM), 2323 ps3v->videoRambytes ); 2324 2325#else 2326 { 2327 void** result = (void**)&ps3v->FBBase; 2328 int err = pci_device_map_range(ps3v->PciInfo, 2329 PCI_REGION_BASE(ps3v->PciInfo, 0, REGION_MEM), 2330 ps3v->videoRambytes, 2331 PCI_DEV_MAP_FLAG_WRITABLE | 2332 PCI_DEV_MAP_FLAG_WRITE_COMBINE, 2333 result); 2334 2335 if (err) 2336 return FALSE; 2337 } 2338#endif 2339 2340 if( !ps3v->FBBase ) { 2341 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2342 "Internal error: could not map framebuffer.\n"); 2343 return FALSE; 2344 } 2345 /* Initially the visual display start */ 2346 /* is the same as the mapped start. */ 2347 ps3v->FBStart = ps3v->FBBase; 2348 } 2349 2350 pScrn->memPhysBase = PCI_REGION_BASE(ps3v->PciInfo, 0, REGION_MEM); 2351 pScrn->fbOffset = 0; 2352 2353 /* Set up offset to hwcursor memory area */ 2354 /* It's a 1K chunk at the end of the frame buffer */ 2355 ps3v->FBCursorOffset = ps3v->videoRambytes - 1024; 2356 S3VEnableMmio( pScrn); 2357 /* Assign hwp->MemBase & IOBase here */ 2358 hwp = VGAHWPTR(pScrn); 2359 /* Sets MMIOBase and Offset, assigns */ 2360 /* functions. Offset from map area */ 2361 /* to VGA reg area is 0x8000. */ 2362 vgaHWSetMmioFuncs( hwp, ps3v->MapBase, S3V_MMIO_REGSIZE ); 2363 /* assigns hwp->IOBase to 3D0 or 3B0 */ 2364 /* needs hwp->MMIOBase to work */ 2365 vgaHWGetIOBase(hwp); 2366 2367 /* Map the VGA memory when the */ 2368 /* primary video */ 2369 2370 if (xf86IsPrimaryPci(ps3v->PciInfo)) { 2371 hwp->MapSize = 0x10000; 2372 if (!vgaHWMapMem(pScrn)) 2373 return FALSE; 2374 ps3v->PrimaryVidMapped = TRUE; 2375 } 2376 2377 return TRUE; 2378} 2379 2380 2381 2382/* UnMapMem - contains half of pre-4.0 EnterLeave function */ 2383/* The EnterLeave function which en/dis access to IO ports and ext. regs */ 2384 2385static void 2386S3VUnmapMem(ScrnInfoPtr pScrn) 2387{ 2388 S3VPtr ps3v; 2389 2390 ps3v = S3VPTR(pScrn); 2391 /* Unmap VGA mem if mapped. */ 2392 if( ps3v->PrimaryVidMapped ) { 2393 vgaHWUnmapMem( pScrn ); 2394 ps3v->PrimaryVidMapped = FALSE; 2395 } 2396 2397#ifndef XSERVER_LIBPCIACCESS 2398 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)ps3v->MapBase, 2399 S3_NEWMMIO_REGSIZE); 2400#else 2401 pci_device_unmap_range(ps3v->PciInfo, ps3v->MapBase, 2402 S3_NEWMMIO_REGSIZE); 2403#endif 2404 2405#ifndef XSERVER_LIBPCIACCESS 2406 if (ps3v->FBBase) 2407 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)ps3v->FBBase, 2408 ps3v->videoRambytes); 2409 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)ps3v->MapBaseDense, 2410 0x8000); 2411#else 2412 pci_device_unmap_range(ps3v->PciInfo, ps3v->FBBase, 2413 ps3v->videoRambytes); 2414#endif 2415 return; 2416} 2417 2418 2419 2420/* Mandatory */ 2421 2422/* This gets called at the start of each server generation */ 2423 2424static Bool 2425S3VScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) 2426{ 2427 ScrnInfoPtr pScrn; 2428 S3VPtr ps3v; 2429 int ret; 2430 2431 PVERB5(" S3VScreenInit\n"); 2432 /* First get the ScrnInfoRec */ 2433 pScrn = xf86Screens[pScreen->myNum]; 2434 /* Get S3V rec */ 2435 ps3v = S3VPTR(pScrn); 2436 /* Make sure we have card access */ 2437/* xf86EnableAccess(pScrn);*/ 2438 /* Map MMIO regs and framebuffer */ 2439 if( !S3VMapMem(pScrn) ) 2440 return FALSE; 2441 /* Save the chip/graphics state */ 2442 S3VSave(pScrn); 2443 /* Blank the screen during init */ 2444 vgaHWBlankScreen(pScrn, TRUE ); 2445 /* Initialise the first mode */ 2446 if (!S3VModeInit(pScrn, pScrn->currentMode)) 2447 return FALSE; 2448 2449 /* 2450 * The next step is to setup the screen's visuals, and initialise the 2451 * framebuffer code. In cases where the framebuffer's default 2452 * choices for things like visual layouts and bits per RGB are OK, 2453 * this may be as simple as calling the framebuffer's ScreenInit() 2454 * function. If not, the visuals will need to be setup before calling 2455 * a fb ScreenInit() function and fixed up after. 2456 * 2457 * For most PC hardware at depths >= 8, the defaults that fb uses 2458 * are not appropriate. In this driver, we fixup the visuals after. 2459 */ 2460 2461 /* 2462 * Reset the visual list. 2463 */ 2464 miClearVisualTypes(); 2465 2466 /* Setup the visuals we support. */ 2467 2468 /* 2469 * For bpp > 8, the default visuals are not acceptable because we only 2470 * support TrueColor and not DirectColor. To deal with this, call 2471 * miSetVisualTypes with the appropriate visual mask. 2472 */ 2473 2474 if (pScrn->bitsPerPixel > 8) { 2475 if (!miSetVisualTypes(pScrn->depth, TrueColorMask, pScrn->rgbBits, 2476 pScrn->defaultVisual)) 2477 return FALSE; 2478 2479 if (!miSetPixmapDepths ()) 2480 return FALSE; 2481 } else { 2482 if (!miSetVisualTypes(pScrn->depth, 2483 miGetDefaultVisualMask(pScrn->depth), 2484 pScrn->rgbBits, pScrn->defaultVisual)) 2485 return FALSE; 2486 2487 if (!miSetPixmapDepths ()) 2488 return FALSE; 2489 } 2490 2491 ret = S3VInternalScreenInit(scrnIndex, pScreen); 2492 2493 if (!ret) 2494 return FALSE; 2495 2496 xf86SetBlackWhitePixels(pScreen); 2497 2498 if (pScrn->bitsPerPixel > 8) { 2499 VisualPtr visual; 2500 /* Fixup RGB ordering */ 2501 visual = pScreen->visuals + pScreen->numVisuals; 2502 while (--visual >= pScreen->visuals) { 2503 if ((visual->class | DynamicClass) == DirectColor) { 2504 visual->offsetRed = pScrn->offset.red; 2505 visual->offsetGreen = pScrn->offset.green; 2506 visual->offsetBlue = pScrn->offset.blue; 2507 visual->redMask = pScrn->mask.red; 2508 visual->greenMask = pScrn->mask.green; 2509 visual->blueMask = pScrn->mask.blue; 2510 } 2511 } 2512 } 2513 2514 /* must be after RGB ordering fixed */ 2515 fbPictureInit (pScreen, 0, 0); 2516 2517 /* Initialize acceleration layer */ 2518 if (!ps3v->NoAccel) { 2519 if(pScrn->bitsPerPixel == 32) { 2520 /* 32 bit Accel currently broken 2521 if (!S3VAccelInit32(pScreen)) 2522 return FALSE; 2523 */ 2524 ; 2525 } else 2526 if (!S3VAccelInit(pScreen)) 2527 return FALSE; 2528 } 2529 2530 miInitializeBackingStore(pScreen); 2531 xf86SetBackingStore(pScreen); 2532 xf86SetSilkenMouse(pScreen); 2533 /* hardware cursor needs to wrap this layer */ 2534 S3VDGAInit(pScreen); 2535 2536 /* Initialise cursor functions */ 2537 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 2538 2539 /* Initialize HW cursor layer. 2540 Must follow software cursor initialization*/ 2541 if (ps3v->hwcursor) { 2542 if(!S3VHWCursorInit(pScreen)) { 2543 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2544 "Hardware cursor initialization failed\n"); 2545 } 2546 } 2547 2548 if (ps3v->shadowFB) { 2549 RefreshAreaFuncPtr refreshArea = s3vRefreshArea; 2550 2551 if(ps3v->rotate) { 2552 if (!ps3v->PointerMoved) { 2553 ps3v->PointerMoved = pScrn->PointerMoved; 2554 pScrn->PointerMoved = s3vPointerMoved; 2555 } 2556 2557 switch(pScrn->bitsPerPixel) { 2558 case 8: refreshArea = s3vRefreshArea8; break; 2559 case 16: refreshArea = s3vRefreshArea16; break; 2560 case 24: refreshArea = s3vRefreshArea24; break; 2561 case 32: refreshArea = s3vRefreshArea32; break; 2562 } 2563 } 2564 2565 ShadowFBInit(pScreen, refreshArea); 2566 } 2567 2568 /* Initialise default colourmap */ 2569 if (!miCreateDefColormap(pScreen)) 2570 return FALSE; 2571 /* Initialize colormap layer. */ 2572 /* Must follow initialization */ 2573 /* of the default colormap. */ 2574 /* And SetGamma call, else it */ 2575 /* will load palette with solid */ 2576 /* white. */ 2577 if(!xf86HandleColormaps(pScreen, 256, 6, S3VLoadPalette, NULL, 2578 CMAP_RELOAD_ON_MODE_SWITCH )) 2579 return FALSE; 2580 /* All the ugly stuff is done, */ 2581 /* so re-enable the screen. */ 2582 vgaHWBlankScreen(pScrn, FALSE ); 2583 2584#if 0 2585 pScrn->racMemFlags = RAC_COLORMAP | RAC_CURSOR | RAC_FB | RAC_VIEWPORT; 2586#endif 2587 pScreen->SaveScreen = S3VSaveScreen; 2588 2589 /* Wrap the current CloseScreen function */ 2590 ps3v->CloseScreen = pScreen->CloseScreen; 2591 pScreen->CloseScreen = S3VCloseScreen; 2592 2593 if(xf86DPMSInit(pScreen, S3VDisplayPowerManagementSet, 0) == FALSE) 2594 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DPMS initialization failed!\n"); 2595 2596 S3VInitVideo(pScreen); 2597 2598 /* Report any unused options (only for the first generation) */ 2599 if (serverGeneration == 1) { 2600 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 2601 } 2602 /* Done */ 2603 return TRUE; 2604} 2605 2606 2607 2608/* Common init routines needed in EnterVT and ScreenInit */ 2609 2610static int 2611S3VInternalScreenInit( int scrnIndex, ScreenPtr pScreen) 2612{ 2613 int ret = TRUE; 2614 ScrnInfoPtr pScrn; 2615 S3VPtr ps3v; 2616 int width, height, displayWidth; 2617 unsigned char* FBStart; 2618 2619 /* First get the ScrnInfoRec */ 2620 pScrn = xf86Screens[pScreen->myNum]; 2621 2622 ps3v = S3VPTR(pScrn); 2623 2624 displayWidth = pScrn->displayWidth; 2625 if (ps3v->rotate) { 2626 height = pScrn->virtualX; 2627 width = pScrn->virtualY; 2628 } else { 2629 width = pScrn->virtualX; 2630 height = pScrn->virtualY; 2631 } 2632 2633 if(ps3v->shadowFB) { 2634 ps3v->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); 2635 ps3v->ShadowPtr = xalloc(ps3v->ShadowPitch * height); 2636 displayWidth = ps3v->ShadowPitch / (pScrn->bitsPerPixel >> 3); 2637 FBStart = ps3v->ShadowPtr; 2638 } else { 2639 ps3v->ShadowPtr = NULL; 2640 FBStart = ps3v->FBStart; 2641 } 2642 2643 /* 2644 * Call the framebuffer layer's ScreenInit function, and fill in other 2645 * pScreen fields. 2646 */ 2647 2648 switch (pScrn->bitsPerPixel) 2649 { 2650 case 8: 2651 case 16: 2652 case 24: 2653 case 32: 2654 ret = fbScreenInit(pScreen, FBStart, width, 2655 height, pScrn->xDpi, pScrn->yDpi, 2656 displayWidth, pScrn->bitsPerPixel); 2657 break; 2658 default: 2659 xf86DrvMsg(scrnIndex, X_ERROR, 2660 "Internal error: invalid bpp (%d) in S3VScreenInit\n", 2661 pScrn->bitsPerPixel); 2662 ret = FALSE; 2663 break; 2664 } 2665 2666 return ret; 2667} 2668 2669 2670 2671/* Checks if a mode is suitable for the selected chipset. */ 2672 2673static ModeStatus 2674S3VValidMode(int index, DisplayModePtr mode, Bool verbose, int flags) 2675{ 2676 ScrnInfoPtr pScrn = xf86Screens[index]; 2677 2678 if ((pScrn->bitsPerPixel + 7)/8 * mode->HDisplay > 4095) 2679 return MODE_VIRTUAL_X; 2680 2681 return MODE_OK; 2682} 2683 2684 2685 2686static Bool 2687S3VModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 2688{ 2689 vgaHWPtr hwp = VGAHWPTR(pScrn); 2690 S3VPtr ps3v = S3VPTR(pScrn); 2691 int width, dclk; 2692 int i, j; 2693 unsigned char tmp = 0; 2694 2695 /* Store values to current mode register structs */ 2696 S3VRegPtr new = &ps3v->ModeReg; 2697 vgaRegPtr vganew = &hwp->ModeReg; 2698 int vgaCRIndex, vgaCRReg, vgaIOBase; 2699 2700 vgaIOBase = hwp->IOBase; 2701 vgaCRIndex = vgaIOBase + 4; 2702 vgaCRReg = vgaIOBase + 5; 2703 2704 PVERB5(" S3VModeInit\n"); 2705 2706 /* Set scale factors for mode timings */ 2707 2708 if (ps3v->Chipset == S3_ViRGE_VX || S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 2709 S3_ViRGE_MX_SERIES(ps3v->Chipset)) { 2710 ps3v->HorizScaleFactor = 1; 2711 } 2712 else if (pScrn->bitsPerPixel == 8) { 2713 ps3v->HorizScaleFactor = 1; 2714 } 2715 else if (pScrn->bitsPerPixel == 16) { 2716 if (S3_TRIO_3D_SERIES(ps3v->Chipset) && mode->Clock > 115000) 2717 ps3v->HorizScaleFactor = 1; 2718 else 2719 ps3v->HorizScaleFactor = 2; 2720 } 2721 else { 2722 ps3v->HorizScaleFactor = 1; 2723 } 2724 2725 2726 /* First we adjust the horizontal timings if needed */ 2727 2728 if(ps3v->HorizScaleFactor != 1) 2729 if (!mode->CrtcHAdjusted) { 2730 mode->CrtcHDisplay *= ps3v->HorizScaleFactor; 2731 mode->CrtcHSyncStart *= ps3v->HorizScaleFactor; 2732 mode->CrtcHSyncEnd *= ps3v->HorizScaleFactor; 2733 mode->CrtcHTotal *= ps3v->HorizScaleFactor; 2734 mode->CrtcHSkew *= ps3v->HorizScaleFactor; 2735 mode->CrtcHAdjusted = TRUE; 2736 } 2737 2738 if(!vgaHWInit (pScrn, mode)) 2739 return FALSE; 2740 2741 /* Now we fill in the rest of the stuff we need for the virge */ 2742 /* Start with MMIO, linear addr. regs */ 2743 2744 VGAOUT8(vgaCRIndex, 0x3a); 2745 tmp = VGAIN8(vgaCRReg); 2746 if( S3_ViRGE_GX2_SERIES(ps3v->Chipset) 2747 /* MXTESTME */ || S3_ViRGE_MX_SERIES(ps3v->Chipset) ) 2748 { 2749 if(ps3v->pci_burst) 2750 /*new->CR3A = (tmp & 0x38) | 0x10; / ENH 256, PCI burst */ 2751 /* Don't clear reserved bits... */ 2752 new->CR3A = (tmp & 0x7f) | 0x10; /* ENH 256, PCI burst */ 2753 else 2754 new->CR3A = tmp | 0x90; /* ENH 256, no PCI burst! */ 2755 } 2756 else 2757 { 2758 if(ps3v->pci_burst) 2759 new->CR3A = (tmp & 0x7f) | 0x15; /* ENH 256, PCI burst */ 2760 else 2761 new->CR3A = tmp | 0x95; /* ENH 256, no PCI burst! */ 2762 } 2763 2764 2765 VGAOUT8(vgaCRIndex, 0x55); 2766 new->CR55 = VGAIN8(vgaCRReg); 2767 if (ps3v->hwcursor) 2768 new->CR55 |= 0x10; /* Enables X11 hw cursor mode */ 2769 if (S3_TRIO_3D_SERIES(ps3v->Chipset)) { 2770 new->CR31 = 0x0c; /* [trio3d] page 54 */ 2771 } else { 2772 new->CR53 = 0x08; /* Enables MMIO */ 2773 new->CR31 = 0x8c; /* Dis. 64k window, en. ENH maps */ 2774 } 2775 2776 /* Enables S3D graphic engine and PCI disconnects */ 2777 if(ps3v->Chipset == S3_ViRGE_VX){ 2778 new->CR66 = 0x90; 2779 new->CR63 = 0x09; 2780 } 2781 else { 2782 new->CR66 = 0x89; 2783 /* Set display fifo */ 2784 if( S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 2785 S3_ViRGE_MX_SERIES(ps3v->Chipset) ) 2786 { 2787 /* Changed from 0x08 based on reports that this */ 2788 /* prevents MX from running properly below 1024x768 */ 2789 new->CR63 = 0x10; 2790 } 2791 else 2792 { 2793 new->CR63 = 0; 2794 } 2795 } 2796 2797 /* Now set linear addr. registers */ 2798 /* LAW size: we have 2 cases, 2MB, 4MB or >= 4MB for VX */ 2799 VGAOUT8(vgaCRIndex, 0x58); 2800 new->CR58 = VGAIN8(vgaCRReg) & 0x80; 2801 if(pScrn->videoRam == 2048){ 2802 new->CR58 |= 0x02 | 0x10; 2803 } 2804 else if (pScrn->videoRam == 1024) { 2805 new->CR58 |= 0x01 | 0x10; 2806 } 2807 else { 2808 if (S3_TRIO_3D_2X_SERIES(ps3v->Chipset) && pScrn->videoRam == 8192) 2809 new->CR58 |= 0x07 | 0x10; /* 8MB window on Trio3D/2X */ 2810 else 2811 new->CR58 |= 0x03 | 0x10; /* 4MB window on virge, 8MB on VX */ 2812 } 2813 if(ps3v->Chipset == S3_ViRGE_VX) 2814 new->CR58 |= 0x40; 2815 if (ps3v->early_ras_precharge) 2816 new->CR58 |= 0x80; 2817 if (ps3v->late_ras_precharge) 2818 new->CR58 &= 0x7f; 2819 2820 /* ** On PCI bus, no need to reprogram the linear window base address */ 2821 2822 /* Now do clock PLL programming. Use the s3gendac function to get m,n */ 2823 /* Also determine if we need doubling etc. */ 2824 2825 dclk = mode->Clock; 2826 new->CR67 = 0x00; /* Defaults */ 2827 2828 if (!S3_TRIO_3D_SERIES(ps3v->Chipset)) 2829 new->SR15 = 0x03 | 0x80; 2830 else { 2831 VGAOUT8(0x3c4, 0x15); 2832 new->SR15 = VGAIN8(0x3c5); 2833 VGAOUT8(0x3c4, 0x0a); 2834 new->SR0A = VGAIN8(0x3c5); 2835 if (ps3v->slow_dram) { 2836 new->SR15 = 0x03; /* 3 CYC MWR */ 2837 new->SR0A &= 0x7F; 2838 } else if (ps3v->fast_dram) { 2839 new->SR15 = 0x03 | 0x80; /* 2 CYC MWR */ 2840 new->SR0A |= 0x80; 2841 } else { /* keep BIOS init defaults */ 2842 new->SR15 = (new->SR15 & 0x80) | 0x03; 2843 } 2844 } 2845 new->SR18 = 0x00; 2846 new->CR43 = 0x00; 2847 new->CR45 = 0x00; 2848 /* Enable MMIO to RAMDAC registers */ 2849 new->CR65 = 0x00; /* CR65_2 must be zero, doc seems to be wrong */ 2850 new->CR54 = 0x00; 2851 2852 if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 2853 /* S3_ViRGE_MX_SERIES(ps3v->Chipset) || CR40 reserved on MX */ 2854 S3_ViRGE_MXP_SERIES(ps3v->Chipset) || 2855 S3_ViRGE_VX_SERIES(ps3v->Chipset) || 2856 /* S3_TRIO_3D_2X_SERIES(ps3v->Chipset) * included in GX2 series */ 2857 ps3v->Chipset == S3_ViRGE_DXGX || 2858 ps3v->Chipset == S3_ViRGE 2859 ) { 2860 VGAOUT8(vgaCRIndex, 0x40); 2861 new->CR40 = VGAIN8(vgaCRReg) & ~0x01; 2862 } 2863 2864 if (S3_ViRGE_MX_SERIES(ps3v->Chipset)) { 2865 /* fix problems with APM suspend/resume trashing CR90/91 */ 2866 switch(pScrn->bitsPerPixel) { 2867 case 8: new->CR41 = 0x38; break; 2868 case 15: new->CR41 = 0x58; break; 2869 case 16: new->CR41 = 0x48; break; 2870 default: new->CR41 = 0x77; 2871 } 2872 } 2873 2874 xf86ErrorFVerb(VERBLEV, " S3VModeInit dclk=%i \n", 2875 dclk 2876 ); 2877 2878 /* Memory controller registers. Optimize for better graphics engine 2879 * performance. These settings are adjusted/overridden below for other bpp/ 2880 * XConfig options.The idea here is to give a longer number of contiguous 2881 * MCLK's to both refresh and the graphics engine, to diminish the 2882 * relative penalty of 3 or 4 mclk's needed to setup memory transfers. 2883 */ 2884 new->MMPR0 = 0x010400; /* defaults */ 2885 new->MMPR1 = 0x00; 2886 new->MMPR2 = 0x0808; 2887 new->MMPR3 = 0x08080810; 2888 2889 /* 2890 * These settings look like they ought to be better adjusted for depth, 2891 * so for problem modes running without any fifo_ option should be 2892 * usable. Note that these adjust some memory timings and relate to 2893 * the boards MCLK setting. 2894 * */ 2895 if( ps3v->fifo_aggressive || ps3v->fifo_moderate || 2896 ps3v->fifo_conservative ) { 2897 2898 new->MMPR1 = 0x0200; /* Low P. stream waits before filling */ 2899 new->MMPR2 = 0x1808; /* Let the FIFO refill itself */ 2900 new->MMPR3 = 0x08081810; /* And let the GE hold the bus for a while */ 2901 } 2902 2903 /* And setup here the new value for MCLK. We use the XConfig 2904 * option "set_mclk", whose value gets stored in ps3v->MCLK. 2905 * I'm not sure what the maximum "permitted" value should be, probably 2906 * 100 MHz is more than enough for now. 2907 */ 2908 2909 if(ps3v->MCLK> 0) { 2910 if (S3_ViRGE_MX_SERIES(ps3v->Chipset)) 2911 S3VCommonCalcClock(pScrn, mode, 2912 (int)(ps3v->MCLK / ps3v->refclk_fact), 2913 1, 1, 31, 0, 3, 2914 135000, 270000, &new->SR11, &new->SR10); 2915 else 2916 S3VCommonCalcClock(pScrn, mode, ps3v->MCLK, 1, 1, 31, 0, 3, 2917 135000, 270000, &new->SR11, &new->SR10); 2918 } 2919 else { 2920 new->SR10 = 255; /* This is a reserved value, so we use as flag */ 2921 new->SR11 = 255; 2922 } 2923 2924 /* most modes don't need STREAMS */ 2925 /* processor, preset FALSE */ 2926 /* support for XVideo needs streams, so added it to some modes */ 2927 ps3v->NeedSTREAMS = FALSE; 2928 2929 if(ps3v->Chipset == S3_ViRGE_VX){ 2930 if (pScrn->bitsPerPixel == 8) { 2931 if (dclk <= 110000) new->CR67 = 0x00; /* 8bpp, 135MHz */ 2932 else new->CR67 = 0x10; /* 8bpp, 220MHz */ 2933 } 2934 else if ((pScrn->bitsPerPixel == 16) && (pScrn->weight.green == 5)) { 2935 if (dclk <= 110000) new->CR67 = 0x20; /* 15bpp, 135MHz */ 2936 else new->CR67 = 0x30; /* 15bpp, 220MHz */ 2937 } 2938 else if (pScrn->bitsPerPixel == 16) { 2939 if (dclk <= 110000) new->CR67 = 0x40; /* 16bpp, 135MHz */ 2940 else new->CR67 = 0x50; /* 16bpp, 220MHz */ 2941 } 2942 else if ((pScrn->bitsPerPixel == 24) || (pScrn->bitsPerPixel == 32)) { 2943 new->CR67 = 0xd0 | 0x0c; /* 24bpp, 135MHz, STREAMS */ 2944 /* Flag STREAMS proc. required */ 2945 ps3v->NeedSTREAMS = TRUE; 2946 S3VInitSTREAMS(pScrn, new->STREAMS, mode); 2947 new->MMPR0 = 0xc098; /* Adjust FIFO slots */ 2948 } 2949 S3VCommonCalcClock(pScrn, mode, dclk, 1, 1, 31, 0, 4, 2950 220000, 440000, &new->SR13, &new->SR12); 2951 2952 } /* end VX if() */ 2953 else if (S3_ViRGE_GX2_SERIES(ps3v->Chipset) || S3_ViRGE_MX_SERIES(ps3v->Chipset)) { 2954 if (pScrn->bitsPerPixel == 8) 2955 new->CR67 = 0x00; 2956 else if (pScrn->bitsPerPixel == 16) { 2957 /* XV support needs STREAMS in depth 16 */ 2958 ps3v->NeedSTREAMS = TRUE; 2959 S3VInitSTREAMS(pScrn, new->STREAMS, mode); 2960 if (pScrn->weight.green == 5) 2961 new->CR67 = 0x30 | 0x4; /* 15bpp */ 2962 else 2963 new->CR67 = 0x50 | 0x4; /* 16bpp */ 2964 } 2965 else if ((pScrn->bitsPerPixel == 24) ) { 2966 new->CR67 = 0x74; /* 24bpp, STREAMS */ 2967 /* Flag STREAMS proc. required */ 2968 ps3v->NeedSTREAMS = TRUE; 2969 S3VInitSTREAMS(pScrn, new->STREAMS, mode); 2970 } 2971 else if (pScrn->bitsPerPixel == 32) { 2972 new->CR67 = 0xd0; /* 32bpp */ 2973 /* Missing STREAMs and other stuff here? KJB */ 2974 /* new->MMPR0 = 0xc098; / Adjust FIFO slots */ 2975 } 2976 { 2977 unsigned char ndiv; 2978 if (S3_ViRGE_MX_SERIES(ps3v->Chipset)) { 2979 unsigned char sr8; 2980 VGAOUT8(0x3c4, 0x08); /* unlock extended SEQ regs */ 2981 sr8 = VGAIN8(0x3c5); 2982 VGAOUT8(0x3c5, 0x06); 2983 VGAOUT8(0x3c4, 0x31); 2984 if (VGAIN8(0x3c5) & 0x10) { /* LCD on */ 2985 if (!ps3v->LCDClk) { /* entered only once for first mode */ 2986 int h_lcd, v_lcd; 2987 VGAOUT8(0x3c4, 0x61); 2988 h_lcd = VGAIN8(0x3c5); 2989 VGAOUT8(0x3c4, 0x66); 2990 h_lcd |= ((VGAIN8(0x3c5) & 0x02) << 7); 2991 h_lcd = (h_lcd+1) * 8; 2992 VGAOUT8(0x3c4, 0x69); 2993 v_lcd = VGAIN8(0x3c5); 2994 VGAOUT8(0x3c4, 0x6e); 2995 v_lcd |= ((VGAIN8(0x3c5) & 0x70) << 4); 2996 v_lcd++; 2997 2998 /* check if first mode has physical LCD resolution */ 2999 if (pScrn->modes->HDisplay == h_lcd && pScrn->modes->VDisplay == v_lcd) 3000 ps3v->LCDClk = mode->Clock; 3001 else { 3002 int n1, n2, sr12, sr13, sr29; 3003 VGAOUT8(0x3c4, 0x12); 3004 sr12 = VGAIN8(0x3c5); 3005 VGAOUT8(0x3c4, 0x13); 3006 sr13 = VGAIN8(0x3c5) & 0x7f; 3007 VGAOUT8(0x3c4, 0x29); 3008 sr29 = VGAIN8(0x3c5); 3009 n1 = sr12 & 0x1f; 3010 n2 = ((sr12>>6) & 0x03) | ((sr29 & 0x01) << 2); 3011 ps3v->LCDClk = ((int)(ps3v->refclk_fact * 1431818 * (sr13+2)) / (n1+2) / (1 << n2) + 50) / 100; 3012 } 3013 } 3014 S3VCommonCalcClock(pScrn, mode, 3015 (int)(ps3v->LCDClk / ps3v->refclk_fact), 3016 1, 1, 31, 0, 4, 3017 170000, 340000, &new->SR13, &ndiv); 3018 } 3019 else 3020 S3VCommonCalcClock(pScrn, mode, 3021 (int)(dclk / ps3v->refclk_fact), 3022 1, 1, 31, 0, 4, 3023 170000, 340000, &new->SR13, &ndiv); 3024 VGAOUT8(0x3c4, 0x08); 3025 VGAOUT8(0x3c5, sr8); 3026 } 3027 else /* S3_ViRGE_GX2 */ 3028 S3VCommonCalcClock(pScrn, mode, dclk, 1, 1, 31, 0, 4, 3029 170000, 340000, &new->SR13, &ndiv); 3030 new->SR29 = ndiv >> 7; 3031 new->SR12 = (ndiv & 0x1f) | ((ndiv & 0x60) << 1); 3032 } 3033 } /* end GX2 or MX if() */ 3034 else if(S3_TRIO_3D_SERIES(ps3v->Chipset)) { 3035 new->SR0F = 0x00; 3036 if (pScrn->bitsPerPixel == 8) { 3037 if(dclk > 115000) { /* We need pixmux */ 3038 new->CR67 = 0x10; 3039 new->SR15 |= 0x10; /* Set DCLK/2 bit */ 3040 new->SR18 = 0x80; /* Enable pixmux */ 3041 } 3042 } 3043 else if ((pScrn->bitsPerPixel == 16) && (pScrn->weight.green == 5)) { 3044 if(dclk > 115000) { 3045 new->CR67 = 0x20; 3046 new->SR15 |= 0x10; 3047 new->SR18 = 0x80; 3048 new->SR0F = 0x10; 3049 } else { 3050 new->CR67 = 0x30; /* 15bpp */ 3051 } 3052 } 3053 else if (pScrn->bitsPerPixel == 16) { 3054 if(dclk > 115000) { 3055 new->CR67 = 0x40; 3056 new->SR15 |= 0x10; 3057 new->SR18 = 0x80; 3058 new->SR0F = 0x10; 3059 } else { 3060 new->CR67 = 0x50; 3061 } 3062 } 3063 else if (pScrn->bitsPerPixel == 24) { 3064 new->CR67 = 0xd0 | 0x0c; 3065 ps3v->NeedSTREAMS = TRUE; 3066 S3VInitSTREAMS(pScrn, new->STREAMS, mode); 3067 new->MMPR0 = 0xc000; /* Adjust FIFO slots */ 3068 } 3069 else if (pScrn->bitsPerPixel == 32) { 3070 new->CR67 = 0xd0 | 0x0c; 3071 ps3v->NeedSTREAMS = TRUE; 3072 S3VInitSTREAMS(pScrn, new->STREAMS, mode); 3073 new->MMPR0 = 0x10000; /* Still more FIFO slots */ 3074 new->SR0F = 0x10; 3075 } 3076 S3VCommonCalcClock(pScrn, mode, dclk, 1, 1, 31, 0, 4, 3077 230000, 460000, &new->SR13, &new->SR12); 3078 } /* end TRIO_3D if() */ 3079 else if(ps3v->Chipset == S3_ViRGE_DXGX) { 3080 if (pScrn->bitsPerPixel == 8) { 3081 if(dclk > 80000) { /* We need pixmux */ 3082 new->CR67 = 0x10; 3083 new->SR15 |= 0x10; /* Set DCLK/2 bit */ 3084 new->SR18 = 0x80; /* Enable pixmux */ 3085 } 3086 } 3087 else if ((pScrn->bitsPerPixel == 16) && (pScrn->weight.green == 5)) { 3088 new->CR67 = 0x30; /* 15bpp */ 3089 } 3090 else if (pScrn->bitsPerPixel == 16) { 3091 if(mode->Flags & V_DBLSCAN) 3092 { 3093 new->CR67 = 0x50; 3094 } 3095 else 3096 { 3097 new->CR67 = 0x50 | 0x0c; 3098 /* Flag STREAMS proc. required */ 3099 /* XV support needs STREAMS in depth 16 */ 3100 ps3v->NeedSTREAMS = TRUE; 3101 S3VInitSTREAMS(pScrn, new->STREAMS, mode); 3102 } 3103 if( ps3v->XVideo ) 3104 { 3105 new->MMPR0 = 0x107c02; /* Adjust FIFO slots, overlay */ 3106 } 3107 else 3108 { 3109 new->MMPR0 = 0xc000; /* Adjust FIFO slots */ 3110 } 3111 } 3112 else if (pScrn->bitsPerPixel == 24) { 3113 new->CR67 = 0xd0 | 0x0c; 3114 /* Flag STREAMS proc. required */ 3115 ps3v->NeedSTREAMS = TRUE; 3116 S3VInitSTREAMS(pScrn, new->STREAMS, mode); 3117 if( ps3v->XVideo ) 3118 { 3119 new->MMPR0 = 0x107c02; /* Adjust FIFO slots, overlay */ 3120 } 3121 else 3122 { 3123 new->MMPR0 = 0xc000; /* Adjust FIFO slots */ 3124 } 3125 } 3126 else if (pScrn->bitsPerPixel == 32) { 3127 new->CR67 = 0xd0 | 0x0c; 3128 /* Flag STREAMS proc. required */ 3129 ps3v->NeedSTREAMS = TRUE; 3130 S3VInitSTREAMS(pScrn, new->STREAMS, mode); 3131 new->MMPR0 = 0x10000; /* Still more FIFO slots */ 3132 } 3133 S3VCommonCalcClock(pScrn, mode, dclk, 1, 1, 31, 0, 3, 3134 135000, 270000, &new->SR13, &new->SR12); 3135 } /* end DXGX if() */ 3136 else { /* Everything else ... (only ViRGE) */ 3137 if (pScrn->bitsPerPixel == 8) { 3138 if(dclk > 80000) { /* We need pixmux */ 3139 new->CR67 = 0x10; 3140 new->SR15 |= 0x10; /* Set DCLK/2 bit */ 3141 new->SR18 = 0x80; /* Enable pixmux */ 3142 } 3143 } 3144 else if ((pScrn->bitsPerPixel == 16) && (pScrn->weight.green == 5)) { 3145 new->CR67 = 0x30; /* 15bpp */ 3146 } 3147 else if (pScrn->bitsPerPixel == 16) { 3148 new->CR67 = 0x50; 3149 } 3150 else if (pScrn->bitsPerPixel == 24) { 3151 new->CR67 = 0xd0 | 0x0c; 3152 /* Flag STREAMS proc. required */ 3153 ps3v->NeedSTREAMS = TRUE; 3154 S3VInitSTREAMS(pScrn, new->STREAMS, mode); 3155 new->MMPR0 = 0xc000; /* Adjust FIFO slots */ 3156 } 3157 else if (pScrn->bitsPerPixel == 32) { 3158 new->CR67 = 0xd0 | 0x0c; 3159 /* Flag STREAMS proc. required */ 3160 ps3v->NeedSTREAMS = TRUE; 3161 S3VInitSTREAMS(pScrn, new->STREAMS, mode); 3162 new->MMPR0 = 0x10000; /* Still more FIFO slots */ 3163 } 3164 S3VCommonCalcClock(pScrn, mode, dclk, 1, 1, 31, 0, 3, 3165 135000, 270000, &new->SR13, &new->SR12); 3166 } /* end great big if()... */ 3167 3168 3169 /* Now adjust the value of the FIFO based upon options specified */ 3170 if( ps3v->fifo_moderate ) { 3171 if(pScrn->bitsPerPixel < 24) 3172 new->MMPR0 -= 0x8000; 3173 else 3174 new->MMPR0 -= 0x4000; 3175 } 3176 else if( ps3v->fifo_aggressive ) { 3177 if(pScrn->bitsPerPixel < 24) 3178 new->MMPR0 -= 0xc000; 3179 else 3180 new->MMPR0 -= 0x6000; 3181 } 3182 3183 /* If we have an interlace mode, set the interlace bit. Note that mode 3184 * vertical timings are already adjusted by the standard VGA code 3185 */ 3186 if(mode->Flags & V_INTERLACE) { 3187 new->CR42 = 0x20; /* Set interlace mode */ 3188 } 3189 else { 3190 new->CR42 = 0x00; 3191 } 3192 3193 if(S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 3194 S3_ViRGE_MX_SERIES(ps3v->Chipset) ) 3195 { 3196 new->CR34 = 0; 3197 } 3198 else 3199 { 3200 /* Set display fifo */ 3201 new->CR34 = 0x10; 3202 } 3203 /* Now we adjust registers for extended mode timings */ 3204 /* This is taken without change from the accel/s3_virge code */ 3205 3206 i = ((((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8) | 3207 ((((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) | 3208 ((((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) | 3209 ((mode->CrtcHSyncStart & 0x800) >> 7); 3210 3211 if ((mode->CrtcHSyncEnd >> 3) - (mode->CrtcHSyncStart >> 3) > 64) 3212 i |= 0x08; /* add another 64 DCLKs to blank pulse width */ 3213 3214 if ((mode->CrtcHSyncEnd >> 3) - (mode->CrtcHSyncStart >> 3) > 32) 3215 i |= 0x20; /* add another 32 DCLKs to hsync pulse width */ 3216 3217 /* video playback chokes if sync start and display end are equal */ 3218 if (mode->CrtcHSyncStart - mode->CrtcHDisplay < ps3v->HorizScaleFactor) { 3219 int tmp = vganew->CRTC[4] + ((i&0x10)<<4) + ps3v->HorizScaleFactor; 3220 vganew->CRTC[4] = tmp & 0xff; 3221 i |= ((tmp >> 4) & 0x10); 3222 } 3223 3224 j = ( vganew->CRTC[0] + ((i&0x01)<<8) 3225 + vganew->CRTC[4] + ((i&0x10)<<4) + 1) / 2; 3226 3227 if (j-(vganew->CRTC[4] + ((i&0x10)<<4)) < 4) { 3228 if (vganew->CRTC[4] + ((i&0x10)<<4) + 4 <= vganew->CRTC[0]+ ((i&0x01)<<8)) 3229 j = vganew->CRTC[4] + ((i&0x10)<<4) + 4; 3230 else 3231 j = vganew->CRTC[0]+ ((i&0x01)<<8) + 1; 3232 } 3233 new->CR3B = j & 0xFF; 3234 i |= (j & 0x100) >> 2; 3235 new->CR3C = (vganew->CRTC[0] + ((i&0x01)<<8))/2; 3236 new->CR5D = i; 3237 3238 new->CR5E = (((mode->CrtcVTotal - 2) & 0x400) >> 10) | 3239 (((mode->CrtcVDisplay - 1) & 0x400) >> 9) | 3240 (((mode->CrtcVSyncStart) & 0x400) >> 8) | 3241 (((mode->CrtcVSyncStart) & 0x400) >> 6) | 0x40; 3242 3243 3244 width = (pScrn->displayWidth * (pScrn->bitsPerPixel / 8))>> 3; 3245 vganew->CRTC[19] = 0xFF & width; 3246 new->CR51 = (0x300 & width) >> 4; /* Extension bits */ 3247 3248 /* Set doublescan */ 3249 if( mode->Flags & V_DBLSCAN) 3250 vganew->CRTC[9] |= 0x80; 3251 3252 /* And finally, select clock source 2 for programmable PLL */ 3253 vganew->MiscOutReg |= 0x0c; 3254 3255 3256 new->CR33 = 0x20; 3257 if (S3_TRIO_3D_2X_SERIES(ps3v->Chipset) || S3_ViRGE_GX2_SERIES(ps3v->Chipset) 3258 /* MXTESTME */ || S3_ViRGE_MX_SERIES(ps3v->Chipset) ) 3259 { 3260 new->CR85 = 0x12; /* avoid sreen flickering */ 3261 /* by increasing FIFO filling, larger # fills FIFO from memory earlier */ 3262 /* on GX2 this affects all depths, not just those running STREAMS. */ 3263 /* new, secondary stream settings. */ 3264 new->CR87 = 0x10; 3265 /* gx2 - set up in XV init code */ 3266 new->CR92 = 0x00; 3267 new->CR93 = 0x00; 3268 /* gx2 primary mclk timeout, def=0xb */ 3269 new->CR7B = 0xb; 3270 /* gx2 secondary mclk timeout, def=0xb */ 3271 new->CR7D = 0xb; 3272 } 3273 if (ps3v->Chipset == S3_ViRGE_DXGX || S3_TRIO_3D_SERIES(ps3v->Chipset)) { 3274 new->CR86 = 0x80; /* disable DAC power saving to avoid bright left edge */ 3275 } 3276 if (ps3v->Chipset == S3_ViRGE_DXGX || S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 3277 S3_ViRGE_MX_SERIES(ps3v->Chipset) || S3_TRIO_3D_SERIES(ps3v->Chipset)) { 3278 int dbytes = pScrn->displayWidth * ((pScrn->bitsPerPixel+7)/8); 3279 new->CR91 = (dbytes + 7) / 8; 3280 new->CR90 = (((dbytes + 7) / 8) >> 8) | 0x80; 3281 } 3282 3283 3284 /* Now we handle various XConfig memory options and others */ 3285 3286 VGAOUT8(vgaCRIndex, 0x36); 3287 new->CR36 = VGAIN8(vgaCRReg); 3288 /* option "slow_edodram" sets EDO to 2 cycle mode on ViRGE */ 3289 if (ps3v->Chipset == S3_ViRGE) { 3290 if( ps3v->slow_edodram ) 3291 new->CR36 = (new->CR36 & 0xf3) | 0x08; 3292 else 3293 new->CR36 &= 0xf3; 3294 } 3295 3296 /* Option "fpm_vram" for ViRGE_VX sets memory in fast page mode */ 3297 if (ps3v->Chipset == S3_ViRGE_VX) { 3298 if( ps3v->fpm_vram ) 3299 new->CR36 |= 0x0c; 3300 else 3301 new->CR36 &= ~0x0c; 3302 } 3303 3304 /* S3_INVERT_VCLK was defaulted to 0 */ 3305 /* in 3.3.3 and never changed. */ 3306 /* Also, bit 0 is never set in 3.9Nm, */ 3307 /* so I left this out for 4.0. */ 3308#if 0 3309 if (mode->Private[0] & (1 << S3_INVERT_VCLK)) { 3310 if (mode->Private[S3_INVERT_VCLK]) 3311 new->CR67 |= 1; 3312 else 3313 new->CR67 &= ~1; 3314 } 3315#endif 3316 /* S3_BLANK_DELAY settings based on */ 3317 /* defaults only. From 3.3.3 */ 3318 { 3319 int blank_delay; 3320 3321 if(ps3v->Chipset == S3_ViRGE_VX) 3322 /* these values need to be changed once CR67_1 is set 3323 for gamma correction (see S3V server) ! */ 3324 if (pScrn->bitsPerPixel == 8) 3325 blank_delay = 0x00; 3326 else if (pScrn->bitsPerPixel == 16) 3327 blank_delay = 0x00; 3328 else 3329 blank_delay = 0x51; 3330 else 3331 if (pScrn->bitsPerPixel == 8) 3332 blank_delay = 0x00; 3333 else if (pScrn->bitsPerPixel == 16) 3334 blank_delay = 0x02; 3335 else 3336 blank_delay = 0x04; 3337 3338 if (ps3v->Chipset == S3_ViRGE_VX) 3339 new->CR6D = blank_delay; 3340 else { 3341 new->CR65 = (new->CR65 & ~0x38) 3342 | (blank_delay & 0x07) << 3; 3343 VGAOUT8(vgaCRIndex, 0x6d); 3344 new->CR6D = VGAIN8(vgaCRReg); 3345 } 3346 } 3347 /* S3_EARLY_SC was defaulted to 0 */ 3348 /* in 3.3.3 and never changed. */ 3349 /* Also, bit 1 is never set in 3.9Nm, */ 3350 /* so I left this out for 4.0. */ 3351#if 0 3352 if (mode->Private[0] & (1 << S3_EARLY_SC)) { 3353 if (mode->Private[S3_EARLY_SC]) 3354 new->CR65 |= 2; 3355 else 3356 new->CR65 &= ~2; 3357 } 3358#endif 3359 3360 VGAOUT8(vgaCRIndex, 0x68); 3361 new->CR68 = VGAIN8(vgaCRReg); 3362 new->CR69 = 0; 3363 3364 /* Flat panel centering and expansion registers */ 3365 if (S3_ViRGE_MX_SERIES(ps3v->Chipset) && (ps3v->lcd_center)) { 3366 new->SR54 = 0x10 ; 3367 new->SR55 = 0x80 ; 3368 new->SR56 = 0x10 ; 3369 new->SR57 = 0x80 ; 3370 } else { 3371 new->SR54 = 0x1f ; 3372 new->SR55 = 0x9f ; 3373 new->SR56 = 0x1f ; 3374 new->SR57 = 0xff ; 3375 } 3376 3377 pScrn->vtSema = TRUE; 3378 3379 /* Do it! Write the mode registers */ 3380 /* to hardware, start STREAMS if */ 3381 /* needed, etc. */ 3382 S3VWriteMode( pScrn, vganew, new ); 3383 /* Adjust the viewport */ 3384 S3VAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 3385 3386 return TRUE; 3387} 3388 3389 3390/* 3391 * This is called at the end of each server generation. It restores the 3392 * original (text) mode. It should also unmap the video memory, and free 3393 * any per-generation data allocated by the driver. It should finish 3394 * by unwrapping and calling the saved CloseScreen function. 3395 */ 3396 3397/* Mandatory */ 3398static Bool 3399S3VCloseScreen(int scrnIndex, ScreenPtr pScreen) 3400{ 3401 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 3402 vgaHWPtr hwp = VGAHWPTR(pScrn); 3403 S3VPtr ps3v = S3VPTR(pScrn); 3404 vgaRegPtr vgaSavePtr = &hwp->SavedReg; 3405 S3VRegPtr S3VSavePtr = &ps3v->SavedReg; 3406 3407 /* Like S3VRestore, but uses passed */ 3408 /* mode registers. */ 3409 if (pScrn->vtSema) { 3410 S3VWriteMode(pScrn, vgaSavePtr, S3VSavePtr); 3411 vgaHWLock(hwp); 3412 S3VDisableMmio(pScrn); 3413 S3VUnmapMem(pScrn); 3414 } 3415 3416 if (ps3v->AccelInfoRec) 3417 XAADestroyInfoRec(ps3v->AccelInfoRec); 3418 if (ps3v->DGAModes) 3419 xfree(ps3v->DGAModes); 3420 3421 pScrn->vtSema = FALSE; 3422 3423 pScreen->CloseScreen = ps3v->CloseScreen; 3424 3425 return (*pScreen->CloseScreen)(scrnIndex, pScreen); 3426} 3427 3428 3429 3430 3431/* Do screen blanking */ 3432 3433/* Mandatory */ 3434static Bool 3435S3VSaveScreen(ScreenPtr pScreen, int mode) 3436{ 3437 return vgaHWSaveScreen(pScreen, mode); 3438} 3439 3440 3441 3442 3443 3444/* This function inits the STREAMS processor variables. 3445 * This has essentially been taken from the accel/s3_virge code and the databook. 3446 */ 3447static void 3448S3VInitSTREAMS(ScrnInfoPtr pScrn, unsigned int *streams, DisplayModePtr mode) 3449{ 3450 PVERB5(" S3VInitSTREAMS\n"); 3451 3452 switch (pScrn->bitsPerPixel) 3453 { 3454 case 16: 3455 streams[0] = 0x05000000; 3456 break; 3457 case 24: 3458 /* data format 8.8.8 (24 bpp) */ 3459 streams[0] = 0x06000000; 3460 break; 3461 case 32: 3462 /* one more bit for X.8.8.8, 32 bpp */ 3463 streams[0] = 0x07000000; 3464 break; 3465 } 3466 /* NO chroma keying... */ 3467 streams[1] = 0x0; 3468 /* Secondary stream format KRGB-16 */ 3469 /* data book suggestion... */ 3470 streams[2] = 0x03000000; 3471 3472 streams[3] = 0x0; 3473 3474 streams[4] = 0x0; 3475 /* use 0x01000000 for primary over second. */ 3476 /* use 0x0 for second over prim. */ 3477 streams[5] = 0x01000000; 3478 3479 streams[6] = 0x0; 3480 3481 streams[7] = 0x0; 3482 /* Stride is 3 bytes for 24 bpp mode and */ 3483 /* 4 bytes for 32 bpp. */ 3484 switch(pScrn->bitsPerPixel) 3485 { 3486 case 16: 3487 streams[8] = 3488 pScrn->displayWidth * 2; 3489 break; 3490 case 24: 3491 streams[8] = 3492 pScrn->displayWidth * 3; 3493 break; 3494 case 32: 3495 streams[8] = 3496 pScrn->displayWidth * 4; 3497 break; 3498 } 3499 /* Choose fbaddr0 as stream source. */ 3500 streams[9] = 0x0; 3501 streams[10] = 0x0; 3502 streams[11] = 0x0; 3503 streams[12] = 0x1; 3504 3505 /* Set primary stream on top of secondary */ 3506 /* stream. */ 3507 streams[13] = 0xc0000000; 3508 /* Vertical scale factor. */ 3509 streams[14] = 0x0; 3510 3511 streams[15] = 0x0; 3512 /* Vertical accum. initial value. */ 3513 streams[16] = 0x0; 3514 /* X and Y start coords + 1. */ 3515 streams[18] = 0x00010001; 3516 3517 /* Specify window Width -1 and Height of */ 3518 /* stream. */ 3519 streams[19] = 3520 (mode->HDisplay - 1) << 16 | 3521 (mode->VDisplay); 3522 3523 /* Book says 0x07ff07ff. */ 3524 streams[20] = 0x07ff07ff; 3525 3526 streams[21] = 0x00010001; 3527 3528} 3529 3530 3531 3532 3533/* Used to adjust start address in frame buffer. We use the new 3534 * CR69 reg for this purpose instead of the older CR31/CR51 combo. 3535 * If STREAMS is running, we program the STREAMS start addr. registers. 3536 */ 3537 3538void 3539S3VAdjustFrame(int scrnIndex, int x, int y, int flags) 3540{ 3541 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 3542 vgaHWPtr hwp = VGAHWPTR(pScrn); 3543 S3VPtr ps3v = S3VPTR(pScrn); 3544 int Base; 3545 int vgaCRIndex, vgaCRReg, vgaIOBase; 3546 vgaIOBase = hwp->IOBase; 3547 vgaCRIndex = vgaIOBase + 4; 3548 vgaCRReg = vgaIOBase + 5; 3549 3550 if(ps3v->ShowCache && y) 3551 y += pScrn->virtualY - 1; 3552 3553 if( (ps3v->STREAMSRunning == FALSE) || 3554 S3_ViRGE_GX2_SERIES(ps3v->Chipset) || S3_ViRGE_MX_SERIES(ps3v->Chipset)) { 3555 Base = ((y * pScrn->displayWidth + x) 3556 * (pScrn->bitsPerPixel / 8)) >> 2; 3557 if (pScrn->bitsPerPixel == 24) 3558 Base = Base+2 - (Base+2) % 3; 3559 if (pScrn->bitsPerPixel == 16) 3560 if (S3_TRIO_3D_SERIES(ps3v->Chipset) && pScrn->modes->Clock > 115000) 3561 Base &= ~1; 3562 3563 /* Now program the start address registers */ 3564 VGAOUT16(vgaCRIndex, (Base & 0x00FF00) | 0x0C); 3565 VGAOUT16(vgaCRIndex, ((Base & 0x00FF) << 8) | 0x0D); 3566 VGAOUT8(vgaCRIndex, 0x69); 3567 VGAOUT8(vgaCRReg, (Base & 0x0F0000) >> 16); 3568 } 3569 else { /* Change start address for STREAMS case */ 3570 VerticalRetraceWait(); 3571 if(ps3v->Chipset == S3_ViRGE_VX) 3572 OUTREG(PSTREAM_FBADDR0_REG, 3573 ((y * pScrn->displayWidth + (x & ~7)) * 3574 pScrn->bitsPerPixel / 8)); 3575 else 3576 OUTREG(PSTREAM_FBADDR0_REG, 3577 ((y * pScrn->displayWidth + (x & ~3)) * 3578 pScrn->bitsPerPixel / 8)); 3579 } 3580 3581 return; 3582} 3583 3584 3585 3586 3587/* Usually mandatory */ 3588Bool 3589S3VSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) 3590{ 3591 return S3VModeInit(xf86Screens[scrnIndex], mode); 3592} 3593 3594 3595 3596void S3VLoadPalette( 3597 ScrnInfoPtr pScrn, 3598 int numColors, 3599 int *indicies, 3600 LOCO *colors, 3601 VisualPtr pVisual 3602){ 3603 S3VPtr ps3v = S3VPTR(pScrn); 3604 int i, index; 3605 3606 for(i = 0; i < numColors; i++) { 3607 index = indicies[i]; 3608 VGAOUT8(0x3c8, index); 3609 VGAOUT8(0x3c9, colors[index].red); 3610 VGAOUT8(0x3c9, colors[index].green); 3611 VGAOUT8(0x3c9, colors[index].blue); 3612 } 3613} 3614 3615 3616/* 3617 * Functions to support getting a ViRGE card into MMIO mode if it fails to 3618 * default to MMIO enabled. 3619 */ 3620 3621void 3622S3VEnableMmio(ScrnInfoPtr pScrn) 3623{ 3624 vgaHWPtr hwp; 3625 S3VPtr ps3v; 3626 IOADDRESS vgaCRIndex, vgaCRReg; 3627 unsigned char val; 3628 3629 PVERB5(" S3VEnableMmio\n"); 3630 3631 hwp = VGAHWPTR(pScrn); 3632 ps3v = S3VPTR(pScrn); 3633 /* 3634 * enable chipset (seen on uninitialized secondary cards) 3635 * might not be needed once we use the VGA softbooter 3636 * (EE 05/04/99) 3637 */ 3638 vgaHWSetStdFuncs(hwp); 3639 /* 3640 * any access to the legacy VGA ports is done here. 3641 * If legacy VGA is inaccessable the MMIO base _has_ 3642 * to be set correctly already and MMIO _has_ to be 3643 * enabled. 3644 */ 3645 val = inb(hwp->PIOOffset + 0x3C3); /*@@@EE*/ 3646 outb(hwp->PIOOffset + 0x3C3, val | 0x01); 3647 /* 3648 * set CR registers to color mode 3649 * in mono mode extended CR registers 3650 * are not accessible. (EE 05/04/99) 3651 */ 3652 val = inb(hwp->PIOOffset + VGA_MISC_OUT_R); /*@@@EE*/ 3653 outb(hwp->PIOOffset + VGA_MISC_OUT_W, val | 0x01); 3654 vgaHWGetIOBase(hwp); /* Get VGA I/O base */ 3655 vgaCRIndex = hwp->PIOOffset + hwp->IOBase + 4; 3656 vgaCRReg = vgaCRIndex + 1; 3657#if 1 3658 /* 3659 * set linear base register to the PCI register values 3660 * some DX chipsets don't seem to do it automatically 3661 * (EE 06/03/99) 3662 */ 3663 outb(vgaCRIndex, 0x59); /*@@@EE*/ 3664 outb(vgaCRReg, PCI_REGION_BASE(ps3v->PciInfo, 0, REGION_MEM) >> 24); 3665 outb(vgaCRIndex, 0x5A); 3666 outb(vgaCRReg, PCI_REGION_BASE(ps3v->PciInfo, 0, REGION_MEM) >> 16); 3667 outb(vgaCRIndex, 0x53); 3668#endif 3669 /* Save register for restore */ 3670 ps3v->EnableMmioCR53 = inb(vgaCRReg); 3671 /* Enable new MMIO, if TRIO mmio is already */ 3672 /* enabled, then it stays enabled. */ 3673 outb(vgaCRReg, ps3v->EnableMmioCR53 | 0x08); 3674 outb(hwp->PIOOffset + VGA_MISC_OUT_W, val); 3675 if (S3_TRIO_3D_SERIES(ps3v->Chipset)) { 3676 outb(vgaCRIndex, 0x40); 3677 val = inb(vgaCRReg); 3678 outb(vgaCRReg, val | 1); 3679 } 3680} 3681 3682 3683 3684void 3685S3VDisableMmio(ScrnInfoPtr pScrn) 3686{ 3687 vgaHWPtr hwp; 3688 S3VPtr ps3v; 3689 IOADDRESS vgaCRIndex, vgaCRReg; 3690 3691 PVERB5(" S3VDisableMmio\n"); 3692 3693 hwp = VGAHWPTR(pScrn); 3694 ps3v = S3VPTR(pScrn); 3695 3696 vgaCRIndex = hwp->PIOOffset + hwp->IOBase + 4; 3697 vgaCRReg = vgaCRIndex + 1; 3698 outb(vgaCRIndex, 0x53); 3699 /* Restore register's original state */ 3700 outb(vgaCRReg, ps3v->EnableMmioCR53); 3701 if (S3_TRIO_3D_SERIES(ps3v->Chipset)) { 3702 unsigned char val; 3703 outb(vgaCRIndex, 0x40); 3704 val = inb(vgaCRReg); 3705 outb(vgaCRReg, val | 1); 3706 } 3707} 3708 3709 3710 3711/* This function is used to debug, it prints out the contents of s3 regs */ 3712 3713static void 3714S3VPrintRegs(ScrnInfoPtr pScrn) 3715{ 3716 unsigned char tmp1, tmp2; 3717 vgaHWPtr hwp = VGAHWPTR(pScrn); 3718 S3VPtr ps3v = S3VPTR(pScrn); 3719 int vgaCRIndex, vgaCRReg, vgaIOBase, vgaIR; 3720 vgaIOBase = hwp->IOBase; 3721 vgaCRIndex = vgaIOBase + 4; 3722 vgaCRReg = vgaIOBase + 5; 3723 vgaIR = vgaIOBase + 0xa; 3724 3725/* All registers */ 3726/* New formatted registers, matches s3rc (sort of) */ 3727 xf86DrvMsgVerb( pScrn->scrnIndex, X_INFO, VERBLEV, "START register dump ------------------\n"); 3728 xf86ErrorFVerb(VERBLEV, "Misc Out[3CC]\n "); 3729 xf86ErrorFVerb(VERBLEV, "%02x\n",VGAIN8(0x3cc)); 3730 3731 xf86ErrorFVerb(VERBLEV, "\nCR[00-2f]\n "); 3732 for(tmp1=0x0;tmp1<=0x2f;tmp1++){ 3733 VGAOUT8(vgaCRIndex, tmp1); 3734 xf86ErrorFVerb(VERBLEV, "%02x ",VGAIN8(vgaCRReg)); 3735 if((tmp1 & 0x3) == 0x3) xf86ErrorFVerb(VERBLEV, " "); 3736 if((tmp1 & 0xf) == 0xf) xf86ErrorFVerb(VERBLEV, "\n "); 3737 } 3738 3739 xf86ErrorFVerb(VERBLEV, "\nSR[00-27]\n "); 3740 for(tmp1=0x0;tmp1<=0x27;tmp1++){ 3741 VGAOUT8(0x3c4, tmp1); 3742 xf86ErrorFVerb(VERBLEV, "%02x ",VGAIN8(0x3c5)); 3743 if((tmp1 & 0x3) == 0x3) xf86ErrorFVerb(VERBLEV, " "); 3744 if((tmp1 & 0xf) == 0xf) xf86ErrorFVerb(VERBLEV, "\n "); 3745 } 3746 xf86ErrorFVerb(VERBLEV, "\n"); /* odd hex number of digits... */ 3747 3748 xf86ErrorFVerb(VERBLEV, "\nGr Cont GR[00-0f]\n "); 3749 for(tmp1=0x0;tmp1<=0x0f;tmp1++){ 3750 VGAOUT8(0x3ce, tmp1); 3751 xf86ErrorFVerb(VERBLEV, "%02x ",VGAIN8(0x3cf)); 3752 if((tmp1 & 0x3) == 0x3) xf86ErrorFVerb(VERBLEV, " "); 3753 if((tmp1 & 0xf) == 0xf) xf86ErrorFVerb(VERBLEV, "\n "); 3754 } 3755 3756 xf86ErrorFVerb(VERBLEV, "\nAtt Cont AR[00-1f]\n "); 3757 VGAIN8(vgaIR); /* preset AR flip-flop by reading 3DA, ignore return value */ 3758 tmp2=VGAIN8(0x3c0) & 0x20; 3759 for(tmp1=0x0;tmp1<=0x1f;tmp1++){ 3760 VGAIN8(vgaIR); /* preset AR flip-flop by reading 3DA, ignore return value */ 3761 VGAOUT8(0x3c0, (tmp1 & ~0x20) | tmp2); 3762 xf86ErrorFVerb(VERBLEV, "%02x ",VGAIN8(0x3c1)); 3763 if((tmp1 & 0x3) == 0x3) xf86ErrorFVerb(VERBLEV, " "); 3764 if((tmp1 & 0xf) == 0xf) xf86ErrorFVerb(VERBLEV, "\n "); 3765 } 3766 3767 xf86ErrorFVerb(VERBLEV, "\nCR[30-6f]\n "); 3768 for(tmp1=0x30;tmp1<=0x6f;tmp1++){ 3769 VGAOUT8(vgaCRIndex, tmp1); 3770 xf86ErrorFVerb(VERBLEV, "%02x ",VGAIN8(vgaCRReg)); 3771 if((tmp1 & 0x3) == 0x3) xf86ErrorFVerb(VERBLEV, " "); 3772 if((tmp1 & 0xf) == 0xf) xf86ErrorFVerb(VERBLEV, "\n "); 3773 } 3774 3775 xf86ErrorFVerb(VERBLEV, "\n"); 3776 xf86DrvMsgVerb( pScrn->scrnIndex, X_INFO, VERBLEV, "END register dump --------------------\n"); 3777} 3778 3779/* this is just a debugger hook */ 3780/* 3781void print_subsys_stat(void *s3vMmioMem); 3782void 3783print_subsys_stat(void *s3vMmioMem) 3784{ 3785 ErrorF("IN_SUBSYS_STAT() = %x\n", IN_SUBSYS_STAT()); 3786 return; 3787} 3788*/ 3789 3790/* 3791 * S3VDisplayPowerManagementSet -- 3792 * 3793 * Sets VESA Display Power Management Signaling (DPMS) Mode. 3794 */ 3795static void 3796S3VDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, 3797 int flags) 3798{ 3799 S3VPtr ps3v; 3800 unsigned char sr8 = 0x0, srd = 0x0; 3801 char modestr[][40] = { "On","Standby","Suspend","Off" }; 3802 3803 ps3v = S3VPTR(pScrn); 3804 3805 /* unlock extended sequence registers */ 3806 3807 VGAOUT8(0x3c4, 0x08); 3808 sr8 = VGAIN8(0x3c5); 3809 sr8 |= 0x6; 3810 VGAOUT8(0x3c5, sr8); 3811 3812 /* load SRD */ 3813 VGAOUT8(0x3c4, 0x0d); 3814 srd = VGAIN8(0x3c5); 3815 3816 srd &= 0x03; /* clear the sync control bits of srd */ 3817 3818 switch (PowerManagementMode) { 3819 case DPMSModeOn: 3820 /* Screen: On; HSync: On, VSync: On */ 3821 break; 3822 case DPMSModeStandby: 3823 /* Screen: Off; HSync: Off, VSync: On */ 3824 srd |= 0x10; 3825 break; 3826 case DPMSModeSuspend: 3827 /* Screen: Off; HSync: On, VSync: Off */ 3828 srd |= 0x40; 3829 break; 3830 case DPMSModeOff: 3831 /* Screen: Off; HSync: Off, VSync: Off */ 3832 srd |= 0x50; 3833 break; 3834 default: 3835 xf86ErrorFVerb(VERBLEV, "Invalid PowerManagementMode %d passed to S3VDisplayPowerManagementSet\n", PowerManagementMode); 3836 break; 3837 } 3838 3839 VGAOUT8(0x3c4, 0x0d); 3840 VGAOUT8(0x3c5, srd); 3841 3842 xf86ErrorFVerb(VERBLEV, "Power Manag: set:%s\n", 3843 modestr[PowerManagementMode]); 3844 3845 return; 3846} 3847 3848static unsigned int 3849S3Vddc1Read(ScrnInfoPtr pScrn) 3850{ 3851 register vgaHWPtr hwp = VGAHWPTR(pScrn); 3852 register CARD32 tmp; 3853 S3VPtr ps3v = S3VPTR(pScrn); 3854 3855 while (hwp->readST01(hwp)&0x8) {}; 3856 while (!(hwp->readST01(hwp)&0x8)) {}; 3857 3858 tmp = (INREG(DDC_REG)); 3859 return ((unsigned int) (tmp & 0x08)); 3860} 3861 3862static Bool 3863S3Vddc1(int scrnIndex) 3864{ 3865 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 3866 S3VPtr ps3v = S3VPTR(pScrn); 3867 CARD32 tmp; 3868 Bool success = FALSE; 3869 xf86MonPtr pMon; 3870 3871 /* initialize chipset */ 3872 tmp = INREG(DDC_REG); 3873 OUTREG(DDC_REG,(tmp | 0x12)); 3874 3875 if ((pMon = xf86PrintEDID( 3876 xf86DoEDID_DDC1(scrnIndex,vgaHWddc1SetSpeedWeak(), 3877 S3Vddc1Read))) != NULL) 3878 success = TRUE; 3879 xf86SetDDCproperties(pScrn,pMon); 3880 3881 /* undo initialization */ 3882 OUTREG(DDC_REG,(tmp)); 3883 return success; 3884} 3885 3886static Bool 3887S3Vddc2(int scrnIndex) 3888{ 3889 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 3890 S3VPtr ps3v = S3VPTR(pScrn); 3891 3892 if ( xf86LoadSubModule(pScrn, "i2c") ) { 3893 xf86LoaderReqSymLists(i2cSymbols,NULL); 3894 if (S3V_I2CInit(pScrn)) { 3895 CARD32 tmp = (INREG(DDC_REG)); 3896 OUTREG(DDC_REG,(tmp | 0x13)); 3897 xf86SetDDCproperties(pScrn,xf86PrintEDID( 3898 xf86DoEDID_DDC2(pScrn->scrnIndex,ps3v->I2C))); 3899 OUTREG(DDC_REG,tmp); 3900 return TRUE; 3901 } 3902 } 3903 return FALSE; 3904} 3905 3906static void 3907S3VProbeDDC(ScrnInfoPtr pScrn, int index) 3908{ 3909 vbeInfoPtr pVbe; 3910 if (xf86LoadSubModule(pScrn, "vbe")) { 3911 pVbe = VBEInit(NULL,index); 3912 ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 3913 vbeFree(pVbe); 3914 } 3915} 3916 3917/*EOF*/ 3918 3919 3920