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