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