sis_driver.c revision c8409b00
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#include <inputstr.h> 90 91#ifdef XF86DRI 92#include "dri.h" 93#endif 94 95/* Globals (yes, these ARE really required to be global) */ 96 97#ifdef SISUSEDEVPORT 98int sisdevport = 0; 99#endif 100 101#ifdef SISDUALHEAD 102static int SISEntityIndex = -1; 103#endif 104 105#ifdef SISMERGED 106#ifdef SISXINERAMA 107static Bool SiSnoPanoramiXExtension = TRUE; 108static int SiSXineramaNumScreens = 0; 109static SiSXineramaData *SiSXineramadataPtr = NULL; 110static int SiSXineramaGeneration; 111 112static int SiSProcXineramaQueryVersion(ClientPtr client); 113static int SiSProcXineramaGetState(ClientPtr client); 114static int SiSProcXineramaGetScreenCount(ClientPtr client); 115static int SiSProcXineramaGetScreenSize(ClientPtr client); 116static int SiSProcXineramaIsActive(ClientPtr client); 117static int SiSProcXineramaQueryScreens(ClientPtr client); 118static int SiSSProcXineramaDispatch(ClientPtr client); 119#endif 120#endif 121 122/* 123 * This is intentionally screen-independent. It indicates the binding 124 * choice made in the first PreInit. 125 */ 126static int pix24bpp = 0; 127 128/* 129 * This contains the functions needed by the server after loading the driver 130 * module. It must be supplied, and gets passed back by the SetupProc 131 * function in the dynamic case. In the static case, a reference to this 132 * is compiled in, and this requires that the name of this DriverRec be 133 * an upper-case version of the driver name. 134 */ 135 136#ifdef _X_EXPORT 137_X_EXPORT 138#endif 139DriverRec SIS = { 140 SIS_CURRENT_VERSION, 141 SIS_DRIVER_NAME, 142 SISIdentify, 143 SISProbe, 144 SISAvailableOptions, 145 NULL, 146 0 147#ifdef SIS_HAVE_DRIVER_FUNC 148 , 149 SISDriverFunc 150#endif 151}; 152 153static SymTabRec SISChipsets[] = { 154 { PCI_CHIP_SIS5597, "SIS5597/5598" }, 155 { PCI_CHIP_SIS530, "SIS530/620" }, 156 { PCI_CHIP_SIS6326, "SIS6326/AGP/DVD" }, 157 { PCI_CHIP_SIS300, "SIS300/305" }, 158 { PCI_CHIP_SIS630, "SIS630/730" }, 159 { PCI_CHIP_SIS540, "SIS540" }, 160 { PCI_CHIP_SIS315, "SIS315" }, 161 { PCI_CHIP_SIS315H, "SIS315H" }, 162 { PCI_CHIP_SIS315PRO, "SIS315PRO/E" }, 163 { PCI_CHIP_SIS550, "SIS550" }, 164 { PCI_CHIP_SIS650, "SIS650/M650/651/740" }, 165 { PCI_CHIP_SIS330, "SIS330(Xabre)" }, 166 { PCI_CHIP_SIS660, "SIS660/[M]661[F|M]X/[M]670/[M]741[GX]/[M]760[GX]/[M]761[GX]/[M]770[GX]" }, 167 { PCI_CHIP_SIS340, "SIS340" }, 168 { -1, NULL } 169}; 170 171static PciChipsets SISPciChipsets[] = { 172 { PCI_CHIP_SIS5597, PCI_CHIP_SIS5597, RES_SHARED_VGA }, 173 { PCI_CHIP_SIS530, PCI_CHIP_SIS530, RES_SHARED_VGA }, 174 { PCI_CHIP_SIS6326, PCI_CHIP_SIS6326, RES_SHARED_VGA }, 175 { PCI_CHIP_SIS300, PCI_CHIP_SIS300, RES_SHARED_VGA }, 176 { PCI_CHIP_SIS630, PCI_CHIP_SIS630, RES_SHARED_VGA }, 177 { PCI_CHIP_SIS540, PCI_CHIP_SIS540, RES_SHARED_VGA }, 178 { PCI_CHIP_SIS550, PCI_CHIP_SIS550, RES_SHARED_VGA }, 179 { PCI_CHIP_SIS315, PCI_CHIP_SIS315, RES_SHARED_VGA }, 180 { PCI_CHIP_SIS315H, PCI_CHIP_SIS315H, RES_SHARED_VGA }, 181 { PCI_CHIP_SIS315PRO, PCI_CHIP_SIS315PRO, RES_SHARED_VGA }, 182 { PCI_CHIP_SIS650, PCI_CHIP_SIS650, RES_SHARED_VGA }, 183 { PCI_CHIP_SIS330, PCI_CHIP_SIS330, RES_SHARED_VGA }, 184 { PCI_CHIP_SIS660, PCI_CHIP_SIS660, RES_SHARED_VGA }, 185 { PCI_CHIP_SIS340, PCI_CHIP_SIS340, RES_SHARED_VGA }, 186 { -1, -1, RES_UNDEFINED } 187}; 188 189static SymTabRec XGIChipsets[] = { 190 { PCI_CHIP_XGIXG20, "Volari Z7 (XG20)" }, 191 { PCI_CHIP_XGIXG40, "Volari V3XT/V5/V8/Duo (XG40)" }, 192 { -1, NULL } 193}; 194 195static PciChipsets XGIPciChipsets[] = { 196 { PCI_CHIP_XGIXG20, PCI_CHIP_XGIXG20, RES_SHARED_VGA }, 197 { PCI_CHIP_XGIXG40, PCI_CHIP_XGIXG40, RES_SHARED_VGA }, 198 { -1, -1, RES_UNDEFINED } 199}; 200 201#ifdef XFree86LOADER 202 203static MODULESETUPPROTO(sisSetup); 204 205static XF86ModuleVersionInfo sisVersRec = 206{ 207 SIS_DRIVER_NAME, 208 MODULEVENDORSTRING, 209 MODINFOSTRING1, 210 MODINFOSTRING2, 211#ifdef XORG_VERSION_CURRENT 212 XORG_VERSION_CURRENT, 213#else 214 XF86_VERSION_CURRENT, 215#endif 216 SIS_MAJOR_VERSION, SIS_MINOR_VERSION, SIS_PATCHLEVEL, 217 ABI_CLASS_VIDEODRV, /* This is a video driver */ 218 ABI_VIDEODRV_VERSION, 219 MOD_CLASS_VIDEODRV, 220 {0,0,0,0} 221}; 222 223#ifdef _X_EXPORT 224_X_EXPORT 225#endif 226XF86ModuleData sisModuleData = { &sisVersRec, sisSetup, NULL }; 227 228pointer 229sisSetup(pointer module, pointer opts, int *errmaj, int *errmin) 230{ 231 static Bool setupDone = FALSE; 232 233 if(!setupDone) { 234 setupDone = TRUE; 235 xf86AddDriver(&SIS, module, SIS_HaveDriverFuncs); 236 return (pointer)TRUE; 237 } 238 239 if(errmaj) *errmaj = LDR_ONCEONLY; 240 return NULL; 241} 242 243#endif /* XFree86LOADER */ 244 245/* Mandatory */ 246static void 247SISIdentify(int flags) 248{ 249 xf86PrintChipsets(SIS_NAME, "driver for SiS chipsets", SISChipsets); 250 xf86PrintChipsets(SIS_NAME, "driver for XGI chipsets", XGIChipsets); 251} 252 253#ifdef SIS_HAVE_DRIVER_FUNC 254static Bool 255SISDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op, pointer ptr) 256{ 257 CARD32 *flag; 258 259 switch(op) { 260 case RR_GET_INFO: 261 break; 262 case RR_SET_CONFIG: 263 break; 264 case GET_REQUIRED_HW_INTERFACES: 265 break; 266 } 267 return TRUE; 268} 269#endif 270 271static Bool 272SISGetRec(ScrnInfoPtr pScrn) 273{ 274 /* Allocate an SISRec, and hook it into pScrn->driverPrivate. 275 * pScrn->driverPrivate is initialised to NULL, so we can check if 276 * the allocation has already been done. 277 */ 278 if(pScrn->driverPrivate != NULL) return TRUE; 279 280 pScrn->driverPrivate = xnfcalloc(sizeof(SISRec), 1); 281 282 /* Initialise it to 0 */ 283 memset(pScrn->driverPrivate, 0, sizeof(SISRec)); 284 285 return TRUE; 286} 287 288static void 289SISFreeRec(ScrnInfoPtr pScrn) 290{ 291 SISPtr pSiS = SISPTR(pScrn); 292#ifdef SISDUALHEAD 293 SISEntPtr pSiSEnt = NULL; 294#endif 295 296 /* Just to make sure... */ 297 if(!pSiS) return; 298 299#ifdef SISDUALHEAD 300 pSiSEnt = pSiS->entityPrivate; 301#endif 302 303 if(pSiS->pstate) xfree(pSiS->pstate); 304 pSiS->pstate = NULL; 305 if(pSiS->fonts) xfree(pSiS->fonts); 306 pSiS->fonts = NULL; 307 308#ifdef SISDUALHEAD 309 if(pSiSEnt) { 310 if(!pSiS->SecondHead) { 311 /* Free memory only if we are first head; in case of an error 312 * during init of the second head, the server will continue - 313 * and we need the BIOS image and SiS_Private for the first 314 * head. 315 */ 316 if(pSiSEnt->BIOS) xfree(pSiSEnt->BIOS); 317 pSiSEnt->BIOS = pSiS->BIOS = NULL; 318 if(pSiSEnt->SiS_Pr) xfree(pSiSEnt->SiS_Pr); 319 pSiSEnt->SiS_Pr = pSiS->SiS_Pr = NULL; 320 if(pSiSEnt->RenderAccelArray) xfree(pSiSEnt->RenderAccelArray); 321 pSiSEnt->RenderAccelArray = pSiS->RenderAccelArray = NULL; 322 pSiSEnt->pScrn_1 = NULL; 323 } else { 324 pSiS->BIOS = NULL; 325 pSiS->SiS_Pr = NULL; 326 pSiS->RenderAccelArray = NULL; 327 pSiSEnt->pScrn_2 = NULL; 328 } 329 } else { 330#endif 331 if(pSiS->BIOS) xfree(pSiS->BIOS); 332 pSiS->BIOS = NULL; 333 if(pSiS->SiS_Pr) xfree(pSiS->SiS_Pr); 334 pSiS->SiS_Pr = NULL; 335 if(pSiS->RenderAccelArray) xfree(pSiS->RenderAccelArray); 336 pSiS->RenderAccelArray = NULL; 337#ifdef SISDUALHEAD 338 } 339#endif 340#ifdef SISMERGED 341 if(pSiS->CRT2HSync) xfree(pSiS->CRT2HSync); 342 pSiS->CRT2HSync = NULL; 343 if(pSiS->CRT2VRefresh) xfree(pSiS->CRT2VRefresh); 344 pSiS->CRT2VRefresh = NULL; 345 if(pSiS->MetaModes) xfree(pSiS->MetaModes); 346 pSiS->MetaModes = NULL; 347 if(pSiS->CRT2pScrn) { 348 if(pSiS->CRT2pScrn->modes) { 349 while(pSiS->CRT2pScrn->modes) 350 xf86DeleteMode(&pSiS->CRT2pScrn->modes, pSiS->CRT2pScrn->modes); 351 } 352 if(pSiS->CRT2pScrn->monitor) { 353 if(pSiS->CRT2pScrn->monitor->Modes) { 354 while(pSiS->CRT2pScrn->monitor->Modes) 355 xf86DeleteMode(&pSiS->CRT2pScrn->monitor->Modes, pSiS->CRT2pScrn->monitor->Modes); 356 } 357 if(pSiS->CRT2pScrn->monitor->DDC) xfree(pSiS->CRT2pScrn->monitor->DDC); 358 xfree(pSiS->CRT2pScrn->monitor); 359 } 360 xfree(pSiS->CRT2pScrn); 361 pSiS->CRT2pScrn = NULL; 362 } 363 if(pSiS->CRT1Modes) { 364 if(pSiS->CRT1Modes != pScrn->modes) { 365 if(pScrn->modes) { 366 pScrn->currentMode = pScrn->modes; 367 do { 368 DisplayModePtr p = pScrn->currentMode->next; 369 if(pScrn->currentMode->Private) 370 xfree(pScrn->currentMode->Private); 371 xfree(pScrn->currentMode); 372 pScrn->currentMode = p; 373 } while(pScrn->currentMode != pScrn->modes); 374 } 375 pScrn->currentMode = pSiS->CRT1CurrentMode; 376 pScrn->modes = pSiS->CRT1Modes; 377 pSiS->CRT1CurrentMode = NULL; 378 pSiS->CRT1Modes = NULL; 379 } 380 } 381#endif 382 while(pSiS->SISVESAModeList) { 383 sisModeInfoPtr mp = pSiS->SISVESAModeList->next; 384 xfree(pSiS->SISVESAModeList); 385 pSiS->SISVESAModeList = mp; 386 } 387 if(pSiS->pVbe) vbeFree(pSiS->pVbe); 388 pSiS->pVbe = NULL; 389 390#ifdef SISUSEDEVPORT 391 if(pSiS->sisdevportopen) close(sisdevport); 392#endif 393 394 if(pScrn->driverPrivate == NULL) 395 return; 396 xfree(pScrn->driverPrivate); 397 pScrn->driverPrivate = NULL; 398} 399 400static void 401SISErrorLog(ScrnInfoPtr pScrn, const char *format, ...) 402{ 403 va_list ap; 404 static const char *str = "**************************************************\n"; 405 406 va_start(ap, format); 407 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, str); 408 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 409 " ERROR:\n"); 410 xf86VDrvMsgVerb(pScrn->scrnIndex, X_ERROR, 1, format, ap); 411 va_end(ap); 412 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 413 " END OF MESSAGE\n"); 414 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, str); 415} 416 417static void 418SiS_SiSFB_Lock(ScrnInfoPtr pScrn, Bool lock) 419{ 420 SISPtr pSiS = SISPTR(pScrn); 421 int fd; 422 CARD32 parm; 423 424 if(!pSiS->sisfbfound) return; 425 if(!pSiS->sisfb_havelock) return; 426 427 if((fd = open(pSiS->sisfbdevname, O_RDONLY)) != -1) { 428 parm = lock ? 1 : 0; 429 ioctl(fd, SISFB_SET_LOCK, &parm); 430 close(fd); 431 } 432} 433 434/* Probe() 435 * 436 * Mandatory 437 */ 438static Bool 439SISProbe(DriverPtr drv, int flags) 440{ 441 int i; 442 GDevPtr *devSections; 443 int *usedChipsSiS, *usedChipsXGI; 444 int numDevSections; 445 int numUsed, numUsedSiS, numUsedXGI; 446 Bool foundScreen = FALSE; 447 448 /* 449 * The aim here is to find all cards that this driver can handle, 450 * and for the ones not already claimed by another driver, claim the 451 * slot, and allocate a ScrnInfoRec. 452 * 453 * This should be a minimal probe, and it should under no circumstances 454 * change the state of the hardware. Because a device is found, don't 455 * assume that it will be used. Don't do any initialisations other than 456 * the required ScrnInfoRec initialisations. Don't allocate any new 457 * data structures. 458 * 459 */ 460 461 /* 462 * Next we check, if there has been a chipset override in the config file. 463 * For this we must find out if there is an active device section which 464 * is relevant, i.e., which has no driver specified or has THIS driver 465 * specified. 466 */ 467 468 if((numDevSections = xf86MatchDevice(SIS_DRIVER_NAME, &devSections)) <= 0) { 469 /* 470 * There's no matching device section in the config file, so quit 471 * now. 472 */ 473 return FALSE; 474 } 475 476 /* 477 * We need to probe the hardware first. We then need to see how this 478 * fits in with what is given in the config file, and allow the config 479 * file info to override any contradictions. 480 */ 481 482 /* 483 * All of the cards this driver supports are PCI, so the "probing" just 484 * amounts to checking the PCI data that the server has already collected. 485 */ 486#ifndef XSERVER_LIBPCIACCESS 487 if(xf86GetPciVideoInfo() == NULL) { 488 /* 489 * We won't let anything in the config file override finding no 490 * PCI video cards at all. 491 */ 492 return FALSE; 493 } 494#endif 495 496 numUsedSiS = xf86MatchPciInstances(SIS_NAME, PCI_VENDOR_SIS, 497 SISChipsets, SISPciChipsets, devSections, 498 numDevSections, drv, &usedChipsSiS); 499 500 numUsedXGI = xf86MatchPciInstances(SIS_NAME, PCI_VENDOR_XGI, 501 XGIChipsets, XGIPciChipsets, devSections, 502 numDevSections, drv, &usedChipsXGI); 503 504 /* Free it since we don't need that list after this */ 505 xfree(devSections); 506 507 numUsed = numUsedSiS + numUsedXGI; 508 509 if(numUsed <= 0) 510 return FALSE; 511 512 if(flags & PROBE_DETECT) { 513 514 foundScreen = TRUE; 515 516 } else for(i = 0; i < numUsed; i++) { 517 518 ScrnInfoPtr pScrn; 519#ifdef SISDUALHEAD 520 EntityInfoPtr pEnt; 521#endif 522 523 /* Allocate a ScrnInfoRec and claim the slot */ 524 pScrn = NULL; 525 526 if((pScrn = xf86ConfigPciEntity(pScrn, 0, 527 (i < numUsedSiS) ? usedChipsSiS[i] : usedChipsXGI[i-numUsedSiS], 528 (i < numUsedSiS) ? SISPciChipsets : XGIPciChipsets, 529 NULL, NULL, NULL, NULL, NULL))) { 530 /* Fill in what we can of the ScrnInfoRec */ 531 pScrn->driverVersion = SIS_CURRENT_VERSION; 532 pScrn->driverName = SIS_DRIVER_NAME; 533 pScrn->name = SIS_NAME; 534 pScrn->Probe = SISProbe; 535 pScrn->PreInit = SISPreInit; 536 pScrn->ScreenInit = SISScreenInit; 537 pScrn->SwitchMode = SISSwitchMode; 538 pScrn->AdjustFrame = SISAdjustFrame; 539 pScrn->EnterVT = SISEnterVT; 540 pScrn->LeaveVT = SISLeaveVT; 541 pScrn->FreeScreen = SISFreeScreen; 542 pScrn->ValidMode = SISValidMode; 543 544 foundScreen = TRUE; 545 } 546 547#ifdef SISDUALHEAD 548 pEnt = xf86GetEntityInfo((i < numUsedSiS) ? usedChipsSiS[i] : usedChipsXGI[i-numUsedSiS]); 549 550 if(pEnt->chipset == PCI_CHIP_SIS630 || pEnt->chipset == PCI_CHIP_SIS540 || 551 pEnt->chipset == PCI_CHIP_SIS650 || pEnt->chipset == PCI_CHIP_SIS550 || 552 pEnt->chipset == PCI_CHIP_SIS315 || pEnt->chipset == PCI_CHIP_SIS315H || 553 pEnt->chipset == PCI_CHIP_SIS315PRO || pEnt->chipset == PCI_CHIP_SIS330 || 554 pEnt->chipset == PCI_CHIP_SIS300 || pEnt->chipset == PCI_CHIP_SIS660 || 555 pEnt->chipset == PCI_CHIP_SIS340 || pEnt->chipset == PCI_CHIP_XGIXG40) { 556 557 SISEntPtr pSiSEnt = NULL; 558 DevUnion *pPriv; 559 560 xf86SetEntitySharable((i < numUsedSiS) ? usedChipsSiS[i] : usedChipsXGI[i-numUsedSiS]); 561 if(SISEntityIndex < 0) { 562 SISEntityIndex = xf86AllocateEntityPrivateIndex(); 563 } 564 pPriv = xf86GetEntityPrivate(pScrn->entityList[0], SISEntityIndex); 565 if(!pPriv->ptr) { 566 pPriv->ptr = xnfcalloc(sizeof(SISEntRec), 1); 567 pSiSEnt = pPriv->ptr; 568 memset(pSiSEnt, 0, sizeof(SISEntRec)); 569 pSiSEnt->lastInstance = -1; 570 } else { 571 pSiSEnt = pPriv->ptr; 572 } 573 pSiSEnt->lastInstance++; 574 xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0], 575 pSiSEnt->lastInstance); 576 } 577#endif /* DUALHEAD */ 578 579 } 580 581 if(usedChipsSiS) xfree(usedChipsSiS); 582 if(usedChipsXGI) xfree(usedChipsXGI); 583 584 return foundScreen; 585} 586 587/* Various helpers */ 588 589static unsigned short 590calcgammaval(int j, int nramp, float invgamma, float bri, float c) 591{ 592 float k = (float)j; 593 float nrm1 = (float)(nramp - 1); 594 float con = c * nrm1 / 3.0; 595 float l, v; 596 597 if(con != 0.0) { 598 l = nrm1 / 2.0; 599 if(con <= 0.0) { 600 k -= l; 601 k *= (l + con) / l; 602 } else { 603 l -= 1.0; 604 k -= l; 605 k *= l / (l - con); 606 } 607 k += l; 608 if(k < 0.0) k = 0.0; 609 } 610 611 if(invgamma == 1.0) { 612 v = k / nrm1 * 65535.0; 613 } else { 614 v = pow(k / nrm1, invgamma) * 65535.0 + 0.5; 615 } 616 617 v += (bri * (65535.0 / 3.0)) ; 618 619 if(v < 0.0) v = 0.0; 620 else if(v > 65535.0) v = 65535.0; 621 622 return (unsigned short)v; 623} 624 625#ifdef SISGAMMARAMP 626void 627SISCalculateGammaRamp(ScreenPtr pScreen, ScrnInfoPtr pScrn) 628{ 629 SISPtr pSiS = SISPTR(pScrn); 630 int i, j, nramp; 631 UShort *ramp[3]; 632 float gamma_max[3], framp; 633 Bool newmethod = FALSE; 634 635 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_OLDGAMMAINUSE)) { 636 newmethod = TRUE; 637 } else { 638 gamma_max[0] = (float)pSiS->GammaBriR / 1000; 639 gamma_max[1] = (float)pSiS->GammaBriG / 1000; 640 gamma_max[2] = (float)pSiS->GammaBriB / 1000; 641 } 642 643 if(!(nramp = xf86GetGammaRampSize(pScreen))) return; 644 645 for(i=0; i<3; i++) { 646 ramp[i] = (UShort *)xalloc(nramp * sizeof(UShort)); 647 if(!ramp[i]) { 648 if(ramp[0]) { xfree(ramp[0]); ramp[0] = NULL; } 649 if(ramp[1]) { xfree(ramp[1]); ramp[1] = NULL; } 650 return; 651 } 652 } 653 654 if(newmethod) { 655 656 for(i = 0; i < 3; i++) { 657 658 float invgamma = 0.0, bri = 0.0, con = 0.0; 659 660 switch(i) { 661 case 0: invgamma = 1. / pScrn->gamma.red; 662 bri = pSiS->NewGammaBriR; 663 con = pSiS->NewGammaConR; 664 break; 665 case 1: invgamma = 1. / pScrn->gamma.green; 666 bri = pSiS->NewGammaBriG; 667 con = pSiS->NewGammaConG; 668 break; 669 case 2: invgamma = 1. / pScrn->gamma.blue; 670 bri = pSiS->NewGammaBriB; 671 con = pSiS->NewGammaConB; 672 break; 673 } 674 675 for(j = 0; j < nramp; j++) { 676 ramp[i][j] = calcgammaval(j, nramp, invgamma, bri, con); 677 } 678 679 } 680 681 } else { 682 683 for(i = 0; i < 3; i++) { 684 int fullscale = 65535 * gamma_max[i]; 685 float dramp = 1. / (nramp - 1); 686 float invgamma = 0.0, v; 687 688 switch(i) { 689 case 0: invgamma = 1. / pScrn->gamma.red; break; 690 case 1: invgamma = 1. / pScrn->gamma.green; break; 691 case 2: invgamma = 1. / pScrn->gamma.blue; break; 692 } 693 694 for(j = 0; j < nramp; j++) { 695 framp = pow(j * dramp, invgamma); 696 697 v = (fullscale < 0) ? (65535 + fullscale * framp) : 698 fullscale * framp; 699 if(v < 0) v = 0; 700 else if(v > 65535) v = 65535; 701 ramp[i][j] = (UShort)v; 702 } 703 } 704 705 } 706 707 xf86ChangeGammaRamp(pScreen, nramp, ramp[0], ramp[1], ramp[2]); 708 709 xfree(ramp[0]); 710 xfree(ramp[1]); 711 xfree(ramp[2]); 712 ramp[0] = ramp[1] = ramp[2] = NULL; 713} 714#endif 715 716void 717SISCalculateGammaRampCRT2(ScrnInfoPtr pScrn) 718{ 719 SISPtr pSiS = SISPTR(pScrn); 720 int i; 721 int myshift = 16 - pScrn->rgbBits; 722 int maxvalue = (1 << pScrn->rgbBits) - 1; 723 int reds = pScrn->mask.red >> pScrn->offset.red; 724 int greens = pScrn->mask.green >> pScrn->offset.green; 725 int blues = pScrn->mask.blue >> pScrn->offset.blue; 726 float framp, invgamma1, invgamma2, invgamma3, v; 727 728 invgamma1 = 1. / pSiS->GammaR2; 729 invgamma2 = 1. / pSiS->GammaG2; 730 invgamma3 = 1. / pSiS->GammaB2; 731 732 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_OLDGAMMAINUSE)) { 733 734 for(i = 0; i < pSiS->CRT2ColNum; i++) { 735 pSiS->crt2gcolortable[i].red = calcgammaval(i, pSiS->CRT2ColNum, invgamma1, 736 pSiS->NewGammaBriR2, pSiS->NewGammaConR2) >> myshift; 737 pSiS->crt2gcolortable[i].green = calcgammaval(i, pSiS->CRT2ColNum, invgamma2, 738 pSiS->NewGammaBriG2, pSiS->NewGammaConG2) >> myshift; 739 pSiS->crt2gcolortable[i].blue = calcgammaval(i, pSiS->CRT2ColNum, invgamma3, 740 pSiS->NewGammaBriB2, pSiS->NewGammaConB2) >> myshift; 741 } 742 743 } else { 744 745 int fullscale1 = 65536 * (float)pSiS->GammaBriR2 / 1000; 746 int fullscale2 = 65536 * (float)pSiS->GammaBriG2 / 1000; 747 int fullscale3 = 65536 * (float)pSiS->GammaBriB2 / 1000; 748 749 float dramp = 1. / (pSiS->CRT2ColNum - 1); 750 751 for(i = 0; i < pSiS->CRT2ColNum; i++) { 752 framp = pow(i * dramp, invgamma1); 753 v = (fullscale1 < 0) ? (65535 + fullscale1 * framp) : fullscale1 * framp; 754 if(v < 0) v = 0; 755 else if(v > 65535) v = 65535; 756 pSiS->crt2gcolortable[i].red = ((UShort)v) >> myshift; 757 framp = pow(i * dramp, invgamma2); 758 v = (fullscale2 < 0) ? (65535 + fullscale2 * framp) : fullscale2 * framp; 759 if(v < 0) v = 0; 760 else if(v > 65535) v = 65535; 761 pSiS->crt2gcolortable[i].green = ((UShort)v) >> myshift; 762 framp = pow(i * dramp, invgamma3); 763 v = (fullscale3 < 0) ? (65535 + fullscale3 * framp) : fullscale3 * framp; 764 if(v < 0) v = 0; 765 else if(v > 65535) v = 65535; 766 pSiS->crt2gcolortable[i].blue = ((UShort)v) >> myshift; 767 } 768 769 } 770 771 for(i = 0; i < pSiS->CRT2ColNum; i++) { 772 pSiS->crt2colors[i].red = 773 pSiS->crt2gcolortable[i * maxvalue / reds].red; 774 pSiS->crt2colors[i].green = 775 pSiS->crt2gcolortable[i * maxvalue / greens].green; 776 pSiS->crt2colors[i].blue = 777 pSiS->crt2gcolortable[i * maxvalue / blues].blue; 778 } 779} 780 781/* If monitor section has no HSync/VRefresh data, 782 * derive it from DDC data. 783 */ 784static void 785SiSSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) 786{ 787 MonPtr mon = pScrn->monitor; 788 xf86MonPtr ddc = mon->DDC; 789 float myhhigh = 0.0, myhlow = 0.0, htest; 790 int myvhigh = 0, myvlow = 0, vtest, i; 791 UChar temp; 792 const myhddctiming myhtiming[12] = { 793 { 1, 0x20, 31.6 }, /* rounded up by .1 */ 794 { 1, 0x80, 31.6 }, 795 { 1, 0x02, 35.3 }, 796 { 1, 0x04, 37.6 }, 797 { 1, 0x08, 38.0 }, 798 { 1, 0x01, 38.0 }, 799 { 2, 0x40, 47.0 }, 800 { 2, 0x80, 48.2 }, 801 { 2, 0x08, 48.5 }, 802 { 2, 0x04, 56.6 }, 803 { 2, 0x02, 60.1 }, 804 { 2, 0x01, 80.1 } 805 }; 806 const myvddctiming myvtiming[11] = { 807 { 1, 0x02, 56 }, 808 { 1, 0x01, 60 }, 809 { 2, 0x08, 60 }, 810 { 2, 0x04, 70 }, 811 { 1, 0x80, 71 }, 812 { 1, 0x08, 72 }, 813 { 2, 0x80, 72 }, 814 { 1, 0x04, 75 }, 815 { 2, 0x40, 75 }, 816 { 2, 0x02, 75 }, 817 { 2, 0x01, 75 } 818 }; 819 820 if(flag) { /* HSync */ 821 822 for(i = 0; i < 4; i++) { 823 if(ddc->det_mon[i].type == DS_RANGES) { 824 mon->nHsync = 1; 825 mon->hsync[0].lo = ddc->det_mon[i].section.ranges.min_h; 826 mon->hsync[0].hi = ddc->det_mon[i].section.ranges.max_h; 827 if(mon->hsync[0].lo > 32.0 || mon->hsync[0].hi < 31.0) { 828 if(ddc->timings1.t1 & 0x80) { 829 mon->nHsync++; 830 mon->hsync[1].lo = 31.0; 831 mon->hsync[1].hi = 32.0; 832 } 833 } 834 return; 835 } 836 } 837 838 /* If no sync ranges detected in detailed timing table, we 839 * derive them from supported VESA modes. 840 */ 841 842 for(i = 0; i < 12; i++) { 843 if(myhtiming[i].whichone == 1) temp = ddc->timings1.t1; 844 else temp = ddc->timings1.t2; 845 if(temp & myhtiming[i].mask) { 846 if((i == 0) || (myhlow > myhtiming[i].rate)) 847 myhlow = myhtiming[i].rate; 848 } 849 if(myhtiming[11-i].whichone == 1) temp = ddc->timings1.t1; 850 else temp = ddc->timings1.t2; 851 if(temp & myhtiming[11-i].mask) { 852 if((i == 0) || (myhhigh < myhtiming[11-i].rate)) 853 myhhigh = myhtiming[11-i].rate; 854 } 855 } 856 857 for(i = 0; i < STD_TIMINGS; i++) { 858 if(ddc->timings2[i].hsize > 256) { 859 htest = ddc->timings2[i].refresh * 1.05 * ddc->timings2[i].vsize / 1000.0; 860 if(htest < myhlow) myhlow = htest; 861 if(htest > myhhigh) myhhigh = htest; 862 } 863 } 864 865 if((myhhigh > 0.0) && (myhlow > 0.0)) { 866 mon->nHsync = 1; 867 mon->hsync[0].lo = myhlow - 0.1; 868 mon->hsync[0].hi = myhhigh; 869 } 870 871 872 } else { /* Vrefresh */ 873 874 for(i = 0; i < 4; i++) { 875 if(ddc->det_mon[i].type == DS_RANGES) { 876 mon->nVrefresh = 1; 877 mon->vrefresh[0].lo = ddc->det_mon[i].section.ranges.min_v; 878 mon->vrefresh[0].hi = ddc->det_mon[i].section.ranges.max_v; 879 if(mon->vrefresh[0].lo > 72 || mon->vrefresh[0].hi < 70) { 880 if(ddc->timings1.t1 & 0x80) { 881 mon->nVrefresh++; 882 mon->vrefresh[1].lo = 71; 883 mon->vrefresh[1].hi = 71; 884 } 885 } 886 return; 887 } 888 } 889 890 for(i = 0; i < 11; i++) { 891 if(myvtiming[i].whichone == 1) temp = ddc->timings1.t1; 892 else temp = ddc->timings1.t2; 893 if(temp & myvtiming[i].mask) { 894 if((i == 0) || (myvlow > myvtiming[i].rate)) 895 myvlow = myvtiming[i].rate; 896 } 897 if(myvtiming[10-i].whichone == 1) temp = ddc->timings1.t1; 898 else temp = ddc->timings1.t2; 899 if(temp & myvtiming[10-i].mask) { 900 if((i == 0) || (myvhigh < myvtiming[10-i].rate)) 901 myvhigh = myvtiming[10-i].rate; 902 } 903 } 904 905 for(i = 0; i < STD_TIMINGS; i++) { 906 if(ddc->timings2[i].hsize > 256) { 907 vtest = ddc->timings2[i].refresh; 908 if(vtest < myvlow) myvlow = vtest; 909 if(vtest > myvhigh) myvhigh = vtest; 910 } 911 } 912 913 if((myvhigh > 0) && (myvlow > 0)) { 914 mon->nVrefresh = 1; 915 mon->vrefresh[0].lo = myvlow; 916 mon->vrefresh[0].hi = myvhigh; 917 } 918 919 } 920} 921 922static Bool 923SiSAllowSyncOverride(SISPtr pSiS, Bool fromDDC) 924{ 925 if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return FALSE; 926 927#ifdef SISDUALHEAD 928 if(pSiS->DualHeadMode) { 929 if(pSiS->SecondHead) { 930 if((pSiS->VBFlags & CRT1_LCDA) && (!fromDDC)) return TRUE; 931 } else { 932 if((pSiS->VBFlags & CRT2_TV) || 933 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC))) return TRUE; 934 } 935 return FALSE; 936 } 937#endif 938 939#ifdef SISMERGED 940 if(pSiS->MergedFB) { 941 if((pSiS->VBFlags & CRT1_LCDA) && (!fromDDC)) return TRUE; 942 return FALSE; 943 } 944#endif 945 946 if(!(pSiS->VBFlags & DISPTYPE_CRT1)) { 947 if( (pSiS->VBFlags & CRT2_TV) || 948 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC)) ) return TRUE; 949 } else if((pSiS->VBFlags & CRT1_LCDA) && (!fromDDC)) return TRUE; 950 951 return FALSE; 952} 953 954static Bool 955SiSCheckForH(float hsync, MonPtr monitor) 956{ 957 int i; 958 for(i = 0; i < monitor->nHsync; i++) { 959 if((hsync > monitor->hsync[i].lo * (1.0 - SYNC_TOLERANCE)) && 960 (hsync < monitor->hsync[i].hi * (1.0 + SYNC_TOLERANCE))) 961 break; 962 } 963 if(i == monitor->nHsync) return FALSE; 964 return TRUE; 965} 966 967static Bool 968SiSCheckForV(float vrefresh, MonPtr monitor) 969{ 970 int i; 971 for(i = 0; i < monitor->nVrefresh; i++) { 972 if((vrefresh > monitor->vrefresh[i].lo * (1.0 - SYNC_TOLERANCE)) && 973 (vrefresh < monitor->vrefresh[i].hi * (1.0 + SYNC_TOLERANCE))) 974 break; 975 } 976 if(i == monitor->nVrefresh) return FALSE; 977 return TRUE; 978} 979 980static Bool 981CheckAndOverruleH(ScrnInfoPtr pScrn, MonPtr monitor) 982{ 983 DisplayModePtr mode = monitor->Modes; 984 float mymin = 30.0, mymax = 80.0, hsync; 985 Bool doit = FALSE; 986 987 for(hsync = mymin; hsync <= mymax; hsync += .5) { 988 if(!SiSCheckForH(hsync, monitor)) doit = TRUE; 989 } 990 991 if(mode) { 992 do { 993 if(mode->type & M_T_BUILTIN) { 994 hsync = (float)mode->Clock / (float)mode->HTotal; 995 if(!SiSCheckForH(hsync, monitor)) { 996 doit = TRUE; 997 if(hsync < mymin) mymin = hsync; 998 if(hsync > mymax) mymax = hsync; 999 } 1000 } 1001 } while((mode = mode->next)); 1002 } 1003 1004 if(doit) { 1005 monitor->nHsync = 1; 1006 monitor->hsync[0].lo = mymin; 1007 monitor->hsync[0].hi = mymax; 1008 return TRUE; 1009 } 1010 1011 return FALSE; 1012} 1013 1014static Bool 1015CheckAndOverruleV(ScrnInfoPtr pScrn, MonPtr monitor) 1016{ 1017 DisplayModePtr mode = monitor->Modes; 1018 float mymin = 59.0, mymax = 61.0, vrefresh; 1019 Bool doit = FALSE, ret = FALSE; 1020 1021 for(vrefresh = mymin; vrefresh <= mymax; vrefresh += 1.0) { 1022 if(!SiSCheckForV(vrefresh, monitor)) doit = TRUE; 1023 } 1024 1025 if(mode) { 1026 do { 1027 if(mode->type & M_T_BUILTIN) { 1028 vrefresh = mode->Clock * 1000.0 / (mode->HTotal * mode->VTotal); 1029 if(mode->Flags & V_INTERLACE) vrefresh *= 2.0; 1030 if(mode->Flags & V_DBLSCAN) vrefresh /= 2.0; 1031 if(!SiSCheckForH(vrefresh, monitor)) { 1032 doit = TRUE; 1033 if(vrefresh < mymin) mymin = vrefresh; 1034 if(vrefresh > mymax) mymax = vrefresh; 1035 } 1036 } 1037 } while((mode = mode->next)); 1038 } 1039 1040 if(doit) { 1041 monitor->nVrefresh = 1; 1042 monitor->vrefresh[0].lo = mymin; 1043 monitor->vrefresh[0].hi = mymax; 1044 ret = TRUE; 1045 } 1046 1047 /* special for 640x400/320x200/@70Hz (VGA/IBM 720x480) */ 1048 if( (!SiSCheckForV(71, monitor)) && 1049 (monitor->nVrefresh < MAX_VREFRESH) ) { 1050 monitor->vrefresh[monitor->nVrefresh].lo = 71; 1051 monitor->vrefresh[monitor->nVrefresh].hi = 71; 1052 monitor->nVrefresh++; 1053 ret = TRUE; 1054 } 1055 return ret; 1056} 1057 1058/* Some helper functions for MergedFB mode */ 1059 1060#ifdef SISMERGED 1061 1062/* Helper function for CRT2 monitor vrefresh/hsync options 1063 * (Code base from mga driver) 1064 */ 1065static int 1066SiSStrToRanges(range *r, char *s, int max) 1067{ 1068 float num = 0.0; 1069 int rangenum = 0; 1070 Bool gotdash = FALSE; 1071 Bool nextdash = FALSE; 1072 char *strnum = NULL; 1073 do { 1074 switch(*s) { 1075 case '0': 1076 case '1': 1077 case '2': 1078 case '3': 1079 case '4': 1080 case '5': 1081 case '6': 1082 case '7': 1083 case '8': 1084 case '9': 1085 case '.': 1086 if(strnum == NULL) { 1087 strnum = s; 1088 gotdash = nextdash; 1089 nextdash = FALSE; 1090 } 1091 break; 1092 case '-': 1093 case ' ': 1094 case 0: 1095 if(strnum == NULL) break; 1096 sscanf(strnum, "%f", &num); 1097 strnum = NULL; 1098 if(gotdash) { 1099 r[rangenum - 1].hi = num; 1100 } else { 1101 r[rangenum].lo = num; 1102 r[rangenum].hi = num; 1103 rangenum++; 1104 } 1105 if(*s == '-') nextdash = (rangenum != 0); 1106 else if(rangenum >= max) return rangenum; 1107 break; 1108 default: 1109 return 0; 1110 } 1111 1112 } while(*(s++) != 0); 1113 1114 return rangenum; 1115} 1116 1117/* Copy and link two modes (i, j) for mergedfb mode 1118 * (Code base taken from mga driver) 1119 * 1120 * - Copy mode i, merge j to copy of i, link the result to dest 1121 * - Link i and j in private record. 1122 * - If dest is NULL, return value is copy of i linked to itself. 1123 * - For mergedfb auto-config, we only check the dimension 1124 * against virtualX/Y, if they were user-provided. 1125 * - No special treatment required for CRTxxOffs. 1126 * - Provide fake dotclock in order to distinguish between similar 1127 * looking MetaModes (for RandR and VidMode extensions) 1128 * - Set unique VRefresh of dest mode for RandR 1129 */ 1130static DisplayModePtr 1131SiSCopyModeNLink(ScrnInfoPtr pScrn, DisplayModePtr dest, 1132 DisplayModePtr i, DisplayModePtr j, 1133 SiSScrn2Rel srel) 1134{ 1135 SISPtr pSiS = SISPTR(pScrn); 1136 DisplayModePtr mode; 1137 int dx = 0,dy = 0; 1138 1139 if(!((mode = xalloc(sizeof(DisplayModeRec))))) return dest; 1140 memcpy(mode, i, sizeof(DisplayModeRec)); 1141 if(!((mode->Private = xalloc(sizeof(SiSMergedDisplayModeRec))))) { 1142 xfree(mode); 1143 return dest; 1144 } 1145 ((SiSMergedDisplayModePtr)mode->Private)->CRT1 = i; 1146 ((SiSMergedDisplayModePtr)mode->Private)->CRT2 = j; 1147 ((SiSMergedDisplayModePtr)mode->Private)->CRT2Position = srel; 1148 mode->PrivSize = 0; 1149 1150 switch(srel) { 1151 case sisLeftOf: 1152 case sisRightOf: 1153 if(!(pScrn->display->virtualX)) { 1154 dx = i->HDisplay + j->HDisplay; 1155 } else { 1156 dx = min(pScrn->virtualX, i->HDisplay + j->HDisplay); 1157 } 1158 dx -= mode->HDisplay; 1159 if(!(pScrn->display->virtualY)) { 1160 dy = max(i->VDisplay, j->VDisplay); 1161 } else { 1162 dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay)); 1163 } 1164 dy -= mode->VDisplay; 1165 break; 1166 case sisAbove: 1167 case sisBelow: 1168 if(!(pScrn->display->virtualY)) { 1169 dy = i->VDisplay + j->VDisplay; 1170 } else { 1171 dy = min(pScrn->virtualY, i->VDisplay + j->VDisplay); 1172 } 1173 dy -= mode->VDisplay; 1174 if(!(pScrn->display->virtualX)) { 1175 dx = max(i->HDisplay, j->HDisplay); 1176 } else { 1177 dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay)); 1178 } 1179 dx -= mode->HDisplay; 1180 break; 1181 case sisClone: 1182 if(!(pScrn->display->virtualX)) { 1183 dx = max(i->HDisplay, j->HDisplay); 1184 } else { 1185 dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay)); 1186 } 1187 dx -= mode->HDisplay; 1188 if(!(pScrn->display->virtualY)) { 1189 dy = max(i->VDisplay, j->VDisplay); 1190 } else { 1191 dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay)); 1192 } 1193 dy -= mode->VDisplay; 1194 break; 1195 } 1196 mode->HDisplay += dx; 1197 mode->HSyncStart += dx; 1198 mode->HSyncEnd += dx; 1199 mode->HTotal += dx; 1200 mode->VDisplay += dy; 1201 mode->VSyncStart += dy; 1202 mode->VSyncEnd += dy; 1203 mode->VTotal += dy; 1204 1205 mode->type = M_T_DEFAULT; 1206#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,2,0) 1207 /* Set up as user defined (ie fake that the mode has been named in the 1208 * Modes-list in the screen section; corrects cycling with CTRL-ALT-[-+] 1209 * when source mode has not been listed there.) 1210 */ 1211 mode->type |= M_T_USERDEF; 1212#endif 1213 1214 /* Set the VRefresh field (in order to make RandR use it for the rates). We 1215 * simply set this to the refresh rate for the CRT1 mode (since CRT2 will 1216 * mostly be LCD or TV anyway). 1217 */ 1218 mode->VRefresh = SiSCalcVRate(i); 1219 1220 if( ((mode->HDisplay * ((pScrn->bitsPerPixel + 7) / 8) * mode->VDisplay) > pSiS->maxxfbmem) || 1221 (mode->HDisplay > 4088) || 1222 (mode->VDisplay > 4096) ) { 1223 1224 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1225 "Skipped \"%s\" (%dx%d), not enough video RAM or beyond hardware specs\n", 1226 mode->name, mode->HDisplay, mode->VDisplay); 1227 xfree(mode->Private); 1228 xfree(mode); 1229 1230 return dest; 1231 } 1232 1233#ifdef SISXINERAMA 1234 if(srel != sisClone) { 1235 pSiS->AtLeastOneNonClone = TRUE; 1236 } 1237#endif 1238 1239 /* Now see if the resulting mode would be discarded as a "size" by the 1240 * RandR extension, and increase its clock by 1000 in case it does. 1241 */ 1242 if(dest) { 1243 DisplayModePtr t = dest; 1244 do { 1245 if((t->HDisplay == mode->HDisplay) && 1246 (t->VDisplay == mode->VDisplay) && 1247 ((int)(t->VRefresh + .5) == (int)(mode->VRefresh + .5))) { 1248 mode->VRefresh += 1000.0; 1249 } 1250 t = t->next; 1251 } while((t) && (t != dest)); 1252 } 1253 1254 /* Provide a fake but unique DotClock in order to trick the vidmode 1255 * extension to allow selecting among a number of modes whose merged result 1256 * looks identical but consists of different modes for CRT1 and CRT2 1257 */ 1258 mode->Clock = (int)(mode->VRefresh * 1000.0); 1259 1260 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1261 "Merged \"%s\" (%dx%d) and \"%s\" (%dx%d) to %dx%d (%d)%s\n", 1262 i->name, i->HDisplay, i->VDisplay, j->name, j->HDisplay, j->VDisplay, 1263 mode->HDisplay, mode->VDisplay, (int)mode->VRefresh, 1264 (srel == sisClone) ? " (Clone)" : ""); 1265 1266 mode->next = mode; 1267 mode->prev = mode; 1268 1269 if(dest) { 1270 mode->next = dest->next; /* Insert node after "dest" */ 1271 dest->next->prev = mode; 1272 mode->prev = dest; 1273 dest->next = mode; 1274 } 1275 1276 return mode; 1277} 1278 1279/* Helper function to find a mode from a given name 1280 * (Code base taken from mga driver) 1281 */ 1282static DisplayModePtr 1283SiSGetModeFromName(char* str, DisplayModePtr i) 1284{ 1285 DisplayModePtr c = i; 1286 if(!i) return NULL; 1287 do { 1288 if(strcmp(str, c->name) == 0) return c; 1289 c = c->next; 1290 } while(c != i); 1291 return NULL; 1292} 1293 1294static DisplayModePtr 1295SiSFindWidestTallestMode(DisplayModePtr i, Bool tallest) 1296{ 1297 DisplayModePtr c = i, d = NULL; 1298 int max = 0; 1299 if(!i) return NULL; 1300 do { 1301 if(tallest) { 1302 if(c->VDisplay > max) { 1303 max = c->VDisplay; 1304 d = c; 1305 } 1306 } else { 1307 if(c->HDisplay > max) { 1308 max = c->HDisplay; 1309 d = c; 1310 } 1311 } 1312 c = c->next; 1313 } while(c != i); 1314 return d; 1315} 1316 1317static void 1318SiSFindWidestTallestCommonMode(DisplayModePtr i, DisplayModePtr j, Bool tallest, 1319 DisplayModePtr *a, DisplayModePtr *b) 1320{ 1321 DisplayModePtr c = i, d; 1322 int max = 0; 1323 Bool foundone; 1324 1325 (*a) = (*b) = NULL; 1326 1327 if(!i || !j) return; 1328 1329 do { 1330 d = j; 1331 foundone = FALSE; 1332 do { 1333 if( (c->HDisplay == d->HDisplay) && 1334 (c->VDisplay == d->VDisplay) ) { 1335 foundone = TRUE; 1336 break; 1337 } 1338 d = d->next; 1339 } while(d != j); 1340 if(foundone) { 1341 if(tallest) { 1342 if(c->VDisplay > max) { 1343 max = c->VDisplay; 1344 (*a) = c; 1345 (*b) = d; 1346 } 1347 } else { 1348 if(c->HDisplay > max) { 1349 max = c->HDisplay; 1350 (*a) = c; 1351 (*b) = d; 1352 } 1353 } 1354 } 1355 c = c->next; 1356 } while(c != i); 1357} 1358 1359static DisplayModePtr 1360SiSGenerateModeListFromLargestModes(ScrnInfoPtr pScrn, 1361 DisplayModePtr i, DisplayModePtr j, 1362 SiSScrn2Rel srel) 1363{ 1364#ifdef SISXINERAMA 1365 SISPtr pSiS = SISPTR(pScrn); 1366#endif 1367 DisplayModePtr mode1 = NULL; 1368 DisplayModePtr mode2 = NULL; 1369 DisplayModePtr mode3 = NULL; 1370 DisplayModePtr mode4 = NULL; 1371 DisplayModePtr result = NULL; 1372 1373#ifdef SISXINERAMA 1374 pSiS->AtLeastOneNonClone = FALSE; 1375#endif 1376 1377 /* Now build a default list of MetaModes. 1378 * - Non-clone: If the user enabled NonRectangular, we use the 1379 * largest mode for each CRT1 and CRT2. If not, we use the largest 1380 * common mode for CRT1 and CRT2 (if available). Additionally, and 1381 * regardless if the above, we produce a clone mode consisting of 1382 * the largest common mode (if available) in order to use DGA. 1383 * - Clone: If the (global) CRT2Position is Clone, we use the 1384 * largest common mode if available, otherwise the first two modes 1385 * in each list. 1386 */ 1387 1388 switch(srel) { 1389 case sisLeftOf: 1390 case sisRightOf: 1391 mode1 = SiSFindWidestTallestMode(i, FALSE); 1392 mode2 = SiSFindWidestTallestMode(j, FALSE); 1393 SiSFindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); 1394 break; 1395 case sisAbove: 1396 case sisBelow: 1397 mode1 = SiSFindWidestTallestMode(i, TRUE); 1398 mode2 = SiSFindWidestTallestMode(j, TRUE); 1399 SiSFindWidestTallestCommonMode(i, j, TRUE, &mode3, &mode4); 1400 break; 1401 case sisClone: 1402 SiSFindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); 1403 if(mode3 && mode4) { 1404 mode1 = mode3; 1405 mode2 = mode4; 1406 } else { 1407 mode1 = i; 1408 mode2 = j; 1409 } 1410 } 1411 1412 if(srel != sisClone) { 1413 if(mode3 && mode4 && !pSiS->NonRect) { 1414 mode1 = mode3; 1415 mode2 = mode2; 1416 } 1417 } 1418 1419 if(mode1 && mode2) { 1420 result = SiSCopyModeNLink(pScrn, result, mode1, mode2, srel); 1421 } 1422 1423 if(srel != sisClone) { 1424 if(mode3 && mode4) { 1425 result = SiSCopyModeNLink(pScrn, result, mode3, mode4, sisClone); 1426 } 1427 } 1428 1429 return result; 1430} 1431 1432/* Generate the merged-fb mode modelist 1433 * (Taken from mga driver) 1434 */ 1435static DisplayModePtr 1436SiSGenerateModeListFromMetaModes(ScrnInfoPtr pScrn, char* str, 1437 DisplayModePtr i, DisplayModePtr j, 1438 SiSScrn2Rel srel) 1439{ 1440#ifdef SISXINERAMA 1441 SISPtr pSiS = SISPTR(pScrn); 1442#endif 1443 char* strmode = str; 1444 char modename[256]; 1445 Bool gotdash = FALSE; 1446 char gotsep = 0; 1447 SiSScrn2Rel sr; 1448 DisplayModePtr mode1 = NULL; 1449 DisplayModePtr mode2 = NULL; 1450 DisplayModePtr result = NULL; 1451 int myslen; 1452 1453#ifdef SISXINERAMA 1454 pSiS->AtLeastOneNonClone = FALSE; 1455#endif 1456 1457 do { 1458 switch(*str) { 1459 case 0: 1460 case '-': 1461 case '+': 1462 case ' ': 1463 case ',': 1464 case ';': 1465 if(strmode != str) { 1466 1467 myslen = str - strmode; 1468 if(myslen > 255) myslen = 255; 1469 strncpy(modename, strmode, myslen); 1470 modename[myslen] = 0; 1471 1472 if(gotdash) { 1473 if(mode1 == NULL) { 1474 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1475 "Error parsing MetaModes parameter\n"); 1476 return NULL; 1477 } 1478 mode2 = SiSGetModeFromName(modename, j); 1479 if(!mode2) { 1480 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1481 "Mode \"%s\" is not a supported mode for CRT2\n", modename); 1482 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1483 "\t(Skipping metamode \"%s%c%s\")\n", mode1->name, gotsep, modename); 1484 mode1 = NULL; 1485 gotsep = 0; 1486 } 1487 } else { 1488 mode1 = SiSGetModeFromName(modename, i); 1489 if(!mode1) { 1490 char* tmps = str; 1491 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1492 "Mode \"%s\" is not a supported mode for CRT1\n", modename); 1493 while(*tmps == ' ' || *tmps == ';') tmps++; 1494 /* skip the next mode */ 1495 if(*tmps == '-' || *tmps == '+' || *tmps == ',') { 1496 tmps++; 1497 /* skip spaces */ 1498 while(*tmps == ' ' || *tmps == ';') tmps++; 1499 /* skip modename */ 1500 while(*tmps && *tmps != ' ' && *tmps != ';' && *tmps != '-' && *tmps != '+' && *tmps != ',') tmps++; 1501 myslen = tmps - strmode; 1502 if(myslen > 255) myslen = 255; 1503 strncpy(modename,strmode,myslen); 1504 modename[myslen] = 0; 1505 str = tmps - 1; 1506 } 1507 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1508 "\t(Skipping metamode \"%s\")\n", modename); 1509 mode1 = NULL; 1510 gotsep = 0; 1511 } 1512 } 1513 gotdash = FALSE; 1514 } 1515 strmode = str + 1; 1516 gotdash |= (*str == '-' || *str == '+' || *str == ','); 1517 if (*str == '-' || *str == '+' || *str == ',') 1518 gotsep = *str; 1519 1520 if(*str != 0) break; 1521 /* Fall through otherwise */ 1522 1523 default: 1524 if(!gotdash && mode1) { 1525 sr = srel; 1526 if(gotsep == '+') sr = sisClone; 1527 if(!mode2) { 1528 mode2 = SiSGetModeFromName(mode1->name, j); 1529 sr = sisClone; 1530 } 1531 if(!mode2) { 1532 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1533 "Mode \"%s\" is not a supported mode for CRT2\n", mode1->name); 1534 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1535 "\t(Skipping metamode \"%s\")\n", modename); 1536 mode1 = NULL; 1537 } else { 1538 result = SiSCopyModeNLink(pScrn, result, mode1, mode2, sr); 1539 mode1 = NULL; 1540 mode2 = NULL; 1541 } 1542 gotsep = 0; 1543 } 1544 break; 1545 1546 } 1547 1548 } while(*(str++) != 0); 1549 1550 return result; 1551} 1552 1553static DisplayModePtr 1554SiSGenerateModeList(ScrnInfoPtr pScrn, char* str, 1555 DisplayModePtr i, DisplayModePtr j, 1556 SiSScrn2Rel srel) 1557{ 1558 SISPtr pSiS = SISPTR(pScrn); 1559 1560 if(str != NULL) { 1561 return(SiSGenerateModeListFromMetaModes(pScrn, str, i, j, srel)); 1562 } else { 1563 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1564 "No MetaModes given, linking %s modes by default\n", 1565 (srel == sisClone) ? "largest common" : 1566 (pSiS->NonRect ? 1567 (((srel == sisLeftOf) || (srel == sisRightOf)) ? "widest" : "tallest") 1568 : 1569 (((srel == sisLeftOf) || (srel == sisRightOf)) ? "widest common" : "tallest common")) ); 1570 return(SiSGenerateModeListFromLargestModes(pScrn, i, j, srel)); 1571 } 1572} 1573 1574static void 1575SiSRecalcDefaultVirtualSize(ScrnInfoPtr pScrn) 1576{ 1577 SISPtr pSiS = SISPTR(pScrn); 1578 DisplayModePtr mode, bmode; 1579 int maxh, maxv; 1580 static const char *str = "MergedFB: Virtual %s %d\n"; 1581 static const char *errstr = "Virtual %s to small for given CRT2Position offset\n"; 1582 1583 mode = bmode = pScrn->modes; 1584 maxh = maxv = 0; 1585 do { 1586 if(mode->HDisplay > maxh) maxh = mode->HDisplay; 1587 if(mode->VDisplay > maxv) maxv = mode->VDisplay; 1588 mode = mode->next; 1589 } while(mode != bmode); 1590 1591 maxh += pSiS->CRT1XOffs + pSiS->CRT2XOffs; 1592 maxv += pSiS->CRT1YOffs + pSiS->CRT2YOffs; 1593 1594 if(!(pScrn->display->virtualX)) { 1595 if(maxh > 4088) { 1596 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1597 "Virtual width with CRT2Position offset beyond hardware specs\n"); 1598 pSiS->CRT1XOffs = pSiS->CRT2XOffs = 0; 1599 maxh -= (pSiS->CRT1XOffs + pSiS->CRT2XOffs); 1600 } 1601 pScrn->virtualX = maxh; 1602 pScrn->displayWidth = maxh; 1603 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "width", maxh); 1604 } else { 1605 if(maxh < pScrn->display->virtualX) { 1606 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "width"); 1607 pSiS->CRT1XOffs = pSiS->CRT2XOffs = 0; 1608 } 1609 } 1610 1611 if(!(pScrn->display->virtualY)) { 1612 pScrn->virtualY = maxv; 1613 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "height", maxv); 1614 } else { 1615 if(maxv < pScrn->display->virtualY) { 1616 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "height"); 1617 pSiS->CRT1YOffs = pSiS->CRT2YOffs = 0; 1618 } 1619 } 1620} 1621 1622static void 1623SiSMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, SiSScrn2Rel srel) 1624{ 1625 SISPtr pSiS = SISPTR(pScrn1); 1626 MessageType from = X_DEFAULT; 1627 xf86MonPtr DDC1 = (xf86MonPtr)(pScrn1->monitor->DDC); 1628 xf86MonPtr DDC2 = (xf86MonPtr)(pScrn2->monitor->DDC); 1629 int ddcWidthmm = 0, ddcHeightmm = 0; 1630 const char *dsstr = "MergedFB: Display dimensions: (%d, %d) mm\n"; 1631 1632 /* This sets the DPI for MergedFB mode. The problem is that 1633 * this can never be exact, because the output devices may 1634 * have different dimensions. This function tries to compromise 1635 * through a few assumptions, and it just calculates an average DPI 1636 * value for both monitors. 1637 */ 1638 1639 /* Given DisplaySize should regard BOTH monitors */ 1640 pScrn1->widthmm = pScrn1->monitor->widthmm; 1641 pScrn1->heightmm = pScrn1->monitor->heightmm; 1642 1643 /* Get DDC display size; if only either CRT1 or CRT2 provided these, 1644 * assume equal dimensions for both, otherwise add dimensions 1645 */ 1646 if( (DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) && 1647 (DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0)) ) { 1648 ddcWidthmm = max(DDC1->features.hsize, DDC2->features.hsize) * 10; 1649 ddcHeightmm = max(DDC1->features.vsize, DDC2->features.vsize) * 10; 1650 switch(srel) { 1651 case sisLeftOf: 1652 case sisRightOf: 1653 ddcWidthmm = (DDC1->features.hsize + DDC2->features.hsize) * 10; 1654 break; 1655 case sisAbove: 1656 case sisBelow: 1657 ddcHeightmm = (DDC1->features.vsize + DDC2->features.vsize) * 10; 1658 default: 1659 break; 1660 } 1661 } else if(DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) { 1662 ddcWidthmm = DDC1->features.hsize * 10; 1663 ddcHeightmm = DDC1->features.vsize * 10; 1664 switch(srel) { 1665 case sisLeftOf: 1666 case sisRightOf: 1667 ddcWidthmm *= 2; 1668 break; 1669 case sisAbove: 1670 case sisBelow: 1671 ddcHeightmm *= 2; 1672 default: 1673 break; 1674 } 1675 } else if(DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0) ) { 1676 ddcWidthmm = DDC2->features.hsize * 10; 1677 ddcHeightmm = DDC2->features.vsize * 10; 1678 switch(srel) { 1679 case sisLeftOf: 1680 case sisRightOf: 1681 ddcWidthmm *= 2; 1682 break; 1683 case sisAbove: 1684 case sisBelow: 1685 ddcHeightmm *= 2; 1686 default: 1687 break; 1688 } 1689 } 1690 1691 if(monitorResolution > 0) { 1692 1693 /* Set command line given values (overrules given options) */ 1694 pScrn1->xDpi = monitorResolution; 1695 pScrn1->yDpi = monitorResolution; 1696 from = X_CMDLINE; 1697 1698 } else if(pSiS->MergedFBXDPI) { 1699 1700 /* Set option-wise given values (overrule DisplaySize) */ 1701 pScrn1->xDpi = pSiS->MergedFBXDPI; 1702 pScrn1->yDpi = pSiS->MergedFBYDPI; 1703 from = X_CONFIG; 1704 1705 } else if(pScrn1->widthmm > 0 || pScrn1->heightmm > 0) { 1706 1707 /* Set values calculated from given DisplaySize */ 1708 from = X_CONFIG; 1709 if(pScrn1->widthmm > 0) { 1710 pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm); 1711 } 1712 if(pScrn1->heightmm > 0) { 1713 pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm); 1714 } 1715 xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, pScrn1->widthmm, pScrn1->heightmm); 1716 1717 } else if(ddcWidthmm && ddcHeightmm) { 1718 1719 /* Set values from DDC-provided display size */ 1720 from = X_PROBED; 1721 xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, ddcWidthmm, ddcHeightmm ); 1722 pScrn1->widthmm = ddcWidthmm; 1723 pScrn1->heightmm = ddcHeightmm; 1724 if(pScrn1->widthmm > 0) { 1725 pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm); 1726 } 1727 if(pScrn1->heightmm > 0) { 1728 pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm); 1729 } 1730 1731 } else { 1732 1733 pScrn1->xDpi = pScrn1->yDpi = DEFAULT_DPI; 1734 1735 } 1736 1737 /* Sanity check */ 1738 if(pScrn1->xDpi > 0 && pScrn1->yDpi <= 0) 1739 pScrn1->yDpi = pScrn1->xDpi; 1740 if(pScrn1->yDpi > 0 && pScrn1->xDpi <= 0) 1741 pScrn1->xDpi = pScrn1->yDpi; 1742 1743 pScrn2->xDpi = pScrn1->xDpi; 1744 pScrn2->yDpi = pScrn1->yDpi; 1745 1746 xf86DrvMsg(pScrn1->scrnIndex, from, "MergedFB: DPI set to (%d, %d)\n", 1747 pScrn1->xDpi, pScrn1->yDpi); 1748} 1749 1750/* Pseudo-Xinerama extension for MergedFB mode */ 1751#ifdef SISXINERAMA 1752 1753static void 1754SiSUpdateXineramaScreenInfo(ScrnInfoPtr pScrn1) 1755{ 1756 SISPtr pSiS = SISPTR(pScrn1); 1757 int crt1scrnnum = 0, crt2scrnnum = 1; 1758 int x1=0, x2=0, y1=0, y2=0, h1=0, h2=0, w1=0, w2=0; 1759 int realvirtX, realvirtY; 1760 DisplayModePtr currentMode, firstMode; 1761 Bool infochanged = FALSE; 1762 Bool usenonrect = pSiS->NonRect; 1763 const char *rectxine = "\t... setting up rectangular Xinerama layout\n"; 1764 1765 pSiS->MBXNR1XMAX = pSiS->MBXNR1YMAX = pSiS->MBXNR2XMAX = pSiS->MBXNR2YMAX = 65536; 1766 pSiS->HaveNonRect = pSiS->HaveOffsRegions = FALSE; 1767 1768 if(!pSiS->MergedFB) return; 1769 1770 if(SiSnoPanoramiXExtension) return; 1771 1772 if(!SiSXineramadataPtr) return; 1773 1774 if(pSiS->CRT2IsScrn0) { 1775 crt1scrnnum = 1; 1776 crt2scrnnum = 0; 1777 } 1778 1779 /* Attention: Usage of RandR may lead to virtual X and Y dimensions 1780 * actually smaller than our MetaModes. To avoid this, we calculate 1781 * the maxCRT fields here (and not somewhere else, like in CopyNLink) 1782 * 1783 * *** Note: RandR is disabled if one of CRTxxOffs is non-zero. 1784 */ 1785 1786 /* "Real" virtual: Virtual without the Offset */ 1787 realvirtX = pScrn1->virtualX - pSiS->CRT1XOffs - pSiS->CRT2XOffs; 1788 realvirtY = pScrn1->virtualY - pSiS->CRT1YOffs - pSiS->CRT2YOffs; 1789 1790 if((pSiS->SiSXineramaVX != pScrn1->virtualX) || (pSiS->SiSXineramaVY != pScrn1->virtualY)) { 1791 1792 if(!(pScrn1->modes)) return; 1793 1794 pSiS->maxCRT1_X1 = pSiS->maxCRT1_X2 = 0; 1795 pSiS->maxCRT1_Y1 = pSiS->maxCRT1_Y2 = 0; 1796 pSiS->maxCRT2_X1 = pSiS->maxCRT2_X2 = 0; 1797 pSiS->maxCRT2_Y1 = pSiS->maxCRT2_Y2 = 0; 1798 pSiS->maxClone_X1 = pSiS->maxClone_X2 = 0; 1799 pSiS->maxClone_Y1 = pSiS->maxClone_Y2 = 0; 1800 1801 currentMode = firstMode = pScrn1->modes; 1802 1803 do { 1804 1805 DisplayModePtr p = currentMode->next; 1806 DisplayModePtr i = ((SiSMergedDisplayModePtr)currentMode->Private)->CRT1; 1807 DisplayModePtr j = ((SiSMergedDisplayModePtr)currentMode->Private)->CRT2; 1808 SiSScrn2Rel srel = ((SiSMergedDisplayModePtr)currentMode->Private)->CRT2Position; 1809 1810 if((currentMode->HDisplay <= realvirtX) && (currentMode->VDisplay <= realvirtY) && 1811 (i->HDisplay <= realvirtX) && (j->HDisplay <= realvirtX) && 1812 (i->VDisplay <= realvirtY) && (j->VDisplay <= realvirtY)) { 1813 1814 if(srel != sisClone) { 1815 if(pSiS->maxCRT1_X1 == i->HDisplay) { 1816 if(pSiS->maxCRT1_X2 < j->HDisplay) { 1817 pSiS->maxCRT1_X2 = j->HDisplay; /* Widest CRT2 mode displayed with widest CRT1 mode */ 1818 } 1819 } else if(pSiS->maxCRT1_X1 < i->HDisplay) { 1820 pSiS->maxCRT1_X1 = i->HDisplay; /* Widest CRT1 mode */ 1821 pSiS->maxCRT1_X2 = j->HDisplay; 1822 } 1823 if(pSiS->maxCRT2_X2 == j->HDisplay) { 1824 if(pSiS->maxCRT2_X1 < i->HDisplay) { 1825 pSiS->maxCRT2_X1 = i->HDisplay; /* Widest CRT1 mode displayed with widest CRT2 mode */ 1826 } 1827 } else if(pSiS->maxCRT2_X2 < j->HDisplay) { 1828 pSiS->maxCRT2_X2 = j->HDisplay; /* Widest CRT2 mode */ 1829 pSiS->maxCRT2_X1 = i->HDisplay; 1830 } 1831 if(pSiS->maxCRT1_Y1 == i->VDisplay) { /* Same as above, but tallest instead of widest */ 1832 if(pSiS->maxCRT1_Y2 < j->VDisplay) { 1833 pSiS->maxCRT1_Y2 = j->VDisplay; 1834 } 1835 } else if(pSiS->maxCRT1_Y1 < i->VDisplay) { 1836 pSiS->maxCRT1_Y1 = i->VDisplay; 1837 pSiS->maxCRT1_Y2 = j->VDisplay; 1838 } 1839 if(pSiS->maxCRT2_Y2 == j->VDisplay) { 1840 if(pSiS->maxCRT2_Y1 < i->VDisplay) { 1841 pSiS->maxCRT2_Y1 = i->VDisplay; 1842 } 1843 } else if(pSiS->maxCRT2_Y2 < j->VDisplay) { 1844 pSiS->maxCRT2_Y2 = j->VDisplay; 1845 pSiS->maxCRT2_Y1 = i->VDisplay; 1846 } 1847 } else { 1848 if(pSiS->maxClone_X1 < i->HDisplay) { 1849 pSiS->maxClone_X1 = i->HDisplay; 1850 } 1851 if(pSiS->maxClone_X2 < j->HDisplay) { 1852 pSiS->maxClone_X2 = j->HDisplay; 1853 } 1854 if(pSiS->maxClone_Y1 < i->VDisplay) { 1855 pSiS->maxClone_Y1 = i->VDisplay; 1856 } 1857 if(pSiS->maxClone_Y2 < j->VDisplay) { 1858 pSiS->maxClone_Y2 = j->VDisplay; 1859 } 1860 } 1861 } 1862 currentMode = p; 1863 1864 } while((currentMode) && (currentMode != firstMode)); 1865 1866 pSiS->SiSXineramaVX = pScrn1->virtualX; 1867 pSiS->SiSXineramaVY = pScrn1->virtualY; 1868 infochanged = TRUE; 1869 1870 } 1871 1872 if((usenonrect) && (pSiS->CRT2Position != sisClone) && pSiS->maxCRT1_X1) { 1873 switch(pSiS->CRT2Position) { 1874 case sisLeftOf: 1875 case sisRightOf: 1876 if((pSiS->maxCRT1_Y1 != realvirtY) && (pSiS->maxCRT2_Y2 != realvirtY)) { 1877 usenonrect = FALSE; 1878 } 1879 break; 1880 case sisAbove: 1881 case sisBelow: 1882 if((pSiS->maxCRT1_X1 != realvirtX) && (pSiS->maxCRT2_X2 != realvirtX)) { 1883 usenonrect = FALSE; 1884 } 1885 break; 1886 case sisClone: 1887 break; 1888 } 1889 if(infochanged && !usenonrect) { 1890 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 1891 "Virtual screen size does not match maximum display modes...\n"); 1892 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, rectxine); 1893 1894 } 1895 } else if(infochanged && usenonrect) { 1896 usenonrect = FALSE; 1897 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 1898 "Only clone modes available for this virtual screen size...\n"); 1899 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, rectxine); 1900 } 1901 1902 if(pSiS->maxCRT1_X1) { /* Means we have at least one non-clone mode */ 1903 switch(pSiS->CRT2Position) { 1904 case sisLeftOf: 1905 x1 = min(pSiS->maxCRT1_X2, pScrn1->virtualX - pSiS->maxCRT1_X1); 1906 if(x1 < 0) x1 = 0; 1907 y1 = pSiS->CRT1YOffs; 1908 w1 = pScrn1->virtualX - x1; 1909 h1 = realvirtY; 1910 if((usenonrect) && (pSiS->maxCRT1_Y1 != realvirtY)) { 1911 h1 = pSiS->MBXNR1YMAX = pSiS->maxCRT1_Y1; 1912 pSiS->NonRectDead.x0 = x1; 1913 pSiS->NonRectDead.x1 = x1 + w1 - 1; 1914 pSiS->NonRectDead.y0 = y1 + h1; 1915 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 1916 pSiS->HaveNonRect = TRUE; 1917 } 1918 x2 = 0; 1919 y2 = pSiS->CRT2YOffs; 1920 w2 = max(pSiS->maxCRT2_X2, pScrn1->virtualX - pSiS->maxCRT2_X1); 1921 if(w2 > pScrn1->virtualX) w2 = pScrn1->virtualX; 1922 h2 = realvirtY; 1923 if((usenonrect) && (pSiS->maxCRT2_Y2 != realvirtY)) { 1924 h2 = pSiS->MBXNR2YMAX = pSiS->maxCRT2_Y2; 1925 pSiS->NonRectDead.x0 = x2; 1926 pSiS->NonRectDead.x1 = x2 + w2 - 1; 1927 pSiS->NonRectDead.y0 = y2 + h2; 1928 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 1929 pSiS->HaveNonRect = TRUE; 1930 } 1931 break; 1932 case sisRightOf: 1933 x1 = 0; 1934 y1 = pSiS->CRT1YOffs; 1935 w1 = max(pSiS->maxCRT1_X1, pScrn1->virtualX - pSiS->maxCRT1_X2); 1936 if(w1 > pScrn1->virtualX) w1 = pScrn1->virtualX; 1937 h1 = realvirtY; 1938 if((usenonrect) && (pSiS->maxCRT1_Y1 != realvirtY)) { 1939 h1 = pSiS->MBXNR1YMAX = pSiS->maxCRT1_Y1; 1940 pSiS->NonRectDead.x0 = x1; 1941 pSiS->NonRectDead.x1 = x1 + w1 - 1; 1942 pSiS->NonRectDead.y0 = y1 + h1; 1943 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 1944 pSiS->HaveNonRect = TRUE; 1945 } 1946 x2 = min(pSiS->maxCRT2_X1, pScrn1->virtualX - pSiS->maxCRT2_X2); 1947 if(x2 < 0) x2 = 0; 1948 y2 = pSiS->CRT2YOffs; 1949 w2 = pScrn1->virtualX - x2; 1950 h2 = realvirtY; 1951 if((usenonrect) && (pSiS->maxCRT2_Y2 != realvirtY)) { 1952 h2 = pSiS->MBXNR2YMAX = pSiS->maxCRT2_Y2; 1953 pSiS->NonRectDead.x0 = x2; 1954 pSiS->NonRectDead.x1 = x2 + w2 - 1; 1955 pSiS->NonRectDead.y0 = y2 + h2; 1956 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 1957 pSiS->HaveNonRect = TRUE; 1958 } 1959 break; 1960 case sisAbove: 1961 x1 = pSiS->CRT1XOffs; 1962 y1 = min(pSiS->maxCRT1_Y2, pScrn1->virtualY - pSiS->maxCRT1_Y1); 1963 if(y1 < 0) y1 = 0; 1964 w1 = realvirtX; 1965 h1 = pScrn1->virtualY - y1; 1966 if((usenonrect) && (pSiS->maxCRT1_X1 != realvirtX)) { 1967 w1 = pSiS->MBXNR1XMAX = pSiS->maxCRT1_X1; 1968 pSiS->NonRectDead.x0 = x1 + w1; 1969 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 1970 pSiS->NonRectDead.y0 = y1; 1971 pSiS->NonRectDead.y1 = y1 + h1 - 1; 1972 pSiS->HaveNonRect = TRUE; 1973 } 1974 x2 = pSiS->CRT2XOffs; 1975 y2 = 0; 1976 w2 = realvirtX; 1977 h2 = max(pSiS->maxCRT2_Y2, pScrn1->virtualY - pSiS->maxCRT2_Y1); 1978 if(h2 > pScrn1->virtualY) h2 = pScrn1->virtualY; 1979 if((usenonrect) && (pSiS->maxCRT2_X2 != realvirtX)) { 1980 w2 = pSiS->MBXNR2XMAX = pSiS->maxCRT2_X2; 1981 pSiS->NonRectDead.x0 = x2 + w2; 1982 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 1983 pSiS->NonRectDead.y0 = y2; 1984 pSiS->NonRectDead.y1 = y2 + h2 - 1; 1985 pSiS->HaveNonRect = TRUE; 1986 } 1987 break; 1988 case sisBelow: 1989 x1 = pSiS->CRT1XOffs; 1990 y1 = 0; 1991 w1 = realvirtX; 1992 h1 = max(pSiS->maxCRT1_Y1, pScrn1->virtualY - pSiS->maxCRT1_Y2); 1993 if(h1 > pScrn1->virtualY) h1 = pScrn1->virtualY; 1994 if((usenonrect) && (pSiS->maxCRT1_X1 != realvirtX)) { 1995 w1 = pSiS->MBXNR1XMAX = pSiS->maxCRT1_X1; 1996 pSiS->NonRectDead.x0 = x1 + w1; 1997 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 1998 pSiS->NonRectDead.y0 = y1; 1999 pSiS->NonRectDead.y1 = y1 + h1 - 1; 2000 pSiS->HaveNonRect = TRUE; 2001 } 2002 x2 = pSiS->CRT2XOffs; 2003 y2 = min(pSiS->maxCRT2_Y1, pScrn1->virtualY - pSiS->maxCRT2_Y2); 2004 if(y2 < 0) y2 = 0; 2005 w2 = realvirtX; 2006 h2 = pScrn1->virtualY - y2; 2007 if((usenonrect) && (pSiS->maxCRT2_X2 != realvirtX)) { 2008 w2 = pSiS->MBXNR2XMAX = pSiS->maxCRT2_X2; 2009 pSiS->NonRectDead.x0 = x2 + w2; 2010 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 2011 pSiS->NonRectDead.y0 = y2; 2012 pSiS->NonRectDead.y1 = y2 + h2 - 1; 2013 pSiS->HaveNonRect = TRUE; 2014 } 2015 default: 2016 break; 2017 } 2018 2019 switch(pSiS->CRT2Position) { 2020 case sisLeftOf: 2021 case sisRightOf: 2022 if(pSiS->CRT1YOffs) { 2023 pSiS->OffDead1.x0 = x1; 2024 pSiS->OffDead1.x1 = x1 + w1 - 1; 2025 pSiS->OffDead1.y0 = 0; 2026 pSiS->OffDead1.y1 = y1 - 1; 2027 pSiS->OffDead2.x0 = x2; 2028 pSiS->OffDead2.x1 = x2 + w2 - 1; 2029 pSiS->OffDead2.y0 = y2 + h2; 2030 pSiS->OffDead2.y1 = pScrn1->virtualY - 1; 2031 pSiS->HaveOffsRegions = TRUE; 2032 } else if(pSiS->CRT2YOffs) { 2033 pSiS->OffDead1.x0 = x2; 2034 pSiS->OffDead1.x1 = x2 + w2 - 1; 2035 pSiS->OffDead1.y0 = 0; 2036 pSiS->OffDead1.y1 = y2 - 1; 2037 pSiS->OffDead2.x0 = x1; 2038 pSiS->OffDead2.x1 = x1 + w1 - 1; 2039 pSiS->OffDead2.y0 = y1 + h1; 2040 pSiS->OffDead2.y1 = pScrn1->virtualY - 1; 2041 pSiS->HaveOffsRegions = TRUE; 2042 } 2043 break; 2044 case sisAbove: 2045 case sisBelow: 2046 if(pSiS->CRT1XOffs) { 2047 pSiS->OffDead1.x0 = x2 + w2; 2048 pSiS->OffDead1.x1 = pScrn1->virtualX - 1; 2049 pSiS->OffDead1.y0 = y2; 2050 pSiS->OffDead1.y1 = y2 + h2 - 1; 2051 pSiS->OffDead2.x0 = 0; 2052 pSiS->OffDead2.x1 = x1 - 1; 2053 pSiS->OffDead2.y0 = y1; 2054 pSiS->OffDead2.y1 = y1 + h1 - 1; 2055 pSiS->HaveOffsRegions = TRUE; 2056 } else if(pSiS->CRT2XOffs) { 2057 pSiS->OffDead1.x0 = x1 + w1; 2058 pSiS->OffDead1.x1 = pScrn1->virtualX - 1; 2059 pSiS->OffDead1.y0 = y1; 2060 pSiS->OffDead1.y1 = y1 + h1 - 1; 2061 pSiS->OffDead2.x0 = 0; 2062 pSiS->OffDead2.x1 = x2 - 1; 2063 pSiS->OffDead2.y0 = y2; 2064 pSiS->OffDead2.y1 = y2 + h2 - 1; 2065 pSiS->HaveOffsRegions = TRUE; 2066 } 2067 default: 2068 break; 2069 } 2070 2071 } else { /* Only clone-modes left */ 2072 2073 x1 = x2 = 0; 2074 y1 = y2 = 0; 2075 w1 = w2 = max(pSiS->maxClone_X1, pSiS->maxClone_X2); 2076 h1 = h2 = max(pSiS->maxClone_Y1, pSiS->maxClone_Y2); 2077 2078 } 2079 2080 SiSXineramadataPtr[crt1scrnnum].x = x1; 2081 SiSXineramadataPtr[crt1scrnnum].y = y1; 2082 SiSXineramadataPtr[crt1scrnnum].width = w1; 2083 SiSXineramadataPtr[crt1scrnnum].height = h1; 2084 SiSXineramadataPtr[crt2scrnnum].x = x2; 2085 SiSXineramadataPtr[crt2scrnnum].y = y2; 2086 SiSXineramadataPtr[crt2scrnnum].width = w2; 2087 SiSXineramadataPtr[crt2scrnnum].height = h2; 2088 2089 if(infochanged) { 2090 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2091 "Pseudo-Xinerama: CRT1 (Screen %d) (%d,%d)-(%d,%d)\n", 2092 crt1scrnnum, x1, y1, w1+x1-1, h1+y1-1); 2093 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2094 "Pseudo-Xinerama: CRT2 (Screen %d) (%d,%d)-(%d,%d)\n", 2095 crt2scrnnum, x2, y2, w2+x2-1, h2+y2-1); 2096 if(pSiS->HaveNonRect) { 2097 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2098 "Pseudo-Xinerama: Inaccessible area (%d,%d)-(%d,%d)\n", 2099 pSiS->NonRectDead.x0, pSiS->NonRectDead.y0, 2100 pSiS->NonRectDead.x1, pSiS->NonRectDead.y1); 2101 } 2102 if(pSiS->HaveOffsRegions) { 2103 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2104 "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", 2105 pSiS->OffDead1.x0, pSiS->OffDead1.y0, 2106 pSiS->OffDead1.x1, pSiS->OffDead1.y1); 2107 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2108 "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", 2109 pSiS->OffDead2.x0, pSiS->OffDead2.y0, 2110 pSiS->OffDead2.x1, pSiS->OffDead2.y1); 2111 } 2112 if(pSiS->HaveNonRect || pSiS->HaveOffsRegions) { 2113 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2114 "Mouse restriction for inaccessible areas is %s\n", 2115 pSiS->MouseRestrictions ? "enabled" : "disabled"); 2116 } 2117 } 2118} 2119 2120/* Proc */ 2121 2122int 2123SiSProcXineramaQueryVersion(ClientPtr client) 2124{ 2125 xPanoramiXQueryVersionReply rep; 2126 register int n; 2127 2128 REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq); 2129 rep.type = X_Reply; 2130 rep.length = 0; 2131 rep.sequenceNumber = client->sequence; 2132 rep.majorVersion = SIS_XINERAMA_MAJOR_VERSION; 2133 rep.minorVersion = SIS_XINERAMA_MINOR_VERSION; 2134 if(client->swapped) { 2135 swaps(&rep.sequenceNumber, n); 2136 swapl(&rep.length, n); 2137 swaps(&rep.majorVersion, n); 2138 swaps(&rep.minorVersion, n); 2139 } 2140 WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *)&rep); 2141 return (client->noClientException); 2142} 2143 2144int 2145SiSProcXineramaGetState(ClientPtr client) 2146{ 2147 REQUEST(xPanoramiXGetStateReq); 2148 WindowPtr pWin; 2149 xPanoramiXGetStateReply rep; 2150 register int n; 2151 2152 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); 2153 pWin = LookupWindow(stuff->window, client); 2154 if(!pWin) return BadWindow; 2155 2156 rep.type = X_Reply; 2157 rep.length = 0; 2158 rep.sequenceNumber = client->sequence; 2159 rep.state = !SiSnoPanoramiXExtension; 2160 if(client->swapped) { 2161 swaps (&rep.sequenceNumber, n); 2162 swapl (&rep.length, n); 2163 swaps (&rep.state, n); 2164 } 2165 WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *)&rep); 2166 return client->noClientException; 2167} 2168 2169int 2170SiSProcXineramaGetScreenCount(ClientPtr client) 2171{ 2172 REQUEST(xPanoramiXGetScreenCountReq); 2173 WindowPtr pWin; 2174 xPanoramiXGetScreenCountReply rep; 2175 register int n; 2176 2177 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); 2178 pWin = LookupWindow(stuff->window, client); 2179 if(!pWin) return BadWindow; 2180 2181 rep.type = X_Reply; 2182 rep.length = 0; 2183 rep.sequenceNumber = client->sequence; 2184 rep.ScreenCount = SiSXineramaNumScreens; 2185 if(client->swapped) { 2186 swaps(&rep.sequenceNumber, n); 2187 swapl(&rep.length, n); 2188 swaps(&rep.ScreenCount, n); 2189 } 2190 WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep); 2191 return client->noClientException; 2192} 2193 2194int 2195SiSProcXineramaGetScreenSize(ClientPtr client) 2196{ 2197 REQUEST(xPanoramiXGetScreenSizeReq); 2198 WindowPtr pWin; 2199 xPanoramiXGetScreenSizeReply rep; 2200 register int n; 2201 2202 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); 2203 pWin = LookupWindow (stuff->window, client); 2204 if(!pWin) return BadWindow; 2205 2206 rep.type = X_Reply; 2207 rep.length = 0; 2208 rep.sequenceNumber = client->sequence; 2209 rep.width = SiSXineramadataPtr[stuff->screen].width; 2210 rep.height = SiSXineramadataPtr[stuff->screen].height; 2211 if(client->swapped) { 2212 swaps(&rep.sequenceNumber, n); 2213 swapl(&rep.length, n); 2214 swaps(&rep.width, n); 2215 swaps(&rep.height, n); 2216 } 2217 WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep); 2218 return client->noClientException; 2219} 2220 2221int 2222SiSProcXineramaIsActive(ClientPtr client) 2223{ 2224 xXineramaIsActiveReply rep; 2225 2226 REQUEST_SIZE_MATCH(xXineramaIsActiveReq); 2227 2228 rep.type = X_Reply; 2229 rep.length = 0; 2230 rep.sequenceNumber = client->sequence; 2231 rep.state = !SiSnoPanoramiXExtension; 2232 if(client->swapped) { 2233 register int n; 2234 swaps(&rep.sequenceNumber, n); 2235 swapl(&rep.length, n); 2236 swapl(&rep.state, n); 2237 } 2238 WriteToClient(client, sizeof(xXineramaIsActiveReply), (char *) &rep); 2239 return client->noClientException; 2240} 2241 2242int 2243SiSProcXineramaQueryScreens(ClientPtr client) 2244{ 2245 xXineramaQueryScreensReply rep; 2246 2247 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); 2248 2249 rep.type = X_Reply; 2250 rep.sequenceNumber = client->sequence; 2251 rep.number = (SiSnoPanoramiXExtension) ? 0 : SiSXineramaNumScreens; 2252 rep.length = rep.number * sz_XineramaScreenInfo >> 2; 2253 if(client->swapped) { 2254 register int n; 2255 swaps(&rep.sequenceNumber, n); 2256 swapl(&rep.length, n); 2257 swapl(&rep.number, n); 2258 } 2259 WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *)&rep); 2260 2261 if(!SiSnoPanoramiXExtension) { 2262 xXineramaScreenInfo scratch; 2263 int i; 2264 2265 for(i = 0; i < SiSXineramaNumScreens; i++) { 2266 scratch.x_org = SiSXineramadataPtr[i].x; 2267 scratch.y_org = SiSXineramadataPtr[i].y; 2268 scratch.width = SiSXineramadataPtr[i].width; 2269 scratch.height = SiSXineramadataPtr[i].height; 2270 if(client->swapped) { 2271 register int n; 2272 swaps(&scratch.x_org, n); 2273 swaps(&scratch.y_org, n); 2274 swaps(&scratch.width, n); 2275 swaps(&scratch.height, n); 2276 } 2277 WriteToClient(client, sz_XineramaScreenInfo, (char *)&scratch); 2278 } 2279 } 2280 2281 return client->noClientException; 2282} 2283 2284static int 2285SiSProcXineramaDispatch(ClientPtr client) 2286{ 2287 REQUEST(xReq); 2288 switch (stuff->data) { 2289 case X_PanoramiXQueryVersion: 2290 return SiSProcXineramaQueryVersion(client); 2291 case X_PanoramiXGetState: 2292 return SiSProcXineramaGetState(client); 2293 case X_PanoramiXGetScreenCount: 2294 return SiSProcXineramaGetScreenCount(client); 2295 case X_PanoramiXGetScreenSize: 2296 return SiSProcXineramaGetScreenSize(client); 2297 case X_XineramaIsActive: 2298 return SiSProcXineramaIsActive(client); 2299 case X_XineramaQueryScreens: 2300 return SiSProcXineramaQueryScreens(client); 2301 } 2302 return BadRequest; 2303} 2304 2305/* SProc */ 2306 2307static int 2308SiSSProcXineramaQueryVersion (ClientPtr client) 2309{ 2310 REQUEST(xPanoramiXQueryVersionReq); 2311 register int n; 2312 swaps(&stuff->length,n); 2313 REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); 2314 return SiSProcXineramaQueryVersion(client); 2315} 2316 2317static int 2318SiSSProcXineramaGetState(ClientPtr client) 2319{ 2320 REQUEST(xPanoramiXGetStateReq); 2321 register int n; 2322 swaps (&stuff->length, n); 2323 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); 2324 return SiSProcXineramaGetState(client); 2325} 2326 2327static int 2328SiSSProcXineramaGetScreenCount(ClientPtr client) 2329{ 2330 REQUEST(xPanoramiXGetScreenCountReq); 2331 register int n; 2332 swaps (&stuff->length, n); 2333 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); 2334 return SiSProcXineramaGetScreenCount(client); 2335} 2336 2337static int 2338SiSSProcXineramaGetScreenSize(ClientPtr client) 2339{ 2340 REQUEST(xPanoramiXGetScreenSizeReq); 2341 register int n; 2342 swaps (&stuff->length, n); 2343 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); 2344 return SiSProcXineramaGetScreenSize(client); 2345} 2346 2347static int 2348SiSSProcXineramaIsActive(ClientPtr client) 2349{ 2350 REQUEST(xXineramaIsActiveReq); 2351 register int n; 2352 swaps (&stuff->length, n); 2353 REQUEST_SIZE_MATCH(xXineramaIsActiveReq); 2354 return SiSProcXineramaIsActive(client); 2355} 2356 2357static int 2358SiSSProcXineramaQueryScreens(ClientPtr client) 2359{ 2360 REQUEST(xXineramaQueryScreensReq); 2361 register int n; 2362 swaps (&stuff->length, n); 2363 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); 2364 return SiSProcXineramaQueryScreens(client); 2365} 2366 2367int 2368SiSSProcXineramaDispatch(ClientPtr client) 2369{ 2370 REQUEST(xReq); 2371 switch (stuff->data) { 2372 case X_PanoramiXQueryVersion: 2373 return SiSSProcXineramaQueryVersion(client); 2374 case X_PanoramiXGetState: 2375 return SiSSProcXineramaGetState(client); 2376 case X_PanoramiXGetScreenCount: 2377 return SiSSProcXineramaGetScreenCount(client); 2378 case X_PanoramiXGetScreenSize: 2379 return SiSSProcXineramaGetScreenSize(client); 2380 case X_XineramaIsActive: 2381 return SiSSProcXineramaIsActive(client); 2382 case X_XineramaQueryScreens: 2383 return SiSSProcXineramaQueryScreens(client); 2384 } 2385 return BadRequest; 2386} 2387 2388static void 2389SiSXineramaResetProc(ExtensionEntry* extEntry) 2390{ 2391 /* Called by CloseDownExtensions() */ 2392 if(SiSXineramadataPtr) { 2393 Xfree(SiSXineramadataPtr); 2394 SiSXineramadataPtr = NULL; 2395 } 2396} 2397 2398static void 2399SiSXineramaExtensionInit(ScrnInfoPtr pScrn) 2400{ 2401 SISPtr pSiS = SISPTR(pScrn); 2402 Bool success = FALSE; 2403 2404 if(!(SiSXineramadataPtr)) { 2405 2406 if(!pSiS->MergedFB) { 2407 SiSnoPanoramiXExtension = TRUE; 2408 pSiS->MouseRestrictions = FALSE; 2409 return; 2410 } 2411 2412#ifdef PANORAMIX 2413 if(!noPanoramiXExtension) { 2414 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2415 "Xinerama active, not initializing SiS Pseudo-Xinerama\n"); 2416 SiSnoPanoramiXExtension = TRUE; 2417 pSiS->MouseRestrictions = FALSE; 2418 return; 2419 } 2420#endif 2421 2422 if(SiSnoPanoramiXExtension) { 2423 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2424 "SiS Pseudo-Xinerama disabled\n"); 2425 pSiS->MouseRestrictions = FALSE; 2426 return; 2427 } 2428 2429 if(pSiS->CRT2Position == sisClone) { 2430 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2431 "Running MergedFB in Clone mode, SiS Pseudo-Xinerama disabled\n"); 2432 SiSnoPanoramiXExtension = TRUE; 2433 pSiS->MouseRestrictions = FALSE; 2434 return; 2435 } 2436 2437 if(!(pSiS->AtLeastOneNonClone)) { 2438 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2439 "Only Clone modes defined, SiS Pseudo-Xinerama disabled\n"); 2440 SiSnoPanoramiXExtension = TRUE; 2441 pSiS->MouseRestrictions = FALSE; 2442 return; 2443 } 2444 2445 SiSXineramaNumScreens = 2; 2446 2447 while(SiSXineramaGeneration != serverGeneration) { 2448 2449 pSiS->XineramaExtEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0, 2450 SiSProcXineramaDispatch, 2451 SiSSProcXineramaDispatch, 2452 SiSXineramaResetProc, 2453 StandardMinorOpcode); 2454 2455 if(!pSiS->XineramaExtEntry) break; 2456 2457 if(!(SiSXineramadataPtr = (SiSXineramaData *) 2458 xcalloc(SiSXineramaNumScreens, sizeof(SiSXineramaData)))) break; 2459 2460 SiSXineramaGeneration = serverGeneration; 2461 success = TRUE; 2462 } 2463 2464 if(!success) { 2465 SISErrorLog(pScrn, "Failed to initialize SiS Pseudo-Xinerama extension\n"); 2466 SiSnoPanoramiXExtension = TRUE; 2467 pSiS->MouseRestrictions = FALSE; 2468 return; 2469 } 2470 2471 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2472 "SiS Pseudo-Xinerama extension initialized\n"); 2473 2474 pSiS->SiSXineramaVX = 0; 2475 pSiS->SiSXineramaVY = 0; 2476 2477 } 2478 2479 SiSUpdateXineramaScreenInfo(pScrn); 2480 2481} 2482#endif /* End of PseudoXinerama */ 2483 2484static void 2485SiSFreeCRT2Structs(SISPtr pSiS) 2486{ 2487 if(pSiS->CRT2pScrn) { 2488 if(pSiS->CRT2pScrn->modes) { 2489 while(pSiS->CRT2pScrn->modes) 2490 xf86DeleteMode(&pSiS->CRT2pScrn->modes, pSiS->CRT2pScrn->modes); 2491 } 2492 if(pSiS->CRT2pScrn->monitor) { 2493 if(pSiS->CRT2pScrn->monitor->Modes) { 2494 while(pSiS->CRT2pScrn->monitor->Modes) 2495 xf86DeleteMode(&pSiS->CRT2pScrn->monitor->Modes, pSiS->CRT2pScrn->monitor->Modes); 2496 } 2497 if(pSiS->CRT2pScrn->monitor->DDC) xfree(pSiS->CRT2pScrn->monitor->DDC); 2498 xfree(pSiS->CRT2pScrn->monitor); 2499 } 2500 xfree(pSiS->CRT2pScrn); 2501 pSiS->CRT2pScrn = NULL; 2502 } 2503} 2504 2505#endif /* End of MergedFB helpers */ 2506 2507static xf86MonPtr 2508SiSInternalDDC(ScrnInfoPtr pScrn, int crtno) 2509{ 2510 SISPtr pSiS = SISPTR(pScrn); 2511 xf86MonPtr pMonitor = NULL; 2512 UShort temp = 0xffff, temp1, i, realcrtno = crtno; 2513 UChar buffer[256]; 2514 2515 /* If CRT1 is off, skip DDC */ 2516 if((pSiS->CRT1off) && (!crtno)) return NULL; 2517 2518 if(crtno) { 2519 if(pSiS->VBFlags & CRT2_LCD) realcrtno = 1; 2520 else if(pSiS->VBFlags & CRT2_VGA) realcrtno = 2; 2521 else return NULL; 2522 if(pSiS->SiS_Pr->DDCPortMixup) realcrtno = 0; 2523 } else { 2524 /* If CRT1 is LCDA, skip DDC (except 301C: DDC allowed, but uses CRT2 port!) */ 2525 if(pSiS->VBFlags & CRT1_LCDA) { 2526 if(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE) realcrtno = 1; 2527 else return NULL; 2528 } 2529 } 2530 2531 i = 3; /* Number of retrys */ 2532 do { 2533 temp1 = SiS_HandleDDC(pSiS->SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 2534 realcrtno, 0, &buffer[0], pSiS->VBFlags2); 2535 if((temp1) && (temp1 != 0xffff)) temp = temp1; 2536 } while((temp == 0xffff) && i--); 2537 if(temp != 0xffff) { 2538 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT%d DDC supported\n", crtno + 1); 2539 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT%d DDC level: %s%s%s%s\n", 2540 crtno + 1, 2541 (temp & 0x1a) ? "" : "[none of the supported]", 2542 (temp & 0x02) ? "2 " : "", 2543 (temp & 0x08) ? "D&P" : "", 2544 (temp & 0x10) ? "FPDI-2" : ""); 2545 if(temp & 0x02) { 2546 i = 5; /* Number of retrys */ 2547 do { 2548 temp = SiS_HandleDDC(pSiS->SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 2549 realcrtno, 1, &buffer[0], pSiS->VBFlags2); 2550 } while((temp) && i--); 2551 if(!temp) { 2552 if((pMonitor = xf86InterpretEDID(pScrn->scrnIndex, &buffer[0]))) { 2553 int tempvgagamma = 0, templcdgamma = 0; 2554 if(buffer[0x14] & 0x80) { 2555 templcdgamma = (buffer[0x17] + 100) * 10; 2556 } else { 2557 tempvgagamma = (buffer[0x17] + 100) * 10;; 2558 } 2559 if(crtno == 0) { 2560 if(tempvgagamma) pSiS->CRT1VGAMonitorGamma = tempvgagamma; 2561 /* LCD never via (demanded) CRT1 DDC port */ 2562 } else { 2563 if(tempvgagamma) pSiS->CRT2VGAMonitorGamma = tempvgagamma; 2564 if(templcdgamma) pSiS->CRT2LCDMonitorGamma = templcdgamma; 2565 } 2566 return(pMonitor); 2567 } else { 2568 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2569 "CRT%d DDC EDID corrupt\n", crtno + 1); 2570 } 2571 } else if(temp == 0xFFFE) { 2572 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2573 "CRT%d DDC data is from wrong device type (%s)\n", 2574 crtno + 1, 2575 (realcrtno == 1) ? "analog instead of digital" : "digital instead of analog"); 2576 } else { 2577 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2578 "CRT%d DDC reading failed\n", crtno + 1); 2579 } 2580 } else if(temp & 0x18) { 2581 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2582 "DDC for VESA D&P and FPDI-2 not supported yet.\n"); 2583 } 2584 } else { 2585 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2586 "CRT%d DDC probing failed\n", crtno + 1); 2587 } 2588 return(NULL); 2589} 2590 2591static xf86MonPtr 2592SiSDoPrivateDDC(ScrnInfoPtr pScrn, int *crtnum) 2593{ 2594 SISPtr pSiS = SISPTR(pScrn); 2595 2596#ifdef SISDUALHEAD 2597 if(pSiS->DualHeadMode) { 2598 if(pSiS->SecondHead) { 2599 *crtnum = 1; 2600 return(SiSInternalDDC(pScrn, 0)); 2601 } else { 2602 *crtnum = 2; 2603 return(SiSInternalDDC(pScrn, 1)); 2604 } 2605 } else 2606#endif 2607 if((pSiS->CRT1off) || (!pSiS->CRT1Detected)) { 2608 *crtnum = 2; 2609 return(SiSInternalDDC(pScrn, 1)); 2610 } else { 2611 *crtnum = 1; 2612 return(SiSInternalDDC(pScrn, 0)); 2613 } 2614} 2615 2616static void 2617SiSFindAspect(ScrnInfoPtr pScrn, xf86MonPtr pMonitor, int crtnum) 2618{ 2619 SISPtr pSiS = SISPTR(pScrn); 2620 int UseWide = 0; 2621 int aspect = 0; 2622 Bool fromdim = FALSE; 2623 2624 if((pSiS->VGAEngine == SIS_315_VGA) && (!DIGITAL(pMonitor->features.input_type))) { 2625 if(pMonitor->features.hsize && pMonitor->features.vsize) { 2626 aspect = (pMonitor->features.hsize * 1000) / pMonitor->features.vsize; 2627 if(aspect >= 1400) UseWide = 1; 2628 fromdim = TRUE; 2629 } else if((PREFERRED_TIMING_MODE(pMonitor->features.msc)) && 2630 (pMonitor->det_mon[0].type == DT)) { 2631 aspect = (pMonitor->det_mon[0].section.d_timings.h_active * 1000) / 2632 pMonitor->det_mon[0].section.d_timings.v_active; 2633 if(aspect >= 1400) UseWide = 1; 2634 } 2635 if(aspect) { 2636 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2637 "According to %s, CRT%d aspect ratio is %.2f:1 (%s)\n", 2638 fromdim ? "DDC size" : "preferred mode", 2639 crtnum, (float)aspect / 1000.0, UseWide ? "wide" : "normal"); 2640 } else { 2641 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2642 "Unable to determine CRT%d aspect ratio, assuming \"normal\"\n", 2643 crtnum); 2644 } 2645 } 2646 2647 if((crtnum == 1) && (pSiS->SiS_Pr->SiS_UseWide == -1)) { 2648 pSiS->SiS_Pr->SiS_UseWide = UseWide; 2649 } else if((crtnum == 2) && (pSiS->SiS_Pr->SiS_UseWideCRT2 == -1)) { 2650 pSiS->SiS_Pr->SiS_UseWideCRT2 = UseWide; 2651 } 2652} 2653 2654static Bool 2655SiSMakeOwnModeList(ScrnInfoPtr pScrn, Bool acceptcustommodes, Bool includelcdmodes, 2656 Bool isfordvi, Bool *havecustommodes, Bool fakecrt2modes, Bool IsForCRT2) 2657{ 2658 DisplayModePtr tempmode, delmode, mymodes; 2659 2660 if((mymodes = SiSBuildBuiltInModeList(pScrn, includelcdmodes, isfordvi, fakecrt2modes, IsForCRT2))) { 2661 if(!acceptcustommodes) { 2662 while(pScrn->monitor->Modes) 2663 xf86DeleteMode(&pScrn->monitor->Modes, pScrn->monitor->Modes); 2664 pScrn->monitor->Modes = mymodes; 2665 } else { 2666 delmode = pScrn->monitor->Modes; 2667 while(delmode) { 2668 if(delmode->type & M_T_DEFAULT) { 2669 tempmode = delmode->next; 2670 xf86DeleteMode(&pScrn->monitor->Modes, delmode); 2671 delmode = tempmode; 2672 } else { 2673 delmode = delmode->next; 2674 } 2675 } 2676 /* Link default modes AFTER user ones */ 2677 if((tempmode = pScrn->monitor->Modes)) { 2678 *havecustommodes = TRUE; 2679 while(tempmode) { 2680 if(!tempmode->next) break; 2681 else tempmode = tempmode->next; 2682 } 2683 tempmode->next = mymodes; 2684 mymodes->prev = tempmode; 2685 } else { 2686 pScrn->monitor->Modes = mymodes; 2687 } 2688#if 0 2689 pScrn->monitor->Modes = mymodes; 2690 while(mymodes) { 2691 if(!mymodes->next) break; 2692 else mymodes = mymodes->next; 2693 } 2694 mymodes->next = tempmode; 2695 if(tempmode) { 2696 tempmode->prev = mymodes; 2697 } 2698#endif 2699 } 2700 return TRUE; 2701 } else 2702 return FALSE; 2703} 2704 2705static void 2706SiSPrintModes(ScrnInfoPtr pScrn) 2707{ 2708 DisplayModePtr p; 2709 float hsync, refresh = 0.0; 2710 char *desc, *desc2, *prefix, *uprefix, *output; 2711 2712 xf86DrvMsg(pScrn->scrnIndex, pScrn->virtualFrom, "Virtual size is %dx%d " 2713 "(pitch %d)\n", pScrn->virtualX, pScrn->virtualY, 2714 pScrn->displayWidth); 2715 2716 if((p = pScrn->modes) == NULL) return; 2717 2718 do { 2719 desc = desc2 = ""; 2720 uprefix = " "; 2721 prefix = "Mode"; 2722 output = "For CRT device: "; 2723 if(p->HSync > 0.0) hsync = p->HSync; 2724 else if (p->HTotal > 0) hsync = (float)p->Clock / (float)p->HTotal; 2725 else hsync = 0.0; 2726 refresh = 0.0; 2727 if(p->VRefresh > 0.0) refresh = p->VRefresh; 2728 else if (p->HTotal > 0 && p->VTotal > 0) { 2729 refresh = p->Clock * 1000.0 / p->HTotal / p->VTotal; 2730 if(p->Flags & V_INTERLACE) refresh *= 2.0; 2731 if(p->Flags & V_DBLSCAN) refresh /= 2.0; 2732 if(p->VScan > 1) refresh /= p->VScan; 2733 } 2734 if(p->Flags & V_INTERLACE) desc = " (I)"; 2735 if(p->Flags & V_DBLSCAN) desc = " (D)"; 2736 if(p->VScan > 1) desc2 = " (VScan)"; 2737#ifdef M_T_USERDEF 2738 if(p->type & M_T_USERDEF) uprefix = "*"; 2739#endif 2740 if(p->type & M_T_BUILTIN) { 2741 prefix = "Built-in mode"; 2742 output = ""; 2743 } else if (p->type & M_T_DEFAULT) { 2744 prefix = "Default mode"; 2745 } else { 2746 output = ""; 2747 } 2748 2749 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2750 "%s%s \"%s\" (%dx%d) (%s%.1f MHz, %.1f kHz, %.1f Hz%s%s)\n", 2751 uprefix, prefix, p->name, p->HDisplay, p->VDisplay, output, 2752 p->Clock / 1000.0, hsync, refresh, desc, desc2); 2753 2754 p = p->next; 2755 } while (p != NULL && p != pScrn->modes); 2756} 2757 2758Bool SISDetermineLCDACap(ScrnInfoPtr pScrn) 2759{ 2760 SISPtr pSiS = SISPTR(pScrn); 2761 2762 if( ((pSiS->ChipType == SIS_650) || 2763 (pSiS->ChipType == SIS_315PRO) || 2764 (pSiS->ChipType >= SIS_661)) && 2765 (pSiS->ChipType != XGI_20) && 2766 (pSiS->VBFlags2 & VB2_SISLCDABRIDGE) && 2767 (pSiS->VESA != 1) ) { 2768 return TRUE; 2769 } 2770 return FALSE; 2771} 2772 2773void SISSaveDetectedDevices(ScrnInfoPtr pScrn) 2774{ 2775 SISPtr pSiS = SISPTR(pScrn); 2776 /* Backup detected CRT2 devices */ 2777 pSiS->detectedCRT2Devices = pSiS->VBFlags & (CRT2_LCD|CRT2_TV|CRT2_VGA|TV_AVIDEO|TV_SVIDEO| 2778 TV_SCART|TV_HIVISION|TV_YPBPR); 2779} 2780 2781static Bool 2782SISCheckBIOS(SISPtr pSiS, UShort mypciid, UShort mypcivendor, int biossize) 2783{ 2784 UShort romptr, pciid; 2785 2786 if(!pSiS->BIOS) return FALSE; 2787 2788 if((pSiS->BIOS[0] != 0x55) || (pSiS->BIOS[1] != 0xaa)) return FALSE; 2789 2790 romptr = pSiS->BIOS[0x18] | (pSiS->BIOS[0x19] << 8); 2791 if(romptr > (biossize - 8)) return FALSE; 2792 if((pSiS->BIOS[romptr] != 'P') || (pSiS->BIOS[romptr+1] != 'C') || 2793 (pSiS->BIOS[romptr+2] != 'I') || (pSiS->BIOS[romptr+3] != 'R')) return FALSE; 2794 2795 pciid = pSiS->BIOS[romptr+4] | (pSiS->BIOS[romptr+5] << 8); 2796 if(pciid != mypcivendor) return FALSE; 2797 2798 pciid = pSiS->BIOS[romptr+6] | (pSiS->BIOS[romptr+7] << 8); 2799 if(pciid != mypciid) return FALSE; 2800 2801 return TRUE; 2802} 2803 2804static void 2805SiS_LoadInitVBE(ScrnInfoPtr pScrn) 2806{ 2807 SISPtr pSiS = SISPTR(pScrn); 2808 2809 /* Don't load the VBE module for secondary 2810 * cards which sisfb POSTed. We don't want 2811 * int10 to overwrite our set up (such as 2812 * disabled a0000 memory address decoding). 2813 * We don't need the VBE anyway because 2814 * the card will never be in text mode, 2815 * and we can restore graphics modes just 2816 * perfectly. 2817 */ 2818 if( !pSiS->Primary && 2819 pSiS->sisfbcardposted) 2820 return; 2821 2822 if(pSiS->pVbe) return; 2823 2824 if(xf86LoadSubModule(pScrn, "vbe")) { 2825#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 2826 pSiS->pVbe = VBEInit(pSiS->pInt, pSiS->pEnt->index); 2827#else 2828 pSiS->pVbe = VBEExtendedInit(pSiS->pInt, pSiS->pEnt->index, 2829 SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH); 2830#endif 2831 } 2832 2833 if(!pSiS->pVbe) { 2834 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2835 "Failed to load/initialize vbe module\n"); 2836 } 2837} 2838 2839#ifdef SIS_PC_PLATFORM 2840static void 2841SiS_MapVGAMem(ScrnInfoPtr pScrn) 2842{ 2843 SISPtr pSiS = SISPTR(pScrn); 2844 2845 /* Map 64k VGA window for saving/restoring CGA fonts */ 2846 pSiS->VGAMapSize = 0x10000; 2847 pSiS->VGAMapPhys = 0; /* Default */ 2848 if((!pSiS->Primary) || (!pSiS->VGADecodingEnabled)) { 2849 /* If card is secondary or if a0000-address decoding 2850 * is disabled, set Phys to beginning of our video RAM. 2851 */ 2852 pSiS->VGAMapPhys = PCI_REGION_BASE(pSiS->PciInfo, 0, REGION_MEM); 2853 } 2854 if(!SiSVGAMapMem(pScrn)) { 2855 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2856 "Failed to map VGA memory (0x%lx), can't save/restore console fonts\n", 2857 pSiS->VGAMapPhys); 2858 } 2859} 2860#endif 2861 2862static void 2863SiS_CheckKernelFB(ScrnInfoPtr pScrn) 2864{ 2865 SISPtr pSiS = SISPTR(pScrn); 2866 int fd, i; 2867 CARD32 sisfbinfosize = 0, sisfbversion; 2868 sisfb_info *mysisfbinfo; 2869 char name[16]; 2870 2871 pSiS->donttrustpdc = FALSE; 2872 pSiS->sisfbpdc = 0xff; 2873 pSiS->sisfbpdca = 0xff; 2874 pSiS->sisfblcda = 0xff; 2875 pSiS->sisfbscalelcd = -1; 2876 pSiS->sisfbspecialtiming = CUT_NONE; 2877 pSiS->sisfb_haveemi = FALSE; 2878 pSiS->sisfbfound = FALSE; 2879 pSiS->sisfb_tvposvalid = FALSE; 2880 pSiS->sisfbdevname[0] = 0; 2881 pSiS->sisfb_havelock = FALSE; 2882 pSiS->sisfbHaveNewHeapDef = FALSE; 2883 pSiS->sisfbHeapSize = 0; 2884 pSiS->sisfbVideoOffset = 0; 2885 pSiS->sisfbxSTN = FALSE; 2886 pSiS->sisfbcanpost = FALSE; /* (Old) sisfb can't POST card */ 2887 pSiS->sisfbcardposted = TRUE; /* If (old) sisfb is running, card must have been POSTed */ 2888 pSiS->sisfbprimary = FALSE; /* (Old) sisfb doesn't know */ 2889 2890 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 2891 2892 i = 0; 2893 do { 2894 2895 if(i <= 7) { 2896 sprintf(name, "/dev/fb%1d", i); 2897 } else { 2898 sprintf(name, "/dev/fb/%1d", (i - 8)); 2899 } 2900 2901 if((fd = open(name, O_RDONLY)) != -1) { 2902 2903 Bool gotit = FALSE; 2904 2905 if(!ioctl(fd, SISFB_GET_INFO_SIZE, &sisfbinfosize)) { 2906 if((mysisfbinfo = xalloc(sisfbinfosize))) { 2907 if(!ioctl(fd, (SISFB_GET_INFO | (sisfbinfosize << 16)), mysisfbinfo)) { 2908 gotit = TRUE; 2909 } else { 2910 xfree(mysisfbinfo); 2911 mysisfbinfo = NULL; 2912 } 2913 } 2914 } else { 2915 if((mysisfbinfo = xalloc(sizeof(*mysisfbinfo) + 16))) { 2916 if(!ioctl(fd, SISFB_GET_INFO_OLD, mysisfbinfo)) { 2917 gotit = TRUE; 2918 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2919 "Possibly old version of sisfb detected. Please update.\n"); 2920 } else { 2921 xfree(mysisfbinfo); 2922 mysisfbinfo = NULL; 2923 } 2924 } 2925 } 2926 2927 if(gotit) { 2928 2929 if(mysisfbinfo->sisfb_id == SISFB_ID) { 2930 2931 sisfbversion = (mysisfbinfo->sisfb_version << 16) | 2932 (mysisfbinfo->sisfb_revision << 8) | 2933 (mysisfbinfo->sisfb_patchlevel); 2934 2935 if(sisfbversion >= SISFB_VERSION(1, 5, 8)) { 2936 /* Added PCI bus/slot/func into in sisfb Version 1.5.08. 2937 * Check this to make sure we run on the same card as sisfb 2938 */ 2939 if((mysisfbinfo->sisfb_pcibus == pSiS->PciBus) && 2940 (mysisfbinfo->sisfb_pcislot == pSiS->PciDevice) && 2941 (mysisfbinfo->sisfb_pcifunc == pSiS->PciFunc)) { 2942 pSiS->sisfbfound = TRUE; 2943 } 2944 } else pSiS->sisfbfound = TRUE; 2945 2946 if(pSiS->sisfbfound) { 2947 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2948 "%s: SiS kernel fb driver (sisfb) %d.%d.%d detected (PCI:%02d:%02d.%d)\n", 2949 &name[5], 2950 mysisfbinfo->sisfb_version, 2951 mysisfbinfo->sisfb_revision, 2952 mysisfbinfo->sisfb_patchlevel, 2953 pSiS->PciBus, 2954 pSiS->PciDevice, 2955 pSiS->PciFunc); 2956 2957 /* Added version/rev/pl in sisfb 1.4.0 */ 2958 if(mysisfbinfo->sisfb_version == 0) { 2959 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2960 "Old version of sisfb found. Please update.\n"); 2961 } 2962 /* Basically, we can't trust the pdc register if sisfb is loaded */ 2963 pSiS->donttrustpdc = TRUE; 2964 pSiS->sisfbHeapStart = mysisfbinfo->heapstart; 2965 2966 if(sisfbversion >= SISFB_VERSION(1, 7, 20)) { 2967 pSiS->sisfbHeapSize = mysisfbinfo->sisfb_heapsize; 2968 pSiS->sisfbVideoOffset = mysisfbinfo->sisfb_videooffset; 2969 pSiS->sisfbHaveNewHeapDef = TRUE; 2970 pSiS->sisfbFSTN = mysisfbinfo->sisfb_curfstn; 2971 pSiS->sisfbDSTN = mysisfbinfo->sisfb_curdstn; 2972 pSiS->sisfbxSTN = TRUE; 2973 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2974 "sisfb: memory heap at %dKB, size %dKB, viewport at %dKB\n", 2975 (int)pSiS->sisfbHeapStart, (int)pSiS->sisfbHeapSize, 2976 (int)pSiS->sisfbVideoOffset/1024); 2977 } else { 2978 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2979 "sisfb: memory heap at %dKB\n", (int)pSiS->sisfbHeapStart); 2980 } 2981 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2982 "sisfb: using video mode 0x%02x\n", mysisfbinfo->fbvidmode); 2983 pSiS->OldMode = mysisfbinfo->fbvidmode; 2984 if(sisfbversion >= SISFB_VERSION(1, 5, 6)) { 2985 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2986 "sisfb: using %s, reserved %dK\n", 2987 (mysisfbinfo->sisfb_caps & 0x40) ? "SiS300 series Turboqueue" : 2988 (mysisfbinfo->sisfb_caps & 0x20) ? "SiS315/330/340 series AGP command queue" : 2989 (mysisfbinfo->sisfb_caps & 0x10) ? "SiS315/330/340 series VRAM command queue" : 2990 (mysisfbinfo->sisfb_caps & 0x08) ? "SiS315/330/340 series MMIO mode" : 2991 "no command queue", 2992 (int)mysisfbinfo->sisfb_tqlen); 2993 } 2994 if(sisfbversion >= SISFB_VERSION(1, 5, 10)) { 2995 /* We can trust the pdc value if sisfb is of recent version */ 2996 if(pSiS->VGAEngine == SIS_300_VGA) pSiS->donttrustpdc = FALSE; 2997 } 2998 if(sisfbversion >= SISFB_VERSION(1, 5, 11)) { 2999 if(pSiS->VGAEngine == SIS_300_VGA) { 3000 /* As of 1.5.11, sisfb saved the register for us (300 series) */ 3001 pSiS->sisfbpdc = mysisfbinfo->sisfb_lcdpdc; 3002 if(!pSiS->sisfbpdc) pSiS->sisfbpdc = 0xff; 3003 } 3004 } 3005 if(sisfbversion >= SISFB_VERSION(1, 5, 14)) { 3006 if(pSiS->VGAEngine == SIS_315_VGA) { 3007 pSiS->sisfblcda = mysisfbinfo->sisfb_lcda; 3008 } 3009 } 3010 if(sisfbversion >= SISFB_VERSION(1, 6, 13)) { 3011 pSiS->sisfbscalelcd = mysisfbinfo->sisfb_scalelcd; 3012 pSiS->sisfbspecialtiming = mysisfbinfo->sisfb_specialtiming; 3013 } 3014 if(sisfbversion >= SISFB_VERSION(1, 6, 16)) { 3015 if(pSiS->VGAEngine == SIS_315_VGA) { 3016 pSiS->donttrustpdc = FALSE; 3017 pSiS->sisfbpdc = mysisfbinfo->sisfb_lcdpdc; 3018 if(sisfbversion >= SISFB_VERSION(1, 6, 24)) { 3019 pSiS->sisfb_haveemi = mysisfbinfo->sisfb_haveemi ? TRUE : FALSE; 3020 pSiS->sisfb_haveemilcd = TRUE; /* will match most cases */ 3021 pSiS->sisfb_emi30 = mysisfbinfo->sisfb_emi30; 3022 pSiS->sisfb_emi31 = mysisfbinfo->sisfb_emi31; 3023 pSiS->sisfb_emi32 = mysisfbinfo->sisfb_emi32; 3024 pSiS->sisfb_emi33 = mysisfbinfo->sisfb_emi33; 3025 } 3026 if(sisfbversion >= SISFB_VERSION(1, 6, 25)) { 3027 pSiS->sisfb_haveemilcd = mysisfbinfo->sisfb_haveemilcd ? TRUE : FALSE; 3028 } 3029 if(sisfbversion >= SISFB_VERSION(1, 6, 31)) { 3030 pSiS->sisfbpdca = mysisfbinfo->sisfb_lcdpdca; 3031 } else { 3032 if(pSiS->sisfbpdc) { 3033 pSiS->sisfbpdca = (pSiS->sisfbpdc & 0xf0) >> 3; 3034 pSiS->sisfbpdc = (pSiS->sisfbpdc & 0x0f) << 1; 3035 } else { 3036 pSiS->sisfbpdca = pSiS->sisfbpdc = 0xff; 3037 } 3038 } 3039 } 3040 } 3041 if(sisfbversion >= SISFB_VERSION(1, 7, 0)) { 3042 pSiS->sisfb_havelock = TRUE; 3043 if(sisfbversion >= SISFB_VERSION(1, 7, 1)) { 3044 pSiS->sisfb_tvxpos = mysisfbinfo->sisfb_tvxpos; 3045 pSiS->sisfb_tvypos = mysisfbinfo->sisfb_tvypos; 3046 pSiS->sisfb_tvposvalid = TRUE; 3047 } 3048 } 3049 if(sisfbversion >= SISFB_VERSION(1, 8, 7)) { 3050 pSiS->sisfbcanpost = (mysisfbinfo->sisfb_can_post) ? TRUE : FALSE; 3051 pSiS->sisfbcardposted = (mysisfbinfo->sisfb_card_posted) ? TRUE : FALSE; 3052 pSiS->sisfbprimary = (mysisfbinfo->sisfb_was_boot_device) ? TRUE : FALSE; 3053 /* Validity check */ 3054 if(!pSiS->sisfbcardposted) { 3055 pSiS->sisfbprimary = FALSE; 3056 } 3057 } 3058 } 3059 } 3060 xfree(mysisfbinfo); 3061 mysisfbinfo = NULL; 3062 } 3063 close (fd); 3064 } 3065 i++; 3066 } while((i <= 15) && (!pSiS->sisfbfound)); 3067 3068 if(pSiS->sisfbfound) { 3069 strncpy(pSiS->sisfbdevname, name, 15); 3070 } else { 3071 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "sisfb not found\n"); 3072 } 3073 } 3074 3075 if(!pSiS->sisfbfound) { 3076 pSiS->sisfbcardposted = FALSE; 3077 } 3078} 3079 3080static void 3081SiSPseudo(ScrnInfoPtr pScrn) 3082{ 3083} 3084 3085/* PreInit() 3086 * 3087 * Mandatory 3088 */ 3089static Bool 3090SISPreInit(ScrnInfoPtr pScrn, int flags) 3091{ 3092 SISPtr pSiS; 3093#ifdef SISDUALHEAD 3094 SISEntPtr pSiSEnt = NULL; 3095#endif 3096 MessageType from; 3097 UChar usScratchCR17, usScratchCR32, usScratchCR63; 3098 UChar usScratchSR1F, srlockReg, crlockReg; 3099 unsigned int i; 3100 int pix24flags, temp; 3101 ClockRangePtr clockRanges; 3102 xf86MonPtr pMonitor = NULL; 3103 Bool didddc2, fromDDC, crt1freqoverruled = FALSE; 3104 UChar CR5F, tempreg; 3105#if defined(SISMERGED) || defined(SISDUALHEAD) 3106 DisplayModePtr first, p, n; 3107#endif 3108#ifdef SISMERGED 3109 Bool crt2freqoverruled = FALSE; 3110#endif 3111 3112 static const char *ddcsstr = "CRT%d DDC monitor info: *******************************************\n"; 3113 static const char *ddcestr = "End of CRT%d DDC monitor info *************************************\n"; 3114 static const char *subshstr = "Substituting missing CRT%d monitor HSync range by DDC data\n"; 3115 static const char *subsvstr = "Substituting missing CRT%d monitor VRefresh range by DDC data\n"; 3116 static const char *saneh = "Correcting %s CRT%d monitor HSync range\n"; 3117 static const char *sanev = "Correcting %s CRT%d monitor VRefresh range\n"; 3118#ifdef SISMERGED 3119 static const char *mergednocrt1 = "CRT1 not detected or forced off. %s.\n"; 3120 static const char *mergednocrt2 = "No CRT2 output selected or no video bridge detected. %s.\n"; 3121 static const char *mergeddisstr = "MergedFB mode disabled"; 3122 static const char *modesforstr = "Modes for CRT%d: **************************************************\n"; 3123 static const char *crtsetupstr = "*************************** CRT%d setup ***************************\n"; 3124 static const char *crt2monname = "CRT2"; 3125#endif 3126#if defined(SISDUALHEAD) || defined(SISMERGED) 3127 static const char *notsuitablestr = "Not using mode \"%s\" (not suitable for %s mode)\n"; 3128#endif 3129 3130 if(flags & PROBE_DETECT) { 3131 3132 vbeInfoPtr pVbe; 3133 3134 if(xf86LoadSubModule(pScrn, "vbe")) { 3135 int index = xf86GetEntityInfo(pScrn->entityList[0])->index; 3136#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 3137 if((pVbe = VBEInit(NULL, index))) 3138#else 3139 if((pVbe = VBEExtendedInit(NULL, index, 0))) 3140#endif 3141 { 3142 ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 3143 vbeFree(pVbe); 3144 } 3145 } 3146 return TRUE; 3147 } 3148 3149 /* 3150 * Note: This function is only called once at server startup, and 3151 * not at the start of each server generation. This means that 3152 * only things that are persistent across server generations can 3153 * be initialised here. xf86Screens[] is the array of all screens, 3154 * (pScrn is a pointer to one of these). Privates allocated using 3155 * xf86AllocateScrnInfoPrivateIndex() are too, and should be used 3156 * for data that must persist across server generations. 3157 * 3158 * Per-generation data should be allocated with 3159 * AllocateScreenPrivateIndex() from the ScreenInit() function. 3160 */ 3161 3162 /* Check the number of entities, and fail if it isn't one. */ 3163 if(pScrn->numEntities != 1) { 3164 SISErrorLog(pScrn, "Number of entities is not 1\n"); 3165 return FALSE; 3166 } 3167 3168 /* Due to the liberal license terms this is needed for 3169 * keeping the copyright notice readable and intact in 3170 * binary distributions. Removing this is a copyright 3171 * infringement. Please read the license terms above. 3172 */ 3173 3174 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3175 "SiS driver (%d/%02d/%02d-%d, compiled for " SISMYSERVERNAME " %d.%d.%d.%d)\n", 3176 SISDRIVERVERSIONYEAR + 2000, SISDRIVERVERSIONMONTH, 3177 SISDRIVERVERSIONDAY, SISDRIVERREVISION, 3178#ifdef XORG_VERSION_CURRENT 3179 XORG_VERSION_MAJOR, XORG_VERSION_MINOR, 3180 XORG_VERSION_PATCH, XORG_VERSION_SNAP 3181#else 3182 XF86_VERSION_MAJOR, XF86_VERSION_MINOR, 3183 XF86_VERSION_PATCH, XF86_VERSION_SNAP 3184#endif 3185 ); 3186 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3187 "Copyright (C) 2001-2005 Thomas Winischhofer <thomas@winischhofer.net> and others\n"); 3188 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3189 "*** See http://www.winischhofer.eu/linuxsisvga.shtml\n"); 3190 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3191 "*** for documentation and updates.\n"); 3192 3193#ifdef XORG_VERSION_CURRENT 3194#if 0 /* no prototype yet */ 3195 if(xorgGetVersion() != XORG_VERSION_CURRENT) { 3196 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3197 "This driver binary is not compiled for this version of " SISMYSERVERNAME "\n"); 3198 } 3199#endif 3200#else 3201#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0) 3202 if(xf86GetVersion() != XF86_VERSION_CURRENT) { 3203 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3204 "This driver binary is not compiled for this version of " SISMYSERVERNAME "\n"); 3205 } 3206#endif 3207#endif 3208 3209 /* Allocate the SISRec driverPrivate */ 3210 if(!SISGetRec(pScrn)) { 3211 SISErrorLog(pScrn, "Could not allocate memory for pSiS private\n"); 3212 return FALSE; 3213 } 3214 pSiS = SISPTR(pScrn); 3215 pSiS->pScrn = pScrn; 3216 3217 pSiS->pInt = NULL; 3218 3219 /* Save PCI Domain Base */ 3220#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 3221 pSiS->IODBase = 0; 3222#else 3223 pSiS->IODBase = pScrn->domainIOBase; 3224#endif 3225 3226 /* Get the entity, and make sure it is PCI. */ 3227 pSiS->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 3228 if(pSiS->pEnt->location.type != BUS_PCI) { 3229 SISErrorLog(pScrn, "Entity's bus type is not PCI\n"); 3230 goto my_error_0; 3231 } 3232 3233#ifdef SISDUALHEAD 3234 /* Allocate an entity private if necessary */ 3235 if(xf86IsEntityShared(pScrn->entityList[0])) { 3236 pSiSEnt = xf86GetEntityPrivate(pScrn->entityList[0], SISEntityIndex)->ptr; 3237 pSiS->entityPrivate = pSiSEnt; 3238 3239 /* If something went wrong, quit here */ 3240 if((pSiSEnt->DisableDual) || (pSiSEnt->ErrorAfterFirst)) { 3241 SISErrorLog(pScrn, "First head encountered fatal error, aborting...\n"); 3242 goto my_error_0; 3243 } 3244 } 3245#endif 3246 3247 /* Find the PCI info for this screen */ 3248 pSiS->PciInfo = xf86GetPciInfoForEntity(pSiS->pEnt->index); 3249 pSiS->PciBus = PCI_CFG_BUS(pSiS->PciInfo); /*SIS_PCI_BUS(pSiS->PciInfo);*/ 3250 pSiS->PciDevice = PCI_CFG_DEV(pSiS->PciInfo); /*SIS_PCI_DEVICE(pSiS->PciInfo);*/ 3251 pSiS->PciFunc = PCI_CFG_FUNC(pSiS->PciInfo); /*SIS_PCI_FUNC(pSiS->PciInfo);*/ 3252 3253 pSiS->PciTag = pciTag(PCI_DEV_BUS(pSiS->PciInfo), 3254 PCI_DEV_DEV(pSiS->PciInfo), 3255 PCI_DEV_FUNC(pSiS->PciInfo)); 3256 3257#ifdef SIS_NEED_MAP_IOP 3258 /********************************************/ 3259 /* THIS IS BROKEN AND WON'T WORK */ 3260 /* Reasons: */ 3261 /* 1) MIPS and ARM have no i/o ports but */ 3262 /* use memory mapped i/o only. The inX/outX */ 3263 /* macros in compiler.h are smart enough to */ 3264 /* add "IOPortBase" to the port number, but */ 3265 /* "IOPortBase" is never initialized. */ 3266 /* 2) IOPortBase is declared in compiler.h */ 3267 /* itself. So until somebody fixes all */ 3268 /* modules that #include compiler.h to set */ 3269 /* IOPortBase, vga support for MIPS and ARM */ 3270 /* is unusable. */ 3271 /* (In this driver this is solvable because */ 3272 /* we have our own vgaHW routines. However, */ 3273 /* we use /dev/port for now instead.) */ 3274 /********************************************/ 3275 pSiS->IOPAddress = pSiS->IODBase + pSiS->PciInfo->ioBase[2]; 3276 if(!SISMapIOPMem(pScrn)) { 3277 SISErrorLog(pScrn, "Could not map I/O port area at 0x%x\n", pSiS->IOPAddress); 3278 goto my_error_0; 3279 } else { 3280 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I/O port area mapped to %p, size 128\n", pSiS->IOPBase); 3281#if defined(__mips__) || defined(__arm32__) 3282 /* inX/outX macros on these use IOPortBase as offset */ 3283 /* This is entirely skrewed. */ 3284 IOPortBase = (unsigned int)pSiS->IOPBase; 3285#endif 3286 } 3287#endif 3288 3289 /* Set up i/o port access (for non-x86) */ 3290#ifdef SISUSEDEVPORT 3291 if((sisdevport = open("/dev/port", O_RDWR, 0)) == -1) { 3292 SISErrorLog(pScrn, "Failed to open /dev/port for read/write\n"); 3293 goto my_error_0; 3294 } 3295 pSiS->sisdevportopen = TRUE; 3296#endif 3297 3298 /* 3299 * Set the Chipset and ChipRev, allowing config file entries to 3300 * override. DANGEROUS! 3301 */ 3302 { 3303 SymTabRec *myChipsets = SISChipsets; 3304 3305 if(PCI_DEV_VENDOR_ID(pSiS->PciInfo) == PCI_VENDOR_XGI) { 3306 myChipsets = XGIChipsets; 3307 } 3308 3309 if(pSiS->pEnt->device->chipset && *pSiS->pEnt->device->chipset) { 3310 3311 pScrn->chipset = pSiS->pEnt->device->chipset; 3312 pSiS->Chipset = xf86StringToToken(myChipsets, pScrn->chipset); 3313 3314 } else if(pSiS->pEnt->device->chipID >= 0) { 3315 3316 pSiS->Chipset = pSiS->pEnt->device->chipID; 3317 pScrn->chipset = (char *)xf86TokenToString(myChipsets, pSiS->Chipset); 3318 3319 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", 3320 pSiS->Chipset); 3321 } else { 3322 3323 pSiS->Chipset = PCI_DEV_DEVICE_ID(pSiS->PciInfo); 3324 pScrn->chipset = (char *)xf86TokenToString(myChipsets, pSiS->Chipset); 3325 3326 } 3327 } 3328 3329 if(pSiS->pEnt->device->chipRev >= 0) { 3330 3331 pSiS->ChipRev = pSiS->pEnt->device->chipRev; 3332 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 3333 pSiS->ChipRev); 3334 } else { 3335 3336 pSiS->ChipRev = PCI_DEV_REVISION(pSiS->PciInfo); 3337 3338 } 3339 3340 /* 3341 * This shouldn't happen because such problems should be caught in 3342 * SISProbe(), but check it just in case the user has overridden them. 3343 */ 3344 if(pScrn->chipset == NULL) { 3345 SISErrorLog(pScrn, "ChipID 0x%04X is not recognised\n", pSiS->Chipset); 3346 goto my_error_0; 3347 } 3348 if(pSiS->Chipset < 0) { 3349 SISErrorLog(pScrn, "Chipset \"%s\" is not recognised\n", pScrn->chipset); 3350 goto my_error_0; 3351 } 3352 3353 pSiS->SiS6326Flags = 0; 3354 3355 /* Determine VGA engine generation */ 3356 switch(pSiS->Chipset) { 3357 case PCI_CHIP_SIS300: 3358 case PCI_CHIP_SIS540: 3359 case PCI_CHIP_SIS630: /* 630 + 730 */ 3360 pSiS->VGAEngine = SIS_300_VGA; 3361 break; 3362 case PCI_CHIP_SIS315H: 3363 case PCI_CHIP_SIS315: 3364 case PCI_CHIP_SIS315PRO: 3365 case PCI_CHIP_SIS550: 3366 case PCI_CHIP_SIS650: /* 650 + 740 */ 3367 case PCI_CHIP_SIS330: 3368 case PCI_CHIP_SIS660: /* 660, 661, 741, 760, 761, 670(?), 770 */ 3369 case PCI_CHIP_SIS340: 3370 case PCI_CHIP_XGIXG20: 3371 case PCI_CHIP_XGIXG40: 3372 pSiS->VGAEngine = SIS_315_VGA; 3373 break; 3374 case PCI_CHIP_SIS530: 3375 pSiS->VGAEngine = SIS_530_VGA; 3376 break; 3377 case PCI_CHIP_SIS6326: 3378 /* Determine SiS6326 revision. According to SiS the differences are: 3379 * Chip name Chip type TV-Out MPEG II decoder 3380 * 6326 AGP Rev. G0/H0 no no 3381 * 6326 DVD Rev. D2 yes yes 3382 * 6326 Rev. Cx yes yes 3383 */ 3384 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3385 "Chipset is SiS6326 %s (revision 0x%02x)\n", 3386 (pSiS->ChipRev == 0xaf) ? "(Ax)" : 3387 ((pSiS->ChipRev == 0x0a) ? "AGP (G0)" : 3388 ((pSiS->ChipRev == 0x0b) ? "AGP (H0)" : 3389 (((pSiS->ChipRev & 0xf0) == 0xd0) ? "DVD (Dx/H0)" : 3390 (((pSiS->ChipRev & 0xf0) == 0x90) ? "(9x)" : 3391 (((pSiS->ChipRev & 0xf0) == 0xc0) ? "(Cx)" : 3392 "(unknown)"))))), 3393 pSiS->ChipRev); 3394 if((pSiS->ChipRev != 0x0a) && (pSiS->ChipRev != 0x0b)) { 3395 pSiS->SiS6326Flags |= SIS6326_HASTV; 3396 } 3397 /* fall through */ 3398 default: 3399 pSiS->VGAEngine = SIS_OLD_VGA; 3400 } 3401 3402 /* We don't know about the current mode yet */ 3403 pSiS->OldMode = 0; 3404 3405 /* Determine whether this is the primary or a secondary 3406 * display adapter. And right here the problem starts: 3407 * On machines with integrated SiS chipsets, the system BIOS 3408 * usually sets VGA_EN on all PCI-to-PCI bridges in the system 3409 * (of which there usually are two: PCI and AGP). This and 3410 * the fact that any PCI card POSTed by sisfb naturally has 3411 * its PCI resources enabled, leads to X assuming that 3412 * there are more than one "primary" cards in the system. 3413 * In this case, X treats ALL cards as "secondary" - 3414 * which by no means is desireable. If sisfb is running, 3415 * we can determine which card really is "primary" (in 3416 * terms of if it's the one that occupies the A0000 area 3417 * etc.) in a better way (Linux 2.6.12 or later). See below. 3418 */ 3419 if(!(pSiS->Primary = xf86IsPrimaryPci(pSiS->PciInfo))) { 3420 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3421 SISMYSERVERNAME " assumes this adapter to be secondary\n"); 3422 } 3423 3424 /* Now check if sisfb is running, and if so, retrieve 3425 * all possible info from it. This also resets all 3426 * sisfb_* entries in pSiS regardless of the chipset. 3427 */ 3428 SiS_CheckKernelFB(pScrn); 3429 3430 /* Now for that primary/secondary mess: Linux kernel 3431 * 2.6.12 and later knows what card is primary, and so 3432 * does any recent version of sisfb. XFree86/X.org takes 3433 * all adapters as "secondary" if more than one card's 3434 * memory and i/o resources are enabled, and more than 3435 * one PCI bridge in the system has VGA_EN set at server 3436 * start. So, let's start thinking: What is this 3437 * primary/secondary classification needed for anyway? 3438 * (This list might be incomplete for the entire server 3439 * infrastructure, but it's complete as regards the driver's 3440 * purposes of primary/secondary classification.) 3441 * 1) VGA/console font restoring: Here it's irrelevant 3442 * whether more than one card's resources are enabled 3443 * at server start or not. Relevant is whether the card 3444 * occupies the A0000 area at this time. Assuming (?) 3445 * that this does not change during machine up-time, 3446 * it suffices to know which device was the boot video 3447 * device (as determined by Linux 2.6.12 and later). 3448 * Also, this is only relevant if the card is in text 3449 * mode; if it's in graphics mode, fonts aren't saved 3450 * or restored anyway. 3451 * sisfb tells us if that card is considered the boot 3452 * video device. The hardware registers tell us if 3453 * the card's A0000 address decoding is enabled, and if 3454 * the card currently is in text mode. These three bits 3455 * of information are enough to decide on whether or not 3456 * to save/restore fonts. 3457 * 2) POSTing. Same here. Relevant is only whether or not 3458 * the card has been POSTed once before. POSTing cards 3459 * on every server start is pretty ugly, especially 3460 * if a framebuffer driver is already handling it. 3461 * SiS/XGI cards POSTed by sisfb can coexist well with other 3462 * active adapters. So we trust sisfb's information more 3463 * than X's (especially as we only use this information for 3464 * console font restoring and eventual POSTing.) 3465 * What we still need is a way to find out about all this if 3466 * sisfb is not running.... 3467 */ 3468 if(!pSiS->Primary && pSiS->sisfbprimary) { 3469 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3470 "sisfb reports this adapter to be primary. Seems more reliable.\n"); 3471 pSiS->Primary = TRUE; 3472 } 3473 3474 /* If the card is "secondary" and has not been 3475 * POSTed by sisfb, POST it now through int10. 3476 * For cards POSTed by sisfb, we definitely don't 3477 * want that as it messes up our set up (eg. the 3478 * disabled A0000 area). 3479 * The int10 module decides on its own if the 3480 * card is primary or secondary. Since it uses 3481 * the generic technique described above, and since 3482 * for "secondary" cards it needs a real PCI BIOS 3483 * ROM, and since integrated chips don't have such 3484 * a PCI BIOS ROM, int10 will naturally fail to 3485 * find/read the BIOS on such machines. Great. 3486 * Using the integrated graphics as "secondary" 3487 * (which it will be as soon as X finds more than 3488 * one card's mem and i/o resources enabled, and more 3489 * than one PCI bridge's VGA_EN bit set during server 3490 * start) will therefore prevent us from restoring 3491 * the mode using the VBE. That means real fun if 3492 * the integrated chip is set up to use the video 3493 * bridge output for text mode (which is something 3494 * the driver doesn't really support since it's done 3495 * pretty much differently on every machine.) 3496 */ 3497#if !defined(__alpha__) 3498 if(!pSiS->Primary) { 3499 if(!pSiS->sisfbcardposted) { 3500 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3501 "Initializing adapter through int10\n"); 3502 if(xf86LoadSubModule(pScrn, "int10")) { 3503 pSiS->pInt = xf86InitInt10(pSiS->pEnt->index); 3504 } else { 3505 SISErrorLog(pScrn, "Failed to load int10 module\n"); 3506 } 3507 } else { 3508 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3509 "Adapter already initialized by sisfb\n"); 3510 } 3511 } 3512#endif 3513 3514 /* Get the address of our relocated IO registers. 3515 * These are enabled by the hardware during cold boot, and 3516 * by the BIOS. So we can pretty much rely on that these 3517 * are enabled. 3518 */ 3519 pSiS->RelIO = (SISIOADDRESS)(PCI_REGION_BASE(pSiS->PciInfo, 2, REGION_IO) + pSiS->IODBase); 3520 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Relocated I/O registers at 0x%lX\n", 3521 (ULong)pSiS->RelIO); 3522 3523 /* Unlock extended registers */ 3524 sisSaveUnlockExtRegisterLock(pSiS, &srlockReg, &crlockReg); 3525 3526 /* Is a0000 memory address decoding enabled? */ 3527 pSiS->VGADecodingEnabled = TRUE; 3528 switch(pSiS->VGAEngine) { 3529 case SIS_OLD_VGA: 3530 /* n/a */ 3531 break; 3532 case SIS_530_VGA: 3533 inSISIDXREG(SISSR, 0x3d, tempreg); 3534 if(tempreg & 0x04) pSiS->VGADecodingEnabled = FALSE; 3535 break; 3536 case SIS_300_VGA: 3537 case SIS_315_VGA: 3538 inSISIDXREG(SISSR, 0x20, tempreg); 3539 if(tempreg & 0x04) pSiS->VGADecodingEnabled = FALSE; 3540 break; 3541 } 3542 3543 if(!pSiS->VGADecodingEnabled) { 3544 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3545 "Standard VGA (0xA0000) memory address decoding is disabled\n"); 3546 } 3547 3548#ifdef SIS_PC_PLATFORM 3549 /* Map 64k VGA window for saving/restoring CGA fonts. 3550 * For secondary cards or if A0000 address decoding 3551 * is disabled, this will map the beginning of the 3552 * linear (PCI) video RAM instead. 3553 */ 3554 SiS_MapVGAMem(pScrn); 3555#endif 3556 3557#ifndef XSERVER_LIBPCIACCESS 3558 /* Set operating state */ 3559 3560 /* 1. memory */ 3561 /* [ResUnusedOpr: Resource decoded by hw, but not used] 3562 * [ResDisableOpr: Resource is not decoded by hw] 3563 * So, if a0000 memory decoding is disabled, one could 3564 * argue that we may say so, too. Hm. Quite likely that 3565 * the VBE (via int10) will eventually enable it. So we 3566 * cowardly say unused instead. 3567 */ 3568 xf86SetOperatingState(resVgaMem, pSiS->pEnt->index, ResUnusedOpr); 3569 3570 /* 2. i/o */ 3571 /* Although we only use the relocated i/o ports, the hardware 3572 * also decodes the standard VGA port range. This could in 3573 * theory be disabled, but I don't dare to do this; in case of 3574 * a server crash, the card would be entirely dead. Also, this 3575 * would prevent int10 and the VBE from working at all. Generic 3576 * access control through the PCI configuration registers does 3577 * nicely anyway. 3578 */ 3579 xf86SetOperatingState(resVgaIo, pSiS->pEnt->index, ResUnusedOpr); 3580 3581 /* Operations for which memory access is required */ 3582 pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; 3583 3584 /* Operations for which I/O access is required */ 3585 pScrn->racIoFlags = RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; 3586 3587#endif 3588 3589 /* Load ramdac module */ 3590 if(!xf86LoadSubModule(pScrn, "ramdac")) { 3591 SISErrorLog(pScrn, "Could not load ramdac module\n"); 3592 goto my_error_1; 3593 } 3594 3595 /* Set pScrn->monitor */ 3596 pScrn->monitor = pScrn->confScreen->monitor; 3597 3598 /* Reset some entries */ 3599 pSiS->SiSFastVidCopy = SiSVidCopyGetDefault(); 3600 pSiS->SiSFastMemCopy = SiSVidCopyGetDefault(); 3601 pSiS->SiSFastVidCopyFrom = SiSVidCopyGetDefault(); 3602 pSiS->SiSFastMemCopyFrom = SiSVidCopyGetDefault(); 3603 pSiS->SiSFastVidCopyDone = FALSE; 3604#ifdef SIS_USE_XAA 3605 pSiS->RenderCallback = NULL; 3606#endif 3607#ifdef SIS_USE_EXA 3608 pSiS->ExaRenderCallback = NULL; 3609#endif 3610 pSiS->InitAccel = SiSPseudo; 3611 pSiS->SyncAccel = SiSPseudo; 3612 pSiS->FillRect = NULL; 3613 pSiS->BlitRect = NULL; 3614 3615 /* Always do a ValidMode() inside Switchmode() */ 3616 pSiS->skipswitchcheck = FALSE; 3617 3618 /* Determine chipset and its capabilities in detail */ 3619 pSiS->ChipFlags = 0; 3620 pSiS->SiS_SD_Flags = pSiS->SiS_SD2_Flags = 0; 3621 pSiS->SiS_SD3_Flags = pSiS->SiS_SD4_Flags = 0; 3622 pSiS->HWCursorMBufNum = pSiS->HWCursorCBufNum = 0; 3623 pSiS->NeedFlush = FALSE; 3624 pSiS->NewCRLayout = FALSE; 3625 pSiS->mmioSize = 64; 3626 3627 switch(pSiS->Chipset) { 3628 case PCI_CHIP_SIS530: 3629 pSiS->ChipType = SIS_530; 3630 break; 3631 case PCI_CHIP_SIS300: 3632 pSiS->ChipType = SIS_300; 3633 pSiS->SiS_SD_Flags |= SiS_SD_IS300SERIES; 3634 break; 3635 case PCI_CHIP_SIS540: 3636 pSiS->ChipType = SIS_540; 3637 pSiS->SiS_SD_Flags |= SiS_SD_IS300SERIES; 3638 break; 3639 case PCI_CHIP_SIS630: /* 630 + 730 */ 3640 pSiS->ChipType = SIS_630; 3641 if(sis_pci_read_host_bridge_u32(0x00) == 0x07301039) { 3642 pSiS->ChipType = SIS_730; 3643 } 3644 pSiS->SiS_SD_Flags |= SiS_SD_IS300SERIES; 3645 break; 3646 case PCI_CHIP_SIS315H: 3647 pSiS->ChipType = SIS_315H; 3648 pSiS->ChipFlags |= (SiSCF_315Core | SiSCF_MMIOPalette); 3649 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3650 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3651 pSiS->myCR63 = 0x63; 3652 break; 3653 case PCI_CHIP_SIS315: 3654 /* Override for simplicity */ 3655 pSiS->Chipset = PCI_CHIP_SIS315H; 3656 pSiS->ChipType = SIS_315; 3657 pSiS->ChipFlags |= (SiSCF_315Core | SiSCF_MMIOPalette); 3658 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3659 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3660 pSiS->myCR63 = 0x63; 3661 break; 3662 case PCI_CHIP_SIS315PRO: 3663 /* Override for simplicity */ 3664 pSiS->Chipset = PCI_CHIP_SIS315H; 3665 pSiS->ChipType = SIS_315PRO; 3666 pSiS->ChipFlags |= (SiSCF_315Core | SiSCF_MMIOPalette); 3667 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3668 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3669 pSiS->myCR63 = 0x63; 3670 break; 3671 case PCI_CHIP_SIS550: 3672 pSiS->ChipType = SIS_550; 3673 pSiS->ChipFlags |= (SiSCF_Integrated | SiSCF_MMIOPalette); 3674 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3675 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3676 pSiS->myCR63 = 0x63; 3677 break; 3678 case PCI_CHIP_SIS650: /* 650 + 740 */ 3679 pSiS->ChipType = SIS_650; 3680 if(sis_pci_read_host_bridge_u32(0x00) == 0x07401039) { 3681 pSiS->ChipType = SIS_740; 3682 } 3683 pSiS->ChipFlags |= (SiSCF_Integrated | SiSCF_Real256ECore | SiSCF_MMIOPalette); 3684 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3685 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3686 pSiS->myCR63 = 0x63; 3687 break; 3688 case PCI_CHIP_SIS330: 3689 pSiS->ChipType = SIS_330; 3690 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette); 3691 pSiS->SiS_SD_Flags |= SiS_SD_IS330SERIES; 3692 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3693 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; /* FIXME ? */ 3694 pSiS->myCR63 = 0x53; /* sic! */ 3695 break; 3696 case PCI_CHIP_SIS660: /* 660, 661, 741, 760, 761, 670(?) */ 3697 { 3698 ULong hpciid = sis_pci_read_host_bridge_u32(0x00); 3699 switch(hpciid) { 3700 case 0x06601039: 3701 pSiS->ChipType = SIS_660; 3702 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3703 pSiS->NeedFlush = TRUE; 3704 break; 3705 case 0x07601039: 3706 pSiS->ChipType = SIS_760; 3707 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3708 pSiS->NeedFlush = TRUE; 3709 break; 3710 case 0x07611039: 3711 pSiS->ChipType = SIS_761; 3712 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3713 pSiS->NeedFlush = TRUE; 3714 break; 3715 case 0x07701039: 3716 pSiS->ChipType = SIS_770; 3717 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3718 pSiS->NeedFlush = TRUE; 3719 break; 3720 case 0x07411039: 3721 pSiS->ChipType = SIS_741; 3722 pSiS->ChipFlags |= SiSCF_Real256ECore; 3723 break; 3724 case 0x06611039: 3725 default: 3726 pSiS->ChipType = SIS_661; 3727 pSiS->ChipFlags |= SiSCF_Real256ECore; 3728 break; 3729 case 0x06701039: 3730 pSiS->ChipType = SIS_670; 3731 pSiS->ChipFlags |= SiSCF_Real256ECore; 3732 } 3733 /* Detection could also be done by CR5C & 0xf8: 3734 * 0x10 = 661 (CR5F & 0xc0: 0x00 both A0 and A1) 3735 * 0x80 = 760 (CR5F & 0xc0: 0x00 A0, 0x40 A1) 3736 * 0x90 = 741 (CR5F & 0xc0: 0x00 A0,A1 0x40 A2) 3737 * other: 660 (CR5F & 0xc0: 0x00 A0 0x40 A1) (DOA?) 3738 */ 3739 pSiS->ChipFlags |= (SiSCF_Integrated | SiSCF_MMIOPalette); 3740 pSiS->SiS_SD_Flags |= SiS_SD_IS330SERIES; 3741 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3742 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; 3743 pSiS->myCR63 = 0x53; /* sic! */ 3744 pSiS->NewCRLayout = TRUE; 3745 } 3746 break; 3747 case PCI_CHIP_SIS340: 3748 pSiS->ChipType = SIS_340; 3749 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette); 3750 pSiS->SiS_SD_Flags |= SiS_SD_IS340SERIES; 3751 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3752 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; 3753 pSiS->myCR63 = 0x53; 3754 pSiS->NewCRLayout = TRUE; 3755 break; 3756 case PCI_CHIP_XGIXG20: 3757 pSiS->ChipType = XGI_20; 3758 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette | SiSCF_IsXGI); 3759 pSiS->SiS_SD2_Flags |= (SiS_SD2_NOOVERLAY | SiS_SD2_ISXGI); 3760 pSiS->myCR63 = 0x53; 3761 pSiS->NewCRLayout = TRUE; 3762 break; 3763 case PCI_CHIP_XGIXG40: 3764 pSiS->ChipType = XGI_40; 3765 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette | SiSCF_IsXGI); 3766 pSiS->SiS_SD2_Flags |= (SiS_SD2_SUPPORTXVHUESAT | SiS_SD2_ISXGI); 3767 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; 3768 pSiS->myCR63 = 0x53; 3769 pSiS->NewCRLayout = TRUE; 3770 if(pSiS->ChipRev == 2) pSiS->ChipFlags |= SiSCF_IsXGIV3; 3771 break; 3772 default: 3773 pSiS->ChipType = SIS_OLD; 3774 break; 3775 } 3776 3777 /* 3778 * Now back to real business: Figure out the depth, bpp, etc. 3779 * Set SupportConvert... flags since we use the fb layer which 3780 * supports this conversion. (24to32 seems not implemented though) 3781 * Additionally, determine the size of the HWCursor memory area. 3782 */ 3783 switch(pSiS->VGAEngine) { 3784 case SIS_300_VGA: 3785 pSiS->CursorSize = 4096; 3786 pix24flags = Support32bppFb; 3787 break; 3788 case SIS_315_VGA: 3789 pSiS->CursorSize = 16384; 3790 pix24flags = Support32bppFb; 3791 break; 3792 case SIS_530_VGA: 3793 pSiS->CursorSize = 2048; 3794 pix24flags = Support32bppFb | 3795 Support24bppFb | 3796 SupportConvert32to24; 3797 break; 3798 default: 3799 pSiS->CursorSize = 2048; 3800 pix24flags = Support24bppFb | 3801 SupportConvert32to24 | 3802 PreferConvert32to24; 3803 break; 3804 } 3805 3806#ifdef SISDUALHEAD 3807 /* In case of Dual Head, we need to determine if we are the "master" head or 3808 * the "slave" head. In order to do that, we set PrimInit to DONE in the 3809 * shared entity at the end of the first initialization. The second 3810 * initialization then knows that some things have already been done. THIS 3811 * ALWAYS ASSUMES THAT THE FIRST DEVICE INITIALIZED IS THE MASTER! 3812 */ 3813 if(xf86IsEntityShared(pScrn->entityList[0])) { 3814 if(pSiSEnt->lastInstance > 0) { 3815 if(!xf86IsPrimInitDone(pScrn->entityList[0])) { 3816 /* First Head (always CRT2) */ 3817 pSiS->SecondHead = FALSE; 3818 pSiSEnt->pScrn_1 = pScrn; 3819 pSiSEnt->CRT1ModeNo = pSiSEnt->CRT2ModeNo = -1; 3820 pSiSEnt->CRT2ModeSet = FALSE; 3821 pSiS->DualHeadMode = TRUE; 3822 pSiSEnt->DisableDual = FALSE; 3823 pSiSEnt->BIOS = NULL; 3824 pSiSEnt->ROM661New = FALSE; 3825 pSiSEnt->HaveXGIBIOS = FALSE; 3826 pSiSEnt->SiS_Pr = NULL; 3827 pSiSEnt->RenderAccelArray = NULL; 3828 pSiSEnt->SiSFastVidCopy = pSiSEnt->SiSFastMemCopy = NULL; 3829 pSiSEnt->SiSFastVidCopyFrom = pSiSEnt->SiSFastMemCopyFrom = NULL; 3830 } else { 3831 /* Second Head (always CRT1) */ 3832 pSiS->SecondHead = TRUE; 3833 pSiSEnt->pScrn_2 = pScrn; 3834 pSiS->DualHeadMode = TRUE; 3835 } 3836 } else { 3837 /* Only one screen in config file - disable dual head mode */ 3838 pSiS->SecondHead = FALSE; 3839 pSiS->DualHeadMode = FALSE; 3840 pSiSEnt->DisableDual = TRUE; 3841 } 3842 } else { 3843 /* Entity is not shared - disable dual head mode */ 3844 pSiS->SecondHead = FALSE; 3845 pSiS->DualHeadMode = FALSE; 3846 } 3847#endif 3848 3849 /* Save the name of our Device section for SiSCtrl usage */ 3850 { 3851 int ttt = 0; 3852 GDevPtr device = xf86GetDevFromEntity(pScrn->entityList[0], 3853 pScrn->entityInstanceList[0]); 3854 if(device && device->identifier) { 3855 if((ttt = strlen(device->identifier)) > 31) ttt = 31; 3856 strncpy(&pSiS->devsectname[0], device->identifier, 31); 3857 } 3858 pSiS->devsectname[ttt] = 0; 3859 } 3860 3861 pSiS->ForceCursorOff = FALSE; 3862 3863 /* Allocate SiS_Private (for mode switching code) and initialize it */ 3864 pSiS->SiS_Pr = NULL; 3865#ifdef SISDUALHEAD 3866 if(pSiSEnt) { 3867 if(pSiSEnt->SiS_Pr) pSiS->SiS_Pr = pSiSEnt->SiS_Pr; 3868 } 3869#endif 3870 if(!pSiS->SiS_Pr) { 3871 if(!(pSiS->SiS_Pr = xnfcalloc(sizeof(struct SiS_Private), 1))) { 3872 SISErrorLog(pScrn, "Could not allocate memory for SiS_Pr structure\n"); 3873 goto my_error_1; 3874 } 3875#ifdef SISDUALHEAD 3876 if(pSiSEnt) pSiSEnt->SiS_Pr = pSiS->SiS_Pr; 3877#endif 3878 memset(pSiS->SiS_Pr, 0, sizeof(struct SiS_Private)); 3879 pSiS->SiS_Pr->PciTag = pSiS->PciTag; 3880 pSiS->SiS_Pr->ChipType = pSiS->ChipType; 3881 pSiS->SiS_Pr->ChipRevision = pSiS->ChipRev; 3882 pSiS->SiS_Pr->SiS_Backup70xx = 0xff; 3883 pSiS->SiS_Pr->SiS_CHOverScan = -1; 3884 pSiS->SiS_Pr->SiS_ChSW = FALSE; 3885 pSiS->SiS_Pr->SiS_CustomT = CUT_NONE; 3886 pSiS->SiS_Pr->SiS_UseWide = -1; 3887 pSiS->SiS_Pr->SiS_UseWideCRT2 = -1; 3888 pSiS->SiS_Pr->SiS_TVBlue = -1; 3889 pSiS->SiS_Pr->PanelSelfDetected = FALSE; 3890 pSiS->SiS_Pr->UsePanelScaler = -1; 3891 pSiS->SiS_Pr->CenterScreen = -1; 3892 pSiS->SiS_Pr->CRT1UsesCustomMode = FALSE; 3893 pSiS->SiS_Pr->PDC = pSiS->SiS_Pr->PDCA = -1; 3894 pSiS->SiS_Pr->LVDSHL = -1; 3895 pSiS->SiS_Pr->HaveEMI = FALSE; 3896 pSiS->SiS_Pr->HaveEMILCD = FALSE; 3897 pSiS->SiS_Pr->OverruleEMI = FALSE; 3898 pSiS->SiS_Pr->SiS_SensibleSR11 = FALSE; 3899 if(pSiS->ChipType >= SIS_661) { 3900 pSiS->SiS_Pr->SiS_SensibleSR11 = TRUE; 3901 } 3902 pSiS->SiS_Pr->SiS_MyCR63 = pSiS->myCR63; 3903 pSiS->SiS_Pr->DDCPortMixup = FALSE; 3904 } 3905 3906 /* Copy IO address to SiS_Pr and init the structure for 3907 * routines inside init.c/init301.c 3908 */ 3909 pSiS->SiS_Pr->IOAddress = (SISIOADDRESS)(pSiS->RelIO + 0x30); 3910 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO + 0x30); 3911 3912 /* The following identifies the old chipsets. This is only 3913 * partly used since the really old chips are not supported, 3914 * but I keep it here for future use. 3915 * 205, 215 and 225 are to be treated the same way, 201 and 202 3916 * are different. 3917 */ 3918 if(pSiS->VGAEngine == SIS_OLD_VGA || pSiS->VGAEngine == SIS_530_VGA) { 3919 switch(pSiS->Chipset) { 3920 case PCI_CHIP_SG86C201: 3921 pSiS->oldChipset = OC_SIS86201; break; 3922 case PCI_CHIP_SG86C202: 3923 pSiS->oldChipset = OC_SIS86202; break; 3924 case PCI_CHIP_SG86C205: 3925 inSISIDXREG(SISSR, 0x10, tempreg); 3926 if(tempreg & 0x80) pSiS->oldChipset = OC_SIS6205B; 3927 else pSiS->oldChipset = (pSiS->ChipRev == 0x11) ? 3928 OC_SIS6205C : OC_SIS6205A; 3929 break; 3930 case PCI_CHIP_SIS82C204: 3931 pSiS->oldChipset = OC_SIS82204; break; 3932 case 0x6225: 3933 pSiS->oldChipset = OC_SIS6225; break; 3934 case PCI_CHIP_SIS5597: 3935 pSiS->oldChipset = OC_SIS5597; break; 3936 case PCI_CHIP_SIS6326: 3937 pSiS->oldChipset = OC_SIS6326; break; 3938 case PCI_CHIP_SIS530: 3939 if(sis_pci_read_host_bridge_u32(0x00) == 0x06201039) { 3940 pSiS->oldChipset = OC_SIS620; 3941 } else { 3942 if((pSiS->ChipRev & 0x0f) < 0x0a) 3943 pSiS->oldChipset = OC_SIS530A; 3944 else pSiS->oldChipset = OC_SIS530B; 3945 } 3946 break; 3947 default: 3948 pSiS->oldChipset = OC_UNKNOWN; 3949 } 3950 } 3951 3952 if(!xf86SetDepthBpp(pScrn, 0, 0, 0, pix24flags)) { 3953 SISErrorLog(pScrn, "xf86SetDepthBpp() error\n"); 3954 goto my_error_1; 3955 } 3956 3957 /* Check that the returned depth is one we support */ 3958 temp = 0; 3959 switch(pScrn->depth) { 3960 case 8: 3961 case 16: 3962 case 24: 3963 break; 3964 case 15: 3965 if((pSiS->VGAEngine == SIS_300_VGA) || 3966 (pSiS->VGAEngine == SIS_315_VGA)) { 3967 temp = 1; 3968 } 3969 break; 3970 default: 3971 temp = 1; 3972 } 3973 3974 if(temp) { 3975 SISErrorLog(pScrn, 3976 "Given color depth (%d) is not supported by this driver/chipset\n", 3977 pScrn->depth); 3978 goto my_error_1; 3979 } 3980 3981 xf86PrintDepthBpp(pScrn); 3982 3983 if( (((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) && 3984 (pScrn->bitsPerPixel == 24)) || 3985 ((pSiS->VGAEngine == SIS_OLD_VGA) && (pScrn->bitsPerPixel == 32)) ) { 3986 SISErrorLog(pScrn, 3987 "Framebuffer bpp %d not supported for this chipset\n", pScrn->bitsPerPixel); 3988 goto my_error_1; 3989 } 3990 3991 /* Get the depth24 pixmap format */ 3992 if(pScrn->depth == 24 && pix24bpp == 0) { 3993 pix24bpp = xf86GetBppFromDepth(pScrn, 24); 3994 } 3995 3996 /* 3997 * This must happen after pScrn->display has been set because 3998 * xf86SetWeight references it. 3999 */ 4000 if(pScrn->depth > 8) { 4001 /* The defaults are OK for us */ 4002 rgb zeros = {0, 0, 0}; 4003 4004 if(!xf86SetWeight(pScrn, zeros, zeros)) { 4005 SISErrorLog(pScrn, "xf86SetWeight() error\n"); 4006 goto my_error_1; 4007 } else { 4008 Bool ret = FALSE; 4009 switch(pScrn->depth) { 4010 case 15: 4011 if((pScrn->weight.red != 5) || 4012 (pScrn->weight.green != 5) || 4013 (pScrn->weight.blue != 5)) ret = TRUE; 4014 break; 4015 case 16: 4016 if((pScrn->weight.red != 5) || 4017 (pScrn->weight.green != 6) || 4018 (pScrn->weight.blue != 5)) ret = TRUE; 4019 break; 4020 case 24: 4021 if((pScrn->weight.red != 8) || 4022 (pScrn->weight.green != 8) || 4023 (pScrn->weight.blue != 8)) ret = TRUE; 4024 break; 4025 } 4026 if(ret) { 4027 SISErrorLog(pScrn, 4028 "RGB weight %d%d%d at depth %d not supported by hardware\n", 4029 (int)pScrn->weight.red, (int)pScrn->weight.green, 4030 (int)pScrn->weight.blue, pScrn->depth); 4031 goto my_error_1; 4032 } 4033 } 4034 } 4035 4036 /* Set the current layout parameters */ 4037 pSiS->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel; 4038 pSiS->CurrentLayout.depth = pScrn->depth; 4039 /* (Inside this function, we can use pScrn's contents anyway) */ 4040 4041 if(!xf86SetDefaultVisual(pScrn, -1)) { 4042 SISErrorLog(pScrn, "xf86SetDefaultVisual() error\n"); 4043 goto my_error_1; 4044 } else { 4045 /* We don't support DirectColor at > 8bpp */ 4046 if(pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { 4047 SISErrorLog(pScrn, 4048 "Given default visual (%s) is not supported at depth %d\n", 4049 xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); 4050 goto my_error_1; 4051 } 4052 } 4053 4054#ifdef SISDUALHEAD 4055 /* Due to palette & timing problems we don't support 8bpp in DHM */ 4056 if((pSiS->DualHeadMode) && (pScrn->bitsPerPixel <= 8)) { 4057 SISErrorLog(pScrn, "Color depth %d not supported in Dual Head mode.\n", 4058 pScrn->bitsPerPixel); 4059 goto my_error_1; 4060 } 4061#endif 4062 4063 /* Read BIOS for 300/315/330/340 series customization */ 4064 pSiS->SiS_Pr->VirtualRomBase = NULL; 4065 pSiS->BIOS = NULL; 4066 pSiS->SiS_Pr->UseROM = FALSE; 4067 pSiS->ROM661New = FALSE; 4068 pSiS->HaveXGIBIOS = FALSE; 4069 4070 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 4071#ifdef SISDUALHEAD 4072 if(pSiSEnt) { 4073 if(pSiSEnt->BIOS) { 4074 pSiS->BIOS = pSiSEnt->BIOS; 4075 pSiS->SiS_Pr->VirtualRomBase = pSiS->BIOS; 4076 pSiS->ROM661New = pSiSEnt->ROM661New; 4077 pSiS->HaveXGIBIOS = pSiSEnt->HaveXGIBIOS; 4078 } 4079 } 4080#endif 4081 if(!pSiS->BIOS) { 4082 if(!(pSiS->BIOS = xcalloc(1, BIOS_SIZE))) { 4083 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4084 "Could not allocate memory for video BIOS image\n"); 4085 } else { 4086 UShort mypciid = pSiS->Chipset; 4087 UShort mypcivendor = (pSiS->ChipFlags & SiSCF_IsXGI) ? PCI_VENDOR_XGI : PCI_VENDOR_SIS; 4088 Bool found = FALSE, readpci = FALSE; 4089 int biossize = BIOS_SIZE; 4090 4091 switch(pSiS->ChipType) { 4092 case SIS_315: mypciid = PCI_CHIP_SIS315; 4093 readpci = TRUE; 4094 break; 4095 case SIS_315PRO: mypciid = PCI_CHIP_SIS315PRO; 4096 readpci = TRUE; 4097 break; 4098 case SIS_300: 4099 case SIS_315H: 4100 case SIS_330: 4101 case SIS_340: 4102 case SIS_650: 4103 case SIS_760: 4104 case XGI_40: readpci = TRUE; 4105 break; 4106 case XGI_20: readpci = TRUE; 4107 biossize = 0x8000; 4108 break; 4109 } 4110#if XSERVER_LIBPCIACCESS 4111 if(readpci) { 4112 pSiS->PciInfo->rom_size = biossize; 4113 pci_device_read_rom(pSiS->PciInfo, pSiS->BIOS); 4114 if(SISCheckBIOS(pSiS, mypciid, mypcivendor, biossize)) { 4115 found = TRUE; 4116 } 4117 } 4118#else 4119 if(readpci) { 4120 xf86ReadPciBIOS(0, pSiS->PciTag, 0, pSiS->BIOS, biossize); 4121 if(SISCheckBIOS(pSiS, mypciid, mypcivendor, biossize)) { 4122 found = TRUE; 4123 } 4124 } 4125 4126 if(!found) { 4127 ULong segstart; 4128 for(segstart = BIOS_BASE; segstart < 0x000f0000; segstart += 0x00001000) { 4129 4130#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 4131 if(xf86ReadBIOS(segstart, 0, pSiS->BIOS, biossize) != biossize) continue; 4132#else 4133 if(xf86ReadDomainMemory(pSiS->PciTag, segstart, biossize, pSiS->BIOS) != biossize) continue; 4134#endif 4135 4136 if(!SISCheckBIOS(pSiS, mypciid, mypcivendor, biossize)) continue; 4137 4138 found = TRUE; 4139 break; 4140 } 4141 } 4142#endif 4143 if(found) { 4144 UShort romptr = pSiS->BIOS[0x16] | (pSiS->BIOS[0x17] << 8); 4145 pSiS->SiS_Pr->VirtualRomBase = pSiS->BIOS; 4146 if(pSiS->ChipFlags & SiSCF_IsXGI) { 4147 pSiS->HaveXGIBIOS = pSiS->SiS_Pr->SiS_XGIROM = TRUE; 4148 pSiS->SiS_Pr->UseROM = FALSE; 4149 if(pSiS->ChipFlags & SiSCF_IsXGIV3) { 4150 if(!(pSiS->BIOS[0x1d1] & 0x01)) { 4151 pSiS->SiS_Pr->DDCPortMixup = TRUE; 4152 } 4153 } 4154 } else { 4155 pSiS->ROM661New = SiSDetermineROMLayout661(pSiS->SiS_Pr); 4156 } 4157 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4158 "Video BIOS version \"%7s\" found (%s data layout)\n", 4159 &pSiS->BIOS[romptr], pSiS->ROM661New ? "new SiS" : 4160 (pSiS->HaveXGIBIOS ? "XGI" : "old SiS")); 4161 if(pSiS->SiS_Pr->DDCPortMixup) { 4162 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4163 "*** Buggy XGI V3XT card detected: If VGA and DVI are connected at the\n"); 4164 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4165 "*** same time, BIOS and driver will be unable to detect DVI connection.\n"); 4166 } 4167#ifdef SISDUALHEAD 4168 if(pSiSEnt) { 4169 pSiSEnt->BIOS = pSiS->BIOS; 4170 pSiSEnt->ROM661New = pSiS->ROM661New; 4171 pSiSEnt->HaveXGIBIOS = pSiS->HaveXGIBIOS; 4172 } 4173#endif 4174 } else { 4175 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4176 "Could not find/read video BIOS\n"); 4177 xfree(pSiS->BIOS); 4178 pSiS->BIOS = NULL; 4179 } 4180 } 4181 } 4182 4183 if(!(pSiS->ChipFlags & SiSCF_IsXGI)) { 4184 if(pSiS->BIOS) pSiS->SiS_Pr->UseROM = TRUE; 4185 else pSiS->SiS_Pr->UseROM = FALSE; 4186 } 4187 } 4188 4189 /* Evaluate options */ 4190 SiSOptions(pScrn); 4191 4192#ifdef SISMERGED 4193 /* Due to palette & timing problems we don't support 8bpp in MFBM */ 4194 if((pSiS->MergedFB) && (pScrn->bitsPerPixel <= 8)) { 4195 SISErrorLog(pScrn, "MergedFB: Color depth %d not supported, %s\n", 4196 pScrn->bitsPerPixel, mergeddisstr); 4197 pSiS->MergedFB = pSiS->MergedFBAuto = FALSE; 4198 } 4199#endif 4200 4201 /* Probe CPU features */ 4202#ifdef SISDUALHEAD 4203 if(pSiS->DualHeadMode) { 4204 pSiS->CPUFlags = pSiSEnt->CPUFlags; 4205 } 4206#endif 4207 if(!pSiS->CPUFlags) { 4208 pSiS->CPUFlags = SiSGetCPUFlags(pScrn); 4209 pSiS->CPUFlags |= SIS_CPUFL_FLAG; 4210#ifdef SISDUALHEAD 4211 if(pSiS->DualHeadMode) pSiSEnt->CPUFlags = pSiS->CPUFlags; 4212#endif 4213 } 4214 4215 /* We use a programamble clock */ 4216 pScrn->progClock = TRUE; 4217 4218 /* Set the bits per RGB for 8bpp mode */ 4219 if(pScrn->depth == 8) pScrn->rgbBits = 8; 4220 4221#ifdef SISDUALHEAD 4222 if(pSiS->DualHeadMode) { 4223 if(!pSiS->SecondHead) { 4224 /* Copy some option settings to entity private */ 4225 pSiSEnt->HWCursor = pSiS->HWCursor; 4226 pSiSEnt->NoAccel = pSiS->NoAccel; 4227 pSiSEnt->useEXA = pSiS->useEXA; 4228 pSiSEnt->restorebyset = pSiS->restorebyset; 4229 pSiSEnt->OptROMUsage = pSiS->OptROMUsage; 4230 pSiSEnt->OptUseOEM = pSiS->OptUseOEM; 4231 pSiSEnt->TurboQueue = pSiS->TurboQueue; 4232 pSiSEnt->forceCRT1 = pSiS->forceCRT1; 4233 pSiSEnt->ForceCRT1Type = pSiS->ForceCRT1Type; 4234 pSiSEnt->CRT1TypeForced = pSiS->CRT1TypeForced; 4235 pSiSEnt->ForceCRT2Type = pSiS->ForceCRT2Type; 4236 pSiSEnt->ForceTVType = pSiS->ForceTVType; 4237 pSiSEnt->ForceYPbPrType = pSiS->ForceYPbPrType; 4238 pSiSEnt->ForceYPbPrAR = pSiS->ForceYPbPrAR; 4239 pSiSEnt->UsePanelScaler = pSiS->UsePanelScaler; 4240 pSiSEnt->CenterLCD = pSiS->CenterLCD; 4241 pSiSEnt->DSTN = pSiS->DSTN; 4242 pSiSEnt->FSTN = pSiS->FSTN; 4243 pSiSEnt->OptTVStand = pSiS->OptTVStand; 4244 pSiSEnt->NonDefaultPAL = pSiS->NonDefaultPAL; 4245 pSiSEnt->NonDefaultNTSC = pSiS->NonDefaultNTSC; 4246 pSiSEnt->chtvtype = pSiS->chtvtype; 4247 pSiSEnt->OptTVOver = pSiS->OptTVOver; 4248 pSiSEnt->OptTVSOver = pSiS->OptTVSOver; 4249 pSiSEnt->chtvlumabandwidthcvbs = pSiS->chtvlumabandwidthcvbs; 4250 pSiSEnt->chtvlumabandwidthsvideo = pSiS->chtvlumabandwidthsvideo; 4251 pSiSEnt->chtvlumaflickerfilter = pSiS->chtvlumaflickerfilter; 4252 pSiSEnt->chtvchromabandwidth = pSiS->chtvchromabandwidth; 4253 pSiSEnt->chtvchromaflickerfilter = pSiS->chtvchromaflickerfilter; 4254 pSiSEnt->chtvtextenhance = pSiS->chtvtextenhance; 4255 pSiSEnt->chtvcontrast = pSiS->chtvcontrast; 4256 pSiSEnt->chtvcvbscolor = pSiS->chtvcvbscolor; 4257 pSiSEnt->sistvedgeenhance = pSiS->sistvedgeenhance; 4258 pSiSEnt->sistvantiflicker = pSiS->sistvantiflicker; 4259 pSiSEnt->sistvsaturation = pSiS->sistvsaturation; 4260 pSiSEnt->sistvcfilter = pSiS->sistvcfilter; 4261 pSiSEnt->sistvyfilter = pSiS->sistvyfilter; 4262 pSiSEnt->sistvcolcalibc = pSiS->sistvcolcalibc; 4263 pSiSEnt->sistvcolcalibf = pSiS->sistvcolcalibf; 4264 pSiSEnt->tvxpos = pSiS->tvxpos; 4265 pSiSEnt->tvypos = pSiS->tvypos; 4266 pSiSEnt->tvxscale = pSiS->tvxscale; 4267 pSiSEnt->tvyscale = pSiS->tvyscale; 4268 pSiSEnt->siscrt1satgain = pSiS->siscrt1satgain; 4269 pSiSEnt->crt1satgaingiven = pSiS->crt1satgaingiven; 4270 pSiSEnt->CRT1gamma = pSiS->CRT1gamma; 4271 pSiSEnt->CRT1gammaGiven = pSiS->CRT1gammaGiven; 4272 pSiSEnt->XvGammaRed = pSiS->XvGammaRed; 4273 pSiSEnt->XvGammaGreen = pSiS->XvGammaGreen; 4274 pSiSEnt->XvGammaBlue = pSiS->XvGammaBlue; 4275 pSiSEnt->XvGamma = pSiS->XvGamma; 4276 pSiSEnt->XvGammaGiven = pSiS->XvGammaGiven; 4277 pSiSEnt->CRT2gamma = pSiS->CRT2gamma; 4278 pSiSEnt->XvOnCRT2 = pSiS->XvOnCRT2; 4279 pSiSEnt->AllowHotkey = pSiS->AllowHotkey; 4280 pSiSEnt->enablesisctrl = pSiS->enablesisctrl; 4281 pSiSEnt->SenseYPbPr = pSiS->SenseYPbPr; 4282 pSiSEnt->XvUseMemcpy = pSiS->XvUseMemcpy; 4283 pSiSEnt->BenchMemCpy = pSiS->BenchMemCpy; 4284#ifdef SIS_CP 4285 SIS_CP_DRIVER_COPYOPTIONSENT 4286#endif 4287 } else { 4288 /* We always use same cursor type on both screens */ 4289 pSiS->HWCursor = pSiSEnt->HWCursor; 4290 /* We need identical NoAccel setting */ 4291 pSiS->NoAccel = pSiSEnt->NoAccel; 4292 pSiS->useEXA = pSiSEnt->useEXA; 4293 pSiS->TurboQueue = pSiSEnt->TurboQueue; 4294 pSiS->restorebyset = pSiSEnt->restorebyset; 4295 pSiS->AllowHotkey = pSiS->AllowHotkey; 4296 pSiS->OptROMUsage = pSiSEnt->OptROMUsage; 4297 pSiS->OptUseOEM = pSiSEnt->OptUseOEM; 4298 pSiS->forceCRT1 = pSiSEnt->forceCRT1; 4299 pSiS->nocrt2ddcdetection = FALSE; 4300 pSiS->forcecrt2redetection = FALSE; 4301 pSiS->ForceCRT1Type = pSiSEnt->ForceCRT1Type; 4302 pSiS->ForceCRT2Type = pSiSEnt->ForceCRT2Type; 4303 pSiS->CRT1TypeForced = pSiSEnt->CRT1TypeForced; 4304 pSiS->UsePanelScaler = pSiSEnt->UsePanelScaler; 4305 pSiS->CenterLCD = pSiSEnt->CenterLCD; 4306 pSiS->DSTN = pSiSEnt->DSTN; 4307 pSiS->FSTN = pSiSEnt->FSTN; 4308 pSiS->OptTVStand = pSiSEnt->OptTVStand; 4309 pSiS->NonDefaultPAL = pSiSEnt->NonDefaultPAL; 4310 pSiS->NonDefaultNTSC = pSiSEnt->NonDefaultNTSC; 4311 pSiS->chtvtype = pSiSEnt->chtvtype; 4312 pSiS->ForceTVType = pSiSEnt->ForceTVType; 4313 pSiS->ForceYPbPrType = pSiSEnt->ForceYPbPrType; 4314 pSiS->ForceYPbPrAR = pSiSEnt->ForceYPbPrAR; 4315 pSiS->OptTVOver = pSiSEnt->OptTVOver; 4316 pSiS->OptTVSOver = pSiSEnt->OptTVSOver; 4317 pSiS->chtvlumabandwidthcvbs = pSiSEnt->chtvlumabandwidthcvbs; 4318 pSiS->chtvlumabandwidthsvideo = pSiSEnt->chtvlumabandwidthsvideo; 4319 pSiS->chtvlumaflickerfilter = pSiSEnt->chtvlumaflickerfilter; 4320 pSiS->chtvchromabandwidth = pSiSEnt->chtvchromabandwidth; 4321 pSiS->chtvchromaflickerfilter = pSiSEnt->chtvchromaflickerfilter; 4322 pSiS->chtvcvbscolor = pSiSEnt->chtvcvbscolor; 4323 pSiS->chtvtextenhance = pSiSEnt->chtvtextenhance; 4324 pSiS->chtvcontrast = pSiSEnt->chtvcontrast; 4325 pSiS->sistvedgeenhance = pSiSEnt->sistvedgeenhance; 4326 pSiS->sistvantiflicker = pSiSEnt->sistvantiflicker; 4327 pSiS->sistvsaturation = pSiSEnt->sistvsaturation; 4328 pSiS->sistvcfilter = pSiSEnt->sistvcfilter; 4329 pSiS->sistvyfilter = pSiSEnt->sistvyfilter; 4330 pSiS->sistvcolcalibc = pSiSEnt->sistvcolcalibc; 4331 pSiS->sistvcolcalibf = pSiSEnt->sistvcolcalibf; 4332 pSiS->tvxpos = pSiSEnt->tvxpos; 4333 pSiS->tvypos = pSiSEnt->tvypos; 4334 pSiS->tvxscale = pSiSEnt->tvxscale; 4335 pSiS->tvyscale = pSiSEnt->tvyscale; 4336 pSiS->SenseYPbPr = pSiSEnt->SenseYPbPr; 4337 if(!pSiS->CRT1gammaGiven) { 4338 if(pSiSEnt->CRT1gammaGiven) 4339 pSiS->CRT1gamma = pSiSEnt->CRT1gamma; 4340 } 4341 pSiS->CRT2gamma = pSiSEnt->CRT2gamma; 4342 if(!pSiS->XvGammaGiven) { 4343 if(pSiSEnt->XvGammaGiven) { 4344 pSiS->XvGamma = pSiSEnt->XvGamma; 4345 pSiS->XvGammaRed = pSiS->XvGammaRedDef = pSiSEnt->XvGammaRed; 4346 pSiS->XvGammaGreen = pSiS->XvGammaGreenDef = pSiSEnt->XvGammaGreen; 4347 pSiS->XvGammaBlue = pSiS->XvGammaBlueDef = pSiSEnt->XvGammaBlue; 4348 } 4349 } 4350 if(!pSiS->crt1satgaingiven) { 4351 if(pSiSEnt->crt1satgaingiven) 4352 pSiS->siscrt1satgain = pSiSEnt->siscrt1satgain; 4353 } 4354 pSiS->XvOnCRT2 = pSiSEnt->XvOnCRT2; 4355 pSiS->enablesisctrl = pSiSEnt->enablesisctrl; 4356 pSiS->XvUseMemcpy = pSiSEnt->XvUseMemcpy; 4357 pSiS->BenchMemCpy = pSiSEnt->BenchMemCpy; 4358 /* Copy gamma brightness to Ent (sic!) for Xinerama */ 4359 pSiSEnt->GammaBriR = pSiS->GammaBriR; 4360 pSiSEnt->GammaBriG = pSiS->GammaBriG; 4361 pSiSEnt->GammaBriB = pSiS->GammaBriB; 4362 pSiSEnt->NewGammaBriR = pSiS->NewGammaBriR; 4363 pSiSEnt->NewGammaBriG = pSiS->NewGammaBriG; 4364 pSiSEnt->NewGammaBriB = pSiS->NewGammaBriB; 4365 pSiSEnt->NewGammaConR = pSiS->NewGammaConR; 4366 pSiSEnt->NewGammaConG = pSiS->NewGammaConG; 4367 pSiSEnt->NewGammaConB = pSiS->NewGammaConB; 4368#ifdef SIS_CP 4369 SIS_CP_DRIVER_COPYOPTIONS 4370#endif 4371 } 4372 } 4373#endif 4374 4375 /* Handle UseROMData, NoOEM and UsePanelScaler options */ 4376 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 4377 from = X_PROBED; 4378 if(pSiS->OptROMUsage == 0) { 4379 pSiS->SiS_Pr->UseROM = FALSE; 4380 from = X_CONFIG; 4381 xf86DrvMsg(pScrn->scrnIndex, from, "Video ROM data usage is disabled\n"); 4382 } 4383 4384 if(!pSiS->OptUseOEM) { 4385 xf86DrvMsg(pScrn->scrnIndex, from, "Internal OEM LCD/TV/VGA2 data usage is disabled\n"); 4386 } 4387 4388 pSiS->SiS_Pr->UsePanelScaler = pSiS->UsePanelScaler; 4389 pSiS->SiS_Pr->CenterScreen = pSiS->CenterLCD; 4390 } 4391 4392 /* Do some HW configuration detection (memory amount & type, clock, etc) */ 4393 SiSSetup(pScrn); 4394 4395 /* Get framebuffer address */ 4396 if(pSiS->pEnt->device->MemBase != 0) { 4397 /* 4398 * XXX Should check that the config file value matches one of the 4399 * PCI base address values. 4400 */ 4401 pSiS->FbAddress = pSiS->pEnt->device->MemBase; 4402 from = X_CONFIG; 4403 } else { 4404 pSiS->FbAddress = PCI_REGION_BASE(pSiS->PciInfo, 0, REGION_MEM) & 0xFFFFFFF0; 4405 from = X_PROBED; 4406 } 4407 4408#ifdef SISDUALHEAD 4409 if(pSiS->DualHeadMode) 4410 xf86DrvMsg(pScrn->scrnIndex, from, "Global linear framebuffer at 0x%lX\n", 4411 (ULong)pSiS->FbAddress); 4412 else 4413#endif 4414 xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", 4415 (ULong)pSiS->FbAddress); 4416 4417 pSiS->realFbAddress = pSiS->FbAddress; 4418 4419 /* Get MMIO address */ 4420 if(pSiS->pEnt->device->IOBase != 0) { 4421 /* 4422 * XXX Should check that the config file value matches one of the 4423 * PCI base address values. 4424 */ 4425 pSiS->IOAddress = pSiS->pEnt->device->IOBase; 4426 from = X_CONFIG; 4427 } else { 4428 pSiS->IOAddress = PCI_REGION_BASE(pSiS->PciInfo, 1, REGION_MEM) & 0xFFFFFFF0; 4429 from = X_PROBED; 4430 } 4431 xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX (size %ldK)\n", 4432 (ULong)pSiS->IOAddress, pSiS->mmioSize); 4433 4434#ifndef XSERVER_LIBPCIACCESS 4435 /* Register the PCI-assigned resources */ 4436 if(xf86RegisterResources(pSiS->pEnt->index, NULL, ResExclusive)) { 4437 SISErrorLog(pScrn, "PCI resource conflicts detected\n"); 4438#ifdef SISDUALHEAD 4439 if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; 4440#endif 4441 sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); 4442 if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); 4443 SISFreeRec(pScrn); 4444 return FALSE; 4445 } 4446#endif 4447 4448 from = X_PROBED; 4449 if(pSiS->pEnt->device->videoRam != 0) { 4450 if(pSiS->Chipset == PCI_CHIP_SIS6326) { 4451 pScrn->videoRam = pSiS->pEnt->device->videoRam; 4452 from = X_CONFIG; 4453 } else { 4454 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4455 "Option \"VideoRAM\" ignored\n"); 4456 } 4457 } 4458 4459 pSiS->RealVideoRam = pScrn->videoRam; 4460 4461 if((pSiS->Chipset == PCI_CHIP_SIS6326) && 4462 (pScrn->videoRam > 4096) && 4463 (from != X_CONFIG)) { 4464 pScrn->videoRam = 4096; 4465 xf86DrvMsg(pScrn->scrnIndex, from, 4466 "SiS6326: Detected %d KB VideoRAM, limiting to %d KB\n", 4467 pSiS->RealVideoRam, pScrn->videoRam); 4468 } else { 4469 xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d KB\n", pScrn->videoRam); 4470 } 4471 4472 if((pSiS->Chipset == PCI_CHIP_SIS6326) && 4473 (pScrn->videoRam > 4096)) { 4474 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4475 "SiS6326 engines do not support more than 4096KB RAM, therefore\n"); 4476 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4477 "TurboQueue, HWCursor, 2D acceleration and XVideo are disabled.\n"); 4478 pSiS->TurboQueue = FALSE; 4479 pSiS->HWCursor = FALSE; 4480 pSiS->NoXvideo = TRUE; 4481 pSiS->NoAccel = TRUE; 4482 } 4483 4484 pSiS->FbMapSize = pSiS->availMem = pScrn->videoRam * 1024; 4485 4486 /* Calculate real availMem according to Accel/TurboQueue and 4487 * HWCursur setting. Also, initialize some variables used 4488 * in other modules. 4489 */ 4490 pSiS->cursorOffset = 0; 4491 pSiS->CurARGBDest = NULL; 4492 pSiS->CurMonoSrc = NULL; 4493 pSiS->CurFGCol = pSiS->CurBGCol = 0; 4494 pSiS->FbBaseOffset = 0; 4495 4496 switch(pSiS->VGAEngine) { 4497 4498 case SIS_300_VGA: 4499 pSiS->TurboQueueLen = 512; 4500 if(pSiS->TurboQueue) { 4501 pSiS->availMem -= (pSiS->TurboQueueLen*1024); 4502 pSiS->cursorOffset = 512; 4503 } 4504 if(pSiS->HWCursor) { 4505 pSiS->availMem -= pSiS->CursorSize; 4506 if(pSiS->OptUseColorCursor) pSiS->availMem -= pSiS->CursorSize; 4507 } 4508 pSiS->CmdQueLenMask = 0xFFFF; 4509 pSiS->CmdQueLenFix = 0; 4510 pSiS->cursorBufferNum = 0; 4511#ifdef SISDUALHEAD 4512 if(pSiSEnt) pSiSEnt->cursorBufferNum = 0; 4513#endif 4514 break; 4515 4516 case SIS_315_VGA: 4517#ifdef SISVRAMQ /* VRAM queue */ 4518 pSiS->cmdQueueSizeMask = pSiS->cmdQueueSize - 1; /* VRAM Command Queue is variable (in therory) */ 4519 pSiS->cmdQueueOffset = (pScrn->videoRam * 1024) - pSiS->cmdQueueSize; 4520 pSiS->cmdQueueLen = 0; 4521 pSiS->cmdQueueSize_div2 = pSiS->cmdQueueSize / 2; 4522 pSiS->cmdQueueSize_div4 = pSiS->cmdQueueSize / 4; 4523 pSiS->cmdQueueSize_4_3 = (pSiS->cmdQueueSize / 4) * 3; 4524 pSiS->availMem -= pSiS->cmdQueueSize; 4525 pSiS->cursorOffset = (pSiS->cmdQueueSize / 1024); 4526 4527 /* Set up shared pointer to current offset */ 4528#ifdef SISDUALHEAD 4529 if(pSiS->DualHeadMode) 4530 pSiS->cmdQ_SharedWritePort = &(pSiSEnt->cmdQ_SharedWritePort_2D); 4531 else 4532#endif 4533 pSiS->cmdQ_SharedWritePort = &(pSiS->cmdQ_SharedWritePort_2D); 4534 4535 4536#else /* MMIO */ 4537 if(pSiS->TurboQueue) { 4538 pSiS->availMem -= (512*1024); /* MMIO Command Queue is 512k (variable in theory) */ 4539 pSiS->cursorOffset = 512; 4540 } 4541#endif 4542 if(pSiS->HWCursor) { 4543 pSiS->availMem -= (pSiS->CursorSize * 2); 4544 if(pSiS->OptUseColorCursor) pSiS->availMem -= (pSiS->CursorSize * 2); 4545 } 4546 pSiS->cursorBufferNum = 0; 4547#ifdef SISDUALHEAD 4548 if(pSiSEnt) pSiSEnt->cursorBufferNum = 0; 4549#endif 4550 4551 if((pSiS->SiS76xLFBSize) && (pSiS->SiS76xUMASize)) { 4552 pSiS->availMem -= pSiS->SiS76xUMASize; 4553 pSiS->FbBaseOffset = pSiS->SiS76xUMASize; 4554 } 4555 4556 break; 4557 4558 default: 4559 /* cursorOffset not used in cursor functions for 530 and 4560 * older chips, because the cursor is *above* the TQ. 4561 * On 5597 and older revisions of the 6326, the TQ is 4562 * max 32K, on newer 6326 revisions and the 530 either 30 4563 * (or 32?) or 62K (or 64?). However, to make sure, we 4564 * use only 30K (or 32?), but reduce the available memory 4565 * by 64, and locate the TQ at the beginning of this last 4566 * 64K block. (We do this that way even when using the 4567 * HWCursor, because the cursor only takes 2K and the 4568 * queue does not seem to last that far anyway.) 4569 * The TQ must be located at 32KB boundaries. 4570 */ 4571 if(pSiS->RealVideoRam < 3072) { 4572 if(pSiS->TurboQueue) { 4573 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4574 "Not enough video RAM for TurboQueue. TurboQueue disabled\n"); 4575 pSiS->TurboQueue = FALSE; 4576 } 4577 } 4578 pSiS->CmdQueMaxLen = 32; 4579 if(pSiS->TurboQueue) { 4580 pSiS->availMem -= (64*1024); 4581 pSiS->CmdQueMaxLen = 900; /* To make sure; should be 992 */ 4582 } else if(pSiS->HWCursor) { 4583 pSiS->availMem -= pSiS->CursorSize; 4584 } 4585 if(pSiS->Chipset == PCI_CHIP_SIS530) { 4586 /* Check if Flat Panel is enabled */ 4587 inSISIDXREG(SISSR, 0x0e, tempreg); 4588 if(!(tempreg & 0x04)) pSiS->availMem -= pSiS->CursorSize; 4589 4590 /* Set up mask for MMIO register */ 4591 pSiS->CmdQueLenMask = (pSiS->TurboQueue) ? 0x1FFF : 0x00FF; 4592 } else { 4593 /* TQ is never used on 6326/5597, because the accelerator 4594 * always Syncs. So this is just cosmentic work. (And I 4595 * am not even sure that 0x7fff is correct. MMIO 0x83a8 4596 * holds 0xec0 if (30k) TQ is enabled, 0x20 if TQ disabled. 4597 * The datasheet has no real explanation on the queue length 4598 * if the TQ is enabled. Not syncing and waiting for a 4599 * suitable queue length instead does not work. 4600 */ 4601 pSiS->CmdQueLenMask = (pSiS->TurboQueue) ? 0x7FFF : 0x003F; 4602 } 4603 4604 /* This is to be subtracted from MMIO queue length register contents 4605 * for getting the real Queue length. 4606 */ 4607 pSiS->CmdQueLenFix = (pSiS->TurboQueue) ? 32 : 0; 4608 } 4609 4610 4611#ifdef SISDUALHEAD 4612 /* In dual head mode, we share availMem equally - so align it 4613 * to 8KB; this way, the address of the FB of the second 4614 * head is aligned to 4KB for mapping. 4615 */ 4616 if(pSiS->DualHeadMode) pSiS->availMem &= 0xFFFFE000; 4617#endif 4618 4619 /* Check MaxXFBMem setting */ 4620#ifdef SISDUALHEAD 4621 if(pSiS->DualHeadMode) { 4622 /* 1. Since DRI is not supported in dual head mode, we 4623 * don't need the MaxXFBMem setting - ignore it. 4624 */ 4625 if(pSiS->maxxfbmem) { 4626 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4627 "MaxXFBMem ignored in Dual Head mode\n"); 4628 } 4629 pSiS->maxxfbmem = pSiS->availMem; 4630 } else 4631#endif 4632 if((pSiS->sisfbHeapStart) || (pSiS->sisfbHaveNewHeapDef)) { 4633 4634 /* 4635 * 2. We have memory layout info from sisfb - ignore MaxXFBMem 4636 */ 4637 if(pSiS->maxxfbmem) { 4638 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4639 "Got memory layout info from sisfb, ignoring MaxXFBMem option\n"); 4640 } 4641 if((pSiS->FbBaseOffset) && (!pSiS->sisfbHaveNewHeapDef)) { 4642 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4643 "Incompatible sisfb version detected, DRI disabled\n"); 4644 pSiS->loadDRI = FALSE; 4645 pSiS->maxxfbmem = pSiS->availMem; 4646 } else { 4647 if(pSiS->FbBaseOffset) { 4648 /* Revert our changes to FbBaseOffset and availMem; use sisfb's info */ 4649 pSiS->availMem += pSiS->FbBaseOffset; 4650 pSiS->FbBaseOffset = 0; 4651 } 4652 if(pSiS->sisfbVideoOffset) { 4653 /* a. DRI heap BELOW framebuffer */ 4654 pSiS->FbBaseOffset = pSiS->sisfbVideoOffset; 4655 pSiS->availMem -= pSiS->FbBaseOffset; 4656 pSiS->maxxfbmem = pSiS->availMem; 4657 } else { 4658 /* b. DRI heap ABOVE framebuffer (traditional layout) */ 4659 if(pSiS->availMem < (pSiS->sisfbHeapStart * 1024)) { 4660 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4661 "Internal error - sisfb memory layout corrupt\n"); 4662 pSiS->loadDRI = FALSE; 4663 pSiS->maxxfbmem = pSiS->availMem; 4664 } else { 4665 pSiS->maxxfbmem = pSiS->sisfbHeapStart * 1024; 4666 } 4667 } 4668 } 4669 4670 } else if(pSiS->maxxfbmem) { 4671 4672 /* 4673 * 3. No sisfb, but user gave "MaxXFBMem" 4674 */ 4675 if(pSiS->FbBaseOffset) { 4676 /* a. DRI heap BELOW framebuffer */ 4677 if(pSiS->maxxfbmem > (pSiS->availMem + pSiS->FbBaseOffset - pSiS->SiS76xUMASize)) { 4678 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4679 "Invalid MaxXFBMem setting\n"); 4680 pSiS->maxxfbmem = pSiS->availMem; 4681 } else { 4682 /* Revert our changes */ 4683 pSiS->availMem += pSiS->FbBaseOffset; 4684 /* Use user's MaxXFBMem setting */ 4685 pSiS->FbBaseOffset = pSiS->availMem - pSiS->maxxfbmem; 4686 pSiS->availMem -= pSiS->FbBaseOffset; 4687 } 4688 } else { 4689 /* b. DRI heap ABOVE framebuffer (traditional layout) */ 4690 if(pSiS->maxxfbmem > pSiS->availMem) { 4691 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4692 "Invalid MaxXFBMem setting.\n"); 4693 pSiS->maxxfbmem = pSiS->availMem; 4694 } 4695 } 4696 4697 } else { 4698 4699 /* 4700 * 4. No MaxXFBMem, no sisfb: Use all memory 4701 */ 4702 pSiS->maxxfbmem = pSiS->availMem; 4703 4704 /* ... except on chipsets, for which DRI is 4705 * supported: If DRI is enabled, we now limit 4706 * ourselves to a reasonable default: 4707 */ 4708 4709 if(pSiS->loadDRI) { 4710 if(pSiS->FbBaseOffset) { 4711 /* a. DRI heap BELOW framebuffer */ 4712 /* See how much UMA and LFB memory we have, 4713 * and calculate a reasonable default. We 4714 * use more vram for ourselves because these 4715 * chips are eg. capable of larger Xv 4716 * overlays, etc. 4717 */ 4718 unsigned long total = (pSiS->SiS76xLFBSize + pSiS->SiS76xUMASize) / 1024; 4719 unsigned long mymax; 4720 if(total <= 16384) /* <= 16MB: Use 8MB for X */ 4721 mymax = 8192 * 1024; 4722 else if(total <= 32768) /* <= 32MB: Use 16MB for X */ 4723 mymax = 16384 * 1024; 4724 else /* Otherwise: Use 20MB for X */ 4725 mymax = 20 * 1024 * 1024; 4726 /* availMem is right now adjusted to not use the UMA 4727 * area. Make sure that our default doesn't reach 4728 * into the UMA area either. 4729 */ 4730 if(pSiS->availMem > mymax) { 4731 /* Write our default to maxxfbmem */ 4732 pSiS->maxxfbmem = mymax; 4733 /* Revert our changes to availMem */ 4734 pSiS->availMem += pSiS->FbBaseOffset; 4735 /* Use our default setting */ 4736 pSiS->FbBaseOffset = pSiS->availMem - pSiS->maxxfbmem; 4737 pSiS->availMem -= pSiS->FbBaseOffset; 4738 } 4739 } else { 4740 /* b. DRI heap ABOVE framebuffer (traditional layout) */ 4741 /* See how much video memory we have, and calculate 4742 * a reasonable default. 4743 * Since DRI is pointless with less than 4MB of total 4744 * video RAM, we disable it in that case. 4745 */ 4746 if(pScrn->videoRam <= 4096) 4747 pSiS->loadDRI = FALSE; 4748 else if(pScrn->videoRam <= 8192) /* <= 8MB: Use 4MB for X */ 4749 pSiS->maxxfbmem = 4096 * 1024; 4750 else if(pScrn->videoRam <= 16384) /* <= 16MB: Use 8MB for X */ 4751 pSiS->maxxfbmem = 8192 * 1024; 4752#ifdef SISMERGED /* Otherwise: --- */ 4753 else if(pSiS->MergedFB) { 4754 if(pScrn->videoRam <= 65536) 4755 pSiS->maxxfbmem = 16384 * 1024; /* If MergedFB and <=64MB, use 16MB for X */ 4756 else 4757 pSiS->maxxfbmem = 20 * 1024 * 1024; /* If MergedFB and > 64MB, use 20MB for X */ 4758 } 4759#endif 4760 else if(pSiS->VGAEngine == SIS_315_VGA) { 4761 if(pScrn->videoRam <= 65536) 4762 pSiS->maxxfbmem = 16384 * 1024; /* On >=315 series and <=64MB, use 16MB */ 4763 else 4764 pSiS->maxxfbmem = 20 * 1024 * 1024; /* On >=315 series and > 64MB, use 20MB */ 4765 } else 4766 pSiS->maxxfbmem = 12288 * 1024; /* On <315 series, use 12MB */ 4767 4768 /* A final check */ 4769 if(pSiS->maxxfbmem > pSiS->availMem) { 4770 pSiS->maxxfbmem = pSiS->availMem; 4771 pSiS->loadDRI = FALSE; 4772 } 4773 } 4774 4775 } 4776 } 4777 4778 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %dK of framebuffer memory at offset %dK\n", 4779 pSiS->maxxfbmem / 1024, pSiS->FbBaseOffset / 1024); 4780 4781 /* Find out about sub-classes of some chipsets and check 4782 * if the chipset supports two video overlays 4783 */ 4784 if(pSiS->VGAEngine == SIS_300_VGA || 4785 pSiS->VGAEngine == SIS_315_VGA || 4786 pSiS->Chipset == PCI_CHIP_SIS530 || 4787 pSiS->Chipset == PCI_CHIP_SIS6326 || 4788 pSiS->Chipset == PCI_CHIP_SIS5597) { 4789 pSiS->hasTwoOverlays = FALSE; 4790 switch(pSiS->Chipset) { 4791 case PCI_CHIP_SIS300: 4792 case PCI_CHIP_SIS540: /* ? (If not, need to add the SwitchCRT Xv attribute!) */ 4793 case PCI_CHIP_SIS630: 4794 case PCI_CHIP_SIS550: 4795 pSiS->hasTwoOverlays = TRUE; 4796 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4797 break; 4798 case PCI_CHIP_SIS315PRO: 4799 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4800 break; 4801 case PCI_CHIP_SIS330: 4802 pSiS->ChipFlags |= (SiSCF_CRT2HWCKaputt | SiSCF_LARGEOVERLAY); 4803 break; 4804 case PCI_CHIP_SIS340: 4805 case PCI_CHIP_XGIXG40: /* Verified: only 1 overlay */ 4806 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4807 break; 4808 case PCI_CHIP_SIS650: 4809 { 4810 UChar tempreg1, tempreg2; 4811 static const char *id650str[] = { 4812 "650", "650", "650", "650", 4813 "650 A0 AA", "650 A2 CA", "650", "650", 4814 "M650 A0", "M650 A1 AA","651 A0 AA", "651 A1 AA", 4815 "M650", "65?", "651", "65?" 4816 }; 4817 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4818 if(pSiS->ChipType == SIS_650) { 4819 inSISIDXREG(SISCR, 0x5f, CR5F); 4820 CR5F &= 0xf0; 4821 andSISIDXREG(SISCR, 0x5c, 0x07); 4822 inSISIDXREG(SISCR, 0x5c, tempreg1); 4823 tempreg1 &= 0xf8; 4824 orSISIDXREG(SISCR, 0x5c, 0xf8); 4825 inSISIDXREG(SISCR, 0x5c, tempreg2); 4826 tempreg2 &= 0xf8; 4827 if((!tempreg1) || (tempreg2)) { 4828 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4829 "SiS650 revision ID %x (%s)\n", CR5F, id650str[CR5F >> 4]); 4830 if(CR5F & 0x80) { 4831 pSiS->hasTwoOverlays = TRUE; /* M650 or 651 */ 4832 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4833 } 4834 switch(CR5F) { 4835 case 0xa0: 4836 case 0xb0: 4837 case 0xe0: 4838 pSiS->ChipFlags |= SiSCF_Is651; 4839 break; 4840 case 0x80: 4841 case 0x90: 4842 case 0xc0: 4843 pSiS->ChipFlags |= SiSCF_IsM650; 4844 break; 4845 } 4846 } else { 4847 pSiS->hasTwoOverlays = TRUE; 4848 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4849 switch(CR5F) { 4850 case 0x90: 4851 inSISIDXREG(SISCR, 0x5c, tempreg1); 4852 tempreg1 &= 0xf8; 4853 switch(tempreg1) { 4854 case 0x00: 4855 pSiS->ChipFlags |= SiSCF_IsM652; 4856 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4857 "SiSM652 revision ID %x\n", CR5F); 4858 break; 4859 case 0x40: 4860 pSiS->ChipFlags |= SiSCF_IsM653; 4861 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4862 "SiSM653 revision ID %x\n", CR5F); 4863 break; 4864 default: 4865 pSiS->ChipFlags |= SiSCF_IsM650; 4866 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4867 "SiSM650 revision ID %x\n", CR5F); 4868 break; 4869 } 4870 break; 4871 case 0xb0: 4872 pSiS->ChipFlags |= SiSCF_Is652; 4873 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4874 "SiS652 revision ID %x\n", CR5F); 4875 break; 4876 default: 4877 pSiS->ChipFlags |= SiSCF_IsM650; 4878 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4879 "SiSM650 revision ID %x\n", CR5F); 4880 break; 4881 } 4882 } 4883 } 4884 break; 4885 } 4886 case PCI_CHIP_SIS660: 4887 { 4888 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4889 pSiS->hasTwoOverlays = TRUE; 4890 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4891 /* 760/761: - UMA only: one/two overlays - dotclock dependent 4892 - UMA+LFB: two overlays if video data in LFB 4893 - LFB only: two overlays 4894 If UMA only: Must switch between one/two overlays on the fly (done 4895 in PostSetMode()) 4896 If LFB+UMA: We use LFB memory only and leave UMA to an eventually 4897 written DRI driver. 4898 */ 4899 break; 4900 } 4901 } 4902 4903 if(!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY)) { 4904 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4905 "Hardware supports %s video overlay%s\n", 4906 pSiS->hasTwoOverlays ? "two" : "one", 4907 pSiS->hasTwoOverlays ? "s" : ""); 4908 } 4909 4910 if(pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORT760OO) { 4911 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4912 "\n\tDear SiS76x user, your machine is using a shared memory framebuffer.\n" 4913 "\tDue to hardware limitations of the SiS chip in combination with the\n" 4914 "\tAMD CPU, video overlay support is very limited on this machine. If you\n" 4915 "\texperience flashing lines in the video and/or the graphics display\n" 4916 "\tduring video playback, reduce the color depth and/or the resolution\n" 4917 "\tand/or the refresh rate. Alternatively, use the video blitter.\n"); 4918 } 4919 4920 } 4921 4922 /* Backup VB connection and CRT1 on/off register */ 4923 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 4924 inSISIDXREG(SISSR, 0x1f, pSiS->oldSR1F); 4925 inSISIDXREG(SISCR, 0x17, pSiS->oldCR17); 4926 inSISIDXREG(SISCR, 0x32, pSiS->oldCR32); 4927 inSISIDXREG(SISCR, 0x36, pSiS->oldCR36); 4928 inSISIDXREG(SISCR, 0x37, pSiS->oldCR37); 4929 if(pSiS->VGAEngine == SIS_315_VGA) { 4930 inSISIDXREG(SISCR, pSiS->myCR63, pSiS->oldCR63); 4931 } 4932 4933 pSiS->postVBCR32 = pSiS->oldCR32; 4934 } 4935 4936 /* There are some machines out there which require a special 4937 * setup of the GPIO registers in order to make the Chrontel 4938 * work. Try to find out if we're running on such a machine. 4939 * Furthermore, there is some highly customized hardware, 4940 * which requires some non-standard LVDS timing. Since the 4941 * vendors don't seem to care about PCI subsystem ID's we 4942 * need to find out using the BIOS version and date strings. 4943 */ 4944 pSiS->SiS_Pr->SiS_ChSW = FALSE; 4945 if(pSiS->Chipset == PCI_CHIP_SIS630) { 4946 int i = 0; 4947 do { 4948 if(mychswtable[i].subsysVendor == PCI_SUB_VENDOR_ID(pSiS->PciInfo) && 4949 mychswtable[i].subsysCard == PCI_SUB_DEVICE_ID(pSiS->PciInfo)) { 4950 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4951 "PCI subsystem ID found in list for Chrontel/GPIO setup:\n"); 4952 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4953 "\tVendor/Card: %s %s (ID %04x)\n", 4954 mychswtable[i].vendorName, 4955 mychswtable[i].cardName, 4956 PCI_SUB_DEVICE_ID(pSiS->PciInfo)); 4957 pSiS->SiS_Pr->SiS_ChSW = TRUE; 4958 break; 4959 } 4960 i++; 4961 } while(mychswtable[i].subsysVendor != 0); 4962 } 4963 4964 if(pSiS->SiS_Pr->SiS_CustomT == CUT_NONE) { 4965 int i = 0, j; 4966 UShort bversptr = 0; 4967 Bool footprint; 4968 CARD32 chksum = 0; 4969 4970 if(pSiS->SiS_Pr->UseROM) { 4971 bversptr = pSiS->BIOS[0x16] | (pSiS->BIOS[0x17] << 8); 4972 for(i=0; i<32768; i++) chksum += pSiS->BIOS[i]; 4973 } 4974 4975 i = 0; 4976 do { 4977 if( (SiS_customttable[i].chipID == pSiS->ChipType) && 4978 ((!strlen(SiS_customttable[i].biosversion)) || 4979 (pSiS->SiS_Pr->UseROM && 4980 (!strncmp(SiS_customttable[i].biosversion, (char *)&pSiS->BIOS[bversptr], 4981 strlen(SiS_customttable[i].biosversion))))) && 4982 ((!strlen(SiS_customttable[i].biosdate)) || 4983 (pSiS->SiS_Pr->UseROM && 4984 (!strncmp(SiS_customttable[i].biosdate, (char *)&pSiS->BIOS[0x2c], 4985 strlen(SiS_customttable[i].biosdate))))) && 4986 ((!SiS_customttable[i].bioschksum) || 4987 (pSiS->SiS_Pr->UseROM && 4988 (SiS_customttable[i].bioschksum == chksum))) && 4989 (SiS_customttable[i].pcisubsysvendor == PCI_SUB_VENDOR_ID(pSiS->PciInfo)) && 4990 (SiS_customttable[i].pcisubsyscard == PCI_SUB_DEVICE_ID(pSiS->PciInfo)) ) { 4991 footprint = TRUE; 4992 for(j=0; j<5; j++) { 4993 if(SiS_customttable[i].biosFootprintAddr[j]) { 4994 if(pSiS->SiS_Pr->UseROM) { 4995 if(pSiS->BIOS[SiS_customttable[i].biosFootprintAddr[j]] != 4996 SiS_customttable[i].biosFootprintData[j]) 4997 footprint = FALSE; 4998 } else footprint = FALSE; 4999 } 5000 } 5001 if(footprint) { 5002 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5003 "Identified %s %s, special timing applies\n", 5004 SiS_customttable[i].vendorName, SiS_customttable[i].cardName); 5005 pSiS->SiS_Pr->SiS_CustomT = SiS_customttable[i].SpecialID; 5006 break; 5007 } 5008 } 5009 i++; 5010 } while(SiS_customttable[i].chipID); 5011 } 5012 5013 /* Handle ForceCRT1 option */ 5014 if(pSiS->forceCRT1 != -1) { 5015 if(pSiS->forceCRT1) pSiS->CRT1off = 0; 5016 else pSiS->CRT1off = 1; 5017 } else pSiS->CRT1off = -1; 5018 5019 /* Detect video bridge and sense TV/VGA2 */ 5020 SISVGAPreInit(pScrn); 5021 5022 /* Detect CRT1 (via DDC1 and DDC2, hence via VGA port; regardless of LCDA) */ 5023 SISCRT1PreInit(pScrn); 5024 5025 /* Detect LCD (connected via CRT2, regardless of LCDA) and LCD resolution */ 5026 SISLCDPreInit(pScrn, FALSE); 5027 5028 /* LCDA only supported under these conditions: */ 5029 if(pSiS->ForceCRT1Type == CRT1_LCDA) { 5030 if(!SISDetermineLCDACap(pScrn)) { 5031 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5032 "Chipset/Video bridge does not support LCD-via-CRT1\n"); 5033 pSiS->ForceCRT1Type = CRT1_VGA; 5034 } else if(!(pSiS->VBFlags & CRT2_LCD)) { 5035 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5036 "No digital LCD panel found, LCD-via-CRT1 disabled\n"); 5037 pSiS->ForceCRT1Type = CRT1_VGA; 5038 } 5039 } 5040 5041 /* Setup SD flags */ 5042 pSiS->SiS_SD_Flags |= SiS_SD_ADDLSUPFLAG; 5043 5044 pSiS->SiS_SD2_Flags |= SiS_SD2_MERGEDUCLOCK; 5045 pSiS->SiS_SD2_Flags |= SiS_SD2_USEVBFLAGS2; 5046 pSiS->SiS_SD2_Flags |= SiS_SD2_VBINVB2ONLY; 5047 pSiS->SiS_SD2_Flags |= SiS_SD2_HAVESD34; 5048 pSiS->SiS_SD2_Flags |= SiS_SD2_NEWGAMMABRICON; 5049 5050 pSiS->SiS_SD3_Flags |= SiS_SD3_MFBALLOWOFFCL; 5051 5052 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 5053 pSiS->SiS_SD2_Flags |= SiS_SD2_VIDEOBRIDGE; 5054 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 5055 pSiS->SiS_SD2_Flags |= ( SiS_SD2_SISBRIDGE | 5056 SiS_SD2_SUPPORTGAMMA2 ); 5057 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) { 5058 pSiS->SiS_SD2_Flags |= ( SiS_SD2_LCDLVDS | 5059 SiS_SD2_SUPPORTLCD ); 5060 } else if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 5061 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 5062 pSiS->SiS_SD2_Flags |= ( SiS_SD2_LCDTMDS | 5063 SiS_SD2_SUPPORTLCD ); 5064 } else if(pSiS->VBFlags & CRT2_LCD) { 5065 pSiS->SiS_SD2_Flags |= ( SiS_SD2_THIRDPARTYLVDS | 5066 SiS_SD2_SUPPORTLCD ); 5067 } 5068 } 5069 } else if(pSiS->VBFlags2 & VB2_LVDS) { 5070 pSiS->SiS_SD2_Flags |= ( SiS_SD2_THIRDPARTYLVDS | 5071 SiS_SD2_SUPPORTLCD ); 5072 } 5073 5074 if(pSiS->VBFlags2 & (VB2_SISTVBRIDGE | VB2_CHRONTEL)) { 5075 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTTV; 5076 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 5077 pSiS->SiS_SD2_Flags |= ( SiS_SD2_SUPPORTTVTYPE | 5078 SiS_SD2_SUPPORTTVSIZE ); 5079 if(!(pSiS->VBFlags2 & VB2_301)) { 5080 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPTVSAT; 5081 } else { 5082 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPTVEDGE; 5083 } 5084 } 5085 } 5086 } 5087 5088#ifdef ENABLE_YPBPR 5089 if((pSiS->VGAEngine == SIS_315_VGA) && 5090 (pSiS->VBFlags2 & VB2_SISYPBPRBRIDGE)) { 5091 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTYPBPR; 5092 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORT625I; 5093 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORT625P; 5094 if(pSiS->VBFlags2 & VB2_SISYPBPRARBRIDGE) { 5095 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTYPBPRAR; 5096 } 5097 } 5098 if(pSiS->VBFlags2 & VB2_SISHIVISIONBRIDGE) { 5099 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTHIVISION; 5100 } 5101#endif 5102 5103 if((pSiS->VGAEngine != SIS_300_VGA) || (!(pSiS->VBFlags2 & VB2_TRUMPION))) { 5104 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTSCALE; 5105 if((pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && 5106 (!(pSiS->VBFlags2 & VB2_30xBDH))) { 5107 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTCENTER; 5108 } 5109 } 5110 5111#ifdef SISDUALHEAD 5112 if(!pSiS->DualHeadMode) { 5113 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTREDETECT; 5114 } 5115#endif 5116 5117#ifndef SISCHECKOSSSE 5118 pSiS->SiS_SD2_Flags |= SiS_SD2_NEEDUSESSE; 5119#endif 5120 5121#ifdef TWDEBUG /* FOR TESTING */ 5122 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTYPBPRAR; 5123 xf86DrvMsg(0, X_INFO, "TEST: Support Aspect Ratio\n"); 5124#endif 5125 5126 /* Detect CRT2-TV and PAL/NTSC mode */ 5127 SISTVPreInit(pScrn, FALSE); 5128 5129 /* Detect CRT2-VGA */ 5130 SISCRT2PreInit(pScrn, FALSE); 5131 5132 /* Backup detected CRT2 devices */ 5133 SISSaveDetectedDevices(pScrn); 5134 5135 if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR)) { 5136 if((pSiS->ForceTVType != -1) && (pSiS->ForceTVType & TV_YPBPR)) { 5137 pSiS->ForceTVType = -1; 5138 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "YPbPr TV output not supported\n"); 5139 } 5140 } 5141 5142 if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTHIVISION)) { 5143 if((pSiS->ForceTVType != -1) && (pSiS->ForceTVType & TV_HIVISION)) { 5144 pSiS->ForceTVType = -1; 5145 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "HiVision TV output not supported\n"); 5146 } 5147 } 5148 5149 if((pSiS->VBFlags2 & VB2_SISTVBRIDGE) || 5150 ((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->ChrontelType == CHRONTEL_701x))) { 5151 pSiS->SiS_SD_Flags |= (SiS_SD_SUPPORTPALMN | SiS_SD_SUPPORTNTSCJ); 5152 } 5153 if((pSiS->VBFlags2 & VB2_SISTVBRIDGE) || 5154 ((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->ChrontelType == CHRONTEL_700x))) { 5155 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTTVPOS; 5156 } 5157 if(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE) { 5158 pSiS->SiS_SD_Flags |= (SiS_SD_SUPPORTSCART | SiS_SD_SUPPORTVGA2); 5159 } 5160 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 5161 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTOVERSCAN; 5162 pSiS->SiS_SD2_Flags |= SiS_SD2_CHRONTEL; 5163 if(pSiS->ChrontelType == CHRONTEL_700x) { 5164 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTSOVER; 5165 } 5166 } 5167 5168 /* Determine if chipset LCDA-capable */ 5169 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTLCDA; 5170 if(SISDetermineLCDACap(pScrn)) { 5171 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTLCDA; 5172 } 5173 5174 /* Default to LCDA if LCD detected and 5175 * - TV detected (hence default to LCDA+TV), or 5176 * - in single head mode, on LCD panels with xres > 1600 5177 * (Don't do this in MergedFB or DHM; LCDA and CRT1/VGA 5178 * are mutually exclusive; if no TV is detected, the 5179 * code below will default to VGA+LCD, so LCD is driven 5180 * via CRT2.) 5181 * (TODO: This might need some modification for the 5182 * 307 bridges, if these are capable of driving 5183 * LCDs > 1600 via channel B) 5184 */ 5185 if((pSiS->SiS_SD_Flags & SiS_SD_SUPPORTLCDA) && 5186 (pSiS->VBFlags & CRT2_LCD) && 5187 (pSiS->SiS_Pr->SiS_CustomT != CUT_UNKNOWNLCD)) { 5188 if((!pSiS->CRT1TypeForced) && (pSiS->ForceCRT2Type == CRT2_DEFAULT)) { 5189 if(pSiS->VBFlags & CRT2_TV) { 5190 /* If both LCD and TV present, default to LCDA+TV */ 5191 pSiS->ForceCRT1Type = CRT1_LCDA; 5192 pSiS->ForceCRT2Type = CRT2_TV; 5193 } else if(pSiS->LCDwidth > 1600) { 5194 /* If LCD is > 1600, default to LCDA if we don't need CRT1/VGA for other head */ 5195 Bool NeedCRT1VGA = FALSE; 5196#ifdef SISDUALHEAD 5197 if(pSiS->DualHeadMode) NeedCRT1VGA = TRUE; 5198#endif 5199#ifdef SISMERGED 5200 if(pSiS->MergedFB && 5201 (!pSiS->MergedFBAuto || pSiS->CRT1Detected)) NeedCRT1VGA = TRUE; 5202#endif 5203 if(!NeedCRT1VGA) { 5204 pSiS->ForceCRT1Type = CRT1_LCDA; 5205 } 5206 } 5207 } 5208 } 5209 5210 /* Set up pseudo-panel if LCDA forced on TMDS bridges */ 5211 if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTLCDA) { 5212 if(pSiS->ForceCRT1Type == CRT1_LCDA) { 5213 if(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE) { 5214 if(!(pSiS->VBLCDFlags)) { 5215 SiSSetupPseudoPanel(pScrn); 5216 pSiS->detectedCRT2Devices |= CRT2_LCD; 5217 } 5218 } else if(!(pSiS->VBLCDFlags)) { 5219 pSiS->ForceCRT1Type = CRT1_VGA; 5220 } 5221 } 5222 } else { 5223 pSiS->ForceCRT1Type = CRT1_VGA; 5224 } 5225 5226 pSiS->VBFlags |= pSiS->ForceCRT1Type; 5227 5228#ifdef TWDEBUG 5229 xf86DrvMsg(0, X_INFO, "SDFlags %lx\n", pSiS->SiS_SD_Flags); 5230#endif 5231 5232 /* Eventually overrule detected CRT2 type 5233 * If no type forced, use the detected devices in the order TV->LCD->VGA2 5234 * Since the Chrontel 7005 sometimes delivers wrong detection results, 5235 * we use a different order on such machines (LCD->TV) 5236 */ 5237 if(pSiS->ForceCRT2Type == CRT2_DEFAULT) { 5238 if((pSiS->VBFlags & CRT2_TV) && (!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VGAEngine == SIS_300_VGA)))) 5239 pSiS->ForceCRT2Type = CRT2_TV; 5240 else if((pSiS->VBFlags & CRT2_LCD) && (pSiS->ForceCRT1Type == CRT1_VGA)) 5241 pSiS->ForceCRT2Type = CRT2_LCD; 5242 else if(pSiS->VBFlags & CRT2_TV) 5243 pSiS->ForceCRT2Type = CRT2_TV; 5244 else if((pSiS->VBFlags & CRT2_VGA) && (pSiS->ForceCRT1Type == CRT1_VGA)) 5245 pSiS->ForceCRT2Type = CRT2_VGA; 5246 } 5247 5248 switch(pSiS->ForceCRT2Type) { 5249 case CRT2_TV: 5250 pSiS->VBFlags &= ~(CRT2_LCD | CRT2_VGA); 5251 if(pSiS->VBFlags2 & (VB2_SISTVBRIDGE | VB2_CHRONTEL)) { 5252 pSiS->VBFlags |= CRT2_TV; 5253 } else { 5254 pSiS->VBFlags &= ~(CRT2_TV); 5255 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 5256 "Hardware does not support TV output\n"); 5257 } 5258 break; 5259 case CRT2_LCD: 5260 pSiS->VBFlags &= ~(CRT2_TV | CRT2_VGA); 5261 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (pSiS->VBLCDFlags)) { 5262 pSiS->VBFlags |= CRT2_LCD; 5263 } else if((pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && (!(pSiS->VBFlags2 & VB2_30xBDH))) { 5264 SiSSetupPseudoPanel(pScrn); 5265 pSiS->detectedCRT2Devices |= CRT2_LCD; 5266 } else { 5267 pSiS->VBFlags &= ~(CRT2_LCD); 5268 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 5269 "Can't force CRT2 to LCD, no LCD detected\n"); 5270 } 5271 break; 5272 case CRT2_VGA: 5273 pSiS->VBFlags &= ~(CRT2_TV | CRT2_LCD); 5274 if(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE) { 5275 pSiS->VBFlags |= CRT2_VGA; 5276 } else { 5277 pSiS->VBFlags &= ~(CRT2_VGA); 5278 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 5279 "Hardware does not support secondary VGA\n"); 5280 } 5281 break; 5282 default: 5283 pSiS->VBFlags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA); 5284 } 5285 5286 /* Setup gamma (the cmap layer needs this to be initialised) */ 5287 /* (Do this after evaluating options) */ 5288 { 5289 Gamma zeros = {0.0, 0.0, 0.0}; 5290 xf86SetGamma(pScrn, zeros); 5291 } 5292 5293#ifdef SISDUALHEAD 5294 if((!pSiS->DualHeadMode) || (pSiS->SecondHead)) { 5295#endif 5296 xf86DrvMsg(pScrn->scrnIndex, pSiS->CRT1gammaGiven ? X_CONFIG : X_INFO, 5297 "%samma correction is %s\n", 5298 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) ? "CRT1 g" : "G", 5299 pSiS->CRT1gamma ? "enabled" : "disabled"); 5300 5301 if((pSiS->VGAEngine == SIS_315_VGA) && 5302 (!(pSiS->NoXvideo)) && 5303 (!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY))) { 5304 xf86DrvMsg(pScrn->scrnIndex, pSiS->XvGammaGiven ? X_CONFIG : X_INFO, 5305 "Separate Xv gamma correction %sis %s\n", 5306 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) ? "for CRT1 " : "", 5307 pSiS->XvGamma ? "enabled" : "disabled"); 5308 if(pSiS->XvGamma) { 5309 xf86DrvMsg(pScrn->scrnIndex, pSiS->XvGammaGiven ? X_CONFIG : X_INFO, 5310 "Xv gamma correction: %.3f %.3f %.3f\n", 5311 (float)((float)pSiS->XvGammaRed / 1000), 5312 (float)((float)pSiS->XvGammaGreen / 1000), 5313 (float)((float)pSiS->XvGammaBlue / 1000)); 5314 if(!pSiS->CRT1gamma) { 5315 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5316 "Xv gamma correction requires %samma correction enabled\n", 5317 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) ? "CRT1 g" : "G"); 5318 } 5319 } 5320 } 5321#ifdef SISDUALHEAD 5322 } 5323#endif 5324 5325#ifdef SISDUALHEAD 5326 if(pSiS->DualHeadMode) pSiS->CRT2SepGamma = FALSE; 5327#endif 5328 5329#ifdef SISDUALHEAD 5330 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) 5331#endif 5332 { 5333 Bool isDH = FALSE; 5334 if(pSiS->CRT2gamma) { 5335 if( ((pSiS->VGAEngine != SIS_300_VGA) && (pSiS->VGAEngine != SIS_315_VGA)) || 5336 (!(pSiS->VBFlags2 & VB2_SISBRIDGE)) ) { 5337 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 5338 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5339 "CRT2 gamma correction not supported by hardware\n"); 5340 } 5341 pSiS->CRT2gamma = pSiS->CRT2SepGamma = FALSE; 5342 } else if((pSiS->VBFlags2 & VB2_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) { 5343 isDH = TRUE; 5344 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5345 "CRT2 gamma correction not supported for LCD\n"); 5346 /* But leave it on, will be caught in LoadPalette */ 5347 } 5348 } 5349 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 5350 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CRT2 gamma correction is %s%s%s\n", 5351 pSiS->CRT2gamma ? "enabled" : "disabled", 5352 isDH ? " (for TV and VGA2) " : "", 5353 pSiS->CRT2SepGamma ? " (separate from CRT1)" : ""); 5354 } 5355 } 5356 5357 /* Eventually overrule TV Type (SVIDEO, COMPOSITE, SCART, HIVISION, YPBPR) */ 5358 if(pSiS->VBFlags2 & VB2_SISTVBRIDGE) { 5359 if(pSiS->ForceTVType != -1) { 5360 pSiS->VBFlags &= ~(TV_INTERFACE); 5361 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) { 5362 pSiS->VBFlags &= ~(TV_CHSCART | TV_CHYPBPR525I); 5363 } 5364 pSiS->VBFlags |= pSiS->ForceTVType; 5365 if(pSiS->VBFlags & TV_YPBPR) { 5366 pSiS->VBFlags &= ~(TV_STANDARD); 5367 pSiS->VBFlags &= ~(TV_YPBPRAR); 5368 pSiS->VBFlags |= pSiS->ForceYPbPrType; 5369 pSiS->VBFlags |= pSiS->ForceYPbPrAR; 5370 } 5371 } 5372 } 5373 5374 /* Handle ForceCRT1 option (part 2) */ 5375 pSiS->CRT1changed = FALSE; 5376 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5377 usScratchCR17 = pSiS->oldCR17; 5378 usScratchCR63 = pSiS->oldCR63; 5379 usScratchSR1F = pSiS->oldSR1F; 5380 usScratchCR32 = pSiS->postVBCR32; 5381 if(pSiS->VESA != 1) { 5382 /* Copy forceCRT1 option to CRT1off if option is given */ 5383#ifdef SISDUALHEAD 5384 /* In DHM, handle this option only for master head, not the slave */ 5385 if( (pSiS->forceCRT1 != -1) && 5386 (!(pSiS->DualHeadMode && pSiS->SecondHead)) ) { 5387#else 5388 if(pSiS->forceCRT1 != -1) { 5389#endif 5390 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5391 "CRT1 detection overruled by ForceCRT1 option\n"); 5392 if(pSiS->forceCRT1) { 5393 pSiS->CRT1off = 0; 5394 if(pSiS->VGAEngine == SIS_300_VGA) { 5395 if(!(usScratchCR17 & 0x80)) pSiS->CRT1changed = TRUE; 5396 } else { 5397 if(usScratchCR63 & 0x40) pSiS->CRT1changed = TRUE; 5398 } 5399 usScratchCR17 |= 0x80; 5400 usScratchCR32 |= 0x20; 5401 usScratchCR63 &= ~0x40; 5402 usScratchSR1F &= ~0xc0; 5403 } else { 5404 if( ! ( (pScrn->bitsPerPixel == 8) && 5405 ( (pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) || 5406 ((pSiS->VBFlags2 & VB2_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) ) ) ) { 5407 pSiS->CRT1off = 1; 5408 if(pSiS->VGAEngine == SIS_300_VGA) { 5409 if(usScratchCR17 & 0x80) pSiS->CRT1changed = TRUE; 5410 } else { 5411 if(!(usScratchCR63 & 0x40)) pSiS->CRT1changed = TRUE; 5412 } 5413 usScratchCR32 &= ~0x20; 5414 /* We must not actually switch off CRT1 before we changed the mode! */ 5415 } 5416 } 5417 /* Here we can write to CR17 even on 315 series as we only ENABLE 5418 * the bit here 5419 */ 5420 outSISIDXREG(SISCR, 0x17, usScratchCR17); 5421 if(pSiS->VGAEngine == SIS_315_VGA) { 5422 outSISIDXREG(SISCR, pSiS->myCR63, usScratchCR63); 5423 } 5424 outSISIDXREG(SISCR, 0x32, usScratchCR32); 5425 if(pSiS->CRT1changed) { 5426 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 5427 usleep(10000); 5428 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 5429 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5430 "CRT1 status changed by ForceCRT1 option\n"); 5431 } 5432 outSISIDXREG(SISSR, 0x1f, usScratchSR1F); 5433 } 5434 } 5435 /* Store the new VB connection register contents for later mode changes */ 5436 pSiS->newCR32 = usScratchCR32; 5437 } 5438 5439 /* Check if CRT1 used (or needed; this eg. if no CRT2 detected) */ 5440 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 5441 5442 /* No CRT2 output? Then we NEED CRT1! 5443 * We also need CRT1 if depth = 8 and bridge=LVDS|301B-DH 5444 */ 5445 if( (!(pSiS->VBFlags & (CRT2_VGA | CRT2_LCD | CRT2_TV))) || 5446 ( (pScrn->bitsPerPixel == 8) && 5447 ( (pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) || 5448 ((pSiS->VBFlags2 & VB2_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) ) ) ) { 5449 pSiS->CRT1off = 0; 5450 } 5451 /* No CRT2 output? Then we can't use Xv on CRT2 */ 5452 if(!(pSiS->VBFlags & (CRT2_VGA | CRT2_LCD | CRT2_TV))) { 5453 pSiS->XvOnCRT2 = FALSE; 5454 } 5455 5456 } else { /* no video bridge? */ 5457 /* Then we NEED CRT1... */ 5458 pSiS->CRT1off = 0; 5459 /* ... and can't use CRT2 for Xv output */ 5460 pSiS->XvOnCRT2 = FALSE; 5461 } 5462 5463 /* LCDA? Then we don't switch off CRT1 */ 5464 if(pSiS->VBFlags & CRT1_LCDA) pSiS->CRT1off = 0; 5465 5466 /* Handle TVStandard option */ 5467 if((pSiS->NonDefaultPAL != -1) || (pSiS->NonDefaultNTSC != -1)) { 5468 if( (!(pSiS->VBFlags2 & VB2_SISTVBRIDGE)) && 5469 (!((pSiS->VBFlags2 & VB2_CHRONTEL)) && (pSiS->ChrontelType == CHRONTEL_701x)) ) { 5470 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5471 "PALM, PALN and NTSCJ not supported on this hardware\n"); 5472 pSiS->NonDefaultPAL = pSiS->NonDefaultNTSC = -1; 5473 pSiS->VBFlags &= ~(TV_PALN | TV_PALM | TV_NTSCJ); 5474 pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTPALMN | SiS_SD_SUPPORTNTSCJ); 5475 } 5476 } 5477 if(pSiS->OptTVStand != -1) { 5478 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5479 if( (!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & (TV_CHSCART | TV_CHYPBPR525I)))) && 5480 (!(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR))) ) { 5481 pSiS->VBFlags &= ~(TV_PAL | TV_NTSC | TV_PALN | TV_PALM | TV_NTSCJ); 5482 if(pSiS->OptTVStand) { 5483 pSiS->VBFlags |= TV_PAL; 5484 if(pSiS->NonDefaultPAL == 1) pSiS->VBFlags |= TV_PALM; 5485 else if(!pSiS->NonDefaultPAL) pSiS->VBFlags |= TV_PALN; 5486 } else { 5487 pSiS->VBFlags |= TV_NTSC; 5488 if(pSiS->NonDefaultNTSC == 1) pSiS->VBFlags |= TV_NTSCJ; 5489 } 5490 } else { 5491 pSiS->OptTVStand = pSiS->NonDefaultPAL = -1; 5492 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5493 "Option TVStandard ignored for YPbPr, HiVision and Chrontel-SCART\n"); 5494 } 5495 } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { 5496 pSiS->SiS6326Flags &= ~SIS6326_TVPAL; 5497 if(pSiS->OptTVStand) pSiS->SiS6326Flags |= SIS6326_TVPAL; 5498 } 5499 } 5500 5501 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5502 /* Default to PAL */ 5503 if(pSiS->VBFlags & (TV_SVIDEO | TV_AVIDEO)) { 5504 if(!(pSiS->VBFlags & (TV_PAL | TV_NTSC))) { 5505 pSiS->VBFlags &= ~(TV_PAL | TV_NTSC | TV_PALN | TV_PALM | TV_NTSCJ); 5506 pSiS->VBFlags |= TV_PAL; 5507 } 5508 } 5509 /* SCART only supported for PAL */ 5510 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && (pSiS->VBFlags & TV_SCART)) { 5511 pSiS->VBFlags &= ~(TV_NTSC | TV_PALN | TV_PALM | TV_NTSCJ); 5512 pSiS->VBFlags |= TV_PAL; 5513 pSiS->OptTVStand = 1; 5514 pSiS->NonDefaultPAL = pSiS->NonDefaultNTSC = -1; 5515 } 5516 } 5517 5518#ifdef SIS_CP 5519 SIS_CP_DRIVER_RECONFIGOPT 5520#endif 5521 5522 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 5523 if(pSiS->sis6326tvplug != -1) { 5524 pSiS->SiS6326Flags &= ~(SIS6326_TVSVIDEO | SIS6326_TVCVBS); 5525 pSiS->SiS6326Flags |= SIS6326_TVDETECTED; 5526 if(pSiS->sis6326tvplug == 1) pSiS->SiS6326Flags |= SIS6326_TVCVBS; 5527 else pSiS->SiS6326Flags |= SIS6326_TVSVIDEO; 5528 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5529 "SiS6326 TV plug type detection overruled by %s\n", 5530 (pSiS->SiS6326Flags & SIS6326_TVCVBS) ? "COMPOSITE" : "SVIDEO"); 5531 } 5532 } 5533 5534 /* Do some checks */ 5535 if(pSiS->OptTVOver != -1) { 5536 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 5537 pSiS->UseCHOverScan = pSiS->OptTVOver; 5538 } else { 5539 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5540 "CHTVOverscan only supported on CHRONTEL 70xx\n"); 5541 pSiS->UseCHOverScan = -1; 5542 } 5543 } else pSiS->UseCHOverScan = -1; 5544 5545 if(pSiS->sistvedgeenhance != -1) { 5546 if(!(pSiS->VBFlags2 & VB2_301)) { 5547 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5548 "SISTVEdgeEnhance only supported on SiS301\n"); 5549 pSiS->sistvedgeenhance = -1; 5550 } 5551 } 5552 if(pSiS->sistvsaturation != -1) { 5553 if(pSiS->VBFlags2 & VB2_301) { 5554 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5555 "SISTVSaturation not supported on SiS301\n"); 5556 pSiS->sistvsaturation = -1; 5557 } 5558 } 5559 5560 /* Do some MergedFB mode initialisation */ 5561#ifdef SISMERGED 5562 if(pSiS->MergedFB) { 5563 pSiS->CRT2pScrn = xalloc(sizeof(ScrnInfoRec)); 5564 if(!pSiS->CRT2pScrn) { 5565 SISErrorLog(pScrn, "Failed to allocate memory for 2nd pScrn, %s\n", mergeddisstr); 5566 pSiS->MergedFB = FALSE; 5567 } else { 5568 memcpy(pSiS->CRT2pScrn, pScrn, sizeof(ScrnInfoRec)); 5569 } 5570 } 5571#endif 5572 5573 /* Determine CRT1<>CRT2 mode 5574 * Note: When using VESA or if the bridge is in slavemode, display 5575 * is ALWAYS in MIRROR_MODE! 5576 * This requires extra checks in functions using this flag! 5577 * (see sis_video.c for example) 5578 */ 5579 if(pSiS->VBFlags & DISPTYPE_DISP2) { 5580 if(pSiS->CRT1off) { /* CRT2 only ------------------------------- */ 5581#ifdef SISDUALHEAD 5582 if(pSiS->DualHeadMode) { 5583 SISErrorLog(pScrn, 5584 "CRT1 not detected or forced off. Dual Head mode can't initialize.\n"); 5585 if(pSiSEnt) pSiSEnt->DisableDual = TRUE; 5586 goto my_error_1; 5587 } 5588#endif 5589#ifdef SISMERGED 5590 if(pSiS->MergedFB) { 5591 if(pSiS->MergedFBAuto) { 5592 xf86DrvMsg(pScrn->scrnIndex, X_INFO, mergednocrt1, mergeddisstr); 5593 } else { 5594 SISErrorLog(pScrn, mergednocrt1, mergeddisstr); 5595 } 5596 if(pSiS->CRT2pScrn) xfree(pSiS->CRT2pScrn); 5597 pSiS->CRT2pScrn = NULL; 5598 pSiS->MergedFB = FALSE; 5599 } 5600#endif 5601 pSiS->VBFlags |= VB_DISPMODE_SINGLE; 5602 /* No CRT1? Then we use the video overlay on CRT2 */ 5603 pSiS->XvOnCRT2 = TRUE; 5604 } else /* CRT1 and CRT2 - mirror or dual head ----- */ 5605#ifdef SISDUALHEAD 5606 if(pSiS->DualHeadMode) { 5607 pSiS->VBFlags |= (VB_DISPMODE_DUAL | DISPTYPE_CRT1); 5608 if(pSiS->VESA != -1) { 5609 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5610 "VESA option not used in Dual Head mode. VESA disabled.\n"); 5611 } 5612 if(pSiSEnt) pSiSEnt->DisableDual = FALSE; 5613 pSiS->VESA = 0; 5614 } else 5615#endif 5616#ifdef SISMERGED 5617 if(pSiS->MergedFB) { 5618 pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_CRT1); 5619 if(pSiS->VESA != -1) { 5620 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5621 "VESA option not used in MergedFB mode. VESA disabled.\n"); 5622 } 5623 pSiS->VESA = 0; 5624 } else 5625#endif 5626 pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_CRT1); 5627 } else { /* CRT1 only ------------------------------- */ 5628#ifdef SISDUALHEAD 5629 if(pSiS->DualHeadMode) { 5630 SISErrorLog(pScrn, 5631 "No CRT2 output selected or no bridge detected. " 5632 "Dual Head mode can't initialize.\n"); 5633 goto my_error_1; 5634 } 5635#endif 5636#ifdef SISMERGED 5637 if(pSiS->MergedFB) { 5638 if(pSiS->MergedFBAuto) { 5639 xf86DrvMsg(pScrn->scrnIndex, X_INFO, mergednocrt2, mergeddisstr); 5640 } else { 5641 SISErrorLog(pScrn, mergednocrt2, mergeddisstr); 5642 } 5643 if(pSiS->CRT2pScrn) xfree(pSiS->CRT2pScrn); 5644 pSiS->CRT2pScrn = NULL; 5645 pSiS->MergedFB = FALSE; 5646 } 5647#endif 5648 pSiS->VBFlags |= (VB_DISPMODE_SINGLE | DISPTYPE_CRT1); 5649 } 5650 5651 if((pSiS->VGAEngine == SIS_315_VGA) || (pSiS->VGAEngine == SIS_300_VGA)) { 5652 if((!pSiS->NoXvideo) && 5653 (!pSiS->hasTwoOverlays) && 5654 (!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY))) { 5655 xf86DrvMsg(pScrn->scrnIndex, from, 5656 "Using Xv overlay by default on CRT%d\n", 5657 pSiS->XvOnCRT2 ? 2 : 1); 5658 } 5659 } 5660 5661 /* Init ptrs for Save/Restore functions and calc MaxClock */ 5662 SISDACPreInit(pScrn); 5663 5664 /* ********** end of VBFlags setup ********** */ 5665 5666 /* VBFlags are initialized now. Back them up for SlaveMode modes. */ 5667 pSiS->VBFlags_backup = pSiS->VBFlags; 5668 5669 /* Backup CR32,36,37 (in order to write them back after a VT switch) */ 5670 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5671 inSISIDXREG(SISCR,0x32,pSiS->myCR32); 5672 inSISIDXREG(SISCR,0x36,pSiS->myCR36); 5673 inSISIDXREG(SISCR,0x37,pSiS->myCR37); 5674 } 5675 5676 /* Find out about paneldelaycompensation and evaluate option */ 5677#ifdef SISDUALHEAD 5678 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) { 5679#endif 5680 if(pSiS->VGAEngine == SIS_300_VGA) { 5681 5682 if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) { 5683 5684 /* Save the current PDC if the panel is used at the moment. 5685 * This seems by far the safest way to find out about it. 5686 * If the system is using an old version of sisfb, we can't 5687 * trust the pdc register value. If sisfb saved the pdc for 5688 * us, use it. 5689 */ 5690 if(pSiS->sisfbpdc != 0xff) { 5691 pSiS->SiS_Pr->PDC = pSiS->sisfbpdc; 5692 } else { 5693 if(!(pSiS->donttrustpdc)) { 5694 UChar tmp; 5695 inSISIDXREG(SISCR, 0x30, tmp); 5696 if(tmp & 0x20) { 5697 inSISIDXREG(SISPART1, 0x13, pSiS->SiS_Pr->PDC); 5698 } else { 5699 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5700 "Unable to detect LCD PanelDelayCompensation, LCD is not active\n"); 5701 } 5702 } else { 5703 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5704 "Unable to detect LCD PanelDelayCompensation, please update sisfb\n"); 5705 } 5706 } 5707 if(pSiS->SiS_Pr->PDC != -1) { 5708 pSiS->SiS_Pr->PDC &= 0x3c; 5709 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5710 "Detected LCD PanelDelayCompensation 0x%02x\n", 5711 pSiS->SiS_Pr->PDC); 5712 } 5713 5714 /* If we haven't been able to find out, use our other methods */ 5715 if(pSiS->SiS_Pr->PDC == -1) { 5716 int i=0; 5717 do { 5718 if(mypdctable[i].subsysVendor == PCI_SUB_VENDOR_ID(pSiS->PciInfo) && 5719 mypdctable[i].subsysCard == PCI_SUB_DEVICE_ID(pSiS->PciInfo)) { 5720 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5721 "PCI card/vendor identified for non-default PanelDelayCompensation\n"); 5722 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5723 "Vendor: %s, card: %s (ID %04x), PanelDelayCompensation: 0x%02x\n", 5724 mypdctable[i].vendorName, mypdctable[i].cardName, 5725 PCI_SUB_DEVICE_ID(pSiS->PciInfo), mypdctable[i].pdc); 5726 if(pSiS->PDC == -1) { 5727 pSiS->PDC = mypdctable[i].pdc; 5728 } else { 5729 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5730 "PanelDelayCompensation overruled by option\n"); 5731 } 5732 break; 5733 } 5734 i++; 5735 } while(mypdctable[i].subsysVendor != 0); 5736 } 5737 5738 if(pSiS->PDC != -1) { 5739 if(pSiS->BIOS) { 5740 if(pSiS->VBFlags2 & VB2_LVDS) { 5741 if(pSiS->BIOS[0x220] & 0x80) { 5742 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5743 "BIOS uses OEM LCD Panel Delay Compensation 0x%02x\n", 5744 pSiS->BIOS[0x220] & 0x3c); 5745 pSiS->BIOS[0x220] &= 0x7f; 5746 } 5747 } 5748 if(pSiS->VBFlags2 & (VB2_301B | VB2_302B)) { 5749 if(pSiS->BIOS[0x220] & 0x80) { 5750 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5751 "BIOS uses OEM LCD Panel Delay Compensation 0x%02x\n", 5752 ( (pSiS->VBLCDFlags & VB_LCD_1280x1024) ? 5753 pSiS->BIOS[0x223] : pSiS->BIOS[0x224] ) & 0x3c); 5754 pSiS->BIOS[0x220] &= 0x7f; 5755 } 5756 } 5757 } 5758 pSiS->SiS_Pr->PDC = (pSiS->PDC & 0x3c); 5759 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5760 "Using LCD Panel Delay Compensation 0x%02x\n", pSiS->SiS_Pr->PDC); 5761 } 5762 } 5763 5764 } /* SIS_300_VGA */ 5765 5766 if(pSiS->VGAEngine == SIS_315_VGA) { 5767 5768 UChar tmp, tmp2; 5769 inSISIDXREG(SISCR, 0x30, tmp); 5770 5771 /* Save the current PDC if the panel is used at the moment. */ 5772 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) { 5773 5774 if(pSiS->sisfbpdc != 0xff) { 5775 pSiS->SiS_Pr->PDC = pSiS->sisfbpdc; 5776 } 5777 if(pSiS->sisfbpdca != 0xff) { 5778 pSiS->SiS_Pr->PDCA = pSiS->sisfbpdca; 5779 } 5780 5781 if(!pSiS->donttrustpdc) { 5782 if((pSiS->sisfbpdc == 0xff) && (pSiS->sisfbpdca == 0xff)) { 5783 CARD16 tempa, tempb; 5784 inSISIDXREG(SISPART1,0x2d,tmp2); 5785 tempa = (tmp2 & 0xf0) >> 3; 5786 tempb = (tmp2 & 0x0f) << 1; 5787 inSISIDXREG(SISPART1,0x20,tmp2); 5788 tempa |= ((tmp2 & 0x40) >> 6); 5789 inSISIDXREG(SISPART1,0x35,tmp2); 5790 tempb |= ((tmp2 & 0x80) >> 7); 5791 inSISIDXREG(SISPART1,0x13,tmp2); 5792 if(!pSiS->ROM661New) { 5793 if((tmp2 & 0x04) || (tmp & 0x20)) { 5794 pSiS->SiS_Pr->PDCA = tempa; 5795 pSiS->SiS_Pr->PDC = tempb; 5796 } else { 5797 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5798 "Unable to detect PanelDelayCompensation, LCD is not active\n"); 5799 } 5800 } else { 5801 if(tmp2 & 0x04) { 5802 pSiS->SiS_Pr->PDCA = tempa; 5803 } else if(tmp & 0x20) { 5804 pSiS->SiS_Pr->PDC = tempb; 5805 } else { 5806 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5807 "Unable to detect PanelDelayCompensation, LCD is not active\n"); 5808 } 5809 } 5810 } 5811 } else { 5812 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5813 "Unable to detect PanelDelayCompensation, please update sisfb\n"); 5814 } 5815 if(pSiS->SiS_Pr->PDC != -1) { 5816 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5817 "Detected LCD PanelDelayCompensation 0x%02x (for LCD=CRT2)\n", 5818 pSiS->SiS_Pr->PDC); 5819 } 5820 if(pSiS->SiS_Pr->PDCA != -1) { 5821 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5822 "Detected LCD PanelDelayCompensation1 0x%02x (for LCD=CRT1)\n", 5823 pSiS->SiS_Pr->PDCA); 5824 } 5825 } 5826 5827 /* Let user override (for all bridges) */ 5828 if(pSiS->VBFlags2 & VB2_30xBLV) { 5829 if(pSiS->PDC != -1) { 5830 pSiS->SiS_Pr->PDC = pSiS->PDC & 0x1f; 5831 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5832 "Using LCD PanelDelayCompensation 0x%02x (for LCD=CRT2)\n", 5833 pSiS->SiS_Pr->PDC); 5834 } 5835 if(pSiS->PDCA != -1) { 5836 pSiS->SiS_Pr->PDCA = pSiS->PDCA & 0x1f; 5837 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5838 "Using LCD PanelDelayCompensation1 0x%02x (for LCD=CRT1)\n", 5839 pSiS->SiS_Pr->PDCA); 5840 } 5841 } 5842 5843 /* Read the current EMI (if not overruled) */ 5844 if(pSiS->VBFlags2 & VB2_SISEMIBRIDGE) { 5845 MessageType from = X_PROBED; 5846 if(pSiS->EMI != -1) { 5847 pSiS->SiS_Pr->EMI_30 = (pSiS->EMI >> 24) & 0x60; 5848 pSiS->SiS_Pr->EMI_31 = (pSiS->EMI >> 16) & 0xff; 5849 pSiS->SiS_Pr->EMI_32 = (pSiS->EMI >> 8) & 0xff; 5850 pSiS->SiS_Pr->EMI_33 = pSiS->EMI & 0xff; 5851 pSiS->SiS_Pr->HaveEMI = pSiS->SiS_Pr->HaveEMILCD = TRUE; 5852 pSiS->SiS_Pr->OverruleEMI = TRUE; 5853 from = X_CONFIG; 5854 } else if((pSiS->sisfbfound) && (pSiS->sisfb_haveemi)) { 5855 pSiS->SiS_Pr->EMI_30 = pSiS->sisfb_emi30; 5856 pSiS->SiS_Pr->EMI_31 = pSiS->sisfb_emi31; 5857 pSiS->SiS_Pr->EMI_32 = pSiS->sisfb_emi32; 5858 pSiS->SiS_Pr->EMI_33 = pSiS->sisfb_emi33; 5859 pSiS->SiS_Pr->HaveEMI = TRUE; 5860 if(pSiS->sisfb_haveemilcd) pSiS->SiS_Pr->HaveEMILCD = TRUE; 5861 pSiS->SiS_Pr->OverruleEMI = FALSE; 5862 } else { 5863 inSISIDXREG(SISPART4, 0x30, pSiS->SiS_Pr->EMI_30); 5864 inSISIDXREG(SISPART4, 0x31, pSiS->SiS_Pr->EMI_31); 5865 inSISIDXREG(SISPART4, 0x32, pSiS->SiS_Pr->EMI_32); 5866 inSISIDXREG(SISPART4, 0x33, pSiS->SiS_Pr->EMI_33); 5867 pSiS->SiS_Pr->HaveEMI = TRUE; 5868 if(tmp & 0x20) pSiS->SiS_Pr->HaveEMILCD = TRUE; 5869 pSiS->SiS_Pr->OverruleEMI = FALSE; 5870 } 5871 xf86DrvMsg(pScrn->scrnIndex, from, 5872 "302LV/302ELV: Using EMI 0x%02x%02x%02x%02x%s\n", 5873 pSiS->SiS_Pr->EMI_30,pSiS->SiS_Pr->EMI_31, 5874 pSiS->SiS_Pr->EMI_32,pSiS->SiS_Pr->EMI_33, 5875 pSiS->SiS_Pr->HaveEMILCD ? " (LCD)" : ""); 5876 } 5877 5878 } /* SIS_315_VGA */ 5879#ifdef SISDUALHEAD 5880 } 5881#endif 5882 5883 5884 /* In dual head mode, both heads (currently) share the maxxfbmem equally. 5885 * If memory sharing is done differently, the following has to be changed; 5886 * the other modules (eg. accel and Xv) use dhmOffset for hardware 5887 * pointer settings relative to VideoRAM start and won't need to be changed. 5888 * 5889 * Addendum: dhmoffset is also used for skipping the UMA area on SiS76x. 5890 */ 5891 5892 pSiS->dhmOffset = pSiS->FbBaseOffset; 5893 pSiS->FbAddress += pSiS->dhmOffset; 5894 5895#ifdef SISDUALHEAD 5896 if(pSiS->DualHeadMode) { 5897 pSiS->FbAddress = pSiS->realFbAddress; 5898 if(!pSiS->SecondHead) { 5899 /* ===== First head (always CRT2) ===== */ 5900 /* We use only half of the memory available */ 5901 pSiS->maxxfbmem /= 2; 5902 /* dhmOffset is 0 (or LFB-base for SiS76x UMA skipping) */ 5903 pSiS->FbAddress += pSiS->dhmOffset; 5904 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5905 "%dKB video RAM at 0x%lx available for master head (CRT2)\n", 5906 pSiS->maxxfbmem/1024, pSiS->FbAddress); 5907 } else { 5908 /* ===== Second head (always CRT1) ===== */ 5909 /* We use only half of the memory available */ 5910 pSiS->maxxfbmem /= 2; 5911 /* Initialize dhmOffset */ 5912 pSiS->dhmOffset += pSiS->maxxfbmem; 5913 /* Adapt FBAddress */ 5914 pSiS->FbAddress += pSiS->dhmOffset; 5915 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5916 "%dKB video RAM at 0x%lx available for slave head (CRT1)\n", 5917 pSiS->maxxfbmem/1024, pSiS->FbAddress); 5918 } 5919 } 5920#endif 5921 5922 /* Note: Do not use availMem for anything from now. Use 5923 * maxxfbmem instead. (availMem does not take dual head 5924 * mode into account.) 5925 */ 5926 5927 if(pSiS->FbBaseOffset) { 5928 /* Doubt that the DRM memory manager can deal 5929 * with a heap start of 0... 5930 */ 5931 pSiS->DRIheapstart = 16; 5932 pSiS->DRIheapend = pSiS->FbBaseOffset; 5933 } else { 5934 pSiS->DRIheapstart = pSiS->maxxfbmem; 5935 pSiS->DRIheapend = pSiS->availMem; 5936 } 5937#ifdef SISDUALHEAD 5938 if(pSiS->DualHeadMode) { 5939 pSiS->DRIheapstart = pSiS->DRIheapend = 0; 5940 } else 5941#endif 5942 if(pSiS->DRIheapstart >= pSiS->DRIheapend) { 5943#if 0 /* For future use */ 5944 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5945 "No memory for DRI heap. Please set the option \"MaxXFBMem\" to\n" 5946 "\tlimit the memory X should use and leave the rest to DRI\n"); 5947#endif 5948 pSiS->DRIheapstart = pSiS->DRIheapend = 0; 5949 } 5950 5951 /* Now for something completely different: DDC. 5952 * For 300 and 315/330/340 series, we provide our 5953 * own functions (in order to probe CRT2 as well) 5954 * If these fail, use the VBE. 5955 * All other chipsets will use VBE. No need to re-invent 5956 * the wheel there. 5957 */ 5958 5959 pSiS->pVbe = NULL; 5960 didddc2 = FALSE; 5961 5962 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5963 if(xf86LoadSubModule(pScrn, "ddc")) { 5964 int crtnum = 0; 5965 if((pMonitor = SiSDoPrivateDDC(pScrn, &crtnum))) { 5966 didddc2 = TRUE; 5967 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcsstr, crtnum); 5968 xf86PrintEDID(pMonitor); 5969 xf86SetDDCproperties(pScrn, pMonitor); 5970 pScrn->monitor->DDC = pMonitor; 5971 /* Now try to find out aspect ratio */ 5972 SiSFindAspect(pScrn, pMonitor, crtnum); 5973 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcestr, crtnum); 5974 } 5975 } 5976 } 5977 5978#ifdef SISDUALHEAD 5979 /* In dual head mode, probe DDC using VBE only for CRT1 (second head) */ 5980 if((pSiS->DualHeadMode) && (!didddc2) && (!pSiS->SecondHead)) { 5981 didddc2 = TRUE; 5982 } 5983#endif 5984 5985 if(!didddc2) { 5986 /* If CRT1 is off or LCDA, skip DDC via VBE */ 5987 if((pSiS->CRT1off) || (pSiS->VBFlags & CRT1_LCDA)) { 5988 didddc2 = TRUE; 5989 } 5990 } 5991 5992 /* Now (re-)load and initialize the DDC module */ 5993 if(!didddc2) { 5994 5995 if(xf86LoadSubModule(pScrn, "ddc")) { 5996 5997 /* Now load and initialize VBE module. */ 5998 SiS_LoadInitVBE(pScrn); 5999 6000 if(pSiS->pVbe) { 6001 if((pMonitor = vbeDoEDID(pSiS->pVbe,NULL))) { 6002 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 6003 "VBE CRT1 DDC monitor info:\n"); 6004 xf86SetDDCproperties(pScrn, xf86PrintEDID(pMonitor)); 6005 pScrn->monitor->DDC = pMonitor; 6006 /* Now try to find out aspect ratio */ 6007 SiSFindAspect(pScrn, pMonitor, 1); 6008 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 6009 "End of VBE CRT1 DDC monitor info\n"); 6010 } 6011 } else { 6012 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6013 "Failed to read DDC data\n"); 6014 } 6015 } 6016 } 6017 6018#ifdef SISMERGED 6019 if(pSiS->MergedFB) { 6020 pSiS->CRT2pScrn->monitor = xalloc(sizeof(MonRec)); 6021 if(pSiS->CRT2pScrn->monitor) { 6022 DisplayModePtr tempm = NULL, currentm = NULL, newm = NULL; 6023 memcpy(pSiS->CRT2pScrn->monitor, pScrn->monitor, sizeof(MonRec)); 6024 pSiS->CRT2pScrn->monitor->DDC = NULL; 6025 pSiS->CRT2pScrn->monitor->Modes = NULL; 6026 pSiS->CRT2pScrn->monitor->id = (char *)crt2monname; 6027 tempm = pScrn->monitor->Modes; 6028 while(tempm) { 6029 if(!(newm = xalloc(sizeof(DisplayModeRec)))) break; 6030 memcpy(newm, tempm, sizeof(DisplayModeRec)); 6031 if(!(newm->name = xalloc(strlen(tempm->name) + 1))) { 6032 xfree(newm); 6033 break; 6034 } 6035 strcpy(newm->name, tempm->name); 6036 if(!pSiS->CRT2pScrn->monitor->Modes) pSiS->CRT2pScrn->monitor->Modes = newm; 6037 if(currentm) { 6038 currentm->next = newm; 6039 newm->prev = currentm; 6040 } 6041 currentm = newm; 6042 tempm = tempm->next; 6043 } 6044 if(pSiS->CRT2HSync) { 6045 pSiS->CRT2pScrn->monitor->nHsync = 6046 SiSStrToRanges(pSiS->CRT2pScrn->monitor->hsync, pSiS->CRT2HSync, MAX_HSYNC); 6047 } 6048 if(pSiS->CRT2VRefresh) { 6049 pSiS->CRT2pScrn->monitor->nVrefresh = 6050 SiSStrToRanges(pSiS->CRT2pScrn->monitor->vrefresh, pSiS->CRT2VRefresh, MAX_VREFRESH); 6051 } 6052 if((pMonitor = SiSInternalDDC(pSiS->CRT2pScrn, 1))) { 6053 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcsstr, 2); 6054 xf86PrintEDID(pMonitor); 6055 xf86SetDDCproperties(pSiS->CRT2pScrn, pMonitor); 6056 pSiS->CRT2pScrn->monitor->DDC = pMonitor; 6057 /* Now try to find out aspect ratio */ 6058 SiSFindAspect(pScrn, pMonitor, 2); 6059 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcestr, 2); 6060 /* use DDC data if no ranges in config file */ 6061 if(!pSiS->CRT2HSync) { 6062 pSiS->CRT2pScrn->monitor->nHsync = 0; 6063 } 6064 if(!pSiS->CRT2VRefresh) { 6065 pSiS->CRT2pScrn->monitor->nVrefresh = 0; 6066 } 6067 } else { 6068 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 6069 "Failed to read DDC data for CRT2\n"); 6070 } 6071 } else { 6072 SISErrorLog(pScrn, "Failed to allocate memory for CRT2 monitor, %s.\n", 6073 mergeddisstr); 6074 if(pSiS->CRT2pScrn) xfree(pSiS->CRT2pScrn); 6075 pSiS->CRT2pScrn = NULL; 6076 pSiS->MergedFB = FALSE; 6077 } 6078 } 6079#endif 6080 6081 /* Copy our detected monitor gammas, part 1. Note that device redetection 6082 * is not supported in DHM, so there is no need to do that anytime later. 6083 */ 6084#ifdef SISDUALHEAD 6085 if(pSiS->DualHeadMode) { 6086 if(!pSiS->SecondHead) { 6087 /* CRT2: Got gamma for LCD or VGA2 */ 6088 pSiSEnt->CRT2VGAMonitorGamma = pSiS->CRT2VGAMonitorGamma; 6089 } else { 6090 /* CRT1: Got gamma for LCD or VGA */ 6091 pSiSEnt->CRT1VGAMonitorGamma = pSiS->CRT1VGAMonitorGamma; 6092 } 6093 if(pSiS->CRT2LCDMonitorGamma) pSiSEnt->CRT2LCDMonitorGamma = pSiS->CRT2LCDMonitorGamma; 6094 } 6095#endif 6096 6097 /* end of DDC */ 6098 6099 /* From here, we mainly deal with clocks and modes */ 6100 6101#ifdef SISMERGED 6102 if(pSiS->MergedFB) xf86DrvMsg(pScrn->scrnIndex, X_INFO, crtsetupstr, 1); 6103#endif 6104 6105 /* Set the min pixel clock */ 6106 pSiS->MinClock = 5000; 6107 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 6108 pSiS->MinClock = 10000; 6109 } 6110 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n", 6111 pSiS->MinClock / 1000); 6112 6113 /* If the user has specified ramdac speed in the config 6114 * file, we respect that setting. 6115 */ 6116 from = X_PROBED; 6117 if(pSiS->pEnt->device->dacSpeeds[0]) { 6118 int speed = 0; 6119 switch(pScrn->bitsPerPixel) { 6120 case 8: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP8]; 6121 break; 6122 case 16: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP16]; 6123 break; 6124 case 24: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP24]; 6125 break; 6126 case 32: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP32]; 6127 break; 6128 } 6129 if(speed == 0) pSiS->MaxClock = pSiS->pEnt->device->dacSpeeds[0]; 6130 else pSiS->MaxClock = speed; 6131 from = X_CONFIG; 6132 } 6133 xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n", 6134 pSiS->MaxClock / 1000); 6135 6136 /* 6137 * Setup the ClockRanges, which describe what clock ranges are available, 6138 * and what sort of modes they can be used for. 6139 */ 6140 clockRanges = xnfcalloc(sizeof(ClockRange), 1); 6141 clockRanges->next = NULL; 6142 clockRanges->minClock = pSiS->MinClock; 6143 clockRanges->maxClock = pSiS->MaxClock; 6144 clockRanges->clockIndex = -1; /* programmable */ 6145 clockRanges->interlaceAllowed = TRUE; 6146 clockRanges->doubleScanAllowed = TRUE; 6147 6148 /* 6149 * Since we have lots of built-in modes for 300/315/330/340 series 6150 * with vb support, we replace the given default mode list with our 6151 * own. In case the video bridge is to be used, we only allow other 6152 * modes if 6153 * -) vbtype is 301, 301B, 301C or 302B, and 6154 * -) crt2 device is not TV, and 6155 * -) crt1 is not LCDA, unless bridge is TMDS/LCDA capable (301C) 6156 */ 6157 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 6158 if(!(pSiS->noInternalModes)) { 6159 Bool acceptcustommodes = TRUE; /* Accept user modelines */ 6160 Bool includelcdmodes = TRUE; /* Include modes reported by DDC */ 6161 Bool isfordvi = FALSE; /* Is for digital DVI output */ 6162 Bool fakecrt2modes = FALSE; /* Fake some modes for CRT2 */ 6163 Bool IsForCRT2 = FALSE; 6164 if(pSiS->UseVESA) { 6165 acceptcustommodes = FALSE; 6166 includelcdmodes = FALSE; 6167 } 6168#ifdef SISDUALHEAD /* Dual head is static. Output devices will not change. */ 6169 if(pSiS->DualHeadMode) { 6170 if(!pSiS->SecondHead) { /* CRT2: */ 6171 if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 6172 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 6173 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA))) includelcdmodes = FALSE; 6174 if(pSiS->VBFlags & CRT2_LCD) isfordvi = TRUE; 6175 if(pSiS->VBFlags & CRT2_TV) acceptcustommodes = FALSE; 6176 } else { 6177 if(pSiS->VBFlags & (CRT2_TV|CRT2_LCD)) { 6178 acceptcustommodes = FALSE; 6179 includelcdmodes = FALSE; 6180 fakecrt2modes = TRUE; 6181 } 6182 } 6183 } else { 6184 acceptcustommodes = FALSE; 6185 includelcdmodes = FALSE; 6186 if(pSiS->VBFlags & (CRT2_TV|CRT2_LCD)) { 6187 fakecrt2modes = TRUE; 6188 } 6189 } 6190 clockRanges->interlaceAllowed = FALSE; 6191 IsForCRT2 = TRUE; 6192 } else { /* CRT1: */ 6193 if(pSiS->VBFlags & CRT1_LCDA) { 6194 if(!(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 6195 acceptcustommodes = FALSE; 6196 includelcdmodes = FALSE; 6197 fakecrt2modes = TRUE; 6198 /* Will handle i-lace in mode-switching code */ 6199 } else { 6200 isfordvi = TRUE; 6201 /* Don't allow i-lace modes */ 6202 clockRanges->interlaceAllowed = FALSE; 6203 } 6204 } else { 6205 includelcdmodes = FALSE; 6206 } 6207 } 6208 } else 6209#endif 6210#ifdef SISMERGED /* MergedFB mode is not static. Output devices may change. */ 6211 if(pSiS->MergedFB) { 6212 if(pSiS->VBFlags & CRT1_LCDA) { 6213 if(!(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 6214 acceptcustommodes = FALSE; 6215 includelcdmodes = FALSE; 6216 fakecrt2modes = TRUE; 6217 /* Will handle i-lace in mode-switching code */ 6218 } else { 6219 isfordvi = TRUE; 6220 /* Don't allow i-lace custom modes */ 6221 clockRanges->interlaceAllowed = FALSE; 6222 } 6223 } else { 6224 includelcdmodes = FALSE; 6225 } 6226 } else 6227#endif /* Mirror mode is not static. Output devices may change. */ 6228 if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 6229 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 6230 if(!(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 6231 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA))) includelcdmodes = FALSE; 6232 if(pSiS->VBFlags & CRT2_LCD) isfordvi = TRUE; 6233 } else { 6234 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA|CRT1_LCDA))) includelcdmodes = FALSE; 6235 if(pSiS->VBFlags & (CRT2_LCD|CRT1_LCDA)) isfordvi = TRUE; 6236 } 6237 if((!(pSiS->VBFlags & DISPTYPE_CRT1)) && (!(pSiS->VBFlags & CRT1_LCDA))) { 6238 IsForCRT2 = TRUE; 6239 } 6240 /* Allow user modes, even if CRT2 is TV. Will be filtered through ValidMode(); 6241 * leaving the user modes here might have the advantage that such a mode, if 6242 * it matches in resolution with a supported TV mode, allows us to drive eg. 6243 * non standard panels, and still permits switching to TV. This mode will be 6244 * "mapped" to a supported mode of identical resolution for TV. All this is 6245 * taken care of by ValidMode() and ModeInit()/PresetMode(). 6246 */ 6247 } else { 6248 if(pSiS->VBFlags & (CRT2_TV|CRT2_LCD)) { 6249 acceptcustommodes = FALSE; 6250 includelcdmodes = FALSE; 6251 if(!(pSiS->VBFlags & DISPTYPE_CRT1)) { 6252 fakecrt2modes = TRUE; 6253 IsForCRT2 = TRUE; 6254 } 6255 } 6256 } 6257 } else if(pSiS->VBFlags & (CRT2_ENABLE | CRT1_LCDA)) { 6258 acceptcustommodes = FALSE; 6259 includelcdmodes = FALSE; 6260 if((pSiS->VBFlags & CRT1_LCDA) || (!(pSiS->VBFlags & DISPTYPE_CRT1))) { 6261 fakecrt2modes = TRUE; 6262 IsForCRT2 = TRUE; 6263 } 6264 } else { 6265 includelcdmodes = FALSE; 6266 } 6267 /* Ignore interlace, mode switching code will handle this */ 6268 6269 pSiS->HaveCustomModes = FALSE; 6270 if(SiSMakeOwnModeList(pScrn, acceptcustommodes, includelcdmodes, 6271 isfordvi, &pSiS->HaveCustomModes, FALSE /*fakecrt2modes*/, IsForCRT2)) { 6272 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6273 "Replaced %s mode list with built-in modes\n", 6274 pSiS->HaveCustomModes ? "default" : "entire"); 6275 if(pSiS->VGAEngine == SIS_315_VGA) { 6276 int UseWide = pSiS->SiS_Pr->SiS_UseWide; 6277 if(IsForCRT2) UseWide = pSiS->SiS_Pr->SiS_UseWideCRT2; 6278 if((!IsForCRT2) || (pSiS->VBFlags2 & VB2_SISVGA2BRIDGE)) { 6279 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6280 "Using %s widescreen modes for CRT%d VGA devices\n", 6281 UseWide ? "real" : "fake", IsForCRT2 ? 2 : 1); 6282 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6283 "\tUse option \"ForceCRT%dVGAAspect\" to overrule\n", 6284 IsForCRT2 ? 2 : 1); 6285 } 6286 } 6287#ifdef TWDEBUG 6288 pScrn->modes = pScrn->monitor->Modes; 6289 xf86PrintModes(pScrn); 6290 pScrn->modes = NULL; 6291#endif 6292 } else { 6293 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 6294 "Building list of built-in modes failed, using server defaults\n"); 6295 } 6296 } else { 6297 pSiS->HaveCustomModes = TRUE; 6298 } 6299 } 6300 6301 /* Add our built-in hi-res and TV modes on the 6326 */ 6302 if(pSiS->Chipset == PCI_CHIP_SIS6326) { 6303 if(pScrn->bitsPerPixel == 8) { 6304 SiS6326SIS1600x1200_60Mode.next = pScrn->monitor->Modes; 6305 pScrn->monitor->Modes = &SiS6326SIS1600x1200_60Mode; 6306 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6307 "Adding mode \"SIS1600x1200-60\" (depth 8 only)\n"); 6308 } 6309 if(pScrn->bitsPerPixel <= 16) { 6310 SiS6326SIS1280x1024_75Mode.next = pScrn->monitor->Modes; 6311 pScrn->monitor->Modes = &SiS6326SIS1280x1024_75Mode; 6312 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6313 "Adding mode \"SIS1280x1024-75\" (depths 8, 15 and 16 only)\n"); 6314 } 6315 if((pSiS->SiS6326Flags & SIS6326_HASTV) && 6316 (pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 6317 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6318 "Adding %s TV modes to mode list:\n", 6319 (pSiS->SiS6326Flags & SIS6326_TVPAL) ? "PAL" : "NTSC"); 6320 if(pSiS->SiS6326Flags & SIS6326_TVPAL) { 6321 SiS6326PAL800x600Mode.next = pScrn->monitor->Modes; 6322 pScrn->monitor->Modes = &SiS6326PAL640x480Mode; 6323 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6324 "\t\"PAL800x600\" \"PAL800x600U\" \"PAL720x540\" \"PAL640x480\"\n"); 6325 } else { 6326 SiS6326NTSC640x480Mode.next = pScrn->monitor->Modes; 6327 pScrn->monitor->Modes = &SiS6326NTSC640x400Mode; 6328 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6329 "\t\"NTSC640x480\" \"NTSC640x480U\" \"NTSC640x400\"\n"); 6330 } 6331 } 6332 } 6333 6334 /* If there is no HSync or VRefresh data for the monitor, 6335 * derive it from DDC data. Essentially done by common layer 6336 * since 4.3.99.14, but this is not usable since it is done 6337 * too late (in ValidateModes()). 6338 * Addendum: I overrule the ranges now in any case unless 6339 * it would affect a CRT output device or DDC data is available. 6340 * Hence, for LCD(A) and TV, we always get proper ranges. This 6341 * is entirely harmless. However, option "NoOverruleRanges" will 6342 * disable this behavior. 6343 * This should "fix" the - by far - most common configuration 6344 * mistakes. 6345 */ 6346 6347 crt1freqoverruled = FALSE; 6348 6349 fromDDC = FALSE; 6350 if((pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6351 if((pScrn->monitor->nHsync <= 0) && (pScrn->monitor->DDC)) { 6352 SiSSetSyncRangeFromEdid(pScrn, 1); 6353 if(pScrn->monitor->nHsync > 0) { 6354 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subshstr, 6355#ifdef SISDUALHEAD 6356 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6357#endif 6358 pSiS->CRT1off ? 2 : 1); 6359 fromDDC = TRUE; 6360 } 6361 } 6362 if((pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6363 if(SiSAllowSyncOverride(pSiS, fromDDC)) { 6364 Bool HaveNoRanges = (pScrn->monitor->nHsync <= 0); 6365 /* Set sane ranges for LCD and TV 6366 * (our strict checking will filter out invalid ones anyway) 6367 */ 6368 if((crt1freqoverruled = CheckAndOverruleH(pScrn, pScrn->monitor))) { 6369 xf86DrvMsg(pScrn->scrnIndex, X_INFO, saneh, 6370 HaveNoRanges ? "missing" : "bogus", 6371#ifdef SISDUALHEAD 6372 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6373#endif 6374 pSiS->CRT1off ? 2 : 1); 6375 } 6376 } 6377 } 6378 } 6379 6380 fromDDC = FALSE; 6381 if((pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6382 if((pScrn->monitor->nVrefresh <= 0) && (pScrn->monitor->DDC)) { 6383 SiSSetSyncRangeFromEdid(pScrn, 0); 6384 if(pScrn->monitor->nVrefresh > 0) { 6385 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subsvstr, 6386#ifdef SISDUALHEAD 6387 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6388#endif 6389 pSiS->CRT1off ? 2 : 1); 6390 fromDDC = TRUE; 6391 } 6392 } 6393 if((pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6394 if(SiSAllowSyncOverride(pSiS, fromDDC)) { 6395 Bool HaveNoRanges = (pScrn->monitor->nVrefresh <= 0); 6396 /* Set sane ranges for LCD and TV */ 6397 if((crt1freqoverruled = CheckAndOverruleV(pScrn, pScrn->monitor))) { 6398 xf86DrvMsg(pScrn->scrnIndex, X_INFO, sanev, 6399 HaveNoRanges ? "missing" : "bogus", 6400#ifdef SISDUALHEAD 6401 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6402#endif 6403 pSiS->CRT1off ? 2 : 1); 6404 } 6405 } 6406 } 6407 } 6408 6409 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 6410 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6411 "\"Unknown reason\" in the following list means that the mode\n"); 6412 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6413 "is not supported on the chipset/bridge/current output device.\n"); 6414 } 6415 6416 /* 6417 * xf86ValidateModes will check that the mode HTotal and VTotal values 6418 * don't exceed the chipset's limit if pScrn->maxHValue and 6419 * pScrn->maxVValue are set. Since our SISValidMode() already takes 6420 * care of this, we don't worry about setting them here. 6421 */ 6422 6423 /* Select valid modes from those available */ 6424 /* 6425 * Assuming min pitch 256, min height 128 6426 */ 6427 { 6428 int minpitch, maxpitch, minheight, maxheight; 6429 pointer backupddc = pScrn->monitor->DDC; 6430 6431 minpitch = 256; 6432 minheight = 128; 6433 switch(pSiS->VGAEngine) { 6434 case SIS_OLD_VGA: 6435 case SIS_530_VGA: 6436 maxpitch = 2040; 6437 maxheight = 2048; 6438 break; 6439 case SIS_300_VGA: 6440 case SIS_315_VGA: 6441 maxpitch = 4088; 6442 maxheight = 4096; 6443 break; 6444 default: 6445 maxpitch = 2048; 6446 maxheight = 2048; 6447 break; 6448 } 6449 6450#ifdef SISMERGED 6451 pSiS->CheckForCRT2 = FALSE; 6452#endif 6453 6454 /* Suppress bogus DDC warning */ 6455 if(crt1freqoverruled) pScrn->monitor->DDC = NULL; 6456 6457 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 6458 pScrn->display->modes, clockRanges, NULL, 6459 minpitch, maxpitch, 6460 pScrn->bitsPerPixel * 8, 6461 minheight, maxheight, 6462 pScrn->display->virtualX, 6463 pScrn->display->virtualY, 6464 pSiS->maxxfbmem, 6465 LOOKUP_BEST_REFRESH); 6466 6467 pScrn->monitor->DDC = backupddc; 6468 } 6469 6470 if(i == -1) { 6471 SISErrorLog(pScrn, "xf86ValidateModes() error\n"); 6472 goto my_error_1; 6473 } 6474 6475 /* Check the virtual screen against the available memory */ 6476 { 6477 ULong memreq = (pScrn->virtualX * ((pScrn->bitsPerPixel + 7) / 8)) * pScrn->virtualY; 6478 6479 if(memreq > pSiS->maxxfbmem) { 6480 SISErrorLog(pScrn, 6481 "Virtual screen too big for memory; %ldK needed, %ldK available\n", 6482 memreq/1024, pSiS->maxxfbmem/1024); 6483 goto my_error_1; 6484 } 6485 } 6486 6487 /* Dual Head: 6488 * -) Go through mode list and mark all those modes as bad, 6489 * which are unsuitable for dual head mode. 6490 * -) Find the highest used pixelclock on the master head. 6491 */ 6492#ifdef SISDUALHEAD 6493 if((pSiS->DualHeadMode) && (!pSiS->SecondHead)) { 6494 6495 pSiSEnt->maxUsedClock = 0; 6496 6497 if((p = first = pScrn->modes)) { 6498 6499 do { 6500 6501 n = p->next; 6502 6503 /* Modes that require the bridge to operate in SlaveMode 6504 * are not suitable for Dual Head mode. 6505 */ 6506 if( (pSiS->VGAEngine == SIS_300_VGA) && 6507 ( (strcmp(p->name, "320x200") == 0) || 6508 (strcmp(p->name, "320x240") == 0) || 6509 (strcmp(p->name, "400x300") == 0) || 6510 (strcmp(p->name, "512x384") == 0) || 6511 (strcmp(p->name, "640x400") == 0) ) ) { 6512 p->status = MODE_BAD; 6513 xf86DrvMsg(pScrn->scrnIndex, X_INFO, notsuitablestr, p->name, "dual head"); 6514 } 6515 6516 /* Search for the highest clock on first head in order to calculate 6517 * max clock for second head (CRT1) 6518 */ 6519 if((p->status == MODE_OK) && (p->Clock > pSiSEnt->maxUsedClock)) { 6520 pSiSEnt->maxUsedClock = p->Clock; 6521 } 6522 6523 p = n; 6524 6525 } while (p != NULL && p != first); 6526 6527 } 6528 } 6529#endif 6530 6531 /* Prune the modes marked as invalid */ 6532 xf86PruneDriverModes(pScrn); 6533 6534 if(i == 0 || pScrn->modes == NULL) { 6535 SISErrorLog(pScrn, "No valid modes found - check VertRefresh/HorizSync\n"); 6536 goto my_error_1; 6537 } 6538 6539 xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 6540 6541 /* Set the current mode to the first in the list */ 6542 pScrn->currentMode = pScrn->modes; 6543 6544 /* Copy to CurrentLayout */ 6545 pSiS->CurrentLayout.mode = pScrn->currentMode; 6546 pSiS->CurrentLayout.displayWidth = pScrn->displayWidth; 6547 pSiS->CurrentLayout.displayHeight = pScrn->virtualY; 6548 6549#ifdef SISMERGED 6550 if(pSiS->MergedFB) { 6551 xf86DrvMsg(pScrn->scrnIndex, X_INFO, modesforstr, 1); 6552 } 6553#endif 6554 6555 /* Print the list of modes being used */ 6556 { 6557 Bool usemyprint = FALSE; 6558 6559#ifdef SISDUALHEAD 6560 if(pSiS->DualHeadMode) { 6561 if(pSiS->SecondHead) { 6562 if(pSiS->VBFlags & CRT1_LCDA) usemyprint = TRUE; 6563 } else { 6564 if(pSiS->VBFlags & (CRT2_LCD | CRT2_TV)) usemyprint = TRUE; 6565 } 6566 } else 6567#endif 6568#ifdef SISMERGED 6569 if(pSiS->MergedFB) { 6570 if(pSiS->VBFlags & CRT1_LCDA) usemyprint = TRUE; 6571 } else 6572#endif 6573 { 6574 if( (pSiS->VBFlags & (CRT2_LCD | CRT2_TV)) && 6575 (!(pSiS->VBFlags & DISPTYPE_DISP1)) ) 6576 usemyprint = TRUE; 6577 } 6578 6579 if(usemyprint) { 6580 SiSPrintModes(pScrn); 6581 } else { 6582 xf86PrintModes(pScrn); 6583 } 6584 } 6585 6586#ifdef SISMERGED 6587 if(pSiS->MergedFB) { 6588 Bool acceptcustommodes = TRUE; 6589 Bool includelcdmodes = TRUE; 6590 Bool isfordvi = FALSE; 6591 Bool fakecrt2modes = FALSE; 6592 6593 xf86DrvMsg(pScrn->scrnIndex, X_INFO, crtsetupstr, 2); 6594 6595 clockRanges->next = NULL; 6596 clockRanges->minClock = pSiS->MinClock; 6597 clockRanges->maxClock = SiSMemBandWidth(pSiS->CRT2pScrn, TRUE); 6598 clockRanges->clockIndex = -1; 6599 clockRanges->interlaceAllowed = FALSE; 6600 clockRanges->doubleScanAllowed = FALSE; 6601 if(pSiS->VGAEngine == SIS_315_VGA) { 6602 clockRanges->doubleScanAllowed = TRUE; 6603 } 6604 6605 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock for CRT2 is %d MHz\n", 6606 clockRanges->minClock / 1000); 6607 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Max pixel clock for CRT2 is %d MHz\n", 6608 clockRanges->maxClock / 1000); 6609 6610 if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 6611 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 6612 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA))) includelcdmodes = FALSE; 6613 if(pSiS->VBFlags & CRT2_LCD) isfordvi = TRUE; 6614 /* See above for a remark on handling CRT2 = TV */ 6615 } else { 6616 if(pSiS->VBFlags & (CRT2_LCD|CRT2_TV)) { 6617 includelcdmodes = FALSE; 6618 acceptcustommodes = FALSE; 6619 fakecrt2modes = TRUE; 6620 } 6621 } 6622 } else { 6623 includelcdmodes = FALSE; 6624 acceptcustommodes = FALSE; 6625 if(pSiS->VBFlags & (CRT2_LCD|CRT2_TV)) { 6626 fakecrt2modes = TRUE; 6627 } 6628 } 6629 6630 pSiS->HaveCustomModes2 = FALSE; 6631 if(!SiSMakeOwnModeList(pSiS->CRT2pScrn, acceptcustommodes, includelcdmodes, 6632 isfordvi, &pSiS->HaveCustomModes2, FALSE /* fakecrt2modes */, TRUE )) { 6633 6634 SISErrorLog(pScrn, "Building list of built-in modes for CRT2 failed, %s\n", 6635 mergeddisstr); 6636 SiSFreeCRT2Structs(pSiS); 6637 pSiS->MergedFB = FALSE; 6638 6639 } else { 6640 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6641 "Replaced %s mode list for CRT2 with built-in modes\n", 6642 pSiS->HaveCustomModes2 ? "default" : "entire"); 6643 if((pSiS->VGAEngine == SIS_315_VGA) && (pSiS->VBFlags2 & VB2_SISVGA2BRIDGE)) { 6644 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6645 "Using %s widescreen modes for CRT2 VGA devices\n", 6646 pSiS->SiS_Pr->SiS_UseWideCRT2 ? "real" : "fake"); 6647 } else pSiS->SiS_Pr->SiS_UseWideCRT2 = 0; 6648 } 6649 6650 } 6651 6652 if(pSiS->MergedFB) { 6653 6654 pointer backupddc; 6655 6656 crt2freqoverruled = FALSE; 6657 6658 fromDDC = FALSE; 6659 if((pSiS->CRT2pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6660 if((pSiS->CRT2pScrn->monitor->nHsync <= 0) && (pSiS->CRT2pScrn->monitor->DDC)) { 6661 SiSSetSyncRangeFromEdid(pSiS->CRT2pScrn, 1); 6662 if(pSiS->CRT2pScrn->monitor->nHsync > 0) { 6663 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subshstr, 2); 6664 fromDDC = TRUE; 6665 } 6666 } 6667 if((pSiS->CRT2pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6668 if( (pSiS->VBFlags & CRT2_TV) || 6669 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC)) ) { 6670 Bool HaveNoRanges = (pSiS->CRT2pScrn->monitor->nHsync <= 0); 6671 /* Set sane ranges for LCD and TV */ 6672 if((crt2freqoverruled = CheckAndOverruleH(pScrn, pSiS->CRT2pScrn->monitor))) { 6673 xf86DrvMsg(pScrn->scrnIndex, X_INFO, saneh, 6674 HaveNoRanges ? "missing" : "bogus", 2); 6675 } 6676 } 6677 } 6678 } 6679 6680 fromDDC = FALSE; 6681 if((pSiS->CRT2pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6682 if((pSiS->CRT2pScrn->monitor->nVrefresh <= 0) && (pSiS->CRT2pScrn->monitor->DDC)) { 6683 SiSSetSyncRangeFromEdid(pSiS->CRT2pScrn, 0); 6684 if(pSiS->CRT2pScrn->monitor->nVrefresh > 0) { 6685 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subsvstr, 2); 6686 fromDDC = TRUE; 6687 } 6688 } 6689 if((pSiS->CRT2pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6690 if( (pSiS->VBFlags & CRT2_TV) || 6691 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC)) ) { 6692 Bool HaveNoRanges = (pSiS->CRT2pScrn->monitor->nVrefresh <= 0); 6693 /* Set sane ranges for LCD and TV */ 6694 if((crt2freqoverruled = CheckAndOverruleV(pScrn, pSiS->CRT2pScrn->monitor))) { 6695 xf86DrvMsg(pScrn->scrnIndex, X_INFO, sanev, 6696 HaveNoRanges ? "missing" : "bogus", 2); 6697 } 6698 } 6699 } 6700 } 6701 6702 backupddc = pSiS->CRT2pScrn->monitor->DDC; 6703 6704 /* Suppress bogus DDC warning */ 6705 if(crt2freqoverruled) pSiS->CRT2pScrn->monitor->DDC = NULL; 6706 6707 pSiS->CheckForCRT2 = TRUE; 6708 6709 i = xf86ValidateModes(pSiS->CRT2pScrn, pSiS->CRT2pScrn->monitor->Modes, 6710 pSiS->CRT2pScrn->display->modes, clockRanges, 6711 NULL, 256, 4088, 6712 pSiS->CRT2pScrn->bitsPerPixel * 8, 128, 4096, 6713 pScrn->display->virtualX ? pScrn->virtualX : 0, 6714 pScrn->display->virtualY ? pScrn->virtualY : 0, 6715 pSiS->maxxfbmem, 6716 LOOKUP_BEST_REFRESH); 6717 6718 pSiS->CheckForCRT2 = FALSE; 6719 pSiS->CRT2pScrn->monitor->DDC = backupddc; 6720 6721 if(i == -1) { 6722 SISErrorLog(pScrn, "xf86ValidateModes() error, %s.\n", mergeddisstr); 6723 SiSFreeCRT2Structs(pSiS); 6724 pSiS->MergedFB = FALSE; 6725 } 6726 6727 } 6728 6729 if(pSiS->MergedFB) { 6730 6731 if((p = first = pSiS->CRT2pScrn->modes)) { 6732 do { 6733 n = p->next; 6734 if( (pSiS->VGAEngine == SIS_300_VGA) && 6735 ( (strcmp(p->name, "320x200") == 0) || 6736 (strcmp(p->name, "320x240") == 0) || 6737 (strcmp(p->name, "400x300") == 0) || 6738 (strcmp(p->name, "512x384") == 0) || 6739 (strcmp(p->name, "640x400") == 0) ) ) { 6740 p->status = MODE_BAD; 6741 xf86DrvMsg(pScrn->scrnIndex, X_INFO, notsuitablestr, p->name, "MergedFB"); 6742 } 6743 p = n; 6744 } while (p != NULL && p != first); 6745 } 6746 6747 xf86PruneDriverModes(pSiS->CRT2pScrn); 6748 6749 if(i == 0 || pSiS->CRT2pScrn->modes == NULL) { 6750 SISErrorLog(pScrn, "No valid modes found for CRT2; %s\n", mergeddisstr); 6751 SiSFreeCRT2Structs(pSiS); 6752 pSiS->MergedFB = FALSE; 6753 } 6754 6755 } 6756 6757 if(pSiS->MergedFB) { 6758 6759 xf86SetCrtcForModes(pSiS->CRT2pScrn, INTERLACE_HALVE_V); 6760 6761 xf86DrvMsg(pScrn->scrnIndex, X_INFO, modesforstr, 2); 6762 6763 if(pSiS->VBFlags & (CRT2_LCD | CRT2_TV)) { 6764 SiSPrintModes(pSiS->CRT2pScrn); 6765 } else { 6766 xf86PrintModes(pSiS->CRT2pScrn); 6767 } 6768 6769 pSiS->CRT1Modes = pScrn->modes; 6770 pSiS->CRT1CurrentMode = pScrn->currentMode; 6771 6772 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MergedFB: Generating mode list\n"); 6773 6774 pScrn->modes = SiSGenerateModeList(pScrn, pSiS->MetaModes, 6775 pSiS->CRT1Modes, pSiS->CRT2pScrn->modes, 6776 pSiS->CRT2Position); 6777 6778 if(!pScrn->modes) { 6779 6780 SISErrorLog(pScrn, "Failed to parse MetaModes or no modes found. %s.\n", 6781 mergeddisstr); 6782 SiSFreeCRT2Structs(pSiS); 6783 pScrn->modes = pSiS->CRT1Modes; 6784 pSiS->CRT1Modes = NULL; 6785 pSiS->MergedFB = FALSE; 6786 6787 } 6788 6789 } 6790 6791 if(pSiS->MergedFB) { 6792 6793 /* If no virtual dimension was given by the user, 6794 * calculate a sane one now. Adapts pScrn->virtualX, 6795 * pScrn->virtualY and pScrn->displayWidth. 6796 */ 6797 SiSRecalcDefaultVirtualSize(pScrn); 6798 6799 pScrn->modes = pScrn->modes->next; /* We get the last from GenerateModeList(), skip to first */ 6800 pScrn->currentMode = pScrn->modes; 6801 6802 /* Update CurrentLayout */ 6803 pSiS->CurrentLayout.mode = pScrn->currentMode; 6804 pSiS->CurrentLayout.displayWidth = pScrn->displayWidth; 6805 pSiS->CurrentLayout.displayHeight = pScrn->virtualY; 6806 6807 } 6808#endif 6809 6810 /* Set display resolution */ 6811#ifdef SISMERGED 6812 if(pSiS->MergedFB) { 6813 SiSMergedFBSetDpi(pScrn, pSiS->CRT2pScrn, pSiS->CRT2Position); 6814 } else 6815#endif 6816 xf86SetDpi(pScrn, 0, 0); 6817 6818 /* Load fb module */ 6819 switch(pScrn->bitsPerPixel) { 6820 case 8: 6821 case 16: 6822 case 24: 6823 case 32: 6824 if(!xf86LoadSubModule(pScrn, "fb")) { 6825 SISErrorLog(pScrn, "Failed to load fb module"); 6826 goto my_error_1; 6827 } 6828 break; 6829 default: 6830 SISErrorLog(pScrn, "Unsupported framebuffer bpp (%d)\n", pScrn->bitsPerPixel); 6831 goto my_error_1; 6832 } 6833 6834 /* Load XAA/EXA (if needed) */ 6835 if(!pSiS->NoAccel) { 6836#ifdef SIS_USE_XAA 6837 if(!pSiS->useEXA) { 6838 if (!xf86LoadSubModule(pScrn, "xaa")) { 6839 SISErrorLog(pScrn, "Could not load xaa module\n"); 6840 goto my_error_1; 6841 } 6842 } 6843#endif 6844#ifdef SIS_USE_EXA 6845 if(pSiS->useEXA) { 6846 XF86ModReqInfo req; 6847 int errmaj, errmin; 6848 6849 memset(&req, 0, sizeof(req)); 6850 req.majorversion = 2; 6851 req.minorversion = 0; 6852 if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, &req, 6853 &errmaj, &errmin)) { 6854 LoaderErrorMsg(NULL, "exa", errmaj, errmin); 6855 goto my_error_1; 6856 } 6857 } 6858#endif 6859 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D acceleration enabled\n"); 6860 } 6861 6862 /* Load shadowfb (if needed) */ 6863 if(pSiS->ShadowFB) { 6864 if(!xf86LoadSubModule(pScrn, "shadowfb")) { 6865 SISErrorLog(pScrn, "Could not load shadowfb module\n"); 6866 goto my_error_1; 6867 } 6868 } 6869 6870 /* Load the dri and glx modules if requested. */ 6871#ifdef XF86DRI 6872 if(pSiS->loadDRI) { 6873 if(!xf86LoaderCheckSymbol("DRIScreenInit")) { 6874 if(xf86LoadSubModule(pScrn, "dri")) { 6875 if(!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) { 6876 if(!xf86LoadSubModule(pScrn, "glx")) { 6877 SISErrorLog(pScrn, "Failed to load glx module\n"); 6878 } 6879 } 6880 } else { 6881 SISErrorLog(pScrn, "Failed to load dri module\n"); 6882 } 6883 } 6884 } 6885#endif 6886 6887 /* Now load and initialize VBE module for VESA mode switching */ 6888 pSiS->UseVESA = 0; 6889 if(pSiS->VESA == 1) { 6890 SiS_LoadInitVBE(pScrn); 6891 if(pSiS->pVbe) { 6892 VbeInfoBlock *vbe; 6893 if((vbe = VBEGetVBEInfo(pSiS->pVbe))) { 6894 pSiS->vesamajor = (unsigned)(vbe->VESAVersion >> 8); 6895 pSiS->vesaminor = vbe->VESAVersion & 0xff; 6896 SiSBuildVesaModeList(pScrn, pSiS->pVbe, vbe); 6897 VBEFreeVBEInfo(vbe); 6898 pSiS->UseVESA = 1; 6899 } else { 6900 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 6901 "Failed to read VBE Info Block\n"); 6902 } 6903 } 6904 if(pSiS->UseVESA == 0) { 6905 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 6906 "VESA mode switching disabled.\n"); 6907 } 6908 } 6909 6910 if(pSiS->pVbe) { 6911 vbeFree(pSiS->pVbe); 6912 pSiS->pVbe = NULL; 6913 } 6914 6915#ifdef SISDUALHEAD 6916 xf86SetPrimInitDone(pScrn->entityList[0]); 6917#endif 6918 6919 sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); 6920 6921 if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); 6922 pSiS->pInt = NULL; 6923 6924 if(pSiS->VGAEngine == SIS_315_VGA) { 6925 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTXVGAMMA1; 6926 } 6927 6928#ifdef SISDUALHEAD 6929 if(pSiS->DualHeadMode) { 6930 pSiS->SiS_SD_Flags |= SiS_SD_ISDUALHEAD; 6931 if(pSiS->SecondHead) pSiS->SiS_SD_Flags |= SiS_SD_ISDHSECONDHEAD; 6932 else pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTXVGAMMA1); 6933#ifdef PANORAMIX 6934 if(!noPanoramiXExtension) { 6935 pSiS->SiS_SD_Flags |= SiS_SD_ISDHXINERAMA; 6936 /* pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTXVGAMMA1); */ 6937 } 6938#endif 6939 } 6940#endif 6941 6942#ifdef SISMERGED 6943 if(pSiS->MergedFB) pSiS->SiS_SD_Flags |= SiS_SD_ISMERGEDFB; 6944#endif 6945 6946 /* Try to determine if this is a laptop */ 6947 /* (only used for SiSCtrl visualisations) */ 6948 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPLTFLAG; 6949 pSiS->SiS_SD2_Flags &= ~SiS_SD2_ISLAPTOP; 6950 if(pSiS->detectedCRT2Devices & CRT2_LCD) { 6951 if(pSiS->VBFlags2 & (VB2_SISLVDSBRIDGE | VB2_LVDS | VB2_30xBDH)) { 6952 /* 1. By bridge type: LVDS in 99% of all cases; 6953 * exclude unusual setups like Barco projectors 6954 * and parallel flat panels. TODO: Exclude 6955 * Sony W1, V1. 6956 */ 6957 if((pSiS->SiS_Pr->SiS_CustomT != CUT_BARCO1366) && 6958 (pSiS->SiS_Pr->SiS_CustomT != CUT_BARCO1024) && 6959 (pSiS->SiS_Pr->SiS_CustomT != CUT_PANEL848) && 6960 (pSiS->SiS_Pr->SiS_CustomT != CUT_PANEL856) && 6961 (pSiS->SiS_Pr->SiS_CustomT != CUT_AOP8060) && 6962 ( (pSiS->ChipType != SIS_550) || 6963 (!pSiS->DSTN && !pSiS->FSTN) ) ) { 6964 pSiS->SiS_SD2_Flags |= SiS_SD2_ISLAPTOP; 6965 } 6966 } else if((pSiS->VBFlags2 & (VB2_301 | VB2_301C)) && 6967 (pSiS->VBLCDFlags & (VB_LCD_1280x960 | 6968 VB_LCD_1400x1050 | 6969 VB_LCD_1024x600 | 6970 VB_LCD_1280x800 | 6971 VB_LCD_1280x854))) { 6972 /* 2. By (odd) LCD resolutions on TMDS bridges 6973 * (eg Averatec). TODO: Exclude IBM Netvista. 6974 */ 6975 pSiS->SiS_SD2_Flags |= SiS_SD2_ISLAPTOP; 6976 } 6977 } 6978 6979 if(pSiS->enablesisctrl) pSiS->SiS_SD_Flags |= SiS_SD_ENABLED; 6980 6981 pSiS->currentModeLast = pScrn->currentMode; 6982 pSiS->VBFlagsInit = pSiS->VBFlags; 6983 6984 return TRUE; 6985 6986 /* ---- */ 6987 6988my_error_1: 6989 sisRestoreExtRegisterLock(pSiS, srlockReg, crlockReg); 6990my_error_0: 6991#ifdef SISDUALHEAD 6992 if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; 6993#endif 6994 if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); 6995 pSiS->pInt = NULL; 6996 SISFreeRec(pScrn); 6997 return FALSE; 6998} 6999 7000/* 7001 * Map I/O port area for non-PC platforms 7002 */ 7003#ifdef SIS_NEED_MAP_IOP 7004static Bool 7005SISMapIOPMem(ScrnInfoPtr pScrn) 7006{ 7007 SISPtr pSiS = SISPTR(pScrn); 7008#ifdef SISDUALHEAD 7009 SISEntPtr pSiSEnt = pSiS->entityPrivate; 7010 7011 if(pSiS->DualHeadMode) { 7012 pSiSEnt->MapCountIOPBase++; 7013 if(!(pSiSEnt->IOPBase)) { 7014 /* Only map if not mapped previously */ 7015#ifndef XSERVER_LIBPCIACCESS 7016 pSiSEnt->IOPBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7017 pSiS->PciTag, pSiS->IOPAddress, 128); 7018#else 7019 { 7020 void **result = (void **)&pSiSEnt->IOPBase; 7021 int err = pci_device_map_range(pSiS->PciInfo, 7022 pSiS->IOPAddress, 7023 128, 7024 PCI_DEV_MAP_FLAG_WRITABLE, 7025 result); 7026 7027 if (err) { 7028 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7029 "Unable to map IO aperture. %s (%d)\n", 7030 strerror (err), err); 7031 } 7032 } 7033#endif 7034 } 7035 pSiS->IOPBase = pSiSEnt->IOPBase; 7036 } else 7037#endif 7038#ifndef XSERVER_LIBPCIACCESS 7039 pSiS->IOPBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7040 pSiS->PciTag, pSiS->IOPAddress, 128); 7041#else 7042 { 7043 void **result = (void **)&pSiS->IOPBase; 7044 int err = pci_device_map_range(pSiS->PciInfo, 7045 pSiS->IOPAddress, 7046 128, 7047 PCI_DEV_MAP_FLAG_WRITABLE, 7048 result); 7049 7050 if (err) { 7051 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7052 "Unable to map IO aperture. %s (%d)\n", 7053 strerror (err), err); 7054 } 7055 } 7056#endif 7057 if(pSiS->IOPBase == NULL) { 7058 SISErrorLog(pScrn, "Could not map I/O port area\n"); 7059 return FALSE; 7060 } 7061 7062 return TRUE; 7063} 7064 7065static Bool 7066SISUnmapIOPMem(ScrnInfoPtr pScrn) 7067{ 7068 SISPtr pSiS = SISPTR(pScrn); 7069#ifdef SISDUALHEAD 7070 SISEntPtr pSiSEnt = pSiS->entityPrivate;; 7071#endif 7072 7073/* In dual head mode, we must not unmap if the other head still 7074 * assumes memory as mapped 7075 */ 7076#ifdef SISDUALHEAD 7077 if(pSiS->DualHeadMode) { 7078 if(pSiSEnt->MapCountIOPBase) { 7079 pSiSEnt->MapCountIOPBase--; 7080 if((pSiSEnt->MapCountIOPBase == 0) || (pSiSEnt->forceUnmapIOPBase)) { 7081 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOPBase, 2048); 7082 pSiSEnt->IOPBase = NULL; 7083 pSiSEnt->MapCountIOPBase = 0; 7084 pSiSEnt->forceUnmapIOPBase = FALSE; 7085 } 7086 pSiS->IOPBase = NULL; 7087 } 7088 } else { 7089#endif 7090 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOPBase, 2048); 7091 pSiS->IOPBase = NULL; 7092#ifdef SISDUALHEAD 7093 } 7094#endif 7095 return TRUE; 7096} 7097#endif 7098 7099/* 7100 * Map the framebuffer and MMIO memory 7101 */ 7102 7103static Bool 7104SISMapMem(ScrnInfoPtr pScrn) 7105{ 7106 SISPtr pSiS = SISPTR(pScrn); 7107 int mmioFlags = VIDMEM_MMIO; 7108#ifdef SISDUALHEAD 7109 SISEntPtr pSiSEnt = pSiS->entityPrivate; 7110#endif 7111 7112 /* 7113 * Map IO registers to virtual address space 7114 * (For Alpha, we need to map SPARSE memory, since we need 7115 * byte/short access.) 7116 */ 7117#if defined(__alpha__) 7118 mmioFlags |= VIDMEM_SPARSE; 7119#endif 7120 7121#ifdef SISDUALHEAD 7122 if(pSiS->DualHeadMode) { 7123 pSiSEnt->MapCountIOBase++; 7124 if(!(pSiSEnt->IOBase)) { 7125 /* Only map if not mapped previously */ 7126#ifndef XSERVER_LIBPCIACCESS 7127 pSiSEnt->IOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, 7128 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7129#else 7130 void **result = (void **)&pSiSEnt->IOBase; 7131 int err = pci_device_map_range(pSiS->PciInfo, 7132 pSiS->IOAddress, 7133 (pSiS->mmioSize * 1024), 7134 PCI_DEV_MAP_FLAG_WRITABLE, 7135 result); 7136 7137 if (err) { 7138 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7139 "Unable to map IO aperture. %s (%d)\n", 7140 strerror (err), err); 7141 } 7142#endif 7143 } 7144 pSiS->IOBase = pSiSEnt->IOBase; 7145 } else 7146#endif 7147#ifndef XSERVER_LIBPCIACCESS 7148 pSiS->IOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, 7149 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7150#else 7151 { 7152 void **result = (void **)&pSiS->IOBase; 7153 int err = pci_device_map_range(pSiS->PciInfo, 7154 pSiS->IOAddress, 7155 (pSiS->mmioSize * 1024), 7156 PCI_DEV_MAP_FLAG_WRITABLE, 7157 result); 7158 7159 if (err) { 7160 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7161 "Unable to map IO aperture. %s (%d)\n", 7162 strerror (err), err); 7163 } 7164 } 7165#endif 7166 7167 if(pSiS->IOBase == NULL) { 7168 SISErrorLog(pScrn, "Could not map MMIO area\n"); 7169 return FALSE; 7170 } 7171 7172#ifdef __alpha__ 7173 /* 7174 * for Alpha, we need to map DENSE memory as well, for 7175 * setting CPUToScreenColorExpandBase. 7176 */ 7177#ifdef SISDUALHEAD 7178 if(pSiS->DualHeadMode) { 7179 pSiSEnt->MapCountIOBaseDense++; 7180 if(!(pSiSEnt->IOBaseDense)) { 7181 /* Only map if not mapped previously */ 7182#ifndef XSERVER_LIBPCIACCESS 7183 pSiSEnt->IOBaseDense = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7184 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7185#else 7186 void **result = (void **)&pSiSEnt->IOBaseDense; 7187 int err = pci_device_map_range(pSiS->PciInfo, 7188 pSiS->IOAddress, 7189 (pSiS->mmioSize * 1024), 7190 PCI_DEV_MAP_FLAG_WRITABLE, 7191 result); 7192 7193 if (err) { 7194 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7195 "Unable to map IO dense aperture. %s (%d)\n", 7196 strerror (err), err); 7197 } 7198#endif /* XSERVER_LIBPCIACCESS */ 7199 } 7200 pSiS->IOBaseDense = pSiSEnt->IOBaseDense; 7201 } else { 7202#endif /* SISDUALHEAD */ 7203#ifndef XSERVER_LIBPCIACCESS 7204 pSiS->IOBaseDense = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7205 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7206#else 7207 void **result = (void **)&pSiS->IOBaseDense; 7208 int err = pci_device_map_range(pSiS->PciInfo, 7209 pSiS->IOAddress, 7210 (pSiS->mmioSize * 1024), 7211 PCI_DEV_MAP_FLAG_WRITABLE, 7212 result); 7213 7214 if (err) { 7215 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7216 "Unable to map IO dense aperture. %s (%d)\n", 7217 strerror (err), err); 7218 } 7219#endif /* XSERVER_LIBPCIACCESS */ 7220#ifdef SISDUALHEAD 7221 } 7222#endif 7223 if(pSiS->IOBaseDense == NULL) { 7224 SISErrorLog(pScrn, "Could not map MMIO dense area\n"); 7225 return FALSE; 7226 } 7227#endif /* __alpha__ */ 7228 7229#ifdef SISDUALHEAD 7230 if(pSiS->DualHeadMode) { 7231 pSiSEnt->MapCountFbBase++; 7232 if(!(pSiSEnt->FbBase)) { 7233 /* Only map if not mapped previously */ 7234#ifndef XSERVER_LIBPCIACCESS 7235 pSiSEnt->FbBase = pSiSEnt->RealFbBase = 7236 xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 7237 pSiS->PciTag, (ULong)pSiS->realFbAddress, 7238 pSiS->FbMapSize); 7239#else 7240 int err = pci_device_map_range(pSiS->PciInfo, 7241 (ULong)pSiS->realFbAddress, 7242 pSiS->FbMapSize, 7243 PCI_DEV_MAP_FLAG_WRITABLE | 7244 PCI_DEV_MAP_FLAG_WRITE_COMBINE, 7245 (void *)&pSiSEnt->FbBase); 7246 if (err) { 7247 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7248 "Unable to map FB aperture. %s (%d)\n", 7249 strerror (err), err); 7250 return FALSE; 7251 } 7252 pSiSEnt->RealFbBase = pSiSEnt->FbBase; 7253#endif 7254 } 7255 pSiS->FbBase = pSiS->RealFbBase = pSiSEnt->FbBase; 7256 /* Adapt FbBase (for DHM and SiS76x UMA skipping; dhmOffset is 0 otherwise) */ 7257 pSiS->FbBase += pSiS->dhmOffset; 7258 } else { 7259#endif 7260 7261#ifndef XSERVER_LIBPCIACCESS 7262 pSiS->FbBase = pSiS->RealFbBase = 7263 xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 7264 pSiS->PciTag, (ULong)pSiS->realFbAddress, 7265 pSiS->FbMapSize); 7266#else 7267 int err = pci_device_map_range(pSiS->PciInfo, 7268 (ULong)pSiS->realFbAddress, 7269 pSiS->FbMapSize, 7270 PCI_DEV_MAP_FLAG_WRITABLE | 7271 PCI_DEV_MAP_FLAG_WRITE_COMBINE, 7272 (void *)&pSiS->FbBase); 7273 if (err) { 7274 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7275 "Unable to map FB aperture. %s (%d)\n", 7276 strerror (err), err); 7277 return FALSE; 7278 } 7279 pSiS->RealFbBase = pSiS->FbBase; 7280#endif 7281 pSiS->FbBase += pSiS->dhmOffset; 7282 7283#ifdef SISDUALHEAD 7284 } 7285#endif 7286 7287 if(pSiS->FbBase == NULL) { 7288 SISErrorLog(pScrn, "Could not map framebuffer area\n"); 7289 return FALSE; 7290 } 7291 7292#ifdef TWDEBUG 7293 xf86DrvMsg(0, 0, "Framebuffer mapped to %p\n", pSiS->FbBase); 7294#endif 7295 7296 return TRUE; 7297} 7298 7299 7300/* 7301 * Unmap the framebuffer and MMIO memory. 7302 */ 7303 7304static Bool 7305SISUnmapMem(ScrnInfoPtr pScrn) 7306{ 7307 SISPtr pSiS = SISPTR(pScrn); 7308#ifdef SISDUALHEAD 7309 SISEntPtr pSiSEnt = pSiS->entityPrivate; 7310#endif 7311 7312/* In dual head mode, we must not unmap if the other head still 7313 * assumes memory as mapped 7314 */ 7315#ifdef SISDUALHEAD 7316 if(pSiS->DualHeadMode) { 7317 if(pSiSEnt->MapCountIOBase) { 7318 pSiSEnt->MapCountIOBase--; 7319 if((pSiSEnt->MapCountIOBase == 0) || (pSiSEnt->forceUnmapIOBase)) { 7320 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOBase, (pSiS->mmioSize * 1024)); 7321 pSiSEnt->IOBase = NULL; 7322 pSiSEnt->MapCountIOBase = 0; 7323 pSiSEnt->forceUnmapIOBase = FALSE; 7324 } 7325 pSiS->IOBase = NULL; 7326 } 7327#ifdef __alpha__ 7328 if(pSiSEnt->MapCountIOBaseDense) { 7329 pSiSEnt->MapCountIOBaseDense--; 7330 if((pSiSEnt->MapCountIOBaseDense == 0) || (pSiSEnt->forceUnmapIOBaseDense)) { 7331 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOBaseDense, (pSiS->mmioSize * 1024)); 7332 pSiSEnt->IOBaseDense = NULL; 7333 pSiSEnt->MapCountIOBaseDense = 0; 7334 pSiSEnt->forceUnmapIOBaseDense = FALSE; 7335 } 7336 pSiS->IOBaseDense = NULL; 7337 } 7338#endif /* __alpha__ */ 7339 if(pSiSEnt->MapCountFbBase) { 7340 pSiSEnt->MapCountFbBase--; 7341 if((pSiSEnt->MapCountFbBase == 0) || (pSiSEnt->forceUnmapFbBase)) { 7342 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->RealFbBase, pSiS->FbMapSize); 7343 pSiSEnt->FbBase = pSiSEnt->RealFbBase = NULL; 7344 pSiSEnt->MapCountFbBase = 0; 7345 pSiSEnt->forceUnmapFbBase = FALSE; 7346 7347 } 7348 pSiS->FbBase = pSiS->RealFbBase = NULL; 7349 } 7350 } else { 7351#endif 7352 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOBase, (pSiS->mmioSize * 1024)); 7353 pSiS->IOBase = NULL; 7354#ifdef __alpha__ 7355 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOBaseDense, (pSiS->mmioSize * 1024)); 7356 pSiS->IOBaseDense = NULL; 7357#endif 7358 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->RealFbBase, pSiS->FbMapSize); 7359 pSiS->FbBase = pSiS->RealFbBase = NULL; 7360#ifdef SISDUALHEAD 7361 } 7362#endif 7363 return TRUE; 7364} 7365 7366/* 7367 * This function saves the video state. 7368 */ 7369static void 7370SISSave(ScrnInfoPtr pScrn) 7371{ 7372 SISPtr pSiS = SISPTR(pScrn); 7373 SISRegPtr sisReg; 7374 int flags; 7375 7376#ifdef SISDUALHEAD 7377 /* We always save master & slave */ 7378 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 7379#endif 7380 7381 sisReg = &pSiS->SavedReg; 7382 7383 if( ((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) && 7384 ((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (SiSBridgeIsInSlaveMode(pScrn))) ) { 7385 SiSVGASave(pScrn, sisReg, SISVGA_SR_CMAP | SISVGA_SR_MODE); 7386#ifdef SIS_PC_PLATFORM 7387 if(pSiS->VGAMemBase) { 7388 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO+0x30); 7389 SiSSetLVDSetc(pSiS->SiS_Pr, 0); 7390 SiS_GetVBType(pSiS->SiS_Pr); 7391 SiS_DisableBridge(pSiS->SiS_Pr); 7392 SiSVGASave(pScrn, sisReg, SISVGA_SR_FONTS); 7393 SiS_EnableBridge(pSiS->SiS_Pr); 7394 } 7395#endif 7396 } else { 7397 flags = SISVGA_SR_CMAP | SISVGA_SR_MODE; 7398#ifdef SIS_PC_PLATFORM 7399 if(pSiS->VGAMemBase) flags |= SISVGA_SR_FONTS; 7400#endif 7401 SiSVGASave(pScrn, sisReg, flags); 7402 } 7403 7404 sisSaveUnlockExtRegisterLock(pSiS, &sisReg->sisRegs3C4[0x05], &sisReg->sisRegs3D4[0x80]); 7405 7406 (*pSiS->SiSSave)(pScrn, sisReg); 7407 7408 if(pSiS->UseVESA) SISVESASaveRestore(pScrn, MODE_SAVE); 7409 7410 /* "Save" these again as they may have been changed prior to SISSave() call */ 7411 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 7412 sisReg->sisRegs3C4[0x1f] = pSiS->oldSR1F; 7413 sisReg->sisRegs3D4[0x17] = pSiS->oldCR17; 7414 sisReg->sisRegs3D4[0x32] = pSiS->oldCR32; 7415 sisReg->sisRegs3D4[0x36] = pSiS->oldCR36; 7416 sisReg->sisRegs3D4[0x37] = pSiS->oldCR37; 7417 if(pSiS->VGAEngine == SIS_315_VGA) { 7418 sisReg->sisRegs3D4[pSiS->myCR63] = pSiS->oldCR63; 7419 } 7420 } 7421} 7422 7423/* VESASaveRestore taken from vesa driver */ 7424static void 7425SISVESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function) 7426{ 7427 SISPtr pSiS = SISPTR(pScrn); 7428 7429 /* Query amount of memory to save state */ 7430 if((function == MODE_QUERY) || 7431 (function == MODE_SAVE && pSiS->state == NULL)) { 7432 7433 /* Make sure we save at least this information in case of failure */ 7434 (void)VBEGetVBEMode(pSiS->pVbe, &pSiS->stateMode); 7435 SiSVGASaveFonts(pScrn); 7436 7437 if(pSiS->vesamajor > 1) { 7438 if(!VBESaveRestore(pSiS->pVbe, function, (pointer)&pSiS->state, 7439 &pSiS->stateSize, &pSiS->statePage)) { 7440 return; 7441 } 7442 } 7443 } 7444 7445 /* Save/Restore Super VGA state */ 7446 if(function != MODE_QUERY) { 7447 7448 if(pSiS->vesamajor > 1) { 7449 if(function == MODE_RESTORE) { 7450 memcpy(pSiS->state, pSiS->pstate, pSiS->stateSize); 7451 } 7452 7453 if(VBESaveRestore(pSiS->pVbe,function,(pointer)&pSiS->state, 7454 &pSiS->stateSize,&pSiS->statePage) && 7455 (function == MODE_SAVE)) { 7456 /* don't rely on the memory not being touched */ 7457 if(!pSiS->pstate) { 7458 pSiS->pstate = xalloc(pSiS->stateSize); 7459 } 7460 memcpy(pSiS->pstate, pSiS->state, pSiS->stateSize); 7461 } 7462 } 7463 7464 if(function == MODE_RESTORE) { 7465 VBESetVBEMode(pSiS->pVbe, pSiS->stateMode, NULL); 7466 SiSVGARestoreFonts(pScrn); 7467 } 7468 7469 } 7470} 7471 7472/* 7473 * Initialise a new mode. This is currently done using the 7474 * "initialise struct, restore/write struct to HW" model for 7475 * the old chipsets (5597/530/6326). For newer chipsets, 7476 * we use our own mode switching code. 7477 */ 7478 7479static Bool 7480SISModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 7481{ 7482 SISPtr pSiS = SISPTR(pScrn); 7483 SISRegPtr sisReg; 7484#ifdef SISDUALHEAD 7485 SISEntPtr pSiSEnt = NULL; 7486#endif 7487 7488 andSISIDXREG(SISCR,0x11,0x7f); /* Unlock CRTC registers */ 7489 7490 SISModifyModeInfo(mode); /* Quick check of the mode parameters */ 7491 7492 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7493 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO+0x30); 7494 } 7495 7496 if(pSiS->UseVESA) { /* With VESA: */ 7497 7498#ifdef SISDUALHEAD 7499 /* No dual head mode when using VESA */ 7500 if(pSiS->SecondHead) return TRUE; 7501#endif 7502 7503 pScrn->vtSema = TRUE; 7504 7505 /* 7506 * This order is required: 7507 * The video bridge needs to be adjusted before the 7508 * BIOS is run as the BIOS sets up CRT2 according to 7509 * these register settings. 7510 * After the BIOS is run, the bridges and turboqueue 7511 * registers need to be readjusted as the BIOS may 7512 * very probably have messed them up. 7513 */ 7514 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7515 SiSPreSetMode(pScrn, mode, SIS_MODE_SIMU); 7516 } 7517 if(!SiSSetVESAMode(pScrn, mode)) { 7518 SISErrorLog(pScrn, "SiSSetVESAMode() failed\n"); 7519 return FALSE; 7520 } 7521 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7522 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7523 SiSPreSetMode(pScrn, mode, SIS_MODE_SIMU); 7524 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7525 } 7526#ifdef TWDEBUG 7527 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 7528 "REAL REGISTER CONTENTS AFTER SETMODE:\n"); 7529#endif 7530 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7531 SISErrorLog(pScrn, "ModeInit() failed\n"); 7532 return FALSE; 7533 } 7534 7535 SiSVGAProtect(pScrn, TRUE); 7536 (*pSiS->SiSRestore)(pScrn, &pSiS->ModeReg); 7537 SiSVGAProtect(pScrn, FALSE); 7538 7539 } else { /* Without VESA: */ 7540 7541#ifdef SISDUALHEAD 7542 if(pSiS->DualHeadMode) { 7543 7544 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7545 SISErrorLog(pScrn, "ModeInit() failed\n"); 7546 return FALSE; 7547 } 7548 7549 pScrn->vtSema = TRUE; 7550 7551 pSiSEnt = pSiS->entityPrivate; 7552 7553 if(!(pSiS->SecondHead)) { 7554 /* Head 1 (master) is always CRT2 */ 7555 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT2); 7556 if(!SiSBIOSSetModeCRT2(pSiS->SiS_Pr, pScrn, mode, pSiS->IsCustom)) { 7557 SISErrorLog(pScrn, "SiSBIOSSetModeCRT2() failed\n"); 7558 return FALSE; 7559 } 7560 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7561 if(pSiSEnt->pScrn_2) { 7562 SISAdjustFrame(pSiSEnt->pScrn_2->scrnIndex, 7563 pSiSEnt->pScrn_2->frameX0, 7564 pSiSEnt->pScrn_2->frameY0, 0); 7565 } 7566 } else { 7567 /* Head 2 (slave) is always CRT1 */ 7568 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT1); 7569 if(!SiSBIOSSetModeCRT1(pSiS->SiS_Pr, pScrn, mode, pSiS->IsCustom)) { 7570 SISErrorLog(pScrn, "SiSBIOSSetModeCRT1() failed\n"); 7571 return FALSE; 7572 } 7573 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7574 if(pSiSEnt->pScrn_1) { 7575 SISAdjustFrame(pSiSEnt->pScrn_1->scrnIndex, 7576 pSiSEnt->pScrn_1->frameX0, 7577 pSiSEnt->pScrn_1->frameY0, 0); 7578 } 7579 } 7580 7581 } else { 7582#endif 7583 7584 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7585 7586 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7587 SISErrorLog(pScrn, "ModeInit() failed\n"); 7588 return FALSE; 7589 } 7590 7591 pScrn->vtSema = TRUE; 7592 7593#ifdef SISMERGED 7594 if(pSiS->MergedFB) { 7595 7596 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting MergedFB mode %dx%d\n", 7597 mode->HDisplay, mode->VDisplay); 7598 7599 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT1); 7600 7601 if(!SiSBIOSSetModeCRT1(pSiS->SiS_Pr, pScrn, 7602 ((SiSMergedDisplayModePtr)mode->Private)->CRT1, 7603 pSiS->IsCustom)) { 7604 SISErrorLog(pScrn, "SiSBIOSSetModeCRT1() failed\n"); 7605 return FALSE; 7606 } 7607 7608 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT2); 7609 7610 if(!SiSBIOSSetModeCRT2(pSiS->SiS_Pr, pScrn, 7611 ((SiSMergedDisplayModePtr)mode->Private)->CRT2, 7612 pSiS->IsCustom)) { 7613 SISErrorLog(pScrn, "SiSBIOSSetModeCRT2() failed\n"); 7614 return FALSE; 7615 } 7616 7617 } else { 7618#endif 7619 7620 if((pSiS->VBFlags & CRT1_LCDA) || (!(mode->type & M_T_DEFAULT))) { 7621 7622 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT1); 7623 7624 if(!SiSBIOSSetModeCRT1(pSiS->SiS_Pr, pScrn, 7625 mode, pSiS->IsCustom)) { 7626 SISErrorLog(pScrn, "SiSBIOSSetModeCRT1() failed\n"); 7627 return FALSE; 7628 } 7629 7630 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT2); 7631 7632 if(!SiSBIOSSetModeCRT2(pSiS->SiS_Pr, pScrn, 7633 mode, pSiS->IsCustom)) { 7634 SISErrorLog(pScrn, "SiSBIOSSetModeCRT2() failed\n"); 7635 return FALSE; 7636 } 7637 7638 } else { 7639 7640 SiSPreSetMode(pScrn, mode, SIS_MODE_SIMU); 7641 7642 if(!SiSBIOSSetMode(pSiS->SiS_Pr, pScrn, 7643 mode, pSiS->IsCustom)) { 7644 SISErrorLog(pScrn, "SiSBIOSSetMode() failed\n"); 7645 return FALSE; 7646 } 7647 7648 } 7649 7650#ifdef SISMERGED 7651 } 7652#endif 7653 7654 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7655 7656#ifdef TWDEBUG 7657 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VBFlags %lx\n", pSiS->VBFlags); 7658 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 7659 "REAL REGISTER CONTENTS AFTER SETMODE:\n"); 7660 (*pSiS->ModeInit)(pScrn, mode); 7661#endif 7662 7663 } else { 7664 7665 /* For other chipsets, use the old method */ 7666 7667 /* Prepare the register contents */ 7668 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7669 SISErrorLog(pScrn, "ModeInit() failed\n"); 7670 return FALSE; 7671 } 7672 7673 pScrn->vtSema = TRUE; 7674 7675 /* Program the registers */ 7676 SiSVGAProtect(pScrn, TRUE); 7677 sisReg = &pSiS->ModeReg; 7678 7679 sisReg->sisRegsATTR[0x10] = 0x01; 7680 if(pScrn->bitsPerPixel > 8) { 7681 sisReg->sisRegsGR[0x05] = 0x00; 7682 } 7683 7684 SiSVGARestore(pScrn, sisReg, SISVGA_SR_MODE); 7685 7686 (*pSiS->SiSRestore)(pScrn, sisReg); 7687 7688 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 7689 SiS6326PostSetMode(pScrn, &pSiS->ModeReg); 7690 } 7691 7692#ifdef TWDEBUG 7693 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 7694 "REAL REGISTER CONTENTS AFTER SETMODE:\n"); 7695 (*pSiS->ModeInit)(pScrn, mode); 7696#endif 7697 7698 SiSVGAProtect(pScrn, FALSE); 7699 7700 } 7701 7702#ifdef SISDUALHEAD 7703 } 7704#endif 7705 } 7706 7707 /* Update Currentlayout */ 7708 pSiS->CurrentLayout.mode = pSiS->currentModeLast = mode; 7709 7710 return TRUE; 7711} 7712 7713static Bool 7714SiSSetVESAMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) 7715{ 7716 SISPtr pSiS; 7717 int mode; 7718 7719 pSiS = SISPTR(pScrn); 7720 7721 if(!(mode = SiSCalcVESAModeIndex(pScrn, pMode))) return FALSE; 7722 7723 mode |= (1 << 15); /* Don't clear framebuffer */ 7724 mode |= (1 << 14); /* Use linear adressing */ 7725 7726 if(VBESetVBEMode(pSiS->pVbe, mode, NULL) == FALSE) { 7727 SISErrorLog(pScrn, "Setting VESA mode 0x%x failed\n", 7728 mode & 0x0fff); 7729 return (FALSE); 7730 } 7731 7732 if(pMode->HDisplay != pScrn->virtualX) { 7733 VBESetLogicalScanline(pSiS->pVbe, pScrn->virtualX); 7734 } 7735 7736 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 7737 "Setting VESA mode 0x%x succeeded\n", 7738 mode & 0x0fff); 7739 7740 return (TRUE); 7741} 7742 7743static void 7744SISSpecialRestore(ScrnInfoPtr pScrn) 7745{ 7746 SISPtr pSiS = SISPTR(pScrn); 7747 SISRegPtr sisReg = &pSiS->SavedReg; 7748 UChar temp; 7749 int i; 7750 7751 /* 1.11.04 and later for 651 and 301B(DH) do strange register 7752 * fiddling after the usual mode change. This happens 7753 * depending on the result of a call of int 2f (with 7754 * ax=0x1680) and if modeno <= 0x13. I have no idea if 7755 * that is specific for the 651 or that very machine. 7756 * So this perhaps requires some more checks in the beginning 7757 * (although it should not do any harm on other chipsets/bridges 7758 * etc.) However, even if I call the VBE to restore mode 0x03, 7759 * these registers don't get restored correctly, possibly 7760 * because that int-2f-call for some reason results non-zero. So 7761 * what I do here is to restore these few registers 7762 * manually. 7763 */ 7764 7765 if(!(pSiS->ChipFlags & SiSCF_Is65x)) return; 7766 inSISIDXREG(SISCR, 0x34, temp); 7767 temp &= 0x7f; 7768 if(temp > 0x13) return; 7769 7770#ifdef UNLOCK_ALWAYS 7771 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7772#endif 7773 7774 SiS_UnLockCRT2(pSiS->SiS_Pr); 7775 7776 outSISIDXREG(SISCAP, 0x3f, sisReg->sisCapt[0x3f]); 7777 outSISIDXREG(SISCAP, 0x00, sisReg->sisCapt[0x00]); 7778 for(i = 0; i < 0x4f; i++) { 7779 outSISIDXREG(SISCAP, i, sisReg->sisCapt[i]); 7780 } 7781 outSISIDXREG(SISVID, 0x32, (sisReg->sisVid[0x32] & ~0x05)); 7782 outSISIDXREG(SISVID, 0x30, sisReg->sisVid[0x30]); 7783 outSISIDXREG(SISVID, 0x32, ((sisReg->sisVid[0x32] & ~0x04) | 0x01)); 7784 outSISIDXREG(SISVID, 0x30, sisReg->sisVid[0x30]); 7785 7786 if(!(pSiS->ChipFlags & SiSCF_Is651)) return; 7787 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 7788 7789 inSISIDXREG(SISCR, 0x30, temp); 7790 if(temp & 0x40) { 7791 UChar myregs[] = { 7792 0x2f, 0x08, 0x09, 0x03, 0x0a, 0x0c, 7793 0x0b, 0x0d, 0x0e, 0x12, 0x0f, 0x10, 7794 0x11, 0x04, 0x05, 0x06, 0x07, 0x00, 7795 0x2e 7796 }; 7797 for(i = 0; i <= 18; i++) { 7798 outSISIDXREG(SISPART1, myregs[i], sisReg->VBPart1[myregs[i]]); 7799 } 7800 } else if((temp & 0x20) || (temp & 0x9c)) { 7801 UChar myregs[] = { 7802 0x04, 0x05, 0x06, 0x07, 0x00, 0x2e 7803 }; 7804 for(i = 0; i <= 5; i++) { 7805 outSISIDXREG(SISPART1, myregs[i], sisReg->VBPart1[myregs[i]]); 7806 } 7807 } 7808} 7809 7810/* Fix SR11 for 661 and later */ 7811static void 7812SiSFixupSR11(ScrnInfoPtr pScrn) 7813{ 7814 SISPtr pSiS = SISPTR(pScrn); 7815 CARD8 tmpreg; 7816 7817#ifdef UNLOCK_ALWAYS 7818 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7819#endif 7820 7821 if(pSiS->ChipType >= SIS_661) { 7822 inSISIDXREG(SISSR,0x11,tmpreg); 7823 if(tmpreg & 0x20) { 7824 inSISIDXREG(SISSR,0x3e,tmpreg); 7825 tmpreg = (tmpreg + 1) & 0xff; 7826 outSISIDXREG(SISSR,0x3e,tmpreg); 7827 } 7828 7829 inSISIDXREG(SISSR,0x11,tmpreg); 7830 if(tmpreg & 0xf0) { 7831 andSISIDXREG(SISSR,0x11,0x0f); 7832 } 7833 } 7834} 7835 7836/* Subroutine for restoring sisfb's TV parameters (used by SiSRestore()) */ 7837 7838static void 7839SiSRestore_SiSFB_TVParms(ScrnInfoPtr pScrn) 7840{ 7841 SISPtr pSiS = SISPTR(pScrn); 7842 int fd; 7843 CARD32 parm; 7844 7845 if(!pSiS->sisfbfound) return; 7846 if(!pSiS->sisfb_tvposvalid) return; 7847 if(!(pSiS->sisfbdevname[0])) return; 7848 7849 if((fd = open(pSiS->sisfbdevname, O_RDONLY)) != -1) { 7850 parm = (CARD32)((pSiS->sisfb_tvxpos << 16) | (pSiS->sisfb_tvypos & 0xffff)); 7851 ioctl(fd, SISFB_SET_TVPOSOFFSET, &parm); 7852 close(fd); 7853 } 7854} 7855 7856/* 7857 * Restore the initial mode. To be used internally only! 7858 */ 7859static void 7860SISRestore(ScrnInfoPtr pScrn) 7861{ 7862 SISPtr pSiS = SISPTR(pScrn); 7863 SISRegPtr sisReg = &pSiS->SavedReg; 7864 Bool doit = FALSE, doitlater = FALSE; 7865 Bool vesasuccess = FALSE; 7866 int flags; 7867 7868 /* WARNING: Don't ever touch this. It now seems to work on 7869 * all chipset/bridge combinations - but finding out the 7870 * correct combination was pure hell. 7871 */ 7872 7873 /* Wait for the accelerators */ 7874 (*pSiS->SyncAccel)(pScrn); 7875 7876 /* Set up restore flags */ 7877 flags = SISVGA_SR_MODE | SISVGA_SR_CMAP; 7878#ifdef SIS_PC_PLATFORM 7879 /* We now restore ALL to overcome the vga=extended problem */ 7880 if(pSiS->VGAMemBase) flags |= SISVGA_SR_FONTS; 7881#endif 7882 7883 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 7884 7885#ifdef SISDUALHEAD 7886 /* We always restore master AND slave */ 7887 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 7888#endif 7889 7890#ifdef UNLOCK_ALWAYS 7891 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7892#endif 7893 7894 /* We must not disable the sequencer if the bridge is in SlaveMode! */ 7895 if(!(SiSBridgeIsInSlaveMode(pScrn))) { 7896 SiSVGAProtect(pScrn, TRUE); 7897 } 7898 7899 /* First, restore CRT1 on/off and VB connection registers */ 7900 outSISIDXREG(SISCR, 0x32, pSiS->oldCR32); 7901 if(!(pSiS->oldCR17 & 0x80)) { /* CRT1 was off */ 7902 if(!(SiSBridgeIsInSlaveMode(pScrn))) { /* Bridge is NOT in SlaveMode now -> do it */ 7903 doit = TRUE; 7904 } else { 7905 doitlater = TRUE; 7906 } 7907 } else { /* CRT1 was on -> do it now */ 7908 doit = TRUE; 7909 } 7910 7911 if(doit) { 7912 outSISIDXREG(SISCR, 0x17, pSiS->oldCR17); 7913 } 7914 if(pSiS->VGAEngine == SIS_315_VGA) { 7915 outSISIDXREG(SISCR, pSiS->myCR63, pSiS->oldCR63); 7916 } 7917 7918 outSISIDXREG(SISSR, 0x1f, pSiS->oldSR1F); 7919 7920 /* For 30xB/LV, restoring the registers does not 7921 * work. We "manually" set the old mode, instead. 7922 * The same applies for SiS730 machines with LVDS. 7923 * Finally, this behavior can be forced by setting 7924 * the option RestoreBySetMode. 7925 */ 7926 if( ( (pSiS->restorebyset) || 7927 (pSiS->VBFlags2 & VB2_30xBLV) || 7928 ((pSiS->ChipType == SIS_730) && (pSiS->VBFlags2 & VB2_LVDS)) ) && 7929 (pSiS->OldMode) ) { 7930 7931 Bool changedmode = FALSE; 7932 7933 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 7934 "Restoring by setting old mode 0x%02x\n", pSiS->OldMode); 7935 7936 if(((pSiS->OldMode <= 0x13) || (!pSiS->sisfbfound)) && (pSiS->pVbe)) { 7937 int vmode = SiSTranslateToVESA(pScrn, pSiS->OldMode); 7938 if(vmode > 0) { 7939 if(vmode > 0x13) vmode |= ((1 << 15) | (1 << 14)); 7940 if(VBESetVBEMode(pSiS->pVbe, vmode, NULL) == TRUE) { 7941 SISSpecialRestore(pScrn); 7942 SiS_GetSetModeID(pScrn,pSiS->OldMode); 7943 vesasuccess = TRUE; 7944 } else { 7945 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 7946 "VBE failed to restore mode 0x%x\n", pSiS->OldMode); 7947 } 7948 } else { 7949 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 7950 "Can't identify VESA mode number for mode 0x%x\n", pSiS->OldMode); 7951 } 7952 } 7953 7954 if(vesasuccess == FALSE) { 7955 7956 int backupscaler = pSiS->SiS_Pr->UsePanelScaler; 7957 int backupcenter = pSiS->SiS_Pr->CenterScreen; 7958 ULong backupspecialtiming = pSiS->SiS_Pr->SiS_CustomT; 7959 int mymode = pSiS->OldMode; 7960 7961 if((pSiS->VGAEngine == SIS_315_VGA) && 7962 ((pSiS->ROM661New) || (pSiS->ChipFlags & SiSCF_IsXGI)) && 7963 (!pSiS->sisfbfound)) { 7964 /* New SiS BIOS or XGI BIOS has set mode, therefore eventually translate number */ 7965 mymode = SiSTranslateToOldMode(mymode); 7966 } 7967 7968 if((pSiS->VBFlags2 & VB2_30xBLV)) { 7969 /* !!! REQUIRED for 630+301B-DH, otherwise the text modes 7970 * will not be restored correctly !!! 7971 * !!! Do this ONLY for LCD; VGA2 will not be restored 7972 * correctly otherwise. 7973 */ 7974 UChar temp; 7975 inSISIDXREG(SISCR, 0x30, temp); 7976 if(temp & 0x20) { 7977 if(mymode == 0x03) { 7978 mymode = 0x13; 7979 changedmode = TRUE; 7980 } 7981 } 7982 } 7983 7984 pSiS->SiS_Pr->UseCustomMode = FALSE; 7985 pSiS->SiS_Pr->CRT1UsesCustomMode = FALSE; 7986 pSiS->SiS_Pr->CenterScreen = 0; 7987 if(pSiS->sisfbfound) { 7988 pSiS->SiS_Pr->UsePanelScaler = pSiS->sisfbscalelcd; 7989 pSiS->SiS_Pr->SiS_CustomT = pSiS->sisfbspecialtiming; 7990 } else { 7991 pSiS->SiS_Pr->UsePanelScaler = -1; 7992 /* Leave CustomT as it is */ 7993 } 7994 SiS_SetEnableDstn(pSiS->SiS_Pr, FALSE); 7995 SiS_SetEnableFstn(pSiS->SiS_Pr, FALSE); 7996 if((pSiS->ChipType == SIS_550) && (pSiS->sisfbfound)) { 7997 if(pSiS->sisfbxSTN) { 7998 SiS_SetEnableDstn(pSiS->SiS_Pr, pSiS->sisfbDSTN); 7999 SiS_SetEnableFstn(pSiS->SiS_Pr, pSiS->sisfbFSTN); 8000 } else if(mymode == 0x5a || mymode == 0x5b) { 8001 SiS_SetEnableFstn(pSiS->SiS_Pr, TRUE); 8002 } 8003 } 8004 SiSSetMode(pSiS->SiS_Pr, pScrn, mymode, FALSE); 8005 if(changedmode) { 8006 outSISIDXREG(SISCR,0x34,0x03); 8007 } 8008 SISSpecialRestore(pScrn); 8009 SiS_GetSetModeID(pScrn, pSiS->OldMode); /* NOT mymode! */ 8010 pSiS->SiS_Pr->UsePanelScaler = backupscaler; 8011 pSiS->SiS_Pr->CenterScreen = backupcenter; 8012 pSiS->SiS_Pr->SiS_CustomT = backupspecialtiming; 8013 SiS_SiSFB_Lock(pScrn, FALSE); 8014 SiSRestore_SiSFB_TVParms(pScrn); 8015 SiS_SiSFB_Lock(pScrn, TRUE); 8016 8017 } 8018 8019 /* Restore CRT1 status */ 8020 if(pSiS->VGAEngine == SIS_315_VGA) { 8021 outSISIDXREG(SISCR, pSiS->myCR63, pSiS->oldCR63); 8022 } 8023 outSISIDXREG(SISSR, 0x1f, pSiS->oldSR1F); 8024 8025#ifdef SISVRAMQ 8026 /* Restore queue mode registers on 315/330/340 series */ 8027 /* (This became necessary due to the switch to VRAM queue) */ 8028 SiSRestoreQueueMode(pSiS, sisReg); 8029#endif 8030 8031 } else { 8032 8033 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 8034 /* If a video bridge is present, we need to restore 8035 * non-extended (=standard VGA) SR and CR registers 8036 * before restoring the extended ones and the bridge 8037 * registers. 8038 */ 8039 if(!(SiSBridgeIsInSlaveMode(pScrn))) { 8040 SiSVGAProtect(pScrn, TRUE); 8041 SiSVGARestore(pScrn, sisReg, SISVGA_SR_MODE); 8042 } 8043 } 8044 8045 (*pSiS->SiSRestore)(pScrn, sisReg); 8046 8047 } 8048 8049 if(doitlater) { 8050 outSISIDXREG(SISCR, 0x17, pSiS->oldCR17); 8051 } 8052 8053 8054 8055 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (SiSBridgeIsInSlaveMode(pScrn))) { 8056 8057 /* IMPORTANT: The 30xLV does not handle well being disabled if in 8058 * LCDA mode! In LCDA mode, the bridge is NOT in slave mode, 8059 * so this is the only safe way: Disable the bridge ONLY if 8060 * in Slave Mode, and don't bother if not. 8061 */ 8062 8063 if(flags & SISVGA_SR_FONTS) { 8064 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO+0x30); 8065 SiSSetLVDSetc(pSiS->SiS_Pr, 0); 8066 SiS_GetVBType(pSiS->SiS_Pr); 8067 SiS_DisableBridge(pSiS->SiS_Pr); 8068 SiSVGAProtect(pScrn, TRUE); 8069 } 8070 8071 SiSVGARestore(pScrn, sisReg, flags); 8072 8073 if(flags & SISVGA_SR_FONTS) { 8074 SiSVGAProtect(pScrn, FALSE); 8075 SiS_EnableBridge(pSiS->SiS_Pr); 8076 andSISIDXREG(SISSR, 0x01, ~0x20); /* Display on */ 8077 } 8078 8079 } else { 8080 8081 SiSVGAProtect(pScrn, TRUE); 8082 SiSVGARestore(pScrn, sisReg, flags); 8083 SiSVGAProtect(pScrn, FALSE); 8084 8085 } 8086 8087 SiSFixupSR11(pScrn); 8088 8089#ifdef TWDEBUG 8090 { 8091 SISRegPtr pReg = &pSiS->ModeReg; 8092 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8093 "REAL REGISTER CONTENTS AFTER RESTORE BY SETMODE:\n"); 8094 (*pSiS->SiSSave)(pScrn, pReg); 8095 } 8096#endif 8097 8098 sisRestoreExtRegisterLock(pSiS,sisReg->sisRegs3C4[0x05],sisReg->sisRegs3D4[0x80]); 8099 8100 } else { /* All other chipsets */ 8101 8102 SiSVGAProtect(pScrn, TRUE); 8103 8104#ifdef UNLOCK_ALWAYS 8105 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8106#endif 8107 8108 (*pSiS->SiSRestore)(pScrn, sisReg); 8109 8110 SiSVGAProtect(pScrn, TRUE); 8111 8112 SiSVGARestore(pScrn, sisReg, flags); 8113 8114 /* Restore TV. This is rather complicated, but if we don't do it, 8115 * TV output will flicker terribly 8116 */ 8117 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 8118 if(sisReg->sis6326tv[0] & 0x04) { 8119 UChar tmp; 8120 int val; 8121 8122 orSISIDXREG(SISSR, 0x01, 0x20); 8123 tmp = SiS6326GetTVReg(pScrn,0x00); 8124 tmp &= ~0x04; 8125 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 8126 SiS6326SetTVReg(pScrn,0x00,tmp); 8127 for(val=0; val < 2; val++) { 8128 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 8129 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 8130 } 8131 SiS6326SetTVReg(pScrn, 0x00, sisReg->sis6326tv[0]); 8132 tmp = inSISREG(SISINPSTAT); 8133 outSISREG(SISAR, 0x20); 8134 tmp = inSISREG(SISINPSTAT); 8135 while(inSISREG(SISINPSTAT) & 0x01); 8136 while(!(inSISREG(SISINPSTAT) & 0x01)); 8137 andSISIDXREG(SISSR, 0x01, ~0x20); 8138 for(val=0; val < 10; val++) { 8139 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 8140 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 8141 } 8142 andSISIDXREG(SISSR, 0x01, ~0x20); 8143 } 8144 } 8145 8146 sisRestoreExtRegisterLock(pSiS,sisReg->sisRegs3C4[5],sisReg->sisRegs3D4[0x80]); 8147 8148 SiSVGAProtect(pScrn, FALSE); 8149 } 8150} 8151 8152static void 8153SISVESARestore(ScrnInfoPtr pScrn) 8154{ 8155 SISPtr pSiS = SISPTR(pScrn); 8156#ifdef SISVRAMQ 8157 SISRegPtr sisReg = &pSiS->SavedReg; 8158#endif 8159 8160 if(pSiS->UseVESA) { 8161 SISVESASaveRestore(pScrn, MODE_RESTORE); 8162#ifdef SISVRAMQ 8163 /* Restore queue mode registers on 315/330/340 series */ 8164 /* (This became necessary due to the switch to VRAM queue) */ 8165 SiSRestoreQueueMode(pSiS, sisReg); 8166#endif 8167 } 8168} 8169 8170/* Restore bridge config registers - to be called BEFORE VESARestore */ 8171static void 8172SISBridgeRestore(ScrnInfoPtr pScrn) 8173{ 8174 SISPtr pSiS = SISPTR(pScrn); 8175 8176#ifdef SISDUALHEAD 8177 /* We only restore for master head */ 8178 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 8179#endif 8180 8181 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 8182 SiSRestoreBridge(pScrn, &pSiS->SavedReg); 8183 } 8184} 8185 8186/* Our BlockHandler */ 8187static void 8188SISBlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask) 8189{ 8190 ScreenPtr pScreen = screenInfo.screens[i]; 8191 ScrnInfoPtr pScrn = xf86Screens[i]; 8192 SISPtr pSiS = SISPTR(pScrn); 8193 8194 pScreen->BlockHandler = pSiS->BlockHandler; 8195 (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); 8196 pScreen->BlockHandler = SISBlockHandler; 8197 8198#ifdef SISDUALHEAD 8199 if(pSiS->NeedCopyFastVidCpy) { 8200 SISEntPtr pSiSEnt = pSiS->entityPrivate; 8201 if(pSiSEnt->HaveFastVidCpy) { 8202 pSiS->NeedCopyFastVidCpy = FALSE; 8203 pSiS->SiSFastVidCopy = pSiSEnt->SiSFastVidCopy; 8204 pSiS->SiSFastMemCopy = pSiSEnt->SiSFastMemCopy; 8205 pSiS->SiSFastVidCopyFrom = pSiSEnt->SiSFastVidCopyFrom; 8206 pSiS->SiSFastMemCopyFrom = pSiSEnt->SiSFastMemCopyFrom; 8207 } 8208 } 8209#endif 8210 8211 if(pSiS->VideoTimerCallback) { 8212 (*pSiS->VideoTimerCallback)(pScrn, currentTime.milliseconds); 8213 } 8214 8215#ifdef SIS_USE_XAA 8216 if(pSiS->RenderCallback) { 8217 (*pSiS->RenderCallback)(pScrn); 8218 } 8219#endif 8220#ifdef SIS_USE_EXA 8221 if(pSiS->ExaRenderCallback) { 8222 (*pSiS->ExaRenderCallback)(pScrn); 8223 } 8224#endif 8225} 8226 8227 8228 8229/* Do screen blanking; DPMS handling 8230 * 8231 * Mandatory; latter optional 8232 */ 8233 8234static void 8235SiSHandleBackLight(SISPtr pSiS, Bool blon) 8236{ 8237 UChar sr11mask = (pSiS->SiS_Pr->SiS_SensibleSR11) ? 0x03 : 0xf3; 8238 8239 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) { 8240 8241 if(!blon) { 8242 SiS_SiS30xBLOff(pSiS->SiS_Pr); 8243 } else { 8244 SiS_SiS30xBLOn(pSiS->SiS_Pr); 8245 } 8246 8247 } else if( ((pSiS->VGAEngine == SIS_300_VGA) && 8248 (pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH))) || 8249 ((pSiS->VGAEngine == SIS_315_VGA) && 8250 ((pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS)) ) { 8251 8252 if(!blon) { 8253 setSISIDXREG(SISSR, 0x11, sr11mask, 0x08); 8254 } else { 8255 setSISIDXREG(SISSR, 0x11, sr11mask, 0x00); 8256 } 8257 8258 } else if((pSiS->VGAEngine == SIS_315_VGA) && 8259 (pSiS->VBFlags2 & VB2_CHRONTEL)) { 8260 8261 if(!blon) { 8262 SiS_Chrontel701xBLOff(pSiS->SiS_Pr); 8263 } else { 8264 SiS_Chrontel701xBLOn(pSiS->SiS_Pr); 8265 } 8266 8267 } 8268} 8269 8270static Bool 8271SISSaveScreen(ScreenPtr pScreen, int mode) 8272{ 8273 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 8274 SISPtr pSiS; 8275 Bool IsUnblank = xf86IsUnblank(mode) ? TRUE : FALSE; 8276 8277 if((pScrn == NULL) || (!pScrn->vtSema)) return TRUE; 8278 8279 pSiS = SISPTR(pScrn); 8280 8281#ifdef UNLOCK_ALWAYS 8282 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8283#endif 8284 8285 if(pSiS->VBFlags & (CRT2_LCD | CRT1_LCDA)) { 8286 SiSHandleBackLight(pSiS, IsUnblank); 8287 } 8288 8289 if(!SiSBridgeIsInSlaveMode(pScrn)) { 8290 return SiSVGASaveScreen(pScreen, mode); 8291 } 8292 8293 return TRUE; 8294} 8295 8296#ifdef SISDUALHEAD 8297/* SaveScreen for dual head mode */ 8298static Bool 8299SISSaveScreenDH(ScreenPtr pScreen, int mode) 8300{ 8301 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 8302 SISPtr pSiS; 8303 Bool IsUnblank = xf86IsUnblank(mode) ? TRUE : FALSE; 8304 8305 if((pScrn == NULL) || (!pScrn->vtSema)) return TRUE; 8306 8307 pSiS = SISPTR(pScrn); 8308 8309 if( (pSiS->SecondHead) && 8310 ((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) ) { 8311 8312 /* Slave head is always CRT1 */ 8313 /* (No backlight handling on TMDS bridges) */ 8314 return SiSVGASaveScreen(pScreen, mode); 8315 8316 } else { 8317 8318 /* Master head is always CRT2 */ 8319 /* But we land here for LCDA, too (if bridge is SiS LVDS type) */ 8320 8321 /* We can only blank LCD, not other CRT2 devices */ 8322 if(pSiS->VBFlags & (CRT2_LCD|CRT1_LCDA)) { 8323 8324#ifdef UNLOCK_ALWAYS 8325 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8326#endif 8327 SiSHandleBackLight(pSiS, IsUnblank); 8328 8329 } 8330 8331 } 8332 return TRUE; 8333} 8334#endif 8335 8336static void 8337SISDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags) 8338{ 8339 SISPtr pSiS = SISPTR(pScrn); 8340 Bool docrt1 = TRUE, docrt2 = TRUE, backlight = TRUE; 8341 UChar sr1=0, cr17=0, cr63=0, pmreg=0, sr7=0; 8342 UChar p1_13=0, p2_0=0, oldpmreg=0; 8343 8344 if(!pScrn->vtSema) return; 8345 8346 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, 8347 "SISDisplayPowerManagementSet(%d)\n", PowerManagementMode); 8348 8349#ifdef SISDUALHEAD 8350 if(pSiS->DualHeadMode) { 8351 if(pSiS->SecondHead) docrt2 = FALSE; 8352 else docrt1 = FALSE; 8353 } 8354#endif 8355 8356 /* FIXME: in old servers, DPMSSet was supposed to be called without open 8357 * the correct PCI bridges before access the hardware. Now we have this 8358 * hook wrapped by the vga arbiter which should do all the work, in 8359 * kernels that implement it. For this case we might not want this hack 8360 * bellow. 8361 */ 8362 outSISIDXREG(SISSR,0x05,0x86); 8363 inSISIDXREG(SISSR,0x05,pmreg); 8364 if(pmreg != 0xa1) return; 8365 8366#ifdef UNLOCK_ALWAYS 8367 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8368#endif 8369 8370 switch(PowerManagementMode) { 8371 8372 case DPMSModeOn: /* HSync: On, VSync: On */ 8373 sr1 = 0x00; 8374 cr17 = 0x80; 8375 pmreg = 0x00; 8376 cr63 = 0x00; 8377 sr7 = 0x10; 8378 p2_0 = 0x20; 8379 p1_13 = 0x00; 8380 backlight = TRUE; 8381 break; 8382 8383 case DPMSModeSuspend: /* HSync: On, VSync: Off */ 8384 sr1 = 0x20; 8385 cr17 = 0x80; 8386 pmreg = 0x80; 8387 cr63 = 0x40; 8388 sr7 = 0x00; 8389 p2_0 = 0x40; 8390 p1_13 = 0x80; 8391 backlight = FALSE; 8392 break; 8393 8394 case DPMSModeStandby: /* HSync: Off, VSync: On */ 8395 sr1 = 0x20; 8396 cr17 = 0x80; 8397 pmreg = 0x40; 8398 cr63 = 0x40; 8399 sr7 = 0x00; 8400 p2_0 = 0x80; 8401 p1_13 = 0x40; 8402 backlight = FALSE; 8403 break; 8404 8405 case DPMSModeOff: /* HSync: Off, VSync: Off */ 8406 sr1 = 0x20; 8407 cr17 = 0x00; 8408 pmreg = 0xc0; 8409 cr63 = 0x40; 8410 sr7 = 0x00; 8411 p2_0 = 0xc0; 8412 p1_13 = 0xc0; 8413 backlight = FALSE; 8414 break; 8415 8416 default: 8417 return; 8418 } 8419 8420 oldpmreg = pmreg; 8421 8422 if((docrt2 && (pSiS->VBFlags & CRT2_LCD)) || 8423 (docrt1 && (pSiS->VBFlags & CRT1_LCDA))) { 8424 SiSHandleBackLight(pSiS, backlight); 8425 } 8426 8427 if(docrt1) { 8428 switch(pSiS->VGAEngine) { 8429 case SIS_OLD_VGA: 8430 case SIS_530_VGA: 8431 setSISIDXREG(SISSR, 0x01, ~0x20, sr1); /* Set/Clear "Display On" bit */ 8432 inSISIDXREG(SISSR, 0x11, oldpmreg); 8433 setSISIDXREG(SISCR, 0x17, 0x7f, cr17); 8434 setSISIDXREG(SISSR, 0x11, 0x3f, pmreg); 8435 break; 8436 case SIS_315_VGA: 8437 if( (!pSiS->CRT1off) && 8438 ((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) ) { 8439 setSISIDXREG(SISCR, pSiS->myCR63, 0xbf, cr63); 8440 setSISIDXREG(SISSR, 0x07, 0xef, sr7); 8441 } 8442 /* fall through */ 8443 default: 8444 if(!SiSBridgeIsInSlaveMode(pScrn)) { 8445 setSISIDXREG(SISSR, 0x01, ~0x20, sr1); /* Set/Clear "Display On" bit */ 8446 } 8447 if((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 8448 inSISIDXREG(SISSR, 0x1f, oldpmreg); 8449 if((!pSiS->CRT1off) && (!SiSBridgeIsInSlaveMode(pScrn))) { 8450 setSISIDXREG(SISSR, 0x1f, 0x3f, pmreg); 8451 } 8452 } 8453 } 8454 oldpmreg &= 0xc0; 8455 } 8456 8457 if(docrt2) { 8458 if(pSiS->VBFlags & CRT2_LCD) { 8459 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && 8460 (!(pSiS->VBFlags2 & VB2_30xBDH))) { 8461 if(pSiS->VGAEngine == SIS_300_VGA) { 8462 SiS_UnLockCRT2(pSiS->SiS_Pr); 8463 setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13); 8464 } 8465 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) p2_0 |= 0x20; 8466 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); 8467 } 8468 } else if(pSiS->VBFlags & (CRT2_VGA | CRT2_TV)) { 8469 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 8470 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); 8471 } 8472 } 8473 } 8474 8475 if( (docrt1) && 8476 (pmreg != oldpmreg) && 8477 ((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) ) { 8478 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 8479 usleep(10000); 8480 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 8481 } 8482 8483} 8484 8485/* Mandatory 8486 * This gets called at the start of each server generation 8487 * 8488 * We use pScrn and not CurrentLayout here, because the 8489 * properties we use have not changed (displayWidth, 8490 * depth, bitsPerPixel) 8491 */ 8492static Bool 8493SISScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) 8494{ 8495 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 8496 SISPtr pSiS = SISPTR(pScrn); 8497 VisualPtr visual; 8498 ULong OnScreenSize; 8499 int ret, height, width, displayWidth; 8500 UChar *FBStart; 8501#ifdef SISDUALHEAD 8502 SISEntPtr pSiSEnt = NULL; 8503#endif 8504 8505#ifdef SISDUALHEAD 8506 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) { 8507#endif 8508 SiS_LoadInitVBE(pScrn); 8509#ifdef SISDUALHEAD 8510 } 8511#endif 8512 8513#ifdef SISDUALHEAD 8514 if(pSiS->DualHeadMode) { 8515 pSiSEnt = pSiS->entityPrivate; 8516 pSiSEnt->refCount++; 8517 } 8518#endif 8519 8520#ifdef SIS_PC_PLATFORM 8521 /* Map 64k VGA window for saving/restoring CGA fonts */ 8522 SiS_MapVGAMem(pScrn); 8523#endif 8524 8525 /* Map the SiS memory and MMIO areas */ 8526 if(!SISMapMem(pScrn)) { 8527 SISErrorLog(pScrn, "SiSMapMem() failed\n"); 8528 return FALSE; 8529 } 8530 8531 SiS_SiSFB_Lock(pScrn, TRUE); 8532 8533#ifdef UNLOCK_ALWAYS 8534 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8535#endif 8536 8537 /* Enable TurboQueue so that SISSave() saves it in enabled 8538 * state. If we don't do this, X will hang after a restart! 8539 * (Happens for some unknown reason only when using VESA 8540 * for mode switching; assumingly a BIOS issue.) 8541 * This is done on 300 and 315 series only. 8542 */ 8543 if(pSiS->UseVESA) { 8544#ifdef SISVRAMQ 8545 if(pSiS->VGAEngine != SIS_315_VGA) 8546#endif 8547 SiSEnableTurboQueue(pScrn); 8548 } 8549 8550 /* Save the current state */ 8551 SISSave(pScrn); 8552 8553 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 8554 8555 if(!pSiS->OldMode) { 8556 8557 /* Try to find out current (=old) mode number 8558 * (Do this only if not sisfb has told us its mode yet) 8559 */ 8560 8561 /* Read 0:449 which the BIOS sets to the current mode number 8562 * Unfortunately, this not reliable since the int10 emulation 8563 * does not change this. So if we call the VBE later, this 8564 * byte won't be touched (which is why we set this manually 8565 * then). 8566 */ 8567 UChar myoldmode = SiS_GetSetModeID(pScrn, 0xFF); 8568 UChar cr30, cr31; 8569 8570 /* Read CR34 which the BIOS sets to the current mode number for CRT2 8571 * This is - of course - not reliable if the machine has no video 8572 * bridge... 8573 */ 8574 inSISIDXREG(SISCR, 0x34, pSiS->OldMode); 8575 inSISIDXREG(SISCR, 0x30, cr30); 8576 inSISIDXREG(SISCR, 0x31, cr31); 8577 8578 /* What if CR34 is different from the BIOS scratch byte? */ 8579 if(pSiS->OldMode != myoldmode) { 8580 /* If no bridge output is active, trust the BIOS scratch byte */ 8581 if( (!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) || 8582 (pSiS->OldMode == 0) || 8583 (!cr31 && !cr30) || 8584 (cr31 & 0x20) ) { 8585 pSiS->OldMode = myoldmode; 8586 } 8587 /* ..else trust CR34 */ 8588 } 8589 8590 /* Newer 650 BIOSes set CR34 to 0xff if the mode has been 8591 * "patched", for instance for 80x50 text mode. (That mode 8592 * has no number of its own, it's 0x03 like 80x25). In this 8593 * case, we trust the BIOS scratch byte (provided that any 8594 * of these two is valid). 8595 */ 8596 if(pSiS->OldMode > 0x7f) { 8597 pSiS->OldMode = myoldmode; 8598 } 8599 } 8600#ifdef SISDUALHEAD 8601 if(pSiS->DualHeadMode) { 8602 if(!pSiS->SecondHead) pSiSEnt->OldMode = pSiS->OldMode; 8603 else pSiS->OldMode = pSiSEnt->OldMode; 8604 } 8605#endif 8606 } 8607 8608 /* RandR resets screen mode and size in CloseScreen(), hence 8609 * we need to adapt our VBFlags to the initial state if the 8610 * current mode has changed since closescreen() (or Screeninit() 8611 * for the first instance) 8612 */ 8613 if(pScrn->currentMode != pSiS->currentModeLast) { 8614 pSiS->VBFlags = pSiS->VBFlags_backup = pSiS->VBFlagsInit; 8615 } 8616 8617 /* Copy our detected monitor gammas, part 2. Note that device redetection 8618 * is not supported in DHM, so there is no need to do that anytime later. 8619 */ 8620#ifdef SISDUALHEAD 8621 if(pSiS->DualHeadMode) { 8622 if(!pSiS->SecondHead) { 8623 /* CRT2 */ 8624 pSiS->CRT1VGAMonitorGamma = pSiSEnt->CRT1VGAMonitorGamma; 8625 } else { 8626 /* CRT1 */ 8627 pSiS->CRT2VGAMonitorGamma = pSiSEnt->CRT2VGAMonitorGamma; 8628 } 8629 if(!pSiS->CRT2LCDMonitorGamma) pSiS->CRT2LCDMonitorGamma = pSiSEnt->CRT2LCDMonitorGamma; 8630 } 8631#endif 8632 8633 /* Initialize the first mode */ 8634 if(!SISModeInit(pScrn, pScrn->currentMode)) { 8635 SISErrorLog(pScrn, "SiSModeInit() failed\n"); 8636 return FALSE; 8637 } 8638 8639 /* Darken the screen for aesthetic reasons */ 8640 /* Not using Dual Head variant on purpose; we darken 8641 * the screen for both displays, and un-darken 8642 * it when the second head is finished 8643 */ 8644 SISSaveScreen(pScreen, SCREEN_SAVER_ON); 8645 8646 /* Set the viewport */ 8647 SISAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 8648 8649 /* Reset visual list. */ 8650 miClearVisualTypes(); 8651 8652 /* Setup the visuals we support. */ 8653 8654 /* 8655 * For bpp > 8, the default visuals are not acceptable because we only 8656 * support TrueColor and not DirectColor. 8657 */ 8658 if(!miSetVisualTypes(pScrn->depth, 8659 (pScrn->bitsPerPixel > 8) ? 8660 TrueColorMask : miGetDefaultVisualMask(pScrn->depth), 8661 pScrn->rgbBits, pScrn->defaultVisual)) { 8662 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8663 SISErrorLog(pScrn, "miSetVisualTypes() failed (bpp %d)\n", 8664 pScrn->bitsPerPixel); 8665 return FALSE; 8666 } 8667 8668 width = pScrn->virtualX; 8669 height = pScrn->virtualY; 8670 displayWidth = pScrn->displayWidth; 8671 8672 if(pSiS->Rotate) { 8673 height = pScrn->virtualX; 8674 width = pScrn->virtualY; 8675 } 8676 8677 if(pSiS->ShadowFB) { 8678 pSiS->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); 8679 pSiS->ShadowPtr = xalloc(pSiS->ShadowPitch * height); 8680 displayWidth = pSiS->ShadowPitch / (pScrn->bitsPerPixel >> 3); 8681 FBStart = pSiS->ShadowPtr; 8682 } else { 8683 pSiS->ShadowPtr = NULL; 8684 FBStart = pSiS->FbBase; 8685 } 8686 8687 if(!miSetPixmapDepths()) { 8688 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8689 SISErrorLog(pScrn, "miSetPixmapDepths() failed\n"); 8690 return FALSE; 8691 } 8692 8693 /* Point cmdQueuePtr to pSiSEnt for shared usage 8694 * (same technique is then eventually used in DRIScreeninit) 8695 * For 315/330 series, this is done in EnableTurboQueue 8696 * which has already been called during ModeInit(). 8697 */ 8698#ifdef SISDUALHEAD 8699 if(pSiS->SecondHead) 8700 pSiS->cmdQueueLenPtr = &(SISPTR(pSiSEnt->pScrn_1)->cmdQueueLen); 8701 else 8702#endif 8703 pSiS->cmdQueueLenPtr = &(pSiS->cmdQueueLen); 8704 8705 pSiS->cmdQueueLen = 0; /* Force an EngineIdle() at start */ 8706 8707#ifdef XF86DRI 8708 if(pSiS->loadDRI) { 8709#ifdef SISDUALHEAD 8710 /* No DRI in dual head mode */ 8711 if(pSiS->DualHeadMode) { 8712 pSiS->directRenderingEnabled = FALSE; 8713 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8714 "DRI not supported in Dual Head mode\n"); 8715 } else 8716#endif 8717 if(pSiS->VGAEngine != SIS_315_VGA) { 8718 /* Force the initialization of the context */ 8719 pSiS->directRenderingEnabled = SISDRIScreenInit(pScreen); 8720 } else { 8721 xf86DrvMsg(pScrn->scrnIndex, X_NOT_IMPLEMENTED, 8722 "DRI not supported on this chipset\n"); 8723 pSiS->directRenderingEnabled = FALSE; 8724 } 8725 } 8726#endif 8727 8728 /* Call the framebuffer layer's ScreenInit function and fill in other 8729 * pScreen fields. 8730 */ 8731 switch(pScrn->bitsPerPixel) { 8732 case 24: 8733 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 8734 ret = FALSE; 8735 break; 8736 } 8737 /* fall through */ 8738 case 8: 8739 case 16: 8740 case 32: 8741 ret = fbScreenInit(pScreen, FBStart, width, 8742 height, pScrn->xDpi, pScrn->yDpi, 8743 displayWidth, pScrn->bitsPerPixel); 8744 break; 8745 default: 8746 ret = FALSE; 8747 break; 8748 } 8749 if(!ret) { 8750 SISErrorLog(pScrn, "Unsupported bpp (%d) or fbScreenInit() failed\n", 8751 pScrn->bitsPerPixel); 8752 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8753 return FALSE; 8754 } 8755 8756 /* Fixup RGB ordering */ 8757 if(pScrn->bitsPerPixel > 8) { 8758 visual = pScreen->visuals + pScreen->numVisuals; 8759 while (--visual >= pScreen->visuals) { 8760 if((visual->class | DynamicClass) == DirectColor) { 8761 visual->offsetRed = pScrn->offset.red; 8762 visual->offsetGreen = pScrn->offset.green; 8763 visual->offsetBlue = pScrn->offset.blue; 8764 visual->redMask = pScrn->mask.red; 8765 visual->greenMask = pScrn->mask.green; 8766 visual->blueMask = pScrn->mask.blue; 8767 } 8768 } 8769 } 8770 8771 /* Initialize RENDER extension (must be after RGB ordering fixed) */ 8772 fbPictureInit(pScreen, 0, 0); 8773 8774 /* Hardware cursor needs to wrap this layer */ 8775 if(!pSiS->ShadowFB) SISDGAInit(pScreen); 8776 8777 xf86SetBlackWhitePixels(pScreen); 8778 8779 /* Initialize the accelerators */ 8780 switch(pSiS->VGAEngine) { 8781 case SIS_530_VGA: 8782 case SIS_300_VGA: 8783 SiS300AccelInit(pScreen); 8784 break; 8785 case SIS_315_VGA: 8786 SiS315AccelInit(pScreen); 8787 break; 8788 default: 8789 SiSAccelInit(pScreen); 8790 } 8791 8792#ifdef TWDEBUG 8793 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CPUFlags %x\n", pSiS->CPUFlags); 8794#endif 8795 8796 /* Benchmark memcpy() methods (needs FB manager initialized) */ 8797 /* Dual head: Do this AFTER the mode for CRT1 has been set */ 8798 pSiS->NeedCopyFastVidCpy = FALSE; 8799 if(!pSiS->SiSFastVidCopyDone) { 8800#ifdef SISDUALHEAD 8801 if(pSiS->DualHeadMode) { 8802 if(pSiS->SecondHead) { 8803 pSiSEnt->SiSFastVidCopy = SiSVidCopyInit(pScreen, &pSiSEnt->SiSFastMemCopy, FALSE); 8804 pSiSEnt->SiSFastVidCopyFrom = SiSVidCopyGetDefault(); 8805 pSiSEnt->SiSFastMemCopyFrom = SiSVidCopyGetDefault(); 8806#ifdef SIS_USE_EXA 8807 if(pSiS->useEXA) { 8808 pSiSEnt->SiSFastVidCopyFrom = SiSVidCopyInit(pScreen, &pSiSEnt->SiSFastMemCopyFrom, TRUE); 8809 } 8810#endif /* EXA */ 8811 pSiSEnt->HaveFastVidCpy = TRUE; 8812 pSiS->SiSFastVidCopy = pSiSEnt->SiSFastVidCopy; 8813 pSiS->SiSFastMemCopy = pSiSEnt->SiSFastMemCopy; 8814 pSiS->SiSFastVidCopyFrom = pSiSEnt->SiSFastVidCopyFrom; 8815 pSiS->SiSFastMemCopyFrom = pSiSEnt->SiSFastMemCopyFrom; 8816 } else { 8817 pSiS->NeedCopyFastVidCpy = TRUE; 8818 } 8819 } else { 8820#endif 8821 pSiS->SiSFastVidCopy = SiSVidCopyInit(pScreen, &pSiS->SiSFastMemCopy, FALSE); 8822 pSiS->SiSFastVidCopyFrom = SiSVidCopyGetDefault(); 8823 pSiS->SiSFastMemCopyFrom = SiSVidCopyGetDefault(); 8824#ifdef SIS_USE_EXA 8825 if(pSiS->useEXA) { 8826 pSiS->SiSFastVidCopyFrom = SiSVidCopyInit(pScreen, &pSiS->SiSFastMemCopyFrom, TRUE); 8827 } 8828#endif /* EXA */ 8829#ifdef SISDUALHEAD 8830 } 8831#endif 8832 } 8833 pSiS->SiSFastVidCopyDone = TRUE; 8834 8835 miInitializeBackingStore(pScreen); 8836 xf86SetBackingStore(pScreen); 8837 xf86SetSilkenMouse(pScreen); 8838 8839 /* Initialise cursor functions */ 8840 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 8841 8842 if(pSiS->HWCursor) { 8843 SiSHWCursorInit(pScreen); 8844 } 8845 8846#ifdef SISDUALHEAD 8847 if(!pSiS->DualHeadMode) { 8848#endif 8849 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && (pScrn->depth > 8)) { 8850 8851 pSiS->CRT2ColNum = 1 << pScrn->rgbBits; 8852 8853 if((pSiS->crt2gcolortable = xalloc(pSiS->CRT2ColNum * 2 * sizeof(LOCO)))) { 8854 pSiS->crt2colors = &pSiS->crt2gcolortable[pSiS->CRT2ColNum]; 8855 if((pSiS->crt2cindices = xalloc(256 * sizeof(int)))) { 8856 int i = pSiS->CRT2ColNum; 8857 SISCalculateGammaRampCRT2(pScrn); 8858 while(i--) pSiS->crt2cindices[i] = i; 8859 } else { 8860 xfree(pSiS->crt2gcolortable); 8861 pSiS->crt2gcolortable = NULL; 8862 pSiS->CRT2SepGamma = FALSE; 8863 } 8864 } else { 8865 pSiS->CRT2SepGamma = FALSE; 8866 } 8867 8868 if(!pSiS->crt2cindices) { 8869 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 8870 "Failed to allocate cmap for CRT2, separate gamma correction disabled\n"); 8871 } 8872 8873 } 8874#ifdef SISDUALHEAD 8875 } else pSiS->CRT2SepGamma = FALSE; 8876#endif 8877 8878 /* Initialise default colormap */ 8879 if(!miCreateDefColormap(pScreen)) { 8880 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8881 SISErrorLog(pScrn, "miCreateDefColormap() failed\n"); 8882 return FALSE; 8883 } 8884 8885 if(!xf86HandleColormaps(pScreen, 256, (pScrn->depth == 8) ? 8 : pScrn->rgbBits, 8886 SISLoadPalette, NULL, 8887 CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH)) { 8888 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8889 SISErrorLog(pScrn, "xf86HandleColormaps() failed\n"); 8890 return FALSE; 8891 } 8892 8893 /* Recalculate our gamma ramp for brightness feature */ 8894#ifdef SISGAMMARAMP 8895 if((pSiS->GammaBriR != 1000) || 8896 (pSiS->GammaBriB != 1000) || 8897 (pSiS->GammaBriG != 1000) || 8898 (pSiS->NewGammaBriR != 0.0) || 8899 (pSiS->NewGammaBriG != 0.0) || 8900 (pSiS->NewGammaBriB != 0.0) || 8901 (pSiS->NewGammaConR != 0.0) || 8902 (pSiS->NewGammaConG != 0.0) || 8903 (pSiS->NewGammaConB != 0.0)) { 8904 SISCalculateGammaRamp(pScreen, pScrn); 8905 } 8906#endif 8907 8908 /* Initialize Shadow framebuffer and screen rotation/reflection */ 8909 if(pSiS->ShadowFB) { 8910 RefreshAreaFuncPtr refreshArea = SISRefreshArea; 8911 8912 if(pSiS->Rotate) { 8913 if(!pSiS->PointerMoved) pSiS->PointerMoved = pScrn->PointerMoved; 8914 pScrn->PointerMoved = SISPointerMoved; 8915 switch(pScrn->bitsPerPixel) { 8916 case 8: refreshArea = SISRefreshArea8; break; 8917 case 16: refreshArea = SISRefreshArea16; break; 8918 case 24: refreshArea = SISRefreshArea24; break; 8919 case 32: refreshArea = SISRefreshArea32; break; 8920 } 8921#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 8922 xf86DisableRandR(); 8923 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8924 "Driver rotation enabled, disabling RandR\n"); 8925#endif 8926 } else if(pSiS->Reflect) { 8927 switch(pScrn->bitsPerPixel) { 8928 case 8: 8929 case 16: 8930 case 32: 8931 if(!pSiS->PointerMoved) pSiS->PointerMoved = pScrn->PointerMoved; 8932 pScrn->PointerMoved = SISPointerMovedReflect; 8933 refreshArea = SISRefreshAreaReflect; 8934#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 8935 xf86DisableRandR(); 8936 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8937 "Driver reflection enabled, disabling RandR\n"); 8938#endif 8939 break; 8940 default: 8941 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 8942 "Reflection not supported at this framebuffer depth\n"); 8943 } 8944 } 8945 8946 ShadowFBInit(pScreen, refreshArea); 8947 } 8948 8949 xf86DPMSInit(pScreen, (DPMSSetProcPtr)SISDisplayPowerManagementSet, 0); 8950 8951 /* Init memPhysBase and fbOffset in pScrn */ 8952 pScrn->memPhysBase = pSiS->FbAddress; 8953 pScrn->fbOffset = 0; 8954 8955 /* Initialize Xv */ 8956 pSiS->ResetXv = pSiS->ResetXvGamma = pSiS->ResetXvDisplay = NULL; 8957#if (XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,99,0,0)) || (defined(XvExtension)) 8958 if((!pSiS->NoXvideo) && (!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY))) { 8959 8960 if((pSiS->VGAEngine == SIS_300_VGA) || 8961 (pSiS->VGAEngine == SIS_315_VGA)) { 8962 8963 const char *using = "Using SiS300/315/330/340 series HW Xv"; 8964 8965#ifdef SISDUALHEAD 8966 if(pSiS->DualHeadMode) { 8967 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8968 "%s on CRT%d\n", using, (pSiS->SecondHead ? 1 : 2)); 8969 if(!pSiS->hasTwoOverlays) { 8970 if( (pSiS->XvOnCRT2 && pSiS->SecondHead) || 8971 (!pSiS->XvOnCRT2 && !pSiS->SecondHead) ) { 8972 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8973 "However, video overlay will by default only be visible on CRT%d\n", 8974 pSiS->XvOnCRT2 ? 2 : 1); 8975 } 8976 } 8977 } else { 8978#endif 8979 if(pSiS->hasTwoOverlays) { 8980 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s\n", using); 8981 } else { 8982 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s by default on CRT%d\n", 8983 using, (pSiS->XvOnCRT2 ? 2 : 1)); 8984 } 8985#ifdef SISDUALHEAD 8986 } 8987#endif 8988 8989 SISInitVideo(pScreen); 8990 8991 if(pSiS->blitadaptor) { 8992 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8993 "Default Xv adaptor is Video %s\n", 8994 pSiS->XvDefAdaptorBlit ? "Blitter" : "Overlay"); 8995 } 8996 8997 } else if(pSiS->Chipset == PCI_CHIP_SIS530 || 8998 pSiS->Chipset == PCI_CHIP_SIS6326 || 8999 pSiS->Chipset == PCI_CHIP_SIS5597) { 9000 9001 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9002 "Using SiS5597/5598/6326/530/620 HW Xv\n" ); 9003 9004 SIS6326InitVideo(pScreen); 9005 9006 } else { /* generic Xv */ 9007 9008 XF86VideoAdaptorPtr *ptr; 9009 int n = xf86XVListGenericAdaptors(pScrn, &ptr); 9010 9011 if(n) { 9012 xf86XVScreenInit(pScreen, ptr, n); 9013 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using generic Xv\n" ); 9014 } 9015 9016 } 9017 } 9018#endif 9019 9020#ifdef XF86DRI 9021 if(pSiS->loadDRI) { 9022 if(pSiS->directRenderingEnabled) { 9023 /* Now that mi, drm and others have done their thing, 9024 * complete the DRI setup. 9025 */ 9026 pSiS->directRenderingEnabled = SISDRIFinishScreenInit(pScreen); 9027 } 9028 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering %s\n", 9029 pSiS->directRenderingEnabled ? "enabled" : "disabled"); 9030 /* TODO */ 9031 /* if(pSiS->directRenderingEnabled) SISSetLFBConfig(pSiS); */ 9032 } 9033#endif 9034 9035 /* Wrap some funcs, initialize pseudo-Xinerama and setup remaining SD flags */ 9036 9037 pSiS->SiS_SD_Flags &= ~(SiS_SD_PSEUDOXINERAMA); 9038#ifdef SISMERGED 9039 if(pSiS->MergedFB) { 9040 pSiS->PointerMoved = pScrn->PointerMoved; 9041 pScrn->PointerMoved = SISMergedPointerMoved; 9042 pSiS->Rotate = 0; 9043 pSiS->Reflect = 0; 9044 pSiS->ShadowFB = FALSE; 9045#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 9046 if(pSiS->CRT1XOffs || pSiS->CRT1YOffs || pSiS->CRT2XOffs || pSiS->CRT2YOffs) { 9047 xf86DisableRandR(); 9048 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9049 "MergedFB: CRT2Position offset used, disabling RandR\n"); 9050 } 9051#endif 9052#ifdef SISXINERAMA 9053 if(pSiS->UseSiSXinerama) { 9054 SiSnoPanoramiXExtension = FALSE; 9055 SiSXineramaExtensionInit(pScrn); 9056 if(!SiSnoPanoramiXExtension) { 9057 pSiS->SiS_SD_Flags |= SiS_SD_PSEUDOXINERAMA; 9058 if(pSiS->HaveNonRect) { 9059 /* Reset the viewport (now eventually non-recangular) */ 9060 SISAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 9061 } 9062 } 9063 } else { 9064 pSiS->MouseRestrictions = FALSE; 9065 } 9066#endif 9067 } 9068#endif 9069 9070 /* Wrap CloseScreen and set up SaveScreen */ 9071 pSiS->CloseScreen = pScreen->CloseScreen; 9072 pScreen->CloseScreen = SISCloseScreen; 9073#ifdef SISDUALHEAD 9074 if(pSiS->DualHeadMode) 9075 pScreen->SaveScreen = SISSaveScreenDH; 9076 else 9077#endif 9078 pScreen->SaveScreen = SISSaveScreen; 9079 9080 /* Install BlockHandler */ 9081 pSiS->BlockHandler = pScreen->BlockHandler; 9082 pScreen->BlockHandler = SISBlockHandler; 9083 9084 /* Report any unused options (only for the first generation) */ 9085 if(serverGeneration == 1) { 9086 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 9087 } 9088 9089 /* Clear frame buffer */ 9090 /* For CRT2, we don't do that at this point in dual head 9091 * mode since the mode isn't switched at this time (it will 9092 * be reset when setting the CRT1 mode). Hence, we just 9093 * save the necessary data and clear the screen when 9094 * going through this for CRT1. 9095 */ 9096 9097 OnScreenSize = pScrn->displayWidth * pScrn->currentMode->VDisplay 9098 * (pScrn->bitsPerPixel >> 3); 9099 9100 /* Turn on the screen now */ 9101 /* We do this in dual head mode after second head is finished */ 9102#ifdef SISDUALHEAD 9103 if(pSiS->DualHeadMode) { 9104 if(pSiS->SecondHead) { 9105 sisclearvram(pSiS->FbBase, OnScreenSize); 9106 sisclearvram(pSiSEnt->FbBase1, pSiSEnt->OnScreenSize1); 9107 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 9108 } else { 9109 pSiSEnt->FbBase1 = pSiS->FbBase; 9110 pSiSEnt->OnScreenSize1 = OnScreenSize; 9111 } 9112 } else { 9113#endif 9114 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 9115 sisclearvram(pSiS->FbBase, OnScreenSize); 9116#ifdef SISDUALHEAD 9117 } 9118#endif 9119 9120 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTSGRCRT2; 9121#ifdef SISDUALHEAD 9122 if(!pSiS->DualHeadMode) { 9123#endif 9124 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 9125 if((pSiS->crt2cindices) && (pSiS->crt2gcolortable)) { 9126 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTSGRCRT2; 9127 } 9128 } 9129#ifdef SISDUALHEAD 9130 } 9131#endif 9132 9133 pSiS->SiS_SD_Flags &= ~SiS_SD_ISDEPTH8; 9134 if(pSiS->CurrentLayout.bitsPerPixel == 8) { 9135 pSiS->SiS_SD_Flags |= SiS_SD_ISDEPTH8; 9136 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTXVGAMMA1; 9137 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTSGRCRT2; 9138 } 9139 9140#ifdef SISGAMMARAMP 9141 pSiS->SiS_SD_Flags |= SiS_SD_CANSETGAMMA; 9142#else 9143 pSiS->SiS_SD_Flags &= ~SiS_SD_CANSETGAMMA; 9144#endif 9145 9146 SiSCtrlExtInit(pScrn); 9147 9148 return TRUE; 9149} 9150 9151/* Usually mandatory */ 9152Bool 9153SISSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) 9154{ 9155 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 9156 SISPtr pSiS = SISPTR(pScrn); 9157 9158 if(!pSiS->skipswitchcheck) { 9159 if(SISValidMode(scrnIndex, mode, TRUE, flags) != MODE_OK) { 9160 return FALSE; 9161 } 9162 } 9163 9164 (*pSiS->SyncAccel)(pScrn); 9165 9166 if(!(SISModeInit(xf86Screens[scrnIndex], mode))) return FALSE; 9167 9168 /* Since RandR (indirectly) uses SwitchMode(), we need to 9169 * update our Xinerama info here, too, in case of resizing 9170 */ 9171#ifdef SISMERGED 9172#ifdef SISXINERAMA 9173 if(pSiS->MergedFB) { 9174 SiSUpdateXineramaScreenInfo(pScrn); 9175 } 9176#endif 9177#endif 9178 return TRUE; 9179} 9180 9181static void 9182SISSetStartAddressCRT1(SISPtr pSiS, ULong base) 9183{ 9184 UChar cr11backup; 9185 9186 inSISIDXREG(SISCR, 0x11, cr11backup); /* Unlock CRTC registers */ 9187 andSISIDXREG(SISCR, 0x11, 0x7F); 9188 outSISIDXREG(SISCR, 0x0D, base & 0xFF); 9189 outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); 9190 outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF); 9191 if(pSiS->VGAEngine == SIS_315_VGA) { 9192 setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01); 9193 } 9194 /* Eventually lock CRTC registers */ 9195 setSISIDXREG(SISCR, 0x11, 0x7F,(cr11backup & 0x80)); 9196} 9197 9198static void 9199SISSetStartAddressCRT2(SISPtr pSiS, ULong base) 9200{ 9201 SiS_UnLockCRT2(pSiS->SiS_Pr); 9202 outSISIDXREG(SISPART1, 0x06, GETVAR8(base)); 9203 outSISIDXREG(SISPART1, 0x05, GETBITS(base, 15:8)); 9204 outSISIDXREG(SISPART1, 0x04, GETBITS(base, 23:16)); 9205 if(pSiS->VGAEngine == SIS_315_VGA) { 9206 setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7); 9207 } 9208 SiS_LockCRT2(pSiS->SiS_Pr); 9209} 9210 9211#ifdef SISMERGED 9212static Bool 9213InRegion(int x, int y, region r) 9214{ 9215 return (r.x0 <= x) && (x <= r.x1) && (r.y0 <= y) && (y <= r.y1); 9216} 9217 9218static void 9219SISAdjustFrameHW_CRT1(ScrnInfoPtr pScrn, int x, int y) 9220{ 9221 SISPtr pSiS = SISPTR(pScrn); 9222 ULong base; 9223 9224 base = y * pSiS->CurrentLayout.displayWidth + x; 9225 switch(pSiS->CurrentLayout.bitsPerPixel) { 9226 case 16: base >>= 1; break; 9227 case 32: break; 9228 default: base >>= 2; 9229 } 9230 base += (pSiS->dhmOffset/4); 9231 SISSetStartAddressCRT1(pSiS, base); 9232} 9233 9234static void 9235SISAdjustFrameHW_CRT2(ScrnInfoPtr pScrn, int x, int y) 9236{ 9237 SISPtr pSiS = SISPTR(pScrn); 9238 ULong base; 9239 9240 base = y * pSiS->CurrentLayout.displayWidth + x; 9241 switch(pSiS->CurrentLayout.bitsPerPixel) { 9242 case 16: base >>= 1; break; 9243 case 32: break; 9244 default: base >>= 2; 9245 } 9246 base += (pSiS->dhmOffset/4); 9247 SISSetStartAddressCRT2(pSiS, base); 9248} 9249 9250static void 9251SISMergedPointerMoved(int scrnIndex, int x, int y) 9252{ 9253 ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex]; 9254 SISPtr pSiS = SISPTR(pScrn1); 9255 ScrnInfoPtr pScrn2 = pSiS->CRT2pScrn; 9256 region out, in1, in2, f2, f1; 9257 int deltax, deltay; 9258 int temp1, temp2; 9259 int old1x0, old1y0, old2x0, old2y0; 9260 int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; 9261 int HVirt = pScrn1->virtualX; 9262 int VVirt = pScrn1->virtualY; 9263 int sigstate; 9264 Bool doit = FALSE, HaveNonRect = FALSE, HaveOffsRegions = FALSE; 9265 SiSScrn2Rel srel = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT2Position; 9266 9267 if(pSiS->DGAactive) { 9268 return; 9269 /* DGA: There is no cursor and no panning while DGA is active. */ 9270 /* If it were, we would need to do: */ 9271 /* HVirt = pSiS->CurrentLayout.displayWidth; 9272 VVirt = pSiS->CurrentLayout.displayHeight; 9273 BOUND(x, pSiS->CurrentLayout.DGAViewportX, HVirt); 9274 BOUND(y, pSiS->CurrentLayout.DGAViewportY, VVirt); */ 9275 } else { 9276 CRT1XOffs = pSiS->CRT1XOffs; 9277 CRT1YOffs = pSiS->CRT1YOffs; 9278 CRT2XOffs = pSiS->CRT2XOffs; 9279 CRT2YOffs = pSiS->CRT2YOffs; 9280 HaveNonRect = pSiS->HaveNonRect; 9281 HaveOffsRegions = pSiS->HaveOffsRegions; 9282 } 9283 9284 /* Check if the pointer is inside our dead areas */ 9285 if((pSiS->MouseRestrictions) && (srel != sisClone) && !SiSnoPanoramiXExtension) { 9286 if(HaveNonRect) { 9287 if(InRegion(x, y, pSiS->NonRectDead)) { 9288 switch(srel) { 9289 case sisLeftOf: 9290 case sisRightOf: y = pSiS->NonRectDead.y0 - 1; 9291 doit = TRUE; 9292 break; 9293 case sisAbove: 9294 case sisBelow: x = pSiS->NonRectDead.x0 - 1; 9295 doit = TRUE; 9296 default: break; 9297 } 9298 } 9299 } 9300 if(HaveOffsRegions) { 9301 if(InRegion(x, y, pSiS->OffDead1)) { 9302 switch(srel) { 9303 case sisLeftOf: 9304 case sisRightOf: y = pSiS->OffDead1.y1; 9305 doit = TRUE; 9306 break; 9307 case sisAbove: 9308 case sisBelow: x = pSiS->OffDead1.x1; 9309 doit = TRUE; 9310 default: break; 9311 } 9312 } else if(InRegion(x, y, pSiS->OffDead2)) { 9313 switch(srel) { 9314 case sisLeftOf: 9315 case sisRightOf: y = pSiS->OffDead2.y0 - 1; 9316 doit = TRUE; 9317 break; 9318 case sisAbove: 9319 case sisBelow: x = pSiS->OffDead2.x0 - 1; 9320 doit = TRUE; 9321 default: break; 9322 } 9323 } 9324 } 9325 if(doit) { 9326 sigstate = xf86BlockSIGIO(); 9327 miPointerSetPosition(inputInfo.pointer, x, y); 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