sis_driver.c revision 5788ca14
1/* 2 * SiS driver main code 3 * 4 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1) Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2) Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3) The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Author: Thomas Winischhofer <thomas@winischhofer.net> 29 * - driver entirely rewritten since 2001, only basic structure taken from 30 * old code (except sis_dri.c, sis_shadow.c, sis_accel.c and parts of 31 * sis_dga.c; these were mostly taken over; sis_dri.c was changed for 32 * new versions of the DRI layer) 33 * 34 * This notice covers the entire driver code unless indicated otherwise. 35 * 36 * Formerly based on code which was 37 * Copyright (C) 1998, 1999 by Alan Hourihane, Wigan, England. 38 * Written by: 39 * Alan Hourihane <alanh@fairlite.demon.co.uk>, 40 * Mike Chapman <mike@paranoia.com>, 41 * Juanjo Santamarta <santamarta@ctv.es>, 42 * Mitani Hiroshi <hmitani@drl.mei.co.jp>, 43 * David Thomas <davtom@dream.org.uk>. 44 */ 45 46#ifdef HAVE_CONFIG_H 47#include "config.h" 48#endif 49 50#include "sis.h" 51 52#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 53#include "xf86RAC.h" 54#endif 55#include "dixstruct.h" 56#include "shadowfb.h" 57#include "fb.h" 58#include "micmap.h" 59#include "mipointer.h" 60#include "mibstore.h" 61#include "edid.h" 62 63#define SIS_NEED_inSISREG 64#define SIS_NEED_inSISIDXREG 65#define SIS_NEED_outSISIDXREG 66#define SIS_NEED_orSISIDXREG 67#define SIS_NEED_andSISIDXREG 68#define SIS_NEED_setSISIDXREG 69#define SIS_NEED_outSISREG 70#define SIS_NEED_MYMMIO 71#define SIS_NEED_sisclearvram 72#include "sis_regs.h" 73#include "sis_dac.h" 74 75#include "sis_driver.h" 76 77#include <X11/extensions/xf86dgaproto.h> 78 79#include "globals.h" 80 81#ifdef HAVE_XEXTPROTO_71 82#include <X11/extensions/dpmsconst.h> 83#else 84#define DPMS_SERVER 85#include <X11/extensions/dpms.h> 86#endif 87 88#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 5 89#include <inputstr.h> /* for inputInfo */ 90#endif 91 92 93#ifdef SISDRI 94#include "dri.h" 95#endif 96 97/* 98 * LookupWindow was removed with video abi 11. 99 */ 100#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 4) 101#ifndef DixGetAttrAccess 102#define DixGetAttrAccess (1<<4) 103#endif 104#endif 105 106#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 2) 107static inline int 108dixLookupWindow(WindowPtr *pWin, XID id, ClientPtr client, Mask access) 109{ 110 *pWin = LookupWindow(id, client); 111 if (!*pWin) 112 return BadWindow; 113 return Success; 114} 115#endif 116 117/* Globals (yes, these ARE really required to be global) */ 118 119#ifdef SISUSEDEVPORT 120int sisdevport = 0; 121#endif 122 123#ifdef SISDUALHEAD 124static int SISEntityIndex = -1; 125#endif 126 127#ifdef SISMERGED 128#ifdef SISXINERAMA 129static Bool SiSnoPanoramiXExtension = TRUE; 130static int SiSXineramaNumScreens = 0; 131static SiSXineramaData *SiSXineramadataPtr = NULL; 132static int SiSXineramaGeneration; 133 134static int SiSProcXineramaQueryVersion(ClientPtr client); 135static int SiSProcXineramaGetState(ClientPtr client); 136static int SiSProcXineramaGetScreenCount(ClientPtr client); 137static int SiSProcXineramaGetScreenSize(ClientPtr client); 138static int SiSProcXineramaIsActive(ClientPtr client); 139static int SiSProcXineramaQueryScreens(ClientPtr client); 140static int SiSSProcXineramaDispatch(ClientPtr client); 141#endif 142#endif 143 144/* 145 * This is intentionally screen-independent. It indicates the binding 146 * choice made in the first PreInit. 147 */ 148static int pix24bpp = 0; 149 150/* 151 * This contains the functions needed by the server after loading the driver 152 * module. It must be supplied, and gets passed back by the SetupProc 153 * function in the dynamic case. In the static case, a reference to this 154 * is compiled in, and this requires that the name of this DriverRec be 155 * an upper-case version of the driver name. 156 */ 157 158#ifdef _X_EXPORT 159_X_EXPORT 160#endif 161DriverRec SIS = { 162 SIS_CURRENT_VERSION, 163 SIS_DRIVER_NAME, 164 SISIdentify, 165 SISProbe, 166 SISAvailableOptions, 167 NULL, 168 0 169#ifdef SIS_HAVE_DRIVER_FUNC 170 , 171 SISDriverFunc 172#endif 173}; 174 175static SymTabRec SISChipsets[] = { 176 { PCI_CHIP_SIS5597, "SIS5597/5598" }, 177 { PCI_CHIP_SIS530, "SIS530/620" }, 178 { PCI_CHIP_SIS6326, "SIS6326/AGP/DVD" }, 179 { PCI_CHIP_SIS300, "SIS300/305" }, 180 { PCI_CHIP_SIS630, "SIS630/730" }, 181 { PCI_CHIP_SIS540, "SIS540" }, 182 { PCI_CHIP_SIS315, "SIS315" }, 183 { PCI_CHIP_SIS315H, "SIS315H" }, 184 { PCI_CHIP_SIS315PRO, "SIS315PRO/E" }, 185 { PCI_CHIP_SIS550, "SIS550" }, 186 { PCI_CHIP_SIS650, "SIS650/M650/651/740" }, 187 { PCI_CHIP_SIS330, "SIS330(Xabre)" }, 188 { PCI_CHIP_SIS660, "SIS660/[M]661[F|M]X/[M]670/[M]741[GX]/[M]760[GX]/[M]761[GX]/[M]770[GX]" }, 189 { PCI_CHIP_SIS340, "SIS340" }, 190 { -1, NULL } 191}; 192 193static PciChipsets SISPciChipsets[] = { 194 { PCI_CHIP_SIS5597, PCI_CHIP_SIS5597, RES_SHARED_VGA }, 195 { PCI_CHIP_SIS530, PCI_CHIP_SIS530, RES_SHARED_VGA }, 196 { PCI_CHIP_SIS6326, PCI_CHIP_SIS6326, RES_SHARED_VGA }, 197 { PCI_CHIP_SIS300, PCI_CHIP_SIS300, RES_SHARED_VGA }, 198 { PCI_CHIP_SIS630, PCI_CHIP_SIS630, RES_SHARED_VGA }, 199 { PCI_CHIP_SIS540, PCI_CHIP_SIS540, RES_SHARED_VGA }, 200 { PCI_CHIP_SIS550, PCI_CHIP_SIS550, RES_SHARED_VGA }, 201 { PCI_CHIP_SIS315, PCI_CHIP_SIS315, RES_SHARED_VGA }, 202 { PCI_CHIP_SIS315H, PCI_CHIP_SIS315H, RES_SHARED_VGA }, 203 { PCI_CHIP_SIS315PRO, PCI_CHIP_SIS315PRO, RES_SHARED_VGA }, 204 { PCI_CHIP_SIS650, PCI_CHIP_SIS650, RES_SHARED_VGA }, 205 { PCI_CHIP_SIS330, PCI_CHIP_SIS330, RES_SHARED_VGA }, 206 { PCI_CHIP_SIS660, PCI_CHIP_SIS660, RES_SHARED_VGA }, 207 { PCI_CHIP_SIS340, PCI_CHIP_SIS340, RES_SHARED_VGA }, 208 { -1, -1, RES_UNDEFINED } 209}; 210 211static SymTabRec XGIChipsets[] = { 212 { PCI_CHIP_XGIXG20, "Volari Z7 (XG20)" }, 213 { PCI_CHIP_XGIXG40, "Volari V3XT/V5/V8/Duo (XG40)" }, 214 { -1, NULL } 215}; 216 217static PciChipsets XGIPciChipsets[] = { 218 { PCI_CHIP_XGIXG20, PCI_CHIP_XGIXG20, RES_SHARED_VGA }, 219 { PCI_CHIP_XGIXG40, PCI_CHIP_XGIXG40, RES_SHARED_VGA }, 220 { -1, -1, RES_UNDEFINED } 221}; 222 223#ifdef XFree86LOADER 224 225static MODULESETUPPROTO(sisSetup); 226 227static XF86ModuleVersionInfo sisVersRec = 228{ 229 SIS_DRIVER_NAME, 230 MODULEVENDORSTRING, 231 MODINFOSTRING1, 232 MODINFOSTRING2, 233#ifdef XORG_VERSION_CURRENT 234 XORG_VERSION_CURRENT, 235#else 236 XF86_VERSION_CURRENT, 237#endif 238 SIS_MAJOR_VERSION, SIS_MINOR_VERSION, SIS_PATCHLEVEL, 239 ABI_CLASS_VIDEODRV, /* This is a video driver */ 240 ABI_VIDEODRV_VERSION, 241 MOD_CLASS_VIDEODRV, 242 {0,0,0,0} 243}; 244 245#ifdef _X_EXPORT 246_X_EXPORT 247#endif 248XF86ModuleData sisModuleData = { &sisVersRec, sisSetup, NULL }; 249 250pointer 251sisSetup(pointer module, pointer opts, int *errmaj, int *errmin) 252{ 253 static Bool setupDone = FALSE; 254 255 if(!setupDone) { 256 setupDone = TRUE; 257 xf86AddDriver(&SIS, module, SIS_HaveDriverFuncs); 258 return (pointer)TRUE; 259 } 260 261 if(errmaj) *errmaj = LDR_ONCEONLY; 262 return NULL; 263} 264 265#endif /* XFree86LOADER */ 266 267/* Mandatory */ 268static void 269SISIdentify(int flags) 270{ 271 xf86PrintChipsets(SIS_NAME, "driver for SiS chipsets", SISChipsets); 272 xf86PrintChipsets(SIS_NAME, "driver for XGI chipsets", XGIChipsets); 273} 274 275#ifdef SIS_HAVE_DRIVER_FUNC 276static Bool 277SISDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op, pointer ptr) 278{ 279 CARD32 *flag; 280 281 switch(op) { 282 case RR_GET_INFO: 283 break; 284 case RR_SET_CONFIG: 285 break; 286 case GET_REQUIRED_HW_INTERFACES: 287 break; 288 } 289 return TRUE; 290} 291#endif 292 293static Bool 294SISGetRec(ScrnInfoPtr pScrn) 295{ 296 /* Allocate an SISRec, and hook it into pScrn->driverPrivate. 297 * pScrn->driverPrivate is initialised to NULL, so we can check if 298 * the allocation has already been done. 299 */ 300 if(pScrn->driverPrivate != NULL) return TRUE; 301 302 pScrn->driverPrivate = xnfcalloc(sizeof(SISRec), 1); 303 304 /* Initialise it to 0 */ 305 memset(pScrn->driverPrivate, 0, sizeof(SISRec)); 306 307 return TRUE; 308} 309 310static void 311SISFreeRec(ScrnInfoPtr pScrn) 312{ 313 SISPtr pSiS = SISPTR(pScrn); 314#ifdef SISDUALHEAD 315 SISEntPtr pSiSEnt = NULL; 316#endif 317 318 /* Just to make sure... */ 319 if(!pSiS) return; 320 321#ifdef SISDUALHEAD 322 pSiSEnt = pSiS->entityPrivate; 323#endif 324 325 if(pSiS->pstate) free(pSiS->pstate); 326 pSiS->pstate = NULL; 327 if(pSiS->fonts) free(pSiS->fonts); 328 pSiS->fonts = NULL; 329 330#ifdef SISDUALHEAD 331 if(pSiSEnt) { 332 if(!pSiS->SecondHead) { 333 /* Free memory only if we are first head; in case of an error 334 * during init of the second head, the server will continue - 335 * and we need the BIOS image and SiS_Private for the first 336 * head. 337 */ 338 if(pSiSEnt->BIOS) free(pSiSEnt->BIOS); 339 pSiSEnt->BIOS = pSiS->BIOS = NULL; 340 if(pSiSEnt->SiS_Pr) free(pSiSEnt->SiS_Pr); 341 pSiSEnt->SiS_Pr = pSiS->SiS_Pr = NULL; 342 if(pSiSEnt->RenderAccelArray) free(pSiSEnt->RenderAccelArray); 343 pSiSEnt->RenderAccelArray = pSiS->RenderAccelArray = NULL; 344 pSiSEnt->pScrn_1 = NULL; 345 } else { 346 pSiS->BIOS = NULL; 347 pSiS->SiS_Pr = NULL; 348 pSiS->RenderAccelArray = NULL; 349 pSiSEnt->pScrn_2 = NULL; 350 } 351 } else { 352#endif 353 if(pSiS->BIOS) free(pSiS->BIOS); 354 pSiS->BIOS = NULL; 355 if(pSiS->SiS_Pr) free(pSiS->SiS_Pr); 356 pSiS->SiS_Pr = NULL; 357 if(pSiS->RenderAccelArray) free(pSiS->RenderAccelArray); 358 pSiS->RenderAccelArray = NULL; 359#ifdef SISDUALHEAD 360 } 361#endif 362#ifdef SISMERGED 363 if(pSiS->CRT2HSync) free(pSiS->CRT2HSync); 364 pSiS->CRT2HSync = NULL; 365 if(pSiS->CRT2VRefresh) free(pSiS->CRT2VRefresh); 366 pSiS->CRT2VRefresh = NULL; 367 if(pSiS->MetaModes) free(pSiS->MetaModes); 368 pSiS->MetaModes = NULL; 369 if(pSiS->CRT2pScrn) { 370 if(pSiS->CRT2pScrn->modes) { 371 while(pSiS->CRT2pScrn->modes) 372 xf86DeleteMode(&pSiS->CRT2pScrn->modes, pSiS->CRT2pScrn->modes); 373 } 374 if(pSiS->CRT2pScrn->monitor) { 375 if(pSiS->CRT2pScrn->monitor->Modes) { 376 while(pSiS->CRT2pScrn->monitor->Modes) 377 xf86DeleteMode(&pSiS->CRT2pScrn->monitor->Modes, pSiS->CRT2pScrn->monitor->Modes); 378 } 379 if(pSiS->CRT2pScrn->monitor->DDC) free(pSiS->CRT2pScrn->monitor->DDC); 380 free(pSiS->CRT2pScrn->monitor); 381 } 382 free(pSiS->CRT2pScrn); 383 pSiS->CRT2pScrn = NULL; 384 } 385 if(pSiS->CRT1Modes) { 386 if(pSiS->CRT1Modes != pScrn->modes) { 387 if(pScrn->modes) { 388 pScrn->currentMode = pScrn->modes; 389 do { 390 DisplayModePtr p = pScrn->currentMode->next; 391 if(pScrn->currentMode->Private) 392 free(pScrn->currentMode->Private); 393 free(pScrn->currentMode); 394 pScrn->currentMode = p; 395 } while(pScrn->currentMode != pScrn->modes); 396 } 397 pScrn->currentMode = pSiS->CRT1CurrentMode; 398 pScrn->modes = pSiS->CRT1Modes; 399 pSiS->CRT1CurrentMode = NULL; 400 pSiS->CRT1Modes = NULL; 401 } 402 } 403#endif 404 while(pSiS->SISVESAModeList) { 405 sisModeInfoPtr mp = pSiS->SISVESAModeList->next; 406 free(pSiS->SISVESAModeList); 407 pSiS->SISVESAModeList = mp; 408 } 409 if(pSiS->pVbe) vbeFree(pSiS->pVbe); 410 pSiS->pVbe = NULL; 411 412#ifdef SISUSEDEVPORT 413 if(pSiS->sisdevportopen) close(sisdevport); 414#endif 415 416 if(pScrn->driverPrivate == NULL) 417 return; 418 free(pScrn->driverPrivate); 419 pScrn->driverPrivate = NULL; 420} 421 422static void 423SISErrorLog(ScrnInfoPtr pScrn, const char *format, ...) 424{ 425 va_list ap; 426 static const char *str = "**************************************************\n"; 427 428 va_start(ap, format); 429 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, str); 430 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 431 " ERROR:\n"); 432 xf86VDrvMsgVerb(pScrn->scrnIndex, X_ERROR, 1, format, ap); 433 va_end(ap); 434 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 435 " END OF MESSAGE\n"); 436 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, str); 437} 438 439static void 440SiS_SiSFB_Lock(ScrnInfoPtr pScrn, Bool lock) 441{ 442 SISPtr pSiS = SISPTR(pScrn); 443 int fd; 444 CARD32 parm; 445 446 if(!pSiS->sisfbfound) return; 447 if(!pSiS->sisfb_havelock) return; 448 449 if((fd = open(pSiS->sisfbdevname, O_RDONLY)) != -1) { 450 parm = lock ? 1 : 0; 451 ioctl(fd, SISFB_SET_LOCK, &parm); 452 close(fd); 453 } 454} 455 456/* Probe() 457 * 458 * Mandatory 459 */ 460static Bool 461SISProbe(DriverPtr drv, int flags) 462{ 463 int i; 464 GDevPtr *devSections; 465 int *usedChipsSiS, *usedChipsXGI; 466 int numDevSections; 467 int numUsed, numUsedSiS, numUsedXGI; 468 Bool foundScreen = FALSE; 469 470 /* 471 * The aim here is to find all cards that this driver can handle, 472 * and for the ones not already claimed by another driver, claim the 473 * slot, and allocate a ScrnInfoRec. 474 * 475 * This should be a minimal probe, and it should under no circumstances 476 * change the state of the hardware. Because a device is found, don't 477 * assume that it will be used. Don't do any initialisations other than 478 * the required ScrnInfoRec initialisations. Don't allocate any new 479 * data structures. 480 * 481 */ 482 483 /* 484 * Next we check, if there has been a chipset override in the config file. 485 * For this we must find out if there is an active device section which 486 * is relevant, i.e., which has no driver specified or has THIS driver 487 * specified. 488 */ 489 490 if((numDevSections = xf86MatchDevice(SIS_DRIVER_NAME, &devSections)) <= 0) { 491 /* 492 * There's no matching device section in the config file, so quit 493 * now. 494 */ 495 return FALSE; 496 } 497 498 /* 499 * We need to probe the hardware first. We then need to see how this 500 * fits in with what is given in the config file, and allow the config 501 * file info to override any contradictions. 502 */ 503 504 /* 505 * All of the cards this driver supports are PCI, so the "probing" just 506 * amounts to checking the PCI data that the server has already collected. 507 */ 508#ifndef XSERVER_LIBPCIACCESS 509 if(xf86GetPciVideoInfo() == NULL) { 510 /* 511 * We won't let anything in the config file override finding no 512 * PCI video cards at all. 513 */ 514 return FALSE; 515 } 516#endif 517 518 numUsedSiS = xf86MatchPciInstances(SIS_NAME, PCI_VENDOR_SIS, 519 SISChipsets, SISPciChipsets, devSections, 520 numDevSections, drv, &usedChipsSiS); 521 522 numUsedXGI = xf86MatchPciInstances(SIS_NAME, PCI_VENDOR_XGI, 523 XGIChipsets, XGIPciChipsets, devSections, 524 numDevSections, drv, &usedChipsXGI); 525 526 /* Free it since we don't need that list after this */ 527 free(devSections); 528 529 numUsed = numUsedSiS + numUsedXGI; 530 531 if(numUsed <= 0) 532 return FALSE; 533 534 if(flags & PROBE_DETECT) { 535 536 foundScreen = TRUE; 537 538 } else for(i = 0; i < numUsed; i++) { 539 540 ScrnInfoPtr pScrn; 541#ifdef SISDUALHEAD 542 EntityInfoPtr pEnt; 543#endif 544 545 /* Allocate a ScrnInfoRec and claim the slot */ 546 pScrn = NULL; 547 548 if((pScrn = xf86ConfigPciEntity(pScrn, 0, 549 (i < numUsedSiS) ? usedChipsSiS[i] : usedChipsXGI[i-numUsedSiS], 550 (i < numUsedSiS) ? SISPciChipsets : XGIPciChipsets, 551 NULL, NULL, NULL, NULL, NULL))) { 552 /* Fill in what we can of the ScrnInfoRec */ 553 pScrn->driverVersion = SIS_CURRENT_VERSION; 554 pScrn->driverName = SIS_DRIVER_NAME; 555 pScrn->name = SIS_NAME; 556 pScrn->Probe = SISProbe; 557 pScrn->PreInit = SISPreInit; 558 pScrn->ScreenInit = SISScreenInit; 559 pScrn->SwitchMode = SISSwitchMode; 560 pScrn->AdjustFrame = SISAdjustFrame; 561 pScrn->EnterVT = SISEnterVT; 562 pScrn->LeaveVT = SISLeaveVT; 563 pScrn->FreeScreen = SISFreeScreen; 564 pScrn->ValidMode = SISValidMode; 565 566 foundScreen = TRUE; 567 } 568 569#ifdef SISDUALHEAD 570 pEnt = xf86GetEntityInfo((i < numUsedSiS) ? usedChipsSiS[i] : usedChipsXGI[i-numUsedSiS]); 571 572 if(pEnt->chipset == PCI_CHIP_SIS630 || pEnt->chipset == PCI_CHIP_SIS540 || 573 pEnt->chipset == PCI_CHIP_SIS650 || pEnt->chipset == PCI_CHIP_SIS550 || 574 pEnt->chipset == PCI_CHIP_SIS315 || pEnt->chipset == PCI_CHIP_SIS315H || 575 pEnt->chipset == PCI_CHIP_SIS315PRO || pEnt->chipset == PCI_CHIP_SIS330 || 576 pEnt->chipset == PCI_CHIP_SIS300 || pEnt->chipset == PCI_CHIP_SIS660 || 577 pEnt->chipset == PCI_CHIP_SIS340 || pEnt->chipset == PCI_CHIP_XGIXG40) { 578 579 SISEntPtr pSiSEnt = NULL; 580 DevUnion *pPriv; 581 582 xf86SetEntitySharable((i < numUsedSiS) ? usedChipsSiS[i] : usedChipsXGI[i-numUsedSiS]); 583 if(SISEntityIndex < 0) { 584 SISEntityIndex = xf86AllocateEntityPrivateIndex(); 585 } 586 pPriv = xf86GetEntityPrivate(pScrn->entityList[0], SISEntityIndex); 587 if(!pPriv->ptr) { 588 pPriv->ptr = xnfcalloc(sizeof(SISEntRec), 1); 589 pSiSEnt = pPriv->ptr; 590 memset(pSiSEnt, 0, sizeof(SISEntRec)); 591 pSiSEnt->lastInstance = -1; 592 } else { 593 pSiSEnt = pPriv->ptr; 594 } 595 pSiSEnt->lastInstance++; 596 xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0], 597 pSiSEnt->lastInstance); 598 } 599#endif /* DUALHEAD */ 600 601 } 602 603 if(usedChipsSiS) free(usedChipsSiS); 604 if(usedChipsXGI) free(usedChipsXGI); 605 606 return foundScreen; 607} 608 609/* Various helpers */ 610 611static unsigned short 612calcgammaval(int j, int nramp, float invgamma, float bri, float c) 613{ 614 float k = (float)j; 615 float nrm1 = (float)(nramp - 1); 616 float con = c * nrm1 / 3.0; 617 float l, v; 618 619 if(con != 0.0) { 620 l = nrm1 / 2.0; 621 if(con <= 0.0) { 622 k -= l; 623 k *= (l + con) / l; 624 } else { 625 l -= 1.0; 626 k -= l; 627 k *= l / (l - con); 628 } 629 k += l; 630 if(k < 0.0) k = 0.0; 631 } 632 633 if(invgamma == 1.0) { 634 v = k / nrm1 * 65535.0; 635 } else { 636 v = pow(k / nrm1, invgamma) * 65535.0 + 0.5; 637 } 638 639 v += (bri * (65535.0 / 3.0)) ; 640 641 if(v < 0.0) v = 0.0; 642 else if(v > 65535.0) v = 65535.0; 643 644 return (unsigned short)v; 645} 646 647#ifdef SISGAMMARAMP 648void 649SISCalculateGammaRamp(ScreenPtr pScreen, ScrnInfoPtr pScrn) 650{ 651 SISPtr pSiS = SISPTR(pScrn); 652 int i, j, nramp; 653 UShort *ramp[3]; 654 float gamma_max[3], framp; 655 Bool newmethod = FALSE; 656 657 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_OLDGAMMAINUSE)) { 658 newmethod = TRUE; 659 } else { 660 gamma_max[0] = (float)pSiS->GammaBriR / 1000; 661 gamma_max[1] = (float)pSiS->GammaBriG / 1000; 662 gamma_max[2] = (float)pSiS->GammaBriB / 1000; 663 } 664 665 if(!(nramp = xf86GetGammaRampSize(pScreen))) return; 666 667 for(i=0; i<3; i++) { 668 ramp[i] = (UShort *)malloc(nramp * sizeof(UShort)); 669 if(!ramp[i]) { 670 if(ramp[0]) { free(ramp[0]); ramp[0] = NULL; } 671 if(ramp[1]) { free(ramp[1]); ramp[1] = NULL; } 672 return; 673 } 674 } 675 676 if(newmethod) { 677 678 for(i = 0; i < 3; i++) { 679 680 float invgamma = 0.0, bri = 0.0, con = 0.0; 681 682 switch(i) { 683 case 0: invgamma = 1. / pScrn->gamma.red; 684 bri = pSiS->NewGammaBriR; 685 con = pSiS->NewGammaConR; 686 break; 687 case 1: invgamma = 1. / pScrn->gamma.green; 688 bri = pSiS->NewGammaBriG; 689 con = pSiS->NewGammaConG; 690 break; 691 case 2: invgamma = 1. / pScrn->gamma.blue; 692 bri = pSiS->NewGammaBriB; 693 con = pSiS->NewGammaConB; 694 break; 695 } 696 697 for(j = 0; j < nramp; j++) { 698 ramp[i][j] = calcgammaval(j, nramp, invgamma, bri, con); 699 } 700 701 } 702 703 } else { 704 705 for(i = 0; i < 3; i++) { 706 int fullscale = 65535 * gamma_max[i]; 707 float dramp = 1. / (nramp - 1); 708 float invgamma = 0.0, v; 709 710 switch(i) { 711 case 0: invgamma = 1. / pScrn->gamma.red; break; 712 case 1: invgamma = 1. / pScrn->gamma.green; break; 713 case 2: invgamma = 1. / pScrn->gamma.blue; break; 714 } 715 716 for(j = 0; j < nramp; j++) { 717 framp = pow(j * dramp, invgamma); 718 719 v = (fullscale < 0) ? (65535 + fullscale * framp) : 720 fullscale * framp; 721 if(v < 0) v = 0; 722 else if(v > 65535) v = 65535; 723 ramp[i][j] = (UShort)v; 724 } 725 } 726 727 } 728 729 xf86ChangeGammaRamp(pScreen, nramp, ramp[0], ramp[1], ramp[2]); 730 731 free(ramp[0]); 732 free(ramp[1]); 733 free(ramp[2]); 734 ramp[0] = ramp[1] = ramp[2] = NULL; 735} 736#endif 737 738void 739SISCalculateGammaRampCRT2(ScrnInfoPtr pScrn) 740{ 741 SISPtr pSiS = SISPTR(pScrn); 742 int i; 743 int myshift = 16 - pScrn->rgbBits; 744 int maxvalue = (1 << pScrn->rgbBits) - 1; 745 int reds = pScrn->mask.red >> pScrn->offset.red; 746 int greens = pScrn->mask.green >> pScrn->offset.green; 747 int blues = pScrn->mask.blue >> pScrn->offset.blue; 748 float framp, invgamma1, invgamma2, invgamma3, v; 749 750 invgamma1 = 1. / pSiS->GammaR2; 751 invgamma2 = 1. / pSiS->GammaG2; 752 invgamma3 = 1. / pSiS->GammaB2; 753 754 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_OLDGAMMAINUSE)) { 755 756 for(i = 0; i < pSiS->CRT2ColNum; i++) { 757 pSiS->crt2gcolortable[i].red = calcgammaval(i, pSiS->CRT2ColNum, invgamma1, 758 pSiS->NewGammaBriR2, pSiS->NewGammaConR2) >> myshift; 759 pSiS->crt2gcolortable[i].green = calcgammaval(i, pSiS->CRT2ColNum, invgamma2, 760 pSiS->NewGammaBriG2, pSiS->NewGammaConG2) >> myshift; 761 pSiS->crt2gcolortable[i].blue = calcgammaval(i, pSiS->CRT2ColNum, invgamma3, 762 pSiS->NewGammaBriB2, pSiS->NewGammaConB2) >> myshift; 763 } 764 765 } else { 766 767 int fullscale1 = 65536 * (float)pSiS->GammaBriR2 / 1000; 768 int fullscale2 = 65536 * (float)pSiS->GammaBriG2 / 1000; 769 int fullscale3 = 65536 * (float)pSiS->GammaBriB2 / 1000; 770 771 float dramp = 1. / (pSiS->CRT2ColNum - 1); 772 773 for(i = 0; i < pSiS->CRT2ColNum; i++) { 774 framp = pow(i * dramp, invgamma1); 775 v = (fullscale1 < 0) ? (65535 + fullscale1 * framp) : fullscale1 * framp; 776 if(v < 0) v = 0; 777 else if(v > 65535) v = 65535; 778 pSiS->crt2gcolortable[i].red = ((UShort)v) >> myshift; 779 framp = pow(i * dramp, invgamma2); 780 v = (fullscale2 < 0) ? (65535 + fullscale2 * framp) : fullscale2 * framp; 781 if(v < 0) v = 0; 782 else if(v > 65535) v = 65535; 783 pSiS->crt2gcolortable[i].green = ((UShort)v) >> myshift; 784 framp = pow(i * dramp, invgamma3); 785 v = (fullscale3 < 0) ? (65535 + fullscale3 * framp) : fullscale3 * framp; 786 if(v < 0) v = 0; 787 else if(v > 65535) v = 65535; 788 pSiS->crt2gcolortable[i].blue = ((UShort)v) >> myshift; 789 } 790 791 } 792 793 for(i = 0; i < pSiS->CRT2ColNum; i++) { 794 pSiS->crt2colors[i].red = 795 pSiS->crt2gcolortable[i * maxvalue / reds].red; 796 pSiS->crt2colors[i].green = 797 pSiS->crt2gcolortable[i * maxvalue / greens].green; 798 pSiS->crt2colors[i].blue = 799 pSiS->crt2gcolortable[i * maxvalue / blues].blue; 800 } 801} 802 803/* If monitor section has no HSync/VRefresh data, 804 * derive it from DDC data. 805 */ 806static void 807SiSSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) 808{ 809 MonPtr mon = pScrn->monitor; 810 xf86MonPtr ddc = mon->DDC; 811 float myhhigh = 0.0, myhlow = 0.0, htest; 812 int myvhigh = 0, myvlow = 0, vtest, i; 813 UChar temp; 814 const myhddctiming myhtiming[12] = { 815 { 1, 0x20, 31.6 }, /* rounded up by .1 */ 816 { 1, 0x80, 31.6 }, 817 { 1, 0x02, 35.3 }, 818 { 1, 0x04, 37.6 }, 819 { 1, 0x08, 38.0 }, 820 { 1, 0x01, 38.0 }, 821 { 2, 0x40, 47.0 }, 822 { 2, 0x80, 48.2 }, 823 { 2, 0x08, 48.5 }, 824 { 2, 0x04, 56.6 }, 825 { 2, 0x02, 60.1 }, 826 { 2, 0x01, 80.1 } 827 }; 828 const myvddctiming myvtiming[11] = { 829 { 1, 0x02, 56 }, 830 { 1, 0x01, 60 }, 831 { 2, 0x08, 60 }, 832 { 2, 0x04, 70 }, 833 { 1, 0x80, 71 }, 834 { 1, 0x08, 72 }, 835 { 2, 0x80, 72 }, 836 { 1, 0x04, 75 }, 837 { 2, 0x40, 75 }, 838 { 2, 0x02, 75 }, 839 { 2, 0x01, 75 } 840 }; 841 842 if(flag) { /* HSync */ 843 844 for(i = 0; i < 4; i++) { 845 if(ddc->det_mon[i].type == DS_RANGES) { 846 mon->nHsync = 1; 847 mon->hsync[0].lo = ddc->det_mon[i].section.ranges.min_h; 848 mon->hsync[0].hi = ddc->det_mon[i].section.ranges.max_h; 849 if(mon->hsync[0].lo > 32.0 || mon->hsync[0].hi < 31.0) { 850 if(ddc->timings1.t1 & 0x80) { 851 mon->nHsync++; 852 mon->hsync[1].lo = 31.0; 853 mon->hsync[1].hi = 32.0; 854 } 855 } 856 return; 857 } 858 } 859 860 /* If no sync ranges detected in detailed timing table, we 861 * derive them from supported VESA modes. 862 */ 863 864 for(i = 0; i < 12; i++) { 865 if(myhtiming[i].whichone == 1) temp = ddc->timings1.t1; 866 else temp = ddc->timings1.t2; 867 if(temp & myhtiming[i].mask) { 868 if((i == 0) || (myhlow > myhtiming[i].rate)) 869 myhlow = myhtiming[i].rate; 870 } 871 if(myhtiming[11-i].whichone == 1) temp = ddc->timings1.t1; 872 else temp = ddc->timings1.t2; 873 if(temp & myhtiming[11-i].mask) { 874 if((i == 0) || (myhhigh < myhtiming[11-i].rate)) 875 myhhigh = myhtiming[11-i].rate; 876 } 877 } 878 879 for(i = 0; i < STD_TIMINGS; i++) { 880 if(ddc->timings2[i].hsize > 256) { 881 htest = ddc->timings2[i].refresh * 1.05 * ddc->timings2[i].vsize / 1000.0; 882 if(htest < myhlow) myhlow = htest; 883 if(htest > myhhigh) myhhigh = htest; 884 } 885 } 886 887 if((myhhigh > 0.0) && (myhlow > 0.0)) { 888 mon->nHsync = 1; 889 mon->hsync[0].lo = myhlow - 0.1; 890 mon->hsync[0].hi = myhhigh; 891 } 892 893 894 } else { /* Vrefresh */ 895 896 for(i = 0; i < 4; i++) { 897 if(ddc->det_mon[i].type == DS_RANGES) { 898 mon->nVrefresh = 1; 899 mon->vrefresh[0].lo = ddc->det_mon[i].section.ranges.min_v; 900 mon->vrefresh[0].hi = ddc->det_mon[i].section.ranges.max_v; 901 if(mon->vrefresh[0].lo > 72 || mon->vrefresh[0].hi < 70) { 902 if(ddc->timings1.t1 & 0x80) { 903 mon->nVrefresh++; 904 mon->vrefresh[1].lo = 71; 905 mon->vrefresh[1].hi = 71; 906 } 907 } 908 return; 909 } 910 } 911 912 for(i = 0; i < 11; i++) { 913 if(myvtiming[i].whichone == 1) temp = ddc->timings1.t1; 914 else temp = ddc->timings1.t2; 915 if(temp & myvtiming[i].mask) { 916 if((i == 0) || (myvlow > myvtiming[i].rate)) 917 myvlow = myvtiming[i].rate; 918 } 919 if(myvtiming[10-i].whichone == 1) temp = ddc->timings1.t1; 920 else temp = ddc->timings1.t2; 921 if(temp & myvtiming[10-i].mask) { 922 if((i == 0) || (myvhigh < myvtiming[10-i].rate)) 923 myvhigh = myvtiming[10-i].rate; 924 } 925 } 926 927 for(i = 0; i < STD_TIMINGS; i++) { 928 if(ddc->timings2[i].hsize > 256) { 929 vtest = ddc->timings2[i].refresh; 930 if(vtest < myvlow) myvlow = vtest; 931 if(vtest > myvhigh) myvhigh = vtest; 932 } 933 } 934 935 if((myvhigh > 0) && (myvlow > 0)) { 936 mon->nVrefresh = 1; 937 mon->vrefresh[0].lo = myvlow; 938 mon->vrefresh[0].hi = myvhigh; 939 } 940 941 } 942} 943 944static Bool 945SiSAllowSyncOverride(SISPtr pSiS, Bool fromDDC) 946{ 947 if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return FALSE; 948 949#ifdef SISDUALHEAD 950 if(pSiS->DualHeadMode) { 951 if(pSiS->SecondHead) { 952 if((pSiS->VBFlags & CRT1_LCDA) && (!fromDDC)) return TRUE; 953 } else { 954 if((pSiS->VBFlags & CRT2_TV) || 955 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC))) return TRUE; 956 } 957 return FALSE; 958 } 959#endif 960 961#ifdef SISMERGED 962 if(pSiS->MergedFB) { 963 if((pSiS->VBFlags & CRT1_LCDA) && (!fromDDC)) return TRUE; 964 return FALSE; 965 } 966#endif 967 968 if(!(pSiS->VBFlags & DISPTYPE_CRT1)) { 969 if( (pSiS->VBFlags & CRT2_TV) || 970 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC)) ) return TRUE; 971 } else if((pSiS->VBFlags & CRT1_LCDA) && (!fromDDC)) return TRUE; 972 973 return FALSE; 974} 975 976static Bool 977SiSCheckForH(float hsync, MonPtr monitor) 978{ 979 int i; 980 for(i = 0; i < monitor->nHsync; i++) { 981 if((hsync > monitor->hsync[i].lo * (1.0 - SYNC_TOLERANCE)) && 982 (hsync < monitor->hsync[i].hi * (1.0 + SYNC_TOLERANCE))) 983 break; 984 } 985 if(i == monitor->nHsync) return FALSE; 986 return TRUE; 987} 988 989static Bool 990SiSCheckForV(float vrefresh, MonPtr monitor) 991{ 992 int i; 993 for(i = 0; i < monitor->nVrefresh; i++) { 994 if((vrefresh > monitor->vrefresh[i].lo * (1.0 - SYNC_TOLERANCE)) && 995 (vrefresh < monitor->vrefresh[i].hi * (1.0 + SYNC_TOLERANCE))) 996 break; 997 } 998 if(i == monitor->nVrefresh) return FALSE; 999 return TRUE; 1000} 1001 1002static Bool 1003CheckAndOverruleH(ScrnInfoPtr pScrn, MonPtr monitor) 1004{ 1005 DisplayModePtr mode = monitor->Modes; 1006 float mymin = 30.0, mymax = 80.0, hsync; 1007 Bool doit = FALSE; 1008 1009 for(hsync = mymin; hsync <= mymax; hsync += .5) { 1010 if(!SiSCheckForH(hsync, monitor)) doit = TRUE; 1011 } 1012 1013 if(mode) { 1014 do { 1015 if(mode->type & M_T_BUILTIN) { 1016 hsync = (float)mode->Clock / (float)mode->HTotal; 1017 if(!SiSCheckForH(hsync, monitor)) { 1018 doit = TRUE; 1019 if(hsync < mymin) mymin = hsync; 1020 if(hsync > mymax) mymax = hsync; 1021 } 1022 } 1023 } while((mode = mode->next)); 1024 } 1025 1026 if(doit) { 1027 monitor->nHsync = 1; 1028 monitor->hsync[0].lo = mymin; 1029 monitor->hsync[0].hi = mymax; 1030 return TRUE; 1031 } 1032 1033 return FALSE; 1034} 1035 1036static Bool 1037CheckAndOverruleV(ScrnInfoPtr pScrn, MonPtr monitor) 1038{ 1039 DisplayModePtr mode = monitor->Modes; 1040 float mymin = 59.0, mymax = 61.0, vrefresh; 1041 Bool doit = FALSE, ret = FALSE; 1042 1043 for(vrefresh = mymin; vrefresh <= mymax; vrefresh += 1.0) { 1044 if(!SiSCheckForV(vrefresh, monitor)) doit = TRUE; 1045 } 1046 1047 if(mode) { 1048 do { 1049 if(mode->type & M_T_BUILTIN) { 1050 vrefresh = mode->Clock * 1000.0 / (mode->HTotal * mode->VTotal); 1051 if(mode->Flags & V_INTERLACE) vrefresh *= 2.0; 1052 if(mode->Flags & V_DBLSCAN) vrefresh /= 2.0; 1053 if(!SiSCheckForH(vrefresh, monitor)) { 1054 doit = TRUE; 1055 if(vrefresh < mymin) mymin = vrefresh; 1056 if(vrefresh > mymax) mymax = vrefresh; 1057 } 1058 } 1059 } while((mode = mode->next)); 1060 } 1061 1062 if(doit) { 1063 monitor->nVrefresh = 1; 1064 monitor->vrefresh[0].lo = mymin; 1065 monitor->vrefresh[0].hi = mymax; 1066 ret = TRUE; 1067 } 1068 1069 /* special for 640x400/320x200/@70Hz (VGA/IBM 720x480) */ 1070 if( (!SiSCheckForV(71, monitor)) && 1071 (monitor->nVrefresh < MAX_VREFRESH) ) { 1072 monitor->vrefresh[monitor->nVrefresh].lo = 71; 1073 monitor->vrefresh[monitor->nVrefresh].hi = 71; 1074 monitor->nVrefresh++; 1075 ret = TRUE; 1076 } 1077 return ret; 1078} 1079 1080/* Some helper functions for MergedFB mode */ 1081 1082#ifdef SISMERGED 1083 1084/* Helper function for CRT2 monitor vrefresh/hsync options 1085 * (Code base from mga driver) 1086 */ 1087static int 1088SiSStrToRanges(range *r, char *s, int max) 1089{ 1090 float num = 0.0; 1091 int rangenum = 0; 1092 Bool gotdash = FALSE; 1093 Bool nextdash = FALSE; 1094 char *strnum = NULL; 1095 do { 1096 switch(*s) { 1097 case '0': 1098 case '1': 1099 case '2': 1100 case '3': 1101 case '4': 1102 case '5': 1103 case '6': 1104 case '7': 1105 case '8': 1106 case '9': 1107 case '.': 1108 if(strnum == NULL) { 1109 strnum = s; 1110 gotdash = nextdash; 1111 nextdash = FALSE; 1112 } 1113 break; 1114 case '-': 1115 case ' ': 1116 case 0: 1117 if(strnum == NULL) break; 1118 sscanf(strnum, "%f", &num); 1119 strnum = NULL; 1120 if(gotdash) { 1121 r[rangenum - 1].hi = num; 1122 } else { 1123 r[rangenum].lo = num; 1124 r[rangenum].hi = num; 1125 rangenum++; 1126 } 1127 if(*s == '-') nextdash = (rangenum != 0); 1128 else if(rangenum >= max) return rangenum; 1129 break; 1130 default: 1131 return 0; 1132 } 1133 1134 } while(*(s++) != 0); 1135 1136 return rangenum; 1137} 1138 1139/* Copy and link two modes (i, j) for mergedfb mode 1140 * (Code base taken from mga driver) 1141 * 1142 * - Copy mode i, merge j to copy of i, link the result to dest 1143 * - Link i and j in private record. 1144 * - If dest is NULL, return value is copy of i linked to itself. 1145 * - For mergedfb auto-config, we only check the dimension 1146 * against virtualX/Y, if they were user-provided. 1147 * - No special treatment required for CRTxxOffs. 1148 * - Provide fake dotclock in order to distinguish between similar 1149 * looking MetaModes (for RandR and VidMode extensions) 1150 * - Set unique VRefresh of dest mode for RandR 1151 */ 1152static DisplayModePtr 1153SiSCopyModeNLink(ScrnInfoPtr pScrn, DisplayModePtr dest, 1154 DisplayModePtr i, DisplayModePtr j, 1155 SiSScrn2Rel srel) 1156{ 1157 SISPtr pSiS = SISPTR(pScrn); 1158 DisplayModePtr mode; 1159 int dx = 0,dy = 0; 1160 1161 if(!((mode = malloc(sizeof(DisplayModeRec))))) return dest; 1162 memcpy(mode, i, sizeof(DisplayModeRec)); 1163 if(!((mode->Private = malloc(sizeof(SiSMergedDisplayModeRec))))) { 1164 free(mode); 1165 return dest; 1166 } 1167 ((SiSMergedDisplayModePtr)mode->Private)->CRT1 = i; 1168 ((SiSMergedDisplayModePtr)mode->Private)->CRT2 = j; 1169 ((SiSMergedDisplayModePtr)mode->Private)->CRT2Position = srel; 1170 mode->PrivSize = 0; 1171 1172 switch(srel) { 1173 case sisLeftOf: 1174 case sisRightOf: 1175 if(!(pScrn->display->virtualX)) { 1176 dx = i->HDisplay + j->HDisplay; 1177 } else { 1178 dx = min(pScrn->virtualX, i->HDisplay + j->HDisplay); 1179 } 1180 dx -= mode->HDisplay; 1181 if(!(pScrn->display->virtualY)) { 1182 dy = max(i->VDisplay, j->VDisplay); 1183 } else { 1184 dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay)); 1185 } 1186 dy -= mode->VDisplay; 1187 break; 1188 case sisAbove: 1189 case sisBelow: 1190 if(!(pScrn->display->virtualY)) { 1191 dy = i->VDisplay + j->VDisplay; 1192 } else { 1193 dy = min(pScrn->virtualY, i->VDisplay + j->VDisplay); 1194 } 1195 dy -= mode->VDisplay; 1196 if(!(pScrn->display->virtualX)) { 1197 dx = max(i->HDisplay, j->HDisplay); 1198 } else { 1199 dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay)); 1200 } 1201 dx -= mode->HDisplay; 1202 break; 1203 case sisClone: 1204 if(!(pScrn->display->virtualX)) { 1205 dx = max(i->HDisplay, j->HDisplay); 1206 } else { 1207 dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay)); 1208 } 1209 dx -= mode->HDisplay; 1210 if(!(pScrn->display->virtualY)) { 1211 dy = max(i->VDisplay, j->VDisplay); 1212 } else { 1213 dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay)); 1214 } 1215 dy -= mode->VDisplay; 1216 break; 1217 } 1218 mode->HDisplay += dx; 1219 mode->HSyncStart += dx; 1220 mode->HSyncEnd += dx; 1221 mode->HTotal += dx; 1222 mode->VDisplay += dy; 1223 mode->VSyncStart += dy; 1224 mode->VSyncEnd += dy; 1225 mode->VTotal += dy; 1226 1227 mode->type = M_T_DEFAULT; 1228#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,2,0) 1229 /* Set up as user defined (ie fake that the mode has been named in the 1230 * Modes-list in the screen section; corrects cycling with CTRL-ALT-[-+] 1231 * when source mode has not been listed there.) 1232 */ 1233 mode->type |= M_T_USERDEF; 1234#endif 1235 1236 /* Set the VRefresh field (in order to make RandR use it for the rates). We 1237 * simply set this to the refresh rate for the CRT1 mode (since CRT2 will 1238 * mostly be LCD or TV anyway). 1239 */ 1240 mode->VRefresh = SiSCalcVRate(i); 1241 1242 if( ((mode->HDisplay * ((pScrn->bitsPerPixel + 7) / 8) * mode->VDisplay) > pSiS->maxxfbmem) || 1243 (mode->HDisplay > 4088) || 1244 (mode->VDisplay > 4096) ) { 1245 1246 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1247 "Skipped \"%s\" (%dx%d), not enough video RAM or beyond hardware specs\n", 1248 mode->name, mode->HDisplay, mode->VDisplay); 1249 free(mode->Private); 1250 free(mode); 1251 1252 return dest; 1253 } 1254 1255#ifdef SISXINERAMA 1256 if(srel != sisClone) { 1257 pSiS->AtLeastOneNonClone = TRUE; 1258 } 1259#endif 1260 1261 /* Now see if the resulting mode would be discarded as a "size" by the 1262 * RandR extension, and increase its clock by 1000 in case it does. 1263 */ 1264 if(dest) { 1265 DisplayModePtr t = dest; 1266 do { 1267 if((t->HDisplay == mode->HDisplay) && 1268 (t->VDisplay == mode->VDisplay) && 1269 ((int)(t->VRefresh + .5) == (int)(mode->VRefresh + .5))) { 1270 mode->VRefresh += 1000.0; 1271 } 1272 t = t->next; 1273 } while((t) && (t != dest)); 1274 } 1275 1276 /* Provide a fake but unique DotClock in order to trick the vidmode 1277 * extension to allow selecting among a number of modes whose merged result 1278 * looks identical but consists of different modes for CRT1 and CRT2 1279 */ 1280 mode->Clock = (int)(mode->VRefresh * 1000.0); 1281 1282 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1283 "Merged \"%s\" (%dx%d) and \"%s\" (%dx%d) to %dx%d (%d)%s\n", 1284 i->name, i->HDisplay, i->VDisplay, j->name, j->HDisplay, j->VDisplay, 1285 mode->HDisplay, mode->VDisplay, (int)mode->VRefresh, 1286 (srel == sisClone) ? " (Clone)" : ""); 1287 1288 mode->next = mode; 1289 mode->prev = mode; 1290 1291 if(dest) { 1292 mode->next = dest->next; /* Insert node after "dest" */ 1293 dest->next->prev = mode; 1294 mode->prev = dest; 1295 dest->next = mode; 1296 } 1297 1298 return mode; 1299} 1300 1301/* Helper function to find a mode from a given name 1302 * (Code base taken from mga driver) 1303 */ 1304static DisplayModePtr 1305SiSGetModeFromName(char* str, DisplayModePtr i) 1306{ 1307 DisplayModePtr c = i; 1308 if(!i) return NULL; 1309 do { 1310 if(strcmp(str, c->name) == 0) return c; 1311 c = c->next; 1312 } while(c != i); 1313 return NULL; 1314} 1315 1316static DisplayModePtr 1317SiSFindWidestTallestMode(DisplayModePtr i, Bool tallest) 1318{ 1319 DisplayModePtr c = i, d = NULL; 1320 int max = 0; 1321 if(!i) return NULL; 1322 do { 1323 if(tallest) { 1324 if(c->VDisplay > max) { 1325 max = c->VDisplay; 1326 d = c; 1327 } 1328 } else { 1329 if(c->HDisplay > max) { 1330 max = c->HDisplay; 1331 d = c; 1332 } 1333 } 1334 c = c->next; 1335 } while(c != i); 1336 return d; 1337} 1338 1339static void 1340SiSFindWidestTallestCommonMode(DisplayModePtr i, DisplayModePtr j, Bool tallest, 1341 DisplayModePtr *a, DisplayModePtr *b) 1342{ 1343 DisplayModePtr c = i, d; 1344 int max = 0; 1345 Bool foundone; 1346 1347 (*a) = (*b) = NULL; 1348 1349 if(!i || !j) return; 1350 1351 do { 1352 d = j; 1353 foundone = FALSE; 1354 do { 1355 if( (c->HDisplay == d->HDisplay) && 1356 (c->VDisplay == d->VDisplay) ) { 1357 foundone = TRUE; 1358 break; 1359 } 1360 d = d->next; 1361 } while(d != j); 1362 if(foundone) { 1363 if(tallest) { 1364 if(c->VDisplay > max) { 1365 max = c->VDisplay; 1366 (*a) = c; 1367 (*b) = d; 1368 } 1369 } else { 1370 if(c->HDisplay > max) { 1371 max = c->HDisplay; 1372 (*a) = c; 1373 (*b) = d; 1374 } 1375 } 1376 } 1377 c = c->next; 1378 } while(c != i); 1379} 1380 1381static DisplayModePtr 1382SiSGenerateModeListFromLargestModes(ScrnInfoPtr pScrn, 1383 DisplayModePtr i, DisplayModePtr j, 1384 SiSScrn2Rel srel) 1385{ 1386#ifdef SISXINERAMA 1387 SISPtr pSiS = SISPTR(pScrn); 1388#endif 1389 DisplayModePtr mode1 = NULL; 1390 DisplayModePtr mode2 = NULL; 1391 DisplayModePtr mode3 = NULL; 1392 DisplayModePtr mode4 = NULL; 1393 DisplayModePtr result = NULL; 1394 1395#ifdef SISXINERAMA 1396 pSiS->AtLeastOneNonClone = FALSE; 1397#endif 1398 1399 /* Now build a default list of MetaModes. 1400 * - Non-clone: If the user enabled NonRectangular, we use the 1401 * largest mode for each CRT1 and CRT2. If not, we use the largest 1402 * common mode for CRT1 and CRT2 (if available). Additionally, and 1403 * regardless if the above, we produce a clone mode consisting of 1404 * the largest common mode (if available) in order to use DGA. 1405 * - Clone: If the (global) CRT2Position is Clone, we use the 1406 * largest common mode if available, otherwise the first two modes 1407 * in each list. 1408 */ 1409 1410 switch(srel) { 1411 case sisLeftOf: 1412 case sisRightOf: 1413 mode1 = SiSFindWidestTallestMode(i, FALSE); 1414 mode2 = SiSFindWidestTallestMode(j, FALSE); 1415 SiSFindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); 1416 break; 1417 case sisAbove: 1418 case sisBelow: 1419 mode1 = SiSFindWidestTallestMode(i, TRUE); 1420 mode2 = SiSFindWidestTallestMode(j, TRUE); 1421 SiSFindWidestTallestCommonMode(i, j, TRUE, &mode3, &mode4); 1422 break; 1423 case sisClone: 1424 SiSFindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); 1425 if(mode3 && mode4) { 1426 mode1 = mode3; 1427 mode2 = mode4; 1428 } else { 1429 mode1 = i; 1430 mode2 = j; 1431 } 1432 } 1433 1434 if(srel != sisClone) { 1435 if(mode3 && mode4 && !pSiS->NonRect) { 1436 mode1 = mode3; 1437 mode2 = mode2; 1438 } 1439 } 1440 1441 if(mode1 && mode2) { 1442 result = SiSCopyModeNLink(pScrn, result, mode1, mode2, srel); 1443 } 1444 1445 if(srel != sisClone) { 1446 if(mode3 && mode4) { 1447 result = SiSCopyModeNLink(pScrn, result, mode3, mode4, sisClone); 1448 } 1449 } 1450 1451 return result; 1452} 1453 1454/* Generate the merged-fb mode modelist 1455 * (Taken from mga driver) 1456 */ 1457static DisplayModePtr 1458SiSGenerateModeListFromMetaModes(ScrnInfoPtr pScrn, char* str, 1459 DisplayModePtr i, DisplayModePtr j, 1460 SiSScrn2Rel srel) 1461{ 1462#ifdef SISXINERAMA 1463 SISPtr pSiS = SISPTR(pScrn); 1464#endif 1465 char* strmode = str; 1466 char modename[256]; 1467 Bool gotdash = FALSE; 1468 char gotsep = 0; 1469 SiSScrn2Rel sr; 1470 DisplayModePtr mode1 = NULL; 1471 DisplayModePtr mode2 = NULL; 1472 DisplayModePtr result = NULL; 1473 int myslen; 1474 1475#ifdef SISXINERAMA 1476 pSiS->AtLeastOneNonClone = FALSE; 1477#endif 1478 1479 do { 1480 switch(*str) { 1481 case 0: 1482 case '-': 1483 case '+': 1484 case ' ': 1485 case ',': 1486 case ';': 1487 if(strmode != str) { 1488 1489 myslen = str - strmode; 1490 if(myslen > 255) myslen = 255; 1491 strncpy(modename, strmode, myslen); 1492 modename[myslen] = 0; 1493 1494 if(gotdash) { 1495 if(mode1 == NULL) { 1496 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1497 "Error parsing MetaModes parameter\n"); 1498 return NULL; 1499 } 1500 mode2 = SiSGetModeFromName(modename, j); 1501 if(!mode2) { 1502 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1503 "Mode \"%s\" is not a supported mode for CRT2\n", modename); 1504 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1505 "\t(Skipping metamode \"%s%c%s\")\n", mode1->name, gotsep, modename); 1506 mode1 = NULL; 1507 gotsep = 0; 1508 } 1509 } else { 1510 mode1 = SiSGetModeFromName(modename, i); 1511 if(!mode1) { 1512 char* tmps = str; 1513 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1514 "Mode \"%s\" is not a supported mode for CRT1\n", modename); 1515 while(*tmps == ' ' || *tmps == ';') tmps++; 1516 /* skip the next mode */ 1517 if(*tmps == '-' || *tmps == '+' || *tmps == ',') { 1518 tmps++; 1519 /* skip spaces */ 1520 while(*tmps == ' ' || *tmps == ';') tmps++; 1521 /* skip modename */ 1522 while(*tmps && *tmps != ' ' && *tmps != ';' && *tmps != '-' && *tmps != '+' && *tmps != ',') tmps++; 1523 myslen = tmps - strmode; 1524 if(myslen > 255) myslen = 255; 1525 strncpy(modename,strmode,myslen); 1526 modename[myslen] = 0; 1527 str = tmps - 1; 1528 } 1529 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1530 "\t(Skipping metamode \"%s\")\n", modename); 1531 mode1 = NULL; 1532 gotsep = 0; 1533 } 1534 } 1535 gotdash = FALSE; 1536 } 1537 strmode = str + 1; 1538 gotdash |= (*str == '-' || *str == '+' || *str == ','); 1539 if (*str == '-' || *str == '+' || *str == ',') 1540 gotsep = *str; 1541 1542 if(*str != 0) break; 1543 /* Fall through otherwise */ 1544 1545 default: 1546 if(!gotdash && mode1) { 1547 sr = srel; 1548 if(gotsep == '+') sr = sisClone; 1549 if(!mode2) { 1550 mode2 = SiSGetModeFromName(mode1->name, j); 1551 sr = sisClone; 1552 } 1553 if(!mode2) { 1554 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1555 "Mode \"%s\" is not a supported mode for CRT2\n", mode1->name); 1556 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1557 "\t(Skipping metamode \"%s\")\n", modename); 1558 mode1 = NULL; 1559 } else { 1560 result = SiSCopyModeNLink(pScrn, result, mode1, mode2, sr); 1561 mode1 = NULL; 1562 mode2 = NULL; 1563 } 1564 gotsep = 0; 1565 } 1566 break; 1567 1568 } 1569 1570 } while(*(str++) != 0); 1571 1572 return result; 1573} 1574 1575static DisplayModePtr 1576SiSGenerateModeList(ScrnInfoPtr pScrn, char* str, 1577 DisplayModePtr i, DisplayModePtr j, 1578 SiSScrn2Rel srel) 1579{ 1580 SISPtr pSiS = SISPTR(pScrn); 1581 1582 if(str != NULL) { 1583 return(SiSGenerateModeListFromMetaModes(pScrn, str, i, j, srel)); 1584 } else { 1585 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1586 "No MetaModes given, linking %s modes by default\n", 1587 (srel == sisClone) ? "largest common" : 1588 (pSiS->NonRect ? 1589 (((srel == sisLeftOf) || (srel == sisRightOf)) ? "widest" : "tallest") 1590 : 1591 (((srel == sisLeftOf) || (srel == sisRightOf)) ? "widest common" : "tallest common")) ); 1592 return(SiSGenerateModeListFromLargestModes(pScrn, i, j, srel)); 1593 } 1594} 1595 1596static void 1597SiSRecalcDefaultVirtualSize(ScrnInfoPtr pScrn) 1598{ 1599 SISPtr pSiS = SISPTR(pScrn); 1600 DisplayModePtr mode, bmode; 1601 int maxh, maxv; 1602 static const char *str = "MergedFB: Virtual %s %d\n"; 1603 static const char *errstr = "Virtual %s to small for given CRT2Position offset\n"; 1604 1605 mode = bmode = pScrn->modes; 1606 maxh = maxv = 0; 1607 do { 1608 if(mode->HDisplay > maxh) maxh = mode->HDisplay; 1609 if(mode->VDisplay > maxv) maxv = mode->VDisplay; 1610 mode = mode->next; 1611 } while(mode != bmode); 1612 1613 maxh += pSiS->CRT1XOffs + pSiS->CRT2XOffs; 1614 maxv += pSiS->CRT1YOffs + pSiS->CRT2YOffs; 1615 1616 if(!(pScrn->display->virtualX)) { 1617 if(maxh > 4088) { 1618 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1619 "Virtual width with CRT2Position offset beyond hardware specs\n"); 1620 pSiS->CRT1XOffs = pSiS->CRT2XOffs = 0; 1621 maxh -= (pSiS->CRT1XOffs + pSiS->CRT2XOffs); 1622 } 1623 pScrn->virtualX = maxh; 1624 pScrn->displayWidth = maxh; 1625 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "width", maxh); 1626 } else { 1627 if(maxh < pScrn->display->virtualX) { 1628 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "width"); 1629 pSiS->CRT1XOffs = pSiS->CRT2XOffs = 0; 1630 } 1631 } 1632 1633 if(!(pScrn->display->virtualY)) { 1634 pScrn->virtualY = maxv; 1635 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "height", maxv); 1636 } else { 1637 if(maxv < pScrn->display->virtualY) { 1638 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "height"); 1639 pSiS->CRT1YOffs = pSiS->CRT2YOffs = 0; 1640 } 1641 } 1642} 1643 1644static void 1645SiSMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, SiSScrn2Rel srel) 1646{ 1647 SISPtr pSiS = SISPTR(pScrn1); 1648 MessageType from = X_DEFAULT; 1649 xf86MonPtr DDC1 = (xf86MonPtr)(pScrn1->monitor->DDC); 1650 xf86MonPtr DDC2 = (xf86MonPtr)(pScrn2->monitor->DDC); 1651 int ddcWidthmm = 0, ddcHeightmm = 0; 1652 const char *dsstr = "MergedFB: Display dimensions: (%d, %d) mm\n"; 1653 1654 /* This sets the DPI for MergedFB mode. The problem is that 1655 * this can never be exact, because the output devices may 1656 * have different dimensions. This function tries to compromise 1657 * through a few assumptions, and it just calculates an average DPI 1658 * value for both monitors. 1659 */ 1660 1661 /* Given DisplaySize should regard BOTH monitors */ 1662 pScrn1->widthmm = pScrn1->monitor->widthmm; 1663 pScrn1->heightmm = pScrn1->monitor->heightmm; 1664 1665 /* Get DDC display size; if only either CRT1 or CRT2 provided these, 1666 * assume equal dimensions for both, otherwise add dimensions 1667 */ 1668 if( (DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) && 1669 (DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0)) ) { 1670 ddcWidthmm = max(DDC1->features.hsize, DDC2->features.hsize) * 10; 1671 ddcHeightmm = max(DDC1->features.vsize, DDC2->features.vsize) * 10; 1672 switch(srel) { 1673 case sisLeftOf: 1674 case sisRightOf: 1675 ddcWidthmm = (DDC1->features.hsize + DDC2->features.hsize) * 10; 1676 break; 1677 case sisAbove: 1678 case sisBelow: 1679 ddcHeightmm = (DDC1->features.vsize + DDC2->features.vsize) * 10; 1680 default: 1681 break; 1682 } 1683 } else if(DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) { 1684 ddcWidthmm = DDC1->features.hsize * 10; 1685 ddcHeightmm = DDC1->features.vsize * 10; 1686 switch(srel) { 1687 case sisLeftOf: 1688 case sisRightOf: 1689 ddcWidthmm *= 2; 1690 break; 1691 case sisAbove: 1692 case sisBelow: 1693 ddcHeightmm *= 2; 1694 default: 1695 break; 1696 } 1697 } else if(DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0) ) { 1698 ddcWidthmm = DDC2->features.hsize * 10; 1699 ddcHeightmm = DDC2->features.vsize * 10; 1700 switch(srel) { 1701 case sisLeftOf: 1702 case sisRightOf: 1703 ddcWidthmm *= 2; 1704 break; 1705 case sisAbove: 1706 case sisBelow: 1707 ddcHeightmm *= 2; 1708 default: 1709 break; 1710 } 1711 } 1712 1713 if(monitorResolution > 0) { 1714 1715 /* Set command line given values (overrules given options) */ 1716 pScrn1->xDpi = monitorResolution; 1717 pScrn1->yDpi = monitorResolution; 1718 from = X_CMDLINE; 1719 1720 } else if(pSiS->MergedFBXDPI) { 1721 1722 /* Set option-wise given values (overrule DisplaySize) */ 1723 pScrn1->xDpi = pSiS->MergedFBXDPI; 1724 pScrn1->yDpi = pSiS->MergedFBYDPI; 1725 from = X_CONFIG; 1726 1727 } else if(pScrn1->widthmm > 0 || pScrn1->heightmm > 0) { 1728 1729 /* Set values calculated from given DisplaySize */ 1730 from = X_CONFIG; 1731 if(pScrn1->widthmm > 0) { 1732 pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm); 1733 } 1734 if(pScrn1->heightmm > 0) { 1735 pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm); 1736 } 1737 xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, pScrn1->widthmm, pScrn1->heightmm); 1738 1739 } else if(ddcWidthmm && ddcHeightmm) { 1740 1741 /* Set values from DDC-provided display size */ 1742 from = X_PROBED; 1743 xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, ddcWidthmm, ddcHeightmm ); 1744 pScrn1->widthmm = ddcWidthmm; 1745 pScrn1->heightmm = ddcHeightmm; 1746 if(pScrn1->widthmm > 0) { 1747 pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm); 1748 } 1749 if(pScrn1->heightmm > 0) { 1750 pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm); 1751 } 1752 1753 } else { 1754 1755 pScrn1->xDpi = pScrn1->yDpi = DEFAULT_DPI; 1756 1757 } 1758 1759 /* Sanity check */ 1760 if(pScrn1->xDpi > 0 && pScrn1->yDpi <= 0) 1761 pScrn1->yDpi = pScrn1->xDpi; 1762 if(pScrn1->yDpi > 0 && pScrn1->xDpi <= 0) 1763 pScrn1->xDpi = pScrn1->yDpi; 1764 1765 pScrn2->xDpi = pScrn1->xDpi; 1766 pScrn2->yDpi = pScrn1->yDpi; 1767 1768 xf86DrvMsg(pScrn1->scrnIndex, from, "MergedFB: DPI set to (%d, %d)\n", 1769 pScrn1->xDpi, pScrn1->yDpi); 1770} 1771 1772/* Pseudo-Xinerama extension for MergedFB mode */ 1773#ifdef SISXINERAMA 1774 1775static void 1776SiSUpdateXineramaScreenInfo(ScrnInfoPtr pScrn1) 1777{ 1778 SISPtr pSiS = SISPTR(pScrn1); 1779 int crt1scrnnum = 0, crt2scrnnum = 1; 1780 int x1=0, x2=0, y1=0, y2=0, h1=0, h2=0, w1=0, w2=0; 1781 int realvirtX, realvirtY; 1782 DisplayModePtr currentMode, firstMode; 1783 Bool infochanged = FALSE; 1784 Bool usenonrect = pSiS->NonRect; 1785 const char *rectxine = "\t... setting up rectangular Xinerama layout\n"; 1786 1787 pSiS->MBXNR1XMAX = pSiS->MBXNR1YMAX = pSiS->MBXNR2XMAX = pSiS->MBXNR2YMAX = 65536; 1788 pSiS->HaveNonRect = pSiS->HaveOffsRegions = FALSE; 1789 1790 if(!pSiS->MergedFB) return; 1791 1792 if(SiSnoPanoramiXExtension) return; 1793 1794 if(!SiSXineramadataPtr) return; 1795 1796 if(pSiS->CRT2IsScrn0) { 1797 crt1scrnnum = 1; 1798 crt2scrnnum = 0; 1799 } 1800 1801 /* Attention: Usage of RandR may lead to virtual X and Y dimensions 1802 * actually smaller than our MetaModes. To avoid this, we calculate 1803 * the maxCRT fields here (and not somewhere else, like in CopyNLink) 1804 * 1805 * *** Note: RandR is disabled if one of CRTxxOffs is non-zero. 1806 */ 1807 1808 /* "Real" virtual: Virtual without the Offset */ 1809 realvirtX = pScrn1->virtualX - pSiS->CRT1XOffs - pSiS->CRT2XOffs; 1810 realvirtY = pScrn1->virtualY - pSiS->CRT1YOffs - pSiS->CRT2YOffs; 1811 1812 if((pSiS->SiSXineramaVX != pScrn1->virtualX) || (pSiS->SiSXineramaVY != pScrn1->virtualY)) { 1813 1814 if(!(pScrn1->modes)) return; 1815 1816 pSiS->maxCRT1_X1 = pSiS->maxCRT1_X2 = 0; 1817 pSiS->maxCRT1_Y1 = pSiS->maxCRT1_Y2 = 0; 1818 pSiS->maxCRT2_X1 = pSiS->maxCRT2_X2 = 0; 1819 pSiS->maxCRT2_Y1 = pSiS->maxCRT2_Y2 = 0; 1820 pSiS->maxClone_X1 = pSiS->maxClone_X2 = 0; 1821 pSiS->maxClone_Y1 = pSiS->maxClone_Y2 = 0; 1822 1823 currentMode = firstMode = pScrn1->modes; 1824 1825 do { 1826 1827 DisplayModePtr p = currentMode->next; 1828 DisplayModePtr i = ((SiSMergedDisplayModePtr)currentMode->Private)->CRT1; 1829 DisplayModePtr j = ((SiSMergedDisplayModePtr)currentMode->Private)->CRT2; 1830 SiSScrn2Rel srel = ((SiSMergedDisplayModePtr)currentMode->Private)->CRT2Position; 1831 1832 if((currentMode->HDisplay <= realvirtX) && (currentMode->VDisplay <= realvirtY) && 1833 (i->HDisplay <= realvirtX) && (j->HDisplay <= realvirtX) && 1834 (i->VDisplay <= realvirtY) && (j->VDisplay <= realvirtY)) { 1835 1836 if(srel != sisClone) { 1837 if(pSiS->maxCRT1_X1 == i->HDisplay) { 1838 if(pSiS->maxCRT1_X2 < j->HDisplay) { 1839 pSiS->maxCRT1_X2 = j->HDisplay; /* Widest CRT2 mode displayed with widest CRT1 mode */ 1840 } 1841 } else if(pSiS->maxCRT1_X1 < i->HDisplay) { 1842 pSiS->maxCRT1_X1 = i->HDisplay; /* Widest CRT1 mode */ 1843 pSiS->maxCRT1_X2 = j->HDisplay; 1844 } 1845 if(pSiS->maxCRT2_X2 == j->HDisplay) { 1846 if(pSiS->maxCRT2_X1 < i->HDisplay) { 1847 pSiS->maxCRT2_X1 = i->HDisplay; /* Widest CRT1 mode displayed with widest CRT2 mode */ 1848 } 1849 } else if(pSiS->maxCRT2_X2 < j->HDisplay) { 1850 pSiS->maxCRT2_X2 = j->HDisplay; /* Widest CRT2 mode */ 1851 pSiS->maxCRT2_X1 = i->HDisplay; 1852 } 1853 if(pSiS->maxCRT1_Y1 == i->VDisplay) { /* Same as above, but tallest instead of widest */ 1854 if(pSiS->maxCRT1_Y2 < j->VDisplay) { 1855 pSiS->maxCRT1_Y2 = j->VDisplay; 1856 } 1857 } else if(pSiS->maxCRT1_Y1 < i->VDisplay) { 1858 pSiS->maxCRT1_Y1 = i->VDisplay; 1859 pSiS->maxCRT1_Y2 = j->VDisplay; 1860 } 1861 if(pSiS->maxCRT2_Y2 == j->VDisplay) { 1862 if(pSiS->maxCRT2_Y1 < i->VDisplay) { 1863 pSiS->maxCRT2_Y1 = i->VDisplay; 1864 } 1865 } else if(pSiS->maxCRT2_Y2 < j->VDisplay) { 1866 pSiS->maxCRT2_Y2 = j->VDisplay; 1867 pSiS->maxCRT2_Y1 = i->VDisplay; 1868 } 1869 } else { 1870 if(pSiS->maxClone_X1 < i->HDisplay) { 1871 pSiS->maxClone_X1 = i->HDisplay; 1872 } 1873 if(pSiS->maxClone_X2 < j->HDisplay) { 1874 pSiS->maxClone_X2 = j->HDisplay; 1875 } 1876 if(pSiS->maxClone_Y1 < i->VDisplay) { 1877 pSiS->maxClone_Y1 = i->VDisplay; 1878 } 1879 if(pSiS->maxClone_Y2 < j->VDisplay) { 1880 pSiS->maxClone_Y2 = j->VDisplay; 1881 } 1882 } 1883 } 1884 currentMode = p; 1885 1886 } while((currentMode) && (currentMode != firstMode)); 1887 1888 pSiS->SiSXineramaVX = pScrn1->virtualX; 1889 pSiS->SiSXineramaVY = pScrn1->virtualY; 1890 infochanged = TRUE; 1891 1892 } 1893 1894 if((usenonrect) && (pSiS->CRT2Position != sisClone) && pSiS->maxCRT1_X1) { 1895 switch(pSiS->CRT2Position) { 1896 case sisLeftOf: 1897 case sisRightOf: 1898 if((pSiS->maxCRT1_Y1 != realvirtY) && (pSiS->maxCRT2_Y2 != realvirtY)) { 1899 usenonrect = FALSE; 1900 } 1901 break; 1902 case sisAbove: 1903 case sisBelow: 1904 if((pSiS->maxCRT1_X1 != realvirtX) && (pSiS->maxCRT2_X2 != realvirtX)) { 1905 usenonrect = FALSE; 1906 } 1907 break; 1908 case sisClone: 1909 break; 1910 } 1911 if(infochanged && !usenonrect) { 1912 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 1913 "Virtual screen size does not match maximum display modes...\n"); 1914 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, rectxine); 1915 1916 } 1917 } else if(infochanged && usenonrect) { 1918 usenonrect = FALSE; 1919 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 1920 "Only clone modes available for this virtual screen size...\n"); 1921 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, rectxine); 1922 } 1923 1924 if(pSiS->maxCRT1_X1) { /* Means we have at least one non-clone mode */ 1925 switch(pSiS->CRT2Position) { 1926 case sisLeftOf: 1927 x1 = min(pSiS->maxCRT1_X2, pScrn1->virtualX - pSiS->maxCRT1_X1); 1928 if(x1 < 0) x1 = 0; 1929 y1 = pSiS->CRT1YOffs; 1930 w1 = pScrn1->virtualX - x1; 1931 h1 = realvirtY; 1932 if((usenonrect) && (pSiS->maxCRT1_Y1 != realvirtY)) { 1933 h1 = pSiS->MBXNR1YMAX = pSiS->maxCRT1_Y1; 1934 pSiS->NonRectDead.x0 = x1; 1935 pSiS->NonRectDead.x1 = x1 + w1 - 1; 1936 pSiS->NonRectDead.y0 = y1 + h1; 1937 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 1938 pSiS->HaveNonRect = TRUE; 1939 } 1940 x2 = 0; 1941 y2 = pSiS->CRT2YOffs; 1942 w2 = max(pSiS->maxCRT2_X2, pScrn1->virtualX - pSiS->maxCRT2_X1); 1943 if(w2 > pScrn1->virtualX) w2 = pScrn1->virtualX; 1944 h2 = realvirtY; 1945 if((usenonrect) && (pSiS->maxCRT2_Y2 != realvirtY)) { 1946 h2 = pSiS->MBXNR2YMAX = pSiS->maxCRT2_Y2; 1947 pSiS->NonRectDead.x0 = x2; 1948 pSiS->NonRectDead.x1 = x2 + w2 - 1; 1949 pSiS->NonRectDead.y0 = y2 + h2; 1950 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 1951 pSiS->HaveNonRect = TRUE; 1952 } 1953 break; 1954 case sisRightOf: 1955 x1 = 0; 1956 y1 = pSiS->CRT1YOffs; 1957 w1 = max(pSiS->maxCRT1_X1, pScrn1->virtualX - pSiS->maxCRT1_X2); 1958 if(w1 > pScrn1->virtualX) w1 = pScrn1->virtualX; 1959 h1 = realvirtY; 1960 if((usenonrect) && (pSiS->maxCRT1_Y1 != realvirtY)) { 1961 h1 = pSiS->MBXNR1YMAX = pSiS->maxCRT1_Y1; 1962 pSiS->NonRectDead.x0 = x1; 1963 pSiS->NonRectDead.x1 = x1 + w1 - 1; 1964 pSiS->NonRectDead.y0 = y1 + h1; 1965 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 1966 pSiS->HaveNonRect = TRUE; 1967 } 1968 x2 = min(pSiS->maxCRT2_X1, pScrn1->virtualX - pSiS->maxCRT2_X2); 1969 if(x2 < 0) x2 = 0; 1970 y2 = pSiS->CRT2YOffs; 1971 w2 = pScrn1->virtualX - x2; 1972 h2 = realvirtY; 1973 if((usenonrect) && (pSiS->maxCRT2_Y2 != realvirtY)) { 1974 h2 = pSiS->MBXNR2YMAX = pSiS->maxCRT2_Y2; 1975 pSiS->NonRectDead.x0 = x2; 1976 pSiS->NonRectDead.x1 = x2 + w2 - 1; 1977 pSiS->NonRectDead.y0 = y2 + h2; 1978 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 1979 pSiS->HaveNonRect = TRUE; 1980 } 1981 break; 1982 case sisAbove: 1983 x1 = pSiS->CRT1XOffs; 1984 y1 = min(pSiS->maxCRT1_Y2, pScrn1->virtualY - pSiS->maxCRT1_Y1); 1985 if(y1 < 0) y1 = 0; 1986 w1 = realvirtX; 1987 h1 = pScrn1->virtualY - y1; 1988 if((usenonrect) && (pSiS->maxCRT1_X1 != realvirtX)) { 1989 w1 = pSiS->MBXNR1XMAX = pSiS->maxCRT1_X1; 1990 pSiS->NonRectDead.x0 = x1 + w1; 1991 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 1992 pSiS->NonRectDead.y0 = y1; 1993 pSiS->NonRectDead.y1 = y1 + h1 - 1; 1994 pSiS->HaveNonRect = TRUE; 1995 } 1996 x2 = pSiS->CRT2XOffs; 1997 y2 = 0; 1998 w2 = realvirtX; 1999 h2 = max(pSiS->maxCRT2_Y2, pScrn1->virtualY - pSiS->maxCRT2_Y1); 2000 if(h2 > pScrn1->virtualY) h2 = pScrn1->virtualY; 2001 if((usenonrect) && (pSiS->maxCRT2_X2 != realvirtX)) { 2002 w2 = pSiS->MBXNR2XMAX = pSiS->maxCRT2_X2; 2003 pSiS->NonRectDead.x0 = x2 + w2; 2004 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 2005 pSiS->NonRectDead.y0 = y2; 2006 pSiS->NonRectDead.y1 = y2 + h2 - 1; 2007 pSiS->HaveNonRect = TRUE; 2008 } 2009 break; 2010 case sisBelow: 2011 x1 = pSiS->CRT1XOffs; 2012 y1 = 0; 2013 w1 = realvirtX; 2014 h1 = max(pSiS->maxCRT1_Y1, pScrn1->virtualY - pSiS->maxCRT1_Y2); 2015 if(h1 > pScrn1->virtualY) h1 = pScrn1->virtualY; 2016 if((usenonrect) && (pSiS->maxCRT1_X1 != realvirtX)) { 2017 w1 = pSiS->MBXNR1XMAX = pSiS->maxCRT1_X1; 2018 pSiS->NonRectDead.x0 = x1 + w1; 2019 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 2020 pSiS->NonRectDead.y0 = y1; 2021 pSiS->NonRectDead.y1 = y1 + h1 - 1; 2022 pSiS->HaveNonRect = TRUE; 2023 } 2024 x2 = pSiS->CRT2XOffs; 2025 y2 = min(pSiS->maxCRT2_Y1, pScrn1->virtualY - pSiS->maxCRT2_Y2); 2026 if(y2 < 0) y2 = 0; 2027 w2 = realvirtX; 2028 h2 = pScrn1->virtualY - y2; 2029 if((usenonrect) && (pSiS->maxCRT2_X2 != realvirtX)) { 2030 w2 = pSiS->MBXNR2XMAX = pSiS->maxCRT2_X2; 2031 pSiS->NonRectDead.x0 = x2 + w2; 2032 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 2033 pSiS->NonRectDead.y0 = y2; 2034 pSiS->NonRectDead.y1 = y2 + h2 - 1; 2035 pSiS->HaveNonRect = TRUE; 2036 } 2037 default: 2038 break; 2039 } 2040 2041 switch(pSiS->CRT2Position) { 2042 case sisLeftOf: 2043 case sisRightOf: 2044 if(pSiS->CRT1YOffs) { 2045 pSiS->OffDead1.x0 = x1; 2046 pSiS->OffDead1.x1 = x1 + w1 - 1; 2047 pSiS->OffDead1.y0 = 0; 2048 pSiS->OffDead1.y1 = y1 - 1; 2049 pSiS->OffDead2.x0 = x2; 2050 pSiS->OffDead2.x1 = x2 + w2 - 1; 2051 pSiS->OffDead2.y0 = y2 + h2; 2052 pSiS->OffDead2.y1 = pScrn1->virtualY - 1; 2053 pSiS->HaveOffsRegions = TRUE; 2054 } else if(pSiS->CRT2YOffs) { 2055 pSiS->OffDead1.x0 = x2; 2056 pSiS->OffDead1.x1 = x2 + w2 - 1; 2057 pSiS->OffDead1.y0 = 0; 2058 pSiS->OffDead1.y1 = y2 - 1; 2059 pSiS->OffDead2.x0 = x1; 2060 pSiS->OffDead2.x1 = x1 + w1 - 1; 2061 pSiS->OffDead2.y0 = y1 + h1; 2062 pSiS->OffDead2.y1 = pScrn1->virtualY - 1; 2063 pSiS->HaveOffsRegions = TRUE; 2064 } 2065 break; 2066 case sisAbove: 2067 case sisBelow: 2068 if(pSiS->CRT1XOffs) { 2069 pSiS->OffDead1.x0 = x2 + w2; 2070 pSiS->OffDead1.x1 = pScrn1->virtualX - 1; 2071 pSiS->OffDead1.y0 = y2; 2072 pSiS->OffDead1.y1 = y2 + h2 - 1; 2073 pSiS->OffDead2.x0 = 0; 2074 pSiS->OffDead2.x1 = x1 - 1; 2075 pSiS->OffDead2.y0 = y1; 2076 pSiS->OffDead2.y1 = y1 + h1 - 1; 2077 pSiS->HaveOffsRegions = TRUE; 2078 } else if(pSiS->CRT2XOffs) { 2079 pSiS->OffDead1.x0 = x1 + w1; 2080 pSiS->OffDead1.x1 = pScrn1->virtualX - 1; 2081 pSiS->OffDead1.y0 = y1; 2082 pSiS->OffDead1.y1 = y1 + h1 - 1; 2083 pSiS->OffDead2.x0 = 0; 2084 pSiS->OffDead2.x1 = x2 - 1; 2085 pSiS->OffDead2.y0 = y2; 2086 pSiS->OffDead2.y1 = y2 + h2 - 1; 2087 pSiS->HaveOffsRegions = TRUE; 2088 } 2089 default: 2090 break; 2091 } 2092 2093 } else { /* Only clone-modes left */ 2094 2095 x1 = x2 = 0; 2096 y1 = y2 = 0; 2097 w1 = w2 = max(pSiS->maxClone_X1, pSiS->maxClone_X2); 2098 h1 = h2 = max(pSiS->maxClone_Y1, pSiS->maxClone_Y2); 2099 2100 } 2101 2102 SiSXineramadataPtr[crt1scrnnum].x = x1; 2103 SiSXineramadataPtr[crt1scrnnum].y = y1; 2104 SiSXineramadataPtr[crt1scrnnum].width = w1; 2105 SiSXineramadataPtr[crt1scrnnum].height = h1; 2106 SiSXineramadataPtr[crt2scrnnum].x = x2; 2107 SiSXineramadataPtr[crt2scrnnum].y = y2; 2108 SiSXineramadataPtr[crt2scrnnum].width = w2; 2109 SiSXineramadataPtr[crt2scrnnum].height = h2; 2110 2111 if(infochanged) { 2112 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2113 "Pseudo-Xinerama: CRT1 (Screen %d) (%d,%d)-(%d,%d)\n", 2114 crt1scrnnum, x1, y1, w1+x1-1, h1+y1-1); 2115 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2116 "Pseudo-Xinerama: CRT2 (Screen %d) (%d,%d)-(%d,%d)\n", 2117 crt2scrnnum, x2, y2, w2+x2-1, h2+y2-1); 2118 if(pSiS->HaveNonRect) { 2119 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2120 "Pseudo-Xinerama: Inaccessible area (%d,%d)-(%d,%d)\n", 2121 pSiS->NonRectDead.x0, pSiS->NonRectDead.y0, 2122 pSiS->NonRectDead.x1, pSiS->NonRectDead.y1); 2123 } 2124 if(pSiS->HaveOffsRegions) { 2125 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2126 "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", 2127 pSiS->OffDead1.x0, pSiS->OffDead1.y0, 2128 pSiS->OffDead1.x1, pSiS->OffDead1.y1); 2129 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2130 "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", 2131 pSiS->OffDead2.x0, pSiS->OffDead2.y0, 2132 pSiS->OffDead2.x1, pSiS->OffDead2.y1); 2133 } 2134 if(pSiS->HaveNonRect || pSiS->HaveOffsRegions) { 2135 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2136 "Mouse restriction for inaccessible areas is %s\n", 2137 pSiS->MouseRestrictions ? "enabled" : "disabled"); 2138 } 2139 } 2140} 2141 2142/* Proc */ 2143 2144int 2145SiSProcXineramaQueryVersion(ClientPtr client) 2146{ 2147 xPanoramiXQueryVersionReply rep; 2148 register int n; 2149 2150 REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq); 2151 rep.type = X_Reply; 2152 rep.length = 0; 2153 rep.sequenceNumber = client->sequence; 2154 rep.majorVersion = SIS_XINERAMA_MAJOR_VERSION; 2155 rep.minorVersion = SIS_XINERAMA_MINOR_VERSION; 2156 if(client->swapped) { 2157 _swaps(&rep.sequenceNumber, n); 2158 _swapl(&rep.length, n); 2159 _swaps(&rep.majorVersion, n); 2160 _swaps(&rep.minorVersion, n); 2161 } 2162 WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *)&rep); 2163 return (client->noClientException); 2164} 2165 2166int 2167SiSProcXineramaGetState(ClientPtr client) 2168{ 2169 REQUEST(xPanoramiXGetStateReq); 2170 WindowPtr pWin; 2171 xPanoramiXGetStateReply rep; 2172 register int n; 2173 int rc; 2174 2175 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); 2176 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 2177 if (rc != Success) 2178 return rc; 2179 2180 rep.type = X_Reply; 2181 rep.length = 0; 2182 rep.sequenceNumber = client->sequence; 2183 rep.state = !SiSnoPanoramiXExtension; 2184 if(client->swapped) { 2185 _swaps (&rep.sequenceNumber, n); 2186 _swapl (&rep.length, n); 2187 } 2188 WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *)&rep); 2189 return client->noClientException; 2190} 2191 2192int 2193SiSProcXineramaGetScreenCount(ClientPtr client) 2194{ 2195 REQUEST(xPanoramiXGetScreenCountReq); 2196 WindowPtr pWin; 2197 xPanoramiXGetScreenCountReply rep; 2198 register int n; 2199 int rc; 2200 2201 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); 2202 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 2203 if (rc != Success) 2204 return rc; 2205 2206 rep.type = X_Reply; 2207 rep.length = 0; 2208 rep.sequenceNumber = client->sequence; 2209 rep.ScreenCount = SiSXineramaNumScreens; 2210 if(client->swapped) { 2211 _swaps(&rep.sequenceNumber, n); 2212 _swapl(&rep.length, n); 2213 } 2214 WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep); 2215 return client->noClientException; 2216} 2217 2218int 2219SiSProcXineramaGetScreenSize(ClientPtr client) 2220{ 2221 REQUEST(xPanoramiXGetScreenSizeReq); 2222 WindowPtr pWin; 2223 xPanoramiXGetScreenSizeReply rep; 2224 register int n; 2225 int rc; 2226 2227 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); 2228 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 2229 if (rc != Success) 2230 return rc; 2231 2232 rep.type = X_Reply; 2233 rep.length = 0; 2234 rep.sequenceNumber = client->sequence; 2235 rep.width = SiSXineramadataPtr[stuff->screen].width; 2236 rep.height = SiSXineramadataPtr[stuff->screen].height; 2237 if(client->swapped) { 2238 _swaps(&rep.sequenceNumber, n); 2239 _swapl(&rep.length, n); 2240 _swapl(&rep.width, n); 2241 _swapl(&rep.height, n); 2242 } 2243 WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep); 2244 return client->noClientException; 2245} 2246 2247int 2248SiSProcXineramaIsActive(ClientPtr client) 2249{ 2250 xXineramaIsActiveReply rep; 2251 2252 REQUEST_SIZE_MATCH(xXineramaIsActiveReq); 2253 2254 rep.type = X_Reply; 2255 rep.length = 0; 2256 rep.sequenceNumber = client->sequence; 2257 rep.state = !SiSnoPanoramiXExtension; 2258 if(client->swapped) { 2259 register int n; 2260 _swaps(&rep.sequenceNumber, n); 2261 _swapl(&rep.length, n); 2262 _swapl(&rep.state, n); 2263 } 2264 WriteToClient(client, sizeof(xXineramaIsActiveReply), (char *) &rep); 2265 return client->noClientException; 2266} 2267 2268int 2269SiSProcXineramaQueryScreens(ClientPtr client) 2270{ 2271 xXineramaQueryScreensReply rep; 2272 2273 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); 2274 2275 rep.type = X_Reply; 2276 rep.sequenceNumber = client->sequence; 2277 rep.number = (SiSnoPanoramiXExtension) ? 0 : SiSXineramaNumScreens; 2278 rep.length = rep.number * sz_XineramaScreenInfo >> 2; 2279 if(client->swapped) { 2280 register int n; 2281 _swaps(&rep.sequenceNumber, n); 2282 _swapl(&rep.length, n); 2283 _swapl(&rep.number, n); 2284 } 2285 WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *)&rep); 2286 2287 if(!SiSnoPanoramiXExtension) { 2288 xXineramaScreenInfo scratch; 2289 int i; 2290 2291 for(i = 0; i < SiSXineramaNumScreens; i++) { 2292 scratch.x_org = SiSXineramadataPtr[i].x; 2293 scratch.y_org = SiSXineramadataPtr[i].y; 2294 scratch.width = SiSXineramadataPtr[i].width; 2295 scratch.height = SiSXineramadataPtr[i].height; 2296 if(client->swapped) { 2297 register int n; 2298 _swaps(&scratch.x_org, n); 2299 _swaps(&scratch.y_org, n); 2300 _swaps(&scratch.width, n); 2301 _swaps(&scratch.height, n); 2302 } 2303 WriteToClient(client, sz_XineramaScreenInfo, (char *)&scratch); 2304 } 2305 } 2306 2307 return client->noClientException; 2308} 2309 2310static int 2311SiSProcXineramaDispatch(ClientPtr client) 2312{ 2313 REQUEST(xReq); 2314 switch (stuff->data) { 2315 case X_PanoramiXQueryVersion: 2316 return SiSProcXineramaQueryVersion(client); 2317 case X_PanoramiXGetState: 2318 return SiSProcXineramaGetState(client); 2319 case X_PanoramiXGetScreenCount: 2320 return SiSProcXineramaGetScreenCount(client); 2321 case X_PanoramiXGetScreenSize: 2322 return SiSProcXineramaGetScreenSize(client); 2323 case X_XineramaIsActive: 2324 return SiSProcXineramaIsActive(client); 2325 case X_XineramaQueryScreens: 2326 return SiSProcXineramaQueryScreens(client); 2327 } 2328 return BadRequest; 2329} 2330 2331/* SProc */ 2332 2333static int 2334SiSSProcXineramaQueryVersion (ClientPtr client) 2335{ 2336 REQUEST(xPanoramiXQueryVersionReq); 2337 register int n; 2338 _swaps(&stuff->length,n); 2339 REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); 2340 return SiSProcXineramaQueryVersion(client); 2341} 2342 2343static int 2344SiSSProcXineramaGetState(ClientPtr client) 2345{ 2346 REQUEST(xPanoramiXGetStateReq); 2347 register int n; 2348 _swaps (&stuff->length, n); 2349 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); 2350 return SiSProcXineramaGetState(client); 2351} 2352 2353static int 2354SiSSProcXineramaGetScreenCount(ClientPtr client) 2355{ 2356 REQUEST(xPanoramiXGetScreenCountReq); 2357 register int n; 2358 _swaps (&stuff->length, n); 2359 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); 2360 return SiSProcXineramaGetScreenCount(client); 2361} 2362 2363static int 2364SiSSProcXineramaGetScreenSize(ClientPtr client) 2365{ 2366 REQUEST(xPanoramiXGetScreenSizeReq); 2367 register int n; 2368 _swaps (&stuff->length, n); 2369 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); 2370 return SiSProcXineramaGetScreenSize(client); 2371} 2372 2373static int 2374SiSSProcXineramaIsActive(ClientPtr client) 2375{ 2376 REQUEST(xXineramaIsActiveReq); 2377 register int n; 2378 _swaps (&stuff->length, n); 2379 REQUEST_SIZE_MATCH(xXineramaIsActiveReq); 2380 return SiSProcXineramaIsActive(client); 2381} 2382 2383static int 2384SiSSProcXineramaQueryScreens(ClientPtr client) 2385{ 2386 REQUEST(xXineramaQueryScreensReq); 2387 register int n; 2388 _swaps (&stuff->length, n); 2389 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); 2390 return SiSProcXineramaQueryScreens(client); 2391} 2392 2393int 2394SiSSProcXineramaDispatch(ClientPtr client) 2395{ 2396 REQUEST(xReq); 2397 switch (stuff->data) { 2398 case X_PanoramiXQueryVersion: 2399 return SiSSProcXineramaQueryVersion(client); 2400 case X_PanoramiXGetState: 2401 return SiSSProcXineramaGetState(client); 2402 case X_PanoramiXGetScreenCount: 2403 return SiSSProcXineramaGetScreenCount(client); 2404 case X_PanoramiXGetScreenSize: 2405 return SiSSProcXineramaGetScreenSize(client); 2406 case X_XineramaIsActive: 2407 return SiSSProcXineramaIsActive(client); 2408 case X_XineramaQueryScreens: 2409 return SiSSProcXineramaQueryScreens(client); 2410 } 2411 return BadRequest; 2412} 2413 2414static void 2415SiSXineramaResetProc(ExtensionEntry* extEntry) 2416{ 2417 /* Called by CloseDownExtensions() */ 2418 if(SiSXineramadataPtr) { 2419 free(SiSXineramadataPtr); 2420 SiSXineramadataPtr = NULL; 2421 } 2422} 2423 2424static void 2425SiSXineramaExtensionInit(ScrnInfoPtr pScrn) 2426{ 2427 SISPtr pSiS = SISPTR(pScrn); 2428 Bool success = FALSE; 2429 2430 if(!(SiSXineramadataPtr)) { 2431 2432 if(!pSiS->MergedFB) { 2433 SiSnoPanoramiXExtension = TRUE; 2434 pSiS->MouseRestrictions = FALSE; 2435 return; 2436 } 2437 2438#ifdef PANORAMIX 2439 if(!noPanoramiXExtension) { 2440 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2441 "Xinerama active, not initializing SiS Pseudo-Xinerama\n"); 2442 SiSnoPanoramiXExtension = TRUE; 2443 pSiS->MouseRestrictions = FALSE; 2444 return; 2445 } 2446#endif 2447 2448 if(SiSnoPanoramiXExtension) { 2449 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2450 "SiS Pseudo-Xinerama disabled\n"); 2451 pSiS->MouseRestrictions = FALSE; 2452 return; 2453 } 2454 2455 if(pSiS->CRT2Position == sisClone) { 2456 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2457 "Running MergedFB in Clone mode, SiS Pseudo-Xinerama disabled\n"); 2458 SiSnoPanoramiXExtension = TRUE; 2459 pSiS->MouseRestrictions = FALSE; 2460 return; 2461 } 2462 2463 if(!(pSiS->AtLeastOneNonClone)) { 2464 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2465 "Only Clone modes defined, SiS Pseudo-Xinerama disabled\n"); 2466 SiSnoPanoramiXExtension = TRUE; 2467 pSiS->MouseRestrictions = FALSE; 2468 return; 2469 } 2470 2471 SiSXineramaNumScreens = 2; 2472 2473 while(SiSXineramaGeneration != serverGeneration) { 2474 2475 pSiS->XineramaExtEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0, 2476 SiSProcXineramaDispatch, 2477 SiSSProcXineramaDispatch, 2478 SiSXineramaResetProc, 2479 StandardMinorOpcode); 2480 2481 if(!pSiS->XineramaExtEntry) break; 2482 2483 if(!(SiSXineramadataPtr = (SiSXineramaData *) 2484 calloc(SiSXineramaNumScreens, sizeof(SiSXineramaData)))) break; 2485 2486 SiSXineramaGeneration = serverGeneration; 2487 success = TRUE; 2488 } 2489 2490 if(!success) { 2491 SISErrorLog(pScrn, "Failed to initialize SiS Pseudo-Xinerama extension\n"); 2492 SiSnoPanoramiXExtension = TRUE; 2493 pSiS->MouseRestrictions = FALSE; 2494 return; 2495 } 2496 2497 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2498 "SiS Pseudo-Xinerama extension initialized\n"); 2499 2500 pSiS->SiSXineramaVX = 0; 2501 pSiS->SiSXineramaVY = 0; 2502 2503 } 2504 2505 SiSUpdateXineramaScreenInfo(pScrn); 2506 2507} 2508#endif /* End of PseudoXinerama */ 2509 2510static void 2511SiSFreeCRT2Structs(SISPtr pSiS) 2512{ 2513 if(pSiS->CRT2pScrn) { 2514 if(pSiS->CRT2pScrn->modes) { 2515 while(pSiS->CRT2pScrn->modes) 2516 xf86DeleteMode(&pSiS->CRT2pScrn->modes, pSiS->CRT2pScrn->modes); 2517 } 2518 if(pSiS->CRT2pScrn->monitor) { 2519 if(pSiS->CRT2pScrn->monitor->Modes) { 2520 while(pSiS->CRT2pScrn->monitor->Modes) 2521 xf86DeleteMode(&pSiS->CRT2pScrn->monitor->Modes, pSiS->CRT2pScrn->monitor->Modes); 2522 } 2523 if(pSiS->CRT2pScrn->monitor->DDC) free(pSiS->CRT2pScrn->monitor->DDC); 2524 free(pSiS->CRT2pScrn->monitor); 2525 } 2526 free(pSiS->CRT2pScrn); 2527 pSiS->CRT2pScrn = NULL; 2528 } 2529} 2530 2531#endif /* End of MergedFB helpers */ 2532 2533static xf86MonPtr 2534SiSInternalDDC(ScrnInfoPtr pScrn, int crtno) 2535{ 2536 SISPtr pSiS = SISPTR(pScrn); 2537 xf86MonPtr pMonitor = NULL; 2538 UShort temp = 0xffff, temp1, i, realcrtno = crtno; 2539 UChar buffer[256]; 2540 2541 /* If CRT1 is off, skip DDC */ 2542 if((pSiS->CRT1off) && (!crtno)) return NULL; 2543 2544 if(crtno) { 2545 if(pSiS->VBFlags & CRT2_LCD) realcrtno = 1; 2546 else if(pSiS->VBFlags & CRT2_VGA) realcrtno = 2; 2547 else return NULL; 2548 if(pSiS->SiS_Pr->DDCPortMixup) realcrtno = 0; 2549 } else { 2550 /* If CRT1 is LCDA, skip DDC (except 301C: DDC allowed, but uses CRT2 port!) */ 2551 if(pSiS->VBFlags & CRT1_LCDA) { 2552 if(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE) realcrtno = 1; 2553 else return NULL; 2554 } 2555 } 2556 2557 i = 3; /* Number of retrys */ 2558 do { 2559 temp1 = SiS_HandleDDC(pSiS->SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 2560 realcrtno, 0, &buffer[0], pSiS->VBFlags2); 2561 if((temp1) && (temp1 != 0xffff)) temp = temp1; 2562 } while((temp == 0xffff) && i--); 2563 if(temp != 0xffff) { 2564 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT%d DDC supported\n", crtno + 1); 2565 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT%d DDC level: %s%s%s%s\n", 2566 crtno + 1, 2567 (temp & 0x1a) ? "" : "[none of the supported]", 2568 (temp & 0x02) ? "2 " : "", 2569 (temp & 0x08) ? "D&P" : "", 2570 (temp & 0x10) ? "FPDI-2" : ""); 2571 if(temp & 0x02) { 2572 i = 5; /* Number of retrys */ 2573 do { 2574 temp = SiS_HandleDDC(pSiS->SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 2575 realcrtno, 1, &buffer[0], pSiS->VBFlags2); 2576 } while((temp) && i--); 2577 if(!temp) { 2578 if((pMonitor = xf86InterpretEDID(pScrn->scrnIndex, &buffer[0]))) { 2579 int tempvgagamma = 0, templcdgamma = 0; 2580 if(buffer[0x14] & 0x80) { 2581 templcdgamma = (buffer[0x17] + 100) * 10; 2582 } else { 2583 tempvgagamma = (buffer[0x17] + 100) * 10;; 2584 } 2585 if(crtno == 0) { 2586 if(tempvgagamma) pSiS->CRT1VGAMonitorGamma = tempvgagamma; 2587 /* LCD never via (demanded) CRT1 DDC port */ 2588 } else { 2589 if(tempvgagamma) pSiS->CRT2VGAMonitorGamma = tempvgagamma; 2590 if(templcdgamma) pSiS->CRT2LCDMonitorGamma = templcdgamma; 2591 } 2592 return(pMonitor); 2593 } else { 2594 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2595 "CRT%d DDC EDID corrupt\n", crtno + 1); 2596 } 2597 } else if(temp == 0xFFFE) { 2598 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2599 "CRT%d DDC data is from wrong device type (%s)\n", 2600 crtno + 1, 2601 (realcrtno == 1) ? "analog instead of digital" : "digital instead of analog"); 2602 } else { 2603 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2604 "CRT%d DDC reading failed\n", crtno + 1); 2605 } 2606 } else if(temp & 0x18) { 2607 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2608 "DDC for VESA D&P and FPDI-2 not supported yet.\n"); 2609 } 2610 } else { 2611 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2612 "CRT%d DDC probing failed\n", crtno + 1); 2613 } 2614 return(NULL); 2615} 2616 2617static xf86MonPtr 2618SiSDoPrivateDDC(ScrnInfoPtr pScrn, int *crtnum) 2619{ 2620 SISPtr pSiS = SISPTR(pScrn); 2621 2622#ifdef SISDUALHEAD 2623 if(pSiS->DualHeadMode) { 2624 if(pSiS->SecondHead) { 2625 *crtnum = 1; 2626 return(SiSInternalDDC(pScrn, 0)); 2627 } else { 2628 *crtnum = 2; 2629 return(SiSInternalDDC(pScrn, 1)); 2630 } 2631 } else 2632#endif 2633 if((pSiS->CRT1off) || (!pSiS->CRT1Detected)) { 2634 *crtnum = 2; 2635 return(SiSInternalDDC(pScrn, 1)); 2636 } else { 2637 *crtnum = 1; 2638 return(SiSInternalDDC(pScrn, 0)); 2639 } 2640} 2641 2642static void 2643SiSFindAspect(ScrnInfoPtr pScrn, xf86MonPtr pMonitor, int crtnum) 2644{ 2645 SISPtr pSiS = SISPTR(pScrn); 2646 int UseWide = 0; 2647 int aspect = 0; 2648 Bool fromdim = FALSE; 2649 2650 if((pSiS->VGAEngine == SIS_315_VGA) && (!DIGITAL(pMonitor->features.input_type))) { 2651 if(pMonitor->features.hsize && pMonitor->features.vsize) { 2652 aspect = (pMonitor->features.hsize * 1000) / pMonitor->features.vsize; 2653 if(aspect >= 1400) UseWide = 1; 2654 fromdim = TRUE; 2655 } else if((PREFERRED_TIMING_MODE(pMonitor->features.msc)) && 2656 (pMonitor->det_mon[0].type == DT)) { 2657 aspect = (pMonitor->det_mon[0].section.d_timings.h_active * 1000) / 2658 pMonitor->det_mon[0].section.d_timings.v_active; 2659 if(aspect >= 1400) UseWide = 1; 2660 } 2661 if(aspect) { 2662 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2663 "According to %s, CRT%d aspect ratio is %.2f:1 (%s)\n", 2664 fromdim ? "DDC size" : "preferred mode", 2665 crtnum, (float)aspect / 1000.0, UseWide ? "wide" : "normal"); 2666 } else { 2667 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2668 "Unable to determine CRT%d aspect ratio, assuming \"normal\"\n", 2669 crtnum); 2670 } 2671 } 2672 2673 if((crtnum == 1) && (pSiS->SiS_Pr->SiS_UseWide == -1)) { 2674 pSiS->SiS_Pr->SiS_UseWide = UseWide; 2675 } else if((crtnum == 2) && (pSiS->SiS_Pr->SiS_UseWideCRT2 == -1)) { 2676 pSiS->SiS_Pr->SiS_UseWideCRT2 = UseWide; 2677 } 2678} 2679 2680static Bool 2681SiSMakeOwnModeList(ScrnInfoPtr pScrn, Bool acceptcustommodes, Bool includelcdmodes, 2682 Bool isfordvi, Bool *havecustommodes, Bool fakecrt2modes, Bool IsForCRT2) 2683{ 2684 DisplayModePtr tempmode, delmode, mymodes; 2685 2686 if((mymodes = SiSBuildBuiltInModeList(pScrn, includelcdmodes, isfordvi, fakecrt2modes, IsForCRT2))) { 2687 if(!acceptcustommodes) { 2688 while(pScrn->monitor->Modes) 2689 xf86DeleteMode(&pScrn->monitor->Modes, pScrn->monitor->Modes); 2690 pScrn->monitor->Modes = mymodes; 2691 } else { 2692 delmode = pScrn->monitor->Modes; 2693 while(delmode) { 2694 if(delmode->type & M_T_DEFAULT) { 2695 tempmode = delmode->next; 2696 xf86DeleteMode(&pScrn->monitor->Modes, delmode); 2697 delmode = tempmode; 2698 } else { 2699 delmode = delmode->next; 2700 } 2701 } 2702 /* Link default modes AFTER user ones */ 2703 if((tempmode = pScrn->monitor->Modes)) { 2704 *havecustommodes = TRUE; 2705 while(tempmode) { 2706 if(!tempmode->next) break; 2707 else tempmode = tempmode->next; 2708 } 2709 tempmode->next = mymodes; 2710 mymodes->prev = tempmode; 2711 } else { 2712 pScrn->monitor->Modes = mymodes; 2713 } 2714#if 0 2715 pScrn->monitor->Modes = mymodes; 2716 while(mymodes) { 2717 if(!mymodes->next) break; 2718 else mymodes = mymodes->next; 2719 } 2720 mymodes->next = tempmode; 2721 if(tempmode) { 2722 tempmode->prev = mymodes; 2723 } 2724#endif 2725 } 2726 return TRUE; 2727 } else 2728 return FALSE; 2729} 2730 2731static void 2732SiSPrintModes(ScrnInfoPtr pScrn) 2733{ 2734 DisplayModePtr p; 2735 float hsync, refresh = 0.0; 2736 char *desc, *desc2, *prefix, *uprefix, *output; 2737 2738 xf86DrvMsg(pScrn->scrnIndex, pScrn->virtualFrom, "Virtual size is %dx%d " 2739 "(pitch %d)\n", pScrn->virtualX, pScrn->virtualY, 2740 pScrn->displayWidth); 2741 2742 if((p = pScrn->modes) == NULL) return; 2743 2744 do { 2745 desc = desc2 = ""; 2746 uprefix = " "; 2747 prefix = "Mode"; 2748 output = "For CRT device: "; 2749 if(p->HSync > 0.0) hsync = p->HSync; 2750 else if (p->HTotal > 0) hsync = (float)p->Clock / (float)p->HTotal; 2751 else hsync = 0.0; 2752 refresh = 0.0; 2753 if(p->VRefresh > 0.0) refresh = p->VRefresh; 2754 else if (p->HTotal > 0 && p->VTotal > 0) { 2755 refresh = p->Clock * 1000.0 / p->HTotal / p->VTotal; 2756 if(p->Flags & V_INTERLACE) refresh *= 2.0; 2757 if(p->Flags & V_DBLSCAN) refresh /= 2.0; 2758 if(p->VScan > 1) refresh /= p->VScan; 2759 } 2760 if(p->Flags & V_INTERLACE) desc = " (I)"; 2761 if(p->Flags & V_DBLSCAN) desc = " (D)"; 2762 if(p->VScan > 1) desc2 = " (VScan)"; 2763#ifdef M_T_USERDEF 2764 if(p->type & M_T_USERDEF) uprefix = "*"; 2765#endif 2766 if(p->type & M_T_BUILTIN) { 2767 prefix = "Built-in mode"; 2768 output = ""; 2769 } else if (p->type & M_T_DEFAULT) { 2770 prefix = "Default mode"; 2771 } else { 2772 output = ""; 2773 } 2774 2775 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2776 "%s%s \"%s\" (%dx%d) (%s%.1f MHz, %.1f kHz, %.1f Hz%s%s)\n", 2777 uprefix, prefix, p->name, p->HDisplay, p->VDisplay, output, 2778 p->Clock / 1000.0, hsync, refresh, desc, desc2); 2779 2780 p = p->next; 2781 } while (p != NULL && p != pScrn->modes); 2782} 2783 2784Bool SISDetermineLCDACap(ScrnInfoPtr pScrn) 2785{ 2786 SISPtr pSiS = SISPTR(pScrn); 2787 2788 if( ((pSiS->ChipType == SIS_650) || 2789 (pSiS->ChipType == SIS_315PRO) || 2790 (pSiS->ChipType >= SIS_661)) && 2791 (pSiS->ChipType != XGI_20) && 2792 (pSiS->VBFlags2 & VB2_SISLCDABRIDGE) && 2793 (pSiS->VESA != 1) ) { 2794 return TRUE; 2795 } 2796 return FALSE; 2797} 2798 2799void SISSaveDetectedDevices(ScrnInfoPtr pScrn) 2800{ 2801 SISPtr pSiS = SISPTR(pScrn); 2802 /* Backup detected CRT2 devices */ 2803 pSiS->detectedCRT2Devices = pSiS->VBFlags & (CRT2_LCD|CRT2_TV|CRT2_VGA|TV_AVIDEO|TV_SVIDEO| 2804 TV_SCART|TV_HIVISION|TV_YPBPR); 2805} 2806 2807static Bool 2808SISCheckBIOS(SISPtr pSiS, UShort mypciid, UShort mypcivendor, int biossize) 2809{ 2810 UShort romptr, pciid; 2811 2812 if(!pSiS->BIOS) return FALSE; 2813 2814 if((pSiS->BIOS[0] != 0x55) || (pSiS->BIOS[1] != 0xaa)) return FALSE; 2815 2816 romptr = pSiS->BIOS[0x18] | (pSiS->BIOS[0x19] << 8); 2817 if(romptr > (biossize - 8)) return FALSE; 2818 if((pSiS->BIOS[romptr] != 'P') || (pSiS->BIOS[romptr+1] != 'C') || 2819 (pSiS->BIOS[romptr+2] != 'I') || (pSiS->BIOS[romptr+3] != 'R')) return FALSE; 2820 2821 pciid = pSiS->BIOS[romptr+4] | (pSiS->BIOS[romptr+5] << 8); 2822 if(pciid != mypcivendor) return FALSE; 2823 2824 pciid = pSiS->BIOS[romptr+6] | (pSiS->BIOS[romptr+7] << 8); 2825 if(pciid != mypciid) return FALSE; 2826 2827 return TRUE; 2828} 2829 2830static void 2831SiS_LoadInitVBE(ScrnInfoPtr pScrn) 2832{ 2833 SISPtr pSiS = SISPTR(pScrn); 2834 2835 /* Don't load the VBE module for secondary 2836 * cards which sisfb POSTed. We don't want 2837 * int10 to overwrite our set up (such as 2838 * disabled a0000 memory address decoding). 2839 * We don't need the VBE anyway because 2840 * the card will never be in text mode, 2841 * and we can restore graphics modes just 2842 * perfectly. 2843 */ 2844 if( !pSiS->Primary && 2845 pSiS->sisfbcardposted) 2846 return; 2847 2848 if(pSiS->pVbe) return; 2849 2850 if(xf86LoadSubModule(pScrn, "vbe")) { 2851#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 2852 pSiS->pVbe = VBEInit(pSiS->pInt, pSiS->pEnt->index); 2853#else 2854 pSiS->pVbe = VBEExtendedInit(pSiS->pInt, pSiS->pEnt->index, 2855 SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH); 2856#endif 2857 } 2858 2859 if(!pSiS->pVbe) { 2860 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2861 "Failed to load/initialize vbe module\n"); 2862 } 2863} 2864 2865#ifdef SIS_PC_PLATFORM 2866static void 2867SiS_MapVGAMem(ScrnInfoPtr pScrn) 2868{ 2869 SISPtr pSiS = SISPTR(pScrn); 2870 2871 /* Map 64k VGA window for saving/restoring CGA fonts */ 2872 pSiS->VGAMapSize = 0x10000; 2873 pSiS->VGAMapPhys = 0; /* Default */ 2874 if((!pSiS->Primary) || (!pSiS->VGADecodingEnabled)) { 2875 /* If card is secondary or if a0000-address decoding 2876 * is disabled, set Phys to beginning of our video RAM. 2877 */ 2878 pSiS->VGAMapPhys = PCI_REGION_BASE(pSiS->PciInfo, 0, REGION_MEM); 2879 } 2880 if(!SiSVGAMapMem(pScrn)) { 2881 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2882 "Failed to map VGA memory (0x%lx), can't save/restore console fonts\n", 2883 pSiS->VGAMapPhys); 2884 } 2885} 2886#endif 2887 2888static void 2889SiS_CheckKernelFB(ScrnInfoPtr pScrn) 2890{ 2891 SISPtr pSiS = SISPTR(pScrn); 2892 int fd, i; 2893 CARD32 sisfbinfosize = 0, sisfbversion; 2894 sisfb_info *mysisfbinfo; 2895 char name[16]; 2896 2897 pSiS->donttrustpdc = FALSE; 2898 pSiS->sisfbpdc = 0xff; 2899 pSiS->sisfbpdca = 0xff; 2900 pSiS->sisfblcda = 0xff; 2901 pSiS->sisfbscalelcd = -1; 2902 pSiS->sisfbspecialtiming = CUT_NONE; 2903 pSiS->sisfb_haveemi = FALSE; 2904 pSiS->sisfbfound = FALSE; 2905 pSiS->sisfb_tvposvalid = FALSE; 2906 pSiS->sisfbdevname[0] = 0; 2907 pSiS->sisfb_havelock = FALSE; 2908 pSiS->sisfbHaveNewHeapDef = FALSE; 2909 pSiS->sisfbHeapSize = 0; 2910 pSiS->sisfbVideoOffset = 0; 2911 pSiS->sisfbxSTN = FALSE; 2912 pSiS->sisfbcanpost = FALSE; /* (Old) sisfb can't POST card */ 2913 pSiS->sisfbcardposted = TRUE; /* If (old) sisfb is running, card must have been POSTed */ 2914 pSiS->sisfbprimary = FALSE; /* (Old) sisfb doesn't know */ 2915 2916 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 2917 2918 i = 0; 2919 do { 2920 2921 if(i <= 7) { 2922 sprintf(name, "/dev/fb%1d", i); 2923 } else { 2924 sprintf(name, "/dev/fb/%1d", (i - 8)); 2925 } 2926 2927 if((fd = open(name, O_RDONLY)) != -1) { 2928 2929 Bool gotit = FALSE; 2930 2931 if(!ioctl(fd, SISFB_GET_INFO_SIZE, &sisfbinfosize)) { 2932 if((mysisfbinfo = malloc(sisfbinfosize))) { 2933 if(!ioctl(fd, (SISFB_GET_INFO | (sisfbinfosize << 16)), mysisfbinfo)) { 2934 gotit = TRUE; 2935 } else { 2936 free(mysisfbinfo); 2937 mysisfbinfo = NULL; 2938 } 2939 } 2940 } else { 2941 if((mysisfbinfo = malloc(sizeof(*mysisfbinfo) + 16))) { 2942 if(!ioctl(fd, SISFB_GET_INFO_OLD, mysisfbinfo)) { 2943 gotit = TRUE; 2944 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2945 "Possibly old version of sisfb detected. Please update.\n"); 2946 } else { 2947 free(mysisfbinfo); 2948 mysisfbinfo = NULL; 2949 } 2950 } 2951 } 2952 2953 if(gotit) { 2954 2955 if(mysisfbinfo->sisfb_id == SISFB_ID) { 2956 2957 sisfbversion = (mysisfbinfo->sisfb_version << 16) | 2958 (mysisfbinfo->sisfb_revision << 8) | 2959 (mysisfbinfo->sisfb_patchlevel); 2960 2961 if(sisfbversion >= SISFB_VERSION(1, 5, 8)) { 2962 /* Added PCI bus/slot/func into in sisfb Version 1.5.08. 2963 * Check this to make sure we run on the same card as sisfb 2964 */ 2965 if((mysisfbinfo->sisfb_pcibus == pSiS->PciBus) && 2966 (mysisfbinfo->sisfb_pcislot == pSiS->PciDevice) && 2967 (mysisfbinfo->sisfb_pcifunc == pSiS->PciFunc)) { 2968 pSiS->sisfbfound = TRUE; 2969 } 2970 } else pSiS->sisfbfound = TRUE; 2971 2972 if(pSiS->sisfbfound) { 2973 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2974 "%s: SiS kernel fb driver (sisfb) %d.%d.%d detected (PCI:%02d:%02d.%d)\n", 2975 &name[5], 2976 mysisfbinfo->sisfb_version, 2977 mysisfbinfo->sisfb_revision, 2978 mysisfbinfo->sisfb_patchlevel, 2979 pSiS->PciBus, 2980 pSiS->PciDevice, 2981 pSiS->PciFunc); 2982 2983 /* Added version/rev/pl in sisfb 1.4.0 */ 2984 if(mysisfbinfo->sisfb_version == 0) { 2985 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2986 "Old version of sisfb found. Please update.\n"); 2987 } 2988 /* Basically, we can't trust the pdc register if sisfb is loaded */ 2989 pSiS->donttrustpdc = TRUE; 2990 pSiS->sisfbHeapStart = mysisfbinfo->heapstart; 2991 2992 if(sisfbversion >= SISFB_VERSION(1, 7, 20)) { 2993 pSiS->sisfbHeapSize = mysisfbinfo->sisfb_heapsize; 2994 pSiS->sisfbVideoOffset = mysisfbinfo->sisfb_videooffset; 2995 pSiS->sisfbHaveNewHeapDef = TRUE; 2996 pSiS->sisfbFSTN = mysisfbinfo->sisfb_curfstn; 2997 pSiS->sisfbDSTN = mysisfbinfo->sisfb_curdstn; 2998 pSiS->sisfbxSTN = TRUE; 2999 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3000 "sisfb: memory heap at %dKB, size %dKB, viewport at %dKB\n", 3001 (int)pSiS->sisfbHeapStart, (int)pSiS->sisfbHeapSize, 3002 (int)pSiS->sisfbVideoOffset/1024); 3003 } else { 3004 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3005 "sisfb: memory heap at %dKB\n", (int)pSiS->sisfbHeapStart); 3006 } 3007 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3008 "sisfb: using video mode 0x%02x\n", mysisfbinfo->fbvidmode); 3009 pSiS->OldMode = mysisfbinfo->fbvidmode; 3010 if(sisfbversion >= SISFB_VERSION(1, 5, 6)) { 3011 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3012 "sisfb: using %s, reserved %dK\n", 3013 (mysisfbinfo->sisfb_caps & 0x40) ? "SiS300 series Turboqueue" : 3014 (mysisfbinfo->sisfb_caps & 0x20) ? "SiS315/330/340 series AGP command queue" : 3015 (mysisfbinfo->sisfb_caps & 0x10) ? "SiS315/330/340 series VRAM command queue" : 3016 (mysisfbinfo->sisfb_caps & 0x08) ? "SiS315/330/340 series MMIO mode" : 3017 "no command queue", 3018 (int)mysisfbinfo->sisfb_tqlen); 3019 } 3020 if(sisfbversion >= SISFB_VERSION(1, 5, 10)) { 3021 /* We can trust the pdc value if sisfb is of recent version */ 3022 if(pSiS->VGAEngine == SIS_300_VGA) pSiS->donttrustpdc = FALSE; 3023 } 3024 if(sisfbversion >= SISFB_VERSION(1, 5, 11)) { 3025 if(pSiS->VGAEngine == SIS_300_VGA) { 3026 /* As of 1.5.11, sisfb saved the register for us (300 series) */ 3027 pSiS->sisfbpdc = mysisfbinfo->sisfb_lcdpdc; 3028 if(!pSiS->sisfbpdc) pSiS->sisfbpdc = 0xff; 3029 } 3030 } 3031 if(sisfbversion >= SISFB_VERSION(1, 5, 14)) { 3032 if(pSiS->VGAEngine == SIS_315_VGA) { 3033 pSiS->sisfblcda = mysisfbinfo->sisfb_lcda; 3034 } 3035 } 3036 if(sisfbversion >= SISFB_VERSION(1, 6, 13)) { 3037 pSiS->sisfbscalelcd = mysisfbinfo->sisfb_scalelcd; 3038 pSiS->sisfbspecialtiming = mysisfbinfo->sisfb_specialtiming; 3039 } 3040 if(sisfbversion >= SISFB_VERSION(1, 6, 16)) { 3041 if(pSiS->VGAEngine == SIS_315_VGA) { 3042 pSiS->donttrustpdc = FALSE; 3043 pSiS->sisfbpdc = mysisfbinfo->sisfb_lcdpdc; 3044 if(sisfbversion >= SISFB_VERSION(1, 6, 24)) { 3045 pSiS->sisfb_haveemi = mysisfbinfo->sisfb_haveemi ? TRUE : FALSE; 3046 pSiS->sisfb_haveemilcd = TRUE; /* will match most cases */ 3047 pSiS->sisfb_emi30 = mysisfbinfo->sisfb_emi30; 3048 pSiS->sisfb_emi31 = mysisfbinfo->sisfb_emi31; 3049 pSiS->sisfb_emi32 = mysisfbinfo->sisfb_emi32; 3050 pSiS->sisfb_emi33 = mysisfbinfo->sisfb_emi33; 3051 } 3052 if(sisfbversion >= SISFB_VERSION(1, 6, 25)) { 3053 pSiS->sisfb_haveemilcd = mysisfbinfo->sisfb_haveemilcd ? TRUE : FALSE; 3054 } 3055 if(sisfbversion >= SISFB_VERSION(1, 6, 31)) { 3056 pSiS->sisfbpdca = mysisfbinfo->sisfb_lcdpdca; 3057 } else { 3058 if(pSiS->sisfbpdc) { 3059 pSiS->sisfbpdca = (pSiS->sisfbpdc & 0xf0) >> 3; 3060 pSiS->sisfbpdc = (pSiS->sisfbpdc & 0x0f) << 1; 3061 } else { 3062 pSiS->sisfbpdca = pSiS->sisfbpdc = 0xff; 3063 } 3064 } 3065 } 3066 } 3067 if(sisfbversion >= SISFB_VERSION(1, 7, 0)) { 3068 pSiS->sisfb_havelock = TRUE; 3069 if(sisfbversion >= SISFB_VERSION(1, 7, 1)) { 3070 pSiS->sisfb_tvxpos = mysisfbinfo->sisfb_tvxpos; 3071 pSiS->sisfb_tvypos = mysisfbinfo->sisfb_tvypos; 3072 pSiS->sisfb_tvposvalid = TRUE; 3073 } 3074 } 3075 if(sisfbversion >= SISFB_VERSION(1, 8, 7)) { 3076 pSiS->sisfbcanpost = (mysisfbinfo->sisfb_can_post) ? TRUE : FALSE; 3077 pSiS->sisfbcardposted = (mysisfbinfo->sisfb_card_posted) ? TRUE : FALSE; 3078 pSiS->sisfbprimary = (mysisfbinfo->sisfb_was_boot_device) ? TRUE : FALSE; 3079 /* Validity check */ 3080 if(!pSiS->sisfbcardposted) { 3081 pSiS->sisfbprimary = FALSE; 3082 } 3083 } 3084 } 3085 } 3086 free(mysisfbinfo); 3087 mysisfbinfo = NULL; 3088 } 3089 close (fd); 3090 } 3091 i++; 3092 } while((i <= 15) && (!pSiS->sisfbfound)); 3093 3094 if(pSiS->sisfbfound) { 3095 strncpy(pSiS->sisfbdevname, name, 15); 3096 } else { 3097 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "sisfb not found\n"); 3098 } 3099 } 3100 3101 if(!pSiS->sisfbfound) { 3102 pSiS->sisfbcardposted = FALSE; 3103 } 3104} 3105 3106static void 3107SiSPseudo(ScrnInfoPtr pScrn) 3108{ 3109} 3110 3111/* PreInit() 3112 * 3113 * Mandatory 3114 */ 3115static Bool 3116SISPreInit(ScrnInfoPtr pScrn, int flags) 3117{ 3118 SISPtr pSiS; 3119#ifdef SISDUALHEAD 3120 SISEntPtr pSiSEnt = NULL; 3121#endif 3122 MessageType from; 3123 UChar usScratchCR17, usScratchCR32, usScratchCR63; 3124 UChar usScratchSR1F, srlockReg, crlockReg; 3125 unsigned int i; 3126 int pix24flags, temp; 3127 ClockRangePtr clockRanges; 3128 xf86MonPtr pMonitor = NULL; 3129 Bool didddc2, fromDDC, crt1freqoverruled = FALSE; 3130 UChar CR5F, tempreg; 3131#if defined(SISMERGED) || defined(SISDUALHEAD) 3132 DisplayModePtr first, p, n; 3133#endif 3134#ifdef SISMERGED 3135 Bool crt2freqoverruled = FALSE; 3136#endif 3137 3138 static const char *ddcsstr = "CRT%d DDC monitor info: *******************************************\n"; 3139 static const char *ddcestr = "End of CRT%d DDC monitor info *************************************\n"; 3140 static const char *subshstr = "Substituting missing CRT%d monitor HSync range by DDC data\n"; 3141 static const char *subsvstr = "Substituting missing CRT%d monitor VRefresh range by DDC data\n"; 3142 static const char *saneh = "Correcting %s CRT%d monitor HSync range\n"; 3143 static const char *sanev = "Correcting %s CRT%d monitor VRefresh range\n"; 3144#ifdef SISMERGED 3145 static const char *mergednocrt1 = "CRT1 not detected or forced off. %s.\n"; 3146 static const char *mergednocrt2 = "No CRT2 output selected or no video bridge detected. %s.\n"; 3147 static const char *mergeddisstr = "MergedFB mode disabled"; 3148 static const char *modesforstr = "Modes for CRT%d: **************************************************\n"; 3149 static const char *crtsetupstr = "*************************** CRT%d setup ***************************\n"; 3150 static const char *crt2monname = "CRT2"; 3151#endif 3152#if defined(SISDUALHEAD) || defined(SISMERGED) 3153 static const char *notsuitablestr = "Not using mode \"%s\" (not suitable for %s mode)\n"; 3154#endif 3155 3156 if(flags & PROBE_DETECT) { 3157 3158 vbeInfoPtr pVbe; 3159 3160 if(xf86LoadSubModule(pScrn, "vbe")) { 3161 int index = xf86GetEntityInfo(pScrn->entityList[0])->index; 3162#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 3163 if((pVbe = VBEInit(NULL, index))) 3164#else 3165 if((pVbe = VBEExtendedInit(NULL, index, 0))) 3166#endif 3167 { 3168 ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 3169 vbeFree(pVbe); 3170 } 3171 } 3172 return TRUE; 3173 } 3174 3175 /* 3176 * Note: This function is only called once at server startup, and 3177 * not at the start of each server generation. This means that 3178 * only things that are persistent across server generations can 3179 * be initialised here. xf86Screens[] is the array of all screens, 3180 * (pScrn is a pointer to one of these). Privates allocated using 3181 * xf86AllocateScrnInfoPrivateIndex() are too, and should be used 3182 * for data that must persist across server generations. 3183 * 3184 * Per-generation data should be allocated with 3185 * AllocateScreenPrivateIndex() from the ScreenInit() function. 3186 */ 3187 3188 /* Check the number of entities, and fail if it isn't one. */ 3189 if(pScrn->numEntities != 1) { 3190 SISErrorLog(pScrn, "Number of entities is not 1\n"); 3191 return FALSE; 3192 } 3193 3194 /* Due to the liberal license terms this is needed for 3195 * keeping the copyright notice readable and intact in 3196 * binary distributions. Removing this is a copyright 3197 * infringement. Please read the license terms above. 3198 */ 3199 3200 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3201 "SiS driver (%d/%02d/%02d-%d, compiled for " SISMYSERVERNAME " %d.%d.%d.%d)\n", 3202 SISDRIVERVERSIONYEAR + 2000, SISDRIVERVERSIONMONTH, 3203 SISDRIVERVERSIONDAY, SISDRIVERREVISION, 3204#ifdef XORG_VERSION_CURRENT 3205 XORG_VERSION_MAJOR, XORG_VERSION_MINOR, 3206 XORG_VERSION_PATCH, XORG_VERSION_SNAP 3207#else 3208 XF86_VERSION_MAJOR, XF86_VERSION_MINOR, 3209 XF86_VERSION_PATCH, XF86_VERSION_SNAP 3210#endif 3211 ); 3212 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3213 "Copyright (C) 2001-2005 Thomas Winischhofer <thomas@winischhofer.net> and others\n"); 3214 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3215 "*** See http://www.winischhofer.eu/linuxsisvga.shtml\n"); 3216 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3217 "*** for documentation and updates.\n"); 3218 3219#ifdef XORG_VERSION_CURRENT 3220#if 0 /* no prototype yet */ 3221 if(xorgGetVersion() != XORG_VERSION_CURRENT) { 3222 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3223 "This driver binary is not compiled for this version of " SISMYSERVERNAME "\n"); 3224 } 3225#endif 3226#else 3227#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0) 3228 if(xf86GetVersion() != XF86_VERSION_CURRENT) { 3229 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3230 "This driver binary is not compiled for this version of " SISMYSERVERNAME "\n"); 3231 } 3232#endif 3233#endif 3234 3235 /* Allocate the SISRec driverPrivate */ 3236 if(!SISGetRec(pScrn)) { 3237 SISErrorLog(pScrn, "Could not allocate memory for pSiS private\n"); 3238 return FALSE; 3239 } 3240 pSiS = SISPTR(pScrn); 3241 pSiS->pScrn = pScrn; 3242 3243 pSiS->pInt = NULL; 3244 3245 /* Save PCI Domain Base */ 3246#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) || GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 12 3247 pSiS->IODBase = 0; 3248#else 3249 pSiS->IODBase = pScrn->domainIOBase; 3250#endif 3251 3252 /* Get the entity, and make sure it is PCI. */ 3253 pSiS->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 3254 if(pSiS->pEnt->location.type != BUS_PCI) { 3255 SISErrorLog(pScrn, "Entity's bus type is not PCI\n"); 3256 goto my_error_0; 3257 } 3258 3259#ifdef SISDUALHEAD 3260 /* Allocate an entity private if necessary */ 3261 if(xf86IsEntityShared(pScrn->entityList[0])) { 3262 pSiSEnt = xf86GetEntityPrivate(pScrn->entityList[0], SISEntityIndex)->ptr; 3263 pSiS->entityPrivate = pSiSEnt; 3264 3265 /* If something went wrong, quit here */ 3266 if((pSiSEnt->DisableDual) || (pSiSEnt->ErrorAfterFirst)) { 3267 SISErrorLog(pScrn, "First head encountered fatal error, aborting...\n"); 3268 goto my_error_0; 3269 } 3270 } 3271#endif 3272 3273 /* Find the PCI info for this screen */ 3274 pSiS->PciInfo = xf86GetPciInfoForEntity(pSiS->pEnt->index); 3275 pSiS->PciBus = PCI_CFG_BUS(pSiS->PciInfo); /*SIS_PCI_BUS(pSiS->PciInfo);*/ 3276 pSiS->PciDevice = PCI_CFG_DEV(pSiS->PciInfo); /*SIS_PCI_DEVICE(pSiS->PciInfo);*/ 3277 pSiS->PciFunc = PCI_CFG_FUNC(pSiS->PciInfo); /*SIS_PCI_FUNC(pSiS->PciInfo);*/ 3278 3279 pSiS->PciTag = pciTag(PCI_DEV_BUS(pSiS->PciInfo), 3280 PCI_DEV_DEV(pSiS->PciInfo), 3281 PCI_DEV_FUNC(pSiS->PciInfo)); 3282 3283#ifdef SIS_NEED_MAP_IOP 3284 /********************************************/ 3285 /* THIS IS BROKEN AND WON'T WORK */ 3286 /* Reasons: */ 3287 /* 1) MIPS and ARM have no i/o ports but */ 3288 /* use memory mapped i/o only. The inX/outX */ 3289 /* macros in compiler.h are smart enough to */ 3290 /* add "IOPortBase" to the port number, but */ 3291 /* "IOPortBase" is never initialized. */ 3292 /* 2) IOPortBase is declared in compiler.h */ 3293 /* itself. So until somebody fixes all */ 3294 /* modules that #include compiler.h to set */ 3295 /* IOPortBase, vga support for MIPS and ARM */ 3296 /* is unusable. */ 3297 /* (In this driver this is solvable because */ 3298 /* we have our own vgaHW routines. However, */ 3299 /* we use /dev/port for now instead.) */ 3300 /********************************************/ 3301 pSiS->IOPAddress = pSiS->IODBase + pSiS->PciInfo->ioBase[2]; 3302 if(!SISMapIOPMem(pScrn)) { 3303 SISErrorLog(pScrn, "Could not map I/O port area at 0x%x\n", pSiS->IOPAddress); 3304 goto my_error_0; 3305 } else { 3306 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I/O port area mapped to %p, size 128\n", pSiS->IOPBase); 3307#if defined(__mips__) || defined(__arm32__) 3308 /* inX/outX macros on these use IOPortBase as offset */ 3309 /* This is entirely skrewed. */ 3310 IOPortBase = (unsigned int)pSiS->IOPBase; 3311#endif 3312 } 3313#endif 3314 3315 /* Set up i/o port access (for non-x86) */ 3316#ifdef SISUSEDEVPORT 3317 if((sisdevport = open("/dev/port", O_RDWR, 0)) == -1) { 3318 SISErrorLog(pScrn, "Failed to open /dev/port for read/write\n"); 3319 goto my_error_0; 3320 } 3321 pSiS->sisdevportopen = TRUE; 3322#endif 3323 3324 /* 3325 * Set the Chipset and ChipRev, allowing config file entries to 3326 * override. DANGEROUS! 3327 */ 3328 { 3329 SymTabRec *myChipsets = SISChipsets; 3330 3331 if(PCI_DEV_VENDOR_ID(pSiS->PciInfo) == PCI_VENDOR_XGI) { 3332 myChipsets = XGIChipsets; 3333 } 3334 3335 if(pSiS->pEnt->device->chipset && *pSiS->pEnt->device->chipset) { 3336 3337 pScrn->chipset = pSiS->pEnt->device->chipset; 3338 pSiS->Chipset = xf86StringToToken(myChipsets, pScrn->chipset); 3339 3340 } else if(pSiS->pEnt->device->chipID >= 0) { 3341 3342 pSiS->Chipset = pSiS->pEnt->device->chipID; 3343 pScrn->chipset = (char *)xf86TokenToString(myChipsets, pSiS->Chipset); 3344 3345 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", 3346 pSiS->Chipset); 3347 } else { 3348 3349 pSiS->Chipset = PCI_DEV_DEVICE_ID(pSiS->PciInfo); 3350 pScrn->chipset = (char *)xf86TokenToString(myChipsets, pSiS->Chipset); 3351 3352 } 3353 } 3354 3355 if(pSiS->pEnt->device->chipRev >= 0) { 3356 3357 pSiS->ChipRev = pSiS->pEnt->device->chipRev; 3358 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 3359 pSiS->ChipRev); 3360 } else { 3361 3362 pSiS->ChipRev = PCI_DEV_REVISION(pSiS->PciInfo); 3363 3364 } 3365 3366 /* 3367 * This shouldn't happen because such problems should be caught in 3368 * SISProbe(), but check it just in case the user has overridden them. 3369 */ 3370 if(pScrn->chipset == NULL) { 3371 SISErrorLog(pScrn, "ChipID 0x%04X is not recognised\n", pSiS->Chipset); 3372 goto my_error_0; 3373 } 3374 if(pSiS->Chipset < 0) { 3375 SISErrorLog(pScrn, "Chipset \"%s\" is not recognised\n", pScrn->chipset); 3376 goto my_error_0; 3377 } 3378 3379 pSiS->SiS6326Flags = 0; 3380 3381 /* Determine VGA engine generation */ 3382 switch(pSiS->Chipset) { 3383 case PCI_CHIP_SIS300: 3384 case PCI_CHIP_SIS540: 3385 case PCI_CHIP_SIS630: /* 630 + 730 */ 3386 pSiS->VGAEngine = SIS_300_VGA; 3387 break; 3388 case PCI_CHIP_SIS315H: 3389 case PCI_CHIP_SIS315: 3390 case PCI_CHIP_SIS315PRO: 3391 case PCI_CHIP_SIS550: 3392 case PCI_CHIP_SIS650: /* 650 + 740 */ 3393 case PCI_CHIP_SIS330: 3394 case PCI_CHIP_SIS660: /* 660, 661, 741, 760, 761, 670(?), 770 */ 3395 case PCI_CHIP_SIS340: 3396 case PCI_CHIP_XGIXG20: 3397 case PCI_CHIP_XGIXG40: 3398 pSiS->VGAEngine = SIS_315_VGA; 3399 break; 3400 case PCI_CHIP_SIS530: 3401 pSiS->VGAEngine = SIS_530_VGA; 3402 break; 3403 case PCI_CHIP_SIS6326: 3404 /* Determine SiS6326 revision. According to SiS the differences are: 3405 * Chip name Chip type TV-Out MPEG II decoder 3406 * 6326 AGP Rev. G0/H0 no no 3407 * 6326 DVD Rev. D2 yes yes 3408 * 6326 Rev. Cx yes yes 3409 */ 3410 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3411 "Chipset is SiS6326 %s (revision 0x%02x)\n", 3412 (pSiS->ChipRev == 0xaf) ? "(Ax)" : 3413 ((pSiS->ChipRev == 0x0a) ? "AGP (G0)" : 3414 ((pSiS->ChipRev == 0x0b) ? "AGP (H0)" : 3415 (((pSiS->ChipRev & 0xf0) == 0xd0) ? "DVD (Dx/H0)" : 3416 (((pSiS->ChipRev & 0xf0) == 0x90) ? "(9x)" : 3417 (((pSiS->ChipRev & 0xf0) == 0xc0) ? "(Cx)" : 3418 "(unknown)"))))), 3419 pSiS->ChipRev); 3420 if((pSiS->ChipRev != 0x0a) && (pSiS->ChipRev != 0x0b)) { 3421 pSiS->SiS6326Flags |= SIS6326_HASTV; 3422 } 3423 /* fall through */ 3424 default: 3425 pSiS->VGAEngine = SIS_OLD_VGA; 3426 } 3427 3428 /* We don't know about the current mode yet */ 3429 pSiS->OldMode = 0; 3430 3431 /* Determine whether this is the primary or a secondary 3432 * display adapter. And right here the problem starts: 3433 * On machines with integrated SiS chipsets, the system BIOS 3434 * usually sets VGA_EN on all PCI-to-PCI bridges in the system 3435 * (of which there usually are two: PCI and AGP). This and 3436 * the fact that any PCI card POSTed by sisfb naturally has 3437 * its PCI resources enabled, leads to X assuming that 3438 * there are more than one "primary" cards in the system. 3439 * In this case, X treats ALL cards as "secondary" - 3440 * which by no means is desireable. If sisfb is running, 3441 * we can determine which card really is "primary" (in 3442 * terms of if it's the one that occupies the A0000 area 3443 * etc.) in a better way (Linux 2.6.12 or later). See below. 3444 */ 3445 if(!(pSiS->Primary = xf86IsPrimaryPci(pSiS->PciInfo))) { 3446 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3447 SISMYSERVERNAME " assumes this adapter to be secondary\n"); 3448 } 3449 3450 /* Now check if sisfb is running, and if so, retrieve 3451 * all possible info from it. This also resets all 3452 * sisfb_* entries in pSiS regardless of the chipset. 3453 */ 3454 SiS_CheckKernelFB(pScrn); 3455 3456 /* Now for that primary/secondary mess: Linux kernel 3457 * 2.6.12 and later knows what card is primary, and so 3458 * does any recent version of sisfb. XFree86/X.org takes 3459 * all adapters as "secondary" if more than one card's 3460 * memory and i/o resources are enabled, and more than 3461 * one PCI bridge in the system has VGA_EN set at server 3462 * start. So, let's start thinking: What is this 3463 * primary/secondary classification needed for anyway? 3464 * (This list might be incomplete for the entire server 3465 * infrastructure, but it's complete as regards the driver's 3466 * purposes of primary/secondary classification.) 3467 * 1) VGA/console font restoring: Here it's irrelevant 3468 * whether more than one card's resources are enabled 3469 * at server start or not. Relevant is whether the card 3470 * occupies the A0000 area at this time. Assuming (?) 3471 * that this does not change during machine up-time, 3472 * it suffices to know which device was the boot video 3473 * device (as determined by Linux 2.6.12 and later). 3474 * Also, this is only relevant if the card is in text 3475 * mode; if it's in graphics mode, fonts aren't saved 3476 * or restored anyway. 3477 * sisfb tells us if that card is considered the boot 3478 * video device. The hardware registers tell us if 3479 * the card's A0000 address decoding is enabled, and if 3480 * the card currently is in text mode. These three bits 3481 * of information are enough to decide on whether or not 3482 * to save/restore fonts. 3483 * 2) POSTing. Same here. Relevant is only whether or not 3484 * the card has been POSTed once before. POSTing cards 3485 * on every server start is pretty ugly, especially 3486 * if a framebuffer driver is already handling it. 3487 * SiS/XGI cards POSTed by sisfb can coexist well with other 3488 * active adapters. So we trust sisfb's information more 3489 * than X's (especially as we only use this information for 3490 * console font restoring and eventual POSTing.) 3491 * What we still need is a way to find out about all this if 3492 * sisfb is not running.... 3493 */ 3494 if(!pSiS->Primary && pSiS->sisfbprimary) { 3495 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3496 "sisfb reports this adapter to be primary. Seems more reliable.\n"); 3497 pSiS->Primary = TRUE; 3498 } 3499 3500 /* If the card is "secondary" and has not been 3501 * POSTed by sisfb, POST it now through int10. 3502 * For cards POSTed by sisfb, we definitely don't 3503 * want that as it messes up our set up (eg. the 3504 * disabled A0000 area). 3505 * The int10 module decides on its own if the 3506 * card is primary or secondary. Since it uses 3507 * the generic technique described above, and since 3508 * for "secondary" cards it needs a real PCI BIOS 3509 * ROM, and since integrated chips don't have such 3510 * a PCI BIOS ROM, int10 will naturally fail to 3511 * find/read the BIOS on such machines. Great. 3512 * Using the integrated graphics as "secondary" 3513 * (which it will be as soon as X finds more than 3514 * one card's mem and i/o resources enabled, and more 3515 * than one PCI bridge's VGA_EN bit set during server 3516 * start) will therefore prevent us from restoring 3517 * the mode using the VBE. That means real fun if 3518 * the integrated chip is set up to use the video 3519 * bridge output for text mode (which is something 3520 * the driver doesn't really support since it's done 3521 * pretty much differently on every machine.) 3522 */ 3523#if !defined(__alpha__) 3524 if(!pSiS->Primary) { 3525 if(!pSiS->sisfbcardposted) { 3526 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3527 "Initializing adapter through int10\n"); 3528 if(xf86LoadSubModule(pScrn, "int10")) { 3529 pSiS->pInt = xf86InitInt10(pSiS->pEnt->index); 3530 } else { 3531 SISErrorLog(pScrn, "Failed to load int10 module\n"); 3532 } 3533 } else { 3534 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3535 "Adapter already initialized by sisfb\n"); 3536 } 3537 } 3538#endif 3539 3540 /* Get the address of our relocated IO registers. 3541 * These are enabled by the hardware during cold boot, and 3542 * by the BIOS. So we can pretty much rely on that these 3543 * are enabled. 3544 */ 3545 pSiS->RelIO = (SISIOADDRESS)(PCI_REGION_BASE(pSiS->PciInfo, 2, REGION_IO) + pSiS->IODBase); 3546 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Relocated I/O registers at 0x%lX\n", 3547 (ULong)pSiS->RelIO); 3548 3549 /* Unlock extended registers */ 3550 sisSaveUnlockExtRegisterLock(pSiS, &srlockReg, &crlockReg); 3551 3552 /* Is a0000 memory address decoding enabled? */ 3553 pSiS->VGADecodingEnabled = TRUE; 3554 switch(pSiS->VGAEngine) { 3555 case SIS_OLD_VGA: 3556 /* n/a */ 3557 break; 3558 case SIS_530_VGA: 3559 inSISIDXREG(SISSR, 0x3d, tempreg); 3560 if(tempreg & 0x04) pSiS->VGADecodingEnabled = FALSE; 3561 break; 3562 case SIS_300_VGA: 3563 case SIS_315_VGA: 3564 inSISIDXREG(SISSR, 0x20, tempreg); 3565 if(tempreg & 0x04) pSiS->VGADecodingEnabled = FALSE; 3566 break; 3567 } 3568 3569 if(!pSiS->VGADecodingEnabled) { 3570 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3571 "Standard VGA (0xA0000) memory address decoding is disabled\n"); 3572 } 3573 3574#ifdef SIS_PC_PLATFORM 3575 /* Map 64k VGA window for saving/restoring CGA fonts. 3576 * For secondary cards or if A0000 address decoding 3577 * is disabled, this will map the beginning of the 3578 * linear (PCI) video RAM instead. 3579 */ 3580 SiS_MapVGAMem(pScrn); 3581#endif 3582 3583#ifndef XSERVER_LIBPCIACCESS 3584 /* Set operating state */ 3585 3586 /* 1. memory */ 3587 /* [ResUnusedOpr: Resource decoded by hw, but not used] 3588 * [ResDisableOpr: Resource is not decoded by hw] 3589 * So, if a0000 memory decoding is disabled, one could 3590 * argue that we may say so, too. Hm. Quite likely that 3591 * the VBE (via int10) will eventually enable it. So we 3592 * cowardly say unused instead. 3593 */ 3594 xf86SetOperatingState(resVgaMem, pSiS->pEnt->index, ResUnusedOpr); 3595 3596 /* 2. i/o */ 3597 /* Although we only use the relocated i/o ports, the hardware 3598 * also decodes the standard VGA port range. This could in 3599 * theory be disabled, but I don't dare to do this; in case of 3600 * a server crash, the card would be entirely dead. Also, this 3601 * would prevent int10 and the VBE from working at all. Generic 3602 * access control through the PCI configuration registers does 3603 * nicely anyway. 3604 */ 3605 xf86SetOperatingState(resVgaIo, pSiS->pEnt->index, ResUnusedOpr); 3606 3607 /* Operations for which memory access is required */ 3608 pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; 3609 3610 /* Operations for which I/O access is required */ 3611 pScrn->racIoFlags = RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; 3612 3613#endif 3614 3615 /* Load ramdac module */ 3616 if(!xf86LoadSubModule(pScrn, "ramdac")) { 3617 SISErrorLog(pScrn, "Could not load ramdac module\n"); 3618 goto my_error_1; 3619 } 3620 3621 /* Set pScrn->monitor */ 3622 pScrn->monitor = pScrn->confScreen->monitor; 3623 3624 /* Reset some entries */ 3625 pSiS->SiSFastVidCopy = SiSVidCopyGetDefault(); 3626 pSiS->SiSFastMemCopy = SiSVidCopyGetDefault(); 3627 pSiS->SiSFastVidCopyFrom = SiSVidCopyGetDefault(); 3628 pSiS->SiSFastMemCopyFrom = SiSVidCopyGetDefault(); 3629 pSiS->SiSFastVidCopyDone = FALSE; 3630#ifdef SIS_USE_XAA 3631 pSiS->RenderCallback = NULL; 3632#endif 3633#ifdef SIS_USE_EXA 3634 pSiS->ExaRenderCallback = NULL; 3635#endif 3636 pSiS->InitAccel = SiSPseudo; 3637 pSiS->SyncAccel = SiSPseudo; 3638 pSiS->FillRect = NULL; 3639 pSiS->BlitRect = NULL; 3640 3641 /* Always do a ValidMode() inside Switchmode() */ 3642 pSiS->skipswitchcheck = FALSE; 3643 3644 /* Determine chipset and its capabilities in detail */ 3645 pSiS->ChipFlags = 0; 3646 pSiS->SiS_SD_Flags = pSiS->SiS_SD2_Flags = 0; 3647 pSiS->SiS_SD3_Flags = pSiS->SiS_SD4_Flags = 0; 3648 pSiS->HWCursorMBufNum = pSiS->HWCursorCBufNum = 0; 3649 pSiS->NeedFlush = FALSE; 3650 pSiS->NewCRLayout = FALSE; 3651 pSiS->mmioSize = 64; 3652 3653 switch(pSiS->Chipset) { 3654 case PCI_CHIP_SIS530: 3655 pSiS->ChipType = SIS_530; 3656 break; 3657 case PCI_CHIP_SIS300: 3658 pSiS->ChipType = SIS_300; 3659 pSiS->SiS_SD_Flags |= SiS_SD_IS300SERIES; 3660 break; 3661 case PCI_CHIP_SIS540: 3662 pSiS->ChipType = SIS_540; 3663 pSiS->SiS_SD_Flags |= SiS_SD_IS300SERIES; 3664 break; 3665 case PCI_CHIP_SIS630: /* 630 + 730 */ 3666 pSiS->ChipType = SIS_630; 3667 if(sis_pci_read_host_bridge_u32(0x00) == 0x07301039) { 3668 pSiS->ChipType = SIS_730; 3669 } 3670 pSiS->SiS_SD_Flags |= SiS_SD_IS300SERIES; 3671 break; 3672 case PCI_CHIP_SIS315H: 3673 pSiS->ChipType = SIS_315H; 3674 pSiS->ChipFlags |= (SiSCF_315Core | SiSCF_MMIOPalette); 3675 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3676 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3677 pSiS->myCR63 = 0x63; 3678 break; 3679 case PCI_CHIP_SIS315: 3680 /* Override for simplicity */ 3681 pSiS->Chipset = PCI_CHIP_SIS315H; 3682 pSiS->ChipType = SIS_315; 3683 pSiS->ChipFlags |= (SiSCF_315Core | SiSCF_MMIOPalette); 3684 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3685 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3686 pSiS->myCR63 = 0x63; 3687 break; 3688 case PCI_CHIP_SIS315PRO: 3689 /* Override for simplicity */ 3690 pSiS->Chipset = PCI_CHIP_SIS315H; 3691 pSiS->ChipType = SIS_315PRO; 3692 pSiS->ChipFlags |= (SiSCF_315Core | SiSCF_MMIOPalette); 3693 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3694 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3695 pSiS->myCR63 = 0x63; 3696 break; 3697 case PCI_CHIP_SIS550: 3698 pSiS->ChipType = SIS_550; 3699 pSiS->ChipFlags |= (SiSCF_Integrated | SiSCF_MMIOPalette); 3700 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3701 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3702 pSiS->myCR63 = 0x63; 3703 break; 3704 case PCI_CHIP_SIS650: /* 650 + 740 */ 3705 pSiS->ChipType = SIS_650; 3706 if(sis_pci_read_host_bridge_u32(0x00) == 0x07401039) { 3707 pSiS->ChipType = SIS_740; 3708 } 3709 pSiS->ChipFlags |= (SiSCF_Integrated | SiSCF_Real256ECore | SiSCF_MMIOPalette); 3710 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3711 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3712 pSiS->myCR63 = 0x63; 3713 break; 3714 case PCI_CHIP_SIS330: 3715 pSiS->ChipType = SIS_330; 3716 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette); 3717 pSiS->SiS_SD_Flags |= SiS_SD_IS330SERIES; 3718 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3719 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; /* FIXME ? */ 3720 pSiS->myCR63 = 0x53; /* sic! */ 3721 break; 3722 case PCI_CHIP_SIS660: /* 660, 661, 741, 760, 761, 670(?) */ 3723 { 3724 ULong hpciid = sis_pci_read_host_bridge_u32(0x00); 3725 switch(hpciid) { 3726 case 0x06601039: 3727 pSiS->ChipType = SIS_660; 3728 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3729 pSiS->NeedFlush = TRUE; 3730 break; 3731 case 0x07601039: 3732 pSiS->ChipType = SIS_760; 3733 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3734 pSiS->NeedFlush = TRUE; 3735 break; 3736 case 0x07611039: 3737 pSiS->ChipType = SIS_761; 3738 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3739 pSiS->NeedFlush = TRUE; 3740 break; 3741 case 0x07701039: 3742 pSiS->ChipType = SIS_770; 3743 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3744 pSiS->NeedFlush = TRUE; 3745 break; 3746 case 0x07411039: 3747 pSiS->ChipType = SIS_741; 3748 pSiS->ChipFlags |= SiSCF_Real256ECore; 3749 break; 3750 case 0x06611039: 3751 default: 3752 pSiS->ChipType = SIS_661; 3753 pSiS->ChipFlags |= SiSCF_Real256ECore; 3754 break; 3755 case 0x06701039: 3756 pSiS->ChipType = SIS_670; 3757 pSiS->ChipFlags |= SiSCF_Real256ECore; 3758 } 3759 /* Detection could also be done by CR5C & 0xf8: 3760 * 0x10 = 661 (CR5F & 0xc0: 0x00 both A0 and A1) 3761 * 0x80 = 760 (CR5F & 0xc0: 0x00 A0, 0x40 A1) 3762 * 0x90 = 741 (CR5F & 0xc0: 0x00 A0,A1 0x40 A2) 3763 * other: 660 (CR5F & 0xc0: 0x00 A0 0x40 A1) (DOA?) 3764 */ 3765 pSiS->ChipFlags |= (SiSCF_Integrated | SiSCF_MMIOPalette); 3766 pSiS->SiS_SD_Flags |= SiS_SD_IS330SERIES; 3767 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3768 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; 3769 pSiS->myCR63 = 0x53; /* sic! */ 3770 pSiS->NewCRLayout = TRUE; 3771 } 3772 break; 3773 case PCI_CHIP_SIS340: 3774 pSiS->ChipType = SIS_340; 3775 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette); 3776 pSiS->SiS_SD_Flags |= SiS_SD_IS340SERIES; 3777 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3778 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; 3779 pSiS->myCR63 = 0x53; 3780 pSiS->NewCRLayout = TRUE; 3781 break; 3782 case PCI_CHIP_XGIXG20: 3783 pSiS->ChipType = XGI_20; 3784 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette | SiSCF_IsXGI); 3785 pSiS->SiS_SD2_Flags |= (SiS_SD2_NOOVERLAY | SiS_SD2_ISXGI); 3786 pSiS->myCR63 = 0x53; 3787 pSiS->NewCRLayout = TRUE; 3788 break; 3789 case PCI_CHIP_XGIXG40: 3790 pSiS->ChipType = XGI_40; 3791 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette | SiSCF_IsXGI); 3792 pSiS->SiS_SD2_Flags |= (SiS_SD2_SUPPORTXVHUESAT | SiS_SD2_ISXGI); 3793 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; 3794 pSiS->myCR63 = 0x53; 3795 pSiS->NewCRLayout = TRUE; 3796 if(pSiS->ChipRev == 2) pSiS->ChipFlags |= SiSCF_IsXGIV3; 3797 break; 3798 default: 3799 pSiS->ChipType = SIS_OLD; 3800 break; 3801 } 3802 3803 /* 3804 * Now back to real business: Figure out the depth, bpp, etc. 3805 * Set SupportConvert... flags since we use the fb layer which 3806 * supports this conversion. (24to32 seems not implemented though) 3807 * Additionally, determine the size of the HWCursor memory area. 3808 */ 3809 switch(pSiS->VGAEngine) { 3810 case SIS_300_VGA: 3811 pSiS->CursorSize = 4096; 3812 pix24flags = Support32bppFb; 3813 break; 3814 case SIS_315_VGA: 3815 pSiS->CursorSize = 16384; 3816 pix24flags = Support32bppFb; 3817 break; 3818 case SIS_530_VGA: 3819 pSiS->CursorSize = 2048; 3820 pix24flags = Support32bppFb | 3821 Support24bppFb | 3822 SupportConvert32to24; 3823 break; 3824 default: 3825 pSiS->CursorSize = 2048; 3826 pix24flags = Support24bppFb | 3827 SupportConvert32to24 | 3828 PreferConvert32to24; 3829 break; 3830 } 3831 3832#ifdef SISDUALHEAD 3833 /* In case of Dual Head, we need to determine if we are the "master" head or 3834 * the "slave" head. In order to do that, we set PrimInit to DONE in the 3835 * shared entity at the end of the first initialization. The second 3836 * initialization then knows that some things have already been done. THIS 3837 * ALWAYS ASSUMES THAT THE FIRST DEVICE INITIALIZED IS THE MASTER! 3838 */ 3839 if(xf86IsEntityShared(pScrn->entityList[0])) { 3840 if(pSiSEnt->lastInstance > 0) { 3841 if(!xf86IsPrimInitDone(pScrn->entityList[0])) { 3842 /* First Head (always CRT2) */ 3843 pSiS->SecondHead = FALSE; 3844 pSiSEnt->pScrn_1 = pScrn; 3845 pSiSEnt->CRT1ModeNo = pSiSEnt->CRT2ModeNo = -1; 3846 pSiSEnt->CRT2ModeSet = FALSE; 3847 pSiS->DualHeadMode = TRUE; 3848 pSiSEnt->DisableDual = FALSE; 3849 pSiSEnt->BIOS = NULL; 3850 pSiSEnt->ROM661New = FALSE; 3851 pSiSEnt->HaveXGIBIOS = FALSE; 3852 pSiSEnt->SiS_Pr = NULL; 3853 pSiSEnt->RenderAccelArray = NULL; 3854 pSiSEnt->SiSFastVidCopy = pSiSEnt->SiSFastMemCopy = NULL; 3855 pSiSEnt->SiSFastVidCopyFrom = pSiSEnt->SiSFastMemCopyFrom = NULL; 3856 } else { 3857 /* Second Head (always CRT1) */ 3858 pSiS->SecondHead = TRUE; 3859 pSiSEnt->pScrn_2 = pScrn; 3860 pSiS->DualHeadMode = TRUE; 3861 } 3862 } else { 3863 /* Only one screen in config file - disable dual head mode */ 3864 pSiS->SecondHead = FALSE; 3865 pSiS->DualHeadMode = FALSE; 3866 pSiSEnt->DisableDual = TRUE; 3867 } 3868 } else { 3869 /* Entity is not shared - disable dual head mode */ 3870 pSiS->SecondHead = FALSE; 3871 pSiS->DualHeadMode = FALSE; 3872 } 3873#endif 3874 3875 /* Save the name of our Device section for SiSCtrl usage */ 3876 { 3877 int ttt = 0; 3878 GDevPtr device = xf86GetDevFromEntity(pScrn->entityList[0], 3879 pScrn->entityInstanceList[0]); 3880 if(device && device->identifier) { 3881 if((ttt = strlen(device->identifier)) > 31) ttt = 31; 3882 strncpy(&pSiS->devsectname[0], device->identifier, 31); 3883 } 3884 pSiS->devsectname[ttt] = 0; 3885 } 3886 3887 pSiS->ForceCursorOff = FALSE; 3888 3889 /* Allocate SiS_Private (for mode switching code) and initialize it */ 3890 pSiS->SiS_Pr = NULL; 3891#ifdef SISDUALHEAD 3892 if(pSiSEnt) { 3893 if(pSiSEnt->SiS_Pr) pSiS->SiS_Pr = pSiSEnt->SiS_Pr; 3894 } 3895#endif 3896 if(!pSiS->SiS_Pr) { 3897 if(!(pSiS->SiS_Pr = xnfcalloc(sizeof(struct SiS_Private), 1))) { 3898 SISErrorLog(pScrn, "Could not allocate memory for SiS_Pr structure\n"); 3899 goto my_error_1; 3900 } 3901#ifdef SISDUALHEAD 3902 if(pSiSEnt) pSiSEnt->SiS_Pr = pSiS->SiS_Pr; 3903#endif 3904 memset(pSiS->SiS_Pr, 0, sizeof(struct SiS_Private)); 3905 pSiS->SiS_Pr->PciTag = pSiS->PciTag; 3906 pSiS->SiS_Pr->ChipType = pSiS->ChipType; 3907 pSiS->SiS_Pr->ChipRevision = pSiS->ChipRev; 3908 pSiS->SiS_Pr->SiS_Backup70xx = 0xff; 3909 pSiS->SiS_Pr->SiS_CHOverScan = -1; 3910 pSiS->SiS_Pr->SiS_ChSW = FALSE; 3911 pSiS->SiS_Pr->SiS_CustomT = CUT_NONE; 3912 pSiS->SiS_Pr->SiS_UseWide = -1; 3913 pSiS->SiS_Pr->SiS_UseWideCRT2 = -1; 3914 pSiS->SiS_Pr->SiS_TVBlue = -1; 3915 pSiS->SiS_Pr->PanelSelfDetected = FALSE; 3916 pSiS->SiS_Pr->UsePanelScaler = -1; 3917 pSiS->SiS_Pr->CenterScreen = -1; 3918 pSiS->SiS_Pr->CRT1UsesCustomMode = FALSE; 3919 pSiS->SiS_Pr->PDC = pSiS->SiS_Pr->PDCA = -1; 3920 pSiS->SiS_Pr->LVDSHL = -1; 3921 pSiS->SiS_Pr->HaveEMI = FALSE; 3922 pSiS->SiS_Pr->HaveEMILCD = FALSE; 3923 pSiS->SiS_Pr->OverruleEMI = FALSE; 3924 pSiS->SiS_Pr->SiS_SensibleSR11 = FALSE; 3925 if(pSiS->ChipType >= SIS_661) { 3926 pSiS->SiS_Pr->SiS_SensibleSR11 = TRUE; 3927 } 3928 pSiS->SiS_Pr->SiS_MyCR63 = pSiS->myCR63; 3929 pSiS->SiS_Pr->DDCPortMixup = FALSE; 3930 } 3931 3932 /* Copy IO address to SiS_Pr and init the structure for 3933 * routines inside init.c/init301.c 3934 */ 3935 pSiS->SiS_Pr->IOAddress = (SISIOADDRESS)(pSiS->RelIO + 0x30); 3936 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO + 0x30); 3937 3938 /* The following identifies the old chipsets. This is only 3939 * partly used since the really old chips are not supported, 3940 * but I keep it here for future use. 3941 * 205, 215 and 225 are to be treated the same way, 201 and 202 3942 * are different. 3943 */ 3944 if(pSiS->VGAEngine == SIS_OLD_VGA || pSiS->VGAEngine == SIS_530_VGA) { 3945 switch(pSiS->Chipset) { 3946 case PCI_CHIP_SG86C201: 3947 pSiS->oldChipset = OC_SIS86201; break; 3948 case PCI_CHIP_SG86C202: 3949 pSiS->oldChipset = OC_SIS86202; break; 3950 case PCI_CHIP_SG86C205: 3951 inSISIDXREG(SISSR, 0x10, tempreg); 3952 if(tempreg & 0x80) pSiS->oldChipset = OC_SIS6205B; 3953 else pSiS->oldChipset = (pSiS->ChipRev == 0x11) ? 3954 OC_SIS6205C : OC_SIS6205A; 3955 break; 3956 case PCI_CHIP_SIS82C204: 3957 pSiS->oldChipset = OC_SIS82204; break; 3958 case 0x6225: 3959 pSiS->oldChipset = OC_SIS6225; break; 3960 case PCI_CHIP_SIS5597: 3961 pSiS->oldChipset = OC_SIS5597; break; 3962 case PCI_CHIP_SIS6326: 3963 pSiS->oldChipset = OC_SIS6326; break; 3964 case PCI_CHIP_SIS530: 3965 if(sis_pci_read_host_bridge_u32(0x00) == 0x06201039) { 3966 pSiS->oldChipset = OC_SIS620; 3967 } else { 3968 if((pSiS->ChipRev & 0x0f) < 0x0a) 3969 pSiS->oldChipset = OC_SIS530A; 3970 else pSiS->oldChipset = OC_SIS530B; 3971 } 3972 break; 3973 default: 3974 pSiS->oldChipset = OC_UNKNOWN; 3975 } 3976 } 3977 3978 if(!xf86SetDepthBpp(pScrn, 0, 0, 0, pix24flags)) { 3979 SISErrorLog(pScrn, "xf86SetDepthBpp() error\n"); 3980 goto my_error_1; 3981 } 3982 3983 /* Check that the returned depth is one we support */ 3984 temp = 0; 3985 switch(pScrn->depth) { 3986 case 8: 3987 case 16: 3988 case 24: 3989 break; 3990 case 15: 3991 if((pSiS->VGAEngine == SIS_300_VGA) || 3992 (pSiS->VGAEngine == SIS_315_VGA)) { 3993 temp = 1; 3994 } 3995 break; 3996 default: 3997 temp = 1; 3998 } 3999 4000 if(temp) { 4001 SISErrorLog(pScrn, 4002 "Given color depth (%d) is not supported by this driver/chipset\n", 4003 pScrn->depth); 4004 goto my_error_1; 4005 } 4006 4007 xf86PrintDepthBpp(pScrn); 4008 4009 if( (((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) && 4010 (pScrn->bitsPerPixel == 24)) || 4011 ((pSiS->VGAEngine == SIS_OLD_VGA) && (pScrn->bitsPerPixel == 32)) ) { 4012 SISErrorLog(pScrn, 4013 "Framebuffer bpp %d not supported for this chipset\n", pScrn->bitsPerPixel); 4014 goto my_error_1; 4015 } 4016 4017 /* Get the depth24 pixmap format */ 4018 if(pScrn->depth == 24 && pix24bpp == 0) { 4019 pix24bpp = xf86GetBppFromDepth(pScrn, 24); 4020 } 4021 4022 /* 4023 * This must happen after pScrn->display has been set because 4024 * xf86SetWeight references it. 4025 */ 4026 if(pScrn->depth > 8) { 4027 /* The defaults are OK for us */ 4028 rgb zeros = {0, 0, 0}; 4029 4030 if(!xf86SetWeight(pScrn, zeros, zeros)) { 4031 SISErrorLog(pScrn, "xf86SetWeight() error\n"); 4032 goto my_error_1; 4033 } else { 4034 Bool ret = FALSE; 4035 switch(pScrn->depth) { 4036 case 15: 4037 if((pScrn->weight.red != 5) || 4038 (pScrn->weight.green != 5) || 4039 (pScrn->weight.blue != 5)) ret = TRUE; 4040 break; 4041 case 16: 4042 if((pScrn->weight.red != 5) || 4043 (pScrn->weight.green != 6) || 4044 (pScrn->weight.blue != 5)) ret = TRUE; 4045 break; 4046 case 24: 4047 if((pScrn->weight.red != 8) || 4048 (pScrn->weight.green != 8) || 4049 (pScrn->weight.blue != 8)) ret = TRUE; 4050 break; 4051 } 4052 if(ret) { 4053 SISErrorLog(pScrn, 4054 "RGB weight %d%d%d at depth %d not supported by hardware\n", 4055 (int)pScrn->weight.red, (int)pScrn->weight.green, 4056 (int)pScrn->weight.blue, pScrn->depth); 4057 goto my_error_1; 4058 } 4059 } 4060 } 4061 4062 /* Set the current layout parameters */ 4063 pSiS->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel; 4064 pSiS->CurrentLayout.depth = pScrn->depth; 4065 /* (Inside this function, we can use pScrn's contents anyway) */ 4066 4067 if(!xf86SetDefaultVisual(pScrn, -1)) { 4068 SISErrorLog(pScrn, "xf86SetDefaultVisual() error\n"); 4069 goto my_error_1; 4070 } else { 4071 /* We don't support DirectColor at > 8bpp */ 4072 if(pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { 4073 SISErrorLog(pScrn, 4074 "Given default visual (%s) is not supported at depth %d\n", 4075 xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); 4076 goto my_error_1; 4077 } 4078 } 4079 4080#ifdef SISDUALHEAD 4081 /* Due to palette & timing problems we don't support 8bpp in DHM */ 4082 if((pSiS->DualHeadMode) && (pScrn->bitsPerPixel <= 8)) { 4083 SISErrorLog(pScrn, "Color depth %d not supported in Dual Head mode.\n", 4084 pScrn->bitsPerPixel); 4085 goto my_error_1; 4086 } 4087#endif 4088 4089 /* Read BIOS for 300/315/330/340 series customization */ 4090 pSiS->SiS_Pr->VirtualRomBase = NULL; 4091 pSiS->BIOS = NULL; 4092 pSiS->SiS_Pr->UseROM = FALSE; 4093 pSiS->ROM661New = FALSE; 4094 pSiS->HaveXGIBIOS = FALSE; 4095 4096 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 4097#ifdef SISDUALHEAD 4098 if(pSiSEnt) { 4099 if(pSiSEnt->BIOS) { 4100 pSiS->BIOS = pSiSEnt->BIOS; 4101 pSiS->SiS_Pr->VirtualRomBase = pSiS->BIOS; 4102 pSiS->ROM661New = pSiSEnt->ROM661New; 4103 pSiS->HaveXGIBIOS = pSiSEnt->HaveXGIBIOS; 4104 } 4105 } 4106#endif 4107 if(!pSiS->BIOS) { 4108 if(!(pSiS->BIOS = calloc(1, BIOS_SIZE))) { 4109 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4110 "Could not allocate memory for video BIOS image\n"); 4111 } else { 4112 UShort mypciid = pSiS->Chipset; 4113 UShort mypcivendor = (pSiS->ChipFlags & SiSCF_IsXGI) ? PCI_VENDOR_XGI : PCI_VENDOR_SIS; 4114 Bool found = FALSE, readpci = FALSE; 4115 int biossize = BIOS_SIZE; 4116 4117 switch(pSiS->ChipType) { 4118 case SIS_315: mypciid = PCI_CHIP_SIS315; 4119 readpci = TRUE; 4120 break; 4121 case SIS_315PRO: mypciid = PCI_CHIP_SIS315PRO; 4122 readpci = TRUE; 4123 break; 4124 case SIS_300: 4125 case SIS_315H: 4126 case SIS_330: 4127 case SIS_340: 4128 case SIS_650: 4129 case SIS_760: 4130 case XGI_40: readpci = TRUE; 4131 break; 4132 case XGI_20: readpci = TRUE; 4133 biossize = 0x8000; 4134 break; 4135 } 4136#if XSERVER_LIBPCIACCESS 4137 if(readpci) { 4138 pSiS->PciInfo->rom_size = biossize; 4139 pci_device_read_rom(pSiS->PciInfo, pSiS->BIOS); 4140 if(SISCheckBIOS(pSiS, mypciid, mypcivendor, biossize)) { 4141 found = TRUE; 4142 } 4143 } 4144#else 4145 if(readpci) { 4146 xf86ReadPciBIOS(0, pSiS->PciTag, 0, pSiS->BIOS, biossize); 4147 if(SISCheckBIOS(pSiS, mypciid, mypcivendor, biossize)) { 4148 found = TRUE; 4149 } 4150 } 4151 4152 if(!found) { 4153 ULong segstart; 4154 for(segstart = BIOS_BASE; segstart < 0x000f0000; segstart += 0x00001000) { 4155 4156#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 4157 if(xf86ReadBIOS(segstart, 0, pSiS->BIOS, biossize) != biossize) continue; 4158#else 4159 if(xf86ReadDomainMemory(pSiS->PciTag, segstart, biossize, pSiS->BIOS) != biossize) continue; 4160#endif 4161 4162 if(!SISCheckBIOS(pSiS, mypciid, mypcivendor, biossize)) continue; 4163 4164 found = TRUE; 4165 break; 4166 } 4167 } 4168#endif 4169 if(found) { 4170 UShort romptr = pSiS->BIOS[0x16] | (pSiS->BIOS[0x17] << 8); 4171 pSiS->SiS_Pr->VirtualRomBase = pSiS->BIOS; 4172 if(pSiS->ChipFlags & SiSCF_IsXGI) { 4173 pSiS->HaveXGIBIOS = pSiS->SiS_Pr->SiS_XGIROM = TRUE; 4174 pSiS->SiS_Pr->UseROM = FALSE; 4175 if(pSiS->ChipFlags & SiSCF_IsXGIV3) { 4176 if(!(pSiS->BIOS[0x1d1] & 0x01)) { 4177 pSiS->SiS_Pr->DDCPortMixup = TRUE; 4178 } 4179 } 4180 } else { 4181 pSiS->ROM661New = SiSDetermineROMLayout661(pSiS->SiS_Pr); 4182 } 4183 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4184 "Video BIOS version \"%7s\" found (%s data layout)\n", 4185 &pSiS->BIOS[romptr], pSiS->ROM661New ? "new SiS" : 4186 (pSiS->HaveXGIBIOS ? "XGI" : "old SiS")); 4187 if(pSiS->SiS_Pr->DDCPortMixup) { 4188 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4189 "*** Buggy XGI V3XT card detected: If VGA and DVI are connected at the\n"); 4190 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4191 "*** same time, BIOS and driver will be unable to detect DVI connection.\n"); 4192 } 4193#ifdef SISDUALHEAD 4194 if(pSiSEnt) { 4195 pSiSEnt->BIOS = pSiS->BIOS; 4196 pSiSEnt->ROM661New = pSiS->ROM661New; 4197 pSiSEnt->HaveXGIBIOS = pSiS->HaveXGIBIOS; 4198 } 4199#endif 4200 } else { 4201 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4202 "Could not find/read video BIOS\n"); 4203 free(pSiS->BIOS); 4204 pSiS->BIOS = NULL; 4205 } 4206 } 4207 } 4208 4209 if(!(pSiS->ChipFlags & SiSCF_IsXGI)) { 4210 if(pSiS->BIOS) pSiS->SiS_Pr->UseROM = TRUE; 4211 else pSiS->SiS_Pr->UseROM = FALSE; 4212 } 4213 } 4214 4215 /* Evaluate options */ 4216 SiSOptions(pScrn); 4217 4218#ifdef SISMERGED 4219 /* Due to palette & timing problems we don't support 8bpp in MFBM */ 4220 if((pSiS->MergedFB) && (pScrn->bitsPerPixel <= 8)) { 4221 SISErrorLog(pScrn, "MergedFB: Color depth %d not supported, %s\n", 4222 pScrn->bitsPerPixel, mergeddisstr); 4223 pSiS->MergedFB = pSiS->MergedFBAuto = FALSE; 4224 } 4225#endif 4226 4227 /* Probe CPU features */ 4228#ifdef SISDUALHEAD 4229 if(pSiS->DualHeadMode) { 4230 pSiS->CPUFlags = pSiSEnt->CPUFlags; 4231 } 4232#endif 4233 if(!pSiS->CPUFlags) { 4234 pSiS->CPUFlags = SiSGetCPUFlags(pScrn); 4235 pSiS->CPUFlags |= SIS_CPUFL_FLAG; 4236#ifdef SISDUALHEAD 4237 if(pSiS->DualHeadMode) pSiSEnt->CPUFlags = pSiS->CPUFlags; 4238#endif 4239 } 4240 4241 /* We use a programamble clock */ 4242 pScrn->progClock = TRUE; 4243 4244 /* Set the bits per RGB for 8bpp mode */ 4245 if(pScrn->depth == 8) pScrn->rgbBits = 8; 4246 4247#ifdef SISDUALHEAD 4248 if(pSiS->DualHeadMode) { 4249 if(!pSiS->SecondHead) { 4250 /* Copy some option settings to entity private */ 4251 pSiSEnt->HWCursor = pSiS->HWCursor; 4252 pSiSEnt->NoAccel = pSiS->NoAccel; 4253 pSiSEnt->useEXA = pSiS->useEXA; 4254 pSiSEnt->restorebyset = pSiS->restorebyset; 4255 pSiSEnt->OptROMUsage = pSiS->OptROMUsage; 4256 pSiSEnt->OptUseOEM = pSiS->OptUseOEM; 4257 pSiSEnt->TurboQueue = pSiS->TurboQueue; 4258 pSiSEnt->forceCRT1 = pSiS->forceCRT1; 4259 pSiSEnt->ForceCRT1Type = pSiS->ForceCRT1Type; 4260 pSiSEnt->CRT1TypeForced = pSiS->CRT1TypeForced; 4261 pSiSEnt->ForceCRT2Type = pSiS->ForceCRT2Type; 4262 pSiSEnt->ForceTVType = pSiS->ForceTVType; 4263 pSiSEnt->ForceYPbPrType = pSiS->ForceYPbPrType; 4264 pSiSEnt->ForceYPbPrAR = pSiS->ForceYPbPrAR; 4265 pSiSEnt->UsePanelScaler = pSiS->UsePanelScaler; 4266 pSiSEnt->CenterLCD = pSiS->CenterLCD; 4267 pSiSEnt->DSTN = pSiS->DSTN; 4268 pSiSEnt->FSTN = pSiS->FSTN; 4269 pSiSEnt->OptTVStand = pSiS->OptTVStand; 4270 pSiSEnt->NonDefaultPAL = pSiS->NonDefaultPAL; 4271 pSiSEnt->NonDefaultNTSC = pSiS->NonDefaultNTSC; 4272 pSiSEnt->chtvtype = pSiS->chtvtype; 4273 pSiSEnt->OptTVOver = pSiS->OptTVOver; 4274 pSiSEnt->OptTVSOver = pSiS->OptTVSOver; 4275 pSiSEnt->chtvlumabandwidthcvbs = pSiS->chtvlumabandwidthcvbs; 4276 pSiSEnt->chtvlumabandwidthsvideo = pSiS->chtvlumabandwidthsvideo; 4277 pSiSEnt->chtvlumaflickerfilter = pSiS->chtvlumaflickerfilter; 4278 pSiSEnt->chtvchromabandwidth = pSiS->chtvchromabandwidth; 4279 pSiSEnt->chtvchromaflickerfilter = pSiS->chtvchromaflickerfilter; 4280 pSiSEnt->chtvtextenhance = pSiS->chtvtextenhance; 4281 pSiSEnt->chtvcontrast = pSiS->chtvcontrast; 4282 pSiSEnt->chtvcvbscolor = pSiS->chtvcvbscolor; 4283 pSiSEnt->sistvedgeenhance = pSiS->sistvedgeenhance; 4284 pSiSEnt->sistvantiflicker = pSiS->sistvantiflicker; 4285 pSiSEnt->sistvsaturation = pSiS->sistvsaturation; 4286 pSiSEnt->sistvcfilter = pSiS->sistvcfilter; 4287 pSiSEnt->sistvyfilter = pSiS->sistvyfilter; 4288 pSiSEnt->sistvcolcalibc = pSiS->sistvcolcalibc; 4289 pSiSEnt->sistvcolcalibf = pSiS->sistvcolcalibf; 4290 pSiSEnt->tvxpos = pSiS->tvxpos; 4291 pSiSEnt->tvypos = pSiS->tvypos; 4292 pSiSEnt->tvxscale = pSiS->tvxscale; 4293 pSiSEnt->tvyscale = pSiS->tvyscale; 4294 pSiSEnt->siscrt1satgain = pSiS->siscrt1satgain; 4295 pSiSEnt->crt1satgaingiven = pSiS->crt1satgaingiven; 4296 pSiSEnt->CRT1gamma = pSiS->CRT1gamma; 4297 pSiSEnt->CRT1gammaGiven = pSiS->CRT1gammaGiven; 4298 pSiSEnt->XvGammaRed = pSiS->XvGammaRed; 4299 pSiSEnt->XvGammaGreen = pSiS->XvGammaGreen; 4300 pSiSEnt->XvGammaBlue = pSiS->XvGammaBlue; 4301 pSiSEnt->XvGamma = pSiS->XvGamma; 4302 pSiSEnt->XvGammaGiven = pSiS->XvGammaGiven; 4303 pSiSEnt->CRT2gamma = pSiS->CRT2gamma; 4304 pSiSEnt->XvOnCRT2 = pSiS->XvOnCRT2; 4305 pSiSEnt->AllowHotkey = pSiS->AllowHotkey; 4306 pSiSEnt->enablesisctrl = pSiS->enablesisctrl; 4307 pSiSEnt->SenseYPbPr = pSiS->SenseYPbPr; 4308 pSiSEnt->XvUseMemcpy = pSiS->XvUseMemcpy; 4309 pSiSEnt->BenchMemCpy = pSiS->BenchMemCpy; 4310#ifdef SIS_CP 4311 SIS_CP_DRIVER_COPYOPTIONSENT 4312#endif 4313 } else { 4314 /* We always use same cursor type on both screens */ 4315 pSiS->HWCursor = pSiSEnt->HWCursor; 4316 /* We need identical NoAccel setting */ 4317 pSiS->NoAccel = pSiSEnt->NoAccel; 4318 pSiS->useEXA = pSiSEnt->useEXA; 4319 pSiS->TurboQueue = pSiSEnt->TurboQueue; 4320 pSiS->restorebyset = pSiSEnt->restorebyset; 4321 pSiS->AllowHotkey = pSiS->AllowHotkey; 4322 pSiS->OptROMUsage = pSiSEnt->OptROMUsage; 4323 pSiS->OptUseOEM = pSiSEnt->OptUseOEM; 4324 pSiS->forceCRT1 = pSiSEnt->forceCRT1; 4325 pSiS->nocrt2ddcdetection = FALSE; 4326 pSiS->forcecrt2redetection = FALSE; 4327 pSiS->ForceCRT1Type = pSiSEnt->ForceCRT1Type; 4328 pSiS->ForceCRT2Type = pSiSEnt->ForceCRT2Type; 4329 pSiS->CRT1TypeForced = pSiSEnt->CRT1TypeForced; 4330 pSiS->UsePanelScaler = pSiSEnt->UsePanelScaler; 4331 pSiS->CenterLCD = pSiSEnt->CenterLCD; 4332 pSiS->DSTN = pSiSEnt->DSTN; 4333 pSiS->FSTN = pSiSEnt->FSTN; 4334 pSiS->OptTVStand = pSiSEnt->OptTVStand; 4335 pSiS->NonDefaultPAL = pSiSEnt->NonDefaultPAL; 4336 pSiS->NonDefaultNTSC = pSiSEnt->NonDefaultNTSC; 4337 pSiS->chtvtype = pSiSEnt->chtvtype; 4338 pSiS->ForceTVType = pSiSEnt->ForceTVType; 4339 pSiS->ForceYPbPrType = pSiSEnt->ForceYPbPrType; 4340 pSiS->ForceYPbPrAR = pSiSEnt->ForceYPbPrAR; 4341 pSiS->OptTVOver = pSiSEnt->OptTVOver; 4342 pSiS->OptTVSOver = pSiSEnt->OptTVSOver; 4343 pSiS->chtvlumabandwidthcvbs = pSiSEnt->chtvlumabandwidthcvbs; 4344 pSiS->chtvlumabandwidthsvideo = pSiSEnt->chtvlumabandwidthsvideo; 4345 pSiS->chtvlumaflickerfilter = pSiSEnt->chtvlumaflickerfilter; 4346 pSiS->chtvchromabandwidth = pSiSEnt->chtvchromabandwidth; 4347 pSiS->chtvchromaflickerfilter = pSiSEnt->chtvchromaflickerfilter; 4348 pSiS->chtvcvbscolor = pSiSEnt->chtvcvbscolor; 4349 pSiS->chtvtextenhance = pSiSEnt->chtvtextenhance; 4350 pSiS->chtvcontrast = pSiSEnt->chtvcontrast; 4351 pSiS->sistvedgeenhance = pSiSEnt->sistvedgeenhance; 4352 pSiS->sistvantiflicker = pSiSEnt->sistvantiflicker; 4353 pSiS->sistvsaturation = pSiSEnt->sistvsaturation; 4354 pSiS->sistvcfilter = pSiSEnt->sistvcfilter; 4355 pSiS->sistvyfilter = pSiSEnt->sistvyfilter; 4356 pSiS->sistvcolcalibc = pSiSEnt->sistvcolcalibc; 4357 pSiS->sistvcolcalibf = pSiSEnt->sistvcolcalibf; 4358 pSiS->tvxpos = pSiSEnt->tvxpos; 4359 pSiS->tvypos = pSiSEnt->tvypos; 4360 pSiS->tvxscale = pSiSEnt->tvxscale; 4361 pSiS->tvyscale = pSiSEnt->tvyscale; 4362 pSiS->SenseYPbPr = pSiSEnt->SenseYPbPr; 4363 if(!pSiS->CRT1gammaGiven) { 4364 if(pSiSEnt->CRT1gammaGiven) 4365 pSiS->CRT1gamma = pSiSEnt->CRT1gamma; 4366 } 4367 pSiS->CRT2gamma = pSiSEnt->CRT2gamma; 4368 if(!pSiS->XvGammaGiven) { 4369 if(pSiSEnt->XvGammaGiven) { 4370 pSiS->XvGamma = pSiSEnt->XvGamma; 4371 pSiS->XvGammaRed = pSiS->XvGammaRedDef = pSiSEnt->XvGammaRed; 4372 pSiS->XvGammaGreen = pSiS->XvGammaGreenDef = pSiSEnt->XvGammaGreen; 4373 pSiS->XvGammaBlue = pSiS->XvGammaBlueDef = pSiSEnt->XvGammaBlue; 4374 } 4375 } 4376 if(!pSiS->crt1satgaingiven) { 4377 if(pSiSEnt->crt1satgaingiven) 4378 pSiS->siscrt1satgain = pSiSEnt->siscrt1satgain; 4379 } 4380 pSiS->XvOnCRT2 = pSiSEnt->XvOnCRT2; 4381 pSiS->enablesisctrl = pSiSEnt->enablesisctrl; 4382 pSiS->XvUseMemcpy = pSiSEnt->XvUseMemcpy; 4383 pSiS->BenchMemCpy = pSiSEnt->BenchMemCpy; 4384 /* Copy gamma brightness to Ent (sic!) for Xinerama */ 4385 pSiSEnt->GammaBriR = pSiS->GammaBriR; 4386 pSiSEnt->GammaBriG = pSiS->GammaBriG; 4387 pSiSEnt->GammaBriB = pSiS->GammaBriB; 4388 pSiSEnt->NewGammaBriR = pSiS->NewGammaBriR; 4389 pSiSEnt->NewGammaBriG = pSiS->NewGammaBriG; 4390 pSiSEnt->NewGammaBriB = pSiS->NewGammaBriB; 4391 pSiSEnt->NewGammaConR = pSiS->NewGammaConR; 4392 pSiSEnt->NewGammaConG = pSiS->NewGammaConG; 4393 pSiSEnt->NewGammaConB = pSiS->NewGammaConB; 4394#ifdef SIS_CP 4395 SIS_CP_DRIVER_COPYOPTIONS 4396#endif 4397 } 4398 } 4399#endif 4400 4401 /* Handle UseROMData, NoOEM and UsePanelScaler options */ 4402 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 4403 from = X_PROBED; 4404 if(pSiS->OptROMUsage == 0) { 4405 pSiS->SiS_Pr->UseROM = FALSE; 4406 from = X_CONFIG; 4407 xf86DrvMsg(pScrn->scrnIndex, from, "Video ROM data usage is disabled\n"); 4408 } 4409 4410 if(!pSiS->OptUseOEM) { 4411 xf86DrvMsg(pScrn->scrnIndex, from, "Internal OEM LCD/TV/VGA2 data usage is disabled\n"); 4412 } 4413 4414 pSiS->SiS_Pr->UsePanelScaler = pSiS->UsePanelScaler; 4415 pSiS->SiS_Pr->CenterScreen = pSiS->CenterLCD; 4416 } 4417 4418 /* Do some HW configuration detection (memory amount & type, clock, etc) */ 4419 SiSSetup(pScrn); 4420 4421 /* Get framebuffer address */ 4422 if(pSiS->pEnt->device->MemBase != 0) { 4423 /* 4424 * XXX Should check that the config file value matches one of the 4425 * PCI base address values. 4426 */ 4427 pSiS->FbAddress = pSiS->pEnt->device->MemBase; 4428 from = X_CONFIG; 4429 } else { 4430 pSiS->FbAddress = PCI_REGION_BASE(pSiS->PciInfo, 0, REGION_MEM) & 0xFFFFFFF0; 4431 from = X_PROBED; 4432 } 4433 4434#ifdef SISDUALHEAD 4435 if(pSiS->DualHeadMode) 4436 xf86DrvMsg(pScrn->scrnIndex, from, "Global linear framebuffer at 0x%lX\n", 4437 (ULong)pSiS->FbAddress); 4438 else 4439#endif 4440 xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", 4441 (ULong)pSiS->FbAddress); 4442 4443 pSiS->realFbAddress = pSiS->FbAddress; 4444 4445 /* Get MMIO address */ 4446 if(pSiS->pEnt->device->IOBase != 0) { 4447 /* 4448 * XXX Should check that the config file value matches one of the 4449 * PCI base address values. 4450 */ 4451 pSiS->IOAddress = pSiS->pEnt->device->IOBase; 4452 from = X_CONFIG; 4453 } else { 4454 pSiS->IOAddress = PCI_REGION_BASE(pSiS->PciInfo, 1, REGION_MEM) & 0xFFFFFFF0; 4455 from = X_PROBED; 4456 } 4457 xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX (size %ldK)\n", 4458 (ULong)pSiS->IOAddress, pSiS->mmioSize); 4459 4460#ifndef XSERVER_LIBPCIACCESS 4461 /* Register the PCI-assigned resources */ 4462 if(xf86RegisterResources(pSiS->pEnt->index, NULL, ResExclusive)) { 4463 SISErrorLog(pScrn, "PCI resource conflicts detected\n"); 4464#ifdef SISDUALHEAD 4465 if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; 4466#endif 4467 sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); 4468 if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); 4469 SISFreeRec(pScrn); 4470 return FALSE; 4471 } 4472#endif 4473 4474 from = X_PROBED; 4475 if(pSiS->pEnt->device->videoRam != 0) { 4476 if(pSiS->Chipset == PCI_CHIP_SIS6326) { 4477 pScrn->videoRam = pSiS->pEnt->device->videoRam; 4478 from = X_CONFIG; 4479 } else { 4480 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4481 "Option \"VideoRAM\" ignored\n"); 4482 } 4483 } 4484 4485 pSiS->RealVideoRam = pScrn->videoRam; 4486 4487 if((pSiS->Chipset == PCI_CHIP_SIS6326) && 4488 (pScrn->videoRam > 4096) && 4489 (from != X_CONFIG)) { 4490 pScrn->videoRam = 4096; 4491 xf86DrvMsg(pScrn->scrnIndex, from, 4492 "SiS6326: Detected %d KB VideoRAM, limiting to %d KB\n", 4493 pSiS->RealVideoRam, pScrn->videoRam); 4494 } else { 4495 xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d KB\n", pScrn->videoRam); 4496 } 4497 4498 if((pSiS->Chipset == PCI_CHIP_SIS6326) && 4499 (pScrn->videoRam > 4096)) { 4500 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4501 "SiS6326 engines do not support more than 4096KB RAM, therefore\n"); 4502 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4503 "TurboQueue, HWCursor, 2D acceleration and XVideo are disabled.\n"); 4504 pSiS->TurboQueue = FALSE; 4505 pSiS->HWCursor = FALSE; 4506 pSiS->NoXvideo = TRUE; 4507 pSiS->NoAccel = TRUE; 4508 } 4509 4510 pSiS->FbMapSize = pSiS->availMem = pScrn->videoRam * 1024; 4511 4512 /* Calculate real availMem according to Accel/TurboQueue and 4513 * HWCursur setting. Also, initialize some variables used 4514 * in other modules. 4515 */ 4516 pSiS->cursorOffset = 0; 4517 pSiS->CurARGBDest = NULL; 4518 pSiS->CurMonoSrc = NULL; 4519 pSiS->CurFGCol = pSiS->CurBGCol = 0; 4520 pSiS->FbBaseOffset = 0; 4521 4522 switch(pSiS->VGAEngine) { 4523 4524 case SIS_300_VGA: 4525 pSiS->TurboQueueLen = 512; 4526 if(pSiS->TurboQueue) { 4527 pSiS->availMem -= (pSiS->TurboQueueLen*1024); 4528 pSiS->cursorOffset = 512; 4529 } 4530 if(pSiS->HWCursor) { 4531 pSiS->availMem -= pSiS->CursorSize; 4532 if(pSiS->OptUseColorCursor) pSiS->availMem -= pSiS->CursorSize; 4533 } 4534 pSiS->CmdQueLenMask = 0xFFFF; 4535 pSiS->CmdQueLenFix = 0; 4536 pSiS->cursorBufferNum = 0; 4537#ifdef SISDUALHEAD 4538 if(pSiSEnt) pSiSEnt->cursorBufferNum = 0; 4539#endif 4540 break; 4541 4542 case SIS_315_VGA: 4543#ifdef SISVRAMQ /* VRAM queue */ 4544 pSiS->cmdQueueSizeMask = pSiS->cmdQueueSize - 1; /* VRAM Command Queue is variable (in therory) */ 4545 pSiS->cmdQueueOffset = (pScrn->videoRam * 1024) - pSiS->cmdQueueSize; 4546 pSiS->cmdQueueLen = 0; 4547 pSiS->cmdQueueSize_div2 = pSiS->cmdQueueSize / 2; 4548 pSiS->cmdQueueSize_div4 = pSiS->cmdQueueSize / 4; 4549 pSiS->cmdQueueSize_4_3 = (pSiS->cmdQueueSize / 4) * 3; 4550 pSiS->availMem -= pSiS->cmdQueueSize; 4551 pSiS->cursorOffset = (pSiS->cmdQueueSize / 1024); 4552 4553 /* Set up shared pointer to current offset */ 4554#ifdef SISDUALHEAD 4555 if(pSiS->DualHeadMode) 4556 pSiS->cmdQ_SharedWritePort = &(pSiSEnt->cmdQ_SharedWritePort_2D); 4557 else 4558#endif 4559 pSiS->cmdQ_SharedWritePort = &(pSiS->cmdQ_SharedWritePort_2D); 4560 4561 4562#else /* MMIO */ 4563 if(pSiS->TurboQueue) { 4564 pSiS->availMem -= (512*1024); /* MMIO Command Queue is 512k (variable in theory) */ 4565 pSiS->cursorOffset = 512; 4566 } 4567#endif 4568 if(pSiS->HWCursor) { 4569 pSiS->availMem -= (pSiS->CursorSize * 2); 4570 if(pSiS->OptUseColorCursor) pSiS->availMem -= (pSiS->CursorSize * 2); 4571 } 4572 pSiS->cursorBufferNum = 0; 4573#ifdef SISDUALHEAD 4574 if(pSiSEnt) pSiSEnt->cursorBufferNum = 0; 4575#endif 4576 4577 if((pSiS->SiS76xLFBSize) && (pSiS->SiS76xUMASize)) { 4578 pSiS->availMem -= pSiS->SiS76xUMASize; 4579 pSiS->FbBaseOffset = pSiS->SiS76xUMASize; 4580 } 4581 4582 break; 4583 4584 default: 4585 /* cursorOffset not used in cursor functions for 530 and 4586 * older chips, because the cursor is *above* the TQ. 4587 * On 5597 and older revisions of the 6326, the TQ is 4588 * max 32K, on newer 6326 revisions and the 530 either 30 4589 * (or 32?) or 62K (or 64?). However, to make sure, we 4590 * use only 30K (or 32?), but reduce the available memory 4591 * by 64, and locate the TQ at the beginning of this last 4592 * 64K block. (We do this that way even when using the 4593 * HWCursor, because the cursor only takes 2K and the 4594 * queue does not seem to last that far anyway.) 4595 * The TQ must be located at 32KB boundaries. 4596 */ 4597 if(pSiS->RealVideoRam < 3072) { 4598 if(pSiS->TurboQueue) { 4599 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4600 "Not enough video RAM for TurboQueue. TurboQueue disabled\n"); 4601 pSiS->TurboQueue = FALSE; 4602 } 4603 } 4604 pSiS->CmdQueMaxLen = 32; 4605 if(pSiS->TurboQueue) { 4606 pSiS->availMem -= (64*1024); 4607 pSiS->CmdQueMaxLen = 900; /* To make sure; should be 992 */ 4608 } else if(pSiS->HWCursor) { 4609 pSiS->availMem -= pSiS->CursorSize; 4610 } 4611 if(pSiS->Chipset == PCI_CHIP_SIS530) { 4612 /* Check if Flat Panel is enabled */ 4613 inSISIDXREG(SISSR, 0x0e, tempreg); 4614 if(!(tempreg & 0x04)) pSiS->availMem -= pSiS->CursorSize; 4615 4616 /* Set up mask for MMIO register */ 4617 pSiS->CmdQueLenMask = (pSiS->TurboQueue) ? 0x1FFF : 0x00FF; 4618 } else { 4619 /* TQ is never used on 6326/5597, because the accelerator 4620 * always Syncs. So this is just cosmentic work. (And I 4621 * am not even sure that 0x7fff is correct. MMIO 0x83a8 4622 * holds 0xec0 if (30k) TQ is enabled, 0x20 if TQ disabled. 4623 * The datasheet has no real explanation on the queue length 4624 * if the TQ is enabled. Not syncing and waiting for a 4625 * suitable queue length instead does not work. 4626 */ 4627 pSiS->CmdQueLenMask = (pSiS->TurboQueue) ? 0x7FFF : 0x003F; 4628 } 4629 4630 /* This is to be subtracted from MMIO queue length register contents 4631 * for getting the real Queue length. 4632 */ 4633 pSiS->CmdQueLenFix = (pSiS->TurboQueue) ? 32 : 0; 4634 } 4635 4636 4637#ifdef SISDUALHEAD 4638 /* In dual head mode, we share availMem equally - so align it 4639 * to 8KB; this way, the address of the FB of the second 4640 * head is aligned to 4KB for mapping. 4641 */ 4642 if(pSiS->DualHeadMode) pSiS->availMem &= 0xFFFFE000; 4643#endif 4644 4645 /* Check MaxXFBMem setting */ 4646#ifdef SISDUALHEAD 4647 if(pSiS->DualHeadMode) { 4648 /* 1. Since DRI is not supported in dual head mode, we 4649 * don't need the MaxXFBMem setting - ignore it. 4650 */ 4651 if(pSiS->maxxfbmem) { 4652 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4653 "MaxXFBMem ignored in Dual Head mode\n"); 4654 } 4655 pSiS->maxxfbmem = pSiS->availMem; 4656 } else 4657#endif 4658 if((pSiS->sisfbHeapStart) || (pSiS->sisfbHaveNewHeapDef)) { 4659 4660 /* 4661 * 2. We have memory layout info from sisfb - ignore MaxXFBMem 4662 */ 4663 if(pSiS->maxxfbmem) { 4664 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4665 "Got memory layout info from sisfb, ignoring MaxXFBMem option\n"); 4666 } 4667 if((pSiS->FbBaseOffset) && (!pSiS->sisfbHaveNewHeapDef)) { 4668 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4669 "Incompatible sisfb version detected, DRI disabled\n"); 4670 pSiS->loadDRI = FALSE; 4671 pSiS->maxxfbmem = pSiS->availMem; 4672 } else { 4673 if(pSiS->FbBaseOffset) { 4674 /* Revert our changes to FbBaseOffset and availMem; use sisfb's info */ 4675 pSiS->availMem += pSiS->FbBaseOffset; 4676 pSiS->FbBaseOffset = 0; 4677 } 4678 if(pSiS->sisfbVideoOffset) { 4679 /* a. DRI heap BELOW framebuffer */ 4680 pSiS->FbBaseOffset = pSiS->sisfbVideoOffset; 4681 pSiS->availMem -= pSiS->FbBaseOffset; 4682 pSiS->maxxfbmem = pSiS->availMem; 4683 } else { 4684 /* b. DRI heap ABOVE framebuffer (traditional layout) */ 4685 if(pSiS->availMem < (pSiS->sisfbHeapStart * 1024)) { 4686 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4687 "Internal error - sisfb memory layout corrupt\n"); 4688 pSiS->loadDRI = FALSE; 4689 pSiS->maxxfbmem = pSiS->availMem; 4690 } else { 4691 pSiS->maxxfbmem = pSiS->sisfbHeapStart * 1024; 4692 } 4693 } 4694 } 4695 4696 } else if(pSiS->maxxfbmem) { 4697 4698 /* 4699 * 3. No sisfb, but user gave "MaxXFBMem" 4700 */ 4701 if(pSiS->FbBaseOffset) { 4702 /* a. DRI heap BELOW framebuffer */ 4703 if(pSiS->maxxfbmem > (pSiS->availMem + pSiS->FbBaseOffset - pSiS->SiS76xUMASize)) { 4704 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4705 "Invalid MaxXFBMem setting\n"); 4706 pSiS->maxxfbmem = pSiS->availMem; 4707 } else { 4708 /* Revert our changes */ 4709 pSiS->availMem += pSiS->FbBaseOffset; 4710 /* Use user's MaxXFBMem setting */ 4711 pSiS->FbBaseOffset = pSiS->availMem - pSiS->maxxfbmem; 4712 pSiS->availMem -= pSiS->FbBaseOffset; 4713 } 4714 } else { 4715 /* b. DRI heap ABOVE framebuffer (traditional layout) */ 4716 if(pSiS->maxxfbmem > pSiS->availMem) { 4717 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4718 "Invalid MaxXFBMem setting.\n"); 4719 pSiS->maxxfbmem = pSiS->availMem; 4720 } 4721 } 4722 4723 } else { 4724 4725 /* 4726 * 4. No MaxXFBMem, no sisfb: Use all memory 4727 */ 4728 pSiS->maxxfbmem = pSiS->availMem; 4729 4730 /* ... except on chipsets, for which DRI is 4731 * supported: If DRI is enabled, we now limit 4732 * ourselves to a reasonable default: 4733 */ 4734 4735 if(pSiS->loadDRI) { 4736 if(pSiS->FbBaseOffset) { 4737 /* a. DRI heap BELOW framebuffer */ 4738 /* See how much UMA and LFB memory we have, 4739 * and calculate a reasonable default. We 4740 * use more vram for ourselves because these 4741 * chips are eg. capable of larger Xv 4742 * overlays, etc. 4743 */ 4744 unsigned long total = (pSiS->SiS76xLFBSize + pSiS->SiS76xUMASize) / 1024; 4745 unsigned long mymax; 4746 if(total <= 16384) /* <= 16MB: Use 8MB for X */ 4747 mymax = 8192 * 1024; 4748 else if(total <= 32768) /* <= 32MB: Use 16MB for X */ 4749 mymax = 16384 * 1024; 4750 else /* Otherwise: Use 20MB for X */ 4751 mymax = 20 * 1024 * 1024; 4752 /* availMem is right now adjusted to not use the UMA 4753 * area. Make sure that our default doesn't reach 4754 * into the UMA area either. 4755 */ 4756 if(pSiS->availMem > mymax) { 4757 /* Write our default to maxxfbmem */ 4758 pSiS->maxxfbmem = mymax; 4759 /* Revert our changes to availMem */ 4760 pSiS->availMem += pSiS->FbBaseOffset; 4761 /* Use our default setting */ 4762 pSiS->FbBaseOffset = pSiS->availMem - pSiS->maxxfbmem; 4763 pSiS->availMem -= pSiS->FbBaseOffset; 4764 } 4765 } else { 4766 /* b. DRI heap ABOVE framebuffer (traditional layout) */ 4767 /* See how much video memory we have, and calculate 4768 * a reasonable default. 4769 * Since DRI is pointless with less than 4MB of total 4770 * video RAM, we disable it in that case. 4771 */ 4772 if(pScrn->videoRam <= 4096) 4773 pSiS->loadDRI = FALSE; 4774 else if(pScrn->videoRam <= 8192) /* <= 8MB: Use 4MB for X */ 4775 pSiS->maxxfbmem = 4096 * 1024; 4776 else if(pScrn->videoRam <= 16384) /* <= 16MB: Use 8MB for X */ 4777 pSiS->maxxfbmem = 8192 * 1024; 4778#ifdef SISMERGED /* Otherwise: --- */ 4779 else if(pSiS->MergedFB) { 4780 if(pScrn->videoRam <= 65536) 4781 pSiS->maxxfbmem = 16384 * 1024; /* If MergedFB and <=64MB, use 16MB for X */ 4782 else 4783 pSiS->maxxfbmem = 20 * 1024 * 1024; /* If MergedFB and > 64MB, use 20MB for X */ 4784 } 4785#endif 4786 else if(pSiS->VGAEngine == SIS_315_VGA) { 4787 if(pScrn->videoRam <= 65536) 4788 pSiS->maxxfbmem = 16384 * 1024; /* On >=315 series and <=64MB, use 16MB */ 4789 else 4790 pSiS->maxxfbmem = 20 * 1024 * 1024; /* On >=315 series and > 64MB, use 20MB */ 4791 } else 4792 pSiS->maxxfbmem = 12288 * 1024; /* On <315 series, use 12MB */ 4793 4794 /* A final check */ 4795 if(pSiS->maxxfbmem > pSiS->availMem) { 4796 pSiS->maxxfbmem = pSiS->availMem; 4797 pSiS->loadDRI = FALSE; 4798 } 4799 } 4800 4801 } 4802 } 4803 4804 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %dK of framebuffer memory at offset %dK\n", 4805 pSiS->maxxfbmem / 1024, pSiS->FbBaseOffset / 1024); 4806 4807 /* Find out about sub-classes of some chipsets and check 4808 * if the chipset supports two video overlays 4809 */ 4810 if(pSiS->VGAEngine == SIS_300_VGA || 4811 pSiS->VGAEngine == SIS_315_VGA || 4812 pSiS->Chipset == PCI_CHIP_SIS530 || 4813 pSiS->Chipset == PCI_CHIP_SIS6326 || 4814 pSiS->Chipset == PCI_CHIP_SIS5597) { 4815 pSiS->hasTwoOverlays = FALSE; 4816 switch(pSiS->Chipset) { 4817 case PCI_CHIP_SIS300: 4818 case PCI_CHIP_SIS540: /* ? (If not, need to add the SwitchCRT Xv attribute!) */ 4819 case PCI_CHIP_SIS630: 4820 case PCI_CHIP_SIS550: 4821 pSiS->hasTwoOverlays = TRUE; 4822 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4823 break; 4824 case PCI_CHIP_SIS315PRO: 4825 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4826 break; 4827 case PCI_CHIP_SIS330: 4828 pSiS->ChipFlags |= (SiSCF_CRT2HWCKaputt | SiSCF_LARGEOVERLAY); 4829 break; 4830 case PCI_CHIP_SIS340: 4831 case PCI_CHIP_XGIXG40: /* Verified: only 1 overlay */ 4832 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4833 break; 4834 case PCI_CHIP_SIS650: 4835 { 4836 UChar tempreg1, tempreg2; 4837 static const char *id650str[] = { 4838 "650", "650", "650", "650", 4839 "650 A0 AA", "650 A2 CA", "650", "650", 4840 "M650 A0", "M650 A1 AA","651 A0 AA", "651 A1 AA", 4841 "M650", "65?", "651", "65?" 4842 }; 4843 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4844 if(pSiS->ChipType == SIS_650) { 4845 inSISIDXREG(SISCR, 0x5f, CR5F); 4846 CR5F &= 0xf0; 4847 andSISIDXREG(SISCR, 0x5c, 0x07); 4848 inSISIDXREG(SISCR, 0x5c, tempreg1); 4849 tempreg1 &= 0xf8; 4850 orSISIDXREG(SISCR, 0x5c, 0xf8); 4851 inSISIDXREG(SISCR, 0x5c, tempreg2); 4852 tempreg2 &= 0xf8; 4853 if((!tempreg1) || (tempreg2)) { 4854 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4855 "SiS650 revision ID %x (%s)\n", CR5F, id650str[CR5F >> 4]); 4856 if(CR5F & 0x80) { 4857 pSiS->hasTwoOverlays = TRUE; /* M650 or 651 */ 4858 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4859 } 4860 switch(CR5F) { 4861 case 0xa0: 4862 case 0xb0: 4863 case 0xe0: 4864 pSiS->ChipFlags |= SiSCF_Is651; 4865 break; 4866 case 0x80: 4867 case 0x90: 4868 case 0xc0: 4869 pSiS->ChipFlags |= SiSCF_IsM650; 4870 break; 4871 } 4872 } else { 4873 pSiS->hasTwoOverlays = TRUE; 4874 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4875 switch(CR5F) { 4876 case 0x90: 4877 inSISIDXREG(SISCR, 0x5c, tempreg1); 4878 tempreg1 &= 0xf8; 4879 switch(tempreg1) { 4880 case 0x00: 4881 pSiS->ChipFlags |= SiSCF_IsM652; 4882 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4883 "SiSM652 revision ID %x\n", CR5F); 4884 break; 4885 case 0x40: 4886 pSiS->ChipFlags |= SiSCF_IsM653; 4887 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4888 "SiSM653 revision ID %x\n", CR5F); 4889 break; 4890 default: 4891 pSiS->ChipFlags |= SiSCF_IsM650; 4892 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4893 "SiSM650 revision ID %x\n", CR5F); 4894 break; 4895 } 4896 break; 4897 case 0xb0: 4898 pSiS->ChipFlags |= SiSCF_Is652; 4899 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4900 "SiS652 revision ID %x\n", CR5F); 4901 break; 4902 default: 4903 pSiS->ChipFlags |= SiSCF_IsM650; 4904 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4905 "SiSM650 revision ID %x\n", CR5F); 4906 break; 4907 } 4908 } 4909 } 4910 break; 4911 } 4912 case PCI_CHIP_SIS660: 4913 { 4914 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4915 pSiS->hasTwoOverlays = TRUE; 4916 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4917 /* 760/761: - UMA only: one/two overlays - dotclock dependent 4918 - UMA+LFB: two overlays if video data in LFB 4919 - LFB only: two overlays 4920 If UMA only: Must switch between one/two overlays on the fly (done 4921 in PostSetMode()) 4922 If LFB+UMA: We use LFB memory only and leave UMA to an eventually 4923 written DRI driver. 4924 */ 4925 break; 4926 } 4927 } 4928 4929 if(!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY)) { 4930 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4931 "Hardware supports %s video overlay%s\n", 4932 pSiS->hasTwoOverlays ? "two" : "one", 4933 pSiS->hasTwoOverlays ? "s" : ""); 4934 } 4935 4936 if(pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORT760OO) { 4937 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4938 "\n\tDear SiS76x user, your machine is using a shared memory framebuffer.\n" 4939 "\tDue to hardware limitations of the SiS chip in combination with the\n" 4940 "\tAMD CPU, video overlay support is very limited on this machine. If you\n" 4941 "\texperience flashing lines in the video and/or the graphics display\n" 4942 "\tduring video playback, reduce the color depth and/or the resolution\n" 4943 "\tand/or the refresh rate. Alternatively, use the video blitter.\n"); 4944 } 4945 4946 } 4947 4948 /* Backup VB connection and CRT1 on/off register */ 4949 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 4950 inSISIDXREG(SISSR, 0x1f, pSiS->oldSR1F); 4951 inSISIDXREG(SISCR, 0x17, pSiS->oldCR17); 4952 inSISIDXREG(SISCR, 0x32, pSiS->oldCR32); 4953 inSISIDXREG(SISCR, 0x36, pSiS->oldCR36); 4954 inSISIDXREG(SISCR, 0x37, pSiS->oldCR37); 4955 if(pSiS->VGAEngine == SIS_315_VGA) { 4956 inSISIDXREG(SISCR, pSiS->myCR63, pSiS->oldCR63); 4957 } 4958 4959 pSiS->postVBCR32 = pSiS->oldCR32; 4960 } 4961 4962 /* There are some machines out there which require a special 4963 * setup of the GPIO registers in order to make the Chrontel 4964 * work. Try to find out if we're running on such a machine. 4965 * Furthermore, there is some highly customized hardware, 4966 * which requires some non-standard LVDS timing. Since the 4967 * vendors don't seem to care about PCI subsystem ID's we 4968 * need to find out using the BIOS version and date strings. 4969 */ 4970 pSiS->SiS_Pr->SiS_ChSW = FALSE; 4971 if(pSiS->Chipset == PCI_CHIP_SIS630) { 4972 int i = 0; 4973 do { 4974 if(mychswtable[i].subsysVendor == PCI_SUB_VENDOR_ID(pSiS->PciInfo) && 4975 mychswtable[i].subsysCard == PCI_SUB_DEVICE_ID(pSiS->PciInfo)) { 4976 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4977 "PCI subsystem ID found in list for Chrontel/GPIO setup:\n"); 4978 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4979 "\tVendor/Card: %s %s (ID %04x)\n", 4980 mychswtable[i].vendorName, 4981 mychswtable[i].cardName, 4982 PCI_SUB_DEVICE_ID(pSiS->PciInfo)); 4983 pSiS->SiS_Pr->SiS_ChSW = TRUE; 4984 break; 4985 } 4986 i++; 4987 } while(mychswtable[i].subsysVendor != 0); 4988 } 4989 4990 if(pSiS->SiS_Pr->SiS_CustomT == CUT_NONE) { 4991 int i = 0, j; 4992 UShort bversptr = 0; 4993 Bool footprint; 4994 CARD32 chksum = 0; 4995 4996 if(pSiS->SiS_Pr->UseROM) { 4997 bversptr = pSiS->BIOS[0x16] | (pSiS->BIOS[0x17] << 8); 4998 for(i=0; i<32768; i++) chksum += pSiS->BIOS[i]; 4999 } 5000 5001 i = 0; 5002 do { 5003 if( (SiS_customttable[i].chipID == pSiS->ChipType) && 5004 ((!strlen(SiS_customttable[i].biosversion)) || 5005 (pSiS->SiS_Pr->UseROM && 5006 (!strncmp(SiS_customttable[i].biosversion, (char *)&pSiS->BIOS[bversptr], 5007 strlen(SiS_customttable[i].biosversion))))) && 5008 ((!strlen(SiS_customttable[i].biosdate)) || 5009 (pSiS->SiS_Pr->UseROM && 5010 (!strncmp(SiS_customttable[i].biosdate, (char *)&pSiS->BIOS[0x2c], 5011 strlen(SiS_customttable[i].biosdate))))) && 5012 ((!SiS_customttable[i].bioschksum) || 5013 (pSiS->SiS_Pr->UseROM && 5014 (SiS_customttable[i].bioschksum == chksum))) && 5015 (SiS_customttable[i].pcisubsysvendor == PCI_SUB_VENDOR_ID(pSiS->PciInfo)) && 5016 (SiS_customttable[i].pcisubsyscard == PCI_SUB_DEVICE_ID(pSiS->PciInfo)) ) { 5017 footprint = TRUE; 5018 for(j=0; j<5; j++) { 5019 if(SiS_customttable[i].biosFootprintAddr[j]) { 5020 if(pSiS->SiS_Pr->UseROM) { 5021 if(pSiS->BIOS[SiS_customttable[i].biosFootprintAddr[j]] != 5022 SiS_customttable[i].biosFootprintData[j]) 5023 footprint = FALSE; 5024 } else footprint = FALSE; 5025 } 5026 } 5027 if(footprint) { 5028 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5029 "Identified %s %s, special timing applies\n", 5030 SiS_customttable[i].vendorName, SiS_customttable[i].cardName); 5031 pSiS->SiS_Pr->SiS_CustomT = SiS_customttable[i].SpecialID; 5032 break; 5033 } 5034 } 5035 i++; 5036 } while(SiS_customttable[i].chipID); 5037 } 5038 5039 /* Handle ForceCRT1 option */ 5040 if(pSiS->forceCRT1 != -1) { 5041 if(pSiS->forceCRT1) pSiS->CRT1off = 0; 5042 else pSiS->CRT1off = 1; 5043 } else pSiS->CRT1off = -1; 5044 5045 /* Detect video bridge and sense TV/VGA2 */ 5046 SISVGAPreInit(pScrn); 5047 5048 /* Detect CRT1 (via DDC1 and DDC2, hence via VGA port; regardless of LCDA) */ 5049 SISCRT1PreInit(pScrn); 5050 5051 /* Detect LCD (connected via CRT2, regardless of LCDA) and LCD resolution */ 5052 SISLCDPreInit(pScrn, FALSE); 5053 5054 /* LCDA only supported under these conditions: */ 5055 if(pSiS->ForceCRT1Type == CRT1_LCDA) { 5056 if(!SISDetermineLCDACap(pScrn)) { 5057 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5058 "Chipset/Video bridge does not support LCD-via-CRT1\n"); 5059 pSiS->ForceCRT1Type = CRT1_VGA; 5060 } else if(!(pSiS->VBFlags & CRT2_LCD)) { 5061 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5062 "No digital LCD panel found, LCD-via-CRT1 disabled\n"); 5063 pSiS->ForceCRT1Type = CRT1_VGA; 5064 } 5065 } 5066 5067 /* Setup SD flags */ 5068 pSiS->SiS_SD_Flags |= SiS_SD_ADDLSUPFLAG; 5069 5070 pSiS->SiS_SD2_Flags |= SiS_SD2_MERGEDUCLOCK; 5071 pSiS->SiS_SD2_Flags |= SiS_SD2_USEVBFLAGS2; 5072 pSiS->SiS_SD2_Flags |= SiS_SD2_VBINVB2ONLY; 5073 pSiS->SiS_SD2_Flags |= SiS_SD2_HAVESD34; 5074 pSiS->SiS_SD2_Flags |= SiS_SD2_NEWGAMMABRICON; 5075 5076 pSiS->SiS_SD3_Flags |= SiS_SD3_MFBALLOWOFFCL; 5077 5078 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 5079 pSiS->SiS_SD2_Flags |= SiS_SD2_VIDEOBRIDGE; 5080 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 5081 pSiS->SiS_SD2_Flags |= ( SiS_SD2_SISBRIDGE | 5082 SiS_SD2_SUPPORTGAMMA2 ); 5083 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) { 5084 pSiS->SiS_SD2_Flags |= ( SiS_SD2_LCDLVDS | 5085 SiS_SD2_SUPPORTLCD ); 5086 } else if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 5087 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 5088 pSiS->SiS_SD2_Flags |= ( SiS_SD2_LCDTMDS | 5089 SiS_SD2_SUPPORTLCD ); 5090 } else if(pSiS->VBFlags & CRT2_LCD) { 5091 pSiS->SiS_SD2_Flags |= ( SiS_SD2_THIRDPARTYLVDS | 5092 SiS_SD2_SUPPORTLCD ); 5093 } 5094 } 5095 } else if(pSiS->VBFlags2 & VB2_LVDS) { 5096 pSiS->SiS_SD2_Flags |= ( SiS_SD2_THIRDPARTYLVDS | 5097 SiS_SD2_SUPPORTLCD ); 5098 } 5099 5100 if(pSiS->VBFlags2 & (VB2_SISTVBRIDGE | VB2_CHRONTEL)) { 5101 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTTV; 5102 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 5103 pSiS->SiS_SD2_Flags |= ( SiS_SD2_SUPPORTTVTYPE | 5104 SiS_SD2_SUPPORTTVSIZE ); 5105 if(!(pSiS->VBFlags2 & VB2_301)) { 5106 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPTVSAT; 5107 } else { 5108 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPTVEDGE; 5109 } 5110 } 5111 } 5112 } 5113 5114#ifdef ENABLE_YPBPR 5115 if((pSiS->VGAEngine == SIS_315_VGA) && 5116 (pSiS->VBFlags2 & VB2_SISYPBPRBRIDGE)) { 5117 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTYPBPR; 5118 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORT625I; 5119 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORT625P; 5120 if(pSiS->VBFlags2 & VB2_SISYPBPRARBRIDGE) { 5121 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTYPBPRAR; 5122 } 5123 } 5124 if(pSiS->VBFlags2 & VB2_SISHIVISIONBRIDGE) { 5125 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTHIVISION; 5126 } 5127#endif 5128 5129 if((pSiS->VGAEngine != SIS_300_VGA) || (!(pSiS->VBFlags2 & VB2_TRUMPION))) { 5130 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTSCALE; 5131 if((pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && 5132 (!(pSiS->VBFlags2 & VB2_30xBDH))) { 5133 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTCENTER; 5134 } 5135 } 5136 5137#ifdef SISDUALHEAD 5138 if(!pSiS->DualHeadMode) { 5139 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTREDETECT; 5140 } 5141#endif 5142 5143#ifndef SISCHECKOSSSE 5144 pSiS->SiS_SD2_Flags |= SiS_SD2_NEEDUSESSE; 5145#endif 5146 5147#ifdef TWDEBUG /* FOR TESTING */ 5148 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTYPBPRAR; 5149 xf86DrvMsg(0, X_INFO, "TEST: Support Aspect Ratio\n"); 5150#endif 5151 5152 /* Detect CRT2-TV and PAL/NTSC mode */ 5153 SISTVPreInit(pScrn, FALSE); 5154 5155 /* Detect CRT2-VGA */ 5156 SISCRT2PreInit(pScrn, FALSE); 5157 5158 /* Backup detected CRT2 devices */ 5159 SISSaveDetectedDevices(pScrn); 5160 5161 if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR)) { 5162 if((pSiS->ForceTVType != -1) && (pSiS->ForceTVType & TV_YPBPR)) { 5163 pSiS->ForceTVType = -1; 5164 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "YPbPr TV output not supported\n"); 5165 } 5166 } 5167 5168 if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTHIVISION)) { 5169 if((pSiS->ForceTVType != -1) && (pSiS->ForceTVType & TV_HIVISION)) { 5170 pSiS->ForceTVType = -1; 5171 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "HiVision TV output not supported\n"); 5172 } 5173 } 5174 5175 if((pSiS->VBFlags2 & VB2_SISTVBRIDGE) || 5176 ((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->ChrontelType == CHRONTEL_701x))) { 5177 pSiS->SiS_SD_Flags |= (SiS_SD_SUPPORTPALMN | SiS_SD_SUPPORTNTSCJ); 5178 } 5179 if((pSiS->VBFlags2 & VB2_SISTVBRIDGE) || 5180 ((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->ChrontelType == CHRONTEL_700x))) { 5181 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTTVPOS; 5182 } 5183 if(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE) { 5184 pSiS->SiS_SD_Flags |= (SiS_SD_SUPPORTSCART | SiS_SD_SUPPORTVGA2); 5185 } 5186 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 5187 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTOVERSCAN; 5188 pSiS->SiS_SD2_Flags |= SiS_SD2_CHRONTEL; 5189 if(pSiS->ChrontelType == CHRONTEL_700x) { 5190 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTSOVER; 5191 } 5192 } 5193 5194 /* Determine if chipset LCDA-capable */ 5195 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTLCDA; 5196 if(SISDetermineLCDACap(pScrn)) { 5197 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTLCDA; 5198 } 5199 5200 /* Default to LCDA if LCD detected and 5201 * - TV detected (hence default to LCDA+TV), or 5202 * - in single head mode, on LCD panels with xres > 1600 5203 * (Don't do this in MergedFB or DHM; LCDA and CRT1/VGA 5204 * are mutually exclusive; if no TV is detected, the 5205 * code below will default to VGA+LCD, so LCD is driven 5206 * via CRT2.) 5207 * (TODO: This might need some modification for the 5208 * 307 bridges, if these are capable of driving 5209 * LCDs > 1600 via channel B) 5210 */ 5211 if((pSiS->SiS_SD_Flags & SiS_SD_SUPPORTLCDA) && 5212 (pSiS->VBFlags & CRT2_LCD) && 5213 (pSiS->SiS_Pr->SiS_CustomT != CUT_UNKNOWNLCD)) { 5214 if((!pSiS->CRT1TypeForced) && (pSiS->ForceCRT2Type == CRT2_DEFAULT)) { 5215 if(pSiS->VBFlags & CRT2_TV) { 5216 /* If both LCD and TV present, default to LCDA+TV */ 5217 pSiS->ForceCRT1Type = CRT1_LCDA; 5218 pSiS->ForceCRT2Type = CRT2_TV; 5219 } else if(pSiS->LCDwidth > 1600) { 5220 /* If LCD is > 1600, default to LCDA if we don't need CRT1/VGA for other head */ 5221 Bool NeedCRT1VGA = FALSE; 5222#ifdef SISDUALHEAD 5223 if(pSiS->DualHeadMode) NeedCRT1VGA = TRUE; 5224#endif 5225#ifdef SISMERGED 5226 if(pSiS->MergedFB && 5227 (!pSiS->MergedFBAuto || pSiS->CRT1Detected)) NeedCRT1VGA = TRUE; 5228#endif 5229 if(!NeedCRT1VGA) { 5230 pSiS->ForceCRT1Type = CRT1_LCDA; 5231 } 5232 } 5233 } 5234 } 5235 5236 /* Set up pseudo-panel if LCDA forced on TMDS bridges */ 5237 if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTLCDA) { 5238 if(pSiS->ForceCRT1Type == CRT1_LCDA) { 5239 if(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE) { 5240 if(!(pSiS->VBLCDFlags)) { 5241 SiSSetupPseudoPanel(pScrn); 5242 pSiS->detectedCRT2Devices |= CRT2_LCD; 5243 } 5244 } else if(!(pSiS->VBLCDFlags)) { 5245 pSiS->ForceCRT1Type = CRT1_VGA; 5246 } 5247 } 5248 } else { 5249 pSiS->ForceCRT1Type = CRT1_VGA; 5250 } 5251 5252 pSiS->VBFlags |= pSiS->ForceCRT1Type; 5253 5254#ifdef TWDEBUG 5255 xf86DrvMsg(0, X_INFO, "SDFlags %lx\n", pSiS->SiS_SD_Flags); 5256#endif 5257 5258 /* Eventually overrule detected CRT2 type 5259 * If no type forced, use the detected devices in the order TV->LCD->VGA2 5260 * Since the Chrontel 7005 sometimes delivers wrong detection results, 5261 * we use a different order on such machines (LCD->TV) 5262 */ 5263 if(pSiS->ForceCRT2Type == CRT2_DEFAULT) { 5264 if((pSiS->VBFlags & CRT2_TV) && (!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VGAEngine == SIS_300_VGA)))) 5265 pSiS->ForceCRT2Type = CRT2_TV; 5266 else if((pSiS->VBFlags & CRT2_LCD) && (pSiS->ForceCRT1Type == CRT1_VGA)) 5267 pSiS->ForceCRT2Type = CRT2_LCD; 5268 else if(pSiS->VBFlags & CRT2_TV) 5269 pSiS->ForceCRT2Type = CRT2_TV; 5270 else if((pSiS->VBFlags & CRT2_VGA) && (pSiS->ForceCRT1Type == CRT1_VGA)) 5271 pSiS->ForceCRT2Type = CRT2_VGA; 5272 } 5273 5274 switch(pSiS->ForceCRT2Type) { 5275 case CRT2_TV: 5276 pSiS->VBFlags &= ~(CRT2_LCD | CRT2_VGA); 5277 if(pSiS->VBFlags2 & (VB2_SISTVBRIDGE | VB2_CHRONTEL)) { 5278 pSiS->VBFlags |= CRT2_TV; 5279 } else { 5280 pSiS->VBFlags &= ~(CRT2_TV); 5281 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 5282 "Hardware does not support TV output\n"); 5283 } 5284 break; 5285 case CRT2_LCD: 5286 pSiS->VBFlags &= ~(CRT2_TV | CRT2_VGA); 5287 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (pSiS->VBLCDFlags)) { 5288 pSiS->VBFlags |= CRT2_LCD; 5289 } else if((pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && (!(pSiS->VBFlags2 & VB2_30xBDH))) { 5290 SiSSetupPseudoPanel(pScrn); 5291 pSiS->detectedCRT2Devices |= CRT2_LCD; 5292 } else { 5293 pSiS->VBFlags &= ~(CRT2_LCD); 5294 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 5295 "Can't force CRT2 to LCD, no LCD detected\n"); 5296 } 5297 break; 5298 case CRT2_VGA: 5299 pSiS->VBFlags &= ~(CRT2_TV | CRT2_LCD); 5300 if(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE) { 5301 pSiS->VBFlags |= CRT2_VGA; 5302 } else { 5303 pSiS->VBFlags &= ~(CRT2_VGA); 5304 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 5305 "Hardware does not support secondary VGA\n"); 5306 } 5307 break; 5308 default: 5309 pSiS->VBFlags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA); 5310 } 5311 5312 /* Setup gamma (the cmap layer needs this to be initialised) */ 5313 /* (Do this after evaluating options) */ 5314 { 5315 Gamma zeros = {0.0, 0.0, 0.0}; 5316 xf86SetGamma(pScrn, zeros); 5317 } 5318 5319#ifdef SISDUALHEAD 5320 if((!pSiS->DualHeadMode) || (pSiS->SecondHead)) { 5321#endif 5322 xf86DrvMsg(pScrn->scrnIndex, pSiS->CRT1gammaGiven ? X_CONFIG : X_INFO, 5323 "%samma correction is %s\n", 5324 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) ? "CRT1 g" : "G", 5325 pSiS->CRT1gamma ? "enabled" : "disabled"); 5326 5327 if((pSiS->VGAEngine == SIS_315_VGA) && 5328 (!(pSiS->NoXvideo)) && 5329 (!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY))) { 5330 xf86DrvMsg(pScrn->scrnIndex, pSiS->XvGammaGiven ? X_CONFIG : X_INFO, 5331 "Separate Xv gamma correction %sis %s\n", 5332 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) ? "for CRT1 " : "", 5333 pSiS->XvGamma ? "enabled" : "disabled"); 5334 if(pSiS->XvGamma) { 5335 xf86DrvMsg(pScrn->scrnIndex, pSiS->XvGammaGiven ? X_CONFIG : X_INFO, 5336 "Xv gamma correction: %.3f %.3f %.3f\n", 5337 (float)((float)pSiS->XvGammaRed / 1000), 5338 (float)((float)pSiS->XvGammaGreen / 1000), 5339 (float)((float)pSiS->XvGammaBlue / 1000)); 5340 if(!pSiS->CRT1gamma) { 5341 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5342 "Xv gamma correction requires %samma correction enabled\n", 5343 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) ? "CRT1 g" : "G"); 5344 } 5345 } 5346 } 5347#ifdef SISDUALHEAD 5348 } 5349#endif 5350 5351#ifdef SISDUALHEAD 5352 if(pSiS->DualHeadMode) pSiS->CRT2SepGamma = FALSE; 5353#endif 5354 5355#ifdef SISDUALHEAD 5356 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) 5357#endif 5358 { 5359 Bool isDH = FALSE; 5360 if(pSiS->CRT2gamma) { 5361 if( ((pSiS->VGAEngine != SIS_300_VGA) && (pSiS->VGAEngine != SIS_315_VGA)) || 5362 (!(pSiS->VBFlags2 & VB2_SISBRIDGE)) ) { 5363 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 5364 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5365 "CRT2 gamma correction not supported by hardware\n"); 5366 } 5367 pSiS->CRT2gamma = pSiS->CRT2SepGamma = FALSE; 5368 } else if((pSiS->VBFlags2 & VB2_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) { 5369 isDH = TRUE; 5370 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5371 "CRT2 gamma correction not supported for LCD\n"); 5372 /* But leave it on, will be caught in LoadPalette */ 5373 } 5374 } 5375 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 5376 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CRT2 gamma correction is %s%s%s\n", 5377 pSiS->CRT2gamma ? "enabled" : "disabled", 5378 isDH ? " (for TV and VGA2) " : "", 5379 pSiS->CRT2SepGamma ? " (separate from CRT1)" : ""); 5380 } 5381 } 5382 5383 /* Eventually overrule TV Type (SVIDEO, COMPOSITE, SCART, HIVISION, YPBPR) */ 5384 if(pSiS->VBFlags2 & VB2_SISTVBRIDGE) { 5385 if(pSiS->ForceTVType != -1) { 5386 pSiS->VBFlags &= ~(TV_INTERFACE); 5387 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) { 5388 pSiS->VBFlags &= ~(TV_CHSCART | TV_CHYPBPR525I); 5389 } 5390 pSiS->VBFlags |= pSiS->ForceTVType; 5391 if(pSiS->VBFlags & TV_YPBPR) { 5392 pSiS->VBFlags &= ~(TV_STANDARD); 5393 pSiS->VBFlags &= ~(TV_YPBPRAR); 5394 pSiS->VBFlags |= pSiS->ForceYPbPrType; 5395 pSiS->VBFlags |= pSiS->ForceYPbPrAR; 5396 } 5397 } 5398 } 5399 5400 /* Handle ForceCRT1 option (part 2) */ 5401 pSiS->CRT1changed = FALSE; 5402 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5403 usScratchCR17 = pSiS->oldCR17; 5404 usScratchCR63 = pSiS->oldCR63; 5405 usScratchSR1F = pSiS->oldSR1F; 5406 usScratchCR32 = pSiS->postVBCR32; 5407 if(pSiS->VESA != 1) { 5408 /* Copy forceCRT1 option to CRT1off if option is given */ 5409#ifdef SISDUALHEAD 5410 /* In DHM, handle this option only for master head, not the slave */ 5411 if( (pSiS->forceCRT1 != -1) && 5412 (!(pSiS->DualHeadMode && pSiS->SecondHead)) ) { 5413#else 5414 if(pSiS->forceCRT1 != -1) { 5415#endif 5416 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5417 "CRT1 detection overruled by ForceCRT1 option\n"); 5418 if(pSiS->forceCRT1) { 5419 pSiS->CRT1off = 0; 5420 if(pSiS->VGAEngine == SIS_300_VGA) { 5421 if(!(usScratchCR17 & 0x80)) pSiS->CRT1changed = TRUE; 5422 } else { 5423 if(usScratchCR63 & 0x40) pSiS->CRT1changed = TRUE; 5424 } 5425 usScratchCR17 |= 0x80; 5426 usScratchCR32 |= 0x20; 5427 usScratchCR63 &= ~0x40; 5428 usScratchSR1F &= ~0xc0; 5429 } else { 5430 if( ! ( (pScrn->bitsPerPixel == 8) && 5431 ( (pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) || 5432 ((pSiS->VBFlags2 & VB2_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) ) ) ) { 5433 pSiS->CRT1off = 1; 5434 if(pSiS->VGAEngine == SIS_300_VGA) { 5435 if(usScratchCR17 & 0x80) pSiS->CRT1changed = TRUE; 5436 } else { 5437 if(!(usScratchCR63 & 0x40)) pSiS->CRT1changed = TRUE; 5438 } 5439 usScratchCR32 &= ~0x20; 5440 /* We must not actually switch off CRT1 before we changed the mode! */ 5441 } 5442 } 5443 /* Here we can write to CR17 even on 315 series as we only ENABLE 5444 * the bit here 5445 */ 5446 outSISIDXREG(SISCR, 0x17, usScratchCR17); 5447 if(pSiS->VGAEngine == SIS_315_VGA) { 5448 outSISIDXREG(SISCR, pSiS->myCR63, usScratchCR63); 5449 } 5450 outSISIDXREG(SISCR, 0x32, usScratchCR32); 5451 if(pSiS->CRT1changed) { 5452 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 5453 usleep(10000); 5454 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 5455 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5456 "CRT1 status changed by ForceCRT1 option\n"); 5457 } 5458 outSISIDXREG(SISSR, 0x1f, usScratchSR1F); 5459 } 5460 } 5461 /* Store the new VB connection register contents for later mode changes */ 5462 pSiS->newCR32 = usScratchCR32; 5463 } 5464 5465 /* Check if CRT1 used (or needed; this eg. if no CRT2 detected) */ 5466 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 5467 5468 /* No CRT2 output? Then we NEED CRT1! 5469 * We also need CRT1 if depth = 8 and bridge=LVDS|301B-DH 5470 */ 5471 if( (!(pSiS->VBFlags & (CRT2_VGA | CRT2_LCD | CRT2_TV))) || 5472 ( (pScrn->bitsPerPixel == 8) && 5473 ( (pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) || 5474 ((pSiS->VBFlags2 & VB2_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) ) ) ) { 5475 pSiS->CRT1off = 0; 5476 } 5477 /* No CRT2 output? Then we can't use Xv on CRT2 */ 5478 if(!(pSiS->VBFlags & (CRT2_VGA | CRT2_LCD | CRT2_TV))) { 5479 pSiS->XvOnCRT2 = FALSE; 5480 } 5481 5482 } else { /* no video bridge? */ 5483 /* Then we NEED CRT1... */ 5484 pSiS->CRT1off = 0; 5485 /* ... and can't use CRT2 for Xv output */ 5486 pSiS->XvOnCRT2 = FALSE; 5487 } 5488 5489 /* LCDA? Then we don't switch off CRT1 */ 5490 if(pSiS->VBFlags & CRT1_LCDA) pSiS->CRT1off = 0; 5491 5492 /* Handle TVStandard option */ 5493 if((pSiS->NonDefaultPAL != -1) || (pSiS->NonDefaultNTSC != -1)) { 5494 if( (!(pSiS->VBFlags2 & VB2_SISTVBRIDGE)) && 5495 (!((pSiS->VBFlags2 & VB2_CHRONTEL)) && (pSiS->ChrontelType == CHRONTEL_701x)) ) { 5496 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5497 "PALM, PALN and NTSCJ not supported on this hardware\n"); 5498 pSiS->NonDefaultPAL = pSiS->NonDefaultNTSC = -1; 5499 pSiS->VBFlags &= ~(TV_PALN | TV_PALM | TV_NTSCJ); 5500 pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTPALMN | SiS_SD_SUPPORTNTSCJ); 5501 } 5502 } 5503 if(pSiS->OptTVStand != -1) { 5504 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5505 if( (!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & (TV_CHSCART | TV_CHYPBPR525I)))) && 5506 (!(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR))) ) { 5507 pSiS->VBFlags &= ~(TV_PAL | TV_NTSC | TV_PALN | TV_PALM | TV_NTSCJ); 5508 if(pSiS->OptTVStand) { 5509 pSiS->VBFlags |= TV_PAL; 5510 if(pSiS->NonDefaultPAL == 1) pSiS->VBFlags |= TV_PALM; 5511 else if(!pSiS->NonDefaultPAL) pSiS->VBFlags |= TV_PALN; 5512 } else { 5513 pSiS->VBFlags |= TV_NTSC; 5514 if(pSiS->NonDefaultNTSC == 1) pSiS->VBFlags |= TV_NTSCJ; 5515 } 5516 } else { 5517 pSiS->OptTVStand = pSiS->NonDefaultPAL = -1; 5518 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5519 "Option TVStandard ignored for YPbPr, HiVision and Chrontel-SCART\n"); 5520 } 5521 } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { 5522 pSiS->SiS6326Flags &= ~SIS6326_TVPAL; 5523 if(pSiS->OptTVStand) pSiS->SiS6326Flags |= SIS6326_TVPAL; 5524 } 5525 } 5526 5527 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5528 /* Default to PAL */ 5529 if(pSiS->VBFlags & (TV_SVIDEO | TV_AVIDEO)) { 5530 if(!(pSiS->VBFlags & (TV_PAL | TV_NTSC))) { 5531 pSiS->VBFlags &= ~(TV_PAL | TV_NTSC | TV_PALN | TV_PALM | TV_NTSCJ); 5532 pSiS->VBFlags |= TV_PAL; 5533 } 5534 } 5535 /* SCART only supported for PAL */ 5536 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && (pSiS->VBFlags & TV_SCART)) { 5537 pSiS->VBFlags &= ~(TV_NTSC | TV_PALN | TV_PALM | TV_NTSCJ); 5538 pSiS->VBFlags |= TV_PAL; 5539 pSiS->OptTVStand = 1; 5540 pSiS->NonDefaultPAL = pSiS->NonDefaultNTSC = -1; 5541 } 5542 } 5543 5544#ifdef SIS_CP 5545 SIS_CP_DRIVER_RECONFIGOPT 5546#endif 5547 5548 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 5549 if(pSiS->sis6326tvplug != -1) { 5550 pSiS->SiS6326Flags &= ~(SIS6326_TVSVIDEO | SIS6326_TVCVBS); 5551 pSiS->SiS6326Flags |= SIS6326_TVDETECTED; 5552 if(pSiS->sis6326tvplug == 1) pSiS->SiS6326Flags |= SIS6326_TVCVBS; 5553 else pSiS->SiS6326Flags |= SIS6326_TVSVIDEO; 5554 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5555 "SiS6326 TV plug type detection overruled by %s\n", 5556 (pSiS->SiS6326Flags & SIS6326_TVCVBS) ? "COMPOSITE" : "SVIDEO"); 5557 } 5558 } 5559 5560 /* Do some checks */ 5561 if(pSiS->OptTVOver != -1) { 5562 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 5563 pSiS->UseCHOverScan = pSiS->OptTVOver; 5564 } else { 5565 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5566 "CHTVOverscan only supported on CHRONTEL 70xx\n"); 5567 pSiS->UseCHOverScan = -1; 5568 } 5569 } else pSiS->UseCHOverScan = -1; 5570 5571 if(pSiS->sistvedgeenhance != -1) { 5572 if(!(pSiS->VBFlags2 & VB2_301)) { 5573 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5574 "SISTVEdgeEnhance only supported on SiS301\n"); 5575 pSiS->sistvedgeenhance = -1; 5576 } 5577 } 5578 if(pSiS->sistvsaturation != -1) { 5579 if(pSiS->VBFlags2 & VB2_301) { 5580 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5581 "SISTVSaturation not supported on SiS301\n"); 5582 pSiS->sistvsaturation = -1; 5583 } 5584 } 5585 5586 /* Do some MergedFB mode initialisation */ 5587#ifdef SISMERGED 5588 if(pSiS->MergedFB) { 5589 pSiS->CRT2pScrn = malloc(sizeof(ScrnInfoRec)); 5590 if(!pSiS->CRT2pScrn) { 5591 SISErrorLog(pScrn, "Failed to allocate memory for 2nd pScrn, %s\n", mergeddisstr); 5592 pSiS->MergedFB = FALSE; 5593 } else { 5594 memcpy(pSiS->CRT2pScrn, pScrn, sizeof(ScrnInfoRec)); 5595 } 5596 } 5597#endif 5598 5599 /* Determine CRT1<>CRT2 mode 5600 * Note: When using VESA or if the bridge is in slavemode, display 5601 * is ALWAYS in MIRROR_MODE! 5602 * This requires extra checks in functions using this flag! 5603 * (see sis_video.c for example) 5604 */ 5605 if(pSiS->VBFlags & DISPTYPE_DISP2) { 5606 if(pSiS->CRT1off) { /* CRT2 only ------------------------------- */ 5607#ifdef SISDUALHEAD 5608 if(pSiS->DualHeadMode) { 5609 SISErrorLog(pScrn, 5610 "CRT1 not detected or forced off. Dual Head mode can't initialize.\n"); 5611 if(pSiSEnt) pSiSEnt->DisableDual = TRUE; 5612 goto my_error_1; 5613 } 5614#endif 5615#ifdef SISMERGED 5616 if(pSiS->MergedFB) { 5617 if(pSiS->MergedFBAuto) { 5618 xf86DrvMsg(pScrn->scrnIndex, X_INFO, mergednocrt1, mergeddisstr); 5619 } else { 5620 SISErrorLog(pScrn, mergednocrt1, mergeddisstr); 5621 } 5622 if(pSiS->CRT2pScrn) free(pSiS->CRT2pScrn); 5623 pSiS->CRT2pScrn = NULL; 5624 pSiS->MergedFB = FALSE; 5625 } 5626#endif 5627 pSiS->VBFlags |= VB_DISPMODE_SINGLE; 5628 /* No CRT1? Then we use the video overlay on CRT2 */ 5629 pSiS->XvOnCRT2 = TRUE; 5630 } else /* CRT1 and CRT2 - mirror or dual head ----- */ 5631#ifdef SISDUALHEAD 5632 if(pSiS->DualHeadMode) { 5633 pSiS->VBFlags |= (VB_DISPMODE_DUAL | DISPTYPE_CRT1); 5634 if(pSiS->VESA != -1) { 5635 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5636 "VESA option not used in Dual Head mode. VESA disabled.\n"); 5637 } 5638 if(pSiSEnt) pSiSEnt->DisableDual = FALSE; 5639 pSiS->VESA = 0; 5640 } else 5641#endif 5642#ifdef SISMERGED 5643 if(pSiS->MergedFB) { 5644 pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_CRT1); 5645 if(pSiS->VESA != -1) { 5646 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5647 "VESA option not used in MergedFB mode. VESA disabled.\n"); 5648 } 5649 pSiS->VESA = 0; 5650 } else 5651#endif 5652 pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_CRT1); 5653 } else { /* CRT1 only ------------------------------- */ 5654#ifdef SISDUALHEAD 5655 if(pSiS->DualHeadMode) { 5656 SISErrorLog(pScrn, 5657 "No CRT2 output selected or no bridge detected. " 5658 "Dual Head mode can't initialize.\n"); 5659 goto my_error_1; 5660 } 5661#endif 5662#ifdef SISMERGED 5663 if(pSiS->MergedFB) { 5664 if(pSiS->MergedFBAuto) { 5665 xf86DrvMsg(pScrn->scrnIndex, X_INFO, mergednocrt2, mergeddisstr); 5666 } else { 5667 SISErrorLog(pScrn, mergednocrt2, mergeddisstr); 5668 } 5669 if(pSiS->CRT2pScrn) free(pSiS->CRT2pScrn); 5670 pSiS->CRT2pScrn = NULL; 5671 pSiS->MergedFB = FALSE; 5672 } 5673#endif 5674 pSiS->VBFlags |= (VB_DISPMODE_SINGLE | DISPTYPE_CRT1); 5675 } 5676 5677 if((pSiS->VGAEngine == SIS_315_VGA) || (pSiS->VGAEngine == SIS_300_VGA)) { 5678 if((!pSiS->NoXvideo) && 5679 (!pSiS->hasTwoOverlays) && 5680 (!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY))) { 5681 xf86DrvMsg(pScrn->scrnIndex, from, 5682 "Using Xv overlay by default on CRT%d\n", 5683 pSiS->XvOnCRT2 ? 2 : 1); 5684 } 5685 } 5686 5687 /* Init ptrs for Save/Restore functions and calc MaxClock */ 5688 SISDACPreInit(pScrn); 5689 5690 /* ********** end of VBFlags setup ********** */ 5691 5692 /* VBFlags are initialized now. Back them up for SlaveMode modes. */ 5693 pSiS->VBFlags_backup = pSiS->VBFlags; 5694 5695 /* Backup CR32,36,37 (in order to write them back after a VT switch) */ 5696 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5697 inSISIDXREG(SISCR,0x32,pSiS->myCR32); 5698 inSISIDXREG(SISCR,0x36,pSiS->myCR36); 5699 inSISIDXREG(SISCR,0x37,pSiS->myCR37); 5700 } 5701 5702 /* Find out about paneldelaycompensation and evaluate option */ 5703#ifdef SISDUALHEAD 5704 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) { 5705#endif 5706 if(pSiS->VGAEngine == SIS_300_VGA) { 5707 5708 if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) { 5709 5710 /* Save the current PDC if the panel is used at the moment. 5711 * This seems by far the safest way to find out about it. 5712 * If the system is using an old version of sisfb, we can't 5713 * trust the pdc register value. If sisfb saved the pdc for 5714 * us, use it. 5715 */ 5716 if(pSiS->sisfbpdc != 0xff) { 5717 pSiS->SiS_Pr->PDC = pSiS->sisfbpdc; 5718 } else { 5719 if(!(pSiS->donttrustpdc)) { 5720 UChar tmp; 5721 inSISIDXREG(SISCR, 0x30, tmp); 5722 if(tmp & 0x20) { 5723 inSISIDXREG(SISPART1, 0x13, pSiS->SiS_Pr->PDC); 5724 } else { 5725 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5726 "Unable to detect LCD PanelDelayCompensation, LCD is not active\n"); 5727 } 5728 } else { 5729 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5730 "Unable to detect LCD PanelDelayCompensation, please update sisfb\n"); 5731 } 5732 } 5733 if(pSiS->SiS_Pr->PDC != -1) { 5734 pSiS->SiS_Pr->PDC &= 0x3c; 5735 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5736 "Detected LCD PanelDelayCompensation 0x%02x\n", 5737 pSiS->SiS_Pr->PDC); 5738 } 5739 5740 /* If we haven't been able to find out, use our other methods */ 5741 if(pSiS->SiS_Pr->PDC == -1) { 5742 int i=0; 5743 do { 5744 if(mypdctable[i].subsysVendor == PCI_SUB_VENDOR_ID(pSiS->PciInfo) && 5745 mypdctable[i].subsysCard == PCI_SUB_DEVICE_ID(pSiS->PciInfo)) { 5746 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5747 "PCI card/vendor identified for non-default PanelDelayCompensation\n"); 5748 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5749 "Vendor: %s, card: %s (ID %04x), PanelDelayCompensation: 0x%02x\n", 5750 mypdctable[i].vendorName, mypdctable[i].cardName, 5751 PCI_SUB_DEVICE_ID(pSiS->PciInfo), mypdctable[i].pdc); 5752 if(pSiS->PDC == -1) { 5753 pSiS->PDC = mypdctable[i].pdc; 5754 } else { 5755 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5756 "PanelDelayCompensation overruled by option\n"); 5757 } 5758 break; 5759 } 5760 i++; 5761 } while(mypdctable[i].subsysVendor != 0); 5762 } 5763 5764 if(pSiS->PDC != -1) { 5765 if(pSiS->BIOS) { 5766 if(pSiS->VBFlags2 & VB2_LVDS) { 5767 if(pSiS->BIOS[0x220] & 0x80) { 5768 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5769 "BIOS uses OEM LCD Panel Delay Compensation 0x%02x\n", 5770 pSiS->BIOS[0x220] & 0x3c); 5771 pSiS->BIOS[0x220] &= 0x7f; 5772 } 5773 } 5774 if(pSiS->VBFlags2 & (VB2_301B | VB2_302B)) { 5775 if(pSiS->BIOS[0x220] & 0x80) { 5776 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5777 "BIOS uses OEM LCD Panel Delay Compensation 0x%02x\n", 5778 ( (pSiS->VBLCDFlags & VB_LCD_1280x1024) ? 5779 pSiS->BIOS[0x223] : pSiS->BIOS[0x224] ) & 0x3c); 5780 pSiS->BIOS[0x220] &= 0x7f; 5781 } 5782 } 5783 } 5784 pSiS->SiS_Pr->PDC = (pSiS->PDC & 0x3c); 5785 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5786 "Using LCD Panel Delay Compensation 0x%02x\n", pSiS->SiS_Pr->PDC); 5787 } 5788 } 5789 5790 } /* SIS_300_VGA */ 5791 5792 if(pSiS->VGAEngine == SIS_315_VGA) { 5793 5794 UChar tmp, tmp2; 5795 inSISIDXREG(SISCR, 0x30, tmp); 5796 5797 /* Save the current PDC if the panel is used at the moment. */ 5798 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) { 5799 5800 if(pSiS->sisfbpdc != 0xff) { 5801 pSiS->SiS_Pr->PDC = pSiS->sisfbpdc; 5802 } 5803 if(pSiS->sisfbpdca != 0xff) { 5804 pSiS->SiS_Pr->PDCA = pSiS->sisfbpdca; 5805 } 5806 5807 if(!pSiS->donttrustpdc) { 5808 if((pSiS->sisfbpdc == 0xff) && (pSiS->sisfbpdca == 0xff)) { 5809 CARD16 tempa, tempb; 5810 inSISIDXREG(SISPART1,0x2d,tmp2); 5811 tempa = (tmp2 & 0xf0) >> 3; 5812 tempb = (tmp2 & 0x0f) << 1; 5813 inSISIDXREG(SISPART1,0x20,tmp2); 5814 tempa |= ((tmp2 & 0x40) >> 6); 5815 inSISIDXREG(SISPART1,0x35,tmp2); 5816 tempb |= ((tmp2 & 0x80) >> 7); 5817 inSISIDXREG(SISPART1,0x13,tmp2); 5818 if(!pSiS->ROM661New) { 5819 if((tmp2 & 0x04) || (tmp & 0x20)) { 5820 pSiS->SiS_Pr->PDCA = tempa; 5821 pSiS->SiS_Pr->PDC = tempb; 5822 } else { 5823 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5824 "Unable to detect PanelDelayCompensation, LCD is not active\n"); 5825 } 5826 } else { 5827 if(tmp2 & 0x04) { 5828 pSiS->SiS_Pr->PDCA = tempa; 5829 } else if(tmp & 0x20) { 5830 pSiS->SiS_Pr->PDC = tempb; 5831 } else { 5832 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5833 "Unable to detect PanelDelayCompensation, LCD is not active\n"); 5834 } 5835 } 5836 } 5837 } else { 5838 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5839 "Unable to detect PanelDelayCompensation, please update sisfb\n"); 5840 } 5841 if(pSiS->SiS_Pr->PDC != -1) { 5842 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5843 "Detected LCD PanelDelayCompensation 0x%02x (for LCD=CRT2)\n", 5844 pSiS->SiS_Pr->PDC); 5845 } 5846 if(pSiS->SiS_Pr->PDCA != -1) { 5847 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5848 "Detected LCD PanelDelayCompensation1 0x%02x (for LCD=CRT1)\n", 5849 pSiS->SiS_Pr->PDCA); 5850 } 5851 } 5852 5853 /* Let user override (for all bridges) */ 5854 if(pSiS->VBFlags2 & VB2_30xBLV) { 5855 if(pSiS->PDC != -1) { 5856 pSiS->SiS_Pr->PDC = pSiS->PDC & 0x1f; 5857 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5858 "Using LCD PanelDelayCompensation 0x%02x (for LCD=CRT2)\n", 5859 pSiS->SiS_Pr->PDC); 5860 } 5861 if(pSiS->PDCA != -1) { 5862 pSiS->SiS_Pr->PDCA = pSiS->PDCA & 0x1f; 5863 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5864 "Using LCD PanelDelayCompensation1 0x%02x (for LCD=CRT1)\n", 5865 pSiS->SiS_Pr->PDCA); 5866 } 5867 } 5868 5869 /* Read the current EMI (if not overruled) */ 5870 if(pSiS->VBFlags2 & VB2_SISEMIBRIDGE) { 5871 MessageType from = X_PROBED; 5872 if(pSiS->EMI != -1) { 5873 pSiS->SiS_Pr->EMI_30 = (pSiS->EMI >> 24) & 0x60; 5874 pSiS->SiS_Pr->EMI_31 = (pSiS->EMI >> 16) & 0xff; 5875 pSiS->SiS_Pr->EMI_32 = (pSiS->EMI >> 8) & 0xff; 5876 pSiS->SiS_Pr->EMI_33 = pSiS->EMI & 0xff; 5877 pSiS->SiS_Pr->HaveEMI = pSiS->SiS_Pr->HaveEMILCD = TRUE; 5878 pSiS->SiS_Pr->OverruleEMI = TRUE; 5879 from = X_CONFIG; 5880 } else if((pSiS->sisfbfound) && (pSiS->sisfb_haveemi)) { 5881 pSiS->SiS_Pr->EMI_30 = pSiS->sisfb_emi30; 5882 pSiS->SiS_Pr->EMI_31 = pSiS->sisfb_emi31; 5883 pSiS->SiS_Pr->EMI_32 = pSiS->sisfb_emi32; 5884 pSiS->SiS_Pr->EMI_33 = pSiS->sisfb_emi33; 5885 pSiS->SiS_Pr->HaveEMI = TRUE; 5886 if(pSiS->sisfb_haveemilcd) pSiS->SiS_Pr->HaveEMILCD = TRUE; 5887 pSiS->SiS_Pr->OverruleEMI = FALSE; 5888 } else { 5889 inSISIDXREG(SISPART4, 0x30, pSiS->SiS_Pr->EMI_30); 5890 inSISIDXREG(SISPART4, 0x31, pSiS->SiS_Pr->EMI_31); 5891 inSISIDXREG(SISPART4, 0x32, pSiS->SiS_Pr->EMI_32); 5892 inSISIDXREG(SISPART4, 0x33, pSiS->SiS_Pr->EMI_33); 5893 pSiS->SiS_Pr->HaveEMI = TRUE; 5894 if(tmp & 0x20) pSiS->SiS_Pr->HaveEMILCD = TRUE; 5895 pSiS->SiS_Pr->OverruleEMI = FALSE; 5896 } 5897 xf86DrvMsg(pScrn->scrnIndex, from, 5898 "302LV/302ELV: Using EMI 0x%02x%02x%02x%02x%s\n", 5899 pSiS->SiS_Pr->EMI_30,pSiS->SiS_Pr->EMI_31, 5900 pSiS->SiS_Pr->EMI_32,pSiS->SiS_Pr->EMI_33, 5901 pSiS->SiS_Pr->HaveEMILCD ? " (LCD)" : ""); 5902 } 5903 5904 } /* SIS_315_VGA */ 5905#ifdef SISDUALHEAD 5906 } 5907#endif 5908 5909 5910 /* In dual head mode, both heads (currently) share the maxxfbmem equally. 5911 * If memory sharing is done differently, the following has to be changed; 5912 * the other modules (eg. accel and Xv) use dhmOffset for hardware 5913 * pointer settings relative to VideoRAM start and won't need to be changed. 5914 * 5915 * Addendum: dhmoffset is also used for skipping the UMA area on SiS76x. 5916 */ 5917 5918 pSiS->dhmOffset = pSiS->FbBaseOffset; 5919 pSiS->FbAddress += pSiS->dhmOffset; 5920 5921#ifdef SISDUALHEAD 5922 if(pSiS->DualHeadMode) { 5923 pSiS->FbAddress = pSiS->realFbAddress; 5924 if(!pSiS->SecondHead) { 5925 /* ===== First head (always CRT2) ===== */ 5926 /* We use only half of the memory available */ 5927 pSiS->maxxfbmem /= 2; 5928 /* dhmOffset is 0 (or LFB-base for SiS76x UMA skipping) */ 5929 pSiS->FbAddress += pSiS->dhmOffset; 5930 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5931 "%dKB video RAM at 0x%lx available for master head (CRT2)\n", 5932 pSiS->maxxfbmem/1024, pSiS->FbAddress); 5933 } else { 5934 /* ===== Second head (always CRT1) ===== */ 5935 /* We use only half of the memory available */ 5936 pSiS->maxxfbmem /= 2; 5937 /* Initialize dhmOffset */ 5938 pSiS->dhmOffset += pSiS->maxxfbmem; 5939 /* Adapt FBAddress */ 5940 pSiS->FbAddress += pSiS->dhmOffset; 5941 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5942 "%dKB video RAM at 0x%lx available for slave head (CRT1)\n", 5943 pSiS->maxxfbmem/1024, pSiS->FbAddress); 5944 } 5945 } 5946#endif 5947 5948 /* Note: Do not use availMem for anything from now. Use 5949 * maxxfbmem instead. (availMem does not take dual head 5950 * mode into account.) 5951 */ 5952 5953 if(pSiS->FbBaseOffset) { 5954 /* Doubt that the DRM memory manager can deal 5955 * with a heap start of 0... 5956 */ 5957 pSiS->DRIheapstart = 16; 5958 pSiS->DRIheapend = pSiS->FbBaseOffset; 5959 } else { 5960 pSiS->DRIheapstart = pSiS->maxxfbmem; 5961 pSiS->DRIheapend = pSiS->availMem; 5962 } 5963#ifdef SISDUALHEAD 5964 if(pSiS->DualHeadMode) { 5965 pSiS->DRIheapstart = pSiS->DRIheapend = 0; 5966 } else 5967#endif 5968 if(pSiS->DRIheapstart >= pSiS->DRIheapend) { 5969#if 0 /* For future use */ 5970 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5971 "No memory for DRI heap. Please set the option \"MaxXFBMem\" to\n" 5972 "\tlimit the memory X should use and leave the rest to DRI\n"); 5973#endif 5974 pSiS->DRIheapstart = pSiS->DRIheapend = 0; 5975 } 5976 5977 /* Now for something completely different: DDC. 5978 * For 300 and 315/330/340 series, we provide our 5979 * own functions (in order to probe CRT2 as well) 5980 * If these fail, use the VBE. 5981 * All other chipsets will use VBE. No need to re-invent 5982 * the wheel there. 5983 */ 5984 5985 pSiS->pVbe = NULL; 5986 didddc2 = FALSE; 5987 5988 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5989 if(xf86LoadSubModule(pScrn, "ddc")) { 5990 int crtnum = 0; 5991 if((pMonitor = SiSDoPrivateDDC(pScrn, &crtnum))) { 5992 didddc2 = TRUE; 5993 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcsstr, crtnum); 5994 xf86PrintEDID(pMonitor); 5995 xf86SetDDCproperties(pScrn, pMonitor); 5996 pScrn->monitor->DDC = pMonitor; 5997 /* Now try to find out aspect ratio */ 5998 SiSFindAspect(pScrn, pMonitor, crtnum); 5999 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcestr, crtnum); 6000 } 6001 } 6002 } 6003 6004#ifdef SISDUALHEAD 6005 /* In dual head mode, probe DDC using VBE only for CRT1 (second head) */ 6006 if((pSiS->DualHeadMode) && (!didddc2) && (!pSiS->SecondHead)) { 6007 didddc2 = TRUE; 6008 } 6009#endif 6010 6011 if(!didddc2) { 6012 /* If CRT1 is off or LCDA, skip DDC via VBE */ 6013 if((pSiS->CRT1off) || (pSiS->VBFlags & CRT1_LCDA)) { 6014 didddc2 = TRUE; 6015 } 6016 } 6017 6018 /* Now (re-)load and initialize the DDC module */ 6019 if(!didddc2) { 6020 6021 if(xf86LoadSubModule(pScrn, "ddc")) { 6022 6023 /* Now load and initialize VBE module. */ 6024 SiS_LoadInitVBE(pScrn); 6025 6026 if(pSiS->pVbe) { 6027 if((pMonitor = vbeDoEDID(pSiS->pVbe,NULL))) { 6028 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 6029 "VBE CRT1 DDC monitor info:\n"); 6030 xf86SetDDCproperties(pScrn, xf86PrintEDID(pMonitor)); 6031 pScrn->monitor->DDC = pMonitor; 6032 /* Now try to find out aspect ratio */ 6033 SiSFindAspect(pScrn, pMonitor, 1); 6034 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 6035 "End of VBE CRT1 DDC monitor info\n"); 6036 } 6037 } else { 6038 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6039 "Failed to read DDC data\n"); 6040 } 6041 } 6042 } 6043 6044#ifdef SISMERGED 6045 if(pSiS->MergedFB) { 6046 pSiS->CRT2pScrn->monitor = malloc(sizeof(MonRec)); 6047 if(pSiS->CRT2pScrn->monitor) { 6048 DisplayModePtr tempm = NULL, currentm = NULL, newm = NULL; 6049 memcpy(pSiS->CRT2pScrn->monitor, pScrn->monitor, sizeof(MonRec)); 6050 pSiS->CRT2pScrn->monitor->DDC = NULL; 6051 pSiS->CRT2pScrn->monitor->Modes = NULL; 6052 pSiS->CRT2pScrn->monitor->id = (char *)crt2monname; 6053 tempm = pScrn->monitor->Modes; 6054 while(tempm) { 6055 if(!(newm = malloc(sizeof(DisplayModeRec)))) break; 6056 memcpy(newm, tempm, sizeof(DisplayModeRec)); 6057 if(!(newm->name = malloc(strlen(tempm->name) + 1))) { 6058 free(newm); 6059 break; 6060 } 6061 strcpy(newm->name, tempm->name); 6062 if(!pSiS->CRT2pScrn->monitor->Modes) pSiS->CRT2pScrn->monitor->Modes = newm; 6063 if(currentm) { 6064 currentm->next = newm; 6065 newm->prev = currentm; 6066 } 6067 currentm = newm; 6068 tempm = tempm->next; 6069 } 6070 if(pSiS->CRT2HSync) { 6071 pSiS->CRT2pScrn->monitor->nHsync = 6072 SiSStrToRanges(pSiS->CRT2pScrn->monitor->hsync, pSiS->CRT2HSync, MAX_HSYNC); 6073 } 6074 if(pSiS->CRT2VRefresh) { 6075 pSiS->CRT2pScrn->monitor->nVrefresh = 6076 SiSStrToRanges(pSiS->CRT2pScrn->monitor->vrefresh, pSiS->CRT2VRefresh, MAX_VREFRESH); 6077 } 6078 if((pMonitor = SiSInternalDDC(pSiS->CRT2pScrn, 1))) { 6079 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcsstr, 2); 6080 xf86PrintEDID(pMonitor); 6081 xf86SetDDCproperties(pSiS->CRT2pScrn, pMonitor); 6082 pSiS->CRT2pScrn->monitor->DDC = pMonitor; 6083 /* Now try to find out aspect ratio */ 6084 SiSFindAspect(pScrn, pMonitor, 2); 6085 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcestr, 2); 6086 /* use DDC data if no ranges in config file */ 6087 if(!pSiS->CRT2HSync) { 6088 pSiS->CRT2pScrn->monitor->nHsync = 0; 6089 } 6090 if(!pSiS->CRT2VRefresh) { 6091 pSiS->CRT2pScrn->monitor->nVrefresh = 0; 6092 } 6093 } else { 6094 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 6095 "Failed to read DDC data for CRT2\n"); 6096 } 6097 } else { 6098 SISErrorLog(pScrn, "Failed to allocate memory for CRT2 monitor, %s.\n", 6099 mergeddisstr); 6100 if(pSiS->CRT2pScrn) free(pSiS->CRT2pScrn); 6101 pSiS->CRT2pScrn = NULL; 6102 pSiS->MergedFB = FALSE; 6103 } 6104 } 6105#endif 6106 6107 /* Copy our detected monitor gammas, part 1. Note that device redetection 6108 * is not supported in DHM, so there is no need to do that anytime later. 6109 */ 6110#ifdef SISDUALHEAD 6111 if(pSiS->DualHeadMode) { 6112 if(!pSiS->SecondHead) { 6113 /* CRT2: Got gamma for LCD or VGA2 */ 6114 pSiSEnt->CRT2VGAMonitorGamma = pSiS->CRT2VGAMonitorGamma; 6115 } else { 6116 /* CRT1: Got gamma for LCD or VGA */ 6117 pSiSEnt->CRT1VGAMonitorGamma = pSiS->CRT1VGAMonitorGamma; 6118 } 6119 if(pSiS->CRT2LCDMonitorGamma) pSiSEnt->CRT2LCDMonitorGamma = pSiS->CRT2LCDMonitorGamma; 6120 } 6121#endif 6122 6123 /* end of DDC */ 6124 6125 /* From here, we mainly deal with clocks and modes */ 6126 6127#ifdef SISMERGED 6128 if(pSiS->MergedFB) xf86DrvMsg(pScrn->scrnIndex, X_INFO, crtsetupstr, 1); 6129#endif 6130 6131 /* Set the min pixel clock */ 6132 pSiS->MinClock = 5000; 6133 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 6134 pSiS->MinClock = 10000; 6135 } 6136 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n", 6137 pSiS->MinClock / 1000); 6138 6139 /* If the user has specified ramdac speed in the config 6140 * file, we respect that setting. 6141 */ 6142 from = X_PROBED; 6143 if(pSiS->pEnt->device->dacSpeeds[0]) { 6144 int speed = 0; 6145 switch(pScrn->bitsPerPixel) { 6146 case 8: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP8]; 6147 break; 6148 case 16: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP16]; 6149 break; 6150 case 24: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP24]; 6151 break; 6152 case 32: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP32]; 6153 break; 6154 } 6155 if(speed == 0) pSiS->MaxClock = pSiS->pEnt->device->dacSpeeds[0]; 6156 else pSiS->MaxClock = speed; 6157 from = X_CONFIG; 6158 } 6159 xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n", 6160 pSiS->MaxClock / 1000); 6161 6162 /* 6163 * Setup the ClockRanges, which describe what clock ranges are available, 6164 * and what sort of modes they can be used for. 6165 */ 6166 clockRanges = xnfcalloc(sizeof(ClockRange), 1); 6167 clockRanges->next = NULL; 6168 clockRanges->minClock = pSiS->MinClock; 6169 clockRanges->maxClock = pSiS->MaxClock; 6170 clockRanges->clockIndex = -1; /* programmable */ 6171 clockRanges->interlaceAllowed = TRUE; 6172 clockRanges->doubleScanAllowed = TRUE; 6173 6174 /* 6175 * Since we have lots of built-in modes for 300/315/330/340 series 6176 * with vb support, we replace the given default mode list with our 6177 * own. In case the video bridge is to be used, we only allow other 6178 * modes if 6179 * -) vbtype is 301, 301B, 301C or 302B, and 6180 * -) crt2 device is not TV, and 6181 * -) crt1 is not LCDA, unless bridge is TMDS/LCDA capable (301C) 6182 */ 6183 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 6184 if(!(pSiS->noInternalModes)) { 6185 Bool acceptcustommodes = TRUE; /* Accept user modelines */ 6186 Bool includelcdmodes = TRUE; /* Include modes reported by DDC */ 6187 Bool isfordvi = FALSE; /* Is for digital DVI output */ 6188 Bool fakecrt2modes = FALSE; /* Fake some modes for CRT2 */ 6189 Bool IsForCRT2 = FALSE; 6190 if(pSiS->UseVESA) { 6191 acceptcustommodes = FALSE; 6192 includelcdmodes = FALSE; 6193 } 6194#ifdef SISDUALHEAD /* Dual head is static. Output devices will not change. */ 6195 if(pSiS->DualHeadMode) { 6196 if(!pSiS->SecondHead) { /* CRT2: */ 6197 if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 6198 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 6199 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA))) includelcdmodes = FALSE; 6200 if(pSiS->VBFlags & CRT2_LCD) isfordvi = TRUE; 6201 if(pSiS->VBFlags & CRT2_TV) acceptcustommodes = FALSE; 6202 } else { 6203 if(pSiS->VBFlags & (CRT2_TV|CRT2_LCD)) { 6204 acceptcustommodes = FALSE; 6205 includelcdmodes = FALSE; 6206 fakecrt2modes = TRUE; 6207 } 6208 } 6209 } else { 6210 acceptcustommodes = FALSE; 6211 includelcdmodes = FALSE; 6212 if(pSiS->VBFlags & (CRT2_TV|CRT2_LCD)) { 6213 fakecrt2modes = TRUE; 6214 } 6215 } 6216 clockRanges->interlaceAllowed = FALSE; 6217 IsForCRT2 = TRUE; 6218 } else { /* CRT1: */ 6219 if(pSiS->VBFlags & CRT1_LCDA) { 6220 if(!(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 6221 acceptcustommodes = FALSE; 6222 includelcdmodes = FALSE; 6223 fakecrt2modes = TRUE; 6224 /* Will handle i-lace in mode-switching code */ 6225 } else { 6226 isfordvi = TRUE; 6227 /* Don't allow i-lace modes */ 6228 clockRanges->interlaceAllowed = FALSE; 6229 } 6230 } else { 6231 includelcdmodes = FALSE; 6232 } 6233 } 6234 } else 6235#endif 6236#ifdef SISMERGED /* MergedFB mode is not static. Output devices may change. */ 6237 if(pSiS->MergedFB) { 6238 if(pSiS->VBFlags & CRT1_LCDA) { 6239 if(!(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 6240 acceptcustommodes = FALSE; 6241 includelcdmodes = FALSE; 6242 fakecrt2modes = TRUE; 6243 /* Will handle i-lace in mode-switching code */ 6244 } else { 6245 isfordvi = TRUE; 6246 /* Don't allow i-lace custom modes */ 6247 clockRanges->interlaceAllowed = FALSE; 6248 } 6249 } else { 6250 includelcdmodes = FALSE; 6251 } 6252 } else 6253#endif /* Mirror mode is not static. Output devices may change. */ 6254 if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 6255 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 6256 if(!(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 6257 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA))) includelcdmodes = FALSE; 6258 if(pSiS->VBFlags & CRT2_LCD) isfordvi = TRUE; 6259 } else { 6260 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA|CRT1_LCDA))) includelcdmodes = FALSE; 6261 if(pSiS->VBFlags & (CRT2_LCD|CRT1_LCDA)) isfordvi = TRUE; 6262 } 6263 if((!(pSiS->VBFlags & DISPTYPE_CRT1)) && (!(pSiS->VBFlags & CRT1_LCDA))) { 6264 IsForCRT2 = TRUE; 6265 } 6266 /* Allow user modes, even if CRT2 is TV. Will be filtered through ValidMode(); 6267 * leaving the user modes here might have the advantage that such a mode, if 6268 * it matches in resolution with a supported TV mode, allows us to drive eg. 6269 * non standard panels, and still permits switching to TV. This mode will be 6270 * "mapped" to a supported mode of identical resolution for TV. All this is 6271 * taken care of by ValidMode() and ModeInit()/PresetMode(). 6272 */ 6273 } else { 6274 if(pSiS->VBFlags & (CRT2_TV|CRT2_LCD)) { 6275 acceptcustommodes = FALSE; 6276 includelcdmodes = FALSE; 6277 if(!(pSiS->VBFlags & DISPTYPE_CRT1)) { 6278 fakecrt2modes = TRUE; 6279 IsForCRT2 = TRUE; 6280 } 6281 } 6282 } 6283 } else if(pSiS->VBFlags & (CRT2_ENABLE | CRT1_LCDA)) { 6284 acceptcustommodes = FALSE; 6285 includelcdmodes = FALSE; 6286 if((pSiS->VBFlags & CRT1_LCDA) || (!(pSiS->VBFlags & DISPTYPE_CRT1))) { 6287 fakecrt2modes = TRUE; 6288 IsForCRT2 = TRUE; 6289 } 6290 } else { 6291 includelcdmodes = FALSE; 6292 } 6293 /* Ignore interlace, mode switching code will handle this */ 6294 6295 pSiS->HaveCustomModes = FALSE; 6296 if(SiSMakeOwnModeList(pScrn, acceptcustommodes, includelcdmodes, 6297 isfordvi, &pSiS->HaveCustomModes, FALSE /*fakecrt2modes*/, IsForCRT2)) { 6298 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6299 "Replaced %s mode list with built-in modes\n", 6300 pSiS->HaveCustomModes ? "default" : "entire"); 6301 if(pSiS->VGAEngine == SIS_315_VGA) { 6302 int UseWide = pSiS->SiS_Pr->SiS_UseWide; 6303 if(IsForCRT2) UseWide = pSiS->SiS_Pr->SiS_UseWideCRT2; 6304 if((!IsForCRT2) || (pSiS->VBFlags2 & VB2_SISVGA2BRIDGE)) { 6305 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6306 "Using %s widescreen modes for CRT%d VGA devices\n", 6307 UseWide ? "real" : "fake", IsForCRT2 ? 2 : 1); 6308 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6309 "\tUse option \"ForceCRT%dVGAAspect\" to overrule\n", 6310 IsForCRT2 ? 2 : 1); 6311 } 6312 } 6313#ifdef TWDEBUG 6314 pScrn->modes = pScrn->monitor->Modes; 6315 xf86PrintModes(pScrn); 6316 pScrn->modes = NULL; 6317#endif 6318 } else { 6319 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 6320 "Building list of built-in modes failed, using server defaults\n"); 6321 } 6322 } else { 6323 pSiS->HaveCustomModes = TRUE; 6324 } 6325 } 6326 6327 /* Add our built-in hi-res and TV modes on the 6326 */ 6328 if(pSiS->Chipset == PCI_CHIP_SIS6326) { 6329 if(pScrn->bitsPerPixel == 8) { 6330 SiS6326SIS1600x1200_60Mode.next = pScrn->monitor->Modes; 6331 pScrn->monitor->Modes = &SiS6326SIS1600x1200_60Mode; 6332 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6333 "Adding mode \"SIS1600x1200-60\" (depth 8 only)\n"); 6334 } 6335 if(pScrn->bitsPerPixel <= 16) { 6336 SiS6326SIS1280x1024_75Mode.next = pScrn->monitor->Modes; 6337 pScrn->monitor->Modes = &SiS6326SIS1280x1024_75Mode; 6338 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6339 "Adding mode \"SIS1280x1024-75\" (depths 8, 15 and 16 only)\n"); 6340 } 6341 if((pSiS->SiS6326Flags & SIS6326_HASTV) && 6342 (pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 6343 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6344 "Adding %s TV modes to mode list:\n", 6345 (pSiS->SiS6326Flags & SIS6326_TVPAL) ? "PAL" : "NTSC"); 6346 if(pSiS->SiS6326Flags & SIS6326_TVPAL) { 6347 SiS6326PAL800x600Mode.next = pScrn->monitor->Modes; 6348 pScrn->monitor->Modes = &SiS6326PAL640x480Mode; 6349 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6350 "\t\"PAL800x600\" \"PAL800x600U\" \"PAL720x540\" \"PAL640x480\"\n"); 6351 } else { 6352 SiS6326NTSC640x480Mode.next = pScrn->monitor->Modes; 6353 pScrn->monitor->Modes = &SiS6326NTSC640x400Mode; 6354 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6355 "\t\"NTSC640x480\" \"NTSC640x480U\" \"NTSC640x400\"\n"); 6356 } 6357 } 6358 } 6359 6360 /* If there is no HSync or VRefresh data for the monitor, 6361 * derive it from DDC data. Essentially done by common layer 6362 * since 4.3.99.14, but this is not usable since it is done 6363 * too late (in ValidateModes()). 6364 * Addendum: I overrule the ranges now in any case unless 6365 * it would affect a CRT output device or DDC data is available. 6366 * Hence, for LCD(A) and TV, we always get proper ranges. This 6367 * is entirely harmless. However, option "NoOverruleRanges" will 6368 * disable this behavior. 6369 * This should "fix" the - by far - most common configuration 6370 * mistakes. 6371 */ 6372 6373 crt1freqoverruled = FALSE; 6374 6375 fromDDC = FALSE; 6376 if((pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6377 if((pScrn->monitor->nHsync <= 0) && (pScrn->monitor->DDC)) { 6378 SiSSetSyncRangeFromEdid(pScrn, 1); 6379 if(pScrn->monitor->nHsync > 0) { 6380 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subshstr, 6381#ifdef SISDUALHEAD 6382 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6383#endif 6384 pSiS->CRT1off ? 2 : 1); 6385 fromDDC = TRUE; 6386 } 6387 } 6388 if((pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6389 if(SiSAllowSyncOverride(pSiS, fromDDC)) { 6390 Bool HaveNoRanges = (pScrn->monitor->nHsync <= 0); 6391 /* Set sane ranges for LCD and TV 6392 * (our strict checking will filter out invalid ones anyway) 6393 */ 6394 if((crt1freqoverruled = CheckAndOverruleH(pScrn, pScrn->monitor))) { 6395 xf86DrvMsg(pScrn->scrnIndex, X_INFO, saneh, 6396 HaveNoRanges ? "missing" : "bogus", 6397#ifdef SISDUALHEAD 6398 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6399#endif 6400 pSiS->CRT1off ? 2 : 1); 6401 } 6402 } 6403 } 6404 } 6405 6406 fromDDC = FALSE; 6407 if((pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6408 if((pScrn->monitor->nVrefresh <= 0) && (pScrn->monitor->DDC)) { 6409 SiSSetSyncRangeFromEdid(pScrn, 0); 6410 if(pScrn->monitor->nVrefresh > 0) { 6411 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subsvstr, 6412#ifdef SISDUALHEAD 6413 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6414#endif 6415 pSiS->CRT1off ? 2 : 1); 6416 fromDDC = TRUE; 6417 } 6418 } 6419 if((pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6420 if(SiSAllowSyncOverride(pSiS, fromDDC)) { 6421 Bool HaveNoRanges = (pScrn->monitor->nVrefresh <= 0); 6422 /* Set sane ranges for LCD and TV */ 6423 if((crt1freqoverruled = CheckAndOverruleV(pScrn, pScrn->monitor))) { 6424 xf86DrvMsg(pScrn->scrnIndex, X_INFO, sanev, 6425 HaveNoRanges ? "missing" : "bogus", 6426#ifdef SISDUALHEAD 6427 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6428#endif 6429 pSiS->CRT1off ? 2 : 1); 6430 } 6431 } 6432 } 6433 } 6434 6435 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 6436 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6437 "\"Unknown reason\" in the following list means that the mode\n"); 6438 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6439 "is not supported on the chipset/bridge/current output device.\n"); 6440 } 6441 6442 /* 6443 * xf86ValidateModes will check that the mode HTotal and VTotal values 6444 * don't exceed the chipset's limit if pScrn->maxHValue and 6445 * pScrn->maxVValue are set. Since our SISValidMode() already takes 6446 * care of this, we don't worry about setting them here. 6447 */ 6448 6449 /* Select valid modes from those available */ 6450 /* 6451 * Assuming min pitch 256, min height 128 6452 */ 6453 { 6454 int minpitch, maxpitch, minheight, maxheight; 6455 pointer backupddc = pScrn->monitor->DDC; 6456 6457 minpitch = 256; 6458 minheight = 128; 6459 switch(pSiS->VGAEngine) { 6460 case SIS_OLD_VGA: 6461 case SIS_530_VGA: 6462 maxpitch = 2040; 6463 maxheight = 2048; 6464 break; 6465 case SIS_300_VGA: 6466 case SIS_315_VGA: 6467 maxpitch = 4088; 6468 maxheight = 4096; 6469 break; 6470 default: 6471 maxpitch = 2048; 6472 maxheight = 2048; 6473 break; 6474 } 6475 6476#ifdef SISMERGED 6477 pSiS->CheckForCRT2 = FALSE; 6478#endif 6479 6480 /* Suppress bogus DDC warning */ 6481 if(crt1freqoverruled) pScrn->monitor->DDC = NULL; 6482 6483 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 6484 pScrn->display->modes, clockRanges, NULL, 6485 minpitch, maxpitch, 6486 pScrn->bitsPerPixel * 8, 6487 minheight, maxheight, 6488 pScrn->display->virtualX, 6489 pScrn->display->virtualY, 6490 pSiS->maxxfbmem, 6491 LOOKUP_BEST_REFRESH); 6492 6493 pScrn->monitor->DDC = backupddc; 6494 } 6495 6496 if(i == -1) { 6497 SISErrorLog(pScrn, "xf86ValidateModes() error\n"); 6498 goto my_error_1; 6499 } 6500 6501 /* Check the virtual screen against the available memory */ 6502 { 6503 ULong memreq = (pScrn->virtualX * ((pScrn->bitsPerPixel + 7) / 8)) * pScrn->virtualY; 6504 6505 if(memreq > pSiS->maxxfbmem) { 6506 SISErrorLog(pScrn, 6507 "Virtual screen too big for memory; %ldK needed, %ldK available\n", 6508 memreq/1024, pSiS->maxxfbmem/1024); 6509 goto my_error_1; 6510 } 6511 } 6512 6513 /* Dual Head: 6514 * -) Go through mode list and mark all those modes as bad, 6515 * which are unsuitable for dual head mode. 6516 * -) Find the highest used pixelclock on the master head. 6517 */ 6518#ifdef SISDUALHEAD 6519 if((pSiS->DualHeadMode) && (!pSiS->SecondHead)) { 6520 6521 pSiSEnt->maxUsedClock = 0; 6522 6523 if((p = first = pScrn->modes)) { 6524 6525 do { 6526 6527 n = p->next; 6528 6529 /* Modes that require the bridge to operate in SlaveMode 6530 * are not suitable for Dual Head mode. 6531 */ 6532 if( (pSiS->VGAEngine == SIS_300_VGA) && 6533 ( (strcmp(p->name, "320x200") == 0) || 6534 (strcmp(p->name, "320x240") == 0) || 6535 (strcmp(p->name, "400x300") == 0) || 6536 (strcmp(p->name, "512x384") == 0) || 6537 (strcmp(p->name, "640x400") == 0) ) ) { 6538 p->status = MODE_BAD; 6539 xf86DrvMsg(pScrn->scrnIndex, X_INFO, notsuitablestr, p->name, "dual head"); 6540 } 6541 6542 /* Search for the highest clock on first head in order to calculate 6543 * max clock for second head (CRT1) 6544 */ 6545 if((p->status == MODE_OK) && (p->Clock > pSiSEnt->maxUsedClock)) { 6546 pSiSEnt->maxUsedClock = p->Clock; 6547 } 6548 6549 p = n; 6550 6551 } while (p != NULL && p != first); 6552 6553 } 6554 } 6555#endif 6556 6557 /* Prune the modes marked as invalid */ 6558 xf86PruneDriverModes(pScrn); 6559 6560 if(i == 0 || pScrn->modes == NULL) { 6561 SISErrorLog(pScrn, "No valid modes found - check VertRefresh/HorizSync\n"); 6562 goto my_error_1; 6563 } 6564 6565 xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 6566 6567 /* Set the current mode to the first in the list */ 6568 pScrn->currentMode = pScrn->modes; 6569 6570 /* Copy to CurrentLayout */ 6571 pSiS->CurrentLayout.mode = pScrn->currentMode; 6572 pSiS->CurrentLayout.displayWidth = pScrn->displayWidth; 6573 pSiS->CurrentLayout.displayHeight = pScrn->virtualY; 6574 6575#ifdef SISMERGED 6576 if(pSiS->MergedFB) { 6577 xf86DrvMsg(pScrn->scrnIndex, X_INFO, modesforstr, 1); 6578 } 6579#endif 6580 6581 /* Print the list of modes being used */ 6582 { 6583 Bool usemyprint = FALSE; 6584 6585#ifdef SISDUALHEAD 6586 if(pSiS->DualHeadMode) { 6587 if(pSiS->SecondHead) { 6588 if(pSiS->VBFlags & CRT1_LCDA) usemyprint = TRUE; 6589 } else { 6590 if(pSiS->VBFlags & (CRT2_LCD | CRT2_TV)) usemyprint = TRUE; 6591 } 6592 } else 6593#endif 6594#ifdef SISMERGED 6595 if(pSiS->MergedFB) { 6596 if(pSiS->VBFlags & CRT1_LCDA) usemyprint = TRUE; 6597 } else 6598#endif 6599 { 6600 if( (pSiS->VBFlags & (CRT2_LCD | CRT2_TV)) && 6601 (!(pSiS->VBFlags & DISPTYPE_DISP1)) ) 6602 usemyprint = TRUE; 6603 } 6604 6605 if(usemyprint) { 6606 SiSPrintModes(pScrn); 6607 } else { 6608 xf86PrintModes(pScrn); 6609 } 6610 } 6611 6612#ifdef SISMERGED 6613 if(pSiS->MergedFB) { 6614 Bool acceptcustommodes = TRUE; 6615 Bool includelcdmodes = TRUE; 6616 Bool isfordvi = FALSE; 6617 Bool fakecrt2modes = FALSE; 6618 6619 xf86DrvMsg(pScrn->scrnIndex, X_INFO, crtsetupstr, 2); 6620 6621 clockRanges->next = NULL; 6622 clockRanges->minClock = pSiS->MinClock; 6623 clockRanges->maxClock = SiSMemBandWidth(pSiS->CRT2pScrn, TRUE); 6624 clockRanges->clockIndex = -1; 6625 clockRanges->interlaceAllowed = FALSE; 6626 clockRanges->doubleScanAllowed = FALSE; 6627 if(pSiS->VGAEngine == SIS_315_VGA) { 6628 clockRanges->doubleScanAllowed = TRUE; 6629 } 6630 6631 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock for CRT2 is %d MHz\n", 6632 clockRanges->minClock / 1000); 6633 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Max pixel clock for CRT2 is %d MHz\n", 6634 clockRanges->maxClock / 1000); 6635 6636 if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 6637 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 6638 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA))) includelcdmodes = FALSE; 6639 if(pSiS->VBFlags & CRT2_LCD) isfordvi = TRUE; 6640 /* See above for a remark on handling CRT2 = TV */ 6641 } else { 6642 if(pSiS->VBFlags & (CRT2_LCD|CRT2_TV)) { 6643 includelcdmodes = FALSE; 6644 acceptcustommodes = FALSE; 6645 fakecrt2modes = TRUE; 6646 } 6647 } 6648 } else { 6649 includelcdmodes = FALSE; 6650 acceptcustommodes = FALSE; 6651 if(pSiS->VBFlags & (CRT2_LCD|CRT2_TV)) { 6652 fakecrt2modes = TRUE; 6653 } 6654 } 6655 6656 pSiS->HaveCustomModes2 = FALSE; 6657 if(!SiSMakeOwnModeList(pSiS->CRT2pScrn, acceptcustommodes, includelcdmodes, 6658 isfordvi, &pSiS->HaveCustomModes2, FALSE /* fakecrt2modes */, TRUE )) { 6659 6660 SISErrorLog(pScrn, "Building list of built-in modes for CRT2 failed, %s\n", 6661 mergeddisstr); 6662 SiSFreeCRT2Structs(pSiS); 6663 pSiS->MergedFB = FALSE; 6664 6665 } else { 6666 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6667 "Replaced %s mode list for CRT2 with built-in modes\n", 6668 pSiS->HaveCustomModes2 ? "default" : "entire"); 6669 if((pSiS->VGAEngine == SIS_315_VGA) && (pSiS->VBFlags2 & VB2_SISVGA2BRIDGE)) { 6670 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6671 "Using %s widescreen modes for CRT2 VGA devices\n", 6672 pSiS->SiS_Pr->SiS_UseWideCRT2 ? "real" : "fake"); 6673 } else pSiS->SiS_Pr->SiS_UseWideCRT2 = 0; 6674 } 6675 6676 } 6677 6678 if(pSiS->MergedFB) { 6679 6680 pointer backupddc; 6681 6682 crt2freqoverruled = FALSE; 6683 6684 fromDDC = FALSE; 6685 if((pSiS->CRT2pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6686 if((pSiS->CRT2pScrn->monitor->nHsync <= 0) && (pSiS->CRT2pScrn->monitor->DDC)) { 6687 SiSSetSyncRangeFromEdid(pSiS->CRT2pScrn, 1); 6688 if(pSiS->CRT2pScrn->monitor->nHsync > 0) { 6689 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subshstr, 2); 6690 fromDDC = TRUE; 6691 } 6692 } 6693 if((pSiS->CRT2pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6694 if( (pSiS->VBFlags & CRT2_TV) || 6695 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC)) ) { 6696 Bool HaveNoRanges = (pSiS->CRT2pScrn->monitor->nHsync <= 0); 6697 /* Set sane ranges for LCD and TV */ 6698 if((crt2freqoverruled = CheckAndOverruleH(pScrn, pSiS->CRT2pScrn->monitor))) { 6699 xf86DrvMsg(pScrn->scrnIndex, X_INFO, saneh, 6700 HaveNoRanges ? "missing" : "bogus", 2); 6701 } 6702 } 6703 } 6704 } 6705 6706 fromDDC = FALSE; 6707 if((pSiS->CRT2pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6708 if((pSiS->CRT2pScrn->monitor->nVrefresh <= 0) && (pSiS->CRT2pScrn->monitor->DDC)) { 6709 SiSSetSyncRangeFromEdid(pSiS->CRT2pScrn, 0); 6710 if(pSiS->CRT2pScrn->monitor->nVrefresh > 0) { 6711 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subsvstr, 2); 6712 fromDDC = TRUE; 6713 } 6714 } 6715 if((pSiS->CRT2pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6716 if( (pSiS->VBFlags & CRT2_TV) || 6717 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC)) ) { 6718 Bool HaveNoRanges = (pSiS->CRT2pScrn->monitor->nVrefresh <= 0); 6719 /* Set sane ranges for LCD and TV */ 6720 if((crt2freqoverruled = CheckAndOverruleV(pScrn, pSiS->CRT2pScrn->monitor))) { 6721 xf86DrvMsg(pScrn->scrnIndex, X_INFO, sanev, 6722 HaveNoRanges ? "missing" : "bogus", 2); 6723 } 6724 } 6725 } 6726 } 6727 6728 backupddc = pSiS->CRT2pScrn->monitor->DDC; 6729 6730 /* Suppress bogus DDC warning */ 6731 if(crt2freqoverruled) pSiS->CRT2pScrn->monitor->DDC = NULL; 6732 6733 pSiS->CheckForCRT2 = TRUE; 6734 6735 i = xf86ValidateModes(pSiS->CRT2pScrn, pSiS->CRT2pScrn->monitor->Modes, 6736 pSiS->CRT2pScrn->display->modes, clockRanges, 6737 NULL, 256, 4088, 6738 pSiS->CRT2pScrn->bitsPerPixel * 8, 128, 4096, 6739 pScrn->display->virtualX ? pScrn->virtualX : 0, 6740 pScrn->display->virtualY ? pScrn->virtualY : 0, 6741 pSiS->maxxfbmem, 6742 LOOKUP_BEST_REFRESH); 6743 6744 pSiS->CheckForCRT2 = FALSE; 6745 pSiS->CRT2pScrn->monitor->DDC = backupddc; 6746 6747 if(i == -1) { 6748 SISErrorLog(pScrn, "xf86ValidateModes() error, %s.\n", mergeddisstr); 6749 SiSFreeCRT2Structs(pSiS); 6750 pSiS->MergedFB = FALSE; 6751 } 6752 6753 } 6754 6755 if(pSiS->MergedFB) { 6756 6757 if((p = first = pSiS->CRT2pScrn->modes)) { 6758 do { 6759 n = p->next; 6760 if( (pSiS->VGAEngine == SIS_300_VGA) && 6761 ( (strcmp(p->name, "320x200") == 0) || 6762 (strcmp(p->name, "320x240") == 0) || 6763 (strcmp(p->name, "400x300") == 0) || 6764 (strcmp(p->name, "512x384") == 0) || 6765 (strcmp(p->name, "640x400") == 0) ) ) { 6766 p->status = MODE_BAD; 6767 xf86DrvMsg(pScrn->scrnIndex, X_INFO, notsuitablestr, p->name, "MergedFB"); 6768 } 6769 p = n; 6770 } while (p != NULL && p != first); 6771 } 6772 6773 xf86PruneDriverModes(pSiS->CRT2pScrn); 6774 6775 if(i == 0 || pSiS->CRT2pScrn->modes == NULL) { 6776 SISErrorLog(pScrn, "No valid modes found for CRT2; %s\n", mergeddisstr); 6777 SiSFreeCRT2Structs(pSiS); 6778 pSiS->MergedFB = FALSE; 6779 } 6780 6781 } 6782 6783 if(pSiS->MergedFB) { 6784 6785 xf86SetCrtcForModes(pSiS->CRT2pScrn, INTERLACE_HALVE_V); 6786 6787 xf86DrvMsg(pScrn->scrnIndex, X_INFO, modesforstr, 2); 6788 6789 if(pSiS->VBFlags & (CRT2_LCD | CRT2_TV)) { 6790 SiSPrintModes(pSiS->CRT2pScrn); 6791 } else { 6792 xf86PrintModes(pSiS->CRT2pScrn); 6793 } 6794 6795 pSiS->CRT1Modes = pScrn->modes; 6796 pSiS->CRT1CurrentMode = pScrn->currentMode; 6797 6798 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MergedFB: Generating mode list\n"); 6799 6800 pScrn->modes = SiSGenerateModeList(pScrn, pSiS->MetaModes, 6801 pSiS->CRT1Modes, pSiS->CRT2pScrn->modes, 6802 pSiS->CRT2Position); 6803 6804 if(!pScrn->modes) { 6805 6806 SISErrorLog(pScrn, "Failed to parse MetaModes or no modes found. %s.\n", 6807 mergeddisstr); 6808 SiSFreeCRT2Structs(pSiS); 6809 pScrn->modes = pSiS->CRT1Modes; 6810 pSiS->CRT1Modes = NULL; 6811 pSiS->MergedFB = FALSE; 6812 6813 } 6814 6815 } 6816 6817 if(pSiS->MergedFB) { 6818 6819 /* If no virtual dimension was given by the user, 6820 * calculate a sane one now. Adapts pScrn->virtualX, 6821 * pScrn->virtualY and pScrn->displayWidth. 6822 */ 6823 SiSRecalcDefaultVirtualSize(pScrn); 6824 6825 pScrn->modes = pScrn->modes->next; /* We get the last from GenerateModeList(), skip to first */ 6826 pScrn->currentMode = pScrn->modes; 6827 6828 /* Update CurrentLayout */ 6829 pSiS->CurrentLayout.mode = pScrn->currentMode; 6830 pSiS->CurrentLayout.displayWidth = pScrn->displayWidth; 6831 pSiS->CurrentLayout.displayHeight = pScrn->virtualY; 6832 6833 } 6834#endif 6835 6836 /* Set display resolution */ 6837#ifdef SISMERGED 6838 if(pSiS->MergedFB) { 6839 SiSMergedFBSetDpi(pScrn, pSiS->CRT2pScrn, pSiS->CRT2Position); 6840 } else 6841#endif 6842 xf86SetDpi(pScrn, 0, 0); 6843 6844 /* Load fb module */ 6845 switch(pScrn->bitsPerPixel) { 6846 case 8: 6847 case 16: 6848 case 24: 6849 case 32: 6850 if(!xf86LoadSubModule(pScrn, "fb")) { 6851 SISErrorLog(pScrn, "Failed to load fb module"); 6852 goto my_error_1; 6853 } 6854 break; 6855 default: 6856 SISErrorLog(pScrn, "Unsupported framebuffer bpp (%d)\n", pScrn->bitsPerPixel); 6857 goto my_error_1; 6858 } 6859 6860 /* Load XAA/EXA (if needed) */ 6861 if(!pSiS->NoAccel) { 6862#ifdef SIS_USE_XAA 6863 if(!pSiS->useEXA) { 6864 if (!xf86LoadSubModule(pScrn, "xaa")) { 6865 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6866 "Falling back to shadowfb\n"); 6867 pSiS->NoAccel = 1; 6868 pSiS->ShadowFB = 1; 6869 } 6870 } 6871#endif 6872#ifdef SIS_USE_EXA 6873 if(pSiS->useEXA) { 6874 XF86ModReqInfo req; 6875 int errmaj, errmin; 6876 6877 memset(&req, 0, sizeof(req)); 6878 req.majorversion = 2; 6879 req.minorversion = 0; 6880 if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, &req, 6881 &errmaj, &errmin)) { 6882 LoaderErrorMsg(NULL, "exa", errmaj, errmin); 6883 goto my_error_1; 6884 } 6885 } 6886#endif 6887 } 6888 6889 /* Load shadowfb (if needed) */ 6890 if(pSiS->ShadowFB) { 6891 if(!xf86LoadSubModule(pScrn, "shadowfb")) { 6892 SISErrorLog(pScrn, "Could not load shadowfb module\n"); 6893 goto my_error_1; 6894 } 6895 } 6896 6897 /* Load the dri and glx modules if requested. */ 6898#ifdef SISDRI 6899 if(pSiS->loadDRI) { 6900 if(!xf86LoaderCheckSymbol("DRIScreenInit")) { 6901 if(xf86LoadSubModule(pScrn, "dri")) { 6902 if(!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) { 6903 if(!xf86LoadSubModule(pScrn, "glx")) { 6904 SISErrorLog(pScrn, "Failed to load glx module\n"); 6905 } 6906 } 6907 } else { 6908 SISErrorLog(pScrn, "Failed to load dri module\n"); 6909 } 6910 } 6911 } 6912#endif 6913 6914 /* Now load and initialize VBE module for VESA mode switching */ 6915 pSiS->UseVESA = 0; 6916 if(pSiS->VESA == 1) { 6917 SiS_LoadInitVBE(pScrn); 6918 if(pSiS->pVbe) { 6919 VbeInfoBlock *vbe; 6920 if((vbe = VBEGetVBEInfo(pSiS->pVbe))) { 6921 pSiS->vesamajor = (unsigned)(vbe->VESAVersion >> 8); 6922 pSiS->vesaminor = vbe->VESAVersion & 0xff; 6923 SiSBuildVesaModeList(pScrn, pSiS->pVbe, vbe); 6924 VBEFreeVBEInfo(vbe); 6925 pSiS->UseVESA = 1; 6926 } else { 6927 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 6928 "Failed to read VBE Info Block\n"); 6929 } 6930 } 6931 if(pSiS->UseVESA == 0) { 6932 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 6933 "VESA mode switching disabled.\n"); 6934 } 6935 } 6936 6937 if(pSiS->pVbe) { 6938 vbeFree(pSiS->pVbe); 6939 pSiS->pVbe = NULL; 6940 } 6941 6942#ifdef SISDUALHEAD 6943 xf86SetPrimInitDone(pScrn->entityList[0]); 6944#endif 6945 6946 sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); 6947 6948 if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); 6949 pSiS->pInt = NULL; 6950 6951 if(pSiS->VGAEngine == SIS_315_VGA) { 6952 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTXVGAMMA1; 6953 } 6954 6955#ifdef SISDUALHEAD 6956 if(pSiS->DualHeadMode) { 6957 pSiS->SiS_SD_Flags |= SiS_SD_ISDUALHEAD; 6958 if(pSiS->SecondHead) pSiS->SiS_SD_Flags |= SiS_SD_ISDHSECONDHEAD; 6959 else pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTXVGAMMA1); 6960#ifdef PANORAMIX 6961 if(!noPanoramiXExtension) { 6962 pSiS->SiS_SD_Flags |= SiS_SD_ISDHXINERAMA; 6963 /* pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTXVGAMMA1); */ 6964 } 6965#endif 6966 } 6967#endif 6968 6969#ifdef SISMERGED 6970 if(pSiS->MergedFB) pSiS->SiS_SD_Flags |= SiS_SD_ISMERGEDFB; 6971#endif 6972 6973 /* Try to determine if this is a laptop */ 6974 /* (only used for SiSCtrl visualisations) */ 6975 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPLTFLAG; 6976 pSiS->SiS_SD2_Flags &= ~SiS_SD2_ISLAPTOP; 6977 if(pSiS->detectedCRT2Devices & CRT2_LCD) { 6978 if(pSiS->VBFlags2 & (VB2_SISLVDSBRIDGE | VB2_LVDS | VB2_30xBDH)) { 6979 /* 1. By bridge type: LVDS in 99% of all cases; 6980 * exclude unusual setups like Barco projectors 6981 * and parallel flat panels. TODO: Exclude 6982 * Sony W1, V1. 6983 */ 6984 if((pSiS->SiS_Pr->SiS_CustomT != CUT_BARCO1366) && 6985 (pSiS->SiS_Pr->SiS_CustomT != CUT_BARCO1024) && 6986 (pSiS->SiS_Pr->SiS_CustomT != CUT_PANEL848) && 6987 (pSiS->SiS_Pr->SiS_CustomT != CUT_PANEL856) && 6988 (pSiS->SiS_Pr->SiS_CustomT != CUT_AOP8060) && 6989 ( (pSiS->ChipType != SIS_550) || 6990 (!pSiS->DSTN && !pSiS->FSTN) ) ) { 6991 pSiS->SiS_SD2_Flags |= SiS_SD2_ISLAPTOP; 6992 } 6993 } else if((pSiS->VBFlags2 & (VB2_301 | VB2_301C)) && 6994 (pSiS->VBLCDFlags & (VB_LCD_1280x960 | 6995 VB_LCD_1400x1050 | 6996 VB_LCD_1024x600 | 6997 VB_LCD_1280x800 | 6998 VB_LCD_1280x854))) { 6999 /* 2. By (odd) LCD resolutions on TMDS bridges 7000 * (eg Averatec). TODO: Exclude IBM Netvista. 7001 */ 7002 pSiS->SiS_SD2_Flags |= SiS_SD2_ISLAPTOP; 7003 } 7004 } 7005 7006 if(pSiS->enablesisctrl) pSiS->SiS_SD_Flags |= SiS_SD_ENABLED; 7007 7008 pSiS->currentModeLast = pScrn->currentMode; 7009 pSiS->VBFlagsInit = pSiS->VBFlags; 7010 7011 return TRUE; 7012 7013 /* ---- */ 7014 7015my_error_1: 7016 sisRestoreExtRegisterLock(pSiS, srlockReg, crlockReg); 7017my_error_0: 7018#ifdef SISDUALHEAD 7019 if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; 7020#endif 7021 if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); 7022 pSiS->pInt = NULL; 7023 SISFreeRec(pScrn); 7024 return FALSE; 7025} 7026 7027/* 7028 * Map I/O port area for non-PC platforms 7029 */ 7030#ifdef SIS_NEED_MAP_IOP 7031static Bool 7032SISMapIOPMem(ScrnInfoPtr pScrn) 7033{ 7034 SISPtr pSiS = SISPTR(pScrn); 7035#ifdef SISDUALHEAD 7036 SISEntPtr pSiSEnt = pSiS->entityPrivate; 7037 7038 if(pSiS->DualHeadMode) { 7039 pSiSEnt->MapCountIOPBase++; 7040 if(!(pSiSEnt->IOPBase)) { 7041 /* Only map if not mapped previously */ 7042#ifndef XSERVER_LIBPCIACCESS 7043 pSiSEnt->IOPBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7044 pSiS->PciTag, pSiS->IOPAddress, 128); 7045#else 7046 { 7047 void **result = (void **)&pSiSEnt->IOPBase; 7048 int err = pci_device_map_range(pSiS->PciInfo, 7049 pSiS->IOPAddress, 7050 128, 7051 PCI_DEV_MAP_FLAG_WRITABLE, 7052 result); 7053 7054 if (err) { 7055 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7056 "Unable to map IO aperture. %s (%d)\n", 7057 strerror (err), err); 7058 } 7059 } 7060#endif 7061 } 7062 pSiS->IOPBase = pSiSEnt->IOPBase; 7063 } else 7064#endif 7065#ifndef XSERVER_LIBPCIACCESS 7066 pSiS->IOPBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7067 pSiS->PciTag, pSiS->IOPAddress, 128); 7068#else 7069 { 7070 void **result = (void **)&pSiS->IOPBase; 7071 int err = pci_device_map_range(pSiS->PciInfo, 7072 pSiS->IOPAddress, 7073 128, 7074 PCI_DEV_MAP_FLAG_WRITABLE, 7075 result); 7076 7077 if (err) { 7078 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7079 "Unable to map IO aperture. %s (%d)\n", 7080 strerror (err), err); 7081 } 7082 } 7083#endif 7084 if(pSiS->IOPBase == NULL) { 7085 SISErrorLog(pScrn, "Could not map I/O port area\n"); 7086 return FALSE; 7087 } 7088 7089 return TRUE; 7090} 7091 7092static Bool 7093SISUnmapIOPMem(ScrnInfoPtr pScrn) 7094{ 7095 SISPtr pSiS = SISPTR(pScrn); 7096#ifdef SISDUALHEAD 7097 SISEntPtr pSiSEnt = pSiS->entityPrivate;; 7098#endif 7099 7100/* In dual head mode, we must not unmap if the other head still 7101 * assumes memory as mapped 7102 */ 7103#ifdef SISDUALHEAD 7104 if(pSiS->DualHeadMode) { 7105 if(pSiSEnt->MapCountIOPBase) { 7106 pSiSEnt->MapCountIOPBase--; 7107 if((pSiSEnt->MapCountIOPBase == 0) || (pSiSEnt->forceUnmapIOPBase)) { 7108 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOPBase, 2048); 7109 pSiSEnt->IOPBase = NULL; 7110 pSiSEnt->MapCountIOPBase = 0; 7111 pSiSEnt->forceUnmapIOPBase = FALSE; 7112 } 7113 pSiS->IOPBase = NULL; 7114 } 7115 } else { 7116#endif 7117 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOPBase, 2048); 7118 pSiS->IOPBase = NULL; 7119#ifdef SISDUALHEAD 7120 } 7121#endif 7122 return TRUE; 7123} 7124#endif 7125 7126/* 7127 * Map the framebuffer and MMIO memory 7128 */ 7129 7130static Bool 7131SISMapMem(ScrnInfoPtr pScrn) 7132{ 7133 SISPtr pSiS = SISPTR(pScrn); 7134 int mmioFlags = VIDMEM_MMIO; 7135#ifdef SISDUALHEAD 7136 SISEntPtr pSiSEnt = pSiS->entityPrivate; 7137#endif 7138 7139 /* 7140 * Map IO registers to virtual address space 7141 * (For Alpha, we need to map SPARSE memory, since we need 7142 * byte/short access.) 7143 */ 7144#if defined(__alpha__) 7145 mmioFlags |= VIDMEM_SPARSE; 7146#endif 7147 7148#ifdef SISDUALHEAD 7149 if(pSiS->DualHeadMode) { 7150 pSiSEnt->MapCountIOBase++; 7151 if(!(pSiSEnt->IOBase)) { 7152 /* Only map if not mapped previously */ 7153#ifndef XSERVER_LIBPCIACCESS 7154 pSiSEnt->IOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, 7155 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7156#else 7157 void **result = (void **)&pSiSEnt->IOBase; 7158 int err = pci_device_map_range(pSiS->PciInfo, 7159 pSiS->IOAddress, 7160 (pSiS->mmioSize * 1024), 7161 PCI_DEV_MAP_FLAG_WRITABLE, 7162 result); 7163 7164 if (err) { 7165 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7166 "Unable to map IO aperture. %s (%d)\n", 7167 strerror (err), err); 7168 } 7169#endif 7170 } 7171 pSiS->IOBase = pSiSEnt->IOBase; 7172 } else 7173#endif 7174#ifndef XSERVER_LIBPCIACCESS 7175 pSiS->IOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, 7176 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7177#else 7178 { 7179 void **result = (void **)&pSiS->IOBase; 7180 int err = pci_device_map_range(pSiS->PciInfo, 7181 pSiS->IOAddress, 7182 (pSiS->mmioSize * 1024), 7183 PCI_DEV_MAP_FLAG_WRITABLE, 7184 result); 7185 7186 if (err) { 7187 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7188 "Unable to map IO aperture. %s (%d)\n", 7189 strerror (err), err); 7190 } 7191 } 7192#endif 7193 7194 if(pSiS->IOBase == NULL) { 7195 SISErrorLog(pScrn, "Could not map MMIO area\n"); 7196 return FALSE; 7197 } 7198 7199#ifdef __alpha__ 7200 /* 7201 * for Alpha, we need to map DENSE memory as well, for 7202 * setting CPUToScreenColorExpandBase. 7203 */ 7204#ifdef SISDUALHEAD 7205 if(pSiS->DualHeadMode) { 7206 pSiSEnt->MapCountIOBaseDense++; 7207 if(!(pSiSEnt->IOBaseDense)) { 7208 /* Only map if not mapped previously */ 7209#ifndef XSERVER_LIBPCIACCESS 7210 pSiSEnt->IOBaseDense = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7211 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7212#else 7213 void **result = (void **)&pSiSEnt->IOBaseDense; 7214 int err = pci_device_map_range(pSiS->PciInfo, 7215 pSiS->IOAddress, 7216 (pSiS->mmioSize * 1024), 7217 PCI_DEV_MAP_FLAG_WRITABLE, 7218 result); 7219 7220 if (err) { 7221 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7222 "Unable to map IO dense aperture. %s (%d)\n", 7223 strerror (err), err); 7224 } 7225#endif /* XSERVER_LIBPCIACCESS */ 7226 } 7227 pSiS->IOBaseDense = pSiSEnt->IOBaseDense; 7228 } else { 7229#endif /* SISDUALHEAD */ 7230#ifndef XSERVER_LIBPCIACCESS 7231 pSiS->IOBaseDense = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7232 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7233#else 7234 void **result = (void **)&pSiS->IOBaseDense; 7235 int err = pci_device_map_range(pSiS->PciInfo, 7236 pSiS->IOAddress, 7237 (pSiS->mmioSize * 1024), 7238 PCI_DEV_MAP_FLAG_WRITABLE, 7239 result); 7240 7241 if (err) { 7242 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7243 "Unable to map IO dense aperture. %s (%d)\n", 7244 strerror (err), err); 7245 } 7246#endif /* XSERVER_LIBPCIACCESS */ 7247#ifdef SISDUALHEAD 7248 } 7249#endif 7250 if(pSiS->IOBaseDense == NULL) { 7251 SISErrorLog(pScrn, "Could not map MMIO dense area\n"); 7252 return FALSE; 7253 } 7254#endif /* __alpha__ */ 7255 7256#ifdef SISDUALHEAD 7257 if(pSiS->DualHeadMode) { 7258 pSiSEnt->MapCountFbBase++; 7259 if(!(pSiSEnt->FbBase)) { 7260 /* Only map if not mapped previously */ 7261#ifndef XSERVER_LIBPCIACCESS 7262 pSiSEnt->FbBase = pSiSEnt->RealFbBase = 7263 xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 7264 pSiS->PciTag, (ULong)pSiS->realFbAddress, 7265 pSiS->FbMapSize); 7266#else 7267 int err = pci_device_map_range(pSiS->PciInfo, 7268 (ULong)pSiS->realFbAddress, 7269 pSiS->FbMapSize, 7270 PCI_DEV_MAP_FLAG_WRITABLE | 7271 PCI_DEV_MAP_FLAG_WRITE_COMBINE, 7272 (void *)&pSiSEnt->FbBase); 7273 if (err) { 7274 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7275 "Unable to map FB aperture. %s (%d)\n", 7276 strerror (err), err); 7277 return FALSE; 7278 } 7279 pSiSEnt->RealFbBase = pSiSEnt->FbBase; 7280#endif 7281 } 7282 pSiS->FbBase = pSiS->RealFbBase = pSiSEnt->FbBase; 7283 /* Adapt FbBase (for DHM and SiS76x UMA skipping; dhmOffset is 0 otherwise) */ 7284 pSiS->FbBase += pSiS->dhmOffset; 7285 } else { 7286#endif 7287 7288#ifndef XSERVER_LIBPCIACCESS 7289 pSiS->FbBase = pSiS->RealFbBase = 7290 xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 7291 pSiS->PciTag, (ULong)pSiS->realFbAddress, 7292 pSiS->FbMapSize); 7293#else 7294 int err = pci_device_map_range(pSiS->PciInfo, 7295 (ULong)pSiS->realFbAddress, 7296 pSiS->FbMapSize, 7297 PCI_DEV_MAP_FLAG_WRITABLE | 7298 PCI_DEV_MAP_FLAG_WRITE_COMBINE, 7299 (void *)&pSiS->FbBase); 7300 if (err) { 7301 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7302 "Unable to map FB aperture. %s (%d)\n", 7303 strerror (err), err); 7304 return FALSE; 7305 } 7306 pSiS->RealFbBase = pSiS->FbBase; 7307#endif 7308 pSiS->FbBase += pSiS->dhmOffset; 7309 7310#ifdef SISDUALHEAD 7311 } 7312#endif 7313 7314 if(pSiS->FbBase == NULL) { 7315 SISErrorLog(pScrn, "Could not map framebuffer area\n"); 7316 return FALSE; 7317 } 7318 7319#ifdef TWDEBUG 7320 xf86DrvMsg(0, 0, "Framebuffer mapped to %p\n", pSiS->FbBase); 7321#endif 7322 7323 return TRUE; 7324} 7325 7326 7327/* 7328 * Unmap the framebuffer and MMIO memory. 7329 */ 7330 7331static Bool 7332SISUnmapMem(ScrnInfoPtr pScrn) 7333{ 7334 SISPtr pSiS = SISPTR(pScrn); 7335#ifdef SISDUALHEAD 7336 SISEntPtr pSiSEnt = pSiS->entityPrivate; 7337#endif 7338 7339/* In dual head mode, we must not unmap if the other head still 7340 * assumes memory as mapped 7341 */ 7342#ifdef SISDUALHEAD 7343 if(pSiS->DualHeadMode) { 7344 if(pSiSEnt->MapCountIOBase) { 7345 pSiSEnt->MapCountIOBase--; 7346 if((pSiSEnt->MapCountIOBase == 0) || (pSiSEnt->forceUnmapIOBase)) { 7347 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOBase, (pSiS->mmioSize * 1024)); 7348 pSiSEnt->IOBase = NULL; 7349 pSiSEnt->MapCountIOBase = 0; 7350 pSiSEnt->forceUnmapIOBase = FALSE; 7351 } 7352 pSiS->IOBase = NULL; 7353 } 7354#ifdef __alpha__ 7355 if(pSiSEnt->MapCountIOBaseDense) { 7356 pSiSEnt->MapCountIOBaseDense--; 7357 if((pSiSEnt->MapCountIOBaseDense == 0) || (pSiSEnt->forceUnmapIOBaseDense)) { 7358 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOBaseDense, (pSiS->mmioSize * 1024)); 7359 pSiSEnt->IOBaseDense = NULL; 7360 pSiSEnt->MapCountIOBaseDense = 0; 7361 pSiSEnt->forceUnmapIOBaseDense = FALSE; 7362 } 7363 pSiS->IOBaseDense = NULL; 7364 } 7365#endif /* __alpha__ */ 7366 if(pSiSEnt->MapCountFbBase) { 7367 pSiSEnt->MapCountFbBase--; 7368 if((pSiSEnt->MapCountFbBase == 0) || (pSiSEnt->forceUnmapFbBase)) { 7369 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->RealFbBase, pSiS->FbMapSize); 7370 pSiSEnt->FbBase = pSiSEnt->RealFbBase = NULL; 7371 pSiSEnt->MapCountFbBase = 0; 7372 pSiSEnt->forceUnmapFbBase = FALSE; 7373 7374 } 7375 pSiS->FbBase = pSiS->RealFbBase = NULL; 7376 } 7377 } else { 7378#endif 7379 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOBase, (pSiS->mmioSize * 1024)); 7380 pSiS->IOBase = NULL; 7381#ifdef __alpha__ 7382 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOBaseDense, (pSiS->mmioSize * 1024)); 7383 pSiS->IOBaseDense = NULL; 7384#endif 7385 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->RealFbBase, pSiS->FbMapSize); 7386 pSiS->FbBase = pSiS->RealFbBase = NULL; 7387#ifdef SISDUALHEAD 7388 } 7389#endif 7390 return TRUE; 7391} 7392 7393/* 7394 * This function saves the video state. 7395 */ 7396static void 7397SISSave(ScrnInfoPtr pScrn) 7398{ 7399 SISPtr pSiS = SISPTR(pScrn); 7400 SISRegPtr sisReg; 7401 int flags; 7402 7403#ifdef SISDUALHEAD 7404 /* We always save master & slave */ 7405 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 7406#endif 7407 7408 sisReg = &pSiS->SavedReg; 7409 7410 if( ((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) && 7411 ((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (SiSBridgeIsInSlaveMode(pScrn))) ) { 7412 SiSVGASave(pScrn, sisReg, SISVGA_SR_CMAP | SISVGA_SR_MODE); 7413#ifdef SIS_PC_PLATFORM 7414 if(pSiS->VGAMemBase) { 7415 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO+0x30); 7416 SiSSetLVDSetc(pSiS->SiS_Pr); 7417 SiS_GetVBType(pSiS->SiS_Pr); 7418 SiS_DisableBridge(pSiS->SiS_Pr); 7419 SiSVGASave(pScrn, sisReg, SISVGA_SR_FONTS); 7420 SiS_EnableBridge(pSiS->SiS_Pr); 7421 } 7422#endif 7423 } else { 7424 flags = SISVGA_SR_CMAP | SISVGA_SR_MODE; 7425#ifdef SIS_PC_PLATFORM 7426 if(pSiS->VGAMemBase) flags |= SISVGA_SR_FONTS; 7427#endif 7428 SiSVGASave(pScrn, sisReg, flags); 7429 } 7430 7431 sisSaveUnlockExtRegisterLock(pSiS, &sisReg->sisRegs3C4[0x05], &sisReg->sisRegs3D4[0x80]); 7432 7433 (*pSiS->SiSSave)(pScrn, sisReg); 7434 7435 if(pSiS->UseVESA) SISVESASaveRestore(pScrn, MODE_SAVE); 7436 7437 /* "Save" these again as they may have been changed prior to SISSave() call */ 7438 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 7439 sisReg->sisRegs3C4[0x1f] = pSiS->oldSR1F; 7440 sisReg->sisRegs3D4[0x17] = pSiS->oldCR17; 7441 sisReg->sisRegs3D4[0x32] = pSiS->oldCR32; 7442 sisReg->sisRegs3D4[0x36] = pSiS->oldCR36; 7443 sisReg->sisRegs3D4[0x37] = pSiS->oldCR37; 7444 if(pSiS->VGAEngine == SIS_315_VGA) { 7445 sisReg->sisRegs3D4[pSiS->myCR63] = pSiS->oldCR63; 7446 } 7447 } 7448} 7449 7450/* VESASaveRestore taken from vesa driver */ 7451static void 7452SISVESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function) 7453{ 7454 SISPtr pSiS = SISPTR(pScrn); 7455 7456 /* Query amount of memory to save state */ 7457 if((function == MODE_QUERY) || 7458 (function == MODE_SAVE && pSiS->state == NULL)) { 7459 7460 /* Make sure we save at least this information in case of failure */ 7461 (void)VBEGetVBEMode(pSiS->pVbe, &pSiS->stateMode); 7462 SiSVGASaveFonts(pScrn); 7463 7464 if(pSiS->vesamajor > 1) { 7465 if(!VBESaveRestore(pSiS->pVbe, function, (pointer)&pSiS->state, 7466 &pSiS->stateSize, &pSiS->statePage)) { 7467 return; 7468 } 7469 } 7470 } 7471 7472 /* Save/Restore Super VGA state */ 7473 if(function != MODE_QUERY) { 7474 7475 if(pSiS->vesamajor > 1) { 7476 if(function == MODE_RESTORE) { 7477 memcpy(pSiS->state, pSiS->pstate, pSiS->stateSize); 7478 } 7479 7480 if(VBESaveRestore(pSiS->pVbe,function,(pointer)&pSiS->state, 7481 &pSiS->stateSize,&pSiS->statePage) && 7482 (function == MODE_SAVE)) { 7483 /* don't rely on the memory not being touched */ 7484 if(!pSiS->pstate) { 7485 pSiS->pstate = malloc(pSiS->stateSize); 7486 } 7487 memcpy(pSiS->pstate, pSiS->state, pSiS->stateSize); 7488 } 7489 } 7490 7491 if(function == MODE_RESTORE) { 7492 VBESetVBEMode(pSiS->pVbe, pSiS->stateMode, NULL); 7493 SiSVGARestoreFonts(pScrn); 7494 } 7495 7496 } 7497} 7498 7499/* 7500 * Initialise a new mode. This is currently done using the 7501 * "initialise struct, restore/write struct to HW" model for 7502 * the old chipsets (5597/530/6326). For newer chipsets, 7503 * we use our own mode switching code. 7504 */ 7505 7506static Bool 7507SISModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 7508{ 7509 SISPtr pSiS = SISPTR(pScrn); 7510 SISRegPtr sisReg; 7511#ifdef SISDUALHEAD 7512 SISEntPtr pSiSEnt = NULL; 7513#endif 7514 7515 andSISIDXREG(SISCR,0x11,0x7f); /* Unlock CRTC registers */ 7516 7517 SISModifyModeInfo(mode); /* Quick check of the mode parameters */ 7518 7519 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7520 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO+0x30); 7521 } 7522 7523 if(pSiS->UseVESA) { /* With VESA: */ 7524 7525#ifdef SISDUALHEAD 7526 /* No dual head mode when using VESA */ 7527 if(pSiS->SecondHead) return TRUE; 7528#endif 7529 7530 pScrn->vtSema = TRUE; 7531 7532 /* 7533 * This order is required: 7534 * The video bridge needs to be adjusted before the 7535 * BIOS is run as the BIOS sets up CRT2 according to 7536 * these register settings. 7537 * After the BIOS is run, the bridges and turboqueue 7538 * registers need to be readjusted as the BIOS may 7539 * very probably have messed them up. 7540 */ 7541 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7542 SiSPreSetMode(pScrn, mode, SIS_MODE_SIMU); 7543 } 7544 if(!SiSSetVESAMode(pScrn, mode)) { 7545 SISErrorLog(pScrn, "SiSSetVESAMode() failed\n"); 7546 return FALSE; 7547 } 7548 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7549 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7550 SiSPreSetMode(pScrn, mode, SIS_MODE_SIMU); 7551 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7552 } 7553#ifdef TWDEBUG 7554 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 7555 "REAL REGISTER CONTENTS AFTER SETMODE:\n"); 7556#endif 7557 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7558 SISErrorLog(pScrn, "ModeInit() failed\n"); 7559 return FALSE; 7560 } 7561 7562 SiSVGAProtect(pScrn, TRUE); 7563 (*pSiS->SiSRestore)(pScrn, &pSiS->ModeReg); 7564 SiSVGAProtect(pScrn, FALSE); 7565 7566 } else { /* Without VESA: */ 7567 7568#ifdef SISDUALHEAD 7569 if(pSiS->DualHeadMode) { 7570 7571 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7572 SISErrorLog(pScrn, "ModeInit() failed\n"); 7573 return FALSE; 7574 } 7575 7576 pScrn->vtSema = TRUE; 7577 7578 pSiSEnt = pSiS->entityPrivate; 7579 7580 if(!(pSiS->SecondHead)) { 7581 /* Head 1 (master) is always CRT2 */ 7582 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT2); 7583 if(!SiSBIOSSetModeCRT2(pSiS->SiS_Pr, pScrn, mode, pSiS->IsCustom)) { 7584 SISErrorLog(pScrn, "SiSBIOSSetModeCRT2() failed\n"); 7585 return FALSE; 7586 } 7587 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7588 if(pSiSEnt->pScrn_2) { 7589 SISAdjustFrame(ADJUST_FRAME_ARGS(pSiSEnt->pScrn_2, 7590 pSiSEnt->pScrn_2->frameX0, 7591 pSiSEnt->pScrn_2->frameY0)); 7592 } 7593 } else { 7594 /* Head 2 (slave) is always CRT1 */ 7595 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT1); 7596 if(!SiSBIOSSetModeCRT1(pSiS->SiS_Pr, pScrn, mode, pSiS->IsCustom)) { 7597 SISErrorLog(pScrn, "SiSBIOSSetModeCRT1() failed\n"); 7598 return FALSE; 7599 } 7600 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7601 if(pSiSEnt->pScrn_1) { 7602 SISAdjustFrame(ADJUST_FRAME_ARGS(pSiSEnt->pScrn_1, 7603 pSiSEnt->pScrn_1->frameX0, 7604 pSiSEnt->pScrn_1->frameY0)); 7605 } 7606 } 7607 7608 } else { 7609#endif 7610 7611 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7612 7613 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7614 SISErrorLog(pScrn, "ModeInit() failed\n"); 7615 return FALSE; 7616 } 7617 7618 pScrn->vtSema = TRUE; 7619 7620#ifdef SISMERGED 7621 if(pSiS->MergedFB) { 7622 7623 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting MergedFB mode %dx%d\n", 7624 mode->HDisplay, mode->VDisplay); 7625 7626 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT1); 7627 7628 if(!SiSBIOSSetModeCRT1(pSiS->SiS_Pr, pScrn, 7629 ((SiSMergedDisplayModePtr)mode->Private)->CRT1, 7630 pSiS->IsCustom)) { 7631 SISErrorLog(pScrn, "SiSBIOSSetModeCRT1() failed\n"); 7632 return FALSE; 7633 } 7634 7635 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT2); 7636 7637 if(!SiSBIOSSetModeCRT2(pSiS->SiS_Pr, pScrn, 7638 ((SiSMergedDisplayModePtr)mode->Private)->CRT2, 7639 pSiS->IsCustom)) { 7640 SISErrorLog(pScrn, "SiSBIOSSetModeCRT2() failed\n"); 7641 return FALSE; 7642 } 7643 7644 } else { 7645#endif 7646 7647 if((pSiS->VBFlags & CRT1_LCDA) || (!(mode->type & M_T_DEFAULT))) { 7648 7649 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT1); 7650 7651 if(!SiSBIOSSetModeCRT1(pSiS->SiS_Pr, pScrn, 7652 mode, pSiS->IsCustom)) { 7653 SISErrorLog(pScrn, "SiSBIOSSetModeCRT1() failed\n"); 7654 return FALSE; 7655 } 7656 7657 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT2); 7658 7659 if(!SiSBIOSSetModeCRT2(pSiS->SiS_Pr, pScrn, 7660 mode, pSiS->IsCustom)) { 7661 SISErrorLog(pScrn, "SiSBIOSSetModeCRT2() failed\n"); 7662 return FALSE; 7663 } 7664 7665 } else { 7666 7667 SiSPreSetMode(pScrn, mode, SIS_MODE_SIMU); 7668 7669 if(!SiSBIOSSetMode(pSiS->SiS_Pr, pScrn, 7670 mode, pSiS->IsCustom)) { 7671 SISErrorLog(pScrn, "SiSBIOSSetMode() failed\n"); 7672 return FALSE; 7673 } 7674 7675 } 7676 7677#ifdef SISMERGED 7678 } 7679#endif 7680 7681 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7682 7683#ifdef TWDEBUG 7684 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VBFlags %lx\n", pSiS->VBFlags); 7685 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 7686 "REAL REGISTER CONTENTS AFTER SETMODE:\n"); 7687 (*pSiS->ModeInit)(pScrn, mode); 7688#endif 7689 7690 } else { 7691 7692 /* For other chipsets, use the old method */ 7693 7694 /* Prepare the register contents */ 7695 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7696 SISErrorLog(pScrn, "ModeInit() failed\n"); 7697 return FALSE; 7698 } 7699 7700 pScrn->vtSema = TRUE; 7701 7702 /* Program the registers */ 7703 SiSVGAProtect(pScrn, TRUE); 7704 sisReg = &pSiS->ModeReg; 7705 7706 sisReg->sisRegsATTR[0x10] = 0x01; 7707 if(pScrn->bitsPerPixel > 8) { 7708 sisReg->sisRegsGR[0x05] = 0x00; 7709 } 7710 7711 SiSVGARestore(pScrn, sisReg, SISVGA_SR_MODE); 7712 7713 (*pSiS->SiSRestore)(pScrn, sisReg); 7714 7715 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 7716 SiS6326PostSetMode(pScrn, &pSiS->ModeReg); 7717 } 7718 7719#ifdef TWDEBUG 7720 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 7721 "REAL REGISTER CONTENTS AFTER SETMODE:\n"); 7722 (*pSiS->ModeInit)(pScrn, mode); 7723#endif 7724 7725 SiSVGAProtect(pScrn, FALSE); 7726 7727 } 7728 7729#ifdef SISDUALHEAD 7730 } 7731#endif 7732 } 7733 7734 /* Update Currentlayout */ 7735 pSiS->CurrentLayout.mode = pSiS->currentModeLast = mode; 7736 7737 return TRUE; 7738} 7739 7740static Bool 7741SiSSetVESAMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) 7742{ 7743 SISPtr pSiS; 7744 int mode; 7745 7746 pSiS = SISPTR(pScrn); 7747 7748 if(!(mode = SiSCalcVESAModeIndex(pScrn, pMode))) return FALSE; 7749 7750 mode |= (1 << 15); /* Don't clear framebuffer */ 7751 mode |= (1 << 14); /* Use linear adressing */ 7752 7753 if(VBESetVBEMode(pSiS->pVbe, mode, NULL) == FALSE) { 7754 SISErrorLog(pScrn, "Setting VESA mode 0x%x failed\n", 7755 mode & 0x0fff); 7756 return (FALSE); 7757 } 7758 7759 if(pMode->HDisplay != pScrn->virtualX) { 7760 VBESetLogicalScanline(pSiS->pVbe, pScrn->virtualX); 7761 } 7762 7763 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 7764 "Setting VESA mode 0x%x succeeded\n", 7765 mode & 0x0fff); 7766 7767 return (TRUE); 7768} 7769 7770static void 7771SISSpecialRestore(ScrnInfoPtr pScrn) 7772{ 7773 SISPtr pSiS = SISPTR(pScrn); 7774 SISRegPtr sisReg = &pSiS->SavedReg; 7775 UChar temp; 7776 int i; 7777 7778 /* 1.11.04 and later for 651 and 301B(DH) do strange register 7779 * fiddling after the usual mode change. This happens 7780 * depending on the result of a call of int 2f (with 7781 * ax=0x1680) and if modeno <= 0x13. I have no idea if 7782 * that is specific for the 651 or that very machine. 7783 * So this perhaps requires some more checks in the beginning 7784 * (although it should not do any harm on other chipsets/bridges 7785 * etc.) However, even if I call the VBE to restore mode 0x03, 7786 * these registers don't get restored correctly, possibly 7787 * because that int-2f-call for some reason results non-zero. So 7788 * what I do here is to restore these few registers 7789 * manually. 7790 */ 7791 7792 if(!(pSiS->ChipFlags & SiSCF_Is65x)) return; 7793 inSISIDXREG(SISCR, 0x34, temp); 7794 temp &= 0x7f; 7795 if(temp > 0x13) return; 7796 7797#ifdef UNLOCK_ALWAYS 7798 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7799#endif 7800 7801 SiS_UnLockCRT2(pSiS->SiS_Pr); 7802 7803 outSISIDXREG(SISCAP, 0x3f, sisReg->sisCapt[0x3f]); 7804 outSISIDXREG(SISCAP, 0x00, sisReg->sisCapt[0x00]); 7805 for(i = 0; i < 0x4f; i++) { 7806 outSISIDXREG(SISCAP, i, sisReg->sisCapt[i]); 7807 } 7808 outSISIDXREG(SISVID, 0x32, (sisReg->sisVid[0x32] & ~0x05)); 7809 outSISIDXREG(SISVID, 0x30, sisReg->sisVid[0x30]); 7810 outSISIDXREG(SISVID, 0x32, ((sisReg->sisVid[0x32] & ~0x04) | 0x01)); 7811 outSISIDXREG(SISVID, 0x30, sisReg->sisVid[0x30]); 7812 7813 if(!(pSiS->ChipFlags & SiSCF_Is651)) return; 7814 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 7815 7816 inSISIDXREG(SISCR, 0x30, temp); 7817 if(temp & 0x40) { 7818 UChar myregs[] = { 7819 0x2f, 0x08, 0x09, 0x03, 0x0a, 0x0c, 7820 0x0b, 0x0d, 0x0e, 0x12, 0x0f, 0x10, 7821 0x11, 0x04, 0x05, 0x06, 0x07, 0x00, 7822 0x2e 7823 }; 7824 for(i = 0; i <= 18; i++) { 7825 outSISIDXREG(SISPART1, myregs[i], sisReg->VBPart1[myregs[i]]); 7826 } 7827 } else if((temp & 0x20) || (temp & 0x9c)) { 7828 UChar myregs[] = { 7829 0x04, 0x05, 0x06, 0x07, 0x00, 0x2e 7830 }; 7831 for(i = 0; i <= 5; i++) { 7832 outSISIDXREG(SISPART1, myregs[i], sisReg->VBPart1[myregs[i]]); 7833 } 7834 } 7835} 7836 7837/* Fix SR11 for 661 and later */ 7838static void 7839SiSFixupSR11(ScrnInfoPtr pScrn) 7840{ 7841 SISPtr pSiS = SISPTR(pScrn); 7842 CARD8 tmpreg; 7843 7844#ifdef UNLOCK_ALWAYS 7845 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7846#endif 7847 7848 if(pSiS->ChipType >= SIS_661) { 7849 inSISIDXREG(SISSR,0x11,tmpreg); 7850 if(tmpreg & 0x20) { 7851 inSISIDXREG(SISSR,0x3e,tmpreg); 7852 tmpreg = (tmpreg + 1) & 0xff; 7853 outSISIDXREG(SISSR,0x3e,tmpreg); 7854 } 7855 7856 inSISIDXREG(SISSR,0x11,tmpreg); 7857 if(tmpreg & 0xf0) { 7858 andSISIDXREG(SISSR,0x11,0x0f); 7859 } 7860 } 7861} 7862 7863/* Subroutine for restoring sisfb's TV parameters (used by SiSRestore()) */ 7864 7865static void 7866SiSRestore_SiSFB_TVParms(ScrnInfoPtr pScrn) 7867{ 7868 SISPtr pSiS = SISPTR(pScrn); 7869 int fd; 7870 CARD32 parm; 7871 7872 if(!pSiS->sisfbfound) return; 7873 if(!pSiS->sisfb_tvposvalid) return; 7874 if(!(pSiS->sisfbdevname[0])) return; 7875 7876 if((fd = open(pSiS->sisfbdevname, O_RDONLY)) != -1) { 7877 parm = (CARD32)((pSiS->sisfb_tvxpos << 16) | (pSiS->sisfb_tvypos & 0xffff)); 7878 ioctl(fd, SISFB_SET_TVPOSOFFSET, &parm); 7879 close(fd); 7880 } 7881} 7882 7883/* 7884 * Restore the initial mode. To be used internally only! 7885 */ 7886static void 7887SISRestore(ScrnInfoPtr pScrn) 7888{ 7889 SISPtr pSiS = SISPTR(pScrn); 7890 SISRegPtr sisReg = &pSiS->SavedReg; 7891 Bool doit = FALSE, doitlater = FALSE; 7892 Bool vesasuccess = FALSE; 7893 int flags; 7894 7895 /* WARNING: Don't ever touch this. It now seems to work on 7896 * all chipset/bridge combinations - but finding out the 7897 * correct combination was pure hell. 7898 */ 7899 7900 /* Wait for the accelerators */ 7901 (*pSiS->SyncAccel)(pScrn); 7902 7903 /* Set up restore flags */ 7904 flags = SISVGA_SR_MODE | SISVGA_SR_CMAP; 7905#ifdef SIS_PC_PLATFORM 7906 /* We now restore ALL to overcome the vga=extended problem */ 7907 if(pSiS->VGAMemBase) flags |= SISVGA_SR_FONTS; 7908#endif 7909 7910 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 7911 7912#ifdef SISDUALHEAD 7913 /* We always restore master AND slave */ 7914 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 7915#endif 7916 7917#ifdef UNLOCK_ALWAYS 7918 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7919#endif 7920 7921 /* We must not disable the sequencer if the bridge is in SlaveMode! */ 7922 if(!(SiSBridgeIsInSlaveMode(pScrn))) { 7923 SiSVGAProtect(pScrn, TRUE); 7924 } 7925 7926 /* First, restore CRT1 on/off and VB connection registers */ 7927 outSISIDXREG(SISCR, 0x32, pSiS->oldCR32); 7928 if(!(pSiS->oldCR17 & 0x80)) { /* CRT1 was off */ 7929 if(!(SiSBridgeIsInSlaveMode(pScrn))) { /* Bridge is NOT in SlaveMode now -> do it */ 7930 doit = TRUE; 7931 } else { 7932 doitlater = TRUE; 7933 } 7934 } else { /* CRT1 was on -> do it now */ 7935 doit = TRUE; 7936 } 7937 7938 if(doit) { 7939 outSISIDXREG(SISCR, 0x17, pSiS->oldCR17); 7940 } 7941 if(pSiS->VGAEngine == SIS_315_VGA) { 7942 outSISIDXREG(SISCR, pSiS->myCR63, pSiS->oldCR63); 7943 } 7944 7945 outSISIDXREG(SISSR, 0x1f, pSiS->oldSR1F); 7946 7947 /* For 30xB/LV, restoring the registers does not 7948 * work. We "manually" set the old mode, instead. 7949 * The same applies for SiS730 machines with LVDS. 7950 * Finally, this behavior can be forced by setting 7951 * the option RestoreBySetMode. 7952 */ 7953 if( ( (pSiS->restorebyset) || 7954 (pSiS->VBFlags2 & VB2_30xBLV) || 7955 ((pSiS->ChipType == SIS_730) && (pSiS->VBFlags2 & VB2_LVDS)) ) && 7956 (pSiS->OldMode) ) { 7957 7958 Bool changedmode = FALSE; 7959 7960 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 7961 "Restoring by setting old mode 0x%02x\n", pSiS->OldMode); 7962 7963 if(((pSiS->OldMode <= 0x13) || (!pSiS->sisfbfound)) && (pSiS->pVbe)) { 7964 int vmode = SiSTranslateToVESA(pScrn, pSiS->OldMode); 7965 if(vmode > 0) { 7966 if(vmode > 0x13) vmode |= ((1 << 15) | (1 << 14)); 7967 if(VBESetVBEMode(pSiS->pVbe, vmode, NULL) == TRUE) { 7968 SISSpecialRestore(pScrn); 7969 SiS_GetSetModeID(pScrn,pSiS->OldMode); 7970 vesasuccess = TRUE; 7971 } else { 7972 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 7973 "VBE failed to restore mode 0x%x\n", pSiS->OldMode); 7974 } 7975 } else { 7976 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 7977 "Can't identify VESA mode number for mode 0x%x\n", pSiS->OldMode); 7978 } 7979 } 7980 7981 if(vesasuccess == FALSE) { 7982 7983 int backupscaler = pSiS->SiS_Pr->UsePanelScaler; 7984 int backupcenter = pSiS->SiS_Pr->CenterScreen; 7985 ULong backupspecialtiming = pSiS->SiS_Pr->SiS_CustomT; 7986 int mymode = pSiS->OldMode; 7987 7988 if((pSiS->VGAEngine == SIS_315_VGA) && 7989 ((pSiS->ROM661New) || (pSiS->ChipFlags & SiSCF_IsXGI)) && 7990 (!pSiS->sisfbfound)) { 7991 /* New SiS BIOS or XGI BIOS has set mode, therefore eventually translate number */ 7992 mymode = SiSTranslateToOldMode(mymode); 7993 } 7994 7995 if((pSiS->VBFlags2 & VB2_30xBLV)) { 7996 /* !!! REQUIRED for 630+301B-DH, otherwise the text modes 7997 * will not be restored correctly !!! 7998 * !!! Do this ONLY for LCD; VGA2 will not be restored 7999 * correctly otherwise. 8000 */ 8001 UChar temp; 8002 inSISIDXREG(SISCR, 0x30, temp); 8003 if(temp & 0x20) { 8004 if(mymode == 0x03) { 8005 mymode = 0x13; 8006 changedmode = TRUE; 8007 } 8008 } 8009 } 8010 8011 pSiS->SiS_Pr->UseCustomMode = FALSE; 8012 pSiS->SiS_Pr->CRT1UsesCustomMode = FALSE; 8013 pSiS->SiS_Pr->CenterScreen = 0; 8014 if(pSiS->sisfbfound) { 8015 pSiS->SiS_Pr->UsePanelScaler = pSiS->sisfbscalelcd; 8016 pSiS->SiS_Pr->SiS_CustomT = pSiS->sisfbspecialtiming; 8017 } else { 8018 pSiS->SiS_Pr->UsePanelScaler = -1; 8019 /* Leave CustomT as it is */ 8020 } 8021 SiS_SetEnableDstn(pSiS->SiS_Pr, FALSE); 8022 SiS_SetEnableFstn(pSiS->SiS_Pr, FALSE); 8023 if((pSiS->ChipType == SIS_550) && (pSiS->sisfbfound)) { 8024 if(pSiS->sisfbxSTN) { 8025 SiS_SetEnableDstn(pSiS->SiS_Pr, pSiS->sisfbDSTN); 8026 SiS_SetEnableFstn(pSiS->SiS_Pr, pSiS->sisfbFSTN); 8027 } else if(mymode == 0x5a || mymode == 0x5b) { 8028 SiS_SetEnableFstn(pSiS->SiS_Pr, TRUE); 8029 } 8030 } 8031 SiSSetMode(pSiS->SiS_Pr, pScrn, mymode, FALSE); 8032 if(changedmode) { 8033 outSISIDXREG(SISCR,0x34,0x03); 8034 } 8035 SISSpecialRestore(pScrn); 8036 SiS_GetSetModeID(pScrn, pSiS->OldMode); /* NOT mymode! */ 8037 pSiS->SiS_Pr->UsePanelScaler = backupscaler; 8038 pSiS->SiS_Pr->CenterScreen = backupcenter; 8039 pSiS->SiS_Pr->SiS_CustomT = backupspecialtiming; 8040 SiS_SiSFB_Lock(pScrn, FALSE); 8041 SiSRestore_SiSFB_TVParms(pScrn); 8042 SiS_SiSFB_Lock(pScrn, TRUE); 8043 8044 } 8045 8046 /* Restore CRT1 status */ 8047 if(pSiS->VGAEngine == SIS_315_VGA) { 8048 outSISIDXREG(SISCR, pSiS->myCR63, pSiS->oldCR63); 8049 } 8050 outSISIDXREG(SISSR, 0x1f, pSiS->oldSR1F); 8051 8052#ifdef SISVRAMQ 8053 /* Restore queue mode registers on 315/330/340 series */ 8054 /* (This became necessary due to the switch to VRAM queue) */ 8055 SiSRestoreQueueMode(pSiS, sisReg); 8056#endif 8057 8058 } else { 8059 8060 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 8061 /* If a video bridge is present, we need to restore 8062 * non-extended (=standard VGA) SR and CR registers 8063 * before restoring the extended ones and the bridge 8064 * registers. 8065 */ 8066 if(!(SiSBridgeIsInSlaveMode(pScrn))) { 8067 SiSVGAProtect(pScrn, TRUE); 8068 SiSVGARestore(pScrn, sisReg, SISVGA_SR_MODE); 8069 } 8070 } 8071 8072 (*pSiS->SiSRestore)(pScrn, sisReg); 8073 8074 } 8075 8076 if(doitlater) { 8077 outSISIDXREG(SISCR, 0x17, pSiS->oldCR17); 8078 } 8079 8080 8081 8082 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (SiSBridgeIsInSlaveMode(pScrn))) { 8083 8084 /* IMPORTANT: The 30xLV does not handle well being disabled if in 8085 * LCDA mode! In LCDA mode, the bridge is NOT in slave mode, 8086 * so this is the only safe way: Disable the bridge ONLY if 8087 * in Slave Mode, and don't bother if not. 8088 */ 8089 8090 if(flags & SISVGA_SR_FONTS) { 8091 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO+0x30); 8092 SiSSetLVDSetc(pSiS->SiS_Pr); 8093 SiS_GetVBType(pSiS->SiS_Pr); 8094 SiS_DisableBridge(pSiS->SiS_Pr); 8095 SiSVGAProtect(pScrn, TRUE); 8096 } 8097 8098 SiSVGARestore(pScrn, sisReg, flags); 8099 8100 if(flags & SISVGA_SR_FONTS) { 8101 SiSVGAProtect(pScrn, FALSE); 8102 SiS_EnableBridge(pSiS->SiS_Pr); 8103 andSISIDXREG(SISSR, 0x01, ~0x20); /* Display on */ 8104 } 8105 8106 } else { 8107 8108 SiSVGAProtect(pScrn, TRUE); 8109 SiSVGARestore(pScrn, sisReg, flags); 8110 SiSVGAProtect(pScrn, FALSE); 8111 8112 } 8113 8114 SiSFixupSR11(pScrn); 8115 8116#ifdef TWDEBUG 8117 { 8118 SISRegPtr pReg = &pSiS->ModeReg; 8119 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8120 "REAL REGISTER CONTENTS AFTER RESTORE BY SETMODE:\n"); 8121 (*pSiS->SiSSave)(pScrn, pReg); 8122 } 8123#endif 8124 8125 sisRestoreExtRegisterLock(pSiS,sisReg->sisRegs3C4[0x05],sisReg->sisRegs3D4[0x80]); 8126 8127 } else { /* All other chipsets */ 8128 8129 SiSVGAProtect(pScrn, TRUE); 8130 8131#ifdef UNLOCK_ALWAYS 8132 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8133#endif 8134 8135 (*pSiS->SiSRestore)(pScrn, sisReg); 8136 8137 SiSVGAProtect(pScrn, TRUE); 8138 8139 SiSVGARestore(pScrn, sisReg, flags); 8140 8141 /* Restore TV. This is rather complicated, but if we don't do it, 8142 * TV output will flicker terribly 8143 */ 8144 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 8145 if(sisReg->sis6326tv[0] & 0x04) { 8146 UChar tmp; 8147 int val; 8148 8149 orSISIDXREG(SISSR, 0x01, 0x20); 8150 tmp = SiS6326GetTVReg(pScrn,0x00); 8151 tmp &= ~0x04; 8152 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 8153 SiS6326SetTVReg(pScrn,0x00,tmp); 8154 for(val=0; val < 2; val++) { 8155 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 8156 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 8157 } 8158 SiS6326SetTVReg(pScrn, 0x00, sisReg->sis6326tv[0]); 8159 tmp = inSISREG(SISINPSTAT); 8160 outSISREG(SISAR, 0x20); 8161 tmp = inSISREG(SISINPSTAT); 8162 while(inSISREG(SISINPSTAT) & 0x01); 8163 while(!(inSISREG(SISINPSTAT) & 0x01)); 8164 andSISIDXREG(SISSR, 0x01, ~0x20); 8165 for(val=0; val < 10; val++) { 8166 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 8167 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 8168 } 8169 andSISIDXREG(SISSR, 0x01, ~0x20); 8170 } 8171 } 8172 8173 sisRestoreExtRegisterLock(pSiS,sisReg->sisRegs3C4[5],sisReg->sisRegs3D4[0x80]); 8174 8175 SiSVGAProtect(pScrn, FALSE); 8176 } 8177} 8178 8179static void 8180SISVESARestore(ScrnInfoPtr pScrn) 8181{ 8182 SISPtr pSiS = SISPTR(pScrn); 8183#ifdef SISVRAMQ 8184 SISRegPtr sisReg = &pSiS->SavedReg; 8185#endif 8186 8187 if(pSiS->UseVESA) { 8188 SISVESASaveRestore(pScrn, MODE_RESTORE); 8189#ifdef SISVRAMQ 8190 /* Restore queue mode registers on 315/330/340 series */ 8191 /* (This became necessary due to the switch to VRAM queue) */ 8192 SiSRestoreQueueMode(pSiS, sisReg); 8193#endif 8194 } 8195} 8196 8197/* Restore bridge config registers - to be called BEFORE VESARestore */ 8198static void 8199SISBridgeRestore(ScrnInfoPtr pScrn) 8200{ 8201 SISPtr pSiS = SISPTR(pScrn); 8202 8203#ifdef SISDUALHEAD 8204 /* We only restore for master head */ 8205 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 8206#endif 8207 8208 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 8209 SiSRestoreBridge(pScrn, &pSiS->SavedReg); 8210 } 8211} 8212 8213/* Our BlockHandler */ 8214static void 8215SISBlockHandler(BLOCKHANDLER_ARGS_DECL) 8216{ 8217 SCREEN_PTR(arg); 8218 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 8219 SISPtr pSiS = SISPTR(pScrn); 8220 8221 pScreen->BlockHandler = pSiS->BlockHandler; 8222 (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS); 8223 pScreen->BlockHandler = SISBlockHandler; 8224 8225#ifdef SISDUALHEAD 8226 if(pSiS->NeedCopyFastVidCpy) { 8227 SISEntPtr pSiSEnt = pSiS->entityPrivate; 8228 if(pSiSEnt->HaveFastVidCpy) { 8229 pSiS->NeedCopyFastVidCpy = FALSE; 8230 pSiS->SiSFastVidCopy = pSiSEnt->SiSFastVidCopy; 8231 pSiS->SiSFastMemCopy = pSiSEnt->SiSFastMemCopy; 8232 pSiS->SiSFastVidCopyFrom = pSiSEnt->SiSFastVidCopyFrom; 8233 pSiS->SiSFastMemCopyFrom = pSiSEnt->SiSFastMemCopyFrom; 8234 } 8235 } 8236#endif 8237 8238 if(pSiS->VideoTimerCallback) { 8239 (*pSiS->VideoTimerCallback)(pScrn, currentTime.milliseconds); 8240 } 8241 8242#ifdef SIS_USE_XAA 8243 if(pSiS->RenderCallback) { 8244 (*pSiS->RenderCallback)(pScrn); 8245 } 8246#endif 8247#ifdef SIS_USE_EXA 8248 if(pSiS->ExaRenderCallback) { 8249 (*pSiS->ExaRenderCallback)(pScrn); 8250 } 8251#endif 8252} 8253 8254 8255 8256/* Do screen blanking; DPMS handling 8257 * 8258 * Mandatory; latter optional 8259 */ 8260 8261static void 8262SiSHandleBackLight(SISPtr pSiS, Bool blon) 8263{ 8264 UChar sr11mask = (pSiS->SiS_Pr->SiS_SensibleSR11) ? 0x03 : 0xf3; 8265 8266 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) { 8267 8268 if(!blon) { 8269 SiS_SiS30xBLOff(pSiS->SiS_Pr); 8270 } else { 8271 SiS_SiS30xBLOn(pSiS->SiS_Pr); 8272 } 8273 8274 } else if( ((pSiS->VGAEngine == SIS_300_VGA) && 8275 (pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH))) || 8276 ((pSiS->VGAEngine == SIS_315_VGA) && 8277 ((pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS)) ) { 8278 8279 if(!blon) { 8280 setSISIDXREG(SISSR, 0x11, sr11mask, 0x08); 8281 } else { 8282 setSISIDXREG(SISSR, 0x11, sr11mask, 0x00); 8283 } 8284 8285 } else if((pSiS->VGAEngine == SIS_315_VGA) && 8286 (pSiS->VBFlags2 & VB2_CHRONTEL)) { 8287 8288 if(!blon) { 8289 SiS_Chrontel701xBLOff(pSiS->SiS_Pr); 8290 } else { 8291 SiS_Chrontel701xBLOn(pSiS->SiS_Pr); 8292 } 8293 8294 } 8295} 8296 8297static Bool 8298SISSaveScreen(ScreenPtr pScreen, int mode) 8299{ 8300 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 8301 SISPtr pSiS; 8302 Bool IsUnblank = xf86IsUnblank(mode) ? TRUE : FALSE; 8303 8304 if((pScrn == NULL) || (!pScrn->vtSema)) return TRUE; 8305 8306 pSiS = SISPTR(pScrn); 8307 8308#ifdef UNLOCK_ALWAYS 8309 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8310#endif 8311 8312 if(pSiS->VBFlags & (CRT2_LCD | CRT1_LCDA)) { 8313 SiSHandleBackLight(pSiS, IsUnblank); 8314 } 8315 8316 if(!SiSBridgeIsInSlaveMode(pScrn)) { 8317 return SiSVGASaveScreen(pScreen, mode); 8318 } 8319 8320 return TRUE; 8321} 8322 8323#ifdef SISDUALHEAD 8324/* SaveScreen for dual head mode */ 8325static Bool 8326SISSaveScreenDH(ScreenPtr pScreen, int mode) 8327{ 8328 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 8329 SISPtr pSiS; 8330 Bool IsUnblank = xf86IsUnblank(mode) ? TRUE : FALSE; 8331 8332 if((pScrn == NULL) || (!pScrn->vtSema)) return TRUE; 8333 8334 pSiS = SISPTR(pScrn); 8335 8336 if( (pSiS->SecondHead) && 8337 ((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) ) { 8338 8339 /* Slave head is always CRT1 */ 8340 /* (No backlight handling on TMDS bridges) */ 8341 return SiSVGASaveScreen(pScreen, mode); 8342 8343 } else { 8344 8345 /* Master head is always CRT2 */ 8346 /* But we land here for LCDA, too (if bridge is SiS LVDS type) */ 8347 8348 /* We can only blank LCD, not other CRT2 devices */ 8349 if(pSiS->VBFlags & (CRT2_LCD|CRT1_LCDA)) { 8350 8351#ifdef UNLOCK_ALWAYS 8352 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8353#endif 8354 SiSHandleBackLight(pSiS, IsUnblank); 8355 8356 } 8357 8358 } 8359 return TRUE; 8360} 8361#endif 8362 8363static void 8364SISDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags) 8365{ 8366 SISPtr pSiS = SISPTR(pScrn); 8367 Bool docrt1 = TRUE, docrt2 = TRUE, backlight = TRUE; 8368 UChar sr1=0, cr17=0, cr63=0, pmreg=0, sr7=0; 8369 UChar p1_13=0, p2_0=0, oldpmreg=0; 8370 8371 if(!pScrn->vtSema) return; 8372 8373 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, 8374 "SISDisplayPowerManagementSet(%d)\n", PowerManagementMode); 8375 8376#ifdef SISDUALHEAD 8377 if(pSiS->DualHeadMode) { 8378 if(pSiS->SecondHead) docrt2 = FALSE; 8379 else docrt1 = FALSE; 8380 } 8381#endif 8382 8383 /* FIXME: in old servers, DPMSSet was supposed to be called without open 8384 * the correct PCI bridges before access the hardware. Now we have this 8385 * hook wrapped by the vga arbiter which should do all the work, in 8386 * kernels that implement it. For this case we might not want this hack 8387 * bellow. 8388 */ 8389 outSISIDXREG(SISSR,0x05,0x86); 8390 inSISIDXREG(SISSR,0x05,pmreg); 8391 if(pmreg != 0xa1) return; 8392 8393#ifdef UNLOCK_ALWAYS 8394 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8395#endif 8396 8397 switch(PowerManagementMode) { 8398 8399 case DPMSModeOn: /* HSync: On, VSync: On */ 8400 sr1 = 0x00; 8401 cr17 = 0x80; 8402 pmreg = 0x00; 8403 cr63 = 0x00; 8404 sr7 = 0x10; 8405 p2_0 = 0x20; 8406 p1_13 = 0x00; 8407 backlight = TRUE; 8408 break; 8409 8410 case DPMSModeSuspend: /* HSync: On, VSync: Off */ 8411 sr1 = 0x20; 8412 cr17 = 0x80; 8413 pmreg = 0x80; 8414 cr63 = 0x40; 8415 sr7 = 0x00; 8416 p2_0 = 0x40; 8417 p1_13 = 0x80; 8418 backlight = FALSE; 8419 break; 8420 8421 case DPMSModeStandby: /* HSync: Off, VSync: On */ 8422 sr1 = 0x20; 8423 cr17 = 0x80; 8424 pmreg = 0x40; 8425 cr63 = 0x40; 8426 sr7 = 0x00; 8427 p2_0 = 0x80; 8428 p1_13 = 0x40; 8429 backlight = FALSE; 8430 break; 8431 8432 case DPMSModeOff: /* HSync: Off, VSync: Off */ 8433 sr1 = 0x20; 8434 cr17 = 0x00; 8435 pmreg = 0xc0; 8436 cr63 = 0x40; 8437 sr7 = 0x00; 8438 p2_0 = 0xc0; 8439 p1_13 = 0xc0; 8440 backlight = FALSE; 8441 break; 8442 8443 default: 8444 return; 8445 } 8446 8447 oldpmreg = pmreg; 8448 8449 if((docrt2 && (pSiS->VBFlags & CRT2_LCD)) || 8450 (docrt1 && (pSiS->VBFlags & CRT1_LCDA))) { 8451 SiSHandleBackLight(pSiS, backlight); 8452 } 8453 8454 if(docrt1) { 8455 switch(pSiS->VGAEngine) { 8456 case SIS_OLD_VGA: 8457 case SIS_530_VGA: 8458 setSISIDXREG(SISSR, 0x01, ~0x20, sr1); /* Set/Clear "Display On" bit */ 8459 inSISIDXREG(SISSR, 0x11, oldpmreg); 8460 setSISIDXREG(SISCR, 0x17, 0x7f, cr17); 8461 setSISIDXREG(SISSR, 0x11, 0x3f, pmreg); 8462 break; 8463 case SIS_315_VGA: 8464 if( (!pSiS->CRT1off) && 8465 ((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) ) { 8466 setSISIDXREG(SISCR, pSiS->myCR63, 0xbf, cr63); 8467 setSISIDXREG(SISSR, 0x07, 0xef, sr7); 8468 } 8469 /* fall through */ 8470 default: 8471 if(!SiSBridgeIsInSlaveMode(pScrn)) { 8472 setSISIDXREG(SISSR, 0x01, ~0x20, sr1); /* Set/Clear "Display On" bit */ 8473 } 8474 if((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 8475 inSISIDXREG(SISSR, 0x1f, oldpmreg); 8476 if((!pSiS->CRT1off) && (!SiSBridgeIsInSlaveMode(pScrn))) { 8477 setSISIDXREG(SISSR, 0x1f, 0x3f, pmreg); 8478 } 8479 } 8480 } 8481 oldpmreg &= 0xc0; 8482 } 8483 8484 if(docrt2) { 8485 if(pSiS->VBFlags & CRT2_LCD) { 8486 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && 8487 (!(pSiS->VBFlags2 & VB2_30xBDH))) { 8488 if(pSiS->VGAEngine == SIS_300_VGA) { 8489 SiS_UnLockCRT2(pSiS->SiS_Pr); 8490 setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13); 8491 } 8492 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) p2_0 |= 0x20; 8493 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); 8494 } 8495 } else if(pSiS->VBFlags & (CRT2_VGA | CRT2_TV)) { 8496 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 8497 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); 8498 } 8499 } 8500 } 8501 8502 if( (docrt1) && 8503 (pmreg != oldpmreg) && 8504 ((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) ) { 8505 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 8506 usleep(10000); 8507 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 8508 } 8509 8510} 8511 8512/* Mandatory 8513 * This gets called at the start of each server generation 8514 * 8515 * We use pScrn and not CurrentLayout here, because the 8516 * properties we use have not changed (displayWidth, 8517 * depth, bitsPerPixel) 8518 */ 8519static Bool 8520SISScreenInit(SCREEN_INIT_ARGS_DECL) 8521{ 8522 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 8523 SISPtr pSiS = SISPTR(pScrn); 8524 VisualPtr visual; 8525 ULong OnScreenSize; 8526 int ret, height, width, displayWidth; 8527 UChar *FBStart; 8528#ifdef SISDUALHEAD 8529 SISEntPtr pSiSEnt = NULL; 8530#endif 8531 8532#ifdef SISDUALHEAD 8533 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) { 8534#endif 8535 SiS_LoadInitVBE(pScrn); 8536#ifdef SISDUALHEAD 8537 } 8538#endif 8539 8540#ifdef SISDUALHEAD 8541 if(pSiS->DualHeadMode) { 8542 pSiSEnt = pSiS->entityPrivate; 8543 pSiSEnt->refCount++; 8544 } 8545#endif 8546 8547#ifdef SIS_PC_PLATFORM 8548 /* Map 64k VGA window for saving/restoring CGA fonts */ 8549 SiS_MapVGAMem(pScrn); 8550#endif 8551 8552 /* Map the SiS memory and MMIO areas */ 8553 if(!SISMapMem(pScrn)) { 8554 SISErrorLog(pScrn, "SiSMapMem() failed\n"); 8555 return FALSE; 8556 } 8557 8558 SiS_SiSFB_Lock(pScrn, TRUE); 8559 8560#ifdef UNLOCK_ALWAYS 8561 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8562#endif 8563 8564 /* Enable TurboQueue so that SISSave() saves it in enabled 8565 * state. If we don't do this, X will hang after a restart! 8566 * (Happens for some unknown reason only when using VESA 8567 * for mode switching; assumingly a BIOS issue.) 8568 * This is done on 300 and 315 series only. 8569 */ 8570 if(pSiS->UseVESA) { 8571#ifdef SISVRAMQ 8572 if(pSiS->VGAEngine != SIS_315_VGA) 8573#endif 8574 SiSEnableTurboQueue(pScrn); 8575 } 8576 8577 /* Save the current state */ 8578 SISSave(pScrn); 8579 8580 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 8581 8582 if(!pSiS->OldMode) { 8583 8584 /* Try to find out current (=old) mode number 8585 * (Do this only if not sisfb has told us its mode yet) 8586 */ 8587 8588 /* Read 0:449 which the BIOS sets to the current mode number 8589 * Unfortunately, this not reliable since the int10 emulation 8590 * does not change this. So if we call the VBE later, this 8591 * byte won't be touched (which is why we set this manually 8592 * then). 8593 */ 8594 UChar myoldmode = SiS_GetSetModeID(pScrn, 0xFF); 8595 UChar cr30, cr31; 8596 8597 /* Read CR34 which the BIOS sets to the current mode number for CRT2 8598 * This is - of course - not reliable if the machine has no video 8599 * bridge... 8600 */ 8601 inSISIDXREG(SISCR, 0x34, pSiS->OldMode); 8602 inSISIDXREG(SISCR, 0x30, cr30); 8603 inSISIDXREG(SISCR, 0x31, cr31); 8604 8605 /* What if CR34 is different from the BIOS scratch byte? */ 8606 if(pSiS->OldMode != myoldmode) { 8607 /* If no bridge output is active, trust the BIOS scratch byte */ 8608 if( (!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) || 8609 (pSiS->OldMode == 0) || 8610 (!cr31 && !cr30) || 8611 (cr31 & 0x20) ) { 8612 pSiS->OldMode = myoldmode; 8613 } 8614 /* ..else trust CR34 */ 8615 } 8616 8617 /* Newer 650 BIOSes set CR34 to 0xff if the mode has been 8618 * "patched", for instance for 80x50 text mode. (That mode 8619 * has no number of its own, it's 0x03 like 80x25). In this 8620 * case, we trust the BIOS scratch byte (provided that any 8621 * of these two is valid). 8622 */ 8623 if(pSiS->OldMode > 0x7f) { 8624 pSiS->OldMode = myoldmode; 8625 } 8626 } 8627#ifdef SISDUALHEAD 8628 if(pSiS->DualHeadMode) { 8629 if(!pSiS->SecondHead) pSiSEnt->OldMode = pSiS->OldMode; 8630 else pSiS->OldMode = pSiSEnt->OldMode; 8631 } 8632#endif 8633 } 8634 8635 /* RandR resets screen mode and size in CloseScreen(), hence 8636 * we need to adapt our VBFlags to the initial state if the 8637 * current mode has changed since closescreen() (or Screeninit() 8638 * for the first instance) 8639 */ 8640 if(pScrn->currentMode != pSiS->currentModeLast) { 8641 pSiS->VBFlags = pSiS->VBFlags_backup = pSiS->VBFlagsInit; 8642 } 8643 8644 /* Copy our detected monitor gammas, part 2. Note that device redetection 8645 * is not supported in DHM, so there is no need to do that anytime later. 8646 */ 8647#ifdef SISDUALHEAD 8648 if(pSiS->DualHeadMode) { 8649 if(!pSiS->SecondHead) { 8650 /* CRT2 */ 8651 pSiS->CRT1VGAMonitorGamma = pSiSEnt->CRT1VGAMonitorGamma; 8652 } else { 8653 /* CRT1 */ 8654 pSiS->CRT2VGAMonitorGamma = pSiSEnt->CRT2VGAMonitorGamma; 8655 } 8656 if(!pSiS->CRT2LCDMonitorGamma) pSiS->CRT2LCDMonitorGamma = pSiSEnt->CRT2LCDMonitorGamma; 8657 } 8658#endif 8659 8660 /* Initialize the first mode */ 8661 if(!SISModeInit(pScrn, pScrn->currentMode)) { 8662 SISErrorLog(pScrn, "SiSModeInit() failed\n"); 8663 return FALSE; 8664 } 8665 8666 /* Darken the screen for aesthetic reasons */ 8667 /* Not using Dual Head variant on purpose; we darken 8668 * the screen for both displays, and un-darken 8669 * it when the second head is finished 8670 */ 8671 SISSaveScreen(pScreen, SCREEN_SAVER_ON); 8672 8673 /* Set the viewport */ 8674 SISAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 8675 8676 /* Reset visual list. */ 8677 miClearVisualTypes(); 8678 8679 /* Setup the visuals we support. */ 8680 8681 /* 8682 * For bpp > 8, the default visuals are not acceptable because we only 8683 * support TrueColor and not DirectColor. 8684 */ 8685 if(!miSetVisualTypes(pScrn->depth, 8686 (pScrn->bitsPerPixel > 8) ? 8687 TrueColorMask : miGetDefaultVisualMask(pScrn->depth), 8688 pScrn->rgbBits, pScrn->defaultVisual)) { 8689 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8690 SISErrorLog(pScrn, "miSetVisualTypes() failed (bpp %d)\n", 8691 pScrn->bitsPerPixel); 8692 return FALSE; 8693 } 8694 8695 width = pScrn->virtualX; 8696 height = pScrn->virtualY; 8697 displayWidth = pScrn->displayWidth; 8698 8699 if(pSiS->Rotate) { 8700 height = pScrn->virtualX; 8701 width = pScrn->virtualY; 8702 } 8703 8704 if(pSiS->ShadowFB) { 8705 pSiS->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); 8706 pSiS->ShadowPtr = malloc(pSiS->ShadowPitch * height); 8707 displayWidth = pSiS->ShadowPitch / (pScrn->bitsPerPixel >> 3); 8708 FBStart = pSiS->ShadowPtr; 8709 } else { 8710 pSiS->ShadowPtr = NULL; 8711 FBStart = pSiS->FbBase; 8712 } 8713 8714 if(!miSetPixmapDepths()) { 8715 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8716 SISErrorLog(pScrn, "miSetPixmapDepths() failed\n"); 8717 return FALSE; 8718 } 8719 8720 /* Point cmdQueuePtr to pSiSEnt for shared usage 8721 * (same technique is then eventually used in DRIScreeninit) 8722 * For 315/330 series, this is done in EnableTurboQueue 8723 * which has already been called during ModeInit(). 8724 */ 8725#ifdef SISDUALHEAD 8726 if(pSiS->SecondHead) 8727 pSiS->cmdQueueLenPtr = &(SISPTR(pSiSEnt->pScrn_1)->cmdQueueLen); 8728 else 8729#endif 8730 pSiS->cmdQueueLenPtr = &(pSiS->cmdQueueLen); 8731 8732 pSiS->cmdQueueLen = 0; /* Force an EngineIdle() at start */ 8733 8734#ifdef SISDRI 8735 if(pSiS->loadDRI) { 8736#ifdef SISDUALHEAD 8737 /* No DRI in dual head mode */ 8738 if(pSiS->DualHeadMode) { 8739 pSiS->directRenderingEnabled = FALSE; 8740 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8741 "DRI not supported in Dual Head mode\n"); 8742 } else 8743#endif 8744 if(pSiS->VGAEngine != SIS_315_VGA) { 8745 /* Force the initialization of the context */ 8746 pSiS->directRenderingEnabled = SISDRIScreenInit(pScreen); 8747 } else { 8748 xf86DrvMsg(pScrn->scrnIndex, X_NOT_IMPLEMENTED, 8749 "DRI not supported on this chipset\n"); 8750 pSiS->directRenderingEnabled = FALSE; 8751 } 8752 } 8753#endif 8754 8755 /* Call the framebuffer layer's ScreenInit function and fill in other 8756 * pScreen fields. 8757 */ 8758 switch(pScrn->bitsPerPixel) { 8759 case 24: 8760 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 8761 ret = FALSE; 8762 break; 8763 } 8764 /* fall through */ 8765 case 8: 8766 case 16: 8767 case 32: 8768 ret = fbScreenInit(pScreen, FBStart, width, 8769 height, pScrn->xDpi, pScrn->yDpi, 8770 displayWidth, pScrn->bitsPerPixel); 8771 break; 8772 default: 8773 ret = FALSE; 8774 break; 8775 } 8776 if(!ret) { 8777 SISErrorLog(pScrn, "Unsupported bpp (%d) or fbScreenInit() failed\n", 8778 pScrn->bitsPerPixel); 8779 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8780 return FALSE; 8781 } 8782 8783 /* Fixup RGB ordering */ 8784 if(pScrn->bitsPerPixel > 8) { 8785 visual = pScreen->visuals + pScreen->numVisuals; 8786 while (--visual >= pScreen->visuals) { 8787 if((visual->class | DynamicClass) == DirectColor) { 8788 visual->offsetRed = pScrn->offset.red; 8789 visual->offsetGreen = pScrn->offset.green; 8790 visual->offsetBlue = pScrn->offset.blue; 8791 visual->redMask = pScrn->mask.red; 8792 visual->greenMask = pScrn->mask.green; 8793 visual->blueMask = pScrn->mask.blue; 8794 } 8795 } 8796 } 8797 8798 /* Initialize RENDER extension (must be after RGB ordering fixed) */ 8799 fbPictureInit(pScreen, 0, 0); 8800 8801 /* Hardware cursor needs to wrap this layer */ 8802 if(!pSiS->ShadowFB) SISDGAInit(pScreen); 8803 8804 xf86SetBlackWhitePixels(pScreen); 8805 8806 /* Initialize the accelerators */ 8807 switch(pSiS->VGAEngine) { 8808 case SIS_530_VGA: 8809 case SIS_300_VGA: 8810 SiS300AccelInit(pScreen); 8811 break; 8812 case SIS_315_VGA: 8813 SiS315AccelInit(pScreen); 8814 break; 8815 default: 8816 SiSAccelInit(pScreen); 8817 } 8818 8819#ifdef TWDEBUG 8820 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CPUFlags %x\n", pSiS->CPUFlags); 8821#endif 8822 8823 /* Benchmark memcpy() methods (needs FB manager initialized) */ 8824 /* Dual head: Do this AFTER the mode for CRT1 has been set */ 8825 pSiS->NeedCopyFastVidCpy = FALSE; 8826 if(!pSiS->SiSFastVidCopyDone) { 8827#ifdef SISDUALHEAD 8828 if(pSiS->DualHeadMode) { 8829 if(pSiS->SecondHead) { 8830 pSiSEnt->SiSFastVidCopy = SiSVidCopyInit(pScreen, &pSiSEnt->SiSFastMemCopy, FALSE); 8831 pSiSEnt->SiSFastVidCopyFrom = SiSVidCopyGetDefault(); 8832 pSiSEnt->SiSFastMemCopyFrom = SiSVidCopyGetDefault(); 8833#ifdef SIS_USE_EXA 8834 if(pSiS->useEXA) { 8835 pSiSEnt->SiSFastVidCopyFrom = SiSVidCopyInit(pScreen, &pSiSEnt->SiSFastMemCopyFrom, TRUE); 8836 } 8837#endif /* EXA */ 8838 pSiSEnt->HaveFastVidCpy = TRUE; 8839 pSiS->SiSFastVidCopy = pSiSEnt->SiSFastVidCopy; 8840 pSiS->SiSFastMemCopy = pSiSEnt->SiSFastMemCopy; 8841 pSiS->SiSFastVidCopyFrom = pSiSEnt->SiSFastVidCopyFrom; 8842 pSiS->SiSFastMemCopyFrom = pSiSEnt->SiSFastMemCopyFrom; 8843 } else { 8844 pSiS->NeedCopyFastVidCpy = TRUE; 8845 } 8846 } else { 8847#endif 8848 pSiS->SiSFastVidCopy = SiSVidCopyInit(pScreen, &pSiS->SiSFastMemCopy, FALSE); 8849 pSiS->SiSFastVidCopyFrom = SiSVidCopyGetDefault(); 8850 pSiS->SiSFastMemCopyFrom = SiSVidCopyGetDefault(); 8851#ifdef SIS_USE_EXA 8852 if(pSiS->useEXA) { 8853 pSiS->SiSFastVidCopyFrom = SiSVidCopyInit(pScreen, &pSiS->SiSFastMemCopyFrom, TRUE); 8854 } 8855#endif /* EXA */ 8856#ifdef SISDUALHEAD 8857 } 8858#endif 8859 } 8860 pSiS->SiSFastVidCopyDone = TRUE; 8861 8862 miInitializeBackingStore(pScreen); 8863 xf86SetBackingStore(pScreen); 8864 xf86SetSilkenMouse(pScreen); 8865 8866 /* Initialise cursor functions */ 8867 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 8868 8869 if(pSiS->HWCursor) { 8870 SiSHWCursorInit(pScreen); 8871 } 8872 8873#ifdef SISDUALHEAD 8874 if(!pSiS->DualHeadMode) { 8875#endif 8876 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && (pScrn->depth > 8)) { 8877 8878 pSiS->CRT2ColNum = 1 << pScrn->rgbBits; 8879 8880 if((pSiS->crt2gcolortable = malloc(pSiS->CRT2ColNum * 2 * sizeof(LOCO)))) { 8881 pSiS->crt2colors = &pSiS->crt2gcolortable[pSiS->CRT2ColNum]; 8882 if((pSiS->crt2cindices = malloc(256 * sizeof(int)))) { 8883 int i = pSiS->CRT2ColNum; 8884 SISCalculateGammaRampCRT2(pScrn); 8885 while(i--) pSiS->crt2cindices[i] = i; 8886 } else { 8887 free(pSiS->crt2gcolortable); 8888 pSiS->crt2gcolortable = NULL; 8889 pSiS->CRT2SepGamma = FALSE; 8890 } 8891 } else { 8892 pSiS->CRT2SepGamma = FALSE; 8893 } 8894 8895 if(!pSiS->crt2cindices) { 8896 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 8897 "Failed to allocate cmap for CRT2, separate gamma correction disabled\n"); 8898 } 8899 8900 } 8901#ifdef SISDUALHEAD 8902 } else pSiS->CRT2SepGamma = FALSE; 8903#endif 8904 8905 /* Initialise default colormap */ 8906 if(!miCreateDefColormap(pScreen)) { 8907 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8908 SISErrorLog(pScrn, "miCreateDefColormap() failed\n"); 8909 return FALSE; 8910 } 8911 8912 if(!xf86HandleColormaps(pScreen, 256, (pScrn->depth == 8) ? 8 : pScrn->rgbBits, 8913 SISLoadPalette, NULL, 8914 CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH)) { 8915 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8916 SISErrorLog(pScrn, "xf86HandleColormaps() failed\n"); 8917 return FALSE; 8918 } 8919 8920 /* Recalculate our gamma ramp for brightness feature */ 8921#ifdef SISGAMMARAMP 8922 if((pSiS->GammaBriR != 1000) || 8923 (pSiS->GammaBriB != 1000) || 8924 (pSiS->GammaBriG != 1000) || 8925 (pSiS->NewGammaBriR != 0.0) || 8926 (pSiS->NewGammaBriG != 0.0) || 8927 (pSiS->NewGammaBriB != 0.0) || 8928 (pSiS->NewGammaConR != 0.0) || 8929 (pSiS->NewGammaConG != 0.0) || 8930 (pSiS->NewGammaConB != 0.0)) { 8931 SISCalculateGammaRamp(pScreen, pScrn); 8932 } 8933#endif 8934 8935 /* Initialize Shadow framebuffer and screen rotation/reflection */ 8936 if(pSiS->ShadowFB) { 8937 RefreshAreaFuncPtr refreshArea = SISRefreshArea; 8938 8939 if(pSiS->Rotate) { 8940 if(!pSiS->PointerMoved) pSiS->PointerMoved = pScrn->PointerMoved; 8941 pScrn->PointerMoved = SISPointerMoved; 8942 switch(pScrn->bitsPerPixel) { 8943 case 8: refreshArea = SISRefreshArea8; break; 8944 case 16: refreshArea = SISRefreshArea16; break; 8945 case 24: refreshArea = SISRefreshArea24; break; 8946 case 32: refreshArea = SISRefreshArea32; break; 8947 } 8948#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 8949 xf86DisableRandR(); 8950 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8951 "Driver rotation enabled, disabling RandR\n"); 8952#endif 8953 } else if(pSiS->Reflect) { 8954 switch(pScrn->bitsPerPixel) { 8955 case 8: 8956 case 16: 8957 case 32: 8958 if(!pSiS->PointerMoved) pSiS->PointerMoved = pScrn->PointerMoved; 8959 pScrn->PointerMoved = SISPointerMovedReflect; 8960 refreshArea = SISRefreshAreaReflect; 8961#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 8962 xf86DisableRandR(); 8963 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8964 "Driver reflection enabled, disabling RandR\n"); 8965#endif 8966 break; 8967 default: 8968 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 8969 "Reflection not supported at this framebuffer depth\n"); 8970 } 8971 } 8972 8973 ShadowFBInit(pScreen, refreshArea); 8974 } 8975 8976 xf86DPMSInit(pScreen, (DPMSSetProcPtr)SISDisplayPowerManagementSet, 0); 8977 8978 /* Init memPhysBase and fbOffset in pScrn */ 8979 pScrn->memPhysBase = pSiS->FbAddress; 8980 pScrn->fbOffset = 0; 8981 8982 /* Initialize Xv */ 8983 pSiS->ResetXv = pSiS->ResetXvGamma = pSiS->ResetXvDisplay = NULL; 8984#if (XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,99,0,0)) || (defined(XvExtension)) 8985 if((!pSiS->NoXvideo) && (!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY))) { 8986 8987 if((pSiS->VGAEngine == SIS_300_VGA) || 8988 (pSiS->VGAEngine == SIS_315_VGA)) { 8989 8990 const char *using = "Using SiS300/315/330/340 series HW Xv"; 8991 8992#ifdef SISDUALHEAD 8993 if(pSiS->DualHeadMode) { 8994 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8995 "%s on CRT%d\n", using, (pSiS->SecondHead ? 1 : 2)); 8996 if(!pSiS->hasTwoOverlays) { 8997 if( (pSiS->XvOnCRT2 && pSiS->SecondHead) || 8998 (!pSiS->XvOnCRT2 && !pSiS->SecondHead) ) { 8999 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9000 "However, video overlay will by default only be visible on CRT%d\n", 9001 pSiS->XvOnCRT2 ? 2 : 1); 9002 } 9003 } 9004 } else { 9005#endif 9006 if(pSiS->hasTwoOverlays) { 9007 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s\n", using); 9008 } else { 9009 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s by default on CRT%d\n", 9010 using, (pSiS->XvOnCRT2 ? 2 : 1)); 9011 } 9012#ifdef SISDUALHEAD 9013 } 9014#endif 9015 9016 SISInitVideo(pScreen); 9017 9018 if(pSiS->blitadaptor) { 9019 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9020 "Default Xv adaptor is Video %s\n", 9021 pSiS->XvDefAdaptorBlit ? "Blitter" : "Overlay"); 9022 } 9023 9024 } else if(pSiS->Chipset == PCI_CHIP_SIS530 || 9025 pSiS->Chipset == PCI_CHIP_SIS6326 || 9026 pSiS->Chipset == PCI_CHIP_SIS5597) { 9027 9028 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9029 "Using SiS5597/5598/6326/530/620 HW Xv\n" ); 9030 9031 SIS6326InitVideo(pScreen); 9032 9033 } else { /* generic Xv */ 9034 9035 XF86VideoAdaptorPtr *ptr; 9036 int n = xf86XVListGenericAdaptors(pScrn, &ptr); 9037 9038 if(n) { 9039 xf86XVScreenInit(pScreen, ptr, n); 9040 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using generic Xv\n" ); 9041 } 9042 9043 } 9044 } 9045#endif 9046 9047#ifdef SISDRI 9048 if(pSiS->loadDRI) { 9049 if(pSiS->directRenderingEnabled) { 9050 /* Now that mi, drm and others have done their thing, 9051 * complete the DRI setup. 9052 */ 9053 pSiS->directRenderingEnabled = SISDRIFinishScreenInit(pScreen); 9054 } 9055 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering %s\n", 9056 pSiS->directRenderingEnabled ? "enabled" : "disabled"); 9057 /* TODO */ 9058 /* if(pSiS->directRenderingEnabled) SISSetLFBConfig(pSiS); */ 9059 } 9060#endif 9061 9062 /* Wrap some funcs, initialize pseudo-Xinerama and setup remaining SD flags */ 9063 9064 pSiS->SiS_SD_Flags &= ~(SiS_SD_PSEUDOXINERAMA); 9065#ifdef SISMERGED 9066 if(pSiS->MergedFB) { 9067 pSiS->PointerMoved = pScrn->PointerMoved; 9068 pScrn->PointerMoved = SISMergedPointerMoved; 9069 pSiS->Rotate = 0; 9070 pSiS->Reflect = 0; 9071 pSiS->ShadowFB = FALSE; 9072#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 9073 if(pSiS->CRT1XOffs || pSiS->CRT1YOffs || pSiS->CRT2XOffs || pSiS->CRT2YOffs) { 9074 xf86DisableRandR(); 9075 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9076 "MergedFB: CRT2Position offset used, disabling RandR\n"); 9077 } 9078#endif 9079#ifdef SISXINERAMA 9080 if(pSiS->UseSiSXinerama) { 9081 SiSnoPanoramiXExtension = FALSE; 9082 SiSXineramaExtensionInit(pScrn); 9083 if(!SiSnoPanoramiXExtension) { 9084 pSiS->SiS_SD_Flags |= SiS_SD_PSEUDOXINERAMA; 9085 if(pSiS->HaveNonRect) { 9086 /* Reset the viewport (now eventually non-recangular) */ 9087 SISAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 9088 } 9089 } 9090 } else { 9091 pSiS->MouseRestrictions = FALSE; 9092 } 9093#endif 9094 } 9095#endif 9096 9097 /* Wrap CloseScreen and set up SaveScreen */ 9098 pSiS->CloseScreen = pScreen->CloseScreen; 9099 pScreen->CloseScreen = SISCloseScreen; 9100#ifdef SISDUALHEAD 9101 if(pSiS->DualHeadMode) 9102 pScreen->SaveScreen = SISSaveScreenDH; 9103 else 9104#endif 9105 pScreen->SaveScreen = SISSaveScreen; 9106 9107 /* Install BlockHandler */ 9108 pSiS->BlockHandler = pScreen->BlockHandler; 9109 pScreen->BlockHandler = SISBlockHandler; 9110 9111 /* Report any unused options (only for the first generation) */ 9112 if(serverGeneration == 1) { 9113 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 9114 } 9115 9116 /* Clear frame buffer */ 9117 /* For CRT2, we don't do that at this point in dual head 9118 * mode since the mode isn't switched at this time (it will 9119 * be reset when setting the CRT1 mode). Hence, we just 9120 * save the necessary data and clear the screen when 9121 * going through this for CRT1. 9122 */ 9123 9124 OnScreenSize = pScrn->displayWidth * pScrn->currentMode->VDisplay 9125 * (pScrn->bitsPerPixel >> 3); 9126 9127 /* Turn on the screen now */ 9128 /* We do this in dual head mode after second head is finished */ 9129#ifdef SISDUALHEAD 9130 if(pSiS->DualHeadMode) { 9131 if(pSiS->SecondHead) { 9132 sisclearvram(pSiS->FbBase, OnScreenSize); 9133 sisclearvram(pSiSEnt->FbBase1, pSiSEnt->OnScreenSize1); 9134 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 9135 } else { 9136 pSiSEnt->FbBase1 = pSiS->FbBase; 9137 pSiSEnt->OnScreenSize1 = OnScreenSize; 9138 } 9139 } else { 9140#endif 9141 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 9142 sisclearvram(pSiS->FbBase, OnScreenSize); 9143#ifdef SISDUALHEAD 9144 } 9145#endif 9146 9147 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTSGRCRT2; 9148#ifdef SISDUALHEAD 9149 if(!pSiS->DualHeadMode) { 9150#endif 9151 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 9152 if((pSiS->crt2cindices) && (pSiS->crt2gcolortable)) { 9153 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTSGRCRT2; 9154 } 9155 } 9156#ifdef SISDUALHEAD 9157 } 9158#endif 9159 9160 pSiS->SiS_SD_Flags &= ~SiS_SD_ISDEPTH8; 9161 if(pSiS->CurrentLayout.bitsPerPixel == 8) { 9162 pSiS->SiS_SD_Flags |= SiS_SD_ISDEPTH8; 9163 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTXVGAMMA1; 9164 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTSGRCRT2; 9165 } 9166 9167#ifdef SISGAMMARAMP 9168 pSiS->SiS_SD_Flags |= SiS_SD_CANSETGAMMA; 9169#else 9170 pSiS->SiS_SD_Flags &= ~SiS_SD_CANSETGAMMA; 9171#endif 9172 9173 SiSCtrlExtInit(pScrn); 9174 9175 return TRUE; 9176} 9177 9178/* Usually mandatory */ 9179Bool 9180SISSwitchMode(SWITCH_MODE_ARGS_DECL) 9181{ 9182 SCRN_INFO_PTR(arg); 9183 SISPtr pSiS = SISPTR(pScrn); 9184 9185 if(!pSiS->skipswitchcheck) { 9186 if(SISValidMode(arg, mode, TRUE, 0) != MODE_OK) { 9187 return FALSE; 9188 } 9189 } 9190 9191 (*pSiS->SyncAccel)(pScrn); 9192 9193 if(!(SISModeInit(pScrn, mode))) return FALSE; 9194 9195 /* Since RandR (indirectly) uses SwitchMode(), we need to 9196 * update our Xinerama info here, too, in case of resizing 9197 */ 9198#ifdef SISMERGED 9199#ifdef SISXINERAMA 9200 if(pSiS->MergedFB) { 9201 SiSUpdateXineramaScreenInfo(pScrn); 9202 } 9203#endif 9204#endif 9205 return TRUE; 9206} 9207 9208static void 9209SISSetStartAddressCRT1(SISPtr pSiS, ULong base) 9210{ 9211 UChar cr11backup; 9212 9213 inSISIDXREG(SISCR, 0x11, cr11backup); /* Unlock CRTC registers */ 9214 andSISIDXREG(SISCR, 0x11, 0x7F); 9215 outSISIDXREG(SISCR, 0x0D, base & 0xFF); 9216 outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); 9217 outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF); 9218 if(pSiS->VGAEngine == SIS_315_VGA) { 9219 setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01); 9220 } 9221 /* Eventually lock CRTC registers */ 9222 setSISIDXREG(SISCR, 0x11, 0x7F,(cr11backup & 0x80)); 9223} 9224 9225static void 9226SISSetStartAddressCRT2(SISPtr pSiS, ULong base) 9227{ 9228 SiS_UnLockCRT2(pSiS->SiS_Pr); 9229 outSISIDXREG(SISPART1, 0x06, GETVAR8(base)); 9230 outSISIDXREG(SISPART1, 0x05, GETBITS(base, 15:8)); 9231 outSISIDXREG(SISPART1, 0x04, GETBITS(base, 23:16)); 9232 if(pSiS->VGAEngine == SIS_315_VGA) { 9233 setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7); 9234 } 9235 SiS_LockCRT2(pSiS->SiS_Pr); 9236} 9237 9238#ifdef SISMERGED 9239static Bool 9240InRegion(int x, int y, region r) 9241{ 9242 return (r.x0 <= x) && (x <= r.x1) && (r.y0 <= y) && (y <= r.y1); 9243} 9244 9245static void 9246SISAdjustFrameHW_CRT1(ScrnInfoPtr pScrn, int x, int y) 9247{ 9248 SISPtr pSiS = SISPTR(pScrn); 9249 ULong base; 9250 9251 base = y * pSiS->CurrentLayout.displayWidth + x; 9252 switch(pSiS->CurrentLayout.bitsPerPixel) { 9253 case 16: base >>= 1; break; 9254 case 32: break; 9255 default: base >>= 2; 9256 } 9257 base += (pSiS->dhmOffset/4); 9258 SISSetStartAddressCRT1(pSiS, base); 9259} 9260 9261static void 9262SISAdjustFrameHW_CRT2(ScrnInfoPtr pScrn, int x, int y) 9263{ 9264 SISPtr pSiS = SISPTR(pScrn); 9265 ULong base; 9266 9267 base = y * pSiS->CurrentLayout.displayWidth + x; 9268 switch(pSiS->CurrentLayout.bitsPerPixel) { 9269 case 16: base >>= 1; break; 9270 case 32: break; 9271 default: base >>= 2; 9272 } 9273 base += (pSiS->dhmOffset/4); 9274 SISSetStartAddressCRT2(pSiS, base); 9275} 9276 9277static void 9278SISMergedPointerMoved(SCRN_ARG_TYPE arg, int x, int y) 9279{ 9280 SCRN_INFO_PTR(arg); 9281 ScrnInfoPtr pScrn1 = pScrn; 9282 SISPtr pSiS = SISPTR(pScrn1); 9283 ScrnInfoPtr pScrn2 = pSiS->CRT2pScrn; 9284 region out, in1, in2, f2, f1; 9285 int deltax, deltay; 9286 int temp1, temp2; 9287 int old1x0, old1y0, old2x0, old2y0; 9288 int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; 9289 int HVirt = pScrn1->virtualX; 9290 int VVirt = pScrn1->virtualY; 9291 int sigstate; 9292 Bool doit = FALSE, HaveNonRect = FALSE, HaveOffsRegions = FALSE; 9293 SiSScrn2Rel srel = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT2Position; 9294 9295 if(pSiS->DGAactive) { 9296 return; 9297 /* DGA: There is no cursor and no panning while DGA is active. */ 9298 /* If it were, we would need to do: */ 9299 /* HVirt = pSiS->CurrentLayout.displayWidth; 9300 VVirt = pSiS->CurrentLayout.displayHeight; 9301 BOUND(x, pSiS->CurrentLayout.DGAViewportX, HVirt); 9302 BOUND(y, pSiS->CurrentLayout.DGAViewportY, VVirt); */ 9303 } else { 9304 CRT1XOffs = pSiS->CRT1XOffs; 9305 CRT1YOffs = pSiS->CRT1YOffs; 9306 CRT2XOffs = pSiS->CRT2XOffs; 9307 CRT2YOffs = pSiS->CRT2YOffs; 9308 HaveNonRect = pSiS->HaveNonRect; 9309 HaveOffsRegions = pSiS->HaveOffsRegions; 9310 } 9311 9312 /* Check if the pointer is inside our dead areas */ 9313 if((pSiS->MouseRestrictions) && (srel != sisClone) && !SiSnoPanoramiXExtension) { 9314 if(HaveNonRect) { 9315 if(InRegion(x, y, pSiS->NonRectDead)) { 9316 switch(srel) { 9317 case sisLeftOf: 9318 case sisRightOf: y = pSiS->NonRectDead.y0 - 1; 9319 doit = TRUE; 9320 break; 9321 case sisAbove: 9322 case sisBelow: x = pSiS->NonRectDead.x0 - 1; 9323 doit = TRUE; 9324 default: break; 9325 } 9326 } 9327 } 9328 if(HaveOffsRegions) { 9329 if(InRegion(x, y, pSiS->OffDead1)) { 9330 switch(srel) { 9331 case sisLeftOf: 9332 case sisRightOf: y = pSiS->OffDead1.y1; 9333 doit = TRUE; 9334 break; 9335 case sisAbove: 9336 case sisBelow: x = pSiS->OffDead1.x1; 9337 doit = TRUE; 9338 default: break; 9339 } 9340 } else if(InRegion(x, y, pSiS->OffDead2)) { 9341 switch(srel) { 9342 case sisLeftOf: 9343 case sisRightOf: y = pSiS->OffDead2.y0 - 1; 9344 doit = TRUE; 9345 break; 9346 case sisAbove: 9347 case sisBelow: x = pSiS->OffDead2.x0 - 1; 9348 doit = TRUE; 9349 default: break; 9350 } 9351 } 9352 } 9353 if(doit) { 9354 sigstate = xf86BlockSIGIO(); 9355#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 15 9356 { 9357 double dx = x, dy = y; 9358 miPointerSetPosition(inputInfo.pointer, Absolute, &dx, &dy); 9359 x = (int)dx; 9360 y = (int)dy; 9361 } 9362#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 13 9363 miPointerSetPosition(inputInfo.pointer, Absolute, x, y); 9364#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 5 9365 miPointerSetPosition(inputInfo.pointer, x, y); 9366#else 9367 UpdateCurrentTime(); 9368 miPointerAbsoluteCursor(x, y, currentTime.milliseconds); 9369#endif 9370 xf86UnblockSIGIO(sigstate); 9371 return; 9372 } 9373 } 9374 9375 f1.x0 = old1x0 = pSiS->CRT1frameX0; 9376 f1.x1 = pSiS->CRT1frameX1; 9377 f1.y0 = old1y0 = pSiS->CRT1frameY0; 9378 f1.y1 = pSiS->CRT1frameY1; 9379 f2.x0 = old2x0 = pScrn2->frameX0; 9380 f2.x1 = pScrn2->frameX1; 9381 f2.y0 = old2y0 = pScrn2->frameY0; 9382 f2.y1 = pScrn2->frameY1; 9383 9384 /* Define the outer region. Crossing this causes all frames to move */ 9385 out.x0 = pScrn1->frameX0; 9386 out.x1 = pScrn1->frameX1; 9387 out.y0 = pScrn1->frameY0; 9388 out.y1 = pScrn1->frameY1; 9389 9390 /* 9391 * Define the inner sliding window. Being outsize both frames but 9392 * inside the outer clipping window will slide corresponding frame 9393 */ 9394 in1 = out; 9395 in2 = out; 9396 switch(srel) { 9397 case sisLeftOf: 9398 in1.x0 = f1.x0; 9399 in2.x1 = f2.x1; 9400 break; 9401 case sisRightOf: 9402 in1.x1 = f1.x1; 9403 in2.x0 = f2.x0; 9404 break; 9405 case sisBelow: 9406 in1.y1 = f1.y1; 9407 in2.y0 = f2.y0; 9408 break; 9409 case sisAbove: 9410 in1.y0 = f1.y0; 9411 in2.y1 = f2.y1; 9412 break; 9413 case sisClone: 9414 break; 9415 } 9416 9417 deltay = 0; 9418 deltax = 0; 9419 9420 if(InRegion(x, y, out)) { /* inside outer region */ 9421 9422 if(InRegion(x, y, in1) && !InRegion(x, y, f1)) { 9423 REBOUND(f1.x0, f1.x1, x); 9424 REBOUND(f1.y0, f1.y1, y); 9425 deltax = 1; 9426 } 9427 if(InRegion(x, y, in2) && !InRegion(x, y, f2)) { 9428 REBOUND(f2.x0, f2.x1, x); 9429 REBOUND(f2.y0, f2.y1, y); 9430 deltax = 1; 9431 } 9432 9433 } else { /* outside outer region */ 9434 9435 if(out.x0 > x) { 9436 deltax = x - out.x0; 9437 } 9438 if(out.x1 < x) { 9439 deltax = x - out.x1; 9440 } 9441 if(deltax) { 9442 pScrn1->frameX0 += deltax; 9443 pScrn1->frameX1 += deltax; 9444 f1.x0 += deltax; 9445 f1.x1 += deltax; 9446 f2.x0 += deltax; 9447 f2.x1 += deltax; 9448 } 9449 9450 if(out.y0 > y) { 9451 deltay = y - out.y0; 9452 } 9453 if(out.y1 < y) { 9454 deltay = y - out.y1; 9455 } 9456 if(deltay) { 9457 pScrn1->frameY0 += deltay; 9458 pScrn1->frameY1 += deltay; 9459 f1.y0 += deltay; 9460 f1.y1 += deltay; 9461 f2.y0 += deltay; 9462 f2.y1 += deltay; 9463 } 9464 9465 switch(srel) { 9466 case sisLeftOf: 9467 if(x >= f1.x0) { REBOUND(f1.y0, f1.y1, y); } 9468 if(x <= f2.x1) { REBOUND(f2.y0, f2.y1, y); } 9469 break; 9470 case sisRightOf: 9471 if(x <= f1.x1) { REBOUND(f1.y0, f1.y1, y); } 9472 if(x >= f2.x0) { REBOUND(f2.y0, f2.y1, y); } 9473 break; 9474 case sisBelow: 9475 if(y <= f1.y1) { REBOUND(f1.x0, f1.x1, x); } 9476 if(y >= f2.y0) { REBOUND(f2.x0, f2.x1, x); } 9477 break; 9478 case sisAbove: 9479 if(y >= f1.y0) { REBOUND(f1.x0, f1.x1, x); } 9480 if(y <= f2.y1) { REBOUND(f2.x0, f2.x1, x); } 9481 break; 9482 case sisClone: 9483 break; 9484 } 9485 9486 } 9487 9488 if(deltax || deltay) { 9489 pSiS->CRT1frameX0 = f1.x0; 9490 pSiS->CRT1frameY0 = f1.y0; 9491 pScrn2->frameX0 = f2.x0; 9492 pScrn2->frameY0 = f2.y0; 9493 9494 switch(srel) { 9495 case sisLeftOf: 9496 case sisRightOf: 9497 if(CRT1YOffs || CRT2YOffs || HaveNonRect) { 9498 if(pSiS->CRT1frameY0 != old1y0) { 9499 if(pSiS->CRT1frameY0 < CRT1YOffs) 9500 pSiS->CRT1frameY0 = CRT1YOffs; 9501 9502 temp1 = pSiS->CRT1frameY0 + CDMPTR->CRT1->VDisplay; 9503 temp2 = min((VVirt - CRT2YOffs), (CRT1YOffs + pSiS->MBXNR1YMAX)); 9504 if(temp1 > temp2) 9505 pSiS->CRT1frameY0 -= (temp1 - temp2); 9506 } 9507 if(pScrn2->frameY0 != old2y0) { 9508 if(pScrn2->frameY0 < CRT2YOffs) 9509 pScrn2->frameY0 = CRT2YOffs; 9510 9511 temp1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay; 9512 temp2 = min((VVirt - CRT1YOffs), (CRT2YOffs + pSiS->MBXNR2YMAX)); 9513 if(temp1 > temp2) 9514 pScrn2->frameY0 -= (temp1 - temp2); 9515 } 9516 } 9517 break; 9518 case sisBelow: 9519 case sisAbove: 9520 if(CRT1XOffs || CRT2XOffs || HaveNonRect) { 9521 if(pSiS->CRT1frameX0 != old1x0) { 9522 if(pSiS->CRT1frameX0 < CRT1XOffs) 9523 pSiS->CRT1frameX0 = CRT1XOffs; 9524 9525 temp1 = pSiS->CRT1frameX0 + CDMPTR->CRT1->HDisplay; 9526 temp2 = min((HVirt - CRT2XOffs), (CRT1XOffs + pSiS->MBXNR1XMAX)); 9527 if(temp1 > temp2) 9528 pSiS->CRT1frameX0 -= (temp1 - temp2); 9529 } 9530 if(pScrn2->frameX0 != old2x0) { 9531 if(pScrn2->frameX0 < CRT2XOffs) 9532 pScrn2->frameX0 = CRT2XOffs; 9533 9534 temp1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay; 9535 temp2 = min((HVirt - CRT1XOffs), (CRT2XOffs + pSiS->MBXNR2XMAX)); 9536 if(temp1 > temp2) 9537 pScrn2->frameX0 -= (temp1 - temp2); 9538 } 9539 } 9540 break; 9541 case sisClone: 9542 break; 9543 } 9544 9545 pSiS->CRT1frameX1 = pSiS->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1; 9546 pSiS->CRT1frameY1 = pSiS->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1; 9547 pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1; 9548 pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1; 9549 9550 /* No need to update pScrn1->frame?1, done above */ 9551 9552 SISAdjustFrameHW_CRT1(pScrn1, pSiS->CRT1frameX0, pSiS->CRT1frameY0); 9553 SISAdjustFrameHW_CRT2(pScrn1, pScrn2->frameX0, pScrn2->frameY0); 9554 } 9555} 9556 9557static void 9558SISAdjustFrameMerged(ADJUST_FRAME_ARGS_DECL) 9559{ 9560 SCRN_INFO_PTR(arg); 9561 ScrnInfoPtr pScrn1 = pScrn; 9562 SISPtr pSiS = SISPTR(pScrn1); 9563 ScrnInfoPtr pScrn2 = pSiS->CRT2pScrn; 9564 int HTotal = pSiS->CurrentLayout.mode->HDisplay; 9565 int VTotal = pSiS->CurrentLayout.mode->VDisplay; 9566 int HMax = HTotal; 9567 int VMax = VTotal; 9568 int HVirt = pScrn1->virtualX; 9569 int VVirt = pScrn1->virtualY; 9570 int x1 = x, x2 = x; 9571 int y1 = y, y2 = y; 9572 int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; 9573 int MBXNR1XMAX = 65536, MBXNR1YMAX = 65536, MBXNR2XMAX = 65536, MBXNR2YMAX = 65536; 9574 9575 if(pSiS->DGAactive) { 9576 HVirt = pSiS->CurrentLayout.displayWidth; 9577 VVirt = pSiS->CurrentLayout.displayHeight; 9578 } else { 9579 CRT1XOffs = pSiS->CRT1XOffs; 9580 CRT1YOffs = pSiS->CRT1YOffs; 9581 CRT2XOffs = pSiS->CRT2XOffs; 9582 CRT2YOffs = pSiS->CRT2YOffs; 9583 MBXNR1XMAX = pSiS->MBXNR1XMAX; 9584 MBXNR1YMAX = pSiS->MBXNR1YMAX; 9585 MBXNR2XMAX = pSiS->MBXNR2XMAX; 9586 MBXNR2YMAX = pSiS->MBXNR2YMAX; 9587 } 9588 9589 BOUND(x, 0, HVirt - HTotal); 9590 BOUND(y, 0, VVirt - VTotal); 9591 if(SDMPTR(pScrn1)->CRT2Position != sisClone) { 9592 BOUND(x1, CRT1XOffs, min(HVirt, MBXNR1XMAX + CRT1XOffs) - min(HTotal, MBXNR1XMAX) - CRT2XOffs); 9593 BOUND(y1, CRT1YOffs, min(VVirt, MBXNR1YMAX + CRT1YOffs) - min(VTotal, MBXNR1YMAX) - CRT2YOffs); 9594 BOUND(x2, CRT2XOffs, min(HVirt, MBXNR2XMAX + CRT2XOffs) - min(HTotal, MBXNR2XMAX) - CRT1XOffs); 9595 BOUND(y2, CRT2YOffs, min(VVirt, MBXNR2YMAX + CRT2YOffs) - min(VTotal, MBXNR2YMAX) - CRT1YOffs); 9596 } 9597 9598 switch(SDMPTR(pScrn1)->CRT2Position) { 9599 case sisLeftOf: 9600 pScrn2->frameX0 = x2; 9601 BOUND(pScrn2->frameY0, y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR->CRT2->VDisplay); 9602 pSiS->CRT1frameX0 = x1 + CDMPTR->CRT2->HDisplay; 9603 BOUND(pSiS->CRT1frameY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR->CRT1->VDisplay); 9604 break; 9605 case sisRightOf: 9606 pSiS->CRT1frameX0 = x1; 9607 BOUND(pSiS->CRT1frameY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR->CRT1->VDisplay); 9608 pScrn2->frameX0 = x2 + CDMPTR->CRT1->HDisplay; 9609 BOUND(pScrn2->frameY0, y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR->CRT2->VDisplay); 9610 break; 9611 case sisAbove: 9612 BOUND(pScrn2->frameX0, x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR->CRT2->HDisplay); 9613 pScrn2->frameY0 = y2; 9614 BOUND(pSiS->CRT1frameX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR->CRT1->HDisplay); 9615 pSiS->CRT1frameY0 = y1 + CDMPTR->CRT2->VDisplay; 9616 break; 9617 case sisBelow: 9618 BOUND(pSiS->CRT1frameX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR->CRT1->HDisplay); 9619 pSiS->CRT1frameY0 = y1; 9620 BOUND(pScrn2->frameX0, x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR->CRT2->HDisplay); 9621 pScrn2->frameY0 = y2 + CDMPTR->CRT1->VDisplay; 9622 break; 9623 case sisClone: 9624 BOUND(pSiS->CRT1frameX0, x, x + HMax - CDMPTR->CRT1->HDisplay); 9625 BOUND(pSiS->CRT1frameY0, y, y + VMax - CDMPTR->CRT1->VDisplay); 9626 BOUND(pScrn2->frameX0, x, x + HMax - CDMPTR->CRT2->HDisplay); 9627 BOUND(pScrn2->frameY0, y, y + VMax - CDMPTR->CRT2->VDisplay); 9628 break; 9629 } 9630 9631 BOUND(pSiS->CRT1frameX0, 0, HVirt - CDMPTR->CRT1->HDisplay); 9632 BOUND(pSiS->CRT1frameY0, 0, VVirt - CDMPTR->CRT1->VDisplay); 9633 BOUND(pScrn2->frameX0, 0, HVirt - CDMPTR->CRT2->HDisplay); 9634 BOUND(pScrn2->frameY0, 0, VVirt - CDMPTR->CRT2->VDisplay); 9635 9636 pScrn1->frameX0 = x; 9637 pScrn1->frameY0 = y; 9638 9639 pSiS->CRT1frameX1 = pSiS->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1; 9640 pSiS->CRT1frameY1 = pSiS->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1; 9641 pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1; 9642 pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1; 9643 9644 pScrn1->frameX1 = pScrn1->frameX0 + pSiS->CurrentLayout.mode->HDisplay - 1; 9645 pScrn1->frameY1 = pScrn1->frameY0 + pSiS->CurrentLayout.mode->VDisplay - 1; 9646 if(SDMPTR(pScrn1)->CRT2Position != sisClone) { 9647 pScrn1->frameX1 += CRT1XOffs + CRT2XOffs; 9648 pScrn1->frameY1 += CRT1YOffs + CRT2YOffs; 9649 } 9650 9651 SISAdjustFrameHW_CRT1(pScrn1, pSiS->CRT1frameX0, pSiS->CRT1frameY0); 9652 SISAdjustFrameHW_CRT2(pScrn1, pScrn2->frameX0, pScrn2->frameY0); 9653} 9654#endif 9655 9656/* 9657 * This function is used to initialize the Start Address - the first 9658 * displayed location in the video memory. 9659 * 9660 * Usually mandatory 9661 */ 9662void 9663SISAdjustFrame(ADJUST_FRAME_ARGS_DECL) 9664{ 9665 SCRN_INFO_PTR(arg); 9666 SISPtr pSiS = SISPTR(pScrn); 9667 ULong base; 9668 UChar temp, cr11backup; 9669 9670#ifdef SISMERGED 9671 if(pSiS->MergedFB) { 9672 SISAdjustFrameMerged(ADJUST_FRAME_ARGS(pScrn, x, y)); 9673 return; 9674 } 9675#endif 9676 9677 if(pSiS->UseVESA) { 9678 VBESetDisplayStart(pSiS->pVbe, x, y, TRUE); 9679 return; 9680 } 9681 9682 if(pScrn->bitsPerPixel < 8) { 9683 base = (y * pSiS->CurrentLayout.displayWidth + x + 3) >> 3; 9684 } else { 9685 base = y * pSiS->CurrentLayout.displayWidth + x; 9686 9687 /* calculate base bpp dep. */ 9688 switch(pSiS->CurrentLayout.bitsPerPixel) { 9689 case 16: 9690 base >>= 1; 9691 break; 9692 case 24: 9693 base = ((base * 3)) >> 2; 9694 base -= base % 6; 9695 break; 9696 case 32: 9697 break; 9698 default: /* 8bpp */ 9699 base >>= 2; 9700 break; 9701 } 9702 } 9703 9704#ifdef UNLOCK_ALWAYS 9705 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 9706#endif 9707 9708 base += (pSiS->dhmOffset/4); 9709 9710#ifdef TWDEBUG 9711 xf86DrvMsg(0, 0, "AdjustFrame: x %d y %d bpp %d dw %d base %d, dhmOffset %d\n", 9712 x, y, pSiS->CurrentLayout.bitsPerPixel, pSiS->CurrentLayout.displayWidth, base, pSiS->dhmOffset); 9713#endif 9714 9715#ifdef SISDUALHEAD 9716 if(pSiS->DualHeadMode) { 9717 if(!pSiS->SecondHead) { 9718 /* Head 1 (master) is always CRT2 */ 9719 SISSetStartAddressCRT2(pSiS, base); 9720 } else { 9721 /* Head 2 (slave) is always CRT1 */ 9722 SISSetStartAddressCRT1(pSiS, base); 9723 } 9724 } else { 9725#endif 9726 switch(pSiS->VGAEngine) { 9727 case SIS_300_VGA: 9728 case SIS_315_VGA: 9729 SISSetStartAddressCRT1(pSiS, base); 9730 if(pSiS->VBFlags & CRT2_ENABLE) { 9731 if(!SiSBridgeIsInSlaveMode(pScrn)) { 9732 SISSetStartAddressCRT2(pSiS, base); 9733 } 9734 } 9735 break; 9736 default: 9737 /* Unlock CRTC registers */ 9738 inSISIDXREG(SISCR, 0x11, cr11backup); 9739 andSISIDXREG(SISCR, 0x11, 0x7F); 9740 outSISIDXREG(SISCR, 0x0D, base & 0xFF); 9741 outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); 9742 inSISIDXREG(SISSR, 0x27, temp); 9743 temp &= 0xF0; 9744 temp |= (base & 0x0F0000) >> 16; 9745 outSISIDXREG(SISSR, 0x27, temp); 9746 /* Eventually lock CRTC registers */ 9747 setSISIDXREG(SISCR, 0x11, 0x7F, (cr11backup & 0x80)); 9748 } 9749#ifdef SISDUALHEAD 9750 } 9751#endif 9752 9753} 9754 9755/* 9756 * This is called when VT switching back to the X server. Its job is 9757 * to reinitialise the video mode. 9758 * Mandatory! 9759 */ 9760static Bool 9761SISEnterVT(VT_FUNC_ARGS_DECL) 9762{ 9763 SCRN_INFO_PTR(arg); 9764 SISPtr pSiS = SISPTR(pScrn); 9765 9766 SiS_SiSFB_Lock(pScrn, TRUE); 9767 9768 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 9769 9770 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 9771 outSISIDXREG(SISCR,0x32,pSiS->myCR32); 9772 outSISIDXREG(SISCR,0x36,pSiS->myCR36); 9773 outSISIDXREG(SISCR,0x37,pSiS->myCR37); 9774 } 9775 9776 if(!SISModeInit(pScrn, pScrn->currentMode)) { 9777 SISErrorLog(pScrn, "SiSEnterVT: SISModeInit() failed\n"); 9778 return FALSE; 9779 } 9780 9781 SISAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 9782 9783#ifdef SISDRI 9784 if(pSiS->directRenderingEnabled) { 9785 DRIUnlock(xf86ScrnToScreen(pScrn)); 9786 } 9787#endif 9788 9789#ifdef SISDUALHEAD 9790 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) 9791#endif 9792 if(pSiS->ResetXv) { 9793 (pSiS->ResetXv)(pScrn); 9794 } 9795 9796 return TRUE; 9797} 9798 9799/* 9800 * This is called when VT switching away from the X server. Its job is 9801 * to restore the previous (text) mode. 9802 * Mandatory! 9803 */ 9804static void 9805SISLeaveVT(VT_FUNC_ARGS_DECL) 9806{ 9807 SCRN_INFO_PTR(arg); 9808 SISPtr pSiS = SISPTR(pScrn); 9809#ifdef SISDRI 9810 ScreenPtr pScreen; 9811 9812 if(pSiS->directRenderingEnabled) { 9813 pScreen = xf86ScrnToScreen(pScrn); 9814 DRILock(pScreen, 0); 9815 } 9816#endif 9817 9818#ifdef SISDUALHEAD 9819 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 9820#endif 9821 9822 if(pSiS->CursorInfoPtr) { 9823#ifdef SISDUALHEAD 9824 if(pSiS->DualHeadMode) { 9825 if(!pSiS->SecondHead) { 9826 pSiS->ForceCursorOff = TRUE; 9827 pSiS->CursorInfoPtr->HideCursor(pScrn); 9828 SISWaitVBRetrace(pScrn); 9829 pSiS->ForceCursorOff = FALSE; 9830 } 9831 } else { 9832#endif 9833 pSiS->CursorInfoPtr->HideCursor(pScrn); 9834 SISWaitVBRetrace(pScrn); 9835#ifdef SISDUALHEAD 9836 } 9837#endif 9838 } 9839 9840 SISBridgeRestore(pScrn); 9841 9842 if(pSiS->UseVESA) { 9843 9844 /* This is a q&d work-around for a BIOS bug. In case we disabled CRT2, 9845 * VBESaveRestore() does not restore CRT1. So we set any mode now, 9846 * because VBESetVBEMode correctly restores CRT1. Afterwards, we 9847 * can call VBESaveRestore to restore original mode. 9848 */ 9849 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (!(pSiS->VBFlags & DISPTYPE_DISP2))) 9850 VBESetVBEMode(pSiS->pVbe, (pSiS->SISVESAModeList->n) | 0xc000, NULL); 9851 9852 SISVESARestore(pScrn); 9853 9854 } else { 9855 9856 SISRestore(pScrn); 9857 9858 } 9859 9860 /* We use (otherwise unused) bit 7 to indicate that we are running 9861 * to keep sisfb to change the displaymode (this would result in 9862 * lethal display corruption upon quitting X or changing to a VT 9863 * until a reboot) 9864 */ 9865 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 9866 orSISIDXREG(SISCR,0x34,0x80); 9867 } 9868 9869 SISVGALock(pSiS); 9870 9871 SiS_SiSFB_Lock(pScrn, FALSE); 9872} 9873 9874 9875/* 9876 * This is called at the end of each server generation. It restores the 9877 * original (text) mode. It should really also unmap the video memory too. 9878 * Mandatory! 9879 */ 9880static Bool 9881SISCloseScreen(CLOSE_SCREEN_ARGS_DECL) 9882{ 9883 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 9884 SISPtr pSiS = SISPTR(pScrn); 9885#ifdef SISDUALHEAD 9886 SISEntPtr pSiSEnt = pSiS->entityPrivate; 9887#endif 9888 9889 if(pSiS->SiSCtrlExtEntry) { 9890 SiSCtrlExtUnregister(pSiS, pScrn->scrnIndex); 9891 } 9892 9893#ifdef SISDRI 9894 if(pSiS->directRenderingEnabled) { 9895 SISDRICloseScreen(pScreen); 9896 pSiS->directRenderingEnabled = FALSE; 9897 } 9898#endif 9899 9900 if(pScrn->vtSema) { 9901 9902 if(pSiS->CursorInfoPtr) { 9903#ifdef SISDUALHEAD 9904 if(pSiS->DualHeadMode) { 9905 if(!pSiS->SecondHead) { 9906 pSiS->ForceCursorOff = TRUE; 9907 pSiS->CursorInfoPtr->HideCursor(pScrn); 9908 SISWaitVBRetrace(pScrn); 9909 pSiS->ForceCursorOff = FALSE; 9910 } 9911 } else { 9912#endif 9913 pSiS->CursorInfoPtr->HideCursor(pScrn); 9914 SISWaitVBRetrace(pScrn); 9915#ifdef SISDUALHEAD 9916 } 9917#endif 9918 } 9919 9920 SISBridgeRestore(pScrn); 9921 9922 if(pSiS->UseVESA) { 9923 9924 /* This is a q&d work-around for a BIOS bug. In case we disabled CRT2, 9925 * VBESaveRestore() does not restore CRT1. So we set any mode now, 9926 * because VBESetVBEMode correctly restores CRT1. Afterwards, we 9927 * can call VBESaveRestore to restore original mode. 9928 */ 9929 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (!(pSiS->VBFlags & DISPTYPE_DISP2))) 9930 VBESetVBEMode(pSiS->pVbe, (pSiS->SISVESAModeList->n) | 0xc000, NULL); 9931 9932 SISVESARestore(pScrn); 9933 9934 } else { 9935 9936 SISRestore(pScrn); 9937 9938 } 9939 9940 SISVGALock(pSiS); 9941 9942 } 9943 9944 SiS_SiSFB_Lock(pScrn, FALSE); 9945 9946 /* We should restore the mode number in case vtsema = false as well, 9947 * but since we haven't register access then we can't do it. I think 9948 * I need to rework the save/restore stuff, like saving the video 9949 * status when returning to the X server and by that save me the 9950 * trouble if sisfb was started from a textmode VT while X was on. 9951 */ 9952 9953 SISUnmapMem(pScrn); 9954#ifdef SIS_PC_PLATFORM 9955 SiSVGAUnmapMem(pScrn); 9956#endif 9957 9958#ifdef SISDUALHEAD 9959 if(pSiS->DualHeadMode) { 9960 pSiSEnt = pSiS->entityPrivate; 9961 pSiSEnt->refCount--; 9962 } 9963#endif 9964 9965 if(pSiS->pInt) { 9966 xf86FreeInt10(pSiS->pInt); 9967 pSiS->pInt = NULL; 9968 } 9969 9970#ifdef SIS_USE_XAA 9971 if(!pSiS->useEXA) { 9972 if(pSiS->AccelLinearScratch) { 9973 xf86FreeOffscreenLinear(pSiS->AccelLinearScratch); 9974 pSiS->AccelLinearScratch = NULL; 9975 } 9976 if(pSiS->AccelInfoPtr) { 9977 XAADestroyInfoRec(pSiS->AccelInfoPtr); 9978 pSiS->AccelInfoPtr = NULL; 9979 } 9980 } 9981#endif 9982 9983#ifdef SIS_USE_EXA 9984 if(pSiS->useEXA) { 9985 if(pSiS->EXADriverPtr) { 9986 exaDriverFini(pScreen); 9987 free(pSiS->EXADriverPtr); 9988 pSiS->EXADriverPtr = NULL; 9989 pSiS->exa_scratch = NULL; 9990 } 9991 } 9992#endif 9993 9994 if(pSiS->CursorInfoPtr) { 9995 xf86DestroyCursorInfoRec(pSiS->CursorInfoPtr); 9996 pSiS->CursorInfoPtr = NULL; 9997 } 9998 9999 if(pSiS->ShadowPtr) { 10000 free(pSiS->ShadowPtr); 10001 pSiS->ShadowPtr = NULL; 10002 } 10003 10004 if(pSiS->DGAModes) { 10005 free(pSiS->DGAModes); 10006 pSiS->DGAModes = NULL; 10007 } 10008 10009 if(pSiS->adaptor) { 10010 free(pSiS->adaptor); 10011 pSiS->adaptor = NULL; 10012 pSiS->ResetXv = pSiS->ResetXvGamma = pSiS->ResetXvDisplay = NULL; 10013 } 10014 10015 if(pSiS->blitadaptor) { 10016 free(pSiS->blitadaptor); 10017 pSiS->blitadaptor = NULL; 10018 } 10019 10020 if(pSiS->crt2gcolortable) { 10021 free(pSiS->crt2gcolortable); 10022 pSiS->crt2gcolortable = NULL; 10023 } 10024 10025 if(pSiS->crt2cindices) { 10026 free(pSiS->crt2cindices); 10027 pSiS->crt2cindices = NULL; 10028 } 10029 10030 pScrn->vtSema = FALSE; 10031 10032 /* Restore Blockhandler */ 10033 pScreen->BlockHandler = pSiS->BlockHandler; 10034 10035 pScreen->CloseScreen = pSiS->CloseScreen; 10036 10037 return(*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); 10038} 10039 10040 10041/* Free up any per-generation data structures */ 10042 10043/* Optional */ 10044static void 10045SISFreeScreen(FREE_SCREEN_ARGS_DECL) 10046{ 10047 SCRN_INFO_PTR(arg); 10048#ifdef SIS_NEED_MAP_IOP 10049 SISPtr pSiS = SISPTR(pScrn); 10050 10051 if(pSiS) { 10052#ifdef SISDUALHEAD 10053 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10054 if(pSiSEnt) { 10055 pSiSEnt->forceUnmapIOPBase = TRUE; 10056 } 10057#endif 10058 SISUnmapIOPMem(pScrn); 10059 } 10060#endif 10061 10062 SISFreeRec(pScrn); 10063} 10064 10065 10066/* Checks if a mode is suitable for the selected chipset. */ 10067 10068static ModeStatus 10069SISValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 10070{ 10071 SCRN_INFO_PTR(arg); 10072 SISPtr pSiS = SISPTR(pScrn); 10073 10074 if(pSiS->UseVESA) { 10075 if(SiSCalcVESAModeIndex(pScrn, mode)) 10076 return(MODE_OK); 10077 else 10078 return(MODE_BAD); 10079 } 10080 10081 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 10082#ifdef SISDUALHEAD 10083 if(pSiS->DualHeadMode) { 10084 if(pSiS->SecondHead) { 10085 if(SiS_CheckModeCRT1(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10086 return(MODE_BAD); 10087 } else { 10088 if(SiS_CheckModeCRT2(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10089 return(MODE_BAD); 10090 } 10091 } else 10092#endif 10093#ifdef SISMERGED 10094 if(pSiS->MergedFB) { 10095 if(!mode->Private) { 10096 if(!pSiS->CheckForCRT2) { 10097 if(SiS_CheckModeCRT1(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10098 return(MODE_BAD); 10099 } else { 10100 if(SiS_CheckModeCRT2(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes2) < 0x14) 10101 return(MODE_BAD); 10102 } 10103 } else { 10104 if(SiS_CheckModeCRT1(pScrn, ((SiSMergedDisplayModePtr)mode->Private)->CRT1, 10105 pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10106 return(MODE_BAD); 10107 10108 if(SiS_CheckModeCRT2(pScrn, ((SiSMergedDisplayModePtr)mode->Private)->CRT2, 10109 pSiS->VBFlags, pSiS->HaveCustomModes2) < 0x14) 10110 return(MODE_BAD); 10111 } 10112 } else 10113#endif 10114 { 10115 if(SiS_CheckModeCRT1(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10116 return(MODE_BAD); 10117 10118 if(SiS_CheckModeCRT2(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10119 return(MODE_BAD); 10120 } 10121 } 10122 10123 return(MODE_OK); 10124} 10125 10126#ifdef DEBUG 10127static void 10128SiSDumpModeInfo(ScrnInfoPtr pScrn, DisplayModePtr mode) 10129{ 10130 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Clock : %x\n", mode->Clock); 10131 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Display : %x\n", mode->CrtcHDisplay); 10132 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Blank Start : %x\n", mode->CrtcHBlankStart); 10133 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Sync Start : %x\n", mode->CrtcHSyncStart); 10134 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Sync End : %x\n", mode->CrtcHSyncEnd); 10135 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Blank End : %x\n", mode->CrtcHBlankEnd); 10136 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Total : %x\n", mode->CrtcHTotal); 10137 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Skew : %x\n", mode->CrtcHSkew); 10138 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz HAdjusted : %x\n", mode->CrtcHAdjusted); 10139 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Display : %x\n", mode->CrtcVDisplay); 10140 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Blank Start : %x\n", mode->CrtcVBlankStart); 10141 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Sync Start : %x\n", mode->CrtcVSyncStart); 10142 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Sync End : %x\n", mode->CrtcVSyncEnd); 10143 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Blank End : %x\n", mode->CrtcVBlankEnd); 10144 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Total : %x\n", mode->CrtcVTotal); 10145 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt VAdjusted : %x\n", mode->CrtcVAdjusted); 10146} 10147#endif 10148 10149static void 10150SISModifyModeInfo(DisplayModePtr mode) 10151{ 10152 if(mode->CrtcHBlankStart == mode->CrtcHDisplay) 10153 mode->CrtcHBlankStart++; 10154 if(mode->CrtcHBlankEnd == mode->CrtcHTotal) 10155 mode->CrtcHBlankEnd--; 10156 if(mode->CrtcVBlankStart == mode->CrtcVDisplay) 10157 mode->CrtcVBlankStart++; 10158 if(mode->CrtcVBlankEnd == mode->CrtcVTotal) 10159 mode->CrtcVBlankEnd--; 10160} 10161 10162/* Enable the Turboqueue/Commandqueue (For 300 and 315/330/340 series only) */ 10163static void 10164SiSEnableTurboQueue(ScrnInfoPtr pScrn) 10165{ 10166 SISPtr pSiS = SISPTR(pScrn); 10167 UShort SR26, SR27; 10168 ULong temp; 10169 10170 switch(pSiS->VGAEngine) { 10171 case SIS_300_VGA: 10172 if((!pSiS->NoAccel) && (pSiS->TurboQueue)) { 10173 /* TQ size is always 512k */ 10174 temp = (pScrn->videoRam/64) - 8; 10175 SR26 = temp & 0xFF; 10176 inSISIDXREG(SISSR, 0x27, SR27); 10177 SR27 &= 0xFC; 10178 SR27 |= (0xF0 | ((temp >> 8) & 3)); 10179 outSISIDXREG(SISSR, 0x26, SR26); 10180 outSISIDXREG(SISSR, 0x27, SR27); 10181 } 10182 break; 10183 10184 case SIS_315_VGA: 10185 if(!pSiS->NoAccel) { 10186 /* On 315/330/340 series, there are three queue modes available 10187 * which are chosen by setting bits 7:5 in SR26: 10188 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep 10189 * track of the queue, the FIFO, command parsing and so 10190 * on. This is the one comparable to the 300 series. 10191 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will 10192 * have to do queue management himself. 10193 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the 10194 * queue in AGP memory space. 10195 * We go VRAM or MMIO here. 10196 * SR26 bit 4 is called "Bypass H/W queue". 10197 * SR26 bit 1 is called "Enable Command Queue Auto Correction" 10198 * SR26 bit 0 resets the queue 10199 * Size of queue memory is encoded in bits 3:2 like this: 10200 * 00 (0x00) 512K 10201 * 01 (0x04) 1M 10202 * 10 (0x08) 2M 10203 * 11 (0x0C) 4M 10204 * The queue location is to be written to 0x85C0. 10205 */ 10206#ifdef SISVRAMQ 10207 /* We use VRAM Cmd Queue, not MMIO or AGP */ 10208 UChar tempCR55 = 0; 10209 10210 /* Set Command Queue Threshold to max value 11111b (?) */ 10211 outSISIDXREG(SISSR, 0x27, 0x1F); 10212 10213 /* Disable queue flipping */ 10214 inSISIDXREG(SISCR, 0x55, tempCR55); 10215 andSISIDXREG(SISCR, 0x55, 0x33); 10216 /* Synchronous reset for Command Queue */ 10217 outSISIDXREG(SISSR, 0x26, 0x01); 10218 SIS_MMIO_OUT32(pSiS->IOBase, 0x85c4, 0); 10219 /* Enable VRAM Command Queue mode */ 10220 if(pSiS->ChipType == XGI_20) { 10221 /* On XGI_20, always 128K */ 10222 SR26 = 0x40 | 0x04 | 0x01; 10223 } else { 10224 switch(pSiS->cmdQueueSize) { 10225 case 1*1024*1024: SR26 = (0x40 | 0x04 | 0x01); break; 10226 case 2*1024*1024: SR26 = (0x40 | 0x08 | 0x01); break; 10227 case 4*1024*1024: SR26 = (0x40 | 0x0C | 0x01); break; 10228 default: 10229 pSiS->cmdQueueSize = 512 * 1024; 10230 case 512*1024: SR26 = (0x40 | 0x00 | 0x01); 10231 } 10232 } 10233 outSISIDXREG(SISSR, 0x26, SR26); 10234 SR26 &= 0xfe; 10235 outSISIDXREG(SISSR, 0x26, SR26); 10236 *(pSiS->cmdQ_SharedWritePort) = (unsigned int)(SIS_MMIO_IN32(pSiS->IOBase, 0x85c8)); 10237 SIS_MMIO_OUT32(pSiS->IOBase, 0x85c4, (CARD32)(*(pSiS->cmdQ_SharedWritePort))); 10238 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C0, pSiS->cmdQueueOffset); 10239 temp = (ULong)pSiS->RealFbBase; 10240#ifdef SISDUALHEAD 10241 if(pSiS->DualHeadMode) { 10242 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10243 temp = (ULong)pSiSEnt->RealFbBase; 10244 } 10245#endif 10246 temp += pSiS->cmdQueueOffset; 10247 pSiS->cmdQueueBase = (unsigned int *)temp; 10248 outSISIDXREG(SISCR, 0x55, tempCR55); 10249#ifdef TWDEBUG 10250 xf86DrvMsg(0, 0, "CmdQueueOffs 0x%x, CmdQueueAdd %p, shwrp 0x%x, status %x, base %p\n", 10251 pSiS->cmdQueueOffset, pSiS->cmdQueueBase, *(pSiS->cmdQ_SharedWritePort), 10252 SIS_MMIO_IN32(pSiS->IOBase, 0x85cc), (ULong *)temp); 10253#endif 10254#else 10255 /* For MMIO */ 10256 /* Syncronous reset for Command Queue */ 10257 orSISIDXREG(SISSR, 0x26, 0x01); 10258 /* Set Command Queue Threshold to max value 11111b */ 10259 outSISIDXREG(SISSR, 0x27, 0x1F); 10260 /* Do some magic (cp readport to writeport) */ 10261 temp = SIS_MMIO_IN32(pSiS->IOBase, 0x85C8); 10262 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C4, temp); 10263 /* Enable MMIO Command Queue mode (0x20), 10264 * Enable_command_queue_auto_correction (0x02) 10265 * (no idea, but sounds good, so use it) 10266 * 512k (0x00) (does this apply to MMIO mode?) */ 10267 outSISIDXREG(SISSR, 0x26, 0x22); 10268 /* Calc Command Queue position (Q is always 512k)*/ 10269 temp = (pScrn->videoRam - 512) * 1024; 10270 /* Set Q position */ 10271 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C0, temp); 10272#endif 10273 } 10274 break; 10275 default: 10276 break; 10277 } 10278} 10279 10280#ifdef SISVRAMQ 10281static void 10282SiSRestoreQueueMode(SISPtr pSiS, SISRegPtr sisReg) 10283{ 10284 UChar tempCR55=0; 10285 10286 if(pSiS->VGAEngine == SIS_315_VGA) { 10287 inSISIDXREG(SISCR,0x55,tempCR55); 10288 andSISIDXREG(SISCR,0x55,0x33); 10289 outSISIDXREG(SISSR,0x26,0x01); 10290 SIS_MMIO_OUT32(pSiS->IOBase, 0x85c4, 0); 10291 outSISIDXREG(SISSR,0x27,sisReg->sisRegs3C4[0x27]); 10292 outSISIDXREG(SISSR,0x26,sisReg->sisRegs3C4[0x26]); 10293 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C0, sisReg->sisMMIO85C0); 10294 outSISIDXREG(SISCR,0x55,tempCR55); 10295 } 10296} 10297#endif 10298 10299/* Things to do before a ModeSwitch. We set up the 10300 * video bridge configuration and the TurboQueue. 10301 */ 10302void SiSPreSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode, int viewmode) 10303{ 10304 SISPtr pSiS = SISPTR(pScrn); 10305 UChar CR30, CR31, CR32, CR33; 10306 UChar CR39 = 0, CR3B = 0; 10307 UChar CR17, CR38 = 0; 10308 UChar CR35 = 0, CR79 = 0; 10309 int temp = 0, crt1rateindex = 0; 10310 ULong vbflag = pSiS->VBFlags; 10311 Bool hcm = pSiS->HaveCustomModes; 10312 DisplayModePtr mymode = mode; 10313 10314 pSiS->IsCustom = FALSE; 10315 10316 /* NEVER call this with viewmode = SIS_MODE_SIMU 10317 * if mode->type is not M_T_DEFAULT! 10318 */ 10319 10320#ifdef SISMERGED 10321 if(pSiS->MergedFB) { 10322 switch(viewmode) { 10323 case SIS_MODE_CRT1: 10324 mymode = ((SiSMergedDisplayModePtr)mode->Private)->CRT1; 10325 break; 10326 case SIS_MODE_CRT2: 10327 mymode = ((SiSMergedDisplayModePtr)mode->Private)->CRT2; 10328 hcm = pSiS->HaveCustomModes2; 10329 } 10330 } 10331#endif 10332 10333 switch(viewmode) { 10334 case SIS_MODE_CRT1: 10335 if(SiS_CheckModeCRT1(pScrn, mymode, vbflag, hcm) == 0xfe) { 10336 pSiS->IsCustom = TRUE; 10337 } 10338 break; 10339 case SIS_MODE_CRT2: 10340 if(vbflag & CRT2_ENABLE) { 10341 if(SiS_CheckModeCRT2(pScrn, mymode, vbflag, hcm) == 0xfe) { 10342 pSiS->IsCustom = TRUE; 10343 } 10344 } else { 10345 /* This can only happen in mirror mode */ 10346 if(SiS_CheckModeCRT1(pScrn, mymode, vbflag, hcm) == 0xfe) { 10347 pSiS->IsCustom = TRUE; 10348 } 10349 } 10350 } 10351 10352#ifdef UNLOCK_ALWAYS 10353 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); /* Unlock Registers */ 10354#endif 10355 10356 inSISIDXREG(SISCR, 0x30, CR30); 10357 inSISIDXREG(SISCR, 0x31, CR31); 10358 CR32 = pSiS->newCR32; 10359 inSISIDXREG(SISCR, 0x33, CR33); 10360 10361 if(pSiS->NewCRLayout) { 10362 10363 inSISIDXREG(SISCR, 0x35, CR35); 10364 inSISIDXREG(SISCR, 0x38, CR38); 10365 inSISIDXREG(SISCR, 0x39, CR39); 10366 10367 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, SISVERBLEVEL, 10368 "Before: CR30=0x%02x,CR31=0x%02x,CR32=0x%02x,CR33=0x%02x,CR35=0x%02x,CR38=0x%02x\n", 10369 CR30, CR31, CR32, CR33, CR35, CR38); 10370 10371 CR38 &= ~0x07; 10372 10373 } else { 10374 10375 if(pSiS->Chipset != PCI_CHIP_SIS300) { 10376 switch(pSiS->VGAEngine) { 10377 case SIS_300_VGA: temp = 0x35; break; 10378 case SIS_315_VGA: temp = 0x38; break; 10379 } 10380 if(temp) inSISIDXREG(SISCR, temp, CR38); 10381 } 10382 if(pSiS->VGAEngine == SIS_315_VGA) { 10383 inSISIDXREG(SISCR, 0x79, CR79); 10384 CR38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */ 10385 } 10386 inSISIDXREG(SISCR, 0x3b, CR3B); 10387 10388 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, SISVERBLEVEL, 10389 "Before: CR30=0x%02x, CR31=0x%02x, CR32=0x%02x, CR33=0x%02x, CR%02x=0x%02x\n", 10390 CR30, CR31, CR32, CR33, temp, CR38); 10391 } 10392 10393 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, SISVERBLEVEL, "VBFlags=0x%x\n", pSiS->VBFlags); 10394 10395 CR30 = 0x00; 10396 CR31 &= ~0x60; /* Clear VB_Drivermode & VB_OutputDisable */ 10397 CR31 |= 0x04; /* Set VB_NotSimuMode (not for 30xB/1400x1050?) */ 10398 CR35 = 0x00; 10399 10400 if(!pSiS->NewCRLayout) { 10401 if(!pSiS->AllowHotkey) { 10402 CR31 |= 0x80; /* Disable hotkey-switch */ 10403 } 10404 CR79 &= ~0x10; /* Enable Backlight control on 315 series */ 10405 } 10406 10407 SiS_SetEnableDstn(pSiS->SiS_Pr, FALSE); 10408 SiS_SetEnableFstn(pSiS->SiS_Pr, FALSE); 10409 10410 if((vbflag & CRT1_LCDA) && (viewmode == SIS_MODE_CRT1)) { 10411 10412 CR38 |= 0x02; 10413 10414 } else { 10415 10416 switch(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA)) { 10417 10418 case CRT2_TV: 10419 10420 CR38 &= ~0xC0; /* Clear Pal M/N bits */ 10421 10422 if((pSiS->VBFlags2 & VB2_CHRONTEL) && (vbflag & TV_CHSCART)) { /* Chrontel */ 10423 CR30 |= 0x10; 10424 CR38 |= 0x04; 10425 CR38 &= ~0x08; 10426 CR31 |= 0x01; 10427 } else if((pSiS->VBFlags2 & VB2_CHRONTEL) && (vbflag & TV_CHYPBPR525I)) { /* Chrontel */ 10428 CR38 |= 0x08; 10429 CR38 &= ~0x04; 10430 CR31 &= ~0x01; 10431 } else if(vbflag & TV_HIVISION) { /* SiS bridge */ 10432 if(pSiS->NewCRLayout) { 10433 CR38 |= 0x04; 10434 CR35 |= 0x60; 10435 } else { 10436 CR30 |= 0x80; 10437 if(pSiS->VGAEngine == SIS_315_VGA) { 10438 if(pSiS->VBFlags2 & VB2_SISYPBPRBRIDGE) { 10439 CR38 |= (0x08 | 0x30); 10440 } 10441 } 10442 } 10443 CR31 |= 0x01; 10444 CR35 |= 0x01; 10445 } else if(vbflag & TV_YPBPR) { /* SiS bridge */ 10446 if(pSiS->NewCRLayout) { 10447 CR38 |= 0x04; 10448 CR31 &= ~0x01; 10449 CR35 &= ~0x01; 10450 if(vbflag & (TV_YPBPR525P | TV_YPBPR625P)) CR35 |= 0x20; 10451 else if(vbflag & TV_YPBPR750P) CR35 |= 0x40; 10452 else if(vbflag & TV_YPBPR1080I) CR35 |= 0x60; 10453 10454 if(vbflag & (TV_YPBPR625I | TV_YPBPR625P)) { 10455 CR31 |= 0x01; 10456 CR35 |= 0x01; 10457 } 10458 10459 CR39 &= ~0x03; 10460 if((vbflag & TV_YPBPRAR) == TV_YPBPR43LB) CR39 |= 0x00; 10461 else if((vbflag & TV_YPBPRAR) == TV_YPBPR43) CR39 |= 0x01; 10462 else if((vbflag & TV_YPBPRAR) == TV_YPBPR169) CR39 |= 0x02; 10463 else CR39 |= 0x03; 10464 } else if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR) { 10465 CR30 |= 0x80; 10466 CR38 |= 0x08; 10467 CR31 &= ~0x01; 10468 if(vbflag & (TV_YPBPR525P|TV_YPBPR625P)) CR38 |= 0x10; 10469 else if(vbflag & TV_YPBPR750P) CR38 |= 0x20; 10470 else if(vbflag & TV_YPBPR1080I) CR38 |= 0x30; 10471 10472 if(vbflag & (TV_YPBPR625I | TV_YPBPR625P)) CR31 |= 0x01; 10473 10474 if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPRAR) { 10475 CR3B &= ~0x03; 10476 if((vbflag & TV_YPBPRAR) == TV_YPBPR43LB) CR3B |= 0x00; 10477 else if((vbflag & TV_YPBPRAR) == TV_YPBPR43) CR3B |= 0x03; 10478 else if((vbflag & TV_YPBPRAR) == TV_YPBPR169) CR3B |= 0x01; 10479 else CR3B |= 0x03; 10480 } 10481 } 10482 } else { /* All */ 10483 if(vbflag & TV_SCART) CR30 |= 0x10; 10484 if(vbflag & TV_SVIDEO) CR30 |= 0x08; 10485 if(vbflag & TV_AVIDEO) CR30 |= 0x04; 10486 if(!(CR30 & 0x1C)) CR30 |= 0x08; /* default: SVIDEO */ 10487 10488 if(vbflag & TV_PAL) { 10489 CR31 |= 0x01; 10490 CR35 |= 0x01; 10491 if( (pSiS->VBFlags2 & VB2_SISBRIDGE) || 10492 ((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->ChrontelType == CHRONTEL_701x)) ) { 10493 if(vbflag & TV_PALM) { 10494 CR38 |= 0x40; 10495 CR35 |= 0x04; 10496 } else if(vbflag & TV_PALN) { 10497 CR38 |= 0x80; 10498 CR35 |= 0x08; 10499 } 10500 } 10501 } else { 10502 CR31 &= ~0x01; 10503 CR35 &= ~0x01; 10504 if(vbflag & TV_NTSCJ) { 10505 CR38 |= 0x40; /* TW, not BIOS */ 10506 CR35 |= 0x02; 10507 } 10508 } 10509 if(vbflag & TV_SCART) { 10510 CR31 |= 0x01; 10511 CR35 |= 0x01; 10512 } 10513 } 10514 10515 CR31 &= ~0x04; /* Clear NotSimuMode */ 10516 pSiS->SiS_Pr->SiS_CHOverScan = pSiS->UseCHOverScan; 10517 if((pSiS->OptTVSOver == 1) && (pSiS->ChrontelType == CHRONTEL_700x)) { 10518 pSiS->SiS_Pr->SiS_CHSOverScan = TRUE; 10519 } else { 10520 pSiS->SiS_Pr->SiS_CHSOverScan = FALSE; 10521 } 10522#ifdef SIS_CP 10523 SIS_CP_DRIVER_CONFIG 10524#endif 10525 break; 10526 10527 case CRT2_LCD: 10528 CR30 |= 0x20; 10529 SiS_SetEnableDstn(pSiS->SiS_Pr, pSiS->DSTN); 10530 SiS_SetEnableFstn(pSiS->SiS_Pr, pSiS->FSTN); 10531 break; 10532 10533 case CRT2_VGA: 10534 CR30 |= 0x40; 10535 break; 10536 10537 default: 10538 CR30 |= 0x00; 10539 CR31 |= 0x20; /* VB_OUTPUT_DISABLE */ 10540 if(pSiS->UseVESA) { 10541 crt1rateindex = SISSearchCRT1Rate(pScrn, mymode); 10542 } 10543 } 10544 10545 } 10546 10547 if(vbflag & CRT1_LCDA) { 10548 switch(viewmode) { 10549 case SIS_MODE_CRT1: 10550 CR38 |= 0x01; 10551 break; 10552 case SIS_MODE_CRT2: 10553 if(vbflag & (CRT2_TV|CRT2_VGA)) { 10554 CR30 |= 0x02; 10555 CR38 |= 0x01; 10556 } else { 10557 CR38 |= 0x03; 10558 } 10559 break; 10560 case SIS_MODE_SIMU: 10561 default: 10562 if(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA)) { 10563 CR30 |= 0x01; 10564 } 10565 break; 10566 } 10567 } else { 10568 if(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA)) { 10569 CR30 |= 0x01; 10570 } 10571 } 10572 10573 if(pSiS->UseVESA) { 10574 CR31 &= ~0x40; /* Clear Drivermode */ 10575 CR31 |= 0x06; /* Set SlaveMode, Enable SimuMode in Slavemode */ 10576#ifdef TWDEBUG 10577 CR31 |= 0x40; /* DEBUG (for non-slave mode VESA) */ 10578 crt1rateindex = SISSearchCRT1Rate(pScrn, mymode); 10579#endif 10580 } else { 10581 CR31 |= 0x40; /* Set Drivermode */ 10582 CR31 &= ~0x06; /* Disable SlaveMode, disable SimuMode in SlaveMode */ 10583 if(!pSiS->IsCustom) { 10584 crt1rateindex = SISSearchCRT1Rate(pScrn, mymode); 10585 } 10586 } 10587 10588 switch(viewmode) { 10589 case SIS_MODE_SIMU: 10590 CR33 = 0; 10591 if(!(vbflag & CRT1_LCDA)) { 10592 CR33 |= (crt1rateindex & 0x0f); 10593 } 10594 if(vbflag & CRT2_VGA) { 10595 CR33 |= ((crt1rateindex & 0x0f) << 4); 10596 } 10597 break; 10598 case SIS_MODE_CRT1: 10599 CR33 &= 0xf0; 10600 if(!(vbflag & CRT1_LCDA)) { 10601 CR33 |= (crt1rateindex & 0x0f); 10602 } 10603 break; 10604 case SIS_MODE_CRT2: 10605 CR33 &= 0x0f; 10606 if(vbflag & CRT2_VGA) { 10607 CR33 |= ((crt1rateindex & 0x0f) << 4); 10608 } 10609 break; 10610 } 10611 10612 if((!pSiS->UseVESA) && (vbflag & CRT2_ENABLE)) { 10613 if(pSiS->CRT1off) CR33 &= 0xf0; 10614 } 10615 10616 if(pSiS->NewCRLayout) { 10617 10618 CR31 &= 0xfe; /* Clear PAL flag (now in CR35) */ 10619 CR38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */ 10620 outSISIDXREG(SISCR, 0x30, CR30); 10621 outSISIDXREG(SISCR, 0x31, CR31); 10622 outSISIDXREG(SISCR, 0x33, CR33); 10623 outSISIDXREG(SISCR, 0x35, CR35); 10624 setSISIDXREG(SISCR, 0x38, 0xf8, CR38); 10625 outSISIDXREG(SISCR, 0x39, CR39); 10626 10627 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, SISVERBLEVEL, 10628 "After: CR30=0x%02x,CR31=0x%02x,CR33=0x%02x,CR35=0x%02x,CR38=%02x\n", 10629 CR30, CR31, CR33, CR35, CR38); 10630 10631 } else { 10632 10633 outSISIDXREG(SISCR, 0x30, CR30); 10634 outSISIDXREG(SISCR, 0x31, CR31); 10635 outSISIDXREG(SISCR, 0x33, CR33); 10636 if(temp) { 10637 outSISIDXREG(SISCR, temp, CR38); 10638 } 10639 if(pSiS->VGAEngine == SIS_315_VGA) { 10640 outSISIDXREG(SISCR, 0x3b, CR3B); 10641 outSISIDXREG(SISCR, 0x79, CR79); 10642 } 10643 10644 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, SISVERBLEVEL, 10645 "After: CR30=0x%02x,CR31=0x%02x,CR33=0x%02x,CR%02x=%02x\n", 10646 CR30, CR31, CR33, temp, CR38); 10647 } 10648 10649 pSiS->SiS_Pr->SiS_UseOEM = pSiS->OptUseOEM; 10650 10651 /* Enable TurboQueue */ 10652#ifdef SISVRAMQ 10653 if(pSiS->VGAEngine != SIS_315_VGA) 10654#endif 10655 SiSEnableTurboQueue(pScrn); 10656 10657 if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE)) { 10658 /* Switch on CRT1 for modes that require the bridge in SlaveMode */ 10659 andSISIDXREG(SISSR,0x1f,0x3f); 10660 inSISIDXREG(SISCR, 0x17, CR17); 10661 if(!(CR17 & 0x80)) { 10662 orSISIDXREG(SISCR, 0x17, 0x80); 10663 outSISIDXREG(SISSR, 0x00, 0x01); 10664 usleep(10000); 10665 outSISIDXREG(SISSR, 0x00, 0x03); 10666 } 10667 } 10668} 10669 10670/* Functions for adjusting various TV settings */ 10671 10672/* These are used by the PostSetMode() functions as well as 10673 * the display properties tool SiSCtrl. 10674 * 10675 * There is each a Set and a Get routine. The Set functions 10676 * take a value of the same range as the corresponding option. 10677 * The Get routines return a value of the same range (although 10678 * not necessarily the same value as previously set because 10679 * of the lower resolution of the respective setting compared 10680 * to the valid range). 10681 * The Get routines return -2 on error (eg. hardware does not 10682 * support this setting). 10683 * Note: The x and y positioning routines accept a position 10684 * RELATIVE to the default position. All other routines 10685 * take ABSOLUTE values. 10686 * 10687 * The Set functions will store the property regardless if TV is 10688 * currently used or not and if the hardware supports the property 10689 * or not. The Get routines will return this stored 10690 * value if TV is not currently used (because the register does 10691 * not contain the correct value then) or if the hardware supports 10692 * the respective property. This should make it easier for the 10693 * display property tool because it does not have to know the 10694 * hardware features. 10695 * 10696 * All the routines are dual head aware. It does not matter 10697 * if the function is called from the CRT1 or CRT2 session. 10698 * The values will be in pSiSEnt anyway, and read from there 10699 * if we're running dual head. 10700 */ 10701 10702void SiS_SetCHTVlumabandwidthcvbs(ScrnInfoPtr pScrn, int val) 10703{ 10704 SISPtr pSiS = SISPTR(pScrn); 10705#ifdef SISDUALHEAD 10706 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10707#endif 10708 10709 pSiS->chtvlumabandwidthcvbs = val; 10710#ifdef SISDUALHEAD 10711 if(pSiSEnt) pSiSEnt->chtvlumabandwidthcvbs = val; 10712#endif 10713 10714 if(!(pSiS->VBFlags & CRT2_TV)) return; 10715 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10716 10717#ifdef UNLOCK_ALWAYS 10718 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10719#endif 10720 10721 switch(pSiS->ChrontelType) { 10722 case CHRONTEL_700x: 10723 val /= 8; 10724 if((val == 0) || (val == 1)) { 10725 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, val, 0xFE); 10726 } 10727 break; 10728 case CHRONTEL_701x: 10729 val /= 4; 10730 if((val >= 0) && (val <= 3)) { 10731 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, val, 0xFC); 10732 } 10733 break; 10734 } 10735} 10736 10737int SiS_GetCHTVlumabandwidthcvbs(ScrnInfoPtr pScrn) 10738{ 10739 SISPtr pSiS = SISPTR(pScrn); 10740#ifdef SISDUALHEAD 10741 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10742#endif 10743 10744 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10745#ifdef SISDUALHEAD 10746 if(pSiSEnt && pSiS->DualHeadMode) 10747 return (int)pSiSEnt->chtvlumabandwidthcvbs; 10748 else 10749#endif 10750 return (int)pSiS->chtvlumabandwidthcvbs; 10751 } else { 10752#ifdef UNLOCK_ALWAYS 10753 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10754#endif 10755 switch(pSiS->ChrontelType) { 10756 case CHRONTEL_700x: 10757 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x01) * 8); 10758 case CHRONTEL_701x: 10759 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x03) * 4); 10760 default: 10761 return (int)pSiS->chtvlumabandwidthcvbs; 10762 } 10763 } 10764} 10765 10766void SiS_SetCHTVlumabandwidthsvideo(ScrnInfoPtr pScrn, int val) 10767{ 10768 SISPtr pSiS = SISPTR(pScrn); 10769#ifdef SISDUALHEAD 10770 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10771#endif 10772 10773 pSiS->chtvlumabandwidthsvideo = val; 10774#ifdef SISDUALHEAD 10775 if(pSiSEnt) pSiSEnt->chtvlumabandwidthsvideo = val; 10776#endif 10777 10778 if(!(pSiS->VBFlags & CRT2_TV)) return; 10779 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10780 10781#ifdef UNLOCK_ALWAYS 10782 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10783#endif 10784 10785 switch(pSiS->ChrontelType) { 10786 case CHRONTEL_700x: 10787 val /= 6; 10788 if((val >= 0) && (val <= 2)) { 10789 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, (val << 1), 0xF9); 10790 } 10791 break; 10792 case CHRONTEL_701x: 10793 val /= 4; 10794 if((val >= 0) && (val <= 3)) { 10795 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, (val << 2), 0xF3); 10796 } 10797 break; 10798 } 10799} 10800 10801int SiS_GetCHTVlumabandwidthsvideo(ScrnInfoPtr pScrn) 10802{ 10803 SISPtr pSiS = SISPTR(pScrn); 10804#ifdef SISDUALHEAD 10805 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10806#endif 10807 10808 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10809#ifdef SISDUALHEAD 10810 if(pSiSEnt && pSiS->DualHeadMode) 10811 return (int)pSiSEnt->chtvlumabandwidthsvideo; 10812 else 10813#endif 10814 return (int)pSiS->chtvlumabandwidthsvideo; 10815 } else { 10816#ifdef UNLOCK_ALWAYS 10817 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10818#endif 10819 switch(pSiS->ChrontelType) { 10820 case CHRONTEL_700x: 10821 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x06) >> 1) * 6); 10822 case CHRONTEL_701x: 10823 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x0c) >> 2) * 4); 10824 default: 10825 return (int)pSiS->chtvlumabandwidthsvideo; 10826 } 10827 } 10828} 10829 10830void SiS_SetCHTVlumaflickerfilter(ScrnInfoPtr pScrn, int val) 10831{ 10832 SISPtr pSiS = SISPTR(pScrn); 10833#ifdef SISDUALHEAD 10834 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10835#endif 10836 10837 pSiS->chtvlumaflickerfilter = val; 10838#ifdef SISDUALHEAD 10839 if(pSiSEnt) pSiSEnt->chtvlumaflickerfilter = val; 10840#endif 10841 10842 if(!(pSiS->VBFlags & CRT2_TV)) return; 10843 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10844 10845#ifdef UNLOCK_ALWAYS 10846 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10847#endif 10848 10849 switch(pSiS->ChrontelType) { 10850 case CHRONTEL_700x: 10851 val /= 6; 10852 if((val >= 0) && (val <= 2)) { 10853 UShort reg = 0; 10854 reg = SiS_GetCH70xx(pSiS->SiS_Pr, 0x01); 10855 reg = (reg & 0xf0) | ((reg & 0x0c) >> 2) | (val << 2); 10856 SiS_SetCH70xx(pSiS->SiS_Pr, 0x01, reg); 10857 } 10858 break; 10859 case CHRONTEL_701x: 10860 val /= 4; 10861 if((val >= 0) && (val <= 3)) { 10862 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x01, (val << 2), 0xF3); 10863 } 10864 break; 10865 } 10866} 10867 10868int SiS_GetCHTVlumaflickerfilter(ScrnInfoPtr pScrn) 10869{ 10870 SISPtr pSiS = SISPTR(pScrn); 10871#ifdef SISDUALHEAD 10872 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10873#endif 10874 10875 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10876#ifdef SISDUALHEAD 10877 if(pSiSEnt && pSiS->DualHeadMode) 10878 return (int)pSiSEnt->chtvlumaflickerfilter; 10879 else 10880#endif 10881 return (int)pSiS->chtvlumaflickerfilter; 10882 } else { 10883#ifdef UNLOCK_ALWAYS 10884 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10885#endif 10886 switch(pSiS->ChrontelType) { 10887 case CHRONTEL_700x: 10888 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x03) * 6); 10889 case CHRONTEL_701x: 10890 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x0c) >> 2) * 4); 10891 default: 10892 return (int)pSiS->chtvlumaflickerfilter; 10893 } 10894 } 10895} 10896 10897void SiS_SetCHTVchromabandwidth(ScrnInfoPtr pScrn, int val) 10898{ 10899 SISPtr pSiS = SISPTR(pScrn); 10900#ifdef SISDUALHEAD 10901 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10902#endif 10903 10904 pSiS->chtvchromabandwidth = val; 10905#ifdef SISDUALHEAD 10906 if(pSiSEnt) pSiSEnt->chtvchromabandwidth = val; 10907#endif 10908 10909 if(!(pSiS->VBFlags & CRT2_TV)) return; 10910 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10911 10912#ifdef UNLOCK_ALWAYS 10913 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10914#endif 10915 10916 switch(pSiS->ChrontelType) { 10917 case CHRONTEL_700x: 10918 val /= 4; 10919 if((val >= 0) && (val <= 3)) { 10920 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, (val << 4), 0xCF); 10921 } 10922 break; 10923 case CHRONTEL_701x: 10924 val /= 8; 10925 if((val >= 0) && (val <= 1)) { 10926 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, (val << 4), 0xEF); 10927 } 10928 break; 10929 } 10930} 10931 10932int SiS_GetCHTVchromabandwidth(ScrnInfoPtr pScrn) 10933{ 10934 SISPtr pSiS = SISPTR(pScrn); 10935#ifdef SISDUALHEAD 10936 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10937#endif 10938 10939 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10940#ifdef SISDUALHEAD 10941 if(pSiSEnt && pSiS->DualHeadMode) 10942 return (int)pSiSEnt->chtvchromabandwidth; 10943 else 10944#endif 10945 return (int)pSiS->chtvchromabandwidth; 10946 } else { 10947#ifdef UNLOCK_ALWAYS 10948 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10949#endif 10950 switch(pSiS->ChrontelType) { 10951 case CHRONTEL_700x: 10952 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x30) >> 4) * 4); 10953 case CHRONTEL_701x: 10954 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x10) >> 4) * 8); 10955 default: 10956 return (int)pSiS->chtvchromabandwidth; 10957 } 10958 } 10959} 10960 10961void SiS_SetCHTVchromaflickerfilter(ScrnInfoPtr pScrn, int val) 10962{ 10963 SISPtr pSiS = SISPTR(pScrn); 10964#ifdef SISDUALHEAD 10965 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10966#endif 10967 10968 pSiS->chtvchromaflickerfilter = val; 10969#ifdef SISDUALHEAD 10970 if(pSiSEnt) pSiSEnt->chtvchromaflickerfilter = val; 10971#endif 10972 10973 if(!(pSiS->VBFlags & CRT2_TV)) return; 10974 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10975 10976#ifdef UNLOCK_ALWAYS 10977 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10978#endif 10979 10980 switch(pSiS->ChrontelType) { 10981 case CHRONTEL_700x: 10982 val /= 6; 10983 if((val >= 0) && (val <= 2)) { 10984 UShort reg = 0; 10985 reg = SiS_GetCH70xx(pSiS->SiS_Pr, 0x01); 10986 reg = (reg & 0xc0) | ((reg & 0x0c) >> 2) | ((reg & 0x03) << 2) | (val << 4); 10987 SiS_SetCH70xx(pSiS->SiS_Pr, 0x01, reg); 10988 } 10989 break; 10990 case CHRONTEL_701x: 10991 val /= 4; 10992 if((val >= 0) && (val <= 3)) { 10993 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x01, (val << 4), 0xCF); 10994 } 10995 break; 10996 } 10997} 10998 10999int SiS_GetCHTVchromaflickerfilter(ScrnInfoPtr pScrn) 11000{ 11001 SISPtr pSiS = SISPTR(pScrn); 11002#ifdef SISDUALHEAD 11003 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11004#endif 11005 11006 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 11007#ifdef SISDUALHEAD 11008 if(pSiSEnt && pSiS->DualHeadMode) 11009 return (int)pSiSEnt->chtvchromaflickerfilter; 11010 else 11011#endif 11012 return (int)pSiS->chtvchromaflickerfilter; 11013 } else { 11014#ifdef UNLOCK_ALWAYS 11015 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11016#endif 11017 switch(pSiS->ChrontelType) { 11018 case CHRONTEL_700x: 11019 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x30) >> 4) * 6); 11020 case CHRONTEL_701x: 11021 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x30) >> 4) * 4); 11022 default: 11023 return (int)pSiS->chtvchromaflickerfilter; 11024 } 11025 } 11026} 11027 11028void SiS_SetCHTVcvbscolor(ScrnInfoPtr pScrn, int val) 11029{ 11030 SISPtr pSiS = SISPTR(pScrn); 11031#ifdef SISDUALHEAD 11032 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11033#endif 11034 11035 pSiS->chtvcvbscolor = val ? 1 : 0; 11036#ifdef SISDUALHEAD 11037 if(pSiSEnt) pSiSEnt->chtvcvbscolor = pSiS->chtvcvbscolor; 11038#endif 11039 11040 if(!(pSiS->VBFlags & CRT2_TV)) return; 11041 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 11042 11043#ifdef UNLOCK_ALWAYS 11044 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11045#endif 11046 11047 switch(pSiS->ChrontelType) { 11048 case CHRONTEL_700x: 11049 if(!val) SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, 0x40, 0x00); 11050 else SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, 0x00, ~0x40); 11051 break; 11052 case CHRONTEL_701x: 11053 if(!val) SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, 0x00, ~0x20); 11054 else SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, 0x20, 0x00); 11055 break; 11056 } 11057} 11058 11059int SiS_GetCHTVcvbscolor(ScrnInfoPtr pScrn) 11060{ 11061 SISPtr pSiS = SISPTR(pScrn); 11062#ifdef SISDUALHEAD 11063 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11064#endif 11065 11066 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 11067#ifdef SISDUALHEAD 11068 if(pSiSEnt && pSiS->DualHeadMode) 11069 return (int)pSiSEnt->chtvcvbscolor; 11070 else 11071#endif 11072 return (int)pSiS->chtvcvbscolor; 11073 } else { 11074#ifdef UNLOCK_ALWAYS 11075 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11076#endif 11077 switch(pSiS->ChrontelType) { 11078 case CHRONTEL_700x: 11079 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x40) >> 6) ^ 0x01); 11080 case CHRONTEL_701x: 11081 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x20) >> 5) ^ 0x01); 11082 default: 11083 return (int)pSiS->chtvcvbscolor; 11084 } 11085 } 11086} 11087 11088void SiS_SetCHTVtextenhance(ScrnInfoPtr pScrn, int val) 11089{ 11090 SISPtr pSiS = SISPTR(pScrn); 11091#ifdef SISDUALHEAD 11092 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11093#endif 11094 11095 pSiS->chtvtextenhance = val; 11096#ifdef SISDUALHEAD 11097 if(pSiSEnt) pSiSEnt->chtvtextenhance = val; 11098#endif 11099 11100 if(!(pSiS->VBFlags & CRT2_TV)) return; 11101 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 11102 11103#ifdef UNLOCK_ALWAYS 11104 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11105#endif 11106 11107 switch(pSiS->ChrontelType) { 11108 case CHRONTEL_700x: 11109 val /= 6; 11110 if((val >= 0) && (val <= 2)) { 11111 UShort reg = 0; 11112 reg = SiS_GetCH70xx(pSiS->SiS_Pr, 0x01); 11113 reg = (reg & 0xf0) | ((reg & 0x03) << 2) | val; 11114 SiS_SetCH70xx(pSiS->SiS_Pr, 0x01, reg); 11115 } 11116 break; 11117 case CHRONTEL_701x: 11118 val /= 2; 11119 if((val >= 0) && (val <= 7)) { 11120 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, val, 0xF8); 11121 } 11122 break; 11123 } 11124} 11125 11126int SiS_GetCHTVtextenhance(ScrnInfoPtr pScrn) 11127{ 11128 SISPtr pSiS = SISPTR(pScrn); 11129#ifdef SISDUALHEAD 11130 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11131#endif 11132 11133 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 11134#ifdef SISDUALHEAD 11135 if(pSiSEnt && pSiS->DualHeadMode) 11136 return (int)pSiSEnt->chtvtextenhance; 11137 else 11138#endif 11139 return (int)pSiS->chtvtextenhance; 11140 } else { 11141#ifdef UNLOCK_ALWAYS 11142 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11143#endif 11144 switch(pSiS->ChrontelType) { 11145 case CHRONTEL_700x: 11146 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x0c) >> 2) * 6); 11147 case CHRONTEL_701x: 11148 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x07) * 2); 11149 default: 11150 return (int)pSiS->chtvtextenhance; 11151 } 11152 } 11153} 11154 11155void SiS_SetCHTVcontrast(ScrnInfoPtr pScrn, int val) 11156{ 11157 SISPtr pSiS = SISPTR(pScrn); 11158#ifdef SISDUALHEAD 11159 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11160#endif 11161 11162 pSiS->chtvcontrast = val; 11163#ifdef SISDUALHEAD 11164 if(pSiSEnt) pSiSEnt->chtvcontrast = val; 11165#endif 11166 11167 if(!(pSiS->VBFlags & CRT2_TV)) return; 11168 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 11169 11170#ifdef UNLOCK_ALWAYS 11171 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11172#endif 11173 11174 val /= 2; 11175 if((val >= 0) && (val <= 7)) { 11176 switch(pSiS->ChrontelType) { 11177 case CHRONTEL_700x: 11178 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x11, val, 0xF8); 11179 break; 11180 case CHRONTEL_701x: 11181 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x08, val, 0xF8); 11182 break; 11183 } 11184 SiS_DDC2Delay(pSiS->SiS_Pr, 1000); 11185 } 11186} 11187 11188int SiS_GetCHTVcontrast(ScrnInfoPtr pScrn) 11189{ 11190 SISPtr pSiS = SISPTR(pScrn); 11191#ifdef SISDUALHEAD 11192 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11193#endif 11194 11195 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 11196#ifdef SISDUALHEAD 11197 if(pSiSEnt && pSiS->DualHeadMode) 11198 return (int)pSiSEnt->chtvcontrast; 11199 else 11200#endif 11201 return (int)pSiS->chtvcontrast; 11202 } else { 11203#ifdef UNLOCK_ALWAYS 11204 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11205#endif 11206 switch(pSiS->ChrontelType) { 11207 case CHRONTEL_700x: 11208 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x11) & 0x07) * 2); 11209 case CHRONTEL_701x: 11210 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x08) & 0x07) * 2); 11211 default: 11212 return (int)pSiS->chtvcontrast; 11213 } 11214 } 11215} 11216 11217void SiS_SetSISTVedgeenhance(ScrnInfoPtr pScrn, int val) 11218{ 11219 SISPtr pSiS = SISPTR(pScrn); 11220#ifdef SISDUALHEAD 11221 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11222#endif 11223 11224 pSiS->sistvedgeenhance = val; 11225#ifdef SISDUALHEAD 11226 if(pSiSEnt) pSiSEnt->sistvedgeenhance = val; 11227#endif 11228 11229 if(!(pSiS->VBFlags2 & VB2_301)) return; 11230 if(!(pSiS->VBFlags & CRT2_TV)) return; 11231 11232#ifdef UNLOCK_ALWAYS 11233 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11234#endif 11235 11236 val /= 2; 11237 if((val >= 0) && (val <= 7)) { 11238 setSISIDXREG(SISPART2,0x3A, 0x1F, (val << 5)); 11239 } 11240} 11241 11242int SiS_GetSISTVedgeenhance(ScrnInfoPtr pScrn) 11243{ 11244 SISPtr pSiS = SISPTR(pScrn); 11245 int result = pSiS->sistvedgeenhance; 11246 UChar temp; 11247#ifdef SISDUALHEAD 11248 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11249 11250 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvedgeenhance; 11251#endif 11252 11253 if(!(pSiS->VBFlags2 & VB2_301)) return result; 11254 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11255 11256#ifdef UNLOCK_ALWAYS 11257 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11258#endif 11259 inSISIDXREG(SISPART2, 0x3a, temp); 11260 return(int)(((temp & 0xe0) >> 5) * 2); 11261} 11262 11263void SiS_SetSISTVantiflicker(ScrnInfoPtr pScrn, int val) 11264{ 11265 SISPtr pSiS = SISPTR(pScrn); 11266#ifdef SISDUALHEAD 11267 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11268#endif 11269 11270 pSiS->sistvantiflicker = val; 11271#ifdef SISDUALHEAD 11272 if(pSiSEnt) pSiSEnt->sistvantiflicker = val; 11273#endif 11274 11275 if(!(pSiS->VBFlags & CRT2_TV)) return; 11276 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11277 if(pSiS->VBFlags & TV_HIVISION) return; 11278 if((pSiS->VBFlags & TV_YPBPR) && 11279 (pSiS->VBFlags & (TV_YPBPR525P | TV_YPBPR625P | TV_YPBPR750P | TV_YPBPR1080I))) return; 11280 11281#ifdef UNLOCK_ALWAYS 11282 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11283#endif 11284 11285 /* Valid values: 0=off, 1=low, 2=med, 3=high, 4=adaptive */ 11286 if((val >= 0) && (val <= 4)) { 11287 setSISIDXREG(SISPART2,0x0A,0x8F, (val << 4)); 11288 } 11289} 11290 11291int SiS_GetSISTVantiflicker(ScrnInfoPtr pScrn) 11292{ 11293 SISPtr pSiS = SISPTR(pScrn); 11294 int result = pSiS->sistvantiflicker; 11295 UChar temp; 11296#ifdef SISDUALHEAD 11297 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11298 11299 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvantiflicker; 11300#endif 11301 11302 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return result; 11303 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11304 if(pSiS->VBFlags & TV_HIVISION) return result; 11305 if((pSiS->VBFlags & TV_YPBPR) && 11306 (pSiS->VBFlags & (TV_YPBPR525P | TV_YPBPR625P | TV_YPBPR750P | TV_YPBPR1080I))) return result; 11307 11308#ifdef UNLOCK_ALWAYS 11309 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11310#endif 11311 inSISIDXREG(SISPART2, 0x0a, temp); 11312 return(int)((temp & 0x70) >> 4); 11313} 11314 11315void SiS_SetSISTVsaturation(ScrnInfoPtr pScrn, int val) 11316{ 11317 SISPtr pSiS = SISPTR(pScrn); 11318#ifdef SISDUALHEAD 11319 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11320#endif 11321 11322 pSiS->sistvsaturation = val; 11323#ifdef SISDUALHEAD 11324 if(pSiSEnt) pSiSEnt->sistvsaturation = val; 11325#endif 11326 11327 if(!(pSiS->VBFlags & CRT2_TV)) return; 11328 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11329 if(pSiS->VBFlags2 & VB2_301) return; 11330 11331#ifdef UNLOCK_ALWAYS 11332 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11333#endif 11334 11335 val /= 2; 11336 if((val >= 0) && (val <= 7)) { 11337 setSISIDXREG(SISPART4,0x21,0xF8, val); 11338 } 11339} 11340 11341int SiS_GetSISTVsaturation(ScrnInfoPtr pScrn) 11342{ 11343 SISPtr pSiS = SISPTR(pScrn); 11344 int result = pSiS->sistvsaturation; 11345 UChar temp; 11346#ifdef SISDUALHEAD 11347 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11348 11349 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvsaturation; 11350#endif 11351 11352 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return result; 11353 if(pSiS->VBFlags2 & VB2_301) return result; 11354 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11355 11356#ifdef UNLOCK_ALWAYS 11357 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11358#endif 11359 inSISIDXREG(SISPART4, 0x21, temp); 11360 return(int)((temp & 0x07) * 2); 11361} 11362 11363void SiS_SetSISTVcolcalib(ScrnInfoPtr pScrn, int val, Bool coarse) 11364{ 11365 SISPtr pSiS = SISPTR(pScrn); 11366#ifdef SISDUALHEAD 11367 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11368#endif 11369 int ccoarse, cfine, cbase = pSiS->sistvccbase; 11370 /* UChar temp; */ 11371 11372#ifdef SISDUALHEAD 11373 if(pSiSEnt && pSiS->DualHeadMode) cbase = pSiSEnt->sistvccbase; 11374#endif 11375 11376 if(coarse) { 11377 pSiS->sistvcolcalibc = ccoarse = val; 11378 cfine = pSiS->sistvcolcalibf; 11379#ifdef SISDUALHEAD 11380 if(pSiSEnt) { 11381 pSiSEnt->sistvcolcalibc = val; 11382 if(pSiS->DualHeadMode) cfine = pSiSEnt->sistvcolcalibf; 11383 } 11384#endif 11385 } else { 11386 pSiS->sistvcolcalibf = cfine = val; 11387 ccoarse = pSiS->sistvcolcalibc; 11388#ifdef SISDUALHEAD 11389 if(pSiSEnt) { 11390 pSiSEnt->sistvcolcalibf = val; 11391 if(pSiS->DualHeadMode) ccoarse = pSiSEnt->sistvcolcalibc; 11392 } 11393#endif 11394 } 11395 11396 if(!(pSiS->VBFlags & CRT2_TV)) return; 11397 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11398 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return; 11399 11400#ifdef UNLOCK_ALWAYS 11401 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11402#endif 11403 11404 if((cfine >= -128) && (cfine <= 127) && (ccoarse >= -120) && (ccoarse <= 120)) { 11405 long finalcc = cbase + (((ccoarse * 256) + cfine) * 256); 11406 11407#if 0 11408 inSISIDXREG(SISPART4,0x1f,temp); 11409 if(!(temp & 0x01)) { 11410 if(pSiS->VBFlags & TV_NTSC) finalcc += 0x21ed8620; 11411 else if(pSiS->VBFlags & TV_PALM) finalcc += ?; 11412 else if(pSiS->VBFlags & TV_PALM) finalcc += ?; 11413 else finalcc += 0x2a05d300; 11414 } 11415#endif 11416 setSISIDXREG(SISPART2,0x31,0x80,((finalcc >> 24) & 0x7f)); 11417 outSISIDXREG(SISPART2,0x32,((finalcc >> 16) & 0xff)); 11418 outSISIDXREG(SISPART2,0x33,((finalcc >> 8) & 0xff)); 11419 outSISIDXREG(SISPART2,0x34,(finalcc & 0xff)); 11420 } 11421} 11422 11423int SiS_GetSISTVcolcalib(ScrnInfoPtr pScrn, Bool coarse) 11424{ 11425 SISPtr pSiS = SISPTR(pScrn); 11426#ifdef SISDUALHEAD 11427 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11428 11429 if(pSiSEnt && pSiS->DualHeadMode) 11430 if(coarse) return (int)pSiSEnt->sistvcolcalibc; 11431 else return (int)pSiSEnt->sistvcolcalibf; 11432 else 11433#endif 11434 if(coarse) return (int)pSiS->sistvcolcalibc; 11435 else return (int)pSiS->sistvcolcalibf; 11436} 11437 11438void SiS_SetSISTVcfilter(ScrnInfoPtr pScrn, int val) 11439{ 11440 SISPtr pSiS = SISPTR(pScrn); 11441#ifdef SISDUALHEAD 11442 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11443#endif 11444 11445 pSiS->sistvcfilter = val ? 1 : 0; 11446#ifdef SISDUALHEAD 11447 if(pSiSEnt) pSiSEnt->sistvcfilter = pSiS->sistvcfilter; 11448#endif 11449 11450 if(!(pSiS->VBFlags & CRT2_TV)) return; 11451 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11452 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return; 11453 11454#ifdef UNLOCK_ALWAYS 11455 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11456#endif 11457 11458 setSISIDXREG(SISPART2,0x30,~0x10,((pSiS->sistvcfilter << 4) & 0x10)); 11459} 11460 11461int SiS_GetSISTVcfilter(ScrnInfoPtr pScrn) 11462{ 11463 SISPtr pSiS = SISPTR(pScrn); 11464 int result = pSiS->sistvcfilter; 11465 UChar temp; 11466#ifdef SISDUALHEAD 11467 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11468 11469 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvcfilter; 11470#endif 11471 11472 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return result; 11473 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11474 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return result; 11475 11476#ifdef UNLOCK_ALWAYS 11477 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11478#endif 11479 inSISIDXREG(SISPART2, 0x30, temp); 11480 return (int)((temp & 0x10) ? 1 : 0); 11481} 11482 11483void SiS_SetSISTVyfilter(ScrnInfoPtr pScrn, int val) 11484{ 11485 SISPtr pSiS = SISPTR(pScrn); 11486#ifdef SISDUALHEAD 11487 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11488#endif 11489 UChar p35,p36,p37,p38,p48,p49,p4a,p30; 11490 int i,j; 11491 11492 pSiS->sistvyfilter = val; 11493#ifdef SISDUALHEAD 11494 if(pSiSEnt) pSiSEnt->sistvyfilter = pSiS->sistvyfilter; 11495#endif 11496 11497 if(!(pSiS->VBFlags & CRT2_TV)) return; 11498 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11499 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return; 11500 11501 p35 = pSiS->p2_35; p36 = pSiS->p2_36; 11502 p37 = pSiS->p2_37; p38 = pSiS->p2_38; 11503 p48 = pSiS->p2_48; p49 = pSiS->p2_49; 11504 p4a = pSiS->p2_4a; p30 = pSiS->p2_30; 11505#ifdef SISDUALHEAD 11506 if(pSiSEnt && pSiS->DualHeadMode) { 11507 p35 = pSiSEnt->p2_35; p36 = pSiSEnt->p2_36; 11508 p37 = pSiSEnt->p2_37; p38 = pSiSEnt->p2_38; 11509 p48 = pSiSEnt->p2_48; p49 = pSiSEnt->p2_49; 11510 p4a = pSiSEnt->p2_4a; p30 = pSiSEnt->p2_30; 11511 } 11512#endif 11513 p30 &= 0x20; 11514 11515#ifdef UNLOCK_ALWAYS 11516 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11517#endif 11518 11519 switch(pSiS->sistvyfilter) { 11520 case 0: 11521 andSISIDXREG(SISPART2,0x30,0xdf); 11522 break; 11523 case 1: 11524 outSISIDXREG(SISPART2,0x35,p35); 11525 outSISIDXREG(SISPART2,0x36,p36); 11526 outSISIDXREG(SISPART2,0x37,p37); 11527 outSISIDXREG(SISPART2,0x38,p38); 11528 if(!(pSiS->VBFlags2 & VB2_301)) { 11529 outSISIDXREG(SISPART2,0x48,p48); 11530 outSISIDXREG(SISPART2,0x49,p49); 11531 outSISIDXREG(SISPART2,0x4a,p4a); 11532 } 11533 setSISIDXREG(SISPART2,0x30,0xdf,p30); 11534 break; 11535 case 2: 11536 case 3: 11537 case 4: 11538 case 5: 11539 case 6: 11540 case 7: 11541 case 8: 11542 if(!(pSiS->VBFlags & (TV_PALM | TV_PALN | TV_NTSCJ))) { 11543 int yindex301 = -1, yindex301B = -1; 11544 UChar p3d4_34; 11545 11546 inSISIDXREG(SISCR,0x34,p3d4_34); 11547 11548 switch((p3d4_34 & 0x7f)) { 11549 case 0x59: /* 320x200 */ 11550 case 0x41: 11551 case 0x4f: 11552 case 0x50: /* 320x240 */ 11553 case 0x56: 11554 case 0x53: 11555 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 0 : 4; 11556 break; 11557 case 0x2f: /* 640x400 */ 11558 case 0x5d: 11559 case 0x5e: 11560 case 0x2e: /* 640x480 */ 11561 case 0x44: 11562 case 0x62: 11563 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 1 : 5; 11564 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 0 : 4; 11565 break; 11566 case 0x31: /* 720x480 */ 11567 case 0x33: 11568 case 0x35: 11569 case 0x32: /* 720x576 */ 11570 case 0x34: 11571 case 0x36: 11572 case 0x5f: /* 768x576 */ 11573 case 0x60: 11574 case 0x61: 11575 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 2 : 6; 11576 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 1 : 5; 11577 break; 11578 case 0x51: /* 400x300 */ 11579 case 0x57: 11580 case 0x54: 11581 case 0x30: /* 800x600 */ 11582 case 0x47: 11583 case 0x63: 11584 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 3 : 7; 11585 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 2 : 6; 11586 break; 11587 case 0x52: /* 512x384 */ 11588 case 0x58: 11589 case 0x5c: 11590 case 0x38: /* 1024x768 */ 11591 case 0x4a: 11592 case 0x64: 11593 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 3 : 7; 11594 break; 11595 } 11596 if(pSiS->VBFlags2 & VB2_301) { 11597 if(yindex301 >= 0) { 11598 for(i=0, j=0x35; i<=3; i++, j++) { 11599 outSISIDXREG(SISPART2,j,(SiSTVFilter301[yindex301].filter[pSiS->sistvyfilter-2][i])); 11600 } 11601 } 11602 } else { 11603 if(yindex301B >= 0) { 11604 for(i=0, j=0x35; i<=3; i++, j++) { 11605 outSISIDXREG(SISPART2,j,(SiSTVFilter301B[yindex301B].filter[pSiS->sistvyfilter-2][i])); 11606 } 11607 for(i=4, j=0x48; i<=6; i++, j++) { 11608 outSISIDXREG(SISPART2,j,(SiSTVFilter301B[yindex301B].filter[pSiS->sistvyfilter-2][i])); 11609 } 11610 } 11611 } 11612 orSISIDXREG(SISPART2,0x30,0x20); 11613 } 11614 } 11615} 11616 11617int SiS_GetSISTVyfilter(ScrnInfoPtr pScrn) 11618{ 11619 SISPtr pSiS = SISPTR(pScrn); 11620#ifdef SISDUALHEAD 11621 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11622 11623 if(pSiSEnt && pSiS->DualHeadMode) 11624 return (int)pSiSEnt->sistvyfilter; 11625 else 11626#endif 11627 return (int)pSiS->sistvyfilter; 11628} 11629 11630void SiS_SetSIS6326TVantiflicker(ScrnInfoPtr pScrn, int val) 11631{ 11632 SISPtr pSiS = SISPTR(pScrn); 11633 UChar tmp; 11634 11635 pSiS->sistvantiflicker = val; 11636 11637 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 11638 11639#ifdef UNLOCK_ALWAYS 11640 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11641#endif 11642 11643 tmp = SiS6326GetTVReg(pScrn,0x00); 11644 if(!(tmp & 0x04)) return; 11645 11646 /* Valid values: 0=off, 1=low, 2=med, 3=high, 4=adaptive */ 11647 if(val >= 0 && val <= 4) { 11648 tmp &= 0x1f; 11649 tmp |= (val << 5); 11650 SiS6326SetTVReg(pScrn,0x00,tmp); 11651 } 11652} 11653 11654int SiS_GetSIS6326TVantiflicker(ScrnInfoPtr pScrn) 11655{ 11656 SISPtr pSiS = SISPTR(pScrn); 11657 UChar tmp; 11658 11659 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 11660 return (int)pSiS->sistvantiflicker; 11661 } 11662 11663#ifdef UNLOCK_ALWAYS 11664 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11665#endif 11666 11667 tmp = SiS6326GetTVReg(pScrn,0x00); 11668 if(!(tmp & 0x04)) { 11669 return (int)pSiS->sistvantiflicker; 11670 } else { 11671 return (int)((tmp >> 5) & 0x07); 11672 } 11673} 11674 11675void SiS_SetSIS6326TVenableyfilter(ScrnInfoPtr pScrn, int val) 11676{ 11677 SISPtr pSiS = SISPTR(pScrn); 11678 UChar tmp; 11679 11680 if(val) val = 1; 11681 pSiS->sis6326enableyfilter = val; 11682 11683 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 11684 11685#ifdef UNLOCK_ALWAYS 11686 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11687#endif 11688 11689 tmp = SiS6326GetTVReg(pScrn,0x00); 11690 if(!(tmp & 0x04)) return; 11691 11692 tmp = SiS6326GetTVReg(pScrn,0x43); 11693 tmp &= ~0x10; 11694 tmp |= ((val & 0x01) << 4); 11695 SiS6326SetTVReg(pScrn,0x43,tmp); 11696} 11697 11698int SiS_GetSIS6326TVenableyfilter(ScrnInfoPtr pScrn) 11699{ 11700 SISPtr pSiS = SISPTR(pScrn); 11701 UChar tmp; 11702 11703 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 11704 return (int)pSiS->sis6326enableyfilter; 11705 } 11706 11707#ifdef UNLOCK_ALWAYS 11708 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11709#endif 11710 11711 tmp = SiS6326GetTVReg(pScrn,0x00); 11712 if(!(tmp & 0x04)) { 11713 return (int)pSiS->sis6326enableyfilter; 11714 } else { 11715 tmp = SiS6326GetTVReg(pScrn,0x43); 11716 return (int)((tmp >> 4) & 0x01); 11717 } 11718} 11719 11720void SiS_SetSIS6326TVyfilterstrong(ScrnInfoPtr pScrn, int val) 11721{ 11722 SISPtr pSiS = SISPTR(pScrn); 11723 UChar tmp; 11724 11725 if(val) val = 1; 11726 pSiS->sis6326yfilterstrong = val; 11727 11728 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 11729 11730#ifdef UNLOCK_ALWAYS 11731 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11732#endif 11733 11734 tmp = SiS6326GetTVReg(pScrn,0x00); 11735 if(!(tmp & 0x04)) return; 11736 11737 tmp = SiS6326GetTVReg(pScrn,0x43); 11738 if(tmp & 0x10) { 11739 tmp &= ~0x40; 11740 tmp |= ((val & 0x01) << 6); 11741 SiS6326SetTVReg(pScrn,0x43,tmp); 11742 } 11743} 11744 11745int SiS_GetSIS6326TVyfilterstrong(ScrnInfoPtr pScrn) 11746{ 11747 SISPtr pSiS = SISPTR(pScrn); 11748 UChar tmp; 11749 11750 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 11751 return (int)pSiS->sis6326yfilterstrong; 11752 } 11753 11754#ifdef UNLOCK_ALWAYS 11755 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11756#endif 11757 11758 tmp = SiS6326GetTVReg(pScrn,0x00); 11759 if(!(tmp & 0x04)) { 11760 return (int)pSiS->sis6326yfilterstrong; 11761 } else { 11762 tmp = SiS6326GetTVReg(pScrn,0x43); 11763 if(!(tmp & 0x10)) { 11764 return (int)pSiS->sis6326yfilterstrong; 11765 } else { 11766 return (int)((tmp >> 6) & 0x01); 11767 } 11768 } 11769} 11770 11771void SiS_SetTVxposoffset(ScrnInfoPtr pScrn, int val) 11772{ 11773 SISPtr pSiS = SISPTR(pScrn); 11774#ifdef SISDUALHEAD 11775 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11776#endif 11777 11778#ifdef UNLOCK_ALWAYS 11779 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11780#endif 11781 11782 pSiS->tvxpos = val; 11783#ifdef SISDUALHEAD 11784 if(pSiSEnt) pSiSEnt->tvxpos = val; 11785#endif 11786 11787 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 11788 11789 if(pSiS->VBFlags & CRT2_TV) { 11790 11791 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 11792 11793 int x = pSiS->tvx; 11794#ifdef SISDUALHEAD 11795 if(pSiSEnt && pSiS->DualHeadMode) x = pSiSEnt->tvx; 11796#endif 11797 switch(pSiS->ChrontelType) { 11798 case CHRONTEL_700x: 11799 if((val >= -32) && (val <= 32)) { 11800 x += val; 11801 if(x < 0) x = 0; 11802 SiS_SetCH700x(pSiS->SiS_Pr, 0x0a, (x & 0xff)); 11803 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD); 11804 } 11805 break; 11806 case CHRONTEL_701x: 11807 /* Not supported by hardware */ 11808 break; 11809 } 11810 11811 } else if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 11812 11813 if((val >= -32) && (val <= 32)) { 11814 11815 UChar p2_1f,p2_20,p2_2b,p2_42,p2_43; 11816 UShort temp; 11817 int mult; 11818 11819 p2_1f = pSiS->p2_1f; 11820 p2_20 = pSiS->p2_20; 11821 p2_2b = pSiS->p2_2b; 11822 p2_42 = pSiS->p2_42; 11823 p2_43 = pSiS->p2_43; 11824#ifdef SISDUALHEAD 11825 if(pSiSEnt && pSiS->DualHeadMode) { 11826 p2_1f = pSiSEnt->p2_1f; 11827 p2_20 = pSiSEnt->p2_20; 11828 p2_2b = pSiSEnt->p2_2b; 11829 p2_42 = pSiSEnt->p2_42; 11830 p2_43 = pSiSEnt->p2_43; 11831 } 11832#endif 11833 mult = 2; 11834 if(pSiS->VBFlags & TV_YPBPR) { 11835 if(pSiS->VBFlags & (TV_YPBPR1080I | TV_YPBPR750P)) { 11836 mult = 4; 11837 } 11838 } 11839 11840 temp = p2_1f | ((p2_20 & 0xf0) << 4); 11841 temp += (val * mult); 11842 p2_1f = temp & 0xff; 11843 p2_20 = (temp & 0xf00) >> 4; 11844 p2_2b = ((p2_2b & 0x0f) + (val * mult)) & 0x0f; 11845 temp = p2_43 | ((p2_42 & 0xf0) << 4); 11846 temp += (val * mult); 11847 p2_43 = temp & 0xff; 11848 p2_42 = (temp & 0xf00) >> 4; 11849 SISWaitRetraceCRT2(pScrn); 11850 outSISIDXREG(SISPART2,0x1f,p2_1f); 11851 setSISIDXREG(SISPART2,0x20,0x0F,p2_20); 11852 setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b); 11853 setSISIDXREG(SISPART2,0x42,0x0F,p2_42); 11854 outSISIDXREG(SISPART2,0x43,p2_43); 11855 } 11856 } 11857 } 11858 11859 } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { 11860 11861 if(pSiS->SiS6326Flags & SIS6326_TVDETECTED) { 11862 11863 UChar tmp; 11864 UShort temp1, temp2, temp3; 11865 11866 tmp = SiS6326GetTVReg(pScrn,0x00); 11867 if(tmp & 0x04) { 11868 11869 temp1 = pSiS->tvx1; 11870 temp2 = pSiS->tvx2; 11871 temp3 = pSiS->tvx3; 11872 if((val >= -16) && (val <= 16)) { 11873 if(val > 0) { 11874 temp1 += (val * 4); 11875 temp2 += (val * 4); 11876 while((temp1 > 0x0fff) || (temp2 > 0x0fff)) { 11877 temp1 -= 4; 11878 temp2 -= 4; 11879 } 11880 } else { 11881 val = -val; 11882 temp3 += (val * 4); 11883 while(temp3 > 0x03ff) { 11884 temp3 -= 4; 11885 } 11886 } 11887 } 11888 SiS6326SetTVReg(pScrn,0x3a,(temp1 & 0xff)); 11889 tmp = SiS6326GetTVReg(pScrn,0x3c); 11890 tmp &= 0xf0; 11891 tmp |= ((temp1 & 0x0f00) >> 8); 11892 SiS6326SetTVReg(pScrn,0x3c,tmp); 11893 SiS6326SetTVReg(pScrn,0x26,(temp2 & 0xff)); 11894 tmp = SiS6326GetTVReg(pScrn,0x27); 11895 tmp &= 0x0f; 11896 tmp |= ((temp2 & 0x0f00) >> 4); 11897 SiS6326SetTVReg(pScrn,0x27,tmp); 11898 SiS6326SetTVReg(pScrn,0x12,(temp3 & 0xff)); 11899 tmp = SiS6326GetTVReg(pScrn,0x13); 11900 tmp &= ~0xC0; 11901 tmp |= ((temp3 & 0x0300) >> 2); 11902 SiS6326SetTVReg(pScrn,0x13,tmp); 11903 } 11904 } 11905 } 11906} 11907 11908int SiS_GetTVxposoffset(ScrnInfoPtr pScrn) 11909{ 11910 SISPtr pSiS = SISPTR(pScrn); 11911#ifdef SISDUALHEAD 11912 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11913 11914 if(pSiSEnt && pSiS->DualHeadMode) 11915 return (int)pSiSEnt->tvxpos; 11916 else 11917#endif 11918 return (int)pSiS->tvxpos; 11919} 11920 11921void SiS_SetTVyposoffset(ScrnInfoPtr pScrn, int val) 11922{ 11923 SISPtr pSiS = SISPTR(pScrn); 11924#ifdef SISDUALHEAD 11925 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11926#endif 11927 11928#ifdef UNLOCK_ALWAYS 11929 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11930#endif 11931 11932 pSiS->tvypos = val; 11933#ifdef SISDUALHEAD 11934 if(pSiSEnt) pSiSEnt->tvypos = val; 11935#endif 11936 11937 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 11938 11939 if(pSiS->VBFlags & CRT2_TV) { 11940 11941 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 11942 11943 int y = pSiS->tvy; 11944#ifdef SISDUALHEAD 11945 if(pSiSEnt && pSiS->DualHeadMode) y = pSiSEnt->tvy; 11946#endif 11947 switch(pSiS->ChrontelType) { 11948 case CHRONTEL_700x: 11949 if((val >= -32) && (val <= 32)) { 11950 y -= val; 11951 if(y < 0) y = 0; 11952 SiS_SetCH700x(pSiS->SiS_Pr, 0x0b, (y & 0xff)); 11953 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE); 11954 } 11955 break; 11956 case CHRONTEL_701x: 11957 /* Not supported by hardware */ 11958 break; 11959 } 11960 11961 } else if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 11962 11963 if((val >= -32) && (val <= 32)) { 11964 char p2_01, p2_02; 11965 11966 if( (pSiS->VBFlags & TV_HIVISION) || 11967 ((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & (TV_YPBPR1080I|TV_YPBPR750P))) ) { 11968 val *= 2; 11969 } else { 11970 val /= 2; /* 4 */ 11971 } 11972 11973 p2_01 = pSiS->p2_01; 11974 p2_02 = pSiS->p2_02; 11975#ifdef SISDUALHEAD 11976 if(pSiSEnt && pSiS->DualHeadMode) { 11977 p2_01 = pSiSEnt->p2_01; 11978 p2_02 = pSiSEnt->p2_02; 11979 } 11980#endif 11981 p2_01 += val; /* val * 2 */ 11982 p2_02 += val; /* val * 2 */ 11983 if(!(pSiS->VBFlags & (TV_YPBPR | TV_HIVISION))) { 11984 while((p2_01 <= 0) || (p2_02 <= 0)) { 11985 p2_01 += 2; 11986 p2_02 += 2; 11987 } 11988 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR1080I)) { 11989 while(p2_01 <= 8) { 11990 p2_01 += 2; 11991 p2_02 += 2; 11992 } 11993 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR750P)) { 11994 while(p2_01 <= 10) { 11995 p2_01 += 2; 11996 p2_02 += 2; 11997 } 11998 } 11999 12000 SISWaitRetraceCRT2(pScrn); 12001 outSISIDXREG(SISPART2,0x01,p2_01); 12002 outSISIDXREG(SISPART2,0x02,p2_02); 12003 } 12004 } 12005 12006 } 12007 12008 } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { 12009 12010 if(pSiS->SiS6326Flags & SIS6326_TVDETECTED) { 12011 12012 UChar tmp; 12013 int temp1, limit; 12014 12015 tmp = SiS6326GetTVReg(pScrn,0x00); 12016 if(tmp & 0x04) { 12017 12018 if((val >= -16) && (val <= 16)) { 12019 temp1 = (UShort)pSiS->tvy1; 12020 limit = (pSiS->SiS6326Flags & SIS6326_TVPAL) ? 625 : 525; 12021 if(val > 0) { 12022 temp1 += (val * 4); 12023 if(temp1 > limit) temp1 -= limit; 12024 } else { 12025 val = -val; 12026 temp1 -= (val * 2); 12027 if(temp1 <= 0) temp1 += (limit -1); 12028 } 12029 SiS6326SetTVReg(pScrn,0x11,(temp1 & 0xff)); 12030 tmp = SiS6326GetTVReg(pScrn,0x13); 12031 tmp &= ~0x30; 12032 tmp |= ((temp1 & 0x300) >> 4); 12033 SiS6326SetTVReg(pScrn,0x13,tmp); 12034 if(temp1 == 1) tmp = 0x10; 12035 else { 12036 if(pSiS->SiS6326Flags & SIS6326_TVPAL) { 12037 if((temp1 <= 3) || (temp1 >= (limit - 2))) tmp = 0x08; 12038 else if(temp1 < 22) tmp = 0x02; 12039 else tmp = 0x04; 12040 } else { 12041 if((temp1 <= 5) || (temp1 >= (limit - 4))) tmp = 0x08; 12042 else if(temp1 < 19) tmp = 0x02; 12043 else tmp = 0x04; 12044 } 12045 } 12046 SiS6326SetTVReg(pScrn,0x21,tmp); 12047 } 12048 } 12049 } 12050 } 12051} 12052 12053int SiS_GetTVyposoffset(ScrnInfoPtr pScrn) 12054{ 12055 SISPtr pSiS = SISPTR(pScrn); 12056#ifdef SISDUALHEAD 12057 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12058 12059 if(pSiSEnt && pSiS->DualHeadMode) 12060 return (int)pSiSEnt->tvypos; 12061 else 12062#endif 12063 return (int)pSiS->tvypos; 12064} 12065 12066void SiS_SetTVxscale(ScrnInfoPtr pScrn, int val) 12067{ 12068 SISPtr pSiS = SISPTR(pScrn); 12069#ifdef SISDUALHEAD 12070 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12071#endif 12072 12073#ifdef UNLOCK_ALWAYS 12074 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12075#endif 12076 12077 pSiS->tvxscale = val; 12078#ifdef SISDUALHEAD 12079 if(pSiSEnt) pSiSEnt->tvxscale = val; 12080#endif 12081 12082 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 12083 12084 if((pSiS->VBFlags & CRT2_TV) && (pSiS->VBFlags2 & VB2_SISBRIDGE)) { 12085 12086 if((val >= -16) && (val <= 16)) { 12087 12088 UChar p2_44,p2_45,p2_46; 12089 int scalingfactor, mult; 12090 12091 p2_44 = pSiS->p2_44; 12092 p2_45 = pSiS->p2_45 & 0x3f; 12093 p2_46 = pSiS->p2_46 & 0x07; 12094#ifdef SISDUALHEAD 12095 if(pSiSEnt && pSiS->DualHeadMode) { 12096 p2_44 = pSiSEnt->p2_44; 12097 p2_45 = pSiSEnt->p2_45 & 0x3f; 12098 p2_46 = pSiSEnt->p2_46 & 0x07; 12099 } 12100#endif 12101 scalingfactor = (p2_46 << 13) | ((p2_45 & 0x1f) << 8) | p2_44; 12102 12103 mult = 64; 12104 if(pSiS->VBFlags & TV_YPBPR) { 12105 if(pSiS->VBFlags & TV_YPBPR1080I) { 12106 mult = 190; 12107 } else if(pSiS->VBFlags & TV_YPBPR750P) { 12108 mult = 360; 12109 } 12110 } else if(pSiS->VBFlags & TV_HIVISION) { 12111 mult = 190; 12112 } 12113 12114 if(val < 0) { 12115 p2_45 &= 0xdf; 12116 scalingfactor += ((-val) * mult); 12117 if(scalingfactor > 0xffff) scalingfactor = 0xffff; 12118 } else if(val > 0) { 12119 p2_45 &= 0xdf; 12120 scalingfactor -= (val * mult); 12121 if(scalingfactor < 1) scalingfactor = 1; 12122 } 12123 12124 p2_44 = scalingfactor & 0xff; 12125 p2_45 &= 0xe0; 12126 p2_45 |= ((scalingfactor >> 8) & 0x1f); 12127 p2_46 = ((scalingfactor >> 13) & 0x07); 12128 12129 SISWaitRetraceCRT2(pScrn); 12130 outSISIDXREG(SISPART2,0x44,p2_44); 12131 setSISIDXREG(SISPART2,0x45,0xC0,p2_45); 12132 if(!(pSiS->VBFlags2 & VB2_301)) { 12133 setSISIDXREG(SISPART2,0x46,0xF8,p2_46); 12134 } 12135 12136 } 12137 12138 } 12139 12140 } 12141} 12142 12143int SiS_GetTVxscale(ScrnInfoPtr pScrn) 12144{ 12145 SISPtr pSiS = SISPTR(pScrn); 12146#ifdef SISDUALHEAD 12147 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12148 12149 if(pSiSEnt && pSiS->DualHeadMode) 12150 return (int)pSiSEnt->tvxscale; 12151 else 12152#endif 12153 return (int)pSiS->tvxscale; 12154} 12155 12156void SiS_SetTVyscale(ScrnInfoPtr pScrn, int val) 12157{ 12158 SISPtr pSiS = SISPTR(pScrn); 12159#ifdef SISDUALHEAD 12160 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12161#endif 12162 12163#ifdef UNLOCK_ALWAYS 12164 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12165#endif 12166 12167 if(val < -4) val = -4; 12168 if(val > 3) val = 3; 12169 12170 pSiS->tvyscale = val; 12171#ifdef SISDUALHEAD 12172 if(pSiSEnt) pSiSEnt->tvyscale = val; 12173#endif 12174 12175 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 12176 12177 if((pSiS->VBFlags & CRT2_TV) && (pSiS->VBFlags2 & VB2_SISBRIDGE)) { 12178 12179 int srindex = -1, newvde, i = 0, j, vlimit, temp, vdediv; 12180 int hdclk = 0; 12181 UChar p3d4_34; 12182 Bool found = FALSE; 12183 Bool usentsc = FALSE; 12184 Bool is750p = FALSE; 12185 Bool is1080i = FALSE; 12186 Bool skipmoveup = FALSE; 12187 12188 SiS_UnLockCRT2(pSiS->SiS_Pr); 12189 12190 if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR525P)) { 12191 vlimit = 525 - 7; 12192 vdediv = 1; 12193 usentsc = TRUE; 12194 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR625P)) { 12195 vlimit = 625 - 7; 12196 vdediv = 1; 12197 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR750P)) { 12198 vlimit = 750 - 7; 12199 vdediv = 1; 12200 is750p = TRUE; 12201 } else if(((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR1080I)) || 12202 (pSiS->VBFlags & TV_HIVISION)) { 12203 vlimit = (1125 - 7) / 2; 12204 vdediv = 2; 12205 is1080i = TRUE; 12206 } else { 12207 if( ((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR525I)) || 12208 ((!(pSiS->VBFlags & TV_YPBPR)) && (pSiS->VBFlags & (TV_NTSC | TV_PALM))) ) { 12209 usentsc = TRUE; 12210 } 12211 vlimit = usentsc ? 259 : 309; 12212 vdediv = 2; 12213 } 12214 12215 inSISIDXREG(SISCR,0x34,p3d4_34); 12216 12217 switch((p3d4_34 & 0x7f)) { 12218 case 0x50: /* 320x240 */ 12219 case 0x56: 12220 case 0x53: 12221 hdclk = 1; 12222 /* fall through */ 12223 case 0x2e: /* 640x480 */ 12224 case 0x44: 12225 case 0x62: 12226 if(is1080i) { 12227 srindex = 98; 12228 } else if(is750p) { 12229 srindex = 42; 12230 } else { 12231 srindex = usentsc ? 0 : 21; 12232 } 12233 break; 12234 case 0x31: /* 720x480 */ 12235 case 0x33: 12236 case 0x35: 12237 if(is1080i) { 12238 /* n/a */ 12239 } else if(is750p) { 12240 srindex = 49; 12241 } else { 12242 srindex = usentsc ? 7 : 21; 12243 } 12244 break; 12245 case 0x32: /* 720x576 */ 12246 case 0x34: 12247 case 0x36: 12248 case 0x5f: /* 768x576 */ 12249 case 0x60: 12250 case 0x61: 12251 if(is1080i) { 12252 /* n/a */ 12253 } else if(is750p) { 12254 srindex = 56; 12255 } else { 12256 srindex = usentsc ? 147 : 28; 12257 } 12258 break; 12259 case 0x70: /* 800x480 */ 12260 case 0x7a: 12261 case 0x76: 12262 if(is1080i) { 12263 srindex = 105; 12264 } else if(is750p) { 12265 srindex = 63; 12266 } else { 12267 srindex = usentsc ? 175 : 21; 12268 } 12269 break; 12270 case 0x51: /* 400x300 - hdclk mode */ 12271 case 0x57: 12272 case 0x54: 12273 hdclk = 1; 12274 /* fall through */ 12275 case 0x30: /* 800x600 */ 12276 case 0x47: 12277 case 0x63: 12278 if(is1080i) { 12279 srindex = 112; 12280 } else if(is750p) { 12281 srindex = 70; 12282 } else { 12283 srindex = usentsc ? 14 : 35; 12284 } 12285 break; 12286 case 0x1d: /* 960x540 */ 12287 case 0x1e: 12288 case 0x1f: 12289 if(is1080i) { 12290 srindex = 196; 12291 skipmoveup = TRUE; 12292 } 12293 break; 12294 case 0x20: /* 960x600 */ 12295 case 0x21: 12296 case 0x22: 12297 if(pSiS->VGAEngine == SIS_315_VGA && is1080i) { 12298 srindex = 203; 12299 } 12300 break; 12301 case 0x71: /* 1024x576 */ 12302 case 0x74: 12303 case 0x77: 12304 if(is1080i) { 12305 srindex = 119; 12306 } else if(is750p) { 12307 srindex = 77; 12308 } else { 12309 srindex = usentsc ? 182 : 189; 12310 } 12311 break; 12312 case 0x52: /* 512x384 */ 12313 case 0x58: 12314 case 0x5c: 12315 hdclk = 1; 12316 /* fall through */ 12317 case 0x38: /* 1024x768 */ 12318 case 0x4a: 12319 case 0x64: 12320 if(is1080i) { 12321 srindex = 126; 12322 } else if(is750p) { 12323 srindex = 84; 12324 } else if(!usentsc) { 12325 srindex = 154; 12326 } else if(vdediv == 1) { 12327 if(!hdclk) srindex = 168; 12328 } else { 12329 if(!hdclk) srindex = 161; 12330 } 12331 break; 12332 case 0x79: /* 1280x720 */ 12333 case 0x75: 12334 case 0x78: 12335 if(is1080i) { 12336 srindex = 133; 12337 } else if(is750p) { 12338 srindex = 91; 12339 } 12340 break; 12341 case 0x3a: /* 1280x1024 */ 12342 case 0x4d: 12343 case 0x65: 12344 if(is1080i) { 12345 srindex = 140; 12346 } 12347 break; 12348 } 12349 12350 if(srindex < 0) return; 12351 12352 if(pSiS->tvyscale != 0) { 12353 for(j = 0; j <= 1; j++) { 12354 for(i = 0; i <= 6; i++) { 12355 if(SiSTVVScale[srindex+i].sindex == pSiS->tvyscale) { 12356 found = TRUE; 12357 break; 12358 } 12359 } 12360 if(found) break; 12361 if(pSiS->tvyscale > 0) pSiS->tvyscale--; 12362 else pSiS->tvyscale++; 12363 } 12364 } 12365 12366#ifdef SISDUALHEAD 12367 if(pSiSEnt) pSiSEnt->tvyscale = pSiS->tvyscale; 12368#endif 12369 12370 if(pSiS->tvyscale == 0) { 12371 UChar p2_0a = pSiS->p2_0a; 12372 UChar p2_2f = pSiS->p2_2f; 12373 UChar p2_30 = pSiS->p2_30; 12374 UChar p2_46 = pSiS->p2_46; 12375 UChar p2_47 = pSiS->p2_47; 12376 UChar p1scaling[9], p4scaling[9]; 12377 UChar *p2scaling; 12378 12379 for(i = 0; i < 9; i++) { 12380 p1scaling[i] = pSiS->scalingp1[i]; 12381 p4scaling[i] = pSiS->scalingp4[i]; 12382 } 12383 p2scaling = &pSiS->scalingp2[0]; 12384 12385#ifdef SISDUALHEAD 12386 if(pSiSEnt && pSiS->DualHeadMode) { 12387 p2_0a = pSiSEnt->p2_0a; 12388 p2_2f = pSiSEnt->p2_2f; 12389 p2_30 = pSiSEnt->p2_30; 12390 p2_46 = pSiSEnt->p2_46; 12391 p2_47 = pSiSEnt->p2_47; 12392 for(i = 0; i < 9; i++) { 12393 p1scaling[i] = pSiSEnt->scalingp1[i]; 12394 p4scaling[i] = pSiSEnt->scalingp4[i]; 12395 } 12396 p2scaling = &pSiSEnt->scalingp2[0]; 12397 } 12398#endif 12399 SISWaitRetraceCRT2(pScrn); 12400 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 12401 for(i = 0; i < 64; i++) { 12402 outSISIDXREG(SISPART2,(0xc0 + i),p2scaling[i]); 12403 } 12404 } 12405 for(i = 0; i < 9; i++) { 12406 outSISIDXREG(SISPART1,SiSScalingP1Regs[i],p1scaling[i]); 12407 } 12408 for(i = 0; i < 9; i++) { 12409 outSISIDXREG(SISPART4,SiSScalingP4Regs[i],p4scaling[i]); 12410 } 12411 12412 setSISIDXREG(SISPART2,0x0a,0x7f,(p2_0a & 0x80)); 12413 outSISIDXREG(SISPART2,0x2f,p2_2f); 12414 setSISIDXREG(SISPART2,0x30,0x3f,(p2_30 & 0xc0)); 12415 if(!(pSiS->VBFlags2 & VB2_301)) { 12416 setSISIDXREG(SISPART2,0x46,0x9f,(p2_46 & 0x60)); 12417 outSISIDXREG(SISPART2,0x47,p2_47); 12418 } 12419 12420 } else { 12421 12422 int realvde, myypos, watchdog = 32; 12423 unsigned short temp1, temp2, vgahde, vgaht, vgavt; 12424 int p1div = 1; 12425 ULong calctemp; 12426 12427 srindex += i; 12428 newvde = SiSTVVScale[srindex].ScaleVDE; 12429 realvde = SiSTVVScale[srindex].RealVDE; 12430 12431 if(vdediv == 1) p1div = 2; 12432 12433 if(!skipmoveup) { 12434 do { 12435 inSISIDXREG(SISPART2,0x01,temp); 12436 temp = vlimit - ((temp & 0x7f) / p1div); 12437 if((temp - (((newvde / vdediv) - 2) + 9)) > 0) break; 12438 myypos = pSiS->tvypos - 1; 12439#ifdef SISDUALHEAD 12440 if(pSiSEnt && pSiS->DualHeadMode) myypos = pSiSEnt->tvypos - 1; 12441#endif 12442 SiS_SetTVyposoffset(pScrn, myypos); 12443 } while(watchdog--); 12444 } 12445 12446 SISWaitRetraceCRT2(pScrn); 12447 12448 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 12449 SiS_CalcXTapScaler(pSiS->SiS_Pr, realvde, newvde, 4, FALSE); 12450 } 12451 12452 if(!(pSiS->VBFlags2 & VB2_301)) { 12453 temp = (newvde / vdediv) - 3; 12454 setSISIDXREG(SISPART2,0x46,0x9f,((temp & 0x0300) >> 3)); 12455 outSISIDXREG(SISPART2,0x47,(temp & 0xff)); 12456 } 12457 12458 inSISIDXREG(SISPART1,0x0a,temp1); 12459 inSISIDXREG(SISPART1,0x0c,temp2); 12460 vgahde = ((temp2 & 0xf0) << 4) | temp1; 12461 if(pSiS->VGAEngine == SIS_300_VGA) { 12462 vgahde -= 12; 12463 } else { 12464 vgahde -= 16; 12465 if(hdclk) vgahde <<= 1; 12466 } 12467 12468 vgaht = SiSTVVScale[srindex].reg[0]; 12469 temp1 = vgaht; 12470 if((pSiS->VGAEngine == SIS_315_VGA) && hdclk) temp1 >>= 1; 12471 temp1--; 12472 outSISIDXREG(SISPART1,0x08,(temp1 & 0xff)); 12473 setSISIDXREG(SISPART1,0x09,0x0f,((temp1 >> 4) & 0xf0)); 12474 12475 temp2 = (vgaht - vgahde) >> 2; 12476 if(pSiS->VGAEngine == SIS_300_VGA) { 12477 temp1 = vgahde + 12 + temp2; 12478 temp2 = temp1 + (temp2 << 1); 12479 } else { 12480 temp1 = vgahde; 12481 if(hdclk) { 12482 temp1 >>= 1; 12483 temp2 >>= 1; 12484 } 12485 temp2 >>= 1; 12486 temp1 = temp1 + 16 + temp2; 12487 temp2 = temp1 + temp2; 12488 } 12489 outSISIDXREG(SISPART1,0x0b,(temp1 & 0xff)); 12490 setSISIDXREG(SISPART1,0x0c,0xf0,((temp1 >> 8) & 0x0f)); 12491 outSISIDXREG(SISPART1,0x0d,(temp2 & 0xff)); 12492 12493 vgavt = SiSTVVScale[srindex].reg[1]; 12494 temp1 = vgavt - 1; 12495 if(pSiS->VGAEngine == SIS_315_VGA) temp1--; 12496 outSISIDXREG(SISPART1,0x0e,(temp1 & 0xff)); 12497 setSISIDXREG(SISPART1,0x12,0xf8,((temp1 >> 8 ) & 0x07)); 12498 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->ChipType >= SIS_661)) { 12499 temp1 = (vgavt + SiSTVVScale[srindex].RealVDE) >> 1; 12500 temp2 = ((vgavt - SiSTVVScale[srindex].RealVDE) >> 4) + temp1 + 1; 12501 } else { 12502 temp1 = (vgavt - SiSTVVScale[srindex].RealVDE) >> 2; 12503 temp2 = (temp1 < 4) ? 4 : temp1; 12504 temp1 += SiSTVVScale[srindex].RealVDE; 12505 temp2 = (temp2 >> 2) + temp1 + 1; 12506 } 12507 outSISIDXREG(SISPART1,0x10,(temp1 & 0xff)); 12508 setSISIDXREG(SISPART1,0x11,0x8f,((temp1 >> 4) & 0x70)); 12509 setSISIDXREG(SISPART1,0x11,0xf0,(temp2 & 0x0f)); 12510 12511 setSISIDXREG(SISPART2,0x0a,0x7f,((SiSTVVScale[srindex].reg[2] >> 8) & 0x80)); 12512 outSISIDXREG(SISPART2,0x2f,((newvde / vdediv) - 2)); 12513 setSISIDXREG(SISPART2,0x30,0x3f,((((newvde / vdediv) - 2) >> 2) & 0xc0)); 12514 12515 outSISIDXREG(SISPART4,0x13,(SiSTVVScale[srindex].reg[2] & 0xff)); 12516 outSISIDXREG(SISPART4,0x14,(SiSTVVScale[srindex].reg[3] & 0xff)); 12517 setSISIDXREG(SISPART4,0x15,0x7f,((SiSTVVScale[srindex].reg[3] >> 1) & 0x80)); 12518 12519 temp1 = vgaht - 1; 12520 outSISIDXREG(SISPART4,0x16,(temp1 & 0xff)); 12521 setSISIDXREG(SISPART4,0x15,0x87,((temp1 >> 5) & 0x78)); 12522 12523 temp1 = vgavt - 1; 12524 outSISIDXREG(SISPART4,0x17,(temp1 & 0xff)); 12525 setSISIDXREG(SISPART4,0x15,0xf8,((temp1 >> 8) & 0x07)); 12526 12527 outSISIDXREG(SISPART4,0x18,0x00); 12528 setSISIDXREG(SISPART4,0x19,0xf0,0x00); 12529 12530 inSISIDXREG(SISPART4,0x0e,temp1); 12531 if(is1080i) { 12532 if(!(temp1 & 0xe0)) newvde >>= 1; 12533 } 12534 12535 temp = 0x40; 12536 if(realvde <= newvde) temp = 0; 12537 else realvde -= newvde; 12538 12539 calctemp = (realvde * 256 * 1024) / newvde; 12540 if((realvde * 256 * 1024) % newvde) calctemp++; 12541 outSISIDXREG(SISPART4,0x1b,(calctemp & 0xff)); 12542 outSISIDXREG(SISPART4,0x1a,((calctemp >> 8) & 0xff)); 12543 setSISIDXREG(SISPART4,0x19,0x8f,(((calctemp >> 12) & 0x70) | temp)); 12544 } 12545 12546 } 12547 12548 } 12549} 12550 12551int SiS_GetTVyscale(ScrnInfoPtr pScrn) 12552{ 12553 SISPtr pSiS = SISPTR(pScrn); 12554#ifdef SISDUALHEAD 12555 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12556 12557 if(pSiSEnt && pSiS->DualHeadMode) 12558 return (int)pSiSEnt->tvyscale; 12559 else 12560#endif 12561 return (int)pSiS->tvyscale; 12562} 12563 12564void SiS_SetSISCRT1SaturationGain(ScrnInfoPtr pScrn, int val) 12565{ 12566 SISPtr pSiS = SISPTR(pScrn); 12567#ifdef SISDUALHEAD 12568 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12569#endif 12570 12571 pSiS->siscrt1satgain = val; 12572#ifdef SISDUALHEAD 12573 if(pSiSEnt) pSiSEnt->siscrt1satgain = val; 12574#endif 12575 12576 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_CRT1SATGAIN)) return; 12577 12578#ifdef UNLOCK_ALWAYS 12579 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12580#endif 12581 12582 if((val >= 0) && (val <= 7)) { 12583 setSISIDXREG(SISCR,0x53,0xE3, (val << 2)); 12584 } 12585} 12586 12587int SiS_GetSISCRT1SaturationGain(ScrnInfoPtr pScrn) 12588{ 12589 SISPtr pSiS = SISPTR(pScrn); 12590 int result = pSiS->siscrt1satgain; 12591 UChar temp; 12592#ifdef SISDUALHEAD 12593 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12594 12595 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->siscrt1satgain; 12596#endif 12597 12598 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_CRT1SATGAIN)) return result; 12599 12600#ifdef UNLOCK_ALWAYS 12601 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12602#endif 12603 inSISIDXREG(SISCR, 0x53, temp); 12604 return (int)((temp >> 2) & 0x07); 12605} 12606 12607/* Calc dotclock from registers */ 12608static int 12609SiSGetClockFromRegs(UChar sr2b, UChar sr2c) 12610{ 12611 float num, denum, postscalar, divider; 12612 int myclock; 12613 12614 divider = (sr2b & 0x80) ? 2.0 : 1.0; 12615 postscalar = (sr2c & 0x80) ? 12616 ( (((sr2c >> 5) & 0x03) == 0x02) ? 6.0 : 8.0 ) : 12617 ( ((sr2c >> 5) & 0x03) + 1.0 ); 12618 num = (sr2b & 0x7f) + 1.0; 12619 denum = (sr2c & 0x1f) + 1.0; 12620 myclock = (int)((14318 * (divider / postscalar) * (num / denum)) / 1000); 12621 return myclock; 12622} 12623 12624#ifdef SISDUALHEAD 12625static void 12626SiS_SetDHFlags(SISPtr pSiS, unsigned int misc, unsigned int sd2) 12627{ 12628 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12629 12630 if(pSiS->DualHeadMode) { 12631 if(pSiSEnt->pScrn_1) { 12632 SISPTR(pSiSEnt->pScrn_1)->MiscFlags |= misc; 12633 SISPTR(pSiSEnt->pScrn_1)->SiS_SD2_Flags |= sd2; 12634 } 12635 if(pSiSEnt->pScrn_2) { 12636 SISPTR(pSiSEnt->pScrn_2)->MiscFlags |= misc; 12637 SISPTR(pSiSEnt->pScrn_2)->SiS_SD2_Flags |= sd2; 12638 } 12639 } 12640} 12641#endif 12642 12643/* PostSetMode: 12644 * -) Disable CRT1 for saving bandwidth. This doesn't work with VESA; 12645 * VESA uses the bridge in SlaveMode and switching CRT1 off while 12646 * the bridge is in SlaveMode not that clever... 12647 * -) Check if overlay can be used (depending on dotclock) 12648 * -) Check if Panel Scaler is active on LVDS for overlay re-scaling 12649 * -) Save TV registers for further processing 12650 * -) Apply TV settings 12651 */ 12652static void 12653SiSPostSetMode(ScrnInfoPtr pScrn, SISRegPtr sisReg) 12654{ 12655 SISPtr pSiS = SISPTR(pScrn); 12656#ifdef SISDUALHEAD 12657 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12658#endif 12659 UChar usScratchCR17, sr2b, sr2c, tmpreg; 12660 int myclock1, myclock2, mycoldepth1, mycoldepth2, temp; 12661 Bool flag = FALSE; 12662 Bool doit = TRUE; 12663 Bool IsInSlaveMode; 12664 12665#ifdef TWDEBUG 12666 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 12667 "CRT1off is %d\n", pSiS->CRT1off); 12668#endif 12669 pSiS->CRT1isoff = pSiS->CRT1off; 12670 12671#ifdef UNLOCK_ALWAYS 12672 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12673#endif 12674 12675 SiSFixupSR11(pScrn); 12676 12677 IsInSlaveMode = SiSBridgeIsInSlaveMode(pScrn); 12678 12679 if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE)) { 12680 12681 if(pSiS->VBFlags != pSiS->VBFlags_backup) { 12682 pSiS->VBFlags = pSiS->VBFlags_backup; 12683 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 12684 "VBFlags restored to %0x\n", pSiS->VBFlags); 12685 } 12686 12687 /* -) We can't switch off CRT1 if bridge is in SlaveMode. 12688 * -) If we change to a SlaveMode-Mode (like 512x384), we 12689 * need to adapt VBFlags for eg. Xv. 12690 */ 12691#ifdef SISDUALHEAD 12692 if(!pSiS->DualHeadMode) { 12693#endif 12694 if(IsInSlaveMode) { 12695 doit = FALSE; 12696 temp = pSiS->VBFlags; 12697 pSiS->VBFlags &= (~VB_DISPMODE_SINGLE); 12698 pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_DISP1); 12699 if(temp != pSiS->VBFlags) { 12700 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 12701 "VBFlags changed to 0x%0x\n", pSiS->VBFlags); 12702 } 12703 } 12704#ifdef SISDUALHEAD 12705 } 12706#endif 12707 12708 if(pSiS->VGAEngine == SIS_315_VGA) { 12709 12710 if((pSiS->CRT1off) && (doit)) { 12711 orSISIDXREG(SISCR,pSiS->myCR63,0x40); 12712 orSISIDXREG(SISSR,0x1f,0xc0); 12713 andSISIDXREG(SISSR,0x07,~0x10); 12714 andSISIDXREG(SISSR,0x06,0xe2); 12715 andSISIDXREG(SISSR,0x31,0xcf); 12716 outSISIDXREG(SISSR,0x2b,0x1b); 12717 outSISIDXREG(SISSR,0x2c,0xe1); 12718 outSISIDXREG(SISSR,0x2d,0x01); 12719 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 12720 usleep(10000); 12721 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 12722 } else { 12723 andSISIDXREG(SISCR,pSiS->myCR63,0xBF); 12724 andSISIDXREG(SISSR,0x1f,0x3f); 12725 orSISIDXREG(SISSR,0x07,0x10); 12726 } 12727 12728 } else { 12729 12730 if(doit) { 12731 inSISIDXREG(SISCR, 0x17, usScratchCR17); 12732 if(pSiS->CRT1off) { 12733 if(usScratchCR17 & 0x80) { 12734 flag = TRUE; 12735 usScratchCR17 &= ~0x80; 12736 } 12737 orSISIDXREG(SISSR,0x1f,0xc0); 12738 } else { 12739 if(!(usScratchCR17 & 0x80)) { 12740 flag = TRUE; 12741 usScratchCR17 |= 0x80; 12742 } 12743 andSISIDXREG(SISSR,0x1f,0x3f); 12744 } 12745 /* Reset only if status changed */ 12746 if(flag) { 12747 outSISIDXREG(SISCR, 0x17, usScratchCR17); 12748 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 12749 usleep(10000); 12750 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 12751 } 12752 } 12753 } 12754 12755 } 12756 12757 /* Set bridge to "disable CRT2" mode if CRT2 is disabled, LCD-A is enabled */ 12758 /* (Not needed for CRT1=VGA since CRT2 will really be disabled then) */ 12759#ifdef SISDUALHEAD 12760 if(!pSiS->DualHeadMode) { 12761#endif 12762 if((pSiS->VGAEngine == SIS_315_VGA) && (pSiS->VBFlags2 & VB2_SISLCDABRIDGE)) { 12763 if((!pSiS->UseVESA) && (!(pSiS->VBFlags & CRT2_ENABLE)) && (pSiS->VBFlags & CRT1_LCDA)) { 12764 if(!IsInSlaveMode) { 12765 andSISIDXREG(SISPART4,0x0d,~0x07); 12766 } 12767 } 12768 } 12769#ifdef SISDUALHEAD 12770 } 12771#endif 12772 12773 /* Reset flags */ 12774 pSiS->MiscFlags &= ~( MISC_CRT1OVERLAY | 12775 MISC_CRT2OVERLAY | 12776 MISC_CRT1OVERLAYGAMMA | 12777 MISC_SIS760ONEOVERLAY | 12778 MISC_PANELLINKSCALER | 12779 MISC_STNMODE | 12780 MISC_TVNTSC1024); 12781 12782 pSiS->SiS_SD2_Flags &= ~SiS_SD2_SIS760ONEOVL; 12783 12784#ifdef SISDUALHEAD 12785 if(pSiS->DualHeadMode) { 12786 if(pSiSEnt->pScrn_1) { 12787 SISPTR(pSiSEnt->pScrn_1)->MiscFlags &= ~(MISC_SIS760ONEOVERLAY | 12788 MISC_CRT1OVERLAY | 12789 MISC_CRT2OVERLAY | 12790 MISC_CRT1OVERLAYGAMMA | 12791 MISC_PANELLINKSCALER | 12792 MISC_STNMODE | 12793 MISC_TVNTSC1024); 12794 SISPTR(pSiSEnt->pScrn_1)->SiS_SD2_Flags &= ~SiS_SD2_SIS760ONEOVL; 12795 } 12796 if(pSiSEnt->pScrn_2) { 12797 SISPTR(pSiSEnt->pScrn_2)->MiscFlags &= ~(MISC_SIS760ONEOVERLAY | 12798 MISC_CRT1OVERLAY | 12799 MISC_CRT2OVERLAY | 12800 MISC_CRT1OVERLAYGAMMA | 12801 MISC_PANELLINKSCALER | 12802 MISC_STNMODE | 12803 MISC_TVNTSC1024); 12804 SISPTR(pSiSEnt->pScrn_2)->SiS_SD2_Flags &= ~SiS_SD2_SIS760ONEOVL; 12805 } 12806 } 12807#endif 12808 12809 /* Determine if the video overlay can be used */ 12810 if(!pSiS->NoXvideo) { 12811 12812 int clklimit1=0, clklimit2=0, clklimitg=0; 12813 Bool OverlayHandled = FALSE; 12814 12815 inSISIDXREG(SISSR,0x2b,sr2b); 12816 inSISIDXREG(SISSR,0x2c,sr2c); 12817 myclock1 = myclock2 = SiSGetClockFromRegs(sr2b, sr2c); 12818 inSISIDXREG(SISSR,0x06,tmpreg); 12819 switch((tmpreg & 0x1c) >> 2) { 12820 case 0: mycoldepth1 = 1; break; 12821 case 1: 12822 case 2: mycoldepth1 = 2; break; 12823 default: mycoldepth1 = 4; 12824 } 12825 mycoldepth2 = mycoldepth1; 12826 12827 if((!IsInSlaveMode) && (pSiS->VBFlags & CRT2_ENABLE)) { 12828 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 12829 inSISIDXREG(SISPART4,0x0a,sr2b); 12830 inSISIDXREG(SISPART4,0x0b,sr2c); 12831 } else { 12832 inSISIDXREG(SISSR,0x2e,sr2b); 12833 inSISIDXREG(SISSR,0x2f,sr2c); 12834 } 12835 myclock2 = SiSGetClockFromRegs(sr2b, sr2c); 12836 inSISIDXREG(SISPART1,0x00,tmpreg); 12837 tmpreg &= 0x0f; 12838 switch(tmpreg) { 12839 case 8: mycoldepth2 = 1; break; 12840 case 4: 12841 case 2: mycoldepth2 = 2; break; 12842 default: mycoldepth2 = 4; 12843 } 12844 } 12845 12846 switch(pSiS->ChipType) { 12847 12848 case SIS_300: 12849 case SIS_540: 12850 case SIS_630: 12851 case SIS_730: 12852 clklimit1 = clklimit2 = clklimitg = 150; 12853 break; 12854 12855 case SIS_550: 12856 case SIS_650: 12857 case SIS_740: 12858 clklimit1 = clklimit2 = 175; /* verified for 65x */ 12859 clklimitg = 166; /* ? */ 12860 break; 12861 12862 case SIS_661: 12863 case SIS_741: 12864 clklimit1 = clklimit2 = 190; /* ? */ 12865 clklimitg = 180; /* ? */ 12866 break; 12867 12868 case SIS_760: 12869 case SIS_761: 12870 clklimit1 = clklimit2 = 190; /* ? */ 12871 if(pSiS->ChipFlags & SiSCF_760LFB) { /* LFB only or hybrid */ 12872 clklimit1 = clklimit2 = 220; /* ? */ 12873 } 12874 clklimitg = 200; /* ? */ 12875 12876 if(pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORT760OO) { /* UMA only */ 12877 12878 Bool OnlyOne = FALSE, NoOverlay = FALSE; 12879 int dotclocksum = 0; 12880 12881 if(pSiS->VBFlags & DISPTYPE_CRT1) dotclocksum += myclock1; 12882 if((!IsInSlaveMode) && (pSiS->VBFlags & CRT2_ENABLE)) dotclocksum += myclock2; 12883 12884 /* TODO: Find out under what circumstances only one 12885 * overlay is usable in UMA-only mode. 12886 * This is not entirely accurate; the overlay 12887 * scaler also requires some time, so even though 12888 * the dotclocks are below these values, some 12889 * distortions in the overlay may occure. 12890 * Solution: Don't use a 760 with shared memory. 12891 */ 12892 if( (pSiS->VBFlags & DISPTYPE_CRT1) && 12893 (pSiS->VBFlags & CRT2_ENABLE) && 12894 (mycoldepth1 != mycoldepth2) ) { 12895 12896 /* 0. If coldepths are different (only possible in dual head mode), 12897 * I have no idea to calculate the limits; hence, allow only one 12898 * overlay in all cases. 12899 */ 12900 OnlyOne = TRUE; 12901 12902 } else if(pSiS->MemClock < 150000) { 12903 12904 /* 1. MCLK <150: If someone seriously considers using such 12905 * slow RAM, so be it. Only one overlay in call cases. 12906 */ 12907 OnlyOne = TRUE; 12908 12909 } else if(pSiS->MemClock < 170000) { 12910 12911 /* 2. MCLK 166 */ 12912 switch(pSiS->CurrentLayout.bitsPerPixel) { 12913 case 32: if(dotclocksum > 133) OnlyOne = TRUE; /* One overlay; verified */ 12914 if(dotclocksum > 180) NoOverlay = TRUE; /* No overlay; verified */ 12915 break; 12916 case 16: if(dotclocksum > 175) OnlyOne = TRUE; /* One overlay; verified */ 12917 if(dotclocksum > 260) NoOverlay = TRUE;; /* No overlay; FIXME */ 12918 break; 12919 } 12920 12921 } else if(pSiS->MemClock < 210000) { 12922 12923 /* 3. MCLK 200 */ 12924 switch(pSiS->CurrentLayout.bitsPerPixel) { 12925 case 32: if(dotclocksum > 160) OnlyOne = TRUE; /* One overlay; FIXME */ 12926 if(dotclocksum > 216) NoOverlay = TRUE;; /* No overlay; FIXME */ 12927 break; 12928 case 16: if(dotclocksum > 210) OnlyOne = TRUE; /* One overlay; FIXME */ 12929 if(dotclocksum > 312) NoOverlay = TRUE;; /* No overlay; FIXME */ 12930 break; 12931 } 12932 12933 } 12934 12935 if(OnlyOne || NoOverlay) { 12936 12937 ULong tmpflags = 0; 12938 12939 if(!NoOverlay) { 12940 if(myclock1 <= clklimit1) tmpflags |= MISC_CRT1OVERLAY; 12941 if(myclock2 <= clklimit2) tmpflags |= MISC_CRT2OVERLAY; 12942 if(myclock1 <= clklimitg) tmpflags |= MISC_CRT1OVERLAYGAMMA; 12943 pSiS->MiscFlags |= tmpflags; 12944 } 12945 pSiS->MiscFlags |= MISC_SIS760ONEOVERLAY; 12946 pSiS->SiS_SD2_Flags |= SiS_SD2_SIS760ONEOVL; 12947#ifdef SISDUALHEAD 12948 SiS_SetDHFlags(pSiS, (tmpflags | MISC_SIS760ONEOVERLAY), SiS_SD2_SIS760ONEOVL); 12949#endif 12950 OverlayHandled = TRUE; 12951 } 12952 12953 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 12954 "SiS76x/UMA: %s video overlay(s) available in current mode\n", 12955 NoOverlay ? "no" : ((pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) ? "one" : "two")); 12956 12957#ifdef TWDEBUG 12958 xf86DrvMsg(0, 0, "SiS760: Memclock %d, c1 %d/%d c2 %d/%d, sum %d / %x\n", 12959 pSiS->MemClock, myclock1, mycoldepth1, 12960 myclock2, mycoldepth2, dotclocksum, pSiS->SiS_SD2_Flags); 12961#endif 12962 } 12963 break; 12964 12965 case SIS_660: 12966 clklimit1 = clklimit2 = 200; /* ? */ 12967 if(pSiS->ChipFlags & SiSCF_760LFB) { /* LFB only */ 12968 clklimit1 = clklimit2 = 220; 12969 } 12970 clklimitg = 200; /* ? */ 12971 break; 12972 12973 case SIS_315H: 12974 case SIS_315: 12975 case SIS_315PRO: 12976 case SIS_330: 12977 clklimit1 = clklimit2 = 180; /* ? */ 12978 clklimitg = 166; /* ? */ 12979 break; 12980 12981 case SIS_340: /* ? */ 12982 case XGI_20: 12983 case XGI_40: 12984 clklimit1 = clklimit2 = 240; /* ? */ 12985 clklimitg = 200; /* ? */ 12986 break; 12987 } 12988 12989 if(!OverlayHandled) { 12990 ULong tmpflags = 0; 12991 if(myclock1 <= clklimit1) tmpflags |= MISC_CRT1OVERLAY; 12992 if(myclock2 <= clklimit2) tmpflags |= MISC_CRT2OVERLAY; 12993 if(myclock1 <= clklimitg) tmpflags |= MISC_CRT1OVERLAYGAMMA; 12994 pSiS->MiscFlags |= tmpflags; 12995#ifdef SISDUALHEAD 12996 SiS_SetDHFlags(pSiS, tmpflags, 0); 12997#endif 12998 if(!(pSiS->MiscFlags & MISC_CRT1OVERLAY)) { 12999#ifdef SISDUALHEAD 13000 if((!pSiS->DualHeadMode) || (pSiS->SecondHead)) 13001#endif 13002 xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, 3, 13003 "Current dotclock (%dMhz) too high for video overlay on CRT1\n", 13004 myclock1); 13005 } 13006 if((pSiS->VBFlags & CRT2_ENABLE) && (!(pSiS->MiscFlags & MISC_CRT2OVERLAY))) { 13007#ifdef SISDUALHEAD 13008 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) 13009#endif 13010 xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, 3, 13011 "Current dotclock (%dMhz) too high for video overlay on CRT2\n", 13012 myclock2); 13013 } 13014 } 13015 13016 } 13017 13018 /* Determine if the Panel Link scaler is active */ 13019 13020 if(pSiS->VBFlags & (CRT2_LCD | CRT1_LCDA)) { 13021 ULong tmpflags = 0; 13022 if(pSiS->VGAEngine == SIS_300_VGA) { 13023 if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) { 13024 inSISIDXREG(SISPART1,0x1e,tmpreg); 13025 tmpreg &= 0x3f; 13026 if(tmpreg) tmpflags |= MISC_PANELLINKSCALER; 13027 } 13028 } else { 13029 if((pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) || (pSiS->VBFlags & CRT1_LCDA)) { 13030 inSISIDXREG(SISPART1,0x35,tmpreg); 13031 tmpreg &= 0x04; 13032 if(!tmpreg) tmpflags |= MISC_PANELLINKSCALER; 13033 } 13034 } 13035 pSiS->MiscFlags |= tmpflags; 13036#ifdef SISDUALHEAD 13037 SiS_SetDHFlags(pSiS, tmpflags, 0); 13038#endif 13039 } 13040 13041 /* Determine if STN is active */ 13042 if(pSiS->ChipType == SIS_550) { 13043 if((pSiS->VBFlags & CRT2_LCD) && (pSiS->FSTN || pSiS->DSTN)) { 13044 inSISIDXREG(SISCR,0x34,tmpreg); 13045 tmpreg &= 0x7f; 13046 if(tmpreg == 0x5a || tmpreg == 0x5b) { 13047 pSiS->MiscFlags |= MISC_STNMODE; 13048#ifdef SISDUALHEAD 13049 SiS_SetDHFlags(pSiS, MISC_STNMODE, 0); 13050#endif 13051 } 13052 } 13053 } 13054 13055 /* Determine if our very special TV mode is active */ 13056 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && (pSiS->VBFlags & CRT2_TV) && (!(pSiS->VBFlags & TV_HIVISION))) { 13057 if( ((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR525I)) || 13058 ((!(pSiS->VBFlags & TV_YPBPR)) && (pSiS->VBFlags & (TV_NTSC | TV_PALM))) ) { 13059 inSISIDXREG(SISCR,0x34,tmpreg); 13060 tmpreg &= 0x7f; 13061 if((tmpreg == 0x64) || (tmpreg == 0x4a) || (tmpreg == 0x38)) { 13062 pSiS->MiscFlags |= MISC_TVNTSC1024; 13063#ifdef SISDUALHEAD 13064 SiS_SetDHFlags(pSiS, MISC_TVNTSC1024, 0); 13065#endif 13066 } 13067 } 13068 } 13069 13070 if(pSiS->VGAEngine == SIS_315_VGA) { 13071 int i; 13072#ifdef SISVRAMQ 13073 /* Re-Enable and reset command queue */ 13074 SiSEnableTurboQueue(pScrn); 13075#endif 13076 /* Get HWCursor register contents for backup */ 13077 for(i = 0; i < 16; i++) { 13078 pSiS->HWCursorBackup[i] = SIS_MMIO_IN32(pSiS->IOBase, 0x8500 + (i << 2)); 13079 } 13080 if(pSiS->ChipType >= SIS_330) { 13081 /* Enable HWCursor protection (Y pos as trigger) */ 13082 andSISIDXREG(SISCR, 0x5b, ~0x30); 13083 } 13084 } 13085 13086 /* Re-initialize accelerator engine */ 13087 /* (We are sync'ed here) */ 13088 if(!pSiS->NoAccel) { 13089 if(pSiS->InitAccel) { 13090 (pSiS->InitAccel)(pScrn); 13091 } 13092 } 13093 13094 /* Set display device gamma (for SISCTRL) */ 13095 if(pSiS->VBFlags & CRT1_LCDA) 13096 pSiS->CRT1MonGamma = pSiS->CRT2LCDMonitorGamma; 13097 else 13098 pSiS->CRT1MonGamma = pSiS->CRT1VGAMonitorGamma; 13099 13100 if(pSiS->VBFlags & CRT2_LCD) 13101 pSiS->CRT2MonGamma = pSiS->CRT2LCDMonitorGamma; 13102 else if(pSiS->VBFlags & CRT2_TV) { 13103 if(pSiS->VBFlags & TV_YPBPR) 13104 pSiS->CRT2MonGamma = 2200; /* */ 13105 else if(pSiS->VBFlags & TV_HIVISION) 13106 pSiS->CRT2MonGamma = 2200; /* ? */ 13107 else if(pSiS->VBFlags & TV_NTSC) 13108 pSiS->CRT2MonGamma = 2200; /* NTSC */ 13109 else 13110 pSiS->CRT2MonGamma = 2800; /* All PAL modes? */ 13111 } else if(pSiS->VBFlags & CRT2_VGA) 13112 pSiS->CRT2MonGamma = pSiS->CRT2VGAMonitorGamma; 13113 else 13114 pSiS->CRT2MonGamma = 0; /* Unknown */ 13115 13116 /* Reset XV display properties (such as number of overlays, etc) */ 13117 /* (And copy monitor gamma) */ 13118#ifdef SISDUALHEAD 13119 if(pSiS->DualHeadMode) { 13120 if(pSiSEnt->pScrn_1) { 13121 if(SISPTR(pSiSEnt->pScrn_1)->ResetXvDisplay) { 13122 (SISPTR(pSiSEnt->pScrn_1)->ResetXvDisplay)(pSiSEnt->pScrn_1); 13123 } 13124 SISPTR(pSiSEnt->pScrn_1)->CRT1MonGamma = pSiS->CRT1MonGamma; 13125 SISPTR(pSiSEnt->pScrn_1)->CRT2MonGamma = pSiS->CRT2MonGamma; 13126 } 13127 if(pSiSEnt->pScrn_2) { 13128 if(SISPTR(pSiSEnt->pScrn_2)->ResetXvDisplay) { 13129 (SISPTR(pSiSEnt->pScrn_1)->ResetXvDisplay)(pSiSEnt->pScrn_2); 13130 } 13131 SISPTR(pSiSEnt->pScrn_2)->CRT1MonGamma = pSiS->CRT1MonGamma; 13132 SISPTR(pSiSEnt->pScrn_2)->CRT2MonGamma = pSiS->CRT2MonGamma; 13133 } 13134 } else { 13135#endif 13136 if(pSiS->ResetXvDisplay) { 13137 (pSiS->ResetXvDisplay)(pScrn); 13138 } 13139#ifdef SISDUALHEAD 13140 } 13141#endif 13142 13143 /* Reset XV gamma correction */ 13144 if(pSiS->ResetXvGamma) { 13145 (pSiS->ResetXvGamma)(pScrn); 13146 } 13147 13148 /* Reset various display parameters */ 13149 { 13150 int val = pSiS->siscrt1satgain; 13151#ifdef SISDUALHEAD 13152 if(pSiS->DualHeadMode && pSiSEnt) val = pSiSEnt->siscrt1satgain; 13153#endif 13154 SiS_SetSISCRT1SaturationGain(pScrn, val); 13155 } 13156 13157 /* Apply TV settings given by options 13158 Do this even in DualHeadMode: 13159 - if this is called by SetModeCRT1, CRT2 mode has been reset by SetModeCRT1 13160 - if this is called by SetModeCRT2, CRT2 mode has changed (duh!) 13161 -> Hence, in both cases, the settings must be re-applied. 13162 */ 13163 13164 if(pSiS->VBFlags & CRT2_TV) { 13165 int val; 13166 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 13167 int mychtvlumabandwidthcvbs = pSiS->chtvlumabandwidthcvbs; 13168 int mychtvlumabandwidthsvideo = pSiS->chtvlumabandwidthsvideo; 13169 int mychtvlumaflickerfilter = pSiS->chtvlumaflickerfilter; 13170 int mychtvchromabandwidth = pSiS->chtvchromabandwidth; 13171 int mychtvchromaflickerfilter = pSiS->chtvchromaflickerfilter; 13172 int mychtvcvbscolor = pSiS->chtvcvbscolor; 13173 int mychtvtextenhance = pSiS->chtvtextenhance; 13174 int mychtvcontrast = pSiS->chtvcontrast; 13175 int mytvxpos = pSiS->tvxpos; 13176 int mytvypos = pSiS->tvypos; 13177#ifdef SISDUALHEAD 13178 if(pSiSEnt && pSiS->DualHeadMode) { 13179 mychtvlumabandwidthcvbs = pSiSEnt->chtvlumabandwidthcvbs; 13180 mychtvlumabandwidthsvideo = pSiSEnt->chtvlumabandwidthsvideo; 13181 mychtvlumaflickerfilter = pSiSEnt->chtvlumaflickerfilter; 13182 mychtvchromabandwidth = pSiSEnt->chtvchromabandwidth; 13183 mychtvchromaflickerfilter = pSiSEnt->chtvchromaflickerfilter; 13184 mychtvcvbscolor = pSiSEnt->chtvcvbscolor; 13185 mychtvtextenhance = pSiSEnt->chtvtextenhance; 13186 mychtvcontrast = pSiSEnt->chtvcontrast; 13187 mytvxpos = pSiSEnt->tvxpos; 13188 mytvypos = pSiSEnt->tvypos; 13189 } 13190#endif 13191 if((val = mychtvlumabandwidthcvbs) != -1) { 13192 SiS_SetCHTVlumabandwidthcvbs(pScrn, val); 13193 } 13194 if((val = mychtvlumabandwidthsvideo) != -1) { 13195 SiS_SetCHTVlumabandwidthsvideo(pScrn, val); 13196 } 13197 if((val = mychtvlumaflickerfilter) != -1) { 13198 SiS_SetCHTVlumaflickerfilter(pScrn, val); 13199 } 13200 if((val = mychtvchromabandwidth) != -1) { 13201 SiS_SetCHTVchromabandwidth(pScrn, val); 13202 } 13203 if((val = mychtvchromaflickerfilter) != -1) { 13204 SiS_SetCHTVchromaflickerfilter(pScrn, val); 13205 } 13206 if((val = mychtvcvbscolor) != -1) { 13207 SiS_SetCHTVcvbscolor(pScrn, val); 13208 } 13209 if((val = mychtvtextenhance) != -1) { 13210 SiS_SetCHTVtextenhance(pScrn, val); 13211 } 13212 if((val = mychtvcontrast) != -1) { 13213 SiS_SetCHTVcontrast(pScrn, val); 13214 } 13215 /* Backup default TV position registers */ 13216 switch(pSiS->ChrontelType) { 13217 case CHRONTEL_700x: 13218 pSiS->tvx = SiS_GetCH700x(pSiS->SiS_Pr, 0x0a); 13219 pSiS->tvx |= (((SiS_GetCH700x(pSiS->SiS_Pr, 0x08) & 0x02) >> 1) << 8); 13220 pSiS->tvy = SiS_GetCH700x(pSiS->SiS_Pr, 0x0b); 13221 pSiS->tvy |= ((SiS_GetCH700x(pSiS->SiS_Pr, 0x08) & 0x01) << 8); 13222#ifdef SISDUALHEAD 13223 if(pSiSEnt) { 13224 pSiSEnt->tvx = pSiS->tvx; 13225 pSiSEnt->tvy = pSiS->tvy; 13226 } 13227#endif 13228 break; 13229 case CHRONTEL_701x: 13230 /* Not supported by hardware */ 13231 break; 13232 } 13233 if((val = mytvxpos) != 0) { 13234 SiS_SetTVxposoffset(pScrn, val); 13235 } 13236 if((val = mytvypos) != 0) { 13237 SiS_SetTVyposoffset(pScrn, val); 13238 } 13239 } 13240 if(pSiS->VBFlags2 & VB2_301) { 13241 int mysistvedgeenhance = pSiS->sistvedgeenhance; 13242#ifdef SISDUALHEAD 13243 if(pSiSEnt && pSiS->DualHeadMode) { 13244 mysistvedgeenhance = pSiSEnt->sistvedgeenhance; 13245 } 13246#endif 13247 if((val = mysistvedgeenhance) != -1) { 13248 SiS_SetSISTVedgeenhance(pScrn, val); 13249 } 13250 } 13251 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 13252 int mysistvantiflicker = pSiS->sistvantiflicker; 13253 int mysistvsaturation = pSiS->sistvsaturation; 13254 int mysistvcolcalibf = pSiS->sistvcolcalibf; 13255 int mysistvcolcalibc = pSiS->sistvcolcalibc; 13256 int mysistvcfilter = pSiS->sistvcfilter; 13257 int mysistvyfilter = pSiS->sistvyfilter; 13258 int mytvxpos = pSiS->tvxpos; 13259 int mytvypos = pSiS->tvypos; 13260 int mytvxscale = pSiS->tvxscale; 13261 int mytvyscale = pSiS->tvyscale; 13262 int i; 13263 ULong cbase; 13264 UChar ctemp; 13265#ifdef SISDUALHEAD 13266 if(pSiSEnt && pSiS->DualHeadMode) { 13267 mysistvantiflicker = pSiSEnt->sistvantiflicker; 13268 mysistvsaturation = pSiSEnt->sistvsaturation; 13269 mysistvcolcalibf = pSiSEnt->sistvcolcalibf; 13270 mysistvcolcalibc = pSiSEnt->sistvcolcalibc; 13271 mysistvcfilter = pSiSEnt->sistvcfilter; 13272 mysistvyfilter = pSiSEnt->sistvyfilter; 13273 mytvxpos = pSiSEnt->tvxpos; 13274 mytvypos = pSiSEnt->tvypos; 13275 mytvxscale = pSiSEnt->tvxscale; 13276 mytvyscale = pSiSEnt->tvyscale; 13277 } 13278#endif 13279 /* Backup default TV position, scale and colcalib registers */ 13280 inSISIDXREG(SISPART2,0x1f,pSiS->p2_1f); 13281 inSISIDXREG(SISPART2,0x20,pSiS->p2_20); 13282 inSISIDXREG(SISPART2,0x2b,pSiS->p2_2b); 13283 inSISIDXREG(SISPART2,0x42,pSiS->p2_42); 13284 inSISIDXREG(SISPART2,0x43,pSiS->p2_43); 13285 inSISIDXREG(SISPART2,0x01,pSiS->p2_01); 13286 inSISIDXREG(SISPART2,0x02,pSiS->p2_02); 13287 inSISIDXREG(SISPART2,0x44,pSiS->p2_44); 13288 inSISIDXREG(SISPART2,0x45,pSiS->p2_45); 13289 if(!(pSiS->VBFlags2 & VB2_301)) { 13290 inSISIDXREG(SISPART2,0x46,pSiS->p2_46); 13291 } else { 13292 pSiS->p2_46 = 0; 13293 } 13294 inSISIDXREG(SISPART2,0x0a,pSiS->p2_0a); 13295 inSISIDXREG(SISPART2,0x31,cbase); 13296 cbase = (cbase & 0x7f) << 8; 13297 inSISIDXREG(SISPART2,0x32,ctemp); 13298 cbase = (cbase | ctemp) << 8; 13299 inSISIDXREG(SISPART2,0x33,ctemp); 13300 cbase = (cbase | ctemp) << 8; 13301 inSISIDXREG(SISPART2,0x34,ctemp); 13302 pSiS->sistvccbase = (cbase | ctemp); 13303 inSISIDXREG(SISPART2,0x35,pSiS->p2_35); 13304 inSISIDXREG(SISPART2,0x36,pSiS->p2_36); 13305 inSISIDXREG(SISPART2,0x37,pSiS->p2_37); 13306 inSISIDXREG(SISPART2,0x38,pSiS->p2_38); 13307 if(!(pSiS->VBFlags2 & VB2_301)) { 13308 inSISIDXREG(SISPART2,0x47,pSiS->p2_47); 13309 inSISIDXREG(SISPART2,0x48,pSiS->p2_48); 13310 inSISIDXREG(SISPART2,0x49,pSiS->p2_49); 13311 inSISIDXREG(SISPART2,0x4a,pSiS->p2_4a); 13312 } 13313 inSISIDXREG(SISPART2,0x2f,pSiS->p2_2f); 13314 inSISIDXREG(SISPART2,0x30,pSiS->p2_30); 13315 for(i=0; i<9; i++) { 13316 inSISIDXREG(SISPART1,SiSScalingP1Regs[i],pSiS->scalingp1[i]); 13317 } 13318 for(i=0; i<9; i++) { 13319 inSISIDXREG(SISPART4,SiSScalingP4Regs[i],pSiS->scalingp4[i]); 13320 } 13321 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 13322 for(i=0; i<64; i++) { 13323 inSISIDXREG(SISPART2,(0xc0 + i),pSiS->scalingp2[i]); 13324 } 13325 } 13326#ifdef SISDUALHEAD 13327 if(pSiSEnt) { 13328 pSiSEnt->p2_1f = pSiS->p2_1f; pSiSEnt->p2_20 = pSiS->p2_20; 13329 pSiSEnt->p2_42 = pSiS->p2_42; pSiSEnt->p2_43 = pSiS->p2_43; 13330 pSiSEnt->p2_2b = pSiS->p2_2b; 13331 pSiSEnt->p2_01 = pSiS->p2_01; pSiSEnt->p2_02 = pSiS->p2_02; 13332 pSiSEnt->p2_44 = pSiS->p2_44; pSiSEnt->p2_45 = pSiS->p2_45; 13333 pSiSEnt->p2_46 = pSiS->p2_46; pSiSEnt->p2_0a = pSiS->p2_0a; 13334 pSiSEnt->sistvccbase = pSiS->sistvccbase; 13335 pSiSEnt->p2_35 = pSiS->p2_35; pSiSEnt->p2_36 = pSiS->p2_36; 13336 pSiSEnt->p2_37 = pSiS->p2_37; pSiSEnt->p2_38 = pSiS->p2_38; 13337 pSiSEnt->p2_48 = pSiS->p2_48; pSiSEnt->p2_49 = pSiS->p2_49; 13338 pSiSEnt->p2_4a = pSiS->p2_4a; pSiSEnt->p2_2f = pSiS->p2_2f; 13339 pSiSEnt->p2_30 = pSiS->p2_30; pSiSEnt->p2_47 = pSiS->p2_47; 13340 for(i=0; i<9; i++) { 13341 pSiSEnt->scalingp1[i] = pSiS->scalingp1[i]; 13342 } 13343 for(i=0; i<9; i++) { 13344 pSiSEnt->scalingp4[i] = pSiS->scalingp4[i]; 13345 } 13346 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 13347 for(i=0; i<64; i++) { 13348 pSiSEnt->scalingp2[i] = pSiS->scalingp2[i]; 13349 } 13350 } 13351 } 13352#endif 13353 if((val = mysistvantiflicker) != -1) { 13354 SiS_SetSISTVantiflicker(pScrn, val); 13355 } 13356 if((val = mysistvsaturation) != -1) { 13357 SiS_SetSISTVsaturation(pScrn, val); 13358 } 13359 if((val = mysistvcfilter) != -1) { 13360 SiS_SetSISTVcfilter(pScrn, val); 13361 } 13362 if((val = mysistvyfilter) != 1) { 13363 SiS_SetSISTVyfilter(pScrn, val); 13364 } 13365 if((val = mysistvcolcalibc) != 0) { 13366 SiS_SetSISTVcolcalib(pScrn, val, TRUE); 13367 } 13368 if((val = mysistvcolcalibf) != 0) { 13369 SiS_SetSISTVcolcalib(pScrn, val, FALSE); 13370 } 13371 if((val = mytvxpos) != 0) { 13372 SiS_SetTVxposoffset(pScrn, val); 13373 } 13374 if((val = mytvypos) != 0) { 13375 SiS_SetTVyposoffset(pScrn, val); 13376 } 13377 if((val = mytvxscale) != 0) { 13378 SiS_SetTVxscale(pScrn, val); 13379 } 13380 if((val = mytvyscale) != 0) { 13381 SiS_SetTVyscale(pScrn, val); 13382 } 13383 } 13384 } 13385 13386} 13387 13388/* Post-set SiS6326 TV registers */ 13389static void 13390SiS6326PostSetMode(ScrnInfoPtr pScrn, SISRegPtr sisReg) 13391{ 13392 SISPtr pSiS = SISPTR(pScrn); 13393 UChar tmp; 13394 int val; 13395 13396 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 13397 13398#ifdef UNLOCK_ALWAYS 13399 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 13400#endif 13401 13402 /* Backup default TV position registers */ 13403 pSiS->tvx1 = SiS6326GetTVReg(pScrn,0x3a); 13404 pSiS->tvx1 |= ((SiS6326GetTVReg(pScrn,0x3c) & 0x0f) << 8); 13405 pSiS->tvx2 = SiS6326GetTVReg(pScrn,0x26); 13406 pSiS->tvx2 |= ((SiS6326GetTVReg(pScrn,0x27) & 0xf0) << 4); 13407 pSiS->tvx3 = SiS6326GetTVReg(pScrn,0x12); 13408 pSiS->tvx3 |= ((SiS6326GetTVReg(pScrn,0x13) & 0xC0) << 2); 13409 pSiS->tvy1 = SiS6326GetTVReg(pScrn,0x11); 13410 pSiS->tvy1 |= ((SiS6326GetTVReg(pScrn,0x13) & 0x30) << 4); 13411 13412 /* Handle TVPosOffset options (BEFORE switching on TV) */ 13413 if((val = pSiS->tvxpos) != 0) { 13414 SiS_SetTVxposoffset(pScrn, val); 13415 } 13416 if((val = pSiS->tvypos) != 0) { 13417 SiS_SetTVyposoffset(pScrn, val); 13418 } 13419 13420 /* Switch on TV output. This is rather complicated, but 13421 * if we don't do it, TV output will flicker terribly. 13422 */ 13423 if(pSiS->SiS6326Flags & SIS6326_TVON) { 13424 orSISIDXREG(SISSR, 0x01, 0x20); 13425 tmp = SiS6326GetTVReg(pScrn,0x00); 13426 tmp &= ~0x04; 13427 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 13428 SiS6326SetTVReg(pScrn,0x00,tmp); 13429 for(val=0; val < 2; val++) { 13430 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 13431 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 13432 } 13433 SiS6326SetTVReg(pScrn, 0x00, sisReg->sis6326tv[0]); 13434 tmp = inSISREG(SISINPSTAT); 13435 outSISREG(SISAR, 0x20); 13436 tmp = inSISREG(SISINPSTAT); 13437 while(inSISREG(SISINPSTAT) & 0x01); 13438 while(!(inSISREG(SISINPSTAT) & 0x01)); 13439 andSISIDXREG(SISSR, 0x01, ~0x20); 13440 for(val=0; val < 10; val++) { 13441 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 13442 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 13443 } 13444 andSISIDXREG(SISSR, 0x01, ~0x20); 13445 } 13446 13447 tmp = SiS6326GetTVReg(pScrn,0x00); 13448 if(!(tmp & 0x04)) return; 13449 13450 /* Apply TV settings given by options */ 13451 if((val = pSiS->sistvantiflicker) != -1) { 13452 SiS_SetSIS6326TVantiflicker(pScrn, val); 13453 } 13454 if((val = pSiS->sis6326enableyfilter) != -1) { 13455 SiS_SetSIS6326TVenableyfilter(pScrn, val); 13456 } 13457 if((val = pSiS->sis6326yfilterstrong) != -1) { 13458 SiS_SetSIS6326TVyfilterstrong(pScrn, val); 13459 } 13460 13461} 13462 13463/* Check if video bridge is in slave mode */ 13464Bool 13465SiSBridgeIsInSlaveMode(ScrnInfoPtr pScrn) 13466{ 13467 SISPtr pSiS = SISPTR(pScrn); 13468 UChar usScrP1_00; 13469 13470 if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return FALSE; 13471 13472 inSISIDXREG(SISPART1,0x00,usScrP1_00); 13473 if( ((pSiS->VGAEngine == SIS_300_VGA) && (usScrP1_00 & 0xa0) == 0x20) || 13474 ((pSiS->VGAEngine == SIS_315_VGA) && (usScrP1_00 & 0x50) == 0x10) ) { 13475 return TRUE; 13476 } 13477 13478 return FALSE; 13479} 13480 13481/* Build a list of the VESA modes the BIOS reports as valid */ 13482static void 13483SiSBuildVesaModeList(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe) 13484{ 13485 SISPtr pSiS = SISPTR(pScrn); 13486 int i = 0; 13487 13488 while(vbe->VideoModePtr[i] != 0xffff) { 13489 sisModeInfoPtr m; 13490 VbeModeInfoBlock *mode; 13491 int id = vbe->VideoModePtr[i++]; 13492 13493 if((mode = VBEGetModeInfo(pVbe, id)) == NULL) { 13494 continue; 13495 } 13496 13497 m = xnfcalloc(sizeof(sisModeInfoRec), 1); 13498 if(!m) { 13499 VBEFreeModeInfo(mode); 13500 continue; 13501 } 13502 m->width = mode->XResolution; 13503 m->height = mode->YResolution; 13504 m->bpp = mode->BitsPerPixel; 13505 m->n = id; 13506 m->next = pSiS->SISVESAModeList; 13507 13508 pSiS->SISVESAModeList = m; 13509 13510 VBEFreeModeInfo(mode); 13511 13512 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 13513 "VESA BIOS supports mode number 0x%x: %ix%i (%i bpp)\n", 13514 m->n, m->width, m->height, m->bpp); 13515 } 13516} 13517 13518/* Get VESA mode number from given resolution/depth */ 13519static UShort 13520SiSCalcVESAModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode) 13521{ 13522 SISPtr pSiS = SISPTR(pScrn); 13523 sisModeInfoPtr m = pSiS->SISVESAModeList; 13524 UShort i = (pScrn->bitsPerPixel+7)/8 - 1; 13525 UShort ModeNumber = 0; 13526 int j; 13527 13528 while(m) { 13529 if( (pScrn->bitsPerPixel == m->bpp) && 13530 (mode->HDisplay == m->width) && 13531 (mode->VDisplay == m->height) ) 13532 return m->n; 13533 m = m->next; 13534 } 13535 13536 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 13537 "No valid VESA BIOS mode found for %dx%d (%d bpp)\n", 13538 mode->HDisplay, mode->VDisplay, pScrn->bitsPerPixel); 13539 13540 if(!pSiS->ROM661New) { /* VESA numbers changed! */ 13541 j = 0; 13542 while(VESAModeIndices[j] != 9999) { 13543 if( (mode->HDisplay == VESAModeIndices[j]) && 13544 (mode->VDisplay == VESAModeIndices[j+1]) ) { 13545 ModeNumber = VESAModeIndices[j + 2 + i]; 13546 break; 13547 } 13548 j += 6; 13549 } 13550 13551 if(!ModeNumber) { 13552 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 13553 "No valid mode found for %dx%dx%d in built-in table either.\n", 13554 mode->HDisplay, mode->VDisplay, pScrn->bitsPerPixel); 13555 } 13556 } 13557 13558 return(ModeNumber); 13559} 13560 13561UShort 13562SiS_GetModeNumber(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned int VBFlags) 13563{ 13564 SISPtr pSiS = SISPTR(pScrn); 13565 UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; 13566 BOOLEAN FSTN = pSiS->FSTN ? TRUE : FALSE; 13567 13568#ifdef SISDUALHEAD 13569 if(pSiS->DualHeadMode && pSiS->SecondHead) FSTN = FALSE; 13570#endif 13571 13572 return(SiS_GetModeID(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, 13573 i, FSTN, pSiS->LCDwidth, pSiS->LCDheight)); 13574} 13575 13576static Bool 13577SiSValidLCDUserMode(SISPtr pSiS, unsigned int VBFlags, DisplayModePtr mode, Bool isforlcda) 13578{ 13579 if(mode->Flags & V_INTERLACE) return FALSE; 13580 13581 if(mode->HDisplay > 2048) return FALSE; 13582 if(mode->VDisplay > 1536) return FALSE; 13583 13584 if(pSiS->VBFlags2 & VB2_LCD162MHZBRIDGE) { 13585 if(mode->Clock > 162500) return FALSE; 13586#ifdef VB_FORBID_CRT2LCD_OVER_1600 13587 if(!isforlcda) { 13588 if(mode->HDisplay > 1600) return FALSE; 13589 } 13590#endif 13591 } else { /* 301, 301B, 302B (no LCDA!) */ 13592 if(mode->Clock > 130000) return FALSE; 13593 if(mode->Clock > 111000) { 13594 xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING, 13595 "WARNING: Mode clock beyond video bridge specs (%dMHz). Hardware damage might occure.\n", 13596 mode->Clock / 1000); 13597 } 13598 if(mode->HDisplay > 1600) return FALSE; 13599 if(mode->VDisplay > 1024) return FALSE; 13600 } 13601 13602 return TRUE; 13603} 13604 13605static Bool 13606SiSValidVGA2UserMode(SISPtr pSiS, unsigned int VBFlags, DisplayModePtr mode) 13607{ 13608 if(mode->Flags & V_INTERLACE) return FALSE; 13609 13610 if(mode->HDisplay > 2048) return FALSE; 13611 if(mode->VDisplay > 1536) return FALSE; 13612 13613 if(pSiS->VBFlags2 & VB2_RAMDAC202MHZBRIDGE) { 13614 if(mode->Clock > 203000) return FALSE; 13615 } else if(pSiS->VBFlags2 & VB2_30xBLV) { 13616 if(mode->Clock > 162500) return FALSE; 13617 } else { 13618 if(mode->Clock > 135500) return FALSE; 13619 } 13620 13621 return TRUE; 13622} 13623 13624UShort 13625SiS_CheckModeCRT1(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned int VBFlags, Bool havecustommodes) 13626{ 13627 SISPtr pSiS = SISPTR(pScrn); 13628 UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; 13629 int j; 13630 13631 if(!(VBFlags & CRT1_LCDA)) { 13632 13633 if((havecustommodes) && (!(mode->type & M_T_DEFAULT))) { 13634 return 0xfe; 13635 } 13636 13637 } else if(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE) { 13638 13639 if(pSiS->ChipType < SIS_661) { /* < 661 only? */ 13640 if(!(mode->type & M_T_DEFAULT)) { 13641 if(mode->HTotal > 2055) return 0; 13642 /* (Default mode will be caught in mode switching code) */ 13643 } 13644 } 13645 13646 if(pSiS->SiS_Pr->CP_HaveCustomData) { 13647 for(j=0; j<7; j++) { 13648 if((pSiS->SiS_Pr->CP_DataValid[j]) && 13649 (mode->HDisplay == pSiS->SiS_Pr->CP_HDisplay[j]) && 13650 (mode->VDisplay == pSiS->SiS_Pr->CP_VDisplay[j]) && 13651 (mode->type & M_T_BUILTIN)) 13652 return 0xfe; 13653 } 13654 } 13655 13656 if((pSiS->AddedPlasmaModes) && (mode->type & M_T_BUILTIN)) 13657 return 0xfe; 13658 13659 if((havecustommodes) && 13660 (pSiS->LCDwidth) && /* = test if LCD present */ 13661 (!(mode->type & M_T_DEFAULT)) && 13662 (SiSValidLCDUserMode(pSiS, VBFlags, mode, TRUE))) 13663 return 0xfe; 13664 13665 if((mode->HDisplay > pSiS->LCDwidth) || 13666 (mode->VDisplay > pSiS->LCDheight)) { 13667 return 0; 13668 } 13669 13670 } else { 13671 13672 if((mode->HDisplay > pSiS->LCDwidth) || 13673 (mode->VDisplay > pSiS->LCDheight)) { 13674 return 0; 13675 } 13676 13677 } 13678 13679 return(SiS_GetModeID(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, 13680 i, pSiS->FSTN, pSiS->LCDwidth, pSiS->LCDheight)); 13681} 13682 13683UShort 13684SiS_CheckModeCRT2(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned int VBFlags, Bool havecustommodes) 13685{ 13686 SISPtr pSiS = SISPTR(pScrn); 13687 UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; 13688 UShort ModeIndex = 0; 13689 int j; 13690 13691#ifdef TWDEBUG 13692 xf86DrvMsg(0, X_INFO, "Inside CheckCalcModeIndex (VBFlags %lx, mode %dx%d)\n", 13693 VBFlags,mode->HDisplay, mode->VDisplay); 13694#endif 13695 13696 if(VBFlags & CRT2_LCD) { /* CRT2 is LCD */ 13697 13698 if((pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && (!(pSiS->VBFlags2 & VB2_30xBDH))) { 13699 13700 if(pSiS->SiS_Pr->CP_HaveCustomData) { 13701 for(j=0; j<7; j++) { 13702 if((pSiS->SiS_Pr->CP_DataValid[j]) && 13703 (mode->HDisplay == pSiS->SiS_Pr->CP_HDisplay[j]) && 13704 (mode->VDisplay == pSiS->SiS_Pr->CP_VDisplay[j]) && 13705#ifdef VB_FORBID_CRT2LCD_OVER_1600 13706 (mode->HDisplay <= 1600) && 13707#endif 13708 (mode->type & M_T_BUILTIN)) 13709 return 0xfe; 13710 } 13711 } 13712 13713 /* All plasma modes have HDisplay <= 1600 */ 13714 if((pSiS->AddedPlasmaModes) && (mode->type & M_T_BUILTIN)) 13715 return 0xfe; 13716 13717 if((havecustommodes) && 13718 (pSiS->LCDwidth) && /* = test if LCD present */ 13719 (!(mode->type & M_T_DEFAULT)) && 13720 (SiSValidLCDUserMode(pSiS, VBFlags, mode, FALSE))) 13721 return 0xfe; 13722 13723 } 13724 13725 if( ((mode->HDisplay <= pSiS->LCDwidth) && 13726 (mode->VDisplay <= pSiS->LCDheight)) || 13727 ((pSiS->SiS_Pr->SiS_CustomT == CUT_PANEL848) && 13728 (((mode->HDisplay == 1360) && (mode->HDisplay == 768)) || 13729 ((mode->HDisplay == 1024) && (mode->HDisplay == 768)) || 13730 ((mode->HDisplay == 800) && (mode->HDisplay == 600)))) || 13731 ((pSiS->SiS_Pr->SiS_CustomT == CUT_PANEL856) && 13732 (((mode->HDisplay == 1024) && (mode->HDisplay == 768)) || 13733 ((mode->HDisplay == 800) && (mode->HDisplay == 600)))) ) { 13734 13735 ModeIndex = SiS_GetModeID_LCD(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, i, 13736 pSiS->FSTN, pSiS->SiS_Pr->SiS_CustomT, pSiS->LCDwidth, pSiS->LCDheight, 13737 pSiS->VBFlags2); 13738 13739 } 13740 13741 } else if(VBFlags & CRT2_TV) { /* CRT2 is TV */ 13742 13743 ModeIndex = SiS_GetModeID_TV(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, i, 13744 pSiS->VBFlags2); 13745 13746 } else if(VBFlags & CRT2_VGA) { /* CRT2 is VGA2 */ 13747 13748 if((pSiS->AddedPlasmaModes) && (mode->type & M_T_BUILTIN)) 13749 return 0xfe; 13750 13751 if((havecustommodes) && 13752 (!(mode->type & M_T_DEFAULT)) && 13753 (SiSValidVGA2UserMode(pSiS, VBFlags, mode))) 13754 return 0xfe; 13755 13756 ModeIndex = SiS_GetModeID_VGA2(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, i, 13757 pSiS->VBFlags2); 13758 13759 } else { /* no CRT2 */ 13760 13761 /* Return a valid mode number */ 13762 ModeIndex = 0xfe; 13763 13764 } 13765 13766 return(ModeIndex); 13767} 13768 13769/* Calculate the vertical refresh rate from a mode */ 13770float 13771SiSCalcVRate(DisplayModePtr mode) 13772{ 13773 float hsync, refresh = 0; 13774 13775 if(mode->HSync > 0.0) 13776 hsync = mode->HSync; 13777 else if(mode->HTotal > 0) 13778 hsync = (float)mode->Clock / (float)mode->HTotal; 13779 else 13780 hsync = 0.0; 13781 13782 if(mode->VTotal > 0) 13783 refresh = hsync * 1000.0 / mode->VTotal; 13784 13785 if(mode->Flags & V_INTERLACE) 13786 refresh *= 2.0; 13787 13788 if(mode->Flags & V_DBLSCAN) 13789 refresh /= 2.0; 13790 13791 if(mode->VScan > 1) 13792 refresh /= mode->VScan; 13793 13794 if(mode->VRefresh > 0.0) 13795 refresh = mode->VRefresh; 13796 13797 if(hsync == 0.0 || refresh == 0.0) return 0.0; 13798 13799 return refresh; 13800} 13801 13802/* Calculate CR33 (rate index) for CRT1. 13803 * Calculation is done using currentmode, therefore it is 13804 * recommended to set VertRefresh and HorizSync to correct 13805 * values in config file. 13806 */ 13807UChar 13808SISSearchCRT1Rate(ScrnInfoPtr pScrn, DisplayModePtr mode) 13809{ 13810 SISPtr pSiS = SISPTR(pScrn); 13811 int i = 0, irefresh; 13812 UShort xres = mode->HDisplay; 13813 UShort yres = mode->VDisplay; 13814 UChar index, defindex; 13815 Bool checksis730 = FALSE; 13816 13817 defindex = (xres == 800 || xres == 1024 || xres == 1280) ? 0x02 : 0x01; 13818 13819 irefresh = (int)SiSCalcVRate(mode); 13820 if(!irefresh) return defindex; 13821 13822 /* SiS730 has troubles on CRT2 if CRT1 is at 32bpp */ 13823 if( (pSiS->ChipType == SIS_730) && 13824 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && 13825 (pSiS->CurrentLayout.bitsPerPixel == 32) ) { 13826#ifdef SISDUALHEAD 13827 if(pSiS->DualHeadMode) { 13828 if(pSiS->SecondHead) { 13829 checksis730 = TRUE; 13830 } 13831 } else 13832#endif 13833 if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE) && (!pSiS->CRT1off)) { 13834 checksis730 = TRUE; 13835 } 13836 } 13837 13838#ifdef TWDEBUG 13839 xf86DrvMsg(0, X_INFO, "Debug: CalcVRate returned %d\n", irefresh); 13840#endif 13841 13842 /* We need the REAL refresh rate here */ 13843 if(mode->Flags & V_INTERLACE) irefresh /= 2; 13844 13845 /* Do not multiply by 2 when DBLSCAN! */ 13846 13847#ifdef TWDEBUG 13848 xf86DrvMsg(0, X_INFO, "Debug: Rate after correction = %d\n", irefresh); 13849#endif 13850 13851 index = 0; 13852 while((sisx_vrate[i].idx != 0) && (sisx_vrate[i].xres <= xres)) { 13853 if((sisx_vrate[i].xres == xres) && (sisx_vrate[i].yres == yres)) { 13854 if((checksis730 == FALSE) || (sisx_vrate[i].SiS730valid32bpp == TRUE)) { 13855 if(sisx_vrate[i].refresh == irefresh) { 13856 index = sisx_vrate[i].idx; 13857 break; 13858 } else if(sisx_vrate[i].refresh > irefresh) { 13859 if((sisx_vrate[i].refresh - irefresh) <= 3) { 13860 index = sisx_vrate[i].idx; 13861 } else if( ((checksis730 == FALSE) || (sisx_vrate[i - 1].SiS730valid32bpp == TRUE)) && 13862 ((irefresh - sisx_vrate[i - 1].refresh) <= 2) && 13863 (sisx_vrate[i].idx != 1) ) { 13864 index = sisx_vrate[i - 1].idx; 13865 } 13866 break; 13867 } else if((irefresh - sisx_vrate[i].refresh) <= 2) { 13868 index = sisx_vrate[i].idx; 13869 break; 13870 } 13871 } 13872 } 13873 i++; 13874 } 13875 13876 if(index > 0) return index; 13877 else return defindex; 13878} 13879 13880void 13881SISWaitRetraceCRT1(ScrnInfoPtr pScrn) 13882{ 13883 SISPtr pSiS = SISPTR(pScrn); 13884 int watchdog; 13885 UChar temp; 13886 13887 inSISIDXREG(SISCR,0x17,temp); 13888 if(!(temp & 0x80)) return; 13889 13890 inSISIDXREG(SISSR,0x1f,temp); 13891 if(temp & 0xc0) return; 13892 13893 watchdog = 65536; 13894 while((inSISREG(SISINPSTAT) & 0x08) && --watchdog); 13895 watchdog = 65536; 13896 while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog); 13897} 13898 13899void 13900SISWaitRetraceCRT2(ScrnInfoPtr pScrn) 13901{ 13902 SISPtr pSiS = SISPTR(pScrn); 13903 int watchdog; 13904 UChar temp, reg; 13905 13906 if(SiSBridgeIsInSlaveMode(pScrn)) { 13907 SISWaitRetraceCRT1(pScrn); 13908 return; 13909 } 13910 13911 switch(pSiS->VGAEngine) { 13912 case SIS_300_VGA: 13913 reg = 0x25; 13914 break; 13915 case SIS_315_VGA: 13916 reg = 0x30; 13917 break; 13918 default: 13919 return; 13920 } 13921 13922 watchdog = 65536; 13923 do { 13924 inSISIDXREG(SISPART1, reg, temp); 13925 if(!(temp & 0x02)) break; 13926 } while(--watchdog); 13927 watchdog = 65536; 13928 do { 13929 inSISIDXREG(SISPART1, reg, temp); 13930 if(temp & 0x02) break; 13931 } while(--watchdog); 13932} 13933 13934static void 13935SISWaitVBRetrace(ScrnInfoPtr pScrn) 13936{ 13937 SISPtr pSiS = SISPTR(pScrn); 13938 13939 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 13940#ifdef SISDUALHEAD 13941 if(pSiS->DualHeadMode) { 13942 if(pSiS->SecondHead) 13943 SISWaitRetraceCRT1(pScrn); 13944 else 13945 SISWaitRetraceCRT2(pScrn); 13946 } else { 13947#endif 13948 if(pSiS->VBFlags & DISPTYPE_DISP1) { 13949 SISWaitRetraceCRT1(pScrn); 13950 } 13951 if(pSiS->VBFlags & DISPTYPE_DISP2) { 13952 if(!(SiSBridgeIsInSlaveMode(pScrn))) { 13953 SISWaitRetraceCRT2(pScrn); 13954 } 13955 } 13956#ifdef SISDUALHEAD 13957 } 13958#endif 13959 } else { 13960 SISWaitRetraceCRT1(pScrn); 13961 } 13962} 13963 13964#define MODEID_OFF 0x449 13965 13966UChar 13967SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, UShort offset, UChar value) 13968{ 13969 UChar ret = 0; 13970#ifdef SIS_USE_BIOS_SCRATCH 13971 UChar *base; 13972#endif 13973 13974 /* For some reasons (like detecting the current display mode), 13975 * we need to read (or write-back) values from the BIOS 13976 * scratch area. This area is only valid for the primary 13977 * graphics card. For the secondary, we just return some 13978 * defaults and ignore requests to write data. As regards 13979 * the display mode: If sisfb is loaded for the secondary 13980 * card, it very probably has set a mode, but in any case 13981 * informed us via its info packet. So this here will not be 13982 * called for mode detection in this case. 13983 */ 13984 13985 switch(offset) { 13986 case 0x489: 13987 ret = 0x11; /* Default VGA Info */ 13988 break; 13989 case MODEID_OFF: 13990 ret = 0x03; /* Default current display mode */ 13991 break; 13992 } 13993 13994#ifdef SIS_USE_BIOS_SCRATCH 13995 if(SISPTR(pScrn)->Primary) { 13996 base = xf86MapVidMem(pScrn->scrnIndex, VIDMEM_MMIO, 0, 0x2000); 13997 if(!base) { 13998 SISErrorLog(pScrn, "(Could not map BIOS scratch area)\n"); 13999 return ret; 14000 } 14001 14002 ret = *(base + offset); 14003 14004 /* value != 0xff means: set register */ 14005 if(value != 0xff) { 14006 *(base + offset) = value; 14007 } 14008 14009 xf86UnMapVidMem(pScrn->scrnIndex, base, 0x2000); 14010 } 14011#endif 14012 return ret; 14013} 14014 14015UChar 14016SiS_GetSetModeID(ScrnInfoPtr pScrn, UChar id) 14017{ 14018 return(SiS_GetSetBIOSScratch(pScrn, MODEID_OFF, id)); 14019} 14020 14021void 14022SiSMemCopyToVideoRam(SISPtr pSiS, UChar *to, UChar *from, int size) 14023{ 14024 if((ULong)to & 15) (*pSiS->SiSFastMemCopy)(to, from, size); 14025 else (*pSiS->SiSFastVidCopy)(to, from, size); 14026} 14027 14028void 14029SiSMemCopyFromVideoRam(SISPtr pSiS, UChar *to, UChar *from, int size) 14030{ 14031 if((ULong)to & 15) (*pSiS->SiSFastMemCopyFrom)(to, from, size); 14032 else (*pSiS->SiSFastVidCopyFrom)(to, from, size); 14033} 14034 14035void 14036sisSaveUnlockExtRegisterLock(SISPtr pSiS, UChar *reg1, UChar *reg2) 14037{ 14038 register UChar val; 14039 ULong mylockcalls; 14040#ifdef TWDEBUG 14041 UChar val1, val2; 14042 int i; 14043#endif 14044 14045 pSiS->lockcalls++; 14046 mylockcalls = pSiS->lockcalls; 14047 14048 /* check if already unlocked */ 14049 inSISIDXREG(SISSR, 0x05, val); 14050 14051 if(val != 0xa1) { 14052 14053 /* save State */ 14054 if(reg1) *reg1 = val; 14055 14056 /* unlock */ 14057 outSISIDXREG(SISSR, 0x05, 0x86); 14058 14059 /* Now check again */ 14060 inSISIDXREG(SISSR, 0x05, val); 14061 14062 if(val != 0xA1) { 14063 14064 xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING, 14065 "Failed to unlock SR registers at relocated i/o ports\n"); 14066 14067#ifdef TWDEBUG 14068 for(i = 0; i <= 0x3f; i++) { 14069 inSISIDXREG(SISSR, i, val1); 14070 inSISIDXREG(0x3c4, i, val2); 14071 xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO, 14072 "SR%02d: RelIO=0x%02x 0x3c4=0x%02x (%ld)\n", 14073 i, val1, val2, mylockcalls); 14074 } 14075#endif 14076 14077 /* Emergency measure: unlock at 0x3c4, and try to enable relocated IO ports */ 14078 switch(pSiS->VGAEngine) { 14079 case SIS_OLD_VGA: 14080 case SIS_530_VGA: 14081 outSISIDXREG(0x3c4, 0x05, 0x86); 14082 andSISIDXREG(0x3c4, 0x33, ~0x20); 14083 break; 14084 case SIS_300_VGA: 14085 case SIS_315_VGA: 14086 outSISIDXREG(0x3c4, 0x05, 0x86); 14087 orSISIDXREG(0x3c4, 0x20, 0x20); 14088 break; 14089 } 14090 outSISIDXREG(SISSR, 0x05, 0x86); 14091 inSISIDXREG(SISSR, 0x05, val); 14092 if(val != 0xa1) { 14093 SISErrorLog(pSiS->pScrn, 14094 "Failed to unlock SR registers (%p, %lx, 0x%02x; %ld)\n", 14095 (void *)pSiS, (ULong)pSiS->RelIO, val, mylockcalls); 14096 /* Now await doom... */ 14097 } 14098 } 14099 } 14100 if((pSiS->VGAEngine == SIS_OLD_VGA) || (pSiS->VGAEngine == SIS_530_VGA)) { 14101 inSISIDXREG(SISCR, 0x80, val); 14102 if(val != 0xa1) { 14103 /* save State */ 14104 if(reg2) *reg2 = val; 14105 outSISIDXREG(SISCR, 0x80, 0x86); 14106 inSISIDXREG(SISCR, 0x80, val); 14107 if(val != 0xA1) { 14108 SISErrorLog(pSiS->pScrn, 14109 "Failed to unlock cr registers (%p, %lx, 0x%02x)\n", 14110 (void *)pSiS, (ULong)pSiS->RelIO, val); 14111 } 14112 } 14113 } 14114} 14115 14116void 14117sisRestoreExtRegisterLock(SISPtr pSiS, UChar reg1, UChar reg2) 14118{ 14119 /* restore lock */ 14120#ifndef UNLOCK_ALWAYS 14121 outSISIDXREG(SISSR, 0x05, reg1 == 0xA1 ? 0x86 : 0x00); 14122 if((pSiS->VGAEngine == SIS_OLD_VGA) || (pSiS->VGAEngine == SIS_530_VGA)) { 14123 outSISIDXREG(SISCR, 0x80, reg2 == 0xA1 ? 0x86 : 0x00); 14124 } 14125#endif 14126} 14127 14128