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