sis_driver.c revision 721a3bc8
172b676d7Smrg/* 272b676d7Smrg * SiS driver main code 372b676d7Smrg * 472b676d7Smrg * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria. 572b676d7Smrg * 672b676d7Smrg * Redistribution and use in source and binary forms, with or without 772b676d7Smrg * modification, are permitted provided that the following conditions 872b676d7Smrg * are met: 972b676d7Smrg * 1) Redistributions of source code must retain the above copyright 1072b676d7Smrg * notice, this list of conditions and the following disclaimer. 1172b676d7Smrg * 2) Redistributions in binary form must reproduce the above copyright 1272b676d7Smrg * notice, this list of conditions and the following disclaimer in the 1372b676d7Smrg * documentation and/or other materials provided with the distribution. 1472b676d7Smrg * 3) The name of the author may not be used to endorse or promote products 1572b676d7Smrg * derived from this software without specific prior written permission. 1672b676d7Smrg * 1772b676d7Smrg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1872b676d7Smrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1972b676d7Smrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2072b676d7Smrg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2172b676d7Smrg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2272b676d7Smrg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2372b676d7Smrg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2472b676d7Smrg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2572b676d7Smrg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2672b676d7Smrg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2772b676d7Smrg * 2872b676d7Smrg * Author: Thomas Winischhofer <thomas@winischhofer.net> 2972b676d7Smrg * - driver entirely rewritten since 2001, only basic structure taken from 3072b676d7Smrg * old code (except sis_dri.c, sis_shadow.c, sis_accel.c and parts of 3172b676d7Smrg * sis_dga.c; these were mostly taken over; sis_dri.c was changed for 3272b676d7Smrg * new versions of the DRI layer) 3372b676d7Smrg * 3472b676d7Smrg * This notice covers the entire driver code unless indicated otherwise. 3572b676d7Smrg * 3672b676d7Smrg * Formerly based on code which was 3772b676d7Smrg * Copyright (C) 1998, 1999 by Alan Hourihane, Wigan, England. 3872b676d7Smrg * Written by: 3972b676d7Smrg * Alan Hourihane <alanh@fairlite.demon.co.uk>, 4072b676d7Smrg * Mike Chapman <mike@paranoia.com>, 4172b676d7Smrg * Juanjo Santamarta <santamarta@ctv.es>, 4272b676d7Smrg * Mitani Hiroshi <hmitani@drl.mei.co.jp>, 4372b676d7Smrg * David Thomas <davtom@dream.org.uk>. 4472b676d7Smrg */ 4572b676d7Smrg 4672b676d7Smrg#ifdef HAVE_CONFIG_H 4772b676d7Smrg#include "config.h" 4872b676d7Smrg#endif 4972b676d7Smrg 5072b676d7Smrg#include "sis.h" 5172b676d7Smrg 52e47418d9Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 5372b676d7Smrg#include "xf86RAC.h" 54e47418d9Smrg#endif 5572b676d7Smrg#include "dixstruct.h" 5672b676d7Smrg#include "shadowfb.h" 5772b676d7Smrg#include "fb.h" 5872b676d7Smrg#include "micmap.h" 5972b676d7Smrg#include "mipointer.h" 6072b676d7Smrg#include "mibstore.h" 6172b676d7Smrg#include "edid.h" 6272b676d7Smrg 6372b676d7Smrg#define SIS_NEED_inSISREG 6472b676d7Smrg#define SIS_NEED_inSISIDXREG 6572b676d7Smrg#define SIS_NEED_outSISIDXREG 6672b676d7Smrg#define SIS_NEED_orSISIDXREG 6772b676d7Smrg#define SIS_NEED_andSISIDXREG 6872b676d7Smrg#define SIS_NEED_setSISIDXREG 6972b676d7Smrg#define SIS_NEED_outSISREG 7072b676d7Smrg#define SIS_NEED_MYMMIO 7172b676d7Smrg#define SIS_NEED_sisclearvram 7272b676d7Smrg#include "sis_regs.h" 7372b676d7Smrg#include "sis_dac.h" 7472b676d7Smrg 7572b676d7Smrg#include "sis_driver.h" 7672b676d7Smrg 775788ca14Smrg#include <X11/extensions/xf86dgaproto.h> 7872b676d7Smrg 7972b676d7Smrg#include "globals.h" 8072b676d7Smrg 81e47418d9Smrg#ifdef HAVE_XEXTPROTO_71 82e47418d9Smrg#include <X11/extensions/dpmsconst.h> 83e47418d9Smrg#else 8472b676d7Smrg#define DPMS_SERVER 8572b676d7Smrg#include <X11/extensions/dpms.h> 86e47418d9Smrg#endif 87e47418d9Smrg 885788ca14Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 5 895788ca14Smrg#include <inputstr.h> /* for inputInfo */ 905788ca14Smrg#endif 915788ca14Smrg 9272b676d7Smrg 935788ca14Smrg#ifdef SISDRI 9472b676d7Smrg#include "dri.h" 9572b676d7Smrg#endif 9672b676d7Smrg 975788ca14Smrg/* 985788ca14Smrg * LookupWindow was removed with video abi 11. 995788ca14Smrg */ 1005788ca14Smrg#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 4) 1015788ca14Smrg#ifndef DixGetAttrAccess 1025788ca14Smrg#define DixGetAttrAccess (1<<4) 1035788ca14Smrg#endif 1045788ca14Smrg#endif 1055788ca14Smrg 1065788ca14Smrg#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 2) 1075788ca14Smrgstatic inline int 1085788ca14SmrgdixLookupWindow(WindowPtr *pWin, XID id, ClientPtr client, Mask access) 1095788ca14Smrg{ 1105788ca14Smrg *pWin = LookupWindow(id, client); 1115788ca14Smrg if (!*pWin) 1125788ca14Smrg return BadWindow; 1135788ca14Smrg return Success; 1145788ca14Smrg} 1155788ca14Smrg#endif 1165788ca14Smrg 11772b676d7Smrg/* Globals (yes, these ARE really required to be global) */ 11872b676d7Smrg 11972b676d7Smrg#ifdef SISUSEDEVPORT 12072b676d7Smrgint sisdevport = 0; 12172b676d7Smrg#endif 12272b676d7Smrg 12372b676d7Smrg#ifdef SISDUALHEAD 12472b676d7Smrgstatic int SISEntityIndex = -1; 12572b676d7Smrg#endif 12672b676d7Smrg 12772b676d7Smrg#ifdef SISMERGED 12872b676d7Smrg#ifdef SISXINERAMA 12972b676d7Smrgstatic Bool SiSnoPanoramiXExtension = TRUE; 13072b676d7Smrgstatic int SiSXineramaNumScreens = 0; 13172b676d7Smrgstatic SiSXineramaData *SiSXineramadataPtr = NULL; 13272b676d7Smrgstatic int SiSXineramaGeneration; 13372b676d7Smrg 13472b676d7Smrgstatic int SiSProcXineramaQueryVersion(ClientPtr client); 13572b676d7Smrgstatic int SiSProcXineramaGetState(ClientPtr client); 13672b676d7Smrgstatic int SiSProcXineramaGetScreenCount(ClientPtr client); 13772b676d7Smrgstatic int SiSProcXineramaGetScreenSize(ClientPtr client); 13872b676d7Smrgstatic int SiSProcXineramaIsActive(ClientPtr client); 13972b676d7Smrgstatic int SiSProcXineramaQueryScreens(ClientPtr client); 14072b676d7Smrgstatic int SiSSProcXineramaDispatch(ClientPtr client); 14172b676d7Smrg#endif 14272b676d7Smrg#endif 14372b676d7Smrg 14472b676d7Smrg/* 14572b676d7Smrg * This is intentionally screen-independent. It indicates the binding 14672b676d7Smrg * choice made in the first PreInit. 14772b676d7Smrg */ 14872b676d7Smrgstatic int pix24bpp = 0; 14972b676d7Smrg 15072b676d7Smrg/* 15172b676d7Smrg * This contains the functions needed by the server after loading the driver 15272b676d7Smrg * module. It must be supplied, and gets passed back by the SetupProc 15372b676d7Smrg * function in the dynamic case. In the static case, a reference to this 15472b676d7Smrg * is compiled in, and this requires that the name of this DriverRec be 15572b676d7Smrg * an upper-case version of the driver name. 15672b676d7Smrg */ 15772b676d7Smrg 15872b676d7Smrg#ifdef _X_EXPORT 15972b676d7Smrg_X_EXPORT 16072b676d7Smrg#endif 16172b676d7SmrgDriverRec SIS = { 16272b676d7Smrg SIS_CURRENT_VERSION, 16372b676d7Smrg SIS_DRIVER_NAME, 16472b676d7Smrg SISIdentify, 16572b676d7Smrg SISProbe, 16672b676d7Smrg SISAvailableOptions, 16772b676d7Smrg NULL, 16872b676d7Smrg 0 16972b676d7Smrg#ifdef SIS_HAVE_DRIVER_FUNC 17072b676d7Smrg , 17172b676d7Smrg SISDriverFunc 17272b676d7Smrg#endif 17372b676d7Smrg}; 17472b676d7Smrg 17572b676d7Smrgstatic SymTabRec SISChipsets[] = { 17672b676d7Smrg { PCI_CHIP_SIS5597, "SIS5597/5598" }, 17772b676d7Smrg { PCI_CHIP_SIS530, "SIS530/620" }, 17872b676d7Smrg { PCI_CHIP_SIS6326, "SIS6326/AGP/DVD" }, 17972b676d7Smrg { PCI_CHIP_SIS300, "SIS300/305" }, 18072b676d7Smrg { PCI_CHIP_SIS630, "SIS630/730" }, 18172b676d7Smrg { PCI_CHIP_SIS540, "SIS540" }, 18272b676d7Smrg { PCI_CHIP_SIS315, "SIS315" }, 18372b676d7Smrg { PCI_CHIP_SIS315H, "SIS315H" }, 18472b676d7Smrg { PCI_CHIP_SIS315PRO, "SIS315PRO/E" }, 18572b676d7Smrg { PCI_CHIP_SIS550, "SIS550" }, 18672b676d7Smrg { PCI_CHIP_SIS650, "SIS650/M650/651/740" }, 18772b676d7Smrg { PCI_CHIP_SIS330, "SIS330(Xabre)" }, 18872b676d7Smrg { PCI_CHIP_SIS660, "SIS660/[M]661[F|M]X/[M]670/[M]741[GX]/[M]760[GX]/[M]761[GX]/[M]770[GX]" }, 18972b676d7Smrg { PCI_CHIP_SIS340, "SIS340" }, 19072b676d7Smrg { -1, NULL } 19172b676d7Smrg}; 19272b676d7Smrg 19372b676d7Smrgstatic PciChipsets SISPciChipsets[] = { 19472b676d7Smrg { PCI_CHIP_SIS5597, PCI_CHIP_SIS5597, RES_SHARED_VGA }, 19572b676d7Smrg { PCI_CHIP_SIS530, PCI_CHIP_SIS530, RES_SHARED_VGA }, 19672b676d7Smrg { PCI_CHIP_SIS6326, PCI_CHIP_SIS6326, RES_SHARED_VGA }, 19772b676d7Smrg { PCI_CHIP_SIS300, PCI_CHIP_SIS300, RES_SHARED_VGA }, 19872b676d7Smrg { PCI_CHIP_SIS630, PCI_CHIP_SIS630, RES_SHARED_VGA }, 19972b676d7Smrg { PCI_CHIP_SIS540, PCI_CHIP_SIS540, RES_SHARED_VGA }, 20072b676d7Smrg { PCI_CHIP_SIS550, PCI_CHIP_SIS550, RES_SHARED_VGA }, 20172b676d7Smrg { PCI_CHIP_SIS315, PCI_CHIP_SIS315, RES_SHARED_VGA }, 20272b676d7Smrg { PCI_CHIP_SIS315H, PCI_CHIP_SIS315H, RES_SHARED_VGA }, 20372b676d7Smrg { PCI_CHIP_SIS315PRO, PCI_CHIP_SIS315PRO, RES_SHARED_VGA }, 20472b676d7Smrg { PCI_CHIP_SIS650, PCI_CHIP_SIS650, RES_SHARED_VGA }, 20572b676d7Smrg { PCI_CHIP_SIS330, PCI_CHIP_SIS330, RES_SHARED_VGA }, 20672b676d7Smrg { PCI_CHIP_SIS660, PCI_CHIP_SIS660, RES_SHARED_VGA }, 20772b676d7Smrg { PCI_CHIP_SIS340, PCI_CHIP_SIS340, RES_SHARED_VGA }, 20872b676d7Smrg { -1, -1, RES_UNDEFINED } 20972b676d7Smrg}; 21072b676d7Smrg 21172b676d7Smrgstatic SymTabRec XGIChipsets[] = { 21272b676d7Smrg { PCI_CHIP_XGIXG20, "Volari Z7 (XG20)" }, 21372b676d7Smrg { PCI_CHIP_XGIXG40, "Volari V3XT/V5/V8/Duo (XG40)" }, 21472b676d7Smrg { -1, NULL } 21572b676d7Smrg}; 21672b676d7Smrg 21772b676d7Smrgstatic PciChipsets XGIPciChipsets[] = { 21872b676d7Smrg { PCI_CHIP_XGIXG20, PCI_CHIP_XGIXG20, RES_SHARED_VGA }, 21972b676d7Smrg { PCI_CHIP_XGIXG40, PCI_CHIP_XGIXG40, RES_SHARED_VGA }, 22072b676d7Smrg { -1, -1, RES_UNDEFINED } 22172b676d7Smrg}; 22272b676d7Smrg 22372b676d7Smrg#ifdef XFree86LOADER 22472b676d7Smrg 22572b676d7Smrgstatic MODULESETUPPROTO(sisSetup); 22672b676d7Smrg 22772b676d7Smrgstatic XF86ModuleVersionInfo sisVersRec = 22872b676d7Smrg{ 22972b676d7Smrg SIS_DRIVER_NAME, 23072b676d7Smrg MODULEVENDORSTRING, 23172b676d7Smrg MODINFOSTRING1, 23272b676d7Smrg MODINFOSTRING2, 23372b676d7Smrg#ifdef XORG_VERSION_CURRENT 23472b676d7Smrg XORG_VERSION_CURRENT, 23572b676d7Smrg#else 23672b676d7Smrg XF86_VERSION_CURRENT, 23772b676d7Smrg#endif 23872b676d7Smrg SIS_MAJOR_VERSION, SIS_MINOR_VERSION, SIS_PATCHLEVEL, 23972b676d7Smrg ABI_CLASS_VIDEODRV, /* This is a video driver */ 24072b676d7Smrg ABI_VIDEODRV_VERSION, 24172b676d7Smrg MOD_CLASS_VIDEODRV, 24272b676d7Smrg {0,0,0,0} 24372b676d7Smrg}; 24472b676d7Smrg 24572b676d7Smrg#ifdef _X_EXPORT 24672b676d7Smrg_X_EXPORT 24772b676d7Smrg#endif 24872b676d7SmrgXF86ModuleData sisModuleData = { &sisVersRec, sisSetup, NULL }; 24972b676d7Smrg 25072b676d7Smrgpointer 25172b676d7SmrgsisSetup(pointer module, pointer opts, int *errmaj, int *errmin) 25272b676d7Smrg{ 25372b676d7Smrg static Bool setupDone = FALSE; 25472b676d7Smrg 25572b676d7Smrg if(!setupDone) { 25672b676d7Smrg setupDone = TRUE; 25772b676d7Smrg xf86AddDriver(&SIS, module, SIS_HaveDriverFuncs); 25872b676d7Smrg return (pointer)TRUE; 25972b676d7Smrg } 26072b676d7Smrg 26172b676d7Smrg if(errmaj) *errmaj = LDR_ONCEONLY; 26272b676d7Smrg return NULL; 26372b676d7Smrg} 26472b676d7Smrg 26572b676d7Smrg#endif /* XFree86LOADER */ 26672b676d7Smrg 26772b676d7Smrg/* Mandatory */ 26872b676d7Smrgstatic void 26972b676d7SmrgSISIdentify(int flags) 27072b676d7Smrg{ 27172b676d7Smrg xf86PrintChipsets(SIS_NAME, "driver for SiS chipsets", SISChipsets); 27272b676d7Smrg xf86PrintChipsets(SIS_NAME, "driver for XGI chipsets", XGIChipsets); 27372b676d7Smrg} 27472b676d7Smrg 27572b676d7Smrg#ifdef SIS_HAVE_DRIVER_FUNC 27672b676d7Smrgstatic Bool 27772b676d7SmrgSISDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op, pointer ptr) 27872b676d7Smrg{ 27972b676d7Smrg CARD32 *flag; 28072b676d7Smrg 28172b676d7Smrg switch(op) { 28272b676d7Smrg case RR_GET_INFO: 28372b676d7Smrg break; 28472b676d7Smrg case RR_SET_CONFIG: 28572b676d7Smrg break; 28672b676d7Smrg case GET_REQUIRED_HW_INTERFACES: 28772b676d7Smrg break; 28872b676d7Smrg } 28972b676d7Smrg return TRUE; 29072b676d7Smrg} 29172b676d7Smrg#endif 29272b676d7Smrg 29372b676d7Smrgstatic Bool 29472b676d7SmrgSISGetRec(ScrnInfoPtr pScrn) 29572b676d7Smrg{ 29672b676d7Smrg /* Allocate an SISRec, and hook it into pScrn->driverPrivate. 29772b676d7Smrg * pScrn->driverPrivate is initialised to NULL, so we can check if 29872b676d7Smrg * the allocation has already been done. 29972b676d7Smrg */ 30072b676d7Smrg if(pScrn->driverPrivate != NULL) return TRUE; 30172b676d7Smrg 30272b676d7Smrg pScrn->driverPrivate = xnfcalloc(sizeof(SISRec), 1); 30372b676d7Smrg 30472b676d7Smrg /* Initialise it to 0 */ 30572b676d7Smrg memset(pScrn->driverPrivate, 0, sizeof(SISRec)); 30672b676d7Smrg 30772b676d7Smrg return TRUE; 30872b676d7Smrg} 30972b676d7Smrg 31072b676d7Smrgstatic void 31172b676d7SmrgSISFreeRec(ScrnInfoPtr pScrn) 31272b676d7Smrg{ 31372b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 31472b676d7Smrg#ifdef SISDUALHEAD 31572b676d7Smrg SISEntPtr pSiSEnt = NULL; 31672b676d7Smrg#endif 31772b676d7Smrg 31872b676d7Smrg /* Just to make sure... */ 31972b676d7Smrg if(!pSiS) return; 32072b676d7Smrg 32172b676d7Smrg#ifdef SISDUALHEAD 32272b676d7Smrg pSiSEnt = pSiS->entityPrivate; 32372b676d7Smrg#endif 32472b676d7Smrg 3255788ca14Smrg if(pSiS->pstate) free(pSiS->pstate); 32672b676d7Smrg pSiS->pstate = NULL; 3275788ca14Smrg if(pSiS->fonts) free(pSiS->fonts); 32872b676d7Smrg pSiS->fonts = NULL; 32972b676d7Smrg 33072b676d7Smrg#ifdef SISDUALHEAD 33172b676d7Smrg if(pSiSEnt) { 33272b676d7Smrg if(!pSiS->SecondHead) { 33372b676d7Smrg /* Free memory only if we are first head; in case of an error 33472b676d7Smrg * during init of the second head, the server will continue - 33572b676d7Smrg * and we need the BIOS image and SiS_Private for the first 33672b676d7Smrg * head. 33772b676d7Smrg */ 3385788ca14Smrg if(pSiSEnt->BIOS) free(pSiSEnt->BIOS); 33972b676d7Smrg pSiSEnt->BIOS = pSiS->BIOS = NULL; 3405788ca14Smrg if(pSiSEnt->SiS_Pr) free(pSiSEnt->SiS_Pr); 34172b676d7Smrg pSiSEnt->SiS_Pr = pSiS->SiS_Pr = NULL; 3425788ca14Smrg if(pSiSEnt->RenderAccelArray) free(pSiSEnt->RenderAccelArray); 34372b676d7Smrg pSiSEnt->RenderAccelArray = pSiS->RenderAccelArray = NULL; 34472b676d7Smrg pSiSEnt->pScrn_1 = NULL; 34572b676d7Smrg } else { 34672b676d7Smrg pSiS->BIOS = NULL; 34772b676d7Smrg pSiS->SiS_Pr = NULL; 34872b676d7Smrg pSiS->RenderAccelArray = NULL; 34972b676d7Smrg pSiSEnt->pScrn_2 = NULL; 35072b676d7Smrg } 35172b676d7Smrg } else { 35272b676d7Smrg#endif 3535788ca14Smrg if(pSiS->BIOS) free(pSiS->BIOS); 35472b676d7Smrg pSiS->BIOS = NULL; 3555788ca14Smrg if(pSiS->SiS_Pr) free(pSiS->SiS_Pr); 35672b676d7Smrg pSiS->SiS_Pr = NULL; 3575788ca14Smrg if(pSiS->RenderAccelArray) free(pSiS->RenderAccelArray); 35872b676d7Smrg pSiS->RenderAccelArray = NULL; 35972b676d7Smrg#ifdef SISDUALHEAD 36072b676d7Smrg } 36172b676d7Smrg#endif 36272b676d7Smrg#ifdef SISMERGED 3635788ca14Smrg if(pSiS->CRT2HSync) free(pSiS->CRT2HSync); 36472b676d7Smrg pSiS->CRT2HSync = NULL; 3655788ca14Smrg if(pSiS->CRT2VRefresh) free(pSiS->CRT2VRefresh); 36672b676d7Smrg pSiS->CRT2VRefresh = NULL; 3675788ca14Smrg if(pSiS->MetaModes) free(pSiS->MetaModes); 36872b676d7Smrg pSiS->MetaModes = NULL; 36972b676d7Smrg if(pSiS->CRT2pScrn) { 37072b676d7Smrg if(pSiS->CRT2pScrn->modes) { 37172b676d7Smrg while(pSiS->CRT2pScrn->modes) 37272b676d7Smrg xf86DeleteMode(&pSiS->CRT2pScrn->modes, pSiS->CRT2pScrn->modes); 37372b676d7Smrg } 37472b676d7Smrg if(pSiS->CRT2pScrn->monitor) { 37572b676d7Smrg if(pSiS->CRT2pScrn->monitor->Modes) { 37672b676d7Smrg while(pSiS->CRT2pScrn->monitor->Modes) 37772b676d7Smrg xf86DeleteMode(&pSiS->CRT2pScrn->monitor->Modes, pSiS->CRT2pScrn->monitor->Modes); 37872b676d7Smrg } 3795788ca14Smrg if(pSiS->CRT2pScrn->monitor->DDC) free(pSiS->CRT2pScrn->monitor->DDC); 3805788ca14Smrg free(pSiS->CRT2pScrn->monitor); 38172b676d7Smrg } 3825788ca14Smrg free(pSiS->CRT2pScrn); 38372b676d7Smrg pSiS->CRT2pScrn = NULL; 38472b676d7Smrg } 38572b676d7Smrg if(pSiS->CRT1Modes) { 38672b676d7Smrg if(pSiS->CRT1Modes != pScrn->modes) { 38772b676d7Smrg if(pScrn->modes) { 38872b676d7Smrg pScrn->currentMode = pScrn->modes; 38972b676d7Smrg do { 39072b676d7Smrg DisplayModePtr p = pScrn->currentMode->next; 39172b676d7Smrg if(pScrn->currentMode->Private) 3925788ca14Smrg free(pScrn->currentMode->Private); 3935788ca14Smrg free(pScrn->currentMode); 39472b676d7Smrg pScrn->currentMode = p; 39572b676d7Smrg } while(pScrn->currentMode != pScrn->modes); 39672b676d7Smrg } 39772b676d7Smrg pScrn->currentMode = pSiS->CRT1CurrentMode; 39872b676d7Smrg pScrn->modes = pSiS->CRT1Modes; 39972b676d7Smrg pSiS->CRT1CurrentMode = NULL; 40072b676d7Smrg pSiS->CRT1Modes = NULL; 40172b676d7Smrg } 40272b676d7Smrg } 40372b676d7Smrg#endif 40472b676d7Smrg while(pSiS->SISVESAModeList) { 40572b676d7Smrg sisModeInfoPtr mp = pSiS->SISVESAModeList->next; 4065788ca14Smrg free(pSiS->SISVESAModeList); 40772b676d7Smrg pSiS->SISVESAModeList = mp; 40872b676d7Smrg } 40972b676d7Smrg if(pSiS->pVbe) vbeFree(pSiS->pVbe); 41072b676d7Smrg pSiS->pVbe = NULL; 41172b676d7Smrg 41272b676d7Smrg#ifdef SISUSEDEVPORT 41372b676d7Smrg if(pSiS->sisdevportopen) close(sisdevport); 41472b676d7Smrg#endif 41572b676d7Smrg 41672b676d7Smrg if(pScrn->driverPrivate == NULL) 41772b676d7Smrg return; 4185788ca14Smrg free(pScrn->driverPrivate); 41972b676d7Smrg pScrn->driverPrivate = NULL; 42072b676d7Smrg} 42172b676d7Smrg 42272b676d7Smrgstatic void 42372b676d7SmrgSISErrorLog(ScrnInfoPtr pScrn, const char *format, ...) 42472b676d7Smrg{ 42572b676d7Smrg va_list ap; 426721a3bc8Sjoerg static const char str[] = "**************************************************\n"; 42772b676d7Smrg 42872b676d7Smrg va_start(ap, format); 42972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, str); 43072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 43172b676d7Smrg " ERROR:\n"); 43272b676d7Smrg xf86VDrvMsgVerb(pScrn->scrnIndex, X_ERROR, 1, format, ap); 43372b676d7Smrg va_end(ap); 43472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 43572b676d7Smrg " END OF MESSAGE\n"); 43672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, str); 43772b676d7Smrg} 43872b676d7Smrg 43972b676d7Smrgstatic void 44072b676d7SmrgSiS_SiSFB_Lock(ScrnInfoPtr pScrn, Bool lock) 44172b676d7Smrg{ 44272b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 44372b676d7Smrg int fd; 44472b676d7Smrg CARD32 parm; 44572b676d7Smrg 44672b676d7Smrg if(!pSiS->sisfbfound) return; 44772b676d7Smrg if(!pSiS->sisfb_havelock) return; 44872b676d7Smrg 4491fd23544Smrg if((fd = open(pSiS->sisfbdevname, O_RDONLY)) != -1) { 45072b676d7Smrg parm = lock ? 1 : 0; 45172b676d7Smrg ioctl(fd, SISFB_SET_LOCK, &parm); 45272b676d7Smrg close(fd); 45372b676d7Smrg } 45472b676d7Smrg} 45572b676d7Smrg 45672b676d7Smrg/* Probe() 45772b676d7Smrg * 45872b676d7Smrg * Mandatory 45972b676d7Smrg */ 46072b676d7Smrgstatic Bool 46172b676d7SmrgSISProbe(DriverPtr drv, int flags) 46272b676d7Smrg{ 46372b676d7Smrg int i; 46472b676d7Smrg GDevPtr *devSections; 46572b676d7Smrg int *usedChipsSiS, *usedChipsXGI; 46672b676d7Smrg int numDevSections; 46772b676d7Smrg int numUsed, numUsedSiS, numUsedXGI; 46872b676d7Smrg Bool foundScreen = FALSE; 46972b676d7Smrg 47072b676d7Smrg /* 47172b676d7Smrg * The aim here is to find all cards that this driver can handle, 47272b676d7Smrg * and for the ones not already claimed by another driver, claim the 47372b676d7Smrg * slot, and allocate a ScrnInfoRec. 47472b676d7Smrg * 47572b676d7Smrg * This should be a minimal probe, and it should under no circumstances 47672b676d7Smrg * change the state of the hardware. Because a device is found, don't 47772b676d7Smrg * assume that it will be used. Don't do any initialisations other than 47872b676d7Smrg * the required ScrnInfoRec initialisations. Don't allocate any new 47972b676d7Smrg * data structures. 48072b676d7Smrg * 48172b676d7Smrg */ 48272b676d7Smrg 48372b676d7Smrg /* 48472b676d7Smrg * Next we check, if there has been a chipset override in the config file. 48572b676d7Smrg * For this we must find out if there is an active device section which 48672b676d7Smrg * is relevant, i.e., which has no driver specified or has THIS driver 48772b676d7Smrg * specified. 48872b676d7Smrg */ 48972b676d7Smrg 49072b676d7Smrg if((numDevSections = xf86MatchDevice(SIS_DRIVER_NAME, &devSections)) <= 0) { 49172b676d7Smrg /* 49272b676d7Smrg * There's no matching device section in the config file, so quit 49372b676d7Smrg * now. 49472b676d7Smrg */ 49572b676d7Smrg return FALSE; 49672b676d7Smrg } 49772b676d7Smrg 49872b676d7Smrg /* 49972b676d7Smrg * We need to probe the hardware first. We then need to see how this 50072b676d7Smrg * fits in with what is given in the config file, and allow the config 50172b676d7Smrg * file info to override any contradictions. 50272b676d7Smrg */ 50372b676d7Smrg 50472b676d7Smrg /* 50572b676d7Smrg * All of the cards this driver supports are PCI, so the "probing" just 50672b676d7Smrg * amounts to checking the PCI data that the server has already collected. 50772b676d7Smrg */ 5081fd23544Smrg#ifndef XSERVER_LIBPCIACCESS 50972b676d7Smrg if(xf86GetPciVideoInfo() == NULL) { 51072b676d7Smrg /* 51172b676d7Smrg * We won't let anything in the config file override finding no 51272b676d7Smrg * PCI video cards at all. 51372b676d7Smrg */ 51472b676d7Smrg return FALSE; 51572b676d7Smrg } 5161fd23544Smrg#endif 51772b676d7Smrg 51872b676d7Smrg numUsedSiS = xf86MatchPciInstances(SIS_NAME, PCI_VENDOR_SIS, 51972b676d7Smrg SISChipsets, SISPciChipsets, devSections, 52072b676d7Smrg numDevSections, drv, &usedChipsSiS); 52172b676d7Smrg 52272b676d7Smrg numUsedXGI = xf86MatchPciInstances(SIS_NAME, PCI_VENDOR_XGI, 52372b676d7Smrg XGIChipsets, XGIPciChipsets, devSections, 52472b676d7Smrg numDevSections, drv, &usedChipsXGI); 52572b676d7Smrg 52672b676d7Smrg /* Free it since we don't need that list after this */ 5275788ca14Smrg free(devSections); 52872b676d7Smrg 52972b676d7Smrg numUsed = numUsedSiS + numUsedXGI; 53072b676d7Smrg 53172b676d7Smrg if(numUsed <= 0) 53272b676d7Smrg return FALSE; 53372b676d7Smrg 53472b676d7Smrg if(flags & PROBE_DETECT) { 53572b676d7Smrg 53672b676d7Smrg foundScreen = TRUE; 53772b676d7Smrg 53872b676d7Smrg } else for(i = 0; i < numUsed; i++) { 53972b676d7Smrg 54072b676d7Smrg ScrnInfoPtr pScrn; 54172b676d7Smrg#ifdef SISDUALHEAD 54272b676d7Smrg EntityInfoPtr pEnt; 54372b676d7Smrg#endif 54472b676d7Smrg 54572b676d7Smrg /* Allocate a ScrnInfoRec and claim the slot */ 54672b676d7Smrg pScrn = NULL; 54772b676d7Smrg 54872b676d7Smrg if((pScrn = xf86ConfigPciEntity(pScrn, 0, 54972b676d7Smrg (i < numUsedSiS) ? usedChipsSiS[i] : usedChipsXGI[i-numUsedSiS], 55072b676d7Smrg (i < numUsedSiS) ? SISPciChipsets : XGIPciChipsets, 55172b676d7Smrg NULL, NULL, NULL, NULL, NULL))) { 55272b676d7Smrg /* Fill in what we can of the ScrnInfoRec */ 55372b676d7Smrg pScrn->driverVersion = SIS_CURRENT_VERSION; 55472b676d7Smrg pScrn->driverName = SIS_DRIVER_NAME; 55572b676d7Smrg pScrn->name = SIS_NAME; 55672b676d7Smrg pScrn->Probe = SISProbe; 55772b676d7Smrg pScrn->PreInit = SISPreInit; 55872b676d7Smrg pScrn->ScreenInit = SISScreenInit; 55972b676d7Smrg pScrn->SwitchMode = SISSwitchMode; 56072b676d7Smrg pScrn->AdjustFrame = SISAdjustFrame; 56172b676d7Smrg pScrn->EnterVT = SISEnterVT; 56272b676d7Smrg pScrn->LeaveVT = SISLeaveVT; 56372b676d7Smrg pScrn->FreeScreen = SISFreeScreen; 56472b676d7Smrg pScrn->ValidMode = SISValidMode; 5651fd23544Smrg 56672b676d7Smrg foundScreen = TRUE; 56772b676d7Smrg } 56872b676d7Smrg 56972b676d7Smrg#ifdef SISDUALHEAD 57072b676d7Smrg pEnt = xf86GetEntityInfo((i < numUsedSiS) ? usedChipsSiS[i] : usedChipsXGI[i-numUsedSiS]); 57172b676d7Smrg 57272b676d7Smrg if(pEnt->chipset == PCI_CHIP_SIS630 || pEnt->chipset == PCI_CHIP_SIS540 || 57372b676d7Smrg pEnt->chipset == PCI_CHIP_SIS650 || pEnt->chipset == PCI_CHIP_SIS550 || 57472b676d7Smrg pEnt->chipset == PCI_CHIP_SIS315 || pEnt->chipset == PCI_CHIP_SIS315H || 57572b676d7Smrg pEnt->chipset == PCI_CHIP_SIS315PRO || pEnt->chipset == PCI_CHIP_SIS330 || 57672b676d7Smrg pEnt->chipset == PCI_CHIP_SIS300 || pEnt->chipset == PCI_CHIP_SIS660 || 57772b676d7Smrg pEnt->chipset == PCI_CHIP_SIS340 || pEnt->chipset == PCI_CHIP_XGIXG40) { 57872b676d7Smrg 57972b676d7Smrg SISEntPtr pSiSEnt = NULL; 58072b676d7Smrg DevUnion *pPriv; 58172b676d7Smrg 58272b676d7Smrg xf86SetEntitySharable((i < numUsedSiS) ? usedChipsSiS[i] : usedChipsXGI[i-numUsedSiS]); 58372b676d7Smrg if(SISEntityIndex < 0) { 58472b676d7Smrg SISEntityIndex = xf86AllocateEntityPrivateIndex(); 58572b676d7Smrg } 58672b676d7Smrg pPriv = xf86GetEntityPrivate(pScrn->entityList[0], SISEntityIndex); 58772b676d7Smrg if(!pPriv->ptr) { 58872b676d7Smrg pPriv->ptr = xnfcalloc(sizeof(SISEntRec), 1); 58972b676d7Smrg pSiSEnt = pPriv->ptr; 59072b676d7Smrg memset(pSiSEnt, 0, sizeof(SISEntRec)); 59172b676d7Smrg pSiSEnt->lastInstance = -1; 59272b676d7Smrg } else { 59372b676d7Smrg pSiSEnt = pPriv->ptr; 59472b676d7Smrg } 59572b676d7Smrg pSiSEnt->lastInstance++; 59672b676d7Smrg xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0], 59772b676d7Smrg pSiSEnt->lastInstance); 59872b676d7Smrg } 59972b676d7Smrg#endif /* DUALHEAD */ 60072b676d7Smrg 60172b676d7Smrg } 60272b676d7Smrg 6035788ca14Smrg if(usedChipsSiS) free(usedChipsSiS); 6045788ca14Smrg if(usedChipsXGI) free(usedChipsXGI); 60572b676d7Smrg 60672b676d7Smrg return foundScreen; 60772b676d7Smrg} 60872b676d7Smrg 60972b676d7Smrg/* Various helpers */ 61072b676d7Smrg 61172b676d7Smrgstatic unsigned short 61272b676d7Smrgcalcgammaval(int j, int nramp, float invgamma, float bri, float c) 61372b676d7Smrg{ 61472b676d7Smrg float k = (float)j; 61572b676d7Smrg float nrm1 = (float)(nramp - 1); 61672b676d7Smrg float con = c * nrm1 / 3.0; 61772b676d7Smrg float l, v; 61872b676d7Smrg 61972b676d7Smrg if(con != 0.0) { 62072b676d7Smrg l = nrm1 / 2.0; 62172b676d7Smrg if(con <= 0.0) { 62272b676d7Smrg k -= l; 62372b676d7Smrg k *= (l + con) / l; 62472b676d7Smrg } else { 62572b676d7Smrg l -= 1.0; 62672b676d7Smrg k -= l; 62772b676d7Smrg k *= l / (l - con); 62872b676d7Smrg } 62972b676d7Smrg k += l; 63072b676d7Smrg if(k < 0.0) k = 0.0; 63172b676d7Smrg } 63272b676d7Smrg 63372b676d7Smrg if(invgamma == 1.0) { 63472b676d7Smrg v = k / nrm1 * 65535.0; 63572b676d7Smrg } else { 63672b676d7Smrg v = pow(k / nrm1, invgamma) * 65535.0 + 0.5; 63772b676d7Smrg } 63872b676d7Smrg 63972b676d7Smrg v += (bri * (65535.0 / 3.0)) ; 64072b676d7Smrg 64172b676d7Smrg if(v < 0.0) v = 0.0; 64272b676d7Smrg else if(v > 65535.0) v = 65535.0; 64372b676d7Smrg 64472b676d7Smrg return (unsigned short)v; 64572b676d7Smrg} 64672b676d7Smrg 64772b676d7Smrg#ifdef SISGAMMARAMP 64872b676d7Smrgvoid 64972b676d7SmrgSISCalculateGammaRamp(ScreenPtr pScreen, ScrnInfoPtr pScrn) 65072b676d7Smrg{ 65172b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 65272b676d7Smrg int i, j, nramp; 65372b676d7Smrg UShort *ramp[3]; 65472b676d7Smrg float gamma_max[3], framp; 65572b676d7Smrg Bool newmethod = FALSE; 65672b676d7Smrg 65772b676d7Smrg if(!(pSiS->SiS_SD3_Flags & SiS_SD3_OLDGAMMAINUSE)) { 65872b676d7Smrg newmethod = TRUE; 65972b676d7Smrg } else { 66072b676d7Smrg gamma_max[0] = (float)pSiS->GammaBriR / 1000; 66172b676d7Smrg gamma_max[1] = (float)pSiS->GammaBriG / 1000; 66272b676d7Smrg gamma_max[2] = (float)pSiS->GammaBriB / 1000; 66372b676d7Smrg } 66472b676d7Smrg 66572b676d7Smrg if(!(nramp = xf86GetGammaRampSize(pScreen))) return; 66672b676d7Smrg 66772b676d7Smrg for(i=0; i<3; i++) { 6685788ca14Smrg ramp[i] = (UShort *)malloc(nramp * sizeof(UShort)); 66972b676d7Smrg if(!ramp[i]) { 6705788ca14Smrg if(ramp[0]) { free(ramp[0]); ramp[0] = NULL; } 6715788ca14Smrg if(ramp[1]) { free(ramp[1]); ramp[1] = NULL; } 67272b676d7Smrg return; 67372b676d7Smrg } 67472b676d7Smrg } 67572b676d7Smrg 67672b676d7Smrg if(newmethod) { 67772b676d7Smrg 67872b676d7Smrg for(i = 0; i < 3; i++) { 67972b676d7Smrg 68072b676d7Smrg float invgamma = 0.0, bri = 0.0, con = 0.0; 68172b676d7Smrg 68272b676d7Smrg switch(i) { 68372b676d7Smrg case 0: invgamma = 1. / pScrn->gamma.red; 68472b676d7Smrg bri = pSiS->NewGammaBriR; 68572b676d7Smrg con = pSiS->NewGammaConR; 68672b676d7Smrg break; 68772b676d7Smrg case 1: invgamma = 1. / pScrn->gamma.green; 68872b676d7Smrg bri = pSiS->NewGammaBriG; 68972b676d7Smrg con = pSiS->NewGammaConG; 69072b676d7Smrg break; 69172b676d7Smrg case 2: invgamma = 1. / pScrn->gamma.blue; 69272b676d7Smrg bri = pSiS->NewGammaBriB; 69372b676d7Smrg con = pSiS->NewGammaConB; 69472b676d7Smrg break; 69572b676d7Smrg } 69672b676d7Smrg 69772b676d7Smrg for(j = 0; j < nramp; j++) { 69872b676d7Smrg ramp[i][j] = calcgammaval(j, nramp, invgamma, bri, con); 69972b676d7Smrg } 70072b676d7Smrg 70172b676d7Smrg } 70272b676d7Smrg 70372b676d7Smrg } else { 70472b676d7Smrg 70572b676d7Smrg for(i = 0; i < 3; i++) { 70672b676d7Smrg int fullscale = 65535 * gamma_max[i]; 70772b676d7Smrg float dramp = 1. / (nramp - 1); 70872b676d7Smrg float invgamma = 0.0, v; 70972b676d7Smrg 71072b676d7Smrg switch(i) { 71172b676d7Smrg case 0: invgamma = 1. / pScrn->gamma.red; break; 71272b676d7Smrg case 1: invgamma = 1. / pScrn->gamma.green; break; 71372b676d7Smrg case 2: invgamma = 1. / pScrn->gamma.blue; break; 71472b676d7Smrg } 71572b676d7Smrg 71672b676d7Smrg for(j = 0; j < nramp; j++) { 71772b676d7Smrg framp = pow(j * dramp, invgamma); 71872b676d7Smrg 71972b676d7Smrg v = (fullscale < 0) ? (65535 + fullscale * framp) : 72072b676d7Smrg fullscale * framp; 72172b676d7Smrg if(v < 0) v = 0; 72272b676d7Smrg else if(v > 65535) v = 65535; 72372b676d7Smrg ramp[i][j] = (UShort)v; 72472b676d7Smrg } 72572b676d7Smrg } 72672b676d7Smrg 72772b676d7Smrg } 72872b676d7Smrg 72972b676d7Smrg xf86ChangeGammaRamp(pScreen, nramp, ramp[0], ramp[1], ramp[2]); 73072b676d7Smrg 7315788ca14Smrg free(ramp[0]); 7325788ca14Smrg free(ramp[1]); 7335788ca14Smrg free(ramp[2]); 73472b676d7Smrg ramp[0] = ramp[1] = ramp[2] = NULL; 73572b676d7Smrg} 73672b676d7Smrg#endif 73772b676d7Smrg 73872b676d7Smrgvoid 73972b676d7SmrgSISCalculateGammaRampCRT2(ScrnInfoPtr pScrn) 74072b676d7Smrg{ 74172b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 74272b676d7Smrg int i; 74372b676d7Smrg int myshift = 16 - pScrn->rgbBits; 74472b676d7Smrg int maxvalue = (1 << pScrn->rgbBits) - 1; 74572b676d7Smrg int reds = pScrn->mask.red >> pScrn->offset.red; 74672b676d7Smrg int greens = pScrn->mask.green >> pScrn->offset.green; 74772b676d7Smrg int blues = pScrn->mask.blue >> pScrn->offset.blue; 74872b676d7Smrg float framp, invgamma1, invgamma2, invgamma3, v; 74972b676d7Smrg 75072b676d7Smrg invgamma1 = 1. / pSiS->GammaR2; 75172b676d7Smrg invgamma2 = 1. / pSiS->GammaG2; 75272b676d7Smrg invgamma3 = 1. / pSiS->GammaB2; 75372b676d7Smrg 75472b676d7Smrg if(!(pSiS->SiS_SD3_Flags & SiS_SD3_OLDGAMMAINUSE)) { 75572b676d7Smrg 75672b676d7Smrg for(i = 0; i < pSiS->CRT2ColNum; i++) { 75772b676d7Smrg pSiS->crt2gcolortable[i].red = calcgammaval(i, pSiS->CRT2ColNum, invgamma1, 75872b676d7Smrg pSiS->NewGammaBriR2, pSiS->NewGammaConR2) >> myshift; 75972b676d7Smrg pSiS->crt2gcolortable[i].green = calcgammaval(i, pSiS->CRT2ColNum, invgamma2, 76072b676d7Smrg pSiS->NewGammaBriG2, pSiS->NewGammaConG2) >> myshift; 76172b676d7Smrg pSiS->crt2gcolortable[i].blue = calcgammaval(i, pSiS->CRT2ColNum, invgamma3, 76272b676d7Smrg pSiS->NewGammaBriB2, pSiS->NewGammaConB2) >> myshift; 76372b676d7Smrg } 76472b676d7Smrg 76572b676d7Smrg } else { 76672b676d7Smrg 76772b676d7Smrg int fullscale1 = 65536 * (float)pSiS->GammaBriR2 / 1000; 76872b676d7Smrg int fullscale2 = 65536 * (float)pSiS->GammaBriG2 / 1000; 76972b676d7Smrg int fullscale3 = 65536 * (float)pSiS->GammaBriB2 / 1000; 77072b676d7Smrg 77172b676d7Smrg float dramp = 1. / (pSiS->CRT2ColNum - 1); 77272b676d7Smrg 77372b676d7Smrg for(i = 0; i < pSiS->CRT2ColNum; i++) { 77472b676d7Smrg framp = pow(i * dramp, invgamma1); 77572b676d7Smrg v = (fullscale1 < 0) ? (65535 + fullscale1 * framp) : fullscale1 * framp; 77672b676d7Smrg if(v < 0) v = 0; 77772b676d7Smrg else if(v > 65535) v = 65535; 77872b676d7Smrg pSiS->crt2gcolortable[i].red = ((UShort)v) >> myshift; 77972b676d7Smrg framp = pow(i * dramp, invgamma2); 78072b676d7Smrg v = (fullscale2 < 0) ? (65535 + fullscale2 * framp) : fullscale2 * framp; 78172b676d7Smrg if(v < 0) v = 0; 78272b676d7Smrg else if(v > 65535) v = 65535; 78372b676d7Smrg pSiS->crt2gcolortable[i].green = ((UShort)v) >> myshift; 78472b676d7Smrg framp = pow(i * dramp, invgamma3); 78572b676d7Smrg v = (fullscale3 < 0) ? (65535 + fullscale3 * framp) : fullscale3 * framp; 78672b676d7Smrg if(v < 0) v = 0; 78772b676d7Smrg else if(v > 65535) v = 65535; 78872b676d7Smrg pSiS->crt2gcolortable[i].blue = ((UShort)v) >> myshift; 78972b676d7Smrg } 79072b676d7Smrg 79172b676d7Smrg } 79272b676d7Smrg 79372b676d7Smrg for(i = 0; i < pSiS->CRT2ColNum; i++) { 79472b676d7Smrg pSiS->crt2colors[i].red = 79572b676d7Smrg pSiS->crt2gcolortable[i * maxvalue / reds].red; 79672b676d7Smrg pSiS->crt2colors[i].green = 79772b676d7Smrg pSiS->crt2gcolortable[i * maxvalue / greens].green; 79872b676d7Smrg pSiS->crt2colors[i].blue = 79972b676d7Smrg pSiS->crt2gcolortable[i * maxvalue / blues].blue; 80072b676d7Smrg } 80172b676d7Smrg} 80272b676d7Smrg 80372b676d7Smrg/* If monitor section has no HSync/VRefresh data, 80472b676d7Smrg * derive it from DDC data. 80572b676d7Smrg */ 80672b676d7Smrgstatic void 80772b676d7SmrgSiSSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) 80872b676d7Smrg{ 80972b676d7Smrg MonPtr mon = pScrn->monitor; 81072b676d7Smrg xf86MonPtr ddc = mon->DDC; 81172b676d7Smrg float myhhigh = 0.0, myhlow = 0.0, htest; 81272b676d7Smrg int myvhigh = 0, myvlow = 0, vtest, i; 81372b676d7Smrg UChar temp; 81472b676d7Smrg const myhddctiming myhtiming[12] = { 81572b676d7Smrg { 1, 0x20, 31.6 }, /* rounded up by .1 */ 81672b676d7Smrg { 1, 0x80, 31.6 }, 81772b676d7Smrg { 1, 0x02, 35.3 }, 81872b676d7Smrg { 1, 0x04, 37.6 }, 81972b676d7Smrg { 1, 0x08, 38.0 }, 82072b676d7Smrg { 1, 0x01, 38.0 }, 82172b676d7Smrg { 2, 0x40, 47.0 }, 82272b676d7Smrg { 2, 0x80, 48.2 }, 82372b676d7Smrg { 2, 0x08, 48.5 }, 82472b676d7Smrg { 2, 0x04, 56.6 }, 82572b676d7Smrg { 2, 0x02, 60.1 }, 82672b676d7Smrg { 2, 0x01, 80.1 } 82772b676d7Smrg }; 82872b676d7Smrg const myvddctiming myvtiming[11] = { 82972b676d7Smrg { 1, 0x02, 56 }, 83072b676d7Smrg { 1, 0x01, 60 }, 83172b676d7Smrg { 2, 0x08, 60 }, 83272b676d7Smrg { 2, 0x04, 70 }, 83372b676d7Smrg { 1, 0x80, 71 }, 83472b676d7Smrg { 1, 0x08, 72 }, 83572b676d7Smrg { 2, 0x80, 72 }, 83672b676d7Smrg { 1, 0x04, 75 }, 83772b676d7Smrg { 2, 0x40, 75 }, 83872b676d7Smrg { 2, 0x02, 75 }, 83972b676d7Smrg { 2, 0x01, 75 } 84072b676d7Smrg }; 84172b676d7Smrg 84272b676d7Smrg if(flag) { /* HSync */ 84372b676d7Smrg 84472b676d7Smrg for(i = 0; i < 4; i++) { 84572b676d7Smrg if(ddc->det_mon[i].type == DS_RANGES) { 84672b676d7Smrg mon->nHsync = 1; 84772b676d7Smrg mon->hsync[0].lo = ddc->det_mon[i].section.ranges.min_h; 84872b676d7Smrg mon->hsync[0].hi = ddc->det_mon[i].section.ranges.max_h; 84972b676d7Smrg if(mon->hsync[0].lo > 32.0 || mon->hsync[0].hi < 31.0) { 85072b676d7Smrg if(ddc->timings1.t1 & 0x80) { 85172b676d7Smrg mon->nHsync++; 85272b676d7Smrg mon->hsync[1].lo = 31.0; 85372b676d7Smrg mon->hsync[1].hi = 32.0; 85472b676d7Smrg } 85572b676d7Smrg } 85672b676d7Smrg return; 85772b676d7Smrg } 85872b676d7Smrg } 85972b676d7Smrg 86072b676d7Smrg /* If no sync ranges detected in detailed timing table, we 86172b676d7Smrg * derive them from supported VESA modes. 86272b676d7Smrg */ 86372b676d7Smrg 86472b676d7Smrg for(i = 0; i < 12; i++) { 86572b676d7Smrg if(myhtiming[i].whichone == 1) temp = ddc->timings1.t1; 86672b676d7Smrg else temp = ddc->timings1.t2; 86772b676d7Smrg if(temp & myhtiming[i].mask) { 86872b676d7Smrg if((i == 0) || (myhlow > myhtiming[i].rate)) 86972b676d7Smrg myhlow = myhtiming[i].rate; 87072b676d7Smrg } 87172b676d7Smrg if(myhtiming[11-i].whichone == 1) temp = ddc->timings1.t1; 87272b676d7Smrg else temp = ddc->timings1.t2; 87372b676d7Smrg if(temp & myhtiming[11-i].mask) { 87472b676d7Smrg if((i == 0) || (myhhigh < myhtiming[11-i].rate)) 87572b676d7Smrg myhhigh = myhtiming[11-i].rate; 87672b676d7Smrg } 87772b676d7Smrg } 87872b676d7Smrg 87972b676d7Smrg for(i = 0; i < STD_TIMINGS; i++) { 88072b676d7Smrg if(ddc->timings2[i].hsize > 256) { 88172b676d7Smrg htest = ddc->timings2[i].refresh * 1.05 * ddc->timings2[i].vsize / 1000.0; 88272b676d7Smrg if(htest < myhlow) myhlow = htest; 88372b676d7Smrg if(htest > myhhigh) myhhigh = htest; 88472b676d7Smrg } 88572b676d7Smrg } 88672b676d7Smrg 88772b676d7Smrg if((myhhigh > 0.0) && (myhlow > 0.0)) { 88872b676d7Smrg mon->nHsync = 1; 88972b676d7Smrg mon->hsync[0].lo = myhlow - 0.1; 89072b676d7Smrg mon->hsync[0].hi = myhhigh; 89172b676d7Smrg } 89272b676d7Smrg 89372b676d7Smrg 89472b676d7Smrg } else { /* Vrefresh */ 89572b676d7Smrg 89672b676d7Smrg for(i = 0; i < 4; i++) { 89772b676d7Smrg if(ddc->det_mon[i].type == DS_RANGES) { 89872b676d7Smrg mon->nVrefresh = 1; 89972b676d7Smrg mon->vrefresh[0].lo = ddc->det_mon[i].section.ranges.min_v; 90072b676d7Smrg mon->vrefresh[0].hi = ddc->det_mon[i].section.ranges.max_v; 90172b676d7Smrg if(mon->vrefresh[0].lo > 72 || mon->vrefresh[0].hi < 70) { 90272b676d7Smrg if(ddc->timings1.t1 & 0x80) { 90372b676d7Smrg mon->nVrefresh++; 90472b676d7Smrg mon->vrefresh[1].lo = 71; 90572b676d7Smrg mon->vrefresh[1].hi = 71; 90672b676d7Smrg } 90772b676d7Smrg } 90872b676d7Smrg return; 90972b676d7Smrg } 91072b676d7Smrg } 91172b676d7Smrg 91272b676d7Smrg for(i = 0; i < 11; i++) { 91372b676d7Smrg if(myvtiming[i].whichone == 1) temp = ddc->timings1.t1; 91472b676d7Smrg else temp = ddc->timings1.t2; 91572b676d7Smrg if(temp & myvtiming[i].mask) { 91672b676d7Smrg if((i == 0) || (myvlow > myvtiming[i].rate)) 91772b676d7Smrg myvlow = myvtiming[i].rate; 91872b676d7Smrg } 91972b676d7Smrg if(myvtiming[10-i].whichone == 1) temp = ddc->timings1.t1; 92072b676d7Smrg else temp = ddc->timings1.t2; 92172b676d7Smrg if(temp & myvtiming[10-i].mask) { 92272b676d7Smrg if((i == 0) || (myvhigh < myvtiming[10-i].rate)) 92372b676d7Smrg myvhigh = myvtiming[10-i].rate; 92472b676d7Smrg } 92572b676d7Smrg } 92672b676d7Smrg 92772b676d7Smrg for(i = 0; i < STD_TIMINGS; i++) { 92872b676d7Smrg if(ddc->timings2[i].hsize > 256) { 92972b676d7Smrg vtest = ddc->timings2[i].refresh; 93072b676d7Smrg if(vtest < myvlow) myvlow = vtest; 93172b676d7Smrg if(vtest > myvhigh) myvhigh = vtest; 93272b676d7Smrg } 93372b676d7Smrg } 93472b676d7Smrg 93572b676d7Smrg if((myvhigh > 0) && (myvlow > 0)) { 93672b676d7Smrg mon->nVrefresh = 1; 93772b676d7Smrg mon->vrefresh[0].lo = myvlow; 93872b676d7Smrg mon->vrefresh[0].hi = myvhigh; 93972b676d7Smrg } 94072b676d7Smrg 94172b676d7Smrg } 94272b676d7Smrg} 94372b676d7Smrg 94472b676d7Smrgstatic Bool 94572b676d7SmrgSiSAllowSyncOverride(SISPtr pSiS, Bool fromDDC) 94672b676d7Smrg{ 94772b676d7Smrg if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return FALSE; 94872b676d7Smrg 94972b676d7Smrg#ifdef SISDUALHEAD 95072b676d7Smrg if(pSiS->DualHeadMode) { 95172b676d7Smrg if(pSiS->SecondHead) { 95272b676d7Smrg if((pSiS->VBFlags & CRT1_LCDA) && (!fromDDC)) return TRUE; 95372b676d7Smrg } else { 95472b676d7Smrg if((pSiS->VBFlags & CRT2_TV) || 95572b676d7Smrg ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC))) return TRUE; 95672b676d7Smrg } 95772b676d7Smrg return FALSE; 95872b676d7Smrg } 95972b676d7Smrg#endif 96072b676d7Smrg 96172b676d7Smrg#ifdef SISMERGED 96272b676d7Smrg if(pSiS->MergedFB) { 96372b676d7Smrg if((pSiS->VBFlags & CRT1_LCDA) && (!fromDDC)) return TRUE; 96472b676d7Smrg return FALSE; 96572b676d7Smrg } 96672b676d7Smrg#endif 96772b676d7Smrg 96872b676d7Smrg if(!(pSiS->VBFlags & DISPTYPE_CRT1)) { 96972b676d7Smrg if( (pSiS->VBFlags & CRT2_TV) || 97072b676d7Smrg ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC)) ) return TRUE; 97172b676d7Smrg } else if((pSiS->VBFlags & CRT1_LCDA) && (!fromDDC)) return TRUE; 97272b676d7Smrg 97372b676d7Smrg return FALSE; 97472b676d7Smrg} 97572b676d7Smrg 97672b676d7Smrgstatic Bool 97772b676d7SmrgSiSCheckForH(float hsync, MonPtr monitor) 97872b676d7Smrg{ 97972b676d7Smrg int i; 98072b676d7Smrg for(i = 0; i < monitor->nHsync; i++) { 98172b676d7Smrg if((hsync > monitor->hsync[i].lo * (1.0 - SYNC_TOLERANCE)) && 98272b676d7Smrg (hsync < monitor->hsync[i].hi * (1.0 + SYNC_TOLERANCE))) 98372b676d7Smrg break; 98472b676d7Smrg } 98572b676d7Smrg if(i == monitor->nHsync) return FALSE; 98672b676d7Smrg return TRUE; 98772b676d7Smrg} 98872b676d7Smrg 98972b676d7Smrgstatic Bool 99072b676d7SmrgSiSCheckForV(float vrefresh, MonPtr monitor) 99172b676d7Smrg{ 99272b676d7Smrg int i; 99372b676d7Smrg for(i = 0; i < monitor->nVrefresh; i++) { 99472b676d7Smrg if((vrefresh > monitor->vrefresh[i].lo * (1.0 - SYNC_TOLERANCE)) && 99572b676d7Smrg (vrefresh < monitor->vrefresh[i].hi * (1.0 + SYNC_TOLERANCE))) 99672b676d7Smrg break; 99772b676d7Smrg } 99872b676d7Smrg if(i == monitor->nVrefresh) return FALSE; 99972b676d7Smrg return TRUE; 100072b676d7Smrg} 100172b676d7Smrg 100272b676d7Smrgstatic Bool 100372b676d7SmrgCheckAndOverruleH(ScrnInfoPtr pScrn, MonPtr monitor) 100472b676d7Smrg{ 100572b676d7Smrg DisplayModePtr mode = monitor->Modes; 100672b676d7Smrg float mymin = 30.0, mymax = 80.0, hsync; 100772b676d7Smrg Bool doit = FALSE; 100872b676d7Smrg 100972b676d7Smrg for(hsync = mymin; hsync <= mymax; hsync += .5) { 101072b676d7Smrg if(!SiSCheckForH(hsync, monitor)) doit = TRUE; 101172b676d7Smrg } 101272b676d7Smrg 101372b676d7Smrg if(mode) { 101472b676d7Smrg do { 101572b676d7Smrg if(mode->type & M_T_BUILTIN) { 101672b676d7Smrg hsync = (float)mode->Clock / (float)mode->HTotal; 101772b676d7Smrg if(!SiSCheckForH(hsync, monitor)) { 101872b676d7Smrg doit = TRUE; 101972b676d7Smrg if(hsync < mymin) mymin = hsync; 102072b676d7Smrg if(hsync > mymax) mymax = hsync; 102172b676d7Smrg } 102272b676d7Smrg } 102372b676d7Smrg } while((mode = mode->next)); 102472b676d7Smrg } 102572b676d7Smrg 102672b676d7Smrg if(doit) { 102772b676d7Smrg monitor->nHsync = 1; 102872b676d7Smrg monitor->hsync[0].lo = mymin; 102972b676d7Smrg monitor->hsync[0].hi = mymax; 103072b676d7Smrg return TRUE; 103172b676d7Smrg } 103272b676d7Smrg 103372b676d7Smrg return FALSE; 103472b676d7Smrg} 103572b676d7Smrg 103672b676d7Smrgstatic Bool 103772b676d7SmrgCheckAndOverruleV(ScrnInfoPtr pScrn, MonPtr monitor) 103872b676d7Smrg{ 103972b676d7Smrg DisplayModePtr mode = monitor->Modes; 104072b676d7Smrg float mymin = 59.0, mymax = 61.0, vrefresh; 104172b676d7Smrg Bool doit = FALSE, ret = FALSE; 104272b676d7Smrg 104372b676d7Smrg for(vrefresh = mymin; vrefresh <= mymax; vrefresh += 1.0) { 104472b676d7Smrg if(!SiSCheckForV(vrefresh, monitor)) doit = TRUE; 104572b676d7Smrg } 104672b676d7Smrg 104772b676d7Smrg if(mode) { 104872b676d7Smrg do { 104972b676d7Smrg if(mode->type & M_T_BUILTIN) { 105072b676d7Smrg vrefresh = mode->Clock * 1000.0 / (mode->HTotal * mode->VTotal); 105172b676d7Smrg if(mode->Flags & V_INTERLACE) vrefresh *= 2.0; 105272b676d7Smrg if(mode->Flags & V_DBLSCAN) vrefresh /= 2.0; 105372b676d7Smrg if(!SiSCheckForH(vrefresh, monitor)) { 105472b676d7Smrg doit = TRUE; 105572b676d7Smrg if(vrefresh < mymin) mymin = vrefresh; 105672b676d7Smrg if(vrefresh > mymax) mymax = vrefresh; 105772b676d7Smrg } 105872b676d7Smrg } 105972b676d7Smrg } while((mode = mode->next)); 106072b676d7Smrg } 106172b676d7Smrg 106272b676d7Smrg if(doit) { 106372b676d7Smrg monitor->nVrefresh = 1; 106472b676d7Smrg monitor->vrefresh[0].lo = mymin; 106572b676d7Smrg monitor->vrefresh[0].hi = mymax; 106672b676d7Smrg ret = TRUE; 106772b676d7Smrg } 106872b676d7Smrg 106972b676d7Smrg /* special for 640x400/320x200/@70Hz (VGA/IBM 720x480) */ 107072b676d7Smrg if( (!SiSCheckForV(71, monitor)) && 107172b676d7Smrg (monitor->nVrefresh < MAX_VREFRESH) ) { 107272b676d7Smrg monitor->vrefresh[monitor->nVrefresh].lo = 71; 107372b676d7Smrg monitor->vrefresh[monitor->nVrefresh].hi = 71; 107472b676d7Smrg monitor->nVrefresh++; 107572b676d7Smrg ret = TRUE; 107672b676d7Smrg } 107772b676d7Smrg return ret; 107872b676d7Smrg} 107972b676d7Smrg 108072b676d7Smrg/* Some helper functions for MergedFB mode */ 108172b676d7Smrg 108272b676d7Smrg#ifdef SISMERGED 108372b676d7Smrg 108472b676d7Smrg/* Helper function for CRT2 monitor vrefresh/hsync options 108572b676d7Smrg * (Code base from mga driver) 108672b676d7Smrg */ 108772b676d7Smrgstatic int 108872b676d7SmrgSiSStrToRanges(range *r, char *s, int max) 108972b676d7Smrg{ 109072b676d7Smrg float num = 0.0; 109172b676d7Smrg int rangenum = 0; 109272b676d7Smrg Bool gotdash = FALSE; 109372b676d7Smrg Bool nextdash = FALSE; 109472b676d7Smrg char *strnum = NULL; 109572b676d7Smrg do { 109672b676d7Smrg switch(*s) { 109772b676d7Smrg case '0': 109872b676d7Smrg case '1': 109972b676d7Smrg case '2': 110072b676d7Smrg case '3': 110172b676d7Smrg case '4': 110272b676d7Smrg case '5': 110372b676d7Smrg case '6': 110472b676d7Smrg case '7': 110572b676d7Smrg case '8': 110672b676d7Smrg case '9': 110772b676d7Smrg case '.': 110872b676d7Smrg if(strnum == NULL) { 110972b676d7Smrg strnum = s; 111072b676d7Smrg gotdash = nextdash; 111172b676d7Smrg nextdash = FALSE; 111272b676d7Smrg } 111372b676d7Smrg break; 111472b676d7Smrg case '-': 111572b676d7Smrg case ' ': 111672b676d7Smrg case 0: 111772b676d7Smrg if(strnum == NULL) break; 111872b676d7Smrg sscanf(strnum, "%f", &num); 111972b676d7Smrg strnum = NULL; 112072b676d7Smrg if(gotdash) { 112172b676d7Smrg r[rangenum - 1].hi = num; 112272b676d7Smrg } else { 112372b676d7Smrg r[rangenum].lo = num; 112472b676d7Smrg r[rangenum].hi = num; 112572b676d7Smrg rangenum++; 112672b676d7Smrg } 112772b676d7Smrg if(*s == '-') nextdash = (rangenum != 0); 112872b676d7Smrg else if(rangenum >= max) return rangenum; 112972b676d7Smrg break; 113072b676d7Smrg default: 113172b676d7Smrg return 0; 113272b676d7Smrg } 113372b676d7Smrg 113472b676d7Smrg } while(*(s++) != 0); 113572b676d7Smrg 113672b676d7Smrg return rangenum; 113772b676d7Smrg} 113872b676d7Smrg 113972b676d7Smrg/* Copy and link two modes (i, j) for mergedfb mode 114072b676d7Smrg * (Code base taken from mga driver) 114172b676d7Smrg * 114272b676d7Smrg * - Copy mode i, merge j to copy of i, link the result to dest 114372b676d7Smrg * - Link i and j in private record. 114472b676d7Smrg * - If dest is NULL, return value is copy of i linked to itself. 114572b676d7Smrg * - For mergedfb auto-config, we only check the dimension 114672b676d7Smrg * against virtualX/Y, if they were user-provided. 114772b676d7Smrg * - No special treatment required for CRTxxOffs. 114872b676d7Smrg * - Provide fake dotclock in order to distinguish between similar 114972b676d7Smrg * looking MetaModes (for RandR and VidMode extensions) 115072b676d7Smrg * - Set unique VRefresh of dest mode for RandR 115172b676d7Smrg */ 115272b676d7Smrgstatic DisplayModePtr 115372b676d7SmrgSiSCopyModeNLink(ScrnInfoPtr pScrn, DisplayModePtr dest, 115472b676d7Smrg DisplayModePtr i, DisplayModePtr j, 115572b676d7Smrg SiSScrn2Rel srel) 115672b676d7Smrg{ 115772b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 115872b676d7Smrg DisplayModePtr mode; 115972b676d7Smrg int dx = 0,dy = 0; 116072b676d7Smrg 11615788ca14Smrg if(!((mode = malloc(sizeof(DisplayModeRec))))) return dest; 116272b676d7Smrg memcpy(mode, i, sizeof(DisplayModeRec)); 11635788ca14Smrg if(!((mode->Private = malloc(sizeof(SiSMergedDisplayModeRec))))) { 11645788ca14Smrg free(mode); 116572b676d7Smrg return dest; 116672b676d7Smrg } 116772b676d7Smrg ((SiSMergedDisplayModePtr)mode->Private)->CRT1 = i; 116872b676d7Smrg ((SiSMergedDisplayModePtr)mode->Private)->CRT2 = j; 116972b676d7Smrg ((SiSMergedDisplayModePtr)mode->Private)->CRT2Position = srel; 117072b676d7Smrg mode->PrivSize = 0; 117172b676d7Smrg 117272b676d7Smrg switch(srel) { 117372b676d7Smrg case sisLeftOf: 117472b676d7Smrg case sisRightOf: 117572b676d7Smrg if(!(pScrn->display->virtualX)) { 117672b676d7Smrg dx = i->HDisplay + j->HDisplay; 117772b676d7Smrg } else { 117872b676d7Smrg dx = min(pScrn->virtualX, i->HDisplay + j->HDisplay); 117972b676d7Smrg } 118072b676d7Smrg dx -= mode->HDisplay; 118172b676d7Smrg if(!(pScrn->display->virtualY)) { 118272b676d7Smrg dy = max(i->VDisplay, j->VDisplay); 118372b676d7Smrg } else { 118472b676d7Smrg dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay)); 118572b676d7Smrg } 118672b676d7Smrg dy -= mode->VDisplay; 118772b676d7Smrg break; 118872b676d7Smrg case sisAbove: 118972b676d7Smrg case sisBelow: 119072b676d7Smrg if(!(pScrn->display->virtualY)) { 119172b676d7Smrg dy = i->VDisplay + j->VDisplay; 119272b676d7Smrg } else { 119372b676d7Smrg dy = min(pScrn->virtualY, i->VDisplay + j->VDisplay); 119472b676d7Smrg } 119572b676d7Smrg dy -= mode->VDisplay; 119672b676d7Smrg if(!(pScrn->display->virtualX)) { 119772b676d7Smrg dx = max(i->HDisplay, j->HDisplay); 119872b676d7Smrg } else { 119972b676d7Smrg dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay)); 120072b676d7Smrg } 120172b676d7Smrg dx -= mode->HDisplay; 120272b676d7Smrg break; 120372b676d7Smrg case sisClone: 120472b676d7Smrg if(!(pScrn->display->virtualX)) { 120572b676d7Smrg dx = max(i->HDisplay, j->HDisplay); 120672b676d7Smrg } else { 120772b676d7Smrg dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay)); 120872b676d7Smrg } 120972b676d7Smrg dx -= mode->HDisplay; 121072b676d7Smrg if(!(pScrn->display->virtualY)) { 121172b676d7Smrg dy = max(i->VDisplay, j->VDisplay); 121272b676d7Smrg } else { 121372b676d7Smrg dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay)); 121472b676d7Smrg } 121572b676d7Smrg dy -= mode->VDisplay; 121672b676d7Smrg break; 121772b676d7Smrg } 121872b676d7Smrg mode->HDisplay += dx; 121972b676d7Smrg mode->HSyncStart += dx; 122072b676d7Smrg mode->HSyncEnd += dx; 122172b676d7Smrg mode->HTotal += dx; 122272b676d7Smrg mode->VDisplay += dy; 122372b676d7Smrg mode->VSyncStart += dy; 122472b676d7Smrg mode->VSyncEnd += dy; 122572b676d7Smrg mode->VTotal += dy; 122672b676d7Smrg 122772b676d7Smrg mode->type = M_T_DEFAULT; 122872b676d7Smrg#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,2,0) 122972b676d7Smrg /* Set up as user defined (ie fake that the mode has been named in the 123072b676d7Smrg * Modes-list in the screen section; corrects cycling with CTRL-ALT-[-+] 123172b676d7Smrg * when source mode has not been listed there.) 123272b676d7Smrg */ 123372b676d7Smrg mode->type |= M_T_USERDEF; 123472b676d7Smrg#endif 123572b676d7Smrg 123672b676d7Smrg /* Set the VRefresh field (in order to make RandR use it for the rates). We 123772b676d7Smrg * simply set this to the refresh rate for the CRT1 mode (since CRT2 will 123872b676d7Smrg * mostly be LCD or TV anyway). 123972b676d7Smrg */ 124072b676d7Smrg mode->VRefresh = SiSCalcVRate(i); 124172b676d7Smrg 124272b676d7Smrg if( ((mode->HDisplay * ((pScrn->bitsPerPixel + 7) / 8) * mode->VDisplay) > pSiS->maxxfbmem) || 124372b676d7Smrg (mode->HDisplay > 4088) || 124472b676d7Smrg (mode->VDisplay > 4096) ) { 124572b676d7Smrg 124672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 124772b676d7Smrg "Skipped \"%s\" (%dx%d), not enough video RAM or beyond hardware specs\n", 124872b676d7Smrg mode->name, mode->HDisplay, mode->VDisplay); 12495788ca14Smrg free(mode->Private); 12505788ca14Smrg free(mode); 125172b676d7Smrg 125272b676d7Smrg return dest; 125372b676d7Smrg } 125472b676d7Smrg 125572b676d7Smrg#ifdef SISXINERAMA 125672b676d7Smrg if(srel != sisClone) { 125772b676d7Smrg pSiS->AtLeastOneNonClone = TRUE; 125872b676d7Smrg } 125972b676d7Smrg#endif 126072b676d7Smrg 126172b676d7Smrg /* Now see if the resulting mode would be discarded as a "size" by the 126272b676d7Smrg * RandR extension, and increase its clock by 1000 in case it does. 126372b676d7Smrg */ 126472b676d7Smrg if(dest) { 126572b676d7Smrg DisplayModePtr t = dest; 126672b676d7Smrg do { 126772b676d7Smrg if((t->HDisplay == mode->HDisplay) && 126872b676d7Smrg (t->VDisplay == mode->VDisplay) && 126972b676d7Smrg ((int)(t->VRefresh + .5) == (int)(mode->VRefresh + .5))) { 127072b676d7Smrg mode->VRefresh += 1000.0; 127172b676d7Smrg } 127272b676d7Smrg t = t->next; 127372b676d7Smrg } while((t) && (t != dest)); 127472b676d7Smrg } 127572b676d7Smrg 127672b676d7Smrg /* Provide a fake but unique DotClock in order to trick the vidmode 127772b676d7Smrg * extension to allow selecting among a number of modes whose merged result 127872b676d7Smrg * looks identical but consists of different modes for CRT1 and CRT2 127972b676d7Smrg */ 128072b676d7Smrg mode->Clock = (int)(mode->VRefresh * 1000.0); 128172b676d7Smrg 128272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 128372b676d7Smrg "Merged \"%s\" (%dx%d) and \"%s\" (%dx%d) to %dx%d (%d)%s\n", 128472b676d7Smrg i->name, i->HDisplay, i->VDisplay, j->name, j->HDisplay, j->VDisplay, 128572b676d7Smrg mode->HDisplay, mode->VDisplay, (int)mode->VRefresh, 128672b676d7Smrg (srel == sisClone) ? " (Clone)" : ""); 128772b676d7Smrg 128872b676d7Smrg mode->next = mode; 128972b676d7Smrg mode->prev = mode; 129072b676d7Smrg 129172b676d7Smrg if(dest) { 129272b676d7Smrg mode->next = dest->next; /* Insert node after "dest" */ 129372b676d7Smrg dest->next->prev = mode; 129472b676d7Smrg mode->prev = dest; 129572b676d7Smrg dest->next = mode; 129672b676d7Smrg } 129772b676d7Smrg 129872b676d7Smrg return mode; 129972b676d7Smrg} 130072b676d7Smrg 130172b676d7Smrg/* Helper function to find a mode from a given name 130272b676d7Smrg * (Code base taken from mga driver) 130372b676d7Smrg */ 130472b676d7Smrgstatic DisplayModePtr 130572b676d7SmrgSiSGetModeFromName(char* str, DisplayModePtr i) 130672b676d7Smrg{ 130772b676d7Smrg DisplayModePtr c = i; 130872b676d7Smrg if(!i) return NULL; 130972b676d7Smrg do { 131072b676d7Smrg if(strcmp(str, c->name) == 0) return c; 131172b676d7Smrg c = c->next; 131272b676d7Smrg } while(c != i); 131372b676d7Smrg return NULL; 131472b676d7Smrg} 131572b676d7Smrg 131672b676d7Smrgstatic DisplayModePtr 131772b676d7SmrgSiSFindWidestTallestMode(DisplayModePtr i, Bool tallest) 131872b676d7Smrg{ 131972b676d7Smrg DisplayModePtr c = i, d = NULL; 132072b676d7Smrg int max = 0; 132172b676d7Smrg if(!i) return NULL; 132272b676d7Smrg do { 132372b676d7Smrg if(tallest) { 132472b676d7Smrg if(c->VDisplay > max) { 132572b676d7Smrg max = c->VDisplay; 132672b676d7Smrg d = c; 132772b676d7Smrg } 132872b676d7Smrg } else { 132972b676d7Smrg if(c->HDisplay > max) { 133072b676d7Smrg max = c->HDisplay; 133172b676d7Smrg d = c; 133272b676d7Smrg } 133372b676d7Smrg } 133472b676d7Smrg c = c->next; 133572b676d7Smrg } while(c != i); 133672b676d7Smrg return d; 133772b676d7Smrg} 133872b676d7Smrg 133972b676d7Smrgstatic void 134072b676d7SmrgSiSFindWidestTallestCommonMode(DisplayModePtr i, DisplayModePtr j, Bool tallest, 134172b676d7Smrg DisplayModePtr *a, DisplayModePtr *b) 134272b676d7Smrg{ 134372b676d7Smrg DisplayModePtr c = i, d; 134472b676d7Smrg int max = 0; 134572b676d7Smrg Bool foundone; 134672b676d7Smrg 134772b676d7Smrg (*a) = (*b) = NULL; 134872b676d7Smrg 134972b676d7Smrg if(!i || !j) return; 135072b676d7Smrg 135172b676d7Smrg do { 135272b676d7Smrg d = j; 135372b676d7Smrg foundone = FALSE; 135472b676d7Smrg do { 135572b676d7Smrg if( (c->HDisplay == d->HDisplay) && 135672b676d7Smrg (c->VDisplay == d->VDisplay) ) { 135772b676d7Smrg foundone = TRUE; 135872b676d7Smrg break; 135972b676d7Smrg } 136072b676d7Smrg d = d->next; 136172b676d7Smrg } while(d != j); 136272b676d7Smrg if(foundone) { 136372b676d7Smrg if(tallest) { 136472b676d7Smrg if(c->VDisplay > max) { 136572b676d7Smrg max = c->VDisplay; 136672b676d7Smrg (*a) = c; 136772b676d7Smrg (*b) = d; 136872b676d7Smrg } 136972b676d7Smrg } else { 137072b676d7Smrg if(c->HDisplay > max) { 137172b676d7Smrg max = c->HDisplay; 137272b676d7Smrg (*a) = c; 137372b676d7Smrg (*b) = d; 137472b676d7Smrg } 137572b676d7Smrg } 137672b676d7Smrg } 137772b676d7Smrg c = c->next; 137872b676d7Smrg } while(c != i); 137972b676d7Smrg} 138072b676d7Smrg 138172b676d7Smrgstatic DisplayModePtr 138272b676d7SmrgSiSGenerateModeListFromLargestModes(ScrnInfoPtr pScrn, 138372b676d7Smrg DisplayModePtr i, DisplayModePtr j, 138472b676d7Smrg SiSScrn2Rel srel) 138572b676d7Smrg{ 138672b676d7Smrg#ifdef SISXINERAMA 138772b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 138872b676d7Smrg#endif 138972b676d7Smrg DisplayModePtr mode1 = NULL; 139072b676d7Smrg DisplayModePtr mode2 = NULL; 139172b676d7Smrg DisplayModePtr mode3 = NULL; 139272b676d7Smrg DisplayModePtr mode4 = NULL; 139372b676d7Smrg DisplayModePtr result = NULL; 139472b676d7Smrg 139572b676d7Smrg#ifdef SISXINERAMA 139672b676d7Smrg pSiS->AtLeastOneNonClone = FALSE; 139772b676d7Smrg#endif 139872b676d7Smrg 139972b676d7Smrg /* Now build a default list of MetaModes. 140072b676d7Smrg * - Non-clone: If the user enabled NonRectangular, we use the 140172b676d7Smrg * largest mode for each CRT1 and CRT2. If not, we use the largest 140272b676d7Smrg * common mode for CRT1 and CRT2 (if available). Additionally, and 140372b676d7Smrg * regardless if the above, we produce a clone mode consisting of 140472b676d7Smrg * the largest common mode (if available) in order to use DGA. 140572b676d7Smrg * - Clone: If the (global) CRT2Position is Clone, we use the 140672b676d7Smrg * largest common mode if available, otherwise the first two modes 140772b676d7Smrg * in each list. 140872b676d7Smrg */ 140972b676d7Smrg 141072b676d7Smrg switch(srel) { 141172b676d7Smrg case sisLeftOf: 141272b676d7Smrg case sisRightOf: 141372b676d7Smrg mode1 = SiSFindWidestTallestMode(i, FALSE); 141472b676d7Smrg mode2 = SiSFindWidestTallestMode(j, FALSE); 141572b676d7Smrg SiSFindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); 141672b676d7Smrg break; 141772b676d7Smrg case sisAbove: 141872b676d7Smrg case sisBelow: 141972b676d7Smrg mode1 = SiSFindWidestTallestMode(i, TRUE); 142072b676d7Smrg mode2 = SiSFindWidestTallestMode(j, TRUE); 142172b676d7Smrg SiSFindWidestTallestCommonMode(i, j, TRUE, &mode3, &mode4); 142272b676d7Smrg break; 142372b676d7Smrg case sisClone: 142472b676d7Smrg SiSFindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); 142572b676d7Smrg if(mode3 && mode4) { 142672b676d7Smrg mode1 = mode3; 142772b676d7Smrg mode2 = mode4; 142872b676d7Smrg } else { 142972b676d7Smrg mode1 = i; 143072b676d7Smrg mode2 = j; 143172b676d7Smrg } 143272b676d7Smrg } 143372b676d7Smrg 143472b676d7Smrg if(srel != sisClone) { 143572b676d7Smrg if(mode3 && mode4 && !pSiS->NonRect) { 143672b676d7Smrg mode1 = mode3; 143772b676d7Smrg mode2 = mode2; 143872b676d7Smrg } 143972b676d7Smrg } 144072b676d7Smrg 144172b676d7Smrg if(mode1 && mode2) { 144272b676d7Smrg result = SiSCopyModeNLink(pScrn, result, mode1, mode2, srel); 144372b676d7Smrg } 144472b676d7Smrg 144572b676d7Smrg if(srel != sisClone) { 144672b676d7Smrg if(mode3 && mode4) { 144772b676d7Smrg result = SiSCopyModeNLink(pScrn, result, mode3, mode4, sisClone); 144872b676d7Smrg } 144972b676d7Smrg } 145072b676d7Smrg 145172b676d7Smrg return result; 145272b676d7Smrg} 145372b676d7Smrg 145472b676d7Smrg/* Generate the merged-fb mode modelist 145572b676d7Smrg * (Taken from mga driver) 145672b676d7Smrg */ 145772b676d7Smrgstatic DisplayModePtr 145872b676d7SmrgSiSGenerateModeListFromMetaModes(ScrnInfoPtr pScrn, char* str, 145972b676d7Smrg DisplayModePtr i, DisplayModePtr j, 146072b676d7Smrg SiSScrn2Rel srel) 146172b676d7Smrg{ 146272b676d7Smrg#ifdef SISXINERAMA 146372b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 146472b676d7Smrg#endif 146572b676d7Smrg char* strmode = str; 146672b676d7Smrg char modename[256]; 146772b676d7Smrg Bool gotdash = FALSE; 146872b676d7Smrg char gotsep = 0; 146972b676d7Smrg SiSScrn2Rel sr; 147072b676d7Smrg DisplayModePtr mode1 = NULL; 147172b676d7Smrg DisplayModePtr mode2 = NULL; 147272b676d7Smrg DisplayModePtr result = NULL; 147372b676d7Smrg int myslen; 147472b676d7Smrg 147572b676d7Smrg#ifdef SISXINERAMA 147672b676d7Smrg pSiS->AtLeastOneNonClone = FALSE; 147772b676d7Smrg#endif 147872b676d7Smrg 147972b676d7Smrg do { 148072b676d7Smrg switch(*str) { 148172b676d7Smrg case 0: 148272b676d7Smrg case '-': 148372b676d7Smrg case '+': 148472b676d7Smrg case ' ': 148572b676d7Smrg case ',': 148672b676d7Smrg case ';': 148772b676d7Smrg if(strmode != str) { 148872b676d7Smrg 148972b676d7Smrg myslen = str - strmode; 149072b676d7Smrg if(myslen > 255) myslen = 255; 149172b676d7Smrg strncpy(modename, strmode, myslen); 149272b676d7Smrg modename[myslen] = 0; 149372b676d7Smrg 149472b676d7Smrg if(gotdash) { 149572b676d7Smrg if(mode1 == NULL) { 149672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 149772b676d7Smrg "Error parsing MetaModes parameter\n"); 149872b676d7Smrg return NULL; 149972b676d7Smrg } 150072b676d7Smrg mode2 = SiSGetModeFromName(modename, j); 150172b676d7Smrg if(!mode2) { 150272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 150372b676d7Smrg "Mode \"%s\" is not a supported mode for CRT2\n", modename); 150472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 150572b676d7Smrg "\t(Skipping metamode \"%s%c%s\")\n", mode1->name, gotsep, modename); 150672b676d7Smrg mode1 = NULL; 150772b676d7Smrg gotsep = 0; 150872b676d7Smrg } 150972b676d7Smrg } else { 151072b676d7Smrg mode1 = SiSGetModeFromName(modename, i); 151172b676d7Smrg if(!mode1) { 151272b676d7Smrg char* tmps = str; 151372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 151472b676d7Smrg "Mode \"%s\" is not a supported mode for CRT1\n", modename); 151572b676d7Smrg while(*tmps == ' ' || *tmps == ';') tmps++; 151672b676d7Smrg /* skip the next mode */ 151772b676d7Smrg if(*tmps == '-' || *tmps == '+' || *tmps == ',') { 151872b676d7Smrg tmps++; 151972b676d7Smrg /* skip spaces */ 152072b676d7Smrg while(*tmps == ' ' || *tmps == ';') tmps++; 152172b676d7Smrg /* skip modename */ 152272b676d7Smrg while(*tmps && *tmps != ' ' && *tmps != ';' && *tmps != '-' && *tmps != '+' && *tmps != ',') tmps++; 152372b676d7Smrg myslen = tmps - strmode; 152472b676d7Smrg if(myslen > 255) myslen = 255; 152572b676d7Smrg strncpy(modename,strmode,myslen); 152672b676d7Smrg modename[myslen] = 0; 152772b676d7Smrg str = tmps - 1; 152872b676d7Smrg } 152972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 153072b676d7Smrg "\t(Skipping metamode \"%s\")\n", modename); 153172b676d7Smrg mode1 = NULL; 153272b676d7Smrg gotsep = 0; 153372b676d7Smrg } 153472b676d7Smrg } 153572b676d7Smrg gotdash = FALSE; 153672b676d7Smrg } 153772b676d7Smrg strmode = str + 1; 153872b676d7Smrg gotdash |= (*str == '-' || *str == '+' || *str == ','); 153972b676d7Smrg if (*str == '-' || *str == '+' || *str == ',') 154072b676d7Smrg gotsep = *str; 154172b676d7Smrg 154272b676d7Smrg if(*str != 0) break; 154372b676d7Smrg /* Fall through otherwise */ 154472b676d7Smrg 154572b676d7Smrg default: 154672b676d7Smrg if(!gotdash && mode1) { 154772b676d7Smrg sr = srel; 154872b676d7Smrg if(gotsep == '+') sr = sisClone; 154972b676d7Smrg if(!mode2) { 155072b676d7Smrg mode2 = SiSGetModeFromName(mode1->name, j); 155172b676d7Smrg sr = sisClone; 155272b676d7Smrg } 155372b676d7Smrg if(!mode2) { 155472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 155572b676d7Smrg "Mode \"%s\" is not a supported mode for CRT2\n", mode1->name); 155672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 155772b676d7Smrg "\t(Skipping metamode \"%s\")\n", modename); 155872b676d7Smrg mode1 = NULL; 155972b676d7Smrg } else { 156072b676d7Smrg result = SiSCopyModeNLink(pScrn, result, mode1, mode2, sr); 156172b676d7Smrg mode1 = NULL; 156272b676d7Smrg mode2 = NULL; 156372b676d7Smrg } 156472b676d7Smrg gotsep = 0; 156572b676d7Smrg } 156672b676d7Smrg break; 156772b676d7Smrg 156872b676d7Smrg } 156972b676d7Smrg 157072b676d7Smrg } while(*(str++) != 0); 157172b676d7Smrg 157272b676d7Smrg return result; 157372b676d7Smrg} 157472b676d7Smrg 157572b676d7Smrgstatic DisplayModePtr 157672b676d7SmrgSiSGenerateModeList(ScrnInfoPtr pScrn, char* str, 157772b676d7Smrg DisplayModePtr i, DisplayModePtr j, 157872b676d7Smrg SiSScrn2Rel srel) 157972b676d7Smrg{ 158072b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 158172b676d7Smrg 158272b676d7Smrg if(str != NULL) { 158372b676d7Smrg return(SiSGenerateModeListFromMetaModes(pScrn, str, i, j, srel)); 158472b676d7Smrg } else { 158572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 158672b676d7Smrg "No MetaModes given, linking %s modes by default\n", 158772b676d7Smrg (srel == sisClone) ? "largest common" : 158872b676d7Smrg (pSiS->NonRect ? 158972b676d7Smrg (((srel == sisLeftOf) || (srel == sisRightOf)) ? "widest" : "tallest") 159072b676d7Smrg : 159172b676d7Smrg (((srel == sisLeftOf) || (srel == sisRightOf)) ? "widest common" : "tallest common")) ); 159272b676d7Smrg return(SiSGenerateModeListFromLargestModes(pScrn, i, j, srel)); 159372b676d7Smrg } 159472b676d7Smrg} 159572b676d7Smrg 159672b676d7Smrgstatic void 159772b676d7SmrgSiSRecalcDefaultVirtualSize(ScrnInfoPtr pScrn) 159872b676d7Smrg{ 159972b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 160072b676d7Smrg DisplayModePtr mode, bmode; 160172b676d7Smrg int maxh, maxv; 160272b676d7Smrg static const char *str = "MergedFB: Virtual %s %d\n"; 160372b676d7Smrg static const char *errstr = "Virtual %s to small for given CRT2Position offset\n"; 160472b676d7Smrg 160572b676d7Smrg mode = bmode = pScrn->modes; 160672b676d7Smrg maxh = maxv = 0; 160772b676d7Smrg do { 160872b676d7Smrg if(mode->HDisplay > maxh) maxh = mode->HDisplay; 160972b676d7Smrg if(mode->VDisplay > maxv) maxv = mode->VDisplay; 161072b676d7Smrg mode = mode->next; 161172b676d7Smrg } while(mode != bmode); 161272b676d7Smrg 161372b676d7Smrg maxh += pSiS->CRT1XOffs + pSiS->CRT2XOffs; 161472b676d7Smrg maxv += pSiS->CRT1YOffs + pSiS->CRT2YOffs; 161572b676d7Smrg 161672b676d7Smrg if(!(pScrn->display->virtualX)) { 161772b676d7Smrg if(maxh > 4088) { 161872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 161972b676d7Smrg "Virtual width with CRT2Position offset beyond hardware specs\n"); 162072b676d7Smrg pSiS->CRT1XOffs = pSiS->CRT2XOffs = 0; 162172b676d7Smrg maxh -= (pSiS->CRT1XOffs + pSiS->CRT2XOffs); 162272b676d7Smrg } 162372b676d7Smrg pScrn->virtualX = maxh; 162472b676d7Smrg pScrn->displayWidth = maxh; 162572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "width", maxh); 162672b676d7Smrg } else { 162772b676d7Smrg if(maxh < pScrn->display->virtualX) { 162872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "width"); 162972b676d7Smrg pSiS->CRT1XOffs = pSiS->CRT2XOffs = 0; 163072b676d7Smrg } 163172b676d7Smrg } 163272b676d7Smrg 163372b676d7Smrg if(!(pScrn->display->virtualY)) { 163472b676d7Smrg pScrn->virtualY = maxv; 163572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "height", maxv); 163672b676d7Smrg } else { 163772b676d7Smrg if(maxv < pScrn->display->virtualY) { 163872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "height"); 163972b676d7Smrg pSiS->CRT1YOffs = pSiS->CRT2YOffs = 0; 164072b676d7Smrg } 164172b676d7Smrg } 164272b676d7Smrg} 164372b676d7Smrg 164472b676d7Smrgstatic void 164572b676d7SmrgSiSMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, SiSScrn2Rel srel) 164672b676d7Smrg{ 164772b676d7Smrg SISPtr pSiS = SISPTR(pScrn1); 164872b676d7Smrg MessageType from = X_DEFAULT; 164972b676d7Smrg xf86MonPtr DDC1 = (xf86MonPtr)(pScrn1->monitor->DDC); 165072b676d7Smrg xf86MonPtr DDC2 = (xf86MonPtr)(pScrn2->monitor->DDC); 165172b676d7Smrg int ddcWidthmm = 0, ddcHeightmm = 0; 165272b676d7Smrg const char *dsstr = "MergedFB: Display dimensions: (%d, %d) mm\n"; 165372b676d7Smrg 165472b676d7Smrg /* This sets the DPI for MergedFB mode. The problem is that 165572b676d7Smrg * this can never be exact, because the output devices may 165672b676d7Smrg * have different dimensions. This function tries to compromise 165772b676d7Smrg * through a few assumptions, and it just calculates an average DPI 165872b676d7Smrg * value for both monitors. 165972b676d7Smrg */ 166072b676d7Smrg 166172b676d7Smrg /* Given DisplaySize should regard BOTH monitors */ 166272b676d7Smrg pScrn1->widthmm = pScrn1->monitor->widthmm; 166372b676d7Smrg pScrn1->heightmm = pScrn1->monitor->heightmm; 166472b676d7Smrg 166572b676d7Smrg /* Get DDC display size; if only either CRT1 or CRT2 provided these, 166672b676d7Smrg * assume equal dimensions for both, otherwise add dimensions 166772b676d7Smrg */ 166872b676d7Smrg if( (DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) && 166972b676d7Smrg (DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0)) ) { 167072b676d7Smrg ddcWidthmm = max(DDC1->features.hsize, DDC2->features.hsize) * 10; 167172b676d7Smrg ddcHeightmm = max(DDC1->features.vsize, DDC2->features.vsize) * 10; 167272b676d7Smrg switch(srel) { 167372b676d7Smrg case sisLeftOf: 167472b676d7Smrg case sisRightOf: 167572b676d7Smrg ddcWidthmm = (DDC1->features.hsize + DDC2->features.hsize) * 10; 167672b676d7Smrg break; 167772b676d7Smrg case sisAbove: 167872b676d7Smrg case sisBelow: 167972b676d7Smrg ddcHeightmm = (DDC1->features.vsize + DDC2->features.vsize) * 10; 168072b676d7Smrg default: 168172b676d7Smrg break; 168272b676d7Smrg } 168372b676d7Smrg } else if(DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) { 168472b676d7Smrg ddcWidthmm = DDC1->features.hsize * 10; 168572b676d7Smrg ddcHeightmm = DDC1->features.vsize * 10; 168672b676d7Smrg switch(srel) { 168772b676d7Smrg case sisLeftOf: 168872b676d7Smrg case sisRightOf: 168972b676d7Smrg ddcWidthmm *= 2; 169072b676d7Smrg break; 169172b676d7Smrg case sisAbove: 169272b676d7Smrg case sisBelow: 169372b676d7Smrg ddcHeightmm *= 2; 169472b676d7Smrg default: 169572b676d7Smrg break; 169672b676d7Smrg } 169772b676d7Smrg } else if(DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0) ) { 169872b676d7Smrg ddcWidthmm = DDC2->features.hsize * 10; 169972b676d7Smrg ddcHeightmm = DDC2->features.vsize * 10; 170072b676d7Smrg switch(srel) { 170172b676d7Smrg case sisLeftOf: 170272b676d7Smrg case sisRightOf: 170372b676d7Smrg ddcWidthmm *= 2; 170472b676d7Smrg break; 170572b676d7Smrg case sisAbove: 170672b676d7Smrg case sisBelow: 170772b676d7Smrg ddcHeightmm *= 2; 170872b676d7Smrg default: 170972b676d7Smrg break; 171072b676d7Smrg } 171172b676d7Smrg } 171272b676d7Smrg 171372b676d7Smrg if(monitorResolution > 0) { 171472b676d7Smrg 171572b676d7Smrg /* Set command line given values (overrules given options) */ 171672b676d7Smrg pScrn1->xDpi = monitorResolution; 171772b676d7Smrg pScrn1->yDpi = monitorResolution; 171872b676d7Smrg from = X_CMDLINE; 171972b676d7Smrg 172072b676d7Smrg } else if(pSiS->MergedFBXDPI) { 172172b676d7Smrg 172272b676d7Smrg /* Set option-wise given values (overrule DisplaySize) */ 172372b676d7Smrg pScrn1->xDpi = pSiS->MergedFBXDPI; 172472b676d7Smrg pScrn1->yDpi = pSiS->MergedFBYDPI; 172572b676d7Smrg from = X_CONFIG; 172672b676d7Smrg 172772b676d7Smrg } else if(pScrn1->widthmm > 0 || pScrn1->heightmm > 0) { 172872b676d7Smrg 172972b676d7Smrg /* Set values calculated from given DisplaySize */ 173072b676d7Smrg from = X_CONFIG; 173172b676d7Smrg if(pScrn1->widthmm > 0) { 173272b676d7Smrg pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm); 173372b676d7Smrg } 173472b676d7Smrg if(pScrn1->heightmm > 0) { 173572b676d7Smrg pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm); 173672b676d7Smrg } 173772b676d7Smrg xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, pScrn1->widthmm, pScrn1->heightmm); 173872b676d7Smrg 173972b676d7Smrg } else if(ddcWidthmm && ddcHeightmm) { 174072b676d7Smrg 174172b676d7Smrg /* Set values from DDC-provided display size */ 174272b676d7Smrg from = X_PROBED; 174372b676d7Smrg xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, ddcWidthmm, ddcHeightmm ); 174472b676d7Smrg pScrn1->widthmm = ddcWidthmm; 174572b676d7Smrg pScrn1->heightmm = ddcHeightmm; 174672b676d7Smrg if(pScrn1->widthmm > 0) { 174772b676d7Smrg pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm); 174872b676d7Smrg } 174972b676d7Smrg if(pScrn1->heightmm > 0) { 175072b676d7Smrg pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm); 175172b676d7Smrg } 175272b676d7Smrg 175372b676d7Smrg } else { 175472b676d7Smrg 175572b676d7Smrg pScrn1->xDpi = pScrn1->yDpi = DEFAULT_DPI; 175672b676d7Smrg 175772b676d7Smrg } 175872b676d7Smrg 175972b676d7Smrg /* Sanity check */ 176072b676d7Smrg if(pScrn1->xDpi > 0 && pScrn1->yDpi <= 0) 176172b676d7Smrg pScrn1->yDpi = pScrn1->xDpi; 176272b676d7Smrg if(pScrn1->yDpi > 0 && pScrn1->xDpi <= 0) 176372b676d7Smrg pScrn1->xDpi = pScrn1->yDpi; 176472b676d7Smrg 176572b676d7Smrg pScrn2->xDpi = pScrn1->xDpi; 176672b676d7Smrg pScrn2->yDpi = pScrn1->yDpi; 176772b676d7Smrg 176872b676d7Smrg xf86DrvMsg(pScrn1->scrnIndex, from, "MergedFB: DPI set to (%d, %d)\n", 176972b676d7Smrg pScrn1->xDpi, pScrn1->yDpi); 177072b676d7Smrg} 177172b676d7Smrg 177272b676d7Smrg/* Pseudo-Xinerama extension for MergedFB mode */ 177372b676d7Smrg#ifdef SISXINERAMA 177472b676d7Smrg 177572b676d7Smrgstatic void 177672b676d7SmrgSiSUpdateXineramaScreenInfo(ScrnInfoPtr pScrn1) 177772b676d7Smrg{ 177872b676d7Smrg SISPtr pSiS = SISPTR(pScrn1); 177972b676d7Smrg int crt1scrnnum = 0, crt2scrnnum = 1; 178072b676d7Smrg int x1=0, x2=0, y1=0, y2=0, h1=0, h2=0, w1=0, w2=0; 178172b676d7Smrg int realvirtX, realvirtY; 178272b676d7Smrg DisplayModePtr currentMode, firstMode; 178372b676d7Smrg Bool infochanged = FALSE; 178472b676d7Smrg Bool usenonrect = pSiS->NonRect; 1785721a3bc8Sjoerg static const char rectxine[] = "\t... setting up rectangular Xinerama layout\n"; 178672b676d7Smrg 178772b676d7Smrg pSiS->MBXNR1XMAX = pSiS->MBXNR1YMAX = pSiS->MBXNR2XMAX = pSiS->MBXNR2YMAX = 65536; 178872b676d7Smrg pSiS->HaveNonRect = pSiS->HaveOffsRegions = FALSE; 178972b676d7Smrg 179072b676d7Smrg if(!pSiS->MergedFB) return; 179172b676d7Smrg 179272b676d7Smrg if(SiSnoPanoramiXExtension) return; 179372b676d7Smrg 179472b676d7Smrg if(!SiSXineramadataPtr) return; 179572b676d7Smrg 179672b676d7Smrg if(pSiS->CRT2IsScrn0) { 179772b676d7Smrg crt1scrnnum = 1; 179872b676d7Smrg crt2scrnnum = 0; 179972b676d7Smrg } 180072b676d7Smrg 180172b676d7Smrg /* Attention: Usage of RandR may lead to virtual X and Y dimensions 180272b676d7Smrg * actually smaller than our MetaModes. To avoid this, we calculate 180372b676d7Smrg * the maxCRT fields here (and not somewhere else, like in CopyNLink) 180472b676d7Smrg * 180572b676d7Smrg * *** Note: RandR is disabled if one of CRTxxOffs is non-zero. 180672b676d7Smrg */ 180772b676d7Smrg 180872b676d7Smrg /* "Real" virtual: Virtual without the Offset */ 180972b676d7Smrg realvirtX = pScrn1->virtualX - pSiS->CRT1XOffs - pSiS->CRT2XOffs; 181072b676d7Smrg realvirtY = pScrn1->virtualY - pSiS->CRT1YOffs - pSiS->CRT2YOffs; 181172b676d7Smrg 181272b676d7Smrg if((pSiS->SiSXineramaVX != pScrn1->virtualX) || (pSiS->SiSXineramaVY != pScrn1->virtualY)) { 181372b676d7Smrg 181472b676d7Smrg if(!(pScrn1->modes)) return; 181572b676d7Smrg 181672b676d7Smrg pSiS->maxCRT1_X1 = pSiS->maxCRT1_X2 = 0; 181772b676d7Smrg pSiS->maxCRT1_Y1 = pSiS->maxCRT1_Y2 = 0; 181872b676d7Smrg pSiS->maxCRT2_X1 = pSiS->maxCRT2_X2 = 0; 181972b676d7Smrg pSiS->maxCRT2_Y1 = pSiS->maxCRT2_Y2 = 0; 182072b676d7Smrg pSiS->maxClone_X1 = pSiS->maxClone_X2 = 0; 182172b676d7Smrg pSiS->maxClone_Y1 = pSiS->maxClone_Y2 = 0; 182272b676d7Smrg 182372b676d7Smrg currentMode = firstMode = pScrn1->modes; 182472b676d7Smrg 182572b676d7Smrg do { 182672b676d7Smrg 182772b676d7Smrg DisplayModePtr p = currentMode->next; 182872b676d7Smrg DisplayModePtr i = ((SiSMergedDisplayModePtr)currentMode->Private)->CRT1; 182972b676d7Smrg DisplayModePtr j = ((SiSMergedDisplayModePtr)currentMode->Private)->CRT2; 183072b676d7Smrg SiSScrn2Rel srel = ((SiSMergedDisplayModePtr)currentMode->Private)->CRT2Position; 183172b676d7Smrg 183272b676d7Smrg if((currentMode->HDisplay <= realvirtX) && (currentMode->VDisplay <= realvirtY) && 183372b676d7Smrg (i->HDisplay <= realvirtX) && (j->HDisplay <= realvirtX) && 183472b676d7Smrg (i->VDisplay <= realvirtY) && (j->VDisplay <= realvirtY)) { 183572b676d7Smrg 183672b676d7Smrg if(srel != sisClone) { 183772b676d7Smrg if(pSiS->maxCRT1_X1 == i->HDisplay) { 183872b676d7Smrg if(pSiS->maxCRT1_X2 < j->HDisplay) { 183972b676d7Smrg pSiS->maxCRT1_X2 = j->HDisplay; /* Widest CRT2 mode displayed with widest CRT1 mode */ 184072b676d7Smrg } 184172b676d7Smrg } else if(pSiS->maxCRT1_X1 < i->HDisplay) { 184272b676d7Smrg pSiS->maxCRT1_X1 = i->HDisplay; /* Widest CRT1 mode */ 184372b676d7Smrg pSiS->maxCRT1_X2 = j->HDisplay; 184472b676d7Smrg } 184572b676d7Smrg if(pSiS->maxCRT2_X2 == j->HDisplay) { 184672b676d7Smrg if(pSiS->maxCRT2_X1 < i->HDisplay) { 184772b676d7Smrg pSiS->maxCRT2_X1 = i->HDisplay; /* Widest CRT1 mode displayed with widest CRT2 mode */ 184872b676d7Smrg } 184972b676d7Smrg } else if(pSiS->maxCRT2_X2 < j->HDisplay) { 185072b676d7Smrg pSiS->maxCRT2_X2 = j->HDisplay; /* Widest CRT2 mode */ 185172b676d7Smrg pSiS->maxCRT2_X1 = i->HDisplay; 185272b676d7Smrg } 185372b676d7Smrg if(pSiS->maxCRT1_Y1 == i->VDisplay) { /* Same as above, but tallest instead of widest */ 185472b676d7Smrg if(pSiS->maxCRT1_Y2 < j->VDisplay) { 185572b676d7Smrg pSiS->maxCRT1_Y2 = j->VDisplay; 185672b676d7Smrg } 185772b676d7Smrg } else if(pSiS->maxCRT1_Y1 < i->VDisplay) { 185872b676d7Smrg pSiS->maxCRT1_Y1 = i->VDisplay; 185972b676d7Smrg pSiS->maxCRT1_Y2 = j->VDisplay; 186072b676d7Smrg } 186172b676d7Smrg if(pSiS->maxCRT2_Y2 == j->VDisplay) { 186272b676d7Smrg if(pSiS->maxCRT2_Y1 < i->VDisplay) { 186372b676d7Smrg pSiS->maxCRT2_Y1 = i->VDisplay; 186472b676d7Smrg } 186572b676d7Smrg } else if(pSiS->maxCRT2_Y2 < j->VDisplay) { 186672b676d7Smrg pSiS->maxCRT2_Y2 = j->VDisplay; 186772b676d7Smrg pSiS->maxCRT2_Y1 = i->VDisplay; 186872b676d7Smrg } 186972b676d7Smrg } else { 187072b676d7Smrg if(pSiS->maxClone_X1 < i->HDisplay) { 187172b676d7Smrg pSiS->maxClone_X1 = i->HDisplay; 187272b676d7Smrg } 187372b676d7Smrg if(pSiS->maxClone_X2 < j->HDisplay) { 187472b676d7Smrg pSiS->maxClone_X2 = j->HDisplay; 187572b676d7Smrg } 187672b676d7Smrg if(pSiS->maxClone_Y1 < i->VDisplay) { 187772b676d7Smrg pSiS->maxClone_Y1 = i->VDisplay; 187872b676d7Smrg } 187972b676d7Smrg if(pSiS->maxClone_Y2 < j->VDisplay) { 188072b676d7Smrg pSiS->maxClone_Y2 = j->VDisplay; 188172b676d7Smrg } 188272b676d7Smrg } 188372b676d7Smrg } 188472b676d7Smrg currentMode = p; 188572b676d7Smrg 188672b676d7Smrg } while((currentMode) && (currentMode != firstMode)); 188772b676d7Smrg 188872b676d7Smrg pSiS->SiSXineramaVX = pScrn1->virtualX; 188972b676d7Smrg pSiS->SiSXineramaVY = pScrn1->virtualY; 189072b676d7Smrg infochanged = TRUE; 189172b676d7Smrg 189272b676d7Smrg } 189372b676d7Smrg 189472b676d7Smrg if((usenonrect) && (pSiS->CRT2Position != sisClone) && pSiS->maxCRT1_X1) { 189572b676d7Smrg switch(pSiS->CRT2Position) { 189672b676d7Smrg case sisLeftOf: 189772b676d7Smrg case sisRightOf: 189872b676d7Smrg if((pSiS->maxCRT1_Y1 != realvirtY) && (pSiS->maxCRT2_Y2 != realvirtY)) { 189972b676d7Smrg usenonrect = FALSE; 190072b676d7Smrg } 190172b676d7Smrg break; 190272b676d7Smrg case sisAbove: 190372b676d7Smrg case sisBelow: 190472b676d7Smrg if((pSiS->maxCRT1_X1 != realvirtX) && (pSiS->maxCRT2_X2 != realvirtX)) { 190572b676d7Smrg usenonrect = FALSE; 190672b676d7Smrg } 190772b676d7Smrg break; 190872b676d7Smrg case sisClone: 190972b676d7Smrg break; 191072b676d7Smrg } 191172b676d7Smrg if(infochanged && !usenonrect) { 191272b676d7Smrg xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 191372b676d7Smrg "Virtual screen size does not match maximum display modes...\n"); 191472b676d7Smrg xf86DrvMsg(pScrn1->scrnIndex, X_INFO, rectxine); 191572b676d7Smrg 191672b676d7Smrg } 191772b676d7Smrg } else if(infochanged && usenonrect) { 191872b676d7Smrg usenonrect = FALSE; 191972b676d7Smrg xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 192072b676d7Smrg "Only clone modes available for this virtual screen size...\n"); 192172b676d7Smrg xf86DrvMsg(pScrn1->scrnIndex, X_INFO, rectxine); 192272b676d7Smrg } 192372b676d7Smrg 192472b676d7Smrg if(pSiS->maxCRT1_X1) { /* Means we have at least one non-clone mode */ 192572b676d7Smrg switch(pSiS->CRT2Position) { 192672b676d7Smrg case sisLeftOf: 192772b676d7Smrg x1 = min(pSiS->maxCRT1_X2, pScrn1->virtualX - pSiS->maxCRT1_X1); 192872b676d7Smrg if(x1 < 0) x1 = 0; 192972b676d7Smrg y1 = pSiS->CRT1YOffs; 193072b676d7Smrg w1 = pScrn1->virtualX - x1; 193172b676d7Smrg h1 = realvirtY; 193272b676d7Smrg if((usenonrect) && (pSiS->maxCRT1_Y1 != realvirtY)) { 193372b676d7Smrg h1 = pSiS->MBXNR1YMAX = pSiS->maxCRT1_Y1; 193472b676d7Smrg pSiS->NonRectDead.x0 = x1; 193572b676d7Smrg pSiS->NonRectDead.x1 = x1 + w1 - 1; 193672b676d7Smrg pSiS->NonRectDead.y0 = y1 + h1; 193772b676d7Smrg pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 193872b676d7Smrg pSiS->HaveNonRect = TRUE; 193972b676d7Smrg } 194072b676d7Smrg x2 = 0; 194172b676d7Smrg y2 = pSiS->CRT2YOffs; 194272b676d7Smrg w2 = max(pSiS->maxCRT2_X2, pScrn1->virtualX - pSiS->maxCRT2_X1); 194372b676d7Smrg if(w2 > pScrn1->virtualX) w2 = pScrn1->virtualX; 194472b676d7Smrg h2 = realvirtY; 194572b676d7Smrg if((usenonrect) && (pSiS->maxCRT2_Y2 != realvirtY)) { 194672b676d7Smrg h2 = pSiS->MBXNR2YMAX = pSiS->maxCRT2_Y2; 194772b676d7Smrg pSiS->NonRectDead.x0 = x2; 194872b676d7Smrg pSiS->NonRectDead.x1 = x2 + w2 - 1; 194972b676d7Smrg pSiS->NonRectDead.y0 = y2 + h2; 195072b676d7Smrg pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 195172b676d7Smrg pSiS->HaveNonRect = TRUE; 195272b676d7Smrg } 195372b676d7Smrg break; 195472b676d7Smrg case sisRightOf: 195572b676d7Smrg x1 = 0; 195672b676d7Smrg y1 = pSiS->CRT1YOffs; 195772b676d7Smrg w1 = max(pSiS->maxCRT1_X1, pScrn1->virtualX - pSiS->maxCRT1_X2); 195872b676d7Smrg if(w1 > pScrn1->virtualX) w1 = pScrn1->virtualX; 195972b676d7Smrg h1 = realvirtY; 196072b676d7Smrg if((usenonrect) && (pSiS->maxCRT1_Y1 != realvirtY)) { 196172b676d7Smrg h1 = pSiS->MBXNR1YMAX = pSiS->maxCRT1_Y1; 196272b676d7Smrg pSiS->NonRectDead.x0 = x1; 196372b676d7Smrg pSiS->NonRectDead.x1 = x1 + w1 - 1; 196472b676d7Smrg pSiS->NonRectDead.y0 = y1 + h1; 196572b676d7Smrg pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 196672b676d7Smrg pSiS->HaveNonRect = TRUE; 196772b676d7Smrg } 196872b676d7Smrg x2 = min(pSiS->maxCRT2_X1, pScrn1->virtualX - pSiS->maxCRT2_X2); 196972b676d7Smrg if(x2 < 0) x2 = 0; 197072b676d7Smrg y2 = pSiS->CRT2YOffs; 197172b676d7Smrg w2 = pScrn1->virtualX - x2; 197272b676d7Smrg h2 = realvirtY; 197372b676d7Smrg if((usenonrect) && (pSiS->maxCRT2_Y2 != realvirtY)) { 197472b676d7Smrg h2 = pSiS->MBXNR2YMAX = pSiS->maxCRT2_Y2; 197572b676d7Smrg pSiS->NonRectDead.x0 = x2; 197672b676d7Smrg pSiS->NonRectDead.x1 = x2 + w2 - 1; 197772b676d7Smrg pSiS->NonRectDead.y0 = y2 + h2; 197872b676d7Smrg pSiS->NonRectDead.y1 = pScrn1->virtualY - 1; 197972b676d7Smrg pSiS->HaveNonRect = TRUE; 198072b676d7Smrg } 198172b676d7Smrg break; 198272b676d7Smrg case sisAbove: 198372b676d7Smrg x1 = pSiS->CRT1XOffs; 198472b676d7Smrg y1 = min(pSiS->maxCRT1_Y2, pScrn1->virtualY - pSiS->maxCRT1_Y1); 198572b676d7Smrg if(y1 < 0) y1 = 0; 198672b676d7Smrg w1 = realvirtX; 198772b676d7Smrg h1 = pScrn1->virtualY - y1; 198872b676d7Smrg if((usenonrect) && (pSiS->maxCRT1_X1 != realvirtX)) { 198972b676d7Smrg w1 = pSiS->MBXNR1XMAX = pSiS->maxCRT1_X1; 199072b676d7Smrg pSiS->NonRectDead.x0 = x1 + w1; 199172b676d7Smrg pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 199272b676d7Smrg pSiS->NonRectDead.y0 = y1; 199372b676d7Smrg pSiS->NonRectDead.y1 = y1 + h1 - 1; 199472b676d7Smrg pSiS->HaveNonRect = TRUE; 199572b676d7Smrg } 199672b676d7Smrg x2 = pSiS->CRT2XOffs; 199772b676d7Smrg y2 = 0; 199872b676d7Smrg w2 = realvirtX; 199972b676d7Smrg h2 = max(pSiS->maxCRT2_Y2, pScrn1->virtualY - pSiS->maxCRT2_Y1); 200072b676d7Smrg if(h2 > pScrn1->virtualY) h2 = pScrn1->virtualY; 200172b676d7Smrg if((usenonrect) && (pSiS->maxCRT2_X2 != realvirtX)) { 200272b676d7Smrg w2 = pSiS->MBXNR2XMAX = pSiS->maxCRT2_X2; 200372b676d7Smrg pSiS->NonRectDead.x0 = x2 + w2; 200472b676d7Smrg pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 200572b676d7Smrg pSiS->NonRectDead.y0 = y2; 200672b676d7Smrg pSiS->NonRectDead.y1 = y2 + h2 - 1; 200772b676d7Smrg pSiS->HaveNonRect = TRUE; 200872b676d7Smrg } 200972b676d7Smrg break; 201072b676d7Smrg case sisBelow: 201172b676d7Smrg x1 = pSiS->CRT1XOffs; 201272b676d7Smrg y1 = 0; 201372b676d7Smrg w1 = realvirtX; 201472b676d7Smrg h1 = max(pSiS->maxCRT1_Y1, pScrn1->virtualY - pSiS->maxCRT1_Y2); 201572b676d7Smrg if(h1 > pScrn1->virtualY) h1 = pScrn1->virtualY; 201672b676d7Smrg if((usenonrect) && (pSiS->maxCRT1_X1 != realvirtX)) { 201772b676d7Smrg w1 = pSiS->MBXNR1XMAX = pSiS->maxCRT1_X1; 201872b676d7Smrg pSiS->NonRectDead.x0 = x1 + w1; 201972b676d7Smrg pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 202072b676d7Smrg pSiS->NonRectDead.y0 = y1; 202172b676d7Smrg pSiS->NonRectDead.y1 = y1 + h1 - 1; 202272b676d7Smrg pSiS->HaveNonRect = TRUE; 202372b676d7Smrg } 202472b676d7Smrg x2 = pSiS->CRT2XOffs; 202572b676d7Smrg y2 = min(pSiS->maxCRT2_Y1, pScrn1->virtualY - pSiS->maxCRT2_Y2); 202672b676d7Smrg if(y2 < 0) y2 = 0; 202772b676d7Smrg w2 = realvirtX; 202872b676d7Smrg h2 = pScrn1->virtualY - y2; 202972b676d7Smrg if((usenonrect) && (pSiS->maxCRT2_X2 != realvirtX)) { 203072b676d7Smrg w2 = pSiS->MBXNR2XMAX = pSiS->maxCRT2_X2; 203172b676d7Smrg pSiS->NonRectDead.x0 = x2 + w2; 203272b676d7Smrg pSiS->NonRectDead.x1 = pScrn1->virtualX - 1; 203372b676d7Smrg pSiS->NonRectDead.y0 = y2; 203472b676d7Smrg pSiS->NonRectDead.y1 = y2 + h2 - 1; 203572b676d7Smrg pSiS->HaveNonRect = TRUE; 203672b676d7Smrg } 203772b676d7Smrg default: 203872b676d7Smrg break; 203972b676d7Smrg } 204072b676d7Smrg 204172b676d7Smrg switch(pSiS->CRT2Position) { 204272b676d7Smrg case sisLeftOf: 204372b676d7Smrg case sisRightOf: 204472b676d7Smrg if(pSiS->CRT1YOffs) { 204572b676d7Smrg pSiS->OffDead1.x0 = x1; 204672b676d7Smrg pSiS->OffDead1.x1 = x1 + w1 - 1; 204772b676d7Smrg pSiS->OffDead1.y0 = 0; 204872b676d7Smrg pSiS->OffDead1.y1 = y1 - 1; 204972b676d7Smrg pSiS->OffDead2.x0 = x2; 205072b676d7Smrg pSiS->OffDead2.x1 = x2 + w2 - 1; 205172b676d7Smrg pSiS->OffDead2.y0 = y2 + h2; 205272b676d7Smrg pSiS->OffDead2.y1 = pScrn1->virtualY - 1; 205372b676d7Smrg pSiS->HaveOffsRegions = TRUE; 205472b676d7Smrg } else if(pSiS->CRT2YOffs) { 205572b676d7Smrg pSiS->OffDead1.x0 = x2; 205672b676d7Smrg pSiS->OffDead1.x1 = x2 + w2 - 1; 205772b676d7Smrg pSiS->OffDead1.y0 = 0; 205872b676d7Smrg pSiS->OffDead1.y1 = y2 - 1; 205972b676d7Smrg pSiS->OffDead2.x0 = x1; 206072b676d7Smrg pSiS->OffDead2.x1 = x1 + w1 - 1; 206172b676d7Smrg pSiS->OffDead2.y0 = y1 + h1; 206272b676d7Smrg pSiS->OffDead2.y1 = pScrn1->virtualY - 1; 206372b676d7Smrg pSiS->HaveOffsRegions = TRUE; 206472b676d7Smrg } 206572b676d7Smrg break; 206672b676d7Smrg case sisAbove: 206772b676d7Smrg case sisBelow: 206872b676d7Smrg if(pSiS->CRT1XOffs) { 206972b676d7Smrg pSiS->OffDead1.x0 = x2 + w2; 207072b676d7Smrg pSiS->OffDead1.x1 = pScrn1->virtualX - 1; 207172b676d7Smrg pSiS->OffDead1.y0 = y2; 207272b676d7Smrg pSiS->OffDead1.y1 = y2 + h2 - 1; 207372b676d7Smrg pSiS->OffDead2.x0 = 0; 207472b676d7Smrg pSiS->OffDead2.x1 = x1 - 1; 207572b676d7Smrg pSiS->OffDead2.y0 = y1; 207672b676d7Smrg pSiS->OffDead2.y1 = y1 + h1 - 1; 207772b676d7Smrg pSiS->HaveOffsRegions = TRUE; 207872b676d7Smrg } else if(pSiS->CRT2XOffs) { 207972b676d7Smrg pSiS->OffDead1.x0 = x1 + w1; 208072b676d7Smrg pSiS->OffDead1.x1 = pScrn1->virtualX - 1; 208172b676d7Smrg pSiS->OffDead1.y0 = y1; 208272b676d7Smrg pSiS->OffDead1.y1 = y1 + h1 - 1; 208372b676d7Smrg pSiS->OffDead2.x0 = 0; 208472b676d7Smrg pSiS->OffDead2.x1 = x2 - 1; 208572b676d7Smrg pSiS->OffDead2.y0 = y2; 208672b676d7Smrg pSiS->OffDead2.y1 = y2 + h2 - 1; 208772b676d7Smrg pSiS->HaveOffsRegions = TRUE; 208872b676d7Smrg } 208972b676d7Smrg default: 209072b676d7Smrg break; 209172b676d7Smrg } 209272b676d7Smrg 209372b676d7Smrg } else { /* Only clone-modes left */ 209472b676d7Smrg 209572b676d7Smrg x1 = x2 = 0; 209672b676d7Smrg y1 = y2 = 0; 209772b676d7Smrg w1 = w2 = max(pSiS->maxClone_X1, pSiS->maxClone_X2); 209872b676d7Smrg h1 = h2 = max(pSiS->maxClone_Y1, pSiS->maxClone_Y2); 209972b676d7Smrg 210072b676d7Smrg } 210172b676d7Smrg 210272b676d7Smrg SiSXineramadataPtr[crt1scrnnum].x = x1; 210372b676d7Smrg SiSXineramadataPtr[crt1scrnnum].y = y1; 210472b676d7Smrg SiSXineramadataPtr[crt1scrnnum].width = w1; 210572b676d7Smrg SiSXineramadataPtr[crt1scrnnum].height = h1; 210672b676d7Smrg SiSXineramadataPtr[crt2scrnnum].x = x2; 210772b676d7Smrg SiSXineramadataPtr[crt2scrnnum].y = y2; 210872b676d7Smrg SiSXineramadataPtr[crt2scrnnum].width = w2; 210972b676d7Smrg SiSXineramadataPtr[crt2scrnnum].height = h2; 211072b676d7Smrg 211172b676d7Smrg if(infochanged) { 211272b676d7Smrg xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 211372b676d7Smrg "Pseudo-Xinerama: CRT1 (Screen %d) (%d,%d)-(%d,%d)\n", 211472b676d7Smrg crt1scrnnum, x1, y1, w1+x1-1, h1+y1-1); 211572b676d7Smrg xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 211672b676d7Smrg "Pseudo-Xinerama: CRT2 (Screen %d) (%d,%d)-(%d,%d)\n", 211772b676d7Smrg crt2scrnnum, x2, y2, w2+x2-1, h2+y2-1); 211872b676d7Smrg if(pSiS->HaveNonRect) { 211972b676d7Smrg xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 212072b676d7Smrg "Pseudo-Xinerama: Inaccessible area (%d,%d)-(%d,%d)\n", 212172b676d7Smrg pSiS->NonRectDead.x0, pSiS->NonRectDead.y0, 212272b676d7Smrg pSiS->NonRectDead.x1, pSiS->NonRectDead.y1); 212372b676d7Smrg } 212472b676d7Smrg if(pSiS->HaveOffsRegions) { 212572b676d7Smrg xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 212672b676d7Smrg "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", 212772b676d7Smrg pSiS->OffDead1.x0, pSiS->OffDead1.y0, 212872b676d7Smrg pSiS->OffDead1.x1, pSiS->OffDead1.y1); 212972b676d7Smrg xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 213072b676d7Smrg "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", 213172b676d7Smrg pSiS->OffDead2.x0, pSiS->OffDead2.y0, 213272b676d7Smrg pSiS->OffDead2.x1, pSiS->OffDead2.y1); 213372b676d7Smrg } 213472b676d7Smrg if(pSiS->HaveNonRect || pSiS->HaveOffsRegions) { 213572b676d7Smrg xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 213672b676d7Smrg "Mouse restriction for inaccessible areas is %s\n", 213772b676d7Smrg pSiS->MouseRestrictions ? "enabled" : "disabled"); 213872b676d7Smrg } 213972b676d7Smrg } 214072b676d7Smrg} 214172b676d7Smrg 214272b676d7Smrg/* Proc */ 214372b676d7Smrg 214472b676d7Smrgint 214572b676d7SmrgSiSProcXineramaQueryVersion(ClientPtr client) 214672b676d7Smrg{ 214772b676d7Smrg xPanoramiXQueryVersionReply rep; 214872b676d7Smrg register int n; 214972b676d7Smrg 215072b676d7Smrg REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq); 215172b676d7Smrg rep.type = X_Reply; 215272b676d7Smrg rep.length = 0; 215372b676d7Smrg rep.sequenceNumber = client->sequence; 215472b676d7Smrg rep.majorVersion = SIS_XINERAMA_MAJOR_VERSION; 215572b676d7Smrg rep.minorVersion = SIS_XINERAMA_MINOR_VERSION; 215672b676d7Smrg if(client->swapped) { 21575788ca14Smrg _swaps(&rep.sequenceNumber, n); 21585788ca14Smrg _swapl(&rep.length, n); 21595788ca14Smrg _swaps(&rep.majorVersion, n); 21605788ca14Smrg _swaps(&rep.minorVersion, n); 216172b676d7Smrg } 216272b676d7Smrg WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *)&rep); 216372b676d7Smrg return (client->noClientException); 216472b676d7Smrg} 216572b676d7Smrg 216672b676d7Smrgint 216772b676d7SmrgSiSProcXineramaGetState(ClientPtr client) 216872b676d7Smrg{ 216972b676d7Smrg REQUEST(xPanoramiXGetStateReq); 217072b676d7Smrg WindowPtr pWin; 217172b676d7Smrg xPanoramiXGetStateReply rep; 217272b676d7Smrg register int n; 21735788ca14Smrg int rc; 217472b676d7Smrg 217572b676d7Smrg REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); 21765788ca14Smrg rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 21775788ca14Smrg if (rc != Success) 21785788ca14Smrg return rc; 217972b676d7Smrg 218072b676d7Smrg rep.type = X_Reply; 218172b676d7Smrg rep.length = 0; 218272b676d7Smrg rep.sequenceNumber = client->sequence; 218372b676d7Smrg rep.state = !SiSnoPanoramiXExtension; 218472b676d7Smrg if(client->swapped) { 21855788ca14Smrg _swaps (&rep.sequenceNumber, n); 21865788ca14Smrg _swapl (&rep.length, n); 218772b676d7Smrg } 218872b676d7Smrg WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *)&rep); 218972b676d7Smrg return client->noClientException; 219072b676d7Smrg} 219172b676d7Smrg 219272b676d7Smrgint 219372b676d7SmrgSiSProcXineramaGetScreenCount(ClientPtr client) 219472b676d7Smrg{ 219572b676d7Smrg REQUEST(xPanoramiXGetScreenCountReq); 219672b676d7Smrg WindowPtr pWin; 219772b676d7Smrg xPanoramiXGetScreenCountReply rep; 219872b676d7Smrg register int n; 21995788ca14Smrg int rc; 220072b676d7Smrg 220172b676d7Smrg REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); 22025788ca14Smrg rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 22035788ca14Smrg if (rc != Success) 22045788ca14Smrg return rc; 220572b676d7Smrg 220672b676d7Smrg rep.type = X_Reply; 220772b676d7Smrg rep.length = 0; 220872b676d7Smrg rep.sequenceNumber = client->sequence; 220972b676d7Smrg rep.ScreenCount = SiSXineramaNumScreens; 221072b676d7Smrg if(client->swapped) { 22115788ca14Smrg _swaps(&rep.sequenceNumber, n); 22125788ca14Smrg _swapl(&rep.length, n); 221372b676d7Smrg } 221472b676d7Smrg WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep); 221572b676d7Smrg return client->noClientException; 221672b676d7Smrg} 221772b676d7Smrg 221872b676d7Smrgint 221972b676d7SmrgSiSProcXineramaGetScreenSize(ClientPtr client) 222072b676d7Smrg{ 222172b676d7Smrg REQUEST(xPanoramiXGetScreenSizeReq); 222272b676d7Smrg WindowPtr pWin; 222372b676d7Smrg xPanoramiXGetScreenSizeReply rep; 222472b676d7Smrg register int n; 22255788ca14Smrg int rc; 222672b676d7Smrg 222772b676d7Smrg REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); 22285788ca14Smrg rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 22295788ca14Smrg if (rc != Success) 22305788ca14Smrg return rc; 223172b676d7Smrg 223272b676d7Smrg rep.type = X_Reply; 223372b676d7Smrg rep.length = 0; 223472b676d7Smrg rep.sequenceNumber = client->sequence; 223572b676d7Smrg rep.width = SiSXineramadataPtr[stuff->screen].width; 223672b676d7Smrg rep.height = SiSXineramadataPtr[stuff->screen].height; 223772b676d7Smrg if(client->swapped) { 22385788ca14Smrg _swaps(&rep.sequenceNumber, n); 22395788ca14Smrg _swapl(&rep.length, n); 22405788ca14Smrg _swapl(&rep.width, n); 22415788ca14Smrg _swapl(&rep.height, n); 224272b676d7Smrg } 224372b676d7Smrg WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep); 224472b676d7Smrg return client->noClientException; 224572b676d7Smrg} 224672b676d7Smrg 224772b676d7Smrgint 224872b676d7SmrgSiSProcXineramaIsActive(ClientPtr client) 224972b676d7Smrg{ 225072b676d7Smrg xXineramaIsActiveReply rep; 225172b676d7Smrg 225272b676d7Smrg REQUEST_SIZE_MATCH(xXineramaIsActiveReq); 225372b676d7Smrg 225472b676d7Smrg rep.type = X_Reply; 225572b676d7Smrg rep.length = 0; 225672b676d7Smrg rep.sequenceNumber = client->sequence; 225772b676d7Smrg rep.state = !SiSnoPanoramiXExtension; 225872b676d7Smrg if(client->swapped) { 225972b676d7Smrg register int n; 22605788ca14Smrg _swaps(&rep.sequenceNumber, n); 22615788ca14Smrg _swapl(&rep.length, n); 22625788ca14Smrg _swapl(&rep.state, n); 226372b676d7Smrg } 226472b676d7Smrg WriteToClient(client, sizeof(xXineramaIsActiveReply), (char *) &rep); 226572b676d7Smrg return client->noClientException; 226672b676d7Smrg} 226772b676d7Smrg 226872b676d7Smrgint 226972b676d7SmrgSiSProcXineramaQueryScreens(ClientPtr client) 227072b676d7Smrg{ 227172b676d7Smrg xXineramaQueryScreensReply rep; 227272b676d7Smrg 227372b676d7Smrg REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); 227472b676d7Smrg 227572b676d7Smrg rep.type = X_Reply; 227672b676d7Smrg rep.sequenceNumber = client->sequence; 227772b676d7Smrg rep.number = (SiSnoPanoramiXExtension) ? 0 : SiSXineramaNumScreens; 227872b676d7Smrg rep.length = rep.number * sz_XineramaScreenInfo >> 2; 227972b676d7Smrg if(client->swapped) { 228072b676d7Smrg register int n; 22815788ca14Smrg _swaps(&rep.sequenceNumber, n); 22825788ca14Smrg _swapl(&rep.length, n); 22835788ca14Smrg _swapl(&rep.number, n); 228472b676d7Smrg } 228572b676d7Smrg WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *)&rep); 228672b676d7Smrg 228772b676d7Smrg if(!SiSnoPanoramiXExtension) { 228872b676d7Smrg xXineramaScreenInfo scratch; 228972b676d7Smrg int i; 229072b676d7Smrg 229172b676d7Smrg for(i = 0; i < SiSXineramaNumScreens; i++) { 229272b676d7Smrg scratch.x_org = SiSXineramadataPtr[i].x; 229372b676d7Smrg scratch.y_org = SiSXineramadataPtr[i].y; 229472b676d7Smrg scratch.width = SiSXineramadataPtr[i].width; 229572b676d7Smrg scratch.height = SiSXineramadataPtr[i].height; 229672b676d7Smrg if(client->swapped) { 229772b676d7Smrg register int n; 22985788ca14Smrg _swaps(&scratch.x_org, n); 22995788ca14Smrg _swaps(&scratch.y_org, n); 23005788ca14Smrg _swaps(&scratch.width, n); 23015788ca14Smrg _swaps(&scratch.height, n); 230272b676d7Smrg } 230372b676d7Smrg WriteToClient(client, sz_XineramaScreenInfo, (char *)&scratch); 230472b676d7Smrg } 230572b676d7Smrg } 230672b676d7Smrg 230772b676d7Smrg return client->noClientException; 230872b676d7Smrg} 230972b676d7Smrg 231072b676d7Smrgstatic int 231172b676d7SmrgSiSProcXineramaDispatch(ClientPtr client) 231272b676d7Smrg{ 231372b676d7Smrg REQUEST(xReq); 231472b676d7Smrg switch (stuff->data) { 231572b676d7Smrg case X_PanoramiXQueryVersion: 231672b676d7Smrg return SiSProcXineramaQueryVersion(client); 231772b676d7Smrg case X_PanoramiXGetState: 231872b676d7Smrg return SiSProcXineramaGetState(client); 231972b676d7Smrg case X_PanoramiXGetScreenCount: 232072b676d7Smrg return SiSProcXineramaGetScreenCount(client); 232172b676d7Smrg case X_PanoramiXGetScreenSize: 232272b676d7Smrg return SiSProcXineramaGetScreenSize(client); 232372b676d7Smrg case X_XineramaIsActive: 232472b676d7Smrg return SiSProcXineramaIsActive(client); 232572b676d7Smrg case X_XineramaQueryScreens: 232672b676d7Smrg return SiSProcXineramaQueryScreens(client); 232772b676d7Smrg } 232872b676d7Smrg return BadRequest; 232972b676d7Smrg} 233072b676d7Smrg 233172b676d7Smrg/* SProc */ 233272b676d7Smrg 233372b676d7Smrgstatic int 233472b676d7SmrgSiSSProcXineramaQueryVersion (ClientPtr client) 233572b676d7Smrg{ 233672b676d7Smrg REQUEST(xPanoramiXQueryVersionReq); 233772b676d7Smrg register int n; 23385788ca14Smrg _swaps(&stuff->length,n); 233972b676d7Smrg REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); 234072b676d7Smrg return SiSProcXineramaQueryVersion(client); 234172b676d7Smrg} 234272b676d7Smrg 234372b676d7Smrgstatic int 234472b676d7SmrgSiSSProcXineramaGetState(ClientPtr client) 234572b676d7Smrg{ 234672b676d7Smrg REQUEST(xPanoramiXGetStateReq); 234772b676d7Smrg register int n; 23485788ca14Smrg _swaps (&stuff->length, n); 234972b676d7Smrg REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); 235072b676d7Smrg return SiSProcXineramaGetState(client); 235172b676d7Smrg} 235272b676d7Smrg 235372b676d7Smrgstatic int 235472b676d7SmrgSiSSProcXineramaGetScreenCount(ClientPtr client) 235572b676d7Smrg{ 235672b676d7Smrg REQUEST(xPanoramiXGetScreenCountReq); 235772b676d7Smrg register int n; 23585788ca14Smrg _swaps (&stuff->length, n); 235972b676d7Smrg REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); 236072b676d7Smrg return SiSProcXineramaGetScreenCount(client); 236172b676d7Smrg} 236272b676d7Smrg 236372b676d7Smrgstatic int 236472b676d7SmrgSiSSProcXineramaGetScreenSize(ClientPtr client) 236572b676d7Smrg{ 236672b676d7Smrg REQUEST(xPanoramiXGetScreenSizeReq); 236772b676d7Smrg register int n; 23685788ca14Smrg _swaps (&stuff->length, n); 236972b676d7Smrg REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); 237072b676d7Smrg return SiSProcXineramaGetScreenSize(client); 237172b676d7Smrg} 237272b676d7Smrg 237372b676d7Smrgstatic int 237472b676d7SmrgSiSSProcXineramaIsActive(ClientPtr client) 237572b676d7Smrg{ 237672b676d7Smrg REQUEST(xXineramaIsActiveReq); 237772b676d7Smrg register int n; 23785788ca14Smrg _swaps (&stuff->length, n); 237972b676d7Smrg REQUEST_SIZE_MATCH(xXineramaIsActiveReq); 238072b676d7Smrg return SiSProcXineramaIsActive(client); 238172b676d7Smrg} 238272b676d7Smrg 238372b676d7Smrgstatic int 238472b676d7SmrgSiSSProcXineramaQueryScreens(ClientPtr client) 238572b676d7Smrg{ 238672b676d7Smrg REQUEST(xXineramaQueryScreensReq); 238772b676d7Smrg register int n; 23885788ca14Smrg _swaps (&stuff->length, n); 238972b676d7Smrg REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); 239072b676d7Smrg return SiSProcXineramaQueryScreens(client); 239172b676d7Smrg} 239272b676d7Smrg 239372b676d7Smrgint 239472b676d7SmrgSiSSProcXineramaDispatch(ClientPtr client) 239572b676d7Smrg{ 239672b676d7Smrg REQUEST(xReq); 239772b676d7Smrg switch (stuff->data) { 239872b676d7Smrg case X_PanoramiXQueryVersion: 239972b676d7Smrg return SiSSProcXineramaQueryVersion(client); 240072b676d7Smrg case X_PanoramiXGetState: 240172b676d7Smrg return SiSSProcXineramaGetState(client); 240272b676d7Smrg case X_PanoramiXGetScreenCount: 240372b676d7Smrg return SiSSProcXineramaGetScreenCount(client); 240472b676d7Smrg case X_PanoramiXGetScreenSize: 240572b676d7Smrg return SiSSProcXineramaGetScreenSize(client); 240672b676d7Smrg case X_XineramaIsActive: 240772b676d7Smrg return SiSSProcXineramaIsActive(client); 240872b676d7Smrg case X_XineramaQueryScreens: 240972b676d7Smrg return SiSSProcXineramaQueryScreens(client); 241072b676d7Smrg } 241172b676d7Smrg return BadRequest; 241272b676d7Smrg} 241372b676d7Smrg 241472b676d7Smrgstatic void 241572b676d7SmrgSiSXineramaResetProc(ExtensionEntry* extEntry) 241672b676d7Smrg{ 241772b676d7Smrg /* Called by CloseDownExtensions() */ 241872b676d7Smrg if(SiSXineramadataPtr) { 24195788ca14Smrg free(SiSXineramadataPtr); 242072b676d7Smrg SiSXineramadataPtr = NULL; 242172b676d7Smrg } 242272b676d7Smrg} 242372b676d7Smrg 242472b676d7Smrgstatic void 242572b676d7SmrgSiSXineramaExtensionInit(ScrnInfoPtr pScrn) 242672b676d7Smrg{ 242772b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 242872b676d7Smrg Bool success = FALSE; 242972b676d7Smrg 243072b676d7Smrg if(!(SiSXineramadataPtr)) { 243172b676d7Smrg 243272b676d7Smrg if(!pSiS->MergedFB) { 243372b676d7Smrg SiSnoPanoramiXExtension = TRUE; 243472b676d7Smrg pSiS->MouseRestrictions = FALSE; 243572b676d7Smrg return; 243672b676d7Smrg } 243772b676d7Smrg 243872b676d7Smrg#ifdef PANORAMIX 243972b676d7Smrg if(!noPanoramiXExtension) { 244072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 244172b676d7Smrg "Xinerama active, not initializing SiS Pseudo-Xinerama\n"); 244272b676d7Smrg SiSnoPanoramiXExtension = TRUE; 244372b676d7Smrg pSiS->MouseRestrictions = FALSE; 244472b676d7Smrg return; 244572b676d7Smrg } 244672b676d7Smrg#endif 244772b676d7Smrg 244872b676d7Smrg if(SiSnoPanoramiXExtension) { 244972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 245072b676d7Smrg "SiS Pseudo-Xinerama disabled\n"); 245172b676d7Smrg pSiS->MouseRestrictions = FALSE; 245272b676d7Smrg return; 245372b676d7Smrg } 245472b676d7Smrg 245572b676d7Smrg if(pSiS->CRT2Position == sisClone) { 245672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 245772b676d7Smrg "Running MergedFB in Clone mode, SiS Pseudo-Xinerama disabled\n"); 245872b676d7Smrg SiSnoPanoramiXExtension = TRUE; 245972b676d7Smrg pSiS->MouseRestrictions = FALSE; 246072b676d7Smrg return; 246172b676d7Smrg } 246272b676d7Smrg 246372b676d7Smrg if(!(pSiS->AtLeastOneNonClone)) { 246472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 246572b676d7Smrg "Only Clone modes defined, SiS Pseudo-Xinerama disabled\n"); 246672b676d7Smrg SiSnoPanoramiXExtension = TRUE; 246772b676d7Smrg pSiS->MouseRestrictions = FALSE; 246872b676d7Smrg return; 246972b676d7Smrg } 247072b676d7Smrg 247172b676d7Smrg SiSXineramaNumScreens = 2; 247272b676d7Smrg 247372b676d7Smrg while(SiSXineramaGeneration != serverGeneration) { 247472b676d7Smrg 247572b676d7Smrg pSiS->XineramaExtEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0, 247672b676d7Smrg SiSProcXineramaDispatch, 247772b676d7Smrg SiSSProcXineramaDispatch, 247872b676d7Smrg SiSXineramaResetProc, 247972b676d7Smrg StandardMinorOpcode); 248072b676d7Smrg 248172b676d7Smrg if(!pSiS->XineramaExtEntry) break; 248272b676d7Smrg 248372b676d7Smrg if(!(SiSXineramadataPtr = (SiSXineramaData *) 24845788ca14Smrg calloc(SiSXineramaNumScreens, sizeof(SiSXineramaData)))) break; 248572b676d7Smrg 248672b676d7Smrg SiSXineramaGeneration = serverGeneration; 248772b676d7Smrg success = TRUE; 248872b676d7Smrg } 248972b676d7Smrg 249072b676d7Smrg if(!success) { 249172b676d7Smrg SISErrorLog(pScrn, "Failed to initialize SiS Pseudo-Xinerama extension\n"); 249272b676d7Smrg SiSnoPanoramiXExtension = TRUE; 249372b676d7Smrg pSiS->MouseRestrictions = FALSE; 249472b676d7Smrg return; 249572b676d7Smrg } 249672b676d7Smrg 249772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 249872b676d7Smrg "SiS Pseudo-Xinerama extension initialized\n"); 249972b676d7Smrg 250072b676d7Smrg pSiS->SiSXineramaVX = 0; 250172b676d7Smrg pSiS->SiSXineramaVY = 0; 250272b676d7Smrg 250372b676d7Smrg } 250472b676d7Smrg 250572b676d7Smrg SiSUpdateXineramaScreenInfo(pScrn); 250672b676d7Smrg 250772b676d7Smrg} 250872b676d7Smrg#endif /* End of PseudoXinerama */ 250972b676d7Smrg 251072b676d7Smrgstatic void 251172b676d7SmrgSiSFreeCRT2Structs(SISPtr pSiS) 251272b676d7Smrg{ 251372b676d7Smrg if(pSiS->CRT2pScrn) { 251472b676d7Smrg if(pSiS->CRT2pScrn->modes) { 251572b676d7Smrg while(pSiS->CRT2pScrn->modes) 251672b676d7Smrg xf86DeleteMode(&pSiS->CRT2pScrn->modes, pSiS->CRT2pScrn->modes); 251772b676d7Smrg } 251872b676d7Smrg if(pSiS->CRT2pScrn->monitor) { 251972b676d7Smrg if(pSiS->CRT2pScrn->monitor->Modes) { 252072b676d7Smrg while(pSiS->CRT2pScrn->monitor->Modes) 252172b676d7Smrg xf86DeleteMode(&pSiS->CRT2pScrn->monitor->Modes, pSiS->CRT2pScrn->monitor->Modes); 252272b676d7Smrg } 25235788ca14Smrg if(pSiS->CRT2pScrn->monitor->DDC) free(pSiS->CRT2pScrn->monitor->DDC); 25245788ca14Smrg free(pSiS->CRT2pScrn->monitor); 252572b676d7Smrg } 25265788ca14Smrg free(pSiS->CRT2pScrn); 252772b676d7Smrg pSiS->CRT2pScrn = NULL; 252872b676d7Smrg } 252972b676d7Smrg} 253072b676d7Smrg 253172b676d7Smrg#endif /* End of MergedFB helpers */ 253272b676d7Smrg 253372b676d7Smrgstatic xf86MonPtr 253472b676d7SmrgSiSInternalDDC(ScrnInfoPtr pScrn, int crtno) 253572b676d7Smrg{ 253672b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 253772b676d7Smrg xf86MonPtr pMonitor = NULL; 253872b676d7Smrg UShort temp = 0xffff, temp1, i, realcrtno = crtno; 253972b676d7Smrg UChar buffer[256]; 254072b676d7Smrg 254172b676d7Smrg /* If CRT1 is off, skip DDC */ 254272b676d7Smrg if((pSiS->CRT1off) && (!crtno)) return NULL; 254372b676d7Smrg 254472b676d7Smrg if(crtno) { 254572b676d7Smrg if(pSiS->VBFlags & CRT2_LCD) realcrtno = 1; 254672b676d7Smrg else if(pSiS->VBFlags & CRT2_VGA) realcrtno = 2; 254772b676d7Smrg else return NULL; 254872b676d7Smrg if(pSiS->SiS_Pr->DDCPortMixup) realcrtno = 0; 254972b676d7Smrg } else { 255072b676d7Smrg /* If CRT1 is LCDA, skip DDC (except 301C: DDC allowed, but uses CRT2 port!) */ 255172b676d7Smrg if(pSiS->VBFlags & CRT1_LCDA) { 255272b676d7Smrg if(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE) realcrtno = 1; 255372b676d7Smrg else return NULL; 255472b676d7Smrg } 255572b676d7Smrg } 255672b676d7Smrg 255772b676d7Smrg i = 3; /* Number of retrys */ 255872b676d7Smrg do { 255972b676d7Smrg temp1 = SiS_HandleDDC(pSiS->SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 256072b676d7Smrg realcrtno, 0, &buffer[0], pSiS->VBFlags2); 256172b676d7Smrg if((temp1) && (temp1 != 0xffff)) temp = temp1; 256272b676d7Smrg } while((temp == 0xffff) && i--); 256372b676d7Smrg if(temp != 0xffff) { 256472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT%d DDC supported\n", crtno + 1); 256572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT%d DDC level: %s%s%s%s\n", 256672b676d7Smrg crtno + 1, 256772b676d7Smrg (temp & 0x1a) ? "" : "[none of the supported]", 256872b676d7Smrg (temp & 0x02) ? "2 " : "", 256972b676d7Smrg (temp & 0x08) ? "D&P" : "", 257072b676d7Smrg (temp & 0x10) ? "FPDI-2" : ""); 257172b676d7Smrg if(temp & 0x02) { 257272b676d7Smrg i = 5; /* Number of retrys */ 257372b676d7Smrg do { 257472b676d7Smrg temp = SiS_HandleDDC(pSiS->SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 257572b676d7Smrg realcrtno, 1, &buffer[0], pSiS->VBFlags2); 257672b676d7Smrg } while((temp) && i--); 257772b676d7Smrg if(!temp) { 257872b676d7Smrg if((pMonitor = xf86InterpretEDID(pScrn->scrnIndex, &buffer[0]))) { 257972b676d7Smrg int tempvgagamma = 0, templcdgamma = 0; 258072b676d7Smrg if(buffer[0x14] & 0x80) { 258172b676d7Smrg templcdgamma = (buffer[0x17] + 100) * 10; 258272b676d7Smrg } else { 258372b676d7Smrg tempvgagamma = (buffer[0x17] + 100) * 10;; 258472b676d7Smrg } 258572b676d7Smrg if(crtno == 0) { 258672b676d7Smrg if(tempvgagamma) pSiS->CRT1VGAMonitorGamma = tempvgagamma; 258772b676d7Smrg /* LCD never via (demanded) CRT1 DDC port */ 258872b676d7Smrg } else { 258972b676d7Smrg if(tempvgagamma) pSiS->CRT2VGAMonitorGamma = tempvgagamma; 259072b676d7Smrg if(templcdgamma) pSiS->CRT2LCDMonitorGamma = templcdgamma; 259172b676d7Smrg } 259272b676d7Smrg return(pMonitor); 259372b676d7Smrg } else { 259472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 259572b676d7Smrg "CRT%d DDC EDID corrupt\n", crtno + 1); 259672b676d7Smrg } 259772b676d7Smrg } else if(temp == 0xFFFE) { 259872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 259972b676d7Smrg "CRT%d DDC data is from wrong device type (%s)\n", 260072b676d7Smrg crtno + 1, 260172b676d7Smrg (realcrtno == 1) ? "analog instead of digital" : "digital instead of analog"); 260272b676d7Smrg } else { 260372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 260472b676d7Smrg "CRT%d DDC reading failed\n", crtno + 1); 260572b676d7Smrg } 260672b676d7Smrg } else if(temp & 0x18) { 260772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 260872b676d7Smrg "DDC for VESA D&P and FPDI-2 not supported yet.\n"); 260972b676d7Smrg } 261072b676d7Smrg } else { 261172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 261272b676d7Smrg "CRT%d DDC probing failed\n", crtno + 1); 261372b676d7Smrg } 261472b676d7Smrg return(NULL); 261572b676d7Smrg} 261672b676d7Smrg 261772b676d7Smrgstatic xf86MonPtr 261872b676d7SmrgSiSDoPrivateDDC(ScrnInfoPtr pScrn, int *crtnum) 261972b676d7Smrg{ 262072b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 262172b676d7Smrg 262272b676d7Smrg#ifdef SISDUALHEAD 262372b676d7Smrg if(pSiS->DualHeadMode) { 262472b676d7Smrg if(pSiS->SecondHead) { 262572b676d7Smrg *crtnum = 1; 262672b676d7Smrg return(SiSInternalDDC(pScrn, 0)); 262772b676d7Smrg } else { 262872b676d7Smrg *crtnum = 2; 262972b676d7Smrg return(SiSInternalDDC(pScrn, 1)); 263072b676d7Smrg } 263172b676d7Smrg } else 263272b676d7Smrg#endif 263372b676d7Smrg if((pSiS->CRT1off) || (!pSiS->CRT1Detected)) { 263472b676d7Smrg *crtnum = 2; 263572b676d7Smrg return(SiSInternalDDC(pScrn, 1)); 263672b676d7Smrg } else { 263772b676d7Smrg *crtnum = 1; 263872b676d7Smrg return(SiSInternalDDC(pScrn, 0)); 263972b676d7Smrg } 264072b676d7Smrg} 264172b676d7Smrg 264272b676d7Smrgstatic void 264372b676d7SmrgSiSFindAspect(ScrnInfoPtr pScrn, xf86MonPtr pMonitor, int crtnum) 264472b676d7Smrg{ 264572b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 264672b676d7Smrg int UseWide = 0; 264772b676d7Smrg int aspect = 0; 264872b676d7Smrg Bool fromdim = FALSE; 264972b676d7Smrg 265072b676d7Smrg if((pSiS->VGAEngine == SIS_315_VGA) && (!DIGITAL(pMonitor->features.input_type))) { 265172b676d7Smrg if(pMonitor->features.hsize && pMonitor->features.vsize) { 265272b676d7Smrg aspect = (pMonitor->features.hsize * 1000) / pMonitor->features.vsize; 265372b676d7Smrg if(aspect >= 1400) UseWide = 1; 265472b676d7Smrg fromdim = TRUE; 265572b676d7Smrg } else if((PREFERRED_TIMING_MODE(pMonitor->features.msc)) && 265672b676d7Smrg (pMonitor->det_mon[0].type == DT)) { 265772b676d7Smrg aspect = (pMonitor->det_mon[0].section.d_timings.h_active * 1000) / 265872b676d7Smrg pMonitor->det_mon[0].section.d_timings.v_active; 265972b676d7Smrg if(aspect >= 1400) UseWide = 1; 266072b676d7Smrg } 266172b676d7Smrg if(aspect) { 266272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 266372b676d7Smrg "According to %s, CRT%d aspect ratio is %.2f:1 (%s)\n", 266472b676d7Smrg fromdim ? "DDC size" : "preferred mode", 266572b676d7Smrg crtnum, (float)aspect / 1000.0, UseWide ? "wide" : "normal"); 266672b676d7Smrg } else { 266772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 266872b676d7Smrg "Unable to determine CRT%d aspect ratio, assuming \"normal\"\n", 266972b676d7Smrg crtnum); 267072b676d7Smrg } 267172b676d7Smrg } 267272b676d7Smrg 267372b676d7Smrg if((crtnum == 1) && (pSiS->SiS_Pr->SiS_UseWide == -1)) { 267472b676d7Smrg pSiS->SiS_Pr->SiS_UseWide = UseWide; 267572b676d7Smrg } else if((crtnum == 2) && (pSiS->SiS_Pr->SiS_UseWideCRT2 == -1)) { 267672b676d7Smrg pSiS->SiS_Pr->SiS_UseWideCRT2 = UseWide; 267772b676d7Smrg } 267872b676d7Smrg} 267972b676d7Smrg 268072b676d7Smrgstatic Bool 268172b676d7SmrgSiSMakeOwnModeList(ScrnInfoPtr pScrn, Bool acceptcustommodes, Bool includelcdmodes, 268272b676d7Smrg Bool isfordvi, Bool *havecustommodes, Bool fakecrt2modes, Bool IsForCRT2) 268372b676d7Smrg{ 268472b676d7Smrg DisplayModePtr tempmode, delmode, mymodes; 268572b676d7Smrg 268672b676d7Smrg if((mymodes = SiSBuildBuiltInModeList(pScrn, includelcdmodes, isfordvi, fakecrt2modes, IsForCRT2))) { 268772b676d7Smrg if(!acceptcustommodes) { 268872b676d7Smrg while(pScrn->monitor->Modes) 268972b676d7Smrg xf86DeleteMode(&pScrn->monitor->Modes, pScrn->monitor->Modes); 269072b676d7Smrg pScrn->monitor->Modes = mymodes; 269172b676d7Smrg } else { 269272b676d7Smrg delmode = pScrn->monitor->Modes; 269372b676d7Smrg while(delmode) { 269472b676d7Smrg if(delmode->type & M_T_DEFAULT) { 269572b676d7Smrg tempmode = delmode->next; 269672b676d7Smrg xf86DeleteMode(&pScrn->monitor->Modes, delmode); 269772b676d7Smrg delmode = tempmode; 269872b676d7Smrg } else { 269972b676d7Smrg delmode = delmode->next; 270072b676d7Smrg } 270172b676d7Smrg } 270272b676d7Smrg /* Link default modes AFTER user ones */ 270372b676d7Smrg if((tempmode = pScrn->monitor->Modes)) { 270472b676d7Smrg *havecustommodes = TRUE; 270572b676d7Smrg while(tempmode) { 270672b676d7Smrg if(!tempmode->next) break; 270772b676d7Smrg else tempmode = tempmode->next; 270872b676d7Smrg } 270972b676d7Smrg tempmode->next = mymodes; 271072b676d7Smrg mymodes->prev = tempmode; 271172b676d7Smrg } else { 271272b676d7Smrg pScrn->monitor->Modes = mymodes; 271372b676d7Smrg } 271472b676d7Smrg#if 0 271572b676d7Smrg pScrn->monitor->Modes = mymodes; 271672b676d7Smrg while(mymodes) { 271772b676d7Smrg if(!mymodes->next) break; 271872b676d7Smrg else mymodes = mymodes->next; 271972b676d7Smrg } 272072b676d7Smrg mymodes->next = tempmode; 272172b676d7Smrg if(tempmode) { 272272b676d7Smrg tempmode->prev = mymodes; 272372b676d7Smrg } 272472b676d7Smrg#endif 272572b676d7Smrg } 272672b676d7Smrg return TRUE; 272772b676d7Smrg } else 272872b676d7Smrg return FALSE; 272972b676d7Smrg} 273072b676d7Smrg 273172b676d7Smrgstatic void 273272b676d7SmrgSiSPrintModes(ScrnInfoPtr pScrn) 273372b676d7Smrg{ 273472b676d7Smrg DisplayModePtr p; 273572b676d7Smrg float hsync, refresh = 0.0; 273672b676d7Smrg char *desc, *desc2, *prefix, *uprefix, *output; 273772b676d7Smrg 273872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, pScrn->virtualFrom, "Virtual size is %dx%d " 273972b676d7Smrg "(pitch %d)\n", pScrn->virtualX, pScrn->virtualY, 274072b676d7Smrg pScrn->displayWidth); 274172b676d7Smrg 274272b676d7Smrg if((p = pScrn->modes) == NULL) return; 274372b676d7Smrg 274472b676d7Smrg do { 274572b676d7Smrg desc = desc2 = ""; 274672b676d7Smrg uprefix = " "; 274772b676d7Smrg prefix = "Mode"; 274872b676d7Smrg output = "For CRT device: "; 274972b676d7Smrg if(p->HSync > 0.0) hsync = p->HSync; 275072b676d7Smrg else if (p->HTotal > 0) hsync = (float)p->Clock / (float)p->HTotal; 275172b676d7Smrg else hsync = 0.0; 275272b676d7Smrg refresh = 0.0; 275372b676d7Smrg if(p->VRefresh > 0.0) refresh = p->VRefresh; 275472b676d7Smrg else if (p->HTotal > 0 && p->VTotal > 0) { 275572b676d7Smrg refresh = p->Clock * 1000.0 / p->HTotal / p->VTotal; 275672b676d7Smrg if(p->Flags & V_INTERLACE) refresh *= 2.0; 275772b676d7Smrg if(p->Flags & V_DBLSCAN) refresh /= 2.0; 275872b676d7Smrg if(p->VScan > 1) refresh /= p->VScan; 275972b676d7Smrg } 276072b676d7Smrg if(p->Flags & V_INTERLACE) desc = " (I)"; 276172b676d7Smrg if(p->Flags & V_DBLSCAN) desc = " (D)"; 276272b676d7Smrg if(p->VScan > 1) desc2 = " (VScan)"; 276372b676d7Smrg#ifdef M_T_USERDEF 276472b676d7Smrg if(p->type & M_T_USERDEF) uprefix = "*"; 276572b676d7Smrg#endif 276672b676d7Smrg if(p->type & M_T_BUILTIN) { 276772b676d7Smrg prefix = "Built-in mode"; 276872b676d7Smrg output = ""; 276972b676d7Smrg } else if (p->type & M_T_DEFAULT) { 277072b676d7Smrg prefix = "Default mode"; 277172b676d7Smrg } else { 277272b676d7Smrg output = ""; 277372b676d7Smrg } 277472b676d7Smrg 277572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 277672b676d7Smrg "%s%s \"%s\" (%dx%d) (%s%.1f MHz, %.1f kHz, %.1f Hz%s%s)\n", 277772b676d7Smrg uprefix, prefix, p->name, p->HDisplay, p->VDisplay, output, 277872b676d7Smrg p->Clock / 1000.0, hsync, refresh, desc, desc2); 277972b676d7Smrg 278072b676d7Smrg p = p->next; 278172b676d7Smrg } while (p != NULL && p != pScrn->modes); 278272b676d7Smrg} 278372b676d7Smrg 278472b676d7SmrgBool SISDetermineLCDACap(ScrnInfoPtr pScrn) 278572b676d7Smrg{ 278672b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 278772b676d7Smrg 278872b676d7Smrg if( ((pSiS->ChipType == SIS_650) || 278972b676d7Smrg (pSiS->ChipType == SIS_315PRO) || 279072b676d7Smrg (pSiS->ChipType >= SIS_661)) && 279172b676d7Smrg (pSiS->ChipType != XGI_20) && 279272b676d7Smrg (pSiS->VBFlags2 & VB2_SISLCDABRIDGE) && 279372b676d7Smrg (pSiS->VESA != 1) ) { 279472b676d7Smrg return TRUE; 279572b676d7Smrg } 279672b676d7Smrg return FALSE; 279772b676d7Smrg} 279872b676d7Smrg 279972b676d7Smrgvoid SISSaveDetectedDevices(ScrnInfoPtr pScrn) 280072b676d7Smrg{ 280172b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 280272b676d7Smrg /* Backup detected CRT2 devices */ 280372b676d7Smrg pSiS->detectedCRT2Devices = pSiS->VBFlags & (CRT2_LCD|CRT2_TV|CRT2_VGA|TV_AVIDEO|TV_SVIDEO| 280472b676d7Smrg TV_SCART|TV_HIVISION|TV_YPBPR); 280572b676d7Smrg} 280672b676d7Smrg 280772b676d7Smrgstatic Bool 280872b676d7SmrgSISCheckBIOS(SISPtr pSiS, UShort mypciid, UShort mypcivendor, int biossize) 280972b676d7Smrg{ 281072b676d7Smrg UShort romptr, pciid; 281172b676d7Smrg 281272b676d7Smrg if(!pSiS->BIOS) return FALSE; 281372b676d7Smrg 281472b676d7Smrg if((pSiS->BIOS[0] != 0x55) || (pSiS->BIOS[1] != 0xaa)) return FALSE; 281572b676d7Smrg 281672b676d7Smrg romptr = pSiS->BIOS[0x18] | (pSiS->BIOS[0x19] << 8); 281772b676d7Smrg if(romptr > (biossize - 8)) return FALSE; 281872b676d7Smrg if((pSiS->BIOS[romptr] != 'P') || (pSiS->BIOS[romptr+1] != 'C') || 281972b676d7Smrg (pSiS->BIOS[romptr+2] != 'I') || (pSiS->BIOS[romptr+3] != 'R')) return FALSE; 282072b676d7Smrg 282172b676d7Smrg pciid = pSiS->BIOS[romptr+4] | (pSiS->BIOS[romptr+5] << 8); 282272b676d7Smrg if(pciid != mypcivendor) return FALSE; 282372b676d7Smrg 282472b676d7Smrg pciid = pSiS->BIOS[romptr+6] | (pSiS->BIOS[romptr+7] << 8); 282572b676d7Smrg if(pciid != mypciid) return FALSE; 282672b676d7Smrg 282772b676d7Smrg return TRUE; 282872b676d7Smrg} 282972b676d7Smrg 283072b676d7Smrgstatic void 283172b676d7SmrgSiS_LoadInitVBE(ScrnInfoPtr pScrn) 283272b676d7Smrg{ 283372b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 283472b676d7Smrg 283572b676d7Smrg /* Don't load the VBE module for secondary 283672b676d7Smrg * cards which sisfb POSTed. We don't want 283772b676d7Smrg * int10 to overwrite our set up (such as 283872b676d7Smrg * disabled a0000 memory address decoding). 283972b676d7Smrg * We don't need the VBE anyway because 284072b676d7Smrg * the card will never be in text mode, 284172b676d7Smrg * and we can restore graphics modes just 284272b676d7Smrg * perfectly. 284372b676d7Smrg */ 284472b676d7Smrg if( !pSiS->Primary && 284572b676d7Smrg pSiS->sisfbcardposted) 284672b676d7Smrg return; 284772b676d7Smrg 284872b676d7Smrg if(pSiS->pVbe) return; 284972b676d7Smrg 285072b676d7Smrg if(xf86LoadSubModule(pScrn, "vbe")) { 285172b676d7Smrg#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 285272b676d7Smrg pSiS->pVbe = VBEInit(pSiS->pInt, pSiS->pEnt->index); 285372b676d7Smrg#else 285472b676d7Smrg pSiS->pVbe = VBEExtendedInit(pSiS->pInt, pSiS->pEnt->index, 285572b676d7Smrg SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH); 285672b676d7Smrg#endif 285772b676d7Smrg } 285872b676d7Smrg 285972b676d7Smrg if(!pSiS->pVbe) { 286072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 286172b676d7Smrg "Failed to load/initialize vbe module\n"); 286272b676d7Smrg } 286372b676d7Smrg} 286472b676d7Smrg 286572b676d7Smrg#ifdef SIS_PC_PLATFORM 286672b676d7Smrgstatic void 286772b676d7SmrgSiS_MapVGAMem(ScrnInfoPtr pScrn) 286872b676d7Smrg{ 286972b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 287072b676d7Smrg 287172b676d7Smrg /* Map 64k VGA window for saving/restoring CGA fonts */ 287272b676d7Smrg pSiS->VGAMapSize = 0x10000; 287372b676d7Smrg pSiS->VGAMapPhys = 0; /* Default */ 287472b676d7Smrg if((!pSiS->Primary) || (!pSiS->VGADecodingEnabled)) { 287572b676d7Smrg /* If card is secondary or if a0000-address decoding 287672b676d7Smrg * is disabled, set Phys to beginning of our video RAM. 287772b676d7Smrg */ 28781fd23544Smrg pSiS->VGAMapPhys = PCI_REGION_BASE(pSiS->PciInfo, 0, REGION_MEM); 287972b676d7Smrg } 288072b676d7Smrg if(!SiSVGAMapMem(pScrn)) { 288172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 288272b676d7Smrg "Failed to map VGA memory (0x%lx), can't save/restore console fonts\n", 288372b676d7Smrg pSiS->VGAMapPhys); 288472b676d7Smrg } 288572b676d7Smrg} 288672b676d7Smrg#endif 288772b676d7Smrg 288872b676d7Smrgstatic void 288972b676d7SmrgSiS_CheckKernelFB(ScrnInfoPtr pScrn) 289072b676d7Smrg{ 289172b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 289272b676d7Smrg int fd, i; 289372b676d7Smrg CARD32 sisfbinfosize = 0, sisfbversion; 289472b676d7Smrg sisfb_info *mysisfbinfo; 289572b676d7Smrg char name[16]; 289672b676d7Smrg 289772b676d7Smrg pSiS->donttrustpdc = FALSE; 289872b676d7Smrg pSiS->sisfbpdc = 0xff; 289972b676d7Smrg pSiS->sisfbpdca = 0xff; 290072b676d7Smrg pSiS->sisfblcda = 0xff; 290172b676d7Smrg pSiS->sisfbscalelcd = -1; 290272b676d7Smrg pSiS->sisfbspecialtiming = CUT_NONE; 290372b676d7Smrg pSiS->sisfb_haveemi = FALSE; 290472b676d7Smrg pSiS->sisfbfound = FALSE; 290572b676d7Smrg pSiS->sisfb_tvposvalid = FALSE; 290672b676d7Smrg pSiS->sisfbdevname[0] = 0; 290772b676d7Smrg pSiS->sisfb_havelock = FALSE; 290872b676d7Smrg pSiS->sisfbHaveNewHeapDef = FALSE; 290972b676d7Smrg pSiS->sisfbHeapSize = 0; 291072b676d7Smrg pSiS->sisfbVideoOffset = 0; 291172b676d7Smrg pSiS->sisfbxSTN = FALSE; 291272b676d7Smrg pSiS->sisfbcanpost = FALSE; /* (Old) sisfb can't POST card */ 291372b676d7Smrg pSiS->sisfbcardposted = TRUE; /* If (old) sisfb is running, card must have been POSTed */ 291472b676d7Smrg pSiS->sisfbprimary = FALSE; /* (Old) sisfb doesn't know */ 291572b676d7Smrg 291672b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 291772b676d7Smrg 291872b676d7Smrg i = 0; 291972b676d7Smrg do { 292072b676d7Smrg 292172b676d7Smrg if(i <= 7) { 292272b676d7Smrg sprintf(name, "/dev/fb%1d", i); 292372b676d7Smrg } else { 292472b676d7Smrg sprintf(name, "/dev/fb/%1d", (i - 8)); 292572b676d7Smrg } 292672b676d7Smrg 29271fd23544Smrg if((fd = open(name, O_RDONLY)) != -1) { 292872b676d7Smrg 292972b676d7Smrg Bool gotit = FALSE; 293072b676d7Smrg 293172b676d7Smrg if(!ioctl(fd, SISFB_GET_INFO_SIZE, &sisfbinfosize)) { 29325788ca14Smrg if((mysisfbinfo = malloc(sisfbinfosize))) { 293372b676d7Smrg if(!ioctl(fd, (SISFB_GET_INFO | (sisfbinfosize << 16)), mysisfbinfo)) { 293472b676d7Smrg gotit = TRUE; 293572b676d7Smrg } else { 29365788ca14Smrg free(mysisfbinfo); 293772b676d7Smrg mysisfbinfo = NULL; 293872b676d7Smrg } 293972b676d7Smrg } 294072b676d7Smrg } else { 29415788ca14Smrg if((mysisfbinfo = malloc(sizeof(*mysisfbinfo) + 16))) { 294272b676d7Smrg if(!ioctl(fd, SISFB_GET_INFO_OLD, mysisfbinfo)) { 294372b676d7Smrg gotit = TRUE; 294472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 294572b676d7Smrg "Possibly old version of sisfb detected. Please update.\n"); 294672b676d7Smrg } else { 29475788ca14Smrg free(mysisfbinfo); 294872b676d7Smrg mysisfbinfo = NULL; 294972b676d7Smrg } 295072b676d7Smrg } 295172b676d7Smrg } 295272b676d7Smrg 295372b676d7Smrg if(gotit) { 295472b676d7Smrg 295572b676d7Smrg if(mysisfbinfo->sisfb_id == SISFB_ID) { 295672b676d7Smrg 295772b676d7Smrg sisfbversion = (mysisfbinfo->sisfb_version << 16) | 295872b676d7Smrg (mysisfbinfo->sisfb_revision << 8) | 295972b676d7Smrg (mysisfbinfo->sisfb_patchlevel); 296072b676d7Smrg 296172b676d7Smrg if(sisfbversion >= SISFB_VERSION(1, 5, 8)) { 296272b676d7Smrg /* Added PCI bus/slot/func into in sisfb Version 1.5.08. 296372b676d7Smrg * Check this to make sure we run on the same card as sisfb 296472b676d7Smrg */ 296572b676d7Smrg if((mysisfbinfo->sisfb_pcibus == pSiS->PciBus) && 296672b676d7Smrg (mysisfbinfo->sisfb_pcislot == pSiS->PciDevice) && 296772b676d7Smrg (mysisfbinfo->sisfb_pcifunc == pSiS->PciFunc)) { 296872b676d7Smrg pSiS->sisfbfound = TRUE; 296972b676d7Smrg } 297072b676d7Smrg } else pSiS->sisfbfound = TRUE; 297172b676d7Smrg 297272b676d7Smrg if(pSiS->sisfbfound) { 297372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 297472b676d7Smrg "%s: SiS kernel fb driver (sisfb) %d.%d.%d detected (PCI:%02d:%02d.%d)\n", 297572b676d7Smrg &name[5], 297672b676d7Smrg mysisfbinfo->sisfb_version, 297772b676d7Smrg mysisfbinfo->sisfb_revision, 297872b676d7Smrg mysisfbinfo->sisfb_patchlevel, 297972b676d7Smrg pSiS->PciBus, 298072b676d7Smrg pSiS->PciDevice, 298172b676d7Smrg pSiS->PciFunc); 298272b676d7Smrg 298372b676d7Smrg /* Added version/rev/pl in sisfb 1.4.0 */ 298472b676d7Smrg if(mysisfbinfo->sisfb_version == 0) { 298572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 298672b676d7Smrg "Old version of sisfb found. Please update.\n"); 298772b676d7Smrg } 298872b676d7Smrg /* Basically, we can't trust the pdc register if sisfb is loaded */ 298972b676d7Smrg pSiS->donttrustpdc = TRUE; 299072b676d7Smrg pSiS->sisfbHeapStart = mysisfbinfo->heapstart; 299172b676d7Smrg 299272b676d7Smrg if(sisfbversion >= SISFB_VERSION(1, 7, 20)) { 299372b676d7Smrg pSiS->sisfbHeapSize = mysisfbinfo->sisfb_heapsize; 299472b676d7Smrg pSiS->sisfbVideoOffset = mysisfbinfo->sisfb_videooffset; 299572b676d7Smrg pSiS->sisfbHaveNewHeapDef = TRUE; 299672b676d7Smrg pSiS->sisfbFSTN = mysisfbinfo->sisfb_curfstn; 299772b676d7Smrg pSiS->sisfbDSTN = mysisfbinfo->sisfb_curdstn; 299872b676d7Smrg pSiS->sisfbxSTN = TRUE; 299972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 300072b676d7Smrg "sisfb: memory heap at %dKB, size %dKB, viewport at %dKB\n", 300172b676d7Smrg (int)pSiS->sisfbHeapStart, (int)pSiS->sisfbHeapSize, 300272b676d7Smrg (int)pSiS->sisfbVideoOffset/1024); 300372b676d7Smrg } else { 300472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 300572b676d7Smrg "sisfb: memory heap at %dKB\n", (int)pSiS->sisfbHeapStart); 300672b676d7Smrg } 300772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 300872b676d7Smrg "sisfb: using video mode 0x%02x\n", mysisfbinfo->fbvidmode); 300972b676d7Smrg pSiS->OldMode = mysisfbinfo->fbvidmode; 301072b676d7Smrg if(sisfbversion >= SISFB_VERSION(1, 5, 6)) { 301172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 301272b676d7Smrg "sisfb: using %s, reserved %dK\n", 301372b676d7Smrg (mysisfbinfo->sisfb_caps & 0x40) ? "SiS300 series Turboqueue" : 301472b676d7Smrg (mysisfbinfo->sisfb_caps & 0x20) ? "SiS315/330/340 series AGP command queue" : 301572b676d7Smrg (mysisfbinfo->sisfb_caps & 0x10) ? "SiS315/330/340 series VRAM command queue" : 301672b676d7Smrg (mysisfbinfo->sisfb_caps & 0x08) ? "SiS315/330/340 series MMIO mode" : 301772b676d7Smrg "no command queue", 301872b676d7Smrg (int)mysisfbinfo->sisfb_tqlen); 301972b676d7Smrg } 302072b676d7Smrg if(sisfbversion >= SISFB_VERSION(1, 5, 10)) { 302172b676d7Smrg /* We can trust the pdc value if sisfb is of recent version */ 302272b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) pSiS->donttrustpdc = FALSE; 302372b676d7Smrg } 302472b676d7Smrg if(sisfbversion >= SISFB_VERSION(1, 5, 11)) { 302572b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 302672b676d7Smrg /* As of 1.5.11, sisfb saved the register for us (300 series) */ 302772b676d7Smrg pSiS->sisfbpdc = mysisfbinfo->sisfb_lcdpdc; 302872b676d7Smrg if(!pSiS->sisfbpdc) pSiS->sisfbpdc = 0xff; 302972b676d7Smrg } 303072b676d7Smrg } 303172b676d7Smrg if(sisfbversion >= SISFB_VERSION(1, 5, 14)) { 303272b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 303372b676d7Smrg pSiS->sisfblcda = mysisfbinfo->sisfb_lcda; 303472b676d7Smrg } 303572b676d7Smrg } 303672b676d7Smrg if(sisfbversion >= SISFB_VERSION(1, 6, 13)) { 303772b676d7Smrg pSiS->sisfbscalelcd = mysisfbinfo->sisfb_scalelcd; 303872b676d7Smrg pSiS->sisfbspecialtiming = mysisfbinfo->sisfb_specialtiming; 303972b676d7Smrg } 304072b676d7Smrg if(sisfbversion >= SISFB_VERSION(1, 6, 16)) { 304172b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 304272b676d7Smrg pSiS->donttrustpdc = FALSE; 304372b676d7Smrg pSiS->sisfbpdc = mysisfbinfo->sisfb_lcdpdc; 304472b676d7Smrg if(sisfbversion >= SISFB_VERSION(1, 6, 24)) { 304572b676d7Smrg pSiS->sisfb_haveemi = mysisfbinfo->sisfb_haveemi ? TRUE : FALSE; 304672b676d7Smrg pSiS->sisfb_haveemilcd = TRUE; /* will match most cases */ 304772b676d7Smrg pSiS->sisfb_emi30 = mysisfbinfo->sisfb_emi30; 304872b676d7Smrg pSiS->sisfb_emi31 = mysisfbinfo->sisfb_emi31; 304972b676d7Smrg pSiS->sisfb_emi32 = mysisfbinfo->sisfb_emi32; 305072b676d7Smrg pSiS->sisfb_emi33 = mysisfbinfo->sisfb_emi33; 305172b676d7Smrg } 305272b676d7Smrg if(sisfbversion >= SISFB_VERSION(1, 6, 25)) { 305372b676d7Smrg pSiS->sisfb_haveemilcd = mysisfbinfo->sisfb_haveemilcd ? TRUE : FALSE; 305472b676d7Smrg } 305572b676d7Smrg if(sisfbversion >= SISFB_VERSION(1, 6, 31)) { 305672b676d7Smrg pSiS->sisfbpdca = mysisfbinfo->sisfb_lcdpdca; 305772b676d7Smrg } else { 305872b676d7Smrg if(pSiS->sisfbpdc) { 305972b676d7Smrg pSiS->sisfbpdca = (pSiS->sisfbpdc & 0xf0) >> 3; 306072b676d7Smrg pSiS->sisfbpdc = (pSiS->sisfbpdc & 0x0f) << 1; 306172b676d7Smrg } else { 306272b676d7Smrg pSiS->sisfbpdca = pSiS->sisfbpdc = 0xff; 306372b676d7Smrg } 306472b676d7Smrg } 306572b676d7Smrg } 306672b676d7Smrg } 306772b676d7Smrg if(sisfbversion >= SISFB_VERSION(1, 7, 0)) { 306872b676d7Smrg pSiS->sisfb_havelock = TRUE; 306972b676d7Smrg if(sisfbversion >= SISFB_VERSION(1, 7, 1)) { 307072b676d7Smrg pSiS->sisfb_tvxpos = mysisfbinfo->sisfb_tvxpos; 307172b676d7Smrg pSiS->sisfb_tvypos = mysisfbinfo->sisfb_tvypos; 307272b676d7Smrg pSiS->sisfb_tvposvalid = TRUE; 307372b676d7Smrg } 307472b676d7Smrg } 307572b676d7Smrg if(sisfbversion >= SISFB_VERSION(1, 8, 7)) { 307672b676d7Smrg pSiS->sisfbcanpost = (mysisfbinfo->sisfb_can_post) ? TRUE : FALSE; 307772b676d7Smrg pSiS->sisfbcardposted = (mysisfbinfo->sisfb_card_posted) ? TRUE : FALSE; 307872b676d7Smrg pSiS->sisfbprimary = (mysisfbinfo->sisfb_was_boot_device) ? TRUE : FALSE; 307972b676d7Smrg /* Validity check */ 308072b676d7Smrg if(!pSiS->sisfbcardposted) { 308172b676d7Smrg pSiS->sisfbprimary = FALSE; 308272b676d7Smrg } 308372b676d7Smrg } 308472b676d7Smrg } 308572b676d7Smrg } 30865788ca14Smrg free(mysisfbinfo); 308772b676d7Smrg mysisfbinfo = NULL; 308872b676d7Smrg } 308972b676d7Smrg close (fd); 309072b676d7Smrg } 309172b676d7Smrg i++; 309272b676d7Smrg } while((i <= 15) && (!pSiS->sisfbfound)); 309372b676d7Smrg 309472b676d7Smrg if(pSiS->sisfbfound) { 309572b676d7Smrg strncpy(pSiS->sisfbdevname, name, 15); 309672b676d7Smrg } else { 309772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "sisfb not found\n"); 309872b676d7Smrg } 309972b676d7Smrg } 310072b676d7Smrg 310172b676d7Smrg if(!pSiS->sisfbfound) { 310272b676d7Smrg pSiS->sisfbcardposted = FALSE; 310372b676d7Smrg } 310472b676d7Smrg} 310572b676d7Smrg 310672b676d7Smrgstatic void 310772b676d7SmrgSiSPseudo(ScrnInfoPtr pScrn) 310872b676d7Smrg{ 310972b676d7Smrg} 311072b676d7Smrg 311172b676d7Smrg/* PreInit() 311272b676d7Smrg * 311372b676d7Smrg * Mandatory 311472b676d7Smrg */ 311572b676d7Smrgstatic Bool 311672b676d7SmrgSISPreInit(ScrnInfoPtr pScrn, int flags) 311772b676d7Smrg{ 311872b676d7Smrg SISPtr pSiS; 311972b676d7Smrg#ifdef SISDUALHEAD 312072b676d7Smrg SISEntPtr pSiSEnt = NULL; 312172b676d7Smrg#endif 312272b676d7Smrg MessageType from; 312372b676d7Smrg UChar usScratchCR17, usScratchCR32, usScratchCR63; 312472b676d7Smrg UChar usScratchSR1F, srlockReg, crlockReg; 312572b676d7Smrg unsigned int i; 312672b676d7Smrg int pix24flags, temp; 312772b676d7Smrg ClockRangePtr clockRanges; 312872b676d7Smrg xf86MonPtr pMonitor = NULL; 312972b676d7Smrg Bool didddc2, fromDDC, crt1freqoverruled = FALSE; 313072b676d7Smrg UChar CR5F, tempreg; 313172b676d7Smrg#if defined(SISMERGED) || defined(SISDUALHEAD) 313272b676d7Smrg DisplayModePtr first, p, n; 313372b676d7Smrg#endif 313472b676d7Smrg#ifdef SISMERGED 313572b676d7Smrg Bool crt2freqoverruled = FALSE; 313672b676d7Smrg#endif 313772b676d7Smrg 313872b676d7Smrg static const char *ddcsstr = "CRT%d DDC monitor info: *******************************************\n"; 313972b676d7Smrg static const char *ddcestr = "End of CRT%d DDC monitor info *************************************\n"; 314072b676d7Smrg static const char *subshstr = "Substituting missing CRT%d monitor HSync range by DDC data\n"; 314172b676d7Smrg static const char *subsvstr = "Substituting missing CRT%d monitor VRefresh range by DDC data\n"; 314272b676d7Smrg static const char *saneh = "Correcting %s CRT%d monitor HSync range\n"; 314372b676d7Smrg static const char *sanev = "Correcting %s CRT%d monitor VRefresh range\n"; 314472b676d7Smrg#ifdef SISMERGED 314572b676d7Smrg static const char *mergednocrt1 = "CRT1 not detected or forced off. %s.\n"; 314672b676d7Smrg static const char *mergednocrt2 = "No CRT2 output selected or no video bridge detected. %s.\n"; 314772b676d7Smrg static const char *mergeddisstr = "MergedFB mode disabled"; 314872b676d7Smrg static const char *modesforstr = "Modes for CRT%d: **************************************************\n"; 314972b676d7Smrg static const char *crtsetupstr = "*************************** CRT%d setup ***************************\n"; 315072b676d7Smrg static const char *crt2monname = "CRT2"; 315172b676d7Smrg#endif 315272b676d7Smrg#if defined(SISDUALHEAD) || defined(SISMERGED) 315372b676d7Smrg static const char *notsuitablestr = "Not using mode \"%s\" (not suitable for %s mode)\n"; 315472b676d7Smrg#endif 315572b676d7Smrg 315672b676d7Smrg if(flags & PROBE_DETECT) { 315772b676d7Smrg 315872b676d7Smrg vbeInfoPtr pVbe; 315972b676d7Smrg 316072b676d7Smrg if(xf86LoadSubModule(pScrn, "vbe")) { 316172b676d7Smrg int index = xf86GetEntityInfo(pScrn->entityList[0])->index; 316272b676d7Smrg#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 316372b676d7Smrg if((pVbe = VBEInit(NULL, index))) 316472b676d7Smrg#else 316572b676d7Smrg if((pVbe = VBEExtendedInit(NULL, index, 0))) 316672b676d7Smrg#endif 316772b676d7Smrg { 316872b676d7Smrg ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 316972b676d7Smrg vbeFree(pVbe); 317072b676d7Smrg } 317172b676d7Smrg } 317272b676d7Smrg return TRUE; 317372b676d7Smrg } 317472b676d7Smrg 317572b676d7Smrg /* 317672b676d7Smrg * Note: This function is only called once at server startup, and 317772b676d7Smrg * not at the start of each server generation. This means that 317872b676d7Smrg * only things that are persistent across server generations can 317972b676d7Smrg * be initialised here. xf86Screens[] is the array of all screens, 318072b676d7Smrg * (pScrn is a pointer to one of these). Privates allocated using 318172b676d7Smrg * xf86AllocateScrnInfoPrivateIndex() are too, and should be used 318272b676d7Smrg * for data that must persist across server generations. 318372b676d7Smrg * 318472b676d7Smrg * Per-generation data should be allocated with 318572b676d7Smrg * AllocateScreenPrivateIndex() from the ScreenInit() function. 318672b676d7Smrg */ 318772b676d7Smrg 318872b676d7Smrg /* Check the number of entities, and fail if it isn't one. */ 318972b676d7Smrg if(pScrn->numEntities != 1) { 319072b676d7Smrg SISErrorLog(pScrn, "Number of entities is not 1\n"); 319172b676d7Smrg return FALSE; 319272b676d7Smrg } 319372b676d7Smrg 319472b676d7Smrg /* Due to the liberal license terms this is needed for 319572b676d7Smrg * keeping the copyright notice readable and intact in 319672b676d7Smrg * binary distributions. Removing this is a copyright 319772b676d7Smrg * infringement. Please read the license terms above. 319872b676d7Smrg */ 319972b676d7Smrg 320072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 320172b676d7Smrg "SiS driver (%d/%02d/%02d-%d, compiled for " SISMYSERVERNAME " %d.%d.%d.%d)\n", 320272b676d7Smrg SISDRIVERVERSIONYEAR + 2000, SISDRIVERVERSIONMONTH, 320372b676d7Smrg SISDRIVERVERSIONDAY, SISDRIVERREVISION, 320472b676d7Smrg#ifdef XORG_VERSION_CURRENT 320572b676d7Smrg XORG_VERSION_MAJOR, XORG_VERSION_MINOR, 320672b676d7Smrg XORG_VERSION_PATCH, XORG_VERSION_SNAP 320772b676d7Smrg#else 320872b676d7Smrg XF86_VERSION_MAJOR, XF86_VERSION_MINOR, 320972b676d7Smrg XF86_VERSION_PATCH, XF86_VERSION_SNAP 321072b676d7Smrg#endif 321172b676d7Smrg ); 321272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 321372b676d7Smrg "Copyright (C) 2001-2005 Thomas Winischhofer <thomas@winischhofer.net> and others\n"); 321472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3215e35772b2Smrg "*** See http://www.winischhofer.eu/linuxsisvga.shtml\n"); 321672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 321772b676d7Smrg "*** for documentation and updates.\n"); 321872b676d7Smrg 321972b676d7Smrg#ifdef XORG_VERSION_CURRENT 322072b676d7Smrg#if 0 /* no prototype yet */ 322172b676d7Smrg if(xorgGetVersion() != XORG_VERSION_CURRENT) { 322272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 322372b676d7Smrg "This driver binary is not compiled for this version of " SISMYSERVERNAME "\n"); 322472b676d7Smrg } 322572b676d7Smrg#endif 322672b676d7Smrg#else 322772b676d7Smrg#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0) 322872b676d7Smrg if(xf86GetVersion() != XF86_VERSION_CURRENT) { 322972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 323072b676d7Smrg "This driver binary is not compiled for this version of " SISMYSERVERNAME "\n"); 323172b676d7Smrg } 323272b676d7Smrg#endif 323372b676d7Smrg#endif 323472b676d7Smrg 323572b676d7Smrg /* Allocate the SISRec driverPrivate */ 323672b676d7Smrg if(!SISGetRec(pScrn)) { 323772b676d7Smrg SISErrorLog(pScrn, "Could not allocate memory for pSiS private\n"); 323872b676d7Smrg return FALSE; 323972b676d7Smrg } 324072b676d7Smrg pSiS = SISPTR(pScrn); 324172b676d7Smrg pSiS->pScrn = pScrn; 324272b676d7Smrg 324372b676d7Smrg pSiS->pInt = NULL; 324472b676d7Smrg 324572b676d7Smrg /* Save PCI Domain Base */ 32465788ca14Smrg#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) || GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 12 324772b676d7Smrg pSiS->IODBase = 0; 324872b676d7Smrg#else 324972b676d7Smrg pSiS->IODBase = pScrn->domainIOBase; 325072b676d7Smrg#endif 325172b676d7Smrg 325272b676d7Smrg /* Get the entity, and make sure it is PCI. */ 325372b676d7Smrg pSiS->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 325472b676d7Smrg if(pSiS->pEnt->location.type != BUS_PCI) { 325572b676d7Smrg SISErrorLog(pScrn, "Entity's bus type is not PCI\n"); 325672b676d7Smrg goto my_error_0; 325772b676d7Smrg } 325872b676d7Smrg 325972b676d7Smrg#ifdef SISDUALHEAD 326072b676d7Smrg /* Allocate an entity private if necessary */ 326172b676d7Smrg if(xf86IsEntityShared(pScrn->entityList[0])) { 326272b676d7Smrg pSiSEnt = xf86GetEntityPrivate(pScrn->entityList[0], SISEntityIndex)->ptr; 326372b676d7Smrg pSiS->entityPrivate = pSiSEnt; 326472b676d7Smrg 326572b676d7Smrg /* If something went wrong, quit here */ 326672b676d7Smrg if((pSiSEnt->DisableDual) || (pSiSEnt->ErrorAfterFirst)) { 326772b676d7Smrg SISErrorLog(pScrn, "First head encountered fatal error, aborting...\n"); 326872b676d7Smrg goto my_error_0; 326972b676d7Smrg } 327072b676d7Smrg } 327172b676d7Smrg#endif 327272b676d7Smrg 327372b676d7Smrg /* Find the PCI info for this screen */ 327472b676d7Smrg pSiS->PciInfo = xf86GetPciInfoForEntity(pSiS->pEnt->index); 32751fd23544Smrg pSiS->PciBus = PCI_CFG_BUS(pSiS->PciInfo); /*SIS_PCI_BUS(pSiS->PciInfo);*/ 32761fd23544Smrg pSiS->PciDevice = PCI_CFG_DEV(pSiS->PciInfo); /*SIS_PCI_DEVICE(pSiS->PciInfo);*/ 32771fd23544Smrg pSiS->PciFunc = PCI_CFG_FUNC(pSiS->PciInfo); /*SIS_PCI_FUNC(pSiS->PciInfo);*/ 32781fd23544Smrg 32791fd23544Smrg pSiS->PciTag = pciTag(PCI_DEV_BUS(pSiS->PciInfo), 32801fd23544Smrg PCI_DEV_DEV(pSiS->PciInfo), 32811fd23544Smrg PCI_DEV_FUNC(pSiS->PciInfo)); 328272b676d7Smrg 328372b676d7Smrg#ifdef SIS_NEED_MAP_IOP 328472b676d7Smrg /********************************************/ 328572b676d7Smrg /* THIS IS BROKEN AND WON'T WORK */ 328672b676d7Smrg /* Reasons: */ 328772b676d7Smrg /* 1) MIPS and ARM have no i/o ports but */ 328872b676d7Smrg /* use memory mapped i/o only. The inX/outX */ 328972b676d7Smrg /* macros in compiler.h are smart enough to */ 329072b676d7Smrg /* add "IOPortBase" to the port number, but */ 329172b676d7Smrg /* "IOPortBase" is never initialized. */ 329272b676d7Smrg /* 2) IOPortBase is declared in compiler.h */ 329372b676d7Smrg /* itself. So until somebody fixes all */ 329472b676d7Smrg /* modules that #include compiler.h to set */ 329572b676d7Smrg /* IOPortBase, vga support for MIPS and ARM */ 329672b676d7Smrg /* is unusable. */ 329772b676d7Smrg /* (In this driver this is solvable because */ 329872b676d7Smrg /* we have our own vgaHW routines. However, */ 329972b676d7Smrg /* we use /dev/port for now instead.) */ 330072b676d7Smrg /********************************************/ 330172b676d7Smrg pSiS->IOPAddress = pSiS->IODBase + pSiS->PciInfo->ioBase[2]; 330272b676d7Smrg if(!SISMapIOPMem(pScrn)) { 330372b676d7Smrg SISErrorLog(pScrn, "Could not map I/O port area at 0x%x\n", pSiS->IOPAddress); 330472b676d7Smrg goto my_error_0; 330572b676d7Smrg } else { 330672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I/O port area mapped to %p, size 128\n", pSiS->IOPBase); 330772b676d7Smrg#if defined(__mips__) || defined(__arm32__) 330872b676d7Smrg /* inX/outX macros on these use IOPortBase as offset */ 330972b676d7Smrg /* This is entirely skrewed. */ 331072b676d7Smrg IOPortBase = (unsigned int)pSiS->IOPBase; 331172b676d7Smrg#endif 331272b676d7Smrg } 331372b676d7Smrg#endif 331472b676d7Smrg 331572b676d7Smrg /* Set up i/o port access (for non-x86) */ 331672b676d7Smrg#ifdef SISUSEDEVPORT 331772b676d7Smrg if((sisdevport = open("/dev/port", O_RDWR, 0)) == -1) { 331872b676d7Smrg SISErrorLog(pScrn, "Failed to open /dev/port for read/write\n"); 331972b676d7Smrg goto my_error_0; 332072b676d7Smrg } 332172b676d7Smrg pSiS->sisdevportopen = TRUE; 332272b676d7Smrg#endif 332372b676d7Smrg 332472b676d7Smrg /* 332572b676d7Smrg * Set the Chipset and ChipRev, allowing config file entries to 332672b676d7Smrg * override. DANGEROUS! 332772b676d7Smrg */ 332872b676d7Smrg { 332972b676d7Smrg SymTabRec *myChipsets = SISChipsets; 333072b676d7Smrg 33311fd23544Smrg if(PCI_DEV_VENDOR_ID(pSiS->PciInfo) == PCI_VENDOR_XGI) { 333272b676d7Smrg myChipsets = XGIChipsets; 333372b676d7Smrg } 333472b676d7Smrg 333572b676d7Smrg if(pSiS->pEnt->device->chipset && *pSiS->pEnt->device->chipset) { 333672b676d7Smrg 333772b676d7Smrg pScrn->chipset = pSiS->pEnt->device->chipset; 333872b676d7Smrg pSiS->Chipset = xf86StringToToken(myChipsets, pScrn->chipset); 333972b676d7Smrg 334072b676d7Smrg } else if(pSiS->pEnt->device->chipID >= 0) { 334172b676d7Smrg 334272b676d7Smrg pSiS->Chipset = pSiS->pEnt->device->chipID; 334372b676d7Smrg pScrn->chipset = (char *)xf86TokenToString(myChipsets, pSiS->Chipset); 334472b676d7Smrg 334572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", 334672b676d7Smrg pSiS->Chipset); 334772b676d7Smrg } else { 334872b676d7Smrg 33491fd23544Smrg pSiS->Chipset = PCI_DEV_DEVICE_ID(pSiS->PciInfo); 335072b676d7Smrg pScrn->chipset = (char *)xf86TokenToString(myChipsets, pSiS->Chipset); 335172b676d7Smrg 335272b676d7Smrg } 335372b676d7Smrg } 335472b676d7Smrg 335572b676d7Smrg if(pSiS->pEnt->device->chipRev >= 0) { 335672b676d7Smrg 335772b676d7Smrg pSiS->ChipRev = pSiS->pEnt->device->chipRev; 335872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 335972b676d7Smrg pSiS->ChipRev); 336072b676d7Smrg } else { 336172b676d7Smrg 33621fd23544Smrg pSiS->ChipRev = PCI_DEV_REVISION(pSiS->PciInfo); 336372b676d7Smrg 336472b676d7Smrg } 336572b676d7Smrg 336672b676d7Smrg /* 336772b676d7Smrg * This shouldn't happen because such problems should be caught in 336872b676d7Smrg * SISProbe(), but check it just in case the user has overridden them. 336972b676d7Smrg */ 337072b676d7Smrg if(pScrn->chipset == NULL) { 337172b676d7Smrg SISErrorLog(pScrn, "ChipID 0x%04X is not recognised\n", pSiS->Chipset); 337272b676d7Smrg goto my_error_0; 337372b676d7Smrg } 337472b676d7Smrg if(pSiS->Chipset < 0) { 337572b676d7Smrg SISErrorLog(pScrn, "Chipset \"%s\" is not recognised\n", pScrn->chipset); 337672b676d7Smrg goto my_error_0; 337772b676d7Smrg } 337872b676d7Smrg 337972b676d7Smrg pSiS->SiS6326Flags = 0; 338072b676d7Smrg 338172b676d7Smrg /* Determine VGA engine generation */ 338272b676d7Smrg switch(pSiS->Chipset) { 338372b676d7Smrg case PCI_CHIP_SIS300: 338472b676d7Smrg case PCI_CHIP_SIS540: 338572b676d7Smrg case PCI_CHIP_SIS630: /* 630 + 730 */ 338672b676d7Smrg pSiS->VGAEngine = SIS_300_VGA; 338772b676d7Smrg break; 338872b676d7Smrg case PCI_CHIP_SIS315H: 338972b676d7Smrg case PCI_CHIP_SIS315: 339072b676d7Smrg case PCI_CHIP_SIS315PRO: 339172b676d7Smrg case PCI_CHIP_SIS550: 339272b676d7Smrg case PCI_CHIP_SIS650: /* 650 + 740 */ 339372b676d7Smrg case PCI_CHIP_SIS330: 339472b676d7Smrg case PCI_CHIP_SIS660: /* 660, 661, 741, 760, 761, 670(?), 770 */ 339572b676d7Smrg case PCI_CHIP_SIS340: 339672b676d7Smrg case PCI_CHIP_XGIXG20: 339772b676d7Smrg case PCI_CHIP_XGIXG40: 339872b676d7Smrg pSiS->VGAEngine = SIS_315_VGA; 339972b676d7Smrg break; 340072b676d7Smrg case PCI_CHIP_SIS530: 340172b676d7Smrg pSiS->VGAEngine = SIS_530_VGA; 340272b676d7Smrg break; 340372b676d7Smrg case PCI_CHIP_SIS6326: 340472b676d7Smrg /* Determine SiS6326 revision. According to SiS the differences are: 340572b676d7Smrg * Chip name Chip type TV-Out MPEG II decoder 340672b676d7Smrg * 6326 AGP Rev. G0/H0 no no 340772b676d7Smrg * 6326 DVD Rev. D2 yes yes 340872b676d7Smrg * 6326 Rev. Cx yes yes 340972b676d7Smrg */ 341072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 341172b676d7Smrg "Chipset is SiS6326 %s (revision 0x%02x)\n", 341272b676d7Smrg (pSiS->ChipRev == 0xaf) ? "(Ax)" : 341372b676d7Smrg ((pSiS->ChipRev == 0x0a) ? "AGP (G0)" : 341472b676d7Smrg ((pSiS->ChipRev == 0x0b) ? "AGP (H0)" : 341572b676d7Smrg (((pSiS->ChipRev & 0xf0) == 0xd0) ? "DVD (Dx/H0)" : 341672b676d7Smrg (((pSiS->ChipRev & 0xf0) == 0x90) ? "(9x)" : 341772b676d7Smrg (((pSiS->ChipRev & 0xf0) == 0xc0) ? "(Cx)" : 341872b676d7Smrg "(unknown)"))))), 341972b676d7Smrg pSiS->ChipRev); 342072b676d7Smrg if((pSiS->ChipRev != 0x0a) && (pSiS->ChipRev != 0x0b)) { 342172b676d7Smrg pSiS->SiS6326Flags |= SIS6326_HASTV; 342272b676d7Smrg } 342372b676d7Smrg /* fall through */ 342472b676d7Smrg default: 342572b676d7Smrg pSiS->VGAEngine = SIS_OLD_VGA; 342672b676d7Smrg } 342772b676d7Smrg 342872b676d7Smrg /* We don't know about the current mode yet */ 342972b676d7Smrg pSiS->OldMode = 0; 343072b676d7Smrg 343172b676d7Smrg /* Determine whether this is the primary or a secondary 343272b676d7Smrg * display adapter. And right here the problem starts: 343372b676d7Smrg * On machines with integrated SiS chipsets, the system BIOS 343472b676d7Smrg * usually sets VGA_EN on all PCI-to-PCI bridges in the system 343572b676d7Smrg * (of which there usually are two: PCI and AGP). This and 343672b676d7Smrg * the fact that any PCI card POSTed by sisfb naturally has 343772b676d7Smrg * its PCI resources enabled, leads to X assuming that 343872b676d7Smrg * there are more than one "primary" cards in the system. 343972b676d7Smrg * In this case, X treats ALL cards as "secondary" - 344072b676d7Smrg * which by no means is desireable. If sisfb is running, 344172b676d7Smrg * we can determine which card really is "primary" (in 344272b676d7Smrg * terms of if it's the one that occupies the A0000 area 344372b676d7Smrg * etc.) in a better way (Linux 2.6.12 or later). See below. 344472b676d7Smrg */ 344572b676d7Smrg if(!(pSiS->Primary = xf86IsPrimaryPci(pSiS->PciInfo))) { 344672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 344772b676d7Smrg SISMYSERVERNAME " assumes this adapter to be secondary\n"); 344872b676d7Smrg } 344972b676d7Smrg 345072b676d7Smrg /* Now check if sisfb is running, and if so, retrieve 345172b676d7Smrg * all possible info from it. This also resets all 345272b676d7Smrg * sisfb_* entries in pSiS regardless of the chipset. 345372b676d7Smrg */ 345472b676d7Smrg SiS_CheckKernelFB(pScrn); 345572b676d7Smrg 345672b676d7Smrg /* Now for that primary/secondary mess: Linux kernel 345772b676d7Smrg * 2.6.12 and later knows what card is primary, and so 345872b676d7Smrg * does any recent version of sisfb. XFree86/X.org takes 345972b676d7Smrg * all adapters as "secondary" if more than one card's 346072b676d7Smrg * memory and i/o resources are enabled, and more than 346172b676d7Smrg * one PCI bridge in the system has VGA_EN set at server 346272b676d7Smrg * start. So, let's start thinking: What is this 346372b676d7Smrg * primary/secondary classification needed for anyway? 346472b676d7Smrg * (This list might be incomplete for the entire server 346572b676d7Smrg * infrastructure, but it's complete as regards the driver's 346672b676d7Smrg * purposes of primary/secondary classification.) 346772b676d7Smrg * 1) VGA/console font restoring: Here it's irrelevant 346872b676d7Smrg * whether more than one card's resources are enabled 346972b676d7Smrg * at server start or not. Relevant is whether the card 347072b676d7Smrg * occupies the A0000 area at this time. Assuming (?) 347172b676d7Smrg * that this does not change during machine up-time, 347272b676d7Smrg * it suffices to know which device was the boot video 347372b676d7Smrg * device (as determined by Linux 2.6.12 and later). 347472b676d7Smrg * Also, this is only relevant if the card is in text 347572b676d7Smrg * mode; if it's in graphics mode, fonts aren't saved 347672b676d7Smrg * or restored anyway. 347772b676d7Smrg * sisfb tells us if that card is considered the boot 347872b676d7Smrg * video device. The hardware registers tell us if 347972b676d7Smrg * the card's A0000 address decoding is enabled, and if 348072b676d7Smrg * the card currently is in text mode. These three bits 348172b676d7Smrg * of information are enough to decide on whether or not 348272b676d7Smrg * to save/restore fonts. 348372b676d7Smrg * 2) POSTing. Same here. Relevant is only whether or not 348472b676d7Smrg * the card has been POSTed once before. POSTing cards 348572b676d7Smrg * on every server start is pretty ugly, especially 348672b676d7Smrg * if a framebuffer driver is already handling it. 348772b676d7Smrg * SiS/XGI cards POSTed by sisfb can coexist well with other 348872b676d7Smrg * active adapters. So we trust sisfb's information more 348972b676d7Smrg * than X's (especially as we only use this information for 349072b676d7Smrg * console font restoring and eventual POSTing.) 349172b676d7Smrg * What we still need is a way to find out about all this if 349272b676d7Smrg * sisfb is not running.... 349372b676d7Smrg */ 349472b676d7Smrg if(!pSiS->Primary && pSiS->sisfbprimary) { 349572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 349672b676d7Smrg "sisfb reports this adapter to be primary. Seems more reliable.\n"); 349772b676d7Smrg pSiS->Primary = TRUE; 349872b676d7Smrg } 349972b676d7Smrg 350072b676d7Smrg /* If the card is "secondary" and has not been 350172b676d7Smrg * POSTed by sisfb, POST it now through int10. 350272b676d7Smrg * For cards POSTed by sisfb, we definitely don't 350372b676d7Smrg * want that as it messes up our set up (eg. the 350472b676d7Smrg * disabled A0000 area). 350572b676d7Smrg * The int10 module decides on its own if the 350672b676d7Smrg * card is primary or secondary. Since it uses 350772b676d7Smrg * the generic technique described above, and since 350872b676d7Smrg * for "secondary" cards it needs a real PCI BIOS 350972b676d7Smrg * ROM, and since integrated chips don't have such 351072b676d7Smrg * a PCI BIOS ROM, int10 will naturally fail to 351172b676d7Smrg * find/read the BIOS on such machines. Great. 351272b676d7Smrg * Using the integrated graphics as "secondary" 351372b676d7Smrg * (which it will be as soon as X finds more than 351472b676d7Smrg * one card's mem and i/o resources enabled, and more 351572b676d7Smrg * than one PCI bridge's VGA_EN bit set during server 351672b676d7Smrg * start) will therefore prevent us from restoring 351772b676d7Smrg * the mode using the VBE. That means real fun if 351872b676d7Smrg * the integrated chip is set up to use the video 351972b676d7Smrg * bridge output for text mode (which is something 352072b676d7Smrg * the driver doesn't really support since it's done 352172b676d7Smrg * pretty much differently on every machine.) 352272b676d7Smrg */ 352372b676d7Smrg#if !defined(__alpha__) 352472b676d7Smrg if(!pSiS->Primary) { 352572b676d7Smrg if(!pSiS->sisfbcardposted) { 352672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 352772b676d7Smrg "Initializing adapter through int10\n"); 352872b676d7Smrg if(xf86LoadSubModule(pScrn, "int10")) { 352972b676d7Smrg pSiS->pInt = xf86InitInt10(pSiS->pEnt->index); 353072b676d7Smrg } else { 353172b676d7Smrg SISErrorLog(pScrn, "Failed to load int10 module\n"); 353272b676d7Smrg } 353372b676d7Smrg } else { 353472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 353572b676d7Smrg "Adapter already initialized by sisfb\n"); 353672b676d7Smrg } 353772b676d7Smrg } 353872b676d7Smrg#endif 353972b676d7Smrg 354072b676d7Smrg /* Get the address of our relocated IO registers. 354172b676d7Smrg * These are enabled by the hardware during cold boot, and 354272b676d7Smrg * by the BIOS. So we can pretty much rely on that these 354372b676d7Smrg * are enabled. 354472b676d7Smrg */ 35451fd23544Smrg pSiS->RelIO = (SISIOADDRESS)(PCI_REGION_BASE(pSiS->PciInfo, 2, REGION_IO) + pSiS->IODBase); 354672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Relocated I/O registers at 0x%lX\n", 354772b676d7Smrg (ULong)pSiS->RelIO); 354872b676d7Smrg 354972b676d7Smrg /* Unlock extended registers */ 355072b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, &srlockReg, &crlockReg); 355172b676d7Smrg 355272b676d7Smrg /* Is a0000 memory address decoding enabled? */ 355372b676d7Smrg pSiS->VGADecodingEnabled = TRUE; 355472b676d7Smrg switch(pSiS->VGAEngine) { 355572b676d7Smrg case SIS_OLD_VGA: 355672b676d7Smrg /* n/a */ 355772b676d7Smrg break; 355872b676d7Smrg case SIS_530_VGA: 355972b676d7Smrg inSISIDXREG(SISSR, 0x3d, tempreg); 356072b676d7Smrg if(tempreg & 0x04) pSiS->VGADecodingEnabled = FALSE; 356172b676d7Smrg break; 356272b676d7Smrg case SIS_300_VGA: 356372b676d7Smrg case SIS_315_VGA: 356472b676d7Smrg inSISIDXREG(SISSR, 0x20, tempreg); 356572b676d7Smrg if(tempreg & 0x04) pSiS->VGADecodingEnabled = FALSE; 356672b676d7Smrg break; 356772b676d7Smrg } 356872b676d7Smrg 356972b676d7Smrg if(!pSiS->VGADecodingEnabled) { 357072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 357172b676d7Smrg "Standard VGA (0xA0000) memory address decoding is disabled\n"); 357272b676d7Smrg } 357372b676d7Smrg 357472b676d7Smrg#ifdef SIS_PC_PLATFORM 357572b676d7Smrg /* Map 64k VGA window for saving/restoring CGA fonts. 357672b676d7Smrg * For secondary cards or if A0000 address decoding 357772b676d7Smrg * is disabled, this will map the beginning of the 357872b676d7Smrg * linear (PCI) video RAM instead. 357972b676d7Smrg */ 358072b676d7Smrg SiS_MapVGAMem(pScrn); 358172b676d7Smrg#endif 358272b676d7Smrg 3583e47418d9Smrg#ifndef XSERVER_LIBPCIACCESS 358472b676d7Smrg /* Set operating state */ 358572b676d7Smrg 358672b676d7Smrg /* 1. memory */ 358772b676d7Smrg /* [ResUnusedOpr: Resource decoded by hw, but not used] 358872b676d7Smrg * [ResDisableOpr: Resource is not decoded by hw] 358972b676d7Smrg * So, if a0000 memory decoding is disabled, one could 359072b676d7Smrg * argue that we may say so, too. Hm. Quite likely that 359172b676d7Smrg * the VBE (via int10) will eventually enable it. So we 359272b676d7Smrg * cowardly say unused instead. 359372b676d7Smrg */ 359472b676d7Smrg xf86SetOperatingState(resVgaMem, pSiS->pEnt->index, ResUnusedOpr); 359572b676d7Smrg 359672b676d7Smrg /* 2. i/o */ 359772b676d7Smrg /* Although we only use the relocated i/o ports, the hardware 359872b676d7Smrg * also decodes the standard VGA port range. This could in 359972b676d7Smrg * theory be disabled, but I don't dare to do this; in case of 360072b676d7Smrg * a server crash, the card would be entirely dead. Also, this 360172b676d7Smrg * would prevent int10 and the VBE from working at all. Generic 360272b676d7Smrg * access control through the PCI configuration registers does 360372b676d7Smrg * nicely anyway. 360472b676d7Smrg */ 360572b676d7Smrg xf86SetOperatingState(resVgaIo, pSiS->pEnt->index, ResUnusedOpr); 360672b676d7Smrg 360772b676d7Smrg /* Operations for which memory access is required */ 360872b676d7Smrg pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; 360972b676d7Smrg 361072b676d7Smrg /* Operations for which I/O access is required */ 361172b676d7Smrg pScrn->racIoFlags = RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; 361272b676d7Smrg 3613e47418d9Smrg#endif 3614e47418d9Smrg 361572b676d7Smrg /* Load ramdac module */ 361672b676d7Smrg if(!xf86LoadSubModule(pScrn, "ramdac")) { 361772b676d7Smrg SISErrorLog(pScrn, "Could not load ramdac module\n"); 361872b676d7Smrg goto my_error_1; 361972b676d7Smrg } 362072b676d7Smrg 362172b676d7Smrg /* Set pScrn->monitor */ 362272b676d7Smrg pScrn->monitor = pScrn->confScreen->monitor; 362372b676d7Smrg 362472b676d7Smrg /* Reset some entries */ 362572b676d7Smrg pSiS->SiSFastVidCopy = SiSVidCopyGetDefault(); 362672b676d7Smrg pSiS->SiSFastMemCopy = SiSVidCopyGetDefault(); 362772b676d7Smrg pSiS->SiSFastVidCopyFrom = SiSVidCopyGetDefault(); 362872b676d7Smrg pSiS->SiSFastMemCopyFrom = SiSVidCopyGetDefault(); 362972b676d7Smrg pSiS->SiSFastVidCopyDone = FALSE; 363072b676d7Smrg#ifdef SIS_USE_XAA 363172b676d7Smrg pSiS->RenderCallback = NULL; 363272b676d7Smrg#endif 363372b676d7Smrg#ifdef SIS_USE_EXA 363472b676d7Smrg pSiS->ExaRenderCallback = NULL; 363572b676d7Smrg#endif 363672b676d7Smrg pSiS->InitAccel = SiSPseudo; 363772b676d7Smrg pSiS->SyncAccel = SiSPseudo; 363872b676d7Smrg pSiS->FillRect = NULL; 363972b676d7Smrg pSiS->BlitRect = NULL; 364072b676d7Smrg 364172b676d7Smrg /* Always do a ValidMode() inside Switchmode() */ 364272b676d7Smrg pSiS->skipswitchcheck = FALSE; 364372b676d7Smrg 364472b676d7Smrg /* Determine chipset and its capabilities in detail */ 364572b676d7Smrg pSiS->ChipFlags = 0; 364672b676d7Smrg pSiS->SiS_SD_Flags = pSiS->SiS_SD2_Flags = 0; 364772b676d7Smrg pSiS->SiS_SD3_Flags = pSiS->SiS_SD4_Flags = 0; 364872b676d7Smrg pSiS->HWCursorMBufNum = pSiS->HWCursorCBufNum = 0; 364972b676d7Smrg pSiS->NeedFlush = FALSE; 365072b676d7Smrg pSiS->NewCRLayout = FALSE; 365172b676d7Smrg pSiS->mmioSize = 64; 365272b676d7Smrg 365372b676d7Smrg switch(pSiS->Chipset) { 365472b676d7Smrg case PCI_CHIP_SIS530: 365572b676d7Smrg pSiS->ChipType = SIS_530; 365672b676d7Smrg break; 365772b676d7Smrg case PCI_CHIP_SIS300: 365872b676d7Smrg pSiS->ChipType = SIS_300; 365972b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_IS300SERIES; 366072b676d7Smrg break; 366172b676d7Smrg case PCI_CHIP_SIS540: 366272b676d7Smrg pSiS->ChipType = SIS_540; 366372b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_IS300SERIES; 366472b676d7Smrg break; 366572b676d7Smrg case PCI_CHIP_SIS630: /* 630 + 730 */ 366672b676d7Smrg pSiS->ChipType = SIS_630; 36671fd23544Smrg if(sis_pci_read_host_bridge_u32(0x00) == 0x07301039) { 366872b676d7Smrg pSiS->ChipType = SIS_730; 366972b676d7Smrg } 367072b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_IS300SERIES; 367172b676d7Smrg break; 367272b676d7Smrg case PCI_CHIP_SIS315H: 367372b676d7Smrg pSiS->ChipType = SIS_315H; 367472b676d7Smrg pSiS->ChipFlags |= (SiSCF_315Core | SiSCF_MMIOPalette); 367572b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 367672b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 367772b676d7Smrg pSiS->myCR63 = 0x63; 367872b676d7Smrg break; 367972b676d7Smrg case PCI_CHIP_SIS315: 368072b676d7Smrg /* Override for simplicity */ 368172b676d7Smrg pSiS->Chipset = PCI_CHIP_SIS315H; 368272b676d7Smrg pSiS->ChipType = SIS_315; 368372b676d7Smrg pSiS->ChipFlags |= (SiSCF_315Core | SiSCF_MMIOPalette); 368472b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 368572b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 368672b676d7Smrg pSiS->myCR63 = 0x63; 368772b676d7Smrg break; 368872b676d7Smrg case PCI_CHIP_SIS315PRO: 368972b676d7Smrg /* Override for simplicity */ 369072b676d7Smrg pSiS->Chipset = PCI_CHIP_SIS315H; 369172b676d7Smrg pSiS->ChipType = SIS_315PRO; 369272b676d7Smrg pSiS->ChipFlags |= (SiSCF_315Core | SiSCF_MMIOPalette); 369372b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 369472b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 369572b676d7Smrg pSiS->myCR63 = 0x63; 369672b676d7Smrg break; 369772b676d7Smrg case PCI_CHIP_SIS550: 369872b676d7Smrg pSiS->ChipType = SIS_550; 369972b676d7Smrg pSiS->ChipFlags |= (SiSCF_Integrated | SiSCF_MMIOPalette); 370072b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 370172b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 370272b676d7Smrg pSiS->myCR63 = 0x63; 370372b676d7Smrg break; 370472b676d7Smrg case PCI_CHIP_SIS650: /* 650 + 740 */ 370572b676d7Smrg pSiS->ChipType = SIS_650; 37061fd23544Smrg if(sis_pci_read_host_bridge_u32(0x00) == 0x07401039) { 370772b676d7Smrg pSiS->ChipType = SIS_740; 370872b676d7Smrg } 370972b676d7Smrg pSiS->ChipFlags |= (SiSCF_Integrated | SiSCF_Real256ECore | SiSCF_MMIOPalette); 371072b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_IS315SERIES; 371172b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 371272b676d7Smrg pSiS->myCR63 = 0x63; 371372b676d7Smrg break; 371472b676d7Smrg case PCI_CHIP_SIS330: 371572b676d7Smrg pSiS->ChipType = SIS_330; 371672b676d7Smrg pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette); 371772b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_IS330SERIES; 371872b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 371972b676d7Smrg pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; /* FIXME ? */ 372072b676d7Smrg pSiS->myCR63 = 0x53; /* sic! */ 372172b676d7Smrg break; 372272b676d7Smrg case PCI_CHIP_SIS660: /* 660, 661, 741, 760, 761, 670(?) */ 372372b676d7Smrg { 37241fd23544Smrg ULong hpciid = sis_pci_read_host_bridge_u32(0x00); 372572b676d7Smrg switch(hpciid) { 372672b676d7Smrg case 0x06601039: 372772b676d7Smrg pSiS->ChipType = SIS_660; 372872b676d7Smrg pSiS->ChipFlags |= SiSCF_Ultra256Core; 372972b676d7Smrg pSiS->NeedFlush = TRUE; 373072b676d7Smrg break; 373172b676d7Smrg case 0x07601039: 373272b676d7Smrg pSiS->ChipType = SIS_760; 373372b676d7Smrg pSiS->ChipFlags |= SiSCF_Ultra256Core; 373472b676d7Smrg pSiS->NeedFlush = TRUE; 373572b676d7Smrg break; 373672b676d7Smrg case 0x07611039: 373772b676d7Smrg pSiS->ChipType = SIS_761; 373872b676d7Smrg pSiS->ChipFlags |= SiSCF_Ultra256Core; 373972b676d7Smrg pSiS->NeedFlush = TRUE; 374072b676d7Smrg break; 374172b676d7Smrg case 0x07701039: 374272b676d7Smrg pSiS->ChipType = SIS_770; 374372b676d7Smrg pSiS->ChipFlags |= SiSCF_Ultra256Core; 374472b676d7Smrg pSiS->NeedFlush = TRUE; 374572b676d7Smrg break; 374672b676d7Smrg case 0x07411039: 374772b676d7Smrg pSiS->ChipType = SIS_741; 374872b676d7Smrg pSiS->ChipFlags |= SiSCF_Real256ECore; 374972b676d7Smrg break; 375072b676d7Smrg case 0x06611039: 375172b676d7Smrg default: 375272b676d7Smrg pSiS->ChipType = SIS_661; 375372b676d7Smrg pSiS->ChipFlags |= SiSCF_Real256ECore; 375472b676d7Smrg break; 375572b676d7Smrg case 0x06701039: 375672b676d7Smrg pSiS->ChipType = SIS_670; 375772b676d7Smrg pSiS->ChipFlags |= SiSCF_Real256ECore; 375872b676d7Smrg } 375972b676d7Smrg /* Detection could also be done by CR5C & 0xf8: 376072b676d7Smrg * 0x10 = 661 (CR5F & 0xc0: 0x00 both A0 and A1) 376172b676d7Smrg * 0x80 = 760 (CR5F & 0xc0: 0x00 A0, 0x40 A1) 376272b676d7Smrg * 0x90 = 741 (CR5F & 0xc0: 0x00 A0,A1 0x40 A2) 376372b676d7Smrg * other: 660 (CR5F & 0xc0: 0x00 A0 0x40 A1) (DOA?) 376472b676d7Smrg */ 376572b676d7Smrg pSiS->ChipFlags |= (SiSCF_Integrated | SiSCF_MMIOPalette); 376672b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_IS330SERIES; 376772b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 376872b676d7Smrg pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; 376972b676d7Smrg pSiS->myCR63 = 0x53; /* sic! */ 377072b676d7Smrg pSiS->NewCRLayout = TRUE; 377172b676d7Smrg } 377272b676d7Smrg break; 377372b676d7Smrg case PCI_CHIP_SIS340: 377472b676d7Smrg pSiS->ChipType = SIS_340; 377572b676d7Smrg pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette); 377672b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_IS340SERIES; 377772b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORTXVHUESAT; 377872b676d7Smrg pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; 377972b676d7Smrg pSiS->myCR63 = 0x53; 378072b676d7Smrg pSiS->NewCRLayout = TRUE; 378172b676d7Smrg break; 378272b676d7Smrg case PCI_CHIP_XGIXG20: 378372b676d7Smrg pSiS->ChipType = XGI_20; 378472b676d7Smrg pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette | SiSCF_IsXGI); 378572b676d7Smrg pSiS->SiS_SD2_Flags |= (SiS_SD2_NOOVERLAY | SiS_SD2_ISXGI); 378672b676d7Smrg pSiS->myCR63 = 0x53; 378772b676d7Smrg pSiS->NewCRLayout = TRUE; 378872b676d7Smrg break; 378972b676d7Smrg case PCI_CHIP_XGIXG40: 379072b676d7Smrg pSiS->ChipType = XGI_40; 379172b676d7Smrg pSiS->ChipFlags |= (SiSCF_XabreCore | SiSCF_MMIOPalette | SiSCF_IsXGI); 379272b676d7Smrg pSiS->SiS_SD2_Flags |= (SiS_SD2_SUPPORTXVHUESAT | SiS_SD2_ISXGI); 379372b676d7Smrg pSiS->SiS_SD3_Flags |= SiS_SD3_CRT1SATGAIN; 379472b676d7Smrg pSiS->myCR63 = 0x53; 379572b676d7Smrg pSiS->NewCRLayout = TRUE; 379672b676d7Smrg if(pSiS->ChipRev == 2) pSiS->ChipFlags |= SiSCF_IsXGIV3; 379772b676d7Smrg break; 379872b676d7Smrg default: 379972b676d7Smrg pSiS->ChipType = SIS_OLD; 380072b676d7Smrg break; 380172b676d7Smrg } 380272b676d7Smrg 380372b676d7Smrg /* 380472b676d7Smrg * Now back to real business: Figure out the depth, bpp, etc. 380572b676d7Smrg * Set SupportConvert... flags since we use the fb layer which 380672b676d7Smrg * supports this conversion. (24to32 seems not implemented though) 380772b676d7Smrg * Additionally, determine the size of the HWCursor memory area. 380872b676d7Smrg */ 380972b676d7Smrg switch(pSiS->VGAEngine) { 381072b676d7Smrg case SIS_300_VGA: 381172b676d7Smrg pSiS->CursorSize = 4096; 381272b676d7Smrg pix24flags = Support32bppFb; 381372b676d7Smrg break; 381472b676d7Smrg case SIS_315_VGA: 381572b676d7Smrg pSiS->CursorSize = 16384; 381672b676d7Smrg pix24flags = Support32bppFb; 381772b676d7Smrg break; 381872b676d7Smrg case SIS_530_VGA: 381972b676d7Smrg pSiS->CursorSize = 2048; 382072b676d7Smrg pix24flags = Support32bppFb | 382172b676d7Smrg Support24bppFb | 382272b676d7Smrg SupportConvert32to24; 382372b676d7Smrg break; 382472b676d7Smrg default: 382572b676d7Smrg pSiS->CursorSize = 2048; 382672b676d7Smrg pix24flags = Support24bppFb | 382772b676d7Smrg SupportConvert32to24 | 382872b676d7Smrg PreferConvert32to24; 382972b676d7Smrg break; 383072b676d7Smrg } 383172b676d7Smrg 383272b676d7Smrg#ifdef SISDUALHEAD 383372b676d7Smrg /* In case of Dual Head, we need to determine if we are the "master" head or 383472b676d7Smrg * the "slave" head. In order to do that, we set PrimInit to DONE in the 383572b676d7Smrg * shared entity at the end of the first initialization. The second 383672b676d7Smrg * initialization then knows that some things have already been done. THIS 383772b676d7Smrg * ALWAYS ASSUMES THAT THE FIRST DEVICE INITIALIZED IS THE MASTER! 383872b676d7Smrg */ 383972b676d7Smrg if(xf86IsEntityShared(pScrn->entityList[0])) { 384072b676d7Smrg if(pSiSEnt->lastInstance > 0) { 384172b676d7Smrg if(!xf86IsPrimInitDone(pScrn->entityList[0])) { 384272b676d7Smrg /* First Head (always CRT2) */ 384372b676d7Smrg pSiS->SecondHead = FALSE; 384472b676d7Smrg pSiSEnt->pScrn_1 = pScrn; 384572b676d7Smrg pSiSEnt->CRT1ModeNo = pSiSEnt->CRT2ModeNo = -1; 384672b676d7Smrg pSiSEnt->CRT2ModeSet = FALSE; 384772b676d7Smrg pSiS->DualHeadMode = TRUE; 384872b676d7Smrg pSiSEnt->DisableDual = FALSE; 384972b676d7Smrg pSiSEnt->BIOS = NULL; 385072b676d7Smrg pSiSEnt->ROM661New = FALSE; 385172b676d7Smrg pSiSEnt->HaveXGIBIOS = FALSE; 385272b676d7Smrg pSiSEnt->SiS_Pr = NULL; 385372b676d7Smrg pSiSEnt->RenderAccelArray = NULL; 385472b676d7Smrg pSiSEnt->SiSFastVidCopy = pSiSEnt->SiSFastMemCopy = NULL; 385572b676d7Smrg pSiSEnt->SiSFastVidCopyFrom = pSiSEnt->SiSFastMemCopyFrom = NULL; 385672b676d7Smrg } else { 385772b676d7Smrg /* Second Head (always CRT1) */ 385872b676d7Smrg pSiS->SecondHead = TRUE; 385972b676d7Smrg pSiSEnt->pScrn_2 = pScrn; 386072b676d7Smrg pSiS->DualHeadMode = TRUE; 386172b676d7Smrg } 386272b676d7Smrg } else { 386372b676d7Smrg /* Only one screen in config file - disable dual head mode */ 386472b676d7Smrg pSiS->SecondHead = FALSE; 386572b676d7Smrg pSiS->DualHeadMode = FALSE; 386672b676d7Smrg pSiSEnt->DisableDual = TRUE; 386772b676d7Smrg } 386872b676d7Smrg } else { 386972b676d7Smrg /* Entity is not shared - disable dual head mode */ 387072b676d7Smrg pSiS->SecondHead = FALSE; 387172b676d7Smrg pSiS->DualHeadMode = FALSE; 387272b676d7Smrg } 387372b676d7Smrg#endif 387472b676d7Smrg 387572b676d7Smrg /* Save the name of our Device section for SiSCtrl usage */ 387672b676d7Smrg { 387772b676d7Smrg int ttt = 0; 387872b676d7Smrg GDevPtr device = xf86GetDevFromEntity(pScrn->entityList[0], 387972b676d7Smrg pScrn->entityInstanceList[0]); 388072b676d7Smrg if(device && device->identifier) { 388172b676d7Smrg if((ttt = strlen(device->identifier)) > 31) ttt = 31; 388272b676d7Smrg strncpy(&pSiS->devsectname[0], device->identifier, 31); 388372b676d7Smrg } 388472b676d7Smrg pSiS->devsectname[ttt] = 0; 388572b676d7Smrg } 388672b676d7Smrg 388772b676d7Smrg pSiS->ForceCursorOff = FALSE; 388872b676d7Smrg 388972b676d7Smrg /* Allocate SiS_Private (for mode switching code) and initialize it */ 389072b676d7Smrg pSiS->SiS_Pr = NULL; 389172b676d7Smrg#ifdef SISDUALHEAD 389272b676d7Smrg if(pSiSEnt) { 389372b676d7Smrg if(pSiSEnt->SiS_Pr) pSiS->SiS_Pr = pSiSEnt->SiS_Pr; 389472b676d7Smrg } 389572b676d7Smrg#endif 389672b676d7Smrg if(!pSiS->SiS_Pr) { 389772b676d7Smrg if(!(pSiS->SiS_Pr = xnfcalloc(sizeof(struct SiS_Private), 1))) { 389872b676d7Smrg SISErrorLog(pScrn, "Could not allocate memory for SiS_Pr structure\n"); 389972b676d7Smrg goto my_error_1; 390072b676d7Smrg } 390172b676d7Smrg#ifdef SISDUALHEAD 390272b676d7Smrg if(pSiSEnt) pSiSEnt->SiS_Pr = pSiS->SiS_Pr; 390372b676d7Smrg#endif 390472b676d7Smrg memset(pSiS->SiS_Pr, 0, sizeof(struct SiS_Private)); 390572b676d7Smrg pSiS->SiS_Pr->PciTag = pSiS->PciTag; 390672b676d7Smrg pSiS->SiS_Pr->ChipType = pSiS->ChipType; 390772b676d7Smrg pSiS->SiS_Pr->ChipRevision = pSiS->ChipRev; 390872b676d7Smrg pSiS->SiS_Pr->SiS_Backup70xx = 0xff; 390972b676d7Smrg pSiS->SiS_Pr->SiS_CHOverScan = -1; 391072b676d7Smrg pSiS->SiS_Pr->SiS_ChSW = FALSE; 391172b676d7Smrg pSiS->SiS_Pr->SiS_CustomT = CUT_NONE; 391272b676d7Smrg pSiS->SiS_Pr->SiS_UseWide = -1; 391372b676d7Smrg pSiS->SiS_Pr->SiS_UseWideCRT2 = -1; 391472b676d7Smrg pSiS->SiS_Pr->SiS_TVBlue = -1; 391572b676d7Smrg pSiS->SiS_Pr->PanelSelfDetected = FALSE; 391672b676d7Smrg pSiS->SiS_Pr->UsePanelScaler = -1; 391772b676d7Smrg pSiS->SiS_Pr->CenterScreen = -1; 391872b676d7Smrg pSiS->SiS_Pr->CRT1UsesCustomMode = FALSE; 391972b676d7Smrg pSiS->SiS_Pr->PDC = pSiS->SiS_Pr->PDCA = -1; 392072b676d7Smrg pSiS->SiS_Pr->LVDSHL = -1; 392172b676d7Smrg pSiS->SiS_Pr->HaveEMI = FALSE; 392272b676d7Smrg pSiS->SiS_Pr->HaveEMILCD = FALSE; 392372b676d7Smrg pSiS->SiS_Pr->OverruleEMI = FALSE; 392472b676d7Smrg pSiS->SiS_Pr->SiS_SensibleSR11 = FALSE; 392572b676d7Smrg if(pSiS->ChipType >= SIS_661) { 392672b676d7Smrg pSiS->SiS_Pr->SiS_SensibleSR11 = TRUE; 392772b676d7Smrg } 392872b676d7Smrg pSiS->SiS_Pr->SiS_MyCR63 = pSiS->myCR63; 392972b676d7Smrg pSiS->SiS_Pr->DDCPortMixup = FALSE; 393072b676d7Smrg } 393172b676d7Smrg 393272b676d7Smrg /* Copy IO address to SiS_Pr and init the structure for 393372b676d7Smrg * routines inside init.c/init301.c 393472b676d7Smrg */ 393572b676d7Smrg pSiS->SiS_Pr->IOAddress = (SISIOADDRESS)(pSiS->RelIO + 0x30); 393672b676d7Smrg SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO + 0x30); 393772b676d7Smrg 393872b676d7Smrg /* The following identifies the old chipsets. This is only 393972b676d7Smrg * partly used since the really old chips are not supported, 394072b676d7Smrg * but I keep it here for future use. 394172b676d7Smrg * 205, 215 and 225 are to be treated the same way, 201 and 202 394272b676d7Smrg * are different. 394372b676d7Smrg */ 394472b676d7Smrg if(pSiS->VGAEngine == SIS_OLD_VGA || pSiS->VGAEngine == SIS_530_VGA) { 394572b676d7Smrg switch(pSiS->Chipset) { 394672b676d7Smrg case PCI_CHIP_SG86C201: 394772b676d7Smrg pSiS->oldChipset = OC_SIS86201; break; 394872b676d7Smrg case PCI_CHIP_SG86C202: 394972b676d7Smrg pSiS->oldChipset = OC_SIS86202; break; 395072b676d7Smrg case PCI_CHIP_SG86C205: 395172b676d7Smrg inSISIDXREG(SISSR, 0x10, tempreg); 395272b676d7Smrg if(tempreg & 0x80) pSiS->oldChipset = OC_SIS6205B; 395372b676d7Smrg else pSiS->oldChipset = (pSiS->ChipRev == 0x11) ? 395472b676d7Smrg OC_SIS6205C : OC_SIS6205A; 395572b676d7Smrg break; 395672b676d7Smrg case PCI_CHIP_SIS82C204: 395772b676d7Smrg pSiS->oldChipset = OC_SIS82204; break; 395872b676d7Smrg case 0x6225: 395972b676d7Smrg pSiS->oldChipset = OC_SIS6225; break; 396072b676d7Smrg case PCI_CHIP_SIS5597: 396172b676d7Smrg pSiS->oldChipset = OC_SIS5597; break; 396272b676d7Smrg case PCI_CHIP_SIS6326: 396372b676d7Smrg pSiS->oldChipset = OC_SIS6326; break; 396472b676d7Smrg case PCI_CHIP_SIS530: 39651fd23544Smrg if(sis_pci_read_host_bridge_u32(0x00) == 0x06201039) { 396672b676d7Smrg pSiS->oldChipset = OC_SIS620; 396772b676d7Smrg } else { 396872b676d7Smrg if((pSiS->ChipRev & 0x0f) < 0x0a) 396972b676d7Smrg pSiS->oldChipset = OC_SIS530A; 397072b676d7Smrg else pSiS->oldChipset = OC_SIS530B; 397172b676d7Smrg } 397272b676d7Smrg break; 397372b676d7Smrg default: 397472b676d7Smrg pSiS->oldChipset = OC_UNKNOWN; 397572b676d7Smrg } 397672b676d7Smrg } 397772b676d7Smrg 397872b676d7Smrg if(!xf86SetDepthBpp(pScrn, 0, 0, 0, pix24flags)) { 397972b676d7Smrg SISErrorLog(pScrn, "xf86SetDepthBpp() error\n"); 398072b676d7Smrg goto my_error_1; 398172b676d7Smrg } 398272b676d7Smrg 398372b676d7Smrg /* Check that the returned depth is one we support */ 398472b676d7Smrg temp = 0; 398572b676d7Smrg switch(pScrn->depth) { 398672b676d7Smrg case 8: 398772b676d7Smrg case 16: 398872b676d7Smrg case 24: 398972b676d7Smrg break; 399072b676d7Smrg case 15: 399172b676d7Smrg if((pSiS->VGAEngine == SIS_300_VGA) || 399272b676d7Smrg (pSiS->VGAEngine == SIS_315_VGA)) { 399372b676d7Smrg temp = 1; 399472b676d7Smrg } 399572b676d7Smrg break; 399672b676d7Smrg default: 399772b676d7Smrg temp = 1; 399872b676d7Smrg } 399972b676d7Smrg 400072b676d7Smrg if(temp) { 400172b676d7Smrg SISErrorLog(pScrn, 400272b676d7Smrg "Given color depth (%d) is not supported by this driver/chipset\n", 400372b676d7Smrg pScrn->depth); 400472b676d7Smrg goto my_error_1; 400572b676d7Smrg } 400672b676d7Smrg 400772b676d7Smrg xf86PrintDepthBpp(pScrn); 400872b676d7Smrg 400972b676d7Smrg if( (((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) && 401072b676d7Smrg (pScrn->bitsPerPixel == 24)) || 401172b676d7Smrg ((pSiS->VGAEngine == SIS_OLD_VGA) && (pScrn->bitsPerPixel == 32)) ) { 401272b676d7Smrg SISErrorLog(pScrn, 401372b676d7Smrg "Framebuffer bpp %d not supported for this chipset\n", pScrn->bitsPerPixel); 401472b676d7Smrg goto my_error_1; 401572b676d7Smrg } 401672b676d7Smrg 401772b676d7Smrg /* Get the depth24 pixmap format */ 401872b676d7Smrg if(pScrn->depth == 24 && pix24bpp == 0) { 401972b676d7Smrg pix24bpp = xf86GetBppFromDepth(pScrn, 24); 402072b676d7Smrg } 402172b676d7Smrg 402272b676d7Smrg /* 402372b676d7Smrg * This must happen after pScrn->display has been set because 402472b676d7Smrg * xf86SetWeight references it. 402572b676d7Smrg */ 402672b676d7Smrg if(pScrn->depth > 8) { 402772b676d7Smrg /* The defaults are OK for us */ 402872b676d7Smrg rgb zeros = {0, 0, 0}; 402972b676d7Smrg 403072b676d7Smrg if(!xf86SetWeight(pScrn, zeros, zeros)) { 403172b676d7Smrg SISErrorLog(pScrn, "xf86SetWeight() error\n"); 403272b676d7Smrg goto my_error_1; 403372b676d7Smrg } else { 403472b676d7Smrg Bool ret = FALSE; 403572b676d7Smrg switch(pScrn->depth) { 403672b676d7Smrg case 15: 403772b676d7Smrg if((pScrn->weight.red != 5) || 403872b676d7Smrg (pScrn->weight.green != 5) || 403972b676d7Smrg (pScrn->weight.blue != 5)) ret = TRUE; 404072b676d7Smrg break; 404172b676d7Smrg case 16: 404272b676d7Smrg if((pScrn->weight.red != 5) || 404372b676d7Smrg (pScrn->weight.green != 6) || 404472b676d7Smrg (pScrn->weight.blue != 5)) ret = TRUE; 404572b676d7Smrg break; 404672b676d7Smrg case 24: 404772b676d7Smrg if((pScrn->weight.red != 8) || 404872b676d7Smrg (pScrn->weight.green != 8) || 404972b676d7Smrg (pScrn->weight.blue != 8)) ret = TRUE; 405072b676d7Smrg break; 405172b676d7Smrg } 405272b676d7Smrg if(ret) { 405372b676d7Smrg SISErrorLog(pScrn, 405472b676d7Smrg "RGB weight %d%d%d at depth %d not supported by hardware\n", 405572b676d7Smrg (int)pScrn->weight.red, (int)pScrn->weight.green, 405672b676d7Smrg (int)pScrn->weight.blue, pScrn->depth); 405772b676d7Smrg goto my_error_1; 405872b676d7Smrg } 405972b676d7Smrg } 406072b676d7Smrg } 406172b676d7Smrg 406272b676d7Smrg /* Set the current layout parameters */ 406372b676d7Smrg pSiS->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel; 406472b676d7Smrg pSiS->CurrentLayout.depth = pScrn->depth; 406572b676d7Smrg /* (Inside this function, we can use pScrn's contents anyway) */ 406672b676d7Smrg 406772b676d7Smrg if(!xf86SetDefaultVisual(pScrn, -1)) { 406872b676d7Smrg SISErrorLog(pScrn, "xf86SetDefaultVisual() error\n"); 406972b676d7Smrg goto my_error_1; 407072b676d7Smrg } else { 407172b676d7Smrg /* We don't support DirectColor at > 8bpp */ 407272b676d7Smrg if(pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { 407372b676d7Smrg SISErrorLog(pScrn, 407472b676d7Smrg "Given default visual (%s) is not supported at depth %d\n", 407572b676d7Smrg xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); 407672b676d7Smrg goto my_error_1; 407772b676d7Smrg } 407872b676d7Smrg } 407972b676d7Smrg 408072b676d7Smrg#ifdef SISDUALHEAD 408172b676d7Smrg /* Due to palette & timing problems we don't support 8bpp in DHM */ 408272b676d7Smrg if((pSiS->DualHeadMode) && (pScrn->bitsPerPixel <= 8)) { 408372b676d7Smrg SISErrorLog(pScrn, "Color depth %d not supported in Dual Head mode.\n", 408472b676d7Smrg pScrn->bitsPerPixel); 408572b676d7Smrg goto my_error_1; 408672b676d7Smrg } 408772b676d7Smrg#endif 408872b676d7Smrg 408972b676d7Smrg /* Read BIOS for 300/315/330/340 series customization */ 409072b676d7Smrg pSiS->SiS_Pr->VirtualRomBase = NULL; 409172b676d7Smrg pSiS->BIOS = NULL; 409272b676d7Smrg pSiS->SiS_Pr->UseROM = FALSE; 409372b676d7Smrg pSiS->ROM661New = FALSE; 409472b676d7Smrg pSiS->HaveXGIBIOS = FALSE; 409572b676d7Smrg 409672b676d7Smrg if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 409772b676d7Smrg#ifdef SISDUALHEAD 409872b676d7Smrg if(pSiSEnt) { 409972b676d7Smrg if(pSiSEnt->BIOS) { 410072b676d7Smrg pSiS->BIOS = pSiSEnt->BIOS; 410172b676d7Smrg pSiS->SiS_Pr->VirtualRomBase = pSiS->BIOS; 410272b676d7Smrg pSiS->ROM661New = pSiSEnt->ROM661New; 410372b676d7Smrg pSiS->HaveXGIBIOS = pSiSEnt->HaveXGIBIOS; 410472b676d7Smrg } 410572b676d7Smrg } 410672b676d7Smrg#endif 410772b676d7Smrg if(!pSiS->BIOS) { 41085788ca14Smrg if(!(pSiS->BIOS = calloc(1, BIOS_SIZE))) { 410972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 411072b676d7Smrg "Could not allocate memory for video BIOS image\n"); 411172b676d7Smrg } else { 411272b676d7Smrg UShort mypciid = pSiS->Chipset; 411372b676d7Smrg UShort mypcivendor = (pSiS->ChipFlags & SiSCF_IsXGI) ? PCI_VENDOR_XGI : PCI_VENDOR_SIS; 411472b676d7Smrg Bool found = FALSE, readpci = FALSE; 411572b676d7Smrg int biossize = BIOS_SIZE; 411672b676d7Smrg 411772b676d7Smrg switch(pSiS->ChipType) { 411872b676d7Smrg case SIS_315: mypciid = PCI_CHIP_SIS315; 411972b676d7Smrg readpci = TRUE; 412072b676d7Smrg break; 412172b676d7Smrg case SIS_315PRO: mypciid = PCI_CHIP_SIS315PRO; 412272b676d7Smrg readpci = TRUE; 412372b676d7Smrg break; 412472b676d7Smrg case SIS_300: 412572b676d7Smrg case SIS_315H: 412672b676d7Smrg case SIS_330: 412772b676d7Smrg case SIS_340: 4128e35772b2Smrg case SIS_650: 4129e35772b2Smrg case SIS_760: 413072b676d7Smrg case XGI_40: readpci = TRUE; 413172b676d7Smrg break; 413272b676d7Smrg case XGI_20: readpci = TRUE; 413372b676d7Smrg biossize = 0x8000; 413472b676d7Smrg break; 413572b676d7Smrg } 41361fd23544Smrg#if XSERVER_LIBPCIACCESS 41371fd23544Smrg if(readpci) { 41381fd23544Smrg pSiS->PciInfo->rom_size = biossize; 41391fd23544Smrg pci_device_read_rom(pSiS->PciInfo, pSiS->BIOS); 41401fd23544Smrg if(SISCheckBIOS(pSiS, mypciid, mypcivendor, biossize)) { 41411fd23544Smrg found = TRUE; 41421fd23544Smrg } 41431fd23544Smrg } 41441fd23544Smrg#else 414572b676d7Smrg if(readpci) { 414672b676d7Smrg xf86ReadPciBIOS(0, pSiS->PciTag, 0, pSiS->BIOS, biossize); 414772b676d7Smrg if(SISCheckBIOS(pSiS, mypciid, mypcivendor, biossize)) { 414872b676d7Smrg found = TRUE; 414972b676d7Smrg } 415072b676d7Smrg } 415172b676d7Smrg 415272b676d7Smrg if(!found) { 41531fd23544Smrg ULong segstart; 415472b676d7Smrg for(segstart = BIOS_BASE; segstart < 0x000f0000; segstart += 0x00001000) { 415572b676d7Smrg 415672b676d7Smrg#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) 415772b676d7Smrg if(xf86ReadBIOS(segstart, 0, pSiS->BIOS, biossize) != biossize) continue; 415872b676d7Smrg#else 415972b676d7Smrg if(xf86ReadDomainMemory(pSiS->PciTag, segstart, biossize, pSiS->BIOS) != biossize) continue; 416072b676d7Smrg#endif 416172b676d7Smrg 416272b676d7Smrg if(!SISCheckBIOS(pSiS, mypciid, mypcivendor, biossize)) continue; 416372b676d7Smrg 416472b676d7Smrg found = TRUE; 416572b676d7Smrg break; 416672b676d7Smrg } 416772b676d7Smrg } 41681fd23544Smrg#endif 416972b676d7Smrg if(found) { 417072b676d7Smrg UShort romptr = pSiS->BIOS[0x16] | (pSiS->BIOS[0x17] << 8); 417172b676d7Smrg pSiS->SiS_Pr->VirtualRomBase = pSiS->BIOS; 417272b676d7Smrg if(pSiS->ChipFlags & SiSCF_IsXGI) { 417372b676d7Smrg pSiS->HaveXGIBIOS = pSiS->SiS_Pr->SiS_XGIROM = TRUE; 417472b676d7Smrg pSiS->SiS_Pr->UseROM = FALSE; 417572b676d7Smrg if(pSiS->ChipFlags & SiSCF_IsXGIV3) { 417672b676d7Smrg if(!(pSiS->BIOS[0x1d1] & 0x01)) { 417772b676d7Smrg pSiS->SiS_Pr->DDCPortMixup = TRUE; 417872b676d7Smrg } 417972b676d7Smrg } 418072b676d7Smrg } else { 418172b676d7Smrg pSiS->ROM661New = SiSDetermineROMLayout661(pSiS->SiS_Pr); 418272b676d7Smrg } 418372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 418472b676d7Smrg "Video BIOS version \"%7s\" found (%s data layout)\n", 418572b676d7Smrg &pSiS->BIOS[romptr], pSiS->ROM661New ? "new SiS" : 418672b676d7Smrg (pSiS->HaveXGIBIOS ? "XGI" : "old SiS")); 418772b676d7Smrg if(pSiS->SiS_Pr->DDCPortMixup) { 418872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 418972b676d7Smrg "*** Buggy XGI V3XT card detected: If VGA and DVI are connected at the\n"); 419072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 419172b676d7Smrg "*** same time, BIOS and driver will be unable to detect DVI connection.\n"); 419272b676d7Smrg } 419372b676d7Smrg#ifdef SISDUALHEAD 419472b676d7Smrg if(pSiSEnt) { 419572b676d7Smrg pSiSEnt->BIOS = pSiS->BIOS; 419672b676d7Smrg pSiSEnt->ROM661New = pSiS->ROM661New; 419772b676d7Smrg pSiSEnt->HaveXGIBIOS = pSiS->HaveXGIBIOS; 419872b676d7Smrg } 419972b676d7Smrg#endif 420072b676d7Smrg } else { 420172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 420272b676d7Smrg "Could not find/read video BIOS\n"); 42035788ca14Smrg free(pSiS->BIOS); 420472b676d7Smrg pSiS->BIOS = NULL; 420572b676d7Smrg } 420672b676d7Smrg } 420772b676d7Smrg } 420872b676d7Smrg 420972b676d7Smrg if(!(pSiS->ChipFlags & SiSCF_IsXGI)) { 421072b676d7Smrg if(pSiS->BIOS) pSiS->SiS_Pr->UseROM = TRUE; 421172b676d7Smrg else pSiS->SiS_Pr->UseROM = FALSE; 421272b676d7Smrg } 421372b676d7Smrg } 421472b676d7Smrg 421572b676d7Smrg /* Evaluate options */ 421672b676d7Smrg SiSOptions(pScrn); 421772b676d7Smrg 421872b676d7Smrg#ifdef SISMERGED 421972b676d7Smrg /* Due to palette & timing problems we don't support 8bpp in MFBM */ 422072b676d7Smrg if((pSiS->MergedFB) && (pScrn->bitsPerPixel <= 8)) { 422172b676d7Smrg SISErrorLog(pScrn, "MergedFB: Color depth %d not supported, %s\n", 422272b676d7Smrg pScrn->bitsPerPixel, mergeddisstr); 422372b676d7Smrg pSiS->MergedFB = pSiS->MergedFBAuto = FALSE; 422472b676d7Smrg } 422572b676d7Smrg#endif 422672b676d7Smrg 422772b676d7Smrg /* Probe CPU features */ 422872b676d7Smrg#ifdef SISDUALHEAD 422972b676d7Smrg if(pSiS->DualHeadMode) { 423072b676d7Smrg pSiS->CPUFlags = pSiSEnt->CPUFlags; 423172b676d7Smrg } 423272b676d7Smrg#endif 423372b676d7Smrg if(!pSiS->CPUFlags) { 423472b676d7Smrg pSiS->CPUFlags = SiSGetCPUFlags(pScrn); 423572b676d7Smrg pSiS->CPUFlags |= SIS_CPUFL_FLAG; 423672b676d7Smrg#ifdef SISDUALHEAD 423772b676d7Smrg if(pSiS->DualHeadMode) pSiSEnt->CPUFlags = pSiS->CPUFlags; 423872b676d7Smrg#endif 423972b676d7Smrg } 424072b676d7Smrg 424172b676d7Smrg /* We use a programamble clock */ 424272b676d7Smrg pScrn->progClock = TRUE; 424372b676d7Smrg 424472b676d7Smrg /* Set the bits per RGB for 8bpp mode */ 424572b676d7Smrg if(pScrn->depth == 8) pScrn->rgbBits = 8; 424672b676d7Smrg 424772b676d7Smrg#ifdef SISDUALHEAD 424872b676d7Smrg if(pSiS->DualHeadMode) { 424972b676d7Smrg if(!pSiS->SecondHead) { 425072b676d7Smrg /* Copy some option settings to entity private */ 425172b676d7Smrg pSiSEnt->HWCursor = pSiS->HWCursor; 425272b676d7Smrg pSiSEnt->NoAccel = pSiS->NoAccel; 425372b676d7Smrg pSiSEnt->useEXA = pSiS->useEXA; 425472b676d7Smrg pSiSEnt->restorebyset = pSiS->restorebyset; 425572b676d7Smrg pSiSEnt->OptROMUsage = pSiS->OptROMUsage; 425672b676d7Smrg pSiSEnt->OptUseOEM = pSiS->OptUseOEM; 425772b676d7Smrg pSiSEnt->TurboQueue = pSiS->TurboQueue; 425872b676d7Smrg pSiSEnt->forceCRT1 = pSiS->forceCRT1; 425972b676d7Smrg pSiSEnt->ForceCRT1Type = pSiS->ForceCRT1Type; 426072b676d7Smrg pSiSEnt->CRT1TypeForced = pSiS->CRT1TypeForced; 426172b676d7Smrg pSiSEnt->ForceCRT2Type = pSiS->ForceCRT2Type; 426272b676d7Smrg pSiSEnt->ForceTVType = pSiS->ForceTVType; 426372b676d7Smrg pSiSEnt->ForceYPbPrType = pSiS->ForceYPbPrType; 426472b676d7Smrg pSiSEnt->ForceYPbPrAR = pSiS->ForceYPbPrAR; 426572b676d7Smrg pSiSEnt->UsePanelScaler = pSiS->UsePanelScaler; 426672b676d7Smrg pSiSEnt->CenterLCD = pSiS->CenterLCD; 426772b676d7Smrg pSiSEnt->DSTN = pSiS->DSTN; 426872b676d7Smrg pSiSEnt->FSTN = pSiS->FSTN; 426972b676d7Smrg pSiSEnt->OptTVStand = pSiS->OptTVStand; 427072b676d7Smrg pSiSEnt->NonDefaultPAL = pSiS->NonDefaultPAL; 427172b676d7Smrg pSiSEnt->NonDefaultNTSC = pSiS->NonDefaultNTSC; 427272b676d7Smrg pSiSEnt->chtvtype = pSiS->chtvtype; 427372b676d7Smrg pSiSEnt->OptTVOver = pSiS->OptTVOver; 427472b676d7Smrg pSiSEnt->OptTVSOver = pSiS->OptTVSOver; 427572b676d7Smrg pSiSEnt->chtvlumabandwidthcvbs = pSiS->chtvlumabandwidthcvbs; 427672b676d7Smrg pSiSEnt->chtvlumabandwidthsvideo = pSiS->chtvlumabandwidthsvideo; 427772b676d7Smrg pSiSEnt->chtvlumaflickerfilter = pSiS->chtvlumaflickerfilter; 427872b676d7Smrg pSiSEnt->chtvchromabandwidth = pSiS->chtvchromabandwidth; 427972b676d7Smrg pSiSEnt->chtvchromaflickerfilter = pSiS->chtvchromaflickerfilter; 428072b676d7Smrg pSiSEnt->chtvtextenhance = pSiS->chtvtextenhance; 428172b676d7Smrg pSiSEnt->chtvcontrast = pSiS->chtvcontrast; 428272b676d7Smrg pSiSEnt->chtvcvbscolor = pSiS->chtvcvbscolor; 428372b676d7Smrg pSiSEnt->sistvedgeenhance = pSiS->sistvedgeenhance; 428472b676d7Smrg pSiSEnt->sistvantiflicker = pSiS->sistvantiflicker; 428572b676d7Smrg pSiSEnt->sistvsaturation = pSiS->sistvsaturation; 428672b676d7Smrg pSiSEnt->sistvcfilter = pSiS->sistvcfilter; 428772b676d7Smrg pSiSEnt->sistvyfilter = pSiS->sistvyfilter; 428872b676d7Smrg pSiSEnt->sistvcolcalibc = pSiS->sistvcolcalibc; 428972b676d7Smrg pSiSEnt->sistvcolcalibf = pSiS->sistvcolcalibf; 429072b676d7Smrg pSiSEnt->tvxpos = pSiS->tvxpos; 429172b676d7Smrg pSiSEnt->tvypos = pSiS->tvypos; 429272b676d7Smrg pSiSEnt->tvxscale = pSiS->tvxscale; 429372b676d7Smrg pSiSEnt->tvyscale = pSiS->tvyscale; 429472b676d7Smrg pSiSEnt->siscrt1satgain = pSiS->siscrt1satgain; 429572b676d7Smrg pSiSEnt->crt1satgaingiven = pSiS->crt1satgaingiven; 429672b676d7Smrg pSiSEnt->CRT1gamma = pSiS->CRT1gamma; 429772b676d7Smrg pSiSEnt->CRT1gammaGiven = pSiS->CRT1gammaGiven; 429872b676d7Smrg pSiSEnt->XvGammaRed = pSiS->XvGammaRed; 429972b676d7Smrg pSiSEnt->XvGammaGreen = pSiS->XvGammaGreen; 430072b676d7Smrg pSiSEnt->XvGammaBlue = pSiS->XvGammaBlue; 430172b676d7Smrg pSiSEnt->XvGamma = pSiS->XvGamma; 430272b676d7Smrg pSiSEnt->XvGammaGiven = pSiS->XvGammaGiven; 430372b676d7Smrg pSiSEnt->CRT2gamma = pSiS->CRT2gamma; 430472b676d7Smrg pSiSEnt->XvOnCRT2 = pSiS->XvOnCRT2; 430572b676d7Smrg pSiSEnt->AllowHotkey = pSiS->AllowHotkey; 430672b676d7Smrg pSiSEnt->enablesisctrl = pSiS->enablesisctrl; 430772b676d7Smrg pSiSEnt->SenseYPbPr = pSiS->SenseYPbPr; 430872b676d7Smrg pSiSEnt->XvUseMemcpy = pSiS->XvUseMemcpy; 430972b676d7Smrg pSiSEnt->BenchMemCpy = pSiS->BenchMemCpy; 431072b676d7Smrg#ifdef SIS_CP 431172b676d7Smrg SIS_CP_DRIVER_COPYOPTIONSENT 431272b676d7Smrg#endif 431372b676d7Smrg } else { 431472b676d7Smrg /* We always use same cursor type on both screens */ 431572b676d7Smrg pSiS->HWCursor = pSiSEnt->HWCursor; 431672b676d7Smrg /* We need identical NoAccel setting */ 431772b676d7Smrg pSiS->NoAccel = pSiSEnt->NoAccel; 431872b676d7Smrg pSiS->useEXA = pSiSEnt->useEXA; 431972b676d7Smrg pSiS->TurboQueue = pSiSEnt->TurboQueue; 432072b676d7Smrg pSiS->restorebyset = pSiSEnt->restorebyset; 432172b676d7Smrg pSiS->AllowHotkey = pSiS->AllowHotkey; 432272b676d7Smrg pSiS->OptROMUsage = pSiSEnt->OptROMUsage; 432372b676d7Smrg pSiS->OptUseOEM = pSiSEnt->OptUseOEM; 432472b676d7Smrg pSiS->forceCRT1 = pSiSEnt->forceCRT1; 432572b676d7Smrg pSiS->nocrt2ddcdetection = FALSE; 432672b676d7Smrg pSiS->forcecrt2redetection = FALSE; 432772b676d7Smrg pSiS->ForceCRT1Type = pSiSEnt->ForceCRT1Type; 432872b676d7Smrg pSiS->ForceCRT2Type = pSiSEnt->ForceCRT2Type; 432972b676d7Smrg pSiS->CRT1TypeForced = pSiSEnt->CRT1TypeForced; 433072b676d7Smrg pSiS->UsePanelScaler = pSiSEnt->UsePanelScaler; 433172b676d7Smrg pSiS->CenterLCD = pSiSEnt->CenterLCD; 433272b676d7Smrg pSiS->DSTN = pSiSEnt->DSTN; 433372b676d7Smrg pSiS->FSTN = pSiSEnt->FSTN; 433472b676d7Smrg pSiS->OptTVStand = pSiSEnt->OptTVStand; 433572b676d7Smrg pSiS->NonDefaultPAL = pSiSEnt->NonDefaultPAL; 433672b676d7Smrg pSiS->NonDefaultNTSC = pSiSEnt->NonDefaultNTSC; 433772b676d7Smrg pSiS->chtvtype = pSiSEnt->chtvtype; 433872b676d7Smrg pSiS->ForceTVType = pSiSEnt->ForceTVType; 433972b676d7Smrg pSiS->ForceYPbPrType = pSiSEnt->ForceYPbPrType; 434072b676d7Smrg pSiS->ForceYPbPrAR = pSiSEnt->ForceYPbPrAR; 434172b676d7Smrg pSiS->OptTVOver = pSiSEnt->OptTVOver; 434272b676d7Smrg pSiS->OptTVSOver = pSiSEnt->OptTVSOver; 434372b676d7Smrg pSiS->chtvlumabandwidthcvbs = pSiSEnt->chtvlumabandwidthcvbs; 434472b676d7Smrg pSiS->chtvlumabandwidthsvideo = pSiSEnt->chtvlumabandwidthsvideo; 434572b676d7Smrg pSiS->chtvlumaflickerfilter = pSiSEnt->chtvlumaflickerfilter; 434672b676d7Smrg pSiS->chtvchromabandwidth = pSiSEnt->chtvchromabandwidth; 434772b676d7Smrg pSiS->chtvchromaflickerfilter = pSiSEnt->chtvchromaflickerfilter; 434872b676d7Smrg pSiS->chtvcvbscolor = pSiSEnt->chtvcvbscolor; 434972b676d7Smrg pSiS->chtvtextenhance = pSiSEnt->chtvtextenhance; 435072b676d7Smrg pSiS->chtvcontrast = pSiSEnt->chtvcontrast; 435172b676d7Smrg pSiS->sistvedgeenhance = pSiSEnt->sistvedgeenhance; 435272b676d7Smrg pSiS->sistvantiflicker = pSiSEnt->sistvantiflicker; 435372b676d7Smrg pSiS->sistvsaturation = pSiSEnt->sistvsaturation; 435472b676d7Smrg pSiS->sistvcfilter = pSiSEnt->sistvcfilter; 435572b676d7Smrg pSiS->sistvyfilter = pSiSEnt->sistvyfilter; 435672b676d7Smrg pSiS->sistvcolcalibc = pSiSEnt->sistvcolcalibc; 435772b676d7Smrg pSiS->sistvcolcalibf = pSiSEnt->sistvcolcalibf; 435872b676d7Smrg pSiS->tvxpos = pSiSEnt->tvxpos; 435972b676d7Smrg pSiS->tvypos = pSiSEnt->tvypos; 436072b676d7Smrg pSiS->tvxscale = pSiSEnt->tvxscale; 436172b676d7Smrg pSiS->tvyscale = pSiSEnt->tvyscale; 436272b676d7Smrg pSiS->SenseYPbPr = pSiSEnt->SenseYPbPr; 436372b676d7Smrg if(!pSiS->CRT1gammaGiven) { 436472b676d7Smrg if(pSiSEnt->CRT1gammaGiven) 436572b676d7Smrg pSiS->CRT1gamma = pSiSEnt->CRT1gamma; 436672b676d7Smrg } 436772b676d7Smrg pSiS->CRT2gamma = pSiSEnt->CRT2gamma; 436872b676d7Smrg if(!pSiS->XvGammaGiven) { 436972b676d7Smrg if(pSiSEnt->XvGammaGiven) { 437072b676d7Smrg pSiS->XvGamma = pSiSEnt->XvGamma; 437172b676d7Smrg pSiS->XvGammaRed = pSiS->XvGammaRedDef = pSiSEnt->XvGammaRed; 437272b676d7Smrg pSiS->XvGammaGreen = pSiS->XvGammaGreenDef = pSiSEnt->XvGammaGreen; 437372b676d7Smrg pSiS->XvGammaBlue = pSiS->XvGammaBlueDef = pSiSEnt->XvGammaBlue; 437472b676d7Smrg } 437572b676d7Smrg } 437672b676d7Smrg if(!pSiS->crt1satgaingiven) { 437772b676d7Smrg if(pSiSEnt->crt1satgaingiven) 437872b676d7Smrg pSiS->siscrt1satgain = pSiSEnt->siscrt1satgain; 437972b676d7Smrg } 438072b676d7Smrg pSiS->XvOnCRT2 = pSiSEnt->XvOnCRT2; 438172b676d7Smrg pSiS->enablesisctrl = pSiSEnt->enablesisctrl; 438272b676d7Smrg pSiS->XvUseMemcpy = pSiSEnt->XvUseMemcpy; 438372b676d7Smrg pSiS->BenchMemCpy = pSiSEnt->BenchMemCpy; 438472b676d7Smrg /* Copy gamma brightness to Ent (sic!) for Xinerama */ 438572b676d7Smrg pSiSEnt->GammaBriR = pSiS->GammaBriR; 438672b676d7Smrg pSiSEnt->GammaBriG = pSiS->GammaBriG; 438772b676d7Smrg pSiSEnt->GammaBriB = pSiS->GammaBriB; 438872b676d7Smrg pSiSEnt->NewGammaBriR = pSiS->NewGammaBriR; 438972b676d7Smrg pSiSEnt->NewGammaBriG = pSiS->NewGammaBriG; 439072b676d7Smrg pSiSEnt->NewGammaBriB = pSiS->NewGammaBriB; 439172b676d7Smrg pSiSEnt->NewGammaConR = pSiS->NewGammaConR; 439272b676d7Smrg pSiSEnt->NewGammaConG = pSiS->NewGammaConG; 439372b676d7Smrg pSiSEnt->NewGammaConB = pSiS->NewGammaConB; 439472b676d7Smrg#ifdef SIS_CP 439572b676d7Smrg SIS_CP_DRIVER_COPYOPTIONS 439672b676d7Smrg#endif 439772b676d7Smrg } 439872b676d7Smrg } 439972b676d7Smrg#endif 440072b676d7Smrg 440172b676d7Smrg /* Handle UseROMData, NoOEM and UsePanelScaler options */ 440272b676d7Smrg if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 440372b676d7Smrg from = X_PROBED; 440472b676d7Smrg if(pSiS->OptROMUsage == 0) { 440572b676d7Smrg pSiS->SiS_Pr->UseROM = FALSE; 440672b676d7Smrg from = X_CONFIG; 440772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, from, "Video ROM data usage is disabled\n"); 440872b676d7Smrg } 440972b676d7Smrg 441072b676d7Smrg if(!pSiS->OptUseOEM) { 441172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, from, "Internal OEM LCD/TV/VGA2 data usage is disabled\n"); 441272b676d7Smrg } 441372b676d7Smrg 441472b676d7Smrg pSiS->SiS_Pr->UsePanelScaler = pSiS->UsePanelScaler; 441572b676d7Smrg pSiS->SiS_Pr->CenterScreen = pSiS->CenterLCD; 441672b676d7Smrg } 441772b676d7Smrg 441872b676d7Smrg /* Do some HW configuration detection (memory amount & type, clock, etc) */ 441972b676d7Smrg SiSSetup(pScrn); 442072b676d7Smrg 442172b676d7Smrg /* Get framebuffer address */ 442272b676d7Smrg if(pSiS->pEnt->device->MemBase != 0) { 442372b676d7Smrg /* 442472b676d7Smrg * XXX Should check that the config file value matches one of the 442572b676d7Smrg * PCI base address values. 442672b676d7Smrg */ 442772b676d7Smrg pSiS->FbAddress = pSiS->pEnt->device->MemBase; 442872b676d7Smrg from = X_CONFIG; 442972b676d7Smrg } else { 44301fd23544Smrg pSiS->FbAddress = PCI_REGION_BASE(pSiS->PciInfo, 0, REGION_MEM) & 0xFFFFFFF0; 443172b676d7Smrg from = X_PROBED; 443272b676d7Smrg } 443372b676d7Smrg 443472b676d7Smrg#ifdef SISDUALHEAD 443572b676d7Smrg if(pSiS->DualHeadMode) 443672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, from, "Global linear framebuffer at 0x%lX\n", 443772b676d7Smrg (ULong)pSiS->FbAddress); 443872b676d7Smrg else 443972b676d7Smrg#endif 444072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", 444172b676d7Smrg (ULong)pSiS->FbAddress); 444272b676d7Smrg 444372b676d7Smrg pSiS->realFbAddress = pSiS->FbAddress; 444472b676d7Smrg 444572b676d7Smrg /* Get MMIO address */ 444672b676d7Smrg if(pSiS->pEnt->device->IOBase != 0) { 444772b676d7Smrg /* 444872b676d7Smrg * XXX Should check that the config file value matches one of the 444972b676d7Smrg * PCI base address values. 445072b676d7Smrg */ 445172b676d7Smrg pSiS->IOAddress = pSiS->pEnt->device->IOBase; 445272b676d7Smrg from = X_CONFIG; 445372b676d7Smrg } else { 44541fd23544Smrg pSiS->IOAddress = PCI_REGION_BASE(pSiS->PciInfo, 1, REGION_MEM) & 0xFFFFFFF0; 445572b676d7Smrg from = X_PROBED; 445672b676d7Smrg } 445772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX (size %ldK)\n", 445872b676d7Smrg (ULong)pSiS->IOAddress, pSiS->mmioSize); 445972b676d7Smrg 4460e47418d9Smrg#ifndef XSERVER_LIBPCIACCESS 446172b676d7Smrg /* Register the PCI-assigned resources */ 446272b676d7Smrg if(xf86RegisterResources(pSiS->pEnt->index, NULL, ResExclusive)) { 446372b676d7Smrg SISErrorLog(pScrn, "PCI resource conflicts detected\n"); 446472b676d7Smrg#ifdef SISDUALHEAD 446572b676d7Smrg if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; 446672b676d7Smrg#endif 446772b676d7Smrg sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); 446872b676d7Smrg if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); 446972b676d7Smrg SISFreeRec(pScrn); 447072b676d7Smrg return FALSE; 447172b676d7Smrg } 4472e47418d9Smrg#endif 447372b676d7Smrg 447472b676d7Smrg from = X_PROBED; 447572b676d7Smrg if(pSiS->pEnt->device->videoRam != 0) { 447672b676d7Smrg if(pSiS->Chipset == PCI_CHIP_SIS6326) { 447772b676d7Smrg pScrn->videoRam = pSiS->pEnt->device->videoRam; 447872b676d7Smrg from = X_CONFIG; 447972b676d7Smrg } else { 448072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 448172b676d7Smrg "Option \"VideoRAM\" ignored\n"); 448272b676d7Smrg } 448372b676d7Smrg } 448472b676d7Smrg 448572b676d7Smrg pSiS->RealVideoRam = pScrn->videoRam; 448672b676d7Smrg 448772b676d7Smrg if((pSiS->Chipset == PCI_CHIP_SIS6326) && 448872b676d7Smrg (pScrn->videoRam > 4096) && 448972b676d7Smrg (from != X_CONFIG)) { 449072b676d7Smrg pScrn->videoRam = 4096; 449172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, from, 449272b676d7Smrg "SiS6326: Detected %d KB VideoRAM, limiting to %d KB\n", 449372b676d7Smrg pSiS->RealVideoRam, pScrn->videoRam); 449472b676d7Smrg } else { 449572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d KB\n", pScrn->videoRam); 449672b676d7Smrg } 449772b676d7Smrg 449872b676d7Smrg if((pSiS->Chipset == PCI_CHIP_SIS6326) && 449972b676d7Smrg (pScrn->videoRam > 4096)) { 450072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 450172b676d7Smrg "SiS6326 engines do not support more than 4096KB RAM, therefore\n"); 450272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 450372b676d7Smrg "TurboQueue, HWCursor, 2D acceleration and XVideo are disabled.\n"); 450472b676d7Smrg pSiS->TurboQueue = FALSE; 450572b676d7Smrg pSiS->HWCursor = FALSE; 450672b676d7Smrg pSiS->NoXvideo = TRUE; 450772b676d7Smrg pSiS->NoAccel = TRUE; 450872b676d7Smrg } 450972b676d7Smrg 451072b676d7Smrg pSiS->FbMapSize = pSiS->availMem = pScrn->videoRam * 1024; 451172b676d7Smrg 451272b676d7Smrg /* Calculate real availMem according to Accel/TurboQueue and 451372b676d7Smrg * HWCursur setting. Also, initialize some variables used 451472b676d7Smrg * in other modules. 451572b676d7Smrg */ 451672b676d7Smrg pSiS->cursorOffset = 0; 451772b676d7Smrg pSiS->CurARGBDest = NULL; 451872b676d7Smrg pSiS->CurMonoSrc = NULL; 451972b676d7Smrg pSiS->CurFGCol = pSiS->CurBGCol = 0; 452072b676d7Smrg pSiS->FbBaseOffset = 0; 452172b676d7Smrg 452272b676d7Smrg switch(pSiS->VGAEngine) { 452372b676d7Smrg 452472b676d7Smrg case SIS_300_VGA: 452572b676d7Smrg pSiS->TurboQueueLen = 512; 452672b676d7Smrg if(pSiS->TurboQueue) { 452772b676d7Smrg pSiS->availMem -= (pSiS->TurboQueueLen*1024); 452872b676d7Smrg pSiS->cursorOffset = 512; 452972b676d7Smrg } 453072b676d7Smrg if(pSiS->HWCursor) { 453172b676d7Smrg pSiS->availMem -= pSiS->CursorSize; 453272b676d7Smrg if(pSiS->OptUseColorCursor) pSiS->availMem -= pSiS->CursorSize; 453372b676d7Smrg } 453472b676d7Smrg pSiS->CmdQueLenMask = 0xFFFF; 453572b676d7Smrg pSiS->CmdQueLenFix = 0; 453672b676d7Smrg pSiS->cursorBufferNum = 0; 453772b676d7Smrg#ifdef SISDUALHEAD 453872b676d7Smrg if(pSiSEnt) pSiSEnt->cursorBufferNum = 0; 453972b676d7Smrg#endif 454072b676d7Smrg break; 454172b676d7Smrg 454272b676d7Smrg case SIS_315_VGA: 454372b676d7Smrg#ifdef SISVRAMQ /* VRAM queue */ 454472b676d7Smrg pSiS->cmdQueueSizeMask = pSiS->cmdQueueSize - 1; /* VRAM Command Queue is variable (in therory) */ 454572b676d7Smrg pSiS->cmdQueueOffset = (pScrn->videoRam * 1024) - pSiS->cmdQueueSize; 454672b676d7Smrg pSiS->cmdQueueLen = 0; 454772b676d7Smrg pSiS->cmdQueueSize_div2 = pSiS->cmdQueueSize / 2; 454872b676d7Smrg pSiS->cmdQueueSize_div4 = pSiS->cmdQueueSize / 4; 454972b676d7Smrg pSiS->cmdQueueSize_4_3 = (pSiS->cmdQueueSize / 4) * 3; 455072b676d7Smrg pSiS->availMem -= pSiS->cmdQueueSize; 455172b676d7Smrg pSiS->cursorOffset = (pSiS->cmdQueueSize / 1024); 455272b676d7Smrg 455372b676d7Smrg /* Set up shared pointer to current offset */ 455472b676d7Smrg#ifdef SISDUALHEAD 455572b676d7Smrg if(pSiS->DualHeadMode) 455672b676d7Smrg pSiS->cmdQ_SharedWritePort = &(pSiSEnt->cmdQ_SharedWritePort_2D); 455772b676d7Smrg else 455872b676d7Smrg#endif 455972b676d7Smrg pSiS->cmdQ_SharedWritePort = &(pSiS->cmdQ_SharedWritePort_2D); 456072b676d7Smrg 456172b676d7Smrg 456272b676d7Smrg#else /* MMIO */ 456372b676d7Smrg if(pSiS->TurboQueue) { 456472b676d7Smrg pSiS->availMem -= (512*1024); /* MMIO Command Queue is 512k (variable in theory) */ 456572b676d7Smrg pSiS->cursorOffset = 512; 456672b676d7Smrg } 456772b676d7Smrg#endif 456872b676d7Smrg if(pSiS->HWCursor) { 456972b676d7Smrg pSiS->availMem -= (pSiS->CursorSize * 2); 457072b676d7Smrg if(pSiS->OptUseColorCursor) pSiS->availMem -= (pSiS->CursorSize * 2); 457172b676d7Smrg } 457272b676d7Smrg pSiS->cursorBufferNum = 0; 457372b676d7Smrg#ifdef SISDUALHEAD 457472b676d7Smrg if(pSiSEnt) pSiSEnt->cursorBufferNum = 0; 457572b676d7Smrg#endif 457672b676d7Smrg 457772b676d7Smrg if((pSiS->SiS76xLFBSize) && (pSiS->SiS76xUMASize)) { 457872b676d7Smrg pSiS->availMem -= pSiS->SiS76xUMASize; 457972b676d7Smrg pSiS->FbBaseOffset = pSiS->SiS76xUMASize; 458072b676d7Smrg } 458172b676d7Smrg 458272b676d7Smrg break; 458372b676d7Smrg 458472b676d7Smrg default: 458572b676d7Smrg /* cursorOffset not used in cursor functions for 530 and 458672b676d7Smrg * older chips, because the cursor is *above* the TQ. 458772b676d7Smrg * On 5597 and older revisions of the 6326, the TQ is 458872b676d7Smrg * max 32K, on newer 6326 revisions and the 530 either 30 458972b676d7Smrg * (or 32?) or 62K (or 64?). However, to make sure, we 459072b676d7Smrg * use only 30K (or 32?), but reduce the available memory 459172b676d7Smrg * by 64, and locate the TQ at the beginning of this last 459272b676d7Smrg * 64K block. (We do this that way even when using the 459372b676d7Smrg * HWCursor, because the cursor only takes 2K and the 459472b676d7Smrg * queue does not seem to last that far anyway.) 459572b676d7Smrg * The TQ must be located at 32KB boundaries. 459672b676d7Smrg */ 459772b676d7Smrg if(pSiS->RealVideoRam < 3072) { 459872b676d7Smrg if(pSiS->TurboQueue) { 459972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 460072b676d7Smrg "Not enough video RAM for TurboQueue. TurboQueue disabled\n"); 460172b676d7Smrg pSiS->TurboQueue = FALSE; 460272b676d7Smrg } 460372b676d7Smrg } 460472b676d7Smrg pSiS->CmdQueMaxLen = 32; 460572b676d7Smrg if(pSiS->TurboQueue) { 460672b676d7Smrg pSiS->availMem -= (64*1024); 460772b676d7Smrg pSiS->CmdQueMaxLen = 900; /* To make sure; should be 992 */ 460872b676d7Smrg } else if(pSiS->HWCursor) { 460972b676d7Smrg pSiS->availMem -= pSiS->CursorSize; 461072b676d7Smrg } 461172b676d7Smrg if(pSiS->Chipset == PCI_CHIP_SIS530) { 461272b676d7Smrg /* Check if Flat Panel is enabled */ 461372b676d7Smrg inSISIDXREG(SISSR, 0x0e, tempreg); 461472b676d7Smrg if(!(tempreg & 0x04)) pSiS->availMem -= pSiS->CursorSize; 461572b676d7Smrg 461672b676d7Smrg /* Set up mask for MMIO register */ 461772b676d7Smrg pSiS->CmdQueLenMask = (pSiS->TurboQueue) ? 0x1FFF : 0x00FF; 461872b676d7Smrg } else { 461972b676d7Smrg /* TQ is never used on 6326/5597, because the accelerator 462072b676d7Smrg * always Syncs. So this is just cosmentic work. (And I 462172b676d7Smrg * am not even sure that 0x7fff is correct. MMIO 0x83a8 462272b676d7Smrg * holds 0xec0 if (30k) TQ is enabled, 0x20 if TQ disabled. 462372b676d7Smrg * The datasheet has no real explanation on the queue length 462472b676d7Smrg * if the TQ is enabled. Not syncing and waiting for a 462572b676d7Smrg * suitable queue length instead does not work. 462672b676d7Smrg */ 462772b676d7Smrg pSiS->CmdQueLenMask = (pSiS->TurboQueue) ? 0x7FFF : 0x003F; 462872b676d7Smrg } 462972b676d7Smrg 463072b676d7Smrg /* This is to be subtracted from MMIO queue length register contents 463172b676d7Smrg * for getting the real Queue length. 463272b676d7Smrg */ 463372b676d7Smrg pSiS->CmdQueLenFix = (pSiS->TurboQueue) ? 32 : 0; 463472b676d7Smrg } 463572b676d7Smrg 463672b676d7Smrg 463772b676d7Smrg#ifdef SISDUALHEAD 463872b676d7Smrg /* In dual head mode, we share availMem equally - so align it 463972b676d7Smrg * to 8KB; this way, the address of the FB of the second 464072b676d7Smrg * head is aligned to 4KB for mapping. 464172b676d7Smrg */ 464272b676d7Smrg if(pSiS->DualHeadMode) pSiS->availMem &= 0xFFFFE000; 464372b676d7Smrg#endif 464472b676d7Smrg 464572b676d7Smrg /* Check MaxXFBMem setting */ 464672b676d7Smrg#ifdef SISDUALHEAD 464772b676d7Smrg if(pSiS->DualHeadMode) { 464872b676d7Smrg /* 1. Since DRI is not supported in dual head mode, we 464972b676d7Smrg * don't need the MaxXFBMem setting - ignore it. 465072b676d7Smrg */ 465172b676d7Smrg if(pSiS->maxxfbmem) { 465272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 465372b676d7Smrg "MaxXFBMem ignored in Dual Head mode\n"); 465472b676d7Smrg } 465572b676d7Smrg pSiS->maxxfbmem = pSiS->availMem; 465672b676d7Smrg } else 465772b676d7Smrg#endif 465872b676d7Smrg if((pSiS->sisfbHeapStart) || (pSiS->sisfbHaveNewHeapDef)) { 465972b676d7Smrg 466072b676d7Smrg /* 466172b676d7Smrg * 2. We have memory layout info from sisfb - ignore MaxXFBMem 466272b676d7Smrg */ 466372b676d7Smrg if(pSiS->maxxfbmem) { 466472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 466572b676d7Smrg "Got memory layout info from sisfb, ignoring MaxXFBMem option\n"); 466672b676d7Smrg } 466772b676d7Smrg if((pSiS->FbBaseOffset) && (!pSiS->sisfbHaveNewHeapDef)) { 466872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 466972b676d7Smrg "Incompatible sisfb version detected, DRI disabled\n"); 467072b676d7Smrg pSiS->loadDRI = FALSE; 467172b676d7Smrg pSiS->maxxfbmem = pSiS->availMem; 467272b676d7Smrg } else { 467372b676d7Smrg if(pSiS->FbBaseOffset) { 467472b676d7Smrg /* Revert our changes to FbBaseOffset and availMem; use sisfb's info */ 467572b676d7Smrg pSiS->availMem += pSiS->FbBaseOffset; 467672b676d7Smrg pSiS->FbBaseOffset = 0; 467772b676d7Smrg } 467872b676d7Smrg if(pSiS->sisfbVideoOffset) { 467972b676d7Smrg /* a. DRI heap BELOW framebuffer */ 468072b676d7Smrg pSiS->FbBaseOffset = pSiS->sisfbVideoOffset; 468172b676d7Smrg pSiS->availMem -= pSiS->FbBaseOffset; 468272b676d7Smrg pSiS->maxxfbmem = pSiS->availMem; 468372b676d7Smrg } else { 468472b676d7Smrg /* b. DRI heap ABOVE framebuffer (traditional layout) */ 468572b676d7Smrg if(pSiS->availMem < (pSiS->sisfbHeapStart * 1024)) { 468672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 468772b676d7Smrg "Internal error - sisfb memory layout corrupt\n"); 468872b676d7Smrg pSiS->loadDRI = FALSE; 468972b676d7Smrg pSiS->maxxfbmem = pSiS->availMem; 469072b676d7Smrg } else { 469172b676d7Smrg pSiS->maxxfbmem = pSiS->sisfbHeapStart * 1024; 469272b676d7Smrg } 469372b676d7Smrg } 469472b676d7Smrg } 469572b676d7Smrg 469672b676d7Smrg } else if(pSiS->maxxfbmem) { 469772b676d7Smrg 469872b676d7Smrg /* 469972b676d7Smrg * 3. No sisfb, but user gave "MaxXFBMem" 470072b676d7Smrg */ 470172b676d7Smrg if(pSiS->FbBaseOffset) { 470272b676d7Smrg /* a. DRI heap BELOW framebuffer */ 470372b676d7Smrg if(pSiS->maxxfbmem > (pSiS->availMem + pSiS->FbBaseOffset - pSiS->SiS76xUMASize)) { 470472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 470572b676d7Smrg "Invalid MaxXFBMem setting\n"); 470672b676d7Smrg pSiS->maxxfbmem = pSiS->availMem; 470772b676d7Smrg } else { 470872b676d7Smrg /* Revert our changes */ 470972b676d7Smrg pSiS->availMem += pSiS->FbBaseOffset; 471072b676d7Smrg /* Use user's MaxXFBMem setting */ 471172b676d7Smrg pSiS->FbBaseOffset = pSiS->availMem - pSiS->maxxfbmem; 471272b676d7Smrg pSiS->availMem -= pSiS->FbBaseOffset; 471372b676d7Smrg } 471472b676d7Smrg } else { 471572b676d7Smrg /* b. DRI heap ABOVE framebuffer (traditional layout) */ 471672b676d7Smrg if(pSiS->maxxfbmem > pSiS->availMem) { 471772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 471872b676d7Smrg "Invalid MaxXFBMem setting.\n"); 471972b676d7Smrg pSiS->maxxfbmem = pSiS->availMem; 472072b676d7Smrg } 472172b676d7Smrg } 472272b676d7Smrg 472372b676d7Smrg } else { 472472b676d7Smrg 472572b676d7Smrg /* 472672b676d7Smrg * 4. No MaxXFBMem, no sisfb: Use all memory 472772b676d7Smrg */ 472872b676d7Smrg pSiS->maxxfbmem = pSiS->availMem; 472972b676d7Smrg 473072b676d7Smrg /* ... except on chipsets, for which DRI is 473172b676d7Smrg * supported: If DRI is enabled, we now limit 473272b676d7Smrg * ourselves to a reasonable default: 473372b676d7Smrg */ 473472b676d7Smrg 473572b676d7Smrg if(pSiS->loadDRI) { 473672b676d7Smrg if(pSiS->FbBaseOffset) { 473772b676d7Smrg /* a. DRI heap BELOW framebuffer */ 473872b676d7Smrg /* See how much UMA and LFB memory we have, 473972b676d7Smrg * and calculate a reasonable default. We 474072b676d7Smrg * use more vram for ourselves because these 474172b676d7Smrg * chips are eg. capable of larger Xv 474272b676d7Smrg * overlays, etc. 474372b676d7Smrg */ 474472b676d7Smrg unsigned long total = (pSiS->SiS76xLFBSize + pSiS->SiS76xUMASize) / 1024; 474572b676d7Smrg unsigned long mymax; 474672b676d7Smrg if(total <= 16384) /* <= 16MB: Use 8MB for X */ 474772b676d7Smrg mymax = 8192 * 1024; 474872b676d7Smrg else if(total <= 32768) /* <= 32MB: Use 16MB for X */ 474972b676d7Smrg mymax = 16384 * 1024; 475072b676d7Smrg else /* Otherwise: Use 20MB for X */ 475172b676d7Smrg mymax = 20 * 1024 * 1024; 475272b676d7Smrg /* availMem is right now adjusted to not use the UMA 475372b676d7Smrg * area. Make sure that our default doesn't reach 475472b676d7Smrg * into the UMA area either. 475572b676d7Smrg */ 475672b676d7Smrg if(pSiS->availMem > mymax) { 475772b676d7Smrg /* Write our default to maxxfbmem */ 475872b676d7Smrg pSiS->maxxfbmem = mymax; 475972b676d7Smrg /* Revert our changes to availMem */ 476072b676d7Smrg pSiS->availMem += pSiS->FbBaseOffset; 476172b676d7Smrg /* Use our default setting */ 476272b676d7Smrg pSiS->FbBaseOffset = pSiS->availMem - pSiS->maxxfbmem; 476372b676d7Smrg pSiS->availMem -= pSiS->FbBaseOffset; 476472b676d7Smrg } 476572b676d7Smrg } else { 476672b676d7Smrg /* b. DRI heap ABOVE framebuffer (traditional layout) */ 476772b676d7Smrg /* See how much video memory we have, and calculate 476872b676d7Smrg * a reasonable default. 476972b676d7Smrg * Since DRI is pointless with less than 4MB of total 477072b676d7Smrg * video RAM, we disable it in that case. 477172b676d7Smrg */ 477272b676d7Smrg if(pScrn->videoRam <= 4096) 477372b676d7Smrg pSiS->loadDRI = FALSE; 477472b676d7Smrg else if(pScrn->videoRam <= 8192) /* <= 8MB: Use 4MB for X */ 477572b676d7Smrg pSiS->maxxfbmem = 4096 * 1024; 477672b676d7Smrg else if(pScrn->videoRam <= 16384) /* <= 16MB: Use 8MB for X */ 477772b676d7Smrg pSiS->maxxfbmem = 8192 * 1024; 477872b676d7Smrg#ifdef SISMERGED /* Otherwise: --- */ 477972b676d7Smrg else if(pSiS->MergedFB) { 478072b676d7Smrg if(pScrn->videoRam <= 65536) 478172b676d7Smrg pSiS->maxxfbmem = 16384 * 1024; /* If MergedFB and <=64MB, use 16MB for X */ 478272b676d7Smrg else 478372b676d7Smrg pSiS->maxxfbmem = 20 * 1024 * 1024; /* If MergedFB and > 64MB, use 20MB for X */ 478472b676d7Smrg } 478572b676d7Smrg#endif 478672b676d7Smrg else if(pSiS->VGAEngine == SIS_315_VGA) { 478772b676d7Smrg if(pScrn->videoRam <= 65536) 478872b676d7Smrg pSiS->maxxfbmem = 16384 * 1024; /* On >=315 series and <=64MB, use 16MB */ 478972b676d7Smrg else 479072b676d7Smrg pSiS->maxxfbmem = 20 * 1024 * 1024; /* On >=315 series and > 64MB, use 20MB */ 479172b676d7Smrg } else 479272b676d7Smrg pSiS->maxxfbmem = 12288 * 1024; /* On <315 series, use 12MB */ 479372b676d7Smrg 479472b676d7Smrg /* A final check */ 479572b676d7Smrg if(pSiS->maxxfbmem > pSiS->availMem) { 479672b676d7Smrg pSiS->maxxfbmem = pSiS->availMem; 479772b676d7Smrg pSiS->loadDRI = FALSE; 479872b676d7Smrg } 479972b676d7Smrg } 480072b676d7Smrg 480172b676d7Smrg } 480272b676d7Smrg } 480372b676d7Smrg 480472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %dK of framebuffer memory at offset %dK\n", 480572b676d7Smrg pSiS->maxxfbmem / 1024, pSiS->FbBaseOffset / 1024); 480672b676d7Smrg 480772b676d7Smrg /* Find out about sub-classes of some chipsets and check 480872b676d7Smrg * if the chipset supports two video overlays 480972b676d7Smrg */ 481072b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA || 481172b676d7Smrg pSiS->VGAEngine == SIS_315_VGA || 481272b676d7Smrg pSiS->Chipset == PCI_CHIP_SIS530 || 481372b676d7Smrg pSiS->Chipset == PCI_CHIP_SIS6326 || 481472b676d7Smrg pSiS->Chipset == PCI_CHIP_SIS5597) { 481572b676d7Smrg pSiS->hasTwoOverlays = FALSE; 481672b676d7Smrg switch(pSiS->Chipset) { 481772b676d7Smrg case PCI_CHIP_SIS300: 481872b676d7Smrg case PCI_CHIP_SIS540: /* ? (If not, need to add the SwitchCRT Xv attribute!) */ 481972b676d7Smrg case PCI_CHIP_SIS630: 482072b676d7Smrg case PCI_CHIP_SIS550: 482172b676d7Smrg pSiS->hasTwoOverlays = TRUE; 482272b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 482372b676d7Smrg break; 482472b676d7Smrg case PCI_CHIP_SIS315PRO: 482572b676d7Smrg pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 482672b676d7Smrg break; 482772b676d7Smrg case PCI_CHIP_SIS330: 482872b676d7Smrg pSiS->ChipFlags |= (SiSCF_CRT2HWCKaputt | SiSCF_LARGEOVERLAY); 482972b676d7Smrg break; 483072b676d7Smrg case PCI_CHIP_SIS340: 483172b676d7Smrg case PCI_CHIP_XGIXG40: /* Verified: only 1 overlay */ 483272b676d7Smrg pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 483372b676d7Smrg break; 483472b676d7Smrg case PCI_CHIP_SIS650: 483572b676d7Smrg { 483672b676d7Smrg UChar tempreg1, tempreg2; 483772b676d7Smrg static const char *id650str[] = { 483872b676d7Smrg "650", "650", "650", "650", 483972b676d7Smrg "650 A0 AA", "650 A2 CA", "650", "650", 484072b676d7Smrg "M650 A0", "M650 A1 AA","651 A0 AA", "651 A1 AA", 484172b676d7Smrg "M650", "65?", "651", "65?" 484272b676d7Smrg }; 484372b676d7Smrg pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 484472b676d7Smrg if(pSiS->ChipType == SIS_650) { 484572b676d7Smrg inSISIDXREG(SISCR, 0x5f, CR5F); 484672b676d7Smrg CR5F &= 0xf0; 484772b676d7Smrg andSISIDXREG(SISCR, 0x5c, 0x07); 484872b676d7Smrg inSISIDXREG(SISCR, 0x5c, tempreg1); 484972b676d7Smrg tempreg1 &= 0xf8; 485072b676d7Smrg orSISIDXREG(SISCR, 0x5c, 0xf8); 485172b676d7Smrg inSISIDXREG(SISCR, 0x5c, tempreg2); 485272b676d7Smrg tempreg2 &= 0xf8; 485372b676d7Smrg if((!tempreg1) || (tempreg2)) { 485472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 485572b676d7Smrg "SiS650 revision ID %x (%s)\n", CR5F, id650str[CR5F >> 4]); 485672b676d7Smrg if(CR5F & 0x80) { 485772b676d7Smrg pSiS->hasTwoOverlays = TRUE; /* M650 or 651 */ 485872b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 485972b676d7Smrg } 486072b676d7Smrg switch(CR5F) { 486172b676d7Smrg case 0xa0: 486272b676d7Smrg case 0xb0: 486372b676d7Smrg case 0xe0: 486472b676d7Smrg pSiS->ChipFlags |= SiSCF_Is651; 486572b676d7Smrg break; 486672b676d7Smrg case 0x80: 486772b676d7Smrg case 0x90: 486872b676d7Smrg case 0xc0: 486972b676d7Smrg pSiS->ChipFlags |= SiSCF_IsM650; 487072b676d7Smrg break; 487172b676d7Smrg } 487272b676d7Smrg } else { 487372b676d7Smrg pSiS->hasTwoOverlays = TRUE; 487472b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 487572b676d7Smrg switch(CR5F) { 487672b676d7Smrg case 0x90: 487772b676d7Smrg inSISIDXREG(SISCR, 0x5c, tempreg1); 487872b676d7Smrg tempreg1 &= 0xf8; 487972b676d7Smrg switch(tempreg1) { 488072b676d7Smrg case 0x00: 488172b676d7Smrg pSiS->ChipFlags |= SiSCF_IsM652; 488272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 488372b676d7Smrg "SiSM652 revision ID %x\n", CR5F); 488472b676d7Smrg break; 488572b676d7Smrg case 0x40: 488672b676d7Smrg pSiS->ChipFlags |= SiSCF_IsM653; 488772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 488872b676d7Smrg "SiSM653 revision ID %x\n", CR5F); 488972b676d7Smrg break; 489072b676d7Smrg default: 489172b676d7Smrg pSiS->ChipFlags |= SiSCF_IsM650; 489272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 489372b676d7Smrg "SiSM650 revision ID %x\n", CR5F); 489472b676d7Smrg break; 489572b676d7Smrg } 489672b676d7Smrg break; 489772b676d7Smrg case 0xb0: 489872b676d7Smrg pSiS->ChipFlags |= SiSCF_Is652; 489972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 490072b676d7Smrg "SiS652 revision ID %x\n", CR5F); 490172b676d7Smrg break; 490272b676d7Smrg default: 490372b676d7Smrg pSiS->ChipFlags |= SiSCF_IsM650; 490472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 490572b676d7Smrg "SiSM650 revision ID %x\n", CR5F); 490672b676d7Smrg break; 490772b676d7Smrg } 490872b676d7Smrg } 490972b676d7Smrg } 491072b676d7Smrg break; 491172b676d7Smrg } 491272b676d7Smrg case PCI_CHIP_SIS660: 491372b676d7Smrg { 491472b676d7Smrg pSiS->ChipFlags |= SiSCF_LARGEOVERLAY; 491572b676d7Smrg pSiS->hasTwoOverlays = TRUE; 491672b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_SUPPORT2OVL; 491772b676d7Smrg /* 760/761: - UMA only: one/two overlays - dotclock dependent 491872b676d7Smrg - UMA+LFB: two overlays if video data in LFB 491972b676d7Smrg - LFB only: two overlays 492072b676d7Smrg If UMA only: Must switch between one/two overlays on the fly (done 492172b676d7Smrg in PostSetMode()) 492272b676d7Smrg If LFB+UMA: We use LFB memory only and leave UMA to an eventually 492372b676d7Smrg written DRI driver. 492472b676d7Smrg */ 492572b676d7Smrg break; 492672b676d7Smrg } 492772b676d7Smrg } 492872b676d7Smrg 492972b676d7Smrg if(!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY)) { 493072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 493172b676d7Smrg "Hardware supports %s video overlay%s\n", 493272b676d7Smrg pSiS->hasTwoOverlays ? "two" : "one", 493372b676d7Smrg pSiS->hasTwoOverlays ? "s" : ""); 493472b676d7Smrg } 493572b676d7Smrg 493672b676d7Smrg if(pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORT760OO) { 493772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 493872b676d7Smrg "\n\tDear SiS76x user, your machine is using a shared memory framebuffer.\n" 493972b676d7Smrg "\tDue to hardware limitations of the SiS chip in combination with the\n" 494072b676d7Smrg "\tAMD CPU, video overlay support is very limited on this machine. If you\n" 494172b676d7Smrg "\texperience flashing lines in the video and/or the graphics display\n" 494272b676d7Smrg "\tduring video playback, reduce the color depth and/or the resolution\n" 494372b676d7Smrg "\tand/or the refresh rate. Alternatively, use the video blitter.\n"); 494472b676d7Smrg } 494572b676d7Smrg 494672b676d7Smrg } 494772b676d7Smrg 494872b676d7Smrg /* Backup VB connection and CRT1 on/off register */ 494972b676d7Smrg if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 495072b676d7Smrg inSISIDXREG(SISSR, 0x1f, pSiS->oldSR1F); 495172b676d7Smrg inSISIDXREG(SISCR, 0x17, pSiS->oldCR17); 495272b676d7Smrg inSISIDXREG(SISCR, 0x32, pSiS->oldCR32); 495372b676d7Smrg inSISIDXREG(SISCR, 0x36, pSiS->oldCR36); 495472b676d7Smrg inSISIDXREG(SISCR, 0x37, pSiS->oldCR37); 495572b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 495672b676d7Smrg inSISIDXREG(SISCR, pSiS->myCR63, pSiS->oldCR63); 495772b676d7Smrg } 495872b676d7Smrg 495972b676d7Smrg pSiS->postVBCR32 = pSiS->oldCR32; 496072b676d7Smrg } 496172b676d7Smrg 496272b676d7Smrg /* There are some machines out there which require a special 496372b676d7Smrg * setup of the GPIO registers in order to make the Chrontel 496472b676d7Smrg * work. Try to find out if we're running on such a machine. 496572b676d7Smrg * Furthermore, there is some highly customized hardware, 496672b676d7Smrg * which requires some non-standard LVDS timing. Since the 496772b676d7Smrg * vendors don't seem to care about PCI subsystem ID's we 496872b676d7Smrg * need to find out using the BIOS version and date strings. 496972b676d7Smrg */ 497072b676d7Smrg pSiS->SiS_Pr->SiS_ChSW = FALSE; 497172b676d7Smrg if(pSiS->Chipset == PCI_CHIP_SIS630) { 497272b676d7Smrg int i = 0; 497372b676d7Smrg do { 49741fd23544Smrg if(mychswtable[i].subsysVendor == PCI_SUB_VENDOR_ID(pSiS->PciInfo) && 49751fd23544Smrg mychswtable[i].subsysCard == PCI_SUB_DEVICE_ID(pSiS->PciInfo)) { 497672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 497772b676d7Smrg "PCI subsystem ID found in list for Chrontel/GPIO setup:\n"); 497872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 497972b676d7Smrg "\tVendor/Card: %s %s (ID %04x)\n", 498072b676d7Smrg mychswtable[i].vendorName, 498172b676d7Smrg mychswtable[i].cardName, 49821fd23544Smrg PCI_SUB_DEVICE_ID(pSiS->PciInfo)); 498372b676d7Smrg pSiS->SiS_Pr->SiS_ChSW = TRUE; 498472b676d7Smrg break; 498572b676d7Smrg } 498672b676d7Smrg i++; 498772b676d7Smrg } while(mychswtable[i].subsysVendor != 0); 498872b676d7Smrg } 498972b676d7Smrg 499072b676d7Smrg if(pSiS->SiS_Pr->SiS_CustomT == CUT_NONE) { 499172b676d7Smrg int i = 0, j; 499272b676d7Smrg UShort bversptr = 0; 499372b676d7Smrg Bool footprint; 499472b676d7Smrg CARD32 chksum = 0; 499572b676d7Smrg 499672b676d7Smrg if(pSiS->SiS_Pr->UseROM) { 499772b676d7Smrg bversptr = pSiS->BIOS[0x16] | (pSiS->BIOS[0x17] << 8); 499872b676d7Smrg for(i=0; i<32768; i++) chksum += pSiS->BIOS[i]; 499972b676d7Smrg } 500072b676d7Smrg 500172b676d7Smrg i = 0; 500272b676d7Smrg do { 500372b676d7Smrg if( (SiS_customttable[i].chipID == pSiS->ChipType) && 500472b676d7Smrg ((!strlen(SiS_customttable[i].biosversion)) || 500572b676d7Smrg (pSiS->SiS_Pr->UseROM && 500672b676d7Smrg (!strncmp(SiS_customttable[i].biosversion, (char *)&pSiS->BIOS[bversptr], 500772b676d7Smrg strlen(SiS_customttable[i].biosversion))))) && 500872b676d7Smrg ((!strlen(SiS_customttable[i].biosdate)) || 500972b676d7Smrg (pSiS->SiS_Pr->UseROM && 501072b676d7Smrg (!strncmp(SiS_customttable[i].biosdate, (char *)&pSiS->BIOS[0x2c], 501172b676d7Smrg strlen(SiS_customttable[i].biosdate))))) && 501272b676d7Smrg ((!SiS_customttable[i].bioschksum) || 501372b676d7Smrg (pSiS->SiS_Pr->UseROM && 501472b676d7Smrg (SiS_customttable[i].bioschksum == chksum))) && 50151fd23544Smrg (SiS_customttable[i].pcisubsysvendor == PCI_SUB_VENDOR_ID(pSiS->PciInfo)) && 50161fd23544Smrg (SiS_customttable[i].pcisubsyscard == PCI_SUB_DEVICE_ID(pSiS->PciInfo)) ) { 501772b676d7Smrg footprint = TRUE; 501872b676d7Smrg for(j=0; j<5; j++) { 501972b676d7Smrg if(SiS_customttable[i].biosFootprintAddr[j]) { 502072b676d7Smrg if(pSiS->SiS_Pr->UseROM) { 502172b676d7Smrg if(pSiS->BIOS[SiS_customttable[i].biosFootprintAddr[j]] != 502272b676d7Smrg SiS_customttable[i].biosFootprintData[j]) 502372b676d7Smrg footprint = FALSE; 502472b676d7Smrg } else footprint = FALSE; 502572b676d7Smrg } 502672b676d7Smrg } 502772b676d7Smrg if(footprint) { 502872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 502972b676d7Smrg "Identified %s %s, special timing applies\n", 503072b676d7Smrg SiS_customttable[i].vendorName, SiS_customttable[i].cardName); 503172b676d7Smrg pSiS->SiS_Pr->SiS_CustomT = SiS_customttable[i].SpecialID; 503272b676d7Smrg break; 503372b676d7Smrg } 503472b676d7Smrg } 503572b676d7Smrg i++; 503672b676d7Smrg } while(SiS_customttable[i].chipID); 503772b676d7Smrg } 503872b676d7Smrg 503972b676d7Smrg /* Handle ForceCRT1 option */ 504072b676d7Smrg if(pSiS->forceCRT1 != -1) { 504172b676d7Smrg if(pSiS->forceCRT1) pSiS->CRT1off = 0; 504272b676d7Smrg else pSiS->CRT1off = 1; 504372b676d7Smrg } else pSiS->CRT1off = -1; 504472b676d7Smrg 504572b676d7Smrg /* Detect video bridge and sense TV/VGA2 */ 504672b676d7Smrg SISVGAPreInit(pScrn); 504772b676d7Smrg 504872b676d7Smrg /* Detect CRT1 (via DDC1 and DDC2, hence via VGA port; regardless of LCDA) */ 504972b676d7Smrg SISCRT1PreInit(pScrn); 505072b676d7Smrg 505172b676d7Smrg /* Detect LCD (connected via CRT2, regardless of LCDA) and LCD resolution */ 505272b676d7Smrg SISLCDPreInit(pScrn, FALSE); 505372b676d7Smrg 505472b676d7Smrg /* LCDA only supported under these conditions: */ 505572b676d7Smrg if(pSiS->ForceCRT1Type == CRT1_LCDA) { 505672b676d7Smrg if(!SISDetermineLCDACap(pScrn)) { 505772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 505872b676d7Smrg "Chipset/Video bridge does not support LCD-via-CRT1\n"); 505972b676d7Smrg pSiS->ForceCRT1Type = CRT1_VGA; 506072b676d7Smrg } else if(!(pSiS->VBFlags & CRT2_LCD)) { 506172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 506272b676d7Smrg "No digital LCD panel found, LCD-via-CRT1 disabled\n"); 506372b676d7Smrg pSiS->ForceCRT1Type = CRT1_VGA; 506472b676d7Smrg } 506572b676d7Smrg } 506672b676d7Smrg 506772b676d7Smrg /* Setup SD flags */ 506872b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_ADDLSUPFLAG; 506972b676d7Smrg 507072b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_MERGEDUCLOCK; 507172b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_USEVBFLAGS2; 507272b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_VBINVB2ONLY; 507372b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_HAVESD34; 507472b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_NEWGAMMABRICON; 507572b676d7Smrg 507672b676d7Smrg pSiS->SiS_SD3_Flags |= SiS_SD3_MFBALLOWOFFCL; 507772b676d7Smrg 507872b676d7Smrg if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 507972b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_VIDEOBRIDGE; 508072b676d7Smrg if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 508172b676d7Smrg pSiS->SiS_SD2_Flags |= ( SiS_SD2_SISBRIDGE | 508272b676d7Smrg SiS_SD2_SUPPORTGAMMA2 ); 508372b676d7Smrg if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) { 508472b676d7Smrg pSiS->SiS_SD2_Flags |= ( SiS_SD2_LCDLVDS | 508572b676d7Smrg SiS_SD2_SUPPORTLCD ); 508672b676d7Smrg } else if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 508772b676d7Smrg if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 508872b676d7Smrg pSiS->SiS_SD2_Flags |= ( SiS_SD2_LCDTMDS | 508972b676d7Smrg SiS_SD2_SUPPORTLCD ); 509072b676d7Smrg } else if(pSiS->VBFlags & CRT2_LCD) { 509172b676d7Smrg pSiS->SiS_SD2_Flags |= ( SiS_SD2_THIRDPARTYLVDS | 509272b676d7Smrg SiS_SD2_SUPPORTLCD ); 509372b676d7Smrg } 509472b676d7Smrg } 509572b676d7Smrg } else if(pSiS->VBFlags2 & VB2_LVDS) { 509672b676d7Smrg pSiS->SiS_SD2_Flags |= ( SiS_SD2_THIRDPARTYLVDS | 509772b676d7Smrg SiS_SD2_SUPPORTLCD ); 509872b676d7Smrg } 509972b676d7Smrg 510072b676d7Smrg if(pSiS->VBFlags2 & (VB2_SISTVBRIDGE | VB2_CHRONTEL)) { 510172b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTTV; 510272b676d7Smrg if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 510372b676d7Smrg pSiS->SiS_SD2_Flags |= ( SiS_SD2_SUPPORTTVTYPE | 510472b676d7Smrg SiS_SD2_SUPPORTTVSIZE ); 510572b676d7Smrg if(!(pSiS->VBFlags2 & VB2_301)) { 510672b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPTVSAT; 510772b676d7Smrg } else { 510872b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPTVEDGE; 510972b676d7Smrg } 511072b676d7Smrg } 511172b676d7Smrg } 511272b676d7Smrg } 511372b676d7Smrg 511472b676d7Smrg#ifdef ENABLE_YPBPR 511572b676d7Smrg if((pSiS->VGAEngine == SIS_315_VGA) && 511672b676d7Smrg (pSiS->VBFlags2 & VB2_SISYPBPRBRIDGE)) { 511772b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTYPBPR; 511872b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORT625I; 511972b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORT625P; 512072b676d7Smrg if(pSiS->VBFlags2 & VB2_SISYPBPRARBRIDGE) { 512172b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTYPBPRAR; 512272b676d7Smrg } 512372b676d7Smrg } 512472b676d7Smrg if(pSiS->VBFlags2 & VB2_SISHIVISIONBRIDGE) { 512572b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTHIVISION; 512672b676d7Smrg } 512772b676d7Smrg#endif 512872b676d7Smrg 512972b676d7Smrg if((pSiS->VGAEngine != SIS_300_VGA) || (!(pSiS->VBFlags2 & VB2_TRUMPION))) { 513072b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTSCALE; 513172b676d7Smrg if((pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && 513272b676d7Smrg (!(pSiS->VBFlags2 & VB2_30xBDH))) { 513372b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTCENTER; 513472b676d7Smrg } 513572b676d7Smrg } 513672b676d7Smrg 513772b676d7Smrg#ifdef SISDUALHEAD 513872b676d7Smrg if(!pSiS->DualHeadMode) { 513972b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTREDETECT; 514072b676d7Smrg } 514172b676d7Smrg#endif 514272b676d7Smrg 514372b676d7Smrg#ifndef SISCHECKOSSSE 514472b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_NEEDUSESSE; 514572b676d7Smrg#endif 514672b676d7Smrg 514772b676d7Smrg#ifdef TWDEBUG /* FOR TESTING */ 514872b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTYPBPRAR; 514972b676d7Smrg xf86DrvMsg(0, X_INFO, "TEST: Support Aspect Ratio\n"); 515072b676d7Smrg#endif 515172b676d7Smrg 515272b676d7Smrg /* Detect CRT2-TV and PAL/NTSC mode */ 515372b676d7Smrg SISTVPreInit(pScrn, FALSE); 515472b676d7Smrg 515572b676d7Smrg /* Detect CRT2-VGA */ 515672b676d7Smrg SISCRT2PreInit(pScrn, FALSE); 515772b676d7Smrg 515872b676d7Smrg /* Backup detected CRT2 devices */ 515972b676d7Smrg SISSaveDetectedDevices(pScrn); 516072b676d7Smrg 516172b676d7Smrg if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR)) { 516272b676d7Smrg if((pSiS->ForceTVType != -1) && (pSiS->ForceTVType & TV_YPBPR)) { 516372b676d7Smrg pSiS->ForceTVType = -1; 516472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "YPbPr TV output not supported\n"); 516572b676d7Smrg } 516672b676d7Smrg } 516772b676d7Smrg 516872b676d7Smrg if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTHIVISION)) { 516972b676d7Smrg if((pSiS->ForceTVType != -1) && (pSiS->ForceTVType & TV_HIVISION)) { 517072b676d7Smrg pSiS->ForceTVType = -1; 517172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "HiVision TV output not supported\n"); 517272b676d7Smrg } 517372b676d7Smrg } 517472b676d7Smrg 517572b676d7Smrg if((pSiS->VBFlags2 & VB2_SISTVBRIDGE) || 517672b676d7Smrg ((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->ChrontelType == CHRONTEL_701x))) { 517772b676d7Smrg pSiS->SiS_SD_Flags |= (SiS_SD_SUPPORTPALMN | SiS_SD_SUPPORTNTSCJ); 517872b676d7Smrg } 517972b676d7Smrg if((pSiS->VBFlags2 & VB2_SISTVBRIDGE) || 518072b676d7Smrg ((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->ChrontelType == CHRONTEL_700x))) { 518172b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTTVPOS; 518272b676d7Smrg } 518372b676d7Smrg if(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE) { 518472b676d7Smrg pSiS->SiS_SD_Flags |= (SiS_SD_SUPPORTSCART | SiS_SD_SUPPORTVGA2); 518572b676d7Smrg } 518672b676d7Smrg if(pSiS->VBFlags2 & VB2_CHRONTEL) { 518772b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTOVERSCAN; 518872b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_CHRONTEL; 518972b676d7Smrg if(pSiS->ChrontelType == CHRONTEL_700x) { 519072b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTSOVER; 519172b676d7Smrg } 519272b676d7Smrg } 519372b676d7Smrg 519472b676d7Smrg /* Determine if chipset LCDA-capable */ 519572b676d7Smrg pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTLCDA; 519672b676d7Smrg if(SISDetermineLCDACap(pScrn)) { 519772b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTLCDA; 519872b676d7Smrg } 519972b676d7Smrg 520072b676d7Smrg /* Default to LCDA if LCD detected and 520172b676d7Smrg * - TV detected (hence default to LCDA+TV), or 520272b676d7Smrg * - in single head mode, on LCD panels with xres > 1600 520372b676d7Smrg * (Don't do this in MergedFB or DHM; LCDA and CRT1/VGA 520472b676d7Smrg * are mutually exclusive; if no TV is detected, the 520572b676d7Smrg * code below will default to VGA+LCD, so LCD is driven 520672b676d7Smrg * via CRT2.) 520772b676d7Smrg * (TODO: This might need some modification for the 520872b676d7Smrg * 307 bridges, if these are capable of driving 520972b676d7Smrg * LCDs > 1600 via channel B) 521072b676d7Smrg */ 521172b676d7Smrg if((pSiS->SiS_SD_Flags & SiS_SD_SUPPORTLCDA) && 521272b676d7Smrg (pSiS->VBFlags & CRT2_LCD) && 521372b676d7Smrg (pSiS->SiS_Pr->SiS_CustomT != CUT_UNKNOWNLCD)) { 521472b676d7Smrg if((!pSiS->CRT1TypeForced) && (pSiS->ForceCRT2Type == CRT2_DEFAULT)) { 521572b676d7Smrg if(pSiS->VBFlags & CRT2_TV) { 521672b676d7Smrg /* If both LCD and TV present, default to LCDA+TV */ 521772b676d7Smrg pSiS->ForceCRT1Type = CRT1_LCDA; 521872b676d7Smrg pSiS->ForceCRT2Type = CRT2_TV; 521972b676d7Smrg } else if(pSiS->LCDwidth > 1600) { 522072b676d7Smrg /* If LCD is > 1600, default to LCDA if we don't need CRT1/VGA for other head */ 522172b676d7Smrg Bool NeedCRT1VGA = FALSE; 522272b676d7Smrg#ifdef SISDUALHEAD 522372b676d7Smrg if(pSiS->DualHeadMode) NeedCRT1VGA = TRUE; 522472b676d7Smrg#endif 522572b676d7Smrg#ifdef SISMERGED 522672b676d7Smrg if(pSiS->MergedFB && 522772b676d7Smrg (!pSiS->MergedFBAuto || pSiS->CRT1Detected)) NeedCRT1VGA = TRUE; 522872b676d7Smrg#endif 522972b676d7Smrg if(!NeedCRT1VGA) { 523072b676d7Smrg pSiS->ForceCRT1Type = CRT1_LCDA; 523172b676d7Smrg } 523272b676d7Smrg } 523372b676d7Smrg } 523472b676d7Smrg } 523572b676d7Smrg 523672b676d7Smrg /* Set up pseudo-panel if LCDA forced on TMDS bridges */ 523772b676d7Smrg if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTLCDA) { 523872b676d7Smrg if(pSiS->ForceCRT1Type == CRT1_LCDA) { 523972b676d7Smrg if(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE) { 524072b676d7Smrg if(!(pSiS->VBLCDFlags)) { 524172b676d7Smrg SiSSetupPseudoPanel(pScrn); 524272b676d7Smrg pSiS->detectedCRT2Devices |= CRT2_LCD; 524372b676d7Smrg } 524472b676d7Smrg } else if(!(pSiS->VBLCDFlags)) { 524572b676d7Smrg pSiS->ForceCRT1Type = CRT1_VGA; 524672b676d7Smrg } 524772b676d7Smrg } 524872b676d7Smrg } else { 524972b676d7Smrg pSiS->ForceCRT1Type = CRT1_VGA; 525072b676d7Smrg } 525172b676d7Smrg 525272b676d7Smrg pSiS->VBFlags |= pSiS->ForceCRT1Type; 525372b676d7Smrg 525472b676d7Smrg#ifdef TWDEBUG 525572b676d7Smrg xf86DrvMsg(0, X_INFO, "SDFlags %lx\n", pSiS->SiS_SD_Flags); 525672b676d7Smrg#endif 525772b676d7Smrg 525872b676d7Smrg /* Eventually overrule detected CRT2 type 525972b676d7Smrg * If no type forced, use the detected devices in the order TV->LCD->VGA2 526072b676d7Smrg * Since the Chrontel 7005 sometimes delivers wrong detection results, 526172b676d7Smrg * we use a different order on such machines (LCD->TV) 526272b676d7Smrg */ 526372b676d7Smrg if(pSiS->ForceCRT2Type == CRT2_DEFAULT) { 526472b676d7Smrg if((pSiS->VBFlags & CRT2_TV) && (!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VGAEngine == SIS_300_VGA)))) 526572b676d7Smrg pSiS->ForceCRT2Type = CRT2_TV; 526672b676d7Smrg else if((pSiS->VBFlags & CRT2_LCD) && (pSiS->ForceCRT1Type == CRT1_VGA)) 526772b676d7Smrg pSiS->ForceCRT2Type = CRT2_LCD; 526872b676d7Smrg else if(pSiS->VBFlags & CRT2_TV) 526972b676d7Smrg pSiS->ForceCRT2Type = CRT2_TV; 527072b676d7Smrg else if((pSiS->VBFlags & CRT2_VGA) && (pSiS->ForceCRT1Type == CRT1_VGA)) 527172b676d7Smrg pSiS->ForceCRT2Type = CRT2_VGA; 527272b676d7Smrg } 527372b676d7Smrg 527472b676d7Smrg switch(pSiS->ForceCRT2Type) { 527572b676d7Smrg case CRT2_TV: 527672b676d7Smrg pSiS->VBFlags &= ~(CRT2_LCD | CRT2_VGA); 527772b676d7Smrg if(pSiS->VBFlags2 & (VB2_SISTVBRIDGE | VB2_CHRONTEL)) { 527872b676d7Smrg pSiS->VBFlags |= CRT2_TV; 527972b676d7Smrg } else { 528072b676d7Smrg pSiS->VBFlags &= ~(CRT2_TV); 528172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 528272b676d7Smrg "Hardware does not support TV output\n"); 528372b676d7Smrg } 528472b676d7Smrg break; 528572b676d7Smrg case CRT2_LCD: 528672b676d7Smrg pSiS->VBFlags &= ~(CRT2_TV | CRT2_VGA); 528772b676d7Smrg if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (pSiS->VBLCDFlags)) { 528872b676d7Smrg pSiS->VBFlags |= CRT2_LCD; 528972b676d7Smrg } else if((pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && (!(pSiS->VBFlags2 & VB2_30xBDH))) { 529072b676d7Smrg SiSSetupPseudoPanel(pScrn); 529172b676d7Smrg pSiS->detectedCRT2Devices |= CRT2_LCD; 529272b676d7Smrg } else { 529372b676d7Smrg pSiS->VBFlags &= ~(CRT2_LCD); 529472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 529572b676d7Smrg "Can't force CRT2 to LCD, no LCD detected\n"); 529672b676d7Smrg } 529772b676d7Smrg break; 529872b676d7Smrg case CRT2_VGA: 529972b676d7Smrg pSiS->VBFlags &= ~(CRT2_TV | CRT2_LCD); 530072b676d7Smrg if(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE) { 530172b676d7Smrg pSiS->VBFlags |= CRT2_VGA; 530272b676d7Smrg } else { 530372b676d7Smrg pSiS->VBFlags &= ~(CRT2_VGA); 530472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 530572b676d7Smrg "Hardware does not support secondary VGA\n"); 530672b676d7Smrg } 530772b676d7Smrg break; 530872b676d7Smrg default: 530972b676d7Smrg pSiS->VBFlags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA); 531072b676d7Smrg } 531172b676d7Smrg 531272b676d7Smrg /* Setup gamma (the cmap layer needs this to be initialised) */ 531372b676d7Smrg /* (Do this after evaluating options) */ 531472b676d7Smrg { 531572b676d7Smrg Gamma zeros = {0.0, 0.0, 0.0}; 531672b676d7Smrg xf86SetGamma(pScrn, zeros); 531772b676d7Smrg } 531872b676d7Smrg 531972b676d7Smrg#ifdef SISDUALHEAD 532072b676d7Smrg if((!pSiS->DualHeadMode) || (pSiS->SecondHead)) { 532172b676d7Smrg#endif 532272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, pSiS->CRT1gammaGiven ? X_CONFIG : X_INFO, 532372b676d7Smrg "%samma correction is %s\n", 532472b676d7Smrg (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) ? "CRT1 g" : "G", 532572b676d7Smrg pSiS->CRT1gamma ? "enabled" : "disabled"); 532672b676d7Smrg 532772b676d7Smrg if((pSiS->VGAEngine == SIS_315_VGA) && 532872b676d7Smrg (!(pSiS->NoXvideo)) && 532972b676d7Smrg (!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY))) { 533072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, pSiS->XvGammaGiven ? X_CONFIG : X_INFO, 533172b676d7Smrg "Separate Xv gamma correction %sis %s\n", 533272b676d7Smrg (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) ? "for CRT1 " : "", 533372b676d7Smrg pSiS->XvGamma ? "enabled" : "disabled"); 533472b676d7Smrg if(pSiS->XvGamma) { 533572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, pSiS->XvGammaGiven ? X_CONFIG : X_INFO, 533672b676d7Smrg "Xv gamma correction: %.3f %.3f %.3f\n", 533772b676d7Smrg (float)((float)pSiS->XvGammaRed / 1000), 533872b676d7Smrg (float)((float)pSiS->XvGammaGreen / 1000), 533972b676d7Smrg (float)((float)pSiS->XvGammaBlue / 1000)); 534072b676d7Smrg if(!pSiS->CRT1gamma) { 534172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 534272b676d7Smrg "Xv gamma correction requires %samma correction enabled\n", 534372b676d7Smrg (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) ? "CRT1 g" : "G"); 534472b676d7Smrg } 534572b676d7Smrg } 534672b676d7Smrg } 534772b676d7Smrg#ifdef SISDUALHEAD 534872b676d7Smrg } 534972b676d7Smrg#endif 535072b676d7Smrg 535172b676d7Smrg#ifdef SISDUALHEAD 535272b676d7Smrg if(pSiS->DualHeadMode) pSiS->CRT2SepGamma = FALSE; 535372b676d7Smrg#endif 535472b676d7Smrg 535572b676d7Smrg#ifdef SISDUALHEAD 535672b676d7Smrg if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) 535772b676d7Smrg#endif 535872b676d7Smrg { 535972b676d7Smrg Bool isDH = FALSE; 536072b676d7Smrg if(pSiS->CRT2gamma) { 536172b676d7Smrg if( ((pSiS->VGAEngine != SIS_300_VGA) && (pSiS->VGAEngine != SIS_315_VGA)) || 536272b676d7Smrg (!(pSiS->VBFlags2 & VB2_SISBRIDGE)) ) { 536372b676d7Smrg if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 536472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 536572b676d7Smrg "CRT2 gamma correction not supported by hardware\n"); 536672b676d7Smrg } 536772b676d7Smrg pSiS->CRT2gamma = pSiS->CRT2SepGamma = FALSE; 536872b676d7Smrg } else if((pSiS->VBFlags2 & VB2_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) { 536972b676d7Smrg isDH = TRUE; 537072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 537172b676d7Smrg "CRT2 gamma correction not supported for LCD\n"); 537272b676d7Smrg /* But leave it on, will be caught in LoadPalette */ 537372b676d7Smrg } 537472b676d7Smrg } 537572b676d7Smrg if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 537672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CRT2 gamma correction is %s%s%s\n", 537772b676d7Smrg pSiS->CRT2gamma ? "enabled" : "disabled", 537872b676d7Smrg isDH ? " (for TV and VGA2) " : "", 537972b676d7Smrg pSiS->CRT2SepGamma ? " (separate from CRT1)" : ""); 538072b676d7Smrg } 538172b676d7Smrg } 538272b676d7Smrg 538372b676d7Smrg /* Eventually overrule TV Type (SVIDEO, COMPOSITE, SCART, HIVISION, YPBPR) */ 538472b676d7Smrg if(pSiS->VBFlags2 & VB2_SISTVBRIDGE) { 538572b676d7Smrg if(pSiS->ForceTVType != -1) { 538672b676d7Smrg pSiS->VBFlags &= ~(TV_INTERFACE); 538772b676d7Smrg if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) { 538872b676d7Smrg pSiS->VBFlags &= ~(TV_CHSCART | TV_CHYPBPR525I); 538972b676d7Smrg } 539072b676d7Smrg pSiS->VBFlags |= pSiS->ForceTVType; 539172b676d7Smrg if(pSiS->VBFlags & TV_YPBPR) { 539272b676d7Smrg pSiS->VBFlags &= ~(TV_STANDARD); 539372b676d7Smrg pSiS->VBFlags &= ~(TV_YPBPRAR); 539472b676d7Smrg pSiS->VBFlags |= pSiS->ForceYPbPrType; 539572b676d7Smrg pSiS->VBFlags |= pSiS->ForceYPbPrAR; 539672b676d7Smrg } 539772b676d7Smrg } 539872b676d7Smrg } 539972b676d7Smrg 540072b676d7Smrg /* Handle ForceCRT1 option (part 2) */ 540172b676d7Smrg pSiS->CRT1changed = FALSE; 540272b676d7Smrg if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 540372b676d7Smrg usScratchCR17 = pSiS->oldCR17; 540472b676d7Smrg usScratchCR63 = pSiS->oldCR63; 540572b676d7Smrg usScratchSR1F = pSiS->oldSR1F; 540672b676d7Smrg usScratchCR32 = pSiS->postVBCR32; 540772b676d7Smrg if(pSiS->VESA != 1) { 540872b676d7Smrg /* Copy forceCRT1 option to CRT1off if option is given */ 540972b676d7Smrg#ifdef SISDUALHEAD 541072b676d7Smrg /* In DHM, handle this option only for master head, not the slave */ 541172b676d7Smrg if( (pSiS->forceCRT1 != -1) && 541272b676d7Smrg (!(pSiS->DualHeadMode && pSiS->SecondHead)) ) { 541372b676d7Smrg#else 541472b676d7Smrg if(pSiS->forceCRT1 != -1) { 541572b676d7Smrg#endif 541672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 541772b676d7Smrg "CRT1 detection overruled by ForceCRT1 option\n"); 541872b676d7Smrg if(pSiS->forceCRT1) { 541972b676d7Smrg pSiS->CRT1off = 0; 542072b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 542172b676d7Smrg if(!(usScratchCR17 & 0x80)) pSiS->CRT1changed = TRUE; 542272b676d7Smrg } else { 542372b676d7Smrg if(usScratchCR63 & 0x40) pSiS->CRT1changed = TRUE; 542472b676d7Smrg } 542572b676d7Smrg usScratchCR17 |= 0x80; 542672b676d7Smrg usScratchCR32 |= 0x20; 542772b676d7Smrg usScratchCR63 &= ~0x40; 542872b676d7Smrg usScratchSR1F &= ~0xc0; 542972b676d7Smrg } else { 543072b676d7Smrg if( ! ( (pScrn->bitsPerPixel == 8) && 543172b676d7Smrg ( (pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) || 543272b676d7Smrg ((pSiS->VBFlags2 & VB2_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) ) ) ) { 543372b676d7Smrg pSiS->CRT1off = 1; 543472b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 543572b676d7Smrg if(usScratchCR17 & 0x80) pSiS->CRT1changed = TRUE; 543672b676d7Smrg } else { 543772b676d7Smrg if(!(usScratchCR63 & 0x40)) pSiS->CRT1changed = TRUE; 543872b676d7Smrg } 543972b676d7Smrg usScratchCR32 &= ~0x20; 544072b676d7Smrg /* We must not actually switch off CRT1 before we changed the mode! */ 544172b676d7Smrg } 544272b676d7Smrg } 544372b676d7Smrg /* Here we can write to CR17 even on 315 series as we only ENABLE 544472b676d7Smrg * the bit here 544572b676d7Smrg */ 544672b676d7Smrg outSISIDXREG(SISCR, 0x17, usScratchCR17); 544772b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 544872b676d7Smrg outSISIDXREG(SISCR, pSiS->myCR63, usScratchCR63); 544972b676d7Smrg } 545072b676d7Smrg outSISIDXREG(SISCR, 0x32, usScratchCR32); 545172b676d7Smrg if(pSiS->CRT1changed) { 545272b676d7Smrg outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 545372b676d7Smrg usleep(10000); 545472b676d7Smrg outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 545572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 545672b676d7Smrg "CRT1 status changed by ForceCRT1 option\n"); 545772b676d7Smrg } 545872b676d7Smrg outSISIDXREG(SISSR, 0x1f, usScratchSR1F); 545972b676d7Smrg } 546072b676d7Smrg } 546172b676d7Smrg /* Store the new VB connection register contents for later mode changes */ 546272b676d7Smrg pSiS->newCR32 = usScratchCR32; 546372b676d7Smrg } 546472b676d7Smrg 546572b676d7Smrg /* Check if CRT1 used (or needed; this eg. if no CRT2 detected) */ 546672b676d7Smrg if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 546772b676d7Smrg 546872b676d7Smrg /* No CRT2 output? Then we NEED CRT1! 546972b676d7Smrg * We also need CRT1 if depth = 8 and bridge=LVDS|301B-DH 547072b676d7Smrg */ 547172b676d7Smrg if( (!(pSiS->VBFlags & (CRT2_VGA | CRT2_LCD | CRT2_TV))) || 547272b676d7Smrg ( (pScrn->bitsPerPixel == 8) && 547372b676d7Smrg ( (pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) || 547472b676d7Smrg ((pSiS->VBFlags2 & VB2_30xBDH) && (pSiS->VBFlags & CRT2_LCD)) ) ) ) { 547572b676d7Smrg pSiS->CRT1off = 0; 547672b676d7Smrg } 547772b676d7Smrg /* No CRT2 output? Then we can't use Xv on CRT2 */ 547872b676d7Smrg if(!(pSiS->VBFlags & (CRT2_VGA | CRT2_LCD | CRT2_TV))) { 547972b676d7Smrg pSiS->XvOnCRT2 = FALSE; 548072b676d7Smrg } 548172b676d7Smrg 548272b676d7Smrg } else { /* no video bridge? */ 548372b676d7Smrg /* Then we NEED CRT1... */ 548472b676d7Smrg pSiS->CRT1off = 0; 548572b676d7Smrg /* ... and can't use CRT2 for Xv output */ 548672b676d7Smrg pSiS->XvOnCRT2 = FALSE; 548772b676d7Smrg } 548872b676d7Smrg 548972b676d7Smrg /* LCDA? Then we don't switch off CRT1 */ 549072b676d7Smrg if(pSiS->VBFlags & CRT1_LCDA) pSiS->CRT1off = 0; 549172b676d7Smrg 549272b676d7Smrg /* Handle TVStandard option */ 549372b676d7Smrg if((pSiS->NonDefaultPAL != -1) || (pSiS->NonDefaultNTSC != -1)) { 549472b676d7Smrg if( (!(pSiS->VBFlags2 & VB2_SISTVBRIDGE)) && 549572b676d7Smrg (!((pSiS->VBFlags2 & VB2_CHRONTEL)) && (pSiS->ChrontelType == CHRONTEL_701x)) ) { 549672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 549772b676d7Smrg "PALM, PALN and NTSCJ not supported on this hardware\n"); 549872b676d7Smrg pSiS->NonDefaultPAL = pSiS->NonDefaultNTSC = -1; 549972b676d7Smrg pSiS->VBFlags &= ~(TV_PALN | TV_PALM | TV_NTSCJ); 550072b676d7Smrg pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTPALMN | SiS_SD_SUPPORTNTSCJ); 550172b676d7Smrg } 550272b676d7Smrg } 550372b676d7Smrg if(pSiS->OptTVStand != -1) { 550472b676d7Smrg if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 550572b676d7Smrg if( (!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & (TV_CHSCART | TV_CHYPBPR525I)))) && 550672b676d7Smrg (!(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR))) ) { 550772b676d7Smrg pSiS->VBFlags &= ~(TV_PAL | TV_NTSC | TV_PALN | TV_PALM | TV_NTSCJ); 550872b676d7Smrg if(pSiS->OptTVStand) { 550972b676d7Smrg pSiS->VBFlags |= TV_PAL; 551072b676d7Smrg if(pSiS->NonDefaultPAL == 1) pSiS->VBFlags |= TV_PALM; 551172b676d7Smrg else if(!pSiS->NonDefaultPAL) pSiS->VBFlags |= TV_PALN; 551272b676d7Smrg } else { 551372b676d7Smrg pSiS->VBFlags |= TV_NTSC; 551472b676d7Smrg if(pSiS->NonDefaultNTSC == 1) pSiS->VBFlags |= TV_NTSCJ; 551572b676d7Smrg } 551672b676d7Smrg } else { 551772b676d7Smrg pSiS->OptTVStand = pSiS->NonDefaultPAL = -1; 551872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 551972b676d7Smrg "Option TVStandard ignored for YPbPr, HiVision and Chrontel-SCART\n"); 552072b676d7Smrg } 552172b676d7Smrg } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { 552272b676d7Smrg pSiS->SiS6326Flags &= ~SIS6326_TVPAL; 552372b676d7Smrg if(pSiS->OptTVStand) pSiS->SiS6326Flags |= SIS6326_TVPAL; 552472b676d7Smrg } 552572b676d7Smrg } 552672b676d7Smrg 552772b676d7Smrg if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 552872b676d7Smrg /* Default to PAL */ 552972b676d7Smrg if(pSiS->VBFlags & (TV_SVIDEO | TV_AVIDEO)) { 553072b676d7Smrg if(!(pSiS->VBFlags & (TV_PAL | TV_NTSC))) { 553172b676d7Smrg pSiS->VBFlags &= ~(TV_PAL | TV_NTSC | TV_PALN | TV_PALM | TV_NTSCJ); 553272b676d7Smrg pSiS->VBFlags |= TV_PAL; 553372b676d7Smrg } 553472b676d7Smrg } 553572b676d7Smrg /* SCART only supported for PAL */ 553672b676d7Smrg if((pSiS->VBFlags2 & VB2_SISBRIDGE) && (pSiS->VBFlags & TV_SCART)) { 553772b676d7Smrg pSiS->VBFlags &= ~(TV_NTSC | TV_PALN | TV_PALM | TV_NTSCJ); 553872b676d7Smrg pSiS->VBFlags |= TV_PAL; 553972b676d7Smrg pSiS->OptTVStand = 1; 554072b676d7Smrg pSiS->NonDefaultPAL = pSiS->NonDefaultNTSC = -1; 554172b676d7Smrg } 554272b676d7Smrg } 554372b676d7Smrg 554472b676d7Smrg#ifdef SIS_CP 554572b676d7Smrg SIS_CP_DRIVER_RECONFIGOPT 554672b676d7Smrg#endif 554772b676d7Smrg 554872b676d7Smrg if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 554972b676d7Smrg if(pSiS->sis6326tvplug != -1) { 555072b676d7Smrg pSiS->SiS6326Flags &= ~(SIS6326_TVSVIDEO | SIS6326_TVCVBS); 555172b676d7Smrg pSiS->SiS6326Flags |= SIS6326_TVDETECTED; 555272b676d7Smrg if(pSiS->sis6326tvplug == 1) pSiS->SiS6326Flags |= SIS6326_TVCVBS; 555372b676d7Smrg else pSiS->SiS6326Flags |= SIS6326_TVSVIDEO; 555472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 555572b676d7Smrg "SiS6326 TV plug type detection overruled by %s\n", 555672b676d7Smrg (pSiS->SiS6326Flags & SIS6326_TVCVBS) ? "COMPOSITE" : "SVIDEO"); 555772b676d7Smrg } 555872b676d7Smrg } 555972b676d7Smrg 556072b676d7Smrg /* Do some checks */ 556172b676d7Smrg if(pSiS->OptTVOver != -1) { 556272b676d7Smrg if(pSiS->VBFlags2 & VB2_CHRONTEL) { 556372b676d7Smrg pSiS->UseCHOverScan = pSiS->OptTVOver; 556472b676d7Smrg } else { 556572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 556672b676d7Smrg "CHTVOverscan only supported on CHRONTEL 70xx\n"); 556772b676d7Smrg pSiS->UseCHOverScan = -1; 556872b676d7Smrg } 556972b676d7Smrg } else pSiS->UseCHOverScan = -1; 557072b676d7Smrg 557172b676d7Smrg if(pSiS->sistvedgeenhance != -1) { 557272b676d7Smrg if(!(pSiS->VBFlags2 & VB2_301)) { 557372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 557472b676d7Smrg "SISTVEdgeEnhance only supported on SiS301\n"); 557572b676d7Smrg pSiS->sistvedgeenhance = -1; 557672b676d7Smrg } 557772b676d7Smrg } 557872b676d7Smrg if(pSiS->sistvsaturation != -1) { 557972b676d7Smrg if(pSiS->VBFlags2 & VB2_301) { 558072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 558172b676d7Smrg "SISTVSaturation not supported on SiS301\n"); 558272b676d7Smrg pSiS->sistvsaturation = -1; 558372b676d7Smrg } 558472b676d7Smrg } 558572b676d7Smrg 558672b676d7Smrg /* Do some MergedFB mode initialisation */ 558772b676d7Smrg#ifdef SISMERGED 558872b676d7Smrg if(pSiS->MergedFB) { 55895788ca14Smrg pSiS->CRT2pScrn = malloc(sizeof(ScrnInfoRec)); 559072b676d7Smrg if(!pSiS->CRT2pScrn) { 559172b676d7Smrg SISErrorLog(pScrn, "Failed to allocate memory for 2nd pScrn, %s\n", mergeddisstr); 559272b676d7Smrg pSiS->MergedFB = FALSE; 559372b676d7Smrg } else { 559472b676d7Smrg memcpy(pSiS->CRT2pScrn, pScrn, sizeof(ScrnInfoRec)); 559572b676d7Smrg } 559672b676d7Smrg } 559772b676d7Smrg#endif 559872b676d7Smrg 559972b676d7Smrg /* Determine CRT1<>CRT2 mode 560072b676d7Smrg * Note: When using VESA or if the bridge is in slavemode, display 560172b676d7Smrg * is ALWAYS in MIRROR_MODE! 560272b676d7Smrg * This requires extra checks in functions using this flag! 560372b676d7Smrg * (see sis_video.c for example) 560472b676d7Smrg */ 560572b676d7Smrg if(pSiS->VBFlags & DISPTYPE_DISP2) { 560672b676d7Smrg if(pSiS->CRT1off) { /* CRT2 only ------------------------------- */ 560772b676d7Smrg#ifdef SISDUALHEAD 560872b676d7Smrg if(pSiS->DualHeadMode) { 560972b676d7Smrg SISErrorLog(pScrn, 561072b676d7Smrg "CRT1 not detected or forced off. Dual Head mode can't initialize.\n"); 561172b676d7Smrg if(pSiSEnt) pSiSEnt->DisableDual = TRUE; 561272b676d7Smrg goto my_error_1; 561372b676d7Smrg } 561472b676d7Smrg#endif 561572b676d7Smrg#ifdef SISMERGED 561672b676d7Smrg if(pSiS->MergedFB) { 561772b676d7Smrg if(pSiS->MergedFBAuto) { 561872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, mergednocrt1, mergeddisstr); 561972b676d7Smrg } else { 562072b676d7Smrg SISErrorLog(pScrn, mergednocrt1, mergeddisstr); 562172b676d7Smrg } 56225788ca14Smrg if(pSiS->CRT2pScrn) free(pSiS->CRT2pScrn); 562372b676d7Smrg pSiS->CRT2pScrn = NULL; 562472b676d7Smrg pSiS->MergedFB = FALSE; 562572b676d7Smrg } 562672b676d7Smrg#endif 562772b676d7Smrg pSiS->VBFlags |= VB_DISPMODE_SINGLE; 562872b676d7Smrg /* No CRT1? Then we use the video overlay on CRT2 */ 562972b676d7Smrg pSiS->XvOnCRT2 = TRUE; 563072b676d7Smrg } else /* CRT1 and CRT2 - mirror or dual head ----- */ 563172b676d7Smrg#ifdef SISDUALHEAD 563272b676d7Smrg if(pSiS->DualHeadMode) { 563372b676d7Smrg pSiS->VBFlags |= (VB_DISPMODE_DUAL | DISPTYPE_CRT1); 563472b676d7Smrg if(pSiS->VESA != -1) { 563572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 563672b676d7Smrg "VESA option not used in Dual Head mode. VESA disabled.\n"); 563772b676d7Smrg } 563872b676d7Smrg if(pSiSEnt) pSiSEnt->DisableDual = FALSE; 563972b676d7Smrg pSiS->VESA = 0; 564072b676d7Smrg } else 564172b676d7Smrg#endif 564272b676d7Smrg#ifdef SISMERGED 564372b676d7Smrg if(pSiS->MergedFB) { 564472b676d7Smrg pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_CRT1); 564572b676d7Smrg if(pSiS->VESA != -1) { 564672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 564772b676d7Smrg "VESA option not used in MergedFB mode. VESA disabled.\n"); 564872b676d7Smrg } 564972b676d7Smrg pSiS->VESA = 0; 565072b676d7Smrg } else 565172b676d7Smrg#endif 565272b676d7Smrg pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_CRT1); 565372b676d7Smrg } else { /* CRT1 only ------------------------------- */ 565472b676d7Smrg#ifdef SISDUALHEAD 565572b676d7Smrg if(pSiS->DualHeadMode) { 565672b676d7Smrg SISErrorLog(pScrn, 565772b676d7Smrg "No CRT2 output selected or no bridge detected. " 565872b676d7Smrg "Dual Head mode can't initialize.\n"); 565972b676d7Smrg goto my_error_1; 566072b676d7Smrg } 566172b676d7Smrg#endif 566272b676d7Smrg#ifdef SISMERGED 566372b676d7Smrg if(pSiS->MergedFB) { 566472b676d7Smrg if(pSiS->MergedFBAuto) { 566572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, mergednocrt2, mergeddisstr); 566672b676d7Smrg } else { 566772b676d7Smrg SISErrorLog(pScrn, mergednocrt2, mergeddisstr); 566872b676d7Smrg } 56695788ca14Smrg if(pSiS->CRT2pScrn) free(pSiS->CRT2pScrn); 567072b676d7Smrg pSiS->CRT2pScrn = NULL; 567172b676d7Smrg pSiS->MergedFB = FALSE; 567272b676d7Smrg } 567372b676d7Smrg#endif 567472b676d7Smrg pSiS->VBFlags |= (VB_DISPMODE_SINGLE | DISPTYPE_CRT1); 567572b676d7Smrg } 567672b676d7Smrg 567772b676d7Smrg if((pSiS->VGAEngine == SIS_315_VGA) || (pSiS->VGAEngine == SIS_300_VGA)) { 567872b676d7Smrg if((!pSiS->NoXvideo) && 567972b676d7Smrg (!pSiS->hasTwoOverlays) && 568072b676d7Smrg (!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY))) { 568172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, from, 568272b676d7Smrg "Using Xv overlay by default on CRT%d\n", 568372b676d7Smrg pSiS->XvOnCRT2 ? 2 : 1); 568472b676d7Smrg } 568572b676d7Smrg } 568672b676d7Smrg 568772b676d7Smrg /* Init ptrs for Save/Restore functions and calc MaxClock */ 568872b676d7Smrg SISDACPreInit(pScrn); 568972b676d7Smrg 569072b676d7Smrg /* ********** end of VBFlags setup ********** */ 569172b676d7Smrg 569272b676d7Smrg /* VBFlags are initialized now. Back them up for SlaveMode modes. */ 569372b676d7Smrg pSiS->VBFlags_backup = pSiS->VBFlags; 569472b676d7Smrg 569572b676d7Smrg /* Backup CR32,36,37 (in order to write them back after a VT switch) */ 569672b676d7Smrg if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 569772b676d7Smrg inSISIDXREG(SISCR,0x32,pSiS->myCR32); 569872b676d7Smrg inSISIDXREG(SISCR,0x36,pSiS->myCR36); 569972b676d7Smrg inSISIDXREG(SISCR,0x37,pSiS->myCR37); 570072b676d7Smrg } 570172b676d7Smrg 570272b676d7Smrg /* Find out about paneldelaycompensation and evaluate option */ 570372b676d7Smrg#ifdef SISDUALHEAD 570472b676d7Smrg if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) { 570572b676d7Smrg#endif 570672b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 570772b676d7Smrg 570872b676d7Smrg if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) { 570972b676d7Smrg 571072b676d7Smrg /* Save the current PDC if the panel is used at the moment. 571172b676d7Smrg * This seems by far the safest way to find out about it. 571272b676d7Smrg * If the system is using an old version of sisfb, we can't 571372b676d7Smrg * trust the pdc register value. If sisfb saved the pdc for 571472b676d7Smrg * us, use it. 571572b676d7Smrg */ 571672b676d7Smrg if(pSiS->sisfbpdc != 0xff) { 571772b676d7Smrg pSiS->SiS_Pr->PDC = pSiS->sisfbpdc; 571872b676d7Smrg } else { 571972b676d7Smrg if(!(pSiS->donttrustpdc)) { 572072b676d7Smrg UChar tmp; 572172b676d7Smrg inSISIDXREG(SISCR, 0x30, tmp); 572272b676d7Smrg if(tmp & 0x20) { 572372b676d7Smrg inSISIDXREG(SISPART1, 0x13, pSiS->SiS_Pr->PDC); 572472b676d7Smrg } else { 572572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 572672b676d7Smrg "Unable to detect LCD PanelDelayCompensation, LCD is not active\n"); 572772b676d7Smrg } 572872b676d7Smrg } else { 572972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 573072b676d7Smrg "Unable to detect LCD PanelDelayCompensation, please update sisfb\n"); 573172b676d7Smrg } 573272b676d7Smrg } 573372b676d7Smrg if(pSiS->SiS_Pr->PDC != -1) { 573472b676d7Smrg pSiS->SiS_Pr->PDC &= 0x3c; 573572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 573672b676d7Smrg "Detected LCD PanelDelayCompensation 0x%02x\n", 573772b676d7Smrg pSiS->SiS_Pr->PDC); 573872b676d7Smrg } 573972b676d7Smrg 574072b676d7Smrg /* If we haven't been able to find out, use our other methods */ 574172b676d7Smrg if(pSiS->SiS_Pr->PDC == -1) { 574272b676d7Smrg int i=0; 574372b676d7Smrg do { 57441fd23544Smrg if(mypdctable[i].subsysVendor == PCI_SUB_VENDOR_ID(pSiS->PciInfo) && 57451fd23544Smrg mypdctable[i].subsysCard == PCI_SUB_DEVICE_ID(pSiS->PciInfo)) { 574672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 574772b676d7Smrg "PCI card/vendor identified for non-default PanelDelayCompensation\n"); 574872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 574972b676d7Smrg "Vendor: %s, card: %s (ID %04x), PanelDelayCompensation: 0x%02x\n", 575072b676d7Smrg mypdctable[i].vendorName, mypdctable[i].cardName, 57511fd23544Smrg PCI_SUB_DEVICE_ID(pSiS->PciInfo), mypdctable[i].pdc); 575272b676d7Smrg if(pSiS->PDC == -1) { 575372b676d7Smrg pSiS->PDC = mypdctable[i].pdc; 575472b676d7Smrg } else { 575572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 575672b676d7Smrg "PanelDelayCompensation overruled by option\n"); 575772b676d7Smrg } 575872b676d7Smrg break; 575972b676d7Smrg } 576072b676d7Smrg i++; 576172b676d7Smrg } while(mypdctable[i].subsysVendor != 0); 576272b676d7Smrg } 576372b676d7Smrg 576472b676d7Smrg if(pSiS->PDC != -1) { 576572b676d7Smrg if(pSiS->BIOS) { 576672b676d7Smrg if(pSiS->VBFlags2 & VB2_LVDS) { 576772b676d7Smrg if(pSiS->BIOS[0x220] & 0x80) { 576872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 576972b676d7Smrg "BIOS uses OEM LCD Panel Delay Compensation 0x%02x\n", 577072b676d7Smrg pSiS->BIOS[0x220] & 0x3c); 577172b676d7Smrg pSiS->BIOS[0x220] &= 0x7f; 577272b676d7Smrg } 577372b676d7Smrg } 577472b676d7Smrg if(pSiS->VBFlags2 & (VB2_301B | VB2_302B)) { 577572b676d7Smrg if(pSiS->BIOS[0x220] & 0x80) { 577672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 577772b676d7Smrg "BIOS uses OEM LCD Panel Delay Compensation 0x%02x\n", 577872b676d7Smrg ( (pSiS->VBLCDFlags & VB_LCD_1280x1024) ? 577972b676d7Smrg pSiS->BIOS[0x223] : pSiS->BIOS[0x224] ) & 0x3c); 578072b676d7Smrg pSiS->BIOS[0x220] &= 0x7f; 578172b676d7Smrg } 578272b676d7Smrg } 578372b676d7Smrg } 578472b676d7Smrg pSiS->SiS_Pr->PDC = (pSiS->PDC & 0x3c); 578572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 578672b676d7Smrg "Using LCD Panel Delay Compensation 0x%02x\n", pSiS->SiS_Pr->PDC); 578772b676d7Smrg } 578872b676d7Smrg } 578972b676d7Smrg 579072b676d7Smrg } /* SIS_300_VGA */ 579172b676d7Smrg 579272b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 579372b676d7Smrg 579472b676d7Smrg UChar tmp, tmp2; 579572b676d7Smrg inSISIDXREG(SISCR, 0x30, tmp); 579672b676d7Smrg 579772b676d7Smrg /* Save the current PDC if the panel is used at the moment. */ 579872b676d7Smrg if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) { 579972b676d7Smrg 580072b676d7Smrg if(pSiS->sisfbpdc != 0xff) { 580172b676d7Smrg pSiS->SiS_Pr->PDC = pSiS->sisfbpdc; 580272b676d7Smrg } 580372b676d7Smrg if(pSiS->sisfbpdca != 0xff) { 580472b676d7Smrg pSiS->SiS_Pr->PDCA = pSiS->sisfbpdca; 580572b676d7Smrg } 580672b676d7Smrg 580772b676d7Smrg if(!pSiS->donttrustpdc) { 580872b676d7Smrg if((pSiS->sisfbpdc == 0xff) && (pSiS->sisfbpdca == 0xff)) { 580972b676d7Smrg CARD16 tempa, tempb; 581072b676d7Smrg inSISIDXREG(SISPART1,0x2d,tmp2); 581172b676d7Smrg tempa = (tmp2 & 0xf0) >> 3; 581272b676d7Smrg tempb = (tmp2 & 0x0f) << 1; 581372b676d7Smrg inSISIDXREG(SISPART1,0x20,tmp2); 581472b676d7Smrg tempa |= ((tmp2 & 0x40) >> 6); 581572b676d7Smrg inSISIDXREG(SISPART1,0x35,tmp2); 581672b676d7Smrg tempb |= ((tmp2 & 0x80) >> 7); 581772b676d7Smrg inSISIDXREG(SISPART1,0x13,tmp2); 581872b676d7Smrg if(!pSiS->ROM661New) { 581972b676d7Smrg if((tmp2 & 0x04) || (tmp & 0x20)) { 582072b676d7Smrg pSiS->SiS_Pr->PDCA = tempa; 582172b676d7Smrg pSiS->SiS_Pr->PDC = tempb; 582272b676d7Smrg } else { 582372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 582472b676d7Smrg "Unable to detect PanelDelayCompensation, LCD is not active\n"); 582572b676d7Smrg } 582672b676d7Smrg } else { 582772b676d7Smrg if(tmp2 & 0x04) { 582872b676d7Smrg pSiS->SiS_Pr->PDCA = tempa; 582972b676d7Smrg } else if(tmp & 0x20) { 583072b676d7Smrg pSiS->SiS_Pr->PDC = tempb; 583172b676d7Smrg } else { 583272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 583372b676d7Smrg "Unable to detect PanelDelayCompensation, LCD is not active\n"); 583472b676d7Smrg } 583572b676d7Smrg } 583672b676d7Smrg } 583772b676d7Smrg } else { 583872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 583972b676d7Smrg "Unable to detect PanelDelayCompensation, please update sisfb\n"); 584072b676d7Smrg } 584172b676d7Smrg if(pSiS->SiS_Pr->PDC != -1) { 584272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 584372b676d7Smrg "Detected LCD PanelDelayCompensation 0x%02x (for LCD=CRT2)\n", 584472b676d7Smrg pSiS->SiS_Pr->PDC); 584572b676d7Smrg } 584672b676d7Smrg if(pSiS->SiS_Pr->PDCA != -1) { 584772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 584872b676d7Smrg "Detected LCD PanelDelayCompensation1 0x%02x (for LCD=CRT1)\n", 584972b676d7Smrg pSiS->SiS_Pr->PDCA); 585072b676d7Smrg } 585172b676d7Smrg } 585272b676d7Smrg 585372b676d7Smrg /* Let user override (for all bridges) */ 585472b676d7Smrg if(pSiS->VBFlags2 & VB2_30xBLV) { 585572b676d7Smrg if(pSiS->PDC != -1) { 585672b676d7Smrg pSiS->SiS_Pr->PDC = pSiS->PDC & 0x1f; 585772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 585872b676d7Smrg "Using LCD PanelDelayCompensation 0x%02x (for LCD=CRT2)\n", 585972b676d7Smrg pSiS->SiS_Pr->PDC); 586072b676d7Smrg } 586172b676d7Smrg if(pSiS->PDCA != -1) { 586272b676d7Smrg pSiS->SiS_Pr->PDCA = pSiS->PDCA & 0x1f; 586372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 586472b676d7Smrg "Using LCD PanelDelayCompensation1 0x%02x (for LCD=CRT1)\n", 586572b676d7Smrg pSiS->SiS_Pr->PDCA); 586672b676d7Smrg } 586772b676d7Smrg } 586872b676d7Smrg 586972b676d7Smrg /* Read the current EMI (if not overruled) */ 587072b676d7Smrg if(pSiS->VBFlags2 & VB2_SISEMIBRIDGE) { 587172b676d7Smrg MessageType from = X_PROBED; 587272b676d7Smrg if(pSiS->EMI != -1) { 587372b676d7Smrg pSiS->SiS_Pr->EMI_30 = (pSiS->EMI >> 24) & 0x60; 587472b676d7Smrg pSiS->SiS_Pr->EMI_31 = (pSiS->EMI >> 16) & 0xff; 587572b676d7Smrg pSiS->SiS_Pr->EMI_32 = (pSiS->EMI >> 8) & 0xff; 587672b676d7Smrg pSiS->SiS_Pr->EMI_33 = pSiS->EMI & 0xff; 587772b676d7Smrg pSiS->SiS_Pr->HaveEMI = pSiS->SiS_Pr->HaveEMILCD = TRUE; 587872b676d7Smrg pSiS->SiS_Pr->OverruleEMI = TRUE; 587972b676d7Smrg from = X_CONFIG; 588072b676d7Smrg } else if((pSiS->sisfbfound) && (pSiS->sisfb_haveemi)) { 588172b676d7Smrg pSiS->SiS_Pr->EMI_30 = pSiS->sisfb_emi30; 588272b676d7Smrg pSiS->SiS_Pr->EMI_31 = pSiS->sisfb_emi31; 588372b676d7Smrg pSiS->SiS_Pr->EMI_32 = pSiS->sisfb_emi32; 588472b676d7Smrg pSiS->SiS_Pr->EMI_33 = pSiS->sisfb_emi33; 588572b676d7Smrg pSiS->SiS_Pr->HaveEMI = TRUE; 588672b676d7Smrg if(pSiS->sisfb_haveemilcd) pSiS->SiS_Pr->HaveEMILCD = TRUE; 588772b676d7Smrg pSiS->SiS_Pr->OverruleEMI = FALSE; 588872b676d7Smrg } else { 588972b676d7Smrg inSISIDXREG(SISPART4, 0x30, pSiS->SiS_Pr->EMI_30); 589072b676d7Smrg inSISIDXREG(SISPART4, 0x31, pSiS->SiS_Pr->EMI_31); 589172b676d7Smrg inSISIDXREG(SISPART4, 0x32, pSiS->SiS_Pr->EMI_32); 589272b676d7Smrg inSISIDXREG(SISPART4, 0x33, pSiS->SiS_Pr->EMI_33); 589372b676d7Smrg pSiS->SiS_Pr->HaveEMI = TRUE; 589472b676d7Smrg if(tmp & 0x20) pSiS->SiS_Pr->HaveEMILCD = TRUE; 589572b676d7Smrg pSiS->SiS_Pr->OverruleEMI = FALSE; 589672b676d7Smrg } 589772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, from, 589872b676d7Smrg "302LV/302ELV: Using EMI 0x%02x%02x%02x%02x%s\n", 589972b676d7Smrg pSiS->SiS_Pr->EMI_30,pSiS->SiS_Pr->EMI_31, 590072b676d7Smrg pSiS->SiS_Pr->EMI_32,pSiS->SiS_Pr->EMI_33, 590172b676d7Smrg pSiS->SiS_Pr->HaveEMILCD ? " (LCD)" : ""); 590272b676d7Smrg } 590372b676d7Smrg 590472b676d7Smrg } /* SIS_315_VGA */ 590572b676d7Smrg#ifdef SISDUALHEAD 590672b676d7Smrg } 590772b676d7Smrg#endif 590872b676d7Smrg 590972b676d7Smrg 591072b676d7Smrg /* In dual head mode, both heads (currently) share the maxxfbmem equally. 591172b676d7Smrg * If memory sharing is done differently, the following has to be changed; 591272b676d7Smrg * the other modules (eg. accel and Xv) use dhmOffset for hardware 591372b676d7Smrg * pointer settings relative to VideoRAM start and won't need to be changed. 591472b676d7Smrg * 591572b676d7Smrg * Addendum: dhmoffset is also used for skipping the UMA area on SiS76x. 591672b676d7Smrg */ 591772b676d7Smrg 591872b676d7Smrg pSiS->dhmOffset = pSiS->FbBaseOffset; 591972b676d7Smrg pSiS->FbAddress += pSiS->dhmOffset; 592072b676d7Smrg 592172b676d7Smrg#ifdef SISDUALHEAD 592272b676d7Smrg if(pSiS->DualHeadMode) { 592372b676d7Smrg pSiS->FbAddress = pSiS->realFbAddress; 592472b676d7Smrg if(!pSiS->SecondHead) { 592572b676d7Smrg /* ===== First head (always CRT2) ===== */ 592672b676d7Smrg /* We use only half of the memory available */ 592772b676d7Smrg pSiS->maxxfbmem /= 2; 592872b676d7Smrg /* dhmOffset is 0 (or LFB-base for SiS76x UMA skipping) */ 592972b676d7Smrg pSiS->FbAddress += pSiS->dhmOffset; 593072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 593172b676d7Smrg "%dKB video RAM at 0x%lx available for master head (CRT2)\n", 593272b676d7Smrg pSiS->maxxfbmem/1024, pSiS->FbAddress); 593372b676d7Smrg } else { 593472b676d7Smrg /* ===== Second head (always CRT1) ===== */ 593572b676d7Smrg /* We use only half of the memory available */ 593672b676d7Smrg pSiS->maxxfbmem /= 2; 593772b676d7Smrg /* Initialize dhmOffset */ 593872b676d7Smrg pSiS->dhmOffset += pSiS->maxxfbmem; 593972b676d7Smrg /* Adapt FBAddress */ 594072b676d7Smrg pSiS->FbAddress += pSiS->dhmOffset; 594172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 594272b676d7Smrg "%dKB video RAM at 0x%lx available for slave head (CRT1)\n", 594372b676d7Smrg pSiS->maxxfbmem/1024, pSiS->FbAddress); 594472b676d7Smrg } 594572b676d7Smrg } 594672b676d7Smrg#endif 594772b676d7Smrg 594872b676d7Smrg /* Note: Do not use availMem for anything from now. Use 594972b676d7Smrg * maxxfbmem instead. (availMem does not take dual head 595072b676d7Smrg * mode into account.) 595172b676d7Smrg */ 595272b676d7Smrg 595372b676d7Smrg if(pSiS->FbBaseOffset) { 595472b676d7Smrg /* Doubt that the DRM memory manager can deal 595572b676d7Smrg * with a heap start of 0... 595672b676d7Smrg */ 595772b676d7Smrg pSiS->DRIheapstart = 16; 595872b676d7Smrg pSiS->DRIheapend = pSiS->FbBaseOffset; 595972b676d7Smrg } else { 596072b676d7Smrg pSiS->DRIheapstart = pSiS->maxxfbmem; 596172b676d7Smrg pSiS->DRIheapend = pSiS->availMem; 596272b676d7Smrg } 596372b676d7Smrg#ifdef SISDUALHEAD 596472b676d7Smrg if(pSiS->DualHeadMode) { 596572b676d7Smrg pSiS->DRIheapstart = pSiS->DRIheapend = 0; 596672b676d7Smrg } else 596772b676d7Smrg#endif 596872b676d7Smrg if(pSiS->DRIheapstart >= pSiS->DRIheapend) { 596972b676d7Smrg#if 0 /* For future use */ 597072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 597172b676d7Smrg "No memory for DRI heap. Please set the option \"MaxXFBMem\" to\n" 597272b676d7Smrg "\tlimit the memory X should use and leave the rest to DRI\n"); 597372b676d7Smrg#endif 597472b676d7Smrg pSiS->DRIheapstart = pSiS->DRIheapend = 0; 597572b676d7Smrg } 597672b676d7Smrg 597772b676d7Smrg /* Now for something completely different: DDC. 597872b676d7Smrg * For 300 and 315/330/340 series, we provide our 597972b676d7Smrg * own functions (in order to probe CRT2 as well) 598072b676d7Smrg * If these fail, use the VBE. 598172b676d7Smrg * All other chipsets will use VBE. No need to re-invent 598272b676d7Smrg * the wheel there. 598372b676d7Smrg */ 598472b676d7Smrg 598572b676d7Smrg pSiS->pVbe = NULL; 598672b676d7Smrg didddc2 = FALSE; 598772b676d7Smrg 598872b676d7Smrg if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 598972b676d7Smrg if(xf86LoadSubModule(pScrn, "ddc")) { 599072b676d7Smrg int crtnum = 0; 599172b676d7Smrg if((pMonitor = SiSDoPrivateDDC(pScrn, &crtnum))) { 599272b676d7Smrg didddc2 = TRUE; 599372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcsstr, crtnum); 599472b676d7Smrg xf86PrintEDID(pMonitor); 599572b676d7Smrg xf86SetDDCproperties(pScrn, pMonitor); 599672b676d7Smrg pScrn->monitor->DDC = pMonitor; 599772b676d7Smrg /* Now try to find out aspect ratio */ 599872b676d7Smrg SiSFindAspect(pScrn, pMonitor, crtnum); 599972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcestr, crtnum); 600072b676d7Smrg } 600172b676d7Smrg } 600272b676d7Smrg } 600372b676d7Smrg 600472b676d7Smrg#ifdef SISDUALHEAD 600572b676d7Smrg /* In dual head mode, probe DDC using VBE only for CRT1 (second head) */ 600672b676d7Smrg if((pSiS->DualHeadMode) && (!didddc2) && (!pSiS->SecondHead)) { 600772b676d7Smrg didddc2 = TRUE; 600872b676d7Smrg } 600972b676d7Smrg#endif 601072b676d7Smrg 601172b676d7Smrg if(!didddc2) { 601272b676d7Smrg /* If CRT1 is off or LCDA, skip DDC via VBE */ 601372b676d7Smrg if((pSiS->CRT1off) || (pSiS->VBFlags & CRT1_LCDA)) { 601472b676d7Smrg didddc2 = TRUE; 601572b676d7Smrg } 601672b676d7Smrg } 601772b676d7Smrg 601872b676d7Smrg /* Now (re-)load and initialize the DDC module */ 601972b676d7Smrg if(!didddc2) { 602072b676d7Smrg 602172b676d7Smrg if(xf86LoadSubModule(pScrn, "ddc")) { 602272b676d7Smrg 602372b676d7Smrg /* Now load and initialize VBE module. */ 602472b676d7Smrg SiS_LoadInitVBE(pScrn); 602572b676d7Smrg 602672b676d7Smrg if(pSiS->pVbe) { 602772b676d7Smrg if((pMonitor = vbeDoEDID(pSiS->pVbe,NULL))) { 602872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 602972b676d7Smrg "VBE CRT1 DDC monitor info:\n"); 603072b676d7Smrg xf86SetDDCproperties(pScrn, xf86PrintEDID(pMonitor)); 603172b676d7Smrg pScrn->monitor->DDC = pMonitor; 603272b676d7Smrg /* Now try to find out aspect ratio */ 603372b676d7Smrg SiSFindAspect(pScrn, pMonitor, 1); 603472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 603572b676d7Smrg "End of VBE CRT1 DDC monitor info\n"); 603672b676d7Smrg } 603772b676d7Smrg } else { 603872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 603972b676d7Smrg "Failed to read DDC data\n"); 604072b676d7Smrg } 604172b676d7Smrg } 604272b676d7Smrg } 604372b676d7Smrg 604472b676d7Smrg#ifdef SISMERGED 604572b676d7Smrg if(pSiS->MergedFB) { 60465788ca14Smrg pSiS->CRT2pScrn->monitor = malloc(sizeof(MonRec)); 604772b676d7Smrg if(pSiS->CRT2pScrn->monitor) { 604872b676d7Smrg DisplayModePtr tempm = NULL, currentm = NULL, newm = NULL; 604972b676d7Smrg memcpy(pSiS->CRT2pScrn->monitor, pScrn->monitor, sizeof(MonRec)); 605072b676d7Smrg pSiS->CRT2pScrn->monitor->DDC = NULL; 605172b676d7Smrg pSiS->CRT2pScrn->monitor->Modes = NULL; 605272b676d7Smrg pSiS->CRT2pScrn->monitor->id = (char *)crt2monname; 605372b676d7Smrg tempm = pScrn->monitor->Modes; 605472b676d7Smrg while(tempm) { 60555788ca14Smrg if(!(newm = malloc(sizeof(DisplayModeRec)))) break; 605672b676d7Smrg memcpy(newm, tempm, sizeof(DisplayModeRec)); 60575788ca14Smrg if(!(newm->name = malloc(strlen(tempm->name) + 1))) { 60585788ca14Smrg free(newm); 605972b676d7Smrg break; 606072b676d7Smrg } 606172b676d7Smrg strcpy(newm->name, tempm->name); 606272b676d7Smrg if(!pSiS->CRT2pScrn->monitor->Modes) pSiS->CRT2pScrn->monitor->Modes = newm; 606372b676d7Smrg if(currentm) { 606472b676d7Smrg currentm->next = newm; 606572b676d7Smrg newm->prev = currentm; 606672b676d7Smrg } 606772b676d7Smrg currentm = newm; 606872b676d7Smrg tempm = tempm->next; 606972b676d7Smrg } 607072b676d7Smrg if(pSiS->CRT2HSync) { 607172b676d7Smrg pSiS->CRT2pScrn->monitor->nHsync = 607272b676d7Smrg SiSStrToRanges(pSiS->CRT2pScrn->monitor->hsync, pSiS->CRT2HSync, MAX_HSYNC); 607372b676d7Smrg } 607472b676d7Smrg if(pSiS->CRT2VRefresh) { 607572b676d7Smrg pSiS->CRT2pScrn->monitor->nVrefresh = 607672b676d7Smrg SiSStrToRanges(pSiS->CRT2pScrn->monitor->vrefresh, pSiS->CRT2VRefresh, MAX_VREFRESH); 607772b676d7Smrg } 607872b676d7Smrg if((pMonitor = SiSInternalDDC(pSiS->CRT2pScrn, 1))) { 607972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcsstr, 2); 608072b676d7Smrg xf86PrintEDID(pMonitor); 608172b676d7Smrg xf86SetDDCproperties(pSiS->CRT2pScrn, pMonitor); 608272b676d7Smrg pSiS->CRT2pScrn->monitor->DDC = pMonitor; 608372b676d7Smrg /* Now try to find out aspect ratio */ 608472b676d7Smrg SiSFindAspect(pScrn, pMonitor, 2); 608572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, ddcestr, 2); 608672b676d7Smrg /* use DDC data if no ranges in config file */ 608772b676d7Smrg if(!pSiS->CRT2HSync) { 608872b676d7Smrg pSiS->CRT2pScrn->monitor->nHsync = 0; 608972b676d7Smrg } 609072b676d7Smrg if(!pSiS->CRT2VRefresh) { 609172b676d7Smrg pSiS->CRT2pScrn->monitor->nVrefresh = 0; 609272b676d7Smrg } 609372b676d7Smrg } else { 609472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 609572b676d7Smrg "Failed to read DDC data for CRT2\n"); 609672b676d7Smrg } 609772b676d7Smrg } else { 609872b676d7Smrg SISErrorLog(pScrn, "Failed to allocate memory for CRT2 monitor, %s.\n", 609972b676d7Smrg mergeddisstr); 61005788ca14Smrg if(pSiS->CRT2pScrn) free(pSiS->CRT2pScrn); 610172b676d7Smrg pSiS->CRT2pScrn = NULL; 610272b676d7Smrg pSiS->MergedFB = FALSE; 610372b676d7Smrg } 610472b676d7Smrg } 610572b676d7Smrg#endif 610672b676d7Smrg 610772b676d7Smrg /* Copy our detected monitor gammas, part 1. Note that device redetection 610872b676d7Smrg * is not supported in DHM, so there is no need to do that anytime later. 610972b676d7Smrg */ 611072b676d7Smrg#ifdef SISDUALHEAD 611172b676d7Smrg if(pSiS->DualHeadMode) { 611272b676d7Smrg if(!pSiS->SecondHead) { 611372b676d7Smrg /* CRT2: Got gamma for LCD or VGA2 */ 611472b676d7Smrg pSiSEnt->CRT2VGAMonitorGamma = pSiS->CRT2VGAMonitorGamma; 611572b676d7Smrg } else { 611672b676d7Smrg /* CRT1: Got gamma for LCD or VGA */ 611772b676d7Smrg pSiSEnt->CRT1VGAMonitorGamma = pSiS->CRT1VGAMonitorGamma; 611872b676d7Smrg } 611972b676d7Smrg if(pSiS->CRT2LCDMonitorGamma) pSiSEnt->CRT2LCDMonitorGamma = pSiS->CRT2LCDMonitorGamma; 612072b676d7Smrg } 612172b676d7Smrg#endif 612272b676d7Smrg 612372b676d7Smrg /* end of DDC */ 612472b676d7Smrg 612572b676d7Smrg /* From here, we mainly deal with clocks and modes */ 612672b676d7Smrg 612772b676d7Smrg#ifdef SISMERGED 612872b676d7Smrg if(pSiS->MergedFB) xf86DrvMsg(pScrn->scrnIndex, X_INFO, crtsetupstr, 1); 612972b676d7Smrg#endif 613072b676d7Smrg 613172b676d7Smrg /* Set the min pixel clock */ 613272b676d7Smrg pSiS->MinClock = 5000; 613372b676d7Smrg if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 613472b676d7Smrg pSiS->MinClock = 10000; 613572b676d7Smrg } 613672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n", 613772b676d7Smrg pSiS->MinClock / 1000); 613872b676d7Smrg 613972b676d7Smrg /* If the user has specified ramdac speed in the config 614072b676d7Smrg * file, we respect that setting. 614172b676d7Smrg */ 614272b676d7Smrg from = X_PROBED; 614372b676d7Smrg if(pSiS->pEnt->device->dacSpeeds[0]) { 614472b676d7Smrg int speed = 0; 614572b676d7Smrg switch(pScrn->bitsPerPixel) { 614672b676d7Smrg case 8: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP8]; 614772b676d7Smrg break; 614872b676d7Smrg case 16: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP16]; 614972b676d7Smrg break; 615072b676d7Smrg case 24: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP24]; 615172b676d7Smrg break; 615272b676d7Smrg case 32: speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP32]; 615372b676d7Smrg break; 615472b676d7Smrg } 615572b676d7Smrg if(speed == 0) pSiS->MaxClock = pSiS->pEnt->device->dacSpeeds[0]; 615672b676d7Smrg else pSiS->MaxClock = speed; 615772b676d7Smrg from = X_CONFIG; 615872b676d7Smrg } 615972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n", 616072b676d7Smrg pSiS->MaxClock / 1000); 616172b676d7Smrg 616272b676d7Smrg /* 616372b676d7Smrg * Setup the ClockRanges, which describe what clock ranges are available, 616472b676d7Smrg * and what sort of modes they can be used for. 616572b676d7Smrg */ 616672b676d7Smrg clockRanges = xnfcalloc(sizeof(ClockRange), 1); 616772b676d7Smrg clockRanges->next = NULL; 616872b676d7Smrg clockRanges->minClock = pSiS->MinClock; 616972b676d7Smrg clockRanges->maxClock = pSiS->MaxClock; 617072b676d7Smrg clockRanges->clockIndex = -1; /* programmable */ 617172b676d7Smrg clockRanges->interlaceAllowed = TRUE; 617272b676d7Smrg clockRanges->doubleScanAllowed = TRUE; 617372b676d7Smrg 617472b676d7Smrg /* 617572b676d7Smrg * Since we have lots of built-in modes for 300/315/330/340 series 617672b676d7Smrg * with vb support, we replace the given default mode list with our 617772b676d7Smrg * own. In case the video bridge is to be used, we only allow other 617872b676d7Smrg * modes if 617972b676d7Smrg * -) vbtype is 301, 301B, 301C or 302B, and 618072b676d7Smrg * -) crt2 device is not TV, and 618172b676d7Smrg * -) crt1 is not LCDA, unless bridge is TMDS/LCDA capable (301C) 618272b676d7Smrg */ 618372b676d7Smrg if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 618472b676d7Smrg if(!(pSiS->noInternalModes)) { 618572b676d7Smrg Bool acceptcustommodes = TRUE; /* Accept user modelines */ 618672b676d7Smrg Bool includelcdmodes = TRUE; /* Include modes reported by DDC */ 618772b676d7Smrg Bool isfordvi = FALSE; /* Is for digital DVI output */ 618872b676d7Smrg Bool fakecrt2modes = FALSE; /* Fake some modes for CRT2 */ 618972b676d7Smrg Bool IsForCRT2 = FALSE; 619072b676d7Smrg if(pSiS->UseVESA) { 619172b676d7Smrg acceptcustommodes = FALSE; 619272b676d7Smrg includelcdmodes = FALSE; 619372b676d7Smrg } 619472b676d7Smrg#ifdef SISDUALHEAD /* Dual head is static. Output devices will not change. */ 619572b676d7Smrg if(pSiS->DualHeadMode) { 619672b676d7Smrg if(!pSiS->SecondHead) { /* CRT2: */ 619772b676d7Smrg if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 619872b676d7Smrg if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 619972b676d7Smrg if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA))) includelcdmodes = FALSE; 620072b676d7Smrg if(pSiS->VBFlags & CRT2_LCD) isfordvi = TRUE; 620172b676d7Smrg if(pSiS->VBFlags & CRT2_TV) acceptcustommodes = FALSE; 620272b676d7Smrg } else { 620372b676d7Smrg if(pSiS->VBFlags & (CRT2_TV|CRT2_LCD)) { 620472b676d7Smrg acceptcustommodes = FALSE; 620572b676d7Smrg includelcdmodes = FALSE; 620672b676d7Smrg fakecrt2modes = TRUE; 620772b676d7Smrg } 620872b676d7Smrg } 620972b676d7Smrg } else { 621072b676d7Smrg acceptcustommodes = FALSE; 621172b676d7Smrg includelcdmodes = FALSE; 621272b676d7Smrg if(pSiS->VBFlags & (CRT2_TV|CRT2_LCD)) { 621372b676d7Smrg fakecrt2modes = TRUE; 621472b676d7Smrg } 621572b676d7Smrg } 621672b676d7Smrg clockRanges->interlaceAllowed = FALSE; 621772b676d7Smrg IsForCRT2 = TRUE; 621872b676d7Smrg } else { /* CRT1: */ 621972b676d7Smrg if(pSiS->VBFlags & CRT1_LCDA) { 622072b676d7Smrg if(!(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 622172b676d7Smrg acceptcustommodes = FALSE; 622272b676d7Smrg includelcdmodes = FALSE; 622372b676d7Smrg fakecrt2modes = TRUE; 622472b676d7Smrg /* Will handle i-lace in mode-switching code */ 622572b676d7Smrg } else { 622672b676d7Smrg isfordvi = TRUE; 622772b676d7Smrg /* Don't allow i-lace modes */ 622872b676d7Smrg clockRanges->interlaceAllowed = FALSE; 622972b676d7Smrg } 623072b676d7Smrg } else { 623172b676d7Smrg includelcdmodes = FALSE; 623272b676d7Smrg } 623372b676d7Smrg } 623472b676d7Smrg } else 623572b676d7Smrg#endif 623672b676d7Smrg#ifdef SISMERGED /* MergedFB mode is not static. Output devices may change. */ 623772b676d7Smrg if(pSiS->MergedFB) { 623872b676d7Smrg if(pSiS->VBFlags & CRT1_LCDA) { 623972b676d7Smrg if(!(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 624072b676d7Smrg acceptcustommodes = FALSE; 624172b676d7Smrg includelcdmodes = FALSE; 624272b676d7Smrg fakecrt2modes = TRUE; 624372b676d7Smrg /* Will handle i-lace in mode-switching code */ 624472b676d7Smrg } else { 624572b676d7Smrg isfordvi = TRUE; 624672b676d7Smrg /* Don't allow i-lace custom modes */ 624772b676d7Smrg clockRanges->interlaceAllowed = FALSE; 624872b676d7Smrg } 624972b676d7Smrg } else { 625072b676d7Smrg includelcdmodes = FALSE; 625172b676d7Smrg } 625272b676d7Smrg } else 625372b676d7Smrg#endif /* Mirror mode is not static. Output devices may change. */ 625472b676d7Smrg if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 625572b676d7Smrg if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 625672b676d7Smrg if(!(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 625772b676d7Smrg if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA))) includelcdmodes = FALSE; 625872b676d7Smrg if(pSiS->VBFlags & CRT2_LCD) isfordvi = TRUE; 625972b676d7Smrg } else { 626072b676d7Smrg if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA|CRT1_LCDA))) includelcdmodes = FALSE; 626172b676d7Smrg if(pSiS->VBFlags & (CRT2_LCD|CRT1_LCDA)) isfordvi = TRUE; 626272b676d7Smrg } 626372b676d7Smrg if((!(pSiS->VBFlags & DISPTYPE_CRT1)) && (!(pSiS->VBFlags & CRT1_LCDA))) { 626472b676d7Smrg IsForCRT2 = TRUE; 626572b676d7Smrg } 626672b676d7Smrg /* Allow user modes, even if CRT2 is TV. Will be filtered through ValidMode(); 626772b676d7Smrg * leaving the user modes here might have the advantage that such a mode, if 626872b676d7Smrg * it matches in resolution with a supported TV mode, allows us to drive eg. 626972b676d7Smrg * non standard panels, and still permits switching to TV. This mode will be 627072b676d7Smrg * "mapped" to a supported mode of identical resolution for TV. All this is 627172b676d7Smrg * taken care of by ValidMode() and ModeInit()/PresetMode(). 627272b676d7Smrg */ 627372b676d7Smrg } else { 627472b676d7Smrg if(pSiS->VBFlags & (CRT2_TV|CRT2_LCD)) { 627572b676d7Smrg acceptcustommodes = FALSE; 627672b676d7Smrg includelcdmodes = FALSE; 627772b676d7Smrg if(!(pSiS->VBFlags & DISPTYPE_CRT1)) { 627872b676d7Smrg fakecrt2modes = TRUE; 627972b676d7Smrg IsForCRT2 = TRUE; 628072b676d7Smrg } 628172b676d7Smrg } 628272b676d7Smrg } 628372b676d7Smrg } else if(pSiS->VBFlags & (CRT2_ENABLE | CRT1_LCDA)) { 628472b676d7Smrg acceptcustommodes = FALSE; 628572b676d7Smrg includelcdmodes = FALSE; 628672b676d7Smrg if((pSiS->VBFlags & CRT1_LCDA) || (!(pSiS->VBFlags & DISPTYPE_CRT1))) { 628772b676d7Smrg fakecrt2modes = TRUE; 628872b676d7Smrg IsForCRT2 = TRUE; 628972b676d7Smrg } 629072b676d7Smrg } else { 629172b676d7Smrg includelcdmodes = FALSE; 629272b676d7Smrg } 629372b676d7Smrg /* Ignore interlace, mode switching code will handle this */ 629472b676d7Smrg 629572b676d7Smrg pSiS->HaveCustomModes = FALSE; 629672b676d7Smrg if(SiSMakeOwnModeList(pScrn, acceptcustommodes, includelcdmodes, 629772b676d7Smrg isfordvi, &pSiS->HaveCustomModes, FALSE /*fakecrt2modes*/, IsForCRT2)) { 629872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 629972b676d7Smrg "Replaced %s mode list with built-in modes\n", 630072b676d7Smrg pSiS->HaveCustomModes ? "default" : "entire"); 630172b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 630272b676d7Smrg int UseWide = pSiS->SiS_Pr->SiS_UseWide; 630372b676d7Smrg if(IsForCRT2) UseWide = pSiS->SiS_Pr->SiS_UseWideCRT2; 630472b676d7Smrg if((!IsForCRT2) || (pSiS->VBFlags2 & VB2_SISVGA2BRIDGE)) { 630572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 630672b676d7Smrg "Using %s widescreen modes for CRT%d VGA devices\n", 630772b676d7Smrg UseWide ? "real" : "fake", IsForCRT2 ? 2 : 1); 630872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 630972b676d7Smrg "\tUse option \"ForceCRT%dVGAAspect\" to overrule\n", 631072b676d7Smrg IsForCRT2 ? 2 : 1); 631172b676d7Smrg } 631272b676d7Smrg } 631372b676d7Smrg#ifdef TWDEBUG 631472b676d7Smrg pScrn->modes = pScrn->monitor->Modes; 631572b676d7Smrg xf86PrintModes(pScrn); 631672b676d7Smrg pScrn->modes = NULL; 631772b676d7Smrg#endif 631872b676d7Smrg } else { 631972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 632072b676d7Smrg "Building list of built-in modes failed, using server defaults\n"); 632172b676d7Smrg } 632272b676d7Smrg } else { 632372b676d7Smrg pSiS->HaveCustomModes = TRUE; 632472b676d7Smrg } 632572b676d7Smrg } 632672b676d7Smrg 632772b676d7Smrg /* Add our built-in hi-res and TV modes on the 6326 */ 632872b676d7Smrg if(pSiS->Chipset == PCI_CHIP_SIS6326) { 632972b676d7Smrg if(pScrn->bitsPerPixel == 8) { 633072b676d7Smrg SiS6326SIS1600x1200_60Mode.next = pScrn->monitor->Modes; 633172b676d7Smrg pScrn->monitor->Modes = &SiS6326SIS1600x1200_60Mode; 633272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 633372b676d7Smrg "Adding mode \"SIS1600x1200-60\" (depth 8 only)\n"); 633472b676d7Smrg } 633572b676d7Smrg if(pScrn->bitsPerPixel <= 16) { 633672b676d7Smrg SiS6326SIS1280x1024_75Mode.next = pScrn->monitor->Modes; 633772b676d7Smrg pScrn->monitor->Modes = &SiS6326SIS1280x1024_75Mode; 633872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 633972b676d7Smrg "Adding mode \"SIS1280x1024-75\" (depths 8, 15 and 16 only)\n"); 634072b676d7Smrg } 634172b676d7Smrg if((pSiS->SiS6326Flags & SIS6326_HASTV) && 634272b676d7Smrg (pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 634372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 634472b676d7Smrg "Adding %s TV modes to mode list:\n", 634572b676d7Smrg (pSiS->SiS6326Flags & SIS6326_TVPAL) ? "PAL" : "NTSC"); 634672b676d7Smrg if(pSiS->SiS6326Flags & SIS6326_TVPAL) { 634772b676d7Smrg SiS6326PAL800x600Mode.next = pScrn->monitor->Modes; 634872b676d7Smrg pScrn->monitor->Modes = &SiS6326PAL640x480Mode; 634972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 635072b676d7Smrg "\t\"PAL800x600\" \"PAL800x600U\" \"PAL720x540\" \"PAL640x480\"\n"); 635172b676d7Smrg } else { 635272b676d7Smrg SiS6326NTSC640x480Mode.next = pScrn->monitor->Modes; 635372b676d7Smrg pScrn->monitor->Modes = &SiS6326NTSC640x400Mode; 635472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 635572b676d7Smrg "\t\"NTSC640x480\" \"NTSC640x480U\" \"NTSC640x400\"\n"); 635672b676d7Smrg } 635772b676d7Smrg } 635872b676d7Smrg } 635972b676d7Smrg 636072b676d7Smrg /* If there is no HSync or VRefresh data for the monitor, 636172b676d7Smrg * derive it from DDC data. Essentially done by common layer 636272b676d7Smrg * since 4.3.99.14, but this is not usable since it is done 636372b676d7Smrg * too late (in ValidateModes()). 636472b676d7Smrg * Addendum: I overrule the ranges now in any case unless 636572b676d7Smrg * it would affect a CRT output device or DDC data is available. 636672b676d7Smrg * Hence, for LCD(A) and TV, we always get proper ranges. This 636772b676d7Smrg * is entirely harmless. However, option "NoOverruleRanges" will 636872b676d7Smrg * disable this behavior. 636972b676d7Smrg * This should "fix" the - by far - most common configuration 637072b676d7Smrg * mistakes. 637172b676d7Smrg */ 637272b676d7Smrg 637372b676d7Smrg crt1freqoverruled = FALSE; 637472b676d7Smrg 637572b676d7Smrg fromDDC = FALSE; 637672b676d7Smrg if((pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 637772b676d7Smrg if((pScrn->monitor->nHsync <= 0) && (pScrn->monitor->DDC)) { 637872b676d7Smrg SiSSetSyncRangeFromEdid(pScrn, 1); 637972b676d7Smrg if(pScrn->monitor->nHsync > 0) { 638072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, subshstr, 638172b676d7Smrg#ifdef SISDUALHEAD 638272b676d7Smrg pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 638372b676d7Smrg#endif 638472b676d7Smrg pSiS->CRT1off ? 2 : 1); 638572b676d7Smrg fromDDC = TRUE; 638672b676d7Smrg } 638772b676d7Smrg } 638872b676d7Smrg if((pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 638972b676d7Smrg if(SiSAllowSyncOverride(pSiS, fromDDC)) { 639072b676d7Smrg Bool HaveNoRanges = (pScrn->monitor->nHsync <= 0); 639172b676d7Smrg /* Set sane ranges for LCD and TV 639272b676d7Smrg * (our strict checking will filter out invalid ones anyway) 639372b676d7Smrg */ 639472b676d7Smrg if((crt1freqoverruled = CheckAndOverruleH(pScrn, pScrn->monitor))) { 639572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, saneh, 639672b676d7Smrg HaveNoRanges ? "missing" : "bogus", 639772b676d7Smrg#ifdef SISDUALHEAD 639872b676d7Smrg pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 639972b676d7Smrg#endif 640072b676d7Smrg pSiS->CRT1off ? 2 : 1); 640172b676d7Smrg } 640272b676d7Smrg } 640372b676d7Smrg } 640472b676d7Smrg } 640572b676d7Smrg 640672b676d7Smrg fromDDC = FALSE; 640772b676d7Smrg if((pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 640872b676d7Smrg if((pScrn->monitor->nVrefresh <= 0) && (pScrn->monitor->DDC)) { 640972b676d7Smrg SiSSetSyncRangeFromEdid(pScrn, 0); 641072b676d7Smrg if(pScrn->monitor->nVrefresh > 0) { 641172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, subsvstr, 641272b676d7Smrg#ifdef SISDUALHEAD 641372b676d7Smrg pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 641472b676d7Smrg#endif 641572b676d7Smrg pSiS->CRT1off ? 2 : 1); 641672b676d7Smrg fromDDC = TRUE; 641772b676d7Smrg } 641872b676d7Smrg } 641972b676d7Smrg if((pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 642072b676d7Smrg if(SiSAllowSyncOverride(pSiS, fromDDC)) { 642172b676d7Smrg Bool HaveNoRanges = (pScrn->monitor->nVrefresh <= 0); 642272b676d7Smrg /* Set sane ranges for LCD and TV */ 642372b676d7Smrg if((crt1freqoverruled = CheckAndOverruleV(pScrn, pScrn->monitor))) { 642472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, sanev, 642572b676d7Smrg HaveNoRanges ? "missing" : "bogus", 642672b676d7Smrg#ifdef SISDUALHEAD 642772b676d7Smrg pSiS->DualHeadMode ? (pSiS->SecondHead ? 1 : 2) : 642872b676d7Smrg#endif 642972b676d7Smrg pSiS->CRT1off ? 2 : 1); 643072b676d7Smrg } 643172b676d7Smrg } 643272b676d7Smrg } 643372b676d7Smrg } 643472b676d7Smrg 643572b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 643672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 643772b676d7Smrg "\"Unknown reason\" in the following list means that the mode\n"); 643872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 643972b676d7Smrg "is not supported on the chipset/bridge/current output device.\n"); 644072b676d7Smrg } 644172b676d7Smrg 644272b676d7Smrg /* 644372b676d7Smrg * xf86ValidateModes will check that the mode HTotal and VTotal values 644472b676d7Smrg * don't exceed the chipset's limit if pScrn->maxHValue and 644572b676d7Smrg * pScrn->maxVValue are set. Since our SISValidMode() already takes 644672b676d7Smrg * care of this, we don't worry about setting them here. 644772b676d7Smrg */ 644872b676d7Smrg 644972b676d7Smrg /* Select valid modes from those available */ 645072b676d7Smrg /* 645172b676d7Smrg * Assuming min pitch 256, min height 128 645272b676d7Smrg */ 645372b676d7Smrg { 645472b676d7Smrg int minpitch, maxpitch, minheight, maxheight; 645572b676d7Smrg pointer backupddc = pScrn->monitor->DDC; 645672b676d7Smrg 645772b676d7Smrg minpitch = 256; 645872b676d7Smrg minheight = 128; 645972b676d7Smrg switch(pSiS->VGAEngine) { 646072b676d7Smrg case SIS_OLD_VGA: 646172b676d7Smrg case SIS_530_VGA: 646272b676d7Smrg maxpitch = 2040; 646372b676d7Smrg maxheight = 2048; 646472b676d7Smrg break; 646572b676d7Smrg case SIS_300_VGA: 646672b676d7Smrg case SIS_315_VGA: 646772b676d7Smrg maxpitch = 4088; 646872b676d7Smrg maxheight = 4096; 646972b676d7Smrg break; 647072b676d7Smrg default: 647172b676d7Smrg maxpitch = 2048; 647272b676d7Smrg maxheight = 2048; 647372b676d7Smrg break; 647472b676d7Smrg } 647572b676d7Smrg 647672b676d7Smrg#ifdef SISMERGED 647772b676d7Smrg pSiS->CheckForCRT2 = FALSE; 647872b676d7Smrg#endif 647972b676d7Smrg 648072b676d7Smrg /* Suppress bogus DDC warning */ 648172b676d7Smrg if(crt1freqoverruled) pScrn->monitor->DDC = NULL; 648272b676d7Smrg 648372b676d7Smrg i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 648472b676d7Smrg pScrn->display->modes, clockRanges, NULL, 648572b676d7Smrg minpitch, maxpitch, 648672b676d7Smrg pScrn->bitsPerPixel * 8, 648772b676d7Smrg minheight, maxheight, 648872b676d7Smrg pScrn->display->virtualX, 648972b676d7Smrg pScrn->display->virtualY, 649072b676d7Smrg pSiS->maxxfbmem, 649172b676d7Smrg LOOKUP_BEST_REFRESH); 649272b676d7Smrg 649372b676d7Smrg pScrn->monitor->DDC = backupddc; 649472b676d7Smrg } 649572b676d7Smrg 649672b676d7Smrg if(i == -1) { 649772b676d7Smrg SISErrorLog(pScrn, "xf86ValidateModes() error\n"); 649872b676d7Smrg goto my_error_1; 649972b676d7Smrg } 650072b676d7Smrg 650172b676d7Smrg /* Check the virtual screen against the available memory */ 650272b676d7Smrg { 650372b676d7Smrg ULong memreq = (pScrn->virtualX * ((pScrn->bitsPerPixel + 7) / 8)) * pScrn->virtualY; 650472b676d7Smrg 650572b676d7Smrg if(memreq > pSiS->maxxfbmem) { 650672b676d7Smrg SISErrorLog(pScrn, 650772b676d7Smrg "Virtual screen too big for memory; %ldK needed, %ldK available\n", 650872b676d7Smrg memreq/1024, pSiS->maxxfbmem/1024); 650972b676d7Smrg goto my_error_1; 651072b676d7Smrg } 651172b676d7Smrg } 651272b676d7Smrg 651372b676d7Smrg /* Dual Head: 651472b676d7Smrg * -) Go through mode list and mark all those modes as bad, 651572b676d7Smrg * which are unsuitable for dual head mode. 651672b676d7Smrg * -) Find the highest used pixelclock on the master head. 651772b676d7Smrg */ 651872b676d7Smrg#ifdef SISDUALHEAD 651972b676d7Smrg if((pSiS->DualHeadMode) && (!pSiS->SecondHead)) { 652072b676d7Smrg 652172b676d7Smrg pSiSEnt->maxUsedClock = 0; 652272b676d7Smrg 652372b676d7Smrg if((p = first = pScrn->modes)) { 652472b676d7Smrg 652572b676d7Smrg do { 652672b676d7Smrg 652772b676d7Smrg n = p->next; 652872b676d7Smrg 652972b676d7Smrg /* Modes that require the bridge to operate in SlaveMode 653072b676d7Smrg * are not suitable for Dual Head mode. 653172b676d7Smrg */ 653272b676d7Smrg if( (pSiS->VGAEngine == SIS_300_VGA) && 653372b676d7Smrg ( (strcmp(p->name, "320x200") == 0) || 653472b676d7Smrg (strcmp(p->name, "320x240") == 0) || 653572b676d7Smrg (strcmp(p->name, "400x300") == 0) || 653672b676d7Smrg (strcmp(p->name, "512x384") == 0) || 653772b676d7Smrg (strcmp(p->name, "640x400") == 0) ) ) { 653872b676d7Smrg p->status = MODE_BAD; 653972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, notsuitablestr, p->name, "dual head"); 654072b676d7Smrg } 654172b676d7Smrg 654272b676d7Smrg /* Search for the highest clock on first head in order to calculate 654372b676d7Smrg * max clock for second head (CRT1) 654472b676d7Smrg */ 654572b676d7Smrg if((p->status == MODE_OK) && (p->Clock > pSiSEnt->maxUsedClock)) { 654672b676d7Smrg pSiSEnt->maxUsedClock = p->Clock; 654772b676d7Smrg } 654872b676d7Smrg 654972b676d7Smrg p = n; 655072b676d7Smrg 655172b676d7Smrg } while (p != NULL && p != first); 655272b676d7Smrg 655372b676d7Smrg } 655472b676d7Smrg } 655572b676d7Smrg#endif 655672b676d7Smrg 655772b676d7Smrg /* Prune the modes marked as invalid */ 655872b676d7Smrg xf86PruneDriverModes(pScrn); 655972b676d7Smrg 656072b676d7Smrg if(i == 0 || pScrn->modes == NULL) { 656172b676d7Smrg SISErrorLog(pScrn, "No valid modes found - check VertRefresh/HorizSync\n"); 656272b676d7Smrg goto my_error_1; 656372b676d7Smrg } 656472b676d7Smrg 656572b676d7Smrg xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 656672b676d7Smrg 656772b676d7Smrg /* Set the current mode to the first in the list */ 656872b676d7Smrg pScrn->currentMode = pScrn->modes; 656972b676d7Smrg 657072b676d7Smrg /* Copy to CurrentLayout */ 657172b676d7Smrg pSiS->CurrentLayout.mode = pScrn->currentMode; 657272b676d7Smrg pSiS->CurrentLayout.displayWidth = pScrn->displayWidth; 657372b676d7Smrg pSiS->CurrentLayout.displayHeight = pScrn->virtualY; 657472b676d7Smrg 657572b676d7Smrg#ifdef SISMERGED 657672b676d7Smrg if(pSiS->MergedFB) { 657772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, modesforstr, 1); 657872b676d7Smrg } 657972b676d7Smrg#endif 658072b676d7Smrg 658172b676d7Smrg /* Print the list of modes being used */ 658272b676d7Smrg { 658372b676d7Smrg Bool usemyprint = FALSE; 658472b676d7Smrg 658572b676d7Smrg#ifdef SISDUALHEAD 658672b676d7Smrg if(pSiS->DualHeadMode) { 658772b676d7Smrg if(pSiS->SecondHead) { 658872b676d7Smrg if(pSiS->VBFlags & CRT1_LCDA) usemyprint = TRUE; 658972b676d7Smrg } else { 659072b676d7Smrg if(pSiS->VBFlags & (CRT2_LCD | CRT2_TV)) usemyprint = TRUE; 659172b676d7Smrg } 659272b676d7Smrg } else 659372b676d7Smrg#endif 659472b676d7Smrg#ifdef SISMERGED 659572b676d7Smrg if(pSiS->MergedFB) { 659672b676d7Smrg if(pSiS->VBFlags & CRT1_LCDA) usemyprint = TRUE; 659772b676d7Smrg } else 659872b676d7Smrg#endif 659972b676d7Smrg { 660072b676d7Smrg if( (pSiS->VBFlags & (CRT2_LCD | CRT2_TV)) && 660172b676d7Smrg (!(pSiS->VBFlags & DISPTYPE_DISP1)) ) 660272b676d7Smrg usemyprint = TRUE; 660372b676d7Smrg } 660472b676d7Smrg 660572b676d7Smrg if(usemyprint) { 660672b676d7Smrg SiSPrintModes(pScrn); 660772b676d7Smrg } else { 660872b676d7Smrg xf86PrintModes(pScrn); 660972b676d7Smrg } 661072b676d7Smrg } 661172b676d7Smrg 661272b676d7Smrg#ifdef SISMERGED 661372b676d7Smrg if(pSiS->MergedFB) { 661472b676d7Smrg Bool acceptcustommodes = TRUE; 661572b676d7Smrg Bool includelcdmodes = TRUE; 661672b676d7Smrg Bool isfordvi = FALSE; 661772b676d7Smrg Bool fakecrt2modes = FALSE; 661872b676d7Smrg 661972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, crtsetupstr, 2); 662072b676d7Smrg 662172b676d7Smrg clockRanges->next = NULL; 662272b676d7Smrg clockRanges->minClock = pSiS->MinClock; 662372b676d7Smrg clockRanges->maxClock = SiSMemBandWidth(pSiS->CRT2pScrn, TRUE); 662472b676d7Smrg clockRanges->clockIndex = -1; 662572b676d7Smrg clockRanges->interlaceAllowed = FALSE; 662672b676d7Smrg clockRanges->doubleScanAllowed = FALSE; 662772b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 662872b676d7Smrg clockRanges->doubleScanAllowed = TRUE; 662972b676d7Smrg } 663072b676d7Smrg 663172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock for CRT2 is %d MHz\n", 663272b676d7Smrg clockRanges->minClock / 1000); 663372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Max pixel clock for CRT2 is %d MHz\n", 663472b676d7Smrg clockRanges->maxClock / 1000); 663572b676d7Smrg 663672b676d7Smrg if(pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) { 663772b676d7Smrg if(!(pSiS->VBFlags2 & VB2_30xBDH)) { 663872b676d7Smrg if(!(pSiS->VBFlags & (CRT2_LCD|CRT2_VGA))) includelcdmodes = FALSE; 663972b676d7Smrg if(pSiS->VBFlags & CRT2_LCD) isfordvi = TRUE; 664072b676d7Smrg /* See above for a remark on handling CRT2 = TV */ 664172b676d7Smrg } else { 664272b676d7Smrg if(pSiS->VBFlags & (CRT2_LCD|CRT2_TV)) { 664372b676d7Smrg includelcdmodes = FALSE; 664472b676d7Smrg acceptcustommodes = FALSE; 664572b676d7Smrg fakecrt2modes = TRUE; 664672b676d7Smrg } 664772b676d7Smrg } 664872b676d7Smrg } else { 664972b676d7Smrg includelcdmodes = FALSE; 665072b676d7Smrg acceptcustommodes = FALSE; 665172b676d7Smrg if(pSiS->VBFlags & (CRT2_LCD|CRT2_TV)) { 665272b676d7Smrg fakecrt2modes = TRUE; 665372b676d7Smrg } 665472b676d7Smrg } 665572b676d7Smrg 665672b676d7Smrg pSiS->HaveCustomModes2 = FALSE; 665772b676d7Smrg if(!SiSMakeOwnModeList(pSiS->CRT2pScrn, acceptcustommodes, includelcdmodes, 665872b676d7Smrg isfordvi, &pSiS->HaveCustomModes2, FALSE /* fakecrt2modes */, TRUE )) { 665972b676d7Smrg 666072b676d7Smrg SISErrorLog(pScrn, "Building list of built-in modes for CRT2 failed, %s\n", 666172b676d7Smrg mergeddisstr); 666272b676d7Smrg SiSFreeCRT2Structs(pSiS); 666372b676d7Smrg pSiS->MergedFB = FALSE; 666472b676d7Smrg 666572b676d7Smrg } else { 666672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 666772b676d7Smrg "Replaced %s mode list for CRT2 with built-in modes\n", 666872b676d7Smrg pSiS->HaveCustomModes2 ? "default" : "entire"); 666972b676d7Smrg if((pSiS->VGAEngine == SIS_315_VGA) && (pSiS->VBFlags2 & VB2_SISVGA2BRIDGE)) { 667072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 667172b676d7Smrg "Using %s widescreen modes for CRT2 VGA devices\n", 667272b676d7Smrg pSiS->SiS_Pr->SiS_UseWideCRT2 ? "real" : "fake"); 667372b676d7Smrg } else pSiS->SiS_Pr->SiS_UseWideCRT2 = 0; 667472b676d7Smrg } 667572b676d7Smrg 667672b676d7Smrg } 667772b676d7Smrg 667872b676d7Smrg if(pSiS->MergedFB) { 667972b676d7Smrg 668072b676d7Smrg pointer backupddc; 668172b676d7Smrg 668272b676d7Smrg crt2freqoverruled = FALSE; 668372b676d7Smrg 668472b676d7Smrg fromDDC = FALSE; 668572b676d7Smrg if((pSiS->CRT2pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 668672b676d7Smrg if((pSiS->CRT2pScrn->monitor->nHsync <= 0) && (pSiS->CRT2pScrn->monitor->DDC)) { 668772b676d7Smrg SiSSetSyncRangeFromEdid(pSiS->CRT2pScrn, 1); 668872b676d7Smrg if(pSiS->CRT2pScrn->monitor->nHsync > 0) { 668972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, subshstr, 2); 669072b676d7Smrg fromDDC = TRUE; 669172b676d7Smrg } 669272b676d7Smrg } 669372b676d7Smrg if((pSiS->CRT2pScrn->monitor->nHsync <= 0) || (pSiS->OverruleRanges)) { 669472b676d7Smrg if( (pSiS->VBFlags & CRT2_TV) || 669572b676d7Smrg ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC)) ) { 669672b676d7Smrg Bool HaveNoRanges = (pSiS->CRT2pScrn->monitor->nHsync <= 0); 669772b676d7Smrg /* Set sane ranges for LCD and TV */ 669872b676d7Smrg if((crt2freqoverruled = CheckAndOverruleH(pScrn, pSiS->CRT2pScrn->monitor))) { 669972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, saneh, 670072b676d7Smrg HaveNoRanges ? "missing" : "bogus", 2); 670172b676d7Smrg } 670272b676d7Smrg } 670372b676d7Smrg } 670472b676d7Smrg } 670572b676d7Smrg 670672b676d7Smrg fromDDC = FALSE; 670772b676d7Smrg if((pSiS->CRT2pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 670872b676d7Smrg if((pSiS->CRT2pScrn->monitor->nVrefresh <= 0) && (pSiS->CRT2pScrn->monitor->DDC)) { 670972b676d7Smrg SiSSetSyncRangeFromEdid(pSiS->CRT2pScrn, 0); 671072b676d7Smrg if(pSiS->CRT2pScrn->monitor->nVrefresh > 0) { 671172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, subsvstr, 2); 671272b676d7Smrg fromDDC = TRUE; 671372b676d7Smrg } 671472b676d7Smrg } 671572b676d7Smrg if((pSiS->CRT2pScrn->monitor->nVrefresh <= 0) || (pSiS->OverruleRanges)) { 671672b676d7Smrg if( (pSiS->VBFlags & CRT2_TV) || 671772b676d7Smrg ((pSiS->VBFlags & CRT2_LCD) && (!fromDDC)) ) { 671872b676d7Smrg Bool HaveNoRanges = (pSiS->CRT2pScrn->monitor->nVrefresh <= 0); 671972b676d7Smrg /* Set sane ranges for LCD and TV */ 672072b676d7Smrg if((crt2freqoverruled = CheckAndOverruleV(pScrn, pSiS->CRT2pScrn->monitor))) { 672172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, sanev, 672272b676d7Smrg HaveNoRanges ? "missing" : "bogus", 2); 672372b676d7Smrg } 672472b676d7Smrg } 672572b676d7Smrg } 672672b676d7Smrg } 672772b676d7Smrg 672872b676d7Smrg backupddc = pSiS->CRT2pScrn->monitor->DDC; 672972b676d7Smrg 673072b676d7Smrg /* Suppress bogus DDC warning */ 673172b676d7Smrg if(crt2freqoverruled) pSiS->CRT2pScrn->monitor->DDC = NULL; 673272b676d7Smrg 673372b676d7Smrg pSiS->CheckForCRT2 = TRUE; 673472b676d7Smrg 673572b676d7Smrg i = xf86ValidateModes(pSiS->CRT2pScrn, pSiS->CRT2pScrn->monitor->Modes, 673672b676d7Smrg pSiS->CRT2pScrn->display->modes, clockRanges, 673772b676d7Smrg NULL, 256, 4088, 673872b676d7Smrg pSiS->CRT2pScrn->bitsPerPixel * 8, 128, 4096, 673972b676d7Smrg pScrn->display->virtualX ? pScrn->virtualX : 0, 674072b676d7Smrg pScrn->display->virtualY ? pScrn->virtualY : 0, 674172b676d7Smrg pSiS->maxxfbmem, 674272b676d7Smrg LOOKUP_BEST_REFRESH); 674372b676d7Smrg 674472b676d7Smrg pSiS->CheckForCRT2 = FALSE; 674572b676d7Smrg pSiS->CRT2pScrn->monitor->DDC = backupddc; 674672b676d7Smrg 674772b676d7Smrg if(i == -1) { 674872b676d7Smrg SISErrorLog(pScrn, "xf86ValidateModes() error, %s.\n", mergeddisstr); 674972b676d7Smrg SiSFreeCRT2Structs(pSiS); 675072b676d7Smrg pSiS->MergedFB = FALSE; 675172b676d7Smrg } 675272b676d7Smrg 675372b676d7Smrg } 675472b676d7Smrg 675572b676d7Smrg if(pSiS->MergedFB) { 675672b676d7Smrg 675772b676d7Smrg if((p = first = pSiS->CRT2pScrn->modes)) { 675872b676d7Smrg do { 675972b676d7Smrg n = p->next; 676072b676d7Smrg if( (pSiS->VGAEngine == SIS_300_VGA) && 676172b676d7Smrg ( (strcmp(p->name, "320x200") == 0) || 676272b676d7Smrg (strcmp(p->name, "320x240") == 0) || 676372b676d7Smrg (strcmp(p->name, "400x300") == 0) || 676472b676d7Smrg (strcmp(p->name, "512x384") == 0) || 676572b676d7Smrg (strcmp(p->name, "640x400") == 0) ) ) { 676672b676d7Smrg p->status = MODE_BAD; 676772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, notsuitablestr, p->name, "MergedFB"); 676872b676d7Smrg } 676972b676d7Smrg p = n; 677072b676d7Smrg } while (p != NULL && p != first); 677172b676d7Smrg } 677272b676d7Smrg 677372b676d7Smrg xf86PruneDriverModes(pSiS->CRT2pScrn); 677472b676d7Smrg 677572b676d7Smrg if(i == 0 || pSiS->CRT2pScrn->modes == NULL) { 677672b676d7Smrg SISErrorLog(pScrn, "No valid modes found for CRT2; %s\n", mergeddisstr); 677772b676d7Smrg SiSFreeCRT2Structs(pSiS); 677872b676d7Smrg pSiS->MergedFB = FALSE; 677972b676d7Smrg } 678072b676d7Smrg 678172b676d7Smrg } 678272b676d7Smrg 678372b676d7Smrg if(pSiS->MergedFB) { 678472b676d7Smrg 678572b676d7Smrg xf86SetCrtcForModes(pSiS->CRT2pScrn, INTERLACE_HALVE_V); 678672b676d7Smrg 678772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, modesforstr, 2); 678872b676d7Smrg 678972b676d7Smrg if(pSiS->VBFlags & (CRT2_LCD | CRT2_TV)) { 679072b676d7Smrg SiSPrintModes(pSiS->CRT2pScrn); 679172b676d7Smrg } else { 679272b676d7Smrg xf86PrintModes(pSiS->CRT2pScrn); 679372b676d7Smrg } 679472b676d7Smrg 679572b676d7Smrg pSiS->CRT1Modes = pScrn->modes; 679672b676d7Smrg pSiS->CRT1CurrentMode = pScrn->currentMode; 679772b676d7Smrg 679872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MergedFB: Generating mode list\n"); 679972b676d7Smrg 680072b676d7Smrg pScrn->modes = SiSGenerateModeList(pScrn, pSiS->MetaModes, 680172b676d7Smrg pSiS->CRT1Modes, pSiS->CRT2pScrn->modes, 680272b676d7Smrg pSiS->CRT2Position); 680372b676d7Smrg 680472b676d7Smrg if(!pScrn->modes) { 680572b676d7Smrg 680672b676d7Smrg SISErrorLog(pScrn, "Failed to parse MetaModes or no modes found. %s.\n", 680772b676d7Smrg mergeddisstr); 680872b676d7Smrg SiSFreeCRT2Structs(pSiS); 680972b676d7Smrg pScrn->modes = pSiS->CRT1Modes; 681072b676d7Smrg pSiS->CRT1Modes = NULL; 681172b676d7Smrg pSiS->MergedFB = FALSE; 681272b676d7Smrg 681372b676d7Smrg } 681472b676d7Smrg 681572b676d7Smrg } 681672b676d7Smrg 681772b676d7Smrg if(pSiS->MergedFB) { 681872b676d7Smrg 681972b676d7Smrg /* If no virtual dimension was given by the user, 682072b676d7Smrg * calculate a sane one now. Adapts pScrn->virtualX, 682172b676d7Smrg * pScrn->virtualY and pScrn->displayWidth. 682272b676d7Smrg */ 682372b676d7Smrg SiSRecalcDefaultVirtualSize(pScrn); 682472b676d7Smrg 682572b676d7Smrg pScrn->modes = pScrn->modes->next; /* We get the last from GenerateModeList(), skip to first */ 682672b676d7Smrg pScrn->currentMode = pScrn->modes; 682772b676d7Smrg 682872b676d7Smrg /* Update CurrentLayout */ 682972b676d7Smrg pSiS->CurrentLayout.mode = pScrn->currentMode; 683072b676d7Smrg pSiS->CurrentLayout.displayWidth = pScrn->displayWidth; 683172b676d7Smrg pSiS->CurrentLayout.displayHeight = pScrn->virtualY; 683272b676d7Smrg 683372b676d7Smrg } 683472b676d7Smrg#endif 683572b676d7Smrg 683672b676d7Smrg /* Set display resolution */ 683772b676d7Smrg#ifdef SISMERGED 683872b676d7Smrg if(pSiS->MergedFB) { 683972b676d7Smrg SiSMergedFBSetDpi(pScrn, pSiS->CRT2pScrn, pSiS->CRT2Position); 684072b676d7Smrg } else 684172b676d7Smrg#endif 684272b676d7Smrg xf86SetDpi(pScrn, 0, 0); 684372b676d7Smrg 684472b676d7Smrg /* Load fb module */ 684572b676d7Smrg switch(pScrn->bitsPerPixel) { 684672b676d7Smrg case 8: 684772b676d7Smrg case 16: 684872b676d7Smrg case 24: 684972b676d7Smrg case 32: 685072b676d7Smrg if(!xf86LoadSubModule(pScrn, "fb")) { 685172b676d7Smrg SISErrorLog(pScrn, "Failed to load fb module"); 685272b676d7Smrg goto my_error_1; 685372b676d7Smrg } 685472b676d7Smrg break; 685572b676d7Smrg default: 685672b676d7Smrg SISErrorLog(pScrn, "Unsupported framebuffer bpp (%d)\n", pScrn->bitsPerPixel); 685772b676d7Smrg goto my_error_1; 685872b676d7Smrg } 685972b676d7Smrg 686072b676d7Smrg /* Load XAA/EXA (if needed) */ 686172b676d7Smrg if(!pSiS->NoAccel) { 686272b676d7Smrg#ifdef SIS_USE_XAA 686372b676d7Smrg if(!pSiS->useEXA) { 686472b676d7Smrg if (!xf86LoadSubModule(pScrn, "xaa")) { 68655788ca14Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 68665788ca14Smrg "Falling back to shadowfb\n"); 68675788ca14Smrg pSiS->NoAccel = 1; 68685788ca14Smrg pSiS->ShadowFB = 1; 686972b676d7Smrg } 687072b676d7Smrg } 687172b676d7Smrg#endif 687272b676d7Smrg#ifdef SIS_USE_EXA 687372b676d7Smrg if(pSiS->useEXA) { 687472b676d7Smrg XF86ModReqInfo req; 687572b676d7Smrg int errmaj, errmin; 687672b676d7Smrg 687772b676d7Smrg memset(&req, 0, sizeof(req)); 687872b676d7Smrg req.majorversion = 2; 687972b676d7Smrg req.minorversion = 0; 688072b676d7Smrg if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, &req, 688172b676d7Smrg &errmaj, &errmin)) { 688272b676d7Smrg LoaderErrorMsg(NULL, "exa", errmaj, errmin); 688372b676d7Smrg goto my_error_1; 688472b676d7Smrg } 688572b676d7Smrg } 688672b676d7Smrg#endif 688772b676d7Smrg } 688872b676d7Smrg 688972b676d7Smrg /* Load shadowfb (if needed) */ 689072b676d7Smrg if(pSiS->ShadowFB) { 689172b676d7Smrg if(!xf86LoadSubModule(pScrn, "shadowfb")) { 689272b676d7Smrg SISErrorLog(pScrn, "Could not load shadowfb module\n"); 689372b676d7Smrg goto my_error_1; 689472b676d7Smrg } 689572b676d7Smrg } 689672b676d7Smrg 689772b676d7Smrg /* Load the dri and glx modules if requested. */ 68985788ca14Smrg#ifdef SISDRI 689972b676d7Smrg if(pSiS->loadDRI) { 690072b676d7Smrg if(!xf86LoaderCheckSymbol("DRIScreenInit")) { 690172b676d7Smrg if(xf86LoadSubModule(pScrn, "dri")) { 690272b676d7Smrg if(!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) { 6903e47418d9Smrg if(!xf86LoadSubModule(pScrn, "glx")) { 690472b676d7Smrg SISErrorLog(pScrn, "Failed to load glx module\n"); 690572b676d7Smrg } 690672b676d7Smrg } 690772b676d7Smrg } else { 690872b676d7Smrg SISErrorLog(pScrn, "Failed to load dri module\n"); 690972b676d7Smrg } 691072b676d7Smrg } 691172b676d7Smrg } 691272b676d7Smrg#endif 691372b676d7Smrg 691472b676d7Smrg /* Now load and initialize VBE module for VESA mode switching */ 691572b676d7Smrg pSiS->UseVESA = 0; 691672b676d7Smrg if(pSiS->VESA == 1) { 691772b676d7Smrg SiS_LoadInitVBE(pScrn); 691872b676d7Smrg if(pSiS->pVbe) { 691972b676d7Smrg VbeInfoBlock *vbe; 692072b676d7Smrg if((vbe = VBEGetVBEInfo(pSiS->pVbe))) { 692172b676d7Smrg pSiS->vesamajor = (unsigned)(vbe->VESAVersion >> 8); 692272b676d7Smrg pSiS->vesaminor = vbe->VESAVersion & 0xff; 692372b676d7Smrg SiSBuildVesaModeList(pScrn, pSiS->pVbe, vbe); 692472b676d7Smrg VBEFreeVBEInfo(vbe); 692572b676d7Smrg pSiS->UseVESA = 1; 692672b676d7Smrg } else { 692772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 692872b676d7Smrg "Failed to read VBE Info Block\n"); 692972b676d7Smrg } 693072b676d7Smrg } 693172b676d7Smrg if(pSiS->UseVESA == 0) { 693272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 693372b676d7Smrg "VESA mode switching disabled.\n"); 693472b676d7Smrg } 693572b676d7Smrg } 693672b676d7Smrg 693772b676d7Smrg if(pSiS->pVbe) { 693872b676d7Smrg vbeFree(pSiS->pVbe); 693972b676d7Smrg pSiS->pVbe = NULL; 694072b676d7Smrg } 694172b676d7Smrg 694272b676d7Smrg#ifdef SISDUALHEAD 694372b676d7Smrg xf86SetPrimInitDone(pScrn->entityList[0]); 694472b676d7Smrg#endif 694572b676d7Smrg 694672b676d7Smrg sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); 694772b676d7Smrg 694872b676d7Smrg if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); 694972b676d7Smrg pSiS->pInt = NULL; 695072b676d7Smrg 695172b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 695272b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTXVGAMMA1; 695372b676d7Smrg } 695472b676d7Smrg 695572b676d7Smrg#ifdef SISDUALHEAD 695672b676d7Smrg if(pSiS->DualHeadMode) { 695772b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_ISDUALHEAD; 695872b676d7Smrg if(pSiS->SecondHead) pSiS->SiS_SD_Flags |= SiS_SD_ISDHSECONDHEAD; 695972b676d7Smrg else pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTXVGAMMA1); 696072b676d7Smrg#ifdef PANORAMIX 696172b676d7Smrg if(!noPanoramiXExtension) { 696272b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_ISDHXINERAMA; 696372b676d7Smrg /* pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTXVGAMMA1); */ 696472b676d7Smrg } 696572b676d7Smrg#endif 696672b676d7Smrg } 696772b676d7Smrg#endif 696872b676d7Smrg 696972b676d7Smrg#ifdef SISMERGED 697072b676d7Smrg if(pSiS->MergedFB) pSiS->SiS_SD_Flags |= SiS_SD_ISMERGEDFB; 697172b676d7Smrg#endif 697272b676d7Smrg 697372b676d7Smrg /* Try to determine if this is a laptop */ 697472b676d7Smrg /* (only used for SiSCtrl visualisations) */ 697572b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPLTFLAG; 697672b676d7Smrg pSiS->SiS_SD2_Flags &= ~SiS_SD2_ISLAPTOP; 697772b676d7Smrg if(pSiS->detectedCRT2Devices & CRT2_LCD) { 697872b676d7Smrg if(pSiS->VBFlags2 & (VB2_SISLVDSBRIDGE | VB2_LVDS | VB2_30xBDH)) { 697972b676d7Smrg /* 1. By bridge type: LVDS in 99% of all cases; 698072b676d7Smrg * exclude unusual setups like Barco projectors 698172b676d7Smrg * and parallel flat panels. TODO: Exclude 698272b676d7Smrg * Sony W1, V1. 698372b676d7Smrg */ 698472b676d7Smrg if((pSiS->SiS_Pr->SiS_CustomT != CUT_BARCO1366) && 698572b676d7Smrg (pSiS->SiS_Pr->SiS_CustomT != CUT_BARCO1024) && 698672b676d7Smrg (pSiS->SiS_Pr->SiS_CustomT != CUT_PANEL848) && 698772b676d7Smrg (pSiS->SiS_Pr->SiS_CustomT != CUT_PANEL856) && 698872b676d7Smrg (pSiS->SiS_Pr->SiS_CustomT != CUT_AOP8060) && 698972b676d7Smrg ( (pSiS->ChipType != SIS_550) || 699072b676d7Smrg (!pSiS->DSTN && !pSiS->FSTN) ) ) { 699172b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_ISLAPTOP; 699272b676d7Smrg } 699372b676d7Smrg } else if((pSiS->VBFlags2 & (VB2_301 | VB2_301C)) && 699472b676d7Smrg (pSiS->VBLCDFlags & (VB_LCD_1280x960 | 699572b676d7Smrg VB_LCD_1400x1050 | 699672b676d7Smrg VB_LCD_1024x600 | 699772b676d7Smrg VB_LCD_1280x800 | 699872b676d7Smrg VB_LCD_1280x854))) { 699972b676d7Smrg /* 2. By (odd) LCD resolutions on TMDS bridges 700072b676d7Smrg * (eg Averatec). TODO: Exclude IBM Netvista. 700172b676d7Smrg */ 700272b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_ISLAPTOP; 700372b676d7Smrg } 700472b676d7Smrg } 700572b676d7Smrg 700672b676d7Smrg if(pSiS->enablesisctrl) pSiS->SiS_SD_Flags |= SiS_SD_ENABLED; 700772b676d7Smrg 700872b676d7Smrg pSiS->currentModeLast = pScrn->currentMode; 700972b676d7Smrg pSiS->VBFlagsInit = pSiS->VBFlags; 701072b676d7Smrg 701172b676d7Smrg return TRUE; 701272b676d7Smrg 701372b676d7Smrg /* ---- */ 701472b676d7Smrg 701572b676d7Smrgmy_error_1: 701672b676d7Smrg sisRestoreExtRegisterLock(pSiS, srlockReg, crlockReg); 701772b676d7Smrgmy_error_0: 701872b676d7Smrg#ifdef SISDUALHEAD 701972b676d7Smrg if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; 702072b676d7Smrg#endif 702172b676d7Smrg if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); 702272b676d7Smrg pSiS->pInt = NULL; 702372b676d7Smrg SISFreeRec(pScrn); 702472b676d7Smrg return FALSE; 702572b676d7Smrg} 702672b676d7Smrg 702772b676d7Smrg/* 702872b676d7Smrg * Map I/O port area for non-PC platforms 702972b676d7Smrg */ 703072b676d7Smrg#ifdef SIS_NEED_MAP_IOP 703172b676d7Smrgstatic Bool 703272b676d7SmrgSISMapIOPMem(ScrnInfoPtr pScrn) 703372b676d7Smrg{ 703472b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 703572b676d7Smrg#ifdef SISDUALHEAD 703672b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 703772b676d7Smrg 703872b676d7Smrg if(pSiS->DualHeadMode) { 703972b676d7Smrg pSiSEnt->MapCountIOPBase++; 704072b676d7Smrg if(!(pSiSEnt->IOPBase)) { 704172b676d7Smrg /* Only map if not mapped previously */ 70421fd23544Smrg#ifndef XSERVER_LIBPCIACCESS 704372b676d7Smrg pSiSEnt->IOPBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 704472b676d7Smrg pSiS->PciTag, pSiS->IOPAddress, 128); 70451fd23544Smrg#else 70461fd23544Smrg { 70471fd23544Smrg void **result = (void **)&pSiSEnt->IOPBase; 70481fd23544Smrg int err = pci_device_map_range(pSiS->PciInfo, 70491fd23544Smrg pSiS->IOPAddress, 70501fd23544Smrg 128, 70511fd23544Smrg PCI_DEV_MAP_FLAG_WRITABLE, 70521fd23544Smrg result); 70531fd23544Smrg 70541fd23544Smrg if (err) { 70551fd23544Smrg xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 70561fd23544Smrg "Unable to map IO aperture. %s (%d)\n", 70571fd23544Smrg strerror (err), err); 70581fd23544Smrg } 70591fd23544Smrg } 70601fd23544Smrg#endif 706172b676d7Smrg } 706272b676d7Smrg pSiS->IOPBase = pSiSEnt->IOPBase; 706372b676d7Smrg } else 706472b676d7Smrg#endif 70651fd23544Smrg#ifndef XSERVER_LIBPCIACCESS 70661fd23544Smrg pSiS->IOPBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 70671fd23544Smrg pSiS->PciTag, pSiS->IOPAddress, 128); 70681fd23544Smrg#else 70691fd23544Smrg { 70701fd23544Smrg void **result = (void **)&pSiS->IOPBase; 70711fd23544Smrg int err = pci_device_map_range(pSiS->PciInfo, 70721fd23544Smrg pSiS->IOPAddress, 70731fd23544Smrg 128, 70741fd23544Smrg PCI_DEV_MAP_FLAG_WRITABLE, 70751fd23544Smrg result); 70761fd23544Smrg 70771fd23544Smrg if (err) { 70781fd23544Smrg xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 70791fd23544Smrg "Unable to map IO aperture. %s (%d)\n", 70801fd23544Smrg strerror (err), err); 70811fd23544Smrg } 70821fd23544Smrg } 70831fd23544Smrg#endif 708472b676d7Smrg if(pSiS->IOPBase == NULL) { 708572b676d7Smrg SISErrorLog(pScrn, "Could not map I/O port area\n"); 708672b676d7Smrg return FALSE; 708772b676d7Smrg } 708872b676d7Smrg 708972b676d7Smrg return TRUE; 709072b676d7Smrg} 709172b676d7Smrg 709272b676d7Smrgstatic Bool 709372b676d7SmrgSISUnmapIOPMem(ScrnInfoPtr pScrn) 709472b676d7Smrg{ 709572b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 709672b676d7Smrg#ifdef SISDUALHEAD 709772b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate;; 709872b676d7Smrg#endif 709972b676d7Smrg 710072b676d7Smrg/* In dual head mode, we must not unmap if the other head still 710172b676d7Smrg * assumes memory as mapped 710272b676d7Smrg */ 710372b676d7Smrg#ifdef SISDUALHEAD 710472b676d7Smrg if(pSiS->DualHeadMode) { 710572b676d7Smrg if(pSiSEnt->MapCountIOPBase) { 710672b676d7Smrg pSiSEnt->MapCountIOPBase--; 710772b676d7Smrg if((pSiSEnt->MapCountIOPBase == 0) || (pSiSEnt->forceUnmapIOPBase)) { 710872b676d7Smrg xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOPBase, 2048); 710972b676d7Smrg pSiSEnt->IOPBase = NULL; 711072b676d7Smrg pSiSEnt->MapCountIOPBase = 0; 711172b676d7Smrg pSiSEnt->forceUnmapIOPBase = FALSE; 711272b676d7Smrg } 711372b676d7Smrg pSiS->IOPBase = NULL; 711472b676d7Smrg } 711572b676d7Smrg } else { 711672b676d7Smrg#endif 711772b676d7Smrg xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOPBase, 2048); 711872b676d7Smrg pSiS->IOPBase = NULL; 711972b676d7Smrg#ifdef SISDUALHEAD 712072b676d7Smrg } 712172b676d7Smrg#endif 712272b676d7Smrg return TRUE; 712372b676d7Smrg} 712472b676d7Smrg#endif 712572b676d7Smrg 712672b676d7Smrg/* 712772b676d7Smrg * Map the framebuffer and MMIO memory 712872b676d7Smrg */ 712972b676d7Smrg 713072b676d7Smrgstatic Bool 713172b676d7SmrgSISMapMem(ScrnInfoPtr pScrn) 713272b676d7Smrg{ 713372b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 713472b676d7Smrg int mmioFlags = VIDMEM_MMIO; 713572b676d7Smrg#ifdef SISDUALHEAD 713672b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 713772b676d7Smrg#endif 713872b676d7Smrg 713972b676d7Smrg /* 714072b676d7Smrg * Map IO registers to virtual address space 714172b676d7Smrg * (For Alpha, we need to map SPARSE memory, since we need 714272b676d7Smrg * byte/short access.) 714372b676d7Smrg */ 714472b676d7Smrg#if defined(__alpha__) 714572b676d7Smrg mmioFlags |= VIDMEM_SPARSE; 714672b676d7Smrg#endif 714772b676d7Smrg 714872b676d7Smrg#ifdef SISDUALHEAD 714972b676d7Smrg if(pSiS->DualHeadMode) { 715072b676d7Smrg pSiSEnt->MapCountIOBase++; 715172b676d7Smrg if(!(pSiSEnt->IOBase)) { 715272b676d7Smrg /* Only map if not mapped previously */ 71531fd23544Smrg#ifndef XSERVER_LIBPCIACCESS 715472b676d7Smrg pSiSEnt->IOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, 715572b676d7Smrg pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 71561fd23544Smrg#else 71571fd23544Smrg void **result = (void **)&pSiSEnt->IOBase; 71581fd23544Smrg int err = pci_device_map_range(pSiS->PciInfo, 71591fd23544Smrg pSiS->IOAddress, 71601fd23544Smrg (pSiS->mmioSize * 1024), 71611fd23544Smrg PCI_DEV_MAP_FLAG_WRITABLE, 71621fd23544Smrg result); 71631fd23544Smrg 71641fd23544Smrg if (err) { 71651fd23544Smrg xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 71661fd23544Smrg "Unable to map IO aperture. %s (%d)\n", 71671fd23544Smrg strerror (err), err); 71681fd23544Smrg } 71691fd23544Smrg#endif 717072b676d7Smrg } 717172b676d7Smrg pSiS->IOBase = pSiSEnt->IOBase; 717272b676d7Smrg } else 717372b676d7Smrg#endif 71741fd23544Smrg#ifndef XSERVER_LIBPCIACCESS 717572b676d7Smrg pSiS->IOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, 717672b676d7Smrg pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 71771fd23544Smrg#else 71781fd23544Smrg { 71791fd23544Smrg void **result = (void **)&pSiS->IOBase; 71801fd23544Smrg int err = pci_device_map_range(pSiS->PciInfo, 71811fd23544Smrg pSiS->IOAddress, 71821fd23544Smrg (pSiS->mmioSize * 1024), 71831fd23544Smrg PCI_DEV_MAP_FLAG_WRITABLE, 71841fd23544Smrg result); 71851fd23544Smrg 71861fd23544Smrg if (err) { 71871fd23544Smrg xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 71881fd23544Smrg "Unable to map IO aperture. %s (%d)\n", 71891fd23544Smrg strerror (err), err); 71901fd23544Smrg } 71911fd23544Smrg } 71921fd23544Smrg#endif 719372b676d7Smrg 719472b676d7Smrg if(pSiS->IOBase == NULL) { 719572b676d7Smrg SISErrorLog(pScrn, "Could not map MMIO area\n"); 719672b676d7Smrg return FALSE; 719772b676d7Smrg } 719872b676d7Smrg 719972b676d7Smrg#ifdef __alpha__ 720072b676d7Smrg /* 720172b676d7Smrg * for Alpha, we need to map DENSE memory as well, for 720272b676d7Smrg * setting CPUToScreenColorExpandBase. 720372b676d7Smrg */ 720472b676d7Smrg#ifdef SISDUALHEAD 720572b676d7Smrg if(pSiS->DualHeadMode) { 720672b676d7Smrg pSiSEnt->MapCountIOBaseDense++; 720772b676d7Smrg if(!(pSiSEnt->IOBaseDense)) { 720872b676d7Smrg /* Only map if not mapped previously */ 72091fd23544Smrg#ifndef XSERVER_LIBPCIACCESS 721072b676d7Smrg pSiSEnt->IOBaseDense = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 721172b676d7Smrg pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 72121fd23544Smrg#else 72131fd23544Smrg void **result = (void **)&pSiSEnt->IOBaseDense; 72141fd23544Smrg int err = pci_device_map_range(pSiS->PciInfo, 72151fd23544Smrg pSiS->IOAddress, 72161fd23544Smrg (pSiS->mmioSize * 1024), 72171fd23544Smrg PCI_DEV_MAP_FLAG_WRITABLE, 72181fd23544Smrg result); 72191fd23544Smrg 72201fd23544Smrg if (err) { 72211fd23544Smrg xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 72221fd23544Smrg "Unable to map IO dense aperture. %s (%d)\n", 72231fd23544Smrg strerror (err), err); 72241fd23544Smrg } 72251fd23544Smrg#endif /* XSERVER_LIBPCIACCESS */ 722672b676d7Smrg } 722772b676d7Smrg pSiS->IOBaseDense = pSiSEnt->IOBaseDense; 72281fd23544Smrg } else { 72291fd23544Smrg#endif /* SISDUALHEAD */ 72301fd23544Smrg#ifndef XSERVER_LIBPCIACCESS 72311fd23544Smrg pSiS->IOBaseDense = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 723272b676d7Smrg pSiS->PciTag, pSiS->IOAddress, (pSiS->mmioSize * 1024)); 72331fd23544Smrg#else 72341fd23544Smrg void **result = (void **)&pSiS->IOBaseDense; 72351fd23544Smrg int err = pci_device_map_range(pSiS->PciInfo, 72361fd23544Smrg pSiS->IOAddress, 72371fd23544Smrg (pSiS->mmioSize * 1024), 72381fd23544Smrg PCI_DEV_MAP_FLAG_WRITABLE, 72391fd23544Smrg result); 72401fd23544Smrg 72411fd23544Smrg if (err) { 72421fd23544Smrg xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 72431fd23544Smrg "Unable to map IO dense aperture. %s (%d)\n", 72441fd23544Smrg strerror (err), err); 72451fd23544Smrg } 72461fd23544Smrg#endif /* XSERVER_LIBPCIACCESS */ 72471fd23544Smrg#ifdef SISDUALHEAD 72481fd23544Smrg } 72491fd23544Smrg#endif 725072b676d7Smrg if(pSiS->IOBaseDense == NULL) { 725172b676d7Smrg SISErrorLog(pScrn, "Could not map MMIO dense area\n"); 725272b676d7Smrg return FALSE; 725372b676d7Smrg } 725472b676d7Smrg#endif /* __alpha__ */ 725572b676d7Smrg 725672b676d7Smrg#ifdef SISDUALHEAD 725772b676d7Smrg if(pSiS->DualHeadMode) { 725872b676d7Smrg pSiSEnt->MapCountFbBase++; 725972b676d7Smrg if(!(pSiSEnt->FbBase)) { 726072b676d7Smrg /* Only map if not mapped previously */ 72611fd23544Smrg#ifndef XSERVER_LIBPCIACCESS 726272b676d7Smrg pSiSEnt->FbBase = pSiSEnt->RealFbBase = 726372b676d7Smrg xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 726472b676d7Smrg pSiS->PciTag, (ULong)pSiS->realFbAddress, 726572b676d7Smrg pSiS->FbMapSize); 72661fd23544Smrg#else 72671fd23544Smrg int err = pci_device_map_range(pSiS->PciInfo, 72681fd23544Smrg (ULong)pSiS->realFbAddress, 72691fd23544Smrg pSiS->FbMapSize, 72701fd23544Smrg PCI_DEV_MAP_FLAG_WRITABLE | 72711fd23544Smrg PCI_DEV_MAP_FLAG_WRITE_COMBINE, 72721fd23544Smrg (void *)&pSiSEnt->FbBase); 72731fd23544Smrg if (err) { 72741fd23544Smrg xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 72751fd23544Smrg "Unable to map FB aperture. %s (%d)\n", 72761fd23544Smrg strerror (err), err); 72771fd23544Smrg return FALSE; 72781fd23544Smrg } 72791fd23544Smrg pSiSEnt->RealFbBase = pSiSEnt->FbBase; 72801fd23544Smrg#endif 728172b676d7Smrg } 728272b676d7Smrg pSiS->FbBase = pSiS->RealFbBase = pSiSEnt->FbBase; 728372b676d7Smrg /* Adapt FbBase (for DHM and SiS76x UMA skipping; dhmOffset is 0 otherwise) */ 728472b676d7Smrg pSiS->FbBase += pSiS->dhmOffset; 728572b676d7Smrg } else { 728672b676d7Smrg#endif 72871fd23544Smrg 72881fd23544Smrg#ifndef XSERVER_LIBPCIACCESS 72891fd23544Smrg pSiS->FbBase = pSiS->RealFbBase = 72901fd23544Smrg xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 729172b676d7Smrg pSiS->PciTag, (ULong)pSiS->realFbAddress, 729272b676d7Smrg pSiS->FbMapSize); 72931fd23544Smrg#else 72941fd23544Smrg int err = pci_device_map_range(pSiS->PciInfo, 72951fd23544Smrg (ULong)pSiS->realFbAddress, 72961fd23544Smrg pSiS->FbMapSize, 72971fd23544Smrg PCI_DEV_MAP_FLAG_WRITABLE | 72981fd23544Smrg PCI_DEV_MAP_FLAG_WRITE_COMBINE, 72991fd23544Smrg (void *)&pSiS->FbBase); 73001fd23544Smrg if (err) { 73011fd23544Smrg xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 73021fd23544Smrg "Unable to map FB aperture. %s (%d)\n", 73031fd23544Smrg strerror (err), err); 73041fd23544Smrg return FALSE; 73051fd23544Smrg } 73061fd23544Smrg pSiS->RealFbBase = pSiS->FbBase; 73071fd23544Smrg#endif 730872b676d7Smrg pSiS->FbBase += pSiS->dhmOffset; 73091fd23544Smrg 731072b676d7Smrg#ifdef SISDUALHEAD 731172b676d7Smrg } 731272b676d7Smrg#endif 731372b676d7Smrg 731472b676d7Smrg if(pSiS->FbBase == NULL) { 731572b676d7Smrg SISErrorLog(pScrn, "Could not map framebuffer area\n"); 731672b676d7Smrg return FALSE; 731772b676d7Smrg } 731872b676d7Smrg 731972b676d7Smrg#ifdef TWDEBUG 732072b676d7Smrg xf86DrvMsg(0, 0, "Framebuffer mapped to %p\n", pSiS->FbBase); 732172b676d7Smrg#endif 732272b676d7Smrg 732372b676d7Smrg return TRUE; 732472b676d7Smrg} 732572b676d7Smrg 732672b676d7Smrg 732772b676d7Smrg/* 732872b676d7Smrg * Unmap the framebuffer and MMIO memory. 732972b676d7Smrg */ 733072b676d7Smrg 733172b676d7Smrgstatic Bool 733272b676d7SmrgSISUnmapMem(ScrnInfoPtr pScrn) 733372b676d7Smrg{ 733472b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 733572b676d7Smrg#ifdef SISDUALHEAD 733672b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 733772b676d7Smrg#endif 733872b676d7Smrg 733972b676d7Smrg/* In dual head mode, we must not unmap if the other head still 734072b676d7Smrg * assumes memory as mapped 734172b676d7Smrg */ 734272b676d7Smrg#ifdef SISDUALHEAD 734372b676d7Smrg if(pSiS->DualHeadMode) { 734472b676d7Smrg if(pSiSEnt->MapCountIOBase) { 734572b676d7Smrg pSiSEnt->MapCountIOBase--; 734672b676d7Smrg if((pSiSEnt->MapCountIOBase == 0) || (pSiSEnt->forceUnmapIOBase)) { 734772b676d7Smrg xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOBase, (pSiS->mmioSize * 1024)); 734872b676d7Smrg pSiSEnt->IOBase = NULL; 734972b676d7Smrg pSiSEnt->MapCountIOBase = 0; 735072b676d7Smrg pSiSEnt->forceUnmapIOBase = FALSE; 735172b676d7Smrg } 735272b676d7Smrg pSiS->IOBase = NULL; 735372b676d7Smrg } 735472b676d7Smrg#ifdef __alpha__ 735572b676d7Smrg if(pSiSEnt->MapCountIOBaseDense) { 735672b676d7Smrg pSiSEnt->MapCountIOBaseDense--; 735772b676d7Smrg if((pSiSEnt->MapCountIOBaseDense == 0) || (pSiSEnt->forceUnmapIOBaseDense)) { 735872b676d7Smrg xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOBaseDense, (pSiS->mmioSize * 1024)); 735972b676d7Smrg pSiSEnt->IOBaseDense = NULL; 736072b676d7Smrg pSiSEnt->MapCountIOBaseDense = 0; 736172b676d7Smrg pSiSEnt->forceUnmapIOBaseDense = FALSE; 736272b676d7Smrg } 736372b676d7Smrg pSiS->IOBaseDense = NULL; 736472b676d7Smrg } 736572b676d7Smrg#endif /* __alpha__ */ 736672b676d7Smrg if(pSiSEnt->MapCountFbBase) { 736772b676d7Smrg pSiSEnt->MapCountFbBase--; 736872b676d7Smrg if((pSiSEnt->MapCountFbBase == 0) || (pSiSEnt->forceUnmapFbBase)) { 736972b676d7Smrg xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->RealFbBase, pSiS->FbMapSize); 737072b676d7Smrg pSiSEnt->FbBase = pSiSEnt->RealFbBase = NULL; 737172b676d7Smrg pSiSEnt->MapCountFbBase = 0; 737272b676d7Smrg pSiSEnt->forceUnmapFbBase = FALSE; 737372b676d7Smrg 737472b676d7Smrg } 737572b676d7Smrg pSiS->FbBase = pSiS->RealFbBase = NULL; 737672b676d7Smrg } 737772b676d7Smrg } else { 737872b676d7Smrg#endif 737972b676d7Smrg xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOBase, (pSiS->mmioSize * 1024)); 738072b676d7Smrg pSiS->IOBase = NULL; 738172b676d7Smrg#ifdef __alpha__ 738272b676d7Smrg xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOBaseDense, (pSiS->mmioSize * 1024)); 738372b676d7Smrg pSiS->IOBaseDense = NULL; 738472b676d7Smrg#endif 738572b676d7Smrg xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->RealFbBase, pSiS->FbMapSize); 738672b676d7Smrg pSiS->FbBase = pSiS->RealFbBase = NULL; 738772b676d7Smrg#ifdef SISDUALHEAD 738872b676d7Smrg } 738972b676d7Smrg#endif 739072b676d7Smrg return TRUE; 739172b676d7Smrg} 739272b676d7Smrg 739372b676d7Smrg/* 739472b676d7Smrg * This function saves the video state. 739572b676d7Smrg */ 739672b676d7Smrgstatic void 739772b676d7SmrgSISSave(ScrnInfoPtr pScrn) 739872b676d7Smrg{ 739972b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 740072b676d7Smrg SISRegPtr sisReg; 740172b676d7Smrg int flags; 740272b676d7Smrg 740372b676d7Smrg#ifdef SISDUALHEAD 740472b676d7Smrg /* We always save master & slave */ 740572b676d7Smrg if(pSiS->DualHeadMode && pSiS->SecondHead) return; 740672b676d7Smrg#endif 740772b676d7Smrg 740872b676d7Smrg sisReg = &pSiS->SavedReg; 740972b676d7Smrg 741072b676d7Smrg if( ((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) && 741172b676d7Smrg ((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (SiSBridgeIsInSlaveMode(pScrn))) ) { 741272b676d7Smrg SiSVGASave(pScrn, sisReg, SISVGA_SR_CMAP | SISVGA_SR_MODE); 741372b676d7Smrg#ifdef SIS_PC_PLATFORM 741472b676d7Smrg if(pSiS->VGAMemBase) { 741572b676d7Smrg SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO+0x30); 74165788ca14Smrg SiSSetLVDSetc(pSiS->SiS_Pr); 741772b676d7Smrg SiS_GetVBType(pSiS->SiS_Pr); 741872b676d7Smrg SiS_DisableBridge(pSiS->SiS_Pr); 741972b676d7Smrg SiSVGASave(pScrn, sisReg, SISVGA_SR_FONTS); 742072b676d7Smrg SiS_EnableBridge(pSiS->SiS_Pr); 742172b676d7Smrg } 742272b676d7Smrg#endif 742372b676d7Smrg } else { 742472b676d7Smrg flags = SISVGA_SR_CMAP | SISVGA_SR_MODE; 742572b676d7Smrg#ifdef SIS_PC_PLATFORM 742672b676d7Smrg if(pSiS->VGAMemBase) flags |= SISVGA_SR_FONTS; 742772b676d7Smrg#endif 742872b676d7Smrg SiSVGASave(pScrn, sisReg, flags); 742972b676d7Smrg } 743072b676d7Smrg 743172b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, &sisReg->sisRegs3C4[0x05], &sisReg->sisRegs3D4[0x80]); 743272b676d7Smrg 743372b676d7Smrg (*pSiS->SiSSave)(pScrn, sisReg); 743472b676d7Smrg 743572b676d7Smrg if(pSiS->UseVESA) SISVESASaveRestore(pScrn, MODE_SAVE); 743672b676d7Smrg 743772b676d7Smrg /* "Save" these again as they may have been changed prior to SISSave() call */ 743872b676d7Smrg if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 743972b676d7Smrg sisReg->sisRegs3C4[0x1f] = pSiS->oldSR1F; 744072b676d7Smrg sisReg->sisRegs3D4[0x17] = pSiS->oldCR17; 744172b676d7Smrg sisReg->sisRegs3D4[0x32] = pSiS->oldCR32; 744272b676d7Smrg sisReg->sisRegs3D4[0x36] = pSiS->oldCR36; 744372b676d7Smrg sisReg->sisRegs3D4[0x37] = pSiS->oldCR37; 744472b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 744572b676d7Smrg sisReg->sisRegs3D4[pSiS->myCR63] = pSiS->oldCR63; 744672b676d7Smrg } 744772b676d7Smrg } 744872b676d7Smrg} 744972b676d7Smrg 745072b676d7Smrg/* VESASaveRestore taken from vesa driver */ 745172b676d7Smrgstatic void 745272b676d7SmrgSISVESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function) 745372b676d7Smrg{ 745472b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 745572b676d7Smrg 745672b676d7Smrg /* Query amount of memory to save state */ 745772b676d7Smrg if((function == MODE_QUERY) || 745872b676d7Smrg (function == MODE_SAVE && pSiS->state == NULL)) { 745972b676d7Smrg 746072b676d7Smrg /* Make sure we save at least this information in case of failure */ 746172b676d7Smrg (void)VBEGetVBEMode(pSiS->pVbe, &pSiS->stateMode); 746272b676d7Smrg SiSVGASaveFonts(pScrn); 746372b676d7Smrg 746472b676d7Smrg if(pSiS->vesamajor > 1) { 746572b676d7Smrg if(!VBESaveRestore(pSiS->pVbe, function, (pointer)&pSiS->state, 746672b676d7Smrg &pSiS->stateSize, &pSiS->statePage)) { 746772b676d7Smrg return; 746872b676d7Smrg } 746972b676d7Smrg } 747072b676d7Smrg } 747172b676d7Smrg 747272b676d7Smrg /* Save/Restore Super VGA state */ 747372b676d7Smrg if(function != MODE_QUERY) { 747472b676d7Smrg 747572b676d7Smrg if(pSiS->vesamajor > 1) { 747672b676d7Smrg if(function == MODE_RESTORE) { 747772b676d7Smrg memcpy(pSiS->state, pSiS->pstate, pSiS->stateSize); 747872b676d7Smrg } 747972b676d7Smrg 748072b676d7Smrg if(VBESaveRestore(pSiS->pVbe,function,(pointer)&pSiS->state, 748172b676d7Smrg &pSiS->stateSize,&pSiS->statePage) && 748272b676d7Smrg (function == MODE_SAVE)) { 748372b676d7Smrg /* don't rely on the memory not being touched */ 748472b676d7Smrg if(!pSiS->pstate) { 74855788ca14Smrg pSiS->pstate = malloc(pSiS->stateSize); 748672b676d7Smrg } 748772b676d7Smrg memcpy(pSiS->pstate, pSiS->state, pSiS->stateSize); 748872b676d7Smrg } 748972b676d7Smrg } 749072b676d7Smrg 749172b676d7Smrg if(function == MODE_RESTORE) { 749272b676d7Smrg VBESetVBEMode(pSiS->pVbe, pSiS->stateMode, NULL); 749372b676d7Smrg SiSVGARestoreFonts(pScrn); 749472b676d7Smrg } 749572b676d7Smrg 749672b676d7Smrg } 749772b676d7Smrg} 749872b676d7Smrg 749972b676d7Smrg/* 750072b676d7Smrg * Initialise a new mode. This is currently done using the 750172b676d7Smrg * "initialise struct, restore/write struct to HW" model for 750272b676d7Smrg * the old chipsets (5597/530/6326). For newer chipsets, 750372b676d7Smrg * we use our own mode switching code. 750472b676d7Smrg */ 750572b676d7Smrg 750672b676d7Smrgstatic Bool 750772b676d7SmrgSISModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 750872b676d7Smrg{ 750972b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 751072b676d7Smrg SISRegPtr sisReg; 751172b676d7Smrg#ifdef SISDUALHEAD 751272b676d7Smrg SISEntPtr pSiSEnt = NULL; 751372b676d7Smrg#endif 751472b676d7Smrg 751572b676d7Smrg andSISIDXREG(SISCR,0x11,0x7f); /* Unlock CRTC registers */ 751672b676d7Smrg 751772b676d7Smrg SISModifyModeInfo(mode); /* Quick check of the mode parameters */ 751872b676d7Smrg 751972b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 752072b676d7Smrg SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO+0x30); 752172b676d7Smrg } 752272b676d7Smrg 752372b676d7Smrg if(pSiS->UseVESA) { /* With VESA: */ 752472b676d7Smrg 752572b676d7Smrg#ifdef SISDUALHEAD 752672b676d7Smrg /* No dual head mode when using VESA */ 752772b676d7Smrg if(pSiS->SecondHead) return TRUE; 752872b676d7Smrg#endif 752972b676d7Smrg 753072b676d7Smrg pScrn->vtSema = TRUE; 753172b676d7Smrg 753272b676d7Smrg /* 753372b676d7Smrg * This order is required: 753472b676d7Smrg * The video bridge needs to be adjusted before the 753572b676d7Smrg * BIOS is run as the BIOS sets up CRT2 according to 753672b676d7Smrg * these register settings. 753772b676d7Smrg * After the BIOS is run, the bridges and turboqueue 753872b676d7Smrg * registers need to be readjusted as the BIOS may 753972b676d7Smrg * very probably have messed them up. 754072b676d7Smrg */ 754172b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 754272b676d7Smrg SiSPreSetMode(pScrn, mode, SIS_MODE_SIMU); 754372b676d7Smrg } 754472b676d7Smrg if(!SiSSetVESAMode(pScrn, mode)) { 754572b676d7Smrg SISErrorLog(pScrn, "SiSSetVESAMode() failed\n"); 754672b676d7Smrg return FALSE; 754772b676d7Smrg } 754872b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 754972b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 755072b676d7Smrg SiSPreSetMode(pScrn, mode, SIS_MODE_SIMU); 755172b676d7Smrg SiSPostSetMode(pScrn, &pSiS->ModeReg); 755272b676d7Smrg } 755372b676d7Smrg#ifdef TWDEBUG 755472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 755572b676d7Smrg "REAL REGISTER CONTENTS AFTER SETMODE:\n"); 755672b676d7Smrg#endif 755772b676d7Smrg if(!(*pSiS->ModeInit)(pScrn, mode)) { 755872b676d7Smrg SISErrorLog(pScrn, "ModeInit() failed\n"); 755972b676d7Smrg return FALSE; 756072b676d7Smrg } 756172b676d7Smrg 756272b676d7Smrg SiSVGAProtect(pScrn, TRUE); 756372b676d7Smrg (*pSiS->SiSRestore)(pScrn, &pSiS->ModeReg); 756472b676d7Smrg SiSVGAProtect(pScrn, FALSE); 756572b676d7Smrg 756672b676d7Smrg } else { /* Without VESA: */ 756772b676d7Smrg 756872b676d7Smrg#ifdef SISDUALHEAD 756972b676d7Smrg if(pSiS->DualHeadMode) { 757072b676d7Smrg 757172b676d7Smrg if(!(*pSiS->ModeInit)(pScrn, mode)) { 757272b676d7Smrg SISErrorLog(pScrn, "ModeInit() failed\n"); 757372b676d7Smrg return FALSE; 757472b676d7Smrg } 757572b676d7Smrg 757672b676d7Smrg pScrn->vtSema = TRUE; 757772b676d7Smrg 757872b676d7Smrg pSiSEnt = pSiS->entityPrivate; 757972b676d7Smrg 758072b676d7Smrg if(!(pSiS->SecondHead)) { 758172b676d7Smrg /* Head 1 (master) is always CRT2 */ 758272b676d7Smrg SiSPreSetMode(pScrn, mode, SIS_MODE_CRT2); 758372b676d7Smrg if(!SiSBIOSSetModeCRT2(pSiS->SiS_Pr, pScrn, mode, pSiS->IsCustom)) { 758472b676d7Smrg SISErrorLog(pScrn, "SiSBIOSSetModeCRT2() failed\n"); 758572b676d7Smrg return FALSE; 758672b676d7Smrg } 758772b676d7Smrg SiSPostSetMode(pScrn, &pSiS->ModeReg); 758872b676d7Smrg if(pSiSEnt->pScrn_2) { 75895788ca14Smrg SISAdjustFrame(ADJUST_FRAME_ARGS(pSiSEnt->pScrn_2, 759072b676d7Smrg pSiSEnt->pScrn_2->frameX0, 75915788ca14Smrg pSiSEnt->pScrn_2->frameY0)); 759272b676d7Smrg } 759372b676d7Smrg } else { 759472b676d7Smrg /* Head 2 (slave) is always CRT1 */ 759572b676d7Smrg SiSPreSetMode(pScrn, mode, SIS_MODE_CRT1); 759672b676d7Smrg if(!SiSBIOSSetModeCRT1(pSiS->SiS_Pr, pScrn, mode, pSiS->IsCustom)) { 759772b676d7Smrg SISErrorLog(pScrn, "SiSBIOSSetModeCRT1() failed\n"); 759872b676d7Smrg return FALSE; 759972b676d7Smrg } 760072b676d7Smrg SiSPostSetMode(pScrn, &pSiS->ModeReg); 760172b676d7Smrg if(pSiSEnt->pScrn_1) { 76025788ca14Smrg SISAdjustFrame(ADJUST_FRAME_ARGS(pSiSEnt->pScrn_1, 760372b676d7Smrg pSiSEnt->pScrn_1->frameX0, 76045788ca14Smrg pSiSEnt->pScrn_1->frameY0)); 760572b676d7Smrg } 760672b676d7Smrg } 760772b676d7Smrg 760872b676d7Smrg } else { 760972b676d7Smrg#endif 761072b676d7Smrg 761172b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 761272b676d7Smrg 761372b676d7Smrg if(!(*pSiS->ModeInit)(pScrn, mode)) { 761472b676d7Smrg SISErrorLog(pScrn, "ModeInit() failed\n"); 761572b676d7Smrg return FALSE; 761672b676d7Smrg } 761772b676d7Smrg 761872b676d7Smrg pScrn->vtSema = TRUE; 761972b676d7Smrg 762072b676d7Smrg#ifdef SISMERGED 762172b676d7Smrg if(pSiS->MergedFB) { 762272b676d7Smrg 762372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting MergedFB mode %dx%d\n", 762472b676d7Smrg mode->HDisplay, mode->VDisplay); 762572b676d7Smrg 762672b676d7Smrg SiSPreSetMode(pScrn, mode, SIS_MODE_CRT1); 762772b676d7Smrg 762872b676d7Smrg if(!SiSBIOSSetModeCRT1(pSiS->SiS_Pr, pScrn, 762972b676d7Smrg ((SiSMergedDisplayModePtr)mode->Private)->CRT1, 763072b676d7Smrg pSiS->IsCustom)) { 763172b676d7Smrg SISErrorLog(pScrn, "SiSBIOSSetModeCRT1() failed\n"); 763272b676d7Smrg return FALSE; 763372b676d7Smrg } 763472b676d7Smrg 763572b676d7Smrg SiSPreSetMode(pScrn, mode, SIS_MODE_CRT2); 763672b676d7Smrg 763772b676d7Smrg if(!SiSBIOSSetModeCRT2(pSiS->SiS_Pr, pScrn, 763872b676d7Smrg ((SiSMergedDisplayModePtr)mode->Private)->CRT2, 763972b676d7Smrg pSiS->IsCustom)) { 764072b676d7Smrg SISErrorLog(pScrn, "SiSBIOSSetModeCRT2() failed\n"); 764172b676d7Smrg return FALSE; 764272b676d7Smrg } 764372b676d7Smrg 764472b676d7Smrg } else { 764572b676d7Smrg#endif 764672b676d7Smrg 764772b676d7Smrg if((pSiS->VBFlags & CRT1_LCDA) || (!(mode->type & M_T_DEFAULT))) { 764872b676d7Smrg 764972b676d7Smrg SiSPreSetMode(pScrn, mode, SIS_MODE_CRT1); 765072b676d7Smrg 765172b676d7Smrg if(!SiSBIOSSetModeCRT1(pSiS->SiS_Pr, pScrn, 765272b676d7Smrg mode, pSiS->IsCustom)) { 765372b676d7Smrg SISErrorLog(pScrn, "SiSBIOSSetModeCRT1() failed\n"); 765472b676d7Smrg return FALSE; 765572b676d7Smrg } 765672b676d7Smrg 765772b676d7Smrg SiSPreSetMode(pScrn, mode, SIS_MODE_CRT2); 765872b676d7Smrg 765972b676d7Smrg if(!SiSBIOSSetModeCRT2(pSiS->SiS_Pr, pScrn, 766072b676d7Smrg mode, pSiS->IsCustom)) { 766172b676d7Smrg SISErrorLog(pScrn, "SiSBIOSSetModeCRT2() failed\n"); 766272b676d7Smrg return FALSE; 766372b676d7Smrg } 766472b676d7Smrg 766572b676d7Smrg } else { 766672b676d7Smrg 766772b676d7Smrg SiSPreSetMode(pScrn, mode, SIS_MODE_SIMU); 766872b676d7Smrg 766972b676d7Smrg if(!SiSBIOSSetMode(pSiS->SiS_Pr, pScrn, 767072b676d7Smrg mode, pSiS->IsCustom)) { 767172b676d7Smrg SISErrorLog(pScrn, "SiSBIOSSetMode() failed\n"); 767272b676d7Smrg return FALSE; 767372b676d7Smrg } 767472b676d7Smrg 767572b676d7Smrg } 767672b676d7Smrg 767772b676d7Smrg#ifdef SISMERGED 767872b676d7Smrg } 767972b676d7Smrg#endif 768072b676d7Smrg 768172b676d7Smrg SiSPostSetMode(pScrn, &pSiS->ModeReg); 768272b676d7Smrg 768372b676d7Smrg#ifdef TWDEBUG 768472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VBFlags %lx\n", pSiS->VBFlags); 768572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 768672b676d7Smrg "REAL REGISTER CONTENTS AFTER SETMODE:\n"); 768772b676d7Smrg (*pSiS->ModeInit)(pScrn, mode); 768872b676d7Smrg#endif 768972b676d7Smrg 769072b676d7Smrg } else { 769172b676d7Smrg 769272b676d7Smrg /* For other chipsets, use the old method */ 769372b676d7Smrg 769472b676d7Smrg /* Prepare the register contents */ 769572b676d7Smrg if(!(*pSiS->ModeInit)(pScrn, mode)) { 769672b676d7Smrg SISErrorLog(pScrn, "ModeInit() failed\n"); 769772b676d7Smrg return FALSE; 769872b676d7Smrg } 769972b676d7Smrg 770072b676d7Smrg pScrn->vtSema = TRUE; 770172b676d7Smrg 770272b676d7Smrg /* Program the registers */ 770372b676d7Smrg SiSVGAProtect(pScrn, TRUE); 770472b676d7Smrg sisReg = &pSiS->ModeReg; 770572b676d7Smrg 770672b676d7Smrg sisReg->sisRegsATTR[0x10] = 0x01; 770772b676d7Smrg if(pScrn->bitsPerPixel > 8) { 770872b676d7Smrg sisReg->sisRegsGR[0x05] = 0x00; 770972b676d7Smrg } 771072b676d7Smrg 771172b676d7Smrg SiSVGARestore(pScrn, sisReg, SISVGA_SR_MODE); 771272b676d7Smrg 771372b676d7Smrg (*pSiS->SiSRestore)(pScrn, sisReg); 771472b676d7Smrg 771572b676d7Smrg if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 771672b676d7Smrg SiS6326PostSetMode(pScrn, &pSiS->ModeReg); 771772b676d7Smrg } 771872b676d7Smrg 771972b676d7Smrg#ifdef TWDEBUG 772072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 772172b676d7Smrg "REAL REGISTER CONTENTS AFTER SETMODE:\n"); 772272b676d7Smrg (*pSiS->ModeInit)(pScrn, mode); 772372b676d7Smrg#endif 772472b676d7Smrg 772572b676d7Smrg SiSVGAProtect(pScrn, FALSE); 772672b676d7Smrg 772772b676d7Smrg } 772872b676d7Smrg 772972b676d7Smrg#ifdef SISDUALHEAD 773072b676d7Smrg } 773172b676d7Smrg#endif 773272b676d7Smrg } 773372b676d7Smrg 773472b676d7Smrg /* Update Currentlayout */ 773572b676d7Smrg pSiS->CurrentLayout.mode = pSiS->currentModeLast = mode; 773672b676d7Smrg 773772b676d7Smrg return TRUE; 773872b676d7Smrg} 773972b676d7Smrg 774072b676d7Smrgstatic Bool 774172b676d7SmrgSiSSetVESAMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) 774272b676d7Smrg{ 774372b676d7Smrg SISPtr pSiS; 774472b676d7Smrg int mode; 774572b676d7Smrg 774672b676d7Smrg pSiS = SISPTR(pScrn); 774772b676d7Smrg 774872b676d7Smrg if(!(mode = SiSCalcVESAModeIndex(pScrn, pMode))) return FALSE; 774972b676d7Smrg 775072b676d7Smrg mode |= (1 << 15); /* Don't clear framebuffer */ 775172b676d7Smrg mode |= (1 << 14); /* Use linear adressing */ 775272b676d7Smrg 775372b676d7Smrg if(VBESetVBEMode(pSiS->pVbe, mode, NULL) == FALSE) { 775472b676d7Smrg SISErrorLog(pScrn, "Setting VESA mode 0x%x failed\n", 775572b676d7Smrg mode & 0x0fff); 775672b676d7Smrg return (FALSE); 775772b676d7Smrg } 775872b676d7Smrg 775972b676d7Smrg if(pMode->HDisplay != pScrn->virtualX) { 776072b676d7Smrg VBESetLogicalScanline(pSiS->pVbe, pScrn->virtualX); 776172b676d7Smrg } 776272b676d7Smrg 776372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 776472b676d7Smrg "Setting VESA mode 0x%x succeeded\n", 776572b676d7Smrg mode & 0x0fff); 776672b676d7Smrg 776772b676d7Smrg return (TRUE); 776872b676d7Smrg} 776972b676d7Smrg 777072b676d7Smrgstatic void 777172b676d7SmrgSISSpecialRestore(ScrnInfoPtr pScrn) 777272b676d7Smrg{ 777372b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 777472b676d7Smrg SISRegPtr sisReg = &pSiS->SavedReg; 777572b676d7Smrg UChar temp; 777672b676d7Smrg int i; 777772b676d7Smrg 777872b676d7Smrg /* 1.11.04 and later for 651 and 301B(DH) do strange register 777972b676d7Smrg * fiddling after the usual mode change. This happens 778072b676d7Smrg * depending on the result of a call of int 2f (with 778172b676d7Smrg * ax=0x1680) and if modeno <= 0x13. I have no idea if 778272b676d7Smrg * that is specific for the 651 or that very machine. 778372b676d7Smrg * So this perhaps requires some more checks in the beginning 778472b676d7Smrg * (although it should not do any harm on other chipsets/bridges 778572b676d7Smrg * etc.) However, even if I call the VBE to restore mode 0x03, 778672b676d7Smrg * these registers don't get restored correctly, possibly 778772b676d7Smrg * because that int-2f-call for some reason results non-zero. So 778872b676d7Smrg * what I do here is to restore these few registers 778972b676d7Smrg * manually. 779072b676d7Smrg */ 779172b676d7Smrg 779272b676d7Smrg if(!(pSiS->ChipFlags & SiSCF_Is65x)) return; 779372b676d7Smrg inSISIDXREG(SISCR, 0x34, temp); 779472b676d7Smrg temp &= 0x7f; 779572b676d7Smrg if(temp > 0x13) return; 779672b676d7Smrg 779772b676d7Smrg#ifdef UNLOCK_ALWAYS 779872b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 779972b676d7Smrg#endif 780072b676d7Smrg 780172b676d7Smrg SiS_UnLockCRT2(pSiS->SiS_Pr); 780272b676d7Smrg 780372b676d7Smrg outSISIDXREG(SISCAP, 0x3f, sisReg->sisCapt[0x3f]); 780472b676d7Smrg outSISIDXREG(SISCAP, 0x00, sisReg->sisCapt[0x00]); 780572b676d7Smrg for(i = 0; i < 0x4f; i++) { 780672b676d7Smrg outSISIDXREG(SISCAP, i, sisReg->sisCapt[i]); 780772b676d7Smrg } 780872b676d7Smrg outSISIDXREG(SISVID, 0x32, (sisReg->sisVid[0x32] & ~0x05)); 780972b676d7Smrg outSISIDXREG(SISVID, 0x30, sisReg->sisVid[0x30]); 781072b676d7Smrg outSISIDXREG(SISVID, 0x32, ((sisReg->sisVid[0x32] & ~0x04) | 0x01)); 781172b676d7Smrg outSISIDXREG(SISVID, 0x30, sisReg->sisVid[0x30]); 781272b676d7Smrg 781372b676d7Smrg if(!(pSiS->ChipFlags & SiSCF_Is651)) return; 781472b676d7Smrg if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 781572b676d7Smrg 781672b676d7Smrg inSISIDXREG(SISCR, 0x30, temp); 781772b676d7Smrg if(temp & 0x40) { 781872b676d7Smrg UChar myregs[] = { 781972b676d7Smrg 0x2f, 0x08, 0x09, 0x03, 0x0a, 0x0c, 782072b676d7Smrg 0x0b, 0x0d, 0x0e, 0x12, 0x0f, 0x10, 782172b676d7Smrg 0x11, 0x04, 0x05, 0x06, 0x07, 0x00, 782272b676d7Smrg 0x2e 782372b676d7Smrg }; 782472b676d7Smrg for(i = 0; i <= 18; i++) { 782572b676d7Smrg outSISIDXREG(SISPART1, myregs[i], sisReg->VBPart1[myregs[i]]); 782672b676d7Smrg } 782772b676d7Smrg } else if((temp & 0x20) || (temp & 0x9c)) { 782872b676d7Smrg UChar myregs[] = { 782972b676d7Smrg 0x04, 0x05, 0x06, 0x07, 0x00, 0x2e 783072b676d7Smrg }; 783172b676d7Smrg for(i = 0; i <= 5; i++) { 783272b676d7Smrg outSISIDXREG(SISPART1, myregs[i], sisReg->VBPart1[myregs[i]]); 783372b676d7Smrg } 783472b676d7Smrg } 783572b676d7Smrg} 783672b676d7Smrg 783772b676d7Smrg/* Fix SR11 for 661 and later */ 783872b676d7Smrgstatic void 783972b676d7SmrgSiSFixupSR11(ScrnInfoPtr pScrn) 784072b676d7Smrg{ 784172b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 784272b676d7Smrg CARD8 tmpreg; 784372b676d7Smrg 784472b676d7Smrg#ifdef UNLOCK_ALWAYS 784572b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 784672b676d7Smrg#endif 784772b676d7Smrg 784872b676d7Smrg if(pSiS->ChipType >= SIS_661) { 784972b676d7Smrg inSISIDXREG(SISSR,0x11,tmpreg); 785072b676d7Smrg if(tmpreg & 0x20) { 785172b676d7Smrg inSISIDXREG(SISSR,0x3e,tmpreg); 785272b676d7Smrg tmpreg = (tmpreg + 1) & 0xff; 785372b676d7Smrg outSISIDXREG(SISSR,0x3e,tmpreg); 785472b676d7Smrg } 785572b676d7Smrg 785672b676d7Smrg inSISIDXREG(SISSR,0x11,tmpreg); 785772b676d7Smrg if(tmpreg & 0xf0) { 785872b676d7Smrg andSISIDXREG(SISSR,0x11,0x0f); 785972b676d7Smrg } 786072b676d7Smrg } 786172b676d7Smrg} 786272b676d7Smrg 786372b676d7Smrg/* Subroutine for restoring sisfb's TV parameters (used by SiSRestore()) */ 786472b676d7Smrg 786572b676d7Smrgstatic void 786672b676d7SmrgSiSRestore_SiSFB_TVParms(ScrnInfoPtr pScrn) 786772b676d7Smrg{ 786872b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 786972b676d7Smrg int fd; 787072b676d7Smrg CARD32 parm; 787172b676d7Smrg 787272b676d7Smrg if(!pSiS->sisfbfound) return; 787372b676d7Smrg if(!pSiS->sisfb_tvposvalid) return; 787472b676d7Smrg if(!(pSiS->sisfbdevname[0])) return; 787572b676d7Smrg 78761fd23544Smrg if((fd = open(pSiS->sisfbdevname, O_RDONLY)) != -1) { 787772b676d7Smrg parm = (CARD32)((pSiS->sisfb_tvxpos << 16) | (pSiS->sisfb_tvypos & 0xffff)); 787872b676d7Smrg ioctl(fd, SISFB_SET_TVPOSOFFSET, &parm); 787972b676d7Smrg close(fd); 788072b676d7Smrg } 788172b676d7Smrg} 788272b676d7Smrg 788372b676d7Smrg/* 788472b676d7Smrg * Restore the initial mode. To be used internally only! 788572b676d7Smrg */ 788672b676d7Smrgstatic void 788772b676d7SmrgSISRestore(ScrnInfoPtr pScrn) 788872b676d7Smrg{ 788972b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 789072b676d7Smrg SISRegPtr sisReg = &pSiS->SavedReg; 789172b676d7Smrg Bool doit = FALSE, doitlater = FALSE; 789272b676d7Smrg Bool vesasuccess = FALSE; 789372b676d7Smrg int flags; 789472b676d7Smrg 789572b676d7Smrg /* WARNING: Don't ever touch this. It now seems to work on 789672b676d7Smrg * all chipset/bridge combinations - but finding out the 789772b676d7Smrg * correct combination was pure hell. 789872b676d7Smrg */ 789972b676d7Smrg 790072b676d7Smrg /* Wait for the accelerators */ 790172b676d7Smrg (*pSiS->SyncAccel)(pScrn); 790272b676d7Smrg 790372b676d7Smrg /* Set up restore flags */ 790472b676d7Smrg flags = SISVGA_SR_MODE | SISVGA_SR_CMAP; 790572b676d7Smrg#ifdef SIS_PC_PLATFORM 790672b676d7Smrg /* We now restore ALL to overcome the vga=extended problem */ 790772b676d7Smrg if(pSiS->VGAMemBase) flags |= SISVGA_SR_FONTS; 790872b676d7Smrg#endif 790972b676d7Smrg 791072b676d7Smrg if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 791172b676d7Smrg 791272b676d7Smrg#ifdef SISDUALHEAD 791372b676d7Smrg /* We always restore master AND slave */ 791472b676d7Smrg if(pSiS->DualHeadMode && pSiS->SecondHead) return; 791572b676d7Smrg#endif 791672b676d7Smrg 791772b676d7Smrg#ifdef UNLOCK_ALWAYS 791872b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 791972b676d7Smrg#endif 792072b676d7Smrg 792172b676d7Smrg /* We must not disable the sequencer if the bridge is in SlaveMode! */ 792272b676d7Smrg if(!(SiSBridgeIsInSlaveMode(pScrn))) { 792372b676d7Smrg SiSVGAProtect(pScrn, TRUE); 792472b676d7Smrg } 792572b676d7Smrg 792672b676d7Smrg /* First, restore CRT1 on/off and VB connection registers */ 792772b676d7Smrg outSISIDXREG(SISCR, 0x32, pSiS->oldCR32); 792872b676d7Smrg if(!(pSiS->oldCR17 & 0x80)) { /* CRT1 was off */ 792972b676d7Smrg if(!(SiSBridgeIsInSlaveMode(pScrn))) { /* Bridge is NOT in SlaveMode now -> do it */ 793072b676d7Smrg doit = TRUE; 793172b676d7Smrg } else { 793272b676d7Smrg doitlater = TRUE; 793372b676d7Smrg } 793472b676d7Smrg } else { /* CRT1 was on -> do it now */ 793572b676d7Smrg doit = TRUE; 793672b676d7Smrg } 793772b676d7Smrg 793872b676d7Smrg if(doit) { 793972b676d7Smrg outSISIDXREG(SISCR, 0x17, pSiS->oldCR17); 794072b676d7Smrg } 794172b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 794272b676d7Smrg outSISIDXREG(SISCR, pSiS->myCR63, pSiS->oldCR63); 794372b676d7Smrg } 794472b676d7Smrg 794572b676d7Smrg outSISIDXREG(SISSR, 0x1f, pSiS->oldSR1F); 794672b676d7Smrg 794772b676d7Smrg /* For 30xB/LV, restoring the registers does not 794872b676d7Smrg * work. We "manually" set the old mode, instead. 794972b676d7Smrg * The same applies for SiS730 machines with LVDS. 795072b676d7Smrg * Finally, this behavior can be forced by setting 795172b676d7Smrg * the option RestoreBySetMode. 795272b676d7Smrg */ 795372b676d7Smrg if( ( (pSiS->restorebyset) || 795472b676d7Smrg (pSiS->VBFlags2 & VB2_30xBLV) || 795572b676d7Smrg ((pSiS->ChipType == SIS_730) && (pSiS->VBFlags2 & VB2_LVDS)) ) && 795672b676d7Smrg (pSiS->OldMode) ) { 795772b676d7Smrg 795872b676d7Smrg Bool changedmode = FALSE; 795972b676d7Smrg 796072b676d7Smrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 796172b676d7Smrg "Restoring by setting old mode 0x%02x\n", pSiS->OldMode); 796272b676d7Smrg 796372b676d7Smrg if(((pSiS->OldMode <= 0x13) || (!pSiS->sisfbfound)) && (pSiS->pVbe)) { 796472b676d7Smrg int vmode = SiSTranslateToVESA(pScrn, pSiS->OldMode); 796572b676d7Smrg if(vmode > 0) { 796672b676d7Smrg if(vmode > 0x13) vmode |= ((1 << 15) | (1 << 14)); 796772b676d7Smrg if(VBESetVBEMode(pSiS->pVbe, vmode, NULL) == TRUE) { 796872b676d7Smrg SISSpecialRestore(pScrn); 796972b676d7Smrg SiS_GetSetModeID(pScrn,pSiS->OldMode); 797072b676d7Smrg vesasuccess = TRUE; 797172b676d7Smrg } else { 797272b676d7Smrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 797372b676d7Smrg "VBE failed to restore mode 0x%x\n", pSiS->OldMode); 797472b676d7Smrg } 797572b676d7Smrg } else { 797672b676d7Smrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 797772b676d7Smrg "Can't identify VESA mode number for mode 0x%x\n", pSiS->OldMode); 797872b676d7Smrg } 797972b676d7Smrg } 798072b676d7Smrg 798172b676d7Smrg if(vesasuccess == FALSE) { 798272b676d7Smrg 798372b676d7Smrg int backupscaler = pSiS->SiS_Pr->UsePanelScaler; 798472b676d7Smrg int backupcenter = pSiS->SiS_Pr->CenterScreen; 798572b676d7Smrg ULong backupspecialtiming = pSiS->SiS_Pr->SiS_CustomT; 798672b676d7Smrg int mymode = pSiS->OldMode; 798772b676d7Smrg 798872b676d7Smrg if((pSiS->VGAEngine == SIS_315_VGA) && 798972b676d7Smrg ((pSiS->ROM661New) || (pSiS->ChipFlags & SiSCF_IsXGI)) && 799072b676d7Smrg (!pSiS->sisfbfound)) { 799172b676d7Smrg /* New SiS BIOS or XGI BIOS has set mode, therefore eventually translate number */ 799272b676d7Smrg mymode = SiSTranslateToOldMode(mymode); 799372b676d7Smrg } 799472b676d7Smrg 799572b676d7Smrg if((pSiS->VBFlags2 & VB2_30xBLV)) { 799672b676d7Smrg /* !!! REQUIRED for 630+301B-DH, otherwise the text modes 799772b676d7Smrg * will not be restored correctly !!! 799872b676d7Smrg * !!! Do this ONLY for LCD; VGA2 will not be restored 799972b676d7Smrg * correctly otherwise. 800072b676d7Smrg */ 800172b676d7Smrg UChar temp; 800272b676d7Smrg inSISIDXREG(SISCR, 0x30, temp); 800372b676d7Smrg if(temp & 0x20) { 800472b676d7Smrg if(mymode == 0x03) { 800572b676d7Smrg mymode = 0x13; 800672b676d7Smrg changedmode = TRUE; 800772b676d7Smrg } 800872b676d7Smrg } 800972b676d7Smrg } 801072b676d7Smrg 801172b676d7Smrg pSiS->SiS_Pr->UseCustomMode = FALSE; 801272b676d7Smrg pSiS->SiS_Pr->CRT1UsesCustomMode = FALSE; 801372b676d7Smrg pSiS->SiS_Pr->CenterScreen = 0; 801472b676d7Smrg if(pSiS->sisfbfound) { 801572b676d7Smrg pSiS->SiS_Pr->UsePanelScaler = pSiS->sisfbscalelcd; 801672b676d7Smrg pSiS->SiS_Pr->SiS_CustomT = pSiS->sisfbspecialtiming; 801772b676d7Smrg } else { 801872b676d7Smrg pSiS->SiS_Pr->UsePanelScaler = -1; 801972b676d7Smrg /* Leave CustomT as it is */ 802072b676d7Smrg } 802172b676d7Smrg SiS_SetEnableDstn(pSiS->SiS_Pr, FALSE); 802272b676d7Smrg SiS_SetEnableFstn(pSiS->SiS_Pr, FALSE); 802372b676d7Smrg if((pSiS->ChipType == SIS_550) && (pSiS->sisfbfound)) { 802472b676d7Smrg if(pSiS->sisfbxSTN) { 802572b676d7Smrg SiS_SetEnableDstn(pSiS->SiS_Pr, pSiS->sisfbDSTN); 802672b676d7Smrg SiS_SetEnableFstn(pSiS->SiS_Pr, pSiS->sisfbFSTN); 802772b676d7Smrg } else if(mymode == 0x5a || mymode == 0x5b) { 802872b676d7Smrg SiS_SetEnableFstn(pSiS->SiS_Pr, TRUE); 802972b676d7Smrg } 803072b676d7Smrg } 803172b676d7Smrg SiSSetMode(pSiS->SiS_Pr, pScrn, mymode, FALSE); 803272b676d7Smrg if(changedmode) { 803372b676d7Smrg outSISIDXREG(SISCR,0x34,0x03); 803472b676d7Smrg } 803572b676d7Smrg SISSpecialRestore(pScrn); 803672b676d7Smrg SiS_GetSetModeID(pScrn, pSiS->OldMode); /* NOT mymode! */ 803772b676d7Smrg pSiS->SiS_Pr->UsePanelScaler = backupscaler; 803872b676d7Smrg pSiS->SiS_Pr->CenterScreen = backupcenter; 803972b676d7Smrg pSiS->SiS_Pr->SiS_CustomT = backupspecialtiming; 804072b676d7Smrg SiS_SiSFB_Lock(pScrn, FALSE); 804172b676d7Smrg SiSRestore_SiSFB_TVParms(pScrn); 804272b676d7Smrg SiS_SiSFB_Lock(pScrn, TRUE); 804372b676d7Smrg 804472b676d7Smrg } 804572b676d7Smrg 804672b676d7Smrg /* Restore CRT1 status */ 804772b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 804872b676d7Smrg outSISIDXREG(SISCR, pSiS->myCR63, pSiS->oldCR63); 804972b676d7Smrg } 805072b676d7Smrg outSISIDXREG(SISSR, 0x1f, pSiS->oldSR1F); 805172b676d7Smrg 805272b676d7Smrg#ifdef SISVRAMQ 805372b676d7Smrg /* Restore queue mode registers on 315/330/340 series */ 805472b676d7Smrg /* (This became necessary due to the switch to VRAM queue) */ 805572b676d7Smrg SiSRestoreQueueMode(pSiS, sisReg); 805672b676d7Smrg#endif 805772b676d7Smrg 805872b676d7Smrg } else { 805972b676d7Smrg 806072b676d7Smrg if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) { 806172b676d7Smrg /* If a video bridge is present, we need to restore 806272b676d7Smrg * non-extended (=standard VGA) SR and CR registers 806372b676d7Smrg * before restoring the extended ones and the bridge 806472b676d7Smrg * registers. 806572b676d7Smrg */ 806672b676d7Smrg if(!(SiSBridgeIsInSlaveMode(pScrn))) { 806772b676d7Smrg SiSVGAProtect(pScrn, TRUE); 806872b676d7Smrg SiSVGARestore(pScrn, sisReg, SISVGA_SR_MODE); 806972b676d7Smrg } 807072b676d7Smrg } 807172b676d7Smrg 807272b676d7Smrg (*pSiS->SiSRestore)(pScrn, sisReg); 807372b676d7Smrg 807472b676d7Smrg } 807572b676d7Smrg 807672b676d7Smrg if(doitlater) { 807772b676d7Smrg outSISIDXREG(SISCR, 0x17, pSiS->oldCR17); 807872b676d7Smrg } 807972b676d7Smrg 808072b676d7Smrg 808172b676d7Smrg 808272b676d7Smrg if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (SiSBridgeIsInSlaveMode(pScrn))) { 808372b676d7Smrg 808472b676d7Smrg /* IMPORTANT: The 30xLV does not handle well being disabled if in 808572b676d7Smrg * LCDA mode! In LCDA mode, the bridge is NOT in slave mode, 808672b676d7Smrg * so this is the only safe way: Disable the bridge ONLY if 808772b676d7Smrg * in Slave Mode, and don't bother if not. 808872b676d7Smrg */ 808972b676d7Smrg 809072b676d7Smrg if(flags & SISVGA_SR_FONTS) { 809172b676d7Smrg SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO+0x30); 80925788ca14Smrg SiSSetLVDSetc(pSiS->SiS_Pr); 809372b676d7Smrg SiS_GetVBType(pSiS->SiS_Pr); 809472b676d7Smrg SiS_DisableBridge(pSiS->SiS_Pr); 809572b676d7Smrg SiSVGAProtect(pScrn, TRUE); 809672b676d7Smrg } 809772b676d7Smrg 809872b676d7Smrg SiSVGARestore(pScrn, sisReg, flags); 809972b676d7Smrg 810072b676d7Smrg if(flags & SISVGA_SR_FONTS) { 810172b676d7Smrg SiSVGAProtect(pScrn, FALSE); 810272b676d7Smrg SiS_EnableBridge(pSiS->SiS_Pr); 810372b676d7Smrg andSISIDXREG(SISSR, 0x01, ~0x20); /* Display on */ 810472b676d7Smrg } 810572b676d7Smrg 810672b676d7Smrg } else { 810772b676d7Smrg 810872b676d7Smrg SiSVGAProtect(pScrn, TRUE); 810972b676d7Smrg SiSVGARestore(pScrn, sisReg, flags); 811072b676d7Smrg SiSVGAProtect(pScrn, FALSE); 811172b676d7Smrg 811272b676d7Smrg } 811372b676d7Smrg 811472b676d7Smrg SiSFixupSR11(pScrn); 811572b676d7Smrg 811672b676d7Smrg#ifdef TWDEBUG 811772b676d7Smrg { 811872b676d7Smrg SISRegPtr pReg = &pSiS->ModeReg; 811972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 812072b676d7Smrg "REAL REGISTER CONTENTS AFTER RESTORE BY SETMODE:\n"); 812172b676d7Smrg (*pSiS->SiSSave)(pScrn, pReg); 812272b676d7Smrg } 812372b676d7Smrg#endif 812472b676d7Smrg 812572b676d7Smrg sisRestoreExtRegisterLock(pSiS,sisReg->sisRegs3C4[0x05],sisReg->sisRegs3D4[0x80]); 812672b676d7Smrg 812772b676d7Smrg } else { /* All other chipsets */ 812872b676d7Smrg 812972b676d7Smrg SiSVGAProtect(pScrn, TRUE); 813072b676d7Smrg 813172b676d7Smrg#ifdef UNLOCK_ALWAYS 813272b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 813372b676d7Smrg#endif 813472b676d7Smrg 813572b676d7Smrg (*pSiS->SiSRestore)(pScrn, sisReg); 813672b676d7Smrg 813772b676d7Smrg SiSVGAProtect(pScrn, TRUE); 813872b676d7Smrg 813972b676d7Smrg SiSVGARestore(pScrn, sisReg, flags); 814072b676d7Smrg 814172b676d7Smrg /* Restore TV. This is rather complicated, but if we don't do it, 814272b676d7Smrg * TV output will flicker terribly 814372b676d7Smrg */ 814472b676d7Smrg if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 814572b676d7Smrg if(sisReg->sis6326tv[0] & 0x04) { 814672b676d7Smrg UChar tmp; 814772b676d7Smrg int val; 814872b676d7Smrg 814972b676d7Smrg orSISIDXREG(SISSR, 0x01, 0x20); 815072b676d7Smrg tmp = SiS6326GetTVReg(pScrn,0x00); 815172b676d7Smrg tmp &= ~0x04; 815272b676d7Smrg while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 815372b676d7Smrg SiS6326SetTVReg(pScrn,0x00,tmp); 815472b676d7Smrg for(val=0; val < 2; val++) { 815572b676d7Smrg while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 815672b676d7Smrg while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 815772b676d7Smrg } 815872b676d7Smrg SiS6326SetTVReg(pScrn, 0x00, sisReg->sis6326tv[0]); 815972b676d7Smrg tmp = inSISREG(SISINPSTAT); 816072b676d7Smrg outSISREG(SISAR, 0x20); 816172b676d7Smrg tmp = inSISREG(SISINPSTAT); 816272b676d7Smrg while(inSISREG(SISINPSTAT) & 0x01); 816372b676d7Smrg while(!(inSISREG(SISINPSTAT) & 0x01)); 816472b676d7Smrg andSISIDXREG(SISSR, 0x01, ~0x20); 816572b676d7Smrg for(val=0; val < 10; val++) { 816672b676d7Smrg while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 816772b676d7Smrg while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 816872b676d7Smrg } 816972b676d7Smrg andSISIDXREG(SISSR, 0x01, ~0x20); 817072b676d7Smrg } 817172b676d7Smrg } 817272b676d7Smrg 817372b676d7Smrg sisRestoreExtRegisterLock(pSiS,sisReg->sisRegs3C4[5],sisReg->sisRegs3D4[0x80]); 817472b676d7Smrg 817572b676d7Smrg SiSVGAProtect(pScrn, FALSE); 817672b676d7Smrg } 817772b676d7Smrg} 817872b676d7Smrg 817972b676d7Smrgstatic void 818072b676d7SmrgSISVESARestore(ScrnInfoPtr pScrn) 818172b676d7Smrg{ 818272b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 818372b676d7Smrg#ifdef SISVRAMQ 818472b676d7Smrg SISRegPtr sisReg = &pSiS->SavedReg; 818572b676d7Smrg#endif 818672b676d7Smrg 818772b676d7Smrg if(pSiS->UseVESA) { 818872b676d7Smrg SISVESASaveRestore(pScrn, MODE_RESTORE); 818972b676d7Smrg#ifdef SISVRAMQ 819072b676d7Smrg /* Restore queue mode registers on 315/330/340 series */ 819172b676d7Smrg /* (This became necessary due to the switch to VRAM queue) */ 819272b676d7Smrg SiSRestoreQueueMode(pSiS, sisReg); 819372b676d7Smrg#endif 819472b676d7Smrg } 819572b676d7Smrg} 819672b676d7Smrg 819772b676d7Smrg/* Restore bridge config registers - to be called BEFORE VESARestore */ 819872b676d7Smrgstatic void 819972b676d7SmrgSISBridgeRestore(ScrnInfoPtr pScrn) 820072b676d7Smrg{ 820172b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 820272b676d7Smrg 820372b676d7Smrg#ifdef SISDUALHEAD 820472b676d7Smrg /* We only restore for master head */ 820572b676d7Smrg if(pSiS->DualHeadMode && pSiS->SecondHead) return; 820672b676d7Smrg#endif 820772b676d7Smrg 820872b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 820972b676d7Smrg SiSRestoreBridge(pScrn, &pSiS->SavedReg); 821072b676d7Smrg } 821172b676d7Smrg} 821272b676d7Smrg 821372b676d7Smrg/* Our BlockHandler */ 821472b676d7Smrgstatic void 82155788ca14SmrgSISBlockHandler(BLOCKHANDLER_ARGS_DECL) 821672b676d7Smrg{ 82175788ca14Smrg SCREEN_PTR(arg); 82185788ca14Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 821972b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 822072b676d7Smrg 822172b676d7Smrg pScreen->BlockHandler = pSiS->BlockHandler; 82225788ca14Smrg (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS); 822372b676d7Smrg pScreen->BlockHandler = SISBlockHandler; 822472b676d7Smrg 822572b676d7Smrg#ifdef SISDUALHEAD 822672b676d7Smrg if(pSiS->NeedCopyFastVidCpy) { 822772b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 822872b676d7Smrg if(pSiSEnt->HaveFastVidCpy) { 822972b676d7Smrg pSiS->NeedCopyFastVidCpy = FALSE; 823072b676d7Smrg pSiS->SiSFastVidCopy = pSiSEnt->SiSFastVidCopy; 823172b676d7Smrg pSiS->SiSFastMemCopy = pSiSEnt->SiSFastMemCopy; 823272b676d7Smrg pSiS->SiSFastVidCopyFrom = pSiSEnt->SiSFastVidCopyFrom; 823372b676d7Smrg pSiS->SiSFastMemCopyFrom = pSiSEnt->SiSFastMemCopyFrom; 823472b676d7Smrg } 823572b676d7Smrg } 823672b676d7Smrg#endif 823772b676d7Smrg 823872b676d7Smrg if(pSiS->VideoTimerCallback) { 823972b676d7Smrg (*pSiS->VideoTimerCallback)(pScrn, currentTime.milliseconds); 824072b676d7Smrg } 824172b676d7Smrg 824272b676d7Smrg#ifdef SIS_USE_XAA 824372b676d7Smrg if(pSiS->RenderCallback) { 824472b676d7Smrg (*pSiS->RenderCallback)(pScrn); 824572b676d7Smrg } 824672b676d7Smrg#endif 824772b676d7Smrg#ifdef SIS_USE_EXA 824872b676d7Smrg if(pSiS->ExaRenderCallback) { 824972b676d7Smrg (*pSiS->ExaRenderCallback)(pScrn); 825072b676d7Smrg } 825172b676d7Smrg#endif 825272b676d7Smrg} 825372b676d7Smrg 825472b676d7Smrg 825572b676d7Smrg 825672b676d7Smrg/* Do screen blanking; DPMS handling 825772b676d7Smrg * 825872b676d7Smrg * Mandatory; latter optional 825972b676d7Smrg */ 826072b676d7Smrg 826172b676d7Smrgstatic void 826272b676d7SmrgSiSHandleBackLight(SISPtr pSiS, Bool blon) 826372b676d7Smrg{ 826472b676d7Smrg UChar sr11mask = (pSiS->SiS_Pr->SiS_SensibleSR11) ? 0x03 : 0xf3; 826572b676d7Smrg 826672b676d7Smrg if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) { 826772b676d7Smrg 826872b676d7Smrg if(!blon) { 826972b676d7Smrg SiS_SiS30xBLOff(pSiS->SiS_Pr); 827072b676d7Smrg } else { 827172b676d7Smrg SiS_SiS30xBLOn(pSiS->SiS_Pr); 827272b676d7Smrg } 827372b676d7Smrg 827472b676d7Smrg } else if( ((pSiS->VGAEngine == SIS_300_VGA) && 827572b676d7Smrg (pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH))) || 827672b676d7Smrg ((pSiS->VGAEngine == SIS_315_VGA) && 827772b676d7Smrg ((pSiS->VBFlags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS)) ) { 827872b676d7Smrg 827972b676d7Smrg if(!blon) { 828072b676d7Smrg setSISIDXREG(SISSR, 0x11, sr11mask, 0x08); 828172b676d7Smrg } else { 828272b676d7Smrg setSISIDXREG(SISSR, 0x11, sr11mask, 0x00); 828372b676d7Smrg } 828472b676d7Smrg 828572b676d7Smrg } else if((pSiS->VGAEngine == SIS_315_VGA) && 828672b676d7Smrg (pSiS->VBFlags2 & VB2_CHRONTEL)) { 828772b676d7Smrg 828872b676d7Smrg if(!blon) { 828972b676d7Smrg SiS_Chrontel701xBLOff(pSiS->SiS_Pr); 829072b676d7Smrg } else { 829172b676d7Smrg SiS_Chrontel701xBLOn(pSiS->SiS_Pr); 829272b676d7Smrg } 829372b676d7Smrg 829472b676d7Smrg } 829572b676d7Smrg} 829672b676d7Smrg 829772b676d7Smrgstatic Bool 829872b676d7SmrgSISSaveScreen(ScreenPtr pScreen, int mode) 829972b676d7Smrg{ 83005788ca14Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 830172b676d7Smrg SISPtr pSiS; 830272b676d7Smrg Bool IsUnblank = xf86IsUnblank(mode) ? TRUE : FALSE; 830372b676d7Smrg 830472b676d7Smrg if((pScrn == NULL) || (!pScrn->vtSema)) return TRUE; 830572b676d7Smrg 830672b676d7Smrg pSiS = SISPTR(pScrn); 830772b676d7Smrg 830872b676d7Smrg#ifdef UNLOCK_ALWAYS 830972b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 831072b676d7Smrg#endif 831172b676d7Smrg 831272b676d7Smrg if(pSiS->VBFlags & (CRT2_LCD | CRT1_LCDA)) { 831372b676d7Smrg SiSHandleBackLight(pSiS, IsUnblank); 831472b676d7Smrg } 831572b676d7Smrg 831672b676d7Smrg if(!SiSBridgeIsInSlaveMode(pScrn)) { 831772b676d7Smrg return SiSVGASaveScreen(pScreen, mode); 831872b676d7Smrg } 831972b676d7Smrg 832072b676d7Smrg return TRUE; 832172b676d7Smrg} 832272b676d7Smrg 832372b676d7Smrg#ifdef SISDUALHEAD 832472b676d7Smrg/* SaveScreen for dual head mode */ 832572b676d7Smrgstatic Bool 832672b676d7SmrgSISSaveScreenDH(ScreenPtr pScreen, int mode) 832772b676d7Smrg{ 83285788ca14Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 832972b676d7Smrg SISPtr pSiS; 833072b676d7Smrg Bool IsUnblank = xf86IsUnblank(mode) ? TRUE : FALSE; 833172b676d7Smrg 833272b676d7Smrg if((pScrn == NULL) || (!pScrn->vtSema)) return TRUE; 833372b676d7Smrg 833472b676d7Smrg pSiS = SISPTR(pScrn); 833572b676d7Smrg 833672b676d7Smrg if( (pSiS->SecondHead) && 833772b676d7Smrg ((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) ) { 833872b676d7Smrg 833972b676d7Smrg /* Slave head is always CRT1 */ 834072b676d7Smrg /* (No backlight handling on TMDS bridges) */ 834172b676d7Smrg return SiSVGASaveScreen(pScreen, mode); 834272b676d7Smrg 834372b676d7Smrg } else { 834472b676d7Smrg 834572b676d7Smrg /* Master head is always CRT2 */ 834672b676d7Smrg /* But we land here for LCDA, too (if bridge is SiS LVDS type) */ 834772b676d7Smrg 834872b676d7Smrg /* We can only blank LCD, not other CRT2 devices */ 834972b676d7Smrg if(pSiS->VBFlags & (CRT2_LCD|CRT1_LCDA)) { 835072b676d7Smrg 835172b676d7Smrg#ifdef UNLOCK_ALWAYS 835272b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 835372b676d7Smrg#endif 835472b676d7Smrg SiSHandleBackLight(pSiS, IsUnblank); 835572b676d7Smrg 835672b676d7Smrg } 835772b676d7Smrg 835872b676d7Smrg } 835972b676d7Smrg return TRUE; 836072b676d7Smrg} 836172b676d7Smrg#endif 836272b676d7Smrg 836372b676d7Smrgstatic void 836472b676d7SmrgSISDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags) 836572b676d7Smrg{ 836672b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 836772b676d7Smrg Bool docrt1 = TRUE, docrt2 = TRUE, backlight = TRUE; 836872b676d7Smrg UChar sr1=0, cr17=0, cr63=0, pmreg=0, sr7=0; 836972b676d7Smrg UChar p1_13=0, p2_0=0, oldpmreg=0; 837072b676d7Smrg 837172b676d7Smrg if(!pScrn->vtSema) return; 837272b676d7Smrg 837372b676d7Smrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, 837472b676d7Smrg "SISDisplayPowerManagementSet(%d)\n", PowerManagementMode); 837572b676d7Smrg 837672b676d7Smrg#ifdef SISDUALHEAD 837772b676d7Smrg if(pSiS->DualHeadMode) { 837872b676d7Smrg if(pSiS->SecondHead) docrt2 = FALSE; 837972b676d7Smrg else docrt1 = FALSE; 838072b676d7Smrg } 838172b676d7Smrg#endif 838272b676d7Smrg 8383e35772b2Smrg /* FIXME: in old servers, DPMSSet was supposed to be called without open 8384e35772b2Smrg * the correct PCI bridges before access the hardware. Now we have this 8385e35772b2Smrg * hook wrapped by the vga arbiter which should do all the work, in 8386e35772b2Smrg * kernels that implement it. For this case we might not want this hack 8387e35772b2Smrg * bellow. 838872b676d7Smrg */ 838972b676d7Smrg outSISIDXREG(SISSR,0x05,0x86); 839072b676d7Smrg inSISIDXREG(SISSR,0x05,pmreg); 839172b676d7Smrg if(pmreg != 0xa1) return; 839272b676d7Smrg 839372b676d7Smrg#ifdef UNLOCK_ALWAYS 839472b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 839572b676d7Smrg#endif 839672b676d7Smrg 839772b676d7Smrg switch(PowerManagementMode) { 839872b676d7Smrg 839972b676d7Smrg case DPMSModeOn: /* HSync: On, VSync: On */ 840072b676d7Smrg sr1 = 0x00; 840172b676d7Smrg cr17 = 0x80; 840272b676d7Smrg pmreg = 0x00; 840372b676d7Smrg cr63 = 0x00; 840472b676d7Smrg sr7 = 0x10; 840572b676d7Smrg p2_0 = 0x20; 840672b676d7Smrg p1_13 = 0x00; 840772b676d7Smrg backlight = TRUE; 840872b676d7Smrg break; 840972b676d7Smrg 841072b676d7Smrg case DPMSModeSuspend: /* HSync: On, VSync: Off */ 841172b676d7Smrg sr1 = 0x20; 841272b676d7Smrg cr17 = 0x80; 841372b676d7Smrg pmreg = 0x80; 841472b676d7Smrg cr63 = 0x40; 841572b676d7Smrg sr7 = 0x00; 841672b676d7Smrg p2_0 = 0x40; 841772b676d7Smrg p1_13 = 0x80; 841872b676d7Smrg backlight = FALSE; 841972b676d7Smrg break; 842072b676d7Smrg 842172b676d7Smrg case DPMSModeStandby: /* HSync: Off, VSync: On */ 842272b676d7Smrg sr1 = 0x20; 842372b676d7Smrg cr17 = 0x80; 842472b676d7Smrg pmreg = 0x40; 842572b676d7Smrg cr63 = 0x40; 842672b676d7Smrg sr7 = 0x00; 842772b676d7Smrg p2_0 = 0x80; 842872b676d7Smrg p1_13 = 0x40; 842972b676d7Smrg backlight = FALSE; 843072b676d7Smrg break; 843172b676d7Smrg 843272b676d7Smrg case DPMSModeOff: /* HSync: Off, VSync: Off */ 843372b676d7Smrg sr1 = 0x20; 843472b676d7Smrg cr17 = 0x00; 843572b676d7Smrg pmreg = 0xc0; 843672b676d7Smrg cr63 = 0x40; 843772b676d7Smrg sr7 = 0x00; 843872b676d7Smrg p2_0 = 0xc0; 843972b676d7Smrg p1_13 = 0xc0; 844072b676d7Smrg backlight = FALSE; 844172b676d7Smrg break; 844272b676d7Smrg 844372b676d7Smrg default: 844472b676d7Smrg return; 844572b676d7Smrg } 844672b676d7Smrg 844772b676d7Smrg oldpmreg = pmreg; 844872b676d7Smrg 844972b676d7Smrg if((docrt2 && (pSiS->VBFlags & CRT2_LCD)) || 845072b676d7Smrg (docrt1 && (pSiS->VBFlags & CRT1_LCDA))) { 845172b676d7Smrg SiSHandleBackLight(pSiS, backlight); 845272b676d7Smrg } 845372b676d7Smrg 845472b676d7Smrg if(docrt1) { 845572b676d7Smrg switch(pSiS->VGAEngine) { 845672b676d7Smrg case SIS_OLD_VGA: 845772b676d7Smrg case SIS_530_VGA: 845872b676d7Smrg setSISIDXREG(SISSR, 0x01, ~0x20, sr1); /* Set/Clear "Display On" bit */ 845972b676d7Smrg inSISIDXREG(SISSR, 0x11, oldpmreg); 846072b676d7Smrg setSISIDXREG(SISCR, 0x17, 0x7f, cr17); 846172b676d7Smrg setSISIDXREG(SISSR, 0x11, 0x3f, pmreg); 846272b676d7Smrg break; 846372b676d7Smrg case SIS_315_VGA: 846472b676d7Smrg if( (!pSiS->CRT1off) && 846572b676d7Smrg ((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) ) { 846672b676d7Smrg setSISIDXREG(SISCR, pSiS->myCR63, 0xbf, cr63); 846772b676d7Smrg setSISIDXREG(SISSR, 0x07, 0xef, sr7); 846872b676d7Smrg } 846972b676d7Smrg /* fall through */ 847072b676d7Smrg default: 847172b676d7Smrg if(!SiSBridgeIsInSlaveMode(pScrn)) { 847272b676d7Smrg setSISIDXREG(SISSR, 0x01, ~0x20, sr1); /* Set/Clear "Display On" bit */ 847372b676d7Smrg } 847472b676d7Smrg if((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) { 847572b676d7Smrg inSISIDXREG(SISSR, 0x1f, oldpmreg); 847672b676d7Smrg if((!pSiS->CRT1off) && (!SiSBridgeIsInSlaveMode(pScrn))) { 847772b676d7Smrg setSISIDXREG(SISSR, 0x1f, 0x3f, pmreg); 847872b676d7Smrg } 847972b676d7Smrg } 848072b676d7Smrg } 848172b676d7Smrg oldpmreg &= 0xc0; 848272b676d7Smrg } 848372b676d7Smrg 848472b676d7Smrg if(docrt2) { 848572b676d7Smrg if(pSiS->VBFlags & CRT2_LCD) { 848672b676d7Smrg if((pSiS->VBFlags2 & VB2_SISBRIDGE) && 848772b676d7Smrg (!(pSiS->VBFlags2 & VB2_30xBDH))) { 848872b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 848972b676d7Smrg SiS_UnLockCRT2(pSiS->SiS_Pr); 849072b676d7Smrg setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13); 849172b676d7Smrg } 849272b676d7Smrg if(pSiS->VBFlags2 & VB2_SISLVDSBRIDGE) p2_0 |= 0x20; 849372b676d7Smrg setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); 849472b676d7Smrg } 849572b676d7Smrg } else if(pSiS->VBFlags & (CRT2_VGA | CRT2_TV)) { 849672b676d7Smrg if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 849772b676d7Smrg setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); 849872b676d7Smrg } 849972b676d7Smrg } 850072b676d7Smrg } 850172b676d7Smrg 850272b676d7Smrg if( (docrt1) && 850372b676d7Smrg (pmreg != oldpmreg) && 850472b676d7Smrg ((!(pSiS->VBFlags & CRT1_LCDA)) || (pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE)) ) { 850572b676d7Smrg outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 850672b676d7Smrg usleep(10000); 850772b676d7Smrg outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 850872b676d7Smrg } 850972b676d7Smrg 851072b676d7Smrg} 851172b676d7Smrg 851272b676d7Smrg/* Mandatory 851372b676d7Smrg * This gets called at the start of each server generation 851472b676d7Smrg * 851572b676d7Smrg * We use pScrn and not CurrentLayout here, because the 851672b676d7Smrg * properties we use have not changed (displayWidth, 851772b676d7Smrg * depth, bitsPerPixel) 851872b676d7Smrg */ 851972b676d7Smrgstatic Bool 85205788ca14SmrgSISScreenInit(SCREEN_INIT_ARGS_DECL) 852172b676d7Smrg{ 85225788ca14Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 852372b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 852472b676d7Smrg VisualPtr visual; 852572b676d7Smrg ULong OnScreenSize; 852672b676d7Smrg int ret, height, width, displayWidth; 852772b676d7Smrg UChar *FBStart; 852872b676d7Smrg#ifdef SISDUALHEAD 852972b676d7Smrg SISEntPtr pSiSEnt = NULL; 853072b676d7Smrg#endif 853172b676d7Smrg 853272b676d7Smrg#ifdef SISDUALHEAD 853372b676d7Smrg if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) { 853472b676d7Smrg#endif 853572b676d7Smrg SiS_LoadInitVBE(pScrn); 853672b676d7Smrg#ifdef SISDUALHEAD 853772b676d7Smrg } 853872b676d7Smrg#endif 853972b676d7Smrg 854072b676d7Smrg#ifdef SISDUALHEAD 854172b676d7Smrg if(pSiS->DualHeadMode) { 854272b676d7Smrg pSiSEnt = pSiS->entityPrivate; 854372b676d7Smrg pSiSEnt->refCount++; 854472b676d7Smrg } 854572b676d7Smrg#endif 854672b676d7Smrg 854772b676d7Smrg#ifdef SIS_PC_PLATFORM 854872b676d7Smrg /* Map 64k VGA window for saving/restoring CGA fonts */ 854972b676d7Smrg SiS_MapVGAMem(pScrn); 855072b676d7Smrg#endif 855172b676d7Smrg 855272b676d7Smrg /* Map the SiS memory and MMIO areas */ 855372b676d7Smrg if(!SISMapMem(pScrn)) { 855472b676d7Smrg SISErrorLog(pScrn, "SiSMapMem() failed\n"); 855572b676d7Smrg return FALSE; 855672b676d7Smrg } 855772b676d7Smrg 855872b676d7Smrg SiS_SiSFB_Lock(pScrn, TRUE); 855972b676d7Smrg 856072b676d7Smrg#ifdef UNLOCK_ALWAYS 856172b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 856272b676d7Smrg#endif 856372b676d7Smrg 856472b676d7Smrg /* Enable TurboQueue so that SISSave() saves it in enabled 856572b676d7Smrg * state. If we don't do this, X will hang after a restart! 856672b676d7Smrg * (Happens for some unknown reason only when using VESA 856772b676d7Smrg * for mode switching; assumingly a BIOS issue.) 856872b676d7Smrg * This is done on 300 and 315 series only. 856972b676d7Smrg */ 857072b676d7Smrg if(pSiS->UseVESA) { 857172b676d7Smrg#ifdef SISVRAMQ 857272b676d7Smrg if(pSiS->VGAEngine != SIS_315_VGA) 857372b676d7Smrg#endif 857472b676d7Smrg SiSEnableTurboQueue(pScrn); 857572b676d7Smrg } 857672b676d7Smrg 857772b676d7Smrg /* Save the current state */ 857872b676d7Smrg SISSave(pScrn); 857972b676d7Smrg 858072b676d7Smrg if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 858172b676d7Smrg 858272b676d7Smrg if(!pSiS->OldMode) { 858372b676d7Smrg 858472b676d7Smrg /* Try to find out current (=old) mode number 858572b676d7Smrg * (Do this only if not sisfb has told us its mode yet) 858672b676d7Smrg */ 858772b676d7Smrg 858872b676d7Smrg /* Read 0:449 which the BIOS sets to the current mode number 858972b676d7Smrg * Unfortunately, this not reliable since the int10 emulation 859072b676d7Smrg * does not change this. So if we call the VBE later, this 859172b676d7Smrg * byte won't be touched (which is why we set this manually 859272b676d7Smrg * then). 859372b676d7Smrg */ 859472b676d7Smrg UChar myoldmode = SiS_GetSetModeID(pScrn, 0xFF); 859572b676d7Smrg UChar cr30, cr31; 859672b676d7Smrg 859772b676d7Smrg /* Read CR34 which the BIOS sets to the current mode number for CRT2 859872b676d7Smrg * This is - of course - not reliable if the machine has no video 859972b676d7Smrg * bridge... 860072b676d7Smrg */ 860172b676d7Smrg inSISIDXREG(SISCR, 0x34, pSiS->OldMode); 860272b676d7Smrg inSISIDXREG(SISCR, 0x30, cr30); 860372b676d7Smrg inSISIDXREG(SISCR, 0x31, cr31); 860472b676d7Smrg 860572b676d7Smrg /* What if CR34 is different from the BIOS scratch byte? */ 860672b676d7Smrg if(pSiS->OldMode != myoldmode) { 860772b676d7Smrg /* If no bridge output is active, trust the BIOS scratch byte */ 860872b676d7Smrg if( (!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) || 860972b676d7Smrg (pSiS->OldMode == 0) || 861072b676d7Smrg (!cr31 && !cr30) || 861172b676d7Smrg (cr31 & 0x20) ) { 861272b676d7Smrg pSiS->OldMode = myoldmode; 861372b676d7Smrg } 861472b676d7Smrg /* ..else trust CR34 */ 861572b676d7Smrg } 861672b676d7Smrg 861772b676d7Smrg /* Newer 650 BIOSes set CR34 to 0xff if the mode has been 861872b676d7Smrg * "patched", for instance for 80x50 text mode. (That mode 861972b676d7Smrg * has no number of its own, it's 0x03 like 80x25). In this 862072b676d7Smrg * case, we trust the BIOS scratch byte (provided that any 862172b676d7Smrg * of these two is valid). 862272b676d7Smrg */ 862372b676d7Smrg if(pSiS->OldMode > 0x7f) { 862472b676d7Smrg pSiS->OldMode = myoldmode; 862572b676d7Smrg } 862672b676d7Smrg } 862772b676d7Smrg#ifdef SISDUALHEAD 862872b676d7Smrg if(pSiS->DualHeadMode) { 862972b676d7Smrg if(!pSiS->SecondHead) pSiSEnt->OldMode = pSiS->OldMode; 863072b676d7Smrg else pSiS->OldMode = pSiSEnt->OldMode; 863172b676d7Smrg } 863272b676d7Smrg#endif 863372b676d7Smrg } 863472b676d7Smrg 863572b676d7Smrg /* RandR resets screen mode and size in CloseScreen(), hence 863672b676d7Smrg * we need to adapt our VBFlags to the initial state if the 863772b676d7Smrg * current mode has changed since closescreen() (or Screeninit() 863872b676d7Smrg * for the first instance) 863972b676d7Smrg */ 864072b676d7Smrg if(pScrn->currentMode != pSiS->currentModeLast) { 864172b676d7Smrg pSiS->VBFlags = pSiS->VBFlags_backup = pSiS->VBFlagsInit; 864272b676d7Smrg } 864372b676d7Smrg 864472b676d7Smrg /* Copy our detected monitor gammas, part 2. Note that device redetection 864572b676d7Smrg * is not supported in DHM, so there is no need to do that anytime later. 864672b676d7Smrg */ 864772b676d7Smrg#ifdef SISDUALHEAD 864872b676d7Smrg if(pSiS->DualHeadMode) { 864972b676d7Smrg if(!pSiS->SecondHead) { 865072b676d7Smrg /* CRT2 */ 865172b676d7Smrg pSiS->CRT1VGAMonitorGamma = pSiSEnt->CRT1VGAMonitorGamma; 865272b676d7Smrg } else { 865372b676d7Smrg /* CRT1 */ 865472b676d7Smrg pSiS->CRT2VGAMonitorGamma = pSiSEnt->CRT2VGAMonitorGamma; 865572b676d7Smrg } 865672b676d7Smrg if(!pSiS->CRT2LCDMonitorGamma) pSiS->CRT2LCDMonitorGamma = pSiSEnt->CRT2LCDMonitorGamma; 865772b676d7Smrg } 865872b676d7Smrg#endif 865972b676d7Smrg 866072b676d7Smrg /* Initialize the first mode */ 866172b676d7Smrg if(!SISModeInit(pScrn, pScrn->currentMode)) { 866272b676d7Smrg SISErrorLog(pScrn, "SiSModeInit() failed\n"); 866372b676d7Smrg return FALSE; 866472b676d7Smrg } 866572b676d7Smrg 866672b676d7Smrg /* Darken the screen for aesthetic reasons */ 866772b676d7Smrg /* Not using Dual Head variant on purpose; we darken 866872b676d7Smrg * the screen for both displays, and un-darken 866972b676d7Smrg * it when the second head is finished 867072b676d7Smrg */ 867172b676d7Smrg SISSaveScreen(pScreen, SCREEN_SAVER_ON); 867272b676d7Smrg 867372b676d7Smrg /* Set the viewport */ 86745788ca14Smrg SISAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 867572b676d7Smrg 867672b676d7Smrg /* Reset visual list. */ 867772b676d7Smrg miClearVisualTypes(); 867872b676d7Smrg 867972b676d7Smrg /* Setup the visuals we support. */ 868072b676d7Smrg 868172b676d7Smrg /* 868272b676d7Smrg * For bpp > 8, the default visuals are not acceptable because we only 868372b676d7Smrg * support TrueColor and not DirectColor. 868472b676d7Smrg */ 868572b676d7Smrg if(!miSetVisualTypes(pScrn->depth, 868672b676d7Smrg (pScrn->bitsPerPixel > 8) ? 868772b676d7Smrg TrueColorMask : miGetDefaultVisualMask(pScrn->depth), 868872b676d7Smrg pScrn->rgbBits, pScrn->defaultVisual)) { 868972b676d7Smrg SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 869072b676d7Smrg SISErrorLog(pScrn, "miSetVisualTypes() failed (bpp %d)\n", 869172b676d7Smrg pScrn->bitsPerPixel); 869272b676d7Smrg return FALSE; 869372b676d7Smrg } 869472b676d7Smrg 869572b676d7Smrg width = pScrn->virtualX; 869672b676d7Smrg height = pScrn->virtualY; 869772b676d7Smrg displayWidth = pScrn->displayWidth; 869872b676d7Smrg 869972b676d7Smrg if(pSiS->Rotate) { 870072b676d7Smrg height = pScrn->virtualX; 870172b676d7Smrg width = pScrn->virtualY; 870272b676d7Smrg } 870372b676d7Smrg 870472b676d7Smrg if(pSiS->ShadowFB) { 870572b676d7Smrg pSiS->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); 87065788ca14Smrg pSiS->ShadowPtr = malloc(pSiS->ShadowPitch * height); 870772b676d7Smrg displayWidth = pSiS->ShadowPitch / (pScrn->bitsPerPixel >> 3); 870872b676d7Smrg FBStart = pSiS->ShadowPtr; 870972b676d7Smrg } else { 871072b676d7Smrg pSiS->ShadowPtr = NULL; 871172b676d7Smrg FBStart = pSiS->FbBase; 871272b676d7Smrg } 871372b676d7Smrg 871472b676d7Smrg if(!miSetPixmapDepths()) { 871572b676d7Smrg SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 871672b676d7Smrg SISErrorLog(pScrn, "miSetPixmapDepths() failed\n"); 871772b676d7Smrg return FALSE; 871872b676d7Smrg } 871972b676d7Smrg 872072b676d7Smrg /* Point cmdQueuePtr to pSiSEnt for shared usage 872172b676d7Smrg * (same technique is then eventually used in DRIScreeninit) 872272b676d7Smrg * For 315/330 series, this is done in EnableTurboQueue 872372b676d7Smrg * which has already been called during ModeInit(). 872472b676d7Smrg */ 872572b676d7Smrg#ifdef SISDUALHEAD 872672b676d7Smrg if(pSiS->SecondHead) 872772b676d7Smrg pSiS->cmdQueueLenPtr = &(SISPTR(pSiSEnt->pScrn_1)->cmdQueueLen); 872872b676d7Smrg else 872972b676d7Smrg#endif 873072b676d7Smrg pSiS->cmdQueueLenPtr = &(pSiS->cmdQueueLen); 873172b676d7Smrg 873272b676d7Smrg pSiS->cmdQueueLen = 0; /* Force an EngineIdle() at start */ 873372b676d7Smrg 87345788ca14Smrg#ifdef SISDRI 873572b676d7Smrg if(pSiS->loadDRI) { 873672b676d7Smrg#ifdef SISDUALHEAD 873772b676d7Smrg /* No DRI in dual head mode */ 873872b676d7Smrg if(pSiS->DualHeadMode) { 873972b676d7Smrg pSiS->directRenderingEnabled = FALSE; 874072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 874172b676d7Smrg "DRI not supported in Dual Head mode\n"); 874272b676d7Smrg } else 874372b676d7Smrg#endif 874472b676d7Smrg if(pSiS->VGAEngine != SIS_315_VGA) { 874572b676d7Smrg /* Force the initialization of the context */ 874672b676d7Smrg pSiS->directRenderingEnabled = SISDRIScreenInit(pScreen); 874772b676d7Smrg } else { 874872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_NOT_IMPLEMENTED, 874972b676d7Smrg "DRI not supported on this chipset\n"); 875072b676d7Smrg pSiS->directRenderingEnabled = FALSE; 875172b676d7Smrg } 875272b676d7Smrg } 875372b676d7Smrg#endif 875472b676d7Smrg 875572b676d7Smrg /* Call the framebuffer layer's ScreenInit function and fill in other 875672b676d7Smrg * pScreen fields. 875772b676d7Smrg */ 875872b676d7Smrg switch(pScrn->bitsPerPixel) { 875972b676d7Smrg case 24: 876072b676d7Smrg if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 876172b676d7Smrg ret = FALSE; 876272b676d7Smrg break; 876372b676d7Smrg } 876472b676d7Smrg /* fall through */ 876572b676d7Smrg case 8: 876672b676d7Smrg case 16: 876772b676d7Smrg case 32: 876872b676d7Smrg ret = fbScreenInit(pScreen, FBStart, width, 876972b676d7Smrg height, pScrn->xDpi, pScrn->yDpi, 877072b676d7Smrg displayWidth, pScrn->bitsPerPixel); 877172b676d7Smrg break; 877272b676d7Smrg default: 877372b676d7Smrg ret = FALSE; 877472b676d7Smrg break; 877572b676d7Smrg } 877672b676d7Smrg if(!ret) { 877772b676d7Smrg SISErrorLog(pScrn, "Unsupported bpp (%d) or fbScreenInit() failed\n", 877872b676d7Smrg pScrn->bitsPerPixel); 877972b676d7Smrg SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 878072b676d7Smrg return FALSE; 878172b676d7Smrg } 878272b676d7Smrg 878372b676d7Smrg /* Fixup RGB ordering */ 878472b676d7Smrg if(pScrn->bitsPerPixel > 8) { 878572b676d7Smrg visual = pScreen->visuals + pScreen->numVisuals; 878672b676d7Smrg while (--visual >= pScreen->visuals) { 878772b676d7Smrg if((visual->class | DynamicClass) == DirectColor) { 878872b676d7Smrg visual->offsetRed = pScrn->offset.red; 878972b676d7Smrg visual->offsetGreen = pScrn->offset.green; 879072b676d7Smrg visual->offsetBlue = pScrn->offset.blue; 879172b676d7Smrg visual->redMask = pScrn->mask.red; 879272b676d7Smrg visual->greenMask = pScrn->mask.green; 879372b676d7Smrg visual->blueMask = pScrn->mask.blue; 879472b676d7Smrg } 879572b676d7Smrg } 879672b676d7Smrg } 879772b676d7Smrg 879872b676d7Smrg /* Initialize RENDER extension (must be after RGB ordering fixed) */ 879972b676d7Smrg fbPictureInit(pScreen, 0, 0); 880072b676d7Smrg 880172b676d7Smrg /* Hardware cursor needs to wrap this layer */ 880272b676d7Smrg if(!pSiS->ShadowFB) SISDGAInit(pScreen); 880372b676d7Smrg 880472b676d7Smrg xf86SetBlackWhitePixels(pScreen); 880572b676d7Smrg 880672b676d7Smrg /* Initialize the accelerators */ 880772b676d7Smrg switch(pSiS->VGAEngine) { 880872b676d7Smrg case SIS_530_VGA: 880972b676d7Smrg case SIS_300_VGA: 881072b676d7Smrg SiS300AccelInit(pScreen); 881172b676d7Smrg break; 881272b676d7Smrg case SIS_315_VGA: 881372b676d7Smrg SiS315AccelInit(pScreen); 881472b676d7Smrg break; 881572b676d7Smrg default: 881672b676d7Smrg SiSAccelInit(pScreen); 881772b676d7Smrg } 881872b676d7Smrg 881972b676d7Smrg#ifdef TWDEBUG 882072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CPUFlags %x\n", pSiS->CPUFlags); 882172b676d7Smrg#endif 882272b676d7Smrg 882372b676d7Smrg /* Benchmark memcpy() methods (needs FB manager initialized) */ 882472b676d7Smrg /* Dual head: Do this AFTER the mode for CRT1 has been set */ 882572b676d7Smrg pSiS->NeedCopyFastVidCpy = FALSE; 882672b676d7Smrg if(!pSiS->SiSFastVidCopyDone) { 882772b676d7Smrg#ifdef SISDUALHEAD 882872b676d7Smrg if(pSiS->DualHeadMode) { 882972b676d7Smrg if(pSiS->SecondHead) { 883072b676d7Smrg pSiSEnt->SiSFastVidCopy = SiSVidCopyInit(pScreen, &pSiSEnt->SiSFastMemCopy, FALSE); 883172b676d7Smrg pSiSEnt->SiSFastVidCopyFrom = SiSVidCopyGetDefault(); 883272b676d7Smrg pSiSEnt->SiSFastMemCopyFrom = SiSVidCopyGetDefault(); 883372b676d7Smrg#ifdef SIS_USE_EXA 883472b676d7Smrg if(pSiS->useEXA) { 883572b676d7Smrg pSiSEnt->SiSFastVidCopyFrom = SiSVidCopyInit(pScreen, &pSiSEnt->SiSFastMemCopyFrom, TRUE); 883672b676d7Smrg } 883772b676d7Smrg#endif /* EXA */ 883872b676d7Smrg pSiSEnt->HaveFastVidCpy = TRUE; 883972b676d7Smrg pSiS->SiSFastVidCopy = pSiSEnt->SiSFastVidCopy; 884072b676d7Smrg pSiS->SiSFastMemCopy = pSiSEnt->SiSFastMemCopy; 884172b676d7Smrg pSiS->SiSFastVidCopyFrom = pSiSEnt->SiSFastVidCopyFrom; 884272b676d7Smrg pSiS->SiSFastMemCopyFrom = pSiSEnt->SiSFastMemCopyFrom; 884372b676d7Smrg } else { 884472b676d7Smrg pSiS->NeedCopyFastVidCpy = TRUE; 884572b676d7Smrg } 884672b676d7Smrg } else { 884772b676d7Smrg#endif 884872b676d7Smrg pSiS->SiSFastVidCopy = SiSVidCopyInit(pScreen, &pSiS->SiSFastMemCopy, FALSE); 884972b676d7Smrg pSiS->SiSFastVidCopyFrom = SiSVidCopyGetDefault(); 885072b676d7Smrg pSiS->SiSFastMemCopyFrom = SiSVidCopyGetDefault(); 885172b676d7Smrg#ifdef SIS_USE_EXA 885272b676d7Smrg if(pSiS->useEXA) { 885372b676d7Smrg pSiS->SiSFastVidCopyFrom = SiSVidCopyInit(pScreen, &pSiS->SiSFastMemCopyFrom, TRUE); 885472b676d7Smrg } 885572b676d7Smrg#endif /* EXA */ 885672b676d7Smrg#ifdef SISDUALHEAD 885772b676d7Smrg } 885872b676d7Smrg#endif 885972b676d7Smrg } 886072b676d7Smrg pSiS->SiSFastVidCopyDone = TRUE; 886172b676d7Smrg 886272b676d7Smrg miInitializeBackingStore(pScreen); 886372b676d7Smrg xf86SetBackingStore(pScreen); 886472b676d7Smrg xf86SetSilkenMouse(pScreen); 886572b676d7Smrg 886672b676d7Smrg /* Initialise cursor functions */ 886772b676d7Smrg miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 886872b676d7Smrg 886972b676d7Smrg if(pSiS->HWCursor) { 887072b676d7Smrg SiSHWCursorInit(pScreen); 887172b676d7Smrg } 887272b676d7Smrg 887372b676d7Smrg#ifdef SISDUALHEAD 887472b676d7Smrg if(!pSiS->DualHeadMode) { 887572b676d7Smrg#endif 887672b676d7Smrg if((pSiS->VBFlags2 & VB2_SISBRIDGE) && (pScrn->depth > 8)) { 887772b676d7Smrg 887872b676d7Smrg pSiS->CRT2ColNum = 1 << pScrn->rgbBits; 887972b676d7Smrg 88805788ca14Smrg if((pSiS->crt2gcolortable = malloc(pSiS->CRT2ColNum * 2 * sizeof(LOCO)))) { 888172b676d7Smrg pSiS->crt2colors = &pSiS->crt2gcolortable[pSiS->CRT2ColNum]; 88825788ca14Smrg if((pSiS->crt2cindices = malloc(256 * sizeof(int)))) { 888372b676d7Smrg int i = pSiS->CRT2ColNum; 888472b676d7Smrg SISCalculateGammaRampCRT2(pScrn); 888572b676d7Smrg while(i--) pSiS->crt2cindices[i] = i; 888672b676d7Smrg } else { 88875788ca14Smrg free(pSiS->crt2gcolortable); 888872b676d7Smrg pSiS->crt2gcolortable = NULL; 888972b676d7Smrg pSiS->CRT2SepGamma = FALSE; 889072b676d7Smrg } 889172b676d7Smrg } else { 889272b676d7Smrg pSiS->CRT2SepGamma = FALSE; 889372b676d7Smrg } 889472b676d7Smrg 889572b676d7Smrg if(!pSiS->crt2cindices) { 889672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 889772b676d7Smrg "Failed to allocate cmap for CRT2, separate gamma correction disabled\n"); 889872b676d7Smrg } 889972b676d7Smrg 890072b676d7Smrg } 890172b676d7Smrg#ifdef SISDUALHEAD 890272b676d7Smrg } else pSiS->CRT2SepGamma = FALSE; 890372b676d7Smrg#endif 890472b676d7Smrg 890572b676d7Smrg /* Initialise default colormap */ 890672b676d7Smrg if(!miCreateDefColormap(pScreen)) { 890772b676d7Smrg SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 890872b676d7Smrg SISErrorLog(pScrn, "miCreateDefColormap() failed\n"); 890972b676d7Smrg return FALSE; 891072b676d7Smrg } 891172b676d7Smrg 891272b676d7Smrg if(!xf86HandleColormaps(pScreen, 256, (pScrn->depth == 8) ? 8 : pScrn->rgbBits, 891372b676d7Smrg SISLoadPalette, NULL, 891472b676d7Smrg CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH)) { 891572b676d7Smrg SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 891672b676d7Smrg SISErrorLog(pScrn, "xf86HandleColormaps() failed\n"); 891772b676d7Smrg return FALSE; 891872b676d7Smrg } 891972b676d7Smrg 892072b676d7Smrg /* Recalculate our gamma ramp for brightness feature */ 892172b676d7Smrg#ifdef SISGAMMARAMP 892272b676d7Smrg if((pSiS->GammaBriR != 1000) || 892372b676d7Smrg (pSiS->GammaBriB != 1000) || 892472b676d7Smrg (pSiS->GammaBriG != 1000) || 892572b676d7Smrg (pSiS->NewGammaBriR != 0.0) || 892672b676d7Smrg (pSiS->NewGammaBriG != 0.0) || 892772b676d7Smrg (pSiS->NewGammaBriB != 0.0) || 892872b676d7Smrg (pSiS->NewGammaConR != 0.0) || 892972b676d7Smrg (pSiS->NewGammaConG != 0.0) || 893072b676d7Smrg (pSiS->NewGammaConB != 0.0)) { 893172b676d7Smrg SISCalculateGammaRamp(pScreen, pScrn); 893272b676d7Smrg } 893372b676d7Smrg#endif 893472b676d7Smrg 893572b676d7Smrg /* Initialize Shadow framebuffer and screen rotation/reflection */ 893672b676d7Smrg if(pSiS->ShadowFB) { 893772b676d7Smrg RefreshAreaFuncPtr refreshArea = SISRefreshArea; 893872b676d7Smrg 893972b676d7Smrg if(pSiS->Rotate) { 894072b676d7Smrg if(!pSiS->PointerMoved) pSiS->PointerMoved = pScrn->PointerMoved; 894172b676d7Smrg pScrn->PointerMoved = SISPointerMoved; 894272b676d7Smrg switch(pScrn->bitsPerPixel) { 894372b676d7Smrg case 8: refreshArea = SISRefreshArea8; break; 894472b676d7Smrg case 16: refreshArea = SISRefreshArea16; break; 894572b676d7Smrg case 24: refreshArea = SISRefreshArea24; break; 894672b676d7Smrg case 32: refreshArea = SISRefreshArea32; break; 894772b676d7Smrg } 894872b676d7Smrg#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 894972b676d7Smrg xf86DisableRandR(); 895072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 895172b676d7Smrg "Driver rotation enabled, disabling RandR\n"); 895272b676d7Smrg#endif 895372b676d7Smrg } else if(pSiS->Reflect) { 895472b676d7Smrg switch(pScrn->bitsPerPixel) { 895572b676d7Smrg case 8: 895672b676d7Smrg case 16: 895772b676d7Smrg case 32: 895872b676d7Smrg if(!pSiS->PointerMoved) pSiS->PointerMoved = pScrn->PointerMoved; 895972b676d7Smrg pScrn->PointerMoved = SISPointerMovedReflect; 896072b676d7Smrg refreshArea = SISRefreshAreaReflect; 896172b676d7Smrg#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 896272b676d7Smrg xf86DisableRandR(); 896372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 896472b676d7Smrg "Driver reflection enabled, disabling RandR\n"); 896572b676d7Smrg#endif 896672b676d7Smrg break; 896772b676d7Smrg default: 896872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 896972b676d7Smrg "Reflection not supported at this framebuffer depth\n"); 897072b676d7Smrg } 897172b676d7Smrg } 897272b676d7Smrg 897372b676d7Smrg ShadowFBInit(pScreen, refreshArea); 897472b676d7Smrg } 897572b676d7Smrg 897672b676d7Smrg xf86DPMSInit(pScreen, (DPMSSetProcPtr)SISDisplayPowerManagementSet, 0); 897772b676d7Smrg 897872b676d7Smrg /* Init memPhysBase and fbOffset in pScrn */ 897972b676d7Smrg pScrn->memPhysBase = pSiS->FbAddress; 898072b676d7Smrg pScrn->fbOffset = 0; 898172b676d7Smrg 898272b676d7Smrg /* Initialize Xv */ 898372b676d7Smrg pSiS->ResetXv = pSiS->ResetXvGamma = pSiS->ResetXvDisplay = NULL; 898472b676d7Smrg#if (XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,99,0,0)) || (defined(XvExtension)) 898572b676d7Smrg if((!pSiS->NoXvideo) && (!(pSiS->SiS_SD2_Flags & SiS_SD2_NOOVERLAY))) { 898672b676d7Smrg 898772b676d7Smrg if((pSiS->VGAEngine == SIS_300_VGA) || 898872b676d7Smrg (pSiS->VGAEngine == SIS_315_VGA)) { 898972b676d7Smrg 899072b676d7Smrg const char *using = "Using SiS300/315/330/340 series HW Xv"; 899172b676d7Smrg 899272b676d7Smrg#ifdef SISDUALHEAD 899372b676d7Smrg if(pSiS->DualHeadMode) { 899472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 899572b676d7Smrg "%s on CRT%d\n", using, (pSiS->SecondHead ? 1 : 2)); 899672b676d7Smrg if(!pSiS->hasTwoOverlays) { 899772b676d7Smrg if( (pSiS->XvOnCRT2 && pSiS->SecondHead) || 899872b676d7Smrg (!pSiS->XvOnCRT2 && !pSiS->SecondHead) ) { 899972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 900072b676d7Smrg "However, video overlay will by default only be visible on CRT%d\n", 900172b676d7Smrg pSiS->XvOnCRT2 ? 2 : 1); 900272b676d7Smrg } 900372b676d7Smrg } 900472b676d7Smrg } else { 900572b676d7Smrg#endif 900672b676d7Smrg if(pSiS->hasTwoOverlays) { 900772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s\n", using); 900872b676d7Smrg } else { 900972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s by default on CRT%d\n", 901072b676d7Smrg using, (pSiS->XvOnCRT2 ? 2 : 1)); 901172b676d7Smrg } 901272b676d7Smrg#ifdef SISDUALHEAD 901372b676d7Smrg } 901472b676d7Smrg#endif 901572b676d7Smrg 901672b676d7Smrg SISInitVideo(pScreen); 901772b676d7Smrg 901872b676d7Smrg if(pSiS->blitadaptor) { 901972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 902072b676d7Smrg "Default Xv adaptor is Video %s\n", 902172b676d7Smrg pSiS->XvDefAdaptorBlit ? "Blitter" : "Overlay"); 902272b676d7Smrg } 902372b676d7Smrg 902472b676d7Smrg } else if(pSiS->Chipset == PCI_CHIP_SIS530 || 902572b676d7Smrg pSiS->Chipset == PCI_CHIP_SIS6326 || 902672b676d7Smrg pSiS->Chipset == PCI_CHIP_SIS5597) { 902772b676d7Smrg 902872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 902972b676d7Smrg "Using SiS5597/5598/6326/530/620 HW Xv\n" ); 903072b676d7Smrg 903172b676d7Smrg SIS6326InitVideo(pScreen); 903272b676d7Smrg 903372b676d7Smrg } else { /* generic Xv */ 903472b676d7Smrg 903572b676d7Smrg XF86VideoAdaptorPtr *ptr; 903672b676d7Smrg int n = xf86XVListGenericAdaptors(pScrn, &ptr); 903772b676d7Smrg 903872b676d7Smrg if(n) { 903972b676d7Smrg xf86XVScreenInit(pScreen, ptr, n); 904072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using generic Xv\n" ); 904172b676d7Smrg } 904272b676d7Smrg 904372b676d7Smrg } 904472b676d7Smrg } 904572b676d7Smrg#endif 904672b676d7Smrg 90475788ca14Smrg#ifdef SISDRI 904872b676d7Smrg if(pSiS->loadDRI) { 904972b676d7Smrg if(pSiS->directRenderingEnabled) { 905072b676d7Smrg /* Now that mi, drm and others have done their thing, 905172b676d7Smrg * complete the DRI setup. 905272b676d7Smrg */ 905372b676d7Smrg pSiS->directRenderingEnabled = SISDRIFinishScreenInit(pScreen); 905472b676d7Smrg } 905572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering %s\n", 905672b676d7Smrg pSiS->directRenderingEnabled ? "enabled" : "disabled"); 905772b676d7Smrg /* TODO */ 905872b676d7Smrg /* if(pSiS->directRenderingEnabled) SISSetLFBConfig(pSiS); */ 905972b676d7Smrg } 906072b676d7Smrg#endif 906172b676d7Smrg 906272b676d7Smrg /* Wrap some funcs, initialize pseudo-Xinerama and setup remaining SD flags */ 906372b676d7Smrg 906472b676d7Smrg pSiS->SiS_SD_Flags &= ~(SiS_SD_PSEUDOXINERAMA); 906572b676d7Smrg#ifdef SISMERGED 906672b676d7Smrg if(pSiS->MergedFB) { 906772b676d7Smrg pSiS->PointerMoved = pScrn->PointerMoved; 906872b676d7Smrg pScrn->PointerMoved = SISMergedPointerMoved; 906972b676d7Smrg pSiS->Rotate = 0; 907072b676d7Smrg pSiS->Reflect = 0; 907172b676d7Smrg pSiS->ShadowFB = FALSE; 907272b676d7Smrg#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 907372b676d7Smrg if(pSiS->CRT1XOffs || pSiS->CRT1YOffs || pSiS->CRT2XOffs || pSiS->CRT2YOffs) { 907472b676d7Smrg xf86DisableRandR(); 907572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 907672b676d7Smrg "MergedFB: CRT2Position offset used, disabling RandR\n"); 907772b676d7Smrg } 907872b676d7Smrg#endif 907972b676d7Smrg#ifdef SISXINERAMA 908072b676d7Smrg if(pSiS->UseSiSXinerama) { 908172b676d7Smrg SiSnoPanoramiXExtension = FALSE; 908272b676d7Smrg SiSXineramaExtensionInit(pScrn); 908372b676d7Smrg if(!SiSnoPanoramiXExtension) { 908472b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_PSEUDOXINERAMA; 908572b676d7Smrg if(pSiS->HaveNonRect) { 908672b676d7Smrg /* Reset the viewport (now eventually non-recangular) */ 90875788ca14Smrg SISAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 908872b676d7Smrg } 908972b676d7Smrg } 909072b676d7Smrg } else { 909172b676d7Smrg pSiS->MouseRestrictions = FALSE; 909272b676d7Smrg } 909372b676d7Smrg#endif 909472b676d7Smrg } 909572b676d7Smrg#endif 909672b676d7Smrg 909772b676d7Smrg /* Wrap CloseScreen and set up SaveScreen */ 909872b676d7Smrg pSiS->CloseScreen = pScreen->CloseScreen; 909972b676d7Smrg pScreen->CloseScreen = SISCloseScreen; 910072b676d7Smrg#ifdef SISDUALHEAD 910172b676d7Smrg if(pSiS->DualHeadMode) 910272b676d7Smrg pScreen->SaveScreen = SISSaveScreenDH; 910372b676d7Smrg else 910472b676d7Smrg#endif 910572b676d7Smrg pScreen->SaveScreen = SISSaveScreen; 910672b676d7Smrg 910772b676d7Smrg /* Install BlockHandler */ 910872b676d7Smrg pSiS->BlockHandler = pScreen->BlockHandler; 910972b676d7Smrg pScreen->BlockHandler = SISBlockHandler; 911072b676d7Smrg 911172b676d7Smrg /* Report any unused options (only for the first generation) */ 911272b676d7Smrg if(serverGeneration == 1) { 911372b676d7Smrg xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 911472b676d7Smrg } 911572b676d7Smrg 911672b676d7Smrg /* Clear frame buffer */ 911772b676d7Smrg /* For CRT2, we don't do that at this point in dual head 911872b676d7Smrg * mode since the mode isn't switched at this time (it will 911972b676d7Smrg * be reset when setting the CRT1 mode). Hence, we just 912072b676d7Smrg * save the necessary data and clear the screen when 912172b676d7Smrg * going through this for CRT1. 912272b676d7Smrg */ 912372b676d7Smrg 912472b676d7Smrg OnScreenSize = pScrn->displayWidth * pScrn->currentMode->VDisplay 912572b676d7Smrg * (pScrn->bitsPerPixel >> 3); 912672b676d7Smrg 912772b676d7Smrg /* Turn on the screen now */ 912872b676d7Smrg /* We do this in dual head mode after second head is finished */ 912972b676d7Smrg#ifdef SISDUALHEAD 913072b676d7Smrg if(pSiS->DualHeadMode) { 913172b676d7Smrg if(pSiS->SecondHead) { 913272b676d7Smrg sisclearvram(pSiS->FbBase, OnScreenSize); 913372b676d7Smrg sisclearvram(pSiSEnt->FbBase1, pSiSEnt->OnScreenSize1); 913472b676d7Smrg SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 913572b676d7Smrg } else { 913672b676d7Smrg pSiSEnt->FbBase1 = pSiS->FbBase; 913772b676d7Smrg pSiSEnt->OnScreenSize1 = OnScreenSize; 913872b676d7Smrg } 913972b676d7Smrg } else { 914072b676d7Smrg#endif 914172b676d7Smrg SISSaveScreen(pScreen, SCREEN_SAVER_OFF); 914272b676d7Smrg sisclearvram(pSiS->FbBase, OnScreenSize); 914372b676d7Smrg#ifdef SISDUALHEAD 914472b676d7Smrg } 914572b676d7Smrg#endif 914672b676d7Smrg 914772b676d7Smrg pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTSGRCRT2; 914872b676d7Smrg#ifdef SISDUALHEAD 914972b676d7Smrg if(!pSiS->DualHeadMode) { 915072b676d7Smrg#endif 915172b676d7Smrg if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 915272b676d7Smrg if((pSiS->crt2cindices) && (pSiS->crt2gcolortable)) { 915372b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTSGRCRT2; 915472b676d7Smrg } 915572b676d7Smrg } 915672b676d7Smrg#ifdef SISDUALHEAD 915772b676d7Smrg } 915872b676d7Smrg#endif 915972b676d7Smrg 916072b676d7Smrg pSiS->SiS_SD_Flags &= ~SiS_SD_ISDEPTH8; 916172b676d7Smrg if(pSiS->CurrentLayout.bitsPerPixel == 8) { 916272b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_ISDEPTH8; 916372b676d7Smrg pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTXVGAMMA1; 916472b676d7Smrg pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTSGRCRT2; 916572b676d7Smrg } 916672b676d7Smrg 916772b676d7Smrg#ifdef SISGAMMARAMP 916872b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_CANSETGAMMA; 916972b676d7Smrg#else 917072b676d7Smrg pSiS->SiS_SD_Flags &= ~SiS_SD_CANSETGAMMA; 917172b676d7Smrg#endif 917272b676d7Smrg 917372b676d7Smrg SiSCtrlExtInit(pScrn); 917472b676d7Smrg 917572b676d7Smrg return TRUE; 917672b676d7Smrg} 917772b676d7Smrg 917872b676d7Smrg/* Usually mandatory */ 917972b676d7SmrgBool 91805788ca14SmrgSISSwitchMode(SWITCH_MODE_ARGS_DECL) 918172b676d7Smrg{ 91825788ca14Smrg SCRN_INFO_PTR(arg); 918372b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 918472b676d7Smrg 918572b676d7Smrg if(!pSiS->skipswitchcheck) { 91865788ca14Smrg if(SISValidMode(arg, mode, TRUE, 0) != MODE_OK) { 918772b676d7Smrg return FALSE; 918872b676d7Smrg } 918972b676d7Smrg } 919072b676d7Smrg 919172b676d7Smrg (*pSiS->SyncAccel)(pScrn); 919272b676d7Smrg 91935788ca14Smrg if(!(SISModeInit(pScrn, mode))) return FALSE; 919472b676d7Smrg 919572b676d7Smrg /* Since RandR (indirectly) uses SwitchMode(), we need to 919672b676d7Smrg * update our Xinerama info here, too, in case of resizing 919772b676d7Smrg */ 919872b676d7Smrg#ifdef SISMERGED 919972b676d7Smrg#ifdef SISXINERAMA 920072b676d7Smrg if(pSiS->MergedFB) { 920172b676d7Smrg SiSUpdateXineramaScreenInfo(pScrn); 920272b676d7Smrg } 920372b676d7Smrg#endif 920472b676d7Smrg#endif 920572b676d7Smrg return TRUE; 920672b676d7Smrg} 920772b676d7Smrg 920872b676d7Smrgstatic void 920972b676d7SmrgSISSetStartAddressCRT1(SISPtr pSiS, ULong base) 921072b676d7Smrg{ 921172b676d7Smrg UChar cr11backup; 921272b676d7Smrg 921372b676d7Smrg inSISIDXREG(SISCR, 0x11, cr11backup); /* Unlock CRTC registers */ 921472b676d7Smrg andSISIDXREG(SISCR, 0x11, 0x7F); 921572b676d7Smrg outSISIDXREG(SISCR, 0x0D, base & 0xFF); 921672b676d7Smrg outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); 921772b676d7Smrg outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF); 921872b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 921972b676d7Smrg setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01); 922072b676d7Smrg } 922172b676d7Smrg /* Eventually lock CRTC registers */ 922272b676d7Smrg setSISIDXREG(SISCR, 0x11, 0x7F,(cr11backup & 0x80)); 922372b676d7Smrg} 922472b676d7Smrg 922572b676d7Smrgstatic void 922672b676d7SmrgSISSetStartAddressCRT2(SISPtr pSiS, ULong base) 922772b676d7Smrg{ 922872b676d7Smrg SiS_UnLockCRT2(pSiS->SiS_Pr); 922972b676d7Smrg outSISIDXREG(SISPART1, 0x06, GETVAR8(base)); 923072b676d7Smrg outSISIDXREG(SISPART1, 0x05, GETBITS(base, 15:8)); 923172b676d7Smrg outSISIDXREG(SISPART1, 0x04, GETBITS(base, 23:16)); 923272b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 923372b676d7Smrg setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7); 923472b676d7Smrg } 923572b676d7Smrg SiS_LockCRT2(pSiS->SiS_Pr); 923672b676d7Smrg} 923772b676d7Smrg 923872b676d7Smrg#ifdef SISMERGED 923972b676d7Smrgstatic Bool 924072b676d7SmrgInRegion(int x, int y, region r) 924172b676d7Smrg{ 924272b676d7Smrg return (r.x0 <= x) && (x <= r.x1) && (r.y0 <= y) && (y <= r.y1); 924372b676d7Smrg} 924472b676d7Smrg 924572b676d7Smrgstatic void 924672b676d7SmrgSISAdjustFrameHW_CRT1(ScrnInfoPtr pScrn, int x, int y) 924772b676d7Smrg{ 924872b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 924972b676d7Smrg ULong base; 925072b676d7Smrg 925172b676d7Smrg base = y * pSiS->CurrentLayout.displayWidth + x; 925272b676d7Smrg switch(pSiS->CurrentLayout.bitsPerPixel) { 925372b676d7Smrg case 16: base >>= 1; break; 925472b676d7Smrg case 32: break; 925572b676d7Smrg default: base >>= 2; 925672b676d7Smrg } 925772b676d7Smrg base += (pSiS->dhmOffset/4); 925872b676d7Smrg SISSetStartAddressCRT1(pSiS, base); 925972b676d7Smrg} 926072b676d7Smrg 926172b676d7Smrgstatic void 926272b676d7SmrgSISAdjustFrameHW_CRT2(ScrnInfoPtr pScrn, int x, int y) 926372b676d7Smrg{ 926472b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 926572b676d7Smrg ULong base; 926672b676d7Smrg 926772b676d7Smrg base = y * pSiS->CurrentLayout.displayWidth + x; 926872b676d7Smrg switch(pSiS->CurrentLayout.bitsPerPixel) { 926972b676d7Smrg case 16: base >>= 1; break; 927072b676d7Smrg case 32: break; 927172b676d7Smrg default: base >>= 2; 927272b676d7Smrg } 927372b676d7Smrg base += (pSiS->dhmOffset/4); 927472b676d7Smrg SISSetStartAddressCRT2(pSiS, base); 927572b676d7Smrg} 927672b676d7Smrg 927772b676d7Smrgstatic void 92785788ca14SmrgSISMergedPointerMoved(SCRN_ARG_TYPE arg, int x, int y) 927972b676d7Smrg{ 92805788ca14Smrg SCRN_INFO_PTR(arg); 92815788ca14Smrg ScrnInfoPtr pScrn1 = pScrn; 928272b676d7Smrg SISPtr pSiS = SISPTR(pScrn1); 928372b676d7Smrg ScrnInfoPtr pScrn2 = pSiS->CRT2pScrn; 928472b676d7Smrg region out, in1, in2, f2, f1; 928572b676d7Smrg int deltax, deltay; 928672b676d7Smrg int temp1, temp2; 928772b676d7Smrg int old1x0, old1y0, old2x0, old2y0; 928872b676d7Smrg int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; 928972b676d7Smrg int HVirt = pScrn1->virtualX; 929072b676d7Smrg int VVirt = pScrn1->virtualY; 929172b676d7Smrg int sigstate; 929272b676d7Smrg Bool doit = FALSE, HaveNonRect = FALSE, HaveOffsRegions = FALSE; 929372b676d7Smrg SiSScrn2Rel srel = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT2Position; 929472b676d7Smrg 929572b676d7Smrg if(pSiS->DGAactive) { 929672b676d7Smrg return; 929772b676d7Smrg /* DGA: There is no cursor and no panning while DGA is active. */ 929872b676d7Smrg /* If it were, we would need to do: */ 929972b676d7Smrg /* HVirt = pSiS->CurrentLayout.displayWidth; 930072b676d7Smrg VVirt = pSiS->CurrentLayout.displayHeight; 930172b676d7Smrg BOUND(x, pSiS->CurrentLayout.DGAViewportX, HVirt); 930272b676d7Smrg BOUND(y, pSiS->CurrentLayout.DGAViewportY, VVirt); */ 930372b676d7Smrg } else { 930472b676d7Smrg CRT1XOffs = pSiS->CRT1XOffs; 930572b676d7Smrg CRT1YOffs = pSiS->CRT1YOffs; 930672b676d7Smrg CRT2XOffs = pSiS->CRT2XOffs; 930772b676d7Smrg CRT2YOffs = pSiS->CRT2YOffs; 930872b676d7Smrg HaveNonRect = pSiS->HaveNonRect; 930972b676d7Smrg HaveOffsRegions = pSiS->HaveOffsRegions; 931072b676d7Smrg } 931172b676d7Smrg 931272b676d7Smrg /* Check if the pointer is inside our dead areas */ 931372b676d7Smrg if((pSiS->MouseRestrictions) && (srel != sisClone) && !SiSnoPanoramiXExtension) { 931472b676d7Smrg if(HaveNonRect) { 931572b676d7Smrg if(InRegion(x, y, pSiS->NonRectDead)) { 931672b676d7Smrg switch(srel) { 931772b676d7Smrg case sisLeftOf: 931872b676d7Smrg case sisRightOf: y = pSiS->NonRectDead.y0 - 1; 931972b676d7Smrg doit = TRUE; 932072b676d7Smrg break; 932172b676d7Smrg case sisAbove: 932272b676d7Smrg case sisBelow: x = pSiS->NonRectDead.x0 - 1; 932372b676d7Smrg doit = TRUE; 932472b676d7Smrg default: break; 932572b676d7Smrg } 932672b676d7Smrg } 932772b676d7Smrg } 932872b676d7Smrg if(HaveOffsRegions) { 932972b676d7Smrg if(InRegion(x, y, pSiS->OffDead1)) { 933072b676d7Smrg switch(srel) { 933172b676d7Smrg case sisLeftOf: 933272b676d7Smrg case sisRightOf: y = pSiS->OffDead1.y1; 933372b676d7Smrg doit = TRUE; 933472b676d7Smrg break; 933572b676d7Smrg case sisAbove: 933672b676d7Smrg case sisBelow: x = pSiS->OffDead1.x1; 933772b676d7Smrg doit = TRUE; 933872b676d7Smrg default: break; 933972b676d7Smrg } 934072b676d7Smrg } else if(InRegion(x, y, pSiS->OffDead2)) { 934172b676d7Smrg switch(srel) { 934272b676d7Smrg case sisLeftOf: 934372b676d7Smrg case sisRightOf: y = pSiS->OffDead2.y0 - 1; 934472b676d7Smrg doit = TRUE; 934572b676d7Smrg break; 934672b676d7Smrg case sisAbove: 934772b676d7Smrg case sisBelow: x = pSiS->OffDead2.x0 - 1; 934872b676d7Smrg doit = TRUE; 934972b676d7Smrg default: break; 935072b676d7Smrg } 935172b676d7Smrg } 935272b676d7Smrg } 935372b676d7Smrg if(doit) { 935472b676d7Smrg sigstate = xf86BlockSIGIO(); 93555788ca14Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 15 93565788ca14Smrg { 93575788ca14Smrg double dx = x, dy = y; 93585788ca14Smrg miPointerSetPosition(inputInfo.pointer, Absolute, &dx, &dy); 93595788ca14Smrg x = (int)dx; 93605788ca14Smrg y = (int)dy; 93615788ca14Smrg } 93625788ca14Smrg#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 13 93635788ca14Smrg miPointerSetPosition(inputInfo.pointer, Absolute, x, y); 93645788ca14Smrg#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 5 9365256c1e2bSmrg miPointerSetPosition(inputInfo.pointer, &x, &y); 93665788ca14Smrg#else 93675788ca14Smrg UpdateCurrentTime(); 93685788ca14Smrg miPointerAbsoluteCursor(x, y, currentTime.milliseconds); 93695788ca14Smrg#endif 937072b676d7Smrg xf86UnblockSIGIO(sigstate); 937172b676d7Smrg return; 937272b676d7Smrg } 937372b676d7Smrg } 937472b676d7Smrg 937572b676d7Smrg f1.x0 = old1x0 = pSiS->CRT1frameX0; 937672b676d7Smrg f1.x1 = pSiS->CRT1frameX1; 937772b676d7Smrg f1.y0 = old1y0 = pSiS->CRT1frameY0; 937872b676d7Smrg f1.y1 = pSiS->CRT1frameY1; 937972b676d7Smrg f2.x0 = old2x0 = pScrn2->frameX0; 938072b676d7Smrg f2.x1 = pScrn2->frameX1; 938172b676d7Smrg f2.y0 = old2y0 = pScrn2->frameY0; 938272b676d7Smrg f2.y1 = pScrn2->frameY1; 938372b676d7Smrg 938472b676d7Smrg /* Define the outer region. Crossing this causes all frames to move */ 938572b676d7Smrg out.x0 = pScrn1->frameX0; 938672b676d7Smrg out.x1 = pScrn1->frameX1; 938772b676d7Smrg out.y0 = pScrn1->frameY0; 938872b676d7Smrg out.y1 = pScrn1->frameY1; 938972b676d7Smrg 939072b676d7Smrg /* 939172b676d7Smrg * Define the inner sliding window. Being outsize both frames but 939272b676d7Smrg * inside the outer clipping window will slide corresponding frame 939372b676d7Smrg */ 939472b676d7Smrg in1 = out; 939572b676d7Smrg in2 = out; 939672b676d7Smrg switch(srel) { 939772b676d7Smrg case sisLeftOf: 939872b676d7Smrg in1.x0 = f1.x0; 939972b676d7Smrg in2.x1 = f2.x1; 940072b676d7Smrg break; 940172b676d7Smrg case sisRightOf: 940272b676d7Smrg in1.x1 = f1.x1; 940372b676d7Smrg in2.x0 = f2.x0; 940472b676d7Smrg break; 940572b676d7Smrg case sisBelow: 940672b676d7Smrg in1.y1 = f1.y1; 940772b676d7Smrg in2.y0 = f2.y0; 940872b676d7Smrg break; 940972b676d7Smrg case sisAbove: 941072b676d7Smrg in1.y0 = f1.y0; 941172b676d7Smrg in2.y1 = f2.y1; 941272b676d7Smrg break; 941372b676d7Smrg case sisClone: 941472b676d7Smrg break; 941572b676d7Smrg } 941672b676d7Smrg 941772b676d7Smrg deltay = 0; 941872b676d7Smrg deltax = 0; 941972b676d7Smrg 942072b676d7Smrg if(InRegion(x, y, out)) { /* inside outer region */ 942172b676d7Smrg 942272b676d7Smrg if(InRegion(x, y, in1) && !InRegion(x, y, f1)) { 942372b676d7Smrg REBOUND(f1.x0, f1.x1, x); 942472b676d7Smrg REBOUND(f1.y0, f1.y1, y); 942572b676d7Smrg deltax = 1; 942672b676d7Smrg } 942772b676d7Smrg if(InRegion(x, y, in2) && !InRegion(x, y, f2)) { 942872b676d7Smrg REBOUND(f2.x0, f2.x1, x); 942972b676d7Smrg REBOUND(f2.y0, f2.y1, y); 943072b676d7Smrg deltax = 1; 943172b676d7Smrg } 943272b676d7Smrg 943372b676d7Smrg } else { /* outside outer region */ 943472b676d7Smrg 943572b676d7Smrg if(out.x0 > x) { 943672b676d7Smrg deltax = x - out.x0; 943772b676d7Smrg } 943872b676d7Smrg if(out.x1 < x) { 943972b676d7Smrg deltax = x - out.x1; 944072b676d7Smrg } 944172b676d7Smrg if(deltax) { 944272b676d7Smrg pScrn1->frameX0 += deltax; 944372b676d7Smrg pScrn1->frameX1 += deltax; 944472b676d7Smrg f1.x0 += deltax; 944572b676d7Smrg f1.x1 += deltax; 944672b676d7Smrg f2.x0 += deltax; 944772b676d7Smrg f2.x1 += deltax; 944872b676d7Smrg } 944972b676d7Smrg 945072b676d7Smrg if(out.y0 > y) { 945172b676d7Smrg deltay = y - out.y0; 945272b676d7Smrg } 945372b676d7Smrg if(out.y1 < y) { 945472b676d7Smrg deltay = y - out.y1; 945572b676d7Smrg } 945672b676d7Smrg if(deltay) { 945772b676d7Smrg pScrn1->frameY0 += deltay; 945872b676d7Smrg pScrn1->frameY1 += deltay; 945972b676d7Smrg f1.y0 += deltay; 946072b676d7Smrg f1.y1 += deltay; 946172b676d7Smrg f2.y0 += deltay; 946272b676d7Smrg f2.y1 += deltay; 946372b676d7Smrg } 946472b676d7Smrg 946572b676d7Smrg switch(srel) { 946672b676d7Smrg case sisLeftOf: 946772b676d7Smrg if(x >= f1.x0) { REBOUND(f1.y0, f1.y1, y); } 946872b676d7Smrg if(x <= f2.x1) { REBOUND(f2.y0, f2.y1, y); } 946972b676d7Smrg break; 947072b676d7Smrg case sisRightOf: 947172b676d7Smrg if(x <= f1.x1) { REBOUND(f1.y0, f1.y1, y); } 947272b676d7Smrg if(x >= f2.x0) { REBOUND(f2.y0, f2.y1, y); } 947372b676d7Smrg break; 947472b676d7Smrg case sisBelow: 947572b676d7Smrg if(y <= f1.y1) { REBOUND(f1.x0, f1.x1, x); } 947672b676d7Smrg if(y >= f2.y0) { REBOUND(f2.x0, f2.x1, x); } 947772b676d7Smrg break; 947872b676d7Smrg case sisAbove: 947972b676d7Smrg if(y >= f1.y0) { REBOUND(f1.x0, f1.x1, x); } 948072b676d7Smrg if(y <= f2.y1) { REBOUND(f2.x0, f2.x1, x); } 948172b676d7Smrg break; 948272b676d7Smrg case sisClone: 948372b676d7Smrg break; 948472b676d7Smrg } 948572b676d7Smrg 948672b676d7Smrg } 948772b676d7Smrg 948872b676d7Smrg if(deltax || deltay) { 948972b676d7Smrg pSiS->CRT1frameX0 = f1.x0; 949072b676d7Smrg pSiS->CRT1frameY0 = f1.y0; 949172b676d7Smrg pScrn2->frameX0 = f2.x0; 949272b676d7Smrg pScrn2->frameY0 = f2.y0; 949372b676d7Smrg 949472b676d7Smrg switch(srel) { 949572b676d7Smrg case sisLeftOf: 949672b676d7Smrg case sisRightOf: 949772b676d7Smrg if(CRT1YOffs || CRT2YOffs || HaveNonRect) { 949872b676d7Smrg if(pSiS->CRT1frameY0 != old1y0) { 949972b676d7Smrg if(pSiS->CRT1frameY0 < CRT1YOffs) 950072b676d7Smrg pSiS->CRT1frameY0 = CRT1YOffs; 950172b676d7Smrg 950272b676d7Smrg temp1 = pSiS->CRT1frameY0 + CDMPTR->CRT1->VDisplay; 950372b676d7Smrg temp2 = min((VVirt - CRT2YOffs), (CRT1YOffs + pSiS->MBXNR1YMAX)); 950472b676d7Smrg if(temp1 > temp2) 950572b676d7Smrg pSiS->CRT1frameY0 -= (temp1 - temp2); 950672b676d7Smrg } 950772b676d7Smrg if(pScrn2->frameY0 != old2y0) { 950872b676d7Smrg if(pScrn2->frameY0 < CRT2YOffs) 950972b676d7Smrg pScrn2->frameY0 = CRT2YOffs; 951072b676d7Smrg 951172b676d7Smrg temp1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay; 951272b676d7Smrg temp2 = min((VVirt - CRT1YOffs), (CRT2YOffs + pSiS->MBXNR2YMAX)); 951372b676d7Smrg if(temp1 > temp2) 951472b676d7Smrg pScrn2->frameY0 -= (temp1 - temp2); 951572b676d7Smrg } 951672b676d7Smrg } 951772b676d7Smrg break; 951872b676d7Smrg case sisBelow: 951972b676d7Smrg case sisAbove: 952072b676d7Smrg if(CRT1XOffs || CRT2XOffs || HaveNonRect) { 952172b676d7Smrg if(pSiS->CRT1frameX0 != old1x0) { 952272b676d7Smrg if(pSiS->CRT1frameX0 < CRT1XOffs) 952372b676d7Smrg pSiS->CRT1frameX0 = CRT1XOffs; 952472b676d7Smrg 952572b676d7Smrg temp1 = pSiS->CRT1frameX0 + CDMPTR->CRT1->HDisplay; 952672b676d7Smrg temp2 = min((HVirt - CRT2XOffs), (CRT1XOffs + pSiS->MBXNR1XMAX)); 952772b676d7Smrg if(temp1 > temp2) 952872b676d7Smrg pSiS->CRT1frameX0 -= (temp1 - temp2); 952972b676d7Smrg } 953072b676d7Smrg if(pScrn2->frameX0 != old2x0) { 953172b676d7Smrg if(pScrn2->frameX0 < CRT2XOffs) 953272b676d7Smrg pScrn2->frameX0 = CRT2XOffs; 953372b676d7Smrg 953472b676d7Smrg temp1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay; 953572b676d7Smrg temp2 = min((HVirt - CRT1XOffs), (CRT2XOffs + pSiS->MBXNR2XMAX)); 953672b676d7Smrg if(temp1 > temp2) 953772b676d7Smrg pScrn2->frameX0 -= (temp1 - temp2); 953872b676d7Smrg } 953972b676d7Smrg } 954072b676d7Smrg break; 954172b676d7Smrg case sisClone: 954272b676d7Smrg break; 954372b676d7Smrg } 954472b676d7Smrg 954572b676d7Smrg pSiS->CRT1frameX1 = pSiS->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1; 954672b676d7Smrg pSiS->CRT1frameY1 = pSiS->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1; 954772b676d7Smrg pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1; 954872b676d7Smrg pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1; 954972b676d7Smrg 955072b676d7Smrg /* No need to update pScrn1->frame?1, done above */ 955172b676d7Smrg 955272b676d7Smrg SISAdjustFrameHW_CRT1(pScrn1, pSiS->CRT1frameX0, pSiS->CRT1frameY0); 955372b676d7Smrg SISAdjustFrameHW_CRT2(pScrn1, pScrn2->frameX0, pScrn2->frameY0); 955472b676d7Smrg } 955572b676d7Smrg} 955672b676d7Smrg 955772b676d7Smrgstatic void 95585788ca14SmrgSISAdjustFrameMerged(ADJUST_FRAME_ARGS_DECL) 955972b676d7Smrg{ 95605788ca14Smrg SCRN_INFO_PTR(arg); 95615788ca14Smrg ScrnInfoPtr pScrn1 = pScrn; 956272b676d7Smrg SISPtr pSiS = SISPTR(pScrn1); 956372b676d7Smrg ScrnInfoPtr pScrn2 = pSiS->CRT2pScrn; 956472b676d7Smrg int HTotal = pSiS->CurrentLayout.mode->HDisplay; 956572b676d7Smrg int VTotal = pSiS->CurrentLayout.mode->VDisplay; 956672b676d7Smrg int HMax = HTotal; 956772b676d7Smrg int VMax = VTotal; 956872b676d7Smrg int HVirt = pScrn1->virtualX; 956972b676d7Smrg int VVirt = pScrn1->virtualY; 957072b676d7Smrg int x1 = x, x2 = x; 957172b676d7Smrg int y1 = y, y2 = y; 957272b676d7Smrg int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; 957372b676d7Smrg int MBXNR1XMAX = 65536, MBXNR1YMAX = 65536, MBXNR2XMAX = 65536, MBXNR2YMAX = 65536; 957472b676d7Smrg 957572b676d7Smrg if(pSiS->DGAactive) { 957672b676d7Smrg HVirt = pSiS->CurrentLayout.displayWidth; 957772b676d7Smrg VVirt = pSiS->CurrentLayout.displayHeight; 957872b676d7Smrg } else { 957972b676d7Smrg CRT1XOffs = pSiS->CRT1XOffs; 958072b676d7Smrg CRT1YOffs = pSiS->CRT1YOffs; 958172b676d7Smrg CRT2XOffs = pSiS->CRT2XOffs; 958272b676d7Smrg CRT2YOffs = pSiS->CRT2YOffs; 958372b676d7Smrg MBXNR1XMAX = pSiS->MBXNR1XMAX; 958472b676d7Smrg MBXNR1YMAX = pSiS->MBXNR1YMAX; 958572b676d7Smrg MBXNR2XMAX = pSiS->MBXNR2XMAX; 958672b676d7Smrg MBXNR2YMAX = pSiS->MBXNR2YMAX; 958772b676d7Smrg } 958872b676d7Smrg 958972b676d7Smrg BOUND(x, 0, HVirt - HTotal); 959072b676d7Smrg BOUND(y, 0, VVirt - VTotal); 959172b676d7Smrg if(SDMPTR(pScrn1)->CRT2Position != sisClone) { 959272b676d7Smrg BOUND(x1, CRT1XOffs, min(HVirt, MBXNR1XMAX + CRT1XOffs) - min(HTotal, MBXNR1XMAX) - CRT2XOffs); 959372b676d7Smrg BOUND(y1, CRT1YOffs, min(VVirt, MBXNR1YMAX + CRT1YOffs) - min(VTotal, MBXNR1YMAX) - CRT2YOffs); 959472b676d7Smrg BOUND(x2, CRT2XOffs, min(HVirt, MBXNR2XMAX + CRT2XOffs) - min(HTotal, MBXNR2XMAX) - CRT1XOffs); 959572b676d7Smrg BOUND(y2, CRT2YOffs, min(VVirt, MBXNR2YMAX + CRT2YOffs) - min(VTotal, MBXNR2YMAX) - CRT1YOffs); 959672b676d7Smrg } 959772b676d7Smrg 959872b676d7Smrg switch(SDMPTR(pScrn1)->CRT2Position) { 959972b676d7Smrg case sisLeftOf: 960072b676d7Smrg pScrn2->frameX0 = x2; 960172b676d7Smrg BOUND(pScrn2->frameY0, y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR->CRT2->VDisplay); 960272b676d7Smrg pSiS->CRT1frameX0 = x1 + CDMPTR->CRT2->HDisplay; 960372b676d7Smrg BOUND(pSiS->CRT1frameY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR->CRT1->VDisplay); 960472b676d7Smrg break; 960572b676d7Smrg case sisRightOf: 960672b676d7Smrg pSiS->CRT1frameX0 = x1; 960772b676d7Smrg BOUND(pSiS->CRT1frameY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR->CRT1->VDisplay); 960872b676d7Smrg pScrn2->frameX0 = x2 + CDMPTR->CRT1->HDisplay; 960972b676d7Smrg BOUND(pScrn2->frameY0, y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR->CRT2->VDisplay); 961072b676d7Smrg break; 961172b676d7Smrg case sisAbove: 961272b676d7Smrg BOUND(pScrn2->frameX0, x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR->CRT2->HDisplay); 961372b676d7Smrg pScrn2->frameY0 = y2; 961472b676d7Smrg BOUND(pSiS->CRT1frameX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR->CRT1->HDisplay); 961572b676d7Smrg pSiS->CRT1frameY0 = y1 + CDMPTR->CRT2->VDisplay; 961672b676d7Smrg break; 961772b676d7Smrg case sisBelow: 961872b676d7Smrg BOUND(pSiS->CRT1frameX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR->CRT1->HDisplay); 961972b676d7Smrg pSiS->CRT1frameY0 = y1; 962072b676d7Smrg BOUND(pScrn2->frameX0, x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR->CRT2->HDisplay); 962172b676d7Smrg pScrn2->frameY0 = y2 + CDMPTR->CRT1->VDisplay; 962272b676d7Smrg break; 962372b676d7Smrg case sisClone: 962472b676d7Smrg BOUND(pSiS->CRT1frameX0, x, x + HMax - CDMPTR->CRT1->HDisplay); 962572b676d7Smrg BOUND(pSiS->CRT1frameY0, y, y + VMax - CDMPTR->CRT1->VDisplay); 962672b676d7Smrg BOUND(pScrn2->frameX0, x, x + HMax - CDMPTR->CRT2->HDisplay); 962772b676d7Smrg BOUND(pScrn2->frameY0, y, y + VMax - CDMPTR->CRT2->VDisplay); 962872b676d7Smrg break; 962972b676d7Smrg } 963072b676d7Smrg 963172b676d7Smrg BOUND(pSiS->CRT1frameX0, 0, HVirt - CDMPTR->CRT1->HDisplay); 963272b676d7Smrg BOUND(pSiS->CRT1frameY0, 0, VVirt - CDMPTR->CRT1->VDisplay); 963372b676d7Smrg BOUND(pScrn2->frameX0, 0, HVirt - CDMPTR->CRT2->HDisplay); 963472b676d7Smrg BOUND(pScrn2->frameY0, 0, VVirt - CDMPTR->CRT2->VDisplay); 963572b676d7Smrg 963672b676d7Smrg pScrn1->frameX0 = x; 963772b676d7Smrg pScrn1->frameY0 = y; 963872b676d7Smrg 963972b676d7Smrg pSiS->CRT1frameX1 = pSiS->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1; 964072b676d7Smrg pSiS->CRT1frameY1 = pSiS->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1; 964172b676d7Smrg pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1; 964272b676d7Smrg pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1; 964372b676d7Smrg 964472b676d7Smrg pScrn1->frameX1 = pScrn1->frameX0 + pSiS->CurrentLayout.mode->HDisplay - 1; 964572b676d7Smrg pScrn1->frameY1 = pScrn1->frameY0 + pSiS->CurrentLayout.mode->VDisplay - 1; 964672b676d7Smrg if(SDMPTR(pScrn1)->CRT2Position != sisClone) { 964772b676d7Smrg pScrn1->frameX1 += CRT1XOffs + CRT2XOffs; 964872b676d7Smrg pScrn1->frameY1 += CRT1YOffs + CRT2YOffs; 964972b676d7Smrg } 965072b676d7Smrg 965172b676d7Smrg SISAdjustFrameHW_CRT1(pScrn1, pSiS->CRT1frameX0, pSiS->CRT1frameY0); 965272b676d7Smrg SISAdjustFrameHW_CRT2(pScrn1, pScrn2->frameX0, pScrn2->frameY0); 965372b676d7Smrg} 965472b676d7Smrg#endif 965572b676d7Smrg 965672b676d7Smrg/* 965772b676d7Smrg * This function is used to initialize the Start Address - the first 965872b676d7Smrg * displayed location in the video memory. 965972b676d7Smrg * 966072b676d7Smrg * Usually mandatory 966172b676d7Smrg */ 966272b676d7Smrgvoid 96635788ca14SmrgSISAdjustFrame(ADJUST_FRAME_ARGS_DECL) 966472b676d7Smrg{ 96655788ca14Smrg SCRN_INFO_PTR(arg); 966672b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 966772b676d7Smrg ULong base; 966872b676d7Smrg UChar temp, cr11backup; 966972b676d7Smrg 967072b676d7Smrg#ifdef SISMERGED 967172b676d7Smrg if(pSiS->MergedFB) { 96725788ca14Smrg SISAdjustFrameMerged(ADJUST_FRAME_ARGS(pScrn, x, y)); 967372b676d7Smrg return; 967472b676d7Smrg } 967572b676d7Smrg#endif 967672b676d7Smrg 967772b676d7Smrg if(pSiS->UseVESA) { 967872b676d7Smrg VBESetDisplayStart(pSiS->pVbe, x, y, TRUE); 967972b676d7Smrg return; 968072b676d7Smrg } 968172b676d7Smrg 968272b676d7Smrg if(pScrn->bitsPerPixel < 8) { 968372b676d7Smrg base = (y * pSiS->CurrentLayout.displayWidth + x + 3) >> 3; 968472b676d7Smrg } else { 968572b676d7Smrg base = y * pSiS->CurrentLayout.displayWidth + x; 968672b676d7Smrg 968772b676d7Smrg /* calculate base bpp dep. */ 968872b676d7Smrg switch(pSiS->CurrentLayout.bitsPerPixel) { 968972b676d7Smrg case 16: 969072b676d7Smrg base >>= 1; 969172b676d7Smrg break; 969272b676d7Smrg case 24: 969372b676d7Smrg base = ((base * 3)) >> 2; 969472b676d7Smrg base -= base % 6; 969572b676d7Smrg break; 969672b676d7Smrg case 32: 969772b676d7Smrg break; 969872b676d7Smrg default: /* 8bpp */ 969972b676d7Smrg base >>= 2; 970072b676d7Smrg break; 970172b676d7Smrg } 970272b676d7Smrg } 970372b676d7Smrg 970472b676d7Smrg#ifdef UNLOCK_ALWAYS 970572b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 970672b676d7Smrg#endif 970772b676d7Smrg 970872b676d7Smrg base += (pSiS->dhmOffset/4); 970972b676d7Smrg 971072b676d7Smrg#ifdef TWDEBUG 971172b676d7Smrg xf86DrvMsg(0, 0, "AdjustFrame: x %d y %d bpp %d dw %d base %d, dhmOffset %d\n", 971272b676d7Smrg x, y, pSiS->CurrentLayout.bitsPerPixel, pSiS->CurrentLayout.displayWidth, base, pSiS->dhmOffset); 971372b676d7Smrg#endif 971472b676d7Smrg 971572b676d7Smrg#ifdef SISDUALHEAD 971672b676d7Smrg if(pSiS->DualHeadMode) { 971772b676d7Smrg if(!pSiS->SecondHead) { 971872b676d7Smrg /* Head 1 (master) is always CRT2 */ 971972b676d7Smrg SISSetStartAddressCRT2(pSiS, base); 972072b676d7Smrg } else { 972172b676d7Smrg /* Head 2 (slave) is always CRT1 */ 972272b676d7Smrg SISSetStartAddressCRT1(pSiS, base); 972372b676d7Smrg } 972472b676d7Smrg } else { 972572b676d7Smrg#endif 972672b676d7Smrg switch(pSiS->VGAEngine) { 972772b676d7Smrg case SIS_300_VGA: 972872b676d7Smrg case SIS_315_VGA: 972972b676d7Smrg SISSetStartAddressCRT1(pSiS, base); 973072b676d7Smrg if(pSiS->VBFlags & CRT2_ENABLE) { 973172b676d7Smrg if(!SiSBridgeIsInSlaveMode(pScrn)) { 973272b676d7Smrg SISSetStartAddressCRT2(pSiS, base); 973372b676d7Smrg } 973472b676d7Smrg } 973572b676d7Smrg break; 973672b676d7Smrg default: 973772b676d7Smrg /* Unlock CRTC registers */ 973872b676d7Smrg inSISIDXREG(SISCR, 0x11, cr11backup); 973972b676d7Smrg andSISIDXREG(SISCR, 0x11, 0x7F); 974072b676d7Smrg outSISIDXREG(SISCR, 0x0D, base & 0xFF); 974172b676d7Smrg outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); 974272b676d7Smrg inSISIDXREG(SISSR, 0x27, temp); 974372b676d7Smrg temp &= 0xF0; 974472b676d7Smrg temp |= (base & 0x0F0000) >> 16; 974572b676d7Smrg outSISIDXREG(SISSR, 0x27, temp); 974672b676d7Smrg /* Eventually lock CRTC registers */ 974772b676d7Smrg setSISIDXREG(SISCR, 0x11, 0x7F, (cr11backup & 0x80)); 974872b676d7Smrg } 974972b676d7Smrg#ifdef SISDUALHEAD 975072b676d7Smrg } 975172b676d7Smrg#endif 975272b676d7Smrg 975372b676d7Smrg} 975472b676d7Smrg 975572b676d7Smrg/* 975672b676d7Smrg * This is called when VT switching back to the X server. Its job is 975772b676d7Smrg * to reinitialise the video mode. 975872b676d7Smrg * Mandatory! 975972b676d7Smrg */ 976072b676d7Smrgstatic Bool 97615788ca14SmrgSISEnterVT(VT_FUNC_ARGS_DECL) 976272b676d7Smrg{ 97635788ca14Smrg SCRN_INFO_PTR(arg); 976472b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 976572b676d7Smrg 976672b676d7Smrg SiS_SiSFB_Lock(pScrn, TRUE); 976772b676d7Smrg 976872b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 976972b676d7Smrg 977072b676d7Smrg if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 977172b676d7Smrg outSISIDXREG(SISCR,0x32,pSiS->myCR32); 977272b676d7Smrg outSISIDXREG(SISCR,0x36,pSiS->myCR36); 977372b676d7Smrg outSISIDXREG(SISCR,0x37,pSiS->myCR37); 977472b676d7Smrg } 977572b676d7Smrg 977672b676d7Smrg if(!SISModeInit(pScrn, pScrn->currentMode)) { 977772b676d7Smrg SISErrorLog(pScrn, "SiSEnterVT: SISModeInit() failed\n"); 977872b676d7Smrg return FALSE; 977972b676d7Smrg } 978072b676d7Smrg 97815788ca14Smrg SISAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 978272b676d7Smrg 97835788ca14Smrg#ifdef SISDRI 978472b676d7Smrg if(pSiS->directRenderingEnabled) { 97855788ca14Smrg DRIUnlock(xf86ScrnToScreen(pScrn)); 978672b676d7Smrg } 978772b676d7Smrg#endif 978872b676d7Smrg 978972b676d7Smrg#ifdef SISDUALHEAD 979072b676d7Smrg if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) 979172b676d7Smrg#endif 979272b676d7Smrg if(pSiS->ResetXv) { 979372b676d7Smrg (pSiS->ResetXv)(pScrn); 979472b676d7Smrg } 979572b676d7Smrg 979672b676d7Smrg return TRUE; 979772b676d7Smrg} 979872b676d7Smrg 979972b676d7Smrg/* 980072b676d7Smrg * This is called when VT switching away from the X server. Its job is 980172b676d7Smrg * to restore the previous (text) mode. 980272b676d7Smrg * Mandatory! 980372b676d7Smrg */ 980472b676d7Smrgstatic void 98055788ca14SmrgSISLeaveVT(VT_FUNC_ARGS_DECL) 980672b676d7Smrg{ 98075788ca14Smrg SCRN_INFO_PTR(arg); 980872b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 98095788ca14Smrg#ifdef SISDRI 981072b676d7Smrg ScreenPtr pScreen; 981172b676d7Smrg 981272b676d7Smrg if(pSiS->directRenderingEnabled) { 98135788ca14Smrg pScreen = xf86ScrnToScreen(pScrn); 981472b676d7Smrg DRILock(pScreen, 0); 981572b676d7Smrg } 981672b676d7Smrg#endif 981772b676d7Smrg 981872b676d7Smrg#ifdef SISDUALHEAD 981972b676d7Smrg if(pSiS->DualHeadMode && pSiS->SecondHead) return; 982072b676d7Smrg#endif 982172b676d7Smrg 982272b676d7Smrg if(pSiS->CursorInfoPtr) { 982372b676d7Smrg#ifdef SISDUALHEAD 982472b676d7Smrg if(pSiS->DualHeadMode) { 982572b676d7Smrg if(!pSiS->SecondHead) { 982672b676d7Smrg pSiS->ForceCursorOff = TRUE; 982772b676d7Smrg pSiS->CursorInfoPtr->HideCursor(pScrn); 982872b676d7Smrg SISWaitVBRetrace(pScrn); 982972b676d7Smrg pSiS->ForceCursorOff = FALSE; 983072b676d7Smrg } 983172b676d7Smrg } else { 983272b676d7Smrg#endif 983372b676d7Smrg pSiS->CursorInfoPtr->HideCursor(pScrn); 983472b676d7Smrg SISWaitVBRetrace(pScrn); 983572b676d7Smrg#ifdef SISDUALHEAD 983672b676d7Smrg } 983772b676d7Smrg#endif 983872b676d7Smrg } 983972b676d7Smrg 984072b676d7Smrg SISBridgeRestore(pScrn); 984172b676d7Smrg 984272b676d7Smrg if(pSiS->UseVESA) { 984372b676d7Smrg 984472b676d7Smrg /* This is a q&d work-around for a BIOS bug. In case we disabled CRT2, 984572b676d7Smrg * VBESaveRestore() does not restore CRT1. So we set any mode now, 984672b676d7Smrg * because VBESetVBEMode correctly restores CRT1. Afterwards, we 984772b676d7Smrg * can call VBESaveRestore to restore original mode. 984872b676d7Smrg */ 984972b676d7Smrg if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (!(pSiS->VBFlags & DISPTYPE_DISP2))) 985072b676d7Smrg VBESetVBEMode(pSiS->pVbe, (pSiS->SISVESAModeList->n) | 0xc000, NULL); 985172b676d7Smrg 985272b676d7Smrg SISVESARestore(pScrn); 985372b676d7Smrg 985472b676d7Smrg } else { 985572b676d7Smrg 985672b676d7Smrg SISRestore(pScrn); 985772b676d7Smrg 985872b676d7Smrg } 985972b676d7Smrg 986072b676d7Smrg /* We use (otherwise unused) bit 7 to indicate that we are running 986172b676d7Smrg * to keep sisfb to change the displaymode (this would result in 986272b676d7Smrg * lethal display corruption upon quitting X or changing to a VT 986372b676d7Smrg * until a reboot) 986472b676d7Smrg */ 986572b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 986672b676d7Smrg orSISIDXREG(SISCR,0x34,0x80); 986772b676d7Smrg } 986872b676d7Smrg 986972b676d7Smrg SISVGALock(pSiS); 987072b676d7Smrg 987172b676d7Smrg SiS_SiSFB_Lock(pScrn, FALSE); 987272b676d7Smrg} 987372b676d7Smrg 987472b676d7Smrg 987572b676d7Smrg/* 987672b676d7Smrg * This is called at the end of each server generation. It restores the 987772b676d7Smrg * original (text) mode. It should really also unmap the video memory too. 987872b676d7Smrg * Mandatory! 987972b676d7Smrg */ 988072b676d7Smrgstatic Bool 98815788ca14SmrgSISCloseScreen(CLOSE_SCREEN_ARGS_DECL) 988272b676d7Smrg{ 98835788ca14Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 988472b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 988572b676d7Smrg#ifdef SISDUALHEAD 988672b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 988772b676d7Smrg#endif 988872b676d7Smrg 988972b676d7Smrg if(pSiS->SiSCtrlExtEntry) { 989072b676d7Smrg SiSCtrlExtUnregister(pSiS, pScrn->scrnIndex); 989172b676d7Smrg } 989272b676d7Smrg 98935788ca14Smrg#ifdef SISDRI 989472b676d7Smrg if(pSiS->directRenderingEnabled) { 989572b676d7Smrg SISDRICloseScreen(pScreen); 989672b676d7Smrg pSiS->directRenderingEnabled = FALSE; 989772b676d7Smrg } 989872b676d7Smrg#endif 989972b676d7Smrg 990072b676d7Smrg if(pScrn->vtSema) { 990172b676d7Smrg 990272b676d7Smrg if(pSiS->CursorInfoPtr) { 990372b676d7Smrg#ifdef SISDUALHEAD 990472b676d7Smrg if(pSiS->DualHeadMode) { 990572b676d7Smrg if(!pSiS->SecondHead) { 990672b676d7Smrg pSiS->ForceCursorOff = TRUE; 990772b676d7Smrg pSiS->CursorInfoPtr->HideCursor(pScrn); 990872b676d7Smrg SISWaitVBRetrace(pScrn); 990972b676d7Smrg pSiS->ForceCursorOff = FALSE; 991072b676d7Smrg } 991172b676d7Smrg } else { 991272b676d7Smrg#endif 991372b676d7Smrg pSiS->CursorInfoPtr->HideCursor(pScrn); 991472b676d7Smrg SISWaitVBRetrace(pScrn); 991572b676d7Smrg#ifdef SISDUALHEAD 991672b676d7Smrg } 991772b676d7Smrg#endif 991872b676d7Smrg } 991972b676d7Smrg 992072b676d7Smrg SISBridgeRestore(pScrn); 992172b676d7Smrg 992272b676d7Smrg if(pSiS->UseVESA) { 992372b676d7Smrg 992472b676d7Smrg /* This is a q&d work-around for a BIOS bug. In case we disabled CRT2, 992572b676d7Smrg * VBESaveRestore() does not restore CRT1. So we set any mode now, 992672b676d7Smrg * because VBESetVBEMode correctly restores CRT1. Afterwards, we 992772b676d7Smrg * can call VBESaveRestore to restore original mode. 992872b676d7Smrg */ 992972b676d7Smrg if((pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && (!(pSiS->VBFlags & DISPTYPE_DISP2))) 993072b676d7Smrg VBESetVBEMode(pSiS->pVbe, (pSiS->SISVESAModeList->n) | 0xc000, NULL); 993172b676d7Smrg 993272b676d7Smrg SISVESARestore(pScrn); 993372b676d7Smrg 993472b676d7Smrg } else { 993572b676d7Smrg 993672b676d7Smrg SISRestore(pScrn); 993772b676d7Smrg 993872b676d7Smrg } 993972b676d7Smrg 994072b676d7Smrg SISVGALock(pSiS); 994172b676d7Smrg 994272b676d7Smrg } 994372b676d7Smrg 994472b676d7Smrg SiS_SiSFB_Lock(pScrn, FALSE); 994572b676d7Smrg 994672b676d7Smrg /* We should restore the mode number in case vtsema = false as well, 994772b676d7Smrg * but since we haven't register access then we can't do it. I think 994872b676d7Smrg * I need to rework the save/restore stuff, like saving the video 994972b676d7Smrg * status when returning to the X server and by that save me the 995072b676d7Smrg * trouble if sisfb was started from a textmode VT while X was on. 995172b676d7Smrg */ 995272b676d7Smrg 995372b676d7Smrg SISUnmapMem(pScrn); 995472b676d7Smrg#ifdef SIS_PC_PLATFORM 995572b676d7Smrg SiSVGAUnmapMem(pScrn); 995672b676d7Smrg#endif 995772b676d7Smrg 995872b676d7Smrg#ifdef SISDUALHEAD 995972b676d7Smrg if(pSiS->DualHeadMode) { 996072b676d7Smrg pSiSEnt = pSiS->entityPrivate; 996172b676d7Smrg pSiSEnt->refCount--; 996272b676d7Smrg } 996372b676d7Smrg#endif 996472b676d7Smrg 996572b676d7Smrg if(pSiS->pInt) { 996672b676d7Smrg xf86FreeInt10(pSiS->pInt); 996772b676d7Smrg pSiS->pInt = NULL; 996872b676d7Smrg } 996972b676d7Smrg 997072b676d7Smrg#ifdef SIS_USE_XAA 997172b676d7Smrg if(!pSiS->useEXA) { 997272b676d7Smrg if(pSiS->AccelLinearScratch) { 997372b676d7Smrg xf86FreeOffscreenLinear(pSiS->AccelLinearScratch); 997472b676d7Smrg pSiS->AccelLinearScratch = NULL; 997572b676d7Smrg } 997672b676d7Smrg if(pSiS->AccelInfoPtr) { 997772b676d7Smrg XAADestroyInfoRec(pSiS->AccelInfoPtr); 997872b676d7Smrg pSiS->AccelInfoPtr = NULL; 997972b676d7Smrg } 998072b676d7Smrg } 998172b676d7Smrg#endif 998272b676d7Smrg 998372b676d7Smrg#ifdef SIS_USE_EXA 998472b676d7Smrg if(pSiS->useEXA) { 998572b676d7Smrg if(pSiS->EXADriverPtr) { 998672b676d7Smrg exaDriverFini(pScreen); 99875788ca14Smrg free(pSiS->EXADriverPtr); 998872b676d7Smrg pSiS->EXADriverPtr = NULL; 998972b676d7Smrg pSiS->exa_scratch = NULL; 999072b676d7Smrg } 999172b676d7Smrg } 999272b676d7Smrg#endif 999372b676d7Smrg 999472b676d7Smrg if(pSiS->CursorInfoPtr) { 999572b676d7Smrg xf86DestroyCursorInfoRec(pSiS->CursorInfoPtr); 999672b676d7Smrg pSiS->CursorInfoPtr = NULL; 999772b676d7Smrg } 999872b676d7Smrg 999972b676d7Smrg if(pSiS->ShadowPtr) { 100005788ca14Smrg free(pSiS->ShadowPtr); 1000172b676d7Smrg pSiS->ShadowPtr = NULL; 1000272b676d7Smrg } 1000372b676d7Smrg 1000472b676d7Smrg if(pSiS->DGAModes) { 100055788ca14Smrg free(pSiS->DGAModes); 1000672b676d7Smrg pSiS->DGAModes = NULL; 1000772b676d7Smrg } 1000872b676d7Smrg 1000972b676d7Smrg if(pSiS->adaptor) { 100105788ca14Smrg free(pSiS->adaptor); 1001172b676d7Smrg pSiS->adaptor = NULL; 1001272b676d7Smrg pSiS->ResetXv = pSiS->ResetXvGamma = pSiS->ResetXvDisplay = NULL; 1001372b676d7Smrg } 1001472b676d7Smrg 1001572b676d7Smrg if(pSiS->blitadaptor) { 100165788ca14Smrg free(pSiS->blitadaptor); 1001772b676d7Smrg pSiS->blitadaptor = NULL; 1001872b676d7Smrg } 1001972b676d7Smrg 1002072b676d7Smrg if(pSiS->crt2gcolortable) { 100215788ca14Smrg free(pSiS->crt2gcolortable); 1002272b676d7Smrg pSiS->crt2gcolortable = NULL; 1002372b676d7Smrg } 1002472b676d7Smrg 1002572b676d7Smrg if(pSiS->crt2cindices) { 100265788ca14Smrg free(pSiS->crt2cindices); 1002772b676d7Smrg pSiS->crt2cindices = NULL; 1002872b676d7Smrg } 1002972b676d7Smrg 1003072b676d7Smrg pScrn->vtSema = FALSE; 1003172b676d7Smrg 1003272b676d7Smrg /* Restore Blockhandler */ 1003372b676d7Smrg pScreen->BlockHandler = pSiS->BlockHandler; 1003472b676d7Smrg 1003572b676d7Smrg pScreen->CloseScreen = pSiS->CloseScreen; 1003672b676d7Smrg 100375788ca14Smrg return(*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); 1003872b676d7Smrg} 1003972b676d7Smrg 1004072b676d7Smrg 1004172b676d7Smrg/* Free up any per-generation data structures */ 1004272b676d7Smrg 1004372b676d7Smrg/* Optional */ 1004472b676d7Smrgstatic void 100455788ca14SmrgSISFreeScreen(FREE_SCREEN_ARGS_DECL) 1004672b676d7Smrg{ 100475788ca14Smrg SCRN_INFO_PTR(arg); 1004872b676d7Smrg#ifdef SIS_NEED_MAP_IOP 1004972b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1005072b676d7Smrg 1005172b676d7Smrg if(pSiS) { 1005272b676d7Smrg#ifdef SISDUALHEAD 1005372b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1005472b676d7Smrg if(pSiSEnt) { 1005572b676d7Smrg pSiSEnt->forceUnmapIOPBase = TRUE; 1005672b676d7Smrg } 1005772b676d7Smrg#endif 1005872b676d7Smrg SISUnmapIOPMem(pScrn); 1005972b676d7Smrg } 1006072b676d7Smrg#endif 1006172b676d7Smrg 100625788ca14Smrg SISFreeRec(pScrn); 1006372b676d7Smrg} 1006472b676d7Smrg 1006572b676d7Smrg 1006672b676d7Smrg/* Checks if a mode is suitable for the selected chipset. */ 1006772b676d7Smrg 1006872b676d7Smrgstatic ModeStatus 100695788ca14SmrgSISValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 1007072b676d7Smrg{ 100715788ca14Smrg SCRN_INFO_PTR(arg); 1007272b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1007372b676d7Smrg 1007472b676d7Smrg if(pSiS->UseVESA) { 1007572b676d7Smrg if(SiSCalcVESAModeIndex(pScrn, mode)) 1007672b676d7Smrg return(MODE_OK); 1007772b676d7Smrg else 1007872b676d7Smrg return(MODE_BAD); 1007972b676d7Smrg } 1008072b676d7Smrg 1008172b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 1008272b676d7Smrg#ifdef SISDUALHEAD 1008372b676d7Smrg if(pSiS->DualHeadMode) { 1008472b676d7Smrg if(pSiS->SecondHead) { 1008572b676d7Smrg if(SiS_CheckModeCRT1(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 1008672b676d7Smrg return(MODE_BAD); 1008772b676d7Smrg } else { 1008872b676d7Smrg if(SiS_CheckModeCRT2(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 1008972b676d7Smrg return(MODE_BAD); 1009072b676d7Smrg } 1009172b676d7Smrg } else 1009272b676d7Smrg#endif 1009372b676d7Smrg#ifdef SISMERGED 1009472b676d7Smrg if(pSiS->MergedFB) { 1009572b676d7Smrg if(!mode->Private) { 1009672b676d7Smrg if(!pSiS->CheckForCRT2) { 1009772b676d7Smrg if(SiS_CheckModeCRT1(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 1009872b676d7Smrg return(MODE_BAD); 1009972b676d7Smrg } else { 1010072b676d7Smrg if(SiS_CheckModeCRT2(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes2) < 0x14) 1010172b676d7Smrg return(MODE_BAD); 1010272b676d7Smrg } 1010372b676d7Smrg } else { 1010472b676d7Smrg if(SiS_CheckModeCRT1(pScrn, ((SiSMergedDisplayModePtr)mode->Private)->CRT1, 1010572b676d7Smrg pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 1010672b676d7Smrg return(MODE_BAD); 1010772b676d7Smrg 1010872b676d7Smrg if(SiS_CheckModeCRT2(pScrn, ((SiSMergedDisplayModePtr)mode->Private)->CRT2, 1010972b676d7Smrg pSiS->VBFlags, pSiS->HaveCustomModes2) < 0x14) 1011072b676d7Smrg return(MODE_BAD); 1011172b676d7Smrg } 1011272b676d7Smrg } else 1011372b676d7Smrg#endif 1011472b676d7Smrg { 1011572b676d7Smrg if(SiS_CheckModeCRT1(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 1011672b676d7Smrg return(MODE_BAD); 1011772b676d7Smrg 1011872b676d7Smrg if(SiS_CheckModeCRT2(pScrn, mode, pSiS->VBFlags, pSiS->HaveCustomModes) < 0x14) 1011972b676d7Smrg return(MODE_BAD); 1012072b676d7Smrg } 1012172b676d7Smrg } 1012272b676d7Smrg 1012372b676d7Smrg return(MODE_OK); 1012472b676d7Smrg} 1012572b676d7Smrg 1012672b676d7Smrg#ifdef DEBUG 1012772b676d7Smrgstatic void 1012872b676d7SmrgSiSDumpModeInfo(ScrnInfoPtr pScrn, DisplayModePtr mode) 1012972b676d7Smrg{ 1013072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Clock : %x\n", mode->Clock); 1013172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Display : %x\n", mode->CrtcHDisplay); 1013272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Blank Start : %x\n", mode->CrtcHBlankStart); 1013372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Sync Start : %x\n", mode->CrtcHSyncStart); 1013472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Sync End : %x\n", mode->CrtcHSyncEnd); 1013572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Blank End : %x\n", mode->CrtcHBlankEnd); 1013672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Total : %x\n", mode->CrtcHTotal); 1013772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Skew : %x\n", mode->CrtcHSkew); 1013872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz HAdjusted : %x\n", mode->CrtcHAdjusted); 1013972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Display : %x\n", mode->CrtcVDisplay); 1014072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Blank Start : %x\n", mode->CrtcVBlankStart); 1014172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Sync Start : %x\n", mode->CrtcVSyncStart); 1014272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Sync End : %x\n", mode->CrtcVSyncEnd); 1014372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Blank End : %x\n", mode->CrtcVBlankEnd); 1014472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Total : %x\n", mode->CrtcVTotal); 1014572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt VAdjusted : %x\n", mode->CrtcVAdjusted); 1014672b676d7Smrg} 1014772b676d7Smrg#endif 1014872b676d7Smrg 1014972b676d7Smrgstatic void 1015072b676d7SmrgSISModifyModeInfo(DisplayModePtr mode) 1015172b676d7Smrg{ 1015272b676d7Smrg if(mode->CrtcHBlankStart == mode->CrtcHDisplay) 1015372b676d7Smrg mode->CrtcHBlankStart++; 1015472b676d7Smrg if(mode->CrtcHBlankEnd == mode->CrtcHTotal) 1015572b676d7Smrg mode->CrtcHBlankEnd--; 1015672b676d7Smrg if(mode->CrtcVBlankStart == mode->CrtcVDisplay) 1015772b676d7Smrg mode->CrtcVBlankStart++; 1015872b676d7Smrg if(mode->CrtcVBlankEnd == mode->CrtcVTotal) 1015972b676d7Smrg mode->CrtcVBlankEnd--; 1016072b676d7Smrg} 1016172b676d7Smrg 1016272b676d7Smrg/* Enable the Turboqueue/Commandqueue (For 300 and 315/330/340 series only) */ 1016372b676d7Smrgstatic void 1016472b676d7SmrgSiSEnableTurboQueue(ScrnInfoPtr pScrn) 1016572b676d7Smrg{ 1016672b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1016772b676d7Smrg UShort SR26, SR27; 1016872b676d7Smrg ULong temp; 1016972b676d7Smrg 1017072b676d7Smrg switch(pSiS->VGAEngine) { 1017172b676d7Smrg case SIS_300_VGA: 1017272b676d7Smrg if((!pSiS->NoAccel) && (pSiS->TurboQueue)) { 1017372b676d7Smrg /* TQ size is always 512k */ 1017472b676d7Smrg temp = (pScrn->videoRam/64) - 8; 1017572b676d7Smrg SR26 = temp & 0xFF; 1017672b676d7Smrg inSISIDXREG(SISSR, 0x27, SR27); 1017772b676d7Smrg SR27 &= 0xFC; 1017872b676d7Smrg SR27 |= (0xF0 | ((temp >> 8) & 3)); 1017972b676d7Smrg outSISIDXREG(SISSR, 0x26, SR26); 1018072b676d7Smrg outSISIDXREG(SISSR, 0x27, SR27); 1018172b676d7Smrg } 1018272b676d7Smrg break; 1018372b676d7Smrg 1018472b676d7Smrg case SIS_315_VGA: 1018572b676d7Smrg if(!pSiS->NoAccel) { 1018672b676d7Smrg /* On 315/330/340 series, there are three queue modes available 1018772b676d7Smrg * which are chosen by setting bits 7:5 in SR26: 1018872b676d7Smrg * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep 1018972b676d7Smrg * track of the queue, the FIFO, command parsing and so 1019072b676d7Smrg * on. This is the one comparable to the 300 series. 1019172b676d7Smrg * 2. VRAM queue mode (bit 6, 0x40). In this case, one will 1019272b676d7Smrg * have to do queue management himself. 1019372b676d7Smrg * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the 1019472b676d7Smrg * queue in AGP memory space. 1019572b676d7Smrg * We go VRAM or MMIO here. 1019672b676d7Smrg * SR26 bit 4 is called "Bypass H/W queue". 1019772b676d7Smrg * SR26 bit 1 is called "Enable Command Queue Auto Correction" 1019872b676d7Smrg * SR26 bit 0 resets the queue 1019972b676d7Smrg * Size of queue memory is encoded in bits 3:2 like this: 1020072b676d7Smrg * 00 (0x00) 512K 1020172b676d7Smrg * 01 (0x04) 1M 1020272b676d7Smrg * 10 (0x08) 2M 1020372b676d7Smrg * 11 (0x0C) 4M 1020472b676d7Smrg * The queue location is to be written to 0x85C0. 1020572b676d7Smrg */ 1020672b676d7Smrg#ifdef SISVRAMQ 1020772b676d7Smrg /* We use VRAM Cmd Queue, not MMIO or AGP */ 1020872b676d7Smrg UChar tempCR55 = 0; 1020972b676d7Smrg 1021072b676d7Smrg /* Set Command Queue Threshold to max value 11111b (?) */ 1021172b676d7Smrg outSISIDXREG(SISSR, 0x27, 0x1F); 1021272b676d7Smrg 1021372b676d7Smrg /* Disable queue flipping */ 1021472b676d7Smrg inSISIDXREG(SISCR, 0x55, tempCR55); 1021572b676d7Smrg andSISIDXREG(SISCR, 0x55, 0x33); 1021672b676d7Smrg /* Synchronous reset for Command Queue */ 1021772b676d7Smrg outSISIDXREG(SISSR, 0x26, 0x01); 1021872b676d7Smrg SIS_MMIO_OUT32(pSiS->IOBase, 0x85c4, 0); 1021972b676d7Smrg /* Enable VRAM Command Queue mode */ 1022072b676d7Smrg if(pSiS->ChipType == XGI_20) { 1022172b676d7Smrg /* On XGI_20, always 128K */ 1022272b676d7Smrg SR26 = 0x40 | 0x04 | 0x01; 1022372b676d7Smrg } else { 1022472b676d7Smrg switch(pSiS->cmdQueueSize) { 1022572b676d7Smrg case 1*1024*1024: SR26 = (0x40 | 0x04 | 0x01); break; 1022672b676d7Smrg case 2*1024*1024: SR26 = (0x40 | 0x08 | 0x01); break; 1022772b676d7Smrg case 4*1024*1024: SR26 = (0x40 | 0x0C | 0x01); break; 1022872b676d7Smrg default: 1022972b676d7Smrg pSiS->cmdQueueSize = 512 * 1024; 1023072b676d7Smrg case 512*1024: SR26 = (0x40 | 0x00 | 0x01); 1023172b676d7Smrg } 1023272b676d7Smrg } 1023372b676d7Smrg outSISIDXREG(SISSR, 0x26, SR26); 1023472b676d7Smrg SR26 &= 0xfe; 1023572b676d7Smrg outSISIDXREG(SISSR, 0x26, SR26); 1023672b676d7Smrg *(pSiS->cmdQ_SharedWritePort) = (unsigned int)(SIS_MMIO_IN32(pSiS->IOBase, 0x85c8)); 1023772b676d7Smrg SIS_MMIO_OUT32(pSiS->IOBase, 0x85c4, (CARD32)(*(pSiS->cmdQ_SharedWritePort))); 1023872b676d7Smrg SIS_MMIO_OUT32(pSiS->IOBase, 0x85C0, pSiS->cmdQueueOffset); 1023972b676d7Smrg temp = (ULong)pSiS->RealFbBase; 1024072b676d7Smrg#ifdef SISDUALHEAD 1024172b676d7Smrg if(pSiS->DualHeadMode) { 1024272b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1024372b676d7Smrg temp = (ULong)pSiSEnt->RealFbBase; 1024472b676d7Smrg } 1024572b676d7Smrg#endif 1024672b676d7Smrg temp += pSiS->cmdQueueOffset; 1024772b676d7Smrg pSiS->cmdQueueBase = (unsigned int *)temp; 1024872b676d7Smrg outSISIDXREG(SISCR, 0x55, tempCR55); 1024972b676d7Smrg#ifdef TWDEBUG 1025072b676d7Smrg xf86DrvMsg(0, 0, "CmdQueueOffs 0x%x, CmdQueueAdd %p, shwrp 0x%x, status %x, base %p\n", 1025172b676d7Smrg pSiS->cmdQueueOffset, pSiS->cmdQueueBase, *(pSiS->cmdQ_SharedWritePort), 1025272b676d7Smrg SIS_MMIO_IN32(pSiS->IOBase, 0x85cc), (ULong *)temp); 1025372b676d7Smrg#endif 1025472b676d7Smrg#else 1025572b676d7Smrg /* For MMIO */ 1025672b676d7Smrg /* Syncronous reset for Command Queue */ 1025772b676d7Smrg orSISIDXREG(SISSR, 0x26, 0x01); 1025872b676d7Smrg /* Set Command Queue Threshold to max value 11111b */ 1025972b676d7Smrg outSISIDXREG(SISSR, 0x27, 0x1F); 1026072b676d7Smrg /* Do some magic (cp readport to writeport) */ 1026172b676d7Smrg temp = SIS_MMIO_IN32(pSiS->IOBase, 0x85C8); 1026272b676d7Smrg SIS_MMIO_OUT32(pSiS->IOBase, 0x85C4, temp); 1026372b676d7Smrg /* Enable MMIO Command Queue mode (0x20), 1026472b676d7Smrg * Enable_command_queue_auto_correction (0x02) 1026572b676d7Smrg * (no idea, but sounds good, so use it) 1026672b676d7Smrg * 512k (0x00) (does this apply to MMIO mode?) */ 1026772b676d7Smrg outSISIDXREG(SISSR, 0x26, 0x22); 1026872b676d7Smrg /* Calc Command Queue position (Q is always 512k)*/ 1026972b676d7Smrg temp = (pScrn->videoRam - 512) * 1024; 1027072b676d7Smrg /* Set Q position */ 1027172b676d7Smrg SIS_MMIO_OUT32(pSiS->IOBase, 0x85C0, temp); 1027272b676d7Smrg#endif 1027372b676d7Smrg } 1027472b676d7Smrg break; 1027572b676d7Smrg default: 1027672b676d7Smrg break; 1027772b676d7Smrg } 1027872b676d7Smrg} 1027972b676d7Smrg 1028072b676d7Smrg#ifdef SISVRAMQ 1028172b676d7Smrgstatic void 1028272b676d7SmrgSiSRestoreQueueMode(SISPtr pSiS, SISRegPtr sisReg) 1028372b676d7Smrg{ 1028472b676d7Smrg UChar tempCR55=0; 1028572b676d7Smrg 1028672b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 1028772b676d7Smrg inSISIDXREG(SISCR,0x55,tempCR55); 1028872b676d7Smrg andSISIDXREG(SISCR,0x55,0x33); 1028972b676d7Smrg outSISIDXREG(SISSR,0x26,0x01); 1029072b676d7Smrg SIS_MMIO_OUT32(pSiS->IOBase, 0x85c4, 0); 1029172b676d7Smrg outSISIDXREG(SISSR,0x27,sisReg->sisRegs3C4[0x27]); 1029272b676d7Smrg outSISIDXREG(SISSR,0x26,sisReg->sisRegs3C4[0x26]); 1029372b676d7Smrg SIS_MMIO_OUT32(pSiS->IOBase, 0x85C0, sisReg->sisMMIO85C0); 1029472b676d7Smrg outSISIDXREG(SISCR,0x55,tempCR55); 1029572b676d7Smrg } 1029672b676d7Smrg} 1029772b676d7Smrg#endif 1029872b676d7Smrg 1029972b676d7Smrg/* Things to do before a ModeSwitch. We set up the 1030072b676d7Smrg * video bridge configuration and the TurboQueue. 1030172b676d7Smrg */ 1030272b676d7Smrgvoid SiSPreSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode, int viewmode) 1030372b676d7Smrg{ 1030472b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1030572b676d7Smrg UChar CR30, CR31, CR32, CR33; 1030672b676d7Smrg UChar CR39 = 0, CR3B = 0; 1030772b676d7Smrg UChar CR17, CR38 = 0; 1030872b676d7Smrg UChar CR35 = 0, CR79 = 0; 1030972b676d7Smrg int temp = 0, crt1rateindex = 0; 1031072b676d7Smrg ULong vbflag = pSiS->VBFlags; 1031172b676d7Smrg Bool hcm = pSiS->HaveCustomModes; 1031272b676d7Smrg DisplayModePtr mymode = mode; 1031372b676d7Smrg 1031472b676d7Smrg pSiS->IsCustom = FALSE; 1031572b676d7Smrg 1031672b676d7Smrg /* NEVER call this with viewmode = SIS_MODE_SIMU 1031772b676d7Smrg * if mode->type is not M_T_DEFAULT! 1031872b676d7Smrg */ 1031972b676d7Smrg 1032072b676d7Smrg#ifdef SISMERGED 1032172b676d7Smrg if(pSiS->MergedFB) { 1032272b676d7Smrg switch(viewmode) { 1032372b676d7Smrg case SIS_MODE_CRT1: 1032472b676d7Smrg mymode = ((SiSMergedDisplayModePtr)mode->Private)->CRT1; 1032572b676d7Smrg break; 1032672b676d7Smrg case SIS_MODE_CRT2: 1032772b676d7Smrg mymode = ((SiSMergedDisplayModePtr)mode->Private)->CRT2; 1032872b676d7Smrg hcm = pSiS->HaveCustomModes2; 1032972b676d7Smrg } 1033072b676d7Smrg } 1033172b676d7Smrg#endif 1033272b676d7Smrg 1033372b676d7Smrg switch(viewmode) { 1033472b676d7Smrg case SIS_MODE_CRT1: 1033572b676d7Smrg if(SiS_CheckModeCRT1(pScrn, mymode, vbflag, hcm) == 0xfe) { 1033672b676d7Smrg pSiS->IsCustom = TRUE; 1033772b676d7Smrg } 1033872b676d7Smrg break; 1033972b676d7Smrg case SIS_MODE_CRT2: 1034072b676d7Smrg if(vbflag & CRT2_ENABLE) { 1034172b676d7Smrg if(SiS_CheckModeCRT2(pScrn, mymode, vbflag, hcm) == 0xfe) { 1034272b676d7Smrg pSiS->IsCustom = TRUE; 1034372b676d7Smrg } 1034472b676d7Smrg } else { 1034572b676d7Smrg /* This can only happen in mirror mode */ 1034672b676d7Smrg if(SiS_CheckModeCRT1(pScrn, mymode, vbflag, hcm) == 0xfe) { 1034772b676d7Smrg pSiS->IsCustom = TRUE; 1034872b676d7Smrg } 1034972b676d7Smrg } 1035072b676d7Smrg } 1035172b676d7Smrg 1035272b676d7Smrg#ifdef UNLOCK_ALWAYS 1035372b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); /* Unlock Registers */ 1035472b676d7Smrg#endif 1035572b676d7Smrg 1035672b676d7Smrg inSISIDXREG(SISCR, 0x30, CR30); 1035772b676d7Smrg inSISIDXREG(SISCR, 0x31, CR31); 1035872b676d7Smrg CR32 = pSiS->newCR32; 1035972b676d7Smrg inSISIDXREG(SISCR, 0x33, CR33); 1036072b676d7Smrg 1036172b676d7Smrg if(pSiS->NewCRLayout) { 1036272b676d7Smrg 1036372b676d7Smrg inSISIDXREG(SISCR, 0x35, CR35); 1036472b676d7Smrg inSISIDXREG(SISCR, 0x38, CR38); 1036572b676d7Smrg inSISIDXREG(SISCR, 0x39, CR39); 1036672b676d7Smrg 1036772b676d7Smrg xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, SISVERBLEVEL, 1036872b676d7Smrg "Before: CR30=0x%02x,CR31=0x%02x,CR32=0x%02x,CR33=0x%02x,CR35=0x%02x,CR38=0x%02x\n", 1036972b676d7Smrg CR30, CR31, CR32, CR33, CR35, CR38); 1037072b676d7Smrg 1037172b676d7Smrg CR38 &= ~0x07; 1037272b676d7Smrg 1037372b676d7Smrg } else { 1037472b676d7Smrg 1037572b676d7Smrg if(pSiS->Chipset != PCI_CHIP_SIS300) { 1037672b676d7Smrg switch(pSiS->VGAEngine) { 1037772b676d7Smrg case SIS_300_VGA: temp = 0x35; break; 1037872b676d7Smrg case SIS_315_VGA: temp = 0x38; break; 1037972b676d7Smrg } 1038072b676d7Smrg if(temp) inSISIDXREG(SISCR, temp, CR38); 1038172b676d7Smrg } 1038272b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 1038372b676d7Smrg inSISIDXREG(SISCR, 0x79, CR79); 1038472b676d7Smrg CR38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */ 1038572b676d7Smrg } 1038672b676d7Smrg inSISIDXREG(SISCR, 0x3b, CR3B); 1038772b676d7Smrg 1038872b676d7Smrg xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, SISVERBLEVEL, 1038972b676d7Smrg "Before: CR30=0x%02x, CR31=0x%02x, CR32=0x%02x, CR33=0x%02x, CR%02x=0x%02x\n", 1039072b676d7Smrg CR30, CR31, CR32, CR33, temp, CR38); 1039172b676d7Smrg } 1039272b676d7Smrg 1039372b676d7Smrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, SISVERBLEVEL, "VBFlags=0x%x\n", pSiS->VBFlags); 1039472b676d7Smrg 1039572b676d7Smrg CR30 = 0x00; 1039672b676d7Smrg CR31 &= ~0x60; /* Clear VB_Drivermode & VB_OutputDisable */ 1039772b676d7Smrg CR31 |= 0x04; /* Set VB_NotSimuMode (not for 30xB/1400x1050?) */ 1039872b676d7Smrg CR35 = 0x00; 1039972b676d7Smrg 1040072b676d7Smrg if(!pSiS->NewCRLayout) { 1040172b676d7Smrg if(!pSiS->AllowHotkey) { 1040272b676d7Smrg CR31 |= 0x80; /* Disable hotkey-switch */ 1040372b676d7Smrg } 1040472b676d7Smrg CR79 &= ~0x10; /* Enable Backlight control on 315 series */ 1040572b676d7Smrg } 1040672b676d7Smrg 1040772b676d7Smrg SiS_SetEnableDstn(pSiS->SiS_Pr, FALSE); 1040872b676d7Smrg SiS_SetEnableFstn(pSiS->SiS_Pr, FALSE); 1040972b676d7Smrg 1041072b676d7Smrg if((vbflag & CRT1_LCDA) && (viewmode == SIS_MODE_CRT1)) { 1041172b676d7Smrg 1041272b676d7Smrg CR38 |= 0x02; 1041372b676d7Smrg 1041472b676d7Smrg } else { 1041572b676d7Smrg 1041672b676d7Smrg switch(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA)) { 1041772b676d7Smrg 1041872b676d7Smrg case CRT2_TV: 1041972b676d7Smrg 1042072b676d7Smrg CR38 &= ~0xC0; /* Clear Pal M/N bits */ 1042172b676d7Smrg 1042272b676d7Smrg if((pSiS->VBFlags2 & VB2_CHRONTEL) && (vbflag & TV_CHSCART)) { /* Chrontel */ 1042372b676d7Smrg CR30 |= 0x10; 1042472b676d7Smrg CR38 |= 0x04; 1042572b676d7Smrg CR38 &= ~0x08; 1042672b676d7Smrg CR31 |= 0x01; 1042772b676d7Smrg } else if((pSiS->VBFlags2 & VB2_CHRONTEL) && (vbflag & TV_CHYPBPR525I)) { /* Chrontel */ 1042872b676d7Smrg CR38 |= 0x08; 1042972b676d7Smrg CR38 &= ~0x04; 1043072b676d7Smrg CR31 &= ~0x01; 1043172b676d7Smrg } else if(vbflag & TV_HIVISION) { /* SiS bridge */ 1043272b676d7Smrg if(pSiS->NewCRLayout) { 1043372b676d7Smrg CR38 |= 0x04; 1043472b676d7Smrg CR35 |= 0x60; 1043572b676d7Smrg } else { 1043672b676d7Smrg CR30 |= 0x80; 1043772b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 1043872b676d7Smrg if(pSiS->VBFlags2 & VB2_SISYPBPRBRIDGE) { 1043972b676d7Smrg CR38 |= (0x08 | 0x30); 1044072b676d7Smrg } 1044172b676d7Smrg } 1044272b676d7Smrg } 1044372b676d7Smrg CR31 |= 0x01; 1044472b676d7Smrg CR35 |= 0x01; 1044572b676d7Smrg } else if(vbflag & TV_YPBPR) { /* SiS bridge */ 1044672b676d7Smrg if(pSiS->NewCRLayout) { 1044772b676d7Smrg CR38 |= 0x04; 1044872b676d7Smrg CR31 &= ~0x01; 1044972b676d7Smrg CR35 &= ~0x01; 1045072b676d7Smrg if(vbflag & (TV_YPBPR525P | TV_YPBPR625P)) CR35 |= 0x20; 1045172b676d7Smrg else if(vbflag & TV_YPBPR750P) CR35 |= 0x40; 1045272b676d7Smrg else if(vbflag & TV_YPBPR1080I) CR35 |= 0x60; 1045372b676d7Smrg 1045472b676d7Smrg if(vbflag & (TV_YPBPR625I | TV_YPBPR625P)) { 1045572b676d7Smrg CR31 |= 0x01; 1045672b676d7Smrg CR35 |= 0x01; 1045772b676d7Smrg } 1045872b676d7Smrg 1045972b676d7Smrg CR39 &= ~0x03; 1046072b676d7Smrg if((vbflag & TV_YPBPRAR) == TV_YPBPR43LB) CR39 |= 0x00; 1046172b676d7Smrg else if((vbflag & TV_YPBPRAR) == TV_YPBPR43) CR39 |= 0x01; 1046272b676d7Smrg else if((vbflag & TV_YPBPRAR) == TV_YPBPR169) CR39 |= 0x02; 1046372b676d7Smrg else CR39 |= 0x03; 1046472b676d7Smrg } else if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR) { 1046572b676d7Smrg CR30 |= 0x80; 1046672b676d7Smrg CR38 |= 0x08; 1046772b676d7Smrg CR31 &= ~0x01; 1046872b676d7Smrg if(vbflag & (TV_YPBPR525P|TV_YPBPR625P)) CR38 |= 0x10; 1046972b676d7Smrg else if(vbflag & TV_YPBPR750P) CR38 |= 0x20; 1047072b676d7Smrg else if(vbflag & TV_YPBPR1080I) CR38 |= 0x30; 1047172b676d7Smrg 1047272b676d7Smrg if(vbflag & (TV_YPBPR625I | TV_YPBPR625P)) CR31 |= 0x01; 1047372b676d7Smrg 1047472b676d7Smrg if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPRAR) { 1047572b676d7Smrg CR3B &= ~0x03; 1047672b676d7Smrg if((vbflag & TV_YPBPRAR) == TV_YPBPR43LB) CR3B |= 0x00; 1047772b676d7Smrg else if((vbflag & TV_YPBPRAR) == TV_YPBPR43) CR3B |= 0x03; 1047872b676d7Smrg else if((vbflag & TV_YPBPRAR) == TV_YPBPR169) CR3B |= 0x01; 1047972b676d7Smrg else CR3B |= 0x03; 1048072b676d7Smrg } 1048172b676d7Smrg } 1048272b676d7Smrg } else { /* All */ 1048372b676d7Smrg if(vbflag & TV_SCART) CR30 |= 0x10; 1048472b676d7Smrg if(vbflag & TV_SVIDEO) CR30 |= 0x08; 1048572b676d7Smrg if(vbflag & TV_AVIDEO) CR30 |= 0x04; 1048672b676d7Smrg if(!(CR30 & 0x1C)) CR30 |= 0x08; /* default: SVIDEO */ 1048772b676d7Smrg 1048872b676d7Smrg if(vbflag & TV_PAL) { 1048972b676d7Smrg CR31 |= 0x01; 1049072b676d7Smrg CR35 |= 0x01; 1049172b676d7Smrg if( (pSiS->VBFlags2 & VB2_SISBRIDGE) || 1049272b676d7Smrg ((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->ChrontelType == CHRONTEL_701x)) ) { 1049372b676d7Smrg if(vbflag & TV_PALM) { 1049472b676d7Smrg CR38 |= 0x40; 1049572b676d7Smrg CR35 |= 0x04; 1049672b676d7Smrg } else if(vbflag & TV_PALN) { 1049772b676d7Smrg CR38 |= 0x80; 1049872b676d7Smrg CR35 |= 0x08; 1049972b676d7Smrg } 1050072b676d7Smrg } 1050172b676d7Smrg } else { 1050272b676d7Smrg CR31 &= ~0x01; 1050372b676d7Smrg CR35 &= ~0x01; 1050472b676d7Smrg if(vbflag & TV_NTSCJ) { 1050572b676d7Smrg CR38 |= 0x40; /* TW, not BIOS */ 1050672b676d7Smrg CR35 |= 0x02; 1050772b676d7Smrg } 1050872b676d7Smrg } 1050972b676d7Smrg if(vbflag & TV_SCART) { 1051072b676d7Smrg CR31 |= 0x01; 1051172b676d7Smrg CR35 |= 0x01; 1051272b676d7Smrg } 1051372b676d7Smrg } 1051472b676d7Smrg 1051572b676d7Smrg CR31 &= ~0x04; /* Clear NotSimuMode */ 1051672b676d7Smrg pSiS->SiS_Pr->SiS_CHOverScan = pSiS->UseCHOverScan; 1051772b676d7Smrg if((pSiS->OptTVSOver == 1) && (pSiS->ChrontelType == CHRONTEL_700x)) { 1051872b676d7Smrg pSiS->SiS_Pr->SiS_CHSOverScan = TRUE; 1051972b676d7Smrg } else { 1052072b676d7Smrg pSiS->SiS_Pr->SiS_CHSOverScan = FALSE; 1052172b676d7Smrg } 1052272b676d7Smrg#ifdef SIS_CP 1052372b676d7Smrg SIS_CP_DRIVER_CONFIG 1052472b676d7Smrg#endif 1052572b676d7Smrg break; 1052672b676d7Smrg 1052772b676d7Smrg case CRT2_LCD: 1052872b676d7Smrg CR30 |= 0x20; 1052972b676d7Smrg SiS_SetEnableDstn(pSiS->SiS_Pr, pSiS->DSTN); 1053072b676d7Smrg SiS_SetEnableFstn(pSiS->SiS_Pr, pSiS->FSTN); 1053172b676d7Smrg break; 1053272b676d7Smrg 1053372b676d7Smrg case CRT2_VGA: 1053472b676d7Smrg CR30 |= 0x40; 1053572b676d7Smrg break; 1053672b676d7Smrg 1053772b676d7Smrg default: 1053872b676d7Smrg CR30 |= 0x00; 1053972b676d7Smrg CR31 |= 0x20; /* VB_OUTPUT_DISABLE */ 1054072b676d7Smrg if(pSiS->UseVESA) { 1054172b676d7Smrg crt1rateindex = SISSearchCRT1Rate(pScrn, mymode); 1054272b676d7Smrg } 1054372b676d7Smrg } 1054472b676d7Smrg 1054572b676d7Smrg } 1054672b676d7Smrg 1054772b676d7Smrg if(vbflag & CRT1_LCDA) { 1054872b676d7Smrg switch(viewmode) { 1054972b676d7Smrg case SIS_MODE_CRT1: 1055072b676d7Smrg CR38 |= 0x01; 1055172b676d7Smrg break; 1055272b676d7Smrg case SIS_MODE_CRT2: 1055372b676d7Smrg if(vbflag & (CRT2_TV|CRT2_VGA)) { 1055472b676d7Smrg CR30 |= 0x02; 1055572b676d7Smrg CR38 |= 0x01; 1055672b676d7Smrg } else { 1055772b676d7Smrg CR38 |= 0x03; 1055872b676d7Smrg } 1055972b676d7Smrg break; 1056072b676d7Smrg case SIS_MODE_SIMU: 1056172b676d7Smrg default: 1056272b676d7Smrg if(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA)) { 1056372b676d7Smrg CR30 |= 0x01; 1056472b676d7Smrg } 1056572b676d7Smrg break; 1056672b676d7Smrg } 1056772b676d7Smrg } else { 1056872b676d7Smrg if(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA)) { 1056972b676d7Smrg CR30 |= 0x01; 1057072b676d7Smrg } 1057172b676d7Smrg } 1057272b676d7Smrg 1057372b676d7Smrg if(pSiS->UseVESA) { 1057472b676d7Smrg CR31 &= ~0x40; /* Clear Drivermode */ 1057572b676d7Smrg CR31 |= 0x06; /* Set SlaveMode, Enable SimuMode in Slavemode */ 1057672b676d7Smrg#ifdef TWDEBUG 1057772b676d7Smrg CR31 |= 0x40; /* DEBUG (for non-slave mode VESA) */ 1057872b676d7Smrg crt1rateindex = SISSearchCRT1Rate(pScrn, mymode); 1057972b676d7Smrg#endif 1058072b676d7Smrg } else { 1058172b676d7Smrg CR31 |= 0x40; /* Set Drivermode */ 1058272b676d7Smrg CR31 &= ~0x06; /* Disable SlaveMode, disable SimuMode in SlaveMode */ 1058372b676d7Smrg if(!pSiS->IsCustom) { 1058472b676d7Smrg crt1rateindex = SISSearchCRT1Rate(pScrn, mymode); 1058572b676d7Smrg } 1058672b676d7Smrg } 1058772b676d7Smrg 1058872b676d7Smrg switch(viewmode) { 1058972b676d7Smrg case SIS_MODE_SIMU: 1059072b676d7Smrg CR33 = 0; 1059172b676d7Smrg if(!(vbflag & CRT1_LCDA)) { 1059272b676d7Smrg CR33 |= (crt1rateindex & 0x0f); 1059372b676d7Smrg } 1059472b676d7Smrg if(vbflag & CRT2_VGA) { 1059572b676d7Smrg CR33 |= ((crt1rateindex & 0x0f) << 4); 1059672b676d7Smrg } 1059772b676d7Smrg break; 1059872b676d7Smrg case SIS_MODE_CRT1: 1059972b676d7Smrg CR33 &= 0xf0; 1060072b676d7Smrg if(!(vbflag & CRT1_LCDA)) { 1060172b676d7Smrg CR33 |= (crt1rateindex & 0x0f); 1060272b676d7Smrg } 1060372b676d7Smrg break; 1060472b676d7Smrg case SIS_MODE_CRT2: 1060572b676d7Smrg CR33 &= 0x0f; 1060672b676d7Smrg if(vbflag & CRT2_VGA) { 1060772b676d7Smrg CR33 |= ((crt1rateindex & 0x0f) << 4); 1060872b676d7Smrg } 1060972b676d7Smrg break; 1061072b676d7Smrg } 1061172b676d7Smrg 1061272b676d7Smrg if((!pSiS->UseVESA) && (vbflag & CRT2_ENABLE)) { 1061372b676d7Smrg if(pSiS->CRT1off) CR33 &= 0xf0; 1061472b676d7Smrg } 1061572b676d7Smrg 1061672b676d7Smrg if(pSiS->NewCRLayout) { 1061772b676d7Smrg 1061872b676d7Smrg CR31 &= 0xfe; /* Clear PAL flag (now in CR35) */ 1061972b676d7Smrg CR38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */ 1062072b676d7Smrg outSISIDXREG(SISCR, 0x30, CR30); 1062172b676d7Smrg outSISIDXREG(SISCR, 0x31, CR31); 1062272b676d7Smrg outSISIDXREG(SISCR, 0x33, CR33); 1062372b676d7Smrg outSISIDXREG(SISCR, 0x35, CR35); 1062472b676d7Smrg setSISIDXREG(SISCR, 0x38, 0xf8, CR38); 1062572b676d7Smrg outSISIDXREG(SISCR, 0x39, CR39); 1062672b676d7Smrg 1062772b676d7Smrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, SISVERBLEVEL, 1062872b676d7Smrg "After: CR30=0x%02x,CR31=0x%02x,CR33=0x%02x,CR35=0x%02x,CR38=%02x\n", 1062972b676d7Smrg CR30, CR31, CR33, CR35, CR38); 1063072b676d7Smrg 1063172b676d7Smrg } else { 1063272b676d7Smrg 1063372b676d7Smrg outSISIDXREG(SISCR, 0x30, CR30); 1063472b676d7Smrg outSISIDXREG(SISCR, 0x31, CR31); 1063572b676d7Smrg outSISIDXREG(SISCR, 0x33, CR33); 1063672b676d7Smrg if(temp) { 1063772b676d7Smrg outSISIDXREG(SISCR, temp, CR38); 1063872b676d7Smrg } 1063972b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 1064072b676d7Smrg outSISIDXREG(SISCR, 0x3b, CR3B); 1064172b676d7Smrg outSISIDXREG(SISCR, 0x79, CR79); 1064272b676d7Smrg } 1064372b676d7Smrg 1064472b676d7Smrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, SISVERBLEVEL, 1064572b676d7Smrg "After: CR30=0x%02x,CR31=0x%02x,CR33=0x%02x,CR%02x=%02x\n", 1064672b676d7Smrg CR30, CR31, CR33, temp, CR38); 1064772b676d7Smrg } 1064872b676d7Smrg 1064972b676d7Smrg pSiS->SiS_Pr->SiS_UseOEM = pSiS->OptUseOEM; 1065072b676d7Smrg 1065172b676d7Smrg /* Enable TurboQueue */ 1065272b676d7Smrg#ifdef SISVRAMQ 1065372b676d7Smrg if(pSiS->VGAEngine != SIS_315_VGA) 1065472b676d7Smrg#endif 1065572b676d7Smrg SiSEnableTurboQueue(pScrn); 1065672b676d7Smrg 1065772b676d7Smrg if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE)) { 1065872b676d7Smrg /* Switch on CRT1 for modes that require the bridge in SlaveMode */ 1065972b676d7Smrg andSISIDXREG(SISSR,0x1f,0x3f); 1066072b676d7Smrg inSISIDXREG(SISCR, 0x17, CR17); 1066172b676d7Smrg if(!(CR17 & 0x80)) { 1066272b676d7Smrg orSISIDXREG(SISCR, 0x17, 0x80); 1066372b676d7Smrg outSISIDXREG(SISSR, 0x00, 0x01); 1066472b676d7Smrg usleep(10000); 1066572b676d7Smrg outSISIDXREG(SISSR, 0x00, 0x03); 1066672b676d7Smrg } 1066772b676d7Smrg } 1066872b676d7Smrg} 1066972b676d7Smrg 1067072b676d7Smrg/* Functions for adjusting various TV settings */ 1067172b676d7Smrg 1067272b676d7Smrg/* These are used by the PostSetMode() functions as well as 1067372b676d7Smrg * the display properties tool SiSCtrl. 1067472b676d7Smrg * 1067572b676d7Smrg * There is each a Set and a Get routine. The Set functions 1067672b676d7Smrg * take a value of the same range as the corresponding option. 1067772b676d7Smrg * The Get routines return a value of the same range (although 1067872b676d7Smrg * not necessarily the same value as previously set because 1067972b676d7Smrg * of the lower resolution of the respective setting compared 1068072b676d7Smrg * to the valid range). 1068172b676d7Smrg * The Get routines return -2 on error (eg. hardware does not 1068272b676d7Smrg * support this setting). 1068372b676d7Smrg * Note: The x and y positioning routines accept a position 1068472b676d7Smrg * RELATIVE to the default position. All other routines 1068572b676d7Smrg * take ABSOLUTE values. 1068672b676d7Smrg * 1068772b676d7Smrg * The Set functions will store the property regardless if TV is 1068872b676d7Smrg * currently used or not and if the hardware supports the property 1068972b676d7Smrg * or not. The Get routines will return this stored 1069072b676d7Smrg * value if TV is not currently used (because the register does 1069172b676d7Smrg * not contain the correct value then) or if the hardware supports 1069272b676d7Smrg * the respective property. This should make it easier for the 1069372b676d7Smrg * display property tool because it does not have to know the 1069472b676d7Smrg * hardware features. 1069572b676d7Smrg * 1069672b676d7Smrg * All the routines are dual head aware. It does not matter 1069772b676d7Smrg * if the function is called from the CRT1 or CRT2 session. 1069872b676d7Smrg * The values will be in pSiSEnt anyway, and read from there 1069972b676d7Smrg * if we're running dual head. 1070072b676d7Smrg */ 1070172b676d7Smrg 1070272b676d7Smrgvoid SiS_SetCHTVlumabandwidthcvbs(ScrnInfoPtr pScrn, int val) 1070372b676d7Smrg{ 1070472b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1070572b676d7Smrg#ifdef SISDUALHEAD 1070672b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1070772b676d7Smrg#endif 1070872b676d7Smrg 1070972b676d7Smrg pSiS->chtvlumabandwidthcvbs = val; 1071072b676d7Smrg#ifdef SISDUALHEAD 1071172b676d7Smrg if(pSiSEnt) pSiSEnt->chtvlumabandwidthcvbs = val; 1071272b676d7Smrg#endif 1071372b676d7Smrg 1071472b676d7Smrg if(!(pSiS->VBFlags & CRT2_TV)) return; 1071572b676d7Smrg if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 1071672b676d7Smrg 1071772b676d7Smrg#ifdef UNLOCK_ALWAYS 1071872b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1071972b676d7Smrg#endif 1072072b676d7Smrg 1072172b676d7Smrg switch(pSiS->ChrontelType) { 1072272b676d7Smrg case CHRONTEL_700x: 1072372b676d7Smrg val /= 8; 1072472b676d7Smrg if((val == 0) || (val == 1)) { 1072572b676d7Smrg SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, val, 0xFE); 1072672b676d7Smrg } 1072772b676d7Smrg break; 1072872b676d7Smrg case CHRONTEL_701x: 1072972b676d7Smrg val /= 4; 1073072b676d7Smrg if((val >= 0) && (val <= 3)) { 1073172b676d7Smrg SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, val, 0xFC); 1073272b676d7Smrg } 1073372b676d7Smrg break; 1073472b676d7Smrg } 1073572b676d7Smrg} 1073672b676d7Smrg 1073772b676d7Smrgint SiS_GetCHTVlumabandwidthcvbs(ScrnInfoPtr pScrn) 1073872b676d7Smrg{ 1073972b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1074072b676d7Smrg#ifdef SISDUALHEAD 1074172b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1074272b676d7Smrg#endif 1074372b676d7Smrg 1074472b676d7Smrg if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 1074572b676d7Smrg#ifdef SISDUALHEAD 1074672b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) 1074772b676d7Smrg return (int)pSiSEnt->chtvlumabandwidthcvbs; 1074872b676d7Smrg else 1074972b676d7Smrg#endif 1075072b676d7Smrg return (int)pSiS->chtvlumabandwidthcvbs; 1075172b676d7Smrg } else { 1075272b676d7Smrg#ifdef UNLOCK_ALWAYS 1075372b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1075472b676d7Smrg#endif 1075572b676d7Smrg switch(pSiS->ChrontelType) { 1075672b676d7Smrg case CHRONTEL_700x: 1075772b676d7Smrg return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x01) * 8); 1075872b676d7Smrg case CHRONTEL_701x: 1075972b676d7Smrg return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x03) * 4); 1076072b676d7Smrg default: 1076172b676d7Smrg return (int)pSiS->chtvlumabandwidthcvbs; 1076272b676d7Smrg } 1076372b676d7Smrg } 1076472b676d7Smrg} 1076572b676d7Smrg 1076672b676d7Smrgvoid SiS_SetCHTVlumabandwidthsvideo(ScrnInfoPtr pScrn, int val) 1076772b676d7Smrg{ 1076872b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1076972b676d7Smrg#ifdef SISDUALHEAD 1077072b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1077172b676d7Smrg#endif 1077272b676d7Smrg 1077372b676d7Smrg pSiS->chtvlumabandwidthsvideo = val; 1077472b676d7Smrg#ifdef SISDUALHEAD 1077572b676d7Smrg if(pSiSEnt) pSiSEnt->chtvlumabandwidthsvideo = val; 1077672b676d7Smrg#endif 1077772b676d7Smrg 1077872b676d7Smrg if(!(pSiS->VBFlags & CRT2_TV)) return; 1077972b676d7Smrg if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 1078072b676d7Smrg 1078172b676d7Smrg#ifdef UNLOCK_ALWAYS 1078272b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1078372b676d7Smrg#endif 1078472b676d7Smrg 1078572b676d7Smrg switch(pSiS->ChrontelType) { 1078672b676d7Smrg case CHRONTEL_700x: 1078772b676d7Smrg val /= 6; 1078872b676d7Smrg if((val >= 0) && (val <= 2)) { 1078972b676d7Smrg SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, (val << 1), 0xF9); 1079072b676d7Smrg } 1079172b676d7Smrg break; 1079272b676d7Smrg case CHRONTEL_701x: 1079372b676d7Smrg val /= 4; 1079472b676d7Smrg if((val >= 0) && (val <= 3)) { 1079572b676d7Smrg SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, (val << 2), 0xF3); 1079672b676d7Smrg } 1079772b676d7Smrg break; 1079872b676d7Smrg } 1079972b676d7Smrg} 1080072b676d7Smrg 1080172b676d7Smrgint SiS_GetCHTVlumabandwidthsvideo(ScrnInfoPtr pScrn) 1080272b676d7Smrg{ 1080372b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1080472b676d7Smrg#ifdef SISDUALHEAD 1080572b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1080672b676d7Smrg#endif 1080772b676d7Smrg 1080872b676d7Smrg if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 1080972b676d7Smrg#ifdef SISDUALHEAD 1081072b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) 1081172b676d7Smrg return (int)pSiSEnt->chtvlumabandwidthsvideo; 1081272b676d7Smrg else 1081372b676d7Smrg#endif 1081472b676d7Smrg return (int)pSiS->chtvlumabandwidthsvideo; 1081572b676d7Smrg } else { 1081672b676d7Smrg#ifdef UNLOCK_ALWAYS 1081772b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1081872b676d7Smrg#endif 1081972b676d7Smrg switch(pSiS->ChrontelType) { 1082072b676d7Smrg case CHRONTEL_700x: 1082172b676d7Smrg return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x06) >> 1) * 6); 1082272b676d7Smrg case CHRONTEL_701x: 1082372b676d7Smrg return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x0c) >> 2) * 4); 1082472b676d7Smrg default: 1082572b676d7Smrg return (int)pSiS->chtvlumabandwidthsvideo; 1082672b676d7Smrg } 1082772b676d7Smrg } 1082872b676d7Smrg} 1082972b676d7Smrg 1083072b676d7Smrgvoid SiS_SetCHTVlumaflickerfilter(ScrnInfoPtr pScrn, int val) 1083172b676d7Smrg{ 1083272b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1083372b676d7Smrg#ifdef SISDUALHEAD 1083472b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1083572b676d7Smrg#endif 1083672b676d7Smrg 1083772b676d7Smrg pSiS->chtvlumaflickerfilter = val; 1083872b676d7Smrg#ifdef SISDUALHEAD 1083972b676d7Smrg if(pSiSEnt) pSiSEnt->chtvlumaflickerfilter = val; 1084072b676d7Smrg#endif 1084172b676d7Smrg 1084272b676d7Smrg if(!(pSiS->VBFlags & CRT2_TV)) return; 1084372b676d7Smrg if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 1084472b676d7Smrg 1084572b676d7Smrg#ifdef UNLOCK_ALWAYS 1084672b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1084772b676d7Smrg#endif 1084872b676d7Smrg 1084972b676d7Smrg switch(pSiS->ChrontelType) { 1085072b676d7Smrg case CHRONTEL_700x: 1085172b676d7Smrg val /= 6; 1085272b676d7Smrg if((val >= 0) && (val <= 2)) { 1085372b676d7Smrg UShort reg = 0; 1085472b676d7Smrg reg = SiS_GetCH70xx(pSiS->SiS_Pr, 0x01); 1085572b676d7Smrg reg = (reg & 0xf0) | ((reg & 0x0c) >> 2) | (val << 2); 1085672b676d7Smrg SiS_SetCH70xx(pSiS->SiS_Pr, 0x01, reg); 1085772b676d7Smrg } 1085872b676d7Smrg break; 1085972b676d7Smrg case CHRONTEL_701x: 1086072b676d7Smrg val /= 4; 1086172b676d7Smrg if((val >= 0) && (val <= 3)) { 1086272b676d7Smrg SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x01, (val << 2), 0xF3); 1086372b676d7Smrg } 1086472b676d7Smrg break; 1086572b676d7Smrg } 1086672b676d7Smrg} 1086772b676d7Smrg 1086872b676d7Smrgint SiS_GetCHTVlumaflickerfilter(ScrnInfoPtr pScrn) 1086972b676d7Smrg{ 1087072b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1087172b676d7Smrg#ifdef SISDUALHEAD 1087272b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1087372b676d7Smrg#endif 1087472b676d7Smrg 1087572b676d7Smrg if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 1087672b676d7Smrg#ifdef SISDUALHEAD 1087772b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) 1087872b676d7Smrg return (int)pSiSEnt->chtvlumaflickerfilter; 1087972b676d7Smrg else 1088072b676d7Smrg#endif 1088172b676d7Smrg return (int)pSiS->chtvlumaflickerfilter; 1088272b676d7Smrg } else { 1088372b676d7Smrg#ifdef UNLOCK_ALWAYS 1088472b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1088572b676d7Smrg#endif 1088672b676d7Smrg switch(pSiS->ChrontelType) { 1088772b676d7Smrg case CHRONTEL_700x: 1088872b676d7Smrg return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x03) * 6); 1088972b676d7Smrg case CHRONTEL_701x: 1089072b676d7Smrg return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x0c) >> 2) * 4); 1089172b676d7Smrg default: 1089272b676d7Smrg return (int)pSiS->chtvlumaflickerfilter; 1089372b676d7Smrg } 1089472b676d7Smrg } 1089572b676d7Smrg} 1089672b676d7Smrg 1089772b676d7Smrgvoid SiS_SetCHTVchromabandwidth(ScrnInfoPtr pScrn, int val) 1089872b676d7Smrg{ 1089972b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1090072b676d7Smrg#ifdef SISDUALHEAD 1090172b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1090272b676d7Smrg#endif 1090372b676d7Smrg 1090472b676d7Smrg pSiS->chtvchromabandwidth = val; 1090572b676d7Smrg#ifdef SISDUALHEAD 1090672b676d7Smrg if(pSiSEnt) pSiSEnt->chtvchromabandwidth = val; 1090772b676d7Smrg#endif 1090872b676d7Smrg 1090972b676d7Smrg if(!(pSiS->VBFlags & CRT2_TV)) return; 1091072b676d7Smrg if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 1091172b676d7Smrg 1091272b676d7Smrg#ifdef UNLOCK_ALWAYS 1091372b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1091472b676d7Smrg#endif 1091572b676d7Smrg 1091672b676d7Smrg switch(pSiS->ChrontelType) { 1091772b676d7Smrg case CHRONTEL_700x: 1091872b676d7Smrg val /= 4; 1091972b676d7Smrg if((val >= 0) && (val <= 3)) { 1092072b676d7Smrg SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, (val << 4), 0xCF); 1092172b676d7Smrg } 1092272b676d7Smrg break; 1092372b676d7Smrg case CHRONTEL_701x: 1092472b676d7Smrg val /= 8; 1092572b676d7Smrg if((val >= 0) && (val <= 1)) { 1092672b676d7Smrg SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, (val << 4), 0xEF); 1092772b676d7Smrg } 1092872b676d7Smrg break; 1092972b676d7Smrg } 1093072b676d7Smrg} 1093172b676d7Smrg 1093272b676d7Smrgint SiS_GetCHTVchromabandwidth(ScrnInfoPtr pScrn) 1093372b676d7Smrg{ 1093472b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1093572b676d7Smrg#ifdef SISDUALHEAD 1093672b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1093772b676d7Smrg#endif 1093872b676d7Smrg 1093972b676d7Smrg if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 1094072b676d7Smrg#ifdef SISDUALHEAD 1094172b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) 1094272b676d7Smrg return (int)pSiSEnt->chtvchromabandwidth; 1094372b676d7Smrg else 1094472b676d7Smrg#endif 1094572b676d7Smrg return (int)pSiS->chtvchromabandwidth; 1094672b676d7Smrg } else { 1094772b676d7Smrg#ifdef UNLOCK_ALWAYS 1094872b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1094972b676d7Smrg#endif 1095072b676d7Smrg switch(pSiS->ChrontelType) { 1095172b676d7Smrg case CHRONTEL_700x: 1095272b676d7Smrg return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x30) >> 4) * 4); 1095372b676d7Smrg case CHRONTEL_701x: 1095472b676d7Smrg return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x10) >> 4) * 8); 1095572b676d7Smrg default: 1095672b676d7Smrg return (int)pSiS->chtvchromabandwidth; 1095772b676d7Smrg } 1095872b676d7Smrg } 1095972b676d7Smrg} 1096072b676d7Smrg 1096172b676d7Smrgvoid SiS_SetCHTVchromaflickerfilter(ScrnInfoPtr pScrn, int val) 1096272b676d7Smrg{ 1096372b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1096472b676d7Smrg#ifdef SISDUALHEAD 1096572b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1096672b676d7Smrg#endif 1096772b676d7Smrg 1096872b676d7Smrg pSiS->chtvchromaflickerfilter = val; 1096972b676d7Smrg#ifdef SISDUALHEAD 1097072b676d7Smrg if(pSiSEnt) pSiSEnt->chtvchromaflickerfilter = val; 1097172b676d7Smrg#endif 1097272b676d7Smrg 1097372b676d7Smrg if(!(pSiS->VBFlags & CRT2_TV)) return; 1097472b676d7Smrg if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 1097572b676d7Smrg 1097672b676d7Smrg#ifdef UNLOCK_ALWAYS 1097772b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1097872b676d7Smrg#endif 1097972b676d7Smrg 1098072b676d7Smrg switch(pSiS->ChrontelType) { 1098172b676d7Smrg case CHRONTEL_700x: 1098272b676d7Smrg val /= 6; 1098372b676d7Smrg if((val >= 0) && (val <= 2)) { 1098472b676d7Smrg UShort reg = 0; 1098572b676d7Smrg reg = SiS_GetCH70xx(pSiS->SiS_Pr, 0x01); 1098672b676d7Smrg reg = (reg & 0xc0) | ((reg & 0x0c) >> 2) | ((reg & 0x03) << 2) | (val << 4); 1098772b676d7Smrg SiS_SetCH70xx(pSiS->SiS_Pr, 0x01, reg); 1098872b676d7Smrg } 1098972b676d7Smrg break; 1099072b676d7Smrg case CHRONTEL_701x: 1099172b676d7Smrg val /= 4; 1099272b676d7Smrg if((val >= 0) && (val <= 3)) { 1099372b676d7Smrg SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x01, (val << 4), 0xCF); 1099472b676d7Smrg } 1099572b676d7Smrg break; 1099672b676d7Smrg } 1099772b676d7Smrg} 1099872b676d7Smrg 1099972b676d7Smrgint SiS_GetCHTVchromaflickerfilter(ScrnInfoPtr pScrn) 1100072b676d7Smrg{ 1100172b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1100272b676d7Smrg#ifdef SISDUALHEAD 1100372b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1100472b676d7Smrg#endif 1100572b676d7Smrg 1100672b676d7Smrg if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 1100772b676d7Smrg#ifdef SISDUALHEAD 1100872b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) 1100972b676d7Smrg return (int)pSiSEnt->chtvchromaflickerfilter; 1101072b676d7Smrg else 1101172b676d7Smrg#endif 1101272b676d7Smrg return (int)pSiS->chtvchromaflickerfilter; 1101372b676d7Smrg } else { 1101472b676d7Smrg#ifdef UNLOCK_ALWAYS 1101572b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1101672b676d7Smrg#endif 1101772b676d7Smrg switch(pSiS->ChrontelType) { 1101872b676d7Smrg case CHRONTEL_700x: 1101972b676d7Smrg return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x30) >> 4) * 6); 1102072b676d7Smrg case CHRONTEL_701x: 1102172b676d7Smrg return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x30) >> 4) * 4); 1102272b676d7Smrg default: 1102372b676d7Smrg return (int)pSiS->chtvchromaflickerfilter; 1102472b676d7Smrg } 1102572b676d7Smrg } 1102672b676d7Smrg} 1102772b676d7Smrg 1102872b676d7Smrgvoid SiS_SetCHTVcvbscolor(ScrnInfoPtr pScrn, int val) 1102972b676d7Smrg{ 1103072b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1103172b676d7Smrg#ifdef SISDUALHEAD 1103272b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1103372b676d7Smrg#endif 1103472b676d7Smrg 1103572b676d7Smrg pSiS->chtvcvbscolor = val ? 1 : 0; 1103672b676d7Smrg#ifdef SISDUALHEAD 1103772b676d7Smrg if(pSiSEnt) pSiSEnt->chtvcvbscolor = pSiS->chtvcvbscolor; 1103872b676d7Smrg#endif 1103972b676d7Smrg 1104072b676d7Smrg if(!(pSiS->VBFlags & CRT2_TV)) return; 1104172b676d7Smrg if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 1104272b676d7Smrg 1104372b676d7Smrg#ifdef UNLOCK_ALWAYS 1104472b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1104572b676d7Smrg#endif 1104672b676d7Smrg 1104772b676d7Smrg switch(pSiS->ChrontelType) { 1104872b676d7Smrg case CHRONTEL_700x: 1104972b676d7Smrg if(!val) SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, 0x40, 0x00); 1105072b676d7Smrg else SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, 0x00, ~0x40); 1105172b676d7Smrg break; 1105272b676d7Smrg case CHRONTEL_701x: 1105372b676d7Smrg if(!val) SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, 0x00, ~0x20); 1105472b676d7Smrg else SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x02, 0x20, 0x00); 1105572b676d7Smrg break; 1105672b676d7Smrg } 1105772b676d7Smrg} 1105872b676d7Smrg 1105972b676d7Smrgint SiS_GetCHTVcvbscolor(ScrnInfoPtr pScrn) 1106072b676d7Smrg{ 1106172b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1106272b676d7Smrg#ifdef SISDUALHEAD 1106372b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1106472b676d7Smrg#endif 1106572b676d7Smrg 1106672b676d7Smrg if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 1106772b676d7Smrg#ifdef SISDUALHEAD 1106872b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) 1106972b676d7Smrg return (int)pSiSEnt->chtvcvbscolor; 1107072b676d7Smrg else 1107172b676d7Smrg#endif 1107272b676d7Smrg return (int)pSiS->chtvcvbscolor; 1107372b676d7Smrg } else { 1107472b676d7Smrg#ifdef UNLOCK_ALWAYS 1107572b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1107672b676d7Smrg#endif 1107772b676d7Smrg switch(pSiS->ChrontelType) { 1107872b676d7Smrg case CHRONTEL_700x: 1107972b676d7Smrg return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x40) >> 6) ^ 0x01); 1108072b676d7Smrg case CHRONTEL_701x: 1108172b676d7Smrg return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x20) >> 5) ^ 0x01); 1108272b676d7Smrg default: 1108372b676d7Smrg return (int)pSiS->chtvcvbscolor; 1108472b676d7Smrg } 1108572b676d7Smrg } 1108672b676d7Smrg} 1108772b676d7Smrg 1108872b676d7Smrgvoid SiS_SetCHTVtextenhance(ScrnInfoPtr pScrn, int val) 1108972b676d7Smrg{ 1109072b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1109172b676d7Smrg#ifdef SISDUALHEAD 1109272b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1109372b676d7Smrg#endif 1109472b676d7Smrg 1109572b676d7Smrg pSiS->chtvtextenhance = val; 1109672b676d7Smrg#ifdef SISDUALHEAD 1109772b676d7Smrg if(pSiSEnt) pSiSEnt->chtvtextenhance = val; 1109872b676d7Smrg#endif 1109972b676d7Smrg 1110072b676d7Smrg if(!(pSiS->VBFlags & CRT2_TV)) return; 1110172b676d7Smrg if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 1110272b676d7Smrg 1110372b676d7Smrg#ifdef UNLOCK_ALWAYS 1110472b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1110572b676d7Smrg#endif 1110672b676d7Smrg 1110772b676d7Smrg switch(pSiS->ChrontelType) { 1110872b676d7Smrg case CHRONTEL_700x: 1110972b676d7Smrg val /= 6; 1111072b676d7Smrg if((val >= 0) && (val <= 2)) { 1111172b676d7Smrg UShort reg = 0; 1111272b676d7Smrg reg = SiS_GetCH70xx(pSiS->SiS_Pr, 0x01); 1111372b676d7Smrg reg = (reg & 0xf0) | ((reg & 0x03) << 2) | val; 1111472b676d7Smrg SiS_SetCH70xx(pSiS->SiS_Pr, 0x01, reg); 1111572b676d7Smrg } 1111672b676d7Smrg break; 1111772b676d7Smrg case CHRONTEL_701x: 1111872b676d7Smrg val /= 2; 1111972b676d7Smrg if((val >= 0) && (val <= 7)) { 1112072b676d7Smrg SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x03, val, 0xF8); 1112172b676d7Smrg } 1112272b676d7Smrg break; 1112372b676d7Smrg } 1112472b676d7Smrg} 1112572b676d7Smrg 1112672b676d7Smrgint SiS_GetCHTVtextenhance(ScrnInfoPtr pScrn) 1112772b676d7Smrg{ 1112872b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1112972b676d7Smrg#ifdef SISDUALHEAD 1113072b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1113172b676d7Smrg#endif 1113272b676d7Smrg 1113372b676d7Smrg if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 1113472b676d7Smrg#ifdef SISDUALHEAD 1113572b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) 1113672b676d7Smrg return (int)pSiSEnt->chtvtextenhance; 1113772b676d7Smrg else 1113872b676d7Smrg#endif 1113972b676d7Smrg return (int)pSiS->chtvtextenhance; 1114072b676d7Smrg } else { 1114172b676d7Smrg#ifdef UNLOCK_ALWAYS 1114272b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1114372b676d7Smrg#endif 1114472b676d7Smrg switch(pSiS->ChrontelType) { 1114572b676d7Smrg case CHRONTEL_700x: 1114672b676d7Smrg return (int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x0c) >> 2) * 6); 1114772b676d7Smrg case CHRONTEL_701x: 1114872b676d7Smrg return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x07) * 2); 1114972b676d7Smrg default: 1115072b676d7Smrg return (int)pSiS->chtvtextenhance; 1115172b676d7Smrg } 1115272b676d7Smrg } 1115372b676d7Smrg} 1115472b676d7Smrg 1115572b676d7Smrgvoid SiS_SetCHTVcontrast(ScrnInfoPtr pScrn, int val) 1115672b676d7Smrg{ 1115772b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1115872b676d7Smrg#ifdef SISDUALHEAD 1115972b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1116072b676d7Smrg#endif 1116172b676d7Smrg 1116272b676d7Smrg pSiS->chtvcontrast = val; 1116372b676d7Smrg#ifdef SISDUALHEAD 1116472b676d7Smrg if(pSiSEnt) pSiSEnt->chtvcontrast = val; 1116572b676d7Smrg#endif 1116672b676d7Smrg 1116772b676d7Smrg if(!(pSiS->VBFlags & CRT2_TV)) return; 1116872b676d7Smrg if(!(pSiS->VBFlags2 & VB2_CHRONTEL)) return; 1116972b676d7Smrg 1117072b676d7Smrg#ifdef UNLOCK_ALWAYS 1117172b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1117272b676d7Smrg#endif 1117372b676d7Smrg 1117472b676d7Smrg val /= 2; 1117572b676d7Smrg if((val >= 0) && (val <= 7)) { 1117672b676d7Smrg switch(pSiS->ChrontelType) { 1117772b676d7Smrg case CHRONTEL_700x: 1117872b676d7Smrg SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x11, val, 0xF8); 1117972b676d7Smrg break; 1118072b676d7Smrg case CHRONTEL_701x: 1118172b676d7Smrg SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x08, val, 0xF8); 1118272b676d7Smrg break; 1118372b676d7Smrg } 1118472b676d7Smrg SiS_DDC2Delay(pSiS->SiS_Pr, 1000); 1118572b676d7Smrg } 1118672b676d7Smrg} 1118772b676d7Smrg 1118872b676d7Smrgint SiS_GetCHTVcontrast(ScrnInfoPtr pScrn) 1118972b676d7Smrg{ 1119072b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1119172b676d7Smrg#ifdef SISDUALHEAD 1119272b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1119372b676d7Smrg#endif 1119472b676d7Smrg 1119572b676d7Smrg if(!((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & CRT2_TV))) { 1119672b676d7Smrg#ifdef SISDUALHEAD 1119772b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) 1119872b676d7Smrg return (int)pSiSEnt->chtvcontrast; 1119972b676d7Smrg else 1120072b676d7Smrg#endif 1120172b676d7Smrg return (int)pSiS->chtvcontrast; 1120272b676d7Smrg } else { 1120372b676d7Smrg#ifdef UNLOCK_ALWAYS 1120472b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1120572b676d7Smrg#endif 1120672b676d7Smrg switch(pSiS->ChrontelType) { 1120772b676d7Smrg case CHRONTEL_700x: 1120872b676d7Smrg return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x11) & 0x07) * 2); 1120972b676d7Smrg case CHRONTEL_701x: 1121072b676d7Smrg return (int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x08) & 0x07) * 2); 1121172b676d7Smrg default: 1121272b676d7Smrg return (int)pSiS->chtvcontrast; 1121372b676d7Smrg } 1121472b676d7Smrg } 1121572b676d7Smrg} 1121672b676d7Smrg 1121772b676d7Smrgvoid SiS_SetSISTVedgeenhance(ScrnInfoPtr pScrn, int val) 1121872b676d7Smrg{ 1121972b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1122072b676d7Smrg#ifdef SISDUALHEAD 1122172b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1122272b676d7Smrg#endif 1122372b676d7Smrg 1122472b676d7Smrg pSiS->sistvedgeenhance = val; 1122572b676d7Smrg#ifdef SISDUALHEAD 1122672b676d7Smrg if(pSiSEnt) pSiSEnt->sistvedgeenhance = val; 1122772b676d7Smrg#endif 1122872b676d7Smrg 1122972b676d7Smrg if(!(pSiS->VBFlags2 & VB2_301)) return; 1123072b676d7Smrg if(!(pSiS->VBFlags & CRT2_TV)) return; 1123172b676d7Smrg 1123272b676d7Smrg#ifdef UNLOCK_ALWAYS 1123372b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1123472b676d7Smrg#endif 1123572b676d7Smrg 1123672b676d7Smrg val /= 2; 1123772b676d7Smrg if((val >= 0) && (val <= 7)) { 1123872b676d7Smrg setSISIDXREG(SISPART2,0x3A, 0x1F, (val << 5)); 1123972b676d7Smrg } 1124072b676d7Smrg} 1124172b676d7Smrg 1124272b676d7Smrgint SiS_GetSISTVedgeenhance(ScrnInfoPtr pScrn) 1124372b676d7Smrg{ 1124472b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1124572b676d7Smrg int result = pSiS->sistvedgeenhance; 1124672b676d7Smrg UChar temp; 1124772b676d7Smrg#ifdef SISDUALHEAD 1124872b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1124972b676d7Smrg 1125072b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvedgeenhance; 1125172b676d7Smrg#endif 1125272b676d7Smrg 1125372b676d7Smrg if(!(pSiS->VBFlags2 & VB2_301)) return result; 1125472b676d7Smrg if(!(pSiS->VBFlags & CRT2_TV)) return result; 1125572b676d7Smrg 1125672b676d7Smrg#ifdef UNLOCK_ALWAYS 1125772b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1125872b676d7Smrg#endif 1125972b676d7Smrg inSISIDXREG(SISPART2, 0x3a, temp); 1126072b676d7Smrg return(int)(((temp & 0xe0) >> 5) * 2); 1126172b676d7Smrg} 1126272b676d7Smrg 1126372b676d7Smrgvoid SiS_SetSISTVantiflicker(ScrnInfoPtr pScrn, int val) 1126472b676d7Smrg{ 1126572b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1126672b676d7Smrg#ifdef SISDUALHEAD 1126772b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1126872b676d7Smrg#endif 1126972b676d7Smrg 1127072b676d7Smrg pSiS->sistvantiflicker = val; 1127172b676d7Smrg#ifdef SISDUALHEAD 1127272b676d7Smrg if(pSiSEnt) pSiSEnt->sistvantiflicker = val; 1127372b676d7Smrg#endif 1127472b676d7Smrg 1127572b676d7Smrg if(!(pSiS->VBFlags & CRT2_TV)) return; 1127672b676d7Smrg if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 1127772b676d7Smrg if(pSiS->VBFlags & TV_HIVISION) return; 1127872b676d7Smrg if((pSiS->VBFlags & TV_YPBPR) && 1127972b676d7Smrg (pSiS->VBFlags & (TV_YPBPR525P | TV_YPBPR625P | TV_YPBPR750P | TV_YPBPR1080I))) return; 1128072b676d7Smrg 1128172b676d7Smrg#ifdef UNLOCK_ALWAYS 1128272b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1128372b676d7Smrg#endif 1128472b676d7Smrg 1128572b676d7Smrg /* Valid values: 0=off, 1=low, 2=med, 3=high, 4=adaptive */ 1128672b676d7Smrg if((val >= 0) && (val <= 4)) { 1128772b676d7Smrg setSISIDXREG(SISPART2,0x0A,0x8F, (val << 4)); 1128872b676d7Smrg } 1128972b676d7Smrg} 1129072b676d7Smrg 1129172b676d7Smrgint SiS_GetSISTVantiflicker(ScrnInfoPtr pScrn) 1129272b676d7Smrg{ 1129372b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1129472b676d7Smrg int result = pSiS->sistvantiflicker; 1129572b676d7Smrg UChar temp; 1129672b676d7Smrg#ifdef SISDUALHEAD 1129772b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1129872b676d7Smrg 1129972b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvantiflicker; 1130072b676d7Smrg#endif 1130172b676d7Smrg 1130272b676d7Smrg if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return result; 1130372b676d7Smrg if(!(pSiS->VBFlags & CRT2_TV)) return result; 1130472b676d7Smrg if(pSiS->VBFlags & TV_HIVISION) return result; 1130572b676d7Smrg if((pSiS->VBFlags & TV_YPBPR) && 1130672b676d7Smrg (pSiS->VBFlags & (TV_YPBPR525P | TV_YPBPR625P | TV_YPBPR750P | TV_YPBPR1080I))) return result; 1130772b676d7Smrg 1130872b676d7Smrg#ifdef UNLOCK_ALWAYS 1130972b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1131072b676d7Smrg#endif 1131172b676d7Smrg inSISIDXREG(SISPART2, 0x0a, temp); 1131272b676d7Smrg return(int)((temp & 0x70) >> 4); 1131372b676d7Smrg} 1131472b676d7Smrg 1131572b676d7Smrgvoid SiS_SetSISTVsaturation(ScrnInfoPtr pScrn, int val) 1131672b676d7Smrg{ 1131772b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1131872b676d7Smrg#ifdef SISDUALHEAD 1131972b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1132072b676d7Smrg#endif 1132172b676d7Smrg 1132272b676d7Smrg pSiS->sistvsaturation = val; 1132372b676d7Smrg#ifdef SISDUALHEAD 1132472b676d7Smrg if(pSiSEnt) pSiSEnt->sistvsaturation = val; 1132572b676d7Smrg#endif 1132672b676d7Smrg 1132772b676d7Smrg if(!(pSiS->VBFlags & CRT2_TV)) return; 1132872b676d7Smrg if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 1132972b676d7Smrg if(pSiS->VBFlags2 & VB2_301) return; 1133072b676d7Smrg 1133172b676d7Smrg#ifdef UNLOCK_ALWAYS 1133272b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1133372b676d7Smrg#endif 1133472b676d7Smrg 1133572b676d7Smrg val /= 2; 1133672b676d7Smrg if((val >= 0) && (val <= 7)) { 1133772b676d7Smrg setSISIDXREG(SISPART4,0x21,0xF8, val); 1133872b676d7Smrg } 1133972b676d7Smrg} 1134072b676d7Smrg 1134172b676d7Smrgint SiS_GetSISTVsaturation(ScrnInfoPtr pScrn) 1134272b676d7Smrg{ 1134372b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1134472b676d7Smrg int result = pSiS->sistvsaturation; 1134572b676d7Smrg UChar temp; 1134672b676d7Smrg#ifdef SISDUALHEAD 1134772b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1134872b676d7Smrg 1134972b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvsaturation; 1135072b676d7Smrg#endif 1135172b676d7Smrg 1135272b676d7Smrg if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return result; 1135372b676d7Smrg if(pSiS->VBFlags2 & VB2_301) return result; 1135472b676d7Smrg if(!(pSiS->VBFlags & CRT2_TV)) return result; 1135572b676d7Smrg 1135672b676d7Smrg#ifdef UNLOCK_ALWAYS 1135772b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1135872b676d7Smrg#endif 1135972b676d7Smrg inSISIDXREG(SISPART4, 0x21, temp); 1136072b676d7Smrg return(int)((temp & 0x07) * 2); 1136172b676d7Smrg} 1136272b676d7Smrg 1136372b676d7Smrgvoid SiS_SetSISTVcolcalib(ScrnInfoPtr pScrn, int val, Bool coarse) 1136472b676d7Smrg{ 1136572b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1136672b676d7Smrg#ifdef SISDUALHEAD 1136772b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1136872b676d7Smrg#endif 1136972b676d7Smrg int ccoarse, cfine, cbase = pSiS->sistvccbase; 1137072b676d7Smrg /* UChar temp; */ 1137172b676d7Smrg 1137272b676d7Smrg#ifdef SISDUALHEAD 1137372b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) cbase = pSiSEnt->sistvccbase; 1137472b676d7Smrg#endif 1137572b676d7Smrg 1137672b676d7Smrg if(coarse) { 1137772b676d7Smrg pSiS->sistvcolcalibc = ccoarse = val; 1137872b676d7Smrg cfine = pSiS->sistvcolcalibf; 1137972b676d7Smrg#ifdef SISDUALHEAD 1138072b676d7Smrg if(pSiSEnt) { 1138172b676d7Smrg pSiSEnt->sistvcolcalibc = val; 1138272b676d7Smrg if(pSiS->DualHeadMode) cfine = pSiSEnt->sistvcolcalibf; 1138372b676d7Smrg } 1138472b676d7Smrg#endif 1138572b676d7Smrg } else { 1138672b676d7Smrg pSiS->sistvcolcalibf = cfine = val; 1138772b676d7Smrg ccoarse = pSiS->sistvcolcalibc; 1138872b676d7Smrg#ifdef SISDUALHEAD 1138972b676d7Smrg if(pSiSEnt) { 1139072b676d7Smrg pSiSEnt->sistvcolcalibf = val; 1139172b676d7Smrg if(pSiS->DualHeadMode) ccoarse = pSiSEnt->sistvcolcalibc; 1139272b676d7Smrg } 1139372b676d7Smrg#endif 1139472b676d7Smrg } 1139572b676d7Smrg 1139672b676d7Smrg if(!(pSiS->VBFlags & CRT2_TV)) return; 1139772b676d7Smrg if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 1139872b676d7Smrg if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return; 1139972b676d7Smrg 1140072b676d7Smrg#ifdef UNLOCK_ALWAYS 1140172b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1140272b676d7Smrg#endif 1140372b676d7Smrg 1140472b676d7Smrg if((cfine >= -128) && (cfine <= 127) && (ccoarse >= -120) && (ccoarse <= 120)) { 1140572b676d7Smrg long finalcc = cbase + (((ccoarse * 256) + cfine) * 256); 1140672b676d7Smrg 1140772b676d7Smrg#if 0 1140872b676d7Smrg inSISIDXREG(SISPART4,0x1f,temp); 1140972b676d7Smrg if(!(temp & 0x01)) { 1141072b676d7Smrg if(pSiS->VBFlags & TV_NTSC) finalcc += 0x21ed8620; 1141172b676d7Smrg else if(pSiS->VBFlags & TV_PALM) finalcc += ?; 1141272b676d7Smrg else if(pSiS->VBFlags & TV_PALM) finalcc += ?; 1141372b676d7Smrg else finalcc += 0x2a05d300; 1141472b676d7Smrg } 1141572b676d7Smrg#endif 1141672b676d7Smrg setSISIDXREG(SISPART2,0x31,0x80,((finalcc >> 24) & 0x7f)); 1141772b676d7Smrg outSISIDXREG(SISPART2,0x32,((finalcc >> 16) & 0xff)); 1141872b676d7Smrg outSISIDXREG(SISPART2,0x33,((finalcc >> 8) & 0xff)); 1141972b676d7Smrg outSISIDXREG(SISPART2,0x34,(finalcc & 0xff)); 1142072b676d7Smrg } 1142172b676d7Smrg} 1142272b676d7Smrg 1142372b676d7Smrgint SiS_GetSISTVcolcalib(ScrnInfoPtr pScrn, Bool coarse) 1142472b676d7Smrg{ 1142572b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1142672b676d7Smrg#ifdef SISDUALHEAD 1142772b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1142872b676d7Smrg 1142972b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) 1143072b676d7Smrg if(coarse) return (int)pSiSEnt->sistvcolcalibc; 1143172b676d7Smrg else return (int)pSiSEnt->sistvcolcalibf; 1143272b676d7Smrg else 1143372b676d7Smrg#endif 1143472b676d7Smrg if(coarse) return (int)pSiS->sistvcolcalibc; 1143572b676d7Smrg else return (int)pSiS->sistvcolcalibf; 1143672b676d7Smrg} 1143772b676d7Smrg 1143872b676d7Smrgvoid SiS_SetSISTVcfilter(ScrnInfoPtr pScrn, int val) 1143972b676d7Smrg{ 1144072b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1144172b676d7Smrg#ifdef SISDUALHEAD 1144272b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1144372b676d7Smrg#endif 1144472b676d7Smrg 1144572b676d7Smrg pSiS->sistvcfilter = val ? 1 : 0; 1144672b676d7Smrg#ifdef SISDUALHEAD 1144772b676d7Smrg if(pSiSEnt) pSiSEnt->sistvcfilter = pSiS->sistvcfilter; 1144872b676d7Smrg#endif 1144972b676d7Smrg 1145072b676d7Smrg if(!(pSiS->VBFlags & CRT2_TV)) return; 1145172b676d7Smrg if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 1145272b676d7Smrg if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return; 1145372b676d7Smrg 1145472b676d7Smrg#ifdef UNLOCK_ALWAYS 1145572b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1145672b676d7Smrg#endif 1145772b676d7Smrg 1145872b676d7Smrg setSISIDXREG(SISPART2,0x30,~0x10,((pSiS->sistvcfilter << 4) & 0x10)); 1145972b676d7Smrg} 1146072b676d7Smrg 1146172b676d7Smrgint SiS_GetSISTVcfilter(ScrnInfoPtr pScrn) 1146272b676d7Smrg{ 1146372b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1146472b676d7Smrg int result = pSiS->sistvcfilter; 1146572b676d7Smrg UChar temp; 1146672b676d7Smrg#ifdef SISDUALHEAD 1146772b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1146872b676d7Smrg 1146972b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->sistvcfilter; 1147072b676d7Smrg#endif 1147172b676d7Smrg 1147272b676d7Smrg if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return result; 1147372b676d7Smrg if(!(pSiS->VBFlags & CRT2_TV)) return result; 1147472b676d7Smrg if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return result; 1147572b676d7Smrg 1147672b676d7Smrg#ifdef UNLOCK_ALWAYS 1147772b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1147872b676d7Smrg#endif 1147972b676d7Smrg inSISIDXREG(SISPART2, 0x30, temp); 1148072b676d7Smrg return (int)((temp & 0x10) ? 1 : 0); 1148172b676d7Smrg} 1148272b676d7Smrg 1148372b676d7Smrgvoid SiS_SetSISTVyfilter(ScrnInfoPtr pScrn, int val) 1148472b676d7Smrg{ 1148572b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1148672b676d7Smrg#ifdef SISDUALHEAD 1148772b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1148872b676d7Smrg#endif 1148972b676d7Smrg UChar p35,p36,p37,p38,p48,p49,p4a,p30; 1149072b676d7Smrg int i,j; 1149172b676d7Smrg 1149272b676d7Smrg pSiS->sistvyfilter = val; 1149372b676d7Smrg#ifdef SISDUALHEAD 1149472b676d7Smrg if(pSiSEnt) pSiSEnt->sistvyfilter = pSiS->sistvyfilter; 1149572b676d7Smrg#endif 1149672b676d7Smrg 1149772b676d7Smrg if(!(pSiS->VBFlags & CRT2_TV)) return; 1149872b676d7Smrg if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 1149972b676d7Smrg if(pSiS->VBFlags & (TV_HIVISION | TV_YPBPR)) return; 1150072b676d7Smrg 1150172b676d7Smrg p35 = pSiS->p2_35; p36 = pSiS->p2_36; 1150272b676d7Smrg p37 = pSiS->p2_37; p38 = pSiS->p2_38; 1150372b676d7Smrg p48 = pSiS->p2_48; p49 = pSiS->p2_49; 1150472b676d7Smrg p4a = pSiS->p2_4a; p30 = pSiS->p2_30; 1150572b676d7Smrg#ifdef SISDUALHEAD 1150672b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) { 1150772b676d7Smrg p35 = pSiSEnt->p2_35; p36 = pSiSEnt->p2_36; 1150872b676d7Smrg p37 = pSiSEnt->p2_37; p38 = pSiSEnt->p2_38; 1150972b676d7Smrg p48 = pSiSEnt->p2_48; p49 = pSiSEnt->p2_49; 1151072b676d7Smrg p4a = pSiSEnt->p2_4a; p30 = pSiSEnt->p2_30; 1151172b676d7Smrg } 1151272b676d7Smrg#endif 1151372b676d7Smrg p30 &= 0x20; 1151472b676d7Smrg 1151572b676d7Smrg#ifdef UNLOCK_ALWAYS 1151672b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1151772b676d7Smrg#endif 1151872b676d7Smrg 1151972b676d7Smrg switch(pSiS->sistvyfilter) { 1152072b676d7Smrg case 0: 1152172b676d7Smrg andSISIDXREG(SISPART2,0x30,0xdf); 1152272b676d7Smrg break; 1152372b676d7Smrg case 1: 1152472b676d7Smrg outSISIDXREG(SISPART2,0x35,p35); 1152572b676d7Smrg outSISIDXREG(SISPART2,0x36,p36); 1152672b676d7Smrg outSISIDXREG(SISPART2,0x37,p37); 1152772b676d7Smrg outSISIDXREG(SISPART2,0x38,p38); 1152872b676d7Smrg if(!(pSiS->VBFlags2 & VB2_301)) { 1152972b676d7Smrg outSISIDXREG(SISPART2,0x48,p48); 1153072b676d7Smrg outSISIDXREG(SISPART2,0x49,p49); 1153172b676d7Smrg outSISIDXREG(SISPART2,0x4a,p4a); 1153272b676d7Smrg } 1153372b676d7Smrg setSISIDXREG(SISPART2,0x30,0xdf,p30); 1153472b676d7Smrg break; 1153572b676d7Smrg case 2: 1153672b676d7Smrg case 3: 1153772b676d7Smrg case 4: 1153872b676d7Smrg case 5: 1153972b676d7Smrg case 6: 1154072b676d7Smrg case 7: 1154172b676d7Smrg case 8: 1154272b676d7Smrg if(!(pSiS->VBFlags & (TV_PALM | TV_PALN | TV_NTSCJ))) { 1154372b676d7Smrg int yindex301 = -1, yindex301B = -1; 1154472b676d7Smrg UChar p3d4_34; 1154572b676d7Smrg 1154672b676d7Smrg inSISIDXREG(SISCR,0x34,p3d4_34); 1154772b676d7Smrg 1154872b676d7Smrg switch((p3d4_34 & 0x7f)) { 1154972b676d7Smrg case 0x59: /* 320x200 */ 1155072b676d7Smrg case 0x41: 1155172b676d7Smrg case 0x4f: 1155272b676d7Smrg case 0x50: /* 320x240 */ 1155372b676d7Smrg case 0x56: 1155472b676d7Smrg case 0x53: 1155572b676d7Smrg yindex301 = (pSiS->VBFlags & TV_NTSC) ? 0 : 4; 1155672b676d7Smrg break; 1155772b676d7Smrg case 0x2f: /* 640x400 */ 1155872b676d7Smrg case 0x5d: 1155972b676d7Smrg case 0x5e: 1156072b676d7Smrg case 0x2e: /* 640x480 */ 1156172b676d7Smrg case 0x44: 1156272b676d7Smrg case 0x62: 1156372b676d7Smrg yindex301 = (pSiS->VBFlags & TV_NTSC) ? 1 : 5; 1156472b676d7Smrg yindex301B = (pSiS->VBFlags & TV_NTSC) ? 0 : 4; 1156572b676d7Smrg break; 1156672b676d7Smrg case 0x31: /* 720x480 */ 1156772b676d7Smrg case 0x33: 1156872b676d7Smrg case 0x35: 1156972b676d7Smrg case 0x32: /* 720x576 */ 1157072b676d7Smrg case 0x34: 1157172b676d7Smrg case 0x36: 1157272b676d7Smrg case 0x5f: /* 768x576 */ 1157372b676d7Smrg case 0x60: 1157472b676d7Smrg case 0x61: 1157572b676d7Smrg yindex301 = (pSiS->VBFlags & TV_NTSC) ? 2 : 6; 1157672b676d7Smrg yindex301B = (pSiS->VBFlags & TV_NTSC) ? 1 : 5; 1157772b676d7Smrg break; 1157872b676d7Smrg case 0x51: /* 400x300 */ 1157972b676d7Smrg case 0x57: 1158072b676d7Smrg case 0x54: 1158172b676d7Smrg case 0x30: /* 800x600 */ 1158272b676d7Smrg case 0x47: 1158372b676d7Smrg case 0x63: 1158472b676d7Smrg yindex301 = (pSiS->VBFlags & TV_NTSC) ? 3 : 7; 1158572b676d7Smrg yindex301B = (pSiS->VBFlags & TV_NTSC) ? 2 : 6; 1158672b676d7Smrg break; 1158772b676d7Smrg case 0x52: /* 512x384 */ 1158872b676d7Smrg case 0x58: 1158972b676d7Smrg case 0x5c: 1159072b676d7Smrg case 0x38: /* 1024x768 */ 1159172b676d7Smrg case 0x4a: 1159272b676d7Smrg case 0x64: 1159372b676d7Smrg yindex301B = (pSiS->VBFlags & TV_NTSC) ? 3 : 7; 1159472b676d7Smrg break; 1159572b676d7Smrg } 1159672b676d7Smrg if(pSiS->VBFlags2 & VB2_301) { 1159772b676d7Smrg if(yindex301 >= 0) { 1159872b676d7Smrg for(i=0, j=0x35; i<=3; i++, j++) { 1159972b676d7Smrg outSISIDXREG(SISPART2,j,(SiSTVFilter301[yindex301].filter[pSiS->sistvyfilter-2][i])); 1160072b676d7Smrg } 1160172b676d7Smrg } 1160272b676d7Smrg } else { 1160372b676d7Smrg if(yindex301B >= 0) { 1160472b676d7Smrg for(i=0, j=0x35; i<=3; i++, j++) { 1160572b676d7Smrg outSISIDXREG(SISPART2,j,(SiSTVFilter301B[yindex301B].filter[pSiS->sistvyfilter-2][i])); 1160672b676d7Smrg } 1160772b676d7Smrg for(i=4, j=0x48; i<=6; i++, j++) { 1160872b676d7Smrg outSISIDXREG(SISPART2,j,(SiSTVFilter301B[yindex301B].filter[pSiS->sistvyfilter-2][i])); 1160972b676d7Smrg } 1161072b676d7Smrg } 1161172b676d7Smrg } 1161272b676d7Smrg orSISIDXREG(SISPART2,0x30,0x20); 1161372b676d7Smrg } 1161472b676d7Smrg } 1161572b676d7Smrg} 1161672b676d7Smrg 1161772b676d7Smrgint SiS_GetSISTVyfilter(ScrnInfoPtr pScrn) 1161872b676d7Smrg{ 1161972b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1162072b676d7Smrg#ifdef SISDUALHEAD 1162172b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1162272b676d7Smrg 1162372b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) 1162472b676d7Smrg return (int)pSiSEnt->sistvyfilter; 1162572b676d7Smrg else 1162672b676d7Smrg#endif 1162772b676d7Smrg return (int)pSiS->sistvyfilter; 1162872b676d7Smrg} 1162972b676d7Smrg 1163072b676d7Smrgvoid SiS_SetSIS6326TVantiflicker(ScrnInfoPtr pScrn, int val) 1163172b676d7Smrg{ 1163272b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1163372b676d7Smrg UChar tmp; 1163472b676d7Smrg 1163572b676d7Smrg pSiS->sistvantiflicker = val; 1163672b676d7Smrg 1163772b676d7Smrg if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 1163872b676d7Smrg 1163972b676d7Smrg#ifdef UNLOCK_ALWAYS 1164072b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1164172b676d7Smrg#endif 1164272b676d7Smrg 1164372b676d7Smrg tmp = SiS6326GetTVReg(pScrn,0x00); 1164472b676d7Smrg if(!(tmp & 0x04)) return; 1164572b676d7Smrg 1164672b676d7Smrg /* Valid values: 0=off, 1=low, 2=med, 3=high, 4=adaptive */ 1164772b676d7Smrg if(val >= 0 && val <= 4) { 1164872b676d7Smrg tmp &= 0x1f; 1164972b676d7Smrg tmp |= (val << 5); 1165072b676d7Smrg SiS6326SetTVReg(pScrn,0x00,tmp); 1165172b676d7Smrg } 1165272b676d7Smrg} 1165372b676d7Smrg 1165472b676d7Smrgint SiS_GetSIS6326TVantiflicker(ScrnInfoPtr pScrn) 1165572b676d7Smrg{ 1165672b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1165772b676d7Smrg UChar tmp; 1165872b676d7Smrg 1165972b676d7Smrg if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 1166072b676d7Smrg return (int)pSiS->sistvantiflicker; 1166172b676d7Smrg } 1166272b676d7Smrg 1166372b676d7Smrg#ifdef UNLOCK_ALWAYS 1166472b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1166572b676d7Smrg#endif 1166672b676d7Smrg 1166772b676d7Smrg tmp = SiS6326GetTVReg(pScrn,0x00); 1166872b676d7Smrg if(!(tmp & 0x04)) { 1166972b676d7Smrg return (int)pSiS->sistvantiflicker; 1167072b676d7Smrg } else { 1167172b676d7Smrg return (int)((tmp >> 5) & 0x07); 1167272b676d7Smrg } 1167372b676d7Smrg} 1167472b676d7Smrg 1167572b676d7Smrgvoid SiS_SetSIS6326TVenableyfilter(ScrnInfoPtr pScrn, int val) 1167672b676d7Smrg{ 1167772b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1167872b676d7Smrg UChar tmp; 1167972b676d7Smrg 1168072b676d7Smrg if(val) val = 1; 1168172b676d7Smrg pSiS->sis6326enableyfilter = val; 1168272b676d7Smrg 1168372b676d7Smrg if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 1168472b676d7Smrg 1168572b676d7Smrg#ifdef UNLOCK_ALWAYS 1168672b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1168772b676d7Smrg#endif 1168872b676d7Smrg 1168972b676d7Smrg tmp = SiS6326GetTVReg(pScrn,0x00); 1169072b676d7Smrg if(!(tmp & 0x04)) return; 1169172b676d7Smrg 1169272b676d7Smrg tmp = SiS6326GetTVReg(pScrn,0x43); 1169372b676d7Smrg tmp &= ~0x10; 1169472b676d7Smrg tmp |= ((val & 0x01) << 4); 1169572b676d7Smrg SiS6326SetTVReg(pScrn,0x43,tmp); 1169672b676d7Smrg} 1169772b676d7Smrg 1169872b676d7Smrgint SiS_GetSIS6326TVenableyfilter(ScrnInfoPtr pScrn) 1169972b676d7Smrg{ 1170072b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1170172b676d7Smrg UChar tmp; 1170272b676d7Smrg 1170372b676d7Smrg if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 1170472b676d7Smrg return (int)pSiS->sis6326enableyfilter; 1170572b676d7Smrg } 1170672b676d7Smrg 1170772b676d7Smrg#ifdef UNLOCK_ALWAYS 1170872b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1170972b676d7Smrg#endif 1171072b676d7Smrg 1171172b676d7Smrg tmp = SiS6326GetTVReg(pScrn,0x00); 1171272b676d7Smrg if(!(tmp & 0x04)) { 1171372b676d7Smrg return (int)pSiS->sis6326enableyfilter; 1171472b676d7Smrg } else { 1171572b676d7Smrg tmp = SiS6326GetTVReg(pScrn,0x43); 1171672b676d7Smrg return (int)((tmp >> 4) & 0x01); 1171772b676d7Smrg } 1171872b676d7Smrg} 1171972b676d7Smrg 1172072b676d7Smrgvoid SiS_SetSIS6326TVyfilterstrong(ScrnInfoPtr pScrn, int val) 1172172b676d7Smrg{ 1172272b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1172372b676d7Smrg UChar tmp; 1172472b676d7Smrg 1172572b676d7Smrg if(val) val = 1; 1172672b676d7Smrg pSiS->sis6326yfilterstrong = val; 1172772b676d7Smrg 1172872b676d7Smrg if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 1172972b676d7Smrg 1173072b676d7Smrg#ifdef UNLOCK_ALWAYS 1173172b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1173272b676d7Smrg#endif 1173372b676d7Smrg 1173472b676d7Smrg tmp = SiS6326GetTVReg(pScrn,0x00); 1173572b676d7Smrg if(!(tmp & 0x04)) return; 1173672b676d7Smrg 1173772b676d7Smrg tmp = SiS6326GetTVReg(pScrn,0x43); 1173872b676d7Smrg if(tmp & 0x10) { 1173972b676d7Smrg tmp &= ~0x40; 1174072b676d7Smrg tmp |= ((val & 0x01) << 6); 1174172b676d7Smrg SiS6326SetTVReg(pScrn,0x43,tmp); 1174272b676d7Smrg } 1174372b676d7Smrg} 1174472b676d7Smrg 1174572b676d7Smrgint SiS_GetSIS6326TVyfilterstrong(ScrnInfoPtr pScrn) 1174672b676d7Smrg{ 1174772b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1174872b676d7Smrg UChar tmp; 1174972b676d7Smrg 1175072b676d7Smrg if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { 1175172b676d7Smrg return (int)pSiS->sis6326yfilterstrong; 1175272b676d7Smrg } 1175372b676d7Smrg 1175472b676d7Smrg#ifdef UNLOCK_ALWAYS 1175572b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1175672b676d7Smrg#endif 1175772b676d7Smrg 1175872b676d7Smrg tmp = SiS6326GetTVReg(pScrn,0x00); 1175972b676d7Smrg if(!(tmp & 0x04)) { 1176072b676d7Smrg return (int)pSiS->sis6326yfilterstrong; 1176172b676d7Smrg } else { 1176272b676d7Smrg tmp = SiS6326GetTVReg(pScrn,0x43); 1176372b676d7Smrg if(!(tmp & 0x10)) { 1176472b676d7Smrg return (int)pSiS->sis6326yfilterstrong; 1176572b676d7Smrg } else { 1176672b676d7Smrg return (int)((tmp >> 6) & 0x01); 1176772b676d7Smrg } 1176872b676d7Smrg } 1176972b676d7Smrg} 1177072b676d7Smrg 1177172b676d7Smrgvoid SiS_SetTVxposoffset(ScrnInfoPtr pScrn, int val) 1177272b676d7Smrg{ 1177372b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1177472b676d7Smrg#ifdef SISDUALHEAD 1177572b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1177672b676d7Smrg#endif 1177772b676d7Smrg 1177872b676d7Smrg#ifdef UNLOCK_ALWAYS 1177972b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1178072b676d7Smrg#endif 1178172b676d7Smrg 1178272b676d7Smrg pSiS->tvxpos = val; 1178372b676d7Smrg#ifdef SISDUALHEAD 1178472b676d7Smrg if(pSiSEnt) pSiSEnt->tvxpos = val; 1178572b676d7Smrg#endif 1178672b676d7Smrg 1178772b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 1178872b676d7Smrg 1178972b676d7Smrg if(pSiS->VBFlags & CRT2_TV) { 1179072b676d7Smrg 1179172b676d7Smrg if(pSiS->VBFlags2 & VB2_CHRONTEL) { 1179272b676d7Smrg 1179372b676d7Smrg int x = pSiS->tvx; 1179472b676d7Smrg#ifdef SISDUALHEAD 1179572b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) x = pSiSEnt->tvx; 1179672b676d7Smrg#endif 1179772b676d7Smrg switch(pSiS->ChrontelType) { 1179872b676d7Smrg case CHRONTEL_700x: 1179972b676d7Smrg if((val >= -32) && (val <= 32)) { 1180072b676d7Smrg x += val; 1180172b676d7Smrg if(x < 0) x = 0; 1180272b676d7Smrg SiS_SetCH700x(pSiS->SiS_Pr, 0x0a, (x & 0xff)); 1180372b676d7Smrg SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD); 1180472b676d7Smrg } 1180572b676d7Smrg break; 1180672b676d7Smrg case CHRONTEL_701x: 1180772b676d7Smrg /* Not supported by hardware */ 1180872b676d7Smrg break; 1180972b676d7Smrg } 1181072b676d7Smrg 1181172b676d7Smrg } else if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 1181272b676d7Smrg 1181372b676d7Smrg if((val >= -32) && (val <= 32)) { 1181472b676d7Smrg 1181572b676d7Smrg UChar p2_1f,p2_20,p2_2b,p2_42,p2_43; 1181672b676d7Smrg UShort temp; 1181772b676d7Smrg int mult; 1181872b676d7Smrg 1181972b676d7Smrg p2_1f = pSiS->p2_1f; 1182072b676d7Smrg p2_20 = pSiS->p2_20; 1182172b676d7Smrg p2_2b = pSiS->p2_2b; 1182272b676d7Smrg p2_42 = pSiS->p2_42; 1182372b676d7Smrg p2_43 = pSiS->p2_43; 1182472b676d7Smrg#ifdef SISDUALHEAD 1182572b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) { 1182672b676d7Smrg p2_1f = pSiSEnt->p2_1f; 1182772b676d7Smrg p2_20 = pSiSEnt->p2_20; 1182872b676d7Smrg p2_2b = pSiSEnt->p2_2b; 1182972b676d7Smrg p2_42 = pSiSEnt->p2_42; 1183072b676d7Smrg p2_43 = pSiSEnt->p2_43; 1183172b676d7Smrg } 1183272b676d7Smrg#endif 1183372b676d7Smrg mult = 2; 1183472b676d7Smrg if(pSiS->VBFlags & TV_YPBPR) { 1183572b676d7Smrg if(pSiS->VBFlags & (TV_YPBPR1080I | TV_YPBPR750P)) { 1183672b676d7Smrg mult = 4; 1183772b676d7Smrg } 1183872b676d7Smrg } 1183972b676d7Smrg 1184072b676d7Smrg temp = p2_1f | ((p2_20 & 0xf0) << 4); 1184172b676d7Smrg temp += (val * mult); 1184272b676d7Smrg p2_1f = temp & 0xff; 1184372b676d7Smrg p2_20 = (temp & 0xf00) >> 4; 1184472b676d7Smrg p2_2b = ((p2_2b & 0x0f) + (val * mult)) & 0x0f; 1184572b676d7Smrg temp = p2_43 | ((p2_42 & 0xf0) << 4); 1184672b676d7Smrg temp += (val * mult); 1184772b676d7Smrg p2_43 = temp & 0xff; 1184872b676d7Smrg p2_42 = (temp & 0xf00) >> 4; 1184972b676d7Smrg SISWaitRetraceCRT2(pScrn); 1185072b676d7Smrg outSISIDXREG(SISPART2,0x1f,p2_1f); 1185172b676d7Smrg setSISIDXREG(SISPART2,0x20,0x0F,p2_20); 1185272b676d7Smrg setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b); 1185372b676d7Smrg setSISIDXREG(SISPART2,0x42,0x0F,p2_42); 1185472b676d7Smrg outSISIDXREG(SISPART2,0x43,p2_43); 1185572b676d7Smrg } 1185672b676d7Smrg } 1185772b676d7Smrg } 1185872b676d7Smrg 1185972b676d7Smrg } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { 1186072b676d7Smrg 1186172b676d7Smrg if(pSiS->SiS6326Flags & SIS6326_TVDETECTED) { 1186272b676d7Smrg 1186372b676d7Smrg UChar tmp; 1186472b676d7Smrg UShort temp1, temp2, temp3; 1186572b676d7Smrg 1186672b676d7Smrg tmp = SiS6326GetTVReg(pScrn,0x00); 1186772b676d7Smrg if(tmp & 0x04) { 1186872b676d7Smrg 1186972b676d7Smrg temp1 = pSiS->tvx1; 1187072b676d7Smrg temp2 = pSiS->tvx2; 1187172b676d7Smrg temp3 = pSiS->tvx3; 1187272b676d7Smrg if((val >= -16) && (val <= 16)) { 1187372b676d7Smrg if(val > 0) { 1187472b676d7Smrg temp1 += (val * 4); 1187572b676d7Smrg temp2 += (val * 4); 1187672b676d7Smrg while((temp1 > 0x0fff) || (temp2 > 0x0fff)) { 1187772b676d7Smrg temp1 -= 4; 1187872b676d7Smrg temp2 -= 4; 1187972b676d7Smrg } 1188072b676d7Smrg } else { 1188172b676d7Smrg val = -val; 1188272b676d7Smrg temp3 += (val * 4); 1188372b676d7Smrg while(temp3 > 0x03ff) { 1188472b676d7Smrg temp3 -= 4; 1188572b676d7Smrg } 1188672b676d7Smrg } 1188772b676d7Smrg } 1188872b676d7Smrg SiS6326SetTVReg(pScrn,0x3a,(temp1 & 0xff)); 1188972b676d7Smrg tmp = SiS6326GetTVReg(pScrn,0x3c); 1189072b676d7Smrg tmp &= 0xf0; 1189172b676d7Smrg tmp |= ((temp1 & 0x0f00) >> 8); 1189272b676d7Smrg SiS6326SetTVReg(pScrn,0x3c,tmp); 1189372b676d7Smrg SiS6326SetTVReg(pScrn,0x26,(temp2 & 0xff)); 1189472b676d7Smrg tmp = SiS6326GetTVReg(pScrn,0x27); 1189572b676d7Smrg tmp &= 0x0f; 1189672b676d7Smrg tmp |= ((temp2 & 0x0f00) >> 4); 1189772b676d7Smrg SiS6326SetTVReg(pScrn,0x27,tmp); 1189872b676d7Smrg SiS6326SetTVReg(pScrn,0x12,(temp3 & 0xff)); 1189972b676d7Smrg tmp = SiS6326GetTVReg(pScrn,0x13); 1190072b676d7Smrg tmp &= ~0xC0; 1190172b676d7Smrg tmp |= ((temp3 & 0x0300) >> 2); 1190272b676d7Smrg SiS6326SetTVReg(pScrn,0x13,tmp); 1190372b676d7Smrg } 1190472b676d7Smrg } 1190572b676d7Smrg } 1190672b676d7Smrg} 1190772b676d7Smrg 1190872b676d7Smrgint SiS_GetTVxposoffset(ScrnInfoPtr pScrn) 1190972b676d7Smrg{ 1191072b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1191172b676d7Smrg#ifdef SISDUALHEAD 1191272b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1191372b676d7Smrg 1191472b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) 1191572b676d7Smrg return (int)pSiSEnt->tvxpos; 1191672b676d7Smrg else 1191772b676d7Smrg#endif 1191872b676d7Smrg return (int)pSiS->tvxpos; 1191972b676d7Smrg} 1192072b676d7Smrg 1192172b676d7Smrgvoid SiS_SetTVyposoffset(ScrnInfoPtr pScrn, int val) 1192272b676d7Smrg{ 1192372b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1192472b676d7Smrg#ifdef SISDUALHEAD 1192572b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1192672b676d7Smrg#endif 1192772b676d7Smrg 1192872b676d7Smrg#ifdef UNLOCK_ALWAYS 1192972b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1193072b676d7Smrg#endif 1193172b676d7Smrg 1193272b676d7Smrg pSiS->tvypos = val; 1193372b676d7Smrg#ifdef SISDUALHEAD 1193472b676d7Smrg if(pSiSEnt) pSiSEnt->tvypos = val; 1193572b676d7Smrg#endif 1193672b676d7Smrg 1193772b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 1193872b676d7Smrg 1193972b676d7Smrg if(pSiS->VBFlags & CRT2_TV) { 1194072b676d7Smrg 1194172b676d7Smrg if(pSiS->VBFlags2 & VB2_CHRONTEL) { 1194272b676d7Smrg 1194372b676d7Smrg int y = pSiS->tvy; 1194472b676d7Smrg#ifdef SISDUALHEAD 1194572b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) y = pSiSEnt->tvy; 1194672b676d7Smrg#endif 1194772b676d7Smrg switch(pSiS->ChrontelType) { 1194872b676d7Smrg case CHRONTEL_700x: 1194972b676d7Smrg if((val >= -32) && (val <= 32)) { 1195072b676d7Smrg y -= val; 1195172b676d7Smrg if(y < 0) y = 0; 1195272b676d7Smrg SiS_SetCH700x(pSiS->SiS_Pr, 0x0b, (y & 0xff)); 1195372b676d7Smrg SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE); 1195472b676d7Smrg } 1195572b676d7Smrg break; 1195672b676d7Smrg case CHRONTEL_701x: 1195772b676d7Smrg /* Not supported by hardware */ 1195872b676d7Smrg break; 1195972b676d7Smrg } 1196072b676d7Smrg 1196172b676d7Smrg } else if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 1196272b676d7Smrg 1196372b676d7Smrg if((val >= -32) && (val <= 32)) { 1196472b676d7Smrg char p2_01, p2_02; 1196572b676d7Smrg 1196672b676d7Smrg if( (pSiS->VBFlags & TV_HIVISION) || 1196772b676d7Smrg ((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & (TV_YPBPR1080I|TV_YPBPR750P))) ) { 1196872b676d7Smrg val *= 2; 1196972b676d7Smrg } else { 1197072b676d7Smrg val /= 2; /* 4 */ 1197172b676d7Smrg } 1197272b676d7Smrg 1197372b676d7Smrg p2_01 = pSiS->p2_01; 1197472b676d7Smrg p2_02 = pSiS->p2_02; 1197572b676d7Smrg#ifdef SISDUALHEAD 1197672b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) { 1197772b676d7Smrg p2_01 = pSiSEnt->p2_01; 1197872b676d7Smrg p2_02 = pSiSEnt->p2_02; 1197972b676d7Smrg } 1198072b676d7Smrg#endif 1198172b676d7Smrg p2_01 += val; /* val * 2 */ 1198272b676d7Smrg p2_02 += val; /* val * 2 */ 1198372b676d7Smrg if(!(pSiS->VBFlags & (TV_YPBPR | TV_HIVISION))) { 1198472b676d7Smrg while((p2_01 <= 0) || (p2_02 <= 0)) { 1198572b676d7Smrg p2_01 += 2; 1198672b676d7Smrg p2_02 += 2; 1198772b676d7Smrg } 1198872b676d7Smrg } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR1080I)) { 1198972b676d7Smrg while(p2_01 <= 8) { 1199072b676d7Smrg p2_01 += 2; 1199172b676d7Smrg p2_02 += 2; 1199272b676d7Smrg } 1199372b676d7Smrg } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR750P)) { 1199472b676d7Smrg while(p2_01 <= 10) { 1199572b676d7Smrg p2_01 += 2; 1199672b676d7Smrg p2_02 += 2; 1199772b676d7Smrg } 1199872b676d7Smrg } 1199972b676d7Smrg 1200072b676d7Smrg SISWaitRetraceCRT2(pScrn); 1200172b676d7Smrg outSISIDXREG(SISPART2,0x01,p2_01); 1200272b676d7Smrg outSISIDXREG(SISPART2,0x02,p2_02); 1200372b676d7Smrg } 1200472b676d7Smrg } 1200572b676d7Smrg 1200672b676d7Smrg } 1200772b676d7Smrg 1200872b676d7Smrg } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { 1200972b676d7Smrg 1201072b676d7Smrg if(pSiS->SiS6326Flags & SIS6326_TVDETECTED) { 1201172b676d7Smrg 1201272b676d7Smrg UChar tmp; 1201372b676d7Smrg int temp1, limit; 1201472b676d7Smrg 1201572b676d7Smrg tmp = SiS6326GetTVReg(pScrn,0x00); 1201672b676d7Smrg if(tmp & 0x04) { 1201772b676d7Smrg 1201872b676d7Smrg if((val >= -16) && (val <= 16)) { 1201972b676d7Smrg temp1 = (UShort)pSiS->tvy1; 1202072b676d7Smrg limit = (pSiS->SiS6326Flags & SIS6326_TVPAL) ? 625 : 525; 1202172b676d7Smrg if(val > 0) { 1202272b676d7Smrg temp1 += (val * 4); 1202372b676d7Smrg if(temp1 > limit) temp1 -= limit; 1202472b676d7Smrg } else { 1202572b676d7Smrg val = -val; 1202672b676d7Smrg temp1 -= (val * 2); 1202772b676d7Smrg if(temp1 <= 0) temp1 += (limit -1); 1202872b676d7Smrg } 1202972b676d7Smrg SiS6326SetTVReg(pScrn,0x11,(temp1 & 0xff)); 1203072b676d7Smrg tmp = SiS6326GetTVReg(pScrn,0x13); 1203172b676d7Smrg tmp &= ~0x30; 1203272b676d7Smrg tmp |= ((temp1 & 0x300) >> 4); 1203372b676d7Smrg SiS6326SetTVReg(pScrn,0x13,tmp); 1203472b676d7Smrg if(temp1 == 1) tmp = 0x10; 1203572b676d7Smrg else { 1203672b676d7Smrg if(pSiS->SiS6326Flags & SIS6326_TVPAL) { 1203772b676d7Smrg if((temp1 <= 3) || (temp1 >= (limit - 2))) tmp = 0x08; 1203872b676d7Smrg else if(temp1 < 22) tmp = 0x02; 1203972b676d7Smrg else tmp = 0x04; 1204072b676d7Smrg } else { 1204172b676d7Smrg if((temp1 <= 5) || (temp1 >= (limit - 4))) tmp = 0x08; 1204272b676d7Smrg else if(temp1 < 19) tmp = 0x02; 1204372b676d7Smrg else tmp = 0x04; 1204472b676d7Smrg } 1204572b676d7Smrg } 1204672b676d7Smrg SiS6326SetTVReg(pScrn,0x21,tmp); 1204772b676d7Smrg } 1204872b676d7Smrg } 1204972b676d7Smrg } 1205072b676d7Smrg } 1205172b676d7Smrg} 1205272b676d7Smrg 1205372b676d7Smrgint SiS_GetTVyposoffset(ScrnInfoPtr pScrn) 1205472b676d7Smrg{ 1205572b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1205672b676d7Smrg#ifdef SISDUALHEAD 1205772b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1205872b676d7Smrg 1205972b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) 1206072b676d7Smrg return (int)pSiSEnt->tvypos; 1206172b676d7Smrg else 1206272b676d7Smrg#endif 1206372b676d7Smrg return (int)pSiS->tvypos; 1206472b676d7Smrg} 1206572b676d7Smrg 1206672b676d7Smrgvoid SiS_SetTVxscale(ScrnInfoPtr pScrn, int val) 1206772b676d7Smrg{ 1206872b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1206972b676d7Smrg#ifdef SISDUALHEAD 1207072b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1207172b676d7Smrg#endif 1207272b676d7Smrg 1207372b676d7Smrg#ifdef UNLOCK_ALWAYS 1207472b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1207572b676d7Smrg#endif 1207672b676d7Smrg 1207772b676d7Smrg pSiS->tvxscale = val; 1207872b676d7Smrg#ifdef SISDUALHEAD 1207972b676d7Smrg if(pSiSEnt) pSiSEnt->tvxscale = val; 1208072b676d7Smrg#endif 1208172b676d7Smrg 1208272b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 1208372b676d7Smrg 1208472b676d7Smrg if((pSiS->VBFlags & CRT2_TV) && (pSiS->VBFlags2 & VB2_SISBRIDGE)) { 1208572b676d7Smrg 1208672b676d7Smrg if((val >= -16) && (val <= 16)) { 1208772b676d7Smrg 1208872b676d7Smrg UChar p2_44,p2_45,p2_46; 1208972b676d7Smrg int scalingfactor, mult; 1209072b676d7Smrg 1209172b676d7Smrg p2_44 = pSiS->p2_44; 1209272b676d7Smrg p2_45 = pSiS->p2_45 & 0x3f; 1209372b676d7Smrg p2_46 = pSiS->p2_46 & 0x07; 1209472b676d7Smrg#ifdef SISDUALHEAD 1209572b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) { 1209672b676d7Smrg p2_44 = pSiSEnt->p2_44; 1209772b676d7Smrg p2_45 = pSiSEnt->p2_45 & 0x3f; 1209872b676d7Smrg p2_46 = pSiSEnt->p2_46 & 0x07; 1209972b676d7Smrg } 1210072b676d7Smrg#endif 1210172b676d7Smrg scalingfactor = (p2_46 << 13) | ((p2_45 & 0x1f) << 8) | p2_44; 1210272b676d7Smrg 1210372b676d7Smrg mult = 64; 1210472b676d7Smrg if(pSiS->VBFlags & TV_YPBPR) { 1210572b676d7Smrg if(pSiS->VBFlags & TV_YPBPR1080I) { 1210672b676d7Smrg mult = 190; 1210772b676d7Smrg } else if(pSiS->VBFlags & TV_YPBPR750P) { 1210872b676d7Smrg mult = 360; 1210972b676d7Smrg } 1211072b676d7Smrg } else if(pSiS->VBFlags & TV_HIVISION) { 1211172b676d7Smrg mult = 190; 1211272b676d7Smrg } 1211372b676d7Smrg 1211472b676d7Smrg if(val < 0) { 1211572b676d7Smrg p2_45 &= 0xdf; 1211672b676d7Smrg scalingfactor += ((-val) * mult); 1211772b676d7Smrg if(scalingfactor > 0xffff) scalingfactor = 0xffff; 1211872b676d7Smrg } else if(val > 0) { 1211972b676d7Smrg p2_45 &= 0xdf; 1212072b676d7Smrg scalingfactor -= (val * mult); 1212172b676d7Smrg if(scalingfactor < 1) scalingfactor = 1; 1212272b676d7Smrg } 1212372b676d7Smrg 1212472b676d7Smrg p2_44 = scalingfactor & 0xff; 1212572b676d7Smrg p2_45 &= 0xe0; 1212672b676d7Smrg p2_45 |= ((scalingfactor >> 8) & 0x1f); 1212772b676d7Smrg p2_46 = ((scalingfactor >> 13) & 0x07); 1212872b676d7Smrg 1212972b676d7Smrg SISWaitRetraceCRT2(pScrn); 1213072b676d7Smrg outSISIDXREG(SISPART2,0x44,p2_44); 1213172b676d7Smrg setSISIDXREG(SISPART2,0x45,0xC0,p2_45); 1213272b676d7Smrg if(!(pSiS->VBFlags2 & VB2_301)) { 1213372b676d7Smrg setSISIDXREG(SISPART2,0x46,0xF8,p2_46); 1213472b676d7Smrg } 1213572b676d7Smrg 1213672b676d7Smrg } 1213772b676d7Smrg 1213872b676d7Smrg } 1213972b676d7Smrg 1214072b676d7Smrg } 1214172b676d7Smrg} 1214272b676d7Smrg 1214372b676d7Smrgint SiS_GetTVxscale(ScrnInfoPtr pScrn) 1214472b676d7Smrg{ 1214572b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1214672b676d7Smrg#ifdef SISDUALHEAD 1214772b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1214872b676d7Smrg 1214972b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) 1215072b676d7Smrg return (int)pSiSEnt->tvxscale; 1215172b676d7Smrg else 1215272b676d7Smrg#endif 1215372b676d7Smrg return (int)pSiS->tvxscale; 1215472b676d7Smrg} 1215572b676d7Smrg 1215672b676d7Smrgvoid SiS_SetTVyscale(ScrnInfoPtr pScrn, int val) 1215772b676d7Smrg{ 1215872b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1215972b676d7Smrg#ifdef SISDUALHEAD 1216072b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1216172b676d7Smrg#endif 1216272b676d7Smrg 1216372b676d7Smrg#ifdef UNLOCK_ALWAYS 1216472b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1216572b676d7Smrg#endif 1216672b676d7Smrg 1216772b676d7Smrg if(val < -4) val = -4; 1216872b676d7Smrg if(val > 3) val = 3; 1216972b676d7Smrg 1217072b676d7Smrg pSiS->tvyscale = val; 1217172b676d7Smrg#ifdef SISDUALHEAD 1217272b676d7Smrg if(pSiSEnt) pSiSEnt->tvyscale = val; 1217372b676d7Smrg#endif 1217472b676d7Smrg 1217572b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { 1217672b676d7Smrg 1217772b676d7Smrg if((pSiS->VBFlags & CRT2_TV) && (pSiS->VBFlags2 & VB2_SISBRIDGE)) { 1217872b676d7Smrg 1217972b676d7Smrg int srindex = -1, newvde, i = 0, j, vlimit, temp, vdediv; 1218072b676d7Smrg int hdclk = 0; 1218172b676d7Smrg UChar p3d4_34; 1218272b676d7Smrg Bool found = FALSE; 1218372b676d7Smrg Bool usentsc = FALSE; 1218472b676d7Smrg Bool is750p = FALSE; 1218572b676d7Smrg Bool is1080i = FALSE; 1218672b676d7Smrg Bool skipmoveup = FALSE; 1218772b676d7Smrg 1218872b676d7Smrg SiS_UnLockCRT2(pSiS->SiS_Pr); 1218972b676d7Smrg 1219072b676d7Smrg if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR525P)) { 1219172b676d7Smrg vlimit = 525 - 7; 1219272b676d7Smrg vdediv = 1; 1219372b676d7Smrg usentsc = TRUE; 1219472b676d7Smrg } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR625P)) { 1219572b676d7Smrg vlimit = 625 - 7; 1219672b676d7Smrg vdediv = 1; 1219772b676d7Smrg } else if((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR750P)) { 1219872b676d7Smrg vlimit = 750 - 7; 1219972b676d7Smrg vdediv = 1; 1220072b676d7Smrg is750p = TRUE; 1220172b676d7Smrg } else if(((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR1080I)) || 1220272b676d7Smrg (pSiS->VBFlags & TV_HIVISION)) { 1220372b676d7Smrg vlimit = (1125 - 7) / 2; 1220472b676d7Smrg vdediv = 2; 1220572b676d7Smrg is1080i = TRUE; 1220672b676d7Smrg } else { 1220772b676d7Smrg if( ((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR525I)) || 1220872b676d7Smrg ((!(pSiS->VBFlags & TV_YPBPR)) && (pSiS->VBFlags & (TV_NTSC | TV_PALM))) ) { 1220972b676d7Smrg usentsc = TRUE; 1221072b676d7Smrg } 1221172b676d7Smrg vlimit = usentsc ? 259 : 309; 1221272b676d7Smrg vdediv = 2; 1221372b676d7Smrg } 1221472b676d7Smrg 1221572b676d7Smrg inSISIDXREG(SISCR,0x34,p3d4_34); 1221672b676d7Smrg 1221772b676d7Smrg switch((p3d4_34 & 0x7f)) { 1221872b676d7Smrg case 0x50: /* 320x240 */ 1221972b676d7Smrg case 0x56: 1222072b676d7Smrg case 0x53: 1222172b676d7Smrg hdclk = 1; 1222272b676d7Smrg /* fall through */ 1222372b676d7Smrg case 0x2e: /* 640x480 */ 1222472b676d7Smrg case 0x44: 1222572b676d7Smrg case 0x62: 1222672b676d7Smrg if(is1080i) { 1222772b676d7Smrg srindex = 98; 1222872b676d7Smrg } else if(is750p) { 1222972b676d7Smrg srindex = 42; 1223072b676d7Smrg } else { 1223172b676d7Smrg srindex = usentsc ? 0 : 21; 1223272b676d7Smrg } 1223372b676d7Smrg break; 1223472b676d7Smrg case 0x31: /* 720x480 */ 1223572b676d7Smrg case 0x33: 1223672b676d7Smrg case 0x35: 1223772b676d7Smrg if(is1080i) { 1223872b676d7Smrg /* n/a */ 1223972b676d7Smrg } else if(is750p) { 1224072b676d7Smrg srindex = 49; 1224172b676d7Smrg } else { 1224272b676d7Smrg srindex = usentsc ? 7 : 21; 1224372b676d7Smrg } 1224472b676d7Smrg break; 1224572b676d7Smrg case 0x32: /* 720x576 */ 1224672b676d7Smrg case 0x34: 1224772b676d7Smrg case 0x36: 1224872b676d7Smrg case 0x5f: /* 768x576 */ 1224972b676d7Smrg case 0x60: 1225072b676d7Smrg case 0x61: 1225172b676d7Smrg if(is1080i) { 1225272b676d7Smrg /* n/a */ 1225372b676d7Smrg } else if(is750p) { 1225472b676d7Smrg srindex = 56; 1225572b676d7Smrg } else { 1225672b676d7Smrg srindex = usentsc ? 147 : 28; 1225772b676d7Smrg } 1225872b676d7Smrg break; 1225972b676d7Smrg case 0x70: /* 800x480 */ 1226072b676d7Smrg case 0x7a: 1226172b676d7Smrg case 0x76: 1226272b676d7Smrg if(is1080i) { 1226372b676d7Smrg srindex = 105; 1226472b676d7Smrg } else if(is750p) { 1226572b676d7Smrg srindex = 63; 1226672b676d7Smrg } else { 1226772b676d7Smrg srindex = usentsc ? 175 : 21; 1226872b676d7Smrg } 1226972b676d7Smrg break; 1227072b676d7Smrg case 0x51: /* 400x300 - hdclk mode */ 1227172b676d7Smrg case 0x57: 1227272b676d7Smrg case 0x54: 1227372b676d7Smrg hdclk = 1; 1227472b676d7Smrg /* fall through */ 1227572b676d7Smrg case 0x30: /* 800x600 */ 1227672b676d7Smrg case 0x47: 1227772b676d7Smrg case 0x63: 1227872b676d7Smrg if(is1080i) { 1227972b676d7Smrg srindex = 112; 1228072b676d7Smrg } else if(is750p) { 1228172b676d7Smrg srindex = 70; 1228272b676d7Smrg } else { 1228372b676d7Smrg srindex = usentsc ? 14 : 35; 1228472b676d7Smrg } 1228572b676d7Smrg break; 1228672b676d7Smrg case 0x1d: /* 960x540 */ 1228772b676d7Smrg case 0x1e: 1228872b676d7Smrg case 0x1f: 1228972b676d7Smrg if(is1080i) { 1229072b676d7Smrg srindex = 196; 1229172b676d7Smrg skipmoveup = TRUE; 1229272b676d7Smrg } 1229372b676d7Smrg break; 1229472b676d7Smrg case 0x20: /* 960x600 */ 1229572b676d7Smrg case 0x21: 1229672b676d7Smrg case 0x22: 1229772b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA && is1080i) { 1229872b676d7Smrg srindex = 203; 1229972b676d7Smrg } 1230072b676d7Smrg break; 1230172b676d7Smrg case 0x71: /* 1024x576 */ 1230272b676d7Smrg case 0x74: 1230372b676d7Smrg case 0x77: 1230472b676d7Smrg if(is1080i) { 1230572b676d7Smrg srindex = 119; 1230672b676d7Smrg } else if(is750p) { 1230772b676d7Smrg srindex = 77; 1230872b676d7Smrg } else { 1230972b676d7Smrg srindex = usentsc ? 182 : 189; 1231072b676d7Smrg } 1231172b676d7Smrg break; 1231272b676d7Smrg case 0x52: /* 512x384 */ 1231372b676d7Smrg case 0x58: 1231472b676d7Smrg case 0x5c: 1231572b676d7Smrg hdclk = 1; 1231672b676d7Smrg /* fall through */ 1231772b676d7Smrg case 0x38: /* 1024x768 */ 1231872b676d7Smrg case 0x4a: 1231972b676d7Smrg case 0x64: 1232072b676d7Smrg if(is1080i) { 1232172b676d7Smrg srindex = 126; 1232272b676d7Smrg } else if(is750p) { 1232372b676d7Smrg srindex = 84; 1232472b676d7Smrg } else if(!usentsc) { 1232572b676d7Smrg srindex = 154; 1232672b676d7Smrg } else if(vdediv == 1) { 1232772b676d7Smrg if(!hdclk) srindex = 168; 1232872b676d7Smrg } else { 1232972b676d7Smrg if(!hdclk) srindex = 161; 1233072b676d7Smrg } 1233172b676d7Smrg break; 1233272b676d7Smrg case 0x79: /* 1280x720 */ 1233372b676d7Smrg case 0x75: 1233472b676d7Smrg case 0x78: 1233572b676d7Smrg if(is1080i) { 1233672b676d7Smrg srindex = 133; 1233772b676d7Smrg } else if(is750p) { 1233872b676d7Smrg srindex = 91; 1233972b676d7Smrg } 1234072b676d7Smrg break; 1234172b676d7Smrg case 0x3a: /* 1280x1024 */ 1234272b676d7Smrg case 0x4d: 1234372b676d7Smrg case 0x65: 1234472b676d7Smrg if(is1080i) { 1234572b676d7Smrg srindex = 140; 1234672b676d7Smrg } 1234772b676d7Smrg break; 1234872b676d7Smrg } 1234972b676d7Smrg 1235072b676d7Smrg if(srindex < 0) return; 1235172b676d7Smrg 1235272b676d7Smrg if(pSiS->tvyscale != 0) { 1235372b676d7Smrg for(j = 0; j <= 1; j++) { 1235472b676d7Smrg for(i = 0; i <= 6; i++) { 1235572b676d7Smrg if(SiSTVVScale[srindex+i].sindex == pSiS->tvyscale) { 1235672b676d7Smrg found = TRUE; 1235772b676d7Smrg break; 1235872b676d7Smrg } 1235972b676d7Smrg } 1236072b676d7Smrg if(found) break; 1236172b676d7Smrg if(pSiS->tvyscale > 0) pSiS->tvyscale--; 1236272b676d7Smrg else pSiS->tvyscale++; 1236372b676d7Smrg } 1236472b676d7Smrg } 1236572b676d7Smrg 1236672b676d7Smrg#ifdef SISDUALHEAD 1236772b676d7Smrg if(pSiSEnt) pSiSEnt->tvyscale = pSiS->tvyscale; 1236872b676d7Smrg#endif 1236972b676d7Smrg 1237072b676d7Smrg if(pSiS->tvyscale == 0) { 1237172b676d7Smrg UChar p2_0a = pSiS->p2_0a; 1237272b676d7Smrg UChar p2_2f = pSiS->p2_2f; 1237372b676d7Smrg UChar p2_30 = pSiS->p2_30; 1237472b676d7Smrg UChar p2_46 = pSiS->p2_46; 1237572b676d7Smrg UChar p2_47 = pSiS->p2_47; 1237672b676d7Smrg UChar p1scaling[9], p4scaling[9]; 1237772b676d7Smrg UChar *p2scaling; 1237872b676d7Smrg 1237972b676d7Smrg for(i = 0; i < 9; i++) { 1238072b676d7Smrg p1scaling[i] = pSiS->scalingp1[i]; 1238172b676d7Smrg p4scaling[i] = pSiS->scalingp4[i]; 1238272b676d7Smrg } 1238372b676d7Smrg p2scaling = &pSiS->scalingp2[0]; 1238472b676d7Smrg 1238572b676d7Smrg#ifdef SISDUALHEAD 1238672b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) { 1238772b676d7Smrg p2_0a = pSiSEnt->p2_0a; 1238872b676d7Smrg p2_2f = pSiSEnt->p2_2f; 1238972b676d7Smrg p2_30 = pSiSEnt->p2_30; 1239072b676d7Smrg p2_46 = pSiSEnt->p2_46; 1239172b676d7Smrg p2_47 = pSiSEnt->p2_47; 1239272b676d7Smrg for(i = 0; i < 9; i++) { 1239372b676d7Smrg p1scaling[i] = pSiSEnt->scalingp1[i]; 1239472b676d7Smrg p4scaling[i] = pSiSEnt->scalingp4[i]; 1239572b676d7Smrg } 1239672b676d7Smrg p2scaling = &pSiSEnt->scalingp2[0]; 1239772b676d7Smrg } 1239872b676d7Smrg#endif 1239972b676d7Smrg SISWaitRetraceCRT2(pScrn); 1240072b676d7Smrg if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 1240172b676d7Smrg for(i = 0; i < 64; i++) { 1240272b676d7Smrg outSISIDXREG(SISPART2,(0xc0 + i),p2scaling[i]); 1240372b676d7Smrg } 1240472b676d7Smrg } 1240572b676d7Smrg for(i = 0; i < 9; i++) { 1240672b676d7Smrg outSISIDXREG(SISPART1,SiSScalingP1Regs[i],p1scaling[i]); 1240772b676d7Smrg } 1240872b676d7Smrg for(i = 0; i < 9; i++) { 1240972b676d7Smrg outSISIDXREG(SISPART4,SiSScalingP4Regs[i],p4scaling[i]); 1241072b676d7Smrg } 1241172b676d7Smrg 1241272b676d7Smrg setSISIDXREG(SISPART2,0x0a,0x7f,(p2_0a & 0x80)); 1241372b676d7Smrg outSISIDXREG(SISPART2,0x2f,p2_2f); 1241472b676d7Smrg setSISIDXREG(SISPART2,0x30,0x3f,(p2_30 & 0xc0)); 1241572b676d7Smrg if(!(pSiS->VBFlags2 & VB2_301)) { 1241672b676d7Smrg setSISIDXREG(SISPART2,0x46,0x9f,(p2_46 & 0x60)); 1241772b676d7Smrg outSISIDXREG(SISPART2,0x47,p2_47); 1241872b676d7Smrg } 1241972b676d7Smrg 1242072b676d7Smrg } else { 1242172b676d7Smrg 1242272b676d7Smrg int realvde, myypos, watchdog = 32; 1242372b676d7Smrg unsigned short temp1, temp2, vgahde, vgaht, vgavt; 1242472b676d7Smrg int p1div = 1; 1242572b676d7Smrg ULong calctemp; 1242672b676d7Smrg 1242772b676d7Smrg srindex += i; 1242872b676d7Smrg newvde = SiSTVVScale[srindex].ScaleVDE; 1242972b676d7Smrg realvde = SiSTVVScale[srindex].RealVDE; 1243072b676d7Smrg 1243172b676d7Smrg if(vdediv == 1) p1div = 2; 1243272b676d7Smrg 1243372b676d7Smrg if(!skipmoveup) { 1243472b676d7Smrg do { 1243572b676d7Smrg inSISIDXREG(SISPART2,0x01,temp); 1243672b676d7Smrg temp = vlimit - ((temp & 0x7f) / p1div); 1243772b676d7Smrg if((temp - (((newvde / vdediv) - 2) + 9)) > 0) break; 1243872b676d7Smrg myypos = pSiS->tvypos - 1; 1243972b676d7Smrg#ifdef SISDUALHEAD 1244072b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) myypos = pSiSEnt->tvypos - 1; 1244172b676d7Smrg#endif 1244272b676d7Smrg SiS_SetTVyposoffset(pScrn, myypos); 1244372b676d7Smrg } while(watchdog--); 1244472b676d7Smrg } 1244572b676d7Smrg 1244672b676d7Smrg SISWaitRetraceCRT2(pScrn); 1244772b676d7Smrg 1244872b676d7Smrg if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 1244972b676d7Smrg SiS_CalcXTapScaler(pSiS->SiS_Pr, realvde, newvde, 4, FALSE); 1245072b676d7Smrg } 1245172b676d7Smrg 1245272b676d7Smrg if(!(pSiS->VBFlags2 & VB2_301)) { 1245372b676d7Smrg temp = (newvde / vdediv) - 3; 1245472b676d7Smrg setSISIDXREG(SISPART2,0x46,0x9f,((temp & 0x0300) >> 3)); 1245572b676d7Smrg outSISIDXREG(SISPART2,0x47,(temp & 0xff)); 1245672b676d7Smrg } 1245772b676d7Smrg 1245872b676d7Smrg inSISIDXREG(SISPART1,0x0a,temp1); 1245972b676d7Smrg inSISIDXREG(SISPART1,0x0c,temp2); 1246072b676d7Smrg vgahde = ((temp2 & 0xf0) << 4) | temp1; 1246172b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 1246272b676d7Smrg vgahde -= 12; 1246372b676d7Smrg } else { 1246472b676d7Smrg vgahde -= 16; 1246572b676d7Smrg if(hdclk) vgahde <<= 1; 1246672b676d7Smrg } 1246772b676d7Smrg 1246872b676d7Smrg vgaht = SiSTVVScale[srindex].reg[0]; 1246972b676d7Smrg temp1 = vgaht; 1247072b676d7Smrg if((pSiS->VGAEngine == SIS_315_VGA) && hdclk) temp1 >>= 1; 1247172b676d7Smrg temp1--; 1247272b676d7Smrg outSISIDXREG(SISPART1,0x08,(temp1 & 0xff)); 1247372b676d7Smrg setSISIDXREG(SISPART1,0x09,0x0f,((temp1 >> 4) & 0xf0)); 1247472b676d7Smrg 1247572b676d7Smrg temp2 = (vgaht - vgahde) >> 2; 1247672b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 1247772b676d7Smrg temp1 = vgahde + 12 + temp2; 1247872b676d7Smrg temp2 = temp1 + (temp2 << 1); 1247972b676d7Smrg } else { 1248072b676d7Smrg temp1 = vgahde; 1248172b676d7Smrg if(hdclk) { 1248272b676d7Smrg temp1 >>= 1; 1248372b676d7Smrg temp2 >>= 1; 1248472b676d7Smrg } 1248572b676d7Smrg temp2 >>= 1; 1248672b676d7Smrg temp1 = temp1 + 16 + temp2; 1248772b676d7Smrg temp2 = temp1 + temp2; 1248872b676d7Smrg } 1248972b676d7Smrg outSISIDXREG(SISPART1,0x0b,(temp1 & 0xff)); 1249072b676d7Smrg setSISIDXREG(SISPART1,0x0c,0xf0,((temp1 >> 8) & 0x0f)); 1249172b676d7Smrg outSISIDXREG(SISPART1,0x0d,(temp2 & 0xff)); 1249272b676d7Smrg 1249372b676d7Smrg vgavt = SiSTVVScale[srindex].reg[1]; 1249472b676d7Smrg temp1 = vgavt - 1; 1249572b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) temp1--; 1249672b676d7Smrg outSISIDXREG(SISPART1,0x0e,(temp1 & 0xff)); 1249772b676d7Smrg setSISIDXREG(SISPART1,0x12,0xf8,((temp1 >> 8 ) & 0x07)); 1249872b676d7Smrg if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->ChipType >= SIS_661)) { 1249972b676d7Smrg temp1 = (vgavt + SiSTVVScale[srindex].RealVDE) >> 1; 1250072b676d7Smrg temp2 = ((vgavt - SiSTVVScale[srindex].RealVDE) >> 4) + temp1 + 1; 1250172b676d7Smrg } else { 1250272b676d7Smrg temp1 = (vgavt - SiSTVVScale[srindex].RealVDE) >> 2; 1250372b676d7Smrg temp2 = (temp1 < 4) ? 4 : temp1; 1250472b676d7Smrg temp1 += SiSTVVScale[srindex].RealVDE; 1250572b676d7Smrg temp2 = (temp2 >> 2) + temp1 + 1; 1250672b676d7Smrg } 1250772b676d7Smrg outSISIDXREG(SISPART1,0x10,(temp1 & 0xff)); 1250872b676d7Smrg setSISIDXREG(SISPART1,0x11,0x8f,((temp1 >> 4) & 0x70)); 1250972b676d7Smrg setSISIDXREG(SISPART1,0x11,0xf0,(temp2 & 0x0f)); 1251072b676d7Smrg 1251172b676d7Smrg setSISIDXREG(SISPART2,0x0a,0x7f,((SiSTVVScale[srindex].reg[2] >> 8) & 0x80)); 1251272b676d7Smrg outSISIDXREG(SISPART2,0x2f,((newvde / vdediv) - 2)); 1251372b676d7Smrg setSISIDXREG(SISPART2,0x30,0x3f,((((newvde / vdediv) - 2) >> 2) & 0xc0)); 1251472b676d7Smrg 1251572b676d7Smrg outSISIDXREG(SISPART4,0x13,(SiSTVVScale[srindex].reg[2] & 0xff)); 1251672b676d7Smrg outSISIDXREG(SISPART4,0x14,(SiSTVVScale[srindex].reg[3] & 0xff)); 1251772b676d7Smrg setSISIDXREG(SISPART4,0x15,0x7f,((SiSTVVScale[srindex].reg[3] >> 1) & 0x80)); 1251872b676d7Smrg 1251972b676d7Smrg temp1 = vgaht - 1; 1252072b676d7Smrg outSISIDXREG(SISPART4,0x16,(temp1 & 0xff)); 1252172b676d7Smrg setSISIDXREG(SISPART4,0x15,0x87,((temp1 >> 5) & 0x78)); 1252272b676d7Smrg 1252372b676d7Smrg temp1 = vgavt - 1; 1252472b676d7Smrg outSISIDXREG(SISPART4,0x17,(temp1 & 0xff)); 1252572b676d7Smrg setSISIDXREG(SISPART4,0x15,0xf8,((temp1 >> 8) & 0x07)); 1252672b676d7Smrg 1252772b676d7Smrg outSISIDXREG(SISPART4,0x18,0x00); 1252872b676d7Smrg setSISIDXREG(SISPART4,0x19,0xf0,0x00); 1252972b676d7Smrg 1253072b676d7Smrg inSISIDXREG(SISPART4,0x0e,temp1); 1253172b676d7Smrg if(is1080i) { 1253272b676d7Smrg if(!(temp1 & 0xe0)) newvde >>= 1; 1253372b676d7Smrg } 1253472b676d7Smrg 1253572b676d7Smrg temp = 0x40; 1253672b676d7Smrg if(realvde <= newvde) temp = 0; 1253772b676d7Smrg else realvde -= newvde; 1253872b676d7Smrg 1253972b676d7Smrg calctemp = (realvde * 256 * 1024) / newvde; 1254072b676d7Smrg if((realvde * 256 * 1024) % newvde) calctemp++; 1254172b676d7Smrg outSISIDXREG(SISPART4,0x1b,(calctemp & 0xff)); 1254272b676d7Smrg outSISIDXREG(SISPART4,0x1a,((calctemp >> 8) & 0xff)); 1254372b676d7Smrg setSISIDXREG(SISPART4,0x19,0x8f,(((calctemp >> 12) & 0x70) | temp)); 1254472b676d7Smrg } 1254572b676d7Smrg 1254672b676d7Smrg } 1254772b676d7Smrg 1254872b676d7Smrg } 1254972b676d7Smrg} 1255072b676d7Smrg 1255172b676d7Smrgint SiS_GetTVyscale(ScrnInfoPtr pScrn) 1255272b676d7Smrg{ 1255372b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1255472b676d7Smrg#ifdef SISDUALHEAD 1255572b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1255672b676d7Smrg 1255772b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) 1255872b676d7Smrg return (int)pSiSEnt->tvyscale; 1255972b676d7Smrg else 1256072b676d7Smrg#endif 1256172b676d7Smrg return (int)pSiS->tvyscale; 1256272b676d7Smrg} 1256372b676d7Smrg 1256472b676d7Smrgvoid SiS_SetSISCRT1SaturationGain(ScrnInfoPtr pScrn, int val) 1256572b676d7Smrg{ 1256672b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1256772b676d7Smrg#ifdef SISDUALHEAD 1256872b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1256972b676d7Smrg#endif 1257072b676d7Smrg 1257172b676d7Smrg pSiS->siscrt1satgain = val; 1257272b676d7Smrg#ifdef SISDUALHEAD 1257372b676d7Smrg if(pSiSEnt) pSiSEnt->siscrt1satgain = val; 1257472b676d7Smrg#endif 1257572b676d7Smrg 1257672b676d7Smrg if(!(pSiS->SiS_SD3_Flags & SiS_SD3_CRT1SATGAIN)) return; 1257772b676d7Smrg 1257872b676d7Smrg#ifdef UNLOCK_ALWAYS 1257972b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1258072b676d7Smrg#endif 1258172b676d7Smrg 1258272b676d7Smrg if((val >= 0) && (val <= 7)) { 1258372b676d7Smrg setSISIDXREG(SISCR,0x53,0xE3, (val << 2)); 1258472b676d7Smrg } 1258572b676d7Smrg} 1258672b676d7Smrg 1258772b676d7Smrgint SiS_GetSISCRT1SaturationGain(ScrnInfoPtr pScrn) 1258872b676d7Smrg{ 1258972b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1259072b676d7Smrg int result = pSiS->siscrt1satgain; 1259172b676d7Smrg UChar temp; 1259272b676d7Smrg#ifdef SISDUALHEAD 1259372b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1259472b676d7Smrg 1259572b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) result = pSiSEnt->siscrt1satgain; 1259672b676d7Smrg#endif 1259772b676d7Smrg 1259872b676d7Smrg if(!(pSiS->SiS_SD3_Flags & SiS_SD3_CRT1SATGAIN)) return result; 1259972b676d7Smrg 1260072b676d7Smrg#ifdef UNLOCK_ALWAYS 1260172b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1260272b676d7Smrg#endif 1260372b676d7Smrg inSISIDXREG(SISCR, 0x53, temp); 1260472b676d7Smrg return (int)((temp >> 2) & 0x07); 1260572b676d7Smrg} 1260672b676d7Smrg 1260772b676d7Smrg/* Calc dotclock from registers */ 1260872b676d7Smrgstatic int 1260972b676d7SmrgSiSGetClockFromRegs(UChar sr2b, UChar sr2c) 1261072b676d7Smrg{ 1261172b676d7Smrg float num, denum, postscalar, divider; 1261272b676d7Smrg int myclock; 1261372b676d7Smrg 1261472b676d7Smrg divider = (sr2b & 0x80) ? 2.0 : 1.0; 1261572b676d7Smrg postscalar = (sr2c & 0x80) ? 1261672b676d7Smrg ( (((sr2c >> 5) & 0x03) == 0x02) ? 6.0 : 8.0 ) : 1261772b676d7Smrg ( ((sr2c >> 5) & 0x03) + 1.0 ); 1261872b676d7Smrg num = (sr2b & 0x7f) + 1.0; 1261972b676d7Smrg denum = (sr2c & 0x1f) + 1.0; 1262072b676d7Smrg myclock = (int)((14318 * (divider / postscalar) * (num / denum)) / 1000); 1262172b676d7Smrg return myclock; 1262272b676d7Smrg} 1262372b676d7Smrg 1262472b676d7Smrg#ifdef SISDUALHEAD 1262572b676d7Smrgstatic void 1262672b676d7SmrgSiS_SetDHFlags(SISPtr pSiS, unsigned int misc, unsigned int sd2) 1262772b676d7Smrg{ 1262872b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1262972b676d7Smrg 1263072b676d7Smrg if(pSiS->DualHeadMode) { 1263172b676d7Smrg if(pSiSEnt->pScrn_1) { 1263272b676d7Smrg SISPTR(pSiSEnt->pScrn_1)->MiscFlags |= misc; 1263372b676d7Smrg SISPTR(pSiSEnt->pScrn_1)->SiS_SD2_Flags |= sd2; 1263472b676d7Smrg } 1263572b676d7Smrg if(pSiSEnt->pScrn_2) { 1263672b676d7Smrg SISPTR(pSiSEnt->pScrn_2)->MiscFlags |= misc; 1263772b676d7Smrg SISPTR(pSiSEnt->pScrn_2)->SiS_SD2_Flags |= sd2; 1263872b676d7Smrg } 1263972b676d7Smrg } 1264072b676d7Smrg} 1264172b676d7Smrg#endif 1264272b676d7Smrg 1264372b676d7Smrg/* PostSetMode: 1264472b676d7Smrg * -) Disable CRT1 for saving bandwidth. This doesn't work with VESA; 1264572b676d7Smrg * VESA uses the bridge in SlaveMode and switching CRT1 off while 1264672b676d7Smrg * the bridge is in SlaveMode not that clever... 1264772b676d7Smrg * -) Check if overlay can be used (depending on dotclock) 1264872b676d7Smrg * -) Check if Panel Scaler is active on LVDS for overlay re-scaling 1264972b676d7Smrg * -) Save TV registers for further processing 1265072b676d7Smrg * -) Apply TV settings 1265172b676d7Smrg */ 1265272b676d7Smrgstatic void 1265372b676d7SmrgSiSPostSetMode(ScrnInfoPtr pScrn, SISRegPtr sisReg) 1265472b676d7Smrg{ 1265572b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1265672b676d7Smrg#ifdef SISDUALHEAD 1265772b676d7Smrg SISEntPtr pSiSEnt = pSiS->entityPrivate; 1265872b676d7Smrg#endif 1265972b676d7Smrg UChar usScratchCR17, sr2b, sr2c, tmpreg; 1266072b676d7Smrg int myclock1, myclock2, mycoldepth1, mycoldepth2, temp; 1266172b676d7Smrg Bool flag = FALSE; 1266272b676d7Smrg Bool doit = TRUE; 1266372b676d7Smrg Bool IsInSlaveMode; 1266472b676d7Smrg 1266572b676d7Smrg#ifdef TWDEBUG 1266672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1266772b676d7Smrg "CRT1off is %d\n", pSiS->CRT1off); 1266872b676d7Smrg#endif 1266972b676d7Smrg pSiS->CRT1isoff = pSiS->CRT1off; 1267072b676d7Smrg 1267172b676d7Smrg#ifdef UNLOCK_ALWAYS 1267272b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1267372b676d7Smrg#endif 1267472b676d7Smrg 1267572b676d7Smrg SiSFixupSR11(pScrn); 1267672b676d7Smrg 1267772b676d7Smrg IsInSlaveMode = SiSBridgeIsInSlaveMode(pScrn); 1267872b676d7Smrg 1267972b676d7Smrg if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE)) { 1268072b676d7Smrg 1268172b676d7Smrg if(pSiS->VBFlags != pSiS->VBFlags_backup) { 1268272b676d7Smrg pSiS->VBFlags = pSiS->VBFlags_backup; 1268372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1268472b676d7Smrg "VBFlags restored to %0x\n", pSiS->VBFlags); 1268572b676d7Smrg } 1268672b676d7Smrg 1268772b676d7Smrg /* -) We can't switch off CRT1 if bridge is in SlaveMode. 1268872b676d7Smrg * -) If we change to a SlaveMode-Mode (like 512x384), we 1268972b676d7Smrg * need to adapt VBFlags for eg. Xv. 1269072b676d7Smrg */ 1269172b676d7Smrg#ifdef SISDUALHEAD 1269272b676d7Smrg if(!pSiS->DualHeadMode) { 1269372b676d7Smrg#endif 1269472b676d7Smrg if(IsInSlaveMode) { 1269572b676d7Smrg doit = FALSE; 1269672b676d7Smrg temp = pSiS->VBFlags; 1269772b676d7Smrg pSiS->VBFlags &= (~VB_DISPMODE_SINGLE); 1269872b676d7Smrg pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_DISP1); 1269972b676d7Smrg if(temp != pSiS->VBFlags) { 1270072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1270172b676d7Smrg "VBFlags changed to 0x%0x\n", pSiS->VBFlags); 1270272b676d7Smrg } 1270372b676d7Smrg } 1270472b676d7Smrg#ifdef SISDUALHEAD 1270572b676d7Smrg } 1270672b676d7Smrg#endif 1270772b676d7Smrg 1270872b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 1270972b676d7Smrg 1271072b676d7Smrg if((pSiS->CRT1off) && (doit)) { 1271172b676d7Smrg orSISIDXREG(SISCR,pSiS->myCR63,0x40); 1271272b676d7Smrg orSISIDXREG(SISSR,0x1f,0xc0); 1271372b676d7Smrg andSISIDXREG(SISSR,0x07,~0x10); 1271472b676d7Smrg andSISIDXREG(SISSR,0x06,0xe2); 1271572b676d7Smrg andSISIDXREG(SISSR,0x31,0xcf); 1271672b676d7Smrg outSISIDXREG(SISSR,0x2b,0x1b); 1271772b676d7Smrg outSISIDXREG(SISSR,0x2c,0xe1); 1271872b676d7Smrg outSISIDXREG(SISSR,0x2d,0x01); 1271972b676d7Smrg outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 1272072b676d7Smrg usleep(10000); 1272172b676d7Smrg outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 1272272b676d7Smrg } else { 1272372b676d7Smrg andSISIDXREG(SISCR,pSiS->myCR63,0xBF); 1272472b676d7Smrg andSISIDXREG(SISSR,0x1f,0x3f); 1272572b676d7Smrg orSISIDXREG(SISSR,0x07,0x10); 1272672b676d7Smrg } 1272772b676d7Smrg 1272872b676d7Smrg } else { 1272972b676d7Smrg 1273072b676d7Smrg if(doit) { 1273172b676d7Smrg inSISIDXREG(SISCR, 0x17, usScratchCR17); 1273272b676d7Smrg if(pSiS->CRT1off) { 1273372b676d7Smrg if(usScratchCR17 & 0x80) { 1273472b676d7Smrg flag = TRUE; 1273572b676d7Smrg usScratchCR17 &= ~0x80; 1273672b676d7Smrg } 1273772b676d7Smrg orSISIDXREG(SISSR,0x1f,0xc0); 1273872b676d7Smrg } else { 1273972b676d7Smrg if(!(usScratchCR17 & 0x80)) { 1274072b676d7Smrg flag = TRUE; 1274172b676d7Smrg usScratchCR17 |= 0x80; 1274272b676d7Smrg } 1274372b676d7Smrg andSISIDXREG(SISSR,0x1f,0x3f); 1274472b676d7Smrg } 1274572b676d7Smrg /* Reset only if status changed */ 1274672b676d7Smrg if(flag) { 1274772b676d7Smrg outSISIDXREG(SISCR, 0x17, usScratchCR17); 1274872b676d7Smrg outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 1274972b676d7Smrg usleep(10000); 1275072b676d7Smrg outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 1275172b676d7Smrg } 1275272b676d7Smrg } 1275372b676d7Smrg } 1275472b676d7Smrg 1275572b676d7Smrg } 1275672b676d7Smrg 1275772b676d7Smrg /* Set bridge to "disable CRT2" mode if CRT2 is disabled, LCD-A is enabled */ 1275872b676d7Smrg /* (Not needed for CRT1=VGA since CRT2 will really be disabled then) */ 1275972b676d7Smrg#ifdef SISDUALHEAD 1276072b676d7Smrg if(!pSiS->DualHeadMode) { 1276172b676d7Smrg#endif 1276272b676d7Smrg if((pSiS->VGAEngine == SIS_315_VGA) && (pSiS->VBFlags2 & VB2_SISLCDABRIDGE)) { 1276372b676d7Smrg if((!pSiS->UseVESA) && (!(pSiS->VBFlags & CRT2_ENABLE)) && (pSiS->VBFlags & CRT1_LCDA)) { 1276472b676d7Smrg if(!IsInSlaveMode) { 1276572b676d7Smrg andSISIDXREG(SISPART4,0x0d,~0x07); 1276672b676d7Smrg } 1276772b676d7Smrg } 1276872b676d7Smrg } 1276972b676d7Smrg#ifdef SISDUALHEAD 1277072b676d7Smrg } 1277172b676d7Smrg#endif 1277272b676d7Smrg 1277372b676d7Smrg /* Reset flags */ 1277472b676d7Smrg pSiS->MiscFlags &= ~( MISC_CRT1OVERLAY | 1277572b676d7Smrg MISC_CRT2OVERLAY | 1277672b676d7Smrg MISC_CRT1OVERLAYGAMMA | 1277772b676d7Smrg MISC_SIS760ONEOVERLAY | 1277872b676d7Smrg MISC_PANELLINKSCALER | 1277972b676d7Smrg MISC_STNMODE | 1278072b676d7Smrg MISC_TVNTSC1024); 1278172b676d7Smrg 1278272b676d7Smrg pSiS->SiS_SD2_Flags &= ~SiS_SD2_SIS760ONEOVL; 1278372b676d7Smrg 1278472b676d7Smrg#ifdef SISDUALHEAD 1278572b676d7Smrg if(pSiS->DualHeadMode) { 1278672b676d7Smrg if(pSiSEnt->pScrn_1) { 1278772b676d7Smrg SISPTR(pSiSEnt->pScrn_1)->MiscFlags &= ~(MISC_SIS760ONEOVERLAY | 1278872b676d7Smrg MISC_CRT1OVERLAY | 1278972b676d7Smrg MISC_CRT2OVERLAY | 1279072b676d7Smrg MISC_CRT1OVERLAYGAMMA | 1279172b676d7Smrg MISC_PANELLINKSCALER | 1279272b676d7Smrg MISC_STNMODE | 1279372b676d7Smrg MISC_TVNTSC1024); 1279472b676d7Smrg SISPTR(pSiSEnt->pScrn_1)->SiS_SD2_Flags &= ~SiS_SD2_SIS760ONEOVL; 1279572b676d7Smrg } 1279672b676d7Smrg if(pSiSEnt->pScrn_2) { 1279772b676d7Smrg SISPTR(pSiSEnt->pScrn_2)->MiscFlags &= ~(MISC_SIS760ONEOVERLAY | 1279872b676d7Smrg MISC_CRT1OVERLAY | 1279972b676d7Smrg MISC_CRT2OVERLAY | 1280072b676d7Smrg MISC_CRT1OVERLAYGAMMA | 1280172b676d7Smrg MISC_PANELLINKSCALER | 1280272b676d7Smrg MISC_STNMODE | 1280372b676d7Smrg MISC_TVNTSC1024); 1280472b676d7Smrg SISPTR(pSiSEnt->pScrn_2)->SiS_SD2_Flags &= ~SiS_SD2_SIS760ONEOVL; 1280572b676d7Smrg } 1280672b676d7Smrg } 1280772b676d7Smrg#endif 1280872b676d7Smrg 1280972b676d7Smrg /* Determine if the video overlay can be used */ 1281072b676d7Smrg if(!pSiS->NoXvideo) { 1281172b676d7Smrg 1281272b676d7Smrg int clklimit1=0, clklimit2=0, clklimitg=0; 1281372b676d7Smrg Bool OverlayHandled = FALSE; 1281472b676d7Smrg 1281572b676d7Smrg inSISIDXREG(SISSR,0x2b,sr2b); 1281672b676d7Smrg inSISIDXREG(SISSR,0x2c,sr2c); 1281772b676d7Smrg myclock1 = myclock2 = SiSGetClockFromRegs(sr2b, sr2c); 1281872b676d7Smrg inSISIDXREG(SISSR,0x06,tmpreg); 1281972b676d7Smrg switch((tmpreg & 0x1c) >> 2) { 1282072b676d7Smrg case 0: mycoldepth1 = 1; break; 1282172b676d7Smrg case 1: 1282272b676d7Smrg case 2: mycoldepth1 = 2; break; 1282372b676d7Smrg default: mycoldepth1 = 4; 1282472b676d7Smrg } 1282572b676d7Smrg mycoldepth2 = mycoldepth1; 1282672b676d7Smrg 1282772b676d7Smrg if((!IsInSlaveMode) && (pSiS->VBFlags & CRT2_ENABLE)) { 1282872b676d7Smrg if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 1282972b676d7Smrg inSISIDXREG(SISPART4,0x0a,sr2b); 1283072b676d7Smrg inSISIDXREG(SISPART4,0x0b,sr2c); 1283172b676d7Smrg } else { 1283272b676d7Smrg inSISIDXREG(SISSR,0x2e,sr2b); 1283372b676d7Smrg inSISIDXREG(SISSR,0x2f,sr2c); 1283472b676d7Smrg } 1283572b676d7Smrg myclock2 = SiSGetClockFromRegs(sr2b, sr2c); 1283672b676d7Smrg inSISIDXREG(SISPART1,0x00,tmpreg); 1283772b676d7Smrg tmpreg &= 0x0f; 1283872b676d7Smrg switch(tmpreg) { 1283972b676d7Smrg case 8: mycoldepth2 = 1; break; 1284072b676d7Smrg case 4: 1284172b676d7Smrg case 2: mycoldepth2 = 2; break; 1284272b676d7Smrg default: mycoldepth2 = 4; 1284372b676d7Smrg } 1284472b676d7Smrg } 1284572b676d7Smrg 1284672b676d7Smrg switch(pSiS->ChipType) { 1284772b676d7Smrg 1284872b676d7Smrg case SIS_300: 1284972b676d7Smrg case SIS_540: 1285072b676d7Smrg case SIS_630: 1285172b676d7Smrg case SIS_730: 1285272b676d7Smrg clklimit1 = clklimit2 = clklimitg = 150; 1285372b676d7Smrg break; 1285472b676d7Smrg 1285572b676d7Smrg case SIS_550: 1285672b676d7Smrg case SIS_650: 1285772b676d7Smrg case SIS_740: 1285872b676d7Smrg clklimit1 = clklimit2 = 175; /* verified for 65x */ 1285972b676d7Smrg clklimitg = 166; /* ? */ 1286072b676d7Smrg break; 1286172b676d7Smrg 1286272b676d7Smrg case SIS_661: 1286372b676d7Smrg case SIS_741: 1286472b676d7Smrg clklimit1 = clklimit2 = 190; /* ? */ 1286572b676d7Smrg clklimitg = 180; /* ? */ 1286672b676d7Smrg break; 1286772b676d7Smrg 1286872b676d7Smrg case SIS_760: 1286972b676d7Smrg case SIS_761: 1287072b676d7Smrg clklimit1 = clklimit2 = 190; /* ? */ 1287172b676d7Smrg if(pSiS->ChipFlags & SiSCF_760LFB) { /* LFB only or hybrid */ 1287272b676d7Smrg clklimit1 = clklimit2 = 220; /* ? */ 1287372b676d7Smrg } 1287472b676d7Smrg clklimitg = 200; /* ? */ 1287572b676d7Smrg 1287672b676d7Smrg if(pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORT760OO) { /* UMA only */ 1287772b676d7Smrg 1287872b676d7Smrg Bool OnlyOne = FALSE, NoOverlay = FALSE; 1287972b676d7Smrg int dotclocksum = 0; 1288072b676d7Smrg 1288172b676d7Smrg if(pSiS->VBFlags & DISPTYPE_CRT1) dotclocksum += myclock1; 1288272b676d7Smrg if((!IsInSlaveMode) && (pSiS->VBFlags & CRT2_ENABLE)) dotclocksum += myclock2; 1288372b676d7Smrg 1288472b676d7Smrg /* TODO: Find out under what circumstances only one 1288572b676d7Smrg * overlay is usable in UMA-only mode. 1288672b676d7Smrg * This is not entirely accurate; the overlay 1288772b676d7Smrg * scaler also requires some time, so even though 1288872b676d7Smrg * the dotclocks are below these values, some 1288972b676d7Smrg * distortions in the overlay may occure. 1289072b676d7Smrg * Solution: Don't use a 760 with shared memory. 1289172b676d7Smrg */ 1289272b676d7Smrg if( (pSiS->VBFlags & DISPTYPE_CRT1) && 1289372b676d7Smrg (pSiS->VBFlags & CRT2_ENABLE) && 1289472b676d7Smrg (mycoldepth1 != mycoldepth2) ) { 1289572b676d7Smrg 1289672b676d7Smrg /* 0. If coldepths are different (only possible in dual head mode), 1289772b676d7Smrg * I have no idea to calculate the limits; hence, allow only one 1289872b676d7Smrg * overlay in all cases. 1289972b676d7Smrg */ 1290072b676d7Smrg OnlyOne = TRUE; 1290172b676d7Smrg 1290272b676d7Smrg } else if(pSiS->MemClock < 150000) { 1290372b676d7Smrg 1290472b676d7Smrg /* 1. MCLK <150: If someone seriously considers using such 1290572b676d7Smrg * slow RAM, so be it. Only one overlay in call cases. 1290672b676d7Smrg */ 1290772b676d7Smrg OnlyOne = TRUE; 1290872b676d7Smrg 1290972b676d7Smrg } else if(pSiS->MemClock < 170000) { 1291072b676d7Smrg 1291172b676d7Smrg /* 2. MCLK 166 */ 1291272b676d7Smrg switch(pSiS->CurrentLayout.bitsPerPixel) { 1291372b676d7Smrg case 32: if(dotclocksum > 133) OnlyOne = TRUE; /* One overlay; verified */ 1291472b676d7Smrg if(dotclocksum > 180) NoOverlay = TRUE; /* No overlay; verified */ 1291572b676d7Smrg break; 1291672b676d7Smrg case 16: if(dotclocksum > 175) OnlyOne = TRUE; /* One overlay; verified */ 1291772b676d7Smrg if(dotclocksum > 260) NoOverlay = TRUE;; /* No overlay; FIXME */ 1291872b676d7Smrg break; 1291972b676d7Smrg } 1292072b676d7Smrg 1292172b676d7Smrg } else if(pSiS->MemClock < 210000) { 1292272b676d7Smrg 1292372b676d7Smrg /* 3. MCLK 200 */ 1292472b676d7Smrg switch(pSiS->CurrentLayout.bitsPerPixel) { 1292572b676d7Smrg case 32: if(dotclocksum > 160) OnlyOne = TRUE; /* One overlay; FIXME */ 1292672b676d7Smrg if(dotclocksum > 216) NoOverlay = TRUE;; /* No overlay; FIXME */ 1292772b676d7Smrg break; 1292872b676d7Smrg case 16: if(dotclocksum > 210) OnlyOne = TRUE; /* One overlay; FIXME */ 1292972b676d7Smrg if(dotclocksum > 312) NoOverlay = TRUE;; /* No overlay; FIXME */ 1293072b676d7Smrg break; 1293172b676d7Smrg } 1293272b676d7Smrg 1293372b676d7Smrg } 1293472b676d7Smrg 1293572b676d7Smrg if(OnlyOne || NoOverlay) { 1293672b676d7Smrg 1293772b676d7Smrg ULong tmpflags = 0; 1293872b676d7Smrg 1293972b676d7Smrg if(!NoOverlay) { 1294072b676d7Smrg if(myclock1 <= clklimit1) tmpflags |= MISC_CRT1OVERLAY; 1294172b676d7Smrg if(myclock2 <= clklimit2) tmpflags |= MISC_CRT2OVERLAY; 1294272b676d7Smrg if(myclock1 <= clklimitg) tmpflags |= MISC_CRT1OVERLAYGAMMA; 1294372b676d7Smrg pSiS->MiscFlags |= tmpflags; 1294472b676d7Smrg } 1294572b676d7Smrg pSiS->MiscFlags |= MISC_SIS760ONEOVERLAY; 1294672b676d7Smrg pSiS->SiS_SD2_Flags |= SiS_SD2_SIS760ONEOVL; 1294772b676d7Smrg#ifdef SISDUALHEAD 1294872b676d7Smrg SiS_SetDHFlags(pSiS, (tmpflags | MISC_SIS760ONEOVERLAY), SiS_SD2_SIS760ONEOVL); 1294972b676d7Smrg#endif 1295072b676d7Smrg OverlayHandled = TRUE; 1295172b676d7Smrg } 1295272b676d7Smrg 1295372b676d7Smrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 1295472b676d7Smrg "SiS76x/UMA: %s video overlay(s) available in current mode\n", 1295572b676d7Smrg NoOverlay ? "no" : ((pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) ? "one" : "two")); 1295672b676d7Smrg 1295772b676d7Smrg#ifdef TWDEBUG 1295872b676d7Smrg xf86DrvMsg(0, 0, "SiS760: Memclock %d, c1 %d/%d c2 %d/%d, sum %d / %x\n", 1295972b676d7Smrg pSiS->MemClock, myclock1, mycoldepth1, 1296072b676d7Smrg myclock2, mycoldepth2, dotclocksum, pSiS->SiS_SD2_Flags); 1296172b676d7Smrg#endif 1296272b676d7Smrg } 1296372b676d7Smrg break; 1296472b676d7Smrg 1296572b676d7Smrg case SIS_660: 1296672b676d7Smrg clklimit1 = clklimit2 = 200; /* ? */ 1296772b676d7Smrg if(pSiS->ChipFlags & SiSCF_760LFB) { /* LFB only */ 1296872b676d7Smrg clklimit1 = clklimit2 = 220; 1296972b676d7Smrg } 1297072b676d7Smrg clklimitg = 200; /* ? */ 1297172b676d7Smrg break; 1297272b676d7Smrg 1297372b676d7Smrg case SIS_315H: 1297472b676d7Smrg case SIS_315: 1297572b676d7Smrg case SIS_315PRO: 1297672b676d7Smrg case SIS_330: 1297772b676d7Smrg clklimit1 = clklimit2 = 180; /* ? */ 1297872b676d7Smrg clklimitg = 166; /* ? */ 1297972b676d7Smrg break; 1298072b676d7Smrg 1298172b676d7Smrg case SIS_340: /* ? */ 1298272b676d7Smrg case XGI_20: 1298372b676d7Smrg case XGI_40: 1298472b676d7Smrg clklimit1 = clklimit2 = 240; /* ? */ 1298572b676d7Smrg clklimitg = 200; /* ? */ 1298672b676d7Smrg break; 1298772b676d7Smrg } 1298872b676d7Smrg 1298972b676d7Smrg if(!OverlayHandled) { 1299072b676d7Smrg ULong tmpflags = 0; 1299172b676d7Smrg if(myclock1 <= clklimit1) tmpflags |= MISC_CRT1OVERLAY; 1299272b676d7Smrg if(myclock2 <= clklimit2) tmpflags |= MISC_CRT2OVERLAY; 1299372b676d7Smrg if(myclock1 <= clklimitg) tmpflags |= MISC_CRT1OVERLAYGAMMA; 1299472b676d7Smrg pSiS->MiscFlags |= tmpflags; 1299572b676d7Smrg#ifdef SISDUALHEAD 1299672b676d7Smrg SiS_SetDHFlags(pSiS, tmpflags, 0); 1299772b676d7Smrg#endif 1299872b676d7Smrg if(!(pSiS->MiscFlags & MISC_CRT1OVERLAY)) { 1299972b676d7Smrg#ifdef SISDUALHEAD 1300072b676d7Smrg if((!pSiS->DualHeadMode) || (pSiS->SecondHead)) 1300172b676d7Smrg#endif 1300272b676d7Smrg xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, 3, 1300372b676d7Smrg "Current dotclock (%dMhz) too high for video overlay on CRT1\n", 1300472b676d7Smrg myclock1); 1300572b676d7Smrg } 1300672b676d7Smrg if((pSiS->VBFlags & CRT2_ENABLE) && (!(pSiS->MiscFlags & MISC_CRT2OVERLAY))) { 1300772b676d7Smrg#ifdef SISDUALHEAD 1300872b676d7Smrg if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) 1300972b676d7Smrg#endif 1301072b676d7Smrg xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, 3, 1301172b676d7Smrg "Current dotclock (%dMhz) too high for video overlay on CRT2\n", 1301272b676d7Smrg myclock2); 1301372b676d7Smrg } 1301472b676d7Smrg } 1301572b676d7Smrg 1301672b676d7Smrg } 1301772b676d7Smrg 1301872b676d7Smrg /* Determine if the Panel Link scaler is active */ 1301972b676d7Smrg 1302072b676d7Smrg if(pSiS->VBFlags & (CRT2_LCD | CRT1_LCDA)) { 1302172b676d7Smrg ULong tmpflags = 0; 1302272b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 1302372b676d7Smrg if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) { 1302472b676d7Smrg inSISIDXREG(SISPART1,0x1e,tmpreg); 1302572b676d7Smrg tmpreg &= 0x3f; 1302672b676d7Smrg if(tmpreg) tmpflags |= MISC_PANELLINKSCALER; 1302772b676d7Smrg } 1302872b676d7Smrg } else { 1302972b676d7Smrg if((pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) || (pSiS->VBFlags & CRT1_LCDA)) { 1303072b676d7Smrg inSISIDXREG(SISPART1,0x35,tmpreg); 1303172b676d7Smrg tmpreg &= 0x04; 1303272b676d7Smrg if(!tmpreg) tmpflags |= MISC_PANELLINKSCALER; 1303372b676d7Smrg } 1303472b676d7Smrg } 1303572b676d7Smrg pSiS->MiscFlags |= tmpflags; 1303672b676d7Smrg#ifdef SISDUALHEAD 1303772b676d7Smrg SiS_SetDHFlags(pSiS, tmpflags, 0); 1303872b676d7Smrg#endif 1303972b676d7Smrg } 1304072b676d7Smrg 1304172b676d7Smrg /* Determine if STN is active */ 1304272b676d7Smrg if(pSiS->ChipType == SIS_550) { 1304372b676d7Smrg if((pSiS->VBFlags & CRT2_LCD) && (pSiS->FSTN || pSiS->DSTN)) { 1304472b676d7Smrg inSISIDXREG(SISCR,0x34,tmpreg); 1304572b676d7Smrg tmpreg &= 0x7f; 1304672b676d7Smrg if(tmpreg == 0x5a || tmpreg == 0x5b) { 1304772b676d7Smrg pSiS->MiscFlags |= MISC_STNMODE; 1304872b676d7Smrg#ifdef SISDUALHEAD 1304972b676d7Smrg SiS_SetDHFlags(pSiS, MISC_STNMODE, 0); 1305072b676d7Smrg#endif 1305172b676d7Smrg } 1305272b676d7Smrg } 1305372b676d7Smrg } 1305472b676d7Smrg 1305572b676d7Smrg /* Determine if our very special TV mode is active */ 1305672b676d7Smrg if((pSiS->VBFlags2 & VB2_SISBRIDGE) && (pSiS->VBFlags & CRT2_TV) && (!(pSiS->VBFlags & TV_HIVISION))) { 1305772b676d7Smrg if( ((pSiS->VBFlags & TV_YPBPR) && (pSiS->VBFlags & TV_YPBPR525I)) || 1305872b676d7Smrg ((!(pSiS->VBFlags & TV_YPBPR)) && (pSiS->VBFlags & (TV_NTSC | TV_PALM))) ) { 1305972b676d7Smrg inSISIDXREG(SISCR,0x34,tmpreg); 1306072b676d7Smrg tmpreg &= 0x7f; 1306172b676d7Smrg if((tmpreg == 0x64) || (tmpreg == 0x4a) || (tmpreg == 0x38)) { 1306272b676d7Smrg pSiS->MiscFlags |= MISC_TVNTSC1024; 1306372b676d7Smrg#ifdef SISDUALHEAD 1306472b676d7Smrg SiS_SetDHFlags(pSiS, MISC_TVNTSC1024, 0); 1306572b676d7Smrg#endif 1306672b676d7Smrg } 1306772b676d7Smrg } 1306872b676d7Smrg } 1306972b676d7Smrg 1307072b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 1307172b676d7Smrg int i; 1307272b676d7Smrg#ifdef SISVRAMQ 1307372b676d7Smrg /* Re-Enable and reset command queue */ 1307472b676d7Smrg SiSEnableTurboQueue(pScrn); 1307572b676d7Smrg#endif 1307672b676d7Smrg /* Get HWCursor register contents for backup */ 1307772b676d7Smrg for(i = 0; i < 16; i++) { 1307872b676d7Smrg pSiS->HWCursorBackup[i] = SIS_MMIO_IN32(pSiS->IOBase, 0x8500 + (i << 2)); 1307972b676d7Smrg } 1308072b676d7Smrg if(pSiS->ChipType >= SIS_330) { 1308172b676d7Smrg /* Enable HWCursor protection (Y pos as trigger) */ 1308272b676d7Smrg andSISIDXREG(SISCR, 0x5b, ~0x30); 1308372b676d7Smrg } 1308472b676d7Smrg } 1308572b676d7Smrg 1308672b676d7Smrg /* Re-initialize accelerator engine */ 1308772b676d7Smrg /* (We are sync'ed here) */ 1308872b676d7Smrg if(!pSiS->NoAccel) { 1308972b676d7Smrg if(pSiS->InitAccel) { 1309072b676d7Smrg (pSiS->InitAccel)(pScrn); 1309172b676d7Smrg } 1309272b676d7Smrg } 1309372b676d7Smrg 1309472b676d7Smrg /* Set display device gamma (for SISCTRL) */ 1309572b676d7Smrg if(pSiS->VBFlags & CRT1_LCDA) 1309672b676d7Smrg pSiS->CRT1MonGamma = pSiS->CRT2LCDMonitorGamma; 1309772b676d7Smrg else 1309872b676d7Smrg pSiS->CRT1MonGamma = pSiS->CRT1VGAMonitorGamma; 1309972b676d7Smrg 1310072b676d7Smrg if(pSiS->VBFlags & CRT2_LCD) 1310172b676d7Smrg pSiS->CRT2MonGamma = pSiS->CRT2LCDMonitorGamma; 1310272b676d7Smrg else if(pSiS->VBFlags & CRT2_TV) { 1310372b676d7Smrg if(pSiS->VBFlags & TV_YPBPR) 1310472b676d7Smrg pSiS->CRT2MonGamma = 2200; /* */ 1310572b676d7Smrg else if(pSiS->VBFlags & TV_HIVISION) 1310672b676d7Smrg pSiS->CRT2MonGamma = 2200; /* ? */ 1310772b676d7Smrg else if(pSiS->VBFlags & TV_NTSC) 1310872b676d7Smrg pSiS->CRT2MonGamma = 2200; /* NTSC */ 1310972b676d7Smrg else 1311072b676d7Smrg pSiS->CRT2MonGamma = 2800; /* All PAL modes? */ 1311172b676d7Smrg } else if(pSiS->VBFlags & CRT2_VGA) 1311272b676d7Smrg pSiS->CRT2MonGamma = pSiS->CRT2VGAMonitorGamma; 1311372b676d7Smrg else 1311472b676d7Smrg pSiS->CRT2MonGamma = 0; /* Unknown */ 1311572b676d7Smrg 1311672b676d7Smrg /* Reset XV display properties (such as number of overlays, etc) */ 1311772b676d7Smrg /* (And copy monitor gamma) */ 1311872b676d7Smrg#ifdef SISDUALHEAD 1311972b676d7Smrg if(pSiS->DualHeadMode) { 1312072b676d7Smrg if(pSiSEnt->pScrn_1) { 1312172b676d7Smrg if(SISPTR(pSiSEnt->pScrn_1)->ResetXvDisplay) { 1312272b676d7Smrg (SISPTR(pSiSEnt->pScrn_1)->ResetXvDisplay)(pSiSEnt->pScrn_1); 1312372b676d7Smrg } 1312472b676d7Smrg SISPTR(pSiSEnt->pScrn_1)->CRT1MonGamma = pSiS->CRT1MonGamma; 1312572b676d7Smrg SISPTR(pSiSEnt->pScrn_1)->CRT2MonGamma = pSiS->CRT2MonGamma; 1312672b676d7Smrg } 1312772b676d7Smrg if(pSiSEnt->pScrn_2) { 1312872b676d7Smrg if(SISPTR(pSiSEnt->pScrn_2)->ResetXvDisplay) { 1312972b676d7Smrg (SISPTR(pSiSEnt->pScrn_1)->ResetXvDisplay)(pSiSEnt->pScrn_2); 1313072b676d7Smrg } 1313172b676d7Smrg SISPTR(pSiSEnt->pScrn_2)->CRT1MonGamma = pSiS->CRT1MonGamma; 1313272b676d7Smrg SISPTR(pSiSEnt->pScrn_2)->CRT2MonGamma = pSiS->CRT2MonGamma; 1313372b676d7Smrg } 1313472b676d7Smrg } else { 1313572b676d7Smrg#endif 1313672b676d7Smrg if(pSiS->ResetXvDisplay) { 1313772b676d7Smrg (pSiS->ResetXvDisplay)(pScrn); 1313872b676d7Smrg } 1313972b676d7Smrg#ifdef SISDUALHEAD 1314072b676d7Smrg } 1314172b676d7Smrg#endif 1314272b676d7Smrg 1314372b676d7Smrg /* Reset XV gamma correction */ 1314472b676d7Smrg if(pSiS->ResetXvGamma) { 1314572b676d7Smrg (pSiS->ResetXvGamma)(pScrn); 1314672b676d7Smrg } 1314772b676d7Smrg 1314872b676d7Smrg /* Reset various display parameters */ 1314972b676d7Smrg { 1315072b676d7Smrg int val = pSiS->siscrt1satgain; 1315172b676d7Smrg#ifdef SISDUALHEAD 1315272b676d7Smrg if(pSiS->DualHeadMode && pSiSEnt) val = pSiSEnt->siscrt1satgain; 1315372b676d7Smrg#endif 1315472b676d7Smrg SiS_SetSISCRT1SaturationGain(pScrn, val); 1315572b676d7Smrg } 1315672b676d7Smrg 1315772b676d7Smrg /* Apply TV settings given by options 1315872b676d7Smrg Do this even in DualHeadMode: 1315972b676d7Smrg - if this is called by SetModeCRT1, CRT2 mode has been reset by SetModeCRT1 1316072b676d7Smrg - if this is called by SetModeCRT2, CRT2 mode has changed (duh!) 1316172b676d7Smrg -> Hence, in both cases, the settings must be re-applied. 1316272b676d7Smrg */ 1316372b676d7Smrg 1316472b676d7Smrg if(pSiS->VBFlags & CRT2_TV) { 1316572b676d7Smrg int val; 1316672b676d7Smrg if(pSiS->VBFlags2 & VB2_CHRONTEL) { 1316772b676d7Smrg int mychtvlumabandwidthcvbs = pSiS->chtvlumabandwidthcvbs; 1316872b676d7Smrg int mychtvlumabandwidthsvideo = pSiS->chtvlumabandwidthsvideo; 1316972b676d7Smrg int mychtvlumaflickerfilter = pSiS->chtvlumaflickerfilter; 1317072b676d7Smrg int mychtvchromabandwidth = pSiS->chtvchromabandwidth; 1317172b676d7Smrg int mychtvchromaflickerfilter = pSiS->chtvchromaflickerfilter; 1317272b676d7Smrg int mychtvcvbscolor = pSiS->chtvcvbscolor; 1317372b676d7Smrg int mychtvtextenhance = pSiS->chtvtextenhance; 1317472b676d7Smrg int mychtvcontrast = pSiS->chtvcontrast; 1317572b676d7Smrg int mytvxpos = pSiS->tvxpos; 1317672b676d7Smrg int mytvypos = pSiS->tvypos; 1317772b676d7Smrg#ifdef SISDUALHEAD 1317872b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) { 1317972b676d7Smrg mychtvlumabandwidthcvbs = pSiSEnt->chtvlumabandwidthcvbs; 1318072b676d7Smrg mychtvlumabandwidthsvideo = pSiSEnt->chtvlumabandwidthsvideo; 1318172b676d7Smrg mychtvlumaflickerfilter = pSiSEnt->chtvlumaflickerfilter; 1318272b676d7Smrg mychtvchromabandwidth = pSiSEnt->chtvchromabandwidth; 1318372b676d7Smrg mychtvchromaflickerfilter = pSiSEnt->chtvchromaflickerfilter; 1318472b676d7Smrg mychtvcvbscolor = pSiSEnt->chtvcvbscolor; 1318572b676d7Smrg mychtvtextenhance = pSiSEnt->chtvtextenhance; 1318672b676d7Smrg mychtvcontrast = pSiSEnt->chtvcontrast; 1318772b676d7Smrg mytvxpos = pSiSEnt->tvxpos; 1318872b676d7Smrg mytvypos = pSiSEnt->tvypos; 1318972b676d7Smrg } 1319072b676d7Smrg#endif 1319172b676d7Smrg if((val = mychtvlumabandwidthcvbs) != -1) { 1319272b676d7Smrg SiS_SetCHTVlumabandwidthcvbs(pScrn, val); 1319372b676d7Smrg } 1319472b676d7Smrg if((val = mychtvlumabandwidthsvideo) != -1) { 1319572b676d7Smrg SiS_SetCHTVlumabandwidthsvideo(pScrn, val); 1319672b676d7Smrg } 1319772b676d7Smrg if((val = mychtvlumaflickerfilter) != -1) { 1319872b676d7Smrg SiS_SetCHTVlumaflickerfilter(pScrn, val); 1319972b676d7Smrg } 1320072b676d7Smrg if((val = mychtvchromabandwidth) != -1) { 1320172b676d7Smrg SiS_SetCHTVchromabandwidth(pScrn, val); 1320272b676d7Smrg } 1320372b676d7Smrg if((val = mychtvchromaflickerfilter) != -1) { 1320472b676d7Smrg SiS_SetCHTVchromaflickerfilter(pScrn, val); 1320572b676d7Smrg } 1320672b676d7Smrg if((val = mychtvcvbscolor) != -1) { 1320772b676d7Smrg SiS_SetCHTVcvbscolor(pScrn, val); 1320872b676d7Smrg } 1320972b676d7Smrg if((val = mychtvtextenhance) != -1) { 1321072b676d7Smrg SiS_SetCHTVtextenhance(pScrn, val); 1321172b676d7Smrg } 1321272b676d7Smrg if((val = mychtvcontrast) != -1) { 1321372b676d7Smrg SiS_SetCHTVcontrast(pScrn, val); 1321472b676d7Smrg } 1321572b676d7Smrg /* Backup default TV position registers */ 1321672b676d7Smrg switch(pSiS->ChrontelType) { 1321772b676d7Smrg case CHRONTEL_700x: 1321872b676d7Smrg pSiS->tvx = SiS_GetCH700x(pSiS->SiS_Pr, 0x0a); 1321972b676d7Smrg pSiS->tvx |= (((SiS_GetCH700x(pSiS->SiS_Pr, 0x08) & 0x02) >> 1) << 8); 1322072b676d7Smrg pSiS->tvy = SiS_GetCH700x(pSiS->SiS_Pr, 0x0b); 1322172b676d7Smrg pSiS->tvy |= ((SiS_GetCH700x(pSiS->SiS_Pr, 0x08) & 0x01) << 8); 1322272b676d7Smrg#ifdef SISDUALHEAD 1322372b676d7Smrg if(pSiSEnt) { 1322472b676d7Smrg pSiSEnt->tvx = pSiS->tvx; 1322572b676d7Smrg pSiSEnt->tvy = pSiS->tvy; 1322672b676d7Smrg } 1322772b676d7Smrg#endif 1322872b676d7Smrg break; 1322972b676d7Smrg case CHRONTEL_701x: 1323072b676d7Smrg /* Not supported by hardware */ 1323172b676d7Smrg break; 1323272b676d7Smrg } 1323372b676d7Smrg if((val = mytvxpos) != 0) { 1323472b676d7Smrg SiS_SetTVxposoffset(pScrn, val); 1323572b676d7Smrg } 1323672b676d7Smrg if((val = mytvypos) != 0) { 1323772b676d7Smrg SiS_SetTVyposoffset(pScrn, val); 1323872b676d7Smrg } 1323972b676d7Smrg } 1324072b676d7Smrg if(pSiS->VBFlags2 & VB2_301) { 1324172b676d7Smrg int mysistvedgeenhance = pSiS->sistvedgeenhance; 1324272b676d7Smrg#ifdef SISDUALHEAD 1324372b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) { 1324472b676d7Smrg mysistvedgeenhance = pSiSEnt->sistvedgeenhance; 1324572b676d7Smrg } 1324672b676d7Smrg#endif 1324772b676d7Smrg if((val = mysistvedgeenhance) != -1) { 1324872b676d7Smrg SiS_SetSISTVedgeenhance(pScrn, val); 1324972b676d7Smrg } 1325072b676d7Smrg } 1325172b676d7Smrg if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 1325272b676d7Smrg int mysistvantiflicker = pSiS->sistvantiflicker; 1325372b676d7Smrg int mysistvsaturation = pSiS->sistvsaturation; 1325472b676d7Smrg int mysistvcolcalibf = pSiS->sistvcolcalibf; 1325572b676d7Smrg int mysistvcolcalibc = pSiS->sistvcolcalibc; 1325672b676d7Smrg int mysistvcfilter = pSiS->sistvcfilter; 1325772b676d7Smrg int mysistvyfilter = pSiS->sistvyfilter; 1325872b676d7Smrg int mytvxpos = pSiS->tvxpos; 1325972b676d7Smrg int mytvypos = pSiS->tvypos; 1326072b676d7Smrg int mytvxscale = pSiS->tvxscale; 1326172b676d7Smrg int mytvyscale = pSiS->tvyscale; 1326272b676d7Smrg int i; 1326372b676d7Smrg ULong cbase; 1326472b676d7Smrg UChar ctemp; 1326572b676d7Smrg#ifdef SISDUALHEAD 1326672b676d7Smrg if(pSiSEnt && pSiS->DualHeadMode) { 1326772b676d7Smrg mysistvantiflicker = pSiSEnt->sistvantiflicker; 1326872b676d7Smrg mysistvsaturation = pSiSEnt->sistvsaturation; 1326972b676d7Smrg mysistvcolcalibf = pSiSEnt->sistvcolcalibf; 1327072b676d7Smrg mysistvcolcalibc = pSiSEnt->sistvcolcalibc; 1327172b676d7Smrg mysistvcfilter = pSiSEnt->sistvcfilter; 1327272b676d7Smrg mysistvyfilter = pSiSEnt->sistvyfilter; 1327372b676d7Smrg mytvxpos = pSiSEnt->tvxpos; 1327472b676d7Smrg mytvypos = pSiSEnt->tvypos; 1327572b676d7Smrg mytvxscale = pSiSEnt->tvxscale; 1327672b676d7Smrg mytvyscale = pSiSEnt->tvyscale; 1327772b676d7Smrg } 1327872b676d7Smrg#endif 1327972b676d7Smrg /* Backup default TV position, scale and colcalib registers */ 1328072b676d7Smrg inSISIDXREG(SISPART2,0x1f,pSiS->p2_1f); 1328172b676d7Smrg inSISIDXREG(SISPART2,0x20,pSiS->p2_20); 1328272b676d7Smrg inSISIDXREG(SISPART2,0x2b,pSiS->p2_2b); 1328372b676d7Smrg inSISIDXREG(SISPART2,0x42,pSiS->p2_42); 1328472b676d7Smrg inSISIDXREG(SISPART2,0x43,pSiS->p2_43); 1328572b676d7Smrg inSISIDXREG(SISPART2,0x01,pSiS->p2_01); 1328672b676d7Smrg inSISIDXREG(SISPART2,0x02,pSiS->p2_02); 1328772b676d7Smrg inSISIDXREG(SISPART2,0x44,pSiS->p2_44); 1328872b676d7Smrg inSISIDXREG(SISPART2,0x45,pSiS->p2_45); 1328972b676d7Smrg if(!(pSiS->VBFlags2 & VB2_301)) { 1329072b676d7Smrg inSISIDXREG(SISPART2,0x46,pSiS->p2_46); 1329172b676d7Smrg } else { 1329272b676d7Smrg pSiS->p2_46 = 0; 1329372b676d7Smrg } 1329472b676d7Smrg inSISIDXREG(SISPART2,0x0a,pSiS->p2_0a); 1329572b676d7Smrg inSISIDXREG(SISPART2,0x31,cbase); 1329672b676d7Smrg cbase = (cbase & 0x7f) << 8; 1329772b676d7Smrg inSISIDXREG(SISPART2,0x32,ctemp); 1329872b676d7Smrg cbase = (cbase | ctemp) << 8; 1329972b676d7Smrg inSISIDXREG(SISPART2,0x33,ctemp); 1330072b676d7Smrg cbase = (cbase | ctemp) << 8; 1330172b676d7Smrg inSISIDXREG(SISPART2,0x34,ctemp); 1330272b676d7Smrg pSiS->sistvccbase = (cbase | ctemp); 1330372b676d7Smrg inSISIDXREG(SISPART2,0x35,pSiS->p2_35); 1330472b676d7Smrg inSISIDXREG(SISPART2,0x36,pSiS->p2_36); 1330572b676d7Smrg inSISIDXREG(SISPART2,0x37,pSiS->p2_37); 1330672b676d7Smrg inSISIDXREG(SISPART2,0x38,pSiS->p2_38); 1330772b676d7Smrg if(!(pSiS->VBFlags2 & VB2_301)) { 1330872b676d7Smrg inSISIDXREG(SISPART2,0x47,pSiS->p2_47); 1330972b676d7Smrg inSISIDXREG(SISPART2,0x48,pSiS->p2_48); 1331072b676d7Smrg inSISIDXREG(SISPART2,0x49,pSiS->p2_49); 1331172b676d7Smrg inSISIDXREG(SISPART2,0x4a,pSiS->p2_4a); 1331272b676d7Smrg } 1331372b676d7Smrg inSISIDXREG(SISPART2,0x2f,pSiS->p2_2f); 1331472b676d7Smrg inSISIDXREG(SISPART2,0x30,pSiS->p2_30); 1331572b676d7Smrg for(i=0; i<9; i++) { 1331672b676d7Smrg inSISIDXREG(SISPART1,SiSScalingP1Regs[i],pSiS->scalingp1[i]); 1331772b676d7Smrg } 1331872b676d7Smrg for(i=0; i<9; i++) { 1331972b676d7Smrg inSISIDXREG(SISPART4,SiSScalingP4Regs[i],pSiS->scalingp4[i]); 1332072b676d7Smrg } 1332172b676d7Smrg if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 1332272b676d7Smrg for(i=0; i<64; i++) { 1332372b676d7Smrg inSISIDXREG(SISPART2,(0xc0 + i),pSiS->scalingp2[i]); 1332472b676d7Smrg } 1332572b676d7Smrg } 1332672b676d7Smrg#ifdef SISDUALHEAD 1332772b676d7Smrg if(pSiSEnt) { 1332872b676d7Smrg pSiSEnt->p2_1f = pSiS->p2_1f; pSiSEnt->p2_20 = pSiS->p2_20; 1332972b676d7Smrg pSiSEnt->p2_42 = pSiS->p2_42; pSiSEnt->p2_43 = pSiS->p2_43; 1333072b676d7Smrg pSiSEnt->p2_2b = pSiS->p2_2b; 1333172b676d7Smrg pSiSEnt->p2_01 = pSiS->p2_01; pSiSEnt->p2_02 = pSiS->p2_02; 1333272b676d7Smrg pSiSEnt->p2_44 = pSiS->p2_44; pSiSEnt->p2_45 = pSiS->p2_45; 1333372b676d7Smrg pSiSEnt->p2_46 = pSiS->p2_46; pSiSEnt->p2_0a = pSiS->p2_0a; 1333472b676d7Smrg pSiSEnt->sistvccbase = pSiS->sistvccbase; 1333572b676d7Smrg pSiSEnt->p2_35 = pSiS->p2_35; pSiSEnt->p2_36 = pSiS->p2_36; 1333672b676d7Smrg pSiSEnt->p2_37 = pSiS->p2_37; pSiSEnt->p2_38 = pSiS->p2_38; 1333772b676d7Smrg pSiSEnt->p2_48 = pSiS->p2_48; pSiSEnt->p2_49 = pSiS->p2_49; 1333872b676d7Smrg pSiSEnt->p2_4a = pSiS->p2_4a; pSiSEnt->p2_2f = pSiS->p2_2f; 1333972b676d7Smrg pSiSEnt->p2_30 = pSiS->p2_30; pSiSEnt->p2_47 = pSiS->p2_47; 1334072b676d7Smrg for(i=0; i<9; i++) { 1334172b676d7Smrg pSiSEnt->scalingp1[i] = pSiS->scalingp1[i]; 1334272b676d7Smrg } 1334372b676d7Smrg for(i=0; i<9; i++) { 1334472b676d7Smrg pSiSEnt->scalingp4[i] = pSiS->scalingp4[i]; 1334572b676d7Smrg } 1334672b676d7Smrg if(pSiS->VBFlags2 & VB2_SISTAP4SCALER) { 1334772b676d7Smrg for(i=0; i<64; i++) { 1334872b676d7Smrg pSiSEnt->scalingp2[i] = pSiS->scalingp2[i]; 1334972b676d7Smrg } 1335072b676d7Smrg } 1335172b676d7Smrg } 1335272b676d7Smrg#endif 1335372b676d7Smrg if((val = mysistvantiflicker) != -1) { 1335472b676d7Smrg SiS_SetSISTVantiflicker(pScrn, val); 1335572b676d7Smrg } 1335672b676d7Smrg if((val = mysistvsaturation) != -1) { 1335772b676d7Smrg SiS_SetSISTVsaturation(pScrn, val); 1335872b676d7Smrg } 1335972b676d7Smrg if((val = mysistvcfilter) != -1) { 1336072b676d7Smrg SiS_SetSISTVcfilter(pScrn, val); 1336172b676d7Smrg } 1336272b676d7Smrg if((val = mysistvyfilter) != 1) { 1336372b676d7Smrg SiS_SetSISTVyfilter(pScrn, val); 1336472b676d7Smrg } 1336572b676d7Smrg if((val = mysistvcolcalibc) != 0) { 1336672b676d7Smrg SiS_SetSISTVcolcalib(pScrn, val, TRUE); 1336772b676d7Smrg } 1336872b676d7Smrg if((val = mysistvcolcalibf) != 0) { 1336972b676d7Smrg SiS_SetSISTVcolcalib(pScrn, val, FALSE); 1337072b676d7Smrg } 1337172b676d7Smrg if((val = mytvxpos) != 0) { 1337272b676d7Smrg SiS_SetTVxposoffset(pScrn, val); 1337372b676d7Smrg } 1337472b676d7Smrg if((val = mytvypos) != 0) { 1337572b676d7Smrg SiS_SetTVyposoffset(pScrn, val); 1337672b676d7Smrg } 1337772b676d7Smrg if((val = mytvxscale) != 0) { 1337872b676d7Smrg SiS_SetTVxscale(pScrn, val); 1337972b676d7Smrg } 1338072b676d7Smrg if((val = mytvyscale) != 0) { 1338172b676d7Smrg SiS_SetTVyscale(pScrn, val); 1338272b676d7Smrg } 1338372b676d7Smrg } 1338472b676d7Smrg } 1338572b676d7Smrg 1338672b676d7Smrg} 1338772b676d7Smrg 1338872b676d7Smrg/* Post-set SiS6326 TV registers */ 1338972b676d7Smrgstatic void 1339072b676d7SmrgSiS6326PostSetMode(ScrnInfoPtr pScrn, SISRegPtr sisReg) 1339172b676d7Smrg{ 1339272b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1339372b676d7Smrg UChar tmp; 1339472b676d7Smrg int val; 1339572b676d7Smrg 1339672b676d7Smrg if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; 1339772b676d7Smrg 1339872b676d7Smrg#ifdef UNLOCK_ALWAYS 1339972b676d7Smrg sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); 1340072b676d7Smrg#endif 1340172b676d7Smrg 1340272b676d7Smrg /* Backup default TV position registers */ 1340372b676d7Smrg pSiS->tvx1 = SiS6326GetTVReg(pScrn,0x3a); 1340472b676d7Smrg pSiS->tvx1 |= ((SiS6326GetTVReg(pScrn,0x3c) & 0x0f) << 8); 1340572b676d7Smrg pSiS->tvx2 = SiS6326GetTVReg(pScrn,0x26); 1340672b676d7Smrg pSiS->tvx2 |= ((SiS6326GetTVReg(pScrn,0x27) & 0xf0) << 4); 1340772b676d7Smrg pSiS->tvx3 = SiS6326GetTVReg(pScrn,0x12); 1340872b676d7Smrg pSiS->tvx3 |= ((SiS6326GetTVReg(pScrn,0x13) & 0xC0) << 2); 1340972b676d7Smrg pSiS->tvy1 = SiS6326GetTVReg(pScrn,0x11); 1341072b676d7Smrg pSiS->tvy1 |= ((SiS6326GetTVReg(pScrn,0x13) & 0x30) << 4); 1341172b676d7Smrg 1341272b676d7Smrg /* Handle TVPosOffset options (BEFORE switching on TV) */ 1341372b676d7Smrg if((val = pSiS->tvxpos) != 0) { 1341472b676d7Smrg SiS_SetTVxposoffset(pScrn, val); 1341572b676d7Smrg } 1341672b676d7Smrg if((val = pSiS->tvypos) != 0) { 1341772b676d7Smrg SiS_SetTVyposoffset(pScrn, val); 1341872b676d7Smrg } 1341972b676d7Smrg 1342072b676d7Smrg /* Switch on TV output. This is rather complicated, but 1342172b676d7Smrg * if we don't do it, TV output will flicker terribly. 1342272b676d7Smrg */ 1342372b676d7Smrg if(pSiS->SiS6326Flags & SIS6326_TVON) { 1342472b676d7Smrg orSISIDXREG(SISSR, 0x01, 0x20); 1342572b676d7Smrg tmp = SiS6326GetTVReg(pScrn,0x00); 1342672b676d7Smrg tmp &= ~0x04; 1342772b676d7Smrg while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 1342872b676d7Smrg SiS6326SetTVReg(pScrn,0x00,tmp); 1342972b676d7Smrg for(val=0; val < 2; val++) { 1343072b676d7Smrg while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 1343172b676d7Smrg while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 1343272b676d7Smrg } 1343372b676d7Smrg SiS6326SetTVReg(pScrn, 0x00, sisReg->sis6326tv[0]); 1343472b676d7Smrg tmp = inSISREG(SISINPSTAT); 1343572b676d7Smrg outSISREG(SISAR, 0x20); 1343672b676d7Smrg tmp = inSISREG(SISINPSTAT); 1343772b676d7Smrg while(inSISREG(SISINPSTAT) & 0x01); 1343872b676d7Smrg while(!(inSISREG(SISINPSTAT) & 0x01)); 1343972b676d7Smrg andSISIDXREG(SISSR, 0x01, ~0x20); 1344072b676d7Smrg for(val=0; val < 10; val++) { 1344172b676d7Smrg while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ 1344272b676d7Smrg while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ 1344372b676d7Smrg } 1344472b676d7Smrg andSISIDXREG(SISSR, 0x01, ~0x20); 1344572b676d7Smrg } 1344672b676d7Smrg 1344772b676d7Smrg tmp = SiS6326GetTVReg(pScrn,0x00); 1344872b676d7Smrg if(!(tmp & 0x04)) return; 1344972b676d7Smrg 1345072b676d7Smrg /* Apply TV settings given by options */ 1345172b676d7Smrg if((val = pSiS->sistvantiflicker) != -1) { 1345272b676d7Smrg SiS_SetSIS6326TVantiflicker(pScrn, val); 1345372b676d7Smrg } 1345472b676d7Smrg if((val = pSiS->sis6326enableyfilter) != -1) { 1345572b676d7Smrg SiS_SetSIS6326TVenableyfilter(pScrn, val); 1345672b676d7Smrg } 1345772b676d7Smrg if((val = pSiS->sis6326yfilterstrong) != -1) { 1345872b676d7Smrg SiS_SetSIS6326TVyfilterstrong(pScrn, val); 1345972b676d7Smrg } 1346072b676d7Smrg 1346172b676d7Smrg} 1346272b676d7Smrg 1346372b676d7Smrg/* Check if video bridge is in slave mode */ 1346472b676d7SmrgBool 1346572b676d7SmrgSiSBridgeIsInSlaveMode(ScrnInfoPtr pScrn) 1346672b676d7Smrg{ 1346772b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1346872b676d7Smrg UChar usScrP1_00; 1346972b676d7Smrg 1347072b676d7Smrg if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return FALSE; 1347172b676d7Smrg 1347272b676d7Smrg inSISIDXREG(SISPART1,0x00,usScrP1_00); 1347372b676d7Smrg if( ((pSiS->VGAEngine == SIS_300_VGA) && (usScrP1_00 & 0xa0) == 0x20) || 1347472b676d7Smrg ((pSiS->VGAEngine == SIS_315_VGA) && (usScrP1_00 & 0x50) == 0x10) ) { 1347572b676d7Smrg return TRUE; 1347672b676d7Smrg } 1347772b676d7Smrg 1347872b676d7Smrg return FALSE; 1347972b676d7Smrg} 1348072b676d7Smrg 1348172b676d7Smrg/* Build a list of the VESA modes the BIOS reports as valid */ 1348272b676d7Smrgstatic void 1348372b676d7SmrgSiSBuildVesaModeList(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe) 1348472b676d7Smrg{ 1348572b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1348672b676d7Smrg int i = 0; 1348772b676d7Smrg 1348872b676d7Smrg while(vbe->VideoModePtr[i] != 0xffff) { 1348972b676d7Smrg sisModeInfoPtr m; 1349072b676d7Smrg VbeModeInfoBlock *mode; 1349172b676d7Smrg int id = vbe->VideoModePtr[i++]; 1349272b676d7Smrg 1349372b676d7Smrg if((mode = VBEGetModeInfo(pVbe, id)) == NULL) { 1349472b676d7Smrg continue; 1349572b676d7Smrg } 1349672b676d7Smrg 1349772b676d7Smrg m = xnfcalloc(sizeof(sisModeInfoRec), 1); 1349872b676d7Smrg if(!m) { 1349972b676d7Smrg VBEFreeModeInfo(mode); 1350072b676d7Smrg continue; 1350172b676d7Smrg } 1350272b676d7Smrg m->width = mode->XResolution; 1350372b676d7Smrg m->height = mode->YResolution; 1350472b676d7Smrg m->bpp = mode->BitsPerPixel; 1350572b676d7Smrg m->n = id; 1350672b676d7Smrg m->next = pSiS->SISVESAModeList; 1350772b676d7Smrg 1350872b676d7Smrg pSiS->SISVESAModeList = m; 1350972b676d7Smrg 1351072b676d7Smrg VBEFreeModeInfo(mode); 1351172b676d7Smrg 1351272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1351372b676d7Smrg "VESA BIOS supports mode number 0x%x: %ix%i (%i bpp)\n", 1351472b676d7Smrg m->n, m->width, m->height, m->bpp); 1351572b676d7Smrg } 1351672b676d7Smrg} 1351772b676d7Smrg 1351872b676d7Smrg/* Get VESA mode number from given resolution/depth */ 1351972b676d7Smrgstatic UShort 1352072b676d7SmrgSiSCalcVESAModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode) 1352172b676d7Smrg{ 1352272b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1352372b676d7Smrg sisModeInfoPtr m = pSiS->SISVESAModeList; 1352472b676d7Smrg UShort i = (pScrn->bitsPerPixel+7)/8 - 1; 1352572b676d7Smrg UShort ModeNumber = 0; 1352672b676d7Smrg int j; 1352772b676d7Smrg 1352872b676d7Smrg while(m) { 1352972b676d7Smrg if( (pScrn->bitsPerPixel == m->bpp) && 1353072b676d7Smrg (mode->HDisplay == m->width) && 1353172b676d7Smrg (mode->VDisplay == m->height) ) 1353272b676d7Smrg return m->n; 1353372b676d7Smrg m = m->next; 1353472b676d7Smrg } 1353572b676d7Smrg 1353672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1353772b676d7Smrg "No valid VESA BIOS mode found for %dx%d (%d bpp)\n", 1353872b676d7Smrg mode->HDisplay, mode->VDisplay, pScrn->bitsPerPixel); 1353972b676d7Smrg 1354072b676d7Smrg if(!pSiS->ROM661New) { /* VESA numbers changed! */ 1354172b676d7Smrg j = 0; 1354272b676d7Smrg while(VESAModeIndices[j] != 9999) { 1354372b676d7Smrg if( (mode->HDisplay == VESAModeIndices[j]) && 1354472b676d7Smrg (mode->VDisplay == VESAModeIndices[j+1]) ) { 1354572b676d7Smrg ModeNumber = VESAModeIndices[j + 2 + i]; 1354672b676d7Smrg break; 1354772b676d7Smrg } 1354872b676d7Smrg j += 6; 1354972b676d7Smrg } 1355072b676d7Smrg 1355172b676d7Smrg if(!ModeNumber) { 1355272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1355372b676d7Smrg "No valid mode found for %dx%dx%d in built-in table either.\n", 1355472b676d7Smrg mode->HDisplay, mode->VDisplay, pScrn->bitsPerPixel); 1355572b676d7Smrg } 1355672b676d7Smrg } 1355772b676d7Smrg 1355872b676d7Smrg return(ModeNumber); 1355972b676d7Smrg} 1356072b676d7Smrg 1356172b676d7SmrgUShort 1356272b676d7SmrgSiS_GetModeNumber(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned int VBFlags) 1356372b676d7Smrg{ 1356472b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1356572b676d7Smrg UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; 1356672b676d7Smrg BOOLEAN FSTN = pSiS->FSTN ? TRUE : FALSE; 1356772b676d7Smrg 1356872b676d7Smrg#ifdef SISDUALHEAD 1356972b676d7Smrg if(pSiS->DualHeadMode && pSiS->SecondHead) FSTN = FALSE; 1357072b676d7Smrg#endif 1357172b676d7Smrg 1357272b676d7Smrg return(SiS_GetModeID(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, 1357372b676d7Smrg i, FSTN, pSiS->LCDwidth, pSiS->LCDheight)); 1357472b676d7Smrg} 1357572b676d7Smrg 1357672b676d7Smrgstatic Bool 1357772b676d7SmrgSiSValidLCDUserMode(SISPtr pSiS, unsigned int VBFlags, DisplayModePtr mode, Bool isforlcda) 1357872b676d7Smrg{ 1357972b676d7Smrg if(mode->Flags & V_INTERLACE) return FALSE; 1358072b676d7Smrg 1358172b676d7Smrg if(mode->HDisplay > 2048) return FALSE; 1358272b676d7Smrg if(mode->VDisplay > 1536) return FALSE; 1358372b676d7Smrg 1358472b676d7Smrg if(pSiS->VBFlags2 & VB2_LCD162MHZBRIDGE) { 1358572b676d7Smrg if(mode->Clock > 162500) return FALSE; 1358672b676d7Smrg#ifdef VB_FORBID_CRT2LCD_OVER_1600 1358772b676d7Smrg if(!isforlcda) { 1358872b676d7Smrg if(mode->HDisplay > 1600) return FALSE; 1358972b676d7Smrg } 1359072b676d7Smrg#endif 1359172b676d7Smrg } else { /* 301, 301B, 302B (no LCDA!) */ 1359272b676d7Smrg if(mode->Clock > 130000) return FALSE; 1359372b676d7Smrg if(mode->Clock > 111000) { 1359472b676d7Smrg xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING, 1359572b676d7Smrg "WARNING: Mode clock beyond video bridge specs (%dMHz). Hardware damage might occure.\n", 1359672b676d7Smrg mode->Clock / 1000); 1359772b676d7Smrg } 1359872b676d7Smrg if(mode->HDisplay > 1600) return FALSE; 1359972b676d7Smrg if(mode->VDisplay > 1024) return FALSE; 1360072b676d7Smrg } 1360172b676d7Smrg 1360272b676d7Smrg return TRUE; 1360372b676d7Smrg} 1360472b676d7Smrg 1360572b676d7Smrgstatic Bool 1360672b676d7SmrgSiSValidVGA2UserMode(SISPtr pSiS, unsigned int VBFlags, DisplayModePtr mode) 1360772b676d7Smrg{ 1360872b676d7Smrg if(mode->Flags & V_INTERLACE) return FALSE; 1360972b676d7Smrg 1361072b676d7Smrg if(mode->HDisplay > 2048) return FALSE; 1361172b676d7Smrg if(mode->VDisplay > 1536) return FALSE; 1361272b676d7Smrg 1361372b676d7Smrg if(pSiS->VBFlags2 & VB2_RAMDAC202MHZBRIDGE) { 1361472b676d7Smrg if(mode->Clock > 203000) return FALSE; 1361572b676d7Smrg } else if(pSiS->VBFlags2 & VB2_30xBLV) { 1361672b676d7Smrg if(mode->Clock > 162500) return FALSE; 1361772b676d7Smrg } else { 1361872b676d7Smrg if(mode->Clock > 135500) return FALSE; 1361972b676d7Smrg } 1362072b676d7Smrg 1362172b676d7Smrg return TRUE; 1362272b676d7Smrg} 1362372b676d7Smrg 1362472b676d7SmrgUShort 1362572b676d7SmrgSiS_CheckModeCRT1(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned int VBFlags, Bool havecustommodes) 1362672b676d7Smrg{ 1362772b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1362872b676d7Smrg UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; 1362972b676d7Smrg int j; 1363072b676d7Smrg 1363172b676d7Smrg if(!(VBFlags & CRT1_LCDA)) { 1363272b676d7Smrg 1363372b676d7Smrg if((havecustommodes) && (!(mode->type & M_T_DEFAULT))) { 1363472b676d7Smrg return 0xfe; 1363572b676d7Smrg } 1363672b676d7Smrg 1363772b676d7Smrg } else if(pSiS->VBFlags2 & VB2_SISTMDSLCDABRIDGE) { 1363872b676d7Smrg 1363972b676d7Smrg if(pSiS->ChipType < SIS_661) { /* < 661 only? */ 1364072b676d7Smrg if(!(mode->type & M_T_DEFAULT)) { 1364172b676d7Smrg if(mode->HTotal > 2055) return 0; 1364272b676d7Smrg /* (Default mode will be caught in mode switching code) */ 1364372b676d7Smrg } 1364472b676d7Smrg } 1364572b676d7Smrg 1364672b676d7Smrg if(pSiS->SiS_Pr->CP_HaveCustomData) { 1364772b676d7Smrg for(j=0; j<7; j++) { 1364872b676d7Smrg if((pSiS->SiS_Pr->CP_DataValid[j]) && 1364972b676d7Smrg (mode->HDisplay == pSiS->SiS_Pr->CP_HDisplay[j]) && 1365072b676d7Smrg (mode->VDisplay == pSiS->SiS_Pr->CP_VDisplay[j]) && 1365172b676d7Smrg (mode->type & M_T_BUILTIN)) 1365272b676d7Smrg return 0xfe; 1365372b676d7Smrg } 1365472b676d7Smrg } 1365572b676d7Smrg 1365672b676d7Smrg if((pSiS->AddedPlasmaModes) && (mode->type & M_T_BUILTIN)) 1365772b676d7Smrg return 0xfe; 1365872b676d7Smrg 1365972b676d7Smrg if((havecustommodes) && 1366072b676d7Smrg (pSiS->LCDwidth) && /* = test if LCD present */ 1366172b676d7Smrg (!(mode->type & M_T_DEFAULT)) && 1366272b676d7Smrg (SiSValidLCDUserMode(pSiS, VBFlags, mode, TRUE))) 1366372b676d7Smrg return 0xfe; 1366472b676d7Smrg 1366572b676d7Smrg if((mode->HDisplay > pSiS->LCDwidth) || 1366672b676d7Smrg (mode->VDisplay > pSiS->LCDheight)) { 1366772b676d7Smrg return 0; 1366872b676d7Smrg } 1366972b676d7Smrg 1367072b676d7Smrg } else { 1367172b676d7Smrg 1367272b676d7Smrg if((mode->HDisplay > pSiS->LCDwidth) || 1367372b676d7Smrg (mode->VDisplay > pSiS->LCDheight)) { 1367472b676d7Smrg return 0; 1367572b676d7Smrg } 1367672b676d7Smrg 1367772b676d7Smrg } 1367872b676d7Smrg 1367972b676d7Smrg return(SiS_GetModeID(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, 1368072b676d7Smrg i, pSiS->FSTN, pSiS->LCDwidth, pSiS->LCDheight)); 1368172b676d7Smrg} 1368272b676d7Smrg 1368372b676d7SmrgUShort 1368472b676d7SmrgSiS_CheckModeCRT2(ScrnInfoPtr pScrn, DisplayModePtr mode, unsigned int VBFlags, Bool havecustommodes) 1368572b676d7Smrg{ 1368672b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1368772b676d7Smrg UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; 1368872b676d7Smrg UShort ModeIndex = 0; 1368972b676d7Smrg int j; 1369072b676d7Smrg 1369172b676d7Smrg#ifdef TWDEBUG 1369272b676d7Smrg xf86DrvMsg(0, X_INFO, "Inside CheckCalcModeIndex (VBFlags %lx, mode %dx%d)\n", 1369372b676d7Smrg VBFlags,mode->HDisplay, mode->VDisplay); 1369472b676d7Smrg#endif 1369572b676d7Smrg 1369672b676d7Smrg if(VBFlags & CRT2_LCD) { /* CRT2 is LCD */ 1369772b676d7Smrg 1369872b676d7Smrg if((pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && (!(pSiS->VBFlags2 & VB2_30xBDH))) { 1369972b676d7Smrg 1370072b676d7Smrg if(pSiS->SiS_Pr->CP_HaveCustomData) { 1370172b676d7Smrg for(j=0; j<7; j++) { 1370272b676d7Smrg if((pSiS->SiS_Pr->CP_DataValid[j]) && 1370372b676d7Smrg (mode->HDisplay == pSiS->SiS_Pr->CP_HDisplay[j]) && 1370472b676d7Smrg (mode->VDisplay == pSiS->SiS_Pr->CP_VDisplay[j]) && 1370572b676d7Smrg#ifdef VB_FORBID_CRT2LCD_OVER_1600 1370672b676d7Smrg (mode->HDisplay <= 1600) && 1370772b676d7Smrg#endif 1370872b676d7Smrg (mode->type & M_T_BUILTIN)) 1370972b676d7Smrg return 0xfe; 1371072b676d7Smrg } 1371172b676d7Smrg } 1371272b676d7Smrg 1371372b676d7Smrg /* All plasma modes have HDisplay <= 1600 */ 1371472b676d7Smrg if((pSiS->AddedPlasmaModes) && (mode->type & M_T_BUILTIN)) 1371572b676d7Smrg return 0xfe; 1371672b676d7Smrg 1371772b676d7Smrg if((havecustommodes) && 1371872b676d7Smrg (pSiS->LCDwidth) && /* = test if LCD present */ 1371972b676d7Smrg (!(mode->type & M_T_DEFAULT)) && 1372072b676d7Smrg (SiSValidLCDUserMode(pSiS, VBFlags, mode, FALSE))) 1372172b676d7Smrg return 0xfe; 1372272b676d7Smrg 1372372b676d7Smrg } 1372472b676d7Smrg 1372572b676d7Smrg if( ((mode->HDisplay <= pSiS->LCDwidth) && 1372672b676d7Smrg (mode->VDisplay <= pSiS->LCDheight)) || 1372772b676d7Smrg ((pSiS->SiS_Pr->SiS_CustomT == CUT_PANEL848) && 1372872b676d7Smrg (((mode->HDisplay == 1360) && (mode->HDisplay == 768)) || 1372972b676d7Smrg ((mode->HDisplay == 1024) && (mode->HDisplay == 768)) || 1373072b676d7Smrg ((mode->HDisplay == 800) && (mode->HDisplay == 600)))) || 1373172b676d7Smrg ((pSiS->SiS_Pr->SiS_CustomT == CUT_PANEL856) && 1373272b676d7Smrg (((mode->HDisplay == 1024) && (mode->HDisplay == 768)) || 1373372b676d7Smrg ((mode->HDisplay == 800) && (mode->HDisplay == 600)))) ) { 1373472b676d7Smrg 1373572b676d7Smrg ModeIndex = SiS_GetModeID_LCD(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, i, 1373672b676d7Smrg pSiS->FSTN, pSiS->SiS_Pr->SiS_CustomT, pSiS->LCDwidth, pSiS->LCDheight, 1373772b676d7Smrg pSiS->VBFlags2); 1373872b676d7Smrg 1373972b676d7Smrg } 1374072b676d7Smrg 1374172b676d7Smrg } else if(VBFlags & CRT2_TV) { /* CRT2 is TV */ 1374272b676d7Smrg 1374372b676d7Smrg ModeIndex = SiS_GetModeID_TV(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, i, 1374472b676d7Smrg pSiS->VBFlags2); 1374572b676d7Smrg 1374672b676d7Smrg } else if(VBFlags & CRT2_VGA) { /* CRT2 is VGA2 */ 1374772b676d7Smrg 1374872b676d7Smrg if((pSiS->AddedPlasmaModes) && (mode->type & M_T_BUILTIN)) 1374972b676d7Smrg return 0xfe; 1375072b676d7Smrg 1375172b676d7Smrg if((havecustommodes) && 1375272b676d7Smrg (!(mode->type & M_T_DEFAULT)) && 1375372b676d7Smrg (SiSValidVGA2UserMode(pSiS, VBFlags, mode))) 1375472b676d7Smrg return 0xfe; 1375572b676d7Smrg 1375672b676d7Smrg ModeIndex = SiS_GetModeID_VGA2(pSiS->VGAEngine, VBFlags, mode->HDisplay, mode->VDisplay, i, 1375772b676d7Smrg pSiS->VBFlags2); 1375872b676d7Smrg 1375972b676d7Smrg } else { /* no CRT2 */ 1376072b676d7Smrg 1376172b676d7Smrg /* Return a valid mode number */ 1376272b676d7Smrg ModeIndex = 0xfe; 1376372b676d7Smrg 1376472b676d7Smrg } 1376572b676d7Smrg 1376672b676d7Smrg return(ModeIndex); 1376772b676d7Smrg} 1376872b676d7Smrg 1376972b676d7Smrg/* Calculate the vertical refresh rate from a mode */ 1377072b676d7Smrgfloat 1377172b676d7SmrgSiSCalcVRate(DisplayModePtr mode) 1377272b676d7Smrg{ 1377372b676d7Smrg float hsync, refresh = 0; 1377472b676d7Smrg 1377572b676d7Smrg if(mode->HSync > 0.0) 1377672b676d7Smrg hsync = mode->HSync; 1377772b676d7Smrg else if(mode->HTotal > 0) 1377872b676d7Smrg hsync = (float)mode->Clock / (float)mode->HTotal; 1377972b676d7Smrg else 1378072b676d7Smrg hsync = 0.0; 1378172b676d7Smrg 1378272b676d7Smrg if(mode->VTotal > 0) 1378372b676d7Smrg refresh = hsync * 1000.0 / mode->VTotal; 1378472b676d7Smrg 1378572b676d7Smrg if(mode->Flags & V_INTERLACE) 1378672b676d7Smrg refresh *= 2.0; 1378772b676d7Smrg 1378872b676d7Smrg if(mode->Flags & V_DBLSCAN) 1378972b676d7Smrg refresh /= 2.0; 1379072b676d7Smrg 1379172b676d7Smrg if(mode->VScan > 1) 1379272b676d7Smrg refresh /= mode->VScan; 1379372b676d7Smrg 1379472b676d7Smrg if(mode->VRefresh > 0.0) 1379572b676d7Smrg refresh = mode->VRefresh; 1379672b676d7Smrg 1379772b676d7Smrg if(hsync == 0.0 || refresh == 0.0) return 0.0; 1379872b676d7Smrg 1379972b676d7Smrg return refresh; 1380072b676d7Smrg} 1380172b676d7Smrg 1380272b676d7Smrg/* Calculate CR33 (rate index) for CRT1. 1380372b676d7Smrg * Calculation is done using currentmode, therefore it is 1380472b676d7Smrg * recommended to set VertRefresh and HorizSync to correct 1380572b676d7Smrg * values in config file. 1380672b676d7Smrg */ 1380772b676d7SmrgUChar 1380872b676d7SmrgSISSearchCRT1Rate(ScrnInfoPtr pScrn, DisplayModePtr mode) 1380972b676d7Smrg{ 1381072b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1381172b676d7Smrg int i = 0, irefresh; 1381272b676d7Smrg UShort xres = mode->HDisplay; 1381372b676d7Smrg UShort yres = mode->VDisplay; 1381472b676d7Smrg UChar index, defindex; 1381572b676d7Smrg Bool checksis730 = FALSE; 1381672b676d7Smrg 1381772b676d7Smrg defindex = (xres == 800 || xres == 1024 || xres == 1280) ? 0x02 : 0x01; 1381872b676d7Smrg 1381972b676d7Smrg irefresh = (int)SiSCalcVRate(mode); 1382072b676d7Smrg if(!irefresh) return defindex; 1382172b676d7Smrg 1382272b676d7Smrg /* SiS730 has troubles on CRT2 if CRT1 is at 32bpp */ 1382372b676d7Smrg if( (pSiS->ChipType == SIS_730) && 1382472b676d7Smrg (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) && 1382572b676d7Smrg (pSiS->CurrentLayout.bitsPerPixel == 32) ) { 1382672b676d7Smrg#ifdef SISDUALHEAD 1382772b676d7Smrg if(pSiS->DualHeadMode) { 1382872b676d7Smrg if(pSiS->SecondHead) { 1382972b676d7Smrg checksis730 = TRUE; 1383072b676d7Smrg } 1383172b676d7Smrg } else 1383272b676d7Smrg#endif 1383372b676d7Smrg if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE) && (!pSiS->CRT1off)) { 1383472b676d7Smrg checksis730 = TRUE; 1383572b676d7Smrg } 1383672b676d7Smrg } 1383772b676d7Smrg 1383872b676d7Smrg#ifdef TWDEBUG 1383972b676d7Smrg xf86DrvMsg(0, X_INFO, "Debug: CalcVRate returned %d\n", irefresh); 1384072b676d7Smrg#endif 1384172b676d7Smrg 1384272b676d7Smrg /* We need the REAL refresh rate here */ 1384372b676d7Smrg if(mode->Flags & V_INTERLACE) irefresh /= 2; 1384472b676d7Smrg 1384572b676d7Smrg /* Do not multiply by 2 when DBLSCAN! */ 1384672b676d7Smrg 1384772b676d7Smrg#ifdef TWDEBUG 1384872b676d7Smrg xf86DrvMsg(0, X_INFO, "Debug: Rate after correction = %d\n", irefresh); 1384972b676d7Smrg#endif 1385072b676d7Smrg 1385172b676d7Smrg index = 0; 1385272b676d7Smrg while((sisx_vrate[i].idx != 0) && (sisx_vrate[i].xres <= xres)) { 1385372b676d7Smrg if((sisx_vrate[i].xres == xres) && (sisx_vrate[i].yres == yres)) { 1385472b676d7Smrg if((checksis730 == FALSE) || (sisx_vrate[i].SiS730valid32bpp == TRUE)) { 1385572b676d7Smrg if(sisx_vrate[i].refresh == irefresh) { 1385672b676d7Smrg index = sisx_vrate[i].idx; 1385772b676d7Smrg break; 1385872b676d7Smrg } else if(sisx_vrate[i].refresh > irefresh) { 1385972b676d7Smrg if((sisx_vrate[i].refresh - irefresh) <= 3) { 1386072b676d7Smrg index = sisx_vrate[i].idx; 1386172b676d7Smrg } else if( ((checksis730 == FALSE) || (sisx_vrate[i - 1].SiS730valid32bpp == TRUE)) && 1386272b676d7Smrg ((irefresh - sisx_vrate[i - 1].refresh) <= 2) && 1386372b676d7Smrg (sisx_vrate[i].idx != 1) ) { 1386472b676d7Smrg index = sisx_vrate[i - 1].idx; 1386572b676d7Smrg } 1386672b676d7Smrg break; 1386772b676d7Smrg } else if((irefresh - sisx_vrate[i].refresh) <= 2) { 1386872b676d7Smrg index = sisx_vrate[i].idx; 1386972b676d7Smrg break; 1387072b676d7Smrg } 1387172b676d7Smrg } 1387272b676d7Smrg } 1387372b676d7Smrg i++; 1387472b676d7Smrg } 1387572b676d7Smrg 1387672b676d7Smrg if(index > 0) return index; 1387772b676d7Smrg else return defindex; 1387872b676d7Smrg} 1387972b676d7Smrg 1388072b676d7Smrgvoid 1388172b676d7SmrgSISWaitRetraceCRT1(ScrnInfoPtr pScrn) 1388272b676d7Smrg{ 1388372b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1388472b676d7Smrg int watchdog; 1388572b676d7Smrg UChar temp; 1388672b676d7Smrg 1388772b676d7Smrg inSISIDXREG(SISCR,0x17,temp); 1388872b676d7Smrg if(!(temp & 0x80)) return; 1388972b676d7Smrg 1389072b676d7Smrg inSISIDXREG(SISSR,0x1f,temp); 1389172b676d7Smrg if(temp & 0xc0) return; 1389272b676d7Smrg 1389372b676d7Smrg watchdog = 65536; 1389472b676d7Smrg while((inSISREG(SISINPSTAT) & 0x08) && --watchdog); 1389572b676d7Smrg watchdog = 65536; 1389672b676d7Smrg while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog); 1389772b676d7Smrg} 1389872b676d7Smrg 1389972b676d7Smrgvoid 1390072b676d7SmrgSISWaitRetraceCRT2(ScrnInfoPtr pScrn) 1390172b676d7Smrg{ 1390272b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1390372b676d7Smrg int watchdog; 1390472b676d7Smrg UChar temp, reg; 1390572b676d7Smrg 1390672b676d7Smrg if(SiSBridgeIsInSlaveMode(pScrn)) { 1390772b676d7Smrg SISWaitRetraceCRT1(pScrn); 1390872b676d7Smrg return; 1390972b676d7Smrg } 1391072b676d7Smrg 1391172b676d7Smrg switch(pSiS->VGAEngine) { 1391272b676d7Smrg case SIS_300_VGA: 1391372b676d7Smrg reg = 0x25; 1391472b676d7Smrg break; 1391572b676d7Smrg case SIS_315_VGA: 1391672b676d7Smrg reg = 0x30; 1391772b676d7Smrg break; 1391872b676d7Smrg default: 1391972b676d7Smrg return; 1392072b676d7Smrg } 1392172b676d7Smrg 1392272b676d7Smrg watchdog = 65536; 1392372b676d7Smrg do { 1392472b676d7Smrg inSISIDXREG(SISPART1, reg, temp); 1392572b676d7Smrg if(!(temp & 0x02)) break; 1392672b676d7Smrg } while(--watchdog); 1392772b676d7Smrg watchdog = 65536; 1392872b676d7Smrg do { 1392972b676d7Smrg inSISIDXREG(SISPART1, reg, temp); 1393072b676d7Smrg if(temp & 0x02) break; 1393172b676d7Smrg } while(--watchdog); 1393272b676d7Smrg} 1393372b676d7Smrg 1393472b676d7Smrgstatic void 1393572b676d7SmrgSISWaitVBRetrace(ScrnInfoPtr pScrn) 1393672b676d7Smrg{ 1393772b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 1393872b676d7Smrg 1393972b676d7Smrg if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { 1394072b676d7Smrg#ifdef SISDUALHEAD 1394172b676d7Smrg if(pSiS->DualHeadMode) { 1394272b676d7Smrg if(pSiS->SecondHead) 1394372b676d7Smrg SISWaitRetraceCRT1(pScrn); 1394472b676d7Smrg else 1394572b676d7Smrg SISWaitRetraceCRT2(pScrn); 1394672b676d7Smrg } else { 1394772b676d7Smrg#endif 1394872b676d7Smrg if(pSiS->VBFlags & DISPTYPE_DISP1) { 1394972b676d7Smrg SISWaitRetraceCRT1(pScrn); 1395072b676d7Smrg } 1395172b676d7Smrg if(pSiS->VBFlags & DISPTYPE_DISP2) { 1395272b676d7Smrg if(!(SiSBridgeIsInSlaveMode(pScrn))) { 1395372b676d7Smrg SISWaitRetraceCRT2(pScrn); 1395472b676d7Smrg } 1395572b676d7Smrg } 1395672b676d7Smrg#ifdef SISDUALHEAD 1395772b676d7Smrg } 1395872b676d7Smrg#endif 1395972b676d7Smrg } else { 1396072b676d7Smrg SISWaitRetraceCRT1(pScrn); 1396172b676d7Smrg } 1396272b676d7Smrg} 1396372b676d7Smrg 1396472b676d7Smrg#define MODEID_OFF 0x449 1396572b676d7Smrg 1396672b676d7SmrgUChar 1396772b676d7SmrgSiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, UShort offset, UChar value) 1396872b676d7Smrg{ 1396972b676d7Smrg UChar ret = 0; 1397072b676d7Smrg#ifdef SIS_USE_BIOS_SCRATCH 1397172b676d7Smrg UChar *base; 1397272b676d7Smrg#endif 1397372b676d7Smrg 1397472b676d7Smrg /* For some reasons (like detecting the current display mode), 1397572b676d7Smrg * we need to read (or write-back) values from the BIOS 1397672b676d7Smrg * scratch area. This area is only valid for the primary 1397772b676d7Smrg * graphics card. For the secondary, we just return some 1397872b676d7Smrg * defaults and ignore requests to write data. As regards 1397972b676d7Smrg * the display mode: If sisfb is loaded for the secondary 1398072b676d7Smrg * card, it very probably has set a mode, but in any case 1398172b676d7Smrg * informed us via its info packet. So this here will not be 1398272b676d7Smrg * called for mode detection in this case. 1398372b676d7Smrg */ 1398472b676d7Smrg 1398572b676d7Smrg switch(offset) { 1398672b676d7Smrg case 0x489: 1398772b676d7Smrg ret = 0x11; /* Default VGA Info */ 1398872b676d7Smrg break; 1398972b676d7Smrg case MODEID_OFF: 1399072b676d7Smrg ret = 0x03; /* Default current display mode */ 1399172b676d7Smrg break; 1399272b676d7Smrg } 1399372b676d7Smrg 1399472b676d7Smrg#ifdef SIS_USE_BIOS_SCRATCH 1399572b676d7Smrg if(SISPTR(pScrn)->Primary) { 1399672b676d7Smrg base = xf86MapVidMem(pScrn->scrnIndex, VIDMEM_MMIO, 0, 0x2000); 1399772b676d7Smrg if(!base) { 1399872b676d7Smrg SISErrorLog(pScrn, "(Could not map BIOS scratch area)\n"); 1399972b676d7Smrg return ret; 1400072b676d7Smrg } 1400172b676d7Smrg 1400272b676d7Smrg ret = *(base + offset); 1400372b676d7Smrg 1400472b676d7Smrg /* value != 0xff means: set register */ 1400572b676d7Smrg if(value != 0xff) { 1400672b676d7Smrg *(base + offset) = value; 1400772b676d7Smrg } 1400872b676d7Smrg 1400972b676d7Smrg xf86UnMapVidMem(pScrn->scrnIndex, base, 0x2000); 1401072b676d7Smrg } 1401172b676d7Smrg#endif 1401272b676d7Smrg return ret; 1401372b676d7Smrg} 1401472b676d7Smrg 1401572b676d7SmrgUChar 1401672b676d7SmrgSiS_GetSetModeID(ScrnInfoPtr pScrn, UChar id) 1401772b676d7Smrg{ 1401872b676d7Smrg return(SiS_GetSetBIOSScratch(pScrn, MODEID_OFF, id)); 1401972b676d7Smrg} 1402072b676d7Smrg 1402172b676d7Smrgvoid 1402272b676d7SmrgSiSMemCopyToVideoRam(SISPtr pSiS, UChar *to, UChar *from, int size) 1402372b676d7Smrg{ 1402472b676d7Smrg if((ULong)to & 15) (*pSiS->SiSFastMemCopy)(to, from, size); 1402572b676d7Smrg else (*pSiS->SiSFastVidCopy)(to, from, size); 1402672b676d7Smrg} 1402772b676d7Smrg 1402872b676d7Smrgvoid 1402972b676d7SmrgSiSMemCopyFromVideoRam(SISPtr pSiS, UChar *to, UChar *from, int size) 1403072b676d7Smrg{ 1403172b676d7Smrg if((ULong)to & 15) (*pSiS->SiSFastMemCopyFrom)(to, from, size); 1403272b676d7Smrg else (*pSiS->SiSFastVidCopyFrom)(to, from, size); 1403372b676d7Smrg} 1403472b676d7Smrg 1403572b676d7Smrgvoid 1403672b676d7SmrgsisSaveUnlockExtRegisterLock(SISPtr pSiS, UChar *reg1, UChar *reg2) 1403772b676d7Smrg{ 1403872b676d7Smrg register UChar val; 1403972b676d7Smrg ULong mylockcalls; 1404072b676d7Smrg#ifdef TWDEBUG 1404172b676d7Smrg UChar val1, val2; 1404272b676d7Smrg int i; 1404372b676d7Smrg#endif 1404472b676d7Smrg 1404572b676d7Smrg pSiS->lockcalls++; 1404672b676d7Smrg mylockcalls = pSiS->lockcalls; 1404772b676d7Smrg 1404872b676d7Smrg /* check if already unlocked */ 1404972b676d7Smrg inSISIDXREG(SISSR, 0x05, val); 1405072b676d7Smrg 1405172b676d7Smrg if(val != 0xa1) { 1405272b676d7Smrg 1405372b676d7Smrg /* save State */ 1405472b676d7Smrg if(reg1) *reg1 = val; 1405572b676d7Smrg 1405672b676d7Smrg /* unlock */ 1405772b676d7Smrg outSISIDXREG(SISSR, 0x05, 0x86); 1405872b676d7Smrg 1405972b676d7Smrg /* Now check again */ 1406072b676d7Smrg inSISIDXREG(SISSR, 0x05, val); 1406172b676d7Smrg 1406272b676d7Smrg if(val != 0xA1) { 1406372b676d7Smrg 1406472b676d7Smrg xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING, 1406572b676d7Smrg "Failed to unlock SR registers at relocated i/o ports\n"); 1406672b676d7Smrg 1406772b676d7Smrg#ifdef TWDEBUG 1406872b676d7Smrg for(i = 0; i <= 0x3f; i++) { 1406972b676d7Smrg inSISIDXREG(SISSR, i, val1); 1407072b676d7Smrg inSISIDXREG(0x3c4, i, val2); 1407172b676d7Smrg xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO, 1407272b676d7Smrg "SR%02d: RelIO=0x%02x 0x3c4=0x%02x (%ld)\n", 1407372b676d7Smrg i, val1, val2, mylockcalls); 1407472b676d7Smrg } 1407572b676d7Smrg#endif 1407672b676d7Smrg 1407772b676d7Smrg /* Emergency measure: unlock at 0x3c4, and try to enable relocated IO ports */ 1407872b676d7Smrg switch(pSiS->VGAEngine) { 1407972b676d7Smrg case SIS_OLD_VGA: 1408072b676d7Smrg case SIS_530_VGA: 1408172b676d7Smrg outSISIDXREG(0x3c4, 0x05, 0x86); 1408272b676d7Smrg andSISIDXREG(0x3c4, 0x33, ~0x20); 1408372b676d7Smrg break; 1408472b676d7Smrg case SIS_300_VGA: 1408572b676d7Smrg case SIS_315_VGA: 1408672b676d7Smrg outSISIDXREG(0x3c4, 0x05, 0x86); 1408772b676d7Smrg orSISIDXREG(0x3c4, 0x20, 0x20); 1408872b676d7Smrg break; 1408972b676d7Smrg } 1409072b676d7Smrg outSISIDXREG(SISSR, 0x05, 0x86); 1409172b676d7Smrg inSISIDXREG(SISSR, 0x05, val); 1409272b676d7Smrg if(val != 0xa1) { 1409372b676d7Smrg SISErrorLog(pSiS->pScrn, 1409472b676d7Smrg "Failed to unlock SR registers (%p, %lx, 0x%02x; %ld)\n", 1409572b676d7Smrg (void *)pSiS, (ULong)pSiS->RelIO, val, mylockcalls); 1409672b676d7Smrg /* Now await doom... */ 1409772b676d7Smrg } 1409872b676d7Smrg } 1409972b676d7Smrg } 1410072b676d7Smrg if((pSiS->VGAEngine == SIS_OLD_VGA) || (pSiS->VGAEngine == SIS_530_VGA)) { 1410172b676d7Smrg inSISIDXREG(SISCR, 0x80, val); 1410272b676d7Smrg if(val != 0xa1) { 1410372b676d7Smrg /* save State */ 1410472b676d7Smrg if(reg2) *reg2 = val; 1410572b676d7Smrg outSISIDXREG(SISCR, 0x80, 0x86); 1410672b676d7Smrg inSISIDXREG(SISCR, 0x80, val); 1410772b676d7Smrg if(val != 0xA1) { 1410872b676d7Smrg SISErrorLog(pSiS->pScrn, 1410972b676d7Smrg "Failed to unlock cr registers (%p, %lx, 0x%02x)\n", 1411072b676d7Smrg (void *)pSiS, (ULong)pSiS->RelIO, val); 1411172b676d7Smrg } 1411272b676d7Smrg } 1411372b676d7Smrg } 1411472b676d7Smrg} 1411572b676d7Smrg 1411672b676d7Smrgvoid 1411772b676d7SmrgsisRestoreExtRegisterLock(SISPtr pSiS, UChar reg1, UChar reg2) 1411872b676d7Smrg{ 1411972b676d7Smrg /* restore lock */ 1412072b676d7Smrg#ifndef UNLOCK_ALWAYS 1412172b676d7Smrg outSISIDXREG(SISSR, 0x05, reg1 == 0xA1 ? 0x86 : 0x00); 1412272b676d7Smrg if((pSiS->VGAEngine == SIS_OLD_VGA) || (pSiS->VGAEngine == SIS_530_VGA)) { 1412372b676d7Smrg outSISIDXREG(SISCR, 0x80, reg2 == 0xA1 ? 0x86 : 0x00); 1412472b676d7Smrg } 1412572b676d7Smrg#endif 1412672b676d7Smrg} 1412772b676d7Smrg 14128