sis_driver.c revision eee1ded1
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 "edid.h" 61 62#define SIS_NEED_inSISREG 63#define SIS_NEED_inSISIDXREG 64#define SIS_NEED_outSISIDXREG 65#define SIS_NEED_orSISIDXREG 66#define SIS_NEED_andSISIDXREG 67#define SIS_NEED_setSISIDXREG 68#define SIS_NEED_outSISREG 69#define SIS_NEED_MYMMIO 70#define SIS_NEED_sisclearvram 71#include "sis_regs.h" 72#include "sis_dac.h" 73 74#include "sis_driver.h" 75 76#include <X11/extensions/xf86dgaproto.h> 77 78#include "globals.h" 79 80#ifdef HAVE_XEXTPROTO_71 81#include <X11/extensions/dpmsconst.h> 82#else 83#define DPMS_SERVER 84#include <X11/extensions/dpms.h> 85#endif 86 87#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 5 88#include <inputstr.h> /* for inputInfo */ 89#endif 90 91 92#ifdef SISDRI 93#include "dri.h" 94#endif 95 96#ifndef DEFAULT_DPI 97#define DEFAULT_DPI 96 98#endif 99 100/* 101 * LookupWindow was removed with video abi 11. 102 */ 103#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 4) 104#ifndef DixGetAttrAccess 105#define DixGetAttrAccess (1<<4) 106#endif 107#endif 108 109#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 2) 110static inline int 111dixLookupWindow(WindowPtr *pWin, XID id, ClientPtr client, Mask access) 112{ 113 *pWin = LookupWindow(id, client); 114 if (!*pWin) 115 return BadWindow; 116 return Success; 117} 118#endif 119 120/* Globals (yes, these ARE really required to be global) */ 121 122#ifdef SISUSEDEVPORT 123int sisdevport = 0; 124#endif 125 126#ifdef SISDUALHEAD 127static int SISEntityIndex = -1; 128#endif 129 130#ifdef SISMERGED 131#ifdef SISXINERAMA 132static Bool SiSnoPanoramiXExtension = TRUE; 133static int SiSXineramaNumScreens = 0; 134static SiSXineramaData *SiSXineramadataPtr = NULL; 135static int SiSXineramaGeneration; 136 137static int SiSProcXineramaQueryVersion(ClientPtr client); 138static int SiSProcXineramaGetState(ClientPtr client); 139static int SiSProcXineramaGetScreenCount(ClientPtr client); 140static int SiSProcXineramaGetScreenSize(ClientPtr client); 141static int SiSProcXineramaIsActive(ClientPtr client); 142static int SiSProcXineramaQueryScreens(ClientPtr client); 143static int SiSSProcXineramaDispatch(ClientPtr client); 144#endif 145#endif 146 147/* 148 * This is intentionally screen-independent. It indicates the binding 149 * choice made in the first PreInit. 150 */ 151static int pix24bpp = 0; 152 153/* 154 * This contains the functions needed by the server after loading the driver 155 * module. It must be supplied, and gets passed back by the SetupProc 156 * function in the dynamic case. In the static case, a reference to this 157 * is compiled in, and this requires that the name of this DriverRec be 158 * an upper-case version of the driver name. 159 */ 160 161#ifdef _X_EXPORT 162_X_EXPORT 163#endif 164DriverRec SIS = { 165 SIS_CURRENT_VERSION, 166 SIS_DRIVER_NAME, 167 SISIdentify, 168 SISProbe, 169 SISAvailableOptions, 170 NULL, 171 0 172#ifdef SIS_HAVE_DRIVER_FUNC 173 , 174 SISDriverFunc 175#endif 176}; 177 178static SymTabRec SISChipsets[] = { 179 { PCI_CHIP_SIS5597, "SIS5597/5598" }, 180 { PCI_CHIP_SIS530, "SIS530/620" }, 181 { PCI_CHIP_SIS6326, "SIS6326/AGP/DVD" }, 182 { PCI_CHIP_SIS300, "SIS300/305" }, 183 { PCI_CHIP_SIS630, "SIS630/730" }, 184 { PCI_CHIP_SIS540, "SIS540" }, 185 { PCI_CHIP_SIS315, "SIS315" }, 186 { PCI_CHIP_SIS315H, "SIS315H" }, 187 { PCI_CHIP_SIS315PRO, "SIS315PRO/E" }, 188 { PCI_CHIP_SIS550, "SIS550" }, 189 { PCI_CHIP_SIS650, "SIS650/M650/651/740" }, 190 { PCI_CHIP_SIS330, "SIS330(Xabre)" }, 191 { PCI_CHIP_SIS660, "SIS660/[M]661[F|M]X/[M]670/[M]741[GX]/[M]760[GX]/[M]761[GX]/[M]770[GX]" }, 192 { PCI_CHIP_SIS340, "SIS340" }, 193 { -1, NULL } 194}; 195 196static PciChipsets SISPciChipsets[] = { 197 { PCI_CHIP_SIS5597, PCI_CHIP_SIS5597, RES_SHARED_VGA }, 198 { PCI_CHIP_SIS530, PCI_CHIP_SIS530, RES_SHARED_VGA }, 199 { PCI_CHIP_SIS6326, PCI_CHIP_SIS6326, RES_SHARED_VGA }, 200 { PCI_CHIP_SIS300, PCI_CHIP_SIS300, RES_SHARED_VGA }, 201 { PCI_CHIP_SIS630, PCI_CHIP_SIS630, RES_SHARED_VGA }, 202 { PCI_CHIP_SIS540, PCI_CHIP_SIS540, RES_SHARED_VGA }, 203 { PCI_CHIP_SIS550, PCI_CHIP_SIS550, RES_SHARED_VGA }, 204 { PCI_CHIP_SIS315, PCI_CHIP_SIS315, RES_SHARED_VGA }, 205 { PCI_CHIP_SIS315H, PCI_CHIP_SIS315H, RES_SHARED_VGA }, 206 { PCI_CHIP_SIS315PRO, PCI_CHIP_SIS315PRO, RES_SHARED_VGA }, 207 { PCI_CHIP_SIS650, PCI_CHIP_SIS650, RES_SHARED_VGA }, 208 { PCI_CHIP_SIS330, PCI_CHIP_SIS330, RES_SHARED_VGA }, 209 { PCI_CHIP_SIS660, PCI_CHIP_SIS660, RES_SHARED_VGA }, 210 { PCI_CHIP_SIS340, PCI_CHIP_SIS340, RES_SHARED_VGA }, 211 { -1, -1, RES_UNDEFINED } 212}; 213 214static SymTabRec XGIChipsets[] = { 215 { PCI_CHIP_XGIXG20, "Volari Z7 (XG20)" }, 216 { PCI_CHIP_XGIXG40, "Volari V3XT/V5/V8/Duo (XG40)" }, 217 { -1, NULL } 218}; 219 220static PciChipsets XGIPciChipsets[] = { 221 { PCI_CHIP_XGIXG20, PCI_CHIP_XGIXG20, RES_SHARED_VGA }, 222 { PCI_CHIP_XGIXG40, PCI_CHIP_XGIXG40, RES_SHARED_VGA }, 223 { -1, -1, RES_UNDEFINED } 224}; 225 226#ifdef XFree86LOADER 227 228static MODULESETUPPROTO(sisSetup); 229 230static XF86ModuleVersionInfo sisVersRec = 231{ 232 SIS_DRIVER_NAME, 233 MODULEVENDORSTRING, 234 MODINFOSTRING1, 235 MODINFOSTRING2, 236#ifdef XORG_VERSION_CURRENT 237 XORG_VERSION_CURRENT, 238#else 239 XF86_VERSION_CURRENT, 240#endif 241 SIS_MAJOR_VERSION, SIS_MINOR_VERSION, SIS_PATCHLEVEL, 242 ABI_CLASS_VIDEODRV, /* This is a video driver */ 243 ABI_VIDEODRV_VERSION, 244 MOD_CLASS_VIDEODRV, 245 {0,0,0,0} 246}; 247 248#ifdef _X_EXPORT 249_X_EXPORT 250#endif 251XF86ModuleData sisModuleData = { &sisVersRec, sisSetup, NULL }; 252 253pointer 254sisSetup(pointer module, pointer opts, int *errmaj, int *errmin) 255{ 256 static Bool setupDone = FALSE; 257 258 if(!setupDone) { 259 setupDone = TRUE; 260 xf86AddDriver(&SIS, module, SIS_HaveDriverFuncs); 261 return (pointer)TRUE; 262 } 263 264 if(errmaj) *errmaj = LDR_ONCEONLY; 265 return NULL; 266} 267 268#endif /* XFree86LOADER */ 269 270/* Mandatory */ 271static void 272SISIdentify(int flags) 273{ 274 xf86PrintChipsets(SIS_NAME, "driver for SiS chipsets", SISChipsets); 275 xf86PrintChipsets(SIS_NAME, "driver for XGI chipsets", XGIChipsets); 276} 277 278#ifdef SIS_HAVE_DRIVER_FUNC 279static Bool 280SISDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op, pointer ptr) 281{ 282 CARD32 *flag; 283 284 switch(op) { 285 case RR_GET_INFO: 286 break; 287 case RR_SET_CONFIG: 288 break; 289 case GET_REQUIRED_HW_INTERFACES: 290 break; 291 } 292 return TRUE; 293} 294#endif 295 296static Bool 297SISGetRec(ScrnInfoPtr pScrn) 298{ 299 /* Allocate an SISRec, and hook it into pScrn->driverPrivate. 300 * pScrn->driverPrivate is initialised to NULL, so we can check if 301 * the allocation has already been done. 302 */ 303 if(pScrn->driverPrivate != NULL) return TRUE; 304 305 pScrn->driverPrivate = xnfcalloc(sizeof(SISRec), 1); 306 307 /* Initialise it to 0 */ 308 memset(pScrn->driverPrivate, 0, sizeof(SISRec)); 309 310 return TRUE; 311} 312 313static void 314SISFreeRec(ScrnInfoPtr pScrn) 315{ 316 SISPtr pSiS = SISPTR(pScrn); 317#ifdef SISDUALHEAD 318 SISEntPtr pSiSEnt = NULL; 319#endif 320 321 /* Just to make sure... */ 322 if(!pSiS) return; 323 324#ifdef SISDUALHEAD 325 pSiSEnt = pSiS->entityPrivate; 326#endif 327 328 if(pSiS->pstate) free(pSiS->pstate); 329 pSiS->pstate = NULL; 330 if(pSiS->fonts) free(pSiS->fonts); 331 pSiS->fonts = NULL; 332 333#ifdef SISDUALHEAD 334 if(pSiSEnt) { 335 if(!pSiS->SecondHead) { 336 /* Free memory only if we are first head; in case of an error 337 * during init of the second head, the server will continue - 338 * and we need the BIOS image and SiS_Private for the first 339 * head. 340 */ 341 if(pSiSEnt->BIOS) free(pSiSEnt->BIOS); 342 pSiSEnt->BIOS = pSiS->BIOS = NULL; 343 if(pSiSEnt->SiS_Pr) free(pSiSEnt->SiS_Pr); 344 pSiSEnt->SiS_Pr = pSiS->SiS_Pr = NULL; 345 if(pSiSEnt->RenderAccelArray) free(pSiSEnt->RenderAccelArray); 346 pSiSEnt->RenderAccelArray = pSiS->RenderAccelArray = NULL; 347 pSiSEnt->pScrn_1 = NULL; 348 } else { 349 pSiS->BIOS = NULL; 350 pSiS->SiS_Pr = NULL; 351 pSiS->RenderAccelArray = NULL; 352 pSiSEnt->pScrn_2 = NULL; 353 } 354 } else { 355#endif 356 if(pSiS->BIOS) free(pSiS->BIOS); 357 pSiS->BIOS = NULL; 358 if(pSiS->SiS_Pr) free(pSiS->SiS_Pr); 359 pSiS->SiS_Pr = NULL; 360 if(pSiS->RenderAccelArray) free(pSiS->RenderAccelArray); 361 pSiS->RenderAccelArray = NULL; 362#ifdef SISDUALHEAD 363 } 364#endif 365#ifdef SISMERGED 366 if(pSiS->CRT2HSync) free(pSiS->CRT2HSync); 367 pSiS->CRT2HSync = NULL; 368 if(pSiS->CRT2VRefresh) free(pSiS->CRT2VRefresh); 369 pSiS->CRT2VRefresh = NULL; 370 if(pSiS->MetaModes) free(pSiS->MetaModes); 371 pSiS->MetaModes = NULL; 372 if(pSiS->CRT2pScrn) { 373 if(pSiS->CRT2pScrn->modes) { 374 while(pSiS->CRT2pScrn->modes) 375 xf86DeleteMode(&pSiS->CRT2pScrn->modes, pSiS->CRT2pScrn->modes); 376 } 377 if(pSiS->CRT2pScrn->monitor) { 378 if(pSiS->CRT2pScrn->monitor->Modes) { 379 while(pSiS->CRT2pScrn->monitor->Modes) 380 xf86DeleteMode(&pSiS->CRT2pScrn->monitor->Modes, pSiS->CRT2pScrn->monitor->Modes); 381 } 382 if(pSiS->CRT2pScrn->monitor->DDC) free(pSiS->CRT2pScrn->monitor->DDC); 383 free(pSiS->CRT2pScrn->monitor); 384 } 385 free(pSiS->CRT2pScrn); 386 pSiS->CRT2pScrn = NULL; 387 } 388 if(pSiS->CRT1Modes) { 389 if(pSiS->CRT1Modes != pScrn->modes) { 390 if(pScrn->modes) { 391 pScrn->currentMode = pScrn->modes; 392 do { 393 DisplayModePtr p = pScrn->currentMode->next; 394 if(pScrn->currentMode->Private) 395 free(pScrn->currentMode->Private); 396 free(pScrn->currentMode); 397 pScrn->currentMode = p; 398 } while(pScrn->currentMode != pScrn->modes); 399 } 400 pScrn->currentMode = pSiS->CRT1CurrentMode; 401 pScrn->modes = pSiS->CRT1Modes; 402 pSiS->CRT1CurrentMode = NULL; 403 pSiS->CRT1Modes = NULL; 404 } 405 } 406#endif 407 while(pSiS->SISVESAModeList) { 408 sisModeInfoPtr mp = pSiS->SISVESAModeList->next; 409 free(pSiS->SISVESAModeList); 410 pSiS->SISVESAModeList = mp; 411 } 412 if(pSiS->pVbe) vbeFree(pSiS->pVbe); 413 pSiS->pVbe = NULL; 414 415#ifdef SISUSEDEVPORT 416 if(pSiS->sisdevportopen) close(sisdevport); 417#endif 418 419 if(pScrn->driverPrivate == NULL) 420 return; 421 free(pScrn->driverPrivate); 422 pScrn->driverPrivate = NULL; 423} 424 425static void 426SISErrorLog(ScrnInfoPtr pScrn, const char *format, ...) 427{ 428 va_list ap; 429 static const char str[] = "**************************************************\n"; 430 431 va_start(ap, format); 432 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s", str); 433 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 434 " ERROR:\n"); 435 xf86VDrvMsgVerb(pScrn->scrnIndex, X_ERROR, 1, format, ap); 436 va_end(ap); 437 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 438 " END OF MESSAGE\n"); 439 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s", str); 440} 441 442static void 443SiS_SiSFB_Lock(ScrnInfoPtr pScrn, Bool lock) 444{ 445 SISPtr pSiS = SISPTR(pScrn); 446 int fd; 447 CARD32 parm; 448 449 if(!pSiS->sisfbfound) return; 450 if(!pSiS->sisfb_havelock) return; 451 452 if((fd = open(pSiS->sisfbdevname, O_RDONLY)) != -1) { 453 parm = lock ? 1 : 0; 454 ioctl(fd, SISFB_SET_LOCK, &parm); 455 close(fd); 456 } 457} 458 459/* Probe() 460 * 461 * Mandatory 462 */ 463static Bool 464SISProbe(DriverPtr drv, int flags) 465{ 466 int i; 467 GDevPtr *devSections; 468 int *usedChipsSiS, *usedChipsXGI; 469 int numDevSections; 470 int numUsed, numUsedSiS, numUsedXGI; 471 Bool foundScreen = FALSE; 472 473 /* 474 * The aim here is to find all cards that this driver can handle, 475 * and for the ones not already claimed by another driver, claim the 476 * slot, and allocate a ScrnInfoRec. 477 * 478 * This should be a minimal probe, and it should under no circumstances 479 * change the state of the hardware. Because a device is found, don't 480 * assume that it will be used. Don't do any initialisations other than 481 * the required ScrnInfoRec initialisations. Don't allocate any new 482 * data structures. 483 * 484 */ 485 486 /* 487 * Next we check, if there has been a chipset override in the config file. 488 * For this we must find out if there is an active device section which 489 * is relevant, i.e., which has no driver specified or has THIS driver 490 * specified. 491 */ 492 493 if((numDevSections = xf86MatchDevice(SIS_DRIVER_NAME, &devSections)) <= 0) { 494 /* 495 * There's no matching device section in the config file, so quit 496 * now. 497 */ 498 return FALSE; 499 } 500 501 /* 502 * We need to probe the hardware first. We then need to see how this 503 * fits in with what is given in the config file, and allow the config 504 * file info to override any contradictions. 505 */ 506 507 /* 508 * All of the cards this driver supports are PCI, so the "probing" just 509 * amounts to checking the PCI data that the server has already collected. 510 */ 511#ifndef XSERVER_LIBPCIACCESS 512 if(xf86GetPciVideoInfo() == NULL) { 513 /* 514 * We won't let anything in the config file override finding no 515 * PCI video cards at all. 516 */ 517 return FALSE; 518 } 519#endif 520 521 numUsedSiS = xf86MatchPciInstances(SIS_NAME, PCI_VENDOR_SIS, 522 SISChipsets, SISPciChipsets, devSections, 523 numDevSections, drv, &usedChipsSiS); 524 525 numUsedXGI = xf86MatchPciInstances(SIS_NAME, PCI_VENDOR_XGI, 526 XGIChipsets, XGIPciChipsets, devSections, 527 numDevSections, drv, &usedChipsXGI); 528 529 /* Free it since we don't need that list after this */ 530 free(devSections); 531 532 numUsed = numUsedSiS + numUsedXGI; 533 534 if(numUsed <= 0) 535 return FALSE; 536 537 if(flags & PROBE_DETECT) { 538 539 foundScreen = TRUE; 540 541 } else for(i = 0; i < numUsed; i++) { 542 543 ScrnInfoPtr pScrn; 544#ifdef SISDUALHEAD 545 EntityInfoPtr pEnt; 546#endif 547 548 /* Allocate a ScrnInfoRec and claim the slot */ 549 pScrn = NULL; 550 551 if((pScrn = xf86ConfigPciEntity(pScrn, 0, 552 (i < numUsedSiS) ? usedChipsSiS[i] : usedChipsXGI[i-numUsedSiS], 553 (i < numUsedSiS) ? SISPciChipsets : XGIPciChipsets, 554 NULL, NULL, NULL, NULL, NULL))) { 555 /* Fill in what we can of the ScrnInfoRec */ 556 pScrn->driverVersion = SIS_CURRENT_VERSION; 557 pScrn->driverName = SIS_DRIVER_NAME; 558 pScrn->name = SIS_NAME; 559 pScrn->Probe = SISProbe; 560 pScrn->PreInit = SISPreInit; 561 pScrn->ScreenInit = SISScreenInit; 562 pScrn->SwitchMode = SISSwitchMode; 563 pScrn->AdjustFrame = SISAdjustFrame; 564 pScrn->EnterVT = SISEnterVT; 565 pScrn->LeaveVT = SISLeaveVT; 566 pScrn->FreeScreen = SISFreeScreen; 567 pScrn->ValidMode = SISValidMode; 568 569 foundScreen = TRUE; 570 } 571 572#ifdef SISDUALHEAD 573 pEnt = xf86GetEntityInfo((i < numUsedSiS) ? usedChipsSiS[i] : usedChipsXGI[i-numUsedSiS]); 574 575 if(pEnt->chipset == PCI_CHIP_SIS630 || pEnt->chipset == PCI_CHIP_SIS540 || 576 pEnt->chipset == PCI_CHIP_SIS650 || pEnt->chipset == PCI_CHIP_SIS550 || 577 pEnt->chipset == PCI_CHIP_SIS315 || pEnt->chipset == PCI_CHIP_SIS315H || 578 pEnt->chipset == PCI_CHIP_SIS315PRO || pEnt->chipset == PCI_CHIP_SIS330 || 579 pEnt->chipset == PCI_CHIP_SIS300 || pEnt->chipset == PCI_CHIP_SIS660 || 580 pEnt->chipset == PCI_CHIP_SIS340 || pEnt->chipset == PCI_CHIP_XGIXG40) { 581 582 SISEntPtr pSiSEnt = NULL; 583 DevUnion *pPriv; 584 585 xf86SetEntitySharable((i < numUsedSiS) ? usedChipsSiS[i] : usedChipsXGI[i-numUsedSiS]); 586 if(SISEntityIndex < 0) { 587 SISEntityIndex = xf86AllocateEntityPrivateIndex(); 588 } 589 pPriv = xf86GetEntityPrivate(pScrn->entityList[0], SISEntityIndex); 590 if(!pPriv->ptr) { 591 pPriv->ptr = xnfcalloc(sizeof(SISEntRec), 1); 592 pSiSEnt = pPriv->ptr; 593 memset(pSiSEnt, 0, sizeof(SISEntRec)); 594 pSiSEnt->lastInstance = -1; 595 } else { 596 pSiSEnt = pPriv->ptr; 597 } 598 pSiSEnt->lastInstance++; 599 xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0], 600 pSiSEnt->lastInstance); 601 } 602#endif /* DUALHEAD */ 603 604 } 605 606 if(usedChipsSiS) free(usedChipsSiS); 607 if(usedChipsXGI) free(usedChipsXGI); 608 609 return foundScreen; 610} 611 612/* Various helpers */ 613 614static unsigned short 615calcgammaval(int j, int nramp, float invgamma, float bri, float c) 616{ 617 float k = (float)j; 618 float nrm1 = (float)(nramp - 1); 619 float con = c * nrm1 / 3.0; 620 float l, v; 621 622 if(con != 0.0) { 623 l = nrm1 / 2.0; 624 if(con <= 0.0) { 625 k -= l; 626 k *= (l + con) / l; 627 } else { 628 l -= 1.0; 629 k -= l; 630 k *= l / (l - con); 631 } 632 k += l; 633 if(k < 0.0) k = 0.0; 634 } 635 636 if(invgamma == 1.0) { 637 v = k / nrm1 * 65535.0; 638 } else { 639 v = pow(k / nrm1, invgamma) * 65535.0 + 0.5; 640 } 641 642 v += (bri * (65535.0 / 3.0)) ; 643 644 if(v < 0.0) v = 0.0; 645 else if(v > 65535.0) v = 65535.0; 646 647 return (unsigned short)v; 648} 649 650#ifdef SISGAMMARAMP 651void 652SISCalculateGammaRamp(ScreenPtr pScreen, ScrnInfoPtr pScrn) 653{ 654 SISPtr pSiS = SISPTR(pScrn); 655 int i, j, nramp; 656 UShort *ramp[3]; 657 float gamma_max[3], framp; 658 Bool newmethod = FALSE; 659 660 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_OLDGAMMAINUSE)) { 661 newmethod = TRUE; 662 } else { 663 gamma_max[0] = (float)pSiS->GammaBriR / 1000; 664 gamma_max[1] = (float)pSiS->GammaBriG / 1000; 665 gamma_max[2] = (float)pSiS->GammaBriB / 1000; 666 } 667 668 if(!(nramp = xf86GetGammaRampSize(pScreen))) return; 669 670 for(i=0; i<3; i++) { 671 ramp[i] = (UShort *)malloc(nramp * sizeof(UShort)); 672 if(!ramp[i]) { 673 if(ramp[0]) { free(ramp[0]); ramp[0] = NULL; } 674 if(ramp[1]) { free(ramp[1]); ramp[1] = NULL; } 675 return; 676 } 677 } 678 679 if(newmethod) { 680 681 for(i = 0; i < 3; i++) { 682 683 float invgamma = 0.0, bri = 0.0, con = 0.0; 684 685 switch(i) { 686 case 0: invgamma = 1. / pScrn->gamma.red; 687 bri = pSiS->NewGammaBriR; 688 con = pSiS->NewGammaConR; 689 break; 690 case 1: invgamma = 1. / pScrn->gamma.green; 691 bri = pSiS->NewGammaBriG; 692 con = pSiS->NewGammaConG; 693 break; 694 case 2: invgamma = 1. / pScrn->gamma.blue; 695 bri = pSiS->NewGammaBriB; 696 con = pSiS->NewGammaConB; 697 break; 698 } 699 700 for(j = 0; j < nramp; j++) { 701 ramp[i][j] = calcgammaval(j, nramp, invgamma, bri, con); 702 } 703 704 } 705 706 } else { 707 708 for(i = 0; i < 3; i++) { 709 int fullscale = 65535 * gamma_max[i]; 710 float dramp = 1. / (nramp - 1); 711 float invgamma = 0.0, v; 712 713 switch(i) { 714 case 0: invgamma = 1. / pScrn->gamma.red; break; 715 case 1: invgamma = 1. / pScrn->gamma.green; break; 716 case 2: invgamma = 1. / pScrn->gamma.blue; break; 717 } 718 719 for(j = 0; j < nramp; j++) { 720 framp = pow(j * dramp, invgamma); 721 722 v = (fullscale < 0) ? (65535 + fullscale * framp) : 723 fullscale * framp; 724 if(v < 0) v = 0; 725 else if(v > 65535) v = 65535; 726 ramp[i][j] = (UShort)v; 727 } 728 } 729 730 } 731 732 xf86ChangeGammaRamp(pScreen, nramp, ramp[0], ramp[1], ramp[2]); 733 734 free(ramp[0]); 735 free(ramp[1]); 736 free(ramp[2]); 737 ramp[0] = ramp[1] = ramp[2] = NULL; 738} 739#endif 740 741void 742SISCalculateGammaRampCRT2(ScrnInfoPtr pScrn) 743{ 744 SISPtr pSiS = SISPTR(pScrn); 745 int i; 746 int myshift = 16 - pScrn->rgbBits; 747 int maxvalue = (1 << pScrn->rgbBits) - 1; 748 int reds = pScrn->mask.red >> pScrn->offset.red; 749 int greens = pScrn->mask.green >> pScrn->offset.green; 750 int blues = pScrn->mask.blue >> pScrn->offset.blue; 751 float framp, invgamma1, invgamma2, invgamma3, v; 752 753 invgamma1 = 1. / pSiS->GammaR2; 754 invgamma2 = 1. / pSiS->GammaG2; 755 invgamma3 = 1. / pSiS->GammaB2; 756 757 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_OLDGAMMAINUSE)) { 758 759 for(i = 0; i < pSiS->CRT2ColNum; i++) { 760 pSiS->crt2gcolortable[i].red = calcgammaval(i, pSiS->CRT2ColNum, invgamma1, 761 pSiS->NewGammaBriR2, pSiS->NewGammaConR2) >> myshift; 762 pSiS->crt2gcolortable[i].green = calcgammaval(i, pSiS->CRT2ColNum, invgamma2, 763 pSiS->NewGammaBriG2, pSiS->NewGammaConG2) >> myshift; 764 pSiS->crt2gcolortable[i].blue = calcgammaval(i, pSiS->CRT2ColNum, invgamma3, 765 pSiS->NewGammaBriB2, pSiS->NewGammaConB2) >> myshift; 766 } 767 768 } else { 769 770 int fullscale1 = 65536 * (float)pSiS->GammaBriR2 / 1000; 771 int fullscale2 = 65536 * (float)pSiS->GammaBriG2 / 1000; 772 int fullscale3 = 65536 * (float)pSiS->GammaBriB2 / 1000; 773 774 float dramp = 1. / (pSiS->CRT2ColNum - 1); 775 776 for(i = 0; i < pSiS->CRT2ColNum; i++) { 777 framp = pow(i * dramp, invgamma1); 778 v = (fullscale1 < 0) ? (65535 + fullscale1 * framp) : fullscale1 * framp; 779 if(v < 0) v = 0; 780 else if(v > 65535) v = 65535; 781 pSiS->crt2gcolortable[i].red = ((UShort)v) >> myshift; 782 framp = pow(i * dramp, invgamma2); 783 v = (fullscale2 < 0) ? (65535 + fullscale2 * framp) : fullscale2 * framp; 784 if(v < 0) v = 0; 785 else if(v > 65535) v = 65535; 786 pSiS->crt2gcolortable[i].green = ((UShort)v) >> myshift; 787 framp = pow(i * dramp, invgamma3); 788 v = (fullscale3 < 0) ? (65535 + fullscale3 * framp) : fullscale3 * framp; 789 if(v < 0) v = 0; 790 else if(v > 65535) v = 65535; 791 pSiS->crt2gcolortable[i].blue = ((UShort)v) >> myshift; 792 } 793 794 } 795 796 for(i = 0; i < pSiS->CRT2ColNum; i++) { 797 pSiS->crt2colors[i].red = 798 pSiS->crt2gcolortable[i * maxvalue / reds].red; 799 pSiS->crt2colors[i].green = 800 pSiS->crt2gcolortable[i * maxvalue / greens].green; 801 pSiS->crt2colors[i].blue = 802 pSiS->crt2gcolortable[i * maxvalue / blues].blue; 803 } 804} 805 806/* If monitor section has no HSync/VRefresh data, 807 * derive it from DDC data. 808 */ 809static void 810SiSSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) 811{ 812 MonPtr mon = pScrn->monitor; 813 xf86MonPtr ddc = mon->DDC; 814 float myhhigh = 0.0, myhlow = 0.0, htest; 815 int myvhigh = 0, myvlow = 0, vtest, i; 816 UChar temp; 817 const myhddctiming myhtiming[12] = { 818 { 1, 0x20, 31.6 }, /* rounded up by .1 */ 819 { 1, 0x80, 31.6 }, 820 { 1, 0x02, 35.3 }, 821 { 1, 0x04, 37.6 }, 822 { 1, 0x08, 38.0 }, 823 { 1, 0x01, 38.0 }, 824 { 2, 0x40, 47.0 }, 825 { 2, 0x80, 48.2 }, 826 { 2, 0x08, 48.5 }, 827 { 2, 0x04, 56.6 }, 828 { 2, 0x02, 60.1 }, 829 { 2, 0x01, 80.1 } 830 }; 831 const myvddctiming myvtiming[11] = { 832 { 1, 0x02, 56 }, 833 { 1, 0x01, 60 }, 834 { 2, 0x08, 60 }, 835 { 2, 0x04, 70 }, 836 { 1, 0x80, 71 }, 837 { 1, 0x08, 72 }, 838 { 2, 0x80, 72 }, 839 { 1, 0x04, 75 }, 840 { 2, 0x40, 75 }, 841 { 2, 0x02, 75 }, 842 { 2, 0x01, 75 } 843 }; 844 845 if(flag) { /* HSync */ 846 847 for(i = 0; i < 4; i++) { 848 if(ddc->det_mon[i].type == DS_RANGES) { 849 mon->nHsync = 1; 850 mon->hsync[0].lo = ddc->det_mon[i].section.ranges.min_h; 851 mon->hsync[0].hi = ddc->det_mon[i].section.ranges.max_h; 852 if(mon->hsync[0].lo > 32.0 || mon->hsync[0].hi < 31.0) { 853 if(ddc->timings1.t1 & 0x80) { 854 mon->nHsync++; 855 mon->hsync[1].lo = 31.0; 856 mon->hsync[1].hi = 32.0; 857 } 858 } 859 return; 860 } 861 } 862 863 /* If no sync ranges detected in detailed timing table, we 864 * derive them from supported VESA modes. 865 */ 866 867 for(i = 0; i < 12; i++) { 868 if(myhtiming[i].whichone == 1) temp = ddc->timings1.t1; 869 else temp = ddc->timings1.t2; 870 if(temp & myhtiming[i].mask) { 871 if((i == 0) || (myhlow > myhtiming[i].rate)) 872 myhlow = myhtiming[i].rate; 873 } 874 if(myhtiming[11-i].whichone == 1) temp = ddc->timings1.t1; 875 else temp = ddc->timings1.t2; 876 if(temp & myhtiming[11-i].mask) { 877 if((i == 0) || (myhhigh < myhtiming[11-i].rate)) 878 myhhigh = myhtiming[11-i].rate; 879 } 880 } 881 882 for(i = 0; i < STD_TIMINGS; i++) { 883 if(ddc->timings2[i].hsize > 256) { 884 htest = ddc->timings2[i].refresh * 1.05 * ddc->timings2[i].vsize / 1000.0; 885 if(htest < myhlow) myhlow = htest; 886 if(htest > myhhigh) myhhigh = htest; 887 } 888 } 889 890 if((myhhigh > 0.0) && (myhlow > 0.0)) { 891 mon->nHsync = 1; 892 mon->hsync[0].lo = myhlow - 0.1; 893 mon->hsync[0].hi = myhhigh; 894 } 895 896 897 } else { /* Vrefresh */ 898 899 for(i = 0; i < 4; i++) { 900 if(ddc->det_mon[i].type == DS_RANGES) { 901 mon->nVrefresh = 1; 902 mon->vrefresh[0].lo = ddc->det_mon[i].section.ranges.min_v; 903 mon->vrefresh[0].hi = ddc->det_mon[i].section.ranges.max_v; 904 if(mon->vrefresh[0].lo > 72 || mon->vrefresh[0].hi < 70) { 905 if(ddc->timings1.t1 & 0x80) { 906 mon->nVrefresh++; 907 mon->vrefresh[1].lo = 71; 908 mon->vrefresh[1].hi = 71; 909 } 910 } 911 return; 912 } 913 } 914 915 for(i = 0; i < 11; i++) { 916 if(myvtiming[i].whichone == 1) temp = ddc->timings1.t1; 917 else temp = ddc->timings1.t2; 918 if(temp & myvtiming[i].mask) { 919 if((i == 0) || (myvlow > myvtiming[i].rate)) 920 myvlow = myvtiming[i].rate; 921 } 922 if(myvtiming[10-i].whichone == 1) temp = ddc->timings1.t1; 923 else temp = ddc->timings1.t2; 924 if(temp & myvtiming[10-i].mask) { 925 if((i == 0) || (myvhigh < myvtiming[10-i].rate)) 926 myvhigh = myvtiming[10-i].rate; 927 } 928 } 929 930 for(i = 0; i < STD_TIMINGS; i++) { 931 if(ddc->timings2[i].hsize > 256) { 932 vtest = ddc->timings2[i].refresh; 933 if(vtest < myvlow) myvlow = vtest; 934 if(vtest > myvhigh) myvhigh = vtest; 935 } 936 } 937 938 if((myvhigh > 0) && (myvlow > 0)) { 939 mon->nVrefresh = 1; 940 mon->vrefresh[0].lo = myvlow; 941 mon->vrefresh[0].hi = myvhigh; 942 } 943 944 } 945} 946 947static Bool 948SiSAllowSyncOverride(SISPtr pSiS, Bool fromDDC) 949{ 950 if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return FALSE; 951 952#ifdef SISDUALHEAD 953 if(pSiS->DualHeadMode) { 954 if(pSiS->SecondHead) { 955 if((pSiS->VBFlags & CRT1_LCDA) && (!fromDDC)) return TRUE; 956 } else { 957 if((pSiS->VBFlags & CRT2_TV) || 958 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC))) return TRUE; 959 } 960 return FALSE; 961 } 962#endif 963 964#ifdef SISMERGED 965 if(pSiS->MergedFB) { 966 if((pSiS->VBFlags & CRT1_LCDA) && (!fromDDC)) return TRUE; 967 return FALSE; 968 } 969#endif 970 971 if(!(pSiS->VBFlags & DISPTYPE_CRT1)) { 972 if( (pSiS->VBFlags & CRT2_TV) || 973 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC)) ) return TRUE; 974 } else if((pSiS->VBFlags & CRT1_LCDA) && (!fromDDC)) return TRUE; 975 976 return FALSE; 977} 978 979static Bool 980SiSCheckForH(float hsync, MonPtr monitor) 981{ 982 int i; 983 for(i = 0; i < monitor->nHsync; i++) { 984 if((hsync > monitor->hsync[i].lo * (1.0 - SYNC_TOLERANCE)) && 985 (hsync < monitor->hsync[i].hi * (1.0 + SYNC_TOLERANCE))) 986 break; 987 } 988 if(i == monitor->nHsync) return FALSE; 989 return TRUE; 990} 991 992static Bool 993SiSCheckForV(float vrefresh, MonPtr monitor) 994{ 995 int i; 996 for(i = 0; i < monitor->nVrefresh; i++) { 997 if((vrefresh > monitor->vrefresh[i].lo * (1.0 - SYNC_TOLERANCE)) && 998 (vrefresh < monitor->vrefresh[i].hi * (1.0 + SYNC_TOLERANCE))) 999 break; 1000 } 1001 if(i == monitor->nVrefresh) return FALSE; 1002 return TRUE; 1003} 1004 1005static Bool 1006CheckAndOverruleH(ScrnInfoPtr pScrn, MonPtr monitor) 1007{ 1008 DisplayModePtr mode = monitor->Modes; 1009 float mymin = 30.0, mymax = 80.0, hsync; 1010 Bool doit = FALSE; 1011 1012 for(hsync = mymin; hsync <= mymax; hsync += .5) { 1013 if(!SiSCheckForH(hsync, monitor)) doit = TRUE; 1014 } 1015 1016 if(mode) { 1017 do { 1018 if(mode->type & M_T_BUILTIN) { 1019 hsync = (float)mode->Clock / (float)mode->HTotal; 1020 if(!SiSCheckForH(hsync, monitor)) { 1021 doit = TRUE; 1022 if(hsync < mymin) mymin = hsync; 1023 if(hsync > mymax) mymax = hsync; 1024 } 1025 } 1026 } while((mode = mode->next)); 1027 } 1028 1029 if(doit) { 1030 monitor->nHsync = 1; 1031 monitor->hsync[0].lo = mymin; 1032 monitor->hsync[0].hi = mymax; 1033 return TRUE; 1034 } 1035 1036 return FALSE; 1037} 1038 1039static Bool 1040CheckAndOverruleV(ScrnInfoPtr pScrn, MonPtr monitor) 1041{ 1042 DisplayModePtr mode = monitor->Modes; 1043 float mymin = 59.0, mymax = 61.0, vrefresh; 1044 Bool doit = FALSE, ret = FALSE; 1045 1046 for(vrefresh = mymin; vrefresh <= mymax; vrefresh += 1.0) { 1047 if(!SiSCheckForV(vrefresh, monitor)) doit = TRUE; 1048 } 1049 1050 if(mode) { 1051 do { 1052 if(mode->type & M_T_BUILTIN) { 1053 vrefresh = mode->Clock * 1000.0 / (mode->HTotal * mode->VTotal); 1054 if(mode->Flags & V_INTERLACE) vrefresh *= 2.0; 1055 if(mode->Flags & V_DBLSCAN) vrefresh /= 2.0; 1056 if(!SiSCheckForH(vrefresh, monitor)) { 1057 doit = TRUE; 1058 if(vrefresh < mymin) mymin = vrefresh; 1059 if(vrefresh > mymax) mymax = vrefresh; 1060 } 1061 } 1062 } while((mode = mode->next)); 1063 } 1064 1065 if(doit) { 1066 monitor->nVrefresh = 1; 1067 monitor->vrefresh[0].lo = mymin; 1068 monitor->vrefresh[0].hi = mymax; 1069 ret = TRUE; 1070 } 1071 1072 /* special for 640x400/320x200/@70Hz (VGA/IBM 720x480) */ 1073 if( (!SiSCheckForV(71, monitor)) && 1074 (monitor->nVrefresh < MAX_VREFRESH) ) { 1075 monitor->vrefresh[monitor->nVrefresh].lo = 71; 1076 monitor->vrefresh[monitor->nVrefresh].hi = 71; 1077 monitor->nVrefresh++; 1078 ret = TRUE; 1079 } 1080 return ret; 1081} 1082 1083/* Some helper functions for MergedFB mode */ 1084 1085#ifdef SISMERGED 1086 1087/* Helper function for CRT2 monitor vrefresh/hsync options 1088 * (Code base from mga driver) 1089 */ 1090static int 1091SiSStrToRanges(range *r, char *s, int max) 1092{ 1093 float num = 0.0; 1094 int rangenum = 0; 1095 Bool gotdash = FALSE; 1096 Bool nextdash = FALSE; 1097 char *strnum = NULL; 1098 do { 1099 switch(*s) { 1100 case '0': 1101 case '1': 1102 case '2': 1103 case '3': 1104 case '4': 1105 case '5': 1106 case '6': 1107 case '7': 1108 case '8': 1109 case '9': 1110 case '.': 1111 if(strnum == NULL) { 1112 strnum = s; 1113 gotdash = nextdash; 1114 nextdash = FALSE; 1115 } 1116 break; 1117 case '-': 1118 case ' ': 1119 case 0: 1120 if(strnum == NULL) break; 1121 sscanf(strnum, "%f", &num); 1122 strnum = NULL; 1123 if(gotdash) { 1124 r[rangenum - 1].hi = num; 1125 } else { 1126 r[rangenum].lo = num; 1127 r[rangenum].hi = num; 1128 rangenum++; 1129 } 1130 if(*s == '-') nextdash = (rangenum != 0); 1131 else if(rangenum >= max) return rangenum; 1132 break; 1133 default: 1134 return 0; 1135 } 1136 1137 } while(*(s++) != 0); 1138 1139 return rangenum; 1140} 1141 1142/* Copy and link two modes (i, j) for mergedfb mode 1143 * (Code base taken from mga driver) 1144 * 1145 * - Copy mode i, merge j to copy of i, link the result to dest 1146 * - Link i and j in private record. 1147 * - If dest is NULL, return value is copy of i linked to itself. 1148 * - For mergedfb auto-config, we only check the dimension 1149 * against virtualX/Y, if they were user-provided. 1150 * - No special treatment required for CRTxxOffs. 1151 * - Provide fake dotclock in order to distinguish between similar 1152 * looking MetaModes (for RandR and VidMode extensions) 1153 * - Set unique VRefresh of dest mode for RandR 1154 */ 1155static DisplayModePtr 1156SiSCopyModeNLink(ScrnInfoPtr pScrn, DisplayModePtr dest, 1157 DisplayModePtr i, DisplayModePtr j, 1158 SiSScrn2Rel srel) 1159{ 1160 SISPtr pSiS = SISPTR(pScrn); 1161 DisplayModePtr mode; 1162 int dx = 0,dy = 0; 1163 1164 if(!((mode = malloc(sizeof(DisplayModeRec))))) return dest; 1165 memcpy(mode, i, sizeof(DisplayModeRec)); 1166 if(!((mode->Private = malloc(sizeof(SiSMergedDisplayModeRec))))) { 1167 free(mode); 1168 return dest; 1169 } 1170 ((SiSMergedDisplayModePtr)mode->Private)->CRT1 = i; 1171 ((SiSMergedDisplayModePtr)mode->Private)->CRT2 = j; 1172 ((SiSMergedDisplayModePtr)mode->Private)->CRT2Position = srel; 1173 mode->PrivSize = 0; 1174 1175 switch(srel) { 1176 case sisLeftOf: 1177 case sisRightOf: 1178 if(!(pScrn->display->virtualX)) { 1179 dx = i->HDisplay + j->HDisplay; 1180 } else { 1181 dx = min(pScrn->virtualX, i->HDisplay + j->HDisplay); 1182 } 1183 dx -= mode->HDisplay; 1184 if(!(pScrn->display->virtualY)) { 1185 dy = max(i->VDisplay, j->VDisplay); 1186 } else { 1187 dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay)); 1188 } 1189 dy -= mode->VDisplay; 1190 break; 1191 case sisAbove: 1192 case sisBelow: 1193 if(!(pScrn->display->virtualY)) { 1194 dy = i->VDisplay + j->VDisplay; 1195 } else { 1196 dy = min(pScrn->virtualY, i->VDisplay + j->VDisplay); 1197 } 1198 dy -= mode->VDisplay; 1199 if(!(pScrn->display->virtualX)) { 1200 dx = max(i->HDisplay, j->HDisplay); 1201 } else { 1202 dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay)); 1203 } 1204 dx -= mode->HDisplay; 1205 break; 1206 case sisClone: 1207 if(!(pScrn->display->virtualX)) { 1208 dx = max(i->HDisplay, j->HDisplay); 1209 } else { 1210 dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay)); 1211 } 1212 dx -= mode->HDisplay; 1213 if(!(pScrn->display->virtualY)) { 1214 dy = max(i->VDisplay, j->VDisplay); 1215 } else { 1216 dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay)); 1217 } 1218 dy -= mode->VDisplay; 1219 break; 1220 } 1221 mode->HDisplay += dx; 1222 mode->HSyncStart += dx; 1223 mode->HSyncEnd += dx; 1224 mode->HTotal += dx; 1225 mode->VDisplay += dy; 1226 mode->VSyncStart += dy; 1227 mode->VSyncEnd += dy; 1228 mode->VTotal += dy; 1229 1230 mode->type = M_T_DEFAULT; 1231#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,2,0) 1232 /* Set up as user defined (ie fake that the mode has been named in the 1233 * Modes-list in the screen section; corrects cycling with CTRL-ALT-[-+] 1234 * when source mode has not been listed there.) 1235 */ 1236 mode->type |= M_T_USERDEF; 1237#endif 1238 1239 /* Set the VRefresh field (in order to make RandR use it for the rates). We 1240 * simply set this to the refresh rate for the CRT1 mode (since CRT2 will 1241 * mostly be LCD or TV anyway). 1242 */ 1243 mode->VRefresh = SiSCalcVRate(i); 1244 1245 if( ((mode->HDisplay * ((pScrn->bitsPerPixel + 7) / 8) * mode->VDisplay) > pSiS->maxxfbmem) || 1246 (mode->HDisplay > 4088) || 1247 (mode->VDisplay > 4096) ) { 1248 1249 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1250 "Skipped \"%s\" (%dx%d), not enough video RAM or beyond hardware specs\n", 1251 mode->name, mode->HDisplay, mode->VDisplay); 1252 free(mode->Private); 1253 free(mode); 1254 1255 return dest; 1256 } 1257 1258#ifdef SISXINERAMA 1259 if(srel != sisClone) { 1260 pSiS->AtLeastOneNonClone = TRUE; 1261 } 1262#endif 1263 1264 /* Now see if the resulting mode would be discarded as a "size" by the 1265 * RandR extension, and increase its clock by 1000 in case it does. 1266 */ 1267 if(dest) { 1268 DisplayModePtr t = dest; 1269 do { 1270 if((t->HDisplay == mode->HDisplay) && 1271 (t->VDisplay == mode->VDisplay) && 1272 ((int)(t->VRefresh + .5) == (int)(mode->VRefresh + .5))) { 1273 mode->VRefresh += 1000.0; 1274 } 1275 t = t->next; 1276 } while((t) && (t != dest)); 1277 } 1278 1279 /* Provide a fake but unique DotClock in order to trick the vidmode 1280 * extension to allow selecting among a number of modes whose merged result 1281 * looks identical but consists of different modes for CRT1 and CRT2 1282 */ 1283 mode->Clock = (int)(mode->VRefresh * 1000.0); 1284 1285 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1286 "Merged \"%s\" (%dx%d) and \"%s\" (%dx%d) to %dx%d (%d)%s\n", 1287 i->name, i->HDisplay, i->VDisplay, j->name, j->HDisplay, j->VDisplay, 1288 mode->HDisplay, mode->VDisplay, (int)mode->VRefresh, 1289 (srel == sisClone) ? " (Clone)" : ""); 1290 1291 mode->next = mode; 1292 mode->prev = mode; 1293 1294 if(dest) { 1295 mode->next = dest->next; /* Insert node after "dest" */ 1296 dest->next->prev = mode; 1297 mode->prev = dest; 1298 dest->next = mode; 1299 } 1300 1301 return mode; 1302} 1303 1304/* Helper function to find a mode from a given name 1305 * (Code base taken from mga driver) 1306 */ 1307static DisplayModePtr 1308SiSGetModeFromName(char* str, DisplayModePtr i) 1309{ 1310 DisplayModePtr c = i; 1311 if(!i) return NULL; 1312 do { 1313 if(strcmp(str, c->name) == 0) return c; 1314 c = c->next; 1315 } while(c != i); 1316 return NULL; 1317} 1318 1319static DisplayModePtr 1320SiSFindWidestTallestMode(DisplayModePtr i, Bool tallest) 1321{ 1322 DisplayModePtr c = i, d = NULL; 1323 int max = 0; 1324 if(!i) return NULL; 1325 do { 1326 if(tallest) { 1327 if(c->VDisplay > max) { 1328 max = c->VDisplay; 1329 d = c; 1330 } 1331 } else { 1332 if(c->HDisplay > max) { 1333 max = c->HDisplay; 1334 d = c; 1335 } 1336 } 1337 c = c->next; 1338 } while(c != i); 1339 return d; 1340} 1341 1342static void 1343SiSFindWidestTallestCommonMode(DisplayModePtr i, DisplayModePtr j, Bool tallest, 1344 DisplayModePtr *a, DisplayModePtr *b) 1345{ 1346 DisplayModePtr c = i, d; 1347 int max = 0; 1348 Bool foundone; 1349 1350 (*a) = (*b) = NULL; 1351 1352 if(!i || !j) return; 1353 1354 do { 1355 d = j; 1356 foundone = FALSE; 1357 do { 1358 if( (c->HDisplay == d->HDisplay) && 1359 (c->VDisplay == d->VDisplay) ) { 1360 foundone = TRUE; 1361 break; 1362 } 1363 d = d->next; 1364 } while(d != j); 1365 if(foundone) { 1366 if(tallest) { 1367 if(c->VDisplay > max) { 1368 max = c->VDisplay; 1369 (*a) = c; 1370 (*b) = d; 1371 } 1372 } else { 1373 if(c->HDisplay > max) { 1374 max = c->HDisplay; 1375 (*a) = c; 1376 (*b) = d; 1377 } 1378 } 1379 } 1380 c = c->next; 1381 } while(c != i); 1382} 1383 1384static DisplayModePtr 1385SiSGenerateModeListFromLargestModes(ScrnInfoPtr pScrn, 1386 DisplayModePtr i, DisplayModePtr j, 1387 SiSScrn2Rel srel) 1388{ 1389#ifdef SISXINERAMA 1390 SISPtr pSiS = SISPTR(pScrn); 1391#endif 1392 DisplayModePtr mode1 = NULL; 1393 DisplayModePtr mode2 = NULL; 1394 DisplayModePtr mode3 = NULL; 1395 DisplayModePtr mode4 = NULL; 1396 DisplayModePtr result = NULL; 1397 1398#ifdef SISXINERAMA 1399 pSiS->AtLeastOneNonClone = FALSE; 1400#endif 1401 1402 /* Now build a default list of MetaModes. 1403 * - Non-clone: If the user enabled NonRectangular, we use the 1404 * largest mode for each CRT1 and CRT2. If not, we use the largest 1405 * common mode for CRT1 and CRT2 (if available). Additionally, and 1406 * regardless if the above, we produce a clone mode consisting of 1407 * the largest common mode (if available) in order to use DGA. 1408 * - Clone: If the (global) CRT2Position is Clone, we use the 1409 * largest common mode if available, otherwise the first two modes 1410 * in each list. 1411 */ 1412 1413 switch(srel) { 1414 case sisLeftOf: 1415 case sisRightOf: 1416 mode1 = SiSFindWidestTallestMode(i, FALSE); 1417 mode2 = SiSFindWidestTallestMode(j, FALSE); 1418 SiSFindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); 1419 break; 1420 case sisAbove: 1421 case sisBelow: 1422 mode1 = SiSFindWidestTallestMode(i, TRUE); 1423 mode2 = SiSFindWidestTallestMode(j, TRUE); 1424 SiSFindWidestTallestCommonMode(i, j, TRUE, &mode3, &mode4); 1425 break; 1426 case sisClone: 1427 SiSFindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); 1428 if(mode3 && mode4) { 1429 mode1 = mode3; 1430 mode2 = mode4; 1431 } else { 1432 mode1 = i; 1433 mode2 = j; 1434 } 1435 } 1436 1437 if(srel != sisClone) { 1438 if(mode3 && mode4 && !pSiS->NonRect) { 1439 mode1 = mode3; 1440 mode2 = mode2; 1441 } 1442 } 1443 1444 if(mode1 && mode2) { 1445 result = SiSCopyModeNLink(pScrn, result, mode1, mode2, srel); 1446 } 1447 1448 if(srel != sisClone) { 1449 if(mode3 && mode4) { 1450 result = SiSCopyModeNLink(pScrn, result, mode3, mode4, sisClone); 1451 } 1452 } 1453 1454 return result; 1455} 1456 1457/* Generate the merged-fb mode modelist 1458 * (Taken from mga driver) 1459 */ 1460static DisplayModePtr 1461SiSGenerateModeListFromMetaModes(ScrnInfoPtr pScrn, char* str, 1462 DisplayModePtr i, DisplayModePtr j, 1463 SiSScrn2Rel srel) 1464{ 1465#ifdef SISXINERAMA 1466 SISPtr pSiS = SISPTR(pScrn); 1467#endif 1468 char* strmode = str; 1469 char modename[256]; 1470 Bool gotdash = FALSE; 1471 char gotsep = 0; 1472 SiSScrn2Rel sr; 1473 DisplayModePtr mode1 = NULL; 1474 DisplayModePtr mode2 = NULL; 1475 DisplayModePtr result = NULL; 1476 int myslen; 1477 1478#ifdef SISXINERAMA 1479 pSiS->AtLeastOneNonClone = FALSE; 1480#endif 1481 1482 do { 1483 switch(*str) { 1484 case 0: 1485 case '-': 1486 case '+': 1487 case ' ': 1488 case ',': 1489 case ';': 1490 if(strmode != str) { 1491 1492 myslen = str - strmode; 1493 if(myslen > 255) myslen = 255; 1494 strncpy(modename, strmode, myslen); 1495 modename[myslen] = 0; 1496 1497 if(gotdash) { 1498 if(mode1 == NULL) { 1499 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1500 "Error parsing MetaModes parameter\n"); 1501 return NULL; 1502 } 1503 mode2 = SiSGetModeFromName(modename, j); 1504 if(!mode2) { 1505 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1506 "Mode \"%s\" is not a supported mode for CRT2\n", modename); 1507 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1508 "\t(Skipping metamode \"%s%c%s\")\n", mode1->name, gotsep, modename); 1509 mode1 = NULL; 1510 gotsep = 0; 1511 } 1512 } else { 1513 mode1 = SiSGetModeFromName(modename, i); 1514 if(!mode1) { 1515 char* tmps = str; 1516 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1517 "Mode \"%s\" is not a supported mode for CRT1\n", modename); 1518 while(*tmps == ' ' || *tmps == ';') tmps++; 1519 /* skip the next mode */ 1520 if(*tmps == '-' || *tmps == '+' || *tmps == ',') { 1521 tmps++; 1522 /* skip spaces */ 1523 while(*tmps == ' ' || *tmps == ';') tmps++; 1524 /* skip modename */ 1525 while(*tmps && *tmps != ' ' && *tmps != ';' && *tmps != '-' && *tmps != '+' && *tmps != ',') tmps++; 1526 myslen = tmps - strmode; 1527 if(myslen > 255) myslen = 255; 1528 strncpy(modename,strmode,myslen); 1529 modename[myslen] = 0; 1530 str = tmps - 1; 1531 } 1532 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1533 "\t(Skipping metamode \"%s\")\n", modename); 1534 mode1 = NULL; 1535 gotsep = 0; 1536 } 1537 } 1538 gotdash = FALSE; 1539 } 1540 strmode = str + 1; 1541 gotdash |= (*str == '-' || *str == '+' || *str == ','); 1542 if (*str == '-' || *str == '+' || *str == ',') 1543 gotsep = *str; 1544 1545 if(*str != 0) break; 1546 /* Fall through otherwise */ 1547 1548 default: 1549 if(!gotdash && mode1) { 1550 sr = srel; 1551 if(gotsep == '+') sr = sisClone; 1552 if(!mode2) { 1553 mode2 = SiSGetModeFromName(mode1->name, j); 1554 sr = sisClone; 1555 } 1556 if(!mode2) { 1557 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1558 "Mode \"%s\" is not a supported mode for CRT2\n", mode1->name); 1559 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1560 "\t(Skipping metamode \"%s\")\n", modename); 1561 mode1 = NULL; 1562 } else { 1563 result = SiSCopyModeNLink(pScrn, result, mode1, mode2, sr); 1564 mode1 = NULL; 1565 mode2 = NULL; 1566 } 1567 gotsep = 0; 1568 } 1569 break; 1570 1571 } 1572 1573 } while(*(str++) != 0); 1574 1575 return result; 1576} 1577 1578static DisplayModePtr 1579SiSGenerateModeList(ScrnInfoPtr pScrn, char* str, 1580 DisplayModePtr i, DisplayModePtr j, 1581 SiSScrn2Rel srel) 1582{ 1583 SISPtr pSiS = SISPTR(pScrn); 1584 1585 if(str != NULL) { 1586 return(SiSGenerateModeListFromMetaModes(pScrn, str, i, j, srel)); 1587 } else { 1588 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1589 "No MetaModes given, linking %s modes by default\n", 1590 (srel == sisClone) ? "largest common" : 1591 (pSiS->NonRect ? 1592 (((srel == sisLeftOf) || (srel == sisRightOf)) ? "widest" : "tallest") 1593 : 1594 (((srel == sisLeftOf) || (srel == sisRightOf)) ? "widest common" : "tallest common")) ); 1595 return(SiSGenerateModeListFromLargestModes(pScrn, i, j, srel)); 1596 } 1597} 1598 1599static void 1600SiSRecalcDefaultVirtualSize(ScrnInfoPtr pScrn) 1601{ 1602 SISPtr pSiS = SISPTR(pScrn); 1603 DisplayModePtr mode, bmode; 1604 int maxh, maxv; 1605 static const char *str = "MergedFB: Virtual %s %d\n"; 1606 static const char *errstr = "Virtual %s to small for given CRT2Position offset\n"; 1607 1608 mode = bmode = pScrn->modes; 1609 maxh = maxv = 0; 1610 do { 1611 if(mode->HDisplay > maxh) maxh = mode->HDisplay; 1612 if(mode->VDisplay > maxv) maxv = mode->VDisplay; 1613 mode = mode->next; 1614 } while(mode != bmode); 1615 1616 maxh += pSiS->CRT1XOffs + pSiS->CRT2XOffs; 1617 maxv += pSiS->CRT1YOffs + pSiS->CRT2YOffs; 1618 1619 if(!(pScrn->display->virtualX)) { 1620 if(maxh > 4088) { 1621 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1622 "Virtual width with CRT2Position offset beyond hardware specs\n"); 1623 pSiS->CRT1XOffs = pSiS->CRT2XOffs = 0; 1624 maxh -= (pSiS->CRT1XOffs + pSiS->CRT2XOffs); 1625 } 1626 pScrn->virtualX = maxh; 1627 pScrn->displayWidth = maxh; 1628 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "width", maxh); 1629 } else { 1630 if(maxh < pScrn->display->virtualX) { 1631 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "width"); 1632 pSiS->CRT1XOffs = pSiS->CRT2XOffs = 0; 1633 } 1634 } 1635 1636 if(!(pScrn->display->virtualY)) { 1637 pScrn->virtualY = maxv; 1638 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "height", maxv); 1639 } else { 1640 if(maxv < pScrn->display->virtualY) { 1641 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "height"); 1642 pSiS->CRT1YOffs = pSiS->CRT2YOffs = 0; 1643 } 1644 } 1645} 1646 1647static void 1648SiSMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, SiSScrn2Rel srel) 1649{ 1650 SISPtr pSiS = SISPTR(pScrn1); 1651 MessageType from = X_DEFAULT; 1652 xf86MonPtr DDC1 = (xf86MonPtr)(pScrn1->monitor->DDC); 1653 xf86MonPtr DDC2 = (xf86MonPtr)(pScrn2->monitor->DDC); 1654 int ddcWidthmm = 0, ddcHeightmm = 0; 1655 const char *dsstr = "MergedFB: Display dimensions: (%d, %d) mm\n"; 1656 1657 /* This sets the DPI for MergedFB mode. The problem is that 1658 * this can never be exact, because the output devices may 1659 * have different dimensions. This function tries to compromise 1660 * through a few assumptions, and it just calculates an average DPI 1661 * value for both monitors. 1662 */ 1663 1664 /* Given DisplaySize should regard BOTH monitors */ 1665 pScrn1->widthmm = pScrn1->monitor->widthmm; 1666 pScrn1->heightmm = pScrn1->monitor->heightmm; 1667 1668 /* Get DDC display size; if only either CRT1 or CRT2 provided these, 1669 * assume equal dimensions for both, otherwise add dimensions 1670 */ 1671 if( (DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) && 1672 (DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0)) ) { 1673 ddcWidthmm = max(DDC1->features.hsize, DDC2->features.hsize) * 10; 1674 ddcHeightmm = max(DDC1->features.vsize, DDC2->features.vsize) * 10; 1675 switch(srel) { 1676 case sisLeftOf: 1677 case sisRightOf: 1678 ddcWidthmm = (DDC1->features.hsize + DDC2->features.hsize) * 10; 1679 break; 1680 case sisAbove: 1681 case sisBelow: 1682 ddcHeightmm = (DDC1->features.vsize + DDC2->features.vsize) * 10; 1683 default: 1684 break; 1685 } 1686 } else if(DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) { 1687 ddcWidthmm = DDC1->features.hsize * 10; 1688 ddcHeightmm = DDC1->features.vsize * 10; 1689 switch(srel) { 1690 case sisLeftOf: 1691 case sisRightOf: 1692 ddcWidthmm *= 2; 1693 break; 1694 case sisAbove: 1695 case sisBelow: 1696 ddcHeightmm *= 2; 1697 default: 1698 break; 1699 } 1700 } else if(DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0) ) { 1701 ddcWidthmm = DDC2->features.hsize * 10; 1702 ddcHeightmm = DDC2->features.vsize * 10; 1703 switch(srel) { 1704 case sisLeftOf: 1705 case sisRightOf: 1706 ddcWidthmm *= 2; 1707 break; 1708 case sisAbove: 1709 case sisBelow: 1710 ddcHeightmm *= 2; 1711 default: 1712 break; 1713 } 1714 } 1715 1716 if(monitorResolution > 0) { 1717 1718 /* Set command line given values (overrules given options) */ 1719 pScrn1->xDpi = monitorResolution; 1720 pScrn1->yDpi = monitorResolution; 1721 from = X_CMDLINE; 1722 1723 } else if(pSiS->MergedFBXDPI) { 1724 1725 /* Set option-wise given values (overrule DisplaySize) */ 1726 pScrn1->xDpi = pSiS->MergedFBXDPI; 1727 pScrn1->yDpi = pSiS->MergedFBYDPI; 1728 from = X_CONFIG; 1729 1730 } else if(pScrn1->widthmm > 0 || pScrn1->heightmm > 0) { 1731 1732 /* Set values calculated from given DisplaySize */ 1733 from = X_CONFIG; 1734 if(pScrn1->widthmm > 0) { 1735 pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm); 1736 } 1737 if(pScrn1->heightmm > 0) { 1738 pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm); 1739 } 1740 xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, pScrn1->widthmm, pScrn1->heightmm); 1741 1742 } else if(ddcWidthmm && ddcHeightmm) { 1743 1744 /* Set values from DDC-provided display size */ 1745 from = X_PROBED; 1746 xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, ddcWidthmm, ddcHeightmm ); 1747 pScrn1->widthmm = ddcWidthmm; 1748 pScrn1->heightmm = ddcHeightmm; 1749 if(pScrn1->widthmm > 0) { 1750 pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm); 1751 } 1752 if(pScrn1->heightmm > 0) { 1753 pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm); 1754 } 1755 1756 } else { 1757 1758 pScrn1->xDpi = pScrn1->yDpi = DEFAULT_DPI; 1759 1760 } 1761 1762 /* Sanity check */ 1763 if(pScrn1->xDpi > 0 && pScrn1->yDpi <= 0) 1764 pScrn1->yDpi = pScrn1->xDpi; 1765 if(pScrn1->yDpi > 0 && pScrn1->xDpi <= 0) 1766 pScrn1->xDpi = pScrn1->yDpi; 1767 1768 pScrn2->xDpi = pScrn1->xDpi; 1769 pScrn2->yDpi = pScrn1->yDpi; 1770 1771 xf86DrvMsg(pScrn1->scrnIndex, from, "MergedFB: DPI set to (%d, %d)\n", 1772 pScrn1->xDpi, pScrn1->yDpi); 1773} 1774 1775/* Pseudo-Xinerama extension for MergedFB mode */ 1776#ifdef SISXINERAMA 1777 1778static void 1779SiSUpdateXineramaScreenInfo(ScrnInfoPtr pScrn1) 1780{ 1781 SISPtr pSiS = SISPTR(pScrn1); 1782 int crt1scrnnum = 0, crt2scrnnum = 1; 1783 int x1=0, x2=0, y1=0, y2=0, h1=0, h2=0, w1=0, w2=0; 1784 int realvirtX, realvirtY; 1785 DisplayModePtr currentMode, firstMode; 1786 Bool infochanged = FALSE; 1787 Bool usenonrect = pSiS->NonRect; 1788 static const char rectxine[] = "\t... setting up rectangular Xinerama layout\n"; 1789 1790 pSiS->MBXNR1XMAX = pSiS->MBXNR1YMAX = pSiS->MBXNR2XMAX = pSiS->MBXNR2YMAX = 65536; 1791 pSiS->HaveNonRect = pSiS->HaveOffsRegions = FALSE; 1792 1793 if(!pSiS->MergedFB) return; 1794 1795 if(SiSnoPanoramiXExtension) return; 1796 1797 if(!SiSXineramadataPtr) return; 1798 1799 if(pSiS->CRT2IsScrn0) { 1800 crt1scrnnum = 1; 1801 crt2scrnnum = 0; 1802 } 1803 1804 /* Attention: Usage of RandR may lead to virtual X and Y dimensions 1805 * actually smaller than our MetaModes. To avoid this, we calculate 1806 * the maxCRT fields here (and not somewhere else, like in CopyNLink) 1807 * 1808 * *** Note: RandR is disabled if one of CRTxxOffs is non-zero. 1809 */ 1810 1811 /* "Real" virtual: Virtual without the Offset */ 1812 realvirtX = pScrn1->virtualX - pSiS->CRT1XOffs - pSiS->CRT2XOffs; 1813 realvirtY = pScrn1->virtualY - pSiS->CRT1YOffs - pSiS->CRT2YOffs; 1814 1815 if((pSiS->SiSXineramaVX != pScrn1->virtualX) || (pSiS->SiSXineramaVY != pScrn1->virtualY)) { 1816 1817 if(!(pScrn1->modes)) return; 1818 1819 pSiS->maxCRT1_X1 = pSiS->maxCRT1_X2 = 0; 1820 pSiS->maxCRT1_Y1 = pSiS->maxCRT1_Y2 = 0; 1821 pSiS->maxCRT2_X1 = pSiS->maxCRT2_X2 = 0; 1822 pSiS->maxCRT2_Y1 = pSiS->maxCRT2_Y2 = 0; 1823 pSiS->maxClone_X1 = pSiS->maxClone_X2 = 0; 1824 pSiS->maxClone_Y1 = pSiS->maxClone_Y2 = 0; 1825 1826 currentMode = firstMode = pScrn1->modes; 1827 1828 do { 1829 1830 DisplayModePtr p = currentMode->next; 1831 DisplayModePtr i = ((SiSMergedDisplayModePtr)currentMode->Private)->CRT1; 1832 DisplayModePtr j = ((SiSMergedDisplayModePtr)currentMode->Private)->CRT2; 1833 SiSScrn2Rel srel = ((SiSMergedDisplayModePtr)currentMode->Private)->CRT2Position; 1834 1835 if((currentMode->HDisplay <= realvirtX) && (currentMode->VDisplay <= realvirtY) && 1836 (i->HDisplay <= realvirtX) && (j->HDisplay <= realvirtX) && 1837 (i->VDisplay <= realvirtY) && (j->VDisplay <= realvirtY)) { 1838 1839 if(srel != sisClone) { 1840 if(pSiS->maxCRT1_X1 == i->HDisplay) { 1841 if(pSiS->maxCRT1_X2 < j->HDisplay) { 1842 pSiS->maxCRT1_X2 = j->HDisplay; /* Widest CRT2 mode displayed with widest CRT1 mode */ 1843 } 1844 } else if(pSiS->maxCRT1_X1 < i->HDisplay) { 1845 pSiS->maxCRT1_X1 = i->HDisplay; /* Widest CRT1 mode */ 1846 pSiS->maxCRT1_X2 = j->HDisplay; 1847 } 1848 if(pSiS->maxCRT2_X2 == j->HDisplay) { 1849 if(pSiS->maxCRT2_X1 < i->HDisplay) { 1850 pSiS->maxCRT2_X1 = i->HDisplay; /* Widest CRT1 mode displayed with widest CRT2 mode */ 1851 } 1852 } else if(pSiS->maxCRT2_X2 < j->HDisplay) { 1853 pSiS->maxCRT2_X2 = j->HDisplay; /* Widest CRT2 mode */ 1854 pSiS->maxCRT2_X1 = i->HDisplay; 1855 } 1856 if(pSiS->maxCRT1_Y1 == i->VDisplay) { /* Same as above, but tallest instead of widest */ 1857 if(pSiS->maxCRT1_Y2 < j->VDisplay) { 1858 pSiS->maxCRT1_Y2 = j->VDisplay; 1859 } 1860 } else if(pSiS->maxCRT1_Y1 < i->VDisplay) { 1861 pSiS->maxCRT1_Y1 = i->VDisplay; 1862 pSiS->maxCRT1_Y2 = j->VDisplay; 1863 } 1864 if(pSiS->maxCRT2_Y2 == j->VDisplay) { 1865 if(pSiS->maxCRT2_Y1 < i->VDisplay) { 1866 pSiS->maxCRT2_Y1 = i->VDisplay; 1867 } 1868 } else if(pSiS->maxCRT2_Y2 < j->VDisplay) { 1869 pSiS->maxCRT2_Y2 = j->VDisplay; 1870 pSiS->maxCRT2_Y1 = i->VDisplay; 1871 } 1872 } else { 1873 if(pSiS->maxClone_X1 < i->HDisplay) { 1874 pSiS->maxClone_X1 = i->HDisplay; 1875 } 1876 if(pSiS->maxClone_X2 < j->HDisplay) { 1877 pSiS->maxClone_X2 = j->HDisplay; 1878 } 1879 if(pSiS->maxClone_Y1 < i->VDisplay) { 1880 pSiS->maxClone_Y1 = i->VDisplay; 1881 } 1882 if(pSiS->maxClone_Y2 < j->VDisplay) { 1883 pSiS->maxClone_Y2 = j->VDisplay; 1884 } 1885 } 1886 } 1887 currentMode = p; 1888 1889 } while((currentMode) && (currentMode != firstMode)); 1890 1891 pSiS->SiSXineramaVX = pScrn1->virtualX; 1892 pSiS->SiSXineramaVY = pScrn1->virtualY; 1893 infochanged = TRUE; 1894 1895 } 1896 1897 if((usenonrect) && (pSiS->CRT2Position != sisClone) && pSiS->maxCRT1_X1) { 1898 switch(pSiS->CRT2Position) { 1899 case sisLeftOf: 1900 case sisRightOf: 1901 if((pSiS->maxCRT1_Y1 != realvirtY) && (pSiS->maxCRT2_Y2 != realvirtY)) { 1902 usenonrect = FALSE; 1903 } 1904 break; 1905 case sisAbove: 1906 case sisBelow: 1907 if((pSiS->maxCRT1_X1 != realvirtX) && (pSiS->maxCRT2_X2 != realvirtX)) { 1908 usenonrect = FALSE; 1909 } 1910 break; 1911 case sisClone: 1912 break; 1913 } 1914 if(infochanged && !usenonrect) { 1915 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 1916 "Virtual screen size does not match maximum display modes...\n"); 1917 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, "%s", rectxine); 1918 1919 } 1920 } else if(infochanged && usenonrect) { 1921 usenonrect = FALSE; 1922 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 1923 "Only clone modes available for this virtual screen size...\n"); 1924 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, "%s", rectxine); 1925 } 1926 1927 if(pSiS->maxCRT1_X1) { /* Means we have at least one non-clone mode */ 1928 switch(pSiS->CRT2Position) { 1929 case sisLeftOf: 1930 x1 = min(pSiS->maxCRT1_X2, pScrn1->virtualX - pSiS->maxCRT1_X1); 1931 if(x1 < 0) x1 = 0; 1932 y1 = pSiS->CRT1YOffs; 1933 w1 = pScrn1->virtualX - x1; 1934 h1 = realvirtY; 1935 if((usenonrect) && (pSiS->maxCRT1_Y1 != realvirtY)) { 1936 h1 = pSiS->MBXNR1YMAX = pSiS->maxCRT1_Y1; 1937 pSiS->NonRectDead.x0 = x1; 1938 pSiS->NonRectDead.x1 = x1 + w1 - 1; 1939 pSiS->NonRectDead.y0 = y1 + h1; 1940 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 1941 pSiS->HaveNonRect = TRUE; 1942 } 1943 x2 = 0; 1944 y2 = pSiS->CRT2YOffs; 1945 w2 = max(pSiS->maxCRT2_X2, pScrn1->virtualX - pSiS->maxCRT2_X1); 1946 if(w2 > pScrn1->virtualX) w2 = pScrn1->virtualX; 1947 h2 = realvirtY; 1948 if((usenonrect) && (pSiS->maxCRT2_Y2 != realvirtY)) { 1949 h2 = pSiS->MBXNR2YMAX = pSiS->maxCRT2_Y2; 1950 pSiS->NonRectDead.x0 = x2; 1951 pSiS->NonRectDead.x1 = x2 + w2 - 1; 1952 pSiS->NonRectDead.y0 = y2 + h2; 1953 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 1954 pSiS->HaveNonRect = TRUE; 1955 } 1956 break; 1957 case sisRightOf: 1958 x1 = 0; 1959 y1 = pSiS->CRT1YOffs; 1960 w1 = max(pSiS->maxCRT1_X1, pScrn1->virtualX - pSiS->maxCRT1_X2); 1961 if(w1 > pScrn1->virtualX) w1 = pScrn1->virtualX; 1962 h1 = realvirtY; 1963 if((usenonrect) && (pSiS->maxCRT1_Y1 != realvirtY)) { 1964 h1 = pSiS->MBXNR1YMAX = pSiS->maxCRT1_Y1; 1965 pSiS->NonRectDead.x0 = x1; 1966 pSiS->NonRectDead.x1 = x1 + w1 - 1; 1967 pSiS->NonRectDead.y0 = y1 + h1; 1968 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 1969 pSiS->HaveNonRect = TRUE; 1970 } 1971 x2 = min(pSiS->maxCRT2_X1, pScrn1->virtualX - pSiS->maxCRT2_X2); 1972 if(x2 < 0) x2 = 0; 1973 y2 = pSiS->CRT2YOffs; 1974 w2 = pScrn1->virtualX - x2; 1975 h2 = realvirtY; 1976 if((usenonrect) && (pSiS->maxCRT2_Y2 != realvirtY)) { 1977 h2 = pSiS->MBXNR2YMAX = pSiS->maxCRT2_Y2; 1978 pSiS->NonRectDead.x0 = x2; 1979 pSiS->NonRectDead.x1 = x2 + w2 - 1; 1980 pSiS->NonRectDead.y0 = y2 + h2; 1981 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 1982 pSiS->HaveNonRect = TRUE; 1983 } 1984 break; 1985 case sisAbove: 1986 x1 = pSiS->CRT1XOffs; 1987 y1 = min(pSiS->maxCRT1_Y2, pScrn1->virtualY - pSiS->maxCRT1_Y1); 1988 if(y1 < 0) y1 = 0; 1989 w1 = realvirtX; 1990 h1 = pScrn1->virtualY - y1; 1991 if((usenonrect) && (pSiS->maxCRT1_X1 != realvirtX)) { 1992 w1 = pSiS->MBXNR1XMAX = pSiS->maxCRT1_X1; 1993 pSiS->NonRectDead.x0 = x1 + w1; 1994 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 1995 pSiS->NonRectDead.y0 = y1; 1996 pSiS->NonRectDead.y1 = y1 + h1 - 1; 1997 pSiS->HaveNonRect = TRUE; 1998 } 1999 x2 = pSiS->CRT2XOffs; 2000 y2 = 0; 2001 w2 = realvirtX; 2002 h2 = max(pSiS->maxCRT2_Y2, pScrn1->virtualY - pSiS->maxCRT2_Y1); 2003 if(h2 > pScrn1->virtualY) h2 = pScrn1->virtualY; 2004 if((usenonrect) && (pSiS->maxCRT2_X2 != realvirtX)) { 2005 w2 = pSiS->MBXNR2XMAX = pSiS->maxCRT2_X2; 2006 pSiS->NonRectDead.x0 = x2 + w2; 2007 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 2008 pSiS->NonRectDead.y0 = y2; 2009 pSiS->NonRectDead.y1 = y2 + h2 - 1; 2010 pSiS->HaveNonRect = TRUE; 2011 } 2012 break; 2013 case sisBelow: 2014 x1 = pSiS->CRT1XOffs; 2015 y1 = 0; 2016 w1 = realvirtX; 2017 h1 = max(pSiS->maxCRT1_Y1, pScrn1->virtualY - pSiS->maxCRT1_Y2); 2018 if(h1 > pScrn1->virtualY) h1 = pScrn1->virtualY; 2019 if((usenonrect) && (pSiS->maxCRT1_X1 != realvirtX)) { 2020 w1 = pSiS->MBXNR1XMAX = pSiS->maxCRT1_X1; 2021 pSiS->NonRectDead.x0 = x1 + w1; 2022 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 2023 pSiS->NonRectDead.y0 = y1; 2024 pSiS->NonRectDead.y1 = y1 + h1 - 1; 2025 pSiS->HaveNonRect = TRUE; 2026 } 2027 x2 = pSiS->CRT2XOffs; 2028 y2 = min(pSiS->maxCRT2_Y1, pScrn1->virtualY - pSiS->maxCRT2_Y2); 2029 if(y2 < 0) y2 = 0; 2030 w2 = realvirtX; 2031 h2 = pScrn1->virtualY - y2; 2032 if((usenonrect) && (pSiS->maxCRT2_X2 != realvirtX)) { 2033 w2 = pSiS->MBXNR2XMAX = pSiS->maxCRT2_X2; 2034 pSiS->NonRectDead.x0 = x2 + w2; 2035 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 2036 pSiS->NonRectDead.y0 = y2; 2037 pSiS->NonRectDead.y1 = y2 + h2 - 1; 2038 pSiS->HaveNonRect = TRUE; 2039 } 2040 default: 2041 break; 2042 } 2043 2044 switch(pSiS->CRT2Position) { 2045 case sisLeftOf: 2046 case sisRightOf: 2047 if(pSiS->CRT1YOffs) { 2048 pSiS->OffDead1.x0 = x1; 2049 pSiS->OffDead1.x1 = x1 + w1 - 1; 2050 pSiS->OffDead1.y0 = 0; 2051 pSiS->OffDead1.y1 = y1 - 1; 2052 pSiS->OffDead2.x0 = x2; 2053 pSiS->OffDead2.x1 = x2 + w2 - 1; 2054 pSiS->OffDead2.y0 = y2 + h2; 2055 pSiS->OffDead2.y1 = pScrn1->virtualY - 1; 2056 pSiS->HaveOffsRegions = TRUE; 2057 } else if(pSiS->CRT2YOffs) { 2058 pSiS->OffDead1.x0 = x2; 2059 pSiS->OffDead1.x1 = x2 + w2 - 1; 2060 pSiS->OffDead1.y0 = 0; 2061 pSiS->OffDead1.y1 = y2 - 1; 2062 pSiS->OffDead2.x0 = x1; 2063 pSiS->OffDead2.x1 = x1 + w1 - 1; 2064 pSiS->OffDead2.y0 = y1 + h1; 2065 pSiS->OffDead2.y1 = pScrn1->virtualY - 1; 2066 pSiS->HaveOffsRegions = TRUE; 2067 } 2068 break; 2069 case sisAbove: 2070 case sisBelow: 2071 if(pSiS->CRT1XOffs) { 2072 pSiS->OffDead1.x0 = x2 + w2; 2073 pSiS->OffDead1.x1 = pScrn1->virtualX - 1; 2074 pSiS->OffDead1.y0 = y2; 2075 pSiS->OffDead1.y1 = y2 + h2 - 1; 2076 pSiS->OffDead2.x0 = 0; 2077 pSiS->OffDead2.x1 = x1 - 1; 2078 pSiS->OffDead2.y0 = y1; 2079 pSiS->OffDead2.y1 = y1 + h1 - 1; 2080 pSiS->HaveOffsRegions = TRUE; 2081 } else if(pSiS->CRT2XOffs) { 2082 pSiS->OffDead1.x0 = x1 + w1; 2083 pSiS->OffDead1.x1 = pScrn1->virtualX - 1; 2084 pSiS->OffDead1.y0 = y1; 2085 pSiS->OffDead1.y1 = y1 + h1 - 1; 2086 pSiS->OffDead2.x0 = 0; 2087 pSiS->OffDead2.x1 = x2 - 1; 2088 pSiS->OffDead2.y0 = y2; 2089 pSiS->OffDead2.y1 = y2 + h2 - 1; 2090 pSiS->HaveOffsRegions = TRUE; 2091 } 2092 default: 2093 break; 2094 } 2095 2096 } else { /* Only clone-modes left */ 2097 2098 x1 = x2 = 0; 2099 y1 = y2 = 0; 2100 w1 = w2 = max(pSiS->maxClone_X1, pSiS->maxClone_X2); 2101 h1 = h2 = max(pSiS->maxClone_Y1, pSiS->maxClone_Y2); 2102 2103 } 2104 2105 SiSXineramadataPtr[crt1scrnnum].x = x1; 2106 SiSXineramadataPtr[crt1scrnnum].y = y1; 2107 SiSXineramadataPtr[crt1scrnnum].width = w1; 2108 SiSXineramadataPtr[crt1scrnnum].height = h1; 2109 SiSXineramadataPtr[crt2scrnnum].x = x2; 2110 SiSXineramadataPtr[crt2scrnnum].y = y2; 2111 SiSXineramadataPtr[crt2scrnnum].width = w2; 2112 SiSXineramadataPtr[crt2scrnnum].height = h2; 2113 2114 if(infochanged) { 2115 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2116 "Pseudo-Xinerama: CRT1 (Screen %d) (%d,%d)-(%d,%d)\n", 2117 crt1scrnnum, x1, y1, w1+x1-1, h1+y1-1); 2118 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2119 "Pseudo-Xinerama: CRT2 (Screen %d) (%d,%d)-(%d,%d)\n", 2120 crt2scrnnum, x2, y2, w2+x2-1, h2+y2-1); 2121 if(pSiS->HaveNonRect) { 2122 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2123 "Pseudo-Xinerama: Inaccessible area (%d,%d)-(%d,%d)\n", 2124 pSiS->NonRectDead.x0, pSiS->NonRectDead.y0, 2125 pSiS->NonRectDead.x1, pSiS->NonRectDead.y1); 2126 } 2127 if(pSiS->HaveOffsRegions) { 2128 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2129 "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", 2130 pSiS->OffDead1.x0, pSiS->OffDead1.y0, 2131 pSiS->OffDead1.x1, pSiS->OffDead1.y1); 2132 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2133 "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", 2134 pSiS->OffDead2.x0, pSiS->OffDead2.y0, 2135 pSiS->OffDead2.x1, pSiS->OffDead2.y1); 2136 } 2137 if(pSiS->HaveNonRect || pSiS->HaveOffsRegions) { 2138 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2139 "Mouse restriction for inaccessible areas is %s\n", 2140 pSiS->MouseRestrictions ? "enabled" : "disabled"); 2141 } 2142 } 2143} 2144 2145/* Proc */ 2146 2147int 2148SiSProcXineramaQueryVersion(ClientPtr client) 2149{ 2150 xPanoramiXQueryVersionReply rep; 2151 register int n; 2152 2153 REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq); 2154 rep.type = X_Reply; 2155 rep.length = 0; 2156 rep.sequenceNumber = client->sequence; 2157 rep.majorVersion = SIS_XINERAMA_MAJOR_VERSION; 2158 rep.minorVersion = SIS_XINERAMA_MINOR_VERSION; 2159 if(client->swapped) { 2160 _swaps(&rep.sequenceNumber, n); 2161 _swapl(&rep.length, n); 2162 _swaps(&rep.majorVersion, n); 2163 _swaps(&rep.minorVersion, n); 2164 } 2165 WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *)&rep); 2166 return (client->noClientException); 2167} 2168 2169int 2170SiSProcXineramaGetState(ClientPtr client) 2171{ 2172 REQUEST(xPanoramiXGetStateReq); 2173 WindowPtr pWin; 2174 xPanoramiXGetStateReply rep; 2175 register int n; 2176 int rc; 2177 2178 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); 2179 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 2180 if (rc != Success) 2181 return rc; 2182 2183 rep.type = X_Reply; 2184 rep.length = 0; 2185 rep.sequenceNumber = client->sequence; 2186 rep.state = !SiSnoPanoramiXExtension; 2187 if(client->swapped) { 2188 _swaps (&rep.sequenceNumber, n); 2189 _swapl (&rep.length, n); 2190 } 2191 WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *)&rep); 2192 return client->noClientException; 2193} 2194 2195int 2196SiSProcXineramaGetScreenCount(ClientPtr client) 2197{ 2198 REQUEST(xPanoramiXGetScreenCountReq); 2199 WindowPtr pWin; 2200 xPanoramiXGetScreenCountReply rep; 2201 register int n; 2202 int rc; 2203 2204 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); 2205 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 2206 if (rc != Success) 2207 return rc; 2208 2209 rep.type = X_Reply; 2210 rep.length = 0; 2211 rep.sequenceNumber = client->sequence; 2212 rep.ScreenCount = SiSXineramaNumScreens; 2213 if(client->swapped) { 2214 _swaps(&rep.sequenceNumber, n); 2215 _swapl(&rep.length, n); 2216 } 2217 WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep); 2218 return client->noClientException; 2219} 2220 2221int 2222SiSProcXineramaGetScreenSize(ClientPtr client) 2223{ 2224 REQUEST(xPanoramiXGetScreenSizeReq); 2225 WindowPtr pWin; 2226 xPanoramiXGetScreenSizeReply rep; 2227 register int n; 2228 int rc; 2229 2230 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); 2231 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 2232 if (rc != Success) 2233 return rc; 2234 2235 rep.type = X_Reply; 2236 rep.length = 0; 2237 rep.sequenceNumber = client->sequence; 2238 rep.width = SiSXineramadataPtr[stuff->screen].width; 2239 rep.height = SiSXineramadataPtr[stuff->screen].height; 2240 if(client->swapped) { 2241 _swaps(&rep.sequenceNumber, n); 2242 _swapl(&rep.length, n); 2243 _swapl(&rep.width, n); 2244 _swapl(&rep.height, n); 2245 } 2246 WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep); 2247 return client->noClientException; 2248} 2249 2250int 2251SiSProcXineramaIsActive(ClientPtr client) 2252{ 2253 xXineramaIsActiveReply rep; 2254 2255 REQUEST_SIZE_MATCH(xXineramaIsActiveReq); 2256 2257 rep.type = X_Reply; 2258 rep.length = 0; 2259 rep.sequenceNumber = client->sequence; 2260 rep.state = !SiSnoPanoramiXExtension; 2261 if(client->swapped) { 2262 register int n; 2263 _swaps(&rep.sequenceNumber, n); 2264 _swapl(&rep.length, n); 2265 _swapl(&rep.state, n); 2266 } 2267 WriteToClient(client, sizeof(xXineramaIsActiveReply), (char *) &rep); 2268 return client->noClientException; 2269} 2270 2271int 2272SiSProcXineramaQueryScreens(ClientPtr client) 2273{ 2274 xXineramaQueryScreensReply rep; 2275 2276 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); 2277 2278 rep.type = X_Reply; 2279 rep.sequenceNumber = client->sequence; 2280 rep.number = (SiSnoPanoramiXExtension) ? 0 : SiSXineramaNumScreens; 2281 rep.length = rep.number * sz_XineramaScreenInfo >> 2; 2282 if(client->swapped) { 2283 register int n; 2284 _swaps(&rep.sequenceNumber, n); 2285 _swapl(&rep.length, n); 2286 _swapl(&rep.number, n); 2287 } 2288 WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *)&rep); 2289 2290 if(!SiSnoPanoramiXExtension) { 2291 xXineramaScreenInfo scratch; 2292 int i; 2293 2294 for(i = 0; i < SiSXineramaNumScreens; i++) { 2295 scratch.x_org = SiSXineramadataPtr[i].x; 2296 scratch.y_org = SiSXineramadataPtr[i].y; 2297 scratch.width = SiSXineramadataPtr[i].width; 2298 scratch.height = SiSXineramadataPtr[i].height; 2299 if(client->swapped) { 2300 register int n; 2301 _swaps(&scratch.x_org, n); 2302 _swaps(&scratch.y_org, n); 2303 _swaps(&scratch.width, n); 2304 _swaps(&scratch.height, n); 2305 } 2306 WriteToClient(client, sz_XineramaScreenInfo, (char *)&scratch); 2307 } 2308 } 2309 2310 return client->noClientException; 2311} 2312 2313static int 2314SiSProcXineramaDispatch(ClientPtr client) 2315{ 2316 REQUEST(xReq); 2317 switch (stuff->data) { 2318 case X_PanoramiXQueryVersion: 2319 return SiSProcXineramaQueryVersion(client); 2320 case X_PanoramiXGetState: 2321 return SiSProcXineramaGetState(client); 2322 case X_PanoramiXGetScreenCount: 2323 return SiSProcXineramaGetScreenCount(client); 2324 case X_PanoramiXGetScreenSize: 2325 return SiSProcXineramaGetScreenSize(client); 2326 case X_XineramaIsActive: 2327 return SiSProcXineramaIsActive(client); 2328 case X_XineramaQueryScreens: 2329 return SiSProcXineramaQueryScreens(client); 2330 } 2331 return BadRequest; 2332} 2333 2334/* SProc */ 2335 2336static int 2337SiSSProcXineramaQueryVersion (ClientPtr client) 2338{ 2339 REQUEST(xPanoramiXQueryVersionReq); 2340 register int n; 2341 _swaps(&stuff->length,n); 2342 REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); 2343 return SiSProcXineramaQueryVersion(client); 2344} 2345 2346static int 2347SiSSProcXineramaGetState(ClientPtr client) 2348{ 2349 REQUEST(xPanoramiXGetStateReq); 2350 register int n; 2351 _swaps (&stuff->length, n); 2352 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); 2353 return SiSProcXineramaGetState(client); 2354} 2355 2356static int 2357SiSSProcXineramaGetScreenCount(ClientPtr client) 2358{ 2359 REQUEST(xPanoramiXGetScreenCountReq); 2360 register int n; 2361 _swaps (&stuff->length, n); 2362 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); 2363 return SiSProcXineramaGetScreenCount(client); 2364} 2365 2366static int 2367SiSSProcXineramaGetScreenSize(ClientPtr client) 2368{ 2369 REQUEST(xPanoramiXGetScreenSizeReq); 2370 register int n; 2371 _swaps (&stuff->length, n); 2372 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); 2373 return SiSProcXineramaGetScreenSize(client); 2374} 2375 2376static int 2377SiSSProcXineramaIsActive(ClientPtr client) 2378{ 2379 REQUEST(xXineramaIsActiveReq); 2380 register int n; 2381 _swaps (&stuff->length, n); 2382 REQUEST_SIZE_MATCH(xXineramaIsActiveReq); 2383 return SiSProcXineramaIsActive(client); 2384} 2385 2386static int 2387SiSSProcXineramaQueryScreens(ClientPtr client) 2388{ 2389 REQUEST(xXineramaQueryScreensReq); 2390 register int n; 2391 _swaps (&stuff->length, n); 2392 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); 2393 return SiSProcXineramaQueryScreens(client); 2394} 2395 2396int 2397SiSSProcXineramaDispatch(ClientPtr client) 2398{ 2399 REQUEST(xReq); 2400 switch (stuff->data) { 2401 case X_PanoramiXQueryVersion: 2402 return SiSSProcXineramaQueryVersion(client); 2403 case X_PanoramiXGetState: 2404 return SiSSProcXineramaGetState(client); 2405 case X_PanoramiXGetScreenCount: 2406 return SiSSProcXineramaGetScreenCount(client); 2407 case X_PanoramiXGetScreenSize: 2408 return SiSSProcXineramaGetScreenSize(client); 2409 case X_XineramaIsActive: 2410 return SiSSProcXineramaIsActive(client); 2411 case X_XineramaQueryScreens: 2412 return SiSSProcXineramaQueryScreens(client); 2413 } 2414 return BadRequest; 2415} 2416 2417static void 2418SiSXineramaResetProc(ExtensionEntry* extEntry) 2419{ 2420 /* Called by CloseDownExtensions() */ 2421 if(SiSXineramadataPtr) { 2422 free(SiSXineramadataPtr); 2423 SiSXineramadataPtr = NULL; 2424 } 2425} 2426 2427static void 2428SiSXineramaExtensionInit(ScrnInfoPtr pScrn) 2429{ 2430 SISPtr pSiS = SISPTR(pScrn); 2431 Bool success = FALSE; 2432 2433 if(!(SiSXineramadataPtr)) { 2434 2435 if(!pSiS->MergedFB) { 2436 SiSnoPanoramiXExtension = TRUE; 2437 pSiS->MouseRestrictions = FALSE; 2438 return; 2439 } 2440 2441#ifdef PANORAMIX 2442 if(!noPanoramiXExtension) { 2443 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2444 "Xinerama active, not initializing SiS Pseudo-Xinerama\n"); 2445 SiSnoPanoramiXExtension = TRUE; 2446 pSiS->MouseRestrictions = FALSE; 2447 return; 2448 } 2449#endif 2450 2451 if(SiSnoPanoramiXExtension) { 2452 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2453 "SiS Pseudo-Xinerama disabled\n"); 2454 pSiS->MouseRestrictions = FALSE; 2455 return; 2456 } 2457 2458 if(pSiS->CRT2Position == sisClone) { 2459 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2460 "Running MergedFB in Clone mode, SiS Pseudo-Xinerama disabled\n"); 2461 SiSnoPanoramiXExtension = TRUE; 2462 pSiS->MouseRestrictions = FALSE; 2463 return; 2464 } 2465 2466 if(!(pSiS->AtLeastOneNonClone)) { 2467 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2468 "Only Clone modes defined, SiS Pseudo-Xinerama disabled\n"); 2469 SiSnoPanoramiXExtension = TRUE; 2470 pSiS->MouseRestrictions = FALSE; 2471 return; 2472 } 2473 2474 SiSXineramaNumScreens = 2; 2475 2476 while(SiSXineramaGeneration != serverGeneration) { 2477 2478 pSiS->XineramaExtEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0, 2479 SiSProcXineramaDispatch, 2480 SiSSProcXineramaDispatch, 2481 SiSXineramaResetProc, 2482 StandardMinorOpcode); 2483 2484 if(!pSiS->XineramaExtEntry) break; 2485 2486 if(!(SiSXineramadataPtr = (SiSXineramaData *) 2487 calloc(SiSXineramaNumScreens, sizeof(SiSXineramaData)))) break; 2488 2489 SiSXineramaGeneration = serverGeneration; 2490 success = TRUE; 2491 } 2492 2493 if(!success) { 2494 SISErrorLog(pScrn, "Failed to initialize SiS Pseudo-Xinerama extension\n"); 2495 SiSnoPanoramiXExtension = TRUE; 2496 pSiS->MouseRestrictions = FALSE; 2497 return; 2498 } 2499 2500 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2501 "SiS Pseudo-Xinerama extension initialized\n"); 2502 2503 pSiS->SiSXineramaVX = 0; 2504 pSiS->SiSXineramaVY = 0; 2505 2506 } 2507 2508 SiSUpdateXineramaScreenInfo(pScrn); 2509 2510} 2511#endif /* End of PseudoXinerama */ 2512 2513static void 2514SiSFreeCRT2Structs(SISPtr pSiS) 2515{ 2516 if(pSiS->CRT2pScrn) { 2517 if(pSiS->CRT2pScrn->modes) { 2518 while(pSiS->CRT2pScrn->modes) 2519 xf86DeleteMode(&pSiS->CRT2pScrn->modes, pSiS->CRT2pScrn->modes); 2520 } 2521 if(pSiS->CRT2pScrn->monitor) { 2522 if(pSiS->CRT2pScrn->monitor->Modes) { 2523 while(pSiS->CRT2pScrn->monitor->Modes) 2524 xf86DeleteMode(&pSiS->CRT2pScrn->monitor->Modes, pSiS->CRT2pScrn->monitor->Modes); 2525 } 2526 if(pSiS->CRT2pScrn->monitor->DDC) free(pSiS->CRT2pScrn->monitor->DDC); 2527 free(pSiS->CRT2pScrn->monitor); 2528 } 2529 free(pSiS->CRT2pScrn); 2530 pSiS->CRT2pScrn = NULL; 2531 } 2532} 2533 2534#endif /* End of MergedFB helpers */ 2535 2536static xf86MonPtr 2537SiSInternalDDC(ScrnInfoPtr pScrn, int crtno) 2538{ 2539 SISPtr pSiS = SISPTR(pScrn); 2540 xf86MonPtr pMonitor = NULL; 2541 UShort temp = 0xffff, temp1, i, realcrtno = crtno; 2542 UChar buffer[256]; 2543 2544 /* If CRT1 is off, skip DDC */ 2545 if((pSiS->CRT1off) && (!crtno)) return NULL; 2546 2547 if(crtno) { 2548 if(pSiS->VBFlags & CRT2_LCD) realcrtno = 1; 2549 else if(pSiS->VBFlags & CRT2_VGA) realcrtno = 2; 2550 else return NULL; 2551 if(pSiS->SiS_Pr->DDCPortMixup) realcrtno = 0; 2552 } else { 2553 /* If CRT1 is LCDA, skip DDC (except 301C: DDC allowed, but uses CRT2 port!) */ 2554 if(pSiS->VBFlags & CRT1_LCDA) { 2555 if(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE) realcrtno = 1; 2556 else return NULL; 2557 } 2558 } 2559 2560 i = 3; /* Number of retrys */ 2561 do { 2562 temp1 = SiS_HandleDDC(pSiS->SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 2563 realcrtno, 0, &buffer[0], pSiS->VBFlags2); 2564 if((temp1) && (temp1 != 0xffff)) temp = temp1; 2565 } while((temp == 0xffff) && i--); 2566 if(temp != 0xffff) { 2567 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT%d DDC supported\n", crtno + 1); 2568 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT%d DDC level: %s%s%s%s\n", 2569 crtno + 1, 2570 (temp & 0x1a) ? "" : "[none of the supported]", 2571 (temp & 0x02) ? "2 " : "", 2572 (temp & 0x08) ? "D&P" : "", 2573 (temp & 0x10) ? "FPDI-2" : ""); 2574 if(temp & 0x02) { 2575 i = 5; /* Number of retrys */ 2576 do { 2577 temp = SiS_HandleDDC(pSiS->SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 2578 realcrtno, 1, &buffer[0], pSiS->VBFlags2); 2579 } while((temp) && i--); 2580 if(!temp) { 2581 if((pMonitor = xf86InterpretEDID(pScrn->scrnIndex, &buffer[0]))) { 2582 int tempvgagamma = 0, templcdgamma = 0; 2583 if(buffer[0x14] & 0x80) { 2584 templcdgamma = (buffer[0x17] + 100) * 10; 2585 } else { 2586 tempvgagamma = (buffer[0x17] + 100) * 10;; 2587 } 2588 if(crtno == 0) { 2589 if(tempvgagamma) pSiS->CRT1VGAMonitorGamma = tempvgagamma; 2590 /* LCD never via (demanded) CRT1 DDC port */ 2591 } else { 2592 if(tempvgagamma) pSiS->CRT2VGAMonitorGamma = tempvgagamma; 2593 if(templcdgamma) pSiS->CRT2LCDMonitorGamma = templcdgamma; 2594 } 2595 return(pMonitor); 2596 } else { 2597 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2598 "CRT%d DDC EDID corrupt\n", crtno + 1); 2599 } 2600 } else if(temp == 0xFFFE) { 2601 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2602 "CRT%d DDC data is from wrong device type (%s)\n", 2603 crtno + 1, 2604 (realcrtno == 1) ? "analog instead of digital" : "digital instead of analog"); 2605 } else { 2606 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2607 "CRT%d DDC reading failed\n", crtno + 1); 2608 } 2609 } else if(temp & 0x18) { 2610 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2611 "DDC for VESA D&P and FPDI-2 not supported yet.\n"); 2612 } 2613 } else { 2614 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2615 "CRT%d DDC probing failed\n", crtno + 1); 2616 } 2617 return(NULL); 2618} 2619 2620static xf86MonPtr 2621SiSDoPrivateDDC(ScrnInfoPtr pScrn, int *crtnum) 2622{ 2623 SISPtr pSiS = SISPTR(pScrn); 2624 2625#ifdef SISDUALHEAD 2626 if(pSiS->DualHeadMode) { 2627 if(pSiS->SecondHead) { 2628 *crtnum = 1; 2629 return(SiSInternalDDC(pScrn, 0)); 2630 } else { 2631 *crtnum = 2; 2632 return(SiSInternalDDC(pScrn, 1)); 2633 } 2634 } else 2635#endif 2636 if((pSiS->CRT1off) || (!pSiS->CRT1Detected)) { 2637 *crtnum = 2; 2638 return(SiSInternalDDC(pScrn, 1)); 2639 } else { 2640 *crtnum = 1; 2641 return(SiSInternalDDC(pScrn, 0)); 2642 } 2643} 2644 2645static void 2646SiSFindAspect(ScrnInfoPtr pScrn, xf86MonPtr pMonitor, int crtnum) 2647{ 2648 SISPtr pSiS = SISPTR(pScrn); 2649 int UseWide = 0; 2650 int aspect = 0; 2651 Bool fromdim = FALSE; 2652 2653 if((pSiS->VGAEngine == SIS_315_VGA) && (!DIGITAL(pMonitor->features.input_type))) { 2654 if(pMonitor->features.hsize && pMonitor->features.vsize) { 2655 aspect = (pMonitor->features.hsize * 1000) / pMonitor->features.vsize; 2656 if(aspect >= 1400) UseWide = 1; 2657 fromdim = TRUE; 2658 } else if((PREFERRED_TIMING_MODE(pMonitor->features.msc)) && 2659 (pMonitor->det_mon[0].type == DT)) { 2660 aspect = (pMonitor->det_mon[0].section.d_timings.h_active * 1000) / 2661 pMonitor->det_mon[0].section.d_timings.v_active; 2662 if(aspect >= 1400) UseWide = 1; 2663 } 2664 if(aspect) { 2665 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2666 "According to %s, CRT%d aspect ratio is %.2f:1 (%s)\n", 2667 fromdim ? "DDC size" : "preferred mode", 2668 crtnum, (float)aspect / 1000.0, UseWide ? "wide" : "normal"); 2669 } else { 2670 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2671 "Unable to determine CRT%d aspect ratio, assuming \"normal\"\n", 2672 crtnum); 2673 } 2674 } 2675 2676 if((crtnum == 1) && (pSiS->SiS_Pr->SiS_UseWide == -1)) { 2677 pSiS->SiS_Pr->SiS_UseWide = UseWide; 2678 } else if((crtnum == 2) && (pSiS->SiS_Pr->SiS_UseWideCRT2 == -1)) { 2679 pSiS->SiS_Pr->SiS_UseWideCRT2 = UseWide; 2680 } 2681} 2682 2683static Bool 2684SiSMakeOwnModeList(ScrnInfoPtr pScrn, Bool acceptcustommodes, Bool includelcdmodes, 2685 Bool isfordvi, Bool *havecustommodes, Bool fakecrt2modes, Bool IsForCRT2) 2686{ 2687 DisplayModePtr tempmode, delmode, mymodes; 2688 2689 if((mymodes = SiSBuildBuiltInModeList(pScrn, includelcdmodes, isfordvi, fakecrt2modes, IsForCRT2))) { 2690 if(!acceptcustommodes) { 2691 while(pScrn->monitor->Modes) 2692 xf86DeleteMode(&pScrn->monitor->Modes, pScrn->monitor->Modes); 2693 pScrn->monitor->Modes = mymodes; 2694 } else { 2695 delmode = pScrn->monitor->Modes; 2696 while(delmode) { 2697 if(delmode->type & M_T_DEFAULT) { 2698 tempmode = delmode->next; 2699 xf86DeleteMode(&pScrn->monitor->Modes, delmode); 2700 delmode = tempmode; 2701 } else { 2702 delmode = delmode->next; 2703 } 2704 } 2705 /* Link default modes AFTER user ones */ 2706 if((tempmode = pScrn->monitor->Modes)) { 2707 *havecustommodes = TRUE; 2708 while(tempmode) { 2709 if(!tempmode->next) break; 2710 else tempmode = tempmode->next; 2711 } 2712 tempmode->next = mymodes; 2713 mymodes->prev = tempmode; 2714 } else { 2715 pScrn->monitor->Modes = mymodes; 2716 } 2717#if 0 2718 pScrn->monitor->Modes = mymodes; 2719 while(mymodes) { 2720 if(!mymodes->next) break; 2721 else mymodes = mymodes->next; 2722 } 2723 mymodes->next = tempmode; 2724 if(tempmode) { 2725 tempmode->prev = mymodes; 2726 } 2727#endif 2728 } 2729 return TRUE; 2730 } else 2731 return FALSE; 2732} 2733 2734static void 2735SiSPrintModes(ScrnInfoPtr pScrn) 2736{ 2737 DisplayModePtr p; 2738 float hsync, refresh = 0.0; 2739 char *desc, *desc2, *prefix, *uprefix, *output; 2740 2741 xf86DrvMsg(pScrn->scrnIndex, pScrn->virtualFrom, "Virtual size is %dx%d " 2742 "(pitch %d)\n", pScrn->virtualX, pScrn->virtualY, 2743 pScrn->displayWidth); 2744 2745 if((p = pScrn->modes) == NULL) return; 2746 2747 do { 2748 desc = desc2 = ""; 2749 uprefix = " "; 2750 prefix = "Mode"; 2751 output = "For CRT device: "; 2752 if(p->HSync > 0.0) hsync = p->HSync; 2753 else if (p->HTotal > 0) hsync = (float)p->Clock / (float)p->HTotal; 2754 else hsync = 0.0; 2755 refresh = 0.0; 2756 if(p->VRefresh > 0.0) refresh = p->VRefresh; 2757 else if (p->HTotal > 0 && p->VTotal > 0) { 2758 refresh = p->Clock * 1000.0 / p->HTotal / p->VTotal; 2759 if(p->Flags & V_INTERLACE) refresh *= 2.0; 2760 if(p->Flags & V_DBLSCAN) refresh /= 2.0; 2761 if(p->VScan > 1) refresh /= p->VScan; 2762 } 2763 if(p->Flags & V_INTERLACE) desc = " (I)"; 2764 if(p->Flags & V_DBLSCAN) desc = " (D)"; 2765 if(p->VScan > 1) desc2 = " (VScan)"; 2766#ifdef M_T_USERDEF 2767 if(p->type & M_T_USERDEF) uprefix = "*"; 2768#endif 2769 if(p->type & M_T_BUILTIN) { 2770 prefix = "Built-in mode"; 2771 output = ""; 2772 } else if (p->type & M_T_DEFAULT) { 2773 prefix = "Default mode"; 2774 } else { 2775 output = ""; 2776 } 2777 2778 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2779 "%s%s \"%s\" (%dx%d) (%s%.1f MHz, %.1f kHz, %.1f Hz%s%s)\n", 2780 uprefix, prefix, p->name, p->HDisplay, p->VDisplay, output, 2781 p->Clock / 1000.0, hsync, refresh, desc, desc2); 2782 2783 p = p->next; 2784 } while (p != NULL && p != pScrn->modes); 2785} 2786 2787Bool SISDetermineLCDACap(ScrnInfoPtr pScrn) 2788{ 2789 SISPtr pSiS = SISPTR(pScrn); 2790 2791 if( ((pSiS->ChipType == SIS_650) || 2792 (pSiS->ChipType == SIS_315PRO) || 2793 (pSiS->ChipType >= SIS_661)) && 2794 (pSiS->ChipType != XGI_20) && 2795 (pSiS->VBFlags2 & VB2_SISLCDABRIDGE) && 2796 (pSiS->VESA != 1) ) { 2797 return TRUE; 2798 } 2799 return FALSE; 2800} 2801 2802void SISSaveDetectedDevices(ScrnInfoPtr pScrn) 2803{ 2804 SISPtr pSiS = SISPTR(pScrn); 2805 /* Backup detected CRT2 devices */ 2806 pSiS->detectedCRT2Devices = pSiS->VBFlags & (CRT2_LCD|CRT2_TV|CRT2_VGA|TV_AVIDEO|TV_SVIDEO| 2807 TV_SCART|TV_HIVISION|TV_YPBPR); 2808} 2809 2810static Bool 2811SISCheckBIOS(SISPtr pSiS, UShort mypciid, UShort mypcivendor, int biossize) 2812{ 2813 UShort romptr, pciid; 2814 2815 if(!pSiS->BIOS) return FALSE; 2816 2817 if((pSiS->BIOS[0] != 0x55) || (pSiS->BIOS[1] != 0xaa)) return FALSE; 2818 2819 romptr = pSiS->BIOS[0x18] | (pSiS->BIOS[0x19] << 8); 2820 if(romptr > (biossize - 8)) return FALSE; 2821 if((pSiS->BIOS[romptr] != 'P') || (pSiS->BIOS[romptr+1] != 'C') || 2822 (pSiS->BIOS[romptr+2] != 'I') || (pSiS->BIOS[romptr+3] != 'R')) return FALSE; 2823 2824 pciid = pSiS->BIOS[romptr+4] | (pSiS->BIOS[romptr+5] << 8); 2825 if(pciid != mypcivendor) return FALSE; 2826 2827 pciid = pSiS->BIOS[romptr+6] | (pSiS->BIOS[romptr+7] << 8); 2828 if(pciid != mypciid) return FALSE; 2829 2830 return TRUE; 2831} 2832 2833static void 2834SiS_LoadInitVBE(ScrnInfoPtr pScrn) 2835{ 2836 SISPtr pSiS = SISPTR(pScrn); 2837 2838 /* Don't load the VBE module for secondary 2839 * cards which sisfb POSTed. We don't want 2840 * int10 to overwrite our set up (such as 2841 * disabled a0000 memory address decoding). 2842 * We don't need the VBE anyway because 2843 * the card will never be in text mode, 2844 * and we can restore graphics modes just 2845 * perfectly. 2846 */ 2847 if( !pSiS->Primary && 2848 pSiS->sisfbcardposted) 2849 return; 2850 2851 if(pSiS->pVbe) return; 2852 2853 if(xf86LoadSubModule(pScrn, "vbe")) { 2854#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 2855 pSiS->pVbe = VBEInit(pSiS->pInt, pSiS->pEnt->index); 2856#else 2857 pSiS->pVbe = VBEExtendedInit(pSiS->pInt, pSiS->pEnt->index, 2858 SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH); 2859#endif 2860 } 2861 2862 if(!pSiS->pVbe) { 2863 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2864 "Failed to load/initialize vbe module\n"); 2865 } 2866} 2867 2868#ifdef SIS_PC_PLATFORM 2869static void 2870SiS_MapVGAMem(ScrnInfoPtr pScrn) 2871{ 2872 SISPtr pSiS = SISPTR(pScrn); 2873 2874 /* Map 64k VGA window for saving/restoring CGA fonts */ 2875 pSiS->VGAMapSize = 0x10000; 2876 pSiS->VGAMapPhys = 0; /* Default */ 2877 if((!pSiS->Primary) || (!pSiS->VGADecodingEnabled)) { 2878 /* If card is secondary or if a0000-address decoding 2879 * is disabled, set Phys to beginning of our video RAM. 2880 */ 2881 pSiS->VGAMapPhys = PCI_REGION_BASE(pSiS->PciInfo, 0, REGION_MEM); 2882 } 2883 if(!SiSVGAMapMem(pScrn)) { 2884 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2885 "Failed to map VGA memory (0x%lx), can't save/restore console fonts\n", 2886 pSiS->VGAMapPhys); 2887 } 2888} 2889#endif 2890 2891static void 2892SiS_CheckKernelFB(ScrnInfoPtr pScrn) 2893{ 2894 SISPtr pSiS = SISPTR(pScrn); 2895 int fd, i; 2896 CARD32 sisfbinfosize = 0, sisfbversion; 2897 sisfb_info *mysisfbinfo; 2898 char name[16]; 2899 2900 pSiS->donttrustpdc = FALSE; 2901 pSiS->sisfbpdc = 0xff; 2902 pSiS->sisfbpdca = 0xff; 2903 pSiS->sisfblcda = 0xff; 2904 pSiS->sisfbscalelcd = -1; 2905 pSiS->sisfbspecialtiming = CUT_NONE; 2906 pSiS->sisfb_haveemi = FALSE; 2907 pSiS->sisfbfound = FALSE; 2908 pSiS->sisfb_tvposvalid = FALSE; 2909 pSiS->sisfbdevname[0] = 0; 2910 pSiS->sisfb_havelock = FALSE; 2911 pSiS->sisfbHaveNewHeapDef = FALSE; 2912 pSiS->sisfbHeapSize = 0; 2913 pSiS->sisfbVideoOffset = 0; 2914 pSiS->sisfbxSTN = FALSE; 2915 pSiS->sisfbcanpost = FALSE; /* (Old) sisfb can't POST card */ 2916 pSiS->sisfbcardposted = TRUE; /* If (old) sisfb is running, card must have been POSTed */ 2917 pSiS->sisfbprimary = FALSE; /* (Old) sisfb doesn't know */ 2918 2919 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 2920 2921 i = 0; 2922 do { 2923 2924 if(i <= 7) { 2925 sprintf(name, "/dev/fb%1d", i); 2926 } else { 2927 sprintf(name, "/dev/fb/%1d", (i - 8)); 2928 } 2929 2930 if((fd = open(name, O_RDONLY)) != -1) { 2931 2932 Bool gotit = FALSE; 2933 2934 if(!ioctl(fd, SISFB_GET_INFO_SIZE, &sisfbinfosize)) { 2935 if((mysisfbinfo = malloc(sisfbinfosize))) { 2936 if(!ioctl(fd, (SISFB_GET_INFO | (sisfbinfosize << 16)), mysisfbinfo)) { 2937 gotit = TRUE; 2938 } else { 2939 free(mysisfbinfo); 2940 mysisfbinfo = NULL; 2941 } 2942 } 2943 } else { 2944 if((mysisfbinfo = malloc(sizeof(*mysisfbinfo) + 16))) { 2945 if(!ioctl(fd, SISFB_GET_INFO_OLD, mysisfbinfo)) { 2946 gotit = TRUE; 2947 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2948 "Possibly old version of sisfb detected. Please update.\n"); 2949 } else { 2950 free(mysisfbinfo); 2951 mysisfbinfo = NULL; 2952 } 2953 } 2954 } 2955 2956 if(gotit) { 2957 2958 if(mysisfbinfo->sisfb_id == SISFB_ID) { 2959 2960 sisfbversion = (mysisfbinfo->sisfb_version << 16) | 2961 (mysisfbinfo->sisfb_revision << 8) | 2962 (mysisfbinfo->sisfb_patchlevel); 2963 2964 if(sisfbversion >= SISFB_VERSION(1, 5, 8)) { 2965 /* Added PCI bus/slot/func into in sisfb Version 1.5.08. 2966 * Check this to make sure we run on the same card as sisfb 2967 */ 2968 if((mysisfbinfo->sisfb_pcibus == pSiS->PciBus) && 2969 (mysisfbinfo->sisfb_pcislot == pSiS->PciDevice) && 2970 (mysisfbinfo->sisfb_pcifunc == pSiS->PciFunc)) { 2971 pSiS->sisfbfound = TRUE; 2972 } 2973 } else pSiS->sisfbfound = TRUE; 2974 2975 if(pSiS->sisfbfound) { 2976 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2977 "%s: SiS kernel fb driver (sisfb) %d.%d.%d detected (PCI:%02d:%02d.%d)\n", 2978 &name[5], 2979 mysisfbinfo->sisfb_version, 2980 mysisfbinfo->sisfb_revision, 2981 mysisfbinfo->sisfb_patchlevel, 2982 pSiS->PciBus, 2983 pSiS->PciDevice, 2984 pSiS->PciFunc); 2985 2986 /* Added version/rev/pl in sisfb 1.4.0 */ 2987 if(mysisfbinfo->sisfb_version == 0) { 2988 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2989 "Old version of sisfb found. Please update.\n"); 2990 } 2991 /* Basically, we can't trust the pdc register if sisfb is loaded */ 2992 pSiS->donttrustpdc = TRUE; 2993 pSiS->sisfbHeapStart = mysisfbinfo->heapstart; 2994 2995 if(sisfbversion >= SISFB_VERSION(1, 7, 20)) { 2996 pSiS->sisfbHeapSize = mysisfbinfo->sisfb_heapsize; 2997 pSiS->sisfbVideoOffset = mysisfbinfo->sisfb_videooffset; 2998 pSiS->sisfbHaveNewHeapDef = TRUE; 2999 pSiS->sisfbFSTN = mysisfbinfo->sisfb_curfstn; 3000 pSiS->sisfbDSTN = mysisfbinfo->sisfb_curdstn; 3001 pSiS->sisfbxSTN = TRUE; 3002 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3003 "sisfb: memory heap at %dKB, size %dKB, viewport at %dKB\n", 3004 (int)pSiS->sisfbHeapStart, (int)pSiS->sisfbHeapSize, 3005 (int)pSiS->sisfbVideoOffset/1024); 3006 } else { 3007 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3008 "sisfb: memory heap at %dKB\n", (int)pSiS->sisfbHeapStart); 3009 } 3010 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3011 "sisfb: using video mode 0x%02x\n", mysisfbinfo->fbvidmode); 3012 pSiS->OldMode = mysisfbinfo->fbvidmode; 3013 if(sisfbversion >= SISFB_VERSION(1, 5, 6)) { 3014 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3015 "sisfb: using %s, reserved %dK\n", 3016 (mysisfbinfo->sisfb_caps & 0x40) ? "SiS300 series Turboqueue" : 3017 (mysisfbinfo->sisfb_caps & 0x20) ? "SiS315/330/340 series AGP command queue" : 3018 (mysisfbinfo->sisfb_caps & 0x10) ? "SiS315/330/340 series VRAM command queue" : 3019 (mysisfbinfo->sisfb_caps & 0x08) ? "SiS315/330/340 series MMIO mode" : 3020 "no command queue", 3021 (int)mysisfbinfo->sisfb_tqlen); 3022 } 3023 if(sisfbversion >= SISFB_VERSION(1, 5, 10)) { 3024 /* We can trust the pdc value if sisfb is of recent version */ 3025 if(pSiS->VGAEngine == SIS_300_VGA) pSiS->donttrustpdc = FALSE; 3026 } 3027 if(sisfbversion >= SISFB_VERSION(1, 5, 11)) { 3028 if(pSiS->VGAEngine == SIS_300_VGA) { 3029 /* As of 1.5.11, sisfb saved the register for us (300 series) */ 3030 pSiS->sisfbpdc = mysisfbinfo->sisfb_lcdpdc; 3031 if(!pSiS->sisfbpdc) pSiS->sisfbpdc = 0xff; 3032 } 3033 } 3034 if(sisfbversion >= SISFB_VERSION(1, 5, 14)) { 3035 if(pSiS->VGAEngine == SIS_315_VGA) { 3036 pSiS->sisfblcda = mysisfbinfo->sisfb_lcda; 3037 } 3038 } 3039 if(sisfbversion >= SISFB_VERSION(1, 6, 13)) { 3040 pSiS->sisfbscalelcd = mysisfbinfo->sisfb_scalelcd; 3041 pSiS->sisfbspecialtiming = mysisfbinfo->sisfb_specialtiming; 3042 } 3043 if(sisfbversion >= SISFB_VERSION(1, 6, 16)) { 3044 if(pSiS->VGAEngine == SIS_315_VGA) { 3045 pSiS->donttrustpdc = FALSE; 3046 pSiS->sisfbpdc = mysisfbinfo->sisfb_lcdpdc; 3047 if(sisfbversion >= SISFB_VERSION(1, 6, 24)) { 3048 pSiS->sisfb_haveemi = mysisfbinfo->sisfb_haveemi ? TRUE : FALSE; 3049 pSiS->sisfb_haveemilcd = TRUE; /* will match most cases */ 3050 pSiS->sisfb_emi30 = mysisfbinfo->sisfb_emi30; 3051 pSiS->sisfb_emi31 = mysisfbinfo->sisfb_emi31; 3052 pSiS->sisfb_emi32 = mysisfbinfo->sisfb_emi32; 3053 pSiS->sisfb_emi33 = mysisfbinfo->sisfb_emi33; 3054 } 3055 if(sisfbversion >= SISFB_VERSION(1, 6, 25)) { 3056 pSiS->sisfb_haveemilcd = mysisfbinfo->sisfb_haveemilcd ? TRUE : FALSE; 3057 } 3058 if(sisfbversion >= SISFB_VERSION(1, 6, 31)) { 3059 pSiS->sisfbpdca = mysisfbinfo->sisfb_lcdpdca; 3060 } else { 3061 if(pSiS->sisfbpdc) { 3062 pSiS->sisfbpdca = (pSiS->sisfbpdc & 0xf0) >> 3; 3063 pSiS->sisfbpdc = (pSiS->sisfbpdc & 0x0f) << 1; 3064 } else { 3065 pSiS->sisfbpdca = pSiS->sisfbpdc = 0xff; 3066 } 3067 } 3068 } 3069 } 3070 if(sisfbversion >= SISFB_VERSION(1, 7, 0)) { 3071 pSiS->sisfb_havelock = TRUE; 3072 if(sisfbversion >= SISFB_VERSION(1, 7, 1)) { 3073 pSiS->sisfb_tvxpos = mysisfbinfo->sisfb_tvxpos; 3074 pSiS->sisfb_tvypos = mysisfbinfo->sisfb_tvypos; 3075 pSiS->sisfb_tvposvalid = TRUE; 3076 } 3077 } 3078 if(sisfbversion >= SISFB_VERSION(1, 8, 7)) { 3079 pSiS->sisfbcanpost = (mysisfbinfo->sisfb_can_post) ? TRUE : FALSE; 3080 pSiS->sisfbcardposted = (mysisfbinfo->sisfb_card_posted) ? TRUE : FALSE; 3081 pSiS->sisfbprimary = (mysisfbinfo->sisfb_was_boot_device) ? TRUE : FALSE; 3082 /* Validity check */ 3083 if(!pSiS->sisfbcardposted) { 3084 pSiS->sisfbprimary = FALSE; 3085 } 3086 } 3087 } 3088 } 3089 free(mysisfbinfo); 3090 mysisfbinfo = NULL; 3091 } 3092 close (fd); 3093 } 3094 i++; 3095 } while((i <= 15) && (!pSiS->sisfbfound)); 3096 3097 if(pSiS->sisfbfound) { 3098 strncpy(pSiS->sisfbdevname, name, 15); 3099 } else { 3100 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "sisfb not found\n"); 3101 } 3102 } 3103 3104 if(!pSiS->sisfbfound) { 3105 pSiS->sisfbcardposted = FALSE; 3106 } 3107} 3108 3109static void 3110SiSPseudo(ScrnInfoPtr pScrn) 3111{ 3112} 3113 3114/* PreInit() 3115 * 3116 * Mandatory 3117 */ 3118static Bool 3119SISPreInit(ScrnInfoPtr pScrn, int flags) 3120{ 3121 SISPtr pSiS; 3122#ifdef SISDUALHEAD 3123 SISEntPtr pSiSEnt = NULL; 3124#endif 3125 MessageType from; 3126 UChar usScratchCR17, usScratchCR32, usScratchCR63; 3127 UChar usScratchSR1F, srlockReg, crlockReg; 3128 unsigned int i; 3129 int pix24flags, temp; 3130 ClockRangePtr clockRanges; 3131 xf86MonPtr pMonitor = NULL; 3132 Bool didddc2, fromDDC, crt1freqoverruled = FALSE; 3133 UChar CR5F, tempreg; 3134#if defined(SISMERGED) || defined(SISDUALHEAD) 3135 DisplayModePtr first, p, n; 3136#endif 3137#ifdef SISMERGED 3138 Bool crt2freqoverruled = FALSE; 3139#endif 3140 3141 static const char *ddcsstr = "CRT%d DDC monitor info: *******************************************\n"; 3142 static const char *ddcestr = "End of CRT%d DDC monitor info *************************************\n"; 3143 static const char *subshstr = "Substituting missing CRT%d monitor HSync range by DDC data\n"; 3144 static const char *subsvstr = "Substituting missing CRT%d monitor VRefresh range by DDC data\n"; 3145 static const char *saneh = "Correcting %s CRT%d monitor HSync range\n"; 3146 static const char *sanev = "Correcting %s CRT%d monitor VRefresh range\n"; 3147#ifdef SISMERGED 3148 static const char *mergednocrt1 = "CRT1 not detected or forced off. %s.\n"; 3149 static const char *mergednocrt2 = "No CRT2 output selected or no video bridge detected. %s.\n"; 3150 static const char *mergeddisstr = "MergedFB mode disabled"; 3151 static const char *modesforstr = "Modes for CRT%d: **************************************************\n"; 3152 static const char *crtsetupstr = "*************************** CRT%d setup ***************************\n"; 3153 static const char *crt2monname = "CRT2"; 3154#endif 3155#if defined(SISDUALHEAD) || defined(SISMERGED) 3156 static const char *notsuitablestr = "Not using mode \"%s\" (not suitable for %s mode)\n"; 3157#endif 3158 3159 if(flags & PROBE_DETECT) { 3160 3161 vbeInfoPtr pVbe; 3162 3163 if(xf86LoadSubModule(pScrn, "vbe")) { 3164 int index = xf86GetEntityInfo(pScrn->entityList[0])->index; 3165#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 3166 if((pVbe = VBEInit(NULL, index))) 3167#else 3168 if((pVbe = VBEExtendedInit(NULL, index, 0))) 3169#endif 3170 { 3171 ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 3172 vbeFree(pVbe); 3173 } 3174 } 3175 return TRUE; 3176 } 3177 3178 /* 3179 * Note: This function is only called once at server startup, and 3180 * not at the start of each server generation. This means that 3181 * only things that are persistent across server generations can 3182 * be initialised here. xf86Screens[] is the array of all screens, 3183 * (pScrn is a pointer to one of these). Privates allocated using 3184 * xf86AllocateScrnInfoPrivateIndex() are too, and should be used 3185 * for data that must persist across server generations. 3186 * 3187 * Per-generation data should be allocated with 3188 * AllocateScreenPrivateIndex() from the ScreenInit() function. 3189 */ 3190 3191 /* Check the number of entities, and fail if it isn't one. */ 3192 if(pScrn->numEntities != 1) { 3193 SISErrorLog(pScrn, "Number of entities is not 1\n"); 3194 return FALSE; 3195 } 3196 3197 /* Due to the liberal license terms this is needed for 3198 * keeping the copyright notice readable and intact in 3199 * binary distributions. Removing this is a copyright 3200 * infringement. Please read the license terms above. 3201 */ 3202 3203 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3204 "SiS driver (%d/%02d/%02d-%d, compiled for " SISMYSERVERNAME " %d.%d.%d.%d)\n", 3205 SISDRIVERVERSIONYEAR + 2000, SISDRIVERVERSIONMONTH, 3206 SISDRIVERVERSIONDAY, SISDRIVERREVISION, 3207#ifdef XORG_VERSION_CURRENT 3208 XORG_VERSION_MAJOR, XORG_VERSION_MINOR, 3209 XORG_VERSION_PATCH, XORG_VERSION_SNAP 3210#else 3211 XF86_VERSION_MAJOR, XF86_VERSION_MINOR, 3212 XF86_VERSION_PATCH, XF86_VERSION_SNAP 3213#endif 3214 ); 3215 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3216 "Copyright (C) 2001-2005 Thomas Winischhofer <thomas@winischhofer.net> and others\n"); 3217 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3218 "*** See http://www.winischhofer.eu/linuxsisvga.shtml\n"); 3219 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3220 "*** for documentation and updates.\n"); 3221 3222#ifdef XORG_VERSION_CURRENT 3223#if 0 /* no prototype yet */ 3224 if(xorgGetVersion() != XORG_VERSION_CURRENT) { 3225 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3226 "This driver binary is not compiled for this version of " SISMYSERVERNAME "\n"); 3227 } 3228#endif 3229#else 3230#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0) 3231 if(xf86GetVersion() != XF86_VERSION_CURRENT) { 3232 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3233 "This driver binary is not compiled for this version of " SISMYSERVERNAME "\n"); 3234 } 3235#endif 3236#endif 3237 3238 /* Allocate the SISRec driverPrivate */ 3239 if(!SISGetRec(pScrn)) { 3240 SISErrorLog(pScrn, "Could not allocate memory for pSiS private\n"); 3241 return FALSE; 3242 } 3243 pSiS = SISPTR(pScrn); 3244 pSiS->pScrn = pScrn; 3245 3246 pSiS->pInt = NULL; 3247 3248 /* Save PCI Domain Base */ 3249#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) || GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 12 3250 pSiS->IODBase = 0; 3251#else 3252 pSiS->IODBase = pScrn->domainIOBase; 3253#endif 3254 3255 /* Get the entity, and make sure it is PCI. */ 3256 pSiS->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 3257 if(pSiS->pEnt->location.type != BUS_PCI) { 3258 SISErrorLog(pScrn, "Entity's bus type is not PCI\n"); 3259 goto my_error_0; 3260 } 3261 3262#ifdef SISDUALHEAD 3263 /* Allocate an entity private if necessary */ 3264 if(xf86IsEntityShared(pScrn->entityList[0])) { 3265 pSiSEnt = xf86GetEntityPrivate(pScrn->entityList[0], SISEntityIndex)->ptr; 3266 pSiS->entityPrivate = pSiSEnt; 3267 3268 /* If something went wrong, quit here */ 3269 if((pSiSEnt->DisableDual) || (pSiSEnt->ErrorAfterFirst)) { 3270 SISErrorLog(pScrn, "First head encountered fatal error, aborting...\n"); 3271 goto my_error_0; 3272 } 3273 } 3274#endif 3275 3276 /* Find the PCI info for this screen */ 3277 pSiS->PciInfo = xf86GetPciInfoForEntity(pSiS->pEnt->index); 3278 pSiS->PciBus = PCI_CFG_BUS(pSiS->PciInfo); /*SIS_PCI_BUS(pSiS->PciInfo);*/ 3279 pSiS->PciDevice = PCI_CFG_DEV(pSiS->PciInfo); /*SIS_PCI_DEVICE(pSiS->PciInfo);*/ 3280 pSiS->PciFunc = PCI_CFG_FUNC(pSiS->PciInfo); /*SIS_PCI_FUNC(pSiS->PciInfo);*/ 3281 3282#ifndef XSERVER_LIBPCIACCESS 3283 pSiS->PciTag = pciTag(PCI_DEV_BUS(pSiS->PciInfo), 3284 PCI_DEV_DEV(pSiS->PciInfo), 3285 PCI_DEV_FUNC(pSiS->PciInfo)); 3286#endif 3287 3288#ifdef SIS_NEED_MAP_IOP 3289 /********************************************/ 3290 /* THIS IS BROKEN AND WON'T WORK */ 3291 /* Reasons: */ 3292 /* 1) MIPS and ARM have no i/o ports but */ 3293 /* use memory mapped i/o only. The inX/outX */ 3294 /* macros in compiler.h are smart enough to */ 3295 /* add "IOPortBase" to the port number, but */ 3296 /* "IOPortBase" is never initialized. */ 3297 /* 2) IOPortBase is declared in compiler.h */ 3298 /* itself. So until somebody fixes all */ 3299 /* modules that #include compiler.h to set */ 3300 /* IOPortBase, vga support for MIPS and ARM */ 3301 /* is unusable. */ 3302 /* (In this driver this is solvable because */ 3303 /* we have our own vgaHW routines. However, */ 3304 /* we use /dev/port for now instead.) */ 3305 /********************************************/ 3306 pSiS->IOPAddress = pSiS->IODBase + pSiS->PciInfo->ioBase[2]; 3307 if(!SISMapIOPMem(pScrn)) { 3308 SISErrorLog(pScrn, "Could not map I/O port area at 0x%x\n", pSiS->IOPAddress); 3309 goto my_error_0; 3310 } else { 3311 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I/O port area mapped to %p, size 128\n", pSiS->IOPBase); 3312#if defined(__mips__) || defined(__arm32__) 3313 /* inX/outX macros on these use IOPortBase as offset */ 3314 /* This is entirely skrewed. */ 3315 IOPortBase = (unsigned int)pSiS->IOPBase; 3316#endif 3317 } 3318#endif 3319 3320 /* Set up i/o port access (for non-x86) */ 3321#ifdef SISUSEDEVPORT 3322 if((sisdevport = open("/dev/port", O_RDWR, 0)) == -1) { 3323 SISErrorLog(pScrn, "Failed to open /dev/port for read/write\n"); 3324 goto my_error_0; 3325 } 3326 pSiS->sisdevportopen = TRUE; 3327#endif 3328 3329 /* 3330 * Set the Chipset and ChipRev, allowing config file entries to 3331 * override. DANGEROUS! 3332 */ 3333 { 3334 SymTabRec *myChipsets = SISChipsets; 3335 3336 if(PCI_DEV_VENDOR_ID(pSiS->PciInfo) == PCI_VENDOR_XGI) { 3337 myChipsets = XGIChipsets; 3338 } 3339 3340 if(pSiS->pEnt->device->chipset && *pSiS->pEnt->device->chipset) { 3341 3342 pScrn->chipset = pSiS->pEnt->device->chipset; 3343 pSiS->Chipset = xf86StringToToken(myChipsets, pScrn->chipset); 3344 3345 } else if(pSiS->pEnt->device->chipID >= 0) { 3346 3347 pSiS->Chipset = pSiS->pEnt->device->chipID; 3348 pScrn->chipset = (char *)xf86TokenToString(myChipsets, pSiS->Chipset); 3349 3350 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", 3351 pSiS->Chipset); 3352 } else { 3353 3354 pSiS->Chipset = PCI_DEV_DEVICE_ID(pSiS->PciInfo); 3355 pScrn->chipset = (char *)xf86TokenToString(myChipsets, pSiS->Chipset); 3356 3357 } 3358 } 3359 3360 if(pSiS->pEnt->device->chipRev >= 0) { 3361 3362 pSiS->ChipRev = pSiS->pEnt->device->chipRev; 3363 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 3364 pSiS->ChipRev); 3365 } else { 3366 3367 pSiS->ChipRev = PCI_DEV_REVISION(pSiS->PciInfo); 3368 3369 } 3370 3371 /* 3372 * This shouldn't happen because such problems should be caught in 3373 * SISProbe(), but check it just in case the user has overridden them. 3374 */ 3375 if(pScrn->chipset == NULL) { 3376 SISErrorLog(pScrn, "ChipID 0x%04X is not recognised\n", pSiS->Chipset); 3377 goto my_error_0; 3378 } 3379 if(pSiS->Chipset < 0) { 3380 SISErrorLog(pScrn, "Chipset \"%s\" is not recognised\n", pScrn->chipset); 3381 goto my_error_0; 3382 } 3383 3384 pSiS->SiS6326Flags = 0; 3385 3386 /* Determine VGA engine generation */ 3387 switch(pSiS->Chipset) { 3388 case PCI_CHIP_SIS300: 3389 case PCI_CHIP_SIS540: 3390 case PCI_CHIP_SIS630: /* 630 + 730 */ 3391 pSiS->VGAEngine = SIS_300_VGA; 3392 break; 3393 case PCI_CHIP_SIS315H: 3394 case PCI_CHIP_SIS315: 3395 case PCI_CHIP_SIS315PRO: 3396 case PCI_CHIP_SIS550: 3397 case PCI_CHIP_SIS650: /* 650 + 740 */ 3398 case PCI_CHIP_SIS330: 3399 case PCI_CHIP_SIS660: /* 660, 661, 741, 760, 761, 670(?), 770 */ 3400 case PCI_CHIP_SIS340: 3401 case PCI_CHIP_XGIXG20: 3402 case PCI_CHIP_XGIXG40: 3403 pSiS->VGAEngine = SIS_315_VGA; 3404 break; 3405 case PCI_CHIP_SIS530: 3406 pSiS->VGAEngine = SIS_530_VGA; 3407 break; 3408 case PCI_CHIP_SIS6326: 3409 /* Determine SiS6326 revision. According to SiS the differences are: 3410 * Chip name Chip type TV-Out MPEG II decoder 3411 * 6326 AGP Rev. G0/H0 no no 3412 * 6326 DVD Rev. D2 yes yes 3413 * 6326 Rev. Cx yes yes 3414 */ 3415 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3416 "Chipset is SiS6326 %s (revision 0x%02x)\n", 3417 (pSiS->ChipRev == 0xaf) ? "(Ax)" : 3418 ((pSiS->ChipRev == 0x0a) ? "AGP (G0)" : 3419 ((pSiS->ChipRev == 0x0b) ? "AGP (H0)" : 3420 (((pSiS->ChipRev & 0xf0) == 0xd0) ? "DVD (Dx/H0)" : 3421 (((pSiS->ChipRev & 0xf0) == 0x90) ? "(9x)" : 3422 (((pSiS->ChipRev & 0xf0) == 0xc0) ? "(Cx)" : 3423 "(unknown)"))))), 3424 pSiS->ChipRev); 3425 if((pSiS->ChipRev != 0x0a) && (pSiS->ChipRev != 0x0b)) { 3426 pSiS->SiS6326Flags |= SIS6326_HASTV; 3427 } 3428 /* fall through */ 3429 default: 3430 pSiS->VGAEngine = SIS_OLD_VGA; 3431 } 3432 3433 /* We don't know about the current mode yet */ 3434 pSiS->OldMode = 0; 3435 3436 /* Determine whether this is the primary or a secondary 3437 * display adapter. And right here the problem starts: 3438 * On machines with integrated SiS chipsets, the system BIOS 3439 * usually sets VGA_EN on all PCI-to-PCI bridges in the system 3440 * (of which there usually are two: PCI and AGP). This and 3441 * the fact that any PCI card POSTed by sisfb naturally has 3442 * its PCI resources enabled, leads to X assuming that 3443 * there are more than one "primary" cards in the system. 3444 * In this case, X treats ALL cards as "secondary" - 3445 * which by no means is desireable. If sisfb is running, 3446 * we can determine which card really is "primary" (in 3447 * terms of if it's the one that occupies the A0000 area 3448 * etc.) in a better way (Linux 2.6.12 or later). See below. 3449 */ 3450 if(!(pSiS->Primary = xf86IsPrimaryPci(pSiS->PciInfo))) { 3451 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3452 SISMYSERVERNAME " assumes this adapter to be secondary\n"); 3453 } 3454 3455 /* Now check if sisfb is running, and if so, retrieve 3456 * all possible info from it. This also resets all 3457 * sisfb_* entries in pSiS regardless of the chipset. 3458 */ 3459 SiS_CheckKernelFB(pScrn); 3460 3461 /* Now for that primary/secondary mess: Linux kernel 3462 * 2.6.12 and later knows what card is primary, and so 3463 * does any recent version of sisfb. XFree86/X.org takes 3464 * all adapters as "secondary" if more than one card's 3465 * memory and i/o resources are enabled, and more than 3466 * one PCI bridge in the system has VGA_EN set at server 3467 * start. So, let's start thinking: What is this 3468 * primary/secondary classification needed for anyway? 3469 * (This list might be incomplete for the entire server 3470 * infrastructure, but it's complete as regards the driver's 3471 * purposes of primary/secondary classification.) 3472 * 1) VGA/console font restoring: Here it's irrelevant 3473 * whether more than one card's resources are enabled 3474 * at server start or not. Relevant is whether the card 3475 * occupies the A0000 area at this time. Assuming (?) 3476 * that this does not change during machine up-time, 3477 * it suffices to know which device was the boot video 3478 * device (as determined by Linux 2.6.12 and later). 3479 * Also, this is only relevant if the card is in text 3480 * mode; if it's in graphics mode, fonts aren't saved 3481 * or restored anyway. 3482 * sisfb tells us if that card is considered the boot 3483 * video device. The hardware registers tell us if 3484 * the card's A0000 address decoding is enabled, and if 3485 * the card currently is in text mode. These three bits 3486 * of information are enough to decide on whether or not 3487 * to save/restore fonts. 3488 * 2) POSTing. Same here. Relevant is only whether or not 3489 * the card has been POSTed once before. POSTing cards 3490 * on every server start is pretty ugly, especially 3491 * if a framebuffer driver is already handling it. 3492 * SiS/XGI cards POSTed by sisfb can coexist well with other 3493 * active adapters. So we trust sisfb's information more 3494 * than X's (especially as we only use this information for 3495 * console font restoring and eventual POSTing.) 3496 * What we still need is a way to find out about all this if 3497 * sisfb is not running.... 3498 */ 3499 if(!pSiS->Primary && pSiS->sisfbprimary) { 3500 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3501 "sisfb reports this adapter to be primary. Seems more reliable.\n"); 3502 pSiS->Primary = TRUE; 3503 } 3504 3505 /* If the card is "secondary" and has not been 3506 * POSTed by sisfb, POST it now through int10. 3507 * For cards POSTed by sisfb, we definitely don't 3508 * want that as it messes up our set up (eg. the 3509 * disabled A0000 area). 3510 * The int10 module decides on its own if the 3511 * card is primary or secondary. Since it uses 3512 * the generic technique described above, and since 3513 * for "secondary" cards it needs a real PCI BIOS 3514 * ROM, and since integrated chips don't have such 3515 * a PCI BIOS ROM, int10 will naturally fail to 3516 * find/read the BIOS on such machines. Great. 3517 * Using the integrated graphics as "secondary" 3518 * (which it will be as soon as X finds more than 3519 * one card's mem and i/o resources enabled, and more 3520 * than one PCI bridge's VGA_EN bit set during server 3521 * start) will therefore prevent us from restoring 3522 * the mode using the VBE. That means real fun if 3523 * the integrated chip is set up to use the video 3524 * bridge output for text mode (which is something 3525 * the driver doesn't really support since it's done 3526 * pretty much differently on every machine.) 3527 */ 3528#if !defined(__alpha__) 3529 if(!pSiS->Primary) { 3530 if(!pSiS->sisfbcardposted) { 3531 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3532 "Initializing adapter through int10\n"); 3533 if(xf86LoadSubModule(pScrn, "int10")) { 3534 pSiS->pInt = xf86InitInt10(pSiS->pEnt->index); 3535 } else { 3536 SISErrorLog(pScrn, "Failed to load int10 module\n"); 3537 } 3538 } else { 3539 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3540 "Adapter already initialized by sisfb\n"); 3541 } 3542 } 3543#endif 3544 3545 /* Get the address of our relocated IO registers. 3546 * These are enabled by the hardware during cold boot, and 3547 * by the BIOS. So we can pretty much rely on that these 3548 * are enabled. 3549 */ 3550 pSiS->RelIO = (SISIOADDRESS)(PCI_REGION_BASE(pSiS->PciInfo, 2, REGION_IO) + pSiS->IODBase); 3551 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Relocated I/O registers at 0x%lX\n", 3552 (ULong)pSiS->RelIO); 3553 3554 /* Unlock extended registers */ 3555 sisSaveUnlockExtRegisterLock(pSiS, &srlockReg, &crlockReg); 3556 3557 /* Is a0000 memory address decoding enabled? */ 3558 pSiS->VGADecodingEnabled = TRUE; 3559 switch(pSiS->VGAEngine) { 3560 case SIS_OLD_VGA: 3561 /* n/a */ 3562 break; 3563 case SIS_530_VGA: 3564 inSISIDXREG(SISSR, 0x3d, tempreg); 3565 if(tempreg & 0x04) pSiS->VGADecodingEnabled = FALSE; 3566 break; 3567 case SIS_300_VGA: 3568 case SIS_315_VGA: 3569 inSISIDXREG(SISSR, 0x20, tempreg); 3570 if(tempreg & 0x04) pSiS->VGADecodingEnabled = FALSE; 3571 break; 3572 } 3573 3574 if(!pSiS->VGADecodingEnabled) { 3575 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3576 "Standard VGA (0xA0000) memory address decoding is disabled\n"); 3577 } 3578 3579#ifdef SIS_PC_PLATFORM 3580 /* Map 64k VGA window for saving/restoring CGA fonts. 3581 * For secondary cards or if A0000 address decoding 3582 * is disabled, this will map the beginning of the 3583 * linear (PCI) video RAM instead. 3584 */ 3585 SiS_MapVGAMem(pScrn); 3586#endif 3587 3588#ifndef XSERVER_LIBPCIACCESS 3589 /* Set operating state */ 3590 3591 /* 1. memory */ 3592 /* [ResUnusedOpr: Resource decoded by hw, but not used] 3593 * [ResDisableOpr: Resource is not decoded by hw] 3594 * So, if a0000 memory decoding is disabled, one could 3595 * argue that we may say so, too. Hm. Quite likely that 3596 * the VBE (via int10) will eventually enable it. So we 3597 * cowardly say unused instead. 3598 */ 3599 xf86SetOperatingState(resVgaMem, pSiS->pEnt->index, ResUnusedOpr); 3600 3601 /* 2. i/o */ 3602 /* Although we only use the relocated i/o ports, the hardware 3603 * also decodes the standard VGA port range. This could in 3604 * theory be disabled, but I don't dare to do this; in case of 3605 * a server crash, the card would be entirely dead. Also, this 3606 * would prevent int10 and the VBE from working at all. Generic 3607 * access control through the PCI configuration registers does 3608 * nicely anyway. 3609 */ 3610 xf86SetOperatingState(resVgaIo, pSiS->pEnt->index, ResUnusedOpr); 3611 3612 /* Operations for which memory access is required */ 3613 pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; 3614 3615 /* Operations for which I/O access is required */ 3616 pScrn->racIoFlags = RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; 3617 3618#endif 3619 3620 /* Load ramdac module */ 3621 if(!xf86LoadSubModule(pScrn, "ramdac")) { 3622 SISErrorLog(pScrn, "Could not load ramdac module\n"); 3623 goto my_error_1; 3624 } 3625 3626 /* Set pScrn->monitor */ 3627 pScrn->monitor = pScrn->confScreen->monitor; 3628 3629 /* Reset some entries */ 3630 pSiS->SiSFastVidCopy = SiSVidCopyGetDefault(); 3631 pSiS->SiSFastMemCopy = SiSVidCopyGetDefault(); 3632 pSiS->SiSFastVidCopyFrom = SiSVidCopyGetDefault(); 3633 pSiS->SiSFastMemCopyFrom = SiSVidCopyGetDefault(); 3634 pSiS->SiSFastVidCopyDone = FALSE; 3635#ifdef SIS_USE_XAA 3636 pSiS->RenderCallback = NULL; 3637#endif 3638#ifdef SIS_USE_EXA 3639 pSiS->ExaRenderCallback = NULL; 3640#endif 3641 pSiS->InitAccel = SiSPseudo; 3642 pSiS->SyncAccel = SiSPseudo; 3643 pSiS->FillRect = NULL; 3644 pSiS->BlitRect = NULL; 3645 3646 /* Always do a ValidMode() inside Switchmode() */ 3647 pSiS->skipswitchcheck = FALSE; 3648 3649 /* Determine chipset and its capabilities in detail */ 3650 pSiS->ChipFlags = 0; 3651 pSiS->SiS_SD_Flags = pSiS->SiS_SD2_Flags = 0; 3652 pSiS->SiS_SD3_Flags = pSiS->SiS_SD4_Flags = 0; 3653 pSiS->HWCursorMBufNum = pSiS->HWCursorCBufNum = 0; 3654 pSiS->NeedFlush = FALSE; 3655 pSiS->NewCRLayout = FALSE; 3656 pSiS->mmioSize = 64; 3657 3658 switch(pSiS->Chipset) { 3659 case PCI_CHIP_SIS530: 3660 pSiS->ChipType = SIS_530; 3661 break; 3662 case PCI_CHIP_SIS300: 3663 pSiS->ChipType = SIS_300; 3664 pSiS->SiS_SD_Flags |= SiS_SD_IS300SERIES; 3665 break; 3666 case PCI_CHIP_SIS540: 3667 pSiS->ChipType = SIS_540; 3668 pSiS->SiS_SD_Flags |= SiS_SD_IS300SERIES; 3669 break; 3670 case PCI_CHIP_SIS630: /* 630 + 730 */ 3671 pSiS->ChipType = SIS_630; 3672 if(sis_pci_read_host_bridge_u32(0x00) == 0x07301039) { 3673 pSiS->ChipType = SIS_730; 3674 } 3675 pSiS->SiS_SD_Flags |= SiS_SD_IS300SERIES; 3676 break; 3677 case PCI_CHIP_SIS315H: 3678 pSiS->ChipType = SIS_315H; 3679 pSiS->ChipFlags |= (SiSCF_315Core | SiSCF_MMIOPalette); 3680 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3681 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3682 pSiS->myCR63 = 0x63; 3683 break; 3684 case PCI_CHIP_SIS315: 3685 /* Override for simplicity */ 3686 pSiS->Chipset = PCI_CHIP_SIS315H; 3687 pSiS->ChipType = SIS_315; 3688 pSiS->ChipFlags |= (SiSCF_315Core | SiSCF_MMIOPalette); 3689 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3690 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3691 pSiS->myCR63 = 0x63; 3692 break; 3693 case PCI_CHIP_SIS315PRO: 3694 /* Override for simplicity */ 3695 pSiS->Chipset = PCI_CHIP_SIS315H; 3696 pSiS->ChipType = SIS_315PRO; 3697 pSiS->ChipFlags |= (SiSCF_315Core | SiSCF_MMIOPalette); 3698 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3699 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3700 pSiS->myCR63 = 0x63; 3701 break; 3702 case PCI_CHIP_SIS550: 3703 pSiS->ChipType = SIS_550; 3704 pSiS->ChipFlags |= (SiSCF_Integrated | SiSCF_MMIOPalette); 3705 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3706 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3707 pSiS->myCR63 = 0x63; 3708 break; 3709 case PCI_CHIP_SIS650: /* 650 + 740 */ 3710 pSiS->ChipType = SIS_650; 3711 if(sis_pci_read_host_bridge_u32(0x00) == 0x07401039) { 3712 pSiS->ChipType = SIS_740; 3713 } 3714 pSiS->ChipFlags |= (SiSCF_Integrated | SiSCF_Real256ECore | SiSCF_MMIOPalette); 3715 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3716 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3717 pSiS->myCR63 = 0x63; 3718 break; 3719 case PCI_CHIP_SIS330: 3720 pSiS->ChipType = SIS_330; 3721 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette); 3722 pSiS->SiS_SD_Flags |= SiS_SD_IS330SERIES; 3723 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3724 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; /* FIXME ? */ 3725 pSiS->myCR63 = 0x53; /* sic! */ 3726 break; 3727 case PCI_CHIP_SIS660: /* 660, 661, 741, 760, 761, 670(?) */ 3728 { 3729 ULong hpciid = sis_pci_read_host_bridge_u32(0x00); 3730 switch(hpciid) { 3731 case 0x06601039: 3732 pSiS->ChipType = SIS_660; 3733 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3734 pSiS->NeedFlush = TRUE; 3735 break; 3736 case 0x07601039: 3737 pSiS->ChipType = SIS_760; 3738 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3739 pSiS->NeedFlush = TRUE; 3740 break; 3741 case 0x07611039: 3742 pSiS->ChipType = SIS_761; 3743 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3744 pSiS->NeedFlush = TRUE; 3745 break; 3746 case 0x07701039: 3747 pSiS->ChipType = SIS_770; 3748 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3749 pSiS->NeedFlush = TRUE; 3750 break; 3751 case 0x07411039: 3752 pSiS->ChipType = SIS_741; 3753 pSiS->ChipFlags |= SiSCF_Real256ECore; 3754 break; 3755 case 0x06611039: 3756 default: 3757 pSiS->ChipType = SIS_661; 3758 pSiS->ChipFlags |= SiSCF_Real256ECore; 3759 break; 3760 case 0x06701039: 3761 pSiS->ChipType = SIS_670; 3762 pSiS->ChipFlags |= SiSCF_Real256ECore; 3763 } 3764 /* Detection could also be done by CR5C & 0xf8: 3765 * 0x10 = 661 (CR5F & 0xc0: 0x00 both A0 and A1) 3766 * 0x80 = 760 (CR5F & 0xc0: 0x00 A0, 0x40 A1) 3767 * 0x90 = 741 (CR5F & 0xc0: 0x00 A0,A1 0x40 A2) 3768 * other: 660 (CR5F & 0xc0: 0x00 A0 0x40 A1) (DOA?) 3769 */ 3770 pSiS->ChipFlags |= (SiSCF_Integrated | SiSCF_MMIOPalette); 3771 pSiS->SiS_SD_Flags |= SiS_SD_IS330SERIES; 3772 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3773 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; 3774 pSiS->myCR63 = 0x53; /* sic! */ 3775 pSiS->NewCRLayout = TRUE; 3776 } 3777 break; 3778 case PCI_CHIP_SIS340: 3779 pSiS->ChipType = SIS_340; 3780 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette); 3781 pSiS->SiS_SD_Flags |= SiS_SD_IS340SERIES; 3782 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3783 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; 3784 pSiS->myCR63 = 0x53; 3785 pSiS->NewCRLayout = TRUE; 3786 break; 3787 case PCI_CHIP_XGIXG20: 3788 pSiS->ChipType = XGI_20; 3789 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette | SiSCF_IsXGI); 3790 pSiS->SiS_SD2_Flags |= (SiS_SD2_NOOVERLAY | SiS_SD2_ISXGI); 3791 pSiS->myCR63 = 0x53; 3792 pSiS->NewCRLayout = TRUE; 3793 break; 3794 case PCI_CHIP_XGIXG40: 3795 pSiS->ChipType = XGI_40; 3796 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette | SiSCF_IsXGI); 3797 pSiS->SiS_SD2_Flags |= (SiS_SD2_SUPPORTXVHUESAT | SiS_SD2_ISXGI); 3798 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; 3799 pSiS->myCR63 = 0x53; 3800 pSiS->NewCRLayout = TRUE; 3801 if(pSiS->ChipRev == 2) pSiS->ChipFlags |= SiSCF_IsXGIV3; 3802 break; 3803 default: 3804 pSiS->ChipType = SIS_OLD; 3805 break; 3806 } 3807 3808 /* 3809 * Now back to real business: Figure out the depth, bpp, etc. 3810 * Set SupportConvert... flags since we use the fb layer which 3811 * supports this conversion. (24to32 seems not implemented though) 3812 * Additionally, determine the size of the HWCursor memory area. 3813 */ 3814 switch(pSiS->VGAEngine) { 3815 case SIS_300_VGA: 3816 pSiS->CursorSize = 4096; 3817 pix24flags = Support32bppFb; 3818 break; 3819 case SIS_315_VGA: 3820 pSiS->CursorSize = 16384; 3821 pix24flags = Support32bppFb; 3822 break; 3823 case SIS_530_VGA: 3824 pSiS->CursorSize = 2048; 3825 pix24flags = Support32bppFb | 3826 Support24bppFb | 3827 SupportConvert32to24; 3828 break; 3829 default: 3830 pSiS->CursorSize = 2048; 3831 pix24flags = Support24bppFb | 3832 SupportConvert32to24 | 3833 PreferConvert32to24; 3834 break; 3835 } 3836 3837#ifdef SISDUALHEAD 3838 /* In case of Dual Head, we need to determine if we are the "master" head or 3839 * the "slave" head. In order to do that, we set PrimInit to DONE in the 3840 * shared entity at the end of the first initialization. The second 3841 * initialization then knows that some things have already been done. THIS 3842 * ALWAYS ASSUMES THAT THE FIRST DEVICE INITIALIZED IS THE MASTER! 3843 */ 3844 if(xf86IsEntityShared(pScrn->entityList[0])) { 3845 if(pSiSEnt->lastInstance > 0) { 3846 if(!xf86IsPrimInitDone(pScrn->entityList[0])) { 3847 /* First Head (always CRT2) */ 3848 pSiS->SecondHead = FALSE; 3849 pSiSEnt->pScrn_1 = pScrn; 3850 pSiSEnt->CRT1ModeNo = pSiSEnt->CRT2ModeNo = -1; 3851 pSiSEnt->CRT2ModeSet = FALSE; 3852 pSiS->DualHeadMode = TRUE; 3853 pSiSEnt->DisableDual = FALSE; 3854 pSiSEnt->BIOS = NULL; 3855 pSiSEnt->ROM661New = FALSE; 3856 pSiSEnt->HaveXGIBIOS = FALSE; 3857 pSiSEnt->SiS_Pr = NULL; 3858 pSiSEnt->RenderAccelArray = NULL; 3859 pSiSEnt->SiSFastVidCopy = pSiSEnt->SiSFastMemCopy = NULL; 3860 pSiSEnt->SiSFastVidCopyFrom = pSiSEnt->SiSFastMemCopyFrom = NULL; 3861 } else { 3862 /* Second Head (always CRT1) */ 3863 pSiS->SecondHead = TRUE; 3864 pSiSEnt->pScrn_2 = pScrn; 3865 pSiS->DualHeadMode = TRUE; 3866 } 3867 } else { 3868 /* Only one screen in config file - disable dual head mode */ 3869 pSiS->SecondHead = FALSE; 3870 pSiS->DualHeadMode = FALSE; 3871 pSiSEnt->DisableDual = TRUE; 3872 } 3873 } else { 3874 /* Entity is not shared - disable dual head mode */ 3875 pSiS->SecondHead = FALSE; 3876 pSiS->DualHeadMode = FALSE; 3877 } 3878#endif 3879 3880 /* Save the name of our Device section for SiSCtrl usage */ 3881 { 3882 int ttt = 0; 3883 GDevPtr device = xf86GetDevFromEntity(pScrn->entityList[0], 3884 pScrn->entityInstanceList[0]); 3885 if(device && device->identifier) { 3886 if((ttt = strlen(device->identifier)) > 31) ttt = 31; 3887 strncpy(&pSiS->devsectname[0], device->identifier, 31); 3888 } 3889 pSiS->devsectname[ttt] = 0; 3890 } 3891 3892 pSiS->ForceCursorOff = FALSE; 3893 3894 /* Allocate SiS_Private (for mode switching code) and initialize it */ 3895 pSiS->SiS_Pr = NULL; 3896#ifdef SISDUALHEAD 3897 if(pSiSEnt) { 3898 if(pSiSEnt->SiS_Pr) pSiS->SiS_Pr = pSiSEnt->SiS_Pr; 3899 } 3900#endif 3901 if(!pSiS->SiS_Pr) { 3902 if(!(pSiS->SiS_Pr = xnfcalloc(sizeof(struct SiS_Private), 1))) { 3903 SISErrorLog(pScrn, "Could not allocate memory for SiS_Pr structure\n"); 3904 goto my_error_1; 3905 } 3906#ifdef SISDUALHEAD 3907 if(pSiSEnt) pSiSEnt->SiS_Pr = pSiS->SiS_Pr; 3908#endif 3909 memset(pSiS->SiS_Pr, 0, sizeof(struct SiS_Private)); 3910#ifndef XSERVER_LIBPCIACCESS 3911 pSiS->SiS_Pr->PciTag = pSiS->PciTag; 3912#endif 3913 pSiS->SiS_Pr->ChipType = pSiS->ChipType; 3914 pSiS->SiS_Pr->ChipRevision = pSiS->ChipRev; 3915 pSiS->SiS_Pr->SiS_Backup70xx = 0xff; 3916 pSiS->SiS_Pr->SiS_CHOverScan = -1; 3917 pSiS->SiS_Pr->SiS_ChSW = FALSE; 3918 pSiS->SiS_Pr->SiS_CustomT = CUT_NONE; 3919 pSiS->SiS_Pr->SiS_UseWide = -1; 3920 pSiS->SiS_Pr->SiS_UseWideCRT2 = -1; 3921 pSiS->SiS_Pr->SiS_TVBlue = -1; 3922 pSiS->SiS_Pr->PanelSelfDetected = FALSE; 3923 pSiS->SiS_Pr->UsePanelScaler = -1; 3924 pSiS->SiS_Pr->CenterScreen = -1; 3925 pSiS->SiS_Pr->CRT1UsesCustomMode = FALSE; 3926 pSiS->SiS_Pr->PDC = pSiS->SiS_Pr->PDCA = -1; 3927 pSiS->SiS_Pr->LVDSHL = -1; 3928 pSiS->SiS_Pr->HaveEMI = FALSE; 3929 pSiS->SiS_Pr->HaveEMILCD = FALSE; 3930 pSiS->SiS_Pr->OverruleEMI = FALSE; 3931 pSiS->SiS_Pr->SiS_SensibleSR11 = FALSE; 3932 if(pSiS->ChipType >= SIS_661) { 3933 pSiS->SiS_Pr->SiS_SensibleSR11 = TRUE; 3934 } 3935 pSiS->SiS_Pr->SiS_MyCR63 = pSiS->myCR63; 3936 pSiS->SiS_Pr->DDCPortMixup = FALSE; 3937 } 3938 3939 /* Copy IO address to SiS_Pr and init the structure for 3940 * routines inside init.c/init301.c 3941 */ 3942 pSiS->SiS_Pr->IOAddress = (SISIOADDRESS)(pSiS->RelIO + 0x30); 3943 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO + 0x30); 3944 3945 /* The following identifies the old chipsets. This is only 3946 * partly used since the really old chips are not supported, 3947 * but I keep it here for future use. 3948 * 205, 215 and 225 are to be treated the same way, 201 and 202 3949 * are different. 3950 */ 3951 if(pSiS->VGAEngine == SIS_OLD_VGA || pSiS->VGAEngine == SIS_530_VGA) { 3952 switch(pSiS->Chipset) { 3953 case PCI_CHIP_SG86C201: 3954 pSiS->oldChipset = OC_SIS86201; break; 3955 case PCI_CHIP_SG86C202: 3956 pSiS->oldChipset = OC_SIS86202; break; 3957 case PCI_CHIP_SG86C205: 3958 inSISIDXREG(SISSR, 0x10, tempreg); 3959 if(tempreg & 0x80) pSiS->oldChipset = OC_SIS6205B; 3960 else pSiS->oldChipset = (pSiS->ChipRev == 0x11) ? 3961 OC_SIS6205C : OC_SIS6205A; 3962 break; 3963 case PCI_CHIP_SIS82C204: 3964 pSiS->oldChipset = OC_SIS82204; break; 3965 case 0x6225: 3966 pSiS->oldChipset = OC_SIS6225; break; 3967 case PCI_CHIP_SIS5597: 3968 pSiS->oldChipset = OC_SIS5597; break; 3969 case PCI_CHIP_SIS6326: 3970 pSiS->oldChipset = OC_SIS6326; break; 3971 case PCI_CHIP_SIS530: 3972 if(sis_pci_read_host_bridge_u32(0x00) == 0x06201039) { 3973 pSiS->oldChipset = OC_SIS620; 3974 } else { 3975 if((pSiS->ChipRev & 0x0f) < 0x0a) 3976 pSiS->oldChipset = OC_SIS530A; 3977 else pSiS->oldChipset = OC_SIS530B; 3978 } 3979 break; 3980 default: 3981 pSiS->oldChipset = OC_UNKNOWN; 3982 } 3983 } 3984 3985 if(!xf86SetDepthBpp(pScrn, 0, 0, 0, pix24flags)) { 3986 SISErrorLog(pScrn, "xf86SetDepthBpp() error\n"); 3987 goto my_error_1; 3988 } 3989 3990 /* Check that the returned depth is one we support */ 3991 temp = 0; 3992 switch(pScrn->depth) { 3993 case 8: 3994 case 16: 3995 case 24: 3996 break; 3997 case 15: 3998 if((pSiS->VGAEngine == SIS_300_VGA) || 3999 (pSiS->VGAEngine == SIS_315_VGA)) { 4000 temp = 1; 4001 } 4002 break; 4003 default: 4004 temp = 1; 4005 } 4006 4007 if(temp) { 4008 SISErrorLog(pScrn, 4009 "Given color depth (%d) is not supported by this driver/chipset\n", 4010 pScrn->depth); 4011 goto my_error_1; 4012 } 4013 4014 xf86PrintDepthBpp(pScrn); 4015 4016 if( (((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) && 4017 (pScrn->bitsPerPixel == 24)) || 4018 ((pSiS->VGAEngine == SIS_OLD_VGA) && (pScrn->bitsPerPixel == 32)) ) { 4019 SISErrorLog(pScrn, 4020 "Framebuffer bpp %d not supported for this chipset\n", pScrn->bitsPerPixel); 4021 goto my_error_1; 4022 } 4023 4024 /* Get the depth24 pixmap format */ 4025 if(pScrn->depth == 24 && pix24bpp == 0) { 4026 pix24bpp = xf86GetBppFromDepth(pScrn, 24); 4027 } 4028 4029 /* 4030 * This must happen after pScrn->display has been set because 4031 * xf86SetWeight references it. 4032 */ 4033 if(pScrn->depth > 8) { 4034 /* The defaults are OK for us */ 4035 rgb zeros = {0, 0, 0}; 4036 4037 if(!xf86SetWeight(pScrn, zeros, zeros)) { 4038 SISErrorLog(pScrn, "xf86SetWeight() error\n"); 4039 goto my_error_1; 4040 } else { 4041 Bool ret = FALSE; 4042 switch(pScrn->depth) { 4043 case 15: 4044 if((pScrn->weight.red != 5) || 4045 (pScrn->weight.green != 5) || 4046 (pScrn->weight.blue != 5)) ret = TRUE; 4047 break; 4048 case 16: 4049 if((pScrn->weight.red != 5) || 4050 (pScrn->weight.green != 6) || 4051 (pScrn->weight.blue != 5)) ret = TRUE; 4052 break; 4053 case 24: 4054 if((pScrn->weight.red != 8) || 4055 (pScrn->weight.green != 8) || 4056 (pScrn->weight.blue != 8)) ret = TRUE; 4057 break; 4058 } 4059 if(ret) { 4060 SISErrorLog(pScrn, 4061 "RGB weight %d%d%d at depth %d not supported by hardware\n", 4062 (int)pScrn->weight.red, (int)pScrn->weight.green, 4063 (int)pScrn->weight.blue, pScrn->depth); 4064 goto my_error_1; 4065 } 4066 } 4067 } 4068 4069 /* Set the current layout parameters */ 4070 pSiS->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel; 4071 pSiS->CurrentLayout.depth = pScrn->depth; 4072 /* (Inside this function, we can use pScrn's contents anyway) */ 4073 4074 if(!xf86SetDefaultVisual(pScrn, -1)) { 4075 SISErrorLog(pScrn, "xf86SetDefaultVisual() error\n"); 4076 goto my_error_1; 4077 } else { 4078 /* We don't support DirectColor at > 8bpp */ 4079 if(pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { 4080 SISErrorLog(pScrn, 4081 "Given default visual (%s) is not supported at depth %d\n", 4082 xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); 4083 goto my_error_1; 4084 } 4085 } 4086 4087#ifdef SISDUALHEAD 4088 /* Due to palette & timing problems we don't support 8bpp in DHM */ 4089 if((pSiS->DualHeadMode) && (pScrn->bitsPerPixel <= 8)) { 4090 SISErrorLog(pScrn, "Color depth %d not supported in Dual Head mode.\n", 4091 pScrn->bitsPerPixel); 4092 goto my_error_1; 4093 } 4094#endif 4095 4096 /* Read BIOS for 300/315/330/340 series customization */ 4097 pSiS->SiS_Pr->VirtualRomBase = NULL; 4098 pSiS->BIOS = NULL; 4099 pSiS->SiS_Pr->UseROM = FALSE; 4100 pSiS->ROM661New = FALSE; 4101 pSiS->HaveXGIBIOS = FALSE; 4102 4103 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 4104#ifdef SISDUALHEAD 4105 if(pSiSEnt) { 4106 if(pSiSEnt->BIOS) { 4107 pSiS->BIOS = pSiSEnt->BIOS; 4108 pSiS->SiS_Pr->VirtualRomBase = pSiS->BIOS; 4109 pSiS->ROM661New = pSiSEnt->ROM661New; 4110 pSiS->HaveXGIBIOS = pSiSEnt->HaveXGIBIOS; 4111 } 4112 } 4113#endif 4114 if(!pSiS->BIOS) { 4115 if(!(pSiS->BIOS = calloc(1, BIOS_SIZE))) { 4116 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4117 "Could not allocate memory for video BIOS image\n"); 4118 } else { 4119 UShort mypciid = pSiS->Chipset; 4120 UShort mypcivendor = (pSiS->ChipFlags & SiSCF_IsXGI) ? PCI_VENDOR_XGI : PCI_VENDOR_SIS; 4121 Bool found = FALSE, readpci = FALSE; 4122 int biossize = BIOS_SIZE; 4123 4124 switch(pSiS->ChipType) { 4125 case SIS_315: mypciid = PCI_CHIP_SIS315; 4126 readpci = TRUE; 4127 break; 4128 case SIS_315PRO: mypciid = PCI_CHIP_SIS315PRO; 4129 readpci = TRUE; 4130 break; 4131 case SIS_300: 4132 case SIS_315H: 4133 case SIS_330: 4134 case SIS_340: 4135 case SIS_650: 4136 case SIS_760: 4137 case XGI_40: readpci = TRUE; 4138 break; 4139 case XGI_20: readpci = TRUE; 4140 biossize = 0x8000; 4141 break; 4142 } 4143#if XSERVER_LIBPCIACCESS 4144 if(readpci) { 4145 pSiS->PciInfo->rom_size = biossize; 4146 pci_device_read_rom(pSiS->PciInfo, pSiS->BIOS); 4147 if(SISCheckBIOS(pSiS, mypciid, mypcivendor, biossize)) { 4148 found = TRUE; 4149 } 4150 } 4151#else 4152 if(readpci) { 4153 xf86ReadPciBIOS(0, pSiS->PciTag, 0, pSiS->BIOS, biossize); 4154 if(SISCheckBIOS(pSiS, mypciid, mypcivendor, biossize)) { 4155 found = TRUE; 4156 } 4157 } 4158 4159 if(!found) { 4160 ULong segstart; 4161 for(segstart = BIOS_BASE; segstart < 0x000f0000; segstart += 0x00001000) { 4162 4163#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 4164 if(xf86ReadBIOS(segstart, 0, pSiS->BIOS, biossize) != biossize) continue; 4165#else 4166 if(xf86ReadDomainMemory(pSiS->PciTag, segstart, biossize, pSiS->BIOS) != biossize) continue; 4167#endif 4168 4169 if(!SISCheckBIOS(pSiS, mypciid, mypcivendor, biossize)) continue; 4170 4171 found = TRUE; 4172 break; 4173 } 4174 } 4175#endif 4176 if(found) { 4177 UShort romptr = pSiS->BIOS[0x16] | (pSiS->BIOS[0x17] << 8); 4178 pSiS->SiS_Pr->VirtualRomBase = pSiS->BIOS; 4179 if(pSiS->ChipFlags & SiSCF_IsXGI) { 4180 pSiS->HaveXGIBIOS = pSiS->SiS_Pr->SiS_XGIROM = TRUE; 4181 pSiS->SiS_Pr->UseROM = FALSE; 4182 if(pSiS->ChipFlags & SiSCF_IsXGIV3) { 4183 if(!(pSiS->BIOS[0x1d1] & 0x01)) { 4184 pSiS->SiS_Pr->DDCPortMixup = TRUE; 4185 } 4186 } 4187 } else { 4188 pSiS->ROM661New = SiSDetermineROMLayout661(pSiS->SiS_Pr); 4189 } 4190 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4191 "Video BIOS version \"%7s\" found (%s data layout)\n", 4192 &pSiS->BIOS[romptr], pSiS->ROM661New ? "new SiS" : 4193 (pSiS->HaveXGIBIOS ? "XGI" : "old SiS")); 4194 if(pSiS->SiS_Pr->DDCPortMixup) { 4195 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4196 "*** Buggy XGI V3XT card detected: If VGA and DVI are connected at the\n"); 4197 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4198 "*** same time, BIOS and driver will be unable to detect DVI connection.\n"); 4199 } 4200#ifdef SISDUALHEAD 4201 if(pSiSEnt) { 4202 pSiSEnt->BIOS = pSiS->BIOS; 4203 pSiSEnt->ROM661New = pSiS->ROM661New; 4204 pSiSEnt->HaveXGIBIOS = pSiS->HaveXGIBIOS; 4205 } 4206#endif 4207 } else { 4208 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4209 "Could not find/read video BIOS\n"); 4210 free(pSiS->BIOS); 4211 pSiS->BIOS = NULL; 4212 } 4213 } 4214 } 4215 4216 if(!(pSiS->ChipFlags & SiSCF_IsXGI)) { 4217 if(pSiS->BIOS) pSiS->SiS_Pr->UseROM = TRUE; 4218 else pSiS->SiS_Pr->UseROM = FALSE; 4219 } 4220 } 4221 4222 /* Evaluate options */ 4223 SiSOptions(pScrn); 4224 4225#ifdef SISMERGED 4226 /* Due to palette & timing problems we don't support 8bpp in MFBM */ 4227 if((pSiS->MergedFB) && (pScrn->bitsPerPixel <= 8)) { 4228 SISErrorLog(pScrn, "MergedFB: Color depth %d not supported, %s\n", 4229 pScrn->bitsPerPixel, mergeddisstr); 4230 pSiS->MergedFB = pSiS->MergedFBAuto = FALSE; 4231 } 4232#endif 4233 4234 /* Probe CPU features */ 4235#ifdef SISDUALHEAD 4236 if(pSiS->DualHeadMode) { 4237 pSiS->CPUFlags = pSiSEnt->CPUFlags; 4238 } 4239#endif 4240 if(!pSiS->CPUFlags) { 4241 pSiS->CPUFlags = SiSGetCPUFlags(pScrn); 4242 pSiS->CPUFlags |= SIS_CPUFL_FLAG; 4243#ifdef SISDUALHEAD 4244 if(pSiS->DualHeadMode) pSiSEnt->CPUFlags = pSiS->CPUFlags; 4245#endif 4246 } 4247 4248 /* We use a programamble clock */ 4249 pScrn->progClock = TRUE; 4250 4251 /* Set the bits per RGB for 8bpp mode */ 4252 if(pScrn->depth == 8) pScrn->rgbBits = 8; 4253 4254#ifdef SISDUALHEAD 4255 if(pSiS->DualHeadMode) { 4256 if(!pSiS->SecondHead) { 4257 /* Copy some option settings to entity private */ 4258 pSiSEnt->HWCursor = pSiS->HWCursor; 4259 pSiSEnt->NoAccel = pSiS->NoAccel; 4260 pSiSEnt->useEXA = pSiS->useEXA; 4261 pSiSEnt->restorebyset = pSiS->restorebyset; 4262 pSiSEnt->OptROMUsage = pSiS->OptROMUsage; 4263 pSiSEnt->OptUseOEM = pSiS->OptUseOEM; 4264 pSiSEnt->TurboQueue = pSiS->TurboQueue; 4265 pSiSEnt->forceCRT1 = pSiS->forceCRT1; 4266 pSiSEnt->ForceCRT1Type = pSiS->ForceCRT1Type; 4267 pSiSEnt->CRT1TypeForced = pSiS->CRT1TypeForced; 4268 pSiSEnt->ForceCRT2Type = pSiS->ForceCRT2Type; 4269 pSiSEnt->ForceTVType = pSiS->ForceTVType; 4270 pSiSEnt->ForceYPbPrType = pSiS->ForceYPbPrType; 4271 pSiSEnt->ForceYPbPrAR = pSiS->ForceYPbPrAR; 4272 pSiSEnt->UsePanelScaler = pSiS->UsePanelScaler; 4273 pSiSEnt->CenterLCD = pSiS->CenterLCD; 4274 pSiSEnt->DSTN = pSiS->DSTN; 4275 pSiSEnt->FSTN = pSiS->FSTN; 4276 pSiSEnt->OptTVStand = pSiS->OptTVStand; 4277 pSiSEnt->NonDefaultPAL = pSiS->NonDefaultPAL; 4278 pSiSEnt->NonDefaultNTSC = pSiS->NonDefaultNTSC; 4279 pSiSEnt->chtvtype = pSiS->chtvtype; 4280 pSiSEnt->OptTVOver = pSiS->OptTVOver; 4281 pSiSEnt->OptTVSOver = pSiS->OptTVSOver; 4282 pSiSEnt->chtvlumabandwidthcvbs = pSiS->chtvlumabandwidthcvbs; 4283 pSiSEnt->chtvlumabandwidthsvideo = pSiS->chtvlumabandwidthsvideo; 4284 pSiSEnt->chtvlumaflickerfilter = pSiS->chtvlumaflickerfilter; 4285 pSiSEnt->chtvchromabandwidth = pSiS->chtvchromabandwidth; 4286 pSiSEnt->chtvchromaflickerfilter = pSiS->chtvchromaflickerfilter; 4287 pSiSEnt->chtvtextenhance = pSiS->chtvtextenhance; 4288 pSiSEnt->chtvcontrast = pSiS->chtvcontrast; 4289 pSiSEnt->chtvcvbscolor = pSiS->chtvcvbscolor; 4290 pSiSEnt->sistvedgeenhance = pSiS->sistvedgeenhance; 4291 pSiSEnt->sistvantiflicker = pSiS->sistvantiflicker; 4292 pSiSEnt->sistvsaturation = pSiS->sistvsaturation; 4293 pSiSEnt->sistvcfilter = pSiS->sistvcfilter; 4294 pSiSEnt->sistvyfilter = pSiS->sistvyfilter; 4295 pSiSEnt->sistvcolcalibc = pSiS->sistvcolcalibc; 4296 pSiSEnt->sistvcolcalibf = pSiS->sistvcolcalibf; 4297 pSiSEnt->tvxpos = pSiS->tvxpos; 4298 pSiSEnt->tvypos = pSiS->tvypos; 4299 pSiSEnt->tvxscale = pSiS->tvxscale; 4300 pSiSEnt->tvyscale = pSiS->tvyscale; 4301 pSiSEnt->siscrt1satgain = pSiS->siscrt1satgain; 4302 pSiSEnt->crt1satgaingiven = pSiS->crt1satgaingiven; 4303 pSiSEnt->CRT1gamma = pSiS->CRT1gamma; 4304 pSiSEnt->CRT1gammaGiven = pSiS->CRT1gammaGiven; 4305 pSiSEnt->XvGammaRed = pSiS->XvGammaRed; 4306 pSiSEnt->XvGammaGreen = pSiS->XvGammaGreen; 4307 pSiSEnt->XvGammaBlue = pSiS->XvGammaBlue; 4308 pSiSEnt->XvGamma = pSiS->XvGamma; 4309 pSiSEnt->XvGammaGiven = pSiS->XvGammaGiven; 4310 pSiSEnt->CRT2gamma = pSiS->CRT2gamma; 4311 pSiSEnt->XvOnCRT2 = pSiS->XvOnCRT2; 4312 pSiSEnt->AllowHotkey = pSiS->AllowHotkey; 4313 pSiSEnt->enablesisctrl = pSiS->enablesisctrl; 4314 pSiSEnt->SenseYPbPr = pSiS->SenseYPbPr; 4315 pSiSEnt->XvUseMemcpy = pSiS->XvUseMemcpy; 4316 pSiSEnt->BenchMemCpy = pSiS->BenchMemCpy; 4317#ifdef SIS_CP 4318 SIS_CP_DRIVER_COPYOPTIONSENT 4319#endif 4320 } else { 4321 /* We always use same cursor type on both screens */ 4322 pSiS->HWCursor = pSiSEnt->HWCursor; 4323 /* We need identical NoAccel setting */ 4324 pSiS->NoAccel = pSiSEnt->NoAccel; 4325 pSiS->useEXA = pSiSEnt->useEXA; 4326 pSiS->TurboQueue = pSiSEnt->TurboQueue; 4327 pSiS->restorebyset = pSiSEnt->restorebyset; 4328 pSiS->AllowHotkey = pSiS->AllowHotkey; 4329 pSiS->OptROMUsage = pSiSEnt->OptROMUsage; 4330 pSiS->OptUseOEM = pSiSEnt->OptUseOEM; 4331 pSiS->forceCRT1 = pSiSEnt->forceCRT1; 4332 pSiS->nocrt2ddcdetection = FALSE; 4333 pSiS->forcecrt2redetection = FALSE; 4334 pSiS->ForceCRT1Type = pSiSEnt->ForceCRT1Type; 4335 pSiS->ForceCRT2Type = pSiSEnt->ForceCRT2Type; 4336 pSiS->CRT1TypeForced = pSiSEnt->CRT1TypeForced; 4337 pSiS->UsePanelScaler = pSiSEnt->UsePanelScaler; 4338 pSiS->CenterLCD = pSiSEnt->CenterLCD; 4339 pSiS->DSTN = pSiSEnt->DSTN; 4340 pSiS->FSTN = pSiSEnt->FSTN; 4341 pSiS->OptTVStand = pSiSEnt->OptTVStand; 4342 pSiS->NonDefaultPAL = pSiSEnt->NonDefaultPAL; 4343 pSiS->NonDefaultNTSC = pSiSEnt->NonDefaultNTSC; 4344 pSiS->chtvtype = pSiSEnt->chtvtype; 4345 pSiS->ForceTVType = pSiSEnt->ForceTVType; 4346 pSiS->ForceYPbPrType = pSiSEnt->ForceYPbPrType; 4347 pSiS->ForceYPbPrAR = pSiSEnt->ForceYPbPrAR; 4348 pSiS->OptTVOver = pSiSEnt->OptTVOver; 4349 pSiS->OptTVSOver = pSiSEnt->OptTVSOver; 4350 pSiS->chtvlumabandwidthcvbs = pSiSEnt->chtvlumabandwidthcvbs; 4351 pSiS->chtvlumabandwidthsvideo = pSiSEnt->chtvlumabandwidthsvideo; 4352 pSiS->chtvlumaflickerfilter = pSiSEnt->chtvlumaflickerfilter; 4353 pSiS->chtvchromabandwidth = pSiSEnt->chtvchromabandwidth; 4354 pSiS->chtvchromaflickerfilter = pSiSEnt->chtvchromaflickerfilter; 4355 pSiS->chtvcvbscolor = pSiSEnt->chtvcvbscolor; 4356 pSiS->chtvtextenhance = pSiSEnt->chtvtextenhance; 4357 pSiS->chtvcontrast = pSiSEnt->chtvcontrast; 4358 pSiS->sistvedgeenhance = pSiSEnt->sistvedgeenhance; 4359 pSiS->sistvantiflicker = pSiSEnt->sistvantiflicker; 4360 pSiS->sistvsaturation = pSiSEnt->sistvsaturation; 4361 pSiS->sistvcfilter = pSiSEnt->sistvcfilter; 4362 pSiS->sistvyfilter = pSiSEnt->sistvyfilter; 4363 pSiS->sistvcolcalibc = pSiSEnt->sistvcolcalibc; 4364 pSiS->sistvcolcalibf = pSiSEnt->sistvcolcalibf; 4365 pSiS->tvxpos = pSiSEnt->tvxpos; 4366 pSiS->tvypos = pSiSEnt->tvypos; 4367 pSiS->tvxscale = pSiSEnt->tvxscale; 4368 pSiS->tvyscale = pSiSEnt->tvyscale; 4369 pSiS->SenseYPbPr = pSiSEnt->SenseYPbPr; 4370 if(!pSiS->CRT1gammaGiven) { 4371 if(pSiSEnt->CRT1gammaGiven) 4372 pSiS->CRT1gamma = pSiSEnt->CRT1gamma; 4373 } 4374 pSiS->CRT2gamma = pSiSEnt->CRT2gamma; 4375 if(!pSiS->XvGammaGiven) { 4376 if(pSiSEnt->XvGammaGiven) { 4377 pSiS->XvGamma = pSiSEnt->XvGamma; 4378 pSiS->XvGammaRed = pSiS->XvGammaRedDef = pSiSEnt->XvGammaRed; 4379 pSiS->XvGammaGreen = pSiS->XvGammaGreenDef = pSiSEnt->XvGammaGreen; 4380 pSiS->XvGammaBlue = pSiS->XvGammaBlueDef = pSiSEnt->XvGammaBlue; 4381 } 4382 } 4383 if(!pSiS->crt1satgaingiven) { 4384 if(pSiSEnt->crt1satgaingiven) 4385 pSiS->siscrt1satgain = pSiSEnt->siscrt1satgain; 4386 } 4387 pSiS->XvOnCRT2 = pSiSEnt->XvOnCRT2; 4388 pSiS->enablesisctrl = pSiSEnt->enablesisctrl; 4389 pSiS->XvUseMemcpy = pSiSEnt->XvUseMemcpy; 4390 pSiS->BenchMemCpy = pSiSEnt->BenchMemCpy; 4391 /* Copy gamma brightness to Ent (sic!) for Xinerama */ 4392 pSiSEnt->GammaBriR = pSiS->GammaBriR; 4393 pSiSEnt->GammaBriG = pSiS->GammaBriG; 4394 pSiSEnt->GammaBriB = pSiS->GammaBriB; 4395 pSiSEnt->NewGammaBriR = pSiS->NewGammaBriR; 4396 pSiSEnt->NewGammaBriG = pSiS->NewGammaBriG; 4397 pSiSEnt->NewGammaBriB = pSiS->NewGammaBriB; 4398 pSiSEnt->NewGammaConR = pSiS->NewGammaConR; 4399 pSiSEnt->NewGammaConG = pSiS->NewGammaConG; 4400 pSiSEnt->NewGammaConB = pSiS->NewGammaConB; 4401#ifdef SIS_CP 4402 SIS_CP_DRIVER_COPYOPTIONS 4403#endif 4404 } 4405 } 4406#endif 4407 4408 /* Handle UseROMData, NoOEM and UsePanelScaler options */ 4409 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 4410 from = X_PROBED; 4411 if(pSiS->OptROMUsage == 0) { 4412 pSiS->SiS_Pr->UseROM = FALSE; 4413 from = X_CONFIG; 4414 xf86DrvMsg(pScrn->scrnIndex, from, "Video ROM data usage is disabled\n"); 4415 } 4416 4417 if(!pSiS->OptUseOEM) { 4418 xf86DrvMsg(pScrn->scrnIndex, from, "Internal OEM LCD/TV/VGA2 data usage is disabled\n"); 4419 } 4420 4421 pSiS->SiS_Pr->UsePanelScaler = pSiS->UsePanelScaler; 4422 pSiS->SiS_Pr->CenterScreen = pSiS->CenterLCD; 4423 } 4424 4425 /* Do some HW configuration detection (memory amount & type, clock, etc) */ 4426 SiSSetup(pScrn); 4427 4428 /* Get framebuffer address */ 4429 if(pSiS->pEnt->device->MemBase != 0) { 4430 /* 4431 * XXX Should check that the config file value matches one of the 4432 * PCI base address values. 4433 */ 4434 pSiS->FbAddress = pSiS->pEnt->device->MemBase; 4435 from = X_CONFIG; 4436 } else { 4437 pSiS->FbAddress = PCI_REGION_BASE(pSiS->PciInfo, 0, REGION_MEM) & 0xFFFFFFF0; 4438 from = X_PROBED; 4439 } 4440 4441#ifdef SISDUALHEAD 4442 if(pSiS->DualHeadMode) 4443 xf86DrvMsg(pScrn->scrnIndex, from, "Global linear framebuffer at 0x%lX\n", 4444 (ULong)pSiS->FbAddress); 4445 else 4446#endif 4447 xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", 4448 (ULong)pSiS->FbAddress); 4449 4450 pSiS->realFbAddress = pSiS->FbAddress; 4451 4452 /* Get MMIO address */ 4453 if(pSiS->pEnt->device->IOBase != 0) { 4454 /* 4455 * XXX Should check that the config file value matches one of the 4456 * PCI base address values. 4457 */ 4458 pSiS->IOAddress = pSiS->pEnt->device->IOBase; 4459 from = X_CONFIG; 4460 } else { 4461 pSiS->IOAddress = PCI_REGION_BASE(pSiS->PciInfo, 1, REGION_MEM) & 0xFFFFFFF0; 4462 from = X_PROBED; 4463 } 4464 xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX (size %ldK)\n", 4465 (ULong)pSiS->IOAddress, pSiS->mmioSize); 4466 4467#ifndef XSERVER_LIBPCIACCESS 4468 /* Register the PCI-assigned resources */ 4469 if(xf86RegisterResources(pSiS->pEnt->index, NULL, ResExclusive)) { 4470 SISErrorLog(pScrn, "PCI resource conflicts detected\n"); 4471#ifdef SISDUALHEAD 4472 if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; 4473#endif 4474 sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); 4475 if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); 4476 SISFreeRec(pScrn); 4477 return FALSE; 4478 } 4479#endif 4480 4481 from = X_PROBED; 4482 if(pSiS->pEnt->device->videoRam != 0) { 4483 if(pSiS->Chipset == PCI_CHIP_SIS6326) { 4484 pScrn->videoRam = pSiS->pEnt->device->videoRam; 4485 from = X_CONFIG; 4486 } else { 4487 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4488 "Option \"VideoRAM\" ignored\n"); 4489 } 4490 } 4491 4492 pSiS->RealVideoRam = pScrn->videoRam; 4493 4494 if((pSiS->Chipset == PCI_CHIP_SIS6326) && 4495 (pScrn->videoRam > 4096) && 4496 (from != X_CONFIG)) { 4497 pScrn->videoRam = 4096; 4498 xf86DrvMsg(pScrn->scrnIndex, from, 4499 "SiS6326: Detected %d KB VideoRAM, limiting to %d KB\n", 4500 pSiS->RealVideoRam, pScrn->videoRam); 4501 } else { 4502 xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d KB\n", pScrn->videoRam); 4503 } 4504 4505 if((pSiS->Chipset == PCI_CHIP_SIS6326) && 4506 (pScrn->videoRam > 4096)) { 4507 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4508 "SiS6326 engines do not support more than 4096KB RAM, therefore\n"); 4509 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4510 "TurboQueue, HWCursor, 2D acceleration and XVideo are disabled.\n"); 4511 pSiS->TurboQueue = FALSE; 4512 pSiS->HWCursor = FALSE; 4513 pSiS->NoXvideo = TRUE; 4514 pSiS->NoAccel = TRUE; 4515 } 4516 4517 pSiS->FbMapSize = pSiS->availMem = pScrn->videoRam * 1024; 4518 4519 /* Calculate real availMem according to Accel/TurboQueue and 4520 * HWCursur setting. Also, initialize some variables used 4521 * in other modules. 4522 */ 4523 pSiS->cursorOffset = 0; 4524 pSiS->CurARGBDest = NULL; 4525 pSiS->CurMonoSrc = NULL; 4526 pSiS->CurFGCol = pSiS->CurBGCol = 0; 4527 pSiS->FbBaseOffset = 0; 4528 4529 switch(pSiS->VGAEngine) { 4530 4531 case SIS_300_VGA: 4532 pSiS->TurboQueueLen = 512; 4533 if(pSiS->TurboQueue) { 4534 pSiS->availMem -= (pSiS->TurboQueueLen*1024); 4535 pSiS->cursorOffset = 512; 4536 } 4537 if(pSiS->HWCursor) { 4538 pSiS->availMem -= pSiS->CursorSize; 4539 if(pSiS->OptUseColorCursor) pSiS->availMem -= pSiS->CursorSize; 4540 } 4541 pSiS->CmdQueLenMask = 0xFFFF; 4542 pSiS->CmdQueLenFix = 0; 4543 pSiS->cursorBufferNum = 0; 4544#ifdef SISDUALHEAD 4545 if(pSiSEnt) pSiSEnt->cursorBufferNum = 0; 4546#endif 4547 break; 4548 4549 case SIS_315_VGA: 4550#ifdef SISVRAMQ /* VRAM queue */ 4551 pSiS->cmdQueueSizeMask = pSiS->cmdQueueSize - 1; /* VRAM Command Queue is variable (in therory) */ 4552 pSiS->cmdQueueOffset = (pScrn->videoRam * 1024) - pSiS->cmdQueueSize; 4553 pSiS->cmdQueueLen = 0; 4554 pSiS->cmdQueueSize_div2 = pSiS->cmdQueueSize / 2; 4555 pSiS->cmdQueueSize_div4 = pSiS->cmdQueueSize / 4; 4556 pSiS->cmdQueueSize_4_3 = (pSiS->cmdQueueSize / 4) * 3; 4557 pSiS->availMem -= pSiS->cmdQueueSize; 4558 pSiS->cursorOffset = (pSiS->cmdQueueSize / 1024); 4559 4560 /* Set up shared pointer to current offset */ 4561#ifdef SISDUALHEAD 4562 if(pSiS->DualHeadMode) 4563 pSiS->cmdQ_SharedWritePort = &(pSiSEnt->cmdQ_SharedWritePort_2D); 4564 else 4565#endif 4566 pSiS->cmdQ_SharedWritePort = &(pSiS->cmdQ_SharedWritePort_2D); 4567 4568 4569#else /* MMIO */ 4570 if(pSiS->TurboQueue) { 4571 pSiS->availMem -= (512*1024); /* MMIO Command Queue is 512k (variable in theory) */ 4572 pSiS->cursorOffset = 512; 4573 } 4574#endif 4575 if(pSiS->HWCursor) { 4576 pSiS->availMem -= (pSiS->CursorSize * 2); 4577 if(pSiS->OptUseColorCursor) pSiS->availMem -= (pSiS->CursorSize * 2); 4578 } 4579 pSiS->cursorBufferNum = 0; 4580#ifdef SISDUALHEAD 4581 if(pSiSEnt) pSiSEnt->cursorBufferNum = 0; 4582#endif 4583 4584 if((pSiS->SiS76xLFBSize) && (pSiS->SiS76xUMASize)) { 4585 pSiS->availMem -= pSiS->SiS76xUMASize; 4586 pSiS->FbBaseOffset = pSiS->SiS76xUMASize; 4587 } 4588 4589 break; 4590 4591 default: 4592 /* cursorOffset not used in cursor functions for 530 and 4593 * older chips, because the cursor is *above* the TQ. 4594 * On 5597 and older revisions of the 6326, the TQ is 4595 * max 32K, on newer 6326 revisions and the 530 either 30 4596 * (or 32?) or 62K (or 64?). However, to make sure, we 4597 * use only 30K (or 32?), but reduce the available memory 4598 * by 64, and locate the TQ at the beginning of this last 4599 * 64K block. (We do this that way even when using the 4600 * HWCursor, because the cursor only takes 2K and the 4601 * queue does not seem to last that far anyway.) 4602 * The TQ must be located at 32KB boundaries. 4603 */ 4604 if(pSiS->RealVideoRam < 3072) { 4605 if(pSiS->TurboQueue) { 4606 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4607 "Not enough video RAM for TurboQueue. TurboQueue disabled\n"); 4608 pSiS->TurboQueue = FALSE; 4609 } 4610 } 4611 pSiS->CmdQueMaxLen = 32; 4612 if(pSiS->TurboQueue) { 4613 pSiS->availMem -= (64*1024); 4614 pSiS->CmdQueMaxLen = 900; /* To make sure; should be 992 */ 4615 } else if(pSiS->HWCursor) { 4616 pSiS->availMem -= pSiS->CursorSize; 4617 } 4618 if(pSiS->Chipset == PCI_CHIP_SIS530) { 4619 /* Check if Flat Panel is enabled */ 4620 inSISIDXREG(SISSR, 0x0e, tempreg); 4621 if(!(tempreg & 0x04)) pSiS->availMem -= pSiS->CursorSize; 4622 4623 /* Set up mask for MMIO register */ 4624 pSiS->CmdQueLenMask = (pSiS->TurboQueue) ? 0x1FFF : 0x00FF; 4625 } else { 4626 /* TQ is never used on 6326/5597, because the accelerator 4627 * always Syncs. So this is just cosmentic work. (And I 4628 * am not even sure that 0x7fff is correct. MMIO 0x83a8 4629 * holds 0xec0 if (30k) TQ is enabled, 0x20 if TQ disabled. 4630 * The datasheet has no real explanation on the queue length 4631 * if the TQ is enabled. Not syncing and waiting for a 4632 * suitable queue length instead does not work. 4633 */ 4634 pSiS->CmdQueLenMask = (pSiS->TurboQueue) ? 0x7FFF : 0x003F; 4635 } 4636 4637 /* This is to be subtracted from MMIO queue length register contents 4638 * for getting the real Queue length. 4639 */ 4640 pSiS->CmdQueLenFix = (pSiS->TurboQueue) ? 32 : 0; 4641 } 4642 4643 4644#ifdef SISDUALHEAD 4645 /* In dual head mode, we share availMem equally - so align it 4646 * to 8KB; this way, the address of the FB of the second 4647 * head is aligned to 4KB for mapping. 4648 */ 4649 if(pSiS->DualHeadMode) pSiS->availMem &= 0xFFFFE000; 4650#endif 4651 4652 /* Check MaxXFBMem setting */ 4653#ifdef SISDUALHEAD 4654 if(pSiS->DualHeadMode) { 4655 /* 1. Since DRI is not supported in dual head mode, we 4656 * don't need the MaxXFBMem setting - ignore it. 4657 */ 4658 if(pSiS->maxxfbmem) { 4659 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4660 "MaxXFBMem ignored in Dual Head mode\n"); 4661 } 4662 pSiS->maxxfbmem = pSiS->availMem; 4663 } else 4664#endif 4665 if((pSiS->sisfbHeapStart) || (pSiS->sisfbHaveNewHeapDef)) { 4666 4667 /* 4668 * 2. We have memory layout info from sisfb - ignore MaxXFBMem 4669 */ 4670 if(pSiS->maxxfbmem) { 4671 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4672 "Got memory layout info from sisfb, ignoring MaxXFBMem option\n"); 4673 } 4674 if((pSiS->FbBaseOffset) && (!pSiS->sisfbHaveNewHeapDef)) { 4675 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4676 "Incompatible sisfb version detected, DRI disabled\n"); 4677 pSiS->loadDRI = FALSE; 4678 pSiS->maxxfbmem = pSiS->availMem; 4679 } else { 4680 if(pSiS->FbBaseOffset) { 4681 /* Revert our changes to FbBaseOffset and availMem; use sisfb's info */ 4682 pSiS->availMem += pSiS->FbBaseOffset; 4683 pSiS->FbBaseOffset = 0; 4684 } 4685 if(pSiS->sisfbVideoOffset) { 4686 /* a. DRI heap BELOW framebuffer */ 4687 pSiS->FbBaseOffset = pSiS->sisfbVideoOffset; 4688 pSiS->availMem -= pSiS->FbBaseOffset; 4689 pSiS->maxxfbmem = pSiS->availMem; 4690 } else { 4691 /* b. DRI heap ABOVE framebuffer (traditional layout) */ 4692 if(pSiS->availMem < (pSiS->sisfbHeapStart * 1024)) { 4693 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4694 "Internal error - sisfb memory layout corrupt\n"); 4695 pSiS->loadDRI = FALSE; 4696 pSiS->maxxfbmem = pSiS->availMem; 4697 } else { 4698 pSiS->maxxfbmem = pSiS->sisfbHeapStart * 1024; 4699 } 4700 } 4701 } 4702 4703 } else if(pSiS->maxxfbmem) { 4704 4705 /* 4706 * 3. No sisfb, but user gave "MaxXFBMem" 4707 */ 4708 if(pSiS->FbBaseOffset) { 4709 /* a. DRI heap BELOW framebuffer */ 4710 if(pSiS->maxxfbmem > (pSiS->availMem + pSiS->FbBaseOffset - pSiS->SiS76xUMASize)) { 4711 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4712 "Invalid MaxXFBMem setting\n"); 4713 pSiS->maxxfbmem = pSiS->availMem; 4714 } else { 4715 /* Revert our changes */ 4716 pSiS->availMem += pSiS->FbBaseOffset; 4717 /* Use user's MaxXFBMem setting */ 4718 pSiS->FbBaseOffset = pSiS->availMem - pSiS->maxxfbmem; 4719 pSiS->availMem -= pSiS->FbBaseOffset; 4720 } 4721 } else { 4722 /* b. DRI heap ABOVE framebuffer (traditional layout) */ 4723 if(pSiS->maxxfbmem > pSiS->availMem) { 4724 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4725 "Invalid MaxXFBMem setting.\n"); 4726 pSiS->maxxfbmem = pSiS->availMem; 4727 } 4728 } 4729 4730 } else { 4731 4732 /* 4733 * 4. No MaxXFBMem, no sisfb: Use all memory 4734 */ 4735 pSiS->maxxfbmem = pSiS->availMem; 4736 4737 /* ... except on chipsets, for which DRI is 4738 * supported: If DRI is enabled, we now limit 4739 * ourselves to a reasonable default: 4740 */ 4741 4742 if(pSiS->loadDRI) { 4743 if(pSiS->FbBaseOffset) { 4744 /* a. DRI heap BELOW framebuffer */ 4745 /* See how much UMA and LFB memory we have, 4746 * and calculate a reasonable default. We 4747 * use more vram for ourselves because these 4748 * chips are eg. capable of larger Xv 4749 * overlays, etc. 4750 */ 4751 unsigned long total = (pSiS->SiS76xLFBSize + pSiS->SiS76xUMASize) / 1024; 4752 unsigned long mymax; 4753 if(total <= 16384) /* <= 16MB: Use 8MB for X */ 4754 mymax = 8192 * 1024; 4755 else if(total <= 32768) /* <= 32MB: Use 16MB for X */ 4756 mymax = 16384 * 1024; 4757 else /* Otherwise: Use 20MB for X */ 4758 mymax = 20 * 1024 * 1024; 4759 /* availMem is right now adjusted to not use the UMA 4760 * area. Make sure that our default doesn't reach 4761 * into the UMA area either. 4762 */ 4763 if(pSiS->availMem > mymax) { 4764 /* Write our default to maxxfbmem */ 4765 pSiS->maxxfbmem = mymax; 4766 /* Revert our changes to availMem */ 4767 pSiS->availMem += pSiS->FbBaseOffset; 4768 /* Use our default setting */ 4769 pSiS->FbBaseOffset = pSiS->availMem - pSiS->maxxfbmem; 4770 pSiS->availMem -= pSiS->FbBaseOffset; 4771 } 4772 } else { 4773 /* b. DRI heap ABOVE framebuffer (traditional layout) */ 4774 /* See how much video memory we have, and calculate 4775 * a reasonable default. 4776 * Since DRI is pointless with less than 4MB of total 4777 * video RAM, we disable it in that case. 4778 */ 4779 if(pScrn->videoRam <= 4096) 4780 pSiS->loadDRI = FALSE; 4781 else if(pScrn->videoRam <= 8192) /* <= 8MB: Use 4MB for X */ 4782 pSiS->maxxfbmem = 4096 * 1024; 4783 else if(pScrn->videoRam <= 16384) /* <= 16MB: Use 8MB for X */ 4784 pSiS->maxxfbmem = 8192 * 1024; 4785#ifdef SISMERGED /* Otherwise: --- */ 4786 else if(pSiS->MergedFB) { 4787 if(pScrn->videoRam <= 65536) 4788 pSiS->maxxfbmem = 16384 * 1024; /* If MergedFB and <=64MB, use 16MB for X */ 4789 else 4790 pSiS->maxxfbmem = 20 * 1024 * 1024; /* If MergedFB and > 64MB, use 20MB for X */ 4791 } 4792#endif 4793 else if(pSiS->VGAEngine == SIS_315_VGA) { 4794 if(pScrn->videoRam <= 65536) 4795 pSiS->maxxfbmem = 16384 * 1024; /* On >=315 series and <=64MB, use 16MB */ 4796 else 4797 pSiS->maxxfbmem = 20 * 1024 * 1024; /* On >=315 series and > 64MB, use 20MB */ 4798 } else 4799 pSiS->maxxfbmem = 12288 * 1024; /* On <315 series, use 12MB */ 4800 4801 /* A final check */ 4802 if(pSiS->maxxfbmem > pSiS->availMem) { 4803 pSiS->maxxfbmem = pSiS->availMem; 4804 pSiS->loadDRI = FALSE; 4805 } 4806 } 4807 4808 } 4809 } 4810 4811 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %dK of framebuffer memory at offset %dK\n", 4812 pSiS->maxxfbmem / 1024, pSiS->FbBaseOffset / 1024); 4813 4814 /* Find out about sub-classes of some chipsets and check 4815 * if the chipset supports two video overlays 4816 */ 4817 if(pSiS->VGAEngine == SIS_300_VGA || 4818 pSiS->VGAEngine == SIS_315_VGA || 4819 pSiS->Chipset == PCI_CHIP_SIS530 || 4820 pSiS->Chipset == PCI_CHIP_SIS6326 || 4821 pSiS->Chipset == PCI_CHIP_SIS5597) { 4822 pSiS->hasTwoOverlays = FALSE; 4823 switch(pSiS->Chipset) { 4824 case PCI_CHIP_SIS300: 4825 case PCI_CHIP_SIS540: /* ? (If not, need to add the SwitchCRT Xv attribute!) */ 4826 case PCI_CHIP_SIS630: 4827 case PCI_CHIP_SIS550: 4828 pSiS->hasTwoOverlays = TRUE; 4829 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4830 break; 4831 case PCI_CHIP_SIS315PRO: 4832 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4833 break; 4834 case PCI_CHIP_SIS330: 4835 pSiS->ChipFlags |= (SiSCF_CRT2HWCKaputt | SiSCF_LARGEOVERLAY); 4836 break; 4837 case PCI_CHIP_SIS340: 4838 case PCI_CHIP_XGIXG40: /* Verified: only 1 overlay */ 4839 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4840 break; 4841 case PCI_CHIP_SIS650: 4842 { 4843 UChar tempreg1, tempreg2; 4844 static const char *id650str[] = { 4845 "650", "650", "650", "650", 4846 "650 A0 AA", "650 A2 CA", "650", "650", 4847 "M650 A0", "M650 A1 AA","651 A0 AA", "651 A1 AA", 4848 "M650", "65?", "651", "65?" 4849 }; 4850 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4851 if(pSiS->ChipType == SIS_650) { 4852 inSISIDXREG(SISCR, 0x5f, CR5F); 4853 CR5F &= 0xf0; 4854 andSISIDXREG(SISCR, 0x5c, 0x07); 4855 inSISIDXREG(SISCR, 0x5c, tempreg1); 4856 tempreg1 &= 0xf8; 4857 orSISIDXREG(SISCR, 0x5c, 0xf8); 4858 inSISIDXREG(SISCR, 0x5c, tempreg2); 4859 tempreg2 &= 0xf8; 4860 if((!tempreg1) || (tempreg2)) { 4861 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4862 "SiS650 revision ID %x (%s)\n", CR5F, id650str[CR5F >> 4]); 4863 if(CR5F & 0x80) { 4864 pSiS->hasTwoOverlays = TRUE; /* M650 or 651 */ 4865 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4866 } 4867 switch(CR5F) { 4868 case 0xa0: 4869 case 0xb0: 4870 case 0xe0: 4871 pSiS->ChipFlags |= SiSCF_Is651; 4872 break; 4873 case 0x80: 4874 case 0x90: 4875 case 0xc0: 4876 pSiS->ChipFlags |= SiSCF_IsM650; 4877 break; 4878 } 4879 } else { 4880 pSiS->hasTwoOverlays = TRUE; 4881 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4882 switch(CR5F) { 4883 case 0x90: 4884 inSISIDXREG(SISCR, 0x5c, tempreg1); 4885 tempreg1 &= 0xf8; 4886 switch(tempreg1) { 4887 case 0x00: 4888 pSiS->ChipFlags |= SiSCF_IsM652; 4889 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4890 "SiSM652 revision ID %x\n", CR5F); 4891 break; 4892 case 0x40: 4893 pSiS->ChipFlags |= SiSCF_IsM653; 4894 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4895 "SiSM653 revision ID %x\n", CR5F); 4896 break; 4897 default: 4898 pSiS->ChipFlags |= SiSCF_IsM650; 4899 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4900 "SiSM650 revision ID %x\n", CR5F); 4901 break; 4902 } 4903 break; 4904 case 0xb0: 4905 pSiS->ChipFlags |= SiSCF_Is652; 4906 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4907 "SiS652 revision ID %x\n", CR5F); 4908 break; 4909 default: 4910 pSiS->ChipFlags |= SiSCF_IsM650; 4911 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4912 "SiSM650 revision ID %x\n", CR5F); 4913 break; 4914 } 4915 } 4916 } 4917 break; 4918 } 4919 case PCI_CHIP_SIS660: 4920 { 4921 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4922 pSiS->hasTwoOverlays = TRUE; 4923 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4924 /* 760/761: - UMA only: one/two overlays - dotclock dependent 4925 - UMA+LFB: two overlays if video data in LFB 4926 - LFB only: two overlays 4927 If UMA only: Must switch between one/two overlays on the fly (done 4928 in PostSetMode()) 4929 If LFB+UMA: We use LFB memory only and leave UMA to an eventually 4930 written DRI driver. 4931 */ 4932 break; 4933 } 4934 } 4935 4936 if(!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY)) { 4937 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4938 "Hardware supports %s video overlay%s\n", 4939 pSiS->hasTwoOverlays ? "two" : "one", 4940 pSiS->hasTwoOverlays ? "s" : ""); 4941 } 4942 4943 if(pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORT760OO) { 4944 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4945 "\n\tDear SiS76x user, your machine is using a shared memory framebuffer.\n" 4946 "\tDue to hardware limitations of the SiS chip in combination with the\n" 4947 "\tAMD CPU, video overlay support is very limited on this machine. If you\n" 4948 "\texperience flashing lines in the video and/or the graphics display\n" 4949 "\tduring video playback, reduce the color depth and/or the resolution\n" 4950 "\tand/or the refresh rate. Alternatively, use the video blitter.\n"); 4951 } 4952 4953 } 4954 4955 /* Backup VB connection and CRT1 on/off register */ 4956 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 4957 inSISIDXREG(SISSR, 0x1f, pSiS->oldSR1F); 4958 inSISIDXREG(SISCR, 0x17, pSiS->oldCR17); 4959 inSISIDXREG(SISCR, 0x32, pSiS->oldCR32); 4960 inSISIDXREG(SISCR, 0x36, pSiS->oldCR36); 4961 inSISIDXREG(SISCR, 0x37, pSiS->oldCR37); 4962 if(pSiS->VGAEngine == SIS_315_VGA) { 4963 inSISIDXREG(SISCR, pSiS->myCR63, pSiS->oldCR63); 4964 } 4965 4966 pSiS->postVBCR32 = pSiS->oldCR32; 4967 } 4968 4969 /* There are some machines out there which require a special 4970 * setup of the GPIO registers in order to make the Chrontel 4971 * work. Try to find out if we're running on such a machine. 4972 * Furthermore, there is some highly customized hardware, 4973 * which requires some non-standard LVDS timing. Since the 4974 * vendors don't seem to care about PCI subsystem ID's we 4975 * need to find out using the BIOS version and date strings. 4976 */ 4977 pSiS->SiS_Pr->SiS_ChSW = FALSE; 4978 if(pSiS->Chipset == PCI_CHIP_SIS630) { 4979 int i = 0; 4980 do { 4981 if(mychswtable[i].subsysVendor == PCI_SUB_VENDOR_ID(pSiS->PciInfo) && 4982 mychswtable[i].subsysCard == PCI_SUB_DEVICE_ID(pSiS->PciInfo)) { 4983 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4984 "PCI subsystem ID found in list for Chrontel/GPIO setup:\n"); 4985 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4986 "\tVendor/Card: %s %s (ID %04x)\n", 4987 mychswtable[i].vendorName, 4988 mychswtable[i].cardName, 4989 PCI_SUB_DEVICE_ID(pSiS->PciInfo)); 4990 pSiS->SiS_Pr->SiS_ChSW = TRUE; 4991 break; 4992 } 4993 i++; 4994 } while(mychswtable[i].subsysVendor != 0); 4995 } 4996 4997 if(pSiS->SiS_Pr->SiS_CustomT == CUT_NONE) { 4998 int i = 0, j; 4999 UShort bversptr = 0; 5000 Bool footprint; 5001 CARD32 chksum = 0; 5002 5003 if(pSiS->SiS_Pr->UseROM) { 5004 bversptr = pSiS->BIOS[0x16] | (pSiS->BIOS[0x17] << 8); 5005 for(i=0; i<32768; i++) chksum += pSiS->BIOS[i]; 5006 } 5007 5008 i = 0; 5009 do { 5010 if( (SiS_customttable[i].chipID == pSiS->ChipType) && 5011 ((!strlen(SiS_customttable[i].biosversion)) || 5012 (pSiS->SiS_Pr->UseROM && 5013 (!strncmp(SiS_customttable[i].biosversion, (char *)&pSiS->BIOS[bversptr], 5014 strlen(SiS_customttable[i].biosversion))))) && 5015 ((!strlen(SiS_customttable[i].biosdate)) || 5016 (pSiS->SiS_Pr->UseROM && 5017 (!strncmp(SiS_customttable[i].biosdate, (char *)&pSiS->BIOS[0x2c], 5018 strlen(SiS_customttable[i].biosdate))))) && 5019 ((!SiS_customttable[i].bioschksum) || 5020 (pSiS->SiS_Pr->UseROM && 5021 (SiS_customttable[i].bioschksum == chksum))) && 5022 (SiS_customttable[i].pcisubsysvendor == PCI_SUB_VENDOR_ID(pSiS->PciInfo)) && 5023 (SiS_customttable[i].pcisubsyscard == PCI_SUB_DEVICE_ID(pSiS->PciInfo)) ) { 5024 footprint = TRUE; 5025 for(j=0; j<5; j++) { 5026 if(SiS_customttable[i].biosFootprintAddr[j]) { 5027 if(pSiS->SiS_Pr->UseROM) { 5028 if(pSiS->BIOS[SiS_customttable[i].biosFootprintAddr[j]] != 5029 SiS_customttable[i].biosFootprintData[j]) 5030 footprint = FALSE; 5031 } else footprint = FALSE; 5032 } 5033 } 5034 if(footprint) { 5035 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5036 "Identified %s %s, special timing applies\n", 5037 SiS_customttable[i].vendorName, SiS_customttable[i].cardName); 5038 pSiS->SiS_Pr->SiS_CustomT = SiS_customttable[i].SpecialID; 5039 break; 5040 } 5041 } 5042 i++; 5043 } while(SiS_customttable[i].chipID); 5044 } 5045 5046 /* Handle ForceCRT1 option */ 5047 if(pSiS->forceCRT1 != -1) { 5048 if(pSiS->forceCRT1) pSiS->CRT1off = 0; 5049 else pSiS->CRT1off = 1; 5050 } else pSiS->CRT1off = -1; 5051 5052 /* Detect video bridge and sense TV/VGA2 */ 5053 SISVGAPreInit(pScrn); 5054 5055 /* Detect CRT1 (via DDC1 and DDC2, hence via VGA port; regardless of LCDA) */ 5056 SISCRT1PreInit(pScrn); 5057 5058 /* Detect LCD (connected via CRT2, regardless of LCDA) and LCD resolution */ 5059 SISLCDPreInit(pScrn, FALSE); 5060 5061 /* LCDA only supported under these conditions: */ 5062 if(pSiS->ForceCRT1Type == CRT1_LCDA) { 5063 if(!SISDetermineLCDACap(pScrn)) { 5064 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5065 "Chipset/Video bridge does not support LCD-via-CRT1\n"); 5066 pSiS->ForceCRT1Type = CRT1_VGA; 5067 } else if(!(pSiS->VBFlags & CRT2_LCD)) { 5068 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5069 "No digital LCD panel found, LCD-via-CRT1 disabled\n"); 5070 pSiS->ForceCRT1Type = CRT1_VGA; 5071 } 5072 } 5073 5074 /* Setup SD flags */ 5075 pSiS->SiS_SD_Flags |= SiS_SD_ADDLSUPFLAG; 5076 5077 pSiS->SiS_SD2_Flags |= SiS_SD2_MERGEDUCLOCK; 5078 pSiS->SiS_SD2_Flags |= SiS_SD2_USEVBFLAGS2; 5079 pSiS->SiS_SD2_Flags |= SiS_SD2_VBINVB2ONLY; 5080 pSiS->SiS_SD2_Flags |= SiS_SD2_HAVESD34; 5081 pSiS->SiS_SD2_Flags |= SiS_SD2_NEWGAMMABRICON; 5082 5083 pSiS->SiS_SD3_Flags |= SiS_SD3_MFBALLOWOFFCL; 5084 5085 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 5086 pSiS->SiS_SD2_Flags |= SiS_SD2_VIDEOBRIDGE; 5087 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 5088 pSiS->SiS_SD2_Flags |= ( SiS_SD2_SISBRIDGE | 5089 SiS_SD2_SUPPORTGAMMA2 ); 5090 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) { 5091 pSiS->SiS_SD2_Flags |= ( SiS_SD2_LCDLVDS | 5092 SiS_SD2_SUPPORTLCD ); 5093 } else if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 5094 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 5095 pSiS->SiS_SD2_Flags |= ( SiS_SD2_LCDTMDS | 5096 SiS_SD2_SUPPORTLCD ); 5097 } else if(pSiS->VBFlags & CRT2_LCD) { 5098 pSiS->SiS_SD2_Flags |= ( SiS_SD2_THIRDPARTYLVDS | 5099 SiS_SD2_SUPPORTLCD ); 5100 } 5101 } 5102 } else if(pSiS->VBFlags2 & VB2_LVDS) { 5103 pSiS->SiS_SD2_Flags |= ( SiS_SD2_THIRDPARTYLVDS | 5104 SiS_SD2_SUPPORTLCD ); 5105 } 5106 5107 if(pSiS->VBFlags2 & (VB2_SISTVBRIDGE | VB2_CHRONTEL)) { 5108 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTTV; 5109 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 5110 pSiS->SiS_SD2_Flags |= ( SiS_SD2_SUPPORTTVTYPE | 5111 SiS_SD2_SUPPORTTVSIZE ); 5112 if(!(pSiS->VBFlags2 & VB2_301)) { 5113 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPTVSAT; 5114 } else { 5115 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPTVEDGE; 5116 } 5117 } 5118 } 5119 } 5120 5121#ifdef ENABLE_YPBPR 5122 if((pSiS->VGAEngine == SIS_315_VGA) && 5123 (pSiS->VBFlags2 & VB2_SISYPBPRBRIDGE)) { 5124 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTYPBPR; 5125 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORT625I; 5126 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORT625P; 5127 if(pSiS->VBFlags2 & VB2_SISYPBPRARBRIDGE) { 5128 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTYPBPRAR; 5129 } 5130 } 5131 if(pSiS->VBFlags2 & VB2_SISHIVISIONBRIDGE) { 5132 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTHIVISION; 5133 } 5134#endif 5135 5136 if((pSiS->VGAEngine != SIS_300_VGA) || (!(pSiS->VBFlags2 & VB2_TRUMPION))) { 5137 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTSCALE; 5138 if((pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && 5139 (!(pSiS->VBFlags2 & VB2_30xBDH))) { 5140 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTCENTER; 5141 } 5142 } 5143 5144#ifdef SISDUALHEAD 5145 if(!pSiS->DualHeadMode) { 5146 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTREDETECT; 5147 } 5148#endif 5149 5150#ifndef SISCHECKOSSSE 5151 pSiS->SiS_SD2_Flags |= SiS_SD2_NEEDUSESSE; 5152#endif 5153 5154#ifdef TWDEBUG /* FOR TESTING */ 5155 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTYPBPRAR; 5156 xf86DrvMsg(0, X_INFO, "TEST: Support Aspect Ratio\n"); 5157#endif 5158 5159 /* Detect CRT2-TV and PAL/NTSC mode */ 5160 SISTVPreInit(pScrn, FALSE); 5161 5162 /* Detect CRT2-VGA */ 5163 SISCRT2PreInit(pScrn, FALSE); 5164 5165 /* Backup detected CRT2 devices */ 5166 SISSaveDetectedDevices(pScrn); 5167 5168 if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR)) { 5169 if((pSiS->ForceTVType != -1) && (pSiS->ForceTVType & TV_YPBPR)) { 5170 pSiS->ForceTVType = -1; 5171 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "YPbPr TV output not supported\n"); 5172 } 5173 } 5174 5175 if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTHIVISION)) { 5176 if((pSiS->ForceTVType != -1) && (pSiS->ForceTVType & TV_HIVISION)) { 5177 pSiS->ForceTVType = -1; 5178 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "HiVision TV output not supported\n"); 5179 } 5180 } 5181 5182 if((pSiS->VBFlags2 & VB2_SISTVBRIDGE) || 5183 ((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->ChrontelType == CHRONTEL_701x))) { 5184 pSiS->SiS_SD_Flags |= (SiS_SD_SUPPORTPALMN | SiS_SD_SUPPORTNTSCJ); 5185 } 5186 if((pSiS->VBFlags2 & VB2_SISTVBRIDGE) || 5187 ((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->ChrontelType == CHRONTEL_700x))) { 5188 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTTVPOS; 5189 } 5190 if(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE) { 5191 pSiS->SiS_SD_Flags |= (SiS_SD_SUPPORTSCART | SiS_SD_SUPPORTVGA2); 5192 } 5193 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 5194 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTOVERSCAN; 5195 pSiS->SiS_SD2_Flags |= SiS_SD2_CHRONTEL; 5196 if(pSiS->ChrontelType == CHRONTEL_700x) { 5197 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTSOVER; 5198 } 5199 } 5200 5201 /* Determine if chipset LCDA-capable */ 5202 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTLCDA; 5203 if(SISDetermineLCDACap(pScrn)) { 5204 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTLCDA; 5205 } 5206 5207 /* Default to LCDA if LCD detected and 5208 * - TV detected (hence default to LCDA+TV), or 5209 * - in single head mode, on LCD panels with xres > 1600 5210 * (Don't do this in MergedFB or DHM; LCDA and CRT1/VGA 5211 * are mutually exclusive; if no TV is detected, the 5212 * code below will default to VGA+LCD, so LCD is driven 5213 * via CRT2.) 5214 * (TODO: This might need some modification for the 5215 * 307 bridges, if these are capable of driving 5216 * LCDs > 1600 via channel B) 5217 */ 5218 if((pSiS->SiS_SD_Flags & SiS_SD_SUPPORTLCDA) && 5219 (pSiS->VBFlags & CRT2_LCD) && 5220 (pSiS->SiS_Pr->SiS_CustomT != CUT_UNKNOWNLCD)) { 5221 if((!pSiS->CRT1TypeForced) && (pSiS->ForceCRT2Type == CRT2_DEFAULT)) { 5222 if(pSiS->VBFlags & CRT2_TV) { 5223 /* If both LCD and TV present, default to LCDA+TV */ 5224 pSiS->ForceCRT1Type = CRT1_LCDA; 5225 pSiS->ForceCRT2Type = CRT2_TV; 5226 } else if(pSiS->LCDwidth > 1600) { 5227 /* If LCD is > 1600, default to LCDA if we don't need CRT1/VGA for other head */ 5228 Bool NeedCRT1VGA = FALSE; 5229#ifdef SISDUALHEAD 5230 if(pSiS->DualHeadMode) NeedCRT1VGA = TRUE; 5231#endif 5232#ifdef SISMERGED 5233 if(pSiS->MergedFB && 5234 (!pSiS->MergedFBAuto || pSiS->CRT1Detected)) NeedCRT1VGA = TRUE; 5235#endif 5236 if(!NeedCRT1VGA) { 5237 pSiS->ForceCRT1Type = CRT1_LCDA; 5238 } 5239 } 5240 } 5241 } 5242 5243 /* Set up pseudo-panel if LCDA forced on TMDS bridges */ 5244 if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTLCDA) { 5245 if(pSiS->ForceCRT1Type == CRT1_LCDA) { 5246 if(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE) { 5247 if(!(pSiS->VBLCDFlags)) { 5248 SiSSetupPseudoPanel(pScrn); 5249 pSiS->detectedCRT2Devices |= CRT2_LCD; 5250 } 5251 } else if(!(pSiS->VBLCDFlags)) { 5252 pSiS->ForceCRT1Type = CRT1_VGA; 5253 } 5254 } 5255 } else { 5256 pSiS->ForceCRT1Type = CRT1_VGA; 5257 } 5258 5259 pSiS->VBFlags |= pSiS->ForceCRT1Type; 5260 5261#ifdef TWDEBUG 5262 xf86DrvMsg(0, X_INFO, "SDFlags %lx\n", pSiS->SiS_SD_Flags); 5263#endif 5264 5265 /* Eventually overrule detected CRT2 type 5266 * If no type forced, use the detected devices in the order TV->LCD->VGA2 5267 * Since the Chrontel 7005 sometimes delivers wrong detection results, 5268 * we use a different order on such machines (LCD->TV) 5269 */ 5270 if(pSiS->ForceCRT2Type == CRT2_DEFAULT) { 5271 if((pSiS->VBFlags & CRT2_TV) && (!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VGAEngine == SIS_300_VGA)))) 5272 pSiS->ForceCRT2Type = CRT2_TV; 5273 else if((pSiS->VBFlags & CRT2_LCD) && (pSiS->ForceCRT1Type == CRT1_VGA)) 5274 pSiS->ForceCRT2Type = CRT2_LCD; 5275 else if(pSiS->VBFlags & CRT2_TV) 5276 pSiS->ForceCRT2Type = CRT2_TV; 5277 else if((pSiS->VBFlags & CRT2_VGA) && (pSiS->ForceCRT1Type == CRT1_VGA)) 5278 pSiS->ForceCRT2Type = CRT2_VGA; 5279 } 5280 5281 switch(pSiS->ForceCRT2Type) { 5282 case CRT2_TV: 5283 pSiS->VBFlags &= ~(CRT2_LCD | CRT2_VGA); 5284 if(pSiS->VBFlags2 & (VB2_SISTVBRIDGE | VB2_CHRONTEL)) { 5285 pSiS->VBFlags |= CRT2_TV; 5286 } else { 5287 pSiS->VBFlags &= ~(CRT2_TV); 5288 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 5289 "Hardware does not support TV output\n"); 5290 } 5291 break; 5292 case CRT2_LCD: 5293 pSiS->VBFlags &= ~(CRT2_TV | CRT2_VGA); 5294 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (pSiS->VBLCDFlags)) { 5295 pSiS->VBFlags |= CRT2_LCD; 5296 } else if((pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && (!(pSiS->VBFlags2 & VB2_30xBDH))) { 5297 SiSSetupPseudoPanel(pScrn); 5298 pSiS->detectedCRT2Devices |= CRT2_LCD; 5299 } else { 5300 pSiS->VBFlags &= ~(CRT2_LCD); 5301 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 5302 "Can't force CRT2 to LCD, no LCD detected\n"); 5303 } 5304 break; 5305 case CRT2_VGA: 5306 pSiS->VBFlags &= ~(CRT2_TV | CRT2_LCD); 5307 if(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE) { 5308 pSiS->VBFlags |= CRT2_VGA; 5309 } else { 5310 pSiS->VBFlags &= ~(CRT2_VGA); 5311 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 5312 "Hardware does not support secondary VGA\n"); 5313 } 5314 break; 5315 default: 5316 pSiS->VBFlags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA); 5317 } 5318 5319 /* Setup gamma (the cmap layer needs this to be initialised) */ 5320 /* (Do this after evaluating options) */ 5321 { 5322 Gamma zeros = {0.0, 0.0, 0.0}; 5323 xf86SetGamma(pScrn, zeros); 5324 } 5325 5326#ifdef SISDUALHEAD 5327 if((!pSiS->DualHeadMode) || (pSiS->SecondHead)) { 5328#endif 5329 xf86DrvMsg(pScrn->scrnIndex, pSiS->CRT1gammaGiven ? X_CONFIG : X_INFO, 5330 "%samma correction is %s\n", 5331 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) ? "CRT1 g" : "G", 5332 pSiS->CRT1gamma ? "enabled" : "disabled"); 5333 5334 if((pSiS->VGAEngine == SIS_315_VGA) && 5335 (!(pSiS->NoXvideo)) && 5336 (!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY))) { 5337 xf86DrvMsg(pScrn->scrnIndex, pSiS->XvGammaGiven ? X_CONFIG : X_INFO, 5338 "Separate Xv gamma correction %sis %s\n", 5339 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) ? "for CRT1 " : "", 5340 pSiS->XvGamma ? "enabled" : "disabled"); 5341 if(pSiS->XvGamma) { 5342 xf86DrvMsg(pScrn->scrnIndex, pSiS->XvGammaGiven ? X_CONFIG : X_INFO, 5343 "Xv gamma correction: %.3f %.3f %.3f\n", 5344 (float)((float)pSiS->XvGammaRed / 1000), 5345 (float)((float)pSiS->XvGammaGreen / 1000), 5346 (float)((float)pSiS->XvGammaBlue / 1000)); 5347 if(!pSiS->CRT1gamma) { 5348 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5349 "Xv gamma correction requires %samma correction enabled\n", 5350 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) ? "CRT1 g" : "G"); 5351 } 5352 } 5353 } 5354#ifdef SISDUALHEAD 5355 } 5356#endif 5357 5358#ifdef SISDUALHEAD 5359 if(pSiS->DualHeadMode) pSiS->CRT2SepGamma = FALSE; 5360#endif 5361 5362#ifdef SISDUALHEAD 5363 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) 5364#endif 5365 { 5366 Bool isDH = FALSE; 5367 if(pSiS->CRT2gamma) { 5368 if( ((pSiS->VGAEngine != SIS_300_VGA) && (pSiS->VGAEngine != SIS_315_VGA)) || 5369 (!(pSiS->VBFlags2 & VB2_SISBRIDGE)) ) { 5370 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 5371 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5372 "CRT2 gamma correction not supported by hardware\n"); 5373 } 5374 pSiS->CRT2gamma = pSiS->CRT2SepGamma = FALSE; 5375 } else if((pSiS->VBFlags2 & VB2_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) { 5376 isDH = TRUE; 5377 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5378 "CRT2 gamma correction not supported for LCD\n"); 5379 /* But leave it on, will be caught in LoadPalette */ 5380 } 5381 } 5382 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 5383 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CRT2 gamma correction is %s%s%s\n", 5384 pSiS->CRT2gamma ? "enabled" : "disabled", 5385 isDH ? " (for TV and VGA2) " : "", 5386 pSiS->CRT2SepGamma ? " (separate from CRT1)" : ""); 5387 } 5388 } 5389 5390 /* Eventually overrule TV Type (SVIDEO, COMPOSITE, SCART, HIVISION, YPBPR) */ 5391 if(pSiS->VBFlags2 & VB2_SISTVBRIDGE) { 5392 if(pSiS->ForceTVType != -1) { 5393 pSiS->VBFlags &= ~(TV_INTERFACE); 5394 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) { 5395 pSiS->VBFlags &= ~(TV_CHSCART | TV_CHYPBPR525I); 5396 } 5397 pSiS->VBFlags |= pSiS->ForceTVType; 5398 if(pSiS->VBFlags & TV_YPBPR) { 5399 pSiS->VBFlags &= ~(TV_STANDARD); 5400 pSiS->VBFlags &= ~(TV_YPBPRAR); 5401 pSiS->VBFlags |= pSiS->ForceYPbPrType; 5402 pSiS->VBFlags |= pSiS->ForceYPbPrAR; 5403 } 5404 } 5405 } 5406 5407 /* Handle ForceCRT1 option (part 2) */ 5408 pSiS->CRT1changed = FALSE; 5409 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5410 usScratchCR17 = pSiS->oldCR17; 5411 usScratchCR63 = pSiS->oldCR63; 5412 usScratchSR1F = pSiS->oldSR1F; 5413 usScratchCR32 = pSiS->postVBCR32; 5414 if(pSiS->VESA != 1) { 5415 /* Copy forceCRT1 option to CRT1off if option is given */ 5416#ifdef SISDUALHEAD 5417 /* In DHM, handle this option only for master head, not the slave */ 5418 if( (pSiS->forceCRT1 != -1) && 5419 (!(pSiS->DualHeadMode && pSiS->SecondHead)) ) { 5420#else 5421 if(pSiS->forceCRT1 != -1) { 5422#endif 5423 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5424 "CRT1 detection overruled by ForceCRT1 option\n"); 5425 if(pSiS->forceCRT1) { 5426 pSiS->CRT1off = 0; 5427 if(pSiS->VGAEngine == SIS_300_VGA) { 5428 if(!(usScratchCR17 & 0x80)) pSiS->CRT1changed = TRUE; 5429 } else { 5430 if(usScratchCR63 & 0x40) pSiS->CRT1changed = TRUE; 5431 } 5432 usScratchCR17 |= 0x80; 5433 usScratchCR32 |= 0x20; 5434 usScratchCR63 &= ~0x40; 5435 usScratchSR1F &= ~0xc0; 5436 } else { 5437 if( ! ( (pScrn->bitsPerPixel == 8) && 5438 ( (pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) || 5439 ((pSiS->VBFlags2 & VB2_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) ) ) ) { 5440 pSiS->CRT1off = 1; 5441 if(pSiS->VGAEngine == SIS_300_VGA) { 5442 if(usScratchCR17 & 0x80) pSiS->CRT1changed = TRUE; 5443 } else { 5444 if(!(usScratchCR63 & 0x40)) pSiS->CRT1changed = TRUE; 5445 } 5446 usScratchCR32 &= ~0x20; 5447 /* We must not actually switch off CRT1 before we changed the mode! */ 5448 } 5449 } 5450 /* Here we can write to CR17 even on 315 series as we only ENABLE 5451 * the bit here 5452 */ 5453 outSISIDXREG(SISCR, 0x17, usScratchCR17); 5454 if(pSiS->VGAEngine == SIS_315_VGA) { 5455 outSISIDXREG(SISCR, pSiS->myCR63, usScratchCR63); 5456 } 5457 outSISIDXREG(SISCR, 0x32, usScratchCR32); 5458 if(pSiS->CRT1changed) { 5459 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 5460 usleep(10000); 5461 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 5462 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5463 "CRT1 status changed by ForceCRT1 option\n"); 5464 } 5465 outSISIDXREG(SISSR, 0x1f, usScratchSR1F); 5466 } 5467 } 5468 /* Store the new VB connection register contents for later mode changes */ 5469 pSiS->newCR32 = usScratchCR32; 5470 } 5471 5472 /* Check if CRT1 used (or needed; this eg. if no CRT2 detected) */ 5473 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 5474 5475 /* No CRT2 output? Then we NEED CRT1! 5476 * We also need CRT1 if depth = 8 and bridge=LVDS|301B-DH 5477 */ 5478 if( (!(pSiS->VBFlags & (CRT2_VGA | CRT2_LCD | CRT2_TV))) || 5479 ( (pScrn->bitsPerPixel == 8) && 5480 ( (pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) || 5481 ((pSiS->VBFlags2 & VB2_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) ) ) ) { 5482 pSiS->CRT1off = 0; 5483 } 5484 /* No CRT2 output? Then we can't use Xv on CRT2 */ 5485 if(!(pSiS->VBFlags & (CRT2_VGA | CRT2_LCD | CRT2_TV))) { 5486 pSiS->XvOnCRT2 = FALSE; 5487 } 5488 5489 } else { /* no video bridge? */ 5490 /* Then we NEED CRT1... */ 5491 pSiS->CRT1off = 0; 5492 /* ... and can't use CRT2 for Xv output */ 5493 pSiS->XvOnCRT2 = FALSE; 5494 } 5495 5496 /* LCDA? Then we don't switch off CRT1 */ 5497 if(pSiS->VBFlags & CRT1_LCDA) pSiS->CRT1off = 0; 5498 5499 /* Handle TVStandard option */ 5500 if((pSiS->NonDefaultPAL != -1) || (pSiS->NonDefaultNTSC != -1)) { 5501 if( (!(pSiS->VBFlags2 & VB2_SISTVBRIDGE)) && 5502 (!((pSiS->VBFlags2 & VB2_CHRONTEL)) && (pSiS->ChrontelType == CHRONTEL_701x)) ) { 5503 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5504 "PALM, PALN and NTSCJ not supported on this hardware\n"); 5505 pSiS->NonDefaultPAL = pSiS->NonDefaultNTSC = -1; 5506 pSiS->VBFlags &= ~(TV_PALN | TV_PALM | TV_NTSCJ); 5507 pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTPALMN | SiS_SD_SUPPORTNTSCJ); 5508 } 5509 } 5510 if(pSiS->OptTVStand != -1) { 5511 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5512 if( (!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & (TV_CHSCART | TV_CHYPBPR525I)))) && 5513 (!(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR))) ) { 5514 pSiS->VBFlags &= ~(TV_PAL | TV_NTSC | TV_PALN | TV_PALM | TV_NTSCJ); 5515 if(pSiS->OptTVStand) { 5516 pSiS->VBFlags |= TV_PAL; 5517 if(pSiS->NonDefaultPAL == 1) pSiS->VBFlags |= TV_PALM; 5518 else if(!pSiS->NonDefaultPAL) pSiS->VBFlags |= TV_PALN; 5519 } else { 5520 pSiS->VBFlags |= TV_NTSC; 5521 if(pSiS->NonDefaultNTSC == 1) pSiS->VBFlags |= TV_NTSCJ; 5522 } 5523 } else { 5524 pSiS->OptTVStand = pSiS->NonDefaultPAL = -1; 5525 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5526 "Option TVStandard ignored for YPbPr, HiVision and Chrontel-SCART\n"); 5527 } 5528 } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { 5529 pSiS->SiS6326Flags &= ~SIS6326_TVPAL; 5530 if(pSiS->OptTVStand) pSiS->SiS6326Flags |= SIS6326_TVPAL; 5531 } 5532 } 5533 5534 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5535 /* Default to PAL */ 5536 if(pSiS->VBFlags & (TV_SVIDEO | TV_AVIDEO)) { 5537 if(!(pSiS->VBFlags & (TV_PAL | TV_NTSC))) { 5538 pSiS->VBFlags &= ~(TV_PAL | TV_NTSC | TV_PALN | TV_PALM | TV_NTSCJ); 5539 pSiS->VBFlags |= TV_PAL; 5540 } 5541 } 5542 /* SCART only supported for PAL */ 5543 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && (pSiS->VBFlags & TV_SCART)) { 5544 pSiS->VBFlags &= ~(TV_NTSC | TV_PALN | TV_PALM | TV_NTSCJ); 5545 pSiS->VBFlags |= TV_PAL; 5546 pSiS->OptTVStand = 1; 5547 pSiS->NonDefaultPAL = pSiS->NonDefaultNTSC = -1; 5548 } 5549 } 5550 5551#ifdef SIS_CP 5552 SIS_CP_DRIVER_RECONFIGOPT 5553#endif 5554 5555 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 5556 if(pSiS->sis6326tvplug != -1) { 5557 pSiS->SiS6326Flags &= ~(SIS6326_TVSVIDEO | SIS6326_TVCVBS); 5558 pSiS->SiS6326Flags |= SIS6326_TVDETECTED; 5559 if(pSiS->sis6326tvplug == 1) pSiS->SiS6326Flags |= SIS6326_TVCVBS; 5560 else pSiS->SiS6326Flags |= SIS6326_TVSVIDEO; 5561 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5562 "SiS6326 TV plug type detection overruled by %s\n", 5563 (pSiS->SiS6326Flags & SIS6326_TVCVBS) ? "COMPOSITE" : "SVIDEO"); 5564 } 5565 } 5566 5567 /* Do some checks */ 5568 if(pSiS->OptTVOver != -1) { 5569 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 5570 pSiS->UseCHOverScan = pSiS->OptTVOver; 5571 } else { 5572 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5573 "CHTVOverscan only supported on CHRONTEL 70xx\n"); 5574 pSiS->UseCHOverScan = -1; 5575 } 5576 } else pSiS->UseCHOverScan = -1; 5577 5578 if(pSiS->sistvedgeenhance != -1) { 5579 if(!(pSiS->VBFlags2 & VB2_301)) { 5580 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5581 "SISTVEdgeEnhance only supported on SiS301\n"); 5582 pSiS->sistvedgeenhance = -1; 5583 } 5584 } 5585 if(pSiS->sistvsaturation != -1) { 5586 if(pSiS->VBFlags2 & VB2_301) { 5587 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5588 "SISTVSaturation not supported on SiS301\n"); 5589 pSiS->sistvsaturation = -1; 5590 } 5591 } 5592 5593 /* Do some MergedFB mode initialisation */ 5594#ifdef SISMERGED 5595 if(pSiS->MergedFB) { 5596 pSiS->CRT2pScrn = malloc(sizeof(ScrnInfoRec)); 5597 if(!pSiS->CRT2pScrn) { 5598 SISErrorLog(pScrn, "Failed to allocate memory for 2nd pScrn, %s\n", mergeddisstr); 5599 pSiS->MergedFB = FALSE; 5600 } else { 5601 memcpy(pSiS->CRT2pScrn, pScrn, sizeof(ScrnInfoRec)); 5602 } 5603 } 5604#endif 5605 5606 /* Determine CRT1<>CRT2 mode 5607 * Note: When using VESA or if the bridge is in slavemode, display 5608 * is ALWAYS in MIRROR_MODE! 5609 * This requires extra checks in functions using this flag! 5610 * (see sis_video.c for example) 5611 */ 5612 if(pSiS->VBFlags & DISPTYPE_DISP2) { 5613 if(pSiS->CRT1off) { /* CRT2 only ------------------------------- */ 5614#ifdef SISDUALHEAD 5615 if(pSiS->DualHeadMode) { 5616 SISErrorLog(pScrn, 5617 "CRT1 not detected or forced off. Dual Head mode can't initialize.\n"); 5618 if(pSiSEnt) pSiSEnt->DisableDual = TRUE; 5619 goto my_error_1; 5620 } 5621#endif 5622#ifdef SISMERGED 5623 if(pSiS->MergedFB) { 5624 if(pSiS->MergedFBAuto) { 5625 xf86DrvMsg(pScrn->scrnIndex, X_INFO, mergednocrt1, mergeddisstr); 5626 } else { 5627 SISErrorLog(pScrn, mergednocrt1, mergeddisstr); 5628 } 5629 if(pSiS->CRT2pScrn) free(pSiS->CRT2pScrn); 5630 pSiS->CRT2pScrn = NULL; 5631 pSiS->MergedFB = FALSE; 5632 } 5633#endif 5634 pSiS->VBFlags |= VB_DISPMODE_SINGLE; 5635 /* No CRT1? Then we use the video overlay on CRT2 */ 5636 pSiS->XvOnCRT2 = TRUE; 5637 } else /* CRT1 and CRT2 - mirror or dual head ----- */ 5638#ifdef SISDUALHEAD 5639 if(pSiS->DualHeadMode) { 5640 pSiS->VBFlags |= (VB_DISPMODE_DUAL | DISPTYPE_CRT1); 5641 if(pSiS->VESA != -1) { 5642 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5643 "VESA option not used in Dual Head mode. VESA disabled.\n"); 5644 } 5645 if(pSiSEnt) pSiSEnt->DisableDual = FALSE; 5646 pSiS->VESA = 0; 5647 } else 5648#endif 5649#ifdef SISMERGED 5650 if(pSiS->MergedFB) { 5651 pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_CRT1); 5652 if(pSiS->VESA != -1) { 5653 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5654 "VESA option not used in MergedFB mode. VESA disabled.\n"); 5655 } 5656 pSiS->VESA = 0; 5657 } else 5658#endif 5659 pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_CRT1); 5660 } else { /* CRT1 only ------------------------------- */ 5661#ifdef SISDUALHEAD 5662 if(pSiS->DualHeadMode) { 5663 SISErrorLog(pScrn, 5664 "No CRT2 output selected or no bridge detected. " 5665 "Dual Head mode can't initialize.\n"); 5666 goto my_error_1; 5667 } 5668#endif 5669#ifdef SISMERGED 5670 if(pSiS->MergedFB) { 5671 if(pSiS->MergedFBAuto) { 5672 xf86DrvMsg(pScrn->scrnIndex, X_INFO, mergednocrt2, mergeddisstr); 5673 } else { 5674 SISErrorLog(pScrn, mergednocrt2, mergeddisstr); 5675 } 5676 if(pSiS->CRT2pScrn) free(pSiS->CRT2pScrn); 5677 pSiS->CRT2pScrn = NULL; 5678 pSiS->MergedFB = FALSE; 5679 } 5680#endif 5681 pSiS->VBFlags |= (VB_DISPMODE_SINGLE | DISPTYPE_CRT1); 5682 } 5683 5684 if((pSiS->VGAEngine == SIS_315_VGA) || (pSiS->VGAEngine == SIS_300_VGA)) { 5685 if((!pSiS->NoXvideo) && 5686 (!pSiS->hasTwoOverlays) && 5687 (!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY))) { 5688 xf86DrvMsg(pScrn->scrnIndex, from, 5689 "Using Xv overlay by default on CRT%d\n", 5690 pSiS->XvOnCRT2 ? 2 : 1); 5691 } 5692 } 5693 5694 /* Init ptrs for Save/Restore functions and calc MaxClock */ 5695 SISDACPreInit(pScrn); 5696 5697 /* ********** end of VBFlags setup ********** */ 5698 5699 /* VBFlags are initialized now. Back them up for SlaveMode modes. */ 5700 pSiS->VBFlags_backup = pSiS->VBFlags; 5701 5702 /* Backup CR32,36,37 (in order to write them back after a VT switch) */ 5703 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5704 inSISIDXREG(SISCR,0x32,pSiS->myCR32); 5705 inSISIDXREG(SISCR,0x36,pSiS->myCR36); 5706 inSISIDXREG(SISCR,0x37,pSiS->myCR37); 5707 } 5708 5709 /* Find out about paneldelaycompensation and evaluate option */ 5710#ifdef SISDUALHEAD 5711 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) { 5712#endif 5713 if(pSiS->VGAEngine == SIS_300_VGA) { 5714 5715 if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) { 5716 5717 /* Save the current PDC if the panel is used at the moment. 5718 * This seems by far the safest way to find out about it. 5719 * If the system is using an old version of sisfb, we can't 5720 * trust the pdc register value. If sisfb saved the pdc for 5721 * us, use it. 5722 */ 5723 if(pSiS->sisfbpdc != 0xff) { 5724 pSiS->SiS_Pr->PDC = pSiS->sisfbpdc; 5725 } else { 5726 if(!(pSiS->donttrustpdc)) { 5727 UChar tmp; 5728 inSISIDXREG(SISCR, 0x30, tmp); 5729 if(tmp & 0x20) { 5730 inSISIDXREG(SISPART1, 0x13, pSiS->SiS_Pr->PDC); 5731 } else { 5732 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5733 "Unable to detect LCD PanelDelayCompensation, LCD is not active\n"); 5734 } 5735 } else { 5736 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5737 "Unable to detect LCD PanelDelayCompensation, please update sisfb\n"); 5738 } 5739 } 5740 if(pSiS->SiS_Pr->PDC != -1) { 5741 pSiS->SiS_Pr->PDC &= 0x3c; 5742 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5743 "Detected LCD PanelDelayCompensation 0x%02x\n", 5744 pSiS->SiS_Pr->PDC); 5745 } 5746 5747 /* If we haven't been able to find out, use our other methods */ 5748 if(pSiS->SiS_Pr->PDC == -1) { 5749 int i=0; 5750 do { 5751 if(mypdctable[i].subsysVendor == PCI_SUB_VENDOR_ID(pSiS->PciInfo) && 5752 mypdctable[i].subsysCard == PCI_SUB_DEVICE_ID(pSiS->PciInfo)) { 5753 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5754 "PCI card/vendor identified for non-default PanelDelayCompensation\n"); 5755 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5756 "Vendor: %s, card: %s (ID %04x), PanelDelayCompensation: 0x%02x\n", 5757 mypdctable[i].vendorName, mypdctable[i].cardName, 5758 PCI_SUB_DEVICE_ID(pSiS->PciInfo), mypdctable[i].pdc); 5759 if(pSiS->PDC == -1) { 5760 pSiS->PDC = mypdctable[i].pdc; 5761 } else { 5762 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5763 "PanelDelayCompensation overruled by option\n"); 5764 } 5765 break; 5766 } 5767 i++; 5768 } while(mypdctable[i].subsysVendor != 0); 5769 } 5770 5771 if(pSiS->PDC != -1) { 5772 if(pSiS->BIOS) { 5773 if(pSiS->VBFlags2 & VB2_LVDS) { 5774 if(pSiS->BIOS[0x220] & 0x80) { 5775 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5776 "BIOS uses OEM LCD Panel Delay Compensation 0x%02x\n", 5777 pSiS->BIOS[0x220] & 0x3c); 5778 pSiS->BIOS[0x220] &= 0x7f; 5779 } 5780 } 5781 if(pSiS->VBFlags2 & (VB2_301B | VB2_302B)) { 5782 if(pSiS->BIOS[0x220] & 0x80) { 5783 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5784 "BIOS uses OEM LCD Panel Delay Compensation 0x%02x\n", 5785 ( (pSiS->VBLCDFlags & VB_LCD_1280x1024) ? 5786 pSiS->BIOS[0x223] : pSiS->BIOS[0x224] ) & 0x3c); 5787 pSiS->BIOS[0x220] &= 0x7f; 5788 } 5789 } 5790 } 5791 pSiS->SiS_Pr->PDC = (pSiS->PDC & 0x3c); 5792 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5793 "Using LCD Panel Delay Compensation 0x%02x\n", pSiS->SiS_Pr->PDC); 5794 } 5795 } 5796 5797 } /* SIS_300_VGA */ 5798 5799 if(pSiS->VGAEngine == SIS_315_VGA) { 5800 5801 UChar tmp, tmp2; 5802 inSISIDXREG(SISCR, 0x30, tmp); 5803 5804 /* Save the current PDC if the panel is used at the moment. */ 5805 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) { 5806 5807 if(pSiS->sisfbpdc != 0xff) { 5808 pSiS->SiS_Pr->PDC = pSiS->sisfbpdc; 5809 } 5810 if(pSiS->sisfbpdca != 0xff) { 5811 pSiS->SiS_Pr->PDCA = pSiS->sisfbpdca; 5812 } 5813 5814 if(!pSiS->donttrustpdc) { 5815 if((pSiS->sisfbpdc == 0xff) && (pSiS->sisfbpdca == 0xff)) { 5816 CARD16 tempa, tempb; 5817 inSISIDXREG(SISPART1,0x2d,tmp2); 5818 tempa = (tmp2 & 0xf0) >> 3; 5819 tempb = (tmp2 & 0x0f) << 1; 5820 inSISIDXREG(SISPART1,0x20,tmp2); 5821 tempa |= ((tmp2 & 0x40) >> 6); 5822 inSISIDXREG(SISPART1,0x35,tmp2); 5823 tempb |= ((tmp2 & 0x80) >> 7); 5824 inSISIDXREG(SISPART1,0x13,tmp2); 5825 if(!pSiS->ROM661New) { 5826 if((tmp2 & 0x04) || (tmp & 0x20)) { 5827 pSiS->SiS_Pr->PDCA = tempa; 5828 pSiS->SiS_Pr->PDC = tempb; 5829 } else { 5830 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5831 "Unable to detect PanelDelayCompensation, LCD is not active\n"); 5832 } 5833 } else { 5834 if(tmp2 & 0x04) { 5835 pSiS->SiS_Pr->PDCA = tempa; 5836 } else if(tmp & 0x20) { 5837 pSiS->SiS_Pr->PDC = tempb; 5838 } else { 5839 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5840 "Unable to detect PanelDelayCompensation, LCD is not active\n"); 5841 } 5842 } 5843 } 5844 } else { 5845 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5846 "Unable to detect PanelDelayCompensation, please update sisfb\n"); 5847 } 5848 if(pSiS->SiS_Pr->PDC != -1) { 5849 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5850 "Detected LCD PanelDelayCompensation 0x%02x (for LCD=CRT2)\n", 5851 pSiS->SiS_Pr->PDC); 5852 } 5853 if(pSiS->SiS_Pr->PDCA != -1) { 5854 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5855 "Detected LCD PanelDelayCompensation1 0x%02x (for LCD=CRT1)\n", 5856 pSiS->SiS_Pr->PDCA); 5857 } 5858 } 5859 5860 /* Let user override (for all bridges) */ 5861 if(pSiS->VBFlags2 & VB2_30xBLV) { 5862 if(pSiS->PDC != -1) { 5863 pSiS->SiS_Pr->PDC = pSiS->PDC & 0x1f; 5864 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5865 "Using LCD PanelDelayCompensation 0x%02x (for LCD=CRT2)\n", 5866 pSiS->SiS_Pr->PDC); 5867 } 5868 if(pSiS->PDCA != -1) { 5869 pSiS->SiS_Pr->PDCA = pSiS->PDCA & 0x1f; 5870 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5871 "Using LCD PanelDelayCompensation1 0x%02x (for LCD=CRT1)\n", 5872 pSiS->SiS_Pr->PDCA); 5873 } 5874 } 5875 5876 /* Read the current EMI (if not overruled) */ 5877 if(pSiS->VBFlags2 & VB2_SISEMIBRIDGE) { 5878 MessageType from = X_PROBED; 5879 if(pSiS->EMI != -1) { 5880 pSiS->SiS_Pr->EMI_30 = (pSiS->EMI >> 24) & 0x60; 5881 pSiS->SiS_Pr->EMI_31 = (pSiS->EMI >> 16) & 0xff; 5882 pSiS->SiS_Pr->EMI_32 = (pSiS->EMI >> 8) & 0xff; 5883 pSiS->SiS_Pr->EMI_33 = pSiS->EMI & 0xff; 5884 pSiS->SiS_Pr->HaveEMI = pSiS->SiS_Pr->HaveEMILCD = TRUE; 5885 pSiS->SiS_Pr->OverruleEMI = TRUE; 5886 from = X_CONFIG; 5887 } else if((pSiS->sisfbfound) && (pSiS->sisfb_haveemi)) { 5888 pSiS->SiS_Pr->EMI_30 = pSiS->sisfb_emi30; 5889 pSiS->SiS_Pr->EMI_31 = pSiS->sisfb_emi31; 5890 pSiS->SiS_Pr->EMI_32 = pSiS->sisfb_emi32; 5891 pSiS->SiS_Pr->EMI_33 = pSiS->sisfb_emi33; 5892 pSiS->SiS_Pr->HaveEMI = TRUE; 5893 if(pSiS->sisfb_haveemilcd) pSiS->SiS_Pr->HaveEMILCD = TRUE; 5894 pSiS->SiS_Pr->OverruleEMI = FALSE; 5895 } else { 5896 inSISIDXREG(SISPART4, 0x30, pSiS->SiS_Pr->EMI_30); 5897 inSISIDXREG(SISPART4, 0x31, pSiS->SiS_Pr->EMI_31); 5898 inSISIDXREG(SISPART4, 0x32, pSiS->SiS_Pr->EMI_32); 5899 inSISIDXREG(SISPART4, 0x33, pSiS->SiS_Pr->EMI_33); 5900 pSiS->SiS_Pr->HaveEMI = TRUE; 5901 if(tmp & 0x20) pSiS->SiS_Pr->HaveEMILCD = TRUE; 5902 pSiS->SiS_Pr->OverruleEMI = FALSE; 5903 } 5904 xf86DrvMsg(pScrn->scrnIndex, from, 5905 "302LV/302ELV: Using EMI 0x%02x%02x%02x%02x%s\n", 5906 pSiS->SiS_Pr->EMI_30,pSiS->SiS_Pr->EMI_31, 5907 pSiS->SiS_Pr->EMI_32,pSiS->SiS_Pr->EMI_33, 5908 pSiS->SiS_Pr->HaveEMILCD ? " (LCD)" : ""); 5909 } 5910 5911 } /* SIS_315_VGA */ 5912#ifdef SISDUALHEAD 5913 } 5914#endif 5915 5916 5917 /* In dual head mode, both heads (currently) share the maxxfbmem equally. 5918 * If memory sharing is done differently, the following has to be changed; 5919 * the other modules (eg. accel and Xv) use dhmOffset for hardware 5920 * pointer settings relative to VideoRAM start and won't need to be changed. 5921 * 5922 * Addendum: dhmoffset is also used for skipping the UMA area on SiS76x. 5923 */ 5924 5925 pSiS->dhmOffset = pSiS->FbBaseOffset; 5926 pSiS->FbAddress += pSiS->dhmOffset; 5927 5928#ifdef SISDUALHEAD 5929 if(pSiS->DualHeadMode) { 5930 pSiS->FbAddress = pSiS->realFbAddress; 5931 if(!pSiS->SecondHead) { 5932 /* ===== First head (always CRT2) ===== */ 5933 /* We use only half of the memory available */ 5934 pSiS->maxxfbmem /= 2; 5935 /* dhmOffset is 0 (or LFB-base for SiS76x UMA skipping) */ 5936 pSiS->FbAddress += pSiS->dhmOffset; 5937 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5938 "%dKB video RAM at 0x%lx available for master head (CRT2)\n", 5939 pSiS->maxxfbmem/1024, pSiS->FbAddress); 5940 } else { 5941 /* ===== Second head (always CRT1) ===== */ 5942 /* We use only half of the memory available */ 5943 pSiS->maxxfbmem /= 2; 5944 /* Initialize dhmOffset */ 5945 pSiS->dhmOffset += pSiS->maxxfbmem; 5946 /* Adapt FBAddress */ 5947 pSiS->FbAddress += pSiS->dhmOffset; 5948 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5949 "%dKB video RAM at 0x%lx available for slave head (CRT1)\n", 5950 pSiS->maxxfbmem/1024, pSiS->FbAddress); 5951 } 5952 } 5953#endif 5954 5955 /* Note: Do not use availMem for anything from now. Use 5956 * maxxfbmem instead. (availMem does not take dual head 5957 * mode into account.) 5958 */ 5959 5960 if(pSiS->FbBaseOffset) { 5961 /* Doubt that the DRM memory manager can deal 5962 * with a heap start of 0... 5963 */ 5964 pSiS->DRIheapstart = 16; 5965 pSiS->DRIheapend = pSiS->FbBaseOffset; 5966 } else { 5967 pSiS->DRIheapstart = pSiS->maxxfbmem; 5968 pSiS->DRIheapend = pSiS->availMem; 5969 } 5970#ifdef SISDUALHEAD 5971 if(pSiS->DualHeadMode) { 5972 pSiS->DRIheapstart = pSiS->DRIheapend = 0; 5973 } else 5974#endif 5975 if(pSiS->DRIheapstart >= pSiS->DRIheapend) { 5976#if 0 /* For future use */ 5977 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5978 "No memory for DRI heap. Please set the option \"MaxXFBMem\" to\n" 5979 "\tlimit the memory X should use and leave the rest to DRI\n"); 5980#endif 5981 pSiS->DRIheapstart = pSiS->DRIheapend = 0; 5982 } 5983 5984 /* Now for something completely different: DDC. 5985 * For 300 and 315/330/340 series, we provide our 5986 * own functions (in order to probe CRT2 as well) 5987 * If these fail, use the VBE. 5988 * All other chipsets will use VBE. No need to re-invent 5989 * the wheel there. 5990 */ 5991 5992 pSiS->pVbe = NULL; 5993 didddc2 = FALSE; 5994 5995 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5996 if(xf86LoadSubModule(pScrn, "ddc")) { 5997 int crtnum = 0; 5998 if((pMonitor = SiSDoPrivateDDC(pScrn, &crtnum))) { 5999 didddc2 = TRUE; 6000 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcsstr, crtnum); 6001 xf86PrintEDID(pMonitor); 6002 xf86SetDDCproperties(pScrn, pMonitor); 6003 pScrn->monitor->DDC = pMonitor; 6004 /* Now try to find out aspect ratio */ 6005 SiSFindAspect(pScrn, pMonitor, crtnum); 6006 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcestr, crtnum); 6007 } 6008 } 6009 } 6010 6011#ifdef SISDUALHEAD 6012 /* In dual head mode, probe DDC using VBE only for CRT1 (second head) */ 6013 if((pSiS->DualHeadMode) && (!didddc2) && (!pSiS->SecondHead)) { 6014 didddc2 = TRUE; 6015 } 6016#endif 6017 6018 if(!didddc2) { 6019 /* If CRT1 is off or LCDA, skip DDC via VBE */ 6020 if((pSiS->CRT1off) || (pSiS->VBFlags & CRT1_LCDA)) { 6021 didddc2 = TRUE; 6022 } 6023 } 6024 6025 /* Now (re-)load and initialize the DDC module */ 6026 if(!didddc2) { 6027 6028 if(xf86LoadSubModule(pScrn, "ddc")) { 6029 6030 /* Now load and initialize VBE module. */ 6031 SiS_LoadInitVBE(pScrn); 6032 6033 if(pSiS->pVbe) { 6034 if((pMonitor = vbeDoEDID(pSiS->pVbe,NULL))) { 6035 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 6036 "VBE CRT1 DDC monitor info:\n"); 6037 xf86SetDDCproperties(pScrn, xf86PrintEDID(pMonitor)); 6038 pScrn->monitor->DDC = pMonitor; 6039 /* Now try to find out aspect ratio */ 6040 SiSFindAspect(pScrn, pMonitor, 1); 6041 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 6042 "End of VBE CRT1 DDC monitor info\n"); 6043 } 6044 } else { 6045 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6046 "Failed to read DDC data\n"); 6047 } 6048 } 6049 } 6050 6051#ifdef SISMERGED 6052 if(pSiS->MergedFB) { 6053 pSiS->CRT2pScrn->monitor = malloc(sizeof(MonRec)); 6054 if(pSiS->CRT2pScrn->monitor) { 6055 DisplayModePtr tempm = NULL, currentm = NULL, newm = NULL; 6056 memcpy(pSiS->CRT2pScrn->monitor, pScrn->monitor, sizeof(MonRec)); 6057 pSiS->CRT2pScrn->monitor->DDC = NULL; 6058 pSiS->CRT2pScrn->monitor->Modes = NULL; 6059 pSiS->CRT2pScrn->monitor->id = (char *)crt2monname; 6060 tempm = pScrn->monitor->Modes; 6061 while(tempm) { 6062 if(!(newm = malloc(sizeof(DisplayModeRec)))) break; 6063 memcpy(newm, tempm, sizeof(DisplayModeRec)); 6064 if(!(newm->name = malloc(strlen(tempm->name) + 1))) { 6065 free(newm); 6066 break; 6067 } 6068 strcpy(newm->name, tempm->name); 6069 if(!pSiS->CRT2pScrn->monitor->Modes) pSiS->CRT2pScrn->monitor->Modes = newm; 6070 if(currentm) { 6071 currentm->next = newm; 6072 newm->prev = currentm; 6073 } 6074 currentm = newm; 6075 tempm = tempm->next; 6076 } 6077 if(pSiS->CRT2HSync) { 6078 pSiS->CRT2pScrn->monitor->nHsync = 6079 SiSStrToRanges(pSiS->CRT2pScrn->monitor->hsync, pSiS->CRT2HSync, MAX_HSYNC); 6080 } 6081 if(pSiS->CRT2VRefresh) { 6082 pSiS->CRT2pScrn->monitor->nVrefresh = 6083 SiSStrToRanges(pSiS->CRT2pScrn->monitor->vrefresh, pSiS->CRT2VRefresh, MAX_VREFRESH); 6084 } 6085 if((pMonitor = SiSInternalDDC(pSiS->CRT2pScrn, 1))) { 6086 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcsstr, 2); 6087 xf86PrintEDID(pMonitor); 6088 xf86SetDDCproperties(pSiS->CRT2pScrn, pMonitor); 6089 pSiS->CRT2pScrn->monitor->DDC = pMonitor; 6090 /* Now try to find out aspect ratio */ 6091 SiSFindAspect(pScrn, pMonitor, 2); 6092 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcestr, 2); 6093 /* use DDC data if no ranges in config file */ 6094 if(!pSiS->CRT2HSync) { 6095 pSiS->CRT2pScrn->monitor->nHsync = 0; 6096 } 6097 if(!pSiS->CRT2VRefresh) { 6098 pSiS->CRT2pScrn->monitor->nVrefresh = 0; 6099 } 6100 } else { 6101 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 6102 "Failed to read DDC data for CRT2\n"); 6103 } 6104 } else { 6105 SISErrorLog(pScrn, "Failed to allocate memory for CRT2 monitor, %s.\n", 6106 mergeddisstr); 6107 if(pSiS->CRT2pScrn) free(pSiS->CRT2pScrn); 6108 pSiS->CRT2pScrn = NULL; 6109 pSiS->MergedFB = FALSE; 6110 } 6111 } 6112#endif 6113 6114 /* Copy our detected monitor gammas, part 1. Note that device redetection 6115 * is not supported in DHM, so there is no need to do that anytime later. 6116 */ 6117#ifdef SISDUALHEAD 6118 if(pSiS->DualHeadMode) { 6119 if(!pSiS->SecondHead) { 6120 /* CRT2: Got gamma for LCD or VGA2 */ 6121 pSiSEnt->CRT2VGAMonitorGamma = pSiS->CRT2VGAMonitorGamma; 6122 } else { 6123 /* CRT1: Got gamma for LCD or VGA */ 6124 pSiSEnt->CRT1VGAMonitorGamma = pSiS->CRT1VGAMonitorGamma; 6125 } 6126 if(pSiS->CRT2LCDMonitorGamma) pSiSEnt->CRT2LCDMonitorGamma = pSiS->CRT2LCDMonitorGamma; 6127 } 6128#endif 6129 6130 /* end of DDC */ 6131 6132 /* From here, we mainly deal with clocks and modes */ 6133 6134#ifdef SISMERGED 6135 if(pSiS->MergedFB) xf86DrvMsg(pScrn->scrnIndex, X_INFO, crtsetupstr, 1); 6136#endif 6137 6138 /* Set the min pixel clock */ 6139 pSiS->MinClock = 5000; 6140 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 6141 pSiS->MinClock = 10000; 6142 } 6143 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n", 6144 pSiS->MinClock / 1000); 6145 6146 /* If the user has specified ramdac speed in the config 6147 * file, we respect that setting. 6148 */ 6149 from = X_PROBED; 6150 if(pSiS->pEnt->device->dacSpeeds[0]) { 6151 int speed = 0; 6152 switch(pScrn->bitsPerPixel) { 6153 case 8: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP8]; 6154 break; 6155 case 16: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP16]; 6156 break; 6157 case 24: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP24]; 6158 break; 6159 case 32: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP32]; 6160 break; 6161 } 6162 if(speed == 0) pSiS->MaxClock = pSiS->pEnt->device->dacSpeeds[0]; 6163 else pSiS->MaxClock = speed; 6164 from = X_CONFIG; 6165 } 6166 xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n", 6167 pSiS->MaxClock / 1000); 6168 6169 /* 6170 * Setup the ClockRanges, which describe what clock ranges are available, 6171 * and what sort of modes they can be used for. 6172 */ 6173 clockRanges = xnfcalloc(sizeof(ClockRange), 1); 6174 clockRanges->next = NULL; 6175 clockRanges->minClock = pSiS->MinClock; 6176 clockRanges->maxClock = pSiS->MaxClock; 6177 clockRanges->clockIndex = -1; /* programmable */ 6178 clockRanges->interlaceAllowed = TRUE; 6179 clockRanges->doubleScanAllowed = TRUE; 6180 6181 /* 6182 * Since we have lots of built-in modes for 300/315/330/340 series 6183 * with vb support, we replace the given default mode list with our 6184 * own. In case the video bridge is to be used, we only allow other 6185 * modes if 6186 * -) vbtype is 301, 301B, 301C or 302B, and 6187 * -) crt2 device is not TV, and 6188 * -) crt1 is not LCDA, unless bridge is TMDS/LCDA capable (301C) 6189 */ 6190 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 6191 if(!(pSiS->noInternalModes)) { 6192 Bool acceptcustommodes = TRUE; /* Accept user modelines */ 6193 Bool includelcdmodes = TRUE; /* Include modes reported by DDC */ 6194 Bool isfordvi = FALSE; /* Is for digital DVI output */ 6195 Bool fakecrt2modes = FALSE; /* Fake some modes for CRT2 */ 6196 Bool IsForCRT2 = FALSE; 6197 if(pSiS->UseVESA) { 6198 acceptcustommodes = FALSE; 6199 includelcdmodes = FALSE; 6200 } 6201#ifdef SISDUALHEAD /* Dual head is static. Output devices will not change. */ 6202 if(pSiS->DualHeadMode) { 6203 if(!pSiS->SecondHead) { /* CRT2: */ 6204 if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 6205 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 6206 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA))) includelcdmodes = FALSE; 6207 if(pSiS->VBFlags & CRT2_LCD) isfordvi = TRUE; 6208 if(pSiS->VBFlags & CRT2_TV) acceptcustommodes = FALSE; 6209 } else { 6210 if(pSiS->VBFlags & (CRT2_TV|CRT2_LCD)) { 6211 acceptcustommodes = FALSE; 6212 includelcdmodes = FALSE; 6213 fakecrt2modes = TRUE; 6214 } 6215 } 6216 } else { 6217 acceptcustommodes = FALSE; 6218 includelcdmodes = FALSE; 6219 if(pSiS->VBFlags & (CRT2_TV|CRT2_LCD)) { 6220 fakecrt2modes = TRUE; 6221 } 6222 } 6223 clockRanges->interlaceAllowed = FALSE; 6224 IsForCRT2 = TRUE; 6225 } else { /* CRT1: */ 6226 if(pSiS->VBFlags & CRT1_LCDA) { 6227 if(!(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 6228 acceptcustommodes = FALSE; 6229 includelcdmodes = FALSE; 6230 fakecrt2modes = TRUE; 6231 /* Will handle i-lace in mode-switching code */ 6232 } else { 6233 isfordvi = TRUE; 6234 /* Don't allow i-lace modes */ 6235 clockRanges->interlaceAllowed = FALSE; 6236 } 6237 } else { 6238 includelcdmodes = FALSE; 6239 } 6240 } 6241 } else 6242#endif 6243#ifdef SISMERGED /* MergedFB mode is not static. Output devices may change. */ 6244 if(pSiS->MergedFB) { 6245 if(pSiS->VBFlags & CRT1_LCDA) { 6246 if(!(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 6247 acceptcustommodes = FALSE; 6248 includelcdmodes = FALSE; 6249 fakecrt2modes = TRUE; 6250 /* Will handle i-lace in mode-switching code */ 6251 } else { 6252 isfordvi = TRUE; 6253 /* Don't allow i-lace custom modes */ 6254 clockRanges->interlaceAllowed = FALSE; 6255 } 6256 } else { 6257 includelcdmodes = FALSE; 6258 } 6259 } else 6260#endif /* Mirror mode is not static. Output devices may change. */ 6261 if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 6262 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 6263 if(!(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 6264 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA))) includelcdmodes = FALSE; 6265 if(pSiS->VBFlags & CRT2_LCD) isfordvi = TRUE; 6266 } else { 6267 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA|CRT1_LCDA))) includelcdmodes = FALSE; 6268 if(pSiS->VBFlags & (CRT2_LCD|CRT1_LCDA)) isfordvi = TRUE; 6269 } 6270 if((!(pSiS->VBFlags & DISPTYPE_CRT1)) && (!(pSiS->VBFlags & CRT1_LCDA))) { 6271 IsForCRT2 = TRUE; 6272 } 6273 /* Allow user modes, even if CRT2 is TV. Will be filtered through ValidMode(); 6274 * leaving the user modes here might have the advantage that such a mode, if 6275 * it matches in resolution with a supported TV mode, allows us to drive eg. 6276 * non standard panels, and still permits switching to TV. This mode will be 6277 * "mapped" to a supported mode of identical resolution for TV. All this is 6278 * taken care of by ValidMode() and ModeInit()/PresetMode(). 6279 */ 6280 } else { 6281 if(pSiS->VBFlags & (CRT2_TV|CRT2_LCD)) { 6282 acceptcustommodes = FALSE; 6283 includelcdmodes = FALSE; 6284 if(!(pSiS->VBFlags & DISPTYPE_CRT1)) { 6285 fakecrt2modes = TRUE; 6286 IsForCRT2 = TRUE; 6287 } 6288 } 6289 } 6290 } else if(pSiS->VBFlags & (CRT2_ENABLE | CRT1_LCDA)) { 6291 acceptcustommodes = FALSE; 6292 includelcdmodes = FALSE; 6293 if((pSiS->VBFlags & CRT1_LCDA) || (!(pSiS->VBFlags & DISPTYPE_CRT1))) { 6294 fakecrt2modes = TRUE; 6295 IsForCRT2 = TRUE; 6296 } 6297 } else { 6298 includelcdmodes = FALSE; 6299 } 6300 /* Ignore interlace, mode switching code will handle this */ 6301 6302 pSiS->HaveCustomModes = FALSE; 6303 if(SiSMakeOwnModeList(pScrn, acceptcustommodes, includelcdmodes, 6304 isfordvi, &pSiS->HaveCustomModes, FALSE /*fakecrt2modes*/, IsForCRT2)) { 6305 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6306 "Replaced %s mode list with built-in modes\n", 6307 pSiS->HaveCustomModes ? "default" : "entire"); 6308 if(pSiS->VGAEngine == SIS_315_VGA) { 6309 int UseWide = pSiS->SiS_Pr->SiS_UseWide; 6310 if(IsForCRT2) UseWide = pSiS->SiS_Pr->SiS_UseWideCRT2; 6311 if((!IsForCRT2) || (pSiS->VBFlags2 & VB2_SISVGA2BRIDGE)) { 6312 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6313 "Using %s widescreen modes for CRT%d VGA devices\n", 6314 UseWide ? "real" : "fake", IsForCRT2 ? 2 : 1); 6315 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6316 "\tUse option \"ForceCRT%dVGAAspect\" to overrule\n", 6317 IsForCRT2 ? 2 : 1); 6318 } 6319 } 6320#ifdef TWDEBUG 6321 pScrn->modes = pScrn->monitor->Modes; 6322 xf86PrintModes(pScrn); 6323 pScrn->modes = NULL; 6324#endif 6325 } else { 6326 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 6327 "Building list of built-in modes failed, using server defaults\n"); 6328 } 6329 } else { 6330 pSiS->HaveCustomModes = TRUE; 6331 } 6332 } 6333 6334 /* Add our built-in hi-res and TV modes on the 6326 */ 6335 if(pSiS->Chipset == PCI_CHIP_SIS6326) { 6336 if(pScrn->bitsPerPixel == 8) { 6337 SiS6326SIS1600x1200_60Mode.next = pScrn->monitor->Modes; 6338 pScrn->monitor->Modes = &SiS6326SIS1600x1200_60Mode; 6339 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6340 "Adding mode \"SIS1600x1200-60\" (depth 8 only)\n"); 6341 } 6342 if(pScrn->bitsPerPixel <= 16) { 6343 SiS6326SIS1280x1024_75Mode.next = pScrn->monitor->Modes; 6344 pScrn->monitor->Modes = &SiS6326SIS1280x1024_75Mode; 6345 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6346 "Adding mode \"SIS1280x1024-75\" (depths 8, 15 and 16 only)\n"); 6347 } 6348 if((pSiS->SiS6326Flags & SIS6326_HASTV) && 6349 (pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 6350 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6351 "Adding %s TV modes to mode list:\n", 6352 (pSiS->SiS6326Flags & SIS6326_TVPAL) ? "PAL" : "NTSC"); 6353 if(pSiS->SiS6326Flags & SIS6326_TVPAL) { 6354 SiS6326PAL800x600Mode.next = pScrn->monitor->Modes; 6355 pScrn->monitor->Modes = &SiS6326PAL640x480Mode; 6356 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6357 "\t\"PAL800x600\" \"PAL800x600U\" \"PAL720x540\" \"PAL640x480\"\n"); 6358 } else { 6359 SiS6326NTSC640x480Mode.next = pScrn->monitor->Modes; 6360 pScrn->monitor->Modes = &SiS6326NTSC640x400Mode; 6361 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6362 "\t\"NTSC640x480\" \"NTSC640x480U\" \"NTSC640x400\"\n"); 6363 } 6364 } 6365 } 6366 6367 /* If there is no HSync or VRefresh data for the monitor, 6368 * derive it from DDC data. Essentially done by common layer 6369 * since 4.3.99.14, but this is not usable since it is done 6370 * too late (in ValidateModes()). 6371 * Addendum: I overrule the ranges now in any case unless 6372 * it would affect a CRT output device or DDC data is available. 6373 * Hence, for LCD(A) and TV, we always get proper ranges. This 6374 * is entirely harmless. However, option "NoOverruleRanges" will 6375 * disable this behavior. 6376 * This should "fix" the - by far - most common configuration 6377 * mistakes. 6378 */ 6379 6380 crt1freqoverruled = FALSE; 6381 6382 fromDDC = FALSE; 6383 if((pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6384 if((pScrn->monitor->nHsync <= 0) && (pScrn->monitor->DDC)) { 6385 SiSSetSyncRangeFromEdid(pScrn, 1); 6386 if(pScrn->monitor->nHsync > 0) { 6387 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subshstr, 6388#ifdef SISDUALHEAD 6389 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6390#endif 6391 pSiS->CRT1off ? 2 : 1); 6392 fromDDC = TRUE; 6393 } 6394 } 6395 if((pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6396 if(SiSAllowSyncOverride(pSiS, fromDDC)) { 6397 Bool HaveNoRanges = (pScrn->monitor->nHsync <= 0); 6398 /* Set sane ranges for LCD and TV 6399 * (our strict checking will filter out invalid ones anyway) 6400 */ 6401 if((crt1freqoverruled = CheckAndOverruleH(pScrn, pScrn->monitor))) { 6402 xf86DrvMsg(pScrn->scrnIndex, X_INFO, saneh, 6403 HaveNoRanges ? "missing" : "bogus", 6404#ifdef SISDUALHEAD 6405 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6406#endif 6407 pSiS->CRT1off ? 2 : 1); 6408 } 6409 } 6410 } 6411 } 6412 6413 fromDDC = FALSE; 6414 if((pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6415 if((pScrn->monitor->nVrefresh <= 0) && (pScrn->monitor->DDC)) { 6416 SiSSetSyncRangeFromEdid(pScrn, 0); 6417 if(pScrn->monitor->nVrefresh > 0) { 6418 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subsvstr, 6419#ifdef SISDUALHEAD 6420 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6421#endif 6422 pSiS->CRT1off ? 2 : 1); 6423 fromDDC = TRUE; 6424 } 6425 } 6426 if((pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6427 if(SiSAllowSyncOverride(pSiS, fromDDC)) { 6428 Bool HaveNoRanges = (pScrn->monitor->nVrefresh <= 0); 6429 /* Set sane ranges for LCD and TV */ 6430 if((crt1freqoverruled = CheckAndOverruleV(pScrn, pScrn->monitor))) { 6431 xf86DrvMsg(pScrn->scrnIndex, X_INFO, sanev, 6432 HaveNoRanges ? "missing" : "bogus", 6433#ifdef SISDUALHEAD 6434 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6435#endif 6436 pSiS->CRT1off ? 2 : 1); 6437 } 6438 } 6439 } 6440 } 6441 6442 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 6443 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6444 "\"Unknown reason\" in the following list means that the mode\n"); 6445 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6446 "is not supported on the chipset/bridge/current output device.\n"); 6447 } 6448 6449 /* 6450 * xf86ValidateModes will check that the mode HTotal and VTotal values 6451 * don't exceed the chipset's limit if pScrn->maxHValue and 6452 * pScrn->maxVValue are set. Since our SISValidMode() already takes 6453 * care of this, we don't worry about setting them here. 6454 */ 6455 6456 /* Select valid modes from those available */ 6457 /* 6458 * Assuming min pitch 256, min height 128 6459 */ 6460 { 6461 int minpitch, maxpitch, minheight, maxheight; 6462 pointer backupddc = pScrn->monitor->DDC; 6463 6464 minpitch = 256; 6465 minheight = 128; 6466 switch(pSiS->VGAEngine) { 6467 case SIS_OLD_VGA: 6468 case SIS_530_VGA: 6469 maxpitch = 2040; 6470 maxheight = 2048; 6471 break; 6472 case SIS_300_VGA: 6473 case SIS_315_VGA: 6474 maxpitch = 4088; 6475 maxheight = 4096; 6476 break; 6477 default: 6478 maxpitch = 2048; 6479 maxheight = 2048; 6480 break; 6481 } 6482 6483#ifdef SISMERGED 6484 pSiS->CheckForCRT2 = FALSE; 6485#endif 6486 6487 /* Suppress bogus DDC warning */ 6488 if(crt1freqoverruled) pScrn->monitor->DDC = NULL; 6489 6490 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 6491 pScrn->display->modes, clockRanges, NULL, 6492 minpitch, maxpitch, 6493 pScrn->bitsPerPixel * 8, 6494 minheight, maxheight, 6495 pScrn->display->virtualX, 6496 pScrn->display->virtualY, 6497 pSiS->maxxfbmem, 6498 LOOKUP_BEST_REFRESH); 6499 6500 pScrn->monitor->DDC = backupddc; 6501 } 6502 6503 if(i == -1) { 6504 SISErrorLog(pScrn, "xf86ValidateModes() error\n"); 6505 goto my_error_1; 6506 } 6507 6508 /* Check the virtual screen against the available memory */ 6509 { 6510 ULong memreq = (pScrn->virtualX * ((pScrn->bitsPerPixel + 7) / 8)) * pScrn->virtualY; 6511 6512 if(memreq > pSiS->maxxfbmem) { 6513 SISErrorLog(pScrn, 6514 "Virtual screen too big for memory; %ldK needed, %ldK available\n", 6515 memreq/1024, pSiS->maxxfbmem/1024); 6516 goto my_error_1; 6517 } 6518 } 6519 6520 /* Dual Head: 6521 * -) Go through mode list and mark all those modes as bad, 6522 * which are unsuitable for dual head mode. 6523 * -) Find the highest used pixelclock on the master head. 6524 */ 6525#ifdef SISDUALHEAD 6526 if((pSiS->DualHeadMode) && (!pSiS->SecondHead)) { 6527 6528 pSiSEnt->maxUsedClock = 0; 6529 6530 if((p = first = pScrn->modes)) { 6531 6532 do { 6533 6534 n = p->next; 6535 6536 /* Modes that require the bridge to operate in SlaveMode 6537 * are not suitable for Dual Head mode. 6538 */ 6539 if( (pSiS->VGAEngine == SIS_300_VGA) && 6540 ( (strcmp(p->name, "320x200") == 0) || 6541 (strcmp(p->name, "320x240") == 0) || 6542 (strcmp(p->name, "400x300") == 0) || 6543 (strcmp(p->name, "512x384") == 0) || 6544 (strcmp(p->name, "640x400") == 0) ) ) { 6545 p->status = MODE_BAD; 6546 xf86DrvMsg(pScrn->scrnIndex, X_INFO, notsuitablestr, p->name, "dual head"); 6547 } 6548 6549 /* Search for the highest clock on first head in order to calculate 6550 * max clock for second head (CRT1) 6551 */ 6552 if((p->status == MODE_OK) && (p->Clock > pSiSEnt->maxUsedClock)) { 6553 pSiSEnt->maxUsedClock = p->Clock; 6554 } 6555 6556 p = n; 6557 6558 } while (p != NULL && p != first); 6559 6560 } 6561 } 6562#endif 6563 6564 /* Prune the modes marked as invalid */ 6565 xf86PruneDriverModes(pScrn); 6566 6567 if(i == 0 || pScrn->modes == NULL) { 6568 SISErrorLog(pScrn, "No valid modes found - check VertRefresh/HorizSync\n"); 6569 goto my_error_1; 6570 } 6571 6572 xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 6573 6574 /* Set the current mode to the first in the list */ 6575 pScrn->currentMode = pScrn->modes; 6576 6577 /* Copy to CurrentLayout */ 6578 pSiS->CurrentLayout.mode = pScrn->currentMode; 6579 pSiS->CurrentLayout.displayWidth = pScrn->displayWidth; 6580 pSiS->CurrentLayout.displayHeight = pScrn->virtualY; 6581 6582#ifdef SISMERGED 6583 if(pSiS->MergedFB) { 6584 xf86DrvMsg(pScrn->scrnIndex, X_INFO, modesforstr, 1); 6585 } 6586#endif 6587 6588 /* Print the list of modes being used */ 6589 { 6590 Bool usemyprint = FALSE; 6591 6592#ifdef SISDUALHEAD 6593 if(pSiS->DualHeadMode) { 6594 if(pSiS->SecondHead) { 6595 if(pSiS->VBFlags & CRT1_LCDA) usemyprint = TRUE; 6596 } else { 6597 if(pSiS->VBFlags & (CRT2_LCD | CRT2_TV)) usemyprint = TRUE; 6598 } 6599 } else 6600#endif 6601#ifdef SISMERGED 6602 if(pSiS->MergedFB) { 6603 if(pSiS->VBFlags & CRT1_LCDA) usemyprint = TRUE; 6604 } else 6605#endif 6606 { 6607 if( (pSiS->VBFlags & (CRT2_LCD | CRT2_TV)) && 6608 (!(pSiS->VBFlags & DISPTYPE_DISP1)) ) 6609 usemyprint = TRUE; 6610 } 6611 6612 if(usemyprint) { 6613 SiSPrintModes(pScrn); 6614 } else { 6615 xf86PrintModes(pScrn); 6616 } 6617 } 6618 6619#ifdef SISMERGED 6620 if(pSiS->MergedFB) { 6621 Bool acceptcustommodes = TRUE; 6622 Bool includelcdmodes = TRUE; 6623 Bool isfordvi = FALSE; 6624 Bool fakecrt2modes = FALSE; 6625 6626 xf86DrvMsg(pScrn->scrnIndex, X_INFO, crtsetupstr, 2); 6627 6628 clockRanges->next = NULL; 6629 clockRanges->minClock = pSiS->MinClock; 6630 clockRanges->maxClock = SiSMemBandWidth(pSiS->CRT2pScrn, TRUE); 6631 clockRanges->clockIndex = -1; 6632 clockRanges->interlaceAllowed = FALSE; 6633 clockRanges->doubleScanAllowed = FALSE; 6634 if(pSiS->VGAEngine == SIS_315_VGA) { 6635 clockRanges->doubleScanAllowed = TRUE; 6636 } 6637 6638 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock for CRT2 is %d MHz\n", 6639 clockRanges->minClock / 1000); 6640 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Max pixel clock for CRT2 is %d MHz\n", 6641 clockRanges->maxClock / 1000); 6642 6643 if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 6644 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 6645 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA))) includelcdmodes = FALSE; 6646 if(pSiS->VBFlags & CRT2_LCD) isfordvi = TRUE; 6647 /* See above for a remark on handling CRT2 = TV */ 6648 } else { 6649 if(pSiS->VBFlags & (CRT2_LCD|CRT2_TV)) { 6650 includelcdmodes = FALSE; 6651 acceptcustommodes = FALSE; 6652 fakecrt2modes = TRUE; 6653 } 6654 } 6655 } else { 6656 includelcdmodes = FALSE; 6657 acceptcustommodes = FALSE; 6658 if(pSiS->VBFlags & (CRT2_LCD|CRT2_TV)) { 6659 fakecrt2modes = TRUE; 6660 } 6661 } 6662 6663 pSiS->HaveCustomModes2 = FALSE; 6664 if(!SiSMakeOwnModeList(pSiS->CRT2pScrn, acceptcustommodes, includelcdmodes, 6665 isfordvi, &pSiS->HaveCustomModes2, FALSE /* fakecrt2modes */, TRUE )) { 6666 6667 SISErrorLog(pScrn, "Building list of built-in modes for CRT2 failed, %s\n", 6668 mergeddisstr); 6669 SiSFreeCRT2Structs(pSiS); 6670 pSiS->MergedFB = FALSE; 6671 6672 } else { 6673 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6674 "Replaced %s mode list for CRT2 with built-in modes\n", 6675 pSiS->HaveCustomModes2 ? "default" : "entire"); 6676 if((pSiS->VGAEngine == SIS_315_VGA) && (pSiS->VBFlags2 & VB2_SISVGA2BRIDGE)) { 6677 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6678 "Using %s widescreen modes for CRT2 VGA devices\n", 6679 pSiS->SiS_Pr->SiS_UseWideCRT2 ? "real" : "fake"); 6680 } else pSiS->SiS_Pr->SiS_UseWideCRT2 = 0; 6681 } 6682 6683 } 6684 6685 if(pSiS->MergedFB) { 6686 6687 pointer backupddc; 6688 6689 crt2freqoverruled = FALSE; 6690 6691 fromDDC = FALSE; 6692 if((pSiS->CRT2pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6693 if((pSiS->CRT2pScrn->monitor->nHsync <= 0) && (pSiS->CRT2pScrn->monitor->DDC)) { 6694 SiSSetSyncRangeFromEdid(pSiS->CRT2pScrn, 1); 6695 if(pSiS->CRT2pScrn->monitor->nHsync > 0) { 6696 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subshstr, 2); 6697 fromDDC = TRUE; 6698 } 6699 } 6700 if((pSiS->CRT2pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6701 if( (pSiS->VBFlags & CRT2_TV) || 6702 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC)) ) { 6703 Bool HaveNoRanges = (pSiS->CRT2pScrn->monitor->nHsync <= 0); 6704 /* Set sane ranges for LCD and TV */ 6705 if((crt2freqoverruled = CheckAndOverruleH(pScrn, pSiS->CRT2pScrn->monitor))) { 6706 xf86DrvMsg(pScrn->scrnIndex, X_INFO, saneh, 6707 HaveNoRanges ? "missing" : "bogus", 2); 6708 } 6709 } 6710 } 6711 } 6712 6713 fromDDC = FALSE; 6714 if((pSiS->CRT2pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6715 if((pSiS->CRT2pScrn->monitor->nVrefresh <= 0) && (pSiS->CRT2pScrn->monitor->DDC)) { 6716 SiSSetSyncRangeFromEdid(pSiS->CRT2pScrn, 0); 6717 if(pSiS->CRT2pScrn->monitor->nVrefresh > 0) { 6718 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subsvstr, 2); 6719 fromDDC = TRUE; 6720 } 6721 } 6722 if((pSiS->CRT2pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6723 if( (pSiS->VBFlags & CRT2_TV) || 6724 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC)) ) { 6725 Bool HaveNoRanges = (pSiS->CRT2pScrn->monitor->nVrefresh <= 0); 6726 /* Set sane ranges for LCD and TV */ 6727 if((crt2freqoverruled = CheckAndOverruleV(pScrn, pSiS->CRT2pScrn->monitor))) { 6728 xf86DrvMsg(pScrn->scrnIndex, X_INFO, sanev, 6729 HaveNoRanges ? "missing" : "bogus", 2); 6730 } 6731 } 6732 } 6733 } 6734 6735 backupddc = pSiS->CRT2pScrn->monitor->DDC; 6736 6737 /* Suppress bogus DDC warning */ 6738 if(crt2freqoverruled) pSiS->CRT2pScrn->monitor->DDC = NULL; 6739 6740 pSiS->CheckForCRT2 = TRUE; 6741 6742 i = xf86ValidateModes(pSiS->CRT2pScrn, pSiS->CRT2pScrn->monitor->Modes, 6743 pSiS->CRT2pScrn->display->modes, clockRanges, 6744 NULL, 256, 4088, 6745 pSiS->CRT2pScrn->bitsPerPixel * 8, 128, 4096, 6746 pScrn->display->virtualX ? pScrn->virtualX : 0, 6747 pScrn->display->virtualY ? pScrn->virtualY : 0, 6748 pSiS->maxxfbmem, 6749 LOOKUP_BEST_REFRESH); 6750 6751 pSiS->CheckForCRT2 = FALSE; 6752 pSiS->CRT2pScrn->monitor->DDC = backupddc; 6753 6754 if(i == -1) { 6755 SISErrorLog(pScrn, "xf86ValidateModes() error, %s.\n", mergeddisstr); 6756 SiSFreeCRT2Structs(pSiS); 6757 pSiS->MergedFB = FALSE; 6758 } 6759 6760 } 6761 6762 if(pSiS->MergedFB) { 6763 6764 if((p = first = pSiS->CRT2pScrn->modes)) { 6765 do { 6766 n = p->next; 6767 if( (pSiS->VGAEngine == SIS_300_VGA) && 6768 ( (strcmp(p->name, "320x200") == 0) || 6769 (strcmp(p->name, "320x240") == 0) || 6770 (strcmp(p->name, "400x300") == 0) || 6771 (strcmp(p->name, "512x384") == 0) || 6772 (strcmp(p->name, "640x400") == 0) ) ) { 6773 p->status = MODE_BAD; 6774 xf86DrvMsg(pScrn->scrnIndex, X_INFO, notsuitablestr, p->name, "MergedFB"); 6775 } 6776 p = n; 6777 } while (p != NULL && p != first); 6778 } 6779 6780 xf86PruneDriverModes(pSiS->CRT2pScrn); 6781 6782 if(i == 0 || pSiS->CRT2pScrn->modes == NULL) { 6783 SISErrorLog(pScrn, "No valid modes found for CRT2; %s\n", mergeddisstr); 6784 SiSFreeCRT2Structs(pSiS); 6785 pSiS->MergedFB = FALSE; 6786 } 6787 6788 } 6789 6790 if(pSiS->MergedFB) { 6791 6792 xf86SetCrtcForModes(pSiS->CRT2pScrn, INTERLACE_HALVE_V); 6793 6794 xf86DrvMsg(pScrn->scrnIndex, X_INFO, modesforstr, 2); 6795 6796 if(pSiS->VBFlags & (CRT2_LCD | CRT2_TV)) { 6797 SiSPrintModes(pSiS->CRT2pScrn); 6798 } else { 6799 xf86PrintModes(pSiS->CRT2pScrn); 6800 } 6801 6802 pSiS->CRT1Modes = pScrn->modes; 6803 pSiS->CRT1CurrentMode = pScrn->currentMode; 6804 6805 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MergedFB: Generating mode list\n"); 6806 6807 pScrn->modes = SiSGenerateModeList(pScrn, pSiS->MetaModes, 6808 pSiS->CRT1Modes, pSiS->CRT2pScrn->modes, 6809 pSiS->CRT2Position); 6810 6811 if(!pScrn->modes) { 6812 6813 SISErrorLog(pScrn, "Failed to parse MetaModes or no modes found. %s.\n", 6814 mergeddisstr); 6815 SiSFreeCRT2Structs(pSiS); 6816 pScrn->modes = pSiS->CRT1Modes; 6817 pSiS->CRT1Modes = NULL; 6818 pSiS->MergedFB = FALSE; 6819 6820 } 6821 6822 } 6823 6824 if(pSiS->MergedFB) { 6825 6826 /* If no virtual dimension was given by the user, 6827 * calculate a sane one now. Adapts pScrn->virtualX, 6828 * pScrn->virtualY and pScrn->displayWidth. 6829 */ 6830 SiSRecalcDefaultVirtualSize(pScrn); 6831 6832 pScrn->modes = pScrn->modes->next; /* We get the last from GenerateModeList(), skip to first */ 6833 pScrn->currentMode = pScrn->modes; 6834 6835 /* Update CurrentLayout */ 6836 pSiS->CurrentLayout.mode = pScrn->currentMode; 6837 pSiS->CurrentLayout.displayWidth = pScrn->displayWidth; 6838 pSiS->CurrentLayout.displayHeight = pScrn->virtualY; 6839 6840 } 6841#endif 6842 6843 /* Set display resolution */ 6844#ifdef SISMERGED 6845 if(pSiS->MergedFB) { 6846 SiSMergedFBSetDpi(pScrn, pSiS->CRT2pScrn, pSiS->CRT2Position); 6847 } else 6848#endif 6849 xf86SetDpi(pScrn, 0, 0); 6850 6851 /* Load fb module */ 6852 switch(pScrn->bitsPerPixel) { 6853 case 8: 6854 case 16: 6855 case 24: 6856 case 32: 6857 if(!xf86LoadSubModule(pScrn, "fb")) { 6858 SISErrorLog(pScrn, "Failed to load fb module"); 6859 goto my_error_1; 6860 } 6861 break; 6862 default: 6863 SISErrorLog(pScrn, "Unsupported framebuffer bpp (%d)\n", pScrn->bitsPerPixel); 6864 goto my_error_1; 6865 } 6866 6867 /* Load XAA/EXA (if needed) */ 6868 if(!pSiS->NoAccel) { 6869#ifdef SIS_USE_XAA 6870 if(!pSiS->useEXA) { 6871 if (!xf86LoadSubModule(pScrn, "xaa")) { 6872 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6873 "Falling back to shadowfb\n"); 6874 pSiS->NoAccel = 1; 6875 pSiS->ShadowFB = 1; 6876 } 6877 } 6878#endif 6879#ifdef SIS_USE_EXA 6880 if(pSiS->useEXA) { 6881 XF86ModReqInfo req; 6882 int errmaj, errmin; 6883 6884 memset(&req, 0, sizeof(req)); 6885 req.majorversion = 2; 6886 req.minorversion = 0; 6887 if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, &req, 6888 &errmaj, &errmin)) { 6889 LoaderErrorMsg(NULL, "exa", errmaj, errmin); 6890 goto my_error_1; 6891 } 6892 } 6893#endif 6894 } 6895 6896 /* Load shadowfb (if needed) */ 6897 if(pSiS->ShadowFB) { 6898 if(!xf86LoadSubModule(pScrn, "shadowfb")) { 6899 SISErrorLog(pScrn, "Could not load shadowfb module\n"); 6900 goto my_error_1; 6901 } 6902 } 6903 6904 /* Load the dri and glx modules if requested. */ 6905#ifdef SISDRI 6906 if(pSiS->loadDRI) { 6907 if(!xf86LoaderCheckSymbol("DRIScreenInit")) { 6908 if(xf86LoadSubModule(pScrn, "dri")) { 6909 if(!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) { 6910 if(!xf86LoadSubModule(pScrn, "glx")) { 6911 SISErrorLog(pScrn, "Failed to load glx module\n"); 6912 } 6913 } 6914 } else { 6915 SISErrorLog(pScrn, "Failed to load dri module\n"); 6916 } 6917 } 6918 } 6919#endif 6920 6921 /* Now load and initialize VBE module for VESA mode switching */ 6922 pSiS->UseVESA = 0; 6923 if(pSiS->VESA == 1) { 6924 SiS_LoadInitVBE(pScrn); 6925 if(pSiS->pVbe) { 6926 VbeInfoBlock *vbe; 6927 if((vbe = VBEGetVBEInfo(pSiS->pVbe))) { 6928 pSiS->vesamajor = (unsigned)(vbe->VESAVersion >> 8); 6929 pSiS->vesaminor = vbe->VESAVersion & 0xff; 6930 SiSBuildVesaModeList(pScrn, pSiS->pVbe, vbe); 6931 VBEFreeVBEInfo(vbe); 6932 pSiS->UseVESA = 1; 6933 } else { 6934 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 6935 "Failed to read VBE Info Block\n"); 6936 } 6937 } 6938 if(pSiS->UseVESA == 0) { 6939 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 6940 "VESA mode switching disabled.\n"); 6941 } 6942 } 6943 6944 if(pSiS->pVbe) { 6945 vbeFree(pSiS->pVbe); 6946 pSiS->pVbe = NULL; 6947 } 6948 6949#ifdef SISDUALHEAD 6950 xf86SetPrimInitDone(pScrn->entityList[0]); 6951#endif 6952 6953 sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); 6954 6955 if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); 6956 pSiS->pInt = NULL; 6957 6958 if(pSiS->VGAEngine == SIS_315_VGA) { 6959 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTXVGAMMA1; 6960 } 6961 6962#ifdef SISDUALHEAD 6963 if(pSiS->DualHeadMode) { 6964 pSiS->SiS_SD_Flags |= SiS_SD_ISDUALHEAD; 6965 if(pSiS->SecondHead) pSiS->SiS_SD_Flags |= SiS_SD_ISDHSECONDHEAD; 6966 else pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTXVGAMMA1); 6967#ifdef PANORAMIX 6968 if(!noPanoramiXExtension) { 6969 pSiS->SiS_SD_Flags |= SiS_SD_ISDHXINERAMA; 6970 /* pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTXVGAMMA1); */ 6971 } 6972#endif 6973 } 6974#endif 6975 6976#ifdef SISMERGED 6977 if(pSiS->MergedFB) pSiS->SiS_SD_Flags |= SiS_SD_ISMERGEDFB; 6978#endif 6979 6980 /* Try to determine if this is a laptop */ 6981 /* (only used for SiSCtrl visualisations) */ 6982 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPLTFLAG; 6983 pSiS->SiS_SD2_Flags &= ~SiS_SD2_ISLAPTOP; 6984 if(pSiS->detectedCRT2Devices & CRT2_LCD) { 6985 if(pSiS->VBFlags2 & (VB2_SISLVDSBRIDGE | VB2_LVDS | VB2_30xBDH)) { 6986 /* 1. By bridge type: LVDS in 99% of all cases; 6987 * exclude unusual setups like Barco projectors 6988 * and parallel flat panels. TODO: Exclude 6989 * Sony W1, V1. 6990 */ 6991 if((pSiS->SiS_Pr->SiS_CustomT != CUT_BARCO1366) && 6992 (pSiS->SiS_Pr->SiS_CustomT != CUT_BARCO1024) && 6993 (pSiS->SiS_Pr->SiS_CustomT != CUT_PANEL848) && 6994 (pSiS->SiS_Pr->SiS_CustomT != CUT_PANEL856) && 6995 (pSiS->SiS_Pr->SiS_CustomT != CUT_AOP8060) && 6996 ( (pSiS->ChipType != SIS_550) || 6997 (!pSiS->DSTN && !pSiS->FSTN) ) ) { 6998 pSiS->SiS_SD2_Flags |= SiS_SD2_ISLAPTOP; 6999 } 7000 } else if((pSiS->VBFlags2 & (VB2_301 | VB2_301C)) && 7001 (pSiS->VBLCDFlags & (VB_LCD_1280x960 | 7002 VB_LCD_1400x1050 | 7003 VB_LCD_1024x600 | 7004 VB_LCD_1280x800 | 7005 VB_LCD_1280x854))) { 7006 /* 2. By (odd) LCD resolutions on TMDS bridges 7007 * (eg Averatec). TODO: Exclude IBM Netvista. 7008 */ 7009 pSiS->SiS_SD2_Flags |= SiS_SD2_ISLAPTOP; 7010 } 7011 } 7012 7013 if(pSiS->enablesisctrl) pSiS->SiS_SD_Flags |= SiS_SD_ENABLED; 7014 7015 pSiS->currentModeLast = pScrn->currentMode; 7016 pSiS->VBFlagsInit = pSiS->VBFlags; 7017 7018 return TRUE; 7019 7020 /* ---- */ 7021 7022my_error_1: 7023 sisRestoreExtRegisterLock(pSiS, srlockReg, crlockReg); 7024my_error_0: 7025#ifdef SISDUALHEAD 7026 if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; 7027#endif 7028 if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); 7029 pSiS->pInt = NULL; 7030 SISFreeRec(pScrn); 7031 return FALSE; 7032} 7033 7034/* 7035 * Map I/O port area for non-PC platforms 7036 */ 7037#ifdef SIS_NEED_MAP_IOP 7038static Bool 7039SISMapIOPMem(ScrnInfoPtr pScrn) 7040{ 7041 SISPtr pSiS = SISPTR(pScrn); 7042#ifdef SISDUALHEAD 7043 SISEntPtr pSiSEnt = pSiS->entityPrivate; 7044 7045 if(pSiS->DualHeadMode) { 7046 pSiSEnt->MapCountIOPBase++; 7047 if(!(pSiSEnt->IOPBase)) { 7048 /* Only map if not mapped previously */ 7049#ifndef XSERVER_LIBPCIACCESS 7050 pSiSEnt->IOPBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7051 pSiS->PciTag, pSiS->IOPAddress, 128); 7052#else 7053 { 7054 void **result = (void **)&pSiSEnt->IOPBase; 7055 int err = pci_device_map_range(pSiS->PciInfo, 7056 pSiS->IOPAddress, 7057 128, 7058 PCI_DEV_MAP_FLAG_WRITABLE, 7059 result); 7060 7061 if (err) { 7062 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7063 "Unable to map IO aperture. %s (%d)\n", 7064 strerror (err), err); 7065 } 7066 } 7067#endif 7068 } 7069 pSiS->IOPBase = pSiSEnt->IOPBase; 7070 } else 7071#endif 7072#ifndef XSERVER_LIBPCIACCESS 7073 pSiS->IOPBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7074 pSiS->PciTag, pSiS->IOPAddress, 128); 7075#else 7076 { 7077 void **result = (void **)&pSiS->IOPBase; 7078 int err = pci_device_map_range(pSiS->PciInfo, 7079 pSiS->IOPAddress, 7080 128, 7081 PCI_DEV_MAP_FLAG_WRITABLE, 7082 result); 7083 7084 if (err) { 7085 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7086 "Unable to map IO aperture. %s (%d)\n", 7087 strerror (err), err); 7088 } 7089 } 7090#endif 7091 if(pSiS->IOPBase == NULL) { 7092 SISErrorLog(pScrn, "Could not map I/O port area\n"); 7093 return FALSE; 7094 } 7095 7096 return TRUE; 7097} 7098 7099static Bool 7100SISUnmapIOPMem(ScrnInfoPtr pScrn) 7101{ 7102 SISPtr pSiS = SISPTR(pScrn); 7103#ifdef SISDUALHEAD 7104 SISEntPtr pSiSEnt = pSiS->entityPrivate;; 7105#endif 7106 7107/* In dual head mode, we must not unmap if the other head still 7108 * assumes memory as mapped 7109 */ 7110#ifdef SISDUALHEAD 7111 if(pSiS->DualHeadMode) { 7112 if(pSiSEnt->MapCountIOPBase) { 7113 pSiSEnt->MapCountIOPBase--; 7114 if((pSiSEnt->MapCountIOPBase == 0) || (pSiSEnt->forceUnmapIOPBase)) { 7115 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOPBase, 2048); 7116 pSiSEnt->IOPBase = NULL; 7117 pSiSEnt->MapCountIOPBase = 0; 7118 pSiSEnt->forceUnmapIOPBase = FALSE; 7119 } 7120 pSiS->IOPBase = NULL; 7121 } 7122 } else { 7123#endif 7124 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOPBase, 2048); 7125 pSiS->IOPBase = NULL; 7126#ifdef SISDUALHEAD 7127 } 7128#endif 7129 return TRUE; 7130} 7131#endif 7132 7133/* 7134 * Map the framebuffer and MMIO memory 7135 */ 7136 7137static Bool 7138SISMapMem(ScrnInfoPtr pScrn) 7139{ 7140 SISPtr pSiS = SISPTR(pScrn); 7141#ifndef XSERVER_LIBPCIACCESS 7142 int mmioFlags = VIDMEM_MMIO; 7143#endif 7144#ifdef SISDUALHEAD 7145 SISEntPtr pSiSEnt = pSiS->entityPrivate; 7146#endif 7147 7148 /* 7149 * Map IO registers to virtual address space 7150 * (For Alpha, we need to map SPARSE memory, since we need 7151 * byte/short access.) 7152 */ 7153#ifndef XSERVER_LIBPCIACCESS 7154#if defined(__alpha__) 7155 mmioFlags |= VIDMEM_SPARSE; 7156#endif 7157#endif 7158 7159#ifdef SISDUALHEAD 7160 if(pSiS->DualHeadMode) { 7161 pSiSEnt->MapCountIOBase++; 7162 if(!(pSiSEnt->IOBase)) { 7163 /* Only map if not mapped previously */ 7164#ifndef XSERVER_LIBPCIACCESS 7165 pSiSEnt->IOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, 7166 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7167#else 7168 void **result = (void **)&pSiSEnt->IOBase; 7169 int err = pci_device_map_range(pSiS->PciInfo, 7170 pSiS->IOAddress, 7171 (pSiS->mmioSize * 1024), 7172 PCI_DEV_MAP_FLAG_WRITABLE, 7173 result); 7174 7175 if (err) { 7176 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7177 "Unable to map IO aperture. %s (%d)\n", 7178 strerror (err), err); 7179 } 7180#endif 7181 } 7182 pSiS->IOBase = pSiSEnt->IOBase; 7183 } else 7184#endif 7185#ifndef XSERVER_LIBPCIACCESS 7186 pSiS->IOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, 7187 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7188#else 7189 { 7190 void **result = (void **)&pSiS->IOBase; 7191 int err = pci_device_map_range(pSiS->PciInfo, 7192 pSiS->IOAddress, 7193 (pSiS->mmioSize * 1024), 7194 PCI_DEV_MAP_FLAG_WRITABLE, 7195 result); 7196 7197 if (err) { 7198 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7199 "Unable to map IO aperture. %s (%d)\n", 7200 strerror (err), err); 7201 } 7202 } 7203#endif 7204 7205 if(pSiS->IOBase == NULL) { 7206 SISErrorLog(pScrn, "Could not map MMIO area\n"); 7207 return FALSE; 7208 } 7209 7210#ifdef __alpha__ 7211 /* 7212 * for Alpha, we need to map DENSE memory as well, for 7213 * setting CPUToScreenColorExpandBase. 7214 */ 7215#ifdef SISDUALHEAD 7216 if(pSiS->DualHeadMode) { 7217 pSiSEnt->MapCountIOBaseDense++; 7218 if(!(pSiSEnt->IOBaseDense)) { 7219 /* Only map if not mapped previously */ 7220#ifndef XSERVER_LIBPCIACCESS 7221 pSiSEnt->IOBaseDense = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7222 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7223#else 7224 void **result = (void **)&pSiSEnt->IOBaseDense; 7225 int err = pci_device_map_range(pSiS->PciInfo, 7226 pSiS->IOAddress, 7227 (pSiS->mmioSize * 1024), 7228 PCI_DEV_MAP_FLAG_WRITABLE, 7229 result); 7230 7231 if (err) { 7232 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7233 "Unable to map IO dense aperture. %s (%d)\n", 7234 strerror (err), err); 7235 } 7236#endif /* XSERVER_LIBPCIACCESS */ 7237 } 7238 pSiS->IOBaseDense = pSiSEnt->IOBaseDense; 7239 } else { 7240#endif /* SISDUALHEAD */ 7241#ifndef XSERVER_LIBPCIACCESS 7242 pSiS->IOBaseDense = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7243 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7244#else 7245 void **result = (void **)&pSiS->IOBaseDense; 7246 int err = pci_device_map_range(pSiS->PciInfo, 7247 pSiS->IOAddress, 7248 (pSiS->mmioSize * 1024), 7249 PCI_DEV_MAP_FLAG_WRITABLE, 7250 result); 7251 7252 if (err) { 7253 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7254 "Unable to map IO dense aperture. %s (%d)\n", 7255 strerror (err), err); 7256 } 7257#endif /* XSERVER_LIBPCIACCESS */ 7258#ifdef SISDUALHEAD 7259 } 7260#endif 7261 if(pSiS->IOBaseDense == NULL) { 7262 SISErrorLog(pScrn, "Could not map MMIO dense area\n"); 7263 return FALSE; 7264 } 7265#endif /* __alpha__ */ 7266 7267#ifdef SISDUALHEAD 7268 if(pSiS->DualHeadMode) { 7269 pSiSEnt->MapCountFbBase++; 7270 if(!(pSiSEnt->FbBase)) { 7271 /* Only map if not mapped previously */ 7272#ifndef XSERVER_LIBPCIACCESS 7273 pSiSEnt->FbBase = pSiSEnt->RealFbBase = 7274 xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 7275 pSiS->PciTag, (ULong)pSiS->realFbAddress, 7276 pSiS->FbMapSize); 7277#else 7278 int err = pci_device_map_range(pSiS->PciInfo, 7279 (ULong)pSiS->realFbAddress, 7280 pSiS->FbMapSize, 7281 PCI_DEV_MAP_FLAG_WRITABLE | 7282 PCI_DEV_MAP_FLAG_WRITE_COMBINE, 7283 (void *)&pSiSEnt->FbBase); 7284 if (err) { 7285 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7286 "Unable to map FB aperture. %s (%d)\n", 7287 strerror (err), err); 7288 return FALSE; 7289 } 7290 pSiSEnt->RealFbBase = pSiSEnt->FbBase; 7291#endif 7292 } 7293 pSiS->FbBase = pSiS->RealFbBase = pSiSEnt->FbBase; 7294 /* Adapt FbBase (for DHM and SiS76x UMA skipping; dhmOffset is 0 otherwise) */ 7295 pSiS->FbBase += pSiS->dhmOffset; 7296 } else { 7297#endif 7298 7299#ifndef XSERVER_LIBPCIACCESS 7300 pSiS->FbBase = pSiS->RealFbBase = 7301 xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 7302 pSiS->PciTag, (ULong)pSiS->realFbAddress, 7303 pSiS->FbMapSize); 7304#else 7305 int err = pci_device_map_range(pSiS->PciInfo, 7306 (ULong)pSiS->realFbAddress, 7307 pSiS->FbMapSize, 7308 PCI_DEV_MAP_FLAG_WRITABLE | 7309 PCI_DEV_MAP_FLAG_WRITE_COMBINE, 7310 (void *)&pSiS->FbBase); 7311 if (err) { 7312 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7313 "Unable to map FB aperture. %s (%d)\n", 7314 strerror (err), err); 7315 return FALSE; 7316 } 7317 pSiS->RealFbBase = pSiS->FbBase; 7318#endif 7319 pSiS->FbBase += pSiS->dhmOffset; 7320 7321#ifdef SISDUALHEAD 7322 } 7323#endif 7324 7325 if(pSiS->FbBase == NULL) { 7326 SISErrorLog(pScrn, "Could not map framebuffer area\n"); 7327 return FALSE; 7328 } 7329 7330#ifdef TWDEBUG 7331 xf86DrvMsg(0, 0, "Framebuffer mapped to %p\n", pSiS->FbBase); 7332#endif 7333 7334 return TRUE; 7335} 7336 7337 7338/* 7339 * Unmap the framebuffer and MMIO memory. 7340 */ 7341 7342static Bool 7343SISUnmapMem(ScrnInfoPtr pScrn) 7344{ 7345 SISPtr pSiS = SISPTR(pScrn); 7346#ifdef SISDUALHEAD 7347 SISEntPtr pSiSEnt = pSiS->entityPrivate; 7348#endif 7349 7350/* In dual head mode, we must not unmap if the other head still 7351 * assumes memory as mapped 7352 */ 7353#ifdef SISDUALHEAD 7354 if(pSiS->DualHeadMode) { 7355 if(pSiSEnt->MapCountIOBase) { 7356 pSiSEnt->MapCountIOBase--; 7357 if((pSiSEnt->MapCountIOBase == 0) || (pSiSEnt->forceUnmapIOBase)) { 7358#ifndef XSERVER_LIBPCIACCESS 7359 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOBase, (pSiS->mmioSize * 1024)); 7360#else 7361 pci_device_unmap_range(pSiS->PciInfo, pSiSEnt->IOBase, (pSiS->mmioSize * 1024)); 7362#endif 7363 pSiSEnt->IOBase = NULL; 7364 pSiSEnt->MapCountIOBase = 0; 7365 pSiSEnt->forceUnmapIOBase = FALSE; 7366 } 7367 pSiS->IOBase = NULL; 7368 } 7369#ifdef __alpha__ 7370 if(pSiSEnt->MapCountIOBaseDense) { 7371 pSiSEnt->MapCountIOBaseDense--; 7372 if((pSiSEnt->MapCountIOBaseDense == 0) || (pSiSEnt->forceUnmapIOBaseDense)) { 7373#ifndef XSERVER_LIBPCIACCESS 7374 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOBaseDense, (pSiS->mmioSize * 1024)); 7375#else 7376 pci_device_unmap_range(pSiS->PciInfo, (pointer)pSiSEnt->IOBaseDense, (pSiS->mmioSize * 1024)); 7377#endif 7378 pSiSEnt->IOBaseDense = NULL; 7379 pSiSEnt->MapCountIOBaseDense = 0; 7380 pSiSEnt->forceUnmapIOBaseDense = FALSE; 7381 } 7382 pSiS->IOBaseDense = NULL; 7383 } 7384#endif /* __alpha__ */ 7385 if(pSiSEnt->MapCountFbBase) { 7386 pSiSEnt->MapCountFbBase--; 7387 if((pSiSEnt->MapCountFbBase == 0) || (pSiSEnt->forceUnmapFbBase)) { 7388#ifndef XSERVER_LIBPCIACCESS 7389 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->RealFbBase, pSiS->FbMapSize); 7390#else 7391 pci_device_unmap_range(pSiS->PciInfo, (pointer)pSiSEnt->RealFbBase, pSiS->FbMapSize); 7392#endif 7393 pSiSEnt->FbBase = pSiSEnt->RealFbBase = NULL; 7394 pSiSEnt->MapCountFbBase = 0; 7395 pSiSEnt->forceUnmapFbBase = FALSE; 7396 7397 } 7398 pSiS->FbBase = pSiS->RealFbBase = NULL; 7399 } 7400 } else { 7401#endif 7402#ifndef XSERVER_LIBPCIACCESS 7403 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOBase, (pSiS->mmioSize * 1024)); 7404#else 7405 pci_device_unmap_range(pSiS->PciInfo, (pointer)pSiS->IOBase, (pSiS->mmioSize * 1024)); 7406#endif 7407 pSiS->IOBase = NULL; 7408#ifdef __alpha__ 7409#ifndef XSERVER_LIBPCIACCESS 7410 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOBaseDense, (pSiS->mmioSize * 1024)); 7411#else 7412 pci_device_unmap_range(pSiS->PciInfo, (pointer)pSiS->IOBaseDense, (pSiS->mmioSize * 1024)); 7413#endif 7414 pSiS->IOBaseDense = NULL; 7415#endif 7416#ifndef XSERVER_LIBPCIACCESS 7417 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->RealFbBase, pSiS->FbMapSize); 7418#else 7419 pci_device_unmap_range(pSiS->PciInfo, (pointer)pSiS->RealFbBase, pSiS->FbMapSize); 7420#endif 7421 pSiS->FbBase = pSiS->RealFbBase = NULL; 7422#ifdef SISDUALHEAD 7423 } 7424#endif 7425 return TRUE; 7426} 7427 7428/* 7429 * This function saves the video state. 7430 */ 7431static void 7432SISSave(ScrnInfoPtr pScrn) 7433{ 7434 SISPtr pSiS = SISPTR(pScrn); 7435 SISRegPtr sisReg; 7436 int flags; 7437 7438#ifdef SISDUALHEAD 7439 /* We always save master & slave */ 7440 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 7441#endif 7442 7443 sisReg = &pSiS->SavedReg; 7444 7445 if( ((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) && 7446 ((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (SiSBridgeIsInSlaveMode(pScrn))) ) { 7447 SiSVGASave(pScrn, sisReg, SISVGA_SR_CMAP | SISVGA_SR_MODE); 7448#ifdef SIS_PC_PLATFORM 7449 if(pSiS->VGAMemBase) { 7450 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO+0x30); 7451 SiSSetLVDSetc(pSiS->SiS_Pr); 7452 SiS_GetVBType(pSiS->SiS_Pr); 7453 SiS_DisableBridge(pSiS->SiS_Pr); 7454 SiSVGASave(pScrn, sisReg, SISVGA_SR_FONTS); 7455 SiS_EnableBridge(pSiS->SiS_Pr); 7456 } 7457#endif 7458 } else { 7459 flags = SISVGA_SR_CMAP | SISVGA_SR_MODE; 7460#ifdef SIS_PC_PLATFORM 7461 if(pSiS->VGAMemBase) flags |= SISVGA_SR_FONTS; 7462#endif 7463 SiSVGASave(pScrn, sisReg, flags); 7464 } 7465 7466 sisSaveUnlockExtRegisterLock(pSiS, &sisReg->sisRegs3C4[0x05], &sisReg->sisRegs3D4[0x80]); 7467 7468 (*pSiS->SiSSave)(pScrn, sisReg); 7469 7470 if(pSiS->UseVESA) SISVESASaveRestore(pScrn, MODE_SAVE); 7471 7472 /* "Save" these again as they may have been changed prior to SISSave() call */ 7473 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 7474 sisReg->sisRegs3C4[0x1f] = pSiS->oldSR1F; 7475 sisReg->sisRegs3D4[0x17] = pSiS->oldCR17; 7476 sisReg->sisRegs3D4[0x32] = pSiS->oldCR32; 7477 sisReg->sisRegs3D4[0x36] = pSiS->oldCR36; 7478 sisReg->sisRegs3D4[0x37] = pSiS->oldCR37; 7479 if(pSiS->VGAEngine == SIS_315_VGA) { 7480 sisReg->sisRegs3D4[pSiS->myCR63] = pSiS->oldCR63; 7481 } 7482 } 7483} 7484 7485/* VESASaveRestore taken from vesa driver */ 7486static void 7487SISVESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function) 7488{ 7489 SISPtr pSiS = SISPTR(pScrn); 7490 7491 /* Query amount of memory to save state */ 7492 if((function == MODE_QUERY) || 7493 (function == MODE_SAVE && pSiS->state == NULL)) { 7494 7495 /* Make sure we save at least this information in case of failure */ 7496 (void)VBEGetVBEMode(pSiS->pVbe, &pSiS->stateMode); 7497 SiSVGASaveFonts(pScrn); 7498 7499 if(pSiS->vesamajor > 1) { 7500 if(!VBESaveRestore(pSiS->pVbe, function, (pointer)&pSiS->state, 7501 &pSiS->stateSize, &pSiS->statePage)) { 7502 return; 7503 } 7504 } 7505 } 7506 7507 /* Save/Restore Super VGA state */ 7508 if(function != MODE_QUERY) { 7509 7510 if(pSiS->vesamajor > 1) { 7511 if(function == MODE_RESTORE) { 7512 memcpy(pSiS->state, pSiS->pstate, pSiS->stateSize); 7513 } 7514 7515 if(VBESaveRestore(pSiS->pVbe,function,(pointer)&pSiS->state, 7516 &pSiS->stateSize,&pSiS->statePage) && 7517 (function == MODE_SAVE)) { 7518 /* don't rely on the memory not being touched */ 7519 if(!pSiS->pstate) { 7520 pSiS->pstate = malloc(pSiS->stateSize); 7521 } 7522 memcpy(pSiS->pstate, pSiS->state, pSiS->stateSize); 7523 } 7524 } 7525 7526 if(function == MODE_RESTORE) { 7527 VBESetVBEMode(pSiS->pVbe, pSiS->stateMode, NULL); 7528 SiSVGARestoreFonts(pScrn); 7529 } 7530 7531 } 7532} 7533 7534/* 7535 * Initialise a new mode. This is currently done using the 7536 * "initialise struct, restore/write struct to HW" model for 7537 * the old chipsets (5597/530/6326). For newer chipsets, 7538 * we use our own mode switching code. 7539 */ 7540 7541static Bool 7542SISModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 7543{ 7544 SISPtr pSiS = SISPTR(pScrn); 7545 SISRegPtr sisReg; 7546#ifdef SISDUALHEAD 7547 SISEntPtr pSiSEnt = NULL; 7548#endif 7549 7550 andSISIDXREG(SISCR,0x11,0x7f); /* Unlock CRTC registers */ 7551 7552 SISModifyModeInfo(mode); /* Quick check of the mode parameters */ 7553 7554 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7555 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO+0x30); 7556 } 7557 7558 if(pSiS->UseVESA) { /* With VESA: */ 7559 7560#ifdef SISDUALHEAD 7561 /* No dual head mode when using VESA */ 7562 if(pSiS->SecondHead) return TRUE; 7563#endif 7564 7565 pScrn->vtSema = TRUE; 7566 7567 /* 7568 * This order is required: 7569 * The video bridge needs to be adjusted before the 7570 * BIOS is run as the BIOS sets up CRT2 according to 7571 * these register settings. 7572 * After the BIOS is run, the bridges and turboqueue 7573 * registers need to be readjusted as the BIOS may 7574 * very probably have messed them up. 7575 */ 7576 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7577 SiSPreSetMode(pScrn, mode, SIS_MODE_SIMU); 7578 } 7579 if(!SiSSetVESAMode(pScrn, mode)) { 7580 SISErrorLog(pScrn, "SiSSetVESAMode() failed\n"); 7581 return FALSE; 7582 } 7583 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7584 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7585 SiSPreSetMode(pScrn, mode, SIS_MODE_SIMU); 7586 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7587 } 7588#ifdef TWDEBUG 7589 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 7590 "REAL REGISTER CONTENTS AFTER SETMODE:\n"); 7591#endif 7592 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7593 SISErrorLog(pScrn, "ModeInit() failed\n"); 7594 return FALSE; 7595 } 7596 7597 SiSVGAProtect(pScrn, TRUE); 7598 (*pSiS->SiSRestore)(pScrn, &pSiS->ModeReg); 7599 SiSVGAProtect(pScrn, FALSE); 7600 7601 } else { /* Without VESA: */ 7602 7603#ifdef SISDUALHEAD 7604 if(pSiS->DualHeadMode) { 7605 7606 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7607 SISErrorLog(pScrn, "ModeInit() failed\n"); 7608 return FALSE; 7609 } 7610 7611 pScrn->vtSema = TRUE; 7612 7613 pSiSEnt = pSiS->entityPrivate; 7614 7615 if(!(pSiS->SecondHead)) { 7616 /* Head 1 (master) is always CRT2 */ 7617 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT2); 7618 if(!SiSBIOSSetModeCRT2(pSiS->SiS_Pr, pScrn, mode, pSiS->IsCustom)) { 7619 SISErrorLog(pScrn, "SiSBIOSSetModeCRT2() failed\n"); 7620 return FALSE; 7621 } 7622 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7623 if(pSiSEnt->pScrn_2) { 7624 SISAdjustFrame(ADJUST_FRAME_ARGS(pSiSEnt->pScrn_2, 7625 pSiSEnt->pScrn_2->frameX0, 7626 pSiSEnt->pScrn_2->frameY0)); 7627 } 7628 } else { 7629 /* Head 2 (slave) is always CRT1 */ 7630 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT1); 7631 if(!SiSBIOSSetModeCRT1(pSiS->SiS_Pr, pScrn, mode, pSiS->IsCustom)) { 7632 SISErrorLog(pScrn, "SiSBIOSSetModeCRT1() failed\n"); 7633 return FALSE; 7634 } 7635 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7636 if(pSiSEnt->pScrn_1) { 7637 SISAdjustFrame(ADJUST_FRAME_ARGS(pSiSEnt->pScrn_1, 7638 pSiSEnt->pScrn_1->frameX0, 7639 pSiSEnt->pScrn_1->frameY0)); 7640 } 7641 } 7642 7643 } else { 7644#endif 7645 7646 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7647 7648 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7649 SISErrorLog(pScrn, "ModeInit() failed\n"); 7650 return FALSE; 7651 } 7652 7653 pScrn->vtSema = TRUE; 7654 7655#ifdef SISMERGED 7656 if(pSiS->MergedFB) { 7657 7658 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting MergedFB mode %dx%d\n", 7659 mode->HDisplay, mode->VDisplay); 7660 7661 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT1); 7662 7663 if(!SiSBIOSSetModeCRT1(pSiS->SiS_Pr, pScrn, 7664 ((SiSMergedDisplayModePtr)mode->Private)->CRT1, 7665 pSiS->IsCustom)) { 7666 SISErrorLog(pScrn, "SiSBIOSSetModeCRT1() failed\n"); 7667 return FALSE; 7668 } 7669 7670 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT2); 7671 7672 if(!SiSBIOSSetModeCRT2(pSiS->SiS_Pr, pScrn, 7673 ((SiSMergedDisplayModePtr)mode->Private)->CRT2, 7674 pSiS->IsCustom)) { 7675 SISErrorLog(pScrn, "SiSBIOSSetModeCRT2() failed\n"); 7676 return FALSE; 7677 } 7678 7679 } else { 7680#endif 7681 7682 if((pSiS->VBFlags & CRT1_LCDA) || (!(mode->type & M_T_DEFAULT))) { 7683 7684 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT1); 7685 7686 if(!SiSBIOSSetModeCRT1(pSiS->SiS_Pr, pScrn, 7687 mode, pSiS->IsCustom)) { 7688 SISErrorLog(pScrn, "SiSBIOSSetModeCRT1() failed\n"); 7689 return FALSE; 7690 } 7691 7692 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT2); 7693 7694 if(!SiSBIOSSetModeCRT2(pSiS->SiS_Pr, pScrn, 7695 mode, pSiS->IsCustom)) { 7696 SISErrorLog(pScrn, "SiSBIOSSetModeCRT2() failed\n"); 7697 return FALSE; 7698 } 7699 7700 } else { 7701 7702 SiSPreSetMode(pScrn, mode, SIS_MODE_SIMU); 7703 7704 if(!SiSBIOSSetMode(pSiS->SiS_Pr, pScrn, 7705 mode, pSiS->IsCustom)) { 7706 SISErrorLog(pScrn, "SiSBIOSSetMode() failed\n"); 7707 return FALSE; 7708 } 7709 7710 } 7711 7712#ifdef SISMERGED 7713 } 7714#endif 7715 7716 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7717 7718#ifdef TWDEBUG 7719 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VBFlags %lx\n", pSiS->VBFlags); 7720 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 7721 "REAL REGISTER CONTENTS AFTER SETMODE:\n"); 7722 (*pSiS->ModeInit)(pScrn, mode); 7723#endif 7724 7725 } else { 7726 7727 /* For other chipsets, use the old method */ 7728 7729 /* Prepare the register contents */ 7730 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7731 SISErrorLog(pScrn, "ModeInit() failed\n"); 7732 return FALSE; 7733 } 7734 7735 pScrn->vtSema = TRUE; 7736 7737 /* Program the registers */ 7738 SiSVGAProtect(pScrn, TRUE); 7739 sisReg = &pSiS->ModeReg; 7740 7741 sisReg->sisRegsATTR[0x10] = 0x01; 7742 if(pScrn->bitsPerPixel > 8) { 7743 sisReg->sisRegsGR[0x05] = 0x00; 7744 } 7745 7746 SiSVGARestore(pScrn, sisReg, SISVGA_SR_MODE); 7747 7748 (*pSiS->SiSRestore)(pScrn, sisReg); 7749 7750 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 7751 SiS6326PostSetMode(pScrn, &pSiS->ModeReg); 7752 } 7753 7754#ifdef TWDEBUG 7755 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 7756 "REAL REGISTER CONTENTS AFTER SETMODE:\n"); 7757 (*pSiS->ModeInit)(pScrn, mode); 7758#endif 7759 7760 SiSVGAProtect(pScrn, FALSE); 7761 7762 } 7763 7764#ifdef SISDUALHEAD 7765 } 7766#endif 7767 } 7768 7769 /* Update Currentlayout */ 7770 pSiS->CurrentLayout.mode = pSiS->currentModeLast = mode; 7771 7772 return TRUE; 7773} 7774 7775static Bool 7776SiSSetVESAMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) 7777{ 7778 SISPtr pSiS; 7779 int mode; 7780 7781 pSiS = SISPTR(pScrn); 7782 7783 if(!(mode = SiSCalcVESAModeIndex(pScrn, pMode))) return FALSE; 7784 7785 mode |= (1 << 15); /* Don't clear framebuffer */ 7786 mode |= (1 << 14); /* Use linear adressing */ 7787 7788 if(VBESetVBEMode(pSiS->pVbe, mode, NULL) == FALSE) { 7789 SISErrorLog(pScrn, "Setting VESA mode 0x%x failed\n", 7790 mode & 0x0fff); 7791 return (FALSE); 7792 } 7793 7794 if(pMode->HDisplay != pScrn->virtualX) { 7795 VBESetLogicalScanline(pSiS->pVbe, pScrn->virtualX); 7796 } 7797 7798 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 7799 "Setting VESA mode 0x%x succeeded\n", 7800 mode & 0x0fff); 7801 7802 return (TRUE); 7803} 7804 7805static void 7806SISSpecialRestore(ScrnInfoPtr pScrn) 7807{ 7808 SISPtr pSiS = SISPTR(pScrn); 7809 SISRegPtr sisReg = &pSiS->SavedReg; 7810 UChar temp; 7811 int i; 7812 7813 /* 1.11.04 and later for 651 and 301B(DH) do strange register 7814 * fiddling after the usual mode change. This happens 7815 * depending on the result of a call of int 2f (with 7816 * ax=0x1680) and if modeno <= 0x13. I have no idea if 7817 * that is specific for the 651 or that very machine. 7818 * So this perhaps requires some more checks in the beginning 7819 * (although it should not do any harm on other chipsets/bridges 7820 * etc.) However, even if I call the VBE to restore mode 0x03, 7821 * these registers don't get restored correctly, possibly 7822 * because that int-2f-call for some reason results non-zero. So 7823 * what I do here is to restore these few registers 7824 * manually. 7825 */ 7826 7827 if(!(pSiS->ChipFlags & SiSCF_Is65x)) return; 7828 inSISIDXREG(SISCR, 0x34, temp); 7829 temp &= 0x7f; 7830 if(temp > 0x13) return; 7831 7832#ifdef UNLOCK_ALWAYS 7833 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7834#endif 7835 7836 SiS_UnLockCRT2(pSiS->SiS_Pr); 7837 7838 outSISIDXREG(SISCAP, 0x3f, sisReg->sisCapt[0x3f]); 7839 outSISIDXREG(SISCAP, 0x00, sisReg->sisCapt[0x00]); 7840 for(i = 0; i < 0x4f; i++) { 7841 outSISIDXREG(SISCAP, i, sisReg->sisCapt[i]); 7842 } 7843 outSISIDXREG(SISVID, 0x32, (sisReg->sisVid[0x32] & ~0x05)); 7844 outSISIDXREG(SISVID, 0x30, sisReg->sisVid[0x30]); 7845 outSISIDXREG(SISVID, 0x32, ((sisReg->sisVid[0x32] & ~0x04) | 0x01)); 7846 outSISIDXREG(SISVID, 0x30, sisReg->sisVid[0x30]); 7847 7848 if(!(pSiS->ChipFlags & SiSCF_Is651)) return; 7849 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 7850 7851 inSISIDXREG(SISCR, 0x30, temp); 7852 if(temp & 0x40) { 7853 UChar myregs[] = { 7854 0x2f, 0x08, 0x09, 0x03, 0x0a, 0x0c, 7855 0x0b, 0x0d, 0x0e, 0x12, 0x0f, 0x10, 7856 0x11, 0x04, 0x05, 0x06, 0x07, 0x00, 7857 0x2e 7858 }; 7859 for(i = 0; i <= 18; i++) { 7860 outSISIDXREG(SISPART1, myregs[i], sisReg->VBPart1[myregs[i]]); 7861 } 7862 } else if((temp & 0x20) || (temp & 0x9c)) { 7863 UChar myregs[] = { 7864 0x04, 0x05, 0x06, 0x07, 0x00, 0x2e 7865 }; 7866 for(i = 0; i <= 5; i++) { 7867 outSISIDXREG(SISPART1, myregs[i], sisReg->VBPart1[myregs[i]]); 7868 } 7869 } 7870} 7871 7872/* Fix SR11 for 661 and later */ 7873static void 7874SiSFixupSR11(ScrnInfoPtr pScrn) 7875{ 7876 SISPtr pSiS = SISPTR(pScrn); 7877 CARD8 tmpreg; 7878 7879#ifdef UNLOCK_ALWAYS 7880 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7881#endif 7882 7883 if(pSiS->ChipType >= SIS_661) { 7884 inSISIDXREG(SISSR,0x11,tmpreg); 7885 if(tmpreg & 0x20) { 7886 inSISIDXREG(SISSR,0x3e,tmpreg); 7887 tmpreg = (tmpreg + 1) & 0xff; 7888 outSISIDXREG(SISSR,0x3e,tmpreg); 7889 } 7890 7891 inSISIDXREG(SISSR,0x11,tmpreg); 7892 if(tmpreg & 0xf0) { 7893 andSISIDXREG(SISSR,0x11,0x0f); 7894 } 7895 } 7896} 7897 7898/* Subroutine for restoring sisfb's TV parameters (used by SiSRestore()) */ 7899 7900static void 7901SiSRestore_SiSFB_TVParms(ScrnInfoPtr pScrn) 7902{ 7903 SISPtr pSiS = SISPTR(pScrn); 7904 int fd; 7905 CARD32 parm; 7906 7907 if(!pSiS->sisfbfound) return; 7908 if(!pSiS->sisfb_tvposvalid) return; 7909 if(!(pSiS->sisfbdevname[0])) return; 7910 7911 if((fd = open(pSiS->sisfbdevname, O_RDONLY)) != -1) { 7912 parm = (CARD32)((pSiS->sisfb_tvxpos << 16) | (pSiS->sisfb_tvypos & 0xffff)); 7913 ioctl(fd, SISFB_SET_TVPOSOFFSET, &parm); 7914 close(fd); 7915 } 7916} 7917 7918/* 7919 * Restore the initial mode. To be used internally only! 7920 */ 7921static void 7922SISRestore(ScrnInfoPtr pScrn) 7923{ 7924 SISPtr pSiS = SISPTR(pScrn); 7925 SISRegPtr sisReg = &pSiS->SavedReg; 7926 Bool doit = FALSE, doitlater = FALSE; 7927 Bool vesasuccess = FALSE; 7928 int flags; 7929 7930 /* WARNING: Don't ever touch this. It now seems to work on 7931 * all chipset/bridge combinations - but finding out the 7932 * correct combination was pure hell. 7933 */ 7934 7935 /* Wait for the accelerators */ 7936 (*pSiS->SyncAccel)(pScrn); 7937 7938 /* Set up restore flags */ 7939 flags = SISVGA_SR_MODE | SISVGA_SR_CMAP; 7940#ifdef SIS_PC_PLATFORM 7941 /* We now restore ALL to overcome the vga=extended problem */ 7942 if(pSiS->VGAMemBase) flags |= SISVGA_SR_FONTS; 7943#endif 7944 7945 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 7946 7947#ifdef SISDUALHEAD 7948 /* We always restore master AND slave */ 7949 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 7950#endif 7951 7952#ifdef UNLOCK_ALWAYS 7953 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7954#endif 7955 7956 /* We must not disable the sequencer if the bridge is in SlaveMode! */ 7957 if(!(SiSBridgeIsInSlaveMode(pScrn))) { 7958 SiSVGAProtect(pScrn, TRUE); 7959 } 7960 7961 /* First, restore CRT1 on/off and VB connection registers */ 7962 outSISIDXREG(SISCR, 0x32, pSiS->oldCR32); 7963 if(!(pSiS->oldCR17 & 0x80)) { /* CRT1 was off */ 7964 if(!(SiSBridgeIsInSlaveMode(pScrn))) { /* Bridge is NOT in SlaveMode now -> do it */ 7965 doit = TRUE; 7966 } else { 7967 doitlater = TRUE; 7968 } 7969 } else { /* CRT1 was on -> do it now */ 7970 doit = TRUE; 7971 } 7972 7973 if(doit) { 7974 outSISIDXREG(SISCR, 0x17, pSiS->oldCR17); 7975 } 7976 if(pSiS->VGAEngine == SIS_315_VGA) { 7977 outSISIDXREG(SISCR, pSiS->myCR63, pSiS->oldCR63); 7978 } 7979 7980 outSISIDXREG(SISSR, 0x1f, pSiS->oldSR1F); 7981 7982 /* For 30xB/LV, restoring the registers does not 7983 * work. We "manually" set the old mode, instead. 7984 * The same applies for SiS730 machines with LVDS. 7985 * Finally, this behavior can be forced by setting 7986 * the option RestoreBySetMode. 7987 */ 7988 if( ( (pSiS->restorebyset) || 7989 (pSiS->VBFlags2 & VB2_30xBLV) || 7990 ((pSiS->ChipType == SIS_730) && (pSiS->VBFlags2 & VB2_LVDS)) ) && 7991 (pSiS->OldMode) ) { 7992 7993 Bool changedmode = FALSE; 7994 7995 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 7996 "Restoring by setting old mode 0x%02x\n", pSiS->OldMode); 7997 7998 if(((pSiS->OldMode <= 0x13) || (!pSiS->sisfbfound)) && (pSiS->pVbe)) { 7999 int vmode = SiSTranslateToVESA(pScrn, pSiS->OldMode); 8000 if(vmode > 0) { 8001 if(vmode > 0x13) vmode |= ((1 << 15) | (1 << 14)); 8002 if(VBESetVBEMode(pSiS->pVbe, vmode, NULL) == TRUE) { 8003 SISSpecialRestore(pScrn); 8004 SiS_GetSetModeID(pScrn,pSiS->OldMode); 8005 vesasuccess = TRUE; 8006 } else { 8007 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 8008 "VBE failed to restore mode 0x%x\n", pSiS->OldMode); 8009 } 8010 } else { 8011 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 8012 "Can't identify VESA mode number for mode 0x%x\n", pSiS->OldMode); 8013 } 8014 } 8015 8016 if(vesasuccess == FALSE) { 8017 8018 int backupscaler = pSiS->SiS_Pr->UsePanelScaler; 8019 int backupcenter = pSiS->SiS_Pr->CenterScreen; 8020 ULong backupspecialtiming = pSiS->SiS_Pr->SiS_CustomT; 8021 int mymode = pSiS->OldMode; 8022 8023 if((pSiS->VGAEngine == SIS_315_VGA) && 8024 ((pSiS->ROM661New) || (pSiS->ChipFlags & SiSCF_IsXGI)) && 8025 (!pSiS->sisfbfound)) { 8026 /* New SiS BIOS or XGI BIOS has set mode, therefore eventually translate number */ 8027 mymode = SiSTranslateToOldMode(mymode); 8028 } 8029 8030 if((pSiS->VBFlags2 & VB2_30xBLV)) { 8031 /* !!! REQUIRED for 630+301B-DH, otherwise the text modes 8032 * will not be restored correctly !!! 8033 * !!! Do this ONLY for LCD; VGA2 will not be restored 8034 * correctly otherwise. 8035 */ 8036 UChar temp; 8037 inSISIDXREG(SISCR, 0x30, temp); 8038 if(temp & 0x20) { 8039 if(mymode == 0x03) { 8040 mymode = 0x13; 8041 changedmode = TRUE; 8042 } 8043 } 8044 } 8045 8046 pSiS->SiS_Pr->UseCustomMode = FALSE; 8047 pSiS->SiS_Pr->CRT1UsesCustomMode = FALSE; 8048 pSiS->SiS_Pr->CenterScreen = 0; 8049 if(pSiS->sisfbfound) { 8050 pSiS->SiS_Pr->UsePanelScaler = pSiS->sisfbscalelcd; 8051 pSiS->SiS_Pr->SiS_CustomT = pSiS->sisfbspecialtiming; 8052 } else { 8053 pSiS->SiS_Pr->UsePanelScaler = -1; 8054 /* Leave CustomT as it is */ 8055 } 8056 SiS_SetEnableDstn(pSiS->SiS_Pr, FALSE); 8057 SiS_SetEnableFstn(pSiS->SiS_Pr, FALSE); 8058 if((pSiS->ChipType == SIS_550) && (pSiS->sisfbfound)) { 8059 if(pSiS->sisfbxSTN) { 8060 SiS_SetEnableDstn(pSiS->SiS_Pr, pSiS->sisfbDSTN); 8061 SiS_SetEnableFstn(pSiS->SiS_Pr, pSiS->sisfbFSTN); 8062 } else if(mymode == 0x5a || mymode == 0x5b) { 8063 SiS_SetEnableFstn(pSiS->SiS_Pr, TRUE); 8064 } 8065 } 8066 SiSSetMode(pSiS->SiS_Pr, pScrn, mymode, FALSE); 8067 if(changedmode) { 8068 outSISIDXREG(SISCR,0x34,0x03); 8069 } 8070 SISSpecialRestore(pScrn); 8071 SiS_GetSetModeID(pScrn, pSiS->OldMode); /* NOT mymode! */ 8072 pSiS->SiS_Pr->UsePanelScaler = backupscaler; 8073 pSiS->SiS_Pr->CenterScreen = backupcenter; 8074 pSiS->SiS_Pr->SiS_CustomT = backupspecialtiming; 8075 SiS_SiSFB_Lock(pScrn, FALSE); 8076 SiSRestore_SiSFB_TVParms(pScrn); 8077 SiS_SiSFB_Lock(pScrn, TRUE); 8078 8079 } 8080 8081 /* Restore CRT1 status */ 8082 if(pSiS->VGAEngine == SIS_315_VGA) { 8083 outSISIDXREG(SISCR, pSiS->myCR63, pSiS->oldCR63); 8084 } 8085 outSISIDXREG(SISSR, 0x1f, pSiS->oldSR1F); 8086 8087#ifdef SISVRAMQ 8088 /* Restore queue mode registers on 315/330/340 series */ 8089 /* (This became necessary due to the switch to VRAM queue) */ 8090 SiSRestoreQueueMode(pSiS, sisReg); 8091#endif 8092 8093 } else { 8094 8095 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 8096 /* If a video bridge is present, we need to restore 8097 * non-extended (=standard VGA) SR and CR registers 8098 * before restoring the extended ones and the bridge 8099 * registers. 8100 */ 8101 if(!(SiSBridgeIsInSlaveMode(pScrn))) { 8102 SiSVGAProtect(pScrn, TRUE); 8103 SiSVGARestore(pScrn, sisReg, SISVGA_SR_MODE); 8104 } 8105 } 8106 8107 (*pSiS->SiSRestore)(pScrn, sisReg); 8108 8109 } 8110 8111 if(doitlater) { 8112 outSISIDXREG(SISCR, 0x17, pSiS->oldCR17); 8113 } 8114 8115 8116 8117 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (SiSBridgeIsInSlaveMode(pScrn))) { 8118 8119 /* IMPORTANT: The 30xLV does not handle well being disabled if in 8120 * LCDA mode! In LCDA mode, the bridge is NOT in slave mode, 8121 * so this is the only safe way: Disable the bridge ONLY if 8122 * in Slave Mode, and don't bother if not. 8123 */ 8124 8125 if(flags & SISVGA_SR_FONTS) { 8126 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO+0x30); 8127 SiSSetLVDSetc(pSiS->SiS_Pr); 8128 SiS_GetVBType(pSiS->SiS_Pr); 8129 SiS_DisableBridge(pSiS->SiS_Pr); 8130 SiSVGAProtect(pScrn, TRUE); 8131 } 8132 8133 SiSVGARestore(pScrn, sisReg, flags); 8134 8135 if(flags & SISVGA_SR_FONTS) { 8136 SiSVGAProtect(pScrn, FALSE); 8137 SiS_EnableBridge(pSiS->SiS_Pr); 8138 andSISIDXREG(SISSR, 0x01, ~0x20); /* Display on */ 8139 } 8140 8141 } else { 8142 8143 SiSVGAProtect(pScrn, TRUE); 8144 SiSVGARestore(pScrn, sisReg, flags); 8145 SiSVGAProtect(pScrn, FALSE); 8146 8147 } 8148 8149 SiSFixupSR11(pScrn); 8150 8151#ifdef TWDEBUG 8152 { 8153 SISRegPtr pReg = &pSiS->ModeReg; 8154 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8155 "REAL REGISTER CONTENTS AFTER RESTORE BY SETMODE:\n"); 8156 (*pSiS->SiSSave)(pScrn, pReg); 8157 } 8158#endif 8159 8160 sisRestoreExtRegisterLock(pSiS,sisReg->sisRegs3C4[0x05],sisReg->sisRegs3D4[0x80]); 8161 8162 } else { /* All other chipsets */ 8163 8164 SiSVGAProtect(pScrn, TRUE); 8165 8166#ifdef UNLOCK_ALWAYS 8167 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8168#endif 8169 8170 (*pSiS->SiSRestore)(pScrn, sisReg); 8171 8172 SiSVGAProtect(pScrn, TRUE); 8173 8174 SiSVGARestore(pScrn, sisReg, flags); 8175 8176 /* Restore TV. This is rather complicated, but if we don't do it, 8177 * TV output will flicker terribly 8178 */ 8179 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 8180 if(sisReg->sis6326tv[0] & 0x04) { 8181 UChar tmp; 8182 int val; 8183 8184 orSISIDXREG(SISSR, 0x01, 0x20); 8185 tmp = SiS6326GetTVReg(pScrn,0x00); 8186 tmp &= ~0x04; 8187 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 8188 SiS6326SetTVReg(pScrn,0x00,tmp); 8189 for(val=0; val < 2; val++) { 8190 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 8191 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 8192 } 8193 SiS6326SetTVReg(pScrn, 0x00, sisReg->sis6326tv[0]); 8194 tmp = inSISREG(SISINPSTAT); 8195 outSISREG(SISAR, 0x20); 8196 tmp = inSISREG(SISINPSTAT); 8197 while(inSISREG(SISINPSTAT) & 0x01); 8198 while(!(inSISREG(SISINPSTAT) & 0x01)); 8199 andSISIDXREG(SISSR, 0x01, ~0x20); 8200 for(val=0; val < 10; val++) { 8201 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 8202 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 8203 } 8204 andSISIDXREG(SISSR, 0x01, ~0x20); 8205 } 8206 } 8207 8208 sisRestoreExtRegisterLock(pSiS,sisReg->sisRegs3C4[5],sisReg->sisRegs3D4[0x80]); 8209 8210 SiSVGAProtect(pScrn, FALSE); 8211 } 8212} 8213 8214static void 8215SISVESARestore(ScrnInfoPtr pScrn) 8216{ 8217 SISPtr pSiS = SISPTR(pScrn); 8218#ifdef SISVRAMQ 8219 SISRegPtr sisReg = &pSiS->SavedReg; 8220#endif 8221 8222 if(pSiS->UseVESA) { 8223 SISVESASaveRestore(pScrn, MODE_RESTORE); 8224#ifdef SISVRAMQ 8225 /* Restore queue mode registers on 315/330/340 series */ 8226 /* (This became necessary due to the switch to VRAM queue) */ 8227 SiSRestoreQueueMode(pSiS, sisReg); 8228#endif 8229 } 8230} 8231 8232/* Restore bridge config registers - to be called BEFORE VESARestore */ 8233static void 8234SISBridgeRestore(ScrnInfoPtr pScrn) 8235{ 8236 SISPtr pSiS = SISPTR(pScrn); 8237 8238#ifdef SISDUALHEAD 8239 /* We only restore for master head */ 8240 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 8241#endif 8242 8243 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 8244 SiSRestoreBridge(pScrn, &pSiS->SavedReg); 8245 } 8246} 8247 8248/* Our BlockHandler */ 8249static void 8250SISBlockHandler(BLOCKHANDLER_ARGS_DECL) 8251{ 8252 SCREEN_PTR(arg); 8253 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 8254 SISPtr pSiS = SISPTR(pScrn); 8255 8256 pScreen->BlockHandler = pSiS->BlockHandler; 8257 (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS); 8258 pScreen->BlockHandler = SISBlockHandler; 8259 8260#ifdef SISDUALHEAD 8261 if(pSiS->NeedCopyFastVidCpy) { 8262 SISEntPtr pSiSEnt = pSiS->entityPrivate; 8263 if(pSiSEnt->HaveFastVidCpy) { 8264 pSiS->NeedCopyFastVidCpy = FALSE; 8265 pSiS->SiSFastVidCopy = pSiSEnt->SiSFastVidCopy; 8266 pSiS->SiSFastMemCopy = pSiSEnt->SiSFastMemCopy; 8267 pSiS->SiSFastVidCopyFrom = pSiSEnt->SiSFastVidCopyFrom; 8268 pSiS->SiSFastMemCopyFrom = pSiSEnt->SiSFastMemCopyFrom; 8269 } 8270 } 8271#endif 8272 8273 if(pSiS->VideoTimerCallback) { 8274 (*pSiS->VideoTimerCallback)(pScrn, currentTime.milliseconds); 8275 } 8276 8277#ifdef SIS_USE_XAA 8278 if(pSiS->RenderCallback) { 8279 (*pSiS->RenderCallback)(pScrn); 8280 } 8281#endif 8282#ifdef SIS_USE_EXA 8283 if(pSiS->ExaRenderCallback) { 8284 (*pSiS->ExaRenderCallback)(pScrn); 8285 } 8286#endif 8287} 8288 8289 8290 8291/* Do screen blanking; DPMS handling 8292 * 8293 * Mandatory; latter optional 8294 */ 8295 8296static void 8297SiSHandleBackLight(SISPtr pSiS, Bool blon) 8298{ 8299 UChar sr11mask = (pSiS->SiS_Pr->SiS_SensibleSR11) ? 0x03 : 0xf3; 8300 8301 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) { 8302 8303 if(!blon) { 8304 SiS_SiS30xBLOff(pSiS->SiS_Pr); 8305 } else { 8306 SiS_SiS30xBLOn(pSiS->SiS_Pr); 8307 } 8308 8309 } else if( ((pSiS->VGAEngine == SIS_300_VGA) && 8310 (pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH))) || 8311 ((pSiS->VGAEngine == SIS_315_VGA) && 8312 ((pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS)) ) { 8313 8314 if(!blon) { 8315 setSISIDXREG(SISSR, 0x11, sr11mask, 0x08); 8316 } else { 8317 setSISIDXREG(SISSR, 0x11, sr11mask, 0x00); 8318 } 8319 8320 } else if((pSiS->VGAEngine == SIS_315_VGA) && 8321 (pSiS->VBFlags2 & VB2_CHRONTEL)) { 8322 8323 if(!blon) { 8324 SiS_Chrontel701xBLOff(pSiS->SiS_Pr); 8325 } else { 8326 SiS_Chrontel701xBLOn(pSiS->SiS_Pr); 8327 } 8328 8329 } 8330} 8331 8332static Bool 8333SISSaveScreen(ScreenPtr pScreen, int mode) 8334{ 8335 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 8336 SISPtr pSiS; 8337 Bool IsUnblank = xf86IsUnblank(mode) ? TRUE : FALSE; 8338 8339 if((pScrn == NULL) || (!pScrn->vtSema)) return TRUE; 8340 8341 pSiS = SISPTR(pScrn); 8342 8343#ifdef UNLOCK_ALWAYS 8344 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8345#endif 8346 8347 if(pSiS->VBFlags & (CRT2_LCD | CRT1_LCDA)) { 8348 SiSHandleBackLight(pSiS, IsUnblank); 8349 } 8350 8351 if(!SiSBridgeIsInSlaveMode(pScrn)) { 8352 return SiSVGASaveScreen(pScreen, mode); 8353 } 8354 8355 return TRUE; 8356} 8357 8358#ifdef SISDUALHEAD 8359/* SaveScreen for dual head mode */ 8360static Bool 8361SISSaveScreenDH(ScreenPtr pScreen, int mode) 8362{ 8363 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 8364 SISPtr pSiS; 8365 Bool IsUnblank = xf86IsUnblank(mode) ? TRUE : FALSE; 8366 8367 if((pScrn == NULL) || (!pScrn->vtSema)) return TRUE; 8368 8369 pSiS = SISPTR(pScrn); 8370 8371 if( (pSiS->SecondHead) && 8372 ((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) ) { 8373 8374 /* Slave head is always CRT1 */ 8375 /* (No backlight handling on TMDS bridges) */ 8376 return SiSVGASaveScreen(pScreen, mode); 8377 8378 } else { 8379 8380 /* Master head is always CRT2 */ 8381 /* But we land here for LCDA, too (if bridge is SiS LVDS type) */ 8382 8383 /* We can only blank LCD, not other CRT2 devices */ 8384 if(pSiS->VBFlags & (CRT2_LCD|CRT1_LCDA)) { 8385 8386#ifdef UNLOCK_ALWAYS 8387 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8388#endif 8389 SiSHandleBackLight(pSiS, IsUnblank); 8390 8391 } 8392 8393 } 8394 return TRUE; 8395} 8396#endif 8397 8398static void 8399SISDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags) 8400{ 8401 SISPtr pSiS = SISPTR(pScrn); 8402 Bool docrt1 = TRUE, docrt2 = TRUE, backlight = TRUE; 8403 UChar sr1=0, cr17=0, cr63=0, pmreg=0, sr7=0; 8404 UChar p1_13=0, p2_0=0, oldpmreg=0; 8405 8406 if(!pScrn->vtSema) return; 8407 8408 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, 8409 "SISDisplayPowerManagementSet(%d)\n", PowerManagementMode); 8410 8411#ifdef SISDUALHEAD 8412 if(pSiS->DualHeadMode) { 8413 if(pSiS->SecondHead) docrt2 = FALSE; 8414 else docrt1 = FALSE; 8415 } 8416#endif 8417 8418 /* FIXME: in old servers, DPMSSet was supposed to be called without open 8419 * the correct PCI bridges before access the hardware. Now we have this 8420 * hook wrapped by the vga arbiter which should do all the work, in 8421 * kernels that implement it. For this case we might not want this hack 8422 * bellow. 8423 */ 8424 outSISIDXREG(SISSR,0x05,0x86); 8425 inSISIDXREG(SISSR,0x05,pmreg); 8426 if(pmreg != 0xa1) return; 8427 8428#ifdef UNLOCK_ALWAYS 8429 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8430#endif 8431 8432 switch(PowerManagementMode) { 8433 8434 case DPMSModeOn: /* HSync: On, VSync: On */ 8435 sr1 = 0x00; 8436 cr17 = 0x80; 8437 pmreg = 0x00; 8438 cr63 = 0x00; 8439 sr7 = 0x10; 8440 p2_0 = 0x20; 8441 p1_13 = 0x00; 8442 backlight = TRUE; 8443 break; 8444 8445 case DPMSModeSuspend: /* HSync: On, VSync: Off */ 8446 sr1 = 0x20; 8447 cr17 = 0x80; 8448 pmreg = 0x80; 8449 cr63 = 0x40; 8450 sr7 = 0x00; 8451 p2_0 = 0x40; 8452 p1_13 = 0x80; 8453 backlight = FALSE; 8454 break; 8455 8456 case DPMSModeStandby: /* HSync: Off, VSync: On */ 8457 sr1 = 0x20; 8458 cr17 = 0x80; 8459 pmreg = 0x40; 8460 cr63 = 0x40; 8461 sr7 = 0x00; 8462 p2_0 = 0x80; 8463 p1_13 = 0x40; 8464 backlight = FALSE; 8465 break; 8466 8467 case DPMSModeOff: /* HSync: Off, VSync: Off */ 8468 sr1 = 0x20; 8469 cr17 = 0x00; 8470 pmreg = 0xc0; 8471 cr63 = 0x40; 8472 sr7 = 0x00; 8473 p2_0 = 0xc0; 8474 p1_13 = 0xc0; 8475 backlight = FALSE; 8476 break; 8477 8478 default: 8479 return; 8480 } 8481 8482 oldpmreg = pmreg; 8483 8484 if((docrt2 && (pSiS->VBFlags & CRT2_LCD)) || 8485 (docrt1 && (pSiS->VBFlags & CRT1_LCDA))) { 8486 SiSHandleBackLight(pSiS, backlight); 8487 } 8488 8489 if(docrt1) { 8490 switch(pSiS->VGAEngine) { 8491 case SIS_OLD_VGA: 8492 case SIS_530_VGA: 8493 setSISIDXREG(SISSR, 0x01, ~0x20, sr1); /* Set/Clear "Display On" bit */ 8494 inSISIDXREG(SISSR, 0x11, oldpmreg); 8495 setSISIDXREG(SISCR, 0x17, 0x7f, cr17); 8496 setSISIDXREG(SISSR, 0x11, 0x3f, pmreg); 8497 break; 8498 case SIS_315_VGA: 8499 if( (!pSiS->CRT1off) && 8500 ((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) ) { 8501 setSISIDXREG(SISCR, pSiS->myCR63, 0xbf, cr63); 8502 setSISIDXREG(SISSR, 0x07, 0xef, sr7); 8503 } 8504 /* fall through */ 8505 default: 8506 if(!SiSBridgeIsInSlaveMode(pScrn)) { 8507 setSISIDXREG(SISSR, 0x01, ~0x20, sr1); /* Set/Clear "Display On" bit */ 8508 } 8509 if((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 8510 inSISIDXREG(SISSR, 0x1f, oldpmreg); 8511 if((!pSiS->CRT1off) && (!SiSBridgeIsInSlaveMode(pScrn))) { 8512 setSISIDXREG(SISSR, 0x1f, 0x3f, pmreg); 8513 } 8514 } 8515 } 8516 oldpmreg &= 0xc0; 8517 } 8518 8519 if(docrt2) { 8520 if(pSiS->VBFlags & CRT2_LCD) { 8521 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && 8522 (!(pSiS->VBFlags2 & VB2_30xBDH))) { 8523 if(pSiS->VGAEngine == SIS_300_VGA) { 8524 SiS_UnLockCRT2(pSiS->SiS_Pr); 8525 setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13); 8526 } 8527 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) p2_0 |= 0x20; 8528 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); 8529 } 8530 } else if(pSiS->VBFlags & (CRT2_VGA | CRT2_TV)) { 8531 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 8532 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); 8533 } 8534 } 8535 } 8536 8537 if( (docrt1) && 8538 (pmreg != oldpmreg) && 8539 ((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) ) { 8540 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 8541 usleep(10000); 8542 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 8543 } 8544 8545} 8546 8547/* Mandatory 8548 * This gets called at the start of each server generation 8549 * 8550 * We use pScrn and not CurrentLayout here, because the 8551 * properties we use have not changed (displayWidth, 8552 * depth, bitsPerPixel) 8553 */ 8554static Bool 8555SISScreenInit(SCREEN_INIT_ARGS_DECL) 8556{ 8557 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 8558 SISPtr pSiS = SISPTR(pScrn); 8559 VisualPtr visual; 8560 ULong OnScreenSize; 8561 int ret, height, width, displayWidth; 8562 UChar *FBStart; 8563#ifdef SISDUALHEAD 8564 SISEntPtr pSiSEnt = NULL; 8565#endif 8566 8567#ifdef SISDUALHEAD 8568 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) { 8569#endif 8570 SiS_LoadInitVBE(pScrn); 8571#ifdef SISDUALHEAD 8572 } 8573#endif 8574 8575#ifdef SISDUALHEAD 8576 if(pSiS->DualHeadMode) { 8577 pSiSEnt = pSiS->entityPrivate; 8578 pSiSEnt->refCount++; 8579 } 8580#endif 8581 8582#ifdef SIS_PC_PLATFORM 8583 /* Map 64k VGA window for saving/restoring CGA fonts */ 8584 SiS_MapVGAMem(pScrn); 8585#endif 8586 8587 /* Map the SiS memory and MMIO areas */ 8588 if(!SISMapMem(pScrn)) { 8589 SISErrorLog(pScrn, "SiSMapMem() failed\n"); 8590 return FALSE; 8591 } 8592 8593 SiS_SiSFB_Lock(pScrn, TRUE); 8594 8595#ifdef UNLOCK_ALWAYS 8596 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8597#endif 8598 8599 /* Enable TurboQueue so that SISSave() saves it in enabled 8600 * state. If we don't do this, X will hang after a restart! 8601 * (Happens for some unknown reason only when using VESA 8602 * for mode switching; assumingly a BIOS issue.) 8603 * This is done on 300 and 315 series only. 8604 */ 8605 if(pSiS->UseVESA) { 8606#ifdef SISVRAMQ 8607 if(pSiS->VGAEngine != SIS_315_VGA) 8608#endif 8609 SiSEnableTurboQueue(pScrn); 8610 } 8611 8612 /* Save the current state */ 8613 SISSave(pScrn); 8614 8615 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 8616 8617 if(!pSiS->OldMode) { 8618 8619 /* Try to find out current (=old) mode number 8620 * (Do this only if not sisfb has told us its mode yet) 8621 */ 8622 8623 /* Read 0:449 which the BIOS sets to the current mode number 8624 * Unfortunately, this not reliable since the int10 emulation 8625 * does not change this. So if we call the VBE later, this 8626 * byte won't be touched (which is why we set this manually 8627 * then). 8628 */ 8629 UChar myoldmode = SiS_GetSetModeID(pScrn, 0xFF); 8630 UChar cr30, cr31; 8631 8632 /* Read CR34 which the BIOS sets to the current mode number for CRT2 8633 * This is - of course - not reliable if the machine has no video 8634 * bridge... 8635 */ 8636 inSISIDXREG(SISCR, 0x34, pSiS->OldMode); 8637 inSISIDXREG(SISCR, 0x30, cr30); 8638 inSISIDXREG(SISCR, 0x31, cr31); 8639 8640 /* What if CR34 is different from the BIOS scratch byte? */ 8641 if(pSiS->OldMode != myoldmode) { 8642 /* If no bridge output is active, trust the BIOS scratch byte */ 8643 if( (!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) || 8644 (pSiS->OldMode == 0) || 8645 (!cr31 && !cr30) || 8646 (cr31 & 0x20) ) { 8647 pSiS->OldMode = myoldmode; 8648 } 8649 /* ..else trust CR34 */ 8650 } 8651 8652 /* Newer 650 BIOSes set CR34 to 0xff if the mode has been 8653 * "patched", for instance for 80x50 text mode. (That mode 8654 * has no number of its own, it's 0x03 like 80x25). In this 8655 * case, we trust the BIOS scratch byte (provided that any 8656 * of these two is valid). 8657 */ 8658 if(pSiS->OldMode > 0x7f) { 8659 pSiS->OldMode = myoldmode; 8660 } 8661 } 8662#ifdef SISDUALHEAD 8663 if(pSiS->DualHeadMode) { 8664 if(!pSiS->SecondHead) pSiSEnt->OldMode = pSiS->OldMode; 8665 else pSiS->OldMode = pSiSEnt->OldMode; 8666 } 8667#endif 8668 } 8669 8670 /* RandR resets screen mode and size in CloseScreen(), hence 8671 * we need to adapt our VBFlags to the initial state if the 8672 * current mode has changed since closescreen() (or Screeninit() 8673 * for the first instance) 8674 */ 8675 if(pScrn->currentMode != pSiS->currentModeLast) { 8676 pSiS->VBFlags = pSiS->VBFlags_backup = pSiS->VBFlagsInit; 8677 } 8678 8679 /* Copy our detected monitor gammas, part 2. Note that device redetection 8680 * is not supported in DHM, so there is no need to do that anytime later. 8681 */ 8682#ifdef SISDUALHEAD 8683 if(pSiS->DualHeadMode) { 8684 if(!pSiS->SecondHead) { 8685 /* CRT2 */ 8686 pSiS->CRT1VGAMonitorGamma = pSiSEnt->CRT1VGAMonitorGamma; 8687 } else { 8688 /* CRT1 */ 8689 pSiS->CRT2VGAMonitorGamma = pSiSEnt->CRT2VGAMonitorGamma; 8690 } 8691 if(!pSiS->CRT2LCDMonitorGamma) pSiS->CRT2LCDMonitorGamma = pSiSEnt->CRT2LCDMonitorGamma; 8692 } 8693#endif 8694 8695 /* Initialize the first mode */ 8696 if(!SISModeInit(pScrn, pScrn->currentMode)) { 8697 SISErrorLog(pScrn, "SiSModeInit() failed\n"); 8698 return FALSE; 8699 } 8700 8701 /* Darken the screen for aesthetic reasons */ 8702 /* Not using Dual Head variant on purpose; we darken 8703 * the screen for both displays, and un-darken 8704 * it when the second head is finished 8705 */ 8706 SISSaveScreen(pScreen, SCREEN_SAVER_ON); 8707 8708 /* Set the viewport */ 8709 SISAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 8710 8711 /* Reset visual list. */ 8712 miClearVisualTypes(); 8713 8714 /* Setup the visuals we support. */ 8715 8716 /* 8717 * For bpp > 8, the default visuals are not acceptable because we only 8718 * support TrueColor and not DirectColor. 8719 */ 8720 if(!miSetVisualTypes(pScrn->depth, 8721 (pScrn->bitsPerPixel > 8) ? 8722 TrueColorMask : miGetDefaultVisualMask(pScrn->depth), 8723 pScrn->rgbBits, pScrn->defaultVisual)) { 8724 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8725 SISErrorLog(pScrn, "miSetVisualTypes() failed (bpp %d)\n", 8726 pScrn->bitsPerPixel); 8727 return FALSE; 8728 } 8729 8730 width = pScrn->virtualX; 8731 height = pScrn->virtualY; 8732 displayWidth = pScrn->displayWidth; 8733 8734 if(pSiS->Rotate) { 8735 height = pScrn->virtualX; 8736 width = pScrn->virtualY; 8737 } 8738 8739 if(pSiS->ShadowFB) { 8740 pSiS->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); 8741 pSiS->ShadowPtr = malloc(pSiS->ShadowPitch * height); 8742 displayWidth = pSiS->ShadowPitch / (pScrn->bitsPerPixel >> 3); 8743 FBStart = pSiS->ShadowPtr; 8744 } else { 8745 pSiS->ShadowPtr = NULL; 8746 FBStart = pSiS->FbBase; 8747 } 8748 8749 if(!miSetPixmapDepths()) { 8750 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8751 SISErrorLog(pScrn, "miSetPixmapDepths() failed\n"); 8752 return FALSE; 8753 } 8754 8755 /* Point cmdQueuePtr to pSiSEnt for shared usage 8756 * (same technique is then eventually used in DRIScreeninit) 8757 * For 315/330 series, this is done in EnableTurboQueue 8758 * which has already been called during ModeInit(). 8759 */ 8760#ifdef SISDUALHEAD 8761 if(pSiS->SecondHead) 8762 pSiS->cmdQueueLenPtr = &(SISPTR(pSiSEnt->pScrn_1)->cmdQueueLen); 8763 else 8764#endif 8765 pSiS->cmdQueueLenPtr = &(pSiS->cmdQueueLen); 8766 8767 pSiS->cmdQueueLen = 0; /* Force an EngineIdle() at start */ 8768 8769#ifdef SISDRI 8770 if(pSiS->loadDRI) { 8771#ifdef SISDUALHEAD 8772 /* No DRI in dual head mode */ 8773 if(pSiS->DualHeadMode) { 8774 pSiS->directRenderingEnabled = FALSE; 8775 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8776 "DRI not supported in Dual Head mode\n"); 8777 } else 8778#endif 8779 if(pSiS->VGAEngine != SIS_315_VGA) { 8780 /* Force the initialization of the context */ 8781 pSiS->directRenderingEnabled = SISDRIScreenInit(pScreen); 8782 } else { 8783 xf86DrvMsg(pScrn->scrnIndex, X_NOT_IMPLEMENTED, 8784 "DRI not supported on this chipset\n"); 8785 pSiS->directRenderingEnabled = FALSE; 8786 } 8787 } 8788#endif 8789 8790 /* Call the framebuffer layer's ScreenInit function and fill in other 8791 * pScreen fields. 8792 */ 8793 switch(pScrn->bitsPerPixel) { 8794 case 24: 8795 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 8796 ret = FALSE; 8797 break; 8798 } 8799 /* fall through */ 8800 case 8: 8801 case 16: 8802 case 32: 8803 ret = fbScreenInit(pScreen, FBStart, width, 8804 height, pScrn->xDpi, pScrn->yDpi, 8805 displayWidth, pScrn->bitsPerPixel); 8806 break; 8807 default: 8808 ret = FALSE; 8809 break; 8810 } 8811 if(!ret) { 8812 SISErrorLog(pScrn, "Unsupported bpp (%d) or fbScreenInit() failed\n", 8813 pScrn->bitsPerPixel); 8814 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8815 return FALSE; 8816 } 8817 8818 /* Fixup RGB ordering */ 8819 if(pScrn->bitsPerPixel > 8) { 8820 visual = pScreen->visuals + pScreen->numVisuals; 8821 while (--visual >= pScreen->visuals) { 8822 if((visual->class | DynamicClass) == DirectColor) { 8823 visual->offsetRed = pScrn->offset.red; 8824 visual->offsetGreen = pScrn->offset.green; 8825 visual->offsetBlue = pScrn->offset.blue; 8826 visual->redMask = pScrn->mask.red; 8827 visual->greenMask = pScrn->mask.green; 8828 visual->blueMask = pScrn->mask.blue; 8829 } 8830 } 8831 } 8832 8833 /* Initialize RENDER extension (must be after RGB ordering fixed) */ 8834 fbPictureInit(pScreen, 0, 0); 8835 8836 /* Hardware cursor needs to wrap this layer */ 8837 if(!pSiS->ShadowFB) SISDGAInit(pScreen); 8838 8839 xf86SetBlackWhitePixels(pScreen); 8840 8841 /* Initialize the accelerators */ 8842 switch(pSiS->VGAEngine) { 8843 case SIS_530_VGA: 8844 case SIS_300_VGA: 8845 SiS300AccelInit(pScreen); 8846 break; 8847 case SIS_315_VGA: 8848 SiS315AccelInit(pScreen); 8849 break; 8850 default: 8851 SiSAccelInit(pScreen); 8852 } 8853 8854#ifdef TWDEBUG 8855 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CPUFlags %x\n", pSiS->CPUFlags); 8856#endif 8857 8858 /* Benchmark memcpy() methods (needs FB manager initialized) */ 8859 /* Dual head: Do this AFTER the mode for CRT1 has been set */ 8860 pSiS->NeedCopyFastVidCpy = FALSE; 8861 if(!pSiS->SiSFastVidCopyDone) { 8862#ifdef SISDUALHEAD 8863 if(pSiS->DualHeadMode) { 8864 if(pSiS->SecondHead) { 8865 pSiSEnt->SiSFastVidCopy = SiSVidCopyInit(pScreen, &pSiSEnt->SiSFastMemCopy, FALSE); 8866 pSiSEnt->SiSFastVidCopyFrom = SiSVidCopyGetDefault(); 8867 pSiSEnt->SiSFastMemCopyFrom = SiSVidCopyGetDefault(); 8868#ifdef SIS_USE_EXA 8869 if(pSiS->useEXA) { 8870 pSiSEnt->SiSFastVidCopyFrom = SiSVidCopyInit(pScreen, &pSiSEnt->SiSFastMemCopyFrom, TRUE); 8871 } 8872#endif /* EXA */ 8873 pSiSEnt->HaveFastVidCpy = TRUE; 8874 pSiS->SiSFastVidCopy = pSiSEnt->SiSFastVidCopy; 8875 pSiS->SiSFastMemCopy = pSiSEnt->SiSFastMemCopy; 8876 pSiS->SiSFastVidCopyFrom = pSiSEnt->SiSFastVidCopyFrom; 8877 pSiS->SiSFastMemCopyFrom = pSiSEnt->SiSFastMemCopyFrom; 8878 } else { 8879 pSiS->NeedCopyFastVidCpy = TRUE; 8880 } 8881 } else { 8882#endif 8883 pSiS->SiSFastVidCopy = SiSVidCopyInit(pScreen, &pSiS->SiSFastMemCopy, FALSE); 8884 pSiS->SiSFastVidCopyFrom = SiSVidCopyGetDefault(); 8885 pSiS->SiSFastMemCopyFrom = SiSVidCopyGetDefault(); 8886#ifdef SIS_USE_EXA 8887 if(pSiS->useEXA) { 8888 pSiS->SiSFastVidCopyFrom = SiSVidCopyInit(pScreen, &pSiS->SiSFastMemCopyFrom, TRUE); 8889 } 8890#endif /* EXA */ 8891#ifdef SISDUALHEAD 8892 } 8893#endif 8894 } 8895 pSiS->SiSFastVidCopyDone = TRUE; 8896 8897 xf86SetBackingStore(pScreen); 8898 xf86SetSilkenMouse(pScreen); 8899 8900 /* Initialise cursor functions */ 8901 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 8902 8903 if(pSiS->HWCursor) { 8904 SiSHWCursorInit(pScreen); 8905 } 8906 8907#ifdef SISDUALHEAD 8908 if(!pSiS->DualHeadMode) { 8909#endif 8910 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && (pScrn->depth > 8)) { 8911 8912 pSiS->CRT2ColNum = 1 << pScrn->rgbBits; 8913 8914 if((pSiS->crt2gcolortable = malloc(pSiS->CRT2ColNum * 2 * sizeof(LOCO)))) { 8915 pSiS->crt2colors = &pSiS->crt2gcolortable[pSiS->CRT2ColNum]; 8916 if((pSiS->crt2cindices = malloc(256 * sizeof(int)))) { 8917 int i = pSiS->CRT2ColNum; 8918 SISCalculateGammaRampCRT2(pScrn); 8919 while(i--) pSiS->crt2cindices[i] = i; 8920 } else { 8921 free(pSiS->crt2gcolortable); 8922 pSiS->crt2gcolortable = NULL; 8923 pSiS->CRT2SepGamma = FALSE; 8924 } 8925 } else { 8926 pSiS->CRT2SepGamma = FALSE; 8927 } 8928 8929 if(!pSiS->crt2cindices) { 8930 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 8931 "Failed to allocate cmap for CRT2, separate gamma correction disabled\n"); 8932 } 8933 8934 } 8935#ifdef SISDUALHEAD 8936 } else pSiS->CRT2SepGamma = FALSE; 8937#endif 8938 8939 /* Initialise default colormap */ 8940 if(!miCreateDefColormap(pScreen)) { 8941 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8942 SISErrorLog(pScrn, "miCreateDefColormap() failed\n"); 8943 return FALSE; 8944 } 8945 8946 if(!xf86HandleColormaps(pScreen, 256, (pScrn->depth == 8) ? 8 : pScrn->rgbBits, 8947 SISLoadPalette, NULL, 8948 CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH)) { 8949 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8950 SISErrorLog(pScrn, "xf86HandleColormaps() failed\n"); 8951 return FALSE; 8952 } 8953 8954 /* Recalculate our gamma ramp for brightness feature */ 8955#ifdef SISGAMMARAMP 8956 if((pSiS->GammaBriR != 1000) || 8957 (pSiS->GammaBriB != 1000) || 8958 (pSiS->GammaBriG != 1000) || 8959 (pSiS->NewGammaBriR != 0.0) || 8960 (pSiS->NewGammaBriG != 0.0) || 8961 (pSiS->NewGammaBriB != 0.0) || 8962 (pSiS->NewGammaConR != 0.0) || 8963 (pSiS->NewGammaConG != 0.0) || 8964 (pSiS->NewGammaConB != 0.0)) { 8965 SISCalculateGammaRamp(pScreen, pScrn); 8966 } 8967#endif 8968 8969 /* Initialize Shadow framebuffer and screen rotation/reflection */ 8970 if(pSiS->ShadowFB) { 8971 RefreshAreaFuncPtr refreshArea = SISRefreshArea; 8972 8973 if(pSiS->Rotate) { 8974 if(!pSiS->PointerMoved) pSiS->PointerMoved = pScrn->PointerMoved; 8975 pScrn->PointerMoved = SISPointerMoved; 8976 switch(pScrn->bitsPerPixel) { 8977 case 8: refreshArea = SISRefreshArea8; break; 8978 case 16: refreshArea = SISRefreshArea16; break; 8979 case 24: refreshArea = SISRefreshArea24; break; 8980 case 32: refreshArea = SISRefreshArea32; break; 8981 } 8982#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 8983 xf86DisableRandR(); 8984 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8985 "Driver rotation enabled, disabling RandR\n"); 8986#endif 8987 } else if(pSiS->Reflect) { 8988 switch(pScrn->bitsPerPixel) { 8989 case 8: 8990 case 16: 8991 case 32: 8992 if(!pSiS->PointerMoved) pSiS->PointerMoved = pScrn->PointerMoved; 8993 pScrn->PointerMoved = SISPointerMovedReflect; 8994 refreshArea = SISRefreshAreaReflect; 8995#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 8996 xf86DisableRandR(); 8997 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8998 "Driver reflection enabled, disabling RandR\n"); 8999#endif 9000 break; 9001 default: 9002 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 9003 "Reflection not supported at this framebuffer depth\n"); 9004 } 9005 } 9006 9007 ShadowFBInit(pScreen, refreshArea); 9008 } 9009 9010 xf86DPMSInit(pScreen, (DPMSSetProcPtr)SISDisplayPowerManagementSet, 0); 9011 9012 /* Init memPhysBase and fbOffset in pScrn */ 9013 pScrn->memPhysBase = pSiS->FbAddress; 9014 pScrn->fbOffset = 0; 9015 9016 /* Initialize Xv */ 9017 pSiS->ResetXv = pSiS->ResetXvGamma = pSiS->ResetXvDisplay = NULL; 9018#if (XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,99,0,0)) || (defined(XvExtension)) 9019 if((!pSiS->NoXvideo) && (!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY))) { 9020 9021 if((pSiS->VGAEngine == SIS_300_VGA) || 9022 (pSiS->VGAEngine == SIS_315_VGA)) { 9023 9024 const char *using = "Using SiS300/315/330/340 series HW Xv"; 9025 9026#ifdef SISDUALHEAD 9027 if(pSiS->DualHeadMode) { 9028 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9029 "%s on CRT%d\n", using, (pSiS->SecondHead ? 1 : 2)); 9030 if(!pSiS->hasTwoOverlays) { 9031 if( (pSiS->XvOnCRT2 && pSiS->SecondHead) || 9032 (!pSiS->XvOnCRT2 && !pSiS->SecondHead) ) { 9033 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9034 "However, video overlay will by default only be visible on CRT%d\n", 9035 pSiS->XvOnCRT2 ? 2 : 1); 9036 } 9037 } 9038 } else { 9039#endif 9040 if(pSiS->hasTwoOverlays) { 9041 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s\n", using); 9042 } else { 9043 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s by default on CRT%d\n", 9044 using, (pSiS->XvOnCRT2 ? 2 : 1)); 9045 } 9046#ifdef SISDUALHEAD 9047 } 9048#endif 9049 9050 SISInitVideo(pScreen); 9051 9052 if(pSiS->blitadaptor) { 9053 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9054 "Default Xv adaptor is Video %s\n", 9055 pSiS->XvDefAdaptorBlit ? "Blitter" : "Overlay"); 9056 } 9057 9058 } else if(pSiS->Chipset == PCI_CHIP_SIS530 || 9059 pSiS->Chipset == PCI_CHIP_SIS6326 || 9060 pSiS->Chipset == PCI_CHIP_SIS5597) { 9061 9062 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9063 "Using SiS5597/5598/6326/530/620 HW Xv\n" ); 9064 9065 SIS6326InitVideo(pScreen); 9066 9067 } else { /* generic Xv */ 9068 9069 XF86VideoAdaptorPtr *ptr; 9070 int n = xf86XVListGenericAdaptors(pScrn, &ptr); 9071 9072 if(n) { 9073 xf86XVScreenInit(pScreen, ptr, n); 9074 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using generic Xv\n" ); 9075 } 9076 9077 } 9078 } 9079#endif 9080 9081#ifdef SISDRI 9082 if(pSiS->loadDRI) { 9083 if(pSiS->directRenderingEnabled) { 9084 /* Now that mi, drm and others have done their thing, 9085 * complete the DRI setup. 9086 */ 9087 pSiS->directRenderingEnabled = SISDRIFinishScreenInit(pScreen); 9088 } 9089 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering %s\n", 9090 pSiS->directRenderingEnabled ? "enabled" : "disabled"); 9091 /* TODO */ 9092 /* if(pSiS->directRenderingEnabled) SISSetLFBConfig(pSiS); */ 9093 } 9094#endif 9095 9096 /* Wrap some funcs, initialize pseudo-Xinerama and setup remaining SD flags */ 9097 9098 pSiS->SiS_SD_Flags &= ~(SiS_SD_PSEUDOXINERAMA); 9099#ifdef SISMERGED 9100 if(pSiS->MergedFB) { 9101 pSiS->PointerMoved = pScrn->PointerMoved; 9102 pScrn->PointerMoved = SISMergedPointerMoved; 9103 pSiS->Rotate = 0; 9104 pSiS->Reflect = 0; 9105 pSiS->ShadowFB = FALSE; 9106#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 9107 if(pSiS->CRT1XOffs || pSiS->CRT1YOffs || pSiS->CRT2XOffs || pSiS->CRT2YOffs) { 9108 xf86DisableRandR(); 9109 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9110 "MergedFB: CRT2Position offset used, disabling RandR\n"); 9111 } 9112#endif 9113#ifdef SISXINERAMA 9114 if(pSiS->UseSiSXinerama) { 9115 SiSnoPanoramiXExtension = FALSE; 9116 SiSXineramaExtensionInit(pScrn); 9117 if(!SiSnoPanoramiXExtension) { 9118 pSiS->SiS_SD_Flags |= SiS_SD_PSEUDOXINERAMA; 9119 if(pSiS->HaveNonRect) { 9120 /* Reset the viewport (now eventually non-recangular) */ 9121 SISAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 9122 } 9123 } 9124 } else { 9125 pSiS->MouseRestrictions = FALSE; 9126 } 9127#endif 9128 } 9129#endif 9130 9131 /* Wrap CloseScreen and set up SaveScreen */ 9132 pSiS->CloseScreen = pScreen->CloseScreen; 9133 pScreen->CloseScreen = SISCloseScreen; 9134#ifdef SISDUALHEAD 9135 if(pSiS->DualHeadMode) 9136 pScreen->SaveScreen = SISSaveScreenDH; 9137 else 9138#endif 9139 pScreen->SaveScreen = SISSaveScreen; 9140 9141 /* Install BlockHandler */ 9142 pSiS->BlockHandler = pScreen->BlockHandler; 9143 pScreen->BlockHandler = SISBlockHandler; 9144 9145 /* Report any unused options (only for the first generation) */ 9146 if(serverGeneration == 1) { 9147 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 9148 } 9149 9150 /* Clear frame buffer */ 9151 /* For CRT2, we don't do that at this point in dual head 9152 * mode since the mode isn't switched at this time (it will 9153 * be reset when setting the CRT1 mode). Hence, we just 9154 * save the necessary data and clear the screen when 9155 * going through this for CRT1. 9156 */ 9157 9158 OnScreenSize = pScrn->displayWidth * pScrn->currentMode->VDisplay 9159 * (pScrn->bitsPerPixel >> 3); 9160 9161 /* Turn on the screen now */ 9162 /* We do this in dual head mode after second head is finished */ 9163#ifdef SISDUALHEAD 9164 if(pSiS->DualHeadMode) { 9165 if(pSiS->SecondHead) { 9166 sisclearvram(pSiS->FbBase, OnScreenSize); 9167 sisclearvram(pSiSEnt->FbBase1, pSiSEnt->OnScreenSize1); 9168 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 9169 } else { 9170 pSiSEnt->FbBase1 = pSiS->FbBase; 9171 pSiSEnt->OnScreenSize1 = OnScreenSize; 9172 } 9173 } else { 9174#endif 9175 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 9176 sisclearvram(pSiS->FbBase, OnScreenSize); 9177#ifdef SISDUALHEAD 9178 } 9179#endif 9180 9181 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTSGRCRT2; 9182#ifdef SISDUALHEAD 9183 if(!pSiS->DualHeadMode) { 9184#endif 9185 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 9186 if((pSiS->crt2cindices) && (pSiS->crt2gcolortable)) { 9187 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTSGRCRT2; 9188 } 9189 } 9190#ifdef SISDUALHEAD 9191 } 9192#endif 9193 9194 pSiS->SiS_SD_Flags &= ~SiS_SD_ISDEPTH8; 9195 if(pSiS->CurrentLayout.bitsPerPixel == 8) { 9196 pSiS->SiS_SD_Flags |= SiS_SD_ISDEPTH8; 9197 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTXVGAMMA1; 9198 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTSGRCRT2; 9199 } 9200 9201#ifdef SISGAMMARAMP 9202 pSiS->SiS_SD_Flags |= SiS_SD_CANSETGAMMA; 9203#else 9204 pSiS->SiS_SD_Flags &= ~SiS_SD_CANSETGAMMA; 9205#endif 9206 9207 SiSCtrlExtInit(pScrn); 9208 9209 return TRUE; 9210} 9211 9212/* Usually mandatory */ 9213Bool 9214SISSwitchMode(SWITCH_MODE_ARGS_DECL) 9215{ 9216 SCRN_INFO_PTR(arg); 9217 SISPtr pSiS = SISPTR(pScrn); 9218 9219 if(!pSiS->skipswitchcheck) { 9220 if(SISValidMode(arg, mode, TRUE, 0) != MODE_OK) { 9221 return FALSE; 9222 } 9223 } 9224 9225 (*pSiS->SyncAccel)(pScrn); 9226 9227 if(!(SISModeInit(pScrn, mode))) return FALSE; 9228 9229 /* Since RandR (indirectly) uses SwitchMode(), we need to 9230 * update our Xinerama info here, too, in case of resizing 9231 */ 9232#ifdef SISMERGED 9233#ifdef SISXINERAMA 9234 if(pSiS->MergedFB) { 9235 SiSUpdateXineramaScreenInfo(pScrn); 9236 } 9237#endif 9238#endif 9239 return TRUE; 9240} 9241 9242static void 9243SISSetStartAddressCRT1(SISPtr pSiS, ULong base) 9244{ 9245 UChar cr11backup; 9246 9247 inSISIDXREG(SISCR, 0x11, cr11backup); /* Unlock CRTC registers */ 9248 andSISIDXREG(SISCR, 0x11, 0x7F); 9249 outSISIDXREG(SISCR, 0x0D, base & 0xFF); 9250 outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); 9251 outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF); 9252 if(pSiS->VGAEngine == SIS_315_VGA) { 9253 setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01); 9254 } 9255 /* Eventually lock CRTC registers */ 9256 setSISIDXREG(SISCR, 0x11, 0x7F,(cr11backup & 0x80)); 9257} 9258 9259static void 9260SISSetStartAddressCRT2(SISPtr pSiS, ULong base) 9261{ 9262 SiS_UnLockCRT2(pSiS->SiS_Pr); 9263 outSISIDXREG(SISPART1, 0x06, GETVAR8(base)); 9264 outSISIDXREG(SISPART1, 0x05, GETBITS(base, 15:8)); 9265 outSISIDXREG(SISPART1, 0x04, GETBITS(base, 23:16)); 9266 if(pSiS->VGAEngine == SIS_315_VGA) { 9267 setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7); 9268 } 9269 SiS_LockCRT2(pSiS->SiS_Pr); 9270} 9271 9272#ifdef SISMERGED 9273static Bool 9274InRegion(int x, int y, region r) 9275{ 9276 return (r.x0 <= x) && (x <= r.x1) && (r.y0 <= y) && (y <= r.y1); 9277} 9278 9279static void 9280SISAdjustFrameHW_CRT1(ScrnInfoPtr pScrn, int x, int y) 9281{ 9282 SISPtr pSiS = SISPTR(pScrn); 9283 ULong base; 9284 9285 base = y * pSiS->CurrentLayout.displayWidth + x; 9286 switch(pSiS->CurrentLayout.bitsPerPixel) { 9287 case 16: base >>= 1; break; 9288 case 32: break; 9289 default: base >>= 2; 9290 } 9291 base += (pSiS->dhmOffset/4); 9292 SISSetStartAddressCRT1(pSiS, base); 9293} 9294 9295static void 9296SISAdjustFrameHW_CRT2(ScrnInfoPtr pScrn, int x, int y) 9297{ 9298 SISPtr pSiS = SISPTR(pScrn); 9299 ULong base; 9300 9301 base = y * pSiS->CurrentLayout.displayWidth + x; 9302 switch(pSiS->CurrentLayout.bitsPerPixel) { 9303 case 16: base >>= 1; break; 9304 case 32: break; 9305 default: base >>= 2; 9306 } 9307 base += (pSiS->dhmOffset/4); 9308 SISSetStartAddressCRT2(pSiS, base); 9309} 9310 9311static void 9312SISMergedPointerMoved(SCRN_ARG_TYPE arg, int x, int y) 9313{ 9314 SCRN_INFO_PTR(arg); 9315 ScrnInfoPtr pScrn1 = pScrn; 9316 SISPtr pSiS = SISPTR(pScrn1); 9317 ScrnInfoPtr pScrn2 = pSiS->CRT2pScrn; 9318 region out, in1, in2, f2, f1; 9319 int deltax, deltay; 9320 int temp1, temp2; 9321 int old1x0, old1y0, old2x0, old2y0; 9322 int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; 9323 int HVirt = pScrn1->virtualX; 9324 int VVirt = pScrn1->virtualY; 9325 int sigstate; 9326 Bool doit = FALSE, HaveNonRect = FALSE, HaveOffsRegions = FALSE; 9327 SiSScrn2Rel srel = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT2Position; 9328 9329 if(pSiS->DGAactive) { 9330 return; 9331 /* DGA: There is no cursor and no panning while DGA is active. */ 9332 /* If it were, we would need to do: */ 9333 /* HVirt = pSiS->CurrentLayout.displayWidth; 9334 VVirt = pSiS->CurrentLayout.displayHeight; 9335 BOUND(x, pSiS->CurrentLayout.DGAViewportX, HVirt); 9336 BOUND(y, pSiS->CurrentLayout.DGAViewportY, VVirt); */ 9337 } else { 9338 CRT1XOffs = pSiS->CRT1XOffs; 9339 CRT1YOffs = pSiS->CRT1YOffs; 9340 CRT2XOffs = pSiS->CRT2XOffs; 9341 CRT2YOffs = pSiS->CRT2YOffs; 9342 HaveNonRect = pSiS->HaveNonRect; 9343 HaveOffsRegions = pSiS->HaveOffsRegions; 9344 } 9345 9346 /* Check if the pointer is inside our dead areas */ 9347 if((pSiS->MouseRestrictions) && (srel != sisClone) && !SiSnoPanoramiXExtension) { 9348 if(HaveNonRect) { 9349 if(InRegion(x, y, pSiS->NonRectDead)) { 9350 switch(srel) { 9351 case sisLeftOf: 9352 case sisRightOf: y = pSiS->NonRectDead.y0 - 1; 9353 doit = TRUE; 9354 break; 9355 case sisAbove: 9356 case sisBelow: x = pSiS->NonRectDead.x0 - 1; 9357 doit = TRUE; 9358 default: break; 9359 } 9360 } 9361 } 9362 if(HaveOffsRegions) { 9363 if(InRegion(x, y, pSiS->OffDead1)) { 9364 switch(srel) { 9365 case sisLeftOf: 9366 case sisRightOf: y = pSiS->OffDead1.y1; 9367 doit = TRUE; 9368 break; 9369 case sisAbove: 9370 case sisBelow: x = pSiS->OffDead1.x1; 9371 doit = TRUE; 9372 default: break; 9373 } 9374 } else if(InRegion(x, y, pSiS->OffDead2)) { 9375 switch(srel) { 9376 case sisLeftOf: 9377 case sisRightOf: y = pSiS->OffDead2.y0 - 1; 9378 doit = TRUE; 9379 break; 9380 case sisAbove: 9381 case sisBelow: x = pSiS->OffDead2.x0 - 1; 9382 doit = TRUE; 9383 default: break; 9384 } 9385 } 9386 } 9387 if(doit) { 9388#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 20 /* screw it */ 9389 sigstate = xf86BlockSIGIO(); 9390#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 15 9391 { 9392 double dx = x, dy = y; 9393 miPointerSetPosition(inputInfo.pointer, Absolute, &dx, &dy); 9394 x = (int)dx; 9395 y = (int)dy; 9396 } 9397#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 13 9398 miPointerSetPosition(inputInfo.pointer, Absolute, &x, &y); 9399#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 5 9400 miPointerSetPosition(inputInfo.pointer, &x, &y); 9401#else 9402 UpdateCurrentTime(); 9403 miPointerAbsoluteCursor(x, y, currentTime.milliseconds); 9404#endif 9405 xf86UnblockSIGIO(sigstate); 9406#endif 9407 return; 9408 } 9409 } 9410 9411 f1.x0 = old1x0 = pSiS->CRT1frameX0; 9412 f1.x1 = pSiS->CRT1frameX1; 9413 f1.y0 = old1y0 = pSiS->CRT1frameY0; 9414 f1.y1 = pSiS->CRT1frameY1; 9415 f2.x0 = old2x0 = pScrn2->frameX0; 9416 f2.x1 = pScrn2->frameX1; 9417 f2.y0 = old2y0 = pScrn2->frameY0; 9418 f2.y1 = pScrn2->frameY1; 9419 9420 /* Define the outer region. Crossing this causes all frames to move */ 9421 out.x0 = pScrn1->frameX0; 9422 out.x1 = pScrn1->frameX1; 9423 out.y0 = pScrn1->frameY0; 9424 out.y1 = pScrn1->frameY1; 9425 9426 /* 9427 * Define the inner sliding window. Being outsize both frames but 9428 * inside the outer clipping window will slide corresponding frame 9429 */ 9430 in1 = out; 9431 in2 = out; 9432 switch(srel) { 9433 case sisLeftOf: 9434 in1.x0 = f1.x0; 9435 in2.x1 = f2.x1; 9436 break; 9437 case sisRightOf: 9438 in1.x1 = f1.x1; 9439 in2.x0 = f2.x0; 9440 break; 9441 case sisBelow: 9442 in1.y1 = f1.y1; 9443 in2.y0 = f2.y0; 9444 break; 9445 case sisAbove: 9446 in1.y0 = f1.y0; 9447 in2.y1 = f2.y1; 9448 break; 9449 case sisClone: 9450 break; 9451 } 9452 9453 deltay = 0; 9454 deltax = 0; 9455 9456 if(InRegion(x, y, out)) { /* inside outer region */ 9457 9458 if(InRegion(x, y, in1) && !InRegion(x, y, f1)) { 9459 REBOUND(f1.x0, f1.x1, x); 9460 REBOUND(f1.y0, f1.y1, y); 9461 deltax = 1; 9462 } 9463 if(InRegion(x, y, in2) && !InRegion(x, y, f2)) { 9464 REBOUND(f2.x0, f2.x1, x); 9465 REBOUND(f2.y0, f2.y1, y); 9466 deltax = 1; 9467 } 9468 9469 } else { /* outside outer region */ 9470 9471 if(out.x0 > x) { 9472 deltax = x - out.x0; 9473 } 9474 if(out.x1 < x) { 9475 deltax = x - out.x1; 9476 } 9477 if(deltax) { 9478 pScrn1->frameX0 += deltax; 9479 pScrn1->frameX1 += deltax; 9480 f1.x0 += deltax; 9481 f1.x1 += deltax; 9482 f2.x0 += deltax; 9483 f2.x1 += deltax; 9484 } 9485 9486 if(out.y0 > y) { 9487 deltay = y - out.y0; 9488 } 9489 if(out.y1 < y) { 9490 deltay = y - out.y1; 9491 } 9492 if(deltay) { 9493 pScrn1->frameY0 += deltay; 9494 pScrn1->frameY1 += deltay; 9495 f1.y0 += deltay; 9496 f1.y1 += deltay; 9497 f2.y0 += deltay; 9498 f2.y1 += deltay; 9499 } 9500 9501 switch(srel) { 9502 case sisLeftOf: 9503 if(x >= f1.x0) { REBOUND(f1.y0, f1.y1, y); } 9504 if(x <= f2.x1) { REBOUND(f2.y0, f2.y1, y); } 9505 break; 9506 case sisRightOf: 9507 if(x <= f1.x1) { REBOUND(f1.y0, f1.y1, y); } 9508 if(x >= f2.x0) { REBOUND(f2.y0, f2.y1, y); } 9509 break; 9510 case sisBelow: 9511 if(y <= f1.y1) { REBOUND(f1.x0, f1.x1, x); } 9512 if(y >= f2.y0) { REBOUND(f2.x0, f2.x1, x); } 9513 break; 9514 case sisAbove: 9515 if(y >= f1.y0) { REBOUND(f1.x0, f1.x1, x); } 9516 if(y <= f2.y1) { REBOUND(f2.x0, f2.x1, x); } 9517 break; 9518 case sisClone: 9519 break; 9520 } 9521 9522 } 9523 9524 if(deltax || deltay) { 9525 pSiS->CRT1frameX0 = f1.x0; 9526 pSiS->CRT1frameY0 = f1.y0; 9527 pScrn2->frameX0 = f2.x0; 9528 pScrn2->frameY0 = f2.y0; 9529 9530 switch(srel) { 9531 case sisLeftOf: 9532 case sisRightOf: 9533 if(CRT1YOffs || CRT2YOffs || HaveNonRect) { 9534 if(pSiS->CRT1frameY0 != old1y0) { 9535 if(pSiS->CRT1frameY0 < CRT1YOffs) 9536 pSiS->CRT1frameY0 = CRT1YOffs; 9537 9538 temp1 = pSiS->CRT1frameY0 + CDMPTR->CRT1->VDisplay; 9539 temp2 = min((VVirt - CRT2YOffs), (CRT1YOffs + pSiS->MBXNR1YMAX)); 9540 if(temp1 > temp2) 9541 pSiS->CRT1frameY0 -= (temp1 - temp2); 9542 } 9543 if(pScrn2->frameY0 != old2y0) { 9544 if(pScrn2->frameY0 < CRT2YOffs) 9545 pScrn2->frameY0 = CRT2YOffs; 9546 9547 temp1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay; 9548 temp2 = min((VVirt - CRT1YOffs), (CRT2YOffs + pSiS->MBXNR2YMAX)); 9549 if(temp1 > temp2) 9550 pScrn2->frameY0 -= (temp1 - temp2); 9551 } 9552 } 9553 break; 9554 case sisBelow: 9555 case sisAbove: 9556 if(CRT1XOffs || CRT2XOffs || HaveNonRect) { 9557 if(pSiS->CRT1frameX0 != old1x0) { 9558 if(pSiS->CRT1frameX0 < CRT1XOffs) 9559 pSiS->CRT1frameX0 = CRT1XOffs; 9560 9561 temp1 = pSiS->CRT1frameX0 + CDMPTR->CRT1->HDisplay; 9562 temp2 = min((HVirt - CRT2XOffs), (CRT1XOffs + pSiS->MBXNR1XMAX)); 9563 if(temp1 > temp2) 9564 pSiS->CRT1frameX0 -= (temp1 - temp2); 9565 } 9566 if(pScrn2->frameX0 != old2x0) { 9567 if(pScrn2->frameX0 < CRT2XOffs) 9568 pScrn2->frameX0 = CRT2XOffs; 9569 9570 temp1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay; 9571 temp2 = min((HVirt - CRT1XOffs), (CRT2XOffs + pSiS->MBXNR2XMAX)); 9572 if(temp1 > temp2) 9573 pScrn2->frameX0 -= (temp1 - temp2); 9574 } 9575 } 9576 break; 9577 case sisClone: 9578 break; 9579 } 9580 9581 pSiS->CRT1frameX1 = pSiS->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1; 9582 pSiS->CRT1frameY1 = pSiS->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1; 9583 pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1; 9584 pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1; 9585 9586 /* No need to update pScrn1->frame?1, done above */ 9587 9588 SISAdjustFrameHW_CRT1(pScrn1, pSiS->CRT1frameX0, pSiS->CRT1frameY0); 9589 SISAdjustFrameHW_CRT2(pScrn1, pScrn2->frameX0, pScrn2->frameY0); 9590 } 9591} 9592 9593static void 9594SISAdjustFrameMerged(ADJUST_FRAME_ARGS_DECL) 9595{ 9596 SCRN_INFO_PTR(arg); 9597 ScrnInfoPtr pScrn1 = pScrn; 9598 SISPtr pSiS = SISPTR(pScrn1); 9599 ScrnInfoPtr pScrn2 = pSiS->CRT2pScrn; 9600 int HTotal = pSiS->CurrentLayout.mode->HDisplay; 9601 int VTotal = pSiS->CurrentLayout.mode->VDisplay; 9602 int HMax = HTotal; 9603 int VMax = VTotal; 9604 int HVirt = pScrn1->virtualX; 9605 int VVirt = pScrn1->virtualY; 9606 int x1 = x, x2 = x; 9607 int y1 = y, y2 = y; 9608 int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; 9609 int MBXNR1XMAX = 65536, MBXNR1YMAX = 65536, MBXNR2XMAX = 65536, MBXNR2YMAX = 65536; 9610 9611 if(pSiS->DGAactive) { 9612 HVirt = pSiS->CurrentLayout.displayWidth; 9613 VVirt = pSiS->CurrentLayout.displayHeight; 9614 } else { 9615 CRT1XOffs = pSiS->CRT1XOffs; 9616 CRT1YOffs = pSiS->CRT1YOffs; 9617 CRT2XOffs = pSiS->CRT2XOffs; 9618 CRT2YOffs = pSiS->CRT2YOffs; 9619 MBXNR1XMAX = pSiS->MBXNR1XMAX; 9620 MBXNR1YMAX = pSiS->MBXNR1YMAX; 9621 MBXNR2XMAX = pSiS->MBXNR2XMAX; 9622 MBXNR2YMAX = pSiS->MBXNR2YMAX; 9623 } 9624 9625 BOUND(x, 0, HVirt - HTotal); 9626 BOUND(y, 0, VVirt - VTotal); 9627 if(SDMPTR(pScrn1)->CRT2Position != sisClone) { 9628 BOUND(x1, CRT1XOffs, min(HVirt, MBXNR1XMAX + CRT1XOffs) - min(HTotal, MBXNR1XMAX) - CRT2XOffs); 9629 BOUND(y1, CRT1YOffs, min(VVirt, MBXNR1YMAX + CRT1YOffs) - min(VTotal, MBXNR1YMAX) - CRT2YOffs); 9630 BOUND(x2, CRT2XOffs, min(HVirt, MBXNR2XMAX + CRT2XOffs) - min(HTotal, MBXNR2XMAX) - CRT1XOffs); 9631 BOUND(y2, CRT2YOffs, min(VVirt, MBXNR2YMAX + CRT2YOffs) - min(VTotal, MBXNR2YMAX) - CRT1YOffs); 9632 } 9633 9634 switch(SDMPTR(pScrn1)->CRT2Position) { 9635 case sisLeftOf: 9636 pScrn2->frameX0 = x2; 9637 BOUND(pScrn2->frameY0, y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR->CRT2->VDisplay); 9638 pSiS->CRT1frameX0 = x1 + CDMPTR->CRT2->HDisplay; 9639 BOUND(pSiS->CRT1frameY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR->CRT1->VDisplay); 9640 break; 9641 case sisRightOf: 9642 pSiS->CRT1frameX0 = x1; 9643 BOUND(pSiS->CRT1frameY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR->CRT1->VDisplay); 9644 pScrn2->frameX0 = x2 + CDMPTR->CRT1->HDisplay; 9645 BOUND(pScrn2->frameY0, y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR->CRT2->VDisplay); 9646 break; 9647 case sisAbove: 9648 BOUND(pScrn2->frameX0, x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR->CRT2->HDisplay); 9649 pScrn2->frameY0 = y2; 9650 BOUND(pSiS->CRT1frameX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR->CRT1->HDisplay); 9651 pSiS->CRT1frameY0 = y1 + CDMPTR->CRT2->VDisplay; 9652 break; 9653 case sisBelow: 9654 BOUND(pSiS->CRT1frameX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR->CRT1->HDisplay); 9655 pSiS->CRT1frameY0 = y1; 9656 BOUND(pScrn2->frameX0, x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR->CRT2->HDisplay); 9657 pScrn2->frameY0 = y2 + CDMPTR->CRT1->VDisplay; 9658 break; 9659 case sisClone: 9660 BOUND(pSiS->CRT1frameX0, x, x + HMax - CDMPTR->CRT1->HDisplay); 9661 BOUND(pSiS->CRT1frameY0, y, y + VMax - CDMPTR->CRT1->VDisplay); 9662 BOUND(pScrn2->frameX0, x, x + HMax - CDMPTR->CRT2->HDisplay); 9663 BOUND(pScrn2->frameY0, y, y + VMax - CDMPTR->CRT2->VDisplay); 9664 break; 9665 } 9666 9667 BOUND(pSiS->CRT1frameX0, 0, HVirt - CDMPTR->CRT1->HDisplay); 9668 BOUND(pSiS->CRT1frameY0, 0, VVirt - CDMPTR->CRT1->VDisplay); 9669 BOUND(pScrn2->frameX0, 0, HVirt - CDMPTR->CRT2->HDisplay); 9670 BOUND(pScrn2->frameY0, 0, VVirt - CDMPTR->CRT2->VDisplay); 9671 9672 pScrn1->frameX0 = x; 9673 pScrn1->frameY0 = y; 9674 9675 pSiS->CRT1frameX1 = pSiS->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1; 9676 pSiS->CRT1frameY1 = pSiS->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1; 9677 pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1; 9678 pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1; 9679 9680 pScrn1->frameX1 = pScrn1->frameX0 + pSiS->CurrentLayout.mode->HDisplay - 1; 9681 pScrn1->frameY1 = pScrn1->frameY0 + pSiS->CurrentLayout.mode->VDisplay - 1; 9682 if(SDMPTR(pScrn1)->CRT2Position != sisClone) { 9683 pScrn1->frameX1 += CRT1XOffs + CRT2XOffs; 9684 pScrn1->frameY1 += CRT1YOffs + CRT2YOffs; 9685 } 9686 9687 SISAdjustFrameHW_CRT1(pScrn1, pSiS->CRT1frameX0, pSiS->CRT1frameY0); 9688 SISAdjustFrameHW_CRT2(pScrn1, pScrn2->frameX0, pScrn2->frameY0); 9689} 9690#endif 9691 9692/* 9693 * This function is used to initialize the Start Address - the first 9694 * displayed location in the video memory. 9695 * 9696 * Usually mandatory 9697 */ 9698void 9699SISAdjustFrame(ADJUST_FRAME_ARGS_DECL) 9700{ 9701 SCRN_INFO_PTR(arg); 9702 SISPtr pSiS = SISPTR(pScrn); 9703 ULong base; 9704 UChar temp, cr11backup; 9705 9706#ifdef SISMERGED 9707 if(pSiS->MergedFB) { 9708 SISAdjustFrameMerged(ADJUST_FRAME_ARGS(pScrn, x, y)); 9709 return; 9710 } 9711#endif 9712 9713 if(pSiS->UseVESA) { 9714 VBESetDisplayStart(pSiS->pVbe, x, y, TRUE); 9715 return; 9716 } 9717 9718 if(pScrn->bitsPerPixel < 8) { 9719 base = (y * pSiS->CurrentLayout.displayWidth + x + 3) >> 3; 9720 } else { 9721 base = y * pSiS->CurrentLayout.displayWidth + x; 9722 9723 /* calculate base bpp dep. */ 9724 switch(pSiS->CurrentLayout.bitsPerPixel) { 9725 case 16: 9726 base >>= 1; 9727 break; 9728 case 24: 9729 base = ((base * 3)) >> 2; 9730 base -= base % 6; 9731 break; 9732 case 32: 9733 break; 9734 default: /* 8bpp */ 9735 base >>= 2; 9736 break; 9737 } 9738 } 9739 9740#ifdef UNLOCK_ALWAYS 9741 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 9742#endif 9743 9744 base += (pSiS->dhmOffset/4); 9745 9746#ifdef TWDEBUG 9747 xf86DrvMsg(0, 0, "AdjustFrame: x %d y %d bpp %d dw %d base %d, dhmOffset %d\n", 9748 x, y, pSiS->CurrentLayout.bitsPerPixel, pSiS->CurrentLayout.displayWidth, base, pSiS->dhmOffset); 9749#endif 9750 9751#ifdef SISDUALHEAD 9752 if(pSiS->DualHeadMode) { 9753 if(!pSiS->SecondHead) { 9754 /* Head 1 (master) is always CRT2 */ 9755 SISSetStartAddressCRT2(pSiS, base); 9756 } else { 9757 /* Head 2 (slave) is always CRT1 */ 9758 SISSetStartAddressCRT1(pSiS, base); 9759 } 9760 } else { 9761#endif 9762 switch(pSiS->VGAEngine) { 9763 case SIS_300_VGA: 9764 case SIS_315_VGA: 9765 SISSetStartAddressCRT1(pSiS, base); 9766 if(pSiS->VBFlags & CRT2_ENABLE) { 9767 if(!SiSBridgeIsInSlaveMode(pScrn)) { 9768 SISSetStartAddressCRT2(pSiS, base); 9769 } 9770 } 9771 break; 9772 default: 9773 /* Unlock CRTC registers */ 9774 inSISIDXREG(SISCR, 0x11, cr11backup); 9775 andSISIDXREG(SISCR, 0x11, 0x7F); 9776 outSISIDXREG(SISCR, 0x0D, base & 0xFF); 9777 outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); 9778 inSISIDXREG(SISSR, 0x27, temp); 9779 temp &= 0xF0; 9780 temp |= (base & 0x0F0000) >> 16; 9781 outSISIDXREG(SISSR, 0x27, temp); 9782 /* Eventually lock CRTC registers */ 9783 setSISIDXREG(SISCR, 0x11, 0x7F, (cr11backup & 0x80)); 9784 } 9785#ifdef SISDUALHEAD 9786 } 9787#endif 9788 9789} 9790 9791/* 9792 * This is called when VT switching back to the X server. Its job is 9793 * to reinitialise the video mode. 9794 * Mandatory! 9795 */ 9796static Bool 9797SISEnterVT(VT_FUNC_ARGS_DECL) 9798{ 9799 SCRN_INFO_PTR(arg); 9800 SISPtr pSiS = SISPTR(pScrn); 9801 9802 SiS_SiSFB_Lock(pScrn, TRUE); 9803 9804 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 9805 9806 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 9807 outSISIDXREG(SISCR,0x32,pSiS->myCR32); 9808 outSISIDXREG(SISCR,0x36,pSiS->myCR36); 9809 outSISIDXREG(SISCR,0x37,pSiS->myCR37); 9810 } 9811 9812 if(!SISModeInit(pScrn, pScrn->currentMode)) { 9813 SISErrorLog(pScrn, "SiSEnterVT: SISModeInit() failed\n"); 9814 return FALSE; 9815 } 9816 9817 SISAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 9818 9819#ifdef SISDRI 9820 if(pSiS->directRenderingEnabled) { 9821 DRIUnlock(xf86ScrnToScreen(pScrn)); 9822 } 9823#endif 9824 9825#ifdef SISDUALHEAD 9826 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) 9827#endif 9828 if(pSiS->ResetXv) { 9829 (pSiS->ResetXv)(pScrn); 9830 } 9831 9832 return TRUE; 9833} 9834 9835/* 9836 * This is called when VT switching away from the X server. Its job is 9837 * to restore the previous (text) mode. 9838 * Mandatory! 9839 */ 9840static void 9841SISLeaveVT(VT_FUNC_ARGS_DECL) 9842{ 9843 SCRN_INFO_PTR(arg); 9844 SISPtr pSiS = SISPTR(pScrn); 9845#ifdef SISDRI 9846 ScreenPtr pScreen; 9847 9848 if(pSiS->directRenderingEnabled) { 9849 pScreen = xf86ScrnToScreen(pScrn); 9850 DRILock(pScreen, 0); 9851 } 9852#endif 9853 9854#ifdef SISDUALHEAD 9855 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 9856#endif 9857 9858 if(pSiS->CursorInfoPtr) { 9859#ifdef SISDUALHEAD 9860 if(pSiS->DualHeadMode) { 9861 if(!pSiS->SecondHead) { 9862 pSiS->ForceCursorOff = TRUE; 9863 pSiS->CursorInfoPtr->HideCursor(pScrn); 9864 SISWaitVBRetrace(pScrn); 9865 pSiS->ForceCursorOff = FALSE; 9866 } 9867 } else { 9868#endif 9869 pSiS->CursorInfoPtr->HideCursor(pScrn); 9870 SISWaitVBRetrace(pScrn); 9871#ifdef SISDUALHEAD 9872 } 9873#endif 9874 } 9875 9876 SISBridgeRestore(pScrn); 9877 9878 if(pSiS->UseVESA) { 9879 9880 /* This is a q&d work-around for a BIOS bug. In case we disabled CRT2, 9881 * VBESaveRestore() does not restore CRT1. So we set any mode now, 9882 * because VBESetVBEMode correctly restores CRT1. Afterwards, we 9883 * can call VBESaveRestore to restore original mode. 9884 */ 9885 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (!(pSiS->VBFlags & DISPTYPE_DISP2))) 9886 VBESetVBEMode(pSiS->pVbe, (pSiS->SISVESAModeList->n) | 0xc000, NULL); 9887 9888 SISVESARestore(pScrn); 9889 9890 } else { 9891 9892 SISRestore(pScrn); 9893 9894 } 9895 9896 /* We use (otherwise unused) bit 7 to indicate that we are running 9897 * to keep sisfb to change the displaymode (this would result in 9898 * lethal display corruption upon quitting X or changing to a VT 9899 * until a reboot) 9900 */ 9901 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 9902 orSISIDXREG(SISCR,0x34,0x80); 9903 } 9904 9905 SISVGALock(pSiS); 9906 9907 SiS_SiSFB_Lock(pScrn, FALSE); 9908} 9909 9910 9911/* 9912 * This is called at the end of each server generation. It restores the 9913 * original (text) mode. It should really also unmap the video memory too. 9914 * Mandatory! 9915 */ 9916static Bool 9917SISCloseScreen(CLOSE_SCREEN_ARGS_DECL) 9918{ 9919 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 9920 SISPtr pSiS = SISPTR(pScrn); 9921#ifdef SISDUALHEAD 9922 SISEntPtr pSiSEnt = pSiS->entityPrivate; 9923#endif 9924 9925 if(pSiS->SiSCtrlExtEntry) { 9926 SiSCtrlExtUnregister(pSiS, pScrn->scrnIndex); 9927 } 9928 9929#ifdef SISDRI 9930 if(pSiS->directRenderingEnabled) { 9931 SISDRICloseScreen(pScreen); 9932 pSiS->directRenderingEnabled = FALSE; 9933 } 9934#endif 9935 9936 if(pScrn->vtSema) { 9937 9938 if(pSiS->CursorInfoPtr) { 9939#ifdef SISDUALHEAD 9940 if(pSiS->DualHeadMode) { 9941 if(!pSiS->SecondHead) { 9942 pSiS->ForceCursorOff = TRUE; 9943 pSiS->CursorInfoPtr->HideCursor(pScrn); 9944 SISWaitVBRetrace(pScrn); 9945 pSiS->ForceCursorOff = FALSE; 9946 } 9947 } else { 9948#endif 9949 pSiS->CursorInfoPtr->HideCursor(pScrn); 9950 SISWaitVBRetrace(pScrn); 9951#ifdef SISDUALHEAD 9952 } 9953#endif 9954 } 9955 9956 SISBridgeRestore(pScrn); 9957 9958 if(pSiS->UseVESA) { 9959 9960 /* This is a q&d work-around for a BIOS bug. In case we disabled CRT2, 9961 * VBESaveRestore() does not restore CRT1. So we set any mode now, 9962 * because VBESetVBEMode correctly restores CRT1. Afterwards, we 9963 * can call VBESaveRestore to restore original mode. 9964 */ 9965 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (!(pSiS->VBFlags & DISPTYPE_DISP2))) 9966 VBESetVBEMode(pSiS->pVbe, (pSiS->SISVESAModeList->n) | 0xc000, NULL); 9967 9968 SISVESARestore(pScrn); 9969 9970 } else { 9971 9972 SISRestore(pScrn); 9973 9974 } 9975 9976 SISVGALock(pSiS); 9977 9978 } 9979 9980 SiS_SiSFB_Lock(pScrn, FALSE); 9981 9982 /* We should restore the mode number in case vtsema = false as well, 9983 * but since we haven't register access then we can't do it. I think 9984 * I need to rework the save/restore stuff, like saving the video 9985 * status when returning to the X server and by that save me the 9986 * trouble if sisfb was started from a textmode VT while X was on. 9987 */ 9988 9989 SISUnmapMem(pScrn); 9990#ifdef SIS_PC_PLATFORM 9991 SiSVGAUnmapMem(pScrn); 9992#endif 9993 9994#ifdef SISDUALHEAD 9995 if(pSiS->DualHeadMode) { 9996 pSiSEnt = pSiS->entityPrivate; 9997 pSiSEnt->refCount--; 9998 } 9999#endif 10000 10001 if(pSiS->pInt) { 10002 xf86FreeInt10(pSiS->pInt); 10003 pSiS->pInt = NULL; 10004 } 10005 10006#ifdef SIS_USE_XAA 10007 if(!pSiS->useEXA) { 10008 if(pSiS->AccelLinearScratch) { 10009 xf86FreeOffscreenLinear(pSiS->AccelLinearScratch); 10010 pSiS->AccelLinearScratch = NULL; 10011 } 10012 if(pSiS->AccelInfoPtr) { 10013 XAADestroyInfoRec(pSiS->AccelInfoPtr); 10014 pSiS->AccelInfoPtr = NULL; 10015 } 10016 } 10017#endif 10018 10019#ifdef SIS_USE_EXA 10020 if(pSiS->useEXA) { 10021 if(pSiS->EXADriverPtr) { 10022 exaDriverFini(pScreen); 10023 free(pSiS->EXADriverPtr); 10024 pSiS->EXADriverPtr = NULL; 10025 pSiS->exa_scratch = NULL; 10026 } 10027 } 10028#endif 10029 10030 if(pSiS->CursorInfoPtr) { 10031 xf86DestroyCursorInfoRec(pSiS->CursorInfoPtr); 10032 pSiS->CursorInfoPtr = NULL; 10033 } 10034 10035 if(pSiS->ShadowPtr) { 10036 free(pSiS->ShadowPtr); 10037 pSiS->ShadowPtr = NULL; 10038 } 10039 10040 if(pSiS->DGAModes) { 10041 free(pSiS->DGAModes); 10042 pSiS->DGAModes = NULL; 10043 } 10044 10045 if(pSiS->adaptor) { 10046 free(pSiS->adaptor); 10047 pSiS->adaptor = NULL; 10048 pSiS->ResetXv = pSiS->ResetXvGamma = pSiS->ResetXvDisplay = NULL; 10049 } 10050 10051 if(pSiS->blitadaptor) { 10052 free(pSiS->blitadaptor); 10053 pSiS->blitadaptor = NULL; 10054 } 10055 10056 if(pSiS->crt2gcolortable) { 10057 free(pSiS->crt2gcolortable); 10058 pSiS->crt2gcolortable = NULL; 10059 } 10060 10061 if(pSiS->crt2cindices) { 10062 free(pSiS->crt2cindices); 10063 pSiS->crt2cindices = NULL; 10064 } 10065 10066 pScrn->vtSema = FALSE; 10067 10068 /* Restore Blockhandler */ 10069 pScreen->BlockHandler = pSiS->BlockHandler; 10070 10071 pScreen->CloseScreen = pSiS->CloseScreen; 10072 10073 return(*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); 10074} 10075 10076 10077/* Free up any per-generation data structures */ 10078 10079/* Optional */ 10080static void 10081SISFreeScreen(FREE_SCREEN_ARGS_DECL) 10082{ 10083 SCRN_INFO_PTR(arg); 10084#ifdef SIS_NEED_MAP_IOP 10085 SISPtr pSiS = SISPTR(pScrn); 10086 10087 if(pSiS) { 10088#ifdef SISDUALHEAD 10089 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10090 if(pSiSEnt) { 10091 pSiSEnt->forceUnmapIOPBase = TRUE; 10092 } 10093#endif 10094 SISUnmapIOPMem(pScrn); 10095 } 10096#endif 10097 10098 SISFreeRec(pScrn); 10099} 10100 10101 10102/* Checks if a mode is suitable for the selected chipset. */ 10103 10104static ModeStatus 10105SISValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 10106{ 10107 SCRN_INFO_PTR(arg); 10108 SISPtr pSiS = SISPTR(pScrn); 10109 10110 if(pSiS->UseVESA) { 10111 if(SiSCalcVESAModeIndex(pScrn, mode)) 10112 return(MODE_OK); 10113 else 10114 return(MODE_BAD); 10115 } 10116 10117 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 10118#ifdef SISDUALHEAD 10119 if(pSiS->DualHeadMode) { 10120 if(pSiS->SecondHead) { 10121 if(SiS_CheckModeCRT1(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10122 return(MODE_BAD); 10123 } else { 10124 if(SiS_CheckModeCRT2(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10125 return(MODE_BAD); 10126 } 10127 } else 10128#endif 10129#ifdef SISMERGED 10130 if(pSiS->MergedFB) { 10131 if(!mode->Private) { 10132 if(!pSiS->CheckForCRT2) { 10133 if(SiS_CheckModeCRT1(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10134 return(MODE_BAD); 10135 } else { 10136 if(SiS_CheckModeCRT2(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes2) < 0x14) 10137 return(MODE_BAD); 10138 } 10139 } else { 10140 if(SiS_CheckModeCRT1(pScrn, ((SiSMergedDisplayModePtr)mode->Private)->CRT1, 10141 pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10142 return(MODE_BAD); 10143 10144 if(SiS_CheckModeCRT2(pScrn, ((SiSMergedDisplayModePtr)mode->Private)->CRT2, 10145 pSiS->VBFlags, pSiS->HaveCustomModes2) < 0x14) 10146 return(MODE_BAD); 10147 } 10148 } else 10149#endif 10150 { 10151 if(SiS_CheckModeCRT1(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10152 return(MODE_BAD); 10153 10154 if(SiS_CheckModeCRT2(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10155 return(MODE_BAD); 10156 } 10157 } 10158 10159 return(MODE_OK); 10160} 10161 10162#ifdef DEBUG 10163static void 10164SiSDumpModeInfo(ScrnInfoPtr pScrn, DisplayModePtr mode) 10165{ 10166 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Clock : %x\n", mode->Clock); 10167 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Display : %x\n", mode->CrtcHDisplay); 10168 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Blank Start : %x\n", mode->CrtcHBlankStart); 10169 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Sync Start : %x\n", mode->CrtcHSyncStart); 10170 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Sync End : %x\n", mode->CrtcHSyncEnd); 10171 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Blank End : %x\n", mode->CrtcHBlankEnd); 10172 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Total : %x\n", mode->CrtcHTotal); 10173 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Skew : %x\n", mode->CrtcHSkew); 10174 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz HAdjusted : %x\n", mode->CrtcHAdjusted); 10175 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Display : %x\n", mode->CrtcVDisplay); 10176 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Blank Start : %x\n", mode->CrtcVBlankStart); 10177 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Sync Start : %x\n", mode->CrtcVSyncStart); 10178 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Sync End : %x\n", mode->CrtcVSyncEnd); 10179 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Blank End : %x\n", mode->CrtcVBlankEnd); 10180 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Total : %x\n", mode->CrtcVTotal); 10181 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt VAdjusted : %x\n", mode->CrtcVAdjusted); 10182} 10183#endif 10184 10185static void 10186SISModifyModeInfo(DisplayModePtr mode) 10187{ 10188 if(mode->CrtcHBlankStart == mode->CrtcHDisplay) 10189 mode->CrtcHBlankStart++; 10190 if(mode->CrtcHBlankEnd == mode->CrtcHTotal) 10191 mode->CrtcHBlankEnd--; 10192 if(mode->CrtcVBlankStart == mode->CrtcVDisplay) 10193 mode->CrtcVBlankStart++; 10194 if(mode->CrtcVBlankEnd == mode->CrtcVTotal) 10195 mode->CrtcVBlankEnd--; 10196} 10197 10198/* Enable the Turboqueue/Commandqueue (For 300 and 315/330/340 series only) */ 10199static void 10200SiSEnableTurboQueue(ScrnInfoPtr pScrn) 10201{ 10202 SISPtr pSiS = SISPTR(pScrn); 10203 UShort SR26, SR27; 10204 ULong temp; 10205 10206 switch(pSiS->VGAEngine) { 10207 case SIS_300_VGA: 10208 if((!pSiS->NoAccel) && (pSiS->TurboQueue)) { 10209 /* TQ size is always 512k */ 10210 temp = (pScrn->videoRam/64) - 8; 10211 SR26 = temp & 0xFF; 10212 inSISIDXREG(SISSR, 0x27, SR27); 10213 SR27 &= 0xFC; 10214 SR27 |= (0xF0 | ((temp >> 8) & 3)); 10215 outSISIDXREG(SISSR, 0x26, SR26); 10216 outSISIDXREG(SISSR, 0x27, SR27); 10217 } 10218 break; 10219 10220 case SIS_315_VGA: 10221 if(!pSiS->NoAccel) { 10222 /* On 315/330/340 series, there are three queue modes available 10223 * which are chosen by setting bits 7:5 in SR26: 10224 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep 10225 * track of the queue, the FIFO, command parsing and so 10226 * on. This is the one comparable to the 300 series. 10227 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will 10228 * have to do queue management himself. 10229 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the 10230 * queue in AGP memory space. 10231 * We go VRAM or MMIO here. 10232 * SR26 bit 4 is called "Bypass H/W queue". 10233 * SR26 bit 1 is called "Enable Command Queue Auto Correction" 10234 * SR26 bit 0 resets the queue 10235 * Size of queue memory is encoded in bits 3:2 like this: 10236 * 00 (0x00) 512K 10237 * 01 (0x04) 1M 10238 * 10 (0x08) 2M 10239 * 11 (0x0C) 4M 10240 * The queue location is to be written to 0x85C0. 10241 */ 10242#ifdef SISVRAMQ 10243 /* We use VRAM Cmd Queue, not MMIO or AGP */ 10244 UChar tempCR55 = 0; 10245 10246 /* Set Command Queue Threshold to max value 11111b (?) */ 10247 outSISIDXREG(SISSR, 0x27, 0x1F); 10248 10249 /* Disable queue flipping */ 10250 inSISIDXREG(SISCR, 0x55, tempCR55); 10251 andSISIDXREG(SISCR, 0x55, 0x33); 10252 /* Synchronous reset for Command Queue */ 10253 outSISIDXREG(SISSR, 0x26, 0x01); 10254 SIS_MMIO_OUT32(pSiS->IOBase, 0x85c4, 0); 10255 /* Enable VRAM Command Queue mode */ 10256 if(pSiS->ChipType == XGI_20) { 10257 /* On XGI_20, always 128K */ 10258 SR26 = 0x40 | 0x04 | 0x01; 10259 } else { 10260 switch(pSiS->cmdQueueSize) { 10261 case 1*1024*1024: SR26 = (0x40 | 0x04 | 0x01); break; 10262 case 2*1024*1024: SR26 = (0x40 | 0x08 | 0x01); break; 10263 case 4*1024*1024: SR26 = (0x40 | 0x0C | 0x01); break; 10264 default: 10265 pSiS->cmdQueueSize = 512 * 1024; 10266 case 512*1024: SR26 = (0x40 | 0x00 | 0x01); 10267 } 10268 } 10269 outSISIDXREG(SISSR, 0x26, SR26); 10270 SR26 &= 0xfe; 10271 outSISIDXREG(SISSR, 0x26, SR26); 10272 *(pSiS->cmdQ_SharedWritePort) = (unsigned int)(SIS_MMIO_IN32(pSiS->IOBase, 0x85c8)); 10273 SIS_MMIO_OUT32(pSiS->IOBase, 0x85c4, (CARD32)(*(pSiS->cmdQ_SharedWritePort))); 10274 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C0, pSiS->cmdQueueOffset); 10275 temp = (ULong)pSiS->RealFbBase; 10276#ifdef SISDUALHEAD 10277 if(pSiS->DualHeadMode) { 10278 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10279 temp = (ULong)pSiSEnt->RealFbBase; 10280 } 10281#endif 10282 temp += pSiS->cmdQueueOffset; 10283 pSiS->cmdQueueBase = (unsigned int *)temp; 10284 outSISIDXREG(SISCR, 0x55, tempCR55); 10285#ifdef TWDEBUG 10286 xf86DrvMsg(0, 0, "CmdQueueOffs 0x%x, CmdQueueAdd %p, shwrp 0x%x, status %x, base %p\n", 10287 pSiS->cmdQueueOffset, pSiS->cmdQueueBase, *(pSiS->cmdQ_SharedWritePort), 10288 SIS_MMIO_IN32(pSiS->IOBase, 0x85cc), (ULong *)temp); 10289#endif 10290#else 10291 /* For MMIO */ 10292 /* Syncronous reset for Command Queue */ 10293 orSISIDXREG(SISSR, 0x26, 0x01); 10294 /* Set Command Queue Threshold to max value 11111b */ 10295 outSISIDXREG(SISSR, 0x27, 0x1F); 10296 /* Do some magic (cp readport to writeport) */ 10297 temp = SIS_MMIO_IN32(pSiS->IOBase, 0x85C8); 10298 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C4, temp); 10299 /* Enable MMIO Command Queue mode (0x20), 10300 * Enable_command_queue_auto_correction (0x02) 10301 * (no idea, but sounds good, so use it) 10302 * 512k (0x00) (does this apply to MMIO mode?) */ 10303 outSISIDXREG(SISSR, 0x26, 0x22); 10304 /* Calc Command Queue position (Q is always 512k)*/ 10305 temp = (pScrn->videoRam - 512) * 1024; 10306 /* Set Q position */ 10307 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C0, temp); 10308#endif 10309 } 10310 break; 10311 default: 10312 break; 10313 } 10314} 10315 10316#ifdef SISVRAMQ 10317static void 10318SiSRestoreQueueMode(SISPtr pSiS, SISRegPtr sisReg) 10319{ 10320 UChar tempCR55=0; 10321 10322 if(pSiS->VGAEngine == SIS_315_VGA) { 10323 inSISIDXREG(SISCR,0x55,tempCR55); 10324 andSISIDXREG(SISCR,0x55,0x33); 10325 outSISIDXREG(SISSR,0x26,0x01); 10326 SIS_MMIO_OUT32(pSiS->IOBase, 0x85c4, 0); 10327 outSISIDXREG(SISSR,0x27,sisReg->sisRegs3C4[0x27]); 10328 outSISIDXREG(SISSR,0x26,sisReg->sisRegs3C4[0x26]); 10329 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C0, sisReg->sisMMIO85C0); 10330 outSISIDXREG(SISCR,0x55,tempCR55); 10331 } 10332} 10333#endif 10334 10335/* Things to do before a ModeSwitch. We set up the 10336 * video bridge configuration and the TurboQueue. 10337 */ 10338void SiSPreSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode, int viewmode) 10339{ 10340 SISPtr pSiS = SISPTR(pScrn); 10341 UChar CR30, CR31, CR32, CR33; 10342 UChar CR39 = 0, CR3B = 0; 10343 UChar CR17, CR38 = 0; 10344 UChar CR35 = 0, CR79 = 0; 10345 int temp = 0, crt1rateindex = 0; 10346 ULong vbflag = pSiS->VBFlags; 10347 Bool hcm = pSiS->HaveCustomModes; 10348 DisplayModePtr mymode = mode; 10349 10350 pSiS->IsCustom = FALSE; 10351 10352 /* NEVER call this with viewmode = SIS_MODE_SIMU 10353 * if mode->type is not M_T_DEFAULT! 10354 */ 10355 10356#ifdef SISMERGED 10357 if(pSiS->MergedFB) { 10358 switch(viewmode) { 10359 case SIS_MODE_CRT1: 10360 mymode = ((SiSMergedDisplayModePtr)mode->Private)->CRT1; 10361 break; 10362 case SIS_MODE_CRT2: 10363 mymode = ((SiSMergedDisplayModePtr)mode->Private)->CRT2; 10364 hcm = pSiS->HaveCustomModes2; 10365 } 10366 } 10367#endif 10368 10369 switch(viewmode) { 10370 case SIS_MODE_CRT1: 10371 if(SiS_CheckModeCRT1(pScrn, mymode, vbflag, hcm) == 0xfe) { 10372 pSiS->IsCustom = TRUE; 10373 } 10374 break; 10375 case SIS_MODE_CRT2: 10376 if(vbflag & CRT2_ENABLE) { 10377 if(SiS_CheckModeCRT2(pScrn, mymode, vbflag, hcm) == 0xfe) { 10378 pSiS->IsCustom = TRUE; 10379 } 10380 } else { 10381 /* This can only happen in mirror mode */ 10382 if(SiS_CheckModeCRT1(pScrn, mymode, vbflag, hcm) == 0xfe) { 10383 pSiS->IsCustom = TRUE; 10384 } 10385 } 10386 } 10387 10388#ifdef UNLOCK_ALWAYS 10389 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); /* Unlock Registers */ 10390#endif 10391 10392 inSISIDXREG(SISCR, 0x30, CR30); 10393 inSISIDXREG(SISCR, 0x31, CR31); 10394 CR32 = pSiS->newCR32; 10395 inSISIDXREG(SISCR, 0x33, CR33); 10396 10397 if(pSiS->NewCRLayout) { 10398 10399 inSISIDXREG(SISCR, 0x35, CR35); 10400 inSISIDXREG(SISCR, 0x38, CR38); 10401 inSISIDXREG(SISCR, 0x39, CR39); 10402 10403 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, SISVERBLEVEL, 10404 "Before: CR30=0x%02x,CR31=0x%02x,CR32=0x%02x,CR33=0x%02x,CR35=0x%02x,CR38=0x%02x\n", 10405 CR30, CR31, CR32, CR33, CR35, CR38); 10406 10407 CR38 &= ~0x07; 10408 10409 } else { 10410 10411 if(pSiS->Chipset != PCI_CHIP_SIS300) { 10412 switch(pSiS->VGAEngine) { 10413 case SIS_300_VGA: temp = 0x35; break; 10414 case SIS_315_VGA: temp = 0x38; break; 10415 } 10416 if(temp) inSISIDXREG(SISCR, temp, CR38); 10417 } 10418 if(pSiS->VGAEngine == SIS_315_VGA) { 10419 inSISIDXREG(SISCR, 0x79, CR79); 10420 CR38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */ 10421 } 10422 inSISIDXREG(SISCR, 0x3b, CR3B); 10423 10424 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, SISVERBLEVEL, 10425 "Before: CR30=0x%02x, CR31=0x%02x, CR32=0x%02x, CR33=0x%02x, CR%02x=0x%02x\n", 10426 CR30, CR31, CR32, CR33, temp, CR38); 10427 } 10428 10429 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, SISVERBLEVEL, "VBFlags=0x%x\n", pSiS->VBFlags); 10430 10431 CR30 = 0x00; 10432 CR31 &= ~0x60; /* Clear VB_Drivermode & VB_OutputDisable */ 10433 CR31 |= 0x04; /* Set VB_NotSimuMode (not for 30xB/1400x1050?) */ 10434 CR35 = 0x00; 10435 10436 if(!pSiS->NewCRLayout) { 10437 if(!pSiS->AllowHotkey) { 10438 CR31 |= 0x80; /* Disable hotkey-switch */ 10439 } 10440 CR79 &= ~0x10; /* Enable Backlight control on 315 series */ 10441 } 10442 10443 SiS_SetEnableDstn(pSiS->SiS_Pr, FALSE); 10444 SiS_SetEnableFstn(pSiS->SiS_Pr, FALSE); 10445 10446 if((vbflag & CRT1_LCDA) && (viewmode == SIS_MODE_CRT1)) { 10447 10448 CR38 |= 0x02; 10449 10450 } else { 10451 10452 switch(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA)) { 10453 10454 case CRT2_TV: 10455 10456 CR38 &= ~0xC0; /* Clear Pal M/N bits */ 10457 10458 if((pSiS->VBFlags2 & VB2_CHRONTEL) && (vbflag & TV_CHSCART)) { /* Chrontel */ 10459 CR30 |= 0x10; 10460 CR38 |= 0x04; 10461 CR38 &= ~0x08; 10462 CR31 |= 0x01; 10463 } else if((pSiS->VBFlags2 & VB2_CHRONTEL) && (vbflag & TV_CHYPBPR525I)) { /* Chrontel */ 10464 CR38 |= 0x08; 10465 CR38 &= ~0x04; 10466 CR31 &= ~0x01; 10467 } else if(vbflag & TV_HIVISION) { /* SiS bridge */ 10468 if(pSiS->NewCRLayout) { 10469 CR38 |= 0x04; 10470 CR35 |= 0x60; 10471 } else { 10472 CR30 |= 0x80; 10473 if(pSiS->VGAEngine == SIS_315_VGA) { 10474 if(pSiS->VBFlags2 & VB2_SISYPBPRBRIDGE) { 10475 CR38 |= (0x08 | 0x30); 10476 } 10477 } 10478 } 10479 CR31 |= 0x01; 10480 CR35 |= 0x01; 10481 } else if(vbflag & TV_YPBPR) { /* SiS bridge */ 10482 if(pSiS->NewCRLayout) { 10483 CR38 |= 0x04; 10484 CR31 &= ~0x01; 10485 CR35 &= ~0x01; 10486 if(vbflag & (TV_YPBPR525P | TV_YPBPR625P)) CR35 |= 0x20; 10487 else if(vbflag & TV_YPBPR750P) CR35 |= 0x40; 10488 else if(vbflag & TV_YPBPR1080I) CR35 |= 0x60; 10489 10490 if(vbflag & (TV_YPBPR625I | TV_YPBPR625P)) { 10491 CR31 |= 0x01; 10492 CR35 |= 0x01; 10493 } 10494 10495 CR39 &= ~0x03; 10496 if((vbflag & TV_YPBPRAR) == TV_YPBPR43LB) CR39 |= 0x00; 10497 else if((vbflag & TV_YPBPRAR) == TV_YPBPR43) CR39 |= 0x01; 10498 else if((vbflag & TV_YPBPRAR) == TV_YPBPR169) CR39 |= 0x02; 10499 else CR39 |= 0x03; 10500 } else if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR) { 10501 CR30 |= 0x80; 10502 CR38 |= 0x08; 10503 CR31 &= ~0x01; 10504 if(vbflag & (TV_YPBPR525P|TV_YPBPR625P)) CR38 |= 0x10; 10505 else if(vbflag & TV_YPBPR750P) CR38 |= 0x20; 10506 else if(vbflag & TV_YPBPR1080I) CR38 |= 0x30; 10507 10508 if(vbflag & (TV_YPBPR625I | TV_YPBPR625P)) CR31 |= 0x01; 10509 10510 if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPRAR) { 10511 CR3B &= ~0x03; 10512 if((vbflag & TV_YPBPRAR) == TV_YPBPR43LB) CR3B |= 0x00; 10513 else if((vbflag & TV_YPBPRAR) == TV_YPBPR43) CR3B |= 0x03; 10514 else if((vbflag & TV_YPBPRAR) == TV_YPBPR169) CR3B |= 0x01; 10515 else CR3B |= 0x03; 10516 } 10517 } 10518 } else { /* All */ 10519 if(vbflag & TV_SCART) CR30 |= 0x10; 10520 if(vbflag & TV_SVIDEO) CR30 |= 0x08; 10521 if(vbflag & TV_AVIDEO) CR30 |= 0x04; 10522 if(!(CR30 & 0x1C)) CR30 |= 0x08; /* default: SVIDEO */ 10523 10524 if(vbflag & TV_PAL) { 10525 CR31 |= 0x01; 10526 CR35 |= 0x01; 10527 if( (pSiS->VBFlags2 & VB2_SISBRIDGE) || 10528 ((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->ChrontelType == CHRONTEL_701x)) ) { 10529 if(vbflag & TV_PALM) { 10530 CR38 |= 0x40; 10531 CR35 |= 0x04; 10532 } else if(vbflag & TV_PALN) { 10533 CR38 |= 0x80; 10534 CR35 |= 0x08; 10535 } 10536 } 10537 } else { 10538 CR31 &= ~0x01; 10539 CR35 &= ~0x01; 10540 if(vbflag & TV_NTSCJ) { 10541 CR38 |= 0x40; /* TW, not BIOS */ 10542 CR35 |= 0x02; 10543 } 10544 } 10545 if(vbflag & TV_SCART) { 10546 CR31 |= 0x01; 10547 CR35 |= 0x01; 10548 } 10549 } 10550 10551 CR31 &= ~0x04; /* Clear NotSimuMode */ 10552 pSiS->SiS_Pr->SiS_CHOverScan = pSiS->UseCHOverScan; 10553 if((pSiS->OptTVSOver == 1) && (pSiS->ChrontelType == CHRONTEL_700x)) { 10554 pSiS->SiS_Pr->SiS_CHSOverScan = TRUE; 10555 } else { 10556 pSiS->SiS_Pr->SiS_CHSOverScan = FALSE; 10557 } 10558#ifdef SIS_CP 10559 SIS_CP_DRIVER_CONFIG 10560#endif 10561 break; 10562 10563 case CRT2_LCD: 10564 CR30 |= 0x20; 10565 SiS_SetEnableDstn(pSiS->SiS_Pr, pSiS->DSTN); 10566 SiS_SetEnableFstn(pSiS->SiS_Pr, pSiS->FSTN); 10567 break; 10568 10569 case CRT2_VGA: 10570 CR30 |= 0x40; 10571 break; 10572 10573 default: 10574 CR30 |= 0x00; 10575 CR31 |= 0x20; /* VB_OUTPUT_DISABLE */ 10576 if(pSiS->UseVESA) { 10577 crt1rateindex = SISSearchCRT1Rate(pScrn, mymode); 10578 } 10579 } 10580 10581 } 10582 10583 if(vbflag & CRT1_LCDA) { 10584 switch(viewmode) { 10585 case SIS_MODE_CRT1: 10586 CR38 |= 0x01; 10587 break; 10588 case SIS_MODE_CRT2: 10589 if(vbflag & (CRT2_TV|CRT2_VGA)) { 10590 CR30 |= 0x02; 10591 CR38 |= 0x01; 10592 } else { 10593 CR38 |= 0x03; 10594 } 10595 break; 10596 case SIS_MODE_SIMU: 10597 default: 10598 if(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA)) { 10599 CR30 |= 0x01; 10600 } 10601 break; 10602 } 10603 } else { 10604 if(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA)) { 10605 CR30 |= 0x01; 10606 } 10607 } 10608 10609 if(pSiS->UseVESA) { 10610 CR31 &= ~0x40; /* Clear Drivermode */ 10611 CR31 |= 0x06; /* Set SlaveMode, Enable SimuMode in Slavemode */ 10612#ifdef TWDEBUG 10613 CR31 |= 0x40; /* DEBUG (for non-slave mode VESA) */ 10614 crt1rateindex = SISSearchCRT1Rate(pScrn, mymode); 10615#endif 10616 } else { 10617 CR31 |= 0x40; /* Set Drivermode */ 10618 CR31 &= ~0x06; /* Disable SlaveMode, disable SimuMode in SlaveMode */ 10619 if(!pSiS->IsCustom) { 10620 crt1rateindex = SISSearchCRT1Rate(pScrn, mymode); 10621 } 10622 } 10623 10624 switch(viewmode) { 10625 case SIS_MODE_SIMU: 10626 CR33 = 0; 10627 if(!(vbflag & CRT1_LCDA)) { 10628 CR33 |= (crt1rateindex & 0x0f); 10629 } 10630 if(vbflag & CRT2_VGA) { 10631 CR33 |= ((crt1rateindex & 0x0f) << 4); 10632 } 10633 break; 10634 case SIS_MODE_CRT1: 10635 CR33 &= 0xf0; 10636 if(!(vbflag & CRT1_LCDA)) { 10637 CR33 |= (crt1rateindex & 0x0f); 10638 } 10639 break; 10640 case SIS_MODE_CRT2: 10641 CR33 &= 0x0f; 10642 if(vbflag & CRT2_VGA) { 10643 CR33 |= ((crt1rateindex & 0x0f) << 4); 10644 } 10645 break; 10646 } 10647 10648 if((!pSiS->UseVESA) && (vbflag & CRT2_ENABLE)) { 10649 if(pSiS->CRT1off) CR33 &= 0xf0; 10650 } 10651 10652 if(pSiS->NewCRLayout) { 10653 10654 CR31 &= 0xfe; /* Clear PAL flag (now in CR35) */ 10655 CR38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */ 10656 outSISIDXREG(SISCR, 0x30, CR30); 10657 outSISIDXREG(SISCR, 0x31, CR31); 10658 outSISIDXREG(SISCR, 0x33, CR33); 10659 outSISIDXREG(SISCR, 0x35, CR35); 10660 setSISIDXREG(SISCR, 0x38, 0xf8, CR38); 10661 outSISIDXREG(SISCR, 0x39, CR39); 10662 10663 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, SISVERBLEVEL, 10664 "After: CR30=0x%02x,CR31=0x%02x,CR33=0x%02x,CR35=0x%02x,CR38=%02x\n", 10665 CR30, CR31, CR33, CR35, CR38); 10666 10667 } else { 10668 10669 outSISIDXREG(SISCR, 0x30, CR30); 10670 outSISIDXREG(SISCR, 0x31, CR31); 10671 outSISIDXREG(SISCR, 0x33, CR33); 10672 if(temp) { 10673 outSISIDXREG(SISCR, temp, CR38); 10674 } 10675 if(pSiS->VGAEngine == SIS_315_VGA) { 10676 outSISIDXREG(SISCR, 0x3b, CR3B); 10677 outSISIDXREG(SISCR, 0x79, CR79); 10678 } 10679 10680 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, SISVERBLEVEL, 10681 "After: CR30=0x%02x,CR31=0x%02x,CR33=0x%02x,CR%02x=%02x\n", 10682 CR30, CR31, CR33, temp, CR38); 10683 } 10684 10685 pSiS->SiS_Pr->SiS_UseOEM = pSiS->OptUseOEM; 10686 10687 /* Enable TurboQueue */ 10688#ifdef SISVRAMQ 10689 if(pSiS->VGAEngine != SIS_315_VGA) 10690#endif 10691 SiSEnableTurboQueue(pScrn); 10692 10693 if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE)) { 10694 /* Switch on CRT1 for modes that require the bridge in SlaveMode */ 10695 andSISIDXREG(SISSR,0x1f,0x3f); 10696 inSISIDXREG(SISCR, 0x17, CR17); 10697 if(!(CR17 & 0x80)) { 10698 orSISIDXREG(SISCR, 0x17, 0x80); 10699 outSISIDXREG(SISSR, 0x00, 0x01); 10700 usleep(10000); 10701 outSISIDXREG(SISSR, 0x00, 0x03); 10702 } 10703 } 10704} 10705 10706/* Functions for adjusting various TV settings */ 10707 10708/* These are used by the PostSetMode() functions as well as 10709 * the display properties tool SiSCtrl. 10710 * 10711 * There is each a Set and a Get routine. The Set functions 10712 * take a value of the same range as the corresponding option. 10713 * The Get routines return a value of the same range (although 10714 * not necessarily the same value as previously set because 10715 * of the lower resolution of the respective setting compared 10716 * to the valid range). 10717 * The Get routines return -2 on error (eg. hardware does not 10718 * support this setting). 10719 * Note: The x and y positioning routines accept a position 10720 * RELATIVE to the default position. All other routines 10721 * take ABSOLUTE values. 10722 * 10723 * The Set functions will store the property regardless if TV is 10724 * currently used or not and if the hardware supports the property 10725 * or not. The Get routines will return this stored 10726 * value if TV is not currently used (because the register does 10727 * not contain the correct value then) or if the hardware supports 10728 * the respective property. This should make it easier for the 10729 * display property tool because it does not have to know the 10730 * hardware features. 10731 * 10732 * All the routines are dual head aware. It does not matter 10733 * if the function is called from the CRT1 or CRT2 session. 10734 * The values will be in pSiSEnt anyway, and read from there 10735 * if we're running dual head. 10736 */ 10737 10738void SiS_SetCHTVlumabandwidthcvbs(ScrnInfoPtr pScrn, int val) 10739{ 10740 SISPtr pSiS = SISPTR(pScrn); 10741#ifdef SISDUALHEAD 10742 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10743#endif 10744 10745 pSiS->chtvlumabandwidthcvbs = val; 10746#ifdef SISDUALHEAD 10747 if(pSiSEnt) pSiSEnt->chtvlumabandwidthcvbs = val; 10748#endif 10749 10750 if(!(pSiS->VBFlags & CRT2_TV)) return; 10751 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10752 10753#ifdef UNLOCK_ALWAYS 10754 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10755#endif 10756 10757 switch(pSiS->ChrontelType) { 10758 case CHRONTEL_700x: 10759 val /= 8; 10760 if((val == 0) || (val == 1)) { 10761 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, val, 0xFE); 10762 } 10763 break; 10764 case CHRONTEL_701x: 10765 val /= 4; 10766 if((val >= 0) && (val <= 3)) { 10767 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, val, 0xFC); 10768 } 10769 break; 10770 } 10771} 10772 10773int SiS_GetCHTVlumabandwidthcvbs(ScrnInfoPtr pScrn) 10774{ 10775 SISPtr pSiS = SISPTR(pScrn); 10776#ifdef SISDUALHEAD 10777 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10778#endif 10779 10780 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10781#ifdef SISDUALHEAD 10782 if(pSiSEnt && pSiS->DualHeadMode) 10783 return (int)pSiSEnt->chtvlumabandwidthcvbs; 10784 else 10785#endif 10786 return (int)pSiS->chtvlumabandwidthcvbs; 10787 } else { 10788#ifdef UNLOCK_ALWAYS 10789 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10790#endif 10791 switch(pSiS->ChrontelType) { 10792 case CHRONTEL_700x: 10793 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x01) * 8); 10794 case CHRONTEL_701x: 10795 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x03) * 4); 10796 default: 10797 return (int)pSiS->chtvlumabandwidthcvbs; 10798 } 10799 } 10800} 10801 10802void SiS_SetCHTVlumabandwidthsvideo(ScrnInfoPtr pScrn, int val) 10803{ 10804 SISPtr pSiS = SISPTR(pScrn); 10805#ifdef SISDUALHEAD 10806 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10807#endif 10808 10809 pSiS->chtvlumabandwidthsvideo = val; 10810#ifdef SISDUALHEAD 10811 if(pSiSEnt) pSiSEnt->chtvlumabandwidthsvideo = val; 10812#endif 10813 10814 if(!(pSiS->VBFlags & CRT2_TV)) return; 10815 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10816 10817#ifdef UNLOCK_ALWAYS 10818 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10819#endif 10820 10821 switch(pSiS->ChrontelType) { 10822 case CHRONTEL_700x: 10823 val /= 6; 10824 if((val >= 0) && (val <= 2)) { 10825 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, (val << 1), 0xF9); 10826 } 10827 break; 10828 case CHRONTEL_701x: 10829 val /= 4; 10830 if((val >= 0) && (val <= 3)) { 10831 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, (val << 2), 0xF3); 10832 } 10833 break; 10834 } 10835} 10836 10837int SiS_GetCHTVlumabandwidthsvideo(ScrnInfoPtr pScrn) 10838{ 10839 SISPtr pSiS = SISPTR(pScrn); 10840#ifdef SISDUALHEAD 10841 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10842#endif 10843 10844 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10845#ifdef SISDUALHEAD 10846 if(pSiSEnt && pSiS->DualHeadMode) 10847 return (int)pSiSEnt->chtvlumabandwidthsvideo; 10848 else 10849#endif 10850 return (int)pSiS->chtvlumabandwidthsvideo; 10851 } else { 10852#ifdef UNLOCK_ALWAYS 10853 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10854#endif 10855 switch(pSiS->ChrontelType) { 10856 case CHRONTEL_700x: 10857 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x06) >> 1) * 6); 10858 case CHRONTEL_701x: 10859 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x0c) >> 2) * 4); 10860 default: 10861 return (int)pSiS->chtvlumabandwidthsvideo; 10862 } 10863 } 10864} 10865 10866void SiS_SetCHTVlumaflickerfilter(ScrnInfoPtr pScrn, int val) 10867{ 10868 SISPtr pSiS = SISPTR(pScrn); 10869#ifdef SISDUALHEAD 10870 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10871#endif 10872 10873 pSiS->chtvlumaflickerfilter = val; 10874#ifdef SISDUALHEAD 10875 if(pSiSEnt) pSiSEnt->chtvlumaflickerfilter = val; 10876#endif 10877 10878 if(!(pSiS->VBFlags & CRT2_TV)) return; 10879 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10880 10881#ifdef UNLOCK_ALWAYS 10882 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10883#endif 10884 10885 switch(pSiS->ChrontelType) { 10886 case CHRONTEL_700x: 10887 val /= 6; 10888 if((val >= 0) && (val <= 2)) { 10889 UShort reg = 0; 10890 reg = SiS_GetCH70xx(pSiS->SiS_Pr, 0x01); 10891 reg = (reg & 0xf0) | ((reg & 0x0c) >> 2) | (val << 2); 10892 SiS_SetCH70xx(pSiS->SiS_Pr, 0x01, reg); 10893 } 10894 break; 10895 case CHRONTEL_701x: 10896 val /= 4; 10897 if((val >= 0) && (val <= 3)) { 10898 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x01, (val << 2), 0xF3); 10899 } 10900 break; 10901 } 10902} 10903 10904int SiS_GetCHTVlumaflickerfilter(ScrnInfoPtr pScrn) 10905{ 10906 SISPtr pSiS = SISPTR(pScrn); 10907#ifdef SISDUALHEAD 10908 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10909#endif 10910 10911 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10912#ifdef SISDUALHEAD 10913 if(pSiSEnt && pSiS->DualHeadMode) 10914 return (int)pSiSEnt->chtvlumaflickerfilter; 10915 else 10916#endif 10917 return (int)pSiS->chtvlumaflickerfilter; 10918 } else { 10919#ifdef UNLOCK_ALWAYS 10920 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10921#endif 10922 switch(pSiS->ChrontelType) { 10923 case CHRONTEL_700x: 10924 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x03) * 6); 10925 case CHRONTEL_701x: 10926 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x0c) >> 2) * 4); 10927 default: 10928 return (int)pSiS->chtvlumaflickerfilter; 10929 } 10930 } 10931} 10932 10933void SiS_SetCHTVchromabandwidth(ScrnInfoPtr pScrn, int val) 10934{ 10935 SISPtr pSiS = SISPTR(pScrn); 10936#ifdef SISDUALHEAD 10937 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10938#endif 10939 10940 pSiS->chtvchromabandwidth = val; 10941#ifdef SISDUALHEAD 10942 if(pSiSEnt) pSiSEnt->chtvchromabandwidth = val; 10943#endif 10944 10945 if(!(pSiS->VBFlags & CRT2_TV)) return; 10946 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10947 10948#ifdef UNLOCK_ALWAYS 10949 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10950#endif 10951 10952 switch(pSiS->ChrontelType) { 10953 case CHRONTEL_700x: 10954 val /= 4; 10955 if((val >= 0) && (val <= 3)) { 10956 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, (val << 4), 0xCF); 10957 } 10958 break; 10959 case CHRONTEL_701x: 10960 val /= 8; 10961 if((val >= 0) && (val <= 1)) { 10962 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, (val << 4), 0xEF); 10963 } 10964 break; 10965 } 10966} 10967 10968int SiS_GetCHTVchromabandwidth(ScrnInfoPtr pScrn) 10969{ 10970 SISPtr pSiS = SISPTR(pScrn); 10971#ifdef SISDUALHEAD 10972 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10973#endif 10974 10975 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10976#ifdef SISDUALHEAD 10977 if(pSiSEnt && pSiS->DualHeadMode) 10978 return (int)pSiSEnt->chtvchromabandwidth; 10979 else 10980#endif 10981 return (int)pSiS->chtvchromabandwidth; 10982 } else { 10983#ifdef UNLOCK_ALWAYS 10984 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10985#endif 10986 switch(pSiS->ChrontelType) { 10987 case CHRONTEL_700x: 10988 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x30) >> 4) * 4); 10989 case CHRONTEL_701x: 10990 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x10) >> 4) * 8); 10991 default: 10992 return (int)pSiS->chtvchromabandwidth; 10993 } 10994 } 10995} 10996 10997void SiS_SetCHTVchromaflickerfilter(ScrnInfoPtr pScrn, int val) 10998{ 10999 SISPtr pSiS = SISPTR(pScrn); 11000#ifdef SISDUALHEAD 11001 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11002#endif 11003 11004 pSiS->chtvchromaflickerfilter = val; 11005#ifdef SISDUALHEAD 11006 if(pSiSEnt) pSiSEnt->chtvchromaflickerfilter = val; 11007#endif 11008 11009 if(!(pSiS->VBFlags & CRT2_TV)) return; 11010 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 11011 11012#ifdef UNLOCK_ALWAYS 11013 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11014#endif 11015 11016 switch(pSiS->ChrontelType) { 11017 case CHRONTEL_700x: 11018 val /= 6; 11019 if((val >= 0) && (val <= 2)) { 11020 UShort reg = 0; 11021 reg = SiS_GetCH70xx(pSiS->SiS_Pr, 0x01); 11022 reg = (reg & 0xc0) | ((reg & 0x0c) >> 2) | ((reg & 0x03) << 2) | (val << 4); 11023 SiS_SetCH70xx(pSiS->SiS_Pr, 0x01, reg); 11024 } 11025 break; 11026 case CHRONTEL_701x: 11027 val /= 4; 11028 if((val >= 0) && (val <= 3)) { 11029 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x01, (val << 4), 0xCF); 11030 } 11031 break; 11032 } 11033} 11034 11035int SiS_GetCHTVchromaflickerfilter(ScrnInfoPtr pScrn) 11036{ 11037 SISPtr pSiS = SISPTR(pScrn); 11038#ifdef SISDUALHEAD 11039 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11040#endif 11041 11042 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 11043#ifdef SISDUALHEAD 11044 if(pSiSEnt && pSiS->DualHeadMode) 11045 return (int)pSiSEnt->chtvchromaflickerfilter; 11046 else 11047#endif 11048 return (int)pSiS->chtvchromaflickerfilter; 11049 } else { 11050#ifdef UNLOCK_ALWAYS 11051 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11052#endif 11053 switch(pSiS->ChrontelType) { 11054 case CHRONTEL_700x: 11055 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x30) >> 4) * 6); 11056 case CHRONTEL_701x: 11057 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x30) >> 4) * 4); 11058 default: 11059 return (int)pSiS->chtvchromaflickerfilter; 11060 } 11061 } 11062} 11063 11064void SiS_SetCHTVcvbscolor(ScrnInfoPtr pScrn, int val) 11065{ 11066 SISPtr pSiS = SISPTR(pScrn); 11067#ifdef SISDUALHEAD 11068 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11069#endif 11070 11071 pSiS->chtvcvbscolor = val ? 1 : 0; 11072#ifdef SISDUALHEAD 11073 if(pSiSEnt) pSiSEnt->chtvcvbscolor = pSiS->chtvcvbscolor; 11074#endif 11075 11076 if(!(pSiS->VBFlags & CRT2_TV)) return; 11077 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 11078 11079#ifdef UNLOCK_ALWAYS 11080 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11081#endif 11082 11083 switch(pSiS->ChrontelType) { 11084 case CHRONTEL_700x: 11085 if(!val) SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, 0x40, 0x00); 11086 else SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, 0x00, ~0x40); 11087 break; 11088 case CHRONTEL_701x: 11089 if(!val) SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, 0x00, ~0x20); 11090 else SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, 0x20, 0x00); 11091 break; 11092 } 11093} 11094 11095int SiS_GetCHTVcvbscolor(ScrnInfoPtr pScrn) 11096{ 11097 SISPtr pSiS = SISPTR(pScrn); 11098#ifdef SISDUALHEAD 11099 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11100#endif 11101 11102 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 11103#ifdef SISDUALHEAD 11104 if(pSiSEnt && pSiS->DualHeadMode) 11105 return (int)pSiSEnt->chtvcvbscolor; 11106 else 11107#endif 11108 return (int)pSiS->chtvcvbscolor; 11109 } else { 11110#ifdef UNLOCK_ALWAYS 11111 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11112#endif 11113 switch(pSiS->ChrontelType) { 11114 case CHRONTEL_700x: 11115 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x40) >> 6) ^ 0x01); 11116 case CHRONTEL_701x: 11117 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x20) >> 5) ^ 0x01); 11118 default: 11119 return (int)pSiS->chtvcvbscolor; 11120 } 11121 } 11122} 11123 11124void SiS_SetCHTVtextenhance(ScrnInfoPtr pScrn, int val) 11125{ 11126 SISPtr pSiS = SISPTR(pScrn); 11127#ifdef SISDUALHEAD 11128 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11129#endif 11130 11131 pSiS->chtvtextenhance = val; 11132#ifdef SISDUALHEAD 11133 if(pSiSEnt) pSiSEnt->chtvtextenhance = val; 11134#endif 11135 11136 if(!(pSiS->VBFlags & CRT2_TV)) return; 11137 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 11138 11139#ifdef UNLOCK_ALWAYS 11140 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11141#endif 11142 11143 switch(pSiS->ChrontelType) { 11144 case CHRONTEL_700x: 11145 val /= 6; 11146 if((val >= 0) && (val <= 2)) { 11147 UShort reg = 0; 11148 reg = SiS_GetCH70xx(pSiS->SiS_Pr, 0x01); 11149 reg = (reg & 0xf0) | ((reg & 0x03) << 2) | val; 11150 SiS_SetCH70xx(pSiS->SiS_Pr, 0x01, reg); 11151 } 11152 break; 11153 case CHRONTEL_701x: 11154 val /= 2; 11155 if((val >= 0) && (val <= 7)) { 11156 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, val, 0xF8); 11157 } 11158 break; 11159 } 11160} 11161 11162int SiS_GetCHTVtextenhance(ScrnInfoPtr pScrn) 11163{ 11164 SISPtr pSiS = SISPTR(pScrn); 11165#ifdef SISDUALHEAD 11166 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11167#endif 11168 11169 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 11170#ifdef SISDUALHEAD 11171 if(pSiSEnt && pSiS->DualHeadMode) 11172 return (int)pSiSEnt->chtvtextenhance; 11173 else 11174#endif 11175 return (int)pSiS->chtvtextenhance; 11176 } else { 11177#ifdef UNLOCK_ALWAYS 11178 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11179#endif 11180 switch(pSiS->ChrontelType) { 11181 case CHRONTEL_700x: 11182 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x0c) >> 2) * 6); 11183 case CHRONTEL_701x: 11184 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x07) * 2); 11185 default: 11186 return (int)pSiS->chtvtextenhance; 11187 } 11188 } 11189} 11190 11191void SiS_SetCHTVcontrast(ScrnInfoPtr pScrn, int val) 11192{ 11193 SISPtr pSiS = SISPTR(pScrn); 11194#ifdef SISDUALHEAD 11195 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11196#endif 11197 11198 pSiS->chtvcontrast = val; 11199#ifdef SISDUALHEAD 11200 if(pSiSEnt) pSiSEnt->chtvcontrast = val; 11201#endif 11202 11203 if(!(pSiS->VBFlags & CRT2_TV)) return; 11204 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 11205 11206#ifdef UNLOCK_ALWAYS 11207 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11208#endif 11209 11210 val /= 2; 11211 if((val >= 0) && (val <= 7)) { 11212 switch(pSiS->ChrontelType) { 11213 case CHRONTEL_700x: 11214 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x11, val, 0xF8); 11215 break; 11216 case CHRONTEL_701x: 11217 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x08, val, 0xF8); 11218 break; 11219 } 11220 SiS_DDC2Delay(pSiS->SiS_Pr, 1000); 11221 } 11222} 11223 11224int SiS_GetCHTVcontrast(ScrnInfoPtr pScrn) 11225{ 11226 SISPtr pSiS = SISPTR(pScrn); 11227#ifdef SISDUALHEAD 11228 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11229#endif 11230 11231 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 11232#ifdef SISDUALHEAD 11233 if(pSiSEnt && pSiS->DualHeadMode) 11234 return (int)pSiSEnt->chtvcontrast; 11235 else 11236#endif 11237 return (int)pSiS->chtvcontrast; 11238 } else { 11239#ifdef UNLOCK_ALWAYS 11240 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11241#endif 11242 switch(pSiS->ChrontelType) { 11243 case CHRONTEL_700x: 11244 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x11) & 0x07) * 2); 11245 case CHRONTEL_701x: 11246 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x08) & 0x07) * 2); 11247 default: 11248 return (int)pSiS->chtvcontrast; 11249 } 11250 } 11251} 11252 11253void SiS_SetSISTVedgeenhance(ScrnInfoPtr pScrn, int val) 11254{ 11255 SISPtr pSiS = SISPTR(pScrn); 11256#ifdef SISDUALHEAD 11257 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11258#endif 11259 11260 pSiS->sistvedgeenhance = val; 11261#ifdef SISDUALHEAD 11262 if(pSiSEnt) pSiSEnt->sistvedgeenhance = val; 11263#endif 11264 11265 if(!(pSiS->VBFlags2 & VB2_301)) return; 11266 if(!(pSiS->VBFlags & CRT2_TV)) return; 11267 11268#ifdef UNLOCK_ALWAYS 11269 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11270#endif 11271 11272 val /= 2; 11273 if((val >= 0) && (val <= 7)) { 11274 setSISIDXREG(SISPART2,0x3A, 0x1F, (val << 5)); 11275 } 11276} 11277 11278int SiS_GetSISTVedgeenhance(ScrnInfoPtr pScrn) 11279{ 11280 SISPtr pSiS = SISPTR(pScrn); 11281 int result = pSiS->sistvedgeenhance; 11282 UChar temp; 11283#ifdef SISDUALHEAD 11284 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11285 11286 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvedgeenhance; 11287#endif 11288 11289 if(!(pSiS->VBFlags2 & VB2_301)) return result; 11290 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11291 11292#ifdef UNLOCK_ALWAYS 11293 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11294#endif 11295 inSISIDXREG(SISPART2, 0x3a, temp); 11296 return(int)(((temp & 0xe0) >> 5) * 2); 11297} 11298 11299void SiS_SetSISTVantiflicker(ScrnInfoPtr pScrn, int val) 11300{ 11301 SISPtr pSiS = SISPTR(pScrn); 11302#ifdef SISDUALHEAD 11303 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11304#endif 11305 11306 pSiS->sistvantiflicker = val; 11307#ifdef SISDUALHEAD 11308 if(pSiSEnt) pSiSEnt->sistvantiflicker = val; 11309#endif 11310 11311 if(!(pSiS->VBFlags & CRT2_TV)) return; 11312 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11313 if(pSiS->VBFlags & TV_HIVISION) return; 11314 if((pSiS->VBFlags & TV_YPBPR) && 11315 (pSiS->VBFlags & (TV_YPBPR525P | TV_YPBPR625P | TV_YPBPR750P | TV_YPBPR1080I))) return; 11316 11317#ifdef UNLOCK_ALWAYS 11318 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11319#endif 11320 11321 /* Valid values: 0=off, 1=low, 2=med, 3=high, 4=adaptive */ 11322 if((val >= 0) && (val <= 4)) { 11323 setSISIDXREG(SISPART2,0x0A,0x8F, (val << 4)); 11324 } 11325} 11326 11327int SiS_GetSISTVantiflicker(ScrnInfoPtr pScrn) 11328{ 11329 SISPtr pSiS = SISPTR(pScrn); 11330 int result = pSiS->sistvantiflicker; 11331 UChar temp; 11332#ifdef SISDUALHEAD 11333 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11334 11335 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvantiflicker; 11336#endif 11337 11338 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return result; 11339 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11340 if(pSiS->VBFlags & TV_HIVISION) return result; 11341 if((pSiS->VBFlags & TV_YPBPR) && 11342 (pSiS->VBFlags & (TV_YPBPR525P | TV_YPBPR625P | TV_YPBPR750P | TV_YPBPR1080I))) return result; 11343 11344#ifdef UNLOCK_ALWAYS 11345 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11346#endif 11347 inSISIDXREG(SISPART2, 0x0a, temp); 11348 return(int)((temp & 0x70) >> 4); 11349} 11350 11351void SiS_SetSISTVsaturation(ScrnInfoPtr pScrn, int val) 11352{ 11353 SISPtr pSiS = SISPTR(pScrn); 11354#ifdef SISDUALHEAD 11355 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11356#endif 11357 11358 pSiS->sistvsaturation = val; 11359#ifdef SISDUALHEAD 11360 if(pSiSEnt) pSiSEnt->sistvsaturation = val; 11361#endif 11362 11363 if(!(pSiS->VBFlags & CRT2_TV)) return; 11364 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11365 if(pSiS->VBFlags2 & VB2_301) return; 11366 11367#ifdef UNLOCK_ALWAYS 11368 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11369#endif 11370 11371 val /= 2; 11372 if((val >= 0) && (val <= 7)) { 11373 setSISIDXREG(SISPART4,0x21,0xF8, val); 11374 } 11375} 11376 11377int SiS_GetSISTVsaturation(ScrnInfoPtr pScrn) 11378{ 11379 SISPtr pSiS = SISPTR(pScrn); 11380 int result = pSiS->sistvsaturation; 11381 UChar temp; 11382#ifdef SISDUALHEAD 11383 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11384 11385 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvsaturation; 11386#endif 11387 11388 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return result; 11389 if(pSiS->VBFlags2 & VB2_301) return result; 11390 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11391 11392#ifdef UNLOCK_ALWAYS 11393 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11394#endif 11395 inSISIDXREG(SISPART4, 0x21, temp); 11396 return(int)((temp & 0x07) * 2); 11397} 11398 11399void SiS_SetSISTVcolcalib(ScrnInfoPtr pScrn, int val, Bool coarse) 11400{ 11401 SISPtr pSiS = SISPTR(pScrn); 11402#ifdef SISDUALHEAD 11403 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11404#endif 11405 int ccoarse, cfine, cbase = pSiS->sistvccbase; 11406 /* UChar temp; */ 11407 11408#ifdef SISDUALHEAD 11409 if(pSiSEnt && pSiS->DualHeadMode) cbase = pSiSEnt->sistvccbase; 11410#endif 11411 11412 if(coarse) { 11413 pSiS->sistvcolcalibc = ccoarse = val; 11414 cfine = pSiS->sistvcolcalibf; 11415#ifdef SISDUALHEAD 11416 if(pSiSEnt) { 11417 pSiSEnt->sistvcolcalibc = val; 11418 if(pSiS->DualHeadMode) cfine = pSiSEnt->sistvcolcalibf; 11419 } 11420#endif 11421 } else { 11422 pSiS->sistvcolcalibf = cfine = val; 11423 ccoarse = pSiS->sistvcolcalibc; 11424#ifdef SISDUALHEAD 11425 if(pSiSEnt) { 11426 pSiSEnt->sistvcolcalibf = val; 11427 if(pSiS->DualHeadMode) ccoarse = pSiSEnt->sistvcolcalibc; 11428 } 11429#endif 11430 } 11431 11432 if(!(pSiS->VBFlags & CRT2_TV)) return; 11433 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11434 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return; 11435 11436#ifdef UNLOCK_ALWAYS 11437 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11438#endif 11439 11440 if((cfine >= -128) && (cfine <= 127) && (ccoarse >= -120) && (ccoarse <= 120)) { 11441 long finalcc = cbase + (((ccoarse * 256) + cfine) * 256); 11442 11443#if 0 11444 inSISIDXREG(SISPART4,0x1f,temp); 11445 if(!(temp & 0x01)) { 11446 if(pSiS->VBFlags & TV_NTSC) finalcc += 0x21ed8620; 11447 else if(pSiS->VBFlags & TV_PALM) finalcc += ?; 11448 else if(pSiS->VBFlags & TV_PALM) finalcc += ?; 11449 else finalcc += 0x2a05d300; 11450 } 11451#endif 11452 setSISIDXREG(SISPART2,0x31,0x80,((finalcc >> 24) & 0x7f)); 11453 outSISIDXREG(SISPART2,0x32,((finalcc >> 16) & 0xff)); 11454 outSISIDXREG(SISPART2,0x33,((finalcc >> 8) & 0xff)); 11455 outSISIDXREG(SISPART2,0x34,(finalcc & 0xff)); 11456 } 11457} 11458 11459int SiS_GetSISTVcolcalib(ScrnInfoPtr pScrn, Bool coarse) 11460{ 11461 SISPtr pSiS = SISPTR(pScrn); 11462#ifdef SISDUALHEAD 11463 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11464 11465 if(pSiSEnt && pSiS->DualHeadMode) 11466 if(coarse) return (int)pSiSEnt->sistvcolcalibc; 11467 else return (int)pSiSEnt->sistvcolcalibf; 11468 else 11469#endif 11470 if(coarse) return (int)pSiS->sistvcolcalibc; 11471 else return (int)pSiS->sistvcolcalibf; 11472} 11473 11474void SiS_SetSISTVcfilter(ScrnInfoPtr pScrn, int val) 11475{ 11476 SISPtr pSiS = SISPTR(pScrn); 11477#ifdef SISDUALHEAD 11478 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11479#endif 11480 11481 pSiS->sistvcfilter = val ? 1 : 0; 11482#ifdef SISDUALHEAD 11483 if(pSiSEnt) pSiSEnt->sistvcfilter = pSiS->sistvcfilter; 11484#endif 11485 11486 if(!(pSiS->VBFlags & CRT2_TV)) return; 11487 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11488 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return; 11489 11490#ifdef UNLOCK_ALWAYS 11491 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11492#endif 11493 11494 setSISIDXREG(SISPART2,0x30,~0x10,((pSiS->sistvcfilter << 4) & 0x10)); 11495} 11496 11497int SiS_GetSISTVcfilter(ScrnInfoPtr pScrn) 11498{ 11499 SISPtr pSiS = SISPTR(pScrn); 11500 int result = pSiS->sistvcfilter; 11501 UChar temp; 11502#ifdef SISDUALHEAD 11503 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11504 11505 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvcfilter; 11506#endif 11507 11508 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return result; 11509 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11510 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return result; 11511 11512#ifdef UNLOCK_ALWAYS 11513 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11514#endif 11515 inSISIDXREG(SISPART2, 0x30, temp); 11516 return (int)((temp & 0x10) ? 1 : 0); 11517} 11518 11519void SiS_SetSISTVyfilter(ScrnInfoPtr pScrn, int val) 11520{ 11521 SISPtr pSiS = SISPTR(pScrn); 11522#ifdef SISDUALHEAD 11523 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11524#endif 11525 UChar p35,p36,p37,p38,p48,p49,p4a,p30; 11526 int i,j; 11527 11528 pSiS->sistvyfilter = val; 11529#ifdef SISDUALHEAD 11530 if(pSiSEnt) pSiSEnt->sistvyfilter = pSiS->sistvyfilter; 11531#endif 11532 11533 if(!(pSiS->VBFlags & CRT2_TV)) return; 11534 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11535 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return; 11536 11537 p35 = pSiS->p2_35; p36 = pSiS->p2_36; 11538 p37 = pSiS->p2_37; p38 = pSiS->p2_38; 11539 p48 = pSiS->p2_48; p49 = pSiS->p2_49; 11540 p4a = pSiS->p2_4a; p30 = pSiS->p2_30; 11541#ifdef SISDUALHEAD 11542 if(pSiSEnt && pSiS->DualHeadMode) { 11543 p35 = pSiSEnt->p2_35; p36 = pSiSEnt->p2_36; 11544 p37 = pSiSEnt->p2_37; p38 = pSiSEnt->p2_38; 11545 p48 = pSiSEnt->p2_48; p49 = pSiSEnt->p2_49; 11546 p4a = pSiSEnt->p2_4a; p30 = pSiSEnt->p2_30; 11547 } 11548#endif 11549 p30 &= 0x20; 11550 11551#ifdef UNLOCK_ALWAYS 11552 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11553#endif 11554 11555 switch(pSiS->sistvyfilter) { 11556 case 0: 11557 andSISIDXREG(SISPART2,0x30,0xdf); 11558 break; 11559 case 1: 11560 outSISIDXREG(SISPART2,0x35,p35); 11561 outSISIDXREG(SISPART2,0x36,p36); 11562 outSISIDXREG(SISPART2,0x37,p37); 11563 outSISIDXREG(SISPART2,0x38,p38); 11564 if(!(pSiS->VBFlags2 & VB2_301)) { 11565 outSISIDXREG(SISPART2,0x48,p48); 11566 outSISIDXREG(SISPART2,0x49,p49); 11567 outSISIDXREG(SISPART2,0x4a,p4a); 11568 } 11569 setSISIDXREG(SISPART2,0x30,0xdf,p30); 11570 break; 11571 case 2: 11572 case 3: 11573 case 4: 11574 case 5: 11575 case 6: 11576 case 7: 11577 case 8: 11578 if(!(pSiS->VBFlags & (TV_PALM | TV_PALN | TV_NTSCJ))) { 11579 int yindex301 = -1, yindex301B = -1; 11580 UChar p3d4_34; 11581 11582 inSISIDXREG(SISCR,0x34,p3d4_34); 11583 11584 switch((p3d4_34 & 0x7f)) { 11585 case 0x59: /* 320x200 */ 11586 case 0x41: 11587 case 0x4f: 11588 case 0x50: /* 320x240 */ 11589 case 0x56: 11590 case 0x53: 11591 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 0 : 4; 11592 break; 11593 case 0x2f: /* 640x400 */ 11594 case 0x5d: 11595 case 0x5e: 11596 case 0x2e: /* 640x480 */ 11597 case 0x44: 11598 case 0x62: 11599 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 1 : 5; 11600 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 0 : 4; 11601 break; 11602 case 0x31: /* 720x480 */ 11603 case 0x33: 11604 case 0x35: 11605 case 0x32: /* 720x576 */ 11606 case 0x34: 11607 case 0x36: 11608 case 0x5f: /* 768x576 */ 11609 case 0x60: 11610 case 0x61: 11611 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 2 : 6; 11612 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 1 : 5; 11613 break; 11614 case 0x51: /* 400x300 */ 11615 case 0x57: 11616 case 0x54: 11617 case 0x30: /* 800x600 */ 11618 case 0x47: 11619 case 0x63: 11620 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 3 : 7; 11621 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 2 : 6; 11622 break; 11623 case 0x52: /* 512x384 */ 11624 case 0x58: 11625 case 0x5c: 11626 case 0x38: /* 1024x768 */ 11627 case 0x4a: 11628 case 0x64: 11629 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 3 : 7; 11630 break; 11631 } 11632 if(pSiS->VBFlags2 & VB2_301) { 11633 if(yindex301 >= 0) { 11634 for(i=0, j=0x35; i<=3; i++, j++) { 11635 outSISIDXREG(SISPART2,j,(SiSTVFilter301[yindex301].filter[pSiS->sistvyfilter-2][i])); 11636 } 11637 } 11638 } else { 11639 if(yindex301B >= 0) { 11640 for(i=0, j=0x35; i<=3; i++, j++) { 11641 outSISIDXREG(SISPART2,j,(SiSTVFilter301B[yindex301B].filter[pSiS->sistvyfilter-2][i])); 11642 } 11643 for(i=4, j=0x48; i<=6; i++, j++) { 11644 outSISIDXREG(SISPART2,j,(SiSTVFilter301B[yindex301B].filter[pSiS->sistvyfilter-2][i])); 11645 } 11646 } 11647 } 11648 orSISIDXREG(SISPART2,0x30,0x20); 11649 } 11650 } 11651} 11652 11653int SiS_GetSISTVyfilter(ScrnInfoPtr pScrn) 11654{ 11655 SISPtr pSiS = SISPTR(pScrn); 11656#ifdef SISDUALHEAD 11657 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11658 11659 if(pSiSEnt && pSiS->DualHeadMode) 11660 return (int)pSiSEnt->sistvyfilter; 11661 else 11662#endif 11663 return (int)pSiS->sistvyfilter; 11664} 11665 11666void SiS_SetSIS6326TVantiflicker(ScrnInfoPtr pScrn, int val) 11667{ 11668 SISPtr pSiS = SISPTR(pScrn); 11669 UChar tmp; 11670 11671 pSiS->sistvantiflicker = val; 11672 11673 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 11674 11675#ifdef UNLOCK_ALWAYS 11676 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11677#endif 11678 11679 tmp = SiS6326GetTVReg(pScrn,0x00); 11680 if(!(tmp & 0x04)) return; 11681 11682 /* Valid values: 0=off, 1=low, 2=med, 3=high, 4=adaptive */ 11683 if(val >= 0 && val <= 4) { 11684 tmp &= 0x1f; 11685 tmp |= (val << 5); 11686 SiS6326SetTVReg(pScrn,0x00,tmp); 11687 } 11688} 11689 11690int SiS_GetSIS6326TVantiflicker(ScrnInfoPtr pScrn) 11691{ 11692 SISPtr pSiS = SISPTR(pScrn); 11693 UChar tmp; 11694 11695 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 11696 return (int)pSiS->sistvantiflicker; 11697 } 11698 11699#ifdef UNLOCK_ALWAYS 11700 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11701#endif 11702 11703 tmp = SiS6326GetTVReg(pScrn,0x00); 11704 if(!(tmp & 0x04)) { 11705 return (int)pSiS->sistvantiflicker; 11706 } else { 11707 return (int)((tmp >> 5) & 0x07); 11708 } 11709} 11710 11711void SiS_SetSIS6326TVenableyfilter(ScrnInfoPtr pScrn, int val) 11712{ 11713 SISPtr pSiS = SISPTR(pScrn); 11714 UChar tmp; 11715 11716 if(val) val = 1; 11717 pSiS->sis6326enableyfilter = val; 11718 11719 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 11720 11721#ifdef UNLOCK_ALWAYS 11722 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11723#endif 11724 11725 tmp = SiS6326GetTVReg(pScrn,0x00); 11726 if(!(tmp & 0x04)) return; 11727 11728 tmp = SiS6326GetTVReg(pScrn,0x43); 11729 tmp &= ~0x10; 11730 tmp |= ((val & 0x01) << 4); 11731 SiS6326SetTVReg(pScrn,0x43,tmp); 11732} 11733 11734int SiS_GetSIS6326TVenableyfilter(ScrnInfoPtr pScrn) 11735{ 11736 SISPtr pSiS = SISPTR(pScrn); 11737 UChar tmp; 11738 11739 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 11740 return (int)pSiS->sis6326enableyfilter; 11741 } 11742 11743#ifdef UNLOCK_ALWAYS 11744 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11745#endif 11746 11747 tmp = SiS6326GetTVReg(pScrn,0x00); 11748 if(!(tmp & 0x04)) { 11749 return (int)pSiS->sis6326enableyfilter; 11750 } else { 11751 tmp = SiS6326GetTVReg(pScrn,0x43); 11752 return (int)((tmp >> 4) & 0x01); 11753 } 11754} 11755 11756void SiS_SetSIS6326TVyfilterstrong(ScrnInfoPtr pScrn, int val) 11757{ 11758 SISPtr pSiS = SISPTR(pScrn); 11759 UChar tmp; 11760 11761 if(val) val = 1; 11762 pSiS->sis6326yfilterstrong = val; 11763 11764 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 11765 11766#ifdef UNLOCK_ALWAYS 11767 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11768#endif 11769 11770 tmp = SiS6326GetTVReg(pScrn,0x00); 11771 if(!(tmp & 0x04)) return; 11772 11773 tmp = SiS6326GetTVReg(pScrn,0x43); 11774 if(tmp & 0x10) { 11775 tmp &= ~0x40; 11776 tmp |= ((val & 0x01) << 6); 11777 SiS6326SetTVReg(pScrn,0x43,tmp); 11778 } 11779} 11780 11781int SiS_GetSIS6326TVyfilterstrong(ScrnInfoPtr pScrn) 11782{ 11783 SISPtr pSiS = SISPTR(pScrn); 11784 UChar tmp; 11785 11786 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 11787 return (int)pSiS->sis6326yfilterstrong; 11788 } 11789 11790#ifdef UNLOCK_ALWAYS 11791 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11792#endif 11793 11794 tmp = SiS6326GetTVReg(pScrn,0x00); 11795 if(!(tmp & 0x04)) { 11796 return (int)pSiS->sis6326yfilterstrong; 11797 } else { 11798 tmp = SiS6326GetTVReg(pScrn,0x43); 11799 if(!(tmp & 0x10)) { 11800 return (int)pSiS->sis6326yfilterstrong; 11801 } else { 11802 return (int)((tmp >> 6) & 0x01); 11803 } 11804 } 11805} 11806 11807void SiS_SetTVxposoffset(ScrnInfoPtr pScrn, int val) 11808{ 11809 SISPtr pSiS = SISPTR(pScrn); 11810#ifdef SISDUALHEAD 11811 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11812#endif 11813 11814#ifdef UNLOCK_ALWAYS 11815 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11816#endif 11817 11818 pSiS->tvxpos = val; 11819#ifdef SISDUALHEAD 11820 if(pSiSEnt) pSiSEnt->tvxpos = val; 11821#endif 11822 11823 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 11824 11825 if(pSiS->VBFlags & CRT2_TV) { 11826 11827 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 11828 11829 int x = pSiS->tvx; 11830#ifdef SISDUALHEAD 11831 if(pSiSEnt && pSiS->DualHeadMode) x = pSiSEnt->tvx; 11832#endif 11833 switch(pSiS->ChrontelType) { 11834 case CHRONTEL_700x: 11835 if((val >= -32) && (val <= 32)) { 11836 x += val; 11837 if(x < 0) x = 0; 11838 SiS_SetCH700x(pSiS->SiS_Pr, 0x0a, (x & 0xff)); 11839 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD); 11840 } 11841 break; 11842 case CHRONTEL_701x: 11843 /* Not supported by hardware */ 11844 break; 11845 } 11846 11847 } else if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 11848 11849 if((val >= -32) && (val <= 32)) { 11850 11851 UChar p2_1f,p2_20,p2_2b,p2_42,p2_43; 11852 UShort temp; 11853 int mult; 11854 11855 p2_1f = pSiS->p2_1f; 11856 p2_20 = pSiS->p2_20; 11857 p2_2b = pSiS->p2_2b; 11858 p2_42 = pSiS->p2_42; 11859 p2_43 = pSiS->p2_43; 11860#ifdef SISDUALHEAD 11861 if(pSiSEnt && pSiS->DualHeadMode) { 11862 p2_1f = pSiSEnt->p2_1f; 11863 p2_20 = pSiSEnt->p2_20; 11864 p2_2b = pSiSEnt->p2_2b; 11865 p2_42 = pSiSEnt->p2_42; 11866 p2_43 = pSiSEnt->p2_43; 11867 } 11868#endif 11869 mult = 2; 11870 if(pSiS->VBFlags & TV_YPBPR) { 11871 if(pSiS->VBFlags & (TV_YPBPR1080I | TV_YPBPR750P)) { 11872 mult = 4; 11873 } 11874 } 11875 11876 temp = p2_1f | ((p2_20 & 0xf0) << 4); 11877 temp += (val * mult); 11878 p2_1f = temp & 0xff; 11879 p2_20 = (temp & 0xf00) >> 4; 11880 p2_2b = ((p2_2b & 0x0f) + (val * mult)) & 0x0f; 11881 temp = p2_43 | ((p2_42 & 0xf0) << 4); 11882 temp += (val * mult); 11883 p2_43 = temp & 0xff; 11884 p2_42 = (temp & 0xf00) >> 4; 11885 SISWaitRetraceCRT2(pScrn); 11886 outSISIDXREG(SISPART2,0x1f,p2_1f); 11887 setSISIDXREG(SISPART2,0x20,0x0F,p2_20); 11888 setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b); 11889 setSISIDXREG(SISPART2,0x42,0x0F,p2_42); 11890 outSISIDXREG(SISPART2,0x43,p2_43); 11891 } 11892 } 11893 } 11894 11895 } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { 11896 11897 if(pSiS->SiS6326Flags & SIS6326_TVDETECTED) { 11898 11899 UChar tmp; 11900 UShort temp1, temp2, temp3; 11901 11902 tmp = SiS6326GetTVReg(pScrn,0x00); 11903 if(tmp & 0x04) { 11904 11905 temp1 = pSiS->tvx1; 11906 temp2 = pSiS->tvx2; 11907 temp3 = pSiS->tvx3; 11908 if((val >= -16) && (val <= 16)) { 11909 if(val > 0) { 11910 temp1 += (val * 4); 11911 temp2 += (val * 4); 11912 while((temp1 > 0x0fff) || (temp2 > 0x0fff)) { 11913 temp1 -= 4; 11914 temp2 -= 4; 11915 } 11916 } else { 11917 val = -val; 11918 temp3 += (val * 4); 11919 while(temp3 > 0x03ff) { 11920 temp3 -= 4; 11921 } 11922 } 11923 } 11924 SiS6326SetTVReg(pScrn,0x3a,(temp1 & 0xff)); 11925 tmp = SiS6326GetTVReg(pScrn,0x3c); 11926 tmp &= 0xf0; 11927 tmp |= ((temp1 & 0x0f00) >> 8); 11928 SiS6326SetTVReg(pScrn,0x3c,tmp); 11929 SiS6326SetTVReg(pScrn,0x26,(temp2 & 0xff)); 11930 tmp = SiS6326GetTVReg(pScrn,0x27); 11931 tmp &= 0x0f; 11932 tmp |= ((temp2 & 0x0f00) >> 4); 11933 SiS6326SetTVReg(pScrn,0x27,tmp); 11934 SiS6326SetTVReg(pScrn,0x12,(temp3 & 0xff)); 11935 tmp = SiS6326GetTVReg(pScrn,0x13); 11936 tmp &= ~0xC0; 11937 tmp |= ((temp3 & 0x0300) >> 2); 11938 SiS6326SetTVReg(pScrn,0x13,tmp); 11939 } 11940 } 11941 } 11942} 11943 11944int SiS_GetTVxposoffset(ScrnInfoPtr pScrn) 11945{ 11946 SISPtr pSiS = SISPTR(pScrn); 11947#ifdef SISDUALHEAD 11948 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11949 11950 if(pSiSEnt && pSiS->DualHeadMode) 11951 return (int)pSiSEnt->tvxpos; 11952 else 11953#endif 11954 return (int)pSiS->tvxpos; 11955} 11956 11957void SiS_SetTVyposoffset(ScrnInfoPtr pScrn, int val) 11958{ 11959 SISPtr pSiS = SISPTR(pScrn); 11960#ifdef SISDUALHEAD 11961 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11962#endif 11963 11964#ifdef UNLOCK_ALWAYS 11965 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11966#endif 11967 11968 pSiS->tvypos = val; 11969#ifdef SISDUALHEAD 11970 if(pSiSEnt) pSiSEnt->tvypos = val; 11971#endif 11972 11973 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 11974 11975 if(pSiS->VBFlags & CRT2_TV) { 11976 11977 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 11978 11979 int y = pSiS->tvy; 11980#ifdef SISDUALHEAD 11981 if(pSiSEnt && pSiS->DualHeadMode) y = pSiSEnt->tvy; 11982#endif 11983 switch(pSiS->ChrontelType) { 11984 case CHRONTEL_700x: 11985 if((val >= -32) && (val <= 32)) { 11986 y -= val; 11987 if(y < 0) y = 0; 11988 SiS_SetCH700x(pSiS->SiS_Pr, 0x0b, (y & 0xff)); 11989 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE); 11990 } 11991 break; 11992 case CHRONTEL_701x: 11993 /* Not supported by hardware */ 11994 break; 11995 } 11996 11997 } else if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 11998 11999 if((val >= -32) && (val <= 32)) { 12000 char p2_01, p2_02; 12001 12002 if( (pSiS->VBFlags & TV_HIVISION) || 12003 ((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & (TV_YPBPR1080I|TV_YPBPR750P))) ) { 12004 val *= 2; 12005 } else { 12006 val /= 2; /* 4 */ 12007 } 12008 12009 p2_01 = pSiS->p2_01; 12010 p2_02 = pSiS->p2_02; 12011#ifdef SISDUALHEAD 12012 if(pSiSEnt && pSiS->DualHeadMode) { 12013 p2_01 = pSiSEnt->p2_01; 12014 p2_02 = pSiSEnt->p2_02; 12015 } 12016#endif 12017 p2_01 += val; /* val * 2 */ 12018 p2_02 += val; /* val * 2 */ 12019 if(!(pSiS->VBFlags & (TV_YPBPR | TV_HIVISION))) { 12020 while((p2_01 <= 0) || (p2_02 <= 0)) { 12021 p2_01 += 2; 12022 p2_02 += 2; 12023 } 12024 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR1080I)) { 12025 while(p2_01 <= 8) { 12026 p2_01 += 2; 12027 p2_02 += 2; 12028 } 12029 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR750P)) { 12030 while(p2_01 <= 10) { 12031 p2_01 += 2; 12032 p2_02 += 2; 12033 } 12034 } 12035 12036 SISWaitRetraceCRT2(pScrn); 12037 outSISIDXREG(SISPART2,0x01,p2_01); 12038 outSISIDXREG(SISPART2,0x02,p2_02); 12039 } 12040 } 12041 12042 } 12043 12044 } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { 12045 12046 if(pSiS->SiS6326Flags & SIS6326_TVDETECTED) { 12047 12048 UChar tmp; 12049 int temp1, limit; 12050 12051 tmp = SiS6326GetTVReg(pScrn,0x00); 12052 if(tmp & 0x04) { 12053 12054 if((val >= -16) && (val <= 16)) { 12055 temp1 = (UShort)pSiS->tvy1; 12056 limit = (pSiS->SiS6326Flags & SIS6326_TVPAL) ? 625 : 525; 12057 if(val > 0) { 12058 temp1 += (val * 4); 12059 if(temp1 > limit) temp1 -= limit; 12060 } else { 12061 val = -val; 12062 temp1 -= (val * 2); 12063 if(temp1 <= 0) temp1 += (limit -1); 12064 } 12065 SiS6326SetTVReg(pScrn,0x11,(temp1 & 0xff)); 12066 tmp = SiS6326GetTVReg(pScrn,0x13); 12067 tmp &= ~0x30; 12068 tmp |= ((temp1 & 0x300) >> 4); 12069 SiS6326SetTVReg(pScrn,0x13,tmp); 12070 if(temp1 == 1) tmp = 0x10; 12071 else { 12072 if(pSiS->SiS6326Flags & SIS6326_TVPAL) { 12073 if((temp1 <= 3) || (temp1 >= (limit - 2))) tmp = 0x08; 12074 else if(temp1 < 22) tmp = 0x02; 12075 else tmp = 0x04; 12076 } else { 12077 if((temp1 <= 5) || (temp1 >= (limit - 4))) tmp = 0x08; 12078 else if(temp1 < 19) tmp = 0x02; 12079 else tmp = 0x04; 12080 } 12081 } 12082 SiS6326SetTVReg(pScrn,0x21,tmp); 12083 } 12084 } 12085 } 12086 } 12087} 12088 12089int SiS_GetTVyposoffset(ScrnInfoPtr pScrn) 12090{ 12091 SISPtr pSiS = SISPTR(pScrn); 12092#ifdef SISDUALHEAD 12093 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12094 12095 if(pSiSEnt && pSiS->DualHeadMode) 12096 return (int)pSiSEnt->tvypos; 12097 else 12098#endif 12099 return (int)pSiS->tvypos; 12100} 12101 12102void SiS_SetTVxscale(ScrnInfoPtr pScrn, int val) 12103{ 12104 SISPtr pSiS = SISPTR(pScrn); 12105#ifdef SISDUALHEAD 12106 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12107#endif 12108 12109#ifdef UNLOCK_ALWAYS 12110 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12111#endif 12112 12113 pSiS->tvxscale = val; 12114#ifdef SISDUALHEAD 12115 if(pSiSEnt) pSiSEnt->tvxscale = val; 12116#endif 12117 12118 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 12119 12120 if((pSiS->VBFlags & CRT2_TV) && (pSiS->VBFlags2 & VB2_SISBRIDGE)) { 12121 12122 if((val >= -16) && (val <= 16)) { 12123 12124 UChar p2_44,p2_45,p2_46; 12125 int scalingfactor, mult; 12126 12127 p2_44 = pSiS->p2_44; 12128 p2_45 = pSiS->p2_45 & 0x3f; 12129 p2_46 = pSiS->p2_46 & 0x07; 12130#ifdef SISDUALHEAD 12131 if(pSiSEnt && pSiS->DualHeadMode) { 12132 p2_44 = pSiSEnt->p2_44; 12133 p2_45 = pSiSEnt->p2_45 & 0x3f; 12134 p2_46 = pSiSEnt->p2_46 & 0x07; 12135 } 12136#endif 12137 scalingfactor = (p2_46 << 13) | ((p2_45 & 0x1f) << 8) | p2_44; 12138 12139 mult = 64; 12140 if(pSiS->VBFlags & TV_YPBPR) { 12141 if(pSiS->VBFlags & TV_YPBPR1080I) { 12142 mult = 190; 12143 } else if(pSiS->VBFlags & TV_YPBPR750P) { 12144 mult = 360; 12145 } 12146 } else if(pSiS->VBFlags & TV_HIVISION) { 12147 mult = 190; 12148 } 12149 12150 if(val < 0) { 12151 p2_45 &= 0xdf; 12152 scalingfactor += ((-val) * mult); 12153 if(scalingfactor > 0xffff) scalingfactor = 0xffff; 12154 } else if(val > 0) { 12155 p2_45 &= 0xdf; 12156 scalingfactor -= (val * mult); 12157 if(scalingfactor < 1) scalingfactor = 1; 12158 } 12159 12160 p2_44 = scalingfactor & 0xff; 12161 p2_45 &= 0xe0; 12162 p2_45 |= ((scalingfactor >> 8) & 0x1f); 12163 p2_46 = ((scalingfactor >> 13) & 0x07); 12164 12165 SISWaitRetraceCRT2(pScrn); 12166 outSISIDXREG(SISPART2,0x44,p2_44); 12167 setSISIDXREG(SISPART2,0x45,0xC0,p2_45); 12168 if(!(pSiS->VBFlags2 & VB2_301)) { 12169 setSISIDXREG(SISPART2,0x46,0xF8,p2_46); 12170 } 12171 12172 } 12173 12174 } 12175 12176 } 12177} 12178 12179int SiS_GetTVxscale(ScrnInfoPtr pScrn) 12180{ 12181 SISPtr pSiS = SISPTR(pScrn); 12182#ifdef SISDUALHEAD 12183 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12184 12185 if(pSiSEnt && pSiS->DualHeadMode) 12186 return (int)pSiSEnt->tvxscale; 12187 else 12188#endif 12189 return (int)pSiS->tvxscale; 12190} 12191 12192void SiS_SetTVyscale(ScrnInfoPtr pScrn, int val) 12193{ 12194 SISPtr pSiS = SISPTR(pScrn); 12195#ifdef SISDUALHEAD 12196 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12197#endif 12198 12199#ifdef UNLOCK_ALWAYS 12200 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12201#endif 12202 12203 if(val < -4) val = -4; 12204 if(val > 3) val = 3; 12205 12206 pSiS->tvyscale = val; 12207#ifdef SISDUALHEAD 12208 if(pSiSEnt) pSiSEnt->tvyscale = val; 12209#endif 12210 12211 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 12212 12213 if((pSiS->VBFlags & CRT2_TV) && (pSiS->VBFlags2 & VB2_SISBRIDGE)) { 12214 12215 int srindex = -1, newvde, i = 0, j, vlimit, temp, vdediv; 12216 int hdclk = 0; 12217 UChar p3d4_34; 12218 Bool found = FALSE; 12219 Bool usentsc = FALSE; 12220 Bool is750p = FALSE; 12221 Bool is1080i = FALSE; 12222 Bool skipmoveup = FALSE; 12223 12224 SiS_UnLockCRT2(pSiS->SiS_Pr); 12225 12226 if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR525P)) { 12227 vlimit = 525 - 7; 12228 vdediv = 1; 12229 usentsc = TRUE; 12230 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR625P)) { 12231 vlimit = 625 - 7; 12232 vdediv = 1; 12233 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR750P)) { 12234 vlimit = 750 - 7; 12235 vdediv = 1; 12236 is750p = TRUE; 12237 } else if(((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR1080I)) || 12238 (pSiS->VBFlags & TV_HIVISION)) { 12239 vlimit = (1125 - 7) / 2; 12240 vdediv = 2; 12241 is1080i = TRUE; 12242 } else { 12243 if( ((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR525I)) || 12244 ((!(pSiS->VBFlags & TV_YPBPR)) && (pSiS->VBFlags & (TV_NTSC | TV_PALM))) ) { 12245 usentsc = TRUE; 12246 } 12247 vlimit = usentsc ? 259 : 309; 12248 vdediv = 2; 12249 } 12250 12251 inSISIDXREG(SISCR,0x34,p3d4_34); 12252 12253 switch((p3d4_34 & 0x7f)) { 12254 case 0x50: /* 320x240 */ 12255 case 0x56: 12256 case 0x53: 12257 hdclk = 1; 12258 /* fall through */ 12259 case 0x2e: /* 640x480 */ 12260 case 0x44: 12261 case 0x62: 12262 if(is1080i) { 12263 srindex = 98; 12264 } else if(is750p) { 12265 srindex = 42; 12266 } else { 12267 srindex = usentsc ? 0 : 21; 12268 } 12269 break; 12270 case 0x31: /* 720x480 */ 12271 case 0x33: 12272 case 0x35: 12273 if(is1080i) { 12274 /* n/a */ 12275 } else if(is750p) { 12276 srindex = 49; 12277 } else { 12278 srindex = usentsc ? 7 : 21; 12279 } 12280 break; 12281 case 0x32: /* 720x576 */ 12282 case 0x34: 12283 case 0x36: 12284 case 0x5f: /* 768x576 */ 12285 case 0x60: 12286 case 0x61: 12287 if(is1080i) { 12288 /* n/a */ 12289 } else if(is750p) { 12290 srindex = 56; 12291 } else { 12292 srindex = usentsc ? 147 : 28; 12293 } 12294 break; 12295 case 0x70: /* 800x480 */ 12296 case 0x7a: 12297 case 0x76: 12298 if(is1080i) { 12299 srindex = 105; 12300 } else if(is750p) { 12301 srindex = 63; 12302 } else { 12303 srindex = usentsc ? 175 : 21; 12304 } 12305 break; 12306 case 0x51: /* 400x300 - hdclk mode */ 12307 case 0x57: 12308 case 0x54: 12309 hdclk = 1; 12310 /* fall through */ 12311 case 0x30: /* 800x600 */ 12312 case 0x47: 12313 case 0x63: 12314 if(is1080i) { 12315 srindex = 112; 12316 } else if(is750p) { 12317 srindex = 70; 12318 } else { 12319 srindex = usentsc ? 14 : 35; 12320 } 12321 break; 12322 case 0x1d: /* 960x540 */ 12323 case 0x1e: 12324 case 0x1f: 12325 if(is1080i) { 12326 srindex = 196; 12327 skipmoveup = TRUE; 12328 } 12329 break; 12330 case 0x20: /* 960x600 */ 12331 case 0x21: 12332 case 0x22: 12333 if(pSiS->VGAEngine == SIS_315_VGA && is1080i) { 12334 srindex = 203; 12335 } 12336 break; 12337 case 0x71: /* 1024x576 */ 12338 case 0x74: 12339 case 0x77: 12340 if(is1080i) { 12341 srindex = 119; 12342 } else if(is750p) { 12343 srindex = 77; 12344 } else { 12345 srindex = usentsc ? 182 : 189; 12346 } 12347 break; 12348 case 0x52: /* 512x384 */ 12349 case 0x58: 12350 case 0x5c: 12351 hdclk = 1; 12352 /* fall through */ 12353 case 0x38: /* 1024x768 */ 12354 case 0x4a: 12355 case 0x64: 12356 if(is1080i) { 12357 srindex = 126; 12358 } else if(is750p) { 12359 srindex = 84; 12360 } else if(!usentsc) { 12361 srindex = 154; 12362 } else if(vdediv == 1) { 12363 if(!hdclk) srindex = 168; 12364 } else { 12365 if(!hdclk) srindex = 161; 12366 } 12367 break; 12368 case 0x79: /* 1280x720 */ 12369 case 0x75: 12370 case 0x78: 12371 if(is1080i) { 12372 srindex = 133; 12373 } else if(is750p) { 12374 srindex = 91; 12375 } 12376 break; 12377 case 0x3a: /* 1280x1024 */ 12378 case 0x4d: 12379 case 0x65: 12380 if(is1080i) { 12381 srindex = 140; 12382 } 12383 break; 12384 } 12385 12386 if(srindex < 0) return; 12387 12388 if(pSiS->tvyscale != 0) { 12389 for(j = 0; j <= 1; j++) { 12390 for(i = 0; i <= 6; i++) { 12391 if(SiSTVVScale[srindex+i].sindex == pSiS->tvyscale) { 12392 found = TRUE; 12393 break; 12394 } 12395 } 12396 if(found) break; 12397 if(pSiS->tvyscale > 0) pSiS->tvyscale--; 12398 else pSiS->tvyscale++; 12399 } 12400 } 12401 12402#ifdef SISDUALHEAD 12403 if(pSiSEnt) pSiSEnt->tvyscale = pSiS->tvyscale; 12404#endif 12405 12406 if(pSiS->tvyscale == 0) { 12407 UChar p2_0a = pSiS->p2_0a; 12408 UChar p2_2f = pSiS->p2_2f; 12409 UChar p2_30 = pSiS->p2_30; 12410 UChar p2_46 = pSiS->p2_46; 12411 UChar p2_47 = pSiS->p2_47; 12412 UChar p1scaling[9], p4scaling[9]; 12413 UChar *p2scaling; 12414 12415 for(i = 0; i < 9; i++) { 12416 p1scaling[i] = pSiS->scalingp1[i]; 12417 p4scaling[i] = pSiS->scalingp4[i]; 12418 } 12419 p2scaling = &pSiS->scalingp2[0]; 12420 12421#ifdef SISDUALHEAD 12422 if(pSiSEnt && pSiS->DualHeadMode) { 12423 p2_0a = pSiSEnt->p2_0a; 12424 p2_2f = pSiSEnt->p2_2f; 12425 p2_30 = pSiSEnt->p2_30; 12426 p2_46 = pSiSEnt->p2_46; 12427 p2_47 = pSiSEnt->p2_47; 12428 for(i = 0; i < 9; i++) { 12429 p1scaling[i] = pSiSEnt->scalingp1[i]; 12430 p4scaling[i] = pSiSEnt->scalingp4[i]; 12431 } 12432 p2scaling = &pSiSEnt->scalingp2[0]; 12433 } 12434#endif 12435 SISWaitRetraceCRT2(pScrn); 12436 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 12437 for(i = 0; i < 64; i++) { 12438 outSISIDXREG(SISPART2,(0xc0 + i),p2scaling[i]); 12439 } 12440 } 12441 for(i = 0; i < 9; i++) { 12442 outSISIDXREG(SISPART1,SiSScalingP1Regs[i],p1scaling[i]); 12443 } 12444 for(i = 0; i < 9; i++) { 12445 outSISIDXREG(SISPART4,SiSScalingP4Regs[i],p4scaling[i]); 12446 } 12447 12448 setSISIDXREG(SISPART2,0x0a,0x7f,(p2_0a & 0x80)); 12449 outSISIDXREG(SISPART2,0x2f,p2_2f); 12450 setSISIDXREG(SISPART2,0x30,0x3f,(p2_30 & 0xc0)); 12451 if(!(pSiS->VBFlags2 & VB2_301)) { 12452 setSISIDXREG(SISPART2,0x46,0x9f,(p2_46 & 0x60)); 12453 outSISIDXREG(SISPART2,0x47,p2_47); 12454 } 12455 12456 } else { 12457 12458 int realvde, myypos, watchdog = 32; 12459 unsigned short temp1, temp2, vgahde, vgaht, vgavt; 12460 int p1div = 1; 12461 ULong calctemp; 12462 12463 srindex += i; 12464 newvde = SiSTVVScale[srindex].ScaleVDE; 12465 realvde = SiSTVVScale[srindex].RealVDE; 12466 12467 if(vdediv == 1) p1div = 2; 12468 12469 if(!skipmoveup) { 12470 do { 12471 inSISIDXREG(SISPART2,0x01,temp); 12472 temp = vlimit - ((temp & 0x7f) / p1div); 12473 if((temp - (((newvde / vdediv) - 2) + 9)) > 0) break; 12474 myypos = pSiS->tvypos - 1; 12475#ifdef SISDUALHEAD 12476 if(pSiSEnt && pSiS->DualHeadMode) myypos = pSiSEnt->tvypos - 1; 12477#endif 12478 SiS_SetTVyposoffset(pScrn, myypos); 12479 } while(watchdog--); 12480 } 12481 12482 SISWaitRetraceCRT2(pScrn); 12483 12484 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 12485 SiS_CalcXTapScaler(pSiS->SiS_Pr, realvde, newvde, 4, FALSE); 12486 } 12487 12488 if(!(pSiS->VBFlags2 & VB2_301)) { 12489 temp = (newvde / vdediv) - 3; 12490 setSISIDXREG(SISPART2,0x46,0x9f,((temp & 0x0300) >> 3)); 12491 outSISIDXREG(SISPART2,0x47,(temp & 0xff)); 12492 } 12493 12494 inSISIDXREG(SISPART1,0x0a,temp1); 12495 inSISIDXREG(SISPART1,0x0c,temp2); 12496 vgahde = ((temp2 & 0xf0) << 4) | temp1; 12497 if(pSiS->VGAEngine == SIS_300_VGA) { 12498 vgahde -= 12; 12499 } else { 12500 vgahde -= 16; 12501 if(hdclk) vgahde <<= 1; 12502 } 12503 12504 vgaht = SiSTVVScale[srindex].reg[0]; 12505 temp1 = vgaht; 12506 if((pSiS->VGAEngine == SIS_315_VGA) && hdclk) temp1 >>= 1; 12507 temp1--; 12508 outSISIDXREG(SISPART1,0x08,(temp1 & 0xff)); 12509 setSISIDXREG(SISPART1,0x09,0x0f,((temp1 >> 4) & 0xf0)); 12510 12511 temp2 = (vgaht - vgahde) >> 2; 12512 if(pSiS->VGAEngine == SIS_300_VGA) { 12513 temp1 = vgahde + 12 + temp2; 12514 temp2 = temp1 + (temp2 << 1); 12515 } else { 12516 temp1 = vgahde; 12517 if(hdclk) { 12518 temp1 >>= 1; 12519 temp2 >>= 1; 12520 } 12521 temp2 >>= 1; 12522 temp1 = temp1 + 16 + temp2; 12523 temp2 = temp1 + temp2; 12524 } 12525 outSISIDXREG(SISPART1,0x0b,(temp1 & 0xff)); 12526 setSISIDXREG(SISPART1,0x0c,0xf0,((temp1 >> 8) & 0x0f)); 12527 outSISIDXREG(SISPART1,0x0d,(temp2 & 0xff)); 12528 12529 vgavt = SiSTVVScale[srindex].reg[1]; 12530 temp1 = vgavt - 1; 12531 if(pSiS->VGAEngine == SIS_315_VGA) temp1--; 12532 outSISIDXREG(SISPART1,0x0e,(temp1 & 0xff)); 12533 setSISIDXREG(SISPART1,0x12,0xf8,((temp1 >> 8 ) & 0x07)); 12534 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->ChipType >= SIS_661)) { 12535 temp1 = (vgavt + SiSTVVScale[srindex].RealVDE) >> 1; 12536 temp2 = ((vgavt - SiSTVVScale[srindex].RealVDE) >> 4) + temp1 + 1; 12537 } else { 12538 temp1 = (vgavt - SiSTVVScale[srindex].RealVDE) >> 2; 12539 temp2 = (temp1 < 4) ? 4 : temp1; 12540 temp1 += SiSTVVScale[srindex].RealVDE; 12541 temp2 = (temp2 >> 2) + temp1 + 1; 12542 } 12543 outSISIDXREG(SISPART1,0x10,(temp1 & 0xff)); 12544 setSISIDXREG(SISPART1,0x11,0x8f,((temp1 >> 4) & 0x70)); 12545 setSISIDXREG(SISPART1,0x11,0xf0,(temp2 & 0x0f)); 12546 12547 setSISIDXREG(SISPART2,0x0a,0x7f,((SiSTVVScale[srindex].reg[2] >> 8) & 0x80)); 12548 outSISIDXREG(SISPART2,0x2f,((newvde / vdediv) - 2)); 12549 setSISIDXREG(SISPART2,0x30,0x3f,((((newvde / vdediv) - 2) >> 2) & 0xc0)); 12550 12551 outSISIDXREG(SISPART4,0x13,(SiSTVVScale[srindex].reg[2] & 0xff)); 12552 outSISIDXREG(SISPART4,0x14,(SiSTVVScale[srindex].reg[3] & 0xff)); 12553 setSISIDXREG(SISPART4,0x15,0x7f,((SiSTVVScale[srindex].reg[3] >> 1) & 0x80)); 12554 12555 temp1 = vgaht - 1; 12556 outSISIDXREG(SISPART4,0x16,(temp1 & 0xff)); 12557 setSISIDXREG(SISPART4,0x15,0x87,((temp1 >> 5) & 0x78)); 12558 12559 temp1 = vgavt - 1; 12560 outSISIDXREG(SISPART4,0x17,(temp1 & 0xff)); 12561 setSISIDXREG(SISPART4,0x15,0xf8,((temp1 >> 8) & 0x07)); 12562 12563 outSISIDXREG(SISPART4,0x18,0x00); 12564 setSISIDXREG(SISPART4,0x19,0xf0,0x00); 12565 12566 inSISIDXREG(SISPART4,0x0e,temp1); 12567 if(is1080i) { 12568 if(!(temp1 & 0xe0)) newvde >>= 1; 12569 } 12570 12571 temp = 0x40; 12572 if(realvde <= newvde) temp = 0; 12573 else realvde -= newvde; 12574 12575 calctemp = (realvde * 256 * 1024) / newvde; 12576 if((realvde * 256 * 1024) % newvde) calctemp++; 12577 outSISIDXREG(SISPART4,0x1b,(calctemp & 0xff)); 12578 outSISIDXREG(SISPART4,0x1a,((calctemp >> 8) & 0xff)); 12579 setSISIDXREG(SISPART4,0x19,0x8f,(((calctemp >> 12) & 0x70) | temp)); 12580 } 12581 12582 } 12583 12584 } 12585} 12586 12587int SiS_GetTVyscale(ScrnInfoPtr pScrn) 12588{ 12589 SISPtr pSiS = SISPTR(pScrn); 12590#ifdef SISDUALHEAD 12591 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12592 12593 if(pSiSEnt && pSiS->DualHeadMode) 12594 return (int)pSiSEnt->tvyscale; 12595 else 12596#endif 12597 return (int)pSiS->tvyscale; 12598} 12599 12600void SiS_SetSISCRT1SaturationGain(ScrnInfoPtr pScrn, int val) 12601{ 12602 SISPtr pSiS = SISPTR(pScrn); 12603#ifdef SISDUALHEAD 12604 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12605#endif 12606 12607 pSiS->siscrt1satgain = val; 12608#ifdef SISDUALHEAD 12609 if(pSiSEnt) pSiSEnt->siscrt1satgain = val; 12610#endif 12611 12612 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_CRT1SATGAIN)) return; 12613 12614#ifdef UNLOCK_ALWAYS 12615 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12616#endif 12617 12618 if((val >= 0) && (val <= 7)) { 12619 setSISIDXREG(SISCR,0x53,0xE3, (val << 2)); 12620 } 12621} 12622 12623int SiS_GetSISCRT1SaturationGain(ScrnInfoPtr pScrn) 12624{ 12625 SISPtr pSiS = SISPTR(pScrn); 12626 int result = pSiS->siscrt1satgain; 12627 UChar temp; 12628#ifdef SISDUALHEAD 12629 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12630 12631 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->siscrt1satgain; 12632#endif 12633 12634 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_CRT1SATGAIN)) return result; 12635 12636#ifdef UNLOCK_ALWAYS 12637 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12638#endif 12639 inSISIDXREG(SISCR, 0x53, temp); 12640 return (int)((temp >> 2) & 0x07); 12641} 12642 12643/* Calc dotclock from registers */ 12644static int 12645SiSGetClockFromRegs(UChar sr2b, UChar sr2c) 12646{ 12647 float num, denum, postscalar, divider; 12648 int myclock; 12649 12650 divider = (sr2b & 0x80) ? 2.0 : 1.0; 12651 postscalar = (sr2c & 0x80) ? 12652 ( (((sr2c >> 5) & 0x03) == 0x02) ? 6.0 : 8.0 ) : 12653 ( ((sr2c >> 5) & 0x03) + 1.0 ); 12654 num = (sr2b & 0x7f) + 1.0; 12655 denum = (sr2c & 0x1f) + 1.0; 12656 myclock = (int)((14318 * (divider / postscalar) * (num / denum)) / 1000); 12657 return myclock; 12658} 12659 12660#ifdef SISDUALHEAD 12661static void 12662SiS_SetDHFlags(SISPtr pSiS, unsigned int misc, unsigned int sd2) 12663{ 12664 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12665 12666 if(pSiS->DualHeadMode) { 12667 if(pSiSEnt->pScrn_1) { 12668 SISPTR(pSiSEnt->pScrn_1)->MiscFlags |= misc; 12669 SISPTR(pSiSEnt->pScrn_1)->SiS_SD2_Flags |= sd2; 12670 } 12671 if(pSiSEnt->pScrn_2) { 12672 SISPTR(pSiSEnt->pScrn_2)->MiscFlags |= misc; 12673 SISPTR(pSiSEnt->pScrn_2)->SiS_SD2_Flags |= sd2; 12674 } 12675 } 12676} 12677#endif 12678 12679/* PostSetMode: 12680 * -) Disable CRT1 for saving bandwidth. This doesn't work with VESA; 12681 * VESA uses the bridge in SlaveMode and switching CRT1 off while 12682 * the bridge is in SlaveMode not that clever... 12683 * -) Check if overlay can be used (depending on dotclock) 12684 * -) Check if Panel Scaler is active on LVDS for overlay re-scaling 12685 * -) Save TV registers for further processing 12686 * -) Apply TV settings 12687 */ 12688static void 12689SiSPostSetMode(ScrnInfoPtr pScrn, SISRegPtr sisReg) 12690{ 12691 SISPtr pSiS = SISPTR(pScrn); 12692#ifdef SISDUALHEAD 12693 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12694#endif 12695 UChar usScratchCR17, sr2b, sr2c, tmpreg; 12696 int myclock1, myclock2, mycoldepth1, mycoldepth2, temp; 12697 Bool flag = FALSE; 12698 Bool doit = TRUE; 12699 Bool IsInSlaveMode; 12700 12701#ifdef TWDEBUG 12702 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 12703 "CRT1off is %d\n", pSiS->CRT1off); 12704#endif 12705 pSiS->CRT1isoff = pSiS->CRT1off; 12706 12707#ifdef UNLOCK_ALWAYS 12708 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12709#endif 12710 12711 SiSFixupSR11(pScrn); 12712 12713 IsInSlaveMode = SiSBridgeIsInSlaveMode(pScrn); 12714 12715 if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE)) { 12716 12717 if(pSiS->VBFlags != pSiS->VBFlags_backup) { 12718 pSiS->VBFlags = pSiS->VBFlags_backup; 12719 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 12720 "VBFlags restored to %0x\n", pSiS->VBFlags); 12721 } 12722 12723 /* -) We can't switch off CRT1 if bridge is in SlaveMode. 12724 * -) If we change to a SlaveMode-Mode (like 512x384), we 12725 * need to adapt VBFlags for eg. Xv. 12726 */ 12727#ifdef SISDUALHEAD 12728 if(!pSiS->DualHeadMode) { 12729#endif 12730 if(IsInSlaveMode) { 12731 doit = FALSE; 12732 temp = pSiS->VBFlags; 12733 pSiS->VBFlags &= (~VB_DISPMODE_SINGLE); 12734 pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_DISP1); 12735 if(temp != pSiS->VBFlags) { 12736 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 12737 "VBFlags changed to 0x%0x\n", pSiS->VBFlags); 12738 } 12739 } 12740#ifdef SISDUALHEAD 12741 } 12742#endif 12743 12744 if(pSiS->VGAEngine == SIS_315_VGA) { 12745 12746 if((pSiS->CRT1off) && (doit)) { 12747 orSISIDXREG(SISCR,pSiS->myCR63,0x40); 12748 orSISIDXREG(SISSR,0x1f,0xc0); 12749 andSISIDXREG(SISSR,0x07,~0x10); 12750 andSISIDXREG(SISSR,0x06,0xe2); 12751 andSISIDXREG(SISSR,0x31,0xcf); 12752 outSISIDXREG(SISSR,0x2b,0x1b); 12753 outSISIDXREG(SISSR,0x2c,0xe1); 12754 outSISIDXREG(SISSR,0x2d,0x01); 12755 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 12756 usleep(10000); 12757 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 12758 } else { 12759 andSISIDXREG(SISCR,pSiS->myCR63,0xBF); 12760 andSISIDXREG(SISSR,0x1f,0x3f); 12761 orSISIDXREG(SISSR,0x07,0x10); 12762 } 12763 12764 } else { 12765 12766 if(doit) { 12767 inSISIDXREG(SISCR, 0x17, usScratchCR17); 12768 if(pSiS->CRT1off) { 12769 if(usScratchCR17 & 0x80) { 12770 flag = TRUE; 12771 usScratchCR17 &= ~0x80; 12772 } 12773 orSISIDXREG(SISSR,0x1f,0xc0); 12774 } else { 12775 if(!(usScratchCR17 & 0x80)) { 12776 flag = TRUE; 12777 usScratchCR17 |= 0x80; 12778 } 12779 andSISIDXREG(SISSR,0x1f,0x3f); 12780 } 12781 /* Reset only if status changed */ 12782 if(flag) { 12783 outSISIDXREG(SISCR, 0x17, usScratchCR17); 12784 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 12785 usleep(10000); 12786 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 12787 } 12788 } 12789 } 12790 12791 } 12792 12793 /* Set bridge to "disable CRT2" mode if CRT2 is disabled, LCD-A is enabled */ 12794 /* (Not needed for CRT1=VGA since CRT2 will really be disabled then) */ 12795#ifdef SISDUALHEAD 12796 if(!pSiS->DualHeadMode) { 12797#endif 12798 if((pSiS->VGAEngine == SIS_315_VGA) && (pSiS->VBFlags2 & VB2_SISLCDABRIDGE)) { 12799 if((!pSiS->UseVESA) && (!(pSiS->VBFlags & CRT2_ENABLE)) && (pSiS->VBFlags & CRT1_LCDA)) { 12800 if(!IsInSlaveMode) { 12801 andSISIDXREG(SISPART4,0x0d,~0x07); 12802 } 12803 } 12804 } 12805#ifdef SISDUALHEAD 12806 } 12807#endif 12808 12809 /* Reset flags */ 12810 pSiS->MiscFlags &= ~( MISC_CRT1OVERLAY | 12811 MISC_CRT2OVERLAY | 12812 MISC_CRT1OVERLAYGAMMA | 12813 MISC_SIS760ONEOVERLAY | 12814 MISC_PANELLINKSCALER | 12815 MISC_STNMODE | 12816 MISC_TVNTSC1024); 12817 12818 pSiS->SiS_SD2_Flags &= ~SiS_SD2_SIS760ONEOVL; 12819 12820#ifdef SISDUALHEAD 12821 if(pSiS->DualHeadMode) { 12822 if(pSiSEnt->pScrn_1) { 12823 SISPTR(pSiSEnt->pScrn_1)->MiscFlags &= ~(MISC_SIS760ONEOVERLAY | 12824 MISC_CRT1OVERLAY | 12825 MISC_CRT2OVERLAY | 12826 MISC_CRT1OVERLAYGAMMA | 12827 MISC_PANELLINKSCALER | 12828 MISC_STNMODE | 12829 MISC_TVNTSC1024); 12830 SISPTR(pSiSEnt->pScrn_1)->SiS_SD2_Flags &= ~SiS_SD2_SIS760ONEOVL; 12831 } 12832 if(pSiSEnt->pScrn_2) { 12833 SISPTR(pSiSEnt->pScrn_2)->MiscFlags &= ~(MISC_SIS760ONEOVERLAY | 12834 MISC_CRT1OVERLAY | 12835 MISC_CRT2OVERLAY | 12836 MISC_CRT1OVERLAYGAMMA | 12837 MISC_PANELLINKSCALER | 12838 MISC_STNMODE | 12839 MISC_TVNTSC1024); 12840 SISPTR(pSiSEnt->pScrn_2)->SiS_SD2_Flags &= ~SiS_SD2_SIS760ONEOVL; 12841 } 12842 } 12843#endif 12844 12845 /* Determine if the video overlay can be used */ 12846 if(!pSiS->NoXvideo) { 12847 12848 int clklimit1=0, clklimit2=0, clklimitg=0; 12849 Bool OverlayHandled = FALSE; 12850 12851 inSISIDXREG(SISSR,0x2b,sr2b); 12852 inSISIDXREG(SISSR,0x2c,sr2c); 12853 myclock1 = myclock2 = SiSGetClockFromRegs(sr2b, sr2c); 12854 inSISIDXREG(SISSR,0x06,tmpreg); 12855 switch((tmpreg & 0x1c) >> 2) { 12856 case 0: mycoldepth1 = 1; break; 12857 case 1: 12858 case 2: mycoldepth1 = 2; break; 12859 default: mycoldepth1 = 4; 12860 } 12861 mycoldepth2 = mycoldepth1; 12862 12863 if((!IsInSlaveMode) && (pSiS->VBFlags & CRT2_ENABLE)) { 12864 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 12865 inSISIDXREG(SISPART4,0x0a,sr2b); 12866 inSISIDXREG(SISPART4,0x0b,sr2c); 12867 } else { 12868 inSISIDXREG(SISSR,0x2e,sr2b); 12869 inSISIDXREG(SISSR,0x2f,sr2c); 12870 } 12871 myclock2 = SiSGetClockFromRegs(sr2b, sr2c); 12872 inSISIDXREG(SISPART1,0x00,tmpreg); 12873 tmpreg &= 0x0f; 12874 switch(tmpreg) { 12875 case 8: mycoldepth2 = 1; break; 12876 case 4: 12877 case 2: mycoldepth2 = 2; break; 12878 default: mycoldepth2 = 4; 12879 } 12880 } 12881 12882 switch(pSiS->ChipType) { 12883 12884 case SIS_300: 12885 case SIS_540: 12886 case SIS_630: 12887 case SIS_730: 12888 clklimit1 = clklimit2 = clklimitg = 150; 12889 break; 12890 12891 case SIS_550: 12892 case SIS_650: 12893 case SIS_740: 12894 clklimit1 = clklimit2 = 175; /* verified for 65x */ 12895 clklimitg = 166; /* ? */ 12896 break; 12897 12898 case SIS_661: 12899 case SIS_741: 12900 clklimit1 = clklimit2 = 190; /* ? */ 12901 clklimitg = 180; /* ? */ 12902 break; 12903 12904 case SIS_760: 12905 case SIS_761: 12906 clklimit1 = clklimit2 = 190; /* ? */ 12907 if(pSiS->ChipFlags & SiSCF_760LFB) { /* LFB only or hybrid */ 12908 clklimit1 = clklimit2 = 220; /* ? */ 12909 } 12910 clklimitg = 200; /* ? */ 12911 12912 if(pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORT760OO) { /* UMA only */ 12913 12914 Bool OnlyOne = FALSE, NoOverlay = FALSE; 12915 int dotclocksum = 0; 12916 12917 if(pSiS->VBFlags & DISPTYPE_CRT1) dotclocksum += myclock1; 12918 if((!IsInSlaveMode) && (pSiS->VBFlags & CRT2_ENABLE)) dotclocksum += myclock2; 12919 12920 /* TODO: Find out under what circumstances only one 12921 * overlay is usable in UMA-only mode. 12922 * This is not entirely accurate; the overlay 12923 * scaler also requires some time, so even though 12924 * the dotclocks are below these values, some 12925 * distortions in the overlay may occure. 12926 * Solution: Don't use a 760 with shared memory. 12927 */ 12928 if( (pSiS->VBFlags & DISPTYPE_CRT1) && 12929 (pSiS->VBFlags & CRT2_ENABLE) && 12930 (mycoldepth1 != mycoldepth2) ) { 12931 12932 /* 0. If coldepths are different (only possible in dual head mode), 12933 * I have no idea to calculate the limits; hence, allow only one 12934 * overlay in all cases. 12935 */ 12936 OnlyOne = TRUE; 12937 12938 } else if(pSiS->MemClock < 150000) { 12939 12940 /* 1. MCLK <150: If someone seriously considers using such 12941 * slow RAM, so be it. Only one overlay in call cases. 12942 */ 12943 OnlyOne = TRUE; 12944 12945 } else if(pSiS->MemClock < 170000) { 12946 12947 /* 2. MCLK 166 */ 12948 switch(pSiS->CurrentLayout.bitsPerPixel) { 12949 case 32: if(dotclocksum > 133) OnlyOne = TRUE; /* One overlay; verified */ 12950 if(dotclocksum > 180) NoOverlay = TRUE; /* No overlay; verified */ 12951 break; 12952 case 16: if(dotclocksum > 175) OnlyOne = TRUE; /* One overlay; verified */ 12953 if(dotclocksum > 260) NoOverlay = TRUE;; /* No overlay; FIXME */ 12954 break; 12955 } 12956 12957 } else if(pSiS->MemClock < 210000) { 12958 12959 /* 3. MCLK 200 */ 12960 switch(pSiS->CurrentLayout.bitsPerPixel) { 12961 case 32: if(dotclocksum > 160) OnlyOne = TRUE; /* One overlay; FIXME */ 12962 if(dotclocksum > 216) NoOverlay = TRUE;; /* No overlay; FIXME */ 12963 break; 12964 case 16: if(dotclocksum > 210) OnlyOne = TRUE; /* One overlay; FIXME */ 12965 if(dotclocksum > 312) NoOverlay = TRUE;; /* No overlay; FIXME */ 12966 break; 12967 } 12968 12969 } 12970 12971 if(OnlyOne || NoOverlay) { 12972 12973 ULong tmpflags = 0; 12974 12975 if(!NoOverlay) { 12976 if(myclock1 <= clklimit1) tmpflags |= MISC_CRT1OVERLAY; 12977 if(myclock2 <= clklimit2) tmpflags |= MISC_CRT2OVERLAY; 12978 if(myclock1 <= clklimitg) tmpflags |= MISC_CRT1OVERLAYGAMMA; 12979 pSiS->MiscFlags |= tmpflags; 12980 } 12981 pSiS->MiscFlags |= MISC_SIS760ONEOVERLAY; 12982 pSiS->SiS_SD2_Flags |= SiS_SD2_SIS760ONEOVL; 12983#ifdef SISDUALHEAD 12984 SiS_SetDHFlags(pSiS, (tmpflags | MISC_SIS760ONEOVERLAY), SiS_SD2_SIS760ONEOVL); 12985#endif 12986 OverlayHandled = TRUE; 12987 } 12988 12989 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 12990 "SiS76x/UMA: %s video overlay(s) available in current mode\n", 12991 NoOverlay ? "no" : ((pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) ? "one" : "two")); 12992 12993#ifdef TWDEBUG 12994 xf86DrvMsg(0, 0, "SiS760: Memclock %d, c1 %d/%d c2 %d/%d, sum %d / %x\n", 12995 pSiS->MemClock, myclock1, mycoldepth1, 12996 myclock2, mycoldepth2, dotclocksum, pSiS->SiS_SD2_Flags); 12997#endif 12998 } 12999 break; 13000 13001 case SIS_660: 13002 clklimit1 = clklimit2 = 200; /* ? */ 13003 if(pSiS->ChipFlags & SiSCF_760LFB) { /* LFB only */ 13004 clklimit1 = clklimit2 = 220; 13005 } 13006 clklimitg = 200; /* ? */ 13007 break; 13008 13009 case SIS_315H: 13010 case SIS_315: 13011 case SIS_315PRO: 13012 case SIS_330: 13013 clklimit1 = clklimit2 = 180; /* ? */ 13014 clklimitg = 166; /* ? */ 13015 break; 13016 13017 case SIS_340: /* ? */ 13018 case XGI_20: 13019 case XGI_40: 13020 clklimit1 = clklimit2 = 240; /* ? */ 13021 clklimitg = 200; /* ? */ 13022 break; 13023 } 13024 13025 if(!OverlayHandled) { 13026 ULong tmpflags = 0; 13027 if(myclock1 <= clklimit1) tmpflags |= MISC_CRT1OVERLAY; 13028 if(myclock2 <= clklimit2) tmpflags |= MISC_CRT2OVERLAY; 13029 if(myclock1 <= clklimitg) tmpflags |= MISC_CRT1OVERLAYGAMMA; 13030 pSiS->MiscFlags |= tmpflags; 13031#ifdef SISDUALHEAD 13032 SiS_SetDHFlags(pSiS, tmpflags, 0); 13033#endif 13034 if(!(pSiS->MiscFlags & MISC_CRT1OVERLAY)) { 13035#ifdef SISDUALHEAD 13036 if((!pSiS->DualHeadMode) || (pSiS->SecondHead)) 13037#endif 13038 xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, 3, 13039 "Current dotclock (%dMhz) too high for video overlay on CRT1\n", 13040 myclock1); 13041 } 13042 if((pSiS->VBFlags & CRT2_ENABLE) && (!(pSiS->MiscFlags & MISC_CRT2OVERLAY))) { 13043#ifdef SISDUALHEAD 13044 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) 13045#endif 13046 xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, 3, 13047 "Current dotclock (%dMhz) too high for video overlay on CRT2\n", 13048 myclock2); 13049 } 13050 } 13051 13052 } 13053 13054 /* Determine if the Panel Link scaler is active */ 13055 13056 if(pSiS->VBFlags & (CRT2_LCD | CRT1_LCDA)) { 13057 ULong tmpflags = 0; 13058 if(pSiS->VGAEngine == SIS_300_VGA) { 13059 if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) { 13060 inSISIDXREG(SISPART1,0x1e,tmpreg); 13061 tmpreg &= 0x3f; 13062 if(tmpreg) tmpflags |= MISC_PANELLINKSCALER; 13063 } 13064 } else { 13065 if((pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) || (pSiS->VBFlags & CRT1_LCDA)) { 13066 inSISIDXREG(SISPART1,0x35,tmpreg); 13067 tmpreg &= 0x04; 13068 if(!tmpreg) tmpflags |= MISC_PANELLINKSCALER; 13069 } 13070 } 13071 pSiS->MiscFlags |= tmpflags; 13072#ifdef SISDUALHEAD 13073 SiS_SetDHFlags(pSiS, tmpflags, 0); 13074#endif 13075 } 13076 13077 /* Determine if STN is active */ 13078 if(pSiS->ChipType == SIS_550) { 13079 if((pSiS->VBFlags & CRT2_LCD) && (pSiS->FSTN || pSiS->DSTN)) { 13080 inSISIDXREG(SISCR,0x34,tmpreg); 13081 tmpreg &= 0x7f; 13082 if(tmpreg == 0x5a || tmpreg == 0x5b) { 13083 pSiS->MiscFlags |= MISC_STNMODE; 13084#ifdef SISDUALHEAD 13085 SiS_SetDHFlags(pSiS, MISC_STNMODE, 0); 13086#endif 13087 } 13088 } 13089 } 13090 13091 /* Determine if our very special TV mode is active */ 13092 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && (pSiS->VBFlags & CRT2_TV) && (!(pSiS->VBFlags & TV_HIVISION))) { 13093 if( ((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR525I)) || 13094 ((!(pSiS->VBFlags & TV_YPBPR)) && (pSiS->VBFlags & (TV_NTSC | TV_PALM))) ) { 13095 inSISIDXREG(SISCR,0x34,tmpreg); 13096 tmpreg &= 0x7f; 13097 if((tmpreg == 0x64) || (tmpreg == 0x4a) || (tmpreg == 0x38)) { 13098 pSiS->MiscFlags |= MISC_TVNTSC1024; 13099#ifdef SISDUALHEAD 13100 SiS_SetDHFlags(pSiS, MISC_TVNTSC1024, 0); 13101#endif 13102 } 13103 } 13104 } 13105 13106 if(pSiS->VGAEngine == SIS_315_VGA) { 13107 int i; 13108#ifdef SISVRAMQ 13109 /* Re-Enable and reset command queue */ 13110 SiSEnableTurboQueue(pScrn); 13111#endif 13112 /* Get HWCursor register contents for backup */ 13113 for(i = 0; i < 16; i++) { 13114 pSiS->HWCursorBackup[i] = SIS_MMIO_IN32(pSiS->IOBase, 0x8500 + (i << 2)); 13115 } 13116 if(pSiS->ChipType >= SIS_330) { 13117 /* Enable HWCursor protection (Y pos as trigger) */ 13118 andSISIDXREG(SISCR, 0x5b, ~0x30); 13119 } 13120 } 13121 13122 /* Re-initialize accelerator engine */ 13123 /* (We are sync'ed here) */ 13124 if(!pSiS->NoAccel) { 13125 if(pSiS->InitAccel) { 13126 (pSiS->InitAccel)(pScrn); 13127 } 13128 } 13129 13130 /* Set display device gamma (for SISCTRL) */ 13131 if(pSiS->VBFlags & CRT1_LCDA) 13132 pSiS->CRT1MonGamma = pSiS->CRT2LCDMonitorGamma; 13133 else 13134 pSiS->CRT1MonGamma = pSiS->CRT1VGAMonitorGamma; 13135 13136 if(pSiS->VBFlags & CRT2_LCD) 13137 pSiS->CRT2MonGamma = pSiS->CRT2LCDMonitorGamma; 13138 else if(pSiS->VBFlags & CRT2_TV) { 13139 if(pSiS->VBFlags & TV_YPBPR) 13140 pSiS->CRT2MonGamma = 2200; /* */ 13141 else if(pSiS->VBFlags & TV_HIVISION) 13142 pSiS->CRT2MonGamma = 2200; /* ? */ 13143 else if(pSiS->VBFlags & TV_NTSC) 13144 pSiS->CRT2MonGamma = 2200; /* NTSC */ 13145 else 13146 pSiS->CRT2MonGamma = 2800; /* All PAL modes? */ 13147 } else if(pSiS->VBFlags & CRT2_VGA) 13148 pSiS->CRT2MonGamma = pSiS->CRT2VGAMonitorGamma; 13149 else 13150 pSiS->CRT2MonGamma = 0; /* Unknown */ 13151 13152 /* Reset XV display properties (such as number of overlays, etc) */ 13153 /* (And copy monitor gamma) */ 13154#ifdef SISDUALHEAD 13155 if(pSiS->DualHeadMode) { 13156 if(pSiSEnt->pScrn_1) { 13157 if(SISPTR(pSiSEnt->pScrn_1)->ResetXvDisplay) { 13158 (SISPTR(pSiSEnt->pScrn_1)->ResetXvDisplay)(pSiSEnt->pScrn_1); 13159 } 13160 SISPTR(pSiSEnt->pScrn_1)->CRT1MonGamma = pSiS->CRT1MonGamma; 13161 SISPTR(pSiSEnt->pScrn_1)->CRT2MonGamma = pSiS->CRT2MonGamma; 13162 } 13163 if(pSiSEnt->pScrn_2) { 13164 if(SISPTR(pSiSEnt->pScrn_2)->ResetXvDisplay) { 13165 (SISPTR(pSiSEnt->pScrn_1)->ResetXvDisplay)(pSiSEnt->pScrn_2); 13166 } 13167 SISPTR(pSiSEnt->pScrn_2)->CRT1MonGamma = pSiS->CRT1MonGamma; 13168 SISPTR(pSiSEnt->pScrn_2)->CRT2MonGamma = pSiS->CRT2MonGamma; 13169 } 13170 } else { 13171#endif 13172 if(pSiS->ResetXvDisplay) { 13173 (pSiS->ResetXvDisplay)(pScrn); 13174 } 13175#ifdef SISDUALHEAD 13176 } 13177#endif 13178 13179 /* Reset XV gamma correction */ 13180 if(pSiS->ResetXvGamma) { 13181 (pSiS->ResetXvGamma)(pScrn); 13182 } 13183 13184 /* Reset various display parameters */ 13185 { 13186 int val = pSiS->siscrt1satgain; 13187#ifdef SISDUALHEAD 13188 if(pSiS->DualHeadMode && pSiSEnt) val = pSiSEnt->siscrt1satgain; 13189#endif 13190 SiS_SetSISCRT1SaturationGain(pScrn, val); 13191 } 13192 13193 /* Apply TV settings given by options 13194 Do this even in DualHeadMode: 13195 - if this is called by SetModeCRT1, CRT2 mode has been reset by SetModeCRT1 13196 - if this is called by SetModeCRT2, CRT2 mode has changed (duh!) 13197 -> Hence, in both cases, the settings must be re-applied. 13198 */ 13199 13200 if(pSiS->VBFlags & CRT2_TV) { 13201 int val; 13202 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 13203 int mychtvlumabandwidthcvbs = pSiS->chtvlumabandwidthcvbs; 13204 int mychtvlumabandwidthsvideo = pSiS->chtvlumabandwidthsvideo; 13205 int mychtvlumaflickerfilter = pSiS->chtvlumaflickerfilter; 13206 int mychtvchromabandwidth = pSiS->chtvchromabandwidth; 13207 int mychtvchromaflickerfilter = pSiS->chtvchromaflickerfilter; 13208 int mychtvcvbscolor = pSiS->chtvcvbscolor; 13209 int mychtvtextenhance = pSiS->chtvtextenhance; 13210 int mychtvcontrast = pSiS->chtvcontrast; 13211 int mytvxpos = pSiS->tvxpos; 13212 int mytvypos = pSiS->tvypos; 13213#ifdef SISDUALHEAD 13214 if(pSiSEnt && pSiS->DualHeadMode) { 13215 mychtvlumabandwidthcvbs = pSiSEnt->chtvlumabandwidthcvbs; 13216 mychtvlumabandwidthsvideo = pSiSEnt->chtvlumabandwidthsvideo; 13217 mychtvlumaflickerfilter = pSiSEnt->chtvlumaflickerfilter; 13218 mychtvchromabandwidth = pSiSEnt->chtvchromabandwidth; 13219 mychtvchromaflickerfilter = pSiSEnt->chtvchromaflickerfilter; 13220 mychtvcvbscolor = pSiSEnt->chtvcvbscolor; 13221 mychtvtextenhance = pSiSEnt->chtvtextenhance; 13222 mychtvcontrast = pSiSEnt->chtvcontrast; 13223 mytvxpos = pSiSEnt->tvxpos; 13224 mytvypos = pSiSEnt->tvypos; 13225 } 13226#endif 13227 if((val = mychtvlumabandwidthcvbs) != -1) { 13228 SiS_SetCHTVlumabandwidthcvbs(pScrn, val); 13229 } 13230 if((val = mychtvlumabandwidthsvideo) != -1) { 13231 SiS_SetCHTVlumabandwidthsvideo(pScrn, val); 13232 } 13233 if((val = mychtvlumaflickerfilter) != -1) { 13234 SiS_SetCHTVlumaflickerfilter(pScrn, val); 13235 } 13236 if((val = mychtvchromabandwidth) != -1) { 13237 SiS_SetCHTVchromabandwidth(pScrn, val); 13238 } 13239 if((val = mychtvchromaflickerfilter) != -1) { 13240 SiS_SetCHTVchromaflickerfilter(pScrn, val); 13241 } 13242 if((val = mychtvcvbscolor) != -1) { 13243 SiS_SetCHTVcvbscolor(pScrn, val); 13244 } 13245 if((val = mychtvtextenhance) != -1) { 13246 SiS_SetCHTVtextenhance(pScrn, val); 13247 } 13248 if((val = mychtvcontrast) != -1) { 13249 SiS_SetCHTVcontrast(pScrn, val); 13250 } 13251 /* Backup default TV position registers */ 13252 switch(pSiS->ChrontelType) { 13253 case CHRONTEL_700x: 13254 pSiS->tvx = SiS_GetCH700x(pSiS->SiS_Pr, 0x0a); 13255 pSiS->tvx |= (((SiS_GetCH700x(pSiS->SiS_Pr, 0x08) & 0x02) >> 1) << 8); 13256 pSiS->tvy = SiS_GetCH700x(pSiS->SiS_Pr, 0x0b); 13257 pSiS->tvy |= ((SiS_GetCH700x(pSiS->SiS_Pr, 0x08) & 0x01) << 8); 13258#ifdef SISDUALHEAD 13259 if(pSiSEnt) { 13260 pSiSEnt->tvx = pSiS->tvx; 13261 pSiSEnt->tvy = pSiS->tvy; 13262 } 13263#endif 13264 break; 13265 case CHRONTEL_701x: 13266 /* Not supported by hardware */ 13267 break; 13268 } 13269 if((val = mytvxpos) != 0) { 13270 SiS_SetTVxposoffset(pScrn, val); 13271 } 13272 if((val = mytvypos) != 0) { 13273 SiS_SetTVyposoffset(pScrn, val); 13274 } 13275 } 13276 if(pSiS->VBFlags2 & VB2_301) { 13277 int mysistvedgeenhance = pSiS->sistvedgeenhance; 13278#ifdef SISDUALHEAD 13279 if(pSiSEnt && pSiS->DualHeadMode) { 13280 mysistvedgeenhance = pSiSEnt->sistvedgeenhance; 13281 } 13282#endif 13283 if((val = mysistvedgeenhance) != -1) { 13284 SiS_SetSISTVedgeenhance(pScrn, val); 13285 } 13286 } 13287 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 13288 int mysistvantiflicker = pSiS->sistvantiflicker; 13289 int mysistvsaturation = pSiS->sistvsaturation; 13290 int mysistvcolcalibf = pSiS->sistvcolcalibf; 13291 int mysistvcolcalibc = pSiS->sistvcolcalibc; 13292 int mysistvcfilter = pSiS->sistvcfilter; 13293 int mysistvyfilter = pSiS->sistvyfilter; 13294 int mytvxpos = pSiS->tvxpos; 13295 int mytvypos = pSiS->tvypos; 13296 int mytvxscale = pSiS->tvxscale; 13297 int mytvyscale = pSiS->tvyscale; 13298 int i; 13299 ULong cbase; 13300 UChar ctemp; 13301#ifdef SISDUALHEAD 13302 if(pSiSEnt && pSiS->DualHeadMode) { 13303 mysistvantiflicker = pSiSEnt->sistvantiflicker; 13304 mysistvsaturation = pSiSEnt->sistvsaturation; 13305 mysistvcolcalibf = pSiSEnt->sistvcolcalibf; 13306 mysistvcolcalibc = pSiSEnt->sistvcolcalibc; 13307 mysistvcfilter = pSiSEnt->sistvcfilter; 13308 mysistvyfilter = pSiSEnt->sistvyfilter; 13309 mytvxpos = pSiSEnt->tvxpos; 13310 mytvypos = pSiSEnt->tvypos; 13311 mytvxscale = pSiSEnt->tvxscale; 13312 mytvyscale = pSiSEnt->tvyscale; 13313 } 13314#endif 13315 /* Backup default TV position, scale and colcalib registers */ 13316 inSISIDXREG(SISPART2,0x1f,pSiS->p2_1f); 13317 inSISIDXREG(SISPART2,0x20,pSiS->p2_20); 13318 inSISIDXREG(SISPART2,0x2b,pSiS->p2_2b); 13319 inSISIDXREG(SISPART2,0x42,pSiS->p2_42); 13320 inSISIDXREG(SISPART2,0x43,pSiS->p2_43); 13321 inSISIDXREG(SISPART2,0x01,pSiS->p2_01); 13322 inSISIDXREG(SISPART2,0x02,pSiS->p2_02); 13323 inSISIDXREG(SISPART2,0x44,pSiS->p2_44); 13324 inSISIDXREG(SISPART2,0x45,pSiS->p2_45); 13325 if(!(pSiS->VBFlags2 & VB2_301)) { 13326 inSISIDXREG(SISPART2,0x46,pSiS->p2_46); 13327 } else { 13328 pSiS->p2_46 = 0; 13329 } 13330 inSISIDXREG(SISPART2,0x0a,pSiS->p2_0a); 13331 inSISIDXREG(SISPART2,0x31,cbase); 13332 cbase = (cbase & 0x7f) << 8; 13333 inSISIDXREG(SISPART2,0x32,ctemp); 13334 cbase = (cbase | ctemp) << 8; 13335 inSISIDXREG(SISPART2,0x33,ctemp); 13336 cbase = (cbase | ctemp) << 8; 13337 inSISIDXREG(SISPART2,0x34,ctemp); 13338 pSiS->sistvccbase = (cbase | ctemp); 13339 inSISIDXREG(SISPART2,0x35,pSiS->p2_35); 13340 inSISIDXREG(SISPART2,0x36,pSiS->p2_36); 13341 inSISIDXREG(SISPART2,0x37,pSiS->p2_37); 13342 inSISIDXREG(SISPART2,0x38,pSiS->p2_38); 13343 if(!(pSiS->VBFlags2 & VB2_301)) { 13344 inSISIDXREG(SISPART2,0x47,pSiS->p2_47); 13345 inSISIDXREG(SISPART2,0x48,pSiS->p2_48); 13346 inSISIDXREG(SISPART2,0x49,pSiS->p2_49); 13347 inSISIDXREG(SISPART2,0x4a,pSiS->p2_4a); 13348 } 13349 inSISIDXREG(SISPART2,0x2f,pSiS->p2_2f); 13350 inSISIDXREG(SISPART2,0x30,pSiS->p2_30); 13351 for(i=0; i<9; i++) { 13352 inSISIDXREG(SISPART1,SiSScalingP1Regs[i],pSiS->scalingp1[i]); 13353 } 13354 for(i=0; i<9; i++) { 13355 inSISIDXREG(SISPART4,SiSScalingP4Regs[i],pSiS->scalingp4[i]); 13356 } 13357 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 13358 for(i=0; i<64; i++) { 13359 inSISIDXREG(SISPART2,(0xc0 + i),pSiS->scalingp2[i]); 13360 } 13361 } 13362#ifdef SISDUALHEAD 13363 if(pSiSEnt) { 13364 pSiSEnt->p2_1f = pSiS->p2_1f; pSiSEnt->p2_20 = pSiS->p2_20; 13365 pSiSEnt->p2_42 = pSiS->p2_42; pSiSEnt->p2_43 = pSiS->p2_43; 13366 pSiSEnt->p2_2b = pSiS->p2_2b; 13367 pSiSEnt->p2_01 = pSiS->p2_01; pSiSEnt->p2_02 = pSiS->p2_02; 13368 pSiSEnt->p2_44 = pSiS->p2_44; pSiSEnt->p2_45 = pSiS->p2_45; 13369 pSiSEnt->p2_46 = pSiS->p2_46; pSiSEnt->p2_0a = pSiS->p2_0a; 13370 pSiSEnt->sistvccbase = pSiS->sistvccbase; 13371 pSiSEnt->p2_35 = pSiS->p2_35; pSiSEnt->p2_36 = pSiS->p2_36; 13372 pSiSEnt->p2_37 = pSiS->p2_37; pSiSEnt->p2_38 = pSiS->p2_38; 13373 pSiSEnt->p2_48 = pSiS->p2_48; pSiSEnt->p2_49 = pSiS->p2_49; 13374 pSiSEnt->p2_4a = pSiS->p2_4a; pSiSEnt->p2_2f = pSiS->p2_2f; 13375 pSiSEnt->p2_30 = pSiS->p2_30; pSiSEnt->p2_47 = pSiS->p2_47; 13376 for(i=0; i<9; i++) { 13377 pSiSEnt->scalingp1[i] = pSiS->scalingp1[i]; 13378 } 13379 for(i=0; i<9; i++) { 13380 pSiSEnt->scalingp4[i] = pSiS->scalingp4[i]; 13381 } 13382 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 13383 for(i=0; i<64; i++) { 13384 pSiSEnt->scalingp2[i] = pSiS->scalingp2[i]; 13385 } 13386 } 13387 } 13388#endif 13389 if((val = mysistvantiflicker) != -1) { 13390 SiS_SetSISTVantiflicker(pScrn, val); 13391 } 13392 if((val = mysistvsaturation) != -1) { 13393 SiS_SetSISTVsaturation(pScrn, val); 13394 } 13395 if((val = mysistvcfilter) != -1) { 13396 SiS_SetSISTVcfilter(pScrn, val); 13397 } 13398 if((val = mysistvyfilter) != 1) { 13399 SiS_SetSISTVyfilter(pScrn, val); 13400 } 13401 if((val = mysistvcolcalibc) != 0) { 13402 SiS_SetSISTVcolcalib(pScrn, val, TRUE); 13403 } 13404 if((val = mysistvcolcalibf) != 0) { 13405 SiS_SetSISTVcolcalib(pScrn, val, FALSE); 13406 } 13407 if((val = mytvxpos) != 0) { 13408 SiS_SetTVxposoffset(pScrn, val); 13409 } 13410 if((val = mytvypos) != 0) { 13411 SiS_SetTVyposoffset(pScrn, val); 13412 } 13413 if((val = mytvxscale) != 0) { 13414 SiS_SetTVxscale(pScrn, val); 13415 } 13416 if((val = mytvyscale) != 0) { 13417 SiS_SetTVyscale(pScrn, val); 13418 } 13419 } 13420 } 13421 13422} 13423 13424/* Post-set SiS6326 TV registers */ 13425static void 13426SiS6326PostSetMode(ScrnInfoPtr pScrn, SISRegPtr sisReg) 13427{ 13428 SISPtr pSiS = SISPTR(pScrn); 13429 UChar tmp; 13430 int val; 13431 13432 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 13433 13434#ifdef UNLOCK_ALWAYS 13435 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 13436#endif 13437 13438 /* Backup default TV position registers */ 13439 pSiS->tvx1 = SiS6326GetTVReg(pScrn,0x3a); 13440 pSiS->tvx1 |= ((SiS6326GetTVReg(pScrn,0x3c) & 0x0f) << 8); 13441 pSiS->tvx2 = SiS6326GetTVReg(pScrn,0x26); 13442 pSiS->tvx2 |= ((SiS6326GetTVReg(pScrn,0x27) & 0xf0) << 4); 13443 pSiS->tvx3 = SiS6326GetTVReg(pScrn,0x12); 13444 pSiS->tvx3 |= ((SiS6326GetTVReg(pScrn,0x13) & 0xC0) << 2); 13445 pSiS->tvy1 = SiS6326GetTVReg(pScrn,0x11); 13446 pSiS->tvy1 |= ((SiS6326GetTVReg(pScrn,0x13) & 0x30) << 4); 13447 13448 /* Handle TVPosOffset options (BEFORE switching on TV) */ 13449 if((val = pSiS->tvxpos) != 0) { 13450 SiS_SetTVxposoffset(pScrn, val); 13451 } 13452 if((val = pSiS->tvypos) != 0) { 13453 SiS_SetTVyposoffset(pScrn, val); 13454 } 13455 13456 /* Switch on TV output. This is rather complicated, but 13457 * if we don't do it, TV output will flicker terribly. 13458 */ 13459 if(pSiS->SiS6326Flags & SIS6326_TVON) { 13460 orSISIDXREG(SISSR, 0x01, 0x20); 13461 tmp = SiS6326GetTVReg(pScrn,0x00); 13462 tmp &= ~0x04; 13463 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 13464 SiS6326SetTVReg(pScrn,0x00,tmp); 13465 for(val=0; val < 2; val++) { 13466 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 13467 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 13468 } 13469 SiS6326SetTVReg(pScrn, 0x00, sisReg->sis6326tv[0]); 13470 tmp = inSISREG(SISINPSTAT); 13471 outSISREG(SISAR, 0x20); 13472 tmp = inSISREG(SISINPSTAT); 13473 while(inSISREG(SISINPSTAT) & 0x01); 13474 while(!(inSISREG(SISINPSTAT) & 0x01)); 13475 andSISIDXREG(SISSR, 0x01, ~0x20); 13476 for(val=0; val < 10; val++) { 13477 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 13478 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 13479 } 13480 andSISIDXREG(SISSR, 0x01, ~0x20); 13481 } 13482 13483 tmp = SiS6326GetTVReg(pScrn,0x00); 13484 if(!(tmp & 0x04)) return; 13485 13486 /* Apply TV settings given by options */ 13487 if((val = pSiS->sistvantiflicker) != -1) { 13488 SiS_SetSIS6326TVantiflicker(pScrn, val); 13489 } 13490 if((val = pSiS->sis6326enableyfilter) != -1) { 13491 SiS_SetSIS6326TVenableyfilter(pScrn, val); 13492 } 13493 if((val = pSiS->sis6326yfilterstrong) != -1) { 13494 SiS_SetSIS6326TVyfilterstrong(pScrn, val); 13495 } 13496 13497} 13498 13499/* Check if video bridge is in slave mode */ 13500Bool 13501SiSBridgeIsInSlaveMode(ScrnInfoPtr pScrn) 13502{ 13503 SISPtr pSiS = SISPTR(pScrn); 13504 UChar usScrP1_00; 13505 13506 if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return FALSE; 13507 13508 inSISIDXREG(SISPART1,0x00,usScrP1_00); 13509 if( ((pSiS->VGAEngine == SIS_300_VGA) && (usScrP1_00 & 0xa0) == 0x20) || 13510 ((pSiS->VGAEngine == SIS_315_VGA) && (usScrP1_00 & 0x50) == 0x10) ) { 13511 return TRUE; 13512 } 13513 13514 return FALSE; 13515} 13516 13517/* Build a list of the VESA modes the BIOS reports as valid */ 13518static void 13519SiSBuildVesaModeList(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe) 13520{ 13521 SISPtr pSiS = SISPTR(pScrn); 13522 int i = 0; 13523 13524 while(vbe->VideoModePtr[i] != 0xffff) { 13525 sisModeInfoPtr m; 13526 VbeModeInfoBlock *mode; 13527 int id = vbe->VideoModePtr[i++]; 13528 13529 if((mode = VBEGetModeInfo(pVbe, id)) == NULL) { 13530 continue; 13531 } 13532 13533 m = xnfcalloc(sizeof(sisModeInfoRec), 1); 13534 if(!m) { 13535 VBEFreeModeInfo(mode); 13536 continue; 13537 } 13538 m->width = mode->XResolution; 13539 m->height = mode->YResolution; 13540 m->bpp = mode->BitsPerPixel; 13541 m->n = id; 13542 m->next = pSiS->SISVESAModeList; 13543 13544 pSiS->SISVESAModeList = m; 13545 13546 VBEFreeModeInfo(mode); 13547 13548 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 13549 "VESA BIOS supports mode number 0x%x: %ix%i (%i bpp)\n", 13550 m->n, m->width, m->height, m->bpp); 13551 } 13552} 13553 13554/* Get VESA mode number from given resolution/depth */ 13555static UShort 13556SiSCalcVESAModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode) 13557{ 13558 SISPtr pSiS = SISPTR(pScrn); 13559 sisModeInfoPtr m = pSiS->SISVESAModeList; 13560 UShort i = (pScrn->bitsPerPixel+7)/8 - 1; 13561 UShort ModeNumber = 0; 13562 int j; 13563 13564 while(m) { 13565 if( (pScrn->bitsPerPixel == m->bpp) && 13566 (mode->HDisplay == m->width) && 13567 (mode->VDisplay == m->height) ) 13568 return m->n; 13569 m = m->next; 13570 } 13571 13572 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 13573 "No valid VESA BIOS mode found for %dx%d (%d bpp)\n", 13574 mode->HDisplay, mode->VDisplay, pScrn->bitsPerPixel); 13575 13576 if(!pSiS->ROM661New) { /* VESA numbers changed! */ 13577 j = 0; 13578 while(VESAModeIndices[j] != 9999) { 13579 if( (mode->HDisplay == VESAModeIndices[j]) && 13580 (mode->VDisplay == VESAModeIndices[j+1]) ) { 13581 ModeNumber = VESAModeIndices[j + 2 + i]; 13582 break; 13583 } 13584 j += 6; 13585 } 13586 13587 if(!ModeNumber) { 13588 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 13589 "No valid mode found for %dx%dx%d in built-in table either.\n", 13590 mode->HDisplay, mode->VDisplay, pScrn->bitsPerPixel); 13591 } 13592 } 13593 13594 return(ModeNumber); 13595} 13596 13597UShort 13598SiS_GetModeNumber(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned int VBFlags) 13599{ 13600 SISPtr pSiS = SISPTR(pScrn); 13601 UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; 13602 BOOLEAN FSTN = pSiS->FSTN ? TRUE : FALSE; 13603 13604#ifdef SISDUALHEAD 13605 if(pSiS->DualHeadMode && pSiS->SecondHead) FSTN = FALSE; 13606#endif 13607 13608 return(SiS_GetModeID(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, 13609 i, FSTN, pSiS->LCDwidth, pSiS->LCDheight)); 13610} 13611 13612static Bool 13613SiSValidLCDUserMode(SISPtr pSiS, unsigned int VBFlags, DisplayModePtr mode, Bool isforlcda) 13614{ 13615 if(mode->Flags & V_INTERLACE) return FALSE; 13616 13617 if(mode->HDisplay > 2048) return FALSE; 13618 if(mode->VDisplay > 1536) return FALSE; 13619 13620 if(pSiS->VBFlags2 & VB2_LCD162MHZBRIDGE) { 13621 if(mode->Clock > 162500) return FALSE; 13622#ifdef VB_FORBID_CRT2LCD_OVER_1600 13623 if(!isforlcda) { 13624 if(mode->HDisplay > 1600) return FALSE; 13625 } 13626#endif 13627 } else { /* 301, 301B, 302B (no LCDA!) */ 13628 if(mode->Clock > 130000) return FALSE; 13629 if(mode->Clock > 111000) { 13630 xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING, 13631 "WARNING: Mode clock beyond video bridge specs (%dMHz). Hardware damage might occure.\n", 13632 mode->Clock / 1000); 13633 } 13634 if(mode->HDisplay > 1600) return FALSE; 13635 if(mode->VDisplay > 1024) return FALSE; 13636 } 13637 13638 return TRUE; 13639} 13640 13641static Bool 13642SiSValidVGA2UserMode(SISPtr pSiS, unsigned int VBFlags, DisplayModePtr mode) 13643{ 13644 if(mode->Flags & V_INTERLACE) return FALSE; 13645 13646 if(mode->HDisplay > 2048) return FALSE; 13647 if(mode->VDisplay > 1536) return FALSE; 13648 13649 if(pSiS->VBFlags2 & VB2_RAMDAC202MHZBRIDGE) { 13650 if(mode->Clock > 203000) return FALSE; 13651 } else if(pSiS->VBFlags2 & VB2_30xBLV) { 13652 if(mode->Clock > 162500) return FALSE; 13653 } else { 13654 if(mode->Clock > 135500) return FALSE; 13655 } 13656 13657 return TRUE; 13658} 13659 13660UShort 13661SiS_CheckModeCRT1(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned int VBFlags, Bool havecustommodes) 13662{ 13663 SISPtr pSiS = SISPTR(pScrn); 13664 UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; 13665 int j; 13666 13667 if(!(VBFlags & CRT1_LCDA)) { 13668 13669 if((havecustommodes) && (!(mode->type & M_T_DEFAULT))) { 13670 return 0xfe; 13671 } 13672 13673 } else if(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE) { 13674 13675 if(pSiS->ChipType < SIS_661) { /* < 661 only? */ 13676 if(!(mode->type & M_T_DEFAULT)) { 13677 if(mode->HTotal > 2055) return 0; 13678 /* (Default mode will be caught in mode switching code) */ 13679 } 13680 } 13681 13682 if(pSiS->SiS_Pr->CP_HaveCustomData) { 13683 for(j=0; j<7; j++) { 13684 if((pSiS->SiS_Pr->CP_DataValid[j]) && 13685 (mode->HDisplay == pSiS->SiS_Pr->CP_HDisplay[j]) && 13686 (mode->VDisplay == pSiS->SiS_Pr->CP_VDisplay[j]) && 13687 (mode->type & M_T_BUILTIN)) 13688 return 0xfe; 13689 } 13690 } 13691 13692 if((pSiS->AddedPlasmaModes) && (mode->type & M_T_BUILTIN)) 13693 return 0xfe; 13694 13695 if((havecustommodes) && 13696 (pSiS->LCDwidth) && /* = test if LCD present */ 13697 (!(mode->type & M_T_DEFAULT)) && 13698 (SiSValidLCDUserMode(pSiS, VBFlags, mode, TRUE))) 13699 return 0xfe; 13700 13701 if((mode->HDisplay > pSiS->LCDwidth) || 13702 (mode->VDisplay > pSiS->LCDheight)) { 13703 return 0; 13704 } 13705 13706 } else { 13707 13708 if((mode->HDisplay > pSiS->LCDwidth) || 13709 (mode->VDisplay > pSiS->LCDheight)) { 13710 return 0; 13711 } 13712 13713 } 13714 13715 return(SiS_GetModeID(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, 13716 i, pSiS->FSTN, pSiS->LCDwidth, pSiS->LCDheight)); 13717} 13718 13719UShort 13720SiS_CheckModeCRT2(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned int VBFlags, Bool havecustommodes) 13721{ 13722 SISPtr pSiS = SISPTR(pScrn); 13723 UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; 13724 UShort ModeIndex = 0; 13725 int j; 13726 13727#ifdef TWDEBUG 13728 xf86DrvMsg(0, X_INFO, "Inside CheckCalcModeIndex (VBFlags %lx, mode %dx%d)\n", 13729 VBFlags,mode->HDisplay, mode->VDisplay); 13730#endif 13731 13732 if(VBFlags & CRT2_LCD) { /* CRT2 is LCD */ 13733 13734 if((pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && (!(pSiS->VBFlags2 & VB2_30xBDH))) { 13735 13736 if(pSiS->SiS_Pr->CP_HaveCustomData) { 13737 for(j=0; j<7; j++) { 13738 if((pSiS->SiS_Pr->CP_DataValid[j]) && 13739 (mode->HDisplay == pSiS->SiS_Pr->CP_HDisplay[j]) && 13740 (mode->VDisplay == pSiS->SiS_Pr->CP_VDisplay[j]) && 13741#ifdef VB_FORBID_CRT2LCD_OVER_1600 13742 (mode->HDisplay <= 1600) && 13743#endif 13744 (mode->type & M_T_BUILTIN)) 13745 return 0xfe; 13746 } 13747 } 13748 13749 /* All plasma modes have HDisplay <= 1600 */ 13750 if((pSiS->AddedPlasmaModes) && (mode->type & M_T_BUILTIN)) 13751 return 0xfe; 13752 13753 if((havecustommodes) && 13754 (pSiS->LCDwidth) && /* = test if LCD present */ 13755 (!(mode->type & M_T_DEFAULT)) && 13756 (SiSValidLCDUserMode(pSiS, VBFlags, mode, FALSE))) 13757 return 0xfe; 13758 13759 } 13760 13761 if( ((mode->HDisplay <= pSiS->LCDwidth) && 13762 (mode->VDisplay <= pSiS->LCDheight)) || 13763 ((pSiS->SiS_Pr->SiS_CustomT == CUT_PANEL848) && 13764 (((mode->HDisplay == 1360) && (mode->VDisplay == 768)) || 13765 ((mode->HDisplay == 1024) && (mode->VDisplay == 768)) || 13766 ((mode->HDisplay == 800) && (mode->VDisplay == 600)))) || 13767 ((pSiS->SiS_Pr->SiS_CustomT == CUT_PANEL856) && 13768 (((mode->HDisplay == 1024) && (mode->VDisplay == 768)) || 13769 ((mode->HDisplay == 800) && (mode->VDisplay == 600)))) ) { 13770 13771 ModeIndex = SiS_GetModeID_LCD(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, i, 13772 pSiS->FSTN, pSiS->SiS_Pr->SiS_CustomT, pSiS->LCDwidth, pSiS->LCDheight, 13773 pSiS->VBFlags2); 13774 13775 } 13776 13777 } else if(VBFlags & CRT2_TV) { /* CRT2 is TV */ 13778 13779 ModeIndex = SiS_GetModeID_TV(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, i, 13780 pSiS->VBFlags2); 13781 13782 } else if(VBFlags & CRT2_VGA) { /* CRT2 is VGA2 */ 13783 13784 if((pSiS->AddedPlasmaModes) && (mode->type & M_T_BUILTIN)) 13785 return 0xfe; 13786 13787 if((havecustommodes) && 13788 (!(mode->type & M_T_DEFAULT)) && 13789 (SiSValidVGA2UserMode(pSiS, VBFlags, mode))) 13790 return 0xfe; 13791 13792 ModeIndex = SiS_GetModeID_VGA2(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, i, 13793 pSiS->VBFlags2); 13794 13795 } else { /* no CRT2 */ 13796 13797 /* Return a valid mode number */ 13798 ModeIndex = 0xfe; 13799 13800 } 13801 13802 return(ModeIndex); 13803} 13804 13805/* Calculate the vertical refresh rate from a mode */ 13806float 13807SiSCalcVRate(DisplayModePtr mode) 13808{ 13809 float hsync, refresh = 0; 13810 13811 if(mode->HSync > 0.0) 13812 hsync = mode->HSync; 13813 else if(mode->HTotal > 0) 13814 hsync = (float)mode->Clock / (float)mode->HTotal; 13815 else 13816 hsync = 0.0; 13817 13818 if(mode->VTotal > 0) 13819 refresh = hsync * 1000.0 / mode->VTotal; 13820 13821 if(mode->Flags & V_INTERLACE) 13822 refresh *= 2.0; 13823 13824 if(mode->Flags & V_DBLSCAN) 13825 refresh /= 2.0; 13826 13827 if(mode->VScan > 1) 13828 refresh /= mode->VScan; 13829 13830 if(mode->VRefresh > 0.0) 13831 refresh = mode->VRefresh; 13832 13833 if(hsync == 0.0 || refresh == 0.0) return 0.0; 13834 13835 return refresh; 13836} 13837 13838/* Calculate CR33 (rate index) for CRT1. 13839 * Calculation is done using currentmode, therefore it is 13840 * recommended to set VertRefresh and HorizSync to correct 13841 * values in config file. 13842 */ 13843UChar 13844SISSearchCRT1Rate(ScrnInfoPtr pScrn, DisplayModePtr mode) 13845{ 13846 SISPtr pSiS = SISPTR(pScrn); 13847 int i = 0, irefresh; 13848 UShort xres = mode->HDisplay; 13849 UShort yres = mode->VDisplay; 13850 UChar index, defindex; 13851 Bool checksis730 = FALSE; 13852 13853 defindex = (xres == 800 || xres == 1024 || xres == 1280) ? 0x02 : 0x01; 13854 13855 irefresh = (int)SiSCalcVRate(mode); 13856 if(!irefresh) return defindex; 13857 13858 /* SiS730 has troubles on CRT2 if CRT1 is at 32bpp */ 13859 if( (pSiS->ChipType == SIS_730) && 13860 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && 13861 (pSiS->CurrentLayout.bitsPerPixel == 32) ) { 13862#ifdef SISDUALHEAD 13863 if(pSiS->DualHeadMode) { 13864 if(pSiS->SecondHead) { 13865 checksis730 = TRUE; 13866 } 13867 } else 13868#endif 13869 if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE) && (!pSiS->CRT1off)) { 13870 checksis730 = TRUE; 13871 } 13872 } 13873 13874#ifdef TWDEBUG 13875 xf86DrvMsg(0, X_INFO, "Debug: CalcVRate returned %d\n", irefresh); 13876#endif 13877 13878 /* We need the REAL refresh rate here */ 13879 if(mode->Flags & V_INTERLACE) irefresh /= 2; 13880 13881 /* Do not multiply by 2 when DBLSCAN! */ 13882 13883#ifdef TWDEBUG 13884 xf86DrvMsg(0, X_INFO, "Debug: Rate after correction = %d\n", irefresh); 13885#endif 13886 13887 index = 0; 13888 while((sisx_vrate[i].idx != 0) && (sisx_vrate[i].xres <= xres)) { 13889 if((sisx_vrate[i].xres == xres) && (sisx_vrate[i].yres == yres)) { 13890 if((checksis730 == FALSE) || (sisx_vrate[i].SiS730valid32bpp == TRUE)) { 13891 if(sisx_vrate[i].refresh == irefresh) { 13892 index = sisx_vrate[i].idx; 13893 break; 13894 } else if(sisx_vrate[i].refresh > irefresh) { 13895 if((sisx_vrate[i].refresh - irefresh) <= 3) { 13896 index = sisx_vrate[i].idx; 13897 } else if( ((checksis730 == FALSE) || (sisx_vrate[i - 1].SiS730valid32bpp == TRUE)) && 13898 ((irefresh - sisx_vrate[i - 1].refresh) <= 2) && 13899 (sisx_vrate[i].idx != 1) ) { 13900 index = sisx_vrate[i - 1].idx; 13901 } 13902 break; 13903 } else if((irefresh - sisx_vrate[i].refresh) <= 2) { 13904 index = sisx_vrate[i].idx; 13905 break; 13906 } 13907 } 13908 } 13909 i++; 13910 } 13911 13912 if(index > 0) return index; 13913 else return defindex; 13914} 13915 13916void 13917SISWaitRetraceCRT1(ScrnInfoPtr pScrn) 13918{ 13919 SISPtr pSiS = SISPTR(pScrn); 13920 int watchdog; 13921 UChar temp; 13922 13923 inSISIDXREG(SISCR,0x17,temp); 13924 if(!(temp & 0x80)) return; 13925 13926 inSISIDXREG(SISSR,0x1f,temp); 13927 if(temp & 0xc0) return; 13928 13929 watchdog = 65536; 13930 while((inSISREG(SISINPSTAT) & 0x08) && --watchdog); 13931 watchdog = 65536; 13932 while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog); 13933} 13934 13935void 13936SISWaitRetraceCRT2(ScrnInfoPtr pScrn) 13937{ 13938 SISPtr pSiS = SISPTR(pScrn); 13939 int watchdog; 13940 UChar temp, reg; 13941 13942 if(SiSBridgeIsInSlaveMode(pScrn)) { 13943 SISWaitRetraceCRT1(pScrn); 13944 return; 13945 } 13946 13947 switch(pSiS->VGAEngine) { 13948 case SIS_300_VGA: 13949 reg = 0x25; 13950 break; 13951 case SIS_315_VGA: 13952 reg = 0x30; 13953 break; 13954 default: 13955 return; 13956 } 13957 13958 watchdog = 65536; 13959 do { 13960 inSISIDXREG(SISPART1, reg, temp); 13961 if(!(temp & 0x02)) break; 13962 } while(--watchdog); 13963 watchdog = 65536; 13964 do { 13965 inSISIDXREG(SISPART1, reg, temp); 13966 if(temp & 0x02) break; 13967 } while(--watchdog); 13968} 13969 13970static void 13971SISWaitVBRetrace(ScrnInfoPtr pScrn) 13972{ 13973 SISPtr pSiS = SISPTR(pScrn); 13974 13975 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 13976#ifdef SISDUALHEAD 13977 if(pSiS->DualHeadMode) { 13978 if(pSiS->SecondHead) 13979 SISWaitRetraceCRT1(pScrn); 13980 else 13981 SISWaitRetraceCRT2(pScrn); 13982 } else { 13983#endif 13984 if(pSiS->VBFlags & DISPTYPE_DISP1) { 13985 SISWaitRetraceCRT1(pScrn); 13986 } 13987 if(pSiS->VBFlags & DISPTYPE_DISP2) { 13988 if(!(SiSBridgeIsInSlaveMode(pScrn))) { 13989 SISWaitRetraceCRT2(pScrn); 13990 } 13991 } 13992#ifdef SISDUALHEAD 13993 } 13994#endif 13995 } else { 13996 SISWaitRetraceCRT1(pScrn); 13997 } 13998} 13999 14000#define MODEID_OFF 0x449 14001 14002UChar 14003SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, UShort offset, UChar value) 14004{ 14005 UChar ret = 0; 14006#ifdef SIS_USE_BIOS_SCRATCH 14007 UChar *base; 14008#endif 14009 14010 /* For some reasons (like detecting the current display mode), 14011 * we need to read (or write-back) values from the BIOS 14012 * scratch area. This area is only valid for the primary 14013 * graphics card. For the secondary, we just return some 14014 * defaults and ignore requests to write data. As regards 14015 * the display mode: If sisfb is loaded for the secondary 14016 * card, it very probably has set a mode, but in any case 14017 * informed us via its info packet. So this here will not be 14018 * called for mode detection in this case. 14019 */ 14020 14021 switch(offset) { 14022 case 0x489: 14023 ret = 0x11; /* Default VGA Info */ 14024 break; 14025 case MODEID_OFF: 14026 ret = 0x03; /* Default current display mode */ 14027 break; 14028 } 14029 14030#ifndef XSERVER_LIBPCIACCESS 14031#ifdef SIS_USE_BIOS_SCRATCH 14032 if(SISPTR(pScrn)->Primary) { 14033 base = xf86MapVidMem(pScrn->scrnIndex, VIDMEM_MMIO, 0, 0x2000); 14034 if(!base) { 14035 SISErrorLog(pScrn, "(Could not map BIOS scratch area)\n"); 14036 return ret; 14037 } 14038 14039 ret = *(base + offset); 14040 14041 /* value != 0xff means: set register */ 14042 if(value != 0xff) { 14043 *(base + offset) = value; 14044 } 14045 14046 xf86UnMapVidMem(pScrn->scrnIndex, base, 0x2000); 14047 } 14048#endif 14049#endif 14050 return ret; 14051} 14052 14053UChar 14054SiS_GetSetModeID(ScrnInfoPtr pScrn, UChar id) 14055{ 14056 return(SiS_GetSetBIOSScratch(pScrn, MODEID_OFF, id)); 14057} 14058 14059void 14060SiSMemCopyToVideoRam(SISPtr pSiS, UChar *to, UChar *from, int size) 14061{ 14062 if((ULong)to & 15) (*pSiS->SiSFastMemCopy)(to, from, size); 14063 else (*pSiS->SiSFastVidCopy)(to, from, size); 14064} 14065 14066void 14067SiSMemCopyFromVideoRam(SISPtr pSiS, UChar *to, UChar *from, int size) 14068{ 14069 if((ULong)to & 15) (*pSiS->SiSFastMemCopyFrom)(to, from, size); 14070 else (*pSiS->SiSFastVidCopyFrom)(to, from, size); 14071} 14072 14073void 14074sisSaveUnlockExtRegisterLock(SISPtr pSiS, UChar *reg1, UChar *reg2) 14075{ 14076 register UChar val; 14077 ULong mylockcalls; 14078#ifdef TWDEBUG 14079 UChar val1, val2; 14080 int i; 14081#endif 14082 14083 pSiS->lockcalls++; 14084 mylockcalls = pSiS->lockcalls; 14085 14086 /* check if already unlocked */ 14087 inSISIDXREG(SISSR, 0x05, val); 14088 14089 if(val != 0xa1) { 14090 14091 /* save State */ 14092 if(reg1) *reg1 = val; 14093 14094 /* unlock */ 14095 outSISIDXREG(SISSR, 0x05, 0x86); 14096 14097 /* Now check again */ 14098 inSISIDXREG(SISSR, 0x05, val); 14099 14100 if(val != 0xA1) { 14101 14102 xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING, 14103 "Failed to unlock SR registers at relocated i/o ports\n"); 14104 14105#ifdef TWDEBUG 14106 for(i = 0; i <= 0x3f; i++) { 14107 inSISIDXREG(SISSR, i, val1); 14108 inSISIDXREG(0x3c4, i, val2); 14109 xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO, 14110 "SR%02d: RelIO=0x%02x 0x3c4=0x%02x (%ld)\n", 14111 i, val1, val2, mylockcalls); 14112 } 14113#endif 14114 14115 /* Emergency measure: unlock at 0x3c4, and try to enable relocated IO ports */ 14116 switch(pSiS->VGAEngine) { 14117 case SIS_OLD_VGA: 14118 case SIS_530_VGA: 14119 outSISIDXREG(0x3c4, 0x05, 0x86); 14120 andSISIDXREG(0x3c4, 0x33, ~0x20); 14121 break; 14122 case SIS_300_VGA: 14123 case SIS_315_VGA: 14124 outSISIDXREG(0x3c4, 0x05, 0x86); 14125 orSISIDXREG(0x3c4, 0x20, 0x20); 14126 break; 14127 } 14128 outSISIDXREG(SISSR, 0x05, 0x86); 14129 inSISIDXREG(SISSR, 0x05, val); 14130 if(val != 0xa1) { 14131 SISErrorLog(pSiS->pScrn, 14132 "Failed to unlock SR registers (%p, %lx, 0x%02x; %ld)\n", 14133 (void *)pSiS, (ULong)pSiS->RelIO, val, mylockcalls); 14134 /* Now await doom... */ 14135 } 14136 } 14137 } 14138 if((pSiS->VGAEngine == SIS_OLD_VGA) || (pSiS->VGAEngine == SIS_530_VGA)) { 14139 inSISIDXREG(SISCR, 0x80, val); 14140 if(val != 0xa1) { 14141 /* save State */ 14142 if(reg2) *reg2 = val; 14143 outSISIDXREG(SISCR, 0x80, 0x86); 14144 inSISIDXREG(SISCR, 0x80, val); 14145 if(val != 0xA1) { 14146 SISErrorLog(pSiS->pScrn, 14147 "Failed to unlock cr registers (%p, %lx, 0x%02x)\n", 14148 (void *)pSiS, (ULong)pSiS->RelIO, val); 14149 } 14150 } 14151 } 14152} 14153 14154void 14155sisRestoreExtRegisterLock(SISPtr pSiS, UChar reg1, UChar reg2) 14156{ 14157 /* restore lock */ 14158#ifndef UNLOCK_ALWAYS 14159 outSISIDXREG(SISSR, 0x05, reg1 == 0xA1 ? 0x86 : 0x00); 14160 if((pSiS->VGAEngine == SIS_OLD_VGA) || (pSiS->VGAEngine == SIS_530_VGA)) { 14161 outSISIDXREG(SISCR, 0x80, reg2 == 0xA1 ? 0x86 : 0x00); 14162 } 14163#endif 14164} 14165 14166