4 * Mode setup and basic video bridge detection
6 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria.
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.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
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.
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.
35 * Author: Thomas Winischhofer <thomas@winischhofer.net>
40 #define SIS_NEED_inSISREG
41 #define SIS_NEED_outSISREG
42 #define SIS_NEED_inSISIDXREG
43 #define SIS_NEED_outSISIDXREG
44 #define SIS_NEED_orSISIDXREG
45 #define SIS_NEED_andSISIDXREG
49 static Bool
SISInit(ScrnInfoPtr pScrn
, DisplayModePtr mode
);
50 static Bool
SIS300Init(ScrnInfoPtr pScrn
, DisplayModePtr mode
);
51 static int SIS6326DoSense(ScrnInfoPtr pScrn
, int tempbh
, int tempbl
, int tempch
, int tempcl
);
52 static void SISSense6326(ScrnInfoPtr pScrn
);
53 static void SiS6326TVDelay(ScrnInfoPtr pScrn
, int delay
);
54 extern void SISSense30x(ScrnInfoPtr pScrn
, Bool quiet
);
55 extern void SISSenseChrontel(ScrnInfoPtr pScrn
, Bool quiet
);
57 /* Our very own vgaHW functions */
58 void SiSVGASave(ScrnInfoPtr pScrn
, SISRegPtr save
, int flags
);
59 void SiSVGARestore(ScrnInfoPtr pScrn
, SISRegPtr restore
, int flags
);
60 void SiSVGASaveFonts(ScrnInfoPtr pScrn
);
61 void SiSVGARestoreFonts(ScrnInfoPtr pScrn
);
62 void SISVGALock(SISPtr pSiS
);
63 void SiSVGAUnlock(SISPtr pSiS
);
64 void SiSVGAProtect(ScrnInfoPtr pScrn
, Bool on
);
65 #ifdef SIS_PC_PLATFORM
66 Bool
SiSVGAMapMem(ScrnInfoPtr pScrn
);
67 void SiSVGAUnmapMem(ScrnInfoPtr pScrn
);
69 Bool
SiSVGASaveScreen(ScreenPtr pScreen
, int mode
);
70 static Bool
SiSVGAInit(ScrnInfoPtr pScrn
, DisplayModePtr mode
, int fixsync
);
72 const CARD8 SiS6326TVRegs1
[14] = {
73 0x00,0x01,0x02,0x03,0x04,0x11,0x12,0x13,0x21,0x26,0x27,0x3a,0x3c,0x43
76 const CARD8 SiS6326TVRegs1_NTSC
[6][14] = {
77 {0x81,0x3f,0x49,0x1b,0xa9,0x03,0x00,0x09,0x08,0x7d,0x00,0x88,0x30,0x60},
78 {0x81,0x3f,0x49,0x1d,0xa0,0x03,0x00,0x09,0x08,0x7d,0x00,0x88,0x30,0x60},
79 {0x81,0x45,0x24,0x8e,0x26,0x0b,0x00,0x09,0x02,0xfe,0x00,0x09,0x51,0x60},
80 {0x81,0x45,0x24,0x8e,0x26,0x07,0x00,0x29,0x04,0x30,0x10,0x3b,0x61,0x60},
81 {0x81,0x3f,0x24,0x8e,0x26,0x09,0x00,0x09,0x02,0x30,0x10,0x3b,0x51,0x60}, /* 640x400, 640x480 */
82 {0x83,0x5d,0x21,0xbe,0x75,0x03,0x00,0x09,0x08,0x42,0x10,0x4d,0x61,0x79} /* 640x480u */
85 const CARD8 SiS6326TVRegs2_NTSC
[6][54] = {
86 {0x11, 0x17, 0x03, 0x09, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C,
87 0x0C, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94,
88 0xFC, 0xDF, 0x94, 0x1F, 0x4A, 0x03, 0x71, 0x07, 0x97, 0x10, 0x40,
89 0x48, 0x00, 0x26, 0xB6, 0x10, 0x5C, 0xEC, 0x21, 0x2E, 0xBE, 0x10,
90 0x64, 0xF4, 0x21, 0x13, 0x75, 0x08, 0x31, 0x6A, 0x01, 0xA0},
91 {0x11, 0x17, 0x03, 0x0A, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C,
92 0x0D, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94,
93 0xFF, 0xDF, 0x94, 0x1F, 0x4A, 0x03, 0x71, 0x07, 0x97, 0x10, 0x40,
94 0x48, 0x00, 0x26, 0xB6, 0x10, 0x5C, 0xEC, 0x21, 0x2E, 0xBE, 0x10,
95 0x64, 0xF4, 0x21, 0x13, 0x75, 0x08, 0x31, 0x6A, 0x01, 0xA0},
96 {0x11, 0x17, 0x03, 0x0A, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C,
97 0x0D, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94,
98 0xFF, 0xDF, 0x94, 0x3F, 0x8C, 0x06, 0xCE, 0x07, 0x27, 0x30, 0x73,
99 0x7B, 0x00, 0x48, 0x68, 0x30, 0xB2, 0xD2, 0x52, 0x50, 0x70, 0x30,
100 0xBA, 0xDA, 0x52, 0xDC, 0x02, 0xD1, 0x53, 0xF7, 0x02, 0xA0},
101 {0x11, 0x17, 0x03, 0x09, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C,
102 0x0C, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94,
103 0xDC, 0xDF, 0x94, 0x3F, 0x8C, 0x06, 0xCE, 0x07, 0x27, 0x30, 0x73,
104 0x7B, 0x00, 0x48, 0x68, 0x30, 0xB2, 0xD2, 0x52, 0x50, 0x70, 0x30,
105 0xBA, 0xDA, 0x52, 0x00, 0x02, 0xF5, 0x53, 0xF7, 0x02, 0xA0},
106 {0x11, 0x17, 0x03, 0x09, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C,
107 0x0C, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94,
108 0xDC, 0xDF, 0x94, 0x3F, 0x8C, 0x06, 0xCE, 0x07, 0x27, 0x30, 0x73,
109 0x7B, 0x00, 0x48, 0x68, 0x30, 0xB2, 0xD2, 0x52, 0x50, 0x70, 0x30,
110 0xBA, 0xDA, 0x52, 0xDC, 0x02, 0xD1, 0x53, 0xF7, 0x02, 0xA0},
111 {0x11, 0x17, 0x03, 0x09, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C, /* 640x480u */
112 0x0C, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94,
113 0xDC, 0xDF, 0x94, 0xAF, 0x95, 0x06, 0xDD, 0x07, 0x5F, 0x30, 0x7E,
114 0x86, 0x00, 0x4C, 0xA4, 0x30, 0xE3, 0x3B, 0x62, 0x54, 0xAC, 0x30,
115 0xEB, 0x43, 0x62, 0x48, 0x34, 0x3D, 0x63, 0x29, 0x03, 0xA0}
118 const CARD8 SiS6326TVRegs1_PAL
[6][14] = {
119 {0x81,0x2d,0xc8,0x07,0xb2,0x0b,0x00,0x09,0x02,0xed,0x00,0xf8,0x30,0x40},
120 {0x80,0x2d,0xa4,0x03,0xd9,0x0b,0x00,0x09,0x02,0xed,0x10,0xf8,0x71,0x40},
121 {0x81,0x2d,0xa4,0x03,0xd9,0x0b,0x00,0x09,0x02,0xed,0x10,0xf8,0x71,0x40}, /* 640x480 */
122 {0x81,0x2d,0xa4,0x03,0xd9,0x0b,0x00,0x09,0x02,0x8f,0x10,0x9a,0x71,0x40}, /* 800x600 */
123 {0x83,0x63,0xa1,0x7a,0xa3,0x0a,0x00,0x09,0x02,0xb5,0x11,0xc0,0x81,0x59}, /* 800x600u */
124 {0x81,0x63,0xa4,0x03,0xd9,0x01,0x00,0x09,0x10,0x9f,0x10,0xaa,0x71,0x59} /* 720x540 */
127 const CARD8 SiS6326TVRegs2_PAL
[6][54] = {
128 {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D,
129 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94,
130 0xE5, 0xDF, 0x94, 0xEF, 0x5A, 0x03, 0x7F, 0x07, 0xFF, 0x10, 0x4E,
131 0x56, 0x00, 0x2B, 0x23, 0x20, 0xB4, 0xAC, 0x31, 0x33, 0x2B, 0x20,
132 0xBC, 0xB4, 0x31, 0x83, 0xE1, 0x78, 0x31, 0xD6, 0x01, 0xA0},
133 {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D,
134 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94,
135 0xE5, 0xDF, 0x94, 0xDF, 0xB2, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x90,
136 0x98, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40,
137 0x6A, 0x5A, 0x73, 0x03, 0xC1, 0xF8, 0x63, 0xB6, 0x03, 0xA0},
138 {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, /* 640x480 */
139 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94,
140 0xE5, 0xDF, 0x94, 0xDF, 0xB2, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x90,
141 0x98, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40,
142 0x6A, 0x5A, 0x73, 0x03, 0xC1, 0xF8, 0x63, 0xB6, 0x03, 0xA0},
143 {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, /* 800x600 */
144 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94,
145 0xE5, 0xDF, 0x94, 0xDF, 0xB2, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x90,
146 0x98, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40,
147 0x6A, 0x5A, 0x73, 0xA0, 0xC1, 0x95, 0x73, 0xB6, 0x03, 0xA0},
148 {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, /* 800x600u */
149 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94,
150 0xE5, 0xDF, 0x94, 0x7F, 0xBD, 0x08, 0x0E, 0x07, 0x47, 0x40, 0x9D,
151 0xA5, 0x00, 0x54, 0x94, 0x40, 0xA4, 0xE4, 0x73, 0x5C, 0x9C, 0x40,
152 0xAC, 0xEC, 0x73, 0x0B, 0x0E, 0x00, 0x84, 0x03, 0x04, 0xA0},
153 {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, /* 720x540 */
154 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94,
155 0xE5, 0xDF, 0x94, 0xDF, 0xB0, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x9D,
156 0xA5, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40,
157 0x6A, 0x5A, 0x73, 0xA0, 0xC1, 0x95, 0x73, 0xB6, 0x03, 0xA0}
160 const CARD8 SiS6326CR
[9][15] = {
161 {0x79,0x63,0x64,0x1d,0x6a,0x93,0x00,0x6f,0xf0,0x58,0x8a,0x57,0x57,0x70,0x20}, /* PAL 800x600 */
162 {0x79,0x4f,0x50,0x95,0x60,0x93,0x00,0x6f,0xba,0x14,0x86,0xdf,0xe0,0x30,0x00}, /* PAL 640x480 */
163 {0x5f,0x4f,0x50,0x82,0x53,0x9f,0x00,0x0b,0x3e,0xe9,0x8b,0xdf,0xe7,0x04,0x00}, /* NTSC 640x480 */
164 {0x5f,0x4f,0x50,0x82,0x53,0x9f,0x00,0x0b,0x3e,0xcb,0x8d,0x8f,0x96,0xe9,0x00}, /* NTSC 640x400 */
165 {0x83,0x63,0x64,0x1f,0x6d,0x9b,0x00,0x6f,0xf0,0x48,0x0a,0x23,0x57,0x70,0x20}, /* PAL 800x600u */
166 {0x79,0x59,0x5b,0x1d,0x66,0x93,0x00,0x6f,0xf0,0x42,0x04,0x1b,0x40,0x70,0x20}, /* PAL 720x540 */
167 {0x66,0x4f,0x51,0x0a,0x57,0x89,0x00,0x0b,0x3e,0xd9,0x0b,0xb6,0xe7,0x04,0x00}, /* NTSC 640x480u */
168 {0xce,0x9f,0x9f,0x92,0xa4,0x16,0x00,0x28,0x5a,0x00,0x04,0xff,0xff,0x29,0x39}, /* 1280x1024-75 */
169 {0x09,0xc7,0xc7,0x0d,0xd2,0x0a,0x01,0xe0,0x10,0xb0,0x04,0xaf,0xaf,0xe1,0x1f} /* 1600x1200-60 */
172 /* Initialize a display mode on 5597/5598, 6326 and 530/620 */
174 SISInit(ScrnInfoPtr pScrn
, DisplayModePtr mode
)
176 SISPtr pSiS
= SISPTR(pScrn
);
177 SISRegPtr pReg
= &pSiS
->ModeReg
;
179 int mclk
= pSiS
->MemClock
;
180 int clock
= mode
->Clock
;
181 int width
= mode
->HDisplay
;
182 int height
= mode
->VDisplay
;
183 int rate
= (int)SiSCalcVRate(mode
);
184 int buswidth
= pSiS
->BusWidth
;
185 unsigned int vclk
[5];
186 UShort CRT_CPUthresholdLow
, CRT_CPUthresholdHigh
, CRT_ENGthreshold
;
188 int d
, factor
, offset
, fixsync
= 1;
189 int num
, denum
, div
, sbit
, scale
;
190 Bool sis6326tvmode
, sis6326himode
;
192 /* Save the registers for further processing */
193 (*pSiS
->SiSSave
)(pScrn
, pReg
);
195 /* Initialise the standard VGA registers */
197 if(!SiSVGAInit(pScrn
, mode
, fixsync
)) {
198 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
, "SISInit: SiSVGAInit() failed\n");
203 /* Determine if chosen mode is suitable for TV on the 6326
204 * and if the mode is one of our special hi-res modes.
206 sis6326tvmode
= FALSE
;
207 sis6326himode
= FALSE
;
208 if(pSiS
->Chipset
== PCI_CHIP_SIS6326
) {
209 if(pSiS
->SiS6326Flags
& SIS6326_HASTV
) {
210 if((pSiS
->SiS6326Flags
& SIS6326_TVDETECTED
) &&
211 ((strcmp(mode
->name
, "PAL800x600") == 0) || /* Special TV modes */
212 (strcmp(mode
->name
, "PAL800x600U") == 0) ||
213 (strcmp(mode
->name
, "PAL720x540") == 0) ||
214 (strcmp(mode
->name
, "PAL640x480") == 0) ||
215 (strcmp(mode
->name
, "NTSC640x480") == 0) ||
216 (strcmp(mode
->name
, "NTSC640x480U") == 0) ||
217 (strcmp(mode
->name
, "NTSC640x400") == 0))) {
218 sis6326tvmode
= TRUE
;
220 pReg
->sis6326tv
[0x00] &= 0xfb;
223 if((strcmp(mode
->name
, "SIS1280x1024-75") == 0) || /* Special high-res modes */
224 (strcmp(mode
->name
, "SIS1600x1200-60") == 0)) {
225 sis6326himode
= TRUE
;
230 outSISIDXREG(SISSR
, 0x05, 0x86);
234 pReg
->sisRegs3C4
[0x06] &= 0x01;
238 if(!(mode
->Flags
& V_INTERLACE
)) {
239 offset
= pSiS
->CurrentLayout
.displayWidth
>> 3;
241 offset
= pSiS
->CurrentLayout
.displayWidth
>> 2;
243 pReg
->sisRegs3C4
[0x06] |= 0x20;
247 /* Enable Linear and Enhanced Gfx Mode */
249 pReg
->sisRegs3C4
[0x06] |= 0x82;
252 /* Enable MMIO at PCI Register 14H (D[6:5]: 11) */
253 if(pSiS
->oldChipset
>= OC_SIS5597
) {
254 pReg
->sisRegs3C4
[0x0B] |= 0x60;
256 pReg
->sisRegs3C4
[0x0B] |= 0x20;
257 pReg
->sisRegs3C4
[0x0B] &= ~0x40;
262 /* Enable 32bit mem access (D7), read-ahead cache (D5) */
263 pReg
->sisRegs3C4
[0x0C] |= 0x80;
264 if(pSiS
->oldChipset
> OC_SIS6225
) {
265 pReg
->sisRegs3C4
[0x0C] |= 0x20;
268 /* Some speed-up stuff */
269 switch(pSiS
->Chipset
) {
270 case PCI_CHIP_SIS5597
:
271 /* enable host bus */
273 pReg
->sisRegs3C4
[0x34] &= ~0x08;
275 pReg
->sisRegs3C4
[0x34] |= 0x08;
278 case PCI_CHIP_SIS6326
:
279 case PCI_CHIP_SIS530
:
280 /* Enable "dual segment register mode" (D2) and "i/o gating while
281 * write buffer is not empty" (D3)
283 pReg
->sisRegs3C4
[0x0B] |= 0x0C;
287 if(pSiS
->Chipset
== PCI_CHIP_SIS530
) {
288 pReg
->sisRegs3C4
[0x09] &= 0x7F;
290 switch(pSiS
->CurrentLayout
.bitsPerPixel
) {
295 if(pSiS
->CurrentLayout
.depth
== 15)
296 pReg
->sisRegs3C4
[0x06] |= 0x04;
298 pReg
->sisRegs3C4
[0x06] |= 0x08;
301 offset
+= (offset
<< 1);
302 pReg
->sisRegs3C4
[0x06] |= 0x10;
303 pReg
->sisRegs3C4
[0x0B] |= 0x90;
306 if(pSiS
->Chipset
== PCI_CHIP_SIS530
) {
308 if(pSiS
->oldChipset
!= OC_SIS620
) {
309 pReg
->sisRegs3C4
[0x06] |= 0x10;
311 pReg
->sisRegs3C4
[0x0B] |= 0x90;
312 pReg
->sisRegs3C4
[0x09] |= 0x80;
318 /* save screen pitch for acceleration functions */
319 pSiS
->scrnOffset
= pSiS
->CurrentLayout
.displayWidth
*
320 ((pSiS
->CurrentLayout
.bitsPerPixel
+ 7) / 8);
324 /* set linear framebuffer addresses */
325 switch(pScrn
->videoRam
) {
326 case 512: temp
= 0x00; break;
327 case 1024: temp
= 0x20; break;
328 case 2048: temp
= 0x40; break;
329 case 4096: temp
= 0x60; break;
330 case 8192: temp
= 0x80; break;
331 default: temp
= 0x20;
333 pReg
->sisRegs3C4
[0x20] = (pSiS
->FbAddress
& 0x07F80000) >> 19;
334 pReg
->sisRegs3C4
[0x21] = ((pSiS
->FbAddress
& 0xF8000000) >> 27) | temp
;
336 /* Set screen offset */
337 pReg
->sisRegs3D4
[0x13] = offset
& 0xFF;
339 /* Set CR registers for our built-in TV and hi-res modes */
340 if((sis6326tvmode
) || (sis6326himode
)) {
344 /* We need our very private data for hi-res and TV modes */
346 if(strcmp(mode
->name
, "SIS1280x1024-75") == 0) index
= 7;
349 if(pSiS
->SiS6326Flags
& SIS6326_TVPAL
) {
352 if((strcmp(mode
->name
, "PAL800x600U") == 0))
371 if((strcmp(mode
->name
, "NTSC640x480U") == 0))
378 for(i
=0; i
<=5; i
++) {
379 pReg
->sisRegs3D4
[i
] = SiS6326CR
[index
][i
];
381 pReg
->sisRegs3C4
[0x12] = SiS6326CR
[index
][6];
382 pReg
->sisRegs3D4
[6] = SiS6326CR
[index
][7];
383 pReg
->sisRegs3D4
[7] = SiS6326CR
[index
][8];
384 pReg
->sisRegs3D4
[0x10] = SiS6326CR
[index
][9];
385 pReg
->sisRegs3D4
[0x11] = SiS6326CR
[index
][10];
386 pReg
->sisRegs3D4
[0x12] = SiS6326CR
[index
][11];
387 pReg
->sisRegs3D4
[0x15] = SiS6326CR
[index
][12];
388 pReg
->sisRegs3D4
[0x16] = SiS6326CR
[index
][13];
389 pReg
->sisRegs3D4
[9] &= ~0x20;
390 pReg
->sisRegs3D4
[9] |= (SiS6326CR
[index
][14] & 0x20);
391 pReg
->sisRegs3C4
[0x0A] = ((offset
& 0xF00) >> 4) | (SiS6326CR
[index
][14] & 0x0f);
395 /* Set extended vertical overflow register */
396 pReg
->sisRegs3C4
[0x0A] = (
397 ((offset
& 0xF00) >> 4) |
398 (((mode
->CrtcVTotal
- 2) & 0x400) >> 10) |
399 (((mode
->CrtcVDisplay
- 1) & 0x400) >> 9) |
400 (((mode
->CrtcVBlankStart
- 1) & 0x400) >> 8) |
401 (((mode
->CrtcVSyncStart
- fixsync
) & 0x400) >> 7));
403 /* Set extended horizontal overflow register */
404 pReg
->sisRegs3C4
[0x12] &= 0xE0;
405 pReg
->sisRegs3C4
[0x12] |= (
406 ((((mode
->CrtcHTotal
>> 3) - 5) & 0x100) >> 8) |
407 ((((mode
->CrtcHDisplay
>> 3) - 1) & 0x100) >> 7) |
408 ((((mode
->CrtcHBlankStart
>> 3) - 1) & 0x100) >> 6) |
409 ((((mode
->CrtcHSyncStart
>> 3) - fixsync
)& 0x100) >> 5) |
410 ((((mode
->CrtcHBlankEnd
>> 3) - 1) & 0x40) >> 2));
413 /* enable (or disable) line compare */
414 if(mode
->CrtcVDisplay
>= 1024)
415 pReg
->sisRegs3C4
[0x38] |= 0x04;
417 pReg
->sisRegs3C4
[0x38] &= 0xFB;
419 /* Enable (or disable) high speed DCLK (some 6326 and 530/620 only) */
420 if( ( (pSiS
->Chipset
== PCI_CHIP_SIS6326
) &&
421 ( (pSiS
->ChipRev
== 0xd0) || (pSiS
->ChipRev
== 0xd1) ||
422 (pSiS
->ChipRev
== 0xd2) || (pSiS
->ChipRev
== 0x92) ||
423 (pSiS
->Flags
& A6326REVAB
) ) ) ||
424 (pSiS
->oldChipset
> OC_SIS6326
) ) {
425 if( (pSiS
->CurrentLayout
.bitsPerPixel
== 24) ||
426 (pSiS
->CurrentLayout
.bitsPerPixel
== 32) ||
427 (mode
->CrtcHDisplay
>= 1280) )
428 pReg
->sisRegs3C4
[0x3E] |= 0x01;
430 pReg
->sisRegs3C4
[0x3E] &= 0xFE;
433 /* We use the internal VCLK */
434 pReg
->sisRegs3C4
[0x38] &= 0xFC;
436 /* Programmable Clock */
437 pReg
->sisRegs3C2
= inSISREG(SISMISCR
) | 0x0C;
440 if(pSiS
->oldChipset
<= OC_SIS86202
) {
441 /* TODO: Handle SR07 for clock selection */
442 /* 86C201 does not even have a programmable clock... */
443 /* pReg->sisRegs3C4[0x07] &= 0x??; */
448 if((sis6326tvmode
) || (sis6326himode
)) {
450 /* For our built-in modes, the calculation is not suitable */
452 if((strcmp(mode
->name
, "SIS1280x1024-75") == 0)) {
453 pReg
->sisRegs3C4
[0x2A] = 0x5d; /* 1280x1024-75 */
454 pReg
->sisRegs3C4
[0x2B] = 0xa4;
456 pReg
->sisRegs3C4
[0x2A] = 0x59; /* 1600x1200-60 */
457 pReg
->sisRegs3C4
[0x2B] = 0xa3;
459 pReg
->sisRegs3C4
[0x13] &= ~0x40;
461 if(pSiS
->SiS6326Flags
& SIS6326_TVPAL
) {
462 /* PAL: 31.500 Mhz */
463 if((strcmp(mode
->name
, "PAL800x600U") == 0)) {
464 pReg
->sisRegs3C4
[0x2A] = 0x46;
465 pReg
->sisRegs3C4
[0x2B] = 0x49;
467 pReg
->sisRegs3C4
[0x2A] = 0xab;
468 pReg
->sisRegs3C4
[0x2B] = 0xe9;
470 pReg
->sisRegs3C4
[0x13] &= ~0x40;
472 /* NTSC: 27.000 Mhz */
473 if((strcmp(mode
->name
, "NTSC640x480U") == 0)) {
474 pReg
->sisRegs3C4
[0x2A] = 0x5a;
475 pReg
->sisRegs3C4
[0x2B] = 0x65;
477 pReg
->sisRegs3C4
[0x2A] = 0x29;
478 pReg
->sisRegs3C4
[0x2B] = 0xe2;
480 pReg
->sisRegs3C4
[0x13] |= 0x40;
484 } else if(SiS_compute_vclk(clock
, &num
, &denum
, &div
, &sbit
, &scale
)) {
486 pReg
->sisRegs3C4
[0x2A] = (num
- 1) & 0x7f ;
487 pReg
->sisRegs3C4
[0x2A] |= (div
== 2) ? 0x80 : 0;
488 pReg
->sisRegs3C4
[0x2B] = ((denum
- 1) & 0x1f);
489 pReg
->sisRegs3C4
[0x2B] |= (((scale
-1) & 3) << 5);
491 /* When setting VCLK, we should set SR13 first */
493 pReg
->sisRegs3C4
[0x13] |= 0x40;
495 pReg
->sisRegs3C4
[0x13] &= 0xBF;
498 xf86DrvMsg(0, X_INFO
, "2a: %x 2b: %x 13: %x clock %d\n",
499 pReg
->sisRegs3C4
[0x2A], pReg
->sisRegs3C4
[0x2B], pReg
->sisRegs3C4
[0x13], clock
);
504 /* if SiS_compute_vclk cannot handle the requested clock, try sisCalcClock */
505 SiSCalcClock(pScrn
, clock
, 2, vclk
);
513 pReg
->sisRegs3C4
[0x2A] = (vclk
[Midx
] - 1) & 0x7f;
514 pReg
->sisRegs3C4
[0x2A] |= ((vclk
[VLDidx
] == 2) ? 1 : 0) << 7;
516 /* D[4:0]: denumerator */
517 pReg
->sisRegs3C4
[0x2B] = (vclk
[Nidx
] - 1) & 0x1f;
520 /* postscale 1,2,3,4 */
521 pReg
->sisRegs3C4
[0x2B] |= (vclk
[Pidx
] - 1) << 5;
522 pReg
->sisRegs3C4
[0x13] &= 0xBF;
525 pReg
->sisRegs3C4
[0x2B] |= ((vclk
[Pidx
] / 2) - 1) << 5;
526 pReg
->sisRegs3C4
[0x13] |= 0x40;
528 pReg
->sisRegs3C4
[0x2B] |= 0x80 ; /* gain for high frequency */
534 pReg
->sisRegs3C4
[0x07] |= 0x02;
536 if(pSiS
->oldChipset
> OC_SIS6225
) {
537 /* 1 or 2 cycle DRAM (set by option FastVram) */
538 if(pSiS
->newFastVram
== -1) {
539 if(pSiS
->oldChipset
== OC_SIS620
) {
540 /* Use different default on the 620 */
541 pReg
->sisRegs3C4
[0x34] |= 0x40;
542 pReg
->sisRegs3C4
[0x34] &= ~0x80;
544 pReg
->sisRegs3C4
[0x34] |= 0x80;
545 pReg
->sisRegs3C4
[0x34] &= ~0x40;
547 } else if(pSiS
->newFastVram
== 1)
548 pReg
->sisRegs3C4
[0x34] |= 0xC0;
550 pReg
->sisRegs3C4
[0x34] &= ~0xC0;
552 if(pSiS
->oldChipset
== OC_SIS620
) {
553 /* Enable SGRAM burst timing (= bit clear) on the 620 */
554 if(pSiS
->Flags
& SYNCDRAM
) {
555 pReg
->sisRegs3C4
[0x35] &= ~0x20;
557 pReg
->sisRegs3C4
[0x35] |= 0x20;
564 /* Logical line length */
565 pSiS
->ValidWidth
= TRUE
;
566 pReg
->sisRegs3C4
[0x27] &= 0xCF;
567 if(pSiS
->CurrentLayout
.bitsPerPixel
== 24) {
568 /* "Invalid logical width" */
569 pReg
->sisRegs3C4
[0x27] |= 0x30;
570 pSiS
->ValidWidth
= FALSE
;
572 switch(pScrn
->virtualX
* (pSiS
->CurrentLayout
.bitsPerPixel
>> 3)) {
574 pReg
->sisRegs3C4
[0x27] |= 0x00;
577 pReg
->sisRegs3C4
[0x27] |= 0x10;
580 pReg
->sisRegs3C4
[0x27] |= 0x20;
583 /* Invalid logical width */
584 pReg
->sisRegs3C4
[0x27] |= 0x30;
585 pSiS
->ValidWidth
= FALSE
;
590 /* Acceleration stuff */
592 pReg
->sisRegs3C4
[0x27] |= 0x40; /* Enable engine programming registers */
593 if( (pSiS
->TurboQueue
) && /* Handle TurboQueue */
594 (pSiS
->oldChipset
> OC_SIS6225
) &&
595 ( (pSiS
->Chipset
!= PCI_CHIP_SIS530
) ||
596 (pSiS
->CurrentLayout
.bitsPerPixel
!= 24) ) ) {
597 pReg
->sisRegs3C4
[0x27] |= 0x80; /* Enable TQ */
598 if((pSiS
->Chipset
== PCI_CHIP_SIS530
) ||
599 ((pSiS
->Chipset
== PCI_CHIP_SIS6326
&&
600 (pSiS
->ChipRev
== 0xd0 || pSiS
->ChipRev
== 0xd1 ||
601 pSiS
->ChipRev
== 0xd2 || pSiS
->ChipRev
== 0x92 ||
602 pSiS
->ChipRev
== 0x0a || pSiS
->ChipRev
== 0x1a ||
603 pSiS
->ChipRev
== 0x2a || pSiS
->ChipRev
== 0x0b ||
604 pSiS
->ChipRev
== 0x1b || pSiS
->ChipRev
== 0x2b) ) ) ) {
605 /* pReg->sisRegs3C4[0x3D] |= 0x80; */ /* Queue is 62K (530/620 specs) */
606 pReg
->sisRegs3C4
[0x3D] &= 0x7F; /* Queue is 30K (530/620 specs) */
608 /* Locate the TQ at the beginning of the last 64K block of
609 * video RAM. The address is to be specified in 32K steps.
611 pReg
->sisRegs3C4
[0x2C] = (pScrn
->videoRam
- 64) / 32;
612 if(pSiS
->Chipset
!= PCI_CHIP_SIS530
) { /* 530/620: Reserved (don't touch) */
613 pReg
->sisRegs3C4
[0x3C] &= 0xFC; /* 6326: Queue is all for 2D */
614 } /* 5597: Must be 0 */
616 pReg
->sisRegs3C4
[0x27] &= 0x7F;
623 /* No idea what this does. The Windows driver does it, so we do it as well */
624 if(pSiS
->Chipset
== PCI_CHIP_SIS6326
) {
625 if((pSiS
->ChipRev
== 0xd0) || (pSiS
->ChipRev
== 0xd1) ||
626 (pSiS
->ChipRev
== 0xd2) || (pSiS
->ChipRev
== 0x92) ||
627 (pSiS
->Flags
& A6326REVAB
)) {
628 if((pSiS
->Flags
& (SYNCDRAM
| RAMFLAG
)) == (SYNCDRAM
| RAMFLAG
)) {
629 if(!(pReg
->sisRegs3C4
[0x0E] & 0x03)) {
630 pReg
->sisRegs3C4
[0x3E] |= 0x02;
638 /* We don't need to do this; the SetMClk option was not used since 4.0. */
639 if((pSiS
->Chipset
== PCI_CHIP_SIS5597
) || (pSiS
->Chipset
== PCI_CHIP_SIS6326
)) {
640 if(pSiS
->MemClock
> 66000) {
641 SiSCalcClock(pScrn
, pSiS
->MemClock
, 1, vclk
);
643 pReg
->sisRegs3C4
[0x28] = (vclk
[Midx
] - 1) & 0x7f ;
644 pReg
->sisRegs3C4
[0x28] |= ((vclk
[VLDidx
] == 2 ) ? 1 : 0 ) << 7 ;
645 pReg
->sisRegs3C4
[0x29] = (vclk
[Nidx
] -1) & 0x1f ; /* bits [4:0] contain denumerator -MC */
646 if(vclk
[Pidx
] <= 4) {
647 pReg
->sisRegs3C4
[0x29] |= (vclk
[Pidx
] - 1) << 5 ; /* postscale 1,2,3,4 */
648 pReg
->sisRegs3C4
[0x13] &= 0x7F;
650 pReg
->sisRegs3C4
[0x29] |= ((vclk
[Pidx
] / 2) - 1) << 5 ; /* postscale 6,8 */
651 pReg
->sisRegs3C4
[0x13] |= 0x80;
653 /* Check programmed memory clock. Enable only to check the above code */
655 mclk = 14318 * ((pReg->sisRegs3C4[0x28] & 0x7f) + 1);
656 mclk /= ((pReg->sisRegs3C4[0x29] & 0x0f) + 1);
657 if(!(pReg->sisRegs3C4[0x13] & 0x80)) {
658 mclk /= (((pReg->sisRegs3C4[0x29] & 0x60) >> 5) + 1);
660 if((pReg->sisRegs3C4[0x29] & 0x60) == 0x40) mclk /= 6;
661 if((pReg->sisRegs3C4[0x29] & 0x60) == 0x60) mclk /= 8;
663 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,2,
664 "Setting memory clock to %.3f MHz\n",
671 /* Set threshold values */
673 * CPU/CRT Threshold: FIFO
674 * MCLK ___________ VCLK
675 * cpu/engine <---o o--------->|___________| -----------> CRT
680 * selector switch Thrsh. low high
682 * CRT consumes the data in the FIFO during scanline display. When the
683 * amount of data in the FIFO reaches the Threshold low value, the selector
684 * switch will switch to the right, and the FIFO will be refilled with data.
685 * When the amount of data in the FIFO reaches the Threshold high value, the
686 * selector switch will switch to the left and allows the CPU and the chip
687 * engines to access the video RAM.
689 * The Threshold low values should be increased at higher bpps, simply because
690 * there is more data needed for the CRT. When Threshold low and high are very
691 * close to each other, the selector switch will be activated more often, which
692 * decreases performance.
695 switch(pSiS
->Chipset
) {
696 case PCI_CHIP_SIS5597
: factor
= 65; break;
697 case PCI_CHIP_SIS6326
: factor
= 30; break;
698 case PCI_CHIP_SIS530
: factor
= (pSiS
->Flags
& UMA
) ? 60 : 30; break;
699 default: factor
= (pScrn
->videoRam
> 1024) ? 24 : 12;
701 a
= width
* height
* rate
* 1.40 * factor
* ((pSiS
->CurrentLayout
.bitsPerPixel
+ 1) / 8);
702 b
= (mclk
/ 1000) * 999488.0 * (buswidth
/ 8);
703 c
= ((a
/ b
) + 1.0) / 2;
706 CRT_CPUthresholdLow
= d
;
707 if((pSiS
->Flags
& (RAMFLAG
| SYNCDRAM
)) == (RAMFLAG
| SYNCDRAM
)) {
708 CRT_CPUthresholdLow
+= 2;
710 CRT_CPUthresholdHigh
= CRT_CPUthresholdLow
+ 3;
712 CRT_ENGthreshold
= 0x0F;
714 #if 0 /* See comment in sis_dac.c on why this is commented */
715 if(pSiS
->Chipset
== PCI_CHIP_SIS530
) {
716 if((pSiS
->oldChipset
== OC_SIS530A
) &&
717 (pSiS
->Flags
& UMA
) &&
719 (pSiS
->Flags
& ESS137xPRESENT
)) {
720 if(!(pSiS
->Flags
& SECRETFLAG
)) index
= 0;
721 if((temp
= SiS_CalcSpecial530Threshold(pSiS
, mode
, index
)) {
722 CRT_CPUthresholdLow
= temp
;
729 switch(pSiS
->Chipset
) {
730 case PCI_CHIP_SIS530
:
731 if(CRT_CPUthresholdLow
> 0x1f) CRT_CPUthresholdLow
= 0x1f;
732 CRT_CPUthresholdHigh
= 0x1f;
734 case PCI_CHIP_SIS5597
:
735 case PCI_CHIP_SIS6326
:
737 if(CRT_CPUthresholdLow
> 0x0f) CRT_CPUthresholdLow
= 0x0f;
738 if(CRT_CPUthresholdHigh
> 0x0f) CRT_CPUthresholdHigh
= 0x0f;
741 pReg
->sisRegs3C4
[0x08] = ((CRT_CPUthresholdLow
& 0x0F) << 4) |
742 (CRT_ENGthreshold
& 0x0F);
744 pReg
->sisRegs3C4
[0x09] &= 0xF0;
745 pReg
->sisRegs3C4
[0x09] |= (CRT_CPUthresholdHigh
& 0x0F);
747 pReg
->sisRegs3C4
[0x3F] &= 0xEB;
748 pReg
->sisRegs3C4
[0x3F] |= ((CRT_CPUthresholdHigh
& 0x10) |
749 ((CRT_CPUthresholdLow
& 0x10) >> 2));
751 if(pSiS
->oldChipset
>= OC_SIS530A
) {
752 pReg
->sisRegs3C4
[0x3F] &= 0xDF;
753 pReg
->sisRegs3C4
[0x3F] |= 0x58;
756 /* Set SiS6326 TV registers */
757 if((pSiS
->Chipset
== PCI_CHIP_SIS6326
) && (sis6326tvmode
)) {
759 int index
=0, i
, j
, k
;
762 if(pSiS
->SiS6326Flags
& SIS6326_TVPAL
) {
763 pReg
->sisRegs3C4
[0x0D] |= 0x04;
766 if((strcmp(mode
->name
, "PAL800x600U") == 0)) index
= 4;
769 case 720: index
= 5; break;
773 for(i
=0; i
<14; i
++) {
774 pReg
->sis6326tv
[SiS6326TVRegs1
[i
]] = SiS6326TVRegs1_PAL
[index
][i
];
776 fsc
= (SiS6326TVRegs1_PAL
[index
][2] << 16) |
777 (SiS6326TVRegs1_PAL
[index
][3] << 8) |
778 (SiS6326TVRegs1_PAL
[index
][4]);
780 pReg
->sisRegs3C4
[0x0D] &= ~0x04;
781 if((strcmp(mode
->name
, "NTSC640x480U") == 0)) index
= 5;
783 for(i
=0; i
<14; i
++) {
784 pReg
->sis6326tv
[SiS6326TVRegs1
[i
]] = SiS6326TVRegs1_NTSC
[index
][i
];
786 fsc
= (SiS6326TVRegs1_NTSC
[index
][2] << 16) |
787 (SiS6326TVRegs1_NTSC
[index
][3] << 8) |
788 (SiS6326TVRegs1_NTSC
[index
][4]);
790 if(pSiS
->sis6326fscadjust
) {
791 fsc
+= pSiS
->sis6326fscadjust
;
792 pReg
->sis6326tv
[2] = (fsc
>> 16) & 0xff;
793 pReg
->sis6326tv
[3] = (fsc
>> 8) & 0xff;
794 pReg
->sis6326tv
[4] = fsc
& 0xff;
796 tmp
= pReg
->sis6326tv
[0x43];
797 if(pSiS
->SiS6326Flags
& SIS6326_TVCVBS
) tmp
|= 0x10;
799 pReg
->sis6326tv
[0x43] = tmp
;
801 for(i
=0; i
<=0x44; i
++) {
802 if(SiS6326TVRegs1
[j
] == i
) {
806 if(pSiS
->SiS6326Flags
& SIS6326_TVPAL
) {
807 tmp
= SiS6326TVRegs2_PAL
[index
][k
];
809 tmp
= SiS6326TVRegs2_NTSC
[index
][k
];
811 pReg
->sis6326tv
[i
] = tmp
;
814 pReg
->sis6326tv
[0x43] |= 0x08;
815 if((pSiS
->ChipRev
== 0xc1) || (pSiS
->ChipRev
== 0xc2)) {
816 pReg
->sis6326tv
[0x43] &= ~0x08;
819 tmp
= pReg
->sis6326tv
[0];
821 if(pSiS
->SiS6326Flags
& SIS6326_TVCVBS
) tmp
&= ~0x10;
822 if(pSiS
->SiS6326Flags
& SIS6326_TVSVIDEO
) tmp
&= ~0x08;
824 pReg
->sis6326tv
[0] = tmp
;
832 /* Init a mode for SiS 300, 315, 330, 340 series
833 * This function is now only used for setting up some
834 * variables (eg. scrnOffset).
837 SIS300Init(ScrnInfoPtr pScrn
, DisplayModePtr mode
)
839 SISPtr pSiS
= SISPTR(pScrn
);
840 SISRegPtr pReg
= &pSiS
->ModeReg
;
842 DisplayModePtr realmode
= mode
;
844 PDEBUG(xf86DrvMsgVerb(pScrn
->scrnIndex
, X_INFO
, 4, "SIS300Init()\n"));
846 xf86DrvMsgVerb(pScrn
->scrnIndex
, X_INFO
, 4,
847 "virtualX = %d depth = %d Logical width = %d\n",
848 pScrn
->virtualX
, pSiS
->CurrentLayout
.bitsPerPixel
,
849 pScrn
->virtualX
* pSiS
->CurrentLayout
.bitsPerPixel
/8);
853 realmode
= ((SiSMergedDisplayModePtr
)mode
->Private
)->CRT1
;
857 /* Copy current register settings to structure */
858 (*pSiS
->SiSSave
)(pScrn
, pReg
);
860 /* Calculate Offset/Display Pitch */
861 pSiS
->scrnOffset
= pSiS
->CurrentLayout
.displayWidth
*
862 ((pSiS
->CurrentLayout
.bitsPerPixel
+ 7) / 8);
864 pSiS
->scrnPitch
= pSiS
->scrnPitch2
= pSiS
->scrnOffset
;
865 if(!(pSiS
->VBFlags
& CRT1_LCDA
)) {
866 if(realmode
->Flags
& V_INTERLACE
) pSiS
->scrnPitch
<<= 1;
868 /* CRT2 mode can never be interlaced */
871 outSISIDXREG(SISSR
, 0x05, 0x86);
874 switch(pSiS
->CurrentLayout
.bitsPerPixel
) {
876 pSiS
->DstColor
= 0x0000;
877 pSiS
->SiS310_AccelDepth
= 0x00000000;
880 if(pSiS
->CurrentLayout
.depth
== 15)
881 pSiS
->DstColor
= (short) 0x4000;
883 pSiS
->DstColor
= (short) 0x8000;
884 pSiS
->SiS310_AccelDepth
= 0x00010000;
889 pSiS
->DstColor
= (short) 0xC000;
890 pSiS
->SiS310_AccelDepth
= 0x00020000;
894 /* Enable PCI LINEAR ADDRESSING (0x80), MMIO (0x01), PCI_IO (0x20) */
895 pReg
->sisRegs3C4
[0x20] = 0xA1;
897 /* Now initialize TurboQueue. TB is always located at the very top of
898 * the videoRAM (notably NOT the x framebuffer memory, which can/should
899 * be limited by MaxXFbMem when using DRI). Also, enable the accelerators.
902 pReg
->sisRegs3C4
[0x1E] |= 0x42; /* Enable 2D accelerator */
903 pReg
->sisRegs3C4
[0x1E] |= 0x18; /* Enable 3D accelerator */
904 switch(pSiS
->VGAEngine
) {
906 if(pSiS
->TurboQueue
) { /* set Turbo Queue as 512k */
907 temp
= ((pScrn
->videoRam
/64)-8); /* 8=512k, 4=256k, 2=128k, 1=64k */
908 pReg
->sisRegs3C4
[0x26] = temp
& 0xFF;
909 pReg
->sisRegs3C4
[0x27] =
910 (pReg
->sisRegs3C4
[0x27] & 0xfc) | (((temp
>> 8) & 3) | 0xF0);
911 } /* line above new for saving D2&3 of status register */
915 /* See comments in sis_driver.c */
916 pReg
->sisRegs3C4
[0x27] = 0x1F;
917 pReg
->sisRegs3C4
[0x26] = 0x22;
918 pReg
->sisMMIO85C0
= (pScrn
->videoRam
- 512) * 1024;
928 SiS6326TVDelay(ScrnInfoPtr pScrn
, int delay
)
930 SISPtr pSiS
= SISPTR(pScrn
);
934 for(i
=0; i
<delay
; i
++) {
935 inSISIDXREG(SISSR
, 0x05, temp
);
941 SIS6326DoSense(ScrnInfoPtr pScrn
, int tempbh
, int tempbl
, int tempch
, int tempcl
)
945 SiS6326SetTVReg(pScrn
, 0x42, tempbl
);
946 temp
= SiS6326GetTVReg(pScrn
, 0x43);
949 SiS6326SetTVReg(pScrn
, 0x43, temp
);
950 SiS6326TVDelay(pScrn
, 0x1000);
951 temp
= SiS6326GetTVReg(pScrn
, 0x43);
953 SiS6326SetTVReg(pScrn
, 0x43, temp
);
954 SiS6326TVDelay(pScrn
, 0x8000);
955 temp
= SiS6326GetTVReg(pScrn
, 0x44);
956 if(!(tempch
& temp
)) tempcl
= 0;
961 SISSense6326(ScrnInfoPtr pScrn
)
963 SISPtr pSiS
= SISPTR(pScrn
);
967 pSiS
->SiS6326Flags
&= (SIS6326_HASTV
| SIS6326_TVPAL
);
968 temp
= SiS6326GetTVReg(pScrn
, 0x43);
970 SiS6326SetTVReg(pScrn
, 0x43, temp
);
971 result
= SIS6326DoSense(pScrn
, 0x01, 0xb0, 0x06, SIS6326_TVSVIDEO
); /* 0x02 */
972 pSiS
->SiS6326Flags
|= result
;
973 result
= SIS6326DoSense(pScrn
, 0x01, 0xa0, 0x01, SIS6326_TVCVBS
); /* 0x04 */
974 pSiS
->SiS6326Flags
|= result
;
975 temp
= SiS6326GetTVReg(pScrn
, 0x43);
977 SiS6326SetTVReg(pScrn
, 0x43, temp
);
978 if(pSiS
->SiS6326Flags
& (SIS6326_TVSVIDEO
| SIS6326_TVCVBS
)) {
979 pSiS
->SiS6326Flags
|= SIS6326_TVDETECTED
;
980 xf86DrvMsg(pScrn
->scrnIndex
, X_PROBED
,
981 "SiS6326: Detected TV connected to %s output\n",
982 (((pSiS
->SiS6326Flags
& (SIS6326_TVSVIDEO
| SIS6326_TVCVBS
)) ==
983 (SIS6326_TVSVIDEO
| SIS6326_TVCVBS
)) ?
984 "both SVIDEO and COMPOSITE" :
985 ((pSiS
->SiS6326Flags
& SIS6326_TVSVIDEO
) ?
986 "SVIDEO" : "COMPOSITE")));
988 xf86DrvMsg(pScrn
->scrnIndex
, X_PROBED
,
989 "SiS6326: No TV detected\n");
994 SISIsUMC(SISPtr pSiS
)
996 UShort p4_0f
, p4_25
, p4_27
, temp
;
998 inSISIDXREG(SISPART4
, 0x0f, p4_0f
);
999 inSISIDXREG(SISPART4
, 0x25, p4_25
);
1000 inSISIDXREG(SISPART4
, 0x27, p4_27
);
1001 andSISIDXREG(SISPART4
, 0x0f, 0x7f);
1002 orSISIDXREG(SISPART4
, 0x25, 0x08);
1003 andSISIDXREG(SISPART4
, 0x27, 0xfd);
1004 inSISIDXREG(SISPART4
, 0x26, temp
);
1005 outSISIDXREG(SISPART4
, 0x27, p4_27
);
1006 outSISIDXREG(SISPART4
, 0x25, p4_25
);
1007 outSISIDXREG(SISPART4
, 0x0f, p4_0f
);
1008 return((temp
& 0x08) ? TRUE
: FALSE
);
1011 /* Detect video bridge and set VBFlags accordingly */
1012 void SISVGAPreInit(ScrnInfoPtr pScrn
)
1014 SISPtr pSiS
= SISPTR(pScrn
);
1015 int temp
,temp1
,temp2
,sistypeidx
;
1016 int upperlimitlvds
, lowerlimitlvds
;
1017 int upperlimitch
, lowerlimitch
;
1018 int chronteltype
, chrontelidreg
, upperlimitvb
;
1019 static const char *detectvb
= "Detected SiS%s video bridge (%s, ID %d; Rev 0x%x)\n";
1023 static const char *ChrontelTypeStr
[] = {
1034 static const char *SiSVBTypeStr
[] = {
1045 switch(pSiS
->Chipset
) {
1046 case PCI_CHIP_SIS300
:
1047 case PCI_CHIP_SIS540
:
1048 case PCI_CHIP_SIS630
:
1049 case PCI_CHIP_SIS550
:
1050 case PCI_CHIP_SIS315
:
1051 case PCI_CHIP_SIS315H
:
1052 case PCI_CHIP_SIS315PRO
:
1053 case PCI_CHIP_SIS650
:
1054 case PCI_CHIP_SIS330
:
1055 case PCI_CHIP_SIS660
:
1056 case PCI_CHIP_SIS340
:
1057 pSiS
->ModeInit
= SIS300Init
;
1060 pSiS
->ModeInit
= SISInit
;
1063 if((pSiS
->Chipset
== PCI_CHIP_SIS6326
) && (pSiS
->SiS6326Flags
& SIS6326_HASTV
)) {
1065 inSISIDXREG(SISSR
, 0x0d, sr0d
);
1067 pSiS
->SiS6326Flags
|= SIS6326_TVPAL
;
1069 SISSense6326(pScrn
);
1072 pSiS
->VBFlags
= pSiS
->VBFlags2
= 0; /* reset VBFlags */
1073 pSiS
->SiS_Pr
->SiS_UseLCDA
= FALSE
;
1074 pSiS
->SiS_Pr
->Backup
= FALSE
;
1076 /* Videobridges only available for 300/315/330/340 series */
1077 if((pSiS
->VGAEngine
!= SIS_300_VGA
) && (pSiS
->VGAEngine
!= SIS_315_VGA
))
1080 inSISIDXREG(SISPART4
, 0x00, temp
);
1084 inSISIDXREG(SISPART4
, 0x01, temp1
);
1088 if(SISIsUMC(pSiS
)) pSiS
->VBFlags2
|= VB_SISUMC
;
1092 inSISIDXREG(SISPART4
, 0x39, temp2
);
1094 pSiS
->VBFlags
|= VB_302LV
;
1097 pSiS
->VBFlags
|= VB_301C
; /* VB_302ELV; */
1098 sistypeidx
= 5; /* 6; */
1100 } else if(temp1
>= 0xD0) {
1101 pSiS
->VBFlags
|= VB_301LV
;
1103 } else if(temp1
>= 0xC0) {
1104 pSiS
->VBFlags
|= VB_301C
;
1106 } else if(temp1
>= 0xB0) {
1107 pSiS
->VBFlags
|= VB_301B
;
1109 inSISIDXREG(SISPART4
, 0x23, temp2
);
1110 if(!(temp2
& 0x02)) {
1111 pSiS
->VBFlags
|= VB_30xBDH
;
1115 pSiS
->VBFlags
|= VB_301
;
1119 xf86DrvMsg(pScrn
->scrnIndex
, X_PROBED
, detectvb
, SiSVBTypeStr
[sistypeidx
],
1120 (pSiS
->VBFlags2
& VB_SISUMC
) ? "UMC-0" : "Charter/UMC-1", 1, temp1
);
1122 SISSense30x(pScrn
, FALSE
);
1124 } else if(temp
== 2) {
1126 inSISIDXREG(SISPART4
, 0x01, temp1
);
1130 if(SISIsUMC(pSiS
)) pSiS
->VBFlags2
|= VB_SISUMC
;
1134 pSiS
->VBFlags
|= VB_302LV
;
1136 } else if(temp1
>= 0xD0) {
1137 pSiS
->VBFlags
|= VB_301LV
;
1140 pSiS
->VBFlags
|= VB_302B
;
1144 xf86DrvMsg(pScrn
->scrnIndex
, X_PROBED
, detectvb
, SiSVBTypeStr
[sistypeidx
],
1145 (pSiS
->VBFlags2
& VB_SISUMC
) ? "UMC-0" : "Charter/UMC-1", 2, temp1
);
1147 SISSense30x(pScrn
, FALSE
);
1149 } else if (temp
== 3) {
1151 xf86DrvMsg(pScrn
->scrnIndex
, X_PROBED
, detectvb
, "303", "unsupported, unknown", temp
, 0);
1155 if(pSiS
->NewCRLayout
) {
1156 inSISIDXREG(SISCR
, 0x38, temp
);
1157 temp
= (temp
>> 5) & 0x07;
1159 inSISIDXREG(SISCR
, 0x37, temp
);
1160 temp
= (temp
>> 1) & 0x07;
1162 if(pSiS
->VGAEngine
== SIS_300_VGA
) {
1163 lowerlimitlvds
= 2; upperlimitlvds
= 4;
1164 lowerlimitch
= 4; upperlimitch
= 5;
1165 chronteltype
= 1; chrontelidreg
= 0x25;
1166 upperlimitvb
= upperlimitlvds
;
1168 lowerlimitlvds
= 2; upperlimitlvds
= 3;
1169 lowerlimitch
= 3; upperlimitch
= 3;
1170 chronteltype
= 2; chrontelidreg
= 0x4b;
1171 upperlimitvb
= upperlimitlvds
;
1172 if(pSiS
->NewCRLayout
) {
1177 if((temp
>= lowerlimitlvds
) && (temp
<= upperlimitlvds
)) {
1178 pSiS
->VBFlags
|= VB_LVDS
;
1179 xf86DrvMsg(pScrn
->scrnIndex
, X_PROBED
,
1180 "Detected LVDS transmitter (External chip ID %d)\n", temp
);
1182 if((temp
>= lowerlimitch
) && (temp
<= upperlimitch
)) {
1183 /* Set global for init301.c */
1184 pSiS
->SiS_Pr
->SiS_IF_DEF_CH70xx
= chronteltype
;
1186 if(chronteltype
== 1) {
1187 /* Set general purpose IO for Chrontel communication */
1188 SiS_SetChrontelGPIO(pSiS
->SiS_Pr
, 0x9c);
1191 /* Read Chrontel version number */
1192 temp1
= SiS_GetCH70xx(pSiS
->SiS_Pr
, chrontelidreg
);
1193 if(chronteltype
== 1) {
1194 /* See Chrontel TB31 for explanation */
1195 temp2
= SiS_GetCH700x(pSiS
->SiS_Pr
, 0x0e);
1196 if(((temp2
& 0x07) == 0x01) || (temp2
& 0x04)) {
1197 SiS_SetCH700x(pSiS
->SiS_Pr
, 0x0b0e);
1198 SiS_DDC2Delay(pSiS
->SiS_Pr
, 300);
1200 temp2
= SiS_GetCH70xx(pSiS
->SiS_Pr
, chrontelidreg
);
1201 if(temp2
!= temp1
) temp1
= temp2
;
1203 if(temp1
== 0xFFFF) { /* 0xFFFF = error reading DDC port */
1204 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
1205 "Detected Chrontel 70xx, but encountered error reading I2C port\n");
1206 andSISIDXREG(SISCR
, 0x32, ~0x07);
1207 pSiS
->postVBCR32
&= ~0x07;
1208 } else if((temp1
>= 0x19) && (temp1
<= 200)) {
1209 /* We only support device ids 0x19-200; other values may indicate DDC problems */
1210 pSiS
->VBFlags
|= VB_CHRONTEL
;
1212 case 0x32: temp2
= 0; pSiS
->ChrontelType
= CHRONTEL_700x
; break;
1213 case 0x3A: temp2
= 1; pSiS
->ChrontelType
= CHRONTEL_700x
; break;
1214 case 0x50: temp2
= 2; pSiS
->ChrontelType
= CHRONTEL_700x
; break;
1215 case 0x2A: temp2
= 3; pSiS
->ChrontelType
= CHRONTEL_700x
; break;
1216 case 0x40: temp2
= 4; pSiS
->ChrontelType
= CHRONTEL_700x
; break;
1217 case 0x22: temp2
= 5; pSiS
->ChrontelType
= CHRONTEL_700x
; break;
1218 case 0x19: temp2
= 6; pSiS
->ChrontelType
= CHRONTEL_701x
; break;
1219 case 0x20: temp2
= 7; pSiS
->ChrontelType
= CHRONTEL_701x
; break; /* ID for 7020? */
1220 default: temp2
= 8; pSiS
->ChrontelType
= CHRONTEL_701x
; break;
1222 xf86DrvMsg(pScrn
->scrnIndex
, X_PROBED
,
1223 "Detected Chrontel %s TV encoder (ID 0x%02x; chip ID %d)\n",
1224 ChrontelTypeStr
[temp2
], temp1
, temp
);
1226 /* Sense connected TV's */
1227 SISSenseChrontel(pScrn
, FALSE
);
1229 } else if(temp1
== 0) {
1230 /* This indicates a communication problem, but it only occures if there
1231 * is no TV attached. So we don't use TV in this case.
1233 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
1234 "Detected Chrontel TV encoder in promiscuous state (DDC/I2C mix-up)\n");
1235 andSISIDXREG(SISCR
, 0x32, ~0x07);
1236 pSiS
->postVBCR32
&= ~0x07;
1238 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
1239 "Chrontel: Unsupported device id (%d) detected\n",temp1
);
1240 andSISIDXREG(SISCR
, 0x32, ~0x07);
1241 pSiS
->postVBCR32
&= ~0x07;
1243 if(chronteltype
== 1) {
1244 /* Set general purpose IO for Chrontel communication */
1245 SiS_SetChrontelGPIO(pSiS
->SiS_Pr
, 0x00);
1248 if((pSiS
->NewCRLayout
) && (temp
== 4)) {
1249 pSiS
->VBFlags
|= VB_CONEXANT
;
1250 xf86DrvMsg(pScrn
->scrnIndex
, X_PROBED
,
1251 "Detected Conexant video bridge - UNSUPPORTED\n");
1253 if((pSiS
->VGAEngine
== SIS_300_VGA
) && (temp
== 3)) {
1254 pSiS
->VBFlags
|= VB_TRUMPION
;
1255 xf86DrvMsg(pScrn
->scrnIndex
, X_PROBED
,
1256 "Detected Trumpion Zurac (I/II/III) LVDS scaler\n");
1258 if(temp
> upperlimitvb
) {
1259 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
1260 "Detected unknown bridge type (%d)\n", temp
);
1264 /* Old BIOSes store the detected CRT2 type in SR17, 16 and 13
1265 * instead of CR32. However, since our detection routines
1266 * store their results to CR32, we now copy the
1267 * remaining bits (for LCD and VGA) to CR32 for unified usage.
1268 * SR17[0] CRT1 [1] LCD [2] TV [3] VGA2
1269 * [4] AVIDEO [5] SVIDEO
1270 * SR13[0] SCART [1] HiVision
1271 * SR16[5] PAL/NTSC [6] LCD-SCALE [7] OVERSCAN
1275 inSISIDXREG(SISSR
, 0x17, sr17
);
1276 if( (pSiS
->VGAEngine
== SIS_300_VGA
) &&
1277 (pSiS
->Chipset
!= PCI_CHIP_SIS300
) &&
1281 inSISIDXREG(SISCR
, 0x32, cr32
);
1283 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
1284 "Converting SR17 (%02x) to CR32 (%02x)\n", sr17
, cr32
);
1286 if(sr17
& 0x01) { /* CRT1 */
1287 orSISIDXREG(SISCR
, 0x32, 0x20);
1288 pSiS
->postVBCR32
|= 0x20;
1290 andSISIDXREG(SISCR
, 0x32, ~0x20);
1291 pSiS
->postVBCR32
&= ~0x20;
1294 if(sr17
& 0x02) { /* LCD */
1295 orSISIDXREG(SISCR
, 0x32, 0x08);
1296 pSiS
->postVBCR32
|= 0x08;
1298 andSISIDXREG(SISCR
, 0x32, ~0x08);
1299 pSiS
->postVBCR32
&= ~0x08;
1302 /* No Hivision, no DVI here */
1303 andSISIDXREG(SISCR
,0x32,~0xc0);
1304 pSiS
->postVBCR32
&= ~0xc0;
1308 /* Try to find out if the bridge uses LCDA for low resolution and
1309 * text modes. If sisfb saved this for us, use it. Otherwise,
1310 * check if we are running on a low mode on LCD and read the
1311 * relevant registers ourselves.
1313 if(pSiS
->VGAEngine
== SIS_315_VGA
) {
1315 if(pSiS
->VBFlags
& (VB_301C
| VB_302B
| VB_301LV
| VB_302LV
| VB_302ELV
)) {
1316 if(pSiS
->sisfblcda
!= 0xff) {
1317 if((pSiS
->sisfblcda
& 0x03) == 0x03) {
1318 pSiS
->SiS_Pr
->SiS_UseLCDA
= TRUE
;
1319 pSiS
->ChipFlags
|= SiSCF_UseLCDA
;
1322 inSISIDXREG(SISCR
,0x34,temp
);
1324 inSISIDXREG(SISCR
,0x38,temp
);
1325 if((temp
& 0x03) == 0x03) {
1326 pSiS
->SiS_Pr
->SiS_UseLCDA
= TRUE
;
1327 pSiS
->ChipFlags
|= SiSCF_UseLCDA
;
1328 pSiS
->SiS_Pr
->Backup
= TRUE
;
1330 orSISIDXREG(SISPART1
,0x2f,0x01); /* Unlock CRT2 */
1331 inSISIDXREG(SISPART1
,0x13,temp
);
1333 pSiS
->SiS_Pr
->SiS_UseLCDA
= TRUE
;
1334 pSiS
->ChipFlags
|= SiSCF_UseLCDA
;
1335 pSiS
->SiS_Pr
->Backup
= TRUE
;
1340 if(pSiS
->ChipFlags
& SiSCF_UseLCDA
) {
1341 xf86DrvMsgVerb(pScrn
->scrnIndex
, X_PROBED
, 3,
1342 "BIOS uses LCDA for low resolution and text modes\n");
1343 if(pSiS
->SiS_Pr
->Backup
== TRUE
) {
1344 inSISIDXREG(SISCR
,0x34,pSiS
->SiS_Pr
->Backup_Mode
);
1345 inSISIDXREG(SISPART1
,0x14,pSiS
->SiS_Pr
->Backup_14
);
1346 inSISIDXREG(SISPART1
,0x15,pSiS
->SiS_Pr
->Backup_15
);
1347 inSISIDXREG(SISPART1
,0x16,pSiS
->SiS_Pr
->Backup_16
);
1348 inSISIDXREG(SISPART1
,0x17,pSiS
->SiS_Pr
->Backup_17
);
1349 inSISIDXREG(SISPART1
,0x18,pSiS
->SiS_Pr
->Backup_18
);
1350 inSISIDXREG(SISPART1
,0x19,pSiS
->SiS_Pr
->Backup_19
);
1351 inSISIDXREG(SISPART1
,0x1a,pSiS
->SiS_Pr
->Backup_1a
);
1352 inSISIDXREG(SISPART1
,0x1b,pSiS
->SiS_Pr
->Backup_1b
);
1353 inSISIDXREG(SISPART1
,0x1c,pSiS
->SiS_Pr
->Backup_1c
);
1354 inSISIDXREG(SISPART1
,0x1d,pSiS
->SiS_Pr
->Backup_1d
);
1362 SiS_WriteAttr(SISPtr pSiS
, int index
, int value
)
1364 (void)inSISREG(SISINPSTAT
);
1366 outSISREG(SISAR
, index
);
1367 outSISREG(SISAR
, value
);
1371 SiS_ReadAttr(SISPtr pSiS
, int index
)
1373 (void)inSISREG(SISINPSTAT
);
1375 outSISREG(SISAR
, index
);
1376 return(inSISREG(SISARR
));
1380 SiS_EnablePalette(SISPtr pSiS
)
1382 (void)inSISREG(SISINPSTAT
);
1383 outSISREG(SISAR
, 0x00);
1384 pSiS
->VGAPaletteEnabled
= TRUE
;
1388 SiS_DisablePalette(SISPtr pSiS
)
1390 (void)inSISREG(SISINPSTAT
);
1391 outSISREG(SISAR
, 0x20);
1392 pSiS
->VGAPaletteEnabled
= FALSE
;
1396 SISVGALock(SISPtr pSiS
)
1398 orSISIDXREG(SISCR
, 0x11, 0x80); /* Protect CRTC[0-7] */
1402 SiSVGAUnlock(SISPtr pSiS
)
1404 andSISIDXREG(SISCR
, 0x11, 0x7f); /* Unprotect CRTC[0-7] */
1407 #define SIS_FONTS_SIZE (8 * 8192)
1410 SiSVGASaveFonts(ScrnInfoPtr pScrn
)
1412 #ifdef SIS_PC_PLATFORM
1413 SISPtr pSiS
= SISPTR(pScrn
);
1414 pointer vgaMemBase
= pSiS
->VGAMemBase
;
1415 UChar miscOut
, attr10
, gr4
, gr5
, gr6
, seq2
, seq4
, scrn
;
1417 if((pSiS
->fonts
) || (vgaMemBase
== NULL
)) return;
1419 /* If in graphics mode, don't save anything */
1420 attr10
= SiS_ReadAttr(pSiS
, 0x10);
1421 if(attr10
& 0x01) return;
1423 if(!(pSiS
->fonts
= xalloc(SIS_FONTS_SIZE
* 2))) {
1424 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
1425 "Could not save console fonts, mem allocation failed\n");
1429 /* save the registers that are needed here */
1430 miscOut
= inSISREG(SISMISCR
);
1431 inSISIDXREG(SISGR
, 0x04, gr4
);
1432 inSISIDXREG(SISGR
, 0x05, gr5
);
1433 inSISIDXREG(SISGR
, 0x06, gr6
);
1434 inSISIDXREG(SISSR
, 0x02, seq2
);
1435 inSISIDXREG(SISSR
, 0x04, seq4
);
1437 /* Force into color mode */
1438 outSISREG(SISMISCW
, miscOut
| 0x01);
1440 inSISIDXREG(SISSR
, 0x01, scrn
);
1441 outSISIDXREG(SISSR
, 0x00, 0x01);
1442 outSISIDXREG(SISSR
, 0x01, scrn
| 0x20);
1443 outSISIDXREG(SISSR
, 0x00, 0x03);
1445 SiS_WriteAttr(pSiS
, 0x10, 0x01); /* graphics mode */
1448 outSISIDXREG(SISSR
, 0x02, 0x04); /* write to plane 2 */
1449 outSISIDXREG(SISSR
, 0x04, 0x06); /* enable plane graphics */
1450 outSISIDXREG(SISGR
, 0x04, 0x02); /* read plane 2 */
1451 outSISIDXREG(SISGR
, 0x05, 0x00); /* write mode 0, read mode 0 */
1452 outSISIDXREG(SISGR
, 0x06, 0x05); /* set graphics */
1453 slowbcopy_frombus(vgaMemBase
, pSiS
->fonts
, SIS_FONTS_SIZE
);
1456 outSISIDXREG(SISSR
, 0x02, 0x08); /* write to plane 3 */
1457 outSISIDXREG(SISSR
, 0x04, 0x06); /* enable plane graphics */
1458 outSISIDXREG(SISGR
, 0x04, 0x03); /* read plane 3 */
1459 outSISIDXREG(SISGR
, 0x05, 0x00); /* write mode 0, read mode 0 */
1460 outSISIDXREG(SISGR
, 0x06, 0x05); /* set graphics */
1461 slowbcopy_frombus(vgaMemBase
, pSiS
->fonts
+ SIS_FONTS_SIZE
, SIS_FONTS_SIZE
);
1463 inSISIDXREG(SISSR
, 0x01, scrn
);
1464 outSISIDXREG(SISSR
, 0x00, 0x01);
1465 outSISIDXREG(SISSR
, 0x01, scrn
& ~0x20);
1466 outSISIDXREG(SISSR
, 0x00, 0x03);
1468 /* Restore clobbered registers */
1469 SiS_WriteAttr(pSiS
, 0x10, attr10
);
1470 outSISIDXREG(SISSR
, 0x02, seq2
);
1471 outSISIDXREG(SISSR
, 0x04, seq4
);
1472 outSISIDXREG(SISGR
, 0x04, gr4
);
1473 outSISIDXREG(SISGR
, 0x05, gr5
);
1474 outSISIDXREG(SISGR
, 0x06, gr6
);
1475 outSISREG(SISMISCW
, miscOut
);
1480 SiSVGASaveMode(ScrnInfoPtr pScrn
, SISRegPtr save
)
1482 SISPtr pSiS
= SISPTR(pScrn
);
1485 save
->sisRegMiscOut
= inSISREG(SISMISCR
);
1487 for(i
= 0; i
< 25; i
++) {
1488 inSISIDXREG(SISCR
, i
, save
->sisRegs3D4
[i
]);
1491 SiS_EnablePalette(pSiS
);
1492 for(i
= 0; i
< 21; i
++) {
1493 save
->sisRegsATTR
[i
] = SiS_ReadAttr(pSiS
, i
);
1495 SiS_DisablePalette(pSiS
);
1497 for(i
= 0; i
< 9; i
++) {
1498 inSISIDXREG(SISGR
, i
, save
->sisRegsGR
[i
]);
1501 for(i
= 1; i
< 5; i
++) {
1502 inSISIDXREG(SISSR
, i
, save
->sisRegs3C4
[i
]);
1507 SiSVGASaveColormap(ScrnInfoPtr pScrn
, SISRegPtr save
)
1509 SISPtr pSiS
= SISPTR(pScrn
);
1512 if(pSiS
->VGACMapSaved
) return;
1514 outSISREG(SISPEL
, 0xff);
1516 outSISREG(SISCOLIDXR
, 0x00);
1517 for(i
= 0; i
< 768; i
++) {
1518 save
->sisDAC
[i
] = inSISREG(SISCOLDATA
);
1519 (void)inSISREG(SISINPSTAT
);
1520 (void)inSISREG(SISINPSTAT
);
1523 SiS_DisablePalette(pSiS
);
1524 pSiS
->VGACMapSaved
= TRUE
;
1528 SiSVGASave(ScrnInfoPtr pScrn
, SISRegPtr save
, int flags
)
1530 if(save
== NULL
) return;
1532 if(flags
& SISVGA_SR_CMAP
) SiSVGASaveColormap(pScrn
, save
);
1533 if(flags
& SISVGA_SR_MODE
) SiSVGASaveMode(pScrn
, save
);
1534 if(flags
& SISVGA_SR_FONTS
) SiSVGASaveFonts(pScrn
);
1538 SiSVGARestoreFonts(ScrnInfoPtr pScrn
)
1540 #ifdef SIS_PC_PLATFORM
1541 SISPtr pSiS
= SISPTR(pScrn
);
1542 pointer vgaMemBase
= pSiS
->VGAMemBase
;
1543 UChar miscOut
, attr10
, gr1
, gr3
, gr4
, gr5
, gr6
, gr8
, seq2
, seq4
, scrn
;
1545 if((!pSiS
->fonts
) || (vgaMemBase
== NULL
)) return;
1547 /* save the registers that are needed here */
1548 miscOut
= inSISREG(SISMISCR
);
1549 attr10
= SiS_ReadAttr(pSiS
, 0x10);
1550 inSISIDXREG(SISGR
, 0x01, gr1
);
1551 inSISIDXREG(SISGR
, 0x03, gr3
);
1552 inSISIDXREG(SISGR
, 0x04, gr4
);
1553 inSISIDXREG(SISGR
, 0x05, gr5
);
1554 inSISIDXREG(SISGR
, 0x06, gr6
);
1555 inSISIDXREG(SISGR
, 0x08, gr8
);
1556 inSISIDXREG(SISSR
, 0x02, seq2
);
1557 inSISIDXREG(SISSR
, 0x04, seq4
);
1559 /* Force into color mode */
1560 outSISREG(SISMISCW
, miscOut
| 0x01);
1561 inSISIDXREG(SISSR
, 0x01, scrn
);
1562 outSISIDXREG(SISSR
, 0x00, 0x01);
1563 outSISIDXREG(SISSR
, 0x01, scrn
| 0x20);
1564 outSISIDXREG(SISSR
, 0x00, 0x03);
1566 SiS_WriteAttr(pSiS
, 0x10, 0x01); /* graphics mode */
1567 if(pScrn
->depth
== 4) {
1568 outSISIDXREG(SISGR
, 0x03, 0x00); /* don't rotate, write unmodified */
1569 outSISIDXREG(SISGR
, 0x08, 0xFF); /* write all bits in a byte */
1570 outSISIDXREG(SISGR
, 0x01, 0x00); /* all planes come from CPU */
1573 outSISIDXREG(SISSR
, 0x02, 0x04); /* write to plane 2 */
1574 outSISIDXREG(SISSR
, 0x04, 0x06); /* enable plane graphics */
1575 outSISIDXREG(SISGR
, 0x04, 0x02); /* read plane 2 */
1576 outSISIDXREG(SISGR
, 0x05, 0x00); /* write mode 0, read mode 0 */
1577 outSISIDXREG(SISGR
, 0x06, 0x05); /* set graphics */
1578 slowbcopy_tobus(pSiS
->fonts
, vgaMemBase
, SIS_FONTS_SIZE
);
1580 outSISIDXREG(SISSR
, 0x02, 0x08); /* write to plane 3 */
1581 outSISIDXREG(SISSR
, 0x04, 0x06); /* enable plane graphics */
1582 outSISIDXREG(SISGR
, 0x04, 0x03); /* read plane 3 */
1583 outSISIDXREG(SISGR
, 0x05, 0x00); /* write mode 0, read mode 0 */
1584 outSISIDXREG(SISGR
, 0x06, 0x05); /* set graphics */
1585 slowbcopy_tobus(pSiS
->fonts
+ SIS_FONTS_SIZE
, vgaMemBase
, SIS_FONTS_SIZE
);
1587 inSISIDXREG(SISSR
, 0x01, scrn
);
1588 outSISIDXREG(SISSR
, 0x00, 0x01);
1589 outSISIDXREG(SISSR
, 0x01, scrn
& ~0x20);
1590 outSISIDXREG(SISSR
, 0x00, 0x03);
1592 /* restore the registers that were changed */
1593 outSISREG(SISMISCW
, miscOut
);
1594 SiS_WriteAttr(pSiS
, 0x10, attr10
);
1595 outSISIDXREG(SISGR
, 0x01, gr1
);
1596 outSISIDXREG(SISGR
, 0x03, gr3
);
1597 outSISIDXREG(SISGR
, 0x04, gr4
);
1598 outSISIDXREG(SISGR
, 0x05, gr5
);
1599 outSISIDXREG(SISGR
, 0x06, gr6
);
1600 outSISIDXREG(SISGR
, 0x08, gr8
);
1601 outSISIDXREG(SISSR
, 0x02, seq2
);
1602 outSISIDXREG(SISSR
, 0x04, seq4
);
1607 SiSVGARestoreMode(ScrnInfoPtr pScrn
, SISRegPtr restore
)
1609 SISPtr pSiS
= SISPTR(pScrn
);
1612 outSISREG(SISMISCW
, restore
->sisRegMiscOut
);
1614 for(i
= 1; i
< 5; i
++) {
1615 outSISIDXREG(SISSR
, i
, restore
->sisRegs3C4
[i
]);
1618 outSISIDXREG(SISCR
, 17, restore
->sisRegs3D4
[17] & ~0x80);
1620 for(i
= 0; i
< 25; i
++) {
1621 outSISIDXREG(SISCR
, i
, restore
->sisRegs3D4
[i
]);
1624 for(i
= 0; i
< 9; i
++) {
1625 outSISIDXREG(SISGR
, i
, restore
->sisRegsGR
[i
]);
1628 SiS_EnablePalette(pSiS
);
1629 for(i
= 0; i
< 21; i
++) {
1630 SiS_WriteAttr(pSiS
, i
, restore
->sisRegsATTR
[i
]);
1632 SiS_DisablePalette(pSiS
);
1637 SiSVGARestoreColormap(ScrnInfoPtr pScrn
, SISRegPtr restore
)
1639 SISPtr pSiS
= SISPTR(pScrn
);
1642 if(!pSiS
->VGACMapSaved
) return;
1644 outSISREG(SISPEL
, 0xff);
1646 outSISREG(SISCOLIDX
, 0x00);
1647 for(i
= 0; i
< 768; i
++) {
1648 outSISREG(SISCOLDATA
, restore
->sisDAC
[i
]);
1649 (void)inSISREG(SISINPSTAT
);
1650 (void)inSISREG(SISINPSTAT
);
1653 SiS_DisablePalette(pSiS
);
1657 SiSVGARestore(ScrnInfoPtr pScrn
, SISRegPtr restore
, int flags
)
1659 if(restore
== NULL
) return;
1661 if(flags
& SISVGA_SR_MODE
) SiSVGARestoreMode(pScrn
, restore
);
1662 if(flags
& SISVGA_SR_FONTS
) SiSVGARestoreFonts(pScrn
);
1663 if(flags
& SISVGA_SR_CMAP
) SiSVGARestoreColormap(pScrn
, restore
);
1667 SiS_SeqReset(SISPtr pSiS
, Bool start
)
1670 outSISIDXREG(SISSR
, 0x00, 0x01); /* Synchronous Reset */
1672 outSISIDXREG(SISSR
, 0x00, 0x03); /* End Reset */
1677 SiSVGAProtect(ScrnInfoPtr pScrn
, Bool on
)
1679 SISPtr pSiS
= SISPTR(pScrn
);
1682 if(!pScrn
->vtSema
) return;
1685 inSISIDXREG(SISSR
, 0x01, tmp
);
1686 SiS_SeqReset(pSiS
, TRUE
); /* start synchronous reset */
1687 outSISIDXREG(SISSR
, 0x01, tmp
| 0x20); /* disable display */
1688 SiS_EnablePalette(pSiS
);
1690 andSISIDXREG(SISSR
, 0x01, ~0x20); /* enable display */
1691 SiS_SeqReset(pSiS
, FALSE
); /* clear synchronous reset */
1692 SiS_DisablePalette(pSiS
);
1696 #ifdef SIS_PC_PLATFORM
1698 SiSVGAMapMem(ScrnInfoPtr pScrn
)
1700 SISPtr pSiS
= SISPTR(pScrn
);
1703 if(pSiS
->VGAMemBase
) return TRUE
;
1705 if(pSiS
->VGAMapSize
== 0) pSiS
->VGAMapSize
= (64 * 1024);
1706 if(pSiS
->VGAMapPhys
== 0) pSiS
->VGAMapPhys
= 0xA0000;
1708 #if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0)
1709 pSiS
->VGAMemBase
= xf86MapDomainMemory(pScrn
->scrnIndex
, VIDMEM_MMIO_32BIT
,
1710 pSiS
->PciTag
, pSiS
->VGAMapPhys
, pSiS
->VGAMapSize
);
1712 pSiS
->VGAMemBase
= xf86MapVidMem(pScrn
->scrnIndex
, VIDMEM_MMIO_32BIT
,
1713 pSiS
->VGAMapPhys
, pSiS
->VGAMapSize
);
1716 return(pSiS
->VGAMemBase
!= NULL
);
1720 SiSVGAUnmapMem(ScrnInfoPtr pScrn
)
1722 SISPtr pSiS
= SISPTR(pScrn
);
1724 if(pSiS
->VGAMemBase
== NULL
) return;
1726 xf86UnMapVidMem(pScrn
->scrnIndex
, pSiS
->VGAMemBase
, pSiS
->VGAMapSize
);
1727 pSiS
->VGAMemBase
= NULL
;
1733 SiS_HBlankKGA(DisplayModePtr mode
, SISRegPtr regp
, int nBits
, unsigned int Flags
)
1735 int nExtBits
= (nBits
< 6) ? 0 : nBits
- 6;
1737 CARD32 ExtBitMask
= ((1 << nExtBits
) - 1) << 6;
1739 regp
->sisRegs3D4
[3] = (regp
->sisRegs3D4
[3] & ~0x1F) |
1740 (((mode
->CrtcHBlankEnd
>> 3) - 1) & 0x1F);
1741 regp
->sisRegs3D4
[5] = (regp
->sisRegs3D4
[5] & ~0x80) |
1742 ((((mode
->CrtcHBlankEnd
>> 3) - 1) & 0x20) << 2);
1743 ExtBits
= ((mode
->CrtcHBlankEnd
>> 3) - 1) & ExtBitMask
;
1745 if( (Flags
& SISKGA_FIX_OVERSCAN
) &&
1746 ((mode
->CrtcHBlankEnd
>> 3) == (mode
->CrtcHTotal
>> 3))) {
1747 int i
= (regp
->sisRegs3D4
[3] & 0x1F) |
1748 ((regp
->sisRegs3D4
[5] & 0x80) >> 2) |
1750 if(Flags
& SISKGA_ENABLE_ON_ZERO
) {
1751 if( (i
-- > (((mode
->CrtcHBlankStart
>> 3) - 1) & (0x3F | ExtBitMask
))) &&
1752 (mode
->CrtcHBlankEnd
== mode
->CrtcHTotal
) ) {
1755 } else if (Flags
& SISKGA_BE_TOT_DEC
) i
--;
1756 regp
->sisRegs3D4
[3] = (regp
->sisRegs3D4
[3] & ~0x1F) | (i
& 0x1F);
1757 regp
->sisRegs3D4
[5] = (regp
->sisRegs3D4
[5] & ~0x80) | ((i
<< 2) & 0x80);
1758 ExtBits
= i
& ExtBitMask
;
1760 return ExtBits
>> 6;
1765 SiS_VBlankKGA(DisplayModePtr mode
, SISRegPtr regp
, int nBits
, unsigned int Flags
)
1767 CARD32 nExtBits
= (nBits
< 8) ? 0 : (nBits
- 8);
1768 CARD32 ExtBitMask
= ((1 << nExtBits
) - 1) << 8;
1769 CARD32 ExtBits
= (mode
->CrtcVBlankEnd
- 1) & ExtBitMask
;
1770 CARD32 BitMask
= (nBits
< 7) ? 0 : ((1 << nExtBits
) - 1);
1771 int VBlankStart
= (mode
->CrtcVBlankStart
- 1) & 0xFF;
1772 regp
->sisRegs3D4
[22] = (mode
->CrtcVBlankEnd
- 1) & 0xFF;
1774 if((Flags
& SISKGA_FIX_OVERSCAN
) && (mode
->CrtcVBlankEnd
== mode
->CrtcVTotal
)) {
1775 int i
= regp
->sisRegs3D4
[22] | ExtBits
;
1776 if(Flags
& SISKGA_ENABLE_ON_ZERO
) {
1777 if( ((BitMask
&& ((i
& BitMask
) > (VBlankStart
& BitMask
))) ||
1778 ((i
> VBlankStart
) && /* 8-bit case */
1779 ((i
& 0x7F) > (VBlankStart
& 0x7F)))) && /* 7-bit case */
1780 (!(regp
->sisRegs3D4
[9] & 0x9F)) ) { /* 1 scanline/row */
1785 } else if(Flags
& SISKGA_BE_TOT_DEC
) i
--;
1787 regp
->sisRegs3D4
[22] = i
& 0xFF;
1788 ExtBits
= i
& 0xFF00;
1790 return (ExtBits
>> 8);
1794 SiSVGAInit(ScrnInfoPtr pScrn
, DisplayModePtr mode
, int fixsync
)
1796 SISPtr pSiS
= SISPTR(pScrn
);
1797 SISRegPtr regp
= &pSiS
->ModeReg
;
1798 int depth
= pScrn
->depth
;
1802 if((mode
->Flags
& (V_PHSYNC
| V_NHSYNC
)) && (mode
->Flags
& (V_PVSYNC
| V_NVSYNC
))) {
1803 regp
->sisRegMiscOut
= 0x23;
1804 if(mode
->Flags
& V_NHSYNC
) regp
->sisRegMiscOut
|= 0x40;
1805 if(mode
->Flags
& V_NVSYNC
) regp
->sisRegMiscOut
|= 0x80;
1807 int VDisplay
= mode
->VDisplay
;
1809 if(mode
->Flags
& V_DBLSCAN
) VDisplay
*= 2;
1810 if(mode
->VScan
> 1) VDisplay
*= mode
->VScan
;
1812 if(VDisplay
< 400) regp
->sisRegMiscOut
= 0xA3; /* +hsync -vsync */
1813 else if (VDisplay
< 480) regp
->sisRegMiscOut
= 0x63; /* -hsync +vsync */
1814 else if (VDisplay
< 768) regp
->sisRegMiscOut
= 0xE3; /* -hsync -vsync */
1815 else regp
->sisRegMiscOut
= 0x23; /* +hsync +vsync */
1818 regp
->sisRegMiscOut
|= (mode
->ClockIndex
& 0x03) << 2;
1821 if(depth
== 4) regp
->sisRegs3C4
[0] = 0x02;
1822 else regp
->sisRegs3C4
[0] = 0x00;
1824 if(mode
->Flags
& V_CLKDIV2
) regp
->sisRegs3C4
[1] = 0x09;
1825 else regp
->sisRegs3C4
[1] = 0x01;
1827 regp
->sisRegs3C4
[2] = 0x0F;
1829 regp
->sisRegs3C4
[3] = 0x00;
1831 if(depth
< 8) regp
->sisRegs3C4
[4] = 0x06;
1832 else regp
->sisRegs3C4
[4] = 0x0E;
1835 regp
->sisRegs3D4
[0] = (mode
->CrtcHTotal
>> 3) - 5;
1836 regp
->sisRegs3D4
[1] = (mode
->CrtcHDisplay
>> 3) - 1;
1837 regp
->sisRegs3D4
[2] = (mode
->CrtcHBlankStart
>> 3) - 1;
1838 regp
->sisRegs3D4
[3] = (((mode
->CrtcHBlankEnd
>> 3) - 1) & 0x1F) | 0x80;
1839 i
= (((mode
->CrtcHSkew
<< 2) + 0x10) & ~0x1F);
1840 if(i
< 0x80) regp
->sisRegs3D4
[3] |= i
;
1841 regp
->sisRegs3D4
[4] = (mode
->CrtcHSyncStart
>> 3) - fixsync
;
1842 regp
->sisRegs3D4
[5] = ((((mode
->CrtcHBlankEnd
>> 3) - 1) & 0x20) << 2) |
1843 (((mode
->CrtcHSyncEnd
>> 3) - fixsync
) & 0x1F);
1844 regp
->sisRegs3D4
[6] = (mode
->CrtcVTotal
- 2) & 0xFF;
1845 regp
->sisRegs3D4
[7] = (((mode
->CrtcVTotal
- 2) & 0x100) >> 8) |
1846 (((mode
->CrtcVDisplay
- 1) & 0x100) >> 7) |
1847 (((mode
->CrtcVSyncStart
- fixsync
) & 0x100) >> 6) |
1848 (((mode
->CrtcVBlankStart
- 1) & 0x100) >> 5) |
1850 (((mode
->CrtcVTotal
- 2) & 0x200) >> 4) |
1851 (((mode
->CrtcVDisplay
- 1) & 0x200) >> 3) |
1852 (((mode
->CrtcVSyncStart
- fixsync
) & 0x200) >> 2);
1853 regp
->sisRegs3D4
[8] = 0x00;
1854 regp
->sisRegs3D4
[9] = (((mode
->CrtcVBlankStart
- 1) & 0x200) >> 4) | 0x40;
1855 if(mode
->Flags
& V_DBLSCAN
) regp
->sisRegs3D4
[9] |= 0x80;
1856 if(mode
->VScan
>= 32) regp
->sisRegs3D4
[9] |= 0x1F;
1857 else if (mode
->VScan
> 1) regp
->sisRegs3D4
[9] |= mode
->VScan
- 1;
1858 regp
->sisRegs3D4
[10] = 0x00;
1859 regp
->sisRegs3D4
[11] = 0x00;
1860 regp
->sisRegs3D4
[12] = 0x00;
1861 regp
->sisRegs3D4
[13] = 0x00;
1862 regp
->sisRegs3D4
[14] = 0x00;
1863 regp
->sisRegs3D4
[15] = 0x00;
1864 regp
->sisRegs3D4
[16] = (mode
->CrtcVSyncStart
- fixsync
) & 0xFF;
1865 regp
->sisRegs3D4
[17] = ((mode
->CrtcVSyncEnd
- fixsync
) & 0x0F) | 0x20;
1866 regp
->sisRegs3D4
[18] = (mode
->CrtcVDisplay
- 1) & 0xFF;
1867 regp
->sisRegs3D4
[19] = pScrn
->displayWidth
>> 4;
1868 regp
->sisRegs3D4
[20] = 0x00;
1869 regp
->sisRegs3D4
[21] = (mode
->CrtcVBlankStart
- 1) & 0xFF;
1870 regp
->sisRegs3D4
[22] = (mode
->CrtcVBlankEnd
- 1) & 0xFF;
1871 if(depth
< 8) regp
->sisRegs3D4
[23] = 0xE3;
1872 else regp
->sisRegs3D4
[23] = 0xC3;
1873 regp
->sisRegs3D4
[24] = 0xFF;
1876 SiS_HBlankKGA(mode
, regp
, 0, SISKGA_FIX_OVERSCAN
| SISKGA_ENABLE_ON_ZERO
);
1878 SiS_VBlankKGA(mode
, regp
, 0, SISKGA_FIX_OVERSCAN
| SISKGA_ENABLE_ON_ZERO
);
1881 regp
->sisRegsGR
[0] = 0x00;
1882 regp
->sisRegsGR
[1] = 0x00;
1883 regp
->sisRegsGR
[2] = 0x00;
1884 regp
->sisRegsGR
[3] = 0x00;
1885 regp
->sisRegsGR
[4] = 0x00;
1886 if(depth
== 4) regp
->sisRegsGR
[5] = 0x02;
1887 else regp
->sisRegsGR
[5] = 0x40;
1888 regp
->sisRegsGR
[6] = 0x05; /* only map 64k VGA memory !!!! */
1889 regp
->sisRegsGR
[7] = 0x0F;
1890 regp
->sisRegsGR
[8] = 0xFF;
1893 for(i
= 0; i
<= 15; i
++) { /* standard colormap translation */
1894 regp
->sisRegsATTR
[i
] = i
;
1896 if(depth
== 4) regp
->sisRegsATTR
[16] = 0x81;
1897 else regp
->sisRegsATTR
[16] = 0x41;
1898 if(depth
>= 4) regp
->sisRegsATTR
[17] = 0xFF;
1899 else regp
->sisRegsATTR
[17] = 0x01;
1900 regp
->sisRegsATTR
[18] = 0x0F;
1901 regp
->sisRegsATTR
[19] = 0x00;
1902 regp
->sisRegsATTR
[20] = 0x00;
1908 SISVGABlankScreen(ScrnInfoPtr pScrn
, Bool on
)
1910 SISPtr pSiS
= SISPTR(pScrn
);
1913 inSISIDXREG(SISSR
, 0x01, tmp
);
1914 if(on
) tmp
&= ~0x20;
1916 SiS_SeqReset(pSiS
, TRUE
);
1917 outSISIDXREG(SISSR
, 0x01, tmp
);
1918 SiS_SeqReset(pSiS
, FALSE
);
1922 SiSVGASaveScreen(ScreenPtr pScreen
, int mode
)
1924 ScrnInfoPtr pScrn
= NULL
;
1925 Bool on
= xf86IsUnblank(mode
);
1927 if(pScreen
== NULL
) return FALSE
;
1929 pScrn
= xf86Screens
[pScreen
->myNum
];
1932 SISVGABlankScreen(pScrn
, on
);
1937 #undef SIS_FONTS_SIZE