1/* 2 * Mode setup and basic video bridge detection 3 * 4 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria. 5 * 6 * The SISInit() function for old series (except TV and FIFO calculation) 7 * was previously based on code which was Copyright (C) 1998,1999 by Alan 8 * Hourihane, Wigan, England. However, the code has been rewritten entirely 9 * and is - it its current representation - not covered by this old copyright. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1) Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2) Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3) The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 * Author: Thomas Winischhofer <thomas@winischhofer.net> 34 * 35 */ 36 37#ifdef HAVE_CONFIG_H 38#include "config.h" 39#endif 40 41#include "sis.h" 42#define SIS_NEED_inSISREG 43#define SIS_NEED_outSISREG 44#define SIS_NEED_inSISIDXREG 45#define SIS_NEED_outSISIDXREG 46#define SIS_NEED_orSISIDXREG 47#define SIS_NEED_andSISIDXREG 48#include "sis_regs.h" 49#include "sis_dac.h" 50 51static Bool SISInit(ScrnInfoPtr pScrn, DisplayModePtr mode); 52static Bool SIS300Init(ScrnInfoPtr pScrn, DisplayModePtr mode); 53static int SIS6326DoSense(ScrnInfoPtr pScrn, int tempbh, int tempbl, int tempch, int tempcl); 54static void SISSense6326(ScrnInfoPtr pScrn); 55static void SiS6326TVDelay(ScrnInfoPtr pScrn, int delay); 56extern void SISSense30x(ScrnInfoPtr pScrn, Bool quiet); 57extern void SISSenseChrontel(ScrnInfoPtr pScrn, Bool quiet); 58 59/* Our very own vgaHW functions */ 60void SiSVGASave(ScrnInfoPtr pScrn, SISRegPtr save, int flags); 61void SiSVGARestore(ScrnInfoPtr pScrn, SISRegPtr restore, int flags); 62void SiSVGASaveFonts(ScrnInfoPtr pScrn); 63void SiSVGARestoreFonts(ScrnInfoPtr pScrn); 64void SISVGALock(SISPtr pSiS); 65void SiSVGAUnlock(SISPtr pSiS); 66void SiSVGAProtect(ScrnInfoPtr pScrn, Bool on); 67#ifdef SIS_PC_PLATFORM 68Bool SiSVGAMapMem(ScrnInfoPtr pScrn); 69void SiSVGAUnmapMem(ScrnInfoPtr pScrn); 70#endif 71Bool SiSVGASaveScreen(ScreenPtr pScreen, int mode); 72static Bool SiSVGAInit(ScrnInfoPtr pScrn, DisplayModePtr mode, int fixsync); 73 74const CARD8 SiS6326TVRegs1[14] = { 75 0x00,0x01,0x02,0x03,0x04,0x11,0x12,0x13,0x21,0x26,0x27,0x3a,0x3c,0x43 76}; 77 78const CARD8 SiS6326TVRegs1_NTSC[6][14] = { 79 {0x81,0x3f,0x49,0x1b,0xa9,0x03,0x00,0x09,0x08,0x7d,0x00,0x88,0x30,0x60}, 80 {0x81,0x3f,0x49,0x1d,0xa0,0x03,0x00,0x09,0x08,0x7d,0x00,0x88,0x30,0x60}, 81 {0x81,0x45,0x24,0x8e,0x26,0x0b,0x00,0x09,0x02,0xfe,0x00,0x09,0x51,0x60}, 82 {0x81,0x45,0x24,0x8e,0x26,0x07,0x00,0x29,0x04,0x30,0x10,0x3b,0x61,0x60}, 83 {0x81,0x3f,0x24,0x8e,0x26,0x09,0x00,0x09,0x02,0x30,0x10,0x3b,0x51,0x60}, /* 640x400, 640x480 */ 84 {0x83,0x5d,0x21,0xbe,0x75,0x03,0x00,0x09,0x08,0x42,0x10,0x4d,0x61,0x79} /* 640x480u */ 85}; 86 87const CARD8 SiS6326TVRegs2_NTSC[6][54] = { 88 {0x11, 0x17, 0x03, 0x09, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C, 89 0x0C, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94, 90 0xFC, 0xDF, 0x94, 0x1F, 0x4A, 0x03, 0x71, 0x07, 0x97, 0x10, 0x40, 91 0x48, 0x00, 0x26, 0xB6, 0x10, 0x5C, 0xEC, 0x21, 0x2E, 0xBE, 0x10, 92 0x64, 0xF4, 0x21, 0x13, 0x75, 0x08, 0x31, 0x6A, 0x01, 0xA0}, 93 {0x11, 0x17, 0x03, 0x0A, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C, 94 0x0D, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94, 95 0xFF, 0xDF, 0x94, 0x1F, 0x4A, 0x03, 0x71, 0x07, 0x97, 0x10, 0x40, 96 0x48, 0x00, 0x26, 0xB6, 0x10, 0x5C, 0xEC, 0x21, 0x2E, 0xBE, 0x10, 97 0x64, 0xF4, 0x21, 0x13, 0x75, 0x08, 0x31, 0x6A, 0x01, 0xA0}, 98 {0x11, 0x17, 0x03, 0x0A, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C, 99 0x0D, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94, 100 0xFF, 0xDF, 0x94, 0x3F, 0x8C, 0x06, 0xCE, 0x07, 0x27, 0x30, 0x73, 101 0x7B, 0x00, 0x48, 0x68, 0x30, 0xB2, 0xD2, 0x52, 0x50, 0x70, 0x30, 102 0xBA, 0xDA, 0x52, 0xDC, 0x02, 0xD1, 0x53, 0xF7, 0x02, 0xA0}, 103 {0x11, 0x17, 0x03, 0x09, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C, 104 0x0C, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94, 105 0xDC, 0xDF, 0x94, 0x3F, 0x8C, 0x06, 0xCE, 0x07, 0x27, 0x30, 0x73, 106 0x7B, 0x00, 0x48, 0x68, 0x30, 0xB2, 0xD2, 0x52, 0x50, 0x70, 0x30, 107 0xBA, 0xDA, 0x52, 0x00, 0x02, 0xF5, 0x53, 0xF7, 0x02, 0xA0}, 108 {0x11, 0x17, 0x03, 0x09, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C, 109 0x0C, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94, 110 0xDC, 0xDF, 0x94, 0x3F, 0x8C, 0x06, 0xCE, 0x07, 0x27, 0x30, 0x73, 111 0x7B, 0x00, 0x48, 0x68, 0x30, 0xB2, 0xD2, 0x52, 0x50, 0x70, 0x30, 112 0xBA, 0xDA, 0x52, 0xDC, 0x02, 0xD1, 0x53, 0xF7, 0x02, 0xA0}, 113 {0x11, 0x17, 0x03, 0x09, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C, /* 640x480u */ 114 0x0C, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94, 115 0xDC, 0xDF, 0x94, 0xAF, 0x95, 0x06, 0xDD, 0x07, 0x5F, 0x30, 0x7E, 116 0x86, 0x00, 0x4C, 0xA4, 0x30, 0xE3, 0x3B, 0x62, 0x54, 0xAC, 0x30, 117 0xEB, 0x43, 0x62, 0x48, 0x34, 0x3D, 0x63, 0x29, 0x03, 0xA0} 118}; 119 120const CARD8 SiS6326TVRegs1_PAL[6][14] = { 121 {0x81,0x2d,0xc8,0x07,0xb2,0x0b,0x00,0x09,0x02,0xed,0x00,0xf8,0x30,0x40}, 122 {0x80,0x2d,0xa4,0x03,0xd9,0x0b,0x00,0x09,0x02,0xed,0x10,0xf8,0x71,0x40}, 123 {0x81,0x2d,0xa4,0x03,0xd9,0x0b,0x00,0x09,0x02,0xed,0x10,0xf8,0x71,0x40}, /* 640x480 */ 124 {0x81,0x2d,0xa4,0x03,0xd9,0x0b,0x00,0x09,0x02,0x8f,0x10,0x9a,0x71,0x40}, /* 800x600 */ 125 {0x83,0x63,0xa1,0x7a,0xa3,0x0a,0x00,0x09,0x02,0xb5,0x11,0xc0,0x81,0x59}, /* 800x600u */ 126 {0x81,0x63,0xa4,0x03,0xd9,0x01,0x00,0x09,0x10,0x9f,0x10,0xaa,0x71,0x59} /* 720x540 */ 127}; 128 129const CARD8 SiS6326TVRegs2_PAL[6][54] = { 130 {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, 131 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94, 132 0xE5, 0xDF, 0x94, 0xEF, 0x5A, 0x03, 0x7F, 0x07, 0xFF, 0x10, 0x4E, 133 0x56, 0x00, 0x2B, 0x23, 0x20, 0xB4, 0xAC, 0x31, 0x33, 0x2B, 0x20, 134 0xBC, 0xB4, 0x31, 0x83, 0xE1, 0x78, 0x31, 0xD6, 0x01, 0xA0}, 135 {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, 136 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94, 137 0xE5, 0xDF, 0x94, 0xDF, 0xB2, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x90, 138 0x98, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40, 139 0x6A, 0x5A, 0x73, 0x03, 0xC1, 0xF8, 0x63, 0xB6, 0x03, 0xA0}, 140 {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, /* 640x480 */ 141 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94, 142 0xE5, 0xDF, 0x94, 0xDF, 0xB2, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x90, 143 0x98, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40, 144 0x6A, 0x5A, 0x73, 0x03, 0xC1, 0xF8, 0x63, 0xB6, 0x03, 0xA0}, 145 {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, /* 800x600 */ 146 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94, 147 0xE5, 0xDF, 0x94, 0xDF, 0xB2, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x90, 148 0x98, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40, 149 0x6A, 0x5A, 0x73, 0xA0, 0xC1, 0x95, 0x73, 0xB6, 0x03, 0xA0}, 150 {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, /* 800x600u */ 151 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94, 152 0xE5, 0xDF, 0x94, 0x7F, 0xBD, 0x08, 0x0E, 0x07, 0x47, 0x40, 0x9D, 153 0xA5, 0x00, 0x54, 0x94, 0x40, 0xA4, 0xE4, 0x73, 0x5C, 0x9C, 0x40, 154 0xAC, 0xEC, 0x73, 0x0B, 0x0E, 0x00, 0x84, 0x03, 0x04, 0xA0}, 155 {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, /* 720x540 */ 156 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94, 157 0xE5, 0xDF, 0x94, 0xDF, 0xB0, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x9D, 158 0xA5, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40, 159 0x6A, 0x5A, 0x73, 0xA0, 0xC1, 0x95, 0x73, 0xB6, 0x03, 0xA0} 160}; 161 162const CARD8 SiS6326CR[9][15] = { 163 {0x79,0x63,0x64,0x1d,0x6a,0x93,0x00,0x6f,0xf0,0x58,0x8a,0x57,0x57,0x70,0x20}, /* PAL 800x600 */ 164 {0x79,0x4f,0x50,0x95,0x60,0x93,0x00,0x6f,0xba,0x14,0x86,0xdf,0xe0,0x30,0x00}, /* PAL 640x480 */ 165 {0x5f,0x4f,0x50,0x82,0x53,0x9f,0x00,0x0b,0x3e,0xe9,0x8b,0xdf,0xe7,0x04,0x00}, /* NTSC 640x480 */ 166 {0x5f,0x4f,0x50,0x82,0x53,0x9f,0x00,0x0b,0x3e,0xcb,0x8d,0x8f,0x96,0xe9,0x00}, /* NTSC 640x400 */ 167 {0x83,0x63,0x64,0x1f,0x6d,0x9b,0x00,0x6f,0xf0,0x48,0x0a,0x23,0x57,0x70,0x20}, /* PAL 800x600u */ 168 {0x79,0x59,0x5b,0x1d,0x66,0x93,0x00,0x6f,0xf0,0x42,0x04,0x1b,0x40,0x70,0x20}, /* PAL 720x540 */ 169 {0x66,0x4f,0x51,0x0a,0x57,0x89,0x00,0x0b,0x3e,0xd9,0x0b,0xb6,0xe7,0x04,0x00}, /* NTSC 640x480u */ 170 {0xce,0x9f,0x9f,0x92,0xa4,0x16,0x00,0x28,0x5a,0x00,0x04,0xff,0xff,0x29,0x39}, /* 1280x1024-75 */ 171 {0x09,0xc7,0xc7,0x0d,0xd2,0x0a,0x01,0xe0,0x10,0xb0,0x04,0xaf,0xaf,0xe1,0x1f} /* 1600x1200-60 */ 172}; 173 174/* Initialize a display mode on 5597/5598, 6326 and 530/620 */ 175static Bool 176SISInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 177{ 178 SISPtr pSiS = SISPTR(pScrn); 179 SISRegPtr pReg = &pSiS->ModeReg; 180 UChar temp; 181 int mclk = pSiS->MemClock; 182 int clock = mode->Clock; 183 int width = mode->HDisplay; 184 int height = mode->VDisplay; 185 int rate = (int)SiSCalcVRate(mode); 186 int buswidth = pSiS->BusWidth; 187 unsigned int vclk[5]; 188 UShort CRT_CPUthresholdLow, CRT_CPUthresholdHigh, CRT_ENGthreshold; 189 double a, b, c; 190 int d, factor, offset, fixsync = 1; 191 int num, denum, div, sbit, scale; 192 Bool sis6326tvmode, sis6326himode; 193 194 /* Save the registers for further processing */ 195 (*pSiS->SiSSave)(pScrn, pReg); 196 197 /* Initialise the standard VGA registers */ 198 if(!pSiS->UseVESA) { 199 if(!SiSVGAInit(pScrn, mode, fixsync)) { 200 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "SISInit: SiSVGAInit() failed\n"); 201 return FALSE; 202 } 203 } 204 205 /* Determine if chosen mode is suitable for TV on the 6326 206 * and if the mode is one of our special hi-res modes. 207 */ 208 sis6326tvmode = FALSE; 209 sis6326himode = FALSE; 210 if(pSiS->Chipset == PCI_CHIP_SIS6326) { 211 if(pSiS->SiS6326Flags & SIS6326_HASTV) { 212 if((pSiS->SiS6326Flags & SIS6326_TVDETECTED) && 213 ((strcmp(mode->name, "PAL800x600") == 0) || /* Special TV modes */ 214 (strcmp(mode->name, "PAL800x600U") == 0) || 215 (strcmp(mode->name, "PAL720x540") == 0) || 216 (strcmp(mode->name, "PAL640x480") == 0) || 217 (strcmp(mode->name, "NTSC640x480") == 0) || 218 (strcmp(mode->name, "NTSC640x480U") == 0) || 219 (strcmp(mode->name, "NTSC640x400") == 0))) { 220 sis6326tvmode = TRUE; 221 } else { 222 pReg->sis6326tv[0x00] &= 0xfb; 223 } 224 } 225 if((strcmp(mode->name, "SIS1280x1024-75") == 0) || /* Special high-res modes */ 226 (strcmp(mode->name, "SIS1600x1200-60") == 0)) { 227 sis6326himode = TRUE; 228 } 229 } 230 231#ifdef UNLOCK_ALWAYS 232 outSISIDXREG(SISSR, 0x05, 0x86); 233#endif 234 235 if(!pSiS->UseVESA) { 236 pReg->sisRegs3C4[0x06] &= 0x01; 237 } 238 239 /* set interlace */ 240 if(!(mode->Flags & V_INTERLACE)) { 241 offset = pSiS->CurrentLayout.displayWidth >> 3; 242 } else { 243 offset = pSiS->CurrentLayout.displayWidth >> 2; 244 if(!pSiS->UseVESA) { 245 pReg->sisRegs3C4[0x06] |= 0x20; 246 } 247 } 248 249 /* Enable Linear and Enhanced Gfx Mode */ 250 if(!pSiS->UseVESA) { 251 pReg->sisRegs3C4[0x06] |= 0x82; 252 } 253 254 /* Enable MMIO at PCI Register 14H (D[6:5]: 11) */ 255 if(pSiS->oldChipset >= OC_SIS5597) { 256 pReg->sisRegs3C4[0x0B] |= 0x60; 257 } else { 258 pReg->sisRegs3C4[0x0B] |= 0x20; 259 pReg->sisRegs3C4[0x0B] &= ~0x40; 260 } 261 262 if(!pSiS->UseVESA) { 263 264 /* Enable 32bit mem access (D7), read-ahead cache (D5) */ 265 pReg->sisRegs3C4[0x0C] |= 0x80; 266 if(pSiS->oldChipset > OC_SIS6225) { 267 pReg->sisRegs3C4[0x0C] |= 0x20; 268 } 269 270 /* Some speed-up stuff */ 271 switch(pSiS->Chipset) { 272 case PCI_CHIP_SIS5597: 273 /* enable host bus */ 274 if(!pSiS->HostBus) { 275 pReg->sisRegs3C4[0x34] &= ~0x08; 276 } else { 277 pReg->sisRegs3C4[0x34] |= 0x08; 278 } 279 /* fall through */ 280 case PCI_CHIP_SIS6326: 281 case PCI_CHIP_SIS530: 282 /* Enable "dual segment register mode" (D2) and "i/o gating while 283 * write buffer is not empty" (D3) 284 */ 285 pReg->sisRegs3C4[0x0B] |= 0x0C; 286 } 287 288 /* set colordepth */ 289 if(pSiS->Chipset == PCI_CHIP_SIS530) { 290 pReg->sisRegs3C4[0x09] &= 0x7F; 291 } 292 switch(pSiS->CurrentLayout.bitsPerPixel) { 293 case 8: 294 break; 295 case 16: 296 offset <<= 1; 297 if(pSiS->CurrentLayout.depth == 15) 298 pReg->sisRegs3C4[0x06] |= 0x04; 299 else 300 pReg->sisRegs3C4[0x06] |= 0x08; 301 break; 302 case 24: 303 offset += (offset << 1); 304 pReg->sisRegs3C4[0x06] |= 0x10; 305 pReg->sisRegs3C4[0x0B] |= 0x90; 306 break; 307 case 32: 308 if(pSiS->Chipset == PCI_CHIP_SIS530) { 309 offset <<= 2; 310 if(pSiS->oldChipset != OC_SIS620) { 311 pReg->sisRegs3C4[0x06] |= 0x10; 312 } 313 pReg->sisRegs3C4[0x0B] |= 0x90; 314 pReg->sisRegs3C4[0x09] |= 0x80; 315 } else return FALSE; 316 break; 317 } 318 } 319 320 /* save screen pitch for acceleration functions */ 321 pSiS->scrnOffset = pSiS->CurrentLayout.displayWidth * 322 ((pSiS->CurrentLayout.bitsPerPixel + 7) / 8); 323 324 /* Set accelerator dest color depth to 0 - not supported on 530/620 */ 325 pSiS->DstColor = 0; 326 327 if(!pSiS->UseVESA) { 328 329 /* set linear framebuffer addresses */ 330 switch(pScrn->videoRam) { 331 case 512: temp = 0x00; break; 332 case 1024: temp = 0x20; break; 333 case 2048: temp = 0x40; break; 334 case 4096: temp = 0x60; break; 335 case 8192: temp = 0x80; break; 336 default: temp = 0x20; 337 } 338 pReg->sisRegs3C4[0x20] = (pSiS->FbAddress & 0x07F80000) >> 19; 339 pReg->sisRegs3C4[0x21] = ((pSiS->FbAddress & 0xF8000000) >> 27) | temp; 340 341 /* Set screen offset */ 342 pReg->sisRegs3D4[0x13] = offset & 0xFF; 343 344 /* Set CR registers for our built-in TV and hi-res modes */ 345 if((sis6326tvmode) || (sis6326himode)) { 346 347 int index,i; 348 349 /* We need our very private data for hi-res and TV modes */ 350 if(sis6326himode) { 351 if(strcmp(mode->name, "SIS1280x1024-75") == 0) index = 7; 352 else index = 8; 353 } else { 354 if(pSiS->SiS6326Flags & SIS6326_TVPAL) { 355 switch(width) { 356 case 800: 357 if((strcmp(mode->name, "PAL800x600U") == 0)) 358 index = 4; 359 else 360 index = 0; 361 break; 362 case 720: 363 index = 5; 364 break; 365 case 640: 366 default: 367 index = 1; 368 } 369 } else { 370 switch(height) { 371 case 400: 372 index = 3; 373 break; 374 case 480: 375 default: 376 if((strcmp(mode->name, "NTSC640x480U") == 0)) 377 index = 6; 378 else 379 index = 2; 380 } 381 } 382 } 383 for(i=0; i<=5; i++) { 384 pReg->sisRegs3D4[i] = SiS6326CR[index][i]; 385 } 386 pReg->sisRegs3C4[0x12] = SiS6326CR[index][6]; 387 pReg->sisRegs3D4[6] = SiS6326CR[index][7]; 388 pReg->sisRegs3D4[7] = SiS6326CR[index][8]; 389 pReg->sisRegs3D4[0x10] = SiS6326CR[index][9]; 390 pReg->sisRegs3D4[0x11] = SiS6326CR[index][10]; 391 pReg->sisRegs3D4[0x12] = SiS6326CR[index][11]; 392 pReg->sisRegs3D4[0x15] = SiS6326CR[index][12]; 393 pReg->sisRegs3D4[0x16] = SiS6326CR[index][13]; 394 pReg->sisRegs3D4[9] &= ~0x20; 395 pReg->sisRegs3D4[9] |= (SiS6326CR[index][14] & 0x20); 396 pReg->sisRegs3C4[0x0A] = ((offset & 0xF00) >> 4) | (SiS6326CR[index][14] & 0x0f); 397 398 } else { 399 400 /* Set extended vertical overflow register */ 401 pReg->sisRegs3C4[0x0A] = ( 402 ((offset & 0xF00) >> 4) | 403 (((mode->CrtcVTotal - 2) & 0x400) >> 10) | 404 (((mode->CrtcVDisplay - 1) & 0x400) >> 9) | 405 (((mode->CrtcVBlankStart - 1) & 0x400) >> 8) | 406 (((mode->CrtcVSyncStart - fixsync) & 0x400) >> 7)); 407 408 /* Set extended horizontal overflow register */ 409 pReg->sisRegs3C4[0x12] &= 0xE0; 410 pReg->sisRegs3C4[0x12] |= ( 411 ((((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8) | 412 ((((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) | 413 ((((mode->CrtcHBlankStart >> 3) - 1) & 0x100) >> 6) | 414 ((((mode->CrtcHSyncStart >> 3) - fixsync)& 0x100) >> 5) | 415 ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 2)); 416 } 417 418 /* enable (or disable) line compare */ 419 if(mode->CrtcVDisplay >= 1024) 420 pReg->sisRegs3C4[0x38] |= 0x04; 421 else 422 pReg->sisRegs3C4[0x38] &= 0xFB; 423 424 /* Enable (or disable) high speed DCLK (some 6326 and 530/620 only) */ 425 if( ( (pSiS->Chipset == PCI_CHIP_SIS6326) && 426 ( (pSiS->ChipRev == 0xd0) || (pSiS->ChipRev == 0xd1) || 427 (pSiS->ChipRev == 0xd2) || (pSiS->ChipRev == 0x92) || 428 (pSiS->Flags & A6326REVAB) ) ) || 429 (pSiS->oldChipset > OC_SIS6326) ) { 430 if( (pSiS->CurrentLayout.bitsPerPixel == 24) || 431 (pSiS->CurrentLayout.bitsPerPixel == 32) || 432 (mode->CrtcHDisplay >= 1280) ) 433 pReg->sisRegs3C4[0x3E] |= 0x01; 434 else 435 pReg->sisRegs3C4[0x3E] &= 0xFE; 436 } 437 438 /* We use the internal VCLK */ 439 pReg->sisRegs3C4[0x38] &= 0xFC; 440 441 /* Programmable Clock */ 442 pReg->sisRegs3C2 = inSISREG(SISMISCR) | 0x0C; 443 444#if 0 445 if(pSiS->oldChipset <= OC_SIS86202) { 446 /* TODO: Handle SR07 for clock selection */ 447 /* 86C201 does not even have a programmable clock... */ 448 /* pReg->sisRegs3C4[0x07] &= 0x??; */ 449 } 450#endif 451 452 /* Set VCLK */ 453 if((sis6326tvmode) || (sis6326himode)) { 454 455 /* For our built-in modes, the calculation is not suitable */ 456 if(sis6326himode) { 457 if((strcmp(mode->name, "SIS1280x1024-75") == 0)) { 458 pReg->sisRegs3C4[0x2A] = 0x5d; /* 1280x1024-75 */ 459 pReg->sisRegs3C4[0x2B] = 0xa4; 460 } else { 461 pReg->sisRegs3C4[0x2A] = 0x59; /* 1600x1200-60 */ 462 pReg->sisRegs3C4[0x2B] = 0xa3; 463 } 464 pReg->sisRegs3C4[0x13] &= ~0x40; 465 } else { 466 if(pSiS->SiS6326Flags & SIS6326_TVPAL) { 467 /* PAL: 31.500 Mhz */ 468 if((strcmp(mode->name, "PAL800x600U") == 0)) { 469 pReg->sisRegs3C4[0x2A] = 0x46; 470 pReg->sisRegs3C4[0x2B] = 0x49; 471 } else { 472 pReg->sisRegs3C4[0x2A] = 0xab; 473 pReg->sisRegs3C4[0x2B] = 0xe9; 474 } 475 pReg->sisRegs3C4[0x13] &= ~0x40; 476 } else { 477 /* NTSC: 27.000 Mhz */ 478 if((strcmp(mode->name, "NTSC640x480U") == 0)) { 479 pReg->sisRegs3C4[0x2A] = 0x5a; 480 pReg->sisRegs3C4[0x2B] = 0x65; 481 } else { 482 pReg->sisRegs3C4[0x2A] = 0x29; 483 pReg->sisRegs3C4[0x2B] = 0xe2; 484 } 485 pReg->sisRegs3C4[0x13] |= 0x40; 486 } 487 } 488 489 } else if(SiS_compute_vclk(clock, &num, &denum, &div, &sbit, &scale)) { 490 491 pReg->sisRegs3C4[0x2A] = (num - 1) & 0x7f ; 492 pReg->sisRegs3C4[0x2A] |= (div == 2) ? 0x80 : 0; 493 pReg->sisRegs3C4[0x2B] = ((denum - 1) & 0x1f); 494 pReg->sisRegs3C4[0x2B] |= (((scale -1) & 3) << 5); 495 496 /* When setting VCLK, we should set SR13 first */ 497 if(sbit) 498 pReg->sisRegs3C4[0x13] |= 0x40; 499 else 500 pReg->sisRegs3C4[0x13] &= 0xBF; 501 502#ifdef TWDEBUG 503 xf86DrvMsg(0, X_INFO, "2a: %x 2b: %x 13: %x clock %d\n", 504 pReg->sisRegs3C4[0x2A], pReg->sisRegs3C4[0x2B], pReg->sisRegs3C4[0x13], clock); 505#endif 506 507 } else { 508 509 /* if SiS_compute_vclk cannot handle the requested clock, try sisCalcClock */ 510 SiSCalcClock(pScrn, clock, 2, vclk); 511 512#define Midx 0 513#define Nidx 1 514#define VLDidx 2 515#define Pidx 3 516#define PSNidx 4 517 518 pReg->sisRegs3C4[0x2A] = (vclk[Midx] - 1) & 0x7f; 519 pReg->sisRegs3C4[0x2A] |= ((vclk[VLDidx] == 2) ? 1 : 0) << 7; 520 521 /* D[4:0]: denumerator */ 522 pReg->sisRegs3C4[0x2B] = (vclk[Nidx] - 1) & 0x1f; 523 524 if(vclk[Pidx] <= 4){ 525 /* postscale 1,2,3,4 */ 526 pReg->sisRegs3C4[0x2B] |= (vclk[Pidx] - 1) << 5; 527 pReg->sisRegs3C4[0x13] &= 0xBF; 528 } else { 529 /* postscale 6,8 */ 530 pReg->sisRegs3C4[0x2B] |= ((vclk[Pidx] / 2) - 1) << 5; 531 pReg->sisRegs3C4[0x13] |= 0x40; 532 } 533 pReg->sisRegs3C4[0x2B] |= 0x80 ; /* gain for high frequency */ 534 535 } 536 537 /* High speed DAC */ 538 if(clock > 135000) 539 pReg->sisRegs3C4[0x07] |= 0x02; 540 541 if(pSiS->oldChipset > OC_SIS6225) { 542 /* 1 or 2 cycle DRAM (set by option FastVram) */ 543 if(pSiS->newFastVram == -1) { 544 if(pSiS->oldChipset == OC_SIS620) { 545 /* Use different default on the 620 */ 546 pReg->sisRegs3C4[0x34] |= 0x40; 547 pReg->sisRegs3C4[0x34] &= ~0x80; 548 } else { 549 pReg->sisRegs3C4[0x34] |= 0x80; 550 pReg->sisRegs3C4[0x34] &= ~0x40; 551 } 552 } else if(pSiS->newFastVram == 1) 553 pReg->sisRegs3C4[0x34] |= 0xC0; 554 else 555 pReg->sisRegs3C4[0x34] &= ~0xC0; 556 557 if(pSiS->oldChipset == OC_SIS620) { 558 /* Enable SGRAM burst timing (= bit clear) on the 620 */ 559 if(pSiS->Flags & SYNCDRAM) { 560 pReg->sisRegs3C4[0x35] &= ~0x20; 561 } else { 562 pReg->sisRegs3C4[0x35] |= 0x20; 563 } 564 } 565 } 566 567 } /* VESA */ 568 569 /* Logical line length */ 570 pSiS->ValidWidth = TRUE; 571 pReg->sisRegs3C4[0x27] &= 0xCF; 572 if(pSiS->CurrentLayout.bitsPerPixel == 24) { 573 /* "Invalid logical width" */ 574 pReg->sisRegs3C4[0x27] |= 0x30; 575 pSiS->ValidWidth = FALSE; 576 } else { 577 switch(pScrn->virtualX * (pSiS->CurrentLayout.bitsPerPixel >> 3)) { 578 case 1024: 579 pReg->sisRegs3C4[0x27] |= 0x00; 580 break; 581 case 2048: 582 pReg->sisRegs3C4[0x27] |= 0x10; 583 break; 584 case 4096: 585 pReg->sisRegs3C4[0x27] |= 0x20; 586 break; 587 default: 588 /* Invalid logical width */ 589 pReg->sisRegs3C4[0x27] |= 0x30; 590 pSiS->ValidWidth = FALSE; 591 break; 592 } 593 } 594 595 /* Acceleration stuff */ 596 if(!pSiS->NoAccel) { 597 pReg->sisRegs3C4[0x27] |= 0x40; /* Enable engine programming registers */ 598 if( (pSiS->TurboQueue) && /* Handle TurboQueue */ 599 (pSiS->oldChipset > OC_SIS6225) && 600 ( (pSiS->Chipset != PCI_CHIP_SIS530) || 601 (pSiS->CurrentLayout.bitsPerPixel != 24) ) ) { 602 pReg->sisRegs3C4[0x27] |= 0x80; /* Enable TQ */ 603 if((pSiS->Chipset == PCI_CHIP_SIS530) || 604 ((pSiS->Chipset == PCI_CHIP_SIS6326 && 605 (pSiS->ChipRev == 0xd0 || pSiS->ChipRev == 0xd1 || 606 pSiS->ChipRev == 0xd2 || pSiS->ChipRev == 0x92 || 607 pSiS->ChipRev == 0x0a || pSiS->ChipRev == 0x1a || 608 pSiS->ChipRev == 0x2a || pSiS->ChipRev == 0x0b || 609 pSiS->ChipRev == 0x1b || pSiS->ChipRev == 0x2b) ) ) ) { 610 /* pReg->sisRegs3C4[0x3D] |= 0x80; */ /* Queue is 62K (530/620 specs) */ 611 pReg->sisRegs3C4[0x3D] &= 0x7F; /* Queue is 30K (530/620 specs) */ 612 } 613 /* Locate the TQ at the beginning of the last 64K block of 614 * video RAM. The address is to be specified in 32K steps. 615 */ 616 pReg->sisRegs3C4[0x2C] = (pScrn->videoRam - 64) / 32; 617 if(pSiS->Chipset != PCI_CHIP_SIS530) { /* 530/620: Reserved (don't touch) */ 618 pReg->sisRegs3C4[0x3C] &= 0xFC; /* 6326: Queue is all for 2D */ 619 } /* 5597: Must be 0 */ 620 } else { 621 pReg->sisRegs3C4[0x27] &= 0x7F; 622 } 623 } 624 625 626 if(!pSiS->UseVESA) { 627 628 /* No idea what this does. The Windows driver does it, so we do it as well */ 629 if(pSiS->Chipset == PCI_CHIP_SIS6326) { 630 if((pSiS->ChipRev == 0xd0) || (pSiS->ChipRev == 0xd1) || 631 (pSiS->ChipRev == 0xd2) || (pSiS->ChipRev == 0x92) || 632 (pSiS->Flags & A6326REVAB)) { 633 if((pSiS->Flags & (SYNCDRAM | RAMFLAG)) == (SYNCDRAM | RAMFLAG)) { 634 if(!(pReg->sisRegs3C4[0x0E] & 0x03)) { 635 pReg->sisRegs3C4[0x3E] |= 0x02; 636 } 637 } 638 } 639 } 640 641 /* Set memclock */ 642#if 0 643 /* We don't need to do this; the SetMClk option was not used since 4.0. */ 644 if((pSiS->Chipset == PCI_CHIP_SIS5597) || (pSiS->Chipset == PCI_CHIP_SIS6326)) { 645 if(pSiS->MemClock > 66000) { 646 SiSCalcClock(pScrn, pSiS->MemClock, 1, vclk); 647 648 pReg->sisRegs3C4[0x28] = (vclk[Midx] - 1) & 0x7f ; 649 pReg->sisRegs3C4[0x28] |= ((vclk[VLDidx] == 2 ) ? 1 : 0 ) << 7 ; 650 pReg->sisRegs3C4[0x29] = (vclk[Nidx] -1) & 0x1f ; /* bits [4:0] contain denumerator -MC */ 651 if(vclk[Pidx] <= 4) { 652 pReg->sisRegs3C4[0x29] |= (vclk[Pidx] - 1) << 5 ; /* postscale 1,2,3,4 */ 653 pReg->sisRegs3C4[0x13] &= 0x7F; 654 } else { 655 pReg->sisRegs3C4[0x29] |= ((vclk[Pidx] / 2) - 1) << 5 ; /* postscale 6,8 */ 656 pReg->sisRegs3C4[0x13] |= 0x80; 657 } 658 /* Check programmed memory clock. Enable only to check the above code */ 659/* 660 mclk = 14318 * ((pReg->sisRegs3C4[0x28] & 0x7f) + 1); 661 mclk /= ((pReg->sisRegs3C4[0x29] & 0x0f) + 1); 662 if(!(pReg->sisRegs3C4[0x13] & 0x80)) { 663 mclk /= (((pReg->sisRegs3C4[0x29] & 0x60) >> 5) + 1); 664 } else { 665 if((pReg->sisRegs3C4[0x29] & 0x60) == 0x40) mclk /= 6; 666 if((pReg->sisRegs3C4[0x29] & 0x60) == 0x60) mclk /= 8; 667 } 668 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,2, 669 "Setting memory clock to %.3f MHz\n", 670 mclk/1000.0); 671*/ 672 } 673 } 674#endif 675 676 /* Set threshold values */ 677 /* 678 * CPU/CRT Threshold: FIFO 679 * MCLK ___________ VCLK 680 * cpu/engine <---o o--------->|___________| -----------> CRT 681 * ^ ^ ^ ^ 682 * \ / | | 683 * \ / |< gap >| 684 * \ / | | 685 * selector switch Thrsh. low high 686 * 687 * CRT consumes the data in the FIFO during scanline display. When the 688 * amount of data in the FIFO reaches the Threshold low value, the selector 689 * switch will switch to the right, and the FIFO will be refilled with data. 690 * When the amount of data in the FIFO reaches the Threshold high value, the 691 * selector switch will switch to the left and allows the CPU and the chip 692 * engines to access the video RAM. 693 * 694 * The Threshold low values should be increased at higher bpps, simply because 695 * there is more data needed for the CRT. When Threshold low and high are very 696 * close to each other, the selector switch will be activated more often, which 697 * decreases performance. 698 * 699 */ 700 switch(pSiS->Chipset) { 701 case PCI_CHIP_SIS5597: factor = 65; break; 702 case PCI_CHIP_SIS6326: factor = 30; break; 703 case PCI_CHIP_SIS530: factor = (pSiS->Flags & UMA) ? 60 : 30; break; 704 default: factor = (pScrn->videoRam > 1024) ? 24 : 12; 705 } 706 a = width * height * rate * 1.40 * factor * ((pSiS->CurrentLayout.bitsPerPixel + 1) / 8); 707 b = (mclk / 1000) * 999488.0 * (buswidth / 8); 708 c = ((a / b) + 1.0) / 2; 709 d = (int)c + 2; 710 711 CRT_CPUthresholdLow = d; 712 if((pSiS->Flags & (RAMFLAG | SYNCDRAM)) == (RAMFLAG | SYNCDRAM)) { 713 CRT_CPUthresholdLow += 2; 714 } 715 CRT_CPUthresholdHigh = CRT_CPUthresholdLow + 3; 716 717 CRT_ENGthreshold = 0x0F; 718 719#if 0 /* See comment in sis_dac.c on why this is commented */ 720 if(pSiS->Chipset == PCI_CHIP_SIS530) { 721 if((pSiS->oldChipset == OC_SIS530A) && 722 (pSiS->Flags & UMA) && 723 (mclk == 100000) && 724 (pSiS->Flags & ESS137xPRESENT)) { 725 if(!(pSiS->Flags & SECRETFLAG)) index = 0; 726 if((temp = SiS_CalcSpecial530Threshold(pSiS, mode, index)) { 727 CRT_CPUthresholdLow = temp; 728 break; 729 } 730 } 731 } 732#endif 733 734 switch(pSiS->Chipset) { 735 case PCI_CHIP_SIS530: 736 if(CRT_CPUthresholdLow > 0x1f) CRT_CPUthresholdLow = 0x1f; 737 CRT_CPUthresholdHigh = 0x1f; 738 break; 739 case PCI_CHIP_SIS5597: 740 case PCI_CHIP_SIS6326: 741 default: 742 if(CRT_CPUthresholdLow > 0x0f) CRT_CPUthresholdLow = 0x0f; 743 if(CRT_CPUthresholdHigh > 0x0f) CRT_CPUthresholdHigh = 0x0f; 744 } 745 746 pReg->sisRegs3C4[0x08] = ((CRT_CPUthresholdLow & 0x0F) << 4) | 747 (CRT_ENGthreshold & 0x0F); 748 749 pReg->sisRegs3C4[0x09] &= 0xF0; 750 pReg->sisRegs3C4[0x09] |= (CRT_CPUthresholdHigh & 0x0F); 751 752 pReg->sisRegs3C4[0x3F] &= 0xEB; 753 pReg->sisRegs3C4[0x3F] |= ((CRT_CPUthresholdHigh & 0x10) | 754 ((CRT_CPUthresholdLow & 0x10) >> 2)); 755 756 if(pSiS->oldChipset >= OC_SIS530A) { 757 pReg->sisRegs3C4[0x3F] &= 0xDF; 758 pReg->sisRegs3C4[0x3F] |= 0x58; 759 } 760 761 /* Set SiS6326 TV registers */ 762 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (sis6326tvmode)) { 763 UChar tmp; 764 int index=0, i, j, k; 765 int fsc; 766 767 if(pSiS->SiS6326Flags & SIS6326_TVPAL) { 768 pReg->sisRegs3C4[0x0D] |= 0x04; 769 switch(width) { 770 case 800: 771 if((strcmp(mode->name, "PAL800x600U") == 0)) index = 4; 772 else index = 3; 773 break; 774 case 720: index = 5; break; 775 case 640: 776 default: index = 2; 777 } 778 for(i=0; i<14; i++) { 779 pReg->sis6326tv[SiS6326TVRegs1[i]] = SiS6326TVRegs1_PAL[index][i]; 780 } 781 fsc = (SiS6326TVRegs1_PAL[index][2] << 16) | 782 (SiS6326TVRegs1_PAL[index][3] << 8) | 783 (SiS6326TVRegs1_PAL[index][4]); 784 } else { 785 pReg->sisRegs3C4[0x0D] &= ~0x04; 786 if((strcmp(mode->name, "NTSC640x480U") == 0)) index = 5; 787 else index = 4; 788 for(i=0; i<14; i++) { 789 pReg->sis6326tv[SiS6326TVRegs1[i]] = SiS6326TVRegs1_NTSC[index][i]; 790 } 791 fsc = (SiS6326TVRegs1_NTSC[index][2] << 16) | 792 (SiS6326TVRegs1_NTSC[index][3] << 8) | 793 (SiS6326TVRegs1_NTSC[index][4]); 794 } 795 if(pSiS->sis6326fscadjust) { 796 fsc += pSiS->sis6326fscadjust; 797 pReg->sis6326tv[2] = (fsc >> 16) & 0xff; 798 pReg->sis6326tv[3] = (fsc >> 8) & 0xff; 799 pReg->sis6326tv[4] = fsc & 0xff; 800 } 801 tmp = pReg->sis6326tv[0x43]; 802 if(pSiS->SiS6326Flags & SIS6326_TVCVBS) tmp |= 0x10; 803 tmp |= 0x08; 804 pReg->sis6326tv[0x43] = tmp; 805 j = 0; k = 0; 806 for(i=0; i<=0x44; i++) { 807 if(SiS6326TVRegs1[j] == i) { 808 j++; 809 continue; 810 } 811 if(pSiS->SiS6326Flags & SIS6326_TVPAL) { 812 tmp = SiS6326TVRegs2_PAL[index][k]; 813 } else { 814 tmp = SiS6326TVRegs2_NTSC[index][k]; 815 } 816 pReg->sis6326tv[i] = tmp; 817 k++; 818 } 819 pReg->sis6326tv[0x43] |= 0x08; 820 if((pSiS->ChipRev == 0xc1) || (pSiS->ChipRev == 0xc2)) { 821 pReg->sis6326tv[0x43] &= ~0x08; 822 } 823 824 tmp = pReg->sis6326tv[0]; 825 tmp |= 0x18; 826 if(pSiS->SiS6326Flags & SIS6326_TVCVBS) tmp &= ~0x10; 827 if(pSiS->SiS6326Flags & SIS6326_TVSVIDEO) tmp &= ~0x08; 828 tmp |= 0x04; 829 pReg->sis6326tv[0] = tmp; 830 } 831 832 } /* VESA */ 833 834 return TRUE; 835} 836 837/* Init a mode for SiS 300, 315, 330, 340 series 838 * This function is now only used for setting up some 839 * variables (eg. scrnOffset). 840 */ 841Bool 842SIS300Init(ScrnInfoPtr pScrn, DisplayModePtr mode) 843{ 844 SISPtr pSiS = SISPTR(pScrn); 845 SISRegPtr pReg = &pSiS->ModeReg; 846 UShort temp; 847 DisplayModePtr realmode = mode; 848 849 PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, "SIS300Init()\n")); 850 851 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, 852 "virtualX = %d depth = %d Logical width = %d\n", 853 pScrn->virtualX, pSiS->CurrentLayout.bitsPerPixel, 854 pScrn->virtualX * pSiS->CurrentLayout.bitsPerPixel/8); 855 856#ifdef SISMERGED 857 if(pSiS->MergedFB) { 858 realmode = ((SiSMergedDisplayModePtr)mode->Private)->CRT1; 859 } 860#endif 861 862 /* Copy current register settings to structure */ 863 (*pSiS->SiSSave)(pScrn, pReg); 864 865 /* Calculate Offset/Display Pitch */ 866 pSiS->scrnOffset = pSiS->CurrentLayout.displayWidth * 867 ((pSiS->CurrentLayout.bitsPerPixel + 7) / 8); 868 869 pSiS->scrnPitch = pSiS->scrnPitch2 = pSiS->scrnOffset; 870 if(!(pSiS->VBFlags & CRT1_LCDA)) { 871 if(realmode->Flags & V_INTERLACE) pSiS->scrnPitch <<= 1; 872 } 873 /* CRT2 mode can never be interlaced */ 874 875#ifdef UNLOCK_ALWAYS 876 outSISIDXREG(SISSR, 0x05, 0x86); 877#endif 878 879 switch(pSiS->CurrentLayout.bitsPerPixel) { 880 case 8: 881 pSiS->DstColor = 0x0000; 882 pSiS->SiS310_AccelDepth = 0x00000000; 883 break; 884 case 16: 885 if(pSiS->CurrentLayout.depth == 15) 886 pSiS->DstColor = (short) 0x4000; 887 else 888 pSiS->DstColor = (short) 0x8000; 889 pSiS->SiS310_AccelDepth = 0x00010000; 890 break; 891 case 32: 892 pSiS->DstColor = (short) 0xC000; 893 pSiS->SiS310_AccelDepth = 0x00020000; 894 break; 895 } 896 897 /* Enable PCI LINEAR ADDRESSING (0x80), MMIO (0x01), PCI_IO (0x20) */ 898 pReg->sisRegs3C4[0x20] = 0xA1; 899 900 /* Now initialize TurboQueue. TB is always located at the very top of 901 * the videoRAM (notably NOT the x framebuffer memory, which can/should 902 * be limited by MaxXFbMem when using DRI). Also, enable the accelerators. 903 */ 904 if(!pSiS->NoAccel) { 905 pReg->sisRegs3C4[0x1E] |= 0x42; /* Enable 2D accelerator */ 906 pReg->sisRegs3C4[0x1E] |= 0x18; /* Enable 3D accelerator */ 907 switch(pSiS->VGAEngine) { 908 case SIS_300_VGA: 909 if(pSiS->TurboQueue) { /* set Turbo Queue as 512k */ 910 temp = ((pScrn->videoRam/64)-8); /* 8=512k, 4=256k, 2=128k, 1=64k */ 911 pReg->sisRegs3C4[0x26] = temp & 0xFF; 912 pReg->sisRegs3C4[0x27] = 913 (pReg->sisRegs3C4[0x27] & 0xfc) | (((temp >> 8) & 3) | 0xF0); 914 } /* line above new for saving D2&3 of status register */ 915 break; 916 case SIS_315_VGA: 917#ifndef SISVRAMQ 918 /* See comments in sis_driver.c */ 919 pReg->sisRegs3C4[0x27] = 0x1F; 920 pReg->sisRegs3C4[0x26] = 0x22; 921 pReg->sisMMIO85C0 = (pScrn->videoRam - 512) * 1024; 922#endif 923 break; 924 } 925 } 926 927 return TRUE; 928} 929 930static void 931SiS6326TVDelay(ScrnInfoPtr pScrn, int delay) 932{ 933 SISPtr pSiS = SISPTR(pScrn); 934 int i; 935 UChar temp; 936 937 for(i=0; i<delay; i++) { 938 inSISIDXREG(SISSR, 0x05, temp); 939 } 940 (void)temp; 941} 942 943static int 944SIS6326DoSense(ScrnInfoPtr pScrn, int tempbh, int tempbl, int tempch, int tempcl) 945{ 946 UChar temp; 947 948 SiS6326SetTVReg(pScrn, 0x42, tempbl); 949 temp = SiS6326GetTVReg(pScrn, 0x43); 950 temp &= 0xfc; 951 temp |= tempbh; 952 SiS6326SetTVReg(pScrn, 0x43, temp); 953 SiS6326TVDelay(pScrn, 0x1000); 954 temp = SiS6326GetTVReg(pScrn, 0x43); 955 temp |= 0x04; 956 SiS6326SetTVReg(pScrn, 0x43, temp); 957 SiS6326TVDelay(pScrn, 0x8000); 958 temp = SiS6326GetTVReg(pScrn, 0x44); 959 if(!(tempch & temp)) tempcl = 0; 960 return tempcl; 961} 962 963static void 964SISSense6326(ScrnInfoPtr pScrn) 965{ 966 SISPtr pSiS = SISPTR(pScrn); 967 UChar temp; 968 int result; 969 970 pSiS->SiS6326Flags &= (SIS6326_HASTV | SIS6326_TVPAL); 971 temp = SiS6326GetTVReg(pScrn, 0x43); 972 temp &= 0xfb; 973 SiS6326SetTVReg(pScrn, 0x43, temp); 974 result = SIS6326DoSense(pScrn, 0x01, 0xb0, 0x06, SIS6326_TVSVIDEO); /* 0x02 */ 975 pSiS->SiS6326Flags |= result; 976 result = SIS6326DoSense(pScrn, 0x01, 0xa0, 0x01, SIS6326_TVCVBS); /* 0x04 */ 977 pSiS->SiS6326Flags |= result; 978 temp = SiS6326GetTVReg(pScrn, 0x43); 979 temp &= 0xfb; 980 SiS6326SetTVReg(pScrn, 0x43, temp); 981 if(pSiS->SiS6326Flags & (SIS6326_TVSVIDEO | SIS6326_TVCVBS)) { 982 pSiS->SiS6326Flags |= SIS6326_TVDETECTED; 983 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 984 "SiS6326: Detected TV connected to %s output\n", 985 (((pSiS->SiS6326Flags & (SIS6326_TVSVIDEO | SIS6326_TVCVBS)) == 986 (SIS6326_TVSVIDEO | SIS6326_TVCVBS)) ? 987 "both SVIDEO and COMPOSITE" : 988 ((pSiS->SiS6326Flags & SIS6326_TVSVIDEO) ? 989 "SVIDEO" : "COMPOSITE"))); 990 } else { 991 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 992 "SiS6326: No TV detected\n"); 993 } 994} 995 996static Bool 997SISIsUMC(SISPtr pSiS) 998{ 999 UShort p4_0f, p4_25, p4_27, temp; 1000 1001 inSISIDXREG(SISPART4, 0x0f, p4_0f); 1002 inSISIDXREG(SISPART4, 0x25, p4_25); 1003 inSISIDXREG(SISPART4, 0x27, p4_27); 1004 andSISIDXREG(SISPART4, 0x0f, 0x7f); 1005 orSISIDXREG(SISPART4, 0x25, 0x08); 1006 andSISIDXREG(SISPART4, 0x27, 0xfd); 1007 inSISIDXREG(SISPART4, 0x26, temp); 1008 outSISIDXREG(SISPART4, 0x27, p4_27); 1009 outSISIDXREG(SISPART4, 0x25, p4_25); 1010 outSISIDXREG(SISPART4, 0x0f, p4_0f); 1011 return((temp & 0x08) ? TRUE : FALSE); 1012} 1013 1014/* Detect video bridge and set VBFlags accordingly */ 1015void SISVGAPreInit(ScrnInfoPtr pScrn) 1016{ 1017 SISPtr pSiS = SISPTR(pScrn); 1018 int temp,temp1,temp2,sistypeidx; 1019 int upperlimitlvds, lowerlimitlvds; 1020 int upperlimitch, lowerlimitch; 1021 int chronteltype, chrontelidreg, upperlimitvb; 1022 static const char *detectvb = "Detected SiS%s video bridge (%s, ID %d; Rev 0x%x)\n"; 1023#if 0 1024 UChar sr17=0; 1025#endif 1026 static const char *ChrontelTypeStr[] = { 1027 "7004", 1028 "7005", 1029 "7007", 1030 "7006", 1031 "7008", 1032 "7013", 1033 "7019", 1034 "7020", 1035 "(unknown)" 1036 }; 1037 static const char *SiSVBTypeStr[] = { 1038 "301", /* 0 */ 1039 "301B", /* 1 */ 1040 "301B-DH", /* 2 */ 1041 "301LV", /* 3 */ 1042 "302LV", /* 4 */ 1043 "301C", /* 5 */ 1044 "302ELV", /* 6 */ 1045 "302B" /* 7 */ 1046 }; 1047 1048 switch(pSiS->Chipset) { 1049 case PCI_CHIP_SIS300: 1050 case PCI_CHIP_SIS540: 1051 case PCI_CHIP_SIS630: 1052 case PCI_CHIP_SIS550: 1053 case PCI_CHIP_SIS315: 1054 case PCI_CHIP_SIS315H: 1055 case PCI_CHIP_SIS315PRO: 1056 case PCI_CHIP_SIS650: 1057 case PCI_CHIP_SIS330: 1058 case PCI_CHIP_SIS660: 1059 case PCI_CHIP_SIS340: 1060 case PCI_CHIP_XGIXG20: 1061 case PCI_CHIP_XGIXG40: 1062 pSiS->ModeInit = SIS300Init; 1063 break; 1064 default: 1065 pSiS->ModeInit = SISInit; 1066 } 1067 1068 if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 1069 UChar sr0d; 1070 inSISIDXREG(SISSR, 0x0d, sr0d); 1071 if(sr0d & 0x04) { 1072 pSiS->SiS6326Flags |= SIS6326_TVPAL; 1073 } 1074 SISSense6326(pScrn); 1075 } 1076 1077 pSiS->VBFlags = pSiS->VBFlags2 = 0; /* reset VBFlags */ 1078 pSiS->SiS_Pr->SiS_UseLCDA = FALSE; 1079 pSiS->SiS_Pr->Backup = FALSE; 1080 1081 /* Videobridges only available for 300/315/330/340 series */ 1082 if((pSiS->VGAEngine != SIS_300_VGA) && (pSiS->VGAEngine != SIS_315_VGA)) 1083 return; 1084 1085 /* No video bridge ever on XGI Z7 (XG20) */ 1086 if(pSiS->ChipType == XGI_20) 1087 return; 1088 1089 inSISIDXREG(SISPART4, 0x00, temp); 1090 temp &= 0x0F; 1091 if(temp == 1) { 1092 1093 inSISIDXREG(SISPART4, 0x01, temp1); 1094 temp1 &= 0xff; 1095 1096 if(temp1 >= 0xC0) { 1097 if(SISIsUMC(pSiS)) pSiS->VBFlags2 |= VB2_SISUMC; 1098 } 1099 1100 if(temp1 >= 0xE0) { 1101 inSISIDXREG(SISPART4, 0x39, temp2); 1102 if(temp2 == 0xff) { 1103 pSiS->VBFlags2 |= VB2_302LV; 1104 sistypeidx = 4; 1105 } else { 1106 pSiS->VBFlags2 |= VB2_301C; /* VB_302ELV; */ 1107 sistypeidx = 5; /* 6; */ 1108 } 1109 } else if(temp1 >= 0xD0) { 1110 pSiS->VBFlags2 |= VB2_301LV; 1111 sistypeidx = 3; 1112 } else if(temp1 >= 0xC0) { 1113 pSiS->VBFlags2 |= VB2_301C; 1114 sistypeidx = 5; 1115 } else if(temp1 >= 0xB0) { 1116 pSiS->VBFlags2 |= VB2_301B; 1117 sistypeidx = 1; 1118 inSISIDXREG(SISPART4, 0x23, temp2); 1119 if(!(temp2 & 0x02)) { 1120 pSiS->VBFlags2 |= VB2_30xBDH; 1121 sistypeidx = 2; 1122 } 1123 } else { 1124 pSiS->VBFlags2 |= VB2_301; 1125 sistypeidx = 0; 1126 } 1127 1128 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, detectvb, SiSVBTypeStr[sistypeidx], 1129 (pSiS->VBFlags2 & VB2_SISUMC) ? "UMC-0" : "Charter/UMC-1", 1, temp1); 1130 1131 SISSense30x(pScrn, FALSE); 1132 1133 } else if(temp == 2) { 1134 1135 inSISIDXREG(SISPART4, 0x01, temp1); 1136 temp1 &= 0xff; 1137 1138 if(temp1 >= 0xC0) { 1139 if(SISIsUMC(pSiS)) pSiS->VBFlags2 |= VB2_SISUMC; 1140 } 1141 1142 if(temp1 >= 0xE0) { 1143 pSiS->VBFlags2 |= VB2_302LV; 1144 sistypeidx = 4; 1145 } else if(temp1 >= 0xD0) { 1146 pSiS->VBFlags2 |= VB2_301LV; 1147 sistypeidx = 3; 1148 } else { 1149 pSiS->VBFlags2 |= VB2_302B; 1150 sistypeidx = 7; 1151 } 1152 1153 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, detectvb, SiSVBTypeStr[sistypeidx], 1154 (pSiS->VBFlags2 & VB2_SISUMC) ? "UMC-0" : "Charter/UMC-1", 2, temp1); 1155 1156 SISSense30x(pScrn, FALSE); 1157 1158 } else if (temp == 3) { 1159 1160 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, detectvb, "303", "unsupported, unknown", temp, 0); 1161 1162 } else { 1163 1164 if(pSiS->NewCRLayout) { 1165 inSISIDXREG(SISCR, 0x38, temp); 1166 temp = (temp >> 5) & 0x07; 1167 } else { 1168 inSISIDXREG(SISCR, 0x37, temp); 1169 temp = (temp >> 1) & 0x07; 1170 } 1171 if(pSiS->VGAEngine == SIS_300_VGA) { 1172 lowerlimitlvds = 2; upperlimitlvds = 4; 1173 lowerlimitch = 4; upperlimitch = 5; 1174 chronteltype = 1; chrontelidreg = 0x25; 1175 upperlimitvb = upperlimitlvds; 1176 } else { 1177 lowerlimitlvds = 2; upperlimitlvds = 3; 1178 lowerlimitch = 3; upperlimitch = 3; 1179 chronteltype = 2; chrontelidreg = 0x4b; 1180 upperlimitvb = upperlimitlvds; 1181 if(pSiS->NewCRLayout) { 1182 upperlimitvb = 4; 1183 } 1184 } 1185 1186 if((temp >= lowerlimitlvds) && (temp <= upperlimitlvds)) { 1187 pSiS->VBFlags2 |= VB2_LVDS; 1188 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1189 "Detected LVDS transmitter (External chip ID %d)\n", temp); 1190 } 1191 if((temp >= lowerlimitch) && (temp <= upperlimitch)) { 1192 /* Set global for init301.c */ 1193 pSiS->SiS_Pr->SiS_IF_DEF_CH70xx = chronteltype; 1194 1195 if(chronteltype == 1) { 1196 /* Set general purpose IO for Chrontel communication */ 1197 SiS_SetChrontelGPIO(pSiS->SiS_Pr, 0x9c); 1198 } 1199 1200 /* Read Chrontel version number */ 1201 temp1 = SiS_GetCH70xx(pSiS->SiS_Pr, chrontelidreg); 1202 if(chronteltype == 1) { 1203 /* See Chrontel TB31 for explanation */ 1204 temp2 = SiS_GetCH700x(pSiS->SiS_Pr, 0x0e); 1205 if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) { 1206 SiS_SetCH700x(pSiS->SiS_Pr, 0x0e, 0x0b); 1207 SiS_DDC2Delay(pSiS->SiS_Pr, 300); 1208 } 1209 temp2 = SiS_GetCH70xx(pSiS->SiS_Pr, chrontelidreg); 1210 if(temp2 != temp1) temp1 = temp2; 1211 } 1212 if(temp1 == 0xFFFF) { /* 0xFFFF = error reading DDC port */ 1213 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1214 "Detected Chrontel 70xx, but encountered error reading I2C port\n"); 1215 andSISIDXREG(SISCR, 0x32, ~0x07); 1216 pSiS->postVBCR32 &= ~0x07; 1217 } else if((temp1 >= 0x19) && (temp1 <= 200)) { 1218 /* We only support device ids 0x19-200; other values may indicate DDC problems */ 1219 pSiS->VBFlags2 |= VB2_CHRONTEL; 1220 switch (temp1) { 1221 case 0x32: temp2 = 0; pSiS->ChrontelType = CHRONTEL_700x; break; 1222 case 0x3A: temp2 = 1; pSiS->ChrontelType = CHRONTEL_700x; break; 1223 case 0x50: temp2 = 2; pSiS->ChrontelType = CHRONTEL_700x; break; 1224 case 0x2A: temp2 = 3; pSiS->ChrontelType = CHRONTEL_700x; break; 1225 case 0x40: temp2 = 4; pSiS->ChrontelType = CHRONTEL_700x; break; 1226 case 0x22: temp2 = 5; pSiS->ChrontelType = CHRONTEL_700x; break; 1227 case 0x19: temp2 = 6; pSiS->ChrontelType = CHRONTEL_701x; break; 1228 case 0x20: temp2 = 7; pSiS->ChrontelType = CHRONTEL_701x; break; /* ID for 7020? */ 1229 default: temp2 = 8; pSiS->ChrontelType = CHRONTEL_701x; break; 1230 } 1231 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1232 "Detected Chrontel %s TV encoder (ID 0x%02x; chip ID %d)\n", 1233 ChrontelTypeStr[temp2], temp1, temp); 1234 1235 /* Sense connected TV's */ 1236 SISSenseChrontel(pScrn, FALSE); 1237 1238 } else if(temp1 == 0) { 1239 /* This indicates a communication problem, but it only occures if there 1240 * is no TV attached. So we don't use TV in this case. 1241 */ 1242 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1243 "Detected Chrontel TV encoder in promiscuous state (DDC/I2C mix-up)\n"); 1244 andSISIDXREG(SISCR, 0x32, ~0x07); 1245 pSiS->postVBCR32 &= ~0x07; 1246 } else { 1247 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1248 "Chrontel: Unsupported device id (%d) detected\n",temp1); 1249 andSISIDXREG(SISCR, 0x32, ~0x07); 1250 pSiS->postVBCR32 &= ~0x07; 1251 } 1252 if(chronteltype == 1) { 1253 /* Set general purpose IO for Chrontel communication */ 1254 SiS_SetChrontelGPIO(pSiS->SiS_Pr, 0x00); 1255 } 1256 } 1257 if((pSiS->NewCRLayout) && (temp == 4)) { 1258 pSiS->VBFlags2 |= VB2_CONEXANT; 1259 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1260 "Detected Conexant video bridge - UNSUPPORTED\n"); 1261 } 1262 if((pSiS->VGAEngine == SIS_300_VGA) && (temp == 3)) { 1263 pSiS->VBFlags2 |= VB2_TRUMPION; 1264 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1265 "Detected Trumpion Zurac (I/II/III) LVDS scaler\n"); 1266 } 1267 if(temp > upperlimitvb) { 1268 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1269 "Detected unknown bridge type (%d)\n", temp); 1270 } 1271 } 1272 1273 /* Old BIOSes store the detected CRT2 type in SR17, 16 and 13 1274 * instead of CR32. However, since our detection routines 1275 * store their results to CR32, we now copy the 1276 * remaining bits (for LCD and VGA) to CR32 for unified usage. 1277 * SR17[0] CRT1 [1] LCD [2] TV [3] VGA2 1278 * [4] AVIDEO [5] SVIDEO 1279 * SR13[0] SCART [1] HiVision 1280 * SR16[5] PAL/NTSC [6] LCD-SCALE [7] OVERSCAN 1281 */ 1282 1283#if 0 1284 inSISIDXREG(SISSR, 0x17, sr17); 1285 if( (pSiS->VGAEngine == SIS_300_VGA) && 1286 (pSiS->Chipset != PCI_CHIP_SIS300) && 1287 (sr17 & 0x0F) ) { 1288 1289 UChar cr32; 1290 inSISIDXREG(SISCR, 0x32, cr32); 1291 1292 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1293 "Converting SR17 (%02x) to CR32 (%02x)\n", sr17, cr32); 1294 1295 if(sr17 & 0x01) { /* CRT1 */ 1296 orSISIDXREG(SISCR, 0x32, 0x20); 1297 pSiS->postVBCR32 |= 0x20; 1298 } else { 1299 andSISIDXREG(SISCR, 0x32, ~0x20); 1300 pSiS->postVBCR32 &= ~0x20; 1301 } 1302 1303 if(sr17 & 0x02) { /* LCD */ 1304 orSISIDXREG(SISCR, 0x32, 0x08); 1305 pSiS->postVBCR32 |= 0x08; 1306 } else { 1307 andSISIDXREG(SISCR, 0x32, ~0x08); 1308 pSiS->postVBCR32 &= ~0x08; 1309 } 1310 1311 /* No Hivision, no DVI here */ 1312 andSISIDXREG(SISCR,0x32,~0xc0); 1313 pSiS->postVBCR32 &= ~0xc0; 1314 } 1315#endif 1316 1317 /* Try to find out if the bridge uses LCDA for low resolution and 1318 * text modes. If sisfb saved this for us, use it. Otherwise, 1319 * check if we are running on a low mode on LCD and read the 1320 * relevant registers ourselves. 1321 */ 1322 if(pSiS->VGAEngine == SIS_315_VGA) { 1323 1324 if(pSiS->VBFlags2 & VB2_SISLCDABRIDGE) { 1325 if(pSiS->sisfblcda != 0xff) { 1326 if((pSiS->sisfblcda & 0x03) == 0x03) { 1327 pSiS->SiS_Pr->SiS_UseLCDA = TRUE; 1328 pSiS->ChipFlags |= SiSCF_UseLCDA; 1329 } 1330 } else { 1331 inSISIDXREG(SISCR,0x34,temp); 1332 if(temp <= 0x13) { 1333 inSISIDXREG(SISCR,0x38,temp); 1334 if((temp & 0x03) == 0x03) { 1335 pSiS->SiS_Pr->SiS_UseLCDA = TRUE; 1336 pSiS->ChipFlags |= SiSCF_UseLCDA; 1337 pSiS->SiS_Pr->Backup = TRUE; 1338 } else { 1339 orSISIDXREG(SISPART1,0x2f,0x01); /* Unlock CRT2 */ 1340 inSISIDXREG(SISPART1,0x13,temp); 1341 if(temp & 0x04) { 1342 pSiS->SiS_Pr->SiS_UseLCDA = TRUE; 1343 pSiS->ChipFlags |= SiSCF_UseLCDA; 1344 pSiS->SiS_Pr->Backup = TRUE; 1345 } 1346 } 1347 } 1348 } 1349 if(pSiS->ChipFlags & SiSCF_UseLCDA) { 1350 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 3, 1351 "BIOS uses LCDA for low resolution and text modes\n"); 1352 if(pSiS->SiS_Pr->Backup == TRUE) { 1353 inSISIDXREG(SISCR,0x34,pSiS->SiS_Pr->Backup_Mode); 1354 inSISIDXREG(SISPART1,0x14,pSiS->SiS_Pr->Backup_14); 1355 inSISIDXREG(SISPART1,0x15,pSiS->SiS_Pr->Backup_15); 1356 inSISIDXREG(SISPART1,0x16,pSiS->SiS_Pr->Backup_16); 1357 inSISIDXREG(SISPART1,0x17,pSiS->SiS_Pr->Backup_17); 1358 inSISIDXREG(SISPART1,0x18,pSiS->SiS_Pr->Backup_18); 1359 inSISIDXREG(SISPART1,0x19,pSiS->SiS_Pr->Backup_19); 1360 inSISIDXREG(SISPART1,0x1a,pSiS->SiS_Pr->Backup_1a); 1361 inSISIDXREG(SISPART1,0x1b,pSiS->SiS_Pr->Backup_1b); 1362 inSISIDXREG(SISPART1,0x1c,pSiS->SiS_Pr->Backup_1c); 1363 inSISIDXREG(SISPART1,0x1d,pSiS->SiS_Pr->Backup_1d); 1364 } 1365 } 1366 } 1367 } 1368} 1369 1370static void 1371SiS_WriteAttr(SISPtr pSiS, int index, int value) 1372{ 1373 (void)inSISREG(SISINPSTAT); 1374 index |= 0x20; 1375 outSISREG(SISAR, index); 1376 outSISREG(SISAR, value); 1377} 1378 1379static int 1380SiS_ReadAttr(SISPtr pSiS, int index) 1381{ 1382 (void)inSISREG(SISINPSTAT); 1383 index |= 0x20; 1384 outSISREG(SISAR, index); 1385 return(inSISREG(SISARR)); 1386} 1387 1388static void 1389SiS_EnablePalette(SISPtr pSiS) 1390{ 1391 (void)inSISREG(SISINPSTAT); 1392 outSISREG(SISAR, 0x00); 1393 pSiS->VGAPaletteEnabled = TRUE; 1394} 1395 1396static void 1397SiS_DisablePalette(SISPtr pSiS) 1398{ 1399 (void)inSISREG(SISINPSTAT); 1400 outSISREG(SISAR, 0x20); 1401 pSiS->VGAPaletteEnabled = FALSE; 1402} 1403 1404void 1405SISVGALock(SISPtr pSiS) 1406{ 1407 orSISIDXREG(SISCR, 0x11, 0x80); /* Protect CRTC[0-7] */ 1408} 1409 1410void 1411SiSVGAUnlock(SISPtr pSiS) 1412{ 1413 andSISIDXREG(SISCR, 0x11, 0x7f); /* Unprotect CRTC[0-7] */ 1414} 1415 1416#define SIS_FONTS_SIZE (8 * 8192) 1417 1418void 1419SiSVGASaveFonts(ScrnInfoPtr pScrn) 1420{ 1421#ifdef SIS_PC_PLATFORM 1422 SISPtr pSiS = SISPTR(pScrn); 1423 pointer vgaMemBase = pSiS->VGAMemBase; 1424 UChar miscOut, attr10, gr4, gr5, gr6, seq2, seq4, scrn; 1425 1426 if((pSiS->fonts) || (vgaMemBase == NULL)) return; 1427 1428 /* If in graphics mode, don't save anything */ 1429 attr10 = SiS_ReadAttr(pSiS, 0x10); 1430 if(attr10 & 0x01) return; 1431 1432 if(!(pSiS->fonts = malloc(SIS_FONTS_SIZE * 2))) { 1433 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1434 "Could not save console fonts, mem allocation failed\n"); 1435 return; 1436 } 1437 1438 /* save the registers that are needed here */ 1439 miscOut = inSISREG(SISMISCR); 1440 inSISIDXREG(SISGR, 0x04, gr4); 1441 inSISIDXREG(SISGR, 0x05, gr5); 1442 inSISIDXREG(SISGR, 0x06, gr6); 1443 inSISIDXREG(SISSR, 0x02, seq2); 1444 inSISIDXREG(SISSR, 0x04, seq4); 1445 1446 /* Force into color mode */ 1447 outSISREG(SISMISCW, miscOut | 0x01); 1448 1449 inSISIDXREG(SISSR, 0x01, scrn); 1450 outSISIDXREG(SISSR, 0x00, 0x01); 1451 outSISIDXREG(SISSR, 0x01, scrn | 0x20); 1452 outSISIDXREG(SISSR, 0x00, 0x03); 1453 1454 SiS_WriteAttr(pSiS, 0x10, 0x01); /* graphics mode */ 1455 1456 /*font1 */ 1457 outSISIDXREG(SISSR, 0x02, 0x04); /* write to plane 2 */ 1458 outSISIDXREG(SISSR, 0x04, 0x06); /* enable plane graphics */ 1459 outSISIDXREG(SISGR, 0x04, 0x02); /* read plane 2 */ 1460 outSISIDXREG(SISGR, 0x05, 0x00); /* write mode 0, read mode 0 */ 1461 outSISIDXREG(SISGR, 0x06, 0x05); /* set graphics */ 1462 slowbcopy_frombus(vgaMemBase, pSiS->fonts, SIS_FONTS_SIZE); 1463 1464 /* font2 */ 1465 outSISIDXREG(SISSR, 0x02, 0x08); /* write to plane 3 */ 1466 outSISIDXREG(SISSR, 0x04, 0x06); /* enable plane graphics */ 1467 outSISIDXREG(SISGR, 0x04, 0x03); /* read plane 3 */ 1468 outSISIDXREG(SISGR, 0x05, 0x00); /* write mode 0, read mode 0 */ 1469 outSISIDXREG(SISGR, 0x06, 0x05); /* set graphics */ 1470 slowbcopy_frombus(vgaMemBase, pSiS->fonts + SIS_FONTS_SIZE, SIS_FONTS_SIZE); 1471 1472 inSISIDXREG(SISSR, 0x01, scrn); 1473 outSISIDXREG(SISSR, 0x00, 0x01); 1474 outSISIDXREG(SISSR, 0x01, scrn & ~0x20); 1475 outSISIDXREG(SISSR, 0x00, 0x03); 1476 1477 /* Restore clobbered registers */ 1478 SiS_WriteAttr(pSiS, 0x10, attr10); 1479 outSISIDXREG(SISSR, 0x02, seq2); 1480 outSISIDXREG(SISSR, 0x04, seq4); 1481 outSISIDXREG(SISGR, 0x04, gr4); 1482 outSISIDXREG(SISGR, 0x05, gr5); 1483 outSISIDXREG(SISGR, 0x06, gr6); 1484 outSISREG(SISMISCW, miscOut); 1485#endif 1486} 1487 1488static void 1489SiSVGASaveMode(ScrnInfoPtr pScrn, SISRegPtr save) 1490{ 1491 SISPtr pSiS = SISPTR(pScrn); 1492 int i; 1493 1494 save->sisRegMiscOut = inSISREG(SISMISCR); 1495 1496 for(i = 0; i < 25; i++) { 1497 inSISIDXREG(SISCR, i, save->sisRegs3D4[i]); 1498 } 1499 1500 SiS_EnablePalette(pSiS); 1501 for(i = 0; i < 21; i++) { 1502 save->sisRegsATTR[i] = SiS_ReadAttr(pSiS, i); 1503 } 1504 SiS_DisablePalette(pSiS); 1505 1506 for(i = 0; i < 9; i++) { 1507 inSISIDXREG(SISGR, i, save->sisRegsGR[i]); 1508 } 1509 1510 for(i = 1; i < 5; i++) { 1511 inSISIDXREG(SISSR, i, save->sisRegs3C4[i]); 1512 } 1513} 1514 1515static void 1516SiSVGASaveColormap(ScrnInfoPtr pScrn, SISRegPtr save) 1517{ 1518 SISPtr pSiS = SISPTR(pScrn); 1519 int i; 1520 1521 if(pSiS->VGACMapSaved) return; 1522 1523 outSISREG(SISPEL, 0xff); 1524 1525 outSISREG(SISCOLIDXR, 0x00); 1526 for(i = 0; i < 768; i++) { 1527 save->sisDAC[i] = inSISREG(SISCOLDATA); 1528 (void)inSISREG(SISINPSTAT); 1529 (void)inSISREG(SISINPSTAT); 1530 } 1531 1532 SiS_DisablePalette(pSiS); 1533 pSiS->VGACMapSaved = TRUE; 1534} 1535 1536void 1537SiSVGASave(ScrnInfoPtr pScrn, SISRegPtr save, int flags) 1538{ 1539 if(save == NULL) return; 1540 1541 if(flags & SISVGA_SR_CMAP) SiSVGASaveColormap(pScrn, save); 1542 if(flags & SISVGA_SR_MODE) SiSVGASaveMode(pScrn, save); 1543 if(flags & SISVGA_SR_FONTS) SiSVGASaveFonts(pScrn); 1544} 1545 1546void 1547SiSVGARestoreFonts(ScrnInfoPtr pScrn) 1548{ 1549#ifdef SIS_PC_PLATFORM 1550 SISPtr pSiS = SISPTR(pScrn); 1551 pointer vgaMemBase = pSiS->VGAMemBase; 1552 UChar miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4, scrn; 1553 1554 if((!pSiS->fonts) || (vgaMemBase == NULL)) return; 1555 1556 /* save the registers that are needed here */ 1557 miscOut = inSISREG(SISMISCR); 1558 attr10 = SiS_ReadAttr(pSiS, 0x10); 1559 inSISIDXREG(SISGR, 0x01, gr1); 1560 inSISIDXREG(SISGR, 0x03, gr3); 1561 inSISIDXREG(SISGR, 0x04, gr4); 1562 inSISIDXREG(SISGR, 0x05, gr5); 1563 inSISIDXREG(SISGR, 0x06, gr6); 1564 inSISIDXREG(SISGR, 0x08, gr8); 1565 inSISIDXREG(SISSR, 0x02, seq2); 1566 inSISIDXREG(SISSR, 0x04, seq4); 1567 1568 /* Force into color mode */ 1569 outSISREG(SISMISCW, miscOut | 0x01); 1570 inSISIDXREG(SISSR, 0x01, scrn); 1571 outSISIDXREG(SISSR, 0x00, 0x01); 1572 outSISIDXREG(SISSR, 0x01, scrn | 0x20); 1573 outSISIDXREG(SISSR, 0x00, 0x03); 1574 1575 SiS_WriteAttr(pSiS, 0x10, 0x01); /* graphics mode */ 1576 if(pScrn->depth == 4) { 1577 outSISIDXREG(SISGR, 0x03, 0x00); /* don't rotate, write unmodified */ 1578 outSISIDXREG(SISGR, 0x08, 0xFF); /* write all bits in a byte */ 1579 outSISIDXREG(SISGR, 0x01, 0x00); /* all planes come from CPU */ 1580 } 1581 1582 outSISIDXREG(SISSR, 0x02, 0x04); /* write to plane 2 */ 1583 outSISIDXREG(SISSR, 0x04, 0x06); /* enable plane graphics */ 1584 outSISIDXREG(SISGR, 0x04, 0x02); /* read plane 2 */ 1585 outSISIDXREG(SISGR, 0x05, 0x00); /* write mode 0, read mode 0 */ 1586 outSISIDXREG(SISGR, 0x06, 0x05); /* set graphics */ 1587 slowbcopy_tobus(pSiS->fonts, vgaMemBase, SIS_FONTS_SIZE); 1588 1589 outSISIDXREG(SISSR, 0x02, 0x08); /* write to plane 3 */ 1590 outSISIDXREG(SISSR, 0x04, 0x06); /* enable plane graphics */ 1591 outSISIDXREG(SISGR, 0x04, 0x03); /* read plane 3 */ 1592 outSISIDXREG(SISGR, 0x05, 0x00); /* write mode 0, read mode 0 */ 1593 outSISIDXREG(SISGR, 0x06, 0x05); /* set graphics */ 1594 slowbcopy_tobus(pSiS->fonts + SIS_FONTS_SIZE, vgaMemBase, SIS_FONTS_SIZE); 1595 1596 inSISIDXREG(SISSR, 0x01, scrn); 1597 outSISIDXREG(SISSR, 0x00, 0x01); 1598 outSISIDXREG(SISSR, 0x01, scrn & ~0x20); 1599 outSISIDXREG(SISSR, 0x00, 0x03); 1600 1601 /* restore the registers that were changed */ 1602 outSISREG(SISMISCW, miscOut); 1603 SiS_WriteAttr(pSiS, 0x10, attr10); 1604 outSISIDXREG(SISGR, 0x01, gr1); 1605 outSISIDXREG(SISGR, 0x03, gr3); 1606 outSISIDXREG(SISGR, 0x04, gr4); 1607 outSISIDXREG(SISGR, 0x05, gr5); 1608 outSISIDXREG(SISGR, 0x06, gr6); 1609 outSISIDXREG(SISGR, 0x08, gr8); 1610 outSISIDXREG(SISSR, 0x02, seq2); 1611 outSISIDXREG(SISSR, 0x04, seq4); 1612#endif 1613} 1614 1615static void 1616SiSVGARestoreMode(ScrnInfoPtr pScrn, SISRegPtr restore) 1617{ 1618 SISPtr pSiS = SISPTR(pScrn); 1619 int i; 1620 1621 outSISREG(SISMISCW, restore->sisRegMiscOut); 1622 1623 for(i = 1; i < 5; i++) { 1624 outSISIDXREG(SISSR, i, restore->sisRegs3C4[i]); 1625 } 1626 1627 outSISIDXREG(SISCR, 17, restore->sisRegs3D4[17] & ~0x80); 1628 1629 for(i = 0; i < 25; i++) { 1630 outSISIDXREG(SISCR, i, restore->sisRegs3D4[i]); 1631 } 1632 1633 for(i = 0; i < 9; i++) { 1634 outSISIDXREG(SISGR, i, restore->sisRegsGR[i]); 1635 } 1636 1637 SiS_EnablePalette(pSiS); 1638 for(i = 0; i < 21; i++) { 1639 SiS_WriteAttr(pSiS, i, restore->sisRegsATTR[i]); 1640 } 1641 SiS_DisablePalette(pSiS); 1642} 1643 1644 1645static void 1646SiSVGARestoreColormap(ScrnInfoPtr pScrn, SISRegPtr restore) 1647{ 1648 SISPtr pSiS = SISPTR(pScrn); 1649 int i; 1650 1651 if(!pSiS->VGACMapSaved) return; 1652 1653 outSISREG(SISPEL, 0xff); 1654 1655 outSISREG(SISCOLIDX, 0x00); 1656 for(i = 0; i < 768; i++) { 1657 outSISREG(SISCOLDATA, restore->sisDAC[i]); 1658 (void)inSISREG(SISINPSTAT); 1659 (void)inSISREG(SISINPSTAT); 1660 } 1661 1662 SiS_DisablePalette(pSiS); 1663} 1664 1665void 1666SiSVGARestore(ScrnInfoPtr pScrn, SISRegPtr restore, int flags) 1667{ 1668 if(restore == NULL) return; 1669 1670 if(flags & SISVGA_SR_MODE) SiSVGARestoreMode(pScrn, restore); 1671 if(flags & SISVGA_SR_FONTS) SiSVGARestoreFonts(pScrn); 1672 if(flags & SISVGA_SR_CMAP) SiSVGARestoreColormap(pScrn, restore); 1673} 1674 1675static void 1676SiS_SeqReset(SISPtr pSiS, Bool start) 1677{ 1678 if(start) { 1679 outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 1680 } else { 1681 outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 1682 } 1683} 1684 1685void 1686SiSVGAProtect(ScrnInfoPtr pScrn, Bool on) 1687{ 1688 SISPtr pSiS = SISPTR(pScrn); 1689 UChar tmp; 1690 1691 if(!pScrn->vtSema) return; 1692 1693 if(on) { 1694 inSISIDXREG(SISSR, 0x01, tmp); 1695 SiS_SeqReset(pSiS, TRUE); /* start synchronous reset */ 1696 outSISIDXREG(SISSR, 0x01, tmp | 0x20); /* disable display */ 1697 SiS_EnablePalette(pSiS); 1698 } else { 1699 andSISIDXREG(SISSR, 0x01, ~0x20); /* enable display */ 1700 SiS_SeqReset(pSiS, FALSE); /* clear synchronous reset */ 1701 SiS_DisablePalette(pSiS); 1702 } 1703} 1704 1705#ifdef SIS_PC_PLATFORM 1706Bool 1707SiSVGAMapMem(ScrnInfoPtr pScrn) 1708{ 1709 SISPtr pSiS = SISPTR(pScrn); 1710 1711 /* Map only once */ 1712 if(pSiS->VGAMemBase) return TRUE; 1713 1714 if(pSiS->VGAMapSize == 0) pSiS->VGAMapSize = (64 * 1024); 1715 if(pSiS->VGAMapPhys == 0) pSiS->VGAMapPhys = 0xA0000; 1716 1717#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 1718#if XSERVER_LIBPCIACCESS 1719 (void) pci_device_map_legacy(pSiS->PciInfo, pSiS->VGAMapPhys, pSiS->VGAMapSize, 1720 PCI_DEV_MAP_FLAG_WRITABLE, &pSiS->VGAMemBase); 1721#else 1722 pSiS->VGAMemBase = xf86MapDomainMemory(pScrn->scrnIndex, VIDMEM_MMIO_32BIT, 1723 pSiS->PciTag, pSiS->VGAMapPhys, pSiS->VGAMapSize); 1724#endif 1725#else 1726 pSiS->VGAMemBase = xf86MapVidMem(pScrn->scrnIndex, VIDMEM_MMIO_32BIT, 1727 pSiS->VGAMapPhys, pSiS->VGAMapSize); 1728#endif 1729 1730 return(pSiS->VGAMemBase != NULL); 1731} 1732 1733void 1734SiSVGAUnmapMem(ScrnInfoPtr pScrn) 1735{ 1736 SISPtr pSiS = SISPTR(pScrn); 1737 1738 if(pSiS->VGAMemBase == NULL) return; 1739 1740#if XSERVER_LIBPCIACCESS 1741 (void) pci_device_unmap_legacy(pSiS->PciInfo, pSiS->VGAMemBase, pSiS->VGAMapSize); 1742#else 1743 xf86UnMapVidMem(pScrn->scrnIndex, pSiS->VGAMemBase, pSiS->VGAMapSize); 1744#endif 1745 1746 pSiS->VGAMemBase = NULL; 1747} 1748#endif 1749 1750#if 0 1751static CARD32 1752SiS_HBlankKGA(DisplayModePtr mode, SISRegPtr regp, int nBits, unsigned int Flags) 1753{ 1754 int nExtBits = (nBits < 6) ? 0 : nBits - 6; 1755 CARD32 ExtBits; 1756 CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 6; 1757 1758 regp->sisRegs3D4[3] = (regp->sisRegs3D4[3] & ~0x1F) | 1759 (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F); 1760 regp->sisRegs3D4[5] = (regp->sisRegs3D4[5] & ~0x80) | 1761 ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2); 1762 ExtBits = ((mode->CrtcHBlankEnd >> 3) - 1) & ExtBitMask; 1763 1764 if( (Flags & SISKGA_FIX_OVERSCAN) && 1765 ((mode->CrtcHBlankEnd >> 3) == (mode->CrtcHTotal >> 3))) { 1766 int i = (regp->sisRegs3D4[3] & 0x1F) | 1767 ((regp->sisRegs3D4[5] & 0x80) >> 2) | 1768 ExtBits; 1769 if(Flags & SISKGA_ENABLE_ON_ZERO) { 1770 if( (i-- > (((mode->CrtcHBlankStart >> 3) - 1) & (0x3F | ExtBitMask))) && 1771 (mode->CrtcHBlankEnd == mode->CrtcHTotal) ) { 1772 i = 0; 1773 } 1774 } else if (Flags & SISKGA_BE_TOT_DEC) i--; 1775 regp->sisRegs3D4[3] = (regp->sisRegs3D4[3] & ~0x1F) | (i & 0x1F); 1776 regp->sisRegs3D4[5] = (regp->sisRegs3D4[5] & ~0x80) | ((i << 2) & 0x80); 1777 ExtBits = i & ExtBitMask; 1778 } 1779 return ExtBits >> 6; 1780} 1781#endif 1782 1783static CARD32 1784SiS_VBlankKGA(DisplayModePtr mode, SISRegPtr regp, int nBits, unsigned int Flags) 1785{ 1786 CARD32 nExtBits = (nBits < 8) ? 0 : (nBits - 8); 1787 CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 8; 1788 CARD32 ExtBits = (mode->CrtcVBlankEnd - 1) & ExtBitMask; 1789 CARD32 BitMask = (nBits < 7) ? 0 : ((1 << nExtBits) - 1); 1790 int VBlankStart = (mode->CrtcVBlankStart - 1) & 0xFF; 1791 regp->sisRegs3D4[22] = (mode->CrtcVBlankEnd - 1) & 0xFF; 1792 1793 if((Flags & SISKGA_FIX_OVERSCAN) && (mode->CrtcVBlankEnd == mode->CrtcVTotal)) { 1794 int i = regp->sisRegs3D4[22] | ExtBits; 1795 if(Flags & SISKGA_ENABLE_ON_ZERO) { 1796 if( ((BitMask && ((i & BitMask) > (VBlankStart & BitMask))) || 1797 ((i > VBlankStart) && /* 8-bit case */ 1798 ((i & 0x7F) > (VBlankStart & 0x7F)))) && /* 7-bit case */ 1799 (!(regp->sisRegs3D4[9] & 0x9F)) ) { /* 1 scanline/row */ 1800 i = 0; 1801 } else { 1802 i--; 1803 } 1804 } else if(Flags & SISKGA_BE_TOT_DEC) i--; 1805 1806 regp->sisRegs3D4[22] = i & 0xFF; 1807 ExtBits = i & 0xFF00; 1808 } 1809 return (ExtBits >> 8); 1810} 1811 1812Bool 1813SiSVGAInit(ScrnInfoPtr pScrn, DisplayModePtr mode, int fixsync) 1814{ 1815 SISPtr pSiS = SISPTR(pScrn); 1816 SISRegPtr regp = &pSiS->ModeReg; 1817 int depth = pScrn->depth; 1818 unsigned int i; 1819 1820 /* Sync */ 1821 if((mode->Flags & (V_PHSYNC | V_NHSYNC)) && (mode->Flags & (V_PVSYNC | V_NVSYNC))) { 1822 regp->sisRegMiscOut = 0x23; 1823 if(mode->Flags & V_NHSYNC) regp->sisRegMiscOut |= 0x40; 1824 if(mode->Flags & V_NVSYNC) regp->sisRegMiscOut |= 0x80; 1825 } else { 1826 int VDisplay = mode->VDisplay; 1827 1828 if(mode->Flags & V_DBLSCAN) VDisplay *= 2; 1829 if(mode->VScan > 1) VDisplay *= mode->VScan; 1830 1831 if(VDisplay < 400) regp->sisRegMiscOut = 0xA3; /* +hsync -vsync */ 1832 else if (VDisplay < 480) regp->sisRegMiscOut = 0x63; /* -hsync +vsync */ 1833 else if (VDisplay < 768) regp->sisRegMiscOut = 0xE3; /* -hsync -vsync */ 1834 else regp->sisRegMiscOut = 0x23; /* +hsync +vsync */ 1835 } 1836 1837 regp->sisRegMiscOut |= (mode->ClockIndex & 0x03) << 2; 1838 1839 /* Seq */ 1840 if(depth == 4) regp->sisRegs3C4[0] = 0x02; 1841 else regp->sisRegs3C4[0] = 0x00; 1842 1843 if(mode->Flags & V_CLKDIV2) regp->sisRegs3C4[1] = 0x09; 1844 else regp->sisRegs3C4[1] = 0x01; 1845 1846 regp->sisRegs3C4[2] = 0x0F; 1847 1848 regp->sisRegs3C4[3] = 0x00; 1849 1850 if(depth < 8) regp->sisRegs3C4[4] = 0x06; 1851 else regp->sisRegs3C4[4] = 0x0E; 1852 1853 /* CRTC */ 1854 regp->sisRegs3D4[0] = (mode->CrtcHTotal >> 3) - 5; 1855 regp->sisRegs3D4[1] = (mode->CrtcHDisplay >> 3) - 1; 1856 regp->sisRegs3D4[2] = (mode->CrtcHBlankStart >> 3) - 1; 1857 regp->sisRegs3D4[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80; 1858 i = (((mode->CrtcHSkew << 2) + 0x10) & ~0x1F); 1859 if(i < 0x80) regp->sisRegs3D4[3] |= i; 1860 regp->sisRegs3D4[4] = (mode->CrtcHSyncStart >> 3) - fixsync; 1861 regp->sisRegs3D4[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2) | 1862 (((mode->CrtcHSyncEnd >> 3) - fixsync) & 0x1F); 1863 regp->sisRegs3D4[6] = (mode->CrtcVTotal - 2) & 0xFF; 1864 regp->sisRegs3D4[7] = (((mode->CrtcVTotal - 2) & 0x100) >> 8) | 1865 (((mode->CrtcVDisplay - 1) & 0x100) >> 7) | 1866 (((mode->CrtcVSyncStart - fixsync) & 0x100) >> 6) | 1867 (((mode->CrtcVBlankStart - 1) & 0x100) >> 5) | 1868 0x10 | 1869 (((mode->CrtcVTotal - 2) & 0x200) >> 4) | 1870 (((mode->CrtcVDisplay - 1) & 0x200) >> 3) | 1871 (((mode->CrtcVSyncStart - fixsync) & 0x200) >> 2); 1872 regp->sisRegs3D4[8] = 0x00; 1873 regp->sisRegs3D4[9] = (((mode->CrtcVBlankStart - 1) & 0x200) >> 4) | 0x40; 1874 if(mode->Flags & V_DBLSCAN) regp->sisRegs3D4[9] |= 0x80; 1875 if(mode->VScan >= 32) regp->sisRegs3D4[9] |= 0x1F; 1876 else if (mode->VScan > 1) regp->sisRegs3D4[9] |= mode->VScan - 1; 1877 regp->sisRegs3D4[10] = 0x00; 1878 regp->sisRegs3D4[11] = 0x00; 1879 regp->sisRegs3D4[12] = 0x00; 1880 regp->sisRegs3D4[13] = 0x00; 1881 regp->sisRegs3D4[14] = 0x00; 1882 regp->sisRegs3D4[15] = 0x00; 1883 regp->sisRegs3D4[16] = (mode->CrtcVSyncStart - fixsync) & 0xFF; 1884 regp->sisRegs3D4[17] = ((mode->CrtcVSyncEnd - fixsync) & 0x0F) | 0x20; 1885 regp->sisRegs3D4[18] = (mode->CrtcVDisplay - 1) & 0xFF; 1886 regp->sisRegs3D4[19] = pScrn->displayWidth >> 4; 1887 regp->sisRegs3D4[20] = 0x00; 1888 regp->sisRegs3D4[21] = (mode->CrtcVBlankStart - 1) & 0xFF; 1889 regp->sisRegs3D4[22] = (mode->CrtcVBlankEnd - 1) & 0xFF; 1890 if(depth < 8) regp->sisRegs3D4[23] = 0xE3; 1891 else regp->sisRegs3D4[23] = 0xC3; 1892 regp->sisRegs3D4[24] = 0xFF; 1893 1894#if 0 1895 SiS_HBlankKGA(mode, regp, 0, SISKGA_FIX_OVERSCAN | SISKGA_ENABLE_ON_ZERO); 1896#endif 1897 SiS_VBlankKGA(mode, regp, 0, SISKGA_FIX_OVERSCAN | SISKGA_ENABLE_ON_ZERO); 1898 1899 /* GR */ 1900 regp->sisRegsGR[0] = 0x00; 1901 regp->sisRegsGR[1] = 0x00; 1902 regp->sisRegsGR[2] = 0x00; 1903 regp->sisRegsGR[3] = 0x00; 1904 regp->sisRegsGR[4] = 0x00; 1905 if(depth == 4) regp->sisRegsGR[5] = 0x02; 1906 else regp->sisRegsGR[5] = 0x40; 1907 regp->sisRegsGR[6] = 0x05; /* only map 64k VGA memory !!!! */ 1908 regp->sisRegsGR[7] = 0x0F; 1909 regp->sisRegsGR[8] = 0xFF; 1910 1911 /* Attr */ 1912 for(i = 0; i <= 15; i++) { /* standard colormap translation */ 1913 regp->sisRegsATTR[i] = i; 1914 } 1915 if(depth == 4) regp->sisRegsATTR[16] = 0x81; 1916 else regp->sisRegsATTR[16] = 0x41; 1917 if(depth >= 4) regp->sisRegsATTR[17] = 0xFF; 1918 else regp->sisRegsATTR[17] = 0x01; 1919 regp->sisRegsATTR[18] = 0x0F; 1920 regp->sisRegsATTR[19] = 0x00; 1921 regp->sisRegsATTR[20] = 0x00; 1922 1923 return TRUE; 1924} 1925 1926static void 1927SISVGABlankScreen(ScrnInfoPtr pScrn, Bool on) 1928{ 1929 SISPtr pSiS = SISPTR(pScrn); 1930 UChar tmp, orig; 1931 1932 inSISIDXREG(SISSR, 0x01, tmp); 1933 orig = tmp; 1934 if(on) tmp &= ~0x20; 1935 else tmp |= 0x20; 1936 /* Only update the hardware if the state changes because the reset will 1937 * disrupt the output requiring the screen to resync. 1938 */ 1939 if(orig == tmp) 1940 return; 1941 SiS_SeqReset(pSiS, TRUE); 1942 outSISIDXREG(SISSR, 0x01, tmp); 1943 SiS_SeqReset(pSiS, FALSE); 1944} 1945 1946Bool 1947SiSVGASaveScreen(ScreenPtr pScreen, int mode) 1948{ 1949 ScrnInfoPtr pScrn = NULL; 1950 Bool on = xf86IsUnblank(mode); 1951 1952 if(pScreen == NULL) return FALSE; 1953 1954 pScrn = xf86ScreenToScrn(pScreen); 1955 1956 if(pScrn->vtSema) { 1957 SISVGABlankScreen(pScrn, on); 1958 } 1959 return TRUE; 1960} 1961 1962#undef SIS_FONTS_SIZE 1963 1964 1965