sis_driver.c revision 72b676d7
1/* $XFree86$ */ 2/* $XdotOrg: driver/xf86-video-sis/src/sis_driver.c,v 1.72 2006/03/09 06:06:25 anholt Exp $ */ 3/* 4 * SiS driver main code 5 * 6 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1) Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2) Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3) The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Author: Thomas Winischhofer <thomas@winischhofer.net> 31 * - driver entirely rewritten since 2001, only basic structure taken from 32 * old code (except sis_dri.c, sis_shadow.c, sis_accel.c and parts of 33 * sis_dga.c; these were mostly taken over; sis_dri.c was changed for 34 * new versions of the DRI layer) 35 * 36 * This notice covers the entire driver code unless indicated otherwise. 37 * 38 * Formerly based on code which was 39 * Copyright (C) 1998, 1999 by Alan Hourihane, Wigan, England. 40 * Written by: 41 * Alan Hourihane <alanh@fairlite.demon.co.uk>, 42 * Mike Chapman <mike@paranoia.com>, 43 * Juanjo Santamarta <santamarta@ctv.es>, 44 * Mitani Hiroshi <hmitani@drl.mei.co.jp>, 45 * David Thomas <davtom@dream.org.uk>. 46 */ 47 48#ifdef HAVE_CONFIG_H 49#include "config.h" 50#endif 51 52#include "sis.h" 53 54#include "xf86RAC.h" 55#include "dixstruct.h" 56#include "shadowfb.h" 57#include "fb.h" 58#include "micmap.h" 59#include "mibank.h" 60#include "mipointer.h" 61#include "mibstore.h" 62#define _XF86MISC_SERVER_ 63#include <X11/extensions/xf86misc.h> 64#include "edid.h" 65 66#define SIS_NEED_inSISREG 67#define SIS_NEED_inSISIDXREG 68#define SIS_NEED_outSISIDXREG 69#define SIS_NEED_orSISIDXREG 70#define SIS_NEED_andSISIDXREG 71#define SIS_NEED_setSISIDXREG 72#define SIS_NEED_outSISREG 73#define SIS_NEED_MYMMIO 74#define SIS_NEED_sisclearvram 75#include "sis_regs.h" 76#include "sis_dac.h" 77 78#include "sis_driver.h" 79 80#define _XF86DGA_SERVER_ 81#include <X11/extensions/xf86dgastr.h> 82 83#include "globals.h" 84 85#define DPMS_SERVER 86#include <X11/extensions/dpms.h> 87 88#ifdef XF86DRI 89#include "dri.h" 90#endif 91 92/* Globals (yes, these ARE really required to be global) */ 93 94#ifdef SISUSEDEVPORT 95int sisdevport = 0; 96#endif 97 98#ifdef SISDUALHEAD 99static int SISEntityIndex = -1; 100#endif 101 102#ifdef SISMERGED 103#ifdef SISXINERAMA 104static Bool SiSnoPanoramiXExtension = TRUE; 105static int SiSXineramaNumScreens = 0; 106static SiSXineramaData *SiSXineramadataPtr = NULL; 107static int SiSXineramaGeneration; 108 109static int SiSProcXineramaQueryVersion(ClientPtr client); 110static int SiSProcXineramaGetState(ClientPtr client); 111static int SiSProcXineramaGetScreenCount(ClientPtr client); 112static int SiSProcXineramaGetScreenSize(ClientPtr client); 113static int SiSProcXineramaIsActive(ClientPtr client); 114static int SiSProcXineramaQueryScreens(ClientPtr client); 115static int SiSSProcXineramaDispatch(ClientPtr client); 116#endif 117#endif 118 119/* 120 * This is intentionally screen-independent. It indicates the binding 121 * choice made in the first PreInit. 122 */ 123static int pix24bpp = 0; 124 125/* 126 * This contains the functions needed by the server after loading the driver 127 * module. It must be supplied, and gets passed back by the SetupProc 128 * function in the dynamic case. In the static case, a reference to this 129 * is compiled in, and this requires that the name of this DriverRec be 130 * an upper-case version of the driver name. 131 */ 132 133#ifdef _X_EXPORT 134_X_EXPORT 135#endif 136DriverRec SIS = { 137 SIS_CURRENT_VERSION, 138 SIS_DRIVER_NAME, 139 SISIdentify, 140 SISProbe, 141 SISAvailableOptions, 142 NULL, 143 0 144#ifdef SIS_HAVE_DRIVER_FUNC 145 , 146 SISDriverFunc 147#endif 148}; 149 150static SymTabRec SISChipsets[] = { 151 { PCI_CHIP_SIS5597, "SIS5597/5598" }, 152 { PCI_CHIP_SIS530, "SIS530/620" }, 153 { PCI_CHIP_SIS6326, "SIS6326/AGP/DVD" }, 154 { PCI_CHIP_SIS300, "SIS300/305" }, 155 { PCI_CHIP_SIS630, "SIS630/730" }, 156 { PCI_CHIP_SIS540, "SIS540" }, 157 { PCI_CHIP_SIS315, "SIS315" }, 158 { PCI_CHIP_SIS315H, "SIS315H" }, 159 { PCI_CHIP_SIS315PRO, "SIS315PRO/E" }, 160 { PCI_CHIP_SIS550, "SIS550" }, 161 { PCI_CHIP_SIS650, "SIS650/M650/651/740" }, 162 { PCI_CHIP_SIS330, "SIS330(Xabre)" }, 163 { PCI_CHIP_SIS660, "SIS660/[M]661[F|M]X/[M]670/[M]741[GX]/[M]760[GX]/[M]761[GX]/[M]770[GX]" }, 164 { PCI_CHIP_SIS340, "SIS340" }, 165 { -1, NULL } 166}; 167 168static PciChipsets SISPciChipsets[] = { 169 { PCI_CHIP_SIS5597, PCI_CHIP_SIS5597, RES_SHARED_VGA }, 170 { PCI_CHIP_SIS530, PCI_CHIP_SIS530, RES_SHARED_VGA }, 171 { PCI_CHIP_SIS6326, PCI_CHIP_SIS6326, RES_SHARED_VGA }, 172 { PCI_CHIP_SIS300, PCI_CHIP_SIS300, RES_SHARED_VGA }, 173 { PCI_CHIP_SIS630, PCI_CHIP_SIS630, RES_SHARED_VGA }, 174 { PCI_CHIP_SIS540, PCI_CHIP_SIS540, RES_SHARED_VGA }, 175 { PCI_CHIP_SIS550, PCI_CHIP_SIS550, RES_SHARED_VGA }, 176 { PCI_CHIP_SIS315, PCI_CHIP_SIS315, RES_SHARED_VGA }, 177 { PCI_CHIP_SIS315H, PCI_CHIP_SIS315H, RES_SHARED_VGA }, 178 { PCI_CHIP_SIS315PRO, PCI_CHIP_SIS315PRO, RES_SHARED_VGA }, 179 { PCI_CHIP_SIS650, PCI_CHIP_SIS650, RES_SHARED_VGA }, 180 { PCI_CHIP_SIS330, PCI_CHIP_SIS330, RES_SHARED_VGA }, 181 { PCI_CHIP_SIS660, PCI_CHIP_SIS660, RES_SHARED_VGA }, 182 { PCI_CHIP_SIS340, PCI_CHIP_SIS340, RES_SHARED_VGA }, 183 { -1, -1, RES_UNDEFINED } 184}; 185 186static SymTabRec XGIChipsets[] = { 187 { PCI_CHIP_XGIXG20, "Volari Z7 (XG20)" }, 188 { PCI_CHIP_XGIXG40, "Volari V3XT/V5/V8/Duo (XG40)" }, 189 { -1, NULL } 190}; 191 192static PciChipsets XGIPciChipsets[] = { 193 { PCI_CHIP_XGIXG20, PCI_CHIP_XGIXG20, RES_SHARED_VGA }, 194 { PCI_CHIP_XGIXG40, PCI_CHIP_XGIXG40, RES_SHARED_VGA }, 195 { -1, -1, RES_UNDEFINED } 196}; 197 198#ifdef SIS_USE_XAA 199static const char *xaaSymbols[] = { 200 "XAACreateInfoRec", 201 "XAADestroyInfoRec", 202 "XAAHelpPatternROP", 203 "XAAInit", 204 NULL 205}; 206#endif 207 208#ifdef SIS_USE_EXA 209static const char *exaSymbols[] = { 210 "exaDriverAccel", 211 "exaDriverInit", 212 "exaDriverFini", 213 "exaOffscreenAlloc", 214 "exaOffscreenFree", 215 NULL 216}; 217#endif 218 219static const char *fbSymbols[] = { 220 "fbPictureInit", 221 "fbScreenInit", 222 NULL 223}; 224 225static const char *shadowSymbols[] = { 226 "ShadowFBInit", 227 NULL 228}; 229 230static const char *ramdacSymbols[] = { 231 "xf86CreateCursorInfoRec", 232 "xf86DestroyCursorInfoRec", 233 "xf86InitCursor", 234 NULL 235}; 236 237static const char *ddcSymbols[] = { 238 "xf86PrintEDID", 239 "xf86SetDDCproperties", 240 "xf86InterpretEDID", 241 NULL 242}; 243 244static const char *int10Symbols[] = { 245 "xf86FreeInt10", 246 "xf86InitInt10", 247 NULL 248}; 249 250static const char *vbeSymbols[] = { 251#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 252 "VBEInit", 253#else 254 "VBEExtendedInit", 255#endif 256 "vbeDoEDID", 257 "vbeFree", 258 "VBEGetVBEInfo", 259 "VBEFreeVBEInfo", 260 "VBEGetModeInfo", 261 "VBEFreeModeInfo", 262 "VBESaveRestore", 263 "VBESetVBEMode", 264 "VBEGetVBEMode", 265 "VBESetDisplayStart", 266 "VBESetGetLogicalScanlineLength", 267 NULL 268}; 269 270#ifdef XF86DRI 271static const char *drmSymbols[] = { 272 "drmAddMap", 273 "drmAgpAcquire", 274 "drmAgpRelease", 275 "drmAgpAlloc", 276 "drmAgpFree", 277 "drmAgpBase", 278 "drmAgpBind", 279 "drmAgpUnbind", 280 "drmAgpEnable", 281 "drmAgpGetMode", 282 "drmCtlInstHandler", 283 "drmCtlUninstHandler", 284 "drmGetInterruptFromBusID", 285#ifndef SISHAVEDRMWRITE 286 "drmSiSAgpInit", 287#else 288 "drmCommandWrite", 289#endif 290#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 291 "drmGetVersion", 292 "drmFreeVersion", 293#endif 294 NULL 295}; 296 297static const char *driSymbols[] = { 298 "DRICreateInfoRec", 299 "DRIScreenInit", 300 "DRIFinishScreenInit", 301 "DRIDestroyInfoRec", 302 "DRICloseScreen", 303 "DRIGetSAREAPrivate", 304 "DRILock", 305 "DRIUnlock", 306 "DRIQueryVersion", 307 "GlxSetVisualConfigs", 308 NULL 309}; 310 311#ifdef XFree86LOADER 312static const char *driRefSymbols[] = { 313 "DRICreatePCIBusID", /* not REQUIRED, but eventually referenced */ 314 NULL 315}; 316#endif 317#endif /* XF86DRI */ 318 319#ifdef XFree86LOADER 320 321static MODULESETUPPROTO(sisSetup); 322 323static XF86ModuleVersionInfo sisVersRec = 324{ 325 SIS_DRIVER_NAME, 326 MODULEVENDORSTRING, 327 MODINFOSTRING1, 328 MODINFOSTRING2, 329#ifdef XORG_VERSION_CURRENT 330 XORG_VERSION_CURRENT, 331#else 332 XF86_VERSION_CURRENT, 333#endif 334 SIS_MAJOR_VERSION, SIS_MINOR_VERSION, SIS_PATCHLEVEL, 335 ABI_CLASS_VIDEODRV, /* This is a video driver */ 336 ABI_VIDEODRV_VERSION, 337 MOD_CLASS_VIDEODRV, 338 {0,0,0,0} 339}; 340 341#ifdef _X_EXPORT 342_X_EXPORT 343#endif 344XF86ModuleData sisModuleData = { &sisVersRec, sisSetup, NULL }; 345 346pointer 347sisSetup(pointer module, pointer opts, int *errmaj, int *errmin) 348{ 349 static Bool setupDone = FALSE; 350 351 if(!setupDone) { 352 setupDone = TRUE; 353 xf86AddDriver(&SIS, module, SIS_HaveDriverFuncs); 354 LoaderRefSymLists(fbSymbols, 355#ifdef SIS_USE_XAA 356 xaaSymbols, 357#endif 358#ifdef SIS_USE_EXA 359 exaSymbols, 360#endif 361 shadowSymbols, ramdacSymbols, 362 vbeSymbols, int10Symbols, 363#ifdef XF86DRI 364 drmSymbols, driSymbols, driRefSymbols, 365#endif 366 NULL); 367 return (pointer)TRUE; 368 } 369 370 if(errmaj) *errmaj = LDR_ONCEONLY; 371 return NULL; 372} 373 374#endif /* XFree86LOADER */ 375 376/* Mandatory */ 377static void 378SISIdentify(int flags) 379{ 380 xf86PrintChipsets(SIS_NAME, "driver for SiS chipsets", SISChipsets); 381 xf86PrintChipsets(SIS_NAME, "driver for XGI chipsets", XGIChipsets); 382} 383 384#ifdef SIS_HAVE_DRIVER_FUNC 385static Bool 386SISDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op, pointer ptr) 387{ 388 CARD32 *flag; 389 390 switch(op) { 391 case RR_GET_INFO: 392 break; 393 case RR_SET_CONFIG: 394 break; 395 case GET_REQUIRED_HW_INTERFACES: 396 break; 397 } 398 return TRUE; 399} 400#endif 401 402static Bool 403SISGetRec(ScrnInfoPtr pScrn) 404{ 405 /* Allocate an SISRec, and hook it into pScrn->driverPrivate. 406 * pScrn->driverPrivate is initialised to NULL, so we can check if 407 * the allocation has already been done. 408 */ 409 if(pScrn->driverPrivate != NULL) return TRUE; 410 411 pScrn->driverPrivate = xnfcalloc(sizeof(SISRec), 1); 412 413 /* Initialise it to 0 */ 414 memset(pScrn->driverPrivate, 0, sizeof(SISRec)); 415 416 return TRUE; 417} 418 419static void 420SISFreeRec(ScrnInfoPtr pScrn) 421{ 422 SISPtr pSiS = SISPTR(pScrn); 423#ifdef SISDUALHEAD 424 SISEntPtr pSiSEnt = NULL; 425#endif 426 427 /* Just to make sure... */ 428 if(!pSiS) return; 429 430#ifdef SISDUALHEAD 431 pSiSEnt = pSiS->entityPrivate; 432#endif 433 434 if(pSiS->pstate) xfree(pSiS->pstate); 435 pSiS->pstate = NULL; 436 if(pSiS->fonts) xfree(pSiS->fonts); 437 pSiS->fonts = NULL; 438 439#ifdef SISDUALHEAD 440 if(pSiSEnt) { 441 if(!pSiS->SecondHead) { 442 /* Free memory only if we are first head; in case of an error 443 * during init of the second head, the server will continue - 444 * and we need the BIOS image and SiS_Private for the first 445 * head. 446 */ 447 if(pSiSEnt->BIOS) xfree(pSiSEnt->BIOS); 448 pSiSEnt->BIOS = pSiS->BIOS = NULL; 449 if(pSiSEnt->SiS_Pr) xfree(pSiSEnt->SiS_Pr); 450 pSiSEnt->SiS_Pr = pSiS->SiS_Pr = NULL; 451 if(pSiSEnt->RenderAccelArray) xfree(pSiSEnt->RenderAccelArray); 452 pSiSEnt->RenderAccelArray = pSiS->RenderAccelArray = NULL; 453 pSiSEnt->pScrn_1 = NULL; 454 } else { 455 pSiS->BIOS = NULL; 456 pSiS->SiS_Pr = NULL; 457 pSiS->RenderAccelArray = NULL; 458 pSiSEnt->pScrn_2 = NULL; 459 } 460 } else { 461#endif 462 if(pSiS->BIOS) xfree(pSiS->BIOS); 463 pSiS->BIOS = NULL; 464 if(pSiS->SiS_Pr) xfree(pSiS->SiS_Pr); 465 pSiS->SiS_Pr = NULL; 466 if(pSiS->RenderAccelArray) xfree(pSiS->RenderAccelArray); 467 pSiS->RenderAccelArray = NULL; 468#ifdef SISDUALHEAD 469 } 470#endif 471#ifdef SISMERGED 472 if(pSiS->CRT2HSync) xfree(pSiS->CRT2HSync); 473 pSiS->CRT2HSync = NULL; 474 if(pSiS->CRT2VRefresh) xfree(pSiS->CRT2VRefresh); 475 pSiS->CRT2VRefresh = NULL; 476 if(pSiS->MetaModes) xfree(pSiS->MetaModes); 477 pSiS->MetaModes = NULL; 478 if(pSiS->CRT2pScrn) { 479 if(pSiS->CRT2pScrn->modes) { 480 while(pSiS->CRT2pScrn->modes) 481 xf86DeleteMode(&pSiS->CRT2pScrn->modes, pSiS->CRT2pScrn->modes); 482 } 483 if(pSiS->CRT2pScrn->monitor) { 484 if(pSiS->CRT2pScrn->monitor->Modes) { 485 while(pSiS->CRT2pScrn->monitor->Modes) 486 xf86DeleteMode(&pSiS->CRT2pScrn->monitor->Modes, pSiS->CRT2pScrn->monitor->Modes); 487 } 488 if(pSiS->CRT2pScrn->monitor->DDC) xfree(pSiS->CRT2pScrn->monitor->DDC); 489 xfree(pSiS->CRT2pScrn->monitor); 490 } 491 xfree(pSiS->CRT2pScrn); 492 pSiS->CRT2pScrn = NULL; 493 } 494 if(pSiS->CRT1Modes) { 495 if(pSiS->CRT1Modes != pScrn->modes) { 496 if(pScrn->modes) { 497 pScrn->currentMode = pScrn->modes; 498 do { 499 DisplayModePtr p = pScrn->currentMode->next; 500 if(pScrn->currentMode->Private) 501 xfree(pScrn->currentMode->Private); 502 xfree(pScrn->currentMode); 503 pScrn->currentMode = p; 504 } while(pScrn->currentMode != pScrn->modes); 505 } 506 pScrn->currentMode = pSiS->CRT1CurrentMode; 507 pScrn->modes = pSiS->CRT1Modes; 508 pSiS->CRT1CurrentMode = NULL; 509 pSiS->CRT1Modes = NULL; 510 } 511 } 512#endif 513 while(pSiS->SISVESAModeList) { 514 sisModeInfoPtr mp = pSiS->SISVESAModeList->next; 515 xfree(pSiS->SISVESAModeList); 516 pSiS->SISVESAModeList = mp; 517 } 518 if(pSiS->pVbe) vbeFree(pSiS->pVbe); 519 pSiS->pVbe = NULL; 520 521#ifdef SISUSEDEVPORT 522 if(pSiS->sisdevportopen) close(sisdevport); 523#endif 524 525 if(pScrn->driverPrivate == NULL) 526 return; 527 xfree(pScrn->driverPrivate); 528 pScrn->driverPrivate = NULL; 529} 530 531static void 532SISErrorLog(ScrnInfoPtr pScrn, const char *format, ...) 533{ 534 va_list ap; 535 static const char *str = "**************************************************\n"; 536 537 va_start(ap, format); 538 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, str); 539 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 540 " ERROR:\n"); 541 xf86VDrvMsgVerb(pScrn->scrnIndex, X_ERROR, 1, format, ap); 542 va_end(ap); 543 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 544 " END OF MESSAGE\n"); 545 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, str); 546} 547 548static void 549SiS_SiSFB_Lock(ScrnInfoPtr pScrn, Bool lock) 550{ 551 SISPtr pSiS = SISPTR(pScrn); 552 int fd; 553 CARD32 parm; 554 555 if(!pSiS->sisfbfound) return; 556 if(!pSiS->sisfb_havelock) return; 557 558 if((fd = open(pSiS->sisfbdevname, 'r')) != -1) { 559 parm = lock ? 1 : 0; 560 ioctl(fd, SISFB_SET_LOCK, &parm); 561 close(fd); 562 } 563} 564 565/* Probe() 566 * 567 * Mandatory 568 */ 569static Bool 570SISProbe(DriverPtr drv, int flags) 571{ 572 int i; 573 GDevPtr *devSections; 574 int *usedChipsSiS, *usedChipsXGI; 575 int numDevSections; 576 int numUsed, numUsedSiS, numUsedXGI; 577 Bool foundScreen = FALSE; 578 579 /* 580 * The aim here is to find all cards that this driver can handle, 581 * and for the ones not already claimed by another driver, claim the 582 * slot, and allocate a ScrnInfoRec. 583 * 584 * This should be a minimal probe, and it should under no circumstances 585 * change the state of the hardware. Because a device is found, don't 586 * assume that it will be used. Don't do any initialisations other than 587 * the required ScrnInfoRec initialisations. Don't allocate any new 588 * data structures. 589 * 590 */ 591 592 /* 593 * Next we check, if there has been a chipset override in the config file. 594 * For this we must find out if there is an active device section which 595 * is relevant, i.e., which has no driver specified or has THIS driver 596 * specified. 597 */ 598 599 if((numDevSections = xf86MatchDevice(SIS_DRIVER_NAME, &devSections)) <= 0) { 600 /* 601 * There's no matching device section in the config file, so quit 602 * now. 603 */ 604 return FALSE; 605 } 606 607 /* 608 * We need to probe the hardware first. We then need to see how this 609 * fits in with what is given in the config file, and allow the config 610 * file info to override any contradictions. 611 */ 612 613 /* 614 * All of the cards this driver supports are PCI, so the "probing" just 615 * amounts to checking the PCI data that the server has already collected. 616 */ 617 if(xf86GetPciVideoInfo() == NULL) { 618 /* 619 * We won't let anything in the config file override finding no 620 * PCI video cards at all. 621 */ 622 return FALSE; 623 } 624 625 numUsedSiS = xf86MatchPciInstances(SIS_NAME, PCI_VENDOR_SIS, 626 SISChipsets, SISPciChipsets, devSections, 627 numDevSections, drv, &usedChipsSiS); 628 629 numUsedXGI = xf86MatchPciInstances(SIS_NAME, PCI_VENDOR_XGI, 630 XGIChipsets, XGIPciChipsets, devSections, 631 numDevSections, drv, &usedChipsXGI); 632 633 /* Free it since we don't need that list after this */ 634 xfree(devSections); 635 636 numUsed = numUsedSiS + numUsedXGI; 637 638 if(numUsed <= 0) 639 return FALSE; 640 641 if(flags & PROBE_DETECT) { 642 643 foundScreen = TRUE; 644 645 } else for(i = 0; i < numUsed; i++) { 646 647 ScrnInfoPtr pScrn; 648#ifdef SISDUALHEAD 649 EntityInfoPtr pEnt; 650#endif 651 652 /* Allocate a ScrnInfoRec and claim the slot */ 653 pScrn = NULL; 654 655 if((pScrn = xf86ConfigPciEntity(pScrn, 0, 656 (i < numUsedSiS) ? usedChipsSiS[i] : usedChipsXGI[i-numUsedSiS], 657 (i < numUsedSiS) ? SISPciChipsets : XGIPciChipsets, 658 NULL, NULL, NULL, NULL, NULL))) { 659 /* Fill in what we can of the ScrnInfoRec */ 660 pScrn->driverVersion = SIS_CURRENT_VERSION; 661 pScrn->driverName = SIS_DRIVER_NAME; 662 pScrn->name = SIS_NAME; 663 pScrn->Probe = SISProbe; 664 pScrn->PreInit = SISPreInit; 665 pScrn->ScreenInit = SISScreenInit; 666 pScrn->SwitchMode = SISSwitchMode; 667 pScrn->AdjustFrame = SISAdjustFrame; 668 pScrn->EnterVT = SISEnterVT; 669 pScrn->LeaveVT = SISLeaveVT; 670 pScrn->FreeScreen = SISFreeScreen; 671 pScrn->ValidMode = SISValidMode; 672#ifdef X_XF86MiscPassMessage 673 if(xf86GetVersion() >= XF86_VERSION_NUMERIC(4,3,99,2,0)) { 674 pScrn->HandleMessage = SISHandleMessage; 675 } 676#endif 677 foundScreen = TRUE; 678 } 679 680#ifdef SISDUALHEAD 681 pEnt = xf86GetEntityInfo((i < numUsedSiS) ? usedChipsSiS[i] : usedChipsXGI[i-numUsedSiS]); 682 683 if(pEnt->chipset == PCI_CHIP_SIS630 || pEnt->chipset == PCI_CHIP_SIS540 || 684 pEnt->chipset == PCI_CHIP_SIS650 || pEnt->chipset == PCI_CHIP_SIS550 || 685 pEnt->chipset == PCI_CHIP_SIS315 || pEnt->chipset == PCI_CHIP_SIS315H || 686 pEnt->chipset == PCI_CHIP_SIS315PRO || pEnt->chipset == PCI_CHIP_SIS330 || 687 pEnt->chipset == PCI_CHIP_SIS300 || pEnt->chipset == PCI_CHIP_SIS660 || 688 pEnt->chipset == PCI_CHIP_SIS340 || pEnt->chipset == PCI_CHIP_XGIXG40) { 689 690 SISEntPtr pSiSEnt = NULL; 691 DevUnion *pPriv; 692 693 xf86SetEntitySharable((i < numUsedSiS) ? usedChipsSiS[i] : usedChipsXGI[i-numUsedSiS]); 694 if(SISEntityIndex < 0) { 695 SISEntityIndex = xf86AllocateEntityPrivateIndex(); 696 } 697 pPriv = xf86GetEntityPrivate(pScrn->entityList[0], SISEntityIndex); 698 if(!pPriv->ptr) { 699 pPriv->ptr = xnfcalloc(sizeof(SISEntRec), 1); 700 pSiSEnt = pPriv->ptr; 701 memset(pSiSEnt, 0, sizeof(SISEntRec)); 702 pSiSEnt->lastInstance = -1; 703 } else { 704 pSiSEnt = pPriv->ptr; 705 } 706 pSiSEnt->lastInstance++; 707 xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0], 708 pSiSEnt->lastInstance); 709 } 710#endif /* DUALHEAD */ 711 712 } 713 714 if(usedChipsSiS) xfree(usedChipsSiS); 715 if(usedChipsXGI) xfree(usedChipsXGI); 716 717 return foundScreen; 718} 719 720/* Various helpers */ 721 722static unsigned short 723calcgammaval(int j, int nramp, float invgamma, float bri, float c) 724{ 725 float k = (float)j; 726 float nrm1 = (float)(nramp - 1); 727 float con = c * nrm1 / 3.0; 728 float l, v; 729 730 if(con != 0.0) { 731 l = nrm1 / 2.0; 732 if(con <= 0.0) { 733 k -= l; 734 k *= (l + con) / l; 735 } else { 736 l -= 1.0; 737 k -= l; 738 k *= l / (l - con); 739 } 740 k += l; 741 if(k < 0.0) k = 0.0; 742 } 743 744 if(invgamma == 1.0) { 745 v = k / nrm1 * 65535.0; 746 } else { 747 v = pow(k / nrm1, invgamma) * 65535.0 + 0.5; 748 } 749 750 v += (bri * (65535.0 / 3.0)) ; 751 752 if(v < 0.0) v = 0.0; 753 else if(v > 65535.0) v = 65535.0; 754 755 return (unsigned short)v; 756} 757 758#ifdef SISGAMMARAMP 759void 760SISCalculateGammaRamp(ScreenPtr pScreen, ScrnInfoPtr pScrn) 761{ 762 SISPtr pSiS = SISPTR(pScrn); 763 int i, j, nramp; 764 UShort *ramp[3]; 765 float gamma_max[3], framp; 766 Bool newmethod = FALSE; 767 768 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_OLDGAMMAINUSE)) { 769 newmethod = TRUE; 770 } else { 771 gamma_max[0] = (float)pSiS->GammaBriR / 1000; 772 gamma_max[1] = (float)pSiS->GammaBriG / 1000; 773 gamma_max[2] = (float)pSiS->GammaBriB / 1000; 774 } 775 776 if(!(nramp = xf86GetGammaRampSize(pScreen))) return; 777 778 for(i=0; i<3; i++) { 779 ramp[i] = (UShort *)xalloc(nramp * sizeof(UShort)); 780 if(!ramp[i]) { 781 if(ramp[0]) { xfree(ramp[0]); ramp[0] = NULL; } 782 if(ramp[1]) { xfree(ramp[1]); ramp[1] = NULL; } 783 return; 784 } 785 } 786 787 if(newmethod) { 788 789 for(i = 0; i < 3; i++) { 790 791 float invgamma = 0.0, bri = 0.0, con = 0.0; 792 793 switch(i) { 794 case 0: invgamma = 1. / pScrn->gamma.red; 795 bri = pSiS->NewGammaBriR; 796 con = pSiS->NewGammaConR; 797 break; 798 case 1: invgamma = 1. / pScrn->gamma.green; 799 bri = pSiS->NewGammaBriG; 800 con = pSiS->NewGammaConG; 801 break; 802 case 2: invgamma = 1. / pScrn->gamma.blue; 803 bri = pSiS->NewGammaBriB; 804 con = pSiS->NewGammaConB; 805 break; 806 } 807 808 for(j = 0; j < nramp; j++) { 809 ramp[i][j] = calcgammaval(j, nramp, invgamma, bri, con); 810 } 811 812 } 813 814 } else { 815 816 for(i = 0; i < 3; i++) { 817 int fullscale = 65535 * gamma_max[i]; 818 float dramp = 1. / (nramp - 1); 819 float invgamma = 0.0, v; 820 821 switch(i) { 822 case 0: invgamma = 1. / pScrn->gamma.red; break; 823 case 1: invgamma = 1. / pScrn->gamma.green; break; 824 case 2: invgamma = 1. / pScrn->gamma.blue; break; 825 } 826 827 for(j = 0; j < nramp; j++) { 828 framp = pow(j * dramp, invgamma); 829 830 v = (fullscale < 0) ? (65535 + fullscale * framp) : 831 fullscale * framp; 832 if(v < 0) v = 0; 833 else if(v > 65535) v = 65535; 834 ramp[i][j] = (UShort)v; 835 } 836 } 837 838 } 839 840 xf86ChangeGammaRamp(pScreen, nramp, ramp[0], ramp[1], ramp[2]); 841 842 xfree(ramp[0]); 843 xfree(ramp[1]); 844 xfree(ramp[2]); 845 ramp[0] = ramp[1] = ramp[2] = NULL; 846} 847#endif 848 849void 850SISCalculateGammaRampCRT2(ScrnInfoPtr pScrn) 851{ 852 SISPtr pSiS = SISPTR(pScrn); 853 int i; 854 int myshift = 16 - pScrn->rgbBits; 855 int maxvalue = (1 << pScrn->rgbBits) - 1; 856 int reds = pScrn->mask.red >> pScrn->offset.red; 857 int greens = pScrn->mask.green >> pScrn->offset.green; 858 int blues = pScrn->mask.blue >> pScrn->offset.blue; 859 float framp, invgamma1, invgamma2, invgamma3, v; 860 861 invgamma1 = 1. / pSiS->GammaR2; 862 invgamma2 = 1. / pSiS->GammaG2; 863 invgamma3 = 1. / pSiS->GammaB2; 864 865 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_OLDGAMMAINUSE)) { 866 867 for(i = 0; i < pSiS->CRT2ColNum; i++) { 868 pSiS->crt2gcolortable[i].red = calcgammaval(i, pSiS->CRT2ColNum, invgamma1, 869 pSiS->NewGammaBriR2, pSiS->NewGammaConR2) >> myshift; 870 pSiS->crt2gcolortable[i].green = calcgammaval(i, pSiS->CRT2ColNum, invgamma2, 871 pSiS->NewGammaBriG2, pSiS->NewGammaConG2) >> myshift; 872 pSiS->crt2gcolortable[i].blue = calcgammaval(i, pSiS->CRT2ColNum, invgamma3, 873 pSiS->NewGammaBriB2, pSiS->NewGammaConB2) >> myshift; 874 } 875 876 } else { 877 878 int fullscale1 = 65536 * (float)pSiS->GammaBriR2 / 1000; 879 int fullscale2 = 65536 * (float)pSiS->GammaBriG2 / 1000; 880 int fullscale3 = 65536 * (float)pSiS->GammaBriB2 / 1000; 881 882 float dramp = 1. / (pSiS->CRT2ColNum - 1); 883 884 for(i = 0; i < pSiS->CRT2ColNum; i++) { 885 framp = pow(i * dramp, invgamma1); 886 v = (fullscale1 < 0) ? (65535 + fullscale1 * framp) : fullscale1 * framp; 887 if(v < 0) v = 0; 888 else if(v > 65535) v = 65535; 889 pSiS->crt2gcolortable[i].red = ((UShort)v) >> myshift; 890 framp = pow(i * dramp, invgamma2); 891 v = (fullscale2 < 0) ? (65535 + fullscale2 * framp) : fullscale2 * framp; 892 if(v < 0) v = 0; 893 else if(v > 65535) v = 65535; 894 pSiS->crt2gcolortable[i].green = ((UShort)v) >> myshift; 895 framp = pow(i * dramp, invgamma3); 896 v = (fullscale3 < 0) ? (65535 + fullscale3 * framp) : fullscale3 * framp; 897 if(v < 0) v = 0; 898 else if(v > 65535) v = 65535; 899 pSiS->crt2gcolortable[i].blue = ((UShort)v) >> myshift; 900 } 901 902 } 903 904 for(i = 0; i < pSiS->CRT2ColNum; i++) { 905 pSiS->crt2colors[i].red = 906 pSiS->crt2gcolortable[i * maxvalue / reds].red; 907 pSiS->crt2colors[i].green = 908 pSiS->crt2gcolortable[i * maxvalue / greens].green; 909 pSiS->crt2colors[i].blue = 910 pSiS->crt2gcolortable[i * maxvalue / blues].blue; 911 } 912} 913 914/* If monitor section has no HSync/VRefresh data, 915 * derive it from DDC data. 916 */ 917static void 918SiSSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) 919{ 920 MonPtr mon = pScrn->monitor; 921 xf86MonPtr ddc = mon->DDC; 922 float myhhigh = 0.0, myhlow = 0.0, htest; 923 int myvhigh = 0, myvlow = 0, vtest, i; 924 UChar temp; 925 const myhddctiming myhtiming[12] = { 926 { 1, 0x20, 31.6 }, /* rounded up by .1 */ 927 { 1, 0x80, 31.6 }, 928 { 1, 0x02, 35.3 }, 929 { 1, 0x04, 37.6 }, 930 { 1, 0x08, 38.0 }, 931 { 1, 0x01, 38.0 }, 932 { 2, 0x40, 47.0 }, 933 { 2, 0x80, 48.2 }, 934 { 2, 0x08, 48.5 }, 935 { 2, 0x04, 56.6 }, 936 { 2, 0x02, 60.1 }, 937 { 2, 0x01, 80.1 } 938 }; 939 const myvddctiming myvtiming[11] = { 940 { 1, 0x02, 56 }, 941 { 1, 0x01, 60 }, 942 { 2, 0x08, 60 }, 943 { 2, 0x04, 70 }, 944 { 1, 0x80, 71 }, 945 { 1, 0x08, 72 }, 946 { 2, 0x80, 72 }, 947 { 1, 0x04, 75 }, 948 { 2, 0x40, 75 }, 949 { 2, 0x02, 75 }, 950 { 2, 0x01, 75 } 951 }; 952 953 if(flag) { /* HSync */ 954 955 for(i = 0; i < 4; i++) { 956 if(ddc->det_mon[i].type == DS_RANGES) { 957 mon->nHsync = 1; 958 mon->hsync[0].lo = ddc->det_mon[i].section.ranges.min_h; 959 mon->hsync[0].hi = ddc->det_mon[i].section.ranges.max_h; 960 if(mon->hsync[0].lo > 32.0 || mon->hsync[0].hi < 31.0) { 961 if(ddc->timings1.t1 & 0x80) { 962 mon->nHsync++; 963 mon->hsync[1].lo = 31.0; 964 mon->hsync[1].hi = 32.0; 965 } 966 } 967 return; 968 } 969 } 970 971 /* If no sync ranges detected in detailed timing table, we 972 * derive them from supported VESA modes. 973 */ 974 975 for(i = 0; i < 12; i++) { 976 if(myhtiming[i].whichone == 1) temp = ddc->timings1.t1; 977 else temp = ddc->timings1.t2; 978 if(temp & myhtiming[i].mask) { 979 if((i == 0) || (myhlow > myhtiming[i].rate)) 980 myhlow = myhtiming[i].rate; 981 } 982 if(myhtiming[11-i].whichone == 1) temp = ddc->timings1.t1; 983 else temp = ddc->timings1.t2; 984 if(temp & myhtiming[11-i].mask) { 985 if((i == 0) || (myhhigh < myhtiming[11-i].rate)) 986 myhhigh = myhtiming[11-i].rate; 987 } 988 } 989 990 for(i = 0; i < STD_TIMINGS; i++) { 991 if(ddc->timings2[i].hsize > 256) { 992 htest = ddc->timings2[i].refresh * 1.05 * ddc->timings2[i].vsize / 1000.0; 993 if(htest < myhlow) myhlow = htest; 994 if(htest > myhhigh) myhhigh = htest; 995 } 996 } 997 998 if((myhhigh > 0.0) && (myhlow > 0.0)) { 999 mon->nHsync = 1; 1000 mon->hsync[0].lo = myhlow - 0.1; 1001 mon->hsync[0].hi = myhhigh; 1002 } 1003 1004 1005 } else { /* Vrefresh */ 1006 1007 for(i = 0; i < 4; i++) { 1008 if(ddc->det_mon[i].type == DS_RANGES) { 1009 mon->nVrefresh = 1; 1010 mon->vrefresh[0].lo = ddc->det_mon[i].section.ranges.min_v; 1011 mon->vrefresh[0].hi = ddc->det_mon[i].section.ranges.max_v; 1012 if(mon->vrefresh[0].lo > 72 || mon->vrefresh[0].hi < 70) { 1013 if(ddc->timings1.t1 & 0x80) { 1014 mon->nVrefresh++; 1015 mon->vrefresh[1].lo = 71; 1016 mon->vrefresh[1].hi = 71; 1017 } 1018 } 1019 return; 1020 } 1021 } 1022 1023 for(i = 0; i < 11; i++) { 1024 if(myvtiming[i].whichone == 1) temp = ddc->timings1.t1; 1025 else temp = ddc->timings1.t2; 1026 if(temp & myvtiming[i].mask) { 1027 if((i == 0) || (myvlow > myvtiming[i].rate)) 1028 myvlow = myvtiming[i].rate; 1029 } 1030 if(myvtiming[10-i].whichone == 1) temp = ddc->timings1.t1; 1031 else temp = ddc->timings1.t2; 1032 if(temp & myvtiming[10-i].mask) { 1033 if((i == 0) || (myvhigh < myvtiming[10-i].rate)) 1034 myvhigh = myvtiming[10-i].rate; 1035 } 1036 } 1037 1038 for(i = 0; i < STD_TIMINGS; i++) { 1039 if(ddc->timings2[i].hsize > 256) { 1040 vtest = ddc->timings2[i].refresh; 1041 if(vtest < myvlow) myvlow = vtest; 1042 if(vtest > myvhigh) myvhigh = vtest; 1043 } 1044 } 1045 1046 if((myvhigh > 0) && (myvlow > 0)) { 1047 mon->nVrefresh = 1; 1048 mon->vrefresh[0].lo = myvlow; 1049 mon->vrefresh[0].hi = myvhigh; 1050 } 1051 1052 } 1053} 1054 1055static Bool 1056SiSAllowSyncOverride(SISPtr pSiS, Bool fromDDC) 1057{ 1058 if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return FALSE; 1059 1060#ifdef SISDUALHEAD 1061 if(pSiS->DualHeadMode) { 1062 if(pSiS->SecondHead) { 1063 if((pSiS->VBFlags & CRT1_LCDA) && (!fromDDC)) return TRUE; 1064 } else { 1065 if((pSiS->VBFlags & CRT2_TV) || 1066 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC))) return TRUE; 1067 } 1068 return FALSE; 1069 } 1070#endif 1071 1072#ifdef SISMERGED 1073 if(pSiS->MergedFB) { 1074 if((pSiS->VBFlags & CRT1_LCDA) && (!fromDDC)) return TRUE; 1075 return FALSE; 1076 } 1077#endif 1078 1079 if(!(pSiS->VBFlags & DISPTYPE_CRT1)) { 1080 if( (pSiS->VBFlags & CRT2_TV) || 1081 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC)) ) return TRUE; 1082 } else if((pSiS->VBFlags & CRT1_LCDA) && (!fromDDC)) return TRUE; 1083 1084 return FALSE; 1085} 1086 1087static Bool 1088SiSCheckForH(float hsync, MonPtr monitor) 1089{ 1090 int i; 1091 for(i = 0; i < monitor->nHsync; i++) { 1092 if((hsync > monitor->hsync[i].lo * (1.0 - SYNC_TOLERANCE)) && 1093 (hsync < monitor->hsync[i].hi * (1.0 + SYNC_TOLERANCE))) 1094 break; 1095 } 1096 if(i == monitor->nHsync) return FALSE; 1097 return TRUE; 1098} 1099 1100static Bool 1101SiSCheckForV(float vrefresh, MonPtr monitor) 1102{ 1103 int i; 1104 for(i = 0; i < monitor->nVrefresh; i++) { 1105 if((vrefresh > monitor->vrefresh[i].lo * (1.0 - SYNC_TOLERANCE)) && 1106 (vrefresh < monitor->vrefresh[i].hi * (1.0 + SYNC_TOLERANCE))) 1107 break; 1108 } 1109 if(i == monitor->nVrefresh) return FALSE; 1110 return TRUE; 1111} 1112 1113static Bool 1114CheckAndOverruleH(ScrnInfoPtr pScrn, MonPtr monitor) 1115{ 1116 DisplayModePtr mode = monitor->Modes; 1117 float mymin = 30.0, mymax = 80.0, hsync; 1118 Bool doit = FALSE; 1119 1120 for(hsync = mymin; hsync <= mymax; hsync += .5) { 1121 if(!SiSCheckForH(hsync, monitor)) doit = TRUE; 1122 } 1123 1124 if(mode) { 1125 do { 1126 if(mode->type & M_T_BUILTIN) { 1127 hsync = (float)mode->Clock / (float)mode->HTotal; 1128 if(!SiSCheckForH(hsync, monitor)) { 1129 doit = TRUE; 1130 if(hsync < mymin) mymin = hsync; 1131 if(hsync > mymax) mymax = hsync; 1132 } 1133 } 1134 } while((mode = mode->next)); 1135 } 1136 1137 if(doit) { 1138 monitor->nHsync = 1; 1139 monitor->hsync[0].lo = mymin; 1140 monitor->hsync[0].hi = mymax; 1141 return TRUE; 1142 } 1143 1144 return FALSE; 1145} 1146 1147static Bool 1148CheckAndOverruleV(ScrnInfoPtr pScrn, MonPtr monitor) 1149{ 1150 DisplayModePtr mode = monitor->Modes; 1151 float mymin = 59.0, mymax = 61.0, vrefresh; 1152 Bool doit = FALSE, ret = FALSE; 1153 1154 for(vrefresh = mymin; vrefresh <= mymax; vrefresh += 1.0) { 1155 if(!SiSCheckForV(vrefresh, monitor)) doit = TRUE; 1156 } 1157 1158 if(mode) { 1159 do { 1160 if(mode->type & M_T_BUILTIN) { 1161 vrefresh = mode->Clock * 1000.0 / (mode->HTotal * mode->VTotal); 1162 if(mode->Flags & V_INTERLACE) vrefresh *= 2.0; 1163 if(mode->Flags & V_DBLSCAN) vrefresh /= 2.0; 1164 if(!SiSCheckForH(vrefresh, monitor)) { 1165 doit = TRUE; 1166 if(vrefresh < mymin) mymin = vrefresh; 1167 if(vrefresh > mymax) mymax = vrefresh; 1168 } 1169 } 1170 } while((mode = mode->next)); 1171 } 1172 1173 if(doit) { 1174 monitor->nVrefresh = 1; 1175 monitor->vrefresh[0].lo = mymin; 1176 monitor->vrefresh[0].hi = mymax; 1177 ret = TRUE; 1178 } 1179 1180 /* special for 640x400/320x200/@70Hz (VGA/IBM 720x480) */ 1181 if( (!SiSCheckForV(71, monitor)) && 1182 (monitor->nVrefresh < MAX_VREFRESH) ) { 1183 monitor->vrefresh[monitor->nVrefresh].lo = 71; 1184 monitor->vrefresh[monitor->nVrefresh].hi = 71; 1185 monitor->nVrefresh++; 1186 ret = TRUE; 1187 } 1188 return ret; 1189} 1190 1191/* Some helper functions for MergedFB mode */ 1192 1193#ifdef SISMERGED 1194 1195/* Helper function for CRT2 monitor vrefresh/hsync options 1196 * (Code base from mga driver) 1197 */ 1198static int 1199SiSStrToRanges(range *r, char *s, int max) 1200{ 1201 float num = 0.0; 1202 int rangenum = 0; 1203 Bool gotdash = FALSE; 1204 Bool nextdash = FALSE; 1205 char *strnum = NULL; 1206 do { 1207 switch(*s) { 1208 case '0': 1209 case '1': 1210 case '2': 1211 case '3': 1212 case '4': 1213 case '5': 1214 case '6': 1215 case '7': 1216 case '8': 1217 case '9': 1218 case '.': 1219 if(strnum == NULL) { 1220 strnum = s; 1221 gotdash = nextdash; 1222 nextdash = FALSE; 1223 } 1224 break; 1225 case '-': 1226 case ' ': 1227 case 0: 1228 if(strnum == NULL) break; 1229 sscanf(strnum, "%f", &num); 1230 strnum = NULL; 1231 if(gotdash) { 1232 r[rangenum - 1].hi = num; 1233 } else { 1234 r[rangenum].lo = num; 1235 r[rangenum].hi = num; 1236 rangenum++; 1237 } 1238 if(*s == '-') nextdash = (rangenum != 0); 1239 else if(rangenum >= max) return rangenum; 1240 break; 1241 default: 1242 return 0; 1243 } 1244 1245 } while(*(s++) != 0); 1246 1247 return rangenum; 1248} 1249 1250/* Copy and link two modes (i, j) for mergedfb mode 1251 * (Code base taken from mga driver) 1252 * 1253 * - Copy mode i, merge j to copy of i, link the result to dest 1254 * - Link i and j in private record. 1255 * - If dest is NULL, return value is copy of i linked to itself. 1256 * - For mergedfb auto-config, we only check the dimension 1257 * against virtualX/Y, if they were user-provided. 1258 * - No special treatment required for CRTxxOffs. 1259 * - Provide fake dotclock in order to distinguish between similar 1260 * looking MetaModes (for RandR and VidMode extensions) 1261 * - Set unique VRefresh of dest mode for RandR 1262 */ 1263static DisplayModePtr 1264SiSCopyModeNLink(ScrnInfoPtr pScrn, DisplayModePtr dest, 1265 DisplayModePtr i, DisplayModePtr j, 1266 SiSScrn2Rel srel) 1267{ 1268 SISPtr pSiS = SISPTR(pScrn); 1269 DisplayModePtr mode; 1270 int dx = 0,dy = 0; 1271 1272 if(!((mode = xalloc(sizeof(DisplayModeRec))))) return dest; 1273 memcpy(mode, i, sizeof(DisplayModeRec)); 1274 if(!((mode->Private = xalloc(sizeof(SiSMergedDisplayModeRec))))) { 1275 xfree(mode); 1276 return dest; 1277 } 1278 ((SiSMergedDisplayModePtr)mode->Private)->CRT1 = i; 1279 ((SiSMergedDisplayModePtr)mode->Private)->CRT2 = j; 1280 ((SiSMergedDisplayModePtr)mode->Private)->CRT2Position = srel; 1281 mode->PrivSize = 0; 1282 1283 switch(srel) { 1284 case sisLeftOf: 1285 case sisRightOf: 1286 if(!(pScrn->display->virtualX)) { 1287 dx = i->HDisplay + j->HDisplay; 1288 } else { 1289 dx = min(pScrn->virtualX, i->HDisplay + j->HDisplay); 1290 } 1291 dx -= mode->HDisplay; 1292 if(!(pScrn->display->virtualY)) { 1293 dy = max(i->VDisplay, j->VDisplay); 1294 } else { 1295 dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay)); 1296 } 1297 dy -= mode->VDisplay; 1298 break; 1299 case sisAbove: 1300 case sisBelow: 1301 if(!(pScrn->display->virtualY)) { 1302 dy = i->VDisplay + j->VDisplay; 1303 } else { 1304 dy = min(pScrn->virtualY, i->VDisplay + j->VDisplay); 1305 } 1306 dy -= mode->VDisplay; 1307 if(!(pScrn->display->virtualX)) { 1308 dx = max(i->HDisplay, j->HDisplay); 1309 } else { 1310 dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay)); 1311 } 1312 dx -= mode->HDisplay; 1313 break; 1314 case sisClone: 1315 if(!(pScrn->display->virtualX)) { 1316 dx = max(i->HDisplay, j->HDisplay); 1317 } else { 1318 dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay)); 1319 } 1320 dx -= mode->HDisplay; 1321 if(!(pScrn->display->virtualY)) { 1322 dy = max(i->VDisplay, j->VDisplay); 1323 } else { 1324 dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay)); 1325 } 1326 dy -= mode->VDisplay; 1327 break; 1328 } 1329 mode->HDisplay += dx; 1330 mode->HSyncStart += dx; 1331 mode->HSyncEnd += dx; 1332 mode->HTotal += dx; 1333 mode->VDisplay += dy; 1334 mode->VSyncStart += dy; 1335 mode->VSyncEnd += dy; 1336 mode->VTotal += dy; 1337 1338 mode->type = M_T_DEFAULT; 1339#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,2,0) 1340 /* Set up as user defined (ie fake that the mode has been named in the 1341 * Modes-list in the screen section; corrects cycling with CTRL-ALT-[-+] 1342 * when source mode has not been listed there.) 1343 */ 1344 mode->type |= M_T_USERDEF; 1345#endif 1346 1347 /* Set the VRefresh field (in order to make RandR use it for the rates). We 1348 * simply set this to the refresh rate for the CRT1 mode (since CRT2 will 1349 * mostly be LCD or TV anyway). 1350 */ 1351 mode->VRefresh = SiSCalcVRate(i); 1352 1353 if( ((mode->HDisplay * ((pScrn->bitsPerPixel + 7) / 8) * mode->VDisplay) > pSiS->maxxfbmem) || 1354 (mode->HDisplay > 4088) || 1355 (mode->VDisplay > 4096) ) { 1356 1357 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1358 "Skipped \"%s\" (%dx%d), not enough video RAM or beyond hardware specs\n", 1359 mode->name, mode->HDisplay, mode->VDisplay); 1360 xfree(mode->Private); 1361 xfree(mode); 1362 1363 return dest; 1364 } 1365 1366#ifdef SISXINERAMA 1367 if(srel != sisClone) { 1368 pSiS->AtLeastOneNonClone = TRUE; 1369 } 1370#endif 1371 1372 /* Now see if the resulting mode would be discarded as a "size" by the 1373 * RandR extension, and increase its clock by 1000 in case it does. 1374 */ 1375 if(dest) { 1376 DisplayModePtr t = dest; 1377 do { 1378 if((t->HDisplay == mode->HDisplay) && 1379 (t->VDisplay == mode->VDisplay) && 1380 ((int)(t->VRefresh + .5) == (int)(mode->VRefresh + .5))) { 1381 mode->VRefresh += 1000.0; 1382 } 1383 t = t->next; 1384 } while((t) && (t != dest)); 1385 } 1386 1387 /* Provide a fake but unique DotClock in order to trick the vidmode 1388 * extension to allow selecting among a number of modes whose merged result 1389 * looks identical but consists of different modes for CRT1 and CRT2 1390 */ 1391 mode->Clock = (int)(mode->VRefresh * 1000.0); 1392 1393 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1394 "Merged \"%s\" (%dx%d) and \"%s\" (%dx%d) to %dx%d (%d)%s\n", 1395 i->name, i->HDisplay, i->VDisplay, j->name, j->HDisplay, j->VDisplay, 1396 mode->HDisplay, mode->VDisplay, (int)mode->VRefresh, 1397 (srel == sisClone) ? " (Clone)" : ""); 1398 1399 mode->next = mode; 1400 mode->prev = mode; 1401 1402 if(dest) { 1403 mode->next = dest->next; /* Insert node after "dest" */ 1404 dest->next->prev = mode; 1405 mode->prev = dest; 1406 dest->next = mode; 1407 } 1408 1409 return mode; 1410} 1411 1412/* Helper function to find a mode from a given name 1413 * (Code base taken from mga driver) 1414 */ 1415static DisplayModePtr 1416SiSGetModeFromName(char* str, DisplayModePtr i) 1417{ 1418 DisplayModePtr c = i; 1419 if(!i) return NULL; 1420 do { 1421 if(strcmp(str, c->name) == 0) return c; 1422 c = c->next; 1423 } while(c != i); 1424 return NULL; 1425} 1426 1427static DisplayModePtr 1428SiSFindWidestTallestMode(DisplayModePtr i, Bool tallest) 1429{ 1430 DisplayModePtr c = i, d = NULL; 1431 int max = 0; 1432 if(!i) return NULL; 1433 do { 1434 if(tallest) { 1435 if(c->VDisplay > max) { 1436 max = c->VDisplay; 1437 d = c; 1438 } 1439 } else { 1440 if(c->HDisplay > max) { 1441 max = c->HDisplay; 1442 d = c; 1443 } 1444 } 1445 c = c->next; 1446 } while(c != i); 1447 return d; 1448} 1449 1450static void 1451SiSFindWidestTallestCommonMode(DisplayModePtr i, DisplayModePtr j, Bool tallest, 1452 DisplayModePtr *a, DisplayModePtr *b) 1453{ 1454 DisplayModePtr c = i, d; 1455 int max = 0; 1456 Bool foundone; 1457 1458 (*a) = (*b) = NULL; 1459 1460 if(!i || !j) return; 1461 1462 do { 1463 d = j; 1464 foundone = FALSE; 1465 do { 1466 if( (c->HDisplay == d->HDisplay) && 1467 (c->VDisplay == d->VDisplay) ) { 1468 foundone = TRUE; 1469 break; 1470 } 1471 d = d->next; 1472 } while(d != j); 1473 if(foundone) { 1474 if(tallest) { 1475 if(c->VDisplay > max) { 1476 max = c->VDisplay; 1477 (*a) = c; 1478 (*b) = d; 1479 } 1480 } else { 1481 if(c->HDisplay > max) { 1482 max = c->HDisplay; 1483 (*a) = c; 1484 (*b) = d; 1485 } 1486 } 1487 } 1488 c = c->next; 1489 } while(c != i); 1490} 1491 1492static DisplayModePtr 1493SiSGenerateModeListFromLargestModes(ScrnInfoPtr pScrn, 1494 DisplayModePtr i, DisplayModePtr j, 1495 SiSScrn2Rel srel) 1496{ 1497#ifdef SISXINERAMA 1498 SISPtr pSiS = SISPTR(pScrn); 1499#endif 1500 DisplayModePtr mode1 = NULL; 1501 DisplayModePtr mode2 = NULL; 1502 DisplayModePtr mode3 = NULL; 1503 DisplayModePtr mode4 = NULL; 1504 DisplayModePtr result = NULL; 1505 1506#ifdef SISXINERAMA 1507 pSiS->AtLeastOneNonClone = FALSE; 1508#endif 1509 1510 /* Now build a default list of MetaModes. 1511 * - Non-clone: If the user enabled NonRectangular, we use the 1512 * largest mode for each CRT1 and CRT2. If not, we use the largest 1513 * common mode for CRT1 and CRT2 (if available). Additionally, and 1514 * regardless if the above, we produce a clone mode consisting of 1515 * the largest common mode (if available) in order to use DGA. 1516 * - Clone: If the (global) CRT2Position is Clone, we use the 1517 * largest common mode if available, otherwise the first two modes 1518 * in each list. 1519 */ 1520 1521 switch(srel) { 1522 case sisLeftOf: 1523 case sisRightOf: 1524 mode1 = SiSFindWidestTallestMode(i, FALSE); 1525 mode2 = SiSFindWidestTallestMode(j, FALSE); 1526 SiSFindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); 1527 break; 1528 case sisAbove: 1529 case sisBelow: 1530 mode1 = SiSFindWidestTallestMode(i, TRUE); 1531 mode2 = SiSFindWidestTallestMode(j, TRUE); 1532 SiSFindWidestTallestCommonMode(i, j, TRUE, &mode3, &mode4); 1533 break; 1534 case sisClone: 1535 SiSFindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); 1536 if(mode3 && mode4) { 1537 mode1 = mode3; 1538 mode2 = mode4; 1539 } else { 1540 mode1 = i; 1541 mode2 = j; 1542 } 1543 } 1544 1545 if(srel != sisClone) { 1546 if(mode3 && mode4 && !pSiS->NonRect) { 1547 mode1 = mode3; 1548 mode2 = mode2; 1549 } 1550 } 1551 1552 if(mode1 && mode2) { 1553 result = SiSCopyModeNLink(pScrn, result, mode1, mode2, srel); 1554 } 1555 1556 if(srel != sisClone) { 1557 if(mode3 && mode4) { 1558 result = SiSCopyModeNLink(pScrn, result, mode3, mode4, sisClone); 1559 } 1560 } 1561 1562 return result; 1563} 1564 1565/* Generate the merged-fb mode modelist 1566 * (Taken from mga driver) 1567 */ 1568static DisplayModePtr 1569SiSGenerateModeListFromMetaModes(ScrnInfoPtr pScrn, char* str, 1570 DisplayModePtr i, DisplayModePtr j, 1571 SiSScrn2Rel srel) 1572{ 1573#ifdef SISXINERAMA 1574 SISPtr pSiS = SISPTR(pScrn); 1575#endif 1576 char* strmode = str; 1577 char modename[256]; 1578 Bool gotdash = FALSE; 1579 char gotsep = 0; 1580 SiSScrn2Rel sr; 1581 DisplayModePtr mode1 = NULL; 1582 DisplayModePtr mode2 = NULL; 1583 DisplayModePtr result = NULL; 1584 int myslen; 1585 1586#ifdef SISXINERAMA 1587 pSiS->AtLeastOneNonClone = FALSE; 1588#endif 1589 1590 do { 1591 switch(*str) { 1592 case 0: 1593 case '-': 1594 case '+': 1595 case ' ': 1596 case ',': 1597 case ';': 1598 if(strmode != str) { 1599 1600 myslen = str - strmode; 1601 if(myslen > 255) myslen = 255; 1602 strncpy(modename, strmode, myslen); 1603 modename[myslen] = 0; 1604 1605 if(gotdash) { 1606 if(mode1 == NULL) { 1607 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1608 "Error parsing MetaModes parameter\n"); 1609 return NULL; 1610 } 1611 mode2 = SiSGetModeFromName(modename, j); 1612 if(!mode2) { 1613 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1614 "Mode \"%s\" is not a supported mode for CRT2\n", modename); 1615 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1616 "\t(Skipping metamode \"%s%c%s\")\n", mode1->name, gotsep, modename); 1617 mode1 = NULL; 1618 gotsep = 0; 1619 } 1620 } else { 1621 mode1 = SiSGetModeFromName(modename, i); 1622 if(!mode1) { 1623 char* tmps = str; 1624 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1625 "Mode \"%s\" is not a supported mode for CRT1\n", modename); 1626 while(*tmps == ' ' || *tmps == ';') tmps++; 1627 /* skip the next mode */ 1628 if(*tmps == '-' || *tmps == '+' || *tmps == ',') { 1629 tmps++; 1630 /* skip spaces */ 1631 while(*tmps == ' ' || *tmps == ';') tmps++; 1632 /* skip modename */ 1633 while(*tmps && *tmps != ' ' && *tmps != ';' && *tmps != '-' && *tmps != '+' && *tmps != ',') tmps++; 1634 myslen = tmps - strmode; 1635 if(myslen > 255) myslen = 255; 1636 strncpy(modename,strmode,myslen); 1637 modename[myslen] = 0; 1638 str = tmps - 1; 1639 } 1640 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1641 "\t(Skipping metamode \"%s\")\n", modename); 1642 mode1 = NULL; 1643 gotsep = 0; 1644 } 1645 } 1646 gotdash = FALSE; 1647 } 1648 strmode = str + 1; 1649 gotdash |= (*str == '-' || *str == '+' || *str == ','); 1650 if (*str == '-' || *str == '+' || *str == ',') 1651 gotsep = *str; 1652 1653 if(*str != 0) break; 1654 /* Fall through otherwise */ 1655 1656 default: 1657 if(!gotdash && mode1) { 1658 sr = srel; 1659 if(gotsep == '+') sr = sisClone; 1660 if(!mode2) { 1661 mode2 = SiSGetModeFromName(mode1->name, j); 1662 sr = sisClone; 1663 } 1664 if(!mode2) { 1665 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1666 "Mode \"%s\" is not a supported mode for CRT2\n", mode1->name); 1667 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1668 "\t(Skipping metamode \"%s\")\n", modename); 1669 mode1 = NULL; 1670 } else { 1671 result = SiSCopyModeNLink(pScrn, result, mode1, mode2, sr); 1672 mode1 = NULL; 1673 mode2 = NULL; 1674 } 1675 gotsep = 0; 1676 } 1677 break; 1678 1679 } 1680 1681 } while(*(str++) != 0); 1682 1683 return result; 1684} 1685 1686static DisplayModePtr 1687SiSGenerateModeList(ScrnInfoPtr pScrn, char* str, 1688 DisplayModePtr i, DisplayModePtr j, 1689 SiSScrn2Rel srel) 1690{ 1691 SISPtr pSiS = SISPTR(pScrn); 1692 1693 if(str != NULL) { 1694 return(SiSGenerateModeListFromMetaModes(pScrn, str, i, j, srel)); 1695 } else { 1696 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1697 "No MetaModes given, linking %s modes by default\n", 1698 (srel == sisClone) ? "largest common" : 1699 (pSiS->NonRect ? 1700 (((srel == sisLeftOf) || (srel == sisRightOf)) ? "widest" : "tallest") 1701 : 1702 (((srel == sisLeftOf) || (srel == sisRightOf)) ? "widest common" : "tallest common")) ); 1703 return(SiSGenerateModeListFromLargestModes(pScrn, i, j, srel)); 1704 } 1705} 1706 1707static void 1708SiSRecalcDefaultVirtualSize(ScrnInfoPtr pScrn) 1709{ 1710 SISPtr pSiS = SISPTR(pScrn); 1711 DisplayModePtr mode, bmode; 1712 int maxh, maxv; 1713 static const char *str = "MergedFB: Virtual %s %d\n"; 1714 static const char *errstr = "Virtual %s to small for given CRT2Position offset\n"; 1715 1716 mode = bmode = pScrn->modes; 1717 maxh = maxv = 0; 1718 do { 1719 if(mode->HDisplay > maxh) maxh = mode->HDisplay; 1720 if(mode->VDisplay > maxv) maxv = mode->VDisplay; 1721 mode = mode->next; 1722 } while(mode != bmode); 1723 1724 maxh += pSiS->CRT1XOffs + pSiS->CRT2XOffs; 1725 maxv += pSiS->CRT1YOffs + pSiS->CRT2YOffs; 1726 1727 if(!(pScrn->display->virtualX)) { 1728 if(maxh > 4088) { 1729 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1730 "Virtual width with CRT2Position offset beyond hardware specs\n"); 1731 pSiS->CRT1XOffs = pSiS->CRT2XOffs = 0; 1732 maxh -= (pSiS->CRT1XOffs + pSiS->CRT2XOffs); 1733 } 1734 pScrn->virtualX = maxh; 1735 pScrn->displayWidth = maxh; 1736 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "width", maxh); 1737 } else { 1738 if(maxh < pScrn->display->virtualX) { 1739 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "width"); 1740 pSiS->CRT1XOffs = pSiS->CRT2XOffs = 0; 1741 } 1742 } 1743 1744 if(!(pScrn->display->virtualY)) { 1745 pScrn->virtualY = maxv; 1746 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "height", maxv); 1747 } else { 1748 if(maxv < pScrn->display->virtualY) { 1749 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "height"); 1750 pSiS->CRT1YOffs = pSiS->CRT2YOffs = 0; 1751 } 1752 } 1753} 1754 1755static void 1756SiSMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, SiSScrn2Rel srel) 1757{ 1758 SISPtr pSiS = SISPTR(pScrn1); 1759 MessageType from = X_DEFAULT; 1760 xf86MonPtr DDC1 = (xf86MonPtr)(pScrn1->monitor->DDC); 1761 xf86MonPtr DDC2 = (xf86MonPtr)(pScrn2->monitor->DDC); 1762 int ddcWidthmm = 0, ddcHeightmm = 0; 1763 const char *dsstr = "MergedFB: Display dimensions: (%d, %d) mm\n"; 1764 1765 /* This sets the DPI for MergedFB mode. The problem is that 1766 * this can never be exact, because the output devices may 1767 * have different dimensions. This function tries to compromise 1768 * through a few assumptions, and it just calculates an average DPI 1769 * value for both monitors. 1770 */ 1771 1772 /* Given DisplaySize should regard BOTH monitors */ 1773 pScrn1->widthmm = pScrn1->monitor->widthmm; 1774 pScrn1->heightmm = pScrn1->monitor->heightmm; 1775 1776 /* Get DDC display size; if only either CRT1 or CRT2 provided these, 1777 * assume equal dimensions for both, otherwise add dimensions 1778 */ 1779 if( (DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) && 1780 (DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0)) ) { 1781 ddcWidthmm = max(DDC1->features.hsize, DDC2->features.hsize) * 10; 1782 ddcHeightmm = max(DDC1->features.vsize, DDC2->features.vsize) * 10; 1783 switch(srel) { 1784 case sisLeftOf: 1785 case sisRightOf: 1786 ddcWidthmm = (DDC1->features.hsize + DDC2->features.hsize) * 10; 1787 break; 1788 case sisAbove: 1789 case sisBelow: 1790 ddcHeightmm = (DDC1->features.vsize + DDC2->features.vsize) * 10; 1791 default: 1792 break; 1793 } 1794 } else if(DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) { 1795 ddcWidthmm = DDC1->features.hsize * 10; 1796 ddcHeightmm = DDC1->features.vsize * 10; 1797 switch(srel) { 1798 case sisLeftOf: 1799 case sisRightOf: 1800 ddcWidthmm *= 2; 1801 break; 1802 case sisAbove: 1803 case sisBelow: 1804 ddcHeightmm *= 2; 1805 default: 1806 break; 1807 } 1808 } else if(DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0) ) { 1809 ddcWidthmm = DDC2->features.hsize * 10; 1810 ddcHeightmm = DDC2->features.vsize * 10; 1811 switch(srel) { 1812 case sisLeftOf: 1813 case sisRightOf: 1814 ddcWidthmm *= 2; 1815 break; 1816 case sisAbove: 1817 case sisBelow: 1818 ddcHeightmm *= 2; 1819 default: 1820 break; 1821 } 1822 } 1823 1824 if(monitorResolution > 0) { 1825 1826 /* Set command line given values (overrules given options) */ 1827 pScrn1->xDpi = monitorResolution; 1828 pScrn1->yDpi = monitorResolution; 1829 from = X_CMDLINE; 1830 1831 } else if(pSiS->MergedFBXDPI) { 1832 1833 /* Set option-wise given values (overrule DisplaySize) */ 1834 pScrn1->xDpi = pSiS->MergedFBXDPI; 1835 pScrn1->yDpi = pSiS->MergedFBYDPI; 1836 from = X_CONFIG; 1837 1838 } else if(pScrn1->widthmm > 0 || pScrn1->heightmm > 0) { 1839 1840 /* Set values calculated from given DisplaySize */ 1841 from = X_CONFIG; 1842 if(pScrn1->widthmm > 0) { 1843 pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm); 1844 } 1845 if(pScrn1->heightmm > 0) { 1846 pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm); 1847 } 1848 xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, pScrn1->widthmm, pScrn1->heightmm); 1849 1850 } else if(ddcWidthmm && ddcHeightmm) { 1851 1852 /* Set values from DDC-provided display size */ 1853 from = X_PROBED; 1854 xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, ddcWidthmm, ddcHeightmm ); 1855 pScrn1->widthmm = ddcWidthmm; 1856 pScrn1->heightmm = ddcHeightmm; 1857 if(pScrn1->widthmm > 0) { 1858 pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm); 1859 } 1860 if(pScrn1->heightmm > 0) { 1861 pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm); 1862 } 1863 1864 } else { 1865 1866 pScrn1->xDpi = pScrn1->yDpi = DEFAULT_DPI; 1867 1868 } 1869 1870 /* Sanity check */ 1871 if(pScrn1->xDpi > 0 && pScrn1->yDpi <= 0) 1872 pScrn1->yDpi = pScrn1->xDpi; 1873 if(pScrn1->yDpi > 0 && pScrn1->xDpi <= 0) 1874 pScrn1->xDpi = pScrn1->yDpi; 1875 1876 pScrn2->xDpi = pScrn1->xDpi; 1877 pScrn2->yDpi = pScrn1->yDpi; 1878 1879 xf86DrvMsg(pScrn1->scrnIndex, from, "MergedFB: DPI set to (%d, %d)\n", 1880 pScrn1->xDpi, pScrn1->yDpi); 1881} 1882 1883/* Pseudo-Xinerama extension for MergedFB mode */ 1884#ifdef SISXINERAMA 1885 1886static void 1887SiSUpdateXineramaScreenInfo(ScrnInfoPtr pScrn1) 1888{ 1889 SISPtr pSiS = SISPTR(pScrn1); 1890 int crt1scrnnum = 0, crt2scrnnum = 1; 1891 int x1=0, x2=0, y1=0, y2=0, h1=0, h2=0, w1=0, w2=0; 1892 int realvirtX, realvirtY; 1893 DisplayModePtr currentMode, firstMode; 1894 Bool infochanged = FALSE; 1895 Bool usenonrect = pSiS->NonRect; 1896 const char *rectxine = "\t... setting up rectangular Xinerama layout\n"; 1897 1898 pSiS->MBXNR1XMAX = pSiS->MBXNR1YMAX = pSiS->MBXNR2XMAX = pSiS->MBXNR2YMAX = 65536; 1899 pSiS->HaveNonRect = pSiS->HaveOffsRegions = FALSE; 1900 1901 if(!pSiS->MergedFB) return; 1902 1903 if(SiSnoPanoramiXExtension) return; 1904 1905 if(!SiSXineramadataPtr) return; 1906 1907 if(pSiS->CRT2IsScrn0) { 1908 crt1scrnnum = 1; 1909 crt2scrnnum = 0; 1910 } 1911 1912 /* Attention: Usage of RandR may lead to virtual X and Y dimensions 1913 * actually smaller than our MetaModes. To avoid this, we calculate 1914 * the maxCRT fields here (and not somewhere else, like in CopyNLink) 1915 * 1916 * *** Note: RandR is disabled if one of CRTxxOffs is non-zero. 1917 */ 1918 1919 /* "Real" virtual: Virtual without the Offset */ 1920 realvirtX = pScrn1->virtualX - pSiS->CRT1XOffs - pSiS->CRT2XOffs; 1921 realvirtY = pScrn1->virtualY - pSiS->CRT1YOffs - pSiS->CRT2YOffs; 1922 1923 if((pSiS->SiSXineramaVX != pScrn1->virtualX) || (pSiS->SiSXineramaVY != pScrn1->virtualY)) { 1924 1925 if(!(pScrn1->modes)) return; 1926 1927 pSiS->maxCRT1_X1 = pSiS->maxCRT1_X2 = 0; 1928 pSiS->maxCRT1_Y1 = pSiS->maxCRT1_Y2 = 0; 1929 pSiS->maxCRT2_X1 = pSiS->maxCRT2_X2 = 0; 1930 pSiS->maxCRT2_Y1 = pSiS->maxCRT2_Y2 = 0; 1931 pSiS->maxClone_X1 = pSiS->maxClone_X2 = 0; 1932 pSiS->maxClone_Y1 = pSiS->maxClone_Y2 = 0; 1933 1934 currentMode = firstMode = pScrn1->modes; 1935 1936 do { 1937 1938 DisplayModePtr p = currentMode->next; 1939 DisplayModePtr i = ((SiSMergedDisplayModePtr)currentMode->Private)->CRT1; 1940 DisplayModePtr j = ((SiSMergedDisplayModePtr)currentMode->Private)->CRT2; 1941 SiSScrn2Rel srel = ((SiSMergedDisplayModePtr)currentMode->Private)->CRT2Position; 1942 1943 if((currentMode->HDisplay <= realvirtX) && (currentMode->VDisplay <= realvirtY) && 1944 (i->HDisplay <= realvirtX) && (j->HDisplay <= realvirtX) && 1945 (i->VDisplay <= realvirtY) && (j->VDisplay <= realvirtY)) { 1946 1947 if(srel != sisClone) { 1948 if(pSiS->maxCRT1_X1 == i->HDisplay) { 1949 if(pSiS->maxCRT1_X2 < j->HDisplay) { 1950 pSiS->maxCRT1_X2 = j->HDisplay; /* Widest CRT2 mode displayed with widest CRT1 mode */ 1951 } 1952 } else if(pSiS->maxCRT1_X1 < i->HDisplay) { 1953 pSiS->maxCRT1_X1 = i->HDisplay; /* Widest CRT1 mode */ 1954 pSiS->maxCRT1_X2 = j->HDisplay; 1955 } 1956 if(pSiS->maxCRT2_X2 == j->HDisplay) { 1957 if(pSiS->maxCRT2_X1 < i->HDisplay) { 1958 pSiS->maxCRT2_X1 = i->HDisplay; /* Widest CRT1 mode displayed with widest CRT2 mode */ 1959 } 1960 } else if(pSiS->maxCRT2_X2 < j->HDisplay) { 1961 pSiS->maxCRT2_X2 = j->HDisplay; /* Widest CRT2 mode */ 1962 pSiS->maxCRT2_X1 = i->HDisplay; 1963 } 1964 if(pSiS->maxCRT1_Y1 == i->VDisplay) { /* Same as above, but tallest instead of widest */ 1965 if(pSiS->maxCRT1_Y2 < j->VDisplay) { 1966 pSiS->maxCRT1_Y2 = j->VDisplay; 1967 } 1968 } else if(pSiS->maxCRT1_Y1 < i->VDisplay) { 1969 pSiS->maxCRT1_Y1 = i->VDisplay; 1970 pSiS->maxCRT1_Y2 = j->VDisplay; 1971 } 1972 if(pSiS->maxCRT2_Y2 == j->VDisplay) { 1973 if(pSiS->maxCRT2_Y1 < i->VDisplay) { 1974 pSiS->maxCRT2_Y1 = i->VDisplay; 1975 } 1976 } else if(pSiS->maxCRT2_Y2 < j->VDisplay) { 1977 pSiS->maxCRT2_Y2 = j->VDisplay; 1978 pSiS->maxCRT2_Y1 = i->VDisplay; 1979 } 1980 } else { 1981 if(pSiS->maxClone_X1 < i->HDisplay) { 1982 pSiS->maxClone_X1 = i->HDisplay; 1983 } 1984 if(pSiS->maxClone_X2 < j->HDisplay) { 1985 pSiS->maxClone_X2 = j->HDisplay; 1986 } 1987 if(pSiS->maxClone_Y1 < i->VDisplay) { 1988 pSiS->maxClone_Y1 = i->VDisplay; 1989 } 1990 if(pSiS->maxClone_Y2 < j->VDisplay) { 1991 pSiS->maxClone_Y2 = j->VDisplay; 1992 } 1993 } 1994 } 1995 currentMode = p; 1996 1997 } while((currentMode) && (currentMode != firstMode)); 1998 1999 pSiS->SiSXineramaVX = pScrn1->virtualX; 2000 pSiS->SiSXineramaVY = pScrn1->virtualY; 2001 infochanged = TRUE; 2002 2003 } 2004 2005 if((usenonrect) && (pSiS->CRT2Position != sisClone) && pSiS->maxCRT1_X1) { 2006 switch(pSiS->CRT2Position) { 2007 case sisLeftOf: 2008 case sisRightOf: 2009 if((pSiS->maxCRT1_Y1 != realvirtY) && (pSiS->maxCRT2_Y2 != realvirtY)) { 2010 usenonrect = FALSE; 2011 } 2012 break; 2013 case sisAbove: 2014 case sisBelow: 2015 if((pSiS->maxCRT1_X1 != realvirtX) && (pSiS->maxCRT2_X2 != realvirtX)) { 2016 usenonrect = FALSE; 2017 } 2018 break; 2019 case sisClone: 2020 break; 2021 } 2022 if(infochanged && !usenonrect) { 2023 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2024 "Virtual screen size does not match maximum display modes...\n"); 2025 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, rectxine); 2026 2027 } 2028 } else if(infochanged && usenonrect) { 2029 usenonrect = FALSE; 2030 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2031 "Only clone modes available for this virtual screen size...\n"); 2032 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, rectxine); 2033 } 2034 2035 if(pSiS->maxCRT1_X1) { /* Means we have at least one non-clone mode */ 2036 switch(pSiS->CRT2Position) { 2037 case sisLeftOf: 2038 x1 = min(pSiS->maxCRT1_X2, pScrn1->virtualX - pSiS->maxCRT1_X1); 2039 if(x1 < 0) x1 = 0; 2040 y1 = pSiS->CRT1YOffs; 2041 w1 = pScrn1->virtualX - x1; 2042 h1 = realvirtY; 2043 if((usenonrect) && (pSiS->maxCRT1_Y1 != realvirtY)) { 2044 h1 = pSiS->MBXNR1YMAX = pSiS->maxCRT1_Y1; 2045 pSiS->NonRectDead.x0 = x1; 2046 pSiS->NonRectDead.x1 = x1 + w1 - 1; 2047 pSiS->NonRectDead.y0 = y1 + h1; 2048 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 2049 pSiS->HaveNonRect = TRUE; 2050 } 2051 x2 = 0; 2052 y2 = pSiS->CRT2YOffs; 2053 w2 = max(pSiS->maxCRT2_X2, pScrn1->virtualX - pSiS->maxCRT2_X1); 2054 if(w2 > pScrn1->virtualX) w2 = pScrn1->virtualX; 2055 h2 = realvirtY; 2056 if((usenonrect) && (pSiS->maxCRT2_Y2 != realvirtY)) { 2057 h2 = pSiS->MBXNR2YMAX = pSiS->maxCRT2_Y2; 2058 pSiS->NonRectDead.x0 = x2; 2059 pSiS->NonRectDead.x1 = x2 + w2 - 1; 2060 pSiS->NonRectDead.y0 = y2 + h2; 2061 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 2062 pSiS->HaveNonRect = TRUE; 2063 } 2064 break; 2065 case sisRightOf: 2066 x1 = 0; 2067 y1 = pSiS->CRT1YOffs; 2068 w1 = max(pSiS->maxCRT1_X1, pScrn1->virtualX - pSiS->maxCRT1_X2); 2069 if(w1 > pScrn1->virtualX) w1 = pScrn1->virtualX; 2070 h1 = realvirtY; 2071 if((usenonrect) && (pSiS->maxCRT1_Y1 != realvirtY)) { 2072 h1 = pSiS->MBXNR1YMAX = pSiS->maxCRT1_Y1; 2073 pSiS->NonRectDead.x0 = x1; 2074 pSiS->NonRectDead.x1 = x1 + w1 - 1; 2075 pSiS->NonRectDead.y0 = y1 + h1; 2076 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 2077 pSiS->HaveNonRect = TRUE; 2078 } 2079 x2 = min(pSiS->maxCRT2_X1, pScrn1->virtualX - pSiS->maxCRT2_X2); 2080 if(x2 < 0) x2 = 0; 2081 y2 = pSiS->CRT2YOffs; 2082 w2 = pScrn1->virtualX - x2; 2083 h2 = realvirtY; 2084 if((usenonrect) && (pSiS->maxCRT2_Y2 != realvirtY)) { 2085 h2 = pSiS->MBXNR2YMAX = pSiS->maxCRT2_Y2; 2086 pSiS->NonRectDead.x0 = x2; 2087 pSiS->NonRectDead.x1 = x2 + w2 - 1; 2088 pSiS->NonRectDead.y0 = y2 + h2; 2089 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 2090 pSiS->HaveNonRect = TRUE; 2091 } 2092 break; 2093 case sisAbove: 2094 x1 = pSiS->CRT1XOffs; 2095 y1 = min(pSiS->maxCRT1_Y2, pScrn1->virtualY - pSiS->maxCRT1_Y1); 2096 if(y1 < 0) y1 = 0; 2097 w1 = realvirtX; 2098 h1 = pScrn1->virtualY - y1; 2099 if((usenonrect) && (pSiS->maxCRT1_X1 != realvirtX)) { 2100 w1 = pSiS->MBXNR1XMAX = pSiS->maxCRT1_X1; 2101 pSiS->NonRectDead.x0 = x1 + w1; 2102 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 2103 pSiS->NonRectDead.y0 = y1; 2104 pSiS->NonRectDead.y1 = y1 + h1 - 1; 2105 pSiS->HaveNonRect = TRUE; 2106 } 2107 x2 = pSiS->CRT2XOffs; 2108 y2 = 0; 2109 w2 = realvirtX; 2110 h2 = max(pSiS->maxCRT2_Y2, pScrn1->virtualY - pSiS->maxCRT2_Y1); 2111 if(h2 > pScrn1->virtualY) h2 = pScrn1->virtualY; 2112 if((usenonrect) && (pSiS->maxCRT2_X2 != realvirtX)) { 2113 w2 = pSiS->MBXNR2XMAX = pSiS->maxCRT2_X2; 2114 pSiS->NonRectDead.x0 = x2 + w2; 2115 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 2116 pSiS->NonRectDead.y0 = y2; 2117 pSiS->NonRectDead.y1 = y2 + h2 - 1; 2118 pSiS->HaveNonRect = TRUE; 2119 } 2120 break; 2121 case sisBelow: 2122 x1 = pSiS->CRT1XOffs; 2123 y1 = 0; 2124 w1 = realvirtX; 2125 h1 = max(pSiS->maxCRT1_Y1, pScrn1->virtualY - pSiS->maxCRT1_Y2); 2126 if(h1 > pScrn1->virtualY) h1 = pScrn1->virtualY; 2127 if((usenonrect) && (pSiS->maxCRT1_X1 != realvirtX)) { 2128 w1 = pSiS->MBXNR1XMAX = pSiS->maxCRT1_X1; 2129 pSiS->NonRectDead.x0 = x1 + w1; 2130 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 2131 pSiS->NonRectDead.y0 = y1; 2132 pSiS->NonRectDead.y1 = y1 + h1 - 1; 2133 pSiS->HaveNonRect = TRUE; 2134 } 2135 x2 = pSiS->CRT2XOffs; 2136 y2 = min(pSiS->maxCRT2_Y1, pScrn1->virtualY - pSiS->maxCRT2_Y2); 2137 if(y2 < 0) y2 = 0; 2138 w2 = realvirtX; 2139 h2 = pScrn1->virtualY - y2; 2140 if((usenonrect) && (pSiS->maxCRT2_X2 != realvirtX)) { 2141 w2 = pSiS->MBXNR2XMAX = pSiS->maxCRT2_X2; 2142 pSiS->NonRectDead.x0 = x2 + w2; 2143 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 2144 pSiS->NonRectDead.y0 = y2; 2145 pSiS->NonRectDead.y1 = y2 + h2 - 1; 2146 pSiS->HaveNonRect = TRUE; 2147 } 2148 default: 2149 break; 2150 } 2151 2152 switch(pSiS->CRT2Position) { 2153 case sisLeftOf: 2154 case sisRightOf: 2155 if(pSiS->CRT1YOffs) { 2156 pSiS->OffDead1.x0 = x1; 2157 pSiS->OffDead1.x1 = x1 + w1 - 1; 2158 pSiS->OffDead1.y0 = 0; 2159 pSiS->OffDead1.y1 = y1 - 1; 2160 pSiS->OffDead2.x0 = x2; 2161 pSiS->OffDead2.x1 = x2 + w2 - 1; 2162 pSiS->OffDead2.y0 = y2 + h2; 2163 pSiS->OffDead2.y1 = pScrn1->virtualY - 1; 2164 pSiS->HaveOffsRegions = TRUE; 2165 } else if(pSiS->CRT2YOffs) { 2166 pSiS->OffDead1.x0 = x2; 2167 pSiS->OffDead1.x1 = x2 + w2 - 1; 2168 pSiS->OffDead1.y0 = 0; 2169 pSiS->OffDead1.y1 = y2 - 1; 2170 pSiS->OffDead2.x0 = x1; 2171 pSiS->OffDead2.x1 = x1 + w1 - 1; 2172 pSiS->OffDead2.y0 = y1 + h1; 2173 pSiS->OffDead2.y1 = pScrn1->virtualY - 1; 2174 pSiS->HaveOffsRegions = TRUE; 2175 } 2176 break; 2177 case sisAbove: 2178 case sisBelow: 2179 if(pSiS->CRT1XOffs) { 2180 pSiS->OffDead1.x0 = x2 + w2; 2181 pSiS->OffDead1.x1 = pScrn1->virtualX - 1; 2182 pSiS->OffDead1.y0 = y2; 2183 pSiS->OffDead1.y1 = y2 + h2 - 1; 2184 pSiS->OffDead2.x0 = 0; 2185 pSiS->OffDead2.x1 = x1 - 1; 2186 pSiS->OffDead2.y0 = y1; 2187 pSiS->OffDead2.y1 = y1 + h1 - 1; 2188 pSiS->HaveOffsRegions = TRUE; 2189 } else if(pSiS->CRT2XOffs) { 2190 pSiS->OffDead1.x0 = x1 + w1; 2191 pSiS->OffDead1.x1 = pScrn1->virtualX - 1; 2192 pSiS->OffDead1.y0 = y1; 2193 pSiS->OffDead1.y1 = y1 + h1 - 1; 2194 pSiS->OffDead2.x0 = 0; 2195 pSiS->OffDead2.x1 = x2 - 1; 2196 pSiS->OffDead2.y0 = y2; 2197 pSiS->OffDead2.y1 = y2 + h2 - 1; 2198 pSiS->HaveOffsRegions = TRUE; 2199 } 2200 default: 2201 break; 2202 } 2203 2204 } else { /* Only clone-modes left */ 2205 2206 x1 = x2 = 0; 2207 y1 = y2 = 0; 2208 w1 = w2 = max(pSiS->maxClone_X1, pSiS->maxClone_X2); 2209 h1 = h2 = max(pSiS->maxClone_Y1, pSiS->maxClone_Y2); 2210 2211 } 2212 2213 SiSXineramadataPtr[crt1scrnnum].x = x1; 2214 SiSXineramadataPtr[crt1scrnnum].y = y1; 2215 SiSXineramadataPtr[crt1scrnnum].width = w1; 2216 SiSXineramadataPtr[crt1scrnnum].height = h1; 2217 SiSXineramadataPtr[crt2scrnnum].x = x2; 2218 SiSXineramadataPtr[crt2scrnnum].y = y2; 2219 SiSXineramadataPtr[crt2scrnnum].width = w2; 2220 SiSXineramadataPtr[crt2scrnnum].height = h2; 2221 2222 if(infochanged) { 2223 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2224 "Pseudo-Xinerama: CRT1 (Screen %d) (%d,%d)-(%d,%d)\n", 2225 crt1scrnnum, x1, y1, w1+x1-1, h1+y1-1); 2226 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2227 "Pseudo-Xinerama: CRT2 (Screen %d) (%d,%d)-(%d,%d)\n", 2228 crt2scrnnum, x2, y2, w2+x2-1, h2+y2-1); 2229 if(pSiS->HaveNonRect) { 2230 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2231 "Pseudo-Xinerama: Inaccessible area (%d,%d)-(%d,%d)\n", 2232 pSiS->NonRectDead.x0, pSiS->NonRectDead.y0, 2233 pSiS->NonRectDead.x1, pSiS->NonRectDead.y1); 2234 } 2235 if(pSiS->HaveOffsRegions) { 2236 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2237 "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", 2238 pSiS->OffDead1.x0, pSiS->OffDead1.y0, 2239 pSiS->OffDead1.x1, pSiS->OffDead1.y1); 2240 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2241 "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", 2242 pSiS->OffDead2.x0, pSiS->OffDead2.y0, 2243 pSiS->OffDead2.x1, pSiS->OffDead2.y1); 2244 } 2245 if(pSiS->HaveNonRect || pSiS->HaveOffsRegions) { 2246 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2247 "Mouse restriction for inaccessible areas is %s\n", 2248 pSiS->MouseRestrictions ? "enabled" : "disabled"); 2249 } 2250 } 2251} 2252 2253/* Proc */ 2254 2255int 2256SiSProcXineramaQueryVersion(ClientPtr client) 2257{ 2258 xPanoramiXQueryVersionReply rep; 2259 register int n; 2260 2261 REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq); 2262 rep.type = X_Reply; 2263 rep.length = 0; 2264 rep.sequenceNumber = client->sequence; 2265 rep.majorVersion = SIS_XINERAMA_MAJOR_VERSION; 2266 rep.minorVersion = SIS_XINERAMA_MINOR_VERSION; 2267 if(client->swapped) { 2268 swaps(&rep.sequenceNumber, n); 2269 swapl(&rep.length, n); 2270 swaps(&rep.majorVersion, n); 2271 swaps(&rep.minorVersion, n); 2272 } 2273 WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *)&rep); 2274 return (client->noClientException); 2275} 2276 2277int 2278SiSProcXineramaGetState(ClientPtr client) 2279{ 2280 REQUEST(xPanoramiXGetStateReq); 2281 WindowPtr pWin; 2282 xPanoramiXGetStateReply rep; 2283 register int n; 2284 2285 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); 2286 pWin = LookupWindow(stuff->window, client); 2287 if(!pWin) return BadWindow; 2288 2289 rep.type = X_Reply; 2290 rep.length = 0; 2291 rep.sequenceNumber = client->sequence; 2292 rep.state = !SiSnoPanoramiXExtension; 2293 if(client->swapped) { 2294 swaps (&rep.sequenceNumber, n); 2295 swapl (&rep.length, n); 2296 swaps (&rep.state, n); 2297 } 2298 WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *)&rep); 2299 return client->noClientException; 2300} 2301 2302int 2303SiSProcXineramaGetScreenCount(ClientPtr client) 2304{ 2305 REQUEST(xPanoramiXGetScreenCountReq); 2306 WindowPtr pWin; 2307 xPanoramiXGetScreenCountReply rep; 2308 register int n; 2309 2310 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); 2311 pWin = LookupWindow(stuff->window, client); 2312 if(!pWin) return BadWindow; 2313 2314 rep.type = X_Reply; 2315 rep.length = 0; 2316 rep.sequenceNumber = client->sequence; 2317 rep.ScreenCount = SiSXineramaNumScreens; 2318 if(client->swapped) { 2319 swaps(&rep.sequenceNumber, n); 2320 swapl(&rep.length, n); 2321 swaps(&rep.ScreenCount, n); 2322 } 2323 WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep); 2324 return client->noClientException; 2325} 2326 2327int 2328SiSProcXineramaGetScreenSize(ClientPtr client) 2329{ 2330 REQUEST(xPanoramiXGetScreenSizeReq); 2331 WindowPtr pWin; 2332 xPanoramiXGetScreenSizeReply rep; 2333 register int n; 2334 2335 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); 2336 pWin = LookupWindow (stuff->window, client); 2337 if(!pWin) return BadWindow; 2338 2339 rep.type = X_Reply; 2340 rep.length = 0; 2341 rep.sequenceNumber = client->sequence; 2342 rep.width = SiSXineramadataPtr[stuff->screen].width; 2343 rep.height = SiSXineramadataPtr[stuff->screen].height; 2344 if(client->swapped) { 2345 swaps(&rep.sequenceNumber, n); 2346 swapl(&rep.length, n); 2347 swaps(&rep.width, n); 2348 swaps(&rep.height, n); 2349 } 2350 WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep); 2351 return client->noClientException; 2352} 2353 2354int 2355SiSProcXineramaIsActive(ClientPtr client) 2356{ 2357 xXineramaIsActiveReply rep; 2358 2359 REQUEST_SIZE_MATCH(xXineramaIsActiveReq); 2360 2361 rep.type = X_Reply; 2362 rep.length = 0; 2363 rep.sequenceNumber = client->sequence; 2364 rep.state = !SiSnoPanoramiXExtension; 2365 if(client->swapped) { 2366 register int n; 2367 swaps(&rep.sequenceNumber, n); 2368 swapl(&rep.length, n); 2369 swapl(&rep.state, n); 2370 } 2371 WriteToClient(client, sizeof(xXineramaIsActiveReply), (char *) &rep); 2372 return client->noClientException; 2373} 2374 2375int 2376SiSProcXineramaQueryScreens(ClientPtr client) 2377{ 2378 xXineramaQueryScreensReply rep; 2379 2380 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); 2381 2382 rep.type = X_Reply; 2383 rep.sequenceNumber = client->sequence; 2384 rep.number = (SiSnoPanoramiXExtension) ? 0 : SiSXineramaNumScreens; 2385 rep.length = rep.number * sz_XineramaScreenInfo >> 2; 2386 if(client->swapped) { 2387 register int n; 2388 swaps(&rep.sequenceNumber, n); 2389 swapl(&rep.length, n); 2390 swapl(&rep.number, n); 2391 } 2392 WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *)&rep); 2393 2394 if(!SiSnoPanoramiXExtension) { 2395 xXineramaScreenInfo scratch; 2396 int i; 2397 2398 for(i = 0; i < SiSXineramaNumScreens; i++) { 2399 scratch.x_org = SiSXineramadataPtr[i].x; 2400 scratch.y_org = SiSXineramadataPtr[i].y; 2401 scratch.width = SiSXineramadataPtr[i].width; 2402 scratch.height = SiSXineramadataPtr[i].height; 2403 if(client->swapped) { 2404 register int n; 2405 swaps(&scratch.x_org, n); 2406 swaps(&scratch.y_org, n); 2407 swaps(&scratch.width, n); 2408 swaps(&scratch.height, n); 2409 } 2410 WriteToClient(client, sz_XineramaScreenInfo, (char *)&scratch); 2411 } 2412 } 2413 2414 return client->noClientException; 2415} 2416 2417static int 2418SiSProcXineramaDispatch(ClientPtr client) 2419{ 2420 REQUEST(xReq); 2421 switch (stuff->data) { 2422 case X_PanoramiXQueryVersion: 2423 return SiSProcXineramaQueryVersion(client); 2424 case X_PanoramiXGetState: 2425 return SiSProcXineramaGetState(client); 2426 case X_PanoramiXGetScreenCount: 2427 return SiSProcXineramaGetScreenCount(client); 2428 case X_PanoramiXGetScreenSize: 2429 return SiSProcXineramaGetScreenSize(client); 2430 case X_XineramaIsActive: 2431 return SiSProcXineramaIsActive(client); 2432 case X_XineramaQueryScreens: 2433 return SiSProcXineramaQueryScreens(client); 2434 } 2435 return BadRequest; 2436} 2437 2438/* SProc */ 2439 2440static int 2441SiSSProcXineramaQueryVersion (ClientPtr client) 2442{ 2443 REQUEST(xPanoramiXQueryVersionReq); 2444 register int n; 2445 swaps(&stuff->length,n); 2446 REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); 2447 return SiSProcXineramaQueryVersion(client); 2448} 2449 2450static int 2451SiSSProcXineramaGetState(ClientPtr client) 2452{ 2453 REQUEST(xPanoramiXGetStateReq); 2454 register int n; 2455 swaps (&stuff->length, n); 2456 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); 2457 return SiSProcXineramaGetState(client); 2458} 2459 2460static int 2461SiSSProcXineramaGetScreenCount(ClientPtr client) 2462{ 2463 REQUEST(xPanoramiXGetScreenCountReq); 2464 register int n; 2465 swaps (&stuff->length, n); 2466 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); 2467 return SiSProcXineramaGetScreenCount(client); 2468} 2469 2470static int 2471SiSSProcXineramaGetScreenSize(ClientPtr client) 2472{ 2473 REQUEST(xPanoramiXGetScreenSizeReq); 2474 register int n; 2475 swaps (&stuff->length, n); 2476 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); 2477 return SiSProcXineramaGetScreenSize(client); 2478} 2479 2480static int 2481SiSSProcXineramaIsActive(ClientPtr client) 2482{ 2483 REQUEST(xXineramaIsActiveReq); 2484 register int n; 2485 swaps (&stuff->length, n); 2486 REQUEST_SIZE_MATCH(xXineramaIsActiveReq); 2487 return SiSProcXineramaIsActive(client); 2488} 2489 2490static int 2491SiSSProcXineramaQueryScreens(ClientPtr client) 2492{ 2493 REQUEST(xXineramaQueryScreensReq); 2494 register int n; 2495 swaps (&stuff->length, n); 2496 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); 2497 return SiSProcXineramaQueryScreens(client); 2498} 2499 2500int 2501SiSSProcXineramaDispatch(ClientPtr client) 2502{ 2503 REQUEST(xReq); 2504 switch (stuff->data) { 2505 case X_PanoramiXQueryVersion: 2506 return SiSSProcXineramaQueryVersion(client); 2507 case X_PanoramiXGetState: 2508 return SiSSProcXineramaGetState(client); 2509 case X_PanoramiXGetScreenCount: 2510 return SiSSProcXineramaGetScreenCount(client); 2511 case X_PanoramiXGetScreenSize: 2512 return SiSSProcXineramaGetScreenSize(client); 2513 case X_XineramaIsActive: 2514 return SiSSProcXineramaIsActive(client); 2515 case X_XineramaQueryScreens: 2516 return SiSSProcXineramaQueryScreens(client); 2517 } 2518 return BadRequest; 2519} 2520 2521static void 2522SiSXineramaResetProc(ExtensionEntry* extEntry) 2523{ 2524 /* Called by CloseDownExtensions() */ 2525 if(SiSXineramadataPtr) { 2526 Xfree(SiSXineramadataPtr); 2527 SiSXineramadataPtr = NULL; 2528 } 2529} 2530 2531static void 2532SiSXineramaExtensionInit(ScrnInfoPtr pScrn) 2533{ 2534 SISPtr pSiS = SISPTR(pScrn); 2535 Bool success = FALSE; 2536 2537 if(!(SiSXineramadataPtr)) { 2538 2539 if(!pSiS->MergedFB) { 2540 SiSnoPanoramiXExtension = TRUE; 2541 pSiS->MouseRestrictions = FALSE; 2542 return; 2543 } 2544 2545#ifdef PANORAMIX 2546 if(!noPanoramiXExtension) { 2547 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2548 "Xinerama active, not initializing SiS Pseudo-Xinerama\n"); 2549 SiSnoPanoramiXExtension = TRUE; 2550 pSiS->MouseRestrictions = FALSE; 2551 return; 2552 } 2553#endif 2554 2555 if(SiSnoPanoramiXExtension) { 2556 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2557 "SiS Pseudo-Xinerama disabled\n"); 2558 pSiS->MouseRestrictions = FALSE; 2559 return; 2560 } 2561 2562 if(pSiS->CRT2Position == sisClone) { 2563 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2564 "Running MergedFB in Clone mode, SiS Pseudo-Xinerama disabled\n"); 2565 SiSnoPanoramiXExtension = TRUE; 2566 pSiS->MouseRestrictions = FALSE; 2567 return; 2568 } 2569 2570 if(!(pSiS->AtLeastOneNonClone)) { 2571 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2572 "Only Clone modes defined, SiS Pseudo-Xinerama disabled\n"); 2573 SiSnoPanoramiXExtension = TRUE; 2574 pSiS->MouseRestrictions = FALSE; 2575 return; 2576 } 2577 2578 SiSXineramaNumScreens = 2; 2579 2580 while(SiSXineramaGeneration != serverGeneration) { 2581 2582 pSiS->XineramaExtEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0, 2583 SiSProcXineramaDispatch, 2584 SiSSProcXineramaDispatch, 2585 SiSXineramaResetProc, 2586 StandardMinorOpcode); 2587 2588 if(!pSiS->XineramaExtEntry) break; 2589 2590 if(!(SiSXineramadataPtr = (SiSXineramaData *) 2591 xcalloc(SiSXineramaNumScreens, sizeof(SiSXineramaData)))) break; 2592 2593 SiSXineramaGeneration = serverGeneration; 2594 success = TRUE; 2595 } 2596 2597 if(!success) { 2598 SISErrorLog(pScrn, "Failed to initialize SiS Pseudo-Xinerama extension\n"); 2599 SiSnoPanoramiXExtension = TRUE; 2600 pSiS->MouseRestrictions = FALSE; 2601 return; 2602 } 2603 2604 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2605 "SiS Pseudo-Xinerama extension initialized\n"); 2606 2607 pSiS->SiSXineramaVX = 0; 2608 pSiS->SiSXineramaVY = 0; 2609 2610 } 2611 2612 SiSUpdateXineramaScreenInfo(pScrn); 2613 2614} 2615#endif /* End of PseudoXinerama */ 2616 2617static void 2618SiSFreeCRT2Structs(SISPtr pSiS) 2619{ 2620 if(pSiS->CRT2pScrn) { 2621 if(pSiS->CRT2pScrn->modes) { 2622 while(pSiS->CRT2pScrn->modes) 2623 xf86DeleteMode(&pSiS->CRT2pScrn->modes, pSiS->CRT2pScrn->modes); 2624 } 2625 if(pSiS->CRT2pScrn->monitor) { 2626 if(pSiS->CRT2pScrn->monitor->Modes) { 2627 while(pSiS->CRT2pScrn->monitor->Modes) 2628 xf86DeleteMode(&pSiS->CRT2pScrn->monitor->Modes, pSiS->CRT2pScrn->monitor->Modes); 2629 } 2630 if(pSiS->CRT2pScrn->monitor->DDC) xfree(pSiS->CRT2pScrn->monitor->DDC); 2631 xfree(pSiS->CRT2pScrn->monitor); 2632 } 2633 xfree(pSiS->CRT2pScrn); 2634 pSiS->CRT2pScrn = NULL; 2635 } 2636} 2637 2638#endif /* End of MergedFB helpers */ 2639 2640static xf86MonPtr 2641SiSInternalDDC(ScrnInfoPtr pScrn, int crtno) 2642{ 2643 SISPtr pSiS = SISPTR(pScrn); 2644 xf86MonPtr pMonitor = NULL; 2645 UShort temp = 0xffff, temp1, i, realcrtno = crtno; 2646 UChar buffer[256]; 2647 2648 /* If CRT1 is off, skip DDC */ 2649 if((pSiS->CRT1off) && (!crtno)) return NULL; 2650 2651 if(crtno) { 2652 if(pSiS->VBFlags & CRT2_LCD) realcrtno = 1; 2653 else if(pSiS->VBFlags & CRT2_VGA) realcrtno = 2; 2654 else return NULL; 2655 if(pSiS->SiS_Pr->DDCPortMixup) realcrtno = 0; 2656 } else { 2657 /* If CRT1 is LCDA, skip DDC (except 301C: DDC allowed, but uses CRT2 port!) */ 2658 if(pSiS->VBFlags & CRT1_LCDA) { 2659 if(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE) realcrtno = 1; 2660 else return NULL; 2661 } 2662 } 2663 2664 i = 3; /* Number of retrys */ 2665 do { 2666 temp1 = SiS_HandleDDC(pSiS->SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 2667 realcrtno, 0, &buffer[0], pSiS->VBFlags2); 2668 if((temp1) && (temp1 != 0xffff)) temp = temp1; 2669 } while((temp == 0xffff) && i--); 2670 if(temp != 0xffff) { 2671 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT%d DDC supported\n", crtno + 1); 2672 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT%d DDC level: %s%s%s%s\n", 2673 crtno + 1, 2674 (temp & 0x1a) ? "" : "[none of the supported]", 2675 (temp & 0x02) ? "2 " : "", 2676 (temp & 0x08) ? "D&P" : "", 2677 (temp & 0x10) ? "FPDI-2" : ""); 2678 if(temp & 0x02) { 2679 i = 5; /* Number of retrys */ 2680 do { 2681 temp = SiS_HandleDDC(pSiS->SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 2682 realcrtno, 1, &buffer[0], pSiS->VBFlags2); 2683 } while((temp) && i--); 2684 if(!temp) { 2685 if((pMonitor = xf86InterpretEDID(pScrn->scrnIndex, &buffer[0]))) { 2686 int tempvgagamma = 0, templcdgamma = 0; 2687 if(buffer[0x14] & 0x80) { 2688 templcdgamma = (buffer[0x17] + 100) * 10; 2689 } else { 2690 tempvgagamma = (buffer[0x17] + 100) * 10;; 2691 } 2692 if(crtno == 0) { 2693 if(tempvgagamma) pSiS->CRT1VGAMonitorGamma = tempvgagamma; 2694 /* LCD never via (demanded) CRT1 DDC port */ 2695 } else { 2696 if(tempvgagamma) pSiS->CRT2VGAMonitorGamma = tempvgagamma; 2697 if(templcdgamma) pSiS->CRT2LCDMonitorGamma = templcdgamma; 2698 } 2699 return(pMonitor); 2700 } else { 2701 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2702 "CRT%d DDC EDID corrupt\n", crtno + 1); 2703 } 2704 } else if(temp == 0xFFFE) { 2705 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2706 "CRT%d DDC data is from wrong device type (%s)\n", 2707 crtno + 1, 2708 (realcrtno == 1) ? "analog instead of digital" : "digital instead of analog"); 2709 } else { 2710 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2711 "CRT%d DDC reading failed\n", crtno + 1); 2712 } 2713 } else if(temp & 0x18) { 2714 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2715 "DDC for VESA D&P and FPDI-2 not supported yet.\n"); 2716 } 2717 } else { 2718 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2719 "CRT%d DDC probing failed\n", crtno + 1); 2720 } 2721 return(NULL); 2722} 2723 2724static xf86MonPtr 2725SiSDoPrivateDDC(ScrnInfoPtr pScrn, int *crtnum) 2726{ 2727 SISPtr pSiS = SISPTR(pScrn); 2728 2729#ifdef SISDUALHEAD 2730 if(pSiS->DualHeadMode) { 2731 if(pSiS->SecondHead) { 2732 *crtnum = 1; 2733 return(SiSInternalDDC(pScrn, 0)); 2734 } else { 2735 *crtnum = 2; 2736 return(SiSInternalDDC(pScrn, 1)); 2737 } 2738 } else 2739#endif 2740 if((pSiS->CRT1off) || (!pSiS->CRT1Detected)) { 2741 *crtnum = 2; 2742 return(SiSInternalDDC(pScrn, 1)); 2743 } else { 2744 *crtnum = 1; 2745 return(SiSInternalDDC(pScrn, 0)); 2746 } 2747} 2748 2749static void 2750SiSFindAspect(ScrnInfoPtr pScrn, xf86MonPtr pMonitor, int crtnum) 2751{ 2752 SISPtr pSiS = SISPTR(pScrn); 2753 int UseWide = 0; 2754 int aspect = 0; 2755 Bool fromdim = FALSE; 2756 2757 if((pSiS->VGAEngine == SIS_315_VGA) && (!DIGITAL(pMonitor->features.input_type))) { 2758 if(pMonitor->features.hsize && pMonitor->features.vsize) { 2759 aspect = (pMonitor->features.hsize * 1000) / pMonitor->features.vsize; 2760 if(aspect >= 1400) UseWide = 1; 2761 fromdim = TRUE; 2762 } else if((PREFERRED_TIMING_MODE(pMonitor->features.msc)) && 2763 (pMonitor->det_mon[0].type == DT)) { 2764 aspect = (pMonitor->det_mon[0].section.d_timings.h_active * 1000) / 2765 pMonitor->det_mon[0].section.d_timings.v_active; 2766 if(aspect >= 1400) UseWide = 1; 2767 } 2768 if(aspect) { 2769 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2770 "According to %s, CRT%d aspect ratio is %.2f:1 (%s)\n", 2771 fromdim ? "DDC size" : "preferred mode", 2772 crtnum, (float)aspect / 1000.0, UseWide ? "wide" : "normal"); 2773 } else { 2774 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2775 "Unable to determine CRT%d aspect ratio, assuming \"normal\"\n", 2776 crtnum); 2777 } 2778 } 2779 2780 if((crtnum == 1) && (pSiS->SiS_Pr->SiS_UseWide == -1)) { 2781 pSiS->SiS_Pr->SiS_UseWide = UseWide; 2782 } else if((crtnum == 2) && (pSiS->SiS_Pr->SiS_UseWideCRT2 == -1)) { 2783 pSiS->SiS_Pr->SiS_UseWideCRT2 = UseWide; 2784 } 2785} 2786 2787static Bool 2788SiSMakeOwnModeList(ScrnInfoPtr pScrn, Bool acceptcustommodes, Bool includelcdmodes, 2789 Bool isfordvi, Bool *havecustommodes, Bool fakecrt2modes, Bool IsForCRT2) 2790{ 2791 DisplayModePtr tempmode, delmode, mymodes; 2792 2793 if((mymodes = SiSBuildBuiltInModeList(pScrn, includelcdmodes, isfordvi, fakecrt2modes, IsForCRT2))) { 2794 if(!acceptcustommodes) { 2795 while(pScrn->monitor->Modes) 2796 xf86DeleteMode(&pScrn->monitor->Modes, pScrn->monitor->Modes); 2797 pScrn->monitor->Modes = mymodes; 2798 } else { 2799 delmode = pScrn->monitor->Modes; 2800 while(delmode) { 2801 if(delmode->type & M_T_DEFAULT) { 2802 tempmode = delmode->next; 2803 xf86DeleteMode(&pScrn->monitor->Modes, delmode); 2804 delmode = tempmode; 2805 } else { 2806 delmode = delmode->next; 2807 } 2808 } 2809 /* Link default modes AFTER user ones */ 2810 if((tempmode = pScrn->monitor->Modes)) { 2811 *havecustommodes = TRUE; 2812 while(tempmode) { 2813 if(!tempmode->next) break; 2814 else tempmode = tempmode->next; 2815 } 2816 tempmode->next = mymodes; 2817 mymodes->prev = tempmode; 2818 } else { 2819 pScrn->monitor->Modes = mymodes; 2820 } 2821#if 0 2822 pScrn->monitor->Modes = mymodes; 2823 while(mymodes) { 2824 if(!mymodes->next) break; 2825 else mymodes = mymodes->next; 2826 } 2827 mymodes->next = tempmode; 2828 if(tempmode) { 2829 tempmode->prev = mymodes; 2830 } 2831#endif 2832 } 2833 return TRUE; 2834 } else 2835 return FALSE; 2836} 2837 2838static void 2839SiSPrintModes(ScrnInfoPtr pScrn) 2840{ 2841 DisplayModePtr p; 2842 float hsync, refresh = 0.0; 2843 char *desc, *desc2, *prefix, *uprefix, *output; 2844 2845 xf86DrvMsg(pScrn->scrnIndex, pScrn->virtualFrom, "Virtual size is %dx%d " 2846 "(pitch %d)\n", pScrn->virtualX, pScrn->virtualY, 2847 pScrn->displayWidth); 2848 2849 if((p = pScrn->modes) == NULL) return; 2850 2851 do { 2852 desc = desc2 = ""; 2853 uprefix = " "; 2854 prefix = "Mode"; 2855 output = "For CRT device: "; 2856 if(p->HSync > 0.0) hsync = p->HSync; 2857 else if (p->HTotal > 0) hsync = (float)p->Clock / (float)p->HTotal; 2858 else hsync = 0.0; 2859 refresh = 0.0; 2860 if(p->VRefresh > 0.0) refresh = p->VRefresh; 2861 else if (p->HTotal > 0 && p->VTotal > 0) { 2862 refresh = p->Clock * 1000.0 / p->HTotal / p->VTotal; 2863 if(p->Flags & V_INTERLACE) refresh *= 2.0; 2864 if(p->Flags & V_DBLSCAN) refresh /= 2.0; 2865 if(p->VScan > 1) refresh /= p->VScan; 2866 } 2867 if(p->Flags & V_INTERLACE) desc = " (I)"; 2868 if(p->Flags & V_DBLSCAN) desc = " (D)"; 2869 if(p->VScan > 1) desc2 = " (VScan)"; 2870#ifdef M_T_USERDEF 2871 if(p->type & M_T_USERDEF) uprefix = "*"; 2872#endif 2873 if(p->type & M_T_BUILTIN) { 2874 prefix = "Built-in mode"; 2875 output = ""; 2876 } else if (p->type & M_T_DEFAULT) { 2877 prefix = "Default mode"; 2878 } else { 2879 output = ""; 2880 } 2881 2882 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2883 "%s%s \"%s\" (%dx%d) (%s%.1f MHz, %.1f kHz, %.1f Hz%s%s)\n", 2884 uprefix, prefix, p->name, p->HDisplay, p->VDisplay, output, 2885 p->Clock / 1000.0, hsync, refresh, desc, desc2); 2886 2887 p = p->next; 2888 } while (p != NULL && p != pScrn->modes); 2889} 2890 2891Bool SISDetermineLCDACap(ScrnInfoPtr pScrn) 2892{ 2893 SISPtr pSiS = SISPTR(pScrn); 2894 2895 if( ((pSiS->ChipType == SIS_650) || 2896 (pSiS->ChipType == SIS_315PRO) || 2897 (pSiS->ChipType >= SIS_661)) && 2898 (pSiS->ChipType != XGI_20) && 2899 (pSiS->VBFlags2 & VB2_SISLCDABRIDGE) && 2900 (pSiS->VESA != 1) ) { 2901 return TRUE; 2902 } 2903 return FALSE; 2904} 2905 2906void SISSaveDetectedDevices(ScrnInfoPtr pScrn) 2907{ 2908 SISPtr pSiS = SISPTR(pScrn); 2909 /* Backup detected CRT2 devices */ 2910 pSiS->detectedCRT2Devices = pSiS->VBFlags & (CRT2_LCD|CRT2_TV|CRT2_VGA|TV_AVIDEO|TV_SVIDEO| 2911 TV_SCART|TV_HIVISION|TV_YPBPR); 2912} 2913 2914static Bool 2915SISCheckBIOS(SISPtr pSiS, UShort mypciid, UShort mypcivendor, int biossize) 2916{ 2917 UShort romptr, pciid; 2918 2919 if(!pSiS->BIOS) return FALSE; 2920 2921 if((pSiS->BIOS[0] != 0x55) || (pSiS->BIOS[1] != 0xaa)) return FALSE; 2922 2923 romptr = pSiS->BIOS[0x18] | (pSiS->BIOS[0x19] << 8); 2924 if(romptr > (biossize - 8)) return FALSE; 2925 if((pSiS->BIOS[romptr] != 'P') || (pSiS->BIOS[romptr+1] != 'C') || 2926 (pSiS->BIOS[romptr+2] != 'I') || (pSiS->BIOS[romptr+3] != 'R')) return FALSE; 2927 2928 pciid = pSiS->BIOS[romptr+4] | (pSiS->BIOS[romptr+5] << 8); 2929 if(pciid != mypcivendor) return FALSE; 2930 2931 pciid = pSiS->BIOS[romptr+6] | (pSiS->BIOS[romptr+7] << 8); 2932 if(pciid != mypciid) return FALSE; 2933 2934 return TRUE; 2935} 2936 2937static void 2938SiS_LoadInitVBE(ScrnInfoPtr pScrn) 2939{ 2940 SISPtr pSiS = SISPTR(pScrn); 2941 2942 /* Don't load the VBE module for secondary 2943 * cards which sisfb POSTed. We don't want 2944 * int10 to overwrite our set up (such as 2945 * disabled a0000 memory address decoding). 2946 * We don't need the VBE anyway because 2947 * the card will never be in text mode, 2948 * and we can restore graphics modes just 2949 * perfectly. 2950 */ 2951 if( !pSiS->Primary && 2952 pSiS->sisfbcardposted) 2953 return; 2954 2955 if(pSiS->pVbe) return; 2956 2957 if(xf86LoadSubModule(pScrn, "vbe")) { 2958 xf86LoaderReqSymLists(vbeSymbols, NULL); 2959#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 2960 pSiS->pVbe = VBEInit(pSiS->pInt, pSiS->pEnt->index); 2961#else 2962 pSiS->pVbe = VBEExtendedInit(pSiS->pInt, pSiS->pEnt->index, 2963 SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH); 2964#endif 2965 } 2966 2967 if(!pSiS->pVbe) { 2968 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2969 "Failed to load/initialize vbe module\n"); 2970 } 2971} 2972 2973#ifdef SIS_PC_PLATFORM 2974static void 2975SiS_MapVGAMem(ScrnInfoPtr pScrn) 2976{ 2977 SISPtr pSiS = SISPTR(pScrn); 2978 2979 /* Map 64k VGA window for saving/restoring CGA fonts */ 2980 pSiS->VGAMapSize = 0x10000; 2981 pSiS->VGAMapPhys = 0; /* Default */ 2982 if((!pSiS->Primary) || (!pSiS->VGADecodingEnabled)) { 2983 /* If card is secondary or if a0000-address decoding 2984 * is disabled, set Phys to beginning of our video RAM. 2985 */ 2986 pSiS->VGAMapPhys = pSiS->PciInfo->memBase[0]; 2987 } 2988 if(!SiSVGAMapMem(pScrn)) { 2989 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2990 "Failed to map VGA memory (0x%lx), can't save/restore console fonts\n", 2991 pSiS->VGAMapPhys); 2992 } 2993} 2994#endif 2995 2996static void 2997SiS_CheckKernelFB(ScrnInfoPtr pScrn) 2998{ 2999 SISPtr pSiS = SISPTR(pScrn); 3000 int fd, i; 3001 CARD32 sisfbinfosize = 0, sisfbversion; 3002 sisfb_info *mysisfbinfo; 3003 char name[16]; 3004 3005 pSiS->donttrustpdc = FALSE; 3006 pSiS->sisfbpdc = 0xff; 3007 pSiS->sisfbpdca = 0xff; 3008 pSiS->sisfblcda = 0xff; 3009 pSiS->sisfbscalelcd = -1; 3010 pSiS->sisfbspecialtiming = CUT_NONE; 3011 pSiS->sisfb_haveemi = FALSE; 3012 pSiS->sisfbfound = FALSE; 3013 pSiS->sisfb_tvposvalid = FALSE; 3014 pSiS->sisfbdevname[0] = 0; 3015 pSiS->sisfb_havelock = FALSE; 3016 pSiS->sisfbHaveNewHeapDef = FALSE; 3017 pSiS->sisfbHeapSize = 0; 3018 pSiS->sisfbVideoOffset = 0; 3019 pSiS->sisfbxSTN = FALSE; 3020 pSiS->sisfbcanpost = FALSE; /* (Old) sisfb can't POST card */ 3021 pSiS->sisfbcardposted = TRUE; /* If (old) sisfb is running, card must have been POSTed */ 3022 pSiS->sisfbprimary = FALSE; /* (Old) sisfb doesn't know */ 3023 3024 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 3025 3026 i = 0; 3027 do { 3028 3029 if(i <= 7) { 3030 sprintf(name, "/dev/fb%1d", i); 3031 } else { 3032 sprintf(name, "/dev/fb/%1d", (i - 8)); 3033 } 3034 3035 if((fd = open(name, 'r')) != -1) { 3036 3037 Bool gotit = FALSE; 3038 3039 if(!ioctl(fd, SISFB_GET_INFO_SIZE, &sisfbinfosize)) { 3040 if((mysisfbinfo = xalloc(sisfbinfosize))) { 3041 if(!ioctl(fd, (SISFB_GET_INFO | (sisfbinfosize << 16)), mysisfbinfo)) { 3042 gotit = TRUE; 3043 } else { 3044 xfree(mysisfbinfo); 3045 mysisfbinfo = NULL; 3046 } 3047 } 3048 } else { 3049 if((mysisfbinfo = xalloc(sizeof(*mysisfbinfo) + 16))) { 3050 if(!ioctl(fd, SISFB_GET_INFO_OLD, mysisfbinfo)) { 3051 gotit = TRUE; 3052 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3053 "Possibly old version of sisfb detected. Please update.\n"); 3054 } else { 3055 xfree(mysisfbinfo); 3056 mysisfbinfo = NULL; 3057 } 3058 } 3059 } 3060 3061 if(gotit) { 3062 3063 if(mysisfbinfo->sisfb_id == SISFB_ID) { 3064 3065 sisfbversion = (mysisfbinfo->sisfb_version << 16) | 3066 (mysisfbinfo->sisfb_revision << 8) | 3067 (mysisfbinfo->sisfb_patchlevel); 3068 3069 if(sisfbversion >= SISFB_VERSION(1, 5, 8)) { 3070 /* Added PCI bus/slot/func into in sisfb Version 1.5.08. 3071 * Check this to make sure we run on the same card as sisfb 3072 */ 3073 if((mysisfbinfo->sisfb_pcibus == pSiS->PciBus) && 3074 (mysisfbinfo->sisfb_pcislot == pSiS->PciDevice) && 3075 (mysisfbinfo->sisfb_pcifunc == pSiS->PciFunc)) { 3076 pSiS->sisfbfound = TRUE; 3077 } 3078 } else pSiS->sisfbfound = TRUE; 3079 3080 if(pSiS->sisfbfound) { 3081 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3082 "%s: SiS kernel fb driver (sisfb) %d.%d.%d detected (PCI:%02d:%02d.%d)\n", 3083 &name[5], 3084 mysisfbinfo->sisfb_version, 3085 mysisfbinfo->sisfb_revision, 3086 mysisfbinfo->sisfb_patchlevel, 3087 pSiS->PciBus, 3088 pSiS->PciDevice, 3089 pSiS->PciFunc); 3090 3091 /* Added version/rev/pl in sisfb 1.4.0 */ 3092 if(mysisfbinfo->sisfb_version == 0) { 3093 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3094 "Old version of sisfb found. Please update.\n"); 3095 } 3096 /* Basically, we can't trust the pdc register if sisfb is loaded */ 3097 pSiS->donttrustpdc = TRUE; 3098 pSiS->sisfbHeapStart = mysisfbinfo->heapstart; 3099 3100 if(sisfbversion >= SISFB_VERSION(1, 7, 20)) { 3101 pSiS->sisfbHeapSize = mysisfbinfo->sisfb_heapsize; 3102 pSiS->sisfbVideoOffset = mysisfbinfo->sisfb_videooffset; 3103 pSiS->sisfbHaveNewHeapDef = TRUE; 3104 pSiS->sisfbFSTN = mysisfbinfo->sisfb_curfstn; 3105 pSiS->sisfbDSTN = mysisfbinfo->sisfb_curdstn; 3106 pSiS->sisfbxSTN = TRUE; 3107 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3108 "sisfb: memory heap at %dKB, size %dKB, viewport at %dKB\n", 3109 (int)pSiS->sisfbHeapStart, (int)pSiS->sisfbHeapSize, 3110 (int)pSiS->sisfbVideoOffset/1024); 3111 } else { 3112 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3113 "sisfb: memory heap at %dKB\n", (int)pSiS->sisfbHeapStart); 3114 } 3115 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3116 "sisfb: using video mode 0x%02x\n", mysisfbinfo->fbvidmode); 3117 pSiS->OldMode = mysisfbinfo->fbvidmode; 3118 if(sisfbversion >= SISFB_VERSION(1, 5, 6)) { 3119 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3120 "sisfb: using %s, reserved %dK\n", 3121 (mysisfbinfo->sisfb_caps & 0x40) ? "SiS300 series Turboqueue" : 3122 (mysisfbinfo->sisfb_caps & 0x20) ? "SiS315/330/340 series AGP command queue" : 3123 (mysisfbinfo->sisfb_caps & 0x10) ? "SiS315/330/340 series VRAM command queue" : 3124 (mysisfbinfo->sisfb_caps & 0x08) ? "SiS315/330/340 series MMIO mode" : 3125 "no command queue", 3126 (int)mysisfbinfo->sisfb_tqlen); 3127 } 3128 if(sisfbversion >= SISFB_VERSION(1, 5, 10)) { 3129 /* We can trust the pdc value if sisfb is of recent version */ 3130 if(pSiS->VGAEngine == SIS_300_VGA) pSiS->donttrustpdc = FALSE; 3131 } 3132 if(sisfbversion >= SISFB_VERSION(1, 5, 11)) { 3133 if(pSiS->VGAEngine == SIS_300_VGA) { 3134 /* As of 1.5.11, sisfb saved the register for us (300 series) */ 3135 pSiS->sisfbpdc = mysisfbinfo->sisfb_lcdpdc; 3136 if(!pSiS->sisfbpdc) pSiS->sisfbpdc = 0xff; 3137 } 3138 } 3139 if(sisfbversion >= SISFB_VERSION(1, 5, 14)) { 3140 if(pSiS->VGAEngine == SIS_315_VGA) { 3141 pSiS->sisfblcda = mysisfbinfo->sisfb_lcda; 3142 } 3143 } 3144 if(sisfbversion >= SISFB_VERSION(1, 6, 13)) { 3145 pSiS->sisfbscalelcd = mysisfbinfo->sisfb_scalelcd; 3146 pSiS->sisfbspecialtiming = mysisfbinfo->sisfb_specialtiming; 3147 } 3148 if(sisfbversion >= SISFB_VERSION(1, 6, 16)) { 3149 if(pSiS->VGAEngine == SIS_315_VGA) { 3150 pSiS->donttrustpdc = FALSE; 3151 pSiS->sisfbpdc = mysisfbinfo->sisfb_lcdpdc; 3152 if(sisfbversion >= SISFB_VERSION(1, 6, 24)) { 3153 pSiS->sisfb_haveemi = mysisfbinfo->sisfb_haveemi ? TRUE : FALSE; 3154 pSiS->sisfb_haveemilcd = TRUE; /* will match most cases */ 3155 pSiS->sisfb_emi30 = mysisfbinfo->sisfb_emi30; 3156 pSiS->sisfb_emi31 = mysisfbinfo->sisfb_emi31; 3157 pSiS->sisfb_emi32 = mysisfbinfo->sisfb_emi32; 3158 pSiS->sisfb_emi33 = mysisfbinfo->sisfb_emi33; 3159 } 3160 if(sisfbversion >= SISFB_VERSION(1, 6, 25)) { 3161 pSiS->sisfb_haveemilcd = mysisfbinfo->sisfb_haveemilcd ? TRUE : FALSE; 3162 } 3163 if(sisfbversion >= SISFB_VERSION(1, 6, 31)) { 3164 pSiS->sisfbpdca = mysisfbinfo->sisfb_lcdpdca; 3165 } else { 3166 if(pSiS->sisfbpdc) { 3167 pSiS->sisfbpdca = (pSiS->sisfbpdc & 0xf0) >> 3; 3168 pSiS->sisfbpdc = (pSiS->sisfbpdc & 0x0f) << 1; 3169 } else { 3170 pSiS->sisfbpdca = pSiS->sisfbpdc = 0xff; 3171 } 3172 } 3173 } 3174 } 3175 if(sisfbversion >= SISFB_VERSION(1, 7, 0)) { 3176 pSiS->sisfb_havelock = TRUE; 3177 if(sisfbversion >= SISFB_VERSION(1, 7, 1)) { 3178 pSiS->sisfb_tvxpos = mysisfbinfo->sisfb_tvxpos; 3179 pSiS->sisfb_tvypos = mysisfbinfo->sisfb_tvypos; 3180 pSiS->sisfb_tvposvalid = TRUE; 3181 } 3182 } 3183 if(sisfbversion >= SISFB_VERSION(1, 8, 7)) { 3184 pSiS->sisfbcanpost = (mysisfbinfo->sisfb_can_post) ? TRUE : FALSE; 3185 pSiS->sisfbcardposted = (mysisfbinfo->sisfb_card_posted) ? TRUE : FALSE; 3186 pSiS->sisfbprimary = (mysisfbinfo->sisfb_was_boot_device) ? TRUE : FALSE; 3187 /* Validity check */ 3188 if(!pSiS->sisfbcardposted) { 3189 pSiS->sisfbprimary = FALSE; 3190 } 3191 } 3192 } 3193 } 3194 xfree(mysisfbinfo); 3195 mysisfbinfo = NULL; 3196 } 3197 close (fd); 3198 } 3199 i++; 3200 } while((i <= 15) && (!pSiS->sisfbfound)); 3201 3202 if(pSiS->sisfbfound) { 3203 strncpy(pSiS->sisfbdevname, name, 15); 3204 } else { 3205 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "sisfb not found\n"); 3206 } 3207 } 3208 3209 if(!pSiS->sisfbfound) { 3210 pSiS->sisfbcardposted = FALSE; 3211 } 3212} 3213 3214static void 3215SiSPseudo(ScrnInfoPtr pScrn) 3216{ 3217} 3218 3219/* PreInit() 3220 * 3221 * Mandatory 3222 */ 3223static Bool 3224SISPreInit(ScrnInfoPtr pScrn, int flags) 3225{ 3226 SISPtr pSiS; 3227#ifdef SISDUALHEAD 3228 SISEntPtr pSiSEnt = NULL; 3229#endif 3230 MessageType from; 3231 UChar usScratchCR17, usScratchCR32, usScratchCR63; 3232 UChar usScratchSR1F, srlockReg, crlockReg; 3233 unsigned int i; 3234 int pix24flags, temp; 3235 ClockRangePtr clockRanges; 3236 xf86MonPtr pMonitor = NULL; 3237 Bool didddc2, fromDDC, crt1freqoverruled = FALSE; 3238 UChar CR5F, tempreg; 3239#if defined(SISMERGED) || defined(SISDUALHEAD) 3240 DisplayModePtr first, p, n; 3241#endif 3242#ifdef SISMERGED 3243 Bool crt2freqoverruled = FALSE; 3244#endif 3245 3246 static const char *ddcsstr = "CRT%d DDC monitor info: *******************************************\n"; 3247 static const char *ddcestr = "End of CRT%d DDC monitor info *************************************\n"; 3248 static const char *subshstr = "Substituting missing CRT%d monitor HSync range by DDC data\n"; 3249 static const char *subsvstr = "Substituting missing CRT%d monitor VRefresh range by DDC data\n"; 3250 static const char *saneh = "Correcting %s CRT%d monitor HSync range\n"; 3251 static const char *sanev = "Correcting %s CRT%d monitor VRefresh range\n"; 3252#ifdef SISMERGED 3253 static const char *mergednocrt1 = "CRT1 not detected or forced off. %s.\n"; 3254 static const char *mergednocrt2 = "No CRT2 output selected or no video bridge detected. %s.\n"; 3255 static const char *mergeddisstr = "MergedFB mode disabled"; 3256 static const char *modesforstr = "Modes for CRT%d: **************************************************\n"; 3257 static const char *crtsetupstr = "*************************** CRT%d setup ***************************\n"; 3258 static const char *crt2monname = "CRT2"; 3259#endif 3260#if defined(SISDUALHEAD) || defined(SISMERGED) 3261 static const char *notsuitablestr = "Not using mode \"%s\" (not suitable for %s mode)\n"; 3262#endif 3263 3264 if(flags & PROBE_DETECT) { 3265 3266 vbeInfoPtr pVbe; 3267 3268 if(xf86LoadSubModule(pScrn, "vbe")) { 3269 int index = xf86GetEntityInfo(pScrn->entityList[0])->index; 3270#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 3271 if((pVbe = VBEInit(NULL, index))) 3272#else 3273 if((pVbe = VBEExtendedInit(NULL, index, 0))) 3274#endif 3275 { 3276 ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 3277 vbeFree(pVbe); 3278 } 3279 } 3280 return TRUE; 3281 } 3282 3283 /* 3284 * Note: This function is only called once at server startup, and 3285 * not at the start of each server generation. This means that 3286 * only things that are persistent across server generations can 3287 * be initialised here. xf86Screens[] is the array of all screens, 3288 * (pScrn is a pointer to one of these). Privates allocated using 3289 * xf86AllocateScrnInfoPrivateIndex() are too, and should be used 3290 * for data that must persist across server generations. 3291 * 3292 * Per-generation data should be allocated with 3293 * AllocateScreenPrivateIndex() from the ScreenInit() function. 3294 */ 3295 3296 /* Check the number of entities, and fail if it isn't one. */ 3297 if(pScrn->numEntities != 1) { 3298 SISErrorLog(pScrn, "Number of entities is not 1\n"); 3299 return FALSE; 3300 } 3301 3302 /* Due to the liberal license terms this is needed for 3303 * keeping the copyright notice readable and intact in 3304 * binary distributions. Removing this is a copyright 3305 * infringement. Please read the license terms above. 3306 */ 3307 3308 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3309 "SiS driver (%d/%02d/%02d-%d, compiled for " SISMYSERVERNAME " %d.%d.%d.%d)\n", 3310 SISDRIVERVERSIONYEAR + 2000, SISDRIVERVERSIONMONTH, 3311 SISDRIVERVERSIONDAY, SISDRIVERREVISION, 3312#ifdef XORG_VERSION_CURRENT 3313 XORG_VERSION_MAJOR, XORG_VERSION_MINOR, 3314 XORG_VERSION_PATCH, XORG_VERSION_SNAP 3315#else 3316 XF86_VERSION_MAJOR, XF86_VERSION_MINOR, 3317 XF86_VERSION_PATCH, XF86_VERSION_SNAP 3318#endif 3319 ); 3320 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3321 "Copyright (C) 2001-2005 Thomas Winischhofer <thomas@winischhofer.net> and others\n"); 3322 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3323 "*** See http://www.winischhofer.at/linuxsisvga.shtml\n"); 3324 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3325 "*** for documentation and updates.\n"); 3326 3327#ifdef XORG_VERSION_CURRENT 3328#if 0 /* no prototype yet */ 3329 if(xorgGetVersion() != XORG_VERSION_CURRENT) { 3330 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3331 "This driver binary is not compiled for this version of " SISMYSERVERNAME "\n"); 3332 } 3333#endif 3334#else 3335#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0) 3336 if(xf86GetVersion() != XF86_VERSION_CURRENT) { 3337 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3338 "This driver binary is not compiled for this version of " SISMYSERVERNAME "\n"); 3339 } 3340#endif 3341#endif 3342 3343 /* Allocate the SISRec driverPrivate */ 3344 if(!SISGetRec(pScrn)) { 3345 SISErrorLog(pScrn, "Could not allocate memory for pSiS private\n"); 3346 return FALSE; 3347 } 3348 pSiS = SISPTR(pScrn); 3349 pSiS->pScrn = pScrn; 3350 3351 pSiS->pInt = NULL; 3352 3353 /* Save PCI Domain Base */ 3354#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 3355 pSiS->IODBase = 0; 3356#else 3357 pSiS->IODBase = pScrn->domainIOBase; 3358#endif 3359 3360 /* Get the entity, and make sure it is PCI. */ 3361 pSiS->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 3362 if(pSiS->pEnt->location.type != BUS_PCI) { 3363 SISErrorLog(pScrn, "Entity's bus type is not PCI\n"); 3364 goto my_error_0; 3365 } 3366 3367#ifdef SISDUALHEAD 3368 /* Allocate an entity private if necessary */ 3369 if(xf86IsEntityShared(pScrn->entityList[0])) { 3370 pSiSEnt = xf86GetEntityPrivate(pScrn->entityList[0], SISEntityIndex)->ptr; 3371 pSiS->entityPrivate = pSiSEnt; 3372 3373 /* If something went wrong, quit here */ 3374 if((pSiSEnt->DisableDual) || (pSiSEnt->ErrorAfterFirst)) { 3375 SISErrorLog(pScrn, "First head encountered fatal error, aborting...\n"); 3376 goto my_error_0; 3377 } 3378 } 3379#endif 3380 3381 /* Find the PCI info for this screen */ 3382 pSiS->PciInfo = xf86GetPciInfoForEntity(pSiS->pEnt->index); 3383 pSiS->PciBus = ((pciConfigPtr)pSiS->PciInfo->thisCard)->busnum; /*SIS_PCI_BUS(pSiS->PciInfo);*/ 3384 pSiS->PciDevice = ((pciConfigPtr)pSiS->PciInfo->thisCard)->devnum; /*SIS_PCI_DEVICE(pSiS->PciInfo);*/ 3385 pSiS->PciFunc = ((pciConfigPtr)pSiS->PciInfo->thisCard)->funcnum; /*SIS_PCI_FUNC(pSiS->PciInfo);*/ 3386 pSiS->PciTag = ((pciConfigPtr)pSiS->PciInfo->thisCard)->tag; /*SIS_PCI_TAG(pSiS->PciInfo);*/ 3387 3388#ifdef SIS_NEED_MAP_IOP 3389 /********************************************/ 3390 /* THIS IS BROKEN AND WON'T WORK */ 3391 /* Reasons: */ 3392 /* 1) MIPS and ARM have no i/o ports but */ 3393 /* use memory mapped i/o only. The inX/outX */ 3394 /* macros in compiler.h are smart enough to */ 3395 /* add "IOPortBase" to the port number, but */ 3396 /* "IOPortBase" is never initialized. */ 3397 /* 2) IOPortBase is declared in compiler.h */ 3398 /* itself. So until somebody fixes all */ 3399 /* modules that #include compiler.h to set */ 3400 /* IOPortBase, vga support for MIPS and ARM */ 3401 /* is unusable. */ 3402 /* (In this driver this is solvable because */ 3403 /* we have our own vgaHW routines. However, */ 3404 /* we use /dev/port for now instead.) */ 3405 /********************************************/ 3406 pSiS->IOPAddress = pSiS->IODBase + pSiS->PciInfo->ioBase[2]; 3407 if(!SISMapIOPMem(pScrn)) { 3408 SISErrorLog(pScrn, "Could not map I/O port area at 0x%x\n", pSiS->IOPAddress); 3409 goto my_error_0; 3410 } else { 3411 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I/O port area mapped to %p, size 128\n", pSiS->IOPBase); 3412#if defined(__mips__) || defined(__arm32__) 3413 /* inX/outX macros on these use IOPortBase as offset */ 3414 /* This is entirely skrewed. */ 3415 IOPortBase = (unsigned int)pSiS->IOPBase; 3416#endif 3417 } 3418#endif 3419 3420 /* Set up i/o port access (for non-x86) */ 3421#ifdef SISUSEDEVPORT 3422 if((sisdevport = open("/dev/port", O_RDWR, 0)) == -1) { 3423 SISErrorLog(pScrn, "Failed to open /dev/port for read/write\n"); 3424 goto my_error_0; 3425 } 3426 pSiS->sisdevportopen = TRUE; 3427#endif 3428 3429 /* 3430 * Set the Chipset and ChipRev, allowing config file entries to 3431 * override. DANGEROUS! 3432 */ 3433 { 3434 SymTabRec *myChipsets = SISChipsets; 3435 3436 if(pSiS->PciInfo->vendor == PCI_VENDOR_XGI) { 3437 myChipsets = XGIChipsets; 3438 } 3439 3440 if(pSiS->pEnt->device->chipset && *pSiS->pEnt->device->chipset) { 3441 3442 pScrn->chipset = pSiS->pEnt->device->chipset; 3443 pSiS->Chipset = xf86StringToToken(myChipsets, pScrn->chipset); 3444 3445 } else if(pSiS->pEnt->device->chipID >= 0) { 3446 3447 pSiS->Chipset = pSiS->pEnt->device->chipID; 3448 pScrn->chipset = (char *)xf86TokenToString(myChipsets, pSiS->Chipset); 3449 3450 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", 3451 pSiS->Chipset); 3452 } else { 3453 3454 pSiS->Chipset = pSiS->PciInfo->chipType; 3455 pScrn->chipset = (char *)xf86TokenToString(myChipsets, pSiS->Chipset); 3456 3457 } 3458 } 3459 3460 if(pSiS->pEnt->device->chipRev >= 0) { 3461 3462 pSiS->ChipRev = pSiS->pEnt->device->chipRev; 3463 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 3464 pSiS->ChipRev); 3465 } else { 3466 3467 pSiS->ChipRev = pSiS->PciInfo->chipRev; 3468 3469 } 3470 3471 /* 3472 * This shouldn't happen because such problems should be caught in 3473 * SISProbe(), but check it just in case the user has overridden them. 3474 */ 3475 if(pScrn->chipset == NULL) { 3476 SISErrorLog(pScrn, "ChipID 0x%04X is not recognised\n", pSiS->Chipset); 3477 goto my_error_0; 3478 } 3479 if(pSiS->Chipset < 0) { 3480 SISErrorLog(pScrn, "Chipset \"%s\" is not recognised\n", pScrn->chipset); 3481 goto my_error_0; 3482 } 3483 3484 pSiS->SiS6326Flags = 0; 3485 3486 /* Determine VGA engine generation */ 3487 switch(pSiS->Chipset) { 3488 case PCI_CHIP_SIS300: 3489 case PCI_CHIP_SIS540: 3490 case PCI_CHIP_SIS630: /* 630 + 730 */ 3491 pSiS->VGAEngine = SIS_300_VGA; 3492 break; 3493 case PCI_CHIP_SIS315H: 3494 case PCI_CHIP_SIS315: 3495 case PCI_CHIP_SIS315PRO: 3496 case PCI_CHIP_SIS550: 3497 case PCI_CHIP_SIS650: /* 650 + 740 */ 3498 case PCI_CHIP_SIS330: 3499 case PCI_CHIP_SIS660: /* 660, 661, 741, 760, 761, 670(?), 770 */ 3500 case PCI_CHIP_SIS340: 3501 case PCI_CHIP_XGIXG20: 3502 case PCI_CHIP_XGIXG40: 3503 pSiS->VGAEngine = SIS_315_VGA; 3504 break; 3505 case PCI_CHIP_SIS530: 3506 pSiS->VGAEngine = SIS_530_VGA; 3507 break; 3508 case PCI_CHIP_SIS6326: 3509 /* Determine SiS6326 revision. According to SiS the differences are: 3510 * Chip name Chip type TV-Out MPEG II decoder 3511 * 6326 AGP Rev. G0/H0 no no 3512 * 6326 DVD Rev. D2 yes yes 3513 * 6326 Rev. Cx yes yes 3514 */ 3515 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3516 "Chipset is SiS6326 %s (revision 0x%02x)\n", 3517 (pSiS->ChipRev == 0xaf) ? "(Ax)" : 3518 ((pSiS->ChipRev == 0x0a) ? "AGP (G0)" : 3519 ((pSiS->ChipRev == 0x0b) ? "AGP (H0)" : 3520 (((pSiS->ChipRev & 0xf0) == 0xd0) ? "DVD (Dx/H0)" : 3521 (((pSiS->ChipRev & 0xf0) == 0x90) ? "(9x)" : 3522 (((pSiS->ChipRev & 0xf0) == 0xc0) ? "(Cx)" : 3523 "(unknown)"))))), 3524 pSiS->ChipRev); 3525 if((pSiS->ChipRev != 0x0a) && (pSiS->ChipRev != 0x0b)) { 3526 pSiS->SiS6326Flags |= SIS6326_HASTV; 3527 } 3528 /* fall through */ 3529 default: 3530 pSiS->VGAEngine = SIS_OLD_VGA; 3531 } 3532 3533 /* We don't know about the current mode yet */ 3534 pSiS->OldMode = 0; 3535 3536 /* Determine whether this is the primary or a secondary 3537 * display adapter. And right here the problem starts: 3538 * On machines with integrated SiS chipsets, the system BIOS 3539 * usually sets VGA_EN on all PCI-to-PCI bridges in the system 3540 * (of which there usually are two: PCI and AGP). This and 3541 * the fact that any PCI card POSTed by sisfb naturally has 3542 * its PCI resources enabled, leads to X assuming that 3543 * there are more than one "primary" cards in the system. 3544 * In this case, X treats ALL cards as "secondary" - 3545 * which by no means is desireable. If sisfb is running, 3546 * we can determine which card really is "primary" (in 3547 * terms of if it's the one that occupies the A0000 area 3548 * etc.) in a better way (Linux 2.6.12 or later). See below. 3549 */ 3550 if(!(pSiS->Primary = xf86IsPrimaryPci(pSiS->PciInfo))) { 3551 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3552 SISMYSERVERNAME " assumes this adapter to be secondary\n"); 3553 } 3554 3555 /* Now check if sisfb is running, and if so, retrieve 3556 * all possible info from it. This also resets all 3557 * sisfb_* entries in pSiS regardless of the chipset. 3558 */ 3559 SiS_CheckKernelFB(pScrn); 3560 3561 /* Now for that primary/secondary mess: Linux kernel 3562 * 2.6.12 and later knows what card is primary, and so 3563 * does any recent version of sisfb. XFree86/X.org takes 3564 * all adapters as "secondary" if more than one card's 3565 * memory and i/o resources are enabled, and more than 3566 * one PCI bridge in the system has VGA_EN set at server 3567 * start. So, let's start thinking: What is this 3568 * primary/secondary classification needed for anyway? 3569 * (This list might be incomplete for the entire server 3570 * infrastructure, but it's complete as regards the driver's 3571 * purposes of primary/secondary classification.) 3572 * 1) VGA/console font restoring: Here it's irrelevant 3573 * whether more than one card's resources are enabled 3574 * at server start or not. Relevant is whether the card 3575 * occupies the A0000 area at this time. Assuming (?) 3576 * that this does not change during machine up-time, 3577 * it suffices to know which device was the boot video 3578 * device (as determined by Linux 2.6.12 and later). 3579 * Also, this is only relevant if the card is in text 3580 * mode; if it's in graphics mode, fonts aren't saved 3581 * or restored anyway. 3582 * sisfb tells us if that card is considered the boot 3583 * video device. The hardware registers tell us if 3584 * the card's A0000 address decoding is enabled, and if 3585 * the card currently is in text mode. These three bits 3586 * of information are enough to decide on whether or not 3587 * to save/restore fonts. 3588 * 2) POSTing. Same here. Relevant is only whether or not 3589 * the card has been POSTed once before. POSTing cards 3590 * on every server start is pretty ugly, especially 3591 * if a framebuffer driver is already handling it. 3592 * SiS/XGI cards POSTed by sisfb can coexist well with other 3593 * active adapters. So we trust sisfb's information more 3594 * than X's (especially as we only use this information for 3595 * console font restoring and eventual POSTing.) 3596 * What we still need is a way to find out about all this if 3597 * sisfb is not running.... 3598 */ 3599 if(!pSiS->Primary && pSiS->sisfbprimary) { 3600 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3601 "sisfb reports this adapter to be primary. Seems more reliable.\n"); 3602 pSiS->Primary = TRUE; 3603 } 3604 3605 /* If the card is "secondary" and has not been 3606 * POSTed by sisfb, POST it now through int10. 3607 * For cards POSTed by sisfb, we definitely don't 3608 * want that as it messes up our set up (eg. the 3609 * disabled A0000 area). 3610 * The int10 module decides on its own if the 3611 * card is primary or secondary. Since it uses 3612 * the generic technique described above, and since 3613 * for "secondary" cards it needs a real PCI BIOS 3614 * ROM, and since integrated chips don't have such 3615 * a PCI BIOS ROM, int10 will naturally fail to 3616 * find/read the BIOS on such machines. Great. 3617 * Using the integrated graphics as "secondary" 3618 * (which it will be as soon as X finds more than 3619 * one card's mem and i/o resources enabled, and more 3620 * than one PCI bridge's VGA_EN bit set during server 3621 * start) will therefore prevent us from restoring 3622 * the mode using the VBE. That means real fun if 3623 * the integrated chip is set up to use the video 3624 * bridge output for text mode (which is something 3625 * the driver doesn't really support since it's done 3626 * pretty much differently on every machine.) 3627 */ 3628#if !defined(__alpha__) 3629 if(!pSiS->Primary) { 3630 if(!pSiS->sisfbcardposted) { 3631 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3632 "Initializing adapter through int10\n"); 3633 if(xf86LoadSubModule(pScrn, "int10")) { 3634 xf86LoaderReqSymLists(int10Symbols, NULL); 3635 pSiS->pInt = xf86InitInt10(pSiS->pEnt->index); 3636 } else { 3637 SISErrorLog(pScrn, "Failed to load int10 module\n"); 3638 } 3639 } else { 3640 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3641 "Adapter already initialized by sisfb\n"); 3642 } 3643 } 3644#endif 3645 3646 /* Get the address of our relocated IO registers. 3647 * These are enabled by the hardware during cold boot, and 3648 * by the BIOS. So we can pretty much rely on that these 3649 * are enabled. 3650 */ 3651 pSiS->RelIO = (SISIOADDRESS)(pSiS->PciInfo->ioBase[2] + pSiS->IODBase); 3652 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Relocated I/O registers at 0x%lX\n", 3653 (ULong)pSiS->RelIO); 3654 3655 /* Unlock extended registers */ 3656 sisSaveUnlockExtRegisterLock(pSiS, &srlockReg, &crlockReg); 3657 3658 /* Is a0000 memory address decoding enabled? */ 3659 pSiS->VGADecodingEnabled = TRUE; 3660 switch(pSiS->VGAEngine) { 3661 case SIS_OLD_VGA: 3662 /* n/a */ 3663 break; 3664 case SIS_530_VGA: 3665 inSISIDXREG(SISSR, 0x3d, tempreg); 3666 if(tempreg & 0x04) pSiS->VGADecodingEnabled = FALSE; 3667 break; 3668 case SIS_300_VGA: 3669 case SIS_315_VGA: 3670 inSISIDXREG(SISSR, 0x20, tempreg); 3671 if(tempreg & 0x04) pSiS->VGADecodingEnabled = FALSE; 3672 break; 3673 } 3674 3675 if(!pSiS->VGADecodingEnabled) { 3676 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3677 "Standard VGA (0xA0000) memory address decoding is disabled\n"); 3678 } 3679 3680#ifdef SIS_PC_PLATFORM 3681 /* Map 64k VGA window for saving/restoring CGA fonts. 3682 * For secondary cards or if A0000 address decoding 3683 * is disabled, this will map the beginning of the 3684 * linear (PCI) video RAM instead. 3685 */ 3686 SiS_MapVGAMem(pScrn); 3687#endif 3688 3689 /* Set operating state */ 3690 3691 /* 1. memory */ 3692 /* [ResUnusedOpr: Resource decoded by hw, but not used] 3693 * [ResDisableOpr: Resource is not decoded by hw] 3694 * So, if a0000 memory decoding is disabled, one could 3695 * argue that we may say so, too. Hm. Quite likely that 3696 * the VBE (via int10) will eventually enable it. So we 3697 * cowardly say unused instead. 3698 */ 3699 xf86SetOperatingState(resVgaMem, pSiS->pEnt->index, ResUnusedOpr); 3700 3701 /* 2. i/o */ 3702 /* Although we only use the relocated i/o ports, the hardware 3703 * also decodes the standard VGA port range. This could in 3704 * theory be disabled, but I don't dare to do this; in case of 3705 * a server crash, the card would be entirely dead. Also, this 3706 * would prevent int10 and the VBE from working at all. Generic 3707 * access control through the PCI configuration registers does 3708 * nicely anyway. 3709 */ 3710 xf86SetOperatingState(resVgaIo, pSiS->pEnt->index, ResUnusedOpr); 3711 3712 /* Operations for which memory access is required */ 3713 pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; 3714 3715 /* Operations for which I/O access is required */ 3716 pScrn->racIoFlags = RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; 3717 3718 /* Load ramdac module */ 3719 if(!xf86LoadSubModule(pScrn, "ramdac")) { 3720 SISErrorLog(pScrn, "Could not load ramdac module\n"); 3721 goto my_error_1; 3722 } 3723 3724 xf86LoaderReqSymLists(ramdacSymbols, NULL); 3725 3726 /* Set pScrn->monitor */ 3727 pScrn->monitor = pScrn->confScreen->monitor; 3728 3729 /* Reset some entries */ 3730 pSiS->SiSFastVidCopy = SiSVidCopyGetDefault(); 3731 pSiS->SiSFastMemCopy = SiSVidCopyGetDefault(); 3732 pSiS->SiSFastVidCopyFrom = SiSVidCopyGetDefault(); 3733 pSiS->SiSFastMemCopyFrom = SiSVidCopyGetDefault(); 3734 pSiS->SiSFastVidCopyDone = FALSE; 3735#ifdef SIS_USE_XAA 3736 pSiS->RenderCallback = NULL; 3737#endif 3738#ifdef SIS_USE_EXA 3739 pSiS->ExaRenderCallback = NULL; 3740#endif 3741 pSiS->InitAccel = SiSPseudo; 3742 pSiS->SyncAccel = SiSPseudo; 3743 pSiS->FillRect = NULL; 3744 pSiS->BlitRect = NULL; 3745 3746 /* Always do a ValidMode() inside Switchmode() */ 3747 pSiS->skipswitchcheck = FALSE; 3748 3749 /* Determine chipset and its capabilities in detail */ 3750 pSiS->ChipFlags = 0; 3751 pSiS->SiS_SD_Flags = pSiS->SiS_SD2_Flags = 0; 3752 pSiS->SiS_SD3_Flags = pSiS->SiS_SD4_Flags = 0; 3753 pSiS->HWCursorMBufNum = pSiS->HWCursorCBufNum = 0; 3754 pSiS->NeedFlush = FALSE; 3755 pSiS->NewCRLayout = FALSE; 3756 pSiS->mmioSize = 64; 3757 3758 switch(pSiS->Chipset) { 3759 case PCI_CHIP_SIS530: 3760 pSiS->ChipType = SIS_530; 3761 break; 3762 case PCI_CHIP_SIS300: 3763 pSiS->ChipType = SIS_300; 3764 pSiS->SiS_SD_Flags |= SiS_SD_IS300SERIES; 3765 break; 3766 case PCI_CHIP_SIS540: 3767 pSiS->ChipType = SIS_540; 3768 pSiS->SiS_SD_Flags |= SiS_SD_IS300SERIES; 3769 break; 3770 case PCI_CHIP_SIS630: /* 630 + 730 */ 3771 pSiS->ChipType = SIS_630; 3772 if(pciReadLong(0x00000000, 0x00) == 0x07301039) { 3773 pSiS->ChipType = SIS_730; 3774 } 3775 pSiS->SiS_SD_Flags |= SiS_SD_IS300SERIES; 3776 break; 3777 case PCI_CHIP_SIS315H: 3778 pSiS->ChipType = SIS_315H; 3779 pSiS->ChipFlags |= (SiSCF_315Core | SiSCF_MMIOPalette); 3780 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3781 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3782 pSiS->myCR63 = 0x63; 3783 break; 3784 case PCI_CHIP_SIS315: 3785 /* Override for simplicity */ 3786 pSiS->Chipset = PCI_CHIP_SIS315H; 3787 pSiS->ChipType = SIS_315; 3788 pSiS->ChipFlags |= (SiSCF_315Core | SiSCF_MMIOPalette); 3789 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3790 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3791 pSiS->myCR63 = 0x63; 3792 break; 3793 case PCI_CHIP_SIS315PRO: 3794 /* Override for simplicity */ 3795 pSiS->Chipset = PCI_CHIP_SIS315H; 3796 pSiS->ChipType = SIS_315PRO; 3797 pSiS->ChipFlags |= (SiSCF_315Core | SiSCF_MMIOPalette); 3798 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3799 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3800 pSiS->myCR63 = 0x63; 3801 break; 3802 case PCI_CHIP_SIS550: 3803 pSiS->ChipType = SIS_550; 3804 pSiS->ChipFlags |= (SiSCF_Integrated | SiSCF_MMIOPalette); 3805 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3806 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3807 pSiS->myCR63 = 0x63; 3808 break; 3809 case PCI_CHIP_SIS650: /* 650 + 740 */ 3810 pSiS->ChipType = SIS_650; 3811 if(pciReadLong(0x00000000, 0x00) == 0x07401039) { 3812 pSiS->ChipType = SIS_740; 3813 } 3814 pSiS->ChipFlags |= (SiSCF_Integrated | SiSCF_Real256ECore | SiSCF_MMIOPalette); 3815 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3816 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3817 pSiS->myCR63 = 0x63; 3818 break; 3819 case PCI_CHIP_SIS330: 3820 pSiS->ChipType = SIS_330; 3821 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette); 3822 pSiS->SiS_SD_Flags |= SiS_SD_IS330SERIES; 3823 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3824 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; /* FIXME ? */ 3825 pSiS->myCR63 = 0x53; /* sic! */ 3826 break; 3827 case PCI_CHIP_SIS660: /* 660, 661, 741, 760, 761, 670(?) */ 3828 { 3829 ULong hpciid = pciReadLong(0x00000000, 0x00); 3830 switch(hpciid) { 3831 case 0x06601039: 3832 pSiS->ChipType = SIS_660; 3833 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3834 pSiS->NeedFlush = TRUE; 3835 break; 3836 case 0x07601039: 3837 pSiS->ChipType = SIS_760; 3838 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3839 pSiS->NeedFlush = TRUE; 3840 break; 3841 case 0x07611039: 3842 pSiS->ChipType = SIS_761; 3843 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3844 pSiS->NeedFlush = TRUE; 3845 break; 3846 case 0x07701039: 3847 pSiS->ChipType = SIS_770; 3848 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3849 pSiS->NeedFlush = TRUE; 3850 break; 3851 case 0x07411039: 3852 pSiS->ChipType = SIS_741; 3853 pSiS->ChipFlags |= SiSCF_Real256ECore; 3854 break; 3855 case 0x06611039: 3856 default: 3857 pSiS->ChipType = SIS_661; 3858 pSiS->ChipFlags |= SiSCF_Real256ECore; 3859 break; 3860 case 0x06701039: 3861 pSiS->ChipType = SIS_670; 3862 pSiS->ChipFlags |= SiSCF_Real256ECore; 3863 } 3864 /* Detection could also be done by CR5C & 0xf8: 3865 * 0x10 = 661 (CR5F & 0xc0: 0x00 both A0 and A1) 3866 * 0x80 = 760 (CR5F & 0xc0: 0x00 A0, 0x40 A1) 3867 * 0x90 = 741 (CR5F & 0xc0: 0x00 A0,A1 0x40 A2) 3868 * other: 660 (CR5F & 0xc0: 0x00 A0 0x40 A1) (DOA?) 3869 */ 3870 pSiS->ChipFlags |= (SiSCF_Integrated | SiSCF_MMIOPalette); 3871 pSiS->SiS_SD_Flags |= SiS_SD_IS330SERIES; 3872 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3873 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; 3874 pSiS->myCR63 = 0x53; /* sic! */ 3875 pSiS->NewCRLayout = TRUE; 3876 } 3877 break; 3878 case PCI_CHIP_SIS340: 3879 pSiS->ChipType = SIS_340; 3880 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette); 3881 pSiS->SiS_SD_Flags |= SiS_SD_IS340SERIES; 3882 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3883 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; 3884 pSiS->myCR63 = 0x53; 3885 pSiS->NewCRLayout = TRUE; 3886 break; 3887 case PCI_CHIP_XGIXG20: 3888 pSiS->ChipType = XGI_20; 3889 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette | SiSCF_IsXGI); 3890 pSiS->SiS_SD2_Flags |= (SiS_SD2_NOOVERLAY | SiS_SD2_ISXGI); 3891 pSiS->myCR63 = 0x53; 3892 pSiS->NewCRLayout = TRUE; 3893 break; 3894 case PCI_CHIP_XGIXG40: 3895 pSiS->ChipType = XGI_40; 3896 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette | SiSCF_IsXGI); 3897 pSiS->SiS_SD2_Flags |= (SiS_SD2_SUPPORTXVHUESAT | SiS_SD2_ISXGI); 3898 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; 3899 pSiS->myCR63 = 0x53; 3900 pSiS->NewCRLayout = TRUE; 3901 if(pSiS->ChipRev == 2) pSiS->ChipFlags |= SiSCF_IsXGIV3; 3902 break; 3903 default: 3904 pSiS->ChipType = SIS_OLD; 3905 break; 3906 } 3907 3908 /* 3909 * Now back to real business: Figure out the depth, bpp, etc. 3910 * Set SupportConvert... flags since we use the fb layer which 3911 * supports this conversion. (24to32 seems not implemented though) 3912 * Additionally, determine the size of the HWCursor memory area. 3913 */ 3914 switch(pSiS->VGAEngine) { 3915 case SIS_300_VGA: 3916 pSiS->CursorSize = 4096; 3917 pix24flags = Support32bppFb; 3918 break; 3919 case SIS_315_VGA: 3920 pSiS->CursorSize = 16384; 3921 pix24flags = Support32bppFb; 3922 break; 3923 case SIS_530_VGA: 3924 pSiS->CursorSize = 2048; 3925 pix24flags = Support32bppFb | 3926 Support24bppFb | 3927 SupportConvert32to24; 3928 break; 3929 default: 3930 pSiS->CursorSize = 2048; 3931 pix24flags = Support24bppFb | 3932 SupportConvert32to24 | 3933 PreferConvert32to24; 3934 break; 3935 } 3936 3937#ifdef SISDUALHEAD 3938 /* In case of Dual Head, we need to determine if we are the "master" head or 3939 * the "slave" head. In order to do that, we set PrimInit to DONE in the 3940 * shared entity at the end of the first initialization. The second 3941 * initialization then knows that some things have already been done. THIS 3942 * ALWAYS ASSUMES THAT THE FIRST DEVICE INITIALIZED IS THE MASTER! 3943 */ 3944 if(xf86IsEntityShared(pScrn->entityList[0])) { 3945 if(pSiSEnt->lastInstance > 0) { 3946 if(!xf86IsPrimInitDone(pScrn->entityList[0])) { 3947 /* First Head (always CRT2) */ 3948 pSiS->SecondHead = FALSE; 3949 pSiSEnt->pScrn_1 = pScrn; 3950 pSiSEnt->CRT1ModeNo = pSiSEnt->CRT2ModeNo = -1; 3951 pSiSEnt->CRT2ModeSet = FALSE; 3952 pSiS->DualHeadMode = TRUE; 3953 pSiSEnt->DisableDual = FALSE; 3954 pSiSEnt->BIOS = NULL; 3955 pSiSEnt->ROM661New = FALSE; 3956 pSiSEnt->HaveXGIBIOS = FALSE; 3957 pSiSEnt->SiS_Pr = NULL; 3958 pSiSEnt->RenderAccelArray = NULL; 3959 pSiSEnt->SiSFastVidCopy = pSiSEnt->SiSFastMemCopy = NULL; 3960 pSiSEnt->SiSFastVidCopyFrom = pSiSEnt->SiSFastMemCopyFrom = NULL; 3961 } else { 3962 /* Second Head (always CRT1) */ 3963 pSiS->SecondHead = TRUE; 3964 pSiSEnt->pScrn_2 = pScrn; 3965 pSiS->DualHeadMode = TRUE; 3966 } 3967 } else { 3968 /* Only one screen in config file - disable dual head mode */ 3969 pSiS->SecondHead = FALSE; 3970 pSiS->DualHeadMode = FALSE; 3971 pSiSEnt->DisableDual = TRUE; 3972 } 3973 } else { 3974 /* Entity is not shared - disable dual head mode */ 3975 pSiS->SecondHead = FALSE; 3976 pSiS->DualHeadMode = FALSE; 3977 } 3978#endif 3979 3980 /* Save the name of our Device section for SiSCtrl usage */ 3981 { 3982 int ttt = 0; 3983 GDevPtr device = xf86GetDevFromEntity(pScrn->entityList[0], 3984 pScrn->entityInstanceList[0]); 3985 if(device && device->identifier) { 3986 if((ttt = strlen(device->identifier)) > 31) ttt = 31; 3987 strncpy(&pSiS->devsectname[0], device->identifier, 31); 3988 } 3989 pSiS->devsectname[ttt] = 0; 3990 } 3991 3992 pSiS->ForceCursorOff = FALSE; 3993 3994 /* Allocate SiS_Private (for mode switching code) and initialize it */ 3995 pSiS->SiS_Pr = NULL; 3996#ifdef SISDUALHEAD 3997 if(pSiSEnt) { 3998 if(pSiSEnt->SiS_Pr) pSiS->SiS_Pr = pSiSEnt->SiS_Pr; 3999 } 4000#endif 4001 if(!pSiS->SiS_Pr) { 4002 if(!(pSiS->SiS_Pr = xnfcalloc(sizeof(struct SiS_Private), 1))) { 4003 SISErrorLog(pScrn, "Could not allocate memory for SiS_Pr structure\n"); 4004 goto my_error_1; 4005 } 4006#ifdef SISDUALHEAD 4007 if(pSiSEnt) pSiSEnt->SiS_Pr = pSiS->SiS_Pr; 4008#endif 4009 memset(pSiS->SiS_Pr, 0, sizeof(struct SiS_Private)); 4010 pSiS->SiS_Pr->PciTag = pSiS->PciTag; 4011 pSiS->SiS_Pr->ChipType = pSiS->ChipType; 4012 pSiS->SiS_Pr->ChipRevision = pSiS->ChipRev; 4013 pSiS->SiS_Pr->SiS_Backup70xx = 0xff; 4014 pSiS->SiS_Pr->SiS_CHOverScan = -1; 4015 pSiS->SiS_Pr->SiS_ChSW = FALSE; 4016 pSiS->SiS_Pr->SiS_CustomT = CUT_NONE; 4017 pSiS->SiS_Pr->SiS_UseWide = -1; 4018 pSiS->SiS_Pr->SiS_UseWideCRT2 = -1; 4019 pSiS->SiS_Pr->SiS_TVBlue = -1; 4020 pSiS->SiS_Pr->PanelSelfDetected = FALSE; 4021 pSiS->SiS_Pr->UsePanelScaler = -1; 4022 pSiS->SiS_Pr->CenterScreen = -1; 4023 pSiS->SiS_Pr->CRT1UsesCustomMode = FALSE; 4024 pSiS->SiS_Pr->PDC = pSiS->SiS_Pr->PDCA = -1; 4025 pSiS->SiS_Pr->LVDSHL = -1; 4026 pSiS->SiS_Pr->HaveEMI = FALSE; 4027 pSiS->SiS_Pr->HaveEMILCD = FALSE; 4028 pSiS->SiS_Pr->OverruleEMI = FALSE; 4029 pSiS->SiS_Pr->SiS_SensibleSR11 = FALSE; 4030 if(pSiS->ChipType >= SIS_661) { 4031 pSiS->SiS_Pr->SiS_SensibleSR11 = TRUE; 4032 } 4033 pSiS->SiS_Pr->SiS_MyCR63 = pSiS->myCR63; 4034 pSiS->SiS_Pr->DDCPortMixup = FALSE; 4035 } 4036 4037 /* Copy IO address to SiS_Pr and init the structure for 4038 * routines inside init.c/init301.c 4039 */ 4040 pSiS->SiS_Pr->IOAddress = (SISIOADDRESS)(pSiS->RelIO + 0x30); 4041 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO + 0x30); 4042 4043 /* The following identifies the old chipsets. This is only 4044 * partly used since the really old chips are not supported, 4045 * but I keep it here for future use. 4046 * 205, 215 and 225 are to be treated the same way, 201 and 202 4047 * are different. 4048 */ 4049 if(pSiS->VGAEngine == SIS_OLD_VGA || pSiS->VGAEngine == SIS_530_VGA) { 4050 switch(pSiS->Chipset) { 4051 case PCI_CHIP_SG86C201: 4052 pSiS->oldChipset = OC_SIS86201; break; 4053 case PCI_CHIP_SG86C202: 4054 pSiS->oldChipset = OC_SIS86202; break; 4055 case PCI_CHIP_SG86C205: 4056 inSISIDXREG(SISSR, 0x10, tempreg); 4057 if(tempreg & 0x80) pSiS->oldChipset = OC_SIS6205B; 4058 else pSiS->oldChipset = (pSiS->ChipRev == 0x11) ? 4059 OC_SIS6205C : OC_SIS6205A; 4060 break; 4061 case PCI_CHIP_SIS82C204: 4062 pSiS->oldChipset = OC_SIS82204; break; 4063 case 0x6225: 4064 pSiS->oldChipset = OC_SIS6225; break; 4065 case PCI_CHIP_SIS5597: 4066 pSiS->oldChipset = OC_SIS5597; break; 4067 case PCI_CHIP_SIS6326: 4068 pSiS->oldChipset = OC_SIS6326; break; 4069 case PCI_CHIP_SIS530: 4070 if(pciReadLong(0x00000000, 0x00) == 0x06201039) { 4071 pSiS->oldChipset = OC_SIS620; 4072 } else { 4073 if((pSiS->ChipRev & 0x0f) < 0x0a) 4074 pSiS->oldChipset = OC_SIS530A; 4075 else pSiS->oldChipset = OC_SIS530B; 4076 } 4077 break; 4078 default: 4079 pSiS->oldChipset = OC_UNKNOWN; 4080 } 4081 } 4082 4083 if(!xf86SetDepthBpp(pScrn, 0, 0, 0, pix24flags)) { 4084 SISErrorLog(pScrn, "xf86SetDepthBpp() error\n"); 4085 goto my_error_1; 4086 } 4087 4088 /* Check that the returned depth is one we support */ 4089 temp = 0; 4090 switch(pScrn->depth) { 4091 case 8: 4092 case 16: 4093 case 24: 4094 break; 4095 case 15: 4096 if((pSiS->VGAEngine == SIS_300_VGA) || 4097 (pSiS->VGAEngine == SIS_315_VGA)) { 4098 temp = 1; 4099 } 4100 break; 4101 default: 4102 temp = 1; 4103 } 4104 4105 if(temp) { 4106 SISErrorLog(pScrn, 4107 "Given color depth (%d) is not supported by this driver/chipset\n", 4108 pScrn->depth); 4109 goto my_error_1; 4110 } 4111 4112 xf86PrintDepthBpp(pScrn); 4113 4114 if( (((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) && 4115 (pScrn->bitsPerPixel == 24)) || 4116 ((pSiS->VGAEngine == SIS_OLD_VGA) && (pScrn->bitsPerPixel == 32)) ) { 4117 SISErrorLog(pScrn, 4118 "Framebuffer bpp %d not supported for this chipset\n", pScrn->bitsPerPixel); 4119 goto my_error_1; 4120 } 4121 4122 /* Get the depth24 pixmap format */ 4123 if(pScrn->depth == 24 && pix24bpp == 0) { 4124 pix24bpp = xf86GetBppFromDepth(pScrn, 24); 4125 } 4126 4127 /* 4128 * This must happen after pScrn->display has been set because 4129 * xf86SetWeight references it. 4130 */ 4131 if(pScrn->depth > 8) { 4132 /* The defaults are OK for us */ 4133 rgb zeros = {0, 0, 0}; 4134 4135 if(!xf86SetWeight(pScrn, zeros, zeros)) { 4136 SISErrorLog(pScrn, "xf86SetWeight() error\n"); 4137 goto my_error_1; 4138 } else { 4139 Bool ret = FALSE; 4140 switch(pScrn->depth) { 4141 case 15: 4142 if((pScrn->weight.red != 5) || 4143 (pScrn->weight.green != 5) || 4144 (pScrn->weight.blue != 5)) ret = TRUE; 4145 break; 4146 case 16: 4147 if((pScrn->weight.red != 5) || 4148 (pScrn->weight.green != 6) || 4149 (pScrn->weight.blue != 5)) ret = TRUE; 4150 break; 4151 case 24: 4152 if((pScrn->weight.red != 8) || 4153 (pScrn->weight.green != 8) || 4154 (pScrn->weight.blue != 8)) ret = TRUE; 4155 break; 4156 } 4157 if(ret) { 4158 SISErrorLog(pScrn, 4159 "RGB weight %d%d%d at depth %d not supported by hardware\n", 4160 (int)pScrn->weight.red, (int)pScrn->weight.green, 4161 (int)pScrn->weight.blue, pScrn->depth); 4162 goto my_error_1; 4163 } 4164 } 4165 } 4166 4167 /* Set the current layout parameters */ 4168 pSiS->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel; 4169 pSiS->CurrentLayout.depth = pScrn->depth; 4170 /* (Inside this function, we can use pScrn's contents anyway) */ 4171 4172 if(!xf86SetDefaultVisual(pScrn, -1)) { 4173 SISErrorLog(pScrn, "xf86SetDefaultVisual() error\n"); 4174 goto my_error_1; 4175 } else { 4176 /* We don't support DirectColor at > 8bpp */ 4177 if(pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { 4178 SISErrorLog(pScrn, 4179 "Given default visual (%s) is not supported at depth %d\n", 4180 xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); 4181 goto my_error_1; 4182 } 4183 } 4184 4185#ifdef SISDUALHEAD 4186 /* Due to palette & timing problems we don't support 8bpp in DHM */ 4187 if((pSiS->DualHeadMode) && (pScrn->bitsPerPixel <= 8)) { 4188 SISErrorLog(pScrn, "Color depth %d not supported in Dual Head mode.\n", 4189 pScrn->bitsPerPixel); 4190 goto my_error_1; 4191 } 4192#endif 4193 4194 /* Read BIOS for 300/315/330/340 series customization */ 4195 pSiS->SiS_Pr->VirtualRomBase = NULL; 4196 pSiS->BIOS = NULL; 4197 pSiS->SiS_Pr->UseROM = FALSE; 4198 pSiS->ROM661New = FALSE; 4199 pSiS->HaveXGIBIOS = FALSE; 4200 4201 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 4202#ifdef SISDUALHEAD 4203 if(pSiSEnt) { 4204 if(pSiSEnt->BIOS) { 4205 pSiS->BIOS = pSiSEnt->BIOS; 4206 pSiS->SiS_Pr->VirtualRomBase = pSiS->BIOS; 4207 pSiS->ROM661New = pSiSEnt->ROM661New; 4208 pSiS->HaveXGIBIOS = pSiSEnt->HaveXGIBIOS; 4209 } 4210 } 4211#endif 4212 if(!pSiS->BIOS) { 4213 if(!(pSiS->BIOS = xcalloc(1, BIOS_SIZE))) { 4214 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4215 "Could not allocate memory for video BIOS image\n"); 4216 } else { 4217 ULong segstart; 4218 UShort mypciid = pSiS->Chipset; 4219 UShort mypcivendor = (pSiS->ChipFlags & SiSCF_IsXGI) ? PCI_VENDOR_XGI : PCI_VENDOR_SIS; 4220 Bool found = FALSE, readpci = FALSE; 4221 int biossize = BIOS_SIZE; 4222 4223 switch(pSiS->ChipType) { 4224 case SIS_315: mypciid = PCI_CHIP_SIS315; 4225 readpci = TRUE; 4226 break; 4227 case SIS_315PRO: mypciid = PCI_CHIP_SIS315PRO; 4228 readpci = TRUE; 4229 break; 4230 case SIS_300: 4231 case SIS_315H: 4232 case SIS_330: 4233 case SIS_340: 4234 case XGI_40: readpci = TRUE; 4235 break; 4236 case XGI_20: readpci = TRUE; 4237 biossize = 0x8000; 4238 break; 4239 } 4240 4241 if(readpci) { 4242 xf86ReadPciBIOS(0, pSiS->PciTag, 0, pSiS->BIOS, biossize); 4243 if(SISCheckBIOS(pSiS, mypciid, mypcivendor, biossize)) { 4244 found = TRUE; 4245 } 4246 } 4247 4248 if(!found) { 4249 for(segstart = BIOS_BASE; segstart < 0x000f0000; segstart += 0x00001000) { 4250 4251#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 4252 if(xf86ReadBIOS(segstart, 0, pSiS->BIOS, biossize) != biossize) continue; 4253#else 4254 if(xf86ReadDomainMemory(pSiS->PciTag, segstart, biossize, pSiS->BIOS) != biossize) continue; 4255#endif 4256 4257 if(!SISCheckBIOS(pSiS, mypciid, mypcivendor, biossize)) continue; 4258 4259 found = TRUE; 4260 break; 4261 } 4262 } 4263 4264 if(found) { 4265 UShort romptr = pSiS->BIOS[0x16] | (pSiS->BIOS[0x17] << 8); 4266 pSiS->SiS_Pr->VirtualRomBase = pSiS->BIOS; 4267 if(pSiS->ChipFlags & SiSCF_IsXGI) { 4268 pSiS->HaveXGIBIOS = pSiS->SiS_Pr->SiS_XGIROM = TRUE; 4269 pSiS->SiS_Pr->UseROM = FALSE; 4270 if(pSiS->ChipFlags & SiSCF_IsXGIV3) { 4271 if(!(pSiS->BIOS[0x1d1] & 0x01)) { 4272 pSiS->SiS_Pr->DDCPortMixup = TRUE; 4273 } 4274 } 4275 } else { 4276 pSiS->ROM661New = SiSDetermineROMLayout661(pSiS->SiS_Pr); 4277 } 4278 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4279 "Video BIOS version \"%7s\" found (%s data layout)\n", 4280 &pSiS->BIOS[romptr], pSiS->ROM661New ? "new SiS" : 4281 (pSiS->HaveXGIBIOS ? "XGI" : "old SiS")); 4282 if(pSiS->SiS_Pr->DDCPortMixup) { 4283 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4284 "*** Buggy XGI V3XT card detected: If VGA and DVI are connected at the\n"); 4285 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4286 "*** same time, BIOS and driver will be unable to detect DVI connection.\n"); 4287 } 4288#ifdef SISDUALHEAD 4289 if(pSiSEnt) { 4290 pSiSEnt->BIOS = pSiS->BIOS; 4291 pSiSEnt->ROM661New = pSiS->ROM661New; 4292 pSiSEnt->HaveXGIBIOS = pSiS->HaveXGIBIOS; 4293 } 4294#endif 4295 } else { 4296 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4297 "Could not find/read video BIOS\n"); 4298 xfree(pSiS->BIOS); 4299 pSiS->BIOS = NULL; 4300 } 4301 } 4302 } 4303 4304 if(!(pSiS->ChipFlags & SiSCF_IsXGI)) { 4305 if(pSiS->BIOS) pSiS->SiS_Pr->UseROM = TRUE; 4306 else pSiS->SiS_Pr->UseROM = FALSE; 4307 } 4308 } 4309 4310 /* Evaluate options */ 4311 SiSOptions(pScrn); 4312 4313#ifdef SISMERGED 4314 /* Due to palette & timing problems we don't support 8bpp in MFBM */ 4315 if((pSiS->MergedFB) && (pScrn->bitsPerPixel <= 8)) { 4316 SISErrorLog(pScrn, "MergedFB: Color depth %d not supported, %s\n", 4317 pScrn->bitsPerPixel, mergeddisstr); 4318 pSiS->MergedFB = pSiS->MergedFBAuto = FALSE; 4319 } 4320#endif 4321 4322 /* Probe CPU features */ 4323#ifdef SISDUALHEAD 4324 if(pSiS->DualHeadMode) { 4325 pSiS->CPUFlags = pSiSEnt->CPUFlags; 4326 } 4327#endif 4328 if(!pSiS->CPUFlags) { 4329 pSiS->CPUFlags = SiSGetCPUFlags(pScrn); 4330 pSiS->CPUFlags |= SIS_CPUFL_FLAG; 4331#ifdef SISDUALHEAD 4332 if(pSiS->DualHeadMode) pSiSEnt->CPUFlags = pSiS->CPUFlags; 4333#endif 4334 } 4335 4336 /* We use a programamble clock */ 4337 pScrn->progClock = TRUE; 4338 4339 /* Set the bits per RGB for 8bpp mode */ 4340 if(pScrn->depth == 8) pScrn->rgbBits = 8; 4341 4342#ifdef SISDUALHEAD 4343 if(pSiS->DualHeadMode) { 4344 if(!pSiS->SecondHead) { 4345 /* Copy some option settings to entity private */ 4346 pSiSEnt->HWCursor = pSiS->HWCursor; 4347 pSiSEnt->NoAccel = pSiS->NoAccel; 4348 pSiSEnt->useEXA = pSiS->useEXA; 4349 pSiSEnt->restorebyset = pSiS->restorebyset; 4350 pSiSEnt->OptROMUsage = pSiS->OptROMUsage; 4351 pSiSEnt->OptUseOEM = pSiS->OptUseOEM; 4352 pSiSEnt->TurboQueue = pSiS->TurboQueue; 4353 pSiSEnt->forceCRT1 = pSiS->forceCRT1; 4354 pSiSEnt->ForceCRT1Type = pSiS->ForceCRT1Type; 4355 pSiSEnt->CRT1TypeForced = pSiS->CRT1TypeForced; 4356 pSiSEnt->ForceCRT2Type = pSiS->ForceCRT2Type; 4357 pSiSEnt->ForceTVType = pSiS->ForceTVType; 4358 pSiSEnt->ForceYPbPrType = pSiS->ForceYPbPrType; 4359 pSiSEnt->ForceYPbPrAR = pSiS->ForceYPbPrAR; 4360 pSiSEnt->UsePanelScaler = pSiS->UsePanelScaler; 4361 pSiSEnt->CenterLCD = pSiS->CenterLCD; 4362 pSiSEnt->DSTN = pSiS->DSTN; 4363 pSiSEnt->FSTN = pSiS->FSTN; 4364 pSiSEnt->OptTVStand = pSiS->OptTVStand; 4365 pSiSEnt->NonDefaultPAL = pSiS->NonDefaultPAL; 4366 pSiSEnt->NonDefaultNTSC = pSiS->NonDefaultNTSC; 4367 pSiSEnt->chtvtype = pSiS->chtvtype; 4368 pSiSEnt->OptTVOver = pSiS->OptTVOver; 4369 pSiSEnt->OptTVSOver = pSiS->OptTVSOver; 4370 pSiSEnt->chtvlumabandwidthcvbs = pSiS->chtvlumabandwidthcvbs; 4371 pSiSEnt->chtvlumabandwidthsvideo = pSiS->chtvlumabandwidthsvideo; 4372 pSiSEnt->chtvlumaflickerfilter = pSiS->chtvlumaflickerfilter; 4373 pSiSEnt->chtvchromabandwidth = pSiS->chtvchromabandwidth; 4374 pSiSEnt->chtvchromaflickerfilter = pSiS->chtvchromaflickerfilter; 4375 pSiSEnt->chtvtextenhance = pSiS->chtvtextenhance; 4376 pSiSEnt->chtvcontrast = pSiS->chtvcontrast; 4377 pSiSEnt->chtvcvbscolor = pSiS->chtvcvbscolor; 4378 pSiSEnt->sistvedgeenhance = pSiS->sistvedgeenhance; 4379 pSiSEnt->sistvantiflicker = pSiS->sistvantiflicker; 4380 pSiSEnt->sistvsaturation = pSiS->sistvsaturation; 4381 pSiSEnt->sistvcfilter = pSiS->sistvcfilter; 4382 pSiSEnt->sistvyfilter = pSiS->sistvyfilter; 4383 pSiSEnt->sistvcolcalibc = pSiS->sistvcolcalibc; 4384 pSiSEnt->sistvcolcalibf = pSiS->sistvcolcalibf; 4385 pSiSEnt->tvxpos = pSiS->tvxpos; 4386 pSiSEnt->tvypos = pSiS->tvypos; 4387 pSiSEnt->tvxscale = pSiS->tvxscale; 4388 pSiSEnt->tvyscale = pSiS->tvyscale; 4389 pSiSEnt->siscrt1satgain = pSiS->siscrt1satgain; 4390 pSiSEnt->crt1satgaingiven = pSiS->crt1satgaingiven; 4391 pSiSEnt->CRT1gamma = pSiS->CRT1gamma; 4392 pSiSEnt->CRT1gammaGiven = pSiS->CRT1gammaGiven; 4393 pSiSEnt->XvGammaRed = pSiS->XvGammaRed; 4394 pSiSEnt->XvGammaGreen = pSiS->XvGammaGreen; 4395 pSiSEnt->XvGammaBlue = pSiS->XvGammaBlue; 4396 pSiSEnt->XvGamma = pSiS->XvGamma; 4397 pSiSEnt->XvGammaGiven = pSiS->XvGammaGiven; 4398 pSiSEnt->CRT2gamma = pSiS->CRT2gamma; 4399 pSiSEnt->XvOnCRT2 = pSiS->XvOnCRT2; 4400 pSiSEnt->AllowHotkey = pSiS->AllowHotkey; 4401 pSiSEnt->enablesisctrl = pSiS->enablesisctrl; 4402 pSiSEnt->SenseYPbPr = pSiS->SenseYPbPr; 4403 pSiSEnt->XvUseMemcpy = pSiS->XvUseMemcpy; 4404 pSiSEnt->BenchMemCpy = pSiS->BenchMemCpy; 4405#ifdef SIS_CP 4406 SIS_CP_DRIVER_COPYOPTIONSENT 4407#endif 4408 } else { 4409 /* We always use same cursor type on both screens */ 4410 pSiS->HWCursor = pSiSEnt->HWCursor; 4411 /* We need identical NoAccel setting */ 4412 pSiS->NoAccel = pSiSEnt->NoAccel; 4413 pSiS->useEXA = pSiSEnt->useEXA; 4414 pSiS->TurboQueue = pSiSEnt->TurboQueue; 4415 pSiS->restorebyset = pSiSEnt->restorebyset; 4416 pSiS->AllowHotkey = pSiS->AllowHotkey; 4417 pSiS->OptROMUsage = pSiSEnt->OptROMUsage; 4418 pSiS->OptUseOEM = pSiSEnt->OptUseOEM; 4419 pSiS->forceCRT1 = pSiSEnt->forceCRT1; 4420 pSiS->nocrt2ddcdetection = FALSE; 4421 pSiS->forcecrt2redetection = FALSE; 4422 pSiS->ForceCRT1Type = pSiSEnt->ForceCRT1Type; 4423 pSiS->ForceCRT2Type = pSiSEnt->ForceCRT2Type; 4424 pSiS->CRT1TypeForced = pSiSEnt->CRT1TypeForced; 4425 pSiS->UsePanelScaler = pSiSEnt->UsePanelScaler; 4426 pSiS->CenterLCD = pSiSEnt->CenterLCD; 4427 pSiS->DSTN = pSiSEnt->DSTN; 4428 pSiS->FSTN = pSiSEnt->FSTN; 4429 pSiS->OptTVStand = pSiSEnt->OptTVStand; 4430 pSiS->NonDefaultPAL = pSiSEnt->NonDefaultPAL; 4431 pSiS->NonDefaultNTSC = pSiSEnt->NonDefaultNTSC; 4432 pSiS->chtvtype = pSiSEnt->chtvtype; 4433 pSiS->ForceTVType = pSiSEnt->ForceTVType; 4434 pSiS->ForceYPbPrType = pSiSEnt->ForceYPbPrType; 4435 pSiS->ForceYPbPrAR = pSiSEnt->ForceYPbPrAR; 4436 pSiS->OptTVOver = pSiSEnt->OptTVOver; 4437 pSiS->OptTVSOver = pSiSEnt->OptTVSOver; 4438 pSiS->chtvlumabandwidthcvbs = pSiSEnt->chtvlumabandwidthcvbs; 4439 pSiS->chtvlumabandwidthsvideo = pSiSEnt->chtvlumabandwidthsvideo; 4440 pSiS->chtvlumaflickerfilter = pSiSEnt->chtvlumaflickerfilter; 4441 pSiS->chtvchromabandwidth = pSiSEnt->chtvchromabandwidth; 4442 pSiS->chtvchromaflickerfilter = pSiSEnt->chtvchromaflickerfilter; 4443 pSiS->chtvcvbscolor = pSiSEnt->chtvcvbscolor; 4444 pSiS->chtvtextenhance = pSiSEnt->chtvtextenhance; 4445 pSiS->chtvcontrast = pSiSEnt->chtvcontrast; 4446 pSiS->sistvedgeenhance = pSiSEnt->sistvedgeenhance; 4447 pSiS->sistvantiflicker = pSiSEnt->sistvantiflicker; 4448 pSiS->sistvsaturation = pSiSEnt->sistvsaturation; 4449 pSiS->sistvcfilter = pSiSEnt->sistvcfilter; 4450 pSiS->sistvyfilter = pSiSEnt->sistvyfilter; 4451 pSiS->sistvcolcalibc = pSiSEnt->sistvcolcalibc; 4452 pSiS->sistvcolcalibf = pSiSEnt->sistvcolcalibf; 4453 pSiS->tvxpos = pSiSEnt->tvxpos; 4454 pSiS->tvypos = pSiSEnt->tvypos; 4455 pSiS->tvxscale = pSiSEnt->tvxscale; 4456 pSiS->tvyscale = pSiSEnt->tvyscale; 4457 pSiS->SenseYPbPr = pSiSEnt->SenseYPbPr; 4458 if(!pSiS->CRT1gammaGiven) { 4459 if(pSiSEnt->CRT1gammaGiven) 4460 pSiS->CRT1gamma = pSiSEnt->CRT1gamma; 4461 } 4462 pSiS->CRT2gamma = pSiSEnt->CRT2gamma; 4463 if(!pSiS->XvGammaGiven) { 4464 if(pSiSEnt->XvGammaGiven) { 4465 pSiS->XvGamma = pSiSEnt->XvGamma; 4466 pSiS->XvGammaRed = pSiS->XvGammaRedDef = pSiSEnt->XvGammaRed; 4467 pSiS->XvGammaGreen = pSiS->XvGammaGreenDef = pSiSEnt->XvGammaGreen; 4468 pSiS->XvGammaBlue = pSiS->XvGammaBlueDef = pSiSEnt->XvGammaBlue; 4469 } 4470 } 4471 if(!pSiS->crt1satgaingiven) { 4472 if(pSiSEnt->crt1satgaingiven) 4473 pSiS->siscrt1satgain = pSiSEnt->siscrt1satgain; 4474 } 4475 pSiS->XvOnCRT2 = pSiSEnt->XvOnCRT2; 4476 pSiS->enablesisctrl = pSiSEnt->enablesisctrl; 4477 pSiS->XvUseMemcpy = pSiSEnt->XvUseMemcpy; 4478 pSiS->BenchMemCpy = pSiSEnt->BenchMemCpy; 4479 /* Copy gamma brightness to Ent (sic!) for Xinerama */ 4480 pSiSEnt->GammaBriR = pSiS->GammaBriR; 4481 pSiSEnt->GammaBriG = pSiS->GammaBriG; 4482 pSiSEnt->GammaBriB = pSiS->GammaBriB; 4483 pSiSEnt->NewGammaBriR = pSiS->NewGammaBriR; 4484 pSiSEnt->NewGammaBriG = pSiS->NewGammaBriG; 4485 pSiSEnt->NewGammaBriB = pSiS->NewGammaBriB; 4486 pSiSEnt->NewGammaConR = pSiS->NewGammaConR; 4487 pSiSEnt->NewGammaConG = pSiS->NewGammaConG; 4488 pSiSEnt->NewGammaConB = pSiS->NewGammaConB; 4489#ifdef SIS_CP 4490 SIS_CP_DRIVER_COPYOPTIONS 4491#endif 4492 } 4493 } 4494#endif 4495 4496 /* Handle UseROMData, NoOEM and UsePanelScaler options */ 4497 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 4498 from = X_PROBED; 4499 if(pSiS->OptROMUsage == 0) { 4500 pSiS->SiS_Pr->UseROM = FALSE; 4501 from = X_CONFIG; 4502 xf86DrvMsg(pScrn->scrnIndex, from, "Video ROM data usage is disabled\n"); 4503 } 4504 4505 if(!pSiS->OptUseOEM) { 4506 xf86DrvMsg(pScrn->scrnIndex, from, "Internal OEM LCD/TV/VGA2 data usage is disabled\n"); 4507 } 4508 4509 pSiS->SiS_Pr->UsePanelScaler = pSiS->UsePanelScaler; 4510 pSiS->SiS_Pr->CenterScreen = pSiS->CenterLCD; 4511 } 4512 4513 /* Do some HW configuration detection (memory amount & type, clock, etc) */ 4514 SiSSetup(pScrn); 4515 4516 /* Get framebuffer address */ 4517 if(pSiS->pEnt->device->MemBase != 0) { 4518 /* 4519 * XXX Should check that the config file value matches one of the 4520 * PCI base address values. 4521 */ 4522 pSiS->FbAddress = pSiS->pEnt->device->MemBase; 4523 from = X_CONFIG; 4524 } else { 4525 pSiS->FbAddress = pSiS->PciInfo->memBase[0] & 0xFFFFFFF0; 4526 from = X_PROBED; 4527 } 4528 4529#ifdef SISDUALHEAD 4530 if(pSiS->DualHeadMode) 4531 xf86DrvMsg(pScrn->scrnIndex, from, "Global linear framebuffer at 0x%lX\n", 4532 (ULong)pSiS->FbAddress); 4533 else 4534#endif 4535 xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", 4536 (ULong)pSiS->FbAddress); 4537 4538 pSiS->realFbAddress = pSiS->FbAddress; 4539 4540 /* Get MMIO address */ 4541 if(pSiS->pEnt->device->IOBase != 0) { 4542 /* 4543 * XXX Should check that the config file value matches one of the 4544 * PCI base address values. 4545 */ 4546 pSiS->IOAddress = pSiS->pEnt->device->IOBase; 4547 from = X_CONFIG; 4548 } else { 4549 pSiS->IOAddress = pSiS->PciInfo->memBase[1] & 0xFFFFFFF0; 4550 from = X_PROBED; 4551 } 4552 xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX (size %ldK)\n", 4553 (ULong)pSiS->IOAddress, pSiS->mmioSize); 4554 4555 /* Register the PCI-assigned resources */ 4556 if(xf86RegisterResources(pSiS->pEnt->index, NULL, ResExclusive)) { 4557 SISErrorLog(pScrn, "PCI resource conflicts detected\n"); 4558#ifdef SISDUALHEAD 4559 if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; 4560#endif 4561 sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); 4562 if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); 4563 SISFreeRec(pScrn); 4564 return FALSE; 4565 } 4566 4567 from = X_PROBED; 4568 if(pSiS->pEnt->device->videoRam != 0) { 4569 if(pSiS->Chipset == PCI_CHIP_SIS6326) { 4570 pScrn->videoRam = pSiS->pEnt->device->videoRam; 4571 from = X_CONFIG; 4572 } else { 4573 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4574 "Option \"VideoRAM\" ignored\n"); 4575 } 4576 } 4577 4578 pSiS->RealVideoRam = pScrn->videoRam; 4579 4580 if((pSiS->Chipset == PCI_CHIP_SIS6326) && 4581 (pScrn->videoRam > 4096) && 4582 (from != X_CONFIG)) { 4583 pScrn->videoRam = 4096; 4584 xf86DrvMsg(pScrn->scrnIndex, from, 4585 "SiS6326: Detected %d KB VideoRAM, limiting to %d KB\n", 4586 pSiS->RealVideoRam, pScrn->videoRam); 4587 } else { 4588 xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d KB\n", pScrn->videoRam); 4589 } 4590 4591 if((pSiS->Chipset == PCI_CHIP_SIS6326) && 4592 (pScrn->videoRam > 4096)) { 4593 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4594 "SiS6326 engines do not support more than 4096KB RAM, therefore\n"); 4595 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4596 "TurboQueue, HWCursor, 2D acceleration and XVideo are disabled.\n"); 4597 pSiS->TurboQueue = FALSE; 4598 pSiS->HWCursor = FALSE; 4599 pSiS->NoXvideo = TRUE; 4600 pSiS->NoAccel = TRUE; 4601 } 4602 4603 pSiS->FbMapSize = pSiS->availMem = pScrn->videoRam * 1024; 4604 4605 /* Calculate real availMem according to Accel/TurboQueue and 4606 * HWCursur setting. Also, initialize some variables used 4607 * in other modules. 4608 */ 4609 pSiS->cursorOffset = 0; 4610 pSiS->CurARGBDest = NULL; 4611 pSiS->CurMonoSrc = NULL; 4612 pSiS->CurFGCol = pSiS->CurBGCol = 0; 4613 pSiS->FbBaseOffset = 0; 4614 4615 switch(pSiS->VGAEngine) { 4616 4617 case SIS_300_VGA: 4618 pSiS->TurboQueueLen = 512; 4619 if(pSiS->TurboQueue) { 4620 pSiS->availMem -= (pSiS->TurboQueueLen*1024); 4621 pSiS->cursorOffset = 512; 4622 } 4623 if(pSiS->HWCursor) { 4624 pSiS->availMem -= pSiS->CursorSize; 4625 if(pSiS->OptUseColorCursor) pSiS->availMem -= pSiS->CursorSize; 4626 } 4627 pSiS->CmdQueLenMask = 0xFFFF; 4628 pSiS->CmdQueLenFix = 0; 4629 pSiS->cursorBufferNum = 0; 4630#ifdef SISDUALHEAD 4631 if(pSiSEnt) pSiSEnt->cursorBufferNum = 0; 4632#endif 4633 break; 4634 4635 case SIS_315_VGA: 4636#ifdef SISVRAMQ /* VRAM queue */ 4637 pSiS->cmdQueueSizeMask = pSiS->cmdQueueSize - 1; /* VRAM Command Queue is variable (in therory) */ 4638 pSiS->cmdQueueOffset = (pScrn->videoRam * 1024) - pSiS->cmdQueueSize; 4639 pSiS->cmdQueueLen = 0; 4640 pSiS->cmdQueueSize_div2 = pSiS->cmdQueueSize / 2; 4641 pSiS->cmdQueueSize_div4 = pSiS->cmdQueueSize / 4; 4642 pSiS->cmdQueueSize_4_3 = (pSiS->cmdQueueSize / 4) * 3; 4643 pSiS->availMem -= pSiS->cmdQueueSize; 4644 pSiS->cursorOffset = (pSiS->cmdQueueSize / 1024); 4645 4646 /* Set up shared pointer to current offset */ 4647#ifdef SISDUALHEAD 4648 if(pSiS->DualHeadMode) 4649 pSiS->cmdQ_SharedWritePort = &(pSiSEnt->cmdQ_SharedWritePort_2D); 4650 else 4651#endif 4652 pSiS->cmdQ_SharedWritePort = &(pSiS->cmdQ_SharedWritePort_2D); 4653 4654 4655#else /* MMIO */ 4656 if(pSiS->TurboQueue) { 4657 pSiS->availMem -= (512*1024); /* MMIO Command Queue is 512k (variable in theory) */ 4658 pSiS->cursorOffset = 512; 4659 } 4660#endif 4661 if(pSiS->HWCursor) { 4662 pSiS->availMem -= (pSiS->CursorSize * 2); 4663 if(pSiS->OptUseColorCursor) pSiS->availMem -= (pSiS->CursorSize * 2); 4664 } 4665 pSiS->cursorBufferNum = 0; 4666#ifdef SISDUALHEAD 4667 if(pSiSEnt) pSiSEnt->cursorBufferNum = 0; 4668#endif 4669 4670 if((pSiS->SiS76xLFBSize) && (pSiS->SiS76xUMASize)) { 4671 pSiS->availMem -= pSiS->SiS76xUMASize; 4672 pSiS->FbBaseOffset = pSiS->SiS76xUMASize; 4673 } 4674 4675 break; 4676 4677 default: 4678 /* cursorOffset not used in cursor functions for 530 and 4679 * older chips, because the cursor is *above* the TQ. 4680 * On 5597 and older revisions of the 6326, the TQ is 4681 * max 32K, on newer 6326 revisions and the 530 either 30 4682 * (or 32?) or 62K (or 64?). However, to make sure, we 4683 * use only 30K (or 32?), but reduce the available memory 4684 * by 64, and locate the TQ at the beginning of this last 4685 * 64K block. (We do this that way even when using the 4686 * HWCursor, because the cursor only takes 2K and the 4687 * queue does not seem to last that far anyway.) 4688 * The TQ must be located at 32KB boundaries. 4689 */ 4690 if(pSiS->RealVideoRam < 3072) { 4691 if(pSiS->TurboQueue) { 4692 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4693 "Not enough video RAM for TurboQueue. TurboQueue disabled\n"); 4694 pSiS->TurboQueue = FALSE; 4695 } 4696 } 4697 pSiS->CmdQueMaxLen = 32; 4698 if(pSiS->TurboQueue) { 4699 pSiS->availMem -= (64*1024); 4700 pSiS->CmdQueMaxLen = 900; /* To make sure; should be 992 */ 4701 } else if(pSiS->HWCursor) { 4702 pSiS->availMem -= pSiS->CursorSize; 4703 } 4704 if(pSiS->Chipset == PCI_CHIP_SIS530) { 4705 /* Check if Flat Panel is enabled */ 4706 inSISIDXREG(SISSR, 0x0e, tempreg); 4707 if(!(tempreg & 0x04)) pSiS->availMem -= pSiS->CursorSize; 4708 4709 /* Set up mask for MMIO register */ 4710 pSiS->CmdQueLenMask = (pSiS->TurboQueue) ? 0x1FFF : 0x00FF; 4711 } else { 4712 /* TQ is never used on 6326/5597, because the accelerator 4713 * always Syncs. So this is just cosmentic work. (And I 4714 * am not even sure that 0x7fff is correct. MMIO 0x83a8 4715 * holds 0xec0 if (30k) TQ is enabled, 0x20 if TQ disabled. 4716 * The datasheet has no real explanation on the queue length 4717 * if the TQ is enabled. Not syncing and waiting for a 4718 * suitable queue length instead does not work. 4719 */ 4720 pSiS->CmdQueLenMask = (pSiS->TurboQueue) ? 0x7FFF : 0x003F; 4721 } 4722 4723 /* This is to be subtracted from MMIO queue length register contents 4724 * for getting the real Queue length. 4725 */ 4726 pSiS->CmdQueLenFix = (pSiS->TurboQueue) ? 32 : 0; 4727 } 4728 4729 4730#ifdef SISDUALHEAD 4731 /* In dual head mode, we share availMem equally - so align it 4732 * to 8KB; this way, the address of the FB of the second 4733 * head is aligned to 4KB for mapping. 4734 */ 4735 if(pSiS->DualHeadMode) pSiS->availMem &= 0xFFFFE000; 4736#endif 4737 4738 /* Check MaxXFBMem setting */ 4739#ifdef SISDUALHEAD 4740 if(pSiS->DualHeadMode) { 4741 /* 1. Since DRI is not supported in dual head mode, we 4742 * don't need the MaxXFBMem setting - ignore it. 4743 */ 4744 if(pSiS->maxxfbmem) { 4745 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4746 "MaxXFBMem ignored in Dual Head mode\n"); 4747 } 4748 pSiS->maxxfbmem = pSiS->availMem; 4749 } else 4750#endif 4751 if((pSiS->sisfbHeapStart) || (pSiS->sisfbHaveNewHeapDef)) { 4752 4753 /* 4754 * 2. We have memory layout info from sisfb - ignore MaxXFBMem 4755 */ 4756 if(pSiS->maxxfbmem) { 4757 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4758 "Got memory layout info from sisfb, ignoring MaxXFBMem option\n"); 4759 } 4760 if((pSiS->FbBaseOffset) && (!pSiS->sisfbHaveNewHeapDef)) { 4761 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4762 "Incompatible sisfb version detected, DRI disabled\n"); 4763 pSiS->loadDRI = FALSE; 4764 pSiS->maxxfbmem = pSiS->availMem; 4765 } else { 4766 if(pSiS->FbBaseOffset) { 4767 /* Revert our changes to FbBaseOffset and availMem; use sisfb's info */ 4768 pSiS->availMem += pSiS->FbBaseOffset; 4769 pSiS->FbBaseOffset = 0; 4770 } 4771 if(pSiS->sisfbVideoOffset) { 4772 /* a. DRI heap BELOW framebuffer */ 4773 pSiS->FbBaseOffset = pSiS->sisfbVideoOffset; 4774 pSiS->availMem -= pSiS->FbBaseOffset; 4775 pSiS->maxxfbmem = pSiS->availMem; 4776 } else { 4777 /* b. DRI heap ABOVE framebuffer (traditional layout) */ 4778 if(pSiS->availMem < (pSiS->sisfbHeapStart * 1024)) { 4779 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4780 "Internal error - sisfb memory layout corrupt\n"); 4781 pSiS->loadDRI = FALSE; 4782 pSiS->maxxfbmem = pSiS->availMem; 4783 } else { 4784 pSiS->maxxfbmem = pSiS->sisfbHeapStart * 1024; 4785 } 4786 } 4787 } 4788 4789 } else if(pSiS->maxxfbmem) { 4790 4791 /* 4792 * 3. No sisfb, but user gave "MaxXFBMem" 4793 */ 4794 if(pSiS->FbBaseOffset) { 4795 /* a. DRI heap BELOW framebuffer */ 4796 if(pSiS->maxxfbmem > (pSiS->availMem + pSiS->FbBaseOffset - pSiS->SiS76xUMASize)) { 4797 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4798 "Invalid MaxXFBMem setting\n"); 4799 pSiS->maxxfbmem = pSiS->availMem; 4800 } else { 4801 /* Revert our changes */ 4802 pSiS->availMem += pSiS->FbBaseOffset; 4803 /* Use user's MaxXFBMem setting */ 4804 pSiS->FbBaseOffset = pSiS->availMem - pSiS->maxxfbmem; 4805 pSiS->availMem -= pSiS->FbBaseOffset; 4806 } 4807 } else { 4808 /* b. DRI heap ABOVE framebuffer (traditional layout) */ 4809 if(pSiS->maxxfbmem > pSiS->availMem) { 4810 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4811 "Invalid MaxXFBMem setting.\n"); 4812 pSiS->maxxfbmem = pSiS->availMem; 4813 } 4814 } 4815 4816 } else { 4817 4818 /* 4819 * 4. No MaxXFBMem, no sisfb: Use all memory 4820 */ 4821 pSiS->maxxfbmem = pSiS->availMem; 4822 4823 /* ... except on chipsets, for which DRI is 4824 * supported: If DRI is enabled, we now limit 4825 * ourselves to a reasonable default: 4826 */ 4827 4828 if(pSiS->loadDRI) { 4829 if(pSiS->FbBaseOffset) { 4830 /* a. DRI heap BELOW framebuffer */ 4831 /* See how much UMA and LFB memory we have, 4832 * and calculate a reasonable default. We 4833 * use more vram for ourselves because these 4834 * chips are eg. capable of larger Xv 4835 * overlays, etc. 4836 */ 4837 unsigned long total = (pSiS->SiS76xLFBSize + pSiS->SiS76xUMASize) / 1024; 4838 unsigned long mymax; 4839 if(total <= 16384) /* <= 16MB: Use 8MB for X */ 4840 mymax = 8192 * 1024; 4841 else if(total <= 32768) /* <= 32MB: Use 16MB for X */ 4842 mymax = 16384 * 1024; 4843 else /* Otherwise: Use 20MB for X */ 4844 mymax = 20 * 1024 * 1024; 4845 /* availMem is right now adjusted to not use the UMA 4846 * area. Make sure that our default doesn't reach 4847 * into the UMA area either. 4848 */ 4849 if(pSiS->availMem > mymax) { 4850 /* Write our default to maxxfbmem */ 4851 pSiS->maxxfbmem = mymax; 4852 /* Revert our changes to availMem */ 4853 pSiS->availMem += pSiS->FbBaseOffset; 4854 /* Use our default setting */ 4855 pSiS->FbBaseOffset = pSiS->availMem - pSiS->maxxfbmem; 4856 pSiS->availMem -= pSiS->FbBaseOffset; 4857 } 4858 } else { 4859 /* b. DRI heap ABOVE framebuffer (traditional layout) */ 4860 /* See how much video memory we have, and calculate 4861 * a reasonable default. 4862 * Since DRI is pointless with less than 4MB of total 4863 * video RAM, we disable it in that case. 4864 */ 4865 if(pScrn->videoRam <= 4096) 4866 pSiS->loadDRI = FALSE; 4867 else if(pScrn->videoRam <= 8192) /* <= 8MB: Use 4MB for X */ 4868 pSiS->maxxfbmem = 4096 * 1024; 4869 else if(pScrn->videoRam <= 16384) /* <= 16MB: Use 8MB for X */ 4870 pSiS->maxxfbmem = 8192 * 1024; 4871#ifdef SISMERGED /* Otherwise: --- */ 4872 else if(pSiS->MergedFB) { 4873 if(pScrn->videoRam <= 65536) 4874 pSiS->maxxfbmem = 16384 * 1024; /* If MergedFB and <=64MB, use 16MB for X */ 4875 else 4876 pSiS->maxxfbmem = 20 * 1024 * 1024; /* If MergedFB and > 64MB, use 20MB for X */ 4877 } 4878#endif 4879 else if(pSiS->VGAEngine == SIS_315_VGA) { 4880 if(pScrn->videoRam <= 65536) 4881 pSiS->maxxfbmem = 16384 * 1024; /* On >=315 series and <=64MB, use 16MB */ 4882 else 4883 pSiS->maxxfbmem = 20 * 1024 * 1024; /* On >=315 series and > 64MB, use 20MB */ 4884 } else 4885 pSiS->maxxfbmem = 12288 * 1024; /* On <315 series, use 12MB */ 4886 4887 /* A final check */ 4888 if(pSiS->maxxfbmem > pSiS->availMem) { 4889 pSiS->maxxfbmem = pSiS->availMem; 4890 pSiS->loadDRI = FALSE; 4891 } 4892 } 4893 4894 } 4895 } 4896 4897 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %dK of framebuffer memory at offset %dK\n", 4898 pSiS->maxxfbmem / 1024, pSiS->FbBaseOffset / 1024); 4899 4900 /* Find out about sub-classes of some chipsets and check 4901 * if the chipset supports two video overlays 4902 */ 4903 if(pSiS->VGAEngine == SIS_300_VGA || 4904 pSiS->VGAEngine == SIS_315_VGA || 4905 pSiS->Chipset == PCI_CHIP_SIS530 || 4906 pSiS->Chipset == PCI_CHIP_SIS6326 || 4907 pSiS->Chipset == PCI_CHIP_SIS5597) { 4908 pSiS->hasTwoOverlays = FALSE; 4909 switch(pSiS->Chipset) { 4910 case PCI_CHIP_SIS300: 4911 case PCI_CHIP_SIS540: /* ? (If not, need to add the SwitchCRT Xv attribute!) */ 4912 case PCI_CHIP_SIS630: 4913 case PCI_CHIP_SIS550: 4914 pSiS->hasTwoOverlays = TRUE; 4915 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4916 break; 4917 case PCI_CHIP_SIS315PRO: 4918 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4919 break; 4920 case PCI_CHIP_SIS330: 4921 pSiS->ChipFlags |= (SiSCF_CRT2HWCKaputt | SiSCF_LARGEOVERLAY); 4922 break; 4923 case PCI_CHIP_SIS340: 4924 case PCI_CHIP_XGIXG40: /* Verified: only 1 overlay */ 4925 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4926 break; 4927 case PCI_CHIP_SIS650: 4928 { 4929 UChar tempreg1, tempreg2; 4930 static const char *id650str[] = { 4931 "650", "650", "650", "650", 4932 "650 A0 AA", "650 A2 CA", "650", "650", 4933 "M650 A0", "M650 A1 AA","651 A0 AA", "651 A1 AA", 4934 "M650", "65?", "651", "65?" 4935 }; 4936 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4937 if(pSiS->ChipType == SIS_650) { 4938 inSISIDXREG(SISCR, 0x5f, CR5F); 4939 CR5F &= 0xf0; 4940 andSISIDXREG(SISCR, 0x5c, 0x07); 4941 inSISIDXREG(SISCR, 0x5c, tempreg1); 4942 tempreg1 &= 0xf8; 4943 orSISIDXREG(SISCR, 0x5c, 0xf8); 4944 inSISIDXREG(SISCR, 0x5c, tempreg2); 4945 tempreg2 &= 0xf8; 4946 if((!tempreg1) || (tempreg2)) { 4947 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4948 "SiS650 revision ID %x (%s)\n", CR5F, id650str[CR5F >> 4]); 4949 if(CR5F & 0x80) { 4950 pSiS->hasTwoOverlays = TRUE; /* M650 or 651 */ 4951 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4952 } 4953 switch(CR5F) { 4954 case 0xa0: 4955 case 0xb0: 4956 case 0xe0: 4957 pSiS->ChipFlags |= SiSCF_Is651; 4958 break; 4959 case 0x80: 4960 case 0x90: 4961 case 0xc0: 4962 pSiS->ChipFlags |= SiSCF_IsM650; 4963 break; 4964 } 4965 } else { 4966 pSiS->hasTwoOverlays = TRUE; 4967 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4968 switch(CR5F) { 4969 case 0x90: 4970 inSISIDXREG(SISCR, 0x5c, tempreg1); 4971 tempreg1 &= 0xf8; 4972 switch(tempreg1) { 4973 case 0x00: 4974 pSiS->ChipFlags |= SiSCF_IsM652; 4975 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4976 "SiSM652 revision ID %x\n", CR5F); 4977 break; 4978 case 0x40: 4979 pSiS->ChipFlags |= SiSCF_IsM653; 4980 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4981 "SiSM653 revision ID %x\n", CR5F); 4982 break; 4983 default: 4984 pSiS->ChipFlags |= SiSCF_IsM650; 4985 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4986 "SiSM650 revision ID %x\n", CR5F); 4987 break; 4988 } 4989 break; 4990 case 0xb0: 4991 pSiS->ChipFlags |= SiSCF_Is652; 4992 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4993 "SiS652 revision ID %x\n", CR5F); 4994 break; 4995 default: 4996 pSiS->ChipFlags |= SiSCF_IsM650; 4997 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4998 "SiSM650 revision ID %x\n", CR5F); 4999 break; 5000 } 5001 } 5002 } 5003 break; 5004 } 5005 case PCI_CHIP_SIS660: 5006 { 5007 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 5008 pSiS->hasTwoOverlays = TRUE; 5009 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 5010 /* 760/761: - UMA only: one/two overlays - dotclock dependent 5011 - UMA+LFB: two overlays if video data in LFB 5012 - LFB only: two overlays 5013 If UMA only: Must switch between one/two overlays on the fly (done 5014 in PostSetMode()) 5015 If LFB+UMA: We use LFB memory only and leave UMA to an eventually 5016 written DRI driver. 5017 */ 5018 break; 5019 } 5020 } 5021 5022 if(!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY)) { 5023 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5024 "Hardware supports %s video overlay%s\n", 5025 pSiS->hasTwoOverlays ? "two" : "one", 5026 pSiS->hasTwoOverlays ? "s" : ""); 5027 } 5028 5029 if(pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORT760OO) { 5030 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5031 "\n\tDear SiS76x user, your machine is using a shared memory framebuffer.\n" 5032 "\tDue to hardware limitations of the SiS chip in combination with the\n" 5033 "\tAMD CPU, video overlay support is very limited on this machine. If you\n" 5034 "\texperience flashing lines in the video and/or the graphics display\n" 5035 "\tduring video playback, reduce the color depth and/or the resolution\n" 5036 "\tand/or the refresh rate. Alternatively, use the video blitter.\n"); 5037 } 5038 5039 } 5040 5041 /* Backup VB connection and CRT1 on/off register */ 5042 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5043 inSISIDXREG(SISSR, 0x1f, pSiS->oldSR1F); 5044 inSISIDXREG(SISCR, 0x17, pSiS->oldCR17); 5045 inSISIDXREG(SISCR, 0x32, pSiS->oldCR32); 5046 inSISIDXREG(SISCR, 0x36, pSiS->oldCR36); 5047 inSISIDXREG(SISCR, 0x37, pSiS->oldCR37); 5048 if(pSiS->VGAEngine == SIS_315_VGA) { 5049 inSISIDXREG(SISCR, pSiS->myCR63, pSiS->oldCR63); 5050 } 5051 5052 pSiS->postVBCR32 = pSiS->oldCR32; 5053 } 5054 5055 /* There are some machines out there which require a special 5056 * setup of the GPIO registers in order to make the Chrontel 5057 * work. Try to find out if we're running on such a machine. 5058 * Furthermore, there is some highly customized hardware, 5059 * which requires some non-standard LVDS timing. Since the 5060 * vendors don't seem to care about PCI subsystem ID's we 5061 * need to find out using the BIOS version and date strings. 5062 */ 5063 pSiS->SiS_Pr->SiS_ChSW = FALSE; 5064 if(pSiS->Chipset == PCI_CHIP_SIS630) { 5065 int i = 0; 5066 do { 5067 if(mychswtable[i].subsysVendor == pSiS->PciInfo->subsysVendor && 5068 mychswtable[i].subsysCard == pSiS->PciInfo->subsysCard) { 5069 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5070 "PCI subsystem ID found in list for Chrontel/GPIO setup:\n"); 5071 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5072 "\tVendor/Card: %s %s (ID %04x)\n", 5073 mychswtable[i].vendorName, 5074 mychswtable[i].cardName, 5075 pSiS->PciInfo->subsysCard); 5076 pSiS->SiS_Pr->SiS_ChSW = TRUE; 5077 break; 5078 } 5079 i++; 5080 } while(mychswtable[i].subsysVendor != 0); 5081 } 5082 5083 if(pSiS->SiS_Pr->SiS_CustomT == CUT_NONE) { 5084 int i = 0, j; 5085 UShort bversptr = 0; 5086 Bool footprint; 5087 CARD32 chksum = 0; 5088 5089 if(pSiS->SiS_Pr->UseROM) { 5090 bversptr = pSiS->BIOS[0x16] | (pSiS->BIOS[0x17] << 8); 5091 for(i=0; i<32768; i++) chksum += pSiS->BIOS[i]; 5092 } 5093 5094 i = 0; 5095 do { 5096 if( (SiS_customttable[i].chipID == pSiS->ChipType) && 5097 ((!strlen(SiS_customttable[i].biosversion)) || 5098 (pSiS->SiS_Pr->UseROM && 5099 (!strncmp(SiS_customttable[i].biosversion, (char *)&pSiS->BIOS[bversptr], 5100 strlen(SiS_customttable[i].biosversion))))) && 5101 ((!strlen(SiS_customttable[i].biosdate)) || 5102 (pSiS->SiS_Pr->UseROM && 5103 (!strncmp(SiS_customttable[i].biosdate, (char *)&pSiS->BIOS[0x2c], 5104 strlen(SiS_customttable[i].biosdate))))) && 5105 ((!SiS_customttable[i].bioschksum) || 5106 (pSiS->SiS_Pr->UseROM && 5107 (SiS_customttable[i].bioschksum == chksum))) && 5108 (SiS_customttable[i].pcisubsysvendor == pSiS->PciInfo->subsysVendor) && 5109 (SiS_customttable[i].pcisubsyscard == pSiS->PciInfo->subsysCard) ) { 5110 footprint = TRUE; 5111 for(j=0; j<5; j++) { 5112 if(SiS_customttable[i].biosFootprintAddr[j]) { 5113 if(pSiS->SiS_Pr->UseROM) { 5114 if(pSiS->BIOS[SiS_customttable[i].biosFootprintAddr[j]] != 5115 SiS_customttable[i].biosFootprintData[j]) 5116 footprint = FALSE; 5117 } else footprint = FALSE; 5118 } 5119 } 5120 if(footprint) { 5121 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5122 "Identified %s %s, special timing applies\n", 5123 SiS_customttable[i].vendorName, SiS_customttable[i].cardName); 5124 pSiS->SiS_Pr->SiS_CustomT = SiS_customttable[i].SpecialID; 5125 break; 5126 } 5127 } 5128 i++; 5129 } while(SiS_customttable[i].chipID); 5130 } 5131 5132 /* Handle ForceCRT1 option */ 5133 if(pSiS->forceCRT1 != -1) { 5134 if(pSiS->forceCRT1) pSiS->CRT1off = 0; 5135 else pSiS->CRT1off = 1; 5136 } else pSiS->CRT1off = -1; 5137 5138 /* Detect video bridge and sense TV/VGA2 */ 5139 SISVGAPreInit(pScrn); 5140 5141 /* Detect CRT1 (via DDC1 and DDC2, hence via VGA port; regardless of LCDA) */ 5142 SISCRT1PreInit(pScrn); 5143 5144 /* Detect LCD (connected via CRT2, regardless of LCDA) and LCD resolution */ 5145 SISLCDPreInit(pScrn, FALSE); 5146 5147 /* LCDA only supported under these conditions: */ 5148 if(pSiS->ForceCRT1Type == CRT1_LCDA) { 5149 if(!SISDetermineLCDACap(pScrn)) { 5150 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5151 "Chipset/Video bridge does not support LCD-via-CRT1\n"); 5152 pSiS->ForceCRT1Type = CRT1_VGA; 5153 } else if(!(pSiS->VBFlags & CRT2_LCD)) { 5154 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5155 "No digital LCD panel found, LCD-via-CRT1 disabled\n"); 5156 pSiS->ForceCRT1Type = CRT1_VGA; 5157 } 5158 } 5159 5160 /* Setup SD flags */ 5161 pSiS->SiS_SD_Flags |= SiS_SD_ADDLSUPFLAG; 5162 5163 pSiS->SiS_SD2_Flags |= SiS_SD2_MERGEDUCLOCK; 5164 pSiS->SiS_SD2_Flags |= SiS_SD2_USEVBFLAGS2; 5165 pSiS->SiS_SD2_Flags |= SiS_SD2_VBINVB2ONLY; 5166 pSiS->SiS_SD2_Flags |= SiS_SD2_HAVESD34; 5167 pSiS->SiS_SD2_Flags |= SiS_SD2_NEWGAMMABRICON; 5168 5169 pSiS->SiS_SD3_Flags |= SiS_SD3_MFBALLOWOFFCL; 5170 5171 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 5172 pSiS->SiS_SD2_Flags |= SiS_SD2_VIDEOBRIDGE; 5173 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 5174 pSiS->SiS_SD2_Flags |= ( SiS_SD2_SISBRIDGE | 5175 SiS_SD2_SUPPORTGAMMA2 ); 5176 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) { 5177 pSiS->SiS_SD2_Flags |= ( SiS_SD2_LCDLVDS | 5178 SiS_SD2_SUPPORTLCD ); 5179 } else if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 5180 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 5181 pSiS->SiS_SD2_Flags |= ( SiS_SD2_LCDTMDS | 5182 SiS_SD2_SUPPORTLCD ); 5183 } else if(pSiS->VBFlags & CRT2_LCD) { 5184 pSiS->SiS_SD2_Flags |= ( SiS_SD2_THIRDPARTYLVDS | 5185 SiS_SD2_SUPPORTLCD ); 5186 } 5187 } 5188 } else if(pSiS->VBFlags2 & VB2_LVDS) { 5189 pSiS->SiS_SD2_Flags |= ( SiS_SD2_THIRDPARTYLVDS | 5190 SiS_SD2_SUPPORTLCD ); 5191 } 5192 5193 if(pSiS->VBFlags2 & (VB2_SISTVBRIDGE | VB2_CHRONTEL)) { 5194 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTTV; 5195 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 5196 pSiS->SiS_SD2_Flags |= ( SiS_SD2_SUPPORTTVTYPE | 5197 SiS_SD2_SUPPORTTVSIZE ); 5198 if(!(pSiS->VBFlags2 & VB2_301)) { 5199 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPTVSAT; 5200 } else { 5201 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPTVEDGE; 5202 } 5203 } 5204 } 5205 } 5206 5207#ifdef ENABLE_YPBPR 5208 if((pSiS->VGAEngine == SIS_315_VGA) && 5209 (pSiS->VBFlags2 & VB2_SISYPBPRBRIDGE)) { 5210 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTYPBPR; 5211 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORT625I; 5212 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORT625P; 5213 if(pSiS->VBFlags2 & VB2_SISYPBPRARBRIDGE) { 5214 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTYPBPRAR; 5215 } 5216 } 5217 if(pSiS->VBFlags2 & VB2_SISHIVISIONBRIDGE) { 5218 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTHIVISION; 5219 } 5220#endif 5221 5222 if((pSiS->VGAEngine != SIS_300_VGA) || (!(pSiS->VBFlags2 & VB2_TRUMPION))) { 5223 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTSCALE; 5224 if((pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && 5225 (!(pSiS->VBFlags2 & VB2_30xBDH))) { 5226 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTCENTER; 5227 } 5228 } 5229 5230#ifdef SISDUALHEAD 5231 if(!pSiS->DualHeadMode) { 5232 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTREDETECT; 5233 } 5234#endif 5235 5236#ifndef SISCHECKOSSSE 5237 pSiS->SiS_SD2_Flags |= SiS_SD2_NEEDUSESSE; 5238#endif 5239 5240#ifdef TWDEBUG /* FOR TESTING */ 5241 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTYPBPRAR; 5242 xf86DrvMsg(0, X_INFO, "TEST: Support Aspect Ratio\n"); 5243#endif 5244 5245 /* Detect CRT2-TV and PAL/NTSC mode */ 5246 SISTVPreInit(pScrn, FALSE); 5247 5248 /* Detect CRT2-VGA */ 5249 SISCRT2PreInit(pScrn, FALSE); 5250 5251 /* Backup detected CRT2 devices */ 5252 SISSaveDetectedDevices(pScrn); 5253 5254 if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR)) { 5255 if((pSiS->ForceTVType != -1) && (pSiS->ForceTVType & TV_YPBPR)) { 5256 pSiS->ForceTVType = -1; 5257 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "YPbPr TV output not supported\n"); 5258 } 5259 } 5260 5261 if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTHIVISION)) { 5262 if((pSiS->ForceTVType != -1) && (pSiS->ForceTVType & TV_HIVISION)) { 5263 pSiS->ForceTVType = -1; 5264 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "HiVision TV output not supported\n"); 5265 } 5266 } 5267 5268 if((pSiS->VBFlags2 & VB2_SISTVBRIDGE) || 5269 ((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->ChrontelType == CHRONTEL_701x))) { 5270 pSiS->SiS_SD_Flags |= (SiS_SD_SUPPORTPALMN | SiS_SD_SUPPORTNTSCJ); 5271 } 5272 if((pSiS->VBFlags2 & VB2_SISTVBRIDGE) || 5273 ((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->ChrontelType == CHRONTEL_700x))) { 5274 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTTVPOS; 5275 } 5276 if(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE) { 5277 pSiS->SiS_SD_Flags |= (SiS_SD_SUPPORTSCART | SiS_SD_SUPPORTVGA2); 5278 } 5279 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 5280 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTOVERSCAN; 5281 pSiS->SiS_SD2_Flags |= SiS_SD2_CHRONTEL; 5282 if(pSiS->ChrontelType == CHRONTEL_700x) { 5283 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTSOVER; 5284 } 5285 } 5286 5287 /* Determine if chipset LCDA-capable */ 5288 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTLCDA; 5289 if(SISDetermineLCDACap(pScrn)) { 5290 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTLCDA; 5291 } 5292 5293 /* Default to LCDA if LCD detected and 5294 * - TV detected (hence default to LCDA+TV), or 5295 * - in single head mode, on LCD panels with xres > 1600 5296 * (Don't do this in MergedFB or DHM; LCDA and CRT1/VGA 5297 * are mutually exclusive; if no TV is detected, the 5298 * code below will default to VGA+LCD, so LCD is driven 5299 * via CRT2.) 5300 * (TODO: This might need some modification for the 5301 * 307 bridges, if these are capable of driving 5302 * LCDs > 1600 via channel B) 5303 */ 5304 if((pSiS->SiS_SD_Flags & SiS_SD_SUPPORTLCDA) && 5305 (pSiS->VBFlags & CRT2_LCD) && 5306 (pSiS->SiS_Pr->SiS_CustomT != CUT_UNKNOWNLCD)) { 5307 if((!pSiS->CRT1TypeForced) && (pSiS->ForceCRT2Type == CRT2_DEFAULT)) { 5308 if(pSiS->VBFlags & CRT2_TV) { 5309 /* If both LCD and TV present, default to LCDA+TV */ 5310 pSiS->ForceCRT1Type = CRT1_LCDA; 5311 pSiS->ForceCRT2Type = CRT2_TV; 5312 } else if(pSiS->LCDwidth > 1600) { 5313 /* If LCD is > 1600, default to LCDA if we don't need CRT1/VGA for other head */ 5314 Bool NeedCRT1VGA = FALSE; 5315#ifdef SISDUALHEAD 5316 if(pSiS->DualHeadMode) NeedCRT1VGA = TRUE; 5317#endif 5318#ifdef SISMERGED 5319 if(pSiS->MergedFB && 5320 (!pSiS->MergedFBAuto || pSiS->CRT1Detected)) NeedCRT1VGA = TRUE; 5321#endif 5322 if(!NeedCRT1VGA) { 5323 pSiS->ForceCRT1Type = CRT1_LCDA; 5324 } 5325 } 5326 } 5327 } 5328 5329 /* Set up pseudo-panel if LCDA forced on TMDS bridges */ 5330 if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTLCDA) { 5331 if(pSiS->ForceCRT1Type == CRT1_LCDA) { 5332 if(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE) { 5333 if(!(pSiS->VBLCDFlags)) { 5334 SiSSetupPseudoPanel(pScrn); 5335 pSiS->detectedCRT2Devices |= CRT2_LCD; 5336 } 5337 } else if(!(pSiS->VBLCDFlags)) { 5338 pSiS->ForceCRT1Type = CRT1_VGA; 5339 } 5340 } 5341 } else { 5342 pSiS->ForceCRT1Type = CRT1_VGA; 5343 } 5344 5345 pSiS->VBFlags |= pSiS->ForceCRT1Type; 5346 5347#ifdef TWDEBUG 5348 xf86DrvMsg(0, X_INFO, "SDFlags %lx\n", pSiS->SiS_SD_Flags); 5349#endif 5350 5351 /* Eventually overrule detected CRT2 type 5352 * If no type forced, use the detected devices in the order TV->LCD->VGA2 5353 * Since the Chrontel 7005 sometimes delivers wrong detection results, 5354 * we use a different order on such machines (LCD->TV) 5355 */ 5356 if(pSiS->ForceCRT2Type == CRT2_DEFAULT) { 5357 if((pSiS->VBFlags & CRT2_TV) && (!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VGAEngine == SIS_300_VGA)))) 5358 pSiS->ForceCRT2Type = CRT2_TV; 5359 else if((pSiS->VBFlags & CRT2_LCD) && (pSiS->ForceCRT1Type == CRT1_VGA)) 5360 pSiS->ForceCRT2Type = CRT2_LCD; 5361 else if(pSiS->VBFlags & CRT2_TV) 5362 pSiS->ForceCRT2Type = CRT2_TV; 5363 else if((pSiS->VBFlags & CRT2_VGA) && (pSiS->ForceCRT1Type == CRT1_VGA)) 5364 pSiS->ForceCRT2Type = CRT2_VGA; 5365 } 5366 5367 switch(pSiS->ForceCRT2Type) { 5368 case CRT2_TV: 5369 pSiS->VBFlags &= ~(CRT2_LCD | CRT2_VGA); 5370 if(pSiS->VBFlags2 & (VB2_SISTVBRIDGE | VB2_CHRONTEL)) { 5371 pSiS->VBFlags |= CRT2_TV; 5372 } else { 5373 pSiS->VBFlags &= ~(CRT2_TV); 5374 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 5375 "Hardware does not support TV output\n"); 5376 } 5377 break; 5378 case CRT2_LCD: 5379 pSiS->VBFlags &= ~(CRT2_TV | CRT2_VGA); 5380 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (pSiS->VBLCDFlags)) { 5381 pSiS->VBFlags |= CRT2_LCD; 5382 } else if((pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && (!(pSiS->VBFlags2 & VB2_30xBDH))) { 5383 SiSSetupPseudoPanel(pScrn); 5384 pSiS->detectedCRT2Devices |= CRT2_LCD; 5385 } else { 5386 pSiS->VBFlags &= ~(CRT2_LCD); 5387 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 5388 "Can't force CRT2 to LCD, no LCD detected\n"); 5389 } 5390 break; 5391 case CRT2_VGA: 5392 pSiS->VBFlags &= ~(CRT2_TV | CRT2_LCD); 5393 if(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE) { 5394 pSiS->VBFlags |= CRT2_VGA; 5395 } else { 5396 pSiS->VBFlags &= ~(CRT2_VGA); 5397 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 5398 "Hardware does not support secondary VGA\n"); 5399 } 5400 break; 5401 default: 5402 pSiS->VBFlags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA); 5403 } 5404 5405 /* Setup gamma (the cmap layer needs this to be initialised) */ 5406 /* (Do this after evaluating options) */ 5407 { 5408 Gamma zeros = {0.0, 0.0, 0.0}; 5409 xf86SetGamma(pScrn, zeros); 5410 } 5411 5412#ifdef SISDUALHEAD 5413 if((!pSiS->DualHeadMode) || (pSiS->SecondHead)) { 5414#endif 5415 xf86DrvMsg(pScrn->scrnIndex, pSiS->CRT1gammaGiven ? X_CONFIG : X_INFO, 5416 "%samma correction is %s\n", 5417 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) ? "CRT1 g" : "G", 5418 pSiS->CRT1gamma ? "enabled" : "disabled"); 5419 5420 if((pSiS->VGAEngine == SIS_315_VGA) && 5421 (!(pSiS->NoXvideo)) && 5422 (!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY))) { 5423 xf86DrvMsg(pScrn->scrnIndex, pSiS->XvGammaGiven ? X_CONFIG : X_INFO, 5424 "Separate Xv gamma correction %sis %s\n", 5425 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) ? "for CRT1 " : "", 5426 pSiS->XvGamma ? "enabled" : "disabled"); 5427 if(pSiS->XvGamma) { 5428 xf86DrvMsg(pScrn->scrnIndex, pSiS->XvGammaGiven ? X_CONFIG : X_INFO, 5429 "Xv gamma correction: %.3f %.3f %.3f\n", 5430 (float)((float)pSiS->XvGammaRed / 1000), 5431 (float)((float)pSiS->XvGammaGreen / 1000), 5432 (float)((float)pSiS->XvGammaBlue / 1000)); 5433 if(!pSiS->CRT1gamma) { 5434 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5435 "Xv gamma correction requires %samma correction enabled\n", 5436 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) ? "CRT1 g" : "G"); 5437 } 5438 } 5439 } 5440#ifdef SISDUALHEAD 5441 } 5442#endif 5443 5444#ifdef SISDUALHEAD 5445 if(pSiS->DualHeadMode) pSiS->CRT2SepGamma = FALSE; 5446#endif 5447 5448#ifdef SISDUALHEAD 5449 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) 5450#endif 5451 { 5452 Bool isDH = FALSE; 5453 if(pSiS->CRT2gamma) { 5454 if( ((pSiS->VGAEngine != SIS_300_VGA) && (pSiS->VGAEngine != SIS_315_VGA)) || 5455 (!(pSiS->VBFlags2 & VB2_SISBRIDGE)) ) { 5456 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 5457 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5458 "CRT2 gamma correction not supported by hardware\n"); 5459 } 5460 pSiS->CRT2gamma = pSiS->CRT2SepGamma = FALSE; 5461 } else if((pSiS->VBFlags2 & VB2_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) { 5462 isDH = TRUE; 5463 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5464 "CRT2 gamma correction not supported for LCD\n"); 5465 /* But leave it on, will be caught in LoadPalette */ 5466 } 5467 } 5468 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 5469 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CRT2 gamma correction is %s%s%s\n", 5470 pSiS->CRT2gamma ? "enabled" : "disabled", 5471 isDH ? " (for TV and VGA2) " : "", 5472 pSiS->CRT2SepGamma ? " (separate from CRT1)" : ""); 5473 } 5474 } 5475 5476 /* Eventually overrule TV Type (SVIDEO, COMPOSITE, SCART, HIVISION, YPBPR) */ 5477 if(pSiS->VBFlags2 & VB2_SISTVBRIDGE) { 5478 if(pSiS->ForceTVType != -1) { 5479 pSiS->VBFlags &= ~(TV_INTERFACE); 5480 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) { 5481 pSiS->VBFlags &= ~(TV_CHSCART | TV_CHYPBPR525I); 5482 } 5483 pSiS->VBFlags |= pSiS->ForceTVType; 5484 if(pSiS->VBFlags & TV_YPBPR) { 5485 pSiS->VBFlags &= ~(TV_STANDARD); 5486 pSiS->VBFlags &= ~(TV_YPBPRAR); 5487 pSiS->VBFlags |= pSiS->ForceYPbPrType; 5488 pSiS->VBFlags |= pSiS->ForceYPbPrAR; 5489 } 5490 } 5491 } 5492 5493 /* Handle ForceCRT1 option (part 2) */ 5494 pSiS->CRT1changed = FALSE; 5495 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5496 usScratchCR17 = pSiS->oldCR17; 5497 usScratchCR63 = pSiS->oldCR63; 5498 usScratchSR1F = pSiS->oldSR1F; 5499 usScratchCR32 = pSiS->postVBCR32; 5500 if(pSiS->VESA != 1) { 5501 /* Copy forceCRT1 option to CRT1off if option is given */ 5502#ifdef SISDUALHEAD 5503 /* In DHM, handle this option only for master head, not the slave */ 5504 if( (pSiS->forceCRT1 != -1) && 5505 (!(pSiS->DualHeadMode && pSiS->SecondHead)) ) { 5506#else 5507 if(pSiS->forceCRT1 != -1) { 5508#endif 5509 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5510 "CRT1 detection overruled by ForceCRT1 option\n"); 5511 if(pSiS->forceCRT1) { 5512 pSiS->CRT1off = 0; 5513 if(pSiS->VGAEngine == SIS_300_VGA) { 5514 if(!(usScratchCR17 & 0x80)) pSiS->CRT1changed = TRUE; 5515 } else { 5516 if(usScratchCR63 & 0x40) pSiS->CRT1changed = TRUE; 5517 } 5518 usScratchCR17 |= 0x80; 5519 usScratchCR32 |= 0x20; 5520 usScratchCR63 &= ~0x40; 5521 usScratchSR1F &= ~0xc0; 5522 } else { 5523 if( ! ( (pScrn->bitsPerPixel == 8) && 5524 ( (pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) || 5525 ((pSiS->VBFlags2 & VB2_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) ) ) ) { 5526 pSiS->CRT1off = 1; 5527 if(pSiS->VGAEngine == SIS_300_VGA) { 5528 if(usScratchCR17 & 0x80) pSiS->CRT1changed = TRUE; 5529 } else { 5530 if(!(usScratchCR63 & 0x40)) pSiS->CRT1changed = TRUE; 5531 } 5532 usScratchCR32 &= ~0x20; 5533 /* We must not actually switch off CRT1 before we changed the mode! */ 5534 } 5535 } 5536 /* Here we can write to CR17 even on 315 series as we only ENABLE 5537 * the bit here 5538 */ 5539 outSISIDXREG(SISCR, 0x17, usScratchCR17); 5540 if(pSiS->VGAEngine == SIS_315_VGA) { 5541 outSISIDXREG(SISCR, pSiS->myCR63, usScratchCR63); 5542 } 5543 outSISIDXREG(SISCR, 0x32, usScratchCR32); 5544 if(pSiS->CRT1changed) { 5545 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 5546 usleep(10000); 5547 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 5548 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5549 "CRT1 status changed by ForceCRT1 option\n"); 5550 } 5551 outSISIDXREG(SISSR, 0x1f, usScratchSR1F); 5552 } 5553 } 5554 /* Store the new VB connection register contents for later mode changes */ 5555 pSiS->newCR32 = usScratchCR32; 5556 } 5557 5558 /* Check if CRT1 used (or needed; this eg. if no CRT2 detected) */ 5559 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 5560 5561 /* No CRT2 output? Then we NEED CRT1! 5562 * We also need CRT1 if depth = 8 and bridge=LVDS|301B-DH 5563 */ 5564 if( (!(pSiS->VBFlags & (CRT2_VGA | CRT2_LCD | CRT2_TV))) || 5565 ( (pScrn->bitsPerPixel == 8) && 5566 ( (pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) || 5567 ((pSiS->VBFlags2 & VB2_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) ) ) ) { 5568 pSiS->CRT1off = 0; 5569 } 5570 /* No CRT2 output? Then we can't use Xv on CRT2 */ 5571 if(!(pSiS->VBFlags & (CRT2_VGA | CRT2_LCD | CRT2_TV))) { 5572 pSiS->XvOnCRT2 = FALSE; 5573 } 5574 5575 } else { /* no video bridge? */ 5576 /* Then we NEED CRT1... */ 5577 pSiS->CRT1off = 0; 5578 /* ... and can't use CRT2 for Xv output */ 5579 pSiS->XvOnCRT2 = FALSE; 5580 } 5581 5582 /* LCDA? Then we don't switch off CRT1 */ 5583 if(pSiS->VBFlags & CRT1_LCDA) pSiS->CRT1off = 0; 5584 5585 /* Handle TVStandard option */ 5586 if((pSiS->NonDefaultPAL != -1) || (pSiS->NonDefaultNTSC != -1)) { 5587 if( (!(pSiS->VBFlags2 & VB2_SISTVBRIDGE)) && 5588 (!((pSiS->VBFlags2 & VB2_CHRONTEL)) && (pSiS->ChrontelType == CHRONTEL_701x)) ) { 5589 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5590 "PALM, PALN and NTSCJ not supported on this hardware\n"); 5591 pSiS->NonDefaultPAL = pSiS->NonDefaultNTSC = -1; 5592 pSiS->VBFlags &= ~(TV_PALN | TV_PALM | TV_NTSCJ); 5593 pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTPALMN | SiS_SD_SUPPORTNTSCJ); 5594 } 5595 } 5596 if(pSiS->OptTVStand != -1) { 5597 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5598 if( (!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & (TV_CHSCART | TV_CHYPBPR525I)))) && 5599 (!(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR))) ) { 5600 pSiS->VBFlags &= ~(TV_PAL | TV_NTSC | TV_PALN | TV_PALM | TV_NTSCJ); 5601 if(pSiS->OptTVStand) { 5602 pSiS->VBFlags |= TV_PAL; 5603 if(pSiS->NonDefaultPAL == 1) pSiS->VBFlags |= TV_PALM; 5604 else if(!pSiS->NonDefaultPAL) pSiS->VBFlags |= TV_PALN; 5605 } else { 5606 pSiS->VBFlags |= TV_NTSC; 5607 if(pSiS->NonDefaultNTSC == 1) pSiS->VBFlags |= TV_NTSCJ; 5608 } 5609 } else { 5610 pSiS->OptTVStand = pSiS->NonDefaultPAL = -1; 5611 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5612 "Option TVStandard ignored for YPbPr, HiVision and Chrontel-SCART\n"); 5613 } 5614 } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { 5615 pSiS->SiS6326Flags &= ~SIS6326_TVPAL; 5616 if(pSiS->OptTVStand) pSiS->SiS6326Flags |= SIS6326_TVPAL; 5617 } 5618 } 5619 5620 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5621 /* Default to PAL */ 5622 if(pSiS->VBFlags & (TV_SVIDEO | TV_AVIDEO)) { 5623 if(!(pSiS->VBFlags & (TV_PAL | TV_NTSC))) { 5624 pSiS->VBFlags &= ~(TV_PAL | TV_NTSC | TV_PALN | TV_PALM | TV_NTSCJ); 5625 pSiS->VBFlags |= TV_PAL; 5626 } 5627 } 5628 /* SCART only supported for PAL */ 5629 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && (pSiS->VBFlags & TV_SCART)) { 5630 pSiS->VBFlags &= ~(TV_NTSC | TV_PALN | TV_PALM | TV_NTSCJ); 5631 pSiS->VBFlags |= TV_PAL; 5632 pSiS->OptTVStand = 1; 5633 pSiS->NonDefaultPAL = pSiS->NonDefaultNTSC = -1; 5634 } 5635 } 5636 5637#ifdef SIS_CP 5638 SIS_CP_DRIVER_RECONFIGOPT 5639#endif 5640 5641 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 5642 if(pSiS->sis6326tvplug != -1) { 5643 pSiS->SiS6326Flags &= ~(SIS6326_TVSVIDEO | SIS6326_TVCVBS); 5644 pSiS->SiS6326Flags |= SIS6326_TVDETECTED; 5645 if(pSiS->sis6326tvplug == 1) pSiS->SiS6326Flags |= SIS6326_TVCVBS; 5646 else pSiS->SiS6326Flags |= SIS6326_TVSVIDEO; 5647 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5648 "SiS6326 TV plug type detection overruled by %s\n", 5649 (pSiS->SiS6326Flags & SIS6326_TVCVBS) ? "COMPOSITE" : "SVIDEO"); 5650 } 5651 } 5652 5653 /* Do some checks */ 5654 if(pSiS->OptTVOver != -1) { 5655 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 5656 pSiS->UseCHOverScan = pSiS->OptTVOver; 5657 } else { 5658 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5659 "CHTVOverscan only supported on CHRONTEL 70xx\n"); 5660 pSiS->UseCHOverScan = -1; 5661 } 5662 } else pSiS->UseCHOverScan = -1; 5663 5664 if(pSiS->sistvedgeenhance != -1) { 5665 if(!(pSiS->VBFlags2 & VB2_301)) { 5666 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5667 "SISTVEdgeEnhance only supported on SiS301\n"); 5668 pSiS->sistvedgeenhance = -1; 5669 } 5670 } 5671 if(pSiS->sistvsaturation != -1) { 5672 if(pSiS->VBFlags2 & VB2_301) { 5673 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5674 "SISTVSaturation not supported on SiS301\n"); 5675 pSiS->sistvsaturation = -1; 5676 } 5677 } 5678 5679 /* Do some MergedFB mode initialisation */ 5680#ifdef SISMERGED 5681 if(pSiS->MergedFB) { 5682 pSiS->CRT2pScrn = xalloc(sizeof(ScrnInfoRec)); 5683 if(!pSiS->CRT2pScrn) { 5684 SISErrorLog(pScrn, "Failed to allocate memory for 2nd pScrn, %s\n", mergeddisstr); 5685 pSiS->MergedFB = FALSE; 5686 } else { 5687 memcpy(pSiS->CRT2pScrn, pScrn, sizeof(ScrnInfoRec)); 5688 } 5689 } 5690#endif 5691 5692 /* Determine CRT1<>CRT2 mode 5693 * Note: When using VESA or if the bridge is in slavemode, display 5694 * is ALWAYS in MIRROR_MODE! 5695 * This requires extra checks in functions using this flag! 5696 * (see sis_video.c for example) 5697 */ 5698 if(pSiS->VBFlags & DISPTYPE_DISP2) { 5699 if(pSiS->CRT1off) { /* CRT2 only ------------------------------- */ 5700#ifdef SISDUALHEAD 5701 if(pSiS->DualHeadMode) { 5702 SISErrorLog(pScrn, 5703 "CRT1 not detected or forced off. Dual Head mode can't initialize.\n"); 5704 if(pSiSEnt) pSiSEnt->DisableDual = TRUE; 5705 goto my_error_1; 5706 } 5707#endif 5708#ifdef SISMERGED 5709 if(pSiS->MergedFB) { 5710 if(pSiS->MergedFBAuto) { 5711 xf86DrvMsg(pScrn->scrnIndex, X_INFO, mergednocrt1, mergeddisstr); 5712 } else { 5713 SISErrorLog(pScrn, mergednocrt1, mergeddisstr); 5714 } 5715 if(pSiS->CRT2pScrn) xfree(pSiS->CRT2pScrn); 5716 pSiS->CRT2pScrn = NULL; 5717 pSiS->MergedFB = FALSE; 5718 } 5719#endif 5720 pSiS->VBFlags |= VB_DISPMODE_SINGLE; 5721 /* No CRT1? Then we use the video overlay on CRT2 */ 5722 pSiS->XvOnCRT2 = TRUE; 5723 } else /* CRT1 and CRT2 - mirror or dual head ----- */ 5724#ifdef SISDUALHEAD 5725 if(pSiS->DualHeadMode) { 5726 pSiS->VBFlags |= (VB_DISPMODE_DUAL | DISPTYPE_CRT1); 5727 if(pSiS->VESA != -1) { 5728 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5729 "VESA option not used in Dual Head mode. VESA disabled.\n"); 5730 } 5731 if(pSiSEnt) pSiSEnt->DisableDual = FALSE; 5732 pSiS->VESA = 0; 5733 } else 5734#endif 5735#ifdef SISMERGED 5736 if(pSiS->MergedFB) { 5737 pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_CRT1); 5738 if(pSiS->VESA != -1) { 5739 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5740 "VESA option not used in MergedFB mode. VESA disabled.\n"); 5741 } 5742 pSiS->VESA = 0; 5743 } else 5744#endif 5745 pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_CRT1); 5746 } else { /* CRT1 only ------------------------------- */ 5747#ifdef SISDUALHEAD 5748 if(pSiS->DualHeadMode) { 5749 SISErrorLog(pScrn, 5750 "No CRT2 output selected or no bridge detected. " 5751 "Dual Head mode can't initialize.\n"); 5752 goto my_error_1; 5753 } 5754#endif 5755#ifdef SISMERGED 5756 if(pSiS->MergedFB) { 5757 if(pSiS->MergedFBAuto) { 5758 xf86DrvMsg(pScrn->scrnIndex, X_INFO, mergednocrt2, mergeddisstr); 5759 } else { 5760 SISErrorLog(pScrn, mergednocrt2, mergeddisstr); 5761 } 5762 if(pSiS->CRT2pScrn) xfree(pSiS->CRT2pScrn); 5763 pSiS->CRT2pScrn = NULL; 5764 pSiS->MergedFB = FALSE; 5765 } 5766#endif 5767 pSiS->VBFlags |= (VB_DISPMODE_SINGLE | DISPTYPE_CRT1); 5768 } 5769 5770 if((pSiS->VGAEngine == SIS_315_VGA) || (pSiS->VGAEngine == SIS_300_VGA)) { 5771 if((!pSiS->NoXvideo) && 5772 (!pSiS->hasTwoOverlays) && 5773 (!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY))) { 5774 xf86DrvMsg(pScrn->scrnIndex, from, 5775 "Using Xv overlay by default on CRT%d\n", 5776 pSiS->XvOnCRT2 ? 2 : 1); 5777 } 5778 } 5779 5780 /* Init ptrs for Save/Restore functions and calc MaxClock */ 5781 SISDACPreInit(pScrn); 5782 5783 /* ********** end of VBFlags setup ********** */ 5784 5785 /* VBFlags are initialized now. Back them up for SlaveMode modes. */ 5786 pSiS->VBFlags_backup = pSiS->VBFlags; 5787 5788 /* Backup CR32,36,37 (in order to write them back after a VT switch) */ 5789 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5790 inSISIDXREG(SISCR,0x32,pSiS->myCR32); 5791 inSISIDXREG(SISCR,0x36,pSiS->myCR36); 5792 inSISIDXREG(SISCR,0x37,pSiS->myCR37); 5793 } 5794 5795 /* Find out about paneldelaycompensation and evaluate option */ 5796#ifdef SISDUALHEAD 5797 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) { 5798#endif 5799 if(pSiS->VGAEngine == SIS_300_VGA) { 5800 5801 if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) { 5802 5803 /* Save the current PDC if the panel is used at the moment. 5804 * This seems by far the safest way to find out about it. 5805 * If the system is using an old version of sisfb, we can't 5806 * trust the pdc register value. If sisfb saved the pdc for 5807 * us, use it. 5808 */ 5809 if(pSiS->sisfbpdc != 0xff) { 5810 pSiS->SiS_Pr->PDC = pSiS->sisfbpdc; 5811 } else { 5812 if(!(pSiS->donttrustpdc)) { 5813 UChar tmp; 5814 inSISIDXREG(SISCR, 0x30, tmp); 5815 if(tmp & 0x20) { 5816 inSISIDXREG(SISPART1, 0x13, pSiS->SiS_Pr->PDC); 5817 } else { 5818 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5819 "Unable to detect LCD PanelDelayCompensation, LCD is not active\n"); 5820 } 5821 } else { 5822 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5823 "Unable to detect LCD PanelDelayCompensation, please update sisfb\n"); 5824 } 5825 } 5826 if(pSiS->SiS_Pr->PDC != -1) { 5827 pSiS->SiS_Pr->PDC &= 0x3c; 5828 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5829 "Detected LCD PanelDelayCompensation 0x%02x\n", 5830 pSiS->SiS_Pr->PDC); 5831 } 5832 5833 /* If we haven't been able to find out, use our other methods */ 5834 if(pSiS->SiS_Pr->PDC == -1) { 5835 int i=0; 5836 do { 5837 if(mypdctable[i].subsysVendor == pSiS->PciInfo->subsysVendor && 5838 mypdctable[i].subsysCard == pSiS->PciInfo->subsysCard) { 5839 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5840 "PCI card/vendor identified for non-default PanelDelayCompensation\n"); 5841 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5842 "Vendor: %s, card: %s (ID %04x), PanelDelayCompensation: 0x%02x\n", 5843 mypdctable[i].vendorName, mypdctable[i].cardName, 5844 pSiS->PciInfo->subsysCard, mypdctable[i].pdc); 5845 if(pSiS->PDC == -1) { 5846 pSiS->PDC = mypdctable[i].pdc; 5847 } else { 5848 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5849 "PanelDelayCompensation overruled by option\n"); 5850 } 5851 break; 5852 } 5853 i++; 5854 } while(mypdctable[i].subsysVendor != 0); 5855 } 5856 5857 if(pSiS->PDC != -1) { 5858 if(pSiS->BIOS) { 5859 if(pSiS->VBFlags2 & VB2_LVDS) { 5860 if(pSiS->BIOS[0x220] & 0x80) { 5861 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5862 "BIOS uses OEM LCD Panel Delay Compensation 0x%02x\n", 5863 pSiS->BIOS[0x220] & 0x3c); 5864 pSiS->BIOS[0x220] &= 0x7f; 5865 } 5866 } 5867 if(pSiS->VBFlags2 & (VB2_301B | VB2_302B)) { 5868 if(pSiS->BIOS[0x220] & 0x80) { 5869 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5870 "BIOS uses OEM LCD Panel Delay Compensation 0x%02x\n", 5871 ( (pSiS->VBLCDFlags & VB_LCD_1280x1024) ? 5872 pSiS->BIOS[0x223] : pSiS->BIOS[0x224] ) & 0x3c); 5873 pSiS->BIOS[0x220] &= 0x7f; 5874 } 5875 } 5876 } 5877 pSiS->SiS_Pr->PDC = (pSiS->PDC & 0x3c); 5878 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5879 "Using LCD Panel Delay Compensation 0x%02x\n", pSiS->SiS_Pr->PDC); 5880 } 5881 } 5882 5883 } /* SIS_300_VGA */ 5884 5885 if(pSiS->VGAEngine == SIS_315_VGA) { 5886 5887 UChar tmp, tmp2; 5888 inSISIDXREG(SISCR, 0x30, tmp); 5889 5890 /* Save the current PDC if the panel is used at the moment. */ 5891 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) { 5892 5893 if(pSiS->sisfbpdc != 0xff) { 5894 pSiS->SiS_Pr->PDC = pSiS->sisfbpdc; 5895 } 5896 if(pSiS->sisfbpdca != 0xff) { 5897 pSiS->SiS_Pr->PDCA = pSiS->sisfbpdca; 5898 } 5899 5900 if(!pSiS->donttrustpdc) { 5901 if((pSiS->sisfbpdc == 0xff) && (pSiS->sisfbpdca == 0xff)) { 5902 CARD16 tempa, tempb; 5903 inSISIDXREG(SISPART1,0x2d,tmp2); 5904 tempa = (tmp2 & 0xf0) >> 3; 5905 tempb = (tmp2 & 0x0f) << 1; 5906 inSISIDXREG(SISPART1,0x20,tmp2); 5907 tempa |= ((tmp2 & 0x40) >> 6); 5908 inSISIDXREG(SISPART1,0x35,tmp2); 5909 tempb |= ((tmp2 & 0x80) >> 7); 5910 inSISIDXREG(SISPART1,0x13,tmp2); 5911 if(!pSiS->ROM661New) { 5912 if((tmp2 & 0x04) || (tmp & 0x20)) { 5913 pSiS->SiS_Pr->PDCA = tempa; 5914 pSiS->SiS_Pr->PDC = tempb; 5915 } else { 5916 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5917 "Unable to detect PanelDelayCompensation, LCD is not active\n"); 5918 } 5919 } else { 5920 if(tmp2 & 0x04) { 5921 pSiS->SiS_Pr->PDCA = tempa; 5922 } else if(tmp & 0x20) { 5923 pSiS->SiS_Pr->PDC = tempb; 5924 } else { 5925 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5926 "Unable to detect PanelDelayCompensation, LCD is not active\n"); 5927 } 5928 } 5929 } 5930 } else { 5931 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5932 "Unable to detect PanelDelayCompensation, please update sisfb\n"); 5933 } 5934 if(pSiS->SiS_Pr->PDC != -1) { 5935 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5936 "Detected LCD PanelDelayCompensation 0x%02x (for LCD=CRT2)\n", 5937 pSiS->SiS_Pr->PDC); 5938 } 5939 if(pSiS->SiS_Pr->PDCA != -1) { 5940 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5941 "Detected LCD PanelDelayCompensation1 0x%02x (for LCD=CRT1)\n", 5942 pSiS->SiS_Pr->PDCA); 5943 } 5944 } 5945 5946 /* Let user override (for all bridges) */ 5947 if(pSiS->VBFlags2 & VB2_30xBLV) { 5948 if(pSiS->PDC != -1) { 5949 pSiS->SiS_Pr->PDC = pSiS->PDC & 0x1f; 5950 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5951 "Using LCD PanelDelayCompensation 0x%02x (for LCD=CRT2)\n", 5952 pSiS->SiS_Pr->PDC); 5953 } 5954 if(pSiS->PDCA != -1) { 5955 pSiS->SiS_Pr->PDCA = pSiS->PDCA & 0x1f; 5956 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5957 "Using LCD PanelDelayCompensation1 0x%02x (for LCD=CRT1)\n", 5958 pSiS->SiS_Pr->PDCA); 5959 } 5960 } 5961 5962 /* Read the current EMI (if not overruled) */ 5963 if(pSiS->VBFlags2 & VB2_SISEMIBRIDGE) { 5964 MessageType from = X_PROBED; 5965 if(pSiS->EMI != -1) { 5966 pSiS->SiS_Pr->EMI_30 = (pSiS->EMI >> 24) & 0x60; 5967 pSiS->SiS_Pr->EMI_31 = (pSiS->EMI >> 16) & 0xff; 5968 pSiS->SiS_Pr->EMI_32 = (pSiS->EMI >> 8) & 0xff; 5969 pSiS->SiS_Pr->EMI_33 = pSiS->EMI & 0xff; 5970 pSiS->SiS_Pr->HaveEMI = pSiS->SiS_Pr->HaveEMILCD = TRUE; 5971 pSiS->SiS_Pr->OverruleEMI = TRUE; 5972 from = X_CONFIG; 5973 } else if((pSiS->sisfbfound) && (pSiS->sisfb_haveemi)) { 5974 pSiS->SiS_Pr->EMI_30 = pSiS->sisfb_emi30; 5975 pSiS->SiS_Pr->EMI_31 = pSiS->sisfb_emi31; 5976 pSiS->SiS_Pr->EMI_32 = pSiS->sisfb_emi32; 5977 pSiS->SiS_Pr->EMI_33 = pSiS->sisfb_emi33; 5978 pSiS->SiS_Pr->HaveEMI = TRUE; 5979 if(pSiS->sisfb_haveemilcd) pSiS->SiS_Pr->HaveEMILCD = TRUE; 5980 pSiS->SiS_Pr->OverruleEMI = FALSE; 5981 } else { 5982 inSISIDXREG(SISPART4, 0x30, pSiS->SiS_Pr->EMI_30); 5983 inSISIDXREG(SISPART4, 0x31, pSiS->SiS_Pr->EMI_31); 5984 inSISIDXREG(SISPART4, 0x32, pSiS->SiS_Pr->EMI_32); 5985 inSISIDXREG(SISPART4, 0x33, pSiS->SiS_Pr->EMI_33); 5986 pSiS->SiS_Pr->HaveEMI = TRUE; 5987 if(tmp & 0x20) pSiS->SiS_Pr->HaveEMILCD = TRUE; 5988 pSiS->SiS_Pr->OverruleEMI = FALSE; 5989 } 5990 xf86DrvMsg(pScrn->scrnIndex, from, 5991 "302LV/302ELV: Using EMI 0x%02x%02x%02x%02x%s\n", 5992 pSiS->SiS_Pr->EMI_30,pSiS->SiS_Pr->EMI_31, 5993 pSiS->SiS_Pr->EMI_32,pSiS->SiS_Pr->EMI_33, 5994 pSiS->SiS_Pr->HaveEMILCD ? " (LCD)" : ""); 5995 } 5996 5997 } /* SIS_315_VGA */ 5998#ifdef SISDUALHEAD 5999 } 6000#endif 6001 6002 6003 /* In dual head mode, both heads (currently) share the maxxfbmem equally. 6004 * If memory sharing is done differently, the following has to be changed; 6005 * the other modules (eg. accel and Xv) use dhmOffset for hardware 6006 * pointer settings relative to VideoRAM start and won't need to be changed. 6007 * 6008 * Addendum: dhmoffset is also used for skipping the UMA area on SiS76x. 6009 */ 6010 6011 pSiS->dhmOffset = pSiS->FbBaseOffset; 6012 pSiS->FbAddress += pSiS->dhmOffset; 6013 6014#ifdef SISDUALHEAD 6015 if(pSiS->DualHeadMode) { 6016 pSiS->FbAddress = pSiS->realFbAddress; 6017 if(!pSiS->SecondHead) { 6018 /* ===== First head (always CRT2) ===== */ 6019 /* We use only half of the memory available */ 6020 pSiS->maxxfbmem /= 2; 6021 /* dhmOffset is 0 (or LFB-base for SiS76x UMA skipping) */ 6022 pSiS->FbAddress += pSiS->dhmOffset; 6023 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 6024 "%dKB video RAM at 0x%lx available for master head (CRT2)\n", 6025 pSiS->maxxfbmem/1024, pSiS->FbAddress); 6026 } else { 6027 /* ===== Second head (always CRT1) ===== */ 6028 /* We use only half of the memory available */ 6029 pSiS->maxxfbmem /= 2; 6030 /* Initialize dhmOffset */ 6031 pSiS->dhmOffset += pSiS->maxxfbmem; 6032 /* Adapt FBAddress */ 6033 pSiS->FbAddress += pSiS->dhmOffset; 6034 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 6035 "%dKB video RAM at 0x%lx available for slave head (CRT1)\n", 6036 pSiS->maxxfbmem/1024, pSiS->FbAddress); 6037 } 6038 } 6039#endif 6040 6041 /* Note: Do not use availMem for anything from now. Use 6042 * maxxfbmem instead. (availMem does not take dual head 6043 * mode into account.) 6044 */ 6045 6046 if(pSiS->FbBaseOffset) { 6047 /* Doubt that the DRM memory manager can deal 6048 * with a heap start of 0... 6049 */ 6050 pSiS->DRIheapstart = 16; 6051 pSiS->DRIheapend = pSiS->FbBaseOffset; 6052 } else { 6053 pSiS->DRIheapstart = pSiS->maxxfbmem; 6054 pSiS->DRIheapend = pSiS->availMem; 6055 } 6056#ifdef SISDUALHEAD 6057 if(pSiS->DualHeadMode) { 6058 pSiS->DRIheapstart = pSiS->DRIheapend = 0; 6059 } else 6060#endif 6061 if(pSiS->DRIheapstart >= pSiS->DRIheapend) { 6062#if 0 /* For future use */ 6063 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6064 "No memory for DRI heap. Please set the option \"MaxXFBMem\" to\n" 6065 "\tlimit the memory X should use and leave the rest to DRI\n"); 6066#endif 6067 pSiS->DRIheapstart = pSiS->DRIheapend = 0; 6068 } 6069 6070 /* Now for something completely different: DDC. 6071 * For 300 and 315/330/340 series, we provide our 6072 * own functions (in order to probe CRT2 as well) 6073 * If these fail, use the VBE. 6074 * All other chipsets will use VBE. No need to re-invent 6075 * the wheel there. 6076 */ 6077 6078 pSiS->pVbe = NULL; 6079 didddc2 = FALSE; 6080 6081 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 6082 if(xf86LoadSubModule(pScrn, "ddc")) { 6083 int crtnum = 0; 6084 xf86LoaderReqSymLists(ddcSymbols, NULL); 6085 if((pMonitor = SiSDoPrivateDDC(pScrn, &crtnum))) { 6086 didddc2 = TRUE; 6087 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcsstr, crtnum); 6088 xf86PrintEDID(pMonitor); 6089 xf86SetDDCproperties(pScrn, pMonitor); 6090 pScrn->monitor->DDC = pMonitor; 6091 /* Now try to find out aspect ratio */ 6092 SiSFindAspect(pScrn, pMonitor, crtnum); 6093 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcestr, crtnum); 6094 } 6095 } 6096 } 6097 6098#ifdef SISDUALHEAD 6099 /* In dual head mode, probe DDC using VBE only for CRT1 (second head) */ 6100 if((pSiS->DualHeadMode) && (!didddc2) && (!pSiS->SecondHead)) { 6101 didddc2 = TRUE; 6102 } 6103#endif 6104 6105 if(!didddc2) { 6106 /* If CRT1 is off or LCDA, skip DDC via VBE */ 6107 if((pSiS->CRT1off) || (pSiS->VBFlags & CRT1_LCDA)) { 6108 didddc2 = TRUE; 6109 } 6110 } 6111 6112 /* Now (re-)load and initialize the DDC module */ 6113 if(!didddc2) { 6114 6115 if(xf86LoadSubModule(pScrn, "ddc")) { 6116 6117 xf86LoaderReqSymLists(ddcSymbols, NULL); 6118 6119 /* Now load and initialize VBE module. */ 6120 SiS_LoadInitVBE(pScrn); 6121 6122 if(pSiS->pVbe) { 6123 if((pMonitor = vbeDoEDID(pSiS->pVbe,NULL))) { 6124 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 6125 "VBE CRT1 DDC monitor info:\n"); 6126 xf86SetDDCproperties(pScrn, xf86PrintEDID(pMonitor)); 6127 pScrn->monitor->DDC = pMonitor; 6128 /* Now try to find out aspect ratio */ 6129 SiSFindAspect(pScrn, pMonitor, 1); 6130 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 6131 "End of VBE CRT1 DDC monitor info\n"); 6132 } 6133 } else { 6134 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6135 "Failed to read DDC data\n"); 6136 } 6137 } 6138 } 6139 6140#ifdef SISMERGED 6141 if(pSiS->MergedFB) { 6142 pSiS->CRT2pScrn->monitor = xalloc(sizeof(MonRec)); 6143 if(pSiS->CRT2pScrn->monitor) { 6144 DisplayModePtr tempm = NULL, currentm = NULL, newm = NULL; 6145 memcpy(pSiS->CRT2pScrn->monitor, pScrn->monitor, sizeof(MonRec)); 6146 pSiS->CRT2pScrn->monitor->DDC = NULL; 6147 pSiS->CRT2pScrn->monitor->Modes = NULL; 6148 pSiS->CRT2pScrn->monitor->id = (char *)crt2monname; 6149 tempm = pScrn->monitor->Modes; 6150 while(tempm) { 6151 if(!(newm = xalloc(sizeof(DisplayModeRec)))) break; 6152 memcpy(newm, tempm, sizeof(DisplayModeRec)); 6153 if(!(newm->name = xalloc(strlen(tempm->name) + 1))) { 6154 xfree(newm); 6155 break; 6156 } 6157 strcpy(newm->name, tempm->name); 6158 if(!pSiS->CRT2pScrn->monitor->Modes) pSiS->CRT2pScrn->monitor->Modes = newm; 6159 if(currentm) { 6160 currentm->next = newm; 6161 newm->prev = currentm; 6162 } 6163 currentm = newm; 6164 tempm = tempm->next; 6165 } 6166 if(pSiS->CRT2HSync) { 6167 pSiS->CRT2pScrn->monitor->nHsync = 6168 SiSStrToRanges(pSiS->CRT2pScrn->monitor->hsync, pSiS->CRT2HSync, MAX_HSYNC); 6169 } 6170 if(pSiS->CRT2VRefresh) { 6171 pSiS->CRT2pScrn->monitor->nVrefresh = 6172 SiSStrToRanges(pSiS->CRT2pScrn->monitor->vrefresh, pSiS->CRT2VRefresh, MAX_VREFRESH); 6173 } 6174 if((pMonitor = SiSInternalDDC(pSiS->CRT2pScrn, 1))) { 6175 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcsstr, 2); 6176 xf86PrintEDID(pMonitor); 6177 xf86SetDDCproperties(pSiS->CRT2pScrn, pMonitor); 6178 pSiS->CRT2pScrn->monitor->DDC = pMonitor; 6179 /* Now try to find out aspect ratio */ 6180 SiSFindAspect(pScrn, pMonitor, 2); 6181 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcestr, 2); 6182 /* use DDC data if no ranges in config file */ 6183 if(!pSiS->CRT2HSync) { 6184 pSiS->CRT2pScrn->monitor->nHsync = 0; 6185 } 6186 if(!pSiS->CRT2VRefresh) { 6187 pSiS->CRT2pScrn->monitor->nVrefresh = 0; 6188 } 6189 } else { 6190 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 6191 "Failed to read DDC data for CRT2\n"); 6192 } 6193 } else { 6194 SISErrorLog(pScrn, "Failed to allocate memory for CRT2 monitor, %s.\n", 6195 mergeddisstr); 6196 if(pSiS->CRT2pScrn) xfree(pSiS->CRT2pScrn); 6197 pSiS->CRT2pScrn = NULL; 6198 pSiS->MergedFB = FALSE; 6199 } 6200 } 6201#endif 6202 6203 /* Copy our detected monitor gammas, part 1. Note that device redetection 6204 * is not supported in DHM, so there is no need to do that anytime later. 6205 */ 6206#ifdef SISDUALHEAD 6207 if(pSiS->DualHeadMode) { 6208 if(!pSiS->SecondHead) { 6209 /* CRT2: Got gamma for LCD or VGA2 */ 6210 pSiSEnt->CRT2VGAMonitorGamma = pSiS->CRT2VGAMonitorGamma; 6211 } else { 6212 /* CRT1: Got gamma for LCD or VGA */ 6213 pSiSEnt->CRT1VGAMonitorGamma = pSiS->CRT1VGAMonitorGamma; 6214 } 6215 if(pSiS->CRT2LCDMonitorGamma) pSiSEnt->CRT2LCDMonitorGamma = pSiS->CRT2LCDMonitorGamma; 6216 } 6217#endif 6218 6219 /* end of DDC */ 6220 6221 /* From here, we mainly deal with clocks and modes */ 6222 6223#ifdef SISMERGED 6224 if(pSiS->MergedFB) xf86DrvMsg(pScrn->scrnIndex, X_INFO, crtsetupstr, 1); 6225#endif 6226 6227 /* Set the min pixel clock */ 6228 pSiS->MinClock = 5000; 6229 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 6230 pSiS->MinClock = 10000; 6231 } 6232 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n", 6233 pSiS->MinClock / 1000); 6234 6235 /* If the user has specified ramdac speed in the config 6236 * file, we respect that setting. 6237 */ 6238 from = X_PROBED; 6239 if(pSiS->pEnt->device->dacSpeeds[0]) { 6240 int speed = 0; 6241 switch(pScrn->bitsPerPixel) { 6242 case 8: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP8]; 6243 break; 6244 case 16: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP16]; 6245 break; 6246 case 24: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP24]; 6247 break; 6248 case 32: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP32]; 6249 break; 6250 } 6251 if(speed == 0) pSiS->MaxClock = pSiS->pEnt->device->dacSpeeds[0]; 6252 else pSiS->MaxClock = speed; 6253 from = X_CONFIG; 6254 } 6255 xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n", 6256 pSiS->MaxClock / 1000); 6257 6258 /* 6259 * Setup the ClockRanges, which describe what clock ranges are available, 6260 * and what sort of modes they can be used for. 6261 */ 6262 clockRanges = xnfcalloc(sizeof(ClockRange), 1); 6263 clockRanges->next = NULL; 6264 clockRanges->minClock = pSiS->MinClock; 6265 clockRanges->maxClock = pSiS->MaxClock; 6266 clockRanges->clockIndex = -1; /* programmable */ 6267 clockRanges->interlaceAllowed = TRUE; 6268 clockRanges->doubleScanAllowed = TRUE; 6269 6270 /* 6271 * Since we have lots of built-in modes for 300/315/330/340 series 6272 * with vb support, we replace the given default mode list with our 6273 * own. In case the video bridge is to be used, we only allow other 6274 * modes if 6275 * -) vbtype is 301, 301B, 301C or 302B, and 6276 * -) crt2 device is not TV, and 6277 * -) crt1 is not LCDA, unless bridge is TMDS/LCDA capable (301C) 6278 */ 6279 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 6280 if(!(pSiS->noInternalModes)) { 6281 Bool acceptcustommodes = TRUE; /* Accept user modelines */ 6282 Bool includelcdmodes = TRUE; /* Include modes reported by DDC */ 6283 Bool isfordvi = FALSE; /* Is for digital DVI output */ 6284 Bool fakecrt2modes = FALSE; /* Fake some modes for CRT2 */ 6285 Bool IsForCRT2 = FALSE; 6286 if(pSiS->UseVESA) { 6287 acceptcustommodes = FALSE; 6288 includelcdmodes = FALSE; 6289 } 6290#ifdef SISDUALHEAD /* Dual head is static. Output devices will not change. */ 6291 if(pSiS->DualHeadMode) { 6292 if(!pSiS->SecondHead) { /* CRT2: */ 6293 if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 6294 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 6295 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA))) includelcdmodes = FALSE; 6296 if(pSiS->VBFlags & CRT2_LCD) isfordvi = TRUE; 6297 if(pSiS->VBFlags & CRT2_TV) acceptcustommodes = FALSE; 6298 } else { 6299 if(pSiS->VBFlags & (CRT2_TV|CRT2_LCD)) { 6300 acceptcustommodes = FALSE; 6301 includelcdmodes = FALSE; 6302 fakecrt2modes = TRUE; 6303 } 6304 } 6305 } else { 6306 acceptcustommodes = FALSE; 6307 includelcdmodes = FALSE; 6308 if(pSiS->VBFlags & (CRT2_TV|CRT2_LCD)) { 6309 fakecrt2modes = TRUE; 6310 } 6311 } 6312 clockRanges->interlaceAllowed = FALSE; 6313 IsForCRT2 = TRUE; 6314 } else { /* CRT1: */ 6315 if(pSiS->VBFlags & CRT1_LCDA) { 6316 if(!(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 6317 acceptcustommodes = FALSE; 6318 includelcdmodes = FALSE; 6319 fakecrt2modes = TRUE; 6320 /* Will handle i-lace in mode-switching code */ 6321 } else { 6322 isfordvi = TRUE; 6323 /* Don't allow i-lace modes */ 6324 clockRanges->interlaceAllowed = FALSE; 6325 } 6326 } else { 6327 includelcdmodes = FALSE; 6328 } 6329 } 6330 } else 6331#endif 6332#ifdef SISMERGED /* MergedFB mode is not static. Output devices may change. */ 6333 if(pSiS->MergedFB) { 6334 if(pSiS->VBFlags & CRT1_LCDA) { 6335 if(!(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 6336 acceptcustommodes = FALSE; 6337 includelcdmodes = FALSE; 6338 fakecrt2modes = TRUE; 6339 /* Will handle i-lace in mode-switching code */ 6340 } else { 6341 isfordvi = TRUE; 6342 /* Don't allow i-lace custom modes */ 6343 clockRanges->interlaceAllowed = FALSE; 6344 } 6345 } else { 6346 includelcdmodes = FALSE; 6347 } 6348 } else 6349#endif /* Mirror mode is not static. Output devices may change. */ 6350 if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 6351 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 6352 if(!(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 6353 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA))) includelcdmodes = FALSE; 6354 if(pSiS->VBFlags & CRT2_LCD) isfordvi = TRUE; 6355 } else { 6356 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA|CRT1_LCDA))) includelcdmodes = FALSE; 6357 if(pSiS->VBFlags & (CRT2_LCD|CRT1_LCDA)) isfordvi = TRUE; 6358 } 6359 if((!(pSiS->VBFlags & DISPTYPE_CRT1)) && (!(pSiS->VBFlags & CRT1_LCDA))) { 6360 IsForCRT2 = TRUE; 6361 } 6362 /* Allow user modes, even if CRT2 is TV. Will be filtered through ValidMode(); 6363 * leaving the user modes here might have the advantage that such a mode, if 6364 * it matches in resolution with a supported TV mode, allows us to drive eg. 6365 * non standard panels, and still permits switching to TV. This mode will be 6366 * "mapped" to a supported mode of identical resolution for TV. All this is 6367 * taken care of by ValidMode() and ModeInit()/PresetMode(). 6368 */ 6369 } else { 6370 if(pSiS->VBFlags & (CRT2_TV|CRT2_LCD)) { 6371 acceptcustommodes = FALSE; 6372 includelcdmodes = FALSE; 6373 if(!(pSiS->VBFlags & DISPTYPE_CRT1)) { 6374 fakecrt2modes = TRUE; 6375 IsForCRT2 = TRUE; 6376 } 6377 } 6378 } 6379 } else if(pSiS->VBFlags & (CRT2_ENABLE | CRT1_LCDA)) { 6380 acceptcustommodes = FALSE; 6381 includelcdmodes = FALSE; 6382 if((pSiS->VBFlags & CRT1_LCDA) || (!(pSiS->VBFlags & DISPTYPE_CRT1))) { 6383 fakecrt2modes = TRUE; 6384 IsForCRT2 = TRUE; 6385 } 6386 } else { 6387 includelcdmodes = FALSE; 6388 } 6389 /* Ignore interlace, mode switching code will handle this */ 6390 6391 pSiS->HaveCustomModes = FALSE; 6392 if(SiSMakeOwnModeList(pScrn, acceptcustommodes, includelcdmodes, 6393 isfordvi, &pSiS->HaveCustomModes, FALSE /*fakecrt2modes*/, IsForCRT2)) { 6394 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6395 "Replaced %s mode list with built-in modes\n", 6396 pSiS->HaveCustomModes ? "default" : "entire"); 6397 if(pSiS->VGAEngine == SIS_315_VGA) { 6398 int UseWide = pSiS->SiS_Pr->SiS_UseWide; 6399 if(IsForCRT2) UseWide = pSiS->SiS_Pr->SiS_UseWideCRT2; 6400 if((!IsForCRT2) || (pSiS->VBFlags2 & VB2_SISVGA2BRIDGE)) { 6401 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6402 "Using %s widescreen modes for CRT%d VGA devices\n", 6403 UseWide ? "real" : "fake", IsForCRT2 ? 2 : 1); 6404 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6405 "\tUse option \"ForceCRT%dVGAAspect\" to overrule\n", 6406 IsForCRT2 ? 2 : 1); 6407 } 6408 } 6409#ifdef TWDEBUG 6410 pScrn->modes = pScrn->monitor->Modes; 6411 xf86PrintModes(pScrn); 6412 pScrn->modes = NULL; 6413#endif 6414 } else { 6415 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 6416 "Building list of built-in modes failed, using server defaults\n"); 6417 } 6418 } else { 6419 pSiS->HaveCustomModes = TRUE; 6420 } 6421 } 6422 6423 /* Add our built-in hi-res and TV modes on the 6326 */ 6424 if(pSiS->Chipset == PCI_CHIP_SIS6326) { 6425 if(pScrn->bitsPerPixel == 8) { 6426 SiS6326SIS1600x1200_60Mode.next = pScrn->monitor->Modes; 6427 pScrn->monitor->Modes = &SiS6326SIS1600x1200_60Mode; 6428 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6429 "Adding mode \"SIS1600x1200-60\" (depth 8 only)\n"); 6430 } 6431 if(pScrn->bitsPerPixel <= 16) { 6432 SiS6326SIS1280x1024_75Mode.next = pScrn->monitor->Modes; 6433 pScrn->monitor->Modes = &SiS6326SIS1280x1024_75Mode; 6434 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6435 "Adding mode \"SIS1280x1024-75\" (depths 8, 15 and 16 only)\n"); 6436 } 6437 if((pSiS->SiS6326Flags & SIS6326_HASTV) && 6438 (pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 6439 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6440 "Adding %s TV modes to mode list:\n", 6441 (pSiS->SiS6326Flags & SIS6326_TVPAL) ? "PAL" : "NTSC"); 6442 if(pSiS->SiS6326Flags & SIS6326_TVPAL) { 6443 SiS6326PAL800x600Mode.next = pScrn->monitor->Modes; 6444 pScrn->monitor->Modes = &SiS6326PAL640x480Mode; 6445 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6446 "\t\"PAL800x600\" \"PAL800x600U\" \"PAL720x540\" \"PAL640x480\"\n"); 6447 } else { 6448 SiS6326NTSC640x480Mode.next = pScrn->monitor->Modes; 6449 pScrn->monitor->Modes = &SiS6326NTSC640x400Mode; 6450 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6451 "\t\"NTSC640x480\" \"NTSC640x480U\" \"NTSC640x400\"\n"); 6452 } 6453 } 6454 } 6455 6456 /* If there is no HSync or VRefresh data for the monitor, 6457 * derive it from DDC data. Essentially done by common layer 6458 * since 4.3.99.14, but this is not usable since it is done 6459 * too late (in ValidateModes()). 6460 * Addendum: I overrule the ranges now in any case unless 6461 * it would affect a CRT output device or DDC data is available. 6462 * Hence, for LCD(A) and TV, we always get proper ranges. This 6463 * is entirely harmless. However, option "NoOverruleRanges" will 6464 * disable this behavior. 6465 * This should "fix" the - by far - most common configuration 6466 * mistakes. 6467 */ 6468 6469 crt1freqoverruled = FALSE; 6470 6471 fromDDC = FALSE; 6472 if((pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6473 if((pScrn->monitor->nHsync <= 0) && (pScrn->monitor->DDC)) { 6474 SiSSetSyncRangeFromEdid(pScrn, 1); 6475 if(pScrn->monitor->nHsync > 0) { 6476 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subshstr, 6477#ifdef SISDUALHEAD 6478 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6479#endif 6480 pSiS->CRT1off ? 2 : 1); 6481 fromDDC = TRUE; 6482 } 6483 } 6484 if((pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6485 if(SiSAllowSyncOverride(pSiS, fromDDC)) { 6486 Bool HaveNoRanges = (pScrn->monitor->nHsync <= 0); 6487 /* Set sane ranges for LCD and TV 6488 * (our strict checking will filter out invalid ones anyway) 6489 */ 6490 if((crt1freqoverruled = CheckAndOverruleH(pScrn, pScrn->monitor))) { 6491 xf86DrvMsg(pScrn->scrnIndex, X_INFO, saneh, 6492 HaveNoRanges ? "missing" : "bogus", 6493#ifdef SISDUALHEAD 6494 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6495#endif 6496 pSiS->CRT1off ? 2 : 1); 6497 } 6498 } 6499 } 6500 } 6501 6502 fromDDC = FALSE; 6503 if((pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6504 if((pScrn->monitor->nVrefresh <= 0) && (pScrn->monitor->DDC)) { 6505 SiSSetSyncRangeFromEdid(pScrn, 0); 6506 if(pScrn->monitor->nVrefresh > 0) { 6507 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subsvstr, 6508#ifdef SISDUALHEAD 6509 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6510#endif 6511 pSiS->CRT1off ? 2 : 1); 6512 fromDDC = TRUE; 6513 } 6514 } 6515 if((pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6516 if(SiSAllowSyncOverride(pSiS, fromDDC)) { 6517 Bool HaveNoRanges = (pScrn->monitor->nVrefresh <= 0); 6518 /* Set sane ranges for LCD and TV */ 6519 if((crt1freqoverruled = CheckAndOverruleV(pScrn, pScrn->monitor))) { 6520 xf86DrvMsg(pScrn->scrnIndex, X_INFO, sanev, 6521 HaveNoRanges ? "missing" : "bogus", 6522#ifdef SISDUALHEAD 6523 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6524#endif 6525 pSiS->CRT1off ? 2 : 1); 6526 } 6527 } 6528 } 6529 } 6530 6531 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 6532 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6533 "\"Unknown reason\" in the following list means that the mode\n"); 6534 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6535 "is not supported on the chipset/bridge/current output device.\n"); 6536 } 6537 6538 /* 6539 * xf86ValidateModes will check that the mode HTotal and VTotal values 6540 * don't exceed the chipset's limit if pScrn->maxHValue and 6541 * pScrn->maxVValue are set. Since our SISValidMode() already takes 6542 * care of this, we don't worry about setting them here. 6543 */ 6544 6545 /* Select valid modes from those available */ 6546 /* 6547 * Assuming min pitch 256, min height 128 6548 */ 6549 { 6550 int minpitch, maxpitch, minheight, maxheight; 6551 pointer backupddc = pScrn->monitor->DDC; 6552 6553 minpitch = 256; 6554 minheight = 128; 6555 switch(pSiS->VGAEngine) { 6556 case SIS_OLD_VGA: 6557 case SIS_530_VGA: 6558 maxpitch = 2040; 6559 maxheight = 2048; 6560 break; 6561 case SIS_300_VGA: 6562 case SIS_315_VGA: 6563 maxpitch = 4088; 6564 maxheight = 4096; 6565 break; 6566 default: 6567 maxpitch = 2048; 6568 maxheight = 2048; 6569 break; 6570 } 6571 6572#ifdef SISMERGED 6573 pSiS->CheckForCRT2 = FALSE; 6574#endif 6575 6576 /* Suppress bogus DDC warning */ 6577 if(crt1freqoverruled) pScrn->monitor->DDC = NULL; 6578 6579 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 6580 pScrn->display->modes, clockRanges, NULL, 6581 minpitch, maxpitch, 6582 pScrn->bitsPerPixel * 8, 6583 minheight, maxheight, 6584 pScrn->display->virtualX, 6585 pScrn->display->virtualY, 6586 pSiS->maxxfbmem, 6587 LOOKUP_BEST_REFRESH); 6588 6589 pScrn->monitor->DDC = backupddc; 6590 } 6591 6592 if(i == -1) { 6593 SISErrorLog(pScrn, "xf86ValidateModes() error\n"); 6594 goto my_error_1; 6595 } 6596 6597 /* Check the virtual screen against the available memory */ 6598 { 6599 ULong memreq = (pScrn->virtualX * ((pScrn->bitsPerPixel + 7) / 8)) * pScrn->virtualY; 6600 6601 if(memreq > pSiS->maxxfbmem) { 6602 SISErrorLog(pScrn, 6603 "Virtual screen too big for memory; %ldK needed, %ldK available\n", 6604 memreq/1024, pSiS->maxxfbmem/1024); 6605 goto my_error_1; 6606 } 6607 } 6608 6609 /* Dual Head: 6610 * -) Go through mode list and mark all those modes as bad, 6611 * which are unsuitable for dual head mode. 6612 * -) Find the highest used pixelclock on the master head. 6613 */ 6614#ifdef SISDUALHEAD 6615 if((pSiS->DualHeadMode) && (!pSiS->SecondHead)) { 6616 6617 pSiSEnt->maxUsedClock = 0; 6618 6619 if((p = first = pScrn->modes)) { 6620 6621 do { 6622 6623 n = p->next; 6624 6625 /* Modes that require the bridge to operate in SlaveMode 6626 * are not suitable for Dual Head mode. 6627 */ 6628 if( (pSiS->VGAEngine == SIS_300_VGA) && 6629 ( (strcmp(p->name, "320x200") == 0) || 6630 (strcmp(p->name, "320x240") == 0) || 6631 (strcmp(p->name, "400x300") == 0) || 6632 (strcmp(p->name, "512x384") == 0) || 6633 (strcmp(p->name, "640x400") == 0) ) ) { 6634 p->status = MODE_BAD; 6635 xf86DrvMsg(pScrn->scrnIndex, X_INFO, notsuitablestr, p->name, "dual head"); 6636 } 6637 6638 /* Search for the highest clock on first head in order to calculate 6639 * max clock for second head (CRT1) 6640 */ 6641 if((p->status == MODE_OK) && (p->Clock > pSiSEnt->maxUsedClock)) { 6642 pSiSEnt->maxUsedClock = p->Clock; 6643 } 6644 6645 p = n; 6646 6647 } while (p != NULL && p != first); 6648 6649 } 6650 } 6651#endif 6652 6653 /* Prune the modes marked as invalid */ 6654 xf86PruneDriverModes(pScrn); 6655 6656 if(i == 0 || pScrn->modes == NULL) { 6657 SISErrorLog(pScrn, "No valid modes found - check VertRefresh/HorizSync\n"); 6658 goto my_error_1; 6659 } 6660 6661 xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 6662 6663 /* Set the current mode to the first in the list */ 6664 pScrn->currentMode = pScrn->modes; 6665 6666 /* Copy to CurrentLayout */ 6667 pSiS->CurrentLayout.mode = pScrn->currentMode; 6668 pSiS->CurrentLayout.displayWidth = pScrn->displayWidth; 6669 pSiS->CurrentLayout.displayHeight = pScrn->virtualY; 6670 6671#ifdef SISMERGED 6672 if(pSiS->MergedFB) { 6673 xf86DrvMsg(pScrn->scrnIndex, X_INFO, modesforstr, 1); 6674 } 6675#endif 6676 6677 /* Print the list of modes being used */ 6678 { 6679 Bool usemyprint = FALSE; 6680 6681#ifdef SISDUALHEAD 6682 if(pSiS->DualHeadMode) { 6683 if(pSiS->SecondHead) { 6684 if(pSiS->VBFlags & CRT1_LCDA) usemyprint = TRUE; 6685 } else { 6686 if(pSiS->VBFlags & (CRT2_LCD | CRT2_TV)) usemyprint = TRUE; 6687 } 6688 } else 6689#endif 6690#ifdef SISMERGED 6691 if(pSiS->MergedFB) { 6692 if(pSiS->VBFlags & CRT1_LCDA) usemyprint = TRUE; 6693 } else 6694#endif 6695 { 6696 if( (pSiS->VBFlags & (CRT2_LCD | CRT2_TV)) && 6697 (!(pSiS->VBFlags & DISPTYPE_DISP1)) ) 6698 usemyprint = TRUE; 6699 } 6700 6701 if(usemyprint) { 6702 SiSPrintModes(pScrn); 6703 } else { 6704 xf86PrintModes(pScrn); 6705 } 6706 } 6707 6708#ifdef SISMERGED 6709 if(pSiS->MergedFB) { 6710 Bool acceptcustommodes = TRUE; 6711 Bool includelcdmodes = TRUE; 6712 Bool isfordvi = FALSE; 6713 Bool fakecrt2modes = FALSE; 6714 6715 xf86DrvMsg(pScrn->scrnIndex, X_INFO, crtsetupstr, 2); 6716 6717 clockRanges->next = NULL; 6718 clockRanges->minClock = pSiS->MinClock; 6719 clockRanges->maxClock = SiSMemBandWidth(pSiS->CRT2pScrn, TRUE); 6720 clockRanges->clockIndex = -1; 6721 clockRanges->interlaceAllowed = FALSE; 6722 clockRanges->doubleScanAllowed = FALSE; 6723 if(pSiS->VGAEngine == SIS_315_VGA) { 6724 clockRanges->doubleScanAllowed = TRUE; 6725 } 6726 6727 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock for CRT2 is %d MHz\n", 6728 clockRanges->minClock / 1000); 6729 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Max pixel clock for CRT2 is %d MHz\n", 6730 clockRanges->maxClock / 1000); 6731 6732 if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 6733 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 6734 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA))) includelcdmodes = FALSE; 6735 if(pSiS->VBFlags & CRT2_LCD) isfordvi = TRUE; 6736 /* See above for a remark on handling CRT2 = TV */ 6737 } else { 6738 if(pSiS->VBFlags & (CRT2_LCD|CRT2_TV)) { 6739 includelcdmodes = FALSE; 6740 acceptcustommodes = FALSE; 6741 fakecrt2modes = TRUE; 6742 } 6743 } 6744 } else { 6745 includelcdmodes = FALSE; 6746 acceptcustommodes = FALSE; 6747 if(pSiS->VBFlags & (CRT2_LCD|CRT2_TV)) { 6748 fakecrt2modes = TRUE; 6749 } 6750 } 6751 6752 pSiS->HaveCustomModes2 = FALSE; 6753 if(!SiSMakeOwnModeList(pSiS->CRT2pScrn, acceptcustommodes, includelcdmodes, 6754 isfordvi, &pSiS->HaveCustomModes2, FALSE /* fakecrt2modes */, TRUE )) { 6755 6756 SISErrorLog(pScrn, "Building list of built-in modes for CRT2 failed, %s\n", 6757 mergeddisstr); 6758 SiSFreeCRT2Structs(pSiS); 6759 pSiS->MergedFB = FALSE; 6760 6761 } else { 6762 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6763 "Replaced %s mode list for CRT2 with built-in modes\n", 6764 pSiS->HaveCustomModes2 ? "default" : "entire"); 6765 if((pSiS->VGAEngine == SIS_315_VGA) && (pSiS->VBFlags2 & VB2_SISVGA2BRIDGE)) { 6766 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6767 "Using %s widescreen modes for CRT2 VGA devices\n", 6768 pSiS->SiS_Pr->SiS_UseWideCRT2 ? "real" : "fake"); 6769 } else pSiS->SiS_Pr->SiS_UseWideCRT2 = 0; 6770 } 6771 6772 } 6773 6774 if(pSiS->MergedFB) { 6775 6776 pointer backupddc; 6777 6778 crt2freqoverruled = FALSE; 6779 6780 fromDDC = FALSE; 6781 if((pSiS->CRT2pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6782 if((pSiS->CRT2pScrn->monitor->nHsync <= 0) && (pSiS->CRT2pScrn->monitor->DDC)) { 6783 SiSSetSyncRangeFromEdid(pSiS->CRT2pScrn, 1); 6784 if(pSiS->CRT2pScrn->monitor->nHsync > 0) { 6785 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subshstr, 2); 6786 fromDDC = TRUE; 6787 } 6788 } 6789 if((pSiS->CRT2pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6790 if( (pSiS->VBFlags & CRT2_TV) || 6791 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC)) ) { 6792 Bool HaveNoRanges = (pSiS->CRT2pScrn->monitor->nHsync <= 0); 6793 /* Set sane ranges for LCD and TV */ 6794 if((crt2freqoverruled = CheckAndOverruleH(pScrn, pSiS->CRT2pScrn->monitor))) { 6795 xf86DrvMsg(pScrn->scrnIndex, X_INFO, saneh, 6796 HaveNoRanges ? "missing" : "bogus", 2); 6797 } 6798 } 6799 } 6800 } 6801 6802 fromDDC = FALSE; 6803 if((pSiS->CRT2pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6804 if((pSiS->CRT2pScrn->monitor->nVrefresh <= 0) && (pSiS->CRT2pScrn->monitor->DDC)) { 6805 SiSSetSyncRangeFromEdid(pSiS->CRT2pScrn, 0); 6806 if(pSiS->CRT2pScrn->monitor->nVrefresh > 0) { 6807 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subsvstr, 2); 6808 fromDDC = TRUE; 6809 } 6810 } 6811 if((pSiS->CRT2pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6812 if( (pSiS->VBFlags & CRT2_TV) || 6813 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC)) ) { 6814 Bool HaveNoRanges = (pSiS->CRT2pScrn->monitor->nVrefresh <= 0); 6815 /* Set sane ranges for LCD and TV */ 6816 if((crt2freqoverruled = CheckAndOverruleV(pScrn, pSiS->CRT2pScrn->monitor))) { 6817 xf86DrvMsg(pScrn->scrnIndex, X_INFO, sanev, 6818 HaveNoRanges ? "missing" : "bogus", 2); 6819 } 6820 } 6821 } 6822 } 6823 6824 backupddc = pSiS->CRT2pScrn->monitor->DDC; 6825 6826 /* Suppress bogus DDC warning */ 6827 if(crt2freqoverruled) pSiS->CRT2pScrn->monitor->DDC = NULL; 6828 6829 pSiS->CheckForCRT2 = TRUE; 6830 6831 i = xf86ValidateModes(pSiS->CRT2pScrn, pSiS->CRT2pScrn->monitor->Modes, 6832 pSiS->CRT2pScrn->display->modes, clockRanges, 6833 NULL, 256, 4088, 6834 pSiS->CRT2pScrn->bitsPerPixel * 8, 128, 4096, 6835 pScrn->display->virtualX ? pScrn->virtualX : 0, 6836 pScrn->display->virtualY ? pScrn->virtualY : 0, 6837 pSiS->maxxfbmem, 6838 LOOKUP_BEST_REFRESH); 6839 6840 pSiS->CheckForCRT2 = FALSE; 6841 pSiS->CRT2pScrn->monitor->DDC = backupddc; 6842 6843 if(i == -1) { 6844 SISErrorLog(pScrn, "xf86ValidateModes() error, %s.\n", mergeddisstr); 6845 SiSFreeCRT2Structs(pSiS); 6846 pSiS->MergedFB = FALSE; 6847 } 6848 6849 } 6850 6851 if(pSiS->MergedFB) { 6852 6853 if((p = first = pSiS->CRT2pScrn->modes)) { 6854 do { 6855 n = p->next; 6856 if( (pSiS->VGAEngine == SIS_300_VGA) && 6857 ( (strcmp(p->name, "320x200") == 0) || 6858 (strcmp(p->name, "320x240") == 0) || 6859 (strcmp(p->name, "400x300") == 0) || 6860 (strcmp(p->name, "512x384") == 0) || 6861 (strcmp(p->name, "640x400") == 0) ) ) { 6862 p->status = MODE_BAD; 6863 xf86DrvMsg(pScrn->scrnIndex, X_INFO, notsuitablestr, p->name, "MergedFB"); 6864 } 6865 p = n; 6866 } while (p != NULL && p != first); 6867 } 6868 6869 xf86PruneDriverModes(pSiS->CRT2pScrn); 6870 6871 if(i == 0 || pSiS->CRT2pScrn->modes == NULL) { 6872 SISErrorLog(pScrn, "No valid modes found for CRT2; %s\n", mergeddisstr); 6873 SiSFreeCRT2Structs(pSiS); 6874 pSiS->MergedFB = FALSE; 6875 } 6876 6877 } 6878 6879 if(pSiS->MergedFB) { 6880 6881 xf86SetCrtcForModes(pSiS->CRT2pScrn, INTERLACE_HALVE_V); 6882 6883 xf86DrvMsg(pScrn->scrnIndex, X_INFO, modesforstr, 2); 6884 6885 if(pSiS->VBFlags & (CRT2_LCD | CRT2_TV)) { 6886 SiSPrintModes(pSiS->CRT2pScrn); 6887 } else { 6888 xf86PrintModes(pSiS->CRT2pScrn); 6889 } 6890 6891 pSiS->CRT1Modes = pScrn->modes; 6892 pSiS->CRT1CurrentMode = pScrn->currentMode; 6893 6894 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MergedFB: Generating mode list\n"); 6895 6896 pScrn->modes = SiSGenerateModeList(pScrn, pSiS->MetaModes, 6897 pSiS->CRT1Modes, pSiS->CRT2pScrn->modes, 6898 pSiS->CRT2Position); 6899 6900 if(!pScrn->modes) { 6901 6902 SISErrorLog(pScrn, "Failed to parse MetaModes or no modes found. %s.\n", 6903 mergeddisstr); 6904 SiSFreeCRT2Structs(pSiS); 6905 pScrn->modes = pSiS->CRT1Modes; 6906 pSiS->CRT1Modes = NULL; 6907 pSiS->MergedFB = FALSE; 6908 6909 } 6910 6911 } 6912 6913 if(pSiS->MergedFB) { 6914 6915 /* If no virtual dimension was given by the user, 6916 * calculate a sane one now. Adapts pScrn->virtualX, 6917 * pScrn->virtualY and pScrn->displayWidth. 6918 */ 6919 SiSRecalcDefaultVirtualSize(pScrn); 6920 6921 pScrn->modes = pScrn->modes->next; /* We get the last from GenerateModeList(), skip to first */ 6922 pScrn->currentMode = pScrn->modes; 6923 6924 /* Update CurrentLayout */ 6925 pSiS->CurrentLayout.mode = pScrn->currentMode; 6926 pSiS->CurrentLayout.displayWidth = pScrn->displayWidth; 6927 pSiS->CurrentLayout.displayHeight = pScrn->virtualY; 6928 6929 } 6930#endif 6931 6932 /* Set display resolution */ 6933#ifdef SISMERGED 6934 if(pSiS->MergedFB) { 6935 SiSMergedFBSetDpi(pScrn, pSiS->CRT2pScrn, pSiS->CRT2Position); 6936 } else 6937#endif 6938 xf86SetDpi(pScrn, 0, 0); 6939 6940 /* Load fb module */ 6941 switch(pScrn->bitsPerPixel) { 6942 case 8: 6943 case 16: 6944 case 24: 6945 case 32: 6946 if(!xf86LoadSubModule(pScrn, "fb")) { 6947 SISErrorLog(pScrn, "Failed to load fb module"); 6948 goto my_error_1; 6949 } 6950 break; 6951 default: 6952 SISErrorLog(pScrn, "Unsupported framebuffer bpp (%d)\n", pScrn->bitsPerPixel); 6953 goto my_error_1; 6954 } 6955 xf86LoaderReqSymLists(fbSymbols, NULL); 6956 6957 /* Load XAA/EXA (if needed) */ 6958 if(!pSiS->NoAccel) { 6959 const char **symNames = NULL; 6960#ifdef SIS_USE_XAA 6961 if(!pSiS->useEXA) { 6962 if (!xf86LoadSubModule(pScrn, "xaa")) { 6963 SISErrorLog(pScrn, "Could not load xaa module\n"); 6964 goto my_error_1; 6965 } 6966 symNames = xaaSymbols; 6967 } 6968#endif 6969#ifdef SIS_USE_EXA 6970 if(pSiS->useEXA) { 6971 XF86ModReqInfo req; 6972 int errmaj, errmin; 6973 6974 memset(&req, 0, sizeof(req)); 6975 req.majorversion = 2; 6976 req.minorversion = 0; 6977 if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, &req, 6978 &errmaj, &errmin)) { 6979 LoaderErrorMsg(NULL, "exa", errmaj, errmin); 6980 goto my_error_1; 6981 } 6982 symNames = exaSymbols; 6983 } 6984#endif 6985 if(symNames) { 6986 xf86LoaderReqSymLists(symNames, NULL); 6987 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D acceleration enabled\n"); 6988 } 6989 } 6990 6991 /* Load shadowfb (if needed) */ 6992 if(pSiS->ShadowFB) { 6993 if(!xf86LoadSubModule(pScrn, "shadowfb")) { 6994 SISErrorLog(pScrn, "Could not load shadowfb module\n"); 6995 goto my_error_1; 6996 } 6997 xf86LoaderReqSymLists(shadowSymbols, NULL); 6998 } 6999 7000 /* Load the dri and glx modules if requested. */ 7001#ifdef XF86DRI 7002 if(pSiS->loadDRI) { 7003 if(!xf86LoaderCheckSymbol("DRIScreenInit")) { 7004 if(xf86LoadSubModule(pScrn, "dri")) { 7005 if(!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) { 7006 if(xf86LoadSubModule(pScrn, "glx")) { 7007 xf86LoaderReqSymLists(driSymbols, drmSymbols, NULL); 7008 } else { 7009 SISErrorLog(pScrn, "Failed to load glx module\n"); 7010 } 7011 } 7012 } else { 7013 SISErrorLog(pScrn, "Failed to load dri module\n"); 7014 } 7015 } 7016 } 7017#endif 7018 7019 /* Now load and initialize VBE module for VESA mode switching */ 7020 pSiS->UseVESA = 0; 7021 if(pSiS->VESA == 1) { 7022 SiS_LoadInitVBE(pScrn); 7023 if(pSiS->pVbe) { 7024 VbeInfoBlock *vbe; 7025 if((vbe = VBEGetVBEInfo(pSiS->pVbe))) { 7026 pSiS->vesamajor = (unsigned)(vbe->VESAVersion >> 8); 7027 pSiS->vesaminor = vbe->VESAVersion & 0xff; 7028 SiSBuildVesaModeList(pScrn, pSiS->pVbe, vbe); 7029 VBEFreeVBEInfo(vbe); 7030 pSiS->UseVESA = 1; 7031 } else { 7032 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 7033 "Failed to read VBE Info Block\n"); 7034 } 7035 } 7036 if(pSiS->UseVESA == 0) { 7037 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 7038 "VESA mode switching disabled.\n"); 7039 } 7040 } 7041 7042 if(pSiS->pVbe) { 7043 vbeFree(pSiS->pVbe); 7044 pSiS->pVbe = NULL; 7045 } 7046 7047#ifdef SISDUALHEAD 7048 xf86SetPrimInitDone(pScrn->entityList[0]); 7049#endif 7050 7051 sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); 7052 7053 if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); 7054 pSiS->pInt = NULL; 7055 7056 if(pSiS->VGAEngine == SIS_315_VGA) { 7057 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTXVGAMMA1; 7058 } 7059 7060#ifdef SISDUALHEAD 7061 if(pSiS->DualHeadMode) { 7062 pSiS->SiS_SD_Flags |= SiS_SD_ISDUALHEAD; 7063 if(pSiS->SecondHead) pSiS->SiS_SD_Flags |= SiS_SD_ISDHSECONDHEAD; 7064 else pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTXVGAMMA1); 7065#ifdef PANORAMIX 7066 if(!noPanoramiXExtension) { 7067 pSiS->SiS_SD_Flags |= SiS_SD_ISDHXINERAMA; 7068 /* pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTXVGAMMA1); */ 7069 } 7070#endif 7071 } 7072#endif 7073 7074#ifdef SISMERGED 7075 if(pSiS->MergedFB) pSiS->SiS_SD_Flags |= SiS_SD_ISMERGEDFB; 7076#endif 7077 7078 /* Try to determine if this is a laptop */ 7079 /* (only used for SiSCtrl visualisations) */ 7080 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPLTFLAG; 7081 pSiS->SiS_SD2_Flags &= ~SiS_SD2_ISLAPTOP; 7082 if(pSiS->detectedCRT2Devices & CRT2_LCD) { 7083 if(pSiS->VBFlags2 & (VB2_SISLVDSBRIDGE | VB2_LVDS | VB2_30xBDH)) { 7084 /* 1. By bridge type: LVDS in 99% of all cases; 7085 * exclude unusual setups like Barco projectors 7086 * and parallel flat panels. TODO: Exclude 7087 * Sony W1, V1. 7088 */ 7089 if((pSiS->SiS_Pr->SiS_CustomT != CUT_BARCO1366) && 7090 (pSiS->SiS_Pr->SiS_CustomT != CUT_BARCO1024) && 7091 (pSiS->SiS_Pr->SiS_CustomT != CUT_PANEL848) && 7092 (pSiS->SiS_Pr->SiS_CustomT != CUT_PANEL856) && 7093 (pSiS->SiS_Pr->SiS_CustomT != CUT_AOP8060) && 7094 ( (pSiS->ChipType != SIS_550) || 7095 (!pSiS->DSTN && !pSiS->FSTN) ) ) { 7096 pSiS->SiS_SD2_Flags |= SiS_SD2_ISLAPTOP; 7097 } 7098 } else if((pSiS->VBFlags2 & (VB2_301 | VB2_301C)) && 7099 (pSiS->VBLCDFlags & (VB_LCD_1280x960 | 7100 VB_LCD_1400x1050 | 7101 VB_LCD_1024x600 | 7102 VB_LCD_1280x800 | 7103 VB_LCD_1280x854))) { 7104 /* 2. By (odd) LCD resolutions on TMDS bridges 7105 * (eg Averatec). TODO: Exclude IBM Netvista. 7106 */ 7107 pSiS->SiS_SD2_Flags |= SiS_SD2_ISLAPTOP; 7108 } 7109 } 7110 7111 if(pSiS->enablesisctrl) pSiS->SiS_SD_Flags |= SiS_SD_ENABLED; 7112 7113 pSiS->currentModeLast = pScrn->currentMode; 7114 pSiS->VBFlagsInit = pSiS->VBFlags; 7115 7116 return TRUE; 7117 7118 /* ---- */ 7119 7120my_error_1: 7121 sisRestoreExtRegisterLock(pSiS, srlockReg, crlockReg); 7122my_error_0: 7123#ifdef SISDUALHEAD 7124 if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; 7125#endif 7126 if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); 7127 pSiS->pInt = NULL; 7128 SISFreeRec(pScrn); 7129 return FALSE; 7130} 7131 7132/* 7133 * Map I/O port area for non-PC platforms 7134 */ 7135#ifdef SIS_NEED_MAP_IOP 7136static Bool 7137SISMapIOPMem(ScrnInfoPtr pScrn) 7138{ 7139 SISPtr pSiS = SISPTR(pScrn); 7140#ifdef SISDUALHEAD 7141 SISEntPtr pSiSEnt = pSiS->entityPrivate; 7142 7143 if(pSiS->DualHeadMode) { 7144 pSiSEnt->MapCountIOPBase++; 7145 if(!(pSiSEnt->IOPBase)) { 7146 /* Only map if not mapped previously */ 7147 pSiSEnt->IOPBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7148 pSiS->PciTag, pSiS->IOPAddress, 128); 7149 } 7150 pSiS->IOPBase = pSiSEnt->IOPBase; 7151 } else 7152#endif 7153 pSiS->IOPBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, 7154 pSiS->PciTag, pSiS->IOPAddress, 128); 7155 7156 if(pSiS->IOPBase == NULL) { 7157 SISErrorLog(pScrn, "Could not map I/O port area\n"); 7158 return FALSE; 7159 } 7160 7161 return TRUE; 7162} 7163 7164static Bool 7165SISUnmapIOPMem(ScrnInfoPtr pScrn) 7166{ 7167 SISPtr pSiS = SISPTR(pScrn); 7168#ifdef SISDUALHEAD 7169 SISEntPtr pSiSEnt = pSiS->entityPrivate;; 7170#endif 7171 7172/* In dual head mode, we must not unmap if the other head still 7173 * assumes memory as mapped 7174 */ 7175#ifdef SISDUALHEAD 7176 if(pSiS->DualHeadMode) { 7177 if(pSiSEnt->MapCountIOPBase) { 7178 pSiSEnt->MapCountIOPBase--; 7179 if((pSiSEnt->MapCountIOPBase == 0) || (pSiSEnt->forceUnmapIOPBase)) { 7180 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOPBase, 2048); 7181 pSiSEnt->IOPBase = NULL; 7182 pSiSEnt->MapCountIOPBase = 0; 7183 pSiSEnt->forceUnmapIOPBase = FALSE; 7184 } 7185 pSiS->IOPBase = NULL; 7186 } 7187 } else { 7188#endif 7189 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOPBase, 2048); 7190 pSiS->IOPBase = NULL; 7191#ifdef SISDUALHEAD 7192 } 7193#endif 7194 return TRUE; 7195} 7196#endif 7197 7198/* 7199 * Map the framebuffer and MMIO memory 7200 */ 7201 7202static Bool 7203SISMapMem(ScrnInfoPtr pScrn) 7204{ 7205 SISPtr pSiS = SISPTR(pScrn); 7206 int mmioFlags = VIDMEM_MMIO; 7207#ifdef SISDUALHEAD 7208 SISEntPtr pSiSEnt = pSiS->entityPrivate; 7209#endif 7210 7211 /* 7212 * Map IO registers to virtual address space 7213 * (For Alpha, we need to map SPARSE memory, since we need 7214 * byte/short access.) 7215 */ 7216#if defined(__alpha__) 7217 mmioFlags |= VIDMEM_SPARSE; 7218#endif 7219 7220#ifdef SISDUALHEAD 7221 if(pSiS->DualHeadMode) { 7222 pSiSEnt->MapCountIOBase++; 7223 if(!(pSiSEnt->IOBase)) { 7224 /* Only map if not mapped previously */ 7225 pSiSEnt->IOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, 7226 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7227 } 7228 pSiS->IOBase = pSiSEnt->IOBase; 7229 } else 7230#endif 7231 pSiS->IOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, 7232 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7233 7234 if(pSiS->IOBase == NULL) { 7235 SISErrorLog(pScrn, "Could not map MMIO area\n"); 7236 return FALSE; 7237 } 7238 7239#ifdef __alpha__ 7240 /* 7241 * for Alpha, we need to map DENSE memory as well, for 7242 * setting CPUToScreenColorExpandBase. 7243 */ 7244#ifdef SISDUALHEAD 7245 if(pSiS->DualHeadMode) { 7246 pSiSEnt->MapCountIOBaseDense++; 7247 if(!(pSiSEnt->IOBaseDense)) { 7248 /* Only map if not mapped previously */ 7249 pSiSEnt->IOBaseDense = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7250 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7251 } 7252 pSiS->IOBaseDense = pSiSEnt->IOBaseDense; 7253 } else 7254#endif 7255 pSiS->IOBaseDense = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7256 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7257 7258 if(pSiS->IOBaseDense == NULL) { 7259 SISErrorLog(pScrn, "Could not map MMIO dense area\n"); 7260 return FALSE; 7261 } 7262#endif /* __alpha__ */ 7263 7264#ifdef SISDUALHEAD 7265 if(pSiS->DualHeadMode) { 7266 pSiSEnt->MapCountFbBase++; 7267 if(!(pSiSEnt->FbBase)) { 7268 /* Only map if not mapped previously */ 7269 pSiSEnt->FbBase = pSiSEnt->RealFbBase = 7270 xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 7271 pSiS->PciTag, (ULong)pSiS->realFbAddress, 7272 pSiS->FbMapSize); 7273 } 7274 pSiS->FbBase = pSiS->RealFbBase = pSiSEnt->FbBase; 7275 /* Adapt FbBase (for DHM and SiS76x UMA skipping; dhmOffset is 0 otherwise) */ 7276 pSiS->FbBase += pSiS->dhmOffset; 7277 } else { 7278#endif 7279 pSiS->FbBase = pSiS->RealFbBase = 7280 xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 7281 pSiS->PciTag, (ULong)pSiS->realFbAddress, 7282 pSiS->FbMapSize); 7283 pSiS->FbBase += pSiS->dhmOffset; 7284#ifdef SISDUALHEAD 7285 } 7286#endif 7287 7288 if(pSiS->FbBase == NULL) { 7289 SISErrorLog(pScrn, "Could not map framebuffer area\n"); 7290 return FALSE; 7291 } 7292 7293#ifdef TWDEBUG 7294 xf86DrvMsg(0, 0, "Framebuffer mapped to %p\n", pSiS->FbBase); 7295#endif 7296 7297 return TRUE; 7298} 7299 7300 7301/* 7302 * Unmap the framebuffer and MMIO memory. 7303 */ 7304 7305static Bool 7306SISUnmapMem(ScrnInfoPtr pScrn) 7307{ 7308 SISPtr pSiS = SISPTR(pScrn); 7309#ifdef SISDUALHEAD 7310 SISEntPtr pSiSEnt = pSiS->entityPrivate; 7311#endif 7312 7313/* In dual head mode, we must not unmap if the other head still 7314 * assumes memory as mapped 7315 */ 7316#ifdef SISDUALHEAD 7317 if(pSiS->DualHeadMode) { 7318 if(pSiSEnt->MapCountIOBase) { 7319 pSiSEnt->MapCountIOBase--; 7320 if((pSiSEnt->MapCountIOBase == 0) || (pSiSEnt->forceUnmapIOBase)) { 7321 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOBase, (pSiS->mmioSize * 1024)); 7322 pSiSEnt->IOBase = NULL; 7323 pSiSEnt->MapCountIOBase = 0; 7324 pSiSEnt->forceUnmapIOBase = FALSE; 7325 } 7326 pSiS->IOBase = NULL; 7327 } 7328#ifdef __alpha__ 7329 if(pSiSEnt->MapCountIOBaseDense) { 7330 pSiSEnt->MapCountIOBaseDense--; 7331 if((pSiSEnt->MapCountIOBaseDense == 0) || (pSiSEnt->forceUnmapIOBaseDense)) { 7332 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOBaseDense, (pSiS->mmioSize * 1024)); 7333 pSiSEnt->IOBaseDense = NULL; 7334 pSiSEnt->MapCountIOBaseDense = 0; 7335 pSiSEnt->forceUnmapIOBaseDense = FALSE; 7336 } 7337 pSiS->IOBaseDense = NULL; 7338 } 7339#endif /* __alpha__ */ 7340 if(pSiSEnt->MapCountFbBase) { 7341 pSiSEnt->MapCountFbBase--; 7342 if((pSiSEnt->MapCountFbBase == 0) || (pSiSEnt->forceUnmapFbBase)) { 7343 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->RealFbBase, pSiS->FbMapSize); 7344 pSiSEnt->FbBase = pSiSEnt->RealFbBase = NULL; 7345 pSiSEnt->MapCountFbBase = 0; 7346 pSiSEnt->forceUnmapFbBase = FALSE; 7347 7348 } 7349 pSiS->FbBase = pSiS->RealFbBase = NULL; 7350 } 7351 } else { 7352#endif 7353 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOBase, (pSiS->mmioSize * 1024)); 7354 pSiS->IOBase = NULL; 7355#ifdef __alpha__ 7356 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOBaseDense, (pSiS->mmioSize * 1024)); 7357 pSiS->IOBaseDense = NULL; 7358#endif 7359 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->RealFbBase, pSiS->FbMapSize); 7360 pSiS->FbBase = pSiS->RealFbBase = NULL; 7361#ifdef SISDUALHEAD 7362 } 7363#endif 7364 return TRUE; 7365} 7366 7367/* 7368 * This function saves the video state. 7369 */ 7370static void 7371SISSave(ScrnInfoPtr pScrn) 7372{ 7373 SISPtr pSiS = SISPTR(pScrn); 7374 SISRegPtr sisReg; 7375 int flags; 7376 7377#ifdef SISDUALHEAD 7378 /* We always save master & slave */ 7379 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 7380#endif 7381 7382 sisReg = &pSiS->SavedReg; 7383 7384 if( ((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) && 7385 ((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (SiSBridgeIsInSlaveMode(pScrn))) ) { 7386 SiSVGASave(pScrn, sisReg, SISVGA_SR_CMAP | SISVGA_SR_MODE); 7387#ifdef SIS_PC_PLATFORM 7388 if(pSiS->VGAMemBase) { 7389 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO+0x30); 7390 SiSSetLVDSetc(pSiS->SiS_Pr, 0); 7391 SiS_GetVBType(pSiS->SiS_Pr); 7392 SiS_DisableBridge(pSiS->SiS_Pr); 7393 SiSVGASave(pScrn, sisReg, SISVGA_SR_FONTS); 7394 SiS_EnableBridge(pSiS->SiS_Pr); 7395 } 7396#endif 7397 } else { 7398 flags = SISVGA_SR_CMAP | SISVGA_SR_MODE; 7399#ifdef SIS_PC_PLATFORM 7400 if(pSiS->VGAMemBase) flags |= SISVGA_SR_FONTS; 7401#endif 7402 SiSVGASave(pScrn, sisReg, flags); 7403 } 7404 7405 sisSaveUnlockExtRegisterLock(pSiS, &sisReg->sisRegs3C4[0x05], &sisReg->sisRegs3D4[0x80]); 7406 7407 (*pSiS->SiSSave)(pScrn, sisReg); 7408 7409 if(pSiS->UseVESA) SISVESASaveRestore(pScrn, MODE_SAVE); 7410 7411 /* "Save" these again as they may have been changed prior to SISSave() call */ 7412 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 7413 sisReg->sisRegs3C4[0x1f] = pSiS->oldSR1F; 7414 sisReg->sisRegs3D4[0x17] = pSiS->oldCR17; 7415 sisReg->sisRegs3D4[0x32] = pSiS->oldCR32; 7416 sisReg->sisRegs3D4[0x36] = pSiS->oldCR36; 7417 sisReg->sisRegs3D4[0x37] = pSiS->oldCR37; 7418 if(pSiS->VGAEngine == SIS_315_VGA) { 7419 sisReg->sisRegs3D4[pSiS->myCR63] = pSiS->oldCR63; 7420 } 7421 } 7422} 7423 7424/* VESASaveRestore taken from vesa driver */ 7425static void 7426SISVESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function) 7427{ 7428 SISPtr pSiS = SISPTR(pScrn); 7429 7430 /* Query amount of memory to save state */ 7431 if((function == MODE_QUERY) || 7432 (function == MODE_SAVE && pSiS->state == NULL)) { 7433 7434 /* Make sure we save at least this information in case of failure */ 7435 (void)VBEGetVBEMode(pSiS->pVbe, &pSiS->stateMode); 7436 SiSVGASaveFonts(pScrn); 7437 7438 if(pSiS->vesamajor > 1) { 7439 if(!VBESaveRestore(pSiS->pVbe, function, (pointer)&pSiS->state, 7440 &pSiS->stateSize, &pSiS->statePage)) { 7441 return; 7442 } 7443 } 7444 } 7445 7446 /* Save/Restore Super VGA state */ 7447 if(function != MODE_QUERY) { 7448 7449 if(pSiS->vesamajor > 1) { 7450 if(function == MODE_RESTORE) { 7451 memcpy(pSiS->state, pSiS->pstate, pSiS->stateSize); 7452 } 7453 7454 if(VBESaveRestore(pSiS->pVbe,function,(pointer)&pSiS->state, 7455 &pSiS->stateSize,&pSiS->statePage) && 7456 (function == MODE_SAVE)) { 7457 /* don't rely on the memory not being touched */ 7458 if(!pSiS->pstate) { 7459 pSiS->pstate = xalloc(pSiS->stateSize); 7460 } 7461 memcpy(pSiS->pstate, pSiS->state, pSiS->stateSize); 7462 } 7463 } 7464 7465 if(function == MODE_RESTORE) { 7466 VBESetVBEMode(pSiS->pVbe, pSiS->stateMode, NULL); 7467 SiSVGARestoreFonts(pScrn); 7468 } 7469 7470 } 7471} 7472 7473/* 7474 * Initialise a new mode. This is currently done using the 7475 * "initialise struct, restore/write struct to HW" model for 7476 * the old chipsets (5597/530/6326). For newer chipsets, 7477 * we use our own mode switching code. 7478 */ 7479 7480static Bool 7481SISModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 7482{ 7483 SISPtr pSiS = SISPTR(pScrn); 7484 SISRegPtr sisReg; 7485#ifdef SISDUALHEAD 7486 SISEntPtr pSiSEnt = NULL; 7487#endif 7488 7489 andSISIDXREG(SISCR,0x11,0x7f); /* Unlock CRTC registers */ 7490 7491 SISModifyModeInfo(mode); /* Quick check of the mode parameters */ 7492 7493 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7494 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO+0x30); 7495 } 7496 7497 if(pSiS->UseVESA) { /* With VESA: */ 7498 7499#ifdef SISDUALHEAD 7500 /* No dual head mode when using VESA */ 7501 if(pSiS->SecondHead) return TRUE; 7502#endif 7503 7504 pScrn->vtSema = TRUE; 7505 7506 /* 7507 * This order is required: 7508 * The video bridge needs to be adjusted before the 7509 * BIOS is run as the BIOS sets up CRT2 according to 7510 * these register settings. 7511 * After the BIOS is run, the bridges and turboqueue 7512 * registers need to be readjusted as the BIOS may 7513 * very probably have messed them up. 7514 */ 7515 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7516 SiSPreSetMode(pScrn, mode, SIS_MODE_SIMU); 7517 } 7518 if(!SiSSetVESAMode(pScrn, mode)) { 7519 SISErrorLog(pScrn, "SiSSetVESAMode() failed\n"); 7520 return FALSE; 7521 } 7522 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7523 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7524 SiSPreSetMode(pScrn, mode, SIS_MODE_SIMU); 7525 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7526 } 7527#ifdef TWDEBUG 7528 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 7529 "REAL REGISTER CONTENTS AFTER SETMODE:\n"); 7530#endif 7531 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7532 SISErrorLog(pScrn, "ModeInit() failed\n"); 7533 return FALSE; 7534 } 7535 7536 SiSVGAProtect(pScrn, TRUE); 7537 (*pSiS->SiSRestore)(pScrn, &pSiS->ModeReg); 7538 SiSVGAProtect(pScrn, FALSE); 7539 7540 } else { /* Without VESA: */ 7541 7542#ifdef SISDUALHEAD 7543 if(pSiS->DualHeadMode) { 7544 7545 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7546 SISErrorLog(pScrn, "ModeInit() failed\n"); 7547 return FALSE; 7548 } 7549 7550 pScrn->vtSema = TRUE; 7551 7552 pSiSEnt = pSiS->entityPrivate; 7553 7554 if(!(pSiS->SecondHead)) { 7555 /* Head 1 (master) is always CRT2 */ 7556 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT2); 7557 if(!SiSBIOSSetModeCRT2(pSiS->SiS_Pr, pScrn, mode, pSiS->IsCustom)) { 7558 SISErrorLog(pScrn, "SiSBIOSSetModeCRT2() failed\n"); 7559 return FALSE; 7560 } 7561 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7562 if(pSiSEnt->pScrn_2) { 7563 SISAdjustFrame(pSiSEnt->pScrn_2->scrnIndex, 7564 pSiSEnt->pScrn_2->frameX0, 7565 pSiSEnt->pScrn_2->frameY0, 0); 7566 } 7567 } else { 7568 /* Head 2 (slave) is always CRT1 */ 7569 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT1); 7570 if(!SiSBIOSSetModeCRT1(pSiS->SiS_Pr, pScrn, mode, pSiS->IsCustom)) { 7571 SISErrorLog(pScrn, "SiSBIOSSetModeCRT1() failed\n"); 7572 return FALSE; 7573 } 7574 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7575 if(pSiSEnt->pScrn_1) { 7576 SISAdjustFrame(pSiSEnt->pScrn_1->scrnIndex, 7577 pSiSEnt->pScrn_1->frameX0, 7578 pSiSEnt->pScrn_1->frameY0, 0); 7579 } 7580 } 7581 7582 } else { 7583#endif 7584 7585 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7586 7587 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7588 SISErrorLog(pScrn, "ModeInit() failed\n"); 7589 return FALSE; 7590 } 7591 7592 pScrn->vtSema = TRUE; 7593 7594#ifdef SISMERGED 7595 if(pSiS->MergedFB) { 7596 7597 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting MergedFB mode %dx%d\n", 7598 mode->HDisplay, mode->VDisplay); 7599 7600 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT1); 7601 7602 if(!SiSBIOSSetModeCRT1(pSiS->SiS_Pr, pScrn, 7603 ((SiSMergedDisplayModePtr)mode->Private)->CRT1, 7604 pSiS->IsCustom)) { 7605 SISErrorLog(pScrn, "SiSBIOSSetModeCRT1() failed\n"); 7606 return FALSE; 7607 } 7608 7609 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT2); 7610 7611 if(!SiSBIOSSetModeCRT2(pSiS->SiS_Pr, pScrn, 7612 ((SiSMergedDisplayModePtr)mode->Private)->CRT2, 7613 pSiS->IsCustom)) { 7614 SISErrorLog(pScrn, "SiSBIOSSetModeCRT2() failed\n"); 7615 return FALSE; 7616 } 7617 7618 } else { 7619#endif 7620 7621 if((pSiS->VBFlags & CRT1_LCDA) || (!(mode->type & M_T_DEFAULT))) { 7622 7623 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT1); 7624 7625 if(!SiSBIOSSetModeCRT1(pSiS->SiS_Pr, pScrn, 7626 mode, pSiS->IsCustom)) { 7627 SISErrorLog(pScrn, "SiSBIOSSetModeCRT1() failed\n"); 7628 return FALSE; 7629 } 7630 7631 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT2); 7632 7633 if(!SiSBIOSSetModeCRT2(pSiS->SiS_Pr, pScrn, 7634 mode, pSiS->IsCustom)) { 7635 SISErrorLog(pScrn, "SiSBIOSSetModeCRT2() failed\n"); 7636 return FALSE; 7637 } 7638 7639 } else { 7640 7641 SiSPreSetMode(pScrn, mode, SIS_MODE_SIMU); 7642 7643 if(!SiSBIOSSetMode(pSiS->SiS_Pr, pScrn, 7644 mode, pSiS->IsCustom)) { 7645 SISErrorLog(pScrn, "SiSBIOSSetMode() failed\n"); 7646 return FALSE; 7647 } 7648 7649 } 7650 7651#ifdef SISMERGED 7652 } 7653#endif 7654 7655 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7656 7657#ifdef TWDEBUG 7658 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VBFlags %lx\n", pSiS->VBFlags); 7659 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 7660 "REAL REGISTER CONTENTS AFTER SETMODE:\n"); 7661 (*pSiS->ModeInit)(pScrn, mode); 7662#endif 7663 7664 } else { 7665 7666 /* For other chipsets, use the old method */ 7667 7668 /* Prepare the register contents */ 7669 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7670 SISErrorLog(pScrn, "ModeInit() failed\n"); 7671 return FALSE; 7672 } 7673 7674 pScrn->vtSema = TRUE; 7675 7676 /* Program the registers */ 7677 SiSVGAProtect(pScrn, TRUE); 7678 sisReg = &pSiS->ModeReg; 7679 7680 sisReg->sisRegsATTR[0x10] = 0x01; 7681 if(pScrn->bitsPerPixel > 8) { 7682 sisReg->sisRegsGR[0x05] = 0x00; 7683 } 7684 7685 SiSVGARestore(pScrn, sisReg, SISVGA_SR_MODE); 7686 7687 (*pSiS->SiSRestore)(pScrn, sisReg); 7688 7689 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 7690 SiS6326PostSetMode(pScrn, &pSiS->ModeReg); 7691 } 7692 7693#ifdef TWDEBUG 7694 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 7695 "REAL REGISTER CONTENTS AFTER SETMODE:\n"); 7696 (*pSiS->ModeInit)(pScrn, mode); 7697#endif 7698 7699 SiSVGAProtect(pScrn, FALSE); 7700 7701 } 7702 7703#ifdef SISDUALHEAD 7704 } 7705#endif 7706 } 7707 7708 /* Update Currentlayout */ 7709 pSiS->CurrentLayout.mode = pSiS->currentModeLast = mode; 7710 7711 return TRUE; 7712} 7713 7714static Bool 7715SiSSetVESAMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) 7716{ 7717 SISPtr pSiS; 7718 int mode; 7719 7720 pSiS = SISPTR(pScrn); 7721 7722 if(!(mode = SiSCalcVESAModeIndex(pScrn, pMode))) return FALSE; 7723 7724 mode |= (1 << 15); /* Don't clear framebuffer */ 7725 mode |= (1 << 14); /* Use linear adressing */ 7726 7727 if(VBESetVBEMode(pSiS->pVbe, mode, NULL) == FALSE) { 7728 SISErrorLog(pScrn, "Setting VESA mode 0x%x failed\n", 7729 mode & 0x0fff); 7730 return (FALSE); 7731 } 7732 7733 if(pMode->HDisplay != pScrn->virtualX) { 7734 VBESetLogicalScanline(pSiS->pVbe, pScrn->virtualX); 7735 } 7736 7737 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 7738 "Setting VESA mode 0x%x succeeded\n", 7739 mode & 0x0fff); 7740 7741 return (TRUE); 7742} 7743 7744static void 7745SISSpecialRestore(ScrnInfoPtr pScrn) 7746{ 7747 SISPtr pSiS = SISPTR(pScrn); 7748 SISRegPtr sisReg = &pSiS->SavedReg; 7749 UChar temp; 7750 int i; 7751 7752 /* 1.11.04 and later for 651 and 301B(DH) do strange register 7753 * fiddling after the usual mode change. This happens 7754 * depending on the result of a call of int 2f (with 7755 * ax=0x1680) and if modeno <= 0x13. I have no idea if 7756 * that is specific for the 651 or that very machine. 7757 * So this perhaps requires some more checks in the beginning 7758 * (although it should not do any harm on other chipsets/bridges 7759 * etc.) However, even if I call the VBE to restore mode 0x03, 7760 * these registers don't get restored correctly, possibly 7761 * because that int-2f-call for some reason results non-zero. So 7762 * what I do here is to restore these few registers 7763 * manually. 7764 */ 7765 7766 if(!(pSiS->ChipFlags & SiSCF_Is65x)) return; 7767 inSISIDXREG(SISCR, 0x34, temp); 7768 temp &= 0x7f; 7769 if(temp > 0x13) return; 7770 7771#ifdef UNLOCK_ALWAYS 7772 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7773#endif 7774 7775 SiS_UnLockCRT2(pSiS->SiS_Pr); 7776 7777 outSISIDXREG(SISCAP, 0x3f, sisReg->sisCapt[0x3f]); 7778 outSISIDXREG(SISCAP, 0x00, sisReg->sisCapt[0x00]); 7779 for(i = 0; i < 0x4f; i++) { 7780 outSISIDXREG(SISCAP, i, sisReg->sisCapt[i]); 7781 } 7782 outSISIDXREG(SISVID, 0x32, (sisReg->sisVid[0x32] & ~0x05)); 7783 outSISIDXREG(SISVID, 0x30, sisReg->sisVid[0x30]); 7784 outSISIDXREG(SISVID, 0x32, ((sisReg->sisVid[0x32] & ~0x04) | 0x01)); 7785 outSISIDXREG(SISVID, 0x30, sisReg->sisVid[0x30]); 7786 7787 if(!(pSiS->ChipFlags & SiSCF_Is651)) return; 7788 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 7789 7790 inSISIDXREG(SISCR, 0x30, temp); 7791 if(temp & 0x40) { 7792 UChar myregs[] = { 7793 0x2f, 0x08, 0x09, 0x03, 0x0a, 0x0c, 7794 0x0b, 0x0d, 0x0e, 0x12, 0x0f, 0x10, 7795 0x11, 0x04, 0x05, 0x06, 0x07, 0x00, 7796 0x2e 7797 }; 7798 for(i = 0; i <= 18; i++) { 7799 outSISIDXREG(SISPART1, myregs[i], sisReg->VBPart1[myregs[i]]); 7800 } 7801 } else if((temp & 0x20) || (temp & 0x9c)) { 7802 UChar myregs[] = { 7803 0x04, 0x05, 0x06, 0x07, 0x00, 0x2e 7804 }; 7805 for(i = 0; i <= 5; i++) { 7806 outSISIDXREG(SISPART1, myregs[i], sisReg->VBPart1[myregs[i]]); 7807 } 7808 } 7809} 7810 7811/* Fix SR11 for 661 and later */ 7812static void 7813SiSFixupSR11(ScrnInfoPtr pScrn) 7814{ 7815 SISPtr pSiS = SISPTR(pScrn); 7816 CARD8 tmpreg; 7817 7818#ifdef UNLOCK_ALWAYS 7819 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7820#endif 7821 7822 if(pSiS->ChipType >= SIS_661) { 7823 inSISIDXREG(SISSR,0x11,tmpreg); 7824 if(tmpreg & 0x20) { 7825 inSISIDXREG(SISSR,0x3e,tmpreg); 7826 tmpreg = (tmpreg + 1) & 0xff; 7827 outSISIDXREG(SISSR,0x3e,tmpreg); 7828 } 7829 7830 inSISIDXREG(SISSR,0x11,tmpreg); 7831 if(tmpreg & 0xf0) { 7832 andSISIDXREG(SISSR,0x11,0x0f); 7833 } 7834 } 7835} 7836 7837/* Subroutine for restoring sisfb's TV parameters (used by SiSRestore()) */ 7838 7839static void 7840SiSRestore_SiSFB_TVParms(ScrnInfoPtr pScrn) 7841{ 7842 SISPtr pSiS = SISPTR(pScrn); 7843 int fd; 7844 CARD32 parm; 7845 7846 if(!pSiS->sisfbfound) return; 7847 if(!pSiS->sisfb_tvposvalid) return; 7848 if(!(pSiS->sisfbdevname[0])) return; 7849 7850 if((fd = open(pSiS->sisfbdevname, 'r')) != -1) { 7851 parm = (CARD32)((pSiS->sisfb_tvxpos << 16) | (pSiS->sisfb_tvypos & 0xffff)); 7852 ioctl(fd, SISFB_SET_TVPOSOFFSET, &parm); 7853 close(fd); 7854 } 7855} 7856 7857/* 7858 * Restore the initial mode. To be used internally only! 7859 */ 7860static void 7861SISRestore(ScrnInfoPtr pScrn) 7862{ 7863 SISPtr pSiS = SISPTR(pScrn); 7864 SISRegPtr sisReg = &pSiS->SavedReg; 7865 Bool doit = FALSE, doitlater = FALSE; 7866 Bool vesasuccess = FALSE; 7867 int flags; 7868 7869 /* WARNING: Don't ever touch this. It now seems to work on 7870 * all chipset/bridge combinations - but finding out the 7871 * correct combination was pure hell. 7872 */ 7873 7874 /* Wait for the accelerators */ 7875 (*pSiS->SyncAccel)(pScrn); 7876 7877 /* Set up restore flags */ 7878 flags = SISVGA_SR_MODE | SISVGA_SR_CMAP; 7879#ifdef SIS_PC_PLATFORM 7880 /* We now restore ALL to overcome the vga=extended problem */ 7881 if(pSiS->VGAMemBase) flags |= SISVGA_SR_FONTS; 7882#endif 7883 7884 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 7885 7886#ifdef SISDUALHEAD 7887 /* We always restore master AND slave */ 7888 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 7889#endif 7890 7891#ifdef UNLOCK_ALWAYS 7892 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7893#endif 7894 7895 /* We must not disable the sequencer if the bridge is in SlaveMode! */ 7896 if(!(SiSBridgeIsInSlaveMode(pScrn))) { 7897 SiSVGAProtect(pScrn, TRUE); 7898 } 7899 7900 /* First, restore CRT1 on/off and VB connection registers */ 7901 outSISIDXREG(SISCR, 0x32, pSiS->oldCR32); 7902 if(!(pSiS->oldCR17 & 0x80)) { /* CRT1 was off */ 7903 if(!(SiSBridgeIsInSlaveMode(pScrn))) { /* Bridge is NOT in SlaveMode now -> do it */ 7904 doit = TRUE; 7905 } else { 7906 doitlater = TRUE; 7907 } 7908 } else { /* CRT1 was on -> do it now */ 7909 doit = TRUE; 7910 } 7911 7912 if(doit) { 7913 outSISIDXREG(SISCR, 0x17, pSiS->oldCR17); 7914 } 7915 if(pSiS->VGAEngine == SIS_315_VGA) { 7916 outSISIDXREG(SISCR, pSiS->myCR63, pSiS->oldCR63); 7917 } 7918 7919 outSISIDXREG(SISSR, 0x1f, pSiS->oldSR1F); 7920 7921 /* For 30xB/LV, restoring the registers does not 7922 * work. We "manually" set the old mode, instead. 7923 * The same applies for SiS730 machines with LVDS. 7924 * Finally, this behavior can be forced by setting 7925 * the option RestoreBySetMode. 7926 */ 7927 if( ( (pSiS->restorebyset) || 7928 (pSiS->VBFlags2 & VB2_30xBLV) || 7929 ((pSiS->ChipType == SIS_730) && (pSiS->VBFlags2 & VB2_LVDS)) ) && 7930 (pSiS->OldMode) ) { 7931 7932 Bool changedmode = FALSE; 7933 7934 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 7935 "Restoring by setting old mode 0x%02x\n", pSiS->OldMode); 7936 7937 if(((pSiS->OldMode <= 0x13) || (!pSiS->sisfbfound)) && (pSiS->pVbe)) { 7938 int vmode = SiSTranslateToVESA(pScrn, pSiS->OldMode); 7939 if(vmode > 0) { 7940 if(vmode > 0x13) vmode |= ((1 << 15) | (1 << 14)); 7941 if(VBESetVBEMode(pSiS->pVbe, vmode, NULL) == TRUE) { 7942 SISSpecialRestore(pScrn); 7943 SiS_GetSetModeID(pScrn,pSiS->OldMode); 7944 vesasuccess = TRUE; 7945 } else { 7946 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 7947 "VBE failed to restore mode 0x%x\n", pSiS->OldMode); 7948 } 7949 } else { 7950 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 7951 "Can't identify VESA mode number for mode 0x%x\n", pSiS->OldMode); 7952 } 7953 } 7954 7955 if(vesasuccess == FALSE) { 7956 7957 int backupscaler = pSiS->SiS_Pr->UsePanelScaler; 7958 int backupcenter = pSiS->SiS_Pr->CenterScreen; 7959 ULong backupspecialtiming = pSiS->SiS_Pr->SiS_CustomT; 7960 int mymode = pSiS->OldMode; 7961 7962 if((pSiS->VGAEngine == SIS_315_VGA) && 7963 ((pSiS->ROM661New) || (pSiS->ChipFlags & SiSCF_IsXGI)) && 7964 (!pSiS->sisfbfound)) { 7965 /* New SiS BIOS or XGI BIOS has set mode, therefore eventually translate number */ 7966 mymode = SiSTranslateToOldMode(mymode); 7967 } 7968 7969 if((pSiS->VBFlags2 & VB2_30xBLV)) { 7970 /* !!! REQUIRED for 630+301B-DH, otherwise the text modes 7971 * will not be restored correctly !!! 7972 * !!! Do this ONLY for LCD; VGA2 will not be restored 7973 * correctly otherwise. 7974 */ 7975 UChar temp; 7976 inSISIDXREG(SISCR, 0x30, temp); 7977 if(temp & 0x20) { 7978 if(mymode == 0x03) { 7979 mymode = 0x13; 7980 changedmode = TRUE; 7981 } 7982 } 7983 } 7984 7985 pSiS->SiS_Pr->UseCustomMode = FALSE; 7986 pSiS->SiS_Pr->CRT1UsesCustomMode = FALSE; 7987 pSiS->SiS_Pr->CenterScreen = 0; 7988 if(pSiS->sisfbfound) { 7989 pSiS->SiS_Pr->UsePanelScaler = pSiS->sisfbscalelcd; 7990 pSiS->SiS_Pr->SiS_CustomT = pSiS->sisfbspecialtiming; 7991 } else { 7992 pSiS->SiS_Pr->UsePanelScaler = -1; 7993 /* Leave CustomT as it is */ 7994 } 7995 SiS_SetEnableDstn(pSiS->SiS_Pr, FALSE); 7996 SiS_SetEnableFstn(pSiS->SiS_Pr, FALSE); 7997 if((pSiS->ChipType == SIS_550) && (pSiS->sisfbfound)) { 7998 if(pSiS->sisfbxSTN) { 7999 SiS_SetEnableDstn(pSiS->SiS_Pr, pSiS->sisfbDSTN); 8000 SiS_SetEnableFstn(pSiS->SiS_Pr, pSiS->sisfbFSTN); 8001 } else if(mymode == 0x5a || mymode == 0x5b) { 8002 SiS_SetEnableFstn(pSiS->SiS_Pr, TRUE); 8003 } 8004 } 8005 SiSSetMode(pSiS->SiS_Pr, pScrn, mymode, FALSE); 8006 if(changedmode) { 8007 outSISIDXREG(SISCR,0x34,0x03); 8008 } 8009 SISSpecialRestore(pScrn); 8010 SiS_GetSetModeID(pScrn, pSiS->OldMode); /* NOT mymode! */ 8011 pSiS->SiS_Pr->UsePanelScaler = backupscaler; 8012 pSiS->SiS_Pr->CenterScreen = backupcenter; 8013 pSiS->SiS_Pr->SiS_CustomT = backupspecialtiming; 8014 SiS_SiSFB_Lock(pScrn, FALSE); 8015 SiSRestore_SiSFB_TVParms(pScrn); 8016 SiS_SiSFB_Lock(pScrn, TRUE); 8017 8018 } 8019 8020 /* Restore CRT1 status */ 8021 if(pSiS->VGAEngine == SIS_315_VGA) { 8022 outSISIDXREG(SISCR, pSiS->myCR63, pSiS->oldCR63); 8023 } 8024 outSISIDXREG(SISSR, 0x1f, pSiS->oldSR1F); 8025 8026#ifdef SISVRAMQ 8027 /* Restore queue mode registers on 315/330/340 series */ 8028 /* (This became necessary due to the switch to VRAM queue) */ 8029 SiSRestoreQueueMode(pSiS, sisReg); 8030#endif 8031 8032 } else { 8033 8034 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 8035 /* If a video bridge is present, we need to restore 8036 * non-extended (=standard VGA) SR and CR registers 8037 * before restoring the extended ones and the bridge 8038 * registers. 8039 */ 8040 if(!(SiSBridgeIsInSlaveMode(pScrn))) { 8041 SiSVGAProtect(pScrn, TRUE); 8042 SiSVGARestore(pScrn, sisReg, SISVGA_SR_MODE); 8043 } 8044 } 8045 8046 (*pSiS->SiSRestore)(pScrn, sisReg); 8047 8048 } 8049 8050 if(doitlater) { 8051 outSISIDXREG(SISCR, 0x17, pSiS->oldCR17); 8052 } 8053 8054 8055 8056 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (SiSBridgeIsInSlaveMode(pScrn))) { 8057 8058 /* IMPORTANT: The 30xLV does not handle well being disabled if in 8059 * LCDA mode! In LCDA mode, the bridge is NOT in slave mode, 8060 * so this is the only safe way: Disable the bridge ONLY if 8061 * in Slave Mode, and don't bother if not. 8062 */ 8063 8064 if(flags & SISVGA_SR_FONTS) { 8065 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO+0x30); 8066 SiSSetLVDSetc(pSiS->SiS_Pr, 0); 8067 SiS_GetVBType(pSiS->SiS_Pr); 8068 SiS_DisableBridge(pSiS->SiS_Pr); 8069 SiSVGAProtect(pScrn, TRUE); 8070 } 8071 8072 SiSVGARestore(pScrn, sisReg, flags); 8073 8074 if(flags & SISVGA_SR_FONTS) { 8075 SiSVGAProtect(pScrn, FALSE); 8076 SiS_EnableBridge(pSiS->SiS_Pr); 8077 andSISIDXREG(SISSR, 0x01, ~0x20); /* Display on */ 8078 } 8079 8080 } else { 8081 8082 SiSVGAProtect(pScrn, TRUE); 8083 SiSVGARestore(pScrn, sisReg, flags); 8084 SiSVGAProtect(pScrn, FALSE); 8085 8086 } 8087 8088 SiSFixupSR11(pScrn); 8089 8090#ifdef TWDEBUG 8091 { 8092 SISRegPtr pReg = &pSiS->ModeReg; 8093 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8094 "REAL REGISTER CONTENTS AFTER RESTORE BY SETMODE:\n"); 8095 (*pSiS->SiSSave)(pScrn, pReg); 8096 } 8097#endif 8098 8099 sisRestoreExtRegisterLock(pSiS,sisReg->sisRegs3C4[0x05],sisReg->sisRegs3D4[0x80]); 8100 8101 } else { /* All other chipsets */ 8102 8103 SiSVGAProtect(pScrn, TRUE); 8104 8105#ifdef UNLOCK_ALWAYS 8106 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8107#endif 8108 8109 (*pSiS->SiSRestore)(pScrn, sisReg); 8110 8111 SiSVGAProtect(pScrn, TRUE); 8112 8113 SiSVGARestore(pScrn, sisReg, flags); 8114 8115 /* Restore TV. This is rather complicated, but if we don't do it, 8116 * TV output will flicker terribly 8117 */ 8118 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 8119 if(sisReg->sis6326tv[0] & 0x04) { 8120 UChar tmp; 8121 int val; 8122 8123 orSISIDXREG(SISSR, 0x01, 0x20); 8124 tmp = SiS6326GetTVReg(pScrn,0x00); 8125 tmp &= ~0x04; 8126 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 8127 SiS6326SetTVReg(pScrn,0x00,tmp); 8128 for(val=0; val < 2; val++) { 8129 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 8130 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 8131 } 8132 SiS6326SetTVReg(pScrn, 0x00, sisReg->sis6326tv[0]); 8133 tmp = inSISREG(SISINPSTAT); 8134 outSISREG(SISAR, 0x20); 8135 tmp = inSISREG(SISINPSTAT); 8136 while(inSISREG(SISINPSTAT) & 0x01); 8137 while(!(inSISREG(SISINPSTAT) & 0x01)); 8138 andSISIDXREG(SISSR, 0x01, ~0x20); 8139 for(val=0; val < 10; val++) { 8140 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 8141 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 8142 } 8143 andSISIDXREG(SISSR, 0x01, ~0x20); 8144 } 8145 } 8146 8147 sisRestoreExtRegisterLock(pSiS,sisReg->sisRegs3C4[5],sisReg->sisRegs3D4[0x80]); 8148 8149 SiSVGAProtect(pScrn, FALSE); 8150 } 8151} 8152 8153static void 8154SISVESARestore(ScrnInfoPtr pScrn) 8155{ 8156 SISPtr pSiS = SISPTR(pScrn); 8157#ifdef SISVRAMQ 8158 SISRegPtr sisReg = &pSiS->SavedReg; 8159#endif 8160 8161 if(pSiS->UseVESA) { 8162 SISVESASaveRestore(pScrn, MODE_RESTORE); 8163#ifdef SISVRAMQ 8164 /* Restore queue mode registers on 315/330/340 series */ 8165 /* (This became necessary due to the switch to VRAM queue) */ 8166 SiSRestoreQueueMode(pSiS, sisReg); 8167#endif 8168 } 8169} 8170 8171/* Restore bridge config registers - to be called BEFORE VESARestore */ 8172static void 8173SISBridgeRestore(ScrnInfoPtr pScrn) 8174{ 8175 SISPtr pSiS = SISPTR(pScrn); 8176 8177#ifdef SISDUALHEAD 8178 /* We only restore for master head */ 8179 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 8180#endif 8181 8182 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 8183 SiSRestoreBridge(pScrn, &pSiS->SavedReg); 8184 } 8185} 8186 8187/* Our BlockHandler */ 8188static void 8189SISBlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask) 8190{ 8191 ScreenPtr pScreen = screenInfo.screens[i]; 8192 ScrnInfoPtr pScrn = xf86Screens[i]; 8193 SISPtr pSiS = SISPTR(pScrn); 8194 8195 pScreen->BlockHandler = pSiS->BlockHandler; 8196 (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); 8197 pScreen->BlockHandler = SISBlockHandler; 8198 8199#ifdef SISDUALHEAD 8200 if(pSiS->NeedCopyFastVidCpy) { 8201 SISEntPtr pSiSEnt = pSiS->entityPrivate; 8202 if(pSiSEnt->HaveFastVidCpy) { 8203 pSiS->NeedCopyFastVidCpy = FALSE; 8204 pSiS->SiSFastVidCopy = pSiSEnt->SiSFastVidCopy; 8205 pSiS->SiSFastMemCopy = pSiSEnt->SiSFastMemCopy; 8206 pSiS->SiSFastVidCopyFrom = pSiSEnt->SiSFastVidCopyFrom; 8207 pSiS->SiSFastMemCopyFrom = pSiSEnt->SiSFastMemCopyFrom; 8208 } 8209 } 8210#endif 8211 8212 if(pSiS->VideoTimerCallback) { 8213 (*pSiS->VideoTimerCallback)(pScrn, currentTime.milliseconds); 8214 } 8215 8216#ifdef SIS_USE_XAA 8217 if(pSiS->RenderCallback) { 8218 (*pSiS->RenderCallback)(pScrn); 8219 } 8220#endif 8221#ifdef SIS_USE_EXA 8222 if(pSiS->ExaRenderCallback) { 8223 (*pSiS->ExaRenderCallback)(pScrn); 8224 } 8225#endif 8226} 8227 8228 8229 8230/* Do screen blanking; DPMS handling 8231 * 8232 * Mandatory; latter optional 8233 */ 8234 8235static void 8236SiSHandleBackLight(SISPtr pSiS, Bool blon) 8237{ 8238 UChar sr11mask = (pSiS->SiS_Pr->SiS_SensibleSR11) ? 0x03 : 0xf3; 8239 8240 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) { 8241 8242 if(!blon) { 8243 SiS_SiS30xBLOff(pSiS->SiS_Pr); 8244 } else { 8245 SiS_SiS30xBLOn(pSiS->SiS_Pr); 8246 } 8247 8248 } else if( ((pSiS->VGAEngine == SIS_300_VGA) && 8249 (pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH))) || 8250 ((pSiS->VGAEngine == SIS_315_VGA) && 8251 ((pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS)) ) { 8252 8253 if(!blon) { 8254 setSISIDXREG(SISSR, 0x11, sr11mask, 0x08); 8255 } else { 8256 setSISIDXREG(SISSR, 0x11, sr11mask, 0x00); 8257 } 8258 8259 } else if((pSiS->VGAEngine == SIS_315_VGA) && 8260 (pSiS->VBFlags2 & VB2_CHRONTEL)) { 8261 8262 if(!blon) { 8263 SiS_Chrontel701xBLOff(pSiS->SiS_Pr); 8264 } else { 8265 SiS_Chrontel701xBLOn(pSiS->SiS_Pr); 8266 } 8267 8268 } 8269} 8270 8271static Bool 8272SISSaveScreen(ScreenPtr pScreen, int mode) 8273{ 8274 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 8275 SISPtr pSiS; 8276 Bool IsUnblank = xf86IsUnblank(mode) ? TRUE : FALSE; 8277 8278 if((pScrn == NULL) || (!pScrn->vtSema)) return TRUE; 8279 8280 pSiS = SISPTR(pScrn); 8281 8282#ifdef UNLOCK_ALWAYS 8283 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8284#endif 8285 8286 if(pSiS->VBFlags & (CRT2_LCD | CRT1_LCDA)) { 8287 SiSHandleBackLight(pSiS, IsUnblank); 8288 } 8289 8290 if(!SiSBridgeIsInSlaveMode(pScrn)) { 8291 return SiSVGASaveScreen(pScreen, mode); 8292 } 8293 8294 return TRUE; 8295} 8296 8297#ifdef SISDUALHEAD 8298/* SaveScreen for dual head mode */ 8299static Bool 8300SISSaveScreenDH(ScreenPtr pScreen, int mode) 8301{ 8302 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 8303 SISPtr pSiS; 8304 Bool IsUnblank = xf86IsUnblank(mode) ? TRUE : FALSE; 8305 8306 if((pScrn == NULL) || (!pScrn->vtSema)) return TRUE; 8307 8308 pSiS = SISPTR(pScrn); 8309 8310 if( (pSiS->SecondHead) && 8311 ((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) ) { 8312 8313 /* Slave head is always CRT1 */ 8314 /* (No backlight handling on TMDS bridges) */ 8315 return SiSVGASaveScreen(pScreen, mode); 8316 8317 } else { 8318 8319 /* Master head is always CRT2 */ 8320 /* But we land here for LCDA, too (if bridge is SiS LVDS type) */ 8321 8322 /* We can only blank LCD, not other CRT2 devices */ 8323 if(pSiS->VBFlags & (CRT2_LCD|CRT1_LCDA)) { 8324 8325#ifdef UNLOCK_ALWAYS 8326 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8327#endif 8328 SiSHandleBackLight(pSiS, IsUnblank); 8329 8330 } 8331 8332 } 8333 return TRUE; 8334} 8335#endif 8336 8337static void 8338SISDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags) 8339{ 8340 SISPtr pSiS = SISPTR(pScrn); 8341 Bool docrt1 = TRUE, docrt2 = TRUE, backlight = TRUE; 8342 UChar sr1=0, cr17=0, cr63=0, pmreg=0, sr7=0; 8343 UChar p1_13=0, p2_0=0, oldpmreg=0; 8344 8345 if(!pScrn->vtSema) return; 8346 8347 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, 8348 "SISDisplayPowerManagementSet(%d)\n", PowerManagementMode); 8349 8350#ifdef SISDUALHEAD 8351 if(pSiS->DualHeadMode) { 8352 if(pSiS->SecondHead) docrt2 = FALSE; 8353 else docrt1 = FALSE; 8354 } 8355#endif 8356 8357 /* Work around a bug in xf86Event.c: 8358 * pScrn->DPMSSet is being called without a previous 8359 * call to xf86EnableAccess(). So we have no hardware 8360 * access here. 8361 */ 8362 outSISIDXREG(SISSR,0x05,0x86); 8363 inSISIDXREG(SISSR,0x05,pmreg); 8364 if(pmreg != 0xa1) return; 8365 8366#ifdef UNLOCK_ALWAYS 8367 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8368#endif 8369 8370 switch(PowerManagementMode) { 8371 8372 case DPMSModeOn: /* HSync: On, VSync: On */ 8373 sr1 = 0x00; 8374 cr17 = 0x80; 8375 pmreg = 0x00; 8376 cr63 = 0x00; 8377 sr7 = 0x10; 8378 p2_0 = 0x20; 8379 p1_13 = 0x00; 8380 backlight = TRUE; 8381 break; 8382 8383 case DPMSModeSuspend: /* HSync: On, VSync: Off */ 8384 sr1 = 0x20; 8385 cr17 = 0x80; 8386 pmreg = 0x80; 8387 cr63 = 0x40; 8388 sr7 = 0x00; 8389 p2_0 = 0x40; 8390 p1_13 = 0x80; 8391 backlight = FALSE; 8392 break; 8393 8394 case DPMSModeStandby: /* HSync: Off, VSync: On */ 8395 sr1 = 0x20; 8396 cr17 = 0x80; 8397 pmreg = 0x40; 8398 cr63 = 0x40; 8399 sr7 = 0x00; 8400 p2_0 = 0x80; 8401 p1_13 = 0x40; 8402 backlight = FALSE; 8403 break; 8404 8405 case DPMSModeOff: /* HSync: Off, VSync: Off */ 8406 sr1 = 0x20; 8407 cr17 = 0x00; 8408 pmreg = 0xc0; 8409 cr63 = 0x40; 8410 sr7 = 0x00; 8411 p2_0 = 0xc0; 8412 p1_13 = 0xc0; 8413 backlight = FALSE; 8414 break; 8415 8416 default: 8417 return; 8418 } 8419 8420 oldpmreg = pmreg; 8421 8422 if((docrt2 && (pSiS->VBFlags & CRT2_LCD)) || 8423 (docrt1 && (pSiS->VBFlags & CRT1_LCDA))) { 8424 SiSHandleBackLight(pSiS, backlight); 8425 } 8426 8427 if(docrt1) { 8428 switch(pSiS->VGAEngine) { 8429 case SIS_OLD_VGA: 8430 case SIS_530_VGA: 8431 setSISIDXREG(SISSR, 0x01, ~0x20, sr1); /* Set/Clear "Display On" bit */ 8432 inSISIDXREG(SISSR, 0x11, oldpmreg); 8433 setSISIDXREG(SISCR, 0x17, 0x7f, cr17); 8434 setSISIDXREG(SISSR, 0x11, 0x3f, pmreg); 8435 break; 8436 case SIS_315_VGA: 8437 if( (!pSiS->CRT1off) && 8438 ((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) ) { 8439 setSISIDXREG(SISCR, pSiS->myCR63, 0xbf, cr63); 8440 setSISIDXREG(SISSR, 0x07, 0xef, sr7); 8441 } 8442 /* fall through */ 8443 default: 8444 if(!SiSBridgeIsInSlaveMode(pScrn)) { 8445 setSISIDXREG(SISSR, 0x01, ~0x20, sr1); /* Set/Clear "Display On" bit */ 8446 } 8447 if((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 8448 inSISIDXREG(SISSR, 0x1f, oldpmreg); 8449 if((!pSiS->CRT1off) && (!SiSBridgeIsInSlaveMode(pScrn))) { 8450 setSISIDXREG(SISSR, 0x1f, 0x3f, pmreg); 8451 } 8452 } 8453 } 8454 oldpmreg &= 0xc0; 8455 } 8456 8457 if(docrt2) { 8458 if(pSiS->VBFlags & CRT2_LCD) { 8459 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && 8460 (!(pSiS->VBFlags2 & VB2_30xBDH))) { 8461 if(pSiS->VGAEngine == SIS_300_VGA) { 8462 SiS_UnLockCRT2(pSiS->SiS_Pr); 8463 setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13); 8464 } 8465 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) p2_0 |= 0x20; 8466 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); 8467 } 8468 } else if(pSiS->VBFlags & (CRT2_VGA | CRT2_TV)) { 8469 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 8470 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); 8471 } 8472 } 8473 } 8474 8475 if( (docrt1) && 8476 (pmreg != oldpmreg) && 8477 ((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) ) { 8478 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 8479 usleep(10000); 8480 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 8481 } 8482 8483} 8484 8485/* Mandatory 8486 * This gets called at the start of each server generation 8487 * 8488 * We use pScrn and not CurrentLayout here, because the 8489 * properties we use have not changed (displayWidth, 8490 * depth, bitsPerPixel) 8491 */ 8492static Bool 8493SISScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) 8494{ 8495 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 8496 SISPtr pSiS = SISPTR(pScrn); 8497 VisualPtr visual; 8498 ULong OnScreenSize; 8499 int ret, height, width, displayWidth; 8500 UChar *FBStart; 8501#ifdef SISDUALHEAD 8502 SISEntPtr pSiSEnt = NULL; 8503#endif 8504 8505#ifdef SISDUALHEAD 8506 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) { 8507#endif 8508 SiS_LoadInitVBE(pScrn); 8509#ifdef SISDUALHEAD 8510 } 8511#endif 8512 8513#ifdef SISDUALHEAD 8514 if(pSiS->DualHeadMode) { 8515 pSiSEnt = pSiS->entityPrivate; 8516 pSiSEnt->refCount++; 8517 } 8518#endif 8519 8520#ifdef SIS_PC_PLATFORM 8521 /* Map 64k VGA window for saving/restoring CGA fonts */ 8522 SiS_MapVGAMem(pScrn); 8523#endif 8524 8525 /* Map the SiS memory and MMIO areas */ 8526 if(!SISMapMem(pScrn)) { 8527 SISErrorLog(pScrn, "SiSMapMem() failed\n"); 8528 return FALSE; 8529 } 8530 8531 SiS_SiSFB_Lock(pScrn, TRUE); 8532 8533#ifdef UNLOCK_ALWAYS 8534 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8535#endif 8536 8537 /* Enable TurboQueue so that SISSave() saves it in enabled 8538 * state. If we don't do this, X will hang after a restart! 8539 * (Happens for some unknown reason only when using VESA 8540 * for mode switching; assumingly a BIOS issue.) 8541 * This is done on 300 and 315 series only. 8542 */ 8543 if(pSiS->UseVESA) { 8544#ifdef SISVRAMQ 8545 if(pSiS->VGAEngine != SIS_315_VGA) 8546#endif 8547 SiSEnableTurboQueue(pScrn); 8548 } 8549 8550 /* Save the current state */ 8551 SISSave(pScrn); 8552 8553 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 8554 8555 if(!pSiS->OldMode) { 8556 8557 /* Try to find out current (=old) mode number 8558 * (Do this only if not sisfb has told us its mode yet) 8559 */ 8560 8561 /* Read 0:449 which the BIOS sets to the current mode number 8562 * Unfortunately, this not reliable since the int10 emulation 8563 * does not change this. So if we call the VBE later, this 8564 * byte won't be touched (which is why we set this manually 8565 * then). 8566 */ 8567 UChar myoldmode = SiS_GetSetModeID(pScrn, 0xFF); 8568 UChar cr30, cr31; 8569 8570 /* Read CR34 which the BIOS sets to the current mode number for CRT2 8571 * This is - of course - not reliable if the machine has no video 8572 * bridge... 8573 */ 8574 inSISIDXREG(SISCR, 0x34, pSiS->OldMode); 8575 inSISIDXREG(SISCR, 0x30, cr30); 8576 inSISIDXREG(SISCR, 0x31, cr31); 8577 8578 /* What if CR34 is different from the BIOS scratch byte? */ 8579 if(pSiS->OldMode != myoldmode) { 8580 /* If no bridge output is active, trust the BIOS scratch byte */ 8581 if( (!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) || 8582 (pSiS->OldMode == 0) || 8583 (!cr31 && !cr30) || 8584 (cr31 & 0x20) ) { 8585 pSiS->OldMode = myoldmode; 8586 } 8587 /* ..else trust CR34 */ 8588 } 8589 8590 /* Newer 650 BIOSes set CR34 to 0xff if the mode has been 8591 * "patched", for instance for 80x50 text mode. (That mode 8592 * has no number of its own, it's 0x03 like 80x25). In this 8593 * case, we trust the BIOS scratch byte (provided that any 8594 * of these two is valid). 8595 */ 8596 if(pSiS->OldMode > 0x7f) { 8597 pSiS->OldMode = myoldmode; 8598 } 8599 } 8600#ifdef SISDUALHEAD 8601 if(pSiS->DualHeadMode) { 8602 if(!pSiS->SecondHead) pSiSEnt->OldMode = pSiS->OldMode; 8603 else pSiS->OldMode = pSiSEnt->OldMode; 8604 } 8605#endif 8606 } 8607 8608 /* RandR resets screen mode and size in CloseScreen(), hence 8609 * we need to adapt our VBFlags to the initial state if the 8610 * current mode has changed since closescreen() (or Screeninit() 8611 * for the first instance) 8612 */ 8613 if(pScrn->currentMode != pSiS->currentModeLast) { 8614 pSiS->VBFlags = pSiS->VBFlags_backup = pSiS->VBFlagsInit; 8615 } 8616 8617 /* Copy our detected monitor gammas, part 2. Note that device redetection 8618 * is not supported in DHM, so there is no need to do that anytime later. 8619 */ 8620#ifdef SISDUALHEAD 8621 if(pSiS->DualHeadMode) { 8622 if(!pSiS->SecondHead) { 8623 /* CRT2 */ 8624 pSiS->CRT1VGAMonitorGamma = pSiSEnt->CRT1VGAMonitorGamma; 8625 } else { 8626 /* CRT1 */ 8627 pSiS->CRT2VGAMonitorGamma = pSiSEnt->CRT2VGAMonitorGamma; 8628 } 8629 if(!pSiS->CRT2LCDMonitorGamma) pSiS->CRT2LCDMonitorGamma = pSiSEnt->CRT2LCDMonitorGamma; 8630 } 8631#endif 8632 8633 /* Initialize the first mode */ 8634 if(!SISModeInit(pScrn, pScrn->currentMode)) { 8635 SISErrorLog(pScrn, "SiSModeInit() failed\n"); 8636 return FALSE; 8637 } 8638 8639 /* Darken the screen for aesthetic reasons */ 8640 /* Not using Dual Head variant on purpose; we darken 8641 * the screen for both displays, and un-darken 8642 * it when the second head is finished 8643 */ 8644 SISSaveScreen(pScreen, SCREEN_SAVER_ON); 8645 8646 /* Set the viewport */ 8647 SISAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 8648 8649 /* Reset visual list. */ 8650 miClearVisualTypes(); 8651 8652 /* Setup the visuals we support. */ 8653 8654 /* 8655 * For bpp > 8, the default visuals are not acceptable because we only 8656 * support TrueColor and not DirectColor. 8657 */ 8658 if(!miSetVisualTypes(pScrn->depth, 8659 (pScrn->bitsPerPixel > 8) ? 8660 TrueColorMask : miGetDefaultVisualMask(pScrn->depth), 8661 pScrn->rgbBits, pScrn->defaultVisual)) { 8662 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8663 SISErrorLog(pScrn, "miSetVisualTypes() failed (bpp %d)\n", 8664 pScrn->bitsPerPixel); 8665 return FALSE; 8666 } 8667 8668 width = pScrn->virtualX; 8669 height = pScrn->virtualY; 8670 displayWidth = pScrn->displayWidth; 8671 8672 if(pSiS->Rotate) { 8673 height = pScrn->virtualX; 8674 width = pScrn->virtualY; 8675 } 8676 8677 if(pSiS->ShadowFB) { 8678 pSiS->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); 8679 pSiS->ShadowPtr = xalloc(pSiS->ShadowPitch * height); 8680 displayWidth = pSiS->ShadowPitch / (pScrn->bitsPerPixel >> 3); 8681 FBStart = pSiS->ShadowPtr; 8682 } else { 8683 pSiS->ShadowPtr = NULL; 8684 FBStart = pSiS->FbBase; 8685 } 8686 8687 if(!miSetPixmapDepths()) { 8688 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8689 SISErrorLog(pScrn, "miSetPixmapDepths() failed\n"); 8690 return FALSE; 8691 } 8692 8693 /* Point cmdQueuePtr to pSiSEnt for shared usage 8694 * (same technique is then eventually used in DRIScreeninit) 8695 * For 315/330 series, this is done in EnableTurboQueue 8696 * which has already been called during ModeInit(). 8697 */ 8698#ifdef SISDUALHEAD 8699 if(pSiS->SecondHead) 8700 pSiS->cmdQueueLenPtr = &(SISPTR(pSiSEnt->pScrn_1)->cmdQueueLen); 8701 else 8702#endif 8703 pSiS->cmdQueueLenPtr = &(pSiS->cmdQueueLen); 8704 8705 pSiS->cmdQueueLen = 0; /* Force an EngineIdle() at start */ 8706 8707#ifdef XF86DRI 8708 if(pSiS->loadDRI) { 8709#ifdef SISDUALHEAD 8710 /* No DRI in dual head mode */ 8711 if(pSiS->DualHeadMode) { 8712 pSiS->directRenderingEnabled = FALSE; 8713 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8714 "DRI not supported in Dual Head mode\n"); 8715 } else 8716#endif 8717 if(pSiS->VGAEngine != SIS_315_VGA) { 8718 /* Force the initialization of the context */ 8719 pSiS->directRenderingEnabled = SISDRIScreenInit(pScreen); 8720 } else { 8721 xf86DrvMsg(pScrn->scrnIndex, X_NOT_IMPLEMENTED, 8722 "DRI not supported on this chipset\n"); 8723 pSiS->directRenderingEnabled = FALSE; 8724 } 8725 } 8726#endif 8727 8728 /* Call the framebuffer layer's ScreenInit function and fill in other 8729 * pScreen fields. 8730 */ 8731 switch(pScrn->bitsPerPixel) { 8732 case 24: 8733 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 8734 ret = FALSE; 8735 break; 8736 } 8737 /* fall through */ 8738 case 8: 8739 case 16: 8740 case 32: 8741 ret = fbScreenInit(pScreen, FBStart, width, 8742 height, pScrn->xDpi, pScrn->yDpi, 8743 displayWidth, pScrn->bitsPerPixel); 8744 break; 8745 default: 8746 ret = FALSE; 8747 break; 8748 } 8749 if(!ret) { 8750 SISErrorLog(pScrn, "Unsupported bpp (%d) or fbScreenInit() failed\n", 8751 pScrn->bitsPerPixel); 8752 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8753 return FALSE; 8754 } 8755 8756 /* Fixup RGB ordering */ 8757 if(pScrn->bitsPerPixel > 8) { 8758 visual = pScreen->visuals + pScreen->numVisuals; 8759 while (--visual >= pScreen->visuals) { 8760 if((visual->class | DynamicClass) == DirectColor) { 8761 visual->offsetRed = pScrn->offset.red; 8762 visual->offsetGreen = pScrn->offset.green; 8763 visual->offsetBlue = pScrn->offset.blue; 8764 visual->redMask = pScrn->mask.red; 8765 visual->greenMask = pScrn->mask.green; 8766 visual->blueMask = pScrn->mask.blue; 8767 } 8768 } 8769 } 8770 8771 /* Initialize RENDER extension (must be after RGB ordering fixed) */ 8772 fbPictureInit(pScreen, 0, 0); 8773 8774 /* Hardware cursor needs to wrap this layer */ 8775 if(!pSiS->ShadowFB) SISDGAInit(pScreen); 8776 8777 xf86SetBlackWhitePixels(pScreen); 8778 8779 /* Initialize the accelerators */ 8780 switch(pSiS->VGAEngine) { 8781 case SIS_530_VGA: 8782 case SIS_300_VGA: 8783 SiS300AccelInit(pScreen); 8784 break; 8785 case SIS_315_VGA: 8786 SiS315AccelInit(pScreen); 8787 break; 8788 default: 8789 SiSAccelInit(pScreen); 8790 } 8791 8792#ifdef TWDEBUG 8793 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CPUFlags %x\n", pSiS->CPUFlags); 8794#endif 8795 8796 /* Benchmark memcpy() methods (needs FB manager initialized) */ 8797 /* Dual head: Do this AFTER the mode for CRT1 has been set */ 8798 pSiS->NeedCopyFastVidCpy = FALSE; 8799 if(!pSiS->SiSFastVidCopyDone) { 8800#ifdef SISDUALHEAD 8801 if(pSiS->DualHeadMode) { 8802 if(pSiS->SecondHead) { 8803 pSiSEnt->SiSFastVidCopy = SiSVidCopyInit(pScreen, &pSiSEnt->SiSFastMemCopy, FALSE); 8804 pSiSEnt->SiSFastVidCopyFrom = SiSVidCopyGetDefault(); 8805 pSiSEnt->SiSFastMemCopyFrom = SiSVidCopyGetDefault(); 8806#ifdef SIS_USE_EXA 8807 if(pSiS->useEXA) { 8808 pSiSEnt->SiSFastVidCopyFrom = SiSVidCopyInit(pScreen, &pSiSEnt->SiSFastMemCopyFrom, TRUE); 8809 } 8810#endif /* EXA */ 8811 pSiSEnt->HaveFastVidCpy = TRUE; 8812 pSiS->SiSFastVidCopy = pSiSEnt->SiSFastVidCopy; 8813 pSiS->SiSFastMemCopy = pSiSEnt->SiSFastMemCopy; 8814 pSiS->SiSFastVidCopyFrom = pSiSEnt->SiSFastVidCopyFrom; 8815 pSiS->SiSFastMemCopyFrom = pSiSEnt->SiSFastMemCopyFrom; 8816 } else { 8817 pSiS->NeedCopyFastVidCpy = TRUE; 8818 } 8819 } else { 8820#endif 8821 pSiS->SiSFastVidCopy = SiSVidCopyInit(pScreen, &pSiS->SiSFastMemCopy, FALSE); 8822 pSiS->SiSFastVidCopyFrom = SiSVidCopyGetDefault(); 8823 pSiS->SiSFastMemCopyFrom = SiSVidCopyGetDefault(); 8824#ifdef SIS_USE_EXA 8825 if(pSiS->useEXA) { 8826 pSiS->SiSFastVidCopyFrom = SiSVidCopyInit(pScreen, &pSiS->SiSFastMemCopyFrom, TRUE); 8827 } 8828#endif /* EXA */ 8829#ifdef SISDUALHEAD 8830 } 8831#endif 8832 } 8833 pSiS->SiSFastVidCopyDone = TRUE; 8834 8835 miInitializeBackingStore(pScreen); 8836 xf86SetBackingStore(pScreen); 8837 xf86SetSilkenMouse(pScreen); 8838 8839 /* Initialise cursor functions */ 8840 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 8841 8842 if(pSiS->HWCursor) { 8843 SiSHWCursorInit(pScreen); 8844 } 8845 8846#ifdef SISDUALHEAD 8847 if(!pSiS->DualHeadMode) { 8848#endif 8849 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && (pScrn->depth > 8)) { 8850 8851 pSiS->CRT2ColNum = 1 << pScrn->rgbBits; 8852 8853 if((pSiS->crt2gcolortable = xalloc(pSiS->CRT2ColNum * 2 * sizeof(LOCO)))) { 8854 pSiS->crt2colors = &pSiS->crt2gcolortable[pSiS->CRT2ColNum]; 8855 if((pSiS->crt2cindices = xalloc(256 * sizeof(int)))) { 8856 int i = pSiS->CRT2ColNum; 8857 SISCalculateGammaRampCRT2(pScrn); 8858 while(i--) pSiS->crt2cindices[i] = i; 8859 } else { 8860 xfree(pSiS->crt2gcolortable); 8861 pSiS->crt2gcolortable = NULL; 8862 pSiS->CRT2SepGamma = FALSE; 8863 } 8864 } else { 8865 pSiS->CRT2SepGamma = FALSE; 8866 } 8867 8868 if(!pSiS->crt2cindices) { 8869 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 8870 "Failed to allocate cmap for CRT2, separate gamma correction disabled\n"); 8871 } 8872 8873 } 8874#ifdef SISDUALHEAD 8875 } else pSiS->CRT2SepGamma = FALSE; 8876#endif 8877 8878 /* Initialise default colormap */ 8879 if(!miCreateDefColormap(pScreen)) { 8880 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8881 SISErrorLog(pScrn, "miCreateDefColormap() failed\n"); 8882 return FALSE; 8883 } 8884 8885 if(!xf86HandleColormaps(pScreen, 256, (pScrn->depth == 8) ? 8 : pScrn->rgbBits, 8886 SISLoadPalette, NULL, 8887 CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH)) { 8888 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8889 SISErrorLog(pScrn, "xf86HandleColormaps() failed\n"); 8890 return FALSE; 8891 } 8892 8893 /* Recalculate our gamma ramp for brightness feature */ 8894#ifdef SISGAMMARAMP 8895 if((pSiS->GammaBriR != 1000) || 8896 (pSiS->GammaBriB != 1000) || 8897 (pSiS->GammaBriG != 1000) || 8898 (pSiS->NewGammaBriR != 0.0) || 8899 (pSiS->NewGammaBriG != 0.0) || 8900 (pSiS->NewGammaBriB != 0.0) || 8901 (pSiS->NewGammaConR != 0.0) || 8902 (pSiS->NewGammaConG != 0.0) || 8903 (pSiS->NewGammaConB != 0.0)) { 8904 SISCalculateGammaRamp(pScreen, pScrn); 8905 } 8906#endif 8907 8908 /* Initialize Shadow framebuffer and screen rotation/reflection */ 8909 if(pSiS->ShadowFB) { 8910 RefreshAreaFuncPtr refreshArea = SISRefreshArea; 8911 8912 if(pSiS->Rotate) { 8913 if(!pSiS->PointerMoved) pSiS->PointerMoved = pScrn->PointerMoved; 8914 pScrn->PointerMoved = SISPointerMoved; 8915 switch(pScrn->bitsPerPixel) { 8916 case 8: refreshArea = SISRefreshArea8; break; 8917 case 16: refreshArea = SISRefreshArea16; break; 8918 case 24: refreshArea = SISRefreshArea24; break; 8919 case 32: refreshArea = SISRefreshArea32; break; 8920 } 8921#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 8922 xf86DisableRandR(); 8923 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8924 "Driver rotation enabled, disabling RandR\n"); 8925#endif 8926 } else if(pSiS->Reflect) { 8927 switch(pScrn->bitsPerPixel) { 8928 case 8: 8929 case 16: 8930 case 32: 8931 if(!pSiS->PointerMoved) pSiS->PointerMoved = pScrn->PointerMoved; 8932 pScrn->PointerMoved = SISPointerMovedReflect; 8933 refreshArea = SISRefreshAreaReflect; 8934#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 8935 xf86DisableRandR(); 8936 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8937 "Driver reflection enabled, disabling RandR\n"); 8938#endif 8939 break; 8940 default: 8941 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 8942 "Reflection not supported at this framebuffer depth\n"); 8943 } 8944 } 8945 8946 ShadowFBInit(pScreen, refreshArea); 8947 } 8948 8949 xf86DPMSInit(pScreen, (DPMSSetProcPtr)SISDisplayPowerManagementSet, 0); 8950 8951 /* Init memPhysBase and fbOffset in pScrn */ 8952 pScrn->memPhysBase = pSiS->FbAddress; 8953 pScrn->fbOffset = 0; 8954 8955 /* Initialize Xv */ 8956 pSiS->ResetXv = pSiS->ResetXvGamma = pSiS->ResetXvDisplay = NULL; 8957#if (XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,99,0,0)) || (defined(XvExtension)) 8958 if((!pSiS->NoXvideo) && (!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY))) { 8959 8960 if((pSiS->VGAEngine == SIS_300_VGA) || 8961 (pSiS->VGAEngine == SIS_315_VGA)) { 8962 8963 const char *using = "Using SiS300/315/330/340 series HW Xv"; 8964 8965#ifdef SISDUALHEAD 8966 if(pSiS->DualHeadMode) { 8967 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8968 "%s on CRT%d\n", using, (pSiS->SecondHead ? 1 : 2)); 8969 if(!pSiS->hasTwoOverlays) { 8970 if( (pSiS->XvOnCRT2 && pSiS->SecondHead) || 8971 (!pSiS->XvOnCRT2 && !pSiS->SecondHead) ) { 8972 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8973 "However, video overlay will by default only be visible on CRT%d\n", 8974 pSiS->XvOnCRT2 ? 2 : 1); 8975 } 8976 } 8977 } else { 8978#endif 8979 if(pSiS->hasTwoOverlays) { 8980 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s\n", using); 8981 } else { 8982 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s by default on CRT%d\n", 8983 using, (pSiS->XvOnCRT2 ? 2 : 1)); 8984 } 8985#ifdef SISDUALHEAD 8986 } 8987#endif 8988 8989 SISInitVideo(pScreen); 8990 8991 if(pSiS->blitadaptor) { 8992 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8993 "Default Xv adaptor is Video %s\n", 8994 pSiS->XvDefAdaptorBlit ? "Blitter" : "Overlay"); 8995 } 8996 8997 } else if(pSiS->Chipset == PCI_CHIP_SIS530 || 8998 pSiS->Chipset == PCI_CHIP_SIS6326 || 8999 pSiS->Chipset == PCI_CHIP_SIS5597) { 9000 9001 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9002 "Using SiS5597/5598/6326/530/620 HW Xv\n" ); 9003 9004 SIS6326InitVideo(pScreen); 9005 9006 } else { /* generic Xv */ 9007 9008 XF86VideoAdaptorPtr *ptr; 9009 int n = xf86XVListGenericAdaptors(pScrn, &ptr); 9010 9011 if(n) { 9012 xf86XVScreenInit(pScreen, ptr, n); 9013 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using generic Xv\n" ); 9014 } 9015 9016 } 9017 } 9018#endif 9019 9020#ifdef XF86DRI 9021 if(pSiS->loadDRI) { 9022 if(pSiS->directRenderingEnabled) { 9023 /* Now that mi, drm and others have done their thing, 9024 * complete the DRI setup. 9025 */ 9026 pSiS->directRenderingEnabled = SISDRIFinishScreenInit(pScreen); 9027 } 9028 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering %s\n", 9029 pSiS->directRenderingEnabled ? "enabled" : "disabled"); 9030 /* TODO */ 9031 /* if(pSiS->directRenderingEnabled) SISSetLFBConfig(pSiS); */ 9032 } 9033#endif 9034 9035 /* Wrap some funcs, initialize pseudo-Xinerama and setup remaining SD flags */ 9036 9037 pSiS->SiS_SD_Flags &= ~(SiS_SD_PSEUDOXINERAMA); 9038#ifdef SISMERGED 9039 if(pSiS->MergedFB) { 9040 pSiS->PointerMoved = pScrn->PointerMoved; 9041 pScrn->PointerMoved = SISMergedPointerMoved; 9042 pSiS->Rotate = 0; 9043 pSiS->Reflect = 0; 9044 pSiS->ShadowFB = FALSE; 9045#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 9046 if(pSiS->CRT1XOffs || pSiS->CRT1YOffs || pSiS->CRT2XOffs || pSiS->CRT2YOffs) { 9047 xf86DisableRandR(); 9048 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9049 "MergedFB: CRT2Position offset used, disabling RandR\n"); 9050 } 9051#endif 9052#ifdef SISXINERAMA 9053 if(pSiS->UseSiSXinerama) { 9054 SiSnoPanoramiXExtension = FALSE; 9055 SiSXineramaExtensionInit(pScrn); 9056 if(!SiSnoPanoramiXExtension) { 9057 pSiS->SiS_SD_Flags |= SiS_SD_PSEUDOXINERAMA; 9058 if(pSiS->HaveNonRect) { 9059 /* Reset the viewport (now eventually non-recangular) */ 9060 SISAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 9061 } 9062 } 9063 } else { 9064 pSiS->MouseRestrictions = FALSE; 9065 } 9066#endif 9067 } 9068#endif 9069 9070 /* Wrap CloseScreen and set up SaveScreen */ 9071 pSiS->CloseScreen = pScreen->CloseScreen; 9072 pScreen->CloseScreen = SISCloseScreen; 9073#ifdef SISDUALHEAD 9074 if(pSiS->DualHeadMode) 9075 pScreen->SaveScreen = SISSaveScreenDH; 9076 else 9077#endif 9078 pScreen->SaveScreen = SISSaveScreen; 9079 9080 /* Install BlockHandler */ 9081 pSiS->BlockHandler = pScreen->BlockHandler; 9082 pScreen->BlockHandler = SISBlockHandler; 9083 9084 /* Report any unused options (only for the first generation) */ 9085 if(serverGeneration == 1) { 9086 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 9087 } 9088 9089 /* Clear frame buffer */ 9090 /* For CRT2, we don't do that at this point in dual head 9091 * mode since the mode isn't switched at this time (it will 9092 * be reset when setting the CRT1 mode). Hence, we just 9093 * save the necessary data and clear the screen when 9094 * going through this for CRT1. 9095 */ 9096 9097 OnScreenSize = pScrn->displayWidth * pScrn->currentMode->VDisplay 9098 * (pScrn->bitsPerPixel >> 3); 9099 9100 /* Turn on the screen now */ 9101 /* We do this in dual head mode after second head is finished */ 9102#ifdef SISDUALHEAD 9103 if(pSiS->DualHeadMode) { 9104 if(pSiS->SecondHead) { 9105 sisclearvram(pSiS->FbBase, OnScreenSize); 9106 sisclearvram(pSiSEnt->FbBase1, pSiSEnt->OnScreenSize1); 9107 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 9108 } else { 9109 pSiSEnt->FbBase1 = pSiS->FbBase; 9110 pSiSEnt->OnScreenSize1 = OnScreenSize; 9111 } 9112 } else { 9113#endif 9114 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 9115 sisclearvram(pSiS->FbBase, OnScreenSize); 9116#ifdef SISDUALHEAD 9117 } 9118#endif 9119 9120 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTSGRCRT2; 9121#ifdef SISDUALHEAD 9122 if(!pSiS->DualHeadMode) { 9123#endif 9124 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 9125 if((pSiS->crt2cindices) && (pSiS->crt2gcolortable)) { 9126 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTSGRCRT2; 9127 } 9128 } 9129#ifdef SISDUALHEAD 9130 } 9131#endif 9132 9133 pSiS->SiS_SD_Flags &= ~SiS_SD_ISDEPTH8; 9134 if(pSiS->CurrentLayout.bitsPerPixel == 8) { 9135 pSiS->SiS_SD_Flags |= SiS_SD_ISDEPTH8; 9136 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTXVGAMMA1; 9137 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTSGRCRT2; 9138 } 9139 9140#ifdef SISGAMMARAMP 9141 pSiS->SiS_SD_Flags |= SiS_SD_CANSETGAMMA; 9142#else 9143 pSiS->SiS_SD_Flags &= ~SiS_SD_CANSETGAMMA; 9144#endif 9145 9146 SiSCtrlExtInit(pScrn); 9147 9148 return TRUE; 9149} 9150 9151/* Usually mandatory */ 9152Bool 9153SISSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) 9154{ 9155 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 9156 SISPtr pSiS = SISPTR(pScrn); 9157 9158 if(!pSiS->skipswitchcheck) { 9159 if(SISValidMode(scrnIndex, mode, TRUE, flags) != MODE_OK) { 9160 return FALSE; 9161 } 9162 } 9163 9164 (*pSiS->SyncAccel)(pScrn); 9165 9166 if(!(SISModeInit(xf86Screens[scrnIndex], mode))) return FALSE; 9167 9168 /* Since RandR (indirectly) uses SwitchMode(), we need to 9169 * update our Xinerama info here, too, in case of resizing 9170 */ 9171#ifdef SISMERGED 9172#ifdef SISXINERAMA 9173 if(pSiS->MergedFB) { 9174 SiSUpdateXineramaScreenInfo(pScrn); 9175 } 9176#endif 9177#endif 9178 return TRUE; 9179} 9180 9181static void 9182SISSetStartAddressCRT1(SISPtr pSiS, ULong base) 9183{ 9184 UChar cr11backup; 9185 9186 inSISIDXREG(SISCR, 0x11, cr11backup); /* Unlock CRTC registers */ 9187 andSISIDXREG(SISCR, 0x11, 0x7F); 9188 outSISIDXREG(SISCR, 0x0D, base & 0xFF); 9189 outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); 9190 outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF); 9191 if(pSiS->VGAEngine == SIS_315_VGA) { 9192 setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01); 9193 } 9194 /* Eventually lock CRTC registers */ 9195 setSISIDXREG(SISCR, 0x11, 0x7F,(cr11backup & 0x80)); 9196} 9197 9198static void 9199SISSetStartAddressCRT2(SISPtr pSiS, ULong base) 9200{ 9201 SiS_UnLockCRT2(pSiS->SiS_Pr); 9202 outSISIDXREG(SISPART1, 0x06, GETVAR8(base)); 9203 outSISIDXREG(SISPART1, 0x05, GETBITS(base, 15:8)); 9204 outSISIDXREG(SISPART1, 0x04, GETBITS(base, 23:16)); 9205 if(pSiS->VGAEngine == SIS_315_VGA) { 9206 setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7); 9207 } 9208 SiS_LockCRT2(pSiS->SiS_Pr); 9209} 9210 9211#ifdef SISMERGED 9212static Bool 9213InRegion(int x, int y, region r) 9214{ 9215 return (r.x0 <= x) && (x <= r.x1) && (r.y0 <= y) && (y <= r.y1); 9216} 9217 9218static void 9219SISAdjustFrameHW_CRT1(ScrnInfoPtr pScrn, int x, int y) 9220{ 9221 SISPtr pSiS = SISPTR(pScrn); 9222 ULong base; 9223 9224 base = y * pSiS->CurrentLayout.displayWidth + x; 9225 switch(pSiS->CurrentLayout.bitsPerPixel) { 9226 case 16: base >>= 1; break; 9227 case 32: break; 9228 default: base >>= 2; 9229 } 9230 base += (pSiS->dhmOffset/4); 9231 SISSetStartAddressCRT1(pSiS, base); 9232} 9233 9234static void 9235SISAdjustFrameHW_CRT2(ScrnInfoPtr pScrn, int x, int y) 9236{ 9237 SISPtr pSiS = SISPTR(pScrn); 9238 ULong base; 9239 9240 base = y * pSiS->CurrentLayout.displayWidth + x; 9241 switch(pSiS->CurrentLayout.bitsPerPixel) { 9242 case 16: base >>= 1; break; 9243 case 32: break; 9244 default: base >>= 2; 9245 } 9246 base += (pSiS->dhmOffset/4); 9247 SISSetStartAddressCRT2(pSiS, base); 9248} 9249 9250static void 9251SISMergedPointerMoved(int scrnIndex, int x, int y) 9252{ 9253 ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex]; 9254 SISPtr pSiS = SISPTR(pScrn1); 9255 ScrnInfoPtr pScrn2 = pSiS->CRT2pScrn; 9256 region out, in1, in2, f2, f1; 9257 int deltax, deltay; 9258 int temp1, temp2; 9259 int old1x0, old1y0, old2x0, old2y0; 9260 int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; 9261 int HVirt = pScrn1->virtualX; 9262 int VVirt = pScrn1->virtualY; 9263 int sigstate; 9264 Bool doit = FALSE, HaveNonRect = FALSE, HaveOffsRegions = FALSE; 9265 SiSScrn2Rel srel = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT2Position; 9266 9267 if(pSiS->DGAactive) { 9268 return; 9269 /* DGA: There is no cursor and no panning while DGA is active. */ 9270 /* If it were, we would need to do: */ 9271 /* HVirt = pSiS->CurrentLayout.displayWidth; 9272 VVirt = pSiS->CurrentLayout.displayHeight; 9273 BOUND(x, pSiS->CurrentLayout.DGAViewportX, HVirt); 9274 BOUND(y, pSiS->CurrentLayout.DGAViewportY, VVirt); */ 9275 } else { 9276 CRT1XOffs = pSiS->CRT1XOffs; 9277 CRT1YOffs = pSiS->CRT1YOffs; 9278 CRT2XOffs = pSiS->CRT2XOffs; 9279 CRT2YOffs = pSiS->CRT2YOffs; 9280 HaveNonRect = pSiS->HaveNonRect; 9281 HaveOffsRegions = pSiS->HaveOffsRegions; 9282 } 9283 9284 /* Check if the pointer is inside our dead areas */ 9285 if((pSiS->MouseRestrictions) && (srel != sisClone) && !SiSnoPanoramiXExtension) { 9286 if(HaveNonRect) { 9287 if(InRegion(x, y, pSiS->NonRectDead)) { 9288 switch(srel) { 9289 case sisLeftOf: 9290 case sisRightOf: y = pSiS->NonRectDead.y0 - 1; 9291 doit = TRUE; 9292 break; 9293 case sisAbove: 9294 case sisBelow: x = pSiS->NonRectDead.x0 - 1; 9295 doit = TRUE; 9296 default: break; 9297 } 9298 } 9299 } 9300 if(HaveOffsRegions) { 9301 if(InRegion(x, y, pSiS->OffDead1)) { 9302 switch(srel) { 9303 case sisLeftOf: 9304 case sisRightOf: y = pSiS->OffDead1.y1; 9305 doit = TRUE; 9306 break; 9307 case sisAbove: 9308 case sisBelow: x = pSiS->OffDead1.x1; 9309 doit = TRUE; 9310 default: break; 9311 } 9312 } else if(InRegion(x, y, pSiS->OffDead2)) { 9313 switch(srel) { 9314 case sisLeftOf: 9315 case sisRightOf: y = pSiS->OffDead2.y0 - 1; 9316 doit = TRUE; 9317 break; 9318 case sisAbove: 9319 case sisBelow: x = pSiS->OffDead2.x0 - 1; 9320 doit = TRUE; 9321 default: break; 9322 } 9323 } 9324 } 9325 if(doit) { 9326 UpdateCurrentTime(); 9327 sigstate = xf86BlockSIGIO(); 9328 miPointerAbsoluteCursor(x, y, currentTime.milliseconds); 9329 xf86UnblockSIGIO(sigstate); 9330 return; 9331 } 9332 } 9333 9334 f1.x0 = old1x0 = pSiS->CRT1frameX0; 9335 f1.x1 = pSiS->CRT1frameX1; 9336 f1.y0 = old1y0 = pSiS->CRT1frameY0; 9337 f1.y1 = pSiS->CRT1frameY1; 9338 f2.x0 = old2x0 = pScrn2->frameX0; 9339 f2.x1 = pScrn2->frameX1; 9340 f2.y0 = old2y0 = pScrn2->frameY0; 9341 f2.y1 = pScrn2->frameY1; 9342 9343 /* Define the outer region. Crossing this causes all frames to move */ 9344 out.x0 = pScrn1->frameX0; 9345 out.x1 = pScrn1->frameX1; 9346 out.y0 = pScrn1->frameY0; 9347 out.y1 = pScrn1->frameY1; 9348 9349 /* 9350 * Define the inner sliding window. Being outsize both frames but 9351 * inside the outer clipping window will slide corresponding frame 9352 */ 9353 in1 = out; 9354 in2 = out; 9355 switch(srel) { 9356 case sisLeftOf: 9357 in1.x0 = f1.x0; 9358 in2.x1 = f2.x1; 9359 break; 9360 case sisRightOf: 9361 in1.x1 = f1.x1; 9362 in2.x0 = f2.x0; 9363 break; 9364 case sisBelow: 9365 in1.y1 = f1.y1; 9366 in2.y0 = f2.y0; 9367 break; 9368 case sisAbove: 9369 in1.y0 = f1.y0; 9370 in2.y1 = f2.y1; 9371 break; 9372 case sisClone: 9373 break; 9374 } 9375 9376 deltay = 0; 9377 deltax = 0; 9378 9379 if(InRegion(x, y, out)) { /* inside outer region */ 9380 9381 if(InRegion(x, y, in1) && !InRegion(x, y, f1)) { 9382 REBOUND(f1.x0, f1.x1, x); 9383 REBOUND(f1.y0, f1.y1, y); 9384 deltax = 1; 9385 } 9386 if(InRegion(x, y, in2) && !InRegion(x, y, f2)) { 9387 REBOUND(f2.x0, f2.x1, x); 9388 REBOUND(f2.y0, f2.y1, y); 9389 deltax = 1; 9390 } 9391 9392 } else { /* outside outer region */ 9393 9394 if(out.x0 > x) { 9395 deltax = x - out.x0; 9396 } 9397 if(out.x1 < x) { 9398 deltax = x - out.x1; 9399 } 9400 if(deltax) { 9401 pScrn1->frameX0 += deltax; 9402 pScrn1->frameX1 += deltax; 9403 f1.x0 += deltax; 9404 f1.x1 += deltax; 9405 f2.x0 += deltax; 9406 f2.x1 += deltax; 9407 } 9408 9409 if(out.y0 > y) { 9410 deltay = y - out.y0; 9411 } 9412 if(out.y1 < y) { 9413 deltay = y - out.y1; 9414 } 9415 if(deltay) { 9416 pScrn1->frameY0 += deltay; 9417 pScrn1->frameY1 += deltay; 9418 f1.y0 += deltay; 9419 f1.y1 += deltay; 9420 f2.y0 += deltay; 9421 f2.y1 += deltay; 9422 } 9423 9424 switch(srel) { 9425 case sisLeftOf: 9426 if(x >= f1.x0) { REBOUND(f1.y0, f1.y1, y); } 9427 if(x <= f2.x1) { REBOUND(f2.y0, f2.y1, y); } 9428 break; 9429 case sisRightOf: 9430 if(x <= f1.x1) { REBOUND(f1.y0, f1.y1, y); } 9431 if(x >= f2.x0) { REBOUND(f2.y0, f2.y1, y); } 9432 break; 9433 case sisBelow: 9434 if(y <= f1.y1) { REBOUND(f1.x0, f1.x1, x); } 9435 if(y >= f2.y0) { REBOUND(f2.x0, f2.x1, x); } 9436 break; 9437 case sisAbove: 9438 if(y >= f1.y0) { REBOUND(f1.x0, f1.x1, x); } 9439 if(y <= f2.y1) { REBOUND(f2.x0, f2.x1, x); } 9440 break; 9441 case sisClone: 9442 break; 9443 } 9444 9445 } 9446 9447 if(deltax || deltay) { 9448 pSiS->CRT1frameX0 = f1.x0; 9449 pSiS->CRT1frameY0 = f1.y0; 9450 pScrn2->frameX0 = f2.x0; 9451 pScrn2->frameY0 = f2.y0; 9452 9453 switch(srel) { 9454 case sisLeftOf: 9455 case sisRightOf: 9456 if(CRT1YOffs || CRT2YOffs || HaveNonRect) { 9457 if(pSiS->CRT1frameY0 != old1y0) { 9458 if(pSiS->CRT1frameY0 < CRT1YOffs) 9459 pSiS->CRT1frameY0 = CRT1YOffs; 9460 9461 temp1 = pSiS->CRT1frameY0 + CDMPTR->CRT1->VDisplay; 9462 temp2 = min((VVirt - CRT2YOffs), (CRT1YOffs + pSiS->MBXNR1YMAX)); 9463 if(temp1 > temp2) 9464 pSiS->CRT1frameY0 -= (temp1 - temp2); 9465 } 9466 if(pScrn2->frameY0 != old2y0) { 9467 if(pScrn2->frameY0 < CRT2YOffs) 9468 pScrn2->frameY0 = CRT2YOffs; 9469 9470 temp1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay; 9471 temp2 = min((VVirt - CRT1YOffs), (CRT2YOffs + pSiS->MBXNR2YMAX)); 9472 if(temp1 > temp2) 9473 pScrn2->frameY0 -= (temp1 - temp2); 9474 } 9475 } 9476 break; 9477 case sisBelow: 9478 case sisAbove: 9479 if(CRT1XOffs || CRT2XOffs || HaveNonRect) { 9480 if(pSiS->CRT1frameX0 != old1x0) { 9481 if(pSiS->CRT1frameX0 < CRT1XOffs) 9482 pSiS->CRT1frameX0 = CRT1XOffs; 9483 9484 temp1 = pSiS->CRT1frameX0 + CDMPTR->CRT1->HDisplay; 9485 temp2 = min((HVirt - CRT2XOffs), (CRT1XOffs + pSiS->MBXNR1XMAX)); 9486 if(temp1 > temp2) 9487 pSiS->CRT1frameX0 -= (temp1 - temp2); 9488 } 9489 if(pScrn2->frameX0 != old2x0) { 9490 if(pScrn2->frameX0 < CRT2XOffs) 9491 pScrn2->frameX0 = CRT2XOffs; 9492 9493 temp1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay; 9494 temp2 = min((HVirt - CRT1XOffs), (CRT2XOffs + pSiS->MBXNR2XMAX)); 9495 if(temp1 > temp2) 9496 pScrn2->frameX0 -= (temp1 - temp2); 9497 } 9498 } 9499 break; 9500 case sisClone: 9501 break; 9502 } 9503 9504 pSiS->CRT1frameX1 = pSiS->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1; 9505 pSiS->CRT1frameY1 = pSiS->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1; 9506 pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1; 9507 pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1; 9508 9509 /* No need to update pScrn1->frame?1, done above */ 9510 9511 SISAdjustFrameHW_CRT1(pScrn1, pSiS->CRT1frameX0, pSiS->CRT1frameY0); 9512 SISAdjustFrameHW_CRT2(pScrn1, pScrn2->frameX0, pScrn2->frameY0); 9513 } 9514} 9515 9516static void 9517SISAdjustFrameMerged(int scrnIndex, int x, int y, int flags) 9518{ 9519 ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex]; 9520 SISPtr pSiS = SISPTR(pScrn1); 9521 ScrnInfoPtr pScrn2 = pSiS->CRT2pScrn; 9522 int HTotal = pSiS->CurrentLayout.mode->HDisplay; 9523 int VTotal = pSiS->CurrentLayout.mode->VDisplay; 9524 int HMax = HTotal; 9525 int VMax = VTotal; 9526 int HVirt = pScrn1->virtualX; 9527 int VVirt = pScrn1->virtualY; 9528 int x1 = x, x2 = x; 9529 int y1 = y, y2 = y; 9530 int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; 9531 int MBXNR1XMAX = 65536, MBXNR1YMAX = 65536, MBXNR2XMAX = 65536, MBXNR2YMAX = 65536; 9532 9533 if(pSiS->DGAactive) { 9534 HVirt = pSiS->CurrentLayout.displayWidth; 9535 VVirt = pSiS->CurrentLayout.displayHeight; 9536 } else { 9537 CRT1XOffs = pSiS->CRT1XOffs; 9538 CRT1YOffs = pSiS->CRT1YOffs; 9539 CRT2XOffs = pSiS->CRT2XOffs; 9540 CRT2YOffs = pSiS->CRT2YOffs; 9541 MBXNR1XMAX = pSiS->MBXNR1XMAX; 9542 MBXNR1YMAX = pSiS->MBXNR1YMAX; 9543 MBXNR2XMAX = pSiS->MBXNR2XMAX; 9544 MBXNR2YMAX = pSiS->MBXNR2YMAX; 9545 } 9546 9547 BOUND(x, 0, HVirt - HTotal); 9548 BOUND(y, 0, VVirt - VTotal); 9549 if(SDMPTR(pScrn1)->CRT2Position != sisClone) { 9550 BOUND(x1, CRT1XOffs, min(HVirt, MBXNR1XMAX + CRT1XOffs) - min(HTotal, MBXNR1XMAX) - CRT2XOffs); 9551 BOUND(y1, CRT1YOffs, min(VVirt, MBXNR1YMAX + CRT1YOffs) - min(VTotal, MBXNR1YMAX) - CRT2YOffs); 9552 BOUND(x2, CRT2XOffs, min(HVirt, MBXNR2XMAX + CRT2XOffs) - min(HTotal, MBXNR2XMAX) - CRT1XOffs); 9553 BOUND(y2, CRT2YOffs, min(VVirt, MBXNR2YMAX + CRT2YOffs) - min(VTotal, MBXNR2YMAX) - CRT1YOffs); 9554 } 9555 9556 switch(SDMPTR(pScrn1)->CRT2Position) { 9557 case sisLeftOf: 9558 pScrn2->frameX0 = x2; 9559 BOUND(pScrn2->frameY0, y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR->CRT2->VDisplay); 9560 pSiS->CRT1frameX0 = x1 + CDMPTR->CRT2->HDisplay; 9561 BOUND(pSiS->CRT1frameY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR->CRT1->VDisplay); 9562 break; 9563 case sisRightOf: 9564 pSiS->CRT1frameX0 = x1; 9565 BOUND(pSiS->CRT1frameY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR->CRT1->VDisplay); 9566 pScrn2->frameX0 = x2 + CDMPTR->CRT1->HDisplay; 9567 BOUND(pScrn2->frameY0, y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR->CRT2->VDisplay); 9568 break; 9569 case sisAbove: 9570 BOUND(pScrn2->frameX0, x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR->CRT2->HDisplay); 9571 pScrn2->frameY0 = y2; 9572 BOUND(pSiS->CRT1frameX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR->CRT1->HDisplay); 9573 pSiS->CRT1frameY0 = y1 + CDMPTR->CRT2->VDisplay; 9574 break; 9575 case sisBelow: 9576 BOUND(pSiS->CRT1frameX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR->CRT1->HDisplay); 9577 pSiS->CRT1frameY0 = y1; 9578 BOUND(pScrn2->frameX0, x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR->CRT2->HDisplay); 9579 pScrn2->frameY0 = y2 + CDMPTR->CRT1->VDisplay; 9580 break; 9581 case sisClone: 9582 BOUND(pSiS->CRT1frameX0, x, x + HMax - CDMPTR->CRT1->HDisplay); 9583 BOUND(pSiS->CRT1frameY0, y, y + VMax - CDMPTR->CRT1->VDisplay); 9584 BOUND(pScrn2->frameX0, x, x + HMax - CDMPTR->CRT2->HDisplay); 9585 BOUND(pScrn2->frameY0, y, y + VMax - CDMPTR->CRT2->VDisplay); 9586 break; 9587 } 9588 9589 BOUND(pSiS->CRT1frameX0, 0, HVirt - CDMPTR->CRT1->HDisplay); 9590 BOUND(pSiS->CRT1frameY0, 0, VVirt - CDMPTR->CRT1->VDisplay); 9591 BOUND(pScrn2->frameX0, 0, HVirt - CDMPTR->CRT2->HDisplay); 9592 BOUND(pScrn2->frameY0, 0, VVirt - CDMPTR->CRT2->VDisplay); 9593 9594 pScrn1->frameX0 = x; 9595 pScrn1->frameY0 = y; 9596 9597 pSiS->CRT1frameX1 = pSiS->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1; 9598 pSiS->CRT1frameY1 = pSiS->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1; 9599 pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1; 9600 pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1; 9601 9602 pScrn1->frameX1 = pScrn1->frameX0 + pSiS->CurrentLayout.mode->HDisplay - 1; 9603 pScrn1->frameY1 = pScrn1->frameY0 + pSiS->CurrentLayout.mode->VDisplay - 1; 9604 if(SDMPTR(pScrn1)->CRT2Position != sisClone) { 9605 pScrn1->frameX1 += CRT1XOffs + CRT2XOffs; 9606 pScrn1->frameY1 += CRT1YOffs + CRT2YOffs; 9607 } 9608 9609 SISAdjustFrameHW_CRT1(pScrn1, pSiS->CRT1frameX0, pSiS->CRT1frameY0); 9610 SISAdjustFrameHW_CRT2(pScrn1, pScrn2->frameX0, pScrn2->frameY0); 9611} 9612#endif 9613 9614/* 9615 * This function is used to initialize the Start Address - the first 9616 * displayed location in the video memory. 9617 * 9618 * Usually mandatory 9619 */ 9620void 9621SISAdjustFrame(int scrnIndex, int x, int y, int flags) 9622{ 9623 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 9624 SISPtr pSiS = SISPTR(pScrn); 9625 ULong base; 9626 UChar temp, cr11backup; 9627 9628#ifdef SISMERGED 9629 if(pSiS->MergedFB) { 9630 SISAdjustFrameMerged(scrnIndex, x, y, flags); 9631 return; 9632 } 9633#endif 9634 9635 if(pSiS->UseVESA) { 9636 VBESetDisplayStart(pSiS->pVbe, x, y, TRUE); 9637 return; 9638 } 9639 9640 if(pScrn->bitsPerPixel < 8) { 9641 base = (y * pSiS->CurrentLayout.displayWidth + x + 3) >> 3; 9642 } else { 9643 base = y * pSiS->CurrentLayout.displayWidth + x; 9644 9645 /* calculate base bpp dep. */ 9646 switch(pSiS->CurrentLayout.bitsPerPixel) { 9647 case 16: 9648 base >>= 1; 9649 break; 9650 case 24: 9651 base = ((base * 3)) >> 2; 9652 base -= base % 6; 9653 break; 9654 case 32: 9655 break; 9656 default: /* 8bpp */ 9657 base >>= 2; 9658 break; 9659 } 9660 } 9661 9662#ifdef UNLOCK_ALWAYS 9663 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 9664#endif 9665 9666 base += (pSiS->dhmOffset/4); 9667 9668#ifdef TWDEBUG 9669 xf86DrvMsg(0, 0, "AdjustFrame: x %d y %d bpp %d dw %d base %d, dhmOffset %d\n", 9670 x, y, pSiS->CurrentLayout.bitsPerPixel, pSiS->CurrentLayout.displayWidth, base, pSiS->dhmOffset); 9671#endif 9672 9673#ifdef SISDUALHEAD 9674 if(pSiS->DualHeadMode) { 9675 if(!pSiS->SecondHead) { 9676 /* Head 1 (master) is always CRT2 */ 9677 SISSetStartAddressCRT2(pSiS, base); 9678 } else { 9679 /* Head 2 (slave) is always CRT1 */ 9680 SISSetStartAddressCRT1(pSiS, base); 9681 } 9682 } else { 9683#endif 9684 switch(pSiS->VGAEngine) { 9685 case SIS_300_VGA: 9686 case SIS_315_VGA: 9687 SISSetStartAddressCRT1(pSiS, base); 9688 if(pSiS->VBFlags & CRT2_ENABLE) { 9689 if(!SiSBridgeIsInSlaveMode(pScrn)) { 9690 SISSetStartAddressCRT2(pSiS, base); 9691 } 9692 } 9693 break; 9694 default: 9695 /* Unlock CRTC registers */ 9696 inSISIDXREG(SISCR, 0x11, cr11backup); 9697 andSISIDXREG(SISCR, 0x11, 0x7F); 9698 outSISIDXREG(SISCR, 0x0D, base & 0xFF); 9699 outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); 9700 inSISIDXREG(SISSR, 0x27, temp); 9701 temp &= 0xF0; 9702 temp |= (base & 0x0F0000) >> 16; 9703 outSISIDXREG(SISSR, 0x27, temp); 9704 /* Eventually lock CRTC registers */ 9705 setSISIDXREG(SISCR, 0x11, 0x7F, (cr11backup & 0x80)); 9706 } 9707#ifdef SISDUALHEAD 9708 } 9709#endif 9710 9711} 9712 9713/* 9714 * This is called when VT switching back to the X server. Its job is 9715 * to reinitialise the video mode. 9716 * Mandatory! 9717 */ 9718static Bool 9719SISEnterVT(int scrnIndex, int flags) 9720{ 9721 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 9722 SISPtr pSiS = SISPTR(pScrn); 9723 9724 SiS_SiSFB_Lock(pScrn, TRUE); 9725 9726 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 9727 9728 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 9729 outSISIDXREG(SISCR,0x32,pSiS->myCR32); 9730 outSISIDXREG(SISCR,0x36,pSiS->myCR36); 9731 outSISIDXREG(SISCR,0x37,pSiS->myCR37); 9732 } 9733 9734 if(!SISModeInit(pScrn, pScrn->currentMode)) { 9735 SISErrorLog(pScrn, "SiSEnterVT: SISModeInit() failed\n"); 9736 return FALSE; 9737 } 9738 9739 SISAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 9740 9741#ifdef XF86DRI 9742 if(pSiS->directRenderingEnabled) { 9743 DRIUnlock(screenInfo.screens[scrnIndex]); 9744 } 9745#endif 9746 9747#ifdef SISDUALHEAD 9748 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) 9749#endif 9750 if(pSiS->ResetXv) { 9751 (pSiS->ResetXv)(pScrn); 9752 } 9753 9754 return TRUE; 9755} 9756 9757/* 9758 * This is called when VT switching away from the X server. Its job is 9759 * to restore the previous (text) mode. 9760 * Mandatory! 9761 */ 9762static void 9763SISLeaveVT(int scrnIndex, int flags) 9764{ 9765 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 9766 SISPtr pSiS = SISPTR(pScrn); 9767#ifdef XF86DRI 9768 ScreenPtr pScreen; 9769 9770 if(pSiS->directRenderingEnabled) { 9771 pScreen = screenInfo.screens[scrnIndex]; 9772 DRILock(pScreen, 0); 9773 } 9774#endif 9775 9776#ifdef SISDUALHEAD 9777 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 9778#endif 9779 9780 if(pSiS->CursorInfoPtr) { 9781#ifdef SISDUALHEAD 9782 if(pSiS->DualHeadMode) { 9783 if(!pSiS->SecondHead) { 9784 pSiS->ForceCursorOff = TRUE; 9785 pSiS->CursorInfoPtr->HideCursor(pScrn); 9786 SISWaitVBRetrace(pScrn); 9787 pSiS->ForceCursorOff = FALSE; 9788 } 9789 } else { 9790#endif 9791 pSiS->CursorInfoPtr->HideCursor(pScrn); 9792 SISWaitVBRetrace(pScrn); 9793#ifdef SISDUALHEAD 9794 } 9795#endif 9796 } 9797 9798 SISBridgeRestore(pScrn); 9799 9800 if(pSiS->UseVESA) { 9801 9802 /* This is a q&d work-around for a BIOS bug. In case we disabled CRT2, 9803 * VBESaveRestore() does not restore CRT1. So we set any mode now, 9804 * because VBESetVBEMode correctly restores CRT1. Afterwards, we 9805 * can call VBESaveRestore to restore original mode. 9806 */ 9807 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (!(pSiS->VBFlags & DISPTYPE_DISP2))) 9808 VBESetVBEMode(pSiS->pVbe, (pSiS->SISVESAModeList->n) | 0xc000, NULL); 9809 9810 SISVESARestore(pScrn); 9811 9812 } else { 9813 9814 SISRestore(pScrn); 9815 9816 } 9817 9818 /* We use (otherwise unused) bit 7 to indicate that we are running 9819 * to keep sisfb to change the displaymode (this would result in 9820 * lethal display corruption upon quitting X or changing to a VT 9821 * until a reboot) 9822 */ 9823 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 9824 orSISIDXREG(SISCR,0x34,0x80); 9825 } 9826 9827 SISVGALock(pSiS); 9828 9829 SiS_SiSFB_Lock(pScrn, FALSE); 9830} 9831 9832 9833/* 9834 * This is called at the end of each server generation. It restores the 9835 * original (text) mode. It should really also unmap the video memory too. 9836 * Mandatory! 9837 */ 9838static Bool 9839SISCloseScreen(int scrnIndex, ScreenPtr pScreen) 9840{ 9841 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 9842 SISPtr pSiS = SISPTR(pScrn); 9843#ifdef SISDUALHEAD 9844 SISEntPtr pSiSEnt = pSiS->entityPrivate; 9845#endif 9846 9847 if(pSiS->SiSCtrlExtEntry) { 9848 SiSCtrlExtUnregister(pSiS, pScrn->scrnIndex); 9849 } 9850 9851#ifdef XF86DRI 9852 if(pSiS->directRenderingEnabled) { 9853 SISDRICloseScreen(pScreen); 9854 pSiS->directRenderingEnabled = FALSE; 9855 } 9856#endif 9857 9858 if(pScrn->vtSema) { 9859 9860 if(pSiS->CursorInfoPtr) { 9861#ifdef SISDUALHEAD 9862 if(pSiS->DualHeadMode) { 9863 if(!pSiS->SecondHead) { 9864 pSiS->ForceCursorOff = TRUE; 9865 pSiS->CursorInfoPtr->HideCursor(pScrn); 9866 SISWaitVBRetrace(pScrn); 9867 pSiS->ForceCursorOff = FALSE; 9868 } 9869 } else { 9870#endif 9871 pSiS->CursorInfoPtr->HideCursor(pScrn); 9872 SISWaitVBRetrace(pScrn); 9873#ifdef SISDUALHEAD 9874 } 9875#endif 9876 } 9877 9878 SISBridgeRestore(pScrn); 9879 9880 if(pSiS->UseVESA) { 9881 9882 /* This is a q&d work-around for a BIOS bug. In case we disabled CRT2, 9883 * VBESaveRestore() does not restore CRT1. So we set any mode now, 9884 * because VBESetVBEMode correctly restores CRT1. Afterwards, we 9885 * can call VBESaveRestore to restore original mode. 9886 */ 9887 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (!(pSiS->VBFlags & DISPTYPE_DISP2))) 9888 VBESetVBEMode(pSiS->pVbe, (pSiS->SISVESAModeList->n) | 0xc000, NULL); 9889 9890 SISVESARestore(pScrn); 9891 9892 } else { 9893 9894 SISRestore(pScrn); 9895 9896 } 9897 9898 SISVGALock(pSiS); 9899 9900 } 9901 9902 SiS_SiSFB_Lock(pScrn, FALSE); 9903 9904 /* We should restore the mode number in case vtsema = false as well, 9905 * but since we haven't register access then we can't do it. I think 9906 * I need to rework the save/restore stuff, like saving the video 9907 * status when returning to the X server and by that save me the 9908 * trouble if sisfb was started from a textmode VT while X was on. 9909 */ 9910 9911 SISUnmapMem(pScrn); 9912#ifdef SIS_PC_PLATFORM 9913 SiSVGAUnmapMem(pScrn); 9914#endif 9915 9916#ifdef SISDUALHEAD 9917 if(pSiS->DualHeadMode) { 9918 pSiSEnt = pSiS->entityPrivate; 9919 pSiSEnt->refCount--; 9920 } 9921#endif 9922 9923 if(pSiS->pInt) { 9924 xf86FreeInt10(pSiS->pInt); 9925 pSiS->pInt = NULL; 9926 } 9927 9928#ifdef SIS_USE_XAA 9929 if(!pSiS->useEXA) { 9930 if(pSiS->AccelLinearScratch) { 9931 xf86FreeOffscreenLinear(pSiS->AccelLinearScratch); 9932 pSiS->AccelLinearScratch = NULL; 9933 } 9934 if(pSiS->AccelInfoPtr) { 9935 XAADestroyInfoRec(pSiS->AccelInfoPtr); 9936 pSiS->AccelInfoPtr = NULL; 9937 } 9938 } 9939#endif 9940 9941#ifdef SIS_USE_EXA 9942 if(pSiS->useEXA) { 9943 if(pSiS->EXADriverPtr) { 9944 exaDriverFini(pScreen); 9945 xfree(pSiS->EXADriverPtr); 9946 pSiS->EXADriverPtr = NULL; 9947 pSiS->exa_scratch = NULL; 9948 } 9949 } 9950#endif 9951 9952 if(pSiS->CursorInfoPtr) { 9953 xf86DestroyCursorInfoRec(pSiS->CursorInfoPtr); 9954 pSiS->CursorInfoPtr = NULL; 9955 } 9956 9957 if(pSiS->ShadowPtr) { 9958 xfree(pSiS->ShadowPtr); 9959 pSiS->ShadowPtr = NULL; 9960 } 9961 9962 if(pSiS->DGAModes) { 9963 xfree(pSiS->DGAModes); 9964 pSiS->DGAModes = NULL; 9965 } 9966 9967 if(pSiS->adaptor) { 9968 xfree(pSiS->adaptor); 9969 pSiS->adaptor = NULL; 9970 pSiS->ResetXv = pSiS->ResetXvGamma = pSiS->ResetXvDisplay = NULL; 9971 } 9972 9973 if(pSiS->blitadaptor) { 9974 xfree(pSiS->blitadaptor); 9975 pSiS->blitadaptor = NULL; 9976 } 9977 9978 if(pSiS->crt2gcolortable) { 9979 xfree(pSiS->crt2gcolortable); 9980 pSiS->crt2gcolortable = NULL; 9981 } 9982 9983 if(pSiS->crt2cindices) { 9984 xfree(pSiS->crt2cindices); 9985 pSiS->crt2cindices = NULL; 9986 } 9987 9988 pScrn->vtSema = FALSE; 9989 9990 /* Restore Blockhandler */ 9991 pScreen->BlockHandler = pSiS->BlockHandler; 9992 9993 pScreen->CloseScreen = pSiS->CloseScreen; 9994 9995 return(*pScreen->CloseScreen)(scrnIndex, pScreen); 9996} 9997 9998 9999/* Free up any per-generation data structures */ 10000 10001/* Optional */ 10002static void 10003SISFreeScreen(int scrnIndex, int flags) 10004{ 10005#ifdef SIS_NEED_MAP_IOP 10006 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 10007 SISPtr pSiS = SISPTR(pScrn); 10008 10009 if(pSiS) { 10010#ifdef SISDUALHEAD 10011 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10012 if(pSiSEnt) { 10013 pSiSEnt->forceUnmapIOPBase = TRUE; 10014 } 10015#endif 10016 SISUnmapIOPMem(pScrn); 10017 } 10018#endif 10019 10020 SISFreeRec(xf86Screens[scrnIndex]); 10021} 10022 10023 10024/* Checks if a mode is suitable for the selected chipset. */ 10025 10026static ModeStatus 10027SISValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) 10028{ 10029 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 10030 SISPtr pSiS = SISPTR(pScrn); 10031 10032 if(pSiS->UseVESA) { 10033 if(SiSCalcVESAModeIndex(pScrn, mode)) 10034 return(MODE_OK); 10035 else 10036 return(MODE_BAD); 10037 } 10038 10039 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 10040#ifdef SISDUALHEAD 10041 if(pSiS->DualHeadMode) { 10042 if(pSiS->SecondHead) { 10043 if(SiS_CheckModeCRT1(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10044 return(MODE_BAD); 10045 } else { 10046 if(SiS_CheckModeCRT2(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10047 return(MODE_BAD); 10048 } 10049 } else 10050#endif 10051#ifdef SISMERGED 10052 if(pSiS->MergedFB) { 10053 if(!mode->Private) { 10054 if(!pSiS->CheckForCRT2) { 10055 if(SiS_CheckModeCRT1(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10056 return(MODE_BAD); 10057 } else { 10058 if(SiS_CheckModeCRT2(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes2) < 0x14) 10059 return(MODE_BAD); 10060 } 10061 } else { 10062 if(SiS_CheckModeCRT1(pScrn, ((SiSMergedDisplayModePtr)mode->Private)->CRT1, 10063 pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10064 return(MODE_BAD); 10065 10066 if(SiS_CheckModeCRT2(pScrn, ((SiSMergedDisplayModePtr)mode->Private)->CRT2, 10067 pSiS->VBFlags, pSiS->HaveCustomModes2) < 0x14) 10068 return(MODE_BAD); 10069 } 10070 } else 10071#endif 10072 { 10073 if(SiS_CheckModeCRT1(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10074 return(MODE_BAD); 10075 10076 if(SiS_CheckModeCRT2(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10077 return(MODE_BAD); 10078 } 10079 } 10080 10081 return(MODE_OK); 10082} 10083 10084#ifdef DEBUG 10085static void 10086SiSDumpModeInfo(ScrnInfoPtr pScrn, DisplayModePtr mode) 10087{ 10088 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Clock : %x\n", mode->Clock); 10089 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Display : %x\n", mode->CrtcHDisplay); 10090 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Blank Start : %x\n", mode->CrtcHBlankStart); 10091 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Sync Start : %x\n", mode->CrtcHSyncStart); 10092 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Sync End : %x\n", mode->CrtcHSyncEnd); 10093 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Blank End : %x\n", mode->CrtcHBlankEnd); 10094 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Total : %x\n", mode->CrtcHTotal); 10095 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Skew : %x\n", mode->CrtcHSkew); 10096 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz HAdjusted : %x\n", mode->CrtcHAdjusted); 10097 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Display : %x\n", mode->CrtcVDisplay); 10098 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Blank Start : %x\n", mode->CrtcVBlankStart); 10099 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Sync Start : %x\n", mode->CrtcVSyncStart); 10100 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Sync End : %x\n", mode->CrtcVSyncEnd); 10101 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Blank End : %x\n", mode->CrtcVBlankEnd); 10102 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Total : %x\n", mode->CrtcVTotal); 10103 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt VAdjusted : %x\n", mode->CrtcVAdjusted); 10104} 10105#endif 10106 10107static void 10108SISModifyModeInfo(DisplayModePtr mode) 10109{ 10110 if(mode->CrtcHBlankStart == mode->CrtcHDisplay) 10111 mode->CrtcHBlankStart++; 10112 if(mode->CrtcHBlankEnd == mode->CrtcHTotal) 10113 mode->CrtcHBlankEnd--; 10114 if(mode->CrtcVBlankStart == mode->CrtcVDisplay) 10115 mode->CrtcVBlankStart++; 10116 if(mode->CrtcVBlankEnd == mode->CrtcVTotal) 10117 mode->CrtcVBlankEnd--; 10118} 10119 10120/* Enable the Turboqueue/Commandqueue (For 300 and 315/330/340 series only) */ 10121static void 10122SiSEnableTurboQueue(ScrnInfoPtr pScrn) 10123{ 10124 SISPtr pSiS = SISPTR(pScrn); 10125 UShort SR26, SR27; 10126 ULong temp; 10127 10128 switch(pSiS->VGAEngine) { 10129 case SIS_300_VGA: 10130 if((!pSiS->NoAccel) && (pSiS->TurboQueue)) { 10131 /* TQ size is always 512k */ 10132 temp = (pScrn->videoRam/64) - 8; 10133 SR26 = temp & 0xFF; 10134 inSISIDXREG(SISSR, 0x27, SR27); 10135 SR27 &= 0xFC; 10136 SR27 |= (0xF0 | ((temp >> 8) & 3)); 10137 outSISIDXREG(SISSR, 0x26, SR26); 10138 outSISIDXREG(SISSR, 0x27, SR27); 10139 } 10140 break; 10141 10142 case SIS_315_VGA: 10143 if(!pSiS->NoAccel) { 10144 /* On 315/330/340 series, there are three queue modes available 10145 * which are chosen by setting bits 7:5 in SR26: 10146 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep 10147 * track of the queue, the FIFO, command parsing and so 10148 * on. This is the one comparable to the 300 series. 10149 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will 10150 * have to do queue management himself. 10151 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the 10152 * queue in AGP memory space. 10153 * We go VRAM or MMIO here. 10154 * SR26 bit 4 is called "Bypass H/W queue". 10155 * SR26 bit 1 is called "Enable Command Queue Auto Correction" 10156 * SR26 bit 0 resets the queue 10157 * Size of queue memory is encoded in bits 3:2 like this: 10158 * 00 (0x00) 512K 10159 * 01 (0x04) 1M 10160 * 10 (0x08) 2M 10161 * 11 (0x0C) 4M 10162 * The queue location is to be written to 0x85C0. 10163 */ 10164#ifdef SISVRAMQ 10165 /* We use VRAM Cmd Queue, not MMIO or AGP */ 10166 UChar tempCR55 = 0; 10167 10168 /* Set Command Queue Threshold to max value 11111b (?) */ 10169 outSISIDXREG(SISSR, 0x27, 0x1F); 10170 10171 /* Disable queue flipping */ 10172 inSISIDXREG(SISCR, 0x55, tempCR55); 10173 andSISIDXREG(SISCR, 0x55, 0x33); 10174 /* Synchronous reset for Command Queue */ 10175 outSISIDXREG(SISSR, 0x26, 0x01); 10176 SIS_MMIO_OUT32(pSiS->IOBase, 0x85c4, 0); 10177 /* Enable VRAM Command Queue mode */ 10178 if(pSiS->ChipType == XGI_20) { 10179 /* On XGI_20, always 128K */ 10180 SR26 = 0x40 | 0x04 | 0x01; 10181 } else { 10182 switch(pSiS->cmdQueueSize) { 10183 case 1*1024*1024: SR26 = (0x40 | 0x04 | 0x01); break; 10184 case 2*1024*1024: SR26 = (0x40 | 0x08 | 0x01); break; 10185 case 4*1024*1024: SR26 = (0x40 | 0x0C | 0x01); break; 10186 default: 10187 pSiS->cmdQueueSize = 512 * 1024; 10188 case 512*1024: SR26 = (0x40 | 0x00 | 0x01); 10189 } 10190 } 10191 outSISIDXREG(SISSR, 0x26, SR26); 10192 SR26 &= 0xfe; 10193 outSISIDXREG(SISSR, 0x26, SR26); 10194 *(pSiS->cmdQ_SharedWritePort) = (unsigned int)(SIS_MMIO_IN32(pSiS->IOBase, 0x85c8)); 10195 SIS_MMIO_OUT32(pSiS->IOBase, 0x85c4, (CARD32)(*(pSiS->cmdQ_SharedWritePort))); 10196 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C0, pSiS->cmdQueueOffset); 10197 temp = (ULong)pSiS->RealFbBase; 10198#ifdef SISDUALHEAD 10199 if(pSiS->DualHeadMode) { 10200 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10201 temp = (ULong)pSiSEnt->RealFbBase; 10202 } 10203#endif 10204 temp += pSiS->cmdQueueOffset; 10205 pSiS->cmdQueueBase = (unsigned int *)temp; 10206 outSISIDXREG(SISCR, 0x55, tempCR55); 10207#ifdef TWDEBUG 10208 xf86DrvMsg(0, 0, "CmdQueueOffs 0x%x, CmdQueueAdd %p, shwrp 0x%x, status %x, base %p\n", 10209 pSiS->cmdQueueOffset, pSiS->cmdQueueBase, *(pSiS->cmdQ_SharedWritePort), 10210 SIS_MMIO_IN32(pSiS->IOBase, 0x85cc), (ULong *)temp); 10211#endif 10212#else 10213 /* For MMIO */ 10214 /* Syncronous reset for Command Queue */ 10215 orSISIDXREG(SISSR, 0x26, 0x01); 10216 /* Set Command Queue Threshold to max value 11111b */ 10217 outSISIDXREG(SISSR, 0x27, 0x1F); 10218 /* Do some magic (cp readport to writeport) */ 10219 temp = SIS_MMIO_IN32(pSiS->IOBase, 0x85C8); 10220 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C4, temp); 10221 /* Enable MMIO Command Queue mode (0x20), 10222 * Enable_command_queue_auto_correction (0x02) 10223 * (no idea, but sounds good, so use it) 10224 * 512k (0x00) (does this apply to MMIO mode?) */ 10225 outSISIDXREG(SISSR, 0x26, 0x22); 10226 /* Calc Command Queue position (Q is always 512k)*/ 10227 temp = (pScrn->videoRam - 512) * 1024; 10228 /* Set Q position */ 10229 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C0, temp); 10230#endif 10231 } 10232 break; 10233 default: 10234 break; 10235 } 10236} 10237 10238#ifdef SISVRAMQ 10239static void 10240SiSRestoreQueueMode(SISPtr pSiS, SISRegPtr sisReg) 10241{ 10242 UChar tempCR55=0; 10243 10244 if(pSiS->VGAEngine == SIS_315_VGA) { 10245 inSISIDXREG(SISCR,0x55,tempCR55); 10246 andSISIDXREG(SISCR,0x55,0x33); 10247 outSISIDXREG(SISSR,0x26,0x01); 10248 SIS_MMIO_OUT32(pSiS->IOBase, 0x85c4, 0); 10249 outSISIDXREG(SISSR,0x27,sisReg->sisRegs3C4[0x27]); 10250 outSISIDXREG(SISSR,0x26,sisReg->sisRegs3C4[0x26]); 10251 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C0, sisReg->sisMMIO85C0); 10252 outSISIDXREG(SISCR,0x55,tempCR55); 10253 } 10254} 10255#endif 10256 10257/* Things to do before a ModeSwitch. We set up the 10258 * video bridge configuration and the TurboQueue. 10259 */ 10260void SiSPreSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode, int viewmode) 10261{ 10262 SISPtr pSiS = SISPTR(pScrn); 10263 UChar CR30, CR31, CR32, CR33; 10264 UChar CR39 = 0, CR3B = 0; 10265 UChar CR17, CR38 = 0; 10266 UChar CR35 = 0, CR79 = 0; 10267 int temp = 0, crt1rateindex = 0; 10268 ULong vbflag = pSiS->VBFlags; 10269 Bool hcm = pSiS->HaveCustomModes; 10270 DisplayModePtr mymode = mode; 10271 10272 pSiS->IsCustom = FALSE; 10273 10274 /* NEVER call this with viewmode = SIS_MODE_SIMU 10275 * if mode->type is not M_T_DEFAULT! 10276 */ 10277 10278#ifdef SISMERGED 10279 if(pSiS->MergedFB) { 10280 switch(viewmode) { 10281 case SIS_MODE_CRT1: 10282 mymode = ((SiSMergedDisplayModePtr)mode->Private)->CRT1; 10283 break; 10284 case SIS_MODE_CRT2: 10285 mymode = ((SiSMergedDisplayModePtr)mode->Private)->CRT2; 10286 hcm = pSiS->HaveCustomModes2; 10287 } 10288 } 10289#endif 10290 10291 switch(viewmode) { 10292 case SIS_MODE_CRT1: 10293 if(SiS_CheckModeCRT1(pScrn, mymode, vbflag, hcm) == 0xfe) { 10294 pSiS->IsCustom = TRUE; 10295 } 10296 break; 10297 case SIS_MODE_CRT2: 10298 if(vbflag & CRT2_ENABLE) { 10299 if(SiS_CheckModeCRT2(pScrn, mymode, vbflag, hcm) == 0xfe) { 10300 pSiS->IsCustom = TRUE; 10301 } 10302 } else { 10303 /* This can only happen in mirror mode */ 10304 if(SiS_CheckModeCRT1(pScrn, mymode, vbflag, hcm) == 0xfe) { 10305 pSiS->IsCustom = TRUE; 10306 } 10307 } 10308 } 10309 10310#ifdef UNLOCK_ALWAYS 10311 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); /* Unlock Registers */ 10312#endif 10313 10314 inSISIDXREG(SISCR, 0x30, CR30); 10315 inSISIDXREG(SISCR, 0x31, CR31); 10316 CR32 = pSiS->newCR32; 10317 inSISIDXREG(SISCR, 0x33, CR33); 10318 10319 if(pSiS->NewCRLayout) { 10320 10321 inSISIDXREG(SISCR, 0x35, CR35); 10322 inSISIDXREG(SISCR, 0x38, CR38); 10323 inSISIDXREG(SISCR, 0x39, CR39); 10324 10325 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, SISVERBLEVEL, 10326 "Before: CR30=0x%02x,CR31=0x%02x,CR32=0x%02x,CR33=0x%02x,CR35=0x%02x,CR38=0x%02x\n", 10327 CR30, CR31, CR32, CR33, CR35, CR38); 10328 10329 CR38 &= ~0x07; 10330 10331 } else { 10332 10333 if(pSiS->Chipset != PCI_CHIP_SIS300) { 10334 switch(pSiS->VGAEngine) { 10335 case SIS_300_VGA: temp = 0x35; break; 10336 case SIS_315_VGA: temp = 0x38; break; 10337 } 10338 if(temp) inSISIDXREG(SISCR, temp, CR38); 10339 } 10340 if(pSiS->VGAEngine == SIS_315_VGA) { 10341 inSISIDXREG(SISCR, 0x79, CR79); 10342 CR38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */ 10343 } 10344 inSISIDXREG(SISCR, 0x3b, CR3B); 10345 10346 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, SISVERBLEVEL, 10347 "Before: CR30=0x%02x, CR31=0x%02x, CR32=0x%02x, CR33=0x%02x, CR%02x=0x%02x\n", 10348 CR30, CR31, CR32, CR33, temp, CR38); 10349 } 10350 10351 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, SISVERBLEVEL, "VBFlags=0x%x\n", pSiS->VBFlags); 10352 10353 CR30 = 0x00; 10354 CR31 &= ~0x60; /* Clear VB_Drivermode & VB_OutputDisable */ 10355 CR31 |= 0x04; /* Set VB_NotSimuMode (not for 30xB/1400x1050?) */ 10356 CR35 = 0x00; 10357 10358 if(!pSiS->NewCRLayout) { 10359 if(!pSiS->AllowHotkey) { 10360 CR31 |= 0x80; /* Disable hotkey-switch */ 10361 } 10362 CR79 &= ~0x10; /* Enable Backlight control on 315 series */ 10363 } 10364 10365 SiS_SetEnableDstn(pSiS->SiS_Pr, FALSE); 10366 SiS_SetEnableFstn(pSiS->SiS_Pr, FALSE); 10367 10368 if((vbflag & CRT1_LCDA) && (viewmode == SIS_MODE_CRT1)) { 10369 10370 CR38 |= 0x02; 10371 10372 } else { 10373 10374 switch(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA)) { 10375 10376 case CRT2_TV: 10377 10378 CR38 &= ~0xC0; /* Clear Pal M/N bits */ 10379 10380 if((pSiS->VBFlags2 & VB2_CHRONTEL) && (vbflag & TV_CHSCART)) { /* Chrontel */ 10381 CR30 |= 0x10; 10382 CR38 |= 0x04; 10383 CR38 &= ~0x08; 10384 CR31 |= 0x01; 10385 } else if((pSiS->VBFlags2 & VB2_CHRONTEL) && (vbflag & TV_CHYPBPR525I)) { /* Chrontel */ 10386 CR38 |= 0x08; 10387 CR38 &= ~0x04; 10388 CR31 &= ~0x01; 10389 } else if(vbflag & TV_HIVISION) { /* SiS bridge */ 10390 if(pSiS->NewCRLayout) { 10391 CR38 |= 0x04; 10392 CR35 |= 0x60; 10393 } else { 10394 CR30 |= 0x80; 10395 if(pSiS->VGAEngine == SIS_315_VGA) { 10396 if(pSiS->VBFlags2 & VB2_SISYPBPRBRIDGE) { 10397 CR38 |= (0x08 | 0x30); 10398 } 10399 } 10400 } 10401 CR31 |= 0x01; 10402 CR35 |= 0x01; 10403 } else if(vbflag & TV_YPBPR) { /* SiS bridge */ 10404 if(pSiS->NewCRLayout) { 10405 CR38 |= 0x04; 10406 CR31 &= ~0x01; 10407 CR35 &= ~0x01; 10408 if(vbflag & (TV_YPBPR525P | TV_YPBPR625P)) CR35 |= 0x20; 10409 else if(vbflag & TV_YPBPR750P) CR35 |= 0x40; 10410 else if(vbflag & TV_YPBPR1080I) CR35 |= 0x60; 10411 10412 if(vbflag & (TV_YPBPR625I | TV_YPBPR625P)) { 10413 CR31 |= 0x01; 10414 CR35 |= 0x01; 10415 } 10416 10417 CR39 &= ~0x03; 10418 if((vbflag & TV_YPBPRAR) == TV_YPBPR43LB) CR39 |= 0x00; 10419 else if((vbflag & TV_YPBPRAR) == TV_YPBPR43) CR39 |= 0x01; 10420 else if((vbflag & TV_YPBPRAR) == TV_YPBPR169) CR39 |= 0x02; 10421 else CR39 |= 0x03; 10422 } else if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR) { 10423 CR30 |= 0x80; 10424 CR38 |= 0x08; 10425 CR31 &= ~0x01; 10426 if(vbflag & (TV_YPBPR525P|TV_YPBPR625P)) CR38 |= 0x10; 10427 else if(vbflag & TV_YPBPR750P) CR38 |= 0x20; 10428 else if(vbflag & TV_YPBPR1080I) CR38 |= 0x30; 10429 10430 if(vbflag & (TV_YPBPR625I | TV_YPBPR625P)) CR31 |= 0x01; 10431 10432 if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPRAR) { 10433 CR3B &= ~0x03; 10434 if((vbflag & TV_YPBPRAR) == TV_YPBPR43LB) CR3B |= 0x00; 10435 else if((vbflag & TV_YPBPRAR) == TV_YPBPR43) CR3B |= 0x03; 10436 else if((vbflag & TV_YPBPRAR) == TV_YPBPR169) CR3B |= 0x01; 10437 else CR3B |= 0x03; 10438 } 10439 } 10440 } else { /* All */ 10441 if(vbflag & TV_SCART) CR30 |= 0x10; 10442 if(vbflag & TV_SVIDEO) CR30 |= 0x08; 10443 if(vbflag & TV_AVIDEO) CR30 |= 0x04; 10444 if(!(CR30 & 0x1C)) CR30 |= 0x08; /* default: SVIDEO */ 10445 10446 if(vbflag & TV_PAL) { 10447 CR31 |= 0x01; 10448 CR35 |= 0x01; 10449 if( (pSiS->VBFlags2 & VB2_SISBRIDGE) || 10450 ((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->ChrontelType == CHRONTEL_701x)) ) { 10451 if(vbflag & TV_PALM) { 10452 CR38 |= 0x40; 10453 CR35 |= 0x04; 10454 } else if(vbflag & TV_PALN) { 10455 CR38 |= 0x80; 10456 CR35 |= 0x08; 10457 } 10458 } 10459 } else { 10460 CR31 &= ~0x01; 10461 CR35 &= ~0x01; 10462 if(vbflag & TV_NTSCJ) { 10463 CR38 |= 0x40; /* TW, not BIOS */ 10464 CR35 |= 0x02; 10465 } 10466 } 10467 if(vbflag & TV_SCART) { 10468 CR31 |= 0x01; 10469 CR35 |= 0x01; 10470 } 10471 } 10472 10473 CR31 &= ~0x04; /* Clear NotSimuMode */ 10474 pSiS->SiS_Pr->SiS_CHOverScan = pSiS->UseCHOverScan; 10475 if((pSiS->OptTVSOver == 1) && (pSiS->ChrontelType == CHRONTEL_700x)) { 10476 pSiS->SiS_Pr->SiS_CHSOverScan = TRUE; 10477 } else { 10478 pSiS->SiS_Pr->SiS_CHSOverScan = FALSE; 10479 } 10480#ifdef SIS_CP 10481 SIS_CP_DRIVER_CONFIG 10482#endif 10483 break; 10484 10485 case CRT2_LCD: 10486 CR30 |= 0x20; 10487 SiS_SetEnableDstn(pSiS->SiS_Pr, pSiS->DSTN); 10488 SiS_SetEnableFstn(pSiS->SiS_Pr, pSiS->FSTN); 10489 break; 10490 10491 case CRT2_VGA: 10492 CR30 |= 0x40; 10493 break; 10494 10495 default: 10496 CR30 |= 0x00; 10497 CR31 |= 0x20; /* VB_OUTPUT_DISABLE */ 10498 if(pSiS->UseVESA) { 10499 crt1rateindex = SISSearchCRT1Rate(pScrn, mymode); 10500 } 10501 } 10502 10503 } 10504 10505 if(vbflag & CRT1_LCDA) { 10506 switch(viewmode) { 10507 case SIS_MODE_CRT1: 10508 CR38 |= 0x01; 10509 break; 10510 case SIS_MODE_CRT2: 10511 if(vbflag & (CRT2_TV|CRT2_VGA)) { 10512 CR30 |= 0x02; 10513 CR38 |= 0x01; 10514 } else { 10515 CR38 |= 0x03; 10516 } 10517 break; 10518 case SIS_MODE_SIMU: 10519 default: 10520 if(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA)) { 10521 CR30 |= 0x01; 10522 } 10523 break; 10524 } 10525 } else { 10526 if(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA)) { 10527 CR30 |= 0x01; 10528 } 10529 } 10530 10531 if(pSiS->UseVESA) { 10532 CR31 &= ~0x40; /* Clear Drivermode */ 10533 CR31 |= 0x06; /* Set SlaveMode, Enable SimuMode in Slavemode */ 10534#ifdef TWDEBUG 10535 CR31 |= 0x40; /* DEBUG (for non-slave mode VESA) */ 10536 crt1rateindex = SISSearchCRT1Rate(pScrn, mymode); 10537#endif 10538 } else { 10539 CR31 |= 0x40; /* Set Drivermode */ 10540 CR31 &= ~0x06; /* Disable SlaveMode, disable SimuMode in SlaveMode */ 10541 if(!pSiS->IsCustom) { 10542 crt1rateindex = SISSearchCRT1Rate(pScrn, mymode); 10543 } 10544 } 10545 10546 switch(viewmode) { 10547 case SIS_MODE_SIMU: 10548 CR33 = 0; 10549 if(!(vbflag & CRT1_LCDA)) { 10550 CR33 |= (crt1rateindex & 0x0f); 10551 } 10552 if(vbflag & CRT2_VGA) { 10553 CR33 |= ((crt1rateindex & 0x0f) << 4); 10554 } 10555 break; 10556 case SIS_MODE_CRT1: 10557 CR33 &= 0xf0; 10558 if(!(vbflag & CRT1_LCDA)) { 10559 CR33 |= (crt1rateindex & 0x0f); 10560 } 10561 break; 10562 case SIS_MODE_CRT2: 10563 CR33 &= 0x0f; 10564 if(vbflag & CRT2_VGA) { 10565 CR33 |= ((crt1rateindex & 0x0f) << 4); 10566 } 10567 break; 10568 } 10569 10570 if((!pSiS->UseVESA) && (vbflag & CRT2_ENABLE)) { 10571 if(pSiS->CRT1off) CR33 &= 0xf0; 10572 } 10573 10574 if(pSiS->NewCRLayout) { 10575 10576 CR31 &= 0xfe; /* Clear PAL flag (now in CR35) */ 10577 CR38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */ 10578 outSISIDXREG(SISCR, 0x30, CR30); 10579 outSISIDXREG(SISCR, 0x31, CR31); 10580 outSISIDXREG(SISCR, 0x33, CR33); 10581 outSISIDXREG(SISCR, 0x35, CR35); 10582 setSISIDXREG(SISCR, 0x38, 0xf8, CR38); 10583 outSISIDXREG(SISCR, 0x39, CR39); 10584 10585 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, SISVERBLEVEL, 10586 "After: CR30=0x%02x,CR31=0x%02x,CR33=0x%02x,CR35=0x%02x,CR38=%02x\n", 10587 CR30, CR31, CR33, CR35, CR38); 10588 10589 } else { 10590 10591 outSISIDXREG(SISCR, 0x30, CR30); 10592 outSISIDXREG(SISCR, 0x31, CR31); 10593 outSISIDXREG(SISCR, 0x33, CR33); 10594 if(temp) { 10595 outSISIDXREG(SISCR, temp, CR38); 10596 } 10597 if(pSiS->VGAEngine == SIS_315_VGA) { 10598 outSISIDXREG(SISCR, 0x3b, CR3B); 10599 outSISIDXREG(SISCR, 0x79, CR79); 10600 } 10601 10602 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, SISVERBLEVEL, 10603 "After: CR30=0x%02x,CR31=0x%02x,CR33=0x%02x,CR%02x=%02x\n", 10604 CR30, CR31, CR33, temp, CR38); 10605 } 10606 10607 pSiS->SiS_Pr->SiS_UseOEM = pSiS->OptUseOEM; 10608 10609 /* Enable TurboQueue */ 10610#ifdef SISVRAMQ 10611 if(pSiS->VGAEngine != SIS_315_VGA) 10612#endif 10613 SiSEnableTurboQueue(pScrn); 10614 10615 if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE)) { 10616 /* Switch on CRT1 for modes that require the bridge in SlaveMode */ 10617 andSISIDXREG(SISSR,0x1f,0x3f); 10618 inSISIDXREG(SISCR, 0x17, CR17); 10619 if(!(CR17 & 0x80)) { 10620 orSISIDXREG(SISCR, 0x17, 0x80); 10621 outSISIDXREG(SISSR, 0x00, 0x01); 10622 usleep(10000); 10623 outSISIDXREG(SISSR, 0x00, 0x03); 10624 } 10625 } 10626} 10627 10628/* Functions for adjusting various TV settings */ 10629 10630/* These are used by the PostSetMode() functions as well as 10631 * the display properties tool SiSCtrl. 10632 * 10633 * There is each a Set and a Get routine. The Set functions 10634 * take a value of the same range as the corresponding option. 10635 * The Get routines return a value of the same range (although 10636 * not necessarily the same value as previously set because 10637 * of the lower resolution of the respective setting compared 10638 * to the valid range). 10639 * The Get routines return -2 on error (eg. hardware does not 10640 * support this setting). 10641 * Note: The x and y positioning routines accept a position 10642 * RELATIVE to the default position. All other routines 10643 * take ABSOLUTE values. 10644 * 10645 * The Set functions will store the property regardless if TV is 10646 * currently used or not and if the hardware supports the property 10647 * or not. The Get routines will return this stored 10648 * value if TV is not currently used (because the register does 10649 * not contain the correct value then) or if the hardware supports 10650 * the respective property. This should make it easier for the 10651 * display property tool because it does not have to know the 10652 * hardware features. 10653 * 10654 * All the routines are dual head aware. It does not matter 10655 * if the function is called from the CRT1 or CRT2 session. 10656 * The values will be in pSiSEnt anyway, and read from there 10657 * if we're running dual head. 10658 */ 10659 10660void SiS_SetCHTVlumabandwidthcvbs(ScrnInfoPtr pScrn, int val) 10661{ 10662 SISPtr pSiS = SISPTR(pScrn); 10663#ifdef SISDUALHEAD 10664 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10665#endif 10666 10667 pSiS->chtvlumabandwidthcvbs = val; 10668#ifdef SISDUALHEAD 10669 if(pSiSEnt) pSiSEnt->chtvlumabandwidthcvbs = val; 10670#endif 10671 10672 if(!(pSiS->VBFlags & CRT2_TV)) return; 10673 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10674 10675#ifdef UNLOCK_ALWAYS 10676 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10677#endif 10678 10679 switch(pSiS->ChrontelType) { 10680 case CHRONTEL_700x: 10681 val /= 8; 10682 if((val == 0) || (val == 1)) { 10683 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, val, 0xFE); 10684 } 10685 break; 10686 case CHRONTEL_701x: 10687 val /= 4; 10688 if((val >= 0) && (val <= 3)) { 10689 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, val, 0xFC); 10690 } 10691 break; 10692 } 10693} 10694 10695int SiS_GetCHTVlumabandwidthcvbs(ScrnInfoPtr pScrn) 10696{ 10697 SISPtr pSiS = SISPTR(pScrn); 10698#ifdef SISDUALHEAD 10699 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10700#endif 10701 10702 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10703#ifdef SISDUALHEAD 10704 if(pSiSEnt && pSiS->DualHeadMode) 10705 return (int)pSiSEnt->chtvlumabandwidthcvbs; 10706 else 10707#endif 10708 return (int)pSiS->chtvlumabandwidthcvbs; 10709 } else { 10710#ifdef UNLOCK_ALWAYS 10711 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10712#endif 10713 switch(pSiS->ChrontelType) { 10714 case CHRONTEL_700x: 10715 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x01) * 8); 10716 case CHRONTEL_701x: 10717 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x03) * 4); 10718 default: 10719 return (int)pSiS->chtvlumabandwidthcvbs; 10720 } 10721 } 10722} 10723 10724void SiS_SetCHTVlumabandwidthsvideo(ScrnInfoPtr pScrn, int val) 10725{ 10726 SISPtr pSiS = SISPTR(pScrn); 10727#ifdef SISDUALHEAD 10728 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10729#endif 10730 10731 pSiS->chtvlumabandwidthsvideo = val; 10732#ifdef SISDUALHEAD 10733 if(pSiSEnt) pSiSEnt->chtvlumabandwidthsvideo = val; 10734#endif 10735 10736 if(!(pSiS->VBFlags & CRT2_TV)) return; 10737 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10738 10739#ifdef UNLOCK_ALWAYS 10740 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10741#endif 10742 10743 switch(pSiS->ChrontelType) { 10744 case CHRONTEL_700x: 10745 val /= 6; 10746 if((val >= 0) && (val <= 2)) { 10747 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, (val << 1), 0xF9); 10748 } 10749 break; 10750 case CHRONTEL_701x: 10751 val /= 4; 10752 if((val >= 0) && (val <= 3)) { 10753 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, (val << 2), 0xF3); 10754 } 10755 break; 10756 } 10757} 10758 10759int SiS_GetCHTVlumabandwidthsvideo(ScrnInfoPtr pScrn) 10760{ 10761 SISPtr pSiS = SISPTR(pScrn); 10762#ifdef SISDUALHEAD 10763 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10764#endif 10765 10766 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10767#ifdef SISDUALHEAD 10768 if(pSiSEnt && pSiS->DualHeadMode) 10769 return (int)pSiSEnt->chtvlumabandwidthsvideo; 10770 else 10771#endif 10772 return (int)pSiS->chtvlumabandwidthsvideo; 10773 } else { 10774#ifdef UNLOCK_ALWAYS 10775 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10776#endif 10777 switch(pSiS->ChrontelType) { 10778 case CHRONTEL_700x: 10779 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x06) >> 1) * 6); 10780 case CHRONTEL_701x: 10781 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x0c) >> 2) * 4); 10782 default: 10783 return (int)pSiS->chtvlumabandwidthsvideo; 10784 } 10785 } 10786} 10787 10788void SiS_SetCHTVlumaflickerfilter(ScrnInfoPtr pScrn, int val) 10789{ 10790 SISPtr pSiS = SISPTR(pScrn); 10791#ifdef SISDUALHEAD 10792 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10793#endif 10794 10795 pSiS->chtvlumaflickerfilter = val; 10796#ifdef SISDUALHEAD 10797 if(pSiSEnt) pSiSEnt->chtvlumaflickerfilter = val; 10798#endif 10799 10800 if(!(pSiS->VBFlags & CRT2_TV)) return; 10801 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10802 10803#ifdef UNLOCK_ALWAYS 10804 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10805#endif 10806 10807 switch(pSiS->ChrontelType) { 10808 case CHRONTEL_700x: 10809 val /= 6; 10810 if((val >= 0) && (val <= 2)) { 10811 UShort reg = 0; 10812 reg = SiS_GetCH70xx(pSiS->SiS_Pr, 0x01); 10813 reg = (reg & 0xf0) | ((reg & 0x0c) >> 2) | (val << 2); 10814 SiS_SetCH70xx(pSiS->SiS_Pr, 0x01, reg); 10815 } 10816 break; 10817 case CHRONTEL_701x: 10818 val /= 4; 10819 if((val >= 0) && (val <= 3)) { 10820 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x01, (val << 2), 0xF3); 10821 } 10822 break; 10823 } 10824} 10825 10826int SiS_GetCHTVlumaflickerfilter(ScrnInfoPtr pScrn) 10827{ 10828 SISPtr pSiS = SISPTR(pScrn); 10829#ifdef SISDUALHEAD 10830 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10831#endif 10832 10833 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10834#ifdef SISDUALHEAD 10835 if(pSiSEnt && pSiS->DualHeadMode) 10836 return (int)pSiSEnt->chtvlumaflickerfilter; 10837 else 10838#endif 10839 return (int)pSiS->chtvlumaflickerfilter; 10840 } else { 10841#ifdef UNLOCK_ALWAYS 10842 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10843#endif 10844 switch(pSiS->ChrontelType) { 10845 case CHRONTEL_700x: 10846 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x03) * 6); 10847 case CHRONTEL_701x: 10848 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x0c) >> 2) * 4); 10849 default: 10850 return (int)pSiS->chtvlumaflickerfilter; 10851 } 10852 } 10853} 10854 10855void SiS_SetCHTVchromabandwidth(ScrnInfoPtr pScrn, int val) 10856{ 10857 SISPtr pSiS = SISPTR(pScrn); 10858#ifdef SISDUALHEAD 10859 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10860#endif 10861 10862 pSiS->chtvchromabandwidth = val; 10863#ifdef SISDUALHEAD 10864 if(pSiSEnt) pSiSEnt->chtvchromabandwidth = val; 10865#endif 10866 10867 if(!(pSiS->VBFlags & CRT2_TV)) return; 10868 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10869 10870#ifdef UNLOCK_ALWAYS 10871 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10872#endif 10873 10874 switch(pSiS->ChrontelType) { 10875 case CHRONTEL_700x: 10876 val /= 4; 10877 if((val >= 0) && (val <= 3)) { 10878 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, (val << 4), 0xCF); 10879 } 10880 break; 10881 case CHRONTEL_701x: 10882 val /= 8; 10883 if((val >= 0) && (val <= 1)) { 10884 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, (val << 4), 0xEF); 10885 } 10886 break; 10887 } 10888} 10889 10890int SiS_GetCHTVchromabandwidth(ScrnInfoPtr pScrn) 10891{ 10892 SISPtr pSiS = SISPTR(pScrn); 10893#ifdef SISDUALHEAD 10894 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10895#endif 10896 10897 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10898#ifdef SISDUALHEAD 10899 if(pSiSEnt && pSiS->DualHeadMode) 10900 return (int)pSiSEnt->chtvchromabandwidth; 10901 else 10902#endif 10903 return (int)pSiS->chtvchromabandwidth; 10904 } else { 10905#ifdef UNLOCK_ALWAYS 10906 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10907#endif 10908 switch(pSiS->ChrontelType) { 10909 case CHRONTEL_700x: 10910 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x30) >> 4) * 4); 10911 case CHRONTEL_701x: 10912 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x10) >> 4) * 8); 10913 default: 10914 return (int)pSiS->chtvchromabandwidth; 10915 } 10916 } 10917} 10918 10919void SiS_SetCHTVchromaflickerfilter(ScrnInfoPtr pScrn, int val) 10920{ 10921 SISPtr pSiS = SISPTR(pScrn); 10922#ifdef SISDUALHEAD 10923 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10924#endif 10925 10926 pSiS->chtvchromaflickerfilter = val; 10927#ifdef SISDUALHEAD 10928 if(pSiSEnt) pSiSEnt->chtvchromaflickerfilter = val; 10929#endif 10930 10931 if(!(pSiS->VBFlags & CRT2_TV)) return; 10932 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10933 10934#ifdef UNLOCK_ALWAYS 10935 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10936#endif 10937 10938 switch(pSiS->ChrontelType) { 10939 case CHRONTEL_700x: 10940 val /= 6; 10941 if((val >= 0) && (val <= 2)) { 10942 UShort reg = 0; 10943 reg = SiS_GetCH70xx(pSiS->SiS_Pr, 0x01); 10944 reg = (reg & 0xc0) | ((reg & 0x0c) >> 2) | ((reg & 0x03) << 2) | (val << 4); 10945 SiS_SetCH70xx(pSiS->SiS_Pr, 0x01, reg); 10946 } 10947 break; 10948 case CHRONTEL_701x: 10949 val /= 4; 10950 if((val >= 0) && (val <= 3)) { 10951 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x01, (val << 4), 0xCF); 10952 } 10953 break; 10954 } 10955} 10956 10957int SiS_GetCHTVchromaflickerfilter(ScrnInfoPtr pScrn) 10958{ 10959 SISPtr pSiS = SISPTR(pScrn); 10960#ifdef SISDUALHEAD 10961 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10962#endif 10963 10964 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10965#ifdef SISDUALHEAD 10966 if(pSiSEnt && pSiS->DualHeadMode) 10967 return (int)pSiSEnt->chtvchromaflickerfilter; 10968 else 10969#endif 10970 return (int)pSiS->chtvchromaflickerfilter; 10971 } else { 10972#ifdef UNLOCK_ALWAYS 10973 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10974#endif 10975 switch(pSiS->ChrontelType) { 10976 case CHRONTEL_700x: 10977 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x30) >> 4) * 6); 10978 case CHRONTEL_701x: 10979 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x30) >> 4) * 4); 10980 default: 10981 return (int)pSiS->chtvchromaflickerfilter; 10982 } 10983 } 10984} 10985 10986void SiS_SetCHTVcvbscolor(ScrnInfoPtr pScrn, int val) 10987{ 10988 SISPtr pSiS = SISPTR(pScrn); 10989#ifdef SISDUALHEAD 10990 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10991#endif 10992 10993 pSiS->chtvcvbscolor = val ? 1 : 0; 10994#ifdef SISDUALHEAD 10995 if(pSiSEnt) pSiSEnt->chtvcvbscolor = pSiS->chtvcvbscolor; 10996#endif 10997 10998 if(!(pSiS->VBFlags & CRT2_TV)) return; 10999 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 11000 11001#ifdef UNLOCK_ALWAYS 11002 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11003#endif 11004 11005 switch(pSiS->ChrontelType) { 11006 case CHRONTEL_700x: 11007 if(!val) SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, 0x40, 0x00); 11008 else SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, 0x00, ~0x40); 11009 break; 11010 case CHRONTEL_701x: 11011 if(!val) SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, 0x00, ~0x20); 11012 else SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, 0x20, 0x00); 11013 break; 11014 } 11015} 11016 11017int SiS_GetCHTVcvbscolor(ScrnInfoPtr pScrn) 11018{ 11019 SISPtr pSiS = SISPTR(pScrn); 11020#ifdef SISDUALHEAD 11021 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11022#endif 11023 11024 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 11025#ifdef SISDUALHEAD 11026 if(pSiSEnt && pSiS->DualHeadMode) 11027 return (int)pSiSEnt->chtvcvbscolor; 11028 else 11029#endif 11030 return (int)pSiS->chtvcvbscolor; 11031 } else { 11032#ifdef UNLOCK_ALWAYS 11033 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11034#endif 11035 switch(pSiS->ChrontelType) { 11036 case CHRONTEL_700x: 11037 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x40) >> 6) ^ 0x01); 11038 case CHRONTEL_701x: 11039 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x20) >> 5) ^ 0x01); 11040 default: 11041 return (int)pSiS->chtvcvbscolor; 11042 } 11043 } 11044} 11045 11046void SiS_SetCHTVtextenhance(ScrnInfoPtr pScrn, int val) 11047{ 11048 SISPtr pSiS = SISPTR(pScrn); 11049#ifdef SISDUALHEAD 11050 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11051#endif 11052 11053 pSiS->chtvtextenhance = val; 11054#ifdef SISDUALHEAD 11055 if(pSiSEnt) pSiSEnt->chtvtextenhance = val; 11056#endif 11057 11058 if(!(pSiS->VBFlags & CRT2_TV)) return; 11059 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 11060 11061#ifdef UNLOCK_ALWAYS 11062 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11063#endif 11064 11065 switch(pSiS->ChrontelType) { 11066 case CHRONTEL_700x: 11067 val /= 6; 11068 if((val >= 0) && (val <= 2)) { 11069 UShort reg = 0; 11070 reg = SiS_GetCH70xx(pSiS->SiS_Pr, 0x01); 11071 reg = (reg & 0xf0) | ((reg & 0x03) << 2) | val; 11072 SiS_SetCH70xx(pSiS->SiS_Pr, 0x01, reg); 11073 } 11074 break; 11075 case CHRONTEL_701x: 11076 val /= 2; 11077 if((val >= 0) && (val <= 7)) { 11078 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, val, 0xF8); 11079 } 11080 break; 11081 } 11082} 11083 11084int SiS_GetCHTVtextenhance(ScrnInfoPtr pScrn) 11085{ 11086 SISPtr pSiS = SISPTR(pScrn); 11087#ifdef SISDUALHEAD 11088 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11089#endif 11090 11091 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 11092#ifdef SISDUALHEAD 11093 if(pSiSEnt && pSiS->DualHeadMode) 11094 return (int)pSiSEnt->chtvtextenhance; 11095 else 11096#endif 11097 return (int)pSiS->chtvtextenhance; 11098 } else { 11099#ifdef UNLOCK_ALWAYS 11100 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11101#endif 11102 switch(pSiS->ChrontelType) { 11103 case CHRONTEL_700x: 11104 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x0c) >> 2) * 6); 11105 case CHRONTEL_701x: 11106 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x07) * 2); 11107 default: 11108 return (int)pSiS->chtvtextenhance; 11109 } 11110 } 11111} 11112 11113void SiS_SetCHTVcontrast(ScrnInfoPtr pScrn, int val) 11114{ 11115 SISPtr pSiS = SISPTR(pScrn); 11116#ifdef SISDUALHEAD 11117 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11118#endif 11119 11120 pSiS->chtvcontrast = val; 11121#ifdef SISDUALHEAD 11122 if(pSiSEnt) pSiSEnt->chtvcontrast = val; 11123#endif 11124 11125 if(!(pSiS->VBFlags & CRT2_TV)) return; 11126 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 11127 11128#ifdef UNLOCK_ALWAYS 11129 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11130#endif 11131 11132 val /= 2; 11133 if((val >= 0) && (val <= 7)) { 11134 switch(pSiS->ChrontelType) { 11135 case CHRONTEL_700x: 11136 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x11, val, 0xF8); 11137 break; 11138 case CHRONTEL_701x: 11139 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x08, val, 0xF8); 11140 break; 11141 } 11142 SiS_DDC2Delay(pSiS->SiS_Pr, 1000); 11143 } 11144} 11145 11146int SiS_GetCHTVcontrast(ScrnInfoPtr pScrn) 11147{ 11148 SISPtr pSiS = SISPTR(pScrn); 11149#ifdef SISDUALHEAD 11150 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11151#endif 11152 11153 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 11154#ifdef SISDUALHEAD 11155 if(pSiSEnt && pSiS->DualHeadMode) 11156 return (int)pSiSEnt->chtvcontrast; 11157 else 11158#endif 11159 return (int)pSiS->chtvcontrast; 11160 } else { 11161#ifdef UNLOCK_ALWAYS 11162 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11163#endif 11164 switch(pSiS->ChrontelType) { 11165 case CHRONTEL_700x: 11166 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x11) & 0x07) * 2); 11167 case CHRONTEL_701x: 11168 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x08) & 0x07) * 2); 11169 default: 11170 return (int)pSiS->chtvcontrast; 11171 } 11172 } 11173} 11174 11175void SiS_SetSISTVedgeenhance(ScrnInfoPtr pScrn, int val) 11176{ 11177 SISPtr pSiS = SISPTR(pScrn); 11178#ifdef SISDUALHEAD 11179 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11180#endif 11181 11182 pSiS->sistvedgeenhance = val; 11183#ifdef SISDUALHEAD 11184 if(pSiSEnt) pSiSEnt->sistvedgeenhance = val; 11185#endif 11186 11187 if(!(pSiS->VBFlags2 & VB2_301)) return; 11188 if(!(pSiS->VBFlags & CRT2_TV)) return; 11189 11190#ifdef UNLOCK_ALWAYS 11191 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11192#endif 11193 11194 val /= 2; 11195 if((val >= 0) && (val <= 7)) { 11196 setSISIDXREG(SISPART2,0x3A, 0x1F, (val << 5)); 11197 } 11198} 11199 11200int SiS_GetSISTVedgeenhance(ScrnInfoPtr pScrn) 11201{ 11202 SISPtr pSiS = SISPTR(pScrn); 11203 int result = pSiS->sistvedgeenhance; 11204 UChar temp; 11205#ifdef SISDUALHEAD 11206 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11207 11208 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvedgeenhance; 11209#endif 11210 11211 if(!(pSiS->VBFlags2 & VB2_301)) return result; 11212 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11213 11214#ifdef UNLOCK_ALWAYS 11215 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11216#endif 11217 inSISIDXREG(SISPART2, 0x3a, temp); 11218 return(int)(((temp & 0xe0) >> 5) * 2); 11219} 11220 11221void SiS_SetSISTVantiflicker(ScrnInfoPtr pScrn, int val) 11222{ 11223 SISPtr pSiS = SISPTR(pScrn); 11224#ifdef SISDUALHEAD 11225 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11226#endif 11227 11228 pSiS->sistvantiflicker = val; 11229#ifdef SISDUALHEAD 11230 if(pSiSEnt) pSiSEnt->sistvantiflicker = val; 11231#endif 11232 11233 if(!(pSiS->VBFlags & CRT2_TV)) return; 11234 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11235 if(pSiS->VBFlags & TV_HIVISION) return; 11236 if((pSiS->VBFlags & TV_YPBPR) && 11237 (pSiS->VBFlags & (TV_YPBPR525P | TV_YPBPR625P | TV_YPBPR750P | TV_YPBPR1080I))) return; 11238 11239#ifdef UNLOCK_ALWAYS 11240 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11241#endif 11242 11243 /* Valid values: 0=off, 1=low, 2=med, 3=high, 4=adaptive */ 11244 if((val >= 0) && (val <= 4)) { 11245 setSISIDXREG(SISPART2,0x0A,0x8F, (val << 4)); 11246 } 11247} 11248 11249int SiS_GetSISTVantiflicker(ScrnInfoPtr pScrn) 11250{ 11251 SISPtr pSiS = SISPTR(pScrn); 11252 int result = pSiS->sistvantiflicker; 11253 UChar temp; 11254#ifdef SISDUALHEAD 11255 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11256 11257 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvantiflicker; 11258#endif 11259 11260 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return result; 11261 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11262 if(pSiS->VBFlags & TV_HIVISION) return result; 11263 if((pSiS->VBFlags & TV_YPBPR) && 11264 (pSiS->VBFlags & (TV_YPBPR525P | TV_YPBPR625P | TV_YPBPR750P | TV_YPBPR1080I))) return result; 11265 11266#ifdef UNLOCK_ALWAYS 11267 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11268#endif 11269 inSISIDXREG(SISPART2, 0x0a, temp); 11270 return(int)((temp & 0x70) >> 4); 11271} 11272 11273void SiS_SetSISTVsaturation(ScrnInfoPtr pScrn, int val) 11274{ 11275 SISPtr pSiS = SISPTR(pScrn); 11276#ifdef SISDUALHEAD 11277 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11278#endif 11279 11280 pSiS->sistvsaturation = val; 11281#ifdef SISDUALHEAD 11282 if(pSiSEnt) pSiSEnt->sistvsaturation = val; 11283#endif 11284 11285 if(!(pSiS->VBFlags & CRT2_TV)) return; 11286 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11287 if(pSiS->VBFlags2 & VB2_301) return; 11288 11289#ifdef UNLOCK_ALWAYS 11290 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11291#endif 11292 11293 val /= 2; 11294 if((val >= 0) && (val <= 7)) { 11295 setSISIDXREG(SISPART4,0x21,0xF8, val); 11296 } 11297} 11298 11299int SiS_GetSISTVsaturation(ScrnInfoPtr pScrn) 11300{ 11301 SISPtr pSiS = SISPTR(pScrn); 11302 int result = pSiS->sistvsaturation; 11303 UChar temp; 11304#ifdef SISDUALHEAD 11305 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11306 11307 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvsaturation; 11308#endif 11309 11310 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return result; 11311 if(pSiS->VBFlags2 & VB2_301) return result; 11312 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11313 11314#ifdef UNLOCK_ALWAYS 11315 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11316#endif 11317 inSISIDXREG(SISPART4, 0x21, temp); 11318 return(int)((temp & 0x07) * 2); 11319} 11320 11321void SiS_SetSISTVcolcalib(ScrnInfoPtr pScrn, int val, Bool coarse) 11322{ 11323 SISPtr pSiS = SISPTR(pScrn); 11324#ifdef SISDUALHEAD 11325 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11326#endif 11327 int ccoarse, cfine, cbase = pSiS->sistvccbase; 11328 /* UChar temp; */ 11329 11330#ifdef SISDUALHEAD 11331 if(pSiSEnt && pSiS->DualHeadMode) cbase = pSiSEnt->sistvccbase; 11332#endif 11333 11334 if(coarse) { 11335 pSiS->sistvcolcalibc = ccoarse = val; 11336 cfine = pSiS->sistvcolcalibf; 11337#ifdef SISDUALHEAD 11338 if(pSiSEnt) { 11339 pSiSEnt->sistvcolcalibc = val; 11340 if(pSiS->DualHeadMode) cfine = pSiSEnt->sistvcolcalibf; 11341 } 11342#endif 11343 } else { 11344 pSiS->sistvcolcalibf = cfine = val; 11345 ccoarse = pSiS->sistvcolcalibc; 11346#ifdef SISDUALHEAD 11347 if(pSiSEnt) { 11348 pSiSEnt->sistvcolcalibf = val; 11349 if(pSiS->DualHeadMode) ccoarse = pSiSEnt->sistvcolcalibc; 11350 } 11351#endif 11352 } 11353 11354 if(!(pSiS->VBFlags & CRT2_TV)) return; 11355 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11356 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return; 11357 11358#ifdef UNLOCK_ALWAYS 11359 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11360#endif 11361 11362 if((cfine >= -128) && (cfine <= 127) && (ccoarse >= -120) && (ccoarse <= 120)) { 11363 long finalcc = cbase + (((ccoarse * 256) + cfine) * 256); 11364 11365#if 0 11366 inSISIDXREG(SISPART4,0x1f,temp); 11367 if(!(temp & 0x01)) { 11368 if(pSiS->VBFlags & TV_NTSC) finalcc += 0x21ed8620; 11369 else if(pSiS->VBFlags & TV_PALM) finalcc += ?; 11370 else if(pSiS->VBFlags & TV_PALM) finalcc += ?; 11371 else finalcc += 0x2a05d300; 11372 } 11373#endif 11374 setSISIDXREG(SISPART2,0x31,0x80,((finalcc >> 24) & 0x7f)); 11375 outSISIDXREG(SISPART2,0x32,((finalcc >> 16) & 0xff)); 11376 outSISIDXREG(SISPART2,0x33,((finalcc >> 8) & 0xff)); 11377 outSISIDXREG(SISPART2,0x34,(finalcc & 0xff)); 11378 } 11379} 11380 11381int SiS_GetSISTVcolcalib(ScrnInfoPtr pScrn, Bool coarse) 11382{ 11383 SISPtr pSiS = SISPTR(pScrn); 11384#ifdef SISDUALHEAD 11385 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11386 11387 if(pSiSEnt && pSiS->DualHeadMode) 11388 if(coarse) return (int)pSiSEnt->sistvcolcalibc; 11389 else return (int)pSiSEnt->sistvcolcalibf; 11390 else 11391#endif 11392 if(coarse) return (int)pSiS->sistvcolcalibc; 11393 else return (int)pSiS->sistvcolcalibf; 11394} 11395 11396void SiS_SetSISTVcfilter(ScrnInfoPtr pScrn, int val) 11397{ 11398 SISPtr pSiS = SISPTR(pScrn); 11399#ifdef SISDUALHEAD 11400 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11401#endif 11402 11403 pSiS->sistvcfilter = val ? 1 : 0; 11404#ifdef SISDUALHEAD 11405 if(pSiSEnt) pSiSEnt->sistvcfilter = pSiS->sistvcfilter; 11406#endif 11407 11408 if(!(pSiS->VBFlags & CRT2_TV)) return; 11409 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11410 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return; 11411 11412#ifdef UNLOCK_ALWAYS 11413 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11414#endif 11415 11416 setSISIDXREG(SISPART2,0x30,~0x10,((pSiS->sistvcfilter << 4) & 0x10)); 11417} 11418 11419int SiS_GetSISTVcfilter(ScrnInfoPtr pScrn) 11420{ 11421 SISPtr pSiS = SISPTR(pScrn); 11422 int result = pSiS->sistvcfilter; 11423 UChar temp; 11424#ifdef SISDUALHEAD 11425 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11426 11427 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvcfilter; 11428#endif 11429 11430 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return result; 11431 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11432 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return result; 11433 11434#ifdef UNLOCK_ALWAYS 11435 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11436#endif 11437 inSISIDXREG(SISPART2, 0x30, temp); 11438 return (int)((temp & 0x10) ? 1 : 0); 11439} 11440 11441void SiS_SetSISTVyfilter(ScrnInfoPtr pScrn, int val) 11442{ 11443 SISPtr pSiS = SISPTR(pScrn); 11444#ifdef SISDUALHEAD 11445 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11446#endif 11447 UChar p35,p36,p37,p38,p48,p49,p4a,p30; 11448 int i,j; 11449 11450 pSiS->sistvyfilter = val; 11451#ifdef SISDUALHEAD 11452 if(pSiSEnt) pSiSEnt->sistvyfilter = pSiS->sistvyfilter; 11453#endif 11454 11455 if(!(pSiS->VBFlags & CRT2_TV)) return; 11456 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11457 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return; 11458 11459 p35 = pSiS->p2_35; p36 = pSiS->p2_36; 11460 p37 = pSiS->p2_37; p38 = pSiS->p2_38; 11461 p48 = pSiS->p2_48; p49 = pSiS->p2_49; 11462 p4a = pSiS->p2_4a; p30 = pSiS->p2_30; 11463#ifdef SISDUALHEAD 11464 if(pSiSEnt && pSiS->DualHeadMode) { 11465 p35 = pSiSEnt->p2_35; p36 = pSiSEnt->p2_36; 11466 p37 = pSiSEnt->p2_37; p38 = pSiSEnt->p2_38; 11467 p48 = pSiSEnt->p2_48; p49 = pSiSEnt->p2_49; 11468 p4a = pSiSEnt->p2_4a; p30 = pSiSEnt->p2_30; 11469 } 11470#endif 11471 p30 &= 0x20; 11472 11473#ifdef UNLOCK_ALWAYS 11474 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11475#endif 11476 11477 switch(pSiS->sistvyfilter) { 11478 case 0: 11479 andSISIDXREG(SISPART2,0x30,0xdf); 11480 break; 11481 case 1: 11482 outSISIDXREG(SISPART2,0x35,p35); 11483 outSISIDXREG(SISPART2,0x36,p36); 11484 outSISIDXREG(SISPART2,0x37,p37); 11485 outSISIDXREG(SISPART2,0x38,p38); 11486 if(!(pSiS->VBFlags2 & VB2_301)) { 11487 outSISIDXREG(SISPART2,0x48,p48); 11488 outSISIDXREG(SISPART2,0x49,p49); 11489 outSISIDXREG(SISPART2,0x4a,p4a); 11490 } 11491 setSISIDXREG(SISPART2,0x30,0xdf,p30); 11492 break; 11493 case 2: 11494 case 3: 11495 case 4: 11496 case 5: 11497 case 6: 11498 case 7: 11499 case 8: 11500 if(!(pSiS->VBFlags & (TV_PALM | TV_PALN | TV_NTSCJ))) { 11501 int yindex301 = -1, yindex301B = -1; 11502 UChar p3d4_34; 11503 11504 inSISIDXREG(SISCR,0x34,p3d4_34); 11505 11506 switch((p3d4_34 & 0x7f)) { 11507 case 0x59: /* 320x200 */ 11508 case 0x41: 11509 case 0x4f: 11510 case 0x50: /* 320x240 */ 11511 case 0x56: 11512 case 0x53: 11513 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 0 : 4; 11514 break; 11515 case 0x2f: /* 640x400 */ 11516 case 0x5d: 11517 case 0x5e: 11518 case 0x2e: /* 640x480 */ 11519 case 0x44: 11520 case 0x62: 11521 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 1 : 5; 11522 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 0 : 4; 11523 break; 11524 case 0x31: /* 720x480 */ 11525 case 0x33: 11526 case 0x35: 11527 case 0x32: /* 720x576 */ 11528 case 0x34: 11529 case 0x36: 11530 case 0x5f: /* 768x576 */ 11531 case 0x60: 11532 case 0x61: 11533 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 2 : 6; 11534 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 1 : 5; 11535 break; 11536 case 0x51: /* 400x300 */ 11537 case 0x57: 11538 case 0x54: 11539 case 0x30: /* 800x600 */ 11540 case 0x47: 11541 case 0x63: 11542 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 3 : 7; 11543 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 2 : 6; 11544 break; 11545 case 0x52: /* 512x384 */ 11546 case 0x58: 11547 case 0x5c: 11548 case 0x38: /* 1024x768 */ 11549 case 0x4a: 11550 case 0x64: 11551 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 3 : 7; 11552 break; 11553 } 11554 if(pSiS->VBFlags2 & VB2_301) { 11555 if(yindex301 >= 0) { 11556 for(i=0, j=0x35; i<=3; i++, j++) { 11557 outSISIDXREG(SISPART2,j,(SiSTVFilter301[yindex301].filter[pSiS->sistvyfilter-2][i])); 11558 } 11559 } 11560 } else { 11561 if(yindex301B >= 0) { 11562 for(i=0, j=0x35; i<=3; i++, j++) { 11563 outSISIDXREG(SISPART2,j,(SiSTVFilter301B[yindex301B].filter[pSiS->sistvyfilter-2][i])); 11564 } 11565 for(i=4, j=0x48; i<=6; i++, j++) { 11566 outSISIDXREG(SISPART2,j,(SiSTVFilter301B[yindex301B].filter[pSiS->sistvyfilter-2][i])); 11567 } 11568 } 11569 } 11570 orSISIDXREG(SISPART2,0x30,0x20); 11571 } 11572 } 11573} 11574 11575int SiS_GetSISTVyfilter(ScrnInfoPtr pScrn) 11576{ 11577 SISPtr pSiS = SISPTR(pScrn); 11578#ifdef SISDUALHEAD 11579 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11580 11581 if(pSiSEnt && pSiS->DualHeadMode) 11582 return (int)pSiSEnt->sistvyfilter; 11583 else 11584#endif 11585 return (int)pSiS->sistvyfilter; 11586} 11587 11588void SiS_SetSIS6326TVantiflicker(ScrnInfoPtr pScrn, int val) 11589{ 11590 SISPtr pSiS = SISPTR(pScrn); 11591 UChar tmp; 11592 11593 pSiS->sistvantiflicker = val; 11594 11595 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 11596 11597#ifdef UNLOCK_ALWAYS 11598 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11599#endif 11600 11601 tmp = SiS6326GetTVReg(pScrn,0x00); 11602 if(!(tmp & 0x04)) return; 11603 11604 /* Valid values: 0=off, 1=low, 2=med, 3=high, 4=adaptive */ 11605 if(val >= 0 && val <= 4) { 11606 tmp &= 0x1f; 11607 tmp |= (val << 5); 11608 SiS6326SetTVReg(pScrn,0x00,tmp); 11609 } 11610} 11611 11612int SiS_GetSIS6326TVantiflicker(ScrnInfoPtr pScrn) 11613{ 11614 SISPtr pSiS = SISPTR(pScrn); 11615 UChar tmp; 11616 11617 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 11618 return (int)pSiS->sistvantiflicker; 11619 } 11620 11621#ifdef UNLOCK_ALWAYS 11622 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11623#endif 11624 11625 tmp = SiS6326GetTVReg(pScrn,0x00); 11626 if(!(tmp & 0x04)) { 11627 return (int)pSiS->sistvantiflicker; 11628 } else { 11629 return (int)((tmp >> 5) & 0x07); 11630 } 11631} 11632 11633void SiS_SetSIS6326TVenableyfilter(ScrnInfoPtr pScrn, int val) 11634{ 11635 SISPtr pSiS = SISPTR(pScrn); 11636 UChar tmp; 11637 11638 if(val) val = 1; 11639 pSiS->sis6326enableyfilter = val; 11640 11641 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 11642 11643#ifdef UNLOCK_ALWAYS 11644 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11645#endif 11646 11647 tmp = SiS6326GetTVReg(pScrn,0x00); 11648 if(!(tmp & 0x04)) return; 11649 11650 tmp = SiS6326GetTVReg(pScrn,0x43); 11651 tmp &= ~0x10; 11652 tmp |= ((val & 0x01) << 4); 11653 SiS6326SetTVReg(pScrn,0x43,tmp); 11654} 11655 11656int SiS_GetSIS6326TVenableyfilter(ScrnInfoPtr pScrn) 11657{ 11658 SISPtr pSiS = SISPTR(pScrn); 11659 UChar tmp; 11660 11661 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 11662 return (int)pSiS->sis6326enableyfilter; 11663 } 11664 11665#ifdef UNLOCK_ALWAYS 11666 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11667#endif 11668 11669 tmp = SiS6326GetTVReg(pScrn,0x00); 11670 if(!(tmp & 0x04)) { 11671 return (int)pSiS->sis6326enableyfilter; 11672 } else { 11673 tmp = SiS6326GetTVReg(pScrn,0x43); 11674 return (int)((tmp >> 4) & 0x01); 11675 } 11676} 11677 11678void SiS_SetSIS6326TVyfilterstrong(ScrnInfoPtr pScrn, int val) 11679{ 11680 SISPtr pSiS = SISPTR(pScrn); 11681 UChar tmp; 11682 11683 if(val) val = 1; 11684 pSiS->sis6326yfilterstrong = val; 11685 11686 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 11687 11688#ifdef UNLOCK_ALWAYS 11689 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11690#endif 11691 11692 tmp = SiS6326GetTVReg(pScrn,0x00); 11693 if(!(tmp & 0x04)) return; 11694 11695 tmp = SiS6326GetTVReg(pScrn,0x43); 11696 if(tmp & 0x10) { 11697 tmp &= ~0x40; 11698 tmp |= ((val & 0x01) << 6); 11699 SiS6326SetTVReg(pScrn,0x43,tmp); 11700 } 11701} 11702 11703int SiS_GetSIS6326TVyfilterstrong(ScrnInfoPtr pScrn) 11704{ 11705 SISPtr pSiS = SISPTR(pScrn); 11706 UChar tmp; 11707 11708 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 11709 return (int)pSiS->sis6326yfilterstrong; 11710 } 11711 11712#ifdef UNLOCK_ALWAYS 11713 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11714#endif 11715 11716 tmp = SiS6326GetTVReg(pScrn,0x00); 11717 if(!(tmp & 0x04)) { 11718 return (int)pSiS->sis6326yfilterstrong; 11719 } else { 11720 tmp = SiS6326GetTVReg(pScrn,0x43); 11721 if(!(tmp & 0x10)) { 11722 return (int)pSiS->sis6326yfilterstrong; 11723 } else { 11724 return (int)((tmp >> 6) & 0x01); 11725 } 11726 } 11727} 11728 11729void SiS_SetTVxposoffset(ScrnInfoPtr pScrn, int val) 11730{ 11731 SISPtr pSiS = SISPTR(pScrn); 11732#ifdef SISDUALHEAD 11733 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11734#endif 11735 11736#ifdef UNLOCK_ALWAYS 11737 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11738#endif 11739 11740 pSiS->tvxpos = val; 11741#ifdef SISDUALHEAD 11742 if(pSiSEnt) pSiSEnt->tvxpos = val; 11743#endif 11744 11745 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 11746 11747 if(pSiS->VBFlags & CRT2_TV) { 11748 11749 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 11750 11751 int x = pSiS->tvx; 11752#ifdef SISDUALHEAD 11753 if(pSiSEnt && pSiS->DualHeadMode) x = pSiSEnt->tvx; 11754#endif 11755 switch(pSiS->ChrontelType) { 11756 case CHRONTEL_700x: 11757 if((val >= -32) && (val <= 32)) { 11758 x += val; 11759 if(x < 0) x = 0; 11760 SiS_SetCH700x(pSiS->SiS_Pr, 0x0a, (x & 0xff)); 11761 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD); 11762 } 11763 break; 11764 case CHRONTEL_701x: 11765 /* Not supported by hardware */ 11766 break; 11767 } 11768 11769 } else if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 11770 11771 if((val >= -32) && (val <= 32)) { 11772 11773 UChar p2_1f,p2_20,p2_2b,p2_42,p2_43; 11774 UShort temp; 11775 int mult; 11776 11777 p2_1f = pSiS->p2_1f; 11778 p2_20 = pSiS->p2_20; 11779 p2_2b = pSiS->p2_2b; 11780 p2_42 = pSiS->p2_42; 11781 p2_43 = pSiS->p2_43; 11782#ifdef SISDUALHEAD 11783 if(pSiSEnt && pSiS->DualHeadMode) { 11784 p2_1f = pSiSEnt->p2_1f; 11785 p2_20 = pSiSEnt->p2_20; 11786 p2_2b = pSiSEnt->p2_2b; 11787 p2_42 = pSiSEnt->p2_42; 11788 p2_43 = pSiSEnt->p2_43; 11789 } 11790#endif 11791 mult = 2; 11792 if(pSiS->VBFlags & TV_YPBPR) { 11793 if(pSiS->VBFlags & (TV_YPBPR1080I | TV_YPBPR750P)) { 11794 mult = 4; 11795 } 11796 } 11797 11798 temp = p2_1f | ((p2_20 & 0xf0) << 4); 11799 temp += (val * mult); 11800 p2_1f = temp & 0xff; 11801 p2_20 = (temp & 0xf00) >> 4; 11802 p2_2b = ((p2_2b & 0x0f) + (val * mult)) & 0x0f; 11803 temp = p2_43 | ((p2_42 & 0xf0) << 4); 11804 temp += (val * mult); 11805 p2_43 = temp & 0xff; 11806 p2_42 = (temp & 0xf00) >> 4; 11807 SISWaitRetraceCRT2(pScrn); 11808 outSISIDXREG(SISPART2,0x1f,p2_1f); 11809 setSISIDXREG(SISPART2,0x20,0x0F,p2_20); 11810 setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b); 11811 setSISIDXREG(SISPART2,0x42,0x0F,p2_42); 11812 outSISIDXREG(SISPART2,0x43,p2_43); 11813 } 11814 } 11815 } 11816 11817 } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { 11818 11819 if(pSiS->SiS6326Flags & SIS6326_TVDETECTED) { 11820 11821 UChar tmp; 11822 UShort temp1, temp2, temp3; 11823 11824 tmp = SiS6326GetTVReg(pScrn,0x00); 11825 if(tmp & 0x04) { 11826 11827 temp1 = pSiS->tvx1; 11828 temp2 = pSiS->tvx2; 11829 temp3 = pSiS->tvx3; 11830 if((val >= -16) && (val <= 16)) { 11831 if(val > 0) { 11832 temp1 += (val * 4); 11833 temp2 += (val * 4); 11834 while((temp1 > 0x0fff) || (temp2 > 0x0fff)) { 11835 temp1 -= 4; 11836 temp2 -= 4; 11837 } 11838 } else { 11839 val = -val; 11840 temp3 += (val * 4); 11841 while(temp3 > 0x03ff) { 11842 temp3 -= 4; 11843 } 11844 } 11845 } 11846 SiS6326SetTVReg(pScrn,0x3a,(temp1 & 0xff)); 11847 tmp = SiS6326GetTVReg(pScrn,0x3c); 11848 tmp &= 0xf0; 11849 tmp |= ((temp1 & 0x0f00) >> 8); 11850 SiS6326SetTVReg(pScrn,0x3c,tmp); 11851 SiS6326SetTVReg(pScrn,0x26,(temp2 & 0xff)); 11852 tmp = SiS6326GetTVReg(pScrn,0x27); 11853 tmp &= 0x0f; 11854 tmp |= ((temp2 & 0x0f00) >> 4); 11855 SiS6326SetTVReg(pScrn,0x27,tmp); 11856 SiS6326SetTVReg(pScrn,0x12,(temp3 & 0xff)); 11857 tmp = SiS6326GetTVReg(pScrn,0x13); 11858 tmp &= ~0xC0; 11859 tmp |= ((temp3 & 0x0300) >> 2); 11860 SiS6326SetTVReg(pScrn,0x13,tmp); 11861 } 11862 } 11863 } 11864} 11865 11866int SiS_GetTVxposoffset(ScrnInfoPtr pScrn) 11867{ 11868 SISPtr pSiS = SISPTR(pScrn); 11869#ifdef SISDUALHEAD 11870 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11871 11872 if(pSiSEnt && pSiS->DualHeadMode) 11873 return (int)pSiSEnt->tvxpos; 11874 else 11875#endif 11876 return (int)pSiS->tvxpos; 11877} 11878 11879void SiS_SetTVyposoffset(ScrnInfoPtr pScrn, int val) 11880{ 11881 SISPtr pSiS = SISPTR(pScrn); 11882#ifdef SISDUALHEAD 11883 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11884#endif 11885 11886#ifdef UNLOCK_ALWAYS 11887 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11888#endif 11889 11890 pSiS->tvypos = val; 11891#ifdef SISDUALHEAD 11892 if(pSiSEnt) pSiSEnt->tvypos = val; 11893#endif 11894 11895 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 11896 11897 if(pSiS->VBFlags & CRT2_TV) { 11898 11899 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 11900 11901 int y = pSiS->tvy; 11902#ifdef SISDUALHEAD 11903 if(pSiSEnt && pSiS->DualHeadMode) y = pSiSEnt->tvy; 11904#endif 11905 switch(pSiS->ChrontelType) { 11906 case CHRONTEL_700x: 11907 if((val >= -32) && (val <= 32)) { 11908 y -= val; 11909 if(y < 0) y = 0; 11910 SiS_SetCH700x(pSiS->SiS_Pr, 0x0b, (y & 0xff)); 11911 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE); 11912 } 11913 break; 11914 case CHRONTEL_701x: 11915 /* Not supported by hardware */ 11916 break; 11917 } 11918 11919 } else if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 11920 11921 if((val >= -32) && (val <= 32)) { 11922 char p2_01, p2_02; 11923 11924 if( (pSiS->VBFlags & TV_HIVISION) || 11925 ((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & (TV_YPBPR1080I|TV_YPBPR750P))) ) { 11926 val *= 2; 11927 } else { 11928 val /= 2; /* 4 */ 11929 } 11930 11931 p2_01 = pSiS->p2_01; 11932 p2_02 = pSiS->p2_02; 11933#ifdef SISDUALHEAD 11934 if(pSiSEnt && pSiS->DualHeadMode) { 11935 p2_01 = pSiSEnt->p2_01; 11936 p2_02 = pSiSEnt->p2_02; 11937 } 11938#endif 11939 p2_01 += val; /* val * 2 */ 11940 p2_02 += val; /* val * 2 */ 11941 if(!(pSiS->VBFlags & (TV_YPBPR | TV_HIVISION))) { 11942 while((p2_01 <= 0) || (p2_02 <= 0)) { 11943 p2_01 += 2; 11944 p2_02 += 2; 11945 } 11946 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR1080I)) { 11947 while(p2_01 <= 8) { 11948 p2_01 += 2; 11949 p2_02 += 2; 11950 } 11951 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR750P)) { 11952 while(p2_01 <= 10) { 11953 p2_01 += 2; 11954 p2_02 += 2; 11955 } 11956 } 11957 11958 SISWaitRetraceCRT2(pScrn); 11959 outSISIDXREG(SISPART2,0x01,p2_01); 11960 outSISIDXREG(SISPART2,0x02,p2_02); 11961 } 11962 } 11963 11964 } 11965 11966 } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { 11967 11968 if(pSiS->SiS6326Flags & SIS6326_TVDETECTED) { 11969 11970 UChar tmp; 11971 int temp1, limit; 11972 11973 tmp = SiS6326GetTVReg(pScrn,0x00); 11974 if(tmp & 0x04) { 11975 11976 if((val >= -16) && (val <= 16)) { 11977 temp1 = (UShort)pSiS->tvy1; 11978 limit = (pSiS->SiS6326Flags & SIS6326_TVPAL) ? 625 : 525; 11979 if(val > 0) { 11980 temp1 += (val * 4); 11981 if(temp1 > limit) temp1 -= limit; 11982 } else { 11983 val = -val; 11984 temp1 -= (val * 2); 11985 if(temp1 <= 0) temp1 += (limit -1); 11986 } 11987 SiS6326SetTVReg(pScrn,0x11,(temp1 & 0xff)); 11988 tmp = SiS6326GetTVReg(pScrn,0x13); 11989 tmp &= ~0x30; 11990 tmp |= ((temp1 & 0x300) >> 4); 11991 SiS6326SetTVReg(pScrn,0x13,tmp); 11992 if(temp1 == 1) tmp = 0x10; 11993 else { 11994 if(pSiS->SiS6326Flags & SIS6326_TVPAL) { 11995 if((temp1 <= 3) || (temp1 >= (limit - 2))) tmp = 0x08; 11996 else if(temp1 < 22) tmp = 0x02; 11997 else tmp = 0x04; 11998 } else { 11999 if((temp1 <= 5) || (temp1 >= (limit - 4))) tmp = 0x08; 12000 else if(temp1 < 19) tmp = 0x02; 12001 else tmp = 0x04; 12002 } 12003 } 12004 SiS6326SetTVReg(pScrn,0x21,tmp); 12005 } 12006 } 12007 } 12008 } 12009} 12010 12011int SiS_GetTVyposoffset(ScrnInfoPtr pScrn) 12012{ 12013 SISPtr pSiS = SISPTR(pScrn); 12014#ifdef SISDUALHEAD 12015 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12016 12017 if(pSiSEnt && pSiS->DualHeadMode) 12018 return (int)pSiSEnt->tvypos; 12019 else 12020#endif 12021 return (int)pSiS->tvypos; 12022} 12023 12024void SiS_SetTVxscale(ScrnInfoPtr pScrn, int val) 12025{ 12026 SISPtr pSiS = SISPTR(pScrn); 12027#ifdef SISDUALHEAD 12028 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12029#endif 12030 12031#ifdef UNLOCK_ALWAYS 12032 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12033#endif 12034 12035 pSiS->tvxscale = val; 12036#ifdef SISDUALHEAD 12037 if(pSiSEnt) pSiSEnt->tvxscale = val; 12038#endif 12039 12040 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 12041 12042 if((pSiS->VBFlags & CRT2_TV) && (pSiS->VBFlags2 & VB2_SISBRIDGE)) { 12043 12044 if((val >= -16) && (val <= 16)) { 12045 12046 UChar p2_44,p2_45,p2_46; 12047 int scalingfactor, mult; 12048 12049 p2_44 = pSiS->p2_44; 12050 p2_45 = pSiS->p2_45 & 0x3f; 12051 p2_46 = pSiS->p2_46 & 0x07; 12052#ifdef SISDUALHEAD 12053 if(pSiSEnt && pSiS->DualHeadMode) { 12054 p2_44 = pSiSEnt->p2_44; 12055 p2_45 = pSiSEnt->p2_45 & 0x3f; 12056 p2_46 = pSiSEnt->p2_46 & 0x07; 12057 } 12058#endif 12059 scalingfactor = (p2_46 << 13) | ((p2_45 & 0x1f) << 8) | p2_44; 12060 12061 mult = 64; 12062 if(pSiS->VBFlags & TV_YPBPR) { 12063 if(pSiS->VBFlags & TV_YPBPR1080I) { 12064 mult = 190; 12065 } else if(pSiS->VBFlags & TV_YPBPR750P) { 12066 mult = 360; 12067 } 12068 } else if(pSiS->VBFlags & TV_HIVISION) { 12069 mult = 190; 12070 } 12071 12072 if(val < 0) { 12073 p2_45 &= 0xdf; 12074 scalingfactor += ((-val) * mult); 12075 if(scalingfactor > 0xffff) scalingfactor = 0xffff; 12076 } else if(val > 0) { 12077 p2_45 &= 0xdf; 12078 scalingfactor -= (val * mult); 12079 if(scalingfactor < 1) scalingfactor = 1; 12080 } 12081 12082 p2_44 = scalingfactor & 0xff; 12083 p2_45 &= 0xe0; 12084 p2_45 |= ((scalingfactor >> 8) & 0x1f); 12085 p2_46 = ((scalingfactor >> 13) & 0x07); 12086 12087 SISWaitRetraceCRT2(pScrn); 12088 outSISIDXREG(SISPART2,0x44,p2_44); 12089 setSISIDXREG(SISPART2,0x45,0xC0,p2_45); 12090 if(!(pSiS->VBFlags2 & VB2_301)) { 12091 setSISIDXREG(SISPART2,0x46,0xF8,p2_46); 12092 } 12093 12094 } 12095 12096 } 12097 12098 } 12099} 12100 12101int SiS_GetTVxscale(ScrnInfoPtr pScrn) 12102{ 12103 SISPtr pSiS = SISPTR(pScrn); 12104#ifdef SISDUALHEAD 12105 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12106 12107 if(pSiSEnt && pSiS->DualHeadMode) 12108 return (int)pSiSEnt->tvxscale; 12109 else 12110#endif 12111 return (int)pSiS->tvxscale; 12112} 12113 12114void SiS_SetTVyscale(ScrnInfoPtr pScrn, int val) 12115{ 12116 SISPtr pSiS = SISPTR(pScrn); 12117#ifdef SISDUALHEAD 12118 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12119#endif 12120 12121#ifdef UNLOCK_ALWAYS 12122 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12123#endif 12124 12125 if(val < -4) val = -4; 12126 if(val > 3) val = 3; 12127 12128 pSiS->tvyscale = val; 12129#ifdef SISDUALHEAD 12130 if(pSiSEnt) pSiSEnt->tvyscale = val; 12131#endif 12132 12133 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 12134 12135 if((pSiS->VBFlags & CRT2_TV) && (pSiS->VBFlags2 & VB2_SISBRIDGE)) { 12136 12137 int srindex = -1, newvde, i = 0, j, vlimit, temp, vdediv; 12138 int hdclk = 0; 12139 UChar p3d4_34; 12140 Bool found = FALSE; 12141 Bool usentsc = FALSE; 12142 Bool is750p = FALSE; 12143 Bool is1080i = FALSE; 12144 Bool skipmoveup = FALSE; 12145 12146 SiS_UnLockCRT2(pSiS->SiS_Pr); 12147 12148 if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR525P)) { 12149 vlimit = 525 - 7; 12150 vdediv = 1; 12151 usentsc = TRUE; 12152 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR625P)) { 12153 vlimit = 625 - 7; 12154 vdediv = 1; 12155 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR750P)) { 12156 vlimit = 750 - 7; 12157 vdediv = 1; 12158 is750p = TRUE; 12159 } else if(((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR1080I)) || 12160 (pSiS->VBFlags & TV_HIVISION)) { 12161 vlimit = (1125 - 7) / 2; 12162 vdediv = 2; 12163 is1080i = TRUE; 12164 } else { 12165 if( ((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR525I)) || 12166 ((!(pSiS->VBFlags & TV_YPBPR)) && (pSiS->VBFlags & (TV_NTSC | TV_PALM))) ) { 12167 usentsc = TRUE; 12168 } 12169 vlimit = usentsc ? 259 : 309; 12170 vdediv = 2; 12171 } 12172 12173 inSISIDXREG(SISCR,0x34,p3d4_34); 12174 12175 switch((p3d4_34 & 0x7f)) { 12176 case 0x50: /* 320x240 */ 12177 case 0x56: 12178 case 0x53: 12179 hdclk = 1; 12180 /* fall through */ 12181 case 0x2e: /* 640x480 */ 12182 case 0x44: 12183 case 0x62: 12184 if(is1080i) { 12185 srindex = 98; 12186 } else if(is750p) { 12187 srindex = 42; 12188 } else { 12189 srindex = usentsc ? 0 : 21; 12190 } 12191 break; 12192 case 0x31: /* 720x480 */ 12193 case 0x33: 12194 case 0x35: 12195 if(is1080i) { 12196 /* n/a */ 12197 } else if(is750p) { 12198 srindex = 49; 12199 } else { 12200 srindex = usentsc ? 7 : 21; 12201 } 12202 break; 12203 case 0x32: /* 720x576 */ 12204 case 0x34: 12205 case 0x36: 12206 case 0x5f: /* 768x576 */ 12207 case 0x60: 12208 case 0x61: 12209 if(is1080i) { 12210 /* n/a */ 12211 } else if(is750p) { 12212 srindex = 56; 12213 } else { 12214 srindex = usentsc ? 147 : 28; 12215 } 12216 break; 12217 case 0x70: /* 800x480 */ 12218 case 0x7a: 12219 case 0x76: 12220 if(is1080i) { 12221 srindex = 105; 12222 } else if(is750p) { 12223 srindex = 63; 12224 } else { 12225 srindex = usentsc ? 175 : 21; 12226 } 12227 break; 12228 case 0x51: /* 400x300 - hdclk mode */ 12229 case 0x57: 12230 case 0x54: 12231 hdclk = 1; 12232 /* fall through */ 12233 case 0x30: /* 800x600 */ 12234 case 0x47: 12235 case 0x63: 12236 if(is1080i) { 12237 srindex = 112; 12238 } else if(is750p) { 12239 srindex = 70; 12240 } else { 12241 srindex = usentsc ? 14 : 35; 12242 } 12243 break; 12244 case 0x1d: /* 960x540 */ 12245 case 0x1e: 12246 case 0x1f: 12247 if(is1080i) { 12248 srindex = 196; 12249 skipmoveup = TRUE; 12250 } 12251 break; 12252 case 0x20: /* 960x600 */ 12253 case 0x21: 12254 case 0x22: 12255 if(pSiS->VGAEngine == SIS_315_VGA && is1080i) { 12256 srindex = 203; 12257 } 12258 break; 12259 case 0x71: /* 1024x576 */ 12260 case 0x74: 12261 case 0x77: 12262 if(is1080i) { 12263 srindex = 119; 12264 } else if(is750p) { 12265 srindex = 77; 12266 } else { 12267 srindex = usentsc ? 182 : 189; 12268 } 12269 break; 12270 case 0x52: /* 512x384 */ 12271 case 0x58: 12272 case 0x5c: 12273 hdclk = 1; 12274 /* fall through */ 12275 case 0x38: /* 1024x768 */ 12276 case 0x4a: 12277 case 0x64: 12278 if(is1080i) { 12279 srindex = 126; 12280 } else if(is750p) { 12281 srindex = 84; 12282 } else if(!usentsc) { 12283 srindex = 154; 12284 } else if(vdediv == 1) { 12285 if(!hdclk) srindex = 168; 12286 } else { 12287 if(!hdclk) srindex = 161; 12288 } 12289 break; 12290 case 0x79: /* 1280x720 */ 12291 case 0x75: 12292 case 0x78: 12293 if(is1080i) { 12294 srindex = 133; 12295 } else if(is750p) { 12296 srindex = 91; 12297 } 12298 break; 12299 case 0x3a: /* 1280x1024 */ 12300 case 0x4d: 12301 case 0x65: 12302 if(is1080i) { 12303 srindex = 140; 12304 } 12305 break; 12306 } 12307 12308 if(srindex < 0) return; 12309 12310 if(pSiS->tvyscale != 0) { 12311 for(j = 0; j <= 1; j++) { 12312 for(i = 0; i <= 6; i++) { 12313 if(SiSTVVScale[srindex+i].sindex == pSiS->tvyscale) { 12314 found = TRUE; 12315 break; 12316 } 12317 } 12318 if(found) break; 12319 if(pSiS->tvyscale > 0) pSiS->tvyscale--; 12320 else pSiS->tvyscale++; 12321 } 12322 } 12323 12324#ifdef SISDUALHEAD 12325 if(pSiSEnt) pSiSEnt->tvyscale = pSiS->tvyscale; 12326#endif 12327 12328 if(pSiS->tvyscale == 0) { 12329 UChar p2_0a = pSiS->p2_0a; 12330 UChar p2_2f = pSiS->p2_2f; 12331 UChar p2_30 = pSiS->p2_30; 12332 UChar p2_46 = pSiS->p2_46; 12333 UChar p2_47 = pSiS->p2_47; 12334 UChar p1scaling[9], p4scaling[9]; 12335 UChar *p2scaling; 12336 12337 for(i = 0; i < 9; i++) { 12338 p1scaling[i] = pSiS->scalingp1[i]; 12339 p4scaling[i] = pSiS->scalingp4[i]; 12340 } 12341 p2scaling = &pSiS->scalingp2[0]; 12342 12343#ifdef SISDUALHEAD 12344 if(pSiSEnt && pSiS->DualHeadMode) { 12345 p2_0a = pSiSEnt->p2_0a; 12346 p2_2f = pSiSEnt->p2_2f; 12347 p2_30 = pSiSEnt->p2_30; 12348 p2_46 = pSiSEnt->p2_46; 12349 p2_47 = pSiSEnt->p2_47; 12350 for(i = 0; i < 9; i++) { 12351 p1scaling[i] = pSiSEnt->scalingp1[i]; 12352 p4scaling[i] = pSiSEnt->scalingp4[i]; 12353 } 12354 p2scaling = &pSiSEnt->scalingp2[0]; 12355 } 12356#endif 12357 SISWaitRetraceCRT2(pScrn); 12358 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 12359 for(i = 0; i < 64; i++) { 12360 outSISIDXREG(SISPART2,(0xc0 + i),p2scaling[i]); 12361 } 12362 } 12363 for(i = 0; i < 9; i++) { 12364 outSISIDXREG(SISPART1,SiSScalingP1Regs[i],p1scaling[i]); 12365 } 12366 for(i = 0; i < 9; i++) { 12367 outSISIDXREG(SISPART4,SiSScalingP4Regs[i],p4scaling[i]); 12368 } 12369 12370 setSISIDXREG(SISPART2,0x0a,0x7f,(p2_0a & 0x80)); 12371 outSISIDXREG(SISPART2,0x2f,p2_2f); 12372 setSISIDXREG(SISPART2,0x30,0x3f,(p2_30 & 0xc0)); 12373 if(!(pSiS->VBFlags2 & VB2_301)) { 12374 setSISIDXREG(SISPART2,0x46,0x9f,(p2_46 & 0x60)); 12375 outSISIDXREG(SISPART2,0x47,p2_47); 12376 } 12377 12378 } else { 12379 12380 int realvde, myypos, watchdog = 32; 12381 unsigned short temp1, temp2, vgahde, vgaht, vgavt; 12382 int p1div = 1; 12383 ULong calctemp; 12384 12385 srindex += i; 12386 newvde = SiSTVVScale[srindex].ScaleVDE; 12387 realvde = SiSTVVScale[srindex].RealVDE; 12388 12389 if(vdediv == 1) p1div = 2; 12390 12391 if(!skipmoveup) { 12392 do { 12393 inSISIDXREG(SISPART2,0x01,temp); 12394 temp = vlimit - ((temp & 0x7f) / p1div); 12395 if((temp - (((newvde / vdediv) - 2) + 9)) > 0) break; 12396 myypos = pSiS->tvypos - 1; 12397#ifdef SISDUALHEAD 12398 if(pSiSEnt && pSiS->DualHeadMode) myypos = pSiSEnt->tvypos - 1; 12399#endif 12400 SiS_SetTVyposoffset(pScrn, myypos); 12401 } while(watchdog--); 12402 } 12403 12404 SISWaitRetraceCRT2(pScrn); 12405 12406 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 12407 SiS_CalcXTapScaler(pSiS->SiS_Pr, realvde, newvde, 4, FALSE); 12408 } 12409 12410 if(!(pSiS->VBFlags2 & VB2_301)) { 12411 temp = (newvde / vdediv) - 3; 12412 setSISIDXREG(SISPART2,0x46,0x9f,((temp & 0x0300) >> 3)); 12413 outSISIDXREG(SISPART2,0x47,(temp & 0xff)); 12414 } 12415 12416 inSISIDXREG(SISPART1,0x0a,temp1); 12417 inSISIDXREG(SISPART1,0x0c,temp2); 12418 vgahde = ((temp2 & 0xf0) << 4) | temp1; 12419 if(pSiS->VGAEngine == SIS_300_VGA) { 12420 vgahde -= 12; 12421 } else { 12422 vgahde -= 16; 12423 if(hdclk) vgahde <<= 1; 12424 } 12425 12426 vgaht = SiSTVVScale[srindex].reg[0]; 12427 temp1 = vgaht; 12428 if((pSiS->VGAEngine == SIS_315_VGA) && hdclk) temp1 >>= 1; 12429 temp1--; 12430 outSISIDXREG(SISPART1,0x08,(temp1 & 0xff)); 12431 setSISIDXREG(SISPART1,0x09,0x0f,((temp1 >> 4) & 0xf0)); 12432 12433 temp2 = (vgaht - vgahde) >> 2; 12434 if(pSiS->VGAEngine == SIS_300_VGA) { 12435 temp1 = vgahde + 12 + temp2; 12436 temp2 = temp1 + (temp2 << 1); 12437 } else { 12438 temp1 = vgahde; 12439 if(hdclk) { 12440 temp1 >>= 1; 12441 temp2 >>= 1; 12442 } 12443 temp2 >>= 1; 12444 temp1 = temp1 + 16 + temp2; 12445 temp2 = temp1 + temp2; 12446 } 12447 outSISIDXREG(SISPART1,0x0b,(temp1 & 0xff)); 12448 setSISIDXREG(SISPART1,0x0c,0xf0,((temp1 >> 8) & 0x0f)); 12449 outSISIDXREG(SISPART1,0x0d,(temp2 & 0xff)); 12450 12451 vgavt = SiSTVVScale[srindex].reg[1]; 12452 temp1 = vgavt - 1; 12453 if(pSiS->VGAEngine == SIS_315_VGA) temp1--; 12454 outSISIDXREG(SISPART1,0x0e,(temp1 & 0xff)); 12455 setSISIDXREG(SISPART1,0x12,0xf8,((temp1 >> 8 ) & 0x07)); 12456 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->ChipType >= SIS_661)) { 12457 temp1 = (vgavt + SiSTVVScale[srindex].RealVDE) >> 1; 12458 temp2 = ((vgavt - SiSTVVScale[srindex].RealVDE) >> 4) + temp1 + 1; 12459 } else { 12460 temp1 = (vgavt - SiSTVVScale[srindex].RealVDE) >> 2; 12461 temp2 = (temp1 < 4) ? 4 : temp1; 12462 temp1 += SiSTVVScale[srindex].RealVDE; 12463 temp2 = (temp2 >> 2) + temp1 + 1; 12464 } 12465 outSISIDXREG(SISPART1,0x10,(temp1 & 0xff)); 12466 setSISIDXREG(SISPART1,0x11,0x8f,((temp1 >> 4) & 0x70)); 12467 setSISIDXREG(SISPART1,0x11,0xf0,(temp2 & 0x0f)); 12468 12469 setSISIDXREG(SISPART2,0x0a,0x7f,((SiSTVVScale[srindex].reg[2] >> 8) & 0x80)); 12470 outSISIDXREG(SISPART2,0x2f,((newvde / vdediv) - 2)); 12471 setSISIDXREG(SISPART2,0x30,0x3f,((((newvde / vdediv) - 2) >> 2) & 0xc0)); 12472 12473 outSISIDXREG(SISPART4,0x13,(SiSTVVScale[srindex].reg[2] & 0xff)); 12474 outSISIDXREG(SISPART4,0x14,(SiSTVVScale[srindex].reg[3] & 0xff)); 12475 setSISIDXREG(SISPART4,0x15,0x7f,((SiSTVVScale[srindex].reg[3] >> 1) & 0x80)); 12476 12477 temp1 = vgaht - 1; 12478 outSISIDXREG(SISPART4,0x16,(temp1 & 0xff)); 12479 setSISIDXREG(SISPART4,0x15,0x87,((temp1 >> 5) & 0x78)); 12480 12481 temp1 = vgavt - 1; 12482 outSISIDXREG(SISPART4,0x17,(temp1 & 0xff)); 12483 setSISIDXREG(SISPART4,0x15,0xf8,((temp1 >> 8) & 0x07)); 12484 12485 outSISIDXREG(SISPART4,0x18,0x00); 12486 setSISIDXREG(SISPART4,0x19,0xf0,0x00); 12487 12488 inSISIDXREG(SISPART4,0x0e,temp1); 12489 if(is1080i) { 12490 if(!(temp1 & 0xe0)) newvde >>= 1; 12491 } 12492 12493 temp = 0x40; 12494 if(realvde <= newvde) temp = 0; 12495 else realvde -= newvde; 12496 12497 calctemp = (realvde * 256 * 1024) / newvde; 12498 if((realvde * 256 * 1024) % newvde) calctemp++; 12499 outSISIDXREG(SISPART4,0x1b,(calctemp & 0xff)); 12500 outSISIDXREG(SISPART4,0x1a,((calctemp >> 8) & 0xff)); 12501 setSISIDXREG(SISPART4,0x19,0x8f,(((calctemp >> 12) & 0x70) | temp)); 12502 } 12503 12504 } 12505 12506 } 12507} 12508 12509int SiS_GetTVyscale(ScrnInfoPtr pScrn) 12510{ 12511 SISPtr pSiS = SISPTR(pScrn); 12512#ifdef SISDUALHEAD 12513 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12514 12515 if(pSiSEnt && pSiS->DualHeadMode) 12516 return (int)pSiSEnt->tvyscale; 12517 else 12518#endif 12519 return (int)pSiS->tvyscale; 12520} 12521 12522void SiS_SetSISCRT1SaturationGain(ScrnInfoPtr pScrn, int val) 12523{ 12524 SISPtr pSiS = SISPTR(pScrn); 12525#ifdef SISDUALHEAD 12526 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12527#endif 12528 12529 pSiS->siscrt1satgain = val; 12530#ifdef SISDUALHEAD 12531 if(pSiSEnt) pSiSEnt->siscrt1satgain = val; 12532#endif 12533 12534 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_CRT1SATGAIN)) return; 12535 12536#ifdef UNLOCK_ALWAYS 12537 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12538#endif 12539 12540 if((val >= 0) && (val <= 7)) { 12541 setSISIDXREG(SISCR,0x53,0xE3, (val << 2)); 12542 } 12543} 12544 12545int SiS_GetSISCRT1SaturationGain(ScrnInfoPtr pScrn) 12546{ 12547 SISPtr pSiS = SISPTR(pScrn); 12548 int result = pSiS->siscrt1satgain; 12549 UChar temp; 12550#ifdef SISDUALHEAD 12551 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12552 12553 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->siscrt1satgain; 12554#endif 12555 12556 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_CRT1SATGAIN)) return result; 12557 12558#ifdef UNLOCK_ALWAYS 12559 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12560#endif 12561 inSISIDXREG(SISCR, 0x53, temp); 12562 return (int)((temp >> 2) & 0x07); 12563} 12564 12565/* Calc dotclock from registers */ 12566static int 12567SiSGetClockFromRegs(UChar sr2b, UChar sr2c) 12568{ 12569 float num, denum, postscalar, divider; 12570 int myclock; 12571 12572 divider = (sr2b & 0x80) ? 2.0 : 1.0; 12573 postscalar = (sr2c & 0x80) ? 12574 ( (((sr2c >> 5) & 0x03) == 0x02) ? 6.0 : 8.0 ) : 12575 ( ((sr2c >> 5) & 0x03) + 1.0 ); 12576 num = (sr2b & 0x7f) + 1.0; 12577 denum = (sr2c & 0x1f) + 1.0; 12578 myclock = (int)((14318 * (divider / postscalar) * (num / denum)) / 1000); 12579 return myclock; 12580} 12581 12582#ifdef SISDUALHEAD 12583static void 12584SiS_SetDHFlags(SISPtr pSiS, unsigned int misc, unsigned int sd2) 12585{ 12586 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12587 12588 if(pSiS->DualHeadMode) { 12589 if(pSiSEnt->pScrn_1) { 12590 SISPTR(pSiSEnt->pScrn_1)->MiscFlags |= misc; 12591 SISPTR(pSiSEnt->pScrn_1)->SiS_SD2_Flags |= sd2; 12592 } 12593 if(pSiSEnt->pScrn_2) { 12594 SISPTR(pSiSEnt->pScrn_2)->MiscFlags |= misc; 12595 SISPTR(pSiSEnt->pScrn_2)->SiS_SD2_Flags |= sd2; 12596 } 12597 } 12598} 12599#endif 12600 12601/* PostSetMode: 12602 * -) Disable CRT1 for saving bandwidth. This doesn't work with VESA; 12603 * VESA uses the bridge in SlaveMode and switching CRT1 off while 12604 * the bridge is in SlaveMode not that clever... 12605 * -) Check if overlay can be used (depending on dotclock) 12606 * -) Check if Panel Scaler is active on LVDS for overlay re-scaling 12607 * -) Save TV registers for further processing 12608 * -) Apply TV settings 12609 */ 12610static void 12611SiSPostSetMode(ScrnInfoPtr pScrn, SISRegPtr sisReg) 12612{ 12613 SISPtr pSiS = SISPTR(pScrn); 12614#ifdef SISDUALHEAD 12615 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12616#endif 12617 UChar usScratchCR17, sr2b, sr2c, tmpreg; 12618 int myclock1, myclock2, mycoldepth1, mycoldepth2, temp; 12619 Bool flag = FALSE; 12620 Bool doit = TRUE; 12621 Bool IsInSlaveMode; 12622 12623#ifdef TWDEBUG 12624 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 12625 "CRT1off is %d\n", pSiS->CRT1off); 12626#endif 12627 pSiS->CRT1isoff = pSiS->CRT1off; 12628 12629#ifdef UNLOCK_ALWAYS 12630 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12631#endif 12632 12633 SiSFixupSR11(pScrn); 12634 12635 IsInSlaveMode = SiSBridgeIsInSlaveMode(pScrn); 12636 12637 if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE)) { 12638 12639 if(pSiS->VBFlags != pSiS->VBFlags_backup) { 12640 pSiS->VBFlags = pSiS->VBFlags_backup; 12641 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 12642 "VBFlags restored to %0x\n", pSiS->VBFlags); 12643 } 12644 12645 /* -) We can't switch off CRT1 if bridge is in SlaveMode. 12646 * -) If we change to a SlaveMode-Mode (like 512x384), we 12647 * need to adapt VBFlags for eg. Xv. 12648 */ 12649#ifdef SISDUALHEAD 12650 if(!pSiS->DualHeadMode) { 12651#endif 12652 if(IsInSlaveMode) { 12653 doit = FALSE; 12654 temp = pSiS->VBFlags; 12655 pSiS->VBFlags &= (~VB_DISPMODE_SINGLE); 12656 pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_DISP1); 12657 if(temp != pSiS->VBFlags) { 12658 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 12659 "VBFlags changed to 0x%0x\n", pSiS->VBFlags); 12660 } 12661 } 12662#ifdef SISDUALHEAD 12663 } 12664#endif 12665 12666 if(pSiS->VGAEngine == SIS_315_VGA) { 12667 12668 if((pSiS->CRT1off) && (doit)) { 12669 orSISIDXREG(SISCR,pSiS->myCR63,0x40); 12670 orSISIDXREG(SISSR,0x1f,0xc0); 12671 andSISIDXREG(SISSR,0x07,~0x10); 12672 andSISIDXREG(SISSR,0x06,0xe2); 12673 andSISIDXREG(SISSR,0x31,0xcf); 12674 outSISIDXREG(SISSR,0x2b,0x1b); 12675 outSISIDXREG(SISSR,0x2c,0xe1); 12676 outSISIDXREG(SISSR,0x2d,0x01); 12677 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 12678 usleep(10000); 12679 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 12680 } else { 12681 andSISIDXREG(SISCR,pSiS->myCR63,0xBF); 12682 andSISIDXREG(SISSR,0x1f,0x3f); 12683 orSISIDXREG(SISSR,0x07,0x10); 12684 } 12685 12686 } else { 12687 12688 if(doit) { 12689 inSISIDXREG(SISCR, 0x17, usScratchCR17); 12690 if(pSiS->CRT1off) { 12691 if(usScratchCR17 & 0x80) { 12692 flag = TRUE; 12693 usScratchCR17 &= ~0x80; 12694 } 12695 orSISIDXREG(SISSR,0x1f,0xc0); 12696 } else { 12697 if(!(usScratchCR17 & 0x80)) { 12698 flag = TRUE; 12699 usScratchCR17 |= 0x80; 12700 } 12701 andSISIDXREG(SISSR,0x1f,0x3f); 12702 } 12703 /* Reset only if status changed */ 12704 if(flag) { 12705 outSISIDXREG(SISCR, 0x17, usScratchCR17); 12706 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 12707 usleep(10000); 12708 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 12709 } 12710 } 12711 } 12712 12713 } 12714 12715 /* Set bridge to "disable CRT2" mode if CRT2 is disabled, LCD-A is enabled */ 12716 /* (Not needed for CRT1=VGA since CRT2 will really be disabled then) */ 12717#ifdef SISDUALHEAD 12718 if(!pSiS->DualHeadMode) { 12719#endif 12720 if((pSiS->VGAEngine == SIS_315_VGA) && (pSiS->VBFlags2 & VB2_SISLCDABRIDGE)) { 12721 if((!pSiS->UseVESA) && (!(pSiS->VBFlags & CRT2_ENABLE)) && (pSiS->VBFlags & CRT1_LCDA)) { 12722 if(!IsInSlaveMode) { 12723 andSISIDXREG(SISPART4,0x0d,~0x07); 12724 } 12725 } 12726 } 12727#ifdef SISDUALHEAD 12728 } 12729#endif 12730 12731 /* Reset flags */ 12732 pSiS->MiscFlags &= ~( MISC_CRT1OVERLAY | 12733 MISC_CRT2OVERLAY | 12734 MISC_CRT1OVERLAYGAMMA | 12735 MISC_SIS760ONEOVERLAY | 12736 MISC_PANELLINKSCALER | 12737 MISC_STNMODE | 12738 MISC_TVNTSC1024); 12739 12740 pSiS->SiS_SD2_Flags &= ~SiS_SD2_SIS760ONEOVL; 12741 12742#ifdef SISDUALHEAD 12743 if(pSiS->DualHeadMode) { 12744 if(pSiSEnt->pScrn_1) { 12745 SISPTR(pSiSEnt->pScrn_1)->MiscFlags &= ~(MISC_SIS760ONEOVERLAY | 12746 MISC_CRT1OVERLAY | 12747 MISC_CRT2OVERLAY | 12748 MISC_CRT1OVERLAYGAMMA | 12749 MISC_PANELLINKSCALER | 12750 MISC_STNMODE | 12751 MISC_TVNTSC1024); 12752 SISPTR(pSiSEnt->pScrn_1)->SiS_SD2_Flags &= ~SiS_SD2_SIS760ONEOVL; 12753 } 12754 if(pSiSEnt->pScrn_2) { 12755 SISPTR(pSiSEnt->pScrn_2)->MiscFlags &= ~(MISC_SIS760ONEOVERLAY | 12756 MISC_CRT1OVERLAY | 12757 MISC_CRT2OVERLAY | 12758 MISC_CRT1OVERLAYGAMMA | 12759 MISC_PANELLINKSCALER | 12760 MISC_STNMODE | 12761 MISC_TVNTSC1024); 12762 SISPTR(pSiSEnt->pScrn_2)->SiS_SD2_Flags &= ~SiS_SD2_SIS760ONEOVL; 12763 } 12764 } 12765#endif 12766 12767 /* Determine if the video overlay can be used */ 12768 if(!pSiS->NoXvideo) { 12769 12770 int clklimit1=0, clklimit2=0, clklimitg=0; 12771 Bool OverlayHandled = FALSE; 12772 12773 inSISIDXREG(SISSR,0x2b,sr2b); 12774 inSISIDXREG(SISSR,0x2c,sr2c); 12775 myclock1 = myclock2 = SiSGetClockFromRegs(sr2b, sr2c); 12776 inSISIDXREG(SISSR,0x06,tmpreg); 12777 switch((tmpreg & 0x1c) >> 2) { 12778 case 0: mycoldepth1 = 1; break; 12779 case 1: 12780 case 2: mycoldepth1 = 2; break; 12781 default: mycoldepth1 = 4; 12782 } 12783 mycoldepth2 = mycoldepth1; 12784 12785 if((!IsInSlaveMode) && (pSiS->VBFlags & CRT2_ENABLE)) { 12786 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 12787 inSISIDXREG(SISPART4,0x0a,sr2b); 12788 inSISIDXREG(SISPART4,0x0b,sr2c); 12789 } else { 12790 inSISIDXREG(SISSR,0x2e,sr2b); 12791 inSISIDXREG(SISSR,0x2f,sr2c); 12792 } 12793 myclock2 = SiSGetClockFromRegs(sr2b, sr2c); 12794 inSISIDXREG(SISPART1,0x00,tmpreg); 12795 tmpreg &= 0x0f; 12796 switch(tmpreg) { 12797 case 8: mycoldepth2 = 1; break; 12798 case 4: 12799 case 2: mycoldepth2 = 2; break; 12800 default: mycoldepth2 = 4; 12801 } 12802 } 12803 12804 switch(pSiS->ChipType) { 12805 12806 case SIS_300: 12807 case SIS_540: 12808 case SIS_630: 12809 case SIS_730: 12810 clklimit1 = clklimit2 = clklimitg = 150; 12811 break; 12812 12813 case SIS_550: 12814 case SIS_650: 12815 case SIS_740: 12816 clklimit1 = clklimit2 = 175; /* verified for 65x */ 12817 clklimitg = 166; /* ? */ 12818 break; 12819 12820 case SIS_661: 12821 case SIS_741: 12822 clklimit1 = clklimit2 = 190; /* ? */ 12823 clklimitg = 180; /* ? */ 12824 break; 12825 12826 case SIS_760: 12827 case SIS_761: 12828 clklimit1 = clklimit2 = 190; /* ? */ 12829 if(pSiS->ChipFlags & SiSCF_760LFB) { /* LFB only or hybrid */ 12830 clklimit1 = clklimit2 = 220; /* ? */ 12831 } 12832 clklimitg = 200; /* ? */ 12833 12834 if(pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORT760OO) { /* UMA only */ 12835 12836 Bool OnlyOne = FALSE, NoOverlay = FALSE; 12837 int dotclocksum = 0; 12838 12839 if(pSiS->VBFlags & DISPTYPE_CRT1) dotclocksum += myclock1; 12840 if((!IsInSlaveMode) && (pSiS->VBFlags & CRT2_ENABLE)) dotclocksum += myclock2; 12841 12842 /* TODO: Find out under what circumstances only one 12843 * overlay is usable in UMA-only mode. 12844 * This is not entirely accurate; the overlay 12845 * scaler also requires some time, so even though 12846 * the dotclocks are below these values, some 12847 * distortions in the overlay may occure. 12848 * Solution: Don't use a 760 with shared memory. 12849 */ 12850 if( (pSiS->VBFlags & DISPTYPE_CRT1) && 12851 (pSiS->VBFlags & CRT2_ENABLE) && 12852 (mycoldepth1 != mycoldepth2) ) { 12853 12854 /* 0. If coldepths are different (only possible in dual head mode), 12855 * I have no idea to calculate the limits; hence, allow only one 12856 * overlay in all cases. 12857 */ 12858 OnlyOne = TRUE; 12859 12860 } else if(pSiS->MemClock < 150000) { 12861 12862 /* 1. MCLK <150: If someone seriously considers using such 12863 * slow RAM, so be it. Only one overlay in call cases. 12864 */ 12865 OnlyOne = TRUE; 12866 12867 } else if(pSiS->MemClock < 170000) { 12868 12869 /* 2. MCLK 166 */ 12870 switch(pSiS->CurrentLayout.bitsPerPixel) { 12871 case 32: if(dotclocksum > 133) OnlyOne = TRUE; /* One overlay; verified */ 12872 if(dotclocksum > 180) NoOverlay = TRUE; /* No overlay; verified */ 12873 break; 12874 case 16: if(dotclocksum > 175) OnlyOne = TRUE; /* One overlay; verified */ 12875 if(dotclocksum > 260) NoOverlay = TRUE;; /* No overlay; FIXME */ 12876 break; 12877 } 12878 12879 } else if(pSiS->MemClock < 210000) { 12880 12881 /* 3. MCLK 200 */ 12882 switch(pSiS->CurrentLayout.bitsPerPixel) { 12883 case 32: if(dotclocksum > 160) OnlyOne = TRUE; /* One overlay; FIXME */ 12884 if(dotclocksum > 216) NoOverlay = TRUE;; /* No overlay; FIXME */ 12885 break; 12886 case 16: if(dotclocksum > 210) OnlyOne = TRUE; /* One overlay; FIXME */ 12887 if(dotclocksum > 312) NoOverlay = TRUE;; /* No overlay; FIXME */ 12888 break; 12889 } 12890 12891 } 12892 12893 if(OnlyOne || NoOverlay) { 12894 12895 ULong tmpflags = 0; 12896 12897 if(!NoOverlay) { 12898 if(myclock1 <= clklimit1) tmpflags |= MISC_CRT1OVERLAY; 12899 if(myclock2 <= clklimit2) tmpflags |= MISC_CRT2OVERLAY; 12900 if(myclock1 <= clklimitg) tmpflags |= MISC_CRT1OVERLAYGAMMA; 12901 pSiS->MiscFlags |= tmpflags; 12902 } 12903 pSiS->MiscFlags |= MISC_SIS760ONEOVERLAY; 12904 pSiS->SiS_SD2_Flags |= SiS_SD2_SIS760ONEOVL; 12905#ifdef SISDUALHEAD 12906 SiS_SetDHFlags(pSiS, (tmpflags | MISC_SIS760ONEOVERLAY), SiS_SD2_SIS760ONEOVL); 12907#endif 12908 OverlayHandled = TRUE; 12909 } 12910 12911 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 12912 "SiS76x/UMA: %s video overlay(s) available in current mode\n", 12913 NoOverlay ? "no" : ((pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) ? "one" : "two")); 12914 12915#ifdef TWDEBUG 12916 xf86DrvMsg(0, 0, "SiS760: Memclock %d, c1 %d/%d c2 %d/%d, sum %d / %x\n", 12917 pSiS->MemClock, myclock1, mycoldepth1, 12918 myclock2, mycoldepth2, dotclocksum, pSiS->SiS_SD2_Flags); 12919#endif 12920 } 12921 break; 12922 12923 case SIS_660: 12924 clklimit1 = clklimit2 = 200; /* ? */ 12925 if(pSiS->ChipFlags & SiSCF_760LFB) { /* LFB only */ 12926 clklimit1 = clklimit2 = 220; 12927 } 12928 clklimitg = 200; /* ? */ 12929 break; 12930 12931 case SIS_315H: 12932 case SIS_315: 12933 case SIS_315PRO: 12934 case SIS_330: 12935 clklimit1 = clklimit2 = 180; /* ? */ 12936 clklimitg = 166; /* ? */ 12937 break; 12938 12939 case SIS_340: /* ? */ 12940 case XGI_20: 12941 case XGI_40: 12942 clklimit1 = clklimit2 = 240; /* ? */ 12943 clklimitg = 200; /* ? */ 12944 break; 12945 } 12946 12947 if(!OverlayHandled) { 12948 ULong tmpflags = 0; 12949 if(myclock1 <= clklimit1) tmpflags |= MISC_CRT1OVERLAY; 12950 if(myclock2 <= clklimit2) tmpflags |= MISC_CRT2OVERLAY; 12951 if(myclock1 <= clklimitg) tmpflags |= MISC_CRT1OVERLAYGAMMA; 12952 pSiS->MiscFlags |= tmpflags; 12953#ifdef SISDUALHEAD 12954 SiS_SetDHFlags(pSiS, tmpflags, 0); 12955#endif 12956 if(!(pSiS->MiscFlags & MISC_CRT1OVERLAY)) { 12957#ifdef SISDUALHEAD 12958 if((!pSiS->DualHeadMode) || (pSiS->SecondHead)) 12959#endif 12960 xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, 3, 12961 "Current dotclock (%dMhz) too high for video overlay on CRT1\n", 12962 myclock1); 12963 } 12964 if((pSiS->VBFlags & CRT2_ENABLE) && (!(pSiS->MiscFlags & MISC_CRT2OVERLAY))) { 12965#ifdef SISDUALHEAD 12966 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) 12967#endif 12968 xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, 3, 12969 "Current dotclock (%dMhz) too high for video overlay on CRT2\n", 12970 myclock2); 12971 } 12972 } 12973 12974 } 12975 12976 /* Determine if the Panel Link scaler is active */ 12977 12978 if(pSiS->VBFlags & (CRT2_LCD | CRT1_LCDA)) { 12979 ULong tmpflags = 0; 12980 if(pSiS->VGAEngine == SIS_300_VGA) { 12981 if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) { 12982 inSISIDXREG(SISPART1,0x1e,tmpreg); 12983 tmpreg &= 0x3f; 12984 if(tmpreg) tmpflags |= MISC_PANELLINKSCALER; 12985 } 12986 } else { 12987 if((pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) || (pSiS->VBFlags & CRT1_LCDA)) { 12988 inSISIDXREG(SISPART1,0x35,tmpreg); 12989 tmpreg &= 0x04; 12990 if(!tmpreg) tmpflags |= MISC_PANELLINKSCALER; 12991 } 12992 } 12993 pSiS->MiscFlags |= tmpflags; 12994#ifdef SISDUALHEAD 12995 SiS_SetDHFlags(pSiS, tmpflags, 0); 12996#endif 12997 } 12998 12999 /* Determine if STN is active */ 13000 if(pSiS->ChipType == SIS_550) { 13001 if((pSiS->VBFlags & CRT2_LCD) && (pSiS->FSTN || pSiS->DSTN)) { 13002 inSISIDXREG(SISCR,0x34,tmpreg); 13003 tmpreg &= 0x7f; 13004 if(tmpreg == 0x5a || tmpreg == 0x5b) { 13005 pSiS->MiscFlags |= MISC_STNMODE; 13006#ifdef SISDUALHEAD 13007 SiS_SetDHFlags(pSiS, MISC_STNMODE, 0); 13008#endif 13009 } 13010 } 13011 } 13012 13013 /* Determine if our very special TV mode is active */ 13014 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && (pSiS->VBFlags & CRT2_TV) && (!(pSiS->VBFlags & TV_HIVISION))) { 13015 if( ((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR525I)) || 13016 ((!(pSiS->VBFlags & TV_YPBPR)) && (pSiS->VBFlags & (TV_NTSC | TV_PALM))) ) { 13017 inSISIDXREG(SISCR,0x34,tmpreg); 13018 tmpreg &= 0x7f; 13019 if((tmpreg == 0x64) || (tmpreg == 0x4a) || (tmpreg == 0x38)) { 13020 pSiS->MiscFlags |= MISC_TVNTSC1024; 13021#ifdef SISDUALHEAD 13022 SiS_SetDHFlags(pSiS, MISC_TVNTSC1024, 0); 13023#endif 13024 } 13025 } 13026 } 13027 13028 if(pSiS->VGAEngine == SIS_315_VGA) { 13029 int i; 13030#ifdef SISVRAMQ 13031 /* Re-Enable and reset command queue */ 13032 SiSEnableTurboQueue(pScrn); 13033#endif 13034 /* Get HWCursor register contents for backup */ 13035 for(i = 0; i < 16; i++) { 13036 pSiS->HWCursorBackup[i] = SIS_MMIO_IN32(pSiS->IOBase, 0x8500 + (i << 2)); 13037 } 13038 if(pSiS->ChipType >= SIS_330) { 13039 /* Enable HWCursor protection (Y pos as trigger) */ 13040 andSISIDXREG(SISCR, 0x5b, ~0x30); 13041 } 13042 } 13043 13044 /* Re-initialize accelerator engine */ 13045 /* (We are sync'ed here) */ 13046 if(!pSiS->NoAccel) { 13047 if(pSiS->InitAccel) { 13048 (pSiS->InitAccel)(pScrn); 13049 } 13050 } 13051 13052 /* Set display device gamma (for SISCTRL) */ 13053 if(pSiS->VBFlags & CRT1_LCDA) 13054 pSiS->CRT1MonGamma = pSiS->CRT2LCDMonitorGamma; 13055 else 13056 pSiS->CRT1MonGamma = pSiS->CRT1VGAMonitorGamma; 13057 13058 if(pSiS->VBFlags & CRT2_LCD) 13059 pSiS->CRT2MonGamma = pSiS->CRT2LCDMonitorGamma; 13060 else if(pSiS->VBFlags & CRT2_TV) { 13061 if(pSiS->VBFlags & TV_YPBPR) 13062 pSiS->CRT2MonGamma = 2200; /* */ 13063 else if(pSiS->VBFlags & TV_HIVISION) 13064 pSiS->CRT2MonGamma = 2200; /* ? */ 13065 else if(pSiS->VBFlags & TV_NTSC) 13066 pSiS->CRT2MonGamma = 2200; /* NTSC */ 13067 else 13068 pSiS->CRT2MonGamma = 2800; /* All PAL modes? */ 13069 } else if(pSiS->VBFlags & CRT2_VGA) 13070 pSiS->CRT2MonGamma = pSiS->CRT2VGAMonitorGamma; 13071 else 13072 pSiS->CRT2MonGamma = 0; /* Unknown */ 13073 13074 /* Reset XV display properties (such as number of overlays, etc) */ 13075 /* (And copy monitor gamma) */ 13076#ifdef SISDUALHEAD 13077 if(pSiS->DualHeadMode) { 13078 if(pSiSEnt->pScrn_1) { 13079 if(SISPTR(pSiSEnt->pScrn_1)->ResetXvDisplay) { 13080 (SISPTR(pSiSEnt->pScrn_1)->ResetXvDisplay)(pSiSEnt->pScrn_1); 13081 } 13082 SISPTR(pSiSEnt->pScrn_1)->CRT1MonGamma = pSiS->CRT1MonGamma; 13083 SISPTR(pSiSEnt->pScrn_1)->CRT2MonGamma = pSiS->CRT2MonGamma; 13084 } 13085 if(pSiSEnt->pScrn_2) { 13086 if(SISPTR(pSiSEnt->pScrn_2)->ResetXvDisplay) { 13087 (SISPTR(pSiSEnt->pScrn_1)->ResetXvDisplay)(pSiSEnt->pScrn_2); 13088 } 13089 SISPTR(pSiSEnt->pScrn_2)->CRT1MonGamma = pSiS->CRT1MonGamma; 13090 SISPTR(pSiSEnt->pScrn_2)->CRT2MonGamma = pSiS->CRT2MonGamma; 13091 } 13092 } else { 13093#endif 13094 if(pSiS->ResetXvDisplay) { 13095 (pSiS->ResetXvDisplay)(pScrn); 13096 } 13097#ifdef SISDUALHEAD 13098 } 13099#endif 13100 13101 /* Reset XV gamma correction */ 13102 if(pSiS->ResetXvGamma) { 13103 (pSiS->ResetXvGamma)(pScrn); 13104 } 13105 13106 /* Reset various display parameters */ 13107 { 13108 int val = pSiS->siscrt1satgain; 13109#ifdef SISDUALHEAD 13110 if(pSiS->DualHeadMode && pSiSEnt) val = pSiSEnt->siscrt1satgain; 13111#endif 13112 SiS_SetSISCRT1SaturationGain(pScrn, val); 13113 } 13114 13115 /* Apply TV settings given by options 13116 Do this even in DualHeadMode: 13117 - if this is called by SetModeCRT1, CRT2 mode has been reset by SetModeCRT1 13118 - if this is called by SetModeCRT2, CRT2 mode has changed (duh!) 13119 -> Hence, in both cases, the settings must be re-applied. 13120 */ 13121 13122 if(pSiS->VBFlags & CRT2_TV) { 13123 int val; 13124 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 13125 int mychtvlumabandwidthcvbs = pSiS->chtvlumabandwidthcvbs; 13126 int mychtvlumabandwidthsvideo = pSiS->chtvlumabandwidthsvideo; 13127 int mychtvlumaflickerfilter = pSiS->chtvlumaflickerfilter; 13128 int mychtvchromabandwidth = pSiS->chtvchromabandwidth; 13129 int mychtvchromaflickerfilter = pSiS->chtvchromaflickerfilter; 13130 int mychtvcvbscolor = pSiS->chtvcvbscolor; 13131 int mychtvtextenhance = pSiS->chtvtextenhance; 13132 int mychtvcontrast = pSiS->chtvcontrast; 13133 int mytvxpos = pSiS->tvxpos; 13134 int mytvypos = pSiS->tvypos; 13135#ifdef SISDUALHEAD 13136 if(pSiSEnt && pSiS->DualHeadMode) { 13137 mychtvlumabandwidthcvbs = pSiSEnt->chtvlumabandwidthcvbs; 13138 mychtvlumabandwidthsvideo = pSiSEnt->chtvlumabandwidthsvideo; 13139 mychtvlumaflickerfilter = pSiSEnt->chtvlumaflickerfilter; 13140 mychtvchromabandwidth = pSiSEnt->chtvchromabandwidth; 13141 mychtvchromaflickerfilter = pSiSEnt->chtvchromaflickerfilter; 13142 mychtvcvbscolor = pSiSEnt->chtvcvbscolor; 13143 mychtvtextenhance = pSiSEnt->chtvtextenhance; 13144 mychtvcontrast = pSiSEnt->chtvcontrast; 13145 mytvxpos = pSiSEnt->tvxpos; 13146 mytvypos = pSiSEnt->tvypos; 13147 } 13148#endif 13149 if((val = mychtvlumabandwidthcvbs) != -1) { 13150 SiS_SetCHTVlumabandwidthcvbs(pScrn, val); 13151 } 13152 if((val = mychtvlumabandwidthsvideo) != -1) { 13153 SiS_SetCHTVlumabandwidthsvideo(pScrn, val); 13154 } 13155 if((val = mychtvlumaflickerfilter) != -1) { 13156 SiS_SetCHTVlumaflickerfilter(pScrn, val); 13157 } 13158 if((val = mychtvchromabandwidth) != -1) { 13159 SiS_SetCHTVchromabandwidth(pScrn, val); 13160 } 13161 if((val = mychtvchromaflickerfilter) != -1) { 13162 SiS_SetCHTVchromaflickerfilter(pScrn, val); 13163 } 13164 if((val = mychtvcvbscolor) != -1) { 13165 SiS_SetCHTVcvbscolor(pScrn, val); 13166 } 13167 if((val = mychtvtextenhance) != -1) { 13168 SiS_SetCHTVtextenhance(pScrn, val); 13169 } 13170 if((val = mychtvcontrast) != -1) { 13171 SiS_SetCHTVcontrast(pScrn, val); 13172 } 13173 /* Backup default TV position registers */ 13174 switch(pSiS->ChrontelType) { 13175 case CHRONTEL_700x: 13176 pSiS->tvx = SiS_GetCH700x(pSiS->SiS_Pr, 0x0a); 13177 pSiS->tvx |= (((SiS_GetCH700x(pSiS->SiS_Pr, 0x08) & 0x02) >> 1) << 8); 13178 pSiS->tvy = SiS_GetCH700x(pSiS->SiS_Pr, 0x0b); 13179 pSiS->tvy |= ((SiS_GetCH700x(pSiS->SiS_Pr, 0x08) & 0x01) << 8); 13180#ifdef SISDUALHEAD 13181 if(pSiSEnt) { 13182 pSiSEnt->tvx = pSiS->tvx; 13183 pSiSEnt->tvy = pSiS->tvy; 13184 } 13185#endif 13186 break; 13187 case CHRONTEL_701x: 13188 /* Not supported by hardware */ 13189 break; 13190 } 13191 if((val = mytvxpos) != 0) { 13192 SiS_SetTVxposoffset(pScrn, val); 13193 } 13194 if((val = mytvypos) != 0) { 13195 SiS_SetTVyposoffset(pScrn, val); 13196 } 13197 } 13198 if(pSiS->VBFlags2 & VB2_301) { 13199 int mysistvedgeenhance = pSiS->sistvedgeenhance; 13200#ifdef SISDUALHEAD 13201 if(pSiSEnt && pSiS->DualHeadMode) { 13202 mysistvedgeenhance = pSiSEnt->sistvedgeenhance; 13203 } 13204#endif 13205 if((val = mysistvedgeenhance) != -1) { 13206 SiS_SetSISTVedgeenhance(pScrn, val); 13207 } 13208 } 13209 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 13210 int mysistvantiflicker = pSiS->sistvantiflicker; 13211 int mysistvsaturation = pSiS->sistvsaturation; 13212 int mysistvcolcalibf = pSiS->sistvcolcalibf; 13213 int mysistvcolcalibc = pSiS->sistvcolcalibc; 13214 int mysistvcfilter = pSiS->sistvcfilter; 13215 int mysistvyfilter = pSiS->sistvyfilter; 13216 int mytvxpos = pSiS->tvxpos; 13217 int mytvypos = pSiS->tvypos; 13218 int mytvxscale = pSiS->tvxscale; 13219 int mytvyscale = pSiS->tvyscale; 13220 int i; 13221 ULong cbase; 13222 UChar ctemp; 13223#ifdef SISDUALHEAD 13224 if(pSiSEnt && pSiS->DualHeadMode) { 13225 mysistvantiflicker = pSiSEnt->sistvantiflicker; 13226 mysistvsaturation = pSiSEnt->sistvsaturation; 13227 mysistvcolcalibf = pSiSEnt->sistvcolcalibf; 13228 mysistvcolcalibc = pSiSEnt->sistvcolcalibc; 13229 mysistvcfilter = pSiSEnt->sistvcfilter; 13230 mysistvyfilter = pSiSEnt->sistvyfilter; 13231 mytvxpos = pSiSEnt->tvxpos; 13232 mytvypos = pSiSEnt->tvypos; 13233 mytvxscale = pSiSEnt->tvxscale; 13234 mytvyscale = pSiSEnt->tvyscale; 13235 } 13236#endif 13237 /* Backup default TV position, scale and colcalib registers */ 13238 inSISIDXREG(SISPART2,0x1f,pSiS->p2_1f); 13239 inSISIDXREG(SISPART2,0x20,pSiS->p2_20); 13240 inSISIDXREG(SISPART2,0x2b,pSiS->p2_2b); 13241 inSISIDXREG(SISPART2,0x42,pSiS->p2_42); 13242 inSISIDXREG(SISPART2,0x43,pSiS->p2_43); 13243 inSISIDXREG(SISPART2,0x01,pSiS->p2_01); 13244 inSISIDXREG(SISPART2,0x02,pSiS->p2_02); 13245 inSISIDXREG(SISPART2,0x44,pSiS->p2_44); 13246 inSISIDXREG(SISPART2,0x45,pSiS->p2_45); 13247 if(!(pSiS->VBFlags2 & VB2_301)) { 13248 inSISIDXREG(SISPART2,0x46,pSiS->p2_46); 13249 } else { 13250 pSiS->p2_46 = 0; 13251 } 13252 inSISIDXREG(SISPART2,0x0a,pSiS->p2_0a); 13253 inSISIDXREG(SISPART2,0x31,cbase); 13254 cbase = (cbase & 0x7f) << 8; 13255 inSISIDXREG(SISPART2,0x32,ctemp); 13256 cbase = (cbase | ctemp) << 8; 13257 inSISIDXREG(SISPART2,0x33,ctemp); 13258 cbase = (cbase | ctemp) << 8; 13259 inSISIDXREG(SISPART2,0x34,ctemp); 13260 pSiS->sistvccbase = (cbase | ctemp); 13261 inSISIDXREG(SISPART2,0x35,pSiS->p2_35); 13262 inSISIDXREG(SISPART2,0x36,pSiS->p2_36); 13263 inSISIDXREG(SISPART2,0x37,pSiS->p2_37); 13264 inSISIDXREG(SISPART2,0x38,pSiS->p2_38); 13265 if(!(pSiS->VBFlags2 & VB2_301)) { 13266 inSISIDXREG(SISPART2,0x47,pSiS->p2_47); 13267 inSISIDXREG(SISPART2,0x48,pSiS->p2_48); 13268 inSISIDXREG(SISPART2,0x49,pSiS->p2_49); 13269 inSISIDXREG(SISPART2,0x4a,pSiS->p2_4a); 13270 } 13271 inSISIDXREG(SISPART2,0x2f,pSiS->p2_2f); 13272 inSISIDXREG(SISPART2,0x30,pSiS->p2_30); 13273 for(i=0; i<9; i++) { 13274 inSISIDXREG(SISPART1,SiSScalingP1Regs[i],pSiS->scalingp1[i]); 13275 } 13276 for(i=0; i<9; i++) { 13277 inSISIDXREG(SISPART4,SiSScalingP4Regs[i],pSiS->scalingp4[i]); 13278 } 13279 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 13280 for(i=0; i<64; i++) { 13281 inSISIDXREG(SISPART2,(0xc0 + i),pSiS->scalingp2[i]); 13282 } 13283 } 13284#ifdef SISDUALHEAD 13285 if(pSiSEnt) { 13286 pSiSEnt->p2_1f = pSiS->p2_1f; pSiSEnt->p2_20 = pSiS->p2_20; 13287 pSiSEnt->p2_42 = pSiS->p2_42; pSiSEnt->p2_43 = pSiS->p2_43; 13288 pSiSEnt->p2_2b = pSiS->p2_2b; 13289 pSiSEnt->p2_01 = pSiS->p2_01; pSiSEnt->p2_02 = pSiS->p2_02; 13290 pSiSEnt->p2_44 = pSiS->p2_44; pSiSEnt->p2_45 = pSiS->p2_45; 13291 pSiSEnt->p2_46 = pSiS->p2_46; pSiSEnt->p2_0a = pSiS->p2_0a; 13292 pSiSEnt->sistvccbase = pSiS->sistvccbase; 13293 pSiSEnt->p2_35 = pSiS->p2_35; pSiSEnt->p2_36 = pSiS->p2_36; 13294 pSiSEnt->p2_37 = pSiS->p2_37; pSiSEnt->p2_38 = pSiS->p2_38; 13295 pSiSEnt->p2_48 = pSiS->p2_48; pSiSEnt->p2_49 = pSiS->p2_49; 13296 pSiSEnt->p2_4a = pSiS->p2_4a; pSiSEnt->p2_2f = pSiS->p2_2f; 13297 pSiSEnt->p2_30 = pSiS->p2_30; pSiSEnt->p2_47 = pSiS->p2_47; 13298 for(i=0; i<9; i++) { 13299 pSiSEnt->scalingp1[i] = pSiS->scalingp1[i]; 13300 } 13301 for(i=0; i<9; i++) { 13302 pSiSEnt->scalingp4[i] = pSiS->scalingp4[i]; 13303 } 13304 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 13305 for(i=0; i<64; i++) { 13306 pSiSEnt->scalingp2[i] = pSiS->scalingp2[i]; 13307 } 13308 } 13309 } 13310#endif 13311 if((val = mysistvantiflicker) != -1) { 13312 SiS_SetSISTVantiflicker(pScrn, val); 13313 } 13314 if((val = mysistvsaturation) != -1) { 13315 SiS_SetSISTVsaturation(pScrn, val); 13316 } 13317 if((val = mysistvcfilter) != -1) { 13318 SiS_SetSISTVcfilter(pScrn, val); 13319 } 13320 if((val = mysistvyfilter) != 1) { 13321 SiS_SetSISTVyfilter(pScrn, val); 13322 } 13323 if((val = mysistvcolcalibc) != 0) { 13324 SiS_SetSISTVcolcalib(pScrn, val, TRUE); 13325 } 13326 if((val = mysistvcolcalibf) != 0) { 13327 SiS_SetSISTVcolcalib(pScrn, val, FALSE); 13328 } 13329 if((val = mytvxpos) != 0) { 13330 SiS_SetTVxposoffset(pScrn, val); 13331 } 13332 if((val = mytvypos) != 0) { 13333 SiS_SetTVyposoffset(pScrn, val); 13334 } 13335 if((val = mytvxscale) != 0) { 13336 SiS_SetTVxscale(pScrn, val); 13337 } 13338 if((val = mytvyscale) != 0) { 13339 SiS_SetTVyscale(pScrn, val); 13340 } 13341 } 13342 } 13343 13344} 13345 13346/* Post-set SiS6326 TV registers */ 13347static void 13348SiS6326PostSetMode(ScrnInfoPtr pScrn, SISRegPtr sisReg) 13349{ 13350 SISPtr pSiS = SISPTR(pScrn); 13351 UChar tmp; 13352 int val; 13353 13354 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 13355 13356#ifdef UNLOCK_ALWAYS 13357 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 13358#endif 13359 13360 /* Backup default TV position registers */ 13361 pSiS->tvx1 = SiS6326GetTVReg(pScrn,0x3a); 13362 pSiS->tvx1 |= ((SiS6326GetTVReg(pScrn,0x3c) & 0x0f) << 8); 13363 pSiS->tvx2 = SiS6326GetTVReg(pScrn,0x26); 13364 pSiS->tvx2 |= ((SiS6326GetTVReg(pScrn,0x27) & 0xf0) << 4); 13365 pSiS->tvx3 = SiS6326GetTVReg(pScrn,0x12); 13366 pSiS->tvx3 |= ((SiS6326GetTVReg(pScrn,0x13) & 0xC0) << 2); 13367 pSiS->tvy1 = SiS6326GetTVReg(pScrn,0x11); 13368 pSiS->tvy1 |= ((SiS6326GetTVReg(pScrn,0x13) & 0x30) << 4); 13369 13370 /* Handle TVPosOffset options (BEFORE switching on TV) */ 13371 if((val = pSiS->tvxpos) != 0) { 13372 SiS_SetTVxposoffset(pScrn, val); 13373 } 13374 if((val = pSiS->tvypos) != 0) { 13375 SiS_SetTVyposoffset(pScrn, val); 13376 } 13377 13378 /* Switch on TV output. This is rather complicated, but 13379 * if we don't do it, TV output will flicker terribly. 13380 */ 13381 if(pSiS->SiS6326Flags & SIS6326_TVON) { 13382 orSISIDXREG(SISSR, 0x01, 0x20); 13383 tmp = SiS6326GetTVReg(pScrn,0x00); 13384 tmp &= ~0x04; 13385 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 13386 SiS6326SetTVReg(pScrn,0x00,tmp); 13387 for(val=0; val < 2; val++) { 13388 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 13389 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 13390 } 13391 SiS6326SetTVReg(pScrn, 0x00, sisReg->sis6326tv[0]); 13392 tmp = inSISREG(SISINPSTAT); 13393 outSISREG(SISAR, 0x20); 13394 tmp = inSISREG(SISINPSTAT); 13395 while(inSISREG(SISINPSTAT) & 0x01); 13396 while(!(inSISREG(SISINPSTAT) & 0x01)); 13397 andSISIDXREG(SISSR, 0x01, ~0x20); 13398 for(val=0; val < 10; val++) { 13399 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 13400 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 13401 } 13402 andSISIDXREG(SISSR, 0x01, ~0x20); 13403 } 13404 13405 tmp = SiS6326GetTVReg(pScrn,0x00); 13406 if(!(tmp & 0x04)) return; 13407 13408 /* Apply TV settings given by options */ 13409 if((val = pSiS->sistvantiflicker) != -1) { 13410 SiS_SetSIS6326TVantiflicker(pScrn, val); 13411 } 13412 if((val = pSiS->sis6326enableyfilter) != -1) { 13413 SiS_SetSIS6326TVenableyfilter(pScrn, val); 13414 } 13415 if((val = pSiS->sis6326yfilterstrong) != -1) { 13416 SiS_SetSIS6326TVyfilterstrong(pScrn, val); 13417 } 13418 13419} 13420 13421/* Check if video bridge is in slave mode */ 13422Bool 13423SiSBridgeIsInSlaveMode(ScrnInfoPtr pScrn) 13424{ 13425 SISPtr pSiS = SISPTR(pScrn); 13426 UChar usScrP1_00; 13427 13428 if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return FALSE; 13429 13430 inSISIDXREG(SISPART1,0x00,usScrP1_00); 13431 if( ((pSiS->VGAEngine == SIS_300_VGA) && (usScrP1_00 & 0xa0) == 0x20) || 13432 ((pSiS->VGAEngine == SIS_315_VGA) && (usScrP1_00 & 0x50) == 0x10) ) { 13433 return TRUE; 13434 } 13435 13436 return FALSE; 13437} 13438 13439/* Build a list of the VESA modes the BIOS reports as valid */ 13440static void 13441SiSBuildVesaModeList(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe) 13442{ 13443 SISPtr pSiS = SISPTR(pScrn); 13444 int i = 0; 13445 13446 while(vbe->VideoModePtr[i] != 0xffff) { 13447 sisModeInfoPtr m; 13448 VbeModeInfoBlock *mode; 13449 int id = vbe->VideoModePtr[i++]; 13450 13451 if((mode = VBEGetModeInfo(pVbe, id)) == NULL) { 13452 continue; 13453 } 13454 13455 m = xnfcalloc(sizeof(sisModeInfoRec), 1); 13456 if(!m) { 13457 VBEFreeModeInfo(mode); 13458 continue; 13459 } 13460 m->width = mode->XResolution; 13461 m->height = mode->YResolution; 13462 m->bpp = mode->BitsPerPixel; 13463 m->n = id; 13464 m->next = pSiS->SISVESAModeList; 13465 13466 pSiS->SISVESAModeList = m; 13467 13468 VBEFreeModeInfo(mode); 13469 13470 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 13471 "VESA BIOS supports mode number 0x%x: %ix%i (%i bpp)\n", 13472 m->n, m->width, m->height, m->bpp); 13473 } 13474} 13475 13476/* Get VESA mode number from given resolution/depth */ 13477static UShort 13478SiSCalcVESAModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode) 13479{ 13480 SISPtr pSiS = SISPTR(pScrn); 13481 sisModeInfoPtr m = pSiS->SISVESAModeList; 13482 UShort i = (pScrn->bitsPerPixel+7)/8 - 1; 13483 UShort ModeNumber = 0; 13484 int j; 13485 13486 while(m) { 13487 if( (pScrn->bitsPerPixel == m->bpp) && 13488 (mode->HDisplay == m->width) && 13489 (mode->VDisplay == m->height) ) 13490 return m->n; 13491 m = m->next; 13492 } 13493 13494 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 13495 "No valid VESA BIOS mode found for %dx%d (%d bpp)\n", 13496 mode->HDisplay, mode->VDisplay, pScrn->bitsPerPixel); 13497 13498 if(!pSiS->ROM661New) { /* VESA numbers changed! */ 13499 j = 0; 13500 while(VESAModeIndices[j] != 9999) { 13501 if( (mode->HDisplay == VESAModeIndices[j]) && 13502 (mode->VDisplay == VESAModeIndices[j+1]) ) { 13503 ModeNumber = VESAModeIndices[j + 2 + i]; 13504 break; 13505 } 13506 j += 6; 13507 } 13508 13509 if(!ModeNumber) { 13510 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 13511 "No valid mode found for %dx%dx%d in built-in table either.\n", 13512 mode->HDisplay, mode->VDisplay, pScrn->bitsPerPixel); 13513 } 13514 } 13515 13516 return(ModeNumber); 13517} 13518 13519UShort 13520SiS_GetModeNumber(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned int VBFlags) 13521{ 13522 SISPtr pSiS = SISPTR(pScrn); 13523 UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; 13524 BOOLEAN FSTN = pSiS->FSTN ? TRUE : FALSE; 13525 13526#ifdef SISDUALHEAD 13527 if(pSiS->DualHeadMode && pSiS->SecondHead) FSTN = FALSE; 13528#endif 13529 13530 return(SiS_GetModeID(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, 13531 i, FSTN, pSiS->LCDwidth, pSiS->LCDheight)); 13532} 13533 13534static Bool 13535SiSValidLCDUserMode(SISPtr pSiS, unsigned int VBFlags, DisplayModePtr mode, Bool isforlcda) 13536{ 13537 if(mode->Flags & V_INTERLACE) return FALSE; 13538 13539 if(mode->HDisplay > 2048) return FALSE; 13540 if(mode->VDisplay > 1536) return FALSE; 13541 13542 if(pSiS->VBFlags2 & VB2_LCD162MHZBRIDGE) { 13543 if(mode->Clock > 162500) return FALSE; 13544#ifdef VB_FORBID_CRT2LCD_OVER_1600 13545 if(!isforlcda) { 13546 if(mode->HDisplay > 1600) return FALSE; 13547 } 13548#endif 13549 } else { /* 301, 301B, 302B (no LCDA!) */ 13550 if(mode->Clock > 130000) return FALSE; 13551 if(mode->Clock > 111000) { 13552 xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING, 13553 "WARNING: Mode clock beyond video bridge specs (%dMHz). Hardware damage might occure.\n", 13554 mode->Clock / 1000); 13555 } 13556 if(mode->HDisplay > 1600) return FALSE; 13557 if(mode->VDisplay > 1024) return FALSE; 13558 } 13559 13560 return TRUE; 13561} 13562 13563static Bool 13564SiSValidVGA2UserMode(SISPtr pSiS, unsigned int VBFlags, DisplayModePtr mode) 13565{ 13566 if(mode->Flags & V_INTERLACE) return FALSE; 13567 13568 if(mode->HDisplay > 2048) return FALSE; 13569 if(mode->VDisplay > 1536) return FALSE; 13570 13571 if(pSiS->VBFlags2 & VB2_RAMDAC202MHZBRIDGE) { 13572 if(mode->Clock > 203000) return FALSE; 13573 } else if(pSiS->VBFlags2 & VB2_30xBLV) { 13574 if(mode->Clock > 162500) return FALSE; 13575 } else { 13576 if(mode->Clock > 135500) return FALSE; 13577 } 13578 13579 return TRUE; 13580} 13581 13582UShort 13583SiS_CheckModeCRT1(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned int VBFlags, Bool havecustommodes) 13584{ 13585 SISPtr pSiS = SISPTR(pScrn); 13586 UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; 13587 int j; 13588 13589 if(!(VBFlags & CRT1_LCDA)) { 13590 13591 if((havecustommodes) && (!(mode->type & M_T_DEFAULT))) { 13592 return 0xfe; 13593 } 13594 13595 } else if(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE) { 13596 13597 if(pSiS->ChipType < SIS_661) { /* < 661 only? */ 13598 if(!(mode->type & M_T_DEFAULT)) { 13599 if(mode->HTotal > 2055) return 0; 13600 /* (Default mode will be caught in mode switching code) */ 13601 } 13602 } 13603 13604 if(pSiS->SiS_Pr->CP_HaveCustomData) { 13605 for(j=0; j<7; j++) { 13606 if((pSiS->SiS_Pr->CP_DataValid[j]) && 13607 (mode->HDisplay == pSiS->SiS_Pr->CP_HDisplay[j]) && 13608 (mode->VDisplay == pSiS->SiS_Pr->CP_VDisplay[j]) && 13609 (mode->type & M_T_BUILTIN)) 13610 return 0xfe; 13611 } 13612 } 13613 13614 if((pSiS->AddedPlasmaModes) && (mode->type & M_T_BUILTIN)) 13615 return 0xfe; 13616 13617 if((havecustommodes) && 13618 (pSiS->LCDwidth) && /* = test if LCD present */ 13619 (!(mode->type & M_T_DEFAULT)) && 13620 (SiSValidLCDUserMode(pSiS, VBFlags, mode, TRUE))) 13621 return 0xfe; 13622 13623 if((mode->HDisplay > pSiS->LCDwidth) || 13624 (mode->VDisplay > pSiS->LCDheight)) { 13625 return 0; 13626 } 13627 13628 } else { 13629 13630 if((mode->HDisplay > pSiS->LCDwidth) || 13631 (mode->VDisplay > pSiS->LCDheight)) { 13632 return 0; 13633 } 13634 13635 } 13636 13637 return(SiS_GetModeID(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, 13638 i, pSiS->FSTN, pSiS->LCDwidth, pSiS->LCDheight)); 13639} 13640 13641UShort 13642SiS_CheckModeCRT2(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned int VBFlags, Bool havecustommodes) 13643{ 13644 SISPtr pSiS = SISPTR(pScrn); 13645 UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; 13646 UShort ModeIndex = 0; 13647 int j; 13648 13649#ifdef TWDEBUG 13650 xf86DrvMsg(0, X_INFO, "Inside CheckCalcModeIndex (VBFlags %lx, mode %dx%d)\n", 13651 VBFlags,mode->HDisplay, mode->VDisplay); 13652#endif 13653 13654 if(VBFlags & CRT2_LCD) { /* CRT2 is LCD */ 13655 13656 if((pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && (!(pSiS->VBFlags2 & VB2_30xBDH))) { 13657 13658 if(pSiS->SiS_Pr->CP_HaveCustomData) { 13659 for(j=0; j<7; j++) { 13660 if((pSiS->SiS_Pr->CP_DataValid[j]) && 13661 (mode->HDisplay == pSiS->SiS_Pr->CP_HDisplay[j]) && 13662 (mode->VDisplay == pSiS->SiS_Pr->CP_VDisplay[j]) && 13663#ifdef VB_FORBID_CRT2LCD_OVER_1600 13664 (mode->HDisplay <= 1600) && 13665#endif 13666 (mode->type & M_T_BUILTIN)) 13667 return 0xfe; 13668 } 13669 } 13670 13671 /* All plasma modes have HDisplay <= 1600 */ 13672 if((pSiS->AddedPlasmaModes) && (mode->type & M_T_BUILTIN)) 13673 return 0xfe; 13674 13675 if((havecustommodes) && 13676 (pSiS->LCDwidth) && /* = test if LCD present */ 13677 (!(mode->type & M_T_DEFAULT)) && 13678 (SiSValidLCDUserMode(pSiS, VBFlags, mode, FALSE))) 13679 return 0xfe; 13680 13681 } 13682 13683 if( ((mode->HDisplay <= pSiS->LCDwidth) && 13684 (mode->VDisplay <= pSiS->LCDheight)) || 13685 ((pSiS->SiS_Pr->SiS_CustomT == CUT_PANEL848) && 13686 (((mode->HDisplay == 1360) && (mode->HDisplay == 768)) || 13687 ((mode->HDisplay == 1024) && (mode->HDisplay == 768)) || 13688 ((mode->HDisplay == 800) && (mode->HDisplay == 600)))) || 13689 ((pSiS->SiS_Pr->SiS_CustomT == CUT_PANEL856) && 13690 (((mode->HDisplay == 1024) && (mode->HDisplay == 768)) || 13691 ((mode->HDisplay == 800) && (mode->HDisplay == 600)))) ) { 13692 13693 ModeIndex = SiS_GetModeID_LCD(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, i, 13694 pSiS->FSTN, pSiS->SiS_Pr->SiS_CustomT, pSiS->LCDwidth, pSiS->LCDheight, 13695 pSiS->VBFlags2); 13696 13697 } 13698 13699 } else if(VBFlags & CRT2_TV) { /* CRT2 is TV */ 13700 13701 ModeIndex = SiS_GetModeID_TV(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, i, 13702 pSiS->VBFlags2); 13703 13704 } else if(VBFlags & CRT2_VGA) { /* CRT2 is VGA2 */ 13705 13706 if((pSiS->AddedPlasmaModes) && (mode->type & M_T_BUILTIN)) 13707 return 0xfe; 13708 13709 if((havecustommodes) && 13710 (!(mode->type & M_T_DEFAULT)) && 13711 (SiSValidVGA2UserMode(pSiS, VBFlags, mode))) 13712 return 0xfe; 13713 13714 ModeIndex = SiS_GetModeID_VGA2(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, i, 13715 pSiS->VBFlags2); 13716 13717 } else { /* no CRT2 */ 13718 13719 /* Return a valid mode number */ 13720 ModeIndex = 0xfe; 13721 13722 } 13723 13724 return(ModeIndex); 13725} 13726 13727/* Calculate the vertical refresh rate from a mode */ 13728float 13729SiSCalcVRate(DisplayModePtr mode) 13730{ 13731 float hsync, refresh = 0; 13732 13733 if(mode->HSync > 0.0) 13734 hsync = mode->HSync; 13735 else if(mode->HTotal > 0) 13736 hsync = (float)mode->Clock / (float)mode->HTotal; 13737 else 13738 hsync = 0.0; 13739 13740 if(mode->VTotal > 0) 13741 refresh = hsync * 1000.0 / mode->VTotal; 13742 13743 if(mode->Flags & V_INTERLACE) 13744 refresh *= 2.0; 13745 13746 if(mode->Flags & V_DBLSCAN) 13747 refresh /= 2.0; 13748 13749 if(mode->VScan > 1) 13750 refresh /= mode->VScan; 13751 13752 if(mode->VRefresh > 0.0) 13753 refresh = mode->VRefresh; 13754 13755 if(hsync == 0.0 || refresh == 0.0) return 0.0; 13756 13757 return refresh; 13758} 13759 13760/* Calculate CR33 (rate index) for CRT1. 13761 * Calculation is done using currentmode, therefore it is 13762 * recommended to set VertRefresh and HorizSync to correct 13763 * values in config file. 13764 */ 13765UChar 13766SISSearchCRT1Rate(ScrnInfoPtr pScrn, DisplayModePtr mode) 13767{ 13768 SISPtr pSiS = SISPTR(pScrn); 13769 int i = 0, irefresh; 13770 UShort xres = mode->HDisplay; 13771 UShort yres = mode->VDisplay; 13772 UChar index, defindex; 13773 Bool checksis730 = FALSE; 13774 13775 defindex = (xres == 800 || xres == 1024 || xres == 1280) ? 0x02 : 0x01; 13776 13777 irefresh = (int)SiSCalcVRate(mode); 13778 if(!irefresh) return defindex; 13779 13780 /* SiS730 has troubles on CRT2 if CRT1 is at 32bpp */ 13781 if( (pSiS->ChipType == SIS_730) && 13782 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && 13783 (pSiS->CurrentLayout.bitsPerPixel == 32) ) { 13784#ifdef SISDUALHEAD 13785 if(pSiS->DualHeadMode) { 13786 if(pSiS->SecondHead) { 13787 checksis730 = TRUE; 13788 } 13789 } else 13790#endif 13791 if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE) && (!pSiS->CRT1off)) { 13792 checksis730 = TRUE; 13793 } 13794 } 13795 13796#ifdef TWDEBUG 13797 xf86DrvMsg(0, X_INFO, "Debug: CalcVRate returned %d\n", irefresh); 13798#endif 13799 13800 /* We need the REAL refresh rate here */ 13801 if(mode->Flags & V_INTERLACE) irefresh /= 2; 13802 13803 /* Do not multiply by 2 when DBLSCAN! */ 13804 13805#ifdef TWDEBUG 13806 xf86DrvMsg(0, X_INFO, "Debug: Rate after correction = %d\n", irefresh); 13807#endif 13808 13809 index = 0; 13810 while((sisx_vrate[i].idx != 0) && (sisx_vrate[i].xres <= xres)) { 13811 if((sisx_vrate[i].xres == xres) && (sisx_vrate[i].yres == yres)) { 13812 if((checksis730 == FALSE) || (sisx_vrate[i].SiS730valid32bpp == TRUE)) { 13813 if(sisx_vrate[i].refresh == irefresh) { 13814 index = sisx_vrate[i].idx; 13815 break; 13816 } else if(sisx_vrate[i].refresh > irefresh) { 13817 if((sisx_vrate[i].refresh - irefresh) <= 3) { 13818 index = sisx_vrate[i].idx; 13819 } else if( ((checksis730 == FALSE) || (sisx_vrate[i - 1].SiS730valid32bpp == TRUE)) && 13820 ((irefresh - sisx_vrate[i - 1].refresh) <= 2) && 13821 (sisx_vrate[i].idx != 1) ) { 13822 index = sisx_vrate[i - 1].idx; 13823 } 13824 break; 13825 } else if((irefresh - sisx_vrate[i].refresh) <= 2) { 13826 index = sisx_vrate[i].idx; 13827 break; 13828 } 13829 } 13830 } 13831 i++; 13832 } 13833 13834 if(index > 0) return index; 13835 else return defindex; 13836} 13837 13838void 13839SISWaitRetraceCRT1(ScrnInfoPtr pScrn) 13840{ 13841 SISPtr pSiS = SISPTR(pScrn); 13842 int watchdog; 13843 UChar temp; 13844 13845 inSISIDXREG(SISCR,0x17,temp); 13846 if(!(temp & 0x80)) return; 13847 13848 inSISIDXREG(SISSR,0x1f,temp); 13849 if(temp & 0xc0) return; 13850 13851 watchdog = 65536; 13852 while((inSISREG(SISINPSTAT) & 0x08) && --watchdog); 13853 watchdog = 65536; 13854 while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog); 13855} 13856 13857void 13858SISWaitRetraceCRT2(ScrnInfoPtr pScrn) 13859{ 13860 SISPtr pSiS = SISPTR(pScrn); 13861 int watchdog; 13862 UChar temp, reg; 13863 13864 if(SiSBridgeIsInSlaveMode(pScrn)) { 13865 SISWaitRetraceCRT1(pScrn); 13866 return; 13867 } 13868 13869 switch(pSiS->VGAEngine) { 13870 case SIS_300_VGA: 13871 reg = 0x25; 13872 break; 13873 case SIS_315_VGA: 13874 reg = 0x30; 13875 break; 13876 default: 13877 return; 13878 } 13879 13880 watchdog = 65536; 13881 do { 13882 inSISIDXREG(SISPART1, reg, temp); 13883 if(!(temp & 0x02)) break; 13884 } while(--watchdog); 13885 watchdog = 65536; 13886 do { 13887 inSISIDXREG(SISPART1, reg, temp); 13888 if(temp & 0x02) break; 13889 } while(--watchdog); 13890} 13891 13892static void 13893SISWaitVBRetrace(ScrnInfoPtr pScrn) 13894{ 13895 SISPtr pSiS = SISPTR(pScrn); 13896 13897 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 13898#ifdef SISDUALHEAD 13899 if(pSiS->DualHeadMode) { 13900 if(pSiS->SecondHead) 13901 SISWaitRetraceCRT1(pScrn); 13902 else 13903 SISWaitRetraceCRT2(pScrn); 13904 } else { 13905#endif 13906 if(pSiS->VBFlags & DISPTYPE_DISP1) { 13907 SISWaitRetraceCRT1(pScrn); 13908 } 13909 if(pSiS->VBFlags & DISPTYPE_DISP2) { 13910 if(!(SiSBridgeIsInSlaveMode(pScrn))) { 13911 SISWaitRetraceCRT2(pScrn); 13912 } 13913 } 13914#ifdef SISDUALHEAD 13915 } 13916#endif 13917 } else { 13918 SISWaitRetraceCRT1(pScrn); 13919 } 13920} 13921 13922#define MODEID_OFF 0x449 13923 13924UChar 13925SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, UShort offset, UChar value) 13926{ 13927 UChar ret = 0; 13928#ifdef SIS_USE_BIOS_SCRATCH 13929 UChar *base; 13930#endif 13931 13932 /* For some reasons (like detecting the current display mode), 13933 * we need to read (or write-back) values from the BIOS 13934 * scratch area. This area is only valid for the primary 13935 * graphics card. For the secondary, we just return some 13936 * defaults and ignore requests to write data. As regards 13937 * the display mode: If sisfb is loaded for the secondary 13938 * card, it very probably has set a mode, but in any case 13939 * informed us via its info packet. So this here will not be 13940 * called for mode detection in this case. 13941 */ 13942 13943 switch(offset) { 13944 case 0x489: 13945 ret = 0x11; /* Default VGA Info */ 13946 break; 13947 case MODEID_OFF: 13948 ret = 0x03; /* Default current display mode */ 13949 break; 13950 } 13951 13952#ifdef SIS_USE_BIOS_SCRATCH 13953 if(SISPTR(pScrn)->Primary) { 13954 base = xf86MapVidMem(pScrn->scrnIndex, VIDMEM_MMIO, 0, 0x2000); 13955 if(!base) { 13956 SISErrorLog(pScrn, "(Could not map BIOS scratch area)\n"); 13957 return ret; 13958 } 13959 13960 ret = *(base + offset); 13961 13962 /* value != 0xff means: set register */ 13963 if(value != 0xff) { 13964 *(base + offset) = value; 13965 } 13966 13967 xf86UnMapVidMem(pScrn->scrnIndex, base, 0x2000); 13968 } 13969#endif 13970 return ret; 13971} 13972 13973UChar 13974SiS_GetSetModeID(ScrnInfoPtr pScrn, UChar id) 13975{ 13976 return(SiS_GetSetBIOSScratch(pScrn, MODEID_OFF, id)); 13977} 13978 13979void 13980SiSMemCopyToVideoRam(SISPtr pSiS, UChar *to, UChar *from, int size) 13981{ 13982 if((ULong)to & 15) (*pSiS->SiSFastMemCopy)(to, from, size); 13983 else (*pSiS->SiSFastVidCopy)(to, from, size); 13984} 13985 13986void 13987SiSMemCopyFromVideoRam(SISPtr pSiS, UChar *to, UChar *from, int size) 13988{ 13989 if((ULong)to & 15) (*pSiS->SiSFastMemCopyFrom)(to, from, size); 13990 else (*pSiS->SiSFastVidCopyFrom)(to, from, size); 13991} 13992 13993void 13994sisSaveUnlockExtRegisterLock(SISPtr pSiS, UChar *reg1, UChar *reg2) 13995{ 13996 register UChar val; 13997 ULong mylockcalls; 13998#ifdef TWDEBUG 13999 UChar val1, val2; 14000 int i; 14001#endif 14002 14003 pSiS->lockcalls++; 14004 mylockcalls = pSiS->lockcalls; 14005 14006 /* check if already unlocked */ 14007 inSISIDXREG(SISSR, 0x05, val); 14008 14009 if(val != 0xa1) { 14010 14011 /* save State */ 14012 if(reg1) *reg1 = val; 14013 14014 /* unlock */ 14015 outSISIDXREG(SISSR, 0x05, 0x86); 14016 14017 /* Now check again */ 14018 inSISIDXREG(SISSR, 0x05, val); 14019 14020 if(val != 0xA1) { 14021 14022 xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING, 14023 "Failed to unlock SR registers at relocated i/o ports\n"); 14024 14025#ifdef TWDEBUG 14026 for(i = 0; i <= 0x3f; i++) { 14027 inSISIDXREG(SISSR, i, val1); 14028 inSISIDXREG(0x3c4, i, val2); 14029 xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO, 14030 "SR%02d: RelIO=0x%02x 0x3c4=0x%02x (%ld)\n", 14031 i, val1, val2, mylockcalls); 14032 } 14033#endif 14034 14035 /* Emergency measure: unlock at 0x3c4, and try to enable relocated IO ports */ 14036 switch(pSiS->VGAEngine) { 14037 case SIS_OLD_VGA: 14038 case SIS_530_VGA: 14039 outSISIDXREG(0x3c4, 0x05, 0x86); 14040 andSISIDXREG(0x3c4, 0x33, ~0x20); 14041 break; 14042 case SIS_300_VGA: 14043 case SIS_315_VGA: 14044 outSISIDXREG(0x3c4, 0x05, 0x86); 14045 orSISIDXREG(0x3c4, 0x20, 0x20); 14046 break; 14047 } 14048 outSISIDXREG(SISSR, 0x05, 0x86); 14049 inSISIDXREG(SISSR, 0x05, val); 14050 if(val != 0xa1) { 14051 SISErrorLog(pSiS->pScrn, 14052 "Failed to unlock SR registers (%p, %lx, 0x%02x; %ld)\n", 14053 (void *)pSiS, (ULong)pSiS->RelIO, val, mylockcalls); 14054 /* Now await doom... */ 14055 } 14056 } 14057 } 14058 if((pSiS->VGAEngine == SIS_OLD_VGA) || (pSiS->VGAEngine == SIS_530_VGA)) { 14059 inSISIDXREG(SISCR, 0x80, val); 14060 if(val != 0xa1) { 14061 /* save State */ 14062 if(reg2) *reg2 = val; 14063 outSISIDXREG(SISCR, 0x80, 0x86); 14064 inSISIDXREG(SISCR, 0x80, val); 14065 if(val != 0xA1) { 14066 SISErrorLog(pSiS->pScrn, 14067 "Failed to unlock cr registers (%p, %lx, 0x%02x)\n", 14068 (void *)pSiS, (ULong)pSiS->RelIO, val); 14069 } 14070 } 14071 } 14072} 14073 14074void 14075sisRestoreExtRegisterLock(SISPtr pSiS, UChar reg1, UChar reg2) 14076{ 14077 /* restore lock */ 14078#ifndef UNLOCK_ALWAYS 14079 outSISIDXREG(SISSR, 0x05, reg1 == 0xA1 ? 0x86 : 0x00); 14080 if((pSiS->VGAEngine == SIS_OLD_VGA) || (pSiS->VGAEngine == SIS_530_VGA)) { 14081 outSISIDXREG(SISCR, 0x80, reg2 == 0xA1 ? 0x86 : 0x00); 14082 } 14083#endif 14084} 14085 14086