s3v_driver.c revision 820a851c
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 const 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 xf86SetBackingStore(pScreen); 2424 xf86SetSilkenMouse(pScreen); 2425 /* hardware cursor needs to wrap this layer */ 2426 S3VDGAInit(pScreen); 2427 2428 /* Initialise cursor functions */ 2429 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 2430 2431 /* Initialize HW cursor layer. 2432 Must follow software cursor initialization*/ 2433 if (ps3v->hwcursor) { 2434 if(!S3VHWCursorInit(pScreen)) { 2435 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2436 "Hardware cursor initialization failed\n"); 2437 } 2438 } 2439 2440 if (ps3v->shadowFB) { 2441 RefreshAreaFuncPtr refreshArea = s3vRefreshArea; 2442 2443 if(ps3v->rotate) { 2444 if (!ps3v->PointerMoved) { 2445 ps3v->PointerMoved = pScrn->PointerMoved; 2446 pScrn->PointerMoved = s3vPointerMoved; 2447 } 2448 2449 switch(pScrn->bitsPerPixel) { 2450 case 8: refreshArea = s3vRefreshArea8; break; 2451 case 16: refreshArea = s3vRefreshArea16; break; 2452 case 24: refreshArea = s3vRefreshArea24; break; 2453 case 32: refreshArea = s3vRefreshArea32; break; 2454 } 2455 } 2456 2457 ShadowFBInit(pScreen, refreshArea); 2458 } 2459 2460 /* Initialise default colourmap */ 2461 if (!miCreateDefColormap(pScreen)) 2462 return FALSE; 2463 /* Initialize colormap layer. */ 2464 /* Must follow initialization */ 2465 /* of the default colormap. */ 2466 /* And SetGamma call, else it */ 2467 /* will load palette with solid */ 2468 /* white. */ 2469 if(!xf86HandleColormaps(pScreen, 256, 6, S3VLoadPalette, NULL, 2470 CMAP_RELOAD_ON_MODE_SWITCH )) 2471 return FALSE; 2472 /* All the ugly stuff is done, */ 2473 /* so re-enable the screen. */ 2474 vgaHWBlankScreen(pScrn, FALSE ); 2475 2476#if 0 2477 pScrn->racMemFlags = RAC_COLORMAP | RAC_CURSOR | RAC_FB | RAC_VIEWPORT; 2478#endif 2479 pScreen->SaveScreen = S3VSaveScreen; 2480 2481 /* Wrap the current CloseScreen function */ 2482 ps3v->CloseScreen = pScreen->CloseScreen; 2483 pScreen->CloseScreen = S3VCloseScreen; 2484 2485 if(xf86DPMSInit(pScreen, S3VDisplayPowerManagementSet, 0) == FALSE) 2486 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DPMS initialization failed!\n"); 2487 2488 S3VInitVideo(pScreen); 2489 2490 /* Report any unused options (only for the first generation) */ 2491 if (serverGeneration == 1) { 2492 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 2493 } 2494 /* Done */ 2495 return TRUE; 2496} 2497 2498 2499 2500/* Common init routines needed in EnterVT and ScreenInit */ 2501 2502static int 2503S3VInternalScreenInit(ScrnInfoPtr pScrn, ScreenPtr pScreen) 2504{ 2505 int ret = TRUE; 2506 S3VPtr ps3v; 2507 int width, height, displayWidth; 2508 unsigned char* FBStart; 2509 2510 ps3v = S3VPTR(pScrn); 2511 2512 displayWidth = pScrn->displayWidth; 2513 if (ps3v->rotate) { 2514 height = pScrn->virtualX; 2515 width = pScrn->virtualY; 2516 } else { 2517 width = pScrn->virtualX; 2518 height = pScrn->virtualY; 2519 } 2520 2521 if(ps3v->shadowFB) { 2522 ps3v->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); 2523 ps3v->ShadowPtr = malloc(ps3v->ShadowPitch * height); 2524 displayWidth = ps3v->ShadowPitch / (pScrn->bitsPerPixel >> 3); 2525 FBStart = ps3v->ShadowPtr; 2526 } else { 2527 ps3v->ShadowPtr = NULL; 2528 FBStart = ps3v->FBStart; 2529 } 2530 2531 /* 2532 * Call the framebuffer layer's ScreenInit function, and fill in other 2533 * pScreen fields. 2534 */ 2535 2536 switch (pScrn->bitsPerPixel) 2537 { 2538 case 8: 2539 case 16: 2540 case 24: 2541 case 32: 2542 ret = fbScreenInit(pScreen, FBStart, width, 2543 height, pScrn->xDpi, pScrn->yDpi, 2544 displayWidth, pScrn->bitsPerPixel); 2545 break; 2546 default: 2547 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2548 "Internal error: invalid bpp (%d) in S3VScreenInit\n", 2549 pScrn->bitsPerPixel); 2550 ret = FALSE; 2551 break; 2552 } 2553 2554 return ret; 2555} 2556 2557 2558 2559/* Checks if a mode is suitable for the selected chipset. */ 2560 2561static ModeStatus 2562S3VValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 2563{ 2564 SCRN_INFO_PTR(arg); 2565 2566 if ((pScrn->bitsPerPixel + 7)/8 * mode->HDisplay > 4095) 2567 return MODE_VIRTUAL_X; 2568 2569 return MODE_OK; 2570} 2571 2572 2573 2574static Bool 2575S3VModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 2576{ 2577 vgaHWPtr hwp = VGAHWPTR(pScrn); 2578 S3VPtr ps3v = S3VPTR(pScrn); 2579 int width, dclk; 2580 int i, j; 2581 unsigned char tmp = 0; 2582 2583 /* Store values to current mode register structs */ 2584 S3VRegPtr new = &ps3v->ModeReg; 2585 vgaRegPtr vganew = &hwp->ModeReg; 2586 int vgaCRIndex, vgaCRReg, vgaIOBase; 2587 2588 vgaIOBase = hwp->IOBase; 2589 vgaCRIndex = vgaIOBase + 4; 2590 vgaCRReg = vgaIOBase + 5; 2591 2592 PVERB5(" S3VModeInit\n"); 2593 2594 /* Set scale factors for mode timings */ 2595 2596 if (ps3v->Chipset == S3_ViRGE_VX || S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 2597 S3_ViRGE_MX_SERIES(ps3v->Chipset)) { 2598 ps3v->HorizScaleFactor = 1; 2599 } 2600 else if (pScrn->bitsPerPixel == 8) { 2601 ps3v->HorizScaleFactor = 1; 2602 } 2603 else if (pScrn->bitsPerPixel == 16) { 2604 if (S3_TRIO_3D_SERIES(ps3v->Chipset) && mode->Clock > 115000) 2605 ps3v->HorizScaleFactor = 1; 2606 else 2607 ps3v->HorizScaleFactor = 2; 2608 } 2609 else { 2610 ps3v->HorizScaleFactor = 1; 2611 } 2612 2613 2614 /* First we adjust the horizontal timings if needed */ 2615 2616 if(ps3v->HorizScaleFactor != 1) 2617 if (!mode->CrtcHAdjusted) { 2618 mode->CrtcHDisplay *= ps3v->HorizScaleFactor; 2619 mode->CrtcHSyncStart *= ps3v->HorizScaleFactor; 2620 mode->CrtcHSyncEnd *= ps3v->HorizScaleFactor; 2621 mode->CrtcHTotal *= ps3v->HorizScaleFactor; 2622 mode->CrtcHSkew *= ps3v->HorizScaleFactor; 2623 mode->CrtcHAdjusted = TRUE; 2624 } 2625 2626 if(!vgaHWInit (pScrn, mode)) 2627 return FALSE; 2628 2629 /* Now we fill in the rest of the stuff we need for the virge */ 2630 /* Start with MMIO, linear addr. regs */ 2631 2632 VGAOUT8(vgaCRIndex, 0x3a); 2633 tmp = VGAIN8(vgaCRReg); 2634 if( S3_ViRGE_GX2_SERIES(ps3v->Chipset) 2635 /* MXTESTME */ || S3_ViRGE_MX_SERIES(ps3v->Chipset) ) 2636 { 2637 if(ps3v->pci_burst) 2638 /*new->CR3A = (tmp & 0x38) | 0x10; / ENH 256, PCI burst */ 2639 /* Don't clear reserved bits... */ 2640 new->CR3A = (tmp & 0x7f) | 0x10; /* ENH 256, PCI burst */ 2641 else 2642 new->CR3A = tmp | 0x90; /* ENH 256, no PCI burst! */ 2643 } 2644 else 2645 { 2646 if(ps3v->pci_burst) 2647 new->CR3A = (tmp & 0x7f) | 0x15; /* ENH 256, PCI burst */ 2648 else 2649 new->CR3A = tmp | 0x95; /* ENH 256, no PCI burst! */ 2650 } 2651 2652 2653 VGAOUT8(vgaCRIndex, 0x55); 2654 new->CR55 = VGAIN8(vgaCRReg); 2655 if (ps3v->hwcursor) 2656 new->CR55 |= 0x10; /* Enables X11 hw cursor mode */ 2657 if (S3_TRIO_3D_SERIES(ps3v->Chipset)) { 2658 new->CR31 = 0x0c; /* [trio3d] page 54 */ 2659 } else { 2660 new->CR53 = 0x08; /* Enables MMIO */ 2661 new->CR31 = 0x8c; /* Dis. 64k window, en. ENH maps */ 2662 } 2663 2664 /* Enables S3D graphic engine and PCI disconnects */ 2665 if(ps3v->Chipset == S3_ViRGE_VX){ 2666 new->CR66 = 0x90; 2667 new->CR63 = 0x09; 2668 } 2669 else { 2670 new->CR66 = 0x89; 2671 /* Set display fifo */ 2672 if( S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 2673 S3_ViRGE_MX_SERIES(ps3v->Chipset) ) 2674 { 2675 /* Changed from 0x08 based on reports that this */ 2676 /* prevents MX from running properly below 1024x768 */ 2677 new->CR63 = 0x10; 2678 } 2679 else 2680 { 2681 new->CR63 = 0; 2682 } 2683 } 2684 2685 /* Now set linear addr. registers */ 2686 /* LAW size: we have 2 cases, 2MB, 4MB or >= 4MB for VX */ 2687 VGAOUT8(vgaCRIndex, 0x58); 2688 new->CR58 = VGAIN8(vgaCRReg) & 0x80; 2689 if(pScrn->videoRam == 2048){ 2690 new->CR58 |= 0x02 | 0x10; 2691 } 2692 else if (pScrn->videoRam == 1024) { 2693 new->CR58 |= 0x01 | 0x10; 2694 } 2695 else { 2696 if (S3_TRIO_3D_2X_SERIES(ps3v->Chipset) && pScrn->videoRam == 8192) 2697 new->CR58 |= 0x07 | 0x10; /* 8MB window on Trio3D/2X */ 2698 else 2699 new->CR58 |= 0x03 | 0x10; /* 4MB window on virge, 8MB on VX */ 2700 } 2701 if(ps3v->Chipset == S3_ViRGE_VX) 2702 new->CR58 |= 0x40; 2703 if (ps3v->early_ras_precharge) 2704 new->CR58 |= 0x80; 2705 if (ps3v->late_ras_precharge) 2706 new->CR58 &= 0x7f; 2707 2708 /* ** On PCI bus, no need to reprogram the linear window base address */ 2709 2710 /* Now do clock PLL programming. Use the s3gendac function to get m,n */ 2711 /* Also determine if we need doubling etc. */ 2712 2713 dclk = mode->Clock; 2714 new->CR67 = 0x00; /* Defaults */ 2715 2716 if (!S3_TRIO_3D_SERIES(ps3v->Chipset)) 2717 new->SR15 = 0x03 | 0x80; 2718 else { 2719 VGAOUT8(0x3c4, 0x15); 2720 new->SR15 = VGAIN8(0x3c5); 2721 VGAOUT8(0x3c4, 0x0a); 2722 new->SR0A = VGAIN8(0x3c5); 2723 if (ps3v->slow_dram) { 2724 new->SR15 = 0x03; /* 3 CYC MWR */ 2725 new->SR0A &= 0x7F; 2726 } else if (ps3v->fast_dram) { 2727 new->SR15 = 0x03 | 0x80; /* 2 CYC MWR */ 2728 new->SR0A |= 0x80; 2729 } else { /* keep BIOS init defaults */ 2730 new->SR15 = (new->SR15 & 0x80) | 0x03; 2731 } 2732 } 2733 new->SR18 = 0x00; 2734 new->CR43 = 0x00; 2735 new->CR45 = 0x00; 2736 /* Enable MMIO to RAMDAC registers */ 2737 new->CR65 = 0x00; /* CR65_2 must be zero, doc seems to be wrong */ 2738 new->CR54 = 0x00; 2739 2740 if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 2741 /* S3_ViRGE_MX_SERIES(ps3v->Chipset) || CR40 reserved on MX */ 2742 S3_ViRGE_MXP_SERIES(ps3v->Chipset) || 2743 S3_ViRGE_VX_SERIES(ps3v->Chipset) || 2744 /* S3_TRIO_3D_2X_SERIES(ps3v->Chipset) * included in GX2 series */ 2745 ps3v->Chipset == S3_ViRGE_DXGX || 2746 ps3v->Chipset == S3_ViRGE 2747 ) { 2748 VGAOUT8(vgaCRIndex, 0x40); 2749 new->CR40 = VGAIN8(vgaCRReg) & ~0x01; 2750 } 2751 2752 if (S3_ViRGE_MX_SERIES(ps3v->Chipset)) { 2753 /* fix problems with APM suspend/resume trashing CR90/91 */ 2754 switch(pScrn->bitsPerPixel) { 2755 case 8: new->CR41 = 0x38; break; 2756 case 15: new->CR41 = 0x58; break; 2757 case 16: new->CR41 = 0x48; break; 2758 default: new->CR41 = 0x77; 2759 } 2760 } 2761 2762 xf86ErrorFVerb(VERBLEV, " S3VModeInit dclk=%i \n", 2763 dclk 2764 ); 2765 2766 /* Memory controller registers. Optimize for better graphics engine 2767 * performance. These settings are adjusted/overridden below for other bpp/ 2768 * XConfig options.The idea here is to give a longer number of contiguous 2769 * MCLK's to both refresh and the graphics engine, to diminish the 2770 * relative penalty of 3 or 4 mclk's needed to setup memory transfers. 2771 */ 2772 new->MMPR0 = 0x010400; /* defaults */ 2773 new->MMPR1 = 0x00; 2774 new->MMPR2 = 0x0808; 2775 new->MMPR3 = 0x08080810; 2776 2777 /* 2778 * These settings look like they ought to be better adjusted for depth, 2779 * so for problem modes running without any fifo_ option should be 2780 * usable. Note that these adjust some memory timings and relate to 2781 * the boards MCLK setting. 2782 * */ 2783 if( ps3v->fifo_aggressive || ps3v->fifo_moderate || 2784 ps3v->fifo_conservative ) { 2785 2786 new->MMPR1 = 0x0200; /* Low P. stream waits before filling */ 2787 new->MMPR2 = 0x1808; /* Let the FIFO refill itself */ 2788 new->MMPR3 = 0x08081810; /* And let the GE hold the bus for a while */ 2789 } 2790 2791 /* And setup here the new value for MCLK. We use the XConfig 2792 * option "set_mclk", whose value gets stored in ps3v->MCLK. 2793 * I'm not sure what the maximum "permitted" value should be, probably 2794 * 100 MHz is more than enough for now. 2795 */ 2796 2797 if(ps3v->MCLK> 0) { 2798 if (S3_ViRGE_MX_SERIES(ps3v->Chipset)) 2799 S3VCommonCalcClock(pScrn, mode, 2800 (int)(ps3v->MCLK / ps3v->refclk_fact), 2801 1, 1, 31, 0, 3, 2802 135000, 270000, &new->SR11, &new->SR10); 2803 else 2804 S3VCommonCalcClock(pScrn, mode, ps3v->MCLK, 1, 1, 31, 0, 3, 2805 135000, 270000, &new->SR11, &new->SR10); 2806 } 2807 else { 2808 new->SR10 = 255; /* This is a reserved value, so we use as flag */ 2809 new->SR11 = 255; 2810 } 2811 2812 /* most modes don't need STREAMS */ 2813 /* processor, preset FALSE */ 2814 /* support for XVideo needs streams, so added it to some modes */ 2815 ps3v->NeedSTREAMS = FALSE; 2816 2817 if(ps3v->Chipset == S3_ViRGE_VX){ 2818 if (pScrn->bitsPerPixel == 8) { 2819 if (dclk <= 110000) new->CR67 = 0x00; /* 8bpp, 135MHz */ 2820 else new->CR67 = 0x10; /* 8bpp, 220MHz */ 2821 } 2822 else if ((pScrn->bitsPerPixel == 16) && (pScrn->weight.green == 5)) { 2823 if (dclk <= 110000) new->CR67 = 0x20; /* 15bpp, 135MHz */ 2824 else new->CR67 = 0x30; /* 15bpp, 220MHz */ 2825 } 2826 else if (pScrn->bitsPerPixel == 16) { 2827 if (dclk <= 110000) new->CR67 = 0x40; /* 16bpp, 135MHz */ 2828 else new->CR67 = 0x50; /* 16bpp, 220MHz */ 2829 } 2830 else if ((pScrn->bitsPerPixel == 24) || (pScrn->bitsPerPixel == 32)) { 2831 new->CR67 = 0xd0 | 0x0c; /* 24bpp, 135MHz, STREAMS */ 2832 /* Flag STREAMS proc. required */ 2833 ps3v->NeedSTREAMS = TRUE; 2834 S3VInitSTREAMS(pScrn, new->STREAMS, mode); 2835 new->MMPR0 = 0xc098; /* Adjust FIFO slots */ 2836 } 2837 S3VCommonCalcClock(pScrn, mode, dclk, 1, 1, 31, 0, 4, 2838 220000, 440000, &new->SR13, &new->SR12); 2839 2840 } /* end VX if() */ 2841 else if (S3_ViRGE_GX2_SERIES(ps3v->Chipset) || S3_ViRGE_MX_SERIES(ps3v->Chipset)) { 2842 if (pScrn->bitsPerPixel == 8) 2843 new->CR67 = 0x00; 2844 else if (pScrn->bitsPerPixel == 16) { 2845 /* XV support needs STREAMS in depth 16 */ 2846 ps3v->NeedSTREAMS = TRUE; 2847 S3VInitSTREAMS(pScrn, new->STREAMS, mode); 2848 if (pScrn->weight.green == 5) 2849 new->CR67 = 0x30 | 0x4; /* 15bpp */ 2850 else 2851 new->CR67 = 0x50 | 0x4; /* 16bpp */ 2852 } 2853 else if ((pScrn->bitsPerPixel == 24) ) { 2854 new->CR67 = 0x74; /* 24bpp, STREAMS */ 2855 /* Flag STREAMS proc. required */ 2856 ps3v->NeedSTREAMS = TRUE; 2857 S3VInitSTREAMS(pScrn, new->STREAMS, mode); 2858 } 2859 else if (pScrn->bitsPerPixel == 32) { 2860 new->CR67 = 0xd0; /* 32bpp */ 2861 /* Missing STREAMs and other stuff here? KJB */ 2862 /* new->MMPR0 = 0xc098; / Adjust FIFO slots */ 2863 } 2864 { 2865 unsigned char ndiv; 2866 if (S3_ViRGE_MX_SERIES(ps3v->Chipset)) { 2867 unsigned char sr8; 2868 VGAOUT8(0x3c4, 0x08); /* unlock extended SEQ regs */ 2869 sr8 = VGAIN8(0x3c5); 2870 VGAOUT8(0x3c5, 0x06); 2871 VGAOUT8(0x3c4, 0x31); 2872 if (VGAIN8(0x3c5) & 0x10) { /* LCD on */ 2873 if (!ps3v->LCDClk) { /* entered only once for first mode */ 2874 int h_lcd, v_lcd; 2875 VGAOUT8(0x3c4, 0x61); 2876 h_lcd = VGAIN8(0x3c5); 2877 VGAOUT8(0x3c4, 0x66); 2878 h_lcd |= ((VGAIN8(0x3c5) & 0x02) << 7); 2879 h_lcd = (h_lcd+1) * 8; 2880 VGAOUT8(0x3c4, 0x69); 2881 v_lcd = VGAIN8(0x3c5); 2882 VGAOUT8(0x3c4, 0x6e); 2883 v_lcd |= ((VGAIN8(0x3c5) & 0x70) << 4); 2884 v_lcd++; 2885 2886 /* check if first mode has physical LCD resolution */ 2887 if (pScrn->modes->HDisplay == h_lcd && pScrn->modes->VDisplay == v_lcd) 2888 ps3v->LCDClk = mode->Clock; 2889 else { 2890 int n1, n2, sr12, sr13, sr29; 2891 VGAOUT8(0x3c4, 0x12); 2892 sr12 = VGAIN8(0x3c5); 2893 VGAOUT8(0x3c4, 0x13); 2894 sr13 = VGAIN8(0x3c5) & 0x7f; 2895 VGAOUT8(0x3c4, 0x29); 2896 sr29 = VGAIN8(0x3c5); 2897 n1 = sr12 & 0x1f; 2898 n2 = ((sr12>>6) & 0x03) | ((sr29 & 0x01) << 2); 2899 ps3v->LCDClk = ((int)(ps3v->refclk_fact * 1431818 * (sr13+2)) / (n1+2) / (1 << n2) + 50) / 100; 2900 } 2901 } 2902 S3VCommonCalcClock(pScrn, mode, 2903 (int)(ps3v->LCDClk / ps3v->refclk_fact), 2904 1, 1, 31, 0, 4, 2905 170000, 340000, &new->SR13, &ndiv); 2906 } 2907 else 2908 S3VCommonCalcClock(pScrn, mode, 2909 (int)(dclk / ps3v->refclk_fact), 2910 1, 1, 31, 0, 4, 2911 170000, 340000, &new->SR13, &ndiv); 2912 VGAOUT8(0x3c4, 0x08); 2913 VGAOUT8(0x3c5, sr8); 2914 } 2915 else /* S3_ViRGE_GX2 */ 2916 S3VCommonCalcClock(pScrn, mode, dclk, 1, 1, 31, 0, 4, 2917 170000, 340000, &new->SR13, &ndiv); 2918 new->SR29 = ndiv >> 7; 2919 new->SR12 = (ndiv & 0x1f) | ((ndiv & 0x60) << 1); 2920 } 2921 } /* end GX2 or MX if() */ 2922 else if(S3_TRIO_3D_SERIES(ps3v->Chipset)) { 2923 new->SR0F = 0x00; 2924 if (pScrn->bitsPerPixel == 8) { 2925 if(dclk > 115000) { /* We need pixmux */ 2926 new->CR67 = 0x10; 2927 new->SR15 |= 0x10; /* Set DCLK/2 bit */ 2928 new->SR18 = 0x80; /* Enable pixmux */ 2929 } 2930 } 2931 else if ((pScrn->bitsPerPixel == 16) && (pScrn->weight.green == 5)) { 2932 if(dclk > 115000) { 2933 new->CR67 = 0x20; 2934 new->SR15 |= 0x10; 2935 new->SR18 = 0x80; 2936 new->SR0F = 0x10; 2937 } else { 2938 new->CR67 = 0x30; /* 15bpp */ 2939 } 2940 } 2941 else if (pScrn->bitsPerPixel == 16) { 2942 if(dclk > 115000) { 2943 new->CR67 = 0x40; 2944 new->SR15 |= 0x10; 2945 new->SR18 = 0x80; 2946 new->SR0F = 0x10; 2947 } else { 2948 new->CR67 = 0x50; 2949 } 2950 } 2951 else if (pScrn->bitsPerPixel == 24) { 2952 new->CR67 = 0xd0 | 0x0c; 2953 ps3v->NeedSTREAMS = TRUE; 2954 S3VInitSTREAMS(pScrn, new->STREAMS, mode); 2955 new->MMPR0 = 0xc000; /* Adjust FIFO slots */ 2956 } 2957 else if (pScrn->bitsPerPixel == 32) { 2958 new->CR67 = 0xd0 | 0x0c; 2959 ps3v->NeedSTREAMS = TRUE; 2960 S3VInitSTREAMS(pScrn, new->STREAMS, mode); 2961 new->MMPR0 = 0x10000; /* Still more FIFO slots */ 2962 new->SR0F = 0x10; 2963 } 2964 S3VCommonCalcClock(pScrn, mode, dclk, 1, 1, 31, 0, 4, 2965 230000, 460000, &new->SR13, &new->SR12); 2966 } /* end TRIO_3D if() */ 2967 else if(ps3v->Chipset == S3_ViRGE_DXGX) { 2968 if (pScrn->bitsPerPixel == 8) { 2969 if(dclk > 80000) { /* We need pixmux */ 2970 new->CR67 = 0x10; 2971 new->SR15 |= 0x10; /* Set DCLK/2 bit */ 2972 new->SR18 = 0x80; /* Enable pixmux */ 2973 } 2974 } 2975 else if ((pScrn->bitsPerPixel == 16) && (pScrn->weight.green == 5)) { 2976 new->CR67 = 0x30; /* 15bpp */ 2977 } 2978 else if (pScrn->bitsPerPixel == 16) { 2979 if(mode->Flags & V_DBLSCAN) 2980 { 2981 new->CR67 = 0x50; 2982 } 2983 else 2984 { 2985 new->CR67 = 0x50 | 0x0c; 2986 /* Flag STREAMS proc. required */ 2987 /* XV support needs STREAMS in depth 16 */ 2988 ps3v->NeedSTREAMS = TRUE; 2989 S3VInitSTREAMS(pScrn, new->STREAMS, mode); 2990 } 2991 if( ps3v->XVideo ) 2992 { 2993 new->MMPR0 = 0x107c02; /* Adjust FIFO slots, overlay */ 2994 } 2995 else 2996 { 2997 new->MMPR0 = 0xc000; /* Adjust FIFO slots */ 2998 } 2999 } 3000 else if (pScrn->bitsPerPixel == 24) { 3001 new->CR67 = 0xd0 | 0x0c; 3002 /* Flag STREAMS proc. required */ 3003 ps3v->NeedSTREAMS = TRUE; 3004 S3VInitSTREAMS(pScrn, new->STREAMS, mode); 3005 if( ps3v->XVideo ) 3006 { 3007 new->MMPR0 = 0x107c02; /* Adjust FIFO slots, overlay */ 3008 } 3009 else 3010 { 3011 new->MMPR0 = 0xc000; /* Adjust FIFO slots */ 3012 } 3013 } 3014 else if (pScrn->bitsPerPixel == 32) { 3015 new->CR67 = 0xd0 | 0x0c; 3016 /* Flag STREAMS proc. required */ 3017 ps3v->NeedSTREAMS = TRUE; 3018 S3VInitSTREAMS(pScrn, new->STREAMS, mode); 3019 new->MMPR0 = 0x10000; /* Still more FIFO slots */ 3020 } 3021 S3VCommonCalcClock(pScrn, mode, dclk, 1, 1, 31, 0, 3, 3022 135000, 270000, &new->SR13, &new->SR12); 3023 } /* end DXGX if() */ 3024 else { /* Everything else ... (only ViRGE) */ 3025 if (pScrn->bitsPerPixel == 8) { 3026 if(dclk > 80000) { /* We need pixmux */ 3027 new->CR67 = 0x10; 3028 new->SR15 |= 0x10; /* Set DCLK/2 bit */ 3029 new->SR18 = 0x80; /* Enable pixmux */ 3030 } 3031 } 3032 else if ((pScrn->bitsPerPixel == 16) && (pScrn->weight.green == 5)) { 3033 new->CR67 = 0x30; /* 15bpp */ 3034 } 3035 else if (pScrn->bitsPerPixel == 16) { 3036 new->CR67 = 0x50; 3037 } 3038 else if (pScrn->bitsPerPixel == 24) { 3039 new->CR67 = 0xd0 | 0x0c; 3040 /* Flag STREAMS proc. required */ 3041 ps3v->NeedSTREAMS = TRUE; 3042 S3VInitSTREAMS(pScrn, new->STREAMS, mode); 3043 new->MMPR0 = 0xc000; /* Adjust FIFO slots */ 3044 } 3045 else if (pScrn->bitsPerPixel == 32) { 3046 new->CR67 = 0xd0 | 0x0c; 3047 /* Flag STREAMS proc. required */ 3048 ps3v->NeedSTREAMS = TRUE; 3049 S3VInitSTREAMS(pScrn, new->STREAMS, mode); 3050 new->MMPR0 = 0x10000; /* Still more FIFO slots */ 3051 } 3052 S3VCommonCalcClock(pScrn, mode, dclk, 1, 1, 31, 0, 3, 3053 135000, 270000, &new->SR13, &new->SR12); 3054 } /* end great big if()... */ 3055 3056 3057 /* Now adjust the value of the FIFO based upon options specified */ 3058 if( ps3v->fifo_moderate ) { 3059 if(pScrn->bitsPerPixel < 24) 3060 new->MMPR0 -= 0x8000; 3061 else 3062 new->MMPR0 -= 0x4000; 3063 } 3064 else if( ps3v->fifo_aggressive ) { 3065 if(pScrn->bitsPerPixel < 24) 3066 new->MMPR0 -= 0xc000; 3067 else 3068 new->MMPR0 -= 0x6000; 3069 } 3070 3071 /* If we have an interlace mode, set the interlace bit. Note that mode 3072 * vertical timings are already adjusted by the standard VGA code 3073 */ 3074 if(mode->Flags & V_INTERLACE) { 3075 new->CR42 = 0x20; /* Set interlace mode */ 3076 } 3077 else { 3078 new->CR42 = 0x00; 3079 } 3080 3081 if(S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 3082 S3_ViRGE_MX_SERIES(ps3v->Chipset) ) 3083 { 3084 new->CR34 = 0; 3085 } 3086 else 3087 { 3088 /* Set display fifo */ 3089 new->CR34 = 0x10; 3090 } 3091 /* Now we adjust registers for extended mode timings */ 3092 /* This is taken without change from the accel/s3_virge code */ 3093 3094 i = ((((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8) | 3095 ((((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) | 3096 ((((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) | 3097 ((mode->CrtcHSyncStart & 0x800) >> 7); 3098 3099 if ((mode->CrtcHSyncEnd >> 3) - (mode->CrtcHSyncStart >> 3) > 64) 3100 i |= 0x08; /* add another 64 DCLKs to blank pulse width */ 3101 3102 if ((mode->CrtcHSyncEnd >> 3) - (mode->CrtcHSyncStart >> 3) > 32) 3103 i |= 0x20; /* add another 32 DCLKs to hsync pulse width */ 3104 3105 /* video playback chokes if sync start and display end are equal */ 3106 if (mode->CrtcHSyncStart - mode->CrtcHDisplay < ps3v->HorizScaleFactor) { 3107 int tmp = vganew->CRTC[4] + ((i&0x10)<<4) + ps3v->HorizScaleFactor; 3108 vganew->CRTC[4] = tmp & 0xff; 3109 i |= ((tmp >> 4) & 0x10); 3110 } 3111 3112 j = ( vganew->CRTC[0] + ((i&0x01)<<8) 3113 + vganew->CRTC[4] + ((i&0x10)<<4) + 1) / 2; 3114 3115 if (j-(vganew->CRTC[4] + ((i&0x10)<<4)) < 4) { 3116 if (vganew->CRTC[4] + ((i&0x10)<<4) + 4 <= vganew->CRTC[0]+ ((i&0x01)<<8)) 3117 j = vganew->CRTC[4] + ((i&0x10)<<4) + 4; 3118 else 3119 j = vganew->CRTC[0]+ ((i&0x01)<<8) + 1; 3120 } 3121 new->CR3B = j & 0xFF; 3122 i |= (j & 0x100) >> 2; 3123 new->CR3C = (vganew->CRTC[0] + ((i&0x01)<<8))/2; 3124 new->CR5D = i; 3125 3126 new->CR5E = (((mode->CrtcVTotal - 2) & 0x400) >> 10) | 3127 (((mode->CrtcVDisplay - 1) & 0x400) >> 9) | 3128 (((mode->CrtcVSyncStart) & 0x400) >> 8) | 3129 (((mode->CrtcVSyncStart) & 0x400) >> 6) | 0x40; 3130 3131 3132 width = (pScrn->displayWidth * (pScrn->bitsPerPixel / 8))>> 3; 3133 vganew->CRTC[19] = 0xFF & width; 3134 new->CR51 = (0x300 & width) >> 4; /* Extension bits */ 3135 3136 /* Set doublescan */ 3137 if( mode->Flags & V_DBLSCAN) 3138 vganew->CRTC[9] |= 0x80; 3139 3140 /* And finally, select clock source 2 for programmable PLL */ 3141 vganew->MiscOutReg |= 0x0c; 3142 3143 3144 new->CR33 = 0x20; 3145 if (S3_TRIO_3D_2X_SERIES(ps3v->Chipset) || S3_ViRGE_GX2_SERIES(ps3v->Chipset) 3146 /* MXTESTME */ || S3_ViRGE_MX_SERIES(ps3v->Chipset) ) 3147 { 3148 new->CR85 = 0x12; /* avoid sreen flickering */ 3149 /* by increasing FIFO filling, larger # fills FIFO from memory earlier */ 3150 /* on GX2 this affects all depths, not just those running STREAMS. */ 3151 /* new, secondary stream settings. */ 3152 new->CR87 = 0x10; 3153 /* gx2 - set up in XV init code */ 3154 new->CR92 = 0x00; 3155 new->CR93 = 0x00; 3156 /* gx2 primary mclk timeout, def=0xb */ 3157 new->CR7B = 0xb; 3158 /* gx2 secondary mclk timeout, def=0xb */ 3159 new->CR7D = 0xb; 3160 } 3161 if (ps3v->Chipset == S3_ViRGE_DXGX || S3_TRIO_3D_SERIES(ps3v->Chipset)) { 3162 new->CR86 = 0x80; /* disable DAC power saving to avoid bright left edge */ 3163 } 3164 if (ps3v->Chipset == S3_ViRGE_DXGX || S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 3165 S3_ViRGE_MX_SERIES(ps3v->Chipset) || S3_TRIO_3D_SERIES(ps3v->Chipset)) { 3166 int dbytes = pScrn->displayWidth * ((pScrn->bitsPerPixel+7)/8); 3167 new->CR91 = (dbytes + 7) / 8; 3168 new->CR90 = (((dbytes + 7) / 8) >> 8) | 0x80; 3169 } 3170 3171 3172 /* Now we handle various XConfig memory options and others */ 3173 3174 VGAOUT8(vgaCRIndex, 0x36); 3175 new->CR36 = VGAIN8(vgaCRReg); 3176 /* option "slow_edodram" sets EDO to 2 cycle mode on ViRGE */ 3177 if (ps3v->Chipset == S3_ViRGE) { 3178 if( ps3v->slow_edodram ) 3179 new->CR36 = (new->CR36 & 0xf3) | 0x08; 3180 else 3181 new->CR36 &= 0xf3; 3182 } 3183 3184 /* Option "fpm_vram" for ViRGE_VX sets memory in fast page mode */ 3185 if (ps3v->Chipset == S3_ViRGE_VX) { 3186 if( ps3v->fpm_vram ) 3187 new->CR36 |= 0x0c; 3188 else 3189 new->CR36 &= ~0x0c; 3190 } 3191 3192 /* S3_INVERT_VCLK was defaulted to 0 */ 3193 /* in 3.3.3 and never changed. */ 3194 /* Also, bit 0 is never set in 3.9Nm, */ 3195 /* so I left this out for 4.0. */ 3196#if 0 3197 if (mode->Private[0] & (1 << S3_INVERT_VCLK)) { 3198 if (mode->Private[S3_INVERT_VCLK]) 3199 new->CR67 |= 1; 3200 else 3201 new->CR67 &= ~1; 3202 } 3203#endif 3204 /* S3_BLANK_DELAY settings based on */ 3205 /* defaults only. From 3.3.3 */ 3206 { 3207 int blank_delay; 3208 3209 if(ps3v->Chipset == S3_ViRGE_VX) 3210 /* these values need to be changed once CR67_1 is set 3211 for gamma correction (see S3V server) ! */ 3212 if (pScrn->bitsPerPixel == 8) 3213 blank_delay = 0x00; 3214 else if (pScrn->bitsPerPixel == 16) 3215 blank_delay = 0x00; 3216 else 3217 blank_delay = 0x51; 3218 else 3219 if (pScrn->bitsPerPixel == 8) 3220 blank_delay = 0x00; 3221 else if (pScrn->bitsPerPixel == 16) 3222 blank_delay = 0x02; 3223 else 3224 blank_delay = 0x04; 3225 3226 if (ps3v->Chipset == S3_ViRGE_VX) 3227 new->CR6D = blank_delay; 3228 else { 3229 new->CR65 = (new->CR65 & ~0x38) 3230 | (blank_delay & 0x07) << 3; 3231 VGAOUT8(vgaCRIndex, 0x6d); 3232 new->CR6D = VGAIN8(vgaCRReg); 3233 } 3234 } 3235 /* S3_EARLY_SC was defaulted to 0 */ 3236 /* in 3.3.3 and never changed. */ 3237 /* Also, bit 1 is never set in 3.9Nm, */ 3238 /* so I left this out for 4.0. */ 3239#if 0 3240 if (mode->Private[0] & (1 << S3_EARLY_SC)) { 3241 if (mode->Private[S3_EARLY_SC]) 3242 new->CR65 |= 2; 3243 else 3244 new->CR65 &= ~2; 3245 } 3246#endif 3247 3248 VGAOUT8(vgaCRIndex, 0x68); 3249 new->CR68 = VGAIN8(vgaCRReg); 3250 new->CR69 = 0; 3251 3252 /* Flat panel centering and expansion registers */ 3253 if (S3_ViRGE_MX_SERIES(ps3v->Chipset) && (ps3v->lcd_center)) { 3254 new->SR54 = 0x10 ; 3255 new->SR55 = 0x80 ; 3256 new->SR56 = 0x10 ; 3257 new->SR57 = 0x80 ; 3258 } else { 3259 new->SR54 = 0x1f ; 3260 new->SR55 = 0x9f ; 3261 new->SR56 = 0x1f ; 3262 new->SR57 = 0xff ; 3263 } 3264 3265 pScrn->vtSema = TRUE; 3266 3267 /* Do it! Write the mode registers */ 3268 /* to hardware, start STREAMS if */ 3269 /* needed, etc. */ 3270 S3VWriteMode( pScrn, vganew, new ); 3271 /* Adjust the viewport */ 3272 S3VAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 3273 3274 return TRUE; 3275} 3276 3277 3278/* 3279 * This is called at the end of each server generation. It restores the 3280 * original (text) mode. It should also unmap the video memory, and free 3281 * any per-generation data allocated by the driver. It should finish 3282 * by unwrapping and calling the saved CloseScreen function. 3283 */ 3284 3285/* Mandatory */ 3286static Bool 3287S3VCloseScreen(CLOSE_SCREEN_ARGS_DECL) 3288{ 3289 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 3290 vgaHWPtr hwp = VGAHWPTR(pScrn); 3291 S3VPtr ps3v = S3VPTR(pScrn); 3292 vgaRegPtr vgaSavePtr = &hwp->SavedReg; 3293 S3VRegPtr S3VSavePtr = &ps3v->SavedReg; 3294 3295 /* Like S3VRestore, but uses passed */ 3296 /* mode registers. */ 3297 if (pScrn->vtSema) { 3298 S3VWriteMode(pScrn, vgaSavePtr, S3VSavePtr); 3299 vgaHWLock(hwp); 3300 S3VDisableMmio(pScrn); 3301 S3VUnmapMem(pScrn); 3302 } 3303 3304#ifdef HAVE_XAA_H 3305 if (ps3v->AccelInfoRec) 3306 XAADestroyInfoRec(ps3v->AccelInfoRec); 3307#endif 3308 if (ps3v->DGAModes) 3309 free(ps3v->DGAModes); 3310 3311 pScrn->vtSema = FALSE; 3312 3313 pScreen->CloseScreen = ps3v->CloseScreen; 3314 3315 return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); 3316} 3317 3318 3319 3320 3321/* Do screen blanking */ 3322 3323/* Mandatory */ 3324static Bool 3325S3VSaveScreen(ScreenPtr pScreen, int mode) 3326{ 3327 return vgaHWSaveScreen(pScreen, mode); 3328} 3329 3330 3331 3332 3333 3334/* This function inits the STREAMS processor variables. 3335 * This has essentially been taken from the accel/s3_virge code and the databook. 3336 */ 3337static void 3338S3VInitSTREAMS(ScrnInfoPtr pScrn, unsigned int *streams, DisplayModePtr mode) 3339{ 3340 PVERB5(" S3VInitSTREAMS\n"); 3341 3342 switch (pScrn->bitsPerPixel) 3343 { 3344 case 16: 3345 streams[0] = 0x05000000; 3346 break; 3347 case 24: 3348 /* data format 8.8.8 (24 bpp) */ 3349 streams[0] = 0x06000000; 3350 break; 3351 case 32: 3352 /* one more bit for X.8.8.8, 32 bpp */ 3353 streams[0] = 0x07000000; 3354 break; 3355 } 3356 /* NO chroma keying... */ 3357 streams[1] = 0x0; 3358 /* Secondary stream format KRGB-16 */ 3359 /* data book suggestion... */ 3360 streams[2] = 0x03000000; 3361 3362 streams[3] = 0x0; 3363 3364 streams[4] = 0x0; 3365 /* use 0x01000000 for primary over second. */ 3366 /* use 0x0 for second over prim. */ 3367 streams[5] = 0x01000000; 3368 3369 streams[6] = 0x0; 3370 3371 streams[7] = 0x0; 3372 /* Stride is 3 bytes for 24 bpp mode and */ 3373 /* 4 bytes for 32 bpp. */ 3374 switch(pScrn->bitsPerPixel) 3375 { 3376 case 16: 3377 streams[8] = 3378 pScrn->displayWidth * 2; 3379 break; 3380 case 24: 3381 streams[8] = 3382 pScrn->displayWidth * 3; 3383 break; 3384 case 32: 3385 streams[8] = 3386 pScrn->displayWidth * 4; 3387 break; 3388 } 3389 /* Choose fbaddr0 as stream source. */ 3390 streams[9] = 0x0; 3391 streams[10] = 0x0; 3392 streams[11] = 0x0; 3393 streams[12] = 0x1; 3394 3395 /* Set primary stream on top of secondary */ 3396 /* stream. */ 3397 streams[13] = 0xc0000000; 3398 /* Vertical scale factor. */ 3399 streams[14] = 0x0; 3400 3401 streams[15] = 0x0; 3402 /* Vertical accum. initial value. */ 3403 streams[16] = 0x0; 3404 /* X and Y start coords + 1. */ 3405 streams[18] = 0x00010001; 3406 3407 /* Specify window Width -1 and Height of */ 3408 /* stream. */ 3409 streams[19] = 3410 (mode->HDisplay - 1) << 16 | 3411 (mode->VDisplay); 3412 3413 /* Book says 0x07ff07ff. */ 3414 streams[20] = 0x07ff07ff; 3415 3416 streams[21] = 0x00010001; 3417 3418} 3419 3420 3421 3422 3423/* Used to adjust start address in frame buffer. We use the new 3424 * CR69 reg for this purpose instead of the older CR31/CR51 combo. 3425 * If STREAMS is running, we program the STREAMS start addr. registers. 3426 */ 3427 3428void 3429S3VAdjustFrame(ADJUST_FRAME_ARGS_DECL) 3430{ 3431 SCRN_INFO_PTR(arg); 3432 vgaHWPtr hwp = VGAHWPTR(pScrn); 3433 S3VPtr ps3v = S3VPTR(pScrn); 3434 int Base; 3435 int vgaCRIndex, vgaCRReg, vgaIOBase; 3436 vgaIOBase = hwp->IOBase; 3437 vgaCRIndex = vgaIOBase + 4; 3438 vgaCRReg = vgaIOBase + 5; 3439 3440 if(ps3v->ShowCache && y) 3441 y += pScrn->virtualY - 1; 3442 3443 if( (ps3v->STREAMSRunning == FALSE) || 3444 S3_ViRGE_GX2_SERIES(ps3v->Chipset) || S3_ViRGE_MX_SERIES(ps3v->Chipset)) { 3445 Base = ((y * pScrn->displayWidth + x) 3446 * (pScrn->bitsPerPixel / 8)) >> 2; 3447 if (pScrn->bitsPerPixel == 24) 3448 Base = Base+2 - (Base+2) % 3; 3449 if (pScrn->bitsPerPixel == 16) 3450 if (S3_TRIO_3D_SERIES(ps3v->Chipset) && pScrn->modes->Clock > 115000) 3451 Base &= ~1; 3452 3453 /* Now program the start address registers */ 3454 VGAOUT16(vgaCRIndex, (Base & 0x00FF00) | 0x0C); 3455 VGAOUT16(vgaCRIndex, ((Base & 0x00FF) << 8) | 0x0D); 3456 VGAOUT8(vgaCRIndex, 0x69); 3457 VGAOUT8(vgaCRReg, (Base & 0x0F0000) >> 16); 3458 } 3459 else { /* Change start address for STREAMS case */ 3460 VerticalRetraceWait(); 3461 if(ps3v->Chipset == S3_ViRGE_VX) 3462 OUTREG(PSTREAM_FBADDR0_REG, 3463 ((y * pScrn->displayWidth + (x & ~7)) * 3464 pScrn->bitsPerPixel / 8)); 3465 else 3466 OUTREG(PSTREAM_FBADDR0_REG, 3467 ((y * pScrn->displayWidth + (x & ~3)) * 3468 pScrn->bitsPerPixel / 8)); 3469 } 3470 3471 return; 3472} 3473 3474 3475 3476 3477/* Usually mandatory */ 3478Bool 3479S3VSwitchMode(SWITCH_MODE_ARGS_DECL) 3480{ 3481 SCRN_INFO_PTR(arg); 3482 return S3VModeInit(pScrn, mode); 3483} 3484 3485 3486 3487void S3VLoadPalette( 3488 ScrnInfoPtr pScrn, 3489 int numColors, 3490 int *indicies, 3491 LOCO *colors, 3492 VisualPtr pVisual 3493){ 3494 S3VPtr ps3v = S3VPTR(pScrn); 3495 int i, index; 3496 3497 for(i = 0; i < numColors; i++) { 3498 index = indicies[i]; 3499 VGAOUT8(0x3c8, index); 3500 VGAOUT8(0x3c9, colors[index].red); 3501 VGAOUT8(0x3c9, colors[index].green); 3502 VGAOUT8(0x3c9, colors[index].blue); 3503 } 3504} 3505 3506 3507/* 3508 * Functions to support getting a ViRGE card into MMIO mode if it fails to 3509 * default to MMIO enabled. 3510 */ 3511 3512void 3513S3VEnableMmio(ScrnInfoPtr pScrn) 3514{ 3515 vgaHWPtr hwp; 3516 S3VPtr ps3v; 3517 unsigned int vgaCRIndex, vgaCRReg; 3518 unsigned char val; 3519 unsigned int PIOOffset = 0; 3520 3521 PVERB5(" S3VEnableMmio\n"); 3522 3523 hwp = VGAHWPTR(pScrn); 3524 ps3v = S3VPTR(pScrn); 3525 3526#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 3527 PIOOffset = hwp->PIOOffset; 3528#endif 3529 3530 /* 3531 * enable chipset (seen on uninitialized secondary cards) 3532 * might not be needed once we use the VGA softbooter 3533 * (EE 05/04/99) 3534 */ 3535 vgaHWSetStdFuncs(hwp); 3536 /* 3537 * any access to the legacy VGA ports is done here. 3538 * If legacy VGA is inaccessable the MMIO base _has_ 3539 * to be set correctly already and MMIO _has_ to be 3540 * enabled. 3541 */ 3542 val = inb(PIOOffset + 0x3C3); /*@@@EE*/ 3543 outb(PIOOffset + 0x3C3, val | 0x01); 3544 /* 3545 * set CR registers to color mode 3546 * in mono mode extended CR registers 3547 * are not accessible. (EE 05/04/99) 3548 */ 3549 val = inb(PIOOffset + VGA_MISC_OUT_R); /*@@@EE*/ 3550 outb(PIOOffset + VGA_MISC_OUT_W, val | 0x01); 3551 vgaHWGetIOBase(hwp); /* Get VGA I/O base */ 3552 vgaCRIndex = PIOOffset + hwp->IOBase + 4; 3553 vgaCRReg = vgaCRIndex + 1; 3554#if 1 3555 /* 3556 * set linear base register to the PCI register values 3557 * some DX chipsets don't seem to do it automatically 3558 * (EE 06/03/99) 3559 */ 3560 outb(vgaCRIndex, 0x59); /*@@@EE*/ 3561 outb(vgaCRReg, PCI_REGION_BASE(ps3v->PciInfo, 0, REGION_MEM) >> 24); 3562 outb(vgaCRIndex, 0x5A); 3563 outb(vgaCRReg, PCI_REGION_BASE(ps3v->PciInfo, 0, REGION_MEM) >> 16); 3564 outb(vgaCRIndex, 0x53); 3565#endif 3566 /* Save register for restore */ 3567 ps3v->EnableMmioCR53 = inb(vgaCRReg); 3568 /* Enable new MMIO, if TRIO mmio is already */ 3569 /* enabled, then it stays enabled. */ 3570 outb(vgaCRReg, ps3v->EnableMmioCR53 | 0x08); 3571 outb(PIOOffset + VGA_MISC_OUT_W, val); 3572 if (S3_TRIO_3D_SERIES(ps3v->Chipset)) { 3573 outb(vgaCRIndex, 0x40); 3574 val = inb(vgaCRReg); 3575 outb(vgaCRReg, val | 1); 3576 } 3577} 3578 3579 3580 3581void 3582S3VDisableMmio(ScrnInfoPtr pScrn) 3583{ 3584 vgaHWPtr hwp; 3585 S3VPtr ps3v; 3586 unsigned int vgaCRIndex, vgaCRReg; 3587 3588 PVERB5(" S3VDisableMmio\n"); 3589 3590 hwp = VGAHWPTR(pScrn); 3591 ps3v = S3VPTR(pScrn); 3592 3593 vgaCRIndex = hwp->IOBase + 4; 3594#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 3595 vgaCRIndex += hwp->PIOOffset; 3596#endif 3597 vgaCRReg = vgaCRIndex + 1; 3598 outb(vgaCRIndex, 0x53); 3599 /* Restore register's original state */ 3600 outb(vgaCRReg, ps3v->EnableMmioCR53); 3601 if (S3_TRIO_3D_SERIES(ps3v->Chipset)) { 3602 unsigned char val; 3603 outb(vgaCRIndex, 0x40); 3604 val = inb(vgaCRReg); 3605 outb(vgaCRReg, val | 1); 3606 } 3607} 3608 3609 3610 3611/* This function is used to debug, it prints out the contents of s3 regs */ 3612 3613static void 3614S3VPrintRegs(ScrnInfoPtr pScrn) 3615{ 3616 unsigned char tmp1, tmp2; 3617 vgaHWPtr hwp = VGAHWPTR(pScrn); 3618 S3VPtr ps3v = S3VPTR(pScrn); 3619 int vgaCRIndex, vgaCRReg, vgaIOBase, vgaIR; 3620 vgaIOBase = hwp->IOBase; 3621 vgaCRIndex = vgaIOBase + 4; 3622 vgaCRReg = vgaIOBase + 5; 3623 vgaIR = vgaIOBase + 0xa; 3624 3625/* All registers */ 3626/* New formatted registers, matches s3rc (sort of) */ 3627 xf86DrvMsgVerb( pScrn->scrnIndex, X_INFO, VERBLEV, "START register dump ------------------\n"); 3628 xf86ErrorFVerb(VERBLEV, "Misc Out[3CC]\n "); 3629 xf86ErrorFVerb(VERBLEV, "%02x\n",VGAIN8(0x3cc)); 3630 3631 xf86ErrorFVerb(VERBLEV, "\nCR[00-2f]\n "); 3632 for(tmp1=0x0;tmp1<=0x2f;tmp1++){ 3633 VGAOUT8(vgaCRIndex, tmp1); 3634 xf86ErrorFVerb(VERBLEV, "%02x ",VGAIN8(vgaCRReg)); 3635 if((tmp1 & 0x3) == 0x3) xf86ErrorFVerb(VERBLEV, " "); 3636 if((tmp1 & 0xf) == 0xf) xf86ErrorFVerb(VERBLEV, "\n "); 3637 } 3638 3639 xf86ErrorFVerb(VERBLEV, "\nSR[00-27]\n "); 3640 for(tmp1=0x0;tmp1<=0x27;tmp1++){ 3641 VGAOUT8(0x3c4, tmp1); 3642 xf86ErrorFVerb(VERBLEV, "%02x ",VGAIN8(0x3c5)); 3643 if((tmp1 & 0x3) == 0x3) xf86ErrorFVerb(VERBLEV, " "); 3644 if((tmp1 & 0xf) == 0xf) xf86ErrorFVerb(VERBLEV, "\n "); 3645 } 3646 xf86ErrorFVerb(VERBLEV, "\n"); /* odd hex number of digits... */ 3647 3648 xf86ErrorFVerb(VERBLEV, "\nGr Cont GR[00-0f]\n "); 3649 for(tmp1=0x0;tmp1<=0x0f;tmp1++){ 3650 VGAOUT8(0x3ce, tmp1); 3651 xf86ErrorFVerb(VERBLEV, "%02x ",VGAIN8(0x3cf)); 3652 if((tmp1 & 0x3) == 0x3) xf86ErrorFVerb(VERBLEV, " "); 3653 if((tmp1 & 0xf) == 0xf) xf86ErrorFVerb(VERBLEV, "\n "); 3654 } 3655 3656 xf86ErrorFVerb(VERBLEV, "\nAtt Cont AR[00-1f]\n "); 3657 VGAIN8(vgaIR); /* preset AR flip-flop by reading 3DA, ignore return value */ 3658 tmp2=VGAIN8(0x3c0) & 0x20; 3659 for(tmp1=0x0;tmp1<=0x1f;tmp1++){ 3660 VGAIN8(vgaIR); /* preset AR flip-flop by reading 3DA, ignore return value */ 3661 VGAOUT8(0x3c0, (tmp1 & ~0x20) | tmp2); 3662 xf86ErrorFVerb(VERBLEV, "%02x ",VGAIN8(0x3c1)); 3663 if((tmp1 & 0x3) == 0x3) xf86ErrorFVerb(VERBLEV, " "); 3664 if((tmp1 & 0xf) == 0xf) xf86ErrorFVerb(VERBLEV, "\n "); 3665 } 3666 3667 xf86ErrorFVerb(VERBLEV, "\nCR[30-6f]\n "); 3668 for(tmp1=0x30;tmp1<=0x6f;tmp1++){ 3669 VGAOUT8(vgaCRIndex, tmp1); 3670 xf86ErrorFVerb(VERBLEV, "%02x ",VGAIN8(vgaCRReg)); 3671 if((tmp1 & 0x3) == 0x3) xf86ErrorFVerb(VERBLEV, " "); 3672 if((tmp1 & 0xf) == 0xf) xf86ErrorFVerb(VERBLEV, "\n "); 3673 } 3674 3675 xf86ErrorFVerb(VERBLEV, "\n"); 3676 xf86DrvMsgVerb( pScrn->scrnIndex, X_INFO, VERBLEV, "END register dump --------------------\n"); 3677} 3678 3679/* this is just a debugger hook */ 3680/* 3681void print_subsys_stat(void *s3vMmioMem); 3682void 3683print_subsys_stat(void *s3vMmioMem) 3684{ 3685 ErrorF("IN_SUBSYS_STAT() = %x\n", IN_SUBSYS_STAT()); 3686 return; 3687} 3688*/ 3689 3690/* 3691 * S3VDisplayPowerManagementSet -- 3692 * 3693 * Sets VESA Display Power Management Signaling (DPMS) Mode. 3694 */ 3695static void 3696S3VDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, 3697 int flags) 3698{ 3699 S3VPtr ps3v; 3700 unsigned char sr8 = 0x0, srd = 0x0; 3701 char modestr[][40] = { "On","Standby","Suspend","Off" }; 3702 3703 ps3v = S3VPTR(pScrn); 3704 3705 /* unlock extended sequence registers */ 3706 3707 VGAOUT8(0x3c4, 0x08); 3708 sr8 = VGAIN8(0x3c5); 3709 sr8 |= 0x6; 3710 VGAOUT8(0x3c5, sr8); 3711 3712 /* load SRD */ 3713 VGAOUT8(0x3c4, 0x0d); 3714 srd = VGAIN8(0x3c5); 3715 3716 srd &= 0x03; /* clear the sync control bits of srd */ 3717 3718 switch (PowerManagementMode) { 3719 case DPMSModeOn: 3720 /* Screen: On; HSync: On, VSync: On */ 3721 break; 3722 case DPMSModeStandby: 3723 /* Screen: Off; HSync: Off, VSync: On */ 3724 srd |= 0x10; 3725 break; 3726 case DPMSModeSuspend: 3727 /* Screen: Off; HSync: On, VSync: Off */ 3728 srd |= 0x40; 3729 break; 3730 case DPMSModeOff: 3731 /* Screen: Off; HSync: Off, VSync: Off */ 3732 srd |= 0x50; 3733 break; 3734 default: 3735 xf86ErrorFVerb(VERBLEV, "Invalid PowerManagementMode %d passed to S3VDisplayPowerManagementSet\n", PowerManagementMode); 3736 break; 3737 } 3738 3739 VGAOUT8(0x3c4, 0x0d); 3740 VGAOUT8(0x3c5, srd); 3741 3742 xf86ErrorFVerb(VERBLEV, "Power Manag: set:%s\n", 3743 modestr[PowerManagementMode]); 3744 3745 return; 3746} 3747 3748static unsigned int 3749S3Vddc1Read(ScrnInfoPtr pScrn) 3750{ 3751 register vgaHWPtr hwp = VGAHWPTR(pScrn); 3752 register CARD32 tmp; 3753 S3VPtr ps3v = S3VPTR(pScrn); 3754 3755 while (hwp->readST01(hwp)&0x8) {}; 3756 while (!(hwp->readST01(hwp)&0x8)) {}; 3757 3758 tmp = (INREG(DDC_REG)); 3759 return ((unsigned int) (tmp & 0x08)); 3760} 3761 3762static void 3763S3Vddc1SetSpeed(ScrnInfoPtr pScrn, xf86ddcSpeed speed) 3764{ 3765 vgaHWddc1SetSpeed(pScrn, speed); 3766} 3767 3768static Bool 3769S3Vddc1(ScrnInfoPtr pScrn) 3770{ 3771 S3VPtr ps3v = S3VPTR(pScrn); 3772 CARD32 tmp; 3773 Bool success = FALSE; 3774 xf86MonPtr pMon; 3775 3776 /* initialize chipset */ 3777 tmp = INREG(DDC_REG); 3778 OUTREG(DDC_REG,(tmp | 0x12)); 3779 3780 if ((pMon = xf86PrintEDID( 3781 xf86DoEDID_DDC1(XF86_SCRN_ARG(pScrn), S3Vddc1SetSpeed, 3782 S3Vddc1Read))) != NULL) 3783 success = TRUE; 3784 xf86SetDDCproperties(pScrn,pMon); 3785 3786 /* undo initialization */ 3787 OUTREG(DDC_REG,(tmp)); 3788 return success; 3789} 3790 3791static Bool 3792S3Vddc2(ScrnInfoPtr pScrn) 3793{ 3794 S3VPtr ps3v = S3VPTR(pScrn); 3795 3796 if ( xf86LoadSubModule(pScrn, "i2c") ) { 3797 if (S3V_I2CInit(pScrn)) { 3798 CARD32 tmp = (INREG(DDC_REG)); 3799 OUTREG(DDC_REG,(tmp | 0x13)); 3800 xf86SetDDCproperties(pScrn,xf86PrintEDID( 3801 xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn),ps3v->I2C))); 3802 OUTREG(DDC_REG,tmp); 3803 return TRUE; 3804 } 3805 } 3806 return FALSE; 3807} 3808 3809static void 3810S3VProbeDDC(ScrnInfoPtr pScrn, int index) 3811{ 3812 vbeInfoPtr pVbe; 3813 if (xf86LoadSubModule(pScrn, "vbe")) { 3814 pVbe = VBEInit(NULL,index); 3815 ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 3816 vbeFree(pVbe); 3817 } 3818} 3819 3820/*EOF*/ 3821 3822 3823