sis_driver.c revision e35772b2
1/* 2 * SiS driver main code 3 * 4 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1) Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2) Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3) The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Author: Thomas Winischhofer <thomas@winischhofer.net> 29 * - driver entirely rewritten since 2001, only basic structure taken from 30 * old code (except sis_dri.c, sis_shadow.c, sis_accel.c and parts of 31 * sis_dga.c; these were mostly taken over; sis_dri.c was changed for 32 * new versions of the DRI layer) 33 * 34 * This notice covers the entire driver code unless indicated otherwise. 35 * 36 * Formerly based on code which was 37 * Copyright (C) 1998, 1999 by Alan Hourihane, Wigan, England. 38 * Written by: 39 * Alan Hourihane <alanh@fairlite.demon.co.uk>, 40 * Mike Chapman <mike@paranoia.com>, 41 * Juanjo Santamarta <santamarta@ctv.es>, 42 * Mitani Hiroshi <hmitani@drl.mei.co.jp>, 43 * David Thomas <davtom@dream.org.uk>. 44 */ 45 46#ifdef HAVE_CONFIG_H 47#include "config.h" 48#endif 49 50#include "sis.h" 51 52#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 53#include "xf86RAC.h" 54#endif 55#include "dixstruct.h" 56#include "shadowfb.h" 57#include "fb.h" 58#include "micmap.h" 59#include "mipointer.h" 60#include "mibstore.h" 61#include "edid.h" 62 63#define SIS_NEED_inSISREG 64#define SIS_NEED_inSISIDXREG 65#define SIS_NEED_outSISIDXREG 66#define SIS_NEED_orSISIDXREG 67#define SIS_NEED_andSISIDXREG 68#define SIS_NEED_setSISIDXREG 69#define SIS_NEED_outSISREG 70#define SIS_NEED_MYMMIO 71#define SIS_NEED_sisclearvram 72#include "sis_regs.h" 73#include "sis_dac.h" 74 75#include "sis_driver.h" 76 77#define _XF86DGA_SERVER_ 78#include <X11/extensions/xf86dgastr.h> 79 80#include "globals.h" 81 82#ifdef HAVE_XEXTPROTO_71 83#include <X11/extensions/dpmsconst.h> 84#else 85#define DPMS_SERVER 86#include <X11/extensions/dpms.h> 87#endif 88 89 90#ifdef XF86DRI 91#include "dri.h" 92#endif 93 94/* Globals (yes, these ARE really required to be global) */ 95 96#ifdef SISUSEDEVPORT 97int sisdevport = 0; 98#endif 99 100#ifdef SISDUALHEAD 101static int SISEntityIndex = -1; 102#endif 103 104#ifdef SISMERGED 105#ifdef SISXINERAMA 106static Bool SiSnoPanoramiXExtension = TRUE; 107static int SiSXineramaNumScreens = 0; 108static SiSXineramaData *SiSXineramadataPtr = NULL; 109static int SiSXineramaGeneration; 110 111static int SiSProcXineramaQueryVersion(ClientPtr client); 112static int SiSProcXineramaGetState(ClientPtr client); 113static int SiSProcXineramaGetScreenCount(ClientPtr client); 114static int SiSProcXineramaGetScreenSize(ClientPtr client); 115static int SiSProcXineramaIsActive(ClientPtr client); 116static int SiSProcXineramaQueryScreens(ClientPtr client); 117static int SiSSProcXineramaDispatch(ClientPtr client); 118#endif 119#endif 120 121/* 122 * This is intentionally screen-independent. It indicates the binding 123 * choice made in the first PreInit. 124 */ 125static int pix24bpp = 0; 126 127/* 128 * This contains the functions needed by the server after loading the driver 129 * module. It must be supplied, and gets passed back by the SetupProc 130 * function in the dynamic case. In the static case, a reference to this 131 * is compiled in, and this requires that the name of this DriverRec be 132 * an upper-case version of the driver name. 133 */ 134 135#ifdef _X_EXPORT 136_X_EXPORT 137#endif 138DriverRec SIS = { 139 SIS_CURRENT_VERSION, 140 SIS_DRIVER_NAME, 141 SISIdentify, 142 SISProbe, 143 SISAvailableOptions, 144 NULL, 145 0 146#ifdef SIS_HAVE_DRIVER_FUNC 147 , 148 SISDriverFunc 149#endif 150}; 151 152static SymTabRec SISChipsets[] = { 153 { PCI_CHIP_SIS5597, "SIS5597/5598" }, 154 { PCI_CHIP_SIS530, "SIS530/620" }, 155 { PCI_CHIP_SIS6326, "SIS6326/AGP/DVD" }, 156 { PCI_CHIP_SIS300, "SIS300/305" }, 157 { PCI_CHIP_SIS630, "SIS630/730" }, 158 { PCI_CHIP_SIS540, "SIS540" }, 159 { PCI_CHIP_SIS315, "SIS315" }, 160 { PCI_CHIP_SIS315H, "SIS315H" }, 161 { PCI_CHIP_SIS315PRO, "SIS315PRO/E" }, 162 { PCI_CHIP_SIS550, "SIS550" }, 163 { PCI_CHIP_SIS650, "SIS650/M650/651/740" }, 164 { PCI_CHIP_SIS330, "SIS330(Xabre)" }, 165 { PCI_CHIP_SIS660, "SIS660/[M]661[F|M]X/[M]670/[M]741[GX]/[M]760[GX]/[M]761[GX]/[M]770[GX]" }, 166 { PCI_CHIP_SIS340, "SIS340" }, 167 { -1, NULL } 168}; 169 170static PciChipsets SISPciChipsets[] = { 171 { PCI_CHIP_SIS5597, PCI_CHIP_SIS5597, RES_SHARED_VGA }, 172 { PCI_CHIP_SIS530, PCI_CHIP_SIS530, RES_SHARED_VGA }, 173 { PCI_CHIP_SIS6326, PCI_CHIP_SIS6326, RES_SHARED_VGA }, 174 { PCI_CHIP_SIS300, PCI_CHIP_SIS300, RES_SHARED_VGA }, 175 { PCI_CHIP_SIS630, PCI_CHIP_SIS630, RES_SHARED_VGA }, 176 { PCI_CHIP_SIS540, PCI_CHIP_SIS540, RES_SHARED_VGA }, 177 { PCI_CHIP_SIS550, PCI_CHIP_SIS550, RES_SHARED_VGA }, 178 { PCI_CHIP_SIS315, PCI_CHIP_SIS315, RES_SHARED_VGA }, 179 { PCI_CHIP_SIS315H, PCI_CHIP_SIS315H, RES_SHARED_VGA }, 180 { PCI_CHIP_SIS315PRO, PCI_CHIP_SIS315PRO, RES_SHARED_VGA }, 181 { PCI_CHIP_SIS650, PCI_CHIP_SIS650, RES_SHARED_VGA }, 182 { PCI_CHIP_SIS330, PCI_CHIP_SIS330, RES_SHARED_VGA }, 183 { PCI_CHIP_SIS660, PCI_CHIP_SIS660, RES_SHARED_VGA }, 184 { PCI_CHIP_SIS340, PCI_CHIP_SIS340, RES_SHARED_VGA }, 185 { -1, -1, RES_UNDEFINED } 186}; 187 188static SymTabRec XGIChipsets[] = { 189 { PCI_CHIP_XGIXG20, "Volari Z7 (XG20)" }, 190 { PCI_CHIP_XGIXG40, "Volari V3XT/V5/V8/Duo (XG40)" }, 191 { -1, NULL } 192}; 193 194static PciChipsets XGIPciChipsets[] = { 195 { PCI_CHIP_XGIXG20, PCI_CHIP_XGIXG20, RES_SHARED_VGA }, 196 { PCI_CHIP_XGIXG40, PCI_CHIP_XGIXG40, RES_SHARED_VGA }, 197 { -1, -1, RES_UNDEFINED } 198}; 199 200#ifdef XFree86LOADER 201 202static MODULESETUPPROTO(sisSetup); 203 204static XF86ModuleVersionInfo sisVersRec = 205{ 206 SIS_DRIVER_NAME, 207 MODULEVENDORSTRING, 208 MODINFOSTRING1, 209 MODINFOSTRING2, 210#ifdef XORG_VERSION_CURRENT 211 XORG_VERSION_CURRENT, 212#else 213 XF86_VERSION_CURRENT, 214#endif 215 SIS_MAJOR_VERSION, SIS_MINOR_VERSION, SIS_PATCHLEVEL, 216 ABI_CLASS_VIDEODRV, /* This is a video driver */ 217 ABI_VIDEODRV_VERSION, 218 MOD_CLASS_VIDEODRV, 219 {0,0,0,0} 220}; 221 222#ifdef _X_EXPORT 223_X_EXPORT 224#endif 225XF86ModuleData sisModuleData = { &sisVersRec, sisSetup, NULL }; 226 227pointer 228sisSetup(pointer module, pointer opts, int *errmaj, int *errmin) 229{ 230 static Bool setupDone = FALSE; 231 232 if(!setupDone) { 233 setupDone = TRUE; 234 xf86AddDriver(&SIS, module, SIS_HaveDriverFuncs); 235 return (pointer)TRUE; 236 } 237 238 if(errmaj) *errmaj = LDR_ONCEONLY; 239 return NULL; 240} 241 242#endif /* XFree86LOADER */ 243 244/* Mandatory */ 245static void 246SISIdentify(int flags) 247{ 248 xf86PrintChipsets(SIS_NAME, "driver for SiS chipsets", SISChipsets); 249 xf86PrintChipsets(SIS_NAME, "driver for XGI chipsets", XGIChipsets); 250} 251 252#ifdef SIS_HAVE_DRIVER_FUNC 253static Bool 254SISDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op, pointer ptr) 255{ 256 CARD32 *flag; 257 258 switch(op) { 259 case RR_GET_INFO: 260 break; 261 case RR_SET_CONFIG: 262 break; 263 case GET_REQUIRED_HW_INTERFACES: 264 break; 265 } 266 return TRUE; 267} 268#endif 269 270static Bool 271SISGetRec(ScrnInfoPtr pScrn) 272{ 273 /* Allocate an SISRec, and hook it into pScrn->driverPrivate. 274 * pScrn->driverPrivate is initialised to NULL, so we can check if 275 * the allocation has already been done. 276 */ 277 if(pScrn->driverPrivate != NULL) return TRUE; 278 279 pScrn->driverPrivate = xnfcalloc(sizeof(SISRec), 1); 280 281 /* Initialise it to 0 */ 282 memset(pScrn->driverPrivate, 0, sizeof(SISRec)); 283 284 return TRUE; 285} 286 287static void 288SISFreeRec(ScrnInfoPtr pScrn) 289{ 290 SISPtr pSiS = SISPTR(pScrn); 291#ifdef SISDUALHEAD 292 SISEntPtr pSiSEnt = NULL; 293#endif 294 295 /* Just to make sure... */ 296 if(!pSiS) return; 297 298#ifdef SISDUALHEAD 299 pSiSEnt = pSiS->entityPrivate; 300#endif 301 302 if(pSiS->pstate) xfree(pSiS->pstate); 303 pSiS->pstate = NULL; 304 if(pSiS->fonts) xfree(pSiS->fonts); 305 pSiS->fonts = NULL; 306 307#ifdef SISDUALHEAD 308 if(pSiSEnt) { 309 if(!pSiS->SecondHead) { 310 /* Free memory only if we are first head; in case of an error 311 * during init of the second head, the server will continue - 312 * and we need the BIOS image and SiS_Private for the first 313 * head. 314 */ 315 if(pSiSEnt->BIOS) xfree(pSiSEnt->BIOS); 316 pSiSEnt->BIOS = pSiS->BIOS = NULL; 317 if(pSiSEnt->SiS_Pr) xfree(pSiSEnt->SiS_Pr); 318 pSiSEnt->SiS_Pr = pSiS->SiS_Pr = NULL; 319 if(pSiSEnt->RenderAccelArray) xfree(pSiSEnt->RenderAccelArray); 320 pSiSEnt->RenderAccelArray = pSiS->RenderAccelArray = NULL; 321 pSiSEnt->pScrn_1 = NULL; 322 } else { 323 pSiS->BIOS = NULL; 324 pSiS->SiS_Pr = NULL; 325 pSiS->RenderAccelArray = NULL; 326 pSiSEnt->pScrn_2 = NULL; 327 } 328 } else { 329#endif 330 if(pSiS->BIOS) xfree(pSiS->BIOS); 331 pSiS->BIOS = NULL; 332 if(pSiS->SiS_Pr) xfree(pSiS->SiS_Pr); 333 pSiS->SiS_Pr = NULL; 334 if(pSiS->RenderAccelArray) xfree(pSiS->RenderAccelArray); 335 pSiS->RenderAccelArray = NULL; 336#ifdef SISDUALHEAD 337 } 338#endif 339#ifdef SISMERGED 340 if(pSiS->CRT2HSync) xfree(pSiS->CRT2HSync); 341 pSiS->CRT2HSync = NULL; 342 if(pSiS->CRT2VRefresh) xfree(pSiS->CRT2VRefresh); 343 pSiS->CRT2VRefresh = NULL; 344 if(pSiS->MetaModes) xfree(pSiS->MetaModes); 345 pSiS->MetaModes = NULL; 346 if(pSiS->CRT2pScrn) { 347 if(pSiS->CRT2pScrn->modes) { 348 while(pSiS->CRT2pScrn->modes) 349 xf86DeleteMode(&pSiS->CRT2pScrn->modes, pSiS->CRT2pScrn->modes); 350 } 351 if(pSiS->CRT2pScrn->monitor) { 352 if(pSiS->CRT2pScrn->monitor->Modes) { 353 while(pSiS->CRT2pScrn->monitor->Modes) 354 xf86DeleteMode(&pSiS->CRT2pScrn->monitor->Modes, pSiS->CRT2pScrn->monitor->Modes); 355 } 356 if(pSiS->CRT2pScrn->monitor->DDC) xfree(pSiS->CRT2pScrn->monitor->DDC); 357 xfree(pSiS->CRT2pScrn->monitor); 358 } 359 xfree(pSiS->CRT2pScrn); 360 pSiS->CRT2pScrn = NULL; 361 } 362 if(pSiS->CRT1Modes) { 363 if(pSiS->CRT1Modes != pScrn->modes) { 364 if(pScrn->modes) { 365 pScrn->currentMode = pScrn->modes; 366 do { 367 DisplayModePtr p = pScrn->currentMode->next; 368 if(pScrn->currentMode->Private) 369 xfree(pScrn->currentMode->Private); 370 xfree(pScrn->currentMode); 371 pScrn->currentMode = p; 372 } while(pScrn->currentMode != pScrn->modes); 373 } 374 pScrn->currentMode = pSiS->CRT1CurrentMode; 375 pScrn->modes = pSiS->CRT1Modes; 376 pSiS->CRT1CurrentMode = NULL; 377 pSiS->CRT1Modes = NULL; 378 } 379 } 380#endif 381 while(pSiS->SISVESAModeList) { 382 sisModeInfoPtr mp = pSiS->SISVESAModeList->next; 383 xfree(pSiS->SISVESAModeList); 384 pSiS->SISVESAModeList = mp; 385 } 386 if(pSiS->pVbe) vbeFree(pSiS->pVbe); 387 pSiS->pVbe = NULL; 388 389#ifdef SISUSEDEVPORT 390 if(pSiS->sisdevportopen) close(sisdevport); 391#endif 392 393 if(pScrn->driverPrivate == NULL) 394 return; 395 xfree(pScrn->driverPrivate); 396 pScrn->driverPrivate = NULL; 397} 398 399static void 400SISErrorLog(ScrnInfoPtr pScrn, const char *format, ...) 401{ 402 va_list ap; 403 static const char *str = "**************************************************\n"; 404 405 va_start(ap, format); 406 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, str); 407 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 408 " ERROR:\n"); 409 xf86VDrvMsgVerb(pScrn->scrnIndex, X_ERROR, 1, format, ap); 410 va_end(ap); 411 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 412 " END OF MESSAGE\n"); 413 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, str); 414} 415 416static void 417SiS_SiSFB_Lock(ScrnInfoPtr pScrn, Bool lock) 418{ 419 SISPtr pSiS = SISPTR(pScrn); 420 int fd; 421 CARD32 parm; 422 423 if(!pSiS->sisfbfound) return; 424 if(!pSiS->sisfb_havelock) return; 425 426 if((fd = open(pSiS->sisfbdevname, O_RDONLY)) != -1) { 427 parm = lock ? 1 : 0; 428 ioctl(fd, SISFB_SET_LOCK, &parm); 429 close(fd); 430 } 431} 432 433/* Probe() 434 * 435 * Mandatory 436 */ 437static Bool 438SISProbe(DriverPtr drv, int flags) 439{ 440 int i; 441 GDevPtr *devSections; 442 int *usedChipsSiS, *usedChipsXGI; 443 int numDevSections; 444 int numUsed, numUsedSiS, numUsedXGI; 445 Bool foundScreen = FALSE; 446 447 /* 448 * The aim here is to find all cards that this driver can handle, 449 * and for the ones not already claimed by another driver, claim the 450 * slot, and allocate a ScrnInfoRec. 451 * 452 * This should be a minimal probe, and it should under no circumstances 453 * change the state of the hardware. Because a device is found, don't 454 * assume that it will be used. Don't do any initialisations other than 455 * the required ScrnInfoRec initialisations. Don't allocate any new 456 * data structures. 457 * 458 */ 459 460 /* 461 * Next we check, if there has been a chipset override in the config file. 462 * For this we must find out if there is an active device section which 463 * is relevant, i.e., which has no driver specified or has THIS driver 464 * specified. 465 */ 466 467 if((numDevSections = xf86MatchDevice(SIS_DRIVER_NAME, &devSections)) <= 0) { 468 /* 469 * There's no matching device section in the config file, so quit 470 * now. 471 */ 472 return FALSE; 473 } 474 475 /* 476 * We need to probe the hardware first. We then need to see how this 477 * fits in with what is given in the config file, and allow the config 478 * file info to override any contradictions. 479 */ 480 481 /* 482 * All of the cards this driver supports are PCI, so the "probing" just 483 * amounts to checking the PCI data that the server has already collected. 484 */ 485#ifndef XSERVER_LIBPCIACCESS 486 if(xf86GetPciVideoInfo() == NULL) { 487 /* 488 * We won't let anything in the config file override finding no 489 * PCI video cards at all. 490 */ 491 return FALSE; 492 } 493#endif 494 495 numUsedSiS = xf86MatchPciInstances(SIS_NAME, PCI_VENDOR_SIS, 496 SISChipsets, SISPciChipsets, devSections, 497 numDevSections, drv, &usedChipsSiS); 498 499 numUsedXGI = xf86MatchPciInstances(SIS_NAME, PCI_VENDOR_XGI, 500 XGIChipsets, XGIPciChipsets, devSections, 501 numDevSections, drv, &usedChipsXGI); 502 503 /* Free it since we don't need that list after this */ 504 xfree(devSections); 505 506 numUsed = numUsedSiS + numUsedXGI; 507 508 if(numUsed <= 0) 509 return FALSE; 510 511 if(flags & PROBE_DETECT) { 512 513 foundScreen = TRUE; 514 515 } else for(i = 0; i < numUsed; i++) { 516 517 ScrnInfoPtr pScrn; 518#ifdef SISDUALHEAD 519 EntityInfoPtr pEnt; 520#endif 521 522 /* Allocate a ScrnInfoRec and claim the slot */ 523 pScrn = NULL; 524 525 if((pScrn = xf86ConfigPciEntity(pScrn, 0, 526 (i < numUsedSiS) ? usedChipsSiS[i] : usedChipsXGI[i-numUsedSiS], 527 (i < numUsedSiS) ? SISPciChipsets : XGIPciChipsets, 528 NULL, NULL, NULL, NULL, NULL))) { 529 /* Fill in what we can of the ScrnInfoRec */ 530 pScrn->driverVersion = SIS_CURRENT_VERSION; 531 pScrn->driverName = SIS_DRIVER_NAME; 532 pScrn->name = SIS_NAME; 533 pScrn->Probe = SISProbe; 534 pScrn->PreInit = SISPreInit; 535 pScrn->ScreenInit = SISScreenInit; 536 pScrn->SwitchMode = SISSwitchMode; 537 pScrn->AdjustFrame = SISAdjustFrame; 538 pScrn->EnterVT = SISEnterVT; 539 pScrn->LeaveVT = SISLeaveVT; 540 pScrn->FreeScreen = SISFreeScreen; 541 pScrn->ValidMode = SISValidMode; 542 543 foundScreen = TRUE; 544 } 545 546#ifdef SISDUALHEAD 547 pEnt = xf86GetEntityInfo((i < numUsedSiS) ? usedChipsSiS[i] : usedChipsXGI[i-numUsedSiS]); 548 549 if(pEnt->chipset == PCI_CHIP_SIS630 || pEnt->chipset == PCI_CHIP_SIS540 || 550 pEnt->chipset == PCI_CHIP_SIS650 || pEnt->chipset == PCI_CHIP_SIS550 || 551 pEnt->chipset == PCI_CHIP_SIS315 || pEnt->chipset == PCI_CHIP_SIS315H || 552 pEnt->chipset == PCI_CHIP_SIS315PRO || pEnt->chipset == PCI_CHIP_SIS330 || 553 pEnt->chipset == PCI_CHIP_SIS300 || pEnt->chipset == PCI_CHIP_SIS660 || 554 pEnt->chipset == PCI_CHIP_SIS340 || pEnt->chipset == PCI_CHIP_XGIXG40) { 555 556 SISEntPtr pSiSEnt = NULL; 557 DevUnion *pPriv; 558 559 xf86SetEntitySharable((i < numUsedSiS) ? usedChipsSiS[i] : usedChipsXGI[i-numUsedSiS]); 560 if(SISEntityIndex < 0) { 561 SISEntityIndex = xf86AllocateEntityPrivateIndex(); 562 } 563 pPriv = xf86GetEntityPrivate(pScrn->entityList[0], SISEntityIndex); 564 if(!pPriv->ptr) { 565 pPriv->ptr = xnfcalloc(sizeof(SISEntRec), 1); 566 pSiSEnt = pPriv->ptr; 567 memset(pSiSEnt, 0, sizeof(SISEntRec)); 568 pSiSEnt->lastInstance = -1; 569 } else { 570 pSiSEnt = pPriv->ptr; 571 } 572 pSiSEnt->lastInstance++; 573 xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0], 574 pSiSEnt->lastInstance); 575 } 576#endif /* DUALHEAD */ 577 578 } 579 580 if(usedChipsSiS) xfree(usedChipsSiS); 581 if(usedChipsXGI) xfree(usedChipsXGI); 582 583 return foundScreen; 584} 585 586/* Various helpers */ 587 588static unsigned short 589calcgammaval(int j, int nramp, float invgamma, float bri, float c) 590{ 591 float k = (float)j; 592 float nrm1 = (float)(nramp - 1); 593 float con = c * nrm1 / 3.0; 594 float l, v; 595 596 if(con != 0.0) { 597 l = nrm1 / 2.0; 598 if(con <= 0.0) { 599 k -= l; 600 k *= (l + con) / l; 601 } else { 602 l -= 1.0; 603 k -= l; 604 k *= l / (l - con); 605 } 606 k += l; 607 if(k < 0.0) k = 0.0; 608 } 609 610 if(invgamma == 1.0) { 611 v = k / nrm1 * 65535.0; 612 } else { 613 v = pow(k / nrm1, invgamma) * 65535.0 + 0.5; 614 } 615 616 v += (bri * (65535.0 / 3.0)) ; 617 618 if(v < 0.0) v = 0.0; 619 else if(v > 65535.0) v = 65535.0; 620 621 return (unsigned short)v; 622} 623 624#ifdef SISGAMMARAMP 625void 626SISCalculateGammaRamp(ScreenPtr pScreen, ScrnInfoPtr pScrn) 627{ 628 SISPtr pSiS = SISPTR(pScrn); 629 int i, j, nramp; 630 UShort *ramp[3]; 631 float gamma_max[3], framp; 632 Bool newmethod = FALSE; 633 634 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_OLDGAMMAINUSE)) { 635 newmethod = TRUE; 636 } else { 637 gamma_max[0] = (float)pSiS->GammaBriR / 1000; 638 gamma_max[1] = (float)pSiS->GammaBriG / 1000; 639 gamma_max[2] = (float)pSiS->GammaBriB / 1000; 640 } 641 642 if(!(nramp = xf86GetGammaRampSize(pScreen))) return; 643 644 for(i=0; i<3; i++) { 645 ramp[i] = (UShort *)xalloc(nramp * sizeof(UShort)); 646 if(!ramp[i]) { 647 if(ramp[0]) { xfree(ramp[0]); ramp[0] = NULL; } 648 if(ramp[1]) { xfree(ramp[1]); ramp[1] = NULL; } 649 return; 650 } 651 } 652 653 if(newmethod) { 654 655 for(i = 0; i < 3; i++) { 656 657 float invgamma = 0.0, bri = 0.0, con = 0.0; 658 659 switch(i) { 660 case 0: invgamma = 1. / pScrn->gamma.red; 661 bri = pSiS->NewGammaBriR; 662 con = pSiS->NewGammaConR; 663 break; 664 case 1: invgamma = 1. / pScrn->gamma.green; 665 bri = pSiS->NewGammaBriG; 666 con = pSiS->NewGammaConG; 667 break; 668 case 2: invgamma = 1. / pScrn->gamma.blue; 669 bri = pSiS->NewGammaBriB; 670 con = pSiS->NewGammaConB; 671 break; 672 } 673 674 for(j = 0; j < nramp; j++) { 675 ramp[i][j] = calcgammaval(j, nramp, invgamma, bri, con); 676 } 677 678 } 679 680 } else { 681 682 for(i = 0; i < 3; i++) { 683 int fullscale = 65535 * gamma_max[i]; 684 float dramp = 1. / (nramp - 1); 685 float invgamma = 0.0, v; 686 687 switch(i) { 688 case 0: invgamma = 1. / pScrn->gamma.red; break; 689 case 1: invgamma = 1. / pScrn->gamma.green; break; 690 case 2: invgamma = 1. / pScrn->gamma.blue; break; 691 } 692 693 for(j = 0; j < nramp; j++) { 694 framp = pow(j * dramp, invgamma); 695 696 v = (fullscale < 0) ? (65535 + fullscale * framp) : 697 fullscale * framp; 698 if(v < 0) v = 0; 699 else if(v > 65535) v = 65535; 700 ramp[i][j] = (UShort)v; 701 } 702 } 703 704 } 705 706 xf86ChangeGammaRamp(pScreen, nramp, ramp[0], ramp[1], ramp[2]); 707 708 xfree(ramp[0]); 709 xfree(ramp[1]); 710 xfree(ramp[2]); 711 ramp[0] = ramp[1] = ramp[2] = NULL; 712} 713#endif 714 715void 716SISCalculateGammaRampCRT2(ScrnInfoPtr pScrn) 717{ 718 SISPtr pSiS = SISPTR(pScrn); 719 int i; 720 int myshift = 16 - pScrn->rgbBits; 721 int maxvalue = (1 << pScrn->rgbBits) - 1; 722 int reds = pScrn->mask.red >> pScrn->offset.red; 723 int greens = pScrn->mask.green >> pScrn->offset.green; 724 int blues = pScrn->mask.blue >> pScrn->offset.blue; 725 float framp, invgamma1, invgamma2, invgamma3, v; 726 727 invgamma1 = 1. / pSiS->GammaR2; 728 invgamma2 = 1. / pSiS->GammaG2; 729 invgamma3 = 1. / pSiS->GammaB2; 730 731 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_OLDGAMMAINUSE)) { 732 733 for(i = 0; i < pSiS->CRT2ColNum; i++) { 734 pSiS->crt2gcolortable[i].red = calcgammaval(i, pSiS->CRT2ColNum, invgamma1, 735 pSiS->NewGammaBriR2, pSiS->NewGammaConR2) >> myshift; 736 pSiS->crt2gcolortable[i].green = calcgammaval(i, pSiS->CRT2ColNum, invgamma2, 737 pSiS->NewGammaBriG2, pSiS->NewGammaConG2) >> myshift; 738 pSiS->crt2gcolortable[i].blue = calcgammaval(i, pSiS->CRT2ColNum, invgamma3, 739 pSiS->NewGammaBriB2, pSiS->NewGammaConB2) >> myshift; 740 } 741 742 } else { 743 744 int fullscale1 = 65536 * (float)pSiS->GammaBriR2 / 1000; 745 int fullscale2 = 65536 * (float)pSiS->GammaBriG2 / 1000; 746 int fullscale3 = 65536 * (float)pSiS->GammaBriB2 / 1000; 747 748 float dramp = 1. / (pSiS->CRT2ColNum - 1); 749 750 for(i = 0; i < pSiS->CRT2ColNum; i++) { 751 framp = pow(i * dramp, invgamma1); 752 v = (fullscale1 < 0) ? (65535 + fullscale1 * framp) : fullscale1 * framp; 753 if(v < 0) v = 0; 754 else if(v > 65535) v = 65535; 755 pSiS->crt2gcolortable[i].red = ((UShort)v) >> myshift; 756 framp = pow(i * dramp, invgamma2); 757 v = (fullscale2 < 0) ? (65535 + fullscale2 * framp) : fullscale2 * framp; 758 if(v < 0) v = 0; 759 else if(v > 65535) v = 65535; 760 pSiS->crt2gcolortable[i].green = ((UShort)v) >> myshift; 761 framp = pow(i * dramp, invgamma3); 762 v = (fullscale3 < 0) ? (65535 + fullscale3 * framp) : fullscale3 * framp; 763 if(v < 0) v = 0; 764 else if(v > 65535) v = 65535; 765 pSiS->crt2gcolortable[i].blue = ((UShort)v) >> myshift; 766 } 767 768 } 769 770 for(i = 0; i < pSiS->CRT2ColNum; i++) { 771 pSiS->crt2colors[i].red = 772 pSiS->crt2gcolortable[i * maxvalue / reds].red; 773 pSiS->crt2colors[i].green = 774 pSiS->crt2gcolortable[i * maxvalue / greens].green; 775 pSiS->crt2colors[i].blue = 776 pSiS->crt2gcolortable[i * maxvalue / blues].blue; 777 } 778} 779 780/* If monitor section has no HSync/VRefresh data, 781 * derive it from DDC data. 782 */ 783static void 784SiSSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) 785{ 786 MonPtr mon = pScrn->monitor; 787 xf86MonPtr ddc = mon->DDC; 788 float myhhigh = 0.0, myhlow = 0.0, htest; 789 int myvhigh = 0, myvlow = 0, vtest, i; 790 UChar temp; 791 const myhddctiming myhtiming[12] = { 792 { 1, 0x20, 31.6 }, /* rounded up by .1 */ 793 { 1, 0x80, 31.6 }, 794 { 1, 0x02, 35.3 }, 795 { 1, 0x04, 37.6 }, 796 { 1, 0x08, 38.0 }, 797 { 1, 0x01, 38.0 }, 798 { 2, 0x40, 47.0 }, 799 { 2, 0x80, 48.2 }, 800 { 2, 0x08, 48.5 }, 801 { 2, 0x04, 56.6 }, 802 { 2, 0x02, 60.1 }, 803 { 2, 0x01, 80.1 } 804 }; 805 const myvddctiming myvtiming[11] = { 806 { 1, 0x02, 56 }, 807 { 1, 0x01, 60 }, 808 { 2, 0x08, 60 }, 809 { 2, 0x04, 70 }, 810 { 1, 0x80, 71 }, 811 { 1, 0x08, 72 }, 812 { 2, 0x80, 72 }, 813 { 1, 0x04, 75 }, 814 { 2, 0x40, 75 }, 815 { 2, 0x02, 75 }, 816 { 2, 0x01, 75 } 817 }; 818 819 if(flag) { /* HSync */ 820 821 for(i = 0; i < 4; i++) { 822 if(ddc->det_mon[i].type == DS_RANGES) { 823 mon->nHsync = 1; 824 mon->hsync[0].lo = ddc->det_mon[i].section.ranges.min_h; 825 mon->hsync[0].hi = ddc->det_mon[i].section.ranges.max_h; 826 if(mon->hsync[0].lo > 32.0 || mon->hsync[0].hi < 31.0) { 827 if(ddc->timings1.t1 & 0x80) { 828 mon->nHsync++; 829 mon->hsync[1].lo = 31.0; 830 mon->hsync[1].hi = 32.0; 831 } 832 } 833 return; 834 } 835 } 836 837 /* If no sync ranges detected in detailed timing table, we 838 * derive them from supported VESA modes. 839 */ 840 841 for(i = 0; i < 12; i++) { 842 if(myhtiming[i].whichone == 1) temp = ddc->timings1.t1; 843 else temp = ddc->timings1.t2; 844 if(temp & myhtiming[i].mask) { 845 if((i == 0) || (myhlow > myhtiming[i].rate)) 846 myhlow = myhtiming[i].rate; 847 } 848 if(myhtiming[11-i].whichone == 1) temp = ddc->timings1.t1; 849 else temp = ddc->timings1.t2; 850 if(temp & myhtiming[11-i].mask) { 851 if((i == 0) || (myhhigh < myhtiming[11-i].rate)) 852 myhhigh = myhtiming[11-i].rate; 853 } 854 } 855 856 for(i = 0; i < STD_TIMINGS; i++) { 857 if(ddc->timings2[i].hsize > 256) { 858 htest = ddc->timings2[i].refresh * 1.05 * ddc->timings2[i].vsize / 1000.0; 859 if(htest < myhlow) myhlow = htest; 860 if(htest > myhhigh) myhhigh = htest; 861 } 862 } 863 864 if((myhhigh > 0.0) && (myhlow > 0.0)) { 865 mon->nHsync = 1; 866 mon->hsync[0].lo = myhlow - 0.1; 867 mon->hsync[0].hi = myhhigh; 868 } 869 870 871 } else { /* Vrefresh */ 872 873 for(i = 0; i < 4; i++) { 874 if(ddc->det_mon[i].type == DS_RANGES) { 875 mon->nVrefresh = 1; 876 mon->vrefresh[0].lo = ddc->det_mon[i].section.ranges.min_v; 877 mon->vrefresh[0].hi = ddc->det_mon[i].section.ranges.max_v; 878 if(mon->vrefresh[0].lo > 72 || mon->vrefresh[0].hi < 70) { 879 if(ddc->timings1.t1 & 0x80) { 880 mon->nVrefresh++; 881 mon->vrefresh[1].lo = 71; 882 mon->vrefresh[1].hi = 71; 883 } 884 } 885 return; 886 } 887 } 888 889 for(i = 0; i < 11; i++) { 890 if(myvtiming[i].whichone == 1) temp = ddc->timings1.t1; 891 else temp = ddc->timings1.t2; 892 if(temp & myvtiming[i].mask) { 893 if((i == 0) || (myvlow > myvtiming[i].rate)) 894 myvlow = myvtiming[i].rate; 895 } 896 if(myvtiming[10-i].whichone == 1) temp = ddc->timings1.t1; 897 else temp = ddc->timings1.t2; 898 if(temp & myvtiming[10-i].mask) { 899 if((i == 0) || (myvhigh < myvtiming[10-i].rate)) 900 myvhigh = myvtiming[10-i].rate; 901 } 902 } 903 904 for(i = 0; i < STD_TIMINGS; i++) { 905 if(ddc->timings2[i].hsize > 256) { 906 vtest = ddc->timings2[i].refresh; 907 if(vtest < myvlow) myvlow = vtest; 908 if(vtest > myvhigh) myvhigh = vtest; 909 } 910 } 911 912 if((myvhigh > 0) && (myvlow > 0)) { 913 mon->nVrefresh = 1; 914 mon->vrefresh[0].lo = myvlow; 915 mon->vrefresh[0].hi = myvhigh; 916 } 917 918 } 919} 920 921static Bool 922SiSAllowSyncOverride(SISPtr pSiS, Bool fromDDC) 923{ 924 if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return FALSE; 925 926#ifdef SISDUALHEAD 927 if(pSiS->DualHeadMode) { 928 if(pSiS->SecondHead) { 929 if((pSiS->VBFlags & CRT1_LCDA) && (!fromDDC)) return TRUE; 930 } else { 931 if((pSiS->VBFlags & CRT2_TV) || 932 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC))) return TRUE; 933 } 934 return FALSE; 935 } 936#endif 937 938#ifdef SISMERGED 939 if(pSiS->MergedFB) { 940 if((pSiS->VBFlags & CRT1_LCDA) && (!fromDDC)) return TRUE; 941 return FALSE; 942 } 943#endif 944 945 if(!(pSiS->VBFlags & DISPTYPE_CRT1)) { 946 if( (pSiS->VBFlags & CRT2_TV) || 947 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC)) ) return TRUE; 948 } else if((pSiS->VBFlags & CRT1_LCDA) && (!fromDDC)) return TRUE; 949 950 return FALSE; 951} 952 953static Bool 954SiSCheckForH(float hsync, MonPtr monitor) 955{ 956 int i; 957 for(i = 0; i < monitor->nHsync; i++) { 958 if((hsync > monitor->hsync[i].lo * (1.0 - SYNC_TOLERANCE)) && 959 (hsync < monitor->hsync[i].hi * (1.0 + SYNC_TOLERANCE))) 960 break; 961 } 962 if(i == monitor->nHsync) return FALSE; 963 return TRUE; 964} 965 966static Bool 967SiSCheckForV(float vrefresh, MonPtr monitor) 968{ 969 int i; 970 for(i = 0; i < monitor->nVrefresh; i++) { 971 if((vrefresh > monitor->vrefresh[i].lo * (1.0 - SYNC_TOLERANCE)) && 972 (vrefresh < monitor->vrefresh[i].hi * (1.0 + SYNC_TOLERANCE))) 973 break; 974 } 975 if(i == monitor->nVrefresh) return FALSE; 976 return TRUE; 977} 978 979static Bool 980CheckAndOverruleH(ScrnInfoPtr pScrn, MonPtr monitor) 981{ 982 DisplayModePtr mode = monitor->Modes; 983 float mymin = 30.0, mymax = 80.0, hsync; 984 Bool doit = FALSE; 985 986 for(hsync = mymin; hsync <= mymax; hsync += .5) { 987 if(!SiSCheckForH(hsync, monitor)) doit = TRUE; 988 } 989 990 if(mode) { 991 do { 992 if(mode->type & M_T_BUILTIN) { 993 hsync = (float)mode->Clock / (float)mode->HTotal; 994 if(!SiSCheckForH(hsync, monitor)) { 995 doit = TRUE; 996 if(hsync < mymin) mymin = hsync; 997 if(hsync > mymax) mymax = hsync; 998 } 999 } 1000 } while((mode = mode->next)); 1001 } 1002 1003 if(doit) { 1004 monitor->nHsync = 1; 1005 monitor->hsync[0].lo = mymin; 1006 monitor->hsync[0].hi = mymax; 1007 return TRUE; 1008 } 1009 1010 return FALSE; 1011} 1012 1013static Bool 1014CheckAndOverruleV(ScrnInfoPtr pScrn, MonPtr monitor) 1015{ 1016 DisplayModePtr mode = monitor->Modes; 1017 float mymin = 59.0, mymax = 61.0, vrefresh; 1018 Bool doit = FALSE, ret = FALSE; 1019 1020 for(vrefresh = mymin; vrefresh <= mymax; vrefresh += 1.0) { 1021 if(!SiSCheckForV(vrefresh, monitor)) doit = TRUE; 1022 } 1023 1024 if(mode) { 1025 do { 1026 if(mode->type & M_T_BUILTIN) { 1027 vrefresh = mode->Clock * 1000.0 / (mode->HTotal * mode->VTotal); 1028 if(mode->Flags & V_INTERLACE) vrefresh *= 2.0; 1029 if(mode->Flags & V_DBLSCAN) vrefresh /= 2.0; 1030 if(!SiSCheckForH(vrefresh, monitor)) { 1031 doit = TRUE; 1032 if(vrefresh < mymin) mymin = vrefresh; 1033 if(vrefresh > mymax) mymax = vrefresh; 1034 } 1035 } 1036 } while((mode = mode->next)); 1037 } 1038 1039 if(doit) { 1040 monitor->nVrefresh = 1; 1041 monitor->vrefresh[0].lo = mymin; 1042 monitor->vrefresh[0].hi = mymax; 1043 ret = TRUE; 1044 } 1045 1046 /* special for 640x400/320x200/@70Hz (VGA/IBM 720x480) */ 1047 if( (!SiSCheckForV(71, monitor)) && 1048 (monitor->nVrefresh < MAX_VREFRESH) ) { 1049 monitor->vrefresh[monitor->nVrefresh].lo = 71; 1050 monitor->vrefresh[monitor->nVrefresh].hi = 71; 1051 monitor->nVrefresh++; 1052 ret = TRUE; 1053 } 1054 return ret; 1055} 1056 1057/* Some helper functions for MergedFB mode */ 1058 1059#ifdef SISMERGED 1060 1061/* Helper function for CRT2 monitor vrefresh/hsync options 1062 * (Code base from mga driver) 1063 */ 1064static int 1065SiSStrToRanges(range *r, char *s, int max) 1066{ 1067 float num = 0.0; 1068 int rangenum = 0; 1069 Bool gotdash = FALSE; 1070 Bool nextdash = FALSE; 1071 char *strnum = NULL; 1072 do { 1073 switch(*s) { 1074 case '0': 1075 case '1': 1076 case '2': 1077 case '3': 1078 case '4': 1079 case '5': 1080 case '6': 1081 case '7': 1082 case '8': 1083 case '9': 1084 case '.': 1085 if(strnum == NULL) { 1086 strnum = s; 1087 gotdash = nextdash; 1088 nextdash = FALSE; 1089 } 1090 break; 1091 case '-': 1092 case ' ': 1093 case 0: 1094 if(strnum == NULL) break; 1095 sscanf(strnum, "%f", &num); 1096 strnum = NULL; 1097 if(gotdash) { 1098 r[rangenum - 1].hi = num; 1099 } else { 1100 r[rangenum].lo = num; 1101 r[rangenum].hi = num; 1102 rangenum++; 1103 } 1104 if(*s == '-') nextdash = (rangenum != 0); 1105 else if(rangenum >= max) return rangenum; 1106 break; 1107 default: 1108 return 0; 1109 } 1110 1111 } while(*(s++) != 0); 1112 1113 return rangenum; 1114} 1115 1116/* Copy and link two modes (i, j) for mergedfb mode 1117 * (Code base taken from mga driver) 1118 * 1119 * - Copy mode i, merge j to copy of i, link the result to dest 1120 * - Link i and j in private record. 1121 * - If dest is NULL, return value is copy of i linked to itself. 1122 * - For mergedfb auto-config, we only check the dimension 1123 * against virtualX/Y, if they were user-provided. 1124 * - No special treatment required for CRTxxOffs. 1125 * - Provide fake dotclock in order to distinguish between similar 1126 * looking MetaModes (for RandR and VidMode extensions) 1127 * - Set unique VRefresh of dest mode for RandR 1128 */ 1129static DisplayModePtr 1130SiSCopyModeNLink(ScrnInfoPtr pScrn, DisplayModePtr dest, 1131 DisplayModePtr i, DisplayModePtr j, 1132 SiSScrn2Rel srel) 1133{ 1134 SISPtr pSiS = SISPTR(pScrn); 1135 DisplayModePtr mode; 1136 int dx = 0,dy = 0; 1137 1138 if(!((mode = xalloc(sizeof(DisplayModeRec))))) return dest; 1139 memcpy(mode, i, sizeof(DisplayModeRec)); 1140 if(!((mode->Private = xalloc(sizeof(SiSMergedDisplayModeRec))))) { 1141 xfree(mode); 1142 return dest; 1143 } 1144 ((SiSMergedDisplayModePtr)mode->Private)->CRT1 = i; 1145 ((SiSMergedDisplayModePtr)mode->Private)->CRT2 = j; 1146 ((SiSMergedDisplayModePtr)mode->Private)->CRT2Position = srel; 1147 mode->PrivSize = 0; 1148 1149 switch(srel) { 1150 case sisLeftOf: 1151 case sisRightOf: 1152 if(!(pScrn->display->virtualX)) { 1153 dx = i->HDisplay + j->HDisplay; 1154 } else { 1155 dx = min(pScrn->virtualX, i->HDisplay + j->HDisplay); 1156 } 1157 dx -= mode->HDisplay; 1158 if(!(pScrn->display->virtualY)) { 1159 dy = max(i->VDisplay, j->VDisplay); 1160 } else { 1161 dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay)); 1162 } 1163 dy -= mode->VDisplay; 1164 break; 1165 case sisAbove: 1166 case sisBelow: 1167 if(!(pScrn->display->virtualY)) { 1168 dy = i->VDisplay + j->VDisplay; 1169 } else { 1170 dy = min(pScrn->virtualY, i->VDisplay + j->VDisplay); 1171 } 1172 dy -= mode->VDisplay; 1173 if(!(pScrn->display->virtualX)) { 1174 dx = max(i->HDisplay, j->HDisplay); 1175 } else { 1176 dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay)); 1177 } 1178 dx -= mode->HDisplay; 1179 break; 1180 case sisClone: 1181 if(!(pScrn->display->virtualX)) { 1182 dx = max(i->HDisplay, j->HDisplay); 1183 } else { 1184 dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay)); 1185 } 1186 dx -= mode->HDisplay; 1187 if(!(pScrn->display->virtualY)) { 1188 dy = max(i->VDisplay, j->VDisplay); 1189 } else { 1190 dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay)); 1191 } 1192 dy -= mode->VDisplay; 1193 break; 1194 } 1195 mode->HDisplay += dx; 1196 mode->HSyncStart += dx; 1197 mode->HSyncEnd += dx; 1198 mode->HTotal += dx; 1199 mode->VDisplay += dy; 1200 mode->VSyncStart += dy; 1201 mode->VSyncEnd += dy; 1202 mode->VTotal += dy; 1203 1204 mode->type = M_T_DEFAULT; 1205#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,2,0) 1206 /* Set up as user defined (ie fake that the mode has been named in the 1207 * Modes-list in the screen section; corrects cycling with CTRL-ALT-[-+] 1208 * when source mode has not been listed there.) 1209 */ 1210 mode->type |= M_T_USERDEF; 1211#endif 1212 1213 /* Set the VRefresh field (in order to make RandR use it for the rates). We 1214 * simply set this to the refresh rate for the CRT1 mode (since CRT2 will 1215 * mostly be LCD or TV anyway). 1216 */ 1217 mode->VRefresh = SiSCalcVRate(i); 1218 1219 if( ((mode->HDisplay * ((pScrn->bitsPerPixel + 7) / 8) * mode->VDisplay) > pSiS->maxxfbmem) || 1220 (mode->HDisplay > 4088) || 1221 (mode->VDisplay > 4096) ) { 1222 1223 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1224 "Skipped \"%s\" (%dx%d), not enough video RAM or beyond hardware specs\n", 1225 mode->name, mode->HDisplay, mode->VDisplay); 1226 xfree(mode->Private); 1227 xfree(mode); 1228 1229 return dest; 1230 } 1231 1232#ifdef SISXINERAMA 1233 if(srel != sisClone) { 1234 pSiS->AtLeastOneNonClone = TRUE; 1235 } 1236#endif 1237 1238 /* Now see if the resulting mode would be discarded as a "size" by the 1239 * RandR extension, and increase its clock by 1000 in case it does. 1240 */ 1241 if(dest) { 1242 DisplayModePtr t = dest; 1243 do { 1244 if((t->HDisplay == mode->HDisplay) && 1245 (t->VDisplay == mode->VDisplay) && 1246 ((int)(t->VRefresh + .5) == (int)(mode->VRefresh + .5))) { 1247 mode->VRefresh += 1000.0; 1248 } 1249 t = t->next; 1250 } while((t) && (t != dest)); 1251 } 1252 1253 /* Provide a fake but unique DotClock in order to trick the vidmode 1254 * extension to allow selecting among a number of modes whose merged result 1255 * looks identical but consists of different modes for CRT1 and CRT2 1256 */ 1257 mode->Clock = (int)(mode->VRefresh * 1000.0); 1258 1259 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1260 "Merged \"%s\" (%dx%d) and \"%s\" (%dx%d) to %dx%d (%d)%s\n", 1261 i->name, i->HDisplay, i->VDisplay, j->name, j->HDisplay, j->VDisplay, 1262 mode->HDisplay, mode->VDisplay, (int)mode->VRefresh, 1263 (srel == sisClone) ? " (Clone)" : ""); 1264 1265 mode->next = mode; 1266 mode->prev = mode; 1267 1268 if(dest) { 1269 mode->next = dest->next; /* Insert node after "dest" */ 1270 dest->next->prev = mode; 1271 mode->prev = dest; 1272 dest->next = mode; 1273 } 1274 1275 return mode; 1276} 1277 1278/* Helper function to find a mode from a given name 1279 * (Code base taken from mga driver) 1280 */ 1281static DisplayModePtr 1282SiSGetModeFromName(char* str, DisplayModePtr i) 1283{ 1284 DisplayModePtr c = i; 1285 if(!i) return NULL; 1286 do { 1287 if(strcmp(str, c->name) == 0) return c; 1288 c = c->next; 1289 } while(c != i); 1290 return NULL; 1291} 1292 1293static DisplayModePtr 1294SiSFindWidestTallestMode(DisplayModePtr i, Bool tallest) 1295{ 1296 DisplayModePtr c = i, d = NULL; 1297 int max = 0; 1298 if(!i) return NULL; 1299 do { 1300 if(tallest) { 1301 if(c->VDisplay > max) { 1302 max = c->VDisplay; 1303 d = c; 1304 } 1305 } else { 1306 if(c->HDisplay > max) { 1307 max = c->HDisplay; 1308 d = c; 1309 } 1310 } 1311 c = c->next; 1312 } while(c != i); 1313 return d; 1314} 1315 1316static void 1317SiSFindWidestTallestCommonMode(DisplayModePtr i, DisplayModePtr j, Bool tallest, 1318 DisplayModePtr *a, DisplayModePtr *b) 1319{ 1320 DisplayModePtr c = i, d; 1321 int max = 0; 1322 Bool foundone; 1323 1324 (*a) = (*b) = NULL; 1325 1326 if(!i || !j) return; 1327 1328 do { 1329 d = j; 1330 foundone = FALSE; 1331 do { 1332 if( (c->HDisplay == d->HDisplay) && 1333 (c->VDisplay == d->VDisplay) ) { 1334 foundone = TRUE; 1335 break; 1336 } 1337 d = d->next; 1338 } while(d != j); 1339 if(foundone) { 1340 if(tallest) { 1341 if(c->VDisplay > max) { 1342 max = c->VDisplay; 1343 (*a) = c; 1344 (*b) = d; 1345 } 1346 } else { 1347 if(c->HDisplay > max) { 1348 max = c->HDisplay; 1349 (*a) = c; 1350 (*b) = d; 1351 } 1352 } 1353 } 1354 c = c->next; 1355 } while(c != i); 1356} 1357 1358static DisplayModePtr 1359SiSGenerateModeListFromLargestModes(ScrnInfoPtr pScrn, 1360 DisplayModePtr i, DisplayModePtr j, 1361 SiSScrn2Rel srel) 1362{ 1363#ifdef SISXINERAMA 1364 SISPtr pSiS = SISPTR(pScrn); 1365#endif 1366 DisplayModePtr mode1 = NULL; 1367 DisplayModePtr mode2 = NULL; 1368 DisplayModePtr mode3 = NULL; 1369 DisplayModePtr mode4 = NULL; 1370 DisplayModePtr result = NULL; 1371 1372#ifdef SISXINERAMA 1373 pSiS->AtLeastOneNonClone = FALSE; 1374#endif 1375 1376 /* Now build a default list of MetaModes. 1377 * - Non-clone: If the user enabled NonRectangular, we use the 1378 * largest mode for each CRT1 and CRT2. If not, we use the largest 1379 * common mode for CRT1 and CRT2 (if available). Additionally, and 1380 * regardless if the above, we produce a clone mode consisting of 1381 * the largest common mode (if available) in order to use DGA. 1382 * - Clone: If the (global) CRT2Position is Clone, we use the 1383 * largest common mode if available, otherwise the first two modes 1384 * in each list. 1385 */ 1386 1387 switch(srel) { 1388 case sisLeftOf: 1389 case sisRightOf: 1390 mode1 = SiSFindWidestTallestMode(i, FALSE); 1391 mode2 = SiSFindWidestTallestMode(j, FALSE); 1392 SiSFindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); 1393 break; 1394 case sisAbove: 1395 case sisBelow: 1396 mode1 = SiSFindWidestTallestMode(i, TRUE); 1397 mode2 = SiSFindWidestTallestMode(j, TRUE); 1398 SiSFindWidestTallestCommonMode(i, j, TRUE, &mode3, &mode4); 1399 break; 1400 case sisClone: 1401 SiSFindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); 1402 if(mode3 && mode4) { 1403 mode1 = mode3; 1404 mode2 = mode4; 1405 } else { 1406 mode1 = i; 1407 mode2 = j; 1408 } 1409 } 1410 1411 if(srel != sisClone) { 1412 if(mode3 && mode4 && !pSiS->NonRect) { 1413 mode1 = mode3; 1414 mode2 = mode2; 1415 } 1416 } 1417 1418 if(mode1 && mode2) { 1419 result = SiSCopyModeNLink(pScrn, result, mode1, mode2, srel); 1420 } 1421 1422 if(srel != sisClone) { 1423 if(mode3 && mode4) { 1424 result = SiSCopyModeNLink(pScrn, result, mode3, mode4, sisClone); 1425 } 1426 } 1427 1428 return result; 1429} 1430 1431/* Generate the merged-fb mode modelist 1432 * (Taken from mga driver) 1433 */ 1434static DisplayModePtr 1435SiSGenerateModeListFromMetaModes(ScrnInfoPtr pScrn, char* str, 1436 DisplayModePtr i, DisplayModePtr j, 1437 SiSScrn2Rel srel) 1438{ 1439#ifdef SISXINERAMA 1440 SISPtr pSiS = SISPTR(pScrn); 1441#endif 1442 char* strmode = str; 1443 char modename[256]; 1444 Bool gotdash = FALSE; 1445 char gotsep = 0; 1446 SiSScrn2Rel sr; 1447 DisplayModePtr mode1 = NULL; 1448 DisplayModePtr mode2 = NULL; 1449 DisplayModePtr result = NULL; 1450 int myslen; 1451 1452#ifdef SISXINERAMA 1453 pSiS->AtLeastOneNonClone = FALSE; 1454#endif 1455 1456 do { 1457 switch(*str) { 1458 case 0: 1459 case '-': 1460 case '+': 1461 case ' ': 1462 case ',': 1463 case ';': 1464 if(strmode != str) { 1465 1466 myslen = str - strmode; 1467 if(myslen > 255) myslen = 255; 1468 strncpy(modename, strmode, myslen); 1469 modename[myslen] = 0; 1470 1471 if(gotdash) { 1472 if(mode1 == NULL) { 1473 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1474 "Error parsing MetaModes parameter\n"); 1475 return NULL; 1476 } 1477 mode2 = SiSGetModeFromName(modename, j); 1478 if(!mode2) { 1479 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1480 "Mode \"%s\" is not a supported mode for CRT2\n", modename); 1481 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1482 "\t(Skipping metamode \"%s%c%s\")\n", mode1->name, gotsep, modename); 1483 mode1 = NULL; 1484 gotsep = 0; 1485 } 1486 } else { 1487 mode1 = SiSGetModeFromName(modename, i); 1488 if(!mode1) { 1489 char* tmps = str; 1490 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1491 "Mode \"%s\" is not a supported mode for CRT1\n", modename); 1492 while(*tmps == ' ' || *tmps == ';') tmps++; 1493 /* skip the next mode */ 1494 if(*tmps == '-' || *tmps == '+' || *tmps == ',') { 1495 tmps++; 1496 /* skip spaces */ 1497 while(*tmps == ' ' || *tmps == ';') tmps++; 1498 /* skip modename */ 1499 while(*tmps && *tmps != ' ' && *tmps != ';' && *tmps != '-' && *tmps != '+' && *tmps != ',') tmps++; 1500 myslen = tmps - strmode; 1501 if(myslen > 255) myslen = 255; 1502 strncpy(modename,strmode,myslen); 1503 modename[myslen] = 0; 1504 str = tmps - 1; 1505 } 1506 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1507 "\t(Skipping metamode \"%s\")\n", modename); 1508 mode1 = NULL; 1509 gotsep = 0; 1510 } 1511 } 1512 gotdash = FALSE; 1513 } 1514 strmode = str + 1; 1515 gotdash |= (*str == '-' || *str == '+' || *str == ','); 1516 if (*str == '-' || *str == '+' || *str == ',') 1517 gotsep = *str; 1518 1519 if(*str != 0) break; 1520 /* Fall through otherwise */ 1521 1522 default: 1523 if(!gotdash && mode1) { 1524 sr = srel; 1525 if(gotsep == '+') sr = sisClone; 1526 if(!mode2) { 1527 mode2 = SiSGetModeFromName(mode1->name, j); 1528 sr = sisClone; 1529 } 1530 if(!mode2) { 1531 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1532 "Mode \"%s\" is not a supported mode for CRT2\n", mode1->name); 1533 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1534 "\t(Skipping metamode \"%s\")\n", modename); 1535 mode1 = NULL; 1536 } else { 1537 result = SiSCopyModeNLink(pScrn, result, mode1, mode2, sr); 1538 mode1 = NULL; 1539 mode2 = NULL; 1540 } 1541 gotsep = 0; 1542 } 1543 break; 1544 1545 } 1546 1547 } while(*(str++) != 0); 1548 1549 return result; 1550} 1551 1552static DisplayModePtr 1553SiSGenerateModeList(ScrnInfoPtr pScrn, char* str, 1554 DisplayModePtr i, DisplayModePtr j, 1555 SiSScrn2Rel srel) 1556{ 1557 SISPtr pSiS = SISPTR(pScrn); 1558 1559 if(str != NULL) { 1560 return(SiSGenerateModeListFromMetaModes(pScrn, str, i, j, srel)); 1561 } else { 1562 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1563 "No MetaModes given, linking %s modes by default\n", 1564 (srel == sisClone) ? "largest common" : 1565 (pSiS->NonRect ? 1566 (((srel == sisLeftOf) || (srel == sisRightOf)) ? "widest" : "tallest") 1567 : 1568 (((srel == sisLeftOf) || (srel == sisRightOf)) ? "widest common" : "tallest common")) ); 1569 return(SiSGenerateModeListFromLargestModes(pScrn, i, j, srel)); 1570 } 1571} 1572 1573static void 1574SiSRecalcDefaultVirtualSize(ScrnInfoPtr pScrn) 1575{ 1576 SISPtr pSiS = SISPTR(pScrn); 1577 DisplayModePtr mode, bmode; 1578 int maxh, maxv; 1579 static const char *str = "MergedFB: Virtual %s %d\n"; 1580 static const char *errstr = "Virtual %s to small for given CRT2Position offset\n"; 1581 1582 mode = bmode = pScrn->modes; 1583 maxh = maxv = 0; 1584 do { 1585 if(mode->HDisplay > maxh) maxh = mode->HDisplay; 1586 if(mode->VDisplay > maxv) maxv = mode->VDisplay; 1587 mode = mode->next; 1588 } while(mode != bmode); 1589 1590 maxh += pSiS->CRT1XOffs + pSiS->CRT2XOffs; 1591 maxv += pSiS->CRT1YOffs + pSiS->CRT2YOffs; 1592 1593 if(!(pScrn->display->virtualX)) { 1594 if(maxh > 4088) { 1595 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1596 "Virtual width with CRT2Position offset beyond hardware specs\n"); 1597 pSiS->CRT1XOffs = pSiS->CRT2XOffs = 0; 1598 maxh -= (pSiS->CRT1XOffs + pSiS->CRT2XOffs); 1599 } 1600 pScrn->virtualX = maxh; 1601 pScrn->displayWidth = maxh; 1602 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "width", maxh); 1603 } else { 1604 if(maxh < pScrn->display->virtualX) { 1605 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "width"); 1606 pSiS->CRT1XOffs = pSiS->CRT2XOffs = 0; 1607 } 1608 } 1609 1610 if(!(pScrn->display->virtualY)) { 1611 pScrn->virtualY = maxv; 1612 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "height", maxv); 1613 } else { 1614 if(maxv < pScrn->display->virtualY) { 1615 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "height"); 1616 pSiS->CRT1YOffs = pSiS->CRT2YOffs = 0; 1617 } 1618 } 1619} 1620 1621static void 1622SiSMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, SiSScrn2Rel srel) 1623{ 1624 SISPtr pSiS = SISPTR(pScrn1); 1625 MessageType from = X_DEFAULT; 1626 xf86MonPtr DDC1 = (xf86MonPtr)(pScrn1->monitor->DDC); 1627 xf86MonPtr DDC2 = (xf86MonPtr)(pScrn2->monitor->DDC); 1628 int ddcWidthmm = 0, ddcHeightmm = 0; 1629 const char *dsstr = "MergedFB: Display dimensions: (%d, %d) mm\n"; 1630 1631 /* This sets the DPI for MergedFB mode. The problem is that 1632 * this can never be exact, because the output devices may 1633 * have different dimensions. This function tries to compromise 1634 * through a few assumptions, and it just calculates an average DPI 1635 * value for both monitors. 1636 */ 1637 1638 /* Given DisplaySize should regard BOTH monitors */ 1639 pScrn1->widthmm = pScrn1->monitor->widthmm; 1640 pScrn1->heightmm = pScrn1->monitor->heightmm; 1641 1642 /* Get DDC display size; if only either CRT1 or CRT2 provided these, 1643 * assume equal dimensions for both, otherwise add dimensions 1644 */ 1645 if( (DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) && 1646 (DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0)) ) { 1647 ddcWidthmm = max(DDC1->features.hsize, DDC2->features.hsize) * 10; 1648 ddcHeightmm = max(DDC1->features.vsize, DDC2->features.vsize) * 10; 1649 switch(srel) { 1650 case sisLeftOf: 1651 case sisRightOf: 1652 ddcWidthmm = (DDC1->features.hsize + DDC2->features.hsize) * 10; 1653 break; 1654 case sisAbove: 1655 case sisBelow: 1656 ddcHeightmm = (DDC1->features.vsize + DDC2->features.vsize) * 10; 1657 default: 1658 break; 1659 } 1660 } else if(DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) { 1661 ddcWidthmm = DDC1->features.hsize * 10; 1662 ddcHeightmm = DDC1->features.vsize * 10; 1663 switch(srel) { 1664 case sisLeftOf: 1665 case sisRightOf: 1666 ddcWidthmm *= 2; 1667 break; 1668 case sisAbove: 1669 case sisBelow: 1670 ddcHeightmm *= 2; 1671 default: 1672 break; 1673 } 1674 } else if(DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0) ) { 1675 ddcWidthmm = DDC2->features.hsize * 10; 1676 ddcHeightmm = DDC2->features.vsize * 10; 1677 switch(srel) { 1678 case sisLeftOf: 1679 case sisRightOf: 1680 ddcWidthmm *= 2; 1681 break; 1682 case sisAbove: 1683 case sisBelow: 1684 ddcHeightmm *= 2; 1685 default: 1686 break; 1687 } 1688 } 1689 1690 if(monitorResolution > 0) { 1691 1692 /* Set command line given values (overrules given options) */ 1693 pScrn1->xDpi = monitorResolution; 1694 pScrn1->yDpi = monitorResolution; 1695 from = X_CMDLINE; 1696 1697 } else if(pSiS->MergedFBXDPI) { 1698 1699 /* Set option-wise given values (overrule DisplaySize) */ 1700 pScrn1->xDpi = pSiS->MergedFBXDPI; 1701 pScrn1->yDpi = pSiS->MergedFBYDPI; 1702 from = X_CONFIG; 1703 1704 } else if(pScrn1->widthmm > 0 || pScrn1->heightmm > 0) { 1705 1706 /* Set values calculated from given DisplaySize */ 1707 from = X_CONFIG; 1708 if(pScrn1->widthmm > 0) { 1709 pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm); 1710 } 1711 if(pScrn1->heightmm > 0) { 1712 pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm); 1713 } 1714 xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, pScrn1->widthmm, pScrn1->heightmm); 1715 1716 } else if(ddcWidthmm && ddcHeightmm) { 1717 1718 /* Set values from DDC-provided display size */ 1719 from = X_PROBED; 1720 xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, ddcWidthmm, ddcHeightmm ); 1721 pScrn1->widthmm = ddcWidthmm; 1722 pScrn1->heightmm = ddcHeightmm; 1723 if(pScrn1->widthmm > 0) { 1724 pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm); 1725 } 1726 if(pScrn1->heightmm > 0) { 1727 pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm); 1728 } 1729 1730 } else { 1731 1732 pScrn1->xDpi = pScrn1->yDpi = DEFAULT_DPI; 1733 1734 } 1735 1736 /* Sanity check */ 1737 if(pScrn1->xDpi > 0 && pScrn1->yDpi <= 0) 1738 pScrn1->yDpi = pScrn1->xDpi; 1739 if(pScrn1->yDpi > 0 && pScrn1->xDpi <= 0) 1740 pScrn1->xDpi = pScrn1->yDpi; 1741 1742 pScrn2->xDpi = pScrn1->xDpi; 1743 pScrn2->yDpi = pScrn1->yDpi; 1744 1745 xf86DrvMsg(pScrn1->scrnIndex, from, "MergedFB: DPI set to (%d, %d)\n", 1746 pScrn1->xDpi, pScrn1->yDpi); 1747} 1748 1749/* Pseudo-Xinerama extension for MergedFB mode */ 1750#ifdef SISXINERAMA 1751 1752static void 1753SiSUpdateXineramaScreenInfo(ScrnInfoPtr pScrn1) 1754{ 1755 SISPtr pSiS = SISPTR(pScrn1); 1756 int crt1scrnnum = 0, crt2scrnnum = 1; 1757 int x1=0, x2=0, y1=0, y2=0, h1=0, h2=0, w1=0, w2=0; 1758 int realvirtX, realvirtY; 1759 DisplayModePtr currentMode, firstMode; 1760 Bool infochanged = FALSE; 1761 Bool usenonrect = pSiS->NonRect; 1762 const char *rectxine = "\t... setting up rectangular Xinerama layout\n"; 1763 1764 pSiS->MBXNR1XMAX = pSiS->MBXNR1YMAX = pSiS->MBXNR2XMAX = pSiS->MBXNR2YMAX = 65536; 1765 pSiS->HaveNonRect = pSiS->HaveOffsRegions = FALSE; 1766 1767 if(!pSiS->MergedFB) return; 1768 1769 if(SiSnoPanoramiXExtension) return; 1770 1771 if(!SiSXineramadataPtr) return; 1772 1773 if(pSiS->CRT2IsScrn0) { 1774 crt1scrnnum = 1; 1775 crt2scrnnum = 0; 1776 } 1777 1778 /* Attention: Usage of RandR may lead to virtual X and Y dimensions 1779 * actually smaller than our MetaModes. To avoid this, we calculate 1780 * the maxCRT fields here (and not somewhere else, like in CopyNLink) 1781 * 1782 * *** Note: RandR is disabled if one of CRTxxOffs is non-zero. 1783 */ 1784 1785 /* "Real" virtual: Virtual without the Offset */ 1786 realvirtX = pScrn1->virtualX - pSiS->CRT1XOffs - pSiS->CRT2XOffs; 1787 realvirtY = pScrn1->virtualY - pSiS->CRT1YOffs - pSiS->CRT2YOffs; 1788 1789 if((pSiS->SiSXineramaVX != pScrn1->virtualX) || (pSiS->SiSXineramaVY != pScrn1->virtualY)) { 1790 1791 if(!(pScrn1->modes)) return; 1792 1793 pSiS->maxCRT1_X1 = pSiS->maxCRT1_X2 = 0; 1794 pSiS->maxCRT1_Y1 = pSiS->maxCRT1_Y2 = 0; 1795 pSiS->maxCRT2_X1 = pSiS->maxCRT2_X2 = 0; 1796 pSiS->maxCRT2_Y1 = pSiS->maxCRT2_Y2 = 0; 1797 pSiS->maxClone_X1 = pSiS->maxClone_X2 = 0; 1798 pSiS->maxClone_Y1 = pSiS->maxClone_Y2 = 0; 1799 1800 currentMode = firstMode = pScrn1->modes; 1801 1802 do { 1803 1804 DisplayModePtr p = currentMode->next; 1805 DisplayModePtr i = ((SiSMergedDisplayModePtr)currentMode->Private)->CRT1; 1806 DisplayModePtr j = ((SiSMergedDisplayModePtr)currentMode->Private)->CRT2; 1807 SiSScrn2Rel srel = ((SiSMergedDisplayModePtr)currentMode->Private)->CRT2Position; 1808 1809 if((currentMode->HDisplay <= realvirtX) && (currentMode->VDisplay <= realvirtY) && 1810 (i->HDisplay <= realvirtX) && (j->HDisplay <= realvirtX) && 1811 (i->VDisplay <= realvirtY) && (j->VDisplay <= realvirtY)) { 1812 1813 if(srel != sisClone) { 1814 if(pSiS->maxCRT1_X1 == i->HDisplay) { 1815 if(pSiS->maxCRT1_X2 < j->HDisplay) { 1816 pSiS->maxCRT1_X2 = j->HDisplay; /* Widest CRT2 mode displayed with widest CRT1 mode */ 1817 } 1818 } else if(pSiS->maxCRT1_X1 < i->HDisplay) { 1819 pSiS->maxCRT1_X1 = i->HDisplay; /* Widest CRT1 mode */ 1820 pSiS->maxCRT1_X2 = j->HDisplay; 1821 } 1822 if(pSiS->maxCRT2_X2 == j->HDisplay) { 1823 if(pSiS->maxCRT2_X1 < i->HDisplay) { 1824 pSiS->maxCRT2_X1 = i->HDisplay; /* Widest CRT1 mode displayed with widest CRT2 mode */ 1825 } 1826 } else if(pSiS->maxCRT2_X2 < j->HDisplay) { 1827 pSiS->maxCRT2_X2 = j->HDisplay; /* Widest CRT2 mode */ 1828 pSiS->maxCRT2_X1 = i->HDisplay; 1829 } 1830 if(pSiS->maxCRT1_Y1 == i->VDisplay) { /* Same as above, but tallest instead of widest */ 1831 if(pSiS->maxCRT1_Y2 < j->VDisplay) { 1832 pSiS->maxCRT1_Y2 = j->VDisplay; 1833 } 1834 } else if(pSiS->maxCRT1_Y1 < i->VDisplay) { 1835 pSiS->maxCRT1_Y1 = i->VDisplay; 1836 pSiS->maxCRT1_Y2 = j->VDisplay; 1837 } 1838 if(pSiS->maxCRT2_Y2 == j->VDisplay) { 1839 if(pSiS->maxCRT2_Y1 < i->VDisplay) { 1840 pSiS->maxCRT2_Y1 = i->VDisplay; 1841 } 1842 } else if(pSiS->maxCRT2_Y2 < j->VDisplay) { 1843 pSiS->maxCRT2_Y2 = j->VDisplay; 1844 pSiS->maxCRT2_Y1 = i->VDisplay; 1845 } 1846 } else { 1847 if(pSiS->maxClone_X1 < i->HDisplay) { 1848 pSiS->maxClone_X1 = i->HDisplay; 1849 } 1850 if(pSiS->maxClone_X2 < j->HDisplay) { 1851 pSiS->maxClone_X2 = j->HDisplay; 1852 } 1853 if(pSiS->maxClone_Y1 < i->VDisplay) { 1854 pSiS->maxClone_Y1 = i->VDisplay; 1855 } 1856 if(pSiS->maxClone_Y2 < j->VDisplay) { 1857 pSiS->maxClone_Y2 = j->VDisplay; 1858 } 1859 } 1860 } 1861 currentMode = p; 1862 1863 } while((currentMode) && (currentMode != firstMode)); 1864 1865 pSiS->SiSXineramaVX = pScrn1->virtualX; 1866 pSiS->SiSXineramaVY = pScrn1->virtualY; 1867 infochanged = TRUE; 1868 1869 } 1870 1871 if((usenonrect) && (pSiS->CRT2Position != sisClone) && pSiS->maxCRT1_X1) { 1872 switch(pSiS->CRT2Position) { 1873 case sisLeftOf: 1874 case sisRightOf: 1875 if((pSiS->maxCRT1_Y1 != realvirtY) && (pSiS->maxCRT2_Y2 != realvirtY)) { 1876 usenonrect = FALSE; 1877 } 1878 break; 1879 case sisAbove: 1880 case sisBelow: 1881 if((pSiS->maxCRT1_X1 != realvirtX) && (pSiS->maxCRT2_X2 != realvirtX)) { 1882 usenonrect = FALSE; 1883 } 1884 break; 1885 case sisClone: 1886 break; 1887 } 1888 if(infochanged && !usenonrect) { 1889 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 1890 "Virtual screen size does not match maximum display modes...\n"); 1891 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, rectxine); 1892 1893 } 1894 } else if(infochanged && usenonrect) { 1895 usenonrect = FALSE; 1896 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 1897 "Only clone modes available for this virtual screen size...\n"); 1898 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, rectxine); 1899 } 1900 1901 if(pSiS->maxCRT1_X1) { /* Means we have at least one non-clone mode */ 1902 switch(pSiS->CRT2Position) { 1903 case sisLeftOf: 1904 x1 = min(pSiS->maxCRT1_X2, pScrn1->virtualX - pSiS->maxCRT1_X1); 1905 if(x1 < 0) x1 = 0; 1906 y1 = pSiS->CRT1YOffs; 1907 w1 = pScrn1->virtualX - x1; 1908 h1 = realvirtY; 1909 if((usenonrect) && (pSiS->maxCRT1_Y1 != realvirtY)) { 1910 h1 = pSiS->MBXNR1YMAX = pSiS->maxCRT1_Y1; 1911 pSiS->NonRectDead.x0 = x1; 1912 pSiS->NonRectDead.x1 = x1 + w1 - 1; 1913 pSiS->NonRectDead.y0 = y1 + h1; 1914 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 1915 pSiS->HaveNonRect = TRUE; 1916 } 1917 x2 = 0; 1918 y2 = pSiS->CRT2YOffs; 1919 w2 = max(pSiS->maxCRT2_X2, pScrn1->virtualX - pSiS->maxCRT2_X1); 1920 if(w2 > pScrn1->virtualX) w2 = pScrn1->virtualX; 1921 h2 = realvirtY; 1922 if((usenonrect) && (pSiS->maxCRT2_Y2 != realvirtY)) { 1923 h2 = pSiS->MBXNR2YMAX = pSiS->maxCRT2_Y2; 1924 pSiS->NonRectDead.x0 = x2; 1925 pSiS->NonRectDead.x1 = x2 + w2 - 1; 1926 pSiS->NonRectDead.y0 = y2 + h2; 1927 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 1928 pSiS->HaveNonRect = TRUE; 1929 } 1930 break; 1931 case sisRightOf: 1932 x1 = 0; 1933 y1 = pSiS->CRT1YOffs; 1934 w1 = max(pSiS->maxCRT1_X1, pScrn1->virtualX - pSiS->maxCRT1_X2); 1935 if(w1 > pScrn1->virtualX) w1 = pScrn1->virtualX; 1936 h1 = realvirtY; 1937 if((usenonrect) && (pSiS->maxCRT1_Y1 != realvirtY)) { 1938 h1 = pSiS->MBXNR1YMAX = pSiS->maxCRT1_Y1; 1939 pSiS->NonRectDead.x0 = x1; 1940 pSiS->NonRectDead.x1 = x1 + w1 - 1; 1941 pSiS->NonRectDead.y0 = y1 + h1; 1942 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 1943 pSiS->HaveNonRect = TRUE; 1944 } 1945 x2 = min(pSiS->maxCRT2_X1, pScrn1->virtualX - pSiS->maxCRT2_X2); 1946 if(x2 < 0) x2 = 0; 1947 y2 = pSiS->CRT2YOffs; 1948 w2 = pScrn1->virtualX - x2; 1949 h2 = realvirtY; 1950 if((usenonrect) && (pSiS->maxCRT2_Y2 != realvirtY)) { 1951 h2 = pSiS->MBXNR2YMAX = pSiS->maxCRT2_Y2; 1952 pSiS->NonRectDead.x0 = x2; 1953 pSiS->NonRectDead.x1 = x2 + w2 - 1; 1954 pSiS->NonRectDead.y0 = y2 + h2; 1955 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 1956 pSiS->HaveNonRect = TRUE; 1957 } 1958 break; 1959 case sisAbove: 1960 x1 = pSiS->CRT1XOffs; 1961 y1 = min(pSiS->maxCRT1_Y2, pScrn1->virtualY - pSiS->maxCRT1_Y1); 1962 if(y1 < 0) y1 = 0; 1963 w1 = realvirtX; 1964 h1 = pScrn1->virtualY - y1; 1965 if((usenonrect) && (pSiS->maxCRT1_X1 != realvirtX)) { 1966 w1 = pSiS->MBXNR1XMAX = pSiS->maxCRT1_X1; 1967 pSiS->NonRectDead.x0 = x1 + w1; 1968 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 1969 pSiS->NonRectDead.y0 = y1; 1970 pSiS->NonRectDead.y1 = y1 + h1 - 1; 1971 pSiS->HaveNonRect = TRUE; 1972 } 1973 x2 = pSiS->CRT2XOffs; 1974 y2 = 0; 1975 w2 = realvirtX; 1976 h2 = max(pSiS->maxCRT2_Y2, pScrn1->virtualY - pSiS->maxCRT2_Y1); 1977 if(h2 > pScrn1->virtualY) h2 = pScrn1->virtualY; 1978 if((usenonrect) && (pSiS->maxCRT2_X2 != realvirtX)) { 1979 w2 = pSiS->MBXNR2XMAX = pSiS->maxCRT2_X2; 1980 pSiS->NonRectDead.x0 = x2 + w2; 1981 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 1982 pSiS->NonRectDead.y0 = y2; 1983 pSiS->NonRectDead.y1 = y2 + h2 - 1; 1984 pSiS->HaveNonRect = TRUE; 1985 } 1986 break; 1987 case sisBelow: 1988 x1 = pSiS->CRT1XOffs; 1989 y1 = 0; 1990 w1 = realvirtX; 1991 h1 = max(pSiS->maxCRT1_Y1, pScrn1->virtualY - pSiS->maxCRT1_Y2); 1992 if(h1 > pScrn1->virtualY) h1 = pScrn1->virtualY; 1993 if((usenonrect) && (pSiS->maxCRT1_X1 != realvirtX)) { 1994 w1 = pSiS->MBXNR1XMAX = pSiS->maxCRT1_X1; 1995 pSiS->NonRectDead.x0 = x1 + w1; 1996 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 1997 pSiS->NonRectDead.y0 = y1; 1998 pSiS->NonRectDead.y1 = y1 + h1 - 1; 1999 pSiS->HaveNonRect = TRUE; 2000 } 2001 x2 = pSiS->CRT2XOffs; 2002 y2 = min(pSiS->maxCRT2_Y1, pScrn1->virtualY - pSiS->maxCRT2_Y2); 2003 if(y2 < 0) y2 = 0; 2004 w2 = realvirtX; 2005 h2 = pScrn1->virtualY - y2; 2006 if((usenonrect) && (pSiS->maxCRT2_X2 != realvirtX)) { 2007 w2 = pSiS->MBXNR2XMAX = pSiS->maxCRT2_X2; 2008 pSiS->NonRectDead.x0 = x2 + w2; 2009 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 2010 pSiS->NonRectDead.y0 = y2; 2011 pSiS->NonRectDead.y1 = y2 + h2 - 1; 2012 pSiS->HaveNonRect = TRUE; 2013 } 2014 default: 2015 break; 2016 } 2017 2018 switch(pSiS->CRT2Position) { 2019 case sisLeftOf: 2020 case sisRightOf: 2021 if(pSiS->CRT1YOffs) { 2022 pSiS->OffDead1.x0 = x1; 2023 pSiS->OffDead1.x1 = x1 + w1 - 1; 2024 pSiS->OffDead1.y0 = 0; 2025 pSiS->OffDead1.y1 = y1 - 1; 2026 pSiS->OffDead2.x0 = x2; 2027 pSiS->OffDead2.x1 = x2 + w2 - 1; 2028 pSiS->OffDead2.y0 = y2 + h2; 2029 pSiS->OffDead2.y1 = pScrn1->virtualY - 1; 2030 pSiS->HaveOffsRegions = TRUE; 2031 } else if(pSiS->CRT2YOffs) { 2032 pSiS->OffDead1.x0 = x2; 2033 pSiS->OffDead1.x1 = x2 + w2 - 1; 2034 pSiS->OffDead1.y0 = 0; 2035 pSiS->OffDead1.y1 = y2 - 1; 2036 pSiS->OffDead2.x0 = x1; 2037 pSiS->OffDead2.x1 = x1 + w1 - 1; 2038 pSiS->OffDead2.y0 = y1 + h1; 2039 pSiS->OffDead2.y1 = pScrn1->virtualY - 1; 2040 pSiS->HaveOffsRegions = TRUE; 2041 } 2042 break; 2043 case sisAbove: 2044 case sisBelow: 2045 if(pSiS->CRT1XOffs) { 2046 pSiS->OffDead1.x0 = x2 + w2; 2047 pSiS->OffDead1.x1 = pScrn1->virtualX - 1; 2048 pSiS->OffDead1.y0 = y2; 2049 pSiS->OffDead1.y1 = y2 + h2 - 1; 2050 pSiS->OffDead2.x0 = 0; 2051 pSiS->OffDead2.x1 = x1 - 1; 2052 pSiS->OffDead2.y0 = y1; 2053 pSiS->OffDead2.y1 = y1 + h1 - 1; 2054 pSiS->HaveOffsRegions = TRUE; 2055 } else if(pSiS->CRT2XOffs) { 2056 pSiS->OffDead1.x0 = x1 + w1; 2057 pSiS->OffDead1.x1 = pScrn1->virtualX - 1; 2058 pSiS->OffDead1.y0 = y1; 2059 pSiS->OffDead1.y1 = y1 + h1 - 1; 2060 pSiS->OffDead2.x0 = 0; 2061 pSiS->OffDead2.x1 = x2 - 1; 2062 pSiS->OffDead2.y0 = y2; 2063 pSiS->OffDead2.y1 = y2 + h2 - 1; 2064 pSiS->HaveOffsRegions = TRUE; 2065 } 2066 default: 2067 break; 2068 } 2069 2070 } else { /* Only clone-modes left */ 2071 2072 x1 = x2 = 0; 2073 y1 = y2 = 0; 2074 w1 = w2 = max(pSiS->maxClone_X1, pSiS->maxClone_X2); 2075 h1 = h2 = max(pSiS->maxClone_Y1, pSiS->maxClone_Y2); 2076 2077 } 2078 2079 SiSXineramadataPtr[crt1scrnnum].x = x1; 2080 SiSXineramadataPtr[crt1scrnnum].y = y1; 2081 SiSXineramadataPtr[crt1scrnnum].width = w1; 2082 SiSXineramadataPtr[crt1scrnnum].height = h1; 2083 SiSXineramadataPtr[crt2scrnnum].x = x2; 2084 SiSXineramadataPtr[crt2scrnnum].y = y2; 2085 SiSXineramadataPtr[crt2scrnnum].width = w2; 2086 SiSXineramadataPtr[crt2scrnnum].height = h2; 2087 2088 if(infochanged) { 2089 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2090 "Pseudo-Xinerama: CRT1 (Screen %d) (%d,%d)-(%d,%d)\n", 2091 crt1scrnnum, x1, y1, w1+x1-1, h1+y1-1); 2092 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2093 "Pseudo-Xinerama: CRT2 (Screen %d) (%d,%d)-(%d,%d)\n", 2094 crt2scrnnum, x2, y2, w2+x2-1, h2+y2-1); 2095 if(pSiS->HaveNonRect) { 2096 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2097 "Pseudo-Xinerama: Inaccessible area (%d,%d)-(%d,%d)\n", 2098 pSiS->NonRectDead.x0, pSiS->NonRectDead.y0, 2099 pSiS->NonRectDead.x1, pSiS->NonRectDead.y1); 2100 } 2101 if(pSiS->HaveOffsRegions) { 2102 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2103 "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", 2104 pSiS->OffDead1.x0, pSiS->OffDead1.y0, 2105 pSiS->OffDead1.x1, pSiS->OffDead1.y1); 2106 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2107 "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", 2108 pSiS->OffDead2.x0, pSiS->OffDead2.y0, 2109 pSiS->OffDead2.x1, pSiS->OffDead2.y1); 2110 } 2111 if(pSiS->HaveNonRect || pSiS->HaveOffsRegions) { 2112 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2113 "Mouse restriction for inaccessible areas is %s\n", 2114 pSiS->MouseRestrictions ? "enabled" : "disabled"); 2115 } 2116 } 2117} 2118 2119/* Proc */ 2120 2121int 2122SiSProcXineramaQueryVersion(ClientPtr client) 2123{ 2124 xPanoramiXQueryVersionReply rep; 2125 register int n; 2126 2127 REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq); 2128 rep.type = X_Reply; 2129 rep.length = 0; 2130 rep.sequenceNumber = client->sequence; 2131 rep.majorVersion = SIS_XINERAMA_MAJOR_VERSION; 2132 rep.minorVersion = SIS_XINERAMA_MINOR_VERSION; 2133 if(client->swapped) { 2134 swaps(&rep.sequenceNumber, n); 2135 swapl(&rep.length, n); 2136 swaps(&rep.majorVersion, n); 2137 swaps(&rep.minorVersion, n); 2138 } 2139 WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *)&rep); 2140 return (client->noClientException); 2141} 2142 2143int 2144SiSProcXineramaGetState(ClientPtr client) 2145{ 2146 REQUEST(xPanoramiXGetStateReq); 2147 WindowPtr pWin; 2148 xPanoramiXGetStateReply rep; 2149 register int n; 2150 2151 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); 2152 pWin = LookupWindow(stuff->window, client); 2153 if(!pWin) return BadWindow; 2154 2155 rep.type = X_Reply; 2156 rep.length = 0; 2157 rep.sequenceNumber = client->sequence; 2158 rep.state = !SiSnoPanoramiXExtension; 2159 if(client->swapped) { 2160 swaps (&rep.sequenceNumber, n); 2161 swapl (&rep.length, n); 2162 swaps (&rep.state, n); 2163 } 2164 WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *)&rep); 2165 return client->noClientException; 2166} 2167 2168int 2169SiSProcXineramaGetScreenCount(ClientPtr client) 2170{ 2171 REQUEST(xPanoramiXGetScreenCountReq); 2172 WindowPtr pWin; 2173 xPanoramiXGetScreenCountReply rep; 2174 register int n; 2175 2176 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); 2177 pWin = LookupWindow(stuff->window, client); 2178 if(!pWin) return BadWindow; 2179 2180 rep.type = X_Reply; 2181 rep.length = 0; 2182 rep.sequenceNumber = client->sequence; 2183 rep.ScreenCount = SiSXineramaNumScreens; 2184 if(client->swapped) { 2185 swaps(&rep.sequenceNumber, n); 2186 swapl(&rep.length, n); 2187 swaps(&rep.ScreenCount, n); 2188 } 2189 WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep); 2190 return client->noClientException; 2191} 2192 2193int 2194SiSProcXineramaGetScreenSize(ClientPtr client) 2195{ 2196 REQUEST(xPanoramiXGetScreenSizeReq); 2197 WindowPtr pWin; 2198 xPanoramiXGetScreenSizeReply rep; 2199 register int n; 2200 2201 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); 2202 pWin = LookupWindow (stuff->window, client); 2203 if(!pWin) return BadWindow; 2204 2205 rep.type = X_Reply; 2206 rep.length = 0; 2207 rep.sequenceNumber = client->sequence; 2208 rep.width = SiSXineramadataPtr[stuff->screen].width; 2209 rep.height = SiSXineramadataPtr[stuff->screen].height; 2210 if(client->swapped) { 2211 swaps(&rep.sequenceNumber, n); 2212 swapl(&rep.length, n); 2213 swaps(&rep.width, n); 2214 swaps(&rep.height, n); 2215 } 2216 WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep); 2217 return client->noClientException; 2218} 2219 2220int 2221SiSProcXineramaIsActive(ClientPtr client) 2222{ 2223 xXineramaIsActiveReply rep; 2224 2225 REQUEST_SIZE_MATCH(xXineramaIsActiveReq); 2226 2227 rep.type = X_Reply; 2228 rep.length = 0; 2229 rep.sequenceNumber = client->sequence; 2230 rep.state = !SiSnoPanoramiXExtension; 2231 if(client->swapped) { 2232 register int n; 2233 swaps(&rep.sequenceNumber, n); 2234 swapl(&rep.length, n); 2235 swapl(&rep.state, n); 2236 } 2237 WriteToClient(client, sizeof(xXineramaIsActiveReply), (char *) &rep); 2238 return client->noClientException; 2239} 2240 2241int 2242SiSProcXineramaQueryScreens(ClientPtr client) 2243{ 2244 xXineramaQueryScreensReply rep; 2245 2246 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); 2247 2248 rep.type = X_Reply; 2249 rep.sequenceNumber = client->sequence; 2250 rep.number = (SiSnoPanoramiXExtension) ? 0 : SiSXineramaNumScreens; 2251 rep.length = rep.number * sz_XineramaScreenInfo >> 2; 2252 if(client->swapped) { 2253 register int n; 2254 swaps(&rep.sequenceNumber, n); 2255 swapl(&rep.length, n); 2256 swapl(&rep.number, n); 2257 } 2258 WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *)&rep); 2259 2260 if(!SiSnoPanoramiXExtension) { 2261 xXineramaScreenInfo scratch; 2262 int i; 2263 2264 for(i = 0; i < SiSXineramaNumScreens; i++) { 2265 scratch.x_org = SiSXineramadataPtr[i].x; 2266 scratch.y_org = SiSXineramadataPtr[i].y; 2267 scratch.width = SiSXineramadataPtr[i].width; 2268 scratch.height = SiSXineramadataPtr[i].height; 2269 if(client->swapped) { 2270 register int n; 2271 swaps(&scratch.x_org, n); 2272 swaps(&scratch.y_org, n); 2273 swaps(&scratch.width, n); 2274 swaps(&scratch.height, n); 2275 } 2276 WriteToClient(client, sz_XineramaScreenInfo, (char *)&scratch); 2277 } 2278 } 2279 2280 return client->noClientException; 2281} 2282 2283static int 2284SiSProcXineramaDispatch(ClientPtr client) 2285{ 2286 REQUEST(xReq); 2287 switch (stuff->data) { 2288 case X_PanoramiXQueryVersion: 2289 return SiSProcXineramaQueryVersion(client); 2290 case X_PanoramiXGetState: 2291 return SiSProcXineramaGetState(client); 2292 case X_PanoramiXGetScreenCount: 2293 return SiSProcXineramaGetScreenCount(client); 2294 case X_PanoramiXGetScreenSize: 2295 return SiSProcXineramaGetScreenSize(client); 2296 case X_XineramaIsActive: 2297 return SiSProcXineramaIsActive(client); 2298 case X_XineramaQueryScreens: 2299 return SiSProcXineramaQueryScreens(client); 2300 } 2301 return BadRequest; 2302} 2303 2304/* SProc */ 2305 2306static int 2307SiSSProcXineramaQueryVersion (ClientPtr client) 2308{ 2309 REQUEST(xPanoramiXQueryVersionReq); 2310 register int n; 2311 swaps(&stuff->length,n); 2312 REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); 2313 return SiSProcXineramaQueryVersion(client); 2314} 2315 2316static int 2317SiSSProcXineramaGetState(ClientPtr client) 2318{ 2319 REQUEST(xPanoramiXGetStateReq); 2320 register int n; 2321 swaps (&stuff->length, n); 2322 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); 2323 return SiSProcXineramaGetState(client); 2324} 2325 2326static int 2327SiSSProcXineramaGetScreenCount(ClientPtr client) 2328{ 2329 REQUEST(xPanoramiXGetScreenCountReq); 2330 register int n; 2331 swaps (&stuff->length, n); 2332 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); 2333 return SiSProcXineramaGetScreenCount(client); 2334} 2335 2336static int 2337SiSSProcXineramaGetScreenSize(ClientPtr client) 2338{ 2339 REQUEST(xPanoramiXGetScreenSizeReq); 2340 register int n; 2341 swaps (&stuff->length, n); 2342 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); 2343 return SiSProcXineramaGetScreenSize(client); 2344} 2345 2346static int 2347SiSSProcXineramaIsActive(ClientPtr client) 2348{ 2349 REQUEST(xXineramaIsActiveReq); 2350 register int n; 2351 swaps (&stuff->length, n); 2352 REQUEST_SIZE_MATCH(xXineramaIsActiveReq); 2353 return SiSProcXineramaIsActive(client); 2354} 2355 2356static int 2357SiSSProcXineramaQueryScreens(ClientPtr client) 2358{ 2359 REQUEST(xXineramaQueryScreensReq); 2360 register int n; 2361 swaps (&stuff->length, n); 2362 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); 2363 return SiSProcXineramaQueryScreens(client); 2364} 2365 2366int 2367SiSSProcXineramaDispatch(ClientPtr client) 2368{ 2369 REQUEST(xReq); 2370 switch (stuff->data) { 2371 case X_PanoramiXQueryVersion: 2372 return SiSSProcXineramaQueryVersion(client); 2373 case X_PanoramiXGetState: 2374 return SiSSProcXineramaGetState(client); 2375 case X_PanoramiXGetScreenCount: 2376 return SiSSProcXineramaGetScreenCount(client); 2377 case X_PanoramiXGetScreenSize: 2378 return SiSSProcXineramaGetScreenSize(client); 2379 case X_XineramaIsActive: 2380 return SiSSProcXineramaIsActive(client); 2381 case X_XineramaQueryScreens: 2382 return SiSSProcXineramaQueryScreens(client); 2383 } 2384 return BadRequest; 2385} 2386 2387static void 2388SiSXineramaResetProc(ExtensionEntry* extEntry) 2389{ 2390 /* Called by CloseDownExtensions() */ 2391 if(SiSXineramadataPtr) { 2392 Xfree(SiSXineramadataPtr); 2393 SiSXineramadataPtr = NULL; 2394 } 2395} 2396 2397static void 2398SiSXineramaExtensionInit(ScrnInfoPtr pScrn) 2399{ 2400 SISPtr pSiS = SISPTR(pScrn); 2401 Bool success = FALSE; 2402 2403 if(!(SiSXineramadataPtr)) { 2404 2405 if(!pSiS->MergedFB) { 2406 SiSnoPanoramiXExtension = TRUE; 2407 pSiS->MouseRestrictions = FALSE; 2408 return; 2409 } 2410 2411#ifdef PANORAMIX 2412 if(!noPanoramiXExtension) { 2413 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2414 "Xinerama active, not initializing SiS Pseudo-Xinerama\n"); 2415 SiSnoPanoramiXExtension = TRUE; 2416 pSiS->MouseRestrictions = FALSE; 2417 return; 2418 } 2419#endif 2420 2421 if(SiSnoPanoramiXExtension) { 2422 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2423 "SiS Pseudo-Xinerama disabled\n"); 2424 pSiS->MouseRestrictions = FALSE; 2425 return; 2426 } 2427 2428 if(pSiS->CRT2Position == sisClone) { 2429 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2430 "Running MergedFB in Clone mode, SiS Pseudo-Xinerama disabled\n"); 2431 SiSnoPanoramiXExtension = TRUE; 2432 pSiS->MouseRestrictions = FALSE; 2433 return; 2434 } 2435 2436 if(!(pSiS->AtLeastOneNonClone)) { 2437 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2438 "Only Clone modes defined, SiS Pseudo-Xinerama disabled\n"); 2439 SiSnoPanoramiXExtension = TRUE; 2440 pSiS->MouseRestrictions = FALSE; 2441 return; 2442 } 2443 2444 SiSXineramaNumScreens = 2; 2445 2446 while(SiSXineramaGeneration != serverGeneration) { 2447 2448 pSiS->XineramaExtEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0, 2449 SiSProcXineramaDispatch, 2450 SiSSProcXineramaDispatch, 2451 SiSXineramaResetProc, 2452 StandardMinorOpcode); 2453 2454 if(!pSiS->XineramaExtEntry) break; 2455 2456 if(!(SiSXineramadataPtr = (SiSXineramaData *) 2457 xcalloc(SiSXineramaNumScreens, sizeof(SiSXineramaData)))) break; 2458 2459 SiSXineramaGeneration = serverGeneration; 2460 success = TRUE; 2461 } 2462 2463 if(!success) { 2464 SISErrorLog(pScrn, "Failed to initialize SiS Pseudo-Xinerama extension\n"); 2465 SiSnoPanoramiXExtension = TRUE; 2466 pSiS->MouseRestrictions = FALSE; 2467 return; 2468 } 2469 2470 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2471 "SiS Pseudo-Xinerama extension initialized\n"); 2472 2473 pSiS->SiSXineramaVX = 0; 2474 pSiS->SiSXineramaVY = 0; 2475 2476 } 2477 2478 SiSUpdateXineramaScreenInfo(pScrn); 2479 2480} 2481#endif /* End of PseudoXinerama */ 2482 2483static void 2484SiSFreeCRT2Structs(SISPtr pSiS) 2485{ 2486 if(pSiS->CRT2pScrn) { 2487 if(pSiS->CRT2pScrn->modes) { 2488 while(pSiS->CRT2pScrn->modes) 2489 xf86DeleteMode(&pSiS->CRT2pScrn->modes, pSiS->CRT2pScrn->modes); 2490 } 2491 if(pSiS->CRT2pScrn->monitor) { 2492 if(pSiS->CRT2pScrn->monitor->Modes) { 2493 while(pSiS->CRT2pScrn->monitor->Modes) 2494 xf86DeleteMode(&pSiS->CRT2pScrn->monitor->Modes, pSiS->CRT2pScrn->monitor->Modes); 2495 } 2496 if(pSiS->CRT2pScrn->monitor->DDC) xfree(pSiS->CRT2pScrn->monitor->DDC); 2497 xfree(pSiS->CRT2pScrn->monitor); 2498 } 2499 xfree(pSiS->CRT2pScrn); 2500 pSiS->CRT2pScrn = NULL; 2501 } 2502} 2503 2504#endif /* End of MergedFB helpers */ 2505 2506static xf86MonPtr 2507SiSInternalDDC(ScrnInfoPtr pScrn, int crtno) 2508{ 2509 SISPtr pSiS = SISPTR(pScrn); 2510 xf86MonPtr pMonitor = NULL; 2511 UShort temp = 0xffff, temp1, i, realcrtno = crtno; 2512 UChar buffer[256]; 2513 2514 /* If CRT1 is off, skip DDC */ 2515 if((pSiS->CRT1off) && (!crtno)) return NULL; 2516 2517 if(crtno) { 2518 if(pSiS->VBFlags & CRT2_LCD) realcrtno = 1; 2519 else if(pSiS->VBFlags & CRT2_VGA) realcrtno = 2; 2520 else return NULL; 2521 if(pSiS->SiS_Pr->DDCPortMixup) realcrtno = 0; 2522 } else { 2523 /* If CRT1 is LCDA, skip DDC (except 301C: DDC allowed, but uses CRT2 port!) */ 2524 if(pSiS->VBFlags & CRT1_LCDA) { 2525 if(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE) realcrtno = 1; 2526 else return NULL; 2527 } 2528 } 2529 2530 i = 3; /* Number of retrys */ 2531 do { 2532 temp1 = SiS_HandleDDC(pSiS->SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 2533 realcrtno, 0, &buffer[0], pSiS->VBFlags2); 2534 if((temp1) && (temp1 != 0xffff)) temp = temp1; 2535 } while((temp == 0xffff) && i--); 2536 if(temp != 0xffff) { 2537 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT%d DDC supported\n", crtno + 1); 2538 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT%d DDC level: %s%s%s%s\n", 2539 crtno + 1, 2540 (temp & 0x1a) ? "" : "[none of the supported]", 2541 (temp & 0x02) ? "2 " : "", 2542 (temp & 0x08) ? "D&P" : "", 2543 (temp & 0x10) ? "FPDI-2" : ""); 2544 if(temp & 0x02) { 2545 i = 5; /* Number of retrys */ 2546 do { 2547 temp = SiS_HandleDDC(pSiS->SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 2548 realcrtno, 1, &buffer[0], pSiS->VBFlags2); 2549 } while((temp) && i--); 2550 if(!temp) { 2551 if((pMonitor = xf86InterpretEDID(pScrn->scrnIndex, &buffer[0]))) { 2552 int tempvgagamma = 0, templcdgamma = 0; 2553 if(buffer[0x14] & 0x80) { 2554 templcdgamma = (buffer[0x17] + 100) * 10; 2555 } else { 2556 tempvgagamma = (buffer[0x17] + 100) * 10;; 2557 } 2558 if(crtno == 0) { 2559 if(tempvgagamma) pSiS->CRT1VGAMonitorGamma = tempvgagamma; 2560 /* LCD never via (demanded) CRT1 DDC port */ 2561 } else { 2562 if(tempvgagamma) pSiS->CRT2VGAMonitorGamma = tempvgagamma; 2563 if(templcdgamma) pSiS->CRT2LCDMonitorGamma = templcdgamma; 2564 } 2565 return(pMonitor); 2566 } else { 2567 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2568 "CRT%d DDC EDID corrupt\n", crtno + 1); 2569 } 2570 } else if(temp == 0xFFFE) { 2571 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2572 "CRT%d DDC data is from wrong device type (%s)\n", 2573 crtno + 1, 2574 (realcrtno == 1) ? "analog instead of digital" : "digital instead of analog"); 2575 } else { 2576 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2577 "CRT%d DDC reading failed\n", crtno + 1); 2578 } 2579 } else if(temp & 0x18) { 2580 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2581 "DDC for VESA D&P and FPDI-2 not supported yet.\n"); 2582 } 2583 } else { 2584 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2585 "CRT%d DDC probing failed\n", crtno + 1); 2586 } 2587 return(NULL); 2588} 2589 2590static xf86MonPtr 2591SiSDoPrivateDDC(ScrnInfoPtr pScrn, int *crtnum) 2592{ 2593 SISPtr pSiS = SISPTR(pScrn); 2594 2595#ifdef SISDUALHEAD 2596 if(pSiS->DualHeadMode) { 2597 if(pSiS->SecondHead) { 2598 *crtnum = 1; 2599 return(SiSInternalDDC(pScrn, 0)); 2600 } else { 2601 *crtnum = 2; 2602 return(SiSInternalDDC(pScrn, 1)); 2603 } 2604 } else 2605#endif 2606 if((pSiS->CRT1off) || (!pSiS->CRT1Detected)) { 2607 *crtnum = 2; 2608 return(SiSInternalDDC(pScrn, 1)); 2609 } else { 2610 *crtnum = 1; 2611 return(SiSInternalDDC(pScrn, 0)); 2612 } 2613} 2614 2615static void 2616SiSFindAspect(ScrnInfoPtr pScrn, xf86MonPtr pMonitor, int crtnum) 2617{ 2618 SISPtr pSiS = SISPTR(pScrn); 2619 int UseWide = 0; 2620 int aspect = 0; 2621 Bool fromdim = FALSE; 2622 2623 if((pSiS->VGAEngine == SIS_315_VGA) && (!DIGITAL(pMonitor->features.input_type))) { 2624 if(pMonitor->features.hsize && pMonitor->features.vsize) { 2625 aspect = (pMonitor->features.hsize * 1000) / pMonitor->features.vsize; 2626 if(aspect >= 1400) UseWide = 1; 2627 fromdim = TRUE; 2628 } else if((PREFERRED_TIMING_MODE(pMonitor->features.msc)) && 2629 (pMonitor->det_mon[0].type == DT)) { 2630 aspect = (pMonitor->det_mon[0].section.d_timings.h_active * 1000) / 2631 pMonitor->det_mon[0].section.d_timings.v_active; 2632 if(aspect >= 1400) UseWide = 1; 2633 } 2634 if(aspect) { 2635 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2636 "According to %s, CRT%d aspect ratio is %.2f:1 (%s)\n", 2637 fromdim ? "DDC size" : "preferred mode", 2638 crtnum, (float)aspect / 1000.0, UseWide ? "wide" : "normal"); 2639 } else { 2640 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2641 "Unable to determine CRT%d aspect ratio, assuming \"normal\"\n", 2642 crtnum); 2643 } 2644 } 2645 2646 if((crtnum == 1) && (pSiS->SiS_Pr->SiS_UseWide == -1)) { 2647 pSiS->SiS_Pr->SiS_UseWide = UseWide; 2648 } else if((crtnum == 2) && (pSiS->SiS_Pr->SiS_UseWideCRT2 == -1)) { 2649 pSiS->SiS_Pr->SiS_UseWideCRT2 = UseWide; 2650 } 2651} 2652 2653static Bool 2654SiSMakeOwnModeList(ScrnInfoPtr pScrn, Bool acceptcustommodes, Bool includelcdmodes, 2655 Bool isfordvi, Bool *havecustommodes, Bool fakecrt2modes, Bool IsForCRT2) 2656{ 2657 DisplayModePtr tempmode, delmode, mymodes; 2658 2659 if((mymodes = SiSBuildBuiltInModeList(pScrn, includelcdmodes, isfordvi, fakecrt2modes, IsForCRT2))) { 2660 if(!acceptcustommodes) { 2661 while(pScrn->monitor->Modes) 2662 xf86DeleteMode(&pScrn->monitor->Modes, pScrn->monitor->Modes); 2663 pScrn->monitor->Modes = mymodes; 2664 } else { 2665 delmode = pScrn->monitor->Modes; 2666 while(delmode) { 2667 if(delmode->type & M_T_DEFAULT) { 2668 tempmode = delmode->next; 2669 xf86DeleteMode(&pScrn->monitor->Modes, delmode); 2670 delmode = tempmode; 2671 } else { 2672 delmode = delmode->next; 2673 } 2674 } 2675 /* Link default modes AFTER user ones */ 2676 if((tempmode = pScrn->monitor->Modes)) { 2677 *havecustommodes = TRUE; 2678 while(tempmode) { 2679 if(!tempmode->next) break; 2680 else tempmode = tempmode->next; 2681 } 2682 tempmode->next = mymodes; 2683 mymodes->prev = tempmode; 2684 } else { 2685 pScrn->monitor->Modes = mymodes; 2686 } 2687#if 0 2688 pScrn->monitor->Modes = mymodes; 2689 while(mymodes) { 2690 if(!mymodes->next) break; 2691 else mymodes = mymodes->next; 2692 } 2693 mymodes->next = tempmode; 2694 if(tempmode) { 2695 tempmode->prev = mymodes; 2696 } 2697#endif 2698 } 2699 return TRUE; 2700 } else 2701 return FALSE; 2702} 2703 2704static void 2705SiSPrintModes(ScrnInfoPtr pScrn) 2706{ 2707 DisplayModePtr p; 2708 float hsync, refresh = 0.0; 2709 char *desc, *desc2, *prefix, *uprefix, *output; 2710 2711 xf86DrvMsg(pScrn->scrnIndex, pScrn->virtualFrom, "Virtual size is %dx%d " 2712 "(pitch %d)\n", pScrn->virtualX, pScrn->virtualY, 2713 pScrn->displayWidth); 2714 2715 if((p = pScrn->modes) == NULL) return; 2716 2717 do { 2718 desc = desc2 = ""; 2719 uprefix = " "; 2720 prefix = "Mode"; 2721 output = "For CRT device: "; 2722 if(p->HSync > 0.0) hsync = p->HSync; 2723 else if (p->HTotal > 0) hsync = (float)p->Clock / (float)p->HTotal; 2724 else hsync = 0.0; 2725 refresh = 0.0; 2726 if(p->VRefresh > 0.0) refresh = p->VRefresh; 2727 else if (p->HTotal > 0 && p->VTotal > 0) { 2728 refresh = p->Clock * 1000.0 / p->HTotal / p->VTotal; 2729 if(p->Flags & V_INTERLACE) refresh *= 2.0; 2730 if(p->Flags & V_DBLSCAN) refresh /= 2.0; 2731 if(p->VScan > 1) refresh /= p->VScan; 2732 } 2733 if(p->Flags & V_INTERLACE) desc = " (I)"; 2734 if(p->Flags & V_DBLSCAN) desc = " (D)"; 2735 if(p->VScan > 1) desc2 = " (VScan)"; 2736#ifdef M_T_USERDEF 2737 if(p->type & M_T_USERDEF) uprefix = "*"; 2738#endif 2739 if(p->type & M_T_BUILTIN) { 2740 prefix = "Built-in mode"; 2741 output = ""; 2742 } else if (p->type & M_T_DEFAULT) { 2743 prefix = "Default mode"; 2744 } else { 2745 output = ""; 2746 } 2747 2748 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2749 "%s%s \"%s\" (%dx%d) (%s%.1f MHz, %.1f kHz, %.1f Hz%s%s)\n", 2750 uprefix, prefix, p->name, p->HDisplay, p->VDisplay, output, 2751 p->Clock / 1000.0, hsync, refresh, desc, desc2); 2752 2753 p = p->next; 2754 } while (p != NULL && p != pScrn->modes); 2755} 2756 2757Bool SISDetermineLCDACap(ScrnInfoPtr pScrn) 2758{ 2759 SISPtr pSiS = SISPTR(pScrn); 2760 2761 if( ((pSiS->ChipType == SIS_650) || 2762 (pSiS->ChipType == SIS_315PRO) || 2763 (pSiS->ChipType >= SIS_661)) && 2764 (pSiS->ChipType != XGI_20) && 2765 (pSiS->VBFlags2 & VB2_SISLCDABRIDGE) && 2766 (pSiS->VESA != 1) ) { 2767 return TRUE; 2768 } 2769 return FALSE; 2770} 2771 2772void SISSaveDetectedDevices(ScrnInfoPtr pScrn) 2773{ 2774 SISPtr pSiS = SISPTR(pScrn); 2775 /* Backup detected CRT2 devices */ 2776 pSiS->detectedCRT2Devices = pSiS->VBFlags & (CRT2_LCD|CRT2_TV|CRT2_VGA|TV_AVIDEO|TV_SVIDEO| 2777 TV_SCART|TV_HIVISION|TV_YPBPR); 2778} 2779 2780static Bool 2781SISCheckBIOS(SISPtr pSiS, UShort mypciid, UShort mypcivendor, int biossize) 2782{ 2783 UShort romptr, pciid; 2784 2785 if(!pSiS->BIOS) return FALSE; 2786 2787 if((pSiS->BIOS[0] != 0x55) || (pSiS->BIOS[1] != 0xaa)) return FALSE; 2788 2789 romptr = pSiS->BIOS[0x18] | (pSiS->BIOS[0x19] << 8); 2790 if(romptr > (biossize - 8)) return FALSE; 2791 if((pSiS->BIOS[romptr] != 'P') || (pSiS->BIOS[romptr+1] != 'C') || 2792 (pSiS->BIOS[romptr+2] != 'I') || (pSiS->BIOS[romptr+3] != 'R')) return FALSE; 2793 2794 pciid = pSiS->BIOS[romptr+4] | (pSiS->BIOS[romptr+5] << 8); 2795 if(pciid != mypcivendor) return FALSE; 2796 2797 pciid = pSiS->BIOS[romptr+6] | (pSiS->BIOS[romptr+7] << 8); 2798 if(pciid != mypciid) return FALSE; 2799 2800 return TRUE; 2801} 2802 2803static void 2804SiS_LoadInitVBE(ScrnInfoPtr pScrn) 2805{ 2806 SISPtr pSiS = SISPTR(pScrn); 2807 2808 /* Don't load the VBE module for secondary 2809 * cards which sisfb POSTed. We don't want 2810 * int10 to overwrite our set up (such as 2811 * disabled a0000 memory address decoding). 2812 * We don't need the VBE anyway because 2813 * the card will never be in text mode, 2814 * and we can restore graphics modes just 2815 * perfectly. 2816 */ 2817 if( !pSiS->Primary && 2818 pSiS->sisfbcardposted) 2819 return; 2820 2821 if(pSiS->pVbe) return; 2822 2823 if(xf86LoadSubModule(pScrn, "vbe")) { 2824#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 2825 pSiS->pVbe = VBEInit(pSiS->pInt, pSiS->pEnt->index); 2826#else 2827 pSiS->pVbe = VBEExtendedInit(pSiS->pInt, pSiS->pEnt->index, 2828 SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH); 2829#endif 2830 } 2831 2832 if(!pSiS->pVbe) { 2833 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2834 "Failed to load/initialize vbe module\n"); 2835 } 2836} 2837 2838#ifdef SIS_PC_PLATFORM 2839static void 2840SiS_MapVGAMem(ScrnInfoPtr pScrn) 2841{ 2842 SISPtr pSiS = SISPTR(pScrn); 2843 2844 /* Map 64k VGA window for saving/restoring CGA fonts */ 2845 pSiS->VGAMapSize = 0x10000; 2846 pSiS->VGAMapPhys = 0; /* Default */ 2847 if((!pSiS->Primary) || (!pSiS->VGADecodingEnabled)) { 2848 /* If card is secondary or if a0000-address decoding 2849 * is disabled, set Phys to beginning of our video RAM. 2850 */ 2851 pSiS->VGAMapPhys = PCI_REGION_BASE(pSiS->PciInfo, 0, REGION_MEM); 2852 } 2853 if(!SiSVGAMapMem(pScrn)) { 2854 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2855 "Failed to map VGA memory (0x%lx), can't save/restore console fonts\n", 2856 pSiS->VGAMapPhys); 2857 } 2858} 2859#endif 2860 2861static void 2862SiS_CheckKernelFB(ScrnInfoPtr pScrn) 2863{ 2864 SISPtr pSiS = SISPTR(pScrn); 2865 int fd, i; 2866 CARD32 sisfbinfosize = 0, sisfbversion; 2867 sisfb_info *mysisfbinfo; 2868 char name[16]; 2869 2870 pSiS->donttrustpdc = FALSE; 2871 pSiS->sisfbpdc = 0xff; 2872 pSiS->sisfbpdca = 0xff; 2873 pSiS->sisfblcda = 0xff; 2874 pSiS->sisfbscalelcd = -1; 2875 pSiS->sisfbspecialtiming = CUT_NONE; 2876 pSiS->sisfb_haveemi = FALSE; 2877 pSiS->sisfbfound = FALSE; 2878 pSiS->sisfb_tvposvalid = FALSE; 2879 pSiS->sisfbdevname[0] = 0; 2880 pSiS->sisfb_havelock = FALSE; 2881 pSiS->sisfbHaveNewHeapDef = FALSE; 2882 pSiS->sisfbHeapSize = 0; 2883 pSiS->sisfbVideoOffset = 0; 2884 pSiS->sisfbxSTN = FALSE; 2885 pSiS->sisfbcanpost = FALSE; /* (Old) sisfb can't POST card */ 2886 pSiS->sisfbcardposted = TRUE; /* If (old) sisfb is running, card must have been POSTed */ 2887 pSiS->sisfbprimary = FALSE; /* (Old) sisfb doesn't know */ 2888 2889 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 2890 2891 i = 0; 2892 do { 2893 2894 if(i <= 7) { 2895 sprintf(name, "/dev/fb%1d", i); 2896 } else { 2897 sprintf(name, "/dev/fb/%1d", (i - 8)); 2898 } 2899 2900 if((fd = open(name, O_RDONLY)) != -1) { 2901 2902 Bool gotit = FALSE; 2903 2904 if(!ioctl(fd, SISFB_GET_INFO_SIZE, &sisfbinfosize)) { 2905 if((mysisfbinfo = xalloc(sisfbinfosize))) { 2906 if(!ioctl(fd, (SISFB_GET_INFO | (sisfbinfosize << 16)), mysisfbinfo)) { 2907 gotit = TRUE; 2908 } else { 2909 xfree(mysisfbinfo); 2910 mysisfbinfo = NULL; 2911 } 2912 } 2913 } else { 2914 if((mysisfbinfo = xalloc(sizeof(*mysisfbinfo) + 16))) { 2915 if(!ioctl(fd, SISFB_GET_INFO_OLD, mysisfbinfo)) { 2916 gotit = TRUE; 2917 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2918 "Possibly old version of sisfb detected. Please update.\n"); 2919 } else { 2920 xfree(mysisfbinfo); 2921 mysisfbinfo = NULL; 2922 } 2923 } 2924 } 2925 2926 if(gotit) { 2927 2928 if(mysisfbinfo->sisfb_id == SISFB_ID) { 2929 2930 sisfbversion = (mysisfbinfo->sisfb_version << 16) | 2931 (mysisfbinfo->sisfb_revision << 8) | 2932 (mysisfbinfo->sisfb_patchlevel); 2933 2934 if(sisfbversion >= SISFB_VERSION(1, 5, 8)) { 2935 /* Added PCI bus/slot/func into in sisfb Version 1.5.08. 2936 * Check this to make sure we run on the same card as sisfb 2937 */ 2938 if((mysisfbinfo->sisfb_pcibus == pSiS->PciBus) && 2939 (mysisfbinfo->sisfb_pcislot == pSiS->PciDevice) && 2940 (mysisfbinfo->sisfb_pcifunc == pSiS->PciFunc)) { 2941 pSiS->sisfbfound = TRUE; 2942 } 2943 } else pSiS->sisfbfound = TRUE; 2944 2945 if(pSiS->sisfbfound) { 2946 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2947 "%s: SiS kernel fb driver (sisfb) %d.%d.%d detected (PCI:%02d:%02d.%d)\n", 2948 &name[5], 2949 mysisfbinfo->sisfb_version, 2950 mysisfbinfo->sisfb_revision, 2951 mysisfbinfo->sisfb_patchlevel, 2952 pSiS->PciBus, 2953 pSiS->PciDevice, 2954 pSiS->PciFunc); 2955 2956 /* Added version/rev/pl in sisfb 1.4.0 */ 2957 if(mysisfbinfo->sisfb_version == 0) { 2958 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2959 "Old version of sisfb found. Please update.\n"); 2960 } 2961 /* Basically, we can't trust the pdc register if sisfb is loaded */ 2962 pSiS->donttrustpdc = TRUE; 2963 pSiS->sisfbHeapStart = mysisfbinfo->heapstart; 2964 2965 if(sisfbversion >= SISFB_VERSION(1, 7, 20)) { 2966 pSiS->sisfbHeapSize = mysisfbinfo->sisfb_heapsize; 2967 pSiS->sisfbVideoOffset = mysisfbinfo->sisfb_videooffset; 2968 pSiS->sisfbHaveNewHeapDef = TRUE; 2969 pSiS->sisfbFSTN = mysisfbinfo->sisfb_curfstn; 2970 pSiS->sisfbDSTN = mysisfbinfo->sisfb_curdstn; 2971 pSiS->sisfbxSTN = TRUE; 2972 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2973 "sisfb: memory heap at %dKB, size %dKB, viewport at %dKB\n", 2974 (int)pSiS->sisfbHeapStart, (int)pSiS->sisfbHeapSize, 2975 (int)pSiS->sisfbVideoOffset/1024); 2976 } else { 2977 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2978 "sisfb: memory heap at %dKB\n", (int)pSiS->sisfbHeapStart); 2979 } 2980 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2981 "sisfb: using video mode 0x%02x\n", mysisfbinfo->fbvidmode); 2982 pSiS->OldMode = mysisfbinfo->fbvidmode; 2983 if(sisfbversion >= SISFB_VERSION(1, 5, 6)) { 2984 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2985 "sisfb: using %s, reserved %dK\n", 2986 (mysisfbinfo->sisfb_caps & 0x40) ? "SiS300 series Turboqueue" : 2987 (mysisfbinfo->sisfb_caps & 0x20) ? "SiS315/330/340 series AGP command queue" : 2988 (mysisfbinfo->sisfb_caps & 0x10) ? "SiS315/330/340 series VRAM command queue" : 2989 (mysisfbinfo->sisfb_caps & 0x08) ? "SiS315/330/340 series MMIO mode" : 2990 "no command queue", 2991 (int)mysisfbinfo->sisfb_tqlen); 2992 } 2993 if(sisfbversion >= SISFB_VERSION(1, 5, 10)) { 2994 /* We can trust the pdc value if sisfb is of recent version */ 2995 if(pSiS->VGAEngine == SIS_300_VGA) pSiS->donttrustpdc = FALSE; 2996 } 2997 if(sisfbversion >= SISFB_VERSION(1, 5, 11)) { 2998 if(pSiS->VGAEngine == SIS_300_VGA) { 2999 /* As of 1.5.11, sisfb saved the register for us (300 series) */ 3000 pSiS->sisfbpdc = mysisfbinfo->sisfb_lcdpdc; 3001 if(!pSiS->sisfbpdc) pSiS->sisfbpdc = 0xff; 3002 } 3003 } 3004 if(sisfbversion >= SISFB_VERSION(1, 5, 14)) { 3005 if(pSiS->VGAEngine == SIS_315_VGA) { 3006 pSiS->sisfblcda = mysisfbinfo->sisfb_lcda; 3007 } 3008 } 3009 if(sisfbversion >= SISFB_VERSION(1, 6, 13)) { 3010 pSiS->sisfbscalelcd = mysisfbinfo->sisfb_scalelcd; 3011 pSiS->sisfbspecialtiming = mysisfbinfo->sisfb_specialtiming; 3012 } 3013 if(sisfbversion >= SISFB_VERSION(1, 6, 16)) { 3014 if(pSiS->VGAEngine == SIS_315_VGA) { 3015 pSiS->donttrustpdc = FALSE; 3016 pSiS->sisfbpdc = mysisfbinfo->sisfb_lcdpdc; 3017 if(sisfbversion >= SISFB_VERSION(1, 6, 24)) { 3018 pSiS->sisfb_haveemi = mysisfbinfo->sisfb_haveemi ? TRUE : FALSE; 3019 pSiS->sisfb_haveemilcd = TRUE; /* will match most cases */ 3020 pSiS->sisfb_emi30 = mysisfbinfo->sisfb_emi30; 3021 pSiS->sisfb_emi31 = mysisfbinfo->sisfb_emi31; 3022 pSiS->sisfb_emi32 = mysisfbinfo->sisfb_emi32; 3023 pSiS->sisfb_emi33 = mysisfbinfo->sisfb_emi33; 3024 } 3025 if(sisfbversion >= SISFB_VERSION(1, 6, 25)) { 3026 pSiS->sisfb_haveemilcd = mysisfbinfo->sisfb_haveemilcd ? TRUE : FALSE; 3027 } 3028 if(sisfbversion >= SISFB_VERSION(1, 6, 31)) { 3029 pSiS->sisfbpdca = mysisfbinfo->sisfb_lcdpdca; 3030 } else { 3031 if(pSiS->sisfbpdc) { 3032 pSiS->sisfbpdca = (pSiS->sisfbpdc & 0xf0) >> 3; 3033 pSiS->sisfbpdc = (pSiS->sisfbpdc & 0x0f) << 1; 3034 } else { 3035 pSiS->sisfbpdca = pSiS->sisfbpdc = 0xff; 3036 } 3037 } 3038 } 3039 } 3040 if(sisfbversion >= SISFB_VERSION(1, 7, 0)) { 3041 pSiS->sisfb_havelock = TRUE; 3042 if(sisfbversion >= SISFB_VERSION(1, 7, 1)) { 3043 pSiS->sisfb_tvxpos = mysisfbinfo->sisfb_tvxpos; 3044 pSiS->sisfb_tvypos = mysisfbinfo->sisfb_tvypos; 3045 pSiS->sisfb_tvposvalid = TRUE; 3046 } 3047 } 3048 if(sisfbversion >= SISFB_VERSION(1, 8, 7)) { 3049 pSiS->sisfbcanpost = (mysisfbinfo->sisfb_can_post) ? TRUE : FALSE; 3050 pSiS->sisfbcardposted = (mysisfbinfo->sisfb_card_posted) ? TRUE : FALSE; 3051 pSiS->sisfbprimary = (mysisfbinfo->sisfb_was_boot_device) ? TRUE : FALSE; 3052 /* Validity check */ 3053 if(!pSiS->sisfbcardposted) { 3054 pSiS->sisfbprimary = FALSE; 3055 } 3056 } 3057 } 3058 } 3059 xfree(mysisfbinfo); 3060 mysisfbinfo = NULL; 3061 } 3062 close (fd); 3063 } 3064 i++; 3065 } while((i <= 15) && (!pSiS->sisfbfound)); 3066 3067 if(pSiS->sisfbfound) { 3068 strncpy(pSiS->sisfbdevname, name, 15); 3069 } else { 3070 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "sisfb not found\n"); 3071 } 3072 } 3073 3074 if(!pSiS->sisfbfound) { 3075 pSiS->sisfbcardposted = FALSE; 3076 } 3077} 3078 3079static void 3080SiSPseudo(ScrnInfoPtr pScrn) 3081{ 3082} 3083 3084/* PreInit() 3085 * 3086 * Mandatory 3087 */ 3088static Bool 3089SISPreInit(ScrnInfoPtr pScrn, int flags) 3090{ 3091 SISPtr pSiS; 3092#ifdef SISDUALHEAD 3093 SISEntPtr pSiSEnt = NULL; 3094#endif 3095 MessageType from; 3096 UChar usScratchCR17, usScratchCR32, usScratchCR63; 3097 UChar usScratchSR1F, srlockReg, crlockReg; 3098 unsigned int i; 3099 int pix24flags, temp; 3100 ClockRangePtr clockRanges; 3101 xf86MonPtr pMonitor = NULL; 3102 Bool didddc2, fromDDC, crt1freqoverruled = FALSE; 3103 UChar CR5F, tempreg; 3104#if defined(SISMERGED) || defined(SISDUALHEAD) 3105 DisplayModePtr first, p, n; 3106#endif 3107#ifdef SISMERGED 3108 Bool crt2freqoverruled = FALSE; 3109#endif 3110 3111 static const char *ddcsstr = "CRT%d DDC monitor info: *******************************************\n"; 3112 static const char *ddcestr = "End of CRT%d DDC monitor info *************************************\n"; 3113 static const char *subshstr = "Substituting missing CRT%d monitor HSync range by DDC data\n"; 3114 static const char *subsvstr = "Substituting missing CRT%d monitor VRefresh range by DDC data\n"; 3115 static const char *saneh = "Correcting %s CRT%d monitor HSync range\n"; 3116 static const char *sanev = "Correcting %s CRT%d monitor VRefresh range\n"; 3117#ifdef SISMERGED 3118 static const char *mergednocrt1 = "CRT1 not detected or forced off. %s.\n"; 3119 static const char *mergednocrt2 = "No CRT2 output selected or no video bridge detected. %s.\n"; 3120 static const char *mergeddisstr = "MergedFB mode disabled"; 3121 static const char *modesforstr = "Modes for CRT%d: **************************************************\n"; 3122 static const char *crtsetupstr = "*************************** CRT%d setup ***************************\n"; 3123 static const char *crt2monname = "CRT2"; 3124#endif 3125#if defined(SISDUALHEAD) || defined(SISMERGED) 3126 static const char *notsuitablestr = "Not using mode \"%s\" (not suitable for %s mode)\n"; 3127#endif 3128 3129 if(flags & PROBE_DETECT) { 3130 3131 vbeInfoPtr pVbe; 3132 3133 if(xf86LoadSubModule(pScrn, "vbe")) { 3134 int index = xf86GetEntityInfo(pScrn->entityList[0])->index; 3135#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 3136 if((pVbe = VBEInit(NULL, index))) 3137#else 3138 if((pVbe = VBEExtendedInit(NULL, index, 0))) 3139#endif 3140 { 3141 ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 3142 vbeFree(pVbe); 3143 } 3144 } 3145 return TRUE; 3146 } 3147 3148 /* 3149 * Note: This function is only called once at server startup, and 3150 * not at the start of each server generation. This means that 3151 * only things that are persistent across server generations can 3152 * be initialised here. xf86Screens[] is the array of all screens, 3153 * (pScrn is a pointer to one of these). Privates allocated using 3154 * xf86AllocateScrnInfoPrivateIndex() are too, and should be used 3155 * for data that must persist across server generations. 3156 * 3157 * Per-generation data should be allocated with 3158 * AllocateScreenPrivateIndex() from the ScreenInit() function. 3159 */ 3160 3161 /* Check the number of entities, and fail if it isn't one. */ 3162 if(pScrn->numEntities != 1) { 3163 SISErrorLog(pScrn, "Number of entities is not 1\n"); 3164 return FALSE; 3165 } 3166 3167 /* Due to the liberal license terms this is needed for 3168 * keeping the copyright notice readable and intact in 3169 * binary distributions. Removing this is a copyright 3170 * infringement. Please read the license terms above. 3171 */ 3172 3173 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3174 "SiS driver (%d/%02d/%02d-%d, compiled for " SISMYSERVERNAME " %d.%d.%d.%d)\n", 3175 SISDRIVERVERSIONYEAR + 2000, SISDRIVERVERSIONMONTH, 3176 SISDRIVERVERSIONDAY, SISDRIVERREVISION, 3177#ifdef XORG_VERSION_CURRENT 3178 XORG_VERSION_MAJOR, XORG_VERSION_MINOR, 3179 XORG_VERSION_PATCH, XORG_VERSION_SNAP 3180#else 3181 XF86_VERSION_MAJOR, XF86_VERSION_MINOR, 3182 XF86_VERSION_PATCH, XF86_VERSION_SNAP 3183#endif 3184 ); 3185 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3186 "Copyright (C) 2001-2005 Thomas Winischhofer <thomas@winischhofer.net> and others\n"); 3187 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3188 "*** See http://www.winischhofer.eu/linuxsisvga.shtml\n"); 3189 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3190 "*** for documentation and updates.\n"); 3191 3192#ifdef XORG_VERSION_CURRENT 3193#if 0 /* no prototype yet */ 3194 if(xorgGetVersion() != XORG_VERSION_CURRENT) { 3195 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3196 "This driver binary is not compiled for this version of " SISMYSERVERNAME "\n"); 3197 } 3198#endif 3199#else 3200#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0) 3201 if(xf86GetVersion() != XF86_VERSION_CURRENT) { 3202 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3203 "This driver binary is not compiled for this version of " SISMYSERVERNAME "\n"); 3204 } 3205#endif 3206#endif 3207 3208 /* Allocate the SISRec driverPrivate */ 3209 if(!SISGetRec(pScrn)) { 3210 SISErrorLog(pScrn, "Could not allocate memory for pSiS private\n"); 3211 return FALSE; 3212 } 3213 pSiS = SISPTR(pScrn); 3214 pSiS->pScrn = pScrn; 3215 3216 pSiS->pInt = NULL; 3217 3218 /* Save PCI Domain Base */ 3219#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 3220 pSiS->IODBase = 0; 3221#else 3222 pSiS->IODBase = pScrn->domainIOBase; 3223#endif 3224 3225 /* Get the entity, and make sure it is PCI. */ 3226 pSiS->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 3227 if(pSiS->pEnt->location.type != BUS_PCI) { 3228 SISErrorLog(pScrn, "Entity's bus type is not PCI\n"); 3229 goto my_error_0; 3230 } 3231 3232#ifdef SISDUALHEAD 3233 /* Allocate an entity private if necessary */ 3234 if(xf86IsEntityShared(pScrn->entityList[0])) { 3235 pSiSEnt = xf86GetEntityPrivate(pScrn->entityList[0], SISEntityIndex)->ptr; 3236 pSiS->entityPrivate = pSiSEnt; 3237 3238 /* If something went wrong, quit here */ 3239 if((pSiSEnt->DisableDual) || (pSiSEnt->ErrorAfterFirst)) { 3240 SISErrorLog(pScrn, "First head encountered fatal error, aborting...\n"); 3241 goto my_error_0; 3242 } 3243 } 3244#endif 3245 3246 /* Find the PCI info for this screen */ 3247 pSiS->PciInfo = xf86GetPciInfoForEntity(pSiS->pEnt->index); 3248 pSiS->PciBus = PCI_CFG_BUS(pSiS->PciInfo); /*SIS_PCI_BUS(pSiS->PciInfo);*/ 3249 pSiS->PciDevice = PCI_CFG_DEV(pSiS->PciInfo); /*SIS_PCI_DEVICE(pSiS->PciInfo);*/ 3250 pSiS->PciFunc = PCI_CFG_FUNC(pSiS->PciInfo); /*SIS_PCI_FUNC(pSiS->PciInfo);*/ 3251 3252 pSiS->PciTag = pciTag(PCI_DEV_BUS(pSiS->PciInfo), 3253 PCI_DEV_DEV(pSiS->PciInfo), 3254 PCI_DEV_FUNC(pSiS->PciInfo)); 3255 3256#ifdef SIS_NEED_MAP_IOP 3257 /********************************************/ 3258 /* THIS IS BROKEN AND WON'T WORK */ 3259 /* Reasons: */ 3260 /* 1) MIPS and ARM have no i/o ports but */ 3261 /* use memory mapped i/o only. The inX/outX */ 3262 /* macros in compiler.h are smart enough to */ 3263 /* add "IOPortBase" to the port number, but */ 3264 /* "IOPortBase" is never initialized. */ 3265 /* 2) IOPortBase is declared in compiler.h */ 3266 /* itself. So until somebody fixes all */ 3267 /* modules that #include compiler.h to set */ 3268 /* IOPortBase, vga support for MIPS and ARM */ 3269 /* is unusable. */ 3270 /* (In this driver this is solvable because */ 3271 /* we have our own vgaHW routines. However, */ 3272 /* we use /dev/port for now instead.) */ 3273 /********************************************/ 3274 pSiS->IOPAddress = pSiS->IODBase + pSiS->PciInfo->ioBase[2]; 3275 if(!SISMapIOPMem(pScrn)) { 3276 SISErrorLog(pScrn, "Could not map I/O port area at 0x%x\n", pSiS->IOPAddress); 3277 goto my_error_0; 3278 } else { 3279 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I/O port area mapped to %p, size 128\n", pSiS->IOPBase); 3280#if defined(__mips__) || defined(__arm32__) 3281 /* inX/outX macros on these use IOPortBase as offset */ 3282 /* This is entirely skrewed. */ 3283 IOPortBase = (unsigned int)pSiS->IOPBase; 3284#endif 3285 } 3286#endif 3287 3288 /* Set up i/o port access (for non-x86) */ 3289#ifdef SISUSEDEVPORT 3290 if((sisdevport = open("/dev/port", O_RDWR, 0)) == -1) { 3291 SISErrorLog(pScrn, "Failed to open /dev/port for read/write\n"); 3292 goto my_error_0; 3293 } 3294 pSiS->sisdevportopen = TRUE; 3295#endif 3296 3297 /* 3298 * Set the Chipset and ChipRev, allowing config file entries to 3299 * override. DANGEROUS! 3300 */ 3301 { 3302 SymTabRec *myChipsets = SISChipsets; 3303 3304 if(PCI_DEV_VENDOR_ID(pSiS->PciInfo) == PCI_VENDOR_XGI) { 3305 myChipsets = XGIChipsets; 3306 } 3307 3308 if(pSiS->pEnt->device->chipset && *pSiS->pEnt->device->chipset) { 3309 3310 pScrn->chipset = pSiS->pEnt->device->chipset; 3311 pSiS->Chipset = xf86StringToToken(myChipsets, pScrn->chipset); 3312 3313 } else if(pSiS->pEnt->device->chipID >= 0) { 3314 3315 pSiS->Chipset = pSiS->pEnt->device->chipID; 3316 pScrn->chipset = (char *)xf86TokenToString(myChipsets, pSiS->Chipset); 3317 3318 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", 3319 pSiS->Chipset); 3320 } else { 3321 3322 pSiS->Chipset = PCI_DEV_DEVICE_ID(pSiS->PciInfo); 3323 pScrn->chipset = (char *)xf86TokenToString(myChipsets, pSiS->Chipset); 3324 3325 } 3326 } 3327 3328 if(pSiS->pEnt->device->chipRev >= 0) { 3329 3330 pSiS->ChipRev = pSiS->pEnt->device->chipRev; 3331 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 3332 pSiS->ChipRev); 3333 } else { 3334 3335 pSiS->ChipRev = PCI_DEV_REVISION(pSiS->PciInfo); 3336 3337 } 3338 3339 /* 3340 * This shouldn't happen because such problems should be caught in 3341 * SISProbe(), but check it just in case the user has overridden them. 3342 */ 3343 if(pScrn->chipset == NULL) { 3344 SISErrorLog(pScrn, "ChipID 0x%04X is not recognised\n", pSiS->Chipset); 3345 goto my_error_0; 3346 } 3347 if(pSiS->Chipset < 0) { 3348 SISErrorLog(pScrn, "Chipset \"%s\" is not recognised\n", pScrn->chipset); 3349 goto my_error_0; 3350 } 3351 3352 pSiS->SiS6326Flags = 0; 3353 3354 /* Determine VGA engine generation */ 3355 switch(pSiS->Chipset) { 3356 case PCI_CHIP_SIS300: 3357 case PCI_CHIP_SIS540: 3358 case PCI_CHIP_SIS630: /* 630 + 730 */ 3359 pSiS->VGAEngine = SIS_300_VGA; 3360 break; 3361 case PCI_CHIP_SIS315H: 3362 case PCI_CHIP_SIS315: 3363 case PCI_CHIP_SIS315PRO: 3364 case PCI_CHIP_SIS550: 3365 case PCI_CHIP_SIS650: /* 650 + 740 */ 3366 case PCI_CHIP_SIS330: 3367 case PCI_CHIP_SIS660: /* 660, 661, 741, 760, 761, 670(?), 770 */ 3368 case PCI_CHIP_SIS340: 3369 case PCI_CHIP_XGIXG20: 3370 case PCI_CHIP_XGIXG40: 3371 pSiS->VGAEngine = SIS_315_VGA; 3372 break; 3373 case PCI_CHIP_SIS530: 3374 pSiS->VGAEngine = SIS_530_VGA; 3375 break; 3376 case PCI_CHIP_SIS6326: 3377 /* Determine SiS6326 revision. According to SiS the differences are: 3378 * Chip name Chip type TV-Out MPEG II decoder 3379 * 6326 AGP Rev. G0/H0 no no 3380 * 6326 DVD Rev. D2 yes yes 3381 * 6326 Rev. Cx yes yes 3382 */ 3383 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3384 "Chipset is SiS6326 %s (revision 0x%02x)\n", 3385 (pSiS->ChipRev == 0xaf) ? "(Ax)" : 3386 ((pSiS->ChipRev == 0x0a) ? "AGP (G0)" : 3387 ((pSiS->ChipRev == 0x0b) ? "AGP (H0)" : 3388 (((pSiS->ChipRev & 0xf0) == 0xd0) ? "DVD (Dx/H0)" : 3389 (((pSiS->ChipRev & 0xf0) == 0x90) ? "(9x)" : 3390 (((pSiS->ChipRev & 0xf0) == 0xc0) ? "(Cx)" : 3391 "(unknown)"))))), 3392 pSiS->ChipRev); 3393 if((pSiS->ChipRev != 0x0a) && (pSiS->ChipRev != 0x0b)) { 3394 pSiS->SiS6326Flags |= SIS6326_HASTV; 3395 } 3396 /* fall through */ 3397 default: 3398 pSiS->VGAEngine = SIS_OLD_VGA; 3399 } 3400 3401 /* We don't know about the current mode yet */ 3402 pSiS->OldMode = 0; 3403 3404 /* Determine whether this is the primary or a secondary 3405 * display adapter. And right here the problem starts: 3406 * On machines with integrated SiS chipsets, the system BIOS 3407 * usually sets VGA_EN on all PCI-to-PCI bridges in the system 3408 * (of which there usually are two: PCI and AGP). This and 3409 * the fact that any PCI card POSTed by sisfb naturally has 3410 * its PCI resources enabled, leads to X assuming that 3411 * there are more than one "primary" cards in the system. 3412 * In this case, X treats ALL cards as "secondary" - 3413 * which by no means is desireable. If sisfb is running, 3414 * we can determine which card really is "primary" (in 3415 * terms of if it's the one that occupies the A0000 area 3416 * etc.) in a better way (Linux 2.6.12 or later). See below. 3417 */ 3418 if(!(pSiS->Primary = xf86IsPrimaryPci(pSiS->PciInfo))) { 3419 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3420 SISMYSERVERNAME " assumes this adapter to be secondary\n"); 3421 } 3422 3423 /* Now check if sisfb is running, and if so, retrieve 3424 * all possible info from it. This also resets all 3425 * sisfb_* entries in pSiS regardless of the chipset. 3426 */ 3427 SiS_CheckKernelFB(pScrn); 3428 3429 /* Now for that primary/secondary mess: Linux kernel 3430 * 2.6.12 and later knows what card is primary, and so 3431 * does any recent version of sisfb. XFree86/X.org takes 3432 * all adapters as "secondary" if more than one card's 3433 * memory and i/o resources are enabled, and more than 3434 * one PCI bridge in the system has VGA_EN set at server 3435 * start. So, let's start thinking: What is this 3436 * primary/secondary classification needed for anyway? 3437 * (This list might be incomplete for the entire server 3438 * infrastructure, but it's complete as regards the driver's 3439 * purposes of primary/secondary classification.) 3440 * 1) VGA/console font restoring: Here it's irrelevant 3441 * whether more than one card's resources are enabled 3442 * at server start or not. Relevant is whether the card 3443 * occupies the A0000 area at this time. Assuming (?) 3444 * that this does not change during machine up-time, 3445 * it suffices to know which device was the boot video 3446 * device (as determined by Linux 2.6.12 and later). 3447 * Also, this is only relevant if the card is in text 3448 * mode; if it's in graphics mode, fonts aren't saved 3449 * or restored anyway. 3450 * sisfb tells us if that card is considered the boot 3451 * video device. The hardware registers tell us if 3452 * the card's A0000 address decoding is enabled, and if 3453 * the card currently is in text mode. These three bits 3454 * of information are enough to decide on whether or not 3455 * to save/restore fonts. 3456 * 2) POSTing. Same here. Relevant is only whether or not 3457 * the card has been POSTed once before. POSTing cards 3458 * on every server start is pretty ugly, especially 3459 * if a framebuffer driver is already handling it. 3460 * SiS/XGI cards POSTed by sisfb can coexist well with other 3461 * active adapters. So we trust sisfb's information more 3462 * than X's (especially as we only use this information for 3463 * console font restoring and eventual POSTing.) 3464 * What we still need is a way to find out about all this if 3465 * sisfb is not running.... 3466 */ 3467 if(!pSiS->Primary && pSiS->sisfbprimary) { 3468 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3469 "sisfb reports this adapter to be primary. Seems more reliable.\n"); 3470 pSiS->Primary = TRUE; 3471 } 3472 3473 /* If the card is "secondary" and has not been 3474 * POSTed by sisfb, POST it now through int10. 3475 * For cards POSTed by sisfb, we definitely don't 3476 * want that as it messes up our set up (eg. the 3477 * disabled A0000 area). 3478 * The int10 module decides on its own if the 3479 * card is primary or secondary. Since it uses 3480 * the generic technique described above, and since 3481 * for "secondary" cards it needs a real PCI BIOS 3482 * ROM, and since integrated chips don't have such 3483 * a PCI BIOS ROM, int10 will naturally fail to 3484 * find/read the BIOS on such machines. Great. 3485 * Using the integrated graphics as "secondary" 3486 * (which it will be as soon as X finds more than 3487 * one card's mem and i/o resources enabled, and more 3488 * than one PCI bridge's VGA_EN bit set during server 3489 * start) will therefore prevent us from restoring 3490 * the mode using the VBE. That means real fun if 3491 * the integrated chip is set up to use the video 3492 * bridge output for text mode (which is something 3493 * the driver doesn't really support since it's done 3494 * pretty much differently on every machine.) 3495 */ 3496#if !defined(__alpha__) 3497 if(!pSiS->Primary) { 3498 if(!pSiS->sisfbcardposted) { 3499 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3500 "Initializing adapter through int10\n"); 3501 if(xf86LoadSubModule(pScrn, "int10")) { 3502 pSiS->pInt = xf86InitInt10(pSiS->pEnt->index); 3503 } else { 3504 SISErrorLog(pScrn, "Failed to load int10 module\n"); 3505 } 3506 } else { 3507 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3508 "Adapter already initialized by sisfb\n"); 3509 } 3510 } 3511#endif 3512 3513 /* Get the address of our relocated IO registers. 3514 * These are enabled by the hardware during cold boot, and 3515 * by the BIOS. So we can pretty much rely on that these 3516 * are enabled. 3517 */ 3518 pSiS->RelIO = (SISIOADDRESS)(PCI_REGION_BASE(pSiS->PciInfo, 2, REGION_IO) + pSiS->IODBase); 3519 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Relocated I/O registers at 0x%lX\n", 3520 (ULong)pSiS->RelIO); 3521 3522 /* Unlock extended registers */ 3523 sisSaveUnlockExtRegisterLock(pSiS, &srlockReg, &crlockReg); 3524 3525 /* Is a0000 memory address decoding enabled? */ 3526 pSiS->VGADecodingEnabled = TRUE; 3527 switch(pSiS->VGAEngine) { 3528 case SIS_OLD_VGA: 3529 /* n/a */ 3530 break; 3531 case SIS_530_VGA: 3532 inSISIDXREG(SISSR, 0x3d, tempreg); 3533 if(tempreg & 0x04) pSiS->VGADecodingEnabled = FALSE; 3534 break; 3535 case SIS_300_VGA: 3536 case SIS_315_VGA: 3537 inSISIDXREG(SISSR, 0x20, tempreg); 3538 if(tempreg & 0x04) pSiS->VGADecodingEnabled = FALSE; 3539 break; 3540 } 3541 3542 if(!pSiS->VGADecodingEnabled) { 3543 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3544 "Standard VGA (0xA0000) memory address decoding is disabled\n"); 3545 } 3546 3547#ifdef SIS_PC_PLATFORM 3548 /* Map 64k VGA window for saving/restoring CGA fonts. 3549 * For secondary cards or if A0000 address decoding 3550 * is disabled, this will map the beginning of the 3551 * linear (PCI) video RAM instead. 3552 */ 3553 SiS_MapVGAMem(pScrn); 3554#endif 3555 3556#ifndef XSERVER_LIBPCIACCESS 3557 /* Set operating state */ 3558 3559 /* 1. memory */ 3560 /* [ResUnusedOpr: Resource decoded by hw, but not used] 3561 * [ResDisableOpr: Resource is not decoded by hw] 3562 * So, if a0000 memory decoding is disabled, one could 3563 * argue that we may say so, too. Hm. Quite likely that 3564 * the VBE (via int10) will eventually enable it. So we 3565 * cowardly say unused instead. 3566 */ 3567 xf86SetOperatingState(resVgaMem, pSiS->pEnt->index, ResUnusedOpr); 3568 3569 /* 2. i/o */ 3570 /* Although we only use the relocated i/o ports, the hardware 3571 * also decodes the standard VGA port range. This could in 3572 * theory be disabled, but I don't dare to do this; in case of 3573 * a server crash, the card would be entirely dead. Also, this 3574 * would prevent int10 and the VBE from working at all. Generic 3575 * access control through the PCI configuration registers does 3576 * nicely anyway. 3577 */ 3578 xf86SetOperatingState(resVgaIo, pSiS->pEnt->index, ResUnusedOpr); 3579 3580 /* Operations for which memory access is required */ 3581 pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; 3582 3583 /* Operations for which I/O access is required */ 3584 pScrn->racIoFlags = RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; 3585 3586#endif 3587 3588 /* Load ramdac module */ 3589 if(!xf86LoadSubModule(pScrn, "ramdac")) { 3590 SISErrorLog(pScrn, "Could not load ramdac module\n"); 3591 goto my_error_1; 3592 } 3593 3594 /* Set pScrn->monitor */ 3595 pScrn->monitor = pScrn->confScreen->monitor; 3596 3597 /* Reset some entries */ 3598 pSiS->SiSFastVidCopy = SiSVidCopyGetDefault(); 3599 pSiS->SiSFastMemCopy = SiSVidCopyGetDefault(); 3600 pSiS->SiSFastVidCopyFrom = SiSVidCopyGetDefault(); 3601 pSiS->SiSFastMemCopyFrom = SiSVidCopyGetDefault(); 3602 pSiS->SiSFastVidCopyDone = FALSE; 3603#ifdef SIS_USE_XAA 3604 pSiS->RenderCallback = NULL; 3605#endif 3606#ifdef SIS_USE_EXA 3607 pSiS->ExaRenderCallback = NULL; 3608#endif 3609 pSiS->InitAccel = SiSPseudo; 3610 pSiS->SyncAccel = SiSPseudo; 3611 pSiS->FillRect = NULL; 3612 pSiS->BlitRect = NULL; 3613 3614 /* Always do a ValidMode() inside Switchmode() */ 3615 pSiS->skipswitchcheck = FALSE; 3616 3617 /* Determine chipset and its capabilities in detail */ 3618 pSiS->ChipFlags = 0; 3619 pSiS->SiS_SD_Flags = pSiS->SiS_SD2_Flags = 0; 3620 pSiS->SiS_SD3_Flags = pSiS->SiS_SD4_Flags = 0; 3621 pSiS->HWCursorMBufNum = pSiS->HWCursorCBufNum = 0; 3622 pSiS->NeedFlush = FALSE; 3623 pSiS->NewCRLayout = FALSE; 3624 pSiS->mmioSize = 64; 3625 3626 switch(pSiS->Chipset) { 3627 case PCI_CHIP_SIS530: 3628 pSiS->ChipType = SIS_530; 3629 break; 3630 case PCI_CHIP_SIS300: 3631 pSiS->ChipType = SIS_300; 3632 pSiS->SiS_SD_Flags |= SiS_SD_IS300SERIES; 3633 break; 3634 case PCI_CHIP_SIS540: 3635 pSiS->ChipType = SIS_540; 3636 pSiS->SiS_SD_Flags |= SiS_SD_IS300SERIES; 3637 break; 3638 case PCI_CHIP_SIS630: /* 630 + 730 */ 3639 pSiS->ChipType = SIS_630; 3640 if(sis_pci_read_host_bridge_u32(0x00) == 0x07301039) { 3641 pSiS->ChipType = SIS_730; 3642 } 3643 pSiS->SiS_SD_Flags |= SiS_SD_IS300SERIES; 3644 break; 3645 case PCI_CHIP_SIS315H: 3646 pSiS->ChipType = SIS_315H; 3647 pSiS->ChipFlags |= (SiSCF_315Core | SiSCF_MMIOPalette); 3648 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3649 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3650 pSiS->myCR63 = 0x63; 3651 break; 3652 case PCI_CHIP_SIS315: 3653 /* Override for simplicity */ 3654 pSiS->Chipset = PCI_CHIP_SIS315H; 3655 pSiS->ChipType = SIS_315; 3656 pSiS->ChipFlags |= (SiSCF_315Core | SiSCF_MMIOPalette); 3657 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3658 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3659 pSiS->myCR63 = 0x63; 3660 break; 3661 case PCI_CHIP_SIS315PRO: 3662 /* Override for simplicity */ 3663 pSiS->Chipset = PCI_CHIP_SIS315H; 3664 pSiS->ChipType = SIS_315PRO; 3665 pSiS->ChipFlags |= (SiSCF_315Core | SiSCF_MMIOPalette); 3666 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3667 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3668 pSiS->myCR63 = 0x63; 3669 break; 3670 case PCI_CHIP_SIS550: 3671 pSiS->ChipType = SIS_550; 3672 pSiS->ChipFlags |= (SiSCF_Integrated | SiSCF_MMIOPalette); 3673 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3674 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3675 pSiS->myCR63 = 0x63; 3676 break; 3677 case PCI_CHIP_SIS650: /* 650 + 740 */ 3678 pSiS->ChipType = SIS_650; 3679 if(sis_pci_read_host_bridge_u32(0x00) == 0x07401039) { 3680 pSiS->ChipType = SIS_740; 3681 } 3682 pSiS->ChipFlags |= (SiSCF_Integrated | SiSCF_Real256ECore | SiSCF_MMIOPalette); 3683 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3684 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3685 pSiS->myCR63 = 0x63; 3686 break; 3687 case PCI_CHIP_SIS330: 3688 pSiS->ChipType = SIS_330; 3689 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette); 3690 pSiS->SiS_SD_Flags |= SiS_SD_IS330SERIES; 3691 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3692 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; /* FIXME ? */ 3693 pSiS->myCR63 = 0x53; /* sic! */ 3694 break; 3695 case PCI_CHIP_SIS660: /* 660, 661, 741, 760, 761, 670(?) */ 3696 { 3697 ULong hpciid = sis_pci_read_host_bridge_u32(0x00); 3698 switch(hpciid) { 3699 case 0x06601039: 3700 pSiS->ChipType = SIS_660; 3701 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3702 pSiS->NeedFlush = TRUE; 3703 break; 3704 case 0x07601039: 3705 pSiS->ChipType = SIS_760; 3706 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3707 pSiS->NeedFlush = TRUE; 3708 break; 3709 case 0x07611039: 3710 pSiS->ChipType = SIS_761; 3711 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3712 pSiS->NeedFlush = TRUE; 3713 break; 3714 case 0x07701039: 3715 pSiS->ChipType = SIS_770; 3716 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3717 pSiS->NeedFlush = TRUE; 3718 break; 3719 case 0x07411039: 3720 pSiS->ChipType = SIS_741; 3721 pSiS->ChipFlags |= SiSCF_Real256ECore; 3722 break; 3723 case 0x06611039: 3724 default: 3725 pSiS->ChipType = SIS_661; 3726 pSiS->ChipFlags |= SiSCF_Real256ECore; 3727 break; 3728 case 0x06701039: 3729 pSiS->ChipType = SIS_670; 3730 pSiS->ChipFlags |= SiSCF_Real256ECore; 3731 } 3732 /* Detection could also be done by CR5C & 0xf8: 3733 * 0x10 = 661 (CR5F & 0xc0: 0x00 both A0 and A1) 3734 * 0x80 = 760 (CR5F & 0xc0: 0x00 A0, 0x40 A1) 3735 * 0x90 = 741 (CR5F & 0xc0: 0x00 A0,A1 0x40 A2) 3736 * other: 660 (CR5F & 0xc0: 0x00 A0 0x40 A1) (DOA?) 3737 */ 3738 pSiS->ChipFlags |= (SiSCF_Integrated | SiSCF_MMIOPalette); 3739 pSiS->SiS_SD_Flags |= SiS_SD_IS330SERIES; 3740 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3741 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; 3742 pSiS->myCR63 = 0x53; /* sic! */ 3743 pSiS->NewCRLayout = TRUE; 3744 } 3745 break; 3746 case PCI_CHIP_SIS340: 3747 pSiS->ChipType = SIS_340; 3748 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette); 3749 pSiS->SiS_SD_Flags |= SiS_SD_IS340SERIES; 3750 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3751 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; 3752 pSiS->myCR63 = 0x53; 3753 pSiS->NewCRLayout = TRUE; 3754 break; 3755 case PCI_CHIP_XGIXG20: 3756 pSiS->ChipType = XGI_20; 3757 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette | SiSCF_IsXGI); 3758 pSiS->SiS_SD2_Flags |= (SiS_SD2_NOOVERLAY | SiS_SD2_ISXGI); 3759 pSiS->myCR63 = 0x53; 3760 pSiS->NewCRLayout = TRUE; 3761 break; 3762 case PCI_CHIP_XGIXG40: 3763 pSiS->ChipType = XGI_40; 3764 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette | SiSCF_IsXGI); 3765 pSiS->SiS_SD2_Flags |= (SiS_SD2_SUPPORTXVHUESAT | SiS_SD2_ISXGI); 3766 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; 3767 pSiS->myCR63 = 0x53; 3768 pSiS->NewCRLayout = TRUE; 3769 if(pSiS->ChipRev == 2) pSiS->ChipFlags |= SiSCF_IsXGIV3; 3770 break; 3771 default: 3772 pSiS->ChipType = SIS_OLD; 3773 break; 3774 } 3775 3776 /* 3777 * Now back to real business: Figure out the depth, bpp, etc. 3778 * Set SupportConvert... flags since we use the fb layer which 3779 * supports this conversion. (24to32 seems not implemented though) 3780 * Additionally, determine the size of the HWCursor memory area. 3781 */ 3782 switch(pSiS->VGAEngine) { 3783 case SIS_300_VGA: 3784 pSiS->CursorSize = 4096; 3785 pix24flags = Support32bppFb; 3786 break; 3787 case SIS_315_VGA: 3788 pSiS->CursorSize = 16384; 3789 pix24flags = Support32bppFb; 3790 break; 3791 case SIS_530_VGA: 3792 pSiS->CursorSize = 2048; 3793 pix24flags = Support32bppFb | 3794 Support24bppFb | 3795 SupportConvert32to24; 3796 break; 3797 default: 3798 pSiS->CursorSize = 2048; 3799 pix24flags = Support24bppFb | 3800 SupportConvert32to24 | 3801 PreferConvert32to24; 3802 break; 3803 } 3804 3805#ifdef SISDUALHEAD 3806 /* In case of Dual Head, we need to determine if we are the "master" head or 3807 * the "slave" head. In order to do that, we set PrimInit to DONE in the 3808 * shared entity at the end of the first initialization. The second 3809 * initialization then knows that some things have already been done. THIS 3810 * ALWAYS ASSUMES THAT THE FIRST DEVICE INITIALIZED IS THE MASTER! 3811 */ 3812 if(xf86IsEntityShared(pScrn->entityList[0])) { 3813 if(pSiSEnt->lastInstance > 0) { 3814 if(!xf86IsPrimInitDone(pScrn->entityList[0])) { 3815 /* First Head (always CRT2) */ 3816 pSiS->SecondHead = FALSE; 3817 pSiSEnt->pScrn_1 = pScrn; 3818 pSiSEnt->CRT1ModeNo = pSiSEnt->CRT2ModeNo = -1; 3819 pSiSEnt->CRT2ModeSet = FALSE; 3820 pSiS->DualHeadMode = TRUE; 3821 pSiSEnt->DisableDual = FALSE; 3822 pSiSEnt->BIOS = NULL; 3823 pSiSEnt->ROM661New = FALSE; 3824 pSiSEnt->HaveXGIBIOS = FALSE; 3825 pSiSEnt->SiS_Pr = NULL; 3826 pSiSEnt->RenderAccelArray = NULL; 3827 pSiSEnt->SiSFastVidCopy = pSiSEnt->SiSFastMemCopy = NULL; 3828 pSiSEnt->SiSFastVidCopyFrom = pSiSEnt->SiSFastMemCopyFrom = NULL; 3829 } else { 3830 /* Second Head (always CRT1) */ 3831 pSiS->SecondHead = TRUE; 3832 pSiSEnt->pScrn_2 = pScrn; 3833 pSiS->DualHeadMode = TRUE; 3834 } 3835 } else { 3836 /* Only one screen in config file - disable dual head mode */ 3837 pSiS->SecondHead = FALSE; 3838 pSiS->DualHeadMode = FALSE; 3839 pSiSEnt->DisableDual = TRUE; 3840 } 3841 } else { 3842 /* Entity is not shared - disable dual head mode */ 3843 pSiS->SecondHead = FALSE; 3844 pSiS->DualHeadMode = FALSE; 3845 } 3846#endif 3847 3848 /* Save the name of our Device section for SiSCtrl usage */ 3849 { 3850 int ttt = 0; 3851 GDevPtr device = xf86GetDevFromEntity(pScrn->entityList[0], 3852 pScrn->entityInstanceList[0]); 3853 if(device && device->identifier) { 3854 if((ttt = strlen(device->identifier)) > 31) ttt = 31; 3855 strncpy(&pSiS->devsectname[0], device->identifier, 31); 3856 } 3857 pSiS->devsectname[ttt] = 0; 3858 } 3859 3860 pSiS->ForceCursorOff = FALSE; 3861 3862 /* Allocate SiS_Private (for mode switching code) and initialize it */ 3863 pSiS->SiS_Pr = NULL; 3864#ifdef SISDUALHEAD 3865 if(pSiSEnt) { 3866 if(pSiSEnt->SiS_Pr) pSiS->SiS_Pr = pSiSEnt->SiS_Pr; 3867 } 3868#endif 3869 if(!pSiS->SiS_Pr) { 3870 if(!(pSiS->SiS_Pr = xnfcalloc(sizeof(struct SiS_Private), 1))) { 3871 SISErrorLog(pScrn, "Could not allocate memory for SiS_Pr structure\n"); 3872 goto my_error_1; 3873 } 3874#ifdef SISDUALHEAD 3875 if(pSiSEnt) pSiSEnt->SiS_Pr = pSiS->SiS_Pr; 3876#endif 3877 memset(pSiS->SiS_Pr, 0, sizeof(struct SiS_Private)); 3878 pSiS->SiS_Pr->PciTag = pSiS->PciTag; 3879 pSiS->SiS_Pr->ChipType = pSiS->ChipType; 3880 pSiS->SiS_Pr->ChipRevision = pSiS->ChipRev; 3881 pSiS->SiS_Pr->SiS_Backup70xx = 0xff; 3882 pSiS->SiS_Pr->SiS_CHOverScan = -1; 3883 pSiS->SiS_Pr->SiS_ChSW = FALSE; 3884 pSiS->SiS_Pr->SiS_CustomT = CUT_NONE; 3885 pSiS->SiS_Pr->SiS_UseWide = -1; 3886 pSiS->SiS_Pr->SiS_UseWideCRT2 = -1; 3887 pSiS->SiS_Pr->SiS_TVBlue = -1; 3888 pSiS->SiS_Pr->PanelSelfDetected = FALSE; 3889 pSiS->SiS_Pr->UsePanelScaler = -1; 3890 pSiS->SiS_Pr->CenterScreen = -1; 3891 pSiS->SiS_Pr->CRT1UsesCustomMode = FALSE; 3892 pSiS->SiS_Pr->PDC = pSiS->SiS_Pr->PDCA = -1; 3893 pSiS->SiS_Pr->LVDSHL = -1; 3894 pSiS->SiS_Pr->HaveEMI = FALSE; 3895 pSiS->SiS_Pr->HaveEMILCD = FALSE; 3896 pSiS->SiS_Pr->OverruleEMI = FALSE; 3897 pSiS->SiS_Pr->SiS_SensibleSR11 = FALSE; 3898 if(pSiS->ChipType >= SIS_661) { 3899 pSiS->SiS_Pr->SiS_SensibleSR11 = TRUE; 3900 } 3901 pSiS->SiS_Pr->SiS_MyCR63 = pSiS->myCR63; 3902 pSiS->SiS_Pr->DDCPortMixup = FALSE; 3903 } 3904 3905 /* Copy IO address to SiS_Pr and init the structure for 3906 * routines inside init.c/init301.c 3907 */ 3908 pSiS->SiS_Pr->IOAddress = (SISIOADDRESS)(pSiS->RelIO + 0x30); 3909 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO + 0x30); 3910 3911 /* The following identifies the old chipsets. This is only 3912 * partly used since the really old chips are not supported, 3913 * but I keep it here for future use. 3914 * 205, 215 and 225 are to be treated the same way, 201 and 202 3915 * are different. 3916 */ 3917 if(pSiS->VGAEngine == SIS_OLD_VGA || pSiS->VGAEngine == SIS_530_VGA) { 3918 switch(pSiS->Chipset) { 3919 case PCI_CHIP_SG86C201: 3920 pSiS->oldChipset = OC_SIS86201; break; 3921 case PCI_CHIP_SG86C202: 3922 pSiS->oldChipset = OC_SIS86202; break; 3923 case PCI_CHIP_SG86C205: 3924 inSISIDXREG(SISSR, 0x10, tempreg); 3925 if(tempreg & 0x80) pSiS->oldChipset = OC_SIS6205B; 3926 else pSiS->oldChipset = (pSiS->ChipRev == 0x11) ? 3927 OC_SIS6205C : OC_SIS6205A; 3928 break; 3929 case PCI_CHIP_SIS82C204: 3930 pSiS->oldChipset = OC_SIS82204; break; 3931 case 0x6225: 3932 pSiS->oldChipset = OC_SIS6225; break; 3933 case PCI_CHIP_SIS5597: 3934 pSiS->oldChipset = OC_SIS5597; break; 3935 case PCI_CHIP_SIS6326: 3936 pSiS->oldChipset = OC_SIS6326; break; 3937 case PCI_CHIP_SIS530: 3938 if(sis_pci_read_host_bridge_u32(0x00) == 0x06201039) { 3939 pSiS->oldChipset = OC_SIS620; 3940 } else { 3941 if((pSiS->ChipRev & 0x0f) < 0x0a) 3942 pSiS->oldChipset = OC_SIS530A; 3943 else pSiS->oldChipset = OC_SIS530B; 3944 } 3945 break; 3946 default: 3947 pSiS->oldChipset = OC_UNKNOWN; 3948 } 3949 } 3950 3951 if(!xf86SetDepthBpp(pScrn, 0, 0, 0, pix24flags)) { 3952 SISErrorLog(pScrn, "xf86SetDepthBpp() error\n"); 3953 goto my_error_1; 3954 } 3955 3956 /* Check that the returned depth is one we support */ 3957 temp = 0; 3958 switch(pScrn->depth) { 3959 case 8: 3960 case 16: 3961 case 24: 3962 break; 3963 case 15: 3964 if((pSiS->VGAEngine == SIS_300_VGA) || 3965 (pSiS->VGAEngine == SIS_315_VGA)) { 3966 temp = 1; 3967 } 3968 break; 3969 default: 3970 temp = 1; 3971 } 3972 3973 if(temp) { 3974 SISErrorLog(pScrn, 3975 "Given color depth (%d) is not supported by this driver/chipset\n", 3976 pScrn->depth); 3977 goto my_error_1; 3978 } 3979 3980 xf86PrintDepthBpp(pScrn); 3981 3982 if( (((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) && 3983 (pScrn->bitsPerPixel == 24)) || 3984 ((pSiS->VGAEngine == SIS_OLD_VGA) && (pScrn->bitsPerPixel == 32)) ) { 3985 SISErrorLog(pScrn, 3986 "Framebuffer bpp %d not supported for this chipset\n", pScrn->bitsPerPixel); 3987 goto my_error_1; 3988 } 3989 3990 /* Get the depth24 pixmap format */ 3991 if(pScrn->depth == 24 && pix24bpp == 0) { 3992 pix24bpp = xf86GetBppFromDepth(pScrn, 24); 3993 } 3994 3995 /* 3996 * This must happen after pScrn->display has been set because 3997 * xf86SetWeight references it. 3998 */ 3999 if(pScrn->depth > 8) { 4000 /* The defaults are OK for us */ 4001 rgb zeros = {0, 0, 0}; 4002 4003 if(!xf86SetWeight(pScrn, zeros, zeros)) { 4004 SISErrorLog(pScrn, "xf86SetWeight() error\n"); 4005 goto my_error_1; 4006 } else { 4007 Bool ret = FALSE; 4008 switch(pScrn->depth) { 4009 case 15: 4010 if((pScrn->weight.red != 5) || 4011 (pScrn->weight.green != 5) || 4012 (pScrn->weight.blue != 5)) ret = TRUE; 4013 break; 4014 case 16: 4015 if((pScrn->weight.red != 5) || 4016 (pScrn->weight.green != 6) || 4017 (pScrn->weight.blue != 5)) ret = TRUE; 4018 break; 4019 case 24: 4020 if((pScrn->weight.red != 8) || 4021 (pScrn->weight.green != 8) || 4022 (pScrn->weight.blue != 8)) ret = TRUE; 4023 break; 4024 } 4025 if(ret) { 4026 SISErrorLog(pScrn, 4027 "RGB weight %d%d%d at depth %d not supported by hardware\n", 4028 (int)pScrn->weight.red, (int)pScrn->weight.green, 4029 (int)pScrn->weight.blue, pScrn->depth); 4030 goto my_error_1; 4031 } 4032 } 4033 } 4034 4035 /* Set the current layout parameters */ 4036 pSiS->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel; 4037 pSiS->CurrentLayout.depth = pScrn->depth; 4038 /* (Inside this function, we can use pScrn's contents anyway) */ 4039 4040 if(!xf86SetDefaultVisual(pScrn, -1)) { 4041 SISErrorLog(pScrn, "xf86SetDefaultVisual() error\n"); 4042 goto my_error_1; 4043 } else { 4044 /* We don't support DirectColor at > 8bpp */ 4045 if(pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { 4046 SISErrorLog(pScrn, 4047 "Given default visual (%s) is not supported at depth %d\n", 4048 xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); 4049 goto my_error_1; 4050 } 4051 } 4052 4053#ifdef SISDUALHEAD 4054 /* Due to palette & timing problems we don't support 8bpp in DHM */ 4055 if((pSiS->DualHeadMode) && (pScrn->bitsPerPixel <= 8)) { 4056 SISErrorLog(pScrn, "Color depth %d not supported in Dual Head mode.\n", 4057 pScrn->bitsPerPixel); 4058 goto my_error_1; 4059 } 4060#endif 4061 4062 /* Read BIOS for 300/315/330/340 series customization */ 4063 pSiS->SiS_Pr->VirtualRomBase = NULL; 4064 pSiS->BIOS = NULL; 4065 pSiS->SiS_Pr->UseROM = FALSE; 4066 pSiS->ROM661New = FALSE; 4067 pSiS->HaveXGIBIOS = FALSE; 4068 4069 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 4070#ifdef SISDUALHEAD 4071 if(pSiSEnt) { 4072 if(pSiSEnt->BIOS) { 4073 pSiS->BIOS = pSiSEnt->BIOS; 4074 pSiS->SiS_Pr->VirtualRomBase = pSiS->BIOS; 4075 pSiS->ROM661New = pSiSEnt->ROM661New; 4076 pSiS->HaveXGIBIOS = pSiSEnt->HaveXGIBIOS; 4077 } 4078 } 4079#endif 4080 if(!pSiS->BIOS) { 4081 if(!(pSiS->BIOS = xcalloc(1, BIOS_SIZE))) { 4082 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4083 "Could not allocate memory for video BIOS image\n"); 4084 } else { 4085 UShort mypciid = pSiS->Chipset; 4086 UShort mypcivendor = (pSiS->ChipFlags & SiSCF_IsXGI) ? PCI_VENDOR_XGI : PCI_VENDOR_SIS; 4087 Bool found = FALSE, readpci = FALSE; 4088 int biossize = BIOS_SIZE; 4089 4090 switch(pSiS->ChipType) { 4091 case SIS_315: mypciid = PCI_CHIP_SIS315; 4092 readpci = TRUE; 4093 break; 4094 case SIS_315PRO: mypciid = PCI_CHIP_SIS315PRO; 4095 readpci = TRUE; 4096 break; 4097 case SIS_300: 4098 case SIS_315H: 4099 case SIS_330: 4100 case SIS_340: 4101 case SIS_650: 4102 case SIS_760: 4103 case XGI_40: readpci = TRUE; 4104 break; 4105 case XGI_20: readpci = TRUE; 4106 biossize = 0x8000; 4107 break; 4108 } 4109#if XSERVER_LIBPCIACCESS 4110 if(readpci) { 4111 pSiS->PciInfo->rom_size = biossize; 4112 pci_device_read_rom(pSiS->PciInfo, pSiS->BIOS); 4113 if(SISCheckBIOS(pSiS, mypciid, mypcivendor, biossize)) { 4114 found = TRUE; 4115 } 4116 } 4117#else 4118 if(readpci) { 4119 xf86ReadPciBIOS(0, pSiS->PciTag, 0, pSiS->BIOS, biossize); 4120 if(SISCheckBIOS(pSiS, mypciid, mypcivendor, biossize)) { 4121 found = TRUE; 4122 } 4123 } 4124 4125 if(!found) { 4126 ULong segstart; 4127 for(segstart = BIOS_BASE; segstart < 0x000f0000; segstart += 0x00001000) { 4128 4129#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 4130 if(xf86ReadBIOS(segstart, 0, pSiS->BIOS, biossize) != biossize) continue; 4131#else 4132 if(xf86ReadDomainMemory(pSiS->PciTag, segstart, biossize, pSiS->BIOS) != biossize) continue; 4133#endif 4134 4135 if(!SISCheckBIOS(pSiS, mypciid, mypcivendor, biossize)) continue; 4136 4137 found = TRUE; 4138 break; 4139 } 4140 } 4141#endif 4142 if(found) { 4143 UShort romptr = pSiS->BIOS[0x16] | (pSiS->BIOS[0x17] << 8); 4144 pSiS->SiS_Pr->VirtualRomBase = pSiS->BIOS; 4145 if(pSiS->ChipFlags & SiSCF_IsXGI) { 4146 pSiS->HaveXGIBIOS = pSiS->SiS_Pr->SiS_XGIROM = TRUE; 4147 pSiS->SiS_Pr->UseROM = FALSE; 4148 if(pSiS->ChipFlags & SiSCF_IsXGIV3) { 4149 if(!(pSiS->BIOS[0x1d1] & 0x01)) { 4150 pSiS->SiS_Pr->DDCPortMixup = TRUE; 4151 } 4152 } 4153 } else { 4154 pSiS->ROM661New = SiSDetermineROMLayout661(pSiS->SiS_Pr); 4155 } 4156 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4157 "Video BIOS version \"%7s\" found (%s data layout)\n", 4158 &pSiS->BIOS[romptr], pSiS->ROM661New ? "new SiS" : 4159 (pSiS->HaveXGIBIOS ? "XGI" : "old SiS")); 4160 if(pSiS->SiS_Pr->DDCPortMixup) { 4161 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4162 "*** Buggy XGI V3XT card detected: If VGA and DVI are connected at the\n"); 4163 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4164 "*** same time, BIOS and driver will be unable to detect DVI connection.\n"); 4165 } 4166#ifdef SISDUALHEAD 4167 if(pSiSEnt) { 4168 pSiSEnt->BIOS = pSiS->BIOS; 4169 pSiSEnt->ROM661New = pSiS->ROM661New; 4170 pSiSEnt->HaveXGIBIOS = pSiS->HaveXGIBIOS; 4171 } 4172#endif 4173 } else { 4174 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4175 "Could not find/read video BIOS\n"); 4176 xfree(pSiS->BIOS); 4177 pSiS->BIOS = NULL; 4178 } 4179 } 4180 } 4181 4182 if(!(pSiS->ChipFlags & SiSCF_IsXGI)) { 4183 if(pSiS->BIOS) pSiS->SiS_Pr->UseROM = TRUE; 4184 else pSiS->SiS_Pr->UseROM = FALSE; 4185 } 4186 } 4187 4188 /* Evaluate options */ 4189 SiSOptions(pScrn); 4190 4191#ifdef SISMERGED 4192 /* Due to palette & timing problems we don't support 8bpp in MFBM */ 4193 if((pSiS->MergedFB) && (pScrn->bitsPerPixel <= 8)) { 4194 SISErrorLog(pScrn, "MergedFB: Color depth %d not supported, %s\n", 4195 pScrn->bitsPerPixel, mergeddisstr); 4196 pSiS->MergedFB = pSiS->MergedFBAuto = FALSE; 4197 } 4198#endif 4199 4200 /* Probe CPU features */ 4201#ifdef SISDUALHEAD 4202 if(pSiS->DualHeadMode) { 4203 pSiS->CPUFlags = pSiSEnt->CPUFlags; 4204 } 4205#endif 4206 if(!pSiS->CPUFlags) { 4207 pSiS->CPUFlags = SiSGetCPUFlags(pScrn); 4208 pSiS->CPUFlags |= SIS_CPUFL_FLAG; 4209#ifdef SISDUALHEAD 4210 if(pSiS->DualHeadMode) pSiSEnt->CPUFlags = pSiS->CPUFlags; 4211#endif 4212 } 4213 4214 /* We use a programamble clock */ 4215 pScrn->progClock = TRUE; 4216 4217 /* Set the bits per RGB for 8bpp mode */ 4218 if(pScrn->depth == 8) pScrn->rgbBits = 8; 4219 4220#ifdef SISDUALHEAD 4221 if(pSiS->DualHeadMode) { 4222 if(!pSiS->SecondHead) { 4223 /* Copy some option settings to entity private */ 4224 pSiSEnt->HWCursor = pSiS->HWCursor; 4225 pSiSEnt->NoAccel = pSiS->NoAccel; 4226 pSiSEnt->useEXA = pSiS->useEXA; 4227 pSiSEnt->restorebyset = pSiS->restorebyset; 4228 pSiSEnt->OptROMUsage = pSiS->OptROMUsage; 4229 pSiSEnt->OptUseOEM = pSiS->OptUseOEM; 4230 pSiSEnt->TurboQueue = pSiS->TurboQueue; 4231 pSiSEnt->forceCRT1 = pSiS->forceCRT1; 4232 pSiSEnt->ForceCRT1Type = pSiS->ForceCRT1Type; 4233 pSiSEnt->CRT1TypeForced = pSiS->CRT1TypeForced; 4234 pSiSEnt->ForceCRT2Type = pSiS->ForceCRT2Type; 4235 pSiSEnt->ForceTVType = pSiS->ForceTVType; 4236 pSiSEnt->ForceYPbPrType = pSiS->ForceYPbPrType; 4237 pSiSEnt->ForceYPbPrAR = pSiS->ForceYPbPrAR; 4238 pSiSEnt->UsePanelScaler = pSiS->UsePanelScaler; 4239 pSiSEnt->CenterLCD = pSiS->CenterLCD; 4240 pSiSEnt->DSTN = pSiS->DSTN; 4241 pSiSEnt->FSTN = pSiS->FSTN; 4242 pSiSEnt->OptTVStand = pSiS->OptTVStand; 4243 pSiSEnt->NonDefaultPAL = pSiS->NonDefaultPAL; 4244 pSiSEnt->NonDefaultNTSC = pSiS->NonDefaultNTSC; 4245 pSiSEnt->chtvtype = pSiS->chtvtype; 4246 pSiSEnt->OptTVOver = pSiS->OptTVOver; 4247 pSiSEnt->OptTVSOver = pSiS->OptTVSOver; 4248 pSiSEnt->chtvlumabandwidthcvbs = pSiS->chtvlumabandwidthcvbs; 4249 pSiSEnt->chtvlumabandwidthsvideo = pSiS->chtvlumabandwidthsvideo; 4250 pSiSEnt->chtvlumaflickerfilter = pSiS->chtvlumaflickerfilter; 4251 pSiSEnt->chtvchromabandwidth = pSiS->chtvchromabandwidth; 4252 pSiSEnt->chtvchromaflickerfilter = pSiS->chtvchromaflickerfilter; 4253 pSiSEnt->chtvtextenhance = pSiS->chtvtextenhance; 4254 pSiSEnt->chtvcontrast = pSiS->chtvcontrast; 4255 pSiSEnt->chtvcvbscolor = pSiS->chtvcvbscolor; 4256 pSiSEnt->sistvedgeenhance = pSiS->sistvedgeenhance; 4257 pSiSEnt->sistvantiflicker = pSiS->sistvantiflicker; 4258 pSiSEnt->sistvsaturation = pSiS->sistvsaturation; 4259 pSiSEnt->sistvcfilter = pSiS->sistvcfilter; 4260 pSiSEnt->sistvyfilter = pSiS->sistvyfilter; 4261 pSiSEnt->sistvcolcalibc = pSiS->sistvcolcalibc; 4262 pSiSEnt->sistvcolcalibf = pSiS->sistvcolcalibf; 4263 pSiSEnt->tvxpos = pSiS->tvxpos; 4264 pSiSEnt->tvypos = pSiS->tvypos; 4265 pSiSEnt->tvxscale = pSiS->tvxscale; 4266 pSiSEnt->tvyscale = pSiS->tvyscale; 4267 pSiSEnt->siscrt1satgain = pSiS->siscrt1satgain; 4268 pSiSEnt->crt1satgaingiven = pSiS->crt1satgaingiven; 4269 pSiSEnt->CRT1gamma = pSiS->CRT1gamma; 4270 pSiSEnt->CRT1gammaGiven = pSiS->CRT1gammaGiven; 4271 pSiSEnt->XvGammaRed = pSiS->XvGammaRed; 4272 pSiSEnt->XvGammaGreen = pSiS->XvGammaGreen; 4273 pSiSEnt->XvGammaBlue = pSiS->XvGammaBlue; 4274 pSiSEnt->XvGamma = pSiS->XvGamma; 4275 pSiSEnt->XvGammaGiven = pSiS->XvGammaGiven; 4276 pSiSEnt->CRT2gamma = pSiS->CRT2gamma; 4277 pSiSEnt->XvOnCRT2 = pSiS->XvOnCRT2; 4278 pSiSEnt->AllowHotkey = pSiS->AllowHotkey; 4279 pSiSEnt->enablesisctrl = pSiS->enablesisctrl; 4280 pSiSEnt->SenseYPbPr = pSiS->SenseYPbPr; 4281 pSiSEnt->XvUseMemcpy = pSiS->XvUseMemcpy; 4282 pSiSEnt->BenchMemCpy = pSiS->BenchMemCpy; 4283#ifdef SIS_CP 4284 SIS_CP_DRIVER_COPYOPTIONSENT 4285#endif 4286 } else { 4287 /* We always use same cursor type on both screens */ 4288 pSiS->HWCursor = pSiSEnt->HWCursor; 4289 /* We need identical NoAccel setting */ 4290 pSiS->NoAccel = pSiSEnt->NoAccel; 4291 pSiS->useEXA = pSiSEnt->useEXA; 4292 pSiS->TurboQueue = pSiSEnt->TurboQueue; 4293 pSiS->restorebyset = pSiSEnt->restorebyset; 4294 pSiS->AllowHotkey = pSiS->AllowHotkey; 4295 pSiS->OptROMUsage = pSiSEnt->OptROMUsage; 4296 pSiS->OptUseOEM = pSiSEnt->OptUseOEM; 4297 pSiS->forceCRT1 = pSiSEnt->forceCRT1; 4298 pSiS->nocrt2ddcdetection = FALSE; 4299 pSiS->forcecrt2redetection = FALSE; 4300 pSiS->ForceCRT1Type = pSiSEnt->ForceCRT1Type; 4301 pSiS->ForceCRT2Type = pSiSEnt->ForceCRT2Type; 4302 pSiS->CRT1TypeForced = pSiSEnt->CRT1TypeForced; 4303 pSiS->UsePanelScaler = pSiSEnt->UsePanelScaler; 4304 pSiS->CenterLCD = pSiSEnt->CenterLCD; 4305 pSiS->DSTN = pSiSEnt->DSTN; 4306 pSiS->FSTN = pSiSEnt->FSTN; 4307 pSiS->OptTVStand = pSiSEnt->OptTVStand; 4308 pSiS->NonDefaultPAL = pSiSEnt->NonDefaultPAL; 4309 pSiS->NonDefaultNTSC = pSiSEnt->NonDefaultNTSC; 4310 pSiS->chtvtype = pSiSEnt->chtvtype; 4311 pSiS->ForceTVType = pSiSEnt->ForceTVType; 4312 pSiS->ForceYPbPrType = pSiSEnt->ForceYPbPrType; 4313 pSiS->ForceYPbPrAR = pSiSEnt->ForceYPbPrAR; 4314 pSiS->OptTVOver = pSiSEnt->OptTVOver; 4315 pSiS->OptTVSOver = pSiSEnt->OptTVSOver; 4316 pSiS->chtvlumabandwidthcvbs = pSiSEnt->chtvlumabandwidthcvbs; 4317 pSiS->chtvlumabandwidthsvideo = pSiSEnt->chtvlumabandwidthsvideo; 4318 pSiS->chtvlumaflickerfilter = pSiSEnt->chtvlumaflickerfilter; 4319 pSiS->chtvchromabandwidth = pSiSEnt->chtvchromabandwidth; 4320 pSiS->chtvchromaflickerfilter = pSiSEnt->chtvchromaflickerfilter; 4321 pSiS->chtvcvbscolor = pSiSEnt->chtvcvbscolor; 4322 pSiS->chtvtextenhance = pSiSEnt->chtvtextenhance; 4323 pSiS->chtvcontrast = pSiSEnt->chtvcontrast; 4324 pSiS->sistvedgeenhance = pSiSEnt->sistvedgeenhance; 4325 pSiS->sistvantiflicker = pSiSEnt->sistvantiflicker; 4326 pSiS->sistvsaturation = pSiSEnt->sistvsaturation; 4327 pSiS->sistvcfilter = pSiSEnt->sistvcfilter; 4328 pSiS->sistvyfilter = pSiSEnt->sistvyfilter; 4329 pSiS->sistvcolcalibc = pSiSEnt->sistvcolcalibc; 4330 pSiS->sistvcolcalibf = pSiSEnt->sistvcolcalibf; 4331 pSiS->tvxpos = pSiSEnt->tvxpos; 4332 pSiS->tvypos = pSiSEnt->tvypos; 4333 pSiS->tvxscale = pSiSEnt->tvxscale; 4334 pSiS->tvyscale = pSiSEnt->tvyscale; 4335 pSiS->SenseYPbPr = pSiSEnt->SenseYPbPr; 4336 if(!pSiS->CRT1gammaGiven) { 4337 if(pSiSEnt->CRT1gammaGiven) 4338 pSiS->CRT1gamma = pSiSEnt->CRT1gamma; 4339 } 4340 pSiS->CRT2gamma = pSiSEnt->CRT2gamma; 4341 if(!pSiS->XvGammaGiven) { 4342 if(pSiSEnt->XvGammaGiven) { 4343 pSiS->XvGamma = pSiSEnt->XvGamma; 4344 pSiS->XvGammaRed = pSiS->XvGammaRedDef = pSiSEnt->XvGammaRed; 4345 pSiS->XvGammaGreen = pSiS->XvGammaGreenDef = pSiSEnt->XvGammaGreen; 4346 pSiS->XvGammaBlue = pSiS->XvGammaBlueDef = pSiSEnt->XvGammaBlue; 4347 } 4348 } 4349 if(!pSiS->crt1satgaingiven) { 4350 if(pSiSEnt->crt1satgaingiven) 4351 pSiS->siscrt1satgain = pSiSEnt->siscrt1satgain; 4352 } 4353 pSiS->XvOnCRT2 = pSiSEnt->XvOnCRT2; 4354 pSiS->enablesisctrl = pSiSEnt->enablesisctrl; 4355 pSiS->XvUseMemcpy = pSiSEnt->XvUseMemcpy; 4356 pSiS->BenchMemCpy = pSiSEnt->BenchMemCpy; 4357 /* Copy gamma brightness to Ent (sic!) for Xinerama */ 4358 pSiSEnt->GammaBriR = pSiS->GammaBriR; 4359 pSiSEnt->GammaBriG = pSiS->GammaBriG; 4360 pSiSEnt->GammaBriB = pSiS->GammaBriB; 4361 pSiSEnt->NewGammaBriR = pSiS->NewGammaBriR; 4362 pSiSEnt->NewGammaBriG = pSiS->NewGammaBriG; 4363 pSiSEnt->NewGammaBriB = pSiS->NewGammaBriB; 4364 pSiSEnt->NewGammaConR = pSiS->NewGammaConR; 4365 pSiSEnt->NewGammaConG = pSiS->NewGammaConG; 4366 pSiSEnt->NewGammaConB = pSiS->NewGammaConB; 4367#ifdef SIS_CP 4368 SIS_CP_DRIVER_COPYOPTIONS 4369#endif 4370 } 4371 } 4372#endif 4373 4374 /* Handle UseROMData, NoOEM and UsePanelScaler options */ 4375 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 4376 from = X_PROBED; 4377 if(pSiS->OptROMUsage == 0) { 4378 pSiS->SiS_Pr->UseROM = FALSE; 4379 from = X_CONFIG; 4380 xf86DrvMsg(pScrn->scrnIndex, from, "Video ROM data usage is disabled\n"); 4381 } 4382 4383 if(!pSiS->OptUseOEM) { 4384 xf86DrvMsg(pScrn->scrnIndex, from, "Internal OEM LCD/TV/VGA2 data usage is disabled\n"); 4385 } 4386 4387 pSiS->SiS_Pr->UsePanelScaler = pSiS->UsePanelScaler; 4388 pSiS->SiS_Pr->CenterScreen = pSiS->CenterLCD; 4389 } 4390 4391 /* Do some HW configuration detection (memory amount & type, clock, etc) */ 4392 SiSSetup(pScrn); 4393 4394 /* Get framebuffer address */ 4395 if(pSiS->pEnt->device->MemBase != 0) { 4396 /* 4397 * XXX Should check that the config file value matches one of the 4398 * PCI base address values. 4399 */ 4400 pSiS->FbAddress = pSiS->pEnt->device->MemBase; 4401 from = X_CONFIG; 4402 } else { 4403 pSiS->FbAddress = PCI_REGION_BASE(pSiS->PciInfo, 0, REGION_MEM) & 0xFFFFFFF0; 4404 from = X_PROBED; 4405 } 4406 4407#ifdef SISDUALHEAD 4408 if(pSiS->DualHeadMode) 4409 xf86DrvMsg(pScrn->scrnIndex, from, "Global linear framebuffer at 0x%lX\n", 4410 (ULong)pSiS->FbAddress); 4411 else 4412#endif 4413 xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", 4414 (ULong)pSiS->FbAddress); 4415 4416 pSiS->realFbAddress = pSiS->FbAddress; 4417 4418 /* Get MMIO address */ 4419 if(pSiS->pEnt->device->IOBase != 0) { 4420 /* 4421 * XXX Should check that the config file value matches one of the 4422 * PCI base address values. 4423 */ 4424 pSiS->IOAddress = pSiS->pEnt->device->IOBase; 4425 from = X_CONFIG; 4426 } else { 4427 pSiS->IOAddress = PCI_REGION_BASE(pSiS->PciInfo, 1, REGION_MEM) & 0xFFFFFFF0; 4428 from = X_PROBED; 4429 } 4430 xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX (size %ldK)\n", 4431 (ULong)pSiS->IOAddress, pSiS->mmioSize); 4432 4433#ifndef XSERVER_LIBPCIACCESS 4434 /* Register the PCI-assigned resources */ 4435 if(xf86RegisterResources(pSiS->pEnt->index, NULL, ResExclusive)) { 4436 SISErrorLog(pScrn, "PCI resource conflicts detected\n"); 4437#ifdef SISDUALHEAD 4438 if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; 4439#endif 4440 sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); 4441 if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); 4442 SISFreeRec(pScrn); 4443 return FALSE; 4444 } 4445#endif 4446 4447 from = X_PROBED; 4448 if(pSiS->pEnt->device->videoRam != 0) { 4449 if(pSiS->Chipset == PCI_CHIP_SIS6326) { 4450 pScrn->videoRam = pSiS->pEnt->device->videoRam; 4451 from = X_CONFIG; 4452 } else { 4453 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4454 "Option \"VideoRAM\" ignored\n"); 4455 } 4456 } 4457 4458 pSiS->RealVideoRam = pScrn->videoRam; 4459 4460 if((pSiS->Chipset == PCI_CHIP_SIS6326) && 4461 (pScrn->videoRam > 4096) && 4462 (from != X_CONFIG)) { 4463 pScrn->videoRam = 4096; 4464 xf86DrvMsg(pScrn->scrnIndex, from, 4465 "SiS6326: Detected %d KB VideoRAM, limiting to %d KB\n", 4466 pSiS->RealVideoRam, pScrn->videoRam); 4467 } else { 4468 xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d KB\n", pScrn->videoRam); 4469 } 4470 4471 if((pSiS->Chipset == PCI_CHIP_SIS6326) && 4472 (pScrn->videoRam > 4096)) { 4473 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4474 "SiS6326 engines do not support more than 4096KB RAM, therefore\n"); 4475 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4476 "TurboQueue, HWCursor, 2D acceleration and XVideo are disabled.\n"); 4477 pSiS->TurboQueue = FALSE; 4478 pSiS->HWCursor = FALSE; 4479 pSiS->NoXvideo = TRUE; 4480 pSiS->NoAccel = TRUE; 4481 } 4482 4483 pSiS->FbMapSize = pSiS->availMem = pScrn->videoRam * 1024; 4484 4485 /* Calculate real availMem according to Accel/TurboQueue and 4486 * HWCursur setting. Also, initialize some variables used 4487 * in other modules. 4488 */ 4489 pSiS->cursorOffset = 0; 4490 pSiS->CurARGBDest = NULL; 4491 pSiS->CurMonoSrc = NULL; 4492 pSiS->CurFGCol = pSiS->CurBGCol = 0; 4493 pSiS->FbBaseOffset = 0; 4494 4495 switch(pSiS->VGAEngine) { 4496 4497 case SIS_300_VGA: 4498 pSiS->TurboQueueLen = 512; 4499 if(pSiS->TurboQueue) { 4500 pSiS->availMem -= (pSiS->TurboQueueLen*1024); 4501 pSiS->cursorOffset = 512; 4502 } 4503 if(pSiS->HWCursor) { 4504 pSiS->availMem -= pSiS->CursorSize; 4505 if(pSiS->OptUseColorCursor) pSiS->availMem -= pSiS->CursorSize; 4506 } 4507 pSiS->CmdQueLenMask = 0xFFFF; 4508 pSiS->CmdQueLenFix = 0; 4509 pSiS->cursorBufferNum = 0; 4510#ifdef SISDUALHEAD 4511 if(pSiSEnt) pSiSEnt->cursorBufferNum = 0; 4512#endif 4513 break; 4514 4515 case SIS_315_VGA: 4516#ifdef SISVRAMQ /* VRAM queue */ 4517 pSiS->cmdQueueSizeMask = pSiS->cmdQueueSize - 1; /* VRAM Command Queue is variable (in therory) */ 4518 pSiS->cmdQueueOffset = (pScrn->videoRam * 1024) - pSiS->cmdQueueSize; 4519 pSiS->cmdQueueLen = 0; 4520 pSiS->cmdQueueSize_div2 = pSiS->cmdQueueSize / 2; 4521 pSiS->cmdQueueSize_div4 = pSiS->cmdQueueSize / 4; 4522 pSiS->cmdQueueSize_4_3 = (pSiS->cmdQueueSize / 4) * 3; 4523 pSiS->availMem -= pSiS->cmdQueueSize; 4524 pSiS->cursorOffset = (pSiS->cmdQueueSize / 1024); 4525 4526 /* Set up shared pointer to current offset */ 4527#ifdef SISDUALHEAD 4528 if(pSiS->DualHeadMode) 4529 pSiS->cmdQ_SharedWritePort = &(pSiSEnt->cmdQ_SharedWritePort_2D); 4530 else 4531#endif 4532 pSiS->cmdQ_SharedWritePort = &(pSiS->cmdQ_SharedWritePort_2D); 4533 4534 4535#else /* MMIO */ 4536 if(pSiS->TurboQueue) { 4537 pSiS->availMem -= (512*1024); /* MMIO Command Queue is 512k (variable in theory) */ 4538 pSiS->cursorOffset = 512; 4539 } 4540#endif 4541 if(pSiS->HWCursor) { 4542 pSiS->availMem -= (pSiS->CursorSize * 2); 4543 if(pSiS->OptUseColorCursor) pSiS->availMem -= (pSiS->CursorSize * 2); 4544 } 4545 pSiS->cursorBufferNum = 0; 4546#ifdef SISDUALHEAD 4547 if(pSiSEnt) pSiSEnt->cursorBufferNum = 0; 4548#endif 4549 4550 if((pSiS->SiS76xLFBSize) && (pSiS->SiS76xUMASize)) { 4551 pSiS->availMem -= pSiS->SiS76xUMASize; 4552 pSiS->FbBaseOffset = pSiS->SiS76xUMASize; 4553 } 4554 4555 break; 4556 4557 default: 4558 /* cursorOffset not used in cursor functions for 530 and 4559 * older chips, because the cursor is *above* the TQ. 4560 * On 5597 and older revisions of the 6326, the TQ is 4561 * max 32K, on newer 6326 revisions and the 530 either 30 4562 * (or 32?) or 62K (or 64?). However, to make sure, we 4563 * use only 30K (or 32?), but reduce the available memory 4564 * by 64, and locate the TQ at the beginning of this last 4565 * 64K block. (We do this that way even when using the 4566 * HWCursor, because the cursor only takes 2K and the 4567 * queue does not seem to last that far anyway.) 4568 * The TQ must be located at 32KB boundaries. 4569 */ 4570 if(pSiS->RealVideoRam < 3072) { 4571 if(pSiS->TurboQueue) { 4572 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4573 "Not enough video RAM for TurboQueue. TurboQueue disabled\n"); 4574 pSiS->TurboQueue = FALSE; 4575 } 4576 } 4577 pSiS->CmdQueMaxLen = 32; 4578 if(pSiS->TurboQueue) { 4579 pSiS->availMem -= (64*1024); 4580 pSiS->CmdQueMaxLen = 900; /* To make sure; should be 992 */ 4581 } else if(pSiS->HWCursor) { 4582 pSiS->availMem -= pSiS->CursorSize; 4583 } 4584 if(pSiS->Chipset == PCI_CHIP_SIS530) { 4585 /* Check if Flat Panel is enabled */ 4586 inSISIDXREG(SISSR, 0x0e, tempreg); 4587 if(!(tempreg & 0x04)) pSiS->availMem -= pSiS->CursorSize; 4588 4589 /* Set up mask for MMIO register */ 4590 pSiS->CmdQueLenMask = (pSiS->TurboQueue) ? 0x1FFF : 0x00FF; 4591 } else { 4592 /* TQ is never used on 6326/5597, because the accelerator 4593 * always Syncs. So this is just cosmentic work. (And I 4594 * am not even sure that 0x7fff is correct. MMIO 0x83a8 4595 * holds 0xec0 if (30k) TQ is enabled, 0x20 if TQ disabled. 4596 * The datasheet has no real explanation on the queue length 4597 * if the TQ is enabled. Not syncing and waiting for a 4598 * suitable queue length instead does not work. 4599 */ 4600 pSiS->CmdQueLenMask = (pSiS->TurboQueue) ? 0x7FFF : 0x003F; 4601 } 4602 4603 /* This is to be subtracted from MMIO queue length register contents 4604 * for getting the real Queue length. 4605 */ 4606 pSiS->CmdQueLenFix = (pSiS->TurboQueue) ? 32 : 0; 4607 } 4608 4609 4610#ifdef SISDUALHEAD 4611 /* In dual head mode, we share availMem equally - so align it 4612 * to 8KB; this way, the address of the FB of the second 4613 * head is aligned to 4KB for mapping. 4614 */ 4615 if(pSiS->DualHeadMode) pSiS->availMem &= 0xFFFFE000; 4616#endif 4617 4618 /* Check MaxXFBMem setting */ 4619#ifdef SISDUALHEAD 4620 if(pSiS->DualHeadMode) { 4621 /* 1. Since DRI is not supported in dual head mode, we 4622 * don't need the MaxXFBMem setting - ignore it. 4623 */ 4624 if(pSiS->maxxfbmem) { 4625 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4626 "MaxXFBMem ignored in Dual Head mode\n"); 4627 } 4628 pSiS->maxxfbmem = pSiS->availMem; 4629 } else 4630#endif 4631 if((pSiS->sisfbHeapStart) || (pSiS->sisfbHaveNewHeapDef)) { 4632 4633 /* 4634 * 2. We have memory layout info from sisfb - ignore MaxXFBMem 4635 */ 4636 if(pSiS->maxxfbmem) { 4637 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4638 "Got memory layout info from sisfb, ignoring MaxXFBMem option\n"); 4639 } 4640 if((pSiS->FbBaseOffset) && (!pSiS->sisfbHaveNewHeapDef)) { 4641 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4642 "Incompatible sisfb version detected, DRI disabled\n"); 4643 pSiS->loadDRI = FALSE; 4644 pSiS->maxxfbmem = pSiS->availMem; 4645 } else { 4646 if(pSiS->FbBaseOffset) { 4647 /* Revert our changes to FbBaseOffset and availMem; use sisfb's info */ 4648 pSiS->availMem += pSiS->FbBaseOffset; 4649 pSiS->FbBaseOffset = 0; 4650 } 4651 if(pSiS->sisfbVideoOffset) { 4652 /* a. DRI heap BELOW framebuffer */ 4653 pSiS->FbBaseOffset = pSiS->sisfbVideoOffset; 4654 pSiS->availMem -= pSiS->FbBaseOffset; 4655 pSiS->maxxfbmem = pSiS->availMem; 4656 } else { 4657 /* b. DRI heap ABOVE framebuffer (traditional layout) */ 4658 if(pSiS->availMem < (pSiS->sisfbHeapStart * 1024)) { 4659 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4660 "Internal error - sisfb memory layout corrupt\n"); 4661 pSiS->loadDRI = FALSE; 4662 pSiS->maxxfbmem = pSiS->availMem; 4663 } else { 4664 pSiS->maxxfbmem = pSiS->sisfbHeapStart * 1024; 4665 } 4666 } 4667 } 4668 4669 } else if(pSiS->maxxfbmem) { 4670 4671 /* 4672 * 3. No sisfb, but user gave "MaxXFBMem" 4673 */ 4674 if(pSiS->FbBaseOffset) { 4675 /* a. DRI heap BELOW framebuffer */ 4676 if(pSiS->maxxfbmem > (pSiS->availMem + pSiS->FbBaseOffset - pSiS->SiS76xUMASize)) { 4677 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4678 "Invalid MaxXFBMem setting\n"); 4679 pSiS->maxxfbmem = pSiS->availMem; 4680 } else { 4681 /* Revert our changes */ 4682 pSiS->availMem += pSiS->FbBaseOffset; 4683 /* Use user's MaxXFBMem setting */ 4684 pSiS->FbBaseOffset = pSiS->availMem - pSiS->maxxfbmem; 4685 pSiS->availMem -= pSiS->FbBaseOffset; 4686 } 4687 } else { 4688 /* b. DRI heap ABOVE framebuffer (traditional layout) */ 4689 if(pSiS->maxxfbmem > pSiS->availMem) { 4690 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4691 "Invalid MaxXFBMem setting.\n"); 4692 pSiS->maxxfbmem = pSiS->availMem; 4693 } 4694 } 4695 4696 } else { 4697 4698 /* 4699 * 4. No MaxXFBMem, no sisfb: Use all memory 4700 */ 4701 pSiS->maxxfbmem = pSiS->availMem; 4702 4703 /* ... except on chipsets, for which DRI is 4704 * supported: If DRI is enabled, we now limit 4705 * ourselves to a reasonable default: 4706 */ 4707 4708 if(pSiS->loadDRI) { 4709 if(pSiS->FbBaseOffset) { 4710 /* a. DRI heap BELOW framebuffer */ 4711 /* See how much UMA and LFB memory we have, 4712 * and calculate a reasonable default. We 4713 * use more vram for ourselves because these 4714 * chips are eg. capable of larger Xv 4715 * overlays, etc. 4716 */ 4717 unsigned long total = (pSiS->SiS76xLFBSize + pSiS->SiS76xUMASize) / 1024; 4718 unsigned long mymax; 4719 if(total <= 16384) /* <= 16MB: Use 8MB for X */ 4720 mymax = 8192 * 1024; 4721 else if(total <= 32768) /* <= 32MB: Use 16MB for X */ 4722 mymax = 16384 * 1024; 4723 else /* Otherwise: Use 20MB for X */ 4724 mymax = 20 * 1024 * 1024; 4725 /* availMem is right now adjusted to not use the UMA 4726 * area. Make sure that our default doesn't reach 4727 * into the UMA area either. 4728 */ 4729 if(pSiS->availMem > mymax) { 4730 /* Write our default to maxxfbmem */ 4731 pSiS->maxxfbmem = mymax; 4732 /* Revert our changes to availMem */ 4733 pSiS->availMem += pSiS->FbBaseOffset; 4734 /* Use our default setting */ 4735 pSiS->FbBaseOffset = pSiS->availMem - pSiS->maxxfbmem; 4736 pSiS->availMem -= pSiS->FbBaseOffset; 4737 } 4738 } else { 4739 /* b. DRI heap ABOVE framebuffer (traditional layout) */ 4740 /* See how much video memory we have, and calculate 4741 * a reasonable default. 4742 * Since DRI is pointless with less than 4MB of total 4743 * video RAM, we disable it in that case. 4744 */ 4745 if(pScrn->videoRam <= 4096) 4746 pSiS->loadDRI = FALSE; 4747 else if(pScrn->videoRam <= 8192) /* <= 8MB: Use 4MB for X */ 4748 pSiS->maxxfbmem = 4096 * 1024; 4749 else if(pScrn->videoRam <= 16384) /* <= 16MB: Use 8MB for X */ 4750 pSiS->maxxfbmem = 8192 * 1024; 4751#ifdef SISMERGED /* Otherwise: --- */ 4752 else if(pSiS->MergedFB) { 4753 if(pScrn->videoRam <= 65536) 4754 pSiS->maxxfbmem = 16384 * 1024; /* If MergedFB and <=64MB, use 16MB for X */ 4755 else 4756 pSiS->maxxfbmem = 20 * 1024 * 1024; /* If MergedFB and > 64MB, use 20MB for X */ 4757 } 4758#endif 4759 else if(pSiS->VGAEngine == SIS_315_VGA) { 4760 if(pScrn->videoRam <= 65536) 4761 pSiS->maxxfbmem = 16384 * 1024; /* On >=315 series and <=64MB, use 16MB */ 4762 else 4763 pSiS->maxxfbmem = 20 * 1024 * 1024; /* On >=315 series and > 64MB, use 20MB */ 4764 } else 4765 pSiS->maxxfbmem = 12288 * 1024; /* On <315 series, use 12MB */ 4766 4767 /* A final check */ 4768 if(pSiS->maxxfbmem > pSiS->availMem) { 4769 pSiS->maxxfbmem = pSiS->availMem; 4770 pSiS->loadDRI = FALSE; 4771 } 4772 } 4773 4774 } 4775 } 4776 4777 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %dK of framebuffer memory at offset %dK\n", 4778 pSiS->maxxfbmem / 1024, pSiS->FbBaseOffset / 1024); 4779 4780 /* Find out about sub-classes of some chipsets and check 4781 * if the chipset supports two video overlays 4782 */ 4783 if(pSiS->VGAEngine == SIS_300_VGA || 4784 pSiS->VGAEngine == SIS_315_VGA || 4785 pSiS->Chipset == PCI_CHIP_SIS530 || 4786 pSiS->Chipset == PCI_CHIP_SIS6326 || 4787 pSiS->Chipset == PCI_CHIP_SIS5597) { 4788 pSiS->hasTwoOverlays = FALSE; 4789 switch(pSiS->Chipset) { 4790 case PCI_CHIP_SIS300: 4791 case PCI_CHIP_SIS540: /* ? (If not, need to add the SwitchCRT Xv attribute!) */ 4792 case PCI_CHIP_SIS630: 4793 case PCI_CHIP_SIS550: 4794 pSiS->hasTwoOverlays = TRUE; 4795 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4796 break; 4797 case PCI_CHIP_SIS315PRO: 4798 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4799 break; 4800 case PCI_CHIP_SIS330: 4801 pSiS->ChipFlags |= (SiSCF_CRT2HWCKaputt | SiSCF_LARGEOVERLAY); 4802 break; 4803 case PCI_CHIP_SIS340: 4804 case PCI_CHIP_XGIXG40: /* Verified: only 1 overlay */ 4805 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4806 break; 4807 case PCI_CHIP_SIS650: 4808 { 4809 UChar tempreg1, tempreg2; 4810 static const char *id650str[] = { 4811 "650", "650", "650", "650", 4812 "650 A0 AA", "650 A2 CA", "650", "650", 4813 "M650 A0", "M650 A1 AA","651 A0 AA", "651 A1 AA", 4814 "M650", "65?", "651", "65?" 4815 }; 4816 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4817 if(pSiS->ChipType == SIS_650) { 4818 inSISIDXREG(SISCR, 0x5f, CR5F); 4819 CR5F &= 0xf0; 4820 andSISIDXREG(SISCR, 0x5c, 0x07); 4821 inSISIDXREG(SISCR, 0x5c, tempreg1); 4822 tempreg1 &= 0xf8; 4823 orSISIDXREG(SISCR, 0x5c, 0xf8); 4824 inSISIDXREG(SISCR, 0x5c, tempreg2); 4825 tempreg2 &= 0xf8; 4826 if((!tempreg1) || (tempreg2)) { 4827 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4828 "SiS650 revision ID %x (%s)\n", CR5F, id650str[CR5F >> 4]); 4829 if(CR5F & 0x80) { 4830 pSiS->hasTwoOverlays = TRUE; /* M650 or 651 */ 4831 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4832 } 4833 switch(CR5F) { 4834 case 0xa0: 4835 case 0xb0: 4836 case 0xe0: 4837 pSiS->ChipFlags |= SiSCF_Is651; 4838 break; 4839 case 0x80: 4840 case 0x90: 4841 case 0xc0: 4842 pSiS->ChipFlags |= SiSCF_IsM650; 4843 break; 4844 } 4845 } else { 4846 pSiS->hasTwoOverlays = TRUE; 4847 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4848 switch(CR5F) { 4849 case 0x90: 4850 inSISIDXREG(SISCR, 0x5c, tempreg1); 4851 tempreg1 &= 0xf8; 4852 switch(tempreg1) { 4853 case 0x00: 4854 pSiS->ChipFlags |= SiSCF_IsM652; 4855 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4856 "SiSM652 revision ID %x\n", CR5F); 4857 break; 4858 case 0x40: 4859 pSiS->ChipFlags |= SiSCF_IsM653; 4860 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4861 "SiSM653 revision ID %x\n", CR5F); 4862 break; 4863 default: 4864 pSiS->ChipFlags |= SiSCF_IsM650; 4865 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4866 "SiSM650 revision ID %x\n", CR5F); 4867 break; 4868 } 4869 break; 4870 case 0xb0: 4871 pSiS->ChipFlags |= SiSCF_Is652; 4872 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4873 "SiS652 revision ID %x\n", CR5F); 4874 break; 4875 default: 4876 pSiS->ChipFlags |= SiSCF_IsM650; 4877 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4878 "SiSM650 revision ID %x\n", CR5F); 4879 break; 4880 } 4881 } 4882 } 4883 break; 4884 } 4885 case PCI_CHIP_SIS660: 4886 { 4887 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4888 pSiS->hasTwoOverlays = TRUE; 4889 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4890 /* 760/761: - UMA only: one/two overlays - dotclock dependent 4891 - UMA+LFB: two overlays if video data in LFB 4892 - LFB only: two overlays 4893 If UMA only: Must switch between one/two overlays on the fly (done 4894 in PostSetMode()) 4895 If LFB+UMA: We use LFB memory only and leave UMA to an eventually 4896 written DRI driver. 4897 */ 4898 break; 4899 } 4900 } 4901 4902 if(!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY)) { 4903 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4904 "Hardware supports %s video overlay%s\n", 4905 pSiS->hasTwoOverlays ? "two" : "one", 4906 pSiS->hasTwoOverlays ? "s" : ""); 4907 } 4908 4909 if(pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORT760OO) { 4910 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4911 "\n\tDear SiS76x user, your machine is using a shared memory framebuffer.\n" 4912 "\tDue to hardware limitations of the SiS chip in combination with the\n" 4913 "\tAMD CPU, video overlay support is very limited on this machine. If you\n" 4914 "\texperience flashing lines in the video and/or the graphics display\n" 4915 "\tduring video playback, reduce the color depth and/or the resolution\n" 4916 "\tand/or the refresh rate. Alternatively, use the video blitter.\n"); 4917 } 4918 4919 } 4920 4921 /* Backup VB connection and CRT1 on/off register */ 4922 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 4923 inSISIDXREG(SISSR, 0x1f, pSiS->oldSR1F); 4924 inSISIDXREG(SISCR, 0x17, pSiS->oldCR17); 4925 inSISIDXREG(SISCR, 0x32, pSiS->oldCR32); 4926 inSISIDXREG(SISCR, 0x36, pSiS->oldCR36); 4927 inSISIDXREG(SISCR, 0x37, pSiS->oldCR37); 4928 if(pSiS->VGAEngine == SIS_315_VGA) { 4929 inSISIDXREG(SISCR, pSiS->myCR63, pSiS->oldCR63); 4930 } 4931 4932 pSiS->postVBCR32 = pSiS->oldCR32; 4933 } 4934 4935 /* There are some machines out there which require a special 4936 * setup of the GPIO registers in order to make the Chrontel 4937 * work. Try to find out if we're running on such a machine. 4938 * Furthermore, there is some highly customized hardware, 4939 * which requires some non-standard LVDS timing. Since the 4940 * vendors don't seem to care about PCI subsystem ID's we 4941 * need to find out using the BIOS version and date strings. 4942 */ 4943 pSiS->SiS_Pr->SiS_ChSW = FALSE; 4944 if(pSiS->Chipset == PCI_CHIP_SIS630) { 4945 int i = 0; 4946 do { 4947 if(mychswtable[i].subsysVendor == PCI_SUB_VENDOR_ID(pSiS->PciInfo) && 4948 mychswtable[i].subsysCard == PCI_SUB_DEVICE_ID(pSiS->PciInfo)) { 4949 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4950 "PCI subsystem ID found in list for Chrontel/GPIO setup:\n"); 4951 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4952 "\tVendor/Card: %s %s (ID %04x)\n", 4953 mychswtable[i].vendorName, 4954 mychswtable[i].cardName, 4955 PCI_SUB_DEVICE_ID(pSiS->PciInfo)); 4956 pSiS->SiS_Pr->SiS_ChSW = TRUE; 4957 break; 4958 } 4959 i++; 4960 } while(mychswtable[i].subsysVendor != 0); 4961 } 4962 4963 if(pSiS->SiS_Pr->SiS_CustomT == CUT_NONE) { 4964 int i = 0, j; 4965 UShort bversptr = 0; 4966 Bool footprint; 4967 CARD32 chksum = 0; 4968 4969 if(pSiS->SiS_Pr->UseROM) { 4970 bversptr = pSiS->BIOS[0x16] | (pSiS->BIOS[0x17] << 8); 4971 for(i=0; i<32768; i++) chksum += pSiS->BIOS[i]; 4972 } 4973 4974 i = 0; 4975 do { 4976 if( (SiS_customttable[i].chipID == pSiS->ChipType) && 4977 ((!strlen(SiS_customttable[i].biosversion)) || 4978 (pSiS->SiS_Pr->UseROM && 4979 (!strncmp(SiS_customttable[i].biosversion, (char *)&pSiS->BIOS[bversptr], 4980 strlen(SiS_customttable[i].biosversion))))) && 4981 ((!strlen(SiS_customttable[i].biosdate)) || 4982 (pSiS->SiS_Pr->UseROM && 4983 (!strncmp(SiS_customttable[i].biosdate, (char *)&pSiS->BIOS[0x2c], 4984 strlen(SiS_customttable[i].biosdate))))) && 4985 ((!SiS_customttable[i].bioschksum) || 4986 (pSiS->SiS_Pr->UseROM && 4987 (SiS_customttable[i].bioschksum == chksum))) && 4988 (SiS_customttable[i].pcisubsysvendor == PCI_SUB_VENDOR_ID(pSiS->PciInfo)) && 4989 (SiS_customttable[i].pcisubsyscard == PCI_SUB_DEVICE_ID(pSiS->PciInfo)) ) { 4990 footprint = TRUE; 4991 for(j=0; j<5; j++) { 4992 if(SiS_customttable[i].biosFootprintAddr[j]) { 4993 if(pSiS->SiS_Pr->UseROM) { 4994 if(pSiS->BIOS[SiS_customttable[i].biosFootprintAddr[j]] != 4995 SiS_customttable[i].biosFootprintData[j]) 4996 footprint = FALSE; 4997 } else footprint = FALSE; 4998 } 4999 } 5000 if(footprint) { 5001 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5002 "Identified %s %s, special timing applies\n", 5003 SiS_customttable[i].vendorName, SiS_customttable[i].cardName); 5004 pSiS->SiS_Pr->SiS_CustomT = SiS_customttable[i].SpecialID; 5005 break; 5006 } 5007 } 5008 i++; 5009 } while(SiS_customttable[i].chipID); 5010 } 5011 5012 /* Handle ForceCRT1 option */ 5013 if(pSiS->forceCRT1 != -1) { 5014 if(pSiS->forceCRT1) pSiS->CRT1off = 0; 5015 else pSiS->CRT1off = 1; 5016 } else pSiS->CRT1off = -1; 5017 5018 /* Detect video bridge and sense TV/VGA2 */ 5019 SISVGAPreInit(pScrn); 5020 5021 /* Detect CRT1 (via DDC1 and DDC2, hence via VGA port; regardless of LCDA) */ 5022 SISCRT1PreInit(pScrn); 5023 5024 /* Detect LCD (connected via CRT2, regardless of LCDA) and LCD resolution */ 5025 SISLCDPreInit(pScrn, FALSE); 5026 5027 /* LCDA only supported under these conditions: */ 5028 if(pSiS->ForceCRT1Type == CRT1_LCDA) { 5029 if(!SISDetermineLCDACap(pScrn)) { 5030 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5031 "Chipset/Video bridge does not support LCD-via-CRT1\n"); 5032 pSiS->ForceCRT1Type = CRT1_VGA; 5033 } else if(!(pSiS->VBFlags & CRT2_LCD)) { 5034 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5035 "No digital LCD panel found, LCD-via-CRT1 disabled\n"); 5036 pSiS->ForceCRT1Type = CRT1_VGA; 5037 } 5038 } 5039 5040 /* Setup SD flags */ 5041 pSiS->SiS_SD_Flags |= SiS_SD_ADDLSUPFLAG; 5042 5043 pSiS->SiS_SD2_Flags |= SiS_SD2_MERGEDUCLOCK; 5044 pSiS->SiS_SD2_Flags |= SiS_SD2_USEVBFLAGS2; 5045 pSiS->SiS_SD2_Flags |= SiS_SD2_VBINVB2ONLY; 5046 pSiS->SiS_SD2_Flags |= SiS_SD2_HAVESD34; 5047 pSiS->SiS_SD2_Flags |= SiS_SD2_NEWGAMMABRICON; 5048 5049 pSiS->SiS_SD3_Flags |= SiS_SD3_MFBALLOWOFFCL; 5050 5051 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 5052 pSiS->SiS_SD2_Flags |= SiS_SD2_VIDEOBRIDGE; 5053 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 5054 pSiS->SiS_SD2_Flags |= ( SiS_SD2_SISBRIDGE | 5055 SiS_SD2_SUPPORTGAMMA2 ); 5056 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) { 5057 pSiS->SiS_SD2_Flags |= ( SiS_SD2_LCDLVDS | 5058 SiS_SD2_SUPPORTLCD ); 5059 } else if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 5060 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 5061 pSiS->SiS_SD2_Flags |= ( SiS_SD2_LCDTMDS | 5062 SiS_SD2_SUPPORTLCD ); 5063 } else if(pSiS->VBFlags & CRT2_LCD) { 5064 pSiS->SiS_SD2_Flags |= ( SiS_SD2_THIRDPARTYLVDS | 5065 SiS_SD2_SUPPORTLCD ); 5066 } 5067 } 5068 } else if(pSiS->VBFlags2 & VB2_LVDS) { 5069 pSiS->SiS_SD2_Flags |= ( SiS_SD2_THIRDPARTYLVDS | 5070 SiS_SD2_SUPPORTLCD ); 5071 } 5072 5073 if(pSiS->VBFlags2 & (VB2_SISTVBRIDGE | VB2_CHRONTEL)) { 5074 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTTV; 5075 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 5076 pSiS->SiS_SD2_Flags |= ( SiS_SD2_SUPPORTTVTYPE | 5077 SiS_SD2_SUPPORTTVSIZE ); 5078 if(!(pSiS->VBFlags2 & VB2_301)) { 5079 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPTVSAT; 5080 } else { 5081 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPTVEDGE; 5082 } 5083 } 5084 } 5085 } 5086 5087#ifdef ENABLE_YPBPR 5088 if((pSiS->VGAEngine == SIS_315_VGA) && 5089 (pSiS->VBFlags2 & VB2_SISYPBPRBRIDGE)) { 5090 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTYPBPR; 5091 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORT625I; 5092 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORT625P; 5093 if(pSiS->VBFlags2 & VB2_SISYPBPRARBRIDGE) { 5094 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTYPBPRAR; 5095 } 5096 } 5097 if(pSiS->VBFlags2 & VB2_SISHIVISIONBRIDGE) { 5098 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTHIVISION; 5099 } 5100#endif 5101 5102 if((pSiS->VGAEngine != SIS_300_VGA) || (!(pSiS->VBFlags2 & VB2_TRUMPION))) { 5103 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTSCALE; 5104 if((pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && 5105 (!(pSiS->VBFlags2 & VB2_30xBDH))) { 5106 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTCENTER; 5107 } 5108 } 5109 5110#ifdef SISDUALHEAD 5111 if(!pSiS->DualHeadMode) { 5112 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTREDETECT; 5113 } 5114#endif 5115 5116#ifndef SISCHECKOSSSE 5117 pSiS->SiS_SD2_Flags |= SiS_SD2_NEEDUSESSE; 5118#endif 5119 5120#ifdef TWDEBUG /* FOR TESTING */ 5121 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTYPBPRAR; 5122 xf86DrvMsg(0, X_INFO, "TEST: Support Aspect Ratio\n"); 5123#endif 5124 5125 /* Detect CRT2-TV and PAL/NTSC mode */ 5126 SISTVPreInit(pScrn, FALSE); 5127 5128 /* Detect CRT2-VGA */ 5129 SISCRT2PreInit(pScrn, FALSE); 5130 5131 /* Backup detected CRT2 devices */ 5132 SISSaveDetectedDevices(pScrn); 5133 5134 if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR)) { 5135 if((pSiS->ForceTVType != -1) && (pSiS->ForceTVType & TV_YPBPR)) { 5136 pSiS->ForceTVType = -1; 5137 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "YPbPr TV output not supported\n"); 5138 } 5139 } 5140 5141 if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTHIVISION)) { 5142 if((pSiS->ForceTVType != -1) && (pSiS->ForceTVType & TV_HIVISION)) { 5143 pSiS->ForceTVType = -1; 5144 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "HiVision TV output not supported\n"); 5145 } 5146 } 5147 5148 if((pSiS->VBFlags2 & VB2_SISTVBRIDGE) || 5149 ((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->ChrontelType == CHRONTEL_701x))) { 5150 pSiS->SiS_SD_Flags |= (SiS_SD_SUPPORTPALMN | SiS_SD_SUPPORTNTSCJ); 5151 } 5152 if((pSiS->VBFlags2 & VB2_SISTVBRIDGE) || 5153 ((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->ChrontelType == CHRONTEL_700x))) { 5154 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTTVPOS; 5155 } 5156 if(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE) { 5157 pSiS->SiS_SD_Flags |= (SiS_SD_SUPPORTSCART | SiS_SD_SUPPORTVGA2); 5158 } 5159 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 5160 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTOVERSCAN; 5161 pSiS->SiS_SD2_Flags |= SiS_SD2_CHRONTEL; 5162 if(pSiS->ChrontelType == CHRONTEL_700x) { 5163 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTSOVER; 5164 } 5165 } 5166 5167 /* Determine if chipset LCDA-capable */ 5168 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTLCDA; 5169 if(SISDetermineLCDACap(pScrn)) { 5170 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTLCDA; 5171 } 5172 5173 /* Default to LCDA if LCD detected and 5174 * - TV detected (hence default to LCDA+TV), or 5175 * - in single head mode, on LCD panels with xres > 1600 5176 * (Don't do this in MergedFB or DHM; LCDA and CRT1/VGA 5177 * are mutually exclusive; if no TV is detected, the 5178 * code below will default to VGA+LCD, so LCD is driven 5179 * via CRT2.) 5180 * (TODO: This might need some modification for the 5181 * 307 bridges, if these are capable of driving 5182 * LCDs > 1600 via channel B) 5183 */ 5184 if((pSiS->SiS_SD_Flags & SiS_SD_SUPPORTLCDA) && 5185 (pSiS->VBFlags & CRT2_LCD) && 5186 (pSiS->SiS_Pr->SiS_CustomT != CUT_UNKNOWNLCD)) { 5187 if((!pSiS->CRT1TypeForced) && (pSiS->ForceCRT2Type == CRT2_DEFAULT)) { 5188 if(pSiS->VBFlags & CRT2_TV) { 5189 /* If both LCD and TV present, default to LCDA+TV */ 5190 pSiS->ForceCRT1Type = CRT1_LCDA; 5191 pSiS->ForceCRT2Type = CRT2_TV; 5192 } else if(pSiS->LCDwidth > 1600) { 5193 /* If LCD is > 1600, default to LCDA if we don't need CRT1/VGA for other head */ 5194 Bool NeedCRT1VGA = FALSE; 5195#ifdef SISDUALHEAD 5196 if(pSiS->DualHeadMode) NeedCRT1VGA = TRUE; 5197#endif 5198#ifdef SISMERGED 5199 if(pSiS->MergedFB && 5200 (!pSiS->MergedFBAuto || pSiS->CRT1Detected)) NeedCRT1VGA = TRUE; 5201#endif 5202 if(!NeedCRT1VGA) { 5203 pSiS->ForceCRT1Type = CRT1_LCDA; 5204 } 5205 } 5206 } 5207 } 5208 5209 /* Set up pseudo-panel if LCDA forced on TMDS bridges */ 5210 if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTLCDA) { 5211 if(pSiS->ForceCRT1Type == CRT1_LCDA) { 5212 if(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE) { 5213 if(!(pSiS->VBLCDFlags)) { 5214 SiSSetupPseudoPanel(pScrn); 5215 pSiS->detectedCRT2Devices |= CRT2_LCD; 5216 } 5217 } else if(!(pSiS->VBLCDFlags)) { 5218 pSiS->ForceCRT1Type = CRT1_VGA; 5219 } 5220 } 5221 } else { 5222 pSiS->ForceCRT1Type = CRT1_VGA; 5223 } 5224 5225 pSiS->VBFlags |= pSiS->ForceCRT1Type; 5226 5227#ifdef TWDEBUG 5228 xf86DrvMsg(0, X_INFO, "SDFlags %lx\n", pSiS->SiS_SD_Flags); 5229#endif 5230 5231 /* Eventually overrule detected CRT2 type 5232 * If no type forced, use the detected devices in the order TV->LCD->VGA2 5233 * Since the Chrontel 7005 sometimes delivers wrong detection results, 5234 * we use a different order on such machines (LCD->TV) 5235 */ 5236 if(pSiS->ForceCRT2Type == CRT2_DEFAULT) { 5237 if((pSiS->VBFlags & CRT2_TV) && (!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VGAEngine == SIS_300_VGA)))) 5238 pSiS->ForceCRT2Type = CRT2_TV; 5239 else if((pSiS->VBFlags & CRT2_LCD) && (pSiS->ForceCRT1Type == CRT1_VGA)) 5240 pSiS->ForceCRT2Type = CRT2_LCD; 5241 else if(pSiS->VBFlags & CRT2_TV) 5242 pSiS->ForceCRT2Type = CRT2_TV; 5243 else if((pSiS->VBFlags & CRT2_VGA) && (pSiS->ForceCRT1Type == CRT1_VGA)) 5244 pSiS->ForceCRT2Type = CRT2_VGA; 5245 } 5246 5247 switch(pSiS->ForceCRT2Type) { 5248 case CRT2_TV: 5249 pSiS->VBFlags &= ~(CRT2_LCD | CRT2_VGA); 5250 if(pSiS->VBFlags2 & (VB2_SISTVBRIDGE | VB2_CHRONTEL)) { 5251 pSiS->VBFlags |= CRT2_TV; 5252 } else { 5253 pSiS->VBFlags &= ~(CRT2_TV); 5254 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 5255 "Hardware does not support TV output\n"); 5256 } 5257 break; 5258 case CRT2_LCD: 5259 pSiS->VBFlags &= ~(CRT2_TV | CRT2_VGA); 5260 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (pSiS->VBLCDFlags)) { 5261 pSiS->VBFlags |= CRT2_LCD; 5262 } else if((pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && (!(pSiS->VBFlags2 & VB2_30xBDH))) { 5263 SiSSetupPseudoPanel(pScrn); 5264 pSiS->detectedCRT2Devices |= CRT2_LCD; 5265 } else { 5266 pSiS->VBFlags &= ~(CRT2_LCD); 5267 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 5268 "Can't force CRT2 to LCD, no LCD detected\n"); 5269 } 5270 break; 5271 case CRT2_VGA: 5272 pSiS->VBFlags &= ~(CRT2_TV | CRT2_LCD); 5273 if(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE) { 5274 pSiS->VBFlags |= CRT2_VGA; 5275 } else { 5276 pSiS->VBFlags &= ~(CRT2_VGA); 5277 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 5278 "Hardware does not support secondary VGA\n"); 5279 } 5280 break; 5281 default: 5282 pSiS->VBFlags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA); 5283 } 5284 5285 /* Setup gamma (the cmap layer needs this to be initialised) */ 5286 /* (Do this after evaluating options) */ 5287 { 5288 Gamma zeros = {0.0, 0.0, 0.0}; 5289 xf86SetGamma(pScrn, zeros); 5290 } 5291 5292#ifdef SISDUALHEAD 5293 if((!pSiS->DualHeadMode) || (pSiS->SecondHead)) { 5294#endif 5295 xf86DrvMsg(pScrn->scrnIndex, pSiS->CRT1gammaGiven ? X_CONFIG : X_INFO, 5296 "%samma correction is %s\n", 5297 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) ? "CRT1 g" : "G", 5298 pSiS->CRT1gamma ? "enabled" : "disabled"); 5299 5300 if((pSiS->VGAEngine == SIS_315_VGA) && 5301 (!(pSiS->NoXvideo)) && 5302 (!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY))) { 5303 xf86DrvMsg(pScrn->scrnIndex, pSiS->XvGammaGiven ? X_CONFIG : X_INFO, 5304 "Separate Xv gamma correction %sis %s\n", 5305 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) ? "for CRT1 " : "", 5306 pSiS->XvGamma ? "enabled" : "disabled"); 5307 if(pSiS->XvGamma) { 5308 xf86DrvMsg(pScrn->scrnIndex, pSiS->XvGammaGiven ? X_CONFIG : X_INFO, 5309 "Xv gamma correction: %.3f %.3f %.3f\n", 5310 (float)((float)pSiS->XvGammaRed / 1000), 5311 (float)((float)pSiS->XvGammaGreen / 1000), 5312 (float)((float)pSiS->XvGammaBlue / 1000)); 5313 if(!pSiS->CRT1gamma) { 5314 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5315 "Xv gamma correction requires %samma correction enabled\n", 5316 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) ? "CRT1 g" : "G"); 5317 } 5318 } 5319 } 5320#ifdef SISDUALHEAD 5321 } 5322#endif 5323 5324#ifdef SISDUALHEAD 5325 if(pSiS->DualHeadMode) pSiS->CRT2SepGamma = FALSE; 5326#endif 5327 5328#ifdef SISDUALHEAD 5329 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) 5330#endif 5331 { 5332 Bool isDH = FALSE; 5333 if(pSiS->CRT2gamma) { 5334 if( ((pSiS->VGAEngine != SIS_300_VGA) && (pSiS->VGAEngine != SIS_315_VGA)) || 5335 (!(pSiS->VBFlags2 & VB2_SISBRIDGE)) ) { 5336 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 5337 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5338 "CRT2 gamma correction not supported by hardware\n"); 5339 } 5340 pSiS->CRT2gamma = pSiS->CRT2SepGamma = FALSE; 5341 } else if((pSiS->VBFlags2 & VB2_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) { 5342 isDH = TRUE; 5343 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5344 "CRT2 gamma correction not supported for LCD\n"); 5345 /* But leave it on, will be caught in LoadPalette */ 5346 } 5347 } 5348 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 5349 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CRT2 gamma correction is %s%s%s\n", 5350 pSiS->CRT2gamma ? "enabled" : "disabled", 5351 isDH ? " (for TV and VGA2) " : "", 5352 pSiS->CRT2SepGamma ? " (separate from CRT1)" : ""); 5353 } 5354 } 5355 5356 /* Eventually overrule TV Type (SVIDEO, COMPOSITE, SCART, HIVISION, YPBPR) */ 5357 if(pSiS->VBFlags2 & VB2_SISTVBRIDGE) { 5358 if(pSiS->ForceTVType != -1) { 5359 pSiS->VBFlags &= ~(TV_INTERFACE); 5360 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) { 5361 pSiS->VBFlags &= ~(TV_CHSCART | TV_CHYPBPR525I); 5362 } 5363 pSiS->VBFlags |= pSiS->ForceTVType; 5364 if(pSiS->VBFlags & TV_YPBPR) { 5365 pSiS->VBFlags &= ~(TV_STANDARD); 5366 pSiS->VBFlags &= ~(TV_YPBPRAR); 5367 pSiS->VBFlags |= pSiS->ForceYPbPrType; 5368 pSiS->VBFlags |= pSiS->ForceYPbPrAR; 5369 } 5370 } 5371 } 5372 5373 /* Handle ForceCRT1 option (part 2) */ 5374 pSiS->CRT1changed = FALSE; 5375 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5376 usScratchCR17 = pSiS->oldCR17; 5377 usScratchCR63 = pSiS->oldCR63; 5378 usScratchSR1F = pSiS->oldSR1F; 5379 usScratchCR32 = pSiS->postVBCR32; 5380 if(pSiS->VESA != 1) { 5381 /* Copy forceCRT1 option to CRT1off if option is given */ 5382#ifdef SISDUALHEAD 5383 /* In DHM, handle this option only for master head, not the slave */ 5384 if( (pSiS->forceCRT1 != -1) && 5385 (!(pSiS->DualHeadMode && pSiS->SecondHead)) ) { 5386#else 5387 if(pSiS->forceCRT1 != -1) { 5388#endif 5389 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5390 "CRT1 detection overruled by ForceCRT1 option\n"); 5391 if(pSiS->forceCRT1) { 5392 pSiS->CRT1off = 0; 5393 if(pSiS->VGAEngine == SIS_300_VGA) { 5394 if(!(usScratchCR17 & 0x80)) pSiS->CRT1changed = TRUE; 5395 } else { 5396 if(usScratchCR63 & 0x40) pSiS->CRT1changed = TRUE; 5397 } 5398 usScratchCR17 |= 0x80; 5399 usScratchCR32 |= 0x20; 5400 usScratchCR63 &= ~0x40; 5401 usScratchSR1F &= ~0xc0; 5402 } else { 5403 if( ! ( (pScrn->bitsPerPixel == 8) && 5404 ( (pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) || 5405 ((pSiS->VBFlags2 & VB2_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) ) ) ) { 5406 pSiS->CRT1off = 1; 5407 if(pSiS->VGAEngine == SIS_300_VGA) { 5408 if(usScratchCR17 & 0x80) pSiS->CRT1changed = TRUE; 5409 } else { 5410 if(!(usScratchCR63 & 0x40)) pSiS->CRT1changed = TRUE; 5411 } 5412 usScratchCR32 &= ~0x20; 5413 /* We must not actually switch off CRT1 before we changed the mode! */ 5414 } 5415 } 5416 /* Here we can write to CR17 even on 315 series as we only ENABLE 5417 * the bit here 5418 */ 5419 outSISIDXREG(SISCR, 0x17, usScratchCR17); 5420 if(pSiS->VGAEngine == SIS_315_VGA) { 5421 outSISIDXREG(SISCR, pSiS->myCR63, usScratchCR63); 5422 } 5423 outSISIDXREG(SISCR, 0x32, usScratchCR32); 5424 if(pSiS->CRT1changed) { 5425 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 5426 usleep(10000); 5427 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 5428 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5429 "CRT1 status changed by ForceCRT1 option\n"); 5430 } 5431 outSISIDXREG(SISSR, 0x1f, usScratchSR1F); 5432 } 5433 } 5434 /* Store the new VB connection register contents for later mode changes */ 5435 pSiS->newCR32 = usScratchCR32; 5436 } 5437 5438 /* Check if CRT1 used (or needed; this eg. if no CRT2 detected) */ 5439 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 5440 5441 /* No CRT2 output? Then we NEED CRT1! 5442 * We also need CRT1 if depth = 8 and bridge=LVDS|301B-DH 5443 */ 5444 if( (!(pSiS->VBFlags & (CRT2_VGA | CRT2_LCD | CRT2_TV))) || 5445 ( (pScrn->bitsPerPixel == 8) && 5446 ( (pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) || 5447 ((pSiS->VBFlags2 & VB2_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) ) ) ) { 5448 pSiS->CRT1off = 0; 5449 } 5450 /* No CRT2 output? Then we can't use Xv on CRT2 */ 5451 if(!(pSiS->VBFlags & (CRT2_VGA | CRT2_LCD | CRT2_TV))) { 5452 pSiS->XvOnCRT2 = FALSE; 5453 } 5454 5455 } else { /* no video bridge? */ 5456 /* Then we NEED CRT1... */ 5457 pSiS->CRT1off = 0; 5458 /* ... and can't use CRT2 for Xv output */ 5459 pSiS->XvOnCRT2 = FALSE; 5460 } 5461 5462 /* LCDA? Then we don't switch off CRT1 */ 5463 if(pSiS->VBFlags & CRT1_LCDA) pSiS->CRT1off = 0; 5464 5465 /* Handle TVStandard option */ 5466 if((pSiS->NonDefaultPAL != -1) || (pSiS->NonDefaultNTSC != -1)) { 5467 if( (!(pSiS->VBFlags2 & VB2_SISTVBRIDGE)) && 5468 (!((pSiS->VBFlags2 & VB2_CHRONTEL)) && (pSiS->ChrontelType == CHRONTEL_701x)) ) { 5469 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5470 "PALM, PALN and NTSCJ not supported on this hardware\n"); 5471 pSiS->NonDefaultPAL = pSiS->NonDefaultNTSC = -1; 5472 pSiS->VBFlags &= ~(TV_PALN | TV_PALM | TV_NTSCJ); 5473 pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTPALMN | SiS_SD_SUPPORTNTSCJ); 5474 } 5475 } 5476 if(pSiS->OptTVStand != -1) { 5477 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5478 if( (!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & (TV_CHSCART | TV_CHYPBPR525I)))) && 5479 (!(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR))) ) { 5480 pSiS->VBFlags &= ~(TV_PAL | TV_NTSC | TV_PALN | TV_PALM | TV_NTSCJ); 5481 if(pSiS->OptTVStand) { 5482 pSiS->VBFlags |= TV_PAL; 5483 if(pSiS->NonDefaultPAL == 1) pSiS->VBFlags |= TV_PALM; 5484 else if(!pSiS->NonDefaultPAL) pSiS->VBFlags |= TV_PALN; 5485 } else { 5486 pSiS->VBFlags |= TV_NTSC; 5487 if(pSiS->NonDefaultNTSC == 1) pSiS->VBFlags |= TV_NTSCJ; 5488 } 5489 } else { 5490 pSiS->OptTVStand = pSiS->NonDefaultPAL = -1; 5491 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5492 "Option TVStandard ignored for YPbPr, HiVision and Chrontel-SCART\n"); 5493 } 5494 } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { 5495 pSiS->SiS6326Flags &= ~SIS6326_TVPAL; 5496 if(pSiS->OptTVStand) pSiS->SiS6326Flags |= SIS6326_TVPAL; 5497 } 5498 } 5499 5500 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5501 /* Default to PAL */ 5502 if(pSiS->VBFlags & (TV_SVIDEO | TV_AVIDEO)) { 5503 if(!(pSiS->VBFlags & (TV_PAL | TV_NTSC))) { 5504 pSiS->VBFlags &= ~(TV_PAL | TV_NTSC | TV_PALN | TV_PALM | TV_NTSCJ); 5505 pSiS->VBFlags |= TV_PAL; 5506 } 5507 } 5508 /* SCART only supported for PAL */ 5509 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && (pSiS->VBFlags & TV_SCART)) { 5510 pSiS->VBFlags &= ~(TV_NTSC | TV_PALN | TV_PALM | TV_NTSCJ); 5511 pSiS->VBFlags |= TV_PAL; 5512 pSiS->OptTVStand = 1; 5513 pSiS->NonDefaultPAL = pSiS->NonDefaultNTSC = -1; 5514 } 5515 } 5516 5517#ifdef SIS_CP 5518 SIS_CP_DRIVER_RECONFIGOPT 5519#endif 5520 5521 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 5522 if(pSiS->sis6326tvplug != -1) { 5523 pSiS->SiS6326Flags &= ~(SIS6326_TVSVIDEO | SIS6326_TVCVBS); 5524 pSiS->SiS6326Flags |= SIS6326_TVDETECTED; 5525 if(pSiS->sis6326tvplug == 1) pSiS->SiS6326Flags |= SIS6326_TVCVBS; 5526 else pSiS->SiS6326Flags |= SIS6326_TVSVIDEO; 5527 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5528 "SiS6326 TV plug type detection overruled by %s\n", 5529 (pSiS->SiS6326Flags & SIS6326_TVCVBS) ? "COMPOSITE" : "SVIDEO"); 5530 } 5531 } 5532 5533 /* Do some checks */ 5534 if(pSiS->OptTVOver != -1) { 5535 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 5536 pSiS->UseCHOverScan = pSiS->OptTVOver; 5537 } else { 5538 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5539 "CHTVOverscan only supported on CHRONTEL 70xx\n"); 5540 pSiS->UseCHOverScan = -1; 5541 } 5542 } else pSiS->UseCHOverScan = -1; 5543 5544 if(pSiS->sistvedgeenhance != -1) { 5545 if(!(pSiS->VBFlags2 & VB2_301)) { 5546 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5547 "SISTVEdgeEnhance only supported on SiS301\n"); 5548 pSiS->sistvedgeenhance = -1; 5549 } 5550 } 5551 if(pSiS->sistvsaturation != -1) { 5552 if(pSiS->VBFlags2 & VB2_301) { 5553 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5554 "SISTVSaturation not supported on SiS301\n"); 5555 pSiS->sistvsaturation = -1; 5556 } 5557 } 5558 5559 /* Do some MergedFB mode initialisation */ 5560#ifdef SISMERGED 5561 if(pSiS->MergedFB) { 5562 pSiS->CRT2pScrn = xalloc(sizeof(ScrnInfoRec)); 5563 if(!pSiS->CRT2pScrn) { 5564 SISErrorLog(pScrn, "Failed to allocate memory for 2nd pScrn, %s\n", mergeddisstr); 5565 pSiS->MergedFB = FALSE; 5566 } else { 5567 memcpy(pSiS->CRT2pScrn, pScrn, sizeof(ScrnInfoRec)); 5568 } 5569 } 5570#endif 5571 5572 /* Determine CRT1<>CRT2 mode 5573 * Note: When using VESA or if the bridge is in slavemode, display 5574 * is ALWAYS in MIRROR_MODE! 5575 * This requires extra checks in functions using this flag! 5576 * (see sis_video.c for example) 5577 */ 5578 if(pSiS->VBFlags & DISPTYPE_DISP2) { 5579 if(pSiS->CRT1off) { /* CRT2 only ------------------------------- */ 5580#ifdef SISDUALHEAD 5581 if(pSiS->DualHeadMode) { 5582 SISErrorLog(pScrn, 5583 "CRT1 not detected or forced off. Dual Head mode can't initialize.\n"); 5584 if(pSiSEnt) pSiSEnt->DisableDual = TRUE; 5585 goto my_error_1; 5586 } 5587#endif 5588#ifdef SISMERGED 5589 if(pSiS->MergedFB) { 5590 if(pSiS->MergedFBAuto) { 5591 xf86DrvMsg(pScrn->scrnIndex, X_INFO, mergednocrt1, mergeddisstr); 5592 } else { 5593 SISErrorLog(pScrn, mergednocrt1, mergeddisstr); 5594 } 5595 if(pSiS->CRT2pScrn) xfree(pSiS->CRT2pScrn); 5596 pSiS->CRT2pScrn = NULL; 5597 pSiS->MergedFB = FALSE; 5598 } 5599#endif 5600 pSiS->VBFlags |= VB_DISPMODE_SINGLE; 5601 /* No CRT1? Then we use the video overlay on CRT2 */ 5602 pSiS->XvOnCRT2 = TRUE; 5603 } else /* CRT1 and CRT2 - mirror or dual head ----- */ 5604#ifdef SISDUALHEAD 5605 if(pSiS->DualHeadMode) { 5606 pSiS->VBFlags |= (VB_DISPMODE_DUAL | DISPTYPE_CRT1); 5607 if(pSiS->VESA != -1) { 5608 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5609 "VESA option not used in Dual Head mode. VESA disabled.\n"); 5610 } 5611 if(pSiSEnt) pSiSEnt->DisableDual = FALSE; 5612 pSiS->VESA = 0; 5613 } else 5614#endif 5615#ifdef SISMERGED 5616 if(pSiS->MergedFB) { 5617 pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_CRT1); 5618 if(pSiS->VESA != -1) { 5619 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5620 "VESA option not used in MergedFB mode. VESA disabled.\n"); 5621 } 5622 pSiS->VESA = 0; 5623 } else 5624#endif 5625 pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_CRT1); 5626 } else { /* CRT1 only ------------------------------- */ 5627#ifdef SISDUALHEAD 5628 if(pSiS->DualHeadMode) { 5629 SISErrorLog(pScrn, 5630 "No CRT2 output selected or no bridge detected. " 5631 "Dual Head mode can't initialize.\n"); 5632 goto my_error_1; 5633 } 5634#endif 5635#ifdef SISMERGED 5636 if(pSiS->MergedFB) { 5637 if(pSiS->MergedFBAuto) { 5638 xf86DrvMsg(pScrn->scrnIndex, X_INFO, mergednocrt2, mergeddisstr); 5639 } else { 5640 SISErrorLog(pScrn, mergednocrt2, mergeddisstr); 5641 } 5642 if(pSiS->CRT2pScrn) xfree(pSiS->CRT2pScrn); 5643 pSiS->CRT2pScrn = NULL; 5644 pSiS->MergedFB = FALSE; 5645 } 5646#endif 5647 pSiS->VBFlags |= (VB_DISPMODE_SINGLE | DISPTYPE_CRT1); 5648 } 5649 5650 if((pSiS->VGAEngine == SIS_315_VGA) || (pSiS->VGAEngine == SIS_300_VGA)) { 5651 if((!pSiS->NoXvideo) && 5652 (!pSiS->hasTwoOverlays) && 5653 (!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY))) { 5654 xf86DrvMsg(pScrn->scrnIndex, from, 5655 "Using Xv overlay by default on CRT%d\n", 5656 pSiS->XvOnCRT2 ? 2 : 1); 5657 } 5658 } 5659 5660 /* Init ptrs for Save/Restore functions and calc MaxClock */ 5661 SISDACPreInit(pScrn); 5662 5663 /* ********** end of VBFlags setup ********** */ 5664 5665 /* VBFlags are initialized now. Back them up for SlaveMode modes. */ 5666 pSiS->VBFlags_backup = pSiS->VBFlags; 5667 5668 /* Backup CR32,36,37 (in order to write them back after a VT switch) */ 5669 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5670 inSISIDXREG(SISCR,0x32,pSiS->myCR32); 5671 inSISIDXREG(SISCR,0x36,pSiS->myCR36); 5672 inSISIDXREG(SISCR,0x37,pSiS->myCR37); 5673 } 5674 5675 /* Find out about paneldelaycompensation and evaluate option */ 5676#ifdef SISDUALHEAD 5677 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) { 5678#endif 5679 if(pSiS->VGAEngine == SIS_300_VGA) { 5680 5681 if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) { 5682 5683 /* Save the current PDC if the panel is used at the moment. 5684 * This seems by far the safest way to find out about it. 5685 * If the system is using an old version of sisfb, we can't 5686 * trust the pdc register value. If sisfb saved the pdc for 5687 * us, use it. 5688 */ 5689 if(pSiS->sisfbpdc != 0xff) { 5690 pSiS->SiS_Pr->PDC = pSiS->sisfbpdc; 5691 } else { 5692 if(!(pSiS->donttrustpdc)) { 5693 UChar tmp; 5694 inSISIDXREG(SISCR, 0x30, tmp); 5695 if(tmp & 0x20) { 5696 inSISIDXREG(SISPART1, 0x13, pSiS->SiS_Pr->PDC); 5697 } else { 5698 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5699 "Unable to detect LCD PanelDelayCompensation, LCD is not active\n"); 5700 } 5701 } else { 5702 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5703 "Unable to detect LCD PanelDelayCompensation, please update sisfb\n"); 5704 } 5705 } 5706 if(pSiS->SiS_Pr->PDC != -1) { 5707 pSiS->SiS_Pr->PDC &= 0x3c; 5708 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5709 "Detected LCD PanelDelayCompensation 0x%02x\n", 5710 pSiS->SiS_Pr->PDC); 5711 } 5712 5713 /* If we haven't been able to find out, use our other methods */ 5714 if(pSiS->SiS_Pr->PDC == -1) { 5715 int i=0; 5716 do { 5717 if(mypdctable[i].subsysVendor == PCI_SUB_VENDOR_ID(pSiS->PciInfo) && 5718 mypdctable[i].subsysCard == PCI_SUB_DEVICE_ID(pSiS->PciInfo)) { 5719 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5720 "PCI card/vendor identified for non-default PanelDelayCompensation\n"); 5721 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5722 "Vendor: %s, card: %s (ID %04x), PanelDelayCompensation: 0x%02x\n", 5723 mypdctable[i].vendorName, mypdctable[i].cardName, 5724 PCI_SUB_DEVICE_ID(pSiS->PciInfo), mypdctable[i].pdc); 5725 if(pSiS->PDC == -1) { 5726 pSiS->PDC = mypdctable[i].pdc; 5727 } else { 5728 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5729 "PanelDelayCompensation overruled by option\n"); 5730 } 5731 break; 5732 } 5733 i++; 5734 } while(mypdctable[i].subsysVendor != 0); 5735 } 5736 5737 if(pSiS->PDC != -1) { 5738 if(pSiS->BIOS) { 5739 if(pSiS->VBFlags2 & VB2_LVDS) { 5740 if(pSiS->BIOS[0x220] & 0x80) { 5741 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5742 "BIOS uses OEM LCD Panel Delay Compensation 0x%02x\n", 5743 pSiS->BIOS[0x220] & 0x3c); 5744 pSiS->BIOS[0x220] &= 0x7f; 5745 } 5746 } 5747 if(pSiS->VBFlags2 & (VB2_301B | VB2_302B)) { 5748 if(pSiS->BIOS[0x220] & 0x80) { 5749 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5750 "BIOS uses OEM LCD Panel Delay Compensation 0x%02x\n", 5751 ( (pSiS->VBLCDFlags & VB_LCD_1280x1024) ? 5752 pSiS->BIOS[0x223] : pSiS->BIOS[0x224] ) & 0x3c); 5753 pSiS->BIOS[0x220] &= 0x7f; 5754 } 5755 } 5756 } 5757 pSiS->SiS_Pr->PDC = (pSiS->PDC & 0x3c); 5758 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5759 "Using LCD Panel Delay Compensation 0x%02x\n", pSiS->SiS_Pr->PDC); 5760 } 5761 } 5762 5763 } /* SIS_300_VGA */ 5764 5765 if(pSiS->VGAEngine == SIS_315_VGA) { 5766 5767 UChar tmp, tmp2; 5768 inSISIDXREG(SISCR, 0x30, tmp); 5769 5770 /* Save the current PDC if the panel is used at the moment. */ 5771 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) { 5772 5773 if(pSiS->sisfbpdc != 0xff) { 5774 pSiS->SiS_Pr->PDC = pSiS->sisfbpdc; 5775 } 5776 if(pSiS->sisfbpdca != 0xff) { 5777 pSiS->SiS_Pr->PDCA = pSiS->sisfbpdca; 5778 } 5779 5780 if(!pSiS->donttrustpdc) { 5781 if((pSiS->sisfbpdc == 0xff) && (pSiS->sisfbpdca == 0xff)) { 5782 CARD16 tempa, tempb; 5783 inSISIDXREG(SISPART1,0x2d,tmp2); 5784 tempa = (tmp2 & 0xf0) >> 3; 5785 tempb = (tmp2 & 0x0f) << 1; 5786 inSISIDXREG(SISPART1,0x20,tmp2); 5787 tempa |= ((tmp2 & 0x40) >> 6); 5788 inSISIDXREG(SISPART1,0x35,tmp2); 5789 tempb |= ((tmp2 & 0x80) >> 7); 5790 inSISIDXREG(SISPART1,0x13,tmp2); 5791 if(!pSiS->ROM661New) { 5792 if((tmp2 & 0x04) || (tmp & 0x20)) { 5793 pSiS->SiS_Pr->PDCA = tempa; 5794 pSiS->SiS_Pr->PDC = tempb; 5795 } else { 5796 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5797 "Unable to detect PanelDelayCompensation, LCD is not active\n"); 5798 } 5799 } else { 5800 if(tmp2 & 0x04) { 5801 pSiS->SiS_Pr->PDCA = tempa; 5802 } else if(tmp & 0x20) { 5803 pSiS->SiS_Pr->PDC = tempb; 5804 } else { 5805 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5806 "Unable to detect PanelDelayCompensation, LCD is not active\n"); 5807 } 5808 } 5809 } 5810 } else { 5811 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5812 "Unable to detect PanelDelayCompensation, please update sisfb\n"); 5813 } 5814 if(pSiS->SiS_Pr->PDC != -1) { 5815 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5816 "Detected LCD PanelDelayCompensation 0x%02x (for LCD=CRT2)\n", 5817 pSiS->SiS_Pr->PDC); 5818 } 5819 if(pSiS->SiS_Pr->PDCA != -1) { 5820 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5821 "Detected LCD PanelDelayCompensation1 0x%02x (for LCD=CRT1)\n", 5822 pSiS->SiS_Pr->PDCA); 5823 } 5824 } 5825 5826 /* Let user override (for all bridges) */ 5827 if(pSiS->VBFlags2 & VB2_30xBLV) { 5828 if(pSiS->PDC != -1) { 5829 pSiS->SiS_Pr->PDC = pSiS->PDC & 0x1f; 5830 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5831 "Using LCD PanelDelayCompensation 0x%02x (for LCD=CRT2)\n", 5832 pSiS->SiS_Pr->PDC); 5833 } 5834 if(pSiS->PDCA != -1) { 5835 pSiS->SiS_Pr->PDCA = pSiS->PDCA & 0x1f; 5836 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5837 "Using LCD PanelDelayCompensation1 0x%02x (for LCD=CRT1)\n", 5838 pSiS->SiS_Pr->PDCA); 5839 } 5840 } 5841 5842 /* Read the current EMI (if not overruled) */ 5843 if(pSiS->VBFlags2 & VB2_SISEMIBRIDGE) { 5844 MessageType from = X_PROBED; 5845 if(pSiS->EMI != -1) { 5846 pSiS->SiS_Pr->EMI_30 = (pSiS->EMI >> 24) & 0x60; 5847 pSiS->SiS_Pr->EMI_31 = (pSiS->EMI >> 16) & 0xff; 5848 pSiS->SiS_Pr->EMI_32 = (pSiS->EMI >> 8) & 0xff; 5849 pSiS->SiS_Pr->EMI_33 = pSiS->EMI & 0xff; 5850 pSiS->SiS_Pr->HaveEMI = pSiS->SiS_Pr->HaveEMILCD = TRUE; 5851 pSiS->SiS_Pr->OverruleEMI = TRUE; 5852 from = X_CONFIG; 5853 } else if((pSiS->sisfbfound) && (pSiS->sisfb_haveemi)) { 5854 pSiS->SiS_Pr->EMI_30 = pSiS->sisfb_emi30; 5855 pSiS->SiS_Pr->EMI_31 = pSiS->sisfb_emi31; 5856 pSiS->SiS_Pr->EMI_32 = pSiS->sisfb_emi32; 5857 pSiS->SiS_Pr->EMI_33 = pSiS->sisfb_emi33; 5858 pSiS->SiS_Pr->HaveEMI = TRUE; 5859 if(pSiS->sisfb_haveemilcd) pSiS->SiS_Pr->HaveEMILCD = TRUE; 5860 pSiS->SiS_Pr->OverruleEMI = FALSE; 5861 } else { 5862 inSISIDXREG(SISPART4, 0x30, pSiS->SiS_Pr->EMI_30); 5863 inSISIDXREG(SISPART4, 0x31, pSiS->SiS_Pr->EMI_31); 5864 inSISIDXREG(SISPART4, 0x32, pSiS->SiS_Pr->EMI_32); 5865 inSISIDXREG(SISPART4, 0x33, pSiS->SiS_Pr->EMI_33); 5866 pSiS->SiS_Pr->HaveEMI = TRUE; 5867 if(tmp & 0x20) pSiS->SiS_Pr->HaveEMILCD = TRUE; 5868 pSiS->SiS_Pr->OverruleEMI = FALSE; 5869 } 5870 xf86DrvMsg(pScrn->scrnIndex, from, 5871 "302LV/302ELV: Using EMI 0x%02x%02x%02x%02x%s\n", 5872 pSiS->SiS_Pr->EMI_30,pSiS->SiS_Pr->EMI_31, 5873 pSiS->SiS_Pr->EMI_32,pSiS->SiS_Pr->EMI_33, 5874 pSiS->SiS_Pr->HaveEMILCD ? " (LCD)" : ""); 5875 } 5876 5877 } /* SIS_315_VGA */ 5878#ifdef SISDUALHEAD 5879 } 5880#endif 5881 5882 5883 /* In dual head mode, both heads (currently) share the maxxfbmem equally. 5884 * If memory sharing is done differently, the following has to be changed; 5885 * the other modules (eg. accel and Xv) use dhmOffset for hardware 5886 * pointer settings relative to VideoRAM start and won't need to be changed. 5887 * 5888 * Addendum: dhmoffset is also used for skipping the UMA area on SiS76x. 5889 */ 5890 5891 pSiS->dhmOffset = pSiS->FbBaseOffset; 5892 pSiS->FbAddress += pSiS->dhmOffset; 5893 5894#ifdef SISDUALHEAD 5895 if(pSiS->DualHeadMode) { 5896 pSiS->FbAddress = pSiS->realFbAddress; 5897 if(!pSiS->SecondHead) { 5898 /* ===== First head (always CRT2) ===== */ 5899 /* We use only half of the memory available */ 5900 pSiS->maxxfbmem /= 2; 5901 /* dhmOffset is 0 (or LFB-base for SiS76x UMA skipping) */ 5902 pSiS->FbAddress += pSiS->dhmOffset; 5903 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5904 "%dKB video RAM at 0x%lx available for master head (CRT2)\n", 5905 pSiS->maxxfbmem/1024, pSiS->FbAddress); 5906 } else { 5907 /* ===== Second head (always CRT1) ===== */ 5908 /* We use only half of the memory available */ 5909 pSiS->maxxfbmem /= 2; 5910 /* Initialize dhmOffset */ 5911 pSiS->dhmOffset += pSiS->maxxfbmem; 5912 /* Adapt FBAddress */ 5913 pSiS->FbAddress += pSiS->dhmOffset; 5914 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5915 "%dKB video RAM at 0x%lx available for slave head (CRT1)\n", 5916 pSiS->maxxfbmem/1024, pSiS->FbAddress); 5917 } 5918 } 5919#endif 5920 5921 /* Note: Do not use availMem for anything from now. Use 5922 * maxxfbmem instead. (availMem does not take dual head 5923 * mode into account.) 5924 */ 5925 5926 if(pSiS->FbBaseOffset) { 5927 /* Doubt that the DRM memory manager can deal 5928 * with a heap start of 0... 5929 */ 5930 pSiS->DRIheapstart = 16; 5931 pSiS->DRIheapend = pSiS->FbBaseOffset; 5932 } else { 5933 pSiS->DRIheapstart = pSiS->maxxfbmem; 5934 pSiS->DRIheapend = pSiS->availMem; 5935 } 5936#ifdef SISDUALHEAD 5937 if(pSiS->DualHeadMode) { 5938 pSiS->DRIheapstart = pSiS->DRIheapend = 0; 5939 } else 5940#endif 5941 if(pSiS->DRIheapstart >= pSiS->DRIheapend) { 5942#if 0 /* For future use */ 5943 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5944 "No memory for DRI heap. Please set the option \"MaxXFBMem\" to\n" 5945 "\tlimit the memory X should use and leave the rest to DRI\n"); 5946#endif 5947 pSiS->DRIheapstart = pSiS->DRIheapend = 0; 5948 } 5949 5950 /* Now for something completely different: DDC. 5951 * For 300 and 315/330/340 series, we provide our 5952 * own functions (in order to probe CRT2 as well) 5953 * If these fail, use the VBE. 5954 * All other chipsets will use VBE. No need to re-invent 5955 * the wheel there. 5956 */ 5957 5958 pSiS->pVbe = NULL; 5959 didddc2 = FALSE; 5960 5961 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5962 if(xf86LoadSubModule(pScrn, "ddc")) { 5963 int crtnum = 0; 5964 if((pMonitor = SiSDoPrivateDDC(pScrn, &crtnum))) { 5965 didddc2 = TRUE; 5966 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcsstr, crtnum); 5967 xf86PrintEDID(pMonitor); 5968 xf86SetDDCproperties(pScrn, pMonitor); 5969 pScrn->monitor->DDC = pMonitor; 5970 /* Now try to find out aspect ratio */ 5971 SiSFindAspect(pScrn, pMonitor, crtnum); 5972 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcestr, crtnum); 5973 } 5974 } 5975 } 5976 5977#ifdef SISDUALHEAD 5978 /* In dual head mode, probe DDC using VBE only for CRT1 (second head) */ 5979 if((pSiS->DualHeadMode) && (!didddc2) && (!pSiS->SecondHead)) { 5980 didddc2 = TRUE; 5981 } 5982#endif 5983 5984 if(!didddc2) { 5985 /* If CRT1 is off or LCDA, skip DDC via VBE */ 5986 if((pSiS->CRT1off) || (pSiS->VBFlags & CRT1_LCDA)) { 5987 didddc2 = TRUE; 5988 } 5989 } 5990 5991 /* Now (re-)load and initialize the DDC module */ 5992 if(!didddc2) { 5993 5994 if(xf86LoadSubModule(pScrn, "ddc")) { 5995 5996 /* Now load and initialize VBE module. */ 5997 SiS_LoadInitVBE(pScrn); 5998 5999 if(pSiS->pVbe) { 6000 if((pMonitor = vbeDoEDID(pSiS->pVbe,NULL))) { 6001 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 6002 "VBE CRT1 DDC monitor info:\n"); 6003 xf86SetDDCproperties(pScrn, xf86PrintEDID(pMonitor)); 6004 pScrn->monitor->DDC = pMonitor; 6005 /* Now try to find out aspect ratio */ 6006 SiSFindAspect(pScrn, pMonitor, 1); 6007 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 6008 "End of VBE CRT1 DDC monitor info\n"); 6009 } 6010 } else { 6011 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6012 "Failed to read DDC data\n"); 6013 } 6014 } 6015 } 6016 6017#ifdef SISMERGED 6018 if(pSiS->MergedFB) { 6019 pSiS->CRT2pScrn->monitor = xalloc(sizeof(MonRec)); 6020 if(pSiS->CRT2pScrn->monitor) { 6021 DisplayModePtr tempm = NULL, currentm = NULL, newm = NULL; 6022 memcpy(pSiS->CRT2pScrn->monitor, pScrn->monitor, sizeof(MonRec)); 6023 pSiS->CRT2pScrn->monitor->DDC = NULL; 6024 pSiS->CRT2pScrn->monitor->Modes = NULL; 6025 pSiS->CRT2pScrn->monitor->id = (char *)crt2monname; 6026 tempm = pScrn->monitor->Modes; 6027 while(tempm) { 6028 if(!(newm = xalloc(sizeof(DisplayModeRec)))) break; 6029 memcpy(newm, tempm, sizeof(DisplayModeRec)); 6030 if(!(newm->name = xalloc(strlen(tempm->name) + 1))) { 6031 xfree(newm); 6032 break; 6033 } 6034 strcpy(newm->name, tempm->name); 6035 if(!pSiS->CRT2pScrn->monitor->Modes) pSiS->CRT2pScrn->monitor->Modes = newm; 6036 if(currentm) { 6037 currentm->next = newm; 6038 newm->prev = currentm; 6039 } 6040 currentm = newm; 6041 tempm = tempm->next; 6042 } 6043 if(pSiS->CRT2HSync) { 6044 pSiS->CRT2pScrn->monitor->nHsync = 6045 SiSStrToRanges(pSiS->CRT2pScrn->monitor->hsync, pSiS->CRT2HSync, MAX_HSYNC); 6046 } 6047 if(pSiS->CRT2VRefresh) { 6048 pSiS->CRT2pScrn->monitor->nVrefresh = 6049 SiSStrToRanges(pSiS->CRT2pScrn->monitor->vrefresh, pSiS->CRT2VRefresh, MAX_VREFRESH); 6050 } 6051 if((pMonitor = SiSInternalDDC(pSiS->CRT2pScrn, 1))) { 6052 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcsstr, 2); 6053 xf86PrintEDID(pMonitor); 6054 xf86SetDDCproperties(pSiS->CRT2pScrn, pMonitor); 6055 pSiS->CRT2pScrn->monitor->DDC = pMonitor; 6056 /* Now try to find out aspect ratio */ 6057 SiSFindAspect(pScrn, pMonitor, 2); 6058 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcestr, 2); 6059 /* use DDC data if no ranges in config file */ 6060 if(!pSiS->CRT2HSync) { 6061 pSiS->CRT2pScrn->monitor->nHsync = 0; 6062 } 6063 if(!pSiS->CRT2VRefresh) { 6064 pSiS->CRT2pScrn->monitor->nVrefresh = 0; 6065 } 6066 } else { 6067 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 6068 "Failed to read DDC data for CRT2\n"); 6069 } 6070 } else { 6071 SISErrorLog(pScrn, "Failed to allocate memory for CRT2 monitor, %s.\n", 6072 mergeddisstr); 6073 if(pSiS->CRT2pScrn) xfree(pSiS->CRT2pScrn); 6074 pSiS->CRT2pScrn = NULL; 6075 pSiS->MergedFB = FALSE; 6076 } 6077 } 6078#endif 6079 6080 /* Copy our detected monitor gammas, part 1. Note that device redetection 6081 * is not supported in DHM, so there is no need to do that anytime later. 6082 */ 6083#ifdef SISDUALHEAD 6084 if(pSiS->DualHeadMode) { 6085 if(!pSiS->SecondHead) { 6086 /* CRT2: Got gamma for LCD or VGA2 */ 6087 pSiSEnt->CRT2VGAMonitorGamma = pSiS->CRT2VGAMonitorGamma; 6088 } else { 6089 /* CRT1: Got gamma for LCD or VGA */ 6090 pSiSEnt->CRT1VGAMonitorGamma = pSiS->CRT1VGAMonitorGamma; 6091 } 6092 if(pSiS->CRT2LCDMonitorGamma) pSiSEnt->CRT2LCDMonitorGamma = pSiS->CRT2LCDMonitorGamma; 6093 } 6094#endif 6095 6096 /* end of DDC */ 6097 6098 /* From here, we mainly deal with clocks and modes */ 6099 6100#ifdef SISMERGED 6101 if(pSiS->MergedFB) xf86DrvMsg(pScrn->scrnIndex, X_INFO, crtsetupstr, 1); 6102#endif 6103 6104 /* Set the min pixel clock */ 6105 pSiS->MinClock = 5000; 6106 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 6107 pSiS->MinClock = 10000; 6108 } 6109 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n", 6110 pSiS->MinClock / 1000); 6111 6112 /* If the user has specified ramdac speed in the config 6113 * file, we respect that setting. 6114 */ 6115 from = X_PROBED; 6116 if(pSiS->pEnt->device->dacSpeeds[0]) { 6117 int speed = 0; 6118 switch(pScrn->bitsPerPixel) { 6119 case 8: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP8]; 6120 break; 6121 case 16: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP16]; 6122 break; 6123 case 24: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP24]; 6124 break; 6125 case 32: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP32]; 6126 break; 6127 } 6128 if(speed == 0) pSiS->MaxClock = pSiS->pEnt->device->dacSpeeds[0]; 6129 else pSiS->MaxClock = speed; 6130 from = X_CONFIG; 6131 } 6132 xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n", 6133 pSiS->MaxClock / 1000); 6134 6135 /* 6136 * Setup the ClockRanges, which describe what clock ranges are available, 6137 * and what sort of modes they can be used for. 6138 */ 6139 clockRanges = xnfcalloc(sizeof(ClockRange), 1); 6140 clockRanges->next = NULL; 6141 clockRanges->minClock = pSiS->MinClock; 6142 clockRanges->maxClock = pSiS->MaxClock; 6143 clockRanges->clockIndex = -1; /* programmable */ 6144 clockRanges->interlaceAllowed = TRUE; 6145 clockRanges->doubleScanAllowed = TRUE; 6146 6147 /* 6148 * Since we have lots of built-in modes for 300/315/330/340 series 6149 * with vb support, we replace the given default mode list with our 6150 * own. In case the video bridge is to be used, we only allow other 6151 * modes if 6152 * -) vbtype is 301, 301B, 301C or 302B, and 6153 * -) crt2 device is not TV, and 6154 * -) crt1 is not LCDA, unless bridge is TMDS/LCDA capable (301C) 6155 */ 6156 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 6157 if(!(pSiS->noInternalModes)) { 6158 Bool acceptcustommodes = TRUE; /* Accept user modelines */ 6159 Bool includelcdmodes = TRUE; /* Include modes reported by DDC */ 6160 Bool isfordvi = FALSE; /* Is for digital DVI output */ 6161 Bool fakecrt2modes = FALSE; /* Fake some modes for CRT2 */ 6162 Bool IsForCRT2 = FALSE; 6163 if(pSiS->UseVESA) { 6164 acceptcustommodes = FALSE; 6165 includelcdmodes = FALSE; 6166 } 6167#ifdef SISDUALHEAD /* Dual head is static. Output devices will not change. */ 6168 if(pSiS->DualHeadMode) { 6169 if(!pSiS->SecondHead) { /* CRT2: */ 6170 if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 6171 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 6172 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA))) includelcdmodes = FALSE; 6173 if(pSiS->VBFlags & CRT2_LCD) isfordvi = TRUE; 6174 if(pSiS->VBFlags & CRT2_TV) acceptcustommodes = FALSE; 6175 } else { 6176 if(pSiS->VBFlags & (CRT2_TV|CRT2_LCD)) { 6177 acceptcustommodes = FALSE; 6178 includelcdmodes = FALSE; 6179 fakecrt2modes = TRUE; 6180 } 6181 } 6182 } else { 6183 acceptcustommodes = FALSE; 6184 includelcdmodes = FALSE; 6185 if(pSiS->VBFlags & (CRT2_TV|CRT2_LCD)) { 6186 fakecrt2modes = TRUE; 6187 } 6188 } 6189 clockRanges->interlaceAllowed = FALSE; 6190 IsForCRT2 = TRUE; 6191 } else { /* CRT1: */ 6192 if(pSiS->VBFlags & CRT1_LCDA) { 6193 if(!(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 6194 acceptcustommodes = FALSE; 6195 includelcdmodes = FALSE; 6196 fakecrt2modes = TRUE; 6197 /* Will handle i-lace in mode-switching code */ 6198 } else { 6199 isfordvi = TRUE; 6200 /* Don't allow i-lace modes */ 6201 clockRanges->interlaceAllowed = FALSE; 6202 } 6203 } else { 6204 includelcdmodes = FALSE; 6205 } 6206 } 6207 } else 6208#endif 6209#ifdef SISMERGED /* MergedFB mode is not static. Output devices may change. */ 6210 if(pSiS->MergedFB) { 6211 if(pSiS->VBFlags & CRT1_LCDA) { 6212 if(!(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 6213 acceptcustommodes = FALSE; 6214 includelcdmodes = FALSE; 6215 fakecrt2modes = TRUE; 6216 /* Will handle i-lace in mode-switching code */ 6217 } else { 6218 isfordvi = TRUE; 6219 /* Don't allow i-lace custom modes */ 6220 clockRanges->interlaceAllowed = FALSE; 6221 } 6222 } else { 6223 includelcdmodes = FALSE; 6224 } 6225 } else 6226#endif /* Mirror mode is not static. Output devices may change. */ 6227 if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 6228 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 6229 if(!(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 6230 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA))) includelcdmodes = FALSE; 6231 if(pSiS->VBFlags & CRT2_LCD) isfordvi = TRUE; 6232 } else { 6233 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA|CRT1_LCDA))) includelcdmodes = FALSE; 6234 if(pSiS->VBFlags & (CRT2_LCD|CRT1_LCDA)) isfordvi = TRUE; 6235 } 6236 if((!(pSiS->VBFlags & DISPTYPE_CRT1)) && (!(pSiS->VBFlags & CRT1_LCDA))) { 6237 IsForCRT2 = TRUE; 6238 } 6239 /* Allow user modes, even if CRT2 is TV. Will be filtered through ValidMode(); 6240 * leaving the user modes here might have the advantage that such a mode, if 6241 * it matches in resolution with a supported TV mode, allows us to drive eg. 6242 * non standard panels, and still permits switching to TV. This mode will be 6243 * "mapped" to a supported mode of identical resolution for TV. All this is 6244 * taken care of by ValidMode() and ModeInit()/PresetMode(). 6245 */ 6246 } else { 6247 if(pSiS->VBFlags & (CRT2_TV|CRT2_LCD)) { 6248 acceptcustommodes = FALSE; 6249 includelcdmodes = FALSE; 6250 if(!(pSiS->VBFlags & DISPTYPE_CRT1)) { 6251 fakecrt2modes = TRUE; 6252 IsForCRT2 = TRUE; 6253 } 6254 } 6255 } 6256 } else if(pSiS->VBFlags & (CRT2_ENABLE | CRT1_LCDA)) { 6257 acceptcustommodes = FALSE; 6258 includelcdmodes = FALSE; 6259 if((pSiS->VBFlags & CRT1_LCDA) || (!(pSiS->VBFlags & DISPTYPE_CRT1))) { 6260 fakecrt2modes = TRUE; 6261 IsForCRT2 = TRUE; 6262 } 6263 } else { 6264 includelcdmodes = FALSE; 6265 } 6266 /* Ignore interlace, mode switching code will handle this */ 6267 6268 pSiS->HaveCustomModes = FALSE; 6269 if(SiSMakeOwnModeList(pScrn, acceptcustommodes, includelcdmodes, 6270 isfordvi, &pSiS->HaveCustomModes, FALSE /*fakecrt2modes*/, IsForCRT2)) { 6271 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6272 "Replaced %s mode list with built-in modes\n", 6273 pSiS->HaveCustomModes ? "default" : "entire"); 6274 if(pSiS->VGAEngine == SIS_315_VGA) { 6275 int UseWide = pSiS->SiS_Pr->SiS_UseWide; 6276 if(IsForCRT2) UseWide = pSiS->SiS_Pr->SiS_UseWideCRT2; 6277 if((!IsForCRT2) || (pSiS->VBFlags2 & VB2_SISVGA2BRIDGE)) { 6278 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6279 "Using %s widescreen modes for CRT%d VGA devices\n", 6280 UseWide ? "real" : "fake", IsForCRT2 ? 2 : 1); 6281 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6282 "\tUse option \"ForceCRT%dVGAAspect\" to overrule\n", 6283 IsForCRT2 ? 2 : 1); 6284 } 6285 } 6286#ifdef TWDEBUG 6287 pScrn->modes = pScrn->monitor->Modes; 6288 xf86PrintModes(pScrn); 6289 pScrn->modes = NULL; 6290#endif 6291 } else { 6292 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 6293 "Building list of built-in modes failed, using server defaults\n"); 6294 } 6295 } else { 6296 pSiS->HaveCustomModes = TRUE; 6297 } 6298 } 6299 6300 /* Add our built-in hi-res and TV modes on the 6326 */ 6301 if(pSiS->Chipset == PCI_CHIP_SIS6326) { 6302 if(pScrn->bitsPerPixel == 8) { 6303 SiS6326SIS1600x1200_60Mode.next = pScrn->monitor->Modes; 6304 pScrn->monitor->Modes = &SiS6326SIS1600x1200_60Mode; 6305 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6306 "Adding mode \"SIS1600x1200-60\" (depth 8 only)\n"); 6307 } 6308 if(pScrn->bitsPerPixel <= 16) { 6309 SiS6326SIS1280x1024_75Mode.next = pScrn->monitor->Modes; 6310 pScrn->monitor->Modes = &SiS6326SIS1280x1024_75Mode; 6311 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6312 "Adding mode \"SIS1280x1024-75\" (depths 8, 15 and 16 only)\n"); 6313 } 6314 if((pSiS->SiS6326Flags & SIS6326_HASTV) && 6315 (pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 6316 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6317 "Adding %s TV modes to mode list:\n", 6318 (pSiS->SiS6326Flags & SIS6326_TVPAL) ? "PAL" : "NTSC"); 6319 if(pSiS->SiS6326Flags & SIS6326_TVPAL) { 6320 SiS6326PAL800x600Mode.next = pScrn->monitor->Modes; 6321 pScrn->monitor->Modes = &SiS6326PAL640x480Mode; 6322 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6323 "\t\"PAL800x600\" \"PAL800x600U\" \"PAL720x540\" \"PAL640x480\"\n"); 6324 } else { 6325 SiS6326NTSC640x480Mode.next = pScrn->monitor->Modes; 6326 pScrn->monitor->Modes = &SiS6326NTSC640x400Mode; 6327 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6328 "\t\"NTSC640x480\" \"NTSC640x480U\" \"NTSC640x400\"\n"); 6329 } 6330 } 6331 } 6332 6333 /* If there is no HSync or VRefresh data for the monitor, 6334 * derive it from DDC data. Essentially done by common layer 6335 * since 4.3.99.14, but this is not usable since it is done 6336 * too late (in ValidateModes()). 6337 * Addendum: I overrule the ranges now in any case unless 6338 * it would affect a CRT output device or DDC data is available. 6339 * Hence, for LCD(A) and TV, we always get proper ranges. This 6340 * is entirely harmless. However, option "NoOverruleRanges" will 6341 * disable this behavior. 6342 * This should "fix" the - by far - most common configuration 6343 * mistakes. 6344 */ 6345 6346 crt1freqoverruled = FALSE; 6347 6348 fromDDC = FALSE; 6349 if((pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6350 if((pScrn->monitor->nHsync <= 0) && (pScrn->monitor->DDC)) { 6351 SiSSetSyncRangeFromEdid(pScrn, 1); 6352 if(pScrn->monitor->nHsync > 0) { 6353 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subshstr, 6354#ifdef SISDUALHEAD 6355 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6356#endif 6357 pSiS->CRT1off ? 2 : 1); 6358 fromDDC = TRUE; 6359 } 6360 } 6361 if((pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6362 if(SiSAllowSyncOverride(pSiS, fromDDC)) { 6363 Bool HaveNoRanges = (pScrn->monitor->nHsync <= 0); 6364 /* Set sane ranges for LCD and TV 6365 * (our strict checking will filter out invalid ones anyway) 6366 */ 6367 if((crt1freqoverruled = CheckAndOverruleH(pScrn, pScrn->monitor))) { 6368 xf86DrvMsg(pScrn->scrnIndex, X_INFO, saneh, 6369 HaveNoRanges ? "missing" : "bogus", 6370#ifdef SISDUALHEAD 6371 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6372#endif 6373 pSiS->CRT1off ? 2 : 1); 6374 } 6375 } 6376 } 6377 } 6378 6379 fromDDC = FALSE; 6380 if((pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6381 if((pScrn->monitor->nVrefresh <= 0) && (pScrn->monitor->DDC)) { 6382 SiSSetSyncRangeFromEdid(pScrn, 0); 6383 if(pScrn->monitor->nVrefresh > 0) { 6384 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subsvstr, 6385#ifdef SISDUALHEAD 6386 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6387#endif 6388 pSiS->CRT1off ? 2 : 1); 6389 fromDDC = TRUE; 6390 } 6391 } 6392 if((pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6393 if(SiSAllowSyncOverride(pSiS, fromDDC)) { 6394 Bool HaveNoRanges = (pScrn->monitor->nVrefresh <= 0); 6395 /* Set sane ranges for LCD and TV */ 6396 if((crt1freqoverruled = CheckAndOverruleV(pScrn, pScrn->monitor))) { 6397 xf86DrvMsg(pScrn->scrnIndex, X_INFO, sanev, 6398 HaveNoRanges ? "missing" : "bogus", 6399#ifdef SISDUALHEAD 6400 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6401#endif 6402 pSiS->CRT1off ? 2 : 1); 6403 } 6404 } 6405 } 6406 } 6407 6408 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 6409 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6410 "\"Unknown reason\" in the following list means that the mode\n"); 6411 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6412 "is not supported on the chipset/bridge/current output device.\n"); 6413 } 6414 6415 /* 6416 * xf86ValidateModes will check that the mode HTotal and VTotal values 6417 * don't exceed the chipset's limit if pScrn->maxHValue and 6418 * pScrn->maxVValue are set. Since our SISValidMode() already takes 6419 * care of this, we don't worry about setting them here. 6420 */ 6421 6422 /* Select valid modes from those available */ 6423 /* 6424 * Assuming min pitch 256, min height 128 6425 */ 6426 { 6427 int minpitch, maxpitch, minheight, maxheight; 6428 pointer backupddc = pScrn->monitor->DDC; 6429 6430 minpitch = 256; 6431 minheight = 128; 6432 switch(pSiS->VGAEngine) { 6433 case SIS_OLD_VGA: 6434 case SIS_530_VGA: 6435 maxpitch = 2040; 6436 maxheight = 2048; 6437 break; 6438 case SIS_300_VGA: 6439 case SIS_315_VGA: 6440 maxpitch = 4088; 6441 maxheight = 4096; 6442 break; 6443 default: 6444 maxpitch = 2048; 6445 maxheight = 2048; 6446 break; 6447 } 6448 6449#ifdef SISMERGED 6450 pSiS->CheckForCRT2 = FALSE; 6451#endif 6452 6453 /* Suppress bogus DDC warning */ 6454 if(crt1freqoverruled) pScrn->monitor->DDC = NULL; 6455 6456 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 6457 pScrn->display->modes, clockRanges, NULL, 6458 minpitch, maxpitch, 6459 pScrn->bitsPerPixel * 8, 6460 minheight, maxheight, 6461 pScrn->display->virtualX, 6462 pScrn->display->virtualY, 6463 pSiS->maxxfbmem, 6464 LOOKUP_BEST_REFRESH); 6465 6466 pScrn->monitor->DDC = backupddc; 6467 } 6468 6469 if(i == -1) { 6470 SISErrorLog(pScrn, "xf86ValidateModes() error\n"); 6471 goto my_error_1; 6472 } 6473 6474 /* Check the virtual screen against the available memory */ 6475 { 6476 ULong memreq = (pScrn->virtualX * ((pScrn->bitsPerPixel + 7) / 8)) * pScrn->virtualY; 6477 6478 if(memreq > pSiS->maxxfbmem) { 6479 SISErrorLog(pScrn, 6480 "Virtual screen too big for memory; %ldK needed, %ldK available\n", 6481 memreq/1024, pSiS->maxxfbmem/1024); 6482 goto my_error_1; 6483 } 6484 } 6485 6486 /* Dual Head: 6487 * -) Go through mode list and mark all those modes as bad, 6488 * which are unsuitable for dual head mode. 6489 * -) Find the highest used pixelclock on the master head. 6490 */ 6491#ifdef SISDUALHEAD 6492 if((pSiS->DualHeadMode) && (!pSiS->SecondHead)) { 6493 6494 pSiSEnt->maxUsedClock = 0; 6495 6496 if((p = first = pScrn->modes)) { 6497 6498 do { 6499 6500 n = p->next; 6501 6502 /* Modes that require the bridge to operate in SlaveMode 6503 * are not suitable for Dual Head mode. 6504 */ 6505 if( (pSiS->VGAEngine == SIS_300_VGA) && 6506 ( (strcmp(p->name, "320x200") == 0) || 6507 (strcmp(p->name, "320x240") == 0) || 6508 (strcmp(p->name, "400x300") == 0) || 6509 (strcmp(p->name, "512x384") == 0) || 6510 (strcmp(p->name, "640x400") == 0) ) ) { 6511 p->status = MODE_BAD; 6512 xf86DrvMsg(pScrn->scrnIndex, X_INFO, notsuitablestr, p->name, "dual head"); 6513 } 6514 6515 /* Search for the highest clock on first head in order to calculate 6516 * max clock for second head (CRT1) 6517 */ 6518 if((p->status == MODE_OK) && (p->Clock > pSiSEnt->maxUsedClock)) { 6519 pSiSEnt->maxUsedClock = p->Clock; 6520 } 6521 6522 p = n; 6523 6524 } while (p != NULL && p != first); 6525 6526 } 6527 } 6528#endif 6529 6530 /* Prune the modes marked as invalid */ 6531 xf86PruneDriverModes(pScrn); 6532 6533 if(i == 0 || pScrn->modes == NULL) { 6534 SISErrorLog(pScrn, "No valid modes found - check VertRefresh/HorizSync\n"); 6535 goto my_error_1; 6536 } 6537 6538 xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 6539 6540 /* Set the current mode to the first in the list */ 6541 pScrn->currentMode = pScrn->modes; 6542 6543 /* Copy to CurrentLayout */ 6544 pSiS->CurrentLayout.mode = pScrn->currentMode; 6545 pSiS->CurrentLayout.displayWidth = pScrn->displayWidth; 6546 pSiS->CurrentLayout.displayHeight = pScrn->virtualY; 6547 6548#ifdef SISMERGED 6549 if(pSiS->MergedFB) { 6550 xf86DrvMsg(pScrn->scrnIndex, X_INFO, modesforstr, 1); 6551 } 6552#endif 6553 6554 /* Print the list of modes being used */ 6555 { 6556 Bool usemyprint = FALSE; 6557 6558#ifdef SISDUALHEAD 6559 if(pSiS->DualHeadMode) { 6560 if(pSiS->SecondHead) { 6561 if(pSiS->VBFlags & CRT1_LCDA) usemyprint = TRUE; 6562 } else { 6563 if(pSiS->VBFlags & (CRT2_LCD | CRT2_TV)) usemyprint = TRUE; 6564 } 6565 } else 6566#endif 6567#ifdef SISMERGED 6568 if(pSiS->MergedFB) { 6569 if(pSiS->VBFlags & CRT1_LCDA) usemyprint = TRUE; 6570 } else 6571#endif 6572 { 6573 if( (pSiS->VBFlags & (CRT2_LCD | CRT2_TV)) && 6574 (!(pSiS->VBFlags & DISPTYPE_DISP1)) ) 6575 usemyprint = TRUE; 6576 } 6577 6578 if(usemyprint) { 6579 SiSPrintModes(pScrn); 6580 } else { 6581 xf86PrintModes(pScrn); 6582 } 6583 } 6584 6585#ifdef SISMERGED 6586 if(pSiS->MergedFB) { 6587 Bool acceptcustommodes = TRUE; 6588 Bool includelcdmodes = TRUE; 6589 Bool isfordvi = FALSE; 6590 Bool fakecrt2modes = FALSE; 6591 6592 xf86DrvMsg(pScrn->scrnIndex, X_INFO, crtsetupstr, 2); 6593 6594 clockRanges->next = NULL; 6595 clockRanges->minClock = pSiS->MinClock; 6596 clockRanges->maxClock = SiSMemBandWidth(pSiS->CRT2pScrn, TRUE); 6597 clockRanges->clockIndex = -1; 6598 clockRanges->interlaceAllowed = FALSE; 6599 clockRanges->doubleScanAllowed = FALSE; 6600 if(pSiS->VGAEngine == SIS_315_VGA) { 6601 clockRanges->doubleScanAllowed = TRUE; 6602 } 6603 6604 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock for CRT2 is %d MHz\n", 6605 clockRanges->minClock / 1000); 6606 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Max pixel clock for CRT2 is %d MHz\n", 6607 clockRanges->maxClock / 1000); 6608 6609 if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 6610 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 6611 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA))) includelcdmodes = FALSE; 6612 if(pSiS->VBFlags & CRT2_LCD) isfordvi = TRUE; 6613 /* See above for a remark on handling CRT2 = TV */ 6614 } else { 6615 if(pSiS->VBFlags & (CRT2_LCD|CRT2_TV)) { 6616 includelcdmodes = FALSE; 6617 acceptcustommodes = FALSE; 6618 fakecrt2modes = TRUE; 6619 } 6620 } 6621 } else { 6622 includelcdmodes = FALSE; 6623 acceptcustommodes = FALSE; 6624 if(pSiS->VBFlags & (CRT2_LCD|CRT2_TV)) { 6625 fakecrt2modes = TRUE; 6626 } 6627 } 6628 6629 pSiS->HaveCustomModes2 = FALSE; 6630 if(!SiSMakeOwnModeList(pSiS->CRT2pScrn, acceptcustommodes, includelcdmodes, 6631 isfordvi, &pSiS->HaveCustomModes2, FALSE /* fakecrt2modes */, TRUE )) { 6632 6633 SISErrorLog(pScrn, "Building list of built-in modes for CRT2 failed, %s\n", 6634 mergeddisstr); 6635 SiSFreeCRT2Structs(pSiS); 6636 pSiS->MergedFB = FALSE; 6637 6638 } else { 6639 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6640 "Replaced %s mode list for CRT2 with built-in modes\n", 6641 pSiS->HaveCustomModes2 ? "default" : "entire"); 6642 if((pSiS->VGAEngine == SIS_315_VGA) && (pSiS->VBFlags2 & VB2_SISVGA2BRIDGE)) { 6643 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6644 "Using %s widescreen modes for CRT2 VGA devices\n", 6645 pSiS->SiS_Pr->SiS_UseWideCRT2 ? "real" : "fake"); 6646 } else pSiS->SiS_Pr->SiS_UseWideCRT2 = 0; 6647 } 6648 6649 } 6650 6651 if(pSiS->MergedFB) { 6652 6653 pointer backupddc; 6654 6655 crt2freqoverruled = FALSE; 6656 6657 fromDDC = FALSE; 6658 if((pSiS->CRT2pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6659 if((pSiS->CRT2pScrn->monitor->nHsync <= 0) && (pSiS->CRT2pScrn->monitor->DDC)) { 6660 SiSSetSyncRangeFromEdid(pSiS->CRT2pScrn, 1); 6661 if(pSiS->CRT2pScrn->monitor->nHsync > 0) { 6662 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subshstr, 2); 6663 fromDDC = TRUE; 6664 } 6665 } 6666 if((pSiS->CRT2pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6667 if( (pSiS->VBFlags & CRT2_TV) || 6668 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC)) ) { 6669 Bool HaveNoRanges = (pSiS->CRT2pScrn->monitor->nHsync <= 0); 6670 /* Set sane ranges for LCD and TV */ 6671 if((crt2freqoverruled = CheckAndOverruleH(pScrn, pSiS->CRT2pScrn->monitor))) { 6672 xf86DrvMsg(pScrn->scrnIndex, X_INFO, saneh, 6673 HaveNoRanges ? "missing" : "bogus", 2); 6674 } 6675 } 6676 } 6677 } 6678 6679 fromDDC = FALSE; 6680 if((pSiS->CRT2pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6681 if((pSiS->CRT2pScrn->monitor->nVrefresh <= 0) && (pSiS->CRT2pScrn->monitor->DDC)) { 6682 SiSSetSyncRangeFromEdid(pSiS->CRT2pScrn, 0); 6683 if(pSiS->CRT2pScrn->monitor->nVrefresh > 0) { 6684 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subsvstr, 2); 6685 fromDDC = TRUE; 6686 } 6687 } 6688 if((pSiS->CRT2pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6689 if( (pSiS->VBFlags & CRT2_TV) || 6690 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC)) ) { 6691 Bool HaveNoRanges = (pSiS->CRT2pScrn->monitor->nVrefresh <= 0); 6692 /* Set sane ranges for LCD and TV */ 6693 if((crt2freqoverruled = CheckAndOverruleV(pScrn, pSiS->CRT2pScrn->monitor))) { 6694 xf86DrvMsg(pScrn->scrnIndex, X_INFO, sanev, 6695 HaveNoRanges ? "missing" : "bogus", 2); 6696 } 6697 } 6698 } 6699 } 6700 6701 backupddc = pSiS->CRT2pScrn->monitor->DDC; 6702 6703 /* Suppress bogus DDC warning */ 6704 if(crt2freqoverruled) pSiS->CRT2pScrn->monitor->DDC = NULL; 6705 6706 pSiS->CheckForCRT2 = TRUE; 6707 6708 i = xf86ValidateModes(pSiS->CRT2pScrn, pSiS->CRT2pScrn->monitor->Modes, 6709 pSiS->CRT2pScrn->display->modes, clockRanges, 6710 NULL, 256, 4088, 6711 pSiS->CRT2pScrn->bitsPerPixel * 8, 128, 4096, 6712 pScrn->display->virtualX ? pScrn->virtualX : 0, 6713 pScrn->display->virtualY ? pScrn->virtualY : 0, 6714 pSiS->maxxfbmem, 6715 LOOKUP_BEST_REFRESH); 6716 6717 pSiS->CheckForCRT2 = FALSE; 6718 pSiS->CRT2pScrn->monitor->DDC = backupddc; 6719 6720 if(i == -1) { 6721 SISErrorLog(pScrn, "xf86ValidateModes() error, %s.\n", mergeddisstr); 6722 SiSFreeCRT2Structs(pSiS); 6723 pSiS->MergedFB = FALSE; 6724 } 6725 6726 } 6727 6728 if(pSiS->MergedFB) { 6729 6730 if((p = first = pSiS->CRT2pScrn->modes)) { 6731 do { 6732 n = p->next; 6733 if( (pSiS->VGAEngine == SIS_300_VGA) && 6734 ( (strcmp(p->name, "320x200") == 0) || 6735 (strcmp(p->name, "320x240") == 0) || 6736 (strcmp(p->name, "400x300") == 0) || 6737 (strcmp(p->name, "512x384") == 0) || 6738 (strcmp(p->name, "640x400") == 0) ) ) { 6739 p->status = MODE_BAD; 6740 xf86DrvMsg(pScrn->scrnIndex, X_INFO, notsuitablestr, p->name, "MergedFB"); 6741 } 6742 p = n; 6743 } while (p != NULL && p != first); 6744 } 6745 6746 xf86PruneDriverModes(pSiS->CRT2pScrn); 6747 6748 if(i == 0 || pSiS->CRT2pScrn->modes == NULL) { 6749 SISErrorLog(pScrn, "No valid modes found for CRT2; %s\n", mergeddisstr); 6750 SiSFreeCRT2Structs(pSiS); 6751 pSiS->MergedFB = FALSE; 6752 } 6753 6754 } 6755 6756 if(pSiS->MergedFB) { 6757 6758 xf86SetCrtcForModes(pSiS->CRT2pScrn, INTERLACE_HALVE_V); 6759 6760 xf86DrvMsg(pScrn->scrnIndex, X_INFO, modesforstr, 2); 6761 6762 if(pSiS->VBFlags & (CRT2_LCD | CRT2_TV)) { 6763 SiSPrintModes(pSiS->CRT2pScrn); 6764 } else { 6765 xf86PrintModes(pSiS->CRT2pScrn); 6766 } 6767 6768 pSiS->CRT1Modes = pScrn->modes; 6769 pSiS->CRT1CurrentMode = pScrn->currentMode; 6770 6771 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MergedFB: Generating mode list\n"); 6772 6773 pScrn->modes = SiSGenerateModeList(pScrn, pSiS->MetaModes, 6774 pSiS->CRT1Modes, pSiS->CRT2pScrn->modes, 6775 pSiS->CRT2Position); 6776 6777 if(!pScrn->modes) { 6778 6779 SISErrorLog(pScrn, "Failed to parse MetaModes or no modes found. %s.\n", 6780 mergeddisstr); 6781 SiSFreeCRT2Structs(pSiS); 6782 pScrn->modes = pSiS->CRT1Modes; 6783 pSiS->CRT1Modes = NULL; 6784 pSiS->MergedFB = FALSE; 6785 6786 } 6787 6788 } 6789 6790 if(pSiS->MergedFB) { 6791 6792 /* If no virtual dimension was given by the user, 6793 * calculate a sane one now. Adapts pScrn->virtualX, 6794 * pScrn->virtualY and pScrn->displayWidth. 6795 */ 6796 SiSRecalcDefaultVirtualSize(pScrn); 6797 6798 pScrn->modes = pScrn->modes->next; /* We get the last from GenerateModeList(), skip to first */ 6799 pScrn->currentMode = pScrn->modes; 6800 6801 /* Update CurrentLayout */ 6802 pSiS->CurrentLayout.mode = pScrn->currentMode; 6803 pSiS->CurrentLayout.displayWidth = pScrn->displayWidth; 6804 pSiS->CurrentLayout.displayHeight = pScrn->virtualY; 6805 6806 } 6807#endif 6808 6809 /* Set display resolution */ 6810#ifdef SISMERGED 6811 if(pSiS->MergedFB) { 6812 SiSMergedFBSetDpi(pScrn, pSiS->CRT2pScrn, pSiS->CRT2Position); 6813 } else 6814#endif 6815 xf86SetDpi(pScrn, 0, 0); 6816 6817 /* Load fb module */ 6818 switch(pScrn->bitsPerPixel) { 6819 case 8: 6820 case 16: 6821 case 24: 6822 case 32: 6823 if(!xf86LoadSubModule(pScrn, "fb")) { 6824 SISErrorLog(pScrn, "Failed to load fb module"); 6825 goto my_error_1; 6826 } 6827 break; 6828 default: 6829 SISErrorLog(pScrn, "Unsupported framebuffer bpp (%d)\n", pScrn->bitsPerPixel); 6830 goto my_error_1; 6831 } 6832 6833 /* Load XAA/EXA (if needed) */ 6834 if(!pSiS->NoAccel) { 6835#ifdef SIS_USE_XAA 6836 if(!pSiS->useEXA) { 6837 if (!xf86LoadSubModule(pScrn, "xaa")) { 6838 SISErrorLog(pScrn, "Could not load xaa module\n"); 6839 goto my_error_1; 6840 } 6841 } 6842#endif 6843#ifdef SIS_USE_EXA 6844 if(pSiS->useEXA) { 6845 XF86ModReqInfo req; 6846 int errmaj, errmin; 6847 6848 memset(&req, 0, sizeof(req)); 6849 req.majorversion = 2; 6850 req.minorversion = 0; 6851 if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, &req, 6852 &errmaj, &errmin)) { 6853 LoaderErrorMsg(NULL, "exa", errmaj, errmin); 6854 goto my_error_1; 6855 } 6856 } 6857#endif 6858 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D acceleration enabled\n"); 6859 } 6860 6861 /* Load shadowfb (if needed) */ 6862 if(pSiS->ShadowFB) { 6863 if(!xf86LoadSubModule(pScrn, "shadowfb")) { 6864 SISErrorLog(pScrn, "Could not load shadowfb module\n"); 6865 goto my_error_1; 6866 } 6867 } 6868 6869 /* Load the dri and glx modules if requested. */ 6870#ifdef XF86DRI 6871 if(pSiS->loadDRI) { 6872 if(!xf86LoaderCheckSymbol("DRIScreenInit")) { 6873 if(xf86LoadSubModule(pScrn, "dri")) { 6874 if(!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) { 6875 if(!xf86LoadSubModule(pScrn, "glx")) { 6876 SISErrorLog(pScrn, "Failed to load glx module\n"); 6877 } 6878 } 6879 } else { 6880 SISErrorLog(pScrn, "Failed to load dri module\n"); 6881 } 6882 } 6883 } 6884#endif 6885 6886 /* Now load and initialize VBE module for VESA mode switching */ 6887 pSiS->UseVESA = 0; 6888 if(pSiS->VESA == 1) { 6889 SiS_LoadInitVBE(pScrn); 6890 if(pSiS->pVbe) { 6891 VbeInfoBlock *vbe; 6892 if((vbe = VBEGetVBEInfo(pSiS->pVbe))) { 6893 pSiS->vesamajor = (unsigned)(vbe->VESAVersion >> 8); 6894 pSiS->vesaminor = vbe->VESAVersion & 0xff; 6895 SiSBuildVesaModeList(pScrn, pSiS->pVbe, vbe); 6896 VBEFreeVBEInfo(vbe); 6897 pSiS->UseVESA = 1; 6898 } else { 6899 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 6900 "Failed to read VBE Info Block\n"); 6901 } 6902 } 6903 if(pSiS->UseVESA == 0) { 6904 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 6905 "VESA mode switching disabled.\n"); 6906 } 6907 } 6908 6909 if(pSiS->pVbe) { 6910 vbeFree(pSiS->pVbe); 6911 pSiS->pVbe = NULL; 6912 } 6913 6914#ifdef SISDUALHEAD 6915 xf86SetPrimInitDone(pScrn->entityList[0]); 6916#endif 6917 6918 sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); 6919 6920 if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); 6921 pSiS->pInt = NULL; 6922 6923 if(pSiS->VGAEngine == SIS_315_VGA) { 6924 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTXVGAMMA1; 6925 } 6926 6927#ifdef SISDUALHEAD 6928 if(pSiS->DualHeadMode) { 6929 pSiS->SiS_SD_Flags |= SiS_SD_ISDUALHEAD; 6930 if(pSiS->SecondHead) pSiS->SiS_SD_Flags |= SiS_SD_ISDHSECONDHEAD; 6931 else pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTXVGAMMA1); 6932#ifdef PANORAMIX 6933 if(!noPanoramiXExtension) { 6934 pSiS->SiS_SD_Flags |= SiS_SD_ISDHXINERAMA; 6935 /* pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTXVGAMMA1); */ 6936 } 6937#endif 6938 } 6939#endif 6940 6941#ifdef SISMERGED 6942 if(pSiS->MergedFB) pSiS->SiS_SD_Flags |= SiS_SD_ISMERGEDFB; 6943#endif 6944 6945 /* Try to determine if this is a laptop */ 6946 /* (only used for SiSCtrl visualisations) */ 6947 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPLTFLAG; 6948 pSiS->SiS_SD2_Flags &= ~SiS_SD2_ISLAPTOP; 6949 if(pSiS->detectedCRT2Devices & CRT2_LCD) { 6950 if(pSiS->VBFlags2 & (VB2_SISLVDSBRIDGE | VB2_LVDS | VB2_30xBDH)) { 6951 /* 1. By bridge type: LVDS in 99% of all cases; 6952 * exclude unusual setups like Barco projectors 6953 * and parallel flat panels. TODO: Exclude 6954 * Sony W1, V1. 6955 */ 6956 if((pSiS->SiS_Pr->SiS_CustomT != CUT_BARCO1366) && 6957 (pSiS->SiS_Pr->SiS_CustomT != CUT_BARCO1024) && 6958 (pSiS->SiS_Pr->SiS_CustomT != CUT_PANEL848) && 6959 (pSiS->SiS_Pr->SiS_CustomT != CUT_PANEL856) && 6960 (pSiS->SiS_Pr->SiS_CustomT != CUT_AOP8060) && 6961 ( (pSiS->ChipType != SIS_550) || 6962 (!pSiS->DSTN && !pSiS->FSTN) ) ) { 6963 pSiS->SiS_SD2_Flags |= SiS_SD2_ISLAPTOP; 6964 } 6965 } else if((pSiS->VBFlags2 & (VB2_301 | VB2_301C)) && 6966 (pSiS->VBLCDFlags & (VB_LCD_1280x960 | 6967 VB_LCD_1400x1050 | 6968 VB_LCD_1024x600 | 6969 VB_LCD_1280x800 | 6970 VB_LCD_1280x854))) { 6971 /* 2. By (odd) LCD resolutions on TMDS bridges 6972 * (eg Averatec). TODO: Exclude IBM Netvista. 6973 */ 6974 pSiS->SiS_SD2_Flags |= SiS_SD2_ISLAPTOP; 6975 } 6976 } 6977 6978 if(pSiS->enablesisctrl) pSiS->SiS_SD_Flags |= SiS_SD_ENABLED; 6979 6980 pSiS->currentModeLast = pScrn->currentMode; 6981 pSiS->VBFlagsInit = pSiS->VBFlags; 6982 6983 return TRUE; 6984 6985 /* ---- */ 6986 6987my_error_1: 6988 sisRestoreExtRegisterLock(pSiS, srlockReg, crlockReg); 6989my_error_0: 6990#ifdef SISDUALHEAD 6991 if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; 6992#endif 6993 if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); 6994 pSiS->pInt = NULL; 6995 SISFreeRec(pScrn); 6996 return FALSE; 6997} 6998 6999/* 7000 * Map I/O port area for non-PC platforms 7001 */ 7002#ifdef SIS_NEED_MAP_IOP 7003static Bool 7004SISMapIOPMem(ScrnInfoPtr pScrn) 7005{ 7006 SISPtr pSiS = SISPTR(pScrn); 7007#ifdef SISDUALHEAD 7008 SISEntPtr pSiSEnt = pSiS->entityPrivate; 7009 7010 if(pSiS->DualHeadMode) { 7011 pSiSEnt->MapCountIOPBase++; 7012 if(!(pSiSEnt->IOPBase)) { 7013 /* Only map if not mapped previously */ 7014#ifndef XSERVER_LIBPCIACCESS 7015 pSiSEnt->IOPBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7016 pSiS->PciTag, pSiS->IOPAddress, 128); 7017#else 7018 { 7019 void **result = (void **)&pSiSEnt->IOPBase; 7020 int err = pci_device_map_range(pSiS->PciInfo, 7021 pSiS->IOPAddress, 7022 128, 7023 PCI_DEV_MAP_FLAG_WRITABLE, 7024 result); 7025 7026 if (err) { 7027 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7028 "Unable to map IO aperture. %s (%d)\n", 7029 strerror (err), err); 7030 } 7031 } 7032#endif 7033 } 7034 pSiS->IOPBase = pSiSEnt->IOPBase; 7035 } else 7036#endif 7037#ifndef XSERVER_LIBPCIACCESS 7038 pSiS->IOPBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7039 pSiS->PciTag, pSiS->IOPAddress, 128); 7040#else 7041 { 7042 void **result = (void **)&pSiS->IOPBase; 7043 int err = pci_device_map_range(pSiS->PciInfo, 7044 pSiS->IOPAddress, 7045 128, 7046 PCI_DEV_MAP_FLAG_WRITABLE, 7047 result); 7048 7049 if (err) { 7050 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7051 "Unable to map IO aperture. %s (%d)\n", 7052 strerror (err), err); 7053 } 7054 } 7055#endif 7056 if(pSiS->IOPBase == NULL) { 7057 SISErrorLog(pScrn, "Could not map I/O port area\n"); 7058 return FALSE; 7059 } 7060 7061 return TRUE; 7062} 7063 7064static Bool 7065SISUnmapIOPMem(ScrnInfoPtr pScrn) 7066{ 7067 SISPtr pSiS = SISPTR(pScrn); 7068#ifdef SISDUALHEAD 7069 SISEntPtr pSiSEnt = pSiS->entityPrivate;; 7070#endif 7071 7072/* In dual head mode, we must not unmap if the other head still 7073 * assumes memory as mapped 7074 */ 7075#ifdef SISDUALHEAD 7076 if(pSiS->DualHeadMode) { 7077 if(pSiSEnt->MapCountIOPBase) { 7078 pSiSEnt->MapCountIOPBase--; 7079 if((pSiSEnt->MapCountIOPBase == 0) || (pSiSEnt->forceUnmapIOPBase)) { 7080 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOPBase, 2048); 7081 pSiSEnt->IOPBase = NULL; 7082 pSiSEnt->MapCountIOPBase = 0; 7083 pSiSEnt->forceUnmapIOPBase = FALSE; 7084 } 7085 pSiS->IOPBase = NULL; 7086 } 7087 } else { 7088#endif 7089 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOPBase, 2048); 7090 pSiS->IOPBase = NULL; 7091#ifdef SISDUALHEAD 7092 } 7093#endif 7094 return TRUE; 7095} 7096#endif 7097 7098/* 7099 * Map the framebuffer and MMIO memory 7100 */ 7101 7102static Bool 7103SISMapMem(ScrnInfoPtr pScrn) 7104{ 7105 SISPtr pSiS = SISPTR(pScrn); 7106 int mmioFlags = VIDMEM_MMIO; 7107#ifdef SISDUALHEAD 7108 SISEntPtr pSiSEnt = pSiS->entityPrivate; 7109#endif 7110 7111 /* 7112 * Map IO registers to virtual address space 7113 * (For Alpha, we need to map SPARSE memory, since we need 7114 * byte/short access.) 7115 */ 7116#if defined(__alpha__) 7117 mmioFlags |= VIDMEM_SPARSE; 7118#endif 7119 7120#ifdef SISDUALHEAD 7121 if(pSiS->DualHeadMode) { 7122 pSiSEnt->MapCountIOBase++; 7123 if(!(pSiSEnt->IOBase)) { 7124 /* Only map if not mapped previously */ 7125#ifndef XSERVER_LIBPCIACCESS 7126 pSiSEnt->IOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, 7127 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7128#else 7129 void **result = (void **)&pSiSEnt->IOBase; 7130 int err = pci_device_map_range(pSiS->PciInfo, 7131 pSiS->IOAddress, 7132 (pSiS->mmioSize * 1024), 7133 PCI_DEV_MAP_FLAG_WRITABLE, 7134 result); 7135 7136 if (err) { 7137 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7138 "Unable to map IO aperture. %s (%d)\n", 7139 strerror (err), err); 7140 } 7141#endif 7142 } 7143 pSiS->IOBase = pSiSEnt->IOBase; 7144 } else 7145#endif 7146#ifndef XSERVER_LIBPCIACCESS 7147 pSiS->IOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, 7148 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7149#else 7150 { 7151 void **result = (void **)&pSiS->IOBase; 7152 int err = pci_device_map_range(pSiS->PciInfo, 7153 pSiS->IOAddress, 7154 (pSiS->mmioSize * 1024), 7155 PCI_DEV_MAP_FLAG_WRITABLE, 7156 result); 7157 7158 if (err) { 7159 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7160 "Unable to map IO aperture. %s (%d)\n", 7161 strerror (err), err); 7162 } 7163 } 7164#endif 7165 7166 if(pSiS->IOBase == NULL) { 7167 SISErrorLog(pScrn, "Could not map MMIO area\n"); 7168 return FALSE; 7169 } 7170 7171#ifdef __alpha__ 7172 /* 7173 * for Alpha, we need to map DENSE memory as well, for 7174 * setting CPUToScreenColorExpandBase. 7175 */ 7176#ifdef SISDUALHEAD 7177 if(pSiS->DualHeadMode) { 7178 pSiSEnt->MapCountIOBaseDense++; 7179 if(!(pSiSEnt->IOBaseDense)) { 7180 /* Only map if not mapped previously */ 7181#ifndef XSERVER_LIBPCIACCESS 7182 pSiSEnt->IOBaseDense = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7183 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7184#else 7185 void **result = (void **)&pSiSEnt->IOBaseDense; 7186 int err = pci_device_map_range(pSiS->PciInfo, 7187 pSiS->IOAddress, 7188 (pSiS->mmioSize * 1024), 7189 PCI_DEV_MAP_FLAG_WRITABLE, 7190 result); 7191 7192 if (err) { 7193 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7194 "Unable to map IO dense aperture. %s (%d)\n", 7195 strerror (err), err); 7196 } 7197#endif /* XSERVER_LIBPCIACCESS */ 7198 } 7199 pSiS->IOBaseDense = pSiSEnt->IOBaseDense; 7200 } else { 7201#endif /* SISDUALHEAD */ 7202#ifndef XSERVER_LIBPCIACCESS 7203 pSiS->IOBaseDense = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7204 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7205#else 7206 void **result = (void **)&pSiS->IOBaseDense; 7207 int err = pci_device_map_range(pSiS->PciInfo, 7208 pSiS->IOAddress, 7209 (pSiS->mmioSize * 1024), 7210 PCI_DEV_MAP_FLAG_WRITABLE, 7211 result); 7212 7213 if (err) { 7214 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7215 "Unable to map IO dense aperture. %s (%d)\n", 7216 strerror (err), err); 7217 } 7218#endif /* XSERVER_LIBPCIACCESS */ 7219#ifdef SISDUALHEAD 7220 } 7221#endif 7222 if(pSiS->IOBaseDense == NULL) { 7223 SISErrorLog(pScrn, "Could not map MMIO dense area\n"); 7224 return FALSE; 7225 } 7226#endif /* __alpha__ */ 7227 7228#ifdef SISDUALHEAD 7229 if(pSiS->DualHeadMode) { 7230 pSiSEnt->MapCountFbBase++; 7231 if(!(pSiSEnt->FbBase)) { 7232 /* Only map if not mapped previously */ 7233#ifndef XSERVER_LIBPCIACCESS 7234 pSiSEnt->FbBase = pSiSEnt->RealFbBase = 7235 xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 7236 pSiS->PciTag, (ULong)pSiS->realFbAddress, 7237 pSiS->FbMapSize); 7238#else 7239 int err = pci_device_map_range(pSiS->PciInfo, 7240 (ULong)pSiS->realFbAddress, 7241 pSiS->FbMapSize, 7242 PCI_DEV_MAP_FLAG_WRITABLE | 7243 PCI_DEV_MAP_FLAG_WRITE_COMBINE, 7244 (void *)&pSiSEnt->FbBase); 7245 if (err) { 7246 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7247 "Unable to map FB aperture. %s (%d)\n", 7248 strerror (err), err); 7249 return FALSE; 7250 } 7251 pSiSEnt->RealFbBase = pSiSEnt->FbBase; 7252#endif 7253 } 7254 pSiS->FbBase = pSiS->RealFbBase = pSiSEnt->FbBase; 7255 /* Adapt FbBase (for DHM and SiS76x UMA skipping; dhmOffset is 0 otherwise) */ 7256 pSiS->FbBase += pSiS->dhmOffset; 7257 } else { 7258#endif 7259 7260#ifndef XSERVER_LIBPCIACCESS 7261 pSiS->FbBase = pSiS->RealFbBase = 7262 xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 7263 pSiS->PciTag, (ULong)pSiS->realFbAddress, 7264 pSiS->FbMapSize); 7265#else 7266 int err = pci_device_map_range(pSiS->PciInfo, 7267 (ULong)pSiS->realFbAddress, 7268 pSiS->FbMapSize, 7269 PCI_DEV_MAP_FLAG_WRITABLE | 7270 PCI_DEV_MAP_FLAG_WRITE_COMBINE, 7271 (void *)&pSiS->FbBase); 7272 if (err) { 7273 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7274 "Unable to map FB aperture. %s (%d)\n", 7275 strerror (err), err); 7276 return FALSE; 7277 } 7278 pSiS->RealFbBase = pSiS->FbBase; 7279#endif 7280 pSiS->FbBase += pSiS->dhmOffset; 7281 7282#ifdef SISDUALHEAD 7283 } 7284#endif 7285 7286 if(pSiS->FbBase == NULL) { 7287 SISErrorLog(pScrn, "Could not map framebuffer area\n"); 7288 return FALSE; 7289 } 7290 7291#ifdef TWDEBUG 7292 xf86DrvMsg(0, 0, "Framebuffer mapped to %p\n", pSiS->FbBase); 7293#endif 7294 7295 return TRUE; 7296} 7297 7298 7299/* 7300 * Unmap the framebuffer and MMIO memory. 7301 */ 7302 7303static Bool 7304SISUnmapMem(ScrnInfoPtr pScrn) 7305{ 7306 SISPtr pSiS = SISPTR(pScrn); 7307#ifdef SISDUALHEAD 7308 SISEntPtr pSiSEnt = pSiS->entityPrivate; 7309#endif 7310 7311/* In dual head mode, we must not unmap if the other head still 7312 * assumes memory as mapped 7313 */ 7314#ifdef SISDUALHEAD 7315 if(pSiS->DualHeadMode) { 7316 if(pSiSEnt->MapCountIOBase) { 7317 pSiSEnt->MapCountIOBase--; 7318 if((pSiSEnt->MapCountIOBase == 0) || (pSiSEnt->forceUnmapIOBase)) { 7319 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOBase, (pSiS->mmioSize * 1024)); 7320 pSiSEnt->IOBase = NULL; 7321 pSiSEnt->MapCountIOBase = 0; 7322 pSiSEnt->forceUnmapIOBase = FALSE; 7323 } 7324 pSiS->IOBase = NULL; 7325 } 7326#ifdef __alpha__ 7327 if(pSiSEnt->MapCountIOBaseDense) { 7328 pSiSEnt->MapCountIOBaseDense--; 7329 if((pSiSEnt->MapCountIOBaseDense == 0) || (pSiSEnt->forceUnmapIOBaseDense)) { 7330 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOBaseDense, (pSiS->mmioSize * 1024)); 7331 pSiSEnt->IOBaseDense = NULL; 7332 pSiSEnt->MapCountIOBaseDense = 0; 7333 pSiSEnt->forceUnmapIOBaseDense = FALSE; 7334 } 7335 pSiS->IOBaseDense = NULL; 7336 } 7337#endif /* __alpha__ */ 7338 if(pSiSEnt->MapCountFbBase) { 7339 pSiSEnt->MapCountFbBase--; 7340 if((pSiSEnt->MapCountFbBase == 0) || (pSiSEnt->forceUnmapFbBase)) { 7341 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->RealFbBase, pSiS->FbMapSize); 7342 pSiSEnt->FbBase = pSiSEnt->RealFbBase = NULL; 7343 pSiSEnt->MapCountFbBase = 0; 7344 pSiSEnt->forceUnmapFbBase = FALSE; 7345 7346 } 7347 pSiS->FbBase = pSiS->RealFbBase = NULL; 7348 } 7349 } else { 7350#endif 7351 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOBase, (pSiS->mmioSize * 1024)); 7352 pSiS->IOBase = NULL; 7353#ifdef __alpha__ 7354 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOBaseDense, (pSiS->mmioSize * 1024)); 7355 pSiS->IOBaseDense = NULL; 7356#endif 7357 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->RealFbBase, pSiS->FbMapSize); 7358 pSiS->FbBase = pSiS->RealFbBase = NULL; 7359#ifdef SISDUALHEAD 7360 } 7361#endif 7362 return TRUE; 7363} 7364 7365/* 7366 * This function saves the video state. 7367 */ 7368static void 7369SISSave(ScrnInfoPtr pScrn) 7370{ 7371 SISPtr pSiS = SISPTR(pScrn); 7372 SISRegPtr sisReg; 7373 int flags; 7374 7375#ifdef SISDUALHEAD 7376 /* We always save master & slave */ 7377 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 7378#endif 7379 7380 sisReg = &pSiS->SavedReg; 7381 7382 if( ((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) && 7383 ((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (SiSBridgeIsInSlaveMode(pScrn))) ) { 7384 SiSVGASave(pScrn, sisReg, SISVGA_SR_CMAP | SISVGA_SR_MODE); 7385#ifdef SIS_PC_PLATFORM 7386 if(pSiS->VGAMemBase) { 7387 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO+0x30); 7388 SiSSetLVDSetc(pSiS->SiS_Pr, 0); 7389 SiS_GetVBType(pSiS->SiS_Pr); 7390 SiS_DisableBridge(pSiS->SiS_Pr); 7391 SiSVGASave(pScrn, sisReg, SISVGA_SR_FONTS); 7392 SiS_EnableBridge(pSiS->SiS_Pr); 7393 } 7394#endif 7395 } else { 7396 flags = SISVGA_SR_CMAP | SISVGA_SR_MODE; 7397#ifdef SIS_PC_PLATFORM 7398 if(pSiS->VGAMemBase) flags |= SISVGA_SR_FONTS; 7399#endif 7400 SiSVGASave(pScrn, sisReg, flags); 7401 } 7402 7403 sisSaveUnlockExtRegisterLock(pSiS, &sisReg->sisRegs3C4[0x05], &sisReg->sisRegs3D4[0x80]); 7404 7405 (*pSiS->SiSSave)(pScrn, sisReg); 7406 7407 if(pSiS->UseVESA) SISVESASaveRestore(pScrn, MODE_SAVE); 7408 7409 /* "Save" these again as they may have been changed prior to SISSave() call */ 7410 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 7411 sisReg->sisRegs3C4[0x1f] = pSiS->oldSR1F; 7412 sisReg->sisRegs3D4[0x17] = pSiS->oldCR17; 7413 sisReg->sisRegs3D4[0x32] = pSiS->oldCR32; 7414 sisReg->sisRegs3D4[0x36] = pSiS->oldCR36; 7415 sisReg->sisRegs3D4[0x37] = pSiS->oldCR37; 7416 if(pSiS->VGAEngine == SIS_315_VGA) { 7417 sisReg->sisRegs3D4[pSiS->myCR63] = pSiS->oldCR63; 7418 } 7419 } 7420} 7421 7422/* VESASaveRestore taken from vesa driver */ 7423static void 7424SISVESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function) 7425{ 7426 SISPtr pSiS = SISPTR(pScrn); 7427 7428 /* Query amount of memory to save state */ 7429 if((function == MODE_QUERY) || 7430 (function == MODE_SAVE && pSiS->state == NULL)) { 7431 7432 /* Make sure we save at least this information in case of failure */ 7433 (void)VBEGetVBEMode(pSiS->pVbe, &pSiS->stateMode); 7434 SiSVGASaveFonts(pScrn); 7435 7436 if(pSiS->vesamajor > 1) { 7437 if(!VBESaveRestore(pSiS->pVbe, function, (pointer)&pSiS->state, 7438 &pSiS->stateSize, &pSiS->statePage)) { 7439 return; 7440 } 7441 } 7442 } 7443 7444 /* Save/Restore Super VGA state */ 7445 if(function != MODE_QUERY) { 7446 7447 if(pSiS->vesamajor > 1) { 7448 if(function == MODE_RESTORE) { 7449 memcpy(pSiS->state, pSiS->pstate, pSiS->stateSize); 7450 } 7451 7452 if(VBESaveRestore(pSiS->pVbe,function,(pointer)&pSiS->state, 7453 &pSiS->stateSize,&pSiS->statePage) && 7454 (function == MODE_SAVE)) { 7455 /* don't rely on the memory not being touched */ 7456 if(!pSiS->pstate) { 7457 pSiS->pstate = xalloc(pSiS->stateSize); 7458 } 7459 memcpy(pSiS->pstate, pSiS->state, pSiS->stateSize); 7460 } 7461 } 7462 7463 if(function == MODE_RESTORE) { 7464 VBESetVBEMode(pSiS->pVbe, pSiS->stateMode, NULL); 7465 SiSVGARestoreFonts(pScrn); 7466 } 7467 7468 } 7469} 7470 7471/* 7472 * Initialise a new mode. This is currently done using the 7473 * "initialise struct, restore/write struct to HW" model for 7474 * the old chipsets (5597/530/6326). For newer chipsets, 7475 * we use our own mode switching code. 7476 */ 7477 7478static Bool 7479SISModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 7480{ 7481 SISPtr pSiS = SISPTR(pScrn); 7482 SISRegPtr sisReg; 7483#ifdef SISDUALHEAD 7484 SISEntPtr pSiSEnt = NULL; 7485#endif 7486 7487 andSISIDXREG(SISCR,0x11,0x7f); /* Unlock CRTC registers */ 7488 7489 SISModifyModeInfo(mode); /* Quick check of the mode parameters */ 7490 7491 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7492 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO+0x30); 7493 } 7494 7495 if(pSiS->UseVESA) { /* With VESA: */ 7496 7497#ifdef SISDUALHEAD 7498 /* No dual head mode when using VESA */ 7499 if(pSiS->SecondHead) return TRUE; 7500#endif 7501 7502 pScrn->vtSema = TRUE; 7503 7504 /* 7505 * This order is required: 7506 * The video bridge needs to be adjusted before the 7507 * BIOS is run as the BIOS sets up CRT2 according to 7508 * these register settings. 7509 * After the BIOS is run, the bridges and turboqueue 7510 * registers need to be readjusted as the BIOS may 7511 * very probably have messed them up. 7512 */ 7513 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7514 SiSPreSetMode(pScrn, mode, SIS_MODE_SIMU); 7515 } 7516 if(!SiSSetVESAMode(pScrn, mode)) { 7517 SISErrorLog(pScrn, "SiSSetVESAMode() failed\n"); 7518 return FALSE; 7519 } 7520 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7521 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7522 SiSPreSetMode(pScrn, mode, SIS_MODE_SIMU); 7523 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7524 } 7525#ifdef TWDEBUG 7526 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 7527 "REAL REGISTER CONTENTS AFTER SETMODE:\n"); 7528#endif 7529 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7530 SISErrorLog(pScrn, "ModeInit() failed\n"); 7531 return FALSE; 7532 } 7533 7534 SiSVGAProtect(pScrn, TRUE); 7535 (*pSiS->SiSRestore)(pScrn, &pSiS->ModeReg); 7536 SiSVGAProtect(pScrn, FALSE); 7537 7538 } else { /* Without VESA: */ 7539 7540#ifdef SISDUALHEAD 7541 if(pSiS->DualHeadMode) { 7542 7543 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7544 SISErrorLog(pScrn, "ModeInit() failed\n"); 7545 return FALSE; 7546 } 7547 7548 pScrn->vtSema = TRUE; 7549 7550 pSiSEnt = pSiS->entityPrivate; 7551 7552 if(!(pSiS->SecondHead)) { 7553 /* Head 1 (master) is always CRT2 */ 7554 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT2); 7555 if(!SiSBIOSSetModeCRT2(pSiS->SiS_Pr, pScrn, mode, pSiS->IsCustom)) { 7556 SISErrorLog(pScrn, "SiSBIOSSetModeCRT2() failed\n"); 7557 return FALSE; 7558 } 7559 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7560 if(pSiSEnt->pScrn_2) { 7561 SISAdjustFrame(pSiSEnt->pScrn_2->scrnIndex, 7562 pSiSEnt->pScrn_2->frameX0, 7563 pSiSEnt->pScrn_2->frameY0, 0); 7564 } 7565 } else { 7566 /* Head 2 (slave) is always CRT1 */ 7567 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT1); 7568 if(!SiSBIOSSetModeCRT1(pSiS->SiS_Pr, pScrn, mode, pSiS->IsCustom)) { 7569 SISErrorLog(pScrn, "SiSBIOSSetModeCRT1() failed\n"); 7570 return FALSE; 7571 } 7572 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7573 if(pSiSEnt->pScrn_1) { 7574 SISAdjustFrame(pSiSEnt->pScrn_1->scrnIndex, 7575 pSiSEnt->pScrn_1->frameX0, 7576 pSiSEnt->pScrn_1->frameY0, 0); 7577 } 7578 } 7579 7580 } else { 7581#endif 7582 7583 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7584 7585 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7586 SISErrorLog(pScrn, "ModeInit() failed\n"); 7587 return FALSE; 7588 } 7589 7590 pScrn->vtSema = TRUE; 7591 7592#ifdef SISMERGED 7593 if(pSiS->MergedFB) { 7594 7595 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting MergedFB mode %dx%d\n", 7596 mode->HDisplay, mode->VDisplay); 7597 7598 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT1); 7599 7600 if(!SiSBIOSSetModeCRT1(pSiS->SiS_Pr, pScrn, 7601 ((SiSMergedDisplayModePtr)mode->Private)->CRT1, 7602 pSiS->IsCustom)) { 7603 SISErrorLog(pScrn, "SiSBIOSSetModeCRT1() failed\n"); 7604 return FALSE; 7605 } 7606 7607 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT2); 7608 7609 if(!SiSBIOSSetModeCRT2(pSiS->SiS_Pr, pScrn, 7610 ((SiSMergedDisplayModePtr)mode->Private)->CRT2, 7611 pSiS->IsCustom)) { 7612 SISErrorLog(pScrn, "SiSBIOSSetModeCRT2() failed\n"); 7613 return FALSE; 7614 } 7615 7616 } else { 7617#endif 7618 7619 if((pSiS->VBFlags & CRT1_LCDA) || (!(mode->type & M_T_DEFAULT))) { 7620 7621 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT1); 7622 7623 if(!SiSBIOSSetModeCRT1(pSiS->SiS_Pr, pScrn, 7624 mode, pSiS->IsCustom)) { 7625 SISErrorLog(pScrn, "SiSBIOSSetModeCRT1() failed\n"); 7626 return FALSE; 7627 } 7628 7629 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT2); 7630 7631 if(!SiSBIOSSetModeCRT2(pSiS->SiS_Pr, pScrn, 7632 mode, pSiS->IsCustom)) { 7633 SISErrorLog(pScrn, "SiSBIOSSetModeCRT2() failed\n"); 7634 return FALSE; 7635 } 7636 7637 } else { 7638 7639 SiSPreSetMode(pScrn, mode, SIS_MODE_SIMU); 7640 7641 if(!SiSBIOSSetMode(pSiS->SiS_Pr, pScrn, 7642 mode, pSiS->IsCustom)) { 7643 SISErrorLog(pScrn, "SiSBIOSSetMode() failed\n"); 7644 return FALSE; 7645 } 7646 7647 } 7648 7649#ifdef SISMERGED 7650 } 7651#endif 7652 7653 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7654 7655#ifdef TWDEBUG 7656 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VBFlags %lx\n", pSiS->VBFlags); 7657 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 7658 "REAL REGISTER CONTENTS AFTER SETMODE:\n"); 7659 (*pSiS->ModeInit)(pScrn, mode); 7660#endif 7661 7662 } else { 7663 7664 /* For other chipsets, use the old method */ 7665 7666 /* Prepare the register contents */ 7667 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7668 SISErrorLog(pScrn, "ModeInit() failed\n"); 7669 return FALSE; 7670 } 7671 7672 pScrn->vtSema = TRUE; 7673 7674 /* Program the registers */ 7675 SiSVGAProtect(pScrn, TRUE); 7676 sisReg = &pSiS->ModeReg; 7677 7678 sisReg->sisRegsATTR[0x10] = 0x01; 7679 if(pScrn->bitsPerPixel > 8) { 7680 sisReg->sisRegsGR[0x05] = 0x00; 7681 } 7682 7683 SiSVGARestore(pScrn, sisReg, SISVGA_SR_MODE); 7684 7685 (*pSiS->SiSRestore)(pScrn, sisReg); 7686 7687 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 7688 SiS6326PostSetMode(pScrn, &pSiS->ModeReg); 7689 } 7690 7691#ifdef TWDEBUG 7692 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 7693 "REAL REGISTER CONTENTS AFTER SETMODE:\n"); 7694 (*pSiS->ModeInit)(pScrn, mode); 7695#endif 7696 7697 SiSVGAProtect(pScrn, FALSE); 7698 7699 } 7700 7701#ifdef SISDUALHEAD 7702 } 7703#endif 7704 } 7705 7706 /* Update Currentlayout */ 7707 pSiS->CurrentLayout.mode = pSiS->currentModeLast = mode; 7708 7709 return TRUE; 7710} 7711 7712static Bool 7713SiSSetVESAMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) 7714{ 7715 SISPtr pSiS; 7716 int mode; 7717 7718 pSiS = SISPTR(pScrn); 7719 7720 if(!(mode = SiSCalcVESAModeIndex(pScrn, pMode))) return FALSE; 7721 7722 mode |= (1 << 15); /* Don't clear framebuffer */ 7723 mode |= (1 << 14); /* Use linear adressing */ 7724 7725 if(VBESetVBEMode(pSiS->pVbe, mode, NULL) == FALSE) { 7726 SISErrorLog(pScrn, "Setting VESA mode 0x%x failed\n", 7727 mode & 0x0fff); 7728 return (FALSE); 7729 } 7730 7731 if(pMode->HDisplay != pScrn->virtualX) { 7732 VBESetLogicalScanline(pSiS->pVbe, pScrn->virtualX); 7733 } 7734 7735 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 7736 "Setting VESA mode 0x%x succeeded\n", 7737 mode & 0x0fff); 7738 7739 return (TRUE); 7740} 7741 7742static void 7743SISSpecialRestore(ScrnInfoPtr pScrn) 7744{ 7745 SISPtr pSiS = SISPTR(pScrn); 7746 SISRegPtr sisReg = &pSiS->SavedReg; 7747 UChar temp; 7748 int i; 7749 7750 /* 1.11.04 and later for 651 and 301B(DH) do strange register 7751 * fiddling after the usual mode change. This happens 7752 * depending on the result of a call of int 2f (with 7753 * ax=0x1680) and if modeno <= 0x13. I have no idea if 7754 * that is specific for the 651 or that very machine. 7755 * So this perhaps requires some more checks in the beginning 7756 * (although it should not do any harm on other chipsets/bridges 7757 * etc.) However, even if I call the VBE to restore mode 0x03, 7758 * these registers don't get restored correctly, possibly 7759 * because that int-2f-call for some reason results non-zero. So 7760 * what I do here is to restore these few registers 7761 * manually. 7762 */ 7763 7764 if(!(pSiS->ChipFlags & SiSCF_Is65x)) return; 7765 inSISIDXREG(SISCR, 0x34, temp); 7766 temp &= 0x7f; 7767 if(temp > 0x13) return; 7768 7769#ifdef UNLOCK_ALWAYS 7770 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7771#endif 7772 7773 SiS_UnLockCRT2(pSiS->SiS_Pr); 7774 7775 outSISIDXREG(SISCAP, 0x3f, sisReg->sisCapt[0x3f]); 7776 outSISIDXREG(SISCAP, 0x00, sisReg->sisCapt[0x00]); 7777 for(i = 0; i < 0x4f; i++) { 7778 outSISIDXREG(SISCAP, i, sisReg->sisCapt[i]); 7779 } 7780 outSISIDXREG(SISVID, 0x32, (sisReg->sisVid[0x32] & ~0x05)); 7781 outSISIDXREG(SISVID, 0x30, sisReg->sisVid[0x30]); 7782 outSISIDXREG(SISVID, 0x32, ((sisReg->sisVid[0x32] & ~0x04) | 0x01)); 7783 outSISIDXREG(SISVID, 0x30, sisReg->sisVid[0x30]); 7784 7785 if(!(pSiS->ChipFlags & SiSCF_Is651)) return; 7786 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 7787 7788 inSISIDXREG(SISCR, 0x30, temp); 7789 if(temp & 0x40) { 7790 UChar myregs[] = { 7791 0x2f, 0x08, 0x09, 0x03, 0x0a, 0x0c, 7792 0x0b, 0x0d, 0x0e, 0x12, 0x0f, 0x10, 7793 0x11, 0x04, 0x05, 0x06, 0x07, 0x00, 7794 0x2e 7795 }; 7796 for(i = 0; i <= 18; i++) { 7797 outSISIDXREG(SISPART1, myregs[i], sisReg->VBPart1[myregs[i]]); 7798 } 7799 } else if((temp & 0x20) || (temp & 0x9c)) { 7800 UChar myregs[] = { 7801 0x04, 0x05, 0x06, 0x07, 0x00, 0x2e 7802 }; 7803 for(i = 0; i <= 5; i++) { 7804 outSISIDXREG(SISPART1, myregs[i], sisReg->VBPart1[myregs[i]]); 7805 } 7806 } 7807} 7808 7809/* Fix SR11 for 661 and later */ 7810static void 7811SiSFixupSR11(ScrnInfoPtr pScrn) 7812{ 7813 SISPtr pSiS = SISPTR(pScrn); 7814 CARD8 tmpreg; 7815 7816#ifdef UNLOCK_ALWAYS 7817 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7818#endif 7819 7820 if(pSiS->ChipType >= SIS_661) { 7821 inSISIDXREG(SISSR,0x11,tmpreg); 7822 if(tmpreg & 0x20) { 7823 inSISIDXREG(SISSR,0x3e,tmpreg); 7824 tmpreg = (tmpreg + 1) & 0xff; 7825 outSISIDXREG(SISSR,0x3e,tmpreg); 7826 } 7827 7828 inSISIDXREG(SISSR,0x11,tmpreg); 7829 if(tmpreg & 0xf0) { 7830 andSISIDXREG(SISSR,0x11,0x0f); 7831 } 7832 } 7833} 7834 7835/* Subroutine for restoring sisfb's TV parameters (used by SiSRestore()) */ 7836 7837static void 7838SiSRestore_SiSFB_TVParms(ScrnInfoPtr pScrn) 7839{ 7840 SISPtr pSiS = SISPTR(pScrn); 7841 int fd; 7842 CARD32 parm; 7843 7844 if(!pSiS->sisfbfound) return; 7845 if(!pSiS->sisfb_tvposvalid) return; 7846 if(!(pSiS->sisfbdevname[0])) return; 7847 7848 if((fd = open(pSiS->sisfbdevname, O_RDONLY)) != -1) { 7849 parm = (CARD32)((pSiS->sisfb_tvxpos << 16) | (pSiS->sisfb_tvypos & 0xffff)); 7850 ioctl(fd, SISFB_SET_TVPOSOFFSET, &parm); 7851 close(fd); 7852 } 7853} 7854 7855/* 7856 * Restore the initial mode. To be used internally only! 7857 */ 7858static void 7859SISRestore(ScrnInfoPtr pScrn) 7860{ 7861 SISPtr pSiS = SISPTR(pScrn); 7862 SISRegPtr sisReg = &pSiS->SavedReg; 7863 Bool doit = FALSE, doitlater = FALSE; 7864 Bool vesasuccess = FALSE; 7865 int flags; 7866 7867 /* WARNING: Don't ever touch this. It now seems to work on 7868 * all chipset/bridge combinations - but finding out the 7869 * correct combination was pure hell. 7870 */ 7871 7872 /* Wait for the accelerators */ 7873 (*pSiS->SyncAccel)(pScrn); 7874 7875 /* Set up restore flags */ 7876 flags = SISVGA_SR_MODE | SISVGA_SR_CMAP; 7877#ifdef SIS_PC_PLATFORM 7878 /* We now restore ALL to overcome the vga=extended problem */ 7879 if(pSiS->VGAMemBase) flags |= SISVGA_SR_FONTS; 7880#endif 7881 7882 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 7883 7884#ifdef SISDUALHEAD 7885 /* We always restore master AND slave */ 7886 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 7887#endif 7888 7889#ifdef UNLOCK_ALWAYS 7890 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7891#endif 7892 7893 /* We must not disable the sequencer if the bridge is in SlaveMode! */ 7894 if(!(SiSBridgeIsInSlaveMode(pScrn))) { 7895 SiSVGAProtect(pScrn, TRUE); 7896 } 7897 7898 /* First, restore CRT1 on/off and VB connection registers */ 7899 outSISIDXREG(SISCR, 0x32, pSiS->oldCR32); 7900 if(!(pSiS->oldCR17 & 0x80)) { /* CRT1 was off */ 7901 if(!(SiSBridgeIsInSlaveMode(pScrn))) { /* Bridge is NOT in SlaveMode now -> do it */ 7902 doit = TRUE; 7903 } else { 7904 doitlater = TRUE; 7905 } 7906 } else { /* CRT1 was on -> do it now */ 7907 doit = TRUE; 7908 } 7909 7910 if(doit) { 7911 outSISIDXREG(SISCR, 0x17, pSiS->oldCR17); 7912 } 7913 if(pSiS->VGAEngine == SIS_315_VGA) { 7914 outSISIDXREG(SISCR, pSiS->myCR63, pSiS->oldCR63); 7915 } 7916 7917 outSISIDXREG(SISSR, 0x1f, pSiS->oldSR1F); 7918 7919 /* For 30xB/LV, restoring the registers does not 7920 * work. We "manually" set the old mode, instead. 7921 * The same applies for SiS730 machines with LVDS. 7922 * Finally, this behavior can be forced by setting 7923 * the option RestoreBySetMode. 7924 */ 7925 if( ( (pSiS->restorebyset) || 7926 (pSiS->VBFlags2 & VB2_30xBLV) || 7927 ((pSiS->ChipType == SIS_730) && (pSiS->VBFlags2 & VB2_LVDS)) ) && 7928 (pSiS->OldMode) ) { 7929 7930 Bool changedmode = FALSE; 7931 7932 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 7933 "Restoring by setting old mode 0x%02x\n", pSiS->OldMode); 7934 7935 if(((pSiS->OldMode <= 0x13) || (!pSiS->sisfbfound)) && (pSiS->pVbe)) { 7936 int vmode = SiSTranslateToVESA(pScrn, pSiS->OldMode); 7937 if(vmode > 0) { 7938 if(vmode > 0x13) vmode |= ((1 << 15) | (1 << 14)); 7939 if(VBESetVBEMode(pSiS->pVbe, vmode, NULL) == TRUE) { 7940 SISSpecialRestore(pScrn); 7941 SiS_GetSetModeID(pScrn,pSiS->OldMode); 7942 vesasuccess = TRUE; 7943 } else { 7944 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 7945 "VBE failed to restore mode 0x%x\n", pSiS->OldMode); 7946 } 7947 } else { 7948 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 7949 "Can't identify VESA mode number for mode 0x%x\n", pSiS->OldMode); 7950 } 7951 } 7952 7953 if(vesasuccess == FALSE) { 7954 7955 int backupscaler = pSiS->SiS_Pr->UsePanelScaler; 7956 int backupcenter = pSiS->SiS_Pr->CenterScreen; 7957 ULong backupspecialtiming = pSiS->SiS_Pr->SiS_CustomT; 7958 int mymode = pSiS->OldMode; 7959 7960 if((pSiS->VGAEngine == SIS_315_VGA) && 7961 ((pSiS->ROM661New) || (pSiS->ChipFlags & SiSCF_IsXGI)) && 7962 (!pSiS->sisfbfound)) { 7963 /* New SiS BIOS or XGI BIOS has set mode, therefore eventually translate number */ 7964 mymode = SiSTranslateToOldMode(mymode); 7965 } 7966 7967 if((pSiS->VBFlags2 & VB2_30xBLV)) { 7968 /* !!! REQUIRED for 630+301B-DH, otherwise the text modes 7969 * will not be restored correctly !!! 7970 * !!! Do this ONLY for LCD; VGA2 will not be restored 7971 * correctly otherwise. 7972 */ 7973 UChar temp; 7974 inSISIDXREG(SISCR, 0x30, temp); 7975 if(temp & 0x20) { 7976 if(mymode == 0x03) { 7977 mymode = 0x13; 7978 changedmode = TRUE; 7979 } 7980 } 7981 } 7982 7983 pSiS->SiS_Pr->UseCustomMode = FALSE; 7984 pSiS->SiS_Pr->CRT1UsesCustomMode = FALSE; 7985 pSiS->SiS_Pr->CenterScreen = 0; 7986 if(pSiS->sisfbfound) { 7987 pSiS->SiS_Pr->UsePanelScaler = pSiS->sisfbscalelcd; 7988 pSiS->SiS_Pr->SiS_CustomT = pSiS->sisfbspecialtiming; 7989 } else { 7990 pSiS->SiS_Pr->UsePanelScaler = -1; 7991 /* Leave CustomT as it is */ 7992 } 7993 SiS_SetEnableDstn(pSiS->SiS_Pr, FALSE); 7994 SiS_SetEnableFstn(pSiS->SiS_Pr, FALSE); 7995 if((pSiS->ChipType == SIS_550) && (pSiS->sisfbfound)) { 7996 if(pSiS->sisfbxSTN) { 7997 SiS_SetEnableDstn(pSiS->SiS_Pr, pSiS->sisfbDSTN); 7998 SiS_SetEnableFstn(pSiS->SiS_Pr, pSiS->sisfbFSTN); 7999 } else if(mymode == 0x5a || mymode == 0x5b) { 8000 SiS_SetEnableFstn(pSiS->SiS_Pr, TRUE); 8001 } 8002 } 8003 SiSSetMode(pSiS->SiS_Pr, pScrn, mymode, FALSE); 8004 if(changedmode) { 8005 outSISIDXREG(SISCR,0x34,0x03); 8006 } 8007 SISSpecialRestore(pScrn); 8008 SiS_GetSetModeID(pScrn, pSiS->OldMode); /* NOT mymode! */ 8009 pSiS->SiS_Pr->UsePanelScaler = backupscaler; 8010 pSiS->SiS_Pr->CenterScreen = backupcenter; 8011 pSiS->SiS_Pr->SiS_CustomT = backupspecialtiming; 8012 SiS_SiSFB_Lock(pScrn, FALSE); 8013 SiSRestore_SiSFB_TVParms(pScrn); 8014 SiS_SiSFB_Lock(pScrn, TRUE); 8015 8016 } 8017 8018 /* Restore CRT1 status */ 8019 if(pSiS->VGAEngine == SIS_315_VGA) { 8020 outSISIDXREG(SISCR, pSiS->myCR63, pSiS->oldCR63); 8021 } 8022 outSISIDXREG(SISSR, 0x1f, pSiS->oldSR1F); 8023 8024#ifdef SISVRAMQ 8025 /* Restore queue mode registers on 315/330/340 series */ 8026 /* (This became necessary due to the switch to VRAM queue) */ 8027 SiSRestoreQueueMode(pSiS, sisReg); 8028#endif 8029 8030 } else { 8031 8032 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 8033 /* If a video bridge is present, we need to restore 8034 * non-extended (=standard VGA) SR and CR registers 8035 * before restoring the extended ones and the bridge 8036 * registers. 8037 */ 8038 if(!(SiSBridgeIsInSlaveMode(pScrn))) { 8039 SiSVGAProtect(pScrn, TRUE); 8040 SiSVGARestore(pScrn, sisReg, SISVGA_SR_MODE); 8041 } 8042 } 8043 8044 (*pSiS->SiSRestore)(pScrn, sisReg); 8045 8046 } 8047 8048 if(doitlater) { 8049 outSISIDXREG(SISCR, 0x17, pSiS->oldCR17); 8050 } 8051 8052 8053 8054 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (SiSBridgeIsInSlaveMode(pScrn))) { 8055 8056 /* IMPORTANT: The 30xLV does not handle well being disabled if in 8057 * LCDA mode! In LCDA mode, the bridge is NOT in slave mode, 8058 * so this is the only safe way: Disable the bridge ONLY if 8059 * in Slave Mode, and don't bother if not. 8060 */ 8061 8062 if(flags & SISVGA_SR_FONTS) { 8063 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO+0x30); 8064 SiSSetLVDSetc(pSiS->SiS_Pr, 0); 8065 SiS_GetVBType(pSiS->SiS_Pr); 8066 SiS_DisableBridge(pSiS->SiS_Pr); 8067 SiSVGAProtect(pScrn, TRUE); 8068 } 8069 8070 SiSVGARestore(pScrn, sisReg, flags); 8071 8072 if(flags & SISVGA_SR_FONTS) { 8073 SiSVGAProtect(pScrn, FALSE); 8074 SiS_EnableBridge(pSiS->SiS_Pr); 8075 andSISIDXREG(SISSR, 0x01, ~0x20); /* Display on */ 8076 } 8077 8078 } else { 8079 8080 SiSVGAProtect(pScrn, TRUE); 8081 SiSVGARestore(pScrn, sisReg, flags); 8082 SiSVGAProtect(pScrn, FALSE); 8083 8084 } 8085 8086 SiSFixupSR11(pScrn); 8087 8088#ifdef TWDEBUG 8089 { 8090 SISRegPtr pReg = &pSiS->ModeReg; 8091 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8092 "REAL REGISTER CONTENTS AFTER RESTORE BY SETMODE:\n"); 8093 (*pSiS->SiSSave)(pScrn, pReg); 8094 } 8095#endif 8096 8097 sisRestoreExtRegisterLock(pSiS,sisReg->sisRegs3C4[0x05],sisReg->sisRegs3D4[0x80]); 8098 8099 } else { /* All other chipsets */ 8100 8101 SiSVGAProtect(pScrn, TRUE); 8102 8103#ifdef UNLOCK_ALWAYS 8104 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8105#endif 8106 8107 (*pSiS->SiSRestore)(pScrn, sisReg); 8108 8109 SiSVGAProtect(pScrn, TRUE); 8110 8111 SiSVGARestore(pScrn, sisReg, flags); 8112 8113 /* Restore TV. This is rather complicated, but if we don't do it, 8114 * TV output will flicker terribly 8115 */ 8116 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 8117 if(sisReg->sis6326tv[0] & 0x04) { 8118 UChar tmp; 8119 int val; 8120 8121 orSISIDXREG(SISSR, 0x01, 0x20); 8122 tmp = SiS6326GetTVReg(pScrn,0x00); 8123 tmp &= ~0x04; 8124 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 8125 SiS6326SetTVReg(pScrn,0x00,tmp); 8126 for(val=0; val < 2; val++) { 8127 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 8128 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 8129 } 8130 SiS6326SetTVReg(pScrn, 0x00, sisReg->sis6326tv[0]); 8131 tmp = inSISREG(SISINPSTAT); 8132 outSISREG(SISAR, 0x20); 8133 tmp = inSISREG(SISINPSTAT); 8134 while(inSISREG(SISINPSTAT) & 0x01); 8135 while(!(inSISREG(SISINPSTAT) & 0x01)); 8136 andSISIDXREG(SISSR, 0x01, ~0x20); 8137 for(val=0; val < 10; val++) { 8138 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 8139 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 8140 } 8141 andSISIDXREG(SISSR, 0x01, ~0x20); 8142 } 8143 } 8144 8145 sisRestoreExtRegisterLock(pSiS,sisReg->sisRegs3C4[5],sisReg->sisRegs3D4[0x80]); 8146 8147 SiSVGAProtect(pScrn, FALSE); 8148 } 8149} 8150 8151static void 8152SISVESARestore(ScrnInfoPtr pScrn) 8153{ 8154 SISPtr pSiS = SISPTR(pScrn); 8155#ifdef SISVRAMQ 8156 SISRegPtr sisReg = &pSiS->SavedReg; 8157#endif 8158 8159 if(pSiS->UseVESA) { 8160 SISVESASaveRestore(pScrn, MODE_RESTORE); 8161#ifdef SISVRAMQ 8162 /* Restore queue mode registers on 315/330/340 series */ 8163 /* (This became necessary due to the switch to VRAM queue) */ 8164 SiSRestoreQueueMode(pSiS, sisReg); 8165#endif 8166 } 8167} 8168 8169/* Restore bridge config registers - to be called BEFORE VESARestore */ 8170static void 8171SISBridgeRestore(ScrnInfoPtr pScrn) 8172{ 8173 SISPtr pSiS = SISPTR(pScrn); 8174 8175#ifdef SISDUALHEAD 8176 /* We only restore for master head */ 8177 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 8178#endif 8179 8180 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 8181 SiSRestoreBridge(pScrn, &pSiS->SavedReg); 8182 } 8183} 8184 8185/* Our BlockHandler */ 8186static void 8187SISBlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask) 8188{ 8189 ScreenPtr pScreen = screenInfo.screens[i]; 8190 ScrnInfoPtr pScrn = xf86Screens[i]; 8191 SISPtr pSiS = SISPTR(pScrn); 8192 8193 pScreen->BlockHandler = pSiS->BlockHandler; 8194 (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); 8195 pScreen->BlockHandler = SISBlockHandler; 8196 8197#ifdef SISDUALHEAD 8198 if(pSiS->NeedCopyFastVidCpy) { 8199 SISEntPtr pSiSEnt = pSiS->entityPrivate; 8200 if(pSiSEnt->HaveFastVidCpy) { 8201 pSiS->NeedCopyFastVidCpy = FALSE; 8202 pSiS->SiSFastVidCopy = pSiSEnt->SiSFastVidCopy; 8203 pSiS->SiSFastMemCopy = pSiSEnt->SiSFastMemCopy; 8204 pSiS->SiSFastVidCopyFrom = pSiSEnt->SiSFastVidCopyFrom; 8205 pSiS->SiSFastMemCopyFrom = pSiSEnt->SiSFastMemCopyFrom; 8206 } 8207 } 8208#endif 8209 8210 if(pSiS->VideoTimerCallback) { 8211 (*pSiS->VideoTimerCallback)(pScrn, currentTime.milliseconds); 8212 } 8213 8214#ifdef SIS_USE_XAA 8215 if(pSiS->RenderCallback) { 8216 (*pSiS->RenderCallback)(pScrn); 8217 } 8218#endif 8219#ifdef SIS_USE_EXA 8220 if(pSiS->ExaRenderCallback) { 8221 (*pSiS->ExaRenderCallback)(pScrn); 8222 } 8223#endif 8224} 8225 8226 8227 8228/* Do screen blanking; DPMS handling 8229 * 8230 * Mandatory; latter optional 8231 */ 8232 8233static void 8234SiSHandleBackLight(SISPtr pSiS, Bool blon) 8235{ 8236 UChar sr11mask = (pSiS->SiS_Pr->SiS_SensibleSR11) ? 0x03 : 0xf3; 8237 8238 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) { 8239 8240 if(!blon) { 8241 SiS_SiS30xBLOff(pSiS->SiS_Pr); 8242 } else { 8243 SiS_SiS30xBLOn(pSiS->SiS_Pr); 8244 } 8245 8246 } else if( ((pSiS->VGAEngine == SIS_300_VGA) && 8247 (pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH))) || 8248 ((pSiS->VGAEngine == SIS_315_VGA) && 8249 ((pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS)) ) { 8250 8251 if(!blon) { 8252 setSISIDXREG(SISSR, 0x11, sr11mask, 0x08); 8253 } else { 8254 setSISIDXREG(SISSR, 0x11, sr11mask, 0x00); 8255 } 8256 8257 } else if((pSiS->VGAEngine == SIS_315_VGA) && 8258 (pSiS->VBFlags2 & VB2_CHRONTEL)) { 8259 8260 if(!blon) { 8261 SiS_Chrontel701xBLOff(pSiS->SiS_Pr); 8262 } else { 8263 SiS_Chrontel701xBLOn(pSiS->SiS_Pr); 8264 } 8265 8266 } 8267} 8268 8269static Bool 8270SISSaveScreen(ScreenPtr pScreen, int mode) 8271{ 8272 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 8273 SISPtr pSiS; 8274 Bool IsUnblank = xf86IsUnblank(mode) ? TRUE : FALSE; 8275 8276 if((pScrn == NULL) || (!pScrn->vtSema)) return TRUE; 8277 8278 pSiS = SISPTR(pScrn); 8279 8280#ifdef UNLOCK_ALWAYS 8281 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8282#endif 8283 8284 if(pSiS->VBFlags & (CRT2_LCD | CRT1_LCDA)) { 8285 SiSHandleBackLight(pSiS, IsUnblank); 8286 } 8287 8288 if(!SiSBridgeIsInSlaveMode(pScrn)) { 8289 return SiSVGASaveScreen(pScreen, mode); 8290 } 8291 8292 return TRUE; 8293} 8294 8295#ifdef SISDUALHEAD 8296/* SaveScreen for dual head mode */ 8297static Bool 8298SISSaveScreenDH(ScreenPtr pScreen, int mode) 8299{ 8300 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 8301 SISPtr pSiS; 8302 Bool IsUnblank = xf86IsUnblank(mode) ? TRUE : FALSE; 8303 8304 if((pScrn == NULL) || (!pScrn->vtSema)) return TRUE; 8305 8306 pSiS = SISPTR(pScrn); 8307 8308 if( (pSiS->SecondHead) && 8309 ((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) ) { 8310 8311 /* Slave head is always CRT1 */ 8312 /* (No backlight handling on TMDS bridges) */ 8313 return SiSVGASaveScreen(pScreen, mode); 8314 8315 } else { 8316 8317 /* Master head is always CRT2 */ 8318 /* But we land here for LCDA, too (if bridge is SiS LVDS type) */ 8319 8320 /* We can only blank LCD, not other CRT2 devices */ 8321 if(pSiS->VBFlags & (CRT2_LCD|CRT1_LCDA)) { 8322 8323#ifdef UNLOCK_ALWAYS 8324 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8325#endif 8326 SiSHandleBackLight(pSiS, IsUnblank); 8327 8328 } 8329 8330 } 8331 return TRUE; 8332} 8333#endif 8334 8335static void 8336SISDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags) 8337{ 8338 SISPtr pSiS = SISPTR(pScrn); 8339 Bool docrt1 = TRUE, docrt2 = TRUE, backlight = TRUE; 8340 UChar sr1=0, cr17=0, cr63=0, pmreg=0, sr7=0; 8341 UChar p1_13=0, p2_0=0, oldpmreg=0; 8342 8343 if(!pScrn->vtSema) return; 8344 8345 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, 8346 "SISDisplayPowerManagementSet(%d)\n", PowerManagementMode); 8347 8348#ifdef SISDUALHEAD 8349 if(pSiS->DualHeadMode) { 8350 if(pSiS->SecondHead) docrt2 = FALSE; 8351 else docrt1 = FALSE; 8352 } 8353#endif 8354 8355 /* FIXME: in old servers, DPMSSet was supposed to be called without open 8356 * the correct PCI bridges before access the hardware. Now we have this 8357 * hook wrapped by the vga arbiter which should do all the work, in 8358 * kernels that implement it. For this case we might not want this hack 8359 * bellow. 8360 */ 8361 outSISIDXREG(SISSR,0x05,0x86); 8362 inSISIDXREG(SISSR,0x05,pmreg); 8363 if(pmreg != 0xa1) return; 8364 8365#ifdef UNLOCK_ALWAYS 8366 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8367#endif 8368 8369 switch(PowerManagementMode) { 8370 8371 case DPMSModeOn: /* HSync: On, VSync: On */ 8372 sr1 = 0x00; 8373 cr17 = 0x80; 8374 pmreg = 0x00; 8375 cr63 = 0x00; 8376 sr7 = 0x10; 8377 p2_0 = 0x20; 8378 p1_13 = 0x00; 8379 backlight = TRUE; 8380 break; 8381 8382 case DPMSModeSuspend: /* HSync: On, VSync: Off */ 8383 sr1 = 0x20; 8384 cr17 = 0x80; 8385 pmreg = 0x80; 8386 cr63 = 0x40; 8387 sr7 = 0x00; 8388 p2_0 = 0x40; 8389 p1_13 = 0x80; 8390 backlight = FALSE; 8391 break; 8392 8393 case DPMSModeStandby: /* HSync: Off, VSync: On */ 8394 sr1 = 0x20; 8395 cr17 = 0x80; 8396 pmreg = 0x40; 8397 cr63 = 0x40; 8398 sr7 = 0x00; 8399 p2_0 = 0x80; 8400 p1_13 = 0x40; 8401 backlight = FALSE; 8402 break; 8403 8404 case DPMSModeOff: /* HSync: Off, VSync: Off */ 8405 sr1 = 0x20; 8406 cr17 = 0x00; 8407 pmreg = 0xc0; 8408 cr63 = 0x40; 8409 sr7 = 0x00; 8410 p2_0 = 0xc0; 8411 p1_13 = 0xc0; 8412 backlight = FALSE; 8413 break; 8414 8415 default: 8416 return; 8417 } 8418 8419 oldpmreg = pmreg; 8420 8421 if((docrt2 && (pSiS->VBFlags & CRT2_LCD)) || 8422 (docrt1 && (pSiS->VBFlags & CRT1_LCDA))) { 8423 SiSHandleBackLight(pSiS, backlight); 8424 } 8425 8426 if(docrt1) { 8427 switch(pSiS->VGAEngine) { 8428 case SIS_OLD_VGA: 8429 case SIS_530_VGA: 8430 setSISIDXREG(SISSR, 0x01, ~0x20, sr1); /* Set/Clear "Display On" bit */ 8431 inSISIDXREG(SISSR, 0x11, oldpmreg); 8432 setSISIDXREG(SISCR, 0x17, 0x7f, cr17); 8433 setSISIDXREG(SISSR, 0x11, 0x3f, pmreg); 8434 break; 8435 case SIS_315_VGA: 8436 if( (!pSiS->CRT1off) && 8437 ((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) ) { 8438 setSISIDXREG(SISCR, pSiS->myCR63, 0xbf, cr63); 8439 setSISIDXREG(SISSR, 0x07, 0xef, sr7); 8440 } 8441 /* fall through */ 8442 default: 8443 if(!SiSBridgeIsInSlaveMode(pScrn)) { 8444 setSISIDXREG(SISSR, 0x01, ~0x20, sr1); /* Set/Clear "Display On" bit */ 8445 } 8446 if((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 8447 inSISIDXREG(SISSR, 0x1f, oldpmreg); 8448 if((!pSiS->CRT1off) && (!SiSBridgeIsInSlaveMode(pScrn))) { 8449 setSISIDXREG(SISSR, 0x1f, 0x3f, pmreg); 8450 } 8451 } 8452 } 8453 oldpmreg &= 0xc0; 8454 } 8455 8456 if(docrt2) { 8457 if(pSiS->VBFlags & CRT2_LCD) { 8458 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && 8459 (!(pSiS->VBFlags2 & VB2_30xBDH))) { 8460 if(pSiS->VGAEngine == SIS_300_VGA) { 8461 SiS_UnLockCRT2(pSiS->SiS_Pr); 8462 setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13); 8463 } 8464 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) p2_0 |= 0x20; 8465 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); 8466 } 8467 } else if(pSiS->VBFlags & (CRT2_VGA | CRT2_TV)) { 8468 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 8469 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); 8470 } 8471 } 8472 } 8473 8474 if( (docrt1) && 8475 (pmreg != oldpmreg) && 8476 ((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) ) { 8477 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 8478 usleep(10000); 8479 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 8480 } 8481 8482} 8483 8484/* Mandatory 8485 * This gets called at the start of each server generation 8486 * 8487 * We use pScrn and not CurrentLayout here, because the 8488 * properties we use have not changed (displayWidth, 8489 * depth, bitsPerPixel) 8490 */ 8491static Bool 8492SISScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) 8493{ 8494 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 8495 SISPtr pSiS = SISPTR(pScrn); 8496 VisualPtr visual; 8497 ULong OnScreenSize; 8498 int ret, height, width, displayWidth; 8499 UChar *FBStart; 8500#ifdef SISDUALHEAD 8501 SISEntPtr pSiSEnt = NULL; 8502#endif 8503 8504#ifdef SISDUALHEAD 8505 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) { 8506#endif 8507 SiS_LoadInitVBE(pScrn); 8508#ifdef SISDUALHEAD 8509 } 8510#endif 8511 8512#ifdef SISDUALHEAD 8513 if(pSiS->DualHeadMode) { 8514 pSiSEnt = pSiS->entityPrivate; 8515 pSiSEnt->refCount++; 8516 } 8517#endif 8518 8519#ifdef SIS_PC_PLATFORM 8520 /* Map 64k VGA window for saving/restoring CGA fonts */ 8521 SiS_MapVGAMem(pScrn); 8522#endif 8523 8524 /* Map the SiS memory and MMIO areas */ 8525 if(!SISMapMem(pScrn)) { 8526 SISErrorLog(pScrn, "SiSMapMem() failed\n"); 8527 return FALSE; 8528 } 8529 8530 SiS_SiSFB_Lock(pScrn, TRUE); 8531 8532#ifdef UNLOCK_ALWAYS 8533 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8534#endif 8535 8536 /* Enable TurboQueue so that SISSave() saves it in enabled 8537 * state. If we don't do this, X will hang after a restart! 8538 * (Happens for some unknown reason only when using VESA 8539 * for mode switching; assumingly a BIOS issue.) 8540 * This is done on 300 and 315 series only. 8541 */ 8542 if(pSiS->UseVESA) { 8543#ifdef SISVRAMQ 8544 if(pSiS->VGAEngine != SIS_315_VGA) 8545#endif 8546 SiSEnableTurboQueue(pScrn); 8547 } 8548 8549 /* Save the current state */ 8550 SISSave(pScrn); 8551 8552 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 8553 8554 if(!pSiS->OldMode) { 8555 8556 /* Try to find out current (=old) mode number 8557 * (Do this only if not sisfb has told us its mode yet) 8558 */ 8559 8560 /* Read 0:449 which the BIOS sets to the current mode number 8561 * Unfortunately, this not reliable since the int10 emulation 8562 * does not change this. So if we call the VBE later, this 8563 * byte won't be touched (which is why we set this manually 8564 * then). 8565 */ 8566 UChar myoldmode = SiS_GetSetModeID(pScrn, 0xFF); 8567 UChar cr30, cr31; 8568 8569 /* Read CR34 which the BIOS sets to the current mode number for CRT2 8570 * This is - of course - not reliable if the machine has no video 8571 * bridge... 8572 */ 8573 inSISIDXREG(SISCR, 0x34, pSiS->OldMode); 8574 inSISIDXREG(SISCR, 0x30, cr30); 8575 inSISIDXREG(SISCR, 0x31, cr31); 8576 8577 /* What if CR34 is different from the BIOS scratch byte? */ 8578 if(pSiS->OldMode != myoldmode) { 8579 /* If no bridge output is active, trust the BIOS scratch byte */ 8580 if( (!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) || 8581 (pSiS->OldMode == 0) || 8582 (!cr31 && !cr30) || 8583 (cr31 & 0x20) ) { 8584 pSiS->OldMode = myoldmode; 8585 } 8586 /* ..else trust CR34 */ 8587 } 8588 8589 /* Newer 650 BIOSes set CR34 to 0xff if the mode has been 8590 * "patched", for instance for 80x50 text mode. (That mode 8591 * has no number of its own, it's 0x03 like 80x25). In this 8592 * case, we trust the BIOS scratch byte (provided that any 8593 * of these two is valid). 8594 */ 8595 if(pSiS->OldMode > 0x7f) { 8596 pSiS->OldMode = myoldmode; 8597 } 8598 } 8599#ifdef SISDUALHEAD 8600 if(pSiS->DualHeadMode) { 8601 if(!pSiS->SecondHead) pSiSEnt->OldMode = pSiS->OldMode; 8602 else pSiS->OldMode = pSiSEnt->OldMode; 8603 } 8604#endif 8605 } 8606 8607 /* RandR resets screen mode and size in CloseScreen(), hence 8608 * we need to adapt our VBFlags to the initial state if the 8609 * current mode has changed since closescreen() (or Screeninit() 8610 * for the first instance) 8611 */ 8612 if(pScrn->currentMode != pSiS->currentModeLast) { 8613 pSiS->VBFlags = pSiS->VBFlags_backup = pSiS->VBFlagsInit; 8614 } 8615 8616 /* Copy our detected monitor gammas, part 2. Note that device redetection 8617 * is not supported in DHM, so there is no need to do that anytime later. 8618 */ 8619#ifdef SISDUALHEAD 8620 if(pSiS->DualHeadMode) { 8621 if(!pSiS->SecondHead) { 8622 /* CRT2 */ 8623 pSiS->CRT1VGAMonitorGamma = pSiSEnt->CRT1VGAMonitorGamma; 8624 } else { 8625 /* CRT1 */ 8626 pSiS->CRT2VGAMonitorGamma = pSiSEnt->CRT2VGAMonitorGamma; 8627 } 8628 if(!pSiS->CRT2LCDMonitorGamma) pSiS->CRT2LCDMonitorGamma = pSiSEnt->CRT2LCDMonitorGamma; 8629 } 8630#endif 8631 8632 /* Initialize the first mode */ 8633 if(!SISModeInit(pScrn, pScrn->currentMode)) { 8634 SISErrorLog(pScrn, "SiSModeInit() failed\n"); 8635 return FALSE; 8636 } 8637 8638 /* Darken the screen for aesthetic reasons */ 8639 /* Not using Dual Head variant on purpose; we darken 8640 * the screen for both displays, and un-darken 8641 * it when the second head is finished 8642 */ 8643 SISSaveScreen(pScreen, SCREEN_SAVER_ON); 8644 8645 /* Set the viewport */ 8646 SISAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 8647 8648 /* Reset visual list. */ 8649 miClearVisualTypes(); 8650 8651 /* Setup the visuals we support. */ 8652 8653 /* 8654 * For bpp > 8, the default visuals are not acceptable because we only 8655 * support TrueColor and not DirectColor. 8656 */ 8657 if(!miSetVisualTypes(pScrn->depth, 8658 (pScrn->bitsPerPixel > 8) ? 8659 TrueColorMask : miGetDefaultVisualMask(pScrn->depth), 8660 pScrn->rgbBits, pScrn->defaultVisual)) { 8661 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8662 SISErrorLog(pScrn, "miSetVisualTypes() failed (bpp %d)\n", 8663 pScrn->bitsPerPixel); 8664 return FALSE; 8665 } 8666 8667 width = pScrn->virtualX; 8668 height = pScrn->virtualY; 8669 displayWidth = pScrn->displayWidth; 8670 8671 if(pSiS->Rotate) { 8672 height = pScrn->virtualX; 8673 width = pScrn->virtualY; 8674 } 8675 8676 if(pSiS->ShadowFB) { 8677 pSiS->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); 8678 pSiS->ShadowPtr = xalloc(pSiS->ShadowPitch * height); 8679 displayWidth = pSiS->ShadowPitch / (pScrn->bitsPerPixel >> 3); 8680 FBStart = pSiS->ShadowPtr; 8681 } else { 8682 pSiS->ShadowPtr = NULL; 8683 FBStart = pSiS->FbBase; 8684 } 8685 8686 if(!miSetPixmapDepths()) { 8687 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8688 SISErrorLog(pScrn, "miSetPixmapDepths() failed\n"); 8689 return FALSE; 8690 } 8691 8692 /* Point cmdQueuePtr to pSiSEnt for shared usage 8693 * (same technique is then eventually used in DRIScreeninit) 8694 * For 315/330 series, this is done in EnableTurboQueue 8695 * which has already been called during ModeInit(). 8696 */ 8697#ifdef SISDUALHEAD 8698 if(pSiS->SecondHead) 8699 pSiS->cmdQueueLenPtr = &(SISPTR(pSiSEnt->pScrn_1)->cmdQueueLen); 8700 else 8701#endif 8702 pSiS->cmdQueueLenPtr = &(pSiS->cmdQueueLen); 8703 8704 pSiS->cmdQueueLen = 0; /* Force an EngineIdle() at start */ 8705 8706#ifdef XF86DRI 8707 if(pSiS->loadDRI) { 8708#ifdef SISDUALHEAD 8709 /* No DRI in dual head mode */ 8710 if(pSiS->DualHeadMode) { 8711 pSiS->directRenderingEnabled = FALSE; 8712 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8713 "DRI not supported in Dual Head mode\n"); 8714 } else 8715#endif 8716 if(pSiS->VGAEngine != SIS_315_VGA) { 8717 /* Force the initialization of the context */ 8718 pSiS->directRenderingEnabled = SISDRIScreenInit(pScreen); 8719 } else { 8720 xf86DrvMsg(pScrn->scrnIndex, X_NOT_IMPLEMENTED, 8721 "DRI not supported on this chipset\n"); 8722 pSiS->directRenderingEnabled = FALSE; 8723 } 8724 } 8725#endif 8726 8727 /* Call the framebuffer layer's ScreenInit function and fill in other 8728 * pScreen fields. 8729 */ 8730 switch(pScrn->bitsPerPixel) { 8731 case 24: 8732 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 8733 ret = FALSE; 8734 break; 8735 } 8736 /* fall through */ 8737 case 8: 8738 case 16: 8739 case 32: 8740 ret = fbScreenInit(pScreen, FBStart, width, 8741 height, pScrn->xDpi, pScrn->yDpi, 8742 displayWidth, pScrn->bitsPerPixel); 8743 break; 8744 default: 8745 ret = FALSE; 8746 break; 8747 } 8748 if(!ret) { 8749 SISErrorLog(pScrn, "Unsupported bpp (%d) or fbScreenInit() failed\n", 8750 pScrn->bitsPerPixel); 8751 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8752 return FALSE; 8753 } 8754 8755 /* Fixup RGB ordering */ 8756 if(pScrn->bitsPerPixel > 8) { 8757 visual = pScreen->visuals + pScreen->numVisuals; 8758 while (--visual >= pScreen->visuals) { 8759 if((visual->class | DynamicClass) == DirectColor) { 8760 visual->offsetRed = pScrn->offset.red; 8761 visual->offsetGreen = pScrn->offset.green; 8762 visual->offsetBlue = pScrn->offset.blue; 8763 visual->redMask = pScrn->mask.red; 8764 visual->greenMask = pScrn->mask.green; 8765 visual->blueMask = pScrn->mask.blue; 8766 } 8767 } 8768 } 8769 8770 /* Initialize RENDER extension (must be after RGB ordering fixed) */ 8771 fbPictureInit(pScreen, 0, 0); 8772 8773 /* Hardware cursor needs to wrap this layer */ 8774 if(!pSiS->ShadowFB) SISDGAInit(pScreen); 8775 8776 xf86SetBlackWhitePixels(pScreen); 8777 8778 /* Initialize the accelerators */ 8779 switch(pSiS->VGAEngine) { 8780 case SIS_530_VGA: 8781 case SIS_300_VGA: 8782 SiS300AccelInit(pScreen); 8783 break; 8784 case SIS_315_VGA: 8785 SiS315AccelInit(pScreen); 8786 break; 8787 default: 8788 SiSAccelInit(pScreen); 8789 } 8790 8791#ifdef TWDEBUG 8792 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CPUFlags %x\n", pSiS->CPUFlags); 8793#endif 8794 8795 /* Benchmark memcpy() methods (needs FB manager initialized) */ 8796 /* Dual head: Do this AFTER the mode for CRT1 has been set */ 8797 pSiS->NeedCopyFastVidCpy = FALSE; 8798 if(!pSiS->SiSFastVidCopyDone) { 8799#ifdef SISDUALHEAD 8800 if(pSiS->DualHeadMode) { 8801 if(pSiS->SecondHead) { 8802 pSiSEnt->SiSFastVidCopy = SiSVidCopyInit(pScreen, &pSiSEnt->SiSFastMemCopy, FALSE); 8803 pSiSEnt->SiSFastVidCopyFrom = SiSVidCopyGetDefault(); 8804 pSiSEnt->SiSFastMemCopyFrom = SiSVidCopyGetDefault(); 8805#ifdef SIS_USE_EXA 8806 if(pSiS->useEXA) { 8807 pSiSEnt->SiSFastVidCopyFrom = SiSVidCopyInit(pScreen, &pSiSEnt->SiSFastMemCopyFrom, TRUE); 8808 } 8809#endif /* EXA */ 8810 pSiSEnt->HaveFastVidCpy = TRUE; 8811 pSiS->SiSFastVidCopy = pSiSEnt->SiSFastVidCopy; 8812 pSiS->SiSFastMemCopy = pSiSEnt->SiSFastMemCopy; 8813 pSiS->SiSFastVidCopyFrom = pSiSEnt->SiSFastVidCopyFrom; 8814 pSiS->SiSFastMemCopyFrom = pSiSEnt->SiSFastMemCopyFrom; 8815 } else { 8816 pSiS->NeedCopyFastVidCpy = TRUE; 8817 } 8818 } else { 8819#endif 8820 pSiS->SiSFastVidCopy = SiSVidCopyInit(pScreen, &pSiS->SiSFastMemCopy, FALSE); 8821 pSiS->SiSFastVidCopyFrom = SiSVidCopyGetDefault(); 8822 pSiS->SiSFastMemCopyFrom = SiSVidCopyGetDefault(); 8823#ifdef SIS_USE_EXA 8824 if(pSiS->useEXA) { 8825 pSiS->SiSFastVidCopyFrom = SiSVidCopyInit(pScreen, &pSiS->SiSFastMemCopyFrom, TRUE); 8826 } 8827#endif /* EXA */ 8828#ifdef SISDUALHEAD 8829 } 8830#endif 8831 } 8832 pSiS->SiSFastVidCopyDone = TRUE; 8833 8834 miInitializeBackingStore(pScreen); 8835 xf86SetBackingStore(pScreen); 8836 xf86SetSilkenMouse(pScreen); 8837 8838 /* Initialise cursor functions */ 8839 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 8840 8841 if(pSiS->HWCursor) { 8842 SiSHWCursorInit(pScreen); 8843 } 8844 8845#ifdef SISDUALHEAD 8846 if(!pSiS->DualHeadMode) { 8847#endif 8848 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && (pScrn->depth > 8)) { 8849 8850 pSiS->CRT2ColNum = 1 << pScrn->rgbBits; 8851 8852 if((pSiS->crt2gcolortable = xalloc(pSiS->CRT2ColNum * 2 * sizeof(LOCO)))) { 8853 pSiS->crt2colors = &pSiS->crt2gcolortable[pSiS->CRT2ColNum]; 8854 if((pSiS->crt2cindices = xalloc(256 * sizeof(int)))) { 8855 int i = pSiS->CRT2ColNum; 8856 SISCalculateGammaRampCRT2(pScrn); 8857 while(i--) pSiS->crt2cindices[i] = i; 8858 } else { 8859 xfree(pSiS->crt2gcolortable); 8860 pSiS->crt2gcolortable = NULL; 8861 pSiS->CRT2SepGamma = FALSE; 8862 } 8863 } else { 8864 pSiS->CRT2SepGamma = FALSE; 8865 } 8866 8867 if(!pSiS->crt2cindices) { 8868 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 8869 "Failed to allocate cmap for CRT2, separate gamma correction disabled\n"); 8870 } 8871 8872 } 8873#ifdef SISDUALHEAD 8874 } else pSiS->CRT2SepGamma = FALSE; 8875#endif 8876 8877 /* Initialise default colormap */ 8878 if(!miCreateDefColormap(pScreen)) { 8879 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8880 SISErrorLog(pScrn, "miCreateDefColormap() failed\n"); 8881 return FALSE; 8882 } 8883 8884 if(!xf86HandleColormaps(pScreen, 256, (pScrn->depth == 8) ? 8 : pScrn->rgbBits, 8885 SISLoadPalette, NULL, 8886 CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH)) { 8887 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8888 SISErrorLog(pScrn, "xf86HandleColormaps() failed\n"); 8889 return FALSE; 8890 } 8891 8892 /* Recalculate our gamma ramp for brightness feature */ 8893#ifdef SISGAMMARAMP 8894 if((pSiS->GammaBriR != 1000) || 8895 (pSiS->GammaBriB != 1000) || 8896 (pSiS->GammaBriG != 1000) || 8897 (pSiS->NewGammaBriR != 0.0) || 8898 (pSiS->NewGammaBriG != 0.0) || 8899 (pSiS->NewGammaBriB != 0.0) || 8900 (pSiS->NewGammaConR != 0.0) || 8901 (pSiS->NewGammaConG != 0.0) || 8902 (pSiS->NewGammaConB != 0.0)) { 8903 SISCalculateGammaRamp(pScreen, pScrn); 8904 } 8905#endif 8906 8907 /* Initialize Shadow framebuffer and screen rotation/reflection */ 8908 if(pSiS->ShadowFB) { 8909 RefreshAreaFuncPtr refreshArea = SISRefreshArea; 8910 8911 if(pSiS->Rotate) { 8912 if(!pSiS->PointerMoved) pSiS->PointerMoved = pScrn->PointerMoved; 8913 pScrn->PointerMoved = SISPointerMoved; 8914 switch(pScrn->bitsPerPixel) { 8915 case 8: refreshArea = SISRefreshArea8; break; 8916 case 16: refreshArea = SISRefreshArea16; break; 8917 case 24: refreshArea = SISRefreshArea24; break; 8918 case 32: refreshArea = SISRefreshArea32; break; 8919 } 8920#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 8921 xf86DisableRandR(); 8922 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8923 "Driver rotation enabled, disabling RandR\n"); 8924#endif 8925 } else if(pSiS->Reflect) { 8926 switch(pScrn->bitsPerPixel) { 8927 case 8: 8928 case 16: 8929 case 32: 8930 if(!pSiS->PointerMoved) pSiS->PointerMoved = pScrn->PointerMoved; 8931 pScrn->PointerMoved = SISPointerMovedReflect; 8932 refreshArea = SISRefreshAreaReflect; 8933#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 8934 xf86DisableRandR(); 8935 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8936 "Driver reflection enabled, disabling RandR\n"); 8937#endif 8938 break; 8939 default: 8940 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 8941 "Reflection not supported at this framebuffer depth\n"); 8942 } 8943 } 8944 8945 ShadowFBInit(pScreen, refreshArea); 8946 } 8947 8948 xf86DPMSInit(pScreen, (DPMSSetProcPtr)SISDisplayPowerManagementSet, 0); 8949 8950 /* Init memPhysBase and fbOffset in pScrn */ 8951 pScrn->memPhysBase = pSiS->FbAddress; 8952 pScrn->fbOffset = 0; 8953 8954 /* Initialize Xv */ 8955 pSiS->ResetXv = pSiS->ResetXvGamma = pSiS->ResetXvDisplay = NULL; 8956#if (XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,99,0,0)) || (defined(XvExtension)) 8957 if((!pSiS->NoXvideo) && (!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY))) { 8958 8959 if((pSiS->VGAEngine == SIS_300_VGA) || 8960 (pSiS->VGAEngine == SIS_315_VGA)) { 8961 8962 const char *using = "Using SiS300/315/330/340 series HW Xv"; 8963 8964#ifdef SISDUALHEAD 8965 if(pSiS->DualHeadMode) { 8966 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8967 "%s on CRT%d\n", using, (pSiS->SecondHead ? 1 : 2)); 8968 if(!pSiS->hasTwoOverlays) { 8969 if( (pSiS->XvOnCRT2 && pSiS->SecondHead) || 8970 (!pSiS->XvOnCRT2 && !pSiS->SecondHead) ) { 8971 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8972 "However, video overlay will by default only be visible on CRT%d\n", 8973 pSiS->XvOnCRT2 ? 2 : 1); 8974 } 8975 } 8976 } else { 8977#endif 8978 if(pSiS->hasTwoOverlays) { 8979 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s\n", using); 8980 } else { 8981 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s by default on CRT%d\n", 8982 using, (pSiS->XvOnCRT2 ? 2 : 1)); 8983 } 8984#ifdef SISDUALHEAD 8985 } 8986#endif 8987 8988 SISInitVideo(pScreen); 8989 8990 if(pSiS->blitadaptor) { 8991 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8992 "Default Xv adaptor is Video %s\n", 8993 pSiS->XvDefAdaptorBlit ? "Blitter" : "Overlay"); 8994 } 8995 8996 } else if(pSiS->Chipset == PCI_CHIP_SIS530 || 8997 pSiS->Chipset == PCI_CHIP_SIS6326 || 8998 pSiS->Chipset == PCI_CHIP_SIS5597) { 8999 9000 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9001 "Using SiS5597/5598/6326/530/620 HW Xv\n" ); 9002 9003 SIS6326InitVideo(pScreen); 9004 9005 } else { /* generic Xv */ 9006 9007 XF86VideoAdaptorPtr *ptr; 9008 int n = xf86XVListGenericAdaptors(pScrn, &ptr); 9009 9010 if(n) { 9011 xf86XVScreenInit(pScreen, ptr, n); 9012 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using generic Xv\n" ); 9013 } 9014 9015 } 9016 } 9017#endif 9018 9019#ifdef XF86DRI 9020 if(pSiS->loadDRI) { 9021 if(pSiS->directRenderingEnabled) { 9022 /* Now that mi, drm and others have done their thing, 9023 * complete the DRI setup. 9024 */ 9025 pSiS->directRenderingEnabled = SISDRIFinishScreenInit(pScreen); 9026 } 9027 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering %s\n", 9028 pSiS->directRenderingEnabled ? "enabled" : "disabled"); 9029 /* TODO */ 9030 /* if(pSiS->directRenderingEnabled) SISSetLFBConfig(pSiS); */ 9031 } 9032#endif 9033 9034 /* Wrap some funcs, initialize pseudo-Xinerama and setup remaining SD flags */ 9035 9036 pSiS->SiS_SD_Flags &= ~(SiS_SD_PSEUDOXINERAMA); 9037#ifdef SISMERGED 9038 if(pSiS->MergedFB) { 9039 pSiS->PointerMoved = pScrn->PointerMoved; 9040 pScrn->PointerMoved = SISMergedPointerMoved; 9041 pSiS->Rotate = 0; 9042 pSiS->Reflect = 0; 9043 pSiS->ShadowFB = FALSE; 9044#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 9045 if(pSiS->CRT1XOffs || pSiS->CRT1YOffs || pSiS->CRT2XOffs || pSiS->CRT2YOffs) { 9046 xf86DisableRandR(); 9047 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9048 "MergedFB: CRT2Position offset used, disabling RandR\n"); 9049 } 9050#endif 9051#ifdef SISXINERAMA 9052 if(pSiS->UseSiSXinerama) { 9053 SiSnoPanoramiXExtension = FALSE; 9054 SiSXineramaExtensionInit(pScrn); 9055 if(!SiSnoPanoramiXExtension) { 9056 pSiS->SiS_SD_Flags |= SiS_SD_PSEUDOXINERAMA; 9057 if(pSiS->HaveNonRect) { 9058 /* Reset the viewport (now eventually non-recangular) */ 9059 SISAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 9060 } 9061 } 9062 } else { 9063 pSiS->MouseRestrictions = FALSE; 9064 } 9065#endif 9066 } 9067#endif 9068 9069 /* Wrap CloseScreen and set up SaveScreen */ 9070 pSiS->CloseScreen = pScreen->CloseScreen; 9071 pScreen->CloseScreen = SISCloseScreen; 9072#ifdef SISDUALHEAD 9073 if(pSiS->DualHeadMode) 9074 pScreen->SaveScreen = SISSaveScreenDH; 9075 else 9076#endif 9077 pScreen->SaveScreen = SISSaveScreen; 9078 9079 /* Install BlockHandler */ 9080 pSiS->BlockHandler = pScreen->BlockHandler; 9081 pScreen->BlockHandler = SISBlockHandler; 9082 9083 /* Report any unused options (only for the first generation) */ 9084 if(serverGeneration == 1) { 9085 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 9086 } 9087 9088 /* Clear frame buffer */ 9089 /* For CRT2, we don't do that at this point in dual head 9090 * mode since the mode isn't switched at this time (it will 9091 * be reset when setting the CRT1 mode). Hence, we just 9092 * save the necessary data and clear the screen when 9093 * going through this for CRT1. 9094 */ 9095 9096 OnScreenSize = pScrn->displayWidth * pScrn->currentMode->VDisplay 9097 * (pScrn->bitsPerPixel >> 3); 9098 9099 /* Turn on the screen now */ 9100 /* We do this in dual head mode after second head is finished */ 9101#ifdef SISDUALHEAD 9102 if(pSiS->DualHeadMode) { 9103 if(pSiS->SecondHead) { 9104 sisclearvram(pSiS->FbBase, OnScreenSize); 9105 sisclearvram(pSiSEnt->FbBase1, pSiSEnt->OnScreenSize1); 9106 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 9107 } else { 9108 pSiSEnt->FbBase1 = pSiS->FbBase; 9109 pSiSEnt->OnScreenSize1 = OnScreenSize; 9110 } 9111 } else { 9112#endif 9113 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 9114 sisclearvram(pSiS->FbBase, OnScreenSize); 9115#ifdef SISDUALHEAD 9116 } 9117#endif 9118 9119 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTSGRCRT2; 9120#ifdef SISDUALHEAD 9121 if(!pSiS->DualHeadMode) { 9122#endif 9123 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 9124 if((pSiS->crt2cindices) && (pSiS->crt2gcolortable)) { 9125 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTSGRCRT2; 9126 } 9127 } 9128#ifdef SISDUALHEAD 9129 } 9130#endif 9131 9132 pSiS->SiS_SD_Flags &= ~SiS_SD_ISDEPTH8; 9133 if(pSiS->CurrentLayout.bitsPerPixel == 8) { 9134 pSiS->SiS_SD_Flags |= SiS_SD_ISDEPTH8; 9135 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTXVGAMMA1; 9136 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTSGRCRT2; 9137 } 9138 9139#ifdef SISGAMMARAMP 9140 pSiS->SiS_SD_Flags |= SiS_SD_CANSETGAMMA; 9141#else 9142 pSiS->SiS_SD_Flags &= ~SiS_SD_CANSETGAMMA; 9143#endif 9144 9145 SiSCtrlExtInit(pScrn); 9146 9147 return TRUE; 9148} 9149 9150/* Usually mandatory */ 9151Bool 9152SISSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) 9153{ 9154 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 9155 SISPtr pSiS = SISPTR(pScrn); 9156 9157 if(!pSiS->skipswitchcheck) { 9158 if(SISValidMode(scrnIndex, mode, TRUE, flags) != MODE_OK) { 9159 return FALSE; 9160 } 9161 } 9162 9163 (*pSiS->SyncAccel)(pScrn); 9164 9165 if(!(SISModeInit(xf86Screens[scrnIndex], mode))) return FALSE; 9166 9167 /* Since RandR (indirectly) uses SwitchMode(), we need to 9168 * update our Xinerama info here, too, in case of resizing 9169 */ 9170#ifdef SISMERGED 9171#ifdef SISXINERAMA 9172 if(pSiS->MergedFB) { 9173 SiSUpdateXineramaScreenInfo(pScrn); 9174 } 9175#endif 9176#endif 9177 return TRUE; 9178} 9179 9180static void 9181SISSetStartAddressCRT1(SISPtr pSiS, ULong base) 9182{ 9183 UChar cr11backup; 9184 9185 inSISIDXREG(SISCR, 0x11, cr11backup); /* Unlock CRTC registers */ 9186 andSISIDXREG(SISCR, 0x11, 0x7F); 9187 outSISIDXREG(SISCR, 0x0D, base & 0xFF); 9188 outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); 9189 outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF); 9190 if(pSiS->VGAEngine == SIS_315_VGA) { 9191 setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01); 9192 } 9193 /* Eventually lock CRTC registers */ 9194 setSISIDXREG(SISCR, 0x11, 0x7F,(cr11backup & 0x80)); 9195} 9196 9197static void 9198SISSetStartAddressCRT2(SISPtr pSiS, ULong base) 9199{ 9200 SiS_UnLockCRT2(pSiS->SiS_Pr); 9201 outSISIDXREG(SISPART1, 0x06, GETVAR8(base)); 9202 outSISIDXREG(SISPART1, 0x05, GETBITS(base, 15:8)); 9203 outSISIDXREG(SISPART1, 0x04, GETBITS(base, 23:16)); 9204 if(pSiS->VGAEngine == SIS_315_VGA) { 9205 setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7); 9206 } 9207 SiS_LockCRT2(pSiS->SiS_Pr); 9208} 9209 9210#ifdef SISMERGED 9211static Bool 9212InRegion(int x, int y, region r) 9213{ 9214 return (r.x0 <= x) && (x <= r.x1) && (r.y0 <= y) && (y <= r.y1); 9215} 9216 9217static void 9218SISAdjustFrameHW_CRT1(ScrnInfoPtr pScrn, int x, int y) 9219{ 9220 SISPtr pSiS = SISPTR(pScrn); 9221 ULong base; 9222 9223 base = y * pSiS->CurrentLayout.displayWidth + x; 9224 switch(pSiS->CurrentLayout.bitsPerPixel) { 9225 case 16: base >>= 1; break; 9226 case 32: break; 9227 default: base >>= 2; 9228 } 9229 base += (pSiS->dhmOffset/4); 9230 SISSetStartAddressCRT1(pSiS, base); 9231} 9232 9233static void 9234SISAdjustFrameHW_CRT2(ScrnInfoPtr pScrn, int x, int y) 9235{ 9236 SISPtr pSiS = SISPTR(pScrn); 9237 ULong base; 9238 9239 base = y * pSiS->CurrentLayout.displayWidth + x; 9240 switch(pSiS->CurrentLayout.bitsPerPixel) { 9241 case 16: base >>= 1; break; 9242 case 32: break; 9243 default: base >>= 2; 9244 } 9245 base += (pSiS->dhmOffset/4); 9246 SISSetStartAddressCRT2(pSiS, base); 9247} 9248 9249static void 9250SISMergedPointerMoved(int scrnIndex, int x, int y) 9251{ 9252 ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex]; 9253 SISPtr pSiS = SISPTR(pScrn1); 9254 ScrnInfoPtr pScrn2 = pSiS->CRT2pScrn; 9255 region out, in1, in2, f2, f1; 9256 int deltax, deltay; 9257 int temp1, temp2; 9258 int old1x0, old1y0, old2x0, old2y0; 9259 int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; 9260 int HVirt = pScrn1->virtualX; 9261 int VVirt = pScrn1->virtualY; 9262 int sigstate; 9263 Bool doit = FALSE, HaveNonRect = FALSE, HaveOffsRegions = FALSE; 9264 SiSScrn2Rel srel = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT2Position; 9265 9266 if(pSiS->DGAactive) { 9267 return; 9268 /* DGA: There is no cursor and no panning while DGA is active. */ 9269 /* If it were, we would need to do: */ 9270 /* HVirt = pSiS->CurrentLayout.displayWidth; 9271 VVirt = pSiS->CurrentLayout.displayHeight; 9272 BOUND(x, pSiS->CurrentLayout.DGAViewportX, HVirt); 9273 BOUND(y, pSiS->CurrentLayout.DGAViewportY, VVirt); */ 9274 } else { 9275 CRT1XOffs = pSiS->CRT1XOffs; 9276 CRT1YOffs = pSiS->CRT1YOffs; 9277 CRT2XOffs = pSiS->CRT2XOffs; 9278 CRT2YOffs = pSiS->CRT2YOffs; 9279 HaveNonRect = pSiS->HaveNonRect; 9280 HaveOffsRegions = pSiS->HaveOffsRegions; 9281 } 9282 9283 /* Check if the pointer is inside our dead areas */ 9284 if((pSiS->MouseRestrictions) && (srel != sisClone) && !SiSnoPanoramiXExtension) { 9285 if(HaveNonRect) { 9286 if(InRegion(x, y, pSiS->NonRectDead)) { 9287 switch(srel) { 9288 case sisLeftOf: 9289 case sisRightOf: y = pSiS->NonRectDead.y0 - 1; 9290 doit = TRUE; 9291 break; 9292 case sisAbove: 9293 case sisBelow: x = pSiS->NonRectDead.x0 - 1; 9294 doit = TRUE; 9295 default: break; 9296 } 9297 } 9298 } 9299 if(HaveOffsRegions) { 9300 if(InRegion(x, y, pSiS->OffDead1)) { 9301 switch(srel) { 9302 case sisLeftOf: 9303 case sisRightOf: y = pSiS->OffDead1.y1; 9304 doit = TRUE; 9305 break; 9306 case sisAbove: 9307 case sisBelow: x = pSiS->OffDead1.x1; 9308 doit = TRUE; 9309 default: break; 9310 } 9311 } else if(InRegion(x, y, pSiS->OffDead2)) { 9312 switch(srel) { 9313 case sisLeftOf: 9314 case sisRightOf: y = pSiS->OffDead2.y0 - 1; 9315 doit = TRUE; 9316 break; 9317 case sisAbove: 9318 case sisBelow: x = pSiS->OffDead2.x0 - 1; 9319 doit = TRUE; 9320 default: break; 9321 } 9322 } 9323 } 9324 if(doit) { 9325 UpdateCurrentTime(); 9326 sigstate = xf86BlockSIGIO(); 9327 miPointerAbsoluteCursor(x, y, currentTime.milliseconds); 9328 xf86UnblockSIGIO(sigstate); 9329 return; 9330 } 9331 } 9332 9333 f1.x0 = old1x0 = pSiS->CRT1frameX0; 9334 f1.x1 = pSiS->CRT1frameX1; 9335 f1.y0 = old1y0 = pSiS->CRT1frameY0; 9336 f1.y1 = pSiS->CRT1frameY1; 9337 f2.x0 = old2x0 = pScrn2->frameX0; 9338 f2.x1 = pScrn2->frameX1; 9339 f2.y0 = old2y0 = pScrn2->frameY0; 9340 f2.y1 = pScrn2->frameY1; 9341 9342 /* Define the outer region. Crossing this causes all frames to move */ 9343 out.x0 = pScrn1->frameX0; 9344 out.x1 = pScrn1->frameX1; 9345 out.y0 = pScrn1->frameY0; 9346 out.y1 = pScrn1->frameY1; 9347 9348 /* 9349 * Define the inner sliding window. Being outsize both frames but 9350 * inside the outer clipping window will slide corresponding frame 9351 */ 9352 in1 = out; 9353 in2 = out; 9354 switch(srel) { 9355 case sisLeftOf: 9356 in1.x0 = f1.x0; 9357 in2.x1 = f2.x1; 9358 break; 9359 case sisRightOf: 9360 in1.x1 = f1.x1; 9361 in2.x0 = f2.x0; 9362 break; 9363 case sisBelow: 9364 in1.y1 = f1.y1; 9365 in2.y0 = f2.y0; 9366 break; 9367 case sisAbove: 9368 in1.y0 = f1.y0; 9369 in2.y1 = f2.y1; 9370 break; 9371 case sisClone: 9372 break; 9373 } 9374 9375 deltay = 0; 9376 deltax = 0; 9377 9378 if(InRegion(x, y, out)) { /* inside outer region */ 9379 9380 if(InRegion(x, y, in1) && !InRegion(x, y, f1)) { 9381 REBOUND(f1.x0, f1.x1, x); 9382 REBOUND(f1.y0, f1.y1, y); 9383 deltax = 1; 9384 } 9385 if(InRegion(x, y, in2) && !InRegion(x, y, f2)) { 9386 REBOUND(f2.x0, f2.x1, x); 9387 REBOUND(f2.y0, f2.y1, y); 9388 deltax = 1; 9389 } 9390 9391 } else { /* outside outer region */ 9392 9393 if(out.x0 > x) { 9394 deltax = x - out.x0; 9395 } 9396 if(out.x1 < x) { 9397 deltax = x - out.x1; 9398 } 9399 if(deltax) { 9400 pScrn1->frameX0 += deltax; 9401 pScrn1->frameX1 += deltax; 9402 f1.x0 += deltax; 9403 f1.x1 += deltax; 9404 f2.x0 += deltax; 9405 f2.x1 += deltax; 9406 } 9407 9408 if(out.y0 > y) { 9409 deltay = y - out.y0; 9410 } 9411 if(out.y1 < y) { 9412 deltay = y - out.y1; 9413 } 9414 if(deltay) { 9415 pScrn1->frameY0 += deltay; 9416 pScrn1->frameY1 += deltay; 9417 f1.y0 += deltay; 9418 f1.y1 += deltay; 9419 f2.y0 += deltay; 9420 f2.y1 += deltay; 9421 } 9422 9423 switch(srel) { 9424 case sisLeftOf: 9425 if(x >= f1.x0) { REBOUND(f1.y0, f1.y1, y); } 9426 if(x <= f2.x1) { REBOUND(f2.y0, f2.y1, y); } 9427 break; 9428 case sisRightOf: 9429 if(x <= f1.x1) { REBOUND(f1.y0, f1.y1, y); } 9430 if(x >= f2.x0) { REBOUND(f2.y0, f2.y1, y); } 9431 break; 9432 case sisBelow: 9433 if(y <= f1.y1) { REBOUND(f1.x0, f1.x1, x); } 9434 if(y >= f2.y0) { REBOUND(f2.x0, f2.x1, x); } 9435 break; 9436 case sisAbove: 9437 if(y >= f1.y0) { REBOUND(f1.x0, f1.x1, x); } 9438 if(y <= f2.y1) { REBOUND(f2.x0, f2.x1, x); } 9439 break; 9440 case sisClone: 9441 break; 9442 } 9443 9444 } 9445 9446 if(deltax || deltay) { 9447 pSiS->CRT1frameX0 = f1.x0; 9448 pSiS->CRT1frameY0 = f1.y0; 9449 pScrn2->frameX0 = f2.x0; 9450 pScrn2->frameY0 = f2.y0; 9451 9452 switch(srel) { 9453 case sisLeftOf: 9454 case sisRightOf: 9455 if(CRT1YOffs || CRT2YOffs || HaveNonRect) { 9456 if(pSiS->CRT1frameY0 != old1y0) { 9457 if(pSiS->CRT1frameY0 < CRT1YOffs) 9458 pSiS->CRT1frameY0 = CRT1YOffs; 9459 9460 temp1 = pSiS->CRT1frameY0 + CDMPTR->CRT1->VDisplay; 9461 temp2 = min((VVirt - CRT2YOffs), (CRT1YOffs + pSiS->MBXNR1YMAX)); 9462 if(temp1 > temp2) 9463 pSiS->CRT1frameY0 -= (temp1 - temp2); 9464 } 9465 if(pScrn2->frameY0 != old2y0) { 9466 if(pScrn2->frameY0 < CRT2YOffs) 9467 pScrn2->frameY0 = CRT2YOffs; 9468 9469 temp1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay; 9470 temp2 = min((VVirt - CRT1YOffs), (CRT2YOffs + pSiS->MBXNR2YMAX)); 9471 if(temp1 > temp2) 9472 pScrn2->frameY0 -= (temp1 - temp2); 9473 } 9474 } 9475 break; 9476 case sisBelow: 9477 case sisAbove: 9478 if(CRT1XOffs || CRT2XOffs || HaveNonRect) { 9479 if(pSiS->CRT1frameX0 != old1x0) { 9480 if(pSiS->CRT1frameX0 < CRT1XOffs) 9481 pSiS->CRT1frameX0 = CRT1XOffs; 9482 9483 temp1 = pSiS->CRT1frameX0 + CDMPTR->CRT1->HDisplay; 9484 temp2 = min((HVirt - CRT2XOffs), (CRT1XOffs + pSiS->MBXNR1XMAX)); 9485 if(temp1 > temp2) 9486 pSiS->CRT1frameX0 -= (temp1 - temp2); 9487 } 9488 if(pScrn2->frameX0 != old2x0) { 9489 if(pScrn2->frameX0 < CRT2XOffs) 9490 pScrn2->frameX0 = CRT2XOffs; 9491 9492 temp1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay; 9493 temp2 = min((HVirt - CRT1XOffs), (CRT2XOffs + pSiS->MBXNR2XMAX)); 9494 if(temp1 > temp2) 9495 pScrn2->frameX0 -= (temp1 - temp2); 9496 } 9497 } 9498 break; 9499 case sisClone: 9500 break; 9501 } 9502 9503 pSiS->CRT1frameX1 = pSiS->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1; 9504 pSiS->CRT1frameY1 = pSiS->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1; 9505 pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1; 9506 pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1; 9507 9508 /* No need to update pScrn1->frame?1, done above */ 9509 9510 SISAdjustFrameHW_CRT1(pScrn1, pSiS->CRT1frameX0, pSiS->CRT1frameY0); 9511 SISAdjustFrameHW_CRT2(pScrn1, pScrn2->frameX0, pScrn2->frameY0); 9512 } 9513} 9514 9515static void 9516SISAdjustFrameMerged(int scrnIndex, int x, int y, int flags) 9517{ 9518 ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex]; 9519 SISPtr pSiS = SISPTR(pScrn1); 9520 ScrnInfoPtr pScrn2 = pSiS->CRT2pScrn; 9521 int HTotal = pSiS->CurrentLayout.mode->HDisplay; 9522 int VTotal = pSiS->CurrentLayout.mode->VDisplay; 9523 int HMax = HTotal; 9524 int VMax = VTotal; 9525 int HVirt = pScrn1->virtualX; 9526 int VVirt = pScrn1->virtualY; 9527 int x1 = x, x2 = x; 9528 int y1 = y, y2 = y; 9529 int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; 9530 int MBXNR1XMAX = 65536, MBXNR1YMAX = 65536, MBXNR2XMAX = 65536, MBXNR2YMAX = 65536; 9531 9532 if(pSiS->DGAactive) { 9533 HVirt = pSiS->CurrentLayout.displayWidth; 9534 VVirt = pSiS->CurrentLayout.displayHeight; 9535 } else { 9536 CRT1XOffs = pSiS->CRT1XOffs; 9537 CRT1YOffs = pSiS->CRT1YOffs; 9538 CRT2XOffs = pSiS->CRT2XOffs; 9539 CRT2YOffs = pSiS->CRT2YOffs; 9540 MBXNR1XMAX = pSiS->MBXNR1XMAX; 9541 MBXNR1YMAX = pSiS->MBXNR1YMAX; 9542 MBXNR2XMAX = pSiS->MBXNR2XMAX; 9543 MBXNR2YMAX = pSiS->MBXNR2YMAX; 9544 } 9545 9546 BOUND(x, 0, HVirt - HTotal); 9547 BOUND(y, 0, VVirt - VTotal); 9548 if(SDMPTR(pScrn1)->CRT2Position != sisClone) { 9549 BOUND(x1, CRT1XOffs, min(HVirt, MBXNR1XMAX + CRT1XOffs) - min(HTotal, MBXNR1XMAX) - CRT2XOffs); 9550 BOUND(y1, CRT1YOffs, min(VVirt, MBXNR1YMAX + CRT1YOffs) - min(VTotal, MBXNR1YMAX) - CRT2YOffs); 9551 BOUND(x2, CRT2XOffs, min(HVirt, MBXNR2XMAX + CRT2XOffs) - min(HTotal, MBXNR2XMAX) - CRT1XOffs); 9552 BOUND(y2, CRT2YOffs, min(VVirt, MBXNR2YMAX + CRT2YOffs) - min(VTotal, MBXNR2YMAX) - CRT1YOffs); 9553 } 9554 9555 switch(SDMPTR(pScrn1)->CRT2Position) { 9556 case sisLeftOf: 9557 pScrn2->frameX0 = x2; 9558 BOUND(pScrn2->frameY0, y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR->CRT2->VDisplay); 9559 pSiS->CRT1frameX0 = x1 + CDMPTR->CRT2->HDisplay; 9560 BOUND(pSiS->CRT1frameY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR->CRT1->VDisplay); 9561 break; 9562 case sisRightOf: 9563 pSiS->CRT1frameX0 = x1; 9564 BOUND(pSiS->CRT1frameY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR->CRT1->VDisplay); 9565 pScrn2->frameX0 = x2 + CDMPTR->CRT1->HDisplay; 9566 BOUND(pScrn2->frameY0, y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR->CRT2->VDisplay); 9567 break; 9568 case sisAbove: 9569 BOUND(pScrn2->frameX0, x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR->CRT2->HDisplay); 9570 pScrn2->frameY0 = y2; 9571 BOUND(pSiS->CRT1frameX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR->CRT1->HDisplay); 9572 pSiS->CRT1frameY0 = y1 + CDMPTR->CRT2->VDisplay; 9573 break; 9574 case sisBelow: 9575 BOUND(pSiS->CRT1frameX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR->CRT1->HDisplay); 9576 pSiS->CRT1frameY0 = y1; 9577 BOUND(pScrn2->frameX0, x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR->CRT2->HDisplay); 9578 pScrn2->frameY0 = y2 + CDMPTR->CRT1->VDisplay; 9579 break; 9580 case sisClone: 9581 BOUND(pSiS->CRT1frameX0, x, x + HMax - CDMPTR->CRT1->HDisplay); 9582 BOUND(pSiS->CRT1frameY0, y, y + VMax - CDMPTR->CRT1->VDisplay); 9583 BOUND(pScrn2->frameX0, x, x + HMax - CDMPTR->CRT2->HDisplay); 9584 BOUND(pScrn2->frameY0, y, y + VMax - CDMPTR->CRT2->VDisplay); 9585 break; 9586 } 9587 9588 BOUND(pSiS->CRT1frameX0, 0, HVirt - CDMPTR->CRT1->HDisplay); 9589 BOUND(pSiS->CRT1frameY0, 0, VVirt - CDMPTR->CRT1->VDisplay); 9590 BOUND(pScrn2->frameX0, 0, HVirt - CDMPTR->CRT2->HDisplay); 9591 BOUND(pScrn2->frameY0, 0, VVirt - CDMPTR->CRT2->VDisplay); 9592 9593 pScrn1->frameX0 = x; 9594 pScrn1->frameY0 = y; 9595 9596 pSiS->CRT1frameX1 = pSiS->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1; 9597 pSiS->CRT1frameY1 = pSiS->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1; 9598 pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1; 9599 pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1; 9600 9601 pScrn1->frameX1 = pScrn1->frameX0 + pSiS->CurrentLayout.mode->HDisplay - 1; 9602 pScrn1->frameY1 = pScrn1->frameY0 + pSiS->CurrentLayout.mode->VDisplay - 1; 9603 if(SDMPTR(pScrn1)->CRT2Position != sisClone) { 9604 pScrn1->frameX1 += CRT1XOffs + CRT2XOffs; 9605 pScrn1->frameY1 += CRT1YOffs + CRT2YOffs; 9606 } 9607 9608 SISAdjustFrameHW_CRT1(pScrn1, pSiS->CRT1frameX0, pSiS->CRT1frameY0); 9609 SISAdjustFrameHW_CRT2(pScrn1, pScrn2->frameX0, pScrn2->frameY0); 9610} 9611#endif 9612 9613/* 9614 * This function is used to initialize the Start Address - the first 9615 * displayed location in the video memory. 9616 * 9617 * Usually mandatory 9618 */ 9619void 9620SISAdjustFrame(int scrnIndex, int x, int y, int flags) 9621{ 9622 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 9623 SISPtr pSiS = SISPTR(pScrn); 9624 ULong base; 9625 UChar temp, cr11backup; 9626 9627#ifdef SISMERGED 9628 if(pSiS->MergedFB) { 9629 SISAdjustFrameMerged(scrnIndex, x, y, flags); 9630 return; 9631 } 9632#endif 9633 9634 if(pSiS->UseVESA) { 9635 VBESetDisplayStart(pSiS->pVbe, x, y, TRUE); 9636 return; 9637 } 9638 9639 if(pScrn->bitsPerPixel < 8) { 9640 base = (y * pSiS->CurrentLayout.displayWidth + x + 3) >> 3; 9641 } else { 9642 base = y * pSiS->CurrentLayout.displayWidth + x; 9643 9644 /* calculate base bpp dep. */ 9645 switch(pSiS->CurrentLayout.bitsPerPixel) { 9646 case 16: 9647 base >>= 1; 9648 break; 9649 case 24: 9650 base = ((base * 3)) >> 2; 9651 base -= base % 6; 9652 break; 9653 case 32: 9654 break; 9655 default: /* 8bpp */ 9656 base >>= 2; 9657 break; 9658 } 9659 } 9660 9661#ifdef UNLOCK_ALWAYS 9662 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 9663#endif 9664 9665 base += (pSiS->dhmOffset/4); 9666 9667#ifdef TWDEBUG 9668 xf86DrvMsg(0, 0, "AdjustFrame: x %d y %d bpp %d dw %d base %d, dhmOffset %d\n", 9669 x, y, pSiS->CurrentLayout.bitsPerPixel, pSiS->CurrentLayout.displayWidth, base, pSiS->dhmOffset); 9670#endif 9671 9672#ifdef SISDUALHEAD 9673 if(pSiS->DualHeadMode) { 9674 if(!pSiS->SecondHead) { 9675 /* Head 1 (master) is always CRT2 */ 9676 SISSetStartAddressCRT2(pSiS, base); 9677 } else { 9678 /* Head 2 (slave) is always CRT1 */ 9679 SISSetStartAddressCRT1(pSiS, base); 9680 } 9681 } else { 9682#endif 9683 switch(pSiS->VGAEngine) { 9684 case SIS_300_VGA: 9685 case SIS_315_VGA: 9686 SISSetStartAddressCRT1(pSiS, base); 9687 if(pSiS->VBFlags & CRT2_ENABLE) { 9688 if(!SiSBridgeIsInSlaveMode(pScrn)) { 9689 SISSetStartAddressCRT2(pSiS, base); 9690 } 9691 } 9692 break; 9693 default: 9694 /* Unlock CRTC registers */ 9695 inSISIDXREG(SISCR, 0x11, cr11backup); 9696 andSISIDXREG(SISCR, 0x11, 0x7F); 9697 outSISIDXREG(SISCR, 0x0D, base & 0xFF); 9698 outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); 9699 inSISIDXREG(SISSR, 0x27, temp); 9700 temp &= 0xF0; 9701 temp |= (base & 0x0F0000) >> 16; 9702 outSISIDXREG(SISSR, 0x27, temp); 9703 /* Eventually lock CRTC registers */ 9704 setSISIDXREG(SISCR, 0x11, 0x7F, (cr11backup & 0x80)); 9705 } 9706#ifdef SISDUALHEAD 9707 } 9708#endif 9709 9710} 9711 9712/* 9713 * This is called when VT switching back to the X server. Its job is 9714 * to reinitialise the video mode. 9715 * Mandatory! 9716 */ 9717static Bool 9718SISEnterVT(int scrnIndex, int flags) 9719{ 9720 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 9721 SISPtr pSiS = SISPTR(pScrn); 9722 9723 SiS_SiSFB_Lock(pScrn, TRUE); 9724 9725 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 9726 9727 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 9728 outSISIDXREG(SISCR,0x32,pSiS->myCR32); 9729 outSISIDXREG(SISCR,0x36,pSiS->myCR36); 9730 outSISIDXREG(SISCR,0x37,pSiS->myCR37); 9731 } 9732 9733 if(!SISModeInit(pScrn, pScrn->currentMode)) { 9734 SISErrorLog(pScrn, "SiSEnterVT: SISModeInit() failed\n"); 9735 return FALSE; 9736 } 9737 9738 SISAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 9739 9740#ifdef XF86DRI 9741 if(pSiS->directRenderingEnabled) { 9742 DRIUnlock(screenInfo.screens[scrnIndex]); 9743 } 9744#endif 9745 9746#ifdef SISDUALHEAD 9747 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) 9748#endif 9749 if(pSiS->ResetXv) { 9750 (pSiS->ResetXv)(pScrn); 9751 } 9752 9753 return TRUE; 9754} 9755 9756/* 9757 * This is called when VT switching away from the X server. Its job is 9758 * to restore the previous (text) mode. 9759 * Mandatory! 9760 */ 9761static void 9762SISLeaveVT(int scrnIndex, int flags) 9763{ 9764 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 9765 SISPtr pSiS = SISPTR(pScrn); 9766#ifdef XF86DRI 9767 ScreenPtr pScreen; 9768 9769 if(pSiS->directRenderingEnabled) { 9770 pScreen = screenInfo.screens[scrnIndex]; 9771 DRILock(pScreen, 0); 9772 } 9773#endif 9774 9775#ifdef SISDUALHEAD 9776 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 9777#endif 9778 9779 if(pSiS->CursorInfoPtr) { 9780#ifdef SISDUALHEAD 9781 if(pSiS->DualHeadMode) { 9782 if(!pSiS->SecondHead) { 9783 pSiS->ForceCursorOff = TRUE; 9784 pSiS->CursorInfoPtr->HideCursor(pScrn); 9785 SISWaitVBRetrace(pScrn); 9786 pSiS->ForceCursorOff = FALSE; 9787 } 9788 } else { 9789#endif 9790 pSiS->CursorInfoPtr->HideCursor(pScrn); 9791 SISWaitVBRetrace(pScrn); 9792#ifdef SISDUALHEAD 9793 } 9794#endif 9795 } 9796 9797 SISBridgeRestore(pScrn); 9798 9799 if(pSiS->UseVESA) { 9800 9801 /* This is a q&d work-around for a BIOS bug. In case we disabled CRT2, 9802 * VBESaveRestore() does not restore CRT1. So we set any mode now, 9803 * because VBESetVBEMode correctly restores CRT1. Afterwards, we 9804 * can call VBESaveRestore to restore original mode. 9805 */ 9806 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (!(pSiS->VBFlags & DISPTYPE_DISP2))) 9807 VBESetVBEMode(pSiS->pVbe, (pSiS->SISVESAModeList->n) | 0xc000, NULL); 9808 9809 SISVESARestore(pScrn); 9810 9811 } else { 9812 9813 SISRestore(pScrn); 9814 9815 } 9816 9817 /* We use (otherwise unused) bit 7 to indicate that we are running 9818 * to keep sisfb to change the displaymode (this would result in 9819 * lethal display corruption upon quitting X or changing to a VT 9820 * until a reboot) 9821 */ 9822 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 9823 orSISIDXREG(SISCR,0x34,0x80); 9824 } 9825 9826 SISVGALock(pSiS); 9827 9828 SiS_SiSFB_Lock(pScrn, FALSE); 9829} 9830 9831 9832/* 9833 * This is called at the end of each server generation. It restores the 9834 * original (text) mode. It should really also unmap the video memory too. 9835 * Mandatory! 9836 */ 9837static Bool 9838SISCloseScreen(int scrnIndex, ScreenPtr pScreen) 9839{ 9840 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 9841 SISPtr pSiS = SISPTR(pScrn); 9842#ifdef SISDUALHEAD 9843 SISEntPtr pSiSEnt = pSiS->entityPrivate; 9844#endif 9845 9846 if(pSiS->SiSCtrlExtEntry) { 9847 SiSCtrlExtUnregister(pSiS, pScrn->scrnIndex); 9848 } 9849 9850#ifdef XF86DRI 9851 if(pSiS->directRenderingEnabled) { 9852 SISDRICloseScreen(pScreen); 9853 pSiS->directRenderingEnabled = FALSE; 9854 } 9855#endif 9856 9857 if(pScrn->vtSema) { 9858 9859 if(pSiS->CursorInfoPtr) { 9860#ifdef SISDUALHEAD 9861 if(pSiS->DualHeadMode) { 9862 if(!pSiS->SecondHead) { 9863 pSiS->ForceCursorOff = TRUE; 9864 pSiS->CursorInfoPtr->HideCursor(pScrn); 9865 SISWaitVBRetrace(pScrn); 9866 pSiS->ForceCursorOff = FALSE; 9867 } 9868 } else { 9869#endif 9870 pSiS->CursorInfoPtr->HideCursor(pScrn); 9871 SISWaitVBRetrace(pScrn); 9872#ifdef SISDUALHEAD 9873 } 9874#endif 9875 } 9876 9877 SISBridgeRestore(pScrn); 9878 9879 if(pSiS->UseVESA) { 9880 9881 /* This is a q&d work-around for a BIOS bug. In case we disabled CRT2, 9882 * VBESaveRestore() does not restore CRT1. So we set any mode now, 9883 * because VBESetVBEMode correctly restores CRT1. Afterwards, we 9884 * can call VBESaveRestore to restore original mode. 9885 */ 9886 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (!(pSiS->VBFlags & DISPTYPE_DISP2))) 9887 VBESetVBEMode(pSiS->pVbe, (pSiS->SISVESAModeList->n) | 0xc000, NULL); 9888 9889 SISVESARestore(pScrn); 9890 9891 } else { 9892 9893 SISRestore(pScrn); 9894 9895 } 9896 9897 SISVGALock(pSiS); 9898 9899 } 9900 9901 SiS_SiSFB_Lock(pScrn, FALSE); 9902 9903 /* We should restore the mode number in case vtsema = false as well, 9904 * but since we haven't register access then we can't do it. I think 9905 * I need to rework the save/restore stuff, like saving the video 9906 * status when returning to the X server and by that save me the 9907 * trouble if sisfb was started from a textmode VT while X was on. 9908 */ 9909 9910 SISUnmapMem(pScrn); 9911#ifdef SIS_PC_PLATFORM 9912 SiSVGAUnmapMem(pScrn); 9913#endif 9914 9915#ifdef SISDUALHEAD 9916 if(pSiS->DualHeadMode) { 9917 pSiSEnt = pSiS->entityPrivate; 9918 pSiSEnt->refCount--; 9919 } 9920#endif 9921 9922 if(pSiS->pInt) { 9923 xf86FreeInt10(pSiS->pInt); 9924 pSiS->pInt = NULL; 9925 } 9926 9927#ifdef SIS_USE_XAA 9928 if(!pSiS->useEXA) { 9929 if(pSiS->AccelLinearScratch) { 9930 xf86FreeOffscreenLinear(pSiS->AccelLinearScratch); 9931 pSiS->AccelLinearScratch = NULL; 9932 } 9933 if(pSiS->AccelInfoPtr) { 9934 XAADestroyInfoRec(pSiS->AccelInfoPtr); 9935 pSiS->AccelInfoPtr = NULL; 9936 } 9937 } 9938#endif 9939 9940#ifdef SIS_USE_EXA 9941 if(pSiS->useEXA) { 9942 if(pSiS->EXADriverPtr) { 9943 exaDriverFini(pScreen); 9944 xfree(pSiS->EXADriverPtr); 9945 pSiS->EXADriverPtr = NULL; 9946 pSiS->exa_scratch = NULL; 9947 } 9948 } 9949#endif 9950 9951 if(pSiS->CursorInfoPtr) { 9952 xf86DestroyCursorInfoRec(pSiS->CursorInfoPtr); 9953 pSiS->CursorInfoPtr = NULL; 9954 } 9955 9956 if(pSiS->ShadowPtr) { 9957 xfree(pSiS->ShadowPtr); 9958 pSiS->ShadowPtr = NULL; 9959 } 9960 9961 if(pSiS->DGAModes) { 9962 xfree(pSiS->DGAModes); 9963 pSiS->DGAModes = NULL; 9964 } 9965 9966 if(pSiS->adaptor) { 9967 xfree(pSiS->adaptor); 9968 pSiS->adaptor = NULL; 9969 pSiS->ResetXv = pSiS->ResetXvGamma = pSiS->ResetXvDisplay = NULL; 9970 } 9971 9972 if(pSiS->blitadaptor) { 9973 xfree(pSiS->blitadaptor); 9974 pSiS->blitadaptor = NULL; 9975 } 9976 9977 if(pSiS->crt2gcolortable) { 9978 xfree(pSiS->crt2gcolortable); 9979 pSiS->crt2gcolortable = NULL; 9980 } 9981 9982 if(pSiS->crt2cindices) { 9983 xfree(pSiS->crt2cindices); 9984 pSiS->crt2cindices = NULL; 9985 } 9986 9987 pScrn->vtSema = FALSE; 9988 9989 /* Restore Blockhandler */ 9990 pScreen->BlockHandler = pSiS->BlockHandler; 9991 9992 pScreen->CloseScreen = pSiS->CloseScreen; 9993 9994 return(*pScreen->CloseScreen)(scrnIndex, pScreen); 9995} 9996 9997 9998/* Free up any per-generation data structures */ 9999 10000/* Optional */ 10001static void 10002SISFreeScreen(int scrnIndex, int flags) 10003{ 10004#ifdef SIS_NEED_MAP_IOP 10005 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 10006 SISPtr pSiS = SISPTR(pScrn); 10007 10008 if(pSiS) { 10009#ifdef SISDUALHEAD 10010 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10011 if(pSiSEnt) { 10012 pSiSEnt->forceUnmapIOPBase = TRUE; 10013 } 10014#endif 10015 SISUnmapIOPMem(pScrn); 10016 } 10017#endif 10018 10019 SISFreeRec(xf86Screens[scrnIndex]); 10020} 10021 10022 10023/* Checks if a mode is suitable for the selected chipset. */ 10024 10025static ModeStatus 10026SISValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) 10027{ 10028 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 10029 SISPtr pSiS = SISPTR(pScrn); 10030 10031 if(pSiS->UseVESA) { 10032 if(SiSCalcVESAModeIndex(pScrn, mode)) 10033 return(MODE_OK); 10034 else 10035 return(MODE_BAD); 10036 } 10037 10038 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 10039#ifdef SISDUALHEAD 10040 if(pSiS->DualHeadMode) { 10041 if(pSiS->SecondHead) { 10042 if(SiS_CheckModeCRT1(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10043 return(MODE_BAD); 10044 } else { 10045 if(SiS_CheckModeCRT2(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10046 return(MODE_BAD); 10047 } 10048 } else 10049#endif 10050#ifdef SISMERGED 10051 if(pSiS->MergedFB) { 10052 if(!mode->Private) { 10053 if(!pSiS->CheckForCRT2) { 10054 if(SiS_CheckModeCRT1(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10055 return(MODE_BAD); 10056 } else { 10057 if(SiS_CheckModeCRT2(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes2) < 0x14) 10058 return(MODE_BAD); 10059 } 10060 } else { 10061 if(SiS_CheckModeCRT1(pScrn, ((SiSMergedDisplayModePtr)mode->Private)->CRT1, 10062 pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10063 return(MODE_BAD); 10064 10065 if(SiS_CheckModeCRT2(pScrn, ((SiSMergedDisplayModePtr)mode->Private)->CRT2, 10066 pSiS->VBFlags, pSiS->HaveCustomModes2) < 0x14) 10067 return(MODE_BAD); 10068 } 10069 } else 10070#endif 10071 { 10072 if(SiS_CheckModeCRT1(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10073 return(MODE_BAD); 10074 10075 if(SiS_CheckModeCRT2(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10076 return(MODE_BAD); 10077 } 10078 } 10079 10080 return(MODE_OK); 10081} 10082 10083#ifdef DEBUG 10084static void 10085SiSDumpModeInfo(ScrnInfoPtr pScrn, DisplayModePtr mode) 10086{ 10087 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Clock : %x\n", mode->Clock); 10088 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Display : %x\n", mode->CrtcHDisplay); 10089 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Blank Start : %x\n", mode->CrtcHBlankStart); 10090 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Sync Start : %x\n", mode->CrtcHSyncStart); 10091 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Sync End : %x\n", mode->CrtcHSyncEnd); 10092 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Blank End : %x\n", mode->CrtcHBlankEnd); 10093 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Total : %x\n", mode->CrtcHTotal); 10094 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Skew : %x\n", mode->CrtcHSkew); 10095 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz HAdjusted : %x\n", mode->CrtcHAdjusted); 10096 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Display : %x\n", mode->CrtcVDisplay); 10097 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Blank Start : %x\n", mode->CrtcVBlankStart); 10098 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Sync Start : %x\n", mode->CrtcVSyncStart); 10099 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Sync End : %x\n", mode->CrtcVSyncEnd); 10100 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Blank End : %x\n", mode->CrtcVBlankEnd); 10101 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Total : %x\n", mode->CrtcVTotal); 10102 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt VAdjusted : %x\n", mode->CrtcVAdjusted); 10103} 10104#endif 10105 10106static void 10107SISModifyModeInfo(DisplayModePtr mode) 10108{ 10109 if(mode->CrtcHBlankStart == mode->CrtcHDisplay) 10110 mode->CrtcHBlankStart++; 10111 if(mode->CrtcHBlankEnd == mode->CrtcHTotal) 10112 mode->CrtcHBlankEnd--; 10113 if(mode->CrtcVBlankStart == mode->CrtcVDisplay) 10114 mode->CrtcVBlankStart++; 10115 if(mode->CrtcVBlankEnd == mode->CrtcVTotal) 10116 mode->CrtcVBlankEnd--; 10117} 10118 10119/* Enable the Turboqueue/Commandqueue (For 300 and 315/330/340 series only) */ 10120static void 10121SiSEnableTurboQueue(ScrnInfoPtr pScrn) 10122{ 10123 SISPtr pSiS = SISPTR(pScrn); 10124 UShort SR26, SR27; 10125 ULong temp; 10126 10127 switch(pSiS->VGAEngine) { 10128 case SIS_300_VGA: 10129 if((!pSiS->NoAccel) && (pSiS->TurboQueue)) { 10130 /* TQ size is always 512k */ 10131 temp = (pScrn->videoRam/64) - 8; 10132 SR26 = temp & 0xFF; 10133 inSISIDXREG(SISSR, 0x27, SR27); 10134 SR27 &= 0xFC; 10135 SR27 |= (0xF0 | ((temp >> 8) & 3)); 10136 outSISIDXREG(SISSR, 0x26, SR26); 10137 outSISIDXREG(SISSR, 0x27, SR27); 10138 } 10139 break; 10140 10141 case SIS_315_VGA: 10142 if(!pSiS->NoAccel) { 10143 /* On 315/330/340 series, there are three queue modes available 10144 * which are chosen by setting bits 7:5 in SR26: 10145 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep 10146 * track of the queue, the FIFO, command parsing and so 10147 * on. This is the one comparable to the 300 series. 10148 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will 10149 * have to do queue management himself. 10150 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the 10151 * queue in AGP memory space. 10152 * We go VRAM or MMIO here. 10153 * SR26 bit 4 is called "Bypass H/W queue". 10154 * SR26 bit 1 is called "Enable Command Queue Auto Correction" 10155 * SR26 bit 0 resets the queue 10156 * Size of queue memory is encoded in bits 3:2 like this: 10157 * 00 (0x00) 512K 10158 * 01 (0x04) 1M 10159 * 10 (0x08) 2M 10160 * 11 (0x0C) 4M 10161 * The queue location is to be written to 0x85C0. 10162 */ 10163#ifdef SISVRAMQ 10164 /* We use VRAM Cmd Queue, not MMIO or AGP */ 10165 UChar tempCR55 = 0; 10166 10167 /* Set Command Queue Threshold to max value 11111b (?) */ 10168 outSISIDXREG(SISSR, 0x27, 0x1F); 10169 10170 /* Disable queue flipping */ 10171 inSISIDXREG(SISCR, 0x55, tempCR55); 10172 andSISIDXREG(SISCR, 0x55, 0x33); 10173 /* Synchronous reset for Command Queue */ 10174 outSISIDXREG(SISSR, 0x26, 0x01); 10175 SIS_MMIO_OUT32(pSiS->IOBase, 0x85c4, 0); 10176 /* Enable VRAM Command Queue mode */ 10177 if(pSiS->ChipType == XGI_20) { 10178 /* On XGI_20, always 128K */ 10179 SR26 = 0x40 | 0x04 | 0x01; 10180 } else { 10181 switch(pSiS->cmdQueueSize) { 10182 case 1*1024*1024: SR26 = (0x40 | 0x04 | 0x01); break; 10183 case 2*1024*1024: SR26 = (0x40 | 0x08 | 0x01); break; 10184 case 4*1024*1024: SR26 = (0x40 | 0x0C | 0x01); break; 10185 default: 10186 pSiS->cmdQueueSize = 512 * 1024; 10187 case 512*1024: SR26 = (0x40 | 0x00 | 0x01); 10188 } 10189 } 10190 outSISIDXREG(SISSR, 0x26, SR26); 10191 SR26 &= 0xfe; 10192 outSISIDXREG(SISSR, 0x26, SR26); 10193 *(pSiS->cmdQ_SharedWritePort) = (unsigned int)(SIS_MMIO_IN32(pSiS->IOBase, 0x85c8)); 10194 SIS_MMIO_OUT32(pSiS->IOBase, 0x85c4, (CARD32)(*(pSiS->cmdQ_SharedWritePort))); 10195 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C0, pSiS->cmdQueueOffset); 10196 temp = (ULong)pSiS->RealFbBase; 10197#ifdef SISDUALHEAD 10198 if(pSiS->DualHeadMode) { 10199 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10200 temp = (ULong)pSiSEnt->RealFbBase; 10201 } 10202#endif 10203 temp += pSiS->cmdQueueOffset; 10204 pSiS->cmdQueueBase = (unsigned int *)temp; 10205 outSISIDXREG(SISCR, 0x55, tempCR55); 10206#ifdef TWDEBUG 10207 xf86DrvMsg(0, 0, "CmdQueueOffs 0x%x, CmdQueueAdd %p, shwrp 0x%x, status %x, base %p\n", 10208 pSiS->cmdQueueOffset, pSiS->cmdQueueBase, *(pSiS->cmdQ_SharedWritePort), 10209 SIS_MMIO_IN32(pSiS->IOBase, 0x85cc), (ULong *)temp); 10210#endif 10211#else 10212 /* For MMIO */ 10213 /* Syncronous reset for Command Queue */ 10214 orSISIDXREG(SISSR, 0x26, 0x01); 10215 /* Set Command Queue Threshold to max value 11111b */ 10216 outSISIDXREG(SISSR, 0x27, 0x1F); 10217 /* Do some magic (cp readport to writeport) */ 10218 temp = SIS_MMIO_IN32(pSiS->IOBase, 0x85C8); 10219 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C4, temp); 10220 /* Enable MMIO Command Queue mode (0x20), 10221 * Enable_command_queue_auto_correction (0x02) 10222 * (no idea, but sounds good, so use it) 10223 * 512k (0x00) (does this apply to MMIO mode?) */ 10224 outSISIDXREG(SISSR, 0x26, 0x22); 10225 /* Calc Command Queue position (Q is always 512k)*/ 10226 temp = (pScrn->videoRam - 512) * 1024; 10227 /* Set Q position */ 10228 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C0, temp); 10229#endif 10230 } 10231 break; 10232 default: 10233 break; 10234 } 10235} 10236 10237#ifdef SISVRAMQ 10238static void 10239SiSRestoreQueueMode(SISPtr pSiS, SISRegPtr sisReg) 10240{ 10241 UChar tempCR55=0; 10242 10243 if(pSiS->VGAEngine == SIS_315_VGA) { 10244 inSISIDXREG(SISCR,0x55,tempCR55); 10245 andSISIDXREG(SISCR,0x55,0x33); 10246 outSISIDXREG(SISSR,0x26,0x01); 10247 SIS_MMIO_OUT32(pSiS->IOBase, 0x85c4, 0); 10248 outSISIDXREG(SISSR,0x27,sisReg->sisRegs3C4[0x27]); 10249 outSISIDXREG(SISSR,0x26,sisReg->sisRegs3C4[0x26]); 10250 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C0, sisReg->sisMMIO85C0); 10251 outSISIDXREG(SISCR,0x55,tempCR55); 10252 } 10253} 10254#endif 10255 10256/* Things to do before a ModeSwitch. We set up the 10257 * video bridge configuration and the TurboQueue. 10258 */ 10259void SiSPreSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode, int viewmode) 10260{ 10261 SISPtr pSiS = SISPTR(pScrn); 10262 UChar CR30, CR31, CR32, CR33; 10263 UChar CR39 = 0, CR3B = 0; 10264 UChar CR17, CR38 = 0; 10265 UChar CR35 = 0, CR79 = 0; 10266 int temp = 0, crt1rateindex = 0; 10267 ULong vbflag = pSiS->VBFlags; 10268 Bool hcm = pSiS->HaveCustomModes; 10269 DisplayModePtr mymode = mode; 10270 10271 pSiS->IsCustom = FALSE; 10272 10273 /* NEVER call this with viewmode = SIS_MODE_SIMU 10274 * if mode->type is not M_T_DEFAULT! 10275 */ 10276 10277#ifdef SISMERGED 10278 if(pSiS->MergedFB) { 10279 switch(viewmode) { 10280 case SIS_MODE_CRT1: 10281 mymode = ((SiSMergedDisplayModePtr)mode->Private)->CRT1; 10282 break; 10283 case SIS_MODE_CRT2: 10284 mymode = ((SiSMergedDisplayModePtr)mode->Private)->CRT2; 10285 hcm = pSiS->HaveCustomModes2; 10286 } 10287 } 10288#endif 10289 10290 switch(viewmode) { 10291 case SIS_MODE_CRT1: 10292 if(SiS_CheckModeCRT1(pScrn, mymode, vbflag, hcm) == 0xfe) { 10293 pSiS->IsCustom = TRUE; 10294 } 10295 break; 10296 case SIS_MODE_CRT2: 10297 if(vbflag & CRT2_ENABLE) { 10298 if(SiS_CheckModeCRT2(pScrn, mymode, vbflag, hcm) == 0xfe) { 10299 pSiS->IsCustom = TRUE; 10300 } 10301 } else { 10302 /* This can only happen in mirror mode */ 10303 if(SiS_CheckModeCRT1(pScrn, mymode, vbflag, hcm) == 0xfe) { 10304 pSiS->IsCustom = TRUE; 10305 } 10306 } 10307 } 10308 10309#ifdef UNLOCK_ALWAYS 10310 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); /* Unlock Registers */ 10311#endif 10312 10313 inSISIDXREG(SISCR, 0x30, CR30); 10314 inSISIDXREG(SISCR, 0x31, CR31); 10315 CR32 = pSiS->newCR32; 10316 inSISIDXREG(SISCR, 0x33, CR33); 10317 10318 if(pSiS->NewCRLayout) { 10319 10320 inSISIDXREG(SISCR, 0x35, CR35); 10321 inSISIDXREG(SISCR, 0x38, CR38); 10322 inSISIDXREG(SISCR, 0x39, CR39); 10323 10324 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, SISVERBLEVEL, 10325 "Before: CR30=0x%02x,CR31=0x%02x,CR32=0x%02x,CR33=0x%02x,CR35=0x%02x,CR38=0x%02x\n", 10326 CR30, CR31, CR32, CR33, CR35, CR38); 10327 10328 CR38 &= ~0x07; 10329 10330 } else { 10331 10332 if(pSiS->Chipset != PCI_CHIP_SIS300) { 10333 switch(pSiS->VGAEngine) { 10334 case SIS_300_VGA: temp = 0x35; break; 10335 case SIS_315_VGA: temp = 0x38; break; 10336 } 10337 if(temp) inSISIDXREG(SISCR, temp, CR38); 10338 } 10339 if(pSiS->VGAEngine == SIS_315_VGA) { 10340 inSISIDXREG(SISCR, 0x79, CR79); 10341 CR38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */ 10342 } 10343 inSISIDXREG(SISCR, 0x3b, CR3B); 10344 10345 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, SISVERBLEVEL, 10346 "Before: CR30=0x%02x, CR31=0x%02x, CR32=0x%02x, CR33=0x%02x, CR%02x=0x%02x\n", 10347 CR30, CR31, CR32, CR33, temp, CR38); 10348 } 10349 10350 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, SISVERBLEVEL, "VBFlags=0x%x\n", pSiS->VBFlags); 10351 10352 CR30 = 0x00; 10353 CR31 &= ~0x60; /* Clear VB_Drivermode & VB_OutputDisable */ 10354 CR31 |= 0x04; /* Set VB_NotSimuMode (not for 30xB/1400x1050?) */ 10355 CR35 = 0x00; 10356 10357 if(!pSiS->NewCRLayout) { 10358 if(!pSiS->AllowHotkey) { 10359 CR31 |= 0x80; /* Disable hotkey-switch */ 10360 } 10361 CR79 &= ~0x10; /* Enable Backlight control on 315 series */ 10362 } 10363 10364 SiS_SetEnableDstn(pSiS->SiS_Pr, FALSE); 10365 SiS_SetEnableFstn(pSiS->SiS_Pr, FALSE); 10366 10367 if((vbflag & CRT1_LCDA) && (viewmode == SIS_MODE_CRT1)) { 10368 10369 CR38 |= 0x02; 10370 10371 } else { 10372 10373 switch(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA)) { 10374 10375 case CRT2_TV: 10376 10377 CR38 &= ~0xC0; /* Clear Pal M/N bits */ 10378 10379 if((pSiS->VBFlags2 & VB2_CHRONTEL) && (vbflag & TV_CHSCART)) { /* Chrontel */ 10380 CR30 |= 0x10; 10381 CR38 |= 0x04; 10382 CR38 &= ~0x08; 10383 CR31 |= 0x01; 10384 } else if((pSiS->VBFlags2 & VB2_CHRONTEL) && (vbflag & TV_CHYPBPR525I)) { /* Chrontel */ 10385 CR38 |= 0x08; 10386 CR38 &= ~0x04; 10387 CR31 &= ~0x01; 10388 } else if(vbflag & TV_HIVISION) { /* SiS bridge */ 10389 if(pSiS->NewCRLayout) { 10390 CR38 |= 0x04; 10391 CR35 |= 0x60; 10392 } else { 10393 CR30 |= 0x80; 10394 if(pSiS->VGAEngine == SIS_315_VGA) { 10395 if(pSiS->VBFlags2 & VB2_SISYPBPRBRIDGE) { 10396 CR38 |= (0x08 | 0x30); 10397 } 10398 } 10399 } 10400 CR31 |= 0x01; 10401 CR35 |= 0x01; 10402 } else if(vbflag & TV_YPBPR) { /* SiS bridge */ 10403 if(pSiS->NewCRLayout) { 10404 CR38 |= 0x04; 10405 CR31 &= ~0x01; 10406 CR35 &= ~0x01; 10407 if(vbflag & (TV_YPBPR525P | TV_YPBPR625P)) CR35 |= 0x20; 10408 else if(vbflag & TV_YPBPR750P) CR35 |= 0x40; 10409 else if(vbflag & TV_YPBPR1080I) CR35 |= 0x60; 10410 10411 if(vbflag & (TV_YPBPR625I | TV_YPBPR625P)) { 10412 CR31 |= 0x01; 10413 CR35 |= 0x01; 10414 } 10415 10416 CR39 &= ~0x03; 10417 if((vbflag & TV_YPBPRAR) == TV_YPBPR43LB) CR39 |= 0x00; 10418 else if((vbflag & TV_YPBPRAR) == TV_YPBPR43) CR39 |= 0x01; 10419 else if((vbflag & TV_YPBPRAR) == TV_YPBPR169) CR39 |= 0x02; 10420 else CR39 |= 0x03; 10421 } else if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR) { 10422 CR30 |= 0x80; 10423 CR38 |= 0x08; 10424 CR31 &= ~0x01; 10425 if(vbflag & (TV_YPBPR525P|TV_YPBPR625P)) CR38 |= 0x10; 10426 else if(vbflag & TV_YPBPR750P) CR38 |= 0x20; 10427 else if(vbflag & TV_YPBPR1080I) CR38 |= 0x30; 10428 10429 if(vbflag & (TV_YPBPR625I | TV_YPBPR625P)) CR31 |= 0x01; 10430 10431 if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPRAR) { 10432 CR3B &= ~0x03; 10433 if((vbflag & TV_YPBPRAR) == TV_YPBPR43LB) CR3B |= 0x00; 10434 else if((vbflag & TV_YPBPRAR) == TV_YPBPR43) CR3B |= 0x03; 10435 else if((vbflag & TV_YPBPRAR) == TV_YPBPR169) CR3B |= 0x01; 10436 else CR3B |= 0x03; 10437 } 10438 } 10439 } else { /* All */ 10440 if(vbflag & TV_SCART) CR30 |= 0x10; 10441 if(vbflag & TV_SVIDEO) CR30 |= 0x08; 10442 if(vbflag & TV_AVIDEO) CR30 |= 0x04; 10443 if(!(CR30 & 0x1C)) CR30 |= 0x08; /* default: SVIDEO */ 10444 10445 if(vbflag & TV_PAL) { 10446 CR31 |= 0x01; 10447 CR35 |= 0x01; 10448 if( (pSiS->VBFlags2 & VB2_SISBRIDGE) || 10449 ((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->ChrontelType == CHRONTEL_701x)) ) { 10450 if(vbflag & TV_PALM) { 10451 CR38 |= 0x40; 10452 CR35 |= 0x04; 10453 } else if(vbflag & TV_PALN) { 10454 CR38 |= 0x80; 10455 CR35 |= 0x08; 10456 } 10457 } 10458 } else { 10459 CR31 &= ~0x01; 10460 CR35 &= ~0x01; 10461 if(vbflag & TV_NTSCJ) { 10462 CR38 |= 0x40; /* TW, not BIOS */ 10463 CR35 |= 0x02; 10464 } 10465 } 10466 if(vbflag & TV_SCART) { 10467 CR31 |= 0x01; 10468 CR35 |= 0x01; 10469 } 10470 } 10471 10472 CR31 &= ~0x04; /* Clear NotSimuMode */ 10473 pSiS->SiS_Pr->SiS_CHOverScan = pSiS->UseCHOverScan; 10474 if((pSiS->OptTVSOver == 1) && (pSiS->ChrontelType == CHRONTEL_700x)) { 10475 pSiS->SiS_Pr->SiS_CHSOverScan = TRUE; 10476 } else { 10477 pSiS->SiS_Pr->SiS_CHSOverScan = FALSE; 10478 } 10479#ifdef SIS_CP 10480 SIS_CP_DRIVER_CONFIG 10481#endif 10482 break; 10483 10484 case CRT2_LCD: 10485 CR30 |= 0x20; 10486 SiS_SetEnableDstn(pSiS->SiS_Pr, pSiS->DSTN); 10487 SiS_SetEnableFstn(pSiS->SiS_Pr, pSiS->FSTN); 10488 break; 10489 10490 case CRT2_VGA: 10491 CR30 |= 0x40; 10492 break; 10493 10494 default: 10495 CR30 |= 0x00; 10496 CR31 |= 0x20; /* VB_OUTPUT_DISABLE */ 10497 if(pSiS->UseVESA) { 10498 crt1rateindex = SISSearchCRT1Rate(pScrn, mymode); 10499 } 10500 } 10501 10502 } 10503 10504 if(vbflag & CRT1_LCDA) { 10505 switch(viewmode) { 10506 case SIS_MODE_CRT1: 10507 CR38 |= 0x01; 10508 break; 10509 case SIS_MODE_CRT2: 10510 if(vbflag & (CRT2_TV|CRT2_VGA)) { 10511 CR30 |= 0x02; 10512 CR38 |= 0x01; 10513 } else { 10514 CR38 |= 0x03; 10515 } 10516 break; 10517 case SIS_MODE_SIMU: 10518 default: 10519 if(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA)) { 10520 CR30 |= 0x01; 10521 } 10522 break; 10523 } 10524 } else { 10525 if(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA)) { 10526 CR30 |= 0x01; 10527 } 10528 } 10529 10530 if(pSiS->UseVESA) { 10531 CR31 &= ~0x40; /* Clear Drivermode */ 10532 CR31 |= 0x06; /* Set SlaveMode, Enable SimuMode in Slavemode */ 10533#ifdef TWDEBUG 10534 CR31 |= 0x40; /* DEBUG (for non-slave mode VESA) */ 10535 crt1rateindex = SISSearchCRT1Rate(pScrn, mymode); 10536#endif 10537 } else { 10538 CR31 |= 0x40; /* Set Drivermode */ 10539 CR31 &= ~0x06; /* Disable SlaveMode, disable SimuMode in SlaveMode */ 10540 if(!pSiS->IsCustom) { 10541 crt1rateindex = SISSearchCRT1Rate(pScrn, mymode); 10542 } 10543 } 10544 10545 switch(viewmode) { 10546 case SIS_MODE_SIMU: 10547 CR33 = 0; 10548 if(!(vbflag & CRT1_LCDA)) { 10549 CR33 |= (crt1rateindex & 0x0f); 10550 } 10551 if(vbflag & CRT2_VGA) { 10552 CR33 |= ((crt1rateindex & 0x0f) << 4); 10553 } 10554 break; 10555 case SIS_MODE_CRT1: 10556 CR33 &= 0xf0; 10557 if(!(vbflag & CRT1_LCDA)) { 10558 CR33 |= (crt1rateindex & 0x0f); 10559 } 10560 break; 10561 case SIS_MODE_CRT2: 10562 CR33 &= 0x0f; 10563 if(vbflag & CRT2_VGA) { 10564 CR33 |= ((crt1rateindex & 0x0f) << 4); 10565 } 10566 break; 10567 } 10568 10569 if((!pSiS->UseVESA) && (vbflag & CRT2_ENABLE)) { 10570 if(pSiS->CRT1off) CR33 &= 0xf0; 10571 } 10572 10573 if(pSiS->NewCRLayout) { 10574 10575 CR31 &= 0xfe; /* Clear PAL flag (now in CR35) */ 10576 CR38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */ 10577 outSISIDXREG(SISCR, 0x30, CR30); 10578 outSISIDXREG(SISCR, 0x31, CR31); 10579 outSISIDXREG(SISCR, 0x33, CR33); 10580 outSISIDXREG(SISCR, 0x35, CR35); 10581 setSISIDXREG(SISCR, 0x38, 0xf8, CR38); 10582 outSISIDXREG(SISCR, 0x39, CR39); 10583 10584 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, SISVERBLEVEL, 10585 "After: CR30=0x%02x,CR31=0x%02x,CR33=0x%02x,CR35=0x%02x,CR38=%02x\n", 10586 CR30, CR31, CR33, CR35, CR38); 10587 10588 } else { 10589 10590 outSISIDXREG(SISCR, 0x30, CR30); 10591 outSISIDXREG(SISCR, 0x31, CR31); 10592 outSISIDXREG(SISCR, 0x33, CR33); 10593 if(temp) { 10594 outSISIDXREG(SISCR, temp, CR38); 10595 } 10596 if(pSiS->VGAEngine == SIS_315_VGA) { 10597 outSISIDXREG(SISCR, 0x3b, CR3B); 10598 outSISIDXREG(SISCR, 0x79, CR79); 10599 } 10600 10601 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, SISVERBLEVEL, 10602 "After: CR30=0x%02x,CR31=0x%02x,CR33=0x%02x,CR%02x=%02x\n", 10603 CR30, CR31, CR33, temp, CR38); 10604 } 10605 10606 pSiS->SiS_Pr->SiS_UseOEM = pSiS->OptUseOEM; 10607 10608 /* Enable TurboQueue */ 10609#ifdef SISVRAMQ 10610 if(pSiS->VGAEngine != SIS_315_VGA) 10611#endif 10612 SiSEnableTurboQueue(pScrn); 10613 10614 if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE)) { 10615 /* Switch on CRT1 for modes that require the bridge in SlaveMode */ 10616 andSISIDXREG(SISSR,0x1f,0x3f); 10617 inSISIDXREG(SISCR, 0x17, CR17); 10618 if(!(CR17 & 0x80)) { 10619 orSISIDXREG(SISCR, 0x17, 0x80); 10620 outSISIDXREG(SISSR, 0x00, 0x01); 10621 usleep(10000); 10622 outSISIDXREG(SISSR, 0x00, 0x03); 10623 } 10624 } 10625} 10626 10627/* Functions for adjusting various TV settings */ 10628 10629/* These are used by the PostSetMode() functions as well as 10630 * the display properties tool SiSCtrl. 10631 * 10632 * There is each a Set and a Get routine. The Set functions 10633 * take a value of the same range as the corresponding option. 10634 * The Get routines return a value of the same range (although 10635 * not necessarily the same value as previously set because 10636 * of the lower resolution of the respective setting compared 10637 * to the valid range). 10638 * The Get routines return -2 on error (eg. hardware does not 10639 * support this setting). 10640 * Note: The x and y positioning routines accept a position 10641 * RELATIVE to the default position. All other routines 10642 * take ABSOLUTE values. 10643 * 10644 * The Set functions will store the property regardless if TV is 10645 * currently used or not and if the hardware supports the property 10646 * or not. The Get routines will return this stored 10647 * value if TV is not currently used (because the register does 10648 * not contain the correct value then) or if the hardware supports 10649 * the respective property. This should make it easier for the 10650 * display property tool because it does not have to know the 10651 * hardware features. 10652 * 10653 * All the routines are dual head aware. It does not matter 10654 * if the function is called from the CRT1 or CRT2 session. 10655 * The values will be in pSiSEnt anyway, and read from there 10656 * if we're running dual head. 10657 */ 10658 10659void SiS_SetCHTVlumabandwidthcvbs(ScrnInfoPtr pScrn, int val) 10660{ 10661 SISPtr pSiS = SISPTR(pScrn); 10662#ifdef SISDUALHEAD 10663 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10664#endif 10665 10666 pSiS->chtvlumabandwidthcvbs = val; 10667#ifdef SISDUALHEAD 10668 if(pSiSEnt) pSiSEnt->chtvlumabandwidthcvbs = val; 10669#endif 10670 10671 if(!(pSiS->VBFlags & CRT2_TV)) return; 10672 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10673 10674#ifdef UNLOCK_ALWAYS 10675 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10676#endif 10677 10678 switch(pSiS->ChrontelType) { 10679 case CHRONTEL_700x: 10680 val /= 8; 10681 if((val == 0) || (val == 1)) { 10682 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, val, 0xFE); 10683 } 10684 break; 10685 case CHRONTEL_701x: 10686 val /= 4; 10687 if((val >= 0) && (val <= 3)) { 10688 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, val, 0xFC); 10689 } 10690 break; 10691 } 10692} 10693 10694int SiS_GetCHTVlumabandwidthcvbs(ScrnInfoPtr pScrn) 10695{ 10696 SISPtr pSiS = SISPTR(pScrn); 10697#ifdef SISDUALHEAD 10698 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10699#endif 10700 10701 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10702#ifdef SISDUALHEAD 10703 if(pSiSEnt && pSiS->DualHeadMode) 10704 return (int)pSiSEnt->chtvlumabandwidthcvbs; 10705 else 10706#endif 10707 return (int)pSiS->chtvlumabandwidthcvbs; 10708 } else { 10709#ifdef UNLOCK_ALWAYS 10710 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10711#endif 10712 switch(pSiS->ChrontelType) { 10713 case CHRONTEL_700x: 10714 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x01) * 8); 10715 case CHRONTEL_701x: 10716 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x03) * 4); 10717 default: 10718 return (int)pSiS->chtvlumabandwidthcvbs; 10719 } 10720 } 10721} 10722 10723void SiS_SetCHTVlumabandwidthsvideo(ScrnInfoPtr pScrn, int val) 10724{ 10725 SISPtr pSiS = SISPTR(pScrn); 10726#ifdef SISDUALHEAD 10727 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10728#endif 10729 10730 pSiS->chtvlumabandwidthsvideo = val; 10731#ifdef SISDUALHEAD 10732 if(pSiSEnt) pSiSEnt->chtvlumabandwidthsvideo = val; 10733#endif 10734 10735 if(!(pSiS->VBFlags & CRT2_TV)) return; 10736 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10737 10738#ifdef UNLOCK_ALWAYS 10739 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10740#endif 10741 10742 switch(pSiS->ChrontelType) { 10743 case CHRONTEL_700x: 10744 val /= 6; 10745 if((val >= 0) && (val <= 2)) { 10746 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, (val << 1), 0xF9); 10747 } 10748 break; 10749 case CHRONTEL_701x: 10750 val /= 4; 10751 if((val >= 0) && (val <= 3)) { 10752 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, (val << 2), 0xF3); 10753 } 10754 break; 10755 } 10756} 10757 10758int SiS_GetCHTVlumabandwidthsvideo(ScrnInfoPtr pScrn) 10759{ 10760 SISPtr pSiS = SISPTR(pScrn); 10761#ifdef SISDUALHEAD 10762 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10763#endif 10764 10765 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10766#ifdef SISDUALHEAD 10767 if(pSiSEnt && pSiS->DualHeadMode) 10768 return (int)pSiSEnt->chtvlumabandwidthsvideo; 10769 else 10770#endif 10771 return (int)pSiS->chtvlumabandwidthsvideo; 10772 } else { 10773#ifdef UNLOCK_ALWAYS 10774 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10775#endif 10776 switch(pSiS->ChrontelType) { 10777 case CHRONTEL_700x: 10778 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x06) >> 1) * 6); 10779 case CHRONTEL_701x: 10780 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x0c) >> 2) * 4); 10781 default: 10782 return (int)pSiS->chtvlumabandwidthsvideo; 10783 } 10784 } 10785} 10786 10787void SiS_SetCHTVlumaflickerfilter(ScrnInfoPtr pScrn, int val) 10788{ 10789 SISPtr pSiS = SISPTR(pScrn); 10790#ifdef SISDUALHEAD 10791 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10792#endif 10793 10794 pSiS->chtvlumaflickerfilter = val; 10795#ifdef SISDUALHEAD 10796 if(pSiSEnt) pSiSEnt->chtvlumaflickerfilter = val; 10797#endif 10798 10799 if(!(pSiS->VBFlags & CRT2_TV)) return; 10800 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10801 10802#ifdef UNLOCK_ALWAYS 10803 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10804#endif 10805 10806 switch(pSiS->ChrontelType) { 10807 case CHRONTEL_700x: 10808 val /= 6; 10809 if((val >= 0) && (val <= 2)) { 10810 UShort reg = 0; 10811 reg = SiS_GetCH70xx(pSiS->SiS_Pr, 0x01); 10812 reg = (reg & 0xf0) | ((reg & 0x0c) >> 2) | (val << 2); 10813 SiS_SetCH70xx(pSiS->SiS_Pr, 0x01, reg); 10814 } 10815 break; 10816 case CHRONTEL_701x: 10817 val /= 4; 10818 if((val >= 0) && (val <= 3)) { 10819 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x01, (val << 2), 0xF3); 10820 } 10821 break; 10822 } 10823} 10824 10825int SiS_GetCHTVlumaflickerfilter(ScrnInfoPtr pScrn) 10826{ 10827 SISPtr pSiS = SISPTR(pScrn); 10828#ifdef SISDUALHEAD 10829 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10830#endif 10831 10832 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10833#ifdef SISDUALHEAD 10834 if(pSiSEnt && pSiS->DualHeadMode) 10835 return (int)pSiSEnt->chtvlumaflickerfilter; 10836 else 10837#endif 10838 return (int)pSiS->chtvlumaflickerfilter; 10839 } else { 10840#ifdef UNLOCK_ALWAYS 10841 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10842#endif 10843 switch(pSiS->ChrontelType) { 10844 case CHRONTEL_700x: 10845 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x03) * 6); 10846 case CHRONTEL_701x: 10847 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x0c) >> 2) * 4); 10848 default: 10849 return (int)pSiS->chtvlumaflickerfilter; 10850 } 10851 } 10852} 10853 10854void SiS_SetCHTVchromabandwidth(ScrnInfoPtr pScrn, int val) 10855{ 10856 SISPtr pSiS = SISPTR(pScrn); 10857#ifdef SISDUALHEAD 10858 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10859#endif 10860 10861 pSiS->chtvchromabandwidth = val; 10862#ifdef SISDUALHEAD 10863 if(pSiSEnt) pSiSEnt->chtvchromabandwidth = val; 10864#endif 10865 10866 if(!(pSiS->VBFlags & CRT2_TV)) return; 10867 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10868 10869#ifdef UNLOCK_ALWAYS 10870 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10871#endif 10872 10873 switch(pSiS->ChrontelType) { 10874 case CHRONTEL_700x: 10875 val /= 4; 10876 if((val >= 0) && (val <= 3)) { 10877 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, (val << 4), 0xCF); 10878 } 10879 break; 10880 case CHRONTEL_701x: 10881 val /= 8; 10882 if((val >= 0) && (val <= 1)) { 10883 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, (val << 4), 0xEF); 10884 } 10885 break; 10886 } 10887} 10888 10889int SiS_GetCHTVchromabandwidth(ScrnInfoPtr pScrn) 10890{ 10891 SISPtr pSiS = SISPTR(pScrn); 10892#ifdef SISDUALHEAD 10893 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10894#endif 10895 10896 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10897#ifdef SISDUALHEAD 10898 if(pSiSEnt && pSiS->DualHeadMode) 10899 return (int)pSiSEnt->chtvchromabandwidth; 10900 else 10901#endif 10902 return (int)pSiS->chtvchromabandwidth; 10903 } else { 10904#ifdef UNLOCK_ALWAYS 10905 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10906#endif 10907 switch(pSiS->ChrontelType) { 10908 case CHRONTEL_700x: 10909 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x30) >> 4) * 4); 10910 case CHRONTEL_701x: 10911 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x10) >> 4) * 8); 10912 default: 10913 return (int)pSiS->chtvchromabandwidth; 10914 } 10915 } 10916} 10917 10918void SiS_SetCHTVchromaflickerfilter(ScrnInfoPtr pScrn, int val) 10919{ 10920 SISPtr pSiS = SISPTR(pScrn); 10921#ifdef SISDUALHEAD 10922 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10923#endif 10924 10925 pSiS->chtvchromaflickerfilter = val; 10926#ifdef SISDUALHEAD 10927 if(pSiSEnt) pSiSEnt->chtvchromaflickerfilter = val; 10928#endif 10929 10930 if(!(pSiS->VBFlags & CRT2_TV)) return; 10931 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10932 10933#ifdef UNLOCK_ALWAYS 10934 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10935#endif 10936 10937 switch(pSiS->ChrontelType) { 10938 case CHRONTEL_700x: 10939 val /= 6; 10940 if((val >= 0) && (val <= 2)) { 10941 UShort reg = 0; 10942 reg = SiS_GetCH70xx(pSiS->SiS_Pr, 0x01); 10943 reg = (reg & 0xc0) | ((reg & 0x0c) >> 2) | ((reg & 0x03) << 2) | (val << 4); 10944 SiS_SetCH70xx(pSiS->SiS_Pr, 0x01, reg); 10945 } 10946 break; 10947 case CHRONTEL_701x: 10948 val /= 4; 10949 if((val >= 0) && (val <= 3)) { 10950 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x01, (val << 4), 0xCF); 10951 } 10952 break; 10953 } 10954} 10955 10956int SiS_GetCHTVchromaflickerfilter(ScrnInfoPtr pScrn) 10957{ 10958 SISPtr pSiS = SISPTR(pScrn); 10959#ifdef SISDUALHEAD 10960 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10961#endif 10962 10963 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10964#ifdef SISDUALHEAD 10965 if(pSiSEnt && pSiS->DualHeadMode) 10966 return (int)pSiSEnt->chtvchromaflickerfilter; 10967 else 10968#endif 10969 return (int)pSiS->chtvchromaflickerfilter; 10970 } else { 10971#ifdef UNLOCK_ALWAYS 10972 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10973#endif 10974 switch(pSiS->ChrontelType) { 10975 case CHRONTEL_700x: 10976 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x30) >> 4) * 6); 10977 case CHRONTEL_701x: 10978 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x30) >> 4) * 4); 10979 default: 10980 return (int)pSiS->chtvchromaflickerfilter; 10981 } 10982 } 10983} 10984 10985void SiS_SetCHTVcvbscolor(ScrnInfoPtr pScrn, int val) 10986{ 10987 SISPtr pSiS = SISPTR(pScrn); 10988#ifdef SISDUALHEAD 10989 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10990#endif 10991 10992 pSiS->chtvcvbscolor = val ? 1 : 0; 10993#ifdef SISDUALHEAD 10994 if(pSiSEnt) pSiSEnt->chtvcvbscolor = pSiS->chtvcvbscolor; 10995#endif 10996 10997 if(!(pSiS->VBFlags & CRT2_TV)) return; 10998 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10999 11000#ifdef UNLOCK_ALWAYS 11001 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11002#endif 11003 11004 switch(pSiS->ChrontelType) { 11005 case CHRONTEL_700x: 11006 if(!val) SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, 0x40, 0x00); 11007 else SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, 0x00, ~0x40); 11008 break; 11009 case CHRONTEL_701x: 11010 if(!val) SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, 0x00, ~0x20); 11011 else SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, 0x20, 0x00); 11012 break; 11013 } 11014} 11015 11016int SiS_GetCHTVcvbscolor(ScrnInfoPtr pScrn) 11017{ 11018 SISPtr pSiS = SISPTR(pScrn); 11019#ifdef SISDUALHEAD 11020 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11021#endif 11022 11023 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 11024#ifdef SISDUALHEAD 11025 if(pSiSEnt && pSiS->DualHeadMode) 11026 return (int)pSiSEnt->chtvcvbscolor; 11027 else 11028#endif 11029 return (int)pSiS->chtvcvbscolor; 11030 } else { 11031#ifdef UNLOCK_ALWAYS 11032 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11033#endif 11034 switch(pSiS->ChrontelType) { 11035 case CHRONTEL_700x: 11036 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x40) >> 6) ^ 0x01); 11037 case CHRONTEL_701x: 11038 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x20) >> 5) ^ 0x01); 11039 default: 11040 return (int)pSiS->chtvcvbscolor; 11041 } 11042 } 11043} 11044 11045void SiS_SetCHTVtextenhance(ScrnInfoPtr pScrn, int val) 11046{ 11047 SISPtr pSiS = SISPTR(pScrn); 11048#ifdef SISDUALHEAD 11049 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11050#endif 11051 11052 pSiS->chtvtextenhance = val; 11053#ifdef SISDUALHEAD 11054 if(pSiSEnt) pSiSEnt->chtvtextenhance = val; 11055#endif 11056 11057 if(!(pSiS->VBFlags & CRT2_TV)) return; 11058 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 11059 11060#ifdef UNLOCK_ALWAYS 11061 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11062#endif 11063 11064 switch(pSiS->ChrontelType) { 11065 case CHRONTEL_700x: 11066 val /= 6; 11067 if((val >= 0) && (val <= 2)) { 11068 UShort reg = 0; 11069 reg = SiS_GetCH70xx(pSiS->SiS_Pr, 0x01); 11070 reg = (reg & 0xf0) | ((reg & 0x03) << 2) | val; 11071 SiS_SetCH70xx(pSiS->SiS_Pr, 0x01, reg); 11072 } 11073 break; 11074 case CHRONTEL_701x: 11075 val /= 2; 11076 if((val >= 0) && (val <= 7)) { 11077 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, val, 0xF8); 11078 } 11079 break; 11080 } 11081} 11082 11083int SiS_GetCHTVtextenhance(ScrnInfoPtr pScrn) 11084{ 11085 SISPtr pSiS = SISPTR(pScrn); 11086#ifdef SISDUALHEAD 11087 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11088#endif 11089 11090 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 11091#ifdef SISDUALHEAD 11092 if(pSiSEnt && pSiS->DualHeadMode) 11093 return (int)pSiSEnt->chtvtextenhance; 11094 else 11095#endif 11096 return (int)pSiS->chtvtextenhance; 11097 } else { 11098#ifdef UNLOCK_ALWAYS 11099 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11100#endif 11101 switch(pSiS->ChrontelType) { 11102 case CHRONTEL_700x: 11103 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x0c) >> 2) * 6); 11104 case CHRONTEL_701x: 11105 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x07) * 2); 11106 default: 11107 return (int)pSiS->chtvtextenhance; 11108 } 11109 } 11110} 11111 11112void SiS_SetCHTVcontrast(ScrnInfoPtr pScrn, int val) 11113{ 11114 SISPtr pSiS = SISPTR(pScrn); 11115#ifdef SISDUALHEAD 11116 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11117#endif 11118 11119 pSiS->chtvcontrast = val; 11120#ifdef SISDUALHEAD 11121 if(pSiSEnt) pSiSEnt->chtvcontrast = val; 11122#endif 11123 11124 if(!(pSiS->VBFlags & CRT2_TV)) return; 11125 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 11126 11127#ifdef UNLOCK_ALWAYS 11128 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11129#endif 11130 11131 val /= 2; 11132 if((val >= 0) && (val <= 7)) { 11133 switch(pSiS->ChrontelType) { 11134 case CHRONTEL_700x: 11135 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x11, val, 0xF8); 11136 break; 11137 case CHRONTEL_701x: 11138 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x08, val, 0xF8); 11139 break; 11140 } 11141 SiS_DDC2Delay(pSiS->SiS_Pr, 1000); 11142 } 11143} 11144 11145int SiS_GetCHTVcontrast(ScrnInfoPtr pScrn) 11146{ 11147 SISPtr pSiS = SISPTR(pScrn); 11148#ifdef SISDUALHEAD 11149 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11150#endif 11151 11152 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 11153#ifdef SISDUALHEAD 11154 if(pSiSEnt && pSiS->DualHeadMode) 11155 return (int)pSiSEnt->chtvcontrast; 11156 else 11157#endif 11158 return (int)pSiS->chtvcontrast; 11159 } else { 11160#ifdef UNLOCK_ALWAYS 11161 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11162#endif 11163 switch(pSiS->ChrontelType) { 11164 case CHRONTEL_700x: 11165 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x11) & 0x07) * 2); 11166 case CHRONTEL_701x: 11167 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x08) & 0x07) * 2); 11168 default: 11169 return (int)pSiS->chtvcontrast; 11170 } 11171 } 11172} 11173 11174void SiS_SetSISTVedgeenhance(ScrnInfoPtr pScrn, int val) 11175{ 11176 SISPtr pSiS = SISPTR(pScrn); 11177#ifdef SISDUALHEAD 11178 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11179#endif 11180 11181 pSiS->sistvedgeenhance = val; 11182#ifdef SISDUALHEAD 11183 if(pSiSEnt) pSiSEnt->sistvedgeenhance = val; 11184#endif 11185 11186 if(!(pSiS->VBFlags2 & VB2_301)) return; 11187 if(!(pSiS->VBFlags & CRT2_TV)) return; 11188 11189#ifdef UNLOCK_ALWAYS 11190 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11191#endif 11192 11193 val /= 2; 11194 if((val >= 0) && (val <= 7)) { 11195 setSISIDXREG(SISPART2,0x3A, 0x1F, (val << 5)); 11196 } 11197} 11198 11199int SiS_GetSISTVedgeenhance(ScrnInfoPtr pScrn) 11200{ 11201 SISPtr pSiS = SISPTR(pScrn); 11202 int result = pSiS->sistvedgeenhance; 11203 UChar temp; 11204#ifdef SISDUALHEAD 11205 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11206 11207 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvedgeenhance; 11208#endif 11209 11210 if(!(pSiS->VBFlags2 & VB2_301)) return result; 11211 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11212 11213#ifdef UNLOCK_ALWAYS 11214 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11215#endif 11216 inSISIDXREG(SISPART2, 0x3a, temp); 11217 return(int)(((temp & 0xe0) >> 5) * 2); 11218} 11219 11220void SiS_SetSISTVantiflicker(ScrnInfoPtr pScrn, int val) 11221{ 11222 SISPtr pSiS = SISPTR(pScrn); 11223#ifdef SISDUALHEAD 11224 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11225#endif 11226 11227 pSiS->sistvantiflicker = val; 11228#ifdef SISDUALHEAD 11229 if(pSiSEnt) pSiSEnt->sistvantiflicker = val; 11230#endif 11231 11232 if(!(pSiS->VBFlags & CRT2_TV)) return; 11233 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11234 if(pSiS->VBFlags & TV_HIVISION) return; 11235 if((pSiS->VBFlags & TV_YPBPR) && 11236 (pSiS->VBFlags & (TV_YPBPR525P | TV_YPBPR625P | TV_YPBPR750P | TV_YPBPR1080I))) return; 11237 11238#ifdef UNLOCK_ALWAYS 11239 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11240#endif 11241 11242 /* Valid values: 0=off, 1=low, 2=med, 3=high, 4=adaptive */ 11243 if((val >= 0) && (val <= 4)) { 11244 setSISIDXREG(SISPART2,0x0A,0x8F, (val << 4)); 11245 } 11246} 11247 11248int SiS_GetSISTVantiflicker(ScrnInfoPtr pScrn) 11249{ 11250 SISPtr pSiS = SISPTR(pScrn); 11251 int result = pSiS->sistvantiflicker; 11252 UChar temp; 11253#ifdef SISDUALHEAD 11254 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11255 11256 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvantiflicker; 11257#endif 11258 11259 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return result; 11260 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11261 if(pSiS->VBFlags & TV_HIVISION) return result; 11262 if((pSiS->VBFlags & TV_YPBPR) && 11263 (pSiS->VBFlags & (TV_YPBPR525P | TV_YPBPR625P | TV_YPBPR750P | TV_YPBPR1080I))) return result; 11264 11265#ifdef UNLOCK_ALWAYS 11266 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11267#endif 11268 inSISIDXREG(SISPART2, 0x0a, temp); 11269 return(int)((temp & 0x70) >> 4); 11270} 11271 11272void SiS_SetSISTVsaturation(ScrnInfoPtr pScrn, int val) 11273{ 11274 SISPtr pSiS = SISPTR(pScrn); 11275#ifdef SISDUALHEAD 11276 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11277#endif 11278 11279 pSiS->sistvsaturation = val; 11280#ifdef SISDUALHEAD 11281 if(pSiSEnt) pSiSEnt->sistvsaturation = val; 11282#endif 11283 11284 if(!(pSiS->VBFlags & CRT2_TV)) return; 11285 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11286 if(pSiS->VBFlags2 & VB2_301) return; 11287 11288#ifdef UNLOCK_ALWAYS 11289 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11290#endif 11291 11292 val /= 2; 11293 if((val >= 0) && (val <= 7)) { 11294 setSISIDXREG(SISPART4,0x21,0xF8, val); 11295 } 11296} 11297 11298int SiS_GetSISTVsaturation(ScrnInfoPtr pScrn) 11299{ 11300 SISPtr pSiS = SISPTR(pScrn); 11301 int result = pSiS->sistvsaturation; 11302 UChar temp; 11303#ifdef SISDUALHEAD 11304 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11305 11306 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvsaturation; 11307#endif 11308 11309 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return result; 11310 if(pSiS->VBFlags2 & VB2_301) return result; 11311 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11312 11313#ifdef UNLOCK_ALWAYS 11314 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11315#endif 11316 inSISIDXREG(SISPART4, 0x21, temp); 11317 return(int)((temp & 0x07) * 2); 11318} 11319 11320void SiS_SetSISTVcolcalib(ScrnInfoPtr pScrn, int val, Bool coarse) 11321{ 11322 SISPtr pSiS = SISPTR(pScrn); 11323#ifdef SISDUALHEAD 11324 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11325#endif 11326 int ccoarse, cfine, cbase = pSiS->sistvccbase; 11327 /* UChar temp; */ 11328 11329#ifdef SISDUALHEAD 11330 if(pSiSEnt && pSiS->DualHeadMode) cbase = pSiSEnt->sistvccbase; 11331#endif 11332 11333 if(coarse) { 11334 pSiS->sistvcolcalibc = ccoarse = val; 11335 cfine = pSiS->sistvcolcalibf; 11336#ifdef SISDUALHEAD 11337 if(pSiSEnt) { 11338 pSiSEnt->sistvcolcalibc = val; 11339 if(pSiS->DualHeadMode) cfine = pSiSEnt->sistvcolcalibf; 11340 } 11341#endif 11342 } else { 11343 pSiS->sistvcolcalibf = cfine = val; 11344 ccoarse = pSiS->sistvcolcalibc; 11345#ifdef SISDUALHEAD 11346 if(pSiSEnt) { 11347 pSiSEnt->sistvcolcalibf = val; 11348 if(pSiS->DualHeadMode) ccoarse = pSiSEnt->sistvcolcalibc; 11349 } 11350#endif 11351 } 11352 11353 if(!(pSiS->VBFlags & CRT2_TV)) return; 11354 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11355 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return; 11356 11357#ifdef UNLOCK_ALWAYS 11358 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11359#endif 11360 11361 if((cfine >= -128) && (cfine <= 127) && (ccoarse >= -120) && (ccoarse <= 120)) { 11362 long finalcc = cbase + (((ccoarse * 256) + cfine) * 256); 11363 11364#if 0 11365 inSISIDXREG(SISPART4,0x1f,temp); 11366 if(!(temp & 0x01)) { 11367 if(pSiS->VBFlags & TV_NTSC) finalcc += 0x21ed8620; 11368 else if(pSiS->VBFlags & TV_PALM) finalcc += ?; 11369 else if(pSiS->VBFlags & TV_PALM) finalcc += ?; 11370 else finalcc += 0x2a05d300; 11371 } 11372#endif 11373 setSISIDXREG(SISPART2,0x31,0x80,((finalcc >> 24) & 0x7f)); 11374 outSISIDXREG(SISPART2,0x32,((finalcc >> 16) & 0xff)); 11375 outSISIDXREG(SISPART2,0x33,((finalcc >> 8) & 0xff)); 11376 outSISIDXREG(SISPART2,0x34,(finalcc & 0xff)); 11377 } 11378} 11379 11380int SiS_GetSISTVcolcalib(ScrnInfoPtr pScrn, Bool coarse) 11381{ 11382 SISPtr pSiS = SISPTR(pScrn); 11383#ifdef SISDUALHEAD 11384 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11385 11386 if(pSiSEnt && pSiS->DualHeadMode) 11387 if(coarse) return (int)pSiSEnt->sistvcolcalibc; 11388 else return (int)pSiSEnt->sistvcolcalibf; 11389 else 11390#endif 11391 if(coarse) return (int)pSiS->sistvcolcalibc; 11392 else return (int)pSiS->sistvcolcalibf; 11393} 11394 11395void SiS_SetSISTVcfilter(ScrnInfoPtr pScrn, int val) 11396{ 11397 SISPtr pSiS = SISPTR(pScrn); 11398#ifdef SISDUALHEAD 11399 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11400#endif 11401 11402 pSiS->sistvcfilter = val ? 1 : 0; 11403#ifdef SISDUALHEAD 11404 if(pSiSEnt) pSiSEnt->sistvcfilter = pSiS->sistvcfilter; 11405#endif 11406 11407 if(!(pSiS->VBFlags & CRT2_TV)) return; 11408 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11409 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return; 11410 11411#ifdef UNLOCK_ALWAYS 11412 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11413#endif 11414 11415 setSISIDXREG(SISPART2,0x30,~0x10,((pSiS->sistvcfilter << 4) & 0x10)); 11416} 11417 11418int SiS_GetSISTVcfilter(ScrnInfoPtr pScrn) 11419{ 11420 SISPtr pSiS = SISPTR(pScrn); 11421 int result = pSiS->sistvcfilter; 11422 UChar temp; 11423#ifdef SISDUALHEAD 11424 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11425 11426 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvcfilter; 11427#endif 11428 11429 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return result; 11430 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11431 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return result; 11432 11433#ifdef UNLOCK_ALWAYS 11434 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11435#endif 11436 inSISIDXREG(SISPART2, 0x30, temp); 11437 return (int)((temp & 0x10) ? 1 : 0); 11438} 11439 11440void SiS_SetSISTVyfilter(ScrnInfoPtr pScrn, int val) 11441{ 11442 SISPtr pSiS = SISPTR(pScrn); 11443#ifdef SISDUALHEAD 11444 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11445#endif 11446 UChar p35,p36,p37,p38,p48,p49,p4a,p30; 11447 int i,j; 11448 11449 pSiS->sistvyfilter = val; 11450#ifdef SISDUALHEAD 11451 if(pSiSEnt) pSiSEnt->sistvyfilter = pSiS->sistvyfilter; 11452#endif 11453 11454 if(!(pSiS->VBFlags & CRT2_TV)) return; 11455 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11456 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return; 11457 11458 p35 = pSiS->p2_35; p36 = pSiS->p2_36; 11459 p37 = pSiS->p2_37; p38 = pSiS->p2_38; 11460 p48 = pSiS->p2_48; p49 = pSiS->p2_49; 11461 p4a = pSiS->p2_4a; p30 = pSiS->p2_30; 11462#ifdef SISDUALHEAD 11463 if(pSiSEnt && pSiS->DualHeadMode) { 11464 p35 = pSiSEnt->p2_35; p36 = pSiSEnt->p2_36; 11465 p37 = pSiSEnt->p2_37; p38 = pSiSEnt->p2_38; 11466 p48 = pSiSEnt->p2_48; p49 = pSiSEnt->p2_49; 11467 p4a = pSiSEnt->p2_4a; p30 = pSiSEnt->p2_30; 11468 } 11469#endif 11470 p30 &= 0x20; 11471 11472#ifdef UNLOCK_ALWAYS 11473 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11474#endif 11475 11476 switch(pSiS->sistvyfilter) { 11477 case 0: 11478 andSISIDXREG(SISPART2,0x30,0xdf); 11479 break; 11480 case 1: 11481 outSISIDXREG(SISPART2,0x35,p35); 11482 outSISIDXREG(SISPART2,0x36,p36); 11483 outSISIDXREG(SISPART2,0x37,p37); 11484 outSISIDXREG(SISPART2,0x38,p38); 11485 if(!(pSiS->VBFlags2 & VB2_301)) { 11486 outSISIDXREG(SISPART2,0x48,p48); 11487 outSISIDXREG(SISPART2,0x49,p49); 11488 outSISIDXREG(SISPART2,0x4a,p4a); 11489 } 11490 setSISIDXREG(SISPART2,0x30,0xdf,p30); 11491 break; 11492 case 2: 11493 case 3: 11494 case 4: 11495 case 5: 11496 case 6: 11497 case 7: 11498 case 8: 11499 if(!(pSiS->VBFlags & (TV_PALM | TV_PALN | TV_NTSCJ))) { 11500 int yindex301 = -1, yindex301B = -1; 11501 UChar p3d4_34; 11502 11503 inSISIDXREG(SISCR,0x34,p3d4_34); 11504 11505 switch((p3d4_34 & 0x7f)) { 11506 case 0x59: /* 320x200 */ 11507 case 0x41: 11508 case 0x4f: 11509 case 0x50: /* 320x240 */ 11510 case 0x56: 11511 case 0x53: 11512 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 0 : 4; 11513 break; 11514 case 0x2f: /* 640x400 */ 11515 case 0x5d: 11516 case 0x5e: 11517 case 0x2e: /* 640x480 */ 11518 case 0x44: 11519 case 0x62: 11520 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 1 : 5; 11521 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 0 : 4; 11522 break; 11523 case 0x31: /* 720x480 */ 11524 case 0x33: 11525 case 0x35: 11526 case 0x32: /* 720x576 */ 11527 case 0x34: 11528 case 0x36: 11529 case 0x5f: /* 768x576 */ 11530 case 0x60: 11531 case 0x61: 11532 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 2 : 6; 11533 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 1 : 5; 11534 break; 11535 case 0x51: /* 400x300 */ 11536 case 0x57: 11537 case 0x54: 11538 case 0x30: /* 800x600 */ 11539 case 0x47: 11540 case 0x63: 11541 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 3 : 7; 11542 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 2 : 6; 11543 break; 11544 case 0x52: /* 512x384 */ 11545 case 0x58: 11546 case 0x5c: 11547 case 0x38: /* 1024x768 */ 11548 case 0x4a: 11549 case 0x64: 11550 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 3 : 7; 11551 break; 11552 } 11553 if(pSiS->VBFlags2 & VB2_301) { 11554 if(yindex301 >= 0) { 11555 for(i=0, j=0x35; i<=3; i++, j++) { 11556 outSISIDXREG(SISPART2,j,(SiSTVFilter301[yindex301].filter[pSiS->sistvyfilter-2][i])); 11557 } 11558 } 11559 } else { 11560 if(yindex301B >= 0) { 11561 for(i=0, j=0x35; i<=3; i++, j++) { 11562 outSISIDXREG(SISPART2,j,(SiSTVFilter301B[yindex301B].filter[pSiS->sistvyfilter-2][i])); 11563 } 11564 for(i=4, j=0x48; i<=6; i++, j++) { 11565 outSISIDXREG(SISPART2,j,(SiSTVFilter301B[yindex301B].filter[pSiS->sistvyfilter-2][i])); 11566 } 11567 } 11568 } 11569 orSISIDXREG(SISPART2,0x30,0x20); 11570 } 11571 } 11572} 11573 11574int SiS_GetSISTVyfilter(ScrnInfoPtr pScrn) 11575{ 11576 SISPtr pSiS = SISPTR(pScrn); 11577#ifdef SISDUALHEAD 11578 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11579 11580 if(pSiSEnt && pSiS->DualHeadMode) 11581 return (int)pSiSEnt->sistvyfilter; 11582 else 11583#endif 11584 return (int)pSiS->sistvyfilter; 11585} 11586 11587void SiS_SetSIS6326TVantiflicker(ScrnInfoPtr pScrn, int val) 11588{ 11589 SISPtr pSiS = SISPTR(pScrn); 11590 UChar tmp; 11591 11592 pSiS->sistvantiflicker = val; 11593 11594 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 11595 11596#ifdef UNLOCK_ALWAYS 11597 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11598#endif 11599 11600 tmp = SiS6326GetTVReg(pScrn,0x00); 11601 if(!(tmp & 0x04)) return; 11602 11603 /* Valid values: 0=off, 1=low, 2=med, 3=high, 4=adaptive */ 11604 if(val >= 0 && val <= 4) { 11605 tmp &= 0x1f; 11606 tmp |= (val << 5); 11607 SiS6326SetTVReg(pScrn,0x00,tmp); 11608 } 11609} 11610 11611int SiS_GetSIS6326TVantiflicker(ScrnInfoPtr pScrn) 11612{ 11613 SISPtr pSiS = SISPTR(pScrn); 11614 UChar tmp; 11615 11616 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 11617 return (int)pSiS->sistvantiflicker; 11618 } 11619 11620#ifdef UNLOCK_ALWAYS 11621 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11622#endif 11623 11624 tmp = SiS6326GetTVReg(pScrn,0x00); 11625 if(!(tmp & 0x04)) { 11626 return (int)pSiS->sistvantiflicker; 11627 } else { 11628 return (int)((tmp >> 5) & 0x07); 11629 } 11630} 11631 11632void SiS_SetSIS6326TVenableyfilter(ScrnInfoPtr pScrn, int val) 11633{ 11634 SISPtr pSiS = SISPTR(pScrn); 11635 UChar tmp; 11636 11637 if(val) val = 1; 11638 pSiS->sis6326enableyfilter = val; 11639 11640 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 11641 11642#ifdef UNLOCK_ALWAYS 11643 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11644#endif 11645 11646 tmp = SiS6326GetTVReg(pScrn,0x00); 11647 if(!(tmp & 0x04)) return; 11648 11649 tmp = SiS6326GetTVReg(pScrn,0x43); 11650 tmp &= ~0x10; 11651 tmp |= ((val & 0x01) << 4); 11652 SiS6326SetTVReg(pScrn,0x43,tmp); 11653} 11654 11655int SiS_GetSIS6326TVenableyfilter(ScrnInfoPtr pScrn) 11656{ 11657 SISPtr pSiS = SISPTR(pScrn); 11658 UChar tmp; 11659 11660 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 11661 return (int)pSiS->sis6326enableyfilter; 11662 } 11663 11664#ifdef UNLOCK_ALWAYS 11665 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11666#endif 11667 11668 tmp = SiS6326GetTVReg(pScrn,0x00); 11669 if(!(tmp & 0x04)) { 11670 return (int)pSiS->sis6326enableyfilter; 11671 } else { 11672 tmp = SiS6326GetTVReg(pScrn,0x43); 11673 return (int)((tmp >> 4) & 0x01); 11674 } 11675} 11676 11677void SiS_SetSIS6326TVyfilterstrong(ScrnInfoPtr pScrn, int val) 11678{ 11679 SISPtr pSiS = SISPTR(pScrn); 11680 UChar tmp; 11681 11682 if(val) val = 1; 11683 pSiS->sis6326yfilterstrong = val; 11684 11685 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 11686 11687#ifdef UNLOCK_ALWAYS 11688 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11689#endif 11690 11691 tmp = SiS6326GetTVReg(pScrn,0x00); 11692 if(!(tmp & 0x04)) return; 11693 11694 tmp = SiS6326GetTVReg(pScrn,0x43); 11695 if(tmp & 0x10) { 11696 tmp &= ~0x40; 11697 tmp |= ((val & 0x01) << 6); 11698 SiS6326SetTVReg(pScrn,0x43,tmp); 11699 } 11700} 11701 11702int SiS_GetSIS6326TVyfilterstrong(ScrnInfoPtr pScrn) 11703{ 11704 SISPtr pSiS = SISPTR(pScrn); 11705 UChar tmp; 11706 11707 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 11708 return (int)pSiS->sis6326yfilterstrong; 11709 } 11710 11711#ifdef UNLOCK_ALWAYS 11712 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11713#endif 11714 11715 tmp = SiS6326GetTVReg(pScrn,0x00); 11716 if(!(tmp & 0x04)) { 11717 return (int)pSiS->sis6326yfilterstrong; 11718 } else { 11719 tmp = SiS6326GetTVReg(pScrn,0x43); 11720 if(!(tmp & 0x10)) { 11721 return (int)pSiS->sis6326yfilterstrong; 11722 } else { 11723 return (int)((tmp >> 6) & 0x01); 11724 } 11725 } 11726} 11727 11728void SiS_SetTVxposoffset(ScrnInfoPtr pScrn, int val) 11729{ 11730 SISPtr pSiS = SISPTR(pScrn); 11731#ifdef SISDUALHEAD 11732 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11733#endif 11734 11735#ifdef UNLOCK_ALWAYS 11736 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11737#endif 11738 11739 pSiS->tvxpos = val; 11740#ifdef SISDUALHEAD 11741 if(pSiSEnt) pSiSEnt->tvxpos = val; 11742#endif 11743 11744 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 11745 11746 if(pSiS->VBFlags & CRT2_TV) { 11747 11748 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 11749 11750 int x = pSiS->tvx; 11751#ifdef SISDUALHEAD 11752 if(pSiSEnt && pSiS->DualHeadMode) x = pSiSEnt->tvx; 11753#endif 11754 switch(pSiS->ChrontelType) { 11755 case CHRONTEL_700x: 11756 if((val >= -32) && (val <= 32)) { 11757 x += val; 11758 if(x < 0) x = 0; 11759 SiS_SetCH700x(pSiS->SiS_Pr, 0x0a, (x & 0xff)); 11760 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD); 11761 } 11762 break; 11763 case CHRONTEL_701x: 11764 /* Not supported by hardware */ 11765 break; 11766 } 11767 11768 } else if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 11769 11770 if((val >= -32) && (val <= 32)) { 11771 11772 UChar p2_1f,p2_20,p2_2b,p2_42,p2_43; 11773 UShort temp; 11774 int mult; 11775 11776 p2_1f = pSiS->p2_1f; 11777 p2_20 = pSiS->p2_20; 11778 p2_2b = pSiS->p2_2b; 11779 p2_42 = pSiS->p2_42; 11780 p2_43 = pSiS->p2_43; 11781#ifdef SISDUALHEAD 11782 if(pSiSEnt && pSiS->DualHeadMode) { 11783 p2_1f = pSiSEnt->p2_1f; 11784 p2_20 = pSiSEnt->p2_20; 11785 p2_2b = pSiSEnt->p2_2b; 11786 p2_42 = pSiSEnt->p2_42; 11787 p2_43 = pSiSEnt->p2_43; 11788 } 11789#endif 11790 mult = 2; 11791 if(pSiS->VBFlags & TV_YPBPR) { 11792 if(pSiS->VBFlags & (TV_YPBPR1080I | TV_YPBPR750P)) { 11793 mult = 4; 11794 } 11795 } 11796 11797 temp = p2_1f | ((p2_20 & 0xf0) << 4); 11798 temp += (val * mult); 11799 p2_1f = temp & 0xff; 11800 p2_20 = (temp & 0xf00) >> 4; 11801 p2_2b = ((p2_2b & 0x0f) + (val * mult)) & 0x0f; 11802 temp = p2_43 | ((p2_42 & 0xf0) << 4); 11803 temp += (val * mult); 11804 p2_43 = temp & 0xff; 11805 p2_42 = (temp & 0xf00) >> 4; 11806 SISWaitRetraceCRT2(pScrn); 11807 outSISIDXREG(SISPART2,0x1f,p2_1f); 11808 setSISIDXREG(SISPART2,0x20,0x0F,p2_20); 11809 setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b); 11810 setSISIDXREG(SISPART2,0x42,0x0F,p2_42); 11811 outSISIDXREG(SISPART2,0x43,p2_43); 11812 } 11813 } 11814 } 11815 11816 } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { 11817 11818 if(pSiS->SiS6326Flags & SIS6326_TVDETECTED) { 11819 11820 UChar tmp; 11821 UShort temp1, temp2, temp3; 11822 11823 tmp = SiS6326GetTVReg(pScrn,0x00); 11824 if(tmp & 0x04) { 11825 11826 temp1 = pSiS->tvx1; 11827 temp2 = pSiS->tvx2; 11828 temp3 = pSiS->tvx3; 11829 if((val >= -16) && (val <= 16)) { 11830 if(val > 0) { 11831 temp1 += (val * 4); 11832 temp2 += (val * 4); 11833 while((temp1 > 0x0fff) || (temp2 > 0x0fff)) { 11834 temp1 -= 4; 11835 temp2 -= 4; 11836 } 11837 } else { 11838 val = -val; 11839 temp3 += (val * 4); 11840 while(temp3 > 0x03ff) { 11841 temp3 -= 4; 11842 } 11843 } 11844 } 11845 SiS6326SetTVReg(pScrn,0x3a,(temp1 & 0xff)); 11846 tmp = SiS6326GetTVReg(pScrn,0x3c); 11847 tmp &= 0xf0; 11848 tmp |= ((temp1 & 0x0f00) >> 8); 11849 SiS6326SetTVReg(pScrn,0x3c,tmp); 11850 SiS6326SetTVReg(pScrn,0x26,(temp2 & 0xff)); 11851 tmp = SiS6326GetTVReg(pScrn,0x27); 11852 tmp &= 0x0f; 11853 tmp |= ((temp2 & 0x0f00) >> 4); 11854 SiS6326SetTVReg(pScrn,0x27,tmp); 11855 SiS6326SetTVReg(pScrn,0x12,(temp3 & 0xff)); 11856 tmp = SiS6326GetTVReg(pScrn,0x13); 11857 tmp &= ~0xC0; 11858 tmp |= ((temp3 & 0x0300) >> 2); 11859 SiS6326SetTVReg(pScrn,0x13,tmp); 11860 } 11861 } 11862 } 11863} 11864 11865int SiS_GetTVxposoffset(ScrnInfoPtr pScrn) 11866{ 11867 SISPtr pSiS = SISPTR(pScrn); 11868#ifdef SISDUALHEAD 11869 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11870 11871 if(pSiSEnt && pSiS->DualHeadMode) 11872 return (int)pSiSEnt->tvxpos; 11873 else 11874#endif 11875 return (int)pSiS->tvxpos; 11876} 11877 11878void SiS_SetTVyposoffset(ScrnInfoPtr pScrn, int val) 11879{ 11880 SISPtr pSiS = SISPTR(pScrn); 11881#ifdef SISDUALHEAD 11882 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11883#endif 11884 11885#ifdef UNLOCK_ALWAYS 11886 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11887#endif 11888 11889 pSiS->tvypos = val; 11890#ifdef SISDUALHEAD 11891 if(pSiSEnt) pSiSEnt->tvypos = val; 11892#endif 11893 11894 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 11895 11896 if(pSiS->VBFlags & CRT2_TV) { 11897 11898 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 11899 11900 int y = pSiS->tvy; 11901#ifdef SISDUALHEAD 11902 if(pSiSEnt && pSiS->DualHeadMode) y = pSiSEnt->tvy; 11903#endif 11904 switch(pSiS->ChrontelType) { 11905 case CHRONTEL_700x: 11906 if((val >= -32) && (val <= 32)) { 11907 y -= val; 11908 if(y < 0) y = 0; 11909 SiS_SetCH700x(pSiS->SiS_Pr, 0x0b, (y & 0xff)); 11910 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE); 11911 } 11912 break; 11913 case CHRONTEL_701x: 11914 /* Not supported by hardware */ 11915 break; 11916 } 11917 11918 } else if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 11919 11920 if((val >= -32) && (val <= 32)) { 11921 char p2_01, p2_02; 11922 11923 if( (pSiS->VBFlags & TV_HIVISION) || 11924 ((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & (TV_YPBPR1080I|TV_YPBPR750P))) ) { 11925 val *= 2; 11926 } else { 11927 val /= 2; /* 4 */ 11928 } 11929 11930 p2_01 = pSiS->p2_01; 11931 p2_02 = pSiS->p2_02; 11932#ifdef SISDUALHEAD 11933 if(pSiSEnt && pSiS->DualHeadMode) { 11934 p2_01 = pSiSEnt->p2_01; 11935 p2_02 = pSiSEnt->p2_02; 11936 } 11937#endif 11938 p2_01 += val; /* val * 2 */ 11939 p2_02 += val; /* val * 2 */ 11940 if(!(pSiS->VBFlags & (TV_YPBPR | TV_HIVISION))) { 11941 while((p2_01 <= 0) || (p2_02 <= 0)) { 11942 p2_01 += 2; 11943 p2_02 += 2; 11944 } 11945 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR1080I)) { 11946 while(p2_01 <= 8) { 11947 p2_01 += 2; 11948 p2_02 += 2; 11949 } 11950 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR750P)) { 11951 while(p2_01 <= 10) { 11952 p2_01 += 2; 11953 p2_02 += 2; 11954 } 11955 } 11956 11957 SISWaitRetraceCRT2(pScrn); 11958 outSISIDXREG(SISPART2,0x01,p2_01); 11959 outSISIDXREG(SISPART2,0x02,p2_02); 11960 } 11961 } 11962 11963 } 11964 11965 } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { 11966 11967 if(pSiS->SiS6326Flags & SIS6326_TVDETECTED) { 11968 11969 UChar tmp; 11970 int temp1, limit; 11971 11972 tmp = SiS6326GetTVReg(pScrn,0x00); 11973 if(tmp & 0x04) { 11974 11975 if((val >= -16) && (val <= 16)) { 11976 temp1 = (UShort)pSiS->tvy1; 11977 limit = (pSiS->SiS6326Flags & SIS6326_TVPAL) ? 625 : 525; 11978 if(val > 0) { 11979 temp1 += (val * 4); 11980 if(temp1 > limit) temp1 -= limit; 11981 } else { 11982 val = -val; 11983 temp1 -= (val * 2); 11984 if(temp1 <= 0) temp1 += (limit -1); 11985 } 11986 SiS6326SetTVReg(pScrn,0x11,(temp1 & 0xff)); 11987 tmp = SiS6326GetTVReg(pScrn,0x13); 11988 tmp &= ~0x30; 11989 tmp |= ((temp1 & 0x300) >> 4); 11990 SiS6326SetTVReg(pScrn,0x13,tmp); 11991 if(temp1 == 1) tmp = 0x10; 11992 else { 11993 if(pSiS->SiS6326Flags & SIS6326_TVPAL) { 11994 if((temp1 <= 3) || (temp1 >= (limit - 2))) tmp = 0x08; 11995 else if(temp1 < 22) tmp = 0x02; 11996 else tmp = 0x04; 11997 } else { 11998 if((temp1 <= 5) || (temp1 >= (limit - 4))) tmp = 0x08; 11999 else if(temp1 < 19) tmp = 0x02; 12000 else tmp = 0x04; 12001 } 12002 } 12003 SiS6326SetTVReg(pScrn,0x21,tmp); 12004 } 12005 } 12006 } 12007 } 12008} 12009 12010int SiS_GetTVyposoffset(ScrnInfoPtr pScrn) 12011{ 12012 SISPtr pSiS = SISPTR(pScrn); 12013#ifdef SISDUALHEAD 12014 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12015 12016 if(pSiSEnt && pSiS->DualHeadMode) 12017 return (int)pSiSEnt->tvypos; 12018 else 12019#endif 12020 return (int)pSiS->tvypos; 12021} 12022 12023void SiS_SetTVxscale(ScrnInfoPtr pScrn, int val) 12024{ 12025 SISPtr pSiS = SISPTR(pScrn); 12026#ifdef SISDUALHEAD 12027 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12028#endif 12029 12030#ifdef UNLOCK_ALWAYS 12031 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12032#endif 12033 12034 pSiS->tvxscale = val; 12035#ifdef SISDUALHEAD 12036 if(pSiSEnt) pSiSEnt->tvxscale = val; 12037#endif 12038 12039 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 12040 12041 if((pSiS->VBFlags & CRT2_TV) && (pSiS->VBFlags2 & VB2_SISBRIDGE)) { 12042 12043 if((val >= -16) && (val <= 16)) { 12044 12045 UChar p2_44,p2_45,p2_46; 12046 int scalingfactor, mult; 12047 12048 p2_44 = pSiS->p2_44; 12049 p2_45 = pSiS->p2_45 & 0x3f; 12050 p2_46 = pSiS->p2_46 & 0x07; 12051#ifdef SISDUALHEAD 12052 if(pSiSEnt && pSiS->DualHeadMode) { 12053 p2_44 = pSiSEnt->p2_44; 12054 p2_45 = pSiSEnt->p2_45 & 0x3f; 12055 p2_46 = pSiSEnt->p2_46 & 0x07; 12056 } 12057#endif 12058 scalingfactor = (p2_46 << 13) | ((p2_45 & 0x1f) << 8) | p2_44; 12059 12060 mult = 64; 12061 if(pSiS->VBFlags & TV_YPBPR) { 12062 if(pSiS->VBFlags & TV_YPBPR1080I) { 12063 mult = 190; 12064 } else if(pSiS->VBFlags & TV_YPBPR750P) { 12065 mult = 360; 12066 } 12067 } else if(pSiS->VBFlags & TV_HIVISION) { 12068 mult = 190; 12069 } 12070 12071 if(val < 0) { 12072 p2_45 &= 0xdf; 12073 scalingfactor += ((-val) * mult); 12074 if(scalingfactor > 0xffff) scalingfactor = 0xffff; 12075 } else if(val > 0) { 12076 p2_45 &= 0xdf; 12077 scalingfactor -= (val * mult); 12078 if(scalingfactor < 1) scalingfactor = 1; 12079 } 12080 12081 p2_44 = scalingfactor & 0xff; 12082 p2_45 &= 0xe0; 12083 p2_45 |= ((scalingfactor >> 8) & 0x1f); 12084 p2_46 = ((scalingfactor >> 13) & 0x07); 12085 12086 SISWaitRetraceCRT2(pScrn); 12087 outSISIDXREG(SISPART2,0x44,p2_44); 12088 setSISIDXREG(SISPART2,0x45,0xC0,p2_45); 12089 if(!(pSiS->VBFlags2 & VB2_301)) { 12090 setSISIDXREG(SISPART2,0x46,0xF8,p2_46); 12091 } 12092 12093 } 12094 12095 } 12096 12097 } 12098} 12099 12100int SiS_GetTVxscale(ScrnInfoPtr pScrn) 12101{ 12102 SISPtr pSiS = SISPTR(pScrn); 12103#ifdef SISDUALHEAD 12104 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12105 12106 if(pSiSEnt && pSiS->DualHeadMode) 12107 return (int)pSiSEnt->tvxscale; 12108 else 12109#endif 12110 return (int)pSiS->tvxscale; 12111} 12112 12113void SiS_SetTVyscale(ScrnInfoPtr pScrn, int val) 12114{ 12115 SISPtr pSiS = SISPTR(pScrn); 12116#ifdef SISDUALHEAD 12117 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12118#endif 12119 12120#ifdef UNLOCK_ALWAYS 12121 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12122#endif 12123 12124 if(val < -4) val = -4; 12125 if(val > 3) val = 3; 12126 12127 pSiS->tvyscale = val; 12128#ifdef SISDUALHEAD 12129 if(pSiSEnt) pSiSEnt->tvyscale = val; 12130#endif 12131 12132 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 12133 12134 if((pSiS->VBFlags & CRT2_TV) && (pSiS->VBFlags2 & VB2_SISBRIDGE)) { 12135 12136 int srindex = -1, newvde, i = 0, j, vlimit, temp, vdediv; 12137 int hdclk = 0; 12138 UChar p3d4_34; 12139 Bool found = FALSE; 12140 Bool usentsc = FALSE; 12141 Bool is750p = FALSE; 12142 Bool is1080i = FALSE; 12143 Bool skipmoveup = FALSE; 12144 12145 SiS_UnLockCRT2(pSiS->SiS_Pr); 12146 12147 if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR525P)) { 12148 vlimit = 525 - 7; 12149 vdediv = 1; 12150 usentsc = TRUE; 12151 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR625P)) { 12152 vlimit = 625 - 7; 12153 vdediv = 1; 12154 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR750P)) { 12155 vlimit = 750 - 7; 12156 vdediv = 1; 12157 is750p = TRUE; 12158 } else if(((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR1080I)) || 12159 (pSiS->VBFlags & TV_HIVISION)) { 12160 vlimit = (1125 - 7) / 2; 12161 vdediv = 2; 12162 is1080i = TRUE; 12163 } else { 12164 if( ((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR525I)) || 12165 ((!(pSiS->VBFlags & TV_YPBPR)) && (pSiS->VBFlags & (TV_NTSC | TV_PALM))) ) { 12166 usentsc = TRUE; 12167 } 12168 vlimit = usentsc ? 259 : 309; 12169 vdediv = 2; 12170 } 12171 12172 inSISIDXREG(SISCR,0x34,p3d4_34); 12173 12174 switch((p3d4_34 & 0x7f)) { 12175 case 0x50: /* 320x240 */ 12176 case 0x56: 12177 case 0x53: 12178 hdclk = 1; 12179 /* fall through */ 12180 case 0x2e: /* 640x480 */ 12181 case 0x44: 12182 case 0x62: 12183 if(is1080i) { 12184 srindex = 98; 12185 } else if(is750p) { 12186 srindex = 42; 12187 } else { 12188 srindex = usentsc ? 0 : 21; 12189 } 12190 break; 12191 case 0x31: /* 720x480 */ 12192 case 0x33: 12193 case 0x35: 12194 if(is1080i) { 12195 /* n/a */ 12196 } else if(is750p) { 12197 srindex = 49; 12198 } else { 12199 srindex = usentsc ? 7 : 21; 12200 } 12201 break; 12202 case 0x32: /* 720x576 */ 12203 case 0x34: 12204 case 0x36: 12205 case 0x5f: /* 768x576 */ 12206 case 0x60: 12207 case 0x61: 12208 if(is1080i) { 12209 /* n/a */ 12210 } else if(is750p) { 12211 srindex = 56; 12212 } else { 12213 srindex = usentsc ? 147 : 28; 12214 } 12215 break; 12216 case 0x70: /* 800x480 */ 12217 case 0x7a: 12218 case 0x76: 12219 if(is1080i) { 12220 srindex = 105; 12221 } else if(is750p) { 12222 srindex = 63; 12223 } else { 12224 srindex = usentsc ? 175 : 21; 12225 } 12226 break; 12227 case 0x51: /* 400x300 - hdclk mode */ 12228 case 0x57: 12229 case 0x54: 12230 hdclk = 1; 12231 /* fall through */ 12232 case 0x30: /* 800x600 */ 12233 case 0x47: 12234 case 0x63: 12235 if(is1080i) { 12236 srindex = 112; 12237 } else if(is750p) { 12238 srindex = 70; 12239 } else { 12240 srindex = usentsc ? 14 : 35; 12241 } 12242 break; 12243 case 0x1d: /* 960x540 */ 12244 case 0x1e: 12245 case 0x1f: 12246 if(is1080i) { 12247 srindex = 196; 12248 skipmoveup = TRUE; 12249 } 12250 break; 12251 case 0x20: /* 960x600 */ 12252 case 0x21: 12253 case 0x22: 12254 if(pSiS->VGAEngine == SIS_315_VGA && is1080i) { 12255 srindex = 203; 12256 } 12257 break; 12258 case 0x71: /* 1024x576 */ 12259 case 0x74: 12260 case 0x77: 12261 if(is1080i) { 12262 srindex = 119; 12263 } else if(is750p) { 12264 srindex = 77; 12265 } else { 12266 srindex = usentsc ? 182 : 189; 12267 } 12268 break; 12269 case 0x52: /* 512x384 */ 12270 case 0x58: 12271 case 0x5c: 12272 hdclk = 1; 12273 /* fall through */ 12274 case 0x38: /* 1024x768 */ 12275 case 0x4a: 12276 case 0x64: 12277 if(is1080i) { 12278 srindex = 126; 12279 } else if(is750p) { 12280 srindex = 84; 12281 } else if(!usentsc) { 12282 srindex = 154; 12283 } else if(vdediv == 1) { 12284 if(!hdclk) srindex = 168; 12285 } else { 12286 if(!hdclk) srindex = 161; 12287 } 12288 break; 12289 case 0x79: /* 1280x720 */ 12290 case 0x75: 12291 case 0x78: 12292 if(is1080i) { 12293 srindex = 133; 12294 } else if(is750p) { 12295 srindex = 91; 12296 } 12297 break; 12298 case 0x3a: /* 1280x1024 */ 12299 case 0x4d: 12300 case 0x65: 12301 if(is1080i) { 12302 srindex = 140; 12303 } 12304 break; 12305 } 12306 12307 if(srindex < 0) return; 12308 12309 if(pSiS->tvyscale != 0) { 12310 for(j = 0; j <= 1; j++) { 12311 for(i = 0; i <= 6; i++) { 12312 if(SiSTVVScale[srindex+i].sindex == pSiS->tvyscale) { 12313 found = TRUE; 12314 break; 12315 } 12316 } 12317 if(found) break; 12318 if(pSiS->tvyscale > 0) pSiS->tvyscale--; 12319 else pSiS->tvyscale++; 12320 } 12321 } 12322 12323#ifdef SISDUALHEAD 12324 if(pSiSEnt) pSiSEnt->tvyscale = pSiS->tvyscale; 12325#endif 12326 12327 if(pSiS->tvyscale == 0) { 12328 UChar p2_0a = pSiS->p2_0a; 12329 UChar p2_2f = pSiS->p2_2f; 12330 UChar p2_30 = pSiS->p2_30; 12331 UChar p2_46 = pSiS->p2_46; 12332 UChar p2_47 = pSiS->p2_47; 12333 UChar p1scaling[9], p4scaling[9]; 12334 UChar *p2scaling; 12335 12336 for(i = 0; i < 9; i++) { 12337 p1scaling[i] = pSiS->scalingp1[i]; 12338 p4scaling[i] = pSiS->scalingp4[i]; 12339 } 12340 p2scaling = &pSiS->scalingp2[0]; 12341 12342#ifdef SISDUALHEAD 12343 if(pSiSEnt && pSiS->DualHeadMode) { 12344 p2_0a = pSiSEnt->p2_0a; 12345 p2_2f = pSiSEnt->p2_2f; 12346 p2_30 = pSiSEnt->p2_30; 12347 p2_46 = pSiSEnt->p2_46; 12348 p2_47 = pSiSEnt->p2_47; 12349 for(i = 0; i < 9; i++) { 12350 p1scaling[i] = pSiSEnt->scalingp1[i]; 12351 p4scaling[i] = pSiSEnt->scalingp4[i]; 12352 } 12353 p2scaling = &pSiSEnt->scalingp2[0]; 12354 } 12355#endif 12356 SISWaitRetraceCRT2(pScrn); 12357 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 12358 for(i = 0; i < 64; i++) { 12359 outSISIDXREG(SISPART2,(0xc0 + i),p2scaling[i]); 12360 } 12361 } 12362 for(i = 0; i < 9; i++) { 12363 outSISIDXREG(SISPART1,SiSScalingP1Regs[i],p1scaling[i]); 12364 } 12365 for(i = 0; i < 9; i++) { 12366 outSISIDXREG(SISPART4,SiSScalingP4Regs[i],p4scaling[i]); 12367 } 12368 12369 setSISIDXREG(SISPART2,0x0a,0x7f,(p2_0a & 0x80)); 12370 outSISIDXREG(SISPART2,0x2f,p2_2f); 12371 setSISIDXREG(SISPART2,0x30,0x3f,(p2_30 & 0xc0)); 12372 if(!(pSiS->VBFlags2 & VB2_301)) { 12373 setSISIDXREG(SISPART2,0x46,0x9f,(p2_46 & 0x60)); 12374 outSISIDXREG(SISPART2,0x47,p2_47); 12375 } 12376 12377 } else { 12378 12379 int realvde, myypos, watchdog = 32; 12380 unsigned short temp1, temp2, vgahde, vgaht, vgavt; 12381 int p1div = 1; 12382 ULong calctemp; 12383 12384 srindex += i; 12385 newvde = SiSTVVScale[srindex].ScaleVDE; 12386 realvde = SiSTVVScale[srindex].RealVDE; 12387 12388 if(vdediv == 1) p1div = 2; 12389 12390 if(!skipmoveup) { 12391 do { 12392 inSISIDXREG(SISPART2,0x01,temp); 12393 temp = vlimit - ((temp & 0x7f) / p1div); 12394 if((temp - (((newvde / vdediv) - 2) + 9)) > 0) break; 12395 myypos = pSiS->tvypos - 1; 12396#ifdef SISDUALHEAD 12397 if(pSiSEnt && pSiS->DualHeadMode) myypos = pSiSEnt->tvypos - 1; 12398#endif 12399 SiS_SetTVyposoffset(pScrn, myypos); 12400 } while(watchdog--); 12401 } 12402 12403 SISWaitRetraceCRT2(pScrn); 12404 12405 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 12406 SiS_CalcXTapScaler(pSiS->SiS_Pr, realvde, newvde, 4, FALSE); 12407 } 12408 12409 if(!(pSiS->VBFlags2 & VB2_301)) { 12410 temp = (newvde / vdediv) - 3; 12411 setSISIDXREG(SISPART2,0x46,0x9f,((temp & 0x0300) >> 3)); 12412 outSISIDXREG(SISPART2,0x47,(temp & 0xff)); 12413 } 12414 12415 inSISIDXREG(SISPART1,0x0a,temp1); 12416 inSISIDXREG(SISPART1,0x0c,temp2); 12417 vgahde = ((temp2 & 0xf0) << 4) | temp1; 12418 if(pSiS->VGAEngine == SIS_300_VGA) { 12419 vgahde -= 12; 12420 } else { 12421 vgahde -= 16; 12422 if(hdclk) vgahde <<= 1; 12423 } 12424 12425 vgaht = SiSTVVScale[srindex].reg[0]; 12426 temp1 = vgaht; 12427 if((pSiS->VGAEngine == SIS_315_VGA) && hdclk) temp1 >>= 1; 12428 temp1--; 12429 outSISIDXREG(SISPART1,0x08,(temp1 & 0xff)); 12430 setSISIDXREG(SISPART1,0x09,0x0f,((temp1 >> 4) & 0xf0)); 12431 12432 temp2 = (vgaht - vgahde) >> 2; 12433 if(pSiS->VGAEngine == SIS_300_VGA) { 12434 temp1 = vgahde + 12 + temp2; 12435 temp2 = temp1 + (temp2 << 1); 12436 } else { 12437 temp1 = vgahde; 12438 if(hdclk) { 12439 temp1 >>= 1; 12440 temp2 >>= 1; 12441 } 12442 temp2 >>= 1; 12443 temp1 = temp1 + 16 + temp2; 12444 temp2 = temp1 + temp2; 12445 } 12446 outSISIDXREG(SISPART1,0x0b,(temp1 & 0xff)); 12447 setSISIDXREG(SISPART1,0x0c,0xf0,((temp1 >> 8) & 0x0f)); 12448 outSISIDXREG(SISPART1,0x0d,(temp2 & 0xff)); 12449 12450 vgavt = SiSTVVScale[srindex].reg[1]; 12451 temp1 = vgavt - 1; 12452 if(pSiS->VGAEngine == SIS_315_VGA) temp1--; 12453 outSISIDXREG(SISPART1,0x0e,(temp1 & 0xff)); 12454 setSISIDXREG(SISPART1,0x12,0xf8,((temp1 >> 8 ) & 0x07)); 12455 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->ChipType >= SIS_661)) { 12456 temp1 = (vgavt + SiSTVVScale[srindex].RealVDE) >> 1; 12457 temp2 = ((vgavt - SiSTVVScale[srindex].RealVDE) >> 4) + temp1 + 1; 12458 } else { 12459 temp1 = (vgavt - SiSTVVScale[srindex].RealVDE) >> 2; 12460 temp2 = (temp1 < 4) ? 4 : temp1; 12461 temp1 += SiSTVVScale[srindex].RealVDE; 12462 temp2 = (temp2 >> 2) + temp1 + 1; 12463 } 12464 outSISIDXREG(SISPART1,0x10,(temp1 & 0xff)); 12465 setSISIDXREG(SISPART1,0x11,0x8f,((temp1 >> 4) & 0x70)); 12466 setSISIDXREG(SISPART1,0x11,0xf0,(temp2 & 0x0f)); 12467 12468 setSISIDXREG(SISPART2,0x0a,0x7f,((SiSTVVScale[srindex].reg[2] >> 8) & 0x80)); 12469 outSISIDXREG(SISPART2,0x2f,((newvde / vdediv) - 2)); 12470 setSISIDXREG(SISPART2,0x30,0x3f,((((newvde / vdediv) - 2) >> 2) & 0xc0)); 12471 12472 outSISIDXREG(SISPART4,0x13,(SiSTVVScale[srindex].reg[2] & 0xff)); 12473 outSISIDXREG(SISPART4,0x14,(SiSTVVScale[srindex].reg[3] & 0xff)); 12474 setSISIDXREG(SISPART4,0x15,0x7f,((SiSTVVScale[srindex].reg[3] >> 1) & 0x80)); 12475 12476 temp1 = vgaht - 1; 12477 outSISIDXREG(SISPART4,0x16,(temp1 & 0xff)); 12478 setSISIDXREG(SISPART4,0x15,0x87,((temp1 >> 5) & 0x78)); 12479 12480 temp1 = vgavt - 1; 12481 outSISIDXREG(SISPART4,0x17,(temp1 & 0xff)); 12482 setSISIDXREG(SISPART4,0x15,0xf8,((temp1 >> 8) & 0x07)); 12483 12484 outSISIDXREG(SISPART4,0x18,0x00); 12485 setSISIDXREG(SISPART4,0x19,0xf0,0x00); 12486 12487 inSISIDXREG(SISPART4,0x0e,temp1); 12488 if(is1080i) { 12489 if(!(temp1 & 0xe0)) newvde >>= 1; 12490 } 12491 12492 temp = 0x40; 12493 if(realvde <= newvde) temp = 0; 12494 else realvde -= newvde; 12495 12496 calctemp = (realvde * 256 * 1024) / newvde; 12497 if((realvde * 256 * 1024) % newvde) calctemp++; 12498 outSISIDXREG(SISPART4,0x1b,(calctemp & 0xff)); 12499 outSISIDXREG(SISPART4,0x1a,((calctemp >> 8) & 0xff)); 12500 setSISIDXREG(SISPART4,0x19,0x8f,(((calctemp >> 12) & 0x70) | temp)); 12501 } 12502 12503 } 12504 12505 } 12506} 12507 12508int SiS_GetTVyscale(ScrnInfoPtr pScrn) 12509{ 12510 SISPtr pSiS = SISPTR(pScrn); 12511#ifdef SISDUALHEAD 12512 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12513 12514 if(pSiSEnt && pSiS->DualHeadMode) 12515 return (int)pSiSEnt->tvyscale; 12516 else 12517#endif 12518 return (int)pSiS->tvyscale; 12519} 12520 12521void SiS_SetSISCRT1SaturationGain(ScrnInfoPtr pScrn, int val) 12522{ 12523 SISPtr pSiS = SISPTR(pScrn); 12524#ifdef SISDUALHEAD 12525 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12526#endif 12527 12528 pSiS->siscrt1satgain = val; 12529#ifdef SISDUALHEAD 12530 if(pSiSEnt) pSiSEnt->siscrt1satgain = val; 12531#endif 12532 12533 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_CRT1SATGAIN)) return; 12534 12535#ifdef UNLOCK_ALWAYS 12536 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12537#endif 12538 12539 if((val >= 0) && (val <= 7)) { 12540 setSISIDXREG(SISCR,0x53,0xE3, (val << 2)); 12541 } 12542} 12543 12544int SiS_GetSISCRT1SaturationGain(ScrnInfoPtr pScrn) 12545{ 12546 SISPtr pSiS = SISPTR(pScrn); 12547 int result = pSiS->siscrt1satgain; 12548 UChar temp; 12549#ifdef SISDUALHEAD 12550 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12551 12552 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->siscrt1satgain; 12553#endif 12554 12555 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_CRT1SATGAIN)) return result; 12556 12557#ifdef UNLOCK_ALWAYS 12558 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12559#endif 12560 inSISIDXREG(SISCR, 0x53, temp); 12561 return (int)((temp >> 2) & 0x07); 12562} 12563 12564/* Calc dotclock from registers */ 12565static int 12566SiSGetClockFromRegs(UChar sr2b, UChar sr2c) 12567{ 12568 float num, denum, postscalar, divider; 12569 int myclock; 12570 12571 divider = (sr2b & 0x80) ? 2.0 : 1.0; 12572 postscalar = (sr2c & 0x80) ? 12573 ( (((sr2c >> 5) & 0x03) == 0x02) ? 6.0 : 8.0 ) : 12574 ( ((sr2c >> 5) & 0x03) + 1.0 ); 12575 num = (sr2b & 0x7f) + 1.0; 12576 denum = (sr2c & 0x1f) + 1.0; 12577 myclock = (int)((14318 * (divider / postscalar) * (num / denum)) / 1000); 12578 return myclock; 12579} 12580 12581#ifdef SISDUALHEAD 12582static void 12583SiS_SetDHFlags(SISPtr pSiS, unsigned int misc, unsigned int sd2) 12584{ 12585 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12586 12587 if(pSiS->DualHeadMode) { 12588 if(pSiSEnt->pScrn_1) { 12589 SISPTR(pSiSEnt->pScrn_1)->MiscFlags |= misc; 12590 SISPTR(pSiSEnt->pScrn_1)->SiS_SD2_Flags |= sd2; 12591 } 12592 if(pSiSEnt->pScrn_2) { 12593 SISPTR(pSiSEnt->pScrn_2)->MiscFlags |= misc; 12594 SISPTR(pSiSEnt->pScrn_2)->SiS_SD2_Flags |= sd2; 12595 } 12596 } 12597} 12598#endif 12599 12600/* PostSetMode: 12601 * -) Disable CRT1 for saving bandwidth. This doesn't work with VESA; 12602 * VESA uses the bridge in SlaveMode and switching CRT1 off while 12603 * the bridge is in SlaveMode not that clever... 12604 * -) Check if overlay can be used (depending on dotclock) 12605 * -) Check if Panel Scaler is active on LVDS for overlay re-scaling 12606 * -) Save TV registers for further processing 12607 * -) Apply TV settings 12608 */ 12609static void 12610SiSPostSetMode(ScrnInfoPtr pScrn, SISRegPtr sisReg) 12611{ 12612 SISPtr pSiS = SISPTR(pScrn); 12613#ifdef SISDUALHEAD 12614 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12615#endif 12616 UChar usScratchCR17, sr2b, sr2c, tmpreg; 12617 int myclock1, myclock2, mycoldepth1, mycoldepth2, temp; 12618 Bool flag = FALSE; 12619 Bool doit = TRUE; 12620 Bool IsInSlaveMode; 12621 12622#ifdef TWDEBUG 12623 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 12624 "CRT1off is %d\n", pSiS->CRT1off); 12625#endif 12626 pSiS->CRT1isoff = pSiS->CRT1off; 12627 12628#ifdef UNLOCK_ALWAYS 12629 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12630#endif 12631 12632 SiSFixupSR11(pScrn); 12633 12634 IsInSlaveMode = SiSBridgeIsInSlaveMode(pScrn); 12635 12636 if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE)) { 12637 12638 if(pSiS->VBFlags != pSiS->VBFlags_backup) { 12639 pSiS->VBFlags = pSiS->VBFlags_backup; 12640 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 12641 "VBFlags restored to %0x\n", pSiS->VBFlags); 12642 } 12643 12644 /* -) We can't switch off CRT1 if bridge is in SlaveMode. 12645 * -) If we change to a SlaveMode-Mode (like 512x384), we 12646 * need to adapt VBFlags for eg. Xv. 12647 */ 12648#ifdef SISDUALHEAD 12649 if(!pSiS->DualHeadMode) { 12650#endif 12651 if(IsInSlaveMode) { 12652 doit = FALSE; 12653 temp = pSiS->VBFlags; 12654 pSiS->VBFlags &= (~VB_DISPMODE_SINGLE); 12655 pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_DISP1); 12656 if(temp != pSiS->VBFlags) { 12657 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 12658 "VBFlags changed to 0x%0x\n", pSiS->VBFlags); 12659 } 12660 } 12661#ifdef SISDUALHEAD 12662 } 12663#endif 12664 12665 if(pSiS->VGAEngine == SIS_315_VGA) { 12666 12667 if((pSiS->CRT1off) && (doit)) { 12668 orSISIDXREG(SISCR,pSiS->myCR63,0x40); 12669 orSISIDXREG(SISSR,0x1f,0xc0); 12670 andSISIDXREG(SISSR,0x07,~0x10); 12671 andSISIDXREG(SISSR,0x06,0xe2); 12672 andSISIDXREG(SISSR,0x31,0xcf); 12673 outSISIDXREG(SISSR,0x2b,0x1b); 12674 outSISIDXREG(SISSR,0x2c,0xe1); 12675 outSISIDXREG(SISSR,0x2d,0x01); 12676 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 12677 usleep(10000); 12678 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 12679 } else { 12680 andSISIDXREG(SISCR,pSiS->myCR63,0xBF); 12681 andSISIDXREG(SISSR,0x1f,0x3f); 12682 orSISIDXREG(SISSR,0x07,0x10); 12683 } 12684 12685 } else { 12686 12687 if(doit) { 12688 inSISIDXREG(SISCR, 0x17, usScratchCR17); 12689 if(pSiS->CRT1off) { 12690 if(usScratchCR17 & 0x80) { 12691 flag = TRUE; 12692 usScratchCR17 &= ~0x80; 12693 } 12694 orSISIDXREG(SISSR,0x1f,0xc0); 12695 } else { 12696 if(!(usScratchCR17 & 0x80)) { 12697 flag = TRUE; 12698 usScratchCR17 |= 0x80; 12699 } 12700 andSISIDXREG(SISSR,0x1f,0x3f); 12701 } 12702 /* Reset only if status changed */ 12703 if(flag) { 12704 outSISIDXREG(SISCR, 0x17, usScratchCR17); 12705 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 12706 usleep(10000); 12707 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 12708 } 12709 } 12710 } 12711 12712 } 12713 12714 /* Set bridge to "disable CRT2" mode if CRT2 is disabled, LCD-A is enabled */ 12715 /* (Not needed for CRT1=VGA since CRT2 will really be disabled then) */ 12716#ifdef SISDUALHEAD 12717 if(!pSiS->DualHeadMode) { 12718#endif 12719 if((pSiS->VGAEngine == SIS_315_VGA) && (pSiS->VBFlags2 & VB2_SISLCDABRIDGE)) { 12720 if((!pSiS->UseVESA) && (!(pSiS->VBFlags & CRT2_ENABLE)) && (pSiS->VBFlags & CRT1_LCDA)) { 12721 if(!IsInSlaveMode) { 12722 andSISIDXREG(SISPART4,0x0d,~0x07); 12723 } 12724 } 12725 } 12726#ifdef SISDUALHEAD 12727 } 12728#endif 12729 12730 /* Reset flags */ 12731 pSiS->MiscFlags &= ~( MISC_CRT1OVERLAY | 12732 MISC_CRT2OVERLAY | 12733 MISC_CRT1OVERLAYGAMMA | 12734 MISC_SIS760ONEOVERLAY | 12735 MISC_PANELLINKSCALER | 12736 MISC_STNMODE | 12737 MISC_TVNTSC1024); 12738 12739 pSiS->SiS_SD2_Flags &= ~SiS_SD2_SIS760ONEOVL; 12740 12741#ifdef SISDUALHEAD 12742 if(pSiS->DualHeadMode) { 12743 if(pSiSEnt->pScrn_1) { 12744 SISPTR(pSiSEnt->pScrn_1)->MiscFlags &= ~(MISC_SIS760ONEOVERLAY | 12745 MISC_CRT1OVERLAY | 12746 MISC_CRT2OVERLAY | 12747 MISC_CRT1OVERLAYGAMMA | 12748 MISC_PANELLINKSCALER | 12749 MISC_STNMODE | 12750 MISC_TVNTSC1024); 12751 SISPTR(pSiSEnt->pScrn_1)->SiS_SD2_Flags &= ~SiS_SD2_SIS760ONEOVL; 12752 } 12753 if(pSiSEnt->pScrn_2) { 12754 SISPTR(pSiSEnt->pScrn_2)->MiscFlags &= ~(MISC_SIS760ONEOVERLAY | 12755 MISC_CRT1OVERLAY | 12756 MISC_CRT2OVERLAY | 12757 MISC_CRT1OVERLAYGAMMA | 12758 MISC_PANELLINKSCALER | 12759 MISC_STNMODE | 12760 MISC_TVNTSC1024); 12761 SISPTR(pSiSEnt->pScrn_2)->SiS_SD2_Flags &= ~SiS_SD2_SIS760ONEOVL; 12762 } 12763 } 12764#endif 12765 12766 /* Determine if the video overlay can be used */ 12767 if(!pSiS->NoXvideo) { 12768 12769 int clklimit1=0, clklimit2=0, clklimitg=0; 12770 Bool OverlayHandled = FALSE; 12771 12772 inSISIDXREG(SISSR,0x2b,sr2b); 12773 inSISIDXREG(SISSR,0x2c,sr2c); 12774 myclock1 = myclock2 = SiSGetClockFromRegs(sr2b, sr2c); 12775 inSISIDXREG(SISSR,0x06,tmpreg); 12776 switch((tmpreg & 0x1c) >> 2) { 12777 case 0: mycoldepth1 = 1; break; 12778 case 1: 12779 case 2: mycoldepth1 = 2; break; 12780 default: mycoldepth1 = 4; 12781 } 12782 mycoldepth2 = mycoldepth1; 12783 12784 if((!IsInSlaveMode) && (pSiS->VBFlags & CRT2_ENABLE)) { 12785 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 12786 inSISIDXREG(SISPART4,0x0a,sr2b); 12787 inSISIDXREG(SISPART4,0x0b,sr2c); 12788 } else { 12789 inSISIDXREG(SISSR,0x2e,sr2b); 12790 inSISIDXREG(SISSR,0x2f,sr2c); 12791 } 12792 myclock2 = SiSGetClockFromRegs(sr2b, sr2c); 12793 inSISIDXREG(SISPART1,0x00,tmpreg); 12794 tmpreg &= 0x0f; 12795 switch(tmpreg) { 12796 case 8: mycoldepth2 = 1; break; 12797 case 4: 12798 case 2: mycoldepth2 = 2; break; 12799 default: mycoldepth2 = 4; 12800 } 12801 } 12802 12803 switch(pSiS->ChipType) { 12804 12805 case SIS_300: 12806 case SIS_540: 12807 case SIS_630: 12808 case SIS_730: 12809 clklimit1 = clklimit2 = clklimitg = 150; 12810 break; 12811 12812 case SIS_550: 12813 case SIS_650: 12814 case SIS_740: 12815 clklimit1 = clklimit2 = 175; /* verified for 65x */ 12816 clklimitg = 166; /* ? */ 12817 break; 12818 12819 case SIS_661: 12820 case SIS_741: 12821 clklimit1 = clklimit2 = 190; /* ? */ 12822 clklimitg = 180; /* ? */ 12823 break; 12824 12825 case SIS_760: 12826 case SIS_761: 12827 clklimit1 = clklimit2 = 190; /* ? */ 12828 if(pSiS->ChipFlags & SiSCF_760LFB) { /* LFB only or hybrid */ 12829 clklimit1 = clklimit2 = 220; /* ? */ 12830 } 12831 clklimitg = 200; /* ? */ 12832 12833 if(pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORT760OO) { /* UMA only */ 12834 12835 Bool OnlyOne = FALSE, NoOverlay = FALSE; 12836 int dotclocksum = 0; 12837 12838 if(pSiS->VBFlags & DISPTYPE_CRT1) dotclocksum += myclock1; 12839 if((!IsInSlaveMode) && (pSiS->VBFlags & CRT2_ENABLE)) dotclocksum += myclock2; 12840 12841 /* TODO: Find out under what circumstances only one 12842 * overlay is usable in UMA-only mode. 12843 * This is not entirely accurate; the overlay 12844 * scaler also requires some time, so even though 12845 * the dotclocks are below these values, some 12846 * distortions in the overlay may occure. 12847 * Solution: Don't use a 760 with shared memory. 12848 */ 12849 if( (pSiS->VBFlags & DISPTYPE_CRT1) && 12850 (pSiS->VBFlags & CRT2_ENABLE) && 12851 (mycoldepth1 != mycoldepth2) ) { 12852 12853 /* 0. If coldepths are different (only possible in dual head mode), 12854 * I have no idea to calculate the limits; hence, allow only one 12855 * overlay in all cases. 12856 */ 12857 OnlyOne = TRUE; 12858 12859 } else if(pSiS->MemClock < 150000) { 12860 12861 /* 1. MCLK <150: If someone seriously considers using such 12862 * slow RAM, so be it. Only one overlay in call cases. 12863 */ 12864 OnlyOne = TRUE; 12865 12866 } else if(pSiS->MemClock < 170000) { 12867 12868 /* 2. MCLK 166 */ 12869 switch(pSiS->CurrentLayout.bitsPerPixel) { 12870 case 32: if(dotclocksum > 133) OnlyOne = TRUE; /* One overlay; verified */ 12871 if(dotclocksum > 180) NoOverlay = TRUE; /* No overlay; verified */ 12872 break; 12873 case 16: if(dotclocksum > 175) OnlyOne = TRUE; /* One overlay; verified */ 12874 if(dotclocksum > 260) NoOverlay = TRUE;; /* No overlay; FIXME */ 12875 break; 12876 } 12877 12878 } else if(pSiS->MemClock < 210000) { 12879 12880 /* 3. MCLK 200 */ 12881 switch(pSiS->CurrentLayout.bitsPerPixel) { 12882 case 32: if(dotclocksum > 160) OnlyOne = TRUE; /* One overlay; FIXME */ 12883 if(dotclocksum > 216) NoOverlay = TRUE;; /* No overlay; FIXME */ 12884 break; 12885 case 16: if(dotclocksum > 210) OnlyOne = TRUE; /* One overlay; FIXME */ 12886 if(dotclocksum > 312) NoOverlay = TRUE;; /* No overlay; FIXME */ 12887 break; 12888 } 12889 12890 } 12891 12892 if(OnlyOne || NoOverlay) { 12893 12894 ULong tmpflags = 0; 12895 12896 if(!NoOverlay) { 12897 if(myclock1 <= clklimit1) tmpflags |= MISC_CRT1OVERLAY; 12898 if(myclock2 <= clklimit2) tmpflags |= MISC_CRT2OVERLAY; 12899 if(myclock1 <= clklimitg) tmpflags |= MISC_CRT1OVERLAYGAMMA; 12900 pSiS->MiscFlags |= tmpflags; 12901 } 12902 pSiS->MiscFlags |= MISC_SIS760ONEOVERLAY; 12903 pSiS->SiS_SD2_Flags |= SiS_SD2_SIS760ONEOVL; 12904#ifdef SISDUALHEAD 12905 SiS_SetDHFlags(pSiS, (tmpflags | MISC_SIS760ONEOVERLAY), SiS_SD2_SIS760ONEOVL); 12906#endif 12907 OverlayHandled = TRUE; 12908 } 12909 12910 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 12911 "SiS76x/UMA: %s video overlay(s) available in current mode\n", 12912 NoOverlay ? "no" : ((pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) ? "one" : "two")); 12913 12914#ifdef TWDEBUG 12915 xf86DrvMsg(0, 0, "SiS760: Memclock %d, c1 %d/%d c2 %d/%d, sum %d / %x\n", 12916 pSiS->MemClock, myclock1, mycoldepth1, 12917 myclock2, mycoldepth2, dotclocksum, pSiS->SiS_SD2_Flags); 12918#endif 12919 } 12920 break; 12921 12922 case SIS_660: 12923 clklimit1 = clklimit2 = 200; /* ? */ 12924 if(pSiS->ChipFlags & SiSCF_760LFB) { /* LFB only */ 12925 clklimit1 = clklimit2 = 220; 12926 } 12927 clklimitg = 200; /* ? */ 12928 break; 12929 12930 case SIS_315H: 12931 case SIS_315: 12932 case SIS_315PRO: 12933 case SIS_330: 12934 clklimit1 = clklimit2 = 180; /* ? */ 12935 clklimitg = 166; /* ? */ 12936 break; 12937 12938 case SIS_340: /* ? */ 12939 case XGI_20: 12940 case XGI_40: 12941 clklimit1 = clklimit2 = 240; /* ? */ 12942 clklimitg = 200; /* ? */ 12943 break; 12944 } 12945 12946 if(!OverlayHandled) { 12947 ULong tmpflags = 0; 12948 if(myclock1 <= clklimit1) tmpflags |= MISC_CRT1OVERLAY; 12949 if(myclock2 <= clklimit2) tmpflags |= MISC_CRT2OVERLAY; 12950 if(myclock1 <= clklimitg) tmpflags |= MISC_CRT1OVERLAYGAMMA; 12951 pSiS->MiscFlags |= tmpflags; 12952#ifdef SISDUALHEAD 12953 SiS_SetDHFlags(pSiS, tmpflags, 0); 12954#endif 12955 if(!(pSiS->MiscFlags & MISC_CRT1OVERLAY)) { 12956#ifdef SISDUALHEAD 12957 if((!pSiS->DualHeadMode) || (pSiS->SecondHead)) 12958#endif 12959 xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, 3, 12960 "Current dotclock (%dMhz) too high for video overlay on CRT1\n", 12961 myclock1); 12962 } 12963 if((pSiS->VBFlags & CRT2_ENABLE) && (!(pSiS->MiscFlags & MISC_CRT2OVERLAY))) { 12964#ifdef SISDUALHEAD 12965 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) 12966#endif 12967 xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, 3, 12968 "Current dotclock (%dMhz) too high for video overlay on CRT2\n", 12969 myclock2); 12970 } 12971 } 12972 12973 } 12974 12975 /* Determine if the Panel Link scaler is active */ 12976 12977 if(pSiS->VBFlags & (CRT2_LCD | CRT1_LCDA)) { 12978 ULong tmpflags = 0; 12979 if(pSiS->VGAEngine == SIS_300_VGA) { 12980 if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) { 12981 inSISIDXREG(SISPART1,0x1e,tmpreg); 12982 tmpreg &= 0x3f; 12983 if(tmpreg) tmpflags |= MISC_PANELLINKSCALER; 12984 } 12985 } else { 12986 if((pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) || (pSiS->VBFlags & CRT1_LCDA)) { 12987 inSISIDXREG(SISPART1,0x35,tmpreg); 12988 tmpreg &= 0x04; 12989 if(!tmpreg) tmpflags |= MISC_PANELLINKSCALER; 12990 } 12991 } 12992 pSiS->MiscFlags |= tmpflags; 12993#ifdef SISDUALHEAD 12994 SiS_SetDHFlags(pSiS, tmpflags, 0); 12995#endif 12996 } 12997 12998 /* Determine if STN is active */ 12999 if(pSiS->ChipType == SIS_550) { 13000 if((pSiS->VBFlags & CRT2_LCD) && (pSiS->FSTN || pSiS->DSTN)) { 13001 inSISIDXREG(SISCR,0x34,tmpreg); 13002 tmpreg &= 0x7f; 13003 if(tmpreg == 0x5a || tmpreg == 0x5b) { 13004 pSiS->MiscFlags |= MISC_STNMODE; 13005#ifdef SISDUALHEAD 13006 SiS_SetDHFlags(pSiS, MISC_STNMODE, 0); 13007#endif 13008 } 13009 } 13010 } 13011 13012 /* Determine if our very special TV mode is active */ 13013 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && (pSiS->VBFlags & CRT2_TV) && (!(pSiS->VBFlags & TV_HIVISION))) { 13014 if( ((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR525I)) || 13015 ((!(pSiS->VBFlags & TV_YPBPR)) && (pSiS->VBFlags & (TV_NTSC | TV_PALM))) ) { 13016 inSISIDXREG(SISCR,0x34,tmpreg); 13017 tmpreg &= 0x7f; 13018 if((tmpreg == 0x64) || (tmpreg == 0x4a) || (tmpreg == 0x38)) { 13019 pSiS->MiscFlags |= MISC_TVNTSC1024; 13020#ifdef SISDUALHEAD 13021 SiS_SetDHFlags(pSiS, MISC_TVNTSC1024, 0); 13022#endif 13023 } 13024 } 13025 } 13026 13027 if(pSiS->VGAEngine == SIS_315_VGA) { 13028 int i; 13029#ifdef SISVRAMQ 13030 /* Re-Enable and reset command queue */ 13031 SiSEnableTurboQueue(pScrn); 13032#endif 13033 /* Get HWCursor register contents for backup */ 13034 for(i = 0; i < 16; i++) { 13035 pSiS->HWCursorBackup[i] = SIS_MMIO_IN32(pSiS->IOBase, 0x8500 + (i << 2)); 13036 } 13037 if(pSiS->ChipType >= SIS_330) { 13038 /* Enable HWCursor protection (Y pos as trigger) */ 13039 andSISIDXREG(SISCR, 0x5b, ~0x30); 13040 } 13041 } 13042 13043 /* Re-initialize accelerator engine */ 13044 /* (We are sync'ed here) */ 13045 if(!pSiS->NoAccel) { 13046 if(pSiS->InitAccel) { 13047 (pSiS->InitAccel)(pScrn); 13048 } 13049 } 13050 13051 /* Set display device gamma (for SISCTRL) */ 13052 if(pSiS->VBFlags & CRT1_LCDA) 13053 pSiS->CRT1MonGamma = pSiS->CRT2LCDMonitorGamma; 13054 else 13055 pSiS->CRT1MonGamma = pSiS->CRT1VGAMonitorGamma; 13056 13057 if(pSiS->VBFlags & CRT2_LCD) 13058 pSiS->CRT2MonGamma = pSiS->CRT2LCDMonitorGamma; 13059 else if(pSiS->VBFlags & CRT2_TV) { 13060 if(pSiS->VBFlags & TV_YPBPR) 13061 pSiS->CRT2MonGamma = 2200; /* */ 13062 else if(pSiS->VBFlags & TV_HIVISION) 13063 pSiS->CRT2MonGamma = 2200; /* ? */ 13064 else if(pSiS->VBFlags & TV_NTSC) 13065 pSiS->CRT2MonGamma = 2200; /* NTSC */ 13066 else 13067 pSiS->CRT2MonGamma = 2800; /* All PAL modes? */ 13068 } else if(pSiS->VBFlags & CRT2_VGA) 13069 pSiS->CRT2MonGamma = pSiS->CRT2VGAMonitorGamma; 13070 else 13071 pSiS->CRT2MonGamma = 0; /* Unknown */ 13072 13073 /* Reset XV display properties (such as number of overlays, etc) */ 13074 /* (And copy monitor gamma) */ 13075#ifdef SISDUALHEAD 13076 if(pSiS->DualHeadMode) { 13077 if(pSiSEnt->pScrn_1) { 13078 if(SISPTR(pSiSEnt->pScrn_1)->ResetXvDisplay) { 13079 (SISPTR(pSiSEnt->pScrn_1)->ResetXvDisplay)(pSiSEnt->pScrn_1); 13080 } 13081 SISPTR(pSiSEnt->pScrn_1)->CRT1MonGamma = pSiS->CRT1MonGamma; 13082 SISPTR(pSiSEnt->pScrn_1)->CRT2MonGamma = pSiS->CRT2MonGamma; 13083 } 13084 if(pSiSEnt->pScrn_2) { 13085 if(SISPTR(pSiSEnt->pScrn_2)->ResetXvDisplay) { 13086 (SISPTR(pSiSEnt->pScrn_1)->ResetXvDisplay)(pSiSEnt->pScrn_2); 13087 } 13088 SISPTR(pSiSEnt->pScrn_2)->CRT1MonGamma = pSiS->CRT1MonGamma; 13089 SISPTR(pSiSEnt->pScrn_2)->CRT2MonGamma = pSiS->CRT2MonGamma; 13090 } 13091 } else { 13092#endif 13093 if(pSiS->ResetXvDisplay) { 13094 (pSiS->ResetXvDisplay)(pScrn); 13095 } 13096#ifdef SISDUALHEAD 13097 } 13098#endif 13099 13100 /* Reset XV gamma correction */ 13101 if(pSiS->ResetXvGamma) { 13102 (pSiS->ResetXvGamma)(pScrn); 13103 } 13104 13105 /* Reset various display parameters */ 13106 { 13107 int val = pSiS->siscrt1satgain; 13108#ifdef SISDUALHEAD 13109 if(pSiS->DualHeadMode && pSiSEnt) val = pSiSEnt->siscrt1satgain; 13110#endif 13111 SiS_SetSISCRT1SaturationGain(pScrn, val); 13112 } 13113 13114 /* Apply TV settings given by options 13115 Do this even in DualHeadMode: 13116 - if this is called by SetModeCRT1, CRT2 mode has been reset by SetModeCRT1 13117 - if this is called by SetModeCRT2, CRT2 mode has changed (duh!) 13118 -> Hence, in both cases, the settings must be re-applied. 13119 */ 13120 13121 if(pSiS->VBFlags & CRT2_TV) { 13122 int val; 13123 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 13124 int mychtvlumabandwidthcvbs = pSiS->chtvlumabandwidthcvbs; 13125 int mychtvlumabandwidthsvideo = pSiS->chtvlumabandwidthsvideo; 13126 int mychtvlumaflickerfilter = pSiS->chtvlumaflickerfilter; 13127 int mychtvchromabandwidth = pSiS->chtvchromabandwidth; 13128 int mychtvchromaflickerfilter = pSiS->chtvchromaflickerfilter; 13129 int mychtvcvbscolor = pSiS->chtvcvbscolor; 13130 int mychtvtextenhance = pSiS->chtvtextenhance; 13131 int mychtvcontrast = pSiS->chtvcontrast; 13132 int mytvxpos = pSiS->tvxpos; 13133 int mytvypos = pSiS->tvypos; 13134#ifdef SISDUALHEAD 13135 if(pSiSEnt && pSiS->DualHeadMode) { 13136 mychtvlumabandwidthcvbs = pSiSEnt->chtvlumabandwidthcvbs; 13137 mychtvlumabandwidthsvideo = pSiSEnt->chtvlumabandwidthsvideo; 13138 mychtvlumaflickerfilter = pSiSEnt->chtvlumaflickerfilter; 13139 mychtvchromabandwidth = pSiSEnt->chtvchromabandwidth; 13140 mychtvchromaflickerfilter = pSiSEnt->chtvchromaflickerfilter; 13141 mychtvcvbscolor = pSiSEnt->chtvcvbscolor; 13142 mychtvtextenhance = pSiSEnt->chtvtextenhance; 13143 mychtvcontrast = pSiSEnt->chtvcontrast; 13144 mytvxpos = pSiSEnt->tvxpos; 13145 mytvypos = pSiSEnt->tvypos; 13146 } 13147#endif 13148 if((val = mychtvlumabandwidthcvbs) != -1) { 13149 SiS_SetCHTVlumabandwidthcvbs(pScrn, val); 13150 } 13151 if((val = mychtvlumabandwidthsvideo) != -1) { 13152 SiS_SetCHTVlumabandwidthsvideo(pScrn, val); 13153 } 13154 if((val = mychtvlumaflickerfilter) != -1) { 13155 SiS_SetCHTVlumaflickerfilter(pScrn, val); 13156 } 13157 if((val = mychtvchromabandwidth) != -1) { 13158 SiS_SetCHTVchromabandwidth(pScrn, val); 13159 } 13160 if((val = mychtvchromaflickerfilter) != -1) { 13161 SiS_SetCHTVchromaflickerfilter(pScrn, val); 13162 } 13163 if((val = mychtvcvbscolor) != -1) { 13164 SiS_SetCHTVcvbscolor(pScrn, val); 13165 } 13166 if((val = mychtvtextenhance) != -1) { 13167 SiS_SetCHTVtextenhance(pScrn, val); 13168 } 13169 if((val = mychtvcontrast) != -1) { 13170 SiS_SetCHTVcontrast(pScrn, val); 13171 } 13172 /* Backup default TV position registers */ 13173 switch(pSiS->ChrontelType) { 13174 case CHRONTEL_700x: 13175 pSiS->tvx = SiS_GetCH700x(pSiS->SiS_Pr, 0x0a); 13176 pSiS->tvx |= (((SiS_GetCH700x(pSiS->SiS_Pr, 0x08) & 0x02) >> 1) << 8); 13177 pSiS->tvy = SiS_GetCH700x(pSiS->SiS_Pr, 0x0b); 13178 pSiS->tvy |= ((SiS_GetCH700x(pSiS->SiS_Pr, 0x08) & 0x01) << 8); 13179#ifdef SISDUALHEAD 13180 if(pSiSEnt) { 13181 pSiSEnt->tvx = pSiS->tvx; 13182 pSiSEnt->tvy = pSiS->tvy; 13183 } 13184#endif 13185 break; 13186 case CHRONTEL_701x: 13187 /* Not supported by hardware */ 13188 break; 13189 } 13190 if((val = mytvxpos) != 0) { 13191 SiS_SetTVxposoffset(pScrn, val); 13192 } 13193 if((val = mytvypos) != 0) { 13194 SiS_SetTVyposoffset(pScrn, val); 13195 } 13196 } 13197 if(pSiS->VBFlags2 & VB2_301) { 13198 int mysistvedgeenhance = pSiS->sistvedgeenhance; 13199#ifdef SISDUALHEAD 13200 if(pSiSEnt && pSiS->DualHeadMode) { 13201 mysistvedgeenhance = pSiSEnt->sistvedgeenhance; 13202 } 13203#endif 13204 if((val = mysistvedgeenhance) != -1) { 13205 SiS_SetSISTVedgeenhance(pScrn, val); 13206 } 13207 } 13208 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 13209 int mysistvantiflicker = pSiS->sistvantiflicker; 13210 int mysistvsaturation = pSiS->sistvsaturation; 13211 int mysistvcolcalibf = pSiS->sistvcolcalibf; 13212 int mysistvcolcalibc = pSiS->sistvcolcalibc; 13213 int mysistvcfilter = pSiS->sistvcfilter; 13214 int mysistvyfilter = pSiS->sistvyfilter; 13215 int mytvxpos = pSiS->tvxpos; 13216 int mytvypos = pSiS->tvypos; 13217 int mytvxscale = pSiS->tvxscale; 13218 int mytvyscale = pSiS->tvyscale; 13219 int i; 13220 ULong cbase; 13221 UChar ctemp; 13222#ifdef SISDUALHEAD 13223 if(pSiSEnt && pSiS->DualHeadMode) { 13224 mysistvantiflicker = pSiSEnt->sistvantiflicker; 13225 mysistvsaturation = pSiSEnt->sistvsaturation; 13226 mysistvcolcalibf = pSiSEnt->sistvcolcalibf; 13227 mysistvcolcalibc = pSiSEnt->sistvcolcalibc; 13228 mysistvcfilter = pSiSEnt->sistvcfilter; 13229 mysistvyfilter = pSiSEnt->sistvyfilter; 13230 mytvxpos = pSiSEnt->tvxpos; 13231 mytvypos = pSiSEnt->tvypos; 13232 mytvxscale = pSiSEnt->tvxscale; 13233 mytvyscale = pSiSEnt->tvyscale; 13234 } 13235#endif 13236 /* Backup default TV position, scale and colcalib registers */ 13237 inSISIDXREG(SISPART2,0x1f,pSiS->p2_1f); 13238 inSISIDXREG(SISPART2,0x20,pSiS->p2_20); 13239 inSISIDXREG(SISPART2,0x2b,pSiS->p2_2b); 13240 inSISIDXREG(SISPART2,0x42,pSiS->p2_42); 13241 inSISIDXREG(SISPART2,0x43,pSiS->p2_43); 13242 inSISIDXREG(SISPART2,0x01,pSiS->p2_01); 13243 inSISIDXREG(SISPART2,0x02,pSiS->p2_02); 13244 inSISIDXREG(SISPART2,0x44,pSiS->p2_44); 13245 inSISIDXREG(SISPART2,0x45,pSiS->p2_45); 13246 if(!(pSiS->VBFlags2 & VB2_301)) { 13247 inSISIDXREG(SISPART2,0x46,pSiS->p2_46); 13248 } else { 13249 pSiS->p2_46 = 0; 13250 } 13251 inSISIDXREG(SISPART2,0x0a,pSiS->p2_0a); 13252 inSISIDXREG(SISPART2,0x31,cbase); 13253 cbase = (cbase & 0x7f) << 8; 13254 inSISIDXREG(SISPART2,0x32,ctemp); 13255 cbase = (cbase | ctemp) << 8; 13256 inSISIDXREG(SISPART2,0x33,ctemp); 13257 cbase = (cbase | ctemp) << 8; 13258 inSISIDXREG(SISPART2,0x34,ctemp); 13259 pSiS->sistvccbase = (cbase | ctemp); 13260 inSISIDXREG(SISPART2,0x35,pSiS->p2_35); 13261 inSISIDXREG(SISPART2,0x36,pSiS->p2_36); 13262 inSISIDXREG(SISPART2,0x37,pSiS->p2_37); 13263 inSISIDXREG(SISPART2,0x38,pSiS->p2_38); 13264 if(!(pSiS->VBFlags2 & VB2_301)) { 13265 inSISIDXREG(SISPART2,0x47,pSiS->p2_47); 13266 inSISIDXREG(SISPART2,0x48,pSiS->p2_48); 13267 inSISIDXREG(SISPART2,0x49,pSiS->p2_49); 13268 inSISIDXREG(SISPART2,0x4a,pSiS->p2_4a); 13269 } 13270 inSISIDXREG(SISPART2,0x2f,pSiS->p2_2f); 13271 inSISIDXREG(SISPART2,0x30,pSiS->p2_30); 13272 for(i=0; i<9; i++) { 13273 inSISIDXREG(SISPART1,SiSScalingP1Regs[i],pSiS->scalingp1[i]); 13274 } 13275 for(i=0; i<9; i++) { 13276 inSISIDXREG(SISPART4,SiSScalingP4Regs[i],pSiS->scalingp4[i]); 13277 } 13278 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 13279 for(i=0; i<64; i++) { 13280 inSISIDXREG(SISPART2,(0xc0 + i),pSiS->scalingp2[i]); 13281 } 13282 } 13283#ifdef SISDUALHEAD 13284 if(pSiSEnt) { 13285 pSiSEnt->p2_1f = pSiS->p2_1f; pSiSEnt->p2_20 = pSiS->p2_20; 13286 pSiSEnt->p2_42 = pSiS->p2_42; pSiSEnt->p2_43 = pSiS->p2_43; 13287 pSiSEnt->p2_2b = pSiS->p2_2b; 13288 pSiSEnt->p2_01 = pSiS->p2_01; pSiSEnt->p2_02 = pSiS->p2_02; 13289 pSiSEnt->p2_44 = pSiS->p2_44; pSiSEnt->p2_45 = pSiS->p2_45; 13290 pSiSEnt->p2_46 = pSiS->p2_46; pSiSEnt->p2_0a = pSiS->p2_0a; 13291 pSiSEnt->sistvccbase = pSiS->sistvccbase; 13292 pSiSEnt->p2_35 = pSiS->p2_35; pSiSEnt->p2_36 = pSiS->p2_36; 13293 pSiSEnt->p2_37 = pSiS->p2_37; pSiSEnt->p2_38 = pSiS->p2_38; 13294 pSiSEnt->p2_48 = pSiS->p2_48; pSiSEnt->p2_49 = pSiS->p2_49; 13295 pSiSEnt->p2_4a = pSiS->p2_4a; pSiSEnt->p2_2f = pSiS->p2_2f; 13296 pSiSEnt->p2_30 = pSiS->p2_30; pSiSEnt->p2_47 = pSiS->p2_47; 13297 for(i=0; i<9; i++) { 13298 pSiSEnt->scalingp1[i] = pSiS->scalingp1[i]; 13299 } 13300 for(i=0; i<9; i++) { 13301 pSiSEnt->scalingp4[i] = pSiS->scalingp4[i]; 13302 } 13303 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 13304 for(i=0; i<64; i++) { 13305 pSiSEnt->scalingp2[i] = pSiS->scalingp2[i]; 13306 } 13307 } 13308 } 13309#endif 13310 if((val = mysistvantiflicker) != -1) { 13311 SiS_SetSISTVantiflicker(pScrn, val); 13312 } 13313 if((val = mysistvsaturation) != -1) { 13314 SiS_SetSISTVsaturation(pScrn, val); 13315 } 13316 if((val = mysistvcfilter) != -1) { 13317 SiS_SetSISTVcfilter(pScrn, val); 13318 } 13319 if((val = mysistvyfilter) != 1) { 13320 SiS_SetSISTVyfilter(pScrn, val); 13321 } 13322 if((val = mysistvcolcalibc) != 0) { 13323 SiS_SetSISTVcolcalib(pScrn, val, TRUE); 13324 } 13325 if((val = mysistvcolcalibf) != 0) { 13326 SiS_SetSISTVcolcalib(pScrn, val, FALSE); 13327 } 13328 if((val = mytvxpos) != 0) { 13329 SiS_SetTVxposoffset(pScrn, val); 13330 } 13331 if((val = mytvypos) != 0) { 13332 SiS_SetTVyposoffset(pScrn, val); 13333 } 13334 if((val = mytvxscale) != 0) { 13335 SiS_SetTVxscale(pScrn, val); 13336 } 13337 if((val = mytvyscale) != 0) { 13338 SiS_SetTVyscale(pScrn, val); 13339 } 13340 } 13341 } 13342 13343} 13344 13345/* Post-set SiS6326 TV registers */ 13346static void 13347SiS6326PostSetMode(ScrnInfoPtr pScrn, SISRegPtr sisReg) 13348{ 13349 SISPtr pSiS = SISPTR(pScrn); 13350 UChar tmp; 13351 int val; 13352 13353 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 13354 13355#ifdef UNLOCK_ALWAYS 13356 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 13357#endif 13358 13359 /* Backup default TV position registers */ 13360 pSiS->tvx1 = SiS6326GetTVReg(pScrn,0x3a); 13361 pSiS->tvx1 |= ((SiS6326GetTVReg(pScrn,0x3c) & 0x0f) << 8); 13362 pSiS->tvx2 = SiS6326GetTVReg(pScrn,0x26); 13363 pSiS->tvx2 |= ((SiS6326GetTVReg(pScrn,0x27) & 0xf0) << 4); 13364 pSiS->tvx3 = SiS6326GetTVReg(pScrn,0x12); 13365 pSiS->tvx3 |= ((SiS6326GetTVReg(pScrn,0x13) & 0xC0) << 2); 13366 pSiS->tvy1 = SiS6326GetTVReg(pScrn,0x11); 13367 pSiS->tvy1 |= ((SiS6326GetTVReg(pScrn,0x13) & 0x30) << 4); 13368 13369 /* Handle TVPosOffset options (BEFORE switching on TV) */ 13370 if((val = pSiS->tvxpos) != 0) { 13371 SiS_SetTVxposoffset(pScrn, val); 13372 } 13373 if((val = pSiS->tvypos) != 0) { 13374 SiS_SetTVyposoffset(pScrn, val); 13375 } 13376 13377 /* Switch on TV output. This is rather complicated, but 13378 * if we don't do it, TV output will flicker terribly. 13379 */ 13380 if(pSiS->SiS6326Flags & SIS6326_TVON) { 13381 orSISIDXREG(SISSR, 0x01, 0x20); 13382 tmp = SiS6326GetTVReg(pScrn,0x00); 13383 tmp &= ~0x04; 13384 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 13385 SiS6326SetTVReg(pScrn,0x00,tmp); 13386 for(val=0; val < 2; val++) { 13387 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 13388 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 13389 } 13390 SiS6326SetTVReg(pScrn, 0x00, sisReg->sis6326tv[0]); 13391 tmp = inSISREG(SISINPSTAT); 13392 outSISREG(SISAR, 0x20); 13393 tmp = inSISREG(SISINPSTAT); 13394 while(inSISREG(SISINPSTAT) & 0x01); 13395 while(!(inSISREG(SISINPSTAT) & 0x01)); 13396 andSISIDXREG(SISSR, 0x01, ~0x20); 13397 for(val=0; val < 10; val++) { 13398 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 13399 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 13400 } 13401 andSISIDXREG(SISSR, 0x01, ~0x20); 13402 } 13403 13404 tmp = SiS6326GetTVReg(pScrn,0x00); 13405 if(!(tmp & 0x04)) return; 13406 13407 /* Apply TV settings given by options */ 13408 if((val = pSiS->sistvantiflicker) != -1) { 13409 SiS_SetSIS6326TVantiflicker(pScrn, val); 13410 } 13411 if((val = pSiS->sis6326enableyfilter) != -1) { 13412 SiS_SetSIS6326TVenableyfilter(pScrn, val); 13413 } 13414 if((val = pSiS->sis6326yfilterstrong) != -1) { 13415 SiS_SetSIS6326TVyfilterstrong(pScrn, val); 13416 } 13417 13418} 13419 13420/* Check if video bridge is in slave mode */ 13421Bool 13422SiSBridgeIsInSlaveMode(ScrnInfoPtr pScrn) 13423{ 13424 SISPtr pSiS = SISPTR(pScrn); 13425 UChar usScrP1_00; 13426 13427 if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return FALSE; 13428 13429 inSISIDXREG(SISPART1,0x00,usScrP1_00); 13430 if( ((pSiS->VGAEngine == SIS_300_VGA) && (usScrP1_00 & 0xa0) == 0x20) || 13431 ((pSiS->VGAEngine == SIS_315_VGA) && (usScrP1_00 & 0x50) == 0x10) ) { 13432 return TRUE; 13433 } 13434 13435 return FALSE; 13436} 13437 13438/* Build a list of the VESA modes the BIOS reports as valid */ 13439static void 13440SiSBuildVesaModeList(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe) 13441{ 13442 SISPtr pSiS = SISPTR(pScrn); 13443 int i = 0; 13444 13445 while(vbe->VideoModePtr[i] != 0xffff) { 13446 sisModeInfoPtr m; 13447 VbeModeInfoBlock *mode; 13448 int id = vbe->VideoModePtr[i++]; 13449 13450 if((mode = VBEGetModeInfo(pVbe, id)) == NULL) { 13451 continue; 13452 } 13453 13454 m = xnfcalloc(sizeof(sisModeInfoRec), 1); 13455 if(!m) { 13456 VBEFreeModeInfo(mode); 13457 continue; 13458 } 13459 m->width = mode->XResolution; 13460 m->height = mode->YResolution; 13461 m->bpp = mode->BitsPerPixel; 13462 m->n = id; 13463 m->next = pSiS->SISVESAModeList; 13464 13465 pSiS->SISVESAModeList = m; 13466 13467 VBEFreeModeInfo(mode); 13468 13469 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 13470 "VESA BIOS supports mode number 0x%x: %ix%i (%i bpp)\n", 13471 m->n, m->width, m->height, m->bpp); 13472 } 13473} 13474 13475/* Get VESA mode number from given resolution/depth */ 13476static UShort 13477SiSCalcVESAModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode) 13478{ 13479 SISPtr pSiS = SISPTR(pScrn); 13480 sisModeInfoPtr m = pSiS->SISVESAModeList; 13481 UShort i = (pScrn->bitsPerPixel+7)/8 - 1; 13482 UShort ModeNumber = 0; 13483 int j; 13484 13485 while(m) { 13486 if( (pScrn->bitsPerPixel == m->bpp) && 13487 (mode->HDisplay == m->width) && 13488 (mode->VDisplay == m->height) ) 13489 return m->n; 13490 m = m->next; 13491 } 13492 13493 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 13494 "No valid VESA BIOS mode found for %dx%d (%d bpp)\n", 13495 mode->HDisplay, mode->VDisplay, pScrn->bitsPerPixel); 13496 13497 if(!pSiS->ROM661New) { /* VESA numbers changed! */ 13498 j = 0; 13499 while(VESAModeIndices[j] != 9999) { 13500 if( (mode->HDisplay == VESAModeIndices[j]) && 13501 (mode->VDisplay == VESAModeIndices[j+1]) ) { 13502 ModeNumber = VESAModeIndices[j + 2 + i]; 13503 break; 13504 } 13505 j += 6; 13506 } 13507 13508 if(!ModeNumber) { 13509 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 13510 "No valid mode found for %dx%dx%d in built-in table either.\n", 13511 mode->HDisplay, mode->VDisplay, pScrn->bitsPerPixel); 13512 } 13513 } 13514 13515 return(ModeNumber); 13516} 13517 13518UShort 13519SiS_GetModeNumber(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned int VBFlags) 13520{ 13521 SISPtr pSiS = SISPTR(pScrn); 13522 UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; 13523 BOOLEAN FSTN = pSiS->FSTN ? TRUE : FALSE; 13524 13525#ifdef SISDUALHEAD 13526 if(pSiS->DualHeadMode && pSiS->SecondHead) FSTN = FALSE; 13527#endif 13528 13529 return(SiS_GetModeID(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, 13530 i, FSTN, pSiS->LCDwidth, pSiS->LCDheight)); 13531} 13532 13533static Bool 13534SiSValidLCDUserMode(SISPtr pSiS, unsigned int VBFlags, DisplayModePtr mode, Bool isforlcda) 13535{ 13536 if(mode->Flags & V_INTERLACE) return FALSE; 13537 13538 if(mode->HDisplay > 2048) return FALSE; 13539 if(mode->VDisplay > 1536) return FALSE; 13540 13541 if(pSiS->VBFlags2 & VB2_LCD162MHZBRIDGE) { 13542 if(mode->Clock > 162500) return FALSE; 13543#ifdef VB_FORBID_CRT2LCD_OVER_1600 13544 if(!isforlcda) { 13545 if(mode->HDisplay > 1600) return FALSE; 13546 } 13547#endif 13548 } else { /* 301, 301B, 302B (no LCDA!) */ 13549 if(mode->Clock > 130000) return FALSE; 13550 if(mode->Clock > 111000) { 13551 xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING, 13552 "WARNING: Mode clock beyond video bridge specs (%dMHz). Hardware damage might occure.\n", 13553 mode->Clock / 1000); 13554 } 13555 if(mode->HDisplay > 1600) return FALSE; 13556 if(mode->VDisplay > 1024) return FALSE; 13557 } 13558 13559 return TRUE; 13560} 13561 13562static Bool 13563SiSValidVGA2UserMode(SISPtr pSiS, unsigned int VBFlags, DisplayModePtr mode) 13564{ 13565 if(mode->Flags & V_INTERLACE) return FALSE; 13566 13567 if(mode->HDisplay > 2048) return FALSE; 13568 if(mode->VDisplay > 1536) return FALSE; 13569 13570 if(pSiS->VBFlags2 & VB2_RAMDAC202MHZBRIDGE) { 13571 if(mode->Clock > 203000) return FALSE; 13572 } else if(pSiS->VBFlags2 & VB2_30xBLV) { 13573 if(mode->Clock > 162500) return FALSE; 13574 } else { 13575 if(mode->Clock > 135500) return FALSE; 13576 } 13577 13578 return TRUE; 13579} 13580 13581UShort 13582SiS_CheckModeCRT1(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned int VBFlags, Bool havecustommodes) 13583{ 13584 SISPtr pSiS = SISPTR(pScrn); 13585 UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; 13586 int j; 13587 13588 if(!(VBFlags & CRT1_LCDA)) { 13589 13590 if((havecustommodes) && (!(mode->type & M_T_DEFAULT))) { 13591 return 0xfe; 13592 } 13593 13594 } else if(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE) { 13595 13596 if(pSiS->ChipType < SIS_661) { /* < 661 only? */ 13597 if(!(mode->type & M_T_DEFAULT)) { 13598 if(mode->HTotal > 2055) return 0; 13599 /* (Default mode will be caught in mode switching code) */ 13600 } 13601 } 13602 13603 if(pSiS->SiS_Pr->CP_HaveCustomData) { 13604 for(j=0; j<7; j++) { 13605 if((pSiS->SiS_Pr->CP_DataValid[j]) && 13606 (mode->HDisplay == pSiS->SiS_Pr->CP_HDisplay[j]) && 13607 (mode->VDisplay == pSiS->SiS_Pr->CP_VDisplay[j]) && 13608 (mode->type & M_T_BUILTIN)) 13609 return 0xfe; 13610 } 13611 } 13612 13613 if((pSiS->AddedPlasmaModes) && (mode->type & M_T_BUILTIN)) 13614 return 0xfe; 13615 13616 if((havecustommodes) && 13617 (pSiS->LCDwidth) && /* = test if LCD present */ 13618 (!(mode->type & M_T_DEFAULT)) && 13619 (SiSValidLCDUserMode(pSiS, VBFlags, mode, TRUE))) 13620 return 0xfe; 13621 13622 if((mode->HDisplay > pSiS->LCDwidth) || 13623 (mode->VDisplay > pSiS->LCDheight)) { 13624 return 0; 13625 } 13626 13627 } else { 13628 13629 if((mode->HDisplay > pSiS->LCDwidth) || 13630 (mode->VDisplay > pSiS->LCDheight)) { 13631 return 0; 13632 } 13633 13634 } 13635 13636 return(SiS_GetModeID(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, 13637 i, pSiS->FSTN, pSiS->LCDwidth, pSiS->LCDheight)); 13638} 13639 13640UShort 13641SiS_CheckModeCRT2(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned int VBFlags, Bool havecustommodes) 13642{ 13643 SISPtr pSiS = SISPTR(pScrn); 13644 UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; 13645 UShort ModeIndex = 0; 13646 int j; 13647 13648#ifdef TWDEBUG 13649 xf86DrvMsg(0, X_INFO, "Inside CheckCalcModeIndex (VBFlags %lx, mode %dx%d)\n", 13650 VBFlags,mode->HDisplay, mode->VDisplay); 13651#endif 13652 13653 if(VBFlags & CRT2_LCD) { /* CRT2 is LCD */ 13654 13655 if((pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && (!(pSiS->VBFlags2 & VB2_30xBDH))) { 13656 13657 if(pSiS->SiS_Pr->CP_HaveCustomData) { 13658 for(j=0; j<7; j++) { 13659 if((pSiS->SiS_Pr->CP_DataValid[j]) && 13660 (mode->HDisplay == pSiS->SiS_Pr->CP_HDisplay[j]) && 13661 (mode->VDisplay == pSiS->SiS_Pr->CP_VDisplay[j]) && 13662#ifdef VB_FORBID_CRT2LCD_OVER_1600 13663 (mode->HDisplay <= 1600) && 13664#endif 13665 (mode->type & M_T_BUILTIN)) 13666 return 0xfe; 13667 } 13668 } 13669 13670 /* All plasma modes have HDisplay <= 1600 */ 13671 if((pSiS->AddedPlasmaModes) && (mode->type & M_T_BUILTIN)) 13672 return 0xfe; 13673 13674 if((havecustommodes) && 13675 (pSiS->LCDwidth) && /* = test if LCD present */ 13676 (!(mode->type & M_T_DEFAULT)) && 13677 (SiSValidLCDUserMode(pSiS, VBFlags, mode, FALSE))) 13678 return 0xfe; 13679 13680 } 13681 13682 if( ((mode->HDisplay <= pSiS->LCDwidth) && 13683 (mode->VDisplay <= pSiS->LCDheight)) || 13684 ((pSiS->SiS_Pr->SiS_CustomT == CUT_PANEL848) && 13685 (((mode->HDisplay == 1360) && (mode->HDisplay == 768)) || 13686 ((mode->HDisplay == 1024) && (mode->HDisplay == 768)) || 13687 ((mode->HDisplay == 800) && (mode->HDisplay == 600)))) || 13688 ((pSiS->SiS_Pr->SiS_CustomT == CUT_PANEL856) && 13689 (((mode->HDisplay == 1024) && (mode->HDisplay == 768)) || 13690 ((mode->HDisplay == 800) && (mode->HDisplay == 600)))) ) { 13691 13692 ModeIndex = SiS_GetModeID_LCD(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, i, 13693 pSiS->FSTN, pSiS->SiS_Pr->SiS_CustomT, pSiS->LCDwidth, pSiS->LCDheight, 13694 pSiS->VBFlags2); 13695 13696 } 13697 13698 } else if(VBFlags & CRT2_TV) { /* CRT2 is TV */ 13699 13700 ModeIndex = SiS_GetModeID_TV(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, i, 13701 pSiS->VBFlags2); 13702 13703 } else if(VBFlags & CRT2_VGA) { /* CRT2 is VGA2 */ 13704 13705 if((pSiS->AddedPlasmaModes) && (mode->type & M_T_BUILTIN)) 13706 return 0xfe; 13707 13708 if((havecustommodes) && 13709 (!(mode->type & M_T_DEFAULT)) && 13710 (SiSValidVGA2UserMode(pSiS, VBFlags, mode))) 13711 return 0xfe; 13712 13713 ModeIndex = SiS_GetModeID_VGA2(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, i, 13714 pSiS->VBFlags2); 13715 13716 } else { /* no CRT2 */ 13717 13718 /* Return a valid mode number */ 13719 ModeIndex = 0xfe; 13720 13721 } 13722 13723 return(ModeIndex); 13724} 13725 13726/* Calculate the vertical refresh rate from a mode */ 13727float 13728SiSCalcVRate(DisplayModePtr mode) 13729{ 13730 float hsync, refresh = 0; 13731 13732 if(mode->HSync > 0.0) 13733 hsync = mode->HSync; 13734 else if(mode->HTotal > 0) 13735 hsync = (float)mode->Clock / (float)mode->HTotal; 13736 else 13737 hsync = 0.0; 13738 13739 if(mode->VTotal > 0) 13740 refresh = hsync * 1000.0 / mode->VTotal; 13741 13742 if(mode->Flags & V_INTERLACE) 13743 refresh *= 2.0; 13744 13745 if(mode->Flags & V_DBLSCAN) 13746 refresh /= 2.0; 13747 13748 if(mode->VScan > 1) 13749 refresh /= mode->VScan; 13750 13751 if(mode->VRefresh > 0.0) 13752 refresh = mode->VRefresh; 13753 13754 if(hsync == 0.0 || refresh == 0.0) return 0.0; 13755 13756 return refresh; 13757} 13758 13759/* Calculate CR33 (rate index) for CRT1. 13760 * Calculation is done using currentmode, therefore it is 13761 * recommended to set VertRefresh and HorizSync to correct 13762 * values in config file. 13763 */ 13764UChar 13765SISSearchCRT1Rate(ScrnInfoPtr pScrn, DisplayModePtr mode) 13766{ 13767 SISPtr pSiS = SISPTR(pScrn); 13768 int i = 0, irefresh; 13769 UShort xres = mode->HDisplay; 13770 UShort yres = mode->VDisplay; 13771 UChar index, defindex; 13772 Bool checksis730 = FALSE; 13773 13774 defindex = (xres == 800 || xres == 1024 || xres == 1280) ? 0x02 : 0x01; 13775 13776 irefresh = (int)SiSCalcVRate(mode); 13777 if(!irefresh) return defindex; 13778 13779 /* SiS730 has troubles on CRT2 if CRT1 is at 32bpp */ 13780 if( (pSiS->ChipType == SIS_730) && 13781 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && 13782 (pSiS->CurrentLayout.bitsPerPixel == 32) ) { 13783#ifdef SISDUALHEAD 13784 if(pSiS->DualHeadMode) { 13785 if(pSiS->SecondHead) { 13786 checksis730 = TRUE; 13787 } 13788 } else 13789#endif 13790 if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE) && (!pSiS->CRT1off)) { 13791 checksis730 = TRUE; 13792 } 13793 } 13794 13795#ifdef TWDEBUG 13796 xf86DrvMsg(0, X_INFO, "Debug: CalcVRate returned %d\n", irefresh); 13797#endif 13798 13799 /* We need the REAL refresh rate here */ 13800 if(mode->Flags & V_INTERLACE) irefresh /= 2; 13801 13802 /* Do not multiply by 2 when DBLSCAN! */ 13803 13804#ifdef TWDEBUG 13805 xf86DrvMsg(0, X_INFO, "Debug: Rate after correction = %d\n", irefresh); 13806#endif 13807 13808 index = 0; 13809 while((sisx_vrate[i].idx != 0) && (sisx_vrate[i].xres <= xres)) { 13810 if((sisx_vrate[i].xres == xres) && (sisx_vrate[i].yres == yres)) { 13811 if((checksis730 == FALSE) || (sisx_vrate[i].SiS730valid32bpp == TRUE)) { 13812 if(sisx_vrate[i].refresh == irefresh) { 13813 index = sisx_vrate[i].idx; 13814 break; 13815 } else if(sisx_vrate[i].refresh > irefresh) { 13816 if((sisx_vrate[i].refresh - irefresh) <= 3) { 13817 index = sisx_vrate[i].idx; 13818 } else if( ((checksis730 == FALSE) || (sisx_vrate[i - 1].SiS730valid32bpp == TRUE)) && 13819 ((irefresh - sisx_vrate[i - 1].refresh) <= 2) && 13820 (sisx_vrate[i].idx != 1) ) { 13821 index = sisx_vrate[i - 1].idx; 13822 } 13823 break; 13824 } else if((irefresh - sisx_vrate[i].refresh) <= 2) { 13825 index = sisx_vrate[i].idx; 13826 break; 13827 } 13828 } 13829 } 13830 i++; 13831 } 13832 13833 if(index > 0) return index; 13834 else return defindex; 13835} 13836 13837void 13838SISWaitRetraceCRT1(ScrnInfoPtr pScrn) 13839{ 13840 SISPtr pSiS = SISPTR(pScrn); 13841 int watchdog; 13842 UChar temp; 13843 13844 inSISIDXREG(SISCR,0x17,temp); 13845 if(!(temp & 0x80)) return; 13846 13847 inSISIDXREG(SISSR,0x1f,temp); 13848 if(temp & 0xc0) return; 13849 13850 watchdog = 65536; 13851 while((inSISREG(SISINPSTAT) & 0x08) && --watchdog); 13852 watchdog = 65536; 13853 while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog); 13854} 13855 13856void 13857SISWaitRetraceCRT2(ScrnInfoPtr pScrn) 13858{ 13859 SISPtr pSiS = SISPTR(pScrn); 13860 int watchdog; 13861 UChar temp, reg; 13862 13863 if(SiSBridgeIsInSlaveMode(pScrn)) { 13864 SISWaitRetraceCRT1(pScrn); 13865 return; 13866 } 13867 13868 switch(pSiS->VGAEngine) { 13869 case SIS_300_VGA: 13870 reg = 0x25; 13871 break; 13872 case SIS_315_VGA: 13873 reg = 0x30; 13874 break; 13875 default: 13876 return; 13877 } 13878 13879 watchdog = 65536; 13880 do { 13881 inSISIDXREG(SISPART1, reg, temp); 13882 if(!(temp & 0x02)) break; 13883 } while(--watchdog); 13884 watchdog = 65536; 13885 do { 13886 inSISIDXREG(SISPART1, reg, temp); 13887 if(temp & 0x02) break; 13888 } while(--watchdog); 13889} 13890 13891static void 13892SISWaitVBRetrace(ScrnInfoPtr pScrn) 13893{ 13894 SISPtr pSiS = SISPTR(pScrn); 13895 13896 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 13897#ifdef SISDUALHEAD 13898 if(pSiS->DualHeadMode) { 13899 if(pSiS->SecondHead) 13900 SISWaitRetraceCRT1(pScrn); 13901 else 13902 SISWaitRetraceCRT2(pScrn); 13903 } else { 13904#endif 13905 if(pSiS->VBFlags & DISPTYPE_DISP1) { 13906 SISWaitRetraceCRT1(pScrn); 13907 } 13908 if(pSiS->VBFlags & DISPTYPE_DISP2) { 13909 if(!(SiSBridgeIsInSlaveMode(pScrn))) { 13910 SISWaitRetraceCRT2(pScrn); 13911 } 13912 } 13913#ifdef SISDUALHEAD 13914 } 13915#endif 13916 } else { 13917 SISWaitRetraceCRT1(pScrn); 13918 } 13919} 13920 13921#define MODEID_OFF 0x449 13922 13923UChar 13924SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, UShort offset, UChar value) 13925{ 13926 UChar ret = 0; 13927#ifdef SIS_USE_BIOS_SCRATCH 13928 UChar *base; 13929#endif 13930 13931 /* For some reasons (like detecting the current display mode), 13932 * we need to read (or write-back) values from the BIOS 13933 * scratch area. This area is only valid for the primary 13934 * graphics card. For the secondary, we just return some 13935 * defaults and ignore requests to write data. As regards 13936 * the display mode: If sisfb is loaded for the secondary 13937 * card, it very probably has set a mode, but in any case 13938 * informed us via its info packet. So this here will not be 13939 * called for mode detection in this case. 13940 */ 13941 13942 switch(offset) { 13943 case 0x489: 13944 ret = 0x11; /* Default VGA Info */ 13945 break; 13946 case MODEID_OFF: 13947 ret = 0x03; /* Default current display mode */ 13948 break; 13949 } 13950 13951#ifdef SIS_USE_BIOS_SCRATCH 13952 if(SISPTR(pScrn)->Primary) { 13953 base = xf86MapVidMem(pScrn->scrnIndex, VIDMEM_MMIO, 0, 0x2000); 13954 if(!base) { 13955 SISErrorLog(pScrn, "(Could not map BIOS scratch area)\n"); 13956 return ret; 13957 } 13958 13959 ret = *(base + offset); 13960 13961 /* value != 0xff means: set register */ 13962 if(value != 0xff) { 13963 *(base + offset) = value; 13964 } 13965 13966 xf86UnMapVidMem(pScrn->scrnIndex, base, 0x2000); 13967 } 13968#endif 13969 return ret; 13970} 13971 13972UChar 13973SiS_GetSetModeID(ScrnInfoPtr pScrn, UChar id) 13974{ 13975 return(SiS_GetSetBIOSScratch(pScrn, MODEID_OFF, id)); 13976} 13977 13978void 13979SiSMemCopyToVideoRam(SISPtr pSiS, UChar *to, UChar *from, int size) 13980{ 13981 if((ULong)to & 15) (*pSiS->SiSFastMemCopy)(to, from, size); 13982 else (*pSiS->SiSFastVidCopy)(to, from, size); 13983} 13984 13985void 13986SiSMemCopyFromVideoRam(SISPtr pSiS, UChar *to, UChar *from, int size) 13987{ 13988 if((ULong)to & 15) (*pSiS->SiSFastMemCopyFrom)(to, from, size); 13989 else (*pSiS->SiSFastVidCopyFrom)(to, from, size); 13990} 13991 13992void 13993sisSaveUnlockExtRegisterLock(SISPtr pSiS, UChar *reg1, UChar *reg2) 13994{ 13995 register UChar val; 13996 ULong mylockcalls; 13997#ifdef TWDEBUG 13998 UChar val1, val2; 13999 int i; 14000#endif 14001 14002 pSiS->lockcalls++; 14003 mylockcalls = pSiS->lockcalls; 14004 14005 /* check if already unlocked */ 14006 inSISIDXREG(SISSR, 0x05, val); 14007 14008 if(val != 0xa1) { 14009 14010 /* save State */ 14011 if(reg1) *reg1 = val; 14012 14013 /* unlock */ 14014 outSISIDXREG(SISSR, 0x05, 0x86); 14015 14016 /* Now check again */ 14017 inSISIDXREG(SISSR, 0x05, val); 14018 14019 if(val != 0xA1) { 14020 14021 xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING, 14022 "Failed to unlock SR registers at relocated i/o ports\n"); 14023 14024#ifdef TWDEBUG 14025 for(i = 0; i <= 0x3f; i++) { 14026 inSISIDXREG(SISSR, i, val1); 14027 inSISIDXREG(0x3c4, i, val2); 14028 xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO, 14029 "SR%02d: RelIO=0x%02x 0x3c4=0x%02x (%ld)\n", 14030 i, val1, val2, mylockcalls); 14031 } 14032#endif 14033 14034 /* Emergency measure: unlock at 0x3c4, and try to enable relocated IO ports */ 14035 switch(pSiS->VGAEngine) { 14036 case SIS_OLD_VGA: 14037 case SIS_530_VGA: 14038 outSISIDXREG(0x3c4, 0x05, 0x86); 14039 andSISIDXREG(0x3c4, 0x33, ~0x20); 14040 break; 14041 case SIS_300_VGA: 14042 case SIS_315_VGA: 14043 outSISIDXREG(0x3c4, 0x05, 0x86); 14044 orSISIDXREG(0x3c4, 0x20, 0x20); 14045 break; 14046 } 14047 outSISIDXREG(SISSR, 0x05, 0x86); 14048 inSISIDXREG(SISSR, 0x05, val); 14049 if(val != 0xa1) { 14050 SISErrorLog(pSiS->pScrn, 14051 "Failed to unlock SR registers (%p, %lx, 0x%02x; %ld)\n", 14052 (void *)pSiS, (ULong)pSiS->RelIO, val, mylockcalls); 14053 /* Now await doom... */ 14054 } 14055 } 14056 } 14057 if((pSiS->VGAEngine == SIS_OLD_VGA) || (pSiS->VGAEngine == SIS_530_VGA)) { 14058 inSISIDXREG(SISCR, 0x80, val); 14059 if(val != 0xa1) { 14060 /* save State */ 14061 if(reg2) *reg2 = val; 14062 outSISIDXREG(SISCR, 0x80, 0x86); 14063 inSISIDXREG(SISCR, 0x80, val); 14064 if(val != 0xA1) { 14065 SISErrorLog(pSiS->pScrn, 14066 "Failed to unlock cr registers (%p, %lx, 0x%02x)\n", 14067 (void *)pSiS, (ULong)pSiS->RelIO, val); 14068 } 14069 } 14070 } 14071} 14072 14073void 14074sisRestoreExtRegisterLock(SISPtr pSiS, UChar reg1, UChar reg2) 14075{ 14076 /* restore lock */ 14077#ifndef UNLOCK_ALWAYS 14078 outSISIDXREG(SISSR, 0x05, reg1 == 0xA1 ? 0x86 : 0x00); 14079 if((pSiS->VGAEngine == SIS_OLD_VGA) || (pSiS->VGAEngine == SIS_530_VGA)) { 14080 outSISIDXREG(SISCR, 0x80, reg2 == 0xA1 ? 0x86 : 0x00); 14081 } 14082#endif 14083} 14084 14085