sis_driver.c revision fe196524
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, X_INFO, "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#if 0 8984 xf86DisableRandR(); 8985#endif 8986 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8987 "Driver rotation enabled, disabling RandR\n"); 8988#endif 8989 } else if(pSiS->Reflect) { 8990 switch(pScrn->bitsPerPixel) { 8991 case 8: 8992 case 16: 8993 case 32: 8994 if(!pSiS->PointerMoved) pSiS->PointerMoved = pScrn->PointerMoved; 8995 pScrn->PointerMoved = SISPointerMovedReflect; 8996 refreshArea = SISRefreshAreaReflect; 8997#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 8998#if 0 8999 xf86DisableRandR(); 9000#endif 9001 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9002 "Driver reflection enabled, disabling RandR\n"); 9003#endif 9004 break; 9005 default: 9006 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 9007 "Reflection not supported at this framebuffer depth\n"); 9008 } 9009 } 9010 9011 ShadowFBInit(pScreen, refreshArea); 9012 } 9013 9014 xf86DPMSInit(pScreen, (DPMSSetProcPtr)SISDisplayPowerManagementSet, 0); 9015 9016 /* Init memPhysBase and fbOffset in pScrn */ 9017 pScrn->memPhysBase = pSiS->FbAddress; 9018 pScrn->fbOffset = 0; 9019 9020 /* Initialize Xv */ 9021 pSiS->ResetXv = pSiS->ResetXvGamma = pSiS->ResetXvDisplay = NULL; 9022#if (XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,99,0,0)) || (defined(XvExtension)) 9023 if((!pSiS->NoXvideo) && (!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY))) { 9024 9025 if((pSiS->VGAEngine == SIS_300_VGA) || 9026 (pSiS->VGAEngine == SIS_315_VGA)) { 9027 9028 const char *using = "Using SiS300/315/330/340 series HW Xv"; 9029 9030#ifdef SISDUALHEAD 9031 if(pSiS->DualHeadMode) { 9032 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9033 "%s on CRT%d\n", using, (pSiS->SecondHead ? 1 : 2)); 9034 if(!pSiS->hasTwoOverlays) { 9035 if( (pSiS->XvOnCRT2 && pSiS->SecondHead) || 9036 (!pSiS->XvOnCRT2 && !pSiS->SecondHead) ) { 9037 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9038 "However, video overlay will by default only be visible on CRT%d\n", 9039 pSiS->XvOnCRT2 ? 2 : 1); 9040 } 9041 } 9042 } else { 9043#endif 9044 if(pSiS->hasTwoOverlays) { 9045 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s\n", using); 9046 } else { 9047 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s by default on CRT%d\n", 9048 using, (pSiS->XvOnCRT2 ? 2 : 1)); 9049 } 9050#ifdef SISDUALHEAD 9051 } 9052#endif 9053 9054 SISInitVideo(pScreen); 9055 9056 if(pSiS->blitadaptor) { 9057 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9058 "Default Xv adaptor is Video %s\n", 9059 pSiS->XvDefAdaptorBlit ? "Blitter" : "Overlay"); 9060 } 9061 9062 } else if(pSiS->Chipset == PCI_CHIP_SIS530 || 9063 pSiS->Chipset == PCI_CHIP_SIS6326 || 9064 pSiS->Chipset == PCI_CHIP_SIS5597) { 9065 9066 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9067 "Using SiS5597/5598/6326/530/620 HW Xv\n" ); 9068 9069 SIS6326InitVideo(pScreen); 9070 9071 } else { /* generic Xv */ 9072 9073 XF86VideoAdaptorPtr *ptr; 9074 int n = xf86XVListGenericAdaptors(pScrn, &ptr); 9075 9076 if(n) { 9077 xf86XVScreenInit(pScreen, ptr, n); 9078 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using generic Xv\n" ); 9079 } 9080 9081 } 9082 } 9083#endif 9084 9085#ifdef SISDRI 9086 if(pSiS->loadDRI) { 9087 if(pSiS->directRenderingEnabled) { 9088 /* Now that mi, drm and others have done their thing, 9089 * complete the DRI setup. 9090 */ 9091 pSiS->directRenderingEnabled = SISDRIFinishScreenInit(pScreen); 9092 } 9093 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering %s\n", 9094 pSiS->directRenderingEnabled ? "enabled" : "disabled"); 9095 /* TODO */ 9096 /* if(pSiS->directRenderingEnabled) SISSetLFBConfig(pSiS); */ 9097 } 9098#endif 9099 9100 /* Wrap some funcs, initialize pseudo-Xinerama and setup remaining SD flags */ 9101 9102 pSiS->SiS_SD_Flags &= ~(SiS_SD_PSEUDOXINERAMA); 9103#ifdef SISMERGED 9104 if(pSiS->MergedFB) { 9105 pSiS->PointerMoved = pScrn->PointerMoved; 9106 pScrn->PointerMoved = SISMergedPointerMoved; 9107 pSiS->Rotate = 0; 9108 pSiS->Reflect = 0; 9109 pSiS->ShadowFB = FALSE; 9110#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 9111 if(pSiS->CRT1XOffs || pSiS->CRT1YOffs || pSiS->CRT2XOffs || pSiS->CRT2YOffs) { 9112#if 0 9113 xf86DisableRandR(); 9114#endif 9115 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9116 "MergedFB: CRT2Position offset used, disabling RandR\n"); 9117 } 9118#endif 9119#ifdef SISXINERAMA 9120 if(pSiS->UseSiSXinerama) { 9121 SiSnoPanoramiXExtension = FALSE; 9122 SiSXineramaExtensionInit(pScrn); 9123 if(!SiSnoPanoramiXExtension) { 9124 pSiS->SiS_SD_Flags |= SiS_SD_PSEUDOXINERAMA; 9125 if(pSiS->HaveNonRect) { 9126 /* Reset the viewport (now eventually non-recangular) */ 9127 SISAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 9128 } 9129 } 9130 } else { 9131 pSiS->MouseRestrictions = FALSE; 9132 } 9133#endif 9134 } 9135#endif 9136 9137 /* Wrap CloseScreen and set up SaveScreen */ 9138 pSiS->CloseScreen = pScreen->CloseScreen; 9139 pScreen->CloseScreen = SISCloseScreen; 9140#ifdef SISDUALHEAD 9141 if(pSiS->DualHeadMode) 9142 pScreen->SaveScreen = SISSaveScreenDH; 9143 else 9144#endif 9145 pScreen->SaveScreen = SISSaveScreen; 9146 9147 /* Install BlockHandler */ 9148 pSiS->BlockHandler = pScreen->BlockHandler; 9149 pScreen->BlockHandler = SISBlockHandler; 9150 9151 /* Report any unused options (only for the first generation) */ 9152 if(serverGeneration == 1) { 9153 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 9154 } 9155 9156 /* Clear frame buffer */ 9157 /* For CRT2, we don't do that at this point in dual head 9158 * mode since the mode isn't switched at this time (it will 9159 * be reset when setting the CRT1 mode). Hence, we just 9160 * save the necessary data and clear the screen when 9161 * going through this for CRT1. 9162 */ 9163 9164 OnScreenSize = pScrn->displayWidth * pScrn->currentMode->VDisplay 9165 * (pScrn->bitsPerPixel >> 3); 9166 9167 /* Turn on the screen now */ 9168 /* We do this in dual head mode after second head is finished */ 9169#ifdef SISDUALHEAD 9170 if(pSiS->DualHeadMode) { 9171 if(pSiS->SecondHead) { 9172 sisclearvram(pSiS->FbBase, OnScreenSize); 9173 sisclearvram(pSiSEnt->FbBase1, pSiSEnt->OnScreenSize1); 9174 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 9175 } else { 9176 pSiSEnt->FbBase1 = pSiS->FbBase; 9177 pSiSEnt->OnScreenSize1 = OnScreenSize; 9178 } 9179 } else { 9180#endif 9181 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 9182 sisclearvram(pSiS->FbBase, OnScreenSize); 9183#ifdef SISDUALHEAD 9184 } 9185#endif 9186 9187 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTSGRCRT2; 9188#ifdef SISDUALHEAD 9189 if(!pSiS->DualHeadMode) { 9190#endif 9191 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 9192 if((pSiS->crt2cindices) && (pSiS->crt2gcolortable)) { 9193 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTSGRCRT2; 9194 } 9195 } 9196#ifdef SISDUALHEAD 9197 } 9198#endif 9199 9200 pSiS->SiS_SD_Flags &= ~SiS_SD_ISDEPTH8; 9201 if(pSiS->CurrentLayout.bitsPerPixel == 8) { 9202 pSiS->SiS_SD_Flags |= SiS_SD_ISDEPTH8; 9203 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTXVGAMMA1; 9204 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTSGRCRT2; 9205 } 9206 9207#ifdef SISGAMMARAMP 9208 pSiS->SiS_SD_Flags |= SiS_SD_CANSETGAMMA; 9209#else 9210 pSiS->SiS_SD_Flags &= ~SiS_SD_CANSETGAMMA; 9211#endif 9212 9213 SiSCtrlExtInit(pScrn); 9214 9215 return TRUE; 9216} 9217 9218/* Usually mandatory */ 9219Bool 9220SISSwitchMode(SWITCH_MODE_ARGS_DECL) 9221{ 9222 SCRN_INFO_PTR(arg); 9223 SISPtr pSiS = SISPTR(pScrn); 9224 9225 if(!pSiS->skipswitchcheck) { 9226 if(SISValidMode(arg, mode, TRUE, 0) != MODE_OK) { 9227 return FALSE; 9228 } 9229 } 9230 9231 (*pSiS->SyncAccel)(pScrn); 9232 9233 if(!(SISModeInit(pScrn, mode))) return FALSE; 9234 9235 /* Since RandR (indirectly) uses SwitchMode(), we need to 9236 * update our Xinerama info here, too, in case of resizing 9237 */ 9238#ifdef SISMERGED 9239#ifdef SISXINERAMA 9240 if(pSiS->MergedFB) { 9241 SiSUpdateXineramaScreenInfo(pScrn); 9242 } 9243#endif 9244#endif 9245 return TRUE; 9246} 9247 9248static void 9249SISSetStartAddressCRT1(SISPtr pSiS, ULong base) 9250{ 9251 UChar cr11backup; 9252 9253 inSISIDXREG(SISCR, 0x11, cr11backup); /* Unlock CRTC registers */ 9254 andSISIDXREG(SISCR, 0x11, 0x7F); 9255 outSISIDXREG(SISCR, 0x0D, base & 0xFF); 9256 outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); 9257 outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF); 9258 if(pSiS->VGAEngine == SIS_315_VGA) { 9259 setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01); 9260 } 9261 /* Eventually lock CRTC registers */ 9262 setSISIDXREG(SISCR, 0x11, 0x7F,(cr11backup & 0x80)); 9263} 9264 9265static void 9266SISSetStartAddressCRT2(SISPtr pSiS, ULong base) 9267{ 9268 SiS_UnLockCRT2(pSiS->SiS_Pr); 9269 outSISIDXREG(SISPART1, 0x06, GETVAR8(base)); 9270 outSISIDXREG(SISPART1, 0x05, GETBITS(base, 15:8)); 9271 outSISIDXREG(SISPART1, 0x04, GETBITS(base, 23:16)); 9272 if(pSiS->VGAEngine == SIS_315_VGA) { 9273 setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7); 9274 } 9275 SiS_LockCRT2(pSiS->SiS_Pr); 9276} 9277 9278#ifdef SISMERGED 9279static Bool 9280InRegion(int x, int y, region r) 9281{ 9282 return (r.x0 <= x) && (x <= r.x1) && (r.y0 <= y) && (y <= r.y1); 9283} 9284 9285static void 9286SISAdjustFrameHW_CRT1(ScrnInfoPtr pScrn, int x, int y) 9287{ 9288 SISPtr pSiS = SISPTR(pScrn); 9289 ULong base; 9290 9291 base = y * pSiS->CurrentLayout.displayWidth + x; 9292 switch(pSiS->CurrentLayout.bitsPerPixel) { 9293 case 16: base >>= 1; break; 9294 case 32: break; 9295 default: base >>= 2; 9296 } 9297 base += (pSiS->dhmOffset/4); 9298 SISSetStartAddressCRT1(pSiS, base); 9299} 9300 9301static void 9302SISAdjustFrameHW_CRT2(ScrnInfoPtr pScrn, int x, int y) 9303{ 9304 SISPtr pSiS = SISPTR(pScrn); 9305 ULong base; 9306 9307 base = y * pSiS->CurrentLayout.displayWidth + x; 9308 switch(pSiS->CurrentLayout.bitsPerPixel) { 9309 case 16: base >>= 1; break; 9310 case 32: break; 9311 default: base >>= 2; 9312 } 9313 base += (pSiS->dhmOffset/4); 9314 SISSetStartAddressCRT2(pSiS, base); 9315} 9316 9317static void 9318SISMergedPointerMoved(SCRN_ARG_TYPE arg, int x, int y) 9319{ 9320 SCRN_INFO_PTR(arg); 9321 ScrnInfoPtr pScrn1 = pScrn; 9322 SISPtr pSiS = SISPTR(pScrn1); 9323 ScrnInfoPtr pScrn2 = pSiS->CRT2pScrn; 9324 region out, in1, in2, f2, f1; 9325 int deltax, deltay; 9326 int temp1, temp2; 9327 int old1x0, old1y0, old2x0, old2y0; 9328 int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; 9329 int HVirt = pScrn1->virtualX; 9330 int VVirt = pScrn1->virtualY; 9331 int sigstate; 9332 Bool doit = FALSE, HaveNonRect = FALSE, HaveOffsRegions = FALSE; 9333 SiSScrn2Rel srel = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT2Position; 9334 9335 if(pSiS->DGAactive) { 9336 return; 9337 /* DGA: There is no cursor and no panning while DGA is active. */ 9338 /* If it were, we would need to do: */ 9339 /* HVirt = pSiS->CurrentLayout.displayWidth; 9340 VVirt = pSiS->CurrentLayout.displayHeight; 9341 BOUND(x, pSiS->CurrentLayout.DGAViewportX, HVirt); 9342 BOUND(y, pSiS->CurrentLayout.DGAViewportY, VVirt); */ 9343 } else { 9344 CRT1XOffs = pSiS->CRT1XOffs; 9345 CRT1YOffs = pSiS->CRT1YOffs; 9346 CRT2XOffs = pSiS->CRT2XOffs; 9347 CRT2YOffs = pSiS->CRT2YOffs; 9348 HaveNonRect = pSiS->HaveNonRect; 9349 HaveOffsRegions = pSiS->HaveOffsRegions; 9350 } 9351 9352 /* Check if the pointer is inside our dead areas */ 9353 if((pSiS->MouseRestrictions) && (srel != sisClone) && !SiSnoPanoramiXExtension) { 9354 if(HaveNonRect) { 9355 if(InRegion(x, y, pSiS->NonRectDead)) { 9356 switch(srel) { 9357 case sisLeftOf: 9358 case sisRightOf: y = pSiS->NonRectDead.y0 - 1; 9359 doit = TRUE; 9360 break; 9361 case sisAbove: 9362 case sisBelow: x = pSiS->NonRectDead.x0 - 1; 9363 doit = TRUE; 9364 default: break; 9365 } 9366 } 9367 } 9368 if(HaveOffsRegions) { 9369 if(InRegion(x, y, pSiS->OffDead1)) { 9370 switch(srel) { 9371 case sisLeftOf: 9372 case sisRightOf: y = pSiS->OffDead1.y1; 9373 doit = TRUE; 9374 break; 9375 case sisAbove: 9376 case sisBelow: x = pSiS->OffDead1.x1; 9377 doit = TRUE; 9378 default: break; 9379 } 9380 } else if(InRegion(x, y, pSiS->OffDead2)) { 9381 switch(srel) { 9382 case sisLeftOf: 9383 case sisRightOf: y = pSiS->OffDead2.y0 - 1; 9384 doit = TRUE; 9385 break; 9386 case sisAbove: 9387 case sisBelow: x = pSiS->OffDead2.x0 - 1; 9388 doit = TRUE; 9389 default: break; 9390 } 9391 } 9392 } 9393 if(doit) { 9394#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 20 /* screw it */ 9395 sigstate = xf86BlockSIGIO(); 9396#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 15 9397 { 9398 double dx = x, dy = y; 9399 miPointerSetPosition(inputInfo.pointer, Absolute, &dx, &dy); 9400 x = (int)dx; 9401 y = (int)dy; 9402 } 9403#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 13 9404 miPointerSetPosition(inputInfo.pointer, Absolute, &x, &y); 9405#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 5 9406 miPointerSetPosition(inputInfo.pointer, &x, &y); 9407#else 9408 UpdateCurrentTime(); 9409 miPointerAbsoluteCursor(x, y, currentTime.milliseconds); 9410#endif 9411 xf86UnblockSIGIO(sigstate); 9412#endif 9413 return; 9414 } 9415 } 9416 9417 f1.x0 = old1x0 = pSiS->CRT1frameX0; 9418 f1.x1 = pSiS->CRT1frameX1; 9419 f1.y0 = old1y0 = pSiS->CRT1frameY0; 9420 f1.y1 = pSiS->CRT1frameY1; 9421 f2.x0 = old2x0 = pScrn2->frameX0; 9422 f2.x1 = pScrn2->frameX1; 9423 f2.y0 = old2y0 = pScrn2->frameY0; 9424 f2.y1 = pScrn2->frameY1; 9425 9426 /* Define the outer region. Crossing this causes all frames to move */ 9427 out.x0 = pScrn1->frameX0; 9428 out.x1 = pScrn1->frameX1; 9429 out.y0 = pScrn1->frameY0; 9430 out.y1 = pScrn1->frameY1; 9431 9432 /* 9433 * Define the inner sliding window. Being outsize both frames but 9434 * inside the outer clipping window will slide corresponding frame 9435 */ 9436 in1 = out; 9437 in2 = out; 9438 switch(srel) { 9439 case sisLeftOf: 9440 in1.x0 = f1.x0; 9441 in2.x1 = f2.x1; 9442 break; 9443 case sisRightOf: 9444 in1.x1 = f1.x1; 9445 in2.x0 = f2.x0; 9446 break; 9447 case sisBelow: 9448 in1.y1 = f1.y1; 9449 in2.y0 = f2.y0; 9450 break; 9451 case sisAbove: 9452 in1.y0 = f1.y0; 9453 in2.y1 = f2.y1; 9454 break; 9455 case sisClone: 9456 break; 9457 } 9458 9459 deltay = 0; 9460 deltax = 0; 9461 9462 if(InRegion(x, y, out)) { /* inside outer region */ 9463 9464 if(InRegion(x, y, in1) && !InRegion(x, y, f1)) { 9465 REBOUND(f1.x0, f1.x1, x); 9466 REBOUND(f1.y0, f1.y1, y); 9467 deltax = 1; 9468 } 9469 if(InRegion(x, y, in2) && !InRegion(x, y, f2)) { 9470 REBOUND(f2.x0, f2.x1, x); 9471 REBOUND(f2.y0, f2.y1, y); 9472 deltax = 1; 9473 } 9474 9475 } else { /* outside outer region */ 9476 9477 if(out.x0 > x) { 9478 deltax = x - out.x0; 9479 } 9480 if(out.x1 < x) { 9481 deltax = x - out.x1; 9482 } 9483 if(deltax) { 9484 pScrn1->frameX0 += deltax; 9485 pScrn1->frameX1 += deltax; 9486 f1.x0 += deltax; 9487 f1.x1 += deltax; 9488 f2.x0 += deltax; 9489 f2.x1 += deltax; 9490 } 9491 9492 if(out.y0 > y) { 9493 deltay = y - out.y0; 9494 } 9495 if(out.y1 < y) { 9496 deltay = y - out.y1; 9497 } 9498 if(deltay) { 9499 pScrn1->frameY0 += deltay; 9500 pScrn1->frameY1 += deltay; 9501 f1.y0 += deltay; 9502 f1.y1 += deltay; 9503 f2.y0 += deltay; 9504 f2.y1 += deltay; 9505 } 9506 9507 switch(srel) { 9508 case sisLeftOf: 9509 if(x >= f1.x0) { REBOUND(f1.y0, f1.y1, y); } 9510 if(x <= f2.x1) { REBOUND(f2.y0, f2.y1, y); } 9511 break; 9512 case sisRightOf: 9513 if(x <= f1.x1) { REBOUND(f1.y0, f1.y1, y); } 9514 if(x >= f2.x0) { REBOUND(f2.y0, f2.y1, y); } 9515 break; 9516 case sisBelow: 9517 if(y <= f1.y1) { REBOUND(f1.x0, f1.x1, x); } 9518 if(y >= f2.y0) { REBOUND(f2.x0, f2.x1, x); } 9519 break; 9520 case sisAbove: 9521 if(y >= f1.y0) { REBOUND(f1.x0, f1.x1, x); } 9522 if(y <= f2.y1) { REBOUND(f2.x0, f2.x1, x); } 9523 break; 9524 case sisClone: 9525 break; 9526 } 9527 9528 } 9529 9530 if(deltax || deltay) { 9531 pSiS->CRT1frameX0 = f1.x0; 9532 pSiS->CRT1frameY0 = f1.y0; 9533 pScrn2->frameX0 = f2.x0; 9534 pScrn2->frameY0 = f2.y0; 9535 9536 switch(srel) { 9537 case sisLeftOf: 9538 case sisRightOf: 9539 if(CRT1YOffs || CRT2YOffs || HaveNonRect) { 9540 if(pSiS->CRT1frameY0 != old1y0) { 9541 if(pSiS->CRT1frameY0 < CRT1YOffs) 9542 pSiS->CRT1frameY0 = CRT1YOffs; 9543 9544 temp1 = pSiS->CRT1frameY0 + CDMPTR->CRT1->VDisplay; 9545 temp2 = min((VVirt - CRT2YOffs), (CRT1YOffs + pSiS->MBXNR1YMAX)); 9546 if(temp1 > temp2) 9547 pSiS->CRT1frameY0 -= (temp1 - temp2); 9548 } 9549 if(pScrn2->frameY0 != old2y0) { 9550 if(pScrn2->frameY0 < CRT2YOffs) 9551 pScrn2->frameY0 = CRT2YOffs; 9552 9553 temp1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay; 9554 temp2 = min((VVirt - CRT1YOffs), (CRT2YOffs + pSiS->MBXNR2YMAX)); 9555 if(temp1 > temp2) 9556 pScrn2->frameY0 -= (temp1 - temp2); 9557 } 9558 } 9559 break; 9560 case sisBelow: 9561 case sisAbove: 9562 if(CRT1XOffs || CRT2XOffs || HaveNonRect) { 9563 if(pSiS->CRT1frameX0 != old1x0) { 9564 if(pSiS->CRT1frameX0 < CRT1XOffs) 9565 pSiS->CRT1frameX0 = CRT1XOffs; 9566 9567 temp1 = pSiS->CRT1frameX0 + CDMPTR->CRT1->HDisplay; 9568 temp2 = min((HVirt - CRT2XOffs), (CRT1XOffs + pSiS->MBXNR1XMAX)); 9569 if(temp1 > temp2) 9570 pSiS->CRT1frameX0 -= (temp1 - temp2); 9571 } 9572 if(pScrn2->frameX0 != old2x0) { 9573 if(pScrn2->frameX0 < CRT2XOffs) 9574 pScrn2->frameX0 = CRT2XOffs; 9575 9576 temp1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay; 9577 temp2 = min((HVirt - CRT1XOffs), (CRT2XOffs + pSiS->MBXNR2XMAX)); 9578 if(temp1 > temp2) 9579 pScrn2->frameX0 -= (temp1 - temp2); 9580 } 9581 } 9582 break; 9583 case sisClone: 9584 break; 9585 } 9586 9587 pSiS->CRT1frameX1 = pSiS->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1; 9588 pSiS->CRT1frameY1 = pSiS->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1; 9589 pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1; 9590 pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1; 9591 9592 /* No need to update pScrn1->frame?1, done above */ 9593 9594 SISAdjustFrameHW_CRT1(pScrn1, pSiS->CRT1frameX0, pSiS->CRT1frameY0); 9595 SISAdjustFrameHW_CRT2(pScrn1, pScrn2->frameX0, pScrn2->frameY0); 9596 } 9597} 9598 9599static void 9600SISAdjustFrameMerged(ADJUST_FRAME_ARGS_DECL) 9601{ 9602 SCRN_INFO_PTR(arg); 9603 ScrnInfoPtr pScrn1 = pScrn; 9604 SISPtr pSiS = SISPTR(pScrn1); 9605 ScrnInfoPtr pScrn2 = pSiS->CRT2pScrn; 9606 int HTotal = pSiS->CurrentLayout.mode->HDisplay; 9607 int VTotal = pSiS->CurrentLayout.mode->VDisplay; 9608 int HMax = HTotal; 9609 int VMax = VTotal; 9610 int HVirt = pScrn1->virtualX; 9611 int VVirt = pScrn1->virtualY; 9612 int x1 = x, x2 = x; 9613 int y1 = y, y2 = y; 9614 int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; 9615 int MBXNR1XMAX = 65536, MBXNR1YMAX = 65536, MBXNR2XMAX = 65536, MBXNR2YMAX = 65536; 9616 9617 if(pSiS->DGAactive) { 9618 HVirt = pSiS->CurrentLayout.displayWidth; 9619 VVirt = pSiS->CurrentLayout.displayHeight; 9620 } else { 9621 CRT1XOffs = pSiS->CRT1XOffs; 9622 CRT1YOffs = pSiS->CRT1YOffs; 9623 CRT2XOffs = pSiS->CRT2XOffs; 9624 CRT2YOffs = pSiS->CRT2YOffs; 9625 MBXNR1XMAX = pSiS->MBXNR1XMAX; 9626 MBXNR1YMAX = pSiS->MBXNR1YMAX; 9627 MBXNR2XMAX = pSiS->MBXNR2XMAX; 9628 MBXNR2YMAX = pSiS->MBXNR2YMAX; 9629 } 9630 9631 BOUND(x, 0, HVirt - HTotal); 9632 BOUND(y, 0, VVirt - VTotal); 9633 if(SDMPTR(pScrn1)->CRT2Position != sisClone) { 9634 BOUND(x1, CRT1XOffs, min(HVirt, MBXNR1XMAX + CRT1XOffs) - min(HTotal, MBXNR1XMAX) - CRT2XOffs); 9635 BOUND(y1, CRT1YOffs, min(VVirt, MBXNR1YMAX + CRT1YOffs) - min(VTotal, MBXNR1YMAX) - CRT2YOffs); 9636 BOUND(x2, CRT2XOffs, min(HVirt, MBXNR2XMAX + CRT2XOffs) - min(HTotal, MBXNR2XMAX) - CRT1XOffs); 9637 BOUND(y2, CRT2YOffs, min(VVirt, MBXNR2YMAX + CRT2YOffs) - min(VTotal, MBXNR2YMAX) - CRT1YOffs); 9638 } 9639 9640 switch(SDMPTR(pScrn1)->CRT2Position) { 9641 case sisLeftOf: 9642 pScrn2->frameX0 = x2; 9643 BOUND(pScrn2->frameY0, y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR->CRT2->VDisplay); 9644 pSiS->CRT1frameX0 = x1 + CDMPTR->CRT2->HDisplay; 9645 BOUND(pSiS->CRT1frameY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR->CRT1->VDisplay); 9646 break; 9647 case sisRightOf: 9648 pSiS->CRT1frameX0 = x1; 9649 BOUND(pSiS->CRT1frameY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR->CRT1->VDisplay); 9650 pScrn2->frameX0 = x2 + CDMPTR->CRT1->HDisplay; 9651 BOUND(pScrn2->frameY0, y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR->CRT2->VDisplay); 9652 break; 9653 case sisAbove: 9654 BOUND(pScrn2->frameX0, x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR->CRT2->HDisplay); 9655 pScrn2->frameY0 = y2; 9656 BOUND(pSiS->CRT1frameX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR->CRT1->HDisplay); 9657 pSiS->CRT1frameY0 = y1 + CDMPTR->CRT2->VDisplay; 9658 break; 9659 case sisBelow: 9660 BOUND(pSiS->CRT1frameX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR->CRT1->HDisplay); 9661 pSiS->CRT1frameY0 = y1; 9662 BOUND(pScrn2->frameX0, x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR->CRT2->HDisplay); 9663 pScrn2->frameY0 = y2 + CDMPTR->CRT1->VDisplay; 9664 break; 9665 case sisClone: 9666 BOUND(pSiS->CRT1frameX0, x, x + HMax - CDMPTR->CRT1->HDisplay); 9667 BOUND(pSiS->CRT1frameY0, y, y + VMax - CDMPTR->CRT1->VDisplay); 9668 BOUND(pScrn2->frameX0, x, x + HMax - CDMPTR->CRT2->HDisplay); 9669 BOUND(pScrn2->frameY0, y, y + VMax - CDMPTR->CRT2->VDisplay); 9670 break; 9671 } 9672 9673 BOUND(pSiS->CRT1frameX0, 0, HVirt - CDMPTR->CRT1->HDisplay); 9674 BOUND(pSiS->CRT1frameY0, 0, VVirt - CDMPTR->CRT1->VDisplay); 9675 BOUND(pScrn2->frameX0, 0, HVirt - CDMPTR->CRT2->HDisplay); 9676 BOUND(pScrn2->frameY0, 0, VVirt - CDMPTR->CRT2->VDisplay); 9677 9678 pScrn1->frameX0 = x; 9679 pScrn1->frameY0 = y; 9680 9681 pSiS->CRT1frameX1 = pSiS->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1; 9682 pSiS->CRT1frameY1 = pSiS->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1; 9683 pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1; 9684 pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1; 9685 9686 pScrn1->frameX1 = pScrn1->frameX0 + pSiS->CurrentLayout.mode->HDisplay - 1; 9687 pScrn1->frameY1 = pScrn1->frameY0 + pSiS->CurrentLayout.mode->VDisplay - 1; 9688 if(SDMPTR(pScrn1)->CRT2Position != sisClone) { 9689 pScrn1->frameX1 += CRT1XOffs + CRT2XOffs; 9690 pScrn1->frameY1 += CRT1YOffs + CRT2YOffs; 9691 } 9692 9693 SISAdjustFrameHW_CRT1(pScrn1, pSiS->CRT1frameX0, pSiS->CRT1frameY0); 9694 SISAdjustFrameHW_CRT2(pScrn1, pScrn2->frameX0, pScrn2->frameY0); 9695} 9696#endif 9697 9698/* 9699 * This function is used to initialize the Start Address - the first 9700 * displayed location in the video memory. 9701 * 9702 * Usually mandatory 9703 */ 9704void 9705SISAdjustFrame(ADJUST_FRAME_ARGS_DECL) 9706{ 9707 SCRN_INFO_PTR(arg); 9708 SISPtr pSiS = SISPTR(pScrn); 9709 ULong base; 9710 UChar temp, cr11backup; 9711 9712#ifdef SISMERGED 9713 if(pSiS->MergedFB) { 9714 SISAdjustFrameMerged(ADJUST_FRAME_ARGS(pScrn, x, y)); 9715 return; 9716 } 9717#endif 9718 9719 if(pSiS->UseVESA) { 9720 VBESetDisplayStart(pSiS->pVbe, x, y, TRUE); 9721 return; 9722 } 9723 9724 if(pScrn->bitsPerPixel < 8) { 9725 base = (y * pSiS->CurrentLayout.displayWidth + x + 3) >> 3; 9726 } else { 9727 base = y * pSiS->CurrentLayout.displayWidth + x; 9728 9729 /* calculate base bpp dep. */ 9730 switch(pSiS->CurrentLayout.bitsPerPixel) { 9731 case 16: 9732 base >>= 1; 9733 break; 9734 case 24: 9735 base = ((base * 3)) >> 2; 9736 base -= base % 6; 9737 break; 9738 case 32: 9739 break; 9740 default: /* 8bpp */ 9741 base >>= 2; 9742 break; 9743 } 9744 } 9745 9746#ifdef UNLOCK_ALWAYS 9747 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 9748#endif 9749 9750 base += (pSiS->dhmOffset/4); 9751 9752#ifdef TWDEBUG 9753 xf86DrvMsg(0, 0, "AdjustFrame: x %d y %d bpp %d dw %d base %d, dhmOffset %d\n", 9754 x, y, pSiS->CurrentLayout.bitsPerPixel, pSiS->CurrentLayout.displayWidth, base, pSiS->dhmOffset); 9755#endif 9756 9757#ifdef SISDUALHEAD 9758 if(pSiS->DualHeadMode) { 9759 if(!pSiS->SecondHead) { 9760 /* Head 1 (master) is always CRT2 */ 9761 SISSetStartAddressCRT2(pSiS, base); 9762 } else { 9763 /* Head 2 (slave) is always CRT1 */ 9764 SISSetStartAddressCRT1(pSiS, base); 9765 } 9766 } else { 9767#endif 9768 switch(pSiS->VGAEngine) { 9769 case SIS_300_VGA: 9770 case SIS_315_VGA: 9771 SISSetStartAddressCRT1(pSiS, base); 9772 if(pSiS->VBFlags & CRT2_ENABLE) { 9773 if(!SiSBridgeIsInSlaveMode(pScrn)) { 9774 SISSetStartAddressCRT2(pSiS, base); 9775 } 9776 } 9777 break; 9778 default: 9779 /* Unlock CRTC registers */ 9780 inSISIDXREG(SISCR, 0x11, cr11backup); 9781 andSISIDXREG(SISCR, 0x11, 0x7F); 9782 outSISIDXREG(SISCR, 0x0D, base & 0xFF); 9783 outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); 9784 inSISIDXREG(SISSR, 0x27, temp); 9785 temp &= 0xF0; 9786 temp |= (base & 0x0F0000) >> 16; 9787 outSISIDXREG(SISSR, 0x27, temp); 9788 /* Eventually lock CRTC registers */ 9789 setSISIDXREG(SISCR, 0x11, 0x7F, (cr11backup & 0x80)); 9790 } 9791#ifdef SISDUALHEAD 9792 } 9793#endif 9794 9795} 9796 9797/* 9798 * This is called when VT switching back to the X server. Its job is 9799 * to reinitialise the video mode. 9800 * Mandatory! 9801 */ 9802static Bool 9803SISEnterVT(VT_FUNC_ARGS_DECL) 9804{ 9805 SCRN_INFO_PTR(arg); 9806 SISPtr pSiS = SISPTR(pScrn); 9807 9808 SiS_SiSFB_Lock(pScrn, TRUE); 9809 9810 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 9811 9812 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 9813 outSISIDXREG(SISCR,0x32,pSiS->myCR32); 9814 outSISIDXREG(SISCR,0x36,pSiS->myCR36); 9815 outSISIDXREG(SISCR,0x37,pSiS->myCR37); 9816 } 9817 9818 if(!SISModeInit(pScrn, pScrn->currentMode)) { 9819 SISErrorLog(pScrn, "SiSEnterVT: SISModeInit() failed\n"); 9820 return FALSE; 9821 } 9822 9823 SISAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 9824 9825#ifdef SISDRI 9826 if(pSiS->directRenderingEnabled) { 9827 DRIUnlock(xf86ScrnToScreen(pScrn)); 9828 } 9829#endif 9830 9831#ifdef SISDUALHEAD 9832 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) 9833#endif 9834 if(pSiS->ResetXv) { 9835 (pSiS->ResetXv)(pScrn); 9836 } 9837 9838 return TRUE; 9839} 9840 9841/* 9842 * This is called when VT switching away from the X server. Its job is 9843 * to restore the previous (text) mode. 9844 * Mandatory! 9845 */ 9846static void 9847SISLeaveVT(VT_FUNC_ARGS_DECL) 9848{ 9849 SCRN_INFO_PTR(arg); 9850 SISPtr pSiS = SISPTR(pScrn); 9851#ifdef SISDRI 9852 ScreenPtr pScreen; 9853 9854 if(pSiS->directRenderingEnabled) { 9855 pScreen = xf86ScrnToScreen(pScrn); 9856 DRILock(pScreen, 0); 9857 } 9858#endif 9859 9860#ifdef SISDUALHEAD 9861 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 9862#endif 9863 9864 if(pSiS->CursorInfoPtr) { 9865#ifdef SISDUALHEAD 9866 if(pSiS->DualHeadMode) { 9867 if(!pSiS->SecondHead) { 9868 pSiS->ForceCursorOff = TRUE; 9869 pSiS->CursorInfoPtr->HideCursor(pScrn); 9870 SISWaitVBRetrace(pScrn); 9871 pSiS->ForceCursorOff = FALSE; 9872 } 9873 } else { 9874#endif 9875 pSiS->CursorInfoPtr->HideCursor(pScrn); 9876 SISWaitVBRetrace(pScrn); 9877#ifdef SISDUALHEAD 9878 } 9879#endif 9880 } 9881 9882 SISBridgeRestore(pScrn); 9883 9884 if(pSiS->UseVESA) { 9885 9886 /* This is a q&d work-around for a BIOS bug. In case we disabled CRT2, 9887 * VBESaveRestore() does not restore CRT1. So we set any mode now, 9888 * because VBESetVBEMode correctly restores CRT1. Afterwards, we 9889 * can call VBESaveRestore to restore original mode. 9890 */ 9891 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (!(pSiS->VBFlags & DISPTYPE_DISP2))) 9892 VBESetVBEMode(pSiS->pVbe, (pSiS->SISVESAModeList->n) | 0xc000, NULL); 9893 9894 SISVESARestore(pScrn); 9895 9896 } else { 9897 9898 SISRestore(pScrn); 9899 9900 } 9901 9902 /* We use (otherwise unused) bit 7 to indicate that we are running 9903 * to keep sisfb to change the displaymode (this would result in 9904 * lethal display corruption upon quitting X or changing to a VT 9905 * until a reboot) 9906 */ 9907 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 9908 orSISIDXREG(SISCR,0x34,0x80); 9909 } 9910 9911 SISVGALock(pSiS); 9912 9913 SiS_SiSFB_Lock(pScrn, FALSE); 9914} 9915 9916 9917/* 9918 * This is called at the end of each server generation. It restores the 9919 * original (text) mode. It should really also unmap the video memory too. 9920 * Mandatory! 9921 */ 9922static Bool 9923SISCloseScreen(CLOSE_SCREEN_ARGS_DECL) 9924{ 9925 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 9926 SISPtr pSiS = SISPTR(pScrn); 9927#ifdef SISDUALHEAD 9928 SISEntPtr pSiSEnt = pSiS->entityPrivate; 9929#endif 9930 9931 if(pSiS->SiSCtrlExtEntry) { 9932 SiSCtrlExtUnregister(pSiS, pScrn->scrnIndex); 9933 } 9934 9935#ifdef SISDRI 9936 if(pSiS->directRenderingEnabled) { 9937 SISDRICloseScreen(pScreen); 9938 pSiS->directRenderingEnabled = FALSE; 9939 } 9940#endif 9941 9942 if(pScrn->vtSema) { 9943 9944 if(pSiS->CursorInfoPtr) { 9945#ifdef SISDUALHEAD 9946 if(pSiS->DualHeadMode) { 9947 if(!pSiS->SecondHead) { 9948 pSiS->ForceCursorOff = TRUE; 9949 pSiS->CursorInfoPtr->HideCursor(pScrn); 9950 SISWaitVBRetrace(pScrn); 9951 pSiS->ForceCursorOff = FALSE; 9952 } 9953 } else { 9954#endif 9955 pSiS->CursorInfoPtr->HideCursor(pScrn); 9956 SISWaitVBRetrace(pScrn); 9957#ifdef SISDUALHEAD 9958 } 9959#endif 9960 } 9961 9962 SISBridgeRestore(pScrn); 9963 9964 if(pSiS->UseVESA) { 9965 9966 /* This is a q&d work-around for a BIOS bug. In case we disabled CRT2, 9967 * VBESaveRestore() does not restore CRT1. So we set any mode now, 9968 * because VBESetVBEMode correctly restores CRT1. Afterwards, we 9969 * can call VBESaveRestore to restore original mode. 9970 */ 9971 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (!(pSiS->VBFlags & DISPTYPE_DISP2))) 9972 VBESetVBEMode(pSiS->pVbe, (pSiS->SISVESAModeList->n) | 0xc000, NULL); 9973 9974 SISVESARestore(pScrn); 9975 9976 } else { 9977 9978 SISRestore(pScrn); 9979 9980 } 9981 9982 SISVGALock(pSiS); 9983 9984 } 9985 9986 SiS_SiSFB_Lock(pScrn, FALSE); 9987 9988 /* We should restore the mode number in case vtsema = false as well, 9989 * but since we haven't register access then we can't do it. I think 9990 * I need to rework the save/restore stuff, like saving the video 9991 * status when returning to the X server and by that save me the 9992 * trouble if sisfb was started from a textmode VT while X was on. 9993 */ 9994 9995 SISUnmapMem(pScrn); 9996#ifdef SIS_PC_PLATFORM 9997 SiSVGAUnmapMem(pScrn); 9998#endif 9999 10000#ifdef SISDUALHEAD 10001 if(pSiS->DualHeadMode) { 10002 pSiSEnt = pSiS->entityPrivate; 10003 pSiSEnt->refCount--; 10004 } 10005#endif 10006 10007 if(pSiS->pInt) { 10008 xf86FreeInt10(pSiS->pInt); 10009 pSiS->pInt = NULL; 10010 } 10011 10012#ifdef SIS_USE_XAA 10013 if(!pSiS->useEXA) { 10014 if(pSiS->AccelLinearScratch) { 10015 xf86FreeOffscreenLinear(pSiS->AccelLinearScratch); 10016 pSiS->AccelLinearScratch = NULL; 10017 } 10018 if(pSiS->AccelInfoPtr) { 10019 XAADestroyInfoRec(pSiS->AccelInfoPtr); 10020 pSiS->AccelInfoPtr = NULL; 10021 } 10022 } 10023#endif 10024 10025#ifdef SIS_USE_EXA 10026 if(pSiS->useEXA) { 10027 if(pSiS->EXADriverPtr) { 10028 exaDriverFini(pScreen); 10029 free(pSiS->EXADriverPtr); 10030 pSiS->EXADriverPtr = NULL; 10031 pSiS->exa_scratch = NULL; 10032 } 10033 } 10034#endif 10035 10036 if(pSiS->CursorInfoPtr) { 10037 xf86DestroyCursorInfoRec(pSiS->CursorInfoPtr); 10038 pSiS->CursorInfoPtr = NULL; 10039 } 10040 10041 if(pSiS->ShadowPtr) { 10042 free(pSiS->ShadowPtr); 10043 pSiS->ShadowPtr = NULL; 10044 } 10045 10046 if(pSiS->DGAModes) { 10047 free(pSiS->DGAModes); 10048 pSiS->DGAModes = NULL; 10049 } 10050 10051 if(pSiS->adaptor) { 10052 free(pSiS->adaptor); 10053 pSiS->adaptor = NULL; 10054 pSiS->ResetXv = pSiS->ResetXvGamma = pSiS->ResetXvDisplay = NULL; 10055 } 10056 10057 if(pSiS->blitadaptor) { 10058 free(pSiS->blitadaptor); 10059 pSiS->blitadaptor = NULL; 10060 } 10061 10062 if(pSiS->crt2gcolortable) { 10063 free(pSiS->crt2gcolortable); 10064 pSiS->crt2gcolortable = NULL; 10065 } 10066 10067 if(pSiS->crt2cindices) { 10068 free(pSiS->crt2cindices); 10069 pSiS->crt2cindices = NULL; 10070 } 10071 10072 pScrn->vtSema = FALSE; 10073 10074 /* Restore Blockhandler */ 10075 pScreen->BlockHandler = pSiS->BlockHandler; 10076 10077 pScreen->CloseScreen = pSiS->CloseScreen; 10078 10079 return(*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); 10080} 10081 10082 10083/* Free up any per-generation data structures */ 10084 10085/* Optional */ 10086static void 10087SISFreeScreen(FREE_SCREEN_ARGS_DECL) 10088{ 10089 SCRN_INFO_PTR(arg); 10090#ifdef SIS_NEED_MAP_IOP 10091 SISPtr pSiS = SISPTR(pScrn); 10092 10093 if(pSiS) { 10094#ifdef SISDUALHEAD 10095 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10096 if(pSiSEnt) { 10097 pSiSEnt->forceUnmapIOPBase = TRUE; 10098 } 10099#endif 10100 SISUnmapIOPMem(pScrn); 10101 } 10102#endif 10103 10104 SISFreeRec(pScrn); 10105} 10106 10107 10108/* Checks if a mode is suitable for the selected chipset. */ 10109 10110static ModeStatus 10111SISValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 10112{ 10113 SCRN_INFO_PTR(arg); 10114 SISPtr pSiS = SISPTR(pScrn); 10115 10116 if(pSiS->UseVESA) { 10117 if(SiSCalcVESAModeIndex(pScrn, mode)) 10118 return(MODE_OK); 10119 else 10120 return(MODE_BAD); 10121 } 10122 10123 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 10124#ifdef SISDUALHEAD 10125 if(pSiS->DualHeadMode) { 10126 if(pSiS->SecondHead) { 10127 if(SiS_CheckModeCRT1(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10128 return(MODE_BAD); 10129 } else { 10130 if(SiS_CheckModeCRT2(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10131 return(MODE_BAD); 10132 } 10133 } else 10134#endif 10135#ifdef SISMERGED 10136 if(pSiS->MergedFB) { 10137 if(!mode->Private) { 10138 if(!pSiS->CheckForCRT2) { 10139 if(SiS_CheckModeCRT1(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10140 return(MODE_BAD); 10141 } else { 10142 if(SiS_CheckModeCRT2(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes2) < 0x14) 10143 return(MODE_BAD); 10144 } 10145 } else { 10146 if(SiS_CheckModeCRT1(pScrn, ((SiSMergedDisplayModePtr)mode->Private)->CRT1, 10147 pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10148 return(MODE_BAD); 10149 10150 if(SiS_CheckModeCRT2(pScrn, ((SiSMergedDisplayModePtr)mode->Private)->CRT2, 10151 pSiS->VBFlags, pSiS->HaveCustomModes2) < 0x14) 10152 return(MODE_BAD); 10153 } 10154 } else 10155#endif 10156 { 10157 if(SiS_CheckModeCRT1(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10158 return(MODE_BAD); 10159 10160 if(SiS_CheckModeCRT2(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10161 return(MODE_BAD); 10162 } 10163 } 10164 10165 return(MODE_OK); 10166} 10167 10168#ifdef DEBUG 10169static void 10170SiSDumpModeInfo(ScrnInfoPtr pScrn, DisplayModePtr mode) 10171{ 10172 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Clock : %x\n", mode->Clock); 10173 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Display : %x\n", mode->CrtcHDisplay); 10174 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Blank Start : %x\n", mode->CrtcHBlankStart); 10175 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Sync Start : %x\n", mode->CrtcHSyncStart); 10176 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Sync End : %x\n", mode->CrtcHSyncEnd); 10177 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Blank End : %x\n", mode->CrtcHBlankEnd); 10178 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Total : %x\n", mode->CrtcHTotal); 10179 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Skew : %x\n", mode->CrtcHSkew); 10180 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz HAdjusted : %x\n", mode->CrtcHAdjusted); 10181 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Display : %x\n", mode->CrtcVDisplay); 10182 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Blank Start : %x\n", mode->CrtcVBlankStart); 10183 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Sync Start : %x\n", mode->CrtcVSyncStart); 10184 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Sync End : %x\n", mode->CrtcVSyncEnd); 10185 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Blank End : %x\n", mode->CrtcVBlankEnd); 10186 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Total : %x\n", mode->CrtcVTotal); 10187 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt VAdjusted : %x\n", mode->CrtcVAdjusted); 10188} 10189#endif 10190 10191static void 10192SISModifyModeInfo(DisplayModePtr mode) 10193{ 10194 if(mode->CrtcHBlankStart == mode->CrtcHDisplay) 10195 mode->CrtcHBlankStart++; 10196 if(mode->CrtcHBlankEnd == mode->CrtcHTotal) 10197 mode->CrtcHBlankEnd--; 10198 if(mode->CrtcVBlankStart == mode->CrtcVDisplay) 10199 mode->CrtcVBlankStart++; 10200 if(mode->CrtcVBlankEnd == mode->CrtcVTotal) 10201 mode->CrtcVBlankEnd--; 10202} 10203 10204/* Enable the Turboqueue/Commandqueue (For 300 and 315/330/340 series only) */ 10205static void 10206SiSEnableTurboQueue(ScrnInfoPtr pScrn) 10207{ 10208 SISPtr pSiS = SISPTR(pScrn); 10209 UShort SR26, SR27; 10210 ULong temp; 10211 10212 switch(pSiS->VGAEngine) { 10213 case SIS_300_VGA: 10214 if((!pSiS->NoAccel) && (pSiS->TurboQueue)) { 10215 /* TQ size is always 512k */ 10216 temp = (pScrn->videoRam/64) - 8; 10217 SR26 = temp & 0xFF; 10218 inSISIDXREG(SISSR, 0x27, SR27); 10219 SR27 &= 0xFC; 10220 SR27 |= (0xF0 | ((temp >> 8) & 3)); 10221 outSISIDXREG(SISSR, 0x26, SR26); 10222 outSISIDXREG(SISSR, 0x27, SR27); 10223 } 10224 break; 10225 10226 case SIS_315_VGA: 10227 if(!pSiS->NoAccel) { 10228 /* On 315/330/340 series, there are three queue modes available 10229 * which are chosen by setting bits 7:5 in SR26: 10230 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep 10231 * track of the queue, the FIFO, command parsing and so 10232 * on. This is the one comparable to the 300 series. 10233 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will 10234 * have to do queue management himself. 10235 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the 10236 * queue in AGP memory space. 10237 * We go VRAM or MMIO here. 10238 * SR26 bit 4 is called "Bypass H/W queue". 10239 * SR26 bit 1 is called "Enable Command Queue Auto Correction" 10240 * SR26 bit 0 resets the queue 10241 * Size of queue memory is encoded in bits 3:2 like this: 10242 * 00 (0x00) 512K 10243 * 01 (0x04) 1M 10244 * 10 (0x08) 2M 10245 * 11 (0x0C) 4M 10246 * The queue location is to be written to 0x85C0. 10247 */ 10248#ifdef SISVRAMQ 10249 /* We use VRAM Cmd Queue, not MMIO or AGP */ 10250 UChar tempCR55 = 0; 10251 10252 /* Set Command Queue Threshold to max value 11111b (?) */ 10253 outSISIDXREG(SISSR, 0x27, 0x1F); 10254 10255 /* Disable queue flipping */ 10256 inSISIDXREG(SISCR, 0x55, tempCR55); 10257 andSISIDXREG(SISCR, 0x55, 0x33); 10258 /* Synchronous reset for Command Queue */ 10259 outSISIDXREG(SISSR, 0x26, 0x01); 10260 SIS_MMIO_OUT32(pSiS->IOBase, 0x85c4, 0); 10261 /* Enable VRAM Command Queue mode */ 10262 if(pSiS->ChipType == XGI_20) { 10263 /* On XGI_20, always 128K */ 10264 SR26 = 0x40 | 0x04 | 0x01; 10265 } else { 10266 switch(pSiS->cmdQueueSize) { 10267 case 1*1024*1024: SR26 = (0x40 | 0x04 | 0x01); break; 10268 case 2*1024*1024: SR26 = (0x40 | 0x08 | 0x01); break; 10269 case 4*1024*1024: SR26 = (0x40 | 0x0C | 0x01); break; 10270 default: 10271 pSiS->cmdQueueSize = 512 * 1024; 10272 case 512*1024: SR26 = (0x40 | 0x00 | 0x01); 10273 } 10274 } 10275 outSISIDXREG(SISSR, 0x26, SR26); 10276 SR26 &= 0xfe; 10277 outSISIDXREG(SISSR, 0x26, SR26); 10278 *(pSiS->cmdQ_SharedWritePort) = (unsigned int)(SIS_MMIO_IN32(pSiS->IOBase, 0x85c8)); 10279 SIS_MMIO_OUT32(pSiS->IOBase, 0x85c4, (CARD32)(*(pSiS->cmdQ_SharedWritePort))); 10280 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C0, pSiS->cmdQueueOffset); 10281 temp = (ULong)pSiS->RealFbBase; 10282#ifdef SISDUALHEAD 10283 if(pSiS->DualHeadMode) { 10284 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10285 temp = (ULong)pSiSEnt->RealFbBase; 10286 } 10287#endif 10288 temp += pSiS->cmdQueueOffset; 10289 pSiS->cmdQueueBase = (unsigned int *)temp; 10290 outSISIDXREG(SISCR, 0x55, tempCR55); 10291#ifdef TWDEBUG 10292 xf86DrvMsg(0, 0, "CmdQueueOffs 0x%x, CmdQueueAdd %p, shwrp 0x%x, status %x, base %p\n", 10293 pSiS->cmdQueueOffset, pSiS->cmdQueueBase, *(pSiS->cmdQ_SharedWritePort), 10294 SIS_MMIO_IN32(pSiS->IOBase, 0x85cc), (ULong *)temp); 10295#endif 10296#else 10297 /* For MMIO */ 10298 /* Syncronous reset for Command Queue */ 10299 orSISIDXREG(SISSR, 0x26, 0x01); 10300 /* Set Command Queue Threshold to max value 11111b */ 10301 outSISIDXREG(SISSR, 0x27, 0x1F); 10302 /* Do some magic (cp readport to writeport) */ 10303 temp = SIS_MMIO_IN32(pSiS->IOBase, 0x85C8); 10304 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C4, temp); 10305 /* Enable MMIO Command Queue mode (0x20), 10306 * Enable_command_queue_auto_correction (0x02) 10307 * (no idea, but sounds good, so use it) 10308 * 512k (0x00) (does this apply to MMIO mode?) */ 10309 outSISIDXREG(SISSR, 0x26, 0x22); 10310 /* Calc Command Queue position (Q is always 512k)*/ 10311 temp = (pScrn->videoRam - 512) * 1024; 10312 /* Set Q position */ 10313 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C0, temp); 10314#endif 10315 } 10316 break; 10317 default: 10318 break; 10319 } 10320} 10321 10322#ifdef SISVRAMQ 10323static void 10324SiSRestoreQueueMode(SISPtr pSiS, SISRegPtr sisReg) 10325{ 10326 UChar tempCR55=0; 10327 10328 if(pSiS->VGAEngine == SIS_315_VGA) { 10329 inSISIDXREG(SISCR,0x55,tempCR55); 10330 andSISIDXREG(SISCR,0x55,0x33); 10331 outSISIDXREG(SISSR,0x26,0x01); 10332 SIS_MMIO_OUT32(pSiS->IOBase, 0x85c4, 0); 10333 outSISIDXREG(SISSR,0x27,sisReg->sisRegs3C4[0x27]); 10334 outSISIDXREG(SISSR,0x26,sisReg->sisRegs3C4[0x26]); 10335 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C0, sisReg->sisMMIO85C0); 10336 outSISIDXREG(SISCR,0x55,tempCR55); 10337 } 10338} 10339#endif 10340 10341/* Things to do before a ModeSwitch. We set up the 10342 * video bridge configuration and the TurboQueue. 10343 */ 10344void SiSPreSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode, int viewmode) 10345{ 10346 SISPtr pSiS = SISPTR(pScrn); 10347 UChar CR30, CR31, CR32, CR33; 10348 UChar CR39 = 0, CR3B = 0; 10349 UChar CR17, CR38 = 0; 10350 UChar CR35 = 0, CR79 = 0; 10351 int temp = 0, crt1rateindex = 0; 10352 ULong vbflag = pSiS->VBFlags; 10353 Bool hcm = pSiS->HaveCustomModes; 10354 DisplayModePtr mymode = mode; 10355 10356 pSiS->IsCustom = FALSE; 10357 10358 /* NEVER call this with viewmode = SIS_MODE_SIMU 10359 * if mode->type is not M_T_DEFAULT! 10360 */ 10361 10362#ifdef SISMERGED 10363 if(pSiS->MergedFB) { 10364 switch(viewmode) { 10365 case SIS_MODE_CRT1: 10366 mymode = ((SiSMergedDisplayModePtr)mode->Private)->CRT1; 10367 break; 10368 case SIS_MODE_CRT2: 10369 mymode = ((SiSMergedDisplayModePtr)mode->Private)->CRT2; 10370 hcm = pSiS->HaveCustomModes2; 10371 } 10372 } 10373#endif 10374 10375 switch(viewmode) { 10376 case SIS_MODE_CRT1: 10377 if(SiS_CheckModeCRT1(pScrn, mymode, vbflag, hcm) == 0xfe) { 10378 pSiS->IsCustom = TRUE; 10379 } 10380 break; 10381 case SIS_MODE_CRT2: 10382 if(vbflag & CRT2_ENABLE) { 10383 if(SiS_CheckModeCRT2(pScrn, mymode, vbflag, hcm) == 0xfe) { 10384 pSiS->IsCustom = TRUE; 10385 } 10386 } else { 10387 /* This can only happen in mirror mode */ 10388 if(SiS_CheckModeCRT1(pScrn, mymode, vbflag, hcm) == 0xfe) { 10389 pSiS->IsCustom = TRUE; 10390 } 10391 } 10392 } 10393 10394#ifdef UNLOCK_ALWAYS 10395 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); /* Unlock Registers */ 10396#endif 10397 10398 inSISIDXREG(SISCR, 0x30, CR30); 10399 inSISIDXREG(SISCR, 0x31, CR31); 10400 CR32 = pSiS->newCR32; 10401 inSISIDXREG(SISCR, 0x33, CR33); 10402 10403 if(pSiS->NewCRLayout) { 10404 10405 inSISIDXREG(SISCR, 0x35, CR35); 10406 inSISIDXREG(SISCR, 0x38, CR38); 10407 inSISIDXREG(SISCR, 0x39, CR39); 10408 10409 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, SISVERBLEVEL, 10410 "Before: CR30=0x%02x,CR31=0x%02x,CR32=0x%02x,CR33=0x%02x,CR35=0x%02x,CR38=0x%02x\n", 10411 CR30, CR31, CR32, CR33, CR35, CR38); 10412 10413 CR38 &= ~0x07; 10414 10415 } else { 10416 10417 if(pSiS->Chipset != PCI_CHIP_SIS300) { 10418 switch(pSiS->VGAEngine) { 10419 case SIS_300_VGA: temp = 0x35; break; 10420 case SIS_315_VGA: temp = 0x38; break; 10421 } 10422 if(temp) inSISIDXREG(SISCR, temp, CR38); 10423 } 10424 if(pSiS->VGAEngine == SIS_315_VGA) { 10425 inSISIDXREG(SISCR, 0x79, CR79); 10426 CR38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */ 10427 } 10428 inSISIDXREG(SISCR, 0x3b, CR3B); 10429 10430 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, SISVERBLEVEL, 10431 "Before: CR30=0x%02x, CR31=0x%02x, CR32=0x%02x, CR33=0x%02x, CR%02x=0x%02x\n", 10432 CR30, CR31, CR32, CR33, temp, CR38); 10433 } 10434 10435 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, SISVERBLEVEL, "VBFlags=0x%x\n", pSiS->VBFlags); 10436 10437 CR30 = 0x00; 10438 CR31 &= ~0x60; /* Clear VB_Drivermode & VB_OutputDisable */ 10439 CR31 |= 0x04; /* Set VB_NotSimuMode (not for 30xB/1400x1050?) */ 10440 CR35 = 0x00; 10441 10442 if(!pSiS->NewCRLayout) { 10443 if(!pSiS->AllowHotkey) { 10444 CR31 |= 0x80; /* Disable hotkey-switch */ 10445 } 10446 CR79 &= ~0x10; /* Enable Backlight control on 315 series */ 10447 } 10448 10449 SiS_SetEnableDstn(pSiS->SiS_Pr, FALSE); 10450 SiS_SetEnableFstn(pSiS->SiS_Pr, FALSE); 10451 10452 if((vbflag & CRT1_LCDA) && (viewmode == SIS_MODE_CRT1)) { 10453 10454 CR38 |= 0x02; 10455 10456 } else { 10457 10458 switch(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA)) { 10459 10460 case CRT2_TV: 10461 10462 CR38 &= ~0xC0; /* Clear Pal M/N bits */ 10463 10464 if((pSiS->VBFlags2 & VB2_CHRONTEL) && (vbflag & TV_CHSCART)) { /* Chrontel */ 10465 CR30 |= 0x10; 10466 CR38 |= 0x04; 10467 CR38 &= ~0x08; 10468 CR31 |= 0x01; 10469 } else if((pSiS->VBFlags2 & VB2_CHRONTEL) && (vbflag & TV_CHYPBPR525I)) { /* Chrontel */ 10470 CR38 |= 0x08; 10471 CR38 &= ~0x04; 10472 CR31 &= ~0x01; 10473 } else if(vbflag & TV_HIVISION) { /* SiS bridge */ 10474 if(pSiS->NewCRLayout) { 10475 CR38 |= 0x04; 10476 CR35 |= 0x60; 10477 } else { 10478 CR30 |= 0x80; 10479 if(pSiS->VGAEngine == SIS_315_VGA) { 10480 if(pSiS->VBFlags2 & VB2_SISYPBPRBRIDGE) { 10481 CR38 |= (0x08 | 0x30); 10482 } 10483 } 10484 } 10485 CR31 |= 0x01; 10486 CR35 |= 0x01; 10487 } else if(vbflag & TV_YPBPR) { /* SiS bridge */ 10488 if(pSiS->NewCRLayout) { 10489 CR38 |= 0x04; 10490 CR31 &= ~0x01; 10491 CR35 &= ~0x01; 10492 if(vbflag & (TV_YPBPR525P | TV_YPBPR625P)) CR35 |= 0x20; 10493 else if(vbflag & TV_YPBPR750P) CR35 |= 0x40; 10494 else if(vbflag & TV_YPBPR1080I) CR35 |= 0x60; 10495 10496 if(vbflag & (TV_YPBPR625I | TV_YPBPR625P)) { 10497 CR31 |= 0x01; 10498 CR35 |= 0x01; 10499 } 10500 10501 CR39 &= ~0x03; 10502 if((vbflag & TV_YPBPRAR) == TV_YPBPR43LB) CR39 |= 0x00; 10503 else if((vbflag & TV_YPBPRAR) == TV_YPBPR43) CR39 |= 0x01; 10504 else if((vbflag & TV_YPBPRAR) == TV_YPBPR169) CR39 |= 0x02; 10505 else CR39 |= 0x03; 10506 } else if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR) { 10507 CR30 |= 0x80; 10508 CR38 |= 0x08; 10509 CR31 &= ~0x01; 10510 if(vbflag & (TV_YPBPR525P|TV_YPBPR625P)) CR38 |= 0x10; 10511 else if(vbflag & TV_YPBPR750P) CR38 |= 0x20; 10512 else if(vbflag & TV_YPBPR1080I) CR38 |= 0x30; 10513 10514 if(vbflag & (TV_YPBPR625I | TV_YPBPR625P)) CR31 |= 0x01; 10515 10516 if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPRAR) { 10517 CR3B &= ~0x03; 10518 if((vbflag & TV_YPBPRAR) == TV_YPBPR43LB) CR3B |= 0x00; 10519 else if((vbflag & TV_YPBPRAR) == TV_YPBPR43) CR3B |= 0x03; 10520 else if((vbflag & TV_YPBPRAR) == TV_YPBPR169) CR3B |= 0x01; 10521 else CR3B |= 0x03; 10522 } 10523 } 10524 } else { /* All */ 10525 if(vbflag & TV_SCART) CR30 |= 0x10; 10526 if(vbflag & TV_SVIDEO) CR30 |= 0x08; 10527 if(vbflag & TV_AVIDEO) CR30 |= 0x04; 10528 if(!(CR30 & 0x1C)) CR30 |= 0x08; /* default: SVIDEO */ 10529 10530 if(vbflag & TV_PAL) { 10531 CR31 |= 0x01; 10532 CR35 |= 0x01; 10533 if( (pSiS->VBFlags2 & VB2_SISBRIDGE) || 10534 ((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->ChrontelType == CHRONTEL_701x)) ) { 10535 if(vbflag & TV_PALM) { 10536 CR38 |= 0x40; 10537 CR35 |= 0x04; 10538 } else if(vbflag & TV_PALN) { 10539 CR38 |= 0x80; 10540 CR35 |= 0x08; 10541 } 10542 } 10543 } else { 10544 CR31 &= ~0x01; 10545 CR35 &= ~0x01; 10546 if(vbflag & TV_NTSCJ) { 10547 CR38 |= 0x40; /* TW, not BIOS */ 10548 CR35 |= 0x02; 10549 } 10550 } 10551 if(vbflag & TV_SCART) { 10552 CR31 |= 0x01; 10553 CR35 |= 0x01; 10554 } 10555 } 10556 10557 CR31 &= ~0x04; /* Clear NotSimuMode */ 10558 pSiS->SiS_Pr->SiS_CHOverScan = pSiS->UseCHOverScan; 10559 if((pSiS->OptTVSOver == 1) && (pSiS->ChrontelType == CHRONTEL_700x)) { 10560 pSiS->SiS_Pr->SiS_CHSOverScan = TRUE; 10561 } else { 10562 pSiS->SiS_Pr->SiS_CHSOverScan = FALSE; 10563 } 10564#ifdef SIS_CP 10565 SIS_CP_DRIVER_CONFIG 10566#endif 10567 break; 10568 10569 case CRT2_LCD: 10570 CR30 |= 0x20; 10571 SiS_SetEnableDstn(pSiS->SiS_Pr, pSiS->DSTN); 10572 SiS_SetEnableFstn(pSiS->SiS_Pr, pSiS->FSTN); 10573 break; 10574 10575 case CRT2_VGA: 10576 CR30 |= 0x40; 10577 break; 10578 10579 default: 10580 CR30 |= 0x00; 10581 CR31 |= 0x20; /* VB_OUTPUT_DISABLE */ 10582 if(pSiS->UseVESA) { 10583 crt1rateindex = SISSearchCRT1Rate(pScrn, mymode); 10584 } 10585 } 10586 10587 } 10588 10589 if(vbflag & CRT1_LCDA) { 10590 switch(viewmode) { 10591 case SIS_MODE_CRT1: 10592 CR38 |= 0x01; 10593 break; 10594 case SIS_MODE_CRT2: 10595 if(vbflag & (CRT2_TV|CRT2_VGA)) { 10596 CR30 |= 0x02; 10597 CR38 |= 0x01; 10598 } else { 10599 CR38 |= 0x03; 10600 } 10601 break; 10602 case SIS_MODE_SIMU: 10603 default: 10604 if(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA)) { 10605 CR30 |= 0x01; 10606 } 10607 break; 10608 } 10609 } else { 10610 if(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA)) { 10611 CR30 |= 0x01; 10612 } 10613 } 10614 10615 if(pSiS->UseVESA) { 10616 CR31 &= ~0x40; /* Clear Drivermode */ 10617 CR31 |= 0x06; /* Set SlaveMode, Enable SimuMode in Slavemode */ 10618#ifdef TWDEBUG 10619 CR31 |= 0x40; /* DEBUG (for non-slave mode VESA) */ 10620 crt1rateindex = SISSearchCRT1Rate(pScrn, mymode); 10621#endif 10622 } else { 10623 CR31 |= 0x40; /* Set Drivermode */ 10624 CR31 &= ~0x06; /* Disable SlaveMode, disable SimuMode in SlaveMode */ 10625 if(!pSiS->IsCustom) { 10626 crt1rateindex = SISSearchCRT1Rate(pScrn, mymode); 10627 } 10628 } 10629 10630 switch(viewmode) { 10631 case SIS_MODE_SIMU: 10632 CR33 = 0; 10633 if(!(vbflag & CRT1_LCDA)) { 10634 CR33 |= (crt1rateindex & 0x0f); 10635 } 10636 if(vbflag & CRT2_VGA) { 10637 CR33 |= ((crt1rateindex & 0x0f) << 4); 10638 } 10639 break; 10640 case SIS_MODE_CRT1: 10641 CR33 &= 0xf0; 10642 if(!(vbflag & CRT1_LCDA)) { 10643 CR33 |= (crt1rateindex & 0x0f); 10644 } 10645 break; 10646 case SIS_MODE_CRT2: 10647 CR33 &= 0x0f; 10648 if(vbflag & CRT2_VGA) { 10649 CR33 |= ((crt1rateindex & 0x0f) << 4); 10650 } 10651 break; 10652 } 10653 10654 if((!pSiS->UseVESA) && (vbflag & CRT2_ENABLE)) { 10655 if(pSiS->CRT1off) CR33 &= 0xf0; 10656 } 10657 10658 if(pSiS->NewCRLayout) { 10659 10660 CR31 &= 0xfe; /* Clear PAL flag (now in CR35) */ 10661 CR38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */ 10662 outSISIDXREG(SISCR, 0x30, CR30); 10663 outSISIDXREG(SISCR, 0x31, CR31); 10664 outSISIDXREG(SISCR, 0x33, CR33); 10665 outSISIDXREG(SISCR, 0x35, CR35); 10666 setSISIDXREG(SISCR, 0x38, 0xf8, CR38); 10667 outSISIDXREG(SISCR, 0x39, CR39); 10668 10669 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, SISVERBLEVEL, 10670 "After: CR30=0x%02x,CR31=0x%02x,CR33=0x%02x,CR35=0x%02x,CR38=%02x\n", 10671 CR30, CR31, CR33, CR35, CR38); 10672 10673 } else { 10674 10675 outSISIDXREG(SISCR, 0x30, CR30); 10676 outSISIDXREG(SISCR, 0x31, CR31); 10677 outSISIDXREG(SISCR, 0x33, CR33); 10678 if(temp) { 10679 outSISIDXREG(SISCR, temp, CR38); 10680 } 10681 if(pSiS->VGAEngine == SIS_315_VGA) { 10682 outSISIDXREG(SISCR, 0x3b, CR3B); 10683 outSISIDXREG(SISCR, 0x79, CR79); 10684 } 10685 10686 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, SISVERBLEVEL, 10687 "After: CR30=0x%02x,CR31=0x%02x,CR33=0x%02x,CR%02x=%02x\n", 10688 CR30, CR31, CR33, temp, CR38); 10689 } 10690 10691 pSiS->SiS_Pr->SiS_UseOEM = pSiS->OptUseOEM; 10692 10693 /* Enable TurboQueue */ 10694#ifdef SISVRAMQ 10695 if(pSiS->VGAEngine != SIS_315_VGA) 10696#endif 10697 SiSEnableTurboQueue(pScrn); 10698 10699 if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE)) { 10700 /* Switch on CRT1 for modes that require the bridge in SlaveMode */ 10701 andSISIDXREG(SISSR,0x1f,0x3f); 10702 inSISIDXREG(SISCR, 0x17, CR17); 10703 if(!(CR17 & 0x80)) { 10704 orSISIDXREG(SISCR, 0x17, 0x80); 10705 outSISIDXREG(SISSR, 0x00, 0x01); 10706 usleep(10000); 10707 outSISIDXREG(SISSR, 0x00, 0x03); 10708 } 10709 } 10710} 10711 10712/* Functions for adjusting various TV settings */ 10713 10714/* These are used by the PostSetMode() functions as well as 10715 * the display properties tool SiSCtrl. 10716 * 10717 * There is each a Set and a Get routine. The Set functions 10718 * take a value of the same range as the corresponding option. 10719 * The Get routines return a value of the same range (although 10720 * not necessarily the same value as previously set because 10721 * of the lower resolution of the respective setting compared 10722 * to the valid range). 10723 * The Get routines return -2 on error (eg. hardware does not 10724 * support this setting). 10725 * Note: The x and y positioning routines accept a position 10726 * RELATIVE to the default position. All other routines 10727 * take ABSOLUTE values. 10728 * 10729 * The Set functions will store the property regardless if TV is 10730 * currently used or not and if the hardware supports the property 10731 * or not. The Get routines will return this stored 10732 * value if TV is not currently used (because the register does 10733 * not contain the correct value then) or if the hardware supports 10734 * the respective property. This should make it easier for the 10735 * display property tool because it does not have to know the 10736 * hardware features. 10737 * 10738 * All the routines are dual head aware. It does not matter 10739 * if the function is called from the CRT1 or CRT2 session. 10740 * The values will be in pSiSEnt anyway, and read from there 10741 * if we're running dual head. 10742 */ 10743 10744void SiS_SetCHTVlumabandwidthcvbs(ScrnInfoPtr pScrn, int val) 10745{ 10746 SISPtr pSiS = SISPTR(pScrn); 10747#ifdef SISDUALHEAD 10748 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10749#endif 10750 10751 pSiS->chtvlumabandwidthcvbs = val; 10752#ifdef SISDUALHEAD 10753 if(pSiSEnt) pSiSEnt->chtvlumabandwidthcvbs = val; 10754#endif 10755 10756 if(!(pSiS->VBFlags & CRT2_TV)) return; 10757 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10758 10759#ifdef UNLOCK_ALWAYS 10760 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10761#endif 10762 10763 switch(pSiS->ChrontelType) { 10764 case CHRONTEL_700x: 10765 val /= 8; 10766 if((val == 0) || (val == 1)) { 10767 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, val, 0xFE); 10768 } 10769 break; 10770 case CHRONTEL_701x: 10771 val /= 4; 10772 if((val >= 0) && (val <= 3)) { 10773 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, val, 0xFC); 10774 } 10775 break; 10776 } 10777} 10778 10779int SiS_GetCHTVlumabandwidthcvbs(ScrnInfoPtr pScrn) 10780{ 10781 SISPtr pSiS = SISPTR(pScrn); 10782#ifdef SISDUALHEAD 10783 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10784#endif 10785 10786 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10787#ifdef SISDUALHEAD 10788 if(pSiSEnt && pSiS->DualHeadMode) 10789 return (int)pSiSEnt->chtvlumabandwidthcvbs; 10790 else 10791#endif 10792 return (int)pSiS->chtvlumabandwidthcvbs; 10793 } else { 10794#ifdef UNLOCK_ALWAYS 10795 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10796#endif 10797 switch(pSiS->ChrontelType) { 10798 case CHRONTEL_700x: 10799 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x01) * 8); 10800 case CHRONTEL_701x: 10801 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x03) * 4); 10802 default: 10803 return (int)pSiS->chtvlumabandwidthcvbs; 10804 } 10805 } 10806} 10807 10808void SiS_SetCHTVlumabandwidthsvideo(ScrnInfoPtr pScrn, int val) 10809{ 10810 SISPtr pSiS = SISPTR(pScrn); 10811#ifdef SISDUALHEAD 10812 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10813#endif 10814 10815 pSiS->chtvlumabandwidthsvideo = val; 10816#ifdef SISDUALHEAD 10817 if(pSiSEnt) pSiSEnt->chtvlumabandwidthsvideo = val; 10818#endif 10819 10820 if(!(pSiS->VBFlags & CRT2_TV)) return; 10821 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10822 10823#ifdef UNLOCK_ALWAYS 10824 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10825#endif 10826 10827 switch(pSiS->ChrontelType) { 10828 case CHRONTEL_700x: 10829 val /= 6; 10830 if((val >= 0) && (val <= 2)) { 10831 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, (val << 1), 0xF9); 10832 } 10833 break; 10834 case CHRONTEL_701x: 10835 val /= 4; 10836 if((val >= 0) && (val <= 3)) { 10837 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, (val << 2), 0xF3); 10838 } 10839 break; 10840 } 10841} 10842 10843int SiS_GetCHTVlumabandwidthsvideo(ScrnInfoPtr pScrn) 10844{ 10845 SISPtr pSiS = SISPTR(pScrn); 10846#ifdef SISDUALHEAD 10847 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10848#endif 10849 10850 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10851#ifdef SISDUALHEAD 10852 if(pSiSEnt && pSiS->DualHeadMode) 10853 return (int)pSiSEnt->chtvlumabandwidthsvideo; 10854 else 10855#endif 10856 return (int)pSiS->chtvlumabandwidthsvideo; 10857 } else { 10858#ifdef UNLOCK_ALWAYS 10859 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10860#endif 10861 switch(pSiS->ChrontelType) { 10862 case CHRONTEL_700x: 10863 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x06) >> 1) * 6); 10864 case CHRONTEL_701x: 10865 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x0c) >> 2) * 4); 10866 default: 10867 return (int)pSiS->chtvlumabandwidthsvideo; 10868 } 10869 } 10870} 10871 10872void SiS_SetCHTVlumaflickerfilter(ScrnInfoPtr pScrn, int val) 10873{ 10874 SISPtr pSiS = SISPTR(pScrn); 10875#ifdef SISDUALHEAD 10876 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10877#endif 10878 10879 pSiS->chtvlumaflickerfilter = val; 10880#ifdef SISDUALHEAD 10881 if(pSiSEnt) pSiSEnt->chtvlumaflickerfilter = val; 10882#endif 10883 10884 if(!(pSiS->VBFlags & CRT2_TV)) return; 10885 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10886 10887#ifdef UNLOCK_ALWAYS 10888 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10889#endif 10890 10891 switch(pSiS->ChrontelType) { 10892 case CHRONTEL_700x: 10893 val /= 6; 10894 if((val >= 0) && (val <= 2)) { 10895 UShort reg = 0; 10896 reg = SiS_GetCH70xx(pSiS->SiS_Pr, 0x01); 10897 reg = (reg & 0xf0) | ((reg & 0x0c) >> 2) | (val << 2); 10898 SiS_SetCH70xx(pSiS->SiS_Pr, 0x01, reg); 10899 } 10900 break; 10901 case CHRONTEL_701x: 10902 val /= 4; 10903 if((val >= 0) && (val <= 3)) { 10904 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x01, (val << 2), 0xF3); 10905 } 10906 break; 10907 } 10908} 10909 10910int SiS_GetCHTVlumaflickerfilter(ScrnInfoPtr pScrn) 10911{ 10912 SISPtr pSiS = SISPTR(pScrn); 10913#ifdef SISDUALHEAD 10914 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10915#endif 10916 10917 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10918#ifdef SISDUALHEAD 10919 if(pSiSEnt && pSiS->DualHeadMode) 10920 return (int)pSiSEnt->chtvlumaflickerfilter; 10921 else 10922#endif 10923 return (int)pSiS->chtvlumaflickerfilter; 10924 } else { 10925#ifdef UNLOCK_ALWAYS 10926 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10927#endif 10928 switch(pSiS->ChrontelType) { 10929 case CHRONTEL_700x: 10930 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x03) * 6); 10931 case CHRONTEL_701x: 10932 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x0c) >> 2) * 4); 10933 default: 10934 return (int)pSiS->chtvlumaflickerfilter; 10935 } 10936 } 10937} 10938 10939void SiS_SetCHTVchromabandwidth(ScrnInfoPtr pScrn, int val) 10940{ 10941 SISPtr pSiS = SISPTR(pScrn); 10942#ifdef SISDUALHEAD 10943 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10944#endif 10945 10946 pSiS->chtvchromabandwidth = val; 10947#ifdef SISDUALHEAD 10948 if(pSiSEnt) pSiSEnt->chtvchromabandwidth = val; 10949#endif 10950 10951 if(!(pSiS->VBFlags & CRT2_TV)) return; 10952 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10953 10954#ifdef UNLOCK_ALWAYS 10955 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10956#endif 10957 10958 switch(pSiS->ChrontelType) { 10959 case CHRONTEL_700x: 10960 val /= 4; 10961 if((val >= 0) && (val <= 3)) { 10962 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, (val << 4), 0xCF); 10963 } 10964 break; 10965 case CHRONTEL_701x: 10966 val /= 8; 10967 if((val >= 0) && (val <= 1)) { 10968 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, (val << 4), 0xEF); 10969 } 10970 break; 10971 } 10972} 10973 10974int SiS_GetCHTVchromabandwidth(ScrnInfoPtr pScrn) 10975{ 10976 SISPtr pSiS = SISPTR(pScrn); 10977#ifdef SISDUALHEAD 10978 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10979#endif 10980 10981 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10982#ifdef SISDUALHEAD 10983 if(pSiSEnt && pSiS->DualHeadMode) 10984 return (int)pSiSEnt->chtvchromabandwidth; 10985 else 10986#endif 10987 return (int)pSiS->chtvchromabandwidth; 10988 } else { 10989#ifdef UNLOCK_ALWAYS 10990 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10991#endif 10992 switch(pSiS->ChrontelType) { 10993 case CHRONTEL_700x: 10994 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x30) >> 4) * 4); 10995 case CHRONTEL_701x: 10996 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x10) >> 4) * 8); 10997 default: 10998 return (int)pSiS->chtvchromabandwidth; 10999 } 11000 } 11001} 11002 11003void SiS_SetCHTVchromaflickerfilter(ScrnInfoPtr pScrn, int val) 11004{ 11005 SISPtr pSiS = SISPTR(pScrn); 11006#ifdef SISDUALHEAD 11007 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11008#endif 11009 11010 pSiS->chtvchromaflickerfilter = val; 11011#ifdef SISDUALHEAD 11012 if(pSiSEnt) pSiSEnt->chtvchromaflickerfilter = val; 11013#endif 11014 11015 if(!(pSiS->VBFlags & CRT2_TV)) return; 11016 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 11017 11018#ifdef UNLOCK_ALWAYS 11019 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11020#endif 11021 11022 switch(pSiS->ChrontelType) { 11023 case CHRONTEL_700x: 11024 val /= 6; 11025 if((val >= 0) && (val <= 2)) { 11026 UShort reg = 0; 11027 reg = SiS_GetCH70xx(pSiS->SiS_Pr, 0x01); 11028 reg = (reg & 0xc0) | ((reg & 0x0c) >> 2) | ((reg & 0x03) << 2) | (val << 4); 11029 SiS_SetCH70xx(pSiS->SiS_Pr, 0x01, reg); 11030 } 11031 break; 11032 case CHRONTEL_701x: 11033 val /= 4; 11034 if((val >= 0) && (val <= 3)) { 11035 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x01, (val << 4), 0xCF); 11036 } 11037 break; 11038 } 11039} 11040 11041int SiS_GetCHTVchromaflickerfilter(ScrnInfoPtr pScrn) 11042{ 11043 SISPtr pSiS = SISPTR(pScrn); 11044#ifdef SISDUALHEAD 11045 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11046#endif 11047 11048 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 11049#ifdef SISDUALHEAD 11050 if(pSiSEnt && pSiS->DualHeadMode) 11051 return (int)pSiSEnt->chtvchromaflickerfilter; 11052 else 11053#endif 11054 return (int)pSiS->chtvchromaflickerfilter; 11055 } else { 11056#ifdef UNLOCK_ALWAYS 11057 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11058#endif 11059 switch(pSiS->ChrontelType) { 11060 case CHRONTEL_700x: 11061 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x30) >> 4) * 6); 11062 case CHRONTEL_701x: 11063 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x30) >> 4) * 4); 11064 default: 11065 return (int)pSiS->chtvchromaflickerfilter; 11066 } 11067 } 11068} 11069 11070void SiS_SetCHTVcvbscolor(ScrnInfoPtr pScrn, int val) 11071{ 11072 SISPtr pSiS = SISPTR(pScrn); 11073#ifdef SISDUALHEAD 11074 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11075#endif 11076 11077 pSiS->chtvcvbscolor = val ? 1 : 0; 11078#ifdef SISDUALHEAD 11079 if(pSiSEnt) pSiSEnt->chtvcvbscolor = pSiS->chtvcvbscolor; 11080#endif 11081 11082 if(!(pSiS->VBFlags & CRT2_TV)) return; 11083 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 11084 11085#ifdef UNLOCK_ALWAYS 11086 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11087#endif 11088 11089 switch(pSiS->ChrontelType) { 11090 case CHRONTEL_700x: 11091 if(!val) SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, 0x40, 0x00); 11092 else SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, 0x00, ~0x40); 11093 break; 11094 case CHRONTEL_701x: 11095 if(!val) SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, 0x00, ~0x20); 11096 else SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, 0x20, 0x00); 11097 break; 11098 } 11099} 11100 11101int SiS_GetCHTVcvbscolor(ScrnInfoPtr pScrn) 11102{ 11103 SISPtr pSiS = SISPTR(pScrn); 11104#ifdef SISDUALHEAD 11105 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11106#endif 11107 11108 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 11109#ifdef SISDUALHEAD 11110 if(pSiSEnt && pSiS->DualHeadMode) 11111 return (int)pSiSEnt->chtvcvbscolor; 11112 else 11113#endif 11114 return (int)pSiS->chtvcvbscolor; 11115 } else { 11116#ifdef UNLOCK_ALWAYS 11117 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11118#endif 11119 switch(pSiS->ChrontelType) { 11120 case CHRONTEL_700x: 11121 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x40) >> 6) ^ 0x01); 11122 case CHRONTEL_701x: 11123 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x20) >> 5) ^ 0x01); 11124 default: 11125 return (int)pSiS->chtvcvbscolor; 11126 } 11127 } 11128} 11129 11130void SiS_SetCHTVtextenhance(ScrnInfoPtr pScrn, int val) 11131{ 11132 SISPtr pSiS = SISPTR(pScrn); 11133#ifdef SISDUALHEAD 11134 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11135#endif 11136 11137 pSiS->chtvtextenhance = val; 11138#ifdef SISDUALHEAD 11139 if(pSiSEnt) pSiSEnt->chtvtextenhance = val; 11140#endif 11141 11142 if(!(pSiS->VBFlags & CRT2_TV)) return; 11143 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 11144 11145#ifdef UNLOCK_ALWAYS 11146 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11147#endif 11148 11149 switch(pSiS->ChrontelType) { 11150 case CHRONTEL_700x: 11151 val /= 6; 11152 if((val >= 0) && (val <= 2)) { 11153 UShort reg = 0; 11154 reg = SiS_GetCH70xx(pSiS->SiS_Pr, 0x01); 11155 reg = (reg & 0xf0) | ((reg & 0x03) << 2) | val; 11156 SiS_SetCH70xx(pSiS->SiS_Pr, 0x01, reg); 11157 } 11158 break; 11159 case CHRONTEL_701x: 11160 val /= 2; 11161 if((val >= 0) && (val <= 7)) { 11162 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, val, 0xF8); 11163 } 11164 break; 11165 } 11166} 11167 11168int SiS_GetCHTVtextenhance(ScrnInfoPtr pScrn) 11169{ 11170 SISPtr pSiS = SISPTR(pScrn); 11171#ifdef SISDUALHEAD 11172 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11173#endif 11174 11175 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 11176#ifdef SISDUALHEAD 11177 if(pSiSEnt && pSiS->DualHeadMode) 11178 return (int)pSiSEnt->chtvtextenhance; 11179 else 11180#endif 11181 return (int)pSiS->chtvtextenhance; 11182 } else { 11183#ifdef UNLOCK_ALWAYS 11184 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11185#endif 11186 switch(pSiS->ChrontelType) { 11187 case CHRONTEL_700x: 11188 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x0c) >> 2) * 6); 11189 case CHRONTEL_701x: 11190 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x07) * 2); 11191 default: 11192 return (int)pSiS->chtvtextenhance; 11193 } 11194 } 11195} 11196 11197void SiS_SetCHTVcontrast(ScrnInfoPtr pScrn, int val) 11198{ 11199 SISPtr pSiS = SISPTR(pScrn); 11200#ifdef SISDUALHEAD 11201 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11202#endif 11203 11204 pSiS->chtvcontrast = val; 11205#ifdef SISDUALHEAD 11206 if(pSiSEnt) pSiSEnt->chtvcontrast = val; 11207#endif 11208 11209 if(!(pSiS->VBFlags & CRT2_TV)) return; 11210 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 11211 11212#ifdef UNLOCK_ALWAYS 11213 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11214#endif 11215 11216 val /= 2; 11217 if((val >= 0) && (val <= 7)) { 11218 switch(pSiS->ChrontelType) { 11219 case CHRONTEL_700x: 11220 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x11, val, 0xF8); 11221 break; 11222 case CHRONTEL_701x: 11223 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x08, val, 0xF8); 11224 break; 11225 } 11226 SiS_DDC2Delay(pSiS->SiS_Pr, 1000); 11227 } 11228} 11229 11230int SiS_GetCHTVcontrast(ScrnInfoPtr pScrn) 11231{ 11232 SISPtr pSiS = SISPTR(pScrn); 11233#ifdef SISDUALHEAD 11234 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11235#endif 11236 11237 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 11238#ifdef SISDUALHEAD 11239 if(pSiSEnt && pSiS->DualHeadMode) 11240 return (int)pSiSEnt->chtvcontrast; 11241 else 11242#endif 11243 return (int)pSiS->chtvcontrast; 11244 } else { 11245#ifdef UNLOCK_ALWAYS 11246 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11247#endif 11248 switch(pSiS->ChrontelType) { 11249 case CHRONTEL_700x: 11250 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x11) & 0x07) * 2); 11251 case CHRONTEL_701x: 11252 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x08) & 0x07) * 2); 11253 default: 11254 return (int)pSiS->chtvcontrast; 11255 } 11256 } 11257} 11258 11259void SiS_SetSISTVedgeenhance(ScrnInfoPtr pScrn, int val) 11260{ 11261 SISPtr pSiS = SISPTR(pScrn); 11262#ifdef SISDUALHEAD 11263 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11264#endif 11265 11266 pSiS->sistvedgeenhance = val; 11267#ifdef SISDUALHEAD 11268 if(pSiSEnt) pSiSEnt->sistvedgeenhance = val; 11269#endif 11270 11271 if(!(pSiS->VBFlags2 & VB2_301)) return; 11272 if(!(pSiS->VBFlags & CRT2_TV)) return; 11273 11274#ifdef UNLOCK_ALWAYS 11275 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11276#endif 11277 11278 val /= 2; 11279 if((val >= 0) && (val <= 7)) { 11280 setSISIDXREG(SISPART2,0x3A, 0x1F, (val << 5)); 11281 } 11282} 11283 11284int SiS_GetSISTVedgeenhance(ScrnInfoPtr pScrn) 11285{ 11286 SISPtr pSiS = SISPTR(pScrn); 11287 int result = pSiS->sistvedgeenhance; 11288 UChar temp; 11289#ifdef SISDUALHEAD 11290 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11291 11292 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvedgeenhance; 11293#endif 11294 11295 if(!(pSiS->VBFlags2 & VB2_301)) return result; 11296 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11297 11298#ifdef UNLOCK_ALWAYS 11299 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11300#endif 11301 inSISIDXREG(SISPART2, 0x3a, temp); 11302 return(int)(((temp & 0xe0) >> 5) * 2); 11303} 11304 11305void SiS_SetSISTVantiflicker(ScrnInfoPtr pScrn, int val) 11306{ 11307 SISPtr pSiS = SISPTR(pScrn); 11308#ifdef SISDUALHEAD 11309 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11310#endif 11311 11312 pSiS->sistvantiflicker = val; 11313#ifdef SISDUALHEAD 11314 if(pSiSEnt) pSiSEnt->sistvantiflicker = val; 11315#endif 11316 11317 if(!(pSiS->VBFlags & CRT2_TV)) return; 11318 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11319 if(pSiS->VBFlags & TV_HIVISION) return; 11320 if((pSiS->VBFlags & TV_YPBPR) && 11321 (pSiS->VBFlags & (TV_YPBPR525P | TV_YPBPR625P | TV_YPBPR750P | TV_YPBPR1080I))) return; 11322 11323#ifdef UNLOCK_ALWAYS 11324 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11325#endif 11326 11327 /* Valid values: 0=off, 1=low, 2=med, 3=high, 4=adaptive */ 11328 if((val >= 0) && (val <= 4)) { 11329 setSISIDXREG(SISPART2,0x0A,0x8F, (val << 4)); 11330 } 11331} 11332 11333int SiS_GetSISTVantiflicker(ScrnInfoPtr pScrn) 11334{ 11335 SISPtr pSiS = SISPTR(pScrn); 11336 int result = pSiS->sistvantiflicker; 11337 UChar temp; 11338#ifdef SISDUALHEAD 11339 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11340 11341 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvantiflicker; 11342#endif 11343 11344 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return result; 11345 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11346 if(pSiS->VBFlags & TV_HIVISION) return result; 11347 if((pSiS->VBFlags & TV_YPBPR) && 11348 (pSiS->VBFlags & (TV_YPBPR525P | TV_YPBPR625P | TV_YPBPR750P | TV_YPBPR1080I))) return result; 11349 11350#ifdef UNLOCK_ALWAYS 11351 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11352#endif 11353 inSISIDXREG(SISPART2, 0x0a, temp); 11354 return(int)((temp & 0x70) >> 4); 11355} 11356 11357void SiS_SetSISTVsaturation(ScrnInfoPtr pScrn, int val) 11358{ 11359 SISPtr pSiS = SISPTR(pScrn); 11360#ifdef SISDUALHEAD 11361 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11362#endif 11363 11364 pSiS->sistvsaturation = val; 11365#ifdef SISDUALHEAD 11366 if(pSiSEnt) pSiSEnt->sistvsaturation = val; 11367#endif 11368 11369 if(!(pSiS->VBFlags & CRT2_TV)) return; 11370 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11371 if(pSiS->VBFlags2 & VB2_301) return; 11372 11373#ifdef UNLOCK_ALWAYS 11374 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11375#endif 11376 11377 val /= 2; 11378 if((val >= 0) && (val <= 7)) { 11379 setSISIDXREG(SISPART4,0x21,0xF8, val); 11380 } 11381} 11382 11383int SiS_GetSISTVsaturation(ScrnInfoPtr pScrn) 11384{ 11385 SISPtr pSiS = SISPTR(pScrn); 11386 int result = pSiS->sistvsaturation; 11387 UChar temp; 11388#ifdef SISDUALHEAD 11389 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11390 11391 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvsaturation; 11392#endif 11393 11394 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return result; 11395 if(pSiS->VBFlags2 & VB2_301) return result; 11396 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11397 11398#ifdef UNLOCK_ALWAYS 11399 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11400#endif 11401 inSISIDXREG(SISPART4, 0x21, temp); 11402 return(int)((temp & 0x07) * 2); 11403} 11404 11405void SiS_SetSISTVcolcalib(ScrnInfoPtr pScrn, int val, Bool coarse) 11406{ 11407 SISPtr pSiS = SISPTR(pScrn); 11408#ifdef SISDUALHEAD 11409 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11410#endif 11411 int ccoarse, cfine, cbase = pSiS->sistvccbase; 11412 /* UChar temp; */ 11413 11414#ifdef SISDUALHEAD 11415 if(pSiSEnt && pSiS->DualHeadMode) cbase = pSiSEnt->sistvccbase; 11416#endif 11417 11418 if(coarse) { 11419 pSiS->sistvcolcalibc = ccoarse = val; 11420 cfine = pSiS->sistvcolcalibf; 11421#ifdef SISDUALHEAD 11422 if(pSiSEnt) { 11423 pSiSEnt->sistvcolcalibc = val; 11424 if(pSiS->DualHeadMode) cfine = pSiSEnt->sistvcolcalibf; 11425 } 11426#endif 11427 } else { 11428 pSiS->sistvcolcalibf = cfine = val; 11429 ccoarse = pSiS->sistvcolcalibc; 11430#ifdef SISDUALHEAD 11431 if(pSiSEnt) { 11432 pSiSEnt->sistvcolcalibf = val; 11433 if(pSiS->DualHeadMode) ccoarse = pSiSEnt->sistvcolcalibc; 11434 } 11435#endif 11436 } 11437 11438 if(!(pSiS->VBFlags & CRT2_TV)) return; 11439 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11440 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return; 11441 11442#ifdef UNLOCK_ALWAYS 11443 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11444#endif 11445 11446 if((cfine >= -128) && (cfine <= 127) && (ccoarse >= -120) && (ccoarse <= 120)) { 11447 long finalcc = cbase + (((ccoarse * 256) + cfine) * 256); 11448 11449#if 0 11450 inSISIDXREG(SISPART4,0x1f,temp); 11451 if(!(temp & 0x01)) { 11452 if(pSiS->VBFlags & TV_NTSC) finalcc += 0x21ed8620; 11453 else if(pSiS->VBFlags & TV_PALM) finalcc += ?; 11454 else if(pSiS->VBFlags & TV_PALM) finalcc += ?; 11455 else finalcc += 0x2a05d300; 11456 } 11457#endif 11458 setSISIDXREG(SISPART2,0x31,0x80,((finalcc >> 24) & 0x7f)); 11459 outSISIDXREG(SISPART2,0x32,((finalcc >> 16) & 0xff)); 11460 outSISIDXREG(SISPART2,0x33,((finalcc >> 8) & 0xff)); 11461 outSISIDXREG(SISPART2,0x34,(finalcc & 0xff)); 11462 } 11463} 11464 11465int SiS_GetSISTVcolcalib(ScrnInfoPtr pScrn, Bool coarse) 11466{ 11467 SISPtr pSiS = SISPTR(pScrn); 11468#ifdef SISDUALHEAD 11469 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11470 11471 if(pSiSEnt && pSiS->DualHeadMode) 11472 if(coarse) return (int)pSiSEnt->sistvcolcalibc; 11473 else return (int)pSiSEnt->sistvcolcalibf; 11474 else 11475#endif 11476 if(coarse) return (int)pSiS->sistvcolcalibc; 11477 else return (int)pSiS->sistvcolcalibf; 11478} 11479 11480void SiS_SetSISTVcfilter(ScrnInfoPtr pScrn, int val) 11481{ 11482 SISPtr pSiS = SISPTR(pScrn); 11483#ifdef SISDUALHEAD 11484 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11485#endif 11486 11487 pSiS->sistvcfilter = val ? 1 : 0; 11488#ifdef SISDUALHEAD 11489 if(pSiSEnt) pSiSEnt->sistvcfilter = pSiS->sistvcfilter; 11490#endif 11491 11492 if(!(pSiS->VBFlags & CRT2_TV)) return; 11493 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11494 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return; 11495 11496#ifdef UNLOCK_ALWAYS 11497 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11498#endif 11499 11500 setSISIDXREG(SISPART2,0x30,~0x10,((pSiS->sistvcfilter << 4) & 0x10)); 11501} 11502 11503int SiS_GetSISTVcfilter(ScrnInfoPtr pScrn) 11504{ 11505 SISPtr pSiS = SISPTR(pScrn); 11506 int result = pSiS->sistvcfilter; 11507 UChar temp; 11508#ifdef SISDUALHEAD 11509 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11510 11511 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvcfilter; 11512#endif 11513 11514 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return result; 11515 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11516 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return result; 11517 11518#ifdef UNLOCK_ALWAYS 11519 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11520#endif 11521 inSISIDXREG(SISPART2, 0x30, temp); 11522 return (int)((temp & 0x10) ? 1 : 0); 11523} 11524 11525void SiS_SetSISTVyfilter(ScrnInfoPtr pScrn, int val) 11526{ 11527 SISPtr pSiS = SISPTR(pScrn); 11528#ifdef SISDUALHEAD 11529 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11530#endif 11531 UChar p35,p36,p37,p38,p48,p49,p4a,p30; 11532 int i,j; 11533 11534 pSiS->sistvyfilter = val; 11535#ifdef SISDUALHEAD 11536 if(pSiSEnt) pSiSEnt->sistvyfilter = pSiS->sistvyfilter; 11537#endif 11538 11539 if(!(pSiS->VBFlags & CRT2_TV)) return; 11540 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11541 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return; 11542 11543 p35 = pSiS->p2_35; p36 = pSiS->p2_36; 11544 p37 = pSiS->p2_37; p38 = pSiS->p2_38; 11545 p48 = pSiS->p2_48; p49 = pSiS->p2_49; 11546 p4a = pSiS->p2_4a; p30 = pSiS->p2_30; 11547#ifdef SISDUALHEAD 11548 if(pSiSEnt && pSiS->DualHeadMode) { 11549 p35 = pSiSEnt->p2_35; p36 = pSiSEnt->p2_36; 11550 p37 = pSiSEnt->p2_37; p38 = pSiSEnt->p2_38; 11551 p48 = pSiSEnt->p2_48; p49 = pSiSEnt->p2_49; 11552 p4a = pSiSEnt->p2_4a; p30 = pSiSEnt->p2_30; 11553 } 11554#endif 11555 p30 &= 0x20; 11556 11557#ifdef UNLOCK_ALWAYS 11558 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11559#endif 11560 11561 switch(pSiS->sistvyfilter) { 11562 case 0: 11563 andSISIDXREG(SISPART2,0x30,0xdf); 11564 break; 11565 case 1: 11566 outSISIDXREG(SISPART2,0x35,p35); 11567 outSISIDXREG(SISPART2,0x36,p36); 11568 outSISIDXREG(SISPART2,0x37,p37); 11569 outSISIDXREG(SISPART2,0x38,p38); 11570 if(!(pSiS->VBFlags2 & VB2_301)) { 11571 outSISIDXREG(SISPART2,0x48,p48); 11572 outSISIDXREG(SISPART2,0x49,p49); 11573 outSISIDXREG(SISPART2,0x4a,p4a); 11574 } 11575 setSISIDXREG(SISPART2,0x30,0xdf,p30); 11576 break; 11577 case 2: 11578 case 3: 11579 case 4: 11580 case 5: 11581 case 6: 11582 case 7: 11583 case 8: 11584 if(!(pSiS->VBFlags & (TV_PALM | TV_PALN | TV_NTSCJ))) { 11585 int yindex301 = -1, yindex301B = -1; 11586 UChar p3d4_34; 11587 11588 inSISIDXREG(SISCR,0x34,p3d4_34); 11589 11590 switch((p3d4_34 & 0x7f)) { 11591 case 0x59: /* 320x200 */ 11592 case 0x41: 11593 case 0x4f: 11594 case 0x50: /* 320x240 */ 11595 case 0x56: 11596 case 0x53: 11597 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 0 : 4; 11598 break; 11599 case 0x2f: /* 640x400 */ 11600 case 0x5d: 11601 case 0x5e: 11602 case 0x2e: /* 640x480 */ 11603 case 0x44: 11604 case 0x62: 11605 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 1 : 5; 11606 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 0 : 4; 11607 break; 11608 case 0x31: /* 720x480 */ 11609 case 0x33: 11610 case 0x35: 11611 case 0x32: /* 720x576 */ 11612 case 0x34: 11613 case 0x36: 11614 case 0x5f: /* 768x576 */ 11615 case 0x60: 11616 case 0x61: 11617 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 2 : 6; 11618 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 1 : 5; 11619 break; 11620 case 0x51: /* 400x300 */ 11621 case 0x57: 11622 case 0x54: 11623 case 0x30: /* 800x600 */ 11624 case 0x47: 11625 case 0x63: 11626 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 3 : 7; 11627 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 2 : 6; 11628 break; 11629 case 0x52: /* 512x384 */ 11630 case 0x58: 11631 case 0x5c: 11632 case 0x38: /* 1024x768 */ 11633 case 0x4a: 11634 case 0x64: 11635 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 3 : 7; 11636 break; 11637 } 11638 if(pSiS->VBFlags2 & VB2_301) { 11639 if(yindex301 >= 0) { 11640 for(i=0, j=0x35; i<=3; i++, j++) { 11641 outSISIDXREG(SISPART2,j,(SiSTVFilter301[yindex301].filter[pSiS->sistvyfilter-2][i])); 11642 } 11643 } 11644 } else { 11645 if(yindex301B >= 0) { 11646 for(i=0, j=0x35; i<=3; i++, j++) { 11647 outSISIDXREG(SISPART2,j,(SiSTVFilter301B[yindex301B].filter[pSiS->sistvyfilter-2][i])); 11648 } 11649 for(i=4, j=0x48; i<=6; i++, j++) { 11650 outSISIDXREG(SISPART2,j,(SiSTVFilter301B[yindex301B].filter[pSiS->sistvyfilter-2][i])); 11651 } 11652 } 11653 } 11654 orSISIDXREG(SISPART2,0x30,0x20); 11655 } 11656 } 11657} 11658 11659int SiS_GetSISTVyfilter(ScrnInfoPtr pScrn) 11660{ 11661 SISPtr pSiS = SISPTR(pScrn); 11662#ifdef SISDUALHEAD 11663 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11664 11665 if(pSiSEnt && pSiS->DualHeadMode) 11666 return (int)pSiSEnt->sistvyfilter; 11667 else 11668#endif 11669 return (int)pSiS->sistvyfilter; 11670} 11671 11672void SiS_SetSIS6326TVantiflicker(ScrnInfoPtr pScrn, int val) 11673{ 11674 SISPtr pSiS = SISPTR(pScrn); 11675 UChar tmp; 11676 11677 pSiS->sistvantiflicker = val; 11678 11679 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 11680 11681#ifdef UNLOCK_ALWAYS 11682 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11683#endif 11684 11685 tmp = SiS6326GetTVReg(pScrn,0x00); 11686 if(!(tmp & 0x04)) return; 11687 11688 /* Valid values: 0=off, 1=low, 2=med, 3=high, 4=adaptive */ 11689 if(val >= 0 && val <= 4) { 11690 tmp &= 0x1f; 11691 tmp |= (val << 5); 11692 SiS6326SetTVReg(pScrn,0x00,tmp); 11693 } 11694} 11695 11696int SiS_GetSIS6326TVantiflicker(ScrnInfoPtr pScrn) 11697{ 11698 SISPtr pSiS = SISPTR(pScrn); 11699 UChar tmp; 11700 11701 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 11702 return (int)pSiS->sistvantiflicker; 11703 } 11704 11705#ifdef UNLOCK_ALWAYS 11706 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11707#endif 11708 11709 tmp = SiS6326GetTVReg(pScrn,0x00); 11710 if(!(tmp & 0x04)) { 11711 return (int)pSiS->sistvantiflicker; 11712 } else { 11713 return (int)((tmp >> 5) & 0x07); 11714 } 11715} 11716 11717void SiS_SetSIS6326TVenableyfilter(ScrnInfoPtr pScrn, int val) 11718{ 11719 SISPtr pSiS = SISPTR(pScrn); 11720 UChar tmp; 11721 11722 if(val) val = 1; 11723 pSiS->sis6326enableyfilter = val; 11724 11725 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 11726 11727#ifdef UNLOCK_ALWAYS 11728 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11729#endif 11730 11731 tmp = SiS6326GetTVReg(pScrn,0x00); 11732 if(!(tmp & 0x04)) return; 11733 11734 tmp = SiS6326GetTVReg(pScrn,0x43); 11735 tmp &= ~0x10; 11736 tmp |= ((val & 0x01) << 4); 11737 SiS6326SetTVReg(pScrn,0x43,tmp); 11738} 11739 11740int SiS_GetSIS6326TVenableyfilter(ScrnInfoPtr pScrn) 11741{ 11742 SISPtr pSiS = SISPTR(pScrn); 11743 UChar tmp; 11744 11745 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 11746 return (int)pSiS->sis6326enableyfilter; 11747 } 11748 11749#ifdef UNLOCK_ALWAYS 11750 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11751#endif 11752 11753 tmp = SiS6326GetTVReg(pScrn,0x00); 11754 if(!(tmp & 0x04)) { 11755 return (int)pSiS->sis6326enableyfilter; 11756 } else { 11757 tmp = SiS6326GetTVReg(pScrn,0x43); 11758 return (int)((tmp >> 4) & 0x01); 11759 } 11760} 11761 11762void SiS_SetSIS6326TVyfilterstrong(ScrnInfoPtr pScrn, int val) 11763{ 11764 SISPtr pSiS = SISPTR(pScrn); 11765 UChar tmp; 11766 11767 if(val) val = 1; 11768 pSiS->sis6326yfilterstrong = val; 11769 11770 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 11771 11772#ifdef UNLOCK_ALWAYS 11773 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11774#endif 11775 11776 tmp = SiS6326GetTVReg(pScrn,0x00); 11777 if(!(tmp & 0x04)) return; 11778 11779 tmp = SiS6326GetTVReg(pScrn,0x43); 11780 if(tmp & 0x10) { 11781 tmp &= ~0x40; 11782 tmp |= ((val & 0x01) << 6); 11783 SiS6326SetTVReg(pScrn,0x43,tmp); 11784 } 11785} 11786 11787int SiS_GetSIS6326TVyfilterstrong(ScrnInfoPtr pScrn) 11788{ 11789 SISPtr pSiS = SISPTR(pScrn); 11790 UChar tmp; 11791 11792 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 11793 return (int)pSiS->sis6326yfilterstrong; 11794 } 11795 11796#ifdef UNLOCK_ALWAYS 11797 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11798#endif 11799 11800 tmp = SiS6326GetTVReg(pScrn,0x00); 11801 if(!(tmp & 0x04)) { 11802 return (int)pSiS->sis6326yfilterstrong; 11803 } else { 11804 tmp = SiS6326GetTVReg(pScrn,0x43); 11805 if(!(tmp & 0x10)) { 11806 return (int)pSiS->sis6326yfilterstrong; 11807 } else { 11808 return (int)((tmp >> 6) & 0x01); 11809 } 11810 } 11811} 11812 11813void SiS_SetTVxposoffset(ScrnInfoPtr pScrn, int val) 11814{ 11815 SISPtr pSiS = SISPTR(pScrn); 11816#ifdef SISDUALHEAD 11817 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11818#endif 11819 11820#ifdef UNLOCK_ALWAYS 11821 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11822#endif 11823 11824 pSiS->tvxpos = val; 11825#ifdef SISDUALHEAD 11826 if(pSiSEnt) pSiSEnt->tvxpos = val; 11827#endif 11828 11829 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 11830 11831 if(pSiS->VBFlags & CRT2_TV) { 11832 11833 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 11834 11835 int x = pSiS->tvx; 11836#ifdef SISDUALHEAD 11837 if(pSiSEnt && pSiS->DualHeadMode) x = pSiSEnt->tvx; 11838#endif 11839 switch(pSiS->ChrontelType) { 11840 case CHRONTEL_700x: 11841 if((val >= -32) && (val <= 32)) { 11842 x += val; 11843 if(x < 0) x = 0; 11844 SiS_SetCH700x(pSiS->SiS_Pr, 0x0a, (x & 0xff)); 11845 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD); 11846 } 11847 break; 11848 case CHRONTEL_701x: 11849 /* Not supported by hardware */ 11850 break; 11851 } 11852 11853 } else if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 11854 11855 if((val >= -32) && (val <= 32)) { 11856 11857 UChar p2_1f,p2_20,p2_2b,p2_42,p2_43; 11858 UShort temp; 11859 int mult; 11860 11861 p2_1f = pSiS->p2_1f; 11862 p2_20 = pSiS->p2_20; 11863 p2_2b = pSiS->p2_2b; 11864 p2_42 = pSiS->p2_42; 11865 p2_43 = pSiS->p2_43; 11866#ifdef SISDUALHEAD 11867 if(pSiSEnt && pSiS->DualHeadMode) { 11868 p2_1f = pSiSEnt->p2_1f; 11869 p2_20 = pSiSEnt->p2_20; 11870 p2_2b = pSiSEnt->p2_2b; 11871 p2_42 = pSiSEnt->p2_42; 11872 p2_43 = pSiSEnt->p2_43; 11873 } 11874#endif 11875 mult = 2; 11876 if(pSiS->VBFlags & TV_YPBPR) { 11877 if(pSiS->VBFlags & (TV_YPBPR1080I | TV_YPBPR750P)) { 11878 mult = 4; 11879 } 11880 } 11881 11882 temp = p2_1f | ((p2_20 & 0xf0) << 4); 11883 temp += (val * mult); 11884 p2_1f = temp & 0xff; 11885 p2_20 = (temp & 0xf00) >> 4; 11886 p2_2b = ((p2_2b & 0x0f) + (val * mult)) & 0x0f; 11887 temp = p2_43 | ((p2_42 & 0xf0) << 4); 11888 temp += (val * mult); 11889 p2_43 = temp & 0xff; 11890 p2_42 = (temp & 0xf00) >> 4; 11891 SISWaitRetraceCRT2(pScrn); 11892 outSISIDXREG(SISPART2,0x1f,p2_1f); 11893 setSISIDXREG(SISPART2,0x20,0x0F,p2_20); 11894 setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b); 11895 setSISIDXREG(SISPART2,0x42,0x0F,p2_42); 11896 outSISIDXREG(SISPART2,0x43,p2_43); 11897 } 11898 } 11899 } 11900 11901 } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { 11902 11903 if(pSiS->SiS6326Flags & SIS6326_TVDETECTED) { 11904 11905 UChar tmp; 11906 UShort temp1, temp2, temp3; 11907 11908 tmp = SiS6326GetTVReg(pScrn,0x00); 11909 if(tmp & 0x04) { 11910 11911 temp1 = pSiS->tvx1; 11912 temp2 = pSiS->tvx2; 11913 temp3 = pSiS->tvx3; 11914 if((val >= -16) && (val <= 16)) { 11915 if(val > 0) { 11916 temp1 += (val * 4); 11917 temp2 += (val * 4); 11918 while((temp1 > 0x0fff) || (temp2 > 0x0fff)) { 11919 temp1 -= 4; 11920 temp2 -= 4; 11921 } 11922 } else { 11923 val = -val; 11924 temp3 += (val * 4); 11925 while(temp3 > 0x03ff) { 11926 temp3 -= 4; 11927 } 11928 } 11929 } 11930 SiS6326SetTVReg(pScrn,0x3a,(temp1 & 0xff)); 11931 tmp = SiS6326GetTVReg(pScrn,0x3c); 11932 tmp &= 0xf0; 11933 tmp |= ((temp1 & 0x0f00) >> 8); 11934 SiS6326SetTVReg(pScrn,0x3c,tmp); 11935 SiS6326SetTVReg(pScrn,0x26,(temp2 & 0xff)); 11936 tmp = SiS6326GetTVReg(pScrn,0x27); 11937 tmp &= 0x0f; 11938 tmp |= ((temp2 & 0x0f00) >> 4); 11939 SiS6326SetTVReg(pScrn,0x27,tmp); 11940 SiS6326SetTVReg(pScrn,0x12,(temp3 & 0xff)); 11941 tmp = SiS6326GetTVReg(pScrn,0x13); 11942 tmp &= ~0xC0; 11943 tmp |= ((temp3 & 0x0300) >> 2); 11944 SiS6326SetTVReg(pScrn,0x13,tmp); 11945 } 11946 } 11947 } 11948} 11949 11950int SiS_GetTVxposoffset(ScrnInfoPtr pScrn) 11951{ 11952 SISPtr pSiS = SISPTR(pScrn); 11953#ifdef SISDUALHEAD 11954 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11955 11956 if(pSiSEnt && pSiS->DualHeadMode) 11957 return (int)pSiSEnt->tvxpos; 11958 else 11959#endif 11960 return (int)pSiS->tvxpos; 11961} 11962 11963void SiS_SetTVyposoffset(ScrnInfoPtr pScrn, int val) 11964{ 11965 SISPtr pSiS = SISPTR(pScrn); 11966#ifdef SISDUALHEAD 11967 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11968#endif 11969 11970#ifdef UNLOCK_ALWAYS 11971 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11972#endif 11973 11974 pSiS->tvypos = val; 11975#ifdef SISDUALHEAD 11976 if(pSiSEnt) pSiSEnt->tvypos = val; 11977#endif 11978 11979 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 11980 11981 if(pSiS->VBFlags & CRT2_TV) { 11982 11983 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 11984 11985 int y = pSiS->tvy; 11986#ifdef SISDUALHEAD 11987 if(pSiSEnt && pSiS->DualHeadMode) y = pSiSEnt->tvy; 11988#endif 11989 switch(pSiS->ChrontelType) { 11990 case CHRONTEL_700x: 11991 if((val >= -32) && (val <= 32)) { 11992 y -= val; 11993 if(y < 0) y = 0; 11994 SiS_SetCH700x(pSiS->SiS_Pr, 0x0b, (y & 0xff)); 11995 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE); 11996 } 11997 break; 11998 case CHRONTEL_701x: 11999 /* Not supported by hardware */ 12000 break; 12001 } 12002 12003 } else if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 12004 12005 if((val >= -32) && (val <= 32)) { 12006 char p2_01, p2_02; 12007 12008 if( (pSiS->VBFlags & TV_HIVISION) || 12009 ((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & (TV_YPBPR1080I|TV_YPBPR750P))) ) { 12010 val *= 2; 12011 } else { 12012 val /= 2; /* 4 */ 12013 } 12014 12015 p2_01 = pSiS->p2_01; 12016 p2_02 = pSiS->p2_02; 12017#ifdef SISDUALHEAD 12018 if(pSiSEnt && pSiS->DualHeadMode) { 12019 p2_01 = pSiSEnt->p2_01; 12020 p2_02 = pSiSEnt->p2_02; 12021 } 12022#endif 12023 p2_01 += val; /* val * 2 */ 12024 p2_02 += val; /* val * 2 */ 12025 if(!(pSiS->VBFlags & (TV_YPBPR | TV_HIVISION))) { 12026 while((p2_01 <= 0) || (p2_02 <= 0)) { 12027 p2_01 += 2; 12028 p2_02 += 2; 12029 } 12030 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR1080I)) { 12031 while(p2_01 <= 8) { 12032 p2_01 += 2; 12033 p2_02 += 2; 12034 } 12035 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR750P)) { 12036 while(p2_01 <= 10) { 12037 p2_01 += 2; 12038 p2_02 += 2; 12039 } 12040 } 12041 12042 SISWaitRetraceCRT2(pScrn); 12043 outSISIDXREG(SISPART2,0x01,p2_01); 12044 outSISIDXREG(SISPART2,0x02,p2_02); 12045 } 12046 } 12047 12048 } 12049 12050 } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { 12051 12052 if(pSiS->SiS6326Flags & SIS6326_TVDETECTED) { 12053 12054 UChar tmp; 12055 int temp1, limit; 12056 12057 tmp = SiS6326GetTVReg(pScrn,0x00); 12058 if(tmp & 0x04) { 12059 12060 if((val >= -16) && (val <= 16)) { 12061 temp1 = (UShort)pSiS->tvy1; 12062 limit = (pSiS->SiS6326Flags & SIS6326_TVPAL) ? 625 : 525; 12063 if(val > 0) { 12064 temp1 += (val * 4); 12065 if(temp1 > limit) temp1 -= limit; 12066 } else { 12067 val = -val; 12068 temp1 -= (val * 2); 12069 if(temp1 <= 0) temp1 += (limit -1); 12070 } 12071 SiS6326SetTVReg(pScrn,0x11,(temp1 & 0xff)); 12072 tmp = SiS6326GetTVReg(pScrn,0x13); 12073 tmp &= ~0x30; 12074 tmp |= ((temp1 & 0x300) >> 4); 12075 SiS6326SetTVReg(pScrn,0x13,tmp); 12076 if(temp1 == 1) tmp = 0x10; 12077 else { 12078 if(pSiS->SiS6326Flags & SIS6326_TVPAL) { 12079 if((temp1 <= 3) || (temp1 >= (limit - 2))) tmp = 0x08; 12080 else if(temp1 < 22) tmp = 0x02; 12081 else tmp = 0x04; 12082 } else { 12083 if((temp1 <= 5) || (temp1 >= (limit - 4))) tmp = 0x08; 12084 else if(temp1 < 19) tmp = 0x02; 12085 else tmp = 0x04; 12086 } 12087 } 12088 SiS6326SetTVReg(pScrn,0x21,tmp); 12089 } 12090 } 12091 } 12092 } 12093} 12094 12095int SiS_GetTVyposoffset(ScrnInfoPtr pScrn) 12096{ 12097 SISPtr pSiS = SISPTR(pScrn); 12098#ifdef SISDUALHEAD 12099 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12100 12101 if(pSiSEnt && pSiS->DualHeadMode) 12102 return (int)pSiSEnt->tvypos; 12103 else 12104#endif 12105 return (int)pSiS->tvypos; 12106} 12107 12108void SiS_SetTVxscale(ScrnInfoPtr pScrn, int val) 12109{ 12110 SISPtr pSiS = SISPTR(pScrn); 12111#ifdef SISDUALHEAD 12112 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12113#endif 12114 12115#ifdef UNLOCK_ALWAYS 12116 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12117#endif 12118 12119 pSiS->tvxscale = val; 12120#ifdef SISDUALHEAD 12121 if(pSiSEnt) pSiSEnt->tvxscale = val; 12122#endif 12123 12124 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 12125 12126 if((pSiS->VBFlags & CRT2_TV) && (pSiS->VBFlags2 & VB2_SISBRIDGE)) { 12127 12128 if((val >= -16) && (val <= 16)) { 12129 12130 UChar p2_44,p2_45,p2_46; 12131 int scalingfactor, mult; 12132 12133 p2_44 = pSiS->p2_44; 12134 p2_45 = pSiS->p2_45 & 0x3f; 12135 p2_46 = pSiS->p2_46 & 0x07; 12136#ifdef SISDUALHEAD 12137 if(pSiSEnt && pSiS->DualHeadMode) { 12138 p2_44 = pSiSEnt->p2_44; 12139 p2_45 = pSiSEnt->p2_45 & 0x3f; 12140 p2_46 = pSiSEnt->p2_46 & 0x07; 12141 } 12142#endif 12143 scalingfactor = (p2_46 << 13) | ((p2_45 & 0x1f) << 8) | p2_44; 12144 12145 mult = 64; 12146 if(pSiS->VBFlags & TV_YPBPR) { 12147 if(pSiS->VBFlags & TV_YPBPR1080I) { 12148 mult = 190; 12149 } else if(pSiS->VBFlags & TV_YPBPR750P) { 12150 mult = 360; 12151 } 12152 } else if(pSiS->VBFlags & TV_HIVISION) { 12153 mult = 190; 12154 } 12155 12156 if(val < 0) { 12157 p2_45 &= 0xdf; 12158 scalingfactor += ((-val) * mult); 12159 if(scalingfactor > 0xffff) scalingfactor = 0xffff; 12160 } else if(val > 0) { 12161 p2_45 &= 0xdf; 12162 scalingfactor -= (val * mult); 12163 if(scalingfactor < 1) scalingfactor = 1; 12164 } 12165 12166 p2_44 = scalingfactor & 0xff; 12167 p2_45 &= 0xe0; 12168 p2_45 |= ((scalingfactor >> 8) & 0x1f); 12169 p2_46 = ((scalingfactor >> 13) & 0x07); 12170 12171 SISWaitRetraceCRT2(pScrn); 12172 outSISIDXREG(SISPART2,0x44,p2_44); 12173 setSISIDXREG(SISPART2,0x45,0xC0,p2_45); 12174 if(!(pSiS->VBFlags2 & VB2_301)) { 12175 setSISIDXREG(SISPART2,0x46,0xF8,p2_46); 12176 } 12177 12178 } 12179 12180 } 12181 12182 } 12183} 12184 12185int SiS_GetTVxscale(ScrnInfoPtr pScrn) 12186{ 12187 SISPtr pSiS = SISPTR(pScrn); 12188#ifdef SISDUALHEAD 12189 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12190 12191 if(pSiSEnt && pSiS->DualHeadMode) 12192 return (int)pSiSEnt->tvxscale; 12193 else 12194#endif 12195 return (int)pSiS->tvxscale; 12196} 12197 12198void SiS_SetTVyscale(ScrnInfoPtr pScrn, int val) 12199{ 12200 SISPtr pSiS = SISPTR(pScrn); 12201#ifdef SISDUALHEAD 12202 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12203#endif 12204 12205#ifdef UNLOCK_ALWAYS 12206 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12207#endif 12208 12209 if(val < -4) val = -4; 12210 if(val > 3) val = 3; 12211 12212 pSiS->tvyscale = val; 12213#ifdef SISDUALHEAD 12214 if(pSiSEnt) pSiSEnt->tvyscale = val; 12215#endif 12216 12217 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 12218 12219 if((pSiS->VBFlags & CRT2_TV) && (pSiS->VBFlags2 & VB2_SISBRIDGE)) { 12220 12221 int srindex = -1, newvde, i = 0, j, vlimit, temp, vdediv; 12222 int hdclk = 0; 12223 UChar p3d4_34; 12224 Bool found = FALSE; 12225 Bool usentsc = FALSE; 12226 Bool is750p = FALSE; 12227 Bool is1080i = FALSE; 12228 Bool skipmoveup = FALSE; 12229 12230 SiS_UnLockCRT2(pSiS->SiS_Pr); 12231 12232 if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR525P)) { 12233 vlimit = 525 - 7; 12234 vdediv = 1; 12235 usentsc = TRUE; 12236 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR625P)) { 12237 vlimit = 625 - 7; 12238 vdediv = 1; 12239 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR750P)) { 12240 vlimit = 750 - 7; 12241 vdediv = 1; 12242 is750p = TRUE; 12243 } else if(((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR1080I)) || 12244 (pSiS->VBFlags & TV_HIVISION)) { 12245 vlimit = (1125 - 7) / 2; 12246 vdediv = 2; 12247 is1080i = TRUE; 12248 } else { 12249 if( ((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR525I)) || 12250 ((!(pSiS->VBFlags & TV_YPBPR)) && (pSiS->VBFlags & (TV_NTSC | TV_PALM))) ) { 12251 usentsc = TRUE; 12252 } 12253 vlimit = usentsc ? 259 : 309; 12254 vdediv = 2; 12255 } 12256 12257 inSISIDXREG(SISCR,0x34,p3d4_34); 12258 12259 switch((p3d4_34 & 0x7f)) { 12260 case 0x50: /* 320x240 */ 12261 case 0x56: 12262 case 0x53: 12263 hdclk = 1; 12264 /* fall through */ 12265 case 0x2e: /* 640x480 */ 12266 case 0x44: 12267 case 0x62: 12268 if(is1080i) { 12269 srindex = 98; 12270 } else if(is750p) { 12271 srindex = 42; 12272 } else { 12273 srindex = usentsc ? 0 : 21; 12274 } 12275 break; 12276 case 0x31: /* 720x480 */ 12277 case 0x33: 12278 case 0x35: 12279 if(is1080i) { 12280 /* n/a */ 12281 } else if(is750p) { 12282 srindex = 49; 12283 } else { 12284 srindex = usentsc ? 7 : 21; 12285 } 12286 break; 12287 case 0x32: /* 720x576 */ 12288 case 0x34: 12289 case 0x36: 12290 case 0x5f: /* 768x576 */ 12291 case 0x60: 12292 case 0x61: 12293 if(is1080i) { 12294 /* n/a */ 12295 } else if(is750p) { 12296 srindex = 56; 12297 } else { 12298 srindex = usentsc ? 147 : 28; 12299 } 12300 break; 12301 case 0x70: /* 800x480 */ 12302 case 0x7a: 12303 case 0x76: 12304 if(is1080i) { 12305 srindex = 105; 12306 } else if(is750p) { 12307 srindex = 63; 12308 } else { 12309 srindex = usentsc ? 175 : 21; 12310 } 12311 break; 12312 case 0x51: /* 400x300 - hdclk mode */ 12313 case 0x57: 12314 case 0x54: 12315 hdclk = 1; 12316 /* fall through */ 12317 case 0x30: /* 800x600 */ 12318 case 0x47: 12319 case 0x63: 12320 if(is1080i) { 12321 srindex = 112; 12322 } else if(is750p) { 12323 srindex = 70; 12324 } else { 12325 srindex = usentsc ? 14 : 35; 12326 } 12327 break; 12328 case 0x1d: /* 960x540 */ 12329 case 0x1e: 12330 case 0x1f: 12331 if(is1080i) { 12332 srindex = 196; 12333 skipmoveup = TRUE; 12334 } 12335 break; 12336 case 0x20: /* 960x600 */ 12337 case 0x21: 12338 case 0x22: 12339 if(pSiS->VGAEngine == SIS_315_VGA && is1080i) { 12340 srindex = 203; 12341 } 12342 break; 12343 case 0x71: /* 1024x576 */ 12344 case 0x74: 12345 case 0x77: 12346 if(is1080i) { 12347 srindex = 119; 12348 } else if(is750p) { 12349 srindex = 77; 12350 } else { 12351 srindex = usentsc ? 182 : 189; 12352 } 12353 break; 12354 case 0x52: /* 512x384 */ 12355 case 0x58: 12356 case 0x5c: 12357 hdclk = 1; 12358 /* fall through */ 12359 case 0x38: /* 1024x768 */ 12360 case 0x4a: 12361 case 0x64: 12362 if(is1080i) { 12363 srindex = 126; 12364 } else if(is750p) { 12365 srindex = 84; 12366 } else if(!usentsc) { 12367 srindex = 154; 12368 } else if(vdediv == 1) { 12369 if(!hdclk) srindex = 168; 12370 } else { 12371 if(!hdclk) srindex = 161; 12372 } 12373 break; 12374 case 0x79: /* 1280x720 */ 12375 case 0x75: 12376 case 0x78: 12377 if(is1080i) { 12378 srindex = 133; 12379 } else if(is750p) { 12380 srindex = 91; 12381 } 12382 break; 12383 case 0x3a: /* 1280x1024 */ 12384 case 0x4d: 12385 case 0x65: 12386 if(is1080i) { 12387 srindex = 140; 12388 } 12389 break; 12390 } 12391 12392 if(srindex < 0) return; 12393 12394 if(pSiS->tvyscale != 0) { 12395 for(j = 0; j <= 1; j++) { 12396 for(i = 0; i <= 6; i++) { 12397 if(SiSTVVScale[srindex+i].sindex == pSiS->tvyscale) { 12398 found = TRUE; 12399 break; 12400 } 12401 } 12402 if(found) break; 12403 if(pSiS->tvyscale > 0) pSiS->tvyscale--; 12404 else pSiS->tvyscale++; 12405 } 12406 } 12407 12408#ifdef SISDUALHEAD 12409 if(pSiSEnt) pSiSEnt->tvyscale = pSiS->tvyscale; 12410#endif 12411 12412 if(pSiS->tvyscale == 0) { 12413 UChar p2_0a = pSiS->p2_0a; 12414 UChar p2_2f = pSiS->p2_2f; 12415 UChar p2_30 = pSiS->p2_30; 12416 UChar p2_46 = pSiS->p2_46; 12417 UChar p2_47 = pSiS->p2_47; 12418 UChar p1scaling[9], p4scaling[9]; 12419 UChar *p2scaling; 12420 12421 for(i = 0; i < 9; i++) { 12422 p1scaling[i] = pSiS->scalingp1[i]; 12423 p4scaling[i] = pSiS->scalingp4[i]; 12424 } 12425 p2scaling = &pSiS->scalingp2[0]; 12426 12427#ifdef SISDUALHEAD 12428 if(pSiSEnt && pSiS->DualHeadMode) { 12429 p2_0a = pSiSEnt->p2_0a; 12430 p2_2f = pSiSEnt->p2_2f; 12431 p2_30 = pSiSEnt->p2_30; 12432 p2_46 = pSiSEnt->p2_46; 12433 p2_47 = pSiSEnt->p2_47; 12434 for(i = 0; i < 9; i++) { 12435 p1scaling[i] = pSiSEnt->scalingp1[i]; 12436 p4scaling[i] = pSiSEnt->scalingp4[i]; 12437 } 12438 p2scaling = &pSiSEnt->scalingp2[0]; 12439 } 12440#endif 12441 SISWaitRetraceCRT2(pScrn); 12442 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 12443 for(i = 0; i < 64; i++) { 12444 outSISIDXREG(SISPART2,(0xc0 + i),p2scaling[i]); 12445 } 12446 } 12447 for(i = 0; i < 9; i++) { 12448 outSISIDXREG(SISPART1,SiSScalingP1Regs[i],p1scaling[i]); 12449 } 12450 for(i = 0; i < 9; i++) { 12451 outSISIDXREG(SISPART4,SiSScalingP4Regs[i],p4scaling[i]); 12452 } 12453 12454 setSISIDXREG(SISPART2,0x0a,0x7f,(p2_0a & 0x80)); 12455 outSISIDXREG(SISPART2,0x2f,p2_2f); 12456 setSISIDXREG(SISPART2,0x30,0x3f,(p2_30 & 0xc0)); 12457 if(!(pSiS->VBFlags2 & VB2_301)) { 12458 setSISIDXREG(SISPART2,0x46,0x9f,(p2_46 & 0x60)); 12459 outSISIDXREG(SISPART2,0x47,p2_47); 12460 } 12461 12462 } else { 12463 12464 int realvde, myypos, watchdog = 32; 12465 unsigned short temp1, temp2, vgahde, vgaht, vgavt; 12466 int p1div = 1; 12467 ULong calctemp; 12468 12469 srindex += i; 12470 newvde = SiSTVVScale[srindex].ScaleVDE; 12471 realvde = SiSTVVScale[srindex].RealVDE; 12472 12473 if(vdediv == 1) p1div = 2; 12474 12475 if(!skipmoveup) { 12476 do { 12477 inSISIDXREG(SISPART2,0x01,temp); 12478 temp = vlimit - ((temp & 0x7f) / p1div); 12479 if((temp - (((newvde / vdediv) - 2) + 9)) > 0) break; 12480 myypos = pSiS->tvypos - 1; 12481#ifdef SISDUALHEAD 12482 if(pSiSEnt && pSiS->DualHeadMode) myypos = pSiSEnt->tvypos - 1; 12483#endif 12484 SiS_SetTVyposoffset(pScrn, myypos); 12485 } while(watchdog--); 12486 } 12487 12488 SISWaitRetraceCRT2(pScrn); 12489 12490 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 12491 SiS_CalcXTapScaler(pSiS->SiS_Pr, realvde, newvde, 4, FALSE); 12492 } 12493 12494 if(!(pSiS->VBFlags2 & VB2_301)) { 12495 temp = (newvde / vdediv) - 3; 12496 setSISIDXREG(SISPART2,0x46,0x9f,((temp & 0x0300) >> 3)); 12497 outSISIDXREG(SISPART2,0x47,(temp & 0xff)); 12498 } 12499 12500 inSISIDXREG(SISPART1,0x0a,temp1); 12501 inSISIDXREG(SISPART1,0x0c,temp2); 12502 vgahde = ((temp2 & 0xf0) << 4) | temp1; 12503 if(pSiS->VGAEngine == SIS_300_VGA) { 12504 vgahde -= 12; 12505 } else { 12506 vgahde -= 16; 12507 if(hdclk) vgahde <<= 1; 12508 } 12509 12510 vgaht = SiSTVVScale[srindex].reg[0]; 12511 temp1 = vgaht; 12512 if((pSiS->VGAEngine == SIS_315_VGA) && hdclk) temp1 >>= 1; 12513 temp1--; 12514 outSISIDXREG(SISPART1,0x08,(temp1 & 0xff)); 12515 setSISIDXREG(SISPART1,0x09,0x0f,((temp1 >> 4) & 0xf0)); 12516 12517 temp2 = (vgaht - vgahde) >> 2; 12518 if(pSiS->VGAEngine == SIS_300_VGA) { 12519 temp1 = vgahde + 12 + temp2; 12520 temp2 = temp1 + (temp2 << 1); 12521 } else { 12522 temp1 = vgahde; 12523 if(hdclk) { 12524 temp1 >>= 1; 12525 temp2 >>= 1; 12526 } 12527 temp2 >>= 1; 12528 temp1 = temp1 + 16 + temp2; 12529 temp2 = temp1 + temp2; 12530 } 12531 outSISIDXREG(SISPART1,0x0b,(temp1 & 0xff)); 12532 setSISIDXREG(SISPART1,0x0c,0xf0,((temp1 >> 8) & 0x0f)); 12533 outSISIDXREG(SISPART1,0x0d,(temp2 & 0xff)); 12534 12535 vgavt = SiSTVVScale[srindex].reg[1]; 12536 temp1 = vgavt - 1; 12537 if(pSiS->VGAEngine == SIS_315_VGA) temp1--; 12538 outSISIDXREG(SISPART1,0x0e,(temp1 & 0xff)); 12539 setSISIDXREG(SISPART1,0x12,0xf8,((temp1 >> 8 ) & 0x07)); 12540 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->ChipType >= SIS_661)) { 12541 temp1 = (vgavt + SiSTVVScale[srindex].RealVDE) >> 1; 12542 temp2 = ((vgavt - SiSTVVScale[srindex].RealVDE) >> 4) + temp1 + 1; 12543 } else { 12544 temp1 = (vgavt - SiSTVVScale[srindex].RealVDE) >> 2; 12545 temp2 = (temp1 < 4) ? 4 : temp1; 12546 temp1 += SiSTVVScale[srindex].RealVDE; 12547 temp2 = (temp2 >> 2) + temp1 + 1; 12548 } 12549 outSISIDXREG(SISPART1,0x10,(temp1 & 0xff)); 12550 setSISIDXREG(SISPART1,0x11,0x8f,((temp1 >> 4) & 0x70)); 12551 setSISIDXREG(SISPART1,0x11,0xf0,(temp2 & 0x0f)); 12552 12553 setSISIDXREG(SISPART2,0x0a,0x7f,((SiSTVVScale[srindex].reg[2] >> 8) & 0x80)); 12554 outSISIDXREG(SISPART2,0x2f,((newvde / vdediv) - 2)); 12555 setSISIDXREG(SISPART2,0x30,0x3f,((((newvde / vdediv) - 2) >> 2) & 0xc0)); 12556 12557 outSISIDXREG(SISPART4,0x13,(SiSTVVScale[srindex].reg[2] & 0xff)); 12558 outSISIDXREG(SISPART4,0x14,(SiSTVVScale[srindex].reg[3] & 0xff)); 12559 setSISIDXREG(SISPART4,0x15,0x7f,((SiSTVVScale[srindex].reg[3] >> 1) & 0x80)); 12560 12561 temp1 = vgaht - 1; 12562 outSISIDXREG(SISPART4,0x16,(temp1 & 0xff)); 12563 setSISIDXREG(SISPART4,0x15,0x87,((temp1 >> 5) & 0x78)); 12564 12565 temp1 = vgavt - 1; 12566 outSISIDXREG(SISPART4,0x17,(temp1 & 0xff)); 12567 setSISIDXREG(SISPART4,0x15,0xf8,((temp1 >> 8) & 0x07)); 12568 12569 outSISIDXREG(SISPART4,0x18,0x00); 12570 setSISIDXREG(SISPART4,0x19,0xf0,0x00); 12571 12572 inSISIDXREG(SISPART4,0x0e,temp1); 12573 if(is1080i) { 12574 if(!(temp1 & 0xe0)) newvde >>= 1; 12575 } 12576 12577 temp = 0x40; 12578 if(realvde <= newvde) temp = 0; 12579 else realvde -= newvde; 12580 12581 calctemp = (realvde * 256 * 1024) / newvde; 12582 if((realvde * 256 * 1024) % newvde) calctemp++; 12583 outSISIDXREG(SISPART4,0x1b,(calctemp & 0xff)); 12584 outSISIDXREG(SISPART4,0x1a,((calctemp >> 8) & 0xff)); 12585 setSISIDXREG(SISPART4,0x19,0x8f,(((calctemp >> 12) & 0x70) | temp)); 12586 } 12587 12588 } 12589 12590 } 12591} 12592 12593int SiS_GetTVyscale(ScrnInfoPtr pScrn) 12594{ 12595 SISPtr pSiS = SISPTR(pScrn); 12596#ifdef SISDUALHEAD 12597 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12598 12599 if(pSiSEnt && pSiS->DualHeadMode) 12600 return (int)pSiSEnt->tvyscale; 12601 else 12602#endif 12603 return (int)pSiS->tvyscale; 12604} 12605 12606void SiS_SetSISCRT1SaturationGain(ScrnInfoPtr pScrn, int val) 12607{ 12608 SISPtr pSiS = SISPTR(pScrn); 12609#ifdef SISDUALHEAD 12610 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12611#endif 12612 12613 pSiS->siscrt1satgain = val; 12614#ifdef SISDUALHEAD 12615 if(pSiSEnt) pSiSEnt->siscrt1satgain = val; 12616#endif 12617 12618 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_CRT1SATGAIN)) return; 12619 12620#ifdef UNLOCK_ALWAYS 12621 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12622#endif 12623 12624 if((val >= 0) && (val <= 7)) { 12625 setSISIDXREG(SISCR,0x53,0xE3, (val << 2)); 12626 } 12627} 12628 12629int SiS_GetSISCRT1SaturationGain(ScrnInfoPtr pScrn) 12630{ 12631 SISPtr pSiS = SISPTR(pScrn); 12632 int result = pSiS->siscrt1satgain; 12633 UChar temp; 12634#ifdef SISDUALHEAD 12635 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12636 12637 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->siscrt1satgain; 12638#endif 12639 12640 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_CRT1SATGAIN)) return result; 12641 12642#ifdef UNLOCK_ALWAYS 12643 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12644#endif 12645 inSISIDXREG(SISCR, 0x53, temp); 12646 return (int)((temp >> 2) & 0x07); 12647} 12648 12649/* Calc dotclock from registers */ 12650static int 12651SiSGetClockFromRegs(UChar sr2b, UChar sr2c) 12652{ 12653 float num, denum, postscalar, divider; 12654 int myclock; 12655 12656 divider = (sr2b & 0x80) ? 2.0 : 1.0; 12657 postscalar = (sr2c & 0x80) ? 12658 ( (((sr2c >> 5) & 0x03) == 0x02) ? 6.0 : 8.0 ) : 12659 ( ((sr2c >> 5) & 0x03) + 1.0 ); 12660 num = (sr2b & 0x7f) + 1.0; 12661 denum = (sr2c & 0x1f) + 1.0; 12662 myclock = (int)((14318 * (divider / postscalar) * (num / denum)) / 1000); 12663 return myclock; 12664} 12665 12666#ifdef SISDUALHEAD 12667static void 12668SiS_SetDHFlags(SISPtr pSiS, unsigned int misc, unsigned int sd2) 12669{ 12670 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12671 12672 if(pSiS->DualHeadMode) { 12673 if(pSiSEnt->pScrn_1) { 12674 SISPTR(pSiSEnt->pScrn_1)->MiscFlags |= misc; 12675 SISPTR(pSiSEnt->pScrn_1)->SiS_SD2_Flags |= sd2; 12676 } 12677 if(pSiSEnt->pScrn_2) { 12678 SISPTR(pSiSEnt->pScrn_2)->MiscFlags |= misc; 12679 SISPTR(pSiSEnt->pScrn_2)->SiS_SD2_Flags |= sd2; 12680 } 12681 } 12682} 12683#endif 12684 12685/* PostSetMode: 12686 * -) Disable CRT1 for saving bandwidth. This doesn't work with VESA; 12687 * VESA uses the bridge in SlaveMode and switching CRT1 off while 12688 * the bridge is in SlaveMode not that clever... 12689 * -) Check if overlay can be used (depending on dotclock) 12690 * -) Check if Panel Scaler is active on LVDS for overlay re-scaling 12691 * -) Save TV registers for further processing 12692 * -) Apply TV settings 12693 */ 12694static void 12695SiSPostSetMode(ScrnInfoPtr pScrn, SISRegPtr sisReg) 12696{ 12697 SISPtr pSiS = SISPTR(pScrn); 12698#ifdef SISDUALHEAD 12699 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12700#endif 12701 UChar usScratchCR17, sr2b, sr2c, tmpreg; 12702 int myclock1, myclock2, mycoldepth1, mycoldepth2, temp; 12703 Bool flag = FALSE; 12704 Bool doit = TRUE; 12705 Bool IsInSlaveMode; 12706 12707#ifdef TWDEBUG 12708 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 12709 "CRT1off is %d\n", pSiS->CRT1off); 12710#endif 12711 pSiS->CRT1isoff = pSiS->CRT1off; 12712 12713#ifdef UNLOCK_ALWAYS 12714 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12715#endif 12716 12717 SiSFixupSR11(pScrn); 12718 12719 IsInSlaveMode = SiSBridgeIsInSlaveMode(pScrn); 12720 12721 if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE)) { 12722 12723 if(pSiS->VBFlags != pSiS->VBFlags_backup) { 12724 pSiS->VBFlags = pSiS->VBFlags_backup; 12725 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 12726 "VBFlags restored to %0x\n", pSiS->VBFlags); 12727 } 12728 12729 /* -) We can't switch off CRT1 if bridge is in SlaveMode. 12730 * -) If we change to a SlaveMode-Mode (like 512x384), we 12731 * need to adapt VBFlags for eg. Xv. 12732 */ 12733#ifdef SISDUALHEAD 12734 if(!pSiS->DualHeadMode) { 12735#endif 12736 if(IsInSlaveMode) { 12737 doit = FALSE; 12738 temp = pSiS->VBFlags; 12739 pSiS->VBFlags &= (~VB_DISPMODE_SINGLE); 12740 pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_DISP1); 12741 if(temp != pSiS->VBFlags) { 12742 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 12743 "VBFlags changed to 0x%0x\n", pSiS->VBFlags); 12744 } 12745 } 12746#ifdef SISDUALHEAD 12747 } 12748#endif 12749 12750 if(pSiS->VGAEngine == SIS_315_VGA) { 12751 12752 if((pSiS->CRT1off) && (doit)) { 12753 orSISIDXREG(SISCR,pSiS->myCR63,0x40); 12754 orSISIDXREG(SISSR,0x1f,0xc0); 12755 andSISIDXREG(SISSR,0x07,~0x10); 12756 andSISIDXREG(SISSR,0x06,0xe2); 12757 andSISIDXREG(SISSR,0x31,0xcf); 12758 outSISIDXREG(SISSR,0x2b,0x1b); 12759 outSISIDXREG(SISSR,0x2c,0xe1); 12760 outSISIDXREG(SISSR,0x2d,0x01); 12761 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 12762 usleep(10000); 12763 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 12764 } else { 12765 andSISIDXREG(SISCR,pSiS->myCR63,0xBF); 12766 andSISIDXREG(SISSR,0x1f,0x3f); 12767 orSISIDXREG(SISSR,0x07,0x10); 12768 } 12769 12770 } else { 12771 12772 if(doit) { 12773 inSISIDXREG(SISCR, 0x17, usScratchCR17); 12774 if(pSiS->CRT1off) { 12775 if(usScratchCR17 & 0x80) { 12776 flag = TRUE; 12777 usScratchCR17 &= ~0x80; 12778 } 12779 orSISIDXREG(SISSR,0x1f,0xc0); 12780 } else { 12781 if(!(usScratchCR17 & 0x80)) { 12782 flag = TRUE; 12783 usScratchCR17 |= 0x80; 12784 } 12785 andSISIDXREG(SISSR,0x1f,0x3f); 12786 } 12787 /* Reset only if status changed */ 12788 if(flag) { 12789 outSISIDXREG(SISCR, 0x17, usScratchCR17); 12790 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 12791 usleep(10000); 12792 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 12793 } 12794 } 12795 } 12796 12797 } 12798 12799 /* Set bridge to "disable CRT2" mode if CRT2 is disabled, LCD-A is enabled */ 12800 /* (Not needed for CRT1=VGA since CRT2 will really be disabled then) */ 12801#ifdef SISDUALHEAD 12802 if(!pSiS->DualHeadMode) { 12803#endif 12804 if((pSiS->VGAEngine == SIS_315_VGA) && (pSiS->VBFlags2 & VB2_SISLCDABRIDGE)) { 12805 if((!pSiS->UseVESA) && (!(pSiS->VBFlags & CRT2_ENABLE)) && (pSiS->VBFlags & CRT1_LCDA)) { 12806 if(!IsInSlaveMode) { 12807 andSISIDXREG(SISPART4,0x0d,~0x07); 12808 } 12809 } 12810 } 12811#ifdef SISDUALHEAD 12812 } 12813#endif 12814 12815 /* Reset flags */ 12816 pSiS->MiscFlags &= ~( MISC_CRT1OVERLAY | 12817 MISC_CRT2OVERLAY | 12818 MISC_CRT1OVERLAYGAMMA | 12819 MISC_SIS760ONEOVERLAY | 12820 MISC_PANELLINKSCALER | 12821 MISC_STNMODE | 12822 MISC_TVNTSC1024); 12823 12824 pSiS->SiS_SD2_Flags &= ~SiS_SD2_SIS760ONEOVL; 12825 12826#ifdef SISDUALHEAD 12827 if(pSiS->DualHeadMode) { 12828 if(pSiSEnt->pScrn_1) { 12829 SISPTR(pSiSEnt->pScrn_1)->MiscFlags &= ~(MISC_SIS760ONEOVERLAY | 12830 MISC_CRT1OVERLAY | 12831 MISC_CRT2OVERLAY | 12832 MISC_CRT1OVERLAYGAMMA | 12833 MISC_PANELLINKSCALER | 12834 MISC_STNMODE | 12835 MISC_TVNTSC1024); 12836 SISPTR(pSiSEnt->pScrn_1)->SiS_SD2_Flags &= ~SiS_SD2_SIS760ONEOVL; 12837 } 12838 if(pSiSEnt->pScrn_2) { 12839 SISPTR(pSiSEnt->pScrn_2)->MiscFlags &= ~(MISC_SIS760ONEOVERLAY | 12840 MISC_CRT1OVERLAY | 12841 MISC_CRT2OVERLAY | 12842 MISC_CRT1OVERLAYGAMMA | 12843 MISC_PANELLINKSCALER | 12844 MISC_STNMODE | 12845 MISC_TVNTSC1024); 12846 SISPTR(pSiSEnt->pScrn_2)->SiS_SD2_Flags &= ~SiS_SD2_SIS760ONEOVL; 12847 } 12848 } 12849#endif 12850 12851 /* Determine if the video overlay can be used */ 12852 if(!pSiS->NoXvideo) { 12853 12854 int clklimit1=0, clklimit2=0, clklimitg=0; 12855 Bool OverlayHandled = FALSE; 12856 12857 inSISIDXREG(SISSR,0x2b,sr2b); 12858 inSISIDXREG(SISSR,0x2c,sr2c); 12859 myclock1 = myclock2 = SiSGetClockFromRegs(sr2b, sr2c); 12860 inSISIDXREG(SISSR,0x06,tmpreg); 12861 switch((tmpreg & 0x1c) >> 2) { 12862 case 0: mycoldepth1 = 1; break; 12863 case 1: 12864 case 2: mycoldepth1 = 2; break; 12865 default: mycoldepth1 = 4; 12866 } 12867 mycoldepth2 = mycoldepth1; 12868 12869 if((!IsInSlaveMode) && (pSiS->VBFlags & CRT2_ENABLE)) { 12870 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 12871 inSISIDXREG(SISPART4,0x0a,sr2b); 12872 inSISIDXREG(SISPART4,0x0b,sr2c); 12873 } else { 12874 inSISIDXREG(SISSR,0x2e,sr2b); 12875 inSISIDXREG(SISSR,0x2f,sr2c); 12876 } 12877 myclock2 = SiSGetClockFromRegs(sr2b, sr2c); 12878 inSISIDXREG(SISPART1,0x00,tmpreg); 12879 tmpreg &= 0x0f; 12880 switch(tmpreg) { 12881 case 8: mycoldepth2 = 1; break; 12882 case 4: 12883 case 2: mycoldepth2 = 2; break; 12884 default: mycoldepth2 = 4; 12885 } 12886 } 12887 12888 switch(pSiS->ChipType) { 12889 12890 case SIS_300: 12891 case SIS_540: 12892 case SIS_630: 12893 case SIS_730: 12894 clklimit1 = clklimit2 = clklimitg = 150; 12895 break; 12896 12897 case SIS_550: 12898 case SIS_650: 12899 case SIS_740: 12900 clklimit1 = clklimit2 = 175; /* verified for 65x */ 12901 clklimitg = 166; /* ? */ 12902 break; 12903 12904 case SIS_661: 12905 case SIS_741: 12906 clklimit1 = clklimit2 = 190; /* ? */ 12907 clklimitg = 180; /* ? */ 12908 break; 12909 12910 case SIS_760: 12911 case SIS_761: 12912 clklimit1 = clklimit2 = 190; /* ? */ 12913 if(pSiS->ChipFlags & SiSCF_760LFB) { /* LFB only or hybrid */ 12914 clklimit1 = clklimit2 = 220; /* ? */ 12915 } 12916 clklimitg = 200; /* ? */ 12917 12918 if(pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORT760OO) { /* UMA only */ 12919 12920 Bool OnlyOne = FALSE, NoOverlay = FALSE; 12921 int dotclocksum = 0; 12922 12923 if(pSiS->VBFlags & DISPTYPE_CRT1) dotclocksum += myclock1; 12924 if((!IsInSlaveMode) && (pSiS->VBFlags & CRT2_ENABLE)) dotclocksum += myclock2; 12925 12926 /* TODO: Find out under what circumstances only one 12927 * overlay is usable in UMA-only mode. 12928 * This is not entirely accurate; the overlay 12929 * scaler also requires some time, so even though 12930 * the dotclocks are below these values, some 12931 * distortions in the overlay may occure. 12932 * Solution: Don't use a 760 with shared memory. 12933 */ 12934 if( (pSiS->VBFlags & DISPTYPE_CRT1) && 12935 (pSiS->VBFlags & CRT2_ENABLE) && 12936 (mycoldepth1 != mycoldepth2) ) { 12937 12938 /* 0. If coldepths are different (only possible in dual head mode), 12939 * I have no idea to calculate the limits; hence, allow only one 12940 * overlay in all cases. 12941 */ 12942 OnlyOne = TRUE; 12943 12944 } else if(pSiS->MemClock < 150000) { 12945 12946 /* 1. MCLK <150: If someone seriously considers using such 12947 * slow RAM, so be it. Only one overlay in call cases. 12948 */ 12949 OnlyOne = TRUE; 12950 12951 } else if(pSiS->MemClock < 170000) { 12952 12953 /* 2. MCLK 166 */ 12954 switch(pSiS->CurrentLayout.bitsPerPixel) { 12955 case 32: if(dotclocksum > 133) OnlyOne = TRUE; /* One overlay; verified */ 12956 if(dotclocksum > 180) NoOverlay = TRUE; /* No overlay; verified */ 12957 break; 12958 case 16: if(dotclocksum > 175) OnlyOne = TRUE; /* One overlay; verified */ 12959 if(dotclocksum > 260) NoOverlay = TRUE;; /* No overlay; FIXME */ 12960 break; 12961 } 12962 12963 } else if(pSiS->MemClock < 210000) { 12964 12965 /* 3. MCLK 200 */ 12966 switch(pSiS->CurrentLayout.bitsPerPixel) { 12967 case 32: if(dotclocksum > 160) OnlyOne = TRUE; /* One overlay; FIXME */ 12968 if(dotclocksum > 216) NoOverlay = TRUE;; /* No overlay; FIXME */ 12969 break; 12970 case 16: if(dotclocksum > 210) OnlyOne = TRUE; /* One overlay; FIXME */ 12971 if(dotclocksum > 312) NoOverlay = TRUE;; /* No overlay; FIXME */ 12972 break; 12973 } 12974 12975 } 12976 12977 if(OnlyOne || NoOverlay) { 12978 12979 ULong tmpflags = 0; 12980 12981 if(!NoOverlay) { 12982 if(myclock1 <= clklimit1) tmpflags |= MISC_CRT1OVERLAY; 12983 if(myclock2 <= clklimit2) tmpflags |= MISC_CRT2OVERLAY; 12984 if(myclock1 <= clklimitg) tmpflags |= MISC_CRT1OVERLAYGAMMA; 12985 pSiS->MiscFlags |= tmpflags; 12986 } 12987 pSiS->MiscFlags |= MISC_SIS760ONEOVERLAY; 12988 pSiS->SiS_SD2_Flags |= SiS_SD2_SIS760ONEOVL; 12989#ifdef SISDUALHEAD 12990 SiS_SetDHFlags(pSiS, (tmpflags | MISC_SIS760ONEOVERLAY), SiS_SD2_SIS760ONEOVL); 12991#endif 12992 OverlayHandled = TRUE; 12993 } 12994 12995 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 12996 "SiS76x/UMA: %s video overlay(s) available in current mode\n", 12997 NoOverlay ? "no" : ((pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) ? "one" : "two")); 12998 12999#ifdef TWDEBUG 13000 xf86DrvMsg(0, 0, "SiS760: Memclock %d, c1 %d/%d c2 %d/%d, sum %d / %x\n", 13001 pSiS->MemClock, myclock1, mycoldepth1, 13002 myclock2, mycoldepth2, dotclocksum, pSiS->SiS_SD2_Flags); 13003#endif 13004 } 13005 break; 13006 13007 case SIS_660: 13008 clklimit1 = clklimit2 = 200; /* ? */ 13009 if(pSiS->ChipFlags & SiSCF_760LFB) { /* LFB only */ 13010 clklimit1 = clklimit2 = 220; 13011 } 13012 clklimitg = 200; /* ? */ 13013 break; 13014 13015 case SIS_315H: 13016 case SIS_315: 13017 case SIS_315PRO: 13018 case SIS_330: 13019 clklimit1 = clklimit2 = 180; /* ? */ 13020 clklimitg = 166; /* ? */ 13021 break; 13022 13023 case SIS_340: /* ? */ 13024 case XGI_20: 13025 case XGI_40: 13026 clklimit1 = clklimit2 = 240; /* ? */ 13027 clklimitg = 200; /* ? */ 13028 break; 13029 } 13030 13031 if(!OverlayHandled) { 13032 ULong tmpflags = 0; 13033 if(myclock1 <= clklimit1) tmpflags |= MISC_CRT1OVERLAY; 13034 if(myclock2 <= clklimit2) tmpflags |= MISC_CRT2OVERLAY; 13035 if(myclock1 <= clklimitg) tmpflags |= MISC_CRT1OVERLAYGAMMA; 13036 pSiS->MiscFlags |= tmpflags; 13037#ifdef SISDUALHEAD 13038 SiS_SetDHFlags(pSiS, tmpflags, 0); 13039#endif 13040 if(!(pSiS->MiscFlags & MISC_CRT1OVERLAY)) { 13041#ifdef SISDUALHEAD 13042 if((!pSiS->DualHeadMode) || (pSiS->SecondHead)) 13043#endif 13044 xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, 3, 13045 "Current dotclock (%dMhz) too high for video overlay on CRT1\n", 13046 myclock1); 13047 } 13048 if((pSiS->VBFlags & CRT2_ENABLE) && (!(pSiS->MiscFlags & MISC_CRT2OVERLAY))) { 13049#ifdef SISDUALHEAD 13050 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) 13051#endif 13052 xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, 3, 13053 "Current dotclock (%dMhz) too high for video overlay on CRT2\n", 13054 myclock2); 13055 } 13056 } 13057 13058 } 13059 13060 /* Determine if the Panel Link scaler is active */ 13061 13062 if(pSiS->VBFlags & (CRT2_LCD | CRT1_LCDA)) { 13063 ULong tmpflags = 0; 13064 if(pSiS->VGAEngine == SIS_300_VGA) { 13065 if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) { 13066 inSISIDXREG(SISPART1,0x1e,tmpreg); 13067 tmpreg &= 0x3f; 13068 if(tmpreg) tmpflags |= MISC_PANELLINKSCALER; 13069 } 13070 } else { 13071 if((pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) || (pSiS->VBFlags & CRT1_LCDA)) { 13072 inSISIDXREG(SISPART1,0x35,tmpreg); 13073 tmpreg &= 0x04; 13074 if(!tmpreg) tmpflags |= MISC_PANELLINKSCALER; 13075 } 13076 } 13077 pSiS->MiscFlags |= tmpflags; 13078#ifdef SISDUALHEAD 13079 SiS_SetDHFlags(pSiS, tmpflags, 0); 13080#endif 13081 } 13082 13083 /* Determine if STN is active */ 13084 if(pSiS->ChipType == SIS_550) { 13085 if((pSiS->VBFlags & CRT2_LCD) && (pSiS->FSTN || pSiS->DSTN)) { 13086 inSISIDXREG(SISCR,0x34,tmpreg); 13087 tmpreg &= 0x7f; 13088 if(tmpreg == 0x5a || tmpreg == 0x5b) { 13089 pSiS->MiscFlags |= MISC_STNMODE; 13090#ifdef SISDUALHEAD 13091 SiS_SetDHFlags(pSiS, MISC_STNMODE, 0); 13092#endif 13093 } 13094 } 13095 } 13096 13097 /* Determine if our very special TV mode is active */ 13098 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && (pSiS->VBFlags & CRT2_TV) && (!(pSiS->VBFlags & TV_HIVISION))) { 13099 if( ((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR525I)) || 13100 ((!(pSiS->VBFlags & TV_YPBPR)) && (pSiS->VBFlags & (TV_NTSC | TV_PALM))) ) { 13101 inSISIDXREG(SISCR,0x34,tmpreg); 13102 tmpreg &= 0x7f; 13103 if((tmpreg == 0x64) || (tmpreg == 0x4a) || (tmpreg == 0x38)) { 13104 pSiS->MiscFlags |= MISC_TVNTSC1024; 13105#ifdef SISDUALHEAD 13106 SiS_SetDHFlags(pSiS, MISC_TVNTSC1024, 0); 13107#endif 13108 } 13109 } 13110 } 13111 13112 if(pSiS->VGAEngine == SIS_315_VGA) { 13113 int i; 13114#ifdef SISVRAMQ 13115 /* Re-Enable and reset command queue */ 13116 SiSEnableTurboQueue(pScrn); 13117#endif 13118 /* Get HWCursor register contents for backup */ 13119 for(i = 0; i < 16; i++) { 13120 pSiS->HWCursorBackup[i] = SIS_MMIO_IN32(pSiS->IOBase, 0x8500 + (i << 2)); 13121 } 13122 if(pSiS->ChipType >= SIS_330) { 13123 /* Enable HWCursor protection (Y pos as trigger) */ 13124 andSISIDXREG(SISCR, 0x5b, ~0x30); 13125 } 13126 } 13127 13128 /* Re-initialize accelerator engine */ 13129 /* (We are sync'ed here) */ 13130 if(!pSiS->NoAccel) { 13131 if(pSiS->InitAccel) { 13132 (pSiS->InitAccel)(pScrn); 13133 } 13134 } 13135 13136 /* Set display device gamma (for SISCTRL) */ 13137 if(pSiS->VBFlags & CRT1_LCDA) 13138 pSiS->CRT1MonGamma = pSiS->CRT2LCDMonitorGamma; 13139 else 13140 pSiS->CRT1MonGamma = pSiS->CRT1VGAMonitorGamma; 13141 13142 if(pSiS->VBFlags & CRT2_LCD) 13143 pSiS->CRT2MonGamma = pSiS->CRT2LCDMonitorGamma; 13144 else if(pSiS->VBFlags & CRT2_TV) { 13145 if(pSiS->VBFlags & TV_YPBPR) 13146 pSiS->CRT2MonGamma = 2200; /* */ 13147 else if(pSiS->VBFlags & TV_HIVISION) 13148 pSiS->CRT2MonGamma = 2200; /* ? */ 13149 else if(pSiS->VBFlags & TV_NTSC) 13150 pSiS->CRT2MonGamma = 2200; /* NTSC */ 13151 else 13152 pSiS->CRT2MonGamma = 2800; /* All PAL modes? */ 13153 } else if(pSiS->VBFlags & CRT2_VGA) 13154 pSiS->CRT2MonGamma = pSiS->CRT2VGAMonitorGamma; 13155 else 13156 pSiS->CRT2MonGamma = 0; /* Unknown */ 13157 13158 /* Reset XV display properties (such as number of overlays, etc) */ 13159 /* (And copy monitor gamma) */ 13160#ifdef SISDUALHEAD 13161 if(pSiS->DualHeadMode) { 13162 if(pSiSEnt->pScrn_1) { 13163 if(SISPTR(pSiSEnt->pScrn_1)->ResetXvDisplay) { 13164 (SISPTR(pSiSEnt->pScrn_1)->ResetXvDisplay)(pSiSEnt->pScrn_1); 13165 } 13166 SISPTR(pSiSEnt->pScrn_1)->CRT1MonGamma = pSiS->CRT1MonGamma; 13167 SISPTR(pSiSEnt->pScrn_1)->CRT2MonGamma = pSiS->CRT2MonGamma; 13168 } 13169 if(pSiSEnt->pScrn_2) { 13170 if(SISPTR(pSiSEnt->pScrn_2)->ResetXvDisplay) { 13171 (SISPTR(pSiSEnt->pScrn_1)->ResetXvDisplay)(pSiSEnt->pScrn_2); 13172 } 13173 SISPTR(pSiSEnt->pScrn_2)->CRT1MonGamma = pSiS->CRT1MonGamma; 13174 SISPTR(pSiSEnt->pScrn_2)->CRT2MonGamma = pSiS->CRT2MonGamma; 13175 } 13176 } else { 13177#endif 13178 if(pSiS->ResetXvDisplay) { 13179 (pSiS->ResetXvDisplay)(pScrn); 13180 } 13181#ifdef SISDUALHEAD 13182 } 13183#endif 13184 13185 /* Reset XV gamma correction */ 13186 if(pSiS->ResetXvGamma) { 13187 (pSiS->ResetXvGamma)(pScrn); 13188 } 13189 13190 /* Reset various display parameters */ 13191 { 13192 int val = pSiS->siscrt1satgain; 13193#ifdef SISDUALHEAD 13194 if(pSiS->DualHeadMode && pSiSEnt) val = pSiSEnt->siscrt1satgain; 13195#endif 13196 SiS_SetSISCRT1SaturationGain(pScrn, val); 13197 } 13198 13199 /* Apply TV settings given by options 13200 Do this even in DualHeadMode: 13201 - if this is called by SetModeCRT1, CRT2 mode has been reset by SetModeCRT1 13202 - if this is called by SetModeCRT2, CRT2 mode has changed (duh!) 13203 -> Hence, in both cases, the settings must be re-applied. 13204 */ 13205 13206 if(pSiS->VBFlags & CRT2_TV) { 13207 int val; 13208 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 13209 int mychtvlumabandwidthcvbs = pSiS->chtvlumabandwidthcvbs; 13210 int mychtvlumabandwidthsvideo = pSiS->chtvlumabandwidthsvideo; 13211 int mychtvlumaflickerfilter = pSiS->chtvlumaflickerfilter; 13212 int mychtvchromabandwidth = pSiS->chtvchromabandwidth; 13213 int mychtvchromaflickerfilter = pSiS->chtvchromaflickerfilter; 13214 int mychtvcvbscolor = pSiS->chtvcvbscolor; 13215 int mychtvtextenhance = pSiS->chtvtextenhance; 13216 int mychtvcontrast = pSiS->chtvcontrast; 13217 int mytvxpos = pSiS->tvxpos; 13218 int mytvypos = pSiS->tvypos; 13219#ifdef SISDUALHEAD 13220 if(pSiSEnt && pSiS->DualHeadMode) { 13221 mychtvlumabandwidthcvbs = pSiSEnt->chtvlumabandwidthcvbs; 13222 mychtvlumabandwidthsvideo = pSiSEnt->chtvlumabandwidthsvideo; 13223 mychtvlumaflickerfilter = pSiSEnt->chtvlumaflickerfilter; 13224 mychtvchromabandwidth = pSiSEnt->chtvchromabandwidth; 13225 mychtvchromaflickerfilter = pSiSEnt->chtvchromaflickerfilter; 13226 mychtvcvbscolor = pSiSEnt->chtvcvbscolor; 13227 mychtvtextenhance = pSiSEnt->chtvtextenhance; 13228 mychtvcontrast = pSiSEnt->chtvcontrast; 13229 mytvxpos = pSiSEnt->tvxpos; 13230 mytvypos = pSiSEnt->tvypos; 13231 } 13232#endif 13233 if((val = mychtvlumabandwidthcvbs) != -1) { 13234 SiS_SetCHTVlumabandwidthcvbs(pScrn, val); 13235 } 13236 if((val = mychtvlumabandwidthsvideo) != -1) { 13237 SiS_SetCHTVlumabandwidthsvideo(pScrn, val); 13238 } 13239 if((val = mychtvlumaflickerfilter) != -1) { 13240 SiS_SetCHTVlumaflickerfilter(pScrn, val); 13241 } 13242 if((val = mychtvchromabandwidth) != -1) { 13243 SiS_SetCHTVchromabandwidth(pScrn, val); 13244 } 13245 if((val = mychtvchromaflickerfilter) != -1) { 13246 SiS_SetCHTVchromaflickerfilter(pScrn, val); 13247 } 13248 if((val = mychtvcvbscolor) != -1) { 13249 SiS_SetCHTVcvbscolor(pScrn, val); 13250 } 13251 if((val = mychtvtextenhance) != -1) { 13252 SiS_SetCHTVtextenhance(pScrn, val); 13253 } 13254 if((val = mychtvcontrast) != -1) { 13255 SiS_SetCHTVcontrast(pScrn, val); 13256 } 13257 /* Backup default TV position registers */ 13258 switch(pSiS->ChrontelType) { 13259 case CHRONTEL_700x: 13260 pSiS->tvx = SiS_GetCH700x(pSiS->SiS_Pr, 0x0a); 13261 pSiS->tvx |= (((SiS_GetCH700x(pSiS->SiS_Pr, 0x08) & 0x02) >> 1) << 8); 13262 pSiS->tvy = SiS_GetCH700x(pSiS->SiS_Pr, 0x0b); 13263 pSiS->tvy |= ((SiS_GetCH700x(pSiS->SiS_Pr, 0x08) & 0x01) << 8); 13264#ifdef SISDUALHEAD 13265 if(pSiSEnt) { 13266 pSiSEnt->tvx = pSiS->tvx; 13267 pSiSEnt->tvy = pSiS->tvy; 13268 } 13269#endif 13270 break; 13271 case CHRONTEL_701x: 13272 /* Not supported by hardware */ 13273 break; 13274 } 13275 if((val = mytvxpos) != 0) { 13276 SiS_SetTVxposoffset(pScrn, val); 13277 } 13278 if((val = mytvypos) != 0) { 13279 SiS_SetTVyposoffset(pScrn, val); 13280 } 13281 } 13282 if(pSiS->VBFlags2 & VB2_301) { 13283 int mysistvedgeenhance = pSiS->sistvedgeenhance; 13284#ifdef SISDUALHEAD 13285 if(pSiSEnt && pSiS->DualHeadMode) { 13286 mysistvedgeenhance = pSiSEnt->sistvedgeenhance; 13287 } 13288#endif 13289 if((val = mysistvedgeenhance) != -1) { 13290 SiS_SetSISTVedgeenhance(pScrn, val); 13291 } 13292 } 13293 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 13294 int mysistvantiflicker = pSiS->sistvantiflicker; 13295 int mysistvsaturation = pSiS->sistvsaturation; 13296 int mysistvcolcalibf = pSiS->sistvcolcalibf; 13297 int mysistvcolcalibc = pSiS->sistvcolcalibc; 13298 int mysistvcfilter = pSiS->sistvcfilter; 13299 int mysistvyfilter = pSiS->sistvyfilter; 13300 int mytvxpos = pSiS->tvxpos; 13301 int mytvypos = pSiS->tvypos; 13302 int mytvxscale = pSiS->tvxscale; 13303 int mytvyscale = pSiS->tvyscale; 13304 int i; 13305 ULong cbase; 13306 UChar ctemp; 13307#ifdef SISDUALHEAD 13308 if(pSiSEnt && pSiS->DualHeadMode) { 13309 mysistvantiflicker = pSiSEnt->sistvantiflicker; 13310 mysistvsaturation = pSiSEnt->sistvsaturation; 13311 mysistvcolcalibf = pSiSEnt->sistvcolcalibf; 13312 mysistvcolcalibc = pSiSEnt->sistvcolcalibc; 13313 mysistvcfilter = pSiSEnt->sistvcfilter; 13314 mysistvyfilter = pSiSEnt->sistvyfilter; 13315 mytvxpos = pSiSEnt->tvxpos; 13316 mytvypos = pSiSEnt->tvypos; 13317 mytvxscale = pSiSEnt->tvxscale; 13318 mytvyscale = pSiSEnt->tvyscale; 13319 } 13320#endif 13321 /* Backup default TV position, scale and colcalib registers */ 13322 inSISIDXREG(SISPART2,0x1f,pSiS->p2_1f); 13323 inSISIDXREG(SISPART2,0x20,pSiS->p2_20); 13324 inSISIDXREG(SISPART2,0x2b,pSiS->p2_2b); 13325 inSISIDXREG(SISPART2,0x42,pSiS->p2_42); 13326 inSISIDXREG(SISPART2,0x43,pSiS->p2_43); 13327 inSISIDXREG(SISPART2,0x01,pSiS->p2_01); 13328 inSISIDXREG(SISPART2,0x02,pSiS->p2_02); 13329 inSISIDXREG(SISPART2,0x44,pSiS->p2_44); 13330 inSISIDXREG(SISPART2,0x45,pSiS->p2_45); 13331 if(!(pSiS->VBFlags2 & VB2_301)) { 13332 inSISIDXREG(SISPART2,0x46,pSiS->p2_46); 13333 } else { 13334 pSiS->p2_46 = 0; 13335 } 13336 inSISIDXREG(SISPART2,0x0a,pSiS->p2_0a); 13337 inSISIDXREG(SISPART2,0x31,cbase); 13338 cbase = (cbase & 0x7f) << 8; 13339 inSISIDXREG(SISPART2,0x32,ctemp); 13340 cbase = (cbase | ctemp) << 8; 13341 inSISIDXREG(SISPART2,0x33,ctemp); 13342 cbase = (cbase | ctemp) << 8; 13343 inSISIDXREG(SISPART2,0x34,ctemp); 13344 pSiS->sistvccbase = (cbase | ctemp); 13345 inSISIDXREG(SISPART2,0x35,pSiS->p2_35); 13346 inSISIDXREG(SISPART2,0x36,pSiS->p2_36); 13347 inSISIDXREG(SISPART2,0x37,pSiS->p2_37); 13348 inSISIDXREG(SISPART2,0x38,pSiS->p2_38); 13349 if(!(pSiS->VBFlags2 & VB2_301)) { 13350 inSISIDXREG(SISPART2,0x47,pSiS->p2_47); 13351 inSISIDXREG(SISPART2,0x48,pSiS->p2_48); 13352 inSISIDXREG(SISPART2,0x49,pSiS->p2_49); 13353 inSISIDXREG(SISPART2,0x4a,pSiS->p2_4a); 13354 } 13355 inSISIDXREG(SISPART2,0x2f,pSiS->p2_2f); 13356 inSISIDXREG(SISPART2,0x30,pSiS->p2_30); 13357 for(i=0; i<9; i++) { 13358 inSISIDXREG(SISPART1,SiSScalingP1Regs[i],pSiS->scalingp1[i]); 13359 } 13360 for(i=0; i<9; i++) { 13361 inSISIDXREG(SISPART4,SiSScalingP4Regs[i],pSiS->scalingp4[i]); 13362 } 13363 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 13364 for(i=0; i<64; i++) { 13365 inSISIDXREG(SISPART2,(0xc0 + i),pSiS->scalingp2[i]); 13366 } 13367 } 13368#ifdef SISDUALHEAD 13369 if(pSiSEnt) { 13370 pSiSEnt->p2_1f = pSiS->p2_1f; pSiSEnt->p2_20 = pSiS->p2_20; 13371 pSiSEnt->p2_42 = pSiS->p2_42; pSiSEnt->p2_43 = pSiS->p2_43; 13372 pSiSEnt->p2_2b = pSiS->p2_2b; 13373 pSiSEnt->p2_01 = pSiS->p2_01; pSiSEnt->p2_02 = pSiS->p2_02; 13374 pSiSEnt->p2_44 = pSiS->p2_44; pSiSEnt->p2_45 = pSiS->p2_45; 13375 pSiSEnt->p2_46 = pSiS->p2_46; pSiSEnt->p2_0a = pSiS->p2_0a; 13376 pSiSEnt->sistvccbase = pSiS->sistvccbase; 13377 pSiSEnt->p2_35 = pSiS->p2_35; pSiSEnt->p2_36 = pSiS->p2_36; 13378 pSiSEnt->p2_37 = pSiS->p2_37; pSiSEnt->p2_38 = pSiS->p2_38; 13379 pSiSEnt->p2_48 = pSiS->p2_48; pSiSEnt->p2_49 = pSiS->p2_49; 13380 pSiSEnt->p2_4a = pSiS->p2_4a; pSiSEnt->p2_2f = pSiS->p2_2f; 13381 pSiSEnt->p2_30 = pSiS->p2_30; pSiSEnt->p2_47 = pSiS->p2_47; 13382 for(i=0; i<9; i++) { 13383 pSiSEnt->scalingp1[i] = pSiS->scalingp1[i]; 13384 } 13385 for(i=0; i<9; i++) { 13386 pSiSEnt->scalingp4[i] = pSiS->scalingp4[i]; 13387 } 13388 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 13389 for(i=0; i<64; i++) { 13390 pSiSEnt->scalingp2[i] = pSiS->scalingp2[i]; 13391 } 13392 } 13393 } 13394#endif 13395 if((val = mysistvantiflicker) != -1) { 13396 SiS_SetSISTVantiflicker(pScrn, val); 13397 } 13398 if((val = mysistvsaturation) != -1) { 13399 SiS_SetSISTVsaturation(pScrn, val); 13400 } 13401 if((val = mysistvcfilter) != -1) { 13402 SiS_SetSISTVcfilter(pScrn, val); 13403 } 13404 if((val = mysistvyfilter) != 1) { 13405 SiS_SetSISTVyfilter(pScrn, val); 13406 } 13407 if((val = mysistvcolcalibc) != 0) { 13408 SiS_SetSISTVcolcalib(pScrn, val, TRUE); 13409 } 13410 if((val = mysistvcolcalibf) != 0) { 13411 SiS_SetSISTVcolcalib(pScrn, val, FALSE); 13412 } 13413 if((val = mytvxpos) != 0) { 13414 SiS_SetTVxposoffset(pScrn, val); 13415 } 13416 if((val = mytvypos) != 0) { 13417 SiS_SetTVyposoffset(pScrn, val); 13418 } 13419 if((val = mytvxscale) != 0) { 13420 SiS_SetTVxscale(pScrn, val); 13421 } 13422 if((val = mytvyscale) != 0) { 13423 SiS_SetTVyscale(pScrn, val); 13424 } 13425 } 13426 } 13427 13428} 13429 13430/* Post-set SiS6326 TV registers */ 13431static void 13432SiS6326PostSetMode(ScrnInfoPtr pScrn, SISRegPtr sisReg) 13433{ 13434 SISPtr pSiS = SISPTR(pScrn); 13435 UChar tmp; 13436 int val; 13437 13438 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 13439 13440#ifdef UNLOCK_ALWAYS 13441 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 13442#endif 13443 13444 /* Backup default TV position registers */ 13445 pSiS->tvx1 = SiS6326GetTVReg(pScrn,0x3a); 13446 pSiS->tvx1 |= ((SiS6326GetTVReg(pScrn,0x3c) & 0x0f) << 8); 13447 pSiS->tvx2 = SiS6326GetTVReg(pScrn,0x26); 13448 pSiS->tvx2 |= ((SiS6326GetTVReg(pScrn,0x27) & 0xf0) << 4); 13449 pSiS->tvx3 = SiS6326GetTVReg(pScrn,0x12); 13450 pSiS->tvx3 |= ((SiS6326GetTVReg(pScrn,0x13) & 0xC0) << 2); 13451 pSiS->tvy1 = SiS6326GetTVReg(pScrn,0x11); 13452 pSiS->tvy1 |= ((SiS6326GetTVReg(pScrn,0x13) & 0x30) << 4); 13453 13454 /* Handle TVPosOffset options (BEFORE switching on TV) */ 13455 if((val = pSiS->tvxpos) != 0) { 13456 SiS_SetTVxposoffset(pScrn, val); 13457 } 13458 if((val = pSiS->tvypos) != 0) { 13459 SiS_SetTVyposoffset(pScrn, val); 13460 } 13461 13462 /* Switch on TV output. This is rather complicated, but 13463 * if we don't do it, TV output will flicker terribly. 13464 */ 13465 if(pSiS->SiS6326Flags & SIS6326_TVON) { 13466 orSISIDXREG(SISSR, 0x01, 0x20); 13467 tmp = SiS6326GetTVReg(pScrn,0x00); 13468 tmp &= ~0x04; 13469 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 13470 SiS6326SetTVReg(pScrn,0x00,tmp); 13471 for(val=0; val < 2; val++) { 13472 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 13473 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 13474 } 13475 SiS6326SetTVReg(pScrn, 0x00, sisReg->sis6326tv[0]); 13476 tmp = inSISREG(SISINPSTAT); 13477 outSISREG(SISAR, 0x20); 13478 tmp = inSISREG(SISINPSTAT); 13479 while(inSISREG(SISINPSTAT) & 0x01); 13480 while(!(inSISREG(SISINPSTAT) & 0x01)); 13481 andSISIDXREG(SISSR, 0x01, ~0x20); 13482 for(val=0; val < 10; val++) { 13483 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 13484 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 13485 } 13486 andSISIDXREG(SISSR, 0x01, ~0x20); 13487 } 13488 13489 tmp = SiS6326GetTVReg(pScrn,0x00); 13490 if(!(tmp & 0x04)) return; 13491 13492 /* Apply TV settings given by options */ 13493 if((val = pSiS->sistvantiflicker) != -1) { 13494 SiS_SetSIS6326TVantiflicker(pScrn, val); 13495 } 13496 if((val = pSiS->sis6326enableyfilter) != -1) { 13497 SiS_SetSIS6326TVenableyfilter(pScrn, val); 13498 } 13499 if((val = pSiS->sis6326yfilterstrong) != -1) { 13500 SiS_SetSIS6326TVyfilterstrong(pScrn, val); 13501 } 13502 13503} 13504 13505/* Check if video bridge is in slave mode */ 13506Bool 13507SiSBridgeIsInSlaveMode(ScrnInfoPtr pScrn) 13508{ 13509 SISPtr pSiS = SISPTR(pScrn); 13510 UChar usScrP1_00; 13511 13512 if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return FALSE; 13513 13514 inSISIDXREG(SISPART1,0x00,usScrP1_00); 13515 if( ((pSiS->VGAEngine == SIS_300_VGA) && (usScrP1_00 & 0xa0) == 0x20) || 13516 ((pSiS->VGAEngine == SIS_315_VGA) && (usScrP1_00 & 0x50) == 0x10) ) { 13517 return TRUE; 13518 } 13519 13520 return FALSE; 13521} 13522 13523/* Build a list of the VESA modes the BIOS reports as valid */ 13524static void 13525SiSBuildVesaModeList(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe) 13526{ 13527 SISPtr pSiS = SISPTR(pScrn); 13528 int i = 0; 13529 13530 while(vbe->VideoModePtr[i] != 0xffff) { 13531 sisModeInfoPtr m; 13532 VbeModeInfoBlock *mode; 13533 int id = vbe->VideoModePtr[i++]; 13534 13535 if((mode = VBEGetModeInfo(pVbe, id)) == NULL) { 13536 continue; 13537 } 13538 13539 m = xnfcalloc(sizeof(sisModeInfoRec), 1); 13540 if(!m) { 13541 VBEFreeModeInfo(mode); 13542 continue; 13543 } 13544 m->width = mode->XResolution; 13545 m->height = mode->YResolution; 13546 m->bpp = mode->BitsPerPixel; 13547 m->n = id; 13548 m->next = pSiS->SISVESAModeList; 13549 13550 pSiS->SISVESAModeList = m; 13551 13552 VBEFreeModeInfo(mode); 13553 13554 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 13555 "VESA BIOS supports mode number 0x%x: %ix%i (%i bpp)\n", 13556 m->n, m->width, m->height, m->bpp); 13557 } 13558} 13559 13560/* Get VESA mode number from given resolution/depth */ 13561static UShort 13562SiSCalcVESAModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode) 13563{ 13564 SISPtr pSiS = SISPTR(pScrn); 13565 sisModeInfoPtr m = pSiS->SISVESAModeList; 13566 UShort i = (pScrn->bitsPerPixel+7)/8 - 1; 13567 UShort ModeNumber = 0; 13568 int j; 13569 13570 while(m) { 13571 if( (pScrn->bitsPerPixel == m->bpp) && 13572 (mode->HDisplay == m->width) && 13573 (mode->VDisplay == m->height) ) 13574 return m->n; 13575 m = m->next; 13576 } 13577 13578 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 13579 "No valid VESA BIOS mode found for %dx%d (%d bpp)\n", 13580 mode->HDisplay, mode->VDisplay, pScrn->bitsPerPixel); 13581 13582 if(!pSiS->ROM661New) { /* VESA numbers changed! */ 13583 j = 0; 13584 while(VESAModeIndices[j] != 9999) { 13585 if( (mode->HDisplay == VESAModeIndices[j]) && 13586 (mode->VDisplay == VESAModeIndices[j+1]) ) { 13587 ModeNumber = VESAModeIndices[j + 2 + i]; 13588 break; 13589 } 13590 j += 6; 13591 } 13592 13593 if(!ModeNumber) { 13594 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 13595 "No valid mode found for %dx%dx%d in built-in table either.\n", 13596 mode->HDisplay, mode->VDisplay, pScrn->bitsPerPixel); 13597 } 13598 } 13599 13600 return(ModeNumber); 13601} 13602 13603UShort 13604SiS_GetModeNumber(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned int VBFlags) 13605{ 13606 SISPtr pSiS = SISPTR(pScrn); 13607 UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; 13608 BOOLEAN FSTN = pSiS->FSTN ? TRUE : FALSE; 13609 13610#ifdef SISDUALHEAD 13611 if(pSiS->DualHeadMode && pSiS->SecondHead) FSTN = FALSE; 13612#endif 13613 13614 return(SiS_GetModeID(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, 13615 i, FSTN, pSiS->LCDwidth, pSiS->LCDheight)); 13616} 13617 13618static Bool 13619SiSValidLCDUserMode(SISPtr pSiS, unsigned int VBFlags, DisplayModePtr mode, Bool isforlcda) 13620{ 13621 if(mode->Flags & V_INTERLACE) return FALSE; 13622 13623 if(mode->HDisplay > 2048) return FALSE; 13624 if(mode->VDisplay > 1536) return FALSE; 13625 13626 if(pSiS->VBFlags2 & VB2_LCD162MHZBRIDGE) { 13627 if(mode->Clock > 162500) return FALSE; 13628#ifdef VB_FORBID_CRT2LCD_OVER_1600 13629 if(!isforlcda) { 13630 if(mode->HDisplay > 1600) return FALSE; 13631 } 13632#endif 13633 } else { /* 301, 301B, 302B (no LCDA!) */ 13634 if(mode->Clock > 130000) return FALSE; 13635 if(mode->Clock > 111000) { 13636 xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING, 13637 "WARNING: Mode clock beyond video bridge specs (%dMHz). Hardware damage might occure.\n", 13638 mode->Clock / 1000); 13639 } 13640 if(mode->HDisplay > 1600) return FALSE; 13641 if(mode->VDisplay > 1024) return FALSE; 13642 } 13643 13644 return TRUE; 13645} 13646 13647static Bool 13648SiSValidVGA2UserMode(SISPtr pSiS, unsigned int VBFlags, DisplayModePtr mode) 13649{ 13650 if(mode->Flags & V_INTERLACE) return FALSE; 13651 13652 if(mode->HDisplay > 2048) return FALSE; 13653 if(mode->VDisplay > 1536) return FALSE; 13654 13655 if(pSiS->VBFlags2 & VB2_RAMDAC202MHZBRIDGE) { 13656 if(mode->Clock > 203000) return FALSE; 13657 } else if(pSiS->VBFlags2 & VB2_30xBLV) { 13658 if(mode->Clock > 162500) return FALSE; 13659 } else { 13660 if(mode->Clock > 135500) return FALSE; 13661 } 13662 13663 return TRUE; 13664} 13665 13666UShort 13667SiS_CheckModeCRT1(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned int VBFlags, Bool havecustommodes) 13668{ 13669 SISPtr pSiS = SISPTR(pScrn); 13670 UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; 13671 int j; 13672 13673 if(!(VBFlags & CRT1_LCDA)) { 13674 13675 if((havecustommodes) && (!(mode->type & M_T_DEFAULT))) { 13676 return 0xfe; 13677 } 13678 13679 } else if(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE) { 13680 13681 if(pSiS->ChipType < SIS_661) { /* < 661 only? */ 13682 if(!(mode->type & M_T_DEFAULT)) { 13683 if(mode->HTotal > 2055) return 0; 13684 /* (Default mode will be caught in mode switching code) */ 13685 } 13686 } 13687 13688 if(pSiS->SiS_Pr->CP_HaveCustomData) { 13689 for(j=0; j<7; j++) { 13690 if((pSiS->SiS_Pr->CP_DataValid[j]) && 13691 (mode->HDisplay == pSiS->SiS_Pr->CP_HDisplay[j]) && 13692 (mode->VDisplay == pSiS->SiS_Pr->CP_VDisplay[j]) && 13693 (mode->type & M_T_BUILTIN)) 13694 return 0xfe; 13695 } 13696 } 13697 13698 if((pSiS->AddedPlasmaModes) && (mode->type & M_T_BUILTIN)) 13699 return 0xfe; 13700 13701 if((havecustommodes) && 13702 (pSiS->LCDwidth) && /* = test if LCD present */ 13703 (!(mode->type & M_T_DEFAULT)) && 13704 (SiSValidLCDUserMode(pSiS, VBFlags, mode, TRUE))) 13705 return 0xfe; 13706 13707 if((mode->HDisplay > pSiS->LCDwidth) || 13708 (mode->VDisplay > pSiS->LCDheight)) { 13709 return 0; 13710 } 13711 13712 } else { 13713 13714 if((mode->HDisplay > pSiS->LCDwidth) || 13715 (mode->VDisplay > pSiS->LCDheight)) { 13716 return 0; 13717 } 13718 13719 } 13720 13721 return(SiS_GetModeID(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, 13722 i, pSiS->FSTN, pSiS->LCDwidth, pSiS->LCDheight)); 13723} 13724 13725UShort 13726SiS_CheckModeCRT2(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned int VBFlags, Bool havecustommodes) 13727{ 13728 SISPtr pSiS = SISPTR(pScrn); 13729 UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; 13730 UShort ModeIndex = 0; 13731 int j; 13732 13733#ifdef TWDEBUG 13734 xf86DrvMsg(0, X_INFO, "Inside CheckCalcModeIndex (VBFlags %lx, mode %dx%d)\n", 13735 VBFlags,mode->HDisplay, mode->VDisplay); 13736#endif 13737 13738 if(VBFlags & CRT2_LCD) { /* CRT2 is LCD */ 13739 13740 if((pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && (!(pSiS->VBFlags2 & VB2_30xBDH))) { 13741 13742 if(pSiS->SiS_Pr->CP_HaveCustomData) { 13743 for(j=0; j<7; j++) { 13744 if((pSiS->SiS_Pr->CP_DataValid[j]) && 13745 (mode->HDisplay == pSiS->SiS_Pr->CP_HDisplay[j]) && 13746 (mode->VDisplay == pSiS->SiS_Pr->CP_VDisplay[j]) && 13747#ifdef VB_FORBID_CRT2LCD_OVER_1600 13748 (mode->HDisplay <= 1600) && 13749#endif 13750 (mode->type & M_T_BUILTIN)) 13751 return 0xfe; 13752 } 13753 } 13754 13755 /* All plasma modes have HDisplay <= 1600 */ 13756 if((pSiS->AddedPlasmaModes) && (mode->type & M_T_BUILTIN)) 13757 return 0xfe; 13758 13759 if((havecustommodes) && 13760 (pSiS->LCDwidth) && /* = test if LCD present */ 13761 (!(mode->type & M_T_DEFAULT)) && 13762 (SiSValidLCDUserMode(pSiS, VBFlags, mode, FALSE))) 13763 return 0xfe; 13764 13765 } 13766 13767 if( ((mode->HDisplay <= pSiS->LCDwidth) && 13768 (mode->VDisplay <= pSiS->LCDheight)) || 13769 ((pSiS->SiS_Pr->SiS_CustomT == CUT_PANEL848) && 13770 (((mode->HDisplay == 1360) && (mode->VDisplay == 768)) || 13771 ((mode->HDisplay == 1024) && (mode->VDisplay == 768)) || 13772 ((mode->HDisplay == 800) && (mode->VDisplay == 600)))) || 13773 ((pSiS->SiS_Pr->SiS_CustomT == CUT_PANEL856) && 13774 (((mode->HDisplay == 1024) && (mode->VDisplay == 768)) || 13775 ((mode->HDisplay == 800) && (mode->VDisplay == 600)))) ) { 13776 13777 ModeIndex = SiS_GetModeID_LCD(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, i, 13778 pSiS->FSTN, pSiS->SiS_Pr->SiS_CustomT, pSiS->LCDwidth, pSiS->LCDheight, 13779 pSiS->VBFlags2); 13780 13781 } 13782 13783 } else if(VBFlags & CRT2_TV) { /* CRT2 is TV */ 13784 13785 ModeIndex = SiS_GetModeID_TV(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, i, 13786 pSiS->VBFlags2); 13787 13788 } else if(VBFlags & CRT2_VGA) { /* CRT2 is VGA2 */ 13789 13790 if((pSiS->AddedPlasmaModes) && (mode->type & M_T_BUILTIN)) 13791 return 0xfe; 13792 13793 if((havecustommodes) && 13794 (!(mode->type & M_T_DEFAULT)) && 13795 (SiSValidVGA2UserMode(pSiS, VBFlags, mode))) 13796 return 0xfe; 13797 13798 ModeIndex = SiS_GetModeID_VGA2(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, i, 13799 pSiS->VBFlags2); 13800 13801 } else { /* no CRT2 */ 13802 13803 /* Return a valid mode number */ 13804 ModeIndex = 0xfe; 13805 13806 } 13807 13808 return(ModeIndex); 13809} 13810 13811/* Calculate the vertical refresh rate from a mode */ 13812float 13813SiSCalcVRate(DisplayModePtr mode) 13814{ 13815 float hsync, refresh = 0; 13816 13817 if(mode->HSync > 0.0) 13818 hsync = mode->HSync; 13819 else if(mode->HTotal > 0) 13820 hsync = (float)mode->Clock / (float)mode->HTotal; 13821 else 13822 hsync = 0.0; 13823 13824 if(mode->VTotal > 0) 13825 refresh = hsync * 1000.0 / mode->VTotal; 13826 13827 if(mode->Flags & V_INTERLACE) 13828 refresh *= 2.0; 13829 13830 if(mode->Flags & V_DBLSCAN) 13831 refresh /= 2.0; 13832 13833 if(mode->VScan > 1) 13834 refresh /= mode->VScan; 13835 13836 if(mode->VRefresh > 0.0) 13837 refresh = mode->VRefresh; 13838 13839 if(hsync == 0.0 || refresh == 0.0) return 0.0; 13840 13841 return refresh; 13842} 13843 13844/* Calculate CR33 (rate index) for CRT1. 13845 * Calculation is done using currentmode, therefore it is 13846 * recommended to set VertRefresh and HorizSync to correct 13847 * values in config file. 13848 */ 13849UChar 13850SISSearchCRT1Rate(ScrnInfoPtr pScrn, DisplayModePtr mode) 13851{ 13852 SISPtr pSiS = SISPTR(pScrn); 13853 int i = 0, irefresh; 13854 UShort xres = mode->HDisplay; 13855 UShort yres = mode->VDisplay; 13856 UChar index, defindex; 13857 Bool checksis730 = FALSE; 13858 13859 defindex = (xres == 800 || xres == 1024 || xres == 1280) ? 0x02 : 0x01; 13860 13861 irefresh = (int)SiSCalcVRate(mode); 13862 if(!irefresh) return defindex; 13863 13864 /* SiS730 has troubles on CRT2 if CRT1 is at 32bpp */ 13865 if( (pSiS->ChipType == SIS_730) && 13866 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && 13867 (pSiS->CurrentLayout.bitsPerPixel == 32) ) { 13868#ifdef SISDUALHEAD 13869 if(pSiS->DualHeadMode) { 13870 if(pSiS->SecondHead) { 13871 checksis730 = TRUE; 13872 } 13873 } else 13874#endif 13875 if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE) && (!pSiS->CRT1off)) { 13876 checksis730 = TRUE; 13877 } 13878 } 13879 13880#ifdef TWDEBUG 13881 xf86DrvMsg(0, X_INFO, "Debug: CalcVRate returned %d\n", irefresh); 13882#endif 13883 13884 /* We need the REAL refresh rate here */ 13885 if(mode->Flags & V_INTERLACE) irefresh /= 2; 13886 13887 /* Do not multiply by 2 when DBLSCAN! */ 13888 13889#ifdef TWDEBUG 13890 xf86DrvMsg(0, X_INFO, "Debug: Rate after correction = %d\n", irefresh); 13891#endif 13892 13893 index = 0; 13894 while((sisx_vrate[i].idx != 0) && (sisx_vrate[i].xres <= xres)) { 13895 if((sisx_vrate[i].xres == xres) && (sisx_vrate[i].yres == yres)) { 13896 if((checksis730 == FALSE) || (sisx_vrate[i].SiS730valid32bpp == TRUE)) { 13897 if(sisx_vrate[i].refresh == irefresh) { 13898 index = sisx_vrate[i].idx; 13899 break; 13900 } else if(sisx_vrate[i].refresh > irefresh) { 13901 if((sisx_vrate[i].refresh - irefresh) <= 3) { 13902 index = sisx_vrate[i].idx; 13903 } else if( ((checksis730 == FALSE) || (sisx_vrate[i - 1].SiS730valid32bpp == TRUE)) && 13904 ((irefresh - sisx_vrate[i - 1].refresh) <= 2) && 13905 (sisx_vrate[i].idx != 1) ) { 13906 index = sisx_vrate[i - 1].idx; 13907 } 13908 break; 13909 } else if((irefresh - sisx_vrate[i].refresh) <= 2) { 13910 index = sisx_vrate[i].idx; 13911 break; 13912 } 13913 } 13914 } 13915 i++; 13916 } 13917 13918 if(index > 0) return index; 13919 else return defindex; 13920} 13921 13922void 13923SISWaitRetraceCRT1(ScrnInfoPtr pScrn) 13924{ 13925 SISPtr pSiS = SISPTR(pScrn); 13926 int watchdog; 13927 UChar temp; 13928 13929 inSISIDXREG(SISCR,0x17,temp); 13930 if(!(temp & 0x80)) return; 13931 13932 inSISIDXREG(SISSR,0x1f,temp); 13933 if(temp & 0xc0) return; 13934 13935 watchdog = 65536; 13936 while((inSISREG(SISINPSTAT) & 0x08) && --watchdog); 13937 watchdog = 65536; 13938 while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog); 13939} 13940 13941void 13942SISWaitRetraceCRT2(ScrnInfoPtr pScrn) 13943{ 13944 SISPtr pSiS = SISPTR(pScrn); 13945 int watchdog; 13946 UChar temp, reg; 13947 13948 if(SiSBridgeIsInSlaveMode(pScrn)) { 13949 SISWaitRetraceCRT1(pScrn); 13950 return; 13951 } 13952 13953 switch(pSiS->VGAEngine) { 13954 case SIS_300_VGA: 13955 reg = 0x25; 13956 break; 13957 case SIS_315_VGA: 13958 reg = 0x30; 13959 break; 13960 default: 13961 return; 13962 } 13963 13964 watchdog = 65536; 13965 do { 13966 inSISIDXREG(SISPART1, reg, temp); 13967 if(!(temp & 0x02)) break; 13968 } while(--watchdog); 13969 watchdog = 65536; 13970 do { 13971 inSISIDXREG(SISPART1, reg, temp); 13972 if(temp & 0x02) break; 13973 } while(--watchdog); 13974} 13975 13976static void 13977SISWaitVBRetrace(ScrnInfoPtr pScrn) 13978{ 13979 SISPtr pSiS = SISPTR(pScrn); 13980 13981 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 13982#ifdef SISDUALHEAD 13983 if(pSiS->DualHeadMode) { 13984 if(pSiS->SecondHead) 13985 SISWaitRetraceCRT1(pScrn); 13986 else 13987 SISWaitRetraceCRT2(pScrn); 13988 } else { 13989#endif 13990 if(pSiS->VBFlags & DISPTYPE_DISP1) { 13991 SISWaitRetraceCRT1(pScrn); 13992 } 13993 if(pSiS->VBFlags & DISPTYPE_DISP2) { 13994 if(!(SiSBridgeIsInSlaveMode(pScrn))) { 13995 SISWaitRetraceCRT2(pScrn); 13996 } 13997 } 13998#ifdef SISDUALHEAD 13999 } 14000#endif 14001 } else { 14002 SISWaitRetraceCRT1(pScrn); 14003 } 14004} 14005 14006#define MODEID_OFF 0x449 14007 14008UChar 14009SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, UShort offset, UChar value) 14010{ 14011 UChar ret = 0; 14012#ifdef SIS_USE_BIOS_SCRATCH 14013 UChar *base; 14014#endif 14015 14016 /* For some reasons (like detecting the current display mode), 14017 * we need to read (or write-back) values from the BIOS 14018 * scratch area. This area is only valid for the primary 14019 * graphics card. For the secondary, we just return some 14020 * defaults and ignore requests to write data. As regards 14021 * the display mode: If sisfb is loaded for the secondary 14022 * card, it very probably has set a mode, but in any case 14023 * informed us via its info packet. So this here will not be 14024 * called for mode detection in this case. 14025 */ 14026 14027 switch(offset) { 14028 case 0x489: 14029 ret = 0x11; /* Default VGA Info */ 14030 break; 14031 case MODEID_OFF: 14032 ret = 0x03; /* Default current display mode */ 14033 break; 14034 } 14035 14036#ifndef XSERVER_LIBPCIACCESS 14037#ifdef SIS_USE_BIOS_SCRATCH 14038 if(SISPTR(pScrn)->Primary) { 14039 base = xf86MapVidMem(pScrn->scrnIndex, VIDMEM_MMIO, 0, 0x2000); 14040 if(!base) { 14041 SISErrorLog(pScrn, "(Could not map BIOS scratch area)\n"); 14042 return ret; 14043 } 14044 14045 ret = *(base + offset); 14046 14047 /* value != 0xff means: set register */ 14048 if(value != 0xff) { 14049 *(base + offset) = value; 14050 } 14051 14052 xf86UnMapVidMem(pScrn->scrnIndex, base, 0x2000); 14053 } 14054#endif 14055#endif 14056 return ret; 14057} 14058 14059UChar 14060SiS_GetSetModeID(ScrnInfoPtr pScrn, UChar id) 14061{ 14062 return(SiS_GetSetBIOSScratch(pScrn, MODEID_OFF, id)); 14063} 14064 14065void 14066SiSMemCopyToVideoRam(SISPtr pSiS, UChar *to, UChar *from, int size) 14067{ 14068 if((ULong)to & 15) (*pSiS->SiSFastMemCopy)(to, from, size); 14069 else (*pSiS->SiSFastVidCopy)(to, from, size); 14070} 14071 14072void 14073SiSMemCopyFromVideoRam(SISPtr pSiS, UChar *to, UChar *from, int size) 14074{ 14075 if((ULong)to & 15) (*pSiS->SiSFastMemCopyFrom)(to, from, size); 14076 else (*pSiS->SiSFastVidCopyFrom)(to, from, size); 14077} 14078 14079void 14080sisSaveUnlockExtRegisterLock(SISPtr pSiS, UChar *reg1, UChar *reg2) 14081{ 14082 register UChar val; 14083 ULong mylockcalls; 14084#ifdef TWDEBUG 14085 UChar val1, val2; 14086 int i; 14087#endif 14088 14089 pSiS->lockcalls++; 14090 mylockcalls = pSiS->lockcalls; 14091 14092 /* check if already unlocked */ 14093 inSISIDXREG(SISSR, 0x05, val); 14094 14095 if(val != 0xa1) { 14096 14097 /* save State */ 14098 if(reg1) *reg1 = val; 14099 14100 /* unlock */ 14101 outSISIDXREG(SISSR, 0x05, 0x86); 14102 14103 /* Now check again */ 14104 inSISIDXREG(SISSR, 0x05, val); 14105 14106 if(val != 0xA1) { 14107 14108 xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING, 14109 "Failed to unlock SR registers at relocated i/o ports\n"); 14110 14111#ifdef TWDEBUG 14112 for(i = 0; i <= 0x3f; i++) { 14113 inSISIDXREG(SISSR, i, val1); 14114 inSISIDXREG(0x3c4, i, val2); 14115 xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO, 14116 "SR%02d: RelIO=0x%02x 0x3c4=0x%02x (%ld)\n", 14117 i, val1, val2, mylockcalls); 14118 } 14119#endif 14120 14121 /* Emergency measure: unlock at 0x3c4, and try to enable relocated IO ports */ 14122 switch(pSiS->VGAEngine) { 14123 case SIS_OLD_VGA: 14124 case SIS_530_VGA: 14125 outSISIDXREG(0x3c4, 0x05, 0x86); 14126 andSISIDXREG(0x3c4, 0x33, ~0x20); 14127 break; 14128 case SIS_300_VGA: 14129 case SIS_315_VGA: 14130 outSISIDXREG(0x3c4, 0x05, 0x86); 14131 orSISIDXREG(0x3c4, 0x20, 0x20); 14132 break; 14133 } 14134 outSISIDXREG(SISSR, 0x05, 0x86); 14135 inSISIDXREG(SISSR, 0x05, val); 14136 if(val != 0xa1) { 14137 SISErrorLog(pSiS->pScrn, 14138 "Failed to unlock SR registers (%p, %lx, 0x%02x; %ld)\n", 14139 (void *)pSiS, (ULong)pSiS->RelIO, val, mylockcalls); 14140 /* Now await doom... */ 14141 } 14142 } 14143 } 14144 if((pSiS->VGAEngine == SIS_OLD_VGA) || (pSiS->VGAEngine == SIS_530_VGA)) { 14145 inSISIDXREG(SISCR, 0x80, val); 14146 if(val != 0xa1) { 14147 /* save State */ 14148 if(reg2) *reg2 = val; 14149 outSISIDXREG(SISCR, 0x80, 0x86); 14150 inSISIDXREG(SISCR, 0x80, val); 14151 if(val != 0xA1) { 14152 SISErrorLog(pSiS->pScrn, 14153 "Failed to unlock cr registers (%p, %lx, 0x%02x)\n", 14154 (void *)pSiS, (ULong)pSiS->RelIO, val); 14155 } 14156 } 14157 } 14158} 14159 14160void 14161sisRestoreExtRegisterLock(SISPtr pSiS, UChar reg1, UChar reg2) 14162{ 14163 /* restore lock */ 14164#ifndef UNLOCK_ALWAYS 14165 outSISIDXREG(SISSR, 0x05, reg1 == 0xA1 ? 0x86 : 0x00); 14166 if((pSiS->VGAEngine == SIS_OLD_VGA) || (pSiS->VGAEngine == SIS_530_VGA)) { 14167 outSISIDXREG(SISCR, 0x80, reg2 == 0xA1 ? 0x86 : 0x00); 14168 } 14169#endif 14170} 14171 14172