1/* 2 * SiS driver main code 3 * 4 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1) Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2) Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3) The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Author: Thomas Winischhofer <thomas@winischhofer.net> 29 * - driver entirely rewritten since 2001, only basic structure taken from 30 * old code (except sis_dri.c, sis_shadow.c, sis_accel.c and parts of 31 * sis_dga.c; these were mostly taken over; sis_dri.c was changed for 32 * new versions of the DRI layer) 33 * 34 * This notice covers the entire driver code unless indicated otherwise. 35 * 36 * Formerly based on code which was 37 * Copyright (C) 1998, 1999 by Alan Hourihane, Wigan, England. 38 * Written by: 39 * Alan Hourihane <alanh@fairlite.demon.co.uk>, 40 * Mike Chapman <mike@paranoia.com>, 41 * Juanjo Santamarta <santamarta@ctv.es>, 42 * Mitani Hiroshi <hmitani@drl.mei.co.jp>, 43 * David Thomas <davtom@dream.org.uk>. 44 */ 45 46#ifdef HAVE_CONFIG_H 47#include "config.h" 48#endif 49 50#include "sis.h" 51 52#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 53#include "xf86RAC.h" 54#endif 55#include "dixstruct.h" 56#include "shadowfb.h" 57#include "fb.h" 58#include "micmap.h" 59#include "mipointer.h" 60#include "edid.h" 61 62#define SIS_NEED_inSISREG 63#define SIS_NEED_inSISIDXREG 64#define SIS_NEED_outSISIDXREG 65#define SIS_NEED_orSISIDXREG 66#define SIS_NEED_andSISIDXREG 67#define SIS_NEED_setSISIDXREG 68#define SIS_NEED_outSISREG 69#define SIS_NEED_MYMMIO 70#define SIS_NEED_sisclearvram 71#include "sis_regs.h" 72#include "sis_dac.h" 73 74#include "sis_driver.h" 75 76#include <X11/extensions/xf86dgaproto.h> 77 78#include "globals.h" 79 80#ifdef HAVE_XEXTPROTO_71 81#include <X11/extensions/dpmsconst.h> 82#else 83#define DPMS_SERVER 84#include <X11/extensions/dpms.h> 85#endif 86 87#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 5 88#include <inputstr.h> /* for inputInfo */ 89#endif 90 91 92#ifdef SISDRI 93#include "dri.h" 94#endif 95 96#ifndef DEFAULT_DPI 97#define DEFAULT_DPI 96 98#endif 99 100/* 101 * LookupWindow was removed with video abi 11. 102 */ 103#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 4) 104#ifndef DixGetAttrAccess 105#define DixGetAttrAccess (1<<4) 106#endif 107#endif 108 109#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 2) 110static inline int 111dixLookupWindow(WindowPtr *pWin, XID id, ClientPtr client, Mask access) 112{ 113 *pWin = LookupWindow(id, client); 114 if (!*pWin) 115 return BadWindow; 116 return Success; 117} 118#endif 119 120/* Globals (yes, these ARE really required to be global) */ 121 122#ifdef SISUSEDEVPORT 123int sisdevport = 0; 124#endif 125 126#ifdef SISDUALHEAD 127static int SISEntityIndex = -1; 128#endif 129 130#ifdef SISMERGED 131#ifdef SISXINERAMA 132static Bool SiSnoPanoramiXExtension = TRUE; 133static int SiSXineramaNumScreens = 0; 134static SiSXineramaData *SiSXineramadataPtr = NULL; 135static int SiSXineramaGeneration; 136 137static int SiSProcXineramaQueryVersion(ClientPtr client); 138static int SiSProcXineramaGetState(ClientPtr client); 139static int SiSProcXineramaGetScreenCount(ClientPtr client); 140static int SiSProcXineramaGetScreenSize(ClientPtr client); 141static int SiSProcXineramaIsActive(ClientPtr client); 142static int SiSProcXineramaQueryScreens(ClientPtr client); 143static int SiSSProcXineramaDispatch(ClientPtr client); 144#endif 145#endif 146 147/* 148 * This is intentionally screen-independent. It indicates the binding 149 * choice made in the first PreInit. 150 */ 151static int pix24bpp = 0; 152 153/* 154 * This contains the functions needed by the server after loading the driver 155 * module. It must be supplied, and gets passed back by the SetupProc 156 * function in the dynamic case. In the static case, a reference to this 157 * is compiled in, and this requires that the name of this DriverRec be 158 * an upper-case version of the driver name. 159 */ 160 161#ifdef _X_EXPORT 162_X_EXPORT 163#endif 164DriverRec SIS = { 165 SIS_CURRENT_VERSION, 166 SIS_DRIVER_NAME, 167 SISIdentify, 168 SISProbe, 169 SISAvailableOptions, 170 NULL, 171 0 172#ifdef SIS_HAVE_DRIVER_FUNC 173 , 174 SISDriverFunc 175#endif 176}; 177 178static SymTabRec SISChipsets[] = { 179 { PCI_CHIP_SIS5597, "SIS5597/5598" }, 180 { PCI_CHIP_SIS530, "SIS530/620" }, 181 { PCI_CHIP_SIS6326, "SIS6326/AGP/DVD" }, 182 { PCI_CHIP_SIS300, "SIS300/305" }, 183 { PCI_CHIP_SIS630, "SIS630/730" }, 184 { PCI_CHIP_SIS540, "SIS540" }, 185 { PCI_CHIP_SIS315, "SIS315" }, 186 { PCI_CHIP_SIS315H, "SIS315H" }, 187 { PCI_CHIP_SIS315PRO, "SIS315PRO/E" }, 188 { PCI_CHIP_SIS550, "SIS550" }, 189 { PCI_CHIP_SIS650, "SIS650/M650/651/740" }, 190 { PCI_CHIP_SIS330, "SIS330(Xabre)" }, 191 { PCI_CHIP_SIS660, "SIS660/[M]661[F|M]X/[M]670/[M]741[GX]/[M]760[GX]/[M]761[GX]/[M]770[GX]" }, 192 { PCI_CHIP_SIS340, "SIS340" }, 193 { -1, NULL } 194}; 195 196static PciChipsets SISPciChipsets[] = { 197 { PCI_CHIP_SIS5597, PCI_CHIP_SIS5597, RES_SHARED_VGA }, 198 { PCI_CHIP_SIS530, PCI_CHIP_SIS530, RES_SHARED_VGA }, 199 { PCI_CHIP_SIS6326, PCI_CHIP_SIS6326, RES_SHARED_VGA }, 200 { PCI_CHIP_SIS300, PCI_CHIP_SIS300, RES_SHARED_VGA }, 201 { PCI_CHIP_SIS630, PCI_CHIP_SIS630, RES_SHARED_VGA }, 202 { PCI_CHIP_SIS540, PCI_CHIP_SIS540, RES_SHARED_VGA }, 203 { PCI_CHIP_SIS550, PCI_CHIP_SIS550, RES_SHARED_VGA }, 204 { PCI_CHIP_SIS315, PCI_CHIP_SIS315, RES_SHARED_VGA }, 205 { PCI_CHIP_SIS315H, PCI_CHIP_SIS315H, RES_SHARED_VGA }, 206 { PCI_CHIP_SIS315PRO, PCI_CHIP_SIS315PRO, RES_SHARED_VGA }, 207 { PCI_CHIP_SIS650, PCI_CHIP_SIS650, RES_SHARED_VGA }, 208 { PCI_CHIP_SIS330, PCI_CHIP_SIS330, RES_SHARED_VGA }, 209 { PCI_CHIP_SIS660, PCI_CHIP_SIS660, RES_SHARED_VGA }, 210 { PCI_CHIP_SIS340, PCI_CHIP_SIS340, RES_SHARED_VGA }, 211 { -1, -1, RES_UNDEFINED } 212}; 213 214static SymTabRec XGIChipsets[] = { 215 { PCI_CHIP_XGIXG20, "Volari Z7 (XG20)" }, 216 { PCI_CHIP_XGIXG40, "Volari V3XT/V5/V8/Duo (XG40)" }, 217 { -1, NULL } 218}; 219 220static PciChipsets XGIPciChipsets[] = { 221 { PCI_CHIP_XGIXG20, PCI_CHIP_XGIXG20, RES_SHARED_VGA }, 222 { PCI_CHIP_XGIXG40, PCI_CHIP_XGIXG40, RES_SHARED_VGA }, 223 { -1, -1, RES_UNDEFINED } 224}; 225 226#ifdef XFree86LOADER 227 228static MODULESETUPPROTO(sisSetup); 229 230static XF86ModuleVersionInfo sisVersRec = 231{ 232 SIS_DRIVER_NAME, 233 MODULEVENDORSTRING, 234 MODINFOSTRING1, 235 MODINFOSTRING2, 236#ifdef XORG_VERSION_CURRENT 237 XORG_VERSION_CURRENT, 238#else 239 XF86_VERSION_CURRENT, 240#endif 241 SIS_MAJOR_VERSION, SIS_MINOR_VERSION, SIS_PATCHLEVEL, 242 ABI_CLASS_VIDEODRV, /* This is a video driver */ 243 ABI_VIDEODRV_VERSION, 244 MOD_CLASS_VIDEODRV, 245 {0,0,0,0} 246}; 247 248#ifdef _X_EXPORT 249_X_EXPORT 250#endif 251XF86ModuleData sisModuleData = { &sisVersRec, sisSetup, NULL }; 252 253pointer 254sisSetup(pointer module, pointer opts, int *errmaj, int *errmin) 255{ 256 static Bool setupDone = FALSE; 257 258 if(!setupDone) { 259 setupDone = TRUE; 260 xf86AddDriver(&SIS, module, SIS_HaveDriverFuncs); 261 return (pointer)TRUE; 262 } 263 264 if(errmaj) *errmaj = LDR_ONCEONLY; 265 return NULL; 266} 267 268#endif /* XFree86LOADER */ 269 270/* Mandatory */ 271static void 272SISIdentify(int flags) 273{ 274 xf86PrintChipsets(SIS_NAME, "driver for SiS chipsets", SISChipsets); 275 xf86PrintChipsets(SIS_NAME, "driver for XGI chipsets", XGIChipsets); 276} 277 278#ifdef SIS_HAVE_DRIVER_FUNC 279static Bool 280SISDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op, pointer ptr) 281{ 282 CARD32 *flag; 283 284 switch(op) { 285 case RR_GET_INFO: 286 break; 287 case RR_SET_CONFIG: 288 break; 289 case GET_REQUIRED_HW_INTERFACES: 290 break; 291 } 292 return TRUE; 293} 294#endif 295 296static Bool 297SISGetRec(ScrnInfoPtr pScrn) 298{ 299 /* Allocate an SISRec, and hook it into pScrn->driverPrivate. 300 * pScrn->driverPrivate is initialised to NULL, so we can check if 301 * the allocation has already been done. 302 */ 303 if(pScrn->driverPrivate != NULL) return TRUE; 304 305 pScrn->driverPrivate = xnfcalloc(sizeof(SISRec), 1); 306 307 /* Initialise it to 0 */ 308 memset(pScrn->driverPrivate, 0, sizeof(SISRec)); 309 310 return TRUE; 311} 312 313static void 314SISFreeRec(ScrnInfoPtr pScrn) 315{ 316 SISPtr pSiS = SISPTR(pScrn); 317#ifdef SISDUALHEAD 318 SISEntPtr pSiSEnt = NULL; 319#endif 320 321 /* Just to make sure... */ 322 if(!pSiS) return; 323 324#ifdef SISDUALHEAD 325 pSiSEnt = pSiS->entityPrivate; 326#endif 327 328 if(pSiS->pstate) free(pSiS->pstate); 329 pSiS->pstate = NULL; 330 if(pSiS->fonts) free(pSiS->fonts); 331 pSiS->fonts = NULL; 332 333#ifdef SISDUALHEAD 334 if(pSiSEnt) { 335 if(!pSiS->SecondHead) { 336 /* Free memory only if we are first head; in case of an error 337 * during init of the second head, the server will continue - 338 * and we need the BIOS image and SiS_Private for the first 339 * head. 340 */ 341 if(pSiSEnt->BIOS) free(pSiSEnt->BIOS); 342 pSiSEnt->BIOS = pSiS->BIOS = NULL; 343 if(pSiSEnt->SiS_Pr) free(pSiSEnt->SiS_Pr); 344 pSiSEnt->SiS_Pr = pSiS->SiS_Pr = NULL; 345 if(pSiSEnt->RenderAccelArray) free(pSiSEnt->RenderAccelArray); 346 pSiSEnt->RenderAccelArray = pSiS->RenderAccelArray = NULL; 347 pSiSEnt->pScrn_1 = NULL; 348 } else { 349 pSiS->BIOS = NULL; 350 pSiS->SiS_Pr = NULL; 351 pSiS->RenderAccelArray = NULL; 352 pSiSEnt->pScrn_2 = NULL; 353 } 354 } else { 355#endif 356 if(pSiS->BIOS) free(pSiS->BIOS); 357 pSiS->BIOS = NULL; 358 if(pSiS->SiS_Pr) free(pSiS->SiS_Pr); 359 pSiS->SiS_Pr = NULL; 360 if(pSiS->RenderAccelArray) free(pSiS->RenderAccelArray); 361 pSiS->RenderAccelArray = NULL; 362#ifdef SISDUALHEAD 363 } 364#endif 365#ifdef SISMERGED 366 if(pSiS->CRT2HSync) free(pSiS->CRT2HSync); 367 pSiS->CRT2HSync = NULL; 368 if(pSiS->CRT2VRefresh) free(pSiS->CRT2VRefresh); 369 pSiS->CRT2VRefresh = NULL; 370 if(pSiS->MetaModes) free(pSiS->MetaModes); 371 pSiS->MetaModes = NULL; 372 if(pSiS->CRT2pScrn) { 373 if(pSiS->CRT2pScrn->modes) { 374 while(pSiS->CRT2pScrn->modes) 375 xf86DeleteMode(&pSiS->CRT2pScrn->modes, pSiS->CRT2pScrn->modes); 376 } 377 if(pSiS->CRT2pScrn->monitor) { 378 if(pSiS->CRT2pScrn->monitor->Modes) { 379 while(pSiS->CRT2pScrn->monitor->Modes) 380 xf86DeleteMode(&pSiS->CRT2pScrn->monitor->Modes, pSiS->CRT2pScrn->monitor->Modes); 381 } 382 if(pSiS->CRT2pScrn->monitor->DDC) free(pSiS->CRT2pScrn->monitor->DDC); 383 free(pSiS->CRT2pScrn->monitor); 384 } 385 free(pSiS->CRT2pScrn); 386 pSiS->CRT2pScrn = NULL; 387 } 388 if(pSiS->CRT1Modes) { 389 if(pSiS->CRT1Modes != pScrn->modes) { 390 if(pScrn->modes) { 391 pScrn->currentMode = pScrn->modes; 392 do { 393 DisplayModePtr p = pScrn->currentMode->next; 394 if(pScrn->currentMode->Private) 395 free(pScrn->currentMode->Private); 396 free(pScrn->currentMode); 397 pScrn->currentMode = p; 398 } while(pScrn->currentMode != pScrn->modes); 399 } 400 pScrn->currentMode = pSiS->CRT1CurrentMode; 401 pScrn->modes = pSiS->CRT1Modes; 402 pSiS->CRT1CurrentMode = NULL; 403 pSiS->CRT1Modes = NULL; 404 } 405 } 406#endif 407 while(pSiS->SISVESAModeList) { 408 sisModeInfoPtr mp = pSiS->SISVESAModeList->next; 409 free(pSiS->SISVESAModeList); 410 pSiS->SISVESAModeList = mp; 411 } 412 if(pSiS->pVbe) vbeFree(pSiS->pVbe); 413 pSiS->pVbe = NULL; 414 415#ifdef SISUSEDEVPORT 416 if(pSiS->sisdevportopen) close(sisdevport); 417#endif 418 419 if(pScrn->driverPrivate == NULL) 420 return; 421 free(pScrn->driverPrivate); 422 pScrn->driverPrivate = NULL; 423} 424 425static void 426SISErrorLog(ScrnInfoPtr pScrn, const char *format, ...) 427{ 428 va_list ap; 429 static const char str[] = "**************************************************\n"; 430 431 va_start(ap, format); 432 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s", str); 433 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 434 " ERROR:\n"); 435 xf86VDrvMsgVerb(pScrn->scrnIndex, X_ERROR, 1, format, ap); 436 va_end(ap); 437 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 438 " END OF MESSAGE\n"); 439 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s", str); 440} 441 442static void 443SiS_SiSFB_Lock(ScrnInfoPtr pScrn, Bool lock) 444{ 445 SISPtr pSiS = SISPTR(pScrn); 446 int fd; 447 CARD32 parm; 448 449 if(!pSiS->sisfbfound) return; 450 if(!pSiS->sisfb_havelock) return; 451 452 if((fd = open(pSiS->sisfbdevname, O_RDONLY)) != -1) { 453 parm = lock ? 1 : 0; 454 ioctl(fd, SISFB_SET_LOCK, &parm); 455 close(fd); 456 } 457} 458 459/* Probe() 460 * 461 * Mandatory 462 */ 463static Bool 464SISProbe(DriverPtr drv, int flags) 465{ 466 int i; 467 GDevPtr *devSections; 468 int *usedChipsSiS, *usedChipsXGI; 469 int numDevSections; 470 int numUsed, numUsedSiS, numUsedXGI; 471 Bool foundScreen = FALSE; 472 473 /* 474 * The aim here is to find all cards that this driver can handle, 475 * and for the ones not already claimed by another driver, claim the 476 * slot, and allocate a ScrnInfoRec. 477 * 478 * This should be a minimal probe, and it should under no circumstances 479 * change the state of the hardware. Because a device is found, don't 480 * assume that it will be used. Don't do any initialisations other than 481 * the required ScrnInfoRec initialisations. Don't allocate any new 482 * data structures. 483 * 484 */ 485 486 /* 487 * Next we check, if there has been a chipset override in the config file. 488 * For this we must find out if there is an active device section which 489 * is relevant, i.e., which has no driver specified or has THIS driver 490 * specified. 491 */ 492 493 if((numDevSections = xf86MatchDevice(SIS_DRIVER_NAME, &devSections)) <= 0) { 494 /* 495 * There's no matching device section in the config file, so quit 496 * now. 497 */ 498 return FALSE; 499 } 500 501 /* 502 * We need to probe the hardware first. We then need to see how this 503 * fits in with what is given in the config file, and allow the config 504 * file info to override any contradictions. 505 */ 506 507 /* 508 * All of the cards this driver supports are PCI, so the "probing" just 509 * amounts to checking the PCI data that the server has already collected. 510 */ 511#ifndef XSERVER_LIBPCIACCESS 512 if(xf86GetPciVideoInfo() == NULL) { 513 /* 514 * We won't let anything in the config file override finding no 515 * PCI video cards at all. 516 */ 517 return FALSE; 518 } 519#endif 520 521 numUsedSiS = xf86MatchPciInstances(SIS_NAME, PCI_VENDOR_SIS, 522 SISChipsets, SISPciChipsets, devSections, 523 numDevSections, drv, &usedChipsSiS); 524 525 numUsedXGI = xf86MatchPciInstances(SIS_NAME, PCI_VENDOR_XGI, 526 XGIChipsets, XGIPciChipsets, devSections, 527 numDevSections, drv, &usedChipsXGI); 528 529 /* Free it since we don't need that list after this */ 530 free(devSections); 531 532 numUsed = numUsedSiS + numUsedXGI; 533 534 if(numUsed <= 0) 535 return FALSE; 536 537 if(flags & PROBE_DETECT) { 538 539 foundScreen = TRUE; 540 541 } else for(i = 0; i < numUsed; i++) { 542 543 ScrnInfoPtr pScrn; 544#ifdef SISDUALHEAD 545 EntityInfoPtr pEnt; 546#endif 547 548 /* Allocate a ScrnInfoRec and claim the slot */ 549 pScrn = NULL; 550 551 if((pScrn = xf86ConfigPciEntity(pScrn, 0, 552 (i < numUsedSiS) ? usedChipsSiS[i] : usedChipsXGI[i-numUsedSiS], 553 (i < numUsedSiS) ? SISPciChipsets : XGIPciChipsets, 554 NULL, NULL, NULL, NULL, NULL))) { 555 /* Fill in what we can of the ScrnInfoRec */ 556 pScrn->driverVersion = SIS_CURRENT_VERSION; 557 pScrn->driverName = SIS_DRIVER_NAME; 558 pScrn->name = SIS_NAME; 559 pScrn->Probe = SISProbe; 560 pScrn->PreInit = SISPreInit; 561 pScrn->ScreenInit = SISScreenInit; 562 pScrn->SwitchMode = SISSwitchMode; 563 pScrn->AdjustFrame = SISAdjustFrame; 564 pScrn->EnterVT = SISEnterVT; 565 pScrn->LeaveVT = SISLeaveVT; 566 pScrn->FreeScreen = SISFreeScreen; 567 pScrn->ValidMode = SISValidMode; 568 569 foundScreen = TRUE; 570 } 571 572#ifdef SISDUALHEAD 573 pEnt = xf86GetEntityInfo((i < numUsedSiS) ? usedChipsSiS[i] : usedChipsXGI[i-numUsedSiS]); 574 575 if(pEnt->chipset == PCI_CHIP_SIS630 || pEnt->chipset == PCI_CHIP_SIS540 || 576 pEnt->chipset == PCI_CHIP_SIS650 || pEnt->chipset == PCI_CHIP_SIS550 || 577 pEnt->chipset == PCI_CHIP_SIS315 || pEnt->chipset == PCI_CHIP_SIS315H || 578 pEnt->chipset == PCI_CHIP_SIS315PRO || pEnt->chipset == PCI_CHIP_SIS330 || 579 pEnt->chipset == PCI_CHIP_SIS300 || pEnt->chipset == PCI_CHIP_SIS660 || 580 pEnt->chipset == PCI_CHIP_SIS340 || pEnt->chipset == PCI_CHIP_XGIXG40) { 581 582 SISEntPtr pSiSEnt = NULL; 583 DevUnion *pPriv; 584 585 xf86SetEntitySharable((i < numUsedSiS) ? usedChipsSiS[i] : usedChipsXGI[i-numUsedSiS]); 586 if(SISEntityIndex < 0) { 587 SISEntityIndex = xf86AllocateEntityPrivateIndex(); 588 } 589 pPriv = xf86GetEntityPrivate(pScrn->entityList[0], SISEntityIndex); 590 if(!pPriv->ptr) { 591 pPriv->ptr = xnfcalloc(sizeof(SISEntRec), 1); 592 pSiSEnt = pPriv->ptr; 593 memset(pSiSEnt, 0, sizeof(SISEntRec)); 594 pSiSEnt->lastInstance = -1; 595 } else { 596 pSiSEnt = pPriv->ptr; 597 } 598 pSiSEnt->lastInstance++; 599 xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0], 600 pSiSEnt->lastInstance); 601 } 602#endif /* DUALHEAD */ 603 604 } 605 606 if(usedChipsSiS) free(usedChipsSiS); 607 if(usedChipsXGI) free(usedChipsXGI); 608 609 return foundScreen; 610} 611 612/* Various helpers */ 613 614static unsigned short 615calcgammaval(int j, int nramp, float invgamma, float bri, float c) 616{ 617 float k = (float)j; 618 float nrm1 = (float)(nramp - 1); 619 float con = c * nrm1 / 3.0; 620 float l, v; 621 622 if(con != 0.0) { 623 l = nrm1 / 2.0; 624 if(con <= 0.0) { 625 k -= l; 626 k *= (l + con) / l; 627 } else { 628 l -= 1.0; 629 k -= l; 630 k *= l / (l - con); 631 } 632 k += l; 633 if(k < 0.0) k = 0.0; 634 } 635 636 if(invgamma == 1.0) { 637 v = k / nrm1 * 65535.0; 638 } else { 639 v = pow(k / nrm1, invgamma) * 65535.0 + 0.5; 640 } 641 642 v += (bri * (65535.0 / 3.0)) ; 643 644 if(v < 0.0) v = 0.0; 645 else if(v > 65535.0) v = 65535.0; 646 647 return (unsigned short)v; 648} 649 650#ifdef SISGAMMARAMP 651void 652SISCalculateGammaRamp(ScreenPtr pScreen, ScrnInfoPtr pScrn) 653{ 654 SISPtr pSiS = SISPTR(pScrn); 655 int i, j, nramp; 656 UShort *ramp[3]; 657 float gamma_max[3], framp; 658 Bool newmethod = FALSE; 659 660 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_OLDGAMMAINUSE)) { 661 newmethod = TRUE; 662 } else { 663 gamma_max[0] = (float)pSiS->GammaBriR / 1000; 664 gamma_max[1] = (float)pSiS->GammaBriG / 1000; 665 gamma_max[2] = (float)pSiS->GammaBriB / 1000; 666 } 667 668 if(!(nramp = xf86GetGammaRampSize(pScreen))) return; 669 670 for(i=0; i<3; i++) { 671 ramp[i] = (UShort *)malloc(nramp * sizeof(UShort)); 672 if(!ramp[i]) { 673 if(ramp[0]) { free(ramp[0]); ramp[0] = NULL; } 674 if(ramp[1]) { free(ramp[1]); ramp[1] = NULL; } 675 return; 676 } 677 } 678 679 if(newmethod) { 680 681 for(i = 0; i < 3; i++) { 682 683 float invgamma = 0.0, bri = 0.0, con = 0.0; 684 685 switch(i) { 686 case 0: invgamma = 1. / pScrn->gamma.red; 687 bri = pSiS->NewGammaBriR; 688 con = pSiS->NewGammaConR; 689 break; 690 case 1: invgamma = 1. / pScrn->gamma.green; 691 bri = pSiS->NewGammaBriG; 692 con = pSiS->NewGammaConG; 693 break; 694 case 2: invgamma = 1. / pScrn->gamma.blue; 695 bri = pSiS->NewGammaBriB; 696 con = pSiS->NewGammaConB; 697 break; 698 } 699 700 for(j = 0; j < nramp; j++) { 701 ramp[i][j] = calcgammaval(j, nramp, invgamma, bri, con); 702 } 703 704 } 705 706 } else { 707 708 for(i = 0; i < 3; i++) { 709 int fullscale = 65535 * gamma_max[i]; 710 float dramp = 1. / (nramp - 1); 711 float invgamma = 0.0, v; 712 713 switch(i) { 714 case 0: invgamma = 1. / pScrn->gamma.red; break; 715 case 1: invgamma = 1. / pScrn->gamma.green; break; 716 case 2: invgamma = 1. / pScrn->gamma.blue; break; 717 } 718 719 for(j = 0; j < nramp; j++) { 720 framp = pow(j * dramp, invgamma); 721 722 v = (fullscale < 0) ? (65535 + fullscale * framp) : 723 fullscale * framp; 724 if(v < 0) v = 0; 725 else if(v > 65535) v = 65535; 726 ramp[i][j] = (UShort)v; 727 } 728 } 729 730 } 731 732 xf86ChangeGammaRamp(pScreen, nramp, ramp[0], ramp[1], ramp[2]); 733 734 free(ramp[0]); 735 free(ramp[1]); 736 free(ramp[2]); 737 ramp[0] = ramp[1] = ramp[2] = NULL; 738} 739#endif 740 741void 742SISCalculateGammaRampCRT2(ScrnInfoPtr pScrn) 743{ 744 SISPtr pSiS = SISPTR(pScrn); 745 int i; 746 int myshift = 16 - pScrn->rgbBits; 747 int maxvalue = (1 << pScrn->rgbBits) - 1; 748 int reds = pScrn->mask.red >> pScrn->offset.red; 749 int greens = pScrn->mask.green >> pScrn->offset.green; 750 int blues = pScrn->mask.blue >> pScrn->offset.blue; 751 float framp, invgamma1, invgamma2, invgamma3, v; 752 753 invgamma1 = 1. / pSiS->GammaR2; 754 invgamma2 = 1. / pSiS->GammaG2; 755 invgamma3 = 1. / pSiS->GammaB2; 756 757 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_OLDGAMMAINUSE)) { 758 759 for(i = 0; i < pSiS->CRT2ColNum; i++) { 760 pSiS->crt2gcolortable[i].red = calcgammaval(i, pSiS->CRT2ColNum, invgamma1, 761 pSiS->NewGammaBriR2, pSiS->NewGammaConR2) >> myshift; 762 pSiS->crt2gcolortable[i].green = calcgammaval(i, pSiS->CRT2ColNum, invgamma2, 763 pSiS->NewGammaBriG2, pSiS->NewGammaConG2) >> myshift; 764 pSiS->crt2gcolortable[i].blue = calcgammaval(i, pSiS->CRT2ColNum, invgamma3, 765 pSiS->NewGammaBriB2, pSiS->NewGammaConB2) >> myshift; 766 } 767 768 } else { 769 770 int fullscale1 = 65536 * (float)pSiS->GammaBriR2 / 1000; 771 int fullscale2 = 65536 * (float)pSiS->GammaBriG2 / 1000; 772 int fullscale3 = 65536 * (float)pSiS->GammaBriB2 / 1000; 773 774 float dramp = 1. / (pSiS->CRT2ColNum - 1); 775 776 for(i = 0; i < pSiS->CRT2ColNum; i++) { 777 framp = pow(i * dramp, invgamma1); 778 v = (fullscale1 < 0) ? (65535 + fullscale1 * framp) : fullscale1 * framp; 779 if(v < 0) v = 0; 780 else if(v > 65535) v = 65535; 781 pSiS->crt2gcolortable[i].red = ((UShort)v) >> myshift; 782 framp = pow(i * dramp, invgamma2); 783 v = (fullscale2 < 0) ? (65535 + fullscale2 * framp) : fullscale2 * framp; 784 if(v < 0) v = 0; 785 else if(v > 65535) v = 65535; 786 pSiS->crt2gcolortable[i].green = ((UShort)v) >> myshift; 787 framp = pow(i * dramp, invgamma3); 788 v = (fullscale3 < 0) ? (65535 + fullscale3 * framp) : fullscale3 * framp; 789 if(v < 0) v = 0; 790 else if(v > 65535) v = 65535; 791 pSiS->crt2gcolortable[i].blue = ((UShort)v) >> myshift; 792 } 793 794 } 795 796 for(i = 0; i < pSiS->CRT2ColNum; i++) { 797 pSiS->crt2colors[i].red = 798 pSiS->crt2gcolortable[i * maxvalue / reds].red; 799 pSiS->crt2colors[i].green = 800 pSiS->crt2gcolortable[i * maxvalue / greens].green; 801 pSiS->crt2colors[i].blue = 802 pSiS->crt2gcolortable[i * maxvalue / blues].blue; 803 } 804} 805 806/* If monitor section has no HSync/VRefresh data, 807 * derive it from DDC data. 808 */ 809static void 810SiSSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) 811{ 812 MonPtr mon = pScrn->monitor; 813 xf86MonPtr ddc = mon->DDC; 814 float myhhigh = 0.0, myhlow = 0.0, htest; 815 int myvhigh = 0, myvlow = 0, vtest, i; 816 UChar temp; 817 const myhddctiming myhtiming[12] = { 818 { 1, 0x20, 31.6 }, /* rounded up by .1 */ 819 { 1, 0x80, 31.6 }, 820 { 1, 0x02, 35.3 }, 821 { 1, 0x04, 37.6 }, 822 { 1, 0x08, 38.0 }, 823 { 1, 0x01, 38.0 }, 824 { 2, 0x40, 47.0 }, 825 { 2, 0x80, 48.2 }, 826 { 2, 0x08, 48.5 }, 827 { 2, 0x04, 56.6 }, 828 { 2, 0x02, 60.1 }, 829 { 2, 0x01, 80.1 } 830 }; 831 const myvddctiming myvtiming[11] = { 832 { 1, 0x02, 56 }, 833 { 1, 0x01, 60 }, 834 { 2, 0x08, 60 }, 835 { 2, 0x04, 70 }, 836 { 1, 0x80, 71 }, 837 { 1, 0x08, 72 }, 838 { 2, 0x80, 72 }, 839 { 1, 0x04, 75 }, 840 { 2, 0x40, 75 }, 841 { 2, 0x02, 75 }, 842 { 2, 0x01, 75 } 843 }; 844 845 if(flag) { /* HSync */ 846 847 for(i = 0; i < 4; i++) { 848 if(ddc->det_mon[i].type == DS_RANGES) { 849 mon->nHsync = 1; 850 mon->hsync[0].lo = ddc->det_mon[i].section.ranges.min_h; 851 mon->hsync[0].hi = ddc->det_mon[i].section.ranges.max_h; 852 if(mon->hsync[0].lo > 32.0 || mon->hsync[0].hi < 31.0) { 853 if(ddc->timings1.t1 & 0x80) { 854 mon->nHsync++; 855 mon->hsync[1].lo = 31.0; 856 mon->hsync[1].hi = 32.0; 857 } 858 } 859 return; 860 } 861 } 862 863 /* If no sync ranges detected in detailed timing table, we 864 * derive them from supported VESA modes. 865 */ 866 867 for(i = 0; i < 12; i++) { 868 if(myhtiming[i].whichone == 1) temp = ddc->timings1.t1; 869 else temp = ddc->timings1.t2; 870 if(temp & myhtiming[i].mask) { 871 if((i == 0) || (myhlow > myhtiming[i].rate)) 872 myhlow = myhtiming[i].rate; 873 } 874 if(myhtiming[11-i].whichone == 1) temp = ddc->timings1.t1; 875 else temp = ddc->timings1.t2; 876 if(temp & myhtiming[11-i].mask) { 877 if((i == 0) || (myhhigh < myhtiming[11-i].rate)) 878 myhhigh = myhtiming[11-i].rate; 879 } 880 } 881 882 for(i = 0; i < STD_TIMINGS; i++) { 883 if(ddc->timings2[i].hsize > 256) { 884 htest = ddc->timings2[i].refresh * 1.05 * ddc->timings2[i].vsize / 1000.0; 885 if(htest < myhlow) myhlow = htest; 886 if(htest > myhhigh) myhhigh = htest; 887 } 888 } 889 890 if((myhhigh > 0.0) && (myhlow > 0.0)) { 891 mon->nHsync = 1; 892 mon->hsync[0].lo = myhlow - 0.1; 893 mon->hsync[0].hi = myhhigh; 894 } 895 896 897 } else { /* Vrefresh */ 898 899 for(i = 0; i < 4; i++) { 900 if(ddc->det_mon[i].type == DS_RANGES) { 901 mon->nVrefresh = 1; 902 mon->vrefresh[0].lo = ddc->det_mon[i].section.ranges.min_v; 903 mon->vrefresh[0].hi = ddc->det_mon[i].section.ranges.max_v; 904 if(mon->vrefresh[0].lo > 72 || mon->vrefresh[0].hi < 70) { 905 if(ddc->timings1.t1 & 0x80) { 906 mon->nVrefresh++; 907 mon->vrefresh[1].lo = 71; 908 mon->vrefresh[1].hi = 71; 909 } 910 } 911 return; 912 } 913 } 914 915 for(i = 0; i < 11; i++) { 916 if(myvtiming[i].whichone == 1) temp = ddc->timings1.t1; 917 else temp = ddc->timings1.t2; 918 if(temp & myvtiming[i].mask) { 919 if((i == 0) || (myvlow > myvtiming[i].rate)) 920 myvlow = myvtiming[i].rate; 921 } 922 if(myvtiming[10-i].whichone == 1) temp = ddc->timings1.t1; 923 else temp = ddc->timings1.t2; 924 if(temp & myvtiming[10-i].mask) { 925 if((i == 0) || (myvhigh < myvtiming[10-i].rate)) 926 myvhigh = myvtiming[10-i].rate; 927 } 928 } 929 930 for(i = 0; i < STD_TIMINGS; i++) { 931 if(ddc->timings2[i].hsize > 256) { 932 vtest = ddc->timings2[i].refresh; 933 if(vtest < myvlow) myvlow = vtest; 934 if(vtest > myvhigh) myvhigh = vtest; 935 } 936 } 937 938 if((myvhigh > 0) && (myvlow > 0)) { 939 mon->nVrefresh = 1; 940 mon->vrefresh[0].lo = myvlow; 941 mon->vrefresh[0].hi = myvhigh; 942 } 943 944 } 945} 946 947static Bool 948SiSAllowSyncOverride(SISPtr pSiS, Bool fromDDC) 949{ 950 if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return FALSE; 951 952#ifdef SISDUALHEAD 953 if(pSiS->DualHeadMode) { 954 if(pSiS->SecondHead) { 955 if((pSiS->VBFlags & CRT1_LCDA) && (!fromDDC)) return TRUE; 956 } else { 957 if((pSiS->VBFlags & CRT2_TV) || 958 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC))) return TRUE; 959 } 960 return FALSE; 961 } 962#endif 963 964#ifdef SISMERGED 965 if(pSiS->MergedFB) { 966 if((pSiS->VBFlags & CRT1_LCDA) && (!fromDDC)) return TRUE; 967 return FALSE; 968 } 969#endif 970 971 if(!(pSiS->VBFlags & DISPTYPE_CRT1)) { 972 if( (pSiS->VBFlags & CRT2_TV) || 973 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC)) ) return TRUE; 974 } else if((pSiS->VBFlags & CRT1_LCDA) && (!fromDDC)) return TRUE; 975 976 return FALSE; 977} 978 979static Bool 980SiSCheckForH(float hsync, MonPtr monitor) 981{ 982 int i; 983 for(i = 0; i < monitor->nHsync; i++) { 984 if((hsync > monitor->hsync[i].lo * (1.0 - SYNC_TOLERANCE)) && 985 (hsync < monitor->hsync[i].hi * (1.0 + SYNC_TOLERANCE))) 986 break; 987 } 988 if(i == monitor->nHsync) return FALSE; 989 return TRUE; 990} 991 992static Bool 993SiSCheckForV(float vrefresh, MonPtr monitor) 994{ 995 int i; 996 for(i = 0; i < monitor->nVrefresh; i++) { 997 if((vrefresh > monitor->vrefresh[i].lo * (1.0 - SYNC_TOLERANCE)) && 998 (vrefresh < monitor->vrefresh[i].hi * (1.0 + SYNC_TOLERANCE))) 999 break; 1000 } 1001 if(i == monitor->nVrefresh) return FALSE; 1002 return TRUE; 1003} 1004 1005static Bool 1006CheckAndOverruleH(ScrnInfoPtr pScrn, MonPtr monitor) 1007{ 1008 DisplayModePtr mode = monitor->Modes; 1009 float mymin = 30.0, mymax = 80.0, hsync; 1010 Bool doit = FALSE; 1011 1012 for(hsync = mymin; hsync <= mymax; hsync += .5) { 1013 if(!SiSCheckForH(hsync, monitor)) doit = TRUE; 1014 } 1015 1016 if(mode) { 1017 do { 1018 if(mode->type & M_T_BUILTIN) { 1019 hsync = (float)mode->Clock / (float)mode->HTotal; 1020 if(!SiSCheckForH(hsync, monitor)) { 1021 doit = TRUE; 1022 if(hsync < mymin) mymin = hsync; 1023 if(hsync > mymax) mymax = hsync; 1024 } 1025 } 1026 } while((mode = mode->next)); 1027 } 1028 1029 if(doit) { 1030 monitor->nHsync = 1; 1031 monitor->hsync[0].lo = mymin; 1032 monitor->hsync[0].hi = mymax; 1033 return TRUE; 1034 } 1035 1036 return FALSE; 1037} 1038 1039static Bool 1040CheckAndOverruleV(ScrnInfoPtr pScrn, MonPtr monitor) 1041{ 1042 DisplayModePtr mode = monitor->Modes; 1043 float mymin = 59.0, mymax = 61.0, vrefresh; 1044 Bool doit = FALSE, ret = FALSE; 1045 1046 for(vrefresh = mymin; vrefresh <= mymax; vrefresh += 1.0) { 1047 if(!SiSCheckForV(vrefresh, monitor)) doit = TRUE; 1048 } 1049 1050 if(mode) { 1051 do { 1052 if(mode->type & M_T_BUILTIN) { 1053 vrefresh = mode->Clock * 1000.0 / (mode->HTotal * mode->VTotal); 1054 if(mode->Flags & V_INTERLACE) vrefresh *= 2.0; 1055 if(mode->Flags & V_DBLSCAN) vrefresh /= 2.0; 1056 if(!SiSCheckForH(vrefresh, monitor)) { 1057 doit = TRUE; 1058 if(vrefresh < mymin) mymin = vrefresh; 1059 if(vrefresh > mymax) mymax = vrefresh; 1060 } 1061 } 1062 } while((mode = mode->next)); 1063 } 1064 1065 if(doit) { 1066 monitor->nVrefresh = 1; 1067 monitor->vrefresh[0].lo = mymin; 1068 monitor->vrefresh[0].hi = mymax; 1069 ret = TRUE; 1070 } 1071 1072 /* special for 640x400/320x200/@70Hz (VGA/IBM 720x480) */ 1073 if( (!SiSCheckForV(71, monitor)) && 1074 (monitor->nVrefresh < MAX_VREFRESH) ) { 1075 monitor->vrefresh[monitor->nVrefresh].lo = 71; 1076 monitor->vrefresh[monitor->nVrefresh].hi = 71; 1077 monitor->nVrefresh++; 1078 ret = TRUE; 1079 } 1080 return ret; 1081} 1082 1083/* Some helper functions for MergedFB mode */ 1084 1085#ifdef SISMERGED 1086 1087/* Helper function for CRT2 monitor vrefresh/hsync options 1088 * (Code base from mga driver) 1089 */ 1090static int 1091SiSStrToRanges(range *r, char *s, int max) 1092{ 1093 float num = 0.0; 1094 int rangenum = 0; 1095 Bool gotdash = FALSE; 1096 Bool nextdash = FALSE; 1097 char *strnum = NULL; 1098 do { 1099 switch(*s) { 1100 case '0': 1101 case '1': 1102 case '2': 1103 case '3': 1104 case '4': 1105 case '5': 1106 case '6': 1107 case '7': 1108 case '8': 1109 case '9': 1110 case '.': 1111 if(strnum == NULL) { 1112 strnum = s; 1113 gotdash = nextdash; 1114 nextdash = FALSE; 1115 } 1116 break; 1117 case '-': 1118 case ' ': 1119 case 0: 1120 if(strnum == NULL) break; 1121 sscanf(strnum, "%f", &num); 1122 strnum = NULL; 1123 if(gotdash) { 1124 r[rangenum - 1].hi = num; 1125 } else { 1126 r[rangenum].lo = num; 1127 r[rangenum].hi = num; 1128 rangenum++; 1129 } 1130 if(*s == '-') nextdash = (rangenum != 0); 1131 else if(rangenum >= max) return rangenum; 1132 break; 1133 default: 1134 return 0; 1135 } 1136 1137 } while(*(s++) != 0); 1138 1139 return rangenum; 1140} 1141 1142/* Copy and link two modes (i, j) for mergedfb mode 1143 * (Code base taken from mga driver) 1144 * 1145 * - Copy mode i, merge j to copy of i, link the result to dest 1146 * - Link i and j in private record. 1147 * - If dest is NULL, return value is copy of i linked to itself. 1148 * - For mergedfb auto-config, we only check the dimension 1149 * against virtualX/Y, if they were user-provided. 1150 * - No special treatment required for CRTxxOffs. 1151 * - Provide fake dotclock in order to distinguish between similar 1152 * looking MetaModes (for RandR and VidMode extensions) 1153 * - Set unique VRefresh of dest mode for RandR 1154 */ 1155static DisplayModePtr 1156SiSCopyModeNLink(ScrnInfoPtr pScrn, DisplayModePtr dest, 1157 DisplayModePtr i, DisplayModePtr j, 1158 SiSScrn2Rel srel) 1159{ 1160 SISPtr pSiS = SISPTR(pScrn); 1161 DisplayModePtr mode; 1162 int dx = 0,dy = 0; 1163 1164 if(!((mode = malloc(sizeof(DisplayModeRec))))) return dest; 1165 memcpy(mode, i, sizeof(DisplayModeRec)); 1166 if(!((mode->Private = malloc(sizeof(SiSMergedDisplayModeRec))))) { 1167 free(mode); 1168 return dest; 1169 } 1170 ((SiSMergedDisplayModePtr)mode->Private)->CRT1 = i; 1171 ((SiSMergedDisplayModePtr)mode->Private)->CRT2 = j; 1172 ((SiSMergedDisplayModePtr)mode->Private)->CRT2Position = srel; 1173 mode->PrivSize = 0; 1174 1175 switch(srel) { 1176 case sisLeftOf: 1177 case sisRightOf: 1178 if(!(pScrn->display->virtualX)) { 1179 dx = i->HDisplay + j->HDisplay; 1180 } else { 1181 dx = min(pScrn->virtualX, i->HDisplay + j->HDisplay); 1182 } 1183 dx -= mode->HDisplay; 1184 if(!(pScrn->display->virtualY)) { 1185 dy = max(i->VDisplay, j->VDisplay); 1186 } else { 1187 dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay)); 1188 } 1189 dy -= mode->VDisplay; 1190 break; 1191 case sisAbove: 1192 case sisBelow: 1193 if(!(pScrn->display->virtualY)) { 1194 dy = i->VDisplay + j->VDisplay; 1195 } else { 1196 dy = min(pScrn->virtualY, i->VDisplay + j->VDisplay); 1197 } 1198 dy -= mode->VDisplay; 1199 if(!(pScrn->display->virtualX)) { 1200 dx = max(i->HDisplay, j->HDisplay); 1201 } else { 1202 dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay)); 1203 } 1204 dx -= mode->HDisplay; 1205 break; 1206 case sisClone: 1207 if(!(pScrn->display->virtualX)) { 1208 dx = max(i->HDisplay, j->HDisplay); 1209 } else { 1210 dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay)); 1211 } 1212 dx -= mode->HDisplay; 1213 if(!(pScrn->display->virtualY)) { 1214 dy = max(i->VDisplay, j->VDisplay); 1215 } else { 1216 dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay)); 1217 } 1218 dy -= mode->VDisplay; 1219 break; 1220 } 1221 mode->HDisplay += dx; 1222 mode->HSyncStart += dx; 1223 mode->HSyncEnd += dx; 1224 mode->HTotal += dx; 1225 mode->VDisplay += dy; 1226 mode->VSyncStart += dy; 1227 mode->VSyncEnd += dy; 1228 mode->VTotal += dy; 1229 1230 mode->type = M_T_DEFAULT; 1231#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,2,0) 1232 /* Set up as user defined (ie fake that the mode has been named in the 1233 * Modes-list in the screen section; corrects cycling with CTRL-ALT-[-+] 1234 * when source mode has not been listed there.) 1235 */ 1236 mode->type |= M_T_USERDEF; 1237#endif 1238 1239 /* Set the VRefresh field (in order to make RandR use it for the rates). We 1240 * simply set this to the refresh rate for the CRT1 mode (since CRT2 will 1241 * mostly be LCD or TV anyway). 1242 */ 1243 mode->VRefresh = SiSCalcVRate(i); 1244 1245 if( ((mode->HDisplay * ((pScrn->bitsPerPixel + 7) / 8) * mode->VDisplay) > pSiS->maxxfbmem) || 1246 (mode->HDisplay > 4088) || 1247 (mode->VDisplay > 4096) ) { 1248 1249 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1250 "Skipped \"%s\" (%dx%d), not enough video RAM or beyond hardware specs\n", 1251 mode->name, mode->HDisplay, mode->VDisplay); 1252 free(mode->Private); 1253 free(mode); 1254 1255 return dest; 1256 } 1257 1258#ifdef SISXINERAMA 1259 if(srel != sisClone) { 1260 pSiS->AtLeastOneNonClone = TRUE; 1261 } 1262#endif 1263 1264 /* Now see if the resulting mode would be discarded as a "size" by the 1265 * RandR extension, and increase its clock by 1000 in case it does. 1266 */ 1267 if(dest) { 1268 DisplayModePtr t = dest; 1269 do { 1270 if((t->HDisplay == mode->HDisplay) && 1271 (t->VDisplay == mode->VDisplay) && 1272 ((int)(t->VRefresh + .5) == (int)(mode->VRefresh + .5))) { 1273 mode->VRefresh += 1000.0; 1274 } 1275 t = t->next; 1276 } while((t) && (t != dest)); 1277 } 1278 1279 /* Provide a fake but unique DotClock in order to trick the vidmode 1280 * extension to allow selecting among a number of modes whose merged result 1281 * looks identical but consists of different modes for CRT1 and CRT2 1282 */ 1283 mode->Clock = (int)(mode->VRefresh * 1000.0); 1284 1285 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1286 "Merged \"%s\" (%dx%d) and \"%s\" (%dx%d) to %dx%d (%d)%s\n", 1287 i->name, i->HDisplay, i->VDisplay, j->name, j->HDisplay, j->VDisplay, 1288 mode->HDisplay, mode->VDisplay, (int)mode->VRefresh, 1289 (srel == sisClone) ? " (Clone)" : ""); 1290 1291 mode->next = mode; 1292 mode->prev = mode; 1293 1294 if(dest) { 1295 mode->next = dest->next; /* Insert node after "dest" */ 1296 dest->next->prev = mode; 1297 mode->prev = dest; 1298 dest->next = mode; 1299 } 1300 1301 return mode; 1302} 1303 1304/* Helper function to find a mode from a given name 1305 * (Code base taken from mga driver) 1306 */ 1307static DisplayModePtr 1308SiSGetModeFromName(const char* str, DisplayModePtr i) 1309{ 1310 DisplayModePtr c = i; 1311 if(!i) return NULL; 1312 do { 1313 if(strcmp(str, c->name) == 0) return c; 1314 c = c->next; 1315 } while(c != i); 1316 return NULL; 1317} 1318 1319static DisplayModePtr 1320SiSFindWidestTallestMode(DisplayModePtr i, Bool tallest) 1321{ 1322 DisplayModePtr c = i, d = NULL; 1323 int max = 0; 1324 if(!i) return NULL; 1325 do { 1326 if(tallest) { 1327 if(c->VDisplay > max) { 1328 max = c->VDisplay; 1329 d = c; 1330 } 1331 } else { 1332 if(c->HDisplay > max) { 1333 max = c->HDisplay; 1334 d = c; 1335 } 1336 } 1337 c = c->next; 1338 } while(c != i); 1339 return d; 1340} 1341 1342static void 1343SiSFindWidestTallestCommonMode(DisplayModePtr i, DisplayModePtr j, Bool tallest, 1344 DisplayModePtr *a, DisplayModePtr *b) 1345{ 1346 DisplayModePtr c = i, d; 1347 int max = 0; 1348 Bool foundone; 1349 1350 (*a) = (*b) = NULL; 1351 1352 if(!i || !j) return; 1353 1354 do { 1355 d = j; 1356 foundone = FALSE; 1357 do { 1358 if( (c->HDisplay == d->HDisplay) && 1359 (c->VDisplay == d->VDisplay) ) { 1360 foundone = TRUE; 1361 break; 1362 } 1363 d = d->next; 1364 } while(d != j); 1365 if(foundone) { 1366 if(tallest) { 1367 if(c->VDisplay > max) { 1368 max = c->VDisplay; 1369 (*a) = c; 1370 (*b) = d; 1371 } 1372 } else { 1373 if(c->HDisplay > max) { 1374 max = c->HDisplay; 1375 (*a) = c; 1376 (*b) = d; 1377 } 1378 } 1379 } 1380 c = c->next; 1381 } while(c != i); 1382} 1383 1384static DisplayModePtr 1385SiSGenerateModeListFromLargestModes(ScrnInfoPtr pScrn, 1386 DisplayModePtr i, DisplayModePtr j, 1387 SiSScrn2Rel srel) 1388{ 1389#ifdef SISXINERAMA 1390 SISPtr pSiS = SISPTR(pScrn); 1391#endif 1392 DisplayModePtr mode1 = NULL; 1393 DisplayModePtr mode2 = NULL; 1394 DisplayModePtr mode3 = NULL; 1395 DisplayModePtr mode4 = NULL; 1396 DisplayModePtr result = NULL; 1397 1398#ifdef SISXINERAMA 1399 pSiS->AtLeastOneNonClone = FALSE; 1400#endif 1401 1402 /* Now build a default list of MetaModes. 1403 * - Non-clone: If the user enabled NonRectangular, we use the 1404 * largest mode for each CRT1 and CRT2. If not, we use the largest 1405 * common mode for CRT1 and CRT2 (if available). Additionally, and 1406 * regardless if the above, we produce a clone mode consisting of 1407 * the largest common mode (if available) in order to use DGA. 1408 * - Clone: If the (global) CRT2Position is Clone, we use the 1409 * largest common mode if available, otherwise the first two modes 1410 * in each list. 1411 */ 1412 1413 switch(srel) { 1414 case sisLeftOf: 1415 case sisRightOf: 1416 mode1 = SiSFindWidestTallestMode(i, FALSE); 1417 mode2 = SiSFindWidestTallestMode(j, FALSE); 1418 SiSFindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); 1419 break; 1420 case sisAbove: 1421 case sisBelow: 1422 mode1 = SiSFindWidestTallestMode(i, TRUE); 1423 mode2 = SiSFindWidestTallestMode(j, TRUE); 1424 SiSFindWidestTallestCommonMode(i, j, TRUE, &mode3, &mode4); 1425 break; 1426 case sisClone: 1427 SiSFindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); 1428 if(mode3 && mode4) { 1429 mode1 = mode3; 1430 mode2 = mode4; 1431 } else { 1432 mode1 = i; 1433 mode2 = j; 1434 } 1435 } 1436 1437 if(srel != sisClone) { 1438 if(mode3 && mode4 && !pSiS->NonRect) { 1439 mode1 = mode3; 1440 mode2 = mode2; 1441 } 1442 } 1443 1444 if(mode1 && mode2) { 1445 result = SiSCopyModeNLink(pScrn, result, mode1, mode2, srel); 1446 } 1447 1448 if(srel != sisClone) { 1449 if(mode3 && mode4) { 1450 result = SiSCopyModeNLink(pScrn, result, mode3, mode4, sisClone); 1451 } 1452 } 1453 1454 return result; 1455} 1456 1457/* Generate the merged-fb mode modelist 1458 * (Taken from mga driver) 1459 */ 1460static DisplayModePtr 1461SiSGenerateModeListFromMetaModes(ScrnInfoPtr pScrn, char* str, 1462 DisplayModePtr i, DisplayModePtr j, 1463 SiSScrn2Rel srel) 1464{ 1465#ifdef SISXINERAMA 1466 SISPtr pSiS = SISPTR(pScrn); 1467#endif 1468 char* strmode = str; 1469 char modename[256]; 1470 Bool gotdash = FALSE; 1471 char gotsep = 0; 1472 SiSScrn2Rel sr; 1473 DisplayModePtr mode1 = NULL; 1474 DisplayModePtr mode2 = NULL; 1475 DisplayModePtr result = NULL; 1476 int myslen; 1477 1478#ifdef SISXINERAMA 1479 pSiS->AtLeastOneNonClone = FALSE; 1480#endif 1481 1482 do { 1483 switch(*str) { 1484 case 0: 1485 case '-': 1486 case '+': 1487 case ' ': 1488 case ',': 1489 case ';': 1490 if(strmode != str) { 1491 1492 myslen = str - strmode; 1493 if(myslen > 255) myslen = 255; 1494 strncpy(modename, strmode, myslen); 1495 modename[myslen] = 0; 1496 1497 if(gotdash) { 1498 if(mode1 == NULL) { 1499 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1500 "Error parsing MetaModes parameter\n"); 1501 return NULL; 1502 } 1503 mode2 = SiSGetModeFromName(modename, j); 1504 if(!mode2) { 1505 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1506 "Mode \"%s\" is not a supported mode for CRT2\n", modename); 1507 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1508 "\t(Skipping metamode \"%s%c%s\")\n", mode1->name, gotsep, modename); 1509 mode1 = NULL; 1510 gotsep = 0; 1511 } 1512 } else { 1513 mode1 = SiSGetModeFromName(modename, i); 1514 if(!mode1) { 1515 char* tmps = str; 1516 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1517 "Mode \"%s\" is not a supported mode for CRT1\n", modename); 1518 while(*tmps == ' ' || *tmps == ';') tmps++; 1519 /* skip the next mode */ 1520 if(*tmps == '-' || *tmps == '+' || *tmps == ',') { 1521 tmps++; 1522 /* skip spaces */ 1523 while(*tmps == ' ' || *tmps == ';') tmps++; 1524 /* skip modename */ 1525 while(*tmps && *tmps != ' ' && *tmps != ';' && *tmps != '-' && *tmps != '+' && *tmps != ',') tmps++; 1526 myslen = tmps - strmode; 1527 if(myslen > 255) myslen = 255; 1528 strncpy(modename,strmode,myslen); 1529 modename[myslen] = 0; 1530 str = tmps - 1; 1531 } 1532 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1533 "\t(Skipping metamode \"%s\")\n", modename); 1534 mode1 = NULL; 1535 gotsep = 0; 1536 } 1537 } 1538 gotdash = FALSE; 1539 } 1540 strmode = str + 1; 1541 gotdash |= (*str == '-' || *str == '+' || *str == ','); 1542 if (*str == '-' || *str == '+' || *str == ',') 1543 gotsep = *str; 1544 1545 if(*str != 0) break; 1546 /* Fall through otherwise */ 1547 1548 default: 1549 if(!gotdash && mode1) { 1550 sr = srel; 1551 if(gotsep == '+') sr = sisClone; 1552 if(!mode2) { 1553 mode2 = SiSGetModeFromName(mode1->name, j); 1554 sr = sisClone; 1555 } 1556 if(!mode2) { 1557 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1558 "Mode \"%s\" is not a supported mode for CRT2\n", mode1->name); 1559 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1560 "\t(Skipping metamode \"%s\")\n", modename); 1561 mode1 = NULL; 1562 } else { 1563 result = SiSCopyModeNLink(pScrn, result, mode1, mode2, sr); 1564 mode1 = NULL; 1565 mode2 = NULL; 1566 } 1567 gotsep = 0; 1568 } 1569 break; 1570 1571 } 1572 1573 } while(*(str++) != 0); 1574 1575 return result; 1576} 1577 1578static DisplayModePtr 1579SiSGenerateModeList(ScrnInfoPtr pScrn, char* str, 1580 DisplayModePtr i, DisplayModePtr j, 1581 SiSScrn2Rel srel) 1582{ 1583 SISPtr pSiS = SISPTR(pScrn); 1584 1585 if(str != NULL) { 1586 return(SiSGenerateModeListFromMetaModes(pScrn, str, i, j, srel)); 1587 } else { 1588 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1589 "No MetaModes given, linking %s modes by default\n", 1590 (srel == sisClone) ? "largest common" : 1591 (pSiS->NonRect ? 1592 (((srel == sisLeftOf) || (srel == sisRightOf)) ? "widest" : "tallest") 1593 : 1594 (((srel == sisLeftOf) || (srel == sisRightOf)) ? "widest common" : "tallest common")) ); 1595 return(SiSGenerateModeListFromLargestModes(pScrn, i, j, srel)); 1596 } 1597} 1598 1599static void 1600SiSRecalcDefaultVirtualSize(ScrnInfoPtr pScrn) 1601{ 1602 SISPtr pSiS = SISPTR(pScrn); 1603 DisplayModePtr mode, bmode; 1604 int maxh, maxv; 1605 static const char *str = "MergedFB: Virtual %s %d\n"; 1606 static const char *errstr = "Virtual %s to small for given CRT2Position offset\n"; 1607 1608 mode = bmode = pScrn->modes; 1609 maxh = maxv = 0; 1610 do { 1611 if(mode->HDisplay > maxh) maxh = mode->HDisplay; 1612 if(mode->VDisplay > maxv) maxv = mode->VDisplay; 1613 mode = mode->next; 1614 } while(mode != bmode); 1615 1616 maxh += pSiS->CRT1XOffs + pSiS->CRT2XOffs; 1617 maxv += pSiS->CRT1YOffs + pSiS->CRT2YOffs; 1618 1619 if(!(pScrn->display->virtualX)) { 1620 if(maxh > 4088) { 1621 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1622 "Virtual width with CRT2Position offset beyond hardware specs\n"); 1623 pSiS->CRT1XOffs = pSiS->CRT2XOffs = 0; 1624 maxh -= (pSiS->CRT1XOffs + pSiS->CRT2XOffs); 1625 } 1626 pScrn->virtualX = maxh; 1627 pScrn->displayWidth = maxh; 1628 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "width", maxh); 1629 } else { 1630 if(maxh < pScrn->display->virtualX) { 1631 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "width"); 1632 pSiS->CRT1XOffs = pSiS->CRT2XOffs = 0; 1633 } 1634 } 1635 1636 if(!(pScrn->display->virtualY)) { 1637 pScrn->virtualY = maxv; 1638 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "height", maxv); 1639 } else { 1640 if(maxv < pScrn->display->virtualY) { 1641 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "height"); 1642 pSiS->CRT1YOffs = pSiS->CRT2YOffs = 0; 1643 } 1644 } 1645} 1646 1647static void 1648SiSMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, SiSScrn2Rel srel) 1649{ 1650 SISPtr pSiS = SISPTR(pScrn1); 1651 MessageType from = X_DEFAULT; 1652 xf86MonPtr DDC1 = (xf86MonPtr)(pScrn1->monitor->DDC); 1653 xf86MonPtr DDC2 = (xf86MonPtr)(pScrn2->monitor->DDC); 1654 int ddcWidthmm = 0, ddcHeightmm = 0; 1655 const char *dsstr = "MergedFB: Display dimensions: (%d, %d) mm\n"; 1656 1657 /* This sets the DPI for MergedFB mode. The problem is that 1658 * this can never be exact, because the output devices may 1659 * have different dimensions. This function tries to compromise 1660 * through a few assumptions, and it just calculates an average DPI 1661 * value for both monitors. 1662 */ 1663 1664 /* Given DisplaySize should regard BOTH monitors */ 1665 pScrn1->widthmm = pScrn1->monitor->widthmm; 1666 pScrn1->heightmm = pScrn1->monitor->heightmm; 1667 1668 /* Get DDC display size; if only either CRT1 or CRT2 provided these, 1669 * assume equal dimensions for both, otherwise add dimensions 1670 */ 1671 if( (DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) && 1672 (DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0)) ) { 1673 ddcWidthmm = max(DDC1->features.hsize, DDC2->features.hsize) * 10; 1674 ddcHeightmm = max(DDC1->features.vsize, DDC2->features.vsize) * 10; 1675 switch(srel) { 1676 case sisLeftOf: 1677 case sisRightOf: 1678 ddcWidthmm = (DDC1->features.hsize + DDC2->features.hsize) * 10; 1679 break; 1680 case sisAbove: 1681 case sisBelow: 1682 ddcHeightmm = (DDC1->features.vsize + DDC2->features.vsize) * 10; 1683 default: 1684 break; 1685 } 1686 } else if(DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) { 1687 ddcWidthmm = DDC1->features.hsize * 10; 1688 ddcHeightmm = DDC1->features.vsize * 10; 1689 switch(srel) { 1690 case sisLeftOf: 1691 case sisRightOf: 1692 ddcWidthmm *= 2; 1693 break; 1694 case sisAbove: 1695 case sisBelow: 1696 ddcHeightmm *= 2; 1697 default: 1698 break; 1699 } 1700 } else if(DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0) ) { 1701 ddcWidthmm = DDC2->features.hsize * 10; 1702 ddcHeightmm = DDC2->features.vsize * 10; 1703 switch(srel) { 1704 case sisLeftOf: 1705 case sisRightOf: 1706 ddcWidthmm *= 2; 1707 break; 1708 case sisAbove: 1709 case sisBelow: 1710 ddcHeightmm *= 2; 1711 default: 1712 break; 1713 } 1714 } 1715 1716 if(monitorResolution > 0) { 1717 1718 /* Set command line given values (overrules given options) */ 1719 pScrn1->xDpi = monitorResolution; 1720 pScrn1->yDpi = monitorResolution; 1721 from = X_CMDLINE; 1722 1723 } else if(pSiS->MergedFBXDPI) { 1724 1725 /* Set option-wise given values (overrule DisplaySize) */ 1726 pScrn1->xDpi = pSiS->MergedFBXDPI; 1727 pScrn1->yDpi = pSiS->MergedFBYDPI; 1728 from = X_CONFIG; 1729 1730 } else if(pScrn1->widthmm > 0 || pScrn1->heightmm > 0) { 1731 1732 /* Set values calculated from given DisplaySize */ 1733 from = X_CONFIG; 1734 if(pScrn1->widthmm > 0) { 1735 pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm); 1736 } 1737 if(pScrn1->heightmm > 0) { 1738 pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm); 1739 } 1740 xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, pScrn1->widthmm, pScrn1->heightmm); 1741 1742 } else if(ddcWidthmm && ddcHeightmm) { 1743 1744 /* Set values from DDC-provided display size */ 1745 from = X_PROBED; 1746 xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, ddcWidthmm, ddcHeightmm ); 1747 pScrn1->widthmm = ddcWidthmm; 1748 pScrn1->heightmm = ddcHeightmm; 1749 if(pScrn1->widthmm > 0) { 1750 pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm); 1751 } 1752 if(pScrn1->heightmm > 0) { 1753 pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm); 1754 } 1755 1756 } else { 1757 1758 pScrn1->xDpi = pScrn1->yDpi = DEFAULT_DPI; 1759 1760 } 1761 1762 /* Sanity check */ 1763 if(pScrn1->xDpi > 0 && pScrn1->yDpi <= 0) 1764 pScrn1->yDpi = pScrn1->xDpi; 1765 if(pScrn1->yDpi > 0 && pScrn1->xDpi <= 0) 1766 pScrn1->xDpi = pScrn1->yDpi; 1767 1768 pScrn2->xDpi = pScrn1->xDpi; 1769 pScrn2->yDpi = pScrn1->yDpi; 1770 1771 xf86DrvMsg(pScrn1->scrnIndex, from, "MergedFB: DPI set to (%d, %d)\n", 1772 pScrn1->xDpi, pScrn1->yDpi); 1773} 1774 1775/* Pseudo-Xinerama extension for MergedFB mode */ 1776#ifdef SISXINERAMA 1777 1778static void 1779SiSUpdateXineramaScreenInfo(ScrnInfoPtr pScrn1) 1780{ 1781 SISPtr pSiS = SISPTR(pScrn1); 1782 int crt1scrnnum = 0, crt2scrnnum = 1; 1783 int x1=0, x2=0, y1=0, y2=0, h1=0, h2=0, w1=0, w2=0; 1784 int realvirtX, realvirtY; 1785 DisplayModePtr currentMode, firstMode; 1786 Bool infochanged = FALSE; 1787 Bool usenonrect = pSiS->NonRect; 1788 static const char rectxine[] = "\t... setting up rectangular Xinerama layout\n"; 1789 1790 pSiS->MBXNR1XMAX = pSiS->MBXNR1YMAX = pSiS->MBXNR2XMAX = pSiS->MBXNR2YMAX = 65536; 1791 pSiS->HaveNonRect = pSiS->HaveOffsRegions = FALSE; 1792 1793 if(!pSiS->MergedFB) return; 1794 1795 if(SiSnoPanoramiXExtension) return; 1796 1797 if(!SiSXineramadataPtr) return; 1798 1799 if(pSiS->CRT2IsScrn0) { 1800 crt1scrnnum = 1; 1801 crt2scrnnum = 0; 1802 } 1803 1804 /* Attention: Usage of RandR may lead to virtual X and Y dimensions 1805 * actually smaller than our MetaModes. To avoid this, we calculate 1806 * the maxCRT fields here (and not somewhere else, like in CopyNLink) 1807 * 1808 * *** Note: RandR is disabled if one of CRTxxOffs is non-zero. 1809 */ 1810 1811 /* "Real" virtual: Virtual without the Offset */ 1812 realvirtX = pScrn1->virtualX - pSiS->CRT1XOffs - pSiS->CRT2XOffs; 1813 realvirtY = pScrn1->virtualY - pSiS->CRT1YOffs - pSiS->CRT2YOffs; 1814 1815 if((pSiS->SiSXineramaVX != pScrn1->virtualX) || (pSiS->SiSXineramaVY != pScrn1->virtualY)) { 1816 1817 if(!(pScrn1->modes)) return; 1818 1819 pSiS->maxCRT1_X1 = pSiS->maxCRT1_X2 = 0; 1820 pSiS->maxCRT1_Y1 = pSiS->maxCRT1_Y2 = 0; 1821 pSiS->maxCRT2_X1 = pSiS->maxCRT2_X2 = 0; 1822 pSiS->maxCRT2_Y1 = pSiS->maxCRT2_Y2 = 0; 1823 pSiS->maxClone_X1 = pSiS->maxClone_X2 = 0; 1824 pSiS->maxClone_Y1 = pSiS->maxClone_Y2 = 0; 1825 1826 currentMode = firstMode = pScrn1->modes; 1827 1828 do { 1829 1830 DisplayModePtr p = currentMode->next; 1831 DisplayModePtr i = ((SiSMergedDisplayModePtr)currentMode->Private)->CRT1; 1832 DisplayModePtr j = ((SiSMergedDisplayModePtr)currentMode->Private)->CRT2; 1833 SiSScrn2Rel srel = ((SiSMergedDisplayModePtr)currentMode->Private)->CRT2Position; 1834 1835 if((currentMode->HDisplay <= realvirtX) && (currentMode->VDisplay <= realvirtY) && 1836 (i->HDisplay <= realvirtX) && (j->HDisplay <= realvirtX) && 1837 (i->VDisplay <= realvirtY) && (j->VDisplay <= realvirtY)) { 1838 1839 if(srel != sisClone) { 1840 if(pSiS->maxCRT1_X1 == i->HDisplay) { 1841 if(pSiS->maxCRT1_X2 < j->HDisplay) { 1842 pSiS->maxCRT1_X2 = j->HDisplay; /* Widest CRT2 mode displayed with widest CRT1 mode */ 1843 } 1844 } else if(pSiS->maxCRT1_X1 < i->HDisplay) { 1845 pSiS->maxCRT1_X1 = i->HDisplay; /* Widest CRT1 mode */ 1846 pSiS->maxCRT1_X2 = j->HDisplay; 1847 } 1848 if(pSiS->maxCRT2_X2 == j->HDisplay) { 1849 if(pSiS->maxCRT2_X1 < i->HDisplay) { 1850 pSiS->maxCRT2_X1 = i->HDisplay; /* Widest CRT1 mode displayed with widest CRT2 mode */ 1851 } 1852 } else if(pSiS->maxCRT2_X2 < j->HDisplay) { 1853 pSiS->maxCRT2_X2 = j->HDisplay; /* Widest CRT2 mode */ 1854 pSiS->maxCRT2_X1 = i->HDisplay; 1855 } 1856 if(pSiS->maxCRT1_Y1 == i->VDisplay) { /* Same as above, but tallest instead of widest */ 1857 if(pSiS->maxCRT1_Y2 < j->VDisplay) { 1858 pSiS->maxCRT1_Y2 = j->VDisplay; 1859 } 1860 } else if(pSiS->maxCRT1_Y1 < i->VDisplay) { 1861 pSiS->maxCRT1_Y1 = i->VDisplay; 1862 pSiS->maxCRT1_Y2 = j->VDisplay; 1863 } 1864 if(pSiS->maxCRT2_Y2 == j->VDisplay) { 1865 if(pSiS->maxCRT2_Y1 < i->VDisplay) { 1866 pSiS->maxCRT2_Y1 = i->VDisplay; 1867 } 1868 } else if(pSiS->maxCRT2_Y2 < j->VDisplay) { 1869 pSiS->maxCRT2_Y2 = j->VDisplay; 1870 pSiS->maxCRT2_Y1 = i->VDisplay; 1871 } 1872 } else { 1873 if(pSiS->maxClone_X1 < i->HDisplay) { 1874 pSiS->maxClone_X1 = i->HDisplay; 1875 } 1876 if(pSiS->maxClone_X2 < j->HDisplay) { 1877 pSiS->maxClone_X2 = j->HDisplay; 1878 } 1879 if(pSiS->maxClone_Y1 < i->VDisplay) { 1880 pSiS->maxClone_Y1 = i->VDisplay; 1881 } 1882 if(pSiS->maxClone_Y2 < j->VDisplay) { 1883 pSiS->maxClone_Y2 = j->VDisplay; 1884 } 1885 } 1886 } 1887 currentMode = p; 1888 1889 } while((currentMode) && (currentMode != firstMode)); 1890 1891 pSiS->SiSXineramaVX = pScrn1->virtualX; 1892 pSiS->SiSXineramaVY = pScrn1->virtualY; 1893 infochanged = TRUE; 1894 1895 } 1896 1897 if((usenonrect) && (pSiS->CRT2Position != sisClone) && pSiS->maxCRT1_X1) { 1898 switch(pSiS->CRT2Position) { 1899 case sisLeftOf: 1900 case sisRightOf: 1901 if((pSiS->maxCRT1_Y1 != realvirtY) && (pSiS->maxCRT2_Y2 != realvirtY)) { 1902 usenonrect = FALSE; 1903 } 1904 break; 1905 case sisAbove: 1906 case sisBelow: 1907 if((pSiS->maxCRT1_X1 != realvirtX) && (pSiS->maxCRT2_X2 != realvirtX)) { 1908 usenonrect = FALSE; 1909 } 1910 break; 1911 case sisClone: 1912 break; 1913 } 1914 if(infochanged && !usenonrect) { 1915 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 1916 "Virtual screen size does not match maximum display modes...\n"); 1917 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, "%s", rectxine); 1918 1919 } 1920 } else if(infochanged && usenonrect) { 1921 usenonrect = FALSE; 1922 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 1923 "Only clone modes available for this virtual screen size...\n"); 1924 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, "%s", rectxine); 1925 } 1926 1927 if(pSiS->maxCRT1_X1) { /* Means we have at least one non-clone mode */ 1928 switch(pSiS->CRT2Position) { 1929 case sisLeftOf: 1930 x1 = min(pSiS->maxCRT1_X2, pScrn1->virtualX - pSiS->maxCRT1_X1); 1931 if(x1 < 0) x1 = 0; 1932 y1 = pSiS->CRT1YOffs; 1933 w1 = pScrn1->virtualX - x1; 1934 h1 = realvirtY; 1935 if((usenonrect) && (pSiS->maxCRT1_Y1 != realvirtY)) { 1936 h1 = pSiS->MBXNR1YMAX = pSiS->maxCRT1_Y1; 1937 pSiS->NonRectDead.x0 = x1; 1938 pSiS->NonRectDead.x1 = x1 + w1 - 1; 1939 pSiS->NonRectDead.y0 = y1 + h1; 1940 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 1941 pSiS->HaveNonRect = TRUE; 1942 } 1943 x2 = 0; 1944 y2 = pSiS->CRT2YOffs; 1945 w2 = max(pSiS->maxCRT2_X2, pScrn1->virtualX - pSiS->maxCRT2_X1); 1946 if(w2 > pScrn1->virtualX) w2 = pScrn1->virtualX; 1947 h2 = realvirtY; 1948 if((usenonrect) && (pSiS->maxCRT2_Y2 != realvirtY)) { 1949 h2 = pSiS->MBXNR2YMAX = pSiS->maxCRT2_Y2; 1950 pSiS->NonRectDead.x0 = x2; 1951 pSiS->NonRectDead.x1 = x2 + w2 - 1; 1952 pSiS->NonRectDead.y0 = y2 + h2; 1953 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 1954 pSiS->HaveNonRect = TRUE; 1955 } 1956 break; 1957 case sisRightOf: 1958 x1 = 0; 1959 y1 = pSiS->CRT1YOffs; 1960 w1 = max(pSiS->maxCRT1_X1, pScrn1->virtualX - pSiS->maxCRT1_X2); 1961 if(w1 > pScrn1->virtualX) w1 = pScrn1->virtualX; 1962 h1 = realvirtY; 1963 if((usenonrect) && (pSiS->maxCRT1_Y1 != realvirtY)) { 1964 h1 = pSiS->MBXNR1YMAX = pSiS->maxCRT1_Y1; 1965 pSiS->NonRectDead.x0 = x1; 1966 pSiS->NonRectDead.x1 = x1 + w1 - 1; 1967 pSiS->NonRectDead.y0 = y1 + h1; 1968 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 1969 pSiS->HaveNonRect = TRUE; 1970 } 1971 x2 = min(pSiS->maxCRT2_X1, pScrn1->virtualX - pSiS->maxCRT2_X2); 1972 if(x2 < 0) x2 = 0; 1973 y2 = pSiS->CRT2YOffs; 1974 w2 = pScrn1->virtualX - x2; 1975 h2 = realvirtY; 1976 if((usenonrect) && (pSiS->maxCRT2_Y2 != realvirtY)) { 1977 h2 = pSiS->MBXNR2YMAX = pSiS->maxCRT2_Y2; 1978 pSiS->NonRectDead.x0 = x2; 1979 pSiS->NonRectDead.x1 = x2 + w2 - 1; 1980 pSiS->NonRectDead.y0 = y2 + h2; 1981 pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 1982 pSiS->HaveNonRect = TRUE; 1983 } 1984 break; 1985 case sisAbove: 1986 x1 = pSiS->CRT1XOffs; 1987 y1 = min(pSiS->maxCRT1_Y2, pScrn1->virtualY - pSiS->maxCRT1_Y1); 1988 if(y1 < 0) y1 = 0; 1989 w1 = realvirtX; 1990 h1 = pScrn1->virtualY - y1; 1991 if((usenonrect) && (pSiS->maxCRT1_X1 != realvirtX)) { 1992 w1 = pSiS->MBXNR1XMAX = pSiS->maxCRT1_X1; 1993 pSiS->NonRectDead.x0 = x1 + w1; 1994 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 1995 pSiS->NonRectDead.y0 = y1; 1996 pSiS->NonRectDead.y1 = y1 + h1 - 1; 1997 pSiS->HaveNonRect = TRUE; 1998 } 1999 x2 = pSiS->CRT2XOffs; 2000 y2 = 0; 2001 w2 = realvirtX; 2002 h2 = max(pSiS->maxCRT2_Y2, pScrn1->virtualY - pSiS->maxCRT2_Y1); 2003 if(h2 > pScrn1->virtualY) h2 = pScrn1->virtualY; 2004 if((usenonrect) && (pSiS->maxCRT2_X2 != realvirtX)) { 2005 w2 = pSiS->MBXNR2XMAX = pSiS->maxCRT2_X2; 2006 pSiS->NonRectDead.x0 = x2 + w2; 2007 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 2008 pSiS->NonRectDead.y0 = y2; 2009 pSiS->NonRectDead.y1 = y2 + h2 - 1; 2010 pSiS->HaveNonRect = TRUE; 2011 } 2012 break; 2013 case sisBelow: 2014 x1 = pSiS->CRT1XOffs; 2015 y1 = 0; 2016 w1 = realvirtX; 2017 h1 = max(pSiS->maxCRT1_Y1, pScrn1->virtualY - pSiS->maxCRT1_Y2); 2018 if(h1 > pScrn1->virtualY) h1 = pScrn1->virtualY; 2019 if((usenonrect) && (pSiS->maxCRT1_X1 != realvirtX)) { 2020 w1 = pSiS->MBXNR1XMAX = pSiS->maxCRT1_X1; 2021 pSiS->NonRectDead.x0 = x1 + w1; 2022 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 2023 pSiS->NonRectDead.y0 = y1; 2024 pSiS->NonRectDead.y1 = y1 + h1 - 1; 2025 pSiS->HaveNonRect = TRUE; 2026 } 2027 x2 = pSiS->CRT2XOffs; 2028 y2 = min(pSiS->maxCRT2_Y1, pScrn1->virtualY - pSiS->maxCRT2_Y2); 2029 if(y2 < 0) y2 = 0; 2030 w2 = realvirtX; 2031 h2 = pScrn1->virtualY - y2; 2032 if((usenonrect) && (pSiS->maxCRT2_X2 != realvirtX)) { 2033 w2 = pSiS->MBXNR2XMAX = pSiS->maxCRT2_X2; 2034 pSiS->NonRectDead.x0 = x2 + w2; 2035 pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 2036 pSiS->NonRectDead.y0 = y2; 2037 pSiS->NonRectDead.y1 = y2 + h2 - 1; 2038 pSiS->HaveNonRect = TRUE; 2039 } 2040 default: 2041 break; 2042 } 2043 2044 switch(pSiS->CRT2Position) { 2045 case sisLeftOf: 2046 case sisRightOf: 2047 if(pSiS->CRT1YOffs) { 2048 pSiS->OffDead1.x0 = x1; 2049 pSiS->OffDead1.x1 = x1 + w1 - 1; 2050 pSiS->OffDead1.y0 = 0; 2051 pSiS->OffDead1.y1 = y1 - 1; 2052 pSiS->OffDead2.x0 = x2; 2053 pSiS->OffDead2.x1 = x2 + w2 - 1; 2054 pSiS->OffDead2.y0 = y2 + h2; 2055 pSiS->OffDead2.y1 = pScrn1->virtualY - 1; 2056 pSiS->HaveOffsRegions = TRUE; 2057 } else if(pSiS->CRT2YOffs) { 2058 pSiS->OffDead1.x0 = x2; 2059 pSiS->OffDead1.x1 = x2 + w2 - 1; 2060 pSiS->OffDead1.y0 = 0; 2061 pSiS->OffDead1.y1 = y2 - 1; 2062 pSiS->OffDead2.x0 = x1; 2063 pSiS->OffDead2.x1 = x1 + w1 - 1; 2064 pSiS->OffDead2.y0 = y1 + h1; 2065 pSiS->OffDead2.y1 = pScrn1->virtualY - 1; 2066 pSiS->HaveOffsRegions = TRUE; 2067 } 2068 break; 2069 case sisAbove: 2070 case sisBelow: 2071 if(pSiS->CRT1XOffs) { 2072 pSiS->OffDead1.x0 = x2 + w2; 2073 pSiS->OffDead1.x1 = pScrn1->virtualX - 1; 2074 pSiS->OffDead1.y0 = y2; 2075 pSiS->OffDead1.y1 = y2 + h2 - 1; 2076 pSiS->OffDead2.x0 = 0; 2077 pSiS->OffDead2.x1 = x1 - 1; 2078 pSiS->OffDead2.y0 = y1; 2079 pSiS->OffDead2.y1 = y1 + h1 - 1; 2080 pSiS->HaveOffsRegions = TRUE; 2081 } else if(pSiS->CRT2XOffs) { 2082 pSiS->OffDead1.x0 = x1 + w1; 2083 pSiS->OffDead1.x1 = pScrn1->virtualX - 1; 2084 pSiS->OffDead1.y0 = y1; 2085 pSiS->OffDead1.y1 = y1 + h1 - 1; 2086 pSiS->OffDead2.x0 = 0; 2087 pSiS->OffDead2.x1 = x2 - 1; 2088 pSiS->OffDead2.y0 = y2; 2089 pSiS->OffDead2.y1 = y2 + h2 - 1; 2090 pSiS->HaveOffsRegions = TRUE; 2091 } 2092 default: 2093 break; 2094 } 2095 2096 } else { /* Only clone-modes left */ 2097 2098 x1 = x2 = 0; 2099 y1 = y2 = 0; 2100 w1 = w2 = max(pSiS->maxClone_X1, pSiS->maxClone_X2); 2101 h1 = h2 = max(pSiS->maxClone_Y1, pSiS->maxClone_Y2); 2102 2103 } 2104 2105 SiSXineramadataPtr[crt1scrnnum].x = x1; 2106 SiSXineramadataPtr[crt1scrnnum].y = y1; 2107 SiSXineramadataPtr[crt1scrnnum].width = w1; 2108 SiSXineramadataPtr[crt1scrnnum].height = h1; 2109 SiSXineramadataPtr[crt2scrnnum].x = x2; 2110 SiSXineramadataPtr[crt2scrnnum].y = y2; 2111 SiSXineramadataPtr[crt2scrnnum].width = w2; 2112 SiSXineramadataPtr[crt2scrnnum].height = h2; 2113 2114 if(infochanged) { 2115 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2116 "Pseudo-Xinerama: CRT1 (Screen %d) (%d,%d)-(%d,%d)\n", 2117 crt1scrnnum, x1, y1, w1+x1-1, h1+y1-1); 2118 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2119 "Pseudo-Xinerama: CRT2 (Screen %d) (%d,%d)-(%d,%d)\n", 2120 crt2scrnnum, x2, y2, w2+x2-1, h2+y2-1); 2121 if(pSiS->HaveNonRect) { 2122 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2123 "Pseudo-Xinerama: Inaccessible area (%d,%d)-(%d,%d)\n", 2124 pSiS->NonRectDead.x0, pSiS->NonRectDead.y0, 2125 pSiS->NonRectDead.x1, pSiS->NonRectDead.y1); 2126 } 2127 if(pSiS->HaveOffsRegions) { 2128 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2129 "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", 2130 pSiS->OffDead1.x0, pSiS->OffDead1.y0, 2131 pSiS->OffDead1.x1, pSiS->OffDead1.y1); 2132 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2133 "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", 2134 pSiS->OffDead2.x0, pSiS->OffDead2.y0, 2135 pSiS->OffDead2.x1, pSiS->OffDead2.y1); 2136 } 2137 if(pSiS->HaveNonRect || pSiS->HaveOffsRegions) { 2138 xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 2139 "Mouse restriction for inaccessible areas is %s\n", 2140 pSiS->MouseRestrictions ? "enabled" : "disabled"); 2141 } 2142 } 2143} 2144 2145/* Proc */ 2146 2147int 2148SiSProcXineramaQueryVersion(ClientPtr client) 2149{ 2150 xPanoramiXQueryVersionReply rep; 2151#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 2152 register int n; 2153#endif 2154 2155 REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq); 2156 rep.type = X_Reply; 2157 rep.length = 0; 2158 rep.sequenceNumber = client->sequence; 2159 rep.majorVersion = SIS_XINERAMA_MAJOR_VERSION; 2160 rep.minorVersion = SIS_XINERAMA_MINOR_VERSION; 2161 if(client->swapped) { 2162 _swaps(&rep.sequenceNumber, n); 2163 _swapl(&rep.length, n); 2164 _swaps(&rep.majorVersion, n); 2165 _swaps(&rep.minorVersion, n); 2166 } 2167 WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *)&rep); 2168 return (client->noClientException); 2169} 2170 2171int 2172SiSProcXineramaGetState(ClientPtr client) 2173{ 2174 REQUEST(xPanoramiXGetStateReq); 2175 WindowPtr pWin; 2176 xPanoramiXGetStateReply rep; 2177#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 2178 register int n; 2179#endif 2180 int rc; 2181 2182 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); 2183 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 2184 if (rc != Success) 2185 return rc; 2186 2187 rep.type = X_Reply; 2188 rep.length = 0; 2189 rep.sequenceNumber = client->sequence; 2190 rep.state = !SiSnoPanoramiXExtension; 2191 if(client->swapped) { 2192 _swaps (&rep.sequenceNumber, n); 2193 _swapl (&rep.length, n); 2194 } 2195 WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *)&rep); 2196 return client->noClientException; 2197} 2198 2199int 2200SiSProcXineramaGetScreenCount(ClientPtr client) 2201{ 2202 REQUEST(xPanoramiXGetScreenCountReq); 2203 WindowPtr pWin; 2204 xPanoramiXGetScreenCountReply rep; 2205#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 2206 register int n; 2207#endif 2208 int rc; 2209 2210 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); 2211 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 2212 if (rc != Success) 2213 return rc; 2214 2215 rep.type = X_Reply; 2216 rep.length = 0; 2217 rep.sequenceNumber = client->sequence; 2218 rep.ScreenCount = SiSXineramaNumScreens; 2219 if(client->swapped) { 2220 _swaps(&rep.sequenceNumber, n); 2221 _swapl(&rep.length, n); 2222 } 2223 WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep); 2224 return client->noClientException; 2225} 2226 2227int 2228SiSProcXineramaGetScreenSize(ClientPtr client) 2229{ 2230 REQUEST(xPanoramiXGetScreenSizeReq); 2231 WindowPtr pWin; 2232 xPanoramiXGetScreenSizeReply rep; 2233#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 2234 register int n; 2235#endif 2236 int rc; 2237 2238 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); 2239 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 2240 if (rc != Success) 2241 return rc; 2242 2243 rep.type = X_Reply; 2244 rep.length = 0; 2245 rep.sequenceNumber = client->sequence; 2246 rep.width = SiSXineramadataPtr[stuff->screen].width; 2247 rep.height = SiSXineramadataPtr[stuff->screen].height; 2248 if(client->swapped) { 2249 _swaps(&rep.sequenceNumber, n); 2250 _swapl(&rep.length, n); 2251 _swapl(&rep.width, n); 2252 _swapl(&rep.height, n); 2253 } 2254 WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep); 2255 return client->noClientException; 2256} 2257 2258int 2259SiSProcXineramaIsActive(ClientPtr client) 2260{ 2261 xXineramaIsActiveReply rep; 2262 2263 REQUEST_SIZE_MATCH(xXineramaIsActiveReq); 2264 2265 rep.type = X_Reply; 2266 rep.length = 0; 2267 rep.sequenceNumber = client->sequence; 2268 rep.state = !SiSnoPanoramiXExtension; 2269 if(client->swapped) { 2270#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 2271 register int n; 2272#endif 2273 _swaps(&rep.sequenceNumber, n); 2274 _swapl(&rep.length, n); 2275 _swapl(&rep.state, n); 2276 } 2277 WriteToClient(client, sizeof(xXineramaIsActiveReply), (char *) &rep); 2278 return client->noClientException; 2279} 2280 2281int 2282SiSProcXineramaQueryScreens(ClientPtr client) 2283{ 2284 xXineramaQueryScreensReply rep; 2285 2286 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); 2287 2288 rep.type = X_Reply; 2289 rep.sequenceNumber = client->sequence; 2290 rep.number = (SiSnoPanoramiXExtension) ? 0 : SiSXineramaNumScreens; 2291 rep.length = rep.number * sz_XineramaScreenInfo >> 2; 2292 if(client->swapped) { 2293#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 2294 register int n; 2295#endif 2296 _swaps(&rep.sequenceNumber, n); 2297 _swapl(&rep.length, n); 2298 _swapl(&rep.number, n); 2299 } 2300 WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *)&rep); 2301 2302 if(!SiSnoPanoramiXExtension) { 2303 xXineramaScreenInfo scratch; 2304 int i; 2305 2306 for(i = 0; i < SiSXineramaNumScreens; i++) { 2307 scratch.x_org = SiSXineramadataPtr[i].x; 2308 scratch.y_org = SiSXineramadataPtr[i].y; 2309 scratch.width = SiSXineramadataPtr[i].width; 2310 scratch.height = SiSXineramadataPtr[i].height; 2311 if(client->swapped) { 2312#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 2313 register int n; 2314#endif 2315 _swaps(&scratch.x_org, n); 2316 _swaps(&scratch.y_org, n); 2317 _swaps(&scratch.width, n); 2318 _swaps(&scratch.height, n); 2319 } 2320 WriteToClient(client, sz_XineramaScreenInfo, (char *)&scratch); 2321 } 2322 } 2323 2324 return client->noClientException; 2325} 2326 2327static int 2328SiSProcXineramaDispatch(ClientPtr client) 2329{ 2330 REQUEST(xReq); 2331 switch (stuff->data) { 2332 case X_PanoramiXQueryVersion: 2333 return SiSProcXineramaQueryVersion(client); 2334 case X_PanoramiXGetState: 2335 return SiSProcXineramaGetState(client); 2336 case X_PanoramiXGetScreenCount: 2337 return SiSProcXineramaGetScreenCount(client); 2338 case X_PanoramiXGetScreenSize: 2339 return SiSProcXineramaGetScreenSize(client); 2340 case X_XineramaIsActive: 2341 return SiSProcXineramaIsActive(client); 2342 case X_XineramaQueryScreens: 2343 return SiSProcXineramaQueryScreens(client); 2344 } 2345 return BadRequest; 2346} 2347 2348/* SProc */ 2349 2350static int 2351SiSSProcXineramaQueryVersion (ClientPtr client) 2352{ 2353 REQUEST(xPanoramiXQueryVersionReq); 2354#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 2355 register int n; 2356#endif 2357 _swaps(&stuff->length,n); 2358 REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); 2359 return SiSProcXineramaQueryVersion(client); 2360} 2361 2362static int 2363SiSSProcXineramaGetState(ClientPtr client) 2364{ 2365 REQUEST(xPanoramiXGetStateReq); 2366#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 2367 register int n; 2368#endif 2369 _swaps (&stuff->length, n); 2370 REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); 2371 return SiSProcXineramaGetState(client); 2372} 2373 2374static int 2375SiSSProcXineramaGetScreenCount(ClientPtr client) 2376{ 2377 REQUEST(xPanoramiXGetScreenCountReq); 2378#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 2379 register int n; 2380#endif 2381 _swaps (&stuff->length, n); 2382 REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); 2383 return SiSProcXineramaGetScreenCount(client); 2384} 2385 2386static int 2387SiSSProcXineramaGetScreenSize(ClientPtr client) 2388{ 2389 REQUEST(xPanoramiXGetScreenSizeReq); 2390#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 2391 register int n; 2392#endif 2393 _swaps (&stuff->length, n); 2394 REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); 2395 return SiSProcXineramaGetScreenSize(client); 2396} 2397 2398static int 2399SiSSProcXineramaIsActive(ClientPtr client) 2400{ 2401 REQUEST(xXineramaIsActiveReq); 2402#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 2403 register int n; 2404#endif 2405 _swaps (&stuff->length, n); 2406 REQUEST_SIZE_MATCH(xXineramaIsActiveReq); 2407 return SiSProcXineramaIsActive(client); 2408} 2409 2410static int 2411SiSSProcXineramaQueryScreens(ClientPtr client) 2412{ 2413 REQUEST(xXineramaQueryScreensReq); 2414#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 2415 register int n; 2416#endif 2417 _swaps (&stuff->length, n); 2418 REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); 2419 return SiSProcXineramaQueryScreens(client); 2420} 2421 2422int 2423SiSSProcXineramaDispatch(ClientPtr client) 2424{ 2425 REQUEST(xReq); 2426 switch (stuff->data) { 2427 case X_PanoramiXQueryVersion: 2428 return SiSSProcXineramaQueryVersion(client); 2429 case X_PanoramiXGetState: 2430 return SiSSProcXineramaGetState(client); 2431 case X_PanoramiXGetScreenCount: 2432 return SiSSProcXineramaGetScreenCount(client); 2433 case X_PanoramiXGetScreenSize: 2434 return SiSSProcXineramaGetScreenSize(client); 2435 case X_XineramaIsActive: 2436 return SiSSProcXineramaIsActive(client); 2437 case X_XineramaQueryScreens: 2438 return SiSSProcXineramaQueryScreens(client); 2439 } 2440 return BadRequest; 2441} 2442 2443static void 2444SiSXineramaResetProc(ExtensionEntry* extEntry) 2445{ 2446 /* Called by CloseDownExtensions() */ 2447 if(SiSXineramadataPtr) { 2448 free(SiSXineramadataPtr); 2449 SiSXineramadataPtr = NULL; 2450 } 2451} 2452 2453static void 2454SiSXineramaExtensionInit(ScrnInfoPtr pScrn) 2455{ 2456 SISPtr pSiS = SISPTR(pScrn); 2457 Bool success = FALSE; 2458 2459 if(!(SiSXineramadataPtr)) { 2460 2461 if(!pSiS->MergedFB) { 2462 SiSnoPanoramiXExtension = TRUE; 2463 pSiS->MouseRestrictions = FALSE; 2464 return; 2465 } 2466 2467#ifdef PANORAMIX 2468 if(!noPanoramiXExtension) { 2469 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2470 "Xinerama active, not initializing SiS Pseudo-Xinerama\n"); 2471 SiSnoPanoramiXExtension = TRUE; 2472 pSiS->MouseRestrictions = FALSE; 2473 return; 2474 } 2475#endif 2476 2477 if(SiSnoPanoramiXExtension) { 2478 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2479 "SiS Pseudo-Xinerama disabled\n"); 2480 pSiS->MouseRestrictions = FALSE; 2481 return; 2482 } 2483 2484 if(pSiS->CRT2Position == sisClone) { 2485 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2486 "Running MergedFB in Clone mode, SiS Pseudo-Xinerama disabled\n"); 2487 SiSnoPanoramiXExtension = TRUE; 2488 pSiS->MouseRestrictions = FALSE; 2489 return; 2490 } 2491 2492 if(!(pSiS->AtLeastOneNonClone)) { 2493 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2494 "Only Clone modes defined, SiS Pseudo-Xinerama disabled\n"); 2495 SiSnoPanoramiXExtension = TRUE; 2496 pSiS->MouseRestrictions = FALSE; 2497 return; 2498 } 2499 2500 SiSXineramaNumScreens = 2; 2501 2502 while(SiSXineramaGeneration != serverGeneration) { 2503 2504 pSiS->XineramaExtEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0, 2505 SiSProcXineramaDispatch, 2506 SiSSProcXineramaDispatch, 2507 SiSXineramaResetProc, 2508 StandardMinorOpcode); 2509 2510 if(!pSiS->XineramaExtEntry) break; 2511 2512 if(!(SiSXineramadataPtr = (SiSXineramaData *) 2513 calloc(SiSXineramaNumScreens, sizeof(SiSXineramaData)))) break; 2514 2515 SiSXineramaGeneration = serverGeneration; 2516 success = TRUE; 2517 } 2518 2519 if(!success) { 2520 SISErrorLog(pScrn, "Failed to initialize SiS Pseudo-Xinerama extension\n"); 2521 SiSnoPanoramiXExtension = TRUE; 2522 pSiS->MouseRestrictions = FALSE; 2523 return; 2524 } 2525 2526 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2527 "SiS Pseudo-Xinerama extension initialized\n"); 2528 2529 pSiS->SiSXineramaVX = 0; 2530 pSiS->SiSXineramaVY = 0; 2531 2532 } 2533 2534 SiSUpdateXineramaScreenInfo(pScrn); 2535 2536} 2537#endif /* End of PseudoXinerama */ 2538 2539static void 2540SiSFreeCRT2Structs(SISPtr pSiS) 2541{ 2542 if(pSiS->CRT2pScrn) { 2543 if(pSiS->CRT2pScrn->modes) { 2544 while(pSiS->CRT2pScrn->modes) 2545 xf86DeleteMode(&pSiS->CRT2pScrn->modes, pSiS->CRT2pScrn->modes); 2546 } 2547 if(pSiS->CRT2pScrn->monitor) { 2548 if(pSiS->CRT2pScrn->monitor->Modes) { 2549 while(pSiS->CRT2pScrn->monitor->Modes) 2550 xf86DeleteMode(&pSiS->CRT2pScrn->monitor->Modes, pSiS->CRT2pScrn->monitor->Modes); 2551 } 2552 if(pSiS->CRT2pScrn->monitor->DDC) free(pSiS->CRT2pScrn->monitor->DDC); 2553 free(pSiS->CRT2pScrn->monitor); 2554 } 2555 free(pSiS->CRT2pScrn); 2556 pSiS->CRT2pScrn = NULL; 2557 } 2558} 2559 2560#endif /* End of MergedFB helpers */ 2561 2562static xf86MonPtr 2563SiSInternalDDC(ScrnInfoPtr pScrn, int crtno) 2564{ 2565 SISPtr pSiS = SISPTR(pScrn); 2566 xf86MonPtr pMonitor = NULL; 2567 UShort temp = 0xffff, temp1, i, realcrtno = crtno; 2568 UChar buffer[256]; 2569 2570 /* If CRT1 is off, skip DDC */ 2571 if((pSiS->CRT1off) && (!crtno)) return NULL; 2572 2573 if(crtno) { 2574 if(pSiS->VBFlags & CRT2_LCD) realcrtno = 1; 2575 else if(pSiS->VBFlags & CRT2_VGA) realcrtno = 2; 2576 else return NULL; 2577 if(pSiS->SiS_Pr->DDCPortMixup) realcrtno = 0; 2578 } else { 2579 /* If CRT1 is LCDA, skip DDC (except 301C: DDC allowed, but uses CRT2 port!) */ 2580 if(pSiS->VBFlags & CRT1_LCDA) { 2581 if(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE) realcrtno = 1; 2582 else return NULL; 2583 } 2584 } 2585 2586 i = 3; /* Number of retrys */ 2587 do { 2588 temp1 = SiS_HandleDDC(pSiS->SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 2589 realcrtno, 0, &buffer[0], pSiS->VBFlags2); 2590 if((temp1) && (temp1 != 0xffff)) temp = temp1; 2591 } while((temp == 0xffff) && i--); 2592 if(temp != 0xffff) { 2593 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT%d DDC supported\n", crtno + 1); 2594 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT%d DDC level: %s%s%s%s\n", 2595 crtno + 1, 2596 (temp & 0x1a) ? "" : "[none of the supported]", 2597 (temp & 0x02) ? "2 " : "", 2598 (temp & 0x08) ? "D&P" : "", 2599 (temp & 0x10) ? "FPDI-2" : ""); 2600 if(temp & 0x02) { 2601 i = 5; /* Number of retrys */ 2602 do { 2603 temp = SiS_HandleDDC(pSiS->SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 2604 realcrtno, 1, &buffer[0], pSiS->VBFlags2); 2605 } while((temp) && i--); 2606 if(!temp) { 2607 if((pMonitor = xf86InterpretEDID(pScrn->scrnIndex, &buffer[0]))) { 2608 int tempvgagamma = 0, templcdgamma = 0; 2609 if(buffer[0x14] & 0x80) { 2610 templcdgamma = (buffer[0x17] + 100) * 10; 2611 } else { 2612 tempvgagamma = (buffer[0x17] + 100) * 10;; 2613 } 2614 if(crtno == 0) { 2615 if(tempvgagamma) pSiS->CRT1VGAMonitorGamma = tempvgagamma; 2616 /* LCD never via (demanded) CRT1 DDC port */ 2617 } else { 2618 if(tempvgagamma) pSiS->CRT2VGAMonitorGamma = tempvgagamma; 2619 if(templcdgamma) pSiS->CRT2LCDMonitorGamma = templcdgamma; 2620 } 2621 return(pMonitor); 2622 } else { 2623 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2624 "CRT%d DDC EDID corrupt\n", crtno + 1); 2625 } 2626 } else if(temp == 0xFFFE) { 2627 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2628 "CRT%d DDC data is from wrong device type (%s)\n", 2629 crtno + 1, 2630 (realcrtno == 1) ? "analog instead of digital" : "digital instead of analog"); 2631 } else { 2632 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2633 "CRT%d DDC reading failed\n", crtno + 1); 2634 } 2635 } else if(temp & 0x18) { 2636 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2637 "DDC for VESA D&P and FPDI-2 not supported yet.\n"); 2638 } 2639 } else { 2640 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2641 "CRT%d DDC probing failed\n", crtno + 1); 2642 } 2643 return(NULL); 2644} 2645 2646static xf86MonPtr 2647SiSDoPrivateDDC(ScrnInfoPtr pScrn, int *crtnum) 2648{ 2649 SISPtr pSiS = SISPTR(pScrn); 2650 2651#ifdef SISDUALHEAD 2652 if(pSiS->DualHeadMode) { 2653 if(pSiS->SecondHead) { 2654 *crtnum = 1; 2655 return(SiSInternalDDC(pScrn, 0)); 2656 } else { 2657 *crtnum = 2; 2658 return(SiSInternalDDC(pScrn, 1)); 2659 } 2660 } else 2661#endif 2662 if((pSiS->CRT1off) || (!pSiS->CRT1Detected)) { 2663 *crtnum = 2; 2664 return(SiSInternalDDC(pScrn, 1)); 2665 } else { 2666 *crtnum = 1; 2667 return(SiSInternalDDC(pScrn, 0)); 2668 } 2669} 2670 2671static void 2672SiSFindAspect(ScrnInfoPtr pScrn, xf86MonPtr pMonitor, int crtnum) 2673{ 2674 SISPtr pSiS = SISPTR(pScrn); 2675 int UseWide = 0; 2676 int aspect = 0; 2677 Bool fromdim = FALSE; 2678 2679 if((pSiS->VGAEngine == SIS_315_VGA) && (!DIGITAL(pMonitor->features.input_type))) { 2680 if(pMonitor->features.hsize && pMonitor->features.vsize) { 2681 aspect = (pMonitor->features.hsize * 1000) / pMonitor->features.vsize; 2682 if(aspect >= 1400) UseWide = 1; 2683 fromdim = TRUE; 2684 } else if((PREFERRED_TIMING_MODE(pMonitor->features.msc)) && 2685 (pMonitor->det_mon[0].type == DT)) { 2686 aspect = (pMonitor->det_mon[0].section.d_timings.h_active * 1000) / 2687 pMonitor->det_mon[0].section.d_timings.v_active; 2688 if(aspect >= 1400) UseWide = 1; 2689 } 2690 if(aspect) { 2691 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2692 "According to %s, CRT%d aspect ratio is %.2f:1 (%s)\n", 2693 fromdim ? "DDC size" : "preferred mode", 2694 crtnum, (float)aspect / 1000.0, UseWide ? "wide" : "normal"); 2695 } else { 2696 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2697 "Unable to determine CRT%d aspect ratio, assuming \"normal\"\n", 2698 crtnum); 2699 } 2700 } 2701 2702 if((crtnum == 1) && (pSiS->SiS_Pr->SiS_UseWide == -1)) { 2703 pSiS->SiS_Pr->SiS_UseWide = UseWide; 2704 } else if((crtnum == 2) && (pSiS->SiS_Pr->SiS_UseWideCRT2 == -1)) { 2705 pSiS->SiS_Pr->SiS_UseWideCRT2 = UseWide; 2706 } 2707} 2708 2709static Bool 2710SiSMakeOwnModeList(ScrnInfoPtr pScrn, Bool acceptcustommodes, Bool includelcdmodes, 2711 Bool isfordvi, Bool *havecustommodes, Bool fakecrt2modes, Bool IsForCRT2) 2712{ 2713 DisplayModePtr tempmode, delmode, mymodes; 2714 2715 if((mymodes = SiSBuildBuiltInModeList(pScrn, includelcdmodes, isfordvi, fakecrt2modes, IsForCRT2))) { 2716 if(!acceptcustommodes) { 2717 while(pScrn->monitor->Modes) 2718 xf86DeleteMode(&pScrn->monitor->Modes, pScrn->monitor->Modes); 2719 pScrn->monitor->Modes = mymodes; 2720 } else { 2721 delmode = pScrn->monitor->Modes; 2722 while(delmode) { 2723 if(delmode->type & M_T_DEFAULT) { 2724 tempmode = delmode->next; 2725 xf86DeleteMode(&pScrn->monitor->Modes, delmode); 2726 delmode = tempmode; 2727 } else { 2728 delmode = delmode->next; 2729 } 2730 } 2731 /* Link default modes AFTER user ones */ 2732 if((tempmode = pScrn->monitor->Modes)) { 2733 *havecustommodes = TRUE; 2734 while(tempmode) { 2735 if(!tempmode->next) break; 2736 else tempmode = tempmode->next; 2737 } 2738 tempmode->next = mymodes; 2739 mymodes->prev = tempmode; 2740 } else { 2741 pScrn->monitor->Modes = mymodes; 2742 } 2743#if 0 2744 pScrn->monitor->Modes = mymodes; 2745 while(mymodes) { 2746 if(!mymodes->next) break; 2747 else mymodes = mymodes->next; 2748 } 2749 mymodes->next = tempmode; 2750 if(tempmode) { 2751 tempmode->prev = mymodes; 2752 } 2753#endif 2754 } 2755 return TRUE; 2756 } else 2757 return FALSE; 2758} 2759 2760static void 2761SiSPrintModes(ScrnInfoPtr pScrn) 2762{ 2763 DisplayModePtr p; 2764 float hsync, refresh = 0.0; 2765 char *desc, *desc2, *prefix, *uprefix, *output; 2766 2767 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Virtual size is %dx%d " 2768 "(pitch %d)\n", pScrn->virtualX, pScrn->virtualY, 2769 pScrn->displayWidth); 2770 2771 if((p = pScrn->modes) == NULL) return; 2772 2773 do { 2774 desc = desc2 = ""; 2775 uprefix = " "; 2776 prefix = "Mode"; 2777 output = "For CRT device: "; 2778 if(p->HSync > 0.0) hsync = p->HSync; 2779 else if (p->HTotal > 0) hsync = (float)p->Clock / (float)p->HTotal; 2780 else hsync = 0.0; 2781 refresh = 0.0; 2782 if(p->VRefresh > 0.0) refresh = p->VRefresh; 2783 else if (p->HTotal > 0 && p->VTotal > 0) { 2784 refresh = p->Clock * 1000.0 / p->HTotal / p->VTotal; 2785 if(p->Flags & V_INTERLACE) refresh *= 2.0; 2786 if(p->Flags & V_DBLSCAN) refresh /= 2.0; 2787 if(p->VScan > 1) refresh /= p->VScan; 2788 } 2789 if(p->Flags & V_INTERLACE) desc = " (I)"; 2790 if(p->Flags & V_DBLSCAN) desc = " (D)"; 2791 if(p->VScan > 1) desc2 = " (VScan)"; 2792#ifdef M_T_USERDEF 2793 if(p->type & M_T_USERDEF) uprefix = "*"; 2794#endif 2795 if(p->type & M_T_BUILTIN) { 2796 prefix = "Built-in mode"; 2797 output = ""; 2798 } else if (p->type & M_T_DEFAULT) { 2799 prefix = "Default mode"; 2800 } else { 2801 output = ""; 2802 } 2803 2804 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2805 "%s%s \"%s\" (%dx%d) (%s%.1f MHz, %.1f kHz, %.1f Hz%s%s)\n", 2806 uprefix, prefix, p->name, p->HDisplay, p->VDisplay, output, 2807 p->Clock / 1000.0, hsync, refresh, desc, desc2); 2808 2809 p = p->next; 2810 } while (p != NULL && p != pScrn->modes); 2811} 2812 2813Bool SISDetermineLCDACap(ScrnInfoPtr pScrn) 2814{ 2815 SISPtr pSiS = SISPTR(pScrn); 2816 2817 if( ((pSiS->ChipType == SIS_650) || 2818 (pSiS->ChipType == SIS_315PRO) || 2819 (pSiS->ChipType >= SIS_661)) && 2820 (pSiS->ChipType != XGI_20) && 2821 (pSiS->VBFlags2 & VB2_SISLCDABRIDGE) && 2822 (pSiS->VESA != 1) ) { 2823 return TRUE; 2824 } 2825 return FALSE; 2826} 2827 2828void SISSaveDetectedDevices(ScrnInfoPtr pScrn) 2829{ 2830 SISPtr pSiS = SISPTR(pScrn); 2831 /* Backup detected CRT2 devices */ 2832 pSiS->detectedCRT2Devices = pSiS->VBFlags & (CRT2_LCD|CRT2_TV|CRT2_VGA|TV_AVIDEO|TV_SVIDEO| 2833 TV_SCART|TV_HIVISION|TV_YPBPR); 2834} 2835 2836static Bool 2837SISCheckBIOS(SISPtr pSiS, UShort mypciid, UShort mypcivendor, int biossize) 2838{ 2839 UShort romptr, pciid; 2840 2841 if(!pSiS->BIOS) return FALSE; 2842 2843 if((pSiS->BIOS[0] != 0x55) || (pSiS->BIOS[1] != 0xaa)) return FALSE; 2844 2845 romptr = pSiS->BIOS[0x18] | (pSiS->BIOS[0x19] << 8); 2846 if(romptr > (biossize - 8)) return FALSE; 2847 if((pSiS->BIOS[romptr] != 'P') || (pSiS->BIOS[romptr+1] != 'C') || 2848 (pSiS->BIOS[romptr+2] != 'I') || (pSiS->BIOS[romptr+3] != 'R')) return FALSE; 2849 2850 pciid = pSiS->BIOS[romptr+4] | (pSiS->BIOS[romptr+5] << 8); 2851 if(pciid != mypcivendor) return FALSE; 2852 2853 pciid = pSiS->BIOS[romptr+6] | (pSiS->BIOS[romptr+7] << 8); 2854 if(pciid != mypciid) return FALSE; 2855 2856 return TRUE; 2857} 2858 2859static void 2860SiS_LoadInitVBE(ScrnInfoPtr pScrn) 2861{ 2862 SISPtr pSiS = SISPTR(pScrn); 2863 2864 /* Don't load the VBE module for secondary 2865 * cards which sisfb POSTed. We don't want 2866 * int10 to overwrite our set up (such as 2867 * disabled a0000 memory address decoding). 2868 * We don't need the VBE anyway because 2869 * the card will never be in text mode, 2870 * and we can restore graphics modes just 2871 * perfectly. 2872 */ 2873 if( !pSiS->Primary && 2874 pSiS->sisfbcardposted) 2875 return; 2876 2877 if(pSiS->pVbe) return; 2878 2879 if(xf86LoadSubModule(pScrn, "vbe")) { 2880#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 2881 pSiS->pVbe = VBEInit(pSiS->pInt, pSiS->pEnt->index); 2882#else 2883 pSiS->pVbe = VBEExtendedInit(pSiS->pInt, pSiS->pEnt->index, 2884 SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH); 2885#endif 2886 } 2887 2888 if(!pSiS->pVbe) { 2889 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2890 "Failed to load/initialize vbe module\n"); 2891 } 2892} 2893 2894#ifdef SIS_PC_PLATFORM 2895static void 2896SiS_MapVGAMem(ScrnInfoPtr pScrn) 2897{ 2898 SISPtr pSiS = SISPTR(pScrn); 2899 2900 /* Map 64k VGA window for saving/restoring CGA fonts */ 2901 pSiS->VGAMapSize = 0x10000; 2902 pSiS->VGAMapPhys = 0; /* Default */ 2903 if((!pSiS->Primary) || (!pSiS->VGADecodingEnabled)) { 2904 /* If card is secondary or if a0000-address decoding 2905 * is disabled, set Phys to beginning of our video RAM. 2906 */ 2907 pSiS->VGAMapPhys = PCI_REGION_BASE(pSiS->PciInfo, 0, REGION_MEM); 2908 } 2909 if(!SiSVGAMapMem(pScrn)) { 2910 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2911 "Failed to map VGA memory (0x%lx), can't save/restore console fonts\n", 2912 pSiS->VGAMapPhys); 2913 } 2914} 2915#endif 2916 2917static void 2918SiS_CheckKernelFB(ScrnInfoPtr pScrn) 2919{ 2920 SISPtr pSiS = SISPTR(pScrn); 2921 int fd, i; 2922 CARD32 sisfbinfosize = 0, sisfbversion; 2923 sisfb_info *mysisfbinfo; 2924 char name[16]; 2925 2926 pSiS->donttrustpdc = FALSE; 2927 pSiS->sisfbpdc = 0xff; 2928 pSiS->sisfbpdca = 0xff; 2929 pSiS->sisfblcda = 0xff; 2930 pSiS->sisfbscalelcd = -1; 2931 pSiS->sisfbspecialtiming = CUT_NONE; 2932 pSiS->sisfb_haveemi = FALSE; 2933 pSiS->sisfbfound = FALSE; 2934 pSiS->sisfb_tvposvalid = FALSE; 2935 pSiS->sisfbdevname[0] = 0; 2936 pSiS->sisfb_havelock = FALSE; 2937 pSiS->sisfbHaveNewHeapDef = FALSE; 2938 pSiS->sisfbHeapSize = 0; 2939 pSiS->sisfbVideoOffset = 0; 2940 pSiS->sisfbxSTN = FALSE; 2941 pSiS->sisfbcanpost = FALSE; /* (Old) sisfb can't POST card */ 2942 pSiS->sisfbcardposted = TRUE; /* If (old) sisfb is running, card must have been POSTed */ 2943 pSiS->sisfbprimary = FALSE; /* (Old) sisfb doesn't know */ 2944 2945 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 2946 2947 i = 0; 2948 do { 2949 2950 if(i <= 7) { 2951 sprintf(name, "/dev/fb%1d", i); 2952 } else { 2953 sprintf(name, "/dev/fb/%1d", (i - 8)); 2954 } 2955 2956 if((fd = open(name, O_RDONLY)) != -1) { 2957 2958 Bool gotit = FALSE; 2959 2960 if(!ioctl(fd, SISFB_GET_INFO_SIZE, &sisfbinfosize)) { 2961 if((mysisfbinfo = malloc(sisfbinfosize))) { 2962 if(!ioctl(fd, (SISFB_GET_INFO | (sisfbinfosize << 16)), mysisfbinfo)) { 2963 gotit = TRUE; 2964 } else { 2965 free(mysisfbinfo); 2966 mysisfbinfo = NULL; 2967 } 2968 } 2969 } else { 2970 if((mysisfbinfo = malloc(sizeof(*mysisfbinfo) + 16))) { 2971 if(!ioctl(fd, SISFB_GET_INFO_OLD, mysisfbinfo)) { 2972 gotit = TRUE; 2973 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2974 "Possibly old version of sisfb detected. Please update.\n"); 2975 } else { 2976 free(mysisfbinfo); 2977 mysisfbinfo = NULL; 2978 } 2979 } 2980 } 2981 2982 if(gotit) { 2983 2984 if(mysisfbinfo->sisfb_id == SISFB_ID) { 2985 2986 sisfbversion = (mysisfbinfo->sisfb_version << 16) | 2987 (mysisfbinfo->sisfb_revision << 8) | 2988 (mysisfbinfo->sisfb_patchlevel); 2989 2990 if(sisfbversion >= SISFB_VERSION(1, 5, 8)) { 2991 /* Added PCI bus/slot/func into in sisfb Version 1.5.08. 2992 * Check this to make sure we run on the same card as sisfb 2993 */ 2994 if((mysisfbinfo->sisfb_pcibus == pSiS->PciBus) && 2995 (mysisfbinfo->sisfb_pcislot == pSiS->PciDevice) && 2996 (mysisfbinfo->sisfb_pcifunc == pSiS->PciFunc)) { 2997 pSiS->sisfbfound = TRUE; 2998 } 2999 } else pSiS->sisfbfound = TRUE; 3000 3001 if(pSiS->sisfbfound) { 3002 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3003 "%s: SiS kernel fb driver (sisfb) %d.%d.%d detected (PCI:%02d:%02d.%d)\n", 3004 &name[5], 3005 mysisfbinfo->sisfb_version, 3006 mysisfbinfo->sisfb_revision, 3007 mysisfbinfo->sisfb_patchlevel, 3008 pSiS->PciBus, 3009 pSiS->PciDevice, 3010 pSiS->PciFunc); 3011 3012 /* Added version/rev/pl in sisfb 1.4.0 */ 3013 if(mysisfbinfo->sisfb_version == 0) { 3014 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3015 "Old version of sisfb found. Please update.\n"); 3016 } 3017 /* Basically, we can't trust the pdc register if sisfb is loaded */ 3018 pSiS->donttrustpdc = TRUE; 3019 pSiS->sisfbHeapStart = mysisfbinfo->heapstart; 3020 3021 if(sisfbversion >= SISFB_VERSION(1, 7, 20)) { 3022 pSiS->sisfbHeapSize = mysisfbinfo->sisfb_heapsize; 3023 pSiS->sisfbVideoOffset = mysisfbinfo->sisfb_videooffset; 3024 pSiS->sisfbHaveNewHeapDef = TRUE; 3025 pSiS->sisfbFSTN = mysisfbinfo->sisfb_curfstn; 3026 pSiS->sisfbDSTN = mysisfbinfo->sisfb_curdstn; 3027 pSiS->sisfbxSTN = TRUE; 3028 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3029 "sisfb: memory heap at %dKB, size %dKB, viewport at %dKB\n", 3030 (int)pSiS->sisfbHeapStart, (int)pSiS->sisfbHeapSize, 3031 (int)pSiS->sisfbVideoOffset/1024); 3032 } else { 3033 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3034 "sisfb: memory heap at %dKB\n", (int)pSiS->sisfbHeapStart); 3035 } 3036 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3037 "sisfb: using video mode 0x%02x\n", mysisfbinfo->fbvidmode); 3038 pSiS->OldMode = mysisfbinfo->fbvidmode; 3039 if(sisfbversion >= SISFB_VERSION(1, 5, 6)) { 3040 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3041 "sisfb: using %s, reserved %dK\n", 3042 (mysisfbinfo->sisfb_caps & 0x40) ? "SiS300 series Turboqueue" : 3043 (mysisfbinfo->sisfb_caps & 0x20) ? "SiS315/330/340 series AGP command queue" : 3044 (mysisfbinfo->sisfb_caps & 0x10) ? "SiS315/330/340 series VRAM command queue" : 3045 (mysisfbinfo->sisfb_caps & 0x08) ? "SiS315/330/340 series MMIO mode" : 3046 "no command queue", 3047 (int)mysisfbinfo->sisfb_tqlen); 3048 } 3049 if(sisfbversion >= SISFB_VERSION(1, 5, 10)) { 3050 /* We can trust the pdc value if sisfb is of recent version */ 3051 if(pSiS->VGAEngine == SIS_300_VGA) pSiS->donttrustpdc = FALSE; 3052 } 3053 if(sisfbversion >= SISFB_VERSION(1, 5, 11)) { 3054 if(pSiS->VGAEngine == SIS_300_VGA) { 3055 /* As of 1.5.11, sisfb saved the register for us (300 series) */ 3056 pSiS->sisfbpdc = mysisfbinfo->sisfb_lcdpdc; 3057 if(!pSiS->sisfbpdc) pSiS->sisfbpdc = 0xff; 3058 } 3059 } 3060 if(sisfbversion >= SISFB_VERSION(1, 5, 14)) { 3061 if(pSiS->VGAEngine == SIS_315_VGA) { 3062 pSiS->sisfblcda = mysisfbinfo->sisfb_lcda; 3063 } 3064 } 3065 if(sisfbversion >= SISFB_VERSION(1, 6, 13)) { 3066 pSiS->sisfbscalelcd = mysisfbinfo->sisfb_scalelcd; 3067 pSiS->sisfbspecialtiming = mysisfbinfo->sisfb_specialtiming; 3068 } 3069 if(sisfbversion >= SISFB_VERSION(1, 6, 16)) { 3070 if(pSiS->VGAEngine == SIS_315_VGA) { 3071 pSiS->donttrustpdc = FALSE; 3072 pSiS->sisfbpdc = mysisfbinfo->sisfb_lcdpdc; 3073 if(sisfbversion >= SISFB_VERSION(1, 6, 24)) { 3074 pSiS->sisfb_haveemi = mysisfbinfo->sisfb_haveemi ? TRUE : FALSE; 3075 pSiS->sisfb_haveemilcd = TRUE; /* will match most cases */ 3076 pSiS->sisfb_emi30 = mysisfbinfo->sisfb_emi30; 3077 pSiS->sisfb_emi31 = mysisfbinfo->sisfb_emi31; 3078 pSiS->sisfb_emi32 = mysisfbinfo->sisfb_emi32; 3079 pSiS->sisfb_emi33 = mysisfbinfo->sisfb_emi33; 3080 } 3081 if(sisfbversion >= SISFB_VERSION(1, 6, 25)) { 3082 pSiS->sisfb_haveemilcd = mysisfbinfo->sisfb_haveemilcd ? TRUE : FALSE; 3083 } 3084 if(sisfbversion >= SISFB_VERSION(1, 6, 31)) { 3085 pSiS->sisfbpdca = mysisfbinfo->sisfb_lcdpdca; 3086 } else { 3087 if(pSiS->sisfbpdc) { 3088 pSiS->sisfbpdca = (pSiS->sisfbpdc & 0xf0) >> 3; 3089 pSiS->sisfbpdc = (pSiS->sisfbpdc & 0x0f) << 1; 3090 } else { 3091 pSiS->sisfbpdca = pSiS->sisfbpdc = 0xff; 3092 } 3093 } 3094 } 3095 } 3096 if(sisfbversion >= SISFB_VERSION(1, 7, 0)) { 3097 pSiS->sisfb_havelock = TRUE; 3098 if(sisfbversion >= SISFB_VERSION(1, 7, 1)) { 3099 pSiS->sisfb_tvxpos = mysisfbinfo->sisfb_tvxpos; 3100 pSiS->sisfb_tvypos = mysisfbinfo->sisfb_tvypos; 3101 pSiS->sisfb_tvposvalid = TRUE; 3102 } 3103 } 3104 if(sisfbversion >= SISFB_VERSION(1, 8, 7)) { 3105 pSiS->sisfbcanpost = (mysisfbinfo->sisfb_can_post) ? TRUE : FALSE; 3106 pSiS->sisfbcardposted = (mysisfbinfo->sisfb_card_posted) ? TRUE : FALSE; 3107 pSiS->sisfbprimary = (mysisfbinfo->sisfb_was_boot_device) ? TRUE : FALSE; 3108 /* Validity check */ 3109 if(!pSiS->sisfbcardposted) { 3110 pSiS->sisfbprimary = FALSE; 3111 } 3112 } 3113 } 3114 } 3115 free(mysisfbinfo); 3116 mysisfbinfo = NULL; 3117 } 3118 close (fd); 3119 } 3120 i++; 3121 } while((i <= 15) && (!pSiS->sisfbfound)); 3122 3123 if(pSiS->sisfbfound) { 3124 strncpy(pSiS->sisfbdevname, name, 15); 3125 } else { 3126 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "sisfb not found\n"); 3127 } 3128 } 3129 3130 if(!pSiS->sisfbfound) { 3131 pSiS->sisfbcardposted = FALSE; 3132 } 3133} 3134 3135static void 3136SiSPseudo(ScrnInfoPtr pScrn) 3137{ 3138} 3139 3140/* PreInit() 3141 * 3142 * Mandatory 3143 */ 3144static Bool 3145SISPreInit(ScrnInfoPtr pScrn, int flags) 3146{ 3147 SISPtr pSiS; 3148#ifdef SISDUALHEAD 3149 SISEntPtr pSiSEnt = NULL; 3150#endif 3151 MessageType from; 3152 UChar usScratchCR17, usScratchCR32, usScratchCR63; 3153 UChar usScratchSR1F, srlockReg, crlockReg; 3154 unsigned int i; 3155 int pix24flags, temp; 3156 ClockRangePtr clockRanges; 3157 xf86MonPtr pMonitor = NULL; 3158 Bool didddc2, fromDDC, crt1freqoverruled = FALSE; 3159 UChar CR5F, tempreg; 3160#if defined(SISMERGED) || defined(SISDUALHEAD) 3161 DisplayModePtr first, p, n; 3162#endif 3163#ifdef SISMERGED 3164 Bool crt2freqoverruled = FALSE; 3165#endif 3166 3167 static const char *ddcsstr = "CRT%d DDC monitor info: *******************************************\n"; 3168 static const char *ddcestr = "End of CRT%d DDC monitor info *************************************\n"; 3169 static const char *subshstr = "Substituting missing CRT%d monitor HSync range by DDC data\n"; 3170 static const char *subsvstr = "Substituting missing CRT%d monitor VRefresh range by DDC data\n"; 3171 static const char *saneh = "Correcting %s CRT%d monitor HSync range\n"; 3172 static const char *sanev = "Correcting %s CRT%d monitor VRefresh range\n"; 3173#ifdef SISMERGED 3174 static const char *mergednocrt1 = "CRT1 not detected or forced off. %s.\n"; 3175 static const char *mergednocrt2 = "No CRT2 output selected or no video bridge detected. %s.\n"; 3176 static const char *mergeddisstr = "MergedFB mode disabled"; 3177 static const char *modesforstr = "Modes for CRT%d: **************************************************\n"; 3178 static const char *crtsetupstr = "*************************** CRT%d setup ***************************\n"; 3179 static const char *crt2monname = "CRT2"; 3180#endif 3181#if defined(SISDUALHEAD) || defined(SISMERGED) 3182 static const char *notsuitablestr = "Not using mode \"%s\" (not suitable for %s mode)\n"; 3183#endif 3184 3185 if(flags & PROBE_DETECT) { 3186 3187 vbeInfoPtr pVbe; 3188 3189 if(xf86LoadSubModule(pScrn, "vbe")) { 3190 int index = xf86GetEntityInfo(pScrn->entityList[0])->index; 3191#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 3192 if((pVbe = VBEInit(NULL, index))) 3193#else 3194 if((pVbe = VBEExtendedInit(NULL, index, 0))) 3195#endif 3196 { 3197 ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 3198 vbeFree(pVbe); 3199 } 3200 } 3201 return TRUE; 3202 } 3203 3204 /* 3205 * Note: This function is only called once at server startup, and 3206 * not at the start of each server generation. This means that 3207 * only things that are persistent across server generations can 3208 * be initialised here. xf86Screens[] is the array of all screens, 3209 * (pScrn is a pointer to one of these). Privates allocated using 3210 * xf86AllocateScrnInfoPrivateIndex() are too, and should be used 3211 * for data that must persist across server generations. 3212 * 3213 * Per-generation data should be allocated with 3214 * AllocateScreenPrivateIndex() from the ScreenInit() function. 3215 */ 3216 3217 /* Check the number of entities, and fail if it isn't one. */ 3218 if(pScrn->numEntities != 1) { 3219 SISErrorLog(pScrn, "Number of entities is not 1\n"); 3220 return FALSE; 3221 } 3222 3223 /* Due to the liberal license terms this is needed for 3224 * keeping the copyright notice readable and intact in 3225 * binary distributions. Removing this is a copyright 3226 * infringement. Please read the license terms above. 3227 */ 3228 3229 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3230 "SiS driver (%d/%02d/%02d-%d, compiled for " SISMYSERVERNAME " %d.%d.%d.%d)\n", 3231 SISDRIVERVERSIONYEAR + 2000, SISDRIVERVERSIONMONTH, 3232 SISDRIVERVERSIONDAY, SISDRIVERREVISION, 3233#ifdef XORG_VERSION_CURRENT 3234 XORG_VERSION_MAJOR, XORG_VERSION_MINOR, 3235 XORG_VERSION_PATCH, XORG_VERSION_SNAP 3236#else 3237 XF86_VERSION_MAJOR, XF86_VERSION_MINOR, 3238 XF86_VERSION_PATCH, XF86_VERSION_SNAP 3239#endif 3240 ); 3241 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3242 "Copyright (C) 2001-2005 Thomas Winischhofer <thomas@winischhofer.net> and others\n"); 3243 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3244 "*** See http://www.winischhofer.eu/linuxsisvga.shtml\n"); 3245 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3246 "*** for documentation and updates.\n"); 3247 3248#ifdef XORG_VERSION_CURRENT 3249#if 0 /* no prototype yet */ 3250 if(xorgGetVersion() != XORG_VERSION_CURRENT) { 3251 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3252 "This driver binary is not compiled for this version of " SISMYSERVERNAME "\n"); 3253 } 3254#endif 3255#else 3256#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0) 3257 if(xf86GetVersion() != XF86_VERSION_CURRENT) { 3258 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3259 "This driver binary is not compiled for this version of " SISMYSERVERNAME "\n"); 3260 } 3261#endif 3262#endif 3263 3264 /* Allocate the SISRec driverPrivate */ 3265 if(!SISGetRec(pScrn)) { 3266 SISErrorLog(pScrn, "Could not allocate memory for pSiS private\n"); 3267 return FALSE; 3268 } 3269 pSiS = SISPTR(pScrn); 3270 pSiS->pScrn = pScrn; 3271 3272 pSiS->pInt = NULL; 3273 3274 /* Save PCI Domain Base */ 3275#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) || GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 12 3276 pSiS->IODBase = 0; 3277#else 3278 pSiS->IODBase = pScrn->domainIOBase; 3279#endif 3280 3281 /* Get the entity, and make sure it is PCI. */ 3282 pSiS->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 3283 if(pSiS->pEnt->location.type != BUS_PCI) { 3284 SISErrorLog(pScrn, "Entity's bus type is not PCI\n"); 3285 goto my_error_0; 3286 } 3287 3288#ifdef SISDUALHEAD 3289 /* Allocate an entity private if necessary */ 3290 if(xf86IsEntityShared(pScrn->entityList[0])) { 3291 pSiSEnt = xf86GetEntityPrivate(pScrn->entityList[0], SISEntityIndex)->ptr; 3292 pSiS->entityPrivate = pSiSEnt; 3293 3294 /* If something went wrong, quit here */ 3295 if((pSiSEnt->DisableDual) || (pSiSEnt->ErrorAfterFirst)) { 3296 SISErrorLog(pScrn, "First head encountered fatal error, aborting...\n"); 3297 goto my_error_0; 3298 } 3299 } 3300#endif 3301 3302 /* Find the PCI info for this screen */ 3303 pSiS->PciInfo = xf86GetPciInfoForEntity(pSiS->pEnt->index); 3304 pSiS->PciBus = PCI_CFG_BUS(pSiS->PciInfo); /*SIS_PCI_BUS(pSiS->PciInfo);*/ 3305 pSiS->PciDevice = PCI_CFG_DEV(pSiS->PciInfo); /*SIS_PCI_DEVICE(pSiS->PciInfo);*/ 3306 pSiS->PciFunc = PCI_CFG_FUNC(pSiS->PciInfo); /*SIS_PCI_FUNC(pSiS->PciInfo);*/ 3307 3308#ifndef XSERVER_LIBPCIACCESS 3309 pSiS->PciTag = pciTag(PCI_DEV_BUS(pSiS->PciInfo), 3310 PCI_DEV_DEV(pSiS->PciInfo), 3311 PCI_DEV_FUNC(pSiS->PciInfo)); 3312#endif 3313 3314#ifdef SIS_NEED_MAP_IOP 3315 /********************************************/ 3316 /* THIS IS BROKEN AND WON'T WORK */ 3317 /* Reasons: */ 3318 /* 1) MIPS and ARM have no i/o ports but */ 3319 /* use memory mapped i/o only. The inX/outX */ 3320 /* macros in compiler.h are smart enough to */ 3321 /* add "IOPortBase" to the port number, but */ 3322 /* "IOPortBase" is never initialized. */ 3323 /* 2) IOPortBase is declared in compiler.h */ 3324 /* itself. So until somebody fixes all */ 3325 /* modules that #include compiler.h to set */ 3326 /* IOPortBase, vga support for MIPS and ARM */ 3327 /* is unusable. */ 3328 /* (In this driver this is solvable because */ 3329 /* we have our own vgaHW routines. However, */ 3330 /* we use /dev/port for now instead.) */ 3331 /********************************************/ 3332 pSiS->IOPAddress = pSiS->IODBase + pSiS->PciInfo->ioBase[2]; 3333 if(!SISMapIOPMem(pScrn)) { 3334 SISErrorLog(pScrn, "Could not map I/O port area at 0x%x\n", pSiS->IOPAddress); 3335 goto my_error_0; 3336 } else { 3337 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I/O port area mapped to %p, size 128\n", pSiS->IOPBase); 3338#if defined(__mips__) || defined(__arm32__) 3339 /* inX/outX macros on these use IOPortBase as offset */ 3340 /* This is entirely skrewed. */ 3341 IOPortBase = (unsigned int)pSiS->IOPBase; 3342#endif 3343 } 3344#endif 3345 3346 /* Set up i/o port access (for non-x86) */ 3347#ifdef SISUSEDEVPORT 3348 if((sisdevport = open("/dev/port", O_RDWR, 0)) == -1) { 3349 SISErrorLog(pScrn, "Failed to open /dev/port for read/write\n"); 3350 goto my_error_0; 3351 } 3352 pSiS->sisdevportopen = TRUE; 3353#endif 3354 3355 /* 3356 * Set the Chipset and ChipRev, allowing config file entries to 3357 * override. DANGEROUS! 3358 */ 3359 { 3360 SymTabRec *myChipsets = SISChipsets; 3361 3362 if(PCI_DEV_VENDOR_ID(pSiS->PciInfo) == PCI_VENDOR_XGI) { 3363 myChipsets = XGIChipsets; 3364 } 3365 3366 if(pSiS->pEnt->device->chipset && *pSiS->pEnt->device->chipset) { 3367 3368 pScrn->chipset = pSiS->pEnt->device->chipset; 3369 pSiS->Chipset = xf86StringToToken(myChipsets, pScrn->chipset); 3370 3371 } else if(pSiS->pEnt->device->chipID >= 0) { 3372 3373 pSiS->Chipset = pSiS->pEnt->device->chipID; 3374 pScrn->chipset = (char *)xf86TokenToString(myChipsets, pSiS->Chipset); 3375 3376 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", 3377 pSiS->Chipset); 3378 } else { 3379 3380 pSiS->Chipset = PCI_DEV_DEVICE_ID(pSiS->PciInfo); 3381 pScrn->chipset = (char *)xf86TokenToString(myChipsets, pSiS->Chipset); 3382 3383 } 3384 } 3385 3386 if(pSiS->pEnt->device->chipRev >= 0) { 3387 3388 pSiS->ChipRev = pSiS->pEnt->device->chipRev; 3389 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 3390 pSiS->ChipRev); 3391 } else { 3392 3393 pSiS->ChipRev = PCI_DEV_REVISION(pSiS->PciInfo); 3394 3395 } 3396 3397 /* 3398 * This shouldn't happen because such problems should be caught in 3399 * SISProbe(), but check it just in case the user has overridden them. 3400 */ 3401 if(pScrn->chipset == NULL) { 3402 SISErrorLog(pScrn, "ChipID 0x%04X is not recognised\n", pSiS->Chipset); 3403 goto my_error_0; 3404 } 3405 if(pSiS->Chipset < 0) { 3406 SISErrorLog(pScrn, "Chipset \"%s\" is not recognised\n", pScrn->chipset); 3407 goto my_error_0; 3408 } 3409 3410 pSiS->SiS6326Flags = 0; 3411 3412 /* Determine VGA engine generation */ 3413 switch(pSiS->Chipset) { 3414 case PCI_CHIP_SIS300: 3415 case PCI_CHIP_SIS540: 3416 case PCI_CHIP_SIS630: /* 630 + 730 */ 3417 pSiS->VGAEngine = SIS_300_VGA; 3418 break; 3419 case PCI_CHIP_SIS315H: 3420 case PCI_CHIP_SIS315: 3421 case PCI_CHIP_SIS315PRO: 3422 case PCI_CHIP_SIS550: 3423 case PCI_CHIP_SIS650: /* 650 + 740 */ 3424 case PCI_CHIP_SIS330: 3425 case PCI_CHIP_SIS660: /* 660, 661, 741, 760, 761, 670(?), 770 */ 3426 case PCI_CHIP_SIS340: 3427 case PCI_CHIP_XGIXG20: 3428 case PCI_CHIP_XGIXG40: 3429 pSiS->VGAEngine = SIS_315_VGA; 3430 break; 3431 case PCI_CHIP_SIS530: 3432 pSiS->VGAEngine = SIS_530_VGA; 3433 break; 3434 case PCI_CHIP_SIS6326: 3435 /* Determine SiS6326 revision. According to SiS the differences are: 3436 * Chip name Chip type TV-Out MPEG II decoder 3437 * 6326 AGP Rev. G0/H0 no no 3438 * 6326 DVD Rev. D2 yes yes 3439 * 6326 Rev. Cx yes yes 3440 */ 3441 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3442 "Chipset is SiS6326 %s (revision 0x%02x)\n", 3443 (pSiS->ChipRev == 0xaf) ? "(Ax)" : 3444 ((pSiS->ChipRev == 0x0a) ? "AGP (G0)" : 3445 ((pSiS->ChipRev == 0x0b) ? "AGP (H0)" : 3446 (((pSiS->ChipRev & 0xf0) == 0xd0) ? "DVD (Dx/H0)" : 3447 (((pSiS->ChipRev & 0xf0) == 0x90) ? "(9x)" : 3448 (((pSiS->ChipRev & 0xf0) == 0xc0) ? "(Cx)" : 3449 "(unknown)"))))), 3450 pSiS->ChipRev); 3451 if((pSiS->ChipRev != 0x0a) && (pSiS->ChipRev != 0x0b)) { 3452 pSiS->SiS6326Flags |= SIS6326_HASTV; 3453 } 3454 /* fall through */ 3455 default: 3456 pSiS->VGAEngine = SIS_OLD_VGA; 3457 } 3458 3459 /* We don't know about the current mode yet */ 3460 pSiS->OldMode = 0; 3461 3462 /* Determine whether this is the primary or a secondary 3463 * display adapter. And right here the problem starts: 3464 * On machines with integrated SiS chipsets, the system BIOS 3465 * usually sets VGA_EN on all PCI-to-PCI bridges in the system 3466 * (of which there usually are two: PCI and AGP). This and 3467 * the fact that any PCI card POSTed by sisfb naturally has 3468 * its PCI resources enabled, leads to X assuming that 3469 * there are more than one "primary" cards in the system. 3470 * In this case, X treats ALL cards as "secondary" - 3471 * which by no means is desireable. If sisfb is running, 3472 * we can determine which card really is "primary" (in 3473 * terms of if it's the one that occupies the A0000 area 3474 * etc.) in a better way (Linux 2.6.12 or later). See below. 3475 */ 3476 if(!(pSiS->Primary = xf86IsPrimaryPci(pSiS->PciInfo))) { 3477 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3478 SISMYSERVERNAME " assumes this adapter to be secondary\n"); 3479 } 3480 3481 /* Now check if sisfb is running, and if so, retrieve 3482 * all possible info from it. This also resets all 3483 * sisfb_* entries in pSiS regardless of the chipset. 3484 */ 3485 SiS_CheckKernelFB(pScrn); 3486 3487 /* Now for that primary/secondary mess: Linux kernel 3488 * 2.6.12 and later knows what card is primary, and so 3489 * does any recent version of sisfb. XFree86/X.org takes 3490 * all adapters as "secondary" if more than one card's 3491 * memory and i/o resources are enabled, and more than 3492 * one PCI bridge in the system has VGA_EN set at server 3493 * start. So, let's start thinking: What is this 3494 * primary/secondary classification needed for anyway? 3495 * (This list might be incomplete for the entire server 3496 * infrastructure, but it's complete as regards the driver's 3497 * purposes of primary/secondary classification.) 3498 * 1) VGA/console font restoring: Here it's irrelevant 3499 * whether more than one card's resources are enabled 3500 * at server start or not. Relevant is whether the card 3501 * occupies the A0000 area at this time. Assuming (?) 3502 * that this does not change during machine up-time, 3503 * it suffices to know which device was the boot video 3504 * device (as determined by Linux 2.6.12 and later). 3505 * Also, this is only relevant if the card is in text 3506 * mode; if it's in graphics mode, fonts aren't saved 3507 * or restored anyway. 3508 * sisfb tells us if that card is considered the boot 3509 * video device. The hardware registers tell us if 3510 * the card's A0000 address decoding is enabled, and if 3511 * the card currently is in text mode. These three bits 3512 * of information are enough to decide on whether or not 3513 * to save/restore fonts. 3514 * 2) POSTing. Same here. Relevant is only whether or not 3515 * the card has been POSTed once before. POSTing cards 3516 * on every server start is pretty ugly, especially 3517 * if a framebuffer driver is already handling it. 3518 * SiS/XGI cards POSTed by sisfb can coexist well with other 3519 * active adapters. So we trust sisfb's information more 3520 * than X's (especially as we only use this information for 3521 * console font restoring and eventual POSTing.) 3522 * What we still need is a way to find out about all this if 3523 * sisfb is not running.... 3524 */ 3525 if(!pSiS->Primary && pSiS->sisfbprimary) { 3526 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3527 "sisfb reports this adapter to be primary. Seems more reliable.\n"); 3528 pSiS->Primary = TRUE; 3529 } 3530 3531 /* If the card is "secondary" and has not been 3532 * POSTed by sisfb, POST it now through int10. 3533 * For cards POSTed by sisfb, we definitely don't 3534 * want that as it messes up our set up (eg. the 3535 * disabled A0000 area). 3536 * The int10 module decides on its own if the 3537 * card is primary or secondary. Since it uses 3538 * the generic technique described above, and since 3539 * for "secondary" cards it needs a real PCI BIOS 3540 * ROM, and since integrated chips don't have such 3541 * a PCI BIOS ROM, int10 will naturally fail to 3542 * find/read the BIOS on such machines. Great. 3543 * Using the integrated graphics as "secondary" 3544 * (which it will be as soon as X finds more than 3545 * one card's mem and i/o resources enabled, and more 3546 * than one PCI bridge's VGA_EN bit set during server 3547 * start) will therefore prevent us from restoring 3548 * the mode using the VBE. That means real fun if 3549 * the integrated chip is set up to use the video 3550 * bridge output for text mode (which is something 3551 * the driver doesn't really support since it's done 3552 * pretty much differently on every machine.) 3553 */ 3554#if !defined(__alpha__) 3555 if(!pSiS->Primary) { 3556 if(!pSiS->sisfbcardposted) { 3557 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3558 "Initializing adapter through int10\n"); 3559 if(xf86LoadSubModule(pScrn, "int10")) { 3560 pSiS->pInt = xf86InitInt10(pSiS->pEnt->index); 3561 } else { 3562 SISErrorLog(pScrn, "Failed to load int10 module\n"); 3563 } 3564 } else { 3565 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3566 "Adapter already initialized by sisfb\n"); 3567 } 3568 } 3569#endif 3570 3571 /* Get the address of our relocated IO registers. 3572 * These are enabled by the hardware during cold boot, and 3573 * by the BIOS. So we can pretty much rely on that these 3574 * are enabled. 3575 */ 3576 pSiS->RelIO = (SISIOADDRESS)(PCI_REGION_BASE(pSiS->PciInfo, 2, REGION_IO) + pSiS->IODBase); 3577 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Relocated I/O registers at 0x%lX\n", 3578 (ULong)pSiS->RelIO); 3579 3580 /* Unlock extended registers */ 3581 sisSaveUnlockExtRegisterLock(pSiS, &srlockReg, &crlockReg); 3582 3583 /* Is a0000 memory address decoding enabled? */ 3584 pSiS->VGADecodingEnabled = TRUE; 3585 switch(pSiS->VGAEngine) { 3586 case SIS_OLD_VGA: 3587 /* n/a */ 3588 break; 3589 case SIS_530_VGA: 3590 inSISIDXREG(SISSR, 0x3d, tempreg); 3591 if(tempreg & 0x04) pSiS->VGADecodingEnabled = FALSE; 3592 break; 3593 case SIS_300_VGA: 3594 case SIS_315_VGA: 3595 inSISIDXREG(SISSR, 0x20, tempreg); 3596 if(tempreg & 0x04) pSiS->VGADecodingEnabled = FALSE; 3597 break; 3598 } 3599 3600 if(!pSiS->VGADecodingEnabled) { 3601 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3602 "Standard VGA (0xA0000) memory address decoding is disabled\n"); 3603 } 3604 3605#ifdef SIS_PC_PLATFORM 3606 /* Map 64k VGA window for saving/restoring CGA fonts. 3607 * For secondary cards or if A0000 address decoding 3608 * is disabled, this will map the beginning of the 3609 * linear (PCI) video RAM instead. 3610 */ 3611 SiS_MapVGAMem(pScrn); 3612#endif 3613 3614#ifndef XSERVER_LIBPCIACCESS 3615 /* Set operating state */ 3616 3617 /* 1. memory */ 3618 /* [ResUnusedOpr: Resource decoded by hw, but not used] 3619 * [ResDisableOpr: Resource is not decoded by hw] 3620 * So, if a0000 memory decoding is disabled, one could 3621 * argue that we may say so, too. Hm. Quite likely that 3622 * the VBE (via int10) will eventually enable it. So we 3623 * cowardly say unused instead. 3624 */ 3625 xf86SetOperatingState(resVgaMem, pSiS->pEnt->index, ResUnusedOpr); 3626 3627 /* 2. i/o */ 3628 /* Although we only use the relocated i/o ports, the hardware 3629 * also decodes the standard VGA port range. This could in 3630 * theory be disabled, but I don't dare to do this; in case of 3631 * a server crash, the card would be entirely dead. Also, this 3632 * would prevent int10 and the VBE from working at all. Generic 3633 * access control through the PCI configuration registers does 3634 * nicely anyway. 3635 */ 3636 xf86SetOperatingState(resVgaIo, pSiS->pEnt->index, ResUnusedOpr); 3637 3638 /* Operations for which memory access is required */ 3639 pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; 3640 3641 /* Operations for which I/O access is required */ 3642 pScrn->racIoFlags = RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; 3643 3644#endif 3645 3646 /* Load ramdac module */ 3647 if(!xf86LoadSubModule(pScrn, "ramdac")) { 3648 SISErrorLog(pScrn, "Could not load ramdac module\n"); 3649 goto my_error_1; 3650 } 3651 3652 /* Set pScrn->monitor */ 3653 pScrn->monitor = pScrn->confScreen->monitor; 3654 3655 /* Reset some entries */ 3656 pSiS->SiSFastVidCopy = SiSVidCopyGetDefault(); 3657 pSiS->SiSFastMemCopy = SiSVidCopyGetDefault(); 3658 pSiS->SiSFastVidCopyFrom = SiSVidCopyGetDefault(); 3659 pSiS->SiSFastMemCopyFrom = SiSVidCopyGetDefault(); 3660 pSiS->SiSFastVidCopyDone = FALSE; 3661#ifdef SIS_USE_XAA 3662 pSiS->RenderCallback = NULL; 3663#endif 3664#ifdef SIS_USE_EXA 3665 pSiS->ExaRenderCallback = NULL; 3666#endif 3667 pSiS->InitAccel = SiSPseudo; 3668 pSiS->SyncAccel = SiSPseudo; 3669 pSiS->FillRect = NULL; 3670 pSiS->BlitRect = NULL; 3671 3672 /* Always do a ValidMode() inside Switchmode() */ 3673 pSiS->skipswitchcheck = FALSE; 3674 3675 /* Determine chipset and its capabilities in detail */ 3676 pSiS->ChipFlags = 0; 3677 pSiS->SiS_SD_Flags = pSiS->SiS_SD2_Flags = 0; 3678 pSiS->SiS_SD3_Flags = pSiS->SiS_SD4_Flags = 0; 3679 pSiS->HWCursorMBufNum = pSiS->HWCursorCBufNum = 0; 3680 pSiS->NeedFlush = FALSE; 3681 pSiS->NewCRLayout = FALSE; 3682 pSiS->mmioSize = 64; 3683 3684 switch(pSiS->Chipset) { 3685 case PCI_CHIP_SIS530: 3686 pSiS->ChipType = SIS_530; 3687 break; 3688 case PCI_CHIP_SIS300: 3689 pSiS->ChipType = SIS_300; 3690 pSiS->SiS_SD_Flags |= SiS_SD_IS300SERIES; 3691 break; 3692 case PCI_CHIP_SIS540: 3693 pSiS->ChipType = SIS_540; 3694 pSiS->SiS_SD_Flags |= SiS_SD_IS300SERIES; 3695 break; 3696 case PCI_CHIP_SIS630: /* 630 + 730 */ 3697 pSiS->ChipType = SIS_630; 3698 if(sis_pci_read_host_bridge_u32(0x00) == 0x07301039) { 3699 pSiS->ChipType = SIS_730; 3700 } 3701 pSiS->SiS_SD_Flags |= SiS_SD_IS300SERIES; 3702 break; 3703 case PCI_CHIP_SIS315H: 3704 pSiS->ChipType = SIS_315H; 3705 pSiS->ChipFlags |= (SiSCF_315Core | SiSCF_MMIOPalette); 3706 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3707 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3708 pSiS->myCR63 = 0x63; 3709 break; 3710 case PCI_CHIP_SIS315: 3711 /* Override for simplicity */ 3712 pSiS->Chipset = PCI_CHIP_SIS315H; 3713 pSiS->ChipType = SIS_315; 3714 pSiS->ChipFlags |= (SiSCF_315Core | SiSCF_MMIOPalette); 3715 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3716 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3717 pSiS->myCR63 = 0x63; 3718 break; 3719 case PCI_CHIP_SIS315PRO: 3720 /* Override for simplicity */ 3721 pSiS->Chipset = PCI_CHIP_SIS315H; 3722 pSiS->ChipType = SIS_315PRO; 3723 pSiS->ChipFlags |= (SiSCF_315Core | SiSCF_MMIOPalette); 3724 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3725 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3726 pSiS->myCR63 = 0x63; 3727 break; 3728 case PCI_CHIP_SIS550: 3729 pSiS->ChipType = SIS_550; 3730 pSiS->ChipFlags |= (SiSCF_Integrated | SiSCF_MMIOPalette); 3731 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3732 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3733 pSiS->myCR63 = 0x63; 3734 break; 3735 case PCI_CHIP_SIS650: /* 650 + 740 */ 3736 pSiS->ChipType = SIS_650; 3737 if(sis_pci_read_host_bridge_u32(0x00) == 0x07401039) { 3738 pSiS->ChipType = SIS_740; 3739 } 3740 pSiS->ChipFlags |= (SiSCF_Integrated | SiSCF_Real256ECore | SiSCF_MMIOPalette); 3741 pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 3742 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3743 pSiS->myCR63 = 0x63; 3744 break; 3745 case PCI_CHIP_SIS330: 3746 pSiS->ChipType = SIS_330; 3747 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette); 3748 pSiS->SiS_SD_Flags |= SiS_SD_IS330SERIES; 3749 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3750 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; /* FIXME ? */ 3751 pSiS->myCR63 = 0x53; /* sic! */ 3752 break; 3753 case PCI_CHIP_SIS660: /* 660, 661, 741, 760, 761, 670(?) */ 3754 { 3755 ULong hpciid = sis_pci_read_host_bridge_u32(0x00); 3756 switch(hpciid) { 3757 case 0x06601039: 3758 pSiS->ChipType = SIS_660; 3759 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3760 pSiS->NeedFlush = TRUE; 3761 break; 3762 case 0x07601039: 3763 pSiS->ChipType = SIS_760; 3764 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3765 pSiS->NeedFlush = TRUE; 3766 break; 3767 case 0x07611039: 3768 pSiS->ChipType = SIS_761; 3769 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3770 pSiS->NeedFlush = TRUE; 3771 break; 3772 case 0x07701039: 3773 pSiS->ChipType = SIS_770; 3774 pSiS->ChipFlags |= SiSCF_Ultra256Core; 3775 pSiS->NeedFlush = TRUE; 3776 break; 3777 case 0x07411039: 3778 pSiS->ChipType = SIS_741; 3779 pSiS->ChipFlags |= SiSCF_Real256ECore; 3780 break; 3781 case 0x06611039: 3782 default: 3783 pSiS->ChipType = SIS_661; 3784 pSiS->ChipFlags |= SiSCF_Real256ECore; 3785 break; 3786 case 0x06701039: 3787 pSiS->ChipType = SIS_670; 3788 pSiS->ChipFlags |= SiSCF_Real256ECore; 3789 } 3790 /* Detection could also be done by CR5C & 0xf8: 3791 * 0x10 = 661 (CR5F & 0xc0: 0x00 both A0 and A1) 3792 * 0x80 = 760 (CR5F & 0xc0: 0x00 A0, 0x40 A1) 3793 * 0x90 = 741 (CR5F & 0xc0: 0x00 A0,A1 0x40 A2) 3794 * other: 660 (CR5F & 0xc0: 0x00 A0 0x40 A1) (DOA?) 3795 */ 3796 pSiS->ChipFlags |= (SiSCF_Integrated | SiSCF_MMIOPalette); 3797 pSiS->SiS_SD_Flags |= SiS_SD_IS330SERIES; 3798 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3799 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; 3800 pSiS->myCR63 = 0x53; /* sic! */ 3801 pSiS->NewCRLayout = TRUE; 3802 } 3803 break; 3804 case PCI_CHIP_SIS340: 3805 pSiS->ChipType = SIS_340; 3806 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette); 3807 pSiS->SiS_SD_Flags |= SiS_SD_IS340SERIES; 3808 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 3809 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; 3810 pSiS->myCR63 = 0x53; 3811 pSiS->NewCRLayout = TRUE; 3812 break; 3813 case PCI_CHIP_XGIXG20: 3814 pSiS->ChipType = XGI_20; 3815 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette | SiSCF_IsXGI); 3816 pSiS->SiS_SD2_Flags |= (SiS_SD2_NOOVERLAY | SiS_SD2_ISXGI); 3817 pSiS->myCR63 = 0x53; 3818 pSiS->NewCRLayout = TRUE; 3819 break; 3820 case PCI_CHIP_XGIXG40: 3821 pSiS->ChipType = XGI_40; 3822 pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette | SiSCF_IsXGI); 3823 pSiS->SiS_SD2_Flags |= (SiS_SD2_SUPPORTXVHUESAT | SiS_SD2_ISXGI); 3824 pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; 3825 pSiS->myCR63 = 0x53; 3826 pSiS->NewCRLayout = TRUE; 3827 if(pSiS->ChipRev == 2) pSiS->ChipFlags |= SiSCF_IsXGIV3; 3828 break; 3829 default: 3830 pSiS->ChipType = SIS_OLD; 3831 break; 3832 } 3833 3834 /* 3835 * Now back to real business: Figure out the depth, bpp, etc. 3836 * Set SupportConvert... flags since we use the fb layer which 3837 * supports this conversion. (24to32 seems not implemented though) 3838 * Additionally, determine the size of the HWCursor memory area. 3839 */ 3840 switch(pSiS->VGAEngine) { 3841 case SIS_300_VGA: 3842 pSiS->CursorSize = 4096; 3843 pix24flags = Support32bppFb; 3844 break; 3845 case SIS_315_VGA: 3846 pSiS->CursorSize = 16384; 3847 pix24flags = Support32bppFb; 3848 break; 3849 case SIS_530_VGA: 3850 pSiS->CursorSize = 2048; 3851 pix24flags = Support32bppFb | 3852 Support24bppFb | 3853 SupportConvert32to24; 3854 break; 3855 default: 3856 pSiS->CursorSize = 2048; 3857 pix24flags = Support24bppFb | 3858 SupportConvert32to24 | 3859 PreferConvert32to24; 3860 break; 3861 } 3862 3863#ifdef SISDUALHEAD 3864 /* In case of Dual Head, we need to determine if we are the "master" head or 3865 * the "slave" head. In order to do that, we set PrimInit to DONE in the 3866 * shared entity at the end of the first initialization. The second 3867 * initialization then knows that some things have already been done. THIS 3868 * ALWAYS ASSUMES THAT THE FIRST DEVICE INITIALIZED IS THE MASTER! 3869 */ 3870 if(xf86IsEntityShared(pScrn->entityList[0])) { 3871 if(pSiSEnt->lastInstance > 0) { 3872 if(!xf86IsPrimInitDone(pScrn->entityList[0])) { 3873 /* First Head (always CRT2) */ 3874 pSiS->SecondHead = FALSE; 3875 pSiSEnt->pScrn_1 = pScrn; 3876 pSiSEnt->CRT1ModeNo = pSiSEnt->CRT2ModeNo = -1; 3877 pSiSEnt->CRT2ModeSet = FALSE; 3878 pSiS->DualHeadMode = TRUE; 3879 pSiSEnt->DisableDual = FALSE; 3880 pSiSEnt->BIOS = NULL; 3881 pSiSEnt->ROM661New = FALSE; 3882 pSiSEnt->HaveXGIBIOS = FALSE; 3883 pSiSEnt->SiS_Pr = NULL; 3884 pSiSEnt->RenderAccelArray = NULL; 3885 pSiSEnt->SiSFastVidCopy = pSiSEnt->SiSFastMemCopy = NULL; 3886 pSiSEnt->SiSFastVidCopyFrom = pSiSEnt->SiSFastMemCopyFrom = NULL; 3887 } else { 3888 /* Second Head (always CRT1) */ 3889 pSiS->SecondHead = TRUE; 3890 pSiSEnt->pScrn_2 = pScrn; 3891 pSiS->DualHeadMode = TRUE; 3892 } 3893 } else { 3894 /* Only one screen in config file - disable dual head mode */ 3895 pSiS->SecondHead = FALSE; 3896 pSiS->DualHeadMode = FALSE; 3897 pSiSEnt->DisableDual = TRUE; 3898 } 3899 } else { 3900 /* Entity is not shared - disable dual head mode */ 3901 pSiS->SecondHead = FALSE; 3902 pSiS->DualHeadMode = FALSE; 3903 } 3904#endif 3905 3906 /* Save the name of our Device section for SiSCtrl usage */ 3907 { 3908 int ttt = 0; 3909 GDevPtr device = xf86GetDevFromEntity(pScrn->entityList[0], 3910 pScrn->entityInstanceList[0]); 3911 if(device && device->identifier) { 3912 if((ttt = strlen(device->identifier)) > 31) ttt = 31; 3913 strncpy(&pSiS->devsectname[0], device->identifier, 31); 3914 } 3915 pSiS->devsectname[ttt] = 0; 3916 } 3917 3918 pSiS->ForceCursorOff = FALSE; 3919 3920 /* Allocate SiS_Private (for mode switching code) and initialize it */ 3921 pSiS->SiS_Pr = NULL; 3922#ifdef SISDUALHEAD 3923 if(pSiSEnt) { 3924 if(pSiSEnt->SiS_Pr) pSiS->SiS_Pr = pSiSEnt->SiS_Pr; 3925 } 3926#endif 3927 if(!pSiS->SiS_Pr) { 3928 if(!(pSiS->SiS_Pr = xnfcalloc(sizeof(struct SiS_Private), 1))) { 3929 SISErrorLog(pScrn, "Could not allocate memory for SiS_Pr structure\n"); 3930 goto my_error_1; 3931 } 3932#ifdef SISDUALHEAD 3933 if(pSiSEnt) pSiSEnt->SiS_Pr = pSiS->SiS_Pr; 3934#endif 3935 memset(pSiS->SiS_Pr, 0, sizeof(struct SiS_Private)); 3936#ifndef XSERVER_LIBPCIACCESS 3937 pSiS->SiS_Pr->PciTag = pSiS->PciTag; 3938#endif 3939 pSiS->SiS_Pr->ChipType = pSiS->ChipType; 3940 pSiS->SiS_Pr->ChipRevision = pSiS->ChipRev; 3941 pSiS->SiS_Pr->SiS_Backup70xx = 0xff; 3942 pSiS->SiS_Pr->SiS_CHOverScan = -1; 3943 pSiS->SiS_Pr->SiS_ChSW = FALSE; 3944 pSiS->SiS_Pr->SiS_CustomT = CUT_NONE; 3945 pSiS->SiS_Pr->SiS_UseWide = -1; 3946 pSiS->SiS_Pr->SiS_UseWideCRT2 = -1; 3947 pSiS->SiS_Pr->SiS_TVBlue = -1; 3948 pSiS->SiS_Pr->PanelSelfDetected = FALSE; 3949 pSiS->SiS_Pr->UsePanelScaler = -1; 3950 pSiS->SiS_Pr->CenterScreen = -1; 3951 pSiS->SiS_Pr->CRT1UsesCustomMode = FALSE; 3952 pSiS->SiS_Pr->PDC = pSiS->SiS_Pr->PDCA = -1; 3953 pSiS->SiS_Pr->LVDSHL = -1; 3954 pSiS->SiS_Pr->HaveEMI = FALSE; 3955 pSiS->SiS_Pr->HaveEMILCD = FALSE; 3956 pSiS->SiS_Pr->OverruleEMI = FALSE; 3957 pSiS->SiS_Pr->SiS_SensibleSR11 = FALSE; 3958 if(pSiS->ChipType >= SIS_661) { 3959 pSiS->SiS_Pr->SiS_SensibleSR11 = TRUE; 3960 } 3961 pSiS->SiS_Pr->SiS_MyCR63 = pSiS->myCR63; 3962 pSiS->SiS_Pr->DDCPortMixup = FALSE; 3963 } 3964 3965 /* Copy IO address to SiS_Pr and init the structure for 3966 * routines inside init.c/init301.c 3967 */ 3968 pSiS->SiS_Pr->IOAddress = (SISIOADDRESS)(pSiS->RelIO + 0x30); 3969 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO + 0x30); 3970 3971 /* The following identifies the old chipsets. This is only 3972 * partly used since the really old chips are not supported, 3973 * but I keep it here for future use. 3974 * 205, 215 and 225 are to be treated the same way, 201 and 202 3975 * are different. 3976 */ 3977 if(pSiS->VGAEngine == SIS_OLD_VGA || pSiS->VGAEngine == SIS_530_VGA) { 3978 switch(pSiS->Chipset) { 3979 case PCI_CHIP_SG86C201: 3980 pSiS->oldChipset = OC_SIS86201; break; 3981 case PCI_CHIP_SG86C202: 3982 pSiS->oldChipset = OC_SIS86202; break; 3983 case PCI_CHIP_SG86C205: 3984 inSISIDXREG(SISSR, 0x10, tempreg); 3985 if(tempreg & 0x80) pSiS->oldChipset = OC_SIS6205B; 3986 else pSiS->oldChipset = (pSiS->ChipRev == 0x11) ? 3987 OC_SIS6205C : OC_SIS6205A; 3988 break; 3989 case PCI_CHIP_SIS82C204: 3990 pSiS->oldChipset = OC_SIS82204; break; 3991 case 0x6225: 3992 pSiS->oldChipset = OC_SIS6225; break; 3993 case PCI_CHIP_SIS5597: 3994 pSiS->oldChipset = OC_SIS5597; break; 3995 case PCI_CHIP_SIS6326: 3996 pSiS->oldChipset = OC_SIS6326; break; 3997 case PCI_CHIP_SIS530: 3998 if(sis_pci_read_host_bridge_u32(0x00) == 0x06201039) { 3999 pSiS->oldChipset = OC_SIS620; 4000 } else { 4001 if((pSiS->ChipRev & 0x0f) < 0x0a) 4002 pSiS->oldChipset = OC_SIS530A; 4003 else pSiS->oldChipset = OC_SIS530B; 4004 } 4005 break; 4006 default: 4007 pSiS->oldChipset = OC_UNKNOWN; 4008 } 4009 } 4010 4011 if(!xf86SetDepthBpp(pScrn, 0, 0, 0, pix24flags)) { 4012 SISErrorLog(pScrn, "xf86SetDepthBpp() error\n"); 4013 goto my_error_1; 4014 } 4015 4016 /* Check that the returned depth is one we support */ 4017 temp = 0; 4018 switch(pScrn->depth) { 4019 case 8: 4020 case 16: 4021 case 24: 4022 break; 4023 case 15: 4024 if((pSiS->VGAEngine == SIS_300_VGA) || 4025 (pSiS->VGAEngine == SIS_315_VGA)) { 4026 temp = 1; 4027 } 4028 break; 4029 default: 4030 temp = 1; 4031 } 4032 4033 if(temp) { 4034 SISErrorLog(pScrn, 4035 "Given color depth (%d) is not supported by this driver/chipset\n", 4036 pScrn->depth); 4037 goto my_error_1; 4038 } 4039 4040 xf86PrintDepthBpp(pScrn); 4041 4042 if( (((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) && 4043 (pScrn->bitsPerPixel == 24)) || 4044 ((pSiS->VGAEngine == SIS_OLD_VGA) && (pScrn->bitsPerPixel == 32)) ) { 4045 SISErrorLog(pScrn, 4046 "Framebuffer bpp %d not supported for this chipset\n", pScrn->bitsPerPixel); 4047 goto my_error_1; 4048 } 4049 4050 /* Get the depth24 pixmap format */ 4051 if(pScrn->depth == 24 && pix24bpp == 0) { 4052 pix24bpp = xf86GetBppFromDepth(pScrn, 24); 4053 } 4054 4055 /* 4056 * This must happen after pScrn->display has been set because 4057 * xf86SetWeight references it. 4058 */ 4059 if(pScrn->depth > 8) { 4060 /* The defaults are OK for us */ 4061 rgb zeros = {0, 0, 0}; 4062 4063 if(!xf86SetWeight(pScrn, zeros, zeros)) { 4064 SISErrorLog(pScrn, "xf86SetWeight() error\n"); 4065 goto my_error_1; 4066 } else { 4067 Bool ret = FALSE; 4068 switch(pScrn->depth) { 4069 case 15: 4070 if((pScrn->weight.red != 5) || 4071 (pScrn->weight.green != 5) || 4072 (pScrn->weight.blue != 5)) ret = TRUE; 4073 break; 4074 case 16: 4075 if((pScrn->weight.red != 5) || 4076 (pScrn->weight.green != 6) || 4077 (pScrn->weight.blue != 5)) ret = TRUE; 4078 break; 4079 case 24: 4080 if((pScrn->weight.red != 8) || 4081 (pScrn->weight.green != 8) || 4082 (pScrn->weight.blue != 8)) ret = TRUE; 4083 break; 4084 } 4085 if(ret) { 4086 SISErrorLog(pScrn, 4087 "RGB weight %d%d%d at depth %d not supported by hardware\n", 4088 (int)pScrn->weight.red, (int)pScrn->weight.green, 4089 (int)pScrn->weight.blue, pScrn->depth); 4090 goto my_error_1; 4091 } 4092 } 4093 } 4094 4095 /* Set the current layout parameters */ 4096 pSiS->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel; 4097 pSiS->CurrentLayout.depth = pScrn->depth; 4098 /* (Inside this function, we can use pScrn's contents anyway) */ 4099 4100 if(!xf86SetDefaultVisual(pScrn, -1)) { 4101 SISErrorLog(pScrn, "xf86SetDefaultVisual() error\n"); 4102 goto my_error_1; 4103 } else { 4104 /* We don't support DirectColor at > 8bpp */ 4105 if(pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { 4106 SISErrorLog(pScrn, 4107 "Given default visual (%s) is not supported at depth %d\n", 4108 xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); 4109 goto my_error_1; 4110 } 4111 } 4112 4113#ifdef SISDUALHEAD 4114 /* Due to palette & timing problems we don't support 8bpp in DHM */ 4115 if((pSiS->DualHeadMode) && (pScrn->bitsPerPixel <= 8)) { 4116 SISErrorLog(pScrn, "Color depth %d not supported in Dual Head mode.\n", 4117 pScrn->bitsPerPixel); 4118 goto my_error_1; 4119 } 4120#endif 4121 4122 /* Read BIOS for 300/315/330/340 series customization */ 4123 pSiS->SiS_Pr->VirtualRomBase = NULL; 4124 pSiS->BIOS = NULL; 4125 pSiS->SiS_Pr->UseROM = FALSE; 4126 pSiS->ROM661New = FALSE; 4127 pSiS->HaveXGIBIOS = FALSE; 4128 4129 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 4130#ifdef SISDUALHEAD 4131 if(pSiSEnt) { 4132 if(pSiSEnt->BIOS) { 4133 pSiS->BIOS = pSiSEnt->BIOS; 4134 pSiS->SiS_Pr->VirtualRomBase = pSiS->BIOS; 4135 pSiS->ROM661New = pSiSEnt->ROM661New; 4136 pSiS->HaveXGIBIOS = pSiSEnt->HaveXGIBIOS; 4137 } 4138 } 4139#endif 4140 if(!pSiS->BIOS) { 4141 if(!(pSiS->BIOS = calloc(1, BIOS_SIZE))) { 4142 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4143 "Could not allocate memory for video BIOS image\n"); 4144 } else { 4145 UShort mypciid = pSiS->Chipset; 4146 UShort mypcivendor = (pSiS->ChipFlags & SiSCF_IsXGI) ? PCI_VENDOR_XGI : PCI_VENDOR_SIS; 4147 Bool found = FALSE, readpci = FALSE; 4148 int biossize = BIOS_SIZE; 4149 4150 switch(pSiS->ChipType) { 4151 case SIS_315: mypciid = PCI_CHIP_SIS315; 4152 readpci = TRUE; 4153 break; 4154 case SIS_315PRO: mypciid = PCI_CHIP_SIS315PRO; 4155 readpci = TRUE; 4156 break; 4157 case SIS_300: 4158 case SIS_315H: 4159 case SIS_330: 4160 case SIS_340: 4161 case SIS_650: 4162 case SIS_760: 4163 case XGI_40: readpci = TRUE; 4164 break; 4165 case XGI_20: readpci = TRUE; 4166 biossize = 0x8000; 4167 break; 4168 } 4169#if XSERVER_LIBPCIACCESS 4170 if(readpci) { 4171 pSiS->PciInfo->rom_size = biossize; 4172 pci_device_read_rom(pSiS->PciInfo, pSiS->BIOS); 4173 if(SISCheckBIOS(pSiS, mypciid, mypcivendor, biossize)) { 4174 found = TRUE; 4175 } 4176 } 4177#else 4178 if(readpci) { 4179 xf86ReadPciBIOS(0, pSiS->PciTag, 0, pSiS->BIOS, biossize); 4180 if(SISCheckBIOS(pSiS, mypciid, mypcivendor, biossize)) { 4181 found = TRUE; 4182 } 4183 } 4184 4185 if(!found) { 4186 ULong segstart; 4187 for(segstart = BIOS_BASE; segstart < 0x000f0000; segstart += 0x00001000) { 4188 4189#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 4190 if(xf86ReadBIOS(segstart, 0, pSiS->BIOS, biossize) != biossize) continue; 4191#else 4192 if(xf86ReadDomainMemory(pSiS->PciTag, segstart, biossize, pSiS->BIOS) != biossize) continue; 4193#endif 4194 4195 if(!SISCheckBIOS(pSiS, mypciid, mypcivendor, biossize)) continue; 4196 4197 found = TRUE; 4198 break; 4199 } 4200 } 4201#endif 4202 if(found) { 4203 UShort romptr = pSiS->BIOS[0x16] | (pSiS->BIOS[0x17] << 8); 4204 pSiS->SiS_Pr->VirtualRomBase = pSiS->BIOS; 4205 if(pSiS->ChipFlags & SiSCF_IsXGI) { 4206 pSiS->HaveXGIBIOS = pSiS->SiS_Pr->SiS_XGIROM = TRUE; 4207 pSiS->SiS_Pr->UseROM = FALSE; 4208 if(pSiS->ChipFlags & SiSCF_IsXGIV3) { 4209 if(!(pSiS->BIOS[0x1d1] & 0x01)) { 4210 pSiS->SiS_Pr->DDCPortMixup = TRUE; 4211 } 4212 } 4213 } else { 4214 pSiS->ROM661New = SiSDetermineROMLayout661(pSiS->SiS_Pr); 4215 } 4216 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4217 "Video BIOS version \"%7s\" found (%s data layout)\n", 4218 &pSiS->BIOS[romptr], pSiS->ROM661New ? "new SiS" : 4219 (pSiS->HaveXGIBIOS ? "XGI" : "old SiS")); 4220 if(pSiS->SiS_Pr->DDCPortMixup) { 4221 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4222 "*** Buggy XGI V3XT card detected: If VGA and DVI are connected at the\n"); 4223 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4224 "*** same time, BIOS and driver will be unable to detect DVI connection.\n"); 4225 } 4226#ifdef SISDUALHEAD 4227 if(pSiSEnt) { 4228 pSiSEnt->BIOS = pSiS->BIOS; 4229 pSiSEnt->ROM661New = pSiS->ROM661New; 4230 pSiSEnt->HaveXGIBIOS = pSiS->HaveXGIBIOS; 4231 } 4232#endif 4233 } else { 4234 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4235 "Could not find/read video BIOS\n"); 4236 free(pSiS->BIOS); 4237 pSiS->BIOS = NULL; 4238 } 4239 } 4240 } 4241 4242 if(!(pSiS->ChipFlags & SiSCF_IsXGI)) { 4243 if(pSiS->BIOS) pSiS->SiS_Pr->UseROM = TRUE; 4244 else pSiS->SiS_Pr->UseROM = FALSE; 4245 } 4246 } 4247 4248 /* Evaluate options */ 4249 SiSOptions(pScrn); 4250 4251#ifdef SISMERGED 4252 /* Due to palette & timing problems we don't support 8bpp in MFBM */ 4253 if((pSiS->MergedFB) && (pScrn->bitsPerPixel <= 8)) { 4254 SISErrorLog(pScrn, "MergedFB: Color depth %d not supported, %s\n", 4255 pScrn->bitsPerPixel, mergeddisstr); 4256 pSiS->MergedFB = pSiS->MergedFBAuto = FALSE; 4257 } 4258#endif 4259 4260 /* Probe CPU features */ 4261#ifdef SISDUALHEAD 4262 if(pSiS->DualHeadMode) { 4263 pSiS->CPUFlags = pSiSEnt->CPUFlags; 4264 } 4265#endif 4266 if(!pSiS->CPUFlags) { 4267 pSiS->CPUFlags = SiSGetCPUFlags(pScrn); 4268 pSiS->CPUFlags |= SIS_CPUFL_FLAG; 4269#ifdef SISDUALHEAD 4270 if(pSiS->DualHeadMode) pSiSEnt->CPUFlags = pSiS->CPUFlags; 4271#endif 4272 } 4273 4274 /* We use a programamble clock */ 4275 pScrn->progClock = TRUE; 4276 4277 /* Set the bits per RGB for 8bpp mode */ 4278 if(pScrn->depth == 8) pScrn->rgbBits = 8; 4279 4280#ifdef SISDUALHEAD 4281 if(pSiS->DualHeadMode) { 4282 if(!pSiS->SecondHead) { 4283 /* Copy some option settings to entity private */ 4284 pSiSEnt->HWCursor = pSiS->HWCursor; 4285 pSiSEnt->NoAccel = pSiS->NoAccel; 4286 pSiSEnt->useEXA = pSiS->useEXA; 4287 pSiSEnt->restorebyset = pSiS->restorebyset; 4288 pSiSEnt->OptROMUsage = pSiS->OptROMUsage; 4289 pSiSEnt->OptUseOEM = pSiS->OptUseOEM; 4290 pSiSEnt->TurboQueue = pSiS->TurboQueue; 4291 pSiSEnt->forceCRT1 = pSiS->forceCRT1; 4292 pSiSEnt->ForceCRT1Type = pSiS->ForceCRT1Type; 4293 pSiSEnt->CRT1TypeForced = pSiS->CRT1TypeForced; 4294 pSiSEnt->ForceCRT2Type = pSiS->ForceCRT2Type; 4295 pSiSEnt->ForceTVType = pSiS->ForceTVType; 4296 pSiSEnt->ForceYPbPrType = pSiS->ForceYPbPrType; 4297 pSiSEnt->ForceYPbPrAR = pSiS->ForceYPbPrAR; 4298 pSiSEnt->UsePanelScaler = pSiS->UsePanelScaler; 4299 pSiSEnt->CenterLCD = pSiS->CenterLCD; 4300 pSiSEnt->DSTN = pSiS->DSTN; 4301 pSiSEnt->FSTN = pSiS->FSTN; 4302 pSiSEnt->OptTVStand = pSiS->OptTVStand; 4303 pSiSEnt->NonDefaultPAL = pSiS->NonDefaultPAL; 4304 pSiSEnt->NonDefaultNTSC = pSiS->NonDefaultNTSC; 4305 pSiSEnt->chtvtype = pSiS->chtvtype; 4306 pSiSEnt->OptTVOver = pSiS->OptTVOver; 4307 pSiSEnt->OptTVSOver = pSiS->OptTVSOver; 4308 pSiSEnt->chtvlumabandwidthcvbs = pSiS->chtvlumabandwidthcvbs; 4309 pSiSEnt->chtvlumabandwidthsvideo = pSiS->chtvlumabandwidthsvideo; 4310 pSiSEnt->chtvlumaflickerfilter = pSiS->chtvlumaflickerfilter; 4311 pSiSEnt->chtvchromabandwidth = pSiS->chtvchromabandwidth; 4312 pSiSEnt->chtvchromaflickerfilter = pSiS->chtvchromaflickerfilter; 4313 pSiSEnt->chtvtextenhance = pSiS->chtvtextenhance; 4314 pSiSEnt->chtvcontrast = pSiS->chtvcontrast; 4315 pSiSEnt->chtvcvbscolor = pSiS->chtvcvbscolor; 4316 pSiSEnt->sistvedgeenhance = pSiS->sistvedgeenhance; 4317 pSiSEnt->sistvantiflicker = pSiS->sistvantiflicker; 4318 pSiSEnt->sistvsaturation = pSiS->sistvsaturation; 4319 pSiSEnt->sistvcfilter = pSiS->sistvcfilter; 4320 pSiSEnt->sistvyfilter = pSiS->sistvyfilter; 4321 pSiSEnt->sistvcolcalibc = pSiS->sistvcolcalibc; 4322 pSiSEnt->sistvcolcalibf = pSiS->sistvcolcalibf; 4323 pSiSEnt->tvxpos = pSiS->tvxpos; 4324 pSiSEnt->tvypos = pSiS->tvypos; 4325 pSiSEnt->tvxscale = pSiS->tvxscale; 4326 pSiSEnt->tvyscale = pSiS->tvyscale; 4327 pSiSEnt->siscrt1satgain = pSiS->siscrt1satgain; 4328 pSiSEnt->crt1satgaingiven = pSiS->crt1satgaingiven; 4329 pSiSEnt->CRT1gamma = pSiS->CRT1gamma; 4330 pSiSEnt->CRT1gammaGiven = pSiS->CRT1gammaGiven; 4331 pSiSEnt->XvGammaRed = pSiS->XvGammaRed; 4332 pSiSEnt->XvGammaGreen = pSiS->XvGammaGreen; 4333 pSiSEnt->XvGammaBlue = pSiS->XvGammaBlue; 4334 pSiSEnt->XvGamma = pSiS->XvGamma; 4335 pSiSEnt->XvGammaGiven = pSiS->XvGammaGiven; 4336 pSiSEnt->CRT2gamma = pSiS->CRT2gamma; 4337 pSiSEnt->XvOnCRT2 = pSiS->XvOnCRT2; 4338 pSiSEnt->AllowHotkey = pSiS->AllowHotkey; 4339 pSiSEnt->enablesisctrl = pSiS->enablesisctrl; 4340 pSiSEnt->SenseYPbPr = pSiS->SenseYPbPr; 4341 pSiSEnt->XvUseMemcpy = pSiS->XvUseMemcpy; 4342 pSiSEnt->BenchMemCpy = pSiS->BenchMemCpy; 4343#ifdef SIS_CP 4344 SIS_CP_DRIVER_COPYOPTIONSENT 4345#endif 4346 } else { 4347 /* We always use same cursor type on both screens */ 4348 pSiS->HWCursor = pSiSEnt->HWCursor; 4349 /* We need identical NoAccel setting */ 4350 pSiS->NoAccel = pSiSEnt->NoAccel; 4351 pSiS->useEXA = pSiSEnt->useEXA; 4352 pSiS->TurboQueue = pSiSEnt->TurboQueue; 4353 pSiS->restorebyset = pSiSEnt->restorebyset; 4354 pSiS->AllowHotkey = pSiS->AllowHotkey; 4355 pSiS->OptROMUsage = pSiSEnt->OptROMUsage; 4356 pSiS->OptUseOEM = pSiSEnt->OptUseOEM; 4357 pSiS->forceCRT1 = pSiSEnt->forceCRT1; 4358 pSiS->nocrt2ddcdetection = FALSE; 4359 pSiS->forcecrt2redetection = FALSE; 4360 pSiS->ForceCRT1Type = pSiSEnt->ForceCRT1Type; 4361 pSiS->ForceCRT2Type = pSiSEnt->ForceCRT2Type; 4362 pSiS->CRT1TypeForced = pSiSEnt->CRT1TypeForced; 4363 pSiS->UsePanelScaler = pSiSEnt->UsePanelScaler; 4364 pSiS->CenterLCD = pSiSEnt->CenterLCD; 4365 pSiS->DSTN = pSiSEnt->DSTN; 4366 pSiS->FSTN = pSiSEnt->FSTN; 4367 pSiS->OptTVStand = pSiSEnt->OptTVStand; 4368 pSiS->NonDefaultPAL = pSiSEnt->NonDefaultPAL; 4369 pSiS->NonDefaultNTSC = pSiSEnt->NonDefaultNTSC; 4370 pSiS->chtvtype = pSiSEnt->chtvtype; 4371 pSiS->ForceTVType = pSiSEnt->ForceTVType; 4372 pSiS->ForceYPbPrType = pSiSEnt->ForceYPbPrType; 4373 pSiS->ForceYPbPrAR = pSiSEnt->ForceYPbPrAR; 4374 pSiS->OptTVOver = pSiSEnt->OptTVOver; 4375 pSiS->OptTVSOver = pSiSEnt->OptTVSOver; 4376 pSiS->chtvlumabandwidthcvbs = pSiSEnt->chtvlumabandwidthcvbs; 4377 pSiS->chtvlumabandwidthsvideo = pSiSEnt->chtvlumabandwidthsvideo; 4378 pSiS->chtvlumaflickerfilter = pSiSEnt->chtvlumaflickerfilter; 4379 pSiS->chtvchromabandwidth = pSiSEnt->chtvchromabandwidth; 4380 pSiS->chtvchromaflickerfilter = pSiSEnt->chtvchromaflickerfilter; 4381 pSiS->chtvcvbscolor = pSiSEnt->chtvcvbscolor; 4382 pSiS->chtvtextenhance = pSiSEnt->chtvtextenhance; 4383 pSiS->chtvcontrast = pSiSEnt->chtvcontrast; 4384 pSiS->sistvedgeenhance = pSiSEnt->sistvedgeenhance; 4385 pSiS->sistvantiflicker = pSiSEnt->sistvantiflicker; 4386 pSiS->sistvsaturation = pSiSEnt->sistvsaturation; 4387 pSiS->sistvcfilter = pSiSEnt->sistvcfilter; 4388 pSiS->sistvyfilter = pSiSEnt->sistvyfilter; 4389 pSiS->sistvcolcalibc = pSiSEnt->sistvcolcalibc; 4390 pSiS->sistvcolcalibf = pSiSEnt->sistvcolcalibf; 4391 pSiS->tvxpos = pSiSEnt->tvxpos; 4392 pSiS->tvypos = pSiSEnt->tvypos; 4393 pSiS->tvxscale = pSiSEnt->tvxscale; 4394 pSiS->tvyscale = pSiSEnt->tvyscale; 4395 pSiS->SenseYPbPr = pSiSEnt->SenseYPbPr; 4396 if(!pSiS->CRT1gammaGiven) { 4397 if(pSiSEnt->CRT1gammaGiven) 4398 pSiS->CRT1gamma = pSiSEnt->CRT1gamma; 4399 } 4400 pSiS->CRT2gamma = pSiSEnt->CRT2gamma; 4401 if(!pSiS->XvGammaGiven) { 4402 if(pSiSEnt->XvGammaGiven) { 4403 pSiS->XvGamma = pSiSEnt->XvGamma; 4404 pSiS->XvGammaRed = pSiS->XvGammaRedDef = pSiSEnt->XvGammaRed; 4405 pSiS->XvGammaGreen = pSiS->XvGammaGreenDef = pSiSEnt->XvGammaGreen; 4406 pSiS->XvGammaBlue = pSiS->XvGammaBlueDef = pSiSEnt->XvGammaBlue; 4407 } 4408 } 4409 if(!pSiS->crt1satgaingiven) { 4410 if(pSiSEnt->crt1satgaingiven) 4411 pSiS->siscrt1satgain = pSiSEnt->siscrt1satgain; 4412 } 4413 pSiS->XvOnCRT2 = pSiSEnt->XvOnCRT2; 4414 pSiS->enablesisctrl = pSiSEnt->enablesisctrl; 4415 pSiS->XvUseMemcpy = pSiSEnt->XvUseMemcpy; 4416 pSiS->BenchMemCpy = pSiSEnt->BenchMemCpy; 4417 /* Copy gamma brightness to Ent (sic!) for Xinerama */ 4418 pSiSEnt->GammaBriR = pSiS->GammaBriR; 4419 pSiSEnt->GammaBriG = pSiS->GammaBriG; 4420 pSiSEnt->GammaBriB = pSiS->GammaBriB; 4421 pSiSEnt->NewGammaBriR = pSiS->NewGammaBriR; 4422 pSiSEnt->NewGammaBriG = pSiS->NewGammaBriG; 4423 pSiSEnt->NewGammaBriB = pSiS->NewGammaBriB; 4424 pSiSEnt->NewGammaConR = pSiS->NewGammaConR; 4425 pSiSEnt->NewGammaConG = pSiS->NewGammaConG; 4426 pSiSEnt->NewGammaConB = pSiS->NewGammaConB; 4427#ifdef SIS_CP 4428 SIS_CP_DRIVER_COPYOPTIONS 4429#endif 4430 } 4431 } 4432#endif 4433 4434 /* Handle UseROMData, NoOEM and UsePanelScaler options */ 4435 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 4436 from = X_PROBED; 4437 if(pSiS->OptROMUsage == 0) { 4438 pSiS->SiS_Pr->UseROM = FALSE; 4439 from = X_CONFIG; 4440 xf86DrvMsg(pScrn->scrnIndex, from, "Video ROM data usage is disabled\n"); 4441 } 4442 4443 if(!pSiS->OptUseOEM) { 4444 xf86DrvMsg(pScrn->scrnIndex, from, "Internal OEM LCD/TV/VGA2 data usage is disabled\n"); 4445 } 4446 4447 pSiS->SiS_Pr->UsePanelScaler = pSiS->UsePanelScaler; 4448 pSiS->SiS_Pr->CenterScreen = pSiS->CenterLCD; 4449 } 4450 4451 /* Do some HW configuration detection (memory amount & type, clock, etc) */ 4452 SiSSetup(pScrn); 4453 4454 /* Get framebuffer address */ 4455 if(pSiS->pEnt->device->MemBase != 0) { 4456 /* 4457 * XXX Should check that the config file value matches one of the 4458 * PCI base address values. 4459 */ 4460 pSiS->FbAddress = pSiS->pEnt->device->MemBase; 4461 from = X_CONFIG; 4462 } else { 4463 pSiS->FbAddress = PCI_REGION_BASE(pSiS->PciInfo, 0, REGION_MEM) & 0xFFFFFFF0; 4464 from = X_PROBED; 4465 } 4466 4467#ifdef SISDUALHEAD 4468 if(pSiS->DualHeadMode) 4469 xf86DrvMsg(pScrn->scrnIndex, from, "Global linear framebuffer at 0x%lX\n", 4470 (ULong)pSiS->FbAddress); 4471 else 4472#endif 4473 xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", 4474 (ULong)pSiS->FbAddress); 4475 4476 pSiS->realFbAddress = pSiS->FbAddress; 4477 4478 /* Get MMIO address */ 4479 if(pSiS->pEnt->device->IOBase != 0) { 4480 /* 4481 * XXX Should check that the config file value matches one of the 4482 * PCI base address values. 4483 */ 4484 pSiS->IOAddress = pSiS->pEnt->device->IOBase; 4485 from = X_CONFIG; 4486 } else { 4487 pSiS->IOAddress = PCI_REGION_BASE(pSiS->PciInfo, 1, REGION_MEM) & 0xFFFFFFF0; 4488 from = X_PROBED; 4489 } 4490 xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX (size %ldK)\n", 4491 (ULong)pSiS->IOAddress, pSiS->mmioSize); 4492 4493#ifndef XSERVER_LIBPCIACCESS 4494 /* Register the PCI-assigned resources */ 4495 if(xf86RegisterResources(pSiS->pEnt->index, NULL, ResExclusive)) { 4496 SISErrorLog(pScrn, "PCI resource conflicts detected\n"); 4497#ifdef SISDUALHEAD 4498 if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; 4499#endif 4500 sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); 4501 if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); 4502 SISFreeRec(pScrn); 4503 return FALSE; 4504 } 4505#endif 4506 4507 from = X_PROBED; 4508 if(pSiS->pEnt->device->videoRam != 0) { 4509 if(pSiS->Chipset == PCI_CHIP_SIS6326) { 4510 pScrn->videoRam = pSiS->pEnt->device->videoRam; 4511 from = X_CONFIG; 4512 } else { 4513 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4514 "Option \"VideoRAM\" ignored\n"); 4515 } 4516 } 4517 4518 pSiS->RealVideoRam = pScrn->videoRam; 4519 4520 if((pSiS->Chipset == PCI_CHIP_SIS6326) && 4521 (pScrn->videoRam > 4096) && 4522 (from != X_CONFIG)) { 4523 pScrn->videoRam = 4096; 4524 xf86DrvMsg(pScrn->scrnIndex, from, 4525 "SiS6326: Detected %d KB VideoRAM, limiting to %d KB\n", 4526 pSiS->RealVideoRam, pScrn->videoRam); 4527 } else { 4528 xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d KB\n", pScrn->videoRam); 4529 } 4530 4531 if((pSiS->Chipset == PCI_CHIP_SIS6326) && 4532 (pScrn->videoRam > 4096)) { 4533 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4534 "SiS6326 engines do not support more than 4096KB RAM, therefore\n"); 4535 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4536 "TurboQueue, HWCursor, 2D acceleration and XVideo are disabled.\n"); 4537 pSiS->TurboQueue = FALSE; 4538 pSiS->HWCursor = FALSE; 4539 pSiS->NoXvideo = TRUE; 4540 pSiS->NoAccel = TRUE; 4541 } 4542 4543 pSiS->FbMapSize = pSiS->availMem = pScrn->videoRam * 1024; 4544 4545 /* Calculate real availMem according to Accel/TurboQueue and 4546 * HWCursur setting. Also, initialize some variables used 4547 * in other modules. 4548 */ 4549 pSiS->cursorOffset = 0; 4550 pSiS->CurARGBDest = NULL; 4551 pSiS->CurMonoSrc = NULL; 4552 pSiS->CurFGCol = pSiS->CurBGCol = 0; 4553 pSiS->FbBaseOffset = 0; 4554 4555 switch(pSiS->VGAEngine) { 4556 4557 case SIS_300_VGA: 4558 pSiS->TurboQueueLen = 512; 4559 if(pSiS->TurboQueue) { 4560 pSiS->availMem -= (pSiS->TurboQueueLen*1024); 4561 pSiS->cursorOffset = 512; 4562 } 4563 if(pSiS->HWCursor) { 4564 pSiS->availMem -= pSiS->CursorSize; 4565 if(pSiS->OptUseColorCursor) pSiS->availMem -= pSiS->CursorSize; 4566 } 4567 pSiS->CmdQueLenMask = 0xFFFF; 4568 pSiS->CmdQueLenFix = 0; 4569 pSiS->cursorBufferNum = 0; 4570#ifdef SISDUALHEAD 4571 if(pSiSEnt) pSiSEnt->cursorBufferNum = 0; 4572#endif 4573 break; 4574 4575 case SIS_315_VGA: 4576#ifdef SISVRAMQ /* VRAM queue */ 4577 pSiS->cmdQueueSizeMask = pSiS->cmdQueueSize - 1; /* VRAM Command Queue is variable (in therory) */ 4578 pSiS->cmdQueueOffset = (pScrn->videoRam * 1024) - pSiS->cmdQueueSize; 4579 pSiS->cmdQueueLen = 0; 4580 pSiS->cmdQueueSize_div2 = pSiS->cmdQueueSize / 2; 4581 pSiS->cmdQueueSize_div4 = pSiS->cmdQueueSize / 4; 4582 pSiS->cmdQueueSize_4_3 = (pSiS->cmdQueueSize / 4) * 3; 4583 pSiS->availMem -= pSiS->cmdQueueSize; 4584 pSiS->cursorOffset = (pSiS->cmdQueueSize / 1024); 4585 4586 /* Set up shared pointer to current offset */ 4587#ifdef SISDUALHEAD 4588 if(pSiS->DualHeadMode) 4589 pSiS->cmdQ_SharedWritePort = &(pSiSEnt->cmdQ_SharedWritePort_2D); 4590 else 4591#endif 4592 pSiS->cmdQ_SharedWritePort = &(pSiS->cmdQ_SharedWritePort_2D); 4593 4594 4595#else /* MMIO */ 4596 if(pSiS->TurboQueue) { 4597 pSiS->availMem -= (512*1024); /* MMIO Command Queue is 512k (variable in theory) */ 4598 pSiS->cursorOffset = 512; 4599 } 4600#endif 4601 if(pSiS->HWCursor) { 4602 pSiS->availMem -= (pSiS->CursorSize * 2); 4603 if(pSiS->OptUseColorCursor) pSiS->availMem -= (pSiS->CursorSize * 2); 4604 } 4605 pSiS->cursorBufferNum = 0; 4606#ifdef SISDUALHEAD 4607 if(pSiSEnt) pSiSEnt->cursorBufferNum = 0; 4608#endif 4609 4610 if((pSiS->SiS76xLFBSize) && (pSiS->SiS76xUMASize)) { 4611 pSiS->availMem -= pSiS->SiS76xUMASize; 4612 pSiS->FbBaseOffset = pSiS->SiS76xUMASize; 4613 } 4614 4615 break; 4616 4617 default: 4618 /* cursorOffset not used in cursor functions for 530 and 4619 * older chips, because the cursor is *above* the TQ. 4620 * On 5597 and older revisions of the 6326, the TQ is 4621 * max 32K, on newer 6326 revisions and the 530 either 30 4622 * (or 32?) or 62K (or 64?). However, to make sure, we 4623 * use only 30K (or 32?), but reduce the available memory 4624 * by 64, and locate the TQ at the beginning of this last 4625 * 64K block. (We do this that way even when using the 4626 * HWCursor, because the cursor only takes 2K and the 4627 * queue does not seem to last that far anyway.) 4628 * The TQ must be located at 32KB boundaries. 4629 */ 4630 if(pSiS->RealVideoRam < 3072) { 4631 if(pSiS->TurboQueue) { 4632 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4633 "Not enough video RAM for TurboQueue. TurboQueue disabled\n"); 4634 pSiS->TurboQueue = FALSE; 4635 } 4636 } 4637 pSiS->CmdQueMaxLen = 32; 4638 if(pSiS->TurboQueue) { 4639 pSiS->availMem -= (64*1024); 4640 pSiS->CmdQueMaxLen = 900; /* To make sure; should be 992 */ 4641 } else if(pSiS->HWCursor) { 4642 pSiS->availMem -= pSiS->CursorSize; 4643 } 4644 if(pSiS->Chipset == PCI_CHIP_SIS530) { 4645 /* Check if Flat Panel is enabled */ 4646 inSISIDXREG(SISSR, 0x0e, tempreg); 4647 if(!(tempreg & 0x04)) pSiS->availMem -= pSiS->CursorSize; 4648 4649 /* Set up mask for MMIO register */ 4650 pSiS->CmdQueLenMask = (pSiS->TurboQueue) ? 0x1FFF : 0x00FF; 4651 } else { 4652 /* TQ is never used on 6326/5597, because the accelerator 4653 * always Syncs. So this is just cosmentic work. (And I 4654 * am not even sure that 0x7fff is correct. MMIO 0x83a8 4655 * holds 0xec0 if (30k) TQ is enabled, 0x20 if TQ disabled. 4656 * The datasheet has no real explanation on the queue length 4657 * if the TQ is enabled. Not syncing and waiting for a 4658 * suitable queue length instead does not work. 4659 */ 4660 pSiS->CmdQueLenMask = (pSiS->TurboQueue) ? 0x7FFF : 0x003F; 4661 } 4662 4663 /* This is to be subtracted from MMIO queue length register contents 4664 * for getting the real Queue length. 4665 */ 4666 pSiS->CmdQueLenFix = (pSiS->TurboQueue) ? 32 : 0; 4667 } 4668 4669 4670#ifdef SISDUALHEAD 4671 /* In dual head mode, we share availMem equally - so align it 4672 * to 8KB; this way, the address of the FB of the second 4673 * head is aligned to 4KB for mapping. 4674 */ 4675 if(pSiS->DualHeadMode) pSiS->availMem &= 0xFFFFE000; 4676#endif 4677 4678 /* Check MaxXFBMem setting */ 4679#ifdef SISDUALHEAD 4680 if(pSiS->DualHeadMode) { 4681 /* 1. Since DRI is not supported in dual head mode, we 4682 * don't need the MaxXFBMem setting - ignore it. 4683 */ 4684 if(pSiS->maxxfbmem) { 4685 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4686 "MaxXFBMem ignored in Dual Head mode\n"); 4687 } 4688 pSiS->maxxfbmem = pSiS->availMem; 4689 } else 4690#endif 4691 if((pSiS->sisfbHeapStart) || (pSiS->sisfbHaveNewHeapDef)) { 4692 4693 /* 4694 * 2. We have memory layout info from sisfb - ignore MaxXFBMem 4695 */ 4696 if(pSiS->maxxfbmem) { 4697 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4698 "Got memory layout info from sisfb, ignoring MaxXFBMem option\n"); 4699 } 4700 if((pSiS->FbBaseOffset) && (!pSiS->sisfbHaveNewHeapDef)) { 4701 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4702 "Incompatible sisfb version detected, DRI disabled\n"); 4703 pSiS->loadDRI = FALSE; 4704 pSiS->maxxfbmem = pSiS->availMem; 4705 } else { 4706 if(pSiS->FbBaseOffset) { 4707 /* Revert our changes to FbBaseOffset and availMem; use sisfb's info */ 4708 pSiS->availMem += pSiS->FbBaseOffset; 4709 pSiS->FbBaseOffset = 0; 4710 } 4711 if(pSiS->sisfbVideoOffset) { 4712 /* a. DRI heap BELOW framebuffer */ 4713 pSiS->FbBaseOffset = pSiS->sisfbVideoOffset; 4714 pSiS->availMem -= pSiS->FbBaseOffset; 4715 pSiS->maxxfbmem = pSiS->availMem; 4716 } else { 4717 /* b. DRI heap ABOVE framebuffer (traditional layout) */ 4718 if(pSiS->availMem < (pSiS->sisfbHeapStart * 1024)) { 4719 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4720 "Internal error - sisfb memory layout corrupt\n"); 4721 pSiS->loadDRI = FALSE; 4722 pSiS->maxxfbmem = pSiS->availMem; 4723 } else { 4724 pSiS->maxxfbmem = pSiS->sisfbHeapStart * 1024; 4725 } 4726 } 4727 } 4728 4729 } else if(pSiS->maxxfbmem) { 4730 4731 /* 4732 * 3. No sisfb, but user gave "MaxXFBMem" 4733 */ 4734 if(pSiS->FbBaseOffset) { 4735 /* a. DRI heap BELOW framebuffer */ 4736 if(pSiS->maxxfbmem > (pSiS->availMem + pSiS->FbBaseOffset - pSiS->SiS76xUMASize)) { 4737 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4738 "Invalid MaxXFBMem setting\n"); 4739 pSiS->maxxfbmem = pSiS->availMem; 4740 } else { 4741 /* Revert our changes */ 4742 pSiS->availMem += pSiS->FbBaseOffset; 4743 /* Use user's MaxXFBMem setting */ 4744 pSiS->FbBaseOffset = pSiS->availMem - pSiS->maxxfbmem; 4745 pSiS->availMem -= pSiS->FbBaseOffset; 4746 } 4747 } else { 4748 /* b. DRI heap ABOVE framebuffer (traditional layout) */ 4749 if(pSiS->maxxfbmem > pSiS->availMem) { 4750 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4751 "Invalid MaxXFBMem setting.\n"); 4752 pSiS->maxxfbmem = pSiS->availMem; 4753 } 4754 } 4755 4756 } else { 4757 4758 /* 4759 * 4. No MaxXFBMem, no sisfb: Use all memory 4760 */ 4761 pSiS->maxxfbmem = pSiS->availMem; 4762 4763 /* ... except on chipsets, for which DRI is 4764 * supported: If DRI is enabled, we now limit 4765 * ourselves to a reasonable default: 4766 */ 4767 4768 if(pSiS->loadDRI) { 4769 if(pSiS->FbBaseOffset) { 4770 /* a. DRI heap BELOW framebuffer */ 4771 /* See how much UMA and LFB memory we have, 4772 * and calculate a reasonable default. We 4773 * use more vram for ourselves because these 4774 * chips are eg. capable of larger Xv 4775 * overlays, etc. 4776 */ 4777 unsigned long total = (pSiS->SiS76xLFBSize + pSiS->SiS76xUMASize) / 1024; 4778 unsigned long mymax; 4779 if(total <= 16384) /* <= 16MB: Use 8MB for X */ 4780 mymax = 8192 * 1024; 4781 else if(total <= 32768) /* <= 32MB: Use 16MB for X */ 4782 mymax = 16384 * 1024; 4783 else /* Otherwise: Use 20MB for X */ 4784 mymax = 20 * 1024 * 1024; 4785 /* availMem is right now adjusted to not use the UMA 4786 * area. Make sure that our default doesn't reach 4787 * into the UMA area either. 4788 */ 4789 if(pSiS->availMem > mymax) { 4790 /* Write our default to maxxfbmem */ 4791 pSiS->maxxfbmem = mymax; 4792 /* Revert our changes to availMem */ 4793 pSiS->availMem += pSiS->FbBaseOffset; 4794 /* Use our default setting */ 4795 pSiS->FbBaseOffset = pSiS->availMem - pSiS->maxxfbmem; 4796 pSiS->availMem -= pSiS->FbBaseOffset; 4797 } 4798 } else { 4799 /* b. DRI heap ABOVE framebuffer (traditional layout) */ 4800 /* See how much video memory we have, and calculate 4801 * a reasonable default. 4802 * Since DRI is pointless with less than 4MB of total 4803 * video RAM, we disable it in that case. 4804 */ 4805 if(pScrn->videoRam <= 4096) 4806 pSiS->loadDRI = FALSE; 4807 else if(pScrn->videoRam <= 8192) /* <= 8MB: Use 4MB for X */ 4808 pSiS->maxxfbmem = 4096 * 1024; 4809 else if(pScrn->videoRam <= 16384) /* <= 16MB: Use 8MB for X */ 4810 pSiS->maxxfbmem = 8192 * 1024; 4811#ifdef SISMERGED /* Otherwise: --- */ 4812 else if(pSiS->MergedFB) { 4813 if(pScrn->videoRam <= 65536) 4814 pSiS->maxxfbmem = 16384 * 1024; /* If MergedFB and <=64MB, use 16MB for X */ 4815 else 4816 pSiS->maxxfbmem = 20 * 1024 * 1024; /* If MergedFB and > 64MB, use 20MB for X */ 4817 } 4818#endif 4819 else if(pSiS->VGAEngine == SIS_315_VGA) { 4820 if(pScrn->videoRam <= 65536) 4821 pSiS->maxxfbmem = 16384 * 1024; /* On >=315 series and <=64MB, use 16MB */ 4822 else 4823 pSiS->maxxfbmem = 20 * 1024 * 1024; /* On >=315 series and > 64MB, use 20MB */ 4824 } else 4825 pSiS->maxxfbmem = 12288 * 1024; /* On <315 series, use 12MB */ 4826 4827 /* A final check */ 4828 if(pSiS->maxxfbmem > pSiS->availMem) { 4829 pSiS->maxxfbmem = pSiS->availMem; 4830 pSiS->loadDRI = FALSE; 4831 } 4832 } 4833 4834 } 4835 } 4836 4837 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %dK of framebuffer memory at offset %dK\n", 4838 pSiS->maxxfbmem / 1024, pSiS->FbBaseOffset / 1024); 4839 4840 /* Find out about sub-classes of some chipsets and check 4841 * if the chipset supports two video overlays 4842 */ 4843 if(pSiS->VGAEngine == SIS_300_VGA || 4844 pSiS->VGAEngine == SIS_315_VGA || 4845 pSiS->Chipset == PCI_CHIP_SIS530 || 4846 pSiS->Chipset == PCI_CHIP_SIS6326 || 4847 pSiS->Chipset == PCI_CHIP_SIS5597) { 4848 pSiS->hasTwoOverlays = FALSE; 4849 switch(pSiS->Chipset) { 4850 case PCI_CHIP_SIS300: 4851 case PCI_CHIP_SIS540: /* ? (If not, need to add the SwitchCRT Xv attribute!) */ 4852 case PCI_CHIP_SIS630: 4853 case PCI_CHIP_SIS550: 4854 pSiS->hasTwoOverlays = TRUE; 4855 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4856 break; 4857 case PCI_CHIP_SIS315PRO: 4858 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4859 break; 4860 case PCI_CHIP_SIS330: 4861 pSiS->ChipFlags |= (SiSCF_CRT2HWCKaputt | SiSCF_LARGEOVERLAY); 4862 break; 4863 case PCI_CHIP_SIS340: 4864 case PCI_CHIP_XGIXG40: /* Verified: only 1 overlay */ 4865 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4866 break; 4867 case PCI_CHIP_SIS650: 4868 { 4869 UChar tempreg1, tempreg2; 4870 static const char *id650str[] = { 4871 "650", "650", "650", "650", 4872 "650 A0 AA", "650 A2 CA", "650", "650", 4873 "M650 A0", "M650 A1 AA","651 A0 AA", "651 A1 AA", 4874 "M650", "65?", "651", "65?" 4875 }; 4876 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4877 if(pSiS->ChipType == SIS_650) { 4878 inSISIDXREG(SISCR, 0x5f, CR5F); 4879 CR5F &= 0xf0; 4880 andSISIDXREG(SISCR, 0x5c, 0x07); 4881 inSISIDXREG(SISCR, 0x5c, tempreg1); 4882 tempreg1 &= 0xf8; 4883 orSISIDXREG(SISCR, 0x5c, 0xf8); 4884 inSISIDXREG(SISCR, 0x5c, tempreg2); 4885 tempreg2 &= 0xf8; 4886 if((!tempreg1) || (tempreg2)) { 4887 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4888 "SiS650 revision ID %x (%s)\n", CR5F, id650str[CR5F >> 4]); 4889 if(CR5F & 0x80) { 4890 pSiS->hasTwoOverlays = TRUE; /* M650 or 651 */ 4891 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4892 } 4893 switch(CR5F) { 4894 case 0xa0: 4895 case 0xb0: 4896 case 0xe0: 4897 pSiS->ChipFlags |= SiSCF_Is651; 4898 break; 4899 case 0x80: 4900 case 0x90: 4901 case 0xc0: 4902 pSiS->ChipFlags |= SiSCF_IsM650; 4903 break; 4904 } 4905 } else { 4906 pSiS->hasTwoOverlays = TRUE; 4907 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4908 switch(CR5F) { 4909 case 0x90: 4910 inSISIDXREG(SISCR, 0x5c, tempreg1); 4911 tempreg1 &= 0xf8; 4912 switch(tempreg1) { 4913 case 0x00: 4914 pSiS->ChipFlags |= SiSCF_IsM652; 4915 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4916 "SiSM652 revision ID %x\n", CR5F); 4917 break; 4918 case 0x40: 4919 pSiS->ChipFlags |= SiSCF_IsM653; 4920 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4921 "SiSM653 revision ID %x\n", CR5F); 4922 break; 4923 default: 4924 pSiS->ChipFlags |= SiSCF_IsM650; 4925 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4926 "SiSM650 revision ID %x\n", CR5F); 4927 break; 4928 } 4929 break; 4930 case 0xb0: 4931 pSiS->ChipFlags |= SiSCF_Is652; 4932 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4933 "SiS652 revision ID %x\n", CR5F); 4934 break; 4935 default: 4936 pSiS->ChipFlags |= SiSCF_IsM650; 4937 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4938 "SiSM650 revision ID %x\n", CR5F); 4939 break; 4940 } 4941 } 4942 } 4943 break; 4944 } 4945 case PCI_CHIP_SIS660: 4946 { 4947 pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 4948 pSiS->hasTwoOverlays = TRUE; 4949 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 4950 /* 760/761: - UMA only: one/two overlays - dotclock dependent 4951 - UMA+LFB: two overlays if video data in LFB 4952 - LFB only: two overlays 4953 If UMA only: Must switch between one/two overlays on the fly (done 4954 in PostSetMode()) 4955 If LFB+UMA: We use LFB memory only and leave UMA to an eventually 4956 written DRI driver. 4957 */ 4958 break; 4959 } 4960 } 4961 4962 if(!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY)) { 4963 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 4964 "Hardware supports %s video overlay%s\n", 4965 pSiS->hasTwoOverlays ? "two" : "one", 4966 pSiS->hasTwoOverlays ? "s" : ""); 4967 } 4968 4969 if(pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORT760OO) { 4970 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4971 "\n\tDear SiS76x user, your machine is using a shared memory framebuffer.\n" 4972 "\tDue to hardware limitations of the SiS chip in combination with the\n" 4973 "\tAMD CPU, video overlay support is very limited on this machine. If you\n" 4974 "\texperience flashing lines in the video and/or the graphics display\n" 4975 "\tduring video playback, reduce the color depth and/or the resolution\n" 4976 "\tand/or the refresh rate. Alternatively, use the video blitter.\n"); 4977 } 4978 4979 } 4980 4981 /* Backup VB connection and CRT1 on/off register */ 4982 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 4983 inSISIDXREG(SISSR, 0x1f, pSiS->oldSR1F); 4984 inSISIDXREG(SISCR, 0x17, pSiS->oldCR17); 4985 inSISIDXREG(SISCR, 0x32, pSiS->oldCR32); 4986 inSISIDXREG(SISCR, 0x36, pSiS->oldCR36); 4987 inSISIDXREG(SISCR, 0x37, pSiS->oldCR37); 4988 if(pSiS->VGAEngine == SIS_315_VGA) { 4989 inSISIDXREG(SISCR, pSiS->myCR63, pSiS->oldCR63); 4990 } 4991 4992 pSiS->postVBCR32 = pSiS->oldCR32; 4993 } 4994 4995 /* There are some machines out there which require a special 4996 * setup of the GPIO registers in order to make the Chrontel 4997 * work. Try to find out if we're running on such a machine. 4998 * Furthermore, there is some highly customized hardware, 4999 * which requires some non-standard LVDS timing. Since the 5000 * vendors don't seem to care about PCI subsystem ID's we 5001 * need to find out using the BIOS version and date strings. 5002 */ 5003 pSiS->SiS_Pr->SiS_ChSW = FALSE; 5004 if(pSiS->Chipset == PCI_CHIP_SIS630) { 5005 int i = 0; 5006 do { 5007 if(mychswtable[i].subsysVendor == PCI_SUB_VENDOR_ID(pSiS->PciInfo) && 5008 mychswtable[i].subsysCard == PCI_SUB_DEVICE_ID(pSiS->PciInfo)) { 5009 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5010 "PCI subsystem ID found in list for Chrontel/GPIO setup:\n"); 5011 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5012 "\tVendor/Card: %s %s (ID %04x)\n", 5013 mychswtable[i].vendorName, 5014 mychswtable[i].cardName, 5015 PCI_SUB_DEVICE_ID(pSiS->PciInfo)); 5016 pSiS->SiS_Pr->SiS_ChSW = TRUE; 5017 break; 5018 } 5019 i++; 5020 } while(mychswtable[i].subsysVendor != 0); 5021 } 5022 5023 if(pSiS->SiS_Pr->SiS_CustomT == CUT_NONE) { 5024 int i = 0, j; 5025 UShort bversptr = 0; 5026 Bool footprint; 5027 CARD32 chksum = 0; 5028 5029 if(pSiS->SiS_Pr->UseROM) { 5030 bversptr = pSiS->BIOS[0x16] | (pSiS->BIOS[0x17] << 8); 5031 for(i=0; i<32768; i++) chksum += pSiS->BIOS[i]; 5032 } 5033 5034 i = 0; 5035 do { 5036 if( (SiS_customttable[i].chipID == pSiS->ChipType) && 5037 ((!strlen(SiS_customttable[i].biosversion)) || 5038 (pSiS->SiS_Pr->UseROM && 5039 (!strncmp(SiS_customttable[i].biosversion, (char *)&pSiS->BIOS[bversptr], 5040 strlen(SiS_customttable[i].biosversion))))) && 5041 ((!strlen(SiS_customttable[i].biosdate)) || 5042 (pSiS->SiS_Pr->UseROM && 5043 (!strncmp(SiS_customttable[i].biosdate, (char *)&pSiS->BIOS[0x2c], 5044 strlen(SiS_customttable[i].biosdate))))) && 5045 ((!SiS_customttable[i].bioschksum) || 5046 (pSiS->SiS_Pr->UseROM && 5047 (SiS_customttable[i].bioschksum == chksum))) && 5048 (SiS_customttable[i].pcisubsysvendor == PCI_SUB_VENDOR_ID(pSiS->PciInfo)) && 5049 (SiS_customttable[i].pcisubsyscard == PCI_SUB_DEVICE_ID(pSiS->PciInfo)) ) { 5050 footprint = TRUE; 5051 for(j=0; j<5; j++) { 5052 if(SiS_customttable[i].biosFootprintAddr[j]) { 5053 if(pSiS->SiS_Pr->UseROM) { 5054 if(pSiS->BIOS[SiS_customttable[i].biosFootprintAddr[j]] != 5055 SiS_customttable[i].biosFootprintData[j]) 5056 footprint = FALSE; 5057 } else footprint = FALSE; 5058 } 5059 } 5060 if(footprint) { 5061 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5062 "Identified %s %s, special timing applies\n", 5063 SiS_customttable[i].vendorName, SiS_customttable[i].cardName); 5064 pSiS->SiS_Pr->SiS_CustomT = SiS_customttable[i].SpecialID; 5065 break; 5066 } 5067 } 5068 i++; 5069 } while(SiS_customttable[i].chipID); 5070 } 5071 5072 /* Handle ForceCRT1 option */ 5073 if(pSiS->forceCRT1 != -1) { 5074 if(pSiS->forceCRT1) pSiS->CRT1off = 0; 5075 else pSiS->CRT1off = 1; 5076 } else pSiS->CRT1off = -1; 5077 5078 /* Detect video bridge and sense TV/VGA2 */ 5079 SISVGAPreInit(pScrn); 5080 5081 /* Detect CRT1 (via DDC1 and DDC2, hence via VGA port; regardless of LCDA) */ 5082 SISCRT1PreInit(pScrn); 5083 5084 /* Detect LCD (connected via CRT2, regardless of LCDA) and LCD resolution */ 5085 SISLCDPreInit(pScrn, FALSE); 5086 5087 /* LCDA only supported under these conditions: */ 5088 if(pSiS->ForceCRT1Type == CRT1_LCDA) { 5089 if(!SISDetermineLCDACap(pScrn)) { 5090 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5091 "Chipset/Video bridge does not support LCD-via-CRT1\n"); 5092 pSiS->ForceCRT1Type = CRT1_VGA; 5093 } else if(!(pSiS->VBFlags & CRT2_LCD)) { 5094 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5095 "No digital LCD panel found, LCD-via-CRT1 disabled\n"); 5096 pSiS->ForceCRT1Type = CRT1_VGA; 5097 } 5098 } 5099 5100 /* Setup SD flags */ 5101 pSiS->SiS_SD_Flags |= SiS_SD_ADDLSUPFLAG; 5102 5103 pSiS->SiS_SD2_Flags |= SiS_SD2_MERGEDUCLOCK; 5104 pSiS->SiS_SD2_Flags |= SiS_SD2_USEVBFLAGS2; 5105 pSiS->SiS_SD2_Flags |= SiS_SD2_VBINVB2ONLY; 5106 pSiS->SiS_SD2_Flags |= SiS_SD2_HAVESD34; 5107 pSiS->SiS_SD2_Flags |= SiS_SD2_NEWGAMMABRICON; 5108 5109 pSiS->SiS_SD3_Flags |= SiS_SD3_MFBALLOWOFFCL; 5110 5111 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 5112 pSiS->SiS_SD2_Flags |= SiS_SD2_VIDEOBRIDGE; 5113 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 5114 pSiS->SiS_SD2_Flags |= ( SiS_SD2_SISBRIDGE | 5115 SiS_SD2_SUPPORTGAMMA2 ); 5116 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) { 5117 pSiS->SiS_SD2_Flags |= ( SiS_SD2_LCDLVDS | 5118 SiS_SD2_SUPPORTLCD ); 5119 } else if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 5120 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 5121 pSiS->SiS_SD2_Flags |= ( SiS_SD2_LCDTMDS | 5122 SiS_SD2_SUPPORTLCD ); 5123 } else if(pSiS->VBFlags & CRT2_LCD) { 5124 pSiS->SiS_SD2_Flags |= ( SiS_SD2_THIRDPARTYLVDS | 5125 SiS_SD2_SUPPORTLCD ); 5126 } 5127 } 5128 } else if(pSiS->VBFlags2 & VB2_LVDS) { 5129 pSiS->SiS_SD2_Flags |= ( SiS_SD2_THIRDPARTYLVDS | 5130 SiS_SD2_SUPPORTLCD ); 5131 } 5132 5133 if(pSiS->VBFlags2 & (VB2_SISTVBRIDGE | VB2_CHRONTEL)) { 5134 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTTV; 5135 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 5136 pSiS->SiS_SD2_Flags |= ( SiS_SD2_SUPPORTTVTYPE | 5137 SiS_SD2_SUPPORTTVSIZE ); 5138 if(!(pSiS->VBFlags2 & VB2_301)) { 5139 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPTVSAT; 5140 } else { 5141 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPTVEDGE; 5142 } 5143 } 5144 } 5145 } 5146 5147#ifdef ENABLE_YPBPR 5148 if((pSiS->VGAEngine == SIS_315_VGA) && 5149 (pSiS->VBFlags2 & VB2_SISYPBPRBRIDGE)) { 5150 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTYPBPR; 5151 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORT625I; 5152 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORT625P; 5153 if(pSiS->VBFlags2 & VB2_SISYPBPRARBRIDGE) { 5154 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTYPBPRAR; 5155 } 5156 } 5157 if(pSiS->VBFlags2 & VB2_SISHIVISIONBRIDGE) { 5158 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTHIVISION; 5159 } 5160#endif 5161 5162 if((pSiS->VGAEngine != SIS_300_VGA) || (!(pSiS->VBFlags2 & VB2_TRUMPION))) { 5163 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTSCALE; 5164 if((pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && 5165 (!(pSiS->VBFlags2 & VB2_30xBDH))) { 5166 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTCENTER; 5167 } 5168 } 5169 5170#ifdef SISDUALHEAD 5171 if(!pSiS->DualHeadMode) { 5172 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTREDETECT; 5173 } 5174#endif 5175 5176#ifndef SISCHECKOSSSE 5177 pSiS->SiS_SD2_Flags |= SiS_SD2_NEEDUSESSE; 5178#endif 5179 5180#ifdef TWDEBUG /* FOR TESTING */ 5181 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTYPBPRAR; 5182 xf86DrvMsg(0, X_INFO, "TEST: Support Aspect Ratio\n"); 5183#endif 5184 5185 /* Detect CRT2-TV and PAL/NTSC mode */ 5186 SISTVPreInit(pScrn, FALSE); 5187 5188 /* Detect CRT2-VGA */ 5189 SISCRT2PreInit(pScrn, FALSE); 5190 5191 /* Backup detected CRT2 devices */ 5192 SISSaveDetectedDevices(pScrn); 5193 5194 if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR)) { 5195 if((pSiS->ForceTVType != -1) && (pSiS->ForceTVType & TV_YPBPR)) { 5196 pSiS->ForceTVType = -1; 5197 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "YPbPr TV output not supported\n"); 5198 } 5199 } 5200 5201 if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTHIVISION)) { 5202 if((pSiS->ForceTVType != -1) && (pSiS->ForceTVType & TV_HIVISION)) { 5203 pSiS->ForceTVType = -1; 5204 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "HiVision TV output not supported\n"); 5205 } 5206 } 5207 5208 if((pSiS->VBFlags2 & VB2_SISTVBRIDGE) || 5209 ((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->ChrontelType == CHRONTEL_701x))) { 5210 pSiS->SiS_SD_Flags |= (SiS_SD_SUPPORTPALMN | SiS_SD_SUPPORTNTSCJ); 5211 } 5212 if((pSiS->VBFlags2 & VB2_SISTVBRIDGE) || 5213 ((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->ChrontelType == CHRONTEL_700x))) { 5214 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTTVPOS; 5215 } 5216 if(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE) { 5217 pSiS->SiS_SD_Flags |= (SiS_SD_SUPPORTSCART | SiS_SD_SUPPORTVGA2); 5218 } 5219 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 5220 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTOVERSCAN; 5221 pSiS->SiS_SD2_Flags |= SiS_SD2_CHRONTEL; 5222 if(pSiS->ChrontelType == CHRONTEL_700x) { 5223 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTSOVER; 5224 } 5225 } 5226 5227 /* Determine if chipset LCDA-capable */ 5228 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTLCDA; 5229 if(SISDetermineLCDACap(pScrn)) { 5230 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTLCDA; 5231 } 5232 5233 /* Default to LCDA if LCD detected and 5234 * - TV detected (hence default to LCDA+TV), or 5235 * - in single head mode, on LCD panels with xres > 1600 5236 * (Don't do this in MergedFB or DHM; LCDA and CRT1/VGA 5237 * are mutually exclusive; if no TV is detected, the 5238 * code below will default to VGA+LCD, so LCD is driven 5239 * via CRT2.) 5240 * (TODO: This might need some modification for the 5241 * 307 bridges, if these are capable of driving 5242 * LCDs > 1600 via channel B) 5243 */ 5244 if((pSiS->SiS_SD_Flags & SiS_SD_SUPPORTLCDA) && 5245 (pSiS->VBFlags & CRT2_LCD) && 5246 (pSiS->SiS_Pr->SiS_CustomT != CUT_UNKNOWNLCD)) { 5247 if((!pSiS->CRT1TypeForced) && (pSiS->ForceCRT2Type == CRT2_DEFAULT)) { 5248 if(pSiS->VBFlags & CRT2_TV) { 5249 /* If both LCD and TV present, default to LCDA+TV */ 5250 pSiS->ForceCRT1Type = CRT1_LCDA; 5251 pSiS->ForceCRT2Type = CRT2_TV; 5252 } else if(pSiS->LCDwidth > 1600) { 5253 /* If LCD is > 1600, default to LCDA if we don't need CRT1/VGA for other head */ 5254 Bool NeedCRT1VGA = FALSE; 5255#ifdef SISDUALHEAD 5256 if(pSiS->DualHeadMode) NeedCRT1VGA = TRUE; 5257#endif 5258#ifdef SISMERGED 5259 if(pSiS->MergedFB && 5260 (!pSiS->MergedFBAuto || pSiS->CRT1Detected)) NeedCRT1VGA = TRUE; 5261#endif 5262 if(!NeedCRT1VGA) { 5263 pSiS->ForceCRT1Type = CRT1_LCDA; 5264 } 5265 } 5266 } 5267 } 5268 5269 /* Set up pseudo-panel if LCDA forced on TMDS bridges */ 5270 if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTLCDA) { 5271 if(pSiS->ForceCRT1Type == CRT1_LCDA) { 5272 if(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE) { 5273 if(!(pSiS->VBLCDFlags)) { 5274 SiSSetupPseudoPanel(pScrn); 5275 pSiS->detectedCRT2Devices |= CRT2_LCD; 5276 } 5277 } else if(!(pSiS->VBLCDFlags)) { 5278 pSiS->ForceCRT1Type = CRT1_VGA; 5279 } 5280 } 5281 } else { 5282 pSiS->ForceCRT1Type = CRT1_VGA; 5283 } 5284 5285 pSiS->VBFlags |= pSiS->ForceCRT1Type; 5286 5287#ifdef TWDEBUG 5288 xf86DrvMsg(0, X_INFO, "SDFlags %lx\n", pSiS->SiS_SD_Flags); 5289#endif 5290 5291 /* Eventually overrule detected CRT2 type 5292 * If no type forced, use the detected devices in the order TV->LCD->VGA2 5293 * Since the Chrontel 7005 sometimes delivers wrong detection results, 5294 * we use a different order on such machines (LCD->TV) 5295 */ 5296 if(pSiS->ForceCRT2Type == CRT2_DEFAULT) { 5297 if((pSiS->VBFlags & CRT2_TV) && (!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VGAEngine == SIS_300_VGA)))) 5298 pSiS->ForceCRT2Type = CRT2_TV; 5299 else if((pSiS->VBFlags & CRT2_LCD) && (pSiS->ForceCRT1Type == CRT1_VGA)) 5300 pSiS->ForceCRT2Type = CRT2_LCD; 5301 else if(pSiS->VBFlags & CRT2_TV) 5302 pSiS->ForceCRT2Type = CRT2_TV; 5303 else if((pSiS->VBFlags & CRT2_VGA) && (pSiS->ForceCRT1Type == CRT1_VGA)) 5304 pSiS->ForceCRT2Type = CRT2_VGA; 5305 } 5306 5307 switch(pSiS->ForceCRT2Type) { 5308 case CRT2_TV: 5309 pSiS->VBFlags &= ~(CRT2_LCD | CRT2_VGA); 5310 if(pSiS->VBFlags2 & (VB2_SISTVBRIDGE | VB2_CHRONTEL)) { 5311 pSiS->VBFlags |= CRT2_TV; 5312 } else { 5313 pSiS->VBFlags &= ~(CRT2_TV); 5314 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 5315 "Hardware does not support TV output\n"); 5316 } 5317 break; 5318 case CRT2_LCD: 5319 pSiS->VBFlags &= ~(CRT2_TV | CRT2_VGA); 5320 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (pSiS->VBLCDFlags)) { 5321 pSiS->VBFlags |= CRT2_LCD; 5322 } else if((pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && (!(pSiS->VBFlags2 & VB2_30xBDH))) { 5323 SiSSetupPseudoPanel(pScrn); 5324 pSiS->detectedCRT2Devices |= CRT2_LCD; 5325 } else { 5326 pSiS->VBFlags &= ~(CRT2_LCD); 5327 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 5328 "Can't force CRT2 to LCD, no LCD detected\n"); 5329 } 5330 break; 5331 case CRT2_VGA: 5332 pSiS->VBFlags &= ~(CRT2_TV | CRT2_LCD); 5333 if(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE) { 5334 pSiS->VBFlags |= CRT2_VGA; 5335 } else { 5336 pSiS->VBFlags &= ~(CRT2_VGA); 5337 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 5338 "Hardware does not support secondary VGA\n"); 5339 } 5340 break; 5341 default: 5342 pSiS->VBFlags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA); 5343 } 5344 5345 /* Setup gamma (the cmap layer needs this to be initialised) */ 5346 /* (Do this after evaluating options) */ 5347 { 5348 Gamma zeros = {0.0, 0.0, 0.0}; 5349 xf86SetGamma(pScrn, zeros); 5350 } 5351 5352#ifdef SISDUALHEAD 5353 if((!pSiS->DualHeadMode) || (pSiS->SecondHead)) { 5354#endif 5355 xf86DrvMsg(pScrn->scrnIndex, pSiS->CRT1gammaGiven ? X_CONFIG : X_INFO, 5356 "%samma correction is %s\n", 5357 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) ? "CRT1 g" : "G", 5358 pSiS->CRT1gamma ? "enabled" : "disabled"); 5359 5360 if((pSiS->VGAEngine == SIS_315_VGA) && 5361 (!(pSiS->NoXvideo)) && 5362 (!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY))) { 5363 xf86DrvMsg(pScrn->scrnIndex, pSiS->XvGammaGiven ? X_CONFIG : X_INFO, 5364 "Separate Xv gamma correction %sis %s\n", 5365 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) ? "for CRT1 " : "", 5366 pSiS->XvGamma ? "enabled" : "disabled"); 5367 if(pSiS->XvGamma) { 5368 xf86DrvMsg(pScrn->scrnIndex, pSiS->XvGammaGiven ? X_CONFIG : X_INFO, 5369 "Xv gamma correction: %.3f %.3f %.3f\n", 5370 (float)((float)pSiS->XvGammaRed / 1000), 5371 (float)((float)pSiS->XvGammaGreen / 1000), 5372 (float)((float)pSiS->XvGammaBlue / 1000)); 5373 if(!pSiS->CRT1gamma) { 5374 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5375 "Xv gamma correction requires %samma correction enabled\n", 5376 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) ? "CRT1 g" : "G"); 5377 } 5378 } 5379 } 5380#ifdef SISDUALHEAD 5381 } 5382#endif 5383 5384#ifdef SISDUALHEAD 5385 if(pSiS->DualHeadMode) pSiS->CRT2SepGamma = FALSE; 5386#endif 5387 5388#ifdef SISDUALHEAD 5389 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) 5390#endif 5391 { 5392 Bool isDH = FALSE; 5393 if(pSiS->CRT2gamma) { 5394 if( ((pSiS->VGAEngine != SIS_300_VGA) && (pSiS->VGAEngine != SIS_315_VGA)) || 5395 (!(pSiS->VBFlags2 & VB2_SISBRIDGE)) ) { 5396 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 5397 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5398 "CRT2 gamma correction not supported by hardware\n"); 5399 } 5400 pSiS->CRT2gamma = pSiS->CRT2SepGamma = FALSE; 5401 } else if((pSiS->VBFlags2 & VB2_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) { 5402 isDH = TRUE; 5403 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5404 "CRT2 gamma correction not supported for LCD\n"); 5405 /* But leave it on, will be caught in LoadPalette */ 5406 } 5407 } 5408 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 5409 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CRT2 gamma correction is %s%s%s\n", 5410 pSiS->CRT2gamma ? "enabled" : "disabled", 5411 isDH ? " (for TV and VGA2) " : "", 5412 pSiS->CRT2SepGamma ? " (separate from CRT1)" : ""); 5413 } 5414 } 5415 5416 /* Eventually overrule TV Type (SVIDEO, COMPOSITE, SCART, HIVISION, YPBPR) */ 5417 if(pSiS->VBFlags2 & VB2_SISTVBRIDGE) { 5418 if(pSiS->ForceTVType != -1) { 5419 pSiS->VBFlags &= ~(TV_INTERFACE); 5420 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) { 5421 pSiS->VBFlags &= ~(TV_CHSCART | TV_CHYPBPR525I); 5422 } 5423 pSiS->VBFlags |= pSiS->ForceTVType; 5424 if(pSiS->VBFlags & TV_YPBPR) { 5425 pSiS->VBFlags &= ~(TV_STANDARD); 5426 pSiS->VBFlags &= ~(TV_YPBPRAR); 5427 pSiS->VBFlags |= pSiS->ForceYPbPrType; 5428 pSiS->VBFlags |= pSiS->ForceYPbPrAR; 5429 } 5430 } 5431 } 5432 5433 /* Handle ForceCRT1 option (part 2) */ 5434 pSiS->CRT1changed = FALSE; 5435 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5436 usScratchCR17 = pSiS->oldCR17; 5437 usScratchCR63 = pSiS->oldCR63; 5438 usScratchSR1F = pSiS->oldSR1F; 5439 usScratchCR32 = pSiS->postVBCR32; 5440 if(pSiS->VESA != 1) { 5441 /* Copy forceCRT1 option to CRT1off if option is given */ 5442#ifdef SISDUALHEAD 5443 /* In DHM, handle this option only for master head, not the slave */ 5444 if( (pSiS->forceCRT1 != -1) && 5445 (!(pSiS->DualHeadMode && pSiS->SecondHead)) ) { 5446#else 5447 if(pSiS->forceCRT1 != -1) { 5448#endif 5449 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5450 "CRT1 detection overruled by ForceCRT1 option\n"); 5451 if(pSiS->forceCRT1) { 5452 pSiS->CRT1off = 0; 5453 if(pSiS->VGAEngine == SIS_300_VGA) { 5454 if(!(usScratchCR17 & 0x80)) pSiS->CRT1changed = TRUE; 5455 } else { 5456 if(usScratchCR63 & 0x40) pSiS->CRT1changed = TRUE; 5457 } 5458 usScratchCR17 |= 0x80; 5459 usScratchCR32 |= 0x20; 5460 usScratchCR63 &= ~0x40; 5461 usScratchSR1F &= ~0xc0; 5462 } else { 5463 if( ! ( (pScrn->bitsPerPixel == 8) && 5464 ( (pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) || 5465 ((pSiS->VBFlags2 & VB2_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) ) ) ) { 5466 pSiS->CRT1off = 1; 5467 if(pSiS->VGAEngine == SIS_300_VGA) { 5468 if(usScratchCR17 & 0x80) pSiS->CRT1changed = TRUE; 5469 } else { 5470 if(!(usScratchCR63 & 0x40)) pSiS->CRT1changed = TRUE; 5471 } 5472 usScratchCR32 &= ~0x20; 5473 /* We must not actually switch off CRT1 before we changed the mode! */ 5474 } 5475 } 5476 /* Here we can write to CR17 even on 315 series as we only ENABLE 5477 * the bit here 5478 */ 5479 outSISIDXREG(SISCR, 0x17, usScratchCR17); 5480 if(pSiS->VGAEngine == SIS_315_VGA) { 5481 outSISIDXREG(SISCR, pSiS->myCR63, usScratchCR63); 5482 } 5483 outSISIDXREG(SISCR, 0x32, usScratchCR32); 5484 if(pSiS->CRT1changed) { 5485 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 5486 usleep(10000); 5487 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 5488 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5489 "CRT1 status changed by ForceCRT1 option\n"); 5490 } 5491 outSISIDXREG(SISSR, 0x1f, usScratchSR1F); 5492 } 5493 } 5494 /* Store the new VB connection register contents for later mode changes */ 5495 pSiS->newCR32 = usScratchCR32; 5496 } 5497 5498 /* Check if CRT1 used (or needed; this eg. if no CRT2 detected) */ 5499 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 5500 5501 /* No CRT2 output? Then we NEED CRT1! 5502 * We also need CRT1 if depth = 8 and bridge=LVDS|301B-DH 5503 */ 5504 if( (!(pSiS->VBFlags & (CRT2_VGA | CRT2_LCD | CRT2_TV))) || 5505 ( (pScrn->bitsPerPixel == 8) && 5506 ( (pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) || 5507 ((pSiS->VBFlags2 & VB2_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) ) ) ) { 5508 pSiS->CRT1off = 0; 5509 } 5510 /* No CRT2 output? Then we can't use Xv on CRT2 */ 5511 if(!(pSiS->VBFlags & (CRT2_VGA | CRT2_LCD | CRT2_TV))) { 5512 pSiS->XvOnCRT2 = FALSE; 5513 } 5514 5515 } else { /* no video bridge? */ 5516 /* Then we NEED CRT1... */ 5517 pSiS->CRT1off = 0; 5518 /* ... and can't use CRT2 for Xv output */ 5519 pSiS->XvOnCRT2 = FALSE; 5520 } 5521 5522 /* LCDA? Then we don't switch off CRT1 */ 5523 if(pSiS->VBFlags & CRT1_LCDA) pSiS->CRT1off = 0; 5524 5525 /* Handle TVStandard option */ 5526 if((pSiS->NonDefaultPAL != -1) || (pSiS->NonDefaultNTSC != -1)) { 5527 if( (!(pSiS->VBFlags2 & VB2_SISTVBRIDGE)) && 5528 (!((pSiS->VBFlags2 & VB2_CHRONTEL)) && (pSiS->ChrontelType == CHRONTEL_701x)) ) { 5529 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5530 "PALM, PALN and NTSCJ not supported on this hardware\n"); 5531 pSiS->NonDefaultPAL = pSiS->NonDefaultNTSC = -1; 5532 pSiS->VBFlags &= ~(TV_PALN | TV_PALM | TV_NTSCJ); 5533 pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTPALMN | SiS_SD_SUPPORTNTSCJ); 5534 } 5535 } 5536 if(pSiS->OptTVStand != -1) { 5537 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5538 if( (!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & (TV_CHSCART | TV_CHYPBPR525I)))) && 5539 (!(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR))) ) { 5540 pSiS->VBFlags &= ~(TV_PAL | TV_NTSC | TV_PALN | TV_PALM | TV_NTSCJ); 5541 if(pSiS->OptTVStand) { 5542 pSiS->VBFlags |= TV_PAL; 5543 if(pSiS->NonDefaultPAL == 1) pSiS->VBFlags |= TV_PALM; 5544 else if(!pSiS->NonDefaultPAL) pSiS->VBFlags |= TV_PALN; 5545 } else { 5546 pSiS->VBFlags |= TV_NTSC; 5547 if(pSiS->NonDefaultNTSC == 1) pSiS->VBFlags |= TV_NTSCJ; 5548 } 5549 } else { 5550 pSiS->OptTVStand = pSiS->NonDefaultPAL = -1; 5551 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5552 "Option TVStandard ignored for YPbPr, HiVision and Chrontel-SCART\n"); 5553 } 5554 } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { 5555 pSiS->SiS6326Flags &= ~SIS6326_TVPAL; 5556 if(pSiS->OptTVStand) pSiS->SiS6326Flags |= SIS6326_TVPAL; 5557 } 5558 } 5559 5560 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5561 /* Default to PAL */ 5562 if(pSiS->VBFlags & (TV_SVIDEO | TV_AVIDEO)) { 5563 if(!(pSiS->VBFlags & (TV_PAL | TV_NTSC))) { 5564 pSiS->VBFlags &= ~(TV_PAL | TV_NTSC | TV_PALN | TV_PALM | TV_NTSCJ); 5565 pSiS->VBFlags |= TV_PAL; 5566 } 5567 } 5568 /* SCART only supported for PAL */ 5569 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && (pSiS->VBFlags & TV_SCART)) { 5570 pSiS->VBFlags &= ~(TV_NTSC | TV_PALN | TV_PALM | TV_NTSCJ); 5571 pSiS->VBFlags |= TV_PAL; 5572 pSiS->OptTVStand = 1; 5573 pSiS->NonDefaultPAL = pSiS->NonDefaultNTSC = -1; 5574 } 5575 } 5576 5577#ifdef SIS_CP 5578 SIS_CP_DRIVER_RECONFIGOPT 5579#endif 5580 5581 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 5582 if(pSiS->sis6326tvplug != -1) { 5583 pSiS->SiS6326Flags &= ~(SIS6326_TVSVIDEO | SIS6326_TVCVBS); 5584 pSiS->SiS6326Flags |= SIS6326_TVDETECTED; 5585 if(pSiS->sis6326tvplug == 1) pSiS->SiS6326Flags |= SIS6326_TVCVBS; 5586 else pSiS->SiS6326Flags |= SIS6326_TVSVIDEO; 5587 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5588 "SiS6326 TV plug type detection overruled by %s\n", 5589 (pSiS->SiS6326Flags & SIS6326_TVCVBS) ? "COMPOSITE" : "SVIDEO"); 5590 } 5591 } 5592 5593 /* Do some checks */ 5594 if(pSiS->OptTVOver != -1) { 5595 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 5596 pSiS->UseCHOverScan = pSiS->OptTVOver; 5597 } else { 5598 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5599 "CHTVOverscan only supported on CHRONTEL 70xx\n"); 5600 pSiS->UseCHOverScan = -1; 5601 } 5602 } else pSiS->UseCHOverScan = -1; 5603 5604 if(pSiS->sistvedgeenhance != -1) { 5605 if(!(pSiS->VBFlags2 & VB2_301)) { 5606 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5607 "SISTVEdgeEnhance only supported on SiS301\n"); 5608 pSiS->sistvedgeenhance = -1; 5609 } 5610 } 5611 if(pSiS->sistvsaturation != -1) { 5612 if(pSiS->VBFlags2 & VB2_301) { 5613 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5614 "SISTVSaturation not supported on SiS301\n"); 5615 pSiS->sistvsaturation = -1; 5616 } 5617 } 5618 5619 /* Do some MergedFB mode initialisation */ 5620#ifdef SISMERGED 5621 if(pSiS->MergedFB) { 5622 pSiS->CRT2pScrn = malloc(sizeof(ScrnInfoRec)); 5623 if(!pSiS->CRT2pScrn) { 5624 SISErrorLog(pScrn, "Failed to allocate memory for 2nd pScrn, %s\n", mergeddisstr); 5625 pSiS->MergedFB = FALSE; 5626 } else { 5627 memcpy(pSiS->CRT2pScrn, pScrn, sizeof(ScrnInfoRec)); 5628 } 5629 } 5630#endif 5631 5632 /* Determine CRT1<>CRT2 mode 5633 * Note: When using VESA or if the bridge is in slavemode, display 5634 * is ALWAYS in MIRROR_MODE! 5635 * This requires extra checks in functions using this flag! 5636 * (see sis_video.c for example) 5637 */ 5638 if(pSiS->VBFlags & DISPTYPE_DISP2) { 5639 if(pSiS->CRT1off) { /* CRT2 only ------------------------------- */ 5640#ifdef SISDUALHEAD 5641 if(pSiS->DualHeadMode) { 5642 SISErrorLog(pScrn, 5643 "CRT1 not detected or forced off. Dual Head mode can't initialize.\n"); 5644 if(pSiSEnt) pSiSEnt->DisableDual = TRUE; 5645 goto my_error_1; 5646 } 5647#endif 5648#ifdef SISMERGED 5649 if(pSiS->MergedFB) { 5650 if(pSiS->MergedFBAuto) { 5651 xf86DrvMsg(pScrn->scrnIndex, X_INFO, mergednocrt1, mergeddisstr); 5652 } else { 5653 SISErrorLog(pScrn, mergednocrt1, mergeddisstr); 5654 } 5655 if(pSiS->CRT2pScrn) free(pSiS->CRT2pScrn); 5656 pSiS->CRT2pScrn = NULL; 5657 pSiS->MergedFB = FALSE; 5658 } 5659#endif 5660 pSiS->VBFlags |= VB_DISPMODE_SINGLE; 5661 /* No CRT1? Then we use the video overlay on CRT2 */ 5662 pSiS->XvOnCRT2 = TRUE; 5663 } else /* CRT1 and CRT2 - mirror or dual head ----- */ 5664#ifdef SISDUALHEAD 5665 if(pSiS->DualHeadMode) { 5666 pSiS->VBFlags |= (VB_DISPMODE_DUAL | DISPTYPE_CRT1); 5667 if(pSiS->VESA != -1) { 5668 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5669 "VESA option not used in Dual Head mode. VESA disabled.\n"); 5670 } 5671 if(pSiSEnt) pSiSEnt->DisableDual = FALSE; 5672 pSiS->VESA = 0; 5673 } else 5674#endif 5675#ifdef SISMERGED 5676 if(pSiS->MergedFB) { 5677 pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_CRT1); 5678 if(pSiS->VESA != -1) { 5679 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5680 "VESA option not used in MergedFB mode. VESA disabled.\n"); 5681 } 5682 pSiS->VESA = 0; 5683 } else 5684#endif 5685 pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_CRT1); 5686 } else { /* CRT1 only ------------------------------- */ 5687#ifdef SISDUALHEAD 5688 if(pSiS->DualHeadMode) { 5689 SISErrorLog(pScrn, 5690 "No CRT2 output selected or no bridge detected. " 5691 "Dual Head mode can't initialize.\n"); 5692 goto my_error_1; 5693 } 5694#endif 5695#ifdef SISMERGED 5696 if(pSiS->MergedFB) { 5697 if(pSiS->MergedFBAuto) { 5698 xf86DrvMsg(pScrn->scrnIndex, X_INFO, mergednocrt2, mergeddisstr); 5699 } else { 5700 SISErrorLog(pScrn, mergednocrt2, mergeddisstr); 5701 } 5702 if(pSiS->CRT2pScrn) free(pSiS->CRT2pScrn); 5703 pSiS->CRT2pScrn = NULL; 5704 pSiS->MergedFB = FALSE; 5705 } 5706#endif 5707 pSiS->VBFlags |= (VB_DISPMODE_SINGLE | DISPTYPE_CRT1); 5708 } 5709 5710 if((pSiS->VGAEngine == SIS_315_VGA) || (pSiS->VGAEngine == SIS_300_VGA)) { 5711 if((!pSiS->NoXvideo) && 5712 (!pSiS->hasTwoOverlays) && 5713 (!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY))) { 5714 xf86DrvMsg(pScrn->scrnIndex, from, 5715 "Using Xv overlay by default on CRT%d\n", 5716 pSiS->XvOnCRT2 ? 2 : 1); 5717 } 5718 } 5719 5720 /* Init ptrs for Save/Restore functions and calc MaxClock */ 5721 SISDACPreInit(pScrn); 5722 5723 /* ********** end of VBFlags setup ********** */ 5724 5725 /* VBFlags are initialized now. Back them up for SlaveMode modes. */ 5726 pSiS->VBFlags_backup = pSiS->VBFlags; 5727 5728 /* Backup CR32,36,37 (in order to write them back after a VT switch) */ 5729 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 5730 inSISIDXREG(SISCR,0x32,pSiS->myCR32); 5731 inSISIDXREG(SISCR,0x36,pSiS->myCR36); 5732 inSISIDXREG(SISCR,0x37,pSiS->myCR37); 5733 } 5734 5735 /* Find out about paneldelaycompensation and evaluate option */ 5736#ifdef SISDUALHEAD 5737 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) { 5738#endif 5739 if(pSiS->VGAEngine == SIS_300_VGA) { 5740 5741 if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) { 5742 5743 /* Save the current PDC if the panel is used at the moment. 5744 * This seems by far the safest way to find out about it. 5745 * If the system is using an old version of sisfb, we can't 5746 * trust the pdc register value. If sisfb saved the pdc for 5747 * us, use it. 5748 */ 5749 if(pSiS->sisfbpdc != 0xff) { 5750 pSiS->SiS_Pr->PDC = pSiS->sisfbpdc; 5751 } else { 5752 if(!(pSiS->donttrustpdc)) { 5753 UChar tmp; 5754 inSISIDXREG(SISCR, 0x30, tmp); 5755 if(tmp & 0x20) { 5756 inSISIDXREG(SISPART1, 0x13, pSiS->SiS_Pr->PDC); 5757 } else { 5758 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5759 "Unable to detect LCD PanelDelayCompensation, LCD is not active\n"); 5760 } 5761 } else { 5762 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5763 "Unable to detect LCD PanelDelayCompensation, please update sisfb\n"); 5764 } 5765 } 5766 if(pSiS->SiS_Pr->PDC != -1) { 5767 pSiS->SiS_Pr->PDC &= 0x3c; 5768 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5769 "Detected LCD PanelDelayCompensation 0x%02x\n", 5770 pSiS->SiS_Pr->PDC); 5771 } 5772 5773 /* If we haven't been able to find out, use our other methods */ 5774 if(pSiS->SiS_Pr->PDC == -1) { 5775 int i=0; 5776 do { 5777 if(mypdctable[i].subsysVendor == PCI_SUB_VENDOR_ID(pSiS->PciInfo) && 5778 mypdctable[i].subsysCard == PCI_SUB_DEVICE_ID(pSiS->PciInfo)) { 5779 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5780 "PCI card/vendor identified for non-default PanelDelayCompensation\n"); 5781 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5782 "Vendor: %s, card: %s (ID %04x), PanelDelayCompensation: 0x%02x\n", 5783 mypdctable[i].vendorName, mypdctable[i].cardName, 5784 PCI_SUB_DEVICE_ID(pSiS->PciInfo), mypdctable[i].pdc); 5785 if(pSiS->PDC == -1) { 5786 pSiS->PDC = mypdctable[i].pdc; 5787 } else { 5788 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5789 "PanelDelayCompensation overruled by option\n"); 5790 } 5791 break; 5792 } 5793 i++; 5794 } while(mypdctable[i].subsysVendor != 0); 5795 } 5796 5797 if(pSiS->PDC != -1) { 5798 if(pSiS->BIOS) { 5799 if(pSiS->VBFlags2 & VB2_LVDS) { 5800 if(pSiS->BIOS[0x220] & 0x80) { 5801 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5802 "BIOS uses OEM LCD Panel Delay Compensation 0x%02x\n", 5803 pSiS->BIOS[0x220] & 0x3c); 5804 pSiS->BIOS[0x220] &= 0x7f; 5805 } 5806 } 5807 if(pSiS->VBFlags2 & (VB2_301B | VB2_302B)) { 5808 if(pSiS->BIOS[0x220] & 0x80) { 5809 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5810 "BIOS uses OEM LCD Panel Delay Compensation 0x%02x\n", 5811 ( (pSiS->VBLCDFlags & VB_LCD_1280x1024) ? 5812 pSiS->BIOS[0x223] : pSiS->BIOS[0x224] ) & 0x3c); 5813 pSiS->BIOS[0x220] &= 0x7f; 5814 } 5815 } 5816 } 5817 pSiS->SiS_Pr->PDC = (pSiS->PDC & 0x3c); 5818 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5819 "Using LCD Panel Delay Compensation 0x%02x\n", pSiS->SiS_Pr->PDC); 5820 } 5821 } 5822 5823 } /* SIS_300_VGA */ 5824 5825 if(pSiS->VGAEngine == SIS_315_VGA) { 5826 5827 UChar tmp, tmp2; 5828 inSISIDXREG(SISCR, 0x30, tmp); 5829 5830 /* Save the current PDC if the panel is used at the moment. */ 5831 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) { 5832 5833 if(pSiS->sisfbpdc != 0xff) { 5834 pSiS->SiS_Pr->PDC = pSiS->sisfbpdc; 5835 } 5836 if(pSiS->sisfbpdca != 0xff) { 5837 pSiS->SiS_Pr->PDCA = pSiS->sisfbpdca; 5838 } 5839 5840 if(!pSiS->donttrustpdc) { 5841 if((pSiS->sisfbpdc == 0xff) && (pSiS->sisfbpdca == 0xff)) { 5842 CARD16 tempa, tempb; 5843 inSISIDXREG(SISPART1,0x2d,tmp2); 5844 tempa = (tmp2 & 0xf0) >> 3; 5845 tempb = (tmp2 & 0x0f) << 1; 5846 inSISIDXREG(SISPART1,0x20,tmp2); 5847 tempa |= ((tmp2 & 0x40) >> 6); 5848 inSISIDXREG(SISPART1,0x35,tmp2); 5849 tempb |= ((tmp2 & 0x80) >> 7); 5850 inSISIDXREG(SISPART1,0x13,tmp2); 5851 if(!pSiS->ROM661New) { 5852 if((tmp2 & 0x04) || (tmp & 0x20)) { 5853 pSiS->SiS_Pr->PDCA = tempa; 5854 pSiS->SiS_Pr->PDC = tempb; 5855 } else { 5856 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5857 "Unable to detect PanelDelayCompensation, LCD is not active\n"); 5858 } 5859 } else { 5860 if(tmp2 & 0x04) { 5861 pSiS->SiS_Pr->PDCA = tempa; 5862 } else if(tmp & 0x20) { 5863 pSiS->SiS_Pr->PDC = tempb; 5864 } else { 5865 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5866 "Unable to detect PanelDelayCompensation, LCD is not active\n"); 5867 } 5868 } 5869 } 5870 } else { 5871 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5872 "Unable to detect PanelDelayCompensation, please update sisfb\n"); 5873 } 5874 if(pSiS->SiS_Pr->PDC != -1) { 5875 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5876 "Detected LCD PanelDelayCompensation 0x%02x (for LCD=CRT2)\n", 5877 pSiS->SiS_Pr->PDC); 5878 } 5879 if(pSiS->SiS_Pr->PDCA != -1) { 5880 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5881 "Detected LCD PanelDelayCompensation1 0x%02x (for LCD=CRT1)\n", 5882 pSiS->SiS_Pr->PDCA); 5883 } 5884 } 5885 5886 /* Let user override (for all bridges) */ 5887 if(pSiS->VBFlags2 & VB2_30xBLV) { 5888 if(pSiS->PDC != -1) { 5889 pSiS->SiS_Pr->PDC = pSiS->PDC & 0x1f; 5890 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5891 "Using LCD PanelDelayCompensation 0x%02x (for LCD=CRT2)\n", 5892 pSiS->SiS_Pr->PDC); 5893 } 5894 if(pSiS->PDCA != -1) { 5895 pSiS->SiS_Pr->PDCA = pSiS->PDCA & 0x1f; 5896 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 5897 "Using LCD PanelDelayCompensation1 0x%02x (for LCD=CRT1)\n", 5898 pSiS->SiS_Pr->PDCA); 5899 } 5900 } 5901 5902 /* Read the current EMI (if not overruled) */ 5903 if(pSiS->VBFlags2 & VB2_SISEMIBRIDGE) { 5904 MessageType from = X_PROBED; 5905 if(pSiS->EMI != -1) { 5906 pSiS->SiS_Pr->EMI_30 = (pSiS->EMI >> 24) & 0x60; 5907 pSiS->SiS_Pr->EMI_31 = (pSiS->EMI >> 16) & 0xff; 5908 pSiS->SiS_Pr->EMI_32 = (pSiS->EMI >> 8) & 0xff; 5909 pSiS->SiS_Pr->EMI_33 = pSiS->EMI & 0xff; 5910 pSiS->SiS_Pr->HaveEMI = pSiS->SiS_Pr->HaveEMILCD = TRUE; 5911 pSiS->SiS_Pr->OverruleEMI = TRUE; 5912 from = X_CONFIG; 5913 } else if((pSiS->sisfbfound) && (pSiS->sisfb_haveemi)) { 5914 pSiS->SiS_Pr->EMI_30 = pSiS->sisfb_emi30; 5915 pSiS->SiS_Pr->EMI_31 = pSiS->sisfb_emi31; 5916 pSiS->SiS_Pr->EMI_32 = pSiS->sisfb_emi32; 5917 pSiS->SiS_Pr->EMI_33 = pSiS->sisfb_emi33; 5918 pSiS->SiS_Pr->HaveEMI = TRUE; 5919 if(pSiS->sisfb_haveemilcd) pSiS->SiS_Pr->HaveEMILCD = TRUE; 5920 pSiS->SiS_Pr->OverruleEMI = FALSE; 5921 } else { 5922 inSISIDXREG(SISPART4, 0x30, pSiS->SiS_Pr->EMI_30); 5923 inSISIDXREG(SISPART4, 0x31, pSiS->SiS_Pr->EMI_31); 5924 inSISIDXREG(SISPART4, 0x32, pSiS->SiS_Pr->EMI_32); 5925 inSISIDXREG(SISPART4, 0x33, pSiS->SiS_Pr->EMI_33); 5926 pSiS->SiS_Pr->HaveEMI = TRUE; 5927 if(tmp & 0x20) pSiS->SiS_Pr->HaveEMILCD = TRUE; 5928 pSiS->SiS_Pr->OverruleEMI = FALSE; 5929 } 5930 xf86DrvMsg(pScrn->scrnIndex, from, 5931 "302LV/302ELV: Using EMI 0x%02x%02x%02x%02x%s\n", 5932 pSiS->SiS_Pr->EMI_30,pSiS->SiS_Pr->EMI_31, 5933 pSiS->SiS_Pr->EMI_32,pSiS->SiS_Pr->EMI_33, 5934 pSiS->SiS_Pr->HaveEMILCD ? " (LCD)" : ""); 5935 } 5936 5937 } /* SIS_315_VGA */ 5938#ifdef SISDUALHEAD 5939 } 5940#endif 5941 5942 5943 /* In dual head mode, both heads (currently) share the maxxfbmem equally. 5944 * If memory sharing is done differently, the following has to be changed; 5945 * the other modules (eg. accel and Xv) use dhmOffset for hardware 5946 * pointer settings relative to VideoRAM start and won't need to be changed. 5947 * 5948 * Addendum: dhmoffset is also used for skipping the UMA area on SiS76x. 5949 */ 5950 5951 pSiS->dhmOffset = pSiS->FbBaseOffset; 5952 pSiS->FbAddress += pSiS->dhmOffset; 5953 5954#ifdef SISDUALHEAD 5955 if(pSiS->DualHeadMode) { 5956 pSiS->FbAddress = pSiS->realFbAddress; 5957 if(!pSiS->SecondHead) { 5958 /* ===== First head (always CRT2) ===== */ 5959 /* We use only half of the memory available */ 5960 pSiS->maxxfbmem /= 2; 5961 /* dhmOffset is 0 (or LFB-base for SiS76x UMA skipping) */ 5962 pSiS->FbAddress += pSiS->dhmOffset; 5963 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5964 "%dKB video RAM at 0x%lx available for master head (CRT2)\n", 5965 pSiS->maxxfbmem/1024, pSiS->FbAddress); 5966 } else { 5967 /* ===== Second head (always CRT1) ===== */ 5968 /* We use only half of the memory available */ 5969 pSiS->maxxfbmem /= 2; 5970 /* Initialize dhmOffset */ 5971 pSiS->dhmOffset += pSiS->maxxfbmem; 5972 /* Adapt FBAddress */ 5973 pSiS->FbAddress += pSiS->dhmOffset; 5974 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 5975 "%dKB video RAM at 0x%lx available for slave head (CRT1)\n", 5976 pSiS->maxxfbmem/1024, pSiS->FbAddress); 5977 } 5978 } 5979#endif 5980 5981 /* Note: Do not use availMem for anything from now. Use 5982 * maxxfbmem instead. (availMem does not take dual head 5983 * mode into account.) 5984 */ 5985 5986 if(pSiS->FbBaseOffset) { 5987 /* Doubt that the DRM memory manager can deal 5988 * with a heap start of 0... 5989 */ 5990 pSiS->DRIheapstart = 16; 5991 pSiS->DRIheapend = pSiS->FbBaseOffset; 5992 } else { 5993 pSiS->DRIheapstart = pSiS->maxxfbmem; 5994 pSiS->DRIheapend = pSiS->availMem; 5995 } 5996#ifdef SISDUALHEAD 5997 if(pSiS->DualHeadMode) { 5998 pSiS->DRIheapstart = pSiS->DRIheapend = 0; 5999 } else 6000#endif 6001 if(pSiS->DRIheapstart >= pSiS->DRIheapend) { 6002#if 0 /* For future use */ 6003 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6004 "No memory for DRI heap. Please set the option \"MaxXFBMem\" to\n" 6005 "\tlimit the memory X should use and leave the rest to DRI\n"); 6006#endif 6007 pSiS->DRIheapstart = pSiS->DRIheapend = 0; 6008 } 6009 6010 /* Now for something completely different: DDC. 6011 * For 300 and 315/330/340 series, we provide our 6012 * own functions (in order to probe CRT2 as well) 6013 * If these fail, use the VBE. 6014 * All other chipsets will use VBE. No need to re-invent 6015 * the wheel there. 6016 */ 6017 6018 pSiS->pVbe = NULL; 6019 didddc2 = FALSE; 6020 6021 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 6022 if(xf86LoadSubModule(pScrn, "ddc")) { 6023 int crtnum = 0; 6024 if((pMonitor = SiSDoPrivateDDC(pScrn, &crtnum))) { 6025 didddc2 = TRUE; 6026 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcsstr, crtnum); 6027 xf86PrintEDID(pMonitor); 6028 xf86SetDDCproperties(pScrn, pMonitor); 6029 pScrn->monitor->DDC = pMonitor; 6030 /* Now try to find out aspect ratio */ 6031 SiSFindAspect(pScrn, pMonitor, crtnum); 6032 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcestr, crtnum); 6033 } 6034 } 6035 } 6036 6037#ifdef SISDUALHEAD 6038 /* In dual head mode, probe DDC using VBE only for CRT1 (second head) */ 6039 if((pSiS->DualHeadMode) && (!didddc2) && (!pSiS->SecondHead)) { 6040 didddc2 = TRUE; 6041 } 6042#endif 6043 6044 if(!didddc2) { 6045 /* If CRT1 is off or LCDA, skip DDC via VBE */ 6046 if((pSiS->CRT1off) || (pSiS->VBFlags & CRT1_LCDA)) { 6047 didddc2 = TRUE; 6048 } 6049 } 6050 6051 /* Now (re-)load and initialize the DDC module */ 6052 if(!didddc2) { 6053 6054 if(xf86LoadSubModule(pScrn, "ddc")) { 6055 6056 /* Now load and initialize VBE module. */ 6057 SiS_LoadInitVBE(pScrn); 6058 6059 if(pSiS->pVbe) { 6060 if((pMonitor = vbeDoEDID(pSiS->pVbe,NULL))) { 6061 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 6062 "VBE CRT1 DDC monitor info:\n"); 6063 xf86SetDDCproperties(pScrn, xf86PrintEDID(pMonitor)); 6064 pScrn->monitor->DDC = pMonitor; 6065 /* Now try to find out aspect ratio */ 6066 SiSFindAspect(pScrn, pMonitor, 1); 6067 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 6068 "End of VBE CRT1 DDC monitor info\n"); 6069 } 6070 } else { 6071 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6072 "Failed to read DDC data\n"); 6073 } 6074 } 6075 } 6076 6077#ifdef SISMERGED 6078 if(pSiS->MergedFB) { 6079 pSiS->CRT2pScrn->monitor = malloc(sizeof(MonRec)); 6080 if(pSiS->CRT2pScrn->monitor) { 6081 DisplayModePtr tempm = NULL, currentm = NULL, newm = NULL; 6082 memcpy(pSiS->CRT2pScrn->monitor, pScrn->monitor, sizeof(MonRec)); 6083 pSiS->CRT2pScrn->monitor->DDC = NULL; 6084 pSiS->CRT2pScrn->monitor->Modes = NULL; 6085 pSiS->CRT2pScrn->monitor->id = (char *)crt2monname; 6086 tempm = pScrn->monitor->Modes; 6087 while(tempm) { 6088 if(!(newm = malloc(sizeof(DisplayModeRec)))) break; 6089 memcpy(newm, tempm, sizeof(DisplayModeRec)); 6090 if(!(newm->name = malloc(strlen(tempm->name) + 1))) { 6091 free(newm); 6092 break; 6093 } 6094 strcpy(newm->name, tempm->name); 6095 if(!pSiS->CRT2pScrn->monitor->Modes) pSiS->CRT2pScrn->monitor->Modes = newm; 6096 if(currentm) { 6097 currentm->next = newm; 6098 newm->prev = currentm; 6099 } 6100 currentm = newm; 6101 tempm = tempm->next; 6102 } 6103 if(pSiS->CRT2HSync) { 6104 pSiS->CRT2pScrn->monitor->nHsync = 6105 SiSStrToRanges(pSiS->CRT2pScrn->monitor->hsync, pSiS->CRT2HSync, MAX_HSYNC); 6106 } 6107 if(pSiS->CRT2VRefresh) { 6108 pSiS->CRT2pScrn->monitor->nVrefresh = 6109 SiSStrToRanges(pSiS->CRT2pScrn->monitor->vrefresh, pSiS->CRT2VRefresh, MAX_VREFRESH); 6110 } 6111 if((pMonitor = SiSInternalDDC(pSiS->CRT2pScrn, 1))) { 6112 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcsstr, 2); 6113 xf86PrintEDID(pMonitor); 6114 xf86SetDDCproperties(pSiS->CRT2pScrn, pMonitor); 6115 pSiS->CRT2pScrn->monitor->DDC = pMonitor; 6116 /* Now try to find out aspect ratio */ 6117 SiSFindAspect(pScrn, pMonitor, 2); 6118 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcestr, 2); 6119 /* use DDC data if no ranges in config file */ 6120 if(!pSiS->CRT2HSync) { 6121 pSiS->CRT2pScrn->monitor->nHsync = 0; 6122 } 6123 if(!pSiS->CRT2VRefresh) { 6124 pSiS->CRT2pScrn->monitor->nVrefresh = 0; 6125 } 6126 } else { 6127 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 6128 "Failed to read DDC data for CRT2\n"); 6129 } 6130 } else { 6131 SISErrorLog(pScrn, "Failed to allocate memory for CRT2 monitor, %s.\n", 6132 mergeddisstr); 6133 if(pSiS->CRT2pScrn) free(pSiS->CRT2pScrn); 6134 pSiS->CRT2pScrn = NULL; 6135 pSiS->MergedFB = FALSE; 6136 } 6137 } 6138#endif 6139 6140 /* Copy our detected monitor gammas, part 1. Note that device redetection 6141 * is not supported in DHM, so there is no need to do that anytime later. 6142 */ 6143#ifdef SISDUALHEAD 6144 if(pSiS->DualHeadMode) { 6145 if(!pSiS->SecondHead) { 6146 /* CRT2: Got gamma for LCD or VGA2 */ 6147 pSiSEnt->CRT2VGAMonitorGamma = pSiS->CRT2VGAMonitorGamma; 6148 } else { 6149 /* CRT1: Got gamma for LCD or VGA */ 6150 pSiSEnt->CRT1VGAMonitorGamma = pSiS->CRT1VGAMonitorGamma; 6151 } 6152 if(pSiS->CRT2LCDMonitorGamma) pSiSEnt->CRT2LCDMonitorGamma = pSiS->CRT2LCDMonitorGamma; 6153 } 6154#endif 6155 6156 /* end of DDC */ 6157 6158 /* From here, we mainly deal with clocks and modes */ 6159 6160#ifdef SISMERGED 6161 if(pSiS->MergedFB) xf86DrvMsg(pScrn->scrnIndex, X_INFO, crtsetupstr, 1); 6162#endif 6163 6164 /* Set the min pixel clock */ 6165 pSiS->MinClock = 5000; 6166 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 6167 pSiS->MinClock = 10000; 6168 } 6169 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n", 6170 pSiS->MinClock / 1000); 6171 6172 /* If the user has specified ramdac speed in the config 6173 * file, we respect that setting. 6174 */ 6175 from = X_PROBED; 6176 if(pSiS->pEnt->device->dacSpeeds[0]) { 6177 int speed = 0; 6178 switch(pScrn->bitsPerPixel) { 6179 case 8: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP8]; 6180 break; 6181 case 16: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP16]; 6182 break; 6183 case 24: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP24]; 6184 break; 6185 case 32: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP32]; 6186 break; 6187 } 6188 if(speed == 0) pSiS->MaxClock = pSiS->pEnt->device->dacSpeeds[0]; 6189 else pSiS->MaxClock = speed; 6190 from = X_CONFIG; 6191 } 6192 xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n", 6193 pSiS->MaxClock / 1000); 6194 6195 /* 6196 * Setup the ClockRanges, which describe what clock ranges are available, 6197 * and what sort of modes they can be used for. 6198 */ 6199 clockRanges = xnfcalloc(sizeof(ClockRange), 1); 6200 clockRanges->next = NULL; 6201 clockRanges->minClock = pSiS->MinClock; 6202 clockRanges->maxClock = pSiS->MaxClock; 6203 clockRanges->clockIndex = -1; /* programmable */ 6204 clockRanges->interlaceAllowed = TRUE; 6205 clockRanges->doubleScanAllowed = TRUE; 6206 6207 /* 6208 * Since we have lots of built-in modes for 300/315/330/340 series 6209 * with vb support, we replace the given default mode list with our 6210 * own. In case the video bridge is to be used, we only allow other 6211 * modes if 6212 * -) vbtype is 301, 301B, 301C or 302B, and 6213 * -) crt2 device is not TV, and 6214 * -) crt1 is not LCDA, unless bridge is TMDS/LCDA capable (301C) 6215 */ 6216 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 6217 if(!(pSiS->noInternalModes)) { 6218 Bool acceptcustommodes = TRUE; /* Accept user modelines */ 6219 Bool includelcdmodes = TRUE; /* Include modes reported by DDC */ 6220 Bool isfordvi = FALSE; /* Is for digital DVI output */ 6221 Bool IsForCRT2 = FALSE; 6222 if(pSiS->UseVESA) { 6223 acceptcustommodes = FALSE; 6224 includelcdmodes = FALSE; 6225 } 6226#ifdef SISDUALHEAD /* Dual head is static. Output devices will not change. */ 6227 if(pSiS->DualHeadMode) { 6228 if(!pSiS->SecondHead) { /* CRT2: */ 6229 if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 6230 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 6231 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA))) includelcdmodes = FALSE; 6232 if(pSiS->VBFlags & CRT2_LCD) isfordvi = TRUE; 6233 if(pSiS->VBFlags & CRT2_TV) acceptcustommodes = FALSE; 6234 } else { 6235 if(pSiS->VBFlags & (CRT2_TV|CRT2_LCD)) { 6236 acceptcustommodes = FALSE; 6237 includelcdmodes = FALSE; 6238 } 6239 } 6240 } else { 6241 acceptcustommodes = FALSE; 6242 includelcdmodes = FALSE; 6243 } 6244 clockRanges->interlaceAllowed = FALSE; 6245 IsForCRT2 = TRUE; 6246 } else { /* CRT1: */ 6247 if(pSiS->VBFlags & CRT1_LCDA) { 6248 if(!(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 6249 acceptcustommodes = FALSE; 6250 includelcdmodes = FALSE; 6251 /* Will handle i-lace in mode-switching code */ 6252 } else { 6253 isfordvi = TRUE; 6254 /* Don't allow i-lace modes */ 6255 clockRanges->interlaceAllowed = FALSE; 6256 } 6257 } else { 6258 includelcdmodes = FALSE; 6259 } 6260 } 6261 } else 6262#endif 6263#ifdef SISMERGED /* MergedFB mode is not static. Output devices may change. */ 6264 if(pSiS->MergedFB) { 6265 if(pSiS->VBFlags & CRT1_LCDA) { 6266 if(!(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 6267 acceptcustommodes = FALSE; 6268 includelcdmodes = FALSE; 6269 /* Will handle i-lace in mode-switching code */ 6270 } else { 6271 isfordvi = TRUE; 6272 /* Don't allow i-lace custom modes */ 6273 clockRanges->interlaceAllowed = FALSE; 6274 } 6275 } else { 6276 includelcdmodes = FALSE; 6277 } 6278 } else 6279#endif /* Mirror mode is not static. Output devices may change. */ 6280 if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 6281 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 6282 if(!(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 6283 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA))) includelcdmodes = FALSE; 6284 if(pSiS->VBFlags & CRT2_LCD) isfordvi = TRUE; 6285 } else { 6286 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA|CRT1_LCDA))) includelcdmodes = FALSE; 6287 if(pSiS->VBFlags & (CRT2_LCD|CRT1_LCDA)) isfordvi = TRUE; 6288 } 6289 if((!(pSiS->VBFlags & DISPTYPE_CRT1)) && (!(pSiS->VBFlags & CRT1_LCDA))) { 6290 IsForCRT2 = TRUE; 6291 } 6292 /* Allow user modes, even if CRT2 is TV. Will be filtered through ValidMode(); 6293 * leaving the user modes here might have the advantage that such a mode, if 6294 * it matches in resolution with a supported TV mode, allows us to drive eg. 6295 * non standard panels, and still permits switching to TV. This mode will be 6296 * "mapped" to a supported mode of identical resolution for TV. All this is 6297 * taken care of by ValidMode() and ModeInit()/PresetMode(). 6298 */ 6299 } else { 6300 if(pSiS->VBFlags & (CRT2_TV|CRT2_LCD)) { 6301 acceptcustommodes = FALSE; 6302 includelcdmodes = FALSE; 6303 if(!(pSiS->VBFlags & DISPTYPE_CRT1)) { 6304 IsForCRT2 = TRUE; 6305 } 6306 } 6307 } 6308 } else if(pSiS->VBFlags & (CRT2_ENABLE | CRT1_LCDA)) { 6309 acceptcustommodes = FALSE; 6310 includelcdmodes = FALSE; 6311 if((pSiS->VBFlags & CRT1_LCDA) || (!(pSiS->VBFlags & DISPTYPE_CRT1))) { 6312 IsForCRT2 = TRUE; 6313 } 6314 } else { 6315 includelcdmodes = FALSE; 6316 } 6317 /* Ignore interlace, mode switching code will handle this */ 6318 6319 pSiS->HaveCustomModes = FALSE; 6320 if(SiSMakeOwnModeList(pScrn, acceptcustommodes, includelcdmodes, 6321 isfordvi, &pSiS->HaveCustomModes, FALSE, IsForCRT2)) { 6322 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6323 "Replaced %s mode list with built-in modes\n", 6324 pSiS->HaveCustomModes ? "default" : "entire"); 6325 if(pSiS->VGAEngine == SIS_315_VGA) { 6326 int UseWide = pSiS->SiS_Pr->SiS_UseWide; 6327 if(IsForCRT2) UseWide = pSiS->SiS_Pr->SiS_UseWideCRT2; 6328 if((!IsForCRT2) || (pSiS->VBFlags2 & VB2_SISVGA2BRIDGE)) { 6329 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6330 "Using %s widescreen modes for CRT%d VGA devices\n", 6331 UseWide ? "real" : "fake", IsForCRT2 ? 2 : 1); 6332 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6333 "\tUse option \"ForceCRT%dVGAAspect\" to overrule\n", 6334 IsForCRT2 ? 2 : 1); 6335 } 6336 } 6337#ifdef TWDEBUG 6338 pScrn->modes = pScrn->monitor->Modes; 6339 xf86PrintModes(pScrn); 6340 pScrn->modes = NULL; 6341#endif 6342 } else { 6343 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 6344 "Building list of built-in modes failed, using server defaults\n"); 6345 } 6346 } else { 6347 pSiS->HaveCustomModes = TRUE; 6348 } 6349 } 6350 6351 /* Add our built-in hi-res and TV modes on the 6326 */ 6352 if(pSiS->Chipset == PCI_CHIP_SIS6326) { 6353 if(pScrn->bitsPerPixel == 8) { 6354 SiS6326SIS1600x1200_60Mode.next = pScrn->monitor->Modes; 6355 pScrn->monitor->Modes = &SiS6326SIS1600x1200_60Mode; 6356 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6357 "Adding mode \"SIS1600x1200-60\" (depth 8 only)\n"); 6358 } 6359 if(pScrn->bitsPerPixel <= 16) { 6360 SiS6326SIS1280x1024_75Mode.next = pScrn->monitor->Modes; 6361 pScrn->monitor->Modes = &SiS6326SIS1280x1024_75Mode; 6362 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6363 "Adding mode \"SIS1280x1024-75\" (depths 8, 15 and 16 only)\n"); 6364 } 6365 if((pSiS->SiS6326Flags & SIS6326_HASTV) && 6366 (pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 6367 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6368 "Adding %s TV modes to mode list:\n", 6369 (pSiS->SiS6326Flags & SIS6326_TVPAL) ? "PAL" : "NTSC"); 6370 if(pSiS->SiS6326Flags & SIS6326_TVPAL) { 6371 SiS6326PAL800x600Mode.next = pScrn->monitor->Modes; 6372 pScrn->monitor->Modes = &SiS6326PAL640x480Mode; 6373 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6374 "\t\"PAL800x600\" \"PAL800x600U\" \"PAL720x540\" \"PAL640x480\"\n"); 6375 } else { 6376 SiS6326NTSC640x480Mode.next = pScrn->monitor->Modes; 6377 pScrn->monitor->Modes = &SiS6326NTSC640x400Mode; 6378 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6379 "\t\"NTSC640x480\" \"NTSC640x480U\" \"NTSC640x400\"\n"); 6380 } 6381 } 6382 } 6383 6384 /* If there is no HSync or VRefresh data for the monitor, 6385 * derive it from DDC data. Essentially done by common layer 6386 * since 4.3.99.14, but this is not usable since it is done 6387 * too late (in ValidateModes()). 6388 * Addendum: I overrule the ranges now in any case unless 6389 * it would affect a CRT output device or DDC data is available. 6390 * Hence, for LCD(A) and TV, we always get proper ranges. This 6391 * is entirely harmless. However, option "NoOverruleRanges" will 6392 * disable this behavior. 6393 * This should "fix" the - by far - most common configuration 6394 * mistakes. 6395 */ 6396 6397 crt1freqoverruled = FALSE; 6398 6399 fromDDC = FALSE; 6400 if((pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6401 if((pScrn->monitor->nHsync <= 0) && (pScrn->monitor->DDC)) { 6402 SiSSetSyncRangeFromEdid(pScrn, 1); 6403 if(pScrn->monitor->nHsync > 0) { 6404 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subshstr, 6405#ifdef SISDUALHEAD 6406 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6407#endif 6408 pSiS->CRT1off ? 2 : 1); 6409 fromDDC = TRUE; 6410 } 6411 } 6412 if((pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6413 if(SiSAllowSyncOverride(pSiS, fromDDC)) { 6414 Bool HaveNoRanges = (pScrn->monitor->nHsync <= 0); 6415 /* Set sane ranges for LCD and TV 6416 * (our strict checking will filter out invalid ones anyway) 6417 */ 6418 if((crt1freqoverruled = CheckAndOverruleH(pScrn, pScrn->monitor))) { 6419 xf86DrvMsg(pScrn->scrnIndex, X_INFO, saneh, 6420 HaveNoRanges ? "missing" : "bogus", 6421#ifdef SISDUALHEAD 6422 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6423#endif 6424 pSiS->CRT1off ? 2 : 1); 6425 } 6426 } 6427 } 6428 } 6429 6430 fromDDC = FALSE; 6431 if((pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6432 if((pScrn->monitor->nVrefresh <= 0) && (pScrn->monitor->DDC)) { 6433 SiSSetSyncRangeFromEdid(pScrn, 0); 6434 if(pScrn->monitor->nVrefresh > 0) { 6435 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subsvstr, 6436#ifdef SISDUALHEAD 6437 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6438#endif 6439 pSiS->CRT1off ? 2 : 1); 6440 fromDDC = TRUE; 6441 } 6442 } 6443 if((pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6444 if(SiSAllowSyncOverride(pSiS, fromDDC)) { 6445 Bool HaveNoRanges = (pScrn->monitor->nVrefresh <= 0); 6446 /* Set sane ranges for LCD and TV */ 6447 if((crt1freqoverruled = CheckAndOverruleV(pScrn, pScrn->monitor))) { 6448 xf86DrvMsg(pScrn->scrnIndex, X_INFO, sanev, 6449 HaveNoRanges ? "missing" : "bogus", 6450#ifdef SISDUALHEAD 6451 pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 6452#endif 6453 pSiS->CRT1off ? 2 : 1); 6454 } 6455 } 6456 } 6457 } 6458 6459 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 6460 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6461 "\"Unknown reason\" in the following list means that the mode\n"); 6462 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6463 "is not supported on the chipset/bridge/current output device.\n"); 6464 } 6465 6466 /* 6467 * xf86ValidateModes will check that the mode HTotal and VTotal values 6468 * don't exceed the chipset's limit if pScrn->maxHValue and 6469 * pScrn->maxVValue are set. Since our SISValidMode() already takes 6470 * care of this, we don't worry about setting them here. 6471 */ 6472 6473 /* Select valid modes from those available */ 6474 /* 6475 * Assuming min pitch 256, min height 128 6476 */ 6477 { 6478 int minpitch, maxpitch, minheight, maxheight; 6479 pointer backupddc = pScrn->monitor->DDC; 6480 6481 minpitch = 256; 6482 minheight = 128; 6483 switch(pSiS->VGAEngine) { 6484 case SIS_OLD_VGA: 6485 case SIS_530_VGA: 6486 maxpitch = 2040; 6487 maxheight = 2048; 6488 break; 6489 case SIS_300_VGA: 6490 case SIS_315_VGA: 6491 maxpitch = 4088; 6492 maxheight = 4096; 6493 break; 6494 default: 6495 maxpitch = 2048; 6496 maxheight = 2048; 6497 break; 6498 } 6499 6500#ifdef SISMERGED 6501 pSiS->CheckForCRT2 = FALSE; 6502#endif 6503 6504 /* Suppress bogus DDC warning */ 6505 if(crt1freqoverruled) pScrn->monitor->DDC = NULL; 6506 6507 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 6508 pScrn->display->modes, clockRanges, NULL, 6509 minpitch, maxpitch, 6510 pScrn->bitsPerPixel * 8, 6511 minheight, maxheight, 6512 pScrn->display->virtualX, 6513 pScrn->display->virtualY, 6514 pSiS->maxxfbmem, 6515 LOOKUP_BEST_REFRESH); 6516 6517 pScrn->monitor->DDC = backupddc; 6518 } 6519 6520 if(i == -1) { 6521 SISErrorLog(pScrn, "xf86ValidateModes() error\n"); 6522 goto my_error_1; 6523 } 6524 6525 /* Check the virtual screen against the available memory */ 6526 { 6527 ULong memreq = (pScrn->virtualX * ((pScrn->bitsPerPixel + 7) / 8)) * pScrn->virtualY; 6528 6529 if(memreq > pSiS->maxxfbmem) { 6530 SISErrorLog(pScrn, 6531 "Virtual screen too big for memory; %ldK needed, %ldK available\n", 6532 memreq/1024, pSiS->maxxfbmem/1024); 6533 goto my_error_1; 6534 } 6535 } 6536 6537 /* Dual Head: 6538 * -) Go through mode list and mark all those modes as bad, 6539 * which are unsuitable for dual head mode. 6540 * -) Find the highest used pixelclock on the master head. 6541 */ 6542#ifdef SISDUALHEAD 6543 if((pSiS->DualHeadMode) && (!pSiS->SecondHead)) { 6544 6545 pSiSEnt->maxUsedClock = 0; 6546 6547 if((p = first = pScrn->modes)) { 6548 6549 do { 6550 6551 n = p->next; 6552 6553 /* Modes that require the bridge to operate in SlaveMode 6554 * are not suitable for Dual Head mode. 6555 */ 6556 if( (pSiS->VGAEngine == SIS_300_VGA) && 6557 ( (strcmp(p->name, "320x200") == 0) || 6558 (strcmp(p->name, "320x240") == 0) || 6559 (strcmp(p->name, "400x300") == 0) || 6560 (strcmp(p->name, "512x384") == 0) || 6561 (strcmp(p->name, "640x400") == 0) ) ) { 6562 p->status = MODE_BAD; 6563 xf86DrvMsg(pScrn->scrnIndex, X_INFO, notsuitablestr, p->name, "dual head"); 6564 } 6565 6566 /* Search for the highest clock on first head in order to calculate 6567 * max clock for second head (CRT1) 6568 */ 6569 if((p->status == MODE_OK) && (p->Clock > pSiSEnt->maxUsedClock)) { 6570 pSiSEnt->maxUsedClock = p->Clock; 6571 } 6572 6573 p = n; 6574 6575 } while (p != NULL && p != first); 6576 6577 } 6578 } 6579#endif 6580 6581 /* Prune the modes marked as invalid */ 6582 xf86PruneDriverModes(pScrn); 6583 6584 if(i == 0 || pScrn->modes == NULL) { 6585 SISErrorLog(pScrn, "No valid modes found - check VertRefresh/HorizSync\n"); 6586 goto my_error_1; 6587 } 6588 6589 xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 6590 6591 /* Set the current mode to the first in the list */ 6592 pScrn->currentMode = pScrn->modes; 6593 6594 /* Copy to CurrentLayout */ 6595 pSiS->CurrentLayout.mode = pScrn->currentMode; 6596 pSiS->CurrentLayout.displayWidth = pScrn->displayWidth; 6597 pSiS->CurrentLayout.displayHeight = pScrn->virtualY; 6598 6599#ifdef SISMERGED 6600 if(pSiS->MergedFB) { 6601 xf86DrvMsg(pScrn->scrnIndex, X_INFO, modesforstr, 1); 6602 } 6603#endif 6604 6605 /* Print the list of modes being used */ 6606 { 6607 Bool usemyprint = FALSE; 6608 6609#ifdef SISDUALHEAD 6610 if(pSiS->DualHeadMode) { 6611 if(pSiS->SecondHead) { 6612 if(pSiS->VBFlags & CRT1_LCDA) usemyprint = TRUE; 6613 } else { 6614 if(pSiS->VBFlags & (CRT2_LCD | CRT2_TV)) usemyprint = TRUE; 6615 } 6616 } else 6617#endif 6618#ifdef SISMERGED 6619 if(pSiS->MergedFB) { 6620 if(pSiS->VBFlags & CRT1_LCDA) usemyprint = TRUE; 6621 } else 6622#endif 6623 { 6624 if( (pSiS->VBFlags & (CRT2_LCD | CRT2_TV)) && 6625 (!(pSiS->VBFlags & DISPTYPE_DISP1)) ) 6626 usemyprint = TRUE; 6627 } 6628 6629 if(usemyprint) { 6630 SiSPrintModes(pScrn); 6631 } else { 6632 xf86PrintModes(pScrn); 6633 } 6634 } 6635 6636#ifdef SISMERGED 6637 if(pSiS->MergedFB) { 6638 Bool acceptcustommodes = TRUE; 6639 Bool includelcdmodes = TRUE; 6640 Bool isfordvi = FALSE; 6641 6642 xf86DrvMsg(pScrn->scrnIndex, X_INFO, crtsetupstr, 2); 6643 6644 clockRanges->next = NULL; 6645 clockRanges->minClock = pSiS->MinClock; 6646 clockRanges->maxClock = SiSMemBandWidth(pSiS->CRT2pScrn, TRUE); 6647 clockRanges->clockIndex = -1; 6648 clockRanges->interlaceAllowed = FALSE; 6649 clockRanges->doubleScanAllowed = FALSE; 6650 if(pSiS->VGAEngine == SIS_315_VGA) { 6651 clockRanges->doubleScanAllowed = TRUE; 6652 } 6653 6654 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock for CRT2 is %d MHz\n", 6655 clockRanges->minClock / 1000); 6656 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Max pixel clock for CRT2 is %d MHz\n", 6657 clockRanges->maxClock / 1000); 6658 6659 if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 6660 if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 6661 if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA))) includelcdmodes = FALSE; 6662 if(pSiS->VBFlags & CRT2_LCD) isfordvi = TRUE; 6663 /* See above for a remark on handling CRT2 = TV */ 6664 } else { 6665 if(pSiS->VBFlags & (CRT2_LCD|CRT2_TV)) { 6666 includelcdmodes = FALSE; 6667 acceptcustommodes = FALSE; 6668 } 6669 } 6670 } else { 6671 includelcdmodes = FALSE; 6672 acceptcustommodes = FALSE; 6673 } 6674 6675 pSiS->HaveCustomModes2 = FALSE; 6676 if(!SiSMakeOwnModeList(pSiS->CRT2pScrn, acceptcustommodes, includelcdmodes, 6677 isfordvi, &pSiS->HaveCustomModes2, FALSE, TRUE )) { 6678 6679 SISErrorLog(pScrn, "Building list of built-in modes for CRT2 failed, %s\n", 6680 mergeddisstr); 6681 SiSFreeCRT2Structs(pSiS); 6682 pSiS->MergedFB = FALSE; 6683 6684 } else { 6685 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6686 "Replaced %s mode list for CRT2 with built-in modes\n", 6687 pSiS->HaveCustomModes2 ? "default" : "entire"); 6688 if((pSiS->VGAEngine == SIS_315_VGA) && (pSiS->VBFlags2 & VB2_SISVGA2BRIDGE)) { 6689 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6690 "Using %s widescreen modes for CRT2 VGA devices\n", 6691 pSiS->SiS_Pr->SiS_UseWideCRT2 ? "real" : "fake"); 6692 } else pSiS->SiS_Pr->SiS_UseWideCRT2 = 0; 6693 } 6694 6695 } 6696 6697 if(pSiS->MergedFB) { 6698 6699 pointer backupddc; 6700 6701 crt2freqoverruled = FALSE; 6702 6703 fromDDC = FALSE; 6704 if((pSiS->CRT2pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6705 if((pSiS->CRT2pScrn->monitor->nHsync <= 0) && (pSiS->CRT2pScrn->monitor->DDC)) { 6706 SiSSetSyncRangeFromEdid(pSiS->CRT2pScrn, 1); 6707 if(pSiS->CRT2pScrn->monitor->nHsync > 0) { 6708 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subshstr, 2); 6709 fromDDC = TRUE; 6710 } 6711 } 6712 if((pSiS->CRT2pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 6713 if( (pSiS->VBFlags & CRT2_TV) || 6714 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC)) ) { 6715 Bool HaveNoRanges = (pSiS->CRT2pScrn->monitor->nHsync <= 0); 6716 /* Set sane ranges for LCD and TV */ 6717 if((crt2freqoverruled = CheckAndOverruleH(pScrn, pSiS->CRT2pScrn->monitor))) { 6718 xf86DrvMsg(pScrn->scrnIndex, X_INFO, saneh, 6719 HaveNoRanges ? "missing" : "bogus", 2); 6720 } 6721 } 6722 } 6723 } 6724 6725 fromDDC = FALSE; 6726 if((pSiS->CRT2pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6727 if((pSiS->CRT2pScrn->monitor->nVrefresh <= 0) && (pSiS->CRT2pScrn->monitor->DDC)) { 6728 SiSSetSyncRangeFromEdid(pSiS->CRT2pScrn, 0); 6729 if(pSiS->CRT2pScrn->monitor->nVrefresh > 0) { 6730 xf86DrvMsg(pScrn->scrnIndex, X_INFO, subsvstr, 2); 6731 fromDDC = TRUE; 6732 } 6733 } 6734 if((pSiS->CRT2pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 6735 if( (pSiS->VBFlags & CRT2_TV) || 6736 ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC)) ) { 6737 Bool HaveNoRanges = (pSiS->CRT2pScrn->monitor->nVrefresh <= 0); 6738 /* Set sane ranges for LCD and TV */ 6739 if((crt2freqoverruled = CheckAndOverruleV(pScrn, pSiS->CRT2pScrn->monitor))) { 6740 xf86DrvMsg(pScrn->scrnIndex, X_INFO, sanev, 6741 HaveNoRanges ? "missing" : "bogus", 2); 6742 } 6743 } 6744 } 6745 } 6746 6747 backupddc = pSiS->CRT2pScrn->monitor->DDC; 6748 6749 /* Suppress bogus DDC warning */ 6750 if(crt2freqoverruled) pSiS->CRT2pScrn->monitor->DDC = NULL; 6751 6752 pSiS->CheckForCRT2 = TRUE; 6753 6754 i = xf86ValidateModes(pSiS->CRT2pScrn, pSiS->CRT2pScrn->monitor->Modes, 6755 pSiS->CRT2pScrn->display->modes, clockRanges, 6756 NULL, 256, 4088, 6757 pSiS->CRT2pScrn->bitsPerPixel * 8, 128, 4096, 6758 pScrn->display->virtualX ? pScrn->virtualX : 0, 6759 pScrn->display->virtualY ? pScrn->virtualY : 0, 6760 pSiS->maxxfbmem, 6761 LOOKUP_BEST_REFRESH); 6762 6763 pSiS->CheckForCRT2 = FALSE; 6764 pSiS->CRT2pScrn->monitor->DDC = backupddc; 6765 6766 if(i == -1) { 6767 SISErrorLog(pScrn, "xf86ValidateModes() error, %s.\n", mergeddisstr); 6768 SiSFreeCRT2Structs(pSiS); 6769 pSiS->MergedFB = FALSE; 6770 } 6771 6772 } 6773 6774 if(pSiS->MergedFB) { 6775 6776 if((p = first = pSiS->CRT2pScrn->modes)) { 6777 do { 6778 n = p->next; 6779 if( (pSiS->VGAEngine == SIS_300_VGA) && 6780 ( (strcmp(p->name, "320x200") == 0) || 6781 (strcmp(p->name, "320x240") == 0) || 6782 (strcmp(p->name, "400x300") == 0) || 6783 (strcmp(p->name, "512x384") == 0) || 6784 (strcmp(p->name, "640x400") == 0) ) ) { 6785 p->status = MODE_BAD; 6786 xf86DrvMsg(pScrn->scrnIndex, X_INFO, notsuitablestr, p->name, "MergedFB"); 6787 } 6788 p = n; 6789 } while (p != NULL && p != first); 6790 } 6791 6792 xf86PruneDriverModes(pSiS->CRT2pScrn); 6793 6794 if(i == 0 || pSiS->CRT2pScrn->modes == NULL) { 6795 SISErrorLog(pScrn, "No valid modes found for CRT2; %s\n", mergeddisstr); 6796 SiSFreeCRT2Structs(pSiS); 6797 pSiS->MergedFB = FALSE; 6798 } 6799 6800 } 6801 6802 if(pSiS->MergedFB) { 6803 6804 xf86SetCrtcForModes(pSiS->CRT2pScrn, INTERLACE_HALVE_V); 6805 6806 xf86DrvMsg(pScrn->scrnIndex, X_INFO, modesforstr, 2); 6807 6808 if(pSiS->VBFlags & (CRT2_LCD | CRT2_TV)) { 6809 SiSPrintModes(pSiS->CRT2pScrn); 6810 } else { 6811 xf86PrintModes(pSiS->CRT2pScrn); 6812 } 6813 6814 pSiS->CRT1Modes = pScrn->modes; 6815 pSiS->CRT1CurrentMode = pScrn->currentMode; 6816 6817 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MergedFB: Generating mode list\n"); 6818 6819 pScrn->modes = SiSGenerateModeList(pScrn, pSiS->MetaModes, 6820 pSiS->CRT1Modes, pSiS->CRT2pScrn->modes, 6821 pSiS->CRT2Position); 6822 6823 if(!pScrn->modes) { 6824 6825 SISErrorLog(pScrn, "Failed to parse MetaModes or no modes found. %s.\n", 6826 mergeddisstr); 6827 SiSFreeCRT2Structs(pSiS); 6828 pScrn->modes = pSiS->CRT1Modes; 6829 pSiS->CRT1Modes = NULL; 6830 pSiS->MergedFB = FALSE; 6831 6832 } 6833 6834 } 6835 6836 if(pSiS->MergedFB) { 6837 6838 /* If no virtual dimension was given by the user, 6839 * calculate a sane one now. Adapts pScrn->virtualX, 6840 * pScrn->virtualY and pScrn->displayWidth. 6841 */ 6842 SiSRecalcDefaultVirtualSize(pScrn); 6843 6844 pScrn->modes = pScrn->modes->next; /* We get the last from GenerateModeList(), skip to first */ 6845 pScrn->currentMode = pScrn->modes; 6846 6847 /* Update CurrentLayout */ 6848 pSiS->CurrentLayout.mode = pScrn->currentMode; 6849 pSiS->CurrentLayout.displayWidth = pScrn->displayWidth; 6850 pSiS->CurrentLayout.displayHeight = pScrn->virtualY; 6851 6852 } 6853#endif 6854 6855 /* Set display resolution */ 6856#ifdef SISMERGED 6857 if(pSiS->MergedFB) { 6858 SiSMergedFBSetDpi(pScrn, pSiS->CRT2pScrn, pSiS->CRT2Position); 6859 } else 6860#endif 6861 xf86SetDpi(pScrn, 0, 0); 6862 6863 /* Load fb module */ 6864 switch(pScrn->bitsPerPixel) { 6865 case 8: 6866 case 16: 6867 case 24: 6868 case 32: 6869 if(!xf86LoadSubModule(pScrn, "fb")) { 6870 SISErrorLog(pScrn, "Failed to load fb module"); 6871 goto my_error_1; 6872 } 6873 break; 6874 default: 6875 SISErrorLog(pScrn, "Unsupported framebuffer bpp (%d)\n", pScrn->bitsPerPixel); 6876 goto my_error_1; 6877 } 6878 6879 /* Load XAA/EXA (if needed) */ 6880 if(!pSiS->NoAccel) { 6881#ifdef SIS_USE_XAA 6882 if(!pSiS->useEXA) { 6883 if (!xf86LoadSubModule(pScrn, "xaa")) { 6884 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 6885 "Falling back to shadowfb\n"); 6886 pSiS->NoAccel = 1; 6887 pSiS->ShadowFB = 1; 6888 } 6889 } 6890#endif 6891#ifdef SIS_USE_EXA 6892 if(pSiS->useEXA) { 6893 XF86ModReqInfo req; 6894 int errmaj, errmin; 6895 6896 memset(&req, 0, sizeof(req)); 6897 req.majorversion = 2; 6898 req.minorversion = 0; 6899 if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, &req, 6900 &errmaj, &errmin)) { 6901 LoaderErrorMsg(NULL, "exa", errmaj, errmin); 6902 goto my_error_1; 6903 } 6904 } 6905#endif 6906 } 6907 6908 /* Load shadowfb (if needed) */ 6909 if(pSiS->ShadowFB) { 6910 if(!xf86LoadSubModule(pScrn, "shadowfb")) { 6911 SISErrorLog(pScrn, "Could not load shadowfb module\n"); 6912 goto my_error_1; 6913 } 6914 } 6915 6916 /* Load the dri modules if requested. */ 6917#ifdef SISDRI 6918 if(pSiS->loadDRI) { 6919 if(!xf86LoaderCheckSymbol("DRIScreenInit")) { 6920 if(!xf86LoadSubModule(pScrn, "dri")) { 6921 SISErrorLog(pScrn, "Failed to load dri module\n"); 6922 } 6923 } 6924 } 6925#endif 6926 6927 /* Now load and initialize VBE module for VESA mode switching */ 6928 pSiS->UseVESA = 0; 6929 if(pSiS->VESA == 1) { 6930 SiS_LoadInitVBE(pScrn); 6931 if(pSiS->pVbe) { 6932 VbeInfoBlock *vbe; 6933 if((vbe = VBEGetVBEInfo(pSiS->pVbe))) { 6934 pSiS->vesamajor = (unsigned)(vbe->VESAVersion >> 8); 6935 pSiS->vesaminor = vbe->VESAVersion & 0xff; 6936 SiSBuildVesaModeList(pScrn, pSiS->pVbe, vbe); 6937 VBEFreeVBEInfo(vbe); 6938 pSiS->UseVESA = 1; 6939 } else { 6940 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 6941 "Failed to read VBE Info Block\n"); 6942 } 6943 } 6944 if(pSiS->UseVESA == 0) { 6945 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 6946 "VESA mode switching disabled.\n"); 6947 } 6948 } 6949 6950 if(pSiS->pVbe) { 6951 vbeFree(pSiS->pVbe); 6952 pSiS->pVbe = NULL; 6953 } 6954 6955#ifdef SISDUALHEAD 6956 xf86SetPrimInitDone(pScrn->entityList[0]); 6957#endif 6958 6959 sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); 6960 6961 if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); 6962 pSiS->pInt = NULL; 6963 6964 if(pSiS->VGAEngine == SIS_315_VGA) { 6965 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTXVGAMMA1; 6966 } 6967 6968#ifdef SISDUALHEAD 6969 if(pSiS->DualHeadMode) { 6970 pSiS->SiS_SD_Flags |= SiS_SD_ISDUALHEAD; 6971 if(pSiS->SecondHead) pSiS->SiS_SD_Flags |= SiS_SD_ISDHSECONDHEAD; 6972 else pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTXVGAMMA1); 6973#ifdef PANORAMIX 6974 if(!noPanoramiXExtension) { 6975 pSiS->SiS_SD_Flags |= SiS_SD_ISDHXINERAMA; 6976 /* pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTXVGAMMA1); */ 6977 } 6978#endif 6979 } 6980#endif 6981 6982#ifdef SISMERGED 6983 if(pSiS->MergedFB) pSiS->SiS_SD_Flags |= SiS_SD_ISMERGEDFB; 6984#endif 6985 6986 /* Try to determine if this is a laptop */ 6987 /* (only used for SiSCtrl visualisations) */ 6988 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPLTFLAG; 6989 pSiS->SiS_SD2_Flags &= ~SiS_SD2_ISLAPTOP; 6990 if(pSiS->detectedCRT2Devices & CRT2_LCD) { 6991 if(pSiS->VBFlags2 & (VB2_SISLVDSBRIDGE | VB2_LVDS | VB2_30xBDH)) { 6992 /* 1. By bridge type: LVDS in 99% of all cases; 6993 * exclude unusual setups like Barco projectors 6994 * and parallel flat panels. TODO: Exclude 6995 * Sony W1, V1. 6996 */ 6997 if((pSiS->SiS_Pr->SiS_CustomT != CUT_BARCO1366) && 6998 (pSiS->SiS_Pr->SiS_CustomT != CUT_BARCO1024) && 6999 (pSiS->SiS_Pr->SiS_CustomT != CUT_PANEL848) && 7000 (pSiS->SiS_Pr->SiS_CustomT != CUT_PANEL856) && 7001 (pSiS->SiS_Pr->SiS_CustomT != CUT_AOP8060) && 7002 ( (pSiS->ChipType != SIS_550) || 7003 (!pSiS->DSTN && !pSiS->FSTN) ) ) { 7004 pSiS->SiS_SD2_Flags |= SiS_SD2_ISLAPTOP; 7005 } 7006 } else if((pSiS->VBFlags2 & (VB2_301 | VB2_301C)) && 7007 (pSiS->VBLCDFlags & (VB_LCD_1280x960 | 7008 VB_LCD_1400x1050 | 7009 VB_LCD_1024x600 | 7010 VB_LCD_1280x800 | 7011 VB_LCD_1280x854))) { 7012 /* 2. By (odd) LCD resolutions on TMDS bridges 7013 * (eg Averatec). TODO: Exclude IBM Netvista. 7014 */ 7015 pSiS->SiS_SD2_Flags |= SiS_SD2_ISLAPTOP; 7016 } 7017 } 7018 7019 if(pSiS->enablesisctrl) pSiS->SiS_SD_Flags |= SiS_SD_ENABLED; 7020 7021 pSiS->currentModeLast = pScrn->currentMode; 7022 pSiS->VBFlagsInit = pSiS->VBFlags; 7023 7024 return TRUE; 7025 7026 /* ---- */ 7027 7028my_error_1: 7029 sisRestoreExtRegisterLock(pSiS, srlockReg, crlockReg); 7030my_error_0: 7031#ifdef SISDUALHEAD 7032 if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; 7033#endif 7034 if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); 7035 pSiS->pInt = NULL; 7036 SISFreeRec(pScrn); 7037 return FALSE; 7038} 7039 7040/* 7041 * Map I/O port area for non-PC platforms 7042 */ 7043#ifdef SIS_NEED_MAP_IOP 7044static Bool 7045SISMapIOPMem(ScrnInfoPtr pScrn) 7046{ 7047 SISPtr pSiS = SISPTR(pScrn); 7048#ifdef SISDUALHEAD 7049 SISEntPtr pSiSEnt = pSiS->entityPrivate; 7050 7051 if(pSiS->DualHeadMode) { 7052 pSiSEnt->MapCountIOPBase++; 7053 if(!(pSiSEnt->IOPBase)) { 7054 /* Only map if not mapped previously */ 7055#ifndef XSERVER_LIBPCIACCESS 7056 pSiSEnt->IOPBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7057 pSiS->PciTag, pSiS->IOPAddress, 128); 7058#else 7059 { 7060 void **result = (void **)&pSiSEnt->IOPBase; 7061 int err = pci_device_map_range(pSiS->PciInfo, 7062 pSiS->IOPAddress, 7063 128, 7064 PCI_DEV_MAP_FLAG_WRITABLE, 7065 result); 7066 7067 if (err) { 7068 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7069 "Unable to map IO aperture. %s (%d)\n", 7070 strerror (err), err); 7071 } 7072 } 7073#endif 7074 } 7075 pSiS->IOPBase = pSiSEnt->IOPBase; 7076 } else 7077#endif 7078#ifndef XSERVER_LIBPCIACCESS 7079 pSiS->IOPBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7080 pSiS->PciTag, pSiS->IOPAddress, 128); 7081#else 7082 { 7083 void **result = (void **)&pSiS->IOPBase; 7084 int err = pci_device_map_range(pSiS->PciInfo, 7085 pSiS->IOPAddress, 7086 128, 7087 PCI_DEV_MAP_FLAG_WRITABLE, 7088 result); 7089 7090 if (err) { 7091 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7092 "Unable to map IO aperture. %s (%d)\n", 7093 strerror (err), err); 7094 } 7095 } 7096#endif 7097 if(pSiS->IOPBase == NULL) { 7098 SISErrorLog(pScrn, "Could not map I/O port area\n"); 7099 return FALSE; 7100 } 7101 7102 return TRUE; 7103} 7104 7105static Bool 7106SISUnmapIOPMem(ScrnInfoPtr pScrn) 7107{ 7108 SISPtr pSiS = SISPTR(pScrn); 7109#ifdef SISDUALHEAD 7110 SISEntPtr pSiSEnt = pSiS->entityPrivate;; 7111#endif 7112 7113/* In dual head mode, we must not unmap if the other head still 7114 * assumes memory as mapped 7115 */ 7116#ifdef SISDUALHEAD 7117 if(pSiS->DualHeadMode) { 7118 if(pSiSEnt->MapCountIOPBase) { 7119 pSiSEnt->MapCountIOPBase--; 7120 if((pSiSEnt->MapCountIOPBase == 0) || (pSiSEnt->forceUnmapIOPBase)) { 7121 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOPBase, 2048); 7122 pSiSEnt->IOPBase = NULL; 7123 pSiSEnt->MapCountIOPBase = 0; 7124 pSiSEnt->forceUnmapIOPBase = FALSE; 7125 } 7126 pSiS->IOPBase = NULL; 7127 } 7128 } else { 7129#endif 7130 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOPBase, 2048); 7131 pSiS->IOPBase = NULL; 7132#ifdef SISDUALHEAD 7133 } 7134#endif 7135 return TRUE; 7136} 7137#endif 7138 7139/* 7140 * Map the framebuffer and MMIO memory 7141 */ 7142 7143static Bool 7144SISMapMem(ScrnInfoPtr pScrn) 7145{ 7146 SISPtr pSiS = SISPTR(pScrn); 7147#ifndef XSERVER_LIBPCIACCESS 7148 int mmioFlags = VIDMEM_MMIO; 7149#endif 7150#ifdef SISDUALHEAD 7151 SISEntPtr pSiSEnt = pSiS->entityPrivate; 7152#endif 7153 7154 /* 7155 * Map IO registers to virtual address space 7156 * (For Alpha, we need to map SPARSE memory, since we need 7157 * byte/short access.) 7158 */ 7159#ifndef XSERVER_LIBPCIACCESS 7160#if defined(__alpha__) 7161 mmioFlags |= VIDMEM_SPARSE; 7162#endif 7163#endif 7164 7165#ifdef SISDUALHEAD 7166 if(pSiS->DualHeadMode) { 7167 pSiSEnt->MapCountIOBase++; 7168 if(!(pSiSEnt->IOBase)) { 7169 /* Only map if not mapped previously */ 7170#ifndef XSERVER_LIBPCIACCESS 7171 pSiSEnt->IOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, 7172 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7173#else 7174 void **result = (void **)&pSiSEnt->IOBase; 7175 int err = pci_device_map_range(pSiS->PciInfo, 7176 pSiS->IOAddress, 7177 (pSiS->mmioSize * 1024), 7178 PCI_DEV_MAP_FLAG_WRITABLE, 7179 result); 7180 7181 if (err) { 7182 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7183 "Unable to map IO aperture. %s (%d)\n", 7184 strerror (err), err); 7185 } 7186#endif 7187 } 7188 pSiS->IOBase = pSiSEnt->IOBase; 7189 } else 7190#endif 7191#ifndef XSERVER_LIBPCIACCESS 7192 pSiS->IOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, 7193 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7194#else 7195 { 7196 void **result = (void **)&pSiS->IOBase; 7197 int err = pci_device_map_range(pSiS->PciInfo, 7198 pSiS->IOAddress, 7199 (pSiS->mmioSize * 1024), 7200 PCI_DEV_MAP_FLAG_WRITABLE, 7201 result); 7202 7203 if (err) { 7204 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7205 "Unable to map IO aperture. %s (%d)\n", 7206 strerror (err), err); 7207 } 7208 } 7209#endif 7210 7211 if(pSiS->IOBase == NULL) { 7212 SISErrorLog(pScrn, "Could not map MMIO area\n"); 7213 return FALSE; 7214 } 7215 7216#ifdef __alpha__ 7217 /* 7218 * for Alpha, we need to map DENSE memory as well, for 7219 * setting CPUToScreenColorExpandBase. 7220 */ 7221#ifdef SISDUALHEAD 7222 if(pSiS->DualHeadMode) { 7223 pSiSEnt->MapCountIOBaseDense++; 7224 if(!(pSiSEnt->IOBaseDense)) { 7225 /* Only map if not mapped previously */ 7226#ifndef XSERVER_LIBPCIACCESS 7227 pSiSEnt->IOBaseDense = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7228 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7229#else 7230 void **result = (void **)&pSiSEnt->IOBaseDense; 7231 int err = pci_device_map_range(pSiS->PciInfo, 7232 pSiS->IOAddress, 7233 (pSiS->mmioSize * 1024), 7234 PCI_DEV_MAP_FLAG_WRITABLE, 7235 result); 7236 7237 if (err) { 7238 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7239 "Unable to map IO dense aperture. %s (%d)\n", 7240 strerror (err), err); 7241 } 7242#endif /* XSERVER_LIBPCIACCESS */ 7243 } 7244 pSiS->IOBaseDense = pSiSEnt->IOBaseDense; 7245 } else { 7246#endif /* SISDUALHEAD */ 7247#ifndef XSERVER_LIBPCIACCESS 7248 pSiS->IOBaseDense = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 7249 pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 7250#else 7251 void **result = (void **)&pSiS->IOBaseDense; 7252 int err = pci_device_map_range(pSiS->PciInfo, 7253 pSiS->IOAddress, 7254 (pSiS->mmioSize * 1024), 7255 PCI_DEV_MAP_FLAG_WRITABLE, 7256 result); 7257 7258 if (err) { 7259 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7260 "Unable to map IO dense aperture. %s (%d)\n", 7261 strerror (err), err); 7262 } 7263#endif /* XSERVER_LIBPCIACCESS */ 7264#ifdef SISDUALHEAD 7265 } 7266#endif 7267 if(pSiS->IOBaseDense == NULL) { 7268 SISErrorLog(pScrn, "Could not map MMIO dense area\n"); 7269 return FALSE; 7270 } 7271#endif /* __alpha__ */ 7272 7273#ifdef SISDUALHEAD 7274 if(pSiS->DualHeadMode) { 7275 pSiSEnt->MapCountFbBase++; 7276 if(!(pSiSEnt->FbBase)) { 7277 /* Only map if not mapped previously */ 7278#ifndef XSERVER_LIBPCIACCESS 7279 pSiSEnt->FbBase = pSiSEnt->RealFbBase = 7280 xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 7281 pSiS->PciTag, (ULong)pSiS->realFbAddress, 7282 pSiS->FbMapSize); 7283#else 7284 int err = pci_device_map_range(pSiS->PciInfo, 7285 (ULong)pSiS->realFbAddress, 7286 pSiS->FbMapSize, 7287 PCI_DEV_MAP_FLAG_WRITABLE | 7288 PCI_DEV_MAP_FLAG_WRITE_COMBINE, 7289 (void *)&pSiSEnt->FbBase); 7290 if (err) { 7291 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7292 "Unable to map FB aperture. %s (%d)\n", 7293 strerror (err), err); 7294 return FALSE; 7295 } 7296 pSiSEnt->RealFbBase = pSiSEnt->FbBase; 7297#endif 7298 } 7299 pSiS->FbBase = pSiS->RealFbBase = pSiSEnt->FbBase; 7300 /* Adapt FbBase (for DHM and SiS76x UMA skipping; dhmOffset is 0 otherwise) */ 7301 pSiS->FbBase += pSiS->dhmOffset; 7302 } else { 7303#endif 7304 7305#ifndef XSERVER_LIBPCIACCESS 7306 pSiS->FbBase = pSiS->RealFbBase = 7307 xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 7308 pSiS->PciTag, (ULong)pSiS->realFbAddress, 7309 pSiS->FbMapSize); 7310#else 7311 int err = pci_device_map_range(pSiS->PciInfo, 7312 (ULong)pSiS->realFbAddress, 7313 pSiS->FbMapSize, 7314 PCI_DEV_MAP_FLAG_WRITABLE | 7315 PCI_DEV_MAP_FLAG_WRITE_COMBINE, 7316 (void *)&pSiS->FbBase); 7317 if (err) { 7318 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 7319 "Unable to map FB aperture. %s (%d)\n", 7320 strerror (err), err); 7321 return FALSE; 7322 } 7323 pSiS->RealFbBase = pSiS->FbBase; 7324#endif 7325 pSiS->FbBase += pSiS->dhmOffset; 7326 7327#ifdef SISDUALHEAD 7328 } 7329#endif 7330 7331 if(pSiS->FbBase == NULL) { 7332 SISErrorLog(pScrn, "Could not map framebuffer area\n"); 7333 return FALSE; 7334 } 7335 7336#ifdef TWDEBUG 7337 xf86DrvMsg(0, 0, "Framebuffer mapped to %p\n", pSiS->FbBase); 7338#endif 7339 7340 return TRUE; 7341} 7342 7343 7344/* 7345 * Unmap the framebuffer and MMIO memory. 7346 */ 7347 7348static Bool 7349SISUnmapMem(ScrnInfoPtr pScrn) 7350{ 7351 SISPtr pSiS = SISPTR(pScrn); 7352#ifdef SISDUALHEAD 7353 SISEntPtr pSiSEnt = pSiS->entityPrivate; 7354#endif 7355 7356/* In dual head mode, we must not unmap if the other head still 7357 * assumes memory as mapped 7358 */ 7359#ifdef SISDUALHEAD 7360 if(pSiS->DualHeadMode) { 7361 if(pSiSEnt->MapCountIOBase) { 7362 pSiSEnt->MapCountIOBase--; 7363 if((pSiSEnt->MapCountIOBase == 0) || (pSiSEnt->forceUnmapIOBase)) { 7364#ifndef XSERVER_LIBPCIACCESS 7365 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOBase, (pSiS->mmioSize * 1024)); 7366#else 7367 pci_device_unmap_range(pSiS->PciInfo, pSiSEnt->IOBase, (pSiS->mmioSize * 1024)); 7368#endif 7369 pSiSEnt->IOBase = NULL; 7370 pSiSEnt->MapCountIOBase = 0; 7371 pSiSEnt->forceUnmapIOBase = FALSE; 7372 } 7373 pSiS->IOBase = NULL; 7374 } 7375#ifdef __alpha__ 7376 if(pSiSEnt->MapCountIOBaseDense) { 7377 pSiSEnt->MapCountIOBaseDense--; 7378 if((pSiSEnt->MapCountIOBaseDense == 0) || (pSiSEnt->forceUnmapIOBaseDense)) { 7379#ifndef XSERVER_LIBPCIACCESS 7380 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOBaseDense, (pSiS->mmioSize * 1024)); 7381#else 7382 pci_device_unmap_range(pSiS->PciInfo, (pointer)pSiSEnt->IOBaseDense, (pSiS->mmioSize * 1024)); 7383#endif 7384 pSiSEnt->IOBaseDense = NULL; 7385 pSiSEnt->MapCountIOBaseDense = 0; 7386 pSiSEnt->forceUnmapIOBaseDense = FALSE; 7387 } 7388 pSiS->IOBaseDense = NULL; 7389 } 7390#endif /* __alpha__ */ 7391 if(pSiSEnt->MapCountFbBase) { 7392 pSiSEnt->MapCountFbBase--; 7393 if((pSiSEnt->MapCountFbBase == 0) || (pSiSEnt->forceUnmapFbBase)) { 7394#ifndef XSERVER_LIBPCIACCESS 7395 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->RealFbBase, pSiS->FbMapSize); 7396#else 7397 pci_device_unmap_range(pSiS->PciInfo, (pointer)pSiSEnt->RealFbBase, pSiS->FbMapSize); 7398#endif 7399 pSiSEnt->FbBase = pSiSEnt->RealFbBase = NULL; 7400 pSiSEnt->MapCountFbBase = 0; 7401 pSiSEnt->forceUnmapFbBase = FALSE; 7402 7403 } 7404 pSiS->FbBase = pSiS->RealFbBase = NULL; 7405 } 7406 } else { 7407#endif 7408#ifndef XSERVER_LIBPCIACCESS 7409 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOBase, (pSiS->mmioSize * 1024)); 7410#else 7411 pci_device_unmap_range(pSiS->PciInfo, (pointer)pSiS->IOBase, (pSiS->mmioSize * 1024)); 7412#endif 7413 pSiS->IOBase = NULL; 7414#ifdef __alpha__ 7415#ifndef XSERVER_LIBPCIACCESS 7416 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOBaseDense, (pSiS->mmioSize * 1024)); 7417#else 7418 pci_device_unmap_range(pSiS->PciInfo, (pointer)pSiS->IOBaseDense, (pSiS->mmioSize * 1024)); 7419#endif 7420 pSiS->IOBaseDense = NULL; 7421#endif 7422#ifndef XSERVER_LIBPCIACCESS 7423 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->RealFbBase, pSiS->FbMapSize); 7424#else 7425 pci_device_unmap_range(pSiS->PciInfo, (pointer)pSiS->RealFbBase, pSiS->FbMapSize); 7426#endif 7427 pSiS->FbBase = pSiS->RealFbBase = NULL; 7428#ifdef SISDUALHEAD 7429 } 7430#endif 7431 return TRUE; 7432} 7433 7434/* 7435 * This function saves the video state. 7436 */ 7437static void 7438SISSave(ScrnInfoPtr pScrn) 7439{ 7440 SISPtr pSiS = SISPTR(pScrn); 7441 SISRegPtr sisReg; 7442 int flags; 7443 7444#ifdef SISDUALHEAD 7445 /* We always save master & slave */ 7446 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 7447#endif 7448 7449 sisReg = &pSiS->SavedReg; 7450 7451 if( ((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) && 7452 ((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (SiSBridgeIsInSlaveMode(pScrn))) ) { 7453 SiSVGASave(pScrn, sisReg, SISVGA_SR_CMAP | SISVGA_SR_MODE); 7454#ifdef SIS_PC_PLATFORM 7455 if(pSiS->VGAMemBase) { 7456 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO+0x30); 7457 SiSSetLVDSetc(pSiS->SiS_Pr); 7458 SiS_GetVBType(pSiS->SiS_Pr); 7459 SiS_DisableBridge(pSiS->SiS_Pr); 7460 SiSVGASave(pScrn, sisReg, SISVGA_SR_FONTS); 7461 SiS_EnableBridge(pSiS->SiS_Pr); 7462 } 7463#endif 7464 } else { 7465 flags = SISVGA_SR_CMAP | SISVGA_SR_MODE; 7466#ifdef SIS_PC_PLATFORM 7467 if(pSiS->VGAMemBase) flags |= SISVGA_SR_FONTS; 7468#endif 7469 SiSVGASave(pScrn, sisReg, flags); 7470 } 7471 7472 sisSaveUnlockExtRegisterLock(pSiS, &sisReg->sisRegs3C4[0x05], &sisReg->sisRegs3D4[0x80]); 7473 7474 (*pSiS->SiSSave)(pScrn, sisReg); 7475 7476 if(pSiS->UseVESA) SISVESASaveRestore(pScrn, MODE_SAVE); 7477 7478 /* "Save" these again as they may have been changed prior to SISSave() call */ 7479 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 7480 sisReg->sisRegs3C4[0x1f] = pSiS->oldSR1F; 7481 sisReg->sisRegs3D4[0x17] = pSiS->oldCR17; 7482 sisReg->sisRegs3D4[0x32] = pSiS->oldCR32; 7483 sisReg->sisRegs3D4[0x36] = pSiS->oldCR36; 7484 sisReg->sisRegs3D4[0x37] = pSiS->oldCR37; 7485 if(pSiS->VGAEngine == SIS_315_VGA) { 7486 sisReg->sisRegs3D4[pSiS->myCR63] = pSiS->oldCR63; 7487 } 7488 } 7489} 7490 7491/* VESASaveRestore taken from vesa driver */ 7492static void 7493SISVESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function) 7494{ 7495 SISPtr pSiS = SISPTR(pScrn); 7496 7497 /* Query amount of memory to save state */ 7498 if((function == MODE_QUERY) || 7499 (function == MODE_SAVE && pSiS->state == NULL)) { 7500 7501 /* Make sure we save at least this information in case of failure */ 7502 (void)VBEGetVBEMode(pSiS->pVbe, &pSiS->stateMode); 7503 SiSVGASaveFonts(pScrn); 7504 7505 if(pSiS->vesamajor > 1) { 7506 if(!VBESaveRestore(pSiS->pVbe, function, (pointer)&pSiS->state, 7507 &pSiS->stateSize, &pSiS->statePage)) { 7508 return; 7509 } 7510 } 7511 } 7512 7513 /* Save/Restore Super VGA state */ 7514 if(function != MODE_QUERY) { 7515 7516 if(pSiS->vesamajor > 1) { 7517 if(function == MODE_RESTORE) { 7518 memcpy(pSiS->state, pSiS->pstate, pSiS->stateSize); 7519 } 7520 7521 if(VBESaveRestore(pSiS->pVbe,function,(pointer)&pSiS->state, 7522 &pSiS->stateSize,&pSiS->statePage) && 7523 (function == MODE_SAVE)) { 7524 /* don't rely on the memory not being touched */ 7525 if(!pSiS->pstate) { 7526 pSiS->pstate = malloc(pSiS->stateSize); 7527 } 7528 memcpy(pSiS->pstate, pSiS->state, pSiS->stateSize); 7529 } 7530 } 7531 7532 if(function == MODE_RESTORE) { 7533 VBESetVBEMode(pSiS->pVbe, pSiS->stateMode, NULL); 7534 SiSVGARestoreFonts(pScrn); 7535 } 7536 7537 } 7538} 7539 7540/* 7541 * Initialise a new mode. This is currently done using the 7542 * "initialise struct, restore/write struct to HW" model for 7543 * the old chipsets (5597/530/6326). For newer chipsets, 7544 * we use our own mode switching code. 7545 */ 7546 7547static Bool 7548SISModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 7549{ 7550 SISPtr pSiS = SISPTR(pScrn); 7551 SISRegPtr sisReg; 7552#ifdef SISDUALHEAD 7553 SISEntPtr pSiSEnt = NULL; 7554#endif 7555 7556 andSISIDXREG(SISCR,0x11,0x7f); /* Unlock CRTC registers */ 7557 7558 SISModifyModeInfo(mode); /* Quick check of the mode parameters */ 7559 7560 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7561 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO+0x30); 7562 } 7563 7564 if(pSiS->UseVESA) { /* With VESA: */ 7565 7566#ifdef SISDUALHEAD 7567 /* No dual head mode when using VESA */ 7568 if(pSiS->SecondHead) return TRUE; 7569#endif 7570 7571 pScrn->vtSema = TRUE; 7572 7573 /* 7574 * This order is required: 7575 * The video bridge needs to be adjusted before the 7576 * BIOS is run as the BIOS sets up CRT2 according to 7577 * these register settings. 7578 * After the BIOS is run, the bridges and turboqueue 7579 * registers need to be readjusted as the BIOS may 7580 * very probably have messed them up. 7581 */ 7582 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7583 SiSPreSetMode(pScrn, mode, SIS_MODE_SIMU); 7584 } 7585 if(!SiSSetVESAMode(pScrn, mode)) { 7586 SISErrorLog(pScrn, "SiSSetVESAMode() failed\n"); 7587 return FALSE; 7588 } 7589 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7590 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7591 SiSPreSetMode(pScrn, mode, SIS_MODE_SIMU); 7592 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7593 } 7594#ifdef TWDEBUG 7595 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 7596 "REAL REGISTER CONTENTS AFTER SETMODE:\n"); 7597#endif 7598 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7599 SISErrorLog(pScrn, "ModeInit() failed\n"); 7600 return FALSE; 7601 } 7602 7603 SiSVGAProtect(pScrn, TRUE); 7604 (*pSiS->SiSRestore)(pScrn, &pSiS->ModeReg); 7605 SiSVGAProtect(pScrn, FALSE); 7606 7607 } else { /* Without VESA: */ 7608 7609#ifdef SISDUALHEAD 7610 if(pSiS->DualHeadMode) { 7611 7612 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7613 SISErrorLog(pScrn, "ModeInit() failed\n"); 7614 return FALSE; 7615 } 7616 7617 pScrn->vtSema = TRUE; 7618 7619 pSiSEnt = pSiS->entityPrivate; 7620 7621 if(!(pSiS->SecondHead)) { 7622 /* Head 1 (master) is always CRT2 */ 7623 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT2); 7624 if(!SiSBIOSSetModeCRT2(pSiS->SiS_Pr, pScrn, mode, pSiS->IsCustom)) { 7625 SISErrorLog(pScrn, "SiSBIOSSetModeCRT2() failed\n"); 7626 return FALSE; 7627 } 7628 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7629 if(pSiSEnt->pScrn_2) { 7630 SISAdjustFrame(ADJUST_FRAME_ARGS(pSiSEnt->pScrn_2, 7631 pSiSEnt->pScrn_2->frameX0, 7632 pSiSEnt->pScrn_2->frameY0)); 7633 } 7634 } else { 7635 /* Head 2 (slave) is always CRT1 */ 7636 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT1); 7637 if(!SiSBIOSSetModeCRT1(pSiS->SiS_Pr, pScrn, mode, pSiS->IsCustom)) { 7638 SISErrorLog(pScrn, "SiSBIOSSetModeCRT1() failed\n"); 7639 return FALSE; 7640 } 7641 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7642 if(pSiSEnt->pScrn_1) { 7643 SISAdjustFrame(ADJUST_FRAME_ARGS(pSiSEnt->pScrn_1, 7644 pSiSEnt->pScrn_1->frameX0, 7645 pSiSEnt->pScrn_1->frameY0)); 7646 } 7647 } 7648 7649 } else { 7650#endif 7651 7652 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 7653 7654 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7655 SISErrorLog(pScrn, "ModeInit() failed\n"); 7656 return FALSE; 7657 } 7658 7659 pScrn->vtSema = TRUE; 7660 7661#ifdef SISMERGED 7662 if(pSiS->MergedFB) { 7663 7664 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting MergedFB mode %dx%d\n", 7665 mode->HDisplay, mode->VDisplay); 7666 7667 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT1); 7668 7669 if(!SiSBIOSSetModeCRT1(pSiS->SiS_Pr, pScrn, 7670 ((SiSMergedDisplayModePtr)mode->Private)->CRT1, 7671 pSiS->IsCustom)) { 7672 SISErrorLog(pScrn, "SiSBIOSSetModeCRT1() failed\n"); 7673 return FALSE; 7674 } 7675 7676 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT2); 7677 7678 if(!SiSBIOSSetModeCRT2(pSiS->SiS_Pr, pScrn, 7679 ((SiSMergedDisplayModePtr)mode->Private)->CRT2, 7680 pSiS->IsCustom)) { 7681 SISErrorLog(pScrn, "SiSBIOSSetModeCRT2() failed\n"); 7682 return FALSE; 7683 } 7684 7685 } else { 7686#endif 7687 7688 if((pSiS->VBFlags & CRT1_LCDA) || (!(mode->type & M_T_DEFAULT))) { 7689 7690 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT1); 7691 7692 if(!SiSBIOSSetModeCRT1(pSiS->SiS_Pr, pScrn, 7693 mode, pSiS->IsCustom)) { 7694 SISErrorLog(pScrn, "SiSBIOSSetModeCRT1() failed\n"); 7695 return FALSE; 7696 } 7697 7698 SiSPreSetMode(pScrn, mode, SIS_MODE_CRT2); 7699 7700 if(!SiSBIOSSetModeCRT2(pSiS->SiS_Pr, pScrn, 7701 mode, pSiS->IsCustom)) { 7702 SISErrorLog(pScrn, "SiSBIOSSetModeCRT2() failed\n"); 7703 return FALSE; 7704 } 7705 7706 } else { 7707 7708 SiSPreSetMode(pScrn, mode, SIS_MODE_SIMU); 7709 7710 if(!SiSBIOSSetMode(pSiS->SiS_Pr, pScrn, 7711 mode, pSiS->IsCustom)) { 7712 SISErrorLog(pScrn, "SiSBIOSSetMode() failed\n"); 7713 return FALSE; 7714 } 7715 7716 } 7717 7718#ifdef SISMERGED 7719 } 7720#endif 7721 7722 SiSPostSetMode(pScrn, &pSiS->ModeReg); 7723 7724#ifdef TWDEBUG 7725 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VBFlags %lx\n", pSiS->VBFlags); 7726 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 7727 "REAL REGISTER CONTENTS AFTER SETMODE:\n"); 7728 (*pSiS->ModeInit)(pScrn, mode); 7729#endif 7730 7731 } else { 7732 7733 /* For other chipsets, use the old method */ 7734 7735 /* Prepare the register contents */ 7736 if(!(*pSiS->ModeInit)(pScrn, mode)) { 7737 SISErrorLog(pScrn, "ModeInit() failed\n"); 7738 return FALSE; 7739 } 7740 7741 pScrn->vtSema = TRUE; 7742 7743 /* Program the registers */ 7744 SiSVGAProtect(pScrn, TRUE); 7745 sisReg = &pSiS->ModeReg; 7746 7747 sisReg->sisRegsATTR[0x10] = 0x01; 7748 if(pScrn->bitsPerPixel > 8) { 7749 sisReg->sisRegsGR[0x05] = 0x00; 7750 } 7751 7752 SiSVGARestore(pScrn, sisReg, SISVGA_SR_MODE); 7753 7754 (*pSiS->SiSRestore)(pScrn, sisReg); 7755 7756 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 7757 SiS6326PostSetMode(pScrn, &pSiS->ModeReg); 7758 } 7759 7760#ifdef TWDEBUG 7761 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 7762 "REAL REGISTER CONTENTS AFTER SETMODE:\n"); 7763 (*pSiS->ModeInit)(pScrn, mode); 7764#endif 7765 7766 SiSVGAProtect(pScrn, FALSE); 7767 7768 } 7769 7770#ifdef SISDUALHEAD 7771 } 7772#endif 7773 } 7774 7775 /* Update Currentlayout */ 7776 pSiS->CurrentLayout.mode = pSiS->currentModeLast = mode; 7777 7778 return TRUE; 7779} 7780 7781static Bool 7782SiSSetVESAMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) 7783{ 7784 SISPtr pSiS; 7785 int mode; 7786 7787 pSiS = SISPTR(pScrn); 7788 7789 if(!(mode = SiSCalcVESAModeIndex(pScrn, pMode))) return FALSE; 7790 7791 mode |= (1 << 15); /* Don't clear framebuffer */ 7792 mode |= (1 << 14); /* Use linear adressing */ 7793 7794 if(VBESetVBEMode(pSiS->pVbe, mode, NULL) == FALSE) { 7795 SISErrorLog(pScrn, "Setting VESA mode 0x%x failed\n", 7796 mode & 0x0fff); 7797 return (FALSE); 7798 } 7799 7800 if(pMode->HDisplay != pScrn->virtualX) { 7801 VBESetLogicalScanline(pSiS->pVbe, pScrn->virtualX); 7802 } 7803 7804 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 7805 "Setting VESA mode 0x%x succeeded\n", 7806 mode & 0x0fff); 7807 7808 return (TRUE); 7809} 7810 7811static void 7812SISSpecialRestore(ScrnInfoPtr pScrn) 7813{ 7814 SISPtr pSiS = SISPTR(pScrn); 7815 SISRegPtr sisReg = &pSiS->SavedReg; 7816 UChar temp; 7817 int i; 7818 7819 /* 1.11.04 and later for 651 and 301B(DH) do strange register 7820 * fiddling after the usual mode change. This happens 7821 * depending on the result of a call of int 2f (with 7822 * ax=0x1680) and if modeno <= 0x13. I have no idea if 7823 * that is specific for the 651 or that very machine. 7824 * So this perhaps requires some more checks in the beginning 7825 * (although it should not do any harm on other chipsets/bridges 7826 * etc.) However, even if I call the VBE to restore mode 0x03, 7827 * these registers don't get restored correctly, possibly 7828 * because that int-2f-call for some reason results non-zero. So 7829 * what I do here is to restore these few registers 7830 * manually. 7831 */ 7832 7833 if(!(pSiS->ChipFlags & SiSCF_Is65x)) return; 7834 inSISIDXREG(SISCR, 0x34, temp); 7835 temp &= 0x7f; 7836 if(temp > 0x13) return; 7837 7838#ifdef UNLOCK_ALWAYS 7839 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7840#endif 7841 7842 SiS_UnLockCRT2(pSiS->SiS_Pr); 7843 7844 outSISIDXREG(SISCAP, 0x3f, sisReg->sisCapt[0x3f]); 7845 outSISIDXREG(SISCAP, 0x00, sisReg->sisCapt[0x00]); 7846 for(i = 0; i < 0x4f; i++) { 7847 outSISIDXREG(SISCAP, i, sisReg->sisCapt[i]); 7848 } 7849 outSISIDXREG(SISVID, 0x32, (sisReg->sisVid[0x32] & ~0x05)); 7850 outSISIDXREG(SISVID, 0x30, sisReg->sisVid[0x30]); 7851 outSISIDXREG(SISVID, 0x32, ((sisReg->sisVid[0x32] & ~0x04) | 0x01)); 7852 outSISIDXREG(SISVID, 0x30, sisReg->sisVid[0x30]); 7853 7854 if(!(pSiS->ChipFlags & SiSCF_Is651)) return; 7855 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 7856 7857 inSISIDXREG(SISCR, 0x30, temp); 7858 if(temp & 0x40) { 7859 UChar myregs[] = { 7860 0x2f, 0x08, 0x09, 0x03, 0x0a, 0x0c, 7861 0x0b, 0x0d, 0x0e, 0x12, 0x0f, 0x10, 7862 0x11, 0x04, 0x05, 0x06, 0x07, 0x00, 7863 0x2e 7864 }; 7865 for(i = 0; i <= 18; i++) { 7866 outSISIDXREG(SISPART1, myregs[i], sisReg->VBPart1[myregs[i]]); 7867 } 7868 } else if((temp & 0x20) || (temp & 0x9c)) { 7869 UChar myregs[] = { 7870 0x04, 0x05, 0x06, 0x07, 0x00, 0x2e 7871 }; 7872 for(i = 0; i <= 5; i++) { 7873 outSISIDXREG(SISPART1, myregs[i], sisReg->VBPart1[myregs[i]]); 7874 } 7875 } 7876} 7877 7878/* Fix SR11 for 661 and later */ 7879static void 7880SiSFixupSR11(ScrnInfoPtr pScrn) 7881{ 7882 SISPtr pSiS = SISPTR(pScrn); 7883 CARD8 tmpreg; 7884 7885#ifdef UNLOCK_ALWAYS 7886 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7887#endif 7888 7889 if(pSiS->ChipType >= SIS_661) { 7890 inSISIDXREG(SISSR,0x11,tmpreg); 7891 if(tmpreg & 0x20) { 7892 inSISIDXREG(SISSR,0x3e,tmpreg); 7893 tmpreg = (tmpreg + 1) & 0xff; 7894 outSISIDXREG(SISSR,0x3e,tmpreg); 7895 } 7896 7897 inSISIDXREG(SISSR,0x11,tmpreg); 7898 if(tmpreg & 0xf0) { 7899 andSISIDXREG(SISSR,0x11,0x0f); 7900 } 7901 } 7902} 7903 7904/* Subroutine for restoring sisfb's TV parameters (used by SiSRestore()) */ 7905 7906static void 7907SiSRestore_SiSFB_TVParms(ScrnInfoPtr pScrn) 7908{ 7909 SISPtr pSiS = SISPTR(pScrn); 7910 int fd; 7911 CARD32 parm; 7912 7913 if(!pSiS->sisfbfound) return; 7914 if(!pSiS->sisfb_tvposvalid) return; 7915 if(!(pSiS->sisfbdevname[0])) return; 7916 7917 if((fd = open(pSiS->sisfbdevname, O_RDONLY)) != -1) { 7918 parm = (CARD32)((pSiS->sisfb_tvxpos << 16) | (pSiS->sisfb_tvypos & 0xffff)); 7919 ioctl(fd, SISFB_SET_TVPOSOFFSET, &parm); 7920 close(fd); 7921 } 7922} 7923 7924/* 7925 * Restore the initial mode. To be used internally only! 7926 */ 7927static void 7928SISRestore(ScrnInfoPtr pScrn) 7929{ 7930 SISPtr pSiS = SISPTR(pScrn); 7931 SISRegPtr sisReg = &pSiS->SavedReg; 7932 Bool doit = FALSE, doitlater = FALSE; 7933 Bool vesasuccess = FALSE; 7934 int flags; 7935 7936 /* WARNING: Don't ever touch this. It now seems to work on 7937 * all chipset/bridge combinations - but finding out the 7938 * correct combination was pure hell. 7939 */ 7940 7941 /* Wait for the accelerators */ 7942 (*pSiS->SyncAccel)(pScrn); 7943 7944 /* Set up restore flags */ 7945 flags = SISVGA_SR_MODE | SISVGA_SR_CMAP; 7946#ifdef SIS_PC_PLATFORM 7947 /* We now restore ALL to overcome the vga=extended problem */ 7948 if(pSiS->VGAMemBase) flags |= SISVGA_SR_FONTS; 7949#endif 7950 7951 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 7952 7953#ifdef SISDUALHEAD 7954 /* We always restore master AND slave */ 7955 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 7956#endif 7957 7958#ifdef UNLOCK_ALWAYS 7959 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 7960#endif 7961 7962 /* We must not disable the sequencer if the bridge is in SlaveMode! */ 7963 if(!(SiSBridgeIsInSlaveMode(pScrn))) { 7964 SiSVGAProtect(pScrn, TRUE); 7965 } 7966 7967 /* First, restore CRT1 on/off and VB connection registers */ 7968 outSISIDXREG(SISCR, 0x32, pSiS->oldCR32); 7969 if(!(pSiS->oldCR17 & 0x80)) { /* CRT1 was off */ 7970 if(!(SiSBridgeIsInSlaveMode(pScrn))) { /* Bridge is NOT in SlaveMode now -> do it */ 7971 doit = TRUE; 7972 } else { 7973 doitlater = TRUE; 7974 } 7975 } else { /* CRT1 was on -> do it now */ 7976 doit = TRUE; 7977 } 7978 7979 if(doit) { 7980 outSISIDXREG(SISCR, 0x17, pSiS->oldCR17); 7981 } 7982 if(pSiS->VGAEngine == SIS_315_VGA) { 7983 outSISIDXREG(SISCR, pSiS->myCR63, pSiS->oldCR63); 7984 } 7985 7986 outSISIDXREG(SISSR, 0x1f, pSiS->oldSR1F); 7987 7988 /* For 30xB/LV, restoring the registers does not 7989 * work. We "manually" set the old mode, instead. 7990 * The same applies for SiS730 machines with LVDS. 7991 * Finally, this behavior can be forced by setting 7992 * the option RestoreBySetMode. 7993 */ 7994 if( ( (pSiS->restorebyset) || 7995 (pSiS->VBFlags2 & VB2_30xBLV) || 7996 ((pSiS->ChipType == SIS_730) && (pSiS->VBFlags2 & VB2_LVDS)) ) && 7997 (pSiS->OldMode) ) { 7998 7999 Bool changedmode = FALSE; 8000 8001 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 8002 "Restoring by setting old mode 0x%02x\n", pSiS->OldMode); 8003 8004 if(((pSiS->OldMode <= 0x13) || (!pSiS->sisfbfound)) && (pSiS->pVbe)) { 8005 int vmode = SiSTranslateToVESA(pScrn, pSiS->OldMode); 8006 if(vmode > 0) { 8007 if(vmode > 0x13) vmode |= ((1 << 15) | (1 << 14)); 8008 if(VBESetVBEMode(pSiS->pVbe, vmode, NULL) == TRUE) { 8009 SISSpecialRestore(pScrn); 8010 SiS_GetSetModeID(pScrn,pSiS->OldMode); 8011 vesasuccess = TRUE; 8012 } else { 8013 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 8014 "VBE failed to restore mode 0x%x\n", pSiS->OldMode); 8015 } 8016 } else { 8017 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 8018 "Can't identify VESA mode number for mode 0x%x\n", pSiS->OldMode); 8019 } 8020 } 8021 8022 if(vesasuccess == FALSE) { 8023 8024 int backupscaler = pSiS->SiS_Pr->UsePanelScaler; 8025 int backupcenter = pSiS->SiS_Pr->CenterScreen; 8026 ULong backupspecialtiming = pSiS->SiS_Pr->SiS_CustomT; 8027 int mymode = pSiS->OldMode; 8028 8029 if((pSiS->VGAEngine == SIS_315_VGA) && 8030 ((pSiS->ROM661New) || (pSiS->ChipFlags & SiSCF_IsXGI)) && 8031 (!pSiS->sisfbfound)) { 8032 /* New SiS BIOS or XGI BIOS has set mode, therefore eventually translate number */ 8033 mymode = SiSTranslateToOldMode(mymode); 8034 } 8035 8036 if((pSiS->VBFlags2 & VB2_30xBLV)) { 8037 /* !!! REQUIRED for 630+301B-DH, otherwise the text modes 8038 * will not be restored correctly !!! 8039 * !!! Do this ONLY for LCD; VGA2 will not be restored 8040 * correctly otherwise. 8041 */ 8042 UChar temp; 8043 inSISIDXREG(SISCR, 0x30, temp); 8044 if(temp & 0x20) { 8045 if(mymode == 0x03) { 8046 mymode = 0x13; 8047 changedmode = TRUE; 8048 } 8049 } 8050 } 8051 8052 pSiS->SiS_Pr->UseCustomMode = FALSE; 8053 pSiS->SiS_Pr->CRT1UsesCustomMode = FALSE; 8054 pSiS->SiS_Pr->CenterScreen = 0; 8055 if(pSiS->sisfbfound) { 8056 pSiS->SiS_Pr->UsePanelScaler = pSiS->sisfbscalelcd; 8057 pSiS->SiS_Pr->SiS_CustomT = pSiS->sisfbspecialtiming; 8058 } else { 8059 pSiS->SiS_Pr->UsePanelScaler = -1; 8060 /* Leave CustomT as it is */ 8061 } 8062 SiS_SetEnableDstn(pSiS->SiS_Pr, FALSE); 8063 SiS_SetEnableFstn(pSiS->SiS_Pr, FALSE); 8064 if((pSiS->ChipType == SIS_550) && (pSiS->sisfbfound)) { 8065 if(pSiS->sisfbxSTN) { 8066 SiS_SetEnableDstn(pSiS->SiS_Pr, pSiS->sisfbDSTN); 8067 SiS_SetEnableFstn(pSiS->SiS_Pr, pSiS->sisfbFSTN); 8068 } else if(mymode == 0x5a || mymode == 0x5b) { 8069 SiS_SetEnableFstn(pSiS->SiS_Pr, TRUE); 8070 } 8071 } 8072 SiSSetMode(pSiS->SiS_Pr, pScrn, mymode, FALSE); 8073 if(changedmode) { 8074 outSISIDXREG(SISCR,0x34,0x03); 8075 } 8076 SISSpecialRestore(pScrn); 8077 SiS_GetSetModeID(pScrn, pSiS->OldMode); /* NOT mymode! */ 8078 pSiS->SiS_Pr->UsePanelScaler = backupscaler; 8079 pSiS->SiS_Pr->CenterScreen = backupcenter; 8080 pSiS->SiS_Pr->SiS_CustomT = backupspecialtiming; 8081 SiS_SiSFB_Lock(pScrn, FALSE); 8082 SiSRestore_SiSFB_TVParms(pScrn); 8083 SiS_SiSFB_Lock(pScrn, TRUE); 8084 8085 } 8086 8087 /* Restore CRT1 status */ 8088 if(pSiS->VGAEngine == SIS_315_VGA) { 8089 outSISIDXREG(SISCR, pSiS->myCR63, pSiS->oldCR63); 8090 } 8091 outSISIDXREG(SISSR, 0x1f, pSiS->oldSR1F); 8092 8093#ifdef SISVRAMQ 8094 /* Restore queue mode registers on 315/330/340 series */ 8095 /* (This became necessary due to the switch to VRAM queue) */ 8096 SiSRestoreQueueMode(pSiS, sisReg); 8097#endif 8098 8099 } else { 8100 8101 if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 8102 /* If a video bridge is present, we need to restore 8103 * non-extended (=standard VGA) SR and CR registers 8104 * before restoring the extended ones and the bridge 8105 * registers. 8106 */ 8107 if(!(SiSBridgeIsInSlaveMode(pScrn))) { 8108 SiSVGAProtect(pScrn, TRUE); 8109 SiSVGARestore(pScrn, sisReg, SISVGA_SR_MODE); 8110 } 8111 } 8112 8113 (*pSiS->SiSRestore)(pScrn, sisReg); 8114 8115 } 8116 8117 if(doitlater) { 8118 outSISIDXREG(SISCR, 0x17, pSiS->oldCR17); 8119 } 8120 8121 8122 8123 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (SiSBridgeIsInSlaveMode(pScrn))) { 8124 8125 /* IMPORTANT: The 30xLV does not handle well being disabled if in 8126 * LCDA mode! In LCDA mode, the bridge is NOT in slave mode, 8127 * so this is the only safe way: Disable the bridge ONLY if 8128 * in Slave Mode, and don't bother if not. 8129 */ 8130 8131 if(flags & SISVGA_SR_FONTS) { 8132 SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO+0x30); 8133 SiSSetLVDSetc(pSiS->SiS_Pr); 8134 SiS_GetVBType(pSiS->SiS_Pr); 8135 SiS_DisableBridge(pSiS->SiS_Pr); 8136 SiSVGAProtect(pScrn, TRUE); 8137 } 8138 8139 SiSVGARestore(pScrn, sisReg, flags); 8140 8141 if(flags & SISVGA_SR_FONTS) { 8142 SiSVGAProtect(pScrn, FALSE); 8143 SiS_EnableBridge(pSiS->SiS_Pr); 8144 andSISIDXREG(SISSR, 0x01, ~0x20); /* Display on */ 8145 } 8146 8147 } else { 8148 8149 SiSVGAProtect(pScrn, TRUE); 8150 SiSVGARestore(pScrn, sisReg, flags); 8151 SiSVGAProtect(pScrn, FALSE); 8152 8153 } 8154 8155 SiSFixupSR11(pScrn); 8156 8157#ifdef TWDEBUG 8158 { 8159 SISRegPtr pReg = &pSiS->ModeReg; 8160 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8161 "REAL REGISTER CONTENTS AFTER RESTORE BY SETMODE:\n"); 8162 (*pSiS->SiSSave)(pScrn, pReg); 8163 } 8164#endif 8165 8166 sisRestoreExtRegisterLock(pSiS,sisReg->sisRegs3C4[0x05],sisReg->sisRegs3D4[0x80]); 8167 8168 } else { /* All other chipsets */ 8169 8170 SiSVGAProtect(pScrn, TRUE); 8171 8172#ifdef UNLOCK_ALWAYS 8173 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8174#endif 8175 8176 (*pSiS->SiSRestore)(pScrn, sisReg); 8177 8178 SiSVGAProtect(pScrn, TRUE); 8179 8180 SiSVGARestore(pScrn, sisReg, flags); 8181 8182 /* Restore TV. This is rather complicated, but if we don't do it, 8183 * TV output will flicker terribly 8184 */ 8185 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 8186 if(sisReg->sis6326tv[0] & 0x04) { 8187 UChar tmp; 8188 int val; 8189 8190 orSISIDXREG(SISSR, 0x01, 0x20); 8191 tmp = SiS6326GetTVReg(pScrn,0x00); 8192 tmp &= ~0x04; 8193 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 8194 SiS6326SetTVReg(pScrn,0x00,tmp); 8195 for(val=0; val < 2; val++) { 8196 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 8197 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 8198 } 8199 SiS6326SetTVReg(pScrn, 0x00, sisReg->sis6326tv[0]); 8200 tmp = inSISREG(SISINPSTAT); 8201 outSISREG(SISAR, 0x20); 8202 tmp = inSISREG(SISINPSTAT); 8203 while(inSISREG(SISINPSTAT) & 0x01); 8204 while(!(inSISREG(SISINPSTAT) & 0x01)); 8205 andSISIDXREG(SISSR, 0x01, ~0x20); 8206 for(val=0; val < 10; val++) { 8207 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 8208 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 8209 } 8210 andSISIDXREG(SISSR, 0x01, ~0x20); 8211 } 8212 } 8213 8214 sisRestoreExtRegisterLock(pSiS,sisReg->sisRegs3C4[5],sisReg->sisRegs3D4[0x80]); 8215 8216 SiSVGAProtect(pScrn, FALSE); 8217 } 8218} 8219 8220static void 8221SISVESARestore(ScrnInfoPtr pScrn) 8222{ 8223 SISPtr pSiS = SISPTR(pScrn); 8224#ifdef SISVRAMQ 8225 SISRegPtr sisReg = &pSiS->SavedReg; 8226#endif 8227 8228 if(pSiS->UseVESA) { 8229 SISVESASaveRestore(pScrn, MODE_RESTORE); 8230#ifdef SISVRAMQ 8231 /* Restore queue mode registers on 315/330/340 series */ 8232 /* (This became necessary due to the switch to VRAM queue) */ 8233 SiSRestoreQueueMode(pSiS, sisReg); 8234#endif 8235 } 8236} 8237 8238/* Restore bridge config registers - to be called BEFORE VESARestore */ 8239static void 8240SISBridgeRestore(ScrnInfoPtr pScrn) 8241{ 8242 SISPtr pSiS = SISPTR(pScrn); 8243 8244#ifdef SISDUALHEAD 8245 /* We only restore for master head */ 8246 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 8247#endif 8248 8249 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 8250 SiSRestoreBridge(pScrn, &pSiS->SavedReg); 8251 } 8252} 8253 8254/* Our BlockHandler */ 8255static void 8256SISBlockHandler(BLOCKHANDLER_ARGS_DECL) 8257{ 8258 SCREEN_PTR(arg); 8259 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 8260 SISPtr pSiS = SISPTR(pScrn); 8261 8262 pScreen->BlockHandler = pSiS->BlockHandler; 8263 (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS); 8264 pScreen->BlockHandler = SISBlockHandler; 8265 8266#ifdef SISDUALHEAD 8267 if(pSiS->NeedCopyFastVidCpy) { 8268 SISEntPtr pSiSEnt = pSiS->entityPrivate; 8269 if(pSiSEnt->HaveFastVidCpy) { 8270 pSiS->NeedCopyFastVidCpy = FALSE; 8271 pSiS->SiSFastVidCopy = pSiSEnt->SiSFastVidCopy; 8272 pSiS->SiSFastMemCopy = pSiSEnt->SiSFastMemCopy; 8273 pSiS->SiSFastVidCopyFrom = pSiSEnt->SiSFastVidCopyFrom; 8274 pSiS->SiSFastMemCopyFrom = pSiSEnt->SiSFastMemCopyFrom; 8275 } 8276 } 8277#endif 8278 8279 if(pSiS->VideoTimerCallback) { 8280 (*pSiS->VideoTimerCallback)(pScrn, currentTime.milliseconds); 8281 } 8282 8283#ifdef SIS_USE_XAA 8284 if(pSiS->RenderCallback) { 8285 (*pSiS->RenderCallback)(pScrn); 8286 } 8287#endif 8288#ifdef SIS_USE_EXA 8289 if(pSiS->ExaRenderCallback) { 8290 (*pSiS->ExaRenderCallback)(pScrn); 8291 } 8292#endif 8293} 8294 8295 8296 8297/* Do screen blanking; DPMS handling 8298 * 8299 * Mandatory; latter optional 8300 */ 8301 8302static void 8303SiSHandleBackLight(SISPtr pSiS, Bool blon) 8304{ 8305 UChar sr11mask = (pSiS->SiS_Pr->SiS_SensibleSR11) ? 0x03 : 0xf3; 8306 8307 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) { 8308 8309 if(!blon) { 8310 SiS_SiS30xBLOff(pSiS->SiS_Pr); 8311 } else { 8312 SiS_SiS30xBLOn(pSiS->SiS_Pr); 8313 } 8314 8315 } else if( ((pSiS->VGAEngine == SIS_300_VGA) && 8316 (pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH))) || 8317 ((pSiS->VGAEngine == SIS_315_VGA) && 8318 ((pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS)) ) { 8319 8320 if(!blon) { 8321 setSISIDXREG(SISSR, 0x11, sr11mask, 0x08); 8322 } else { 8323 setSISIDXREG(SISSR, 0x11, sr11mask, 0x00); 8324 } 8325 8326 } else if((pSiS->VGAEngine == SIS_315_VGA) && 8327 (pSiS->VBFlags2 & VB2_CHRONTEL)) { 8328 8329 if(!blon) { 8330 SiS_Chrontel701xBLOff(pSiS->SiS_Pr); 8331 } else { 8332 SiS_Chrontel701xBLOn(pSiS->SiS_Pr); 8333 } 8334 8335 } 8336} 8337 8338static Bool 8339SISSaveScreen(ScreenPtr pScreen, int mode) 8340{ 8341 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 8342 SISPtr pSiS; 8343 Bool IsUnblank = xf86IsUnblank(mode) ? TRUE : FALSE; 8344 8345 if((pScrn == NULL) || (!pScrn->vtSema)) return TRUE; 8346 8347 pSiS = SISPTR(pScrn); 8348 8349#ifdef UNLOCK_ALWAYS 8350 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8351#endif 8352 8353 if(pSiS->VBFlags & (CRT2_LCD | CRT1_LCDA)) { 8354 SiSHandleBackLight(pSiS, IsUnblank); 8355 } 8356 8357 if(!SiSBridgeIsInSlaveMode(pScrn)) { 8358 return SiSVGASaveScreen(pScreen, mode); 8359 } 8360 8361 return TRUE; 8362} 8363 8364#ifdef SISDUALHEAD 8365/* SaveScreen for dual head mode */ 8366static Bool 8367SISSaveScreenDH(ScreenPtr pScreen, int mode) 8368{ 8369 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 8370 SISPtr pSiS; 8371 Bool IsUnblank = xf86IsUnblank(mode) ? TRUE : FALSE; 8372 8373 if((pScrn == NULL) || (!pScrn->vtSema)) return TRUE; 8374 8375 pSiS = SISPTR(pScrn); 8376 8377 if( (pSiS->SecondHead) && 8378 ((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) ) { 8379 8380 /* Slave head is always CRT1 */ 8381 /* (No backlight handling on TMDS bridges) */ 8382 return SiSVGASaveScreen(pScreen, mode); 8383 8384 } else { 8385 8386 /* Master head is always CRT2 */ 8387 /* But we land here for LCDA, too (if bridge is SiS LVDS type) */ 8388 8389 /* We can only blank LCD, not other CRT2 devices */ 8390 if(pSiS->VBFlags & (CRT2_LCD|CRT1_LCDA)) { 8391 8392#ifdef UNLOCK_ALWAYS 8393 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8394#endif 8395 SiSHandleBackLight(pSiS, IsUnblank); 8396 8397 } 8398 8399 } 8400 return TRUE; 8401} 8402#endif 8403 8404static void 8405SISDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags) 8406{ 8407 SISPtr pSiS = SISPTR(pScrn); 8408 Bool docrt1 = TRUE, docrt2 = TRUE, backlight = TRUE; 8409 UChar sr1=0, cr17=0, cr63=0, pmreg=0, sr7=0; 8410 UChar p1_13=0, p2_0=0, oldpmreg=0; 8411 8412 if(!pScrn->vtSema) return; 8413 8414 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, 8415 "SISDisplayPowerManagementSet(%d)\n", PowerManagementMode); 8416 8417#ifdef SISDUALHEAD 8418 if(pSiS->DualHeadMode) { 8419 if(pSiS->SecondHead) docrt2 = FALSE; 8420 else docrt1 = FALSE; 8421 } 8422#endif 8423 8424 /* FIXME: in old servers, DPMSSet was supposed to be called without open 8425 * the correct PCI bridges before access the hardware. Now we have this 8426 * hook wrapped by the vga arbiter which should do all the work, in 8427 * kernels that implement it. For this case we might not want this hack 8428 * bellow. 8429 */ 8430 outSISIDXREG(SISSR,0x05,0x86); 8431 inSISIDXREG(SISSR,0x05,pmreg); 8432 if(pmreg != 0xa1) return; 8433 8434#ifdef UNLOCK_ALWAYS 8435 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8436#endif 8437 8438 switch(PowerManagementMode) { 8439 8440 case DPMSModeOn: /* HSync: On, VSync: On */ 8441 sr1 = 0x00; 8442 cr17 = 0x80; 8443 pmreg = 0x00; 8444 cr63 = 0x00; 8445 sr7 = 0x10; 8446 p2_0 = 0x20; 8447 p1_13 = 0x00; 8448 backlight = TRUE; 8449 break; 8450 8451 case DPMSModeSuspend: /* HSync: On, VSync: Off */ 8452 sr1 = 0x20; 8453 cr17 = 0x80; 8454 pmreg = 0x80; 8455 cr63 = 0x40; 8456 sr7 = 0x00; 8457 p2_0 = 0x40; 8458 p1_13 = 0x80; 8459 backlight = FALSE; 8460 break; 8461 8462 case DPMSModeStandby: /* HSync: Off, VSync: On */ 8463 sr1 = 0x20; 8464 cr17 = 0x80; 8465 pmreg = 0x40; 8466 cr63 = 0x40; 8467 sr7 = 0x00; 8468 p2_0 = 0x80; 8469 p1_13 = 0x40; 8470 backlight = FALSE; 8471 break; 8472 8473 case DPMSModeOff: /* HSync: Off, VSync: Off */ 8474 sr1 = 0x20; 8475 cr17 = 0x00; 8476 pmreg = 0xc0; 8477 cr63 = 0x40; 8478 sr7 = 0x00; 8479 p2_0 = 0xc0; 8480 p1_13 = 0xc0; 8481 backlight = FALSE; 8482 break; 8483 8484 default: 8485 return; 8486 } 8487 8488 oldpmreg = pmreg; 8489 8490 if((docrt2 && (pSiS->VBFlags & CRT2_LCD)) || 8491 (docrt1 && (pSiS->VBFlags & CRT1_LCDA))) { 8492 SiSHandleBackLight(pSiS, backlight); 8493 } 8494 8495 if(docrt1) { 8496 switch(pSiS->VGAEngine) { 8497 case SIS_OLD_VGA: 8498 case SIS_530_VGA: 8499 setSISIDXREG(SISSR, 0x01, ~0x20, sr1); /* Set/Clear "Display On" bit */ 8500 inSISIDXREG(SISSR, 0x11, oldpmreg); 8501 setSISIDXREG(SISCR, 0x17, 0x7f, cr17); 8502 setSISIDXREG(SISSR, 0x11, 0x3f, pmreg); 8503 break; 8504 case SIS_315_VGA: 8505 if( (!pSiS->CRT1off) && 8506 ((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) ) { 8507 setSISIDXREG(SISCR, pSiS->myCR63, 0xbf, cr63); 8508 setSISIDXREG(SISSR, 0x07, 0xef, sr7); 8509 } 8510 /* fall through */ 8511 default: 8512 if(!SiSBridgeIsInSlaveMode(pScrn)) { 8513 setSISIDXREG(SISSR, 0x01, ~0x20, sr1); /* Set/Clear "Display On" bit */ 8514 } 8515 if((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 8516 inSISIDXREG(SISSR, 0x1f, oldpmreg); 8517 if((!pSiS->CRT1off) && (!SiSBridgeIsInSlaveMode(pScrn))) { 8518 setSISIDXREG(SISSR, 0x1f, 0x3f, pmreg); 8519 } 8520 } 8521 } 8522 oldpmreg &= 0xc0; 8523 } 8524 8525 if(docrt2) { 8526 if(pSiS->VBFlags & CRT2_LCD) { 8527 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && 8528 (!(pSiS->VBFlags2 & VB2_30xBDH))) { 8529 if(pSiS->VGAEngine == SIS_300_VGA) { 8530 SiS_UnLockCRT2(pSiS->SiS_Pr); 8531 setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13); 8532 } 8533 if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) p2_0 |= 0x20; 8534 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); 8535 } 8536 } else if(pSiS->VBFlags & (CRT2_VGA | CRT2_TV)) { 8537 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 8538 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); 8539 } 8540 } 8541 } 8542 8543 if( (docrt1) && 8544 (pmreg != oldpmreg) && 8545 ((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) ) { 8546 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 8547 usleep(10000); 8548 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 8549 } 8550 8551} 8552 8553/* Mandatory 8554 * This gets called at the start of each server generation 8555 * 8556 * We use pScrn and not CurrentLayout here, because the 8557 * properties we use have not changed (displayWidth, 8558 * depth, bitsPerPixel) 8559 */ 8560static Bool 8561SISScreenInit(SCREEN_INIT_ARGS_DECL) 8562{ 8563 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 8564 SISPtr pSiS = SISPTR(pScrn); 8565 VisualPtr visual; 8566 ULong OnScreenSize; 8567 int ret, height, width, displayWidth; 8568 UChar *FBStart; 8569#ifdef SISDUALHEAD 8570 SISEntPtr pSiSEnt = NULL; 8571#endif 8572 8573#ifdef SISDUALHEAD 8574 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) { 8575#endif 8576 SiS_LoadInitVBE(pScrn); 8577#ifdef SISDUALHEAD 8578 } 8579#endif 8580 8581#ifdef SISDUALHEAD 8582 if(pSiS->DualHeadMode) { 8583 pSiSEnt = pSiS->entityPrivate; 8584 pSiSEnt->refCount++; 8585 } 8586#endif 8587 8588#ifdef SIS_PC_PLATFORM 8589 /* Map 64k VGA window for saving/restoring CGA fonts */ 8590 SiS_MapVGAMem(pScrn); 8591#endif 8592 8593 /* Map the SiS memory and MMIO areas */ 8594 if(!SISMapMem(pScrn)) { 8595 SISErrorLog(pScrn, "SiSMapMem() failed\n"); 8596 return FALSE; 8597 } 8598 8599 SiS_SiSFB_Lock(pScrn, TRUE); 8600 8601#ifdef UNLOCK_ALWAYS 8602 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 8603#endif 8604 8605 /* Enable TurboQueue so that SISSave() saves it in enabled 8606 * state. If we don't do this, X will hang after a restart! 8607 * (Happens for some unknown reason only when using VESA 8608 * for mode switching; assumingly a BIOS issue.) 8609 * This is done on 300 and 315 series only. 8610 */ 8611 if(pSiS->UseVESA) { 8612#ifdef SISVRAMQ 8613 if(pSiS->VGAEngine != SIS_315_VGA) 8614#endif 8615 SiSEnableTurboQueue(pScrn); 8616 } 8617 8618 /* Save the current state */ 8619 SISSave(pScrn); 8620 8621 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 8622 8623 if(!pSiS->OldMode) { 8624 8625 /* Try to find out current (=old) mode number 8626 * (Do this only if not sisfb has told us its mode yet) 8627 */ 8628 8629 /* Read 0:449 which the BIOS sets to the current mode number 8630 * Unfortunately, this not reliable since the int10 emulation 8631 * does not change this. So if we call the VBE later, this 8632 * byte won't be touched (which is why we set this manually 8633 * then). 8634 */ 8635 UChar myoldmode = SiS_GetSetModeID(pScrn, 0xFF); 8636 UChar cr30, cr31; 8637 8638 /* Read CR34 which the BIOS sets to the current mode number for CRT2 8639 * This is - of course - not reliable if the machine has no video 8640 * bridge... 8641 */ 8642 inSISIDXREG(SISCR, 0x34, pSiS->OldMode); 8643 inSISIDXREG(SISCR, 0x30, cr30); 8644 inSISIDXREG(SISCR, 0x31, cr31); 8645 8646 /* What if CR34 is different from the BIOS scratch byte? */ 8647 if(pSiS->OldMode != myoldmode) { 8648 /* If no bridge output is active, trust the BIOS scratch byte */ 8649 if( (!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) || 8650 (pSiS->OldMode == 0) || 8651 (!cr31 && !cr30) || 8652 (cr31 & 0x20) ) { 8653 pSiS->OldMode = myoldmode; 8654 } 8655 /* ..else trust CR34 */ 8656 } 8657 8658 /* Newer 650 BIOSes set CR34 to 0xff if the mode has been 8659 * "patched", for instance for 80x50 text mode. (That mode 8660 * has no number of its own, it's 0x03 like 80x25). In this 8661 * case, we trust the BIOS scratch byte (provided that any 8662 * of these two is valid). 8663 */ 8664 if(pSiS->OldMode > 0x7f) { 8665 pSiS->OldMode = myoldmode; 8666 } 8667 } 8668#ifdef SISDUALHEAD 8669 if(pSiS->DualHeadMode) { 8670 if(!pSiS->SecondHead) pSiSEnt->OldMode = pSiS->OldMode; 8671 else pSiS->OldMode = pSiSEnt->OldMode; 8672 } 8673#endif 8674 } 8675 8676 /* RandR resets screen mode and size in CloseScreen(), hence 8677 * we need to adapt our VBFlags to the initial state if the 8678 * current mode has changed since closescreen() (or Screeninit() 8679 * for the first instance) 8680 */ 8681 if(pScrn->currentMode != pSiS->currentModeLast) { 8682 pSiS->VBFlags = pSiS->VBFlags_backup = pSiS->VBFlagsInit; 8683 } 8684 8685 /* Copy our detected monitor gammas, part 2. Note that device redetection 8686 * is not supported in DHM, so there is no need to do that anytime later. 8687 */ 8688#ifdef SISDUALHEAD 8689 if(pSiS->DualHeadMode) { 8690 if(!pSiS->SecondHead) { 8691 /* CRT2 */ 8692 pSiS->CRT1VGAMonitorGamma = pSiSEnt->CRT1VGAMonitorGamma; 8693 } else { 8694 /* CRT1 */ 8695 pSiS->CRT2VGAMonitorGamma = pSiSEnt->CRT2VGAMonitorGamma; 8696 } 8697 if(!pSiS->CRT2LCDMonitorGamma) pSiS->CRT2LCDMonitorGamma = pSiSEnt->CRT2LCDMonitorGamma; 8698 } 8699#endif 8700 8701 /* Initialize the first mode */ 8702 if(!SISModeInit(pScrn, pScrn->currentMode)) { 8703 SISErrorLog(pScrn, "SiSModeInit() failed\n"); 8704 return FALSE; 8705 } 8706 8707 /* Darken the screen for aesthetic reasons */ 8708 /* Not using Dual Head variant on purpose; we darken 8709 * the screen for both displays, and un-darken 8710 * it when the second head is finished 8711 */ 8712 SISSaveScreen(pScreen, SCREEN_SAVER_ON); 8713 8714 /* Set the viewport */ 8715 SISAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 8716 8717 /* Reset visual list. */ 8718 miClearVisualTypes(); 8719 8720 /* Setup the visuals we support. */ 8721 8722 /* 8723 * For bpp > 8, the default visuals are not acceptable because we only 8724 * support TrueColor and not DirectColor. 8725 */ 8726 if(!miSetVisualTypes(pScrn->depth, 8727 (pScrn->bitsPerPixel > 8) ? 8728 TrueColorMask : miGetDefaultVisualMask(pScrn->depth), 8729 pScrn->rgbBits, pScrn->defaultVisual)) { 8730 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8731 SISErrorLog(pScrn, "miSetVisualTypes() failed (bpp %d)\n", 8732 pScrn->bitsPerPixel); 8733 return FALSE; 8734 } 8735 8736 width = pScrn->virtualX; 8737 height = pScrn->virtualY; 8738 displayWidth = pScrn->displayWidth; 8739 8740 if(pSiS->Rotate) { 8741 height = pScrn->virtualX; 8742 width = pScrn->virtualY; 8743 } 8744 8745 if(pSiS->ShadowFB) { 8746 pSiS->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); 8747 pSiS->ShadowPtr = malloc(pSiS->ShadowPitch * height); 8748 displayWidth = pSiS->ShadowPitch / (pScrn->bitsPerPixel >> 3); 8749 FBStart = pSiS->ShadowPtr; 8750 } else { 8751 pSiS->ShadowPtr = NULL; 8752 FBStart = pSiS->FbBase; 8753 } 8754 8755 if(!miSetPixmapDepths()) { 8756 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8757 SISErrorLog(pScrn, "miSetPixmapDepths() failed\n"); 8758 return FALSE; 8759 } 8760 8761 /* Point cmdQueuePtr to pSiSEnt for shared usage 8762 * (same technique is then eventually used in DRIScreeninit) 8763 * For 315/330 series, this is done in EnableTurboQueue 8764 * which has already been called during ModeInit(). 8765 */ 8766#ifdef SISDUALHEAD 8767 if(pSiS->SecondHead) 8768 pSiS->cmdQueueLenPtr = &(SISPTR(pSiSEnt->pScrn_1)->cmdQueueLen); 8769 else 8770#endif 8771 pSiS->cmdQueueLenPtr = &(pSiS->cmdQueueLen); 8772 8773 pSiS->cmdQueueLen = 0; /* Force an EngineIdle() at start */ 8774 8775#ifdef SISDRI 8776 if(pSiS->loadDRI) { 8777#ifdef SISDUALHEAD 8778 /* No DRI in dual head mode */ 8779 if(pSiS->DualHeadMode) { 8780 pSiS->directRenderingEnabled = FALSE; 8781 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8782 "DRI not supported in Dual Head mode\n"); 8783 } else 8784#endif 8785 if(pSiS->VGAEngine != SIS_315_VGA) { 8786 /* Force the initialization of the context */ 8787 pSiS->directRenderingEnabled = SISDRIScreenInit(pScreen); 8788 } else { 8789 xf86DrvMsg(pScrn->scrnIndex, X_NOT_IMPLEMENTED, 8790 "DRI not supported on this chipset\n"); 8791 pSiS->directRenderingEnabled = FALSE; 8792 } 8793 } 8794#endif 8795 8796 /* Call the framebuffer layer's ScreenInit function and fill in other 8797 * pScreen fields. 8798 */ 8799 switch(pScrn->bitsPerPixel) { 8800 case 24: 8801 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 8802 ret = FALSE; 8803 break; 8804 } 8805 /* fall through */ 8806 case 8: 8807 case 16: 8808 case 32: 8809 ret = fbScreenInit(pScreen, FBStart, width, 8810 height, pScrn->xDpi, pScrn->yDpi, 8811 displayWidth, pScrn->bitsPerPixel); 8812 break; 8813 default: 8814 ret = FALSE; 8815 break; 8816 } 8817 if(!ret) { 8818 SISErrorLog(pScrn, "Unsupported bpp (%d) or fbScreenInit() failed\n", 8819 pScrn->bitsPerPixel); 8820 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8821 return FALSE; 8822 } 8823 8824 /* Fixup RGB ordering */ 8825 if(pScrn->bitsPerPixel > 8) { 8826 visual = pScreen->visuals + pScreen->numVisuals; 8827 while (--visual >= pScreen->visuals) { 8828 if((visual->class | DynamicClass) == DirectColor) { 8829 visual->offsetRed = pScrn->offset.red; 8830 visual->offsetGreen = pScrn->offset.green; 8831 visual->offsetBlue = pScrn->offset.blue; 8832 visual->redMask = pScrn->mask.red; 8833 visual->greenMask = pScrn->mask.green; 8834 visual->blueMask = pScrn->mask.blue; 8835 } 8836 } 8837 } 8838 8839 /* Initialize RENDER extension (must be after RGB ordering fixed) */ 8840 fbPictureInit(pScreen, 0, 0); 8841 8842 /* Hardware cursor needs to wrap this layer */ 8843 if(!pSiS->ShadowFB) SISDGAInit(pScreen); 8844 8845 xf86SetBlackWhitePixels(pScreen); 8846 8847 /* Initialize the accelerators */ 8848 switch(pSiS->VGAEngine) { 8849 case SIS_530_VGA: 8850 case SIS_300_VGA: 8851 SiS300AccelInit(pScreen); 8852 break; 8853 case SIS_315_VGA: 8854 SiS315AccelInit(pScreen); 8855 break; 8856 default: 8857 SiSAccelInit(pScreen); 8858 } 8859 8860#ifdef TWDEBUG 8861 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CPUFlags %x\n", pSiS->CPUFlags); 8862#endif 8863 8864 /* Benchmark memcpy() methods (needs FB manager initialized) */ 8865 /* Dual head: Do this AFTER the mode for CRT1 has been set */ 8866 pSiS->NeedCopyFastVidCpy = FALSE; 8867 if(!pSiS->SiSFastVidCopyDone) { 8868#ifdef SISDUALHEAD 8869 if(pSiS->DualHeadMode) { 8870 if(pSiS->SecondHead) { 8871 pSiSEnt->SiSFastVidCopy = SiSVidCopyInit(pScreen, &pSiSEnt->SiSFastMemCopy, FALSE); 8872 pSiSEnt->SiSFastVidCopyFrom = SiSVidCopyGetDefault(); 8873 pSiSEnt->SiSFastMemCopyFrom = SiSVidCopyGetDefault(); 8874#ifdef SIS_USE_EXA 8875 if(pSiS->useEXA) { 8876 pSiSEnt->SiSFastVidCopyFrom = SiSVidCopyInit(pScreen, &pSiSEnt->SiSFastMemCopyFrom, TRUE); 8877 } 8878#endif /* EXA */ 8879 pSiSEnt->HaveFastVidCpy = TRUE; 8880 pSiS->SiSFastVidCopy = pSiSEnt->SiSFastVidCopy; 8881 pSiS->SiSFastMemCopy = pSiSEnt->SiSFastMemCopy; 8882 pSiS->SiSFastVidCopyFrom = pSiSEnt->SiSFastVidCopyFrom; 8883 pSiS->SiSFastMemCopyFrom = pSiSEnt->SiSFastMemCopyFrom; 8884 } else { 8885 pSiS->NeedCopyFastVidCpy = TRUE; 8886 } 8887 } else { 8888#endif 8889 pSiS->SiSFastVidCopy = SiSVidCopyInit(pScreen, &pSiS->SiSFastMemCopy, FALSE); 8890 pSiS->SiSFastVidCopyFrom = SiSVidCopyGetDefault(); 8891 pSiS->SiSFastMemCopyFrom = SiSVidCopyGetDefault(); 8892#ifdef SIS_USE_EXA 8893 if(pSiS->useEXA) { 8894 pSiS->SiSFastVidCopyFrom = SiSVidCopyInit(pScreen, &pSiS->SiSFastMemCopyFrom, TRUE); 8895 } 8896#endif /* EXA */ 8897#ifdef SISDUALHEAD 8898 } 8899#endif 8900 } 8901 pSiS->SiSFastVidCopyDone = TRUE; 8902 8903 xf86SetBackingStore(pScreen); 8904 xf86SetSilkenMouse(pScreen); 8905 8906 /* Initialise cursor functions */ 8907 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 8908 8909 if(pSiS->HWCursor) { 8910 SiSHWCursorInit(pScreen); 8911 } 8912 8913#ifdef SISDUALHEAD 8914 if(!pSiS->DualHeadMode) { 8915#endif 8916 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && (pScrn->depth > 8)) { 8917 8918 pSiS->CRT2ColNum = 1 << pScrn->rgbBits; 8919 8920 if((pSiS->crt2gcolortable = malloc(pSiS->CRT2ColNum * 2 * sizeof(LOCO)))) { 8921 pSiS->crt2colors = &pSiS->crt2gcolortable[pSiS->CRT2ColNum]; 8922 if((pSiS->crt2cindices = malloc(256 * sizeof(int)))) { 8923 int i = pSiS->CRT2ColNum; 8924 SISCalculateGammaRampCRT2(pScrn); 8925 while(i--) pSiS->crt2cindices[i] = i; 8926 } else { 8927 free(pSiS->crt2gcolortable); 8928 pSiS->crt2gcolortable = NULL; 8929 pSiS->CRT2SepGamma = FALSE; 8930 } 8931 } else { 8932 pSiS->CRT2SepGamma = FALSE; 8933 } 8934 8935 if(!pSiS->crt2cindices) { 8936 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 8937 "Failed to allocate cmap for CRT2, separate gamma correction disabled\n"); 8938 } 8939 8940 } 8941#ifdef SISDUALHEAD 8942 } else pSiS->CRT2SepGamma = FALSE; 8943#endif 8944 8945 /* Initialise default colormap */ 8946 if(!miCreateDefColormap(pScreen)) { 8947 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8948 SISErrorLog(pScrn, "miCreateDefColormap() failed\n"); 8949 return FALSE; 8950 } 8951 8952 if(!xf86HandleColormaps(pScreen, 256, (pScrn->depth == 8) ? 8 : pScrn->rgbBits, 8953 SISLoadPalette, NULL, 8954 CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH)) { 8955 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 8956 SISErrorLog(pScrn, "xf86HandleColormaps() failed\n"); 8957 return FALSE; 8958 } 8959 8960 /* Recalculate our gamma ramp for brightness feature */ 8961#ifdef SISGAMMARAMP 8962 if((pSiS->GammaBriR != 1000) || 8963 (pSiS->GammaBriB != 1000) || 8964 (pSiS->GammaBriG != 1000) || 8965 (pSiS->NewGammaBriR != 0.0) || 8966 (pSiS->NewGammaBriG != 0.0) || 8967 (pSiS->NewGammaBriB != 0.0) || 8968 (pSiS->NewGammaConR != 0.0) || 8969 (pSiS->NewGammaConG != 0.0) || 8970 (pSiS->NewGammaConB != 0.0)) { 8971 SISCalculateGammaRamp(pScreen, pScrn); 8972 } 8973#endif 8974 8975 /* Initialize Shadow framebuffer and screen rotation/reflection */ 8976 if(pSiS->ShadowFB) { 8977 RefreshAreaFuncPtr refreshArea = SISRefreshArea; 8978 8979 if(pSiS->Rotate) { 8980 if(!pSiS->PointerMoved) pSiS->PointerMoved = pScrn->PointerMoved; 8981 pScrn->PointerMoved = SISPointerMoved; 8982 switch(pScrn->bitsPerPixel) { 8983 case 8: refreshArea = SISRefreshArea8; break; 8984 case 16: refreshArea = SISRefreshArea16; break; 8985 case 24: refreshArea = SISRefreshArea24; break; 8986 case 32: refreshArea = SISRefreshArea32; break; 8987 } 8988#if (XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0)) && (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 24) 8989 xf86DisableRandR(); 8990 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 8991 "Driver rotation enabled, disabling RandR\n"); 8992#endif 8993 } else if(pSiS->Reflect) { 8994 switch(pScrn->bitsPerPixel) { 8995 case 8: 8996 case 16: 8997 case 32: 8998 if(!pSiS->PointerMoved) pSiS->PointerMoved = pScrn->PointerMoved; 8999 pScrn->PointerMoved = SISPointerMovedReflect; 9000 refreshArea = SISRefreshAreaReflect; 9001#if (XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0)) && (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 24) 9002 xf86DisableRandR(); 9003 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9004 "Driver reflection enabled, disabling RandR\n"); 9005#endif 9006 break; 9007 default: 9008 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 9009 "Reflection not supported at this framebuffer depth\n"); 9010 } 9011 } 9012 9013 ShadowFBInit(pScreen, refreshArea); 9014 } 9015 9016 xf86DPMSInit(pScreen, (DPMSSetProcPtr)SISDisplayPowerManagementSet, 0); 9017 9018 /* Init memPhysBase and fbOffset in pScrn */ 9019 pScrn->memPhysBase = pSiS->FbAddress; 9020 pScrn->fbOffset = 0; 9021 9022 /* Initialize Xv */ 9023 pSiS->ResetXv = pSiS->ResetXvGamma = pSiS->ResetXvDisplay = NULL; 9024#if (XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,99,0,0)) || (defined(XvExtension)) 9025 if((!pSiS->NoXvideo) && (!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY))) { 9026 9027 if((pSiS->VGAEngine == SIS_300_VGA) || 9028 (pSiS->VGAEngine == SIS_315_VGA)) { 9029 9030 const char *using = "Using SiS300/315/330/340 series HW Xv"; 9031 9032#ifdef SISDUALHEAD 9033 if(pSiS->DualHeadMode) { 9034 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9035 "%s on CRT%d\n", using, (pSiS->SecondHead ? 1 : 2)); 9036 if(!pSiS->hasTwoOverlays) { 9037 if( (pSiS->XvOnCRT2 && pSiS->SecondHead) || 9038 (!pSiS->XvOnCRT2 && !pSiS->SecondHead) ) { 9039 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9040 "However, video overlay will by default only be visible on CRT%d\n", 9041 pSiS->XvOnCRT2 ? 2 : 1); 9042 } 9043 } 9044 } else { 9045#endif 9046 if(pSiS->hasTwoOverlays) { 9047 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s\n", using); 9048 } else { 9049 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s by default on CRT%d\n", 9050 using, (pSiS->XvOnCRT2 ? 2 : 1)); 9051 } 9052#ifdef SISDUALHEAD 9053 } 9054#endif 9055 9056 SISInitVideo(pScreen); 9057 9058 if(pSiS->blitadaptor) { 9059 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9060 "Default Xv adaptor is Video %s\n", 9061 pSiS->XvDefAdaptorBlit ? "Blitter" : "Overlay"); 9062 } 9063 9064 } else if(pSiS->Chipset == PCI_CHIP_SIS530 || 9065 pSiS->Chipset == PCI_CHIP_SIS6326 || 9066 pSiS->Chipset == PCI_CHIP_SIS5597) { 9067 9068 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9069 "Using SiS5597/5598/6326/530/620 HW Xv\n" ); 9070 9071 SIS6326InitVideo(pScreen); 9072 9073 } else { /* generic Xv */ 9074 9075 XF86VideoAdaptorPtr *ptr; 9076 int n = xf86XVListGenericAdaptors(pScrn, &ptr); 9077 9078 if(n) { 9079 xf86XVScreenInit(pScreen, ptr, n); 9080 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using generic Xv\n" ); 9081 } 9082 9083 } 9084 } 9085#endif 9086 9087#ifdef SISDRI 9088 if(pSiS->loadDRI) { 9089 if(pSiS->directRenderingEnabled) { 9090 /* Now that mi, drm and others have done their thing, 9091 * complete the DRI setup. 9092 */ 9093 pSiS->directRenderingEnabled = SISDRIFinishScreenInit(pScreen); 9094 } 9095 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering %s\n", 9096 pSiS->directRenderingEnabled ? "enabled" : "disabled"); 9097 /* TODO */ 9098 /* if(pSiS->directRenderingEnabled) SISSetLFBConfig(pSiS); */ 9099 } 9100#endif 9101 9102 /* Wrap some funcs, initialize pseudo-Xinerama and setup remaining SD flags */ 9103 9104 pSiS->SiS_SD_Flags &= ~(SiS_SD_PSEUDOXINERAMA); 9105#ifdef SISMERGED 9106 if(pSiS->MergedFB) { 9107 pSiS->PointerMoved = pScrn->PointerMoved; 9108 pScrn->PointerMoved = SISMergedPointerMoved; 9109 pSiS->Rotate = 0; 9110 pSiS->Reflect = 0; 9111 pSiS->ShadowFB = FALSE; 9112#if (XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0)) && (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 24) 9113 if(pSiS->CRT1XOffs || pSiS->CRT1YOffs || pSiS->CRT2XOffs || pSiS->CRT2YOffs) { 9114 xf86DisableRandR(); 9115 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 9116 "MergedFB: CRT2Position offset used, disabling RandR\n"); 9117 } 9118#endif 9119#ifdef SISXINERAMA 9120 if(pSiS->UseSiSXinerama) { 9121 SiSnoPanoramiXExtension = FALSE; 9122 SiSXineramaExtensionInit(pScrn); 9123 if(!SiSnoPanoramiXExtension) { 9124 pSiS->SiS_SD_Flags |= SiS_SD_PSEUDOXINERAMA; 9125 if(pSiS->HaveNonRect) { 9126 /* Reset the viewport (now eventually non-recangular) */ 9127 SISAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 9128 } 9129 } 9130 } else { 9131 pSiS->MouseRestrictions = FALSE; 9132 } 9133#endif 9134 } 9135#endif 9136 9137 /* Wrap CloseScreen and set up SaveScreen */ 9138 pSiS->CloseScreen = pScreen->CloseScreen; 9139 pScreen->CloseScreen = SISCloseScreen; 9140#ifdef SISDUALHEAD 9141 if(pSiS->DualHeadMode) 9142 pScreen->SaveScreen = SISSaveScreenDH; 9143 else 9144#endif 9145 pScreen->SaveScreen = SISSaveScreen; 9146 9147 /* Install BlockHandler */ 9148 pSiS->BlockHandler = pScreen->BlockHandler; 9149 pScreen->BlockHandler = SISBlockHandler; 9150 9151 /* Report any unused options (only for the first generation) */ 9152 if(serverGeneration == 1) { 9153 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 9154 } 9155 9156 /* Clear frame buffer */ 9157 /* For CRT2, we don't do that at this point in dual head 9158 * mode since the mode isn't switched at this time (it will 9159 * be reset when setting the CRT1 mode). Hence, we just 9160 * save the necessary data and clear the screen when 9161 * going through this for CRT1. 9162 */ 9163 9164 OnScreenSize = pScrn->displayWidth * pScrn->currentMode->VDisplay 9165 * (pScrn->bitsPerPixel >> 3); 9166 9167 /* Turn on the screen now */ 9168 /* We do this in dual head mode after second head is finished */ 9169#ifdef SISDUALHEAD 9170 if(pSiS->DualHeadMode) { 9171 if(pSiS->SecondHead) { 9172 sisclearvram(pSiS->FbBase, OnScreenSize); 9173 sisclearvram(pSiSEnt->FbBase1, pSiSEnt->OnScreenSize1); 9174 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 9175 } else { 9176 pSiSEnt->FbBase1 = pSiS->FbBase; 9177 pSiSEnt->OnScreenSize1 = OnScreenSize; 9178 } 9179 } else { 9180#endif 9181 SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 9182 sisclearvram(pSiS->FbBase, OnScreenSize); 9183#ifdef SISDUALHEAD 9184 } 9185#endif 9186 9187 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTSGRCRT2; 9188#ifdef SISDUALHEAD 9189 if(!pSiS->DualHeadMode) { 9190#endif 9191 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 9192 if((pSiS->crt2cindices) && (pSiS->crt2gcolortable)) { 9193 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTSGRCRT2; 9194 } 9195 } 9196#ifdef SISDUALHEAD 9197 } 9198#endif 9199 9200 pSiS->SiS_SD_Flags &= ~SiS_SD_ISDEPTH8; 9201 if(pSiS->CurrentLayout.bitsPerPixel == 8) { 9202 pSiS->SiS_SD_Flags |= SiS_SD_ISDEPTH8; 9203 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTXVGAMMA1; 9204 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTSGRCRT2; 9205 } 9206 9207#ifdef SISGAMMARAMP 9208 pSiS->SiS_SD_Flags |= SiS_SD_CANSETGAMMA; 9209#else 9210 pSiS->SiS_SD_Flags &= ~SiS_SD_CANSETGAMMA; 9211#endif 9212 9213 SiSCtrlExtInit(pScrn); 9214 9215 return TRUE; 9216} 9217 9218/* Usually mandatory */ 9219Bool 9220SISSwitchMode(SWITCH_MODE_ARGS_DECL) 9221{ 9222 SCRN_INFO_PTR(arg); 9223 SISPtr pSiS = SISPTR(pScrn); 9224 9225 if(!pSiS->skipswitchcheck) { 9226 if(SISValidMode(arg, mode, TRUE, 0) != MODE_OK) { 9227 return FALSE; 9228 } 9229 } 9230 9231 (*pSiS->SyncAccel)(pScrn); 9232 9233 if(!(SISModeInit(pScrn, mode))) return FALSE; 9234 9235 /* Since RandR (indirectly) uses SwitchMode(), we need to 9236 * update our Xinerama info here, too, in case of resizing 9237 */ 9238#ifdef SISMERGED 9239#ifdef SISXINERAMA 9240 if(pSiS->MergedFB) { 9241 SiSUpdateXineramaScreenInfo(pScrn); 9242 } 9243#endif 9244#endif 9245 return TRUE; 9246} 9247 9248static void 9249SISSetStartAddressCRT1(SISPtr pSiS, ULong base) 9250{ 9251 UChar cr11backup; 9252 9253 inSISIDXREG(SISCR, 0x11, cr11backup); /* Unlock CRTC registers */ 9254 andSISIDXREG(SISCR, 0x11, 0x7F); 9255 outSISIDXREG(SISCR, 0x0D, base & 0xFF); 9256 outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); 9257 outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF); 9258 if(pSiS->VGAEngine == SIS_315_VGA) { 9259 setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01); 9260 } 9261 /* Eventually lock CRTC registers */ 9262 setSISIDXREG(SISCR, 0x11, 0x7F,(cr11backup & 0x80)); 9263} 9264 9265static void 9266SISSetStartAddressCRT2(SISPtr pSiS, ULong base) 9267{ 9268 SiS_UnLockCRT2(pSiS->SiS_Pr); 9269 outSISIDXREG(SISPART1, 0x06, GETVAR8(base)); 9270 outSISIDXREG(SISPART1, 0x05, GETBITS(base, 15:8)); 9271 outSISIDXREG(SISPART1, 0x04, GETBITS(base, 23:16)); 9272 if(pSiS->VGAEngine == SIS_315_VGA) { 9273 setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7); 9274 } 9275 SiS_LockCRT2(pSiS->SiS_Pr); 9276} 9277 9278#ifdef SISMERGED 9279static Bool 9280InRegion(int x, int y, region r) 9281{ 9282 return (r.x0 <= x) && (x <= r.x1) && (r.y0 <= y) && (y <= r.y1); 9283} 9284 9285static void 9286SISAdjustFrameHW_CRT1(ScrnInfoPtr pScrn, int x, int y) 9287{ 9288 SISPtr pSiS = SISPTR(pScrn); 9289 ULong base; 9290 9291 base = y * pSiS->CurrentLayout.displayWidth + x; 9292 switch(pSiS->CurrentLayout.bitsPerPixel) { 9293 case 16: base >>= 1; break; 9294 case 32: break; 9295 default: base >>= 2; 9296 } 9297 base += (pSiS->dhmOffset/4); 9298 SISSetStartAddressCRT1(pSiS, base); 9299} 9300 9301static void 9302SISAdjustFrameHW_CRT2(ScrnInfoPtr pScrn, int x, int y) 9303{ 9304 SISPtr pSiS = SISPTR(pScrn); 9305 ULong base; 9306 9307 base = y * pSiS->CurrentLayout.displayWidth + x; 9308 switch(pSiS->CurrentLayout.bitsPerPixel) { 9309 case 16: base >>= 1; break; 9310 case 32: break; 9311 default: base >>= 2; 9312 } 9313 base += (pSiS->dhmOffset/4); 9314 SISSetStartAddressCRT2(pSiS, base); 9315} 9316 9317static void 9318SISMergedPointerMoved(SCRN_ARG_TYPE arg, int x, int y) 9319{ 9320 SCRN_INFO_PTR(arg); 9321 ScrnInfoPtr pScrn1 = pScrn; 9322 SISPtr pSiS = SISPTR(pScrn1); 9323 ScrnInfoPtr pScrn2 = pSiS->CRT2pScrn; 9324 region out, in1, in2, f2, f1; 9325 int deltax, deltay; 9326 int temp1, temp2; 9327 int old1x0, old1y0, old2x0, old2y0; 9328 int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; 9329 int HVirt = pScrn1->virtualX; 9330 int VVirt = pScrn1->virtualY; 9331#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 20 9332 int sigstate; 9333#endif 9334 Bool doit = FALSE, HaveNonRect = FALSE, HaveOffsRegions = FALSE; 9335 SiSScrn2Rel srel = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT2Position; 9336 9337 if(pSiS->DGAactive) { 9338 return; 9339 /* DGA: There is no cursor and no panning while DGA is active. */ 9340 /* If it were, we would need to do: */ 9341 /* HVirt = pSiS->CurrentLayout.displayWidth; 9342 VVirt = pSiS->CurrentLayout.displayHeight; 9343 BOUND(x, pSiS->CurrentLayout.DGAViewportX, HVirt); 9344 BOUND(y, pSiS->CurrentLayout.DGAViewportY, VVirt); */ 9345 } else { 9346 CRT1XOffs = pSiS->CRT1XOffs; 9347 CRT1YOffs = pSiS->CRT1YOffs; 9348 CRT2XOffs = pSiS->CRT2XOffs; 9349 CRT2YOffs = pSiS->CRT2YOffs; 9350 HaveNonRect = pSiS->HaveNonRect; 9351 HaveOffsRegions = pSiS->HaveOffsRegions; 9352 } 9353 9354 /* Check if the pointer is inside our dead areas */ 9355 if((pSiS->MouseRestrictions) && (srel != sisClone) && !SiSnoPanoramiXExtension) { 9356 if(HaveNonRect) { 9357 if(InRegion(x, y, pSiS->NonRectDead)) { 9358 switch(srel) { 9359 case sisLeftOf: 9360 case sisRightOf: y = pSiS->NonRectDead.y0 - 1; 9361 doit = TRUE; 9362 break; 9363 case sisAbove: 9364 case sisBelow: x = pSiS->NonRectDead.x0 - 1; 9365 doit = TRUE; 9366 default: break; 9367 } 9368 } 9369 } 9370 if(HaveOffsRegions) { 9371 if(InRegion(x, y, pSiS->OffDead1)) { 9372 switch(srel) { 9373 case sisLeftOf: 9374 case sisRightOf: y = pSiS->OffDead1.y1; 9375 doit = TRUE; 9376 break; 9377 case sisAbove: 9378 case sisBelow: x = pSiS->OffDead1.x1; 9379 doit = TRUE; 9380 default: break; 9381 } 9382 } else if(InRegion(x, y, pSiS->OffDead2)) { 9383 switch(srel) { 9384 case sisLeftOf: 9385 case sisRightOf: y = pSiS->OffDead2.y0 - 1; 9386 doit = TRUE; 9387 break; 9388 case sisAbove: 9389 case sisBelow: x = pSiS->OffDead2.x0 - 1; 9390 doit = TRUE; 9391 default: break; 9392 } 9393 } 9394 } 9395 if(doit) { 9396#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 20 /* screw it */ 9397 sigstate = xf86BlockSIGIO(); 9398#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 15 9399 { 9400 double dx = x, dy = y; 9401 miPointerSetPosition(inputInfo.pointer, Absolute, &dx, &dy); 9402 x = (int)dx; 9403 y = (int)dy; 9404 } 9405#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 13 9406 miPointerSetPosition(inputInfo.pointer, Absolute, &x, &y); 9407#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 5 9408 miPointerSetPosition(inputInfo.pointer, &x, &y); 9409#else 9410 UpdateCurrentTime(); 9411 miPointerAbsoluteCursor(x, y, currentTime.milliseconds); 9412#endif 9413 xf86UnblockSIGIO(sigstate); 9414#endif 9415 return; 9416 } 9417 } 9418 9419 f1.x0 = old1x0 = pSiS->CRT1frameX0; 9420 f1.x1 = pSiS->CRT1frameX1; 9421 f1.y0 = old1y0 = pSiS->CRT1frameY0; 9422 f1.y1 = pSiS->CRT1frameY1; 9423 f2.x0 = old2x0 = pScrn2->frameX0; 9424 f2.x1 = pScrn2->frameX1; 9425 f2.y0 = old2y0 = pScrn2->frameY0; 9426 f2.y1 = pScrn2->frameY1; 9427 9428 /* Define the outer region. Crossing this causes all frames to move */ 9429 out.x0 = pScrn1->frameX0; 9430 out.x1 = pScrn1->frameX1; 9431 out.y0 = pScrn1->frameY0; 9432 out.y1 = pScrn1->frameY1; 9433 9434 /* 9435 * Define the inner sliding window. Being outsize both frames but 9436 * inside the outer clipping window will slide corresponding frame 9437 */ 9438 in1 = out; 9439 in2 = out; 9440 switch(srel) { 9441 case sisLeftOf: 9442 in1.x0 = f1.x0; 9443 in2.x1 = f2.x1; 9444 break; 9445 case sisRightOf: 9446 in1.x1 = f1.x1; 9447 in2.x0 = f2.x0; 9448 break; 9449 case sisBelow: 9450 in1.y1 = f1.y1; 9451 in2.y0 = f2.y0; 9452 break; 9453 case sisAbove: 9454 in1.y0 = f1.y0; 9455 in2.y1 = f2.y1; 9456 break; 9457 case sisClone: 9458 break; 9459 } 9460 9461 deltay = 0; 9462 deltax = 0; 9463 9464 if(InRegion(x, y, out)) { /* inside outer region */ 9465 9466 if(InRegion(x, y, in1) && !InRegion(x, y, f1)) { 9467 REBOUND(f1.x0, f1.x1, x); 9468 REBOUND(f1.y0, f1.y1, y); 9469 deltax = 1; 9470 } 9471 if(InRegion(x, y, in2) && !InRegion(x, y, f2)) { 9472 REBOUND(f2.x0, f2.x1, x); 9473 REBOUND(f2.y0, f2.y1, y); 9474 deltax = 1; 9475 } 9476 9477 } else { /* outside outer region */ 9478 9479 if(out.x0 > x) { 9480 deltax = x - out.x0; 9481 } 9482 if(out.x1 < x) { 9483 deltax = x - out.x1; 9484 } 9485 if(deltax) { 9486 pScrn1->frameX0 += deltax; 9487 pScrn1->frameX1 += deltax; 9488 f1.x0 += deltax; 9489 f1.x1 += deltax; 9490 f2.x0 += deltax; 9491 f2.x1 += deltax; 9492 } 9493 9494 if(out.y0 > y) { 9495 deltay = y - out.y0; 9496 } 9497 if(out.y1 < y) { 9498 deltay = y - out.y1; 9499 } 9500 if(deltay) { 9501 pScrn1->frameY0 += deltay; 9502 pScrn1->frameY1 += deltay; 9503 f1.y0 += deltay; 9504 f1.y1 += deltay; 9505 f2.y0 += deltay; 9506 f2.y1 += deltay; 9507 } 9508 9509 switch(srel) { 9510 case sisLeftOf: 9511 if(x >= f1.x0) { REBOUND(f1.y0, f1.y1, y); } 9512 if(x <= f2.x1) { REBOUND(f2.y0, f2.y1, y); } 9513 break; 9514 case sisRightOf: 9515 if(x <= f1.x1) { REBOUND(f1.y0, f1.y1, y); } 9516 if(x >= f2.x0) { REBOUND(f2.y0, f2.y1, y); } 9517 break; 9518 case sisBelow: 9519 if(y <= f1.y1) { REBOUND(f1.x0, f1.x1, x); } 9520 if(y >= f2.y0) { REBOUND(f2.x0, f2.x1, x); } 9521 break; 9522 case sisAbove: 9523 if(y >= f1.y0) { REBOUND(f1.x0, f1.x1, x); } 9524 if(y <= f2.y1) { REBOUND(f2.x0, f2.x1, x); } 9525 break; 9526 case sisClone: 9527 break; 9528 } 9529 9530 } 9531 9532 if(deltax || deltay) { 9533 pSiS->CRT1frameX0 = f1.x0; 9534 pSiS->CRT1frameY0 = f1.y0; 9535 pScrn2->frameX0 = f2.x0; 9536 pScrn2->frameY0 = f2.y0; 9537 9538 switch(srel) { 9539 case sisLeftOf: 9540 case sisRightOf: 9541 if(CRT1YOffs || CRT2YOffs || HaveNonRect) { 9542 if(pSiS->CRT1frameY0 != old1y0) { 9543 if(pSiS->CRT1frameY0 < CRT1YOffs) 9544 pSiS->CRT1frameY0 = CRT1YOffs; 9545 9546 temp1 = pSiS->CRT1frameY0 + CDMPTR->CRT1->VDisplay; 9547 temp2 = min((VVirt - CRT2YOffs), (CRT1YOffs + pSiS->MBXNR1YMAX)); 9548 if(temp1 > temp2) 9549 pSiS->CRT1frameY0 -= (temp1 - temp2); 9550 } 9551 if(pScrn2->frameY0 != old2y0) { 9552 if(pScrn2->frameY0 < CRT2YOffs) 9553 pScrn2->frameY0 = CRT2YOffs; 9554 9555 temp1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay; 9556 temp2 = min((VVirt - CRT1YOffs), (CRT2YOffs + pSiS->MBXNR2YMAX)); 9557 if(temp1 > temp2) 9558 pScrn2->frameY0 -= (temp1 - temp2); 9559 } 9560 } 9561 break; 9562 case sisBelow: 9563 case sisAbove: 9564 if(CRT1XOffs || CRT2XOffs || HaveNonRect) { 9565 if(pSiS->CRT1frameX0 != old1x0) { 9566 if(pSiS->CRT1frameX0 < CRT1XOffs) 9567 pSiS->CRT1frameX0 = CRT1XOffs; 9568 9569 temp1 = pSiS->CRT1frameX0 + CDMPTR->CRT1->HDisplay; 9570 temp2 = min((HVirt - CRT2XOffs), (CRT1XOffs + pSiS->MBXNR1XMAX)); 9571 if(temp1 > temp2) 9572 pSiS->CRT1frameX0 -= (temp1 - temp2); 9573 } 9574 if(pScrn2->frameX0 != old2x0) { 9575 if(pScrn2->frameX0 < CRT2XOffs) 9576 pScrn2->frameX0 = CRT2XOffs; 9577 9578 temp1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay; 9579 temp2 = min((HVirt - CRT1XOffs), (CRT2XOffs + pSiS->MBXNR2XMAX)); 9580 if(temp1 > temp2) 9581 pScrn2->frameX0 -= (temp1 - temp2); 9582 } 9583 } 9584 break; 9585 case sisClone: 9586 break; 9587 } 9588 9589 pSiS->CRT1frameX1 = pSiS->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1; 9590 pSiS->CRT1frameY1 = pSiS->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1; 9591 pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1; 9592 pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1; 9593 9594 /* No need to update pScrn1->frame?1, done above */ 9595 9596 SISAdjustFrameHW_CRT1(pScrn1, pSiS->CRT1frameX0, pSiS->CRT1frameY0); 9597 SISAdjustFrameHW_CRT2(pScrn1, pScrn2->frameX0, pScrn2->frameY0); 9598 } 9599} 9600 9601static void 9602SISAdjustFrameMerged(ADJUST_FRAME_ARGS_DECL) 9603{ 9604 SCRN_INFO_PTR(arg); 9605 ScrnInfoPtr pScrn1 = pScrn; 9606 SISPtr pSiS = SISPTR(pScrn1); 9607 ScrnInfoPtr pScrn2 = pSiS->CRT2pScrn; 9608 int HTotal = pSiS->CurrentLayout.mode->HDisplay; 9609 int VTotal = pSiS->CurrentLayout.mode->VDisplay; 9610 int HMax = HTotal; 9611 int VMax = VTotal; 9612 int HVirt = pScrn1->virtualX; 9613 int VVirt = pScrn1->virtualY; 9614 int x1 = x, x2 = x; 9615 int y1 = y, y2 = y; 9616 int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; 9617 int MBXNR1XMAX = 65536, MBXNR1YMAX = 65536, MBXNR2XMAX = 65536, MBXNR2YMAX = 65536; 9618 9619 if(pSiS->DGAactive) { 9620 HVirt = pSiS->CurrentLayout.displayWidth; 9621 VVirt = pSiS->CurrentLayout.displayHeight; 9622 } else { 9623 CRT1XOffs = pSiS->CRT1XOffs; 9624 CRT1YOffs = pSiS->CRT1YOffs; 9625 CRT2XOffs = pSiS->CRT2XOffs; 9626 CRT2YOffs = pSiS->CRT2YOffs; 9627 MBXNR1XMAX = pSiS->MBXNR1XMAX; 9628 MBXNR1YMAX = pSiS->MBXNR1YMAX; 9629 MBXNR2XMAX = pSiS->MBXNR2XMAX; 9630 MBXNR2YMAX = pSiS->MBXNR2YMAX; 9631 } 9632 9633 BOUND(x, 0, HVirt - HTotal); 9634 BOUND(y, 0, VVirt - VTotal); 9635 if(SDMPTR(pScrn1)->CRT2Position != sisClone) { 9636 BOUND(x1, CRT1XOffs, min(HVirt, MBXNR1XMAX + CRT1XOffs) - min(HTotal, MBXNR1XMAX) - CRT2XOffs); 9637 BOUND(y1, CRT1YOffs, min(VVirt, MBXNR1YMAX + CRT1YOffs) - min(VTotal, MBXNR1YMAX) - CRT2YOffs); 9638 BOUND(x2, CRT2XOffs, min(HVirt, MBXNR2XMAX + CRT2XOffs) - min(HTotal, MBXNR2XMAX) - CRT1XOffs); 9639 BOUND(y2, CRT2YOffs, min(VVirt, MBXNR2YMAX + CRT2YOffs) - min(VTotal, MBXNR2YMAX) - CRT1YOffs); 9640 } 9641 9642 switch(SDMPTR(pScrn1)->CRT2Position) { 9643 case sisLeftOf: 9644 pScrn2->frameX0 = x2; 9645 BOUND(pScrn2->frameY0, y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR->CRT2->VDisplay); 9646 pSiS->CRT1frameX0 = x1 + CDMPTR->CRT2->HDisplay; 9647 BOUND(pSiS->CRT1frameY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR->CRT1->VDisplay); 9648 break; 9649 case sisRightOf: 9650 pSiS->CRT1frameX0 = x1; 9651 BOUND(pSiS->CRT1frameY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR->CRT1->VDisplay); 9652 pScrn2->frameX0 = x2 + CDMPTR->CRT1->HDisplay; 9653 BOUND(pScrn2->frameY0, y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR->CRT2->VDisplay); 9654 break; 9655 case sisAbove: 9656 BOUND(pScrn2->frameX0, x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR->CRT2->HDisplay); 9657 pScrn2->frameY0 = y2; 9658 BOUND(pSiS->CRT1frameX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR->CRT1->HDisplay); 9659 pSiS->CRT1frameY0 = y1 + CDMPTR->CRT2->VDisplay; 9660 break; 9661 case sisBelow: 9662 BOUND(pSiS->CRT1frameX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR->CRT1->HDisplay); 9663 pSiS->CRT1frameY0 = y1; 9664 BOUND(pScrn2->frameX0, x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR->CRT2->HDisplay); 9665 pScrn2->frameY0 = y2 + CDMPTR->CRT1->VDisplay; 9666 break; 9667 case sisClone: 9668 BOUND(pSiS->CRT1frameX0, x, x + HMax - CDMPTR->CRT1->HDisplay); 9669 BOUND(pSiS->CRT1frameY0, y, y + VMax - CDMPTR->CRT1->VDisplay); 9670 BOUND(pScrn2->frameX0, x, x + HMax - CDMPTR->CRT2->HDisplay); 9671 BOUND(pScrn2->frameY0, y, y + VMax - CDMPTR->CRT2->VDisplay); 9672 break; 9673 } 9674 9675 BOUND(pSiS->CRT1frameX0, 0, HVirt - CDMPTR->CRT1->HDisplay); 9676 BOUND(pSiS->CRT1frameY0, 0, VVirt - CDMPTR->CRT1->VDisplay); 9677 BOUND(pScrn2->frameX0, 0, HVirt - CDMPTR->CRT2->HDisplay); 9678 BOUND(pScrn2->frameY0, 0, VVirt - CDMPTR->CRT2->VDisplay); 9679 9680 pScrn1->frameX0 = x; 9681 pScrn1->frameY0 = y; 9682 9683 pSiS->CRT1frameX1 = pSiS->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1; 9684 pSiS->CRT1frameY1 = pSiS->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1; 9685 pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1; 9686 pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1; 9687 9688 pScrn1->frameX1 = pScrn1->frameX0 + pSiS->CurrentLayout.mode->HDisplay - 1; 9689 pScrn1->frameY1 = pScrn1->frameY0 + pSiS->CurrentLayout.mode->VDisplay - 1; 9690 if(SDMPTR(pScrn1)->CRT2Position != sisClone) { 9691 pScrn1->frameX1 += CRT1XOffs + CRT2XOffs; 9692 pScrn1->frameY1 += CRT1YOffs + CRT2YOffs; 9693 } 9694 9695 SISAdjustFrameHW_CRT1(pScrn1, pSiS->CRT1frameX0, pSiS->CRT1frameY0); 9696 SISAdjustFrameHW_CRT2(pScrn1, pScrn2->frameX0, pScrn2->frameY0); 9697} 9698#endif 9699 9700/* 9701 * This function is used to initialize the Start Address - the first 9702 * displayed location in the video memory. 9703 * 9704 * Usually mandatory 9705 */ 9706void 9707SISAdjustFrame(ADJUST_FRAME_ARGS_DECL) 9708{ 9709 SCRN_INFO_PTR(arg); 9710 SISPtr pSiS = SISPTR(pScrn); 9711 ULong base; 9712 UChar temp, cr11backup; 9713 9714#ifdef SISMERGED 9715 if(pSiS->MergedFB) { 9716 SISAdjustFrameMerged(ADJUST_FRAME_ARGS(pScrn, x, y)); 9717 return; 9718 } 9719#endif 9720 9721 if(pSiS->UseVESA) { 9722 VBESetDisplayStart(pSiS->pVbe, x, y, TRUE); 9723 return; 9724 } 9725 9726 if(pScrn->bitsPerPixel < 8) { 9727 base = (y * pSiS->CurrentLayout.displayWidth + x + 3) >> 3; 9728 } else { 9729 base = y * pSiS->CurrentLayout.displayWidth + x; 9730 9731 /* calculate base bpp dep. */ 9732 switch(pSiS->CurrentLayout.bitsPerPixel) { 9733 case 16: 9734 base >>= 1; 9735 break; 9736 case 24: 9737 base = ((base * 3)) >> 2; 9738 base -= base % 6; 9739 break; 9740 case 32: 9741 break; 9742 default: /* 8bpp */ 9743 base >>= 2; 9744 break; 9745 } 9746 } 9747 9748#ifdef UNLOCK_ALWAYS 9749 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 9750#endif 9751 9752 base += (pSiS->dhmOffset/4); 9753 9754#ifdef TWDEBUG 9755 xf86DrvMsg(0, 0, "AdjustFrame: x %d y %d bpp %d dw %d base %d, dhmOffset %d\n", 9756 x, y, pSiS->CurrentLayout.bitsPerPixel, pSiS->CurrentLayout.displayWidth, base, pSiS->dhmOffset); 9757#endif 9758 9759#ifdef SISDUALHEAD 9760 if(pSiS->DualHeadMode) { 9761 if(!pSiS->SecondHead) { 9762 /* Head 1 (master) is always CRT2 */ 9763 SISSetStartAddressCRT2(pSiS, base); 9764 } else { 9765 /* Head 2 (slave) is always CRT1 */ 9766 SISSetStartAddressCRT1(pSiS, base); 9767 } 9768 } else { 9769#endif 9770 switch(pSiS->VGAEngine) { 9771 case SIS_300_VGA: 9772 case SIS_315_VGA: 9773 SISSetStartAddressCRT1(pSiS, base); 9774 if(pSiS->VBFlags & CRT2_ENABLE) { 9775 if(!SiSBridgeIsInSlaveMode(pScrn)) { 9776 SISSetStartAddressCRT2(pSiS, base); 9777 } 9778 } 9779 break; 9780 default: 9781 /* Unlock CRTC registers */ 9782 inSISIDXREG(SISCR, 0x11, cr11backup); 9783 andSISIDXREG(SISCR, 0x11, 0x7F); 9784 outSISIDXREG(SISCR, 0x0D, base & 0xFF); 9785 outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); 9786 inSISIDXREG(SISSR, 0x27, temp); 9787 temp &= 0xF0; 9788 temp |= (base & 0x0F0000) >> 16; 9789 outSISIDXREG(SISSR, 0x27, temp); 9790 /* Eventually lock CRTC registers */ 9791 setSISIDXREG(SISCR, 0x11, 0x7F, (cr11backup & 0x80)); 9792 } 9793#ifdef SISDUALHEAD 9794 } 9795#endif 9796 9797} 9798 9799/* 9800 * This is called when VT switching back to the X server. Its job is 9801 * to reinitialise the video mode. 9802 * Mandatory! 9803 */ 9804static Bool 9805SISEnterVT(VT_FUNC_ARGS_DECL) 9806{ 9807 SCRN_INFO_PTR(arg); 9808 SISPtr pSiS = SISPTR(pScrn); 9809 9810 SiS_SiSFB_Lock(pScrn, TRUE); 9811 9812 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 9813 9814 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 9815 outSISIDXREG(SISCR,0x32,pSiS->myCR32); 9816 outSISIDXREG(SISCR,0x36,pSiS->myCR36); 9817 outSISIDXREG(SISCR,0x37,pSiS->myCR37); 9818 } 9819 9820 if(!SISModeInit(pScrn, pScrn->currentMode)) { 9821 SISErrorLog(pScrn, "SiSEnterVT: SISModeInit() failed\n"); 9822 return FALSE; 9823 } 9824 9825 SISAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 9826 9827#ifdef SISDRI 9828 if(pSiS->directRenderingEnabled) { 9829 DRIUnlock(xf86ScrnToScreen(pScrn)); 9830 } 9831#endif 9832 9833#ifdef SISDUALHEAD 9834 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) 9835#endif 9836 if(pSiS->ResetXv) { 9837 (pSiS->ResetXv)(pScrn); 9838 } 9839 9840 return TRUE; 9841} 9842 9843/* 9844 * This is called when VT switching away from the X server. Its job is 9845 * to restore the previous (text) mode. 9846 * Mandatory! 9847 */ 9848static void 9849SISLeaveVT(VT_FUNC_ARGS_DECL) 9850{ 9851 SCRN_INFO_PTR(arg); 9852 SISPtr pSiS = SISPTR(pScrn); 9853#ifdef SISDRI 9854 ScreenPtr pScreen; 9855 9856 if(pSiS->directRenderingEnabled) { 9857 pScreen = xf86ScrnToScreen(pScrn); 9858 DRILock(pScreen, 0); 9859 } 9860#endif 9861 9862#ifdef SISDUALHEAD 9863 if(pSiS->DualHeadMode && pSiS->SecondHead) return; 9864#endif 9865 9866 if(pSiS->CursorInfoPtr) { 9867#ifdef SISDUALHEAD 9868 if(pSiS->DualHeadMode) { 9869 if(!pSiS->SecondHead) { 9870 pSiS->ForceCursorOff = TRUE; 9871 pSiS->CursorInfoPtr->HideCursor(pScrn); 9872 SISWaitVBRetrace(pScrn); 9873 pSiS->ForceCursorOff = FALSE; 9874 } 9875 } else { 9876#endif 9877 pSiS->CursorInfoPtr->HideCursor(pScrn); 9878 SISWaitVBRetrace(pScrn); 9879#ifdef SISDUALHEAD 9880 } 9881#endif 9882 } 9883 9884 SISBridgeRestore(pScrn); 9885 9886 if(pSiS->UseVESA) { 9887 9888 /* This is a q&d work-around for a BIOS bug. In case we disabled CRT2, 9889 * VBESaveRestore() does not restore CRT1. So we set any mode now, 9890 * because VBESetVBEMode correctly restores CRT1. Afterwards, we 9891 * can call VBESaveRestore to restore original mode. 9892 */ 9893 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (!(pSiS->VBFlags & DISPTYPE_DISP2))) 9894 VBESetVBEMode(pSiS->pVbe, (pSiS->SISVESAModeList->n) | 0xc000, NULL); 9895 9896 SISVESARestore(pScrn); 9897 9898 } else { 9899 9900 SISRestore(pScrn); 9901 9902 } 9903 9904 /* We use (otherwise unused) bit 7 to indicate that we are running 9905 * to keep sisfb to change the displaymode (this would result in 9906 * lethal display corruption upon quitting X or changing to a VT 9907 * until a reboot) 9908 */ 9909 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 9910 orSISIDXREG(SISCR,0x34,0x80); 9911 } 9912 9913 SISVGALock(pSiS); 9914 9915 SiS_SiSFB_Lock(pScrn, FALSE); 9916} 9917 9918 9919/* 9920 * This is called at the end of each server generation. It restores the 9921 * original (text) mode. It should really also unmap the video memory too. 9922 * Mandatory! 9923 */ 9924static Bool 9925SISCloseScreen(CLOSE_SCREEN_ARGS_DECL) 9926{ 9927 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 9928 SISPtr pSiS = SISPTR(pScrn); 9929#ifdef SISDUALHEAD 9930 SISEntPtr pSiSEnt = pSiS->entityPrivate; 9931#endif 9932 9933 if(pSiS->SiSCtrlExtEntry) { 9934 SiSCtrlExtUnregister(pSiS, pScrn->scrnIndex); 9935 } 9936 9937#ifdef SISDRI 9938 if(pSiS->directRenderingEnabled) { 9939 SISDRICloseScreen(pScreen); 9940 pSiS->directRenderingEnabled = FALSE; 9941 } 9942#endif 9943 9944 if(pScrn->vtSema) { 9945 9946 if(pSiS->CursorInfoPtr) { 9947#ifdef SISDUALHEAD 9948 if(pSiS->DualHeadMode) { 9949 if(!pSiS->SecondHead) { 9950 pSiS->ForceCursorOff = TRUE; 9951 pSiS->CursorInfoPtr->HideCursor(pScrn); 9952 SISWaitVBRetrace(pScrn); 9953 pSiS->ForceCursorOff = FALSE; 9954 } 9955 } else { 9956#endif 9957 pSiS->CursorInfoPtr->HideCursor(pScrn); 9958 SISWaitVBRetrace(pScrn); 9959#ifdef SISDUALHEAD 9960 } 9961#endif 9962 } 9963 9964 SISBridgeRestore(pScrn); 9965 9966 if(pSiS->UseVESA) { 9967 9968 /* This is a q&d work-around for a BIOS bug. In case we disabled CRT2, 9969 * VBESaveRestore() does not restore CRT1. So we set any mode now, 9970 * because VBESetVBEMode correctly restores CRT1. Afterwards, we 9971 * can call VBESaveRestore to restore original mode. 9972 */ 9973 if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (!(pSiS->VBFlags & DISPTYPE_DISP2))) 9974 VBESetVBEMode(pSiS->pVbe, (pSiS->SISVESAModeList->n) | 0xc000, NULL); 9975 9976 SISVESARestore(pScrn); 9977 9978 } else { 9979 9980 SISRestore(pScrn); 9981 9982 } 9983 9984 SISVGALock(pSiS); 9985 9986 } 9987 9988 SiS_SiSFB_Lock(pScrn, FALSE); 9989 9990 /* We should restore the mode number in case vtsema = false as well, 9991 * but since we haven't register access then we can't do it. I think 9992 * I need to rework the save/restore stuff, like saving the video 9993 * status when returning to the X server and by that save me the 9994 * trouble if sisfb was started from a textmode VT while X was on. 9995 */ 9996 9997 SISUnmapMem(pScrn); 9998#ifdef SIS_PC_PLATFORM 9999 SiSVGAUnmapMem(pScrn); 10000#endif 10001 10002#ifdef SISDUALHEAD 10003 if(pSiS->DualHeadMode) { 10004 pSiSEnt = pSiS->entityPrivate; 10005 pSiSEnt->refCount--; 10006 } 10007#endif 10008 10009 if(pSiS->pInt) { 10010 xf86FreeInt10(pSiS->pInt); 10011 pSiS->pInt = NULL; 10012 } 10013 10014#ifdef SIS_USE_XAA 10015 if(!pSiS->useEXA) { 10016 if(pSiS->AccelLinearScratch) { 10017 xf86FreeOffscreenLinear(pSiS->AccelLinearScratch); 10018 pSiS->AccelLinearScratch = NULL; 10019 } 10020 if(pSiS->AccelInfoPtr) { 10021 XAADestroyInfoRec(pSiS->AccelInfoPtr); 10022 pSiS->AccelInfoPtr = NULL; 10023 } 10024 } 10025#endif 10026 10027#ifdef SIS_USE_EXA 10028 if(pSiS->useEXA) { 10029 if(pSiS->EXADriverPtr) { 10030 exaDriverFini(pScreen); 10031 free(pSiS->EXADriverPtr); 10032 pSiS->EXADriverPtr = NULL; 10033 pSiS->exa_scratch = NULL; 10034 } 10035 } 10036#endif 10037 10038 if(pSiS->CursorInfoPtr) { 10039 xf86DestroyCursorInfoRec(pSiS->CursorInfoPtr); 10040 pSiS->CursorInfoPtr = NULL; 10041 } 10042 10043 if(pSiS->ShadowPtr) { 10044 free(pSiS->ShadowPtr); 10045 pSiS->ShadowPtr = NULL; 10046 } 10047 10048 if(pSiS->DGAModes) { 10049 free(pSiS->DGAModes); 10050 pSiS->DGAModes = NULL; 10051 } 10052 10053 if(pSiS->adaptor) { 10054 free(pSiS->adaptor); 10055 pSiS->adaptor = NULL; 10056 pSiS->ResetXv = pSiS->ResetXvGamma = pSiS->ResetXvDisplay = NULL; 10057 } 10058 10059 if(pSiS->blitadaptor) { 10060 free(pSiS->blitadaptor); 10061 pSiS->blitadaptor = NULL; 10062 } 10063 10064 if(pSiS->crt2gcolortable) { 10065 free(pSiS->crt2gcolortable); 10066 pSiS->crt2gcolortable = NULL; 10067 } 10068 10069 if(pSiS->crt2cindices) { 10070 free(pSiS->crt2cindices); 10071 pSiS->crt2cindices = NULL; 10072 } 10073 10074 pScrn->vtSema = FALSE; 10075 10076 /* Restore Blockhandler */ 10077 pScreen->BlockHandler = pSiS->BlockHandler; 10078 10079 pScreen->CloseScreen = pSiS->CloseScreen; 10080 10081 return(*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); 10082} 10083 10084 10085/* Free up any per-generation data structures */ 10086 10087/* Optional */ 10088static void 10089SISFreeScreen(FREE_SCREEN_ARGS_DECL) 10090{ 10091 SCRN_INFO_PTR(arg); 10092#ifdef SIS_NEED_MAP_IOP 10093 SISPtr pSiS = SISPTR(pScrn); 10094 10095 if(pSiS) { 10096#ifdef SISDUALHEAD 10097 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10098 if(pSiSEnt) { 10099 pSiSEnt->forceUnmapIOPBase = TRUE; 10100 } 10101#endif 10102 SISUnmapIOPMem(pScrn); 10103 } 10104#endif 10105 10106 SISFreeRec(pScrn); 10107} 10108 10109 10110/* Checks if a mode is suitable for the selected chipset. */ 10111 10112static ModeStatus 10113SISValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 10114{ 10115 SCRN_INFO_PTR(arg); 10116 SISPtr pSiS = SISPTR(pScrn); 10117 10118 if(pSiS->UseVESA) { 10119 if(SiSCalcVESAModeIndex(pScrn, mode)) 10120 return(MODE_OK); 10121 else 10122 return(MODE_BAD); 10123 } 10124 10125 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 10126#ifdef SISDUALHEAD 10127 if(pSiS->DualHeadMode) { 10128 if(pSiS->SecondHead) { 10129 if(SiS_CheckModeCRT1(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10130 return(MODE_BAD); 10131 } else { 10132 if(SiS_CheckModeCRT2(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10133 return(MODE_BAD); 10134 } 10135 } else 10136#endif 10137#ifdef SISMERGED 10138 if(pSiS->MergedFB) { 10139 if(!mode->Private) { 10140 if(!pSiS->CheckForCRT2) { 10141 if(SiS_CheckModeCRT1(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10142 return(MODE_BAD); 10143 } else { 10144 if(SiS_CheckModeCRT2(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes2) < 0x14) 10145 return(MODE_BAD); 10146 } 10147 } else { 10148 if(SiS_CheckModeCRT1(pScrn, ((SiSMergedDisplayModePtr)mode->Private)->CRT1, 10149 pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10150 return(MODE_BAD); 10151 10152 if(SiS_CheckModeCRT2(pScrn, ((SiSMergedDisplayModePtr)mode->Private)->CRT2, 10153 pSiS->VBFlags, pSiS->HaveCustomModes2) < 0x14) 10154 return(MODE_BAD); 10155 } 10156 } else 10157#endif 10158 { 10159 if(SiS_CheckModeCRT1(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10160 return(MODE_BAD); 10161 10162 if(SiS_CheckModeCRT2(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 10163 return(MODE_BAD); 10164 } 10165 } 10166 10167 return(MODE_OK); 10168} 10169 10170#ifdef DEBUG 10171static void 10172SiSDumpModeInfo(ScrnInfoPtr pScrn, DisplayModePtr mode) 10173{ 10174 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Clock : %x\n", mode->Clock); 10175 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Display : %x\n", mode->CrtcHDisplay); 10176 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Blank Start : %x\n", mode->CrtcHBlankStart); 10177 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Sync Start : %x\n", mode->CrtcHSyncStart); 10178 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Sync End : %x\n", mode->CrtcHSyncEnd); 10179 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Blank End : %x\n", mode->CrtcHBlankEnd); 10180 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Total : %x\n", mode->CrtcHTotal); 10181 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Skew : %x\n", mode->CrtcHSkew); 10182 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz HAdjusted : %x\n", mode->CrtcHAdjusted); 10183 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Display : %x\n", mode->CrtcVDisplay); 10184 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Blank Start : %x\n", mode->CrtcVBlankStart); 10185 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Sync Start : %x\n", mode->CrtcVSyncStart); 10186 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Sync End : %x\n", mode->CrtcVSyncEnd); 10187 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Blank End : %x\n", mode->CrtcVBlankEnd); 10188 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Total : %x\n", mode->CrtcVTotal); 10189 xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt VAdjusted : %x\n", mode->CrtcVAdjusted); 10190} 10191#endif 10192 10193static void 10194SISModifyModeInfo(DisplayModePtr mode) 10195{ 10196 if(mode->CrtcHBlankStart == mode->CrtcHDisplay) 10197 mode->CrtcHBlankStart++; 10198 if(mode->CrtcHBlankEnd == mode->CrtcHTotal) 10199 mode->CrtcHBlankEnd--; 10200 if(mode->CrtcVBlankStart == mode->CrtcVDisplay) 10201 mode->CrtcVBlankStart++; 10202 if(mode->CrtcVBlankEnd == mode->CrtcVTotal) 10203 mode->CrtcVBlankEnd--; 10204} 10205 10206/* Enable the Turboqueue/Commandqueue (For 300 and 315/330/340 series only) */ 10207static void 10208SiSEnableTurboQueue(ScrnInfoPtr pScrn) 10209{ 10210 SISPtr pSiS = SISPTR(pScrn); 10211 UShort SR26, SR27; 10212 ULong temp; 10213 10214 switch(pSiS->VGAEngine) { 10215 case SIS_300_VGA: 10216 if((!pSiS->NoAccel) && (pSiS->TurboQueue)) { 10217 /* TQ size is always 512k */ 10218 temp = (pScrn->videoRam/64) - 8; 10219 SR26 = temp & 0xFF; 10220 inSISIDXREG(SISSR, 0x27, SR27); 10221 SR27 &= 0xFC; 10222 SR27 |= (0xF0 | ((temp >> 8) & 3)); 10223 outSISIDXREG(SISSR, 0x26, SR26); 10224 outSISIDXREG(SISSR, 0x27, SR27); 10225 } 10226 break; 10227 10228 case SIS_315_VGA: 10229 if(!pSiS->NoAccel) { 10230 /* On 315/330/340 series, there are three queue modes available 10231 * which are chosen by setting bits 7:5 in SR26: 10232 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep 10233 * track of the queue, the FIFO, command parsing and so 10234 * on. This is the one comparable to the 300 series. 10235 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will 10236 * have to do queue management himself. 10237 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the 10238 * queue in AGP memory space. 10239 * We go VRAM or MMIO here. 10240 * SR26 bit 4 is called "Bypass H/W queue". 10241 * SR26 bit 1 is called "Enable Command Queue Auto Correction" 10242 * SR26 bit 0 resets the queue 10243 * Size of queue memory is encoded in bits 3:2 like this: 10244 * 00 (0x00) 512K 10245 * 01 (0x04) 1M 10246 * 10 (0x08) 2M 10247 * 11 (0x0C) 4M 10248 * The queue location is to be written to 0x85C0. 10249 */ 10250#ifdef SISVRAMQ 10251 /* We use VRAM Cmd Queue, not MMIO or AGP */ 10252 UChar tempCR55 = 0; 10253 10254 /* Set Command Queue Threshold to max value 11111b (?) */ 10255 outSISIDXREG(SISSR, 0x27, 0x1F); 10256 10257 /* Disable queue flipping */ 10258 inSISIDXREG(SISCR, 0x55, tempCR55); 10259 andSISIDXREG(SISCR, 0x55, 0x33); 10260 /* Synchronous reset for Command Queue */ 10261 outSISIDXREG(SISSR, 0x26, 0x01); 10262 SIS_MMIO_OUT32(pSiS->IOBase, 0x85c4, 0); 10263 /* Enable VRAM Command Queue mode */ 10264 if(pSiS->ChipType == XGI_20) { 10265 /* On XGI_20, always 128K */ 10266 SR26 = 0x40 | 0x04 | 0x01; 10267 } else { 10268 switch(pSiS->cmdQueueSize) { 10269 case 1*1024*1024: SR26 = (0x40 | 0x04 | 0x01); break; 10270 case 2*1024*1024: SR26 = (0x40 | 0x08 | 0x01); break; 10271 case 4*1024*1024: SR26 = (0x40 | 0x0C | 0x01); break; 10272 default: 10273 pSiS->cmdQueueSize = 512 * 1024; 10274 case 512*1024: SR26 = (0x40 | 0x00 | 0x01); 10275 } 10276 } 10277 outSISIDXREG(SISSR, 0x26, SR26); 10278 SR26 &= 0xfe; 10279 outSISIDXREG(SISSR, 0x26, SR26); 10280 *(pSiS->cmdQ_SharedWritePort) = (unsigned int)(SIS_MMIO_IN32(pSiS->IOBase, 0x85c8)); 10281 SIS_MMIO_OUT32(pSiS->IOBase, 0x85c4, (CARD32)(*(pSiS->cmdQ_SharedWritePort))); 10282 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C0, pSiS->cmdQueueOffset); 10283 temp = (ULong)pSiS->RealFbBase; 10284#ifdef SISDUALHEAD 10285 if(pSiS->DualHeadMode) { 10286 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10287 temp = (ULong)pSiSEnt->RealFbBase; 10288 } 10289#endif 10290 temp += pSiS->cmdQueueOffset; 10291 pSiS->cmdQueueBase = (unsigned int *)temp; 10292 outSISIDXREG(SISCR, 0x55, tempCR55); 10293#ifdef TWDEBUG 10294 xf86DrvMsg(0, 0, "CmdQueueOffs 0x%x, CmdQueueAdd %p, shwrp 0x%x, status %x, base %p\n", 10295 pSiS->cmdQueueOffset, pSiS->cmdQueueBase, *(pSiS->cmdQ_SharedWritePort), 10296 SIS_MMIO_IN32(pSiS->IOBase, 0x85cc), (ULong *)temp); 10297#endif 10298#else 10299 /* For MMIO */ 10300 /* Syncronous reset for Command Queue */ 10301 orSISIDXREG(SISSR, 0x26, 0x01); 10302 /* Set Command Queue Threshold to max value 11111b */ 10303 outSISIDXREG(SISSR, 0x27, 0x1F); 10304 /* Do some magic (cp readport to writeport) */ 10305 temp = SIS_MMIO_IN32(pSiS->IOBase, 0x85C8); 10306 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C4, temp); 10307 /* Enable MMIO Command Queue mode (0x20), 10308 * Enable_command_queue_auto_correction (0x02) 10309 * (no idea, but sounds good, so use it) 10310 * 512k (0x00) (does this apply to MMIO mode?) */ 10311 outSISIDXREG(SISSR, 0x26, 0x22); 10312 /* Calc Command Queue position (Q is always 512k)*/ 10313 temp = (pScrn->videoRam - 512) * 1024; 10314 /* Set Q position */ 10315 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C0, temp); 10316#endif 10317 } 10318 break; 10319 default: 10320 break; 10321 } 10322} 10323 10324#ifdef SISVRAMQ 10325static void 10326SiSRestoreQueueMode(SISPtr pSiS, SISRegPtr sisReg) 10327{ 10328 UChar tempCR55=0; 10329 10330 if(pSiS->VGAEngine == SIS_315_VGA) { 10331 inSISIDXREG(SISCR,0x55,tempCR55); 10332 andSISIDXREG(SISCR,0x55,0x33); 10333 outSISIDXREG(SISSR,0x26,0x01); 10334 SIS_MMIO_OUT32(pSiS->IOBase, 0x85c4, 0); 10335 outSISIDXREG(SISSR,0x27,sisReg->sisRegs3C4[0x27]); 10336 outSISIDXREG(SISSR,0x26,sisReg->sisRegs3C4[0x26]); 10337 SIS_MMIO_OUT32(pSiS->IOBase, 0x85C0, sisReg->sisMMIO85C0); 10338 outSISIDXREG(SISCR,0x55,tempCR55); 10339 } 10340} 10341#endif 10342 10343/* Things to do before a ModeSwitch. We set up the 10344 * video bridge configuration and the TurboQueue. 10345 */ 10346void SiSPreSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode, int viewmode) 10347{ 10348 SISPtr pSiS = SISPTR(pScrn); 10349 UChar CR30, CR31, CR32, CR33; 10350 UChar CR39 = 0, CR3B = 0; 10351 UChar CR17, CR38 = 0; 10352 UChar CR35 = 0, CR79 = 0; 10353 int temp = 0, crt1rateindex = 0; 10354 ULong vbflag = pSiS->VBFlags; 10355 Bool hcm = pSiS->HaveCustomModes; 10356 DisplayModePtr mymode = mode; 10357 10358 pSiS->IsCustom = FALSE; 10359 10360 /* NEVER call this with viewmode = SIS_MODE_SIMU 10361 * if mode->type is not M_T_DEFAULT! 10362 */ 10363 10364#ifdef SISMERGED 10365 if(pSiS->MergedFB) { 10366 switch(viewmode) { 10367 case SIS_MODE_CRT1: 10368 mymode = ((SiSMergedDisplayModePtr)mode->Private)->CRT1; 10369 break; 10370 case SIS_MODE_CRT2: 10371 mymode = ((SiSMergedDisplayModePtr)mode->Private)->CRT2; 10372 hcm = pSiS->HaveCustomModes2; 10373 } 10374 } 10375#endif 10376 10377 switch(viewmode) { 10378 case SIS_MODE_CRT1: 10379 if(SiS_CheckModeCRT1(pScrn, mymode, vbflag, hcm) == 0xfe) { 10380 pSiS->IsCustom = TRUE; 10381 } 10382 break; 10383 case SIS_MODE_CRT2: 10384 if(vbflag & CRT2_ENABLE) { 10385 if(SiS_CheckModeCRT2(pScrn, mymode, vbflag, hcm) == 0xfe) { 10386 pSiS->IsCustom = TRUE; 10387 } 10388 } else { 10389 /* This can only happen in mirror mode */ 10390 if(SiS_CheckModeCRT1(pScrn, mymode, vbflag, hcm) == 0xfe) { 10391 pSiS->IsCustom = TRUE; 10392 } 10393 } 10394 } 10395 10396#ifdef UNLOCK_ALWAYS 10397 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); /* Unlock Registers */ 10398#endif 10399 10400 inSISIDXREG(SISCR, 0x30, CR30); 10401 inSISIDXREG(SISCR, 0x31, CR31); 10402 CR32 = pSiS->newCR32; 10403 inSISIDXREG(SISCR, 0x33, CR33); 10404 10405 if(pSiS->NewCRLayout) { 10406 10407 inSISIDXREG(SISCR, 0x35, CR35); 10408 inSISIDXREG(SISCR, 0x38, CR38); 10409 inSISIDXREG(SISCR, 0x39, CR39); 10410 10411 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, SISVERBLEVEL, 10412 "Before: CR30=0x%02x,CR31=0x%02x,CR32=0x%02x,CR33=0x%02x,CR35=0x%02x,CR38=0x%02x\n", 10413 CR30, CR31, CR32, CR33, CR35, CR38); 10414 10415 CR38 &= ~0x07; 10416 10417 } else { 10418 10419 if(pSiS->Chipset != PCI_CHIP_SIS300) { 10420 switch(pSiS->VGAEngine) { 10421 case SIS_300_VGA: temp = 0x35; break; 10422 case SIS_315_VGA: temp = 0x38; break; 10423 } 10424 if(temp) inSISIDXREG(SISCR, temp, CR38); 10425 } 10426 if(pSiS->VGAEngine == SIS_315_VGA) { 10427 inSISIDXREG(SISCR, 0x79, CR79); 10428 CR38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */ 10429 } 10430 inSISIDXREG(SISCR, 0x3b, CR3B); 10431 10432 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, SISVERBLEVEL, 10433 "Before: CR30=0x%02x, CR31=0x%02x, CR32=0x%02x, CR33=0x%02x, CR%02x=0x%02x\n", 10434 CR30, CR31, CR32, CR33, temp, CR38); 10435 } 10436 10437 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, SISVERBLEVEL, "VBFlags=0x%x\n", pSiS->VBFlags); 10438 10439 CR30 = 0x00; 10440 CR31 &= ~0x60; /* Clear VB_Drivermode & VB_OutputDisable */ 10441 CR31 |= 0x04; /* Set VB_NotSimuMode (not for 30xB/1400x1050?) */ 10442 CR35 = 0x00; 10443 10444 if(!pSiS->NewCRLayout) { 10445 if(!pSiS->AllowHotkey) { 10446 CR31 |= 0x80; /* Disable hotkey-switch */ 10447 } 10448 CR79 &= ~0x10; /* Enable Backlight control on 315 series */ 10449 } 10450 10451 SiS_SetEnableDstn(pSiS->SiS_Pr, FALSE); 10452 SiS_SetEnableFstn(pSiS->SiS_Pr, FALSE); 10453 10454 if((vbflag & CRT1_LCDA) && (viewmode == SIS_MODE_CRT1)) { 10455 10456 CR38 |= 0x02; 10457 10458 } else { 10459 10460 switch(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA)) { 10461 10462 case CRT2_TV: 10463 10464 CR38 &= ~0xC0; /* Clear Pal M/N bits */ 10465 10466 if((pSiS->VBFlags2 & VB2_CHRONTEL) && (vbflag & TV_CHSCART)) { /* Chrontel */ 10467 CR30 |= 0x10; 10468 CR38 |= 0x04; 10469 CR38 &= ~0x08; 10470 CR31 |= 0x01; 10471 } else if((pSiS->VBFlags2 & VB2_CHRONTEL) && (vbflag & TV_CHYPBPR525I)) { /* Chrontel */ 10472 CR38 |= 0x08; 10473 CR38 &= ~0x04; 10474 CR31 &= ~0x01; 10475 } else if(vbflag & TV_HIVISION) { /* SiS bridge */ 10476 if(pSiS->NewCRLayout) { 10477 CR38 |= 0x04; 10478 CR35 |= 0x60; 10479 } else { 10480 CR30 |= 0x80; 10481 if(pSiS->VGAEngine == SIS_315_VGA) { 10482 if(pSiS->VBFlags2 & VB2_SISYPBPRBRIDGE) { 10483 CR38 |= (0x08 | 0x30); 10484 } 10485 } 10486 } 10487 CR31 |= 0x01; 10488 CR35 |= 0x01; 10489 } else if(vbflag & TV_YPBPR) { /* SiS bridge */ 10490 if(pSiS->NewCRLayout) { 10491 CR38 |= 0x04; 10492 CR31 &= ~0x01; 10493 CR35 &= ~0x01; 10494 if(vbflag & (TV_YPBPR525P | TV_YPBPR625P)) CR35 |= 0x20; 10495 else if(vbflag & TV_YPBPR750P) CR35 |= 0x40; 10496 else if(vbflag & TV_YPBPR1080I) CR35 |= 0x60; 10497 10498 if(vbflag & (TV_YPBPR625I | TV_YPBPR625P)) { 10499 CR31 |= 0x01; 10500 CR35 |= 0x01; 10501 } 10502 10503 CR39 &= ~0x03; 10504 if((vbflag & TV_YPBPRAR) == TV_YPBPR43LB) CR39 |= 0x00; 10505 else if((vbflag & TV_YPBPRAR) == TV_YPBPR43) CR39 |= 0x01; 10506 else if((vbflag & TV_YPBPRAR) == TV_YPBPR169) CR39 |= 0x02; 10507 else CR39 |= 0x03; 10508 } else if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR) { 10509 CR30 |= 0x80; 10510 CR38 |= 0x08; 10511 CR31 &= ~0x01; 10512 if(vbflag & (TV_YPBPR525P|TV_YPBPR625P)) CR38 |= 0x10; 10513 else if(vbflag & TV_YPBPR750P) CR38 |= 0x20; 10514 else if(vbflag & TV_YPBPR1080I) CR38 |= 0x30; 10515 10516 if(vbflag & (TV_YPBPR625I | TV_YPBPR625P)) CR31 |= 0x01; 10517 10518 if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPRAR) { 10519 CR3B &= ~0x03; 10520 if((vbflag & TV_YPBPRAR) == TV_YPBPR43LB) CR3B |= 0x00; 10521 else if((vbflag & TV_YPBPRAR) == TV_YPBPR43) CR3B |= 0x03; 10522 else if((vbflag & TV_YPBPRAR) == TV_YPBPR169) CR3B |= 0x01; 10523 else CR3B |= 0x03; 10524 } 10525 } 10526 } else { /* All */ 10527 if(vbflag & TV_SCART) CR30 |= 0x10; 10528 if(vbflag & TV_SVIDEO) CR30 |= 0x08; 10529 if(vbflag & TV_AVIDEO) CR30 |= 0x04; 10530 if(!(CR30 & 0x1C)) CR30 |= 0x08; /* default: SVIDEO */ 10531 10532 if(vbflag & TV_PAL) { 10533 CR31 |= 0x01; 10534 CR35 |= 0x01; 10535 if( (pSiS->VBFlags2 & VB2_SISBRIDGE) || 10536 ((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->ChrontelType == CHRONTEL_701x)) ) { 10537 if(vbflag & TV_PALM) { 10538 CR38 |= 0x40; 10539 CR35 |= 0x04; 10540 } else if(vbflag & TV_PALN) { 10541 CR38 |= 0x80; 10542 CR35 |= 0x08; 10543 } 10544 } 10545 } else { 10546 CR31 &= ~0x01; 10547 CR35 &= ~0x01; 10548 if(vbflag & TV_NTSCJ) { 10549 CR38 |= 0x40; /* TW, not BIOS */ 10550 CR35 |= 0x02; 10551 } 10552 } 10553 if(vbflag & TV_SCART) { 10554 CR31 |= 0x01; 10555 CR35 |= 0x01; 10556 } 10557 } 10558 10559 CR31 &= ~0x04; /* Clear NotSimuMode */ 10560 pSiS->SiS_Pr->SiS_CHOverScan = pSiS->UseCHOverScan; 10561 if((pSiS->OptTVSOver == 1) && (pSiS->ChrontelType == CHRONTEL_700x)) { 10562 pSiS->SiS_Pr->SiS_CHSOverScan = TRUE; 10563 } else { 10564 pSiS->SiS_Pr->SiS_CHSOverScan = FALSE; 10565 } 10566#ifdef SIS_CP 10567 SIS_CP_DRIVER_CONFIG 10568#endif 10569 break; 10570 10571 case CRT2_LCD: 10572 CR30 |= 0x20; 10573 SiS_SetEnableDstn(pSiS->SiS_Pr, pSiS->DSTN); 10574 SiS_SetEnableFstn(pSiS->SiS_Pr, pSiS->FSTN); 10575 break; 10576 10577 case CRT2_VGA: 10578 CR30 |= 0x40; 10579 break; 10580 10581 default: 10582 CR30 |= 0x00; 10583 CR31 |= 0x20; /* VB_OUTPUT_DISABLE */ 10584 if(pSiS->UseVESA) { 10585 crt1rateindex = SISSearchCRT1Rate(pScrn, mymode); 10586 } 10587 } 10588 10589 } 10590 10591 if(vbflag & CRT1_LCDA) { 10592 switch(viewmode) { 10593 case SIS_MODE_CRT1: 10594 CR38 |= 0x01; 10595 break; 10596 case SIS_MODE_CRT2: 10597 if(vbflag & (CRT2_TV|CRT2_VGA)) { 10598 CR30 |= 0x02; 10599 CR38 |= 0x01; 10600 } else { 10601 CR38 |= 0x03; 10602 } 10603 break; 10604 case SIS_MODE_SIMU: 10605 default: 10606 if(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA)) { 10607 CR30 |= 0x01; 10608 } 10609 break; 10610 } 10611 } else { 10612 if(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA)) { 10613 CR30 |= 0x01; 10614 } 10615 } 10616 10617 if(pSiS->UseVESA) { 10618 CR31 &= ~0x40; /* Clear Drivermode */ 10619 CR31 |= 0x06; /* Set SlaveMode, Enable SimuMode in Slavemode */ 10620#ifdef TWDEBUG 10621 CR31 |= 0x40; /* DEBUG (for non-slave mode VESA) */ 10622 crt1rateindex = SISSearchCRT1Rate(pScrn, mymode); 10623#endif 10624 } else { 10625 CR31 |= 0x40; /* Set Drivermode */ 10626 CR31 &= ~0x06; /* Disable SlaveMode, disable SimuMode in SlaveMode */ 10627 if(!pSiS->IsCustom) { 10628 crt1rateindex = SISSearchCRT1Rate(pScrn, mymode); 10629 } 10630 } 10631 10632 switch(viewmode) { 10633 case SIS_MODE_SIMU: 10634 CR33 = 0; 10635 if(!(vbflag & CRT1_LCDA)) { 10636 CR33 |= (crt1rateindex & 0x0f); 10637 } 10638 if(vbflag & CRT2_VGA) { 10639 CR33 |= ((crt1rateindex & 0x0f) << 4); 10640 } 10641 break; 10642 case SIS_MODE_CRT1: 10643 CR33 &= 0xf0; 10644 if(!(vbflag & CRT1_LCDA)) { 10645 CR33 |= (crt1rateindex & 0x0f); 10646 } 10647 break; 10648 case SIS_MODE_CRT2: 10649 CR33 &= 0x0f; 10650 if(vbflag & CRT2_VGA) { 10651 CR33 |= ((crt1rateindex & 0x0f) << 4); 10652 } 10653 break; 10654 } 10655 10656 if((!pSiS->UseVESA) && (vbflag & CRT2_ENABLE)) { 10657 if(pSiS->CRT1off) CR33 &= 0xf0; 10658 } 10659 10660 if(pSiS->NewCRLayout) { 10661 10662 CR31 &= 0xfe; /* Clear PAL flag (now in CR35) */ 10663 CR38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */ 10664 outSISIDXREG(SISCR, 0x30, CR30); 10665 outSISIDXREG(SISCR, 0x31, CR31); 10666 outSISIDXREG(SISCR, 0x33, CR33); 10667 outSISIDXREG(SISCR, 0x35, CR35); 10668 setSISIDXREG(SISCR, 0x38, 0xf8, CR38); 10669 outSISIDXREG(SISCR, 0x39, CR39); 10670 10671 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, SISVERBLEVEL, 10672 "After: CR30=0x%02x,CR31=0x%02x,CR33=0x%02x,CR35=0x%02x,CR38=%02x\n", 10673 CR30, CR31, CR33, CR35, CR38); 10674 10675 } else { 10676 10677 outSISIDXREG(SISCR, 0x30, CR30); 10678 outSISIDXREG(SISCR, 0x31, CR31); 10679 outSISIDXREG(SISCR, 0x33, CR33); 10680 if(temp) { 10681 outSISIDXREG(SISCR, temp, CR38); 10682 } 10683 if(pSiS->VGAEngine == SIS_315_VGA) { 10684 outSISIDXREG(SISCR, 0x3b, CR3B); 10685 outSISIDXREG(SISCR, 0x79, CR79); 10686 } 10687 10688 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, SISVERBLEVEL, 10689 "After: CR30=0x%02x,CR31=0x%02x,CR33=0x%02x,CR%02x=%02x\n", 10690 CR30, CR31, CR33, temp, CR38); 10691 } 10692 10693 pSiS->SiS_Pr->SiS_UseOEM = pSiS->OptUseOEM; 10694 10695 /* Enable TurboQueue */ 10696#ifdef SISVRAMQ 10697 if(pSiS->VGAEngine != SIS_315_VGA) 10698#endif 10699 SiSEnableTurboQueue(pScrn); 10700 10701 if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE)) { 10702 /* Switch on CRT1 for modes that require the bridge in SlaveMode */ 10703 andSISIDXREG(SISSR,0x1f,0x3f); 10704 inSISIDXREG(SISCR, 0x17, CR17); 10705 if(!(CR17 & 0x80)) { 10706 orSISIDXREG(SISCR, 0x17, 0x80); 10707 outSISIDXREG(SISSR, 0x00, 0x01); 10708 usleep(10000); 10709 outSISIDXREG(SISSR, 0x00, 0x03); 10710 } 10711 } 10712} 10713 10714/* Functions for adjusting various TV settings */ 10715 10716/* These are used by the PostSetMode() functions as well as 10717 * the display properties tool SiSCtrl. 10718 * 10719 * There is each a Set and a Get routine. The Set functions 10720 * take a value of the same range as the corresponding option. 10721 * The Get routines return a value of the same range (although 10722 * not necessarily the same value as previously set because 10723 * of the lower resolution of the respective setting compared 10724 * to the valid range). 10725 * The Get routines return -2 on error (eg. hardware does not 10726 * support this setting). 10727 * Note: The x and y positioning routines accept a position 10728 * RELATIVE to the default position. All other routines 10729 * take ABSOLUTE values. 10730 * 10731 * The Set functions will store the property regardless if TV is 10732 * currently used or not and if the hardware supports the property 10733 * or not. The Get routines will return this stored 10734 * value if TV is not currently used (because the register does 10735 * not contain the correct value then) or if the hardware supports 10736 * the respective property. This should make it easier for the 10737 * display property tool because it does not have to know the 10738 * hardware features. 10739 * 10740 * All the routines are dual head aware. It does not matter 10741 * if the function is called from the CRT1 or CRT2 session. 10742 * The values will be in pSiSEnt anyway, and read from there 10743 * if we're running dual head. 10744 */ 10745 10746void SiS_SetCHTVlumabandwidthcvbs(ScrnInfoPtr pScrn, int val) 10747{ 10748 SISPtr pSiS = SISPTR(pScrn); 10749#ifdef SISDUALHEAD 10750 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10751#endif 10752 10753 pSiS->chtvlumabandwidthcvbs = val; 10754#ifdef SISDUALHEAD 10755 if(pSiSEnt) pSiSEnt->chtvlumabandwidthcvbs = val; 10756#endif 10757 10758 if(!(pSiS->VBFlags & CRT2_TV)) return; 10759 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10760 10761#ifdef UNLOCK_ALWAYS 10762 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10763#endif 10764 10765 switch(pSiS->ChrontelType) { 10766 case CHRONTEL_700x: 10767 val /= 8; 10768 if((val == 0) || (val == 1)) { 10769 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, val, 0xFE); 10770 } 10771 break; 10772 case CHRONTEL_701x: 10773 val /= 4; 10774 if((val >= 0) && (val <= 3)) { 10775 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, val, 0xFC); 10776 } 10777 break; 10778 } 10779} 10780 10781int SiS_GetCHTVlumabandwidthcvbs(ScrnInfoPtr pScrn) 10782{ 10783 SISPtr pSiS = SISPTR(pScrn); 10784#ifdef SISDUALHEAD 10785 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10786#endif 10787 10788 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10789#ifdef SISDUALHEAD 10790 if(pSiSEnt && pSiS->DualHeadMode) 10791 return (int)pSiSEnt->chtvlumabandwidthcvbs; 10792 else 10793#endif 10794 return (int)pSiS->chtvlumabandwidthcvbs; 10795 } else { 10796#ifdef UNLOCK_ALWAYS 10797 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10798#endif 10799 switch(pSiS->ChrontelType) { 10800 case CHRONTEL_700x: 10801 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x01) * 8); 10802 case CHRONTEL_701x: 10803 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x03) * 4); 10804 default: 10805 return (int)pSiS->chtvlumabandwidthcvbs; 10806 } 10807 } 10808} 10809 10810void SiS_SetCHTVlumabandwidthsvideo(ScrnInfoPtr pScrn, int val) 10811{ 10812 SISPtr pSiS = SISPTR(pScrn); 10813#ifdef SISDUALHEAD 10814 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10815#endif 10816 10817 pSiS->chtvlumabandwidthsvideo = val; 10818#ifdef SISDUALHEAD 10819 if(pSiSEnt) pSiSEnt->chtvlumabandwidthsvideo = val; 10820#endif 10821 10822 if(!(pSiS->VBFlags & CRT2_TV)) return; 10823 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10824 10825#ifdef UNLOCK_ALWAYS 10826 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10827#endif 10828 10829 switch(pSiS->ChrontelType) { 10830 case CHRONTEL_700x: 10831 val /= 6; 10832 if((val >= 0) && (val <= 2)) { 10833 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, (val << 1), 0xF9); 10834 } 10835 break; 10836 case CHRONTEL_701x: 10837 val /= 4; 10838 if((val >= 0) && (val <= 3)) { 10839 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, (val << 2), 0xF3); 10840 } 10841 break; 10842 } 10843} 10844 10845int SiS_GetCHTVlumabandwidthsvideo(ScrnInfoPtr pScrn) 10846{ 10847 SISPtr pSiS = SISPTR(pScrn); 10848#ifdef SISDUALHEAD 10849 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10850#endif 10851 10852 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10853#ifdef SISDUALHEAD 10854 if(pSiSEnt && pSiS->DualHeadMode) 10855 return (int)pSiSEnt->chtvlumabandwidthsvideo; 10856 else 10857#endif 10858 return (int)pSiS->chtvlumabandwidthsvideo; 10859 } else { 10860#ifdef UNLOCK_ALWAYS 10861 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10862#endif 10863 switch(pSiS->ChrontelType) { 10864 case CHRONTEL_700x: 10865 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x06) >> 1) * 6); 10866 case CHRONTEL_701x: 10867 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x0c) >> 2) * 4); 10868 default: 10869 return (int)pSiS->chtvlumabandwidthsvideo; 10870 } 10871 } 10872} 10873 10874void SiS_SetCHTVlumaflickerfilter(ScrnInfoPtr pScrn, int val) 10875{ 10876 SISPtr pSiS = SISPTR(pScrn); 10877#ifdef SISDUALHEAD 10878 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10879#endif 10880 10881 pSiS->chtvlumaflickerfilter = val; 10882#ifdef SISDUALHEAD 10883 if(pSiSEnt) pSiSEnt->chtvlumaflickerfilter = val; 10884#endif 10885 10886 if(!(pSiS->VBFlags & CRT2_TV)) return; 10887 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10888 10889#ifdef UNLOCK_ALWAYS 10890 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10891#endif 10892 10893 switch(pSiS->ChrontelType) { 10894 case CHRONTEL_700x: 10895 val /= 6; 10896 if((val >= 0) && (val <= 2)) { 10897 UShort reg = 0; 10898 reg = SiS_GetCH70xx(pSiS->SiS_Pr, 0x01); 10899 reg = (reg & 0xf0) | ((reg & 0x0c) >> 2) | (val << 2); 10900 SiS_SetCH70xx(pSiS->SiS_Pr, 0x01, reg); 10901 } 10902 break; 10903 case CHRONTEL_701x: 10904 val /= 4; 10905 if((val >= 0) && (val <= 3)) { 10906 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x01, (val << 2), 0xF3); 10907 } 10908 break; 10909 } 10910} 10911 10912int SiS_GetCHTVlumaflickerfilter(ScrnInfoPtr pScrn) 10913{ 10914 SISPtr pSiS = SISPTR(pScrn); 10915#ifdef SISDUALHEAD 10916 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10917#endif 10918 10919 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10920#ifdef SISDUALHEAD 10921 if(pSiSEnt && pSiS->DualHeadMode) 10922 return (int)pSiSEnt->chtvlumaflickerfilter; 10923 else 10924#endif 10925 return (int)pSiS->chtvlumaflickerfilter; 10926 } else { 10927#ifdef UNLOCK_ALWAYS 10928 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10929#endif 10930 switch(pSiS->ChrontelType) { 10931 case CHRONTEL_700x: 10932 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x03) * 6); 10933 case CHRONTEL_701x: 10934 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x0c) >> 2) * 4); 10935 default: 10936 return (int)pSiS->chtvlumaflickerfilter; 10937 } 10938 } 10939} 10940 10941void SiS_SetCHTVchromabandwidth(ScrnInfoPtr pScrn, int val) 10942{ 10943 SISPtr pSiS = SISPTR(pScrn); 10944#ifdef SISDUALHEAD 10945 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10946#endif 10947 10948 pSiS->chtvchromabandwidth = val; 10949#ifdef SISDUALHEAD 10950 if(pSiSEnt) pSiSEnt->chtvchromabandwidth = val; 10951#endif 10952 10953 if(!(pSiS->VBFlags & CRT2_TV)) return; 10954 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 10955 10956#ifdef UNLOCK_ALWAYS 10957 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10958#endif 10959 10960 switch(pSiS->ChrontelType) { 10961 case CHRONTEL_700x: 10962 val /= 4; 10963 if((val >= 0) && (val <= 3)) { 10964 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, (val << 4), 0xCF); 10965 } 10966 break; 10967 case CHRONTEL_701x: 10968 val /= 8; 10969 if((val >= 0) && (val <= 1)) { 10970 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, (val << 4), 0xEF); 10971 } 10972 break; 10973 } 10974} 10975 10976int SiS_GetCHTVchromabandwidth(ScrnInfoPtr pScrn) 10977{ 10978 SISPtr pSiS = SISPTR(pScrn); 10979#ifdef SISDUALHEAD 10980 SISEntPtr pSiSEnt = pSiS->entityPrivate; 10981#endif 10982 10983 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 10984#ifdef SISDUALHEAD 10985 if(pSiSEnt && pSiS->DualHeadMode) 10986 return (int)pSiSEnt->chtvchromabandwidth; 10987 else 10988#endif 10989 return (int)pSiS->chtvchromabandwidth; 10990 } else { 10991#ifdef UNLOCK_ALWAYS 10992 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 10993#endif 10994 switch(pSiS->ChrontelType) { 10995 case CHRONTEL_700x: 10996 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x30) >> 4) * 4); 10997 case CHRONTEL_701x: 10998 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x10) >> 4) * 8); 10999 default: 11000 return (int)pSiS->chtvchromabandwidth; 11001 } 11002 } 11003} 11004 11005void SiS_SetCHTVchromaflickerfilter(ScrnInfoPtr pScrn, int val) 11006{ 11007 SISPtr pSiS = SISPTR(pScrn); 11008#ifdef SISDUALHEAD 11009 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11010#endif 11011 11012 pSiS->chtvchromaflickerfilter = val; 11013#ifdef SISDUALHEAD 11014 if(pSiSEnt) pSiSEnt->chtvchromaflickerfilter = val; 11015#endif 11016 11017 if(!(pSiS->VBFlags & CRT2_TV)) return; 11018 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 11019 11020#ifdef UNLOCK_ALWAYS 11021 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11022#endif 11023 11024 switch(pSiS->ChrontelType) { 11025 case CHRONTEL_700x: 11026 val /= 6; 11027 if((val >= 0) && (val <= 2)) { 11028 UShort reg = 0; 11029 reg = SiS_GetCH70xx(pSiS->SiS_Pr, 0x01); 11030 reg = (reg & 0xc0) | ((reg & 0x0c) >> 2) | ((reg & 0x03) << 2) | (val << 4); 11031 SiS_SetCH70xx(pSiS->SiS_Pr, 0x01, reg); 11032 } 11033 break; 11034 case CHRONTEL_701x: 11035 val /= 4; 11036 if((val >= 0) && (val <= 3)) { 11037 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x01, (val << 4), 0xCF); 11038 } 11039 break; 11040 } 11041} 11042 11043int SiS_GetCHTVchromaflickerfilter(ScrnInfoPtr pScrn) 11044{ 11045 SISPtr pSiS = SISPTR(pScrn); 11046#ifdef SISDUALHEAD 11047 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11048#endif 11049 11050 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 11051#ifdef SISDUALHEAD 11052 if(pSiSEnt && pSiS->DualHeadMode) 11053 return (int)pSiSEnt->chtvchromaflickerfilter; 11054 else 11055#endif 11056 return (int)pSiS->chtvchromaflickerfilter; 11057 } else { 11058#ifdef UNLOCK_ALWAYS 11059 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11060#endif 11061 switch(pSiS->ChrontelType) { 11062 case CHRONTEL_700x: 11063 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x30) >> 4) * 6); 11064 case CHRONTEL_701x: 11065 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x30) >> 4) * 4); 11066 default: 11067 return (int)pSiS->chtvchromaflickerfilter; 11068 } 11069 } 11070} 11071 11072void SiS_SetCHTVcvbscolor(ScrnInfoPtr pScrn, int val) 11073{ 11074 SISPtr pSiS = SISPTR(pScrn); 11075#ifdef SISDUALHEAD 11076 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11077#endif 11078 11079 pSiS->chtvcvbscolor = val ? 1 : 0; 11080#ifdef SISDUALHEAD 11081 if(pSiSEnt) pSiSEnt->chtvcvbscolor = pSiS->chtvcvbscolor; 11082#endif 11083 11084 if(!(pSiS->VBFlags & CRT2_TV)) return; 11085 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 11086 11087#ifdef UNLOCK_ALWAYS 11088 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11089#endif 11090 11091 switch(pSiS->ChrontelType) { 11092 case CHRONTEL_700x: 11093 if(!val) SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, 0x40, 0x00); 11094 else SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, 0x00, ~0x40); 11095 break; 11096 case CHRONTEL_701x: 11097 if(!val) SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, 0x00, ~0x20); 11098 else SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, 0x20, 0x00); 11099 break; 11100 } 11101} 11102 11103int SiS_GetCHTVcvbscolor(ScrnInfoPtr pScrn) 11104{ 11105 SISPtr pSiS = SISPTR(pScrn); 11106#ifdef SISDUALHEAD 11107 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11108#endif 11109 11110 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 11111#ifdef SISDUALHEAD 11112 if(pSiSEnt && pSiS->DualHeadMode) 11113 return (int)pSiSEnt->chtvcvbscolor; 11114 else 11115#endif 11116 return (int)pSiS->chtvcvbscolor; 11117 } else { 11118#ifdef UNLOCK_ALWAYS 11119 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11120#endif 11121 switch(pSiS->ChrontelType) { 11122 case CHRONTEL_700x: 11123 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x40) >> 6) ^ 0x01); 11124 case CHRONTEL_701x: 11125 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x20) >> 5) ^ 0x01); 11126 default: 11127 return (int)pSiS->chtvcvbscolor; 11128 } 11129 } 11130} 11131 11132void SiS_SetCHTVtextenhance(ScrnInfoPtr pScrn, int val) 11133{ 11134 SISPtr pSiS = SISPTR(pScrn); 11135#ifdef SISDUALHEAD 11136 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11137#endif 11138 11139 pSiS->chtvtextenhance = val; 11140#ifdef SISDUALHEAD 11141 if(pSiSEnt) pSiSEnt->chtvtextenhance = val; 11142#endif 11143 11144 if(!(pSiS->VBFlags & CRT2_TV)) return; 11145 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 11146 11147#ifdef UNLOCK_ALWAYS 11148 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11149#endif 11150 11151 switch(pSiS->ChrontelType) { 11152 case CHRONTEL_700x: 11153 val /= 6; 11154 if((val >= 0) && (val <= 2)) { 11155 UShort reg = 0; 11156 reg = SiS_GetCH70xx(pSiS->SiS_Pr, 0x01); 11157 reg = (reg & 0xf0) | ((reg & 0x03) << 2) | val; 11158 SiS_SetCH70xx(pSiS->SiS_Pr, 0x01, reg); 11159 } 11160 break; 11161 case CHRONTEL_701x: 11162 val /= 2; 11163 if((val >= 0) && (val <= 7)) { 11164 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, val, 0xF8); 11165 } 11166 break; 11167 } 11168} 11169 11170int SiS_GetCHTVtextenhance(ScrnInfoPtr pScrn) 11171{ 11172 SISPtr pSiS = SISPTR(pScrn); 11173#ifdef SISDUALHEAD 11174 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11175#endif 11176 11177 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 11178#ifdef SISDUALHEAD 11179 if(pSiSEnt && pSiS->DualHeadMode) 11180 return (int)pSiSEnt->chtvtextenhance; 11181 else 11182#endif 11183 return (int)pSiS->chtvtextenhance; 11184 } else { 11185#ifdef UNLOCK_ALWAYS 11186 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11187#endif 11188 switch(pSiS->ChrontelType) { 11189 case CHRONTEL_700x: 11190 return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x0c) >> 2) * 6); 11191 case CHRONTEL_701x: 11192 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x07) * 2); 11193 default: 11194 return (int)pSiS->chtvtextenhance; 11195 } 11196 } 11197} 11198 11199void SiS_SetCHTVcontrast(ScrnInfoPtr pScrn, int val) 11200{ 11201 SISPtr pSiS = SISPTR(pScrn); 11202#ifdef SISDUALHEAD 11203 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11204#endif 11205 11206 pSiS->chtvcontrast = val; 11207#ifdef SISDUALHEAD 11208 if(pSiSEnt) pSiSEnt->chtvcontrast = val; 11209#endif 11210 11211 if(!(pSiS->VBFlags & CRT2_TV)) return; 11212 if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 11213 11214#ifdef UNLOCK_ALWAYS 11215 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11216#endif 11217 11218 val /= 2; 11219 if((val >= 0) && (val <= 7)) { 11220 switch(pSiS->ChrontelType) { 11221 case CHRONTEL_700x: 11222 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x11, val, 0xF8); 11223 break; 11224 case CHRONTEL_701x: 11225 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x08, val, 0xF8); 11226 break; 11227 } 11228 SiS_DDC2Delay(pSiS->SiS_Pr, 1000); 11229 } 11230} 11231 11232int SiS_GetCHTVcontrast(ScrnInfoPtr pScrn) 11233{ 11234 SISPtr pSiS = SISPTR(pScrn); 11235#ifdef SISDUALHEAD 11236 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11237#endif 11238 11239 if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 11240#ifdef SISDUALHEAD 11241 if(pSiSEnt && pSiS->DualHeadMode) 11242 return (int)pSiSEnt->chtvcontrast; 11243 else 11244#endif 11245 return (int)pSiS->chtvcontrast; 11246 } else { 11247#ifdef UNLOCK_ALWAYS 11248 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11249#endif 11250 switch(pSiS->ChrontelType) { 11251 case CHRONTEL_700x: 11252 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x11) & 0x07) * 2); 11253 case CHRONTEL_701x: 11254 return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x08) & 0x07) * 2); 11255 default: 11256 return (int)pSiS->chtvcontrast; 11257 } 11258 } 11259} 11260 11261void SiS_SetSISTVedgeenhance(ScrnInfoPtr pScrn, int val) 11262{ 11263 SISPtr pSiS = SISPTR(pScrn); 11264#ifdef SISDUALHEAD 11265 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11266#endif 11267 11268 pSiS->sistvedgeenhance = val; 11269#ifdef SISDUALHEAD 11270 if(pSiSEnt) pSiSEnt->sistvedgeenhance = val; 11271#endif 11272 11273 if(!(pSiS->VBFlags2 & VB2_301)) return; 11274 if(!(pSiS->VBFlags & CRT2_TV)) return; 11275 11276#ifdef UNLOCK_ALWAYS 11277 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11278#endif 11279 11280 val /= 2; 11281 if((val >= 0) && (val <= 7)) { 11282 setSISIDXREG(SISPART2,0x3A, 0x1F, (val << 5)); 11283 } 11284} 11285 11286int SiS_GetSISTVedgeenhance(ScrnInfoPtr pScrn) 11287{ 11288 SISPtr pSiS = SISPTR(pScrn); 11289 int result = pSiS->sistvedgeenhance; 11290 UChar temp; 11291#ifdef SISDUALHEAD 11292 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11293 11294 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvedgeenhance; 11295#endif 11296 11297 if(!(pSiS->VBFlags2 & VB2_301)) return result; 11298 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11299 11300#ifdef UNLOCK_ALWAYS 11301 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11302#endif 11303 inSISIDXREG(SISPART2, 0x3a, temp); 11304 return(int)(((temp & 0xe0) >> 5) * 2); 11305} 11306 11307void SiS_SetSISTVantiflicker(ScrnInfoPtr pScrn, int val) 11308{ 11309 SISPtr pSiS = SISPTR(pScrn); 11310#ifdef SISDUALHEAD 11311 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11312#endif 11313 11314 pSiS->sistvantiflicker = val; 11315#ifdef SISDUALHEAD 11316 if(pSiSEnt) pSiSEnt->sistvantiflicker = val; 11317#endif 11318 11319 if(!(pSiS->VBFlags & CRT2_TV)) return; 11320 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11321 if(pSiS->VBFlags & TV_HIVISION) return; 11322 if((pSiS->VBFlags & TV_YPBPR) && 11323 (pSiS->VBFlags & (TV_YPBPR525P | TV_YPBPR625P | TV_YPBPR750P | TV_YPBPR1080I))) return; 11324 11325#ifdef UNLOCK_ALWAYS 11326 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11327#endif 11328 11329 /* Valid values: 0=off, 1=low, 2=med, 3=high, 4=adaptive */ 11330 if((val >= 0) && (val <= 4)) { 11331 setSISIDXREG(SISPART2,0x0A,0x8F, (val << 4)); 11332 } 11333} 11334 11335int SiS_GetSISTVantiflicker(ScrnInfoPtr pScrn) 11336{ 11337 SISPtr pSiS = SISPTR(pScrn); 11338 int result = pSiS->sistvantiflicker; 11339 UChar temp; 11340#ifdef SISDUALHEAD 11341 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11342 11343 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvantiflicker; 11344#endif 11345 11346 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return result; 11347 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11348 if(pSiS->VBFlags & TV_HIVISION) return result; 11349 if((pSiS->VBFlags & TV_YPBPR) && 11350 (pSiS->VBFlags & (TV_YPBPR525P | TV_YPBPR625P | TV_YPBPR750P | TV_YPBPR1080I))) return result; 11351 11352#ifdef UNLOCK_ALWAYS 11353 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11354#endif 11355 inSISIDXREG(SISPART2, 0x0a, temp); 11356 return(int)((temp & 0x70) >> 4); 11357} 11358 11359void SiS_SetSISTVsaturation(ScrnInfoPtr pScrn, int val) 11360{ 11361 SISPtr pSiS = SISPTR(pScrn); 11362#ifdef SISDUALHEAD 11363 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11364#endif 11365 11366 pSiS->sistvsaturation = val; 11367#ifdef SISDUALHEAD 11368 if(pSiSEnt) pSiSEnt->sistvsaturation = val; 11369#endif 11370 11371 if(!(pSiS->VBFlags & CRT2_TV)) return; 11372 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11373 if(pSiS->VBFlags2 & VB2_301) return; 11374 11375#ifdef UNLOCK_ALWAYS 11376 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11377#endif 11378 11379 val /= 2; 11380 if((val >= 0) && (val <= 7)) { 11381 setSISIDXREG(SISPART4,0x21,0xF8, val); 11382 } 11383} 11384 11385int SiS_GetSISTVsaturation(ScrnInfoPtr pScrn) 11386{ 11387 SISPtr pSiS = SISPTR(pScrn); 11388 int result = pSiS->sistvsaturation; 11389 UChar temp; 11390#ifdef SISDUALHEAD 11391 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11392 11393 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvsaturation; 11394#endif 11395 11396 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return result; 11397 if(pSiS->VBFlags2 & VB2_301) return result; 11398 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11399 11400#ifdef UNLOCK_ALWAYS 11401 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11402#endif 11403 inSISIDXREG(SISPART4, 0x21, temp); 11404 return(int)((temp & 0x07) * 2); 11405} 11406 11407void SiS_SetSISTVcolcalib(ScrnInfoPtr pScrn, int val, Bool coarse) 11408{ 11409 SISPtr pSiS = SISPTR(pScrn); 11410#ifdef SISDUALHEAD 11411 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11412#endif 11413 int ccoarse, cfine, cbase = pSiS->sistvccbase; 11414 /* UChar temp; */ 11415 11416#ifdef SISDUALHEAD 11417 if(pSiSEnt && pSiS->DualHeadMode) cbase = pSiSEnt->sistvccbase; 11418#endif 11419 11420 if(coarse) { 11421 pSiS->sistvcolcalibc = ccoarse = val; 11422 cfine = pSiS->sistvcolcalibf; 11423#ifdef SISDUALHEAD 11424 if(pSiSEnt) { 11425 pSiSEnt->sistvcolcalibc = val; 11426 if(pSiS->DualHeadMode) cfine = pSiSEnt->sistvcolcalibf; 11427 } 11428#endif 11429 } else { 11430 pSiS->sistvcolcalibf = cfine = val; 11431 ccoarse = pSiS->sistvcolcalibc; 11432#ifdef SISDUALHEAD 11433 if(pSiSEnt) { 11434 pSiSEnt->sistvcolcalibf = val; 11435 if(pSiS->DualHeadMode) ccoarse = pSiSEnt->sistvcolcalibc; 11436 } 11437#endif 11438 } 11439 11440 if(!(pSiS->VBFlags & CRT2_TV)) return; 11441 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11442 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return; 11443 11444#ifdef UNLOCK_ALWAYS 11445 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11446#endif 11447 11448 if((cfine >= -128) && (cfine <= 127) && (ccoarse >= -120) && (ccoarse <= 120)) { 11449 long finalcc = cbase + (((ccoarse * 256) + cfine) * 256); 11450 11451#if 0 11452 inSISIDXREG(SISPART4,0x1f,temp); 11453 if(!(temp & 0x01)) { 11454 if(pSiS->VBFlags & TV_NTSC) finalcc += 0x21ed8620; 11455 else if(pSiS->VBFlags & TV_PALM) finalcc += ?; 11456 else if(pSiS->VBFlags & TV_PALM) finalcc += ?; 11457 else finalcc += 0x2a05d300; 11458 } 11459#endif 11460 setSISIDXREG(SISPART2,0x31,0x80,((finalcc >> 24) & 0x7f)); 11461 outSISIDXREG(SISPART2,0x32,((finalcc >> 16) & 0xff)); 11462 outSISIDXREG(SISPART2,0x33,((finalcc >> 8) & 0xff)); 11463 outSISIDXREG(SISPART2,0x34,(finalcc & 0xff)); 11464 } 11465} 11466 11467int SiS_GetSISTVcolcalib(ScrnInfoPtr pScrn, Bool coarse) 11468{ 11469 SISPtr pSiS = SISPTR(pScrn); 11470#ifdef SISDUALHEAD 11471 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11472 11473 if(pSiSEnt && pSiS->DualHeadMode) 11474 if(coarse) return (int)pSiSEnt->sistvcolcalibc; 11475 else return (int)pSiSEnt->sistvcolcalibf; 11476 else 11477#endif 11478 if(coarse) return (int)pSiS->sistvcolcalibc; 11479 else return (int)pSiS->sistvcolcalibf; 11480} 11481 11482void SiS_SetSISTVcfilter(ScrnInfoPtr pScrn, int val) 11483{ 11484 SISPtr pSiS = SISPTR(pScrn); 11485#ifdef SISDUALHEAD 11486 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11487#endif 11488 11489 pSiS->sistvcfilter = val ? 1 : 0; 11490#ifdef SISDUALHEAD 11491 if(pSiSEnt) pSiSEnt->sistvcfilter = pSiS->sistvcfilter; 11492#endif 11493 11494 if(!(pSiS->VBFlags & CRT2_TV)) return; 11495 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11496 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return; 11497 11498#ifdef UNLOCK_ALWAYS 11499 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11500#endif 11501 11502 setSISIDXREG(SISPART2,0x30,~0x10,((pSiS->sistvcfilter << 4) & 0x10)); 11503} 11504 11505int SiS_GetSISTVcfilter(ScrnInfoPtr pScrn) 11506{ 11507 SISPtr pSiS = SISPTR(pScrn); 11508 int result = pSiS->sistvcfilter; 11509 UChar temp; 11510#ifdef SISDUALHEAD 11511 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11512 11513 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvcfilter; 11514#endif 11515 11516 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return result; 11517 if(!(pSiS->VBFlags & CRT2_TV)) return result; 11518 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return result; 11519 11520#ifdef UNLOCK_ALWAYS 11521 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11522#endif 11523 inSISIDXREG(SISPART2, 0x30, temp); 11524 return (int)((temp & 0x10) ? 1 : 0); 11525} 11526 11527void SiS_SetSISTVyfilter(ScrnInfoPtr pScrn, int val) 11528{ 11529 SISPtr pSiS = SISPTR(pScrn); 11530#ifdef SISDUALHEAD 11531 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11532#endif 11533 UChar p35,p36,p37,p38,p48,p49,p4a,p30; 11534 int i,j; 11535 11536 pSiS->sistvyfilter = val; 11537#ifdef SISDUALHEAD 11538 if(pSiSEnt) pSiSEnt->sistvyfilter = pSiS->sistvyfilter; 11539#endif 11540 11541 if(!(pSiS->VBFlags & CRT2_TV)) return; 11542 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 11543 if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return; 11544 11545 p35 = pSiS->p2_35; p36 = pSiS->p2_36; 11546 p37 = pSiS->p2_37; p38 = pSiS->p2_38; 11547 p48 = pSiS->p2_48; p49 = pSiS->p2_49; 11548 p4a = pSiS->p2_4a; p30 = pSiS->p2_30; 11549#ifdef SISDUALHEAD 11550 if(pSiSEnt && pSiS->DualHeadMode) { 11551 p35 = pSiSEnt->p2_35; p36 = pSiSEnt->p2_36; 11552 p37 = pSiSEnt->p2_37; p38 = pSiSEnt->p2_38; 11553 p48 = pSiSEnt->p2_48; p49 = pSiSEnt->p2_49; 11554 p4a = pSiSEnt->p2_4a; p30 = pSiSEnt->p2_30; 11555 } 11556#endif 11557 p30 &= 0x20; 11558 11559#ifdef UNLOCK_ALWAYS 11560 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11561#endif 11562 11563 switch(pSiS->sistvyfilter) { 11564 case 0: 11565 andSISIDXREG(SISPART2,0x30,0xdf); 11566 break; 11567 case 1: 11568 outSISIDXREG(SISPART2,0x35,p35); 11569 outSISIDXREG(SISPART2,0x36,p36); 11570 outSISIDXREG(SISPART2,0x37,p37); 11571 outSISIDXREG(SISPART2,0x38,p38); 11572 if(!(pSiS->VBFlags2 & VB2_301)) { 11573 outSISIDXREG(SISPART2,0x48,p48); 11574 outSISIDXREG(SISPART2,0x49,p49); 11575 outSISIDXREG(SISPART2,0x4a,p4a); 11576 } 11577 setSISIDXREG(SISPART2,0x30,0xdf,p30); 11578 break; 11579 case 2: 11580 case 3: 11581 case 4: 11582 case 5: 11583 case 6: 11584 case 7: 11585 case 8: 11586 if(!(pSiS->VBFlags & (TV_PALM | TV_PALN | TV_NTSCJ))) { 11587 int yindex301 = -1, yindex301B = -1; 11588 UChar p3d4_34; 11589 11590 inSISIDXREG(SISCR,0x34,p3d4_34); 11591 11592 switch((p3d4_34 & 0x7f)) { 11593 case 0x59: /* 320x200 */ 11594 case 0x41: 11595 case 0x4f: 11596 case 0x50: /* 320x240 */ 11597 case 0x56: 11598 case 0x53: 11599 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 0 : 4; 11600 break; 11601 case 0x2f: /* 640x400 */ 11602 case 0x5d: 11603 case 0x5e: 11604 case 0x2e: /* 640x480 */ 11605 case 0x44: 11606 case 0x62: 11607 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 1 : 5; 11608 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 0 : 4; 11609 break; 11610 case 0x31: /* 720x480 */ 11611 case 0x33: 11612 case 0x35: 11613 case 0x32: /* 720x576 */ 11614 case 0x34: 11615 case 0x36: 11616 case 0x5f: /* 768x576 */ 11617 case 0x60: 11618 case 0x61: 11619 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 2 : 6; 11620 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 1 : 5; 11621 break; 11622 case 0x51: /* 400x300 */ 11623 case 0x57: 11624 case 0x54: 11625 case 0x30: /* 800x600 */ 11626 case 0x47: 11627 case 0x63: 11628 yindex301 = (pSiS->VBFlags & TV_NTSC) ? 3 : 7; 11629 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 2 : 6; 11630 break; 11631 case 0x52: /* 512x384 */ 11632 case 0x58: 11633 case 0x5c: 11634 case 0x38: /* 1024x768 */ 11635 case 0x4a: 11636 case 0x64: 11637 yindex301B = (pSiS->VBFlags & TV_NTSC) ? 3 : 7; 11638 break; 11639 } 11640 if(pSiS->VBFlags2 & VB2_301) { 11641 if(yindex301 >= 0) { 11642 for(i=0, j=0x35; i<=3; i++, j++) { 11643 outSISIDXREG(SISPART2,j,(SiSTVFilter301[yindex301].filter[pSiS->sistvyfilter-2][i])); 11644 } 11645 } 11646 } else { 11647 if(yindex301B >= 0) { 11648 for(i=0, j=0x35; i<=3; i++, j++) { 11649 outSISIDXREG(SISPART2,j,(SiSTVFilter301B[yindex301B].filter[pSiS->sistvyfilter-2][i])); 11650 } 11651 for(i=4, j=0x48; i<=6; i++, j++) { 11652 outSISIDXREG(SISPART2,j,(SiSTVFilter301B[yindex301B].filter[pSiS->sistvyfilter-2][i])); 11653 } 11654 } 11655 } 11656 orSISIDXREG(SISPART2,0x30,0x20); 11657 } 11658 } 11659} 11660 11661int SiS_GetSISTVyfilter(ScrnInfoPtr pScrn) 11662{ 11663 SISPtr pSiS = SISPTR(pScrn); 11664#ifdef SISDUALHEAD 11665 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11666 11667 if(pSiSEnt && pSiS->DualHeadMode) 11668 return (int)pSiSEnt->sistvyfilter; 11669 else 11670#endif 11671 return (int)pSiS->sistvyfilter; 11672} 11673 11674void SiS_SetSIS6326TVantiflicker(ScrnInfoPtr pScrn, int val) 11675{ 11676 SISPtr pSiS = SISPTR(pScrn); 11677 UChar tmp; 11678 11679 pSiS->sistvantiflicker = val; 11680 11681 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 11682 11683#ifdef UNLOCK_ALWAYS 11684 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11685#endif 11686 11687 tmp = SiS6326GetTVReg(pScrn,0x00); 11688 if(!(tmp & 0x04)) return; 11689 11690 /* Valid values: 0=off, 1=low, 2=med, 3=high, 4=adaptive */ 11691 if(val >= 0 && val <= 4) { 11692 tmp &= 0x1f; 11693 tmp |= (val << 5); 11694 SiS6326SetTVReg(pScrn,0x00,tmp); 11695 } 11696} 11697 11698int SiS_GetSIS6326TVantiflicker(ScrnInfoPtr pScrn) 11699{ 11700 SISPtr pSiS = SISPTR(pScrn); 11701 UChar tmp; 11702 11703 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 11704 return (int)pSiS->sistvantiflicker; 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->sistvantiflicker; 11714 } else { 11715 return (int)((tmp >> 5) & 0x07); 11716 } 11717} 11718 11719void SiS_SetSIS6326TVenableyfilter(ScrnInfoPtr pScrn, int val) 11720{ 11721 SISPtr pSiS = SISPTR(pScrn); 11722 UChar tmp; 11723 11724 if(val) val = 1; 11725 pSiS->sis6326enableyfilter = val; 11726 11727 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 11728 11729#ifdef UNLOCK_ALWAYS 11730 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11731#endif 11732 11733 tmp = SiS6326GetTVReg(pScrn,0x00); 11734 if(!(tmp & 0x04)) return; 11735 11736 tmp = SiS6326GetTVReg(pScrn,0x43); 11737 tmp &= ~0x10; 11738 tmp |= ((val & 0x01) << 4); 11739 SiS6326SetTVReg(pScrn,0x43,tmp); 11740} 11741 11742int SiS_GetSIS6326TVenableyfilter(ScrnInfoPtr pScrn) 11743{ 11744 SISPtr pSiS = SISPTR(pScrn); 11745 UChar tmp; 11746 11747 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 11748 return (int)pSiS->sis6326enableyfilter; 11749 } 11750 11751#ifdef UNLOCK_ALWAYS 11752 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11753#endif 11754 11755 tmp = SiS6326GetTVReg(pScrn,0x00); 11756 if(!(tmp & 0x04)) { 11757 return (int)pSiS->sis6326enableyfilter; 11758 } else { 11759 tmp = SiS6326GetTVReg(pScrn,0x43); 11760 return (int)((tmp >> 4) & 0x01); 11761 } 11762} 11763 11764void SiS_SetSIS6326TVyfilterstrong(ScrnInfoPtr pScrn, int val) 11765{ 11766 SISPtr pSiS = SISPTR(pScrn); 11767 UChar tmp; 11768 11769 if(val) val = 1; 11770 pSiS->sis6326yfilterstrong = val; 11771 11772 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 11773 11774#ifdef UNLOCK_ALWAYS 11775 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11776#endif 11777 11778 tmp = SiS6326GetTVReg(pScrn,0x00); 11779 if(!(tmp & 0x04)) return; 11780 11781 tmp = SiS6326GetTVReg(pScrn,0x43); 11782 if(tmp & 0x10) { 11783 tmp &= ~0x40; 11784 tmp |= ((val & 0x01) << 6); 11785 SiS6326SetTVReg(pScrn,0x43,tmp); 11786 } 11787} 11788 11789int SiS_GetSIS6326TVyfilterstrong(ScrnInfoPtr pScrn) 11790{ 11791 SISPtr pSiS = SISPTR(pScrn); 11792 UChar tmp; 11793 11794 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 11795 return (int)pSiS->sis6326yfilterstrong; 11796 } 11797 11798#ifdef UNLOCK_ALWAYS 11799 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11800#endif 11801 11802 tmp = SiS6326GetTVReg(pScrn,0x00); 11803 if(!(tmp & 0x04)) { 11804 return (int)pSiS->sis6326yfilterstrong; 11805 } else { 11806 tmp = SiS6326GetTVReg(pScrn,0x43); 11807 if(!(tmp & 0x10)) { 11808 return (int)pSiS->sis6326yfilterstrong; 11809 } else { 11810 return (int)((tmp >> 6) & 0x01); 11811 } 11812 } 11813} 11814 11815void SiS_SetTVxposoffset(ScrnInfoPtr pScrn, int val) 11816{ 11817 SISPtr pSiS = SISPTR(pScrn); 11818#ifdef SISDUALHEAD 11819 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11820#endif 11821 11822#ifdef UNLOCK_ALWAYS 11823 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11824#endif 11825 11826 pSiS->tvxpos = val; 11827#ifdef SISDUALHEAD 11828 if(pSiSEnt) pSiSEnt->tvxpos = val; 11829#endif 11830 11831 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 11832 11833 if(pSiS->VBFlags & CRT2_TV) { 11834 11835 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 11836 11837 int x = pSiS->tvx; 11838#ifdef SISDUALHEAD 11839 if(pSiSEnt && pSiS->DualHeadMode) x = pSiSEnt->tvx; 11840#endif 11841 switch(pSiS->ChrontelType) { 11842 case CHRONTEL_700x: 11843 if((val >= -32) && (val <= 32)) { 11844 x += val; 11845 if(x < 0) x = 0; 11846 SiS_SetCH700x(pSiS->SiS_Pr, 0x0a, (x & 0xff)); 11847 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD); 11848 } 11849 break; 11850 case CHRONTEL_701x: 11851 /* Not supported by hardware */ 11852 break; 11853 } 11854 11855 } else if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 11856 11857 if((val >= -32) && (val <= 32)) { 11858 11859 UChar p2_1f,p2_20,p2_2b,p2_42,p2_43; 11860 UShort temp; 11861 int mult; 11862 11863 p2_1f = pSiS->p2_1f; 11864 p2_20 = pSiS->p2_20; 11865 p2_2b = pSiS->p2_2b; 11866 p2_42 = pSiS->p2_42; 11867 p2_43 = pSiS->p2_43; 11868#ifdef SISDUALHEAD 11869 if(pSiSEnt && pSiS->DualHeadMode) { 11870 p2_1f = pSiSEnt->p2_1f; 11871 p2_20 = pSiSEnt->p2_20; 11872 p2_2b = pSiSEnt->p2_2b; 11873 p2_42 = pSiSEnt->p2_42; 11874 p2_43 = pSiSEnt->p2_43; 11875 } 11876#endif 11877 mult = 2; 11878 if(pSiS->VBFlags & TV_YPBPR) { 11879 if(pSiS->VBFlags & (TV_YPBPR1080I | TV_YPBPR750P)) { 11880 mult = 4; 11881 } 11882 } 11883 11884 temp = p2_1f | ((p2_20 & 0xf0) << 4); 11885 temp += (val * mult); 11886 p2_1f = temp & 0xff; 11887 p2_20 = (temp & 0xf00) >> 4; 11888 p2_2b = ((p2_2b & 0x0f) + (val * mult)) & 0x0f; 11889 temp = p2_43 | ((p2_42 & 0xf0) << 4); 11890 temp += (val * mult); 11891 p2_43 = temp & 0xff; 11892 p2_42 = (temp & 0xf00) >> 4; 11893 SISWaitRetraceCRT2(pScrn); 11894 outSISIDXREG(SISPART2,0x1f,p2_1f); 11895 setSISIDXREG(SISPART2,0x20,0x0F,p2_20); 11896 setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b); 11897 setSISIDXREG(SISPART2,0x42,0x0F,p2_42); 11898 outSISIDXREG(SISPART2,0x43,p2_43); 11899 } 11900 } 11901 } 11902 11903 } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { 11904 11905 if(pSiS->SiS6326Flags & SIS6326_TVDETECTED) { 11906 11907 UChar tmp; 11908 UShort temp1, temp2, temp3; 11909 11910 tmp = SiS6326GetTVReg(pScrn,0x00); 11911 if(tmp & 0x04) { 11912 11913 temp1 = pSiS->tvx1; 11914 temp2 = pSiS->tvx2; 11915 temp3 = pSiS->tvx3; 11916 if((val >= -16) && (val <= 16)) { 11917 if(val > 0) { 11918 temp1 += (val * 4); 11919 temp2 += (val * 4); 11920 while((temp1 > 0x0fff) || (temp2 > 0x0fff)) { 11921 temp1 -= 4; 11922 temp2 -= 4; 11923 } 11924 } else { 11925 val = -val; 11926 temp3 += (val * 4); 11927 while(temp3 > 0x03ff) { 11928 temp3 -= 4; 11929 } 11930 } 11931 } 11932 SiS6326SetTVReg(pScrn,0x3a,(temp1 & 0xff)); 11933 tmp = SiS6326GetTVReg(pScrn,0x3c); 11934 tmp &= 0xf0; 11935 tmp |= ((temp1 & 0x0f00) >> 8); 11936 SiS6326SetTVReg(pScrn,0x3c,tmp); 11937 SiS6326SetTVReg(pScrn,0x26,(temp2 & 0xff)); 11938 tmp = SiS6326GetTVReg(pScrn,0x27); 11939 tmp &= 0x0f; 11940 tmp |= ((temp2 & 0x0f00) >> 4); 11941 SiS6326SetTVReg(pScrn,0x27,tmp); 11942 SiS6326SetTVReg(pScrn,0x12,(temp3 & 0xff)); 11943 tmp = SiS6326GetTVReg(pScrn,0x13); 11944 tmp &= ~0xC0; 11945 tmp |= ((temp3 & 0x0300) >> 2); 11946 SiS6326SetTVReg(pScrn,0x13,tmp); 11947 } 11948 } 11949 } 11950} 11951 11952int SiS_GetTVxposoffset(ScrnInfoPtr pScrn) 11953{ 11954 SISPtr pSiS = SISPTR(pScrn); 11955#ifdef SISDUALHEAD 11956 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11957 11958 if(pSiSEnt && pSiS->DualHeadMode) 11959 return (int)pSiSEnt->tvxpos; 11960 else 11961#endif 11962 return (int)pSiS->tvxpos; 11963} 11964 11965void SiS_SetTVyposoffset(ScrnInfoPtr pScrn, int val) 11966{ 11967 SISPtr pSiS = SISPTR(pScrn); 11968#ifdef SISDUALHEAD 11969 SISEntPtr pSiSEnt = pSiS->entityPrivate; 11970#endif 11971 11972#ifdef UNLOCK_ALWAYS 11973 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 11974#endif 11975 11976 pSiS->tvypos = val; 11977#ifdef SISDUALHEAD 11978 if(pSiSEnt) pSiSEnt->tvypos = val; 11979#endif 11980 11981 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 11982 11983 if(pSiS->VBFlags & CRT2_TV) { 11984 11985 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 11986 11987 int y = pSiS->tvy; 11988#ifdef SISDUALHEAD 11989 if(pSiSEnt && pSiS->DualHeadMode) y = pSiSEnt->tvy; 11990#endif 11991 switch(pSiS->ChrontelType) { 11992 case CHRONTEL_700x: 11993 if((val >= -32) && (val <= 32)) { 11994 y -= val; 11995 if(y < 0) y = 0; 11996 SiS_SetCH700x(pSiS->SiS_Pr, 0x0b, (y & 0xff)); 11997 SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE); 11998 } 11999 break; 12000 case CHRONTEL_701x: 12001 /* Not supported by hardware */ 12002 break; 12003 } 12004 12005 } else if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 12006 12007 if((val >= -32) && (val <= 32)) { 12008 char p2_01, p2_02; 12009 12010 if( (pSiS->VBFlags & TV_HIVISION) || 12011 ((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & (TV_YPBPR1080I|TV_YPBPR750P))) ) { 12012 val *= 2; 12013 } else { 12014 val /= 2; /* 4 */ 12015 } 12016 12017 p2_01 = pSiS->p2_01; 12018 p2_02 = pSiS->p2_02; 12019#ifdef SISDUALHEAD 12020 if(pSiSEnt && pSiS->DualHeadMode) { 12021 p2_01 = pSiSEnt->p2_01; 12022 p2_02 = pSiSEnt->p2_02; 12023 } 12024#endif 12025 p2_01 += val; /* val * 2 */ 12026 p2_02 += val; /* val * 2 */ 12027 if(!(pSiS->VBFlags & (TV_YPBPR | TV_HIVISION))) { 12028 while((p2_01 <= 0) || (p2_02 <= 0)) { 12029 p2_01 += 2; 12030 p2_02 += 2; 12031 } 12032 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR1080I)) { 12033 while(p2_01 <= 8) { 12034 p2_01 += 2; 12035 p2_02 += 2; 12036 } 12037 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR750P)) { 12038 while(p2_01 <= 10) { 12039 p2_01 += 2; 12040 p2_02 += 2; 12041 } 12042 } 12043 12044 SISWaitRetraceCRT2(pScrn); 12045 outSISIDXREG(SISPART2,0x01,p2_01); 12046 outSISIDXREG(SISPART2,0x02,p2_02); 12047 } 12048 } 12049 12050 } 12051 12052 } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { 12053 12054 if(pSiS->SiS6326Flags & SIS6326_TVDETECTED) { 12055 12056 UChar tmp; 12057 int temp1, limit; 12058 12059 tmp = SiS6326GetTVReg(pScrn,0x00); 12060 if(tmp & 0x04) { 12061 12062 if((val >= -16) && (val <= 16)) { 12063 temp1 = (UShort)pSiS->tvy1; 12064 limit = (pSiS->SiS6326Flags & SIS6326_TVPAL) ? 625 : 525; 12065 if(val > 0) { 12066 temp1 += (val * 4); 12067 if(temp1 > limit) temp1 -= limit; 12068 } else { 12069 val = -val; 12070 temp1 -= (val * 2); 12071 if(temp1 <= 0) temp1 += (limit -1); 12072 } 12073 SiS6326SetTVReg(pScrn,0x11,(temp1 & 0xff)); 12074 tmp = SiS6326GetTVReg(pScrn,0x13); 12075 tmp &= ~0x30; 12076 tmp |= ((temp1 & 0x300) >> 4); 12077 SiS6326SetTVReg(pScrn,0x13,tmp); 12078 if(temp1 == 1) tmp = 0x10; 12079 else { 12080 if(pSiS->SiS6326Flags & SIS6326_TVPAL) { 12081 if((temp1 <= 3) || (temp1 >= (limit - 2))) tmp = 0x08; 12082 else if(temp1 < 22) tmp = 0x02; 12083 else tmp = 0x04; 12084 } else { 12085 if((temp1 <= 5) || (temp1 >= (limit - 4))) tmp = 0x08; 12086 else if(temp1 < 19) tmp = 0x02; 12087 else tmp = 0x04; 12088 } 12089 } 12090 SiS6326SetTVReg(pScrn,0x21,tmp); 12091 } 12092 } 12093 } 12094 } 12095} 12096 12097int SiS_GetTVyposoffset(ScrnInfoPtr pScrn) 12098{ 12099 SISPtr pSiS = SISPTR(pScrn); 12100#ifdef SISDUALHEAD 12101 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12102 12103 if(pSiSEnt && pSiS->DualHeadMode) 12104 return (int)pSiSEnt->tvypos; 12105 else 12106#endif 12107 return (int)pSiS->tvypos; 12108} 12109 12110void SiS_SetTVxscale(ScrnInfoPtr pScrn, int val) 12111{ 12112 SISPtr pSiS = SISPTR(pScrn); 12113#ifdef SISDUALHEAD 12114 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12115#endif 12116 12117#ifdef UNLOCK_ALWAYS 12118 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12119#endif 12120 12121 pSiS->tvxscale = val; 12122#ifdef SISDUALHEAD 12123 if(pSiSEnt) pSiSEnt->tvxscale = val; 12124#endif 12125 12126 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 12127 12128 if((pSiS->VBFlags & CRT2_TV) && (pSiS->VBFlags2 & VB2_SISBRIDGE)) { 12129 12130 if((val >= -16) && (val <= 16)) { 12131 12132 UChar p2_44,p2_45,p2_46; 12133 int scalingfactor, mult; 12134 12135 p2_44 = pSiS->p2_44; 12136 p2_45 = pSiS->p2_45 & 0x3f; 12137 p2_46 = pSiS->p2_46 & 0x07; 12138#ifdef SISDUALHEAD 12139 if(pSiSEnt && pSiS->DualHeadMode) { 12140 p2_44 = pSiSEnt->p2_44; 12141 p2_45 = pSiSEnt->p2_45 & 0x3f; 12142 p2_46 = pSiSEnt->p2_46 & 0x07; 12143 } 12144#endif 12145 scalingfactor = (p2_46 << 13) | ((p2_45 & 0x1f) << 8) | p2_44; 12146 12147 mult = 64; 12148 if(pSiS->VBFlags & TV_YPBPR) { 12149 if(pSiS->VBFlags & TV_YPBPR1080I) { 12150 mult = 190; 12151 } else if(pSiS->VBFlags & TV_YPBPR750P) { 12152 mult = 360; 12153 } 12154 } else if(pSiS->VBFlags & TV_HIVISION) { 12155 mult = 190; 12156 } 12157 12158 if(val < 0) { 12159 p2_45 &= 0xdf; 12160 scalingfactor += ((-val) * mult); 12161 if(scalingfactor > 0xffff) scalingfactor = 0xffff; 12162 } else if(val > 0) { 12163 p2_45 &= 0xdf; 12164 scalingfactor -= (val * mult); 12165 if(scalingfactor < 1) scalingfactor = 1; 12166 } 12167 12168 p2_44 = scalingfactor & 0xff; 12169 p2_45 &= 0xe0; 12170 p2_45 |= ((scalingfactor >> 8) & 0x1f); 12171 p2_46 = ((scalingfactor >> 13) & 0x07); 12172 12173 SISWaitRetraceCRT2(pScrn); 12174 outSISIDXREG(SISPART2,0x44,p2_44); 12175 setSISIDXREG(SISPART2,0x45,0xC0,p2_45); 12176 if(!(pSiS->VBFlags2 & VB2_301)) { 12177 setSISIDXREG(SISPART2,0x46,0xF8,p2_46); 12178 } 12179 12180 } 12181 12182 } 12183 12184 } 12185} 12186 12187int SiS_GetTVxscale(ScrnInfoPtr pScrn) 12188{ 12189 SISPtr pSiS = SISPTR(pScrn); 12190#ifdef SISDUALHEAD 12191 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12192 12193 if(pSiSEnt && pSiS->DualHeadMode) 12194 return (int)pSiSEnt->tvxscale; 12195 else 12196#endif 12197 return (int)pSiS->tvxscale; 12198} 12199 12200void SiS_SetTVyscale(ScrnInfoPtr pScrn, int val) 12201{ 12202 SISPtr pSiS = SISPTR(pScrn); 12203#ifdef SISDUALHEAD 12204 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12205#endif 12206 12207#ifdef UNLOCK_ALWAYS 12208 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12209#endif 12210 12211 if(val < -4) val = -4; 12212 if(val > 3) val = 3; 12213 12214 pSiS->tvyscale = val; 12215#ifdef SISDUALHEAD 12216 if(pSiSEnt) pSiSEnt->tvyscale = val; 12217#endif 12218 12219 if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 12220 12221 if((pSiS->VBFlags & CRT2_TV) && (pSiS->VBFlags2 & VB2_SISBRIDGE)) { 12222 12223 int srindex = -1, newvde, i = 0, j, vlimit, temp, vdediv; 12224 int hdclk = 0; 12225 UChar p3d4_34; 12226 Bool found = FALSE; 12227 Bool usentsc = FALSE; 12228 Bool is750p = FALSE; 12229 Bool is1080i = FALSE; 12230 Bool skipmoveup = FALSE; 12231 12232 SiS_UnLockCRT2(pSiS->SiS_Pr); 12233 12234 if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR525P)) { 12235 vlimit = 525 - 7; 12236 vdediv = 1; 12237 usentsc = TRUE; 12238 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR625P)) { 12239 vlimit = 625 - 7; 12240 vdediv = 1; 12241 } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR750P)) { 12242 vlimit = 750 - 7; 12243 vdediv = 1; 12244 is750p = TRUE; 12245 } else if(((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR1080I)) || 12246 (pSiS->VBFlags & TV_HIVISION)) { 12247 vlimit = (1125 - 7) / 2; 12248 vdediv = 2; 12249 is1080i = TRUE; 12250 } else { 12251 if( ((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR525I)) || 12252 ((!(pSiS->VBFlags & TV_YPBPR)) && (pSiS->VBFlags & (TV_NTSC | TV_PALM))) ) { 12253 usentsc = TRUE; 12254 } 12255 vlimit = usentsc ? 259 : 309; 12256 vdediv = 2; 12257 } 12258 12259 inSISIDXREG(SISCR,0x34,p3d4_34); 12260 12261 switch((p3d4_34 & 0x7f)) { 12262 case 0x50: /* 320x240 */ 12263 case 0x56: 12264 case 0x53: 12265 hdclk = 1; 12266 /* fall through */ 12267 case 0x2e: /* 640x480 */ 12268 case 0x44: 12269 case 0x62: 12270 if(is1080i) { 12271 srindex = 98; 12272 } else if(is750p) { 12273 srindex = 42; 12274 } else { 12275 srindex = usentsc ? 0 : 21; 12276 } 12277 break; 12278 case 0x31: /* 720x480 */ 12279 case 0x33: 12280 case 0x35: 12281 if(is1080i) { 12282 /* n/a */ 12283 } else if(is750p) { 12284 srindex = 49; 12285 } else { 12286 srindex = usentsc ? 7 : 21; 12287 } 12288 break; 12289 case 0x32: /* 720x576 */ 12290 case 0x34: 12291 case 0x36: 12292 case 0x5f: /* 768x576 */ 12293 case 0x60: 12294 case 0x61: 12295 if(is1080i) { 12296 /* n/a */ 12297 } else if(is750p) { 12298 srindex = 56; 12299 } else { 12300 srindex = usentsc ? 147 : 28; 12301 } 12302 break; 12303 case 0x70: /* 800x480 */ 12304 case 0x7a: 12305 case 0x76: 12306 if(is1080i) { 12307 srindex = 105; 12308 } else if(is750p) { 12309 srindex = 63; 12310 } else { 12311 srindex = usentsc ? 175 : 21; 12312 } 12313 break; 12314 case 0x51: /* 400x300 - hdclk mode */ 12315 case 0x57: 12316 case 0x54: 12317 hdclk = 1; 12318 /* fall through */ 12319 case 0x30: /* 800x600 */ 12320 case 0x47: 12321 case 0x63: 12322 if(is1080i) { 12323 srindex = 112; 12324 } else if(is750p) { 12325 srindex = 70; 12326 } else { 12327 srindex = usentsc ? 14 : 35; 12328 } 12329 break; 12330 case 0x1d: /* 960x540 */ 12331 case 0x1e: 12332 case 0x1f: 12333 if(is1080i) { 12334 srindex = 196; 12335 skipmoveup = TRUE; 12336 } 12337 break; 12338 case 0x20: /* 960x600 */ 12339 case 0x21: 12340 case 0x22: 12341 if(pSiS->VGAEngine == SIS_315_VGA && is1080i) { 12342 srindex = 203; 12343 } 12344 break; 12345 case 0x71: /* 1024x576 */ 12346 case 0x74: 12347 case 0x77: 12348 if(is1080i) { 12349 srindex = 119; 12350 } else if(is750p) { 12351 srindex = 77; 12352 } else { 12353 srindex = usentsc ? 182 : 189; 12354 } 12355 break; 12356 case 0x52: /* 512x384 */ 12357 case 0x58: 12358 case 0x5c: 12359 hdclk = 1; 12360 /* fall through */ 12361 case 0x38: /* 1024x768 */ 12362 case 0x4a: 12363 case 0x64: 12364 if(is1080i) { 12365 srindex = 126; 12366 } else if(is750p) { 12367 srindex = 84; 12368 } else if(!usentsc) { 12369 srindex = 154; 12370 } else if(vdediv == 1) { 12371 if(!hdclk) srindex = 168; 12372 } else { 12373 if(!hdclk) srindex = 161; 12374 } 12375 break; 12376 case 0x79: /* 1280x720 */ 12377 case 0x75: 12378 case 0x78: 12379 if(is1080i) { 12380 srindex = 133; 12381 } else if(is750p) { 12382 srindex = 91; 12383 } 12384 break; 12385 case 0x3a: /* 1280x1024 */ 12386 case 0x4d: 12387 case 0x65: 12388 if(is1080i) { 12389 srindex = 140; 12390 } 12391 break; 12392 } 12393 12394 if(srindex < 0) return; 12395 12396 if(pSiS->tvyscale != 0) { 12397 for(j = 0; j <= 1; j++) { 12398 for(i = 0; i <= 6; i++) { 12399 if(SiSTVVScale[srindex+i].sindex == pSiS->tvyscale) { 12400 found = TRUE; 12401 break; 12402 } 12403 } 12404 if(found) break; 12405 if(pSiS->tvyscale > 0) pSiS->tvyscale--; 12406 else pSiS->tvyscale++; 12407 } 12408 } 12409 12410#ifdef SISDUALHEAD 12411 if(pSiSEnt) pSiSEnt->tvyscale = pSiS->tvyscale; 12412#endif 12413 12414 if(pSiS->tvyscale == 0) { 12415 UChar p2_0a = pSiS->p2_0a; 12416 UChar p2_2f = pSiS->p2_2f; 12417 UChar p2_30 = pSiS->p2_30; 12418 UChar p2_46 = pSiS->p2_46; 12419 UChar p2_47 = pSiS->p2_47; 12420 UChar p1scaling[9], p4scaling[9]; 12421 UChar *p2scaling; 12422 12423 for(i = 0; i < 9; i++) { 12424 p1scaling[i] = pSiS->scalingp1[i]; 12425 p4scaling[i] = pSiS->scalingp4[i]; 12426 } 12427 p2scaling = &pSiS->scalingp2[0]; 12428 12429#ifdef SISDUALHEAD 12430 if(pSiSEnt && pSiS->DualHeadMode) { 12431 p2_0a = pSiSEnt->p2_0a; 12432 p2_2f = pSiSEnt->p2_2f; 12433 p2_30 = pSiSEnt->p2_30; 12434 p2_46 = pSiSEnt->p2_46; 12435 p2_47 = pSiSEnt->p2_47; 12436 for(i = 0; i < 9; i++) { 12437 p1scaling[i] = pSiSEnt->scalingp1[i]; 12438 p4scaling[i] = pSiSEnt->scalingp4[i]; 12439 } 12440 p2scaling = &pSiSEnt->scalingp2[0]; 12441 } 12442#endif 12443 SISWaitRetraceCRT2(pScrn); 12444 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 12445 for(i = 0; i < 64; i++) { 12446 outSISIDXREG(SISPART2,(0xc0 + i),p2scaling[i]); 12447 } 12448 } 12449 for(i = 0; i < 9; i++) { 12450 outSISIDXREG(SISPART1,SiSScalingP1Regs[i],p1scaling[i]); 12451 } 12452 for(i = 0; i < 9; i++) { 12453 outSISIDXREG(SISPART4,SiSScalingP4Regs[i],p4scaling[i]); 12454 } 12455 12456 setSISIDXREG(SISPART2,0x0a,0x7f,(p2_0a & 0x80)); 12457 outSISIDXREG(SISPART2,0x2f,p2_2f); 12458 setSISIDXREG(SISPART2,0x30,0x3f,(p2_30 & 0xc0)); 12459 if(!(pSiS->VBFlags2 & VB2_301)) { 12460 setSISIDXREG(SISPART2,0x46,0x9f,(p2_46 & 0x60)); 12461 outSISIDXREG(SISPART2,0x47,p2_47); 12462 } 12463 12464 } else { 12465 12466 int realvde, myypos, watchdog = 32; 12467 unsigned short temp1, temp2, vgahde, vgaht, vgavt; 12468 int p1div = 1; 12469 ULong calctemp; 12470 12471 srindex += i; 12472 newvde = SiSTVVScale[srindex].ScaleVDE; 12473 realvde = SiSTVVScale[srindex].RealVDE; 12474 12475 if(vdediv == 1) p1div = 2; 12476 12477 if(!skipmoveup) { 12478 do { 12479 inSISIDXREG(SISPART2,0x01,temp); 12480 temp = vlimit - ((temp & 0x7f) / p1div); 12481 if((temp - (((newvde / vdediv) - 2) + 9)) > 0) break; 12482 myypos = pSiS->tvypos - 1; 12483#ifdef SISDUALHEAD 12484 if(pSiSEnt && pSiS->DualHeadMode) myypos = pSiSEnt->tvypos - 1; 12485#endif 12486 SiS_SetTVyposoffset(pScrn, myypos); 12487 } while(watchdog--); 12488 } 12489 12490 SISWaitRetraceCRT2(pScrn); 12491 12492 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 12493 SiS_CalcXTapScaler(pSiS->SiS_Pr, realvde, newvde, 4, FALSE); 12494 } 12495 12496 if(!(pSiS->VBFlags2 & VB2_301)) { 12497 temp = (newvde / vdediv) - 3; 12498 setSISIDXREG(SISPART2,0x46,0x9f,((temp & 0x0300) >> 3)); 12499 outSISIDXREG(SISPART2,0x47,(temp & 0xff)); 12500 } 12501 12502 inSISIDXREG(SISPART1,0x0a,temp1); 12503 inSISIDXREG(SISPART1,0x0c,temp2); 12504 vgahde = ((temp2 & 0xf0) << 4) | temp1; 12505 if(pSiS->VGAEngine == SIS_300_VGA) { 12506 vgahde -= 12; 12507 } else { 12508 vgahde -= 16; 12509 if(hdclk) vgahde <<= 1; 12510 } 12511 12512 vgaht = SiSTVVScale[srindex].reg[0]; 12513 temp1 = vgaht; 12514 if((pSiS->VGAEngine == SIS_315_VGA) && hdclk) temp1 >>= 1; 12515 temp1--; 12516 outSISIDXREG(SISPART1,0x08,(temp1 & 0xff)); 12517 setSISIDXREG(SISPART1,0x09,0x0f,((temp1 >> 4) & 0xf0)); 12518 12519 temp2 = (vgaht - vgahde) >> 2; 12520 if(pSiS->VGAEngine == SIS_300_VGA) { 12521 temp1 = vgahde + 12 + temp2; 12522 temp2 = temp1 + (temp2 << 1); 12523 } else { 12524 temp1 = vgahde; 12525 if(hdclk) { 12526 temp1 >>= 1; 12527 temp2 >>= 1; 12528 } 12529 temp2 >>= 1; 12530 temp1 = temp1 + 16 + temp2; 12531 temp2 = temp1 + temp2; 12532 } 12533 outSISIDXREG(SISPART1,0x0b,(temp1 & 0xff)); 12534 setSISIDXREG(SISPART1,0x0c,0xf0,((temp1 >> 8) & 0x0f)); 12535 outSISIDXREG(SISPART1,0x0d,(temp2 & 0xff)); 12536 12537 vgavt = SiSTVVScale[srindex].reg[1]; 12538 temp1 = vgavt - 1; 12539 if(pSiS->VGAEngine == SIS_315_VGA) temp1--; 12540 outSISIDXREG(SISPART1,0x0e,(temp1 & 0xff)); 12541 setSISIDXREG(SISPART1,0x12,0xf8,((temp1 >> 8 ) & 0x07)); 12542 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->ChipType >= SIS_661)) { 12543 temp1 = (vgavt + SiSTVVScale[srindex].RealVDE) >> 1; 12544 temp2 = ((vgavt - SiSTVVScale[srindex].RealVDE) >> 4) + temp1 + 1; 12545 } else { 12546 temp1 = (vgavt - SiSTVVScale[srindex].RealVDE) >> 2; 12547 temp2 = (temp1 < 4) ? 4 : temp1; 12548 temp1 += SiSTVVScale[srindex].RealVDE; 12549 temp2 = (temp2 >> 2) + temp1 + 1; 12550 } 12551 outSISIDXREG(SISPART1,0x10,(temp1 & 0xff)); 12552 setSISIDXREG(SISPART1,0x11,0x8f,((temp1 >> 4) & 0x70)); 12553 setSISIDXREG(SISPART1,0x11,0xf0,(temp2 & 0x0f)); 12554 12555 setSISIDXREG(SISPART2,0x0a,0x7f,((SiSTVVScale[srindex].reg[2] >> 8) & 0x80)); 12556 outSISIDXREG(SISPART2,0x2f,((newvde / vdediv) - 2)); 12557 setSISIDXREG(SISPART2,0x30,0x3f,((((newvde / vdediv) - 2) >> 2) & 0xc0)); 12558 12559 outSISIDXREG(SISPART4,0x13,(SiSTVVScale[srindex].reg[2] & 0xff)); 12560 outSISIDXREG(SISPART4,0x14,(SiSTVVScale[srindex].reg[3] & 0xff)); 12561 setSISIDXREG(SISPART4,0x15,0x7f,((SiSTVVScale[srindex].reg[3] >> 1) & 0x80)); 12562 12563 temp1 = vgaht - 1; 12564 outSISIDXREG(SISPART4,0x16,(temp1 & 0xff)); 12565 setSISIDXREG(SISPART4,0x15,0x87,((temp1 >> 5) & 0x78)); 12566 12567 temp1 = vgavt - 1; 12568 outSISIDXREG(SISPART4,0x17,(temp1 & 0xff)); 12569 setSISIDXREG(SISPART4,0x15,0xf8,((temp1 >> 8) & 0x07)); 12570 12571 outSISIDXREG(SISPART4,0x18,0x00); 12572 setSISIDXREG(SISPART4,0x19,0xf0,0x00); 12573 12574 inSISIDXREG(SISPART4,0x0e,temp1); 12575 if(is1080i) { 12576 if(!(temp1 & 0xe0)) newvde >>= 1; 12577 } 12578 12579 temp = 0x40; 12580 if(realvde <= newvde) temp = 0; 12581 else realvde -= newvde; 12582 12583 calctemp = (realvde * 256 * 1024) / newvde; 12584 if((realvde * 256 * 1024) % newvde) calctemp++; 12585 outSISIDXREG(SISPART4,0x1b,(calctemp & 0xff)); 12586 outSISIDXREG(SISPART4,0x1a,((calctemp >> 8) & 0xff)); 12587 setSISIDXREG(SISPART4,0x19,0x8f,(((calctemp >> 12) & 0x70) | temp)); 12588 } 12589 12590 } 12591 12592 } 12593} 12594 12595int SiS_GetTVyscale(ScrnInfoPtr pScrn) 12596{ 12597 SISPtr pSiS = SISPTR(pScrn); 12598#ifdef SISDUALHEAD 12599 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12600 12601 if(pSiSEnt && pSiS->DualHeadMode) 12602 return (int)pSiSEnt->tvyscale; 12603 else 12604#endif 12605 return (int)pSiS->tvyscale; 12606} 12607 12608void SiS_SetSISCRT1SaturationGain(ScrnInfoPtr pScrn, int val) 12609{ 12610 SISPtr pSiS = SISPTR(pScrn); 12611#ifdef SISDUALHEAD 12612 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12613#endif 12614 12615 pSiS->siscrt1satgain = val; 12616#ifdef SISDUALHEAD 12617 if(pSiSEnt) pSiSEnt->siscrt1satgain = val; 12618#endif 12619 12620 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_CRT1SATGAIN)) return; 12621 12622#ifdef UNLOCK_ALWAYS 12623 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12624#endif 12625 12626 if((val >= 0) && (val <= 7)) { 12627 setSISIDXREG(SISCR,0x53,0xE3, (val << 2)); 12628 } 12629} 12630 12631int SiS_GetSISCRT1SaturationGain(ScrnInfoPtr pScrn) 12632{ 12633 SISPtr pSiS = SISPTR(pScrn); 12634 int result = pSiS->siscrt1satgain; 12635 UChar temp; 12636#ifdef SISDUALHEAD 12637 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12638 12639 if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->siscrt1satgain; 12640#endif 12641 12642 if(!(pSiS->SiS_SD3_Flags & SiS_SD3_CRT1SATGAIN)) return result; 12643 12644#ifdef UNLOCK_ALWAYS 12645 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12646#endif 12647 inSISIDXREG(SISCR, 0x53, temp); 12648 return (int)((temp >> 2) & 0x07); 12649} 12650 12651/* Calc dotclock from registers */ 12652static int 12653SiSGetClockFromRegs(UChar sr2b, UChar sr2c) 12654{ 12655 float num, denum, postscalar, divider; 12656 int myclock; 12657 12658 divider = (sr2b & 0x80) ? 2.0 : 1.0; 12659 postscalar = (sr2c & 0x80) ? 12660 ( (((sr2c >> 5) & 0x03) == 0x02) ? 6.0 : 8.0 ) : 12661 ( ((sr2c >> 5) & 0x03) + 1.0 ); 12662 num = (sr2b & 0x7f) + 1.0; 12663 denum = (sr2c & 0x1f) + 1.0; 12664 myclock = (int)((14318 * (divider / postscalar) * (num / denum)) / 1000); 12665 return myclock; 12666} 12667 12668#ifdef SISDUALHEAD 12669static void 12670SiS_SetDHFlags(SISPtr pSiS, unsigned int misc, unsigned int sd2) 12671{ 12672 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12673 12674 if(pSiS->DualHeadMode) { 12675 if(pSiSEnt->pScrn_1) { 12676 SISPTR(pSiSEnt->pScrn_1)->MiscFlags |= misc; 12677 SISPTR(pSiSEnt->pScrn_1)->SiS_SD2_Flags |= sd2; 12678 } 12679 if(pSiSEnt->pScrn_2) { 12680 SISPTR(pSiSEnt->pScrn_2)->MiscFlags |= misc; 12681 SISPTR(pSiSEnt->pScrn_2)->SiS_SD2_Flags |= sd2; 12682 } 12683 } 12684} 12685#endif 12686 12687/* PostSetMode: 12688 * -) Disable CRT1 for saving bandwidth. This doesn't work with VESA; 12689 * VESA uses the bridge in SlaveMode and switching CRT1 off while 12690 * the bridge is in SlaveMode not that clever... 12691 * -) Check if overlay can be used (depending on dotclock) 12692 * -) Check if Panel Scaler is active on LVDS for overlay re-scaling 12693 * -) Save TV registers for further processing 12694 * -) Apply TV settings 12695 */ 12696static void 12697SiSPostSetMode(ScrnInfoPtr pScrn, SISRegPtr sisReg) 12698{ 12699 SISPtr pSiS = SISPTR(pScrn); 12700#ifdef SISDUALHEAD 12701 SISEntPtr pSiSEnt = pSiS->entityPrivate; 12702#endif 12703 UChar usScratchCR17, sr2b, sr2c, tmpreg; 12704 int myclock1, myclock2, mycoldepth1, mycoldepth2, temp; 12705 Bool flag = FALSE; 12706 Bool doit = TRUE; 12707 Bool IsInSlaveMode; 12708 12709#ifdef TWDEBUG 12710 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 12711 "CRT1off is %d\n", pSiS->CRT1off); 12712#endif 12713 pSiS->CRT1isoff = pSiS->CRT1off; 12714 12715#ifdef UNLOCK_ALWAYS 12716 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 12717#endif 12718 12719 SiSFixupSR11(pScrn); 12720 12721 IsInSlaveMode = SiSBridgeIsInSlaveMode(pScrn); 12722 12723 if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE)) { 12724 12725 if(pSiS->VBFlags != pSiS->VBFlags_backup) { 12726 pSiS->VBFlags = pSiS->VBFlags_backup; 12727 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 12728 "VBFlags restored to %0x\n", pSiS->VBFlags); 12729 } 12730 12731 /* -) We can't switch off CRT1 if bridge is in SlaveMode. 12732 * -) If we change to a SlaveMode-Mode (like 512x384), we 12733 * need to adapt VBFlags for eg. Xv. 12734 */ 12735#ifdef SISDUALHEAD 12736 if(!pSiS->DualHeadMode) { 12737#endif 12738 if(IsInSlaveMode) { 12739 doit = FALSE; 12740 temp = pSiS->VBFlags; 12741 pSiS->VBFlags &= (~VB_DISPMODE_SINGLE); 12742 pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_DISP1); 12743 if(temp != pSiS->VBFlags) { 12744 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 12745 "VBFlags changed to 0x%0x\n", pSiS->VBFlags); 12746 } 12747 } 12748#ifdef SISDUALHEAD 12749 } 12750#endif 12751 12752 if(pSiS->VGAEngine == SIS_315_VGA) { 12753 12754 if((pSiS->CRT1off) && (doit)) { 12755 orSISIDXREG(SISCR,pSiS->myCR63,0x40); 12756 orSISIDXREG(SISSR,0x1f,0xc0); 12757 andSISIDXREG(SISSR,0x07,~0x10); 12758 andSISIDXREG(SISSR,0x06,0xe2); 12759 andSISIDXREG(SISSR,0x31,0xcf); 12760 outSISIDXREG(SISSR,0x2b,0x1b); 12761 outSISIDXREG(SISSR,0x2c,0xe1); 12762 outSISIDXREG(SISSR,0x2d,0x01); 12763 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 12764 usleep(10000); 12765 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 12766 } else { 12767 andSISIDXREG(SISCR,pSiS->myCR63,0xBF); 12768 andSISIDXREG(SISSR,0x1f,0x3f); 12769 orSISIDXREG(SISSR,0x07,0x10); 12770 } 12771 12772 } else { 12773 12774 if(doit) { 12775 inSISIDXREG(SISCR, 0x17, usScratchCR17); 12776 if(pSiS->CRT1off) { 12777 if(usScratchCR17 & 0x80) { 12778 flag = TRUE; 12779 usScratchCR17 &= ~0x80; 12780 } 12781 orSISIDXREG(SISSR,0x1f,0xc0); 12782 } else { 12783 if(!(usScratchCR17 & 0x80)) { 12784 flag = TRUE; 12785 usScratchCR17 |= 0x80; 12786 } 12787 andSISIDXREG(SISSR,0x1f,0x3f); 12788 } 12789 /* Reset only if status changed */ 12790 if(flag) { 12791 outSISIDXREG(SISCR, 0x17, usScratchCR17); 12792 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 12793 usleep(10000); 12794 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 12795 } 12796 } 12797 } 12798 12799 } 12800 12801 /* Set bridge to "disable CRT2" mode if CRT2 is disabled, LCD-A is enabled */ 12802 /* (Not needed for CRT1=VGA since CRT2 will really be disabled then) */ 12803#ifdef SISDUALHEAD 12804 if(!pSiS->DualHeadMode) { 12805#endif 12806 if((pSiS->VGAEngine == SIS_315_VGA) && (pSiS->VBFlags2 & VB2_SISLCDABRIDGE)) { 12807 if((!pSiS->UseVESA) && (!(pSiS->VBFlags & CRT2_ENABLE)) && (pSiS->VBFlags & CRT1_LCDA)) { 12808 if(!IsInSlaveMode) { 12809 andSISIDXREG(SISPART4,0x0d,~0x07); 12810 } 12811 } 12812 } 12813#ifdef SISDUALHEAD 12814 } 12815#endif 12816 12817 /* Reset flags */ 12818 pSiS->MiscFlags &= ~( MISC_CRT1OVERLAY | 12819 MISC_CRT2OVERLAY | 12820 MISC_CRT1OVERLAYGAMMA | 12821 MISC_SIS760ONEOVERLAY | 12822 MISC_PANELLINKSCALER | 12823 MISC_STNMODE | 12824 MISC_TVNTSC1024); 12825 12826 pSiS->SiS_SD2_Flags &= ~SiS_SD2_SIS760ONEOVL; 12827 12828#ifdef SISDUALHEAD 12829 if(pSiS->DualHeadMode) { 12830 if(pSiSEnt->pScrn_1) { 12831 SISPTR(pSiSEnt->pScrn_1)->MiscFlags &= ~(MISC_SIS760ONEOVERLAY | 12832 MISC_CRT1OVERLAY | 12833 MISC_CRT2OVERLAY | 12834 MISC_CRT1OVERLAYGAMMA | 12835 MISC_PANELLINKSCALER | 12836 MISC_STNMODE | 12837 MISC_TVNTSC1024); 12838 SISPTR(pSiSEnt->pScrn_1)->SiS_SD2_Flags &= ~SiS_SD2_SIS760ONEOVL; 12839 } 12840 if(pSiSEnt->pScrn_2) { 12841 SISPTR(pSiSEnt->pScrn_2)->MiscFlags &= ~(MISC_SIS760ONEOVERLAY | 12842 MISC_CRT1OVERLAY | 12843 MISC_CRT2OVERLAY | 12844 MISC_CRT1OVERLAYGAMMA | 12845 MISC_PANELLINKSCALER | 12846 MISC_STNMODE | 12847 MISC_TVNTSC1024); 12848 SISPTR(pSiSEnt->pScrn_2)->SiS_SD2_Flags &= ~SiS_SD2_SIS760ONEOVL; 12849 } 12850 } 12851#endif 12852 12853 /* Determine if the video overlay can be used */ 12854 if(!pSiS->NoXvideo) { 12855 12856 int clklimit1=0, clklimit2=0, clklimitg=0; 12857 Bool OverlayHandled = FALSE; 12858 12859 inSISIDXREG(SISSR,0x2b,sr2b); 12860 inSISIDXREG(SISSR,0x2c,sr2c); 12861 myclock1 = myclock2 = SiSGetClockFromRegs(sr2b, sr2c); 12862 inSISIDXREG(SISSR,0x06,tmpreg); 12863 switch((tmpreg & 0x1c) >> 2) { 12864 case 0: mycoldepth1 = 1; break; 12865 case 1: 12866 case 2: mycoldepth1 = 2; break; 12867 default: mycoldepth1 = 4; 12868 } 12869 mycoldepth2 = mycoldepth1; 12870 12871 if((!IsInSlaveMode) && (pSiS->VBFlags & CRT2_ENABLE)) { 12872 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 12873 inSISIDXREG(SISPART4,0x0a,sr2b); 12874 inSISIDXREG(SISPART4,0x0b,sr2c); 12875 } else { 12876 inSISIDXREG(SISSR,0x2e,sr2b); 12877 inSISIDXREG(SISSR,0x2f,sr2c); 12878 } 12879 myclock2 = SiSGetClockFromRegs(sr2b, sr2c); 12880 inSISIDXREG(SISPART1,0x00,tmpreg); 12881 tmpreg &= 0x0f; 12882 switch(tmpreg) { 12883 case 8: mycoldepth2 = 1; break; 12884 case 4: 12885 case 2: mycoldepth2 = 2; break; 12886 default: mycoldepth2 = 4; 12887 } 12888 } 12889 12890 switch(pSiS->ChipType) { 12891 12892 case SIS_300: 12893 case SIS_540: 12894 case SIS_630: 12895 case SIS_730: 12896 clklimit1 = clklimit2 = clklimitg = 150; 12897 break; 12898 12899 case SIS_550: 12900 case SIS_650: 12901 case SIS_740: 12902 clklimit1 = clklimit2 = 175; /* verified for 65x */ 12903 clklimitg = 166; /* ? */ 12904 break; 12905 12906 case SIS_661: 12907 case SIS_741: 12908 clklimit1 = clklimit2 = 190; /* ? */ 12909 clklimitg = 180; /* ? */ 12910 break; 12911 12912 case SIS_760: 12913 case SIS_761: 12914 clklimit1 = clklimit2 = 190; /* ? */ 12915 if(pSiS->ChipFlags & SiSCF_760LFB) { /* LFB only or hybrid */ 12916 clklimit1 = clklimit2 = 220; /* ? */ 12917 } 12918 clklimitg = 200; /* ? */ 12919 12920 if(pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORT760OO) { /* UMA only */ 12921 12922 Bool OnlyOne = FALSE, NoOverlay = FALSE; 12923 int dotclocksum = 0; 12924 12925 if(pSiS->VBFlags & DISPTYPE_CRT1) dotclocksum += myclock1; 12926 if((!IsInSlaveMode) && (pSiS->VBFlags & CRT2_ENABLE)) dotclocksum += myclock2; 12927 12928 /* TODO: Find out under what circumstances only one 12929 * overlay is usable in UMA-only mode. 12930 * This is not entirely accurate; the overlay 12931 * scaler also requires some time, so even though 12932 * the dotclocks are below these values, some 12933 * distortions in the overlay may occure. 12934 * Solution: Don't use a 760 with shared memory. 12935 */ 12936 if( (pSiS->VBFlags & DISPTYPE_CRT1) && 12937 (pSiS->VBFlags & CRT2_ENABLE) && 12938 (mycoldepth1 != mycoldepth2) ) { 12939 12940 /* 0. If coldepths are different (only possible in dual head mode), 12941 * I have no idea to calculate the limits; hence, allow only one 12942 * overlay in all cases. 12943 */ 12944 OnlyOne = TRUE; 12945 12946 } else if(pSiS->MemClock < 150000) { 12947 12948 /* 1. MCLK <150: If someone seriously considers using such 12949 * slow RAM, so be it. Only one overlay in call cases. 12950 */ 12951 OnlyOne = TRUE; 12952 12953 } else if(pSiS->MemClock < 170000) { 12954 12955 /* 2. MCLK 166 */ 12956 switch(pSiS->CurrentLayout.bitsPerPixel) { 12957 case 32: if(dotclocksum > 133) OnlyOne = TRUE; /* One overlay; verified */ 12958 if(dotclocksum > 180) NoOverlay = TRUE; /* No overlay; verified */ 12959 break; 12960 case 16: if(dotclocksum > 175) OnlyOne = TRUE; /* One overlay; verified */ 12961 if(dotclocksum > 260) NoOverlay = TRUE;; /* No overlay; FIXME */ 12962 break; 12963 } 12964 12965 } else if(pSiS->MemClock < 210000) { 12966 12967 /* 3. MCLK 200 */ 12968 switch(pSiS->CurrentLayout.bitsPerPixel) { 12969 case 32: if(dotclocksum > 160) OnlyOne = TRUE; /* One overlay; FIXME */ 12970 if(dotclocksum > 216) NoOverlay = TRUE;; /* No overlay; FIXME */ 12971 break; 12972 case 16: if(dotclocksum > 210) OnlyOne = TRUE; /* One overlay; FIXME */ 12973 if(dotclocksum > 312) NoOverlay = TRUE;; /* No overlay; FIXME */ 12974 break; 12975 } 12976 12977 } 12978 12979 if(OnlyOne || NoOverlay) { 12980 12981 ULong tmpflags = 0; 12982 12983 if(!NoOverlay) { 12984 if(myclock1 <= clklimit1) tmpflags |= MISC_CRT1OVERLAY; 12985 if(myclock2 <= clklimit2) tmpflags |= MISC_CRT2OVERLAY; 12986 if(myclock1 <= clklimitg) tmpflags |= MISC_CRT1OVERLAYGAMMA; 12987 pSiS->MiscFlags |= tmpflags; 12988 } 12989 pSiS->MiscFlags |= MISC_SIS760ONEOVERLAY; 12990 pSiS->SiS_SD2_Flags |= SiS_SD2_SIS760ONEOVL; 12991#ifdef SISDUALHEAD 12992 SiS_SetDHFlags(pSiS, (tmpflags | MISC_SIS760ONEOVERLAY), SiS_SD2_SIS760ONEOVL); 12993#endif 12994 OverlayHandled = TRUE; 12995 } 12996 12997 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 12998 "SiS76x/UMA: %s video overlay(s) available in current mode\n", 12999 NoOverlay ? "no" : ((pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) ? "one" : "two")); 13000 13001#ifdef TWDEBUG 13002 xf86DrvMsg(0, 0, "SiS760: Memclock %d, c1 %d/%d c2 %d/%d, sum %d / %x\n", 13003 pSiS->MemClock, myclock1, mycoldepth1, 13004 myclock2, mycoldepth2, dotclocksum, pSiS->SiS_SD2_Flags); 13005#endif 13006 } 13007 break; 13008 13009 case SIS_660: 13010 clklimit1 = clklimit2 = 200; /* ? */ 13011 if(pSiS->ChipFlags & SiSCF_760LFB) { /* LFB only */ 13012 clklimit1 = clklimit2 = 220; 13013 } 13014 clklimitg = 200; /* ? */ 13015 break; 13016 13017 case SIS_315H: 13018 case SIS_315: 13019 case SIS_315PRO: 13020 case SIS_330: 13021 clklimit1 = clklimit2 = 180; /* ? */ 13022 clklimitg = 166; /* ? */ 13023 break; 13024 13025 case SIS_340: /* ? */ 13026 case XGI_20: 13027 case XGI_40: 13028 clklimit1 = clklimit2 = 240; /* ? */ 13029 clklimitg = 200; /* ? */ 13030 break; 13031 } 13032 13033 if(!OverlayHandled) { 13034 ULong tmpflags = 0; 13035 if(myclock1 <= clklimit1) tmpflags |= MISC_CRT1OVERLAY; 13036 if(myclock2 <= clklimit2) tmpflags |= MISC_CRT2OVERLAY; 13037 if(myclock1 <= clklimitg) tmpflags |= MISC_CRT1OVERLAYGAMMA; 13038 pSiS->MiscFlags |= tmpflags; 13039#ifdef SISDUALHEAD 13040 SiS_SetDHFlags(pSiS, tmpflags, 0); 13041#endif 13042 if(!(pSiS->MiscFlags & MISC_CRT1OVERLAY)) { 13043#ifdef SISDUALHEAD 13044 if((!pSiS->DualHeadMode) || (pSiS->SecondHead)) 13045#endif 13046 xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, 3, 13047 "Current dotclock (%dMhz) too high for video overlay on CRT1\n", 13048 myclock1); 13049 } 13050 if((pSiS->VBFlags & CRT2_ENABLE) && (!(pSiS->MiscFlags & MISC_CRT2OVERLAY))) { 13051#ifdef SISDUALHEAD 13052 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) 13053#endif 13054 xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, 3, 13055 "Current dotclock (%dMhz) too high for video overlay on CRT2\n", 13056 myclock2); 13057 } 13058 } 13059 13060 } 13061 13062 /* Determine if the Panel Link scaler is active */ 13063 13064 if(pSiS->VBFlags & (CRT2_LCD | CRT1_LCDA)) { 13065 ULong tmpflags = 0; 13066 if(pSiS->VGAEngine == SIS_300_VGA) { 13067 if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) { 13068 inSISIDXREG(SISPART1,0x1e,tmpreg); 13069 tmpreg &= 0x3f; 13070 if(tmpreg) tmpflags |= MISC_PANELLINKSCALER; 13071 } 13072 } else { 13073 if((pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) || (pSiS->VBFlags & CRT1_LCDA)) { 13074 inSISIDXREG(SISPART1,0x35,tmpreg); 13075 tmpreg &= 0x04; 13076 if(!tmpreg) tmpflags |= MISC_PANELLINKSCALER; 13077 } 13078 } 13079 pSiS->MiscFlags |= tmpflags; 13080#ifdef SISDUALHEAD 13081 SiS_SetDHFlags(pSiS, tmpflags, 0); 13082#endif 13083 } 13084 13085 /* Determine if STN is active */ 13086 if(pSiS->ChipType == SIS_550) { 13087 if((pSiS->VBFlags & CRT2_LCD) && (pSiS->FSTN || pSiS->DSTN)) { 13088 inSISIDXREG(SISCR,0x34,tmpreg); 13089 tmpreg &= 0x7f; 13090 if(tmpreg == 0x5a || tmpreg == 0x5b) { 13091 pSiS->MiscFlags |= MISC_STNMODE; 13092#ifdef SISDUALHEAD 13093 SiS_SetDHFlags(pSiS, MISC_STNMODE, 0); 13094#endif 13095 } 13096 } 13097 } 13098 13099 /* Determine if our very special TV mode is active */ 13100 if((pSiS->VBFlags2 & VB2_SISBRIDGE) && (pSiS->VBFlags & CRT2_TV) && (!(pSiS->VBFlags & TV_HIVISION))) { 13101 if( ((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR525I)) || 13102 ((!(pSiS->VBFlags & TV_YPBPR)) && (pSiS->VBFlags & (TV_NTSC | TV_PALM))) ) { 13103 inSISIDXREG(SISCR,0x34,tmpreg); 13104 tmpreg &= 0x7f; 13105 if((tmpreg == 0x64) || (tmpreg == 0x4a) || (tmpreg == 0x38)) { 13106 pSiS->MiscFlags |= MISC_TVNTSC1024; 13107#ifdef SISDUALHEAD 13108 SiS_SetDHFlags(pSiS, MISC_TVNTSC1024, 0); 13109#endif 13110 } 13111 } 13112 } 13113 13114 if(pSiS->VGAEngine == SIS_315_VGA) { 13115 int i; 13116#ifdef SISVRAMQ 13117 /* Re-Enable and reset command queue */ 13118 SiSEnableTurboQueue(pScrn); 13119#endif 13120 /* Get HWCursor register contents for backup */ 13121 for(i = 0; i < 16; i++) { 13122 pSiS->HWCursorBackup[i] = SIS_MMIO_IN32(pSiS->IOBase, 0x8500 + (i << 2)); 13123 } 13124 if(pSiS->ChipType >= SIS_330) { 13125 /* Enable HWCursor protection (Y pos as trigger) */ 13126 andSISIDXREG(SISCR, 0x5b, ~0x30); 13127 } 13128 } 13129 13130 /* Re-initialize accelerator engine */ 13131 /* (We are sync'ed here) */ 13132 if(!pSiS->NoAccel) { 13133 if(pSiS->InitAccel) { 13134 (pSiS->InitAccel)(pScrn); 13135 } 13136 } 13137 13138 /* Set display device gamma (for SISCTRL) */ 13139 if(pSiS->VBFlags & CRT1_LCDA) 13140 pSiS->CRT1MonGamma = pSiS->CRT2LCDMonitorGamma; 13141 else 13142 pSiS->CRT1MonGamma = pSiS->CRT1VGAMonitorGamma; 13143 13144 if(pSiS->VBFlags & CRT2_LCD) 13145 pSiS->CRT2MonGamma = pSiS->CRT2LCDMonitorGamma; 13146 else if(pSiS->VBFlags & CRT2_TV) { 13147 if(pSiS->VBFlags & TV_YPBPR) 13148 pSiS->CRT2MonGamma = 2200; /* */ 13149 else if(pSiS->VBFlags & TV_HIVISION) 13150 pSiS->CRT2MonGamma = 2200; /* ? */ 13151 else if(pSiS->VBFlags & TV_NTSC) 13152 pSiS->CRT2MonGamma = 2200; /* NTSC */ 13153 else 13154 pSiS->CRT2MonGamma = 2800; /* All PAL modes? */ 13155 } else if(pSiS->VBFlags & CRT2_VGA) 13156 pSiS->CRT2MonGamma = pSiS->CRT2VGAMonitorGamma; 13157 else 13158 pSiS->CRT2MonGamma = 0; /* Unknown */ 13159 13160 /* Reset XV display properties (such as number of overlays, etc) */ 13161 /* (And copy monitor gamma) */ 13162#ifdef SISDUALHEAD 13163 if(pSiS->DualHeadMode) { 13164 if(pSiSEnt->pScrn_1) { 13165 if(SISPTR(pSiSEnt->pScrn_1)->ResetXvDisplay) { 13166 (SISPTR(pSiSEnt->pScrn_1)->ResetXvDisplay)(pSiSEnt->pScrn_1); 13167 } 13168 SISPTR(pSiSEnt->pScrn_1)->CRT1MonGamma = pSiS->CRT1MonGamma; 13169 SISPTR(pSiSEnt->pScrn_1)->CRT2MonGamma = pSiS->CRT2MonGamma; 13170 } 13171 if(pSiSEnt->pScrn_2) { 13172 if(SISPTR(pSiSEnt->pScrn_2)->ResetXvDisplay) { 13173 (SISPTR(pSiSEnt->pScrn_1)->ResetXvDisplay)(pSiSEnt->pScrn_2); 13174 } 13175 SISPTR(pSiSEnt->pScrn_2)->CRT1MonGamma = pSiS->CRT1MonGamma; 13176 SISPTR(pSiSEnt->pScrn_2)->CRT2MonGamma = pSiS->CRT2MonGamma; 13177 } 13178 } else { 13179#endif 13180 if(pSiS->ResetXvDisplay) { 13181 (pSiS->ResetXvDisplay)(pScrn); 13182 } 13183#ifdef SISDUALHEAD 13184 } 13185#endif 13186 13187 /* Reset XV gamma correction */ 13188 if(pSiS->ResetXvGamma) { 13189 (pSiS->ResetXvGamma)(pScrn); 13190 } 13191 13192 /* Reset various display parameters */ 13193 { 13194 int val = pSiS->siscrt1satgain; 13195#ifdef SISDUALHEAD 13196 if(pSiS->DualHeadMode && pSiSEnt) val = pSiSEnt->siscrt1satgain; 13197#endif 13198 SiS_SetSISCRT1SaturationGain(pScrn, val); 13199 } 13200 13201 /* Apply TV settings given by options 13202 Do this even in DualHeadMode: 13203 - if this is called by SetModeCRT1, CRT2 mode has been reset by SetModeCRT1 13204 - if this is called by SetModeCRT2, CRT2 mode has changed (duh!) 13205 -> Hence, in both cases, the settings must be re-applied. 13206 */ 13207 13208 if(pSiS->VBFlags & CRT2_TV) { 13209 int val; 13210 if(pSiS->VBFlags2 & VB2_CHRONTEL) { 13211 int mychtvlumabandwidthcvbs = pSiS->chtvlumabandwidthcvbs; 13212 int mychtvlumabandwidthsvideo = pSiS->chtvlumabandwidthsvideo; 13213 int mychtvlumaflickerfilter = pSiS->chtvlumaflickerfilter; 13214 int mychtvchromabandwidth = pSiS->chtvchromabandwidth; 13215 int mychtvchromaflickerfilter = pSiS->chtvchromaflickerfilter; 13216 int mychtvcvbscolor = pSiS->chtvcvbscolor; 13217 int mychtvtextenhance = pSiS->chtvtextenhance; 13218 int mychtvcontrast = pSiS->chtvcontrast; 13219 int mytvxpos = pSiS->tvxpos; 13220 int mytvypos = pSiS->tvypos; 13221#ifdef SISDUALHEAD 13222 if(pSiSEnt && pSiS->DualHeadMode) { 13223 mychtvlumabandwidthcvbs = pSiSEnt->chtvlumabandwidthcvbs; 13224 mychtvlumabandwidthsvideo = pSiSEnt->chtvlumabandwidthsvideo; 13225 mychtvlumaflickerfilter = pSiSEnt->chtvlumaflickerfilter; 13226 mychtvchromabandwidth = pSiSEnt->chtvchromabandwidth; 13227 mychtvchromaflickerfilter = pSiSEnt->chtvchromaflickerfilter; 13228 mychtvcvbscolor = pSiSEnt->chtvcvbscolor; 13229 mychtvtextenhance = pSiSEnt->chtvtextenhance; 13230 mychtvcontrast = pSiSEnt->chtvcontrast; 13231 mytvxpos = pSiSEnt->tvxpos; 13232 mytvypos = pSiSEnt->tvypos; 13233 } 13234#endif 13235 if((val = mychtvlumabandwidthcvbs) != -1) { 13236 SiS_SetCHTVlumabandwidthcvbs(pScrn, val); 13237 } 13238 if((val = mychtvlumabandwidthsvideo) != -1) { 13239 SiS_SetCHTVlumabandwidthsvideo(pScrn, val); 13240 } 13241 if((val = mychtvlumaflickerfilter) != -1) { 13242 SiS_SetCHTVlumaflickerfilter(pScrn, val); 13243 } 13244 if((val = mychtvchromabandwidth) != -1) { 13245 SiS_SetCHTVchromabandwidth(pScrn, val); 13246 } 13247 if((val = mychtvchromaflickerfilter) != -1) { 13248 SiS_SetCHTVchromaflickerfilter(pScrn, val); 13249 } 13250 if((val = mychtvcvbscolor) != -1) { 13251 SiS_SetCHTVcvbscolor(pScrn, val); 13252 } 13253 if((val = mychtvtextenhance) != -1) { 13254 SiS_SetCHTVtextenhance(pScrn, val); 13255 } 13256 if((val = mychtvcontrast) != -1) { 13257 SiS_SetCHTVcontrast(pScrn, val); 13258 } 13259 /* Backup default TV position registers */ 13260 switch(pSiS->ChrontelType) { 13261 case CHRONTEL_700x: 13262 pSiS->tvx = SiS_GetCH700x(pSiS->SiS_Pr, 0x0a); 13263 pSiS->tvx |= (((SiS_GetCH700x(pSiS->SiS_Pr, 0x08) & 0x02) >> 1) << 8); 13264 pSiS->tvy = SiS_GetCH700x(pSiS->SiS_Pr, 0x0b); 13265 pSiS->tvy |= ((SiS_GetCH700x(pSiS->SiS_Pr, 0x08) & 0x01) << 8); 13266#ifdef SISDUALHEAD 13267 if(pSiSEnt) { 13268 pSiSEnt->tvx = pSiS->tvx; 13269 pSiSEnt->tvy = pSiS->tvy; 13270 } 13271#endif 13272 break; 13273 case CHRONTEL_701x: 13274 /* Not supported by hardware */ 13275 break; 13276 } 13277 if((val = mytvxpos) != 0) { 13278 SiS_SetTVxposoffset(pScrn, val); 13279 } 13280 if((val = mytvypos) != 0) { 13281 SiS_SetTVyposoffset(pScrn, val); 13282 } 13283 } 13284 if(pSiS->VBFlags2 & VB2_301) { 13285 int mysistvedgeenhance = pSiS->sistvedgeenhance; 13286#ifdef SISDUALHEAD 13287 if(pSiSEnt && pSiS->DualHeadMode) { 13288 mysistvedgeenhance = pSiSEnt->sistvedgeenhance; 13289 } 13290#endif 13291 if((val = mysistvedgeenhance) != -1) { 13292 SiS_SetSISTVedgeenhance(pScrn, val); 13293 } 13294 } 13295 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 13296 int mysistvantiflicker = pSiS->sistvantiflicker; 13297 int mysistvsaturation = pSiS->sistvsaturation; 13298 int mysistvcolcalibf = pSiS->sistvcolcalibf; 13299 int mysistvcolcalibc = pSiS->sistvcolcalibc; 13300 int mysistvcfilter = pSiS->sistvcfilter; 13301 int mysistvyfilter = pSiS->sistvyfilter; 13302 int mytvxpos = pSiS->tvxpos; 13303 int mytvypos = pSiS->tvypos; 13304 int mytvxscale = pSiS->tvxscale; 13305 int mytvyscale = pSiS->tvyscale; 13306 int i; 13307 ULong cbase; 13308 UChar ctemp; 13309#ifdef SISDUALHEAD 13310 if(pSiSEnt && pSiS->DualHeadMode) { 13311 mysistvantiflicker = pSiSEnt->sistvantiflicker; 13312 mysistvsaturation = pSiSEnt->sistvsaturation; 13313 mysistvcolcalibf = pSiSEnt->sistvcolcalibf; 13314 mysistvcolcalibc = pSiSEnt->sistvcolcalibc; 13315 mysistvcfilter = pSiSEnt->sistvcfilter; 13316 mysistvyfilter = pSiSEnt->sistvyfilter; 13317 mytvxpos = pSiSEnt->tvxpos; 13318 mytvypos = pSiSEnt->tvypos; 13319 mytvxscale = pSiSEnt->tvxscale; 13320 mytvyscale = pSiSEnt->tvyscale; 13321 } 13322#endif 13323 /* Backup default TV position, scale and colcalib registers */ 13324 inSISIDXREG(SISPART2,0x1f,pSiS->p2_1f); 13325 inSISIDXREG(SISPART2,0x20,pSiS->p2_20); 13326 inSISIDXREG(SISPART2,0x2b,pSiS->p2_2b); 13327 inSISIDXREG(SISPART2,0x42,pSiS->p2_42); 13328 inSISIDXREG(SISPART2,0x43,pSiS->p2_43); 13329 inSISIDXREG(SISPART2,0x01,pSiS->p2_01); 13330 inSISIDXREG(SISPART2,0x02,pSiS->p2_02); 13331 inSISIDXREG(SISPART2,0x44,pSiS->p2_44); 13332 inSISIDXREG(SISPART2,0x45,pSiS->p2_45); 13333 if(!(pSiS->VBFlags2 & VB2_301)) { 13334 inSISIDXREG(SISPART2,0x46,pSiS->p2_46); 13335 } else { 13336 pSiS->p2_46 = 0; 13337 } 13338 inSISIDXREG(SISPART2,0x0a,pSiS->p2_0a); 13339 inSISIDXREG(SISPART2,0x31,cbase); 13340 cbase = (cbase & 0x7f) << 8; 13341 inSISIDXREG(SISPART2,0x32,ctemp); 13342 cbase = (cbase | ctemp) << 8; 13343 inSISIDXREG(SISPART2,0x33,ctemp); 13344 cbase = (cbase | ctemp) << 8; 13345 inSISIDXREG(SISPART2,0x34,ctemp); 13346 pSiS->sistvccbase = (cbase | ctemp); 13347 inSISIDXREG(SISPART2,0x35,pSiS->p2_35); 13348 inSISIDXREG(SISPART2,0x36,pSiS->p2_36); 13349 inSISIDXREG(SISPART2,0x37,pSiS->p2_37); 13350 inSISIDXREG(SISPART2,0x38,pSiS->p2_38); 13351 if(!(pSiS->VBFlags2 & VB2_301)) { 13352 inSISIDXREG(SISPART2,0x47,pSiS->p2_47); 13353 inSISIDXREG(SISPART2,0x48,pSiS->p2_48); 13354 inSISIDXREG(SISPART2,0x49,pSiS->p2_49); 13355 inSISIDXREG(SISPART2,0x4a,pSiS->p2_4a); 13356 } 13357 inSISIDXREG(SISPART2,0x2f,pSiS->p2_2f); 13358 inSISIDXREG(SISPART2,0x30,pSiS->p2_30); 13359 for(i=0; i<9; i++) { 13360 inSISIDXREG(SISPART1,SiSScalingP1Regs[i],pSiS->scalingp1[i]); 13361 } 13362 for(i=0; i<9; i++) { 13363 inSISIDXREG(SISPART4,SiSScalingP4Regs[i],pSiS->scalingp4[i]); 13364 } 13365 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 13366 for(i=0; i<64; i++) { 13367 inSISIDXREG(SISPART2,(0xc0 + i),pSiS->scalingp2[i]); 13368 } 13369 } 13370#ifdef SISDUALHEAD 13371 if(pSiSEnt) { 13372 pSiSEnt->p2_1f = pSiS->p2_1f; pSiSEnt->p2_20 = pSiS->p2_20; 13373 pSiSEnt->p2_42 = pSiS->p2_42; pSiSEnt->p2_43 = pSiS->p2_43; 13374 pSiSEnt->p2_2b = pSiS->p2_2b; 13375 pSiSEnt->p2_01 = pSiS->p2_01; pSiSEnt->p2_02 = pSiS->p2_02; 13376 pSiSEnt->p2_44 = pSiS->p2_44; pSiSEnt->p2_45 = pSiS->p2_45; 13377 pSiSEnt->p2_46 = pSiS->p2_46; pSiSEnt->p2_0a = pSiS->p2_0a; 13378 pSiSEnt->sistvccbase = pSiS->sistvccbase; 13379 pSiSEnt->p2_35 = pSiS->p2_35; pSiSEnt->p2_36 = pSiS->p2_36; 13380 pSiSEnt->p2_37 = pSiS->p2_37; pSiSEnt->p2_38 = pSiS->p2_38; 13381 pSiSEnt->p2_48 = pSiS->p2_48; pSiSEnt->p2_49 = pSiS->p2_49; 13382 pSiSEnt->p2_4a = pSiS->p2_4a; pSiSEnt->p2_2f = pSiS->p2_2f; 13383 pSiSEnt->p2_30 = pSiS->p2_30; pSiSEnt->p2_47 = pSiS->p2_47; 13384 for(i=0; i<9; i++) { 13385 pSiSEnt->scalingp1[i] = pSiS->scalingp1[i]; 13386 } 13387 for(i=0; i<9; i++) { 13388 pSiSEnt->scalingp4[i] = pSiS->scalingp4[i]; 13389 } 13390 if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 13391 for(i=0; i<64; i++) { 13392 pSiSEnt->scalingp2[i] = pSiS->scalingp2[i]; 13393 } 13394 } 13395 } 13396#endif 13397 if((val = mysistvantiflicker) != -1) { 13398 SiS_SetSISTVantiflicker(pScrn, val); 13399 } 13400 if((val = mysistvsaturation) != -1) { 13401 SiS_SetSISTVsaturation(pScrn, val); 13402 } 13403 if((val = mysistvcfilter) != -1) { 13404 SiS_SetSISTVcfilter(pScrn, val); 13405 } 13406 if((val = mysistvyfilter) != 1) { 13407 SiS_SetSISTVyfilter(pScrn, val); 13408 } 13409 if((val = mysistvcolcalibc) != 0) { 13410 SiS_SetSISTVcolcalib(pScrn, val, TRUE); 13411 } 13412 if((val = mysistvcolcalibf) != 0) { 13413 SiS_SetSISTVcolcalib(pScrn, val, FALSE); 13414 } 13415 if((val = mytvxpos) != 0) { 13416 SiS_SetTVxposoffset(pScrn, val); 13417 } 13418 if((val = mytvypos) != 0) { 13419 SiS_SetTVyposoffset(pScrn, val); 13420 } 13421 if((val = mytvxscale) != 0) { 13422 SiS_SetTVxscale(pScrn, val); 13423 } 13424 if((val = mytvyscale) != 0) { 13425 SiS_SetTVyscale(pScrn, val); 13426 } 13427 } 13428 } 13429 13430} 13431 13432/* Post-set SiS6326 TV registers */ 13433static void 13434SiS6326PostSetMode(ScrnInfoPtr pScrn, SISRegPtr sisReg) 13435{ 13436 SISPtr pSiS = SISPTR(pScrn); 13437 UChar tmp; 13438 int val; 13439 13440 if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 13441 13442#ifdef UNLOCK_ALWAYS 13443 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 13444#endif 13445 13446 /* Backup default TV position registers */ 13447 pSiS->tvx1 = SiS6326GetTVReg(pScrn,0x3a); 13448 pSiS->tvx1 |= ((SiS6326GetTVReg(pScrn,0x3c) & 0x0f) << 8); 13449 pSiS->tvx2 = SiS6326GetTVReg(pScrn,0x26); 13450 pSiS->tvx2 |= ((SiS6326GetTVReg(pScrn,0x27) & 0xf0) << 4); 13451 pSiS->tvx3 = SiS6326GetTVReg(pScrn,0x12); 13452 pSiS->tvx3 |= ((SiS6326GetTVReg(pScrn,0x13) & 0xC0) << 2); 13453 pSiS->tvy1 = SiS6326GetTVReg(pScrn,0x11); 13454 pSiS->tvy1 |= ((SiS6326GetTVReg(pScrn,0x13) & 0x30) << 4); 13455 13456 /* Handle TVPosOffset options (BEFORE switching on TV) */ 13457 if((val = pSiS->tvxpos) != 0) { 13458 SiS_SetTVxposoffset(pScrn, val); 13459 } 13460 if((val = pSiS->tvypos) != 0) { 13461 SiS_SetTVyposoffset(pScrn, val); 13462 } 13463 13464 /* Switch on TV output. This is rather complicated, but 13465 * if we don't do it, TV output will flicker terribly. 13466 */ 13467 if(pSiS->SiS6326Flags & SIS6326_TVON) { 13468 orSISIDXREG(SISSR, 0x01, 0x20); 13469 tmp = SiS6326GetTVReg(pScrn,0x00); 13470 tmp &= ~0x04; 13471 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 13472 SiS6326SetTVReg(pScrn,0x00,tmp); 13473 for(val=0; val < 2; val++) { 13474 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 13475 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 13476 } 13477 SiS6326SetTVReg(pScrn, 0x00, sisReg->sis6326tv[0]); 13478 tmp = inSISREG(SISINPSTAT); 13479 outSISREG(SISAR, 0x20); 13480 tmp = inSISREG(SISINPSTAT); 13481 while(inSISREG(SISINPSTAT) & 0x01); 13482 while(!(inSISREG(SISINPSTAT) & 0x01)); 13483 andSISIDXREG(SISSR, 0x01, ~0x20); 13484 for(val=0; val < 10; val++) { 13485 while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 13486 while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 13487 } 13488 andSISIDXREG(SISSR, 0x01, ~0x20); 13489 } 13490 13491 tmp = SiS6326GetTVReg(pScrn,0x00); 13492 if(!(tmp & 0x04)) return; 13493 13494 /* Apply TV settings given by options */ 13495 if((val = pSiS->sistvantiflicker) != -1) { 13496 SiS_SetSIS6326TVantiflicker(pScrn, val); 13497 } 13498 if((val = pSiS->sis6326enableyfilter) != -1) { 13499 SiS_SetSIS6326TVenableyfilter(pScrn, val); 13500 } 13501 if((val = pSiS->sis6326yfilterstrong) != -1) { 13502 SiS_SetSIS6326TVyfilterstrong(pScrn, val); 13503 } 13504 13505} 13506 13507/* Check if video bridge is in slave mode */ 13508Bool 13509SiSBridgeIsInSlaveMode(ScrnInfoPtr pScrn) 13510{ 13511 SISPtr pSiS = SISPTR(pScrn); 13512 UChar usScrP1_00; 13513 13514 if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return FALSE; 13515 13516 inSISIDXREG(SISPART1,0x00,usScrP1_00); 13517 if( ((pSiS->VGAEngine == SIS_300_VGA) && (usScrP1_00 & 0xa0) == 0x20) || 13518 ((pSiS->VGAEngine == SIS_315_VGA) && (usScrP1_00 & 0x50) == 0x10) ) { 13519 return TRUE; 13520 } 13521 13522 return FALSE; 13523} 13524 13525/* Build a list of the VESA modes the BIOS reports as valid */ 13526static void 13527SiSBuildVesaModeList(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe) 13528{ 13529 SISPtr pSiS = SISPTR(pScrn); 13530 int i = 0; 13531 13532 while(vbe->VideoModePtr[i] != 0xffff) { 13533 sisModeInfoPtr m; 13534 VbeModeInfoBlock *mode; 13535 int id = vbe->VideoModePtr[i++]; 13536 13537 if((mode = VBEGetModeInfo(pVbe, id)) == NULL) { 13538 continue; 13539 } 13540 13541 m = xnfcalloc(sizeof(sisModeInfoRec), 1); 13542 if(!m) { 13543 VBEFreeModeInfo(mode); 13544 continue; 13545 } 13546 m->width = mode->XResolution; 13547 m->height = mode->YResolution; 13548 m->bpp = mode->BitsPerPixel; 13549 m->n = id; 13550 m->next = pSiS->SISVESAModeList; 13551 13552 pSiS->SISVESAModeList = m; 13553 13554 VBEFreeModeInfo(mode); 13555 13556 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 13557 "VESA BIOS supports mode number 0x%x: %ix%i (%i bpp)\n", 13558 m->n, m->width, m->height, m->bpp); 13559 } 13560} 13561 13562/* Get VESA mode number from given resolution/depth */ 13563static UShort 13564SiSCalcVESAModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode) 13565{ 13566 SISPtr pSiS = SISPTR(pScrn); 13567 sisModeInfoPtr m = pSiS->SISVESAModeList; 13568 UShort i = (pScrn->bitsPerPixel+7)/8 - 1; 13569 UShort ModeNumber = 0; 13570 int j; 13571 13572 while(m) { 13573 if( (pScrn->bitsPerPixel == m->bpp) && 13574 (mode->HDisplay == m->width) && 13575 (mode->VDisplay == m->height) ) 13576 return m->n; 13577 m = m->next; 13578 } 13579 13580 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 13581 "No valid VESA BIOS mode found for %dx%d (%d bpp)\n", 13582 mode->HDisplay, mode->VDisplay, pScrn->bitsPerPixel); 13583 13584 if(!pSiS->ROM661New) { /* VESA numbers changed! */ 13585 j = 0; 13586 while(VESAModeIndices[j] != 9999) { 13587 if( (mode->HDisplay == VESAModeIndices[j]) && 13588 (mode->VDisplay == VESAModeIndices[j+1]) ) { 13589 ModeNumber = VESAModeIndices[j + 2 + i]; 13590 break; 13591 } 13592 j += 6; 13593 } 13594 13595 if(!ModeNumber) { 13596 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 13597 "No valid mode found for %dx%dx%d in built-in table either.\n", 13598 mode->HDisplay, mode->VDisplay, pScrn->bitsPerPixel); 13599 } 13600 } 13601 13602 return(ModeNumber); 13603} 13604 13605UShort 13606SiS_GetModeNumber(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned int VBFlags) 13607{ 13608 SISPtr pSiS = SISPTR(pScrn); 13609 UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; 13610 BOOLEAN FSTN = pSiS->FSTN ? TRUE : FALSE; 13611 13612#ifdef SISDUALHEAD 13613 if(pSiS->DualHeadMode && pSiS->SecondHead) FSTN = FALSE; 13614#endif 13615 13616 return(SiS_GetModeID(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, 13617 i, FSTN, pSiS->LCDwidth, pSiS->LCDheight)); 13618} 13619 13620static Bool 13621SiSValidLCDUserMode(SISPtr pSiS, unsigned int VBFlags, DisplayModePtr mode, Bool isforlcda) 13622{ 13623 if(mode->Flags & V_INTERLACE) return FALSE; 13624 13625 if(mode->HDisplay > 2048) return FALSE; 13626 if(mode->VDisplay > 1536) return FALSE; 13627 13628 if(pSiS->VBFlags2 & VB2_LCD162MHZBRIDGE) { 13629 if(mode->Clock > 162500) return FALSE; 13630#ifdef VB_FORBID_CRT2LCD_OVER_1600 13631 if(!isforlcda) { 13632 if(mode->HDisplay > 1600) return FALSE; 13633 } 13634#endif 13635 } else { /* 301, 301B, 302B (no LCDA!) */ 13636 if(mode->Clock > 130000) return FALSE; 13637 if(mode->Clock > 111000) { 13638 xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING, 13639 "WARNING: Mode clock beyond video bridge specs (%dMHz). Hardware damage might occure.\n", 13640 mode->Clock / 1000); 13641 } 13642 if(mode->HDisplay > 1600) return FALSE; 13643 if(mode->VDisplay > 1024) return FALSE; 13644 } 13645 13646 return TRUE; 13647} 13648 13649static Bool 13650SiSValidVGA2UserMode(SISPtr pSiS, unsigned int VBFlags, DisplayModePtr mode) 13651{ 13652 if(mode->Flags & V_INTERLACE) return FALSE; 13653 13654 if(mode->HDisplay > 2048) return FALSE; 13655 if(mode->VDisplay > 1536) return FALSE; 13656 13657 if(pSiS->VBFlags2 & VB2_RAMDAC202MHZBRIDGE) { 13658 if(mode->Clock > 203000) return FALSE; 13659 } else if(pSiS->VBFlags2 & VB2_30xBLV) { 13660 if(mode->Clock > 162500) return FALSE; 13661 } else { 13662 if(mode->Clock > 135500) return FALSE; 13663 } 13664 13665 return TRUE; 13666} 13667 13668UShort 13669SiS_CheckModeCRT1(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned int VBFlags, Bool havecustommodes) 13670{ 13671 SISPtr pSiS = SISPTR(pScrn); 13672 UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; 13673 int j; 13674 13675 if(!(VBFlags & CRT1_LCDA)) { 13676 13677 if((havecustommodes) && (!(mode->type & M_T_DEFAULT))) { 13678 return 0xfe; 13679 } 13680 13681 } else if(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE) { 13682 13683 if(pSiS->ChipType < SIS_661) { /* < 661 only? */ 13684 if(!(mode->type & M_T_DEFAULT)) { 13685 if(mode->HTotal > 2055) return 0; 13686 /* (Default mode will be caught in mode switching code) */ 13687 } 13688 } 13689 13690 if(pSiS->SiS_Pr->CP_HaveCustomData) { 13691 for(j=0; j<7; j++) { 13692 if((pSiS->SiS_Pr->CP_DataValid[j]) && 13693 (mode->HDisplay == pSiS->SiS_Pr->CP_HDisplay[j]) && 13694 (mode->VDisplay == pSiS->SiS_Pr->CP_VDisplay[j]) && 13695 (mode->type & M_T_BUILTIN)) 13696 return 0xfe; 13697 } 13698 } 13699 13700 if((pSiS->AddedPlasmaModes) && (mode->type & M_T_BUILTIN)) 13701 return 0xfe; 13702 13703 if((havecustommodes) && 13704 (pSiS->LCDwidth) && /* = test if LCD present */ 13705 (!(mode->type & M_T_DEFAULT)) && 13706 (SiSValidLCDUserMode(pSiS, VBFlags, mode, TRUE))) 13707 return 0xfe; 13708 13709 if((mode->HDisplay > pSiS->LCDwidth) || 13710 (mode->VDisplay > pSiS->LCDheight)) { 13711 return 0; 13712 } 13713 13714 } else { 13715 13716 if((mode->HDisplay > pSiS->LCDwidth) || 13717 (mode->VDisplay > pSiS->LCDheight)) { 13718 return 0; 13719 } 13720 13721 } 13722 13723 return(SiS_GetModeID(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, 13724 i, pSiS->FSTN, pSiS->LCDwidth, pSiS->LCDheight)); 13725} 13726 13727UShort 13728SiS_CheckModeCRT2(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned int VBFlags, Bool havecustommodes) 13729{ 13730 SISPtr pSiS = SISPTR(pScrn); 13731 UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; 13732 UShort ModeIndex = 0; 13733 int j; 13734 13735#ifdef TWDEBUG 13736 xf86DrvMsg(0, X_INFO, "Inside CheckCalcModeIndex (VBFlags %lx, mode %dx%d)\n", 13737 VBFlags,mode->HDisplay, mode->VDisplay); 13738#endif 13739 13740 if(VBFlags & CRT2_LCD) { /* CRT2 is LCD */ 13741 13742 if((pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && (!(pSiS->VBFlags2 & VB2_30xBDH))) { 13743 13744 if(pSiS->SiS_Pr->CP_HaveCustomData) { 13745 for(j=0; j<7; j++) { 13746 if((pSiS->SiS_Pr->CP_DataValid[j]) && 13747 (mode->HDisplay == pSiS->SiS_Pr->CP_HDisplay[j]) && 13748 (mode->VDisplay == pSiS->SiS_Pr->CP_VDisplay[j]) && 13749#ifdef VB_FORBID_CRT2LCD_OVER_1600 13750 (mode->HDisplay <= 1600) && 13751#endif 13752 (mode->type & M_T_BUILTIN)) 13753 return 0xfe; 13754 } 13755 } 13756 13757 /* All plasma modes have HDisplay <= 1600 */ 13758 if((pSiS->AddedPlasmaModes) && (mode->type & M_T_BUILTIN)) 13759 return 0xfe; 13760 13761 if((havecustommodes) && 13762 (pSiS->LCDwidth) && /* = test if LCD present */ 13763 (!(mode->type & M_T_DEFAULT)) && 13764 (SiSValidLCDUserMode(pSiS, VBFlags, mode, FALSE))) 13765 return 0xfe; 13766 13767 } 13768 13769 if( ((mode->HDisplay <= pSiS->LCDwidth) && 13770 (mode->VDisplay <= pSiS->LCDheight)) || 13771 ((pSiS->SiS_Pr->SiS_CustomT == CUT_PANEL848) && 13772 (((mode->HDisplay == 1360) && (mode->VDisplay == 768)) || 13773 ((mode->HDisplay == 1024) && (mode->VDisplay == 768)) || 13774 ((mode->HDisplay == 800) && (mode->VDisplay == 600)))) || 13775 ((pSiS->SiS_Pr->SiS_CustomT == CUT_PANEL856) && 13776 (((mode->HDisplay == 1024) && (mode->VDisplay == 768)) || 13777 ((mode->HDisplay == 800) && (mode->VDisplay == 600)))) ) { 13778 13779 ModeIndex = SiS_GetModeID_LCD(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, i, 13780 pSiS->FSTN, pSiS->SiS_Pr->SiS_CustomT, pSiS->LCDwidth, pSiS->LCDheight, 13781 pSiS->VBFlags2); 13782 13783 } 13784 13785 } else if(VBFlags & CRT2_TV) { /* CRT2 is TV */ 13786 13787 ModeIndex = SiS_GetModeID_TV(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, i, 13788 pSiS->VBFlags2); 13789 13790 } else if(VBFlags & CRT2_VGA) { /* CRT2 is VGA2 */ 13791 13792 if((pSiS->AddedPlasmaModes) && (mode->type & M_T_BUILTIN)) 13793 return 0xfe; 13794 13795 if((havecustommodes) && 13796 (!(mode->type & M_T_DEFAULT)) && 13797 (SiSValidVGA2UserMode(pSiS, VBFlags, mode))) 13798 return 0xfe; 13799 13800 ModeIndex = SiS_GetModeID_VGA2(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, i, 13801 pSiS->VBFlags2); 13802 13803 } else { /* no CRT2 */ 13804 13805 /* Return a valid mode number */ 13806 ModeIndex = 0xfe; 13807 13808 } 13809 13810 return(ModeIndex); 13811} 13812 13813/* Calculate the vertical refresh rate from a mode */ 13814float 13815SiSCalcVRate(DisplayModePtr mode) 13816{ 13817 float hsync, refresh = 0; 13818 13819 if(mode->HSync > 0.0) 13820 hsync = mode->HSync; 13821 else if(mode->HTotal > 0) 13822 hsync = (float)mode->Clock / (float)mode->HTotal; 13823 else 13824 hsync = 0.0; 13825 13826 if(mode->VTotal > 0) 13827 refresh = hsync * 1000.0 / mode->VTotal; 13828 13829 if(mode->Flags & V_INTERLACE) 13830 refresh *= 2.0; 13831 13832 if(mode->Flags & V_DBLSCAN) 13833 refresh /= 2.0; 13834 13835 if(mode->VScan > 1) 13836 refresh /= mode->VScan; 13837 13838 if(mode->VRefresh > 0.0) 13839 refresh = mode->VRefresh; 13840 13841 if(hsync == 0.0 || refresh == 0.0) return 0.0; 13842 13843 return refresh; 13844} 13845 13846/* Calculate CR33 (rate index) for CRT1. 13847 * Calculation is done using currentmode, therefore it is 13848 * recommended to set VertRefresh and HorizSync to correct 13849 * values in config file. 13850 */ 13851UChar 13852SISSearchCRT1Rate(ScrnInfoPtr pScrn, DisplayModePtr mode) 13853{ 13854 SISPtr pSiS = SISPTR(pScrn); 13855 int i = 0, irefresh; 13856 UShort xres = mode->HDisplay; 13857 UShort yres = mode->VDisplay; 13858 UChar index, defindex; 13859 Bool checksis730 = FALSE; 13860 13861 defindex = (xres == 800 || xres == 1024 || xres == 1280) ? 0x02 : 0x01; 13862 13863 irefresh = (int)SiSCalcVRate(mode); 13864 if(!irefresh) return defindex; 13865 13866 /* SiS730 has troubles on CRT2 if CRT1 is at 32bpp */ 13867 if( (pSiS->ChipType == SIS_730) && 13868 (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && 13869 (pSiS->CurrentLayout.bitsPerPixel == 32) ) { 13870#ifdef SISDUALHEAD 13871 if(pSiS->DualHeadMode) { 13872 if(pSiS->SecondHead) { 13873 checksis730 = TRUE; 13874 } 13875 } else 13876#endif 13877 if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE) && (!pSiS->CRT1off)) { 13878 checksis730 = TRUE; 13879 } 13880 } 13881 13882#ifdef TWDEBUG 13883 xf86DrvMsg(0, X_INFO, "Debug: CalcVRate returned %d\n", irefresh); 13884#endif 13885 13886 /* We need the REAL refresh rate here */ 13887 if(mode->Flags & V_INTERLACE) irefresh /= 2; 13888 13889 /* Do not multiply by 2 when DBLSCAN! */ 13890 13891#ifdef TWDEBUG 13892 xf86DrvMsg(0, X_INFO, "Debug: Rate after correction = %d\n", irefresh); 13893#endif 13894 13895 index = 0; 13896 while((sisx_vrate[i].idx != 0) && (sisx_vrate[i].xres <= xres)) { 13897 if((sisx_vrate[i].xres == xres) && (sisx_vrate[i].yres == yres)) { 13898 if((checksis730 == FALSE) || (sisx_vrate[i].SiS730valid32bpp == TRUE)) { 13899 if(sisx_vrate[i].refresh == irefresh) { 13900 index = sisx_vrate[i].idx; 13901 break; 13902 } else if(sisx_vrate[i].refresh > irefresh) { 13903 if((sisx_vrate[i].refresh - irefresh) <= 3) { 13904 index = sisx_vrate[i].idx; 13905 } else if( ((checksis730 == FALSE) || (sisx_vrate[i - 1].SiS730valid32bpp == TRUE)) && 13906 ((irefresh - sisx_vrate[i - 1].refresh) <= 2) && 13907 (sisx_vrate[i].idx != 1) ) { 13908 index = sisx_vrate[i - 1].idx; 13909 } 13910 break; 13911 } else if((irefresh - sisx_vrate[i].refresh) <= 2) { 13912 index = sisx_vrate[i].idx; 13913 break; 13914 } 13915 } 13916 } 13917 i++; 13918 } 13919 13920 if(index > 0) return index; 13921 else return defindex; 13922} 13923 13924void 13925SISWaitRetraceCRT1(ScrnInfoPtr pScrn) 13926{ 13927 SISPtr pSiS = SISPTR(pScrn); 13928 int watchdog; 13929 UChar temp; 13930 13931 inSISIDXREG(SISCR,0x17,temp); 13932 if(!(temp & 0x80)) return; 13933 13934 inSISIDXREG(SISSR,0x1f,temp); 13935 if(temp & 0xc0) return; 13936 13937 watchdog = 65536; 13938 while((inSISREG(SISINPSTAT) & 0x08) && --watchdog); 13939 watchdog = 65536; 13940 while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog); 13941} 13942 13943void 13944SISWaitRetraceCRT2(ScrnInfoPtr pScrn) 13945{ 13946 SISPtr pSiS = SISPTR(pScrn); 13947 int watchdog; 13948 UChar temp, reg; 13949 13950 if(SiSBridgeIsInSlaveMode(pScrn)) { 13951 SISWaitRetraceCRT1(pScrn); 13952 return; 13953 } 13954 13955 switch(pSiS->VGAEngine) { 13956 case SIS_300_VGA: 13957 reg = 0x25; 13958 break; 13959 case SIS_315_VGA: 13960 reg = 0x30; 13961 break; 13962 default: 13963 return; 13964 } 13965 13966 watchdog = 65536; 13967 do { 13968 inSISIDXREG(SISPART1, reg, temp); 13969 if(!(temp & 0x02)) break; 13970 } while(--watchdog); 13971 watchdog = 65536; 13972 do { 13973 inSISIDXREG(SISPART1, reg, temp); 13974 if(temp & 0x02) break; 13975 } while(--watchdog); 13976} 13977 13978static void 13979SISWaitVBRetrace(ScrnInfoPtr pScrn) 13980{ 13981 SISPtr pSiS = SISPTR(pScrn); 13982 13983 if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 13984#ifdef SISDUALHEAD 13985 if(pSiS->DualHeadMode) { 13986 if(pSiS->SecondHead) 13987 SISWaitRetraceCRT1(pScrn); 13988 else 13989 SISWaitRetraceCRT2(pScrn); 13990 } else { 13991#endif 13992 if(pSiS->VBFlags & DISPTYPE_DISP1) { 13993 SISWaitRetraceCRT1(pScrn); 13994 } 13995 if(pSiS->VBFlags & DISPTYPE_DISP2) { 13996 if(!(SiSBridgeIsInSlaveMode(pScrn))) { 13997 SISWaitRetraceCRT2(pScrn); 13998 } 13999 } 14000#ifdef SISDUALHEAD 14001 } 14002#endif 14003 } else { 14004 SISWaitRetraceCRT1(pScrn); 14005 } 14006} 14007 14008#define MODEID_OFF 0x449 14009 14010UChar 14011SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, UShort offset, UChar value) 14012{ 14013 UChar ret = 0; 14014#ifndef XSERVER_LIBPCIACCESS 14015#ifdef SIS_USE_BIOS_SCRATCH 14016 UChar *base; 14017#endif 14018#endif 14019 14020 /* For some reasons (like detecting the current display mode), 14021 * we need to read (or write-back) values from the BIOS 14022 * scratch area. This area is only valid for the primary 14023 * graphics card. For the secondary, we just return some 14024 * defaults and ignore requests to write data. As regards 14025 * the display mode: If sisfb is loaded for the secondary 14026 * card, it very probably has set a mode, but in any case 14027 * informed us via its info packet. So this here will not be 14028 * called for mode detection in this case. 14029 */ 14030 14031 switch(offset) { 14032 case 0x489: 14033 ret = 0x11; /* Default VGA Info */ 14034 break; 14035 case MODEID_OFF: 14036 ret = 0x03; /* Default current display mode */ 14037 break; 14038 } 14039 14040#ifndef XSERVER_LIBPCIACCESS 14041#ifdef SIS_USE_BIOS_SCRATCH 14042 if(SISPTR(pScrn)->Primary) { 14043 base = xf86MapVidMem(pScrn->scrnIndex, VIDMEM_MMIO, 0, 0x2000); 14044 if(!base) { 14045 SISErrorLog(pScrn, "(Could not map BIOS scratch area)\n"); 14046 return ret; 14047 } 14048 14049 ret = *(base + offset); 14050 14051 /* value != 0xff means: set register */ 14052 if(value != 0xff) { 14053 *(base + offset) = value; 14054 } 14055 14056 xf86UnMapVidMem(pScrn->scrnIndex, base, 0x2000); 14057 } 14058#endif 14059#endif 14060 return ret; 14061} 14062 14063UChar 14064SiS_GetSetModeID(ScrnInfoPtr pScrn, UChar id) 14065{ 14066 return(SiS_GetSetBIOSScratch(pScrn, MODEID_OFF, id)); 14067} 14068 14069void 14070SiSMemCopyToVideoRam(SISPtr pSiS, UChar *to, UChar *from, int size) 14071{ 14072 if((ULong)to & 15) (*pSiS->SiSFastMemCopy)(to, from, size); 14073 else (*pSiS->SiSFastVidCopy)(to, from, size); 14074} 14075 14076void 14077SiSMemCopyFromVideoRam(SISPtr pSiS, UChar *to, UChar *from, int size) 14078{ 14079 if((ULong)to & 15) (*pSiS->SiSFastMemCopyFrom)(to, from, size); 14080 else (*pSiS->SiSFastVidCopyFrom)(to, from, size); 14081} 14082 14083void 14084sisSaveUnlockExtRegisterLock(SISPtr pSiS, UChar *reg1, UChar *reg2) 14085{ 14086 register UChar val; 14087 ULong mylockcalls; 14088#ifdef TWDEBUG 14089 UChar val1, val2; 14090 int i; 14091#endif 14092 14093 pSiS->lockcalls++; 14094 mylockcalls = pSiS->lockcalls; 14095 14096 /* check if already unlocked */ 14097 inSISIDXREG(SISSR, 0x05, val); 14098 14099 if(val != 0xa1) { 14100 14101 /* save State */ 14102 if(reg1) *reg1 = val; 14103 14104 /* unlock */ 14105 outSISIDXREG(SISSR, 0x05, 0x86); 14106 14107 /* Now check again */ 14108 inSISIDXREG(SISSR, 0x05, val); 14109 14110 if(val != 0xA1) { 14111 14112 xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING, 14113 "Failed to unlock SR registers at relocated i/o ports\n"); 14114 14115#ifdef TWDEBUG 14116 for(i = 0; i <= 0x3f; i++) { 14117 inSISIDXREG(SISSR, i, val1); 14118 inSISIDXREG(0x3c4, i, val2); 14119 xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO, 14120 "SR%02d: RelIO=0x%02x 0x3c4=0x%02x (%ld)\n", 14121 i, val1, val2, mylockcalls); 14122 } 14123#endif 14124 14125 /* Emergency measure: unlock at 0x3c4, and try to enable relocated IO ports */ 14126 switch(pSiS->VGAEngine) { 14127 case SIS_OLD_VGA: 14128 case SIS_530_VGA: 14129 outSISIDXREG(0x3c4, 0x05, 0x86); 14130 andSISIDXREG(0x3c4, 0x33, ~0x20); 14131 break; 14132 case SIS_300_VGA: 14133 case SIS_315_VGA: 14134 outSISIDXREG(0x3c4, 0x05, 0x86); 14135 orSISIDXREG(0x3c4, 0x20, 0x20); 14136 break; 14137 } 14138 outSISIDXREG(SISSR, 0x05, 0x86); 14139 inSISIDXREG(SISSR, 0x05, val); 14140 if(val != 0xa1) { 14141 SISErrorLog(pSiS->pScrn, 14142 "Failed to unlock SR registers (%p, %lx, 0x%02x; %ld)\n", 14143 (void *)pSiS, (ULong)pSiS->RelIO, val, mylockcalls); 14144 /* Now await doom... */ 14145 } 14146 } 14147 } 14148 if((pSiS->VGAEngine == SIS_OLD_VGA) || (pSiS->VGAEngine == SIS_530_VGA)) { 14149 inSISIDXREG(SISCR, 0x80, val); 14150 if(val != 0xa1) { 14151 /* save State */ 14152 if(reg2) *reg2 = val; 14153 outSISIDXREG(SISCR, 0x80, 0x86); 14154 inSISIDXREG(SISCR, 0x80, val); 14155 if(val != 0xA1) { 14156 SISErrorLog(pSiS->pScrn, 14157 "Failed to unlock cr registers (%p, %lx, 0x%02x)\n", 14158 (void *)pSiS, (ULong)pSiS->RelIO, val); 14159 } 14160 } 14161 } 14162} 14163 14164void 14165sisRestoreExtRegisterLock(SISPtr pSiS, UChar reg1, UChar reg2) 14166{ 14167 /* restore lock */ 14168#ifndef UNLOCK_ALWAYS 14169 outSISIDXREG(SISSR, 0x05, reg1 == 0xA1 ? 0x86 : 0x00); 14170 if((pSiS->VGAEngine == SIS_OLD_VGA) || (pSiS->VGAEngine == SIS_530_VGA)) { 14171 outSISIDXREG(SISCR, 0x80, reg2 == 0xA1 ? 0x86 : 0x00); 14172 } 14173#endif 14174} 14175 14176