diff options
Diffstat (limited to 'drivers/video/sis/sis_main.c')
-rw-r--r-- | drivers/video/sis/sis_main.c | 7525 |
1 files changed, 4314 insertions, 3211 deletions
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 698266036819..42c54b69726e 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c | |||
@@ -1,9 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * SiS 300/305/540/630(S)/730(S) | 2 | * SiS 300/540/630[S]/730[S], |
3 | * SiS 315(H/PRO)/55x/(M)65x/(M)661(F/M)X/740/741(GX)/330/(M)760 | 3 | * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX], |
4 | * XGI V3XT/V5/V8, Z7 | ||
4 | * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3 | 5 | * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3 |
5 | * | 6 | * |
6 | * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria. | 7 | * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria. |
7 | * | 8 | * |
8 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
@@ -19,11 +20,11 @@ | |||
19 | * along with this program; if not, write to the Free Software | 20 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA | 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA |
21 | * | 22 | * |
22 | * Author: Thomas Winischhofer <thomas@winischhofer.net> | 23 | * Author: Thomas Winischhofer <thomas@winischhofer.net> |
23 | * | 24 | * |
24 | * Author of (practically wiped) code base: | 25 | * Author of (practically wiped) code base: |
25 | * SiS (www.sis.com) | 26 | * SiS (www.sis.com) |
26 | * Copyright (C) 1999 Silicon Integrated Systems, Inc. | 27 | * Copyright (C) 1999 Silicon Integrated Systems, Inc. |
27 | * | 28 | * |
28 | * See http://www.winischhofer.net/ for more information and updates | 29 | * See http://www.winischhofer.net/ for more information and updates |
29 | * | 30 | * |
@@ -46,16 +47,15 @@ | |||
46 | #include <linux/mm.h> | 47 | #include <linux/mm.h> |
47 | #include <linux/tty.h> | 48 | #include <linux/tty.h> |
48 | #include <linux/slab.h> | 49 | #include <linux/slab.h> |
49 | #include <linux/delay.h> | ||
50 | #include <linux/fb.h> | 50 | #include <linux/fb.h> |
51 | #include <linux/console.h> | ||
52 | #include <linux/selection.h> | 51 | #include <linux/selection.h> |
53 | #include <linux/smp_lock.h> | ||
54 | #include <linux/ioport.h> | 52 | #include <linux/ioport.h> |
55 | #include <linux/init.h> | 53 | #include <linux/init.h> |
56 | #include <linux/pci.h> | 54 | #include <linux/pci.h> |
57 | #include <linux/vmalloc.h> | 55 | #include <linux/vmalloc.h> |
56 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
58 | #include <linux/vt_kern.h> | 57 | #include <linux/vt_kern.h> |
58 | #endif | ||
59 | #include <linux/capability.h> | 59 | #include <linux/capability.h> |
60 | #include <linux/fs.h> | 60 | #include <linux/fs.h> |
61 | #include <linux/types.h> | 61 | #include <linux/types.h> |
@@ -94,71 +94,75 @@ extern struct display_switch fbcon_sis32; | |||
94 | #endif | 94 | #endif |
95 | #endif | 95 | #endif |
96 | 96 | ||
97 | static void sisfb_handle_command(struct sis_video_info *ivideo, | ||
98 | struct sisfb_cmd *sisfb_command); | ||
99 | |||
97 | /* ------------------ Internal helper routines ----------------- */ | 100 | /* ------------------ Internal helper routines ----------------- */ |
98 | 101 | ||
99 | static void __init | 102 | static void __init |
100 | sisfb_setdefaultparms(void) | 103 | sisfb_setdefaultparms(void) |
101 | { | 104 | { |
102 | sisfb_off = 0; | 105 | sisfb_off = 0; |
103 | sisfb_parm_mem = 0; | 106 | sisfb_parm_mem = 0; |
104 | sisfb_accel = -1; | 107 | sisfb_accel = -1; |
105 | sisfb_ypan = -1; | 108 | sisfb_ypan = -1; |
106 | sisfb_max = -1; | 109 | sisfb_max = -1; |
107 | sisfb_userom = -1; | 110 | sisfb_userom = -1; |
108 | sisfb_useoem = -1; | 111 | sisfb_useoem = -1; |
109 | #ifdef MODULE | 112 | #ifdef MODULE |
110 | /* Module: "None" for 2.4, default mode for 2.5+ */ | 113 | /* Module: "None" for 2.4, default mode for 2.5+ */ |
111 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | 114 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) |
112 | sisfb_mode_idx = -1; | 115 | sisfb_mode_idx = -1; |
113 | #else | 116 | #else |
114 | sisfb_mode_idx = MODE_INDEX_NONE; | 117 | sisfb_mode_idx = MODE_INDEX_NONE; |
115 | #endif | 118 | #endif |
116 | #else | 119 | #else |
117 | /* Static: Default mode */ | 120 | /* Static: Default mode */ |
118 | sisfb_mode_idx = -1; | 121 | sisfb_mode_idx = -1; |
119 | #endif | 122 | #endif |
120 | sisfb_parm_rate = -1; | 123 | sisfb_parm_rate = -1; |
121 | sisfb_crt1off = 0; | 124 | sisfb_crt1off = 0; |
122 | sisfb_forcecrt1 = -1; | 125 | sisfb_forcecrt1 = -1; |
123 | sisfb_crt2type = -1; | 126 | sisfb_crt2type = -1; |
124 | sisfb_crt2flags = 0; | 127 | sisfb_crt2flags = 0; |
125 | sisfb_pdc = 0xff; | 128 | sisfb_pdc = 0xff; |
126 | sisfb_pdca = 0xff; | 129 | sisfb_pdca = 0xff; |
127 | sisfb_scalelcd = -1; | 130 | sisfb_scalelcd = -1; |
128 | sisfb_specialtiming = CUT_NONE; | 131 | sisfb_specialtiming = CUT_NONE; |
129 | sisfb_lvdshl = -1; | 132 | sisfb_lvdshl = -1; |
130 | sisfb_dstn = 0; | 133 | sisfb_dstn = 0; |
131 | sisfb_fstn = 0; | 134 | sisfb_fstn = 0; |
132 | sisfb_tvplug = -1; | 135 | sisfb_tvplug = -1; |
133 | sisfb_tvstd = -1; | 136 | sisfb_tvstd = -1; |
134 | sisfb_tvxposoffset = 0; | 137 | sisfb_tvxposoffset = 0; |
135 | sisfb_tvyposoffset = 0; | 138 | sisfb_tvyposoffset = 0; |
136 | sisfb_filter = -1; | 139 | sisfb_nocrt2rate = 0; |
137 | sisfb_nocrt2rate = 0; | ||
138 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | 140 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) |
139 | sisfb_inverse = 0; | 141 | sisfb_inverse = 0; |
140 | sisfb_fontname[0] = 0; | 142 | sisfb_fontname[0] = 0; |
141 | #endif | 143 | #endif |
142 | #if !defined(__i386__) && !defined(__x86_64__) | 144 | #if !defined(__i386__) && !defined(__x86_64__) |
143 | sisfb_resetcard = 0; | 145 | sisfb_resetcard = 0; |
144 | sisfb_videoram = 0; | 146 | sisfb_videoram = 0; |
145 | #endif | 147 | #endif |
146 | } | 148 | } |
147 | 149 | ||
150 | /* ------------- Parameter parsing -------------- */ | ||
151 | |||
148 | static void __devinit | 152 | static void __devinit |
149 | sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet) | 153 | sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet) |
150 | { | 154 | { |
151 | int i = 0, j = 0; | 155 | int i = 0, j = 0; |
152 | 156 | ||
153 | /* BEWARE: We don't know the hardware specs yet and there is no ivideo */ | 157 | /* We don't know the hardware specs yet and there is no ivideo */ |
154 | 158 | ||
155 | if(vesamode == 0) { | 159 | if(vesamode == 0) { |
156 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | 160 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) |
157 | sisfb_mode_idx = MODE_INDEX_NONE; | 161 | sisfb_mode_idx = MODE_INDEX_NONE; |
158 | #else | 162 | #else |
159 | if(!quiet) { | 163 | if(!quiet) |
160 | printk(KERN_ERR "sisfb: Invalid mode. Using default.\n"); | 164 | printk(KERN_ERR "sisfb: Invalid mode. Using default.\n"); |
161 | } | 165 | |
162 | sisfb_mode_idx = DEFAULT_MODE; | 166 | sisfb_mode_idx = DEFAULT_MODE; |
163 | #endif | 167 | #endif |
164 | return; | 168 | return; |
@@ -169,95 +173,102 @@ sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet) | |||
169 | while(sisbios_mode[i++].mode_no[0] != 0) { | 173 | while(sisbios_mode[i++].mode_no[0] != 0) { |
170 | if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) || | 174 | if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) || |
171 | (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) { | 175 | (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) { |
172 | if(sisfb_fstn) { | 176 | if(sisfb_fstn) { |
173 | if(sisbios_mode[i-1].mode_no[1] == 0x50 || | 177 | if(sisbios_mode[i-1].mode_no[1] == 0x50 || |
174 | sisbios_mode[i-1].mode_no[1] == 0x56 || | 178 | sisbios_mode[i-1].mode_no[1] == 0x56 || |
175 | sisbios_mode[i-1].mode_no[1] == 0x53) continue; | 179 | sisbios_mode[i-1].mode_no[1] == 0x53) |
176 | } else { | 180 | continue; |
177 | if(sisbios_mode[i-1].mode_no[1] == 0x5a || | 181 | } else { |
178 | sisbios_mode[i-1].mode_no[1] == 0x5b) continue; | 182 | if(sisbios_mode[i-1].mode_no[1] == 0x5a || |
179 | } | 183 | sisbios_mode[i-1].mode_no[1] == 0x5b) |
180 | sisfb_mode_idx = i - 1; | 184 | continue; |
181 | j = 1; | 185 | } |
182 | break; | 186 | sisfb_mode_idx = i - 1; |
187 | j = 1; | ||
188 | break; | ||
183 | } | 189 | } |
184 | } | 190 | } |
185 | if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode); | 191 | if((!j) && !quiet) |
192 | printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode); | ||
186 | } | 193 | } |
187 | 194 | ||
188 | static void | 195 | static void __devinit |
189 | sisfb_search_mode(char *name, BOOLEAN quiet) | 196 | sisfb_search_mode(char *name, BOOLEAN quiet) |
190 | { | 197 | { |
191 | int i = 0; | ||
192 | unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0; | 198 | unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0; |
199 | int i = 0; | ||
193 | char strbuf[16], strbuf1[20]; | 200 | char strbuf[16], strbuf1[20]; |
194 | char *nameptr = name; | 201 | char *nameptr = name; |
195 | 202 | ||
196 | /* BEWARE: We don't know the hardware specs yet and there is no ivideo */ | 203 | /* We don't know the hardware specs yet and there is no ivideo */ |
197 | 204 | ||
198 | if(name == NULL) { | 205 | if(name == NULL) { |
199 | if(!quiet) { | 206 | if(!quiet) |
200 | printk(KERN_ERR "sisfb: Internal error, using default mode.\n"); | 207 | printk(KERN_ERR "sisfb: Internal error, using default mode.\n"); |
201 | } | 208 | |
202 | sisfb_mode_idx = DEFAULT_MODE; | 209 | sisfb_mode_idx = DEFAULT_MODE; |
203 | return; | 210 | return; |
204 | } | 211 | } |
205 | 212 | ||
206 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | 213 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) |
207 | if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) { | 214 | if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) { |
208 | if(!quiet) { | 215 | if(!quiet) |
209 | printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n"); | 216 | printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n"); |
210 | } | 217 | |
211 | sisfb_mode_idx = DEFAULT_MODE; | 218 | sisfb_mode_idx = DEFAULT_MODE; |
212 | return; | 219 | return; |
213 | } | 220 | } |
214 | #endif | 221 | #endif |
215 | if(strlen(name) <= 19) { | 222 | if(strlen(name) <= 19) { |
216 | strcpy(strbuf1, name); | 223 | strcpy(strbuf1, name); |
217 | for(i=0; i<strlen(strbuf1); i++) { | 224 | for(i = 0; i < strlen(strbuf1); i++) { |
218 | if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' '; | 225 | if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' '; |
219 | } | 226 | } |
220 | 227 | ||
221 | /* This does some fuzzy mode naming detection */ | 228 | /* This does some fuzzy mode naming detection */ |
222 | if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) { | 229 | if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) { |
223 | if((rate <= 32) || (depth > 32)) { | 230 | if((rate <= 32) || (depth > 32)) { |
224 | j = rate; rate = depth; depth = j; | 231 | j = rate; rate = depth; depth = j; |
225 | } | 232 | } |
226 | sprintf(strbuf, "%ux%ux%u", xres, yres, depth); | 233 | sprintf(strbuf, "%ux%ux%u", xres, yres, depth); |
227 | nameptr = strbuf; | 234 | nameptr = strbuf; |
228 | sisfb_parm_rate = rate; | 235 | sisfb_parm_rate = rate; |
229 | } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) { | 236 | } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) { |
230 | sprintf(strbuf, "%ux%ux%u", xres, yres, depth); | 237 | sprintf(strbuf, "%ux%ux%u", xres, yres, depth); |
231 | nameptr = strbuf; | 238 | nameptr = strbuf; |
232 | } else { | 239 | } else { |
233 | xres = 0; | 240 | xres = 0; |
234 | if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) { | 241 | if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) { |
235 | sprintf(strbuf, "%ux%ux8", xres, yres); | 242 | sprintf(strbuf, "%ux%ux8", xres, yres); |
236 | nameptr = strbuf; | 243 | nameptr = strbuf; |
237 | } else { | 244 | } else { |
238 | sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet); | 245 | sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet); |
239 | return; | 246 | return; |
240 | } | 247 | } |
241 | } | 248 | } |
242 | } | 249 | } |
243 | 250 | ||
244 | i = 0; j = 0; | 251 | i = 0; j = 0; |
245 | while(sisbios_mode[i].mode_no[0] != 0) { | 252 | while(sisbios_mode[i].mode_no[0] != 0) { |
246 | if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) { | 253 | if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) { |
247 | if(sisfb_fstn) { | 254 | if(sisfb_fstn) { |
248 | if(sisbios_mode[i-1].mode_no[1] == 0x50 || | 255 | if(sisbios_mode[i-1].mode_no[1] == 0x50 || |
249 | sisbios_mode[i-1].mode_no[1] == 0x56 || | 256 | sisbios_mode[i-1].mode_no[1] == 0x56 || |
250 | sisbios_mode[i-1].mode_no[1] == 0x53) continue; | 257 | sisbios_mode[i-1].mode_no[1] == 0x53) |
251 | } else { | 258 | continue; |
252 | if(sisbios_mode[i-1].mode_no[1] == 0x5a || | 259 | } else { |
253 | sisbios_mode[i-1].mode_no[1] == 0x5b) continue; | 260 | if(sisbios_mode[i-1].mode_no[1] == 0x5a || |
254 | } | 261 | sisbios_mode[i-1].mode_no[1] == 0x5b) |
255 | sisfb_mode_idx = i - 1; | 262 | continue; |
256 | j = 1; | 263 | } |
257 | break; | 264 | sisfb_mode_idx = i - 1; |
258 | } | 265 | j = 1; |
259 | } | 266 | break; |
260 | if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr); | 267 | } |
268 | } | ||
269 | |||
270 | if((!j) && !quiet) | ||
271 | printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr); | ||
261 | } | 272 | } |
262 | 273 | ||
263 | #ifndef MODULE | 274 | #ifndef MODULE |
@@ -265,7 +276,7 @@ static void __devinit | |||
265 | sisfb_get_vga_mode_from_kernel(void) | 276 | sisfb_get_vga_mode_from_kernel(void) |
266 | { | 277 | { |
267 | #if (defined(__i386__) || defined(__x86_64__)) && defined(CONFIG_VIDEO_SELECT) | 278 | #if (defined(__i386__) || defined(__x86_64__)) && defined(CONFIG_VIDEO_SELECT) |
268 | char mymode[32]; | 279 | char mymode[32]; |
269 | int mydepth = screen_info.lfb_depth; | 280 | int mydepth = screen_info.lfb_depth; |
270 | 281 | ||
271 | if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return; | 282 | if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return; |
@@ -274,15 +285,17 @@ sisfb_get_vga_mode_from_kernel(void) | |||
274 | (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) && | 285 | (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) && |
275 | (mydepth >= 8) && (mydepth <= 32) ) { | 286 | (mydepth >= 8) && (mydepth <= 32) ) { |
276 | 287 | ||
277 | if(mydepth == 24) mydepth = 32; | 288 | if(mydepth == 24) mydepth = 32; |
278 | 289 | ||
279 | sprintf(mymode, "%ux%ux%u", screen_info.lfb_width, | 290 | sprintf(mymode, "%ux%ux%u", screen_info.lfb_width, |
280 | screen_info.lfb_height, | 291 | screen_info.lfb_height, |
281 | mydepth); | 292 | mydepth); |
282 | 293 | ||
283 | printk(KERN_DEBUG "sisfb: Using vga mode %s pre-set by kernel as default\n", mymode); | 294 | printk(KERN_DEBUG |
295 | "sisfb: Using vga mode %s pre-set by kernel as default\n", | ||
296 | mymode); | ||
284 | 297 | ||
285 | sisfb_search_mode(mymode, TRUE); | 298 | sisfb_search_mode(mymode, TRUE); |
286 | } | 299 | } |
287 | #endif | 300 | #endif |
288 | return; | 301 | return; |
@@ -294,26 +307,25 @@ sisfb_search_crt2type(const char *name) | |||
294 | { | 307 | { |
295 | int i = 0; | 308 | int i = 0; |
296 | 309 | ||
297 | /* BEWARE: We don't know the hardware specs yet and there is no ivideo */ | 310 | /* We don't know the hardware specs yet and there is no ivideo */ |
298 | 311 | ||
299 | if(name == NULL) return; | 312 | if(name == NULL) return; |
300 | 313 | ||
301 | while(sis_crt2type[i].type_no != -1) { | 314 | while(sis_crt2type[i].type_no != -1) { |
302 | if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) { | 315 | if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) { |
303 | sisfb_crt2type = sis_crt2type[i].type_no; | 316 | sisfb_crt2type = sis_crt2type[i].type_no; |
304 | sisfb_tvplug = sis_crt2type[i].tvplug_no; | 317 | sisfb_tvplug = sis_crt2type[i].tvplug_no; |
305 | sisfb_crt2flags = sis_crt2type[i].flags; | 318 | sisfb_crt2flags = sis_crt2type[i].flags; |
306 | break; | 319 | break; |
307 | } | 320 | } |
308 | i++; | 321 | i++; |
309 | } | 322 | } |
310 | 323 | ||
311 | sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0; | 324 | sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0; |
312 | sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0; | 325 | sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0; |
313 | 326 | ||
314 | if(sisfb_crt2type < 0) { | 327 | if(sisfb_crt2type < 0) |
315 | printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name); | 328 | printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name); |
316 | } | ||
317 | } | 329 | } |
318 | 330 | ||
319 | static void __init | 331 | static void __init |
@@ -321,16 +333,17 @@ sisfb_search_tvstd(const char *name) | |||
321 | { | 333 | { |
322 | int i = 0; | 334 | int i = 0; |
323 | 335 | ||
324 | /* BEWARE: We don't know the hardware specs yet and there is no ivideo */ | 336 | /* We don't know the hardware specs yet and there is no ivideo */ |
325 | 337 | ||
326 | if(name == NULL) return; | 338 | if(name == NULL) |
339 | return; | ||
327 | 340 | ||
328 | while(sis_tvtype[i].type_no != -1) { | 341 | while(sis_tvtype[i].type_no != -1) { |
329 | if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) { | 342 | if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) { |
330 | sisfb_tvstd = sis_tvtype[i].type_no; | 343 | sisfb_tvstd = sis_tvtype[i].type_no; |
331 | break; | 344 | break; |
332 | } | 345 | } |
333 | i++; | 346 | i++; |
334 | } | 347 | } |
335 | } | 348 | } |
336 | 349 | ||
@@ -340,38 +353,101 @@ sisfb_search_specialtiming(const char *name) | |||
340 | int i = 0; | 353 | int i = 0; |
341 | BOOLEAN found = FALSE; | 354 | BOOLEAN found = FALSE; |
342 | 355 | ||
343 | /* BEWARE: We don't know the hardware specs yet and there is no ivideo */ | 356 | /* We don't know the hardware specs yet and there is no ivideo */ |
344 | 357 | ||
345 | if(name == NULL) return; | 358 | if(name == NULL) |
359 | return; | ||
346 | 360 | ||
347 | if(!strnicmp(name, "none", 4)) { | 361 | if(!strnicmp(name, "none", 4)) { |
348 | sisfb_specialtiming = CUT_FORCENONE; | 362 | sisfb_specialtiming = CUT_FORCENONE; |
349 | printk(KERN_DEBUG "sisfb: Special timing disabled\n"); | 363 | printk(KERN_DEBUG "sisfb: Special timing disabled\n"); |
350 | } else { | 364 | } else { |
351 | while(mycustomttable[i].chipID != 0) { | 365 | while(mycustomttable[i].chipID != 0) { |
352 | if(!strnicmp(name,mycustomttable[i].optionName, strlen(mycustomttable[i].optionName))) { | 366 | if(!strnicmp(name,mycustomttable[i].optionName, |
353 | sisfb_specialtiming = mycustomttable[i].SpecialID; | 367 | strlen(mycustomttable[i].optionName))) { |
354 | found = TRUE; | 368 | sisfb_specialtiming = mycustomttable[i].SpecialID; |
355 | printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n", | 369 | found = TRUE; |
356 | mycustomttable[i].vendorName, mycustomttable[i].cardName, | 370 | printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n", |
357 | mycustomttable[i].optionName); | 371 | mycustomttable[i].vendorName, |
358 | break; | 372 | mycustomttable[i].cardName, |
359 | } | 373 | mycustomttable[i].optionName); |
360 | i++; | 374 | break; |
361 | } | 375 | } |
362 | if(!found) { | 376 | i++; |
363 | printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:"); | 377 | } |
364 | printk(KERN_WARNING "\t\"none\" (to disable special timings)\n"); | 378 | if(!found) { |
365 | i = 0; | 379 | printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:"); |
366 | while(mycustomttable[i].chipID != 0) { | 380 | printk(KERN_WARNING "\t\"none\" (to disable special timings)\n"); |
367 | printk(KERN_WARNING "\t\"%s\" (for %s %s)\n", | 381 | i = 0; |
368 | mycustomttable[i].optionName, | 382 | while(mycustomttable[i].chipID != 0) { |
369 | mycustomttable[i].vendorName, | 383 | printk(KERN_WARNING "\t\"%s\" (for %s %s)\n", |
370 | mycustomttable[i].cardName); | 384 | mycustomttable[i].optionName, |
371 | i++; | 385 | mycustomttable[i].vendorName, |
372 | } | 386 | mycustomttable[i].cardName); |
373 | } | 387 | i++; |
374 | } | 388 | } |
389 | } | ||
390 | } | ||
391 | } | ||
392 | |||
393 | /* ----------- Various detection routines ----------- */ | ||
394 | |||
395 | static void __devinit | ||
396 | sisfb_detect_custom_timing(struct sis_video_info *ivideo) | ||
397 | { | ||
398 | unsigned char *biosver = NULL; | ||
399 | unsigned char *biosdate = NULL; | ||
400 | BOOLEAN footprint; | ||
401 | u32 chksum = 0; | ||
402 | int i, j; | ||
403 | |||
404 | if(ivideo->SiS_Pr.UseROM) { | ||
405 | biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06; | ||
406 | biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c; | ||
407 | for(i = 0; i < 32768; i++) | ||
408 | chksum += ivideo->SiS_Pr.VirtualRomBase[i]; | ||
409 | } | ||
410 | |||
411 | i = 0; | ||
412 | do { | ||
413 | if( (mycustomttable[i].chipID == ivideo->chip) && | ||
414 | ((!strlen(mycustomttable[i].biosversion)) || | ||
415 | (ivideo->SiS_Pr.UseROM && | ||
416 | (!strncmp(mycustomttable[i].biosversion, biosver, | ||
417 | strlen(mycustomttable[i].biosversion))))) && | ||
418 | ((!strlen(mycustomttable[i].biosdate)) || | ||
419 | (ivideo->SiS_Pr.UseROM && | ||
420 | (!strncmp(mycustomttable[i].biosdate, biosdate, | ||
421 | strlen(mycustomttable[i].biosdate))))) && | ||
422 | ((!mycustomttable[i].bioschksum) || | ||
423 | (ivideo->SiS_Pr.UseROM && | ||
424 | (mycustomttable[i].bioschksum == chksum))) && | ||
425 | (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) && | ||
426 | (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) { | ||
427 | footprint = TRUE; | ||
428 | for(j = 0; j < 5; j++) { | ||
429 | if(mycustomttable[i].biosFootprintAddr[j]) { | ||
430 | if(ivideo->SiS_Pr.UseROM) { | ||
431 | if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] != | ||
432 | mycustomttable[i].biosFootprintData[j]) { | ||
433 | footprint = FALSE; | ||
434 | } | ||
435 | } else | ||
436 | footprint = FALSE; | ||
437 | } | ||
438 | } | ||
439 | if(footprint) { | ||
440 | ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID; | ||
441 | printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n", | ||
442 | mycustomttable[i].vendorName, | ||
443 | mycustomttable[i].cardName); | ||
444 | printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n", | ||
445 | mycustomttable[i].optionName); | ||
446 | break; | ||
447 | } | ||
448 | } | ||
449 | i++; | ||
450 | } while(mycustomttable[i].chipID); | ||
375 | } | 451 | } |
376 | 452 | ||
377 | static BOOLEAN __devinit | 453 | static BOOLEAN __devinit |
@@ -384,22 +460,23 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer) | |||
384 | buffer[2] != 0xff || buffer[3] != 0xff || | 460 | buffer[2] != 0xff || buffer[3] != 0xff || |
385 | buffer[4] != 0xff || buffer[5] != 0xff || | 461 | buffer[4] != 0xff || buffer[5] != 0xff || |
386 | buffer[6] != 0xff || buffer[7] != 0x00) { | 462 | buffer[6] != 0xff || buffer[7] != 0x00) { |
387 | printk(KERN_DEBUG "sisfb: Bad EDID header\n"); | 463 | printk(KERN_DEBUG "sisfb: Bad EDID header\n"); |
388 | return FALSE; | 464 | return FALSE; |
389 | } | 465 | } |
390 | 466 | ||
391 | if(buffer[0x12] != 0x01) { | 467 | if(buffer[0x12] != 0x01) { |
392 | printk(KERN_INFO "sisfb: EDID version %d not supported\n", | 468 | printk(KERN_INFO "sisfb: EDID version %d not supported\n", |
393 | buffer[0x12]); | 469 | buffer[0x12]); |
394 | return FALSE; | 470 | return FALSE; |
395 | } | 471 | } |
396 | 472 | ||
397 | monitor->feature = buffer[0x18]; | 473 | monitor->feature = buffer[0x18]; |
398 | 474 | ||
399 | if(!buffer[0x14] & 0x80) { | 475 | if(!buffer[0x14] & 0x80) { |
400 | if(!(buffer[0x14] & 0x08)) { | 476 | if(!(buffer[0x14] & 0x08)) { |
401 | printk(KERN_INFO "sisfb: WARNING: Monitor does not support separate syncs\n"); | 477 | printk(KERN_INFO |
402 | } | 478 | "sisfb: WARNING: Monitor does not support separate syncs\n"); |
479 | } | ||
403 | } | 480 | } |
404 | 481 | ||
405 | if(buffer[0x13] >= 0x01) { | 482 | if(buffer[0x13] >= 0x01) { |
@@ -409,7 +486,7 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer) | |||
409 | j = 0x36; | 486 | j = 0x36; |
410 | for(i=0; i<4; i++) { | 487 | for(i=0; i<4; i++) { |
411 | if(buffer[j] == 0x00 && buffer[j + 1] == 0x00 && | 488 | if(buffer[j] == 0x00 && buffer[j + 1] == 0x00 && |
412 | buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd && | 489 | buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd && |
413 | buffer[j + 4] == 0x00) { | 490 | buffer[j + 4] == 0x00) { |
414 | monitor->hmin = buffer[j + 7]; | 491 | monitor->hmin = buffer[j + 7]; |
415 | monitor->hmax = buffer[j + 8]; | 492 | monitor->hmax = buffer[j + 8]; |
@@ -435,7 +512,7 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer) | |||
435 | emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16); | 512 | emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16); |
436 | for(i = 0; i < 13; i++) { | 513 | for(i = 0; i < 13; i++) { |
437 | if(emodes & sisfb_ddcsmodes[i].mask) { | 514 | if(emodes & sisfb_ddcsmodes[i].mask) { |
438 | if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h; | 515 | if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h; |
439 | if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1; | 516 | if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1; |
440 | if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v; | 517 | if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v; |
441 | if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v; | 518 | if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v; |
@@ -446,80 +523,81 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer) | |||
446 | for(i = 0; i < 8; i++) { | 523 | for(i = 0; i < 8; i++) { |
447 | xres = (buffer[index] + 31) * 8; | 524 | xres = (buffer[index] + 31) * 8; |
448 | switch(buffer[index + 1] & 0xc0) { | 525 | switch(buffer[index + 1] & 0xc0) { |
449 | case 0xc0: yres = (xres * 9) / 16; break; | 526 | case 0xc0: yres = (xres * 9) / 16; break; |
450 | case 0x80: yres = (xres * 4) / 5; break; | 527 | case 0x80: yres = (xres * 4) / 5; break; |
451 | case 0x40: yres = (xres * 3) / 4; break; | 528 | case 0x40: yres = (xres * 3) / 4; break; |
452 | default: yres = xres; break; | 529 | default: yres = xres; break; |
453 | } | 530 | } |
454 | refresh = (buffer[index + 1] & 0x3f) + 60; | 531 | refresh = (buffer[index + 1] & 0x3f) + 60; |
455 | if((xres >= 640) && (yres >= 480)) { | 532 | if((xres >= 640) && (yres >= 480)) { |
456 | for(j = 0; j < 8; j++) { | 533 | for(j = 0; j < 8; j++) { |
457 | if((xres == sisfb_ddcfmodes[j].x) && | 534 | if((xres == sisfb_ddcfmodes[j].x) && |
458 | (yres == sisfb_ddcfmodes[j].y) && | 535 | (yres == sisfb_ddcfmodes[j].y) && |
459 | (refresh == sisfb_ddcfmodes[j].v)) { | 536 | (refresh == sisfb_ddcfmodes[j].v)) { |
460 | if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h; | 537 | if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h; |
461 | if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1; | 538 | if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1; |
462 | if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v; | 539 | if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v; |
463 | if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v; | 540 | if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v; |
464 | if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[i].d; | 541 | if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d; |
465 | } | 542 | } |
466 | } | 543 | } |
467 | } | 544 | } |
468 | index += 2; | 545 | index += 2; |
469 | } | 546 | } |
470 | if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) { | 547 | if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) { |
471 | monitor->datavalid = TRUE; | 548 | monitor->datavalid = TRUE; |
472 | } | 549 | } |
473 | } | 550 | } |
474 | 551 | ||
475 | return(monitor->datavalid); | 552 | return monitor->datavalid; |
476 | } | 553 | } |
477 | 554 | ||
478 | static void __devinit | 555 | static void __devinit |
479 | sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, int crtno) | 556 | sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, int crtno) |
480 | { | 557 | { |
481 | USHORT temp, i, realcrtno = crtno; | 558 | unsigned short temp, i, realcrtno = crtno; |
482 | u8 buffer[256]; | 559 | unsigned char buffer[256]; |
483 | 560 | ||
484 | monitor->datavalid = FALSE; | 561 | monitor->datavalid = FALSE; |
485 | 562 | ||
486 | if(crtno) { | 563 | if(crtno) { |
487 | if(ivideo->vbflags & CRT2_LCD) realcrtno = 1; | 564 | if(ivideo->vbflags & CRT2_LCD) realcrtno = 1; |
488 | else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2; | 565 | else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2; |
489 | else return; | 566 | else return; |
490 | } | 567 | } |
491 | 568 | ||
492 | if((ivideo->sisfb_crt1off) && (!crtno)) return; | 569 | if((ivideo->sisfb_crt1off) && (!crtno)) |
570 | return; | ||
493 | 571 | ||
494 | temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, | 572 | temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, |
495 | realcrtno, 0, &buffer[0]); | 573 | realcrtno, 0, &buffer[0], ivideo->vbflags2); |
496 | if((!temp) || (temp == 0xffff)) { | 574 | if((!temp) || (temp == 0xffff)) { |
497 | printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1); | 575 | printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1); |
498 | return; | 576 | return; |
499 | } else { | 577 | } else { |
500 | printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1); | 578 | printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1); |
501 | printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n", | 579 | printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n", |
502 | crtno + 1, | 580 | crtno + 1, |
503 | (temp & 0x1a) ? "" : "[none of the supported]", | 581 | (temp & 0x1a) ? "" : "[none of the supported]", |
504 | (temp & 0x02) ? "2 " : "", | 582 | (temp & 0x02) ? "2 " : "", |
505 | (temp & 0x08) ? "D&P" : "", | 583 | (temp & 0x08) ? "D&P" : "", |
506 | (temp & 0x10) ? "FPDI-2" : ""); | 584 | (temp & 0x10) ? "FPDI-2" : ""); |
507 | if(temp & 0x02) { | 585 | if(temp & 0x02) { |
508 | i = 3; /* Number of retrys */ | 586 | i = 3; /* Number of retrys */ |
509 | do { | 587 | do { |
510 | temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, | 588 | temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, |
511 | realcrtno, 1, &buffer[0]); | 589 | realcrtno, 1, &buffer[0], ivideo->vbflags2); |
512 | } while((temp) && i--); | 590 | } while((temp) && i--); |
513 | if(!temp) { | 591 | if(!temp) { |
514 | if(sisfb_interpret_edid(monitor, &buffer[0])) { | 592 | if(sisfb_interpret_edid(monitor, &buffer[0])) { |
515 | printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n", | 593 | printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n", |
516 | monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax, | 594 | monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax, |
517 | monitor->dclockmax / 1000); | 595 | monitor->dclockmax / 1000); |
518 | } else { | 596 | } else { |
519 | printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1); | 597 | printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1); |
520 | } | 598 | } |
521 | } else { | 599 | } else { |
522 | printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1); | 600 | printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1); |
523 | } | 601 | } |
524 | } else { | 602 | } else { |
525 | printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n"); | 603 | printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n"); |
@@ -527,6 +605,8 @@ sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, i | |||
527 | } | 605 | } |
528 | } | 606 | } |
529 | 607 | ||
608 | /* -------------- Mode validation --------------- */ | ||
609 | |||
530 | static BOOLEAN | 610 | static BOOLEAN |
531 | sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, | 611 | sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, |
532 | int mode_idx, int rate_idx, int rate) | 612 | int mode_idx, int rate_idx, int rate) |
@@ -534,42 +614,49 @@ sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, | |||
534 | int htotal, vtotal; | 614 | int htotal, vtotal; |
535 | unsigned int dclock, hsync; | 615 | unsigned int dclock, hsync; |
536 | 616 | ||
537 | if(!monitor->datavalid) return TRUE; | 617 | if(!monitor->datavalid) |
618 | return TRUE; | ||
538 | 619 | ||
539 | if(mode_idx < 0) return FALSE; | 620 | if(mode_idx < 0) |
621 | return FALSE; | ||
540 | 622 | ||
541 | /* Skip for 320x200, 320x240, 640x400 */ | 623 | /* Skip for 320x200, 320x240, 640x400 */ |
542 | switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) { | 624 | switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) { |
543 | case 0x59: | 625 | case 0x59: |
544 | case 0x41: | 626 | case 0x41: |
545 | case 0x4f: | 627 | case 0x4f: |
546 | case 0x50: | 628 | case 0x50: |
547 | case 0x56: | 629 | case 0x56: |
548 | case 0x53: | 630 | case 0x53: |
549 | case 0x2f: | 631 | case 0x2f: |
550 | case 0x5d: | 632 | case 0x5d: |
551 | case 0x5e: | 633 | case 0x5e: |
552 | return TRUE; | 634 | return TRUE; |
553 | #ifdef CONFIG_FB_SIS_315 | 635 | #ifdef CONFIG_FB_SIS_315 |
554 | case 0x5a: | 636 | case 0x5a: |
555 | case 0x5b: | 637 | case 0x5b: |
556 | if(ivideo->sisvga_engine == SIS_315_VGA) return TRUE; | 638 | if(ivideo->sisvga_engine == SIS_315_VGA) return TRUE; |
557 | #endif | 639 | #endif |
558 | } | 640 | } |
559 | 641 | ||
560 | if(rate < (monitor->vmin - 1)) return FALSE; | 642 | if(rate < (monitor->vmin - 1)) |
561 | if(rate > (monitor->vmax + 1)) return FALSE; | 643 | return FALSE; |
644 | if(rate > (monitor->vmax + 1)) | ||
645 | return FALSE; | ||
562 | 646 | ||
563 | if(sisfb_gettotalfrommode(&ivideo->SiS_Pr, &ivideo->sishw_ext, | 647 | if(sisfb_gettotalfrommode(&ivideo->SiS_Pr, |
564 | sisbios_mode[mode_idx].mode_no[ivideo->mni], | 648 | sisbios_mode[mode_idx].mode_no[ivideo->mni], |
565 | &htotal, &vtotal, rate_idx)) { | 649 | &htotal, &vtotal, rate_idx)) { |
566 | dclock = (htotal * vtotal * rate) / 1000; | 650 | dclock = (htotal * vtotal * rate) / 1000; |
567 | if(dclock > (monitor->dclockmax + 1000)) return FALSE; | 651 | if(dclock > (monitor->dclockmax + 1000)) |
652 | return FALSE; | ||
568 | hsync = dclock / htotal; | 653 | hsync = dclock / htotal; |
569 | if(hsync < (monitor->hmin - 1)) return FALSE; | 654 | if(hsync < (monitor->hmin - 1)) |
570 | if(hsync > (monitor->hmax + 1)) return FALSE; | 655 | return FALSE; |
656 | if(hsync > (monitor->hmax + 1)) | ||
657 | return FALSE; | ||
571 | } else { | 658 | } else { |
572 | return FALSE; | 659 | return FALSE; |
573 | } | 660 | } |
574 | return TRUE; | 661 | return TRUE; |
575 | } | 662 | } |
@@ -577,82 +664,79 @@ sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, | |||
577 | static int | 664 | static int |
578 | sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags) | 665 | sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags) |
579 | { | 666 | { |
580 | u16 xres=0, yres, myres; | 667 | u16 xres=0, yres, myres; |
581 | 668 | ||
582 | #ifdef CONFIG_FB_SIS_300 | 669 | #ifdef CONFIG_FB_SIS_300 |
583 | if(ivideo->sisvga_engine == SIS_300_VGA) { | 670 | if(ivideo->sisvga_engine == SIS_300_VGA) { |
584 | if(!(sisbios_mode[myindex].chipset & MD_SIS300)) return(-1); | 671 | if(!(sisbios_mode[myindex].chipset & MD_SIS300)) |
585 | } | 672 | return -1 ; |
673 | } | ||
586 | #endif | 674 | #endif |
587 | #ifdef CONFIG_FB_SIS_315 | 675 | #ifdef CONFIG_FB_SIS_315 |
588 | if(ivideo->sisvga_engine == SIS_315_VGA) { | 676 | if(ivideo->sisvga_engine == SIS_315_VGA) { |
589 | if(!(sisbios_mode[myindex].chipset & MD_SIS315)) return(-1); | 677 | if(!(sisbios_mode[myindex].chipset & MD_SIS315)) |
590 | } | 678 | return -1; |
679 | } | ||
591 | #endif | 680 | #endif |
592 | 681 | ||
593 | myres = sisbios_mode[myindex].yres; | 682 | myres = sisbios_mode[myindex].yres; |
594 | |||
595 | switch(vbflags & VB_DISPTYPE_DISP2) { | ||
596 | 683 | ||
597 | case CRT2_LCD: | 684 | switch(vbflags & VB_DISPTYPE_DISP2) { |
598 | 685 | ||
599 | xres = ivideo->lcdxres; yres = ivideo->lcdyres; | 686 | case CRT2_LCD: |
687 | xres = ivideo->lcdxres; yres = ivideo->lcdyres; | ||
600 | 688 | ||
601 | if(ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) { | 689 | if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) && |
602 | if(sisbios_mode[myindex].xres > xres) return(-1); | 690 | (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) { |
603 | if(myres > yres) return(-1); | 691 | if(sisbios_mode[myindex].xres > xres) |
604 | } | 692 | return -1; |
693 | if(myres > yres) | ||
694 | return -1; | ||
695 | } | ||
605 | 696 | ||
606 | if(vbflags & (VB_LVDS | VB_30xBDH)) { | 697 | if(ivideo->sisfb_fstn) { |
607 | if(sisbios_mode[myindex].xres == 320) { | 698 | if(sisbios_mode[myindex].xres == 320) { |
608 | if((myres == 240) || (myres == 480)) { | 699 | if(myres == 240) { |
609 | if(!ivideo->sisfb_fstn) { | 700 | switch(sisbios_mode[myindex].mode_no[1]) { |
610 | if(sisbios_mode[myindex].mode_no[1] == 0x5a || | 701 | case 0x50: myindex = MODE_FSTN_8; break; |
611 | sisbios_mode[myindex].mode_no[1] == 0x5b) | 702 | case 0x56: myindex = MODE_FSTN_16; break; |
612 | return(-1); | 703 | case 0x53: return -1; |
613 | } else { | 704 | } |
614 | if(sisbios_mode[myindex].mode_no[1] == 0x50 || | 705 | } |
615 | sisbios_mode[myindex].mode_no[1] == 0x56 || | 706 | } |
616 | sisbios_mode[myindex].mode_no[1] == 0x53) | 707 | } |
617 | return(-1); | ||
618 | } | ||
619 | } | ||
620 | } | ||
621 | } | ||
622 | 708 | ||
623 | if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres, | 709 | if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres, |
624 | sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn, | 710 | sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn, |
625 | ivideo->SiS_Pr.SiS_CustomT, xres, yres) < 0x14) { | 711 | ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) { |
626 | return(-1); | 712 | return -1; |
627 | } | 713 | } |
628 | break; | 714 | break; |
629 | 715 | ||
630 | case CRT2_TV: | 716 | case CRT2_TV: |
631 | if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres, | 717 | if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres, |
632 | sisbios_mode[myindex].yres, 0) < 0x14) { | 718 | sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) { |
633 | return(-1); | 719 | return -1; |
634 | } | 720 | } |
635 | break; | 721 | break; |
636 | 722 | ||
637 | case CRT2_VGA: | 723 | case CRT2_VGA: |
638 | if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres, | 724 | if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres, |
639 | sisbios_mode[myindex].yres, 0) < 0x14) { | 725 | sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) { |
640 | return(-1); | 726 | return -1; |
727 | } | ||
728 | break; | ||
641 | } | 729 | } |
642 | break; | ||
643 | } | ||
644 | 730 | ||
645 | return(myindex); | 731 | return myindex; |
646 | } | 732 | } |
647 | 733 | ||
648 | static u8 | 734 | static u8 |
649 | sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx) | 735 | sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx) |
650 | { | 736 | { |
651 | u16 xres, yres; | ||
652 | int i = 0; | 737 | int i = 0; |
653 | 738 | u16 xres = sisbios_mode[mode_idx].xres; | |
654 | xres = sisbios_mode[mode_idx].xres; | 739 | u16 yres = sisbios_mode[mode_idx].yres; |
655 | yres = sisbios_mode[mode_idx].yres; | ||
656 | 740 | ||
657 | ivideo->rate_idx = 0; | 741 | ivideo->rate_idx = 0; |
658 | while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) { | 742 | while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) { |
@@ -672,14 +756,14 @@ sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int | |||
672 | rate, sisfb_vrate[i-1].refresh); | 756 | rate, sisfb_vrate[i-1].refresh); |
673 | ivideo->rate_idx = sisfb_vrate[i-1].idx; | 757 | ivideo->rate_idx = sisfb_vrate[i-1].idx; |
674 | ivideo->refresh_rate = sisfb_vrate[i-1].refresh; | 758 | ivideo->refresh_rate = sisfb_vrate[i-1].refresh; |
675 | } | 759 | } |
676 | break; | 760 | break; |
677 | } else if((rate - sisfb_vrate[i].refresh) <= 2) { | 761 | } else if((rate - sisfb_vrate[i].refresh) <= 2) { |
678 | DPRINTK("sisfb: Adjusting rate from %d down to %d\n", | 762 | DPRINTK("sisfb: Adjusting rate from %d down to %d\n", |
679 | rate, sisfb_vrate[i].refresh); | 763 | rate, sisfb_vrate[i].refresh); |
680 | ivideo->rate_idx = sisfb_vrate[i].idx; | 764 | ivideo->rate_idx = sisfb_vrate[i].idx; |
681 | break; | 765 | break; |
682 | } | 766 | } |
683 | } | 767 | } |
684 | i++; | 768 | i++; |
685 | } | 769 | } |
@@ -695,252 +779,321 @@ sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int | |||
695 | static BOOLEAN | 779 | static BOOLEAN |
696 | sisfb_bridgeisslave(struct sis_video_info *ivideo) | 780 | sisfb_bridgeisslave(struct sis_video_info *ivideo) |
697 | { | 781 | { |
698 | unsigned char P1_00; | 782 | unsigned char P1_00; |
699 | 783 | ||
700 | if(!(ivideo->vbflags & VB_VIDEOBRIDGE)) return FALSE; | 784 | if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) |
785 | return FALSE; | ||
701 | 786 | ||
702 | inSISIDXREG(SISPART1,0x00,P1_00); | 787 | inSISIDXREG(SISPART1,0x00,P1_00); |
703 | if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) || | 788 | if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) || |
704 | ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) { | 789 | ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) { |
705 | return TRUE; | 790 | return TRUE; |
706 | } else { | 791 | } else { |
707 | return FALSE; | 792 | return FALSE; |
708 | } | 793 | } |
709 | } | 794 | } |
710 | 795 | ||
711 | static BOOLEAN | 796 | static BOOLEAN |
712 | sisfballowretracecrt1(struct sis_video_info *ivideo) | 797 | sisfballowretracecrt1(struct sis_video_info *ivideo) |
713 | { | 798 | { |
714 | u8 temp; | 799 | u8 temp; |
715 | 800 | ||
716 | inSISIDXREG(SISCR,0x17,temp); | 801 | inSISIDXREG(SISCR,0x17,temp); |
717 | if(!(temp & 0x80)) return FALSE; | 802 | if(!(temp & 0x80)) |
803 | return FALSE; | ||
718 | 804 | ||
719 | inSISIDXREG(SISSR,0x1f,temp); | 805 | inSISIDXREG(SISSR,0x1f,temp); |
720 | if(temp & 0xc0) return FALSE; | 806 | if(temp & 0xc0) |
807 | return FALSE; | ||
721 | 808 | ||
722 | return TRUE; | 809 | return TRUE; |
723 | } | 810 | } |
724 | 811 | ||
725 | static BOOLEAN | 812 | static BOOLEAN |
726 | sisfbcheckvretracecrt1(struct sis_video_info *ivideo) | 813 | sisfbcheckvretracecrt1(struct sis_video_info *ivideo) |
727 | { | 814 | { |
728 | if(!sisfballowretracecrt1(ivideo)) return FALSE; | 815 | if(!sisfballowretracecrt1(ivideo)) |
816 | return FALSE; | ||
729 | 817 | ||
730 | if(inSISREG(SISINPSTAT) & 0x08) return TRUE; | 818 | if(inSISREG(SISINPSTAT) & 0x08) |
731 | else return FALSE; | 819 | return TRUE; |
820 | else | ||
821 | return FALSE; | ||
732 | } | 822 | } |
733 | 823 | ||
734 | static void | 824 | static void |
735 | sisfbwaitretracecrt1(struct sis_video_info *ivideo) | 825 | sisfbwaitretracecrt1(struct sis_video_info *ivideo) |
736 | { | 826 | { |
737 | int watchdog; | 827 | int watchdog; |
738 | 828 | ||
739 | if(!sisfballowretracecrt1(ivideo)) return; | 829 | if(!sisfballowretracecrt1(ivideo)) |
830 | return; | ||
740 | 831 | ||
741 | watchdog = 65536; | 832 | watchdog = 65536; |
742 | while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog); | 833 | while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog); |
743 | watchdog = 65536; | 834 | watchdog = 65536; |
744 | while((inSISREG(SISINPSTAT) & 0x08) && --watchdog); | 835 | while((inSISREG(SISINPSTAT) & 0x08) && --watchdog); |
745 | } | 836 | } |
746 | 837 | ||
747 | static BOOLEAN | 838 | static BOOLEAN |
748 | sisfbcheckvretracecrt2(struct sis_video_info *ivideo) | 839 | sisfbcheckvretracecrt2(struct sis_video_info *ivideo) |
749 | { | 840 | { |
750 | unsigned char temp, reg; | 841 | unsigned char temp, reg; |
751 | 842 | ||
752 | switch(ivideo->sisvga_engine) { | 843 | switch(ivideo->sisvga_engine) { |
753 | case SIS_300_VGA: reg = 0x25; break; | 844 | case SIS_300_VGA: reg = 0x25; break; |
754 | case SIS_315_VGA: reg = 0x30; break; | 845 | case SIS_315_VGA: reg = 0x30; break; |
755 | default: return FALSE; | 846 | default: return FALSE; |
756 | } | 847 | } |
757 | 848 | ||
758 | inSISIDXREG(SISPART1, reg, temp); | 849 | inSISIDXREG(SISPART1, reg, temp); |
759 | if(temp & 0x02) return TRUE; | 850 | if(temp & 0x02) |
760 | else return FALSE; | 851 | return TRUE; |
852 | else | ||
853 | return FALSE; | ||
761 | } | 854 | } |
762 | 855 | ||
763 | static BOOLEAN | 856 | static BOOLEAN |
764 | sisfb_CheckVBRetrace(struct sis_video_info *ivideo) | 857 | sisfb_CheckVBRetrace(struct sis_video_info *ivideo) |
765 | { | 858 | { |
766 | if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { | 859 | if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { |
767 | if(sisfb_bridgeisslave(ivideo)) { | 860 | if(!sisfb_bridgeisslave(ivideo)) { |
768 | return(sisfbcheckvretracecrt1(ivideo)); | 861 | return sisfbcheckvretracecrt2(ivideo); |
769 | } else { | 862 | } |
770 | return(sisfbcheckvretracecrt2(ivideo)); | 863 | } |
771 | } | 864 | return sisfbcheckvretracecrt1(ivideo); |
772 | } | ||
773 | return(sisfbcheckvretracecrt1(ivideo)); | ||
774 | } | 865 | } |
775 | 866 | ||
776 | static u32 | 867 | static u32 |
777 | sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount) | 868 | sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount) |
778 | { | 869 | { |
779 | u8 idx, reg1, reg2, reg3, reg4; | 870 | u8 idx, reg1, reg2, reg3, reg4; |
780 | u32 ret = 0; | 871 | u32 ret = 0; |
781 | 872 | ||
782 | (*vcount) = (*hcount) = 0; | 873 | (*vcount) = (*hcount) = 0; |
783 | 874 | ||
784 | if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) { | 875 | if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) { |
785 | ret |= (FB_VBLANK_HAVE_VSYNC | | 876 | |
786 | FB_VBLANK_HAVE_HBLANK | | 877 | ret |= (FB_VBLANK_HAVE_VSYNC | |
787 | FB_VBLANK_HAVE_VBLANK | | 878 | FB_VBLANK_HAVE_HBLANK | |
788 | FB_VBLANK_HAVE_VCOUNT | | 879 | FB_VBLANK_HAVE_VBLANK | |
789 | FB_VBLANK_HAVE_HCOUNT); | 880 | FB_VBLANK_HAVE_VCOUNT | |
790 | switch(ivideo->sisvga_engine) { | 881 | FB_VBLANK_HAVE_HCOUNT); |
791 | case SIS_300_VGA: idx = 0x25; break; | 882 | switch(ivideo->sisvga_engine) { |
792 | default: | 883 | case SIS_300_VGA: idx = 0x25; break; |
793 | case SIS_315_VGA: idx = 0x30; break; | 884 | default: |
794 | } | 885 | case SIS_315_VGA: idx = 0x30; break; |
795 | inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */ | 886 | } |
796 | inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */ | 887 | inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */ |
797 | inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */ | 888 | inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */ |
798 | inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */ | 889 | inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */ |
799 | if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING; | 890 | inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */ |
800 | if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING; | 891 | if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING; |
801 | if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING; | 892 | if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING; |
802 | (*vcount) = reg3 | ((reg4 & 0x70) << 4); | 893 | if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING; |
803 | (*hcount) = reg2 | ((reg4 & 0x0f) << 8); | 894 | (*vcount) = reg3 | ((reg4 & 0x70) << 4); |
804 | } else if(sisfballowretracecrt1(ivideo)) { | 895 | (*hcount) = reg2 | ((reg4 & 0x0f) << 8); |
805 | ret |= (FB_VBLANK_HAVE_VSYNC | | 896 | |
806 | FB_VBLANK_HAVE_VBLANK | | 897 | } else if(sisfballowretracecrt1(ivideo)) { |
807 | FB_VBLANK_HAVE_VCOUNT | | 898 | |
808 | FB_VBLANK_HAVE_HCOUNT); | 899 | ret |= (FB_VBLANK_HAVE_VSYNC | |
809 | reg1 = inSISREG(SISINPSTAT); | 900 | FB_VBLANK_HAVE_VBLANK | |
810 | if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING; | 901 | FB_VBLANK_HAVE_VCOUNT | |
811 | if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING; | 902 | FB_VBLANK_HAVE_HCOUNT); |
812 | inSISIDXREG(SISCR,0x20,reg1); | 903 | reg1 = inSISREG(SISINPSTAT); |
813 | inSISIDXREG(SISCR,0x1b,reg1); | 904 | if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING; |
814 | inSISIDXREG(SISCR,0x1c,reg2); | 905 | if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING; |
815 | inSISIDXREG(SISCR,0x1d,reg3); | 906 | inSISIDXREG(SISCR,0x20,reg1); |
816 | (*vcount) = reg2 | ((reg3 & 0x07) << 8); | 907 | inSISIDXREG(SISCR,0x1b,reg1); |
817 | (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3; | 908 | inSISIDXREG(SISCR,0x1c,reg2); |
818 | } | 909 | inSISIDXREG(SISCR,0x1d,reg3); |
819 | return ret; | 910 | (*vcount) = reg2 | ((reg3 & 0x07) << 8); |
911 | (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3; | ||
912 | } | ||
913 | |||
914 | return ret; | ||
820 | } | 915 | } |
821 | 916 | ||
822 | static int | 917 | static int |
823 | sisfb_myblank(struct sis_video_info *ivideo, int blank) | 918 | sisfb_myblank(struct sis_video_info *ivideo, int blank) |
824 | { | 919 | { |
825 | u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13; | 920 | u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13; |
826 | BOOLEAN backlight = TRUE; | 921 | BOOLEAN backlight = TRUE; |
827 | 922 | ||
828 | switch(blank) { | 923 | switch(blank) { |
829 | case FB_BLANK_UNBLANK: /* on */ | 924 | case FB_BLANK_UNBLANK: /* on */ |
830 | sr01 = 0x00; | 925 | sr01 = 0x00; |
831 | sr11 = 0x00; | 926 | sr11 = 0x00; |
832 | sr1f = 0x00; | 927 | sr1f = 0x00; |
833 | cr63 = 0x00; | 928 | cr63 = 0x00; |
834 | p2_0 = 0x20; | 929 | p2_0 = 0x20; |
835 | p1_13 = 0x00; | 930 | p1_13 = 0x00; |
836 | backlight = TRUE; | 931 | backlight = TRUE; |
837 | break; | 932 | break; |
838 | case FB_BLANK_NORMAL: /* blank */ | 933 | case FB_BLANK_NORMAL: /* blank */ |
839 | sr01 = 0x20; | 934 | sr01 = 0x20; |
840 | sr11 = 0x00; | 935 | sr11 = 0x00; |
841 | sr1f = 0x00; | 936 | sr1f = 0x00; |
842 | cr63 = 0x00; | 937 | cr63 = 0x00; |
843 | p2_0 = 0x20; | 938 | p2_0 = 0x20; |
844 | p1_13 = 0x00; | 939 | p1_13 = 0x00; |
845 | backlight = TRUE; | 940 | backlight = TRUE; |
846 | break; | 941 | break; |
847 | case FB_BLANK_VSYNC_SUSPEND: /* no vsync */ | 942 | case FB_BLANK_VSYNC_SUSPEND: /* no vsync */ |
848 | sr01 = 0x20; | 943 | sr01 = 0x20; |
849 | sr11 = 0x08; | 944 | sr11 = 0x08; |
850 | sr1f = 0x80; | 945 | sr1f = 0x80; |
851 | cr63 = 0x40; | 946 | cr63 = 0x40; |
852 | p2_0 = 0x40; | 947 | p2_0 = 0x40; |
853 | p1_13 = 0x80; | 948 | p1_13 = 0x80; |
854 | backlight = FALSE; | 949 | backlight = FALSE; |
855 | break; | 950 | break; |
856 | case FB_BLANK_HSYNC_SUSPEND: /* no hsync */ | 951 | case FB_BLANK_HSYNC_SUSPEND: /* no hsync */ |
857 | sr01 = 0x20; | 952 | sr01 = 0x20; |
858 | sr11 = 0x08; | 953 | sr11 = 0x08; |
859 | sr1f = 0x40; | 954 | sr1f = 0x40; |
860 | cr63 = 0x40; | 955 | cr63 = 0x40; |
861 | p2_0 = 0x80; | 956 | p2_0 = 0x80; |
862 | p1_13 = 0x40; | 957 | p1_13 = 0x40; |
863 | backlight = FALSE; | 958 | backlight = FALSE; |
864 | break; | 959 | break; |
865 | case FB_BLANK_POWERDOWN: /* off */ | 960 | case FB_BLANK_POWERDOWN: /* off */ |
866 | sr01 = 0x20; | 961 | sr01 = 0x20; |
867 | sr11 = 0x08; | 962 | sr11 = 0x08; |
868 | sr1f = 0xc0; | 963 | sr1f = 0xc0; |
869 | cr63 = 0x40; | 964 | cr63 = 0x40; |
870 | p2_0 = 0xc0; | 965 | p2_0 = 0xc0; |
871 | p1_13 = 0xc0; | 966 | p1_13 = 0xc0; |
872 | backlight = FALSE; | 967 | backlight = FALSE; |
873 | break; | 968 | break; |
874 | default: | 969 | default: |
875 | return 1; | 970 | return 1; |
876 | } | 971 | } |
877 | 972 | ||
878 | if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) { | 973 | if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) { |
879 | 974 | ||
880 | if( (!ivideo->sisfb_thismonitor.datavalid) || | 975 | if( (!ivideo->sisfb_thismonitor.datavalid) || |
881 | ((ivideo->sisfb_thismonitor.datavalid) && | 976 | ((ivideo->sisfb_thismonitor.datavalid) && |
882 | (ivideo->sisfb_thismonitor.feature & 0xe0))) { | 977 | (ivideo->sisfb_thismonitor.feature & 0xe0))) { |
883 | 978 | ||
884 | if(ivideo->sisvga_engine == SIS_315_VGA) { | 979 | if(ivideo->sisvga_engine == SIS_315_VGA) { |
885 | setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63); | 980 | setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63); |
886 | } | 981 | } |
887 | 982 | ||
888 | if(!(sisfb_bridgeisslave(ivideo))) { | 983 | if(!(sisfb_bridgeisslave(ivideo))) { |
889 | setSISIDXREG(SISSR, 0x01, ~0x20, sr01); | 984 | setSISIDXREG(SISSR, 0x01, ~0x20, sr01); |
890 | setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f); | 985 | setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f); |
891 | } | 986 | } |
892 | } | 987 | } |
893 | 988 | ||
894 | } | 989 | } |
895 | 990 | ||
896 | if(ivideo->currentvbflags & CRT2_LCD) { | 991 | if(ivideo->currentvbflags & CRT2_LCD) { |
897 | 992 | ||
898 | if(ivideo->vbflags & (VB_301LV|VB_302LV|VB_302ELV)) { | 993 | if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) { |
899 | if(backlight) { | 994 | if(backlight) { |
900 | SiS_SiS30xBLOn(&ivideo->SiS_Pr, &ivideo->sishw_ext); | 995 | SiS_SiS30xBLOn(&ivideo->SiS_Pr); |
901 | } else { | 996 | } else { |
902 | SiS_SiS30xBLOff(&ivideo->SiS_Pr, &ivideo->sishw_ext); | 997 | SiS_SiS30xBLOff(&ivideo->SiS_Pr); |
903 | } | 998 | } |
904 | } else if(ivideo->sisvga_engine == SIS_315_VGA) { | 999 | } else if(ivideo->sisvga_engine == SIS_315_VGA) { |
905 | if(ivideo->vbflags & VB_CHRONTEL) { | 1000 | #ifdef CONFIG_FB_SIS_315 |
906 | if(backlight) { | 1001 | if(ivideo->vbflags2 & VB2_CHRONTEL) { |
907 | SiS_Chrontel701xBLOn(&ivideo->SiS_Pr,&ivideo->sishw_ext); | 1002 | if(backlight) { |
908 | } else { | 1003 | SiS_Chrontel701xBLOn(&ivideo->SiS_Pr); |
909 | SiS_Chrontel701xBLOff(&ivideo->SiS_Pr); | 1004 | } else { |
910 | } | 1005 | SiS_Chrontel701xBLOff(&ivideo->SiS_Pr); |
911 | } | 1006 | } |
912 | } | 1007 | } |
913 | 1008 | #endif | |
914 | if(((ivideo->sisvga_engine == SIS_300_VGA) && | 1009 | } |
915 | (ivideo->vbflags & (VB_301|VB_30xBDH|VB_LVDS))) || | 1010 | |
916 | ((ivideo->sisvga_engine == SIS_315_VGA) && | 1011 | if(((ivideo->sisvga_engine == SIS_300_VGA) && |
917 | ((ivideo->vbflags & (VB_LVDS | VB_CHRONTEL)) == VB_LVDS))) { | 1012 | (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) || |
918 | setSISIDXREG(SISSR, 0x11, ~0x0c, sr11); | 1013 | ((ivideo->sisvga_engine == SIS_315_VGA) && |
919 | } | 1014 | ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) { |
920 | 1015 | setSISIDXREG(SISSR, 0x11, ~0x0c, sr11); | |
921 | if(ivideo->sisvga_engine == SIS_300_VGA) { | 1016 | } |
922 | if((ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) && | 1017 | |
923 | (!(ivideo->vbflags & VB_30xBDH))) { | 1018 | if(ivideo->sisvga_engine == SIS_300_VGA) { |
924 | setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13); | 1019 | if((ivideo->vbflags2 & VB2_30xB) && |
925 | } | 1020 | (!(ivideo->vbflags2 & VB2_30xBDH))) { |
926 | } else if(ivideo->sisvga_engine == SIS_315_VGA) { | 1021 | setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13); |
927 | if((ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) && | 1022 | } |
928 | (!(ivideo->vbflags & VB_30xBDH))) { | 1023 | } else if(ivideo->sisvga_engine == SIS_315_VGA) { |
929 | setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); | 1024 | if((ivideo->vbflags2 & VB2_30xB) && |
930 | } | 1025 | (!(ivideo->vbflags2 & VB2_30xBDH))) { |
931 | } | 1026 | setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); |
932 | 1027 | } | |
933 | } else if(ivideo->currentvbflags & CRT2_VGA) { | 1028 | } |
934 | 1029 | ||
935 | if(ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) { | 1030 | } else if(ivideo->currentvbflags & CRT2_VGA) { |
936 | setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); | 1031 | |
937 | } | 1032 | if(ivideo->vbflags2 & VB2_30xB) { |
938 | 1033 | setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); | |
939 | } | 1034 | } |
940 | 1035 | ||
941 | return(0); | 1036 | } |
1037 | |||
1038 | return 0; | ||
1039 | } | ||
1040 | |||
1041 | /* ------------- Callbacks from init.c/init301.c -------------- */ | ||
1042 | |||
1043 | #ifdef CONFIG_FB_SIS_300 | ||
1044 | unsigned int | ||
1045 | sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg) | ||
1046 | { | ||
1047 | struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo; | ||
1048 | u32 val = 0; | ||
1049 | |||
1050 | pci_read_config_dword(ivideo->nbridge, reg, &val); | ||
1051 | return (unsigned int)val; | ||
1052 | } | ||
1053 | |||
1054 | void | ||
1055 | sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val) | ||
1056 | { | ||
1057 | struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo; | ||
1058 | |||
1059 | pci_write_config_dword(ivideo->nbridge, reg, (u32)val); | ||
942 | } | 1060 | } |
943 | 1061 | ||
1062 | unsigned int | ||
1063 | sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg) | ||
1064 | { | ||
1065 | struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo; | ||
1066 | u32 val = 0; | ||
1067 | |||
1068 | if(!ivideo->lpcdev) return 0; | ||
1069 | |||
1070 | pci_read_config_dword(ivideo->lpcdev, reg, &val); | ||
1071 | return (unsigned int)val; | ||
1072 | } | ||
1073 | #endif | ||
1074 | |||
1075 | #ifdef CONFIG_FB_SIS_315 | ||
1076 | void | ||
1077 | sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val) | ||
1078 | { | ||
1079 | struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo; | ||
1080 | |||
1081 | pci_write_config_byte(ivideo->nbridge, reg, (u8)val); | ||
1082 | } | ||
1083 | |||
1084 | unsigned int | ||
1085 | sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg) | ||
1086 | { | ||
1087 | struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo; | ||
1088 | u16 val = 0; | ||
1089 | |||
1090 | if(!ivideo->lpcdev) return 0; | ||
1091 | |||
1092 | pci_read_config_word(ivideo->lpcdev, reg, &val); | ||
1093 | return (unsigned int)val; | ||
1094 | } | ||
1095 | #endif | ||
1096 | |||
944 | /* ----------- FBDev related routines for all series ----------- */ | 1097 | /* ----------- FBDev related routines for all series ----------- */ |
945 | 1098 | ||
946 | static int | 1099 | static int |
@@ -952,7 +1105,7 @@ sisfb_get_cmap_len(const struct fb_var_screeninfo *var) | |||
952 | static void | 1105 | static void |
953 | sisfb_set_vparms(struct sis_video_info *ivideo) | 1106 | sisfb_set_vparms(struct sis_video_info *ivideo) |
954 | { | 1107 | { |
955 | switch(ivideo->video_bpp) { | 1108 | switch(ivideo->video_bpp) { |
956 | case 8: | 1109 | case 8: |
957 | ivideo->DstColor = 0x0000; | 1110 | ivideo->DstColor = 0x0000; |
958 | ivideo->SiS310_AccelDepth = 0x00000000; | 1111 | ivideo->SiS310_AccelDepth = 0x00000000; |
@@ -972,14 +1125,13 @@ sisfb_set_vparms(struct sis_video_info *ivideo) | |||
972 | ivideo->video_cmap_len = 16; | 1125 | ivideo->video_cmap_len = 16; |
973 | printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp); | 1126 | printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp); |
974 | ivideo->accel = 0; | 1127 | ivideo->accel = 0; |
975 | break; | 1128 | } |
976 | } | ||
977 | } | 1129 | } |
978 | 1130 | ||
979 | static int | 1131 | static int |
980 | sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) | 1132 | sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) |
981 | { | 1133 | { |
982 | int maxyres = ivideo->heapstart / (var->xres_virtual * (var->bits_per_pixel >> 3)); | 1134 | int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3)); |
983 | 1135 | ||
984 | if(maxyres > 32767) maxyres = 32767; | 1136 | if(maxyres > 32767) maxyres = 32767; |
985 | 1137 | ||
@@ -996,30 +1148,29 @@ sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) | |||
996 | ivideo->scrnpitchCRT1 <<= 1; | 1148 | ivideo->scrnpitchCRT1 <<= 1; |
997 | } | 1149 | } |
998 | } | 1150 | } |
999 | |||
1000 | } | 1151 | } |
1001 | 1152 | ||
1002 | static void | 1153 | static void |
1003 | sisfb_set_pitch(struct sis_video_info *ivideo) | 1154 | sisfb_set_pitch(struct sis_video_info *ivideo) |
1004 | { | 1155 | { |
1005 | BOOLEAN isslavemode = FALSE; | 1156 | BOOLEAN isslavemode = FALSE; |
1006 | unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3; | 1157 | unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3; |
1007 | unsigned short HDisplay2 = ivideo->video_linelength >> 3; | 1158 | unsigned short HDisplay2 = ivideo->video_linelength >> 3; |
1008 | 1159 | ||
1009 | if(sisfb_bridgeisslave(ivideo)) isslavemode = TRUE; | 1160 | if(sisfb_bridgeisslave(ivideo)) isslavemode = TRUE; |
1010 | 1161 | ||
1011 | /* We need to set pitch for CRT1 if bridge is in slave mode, too */ | 1162 | /* We need to set pitch for CRT1 if bridge is in slave mode, too */ |
1012 | if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) { | 1163 | if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) { |
1013 | outSISIDXREG(SISCR,0x13,(HDisplay1 & 0xFF)); | 1164 | outSISIDXREG(SISCR,0x13,(HDisplay1 & 0xFF)); |
1014 | setSISIDXREG(SISSR,0x0E,0xF0,(HDisplay1 >> 8)); | 1165 | setSISIDXREG(SISSR,0x0E,0xF0,(HDisplay1 >> 8)); |
1015 | } | 1166 | } |
1016 | 1167 | ||
1017 | /* We must not set the pitch for CRT2 if bridge is in slave mode */ | 1168 | /* We must not set the pitch for CRT2 if bridge is in slave mode */ |
1018 | if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) { | 1169 | if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) { |
1019 | orSISIDXREG(SISPART1,ivideo->CRT2_write_enable,0x01); | 1170 | orSISIDXREG(SISPART1,ivideo->CRT2_write_enable,0x01); |
1020 | outSISIDXREG(SISPART1,0x07,(HDisplay2 & 0xFF)); | 1171 | outSISIDXREG(SISPART1,0x07,(HDisplay2 & 0xFF)); |
1021 | setSISIDXREG(SISPART1,0x09,0xF0,(HDisplay2 >> 8)); | 1172 | setSISIDXREG(SISPART1,0x09,0xF0,(HDisplay2 >> 8)); |
1022 | } | 1173 | } |
1023 | } | 1174 | } |
1024 | 1175 | ||
1025 | static void | 1176 | static void |
@@ -1056,12 +1207,41 @@ sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) | |||
1056 | } | 1207 | } |
1057 | 1208 | ||
1058 | static int | 1209 | static int |
1210 | sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn) | ||
1211 | { | ||
1212 | unsigned short modeno = ivideo->mode_no; | ||
1213 | |||
1214 | /* >=2.6.12's fbcon clears the screen anyway */ | ||
1215 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12) | ||
1216 | if(!clrscrn) modeno |= 0x80; | ||
1217 | #else | ||
1218 | modeno |= 0x80; | ||
1219 | #endif | ||
1220 | |||
1221 | outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); | ||
1222 | |||
1223 | sisfb_pre_setmode(ivideo); | ||
1224 | |||
1225 | if(SiSSetMode(&ivideo->SiS_Pr, modeno) == 0) { | ||
1226 | printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no); | ||
1227 | return -EINVAL; | ||
1228 | } | ||
1229 | |||
1230 | outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); | ||
1231 | |||
1232 | sisfb_post_setmode(ivideo); | ||
1233 | |||
1234 | return 0; | ||
1235 | } | ||
1236 | |||
1237 | |||
1238 | static int | ||
1059 | sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info) | 1239 | sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info) |
1060 | { | 1240 | { |
1061 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; | 1241 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; |
1062 | unsigned int htotal = 0, vtotal = 0; | 1242 | unsigned int htotal = 0, vtotal = 0; |
1063 | unsigned int drate = 0, hrate = 0; | 1243 | unsigned int drate = 0, hrate = 0; |
1064 | int found_mode = 0; | 1244 | int found_mode = 0, ret; |
1065 | int old_mode; | 1245 | int old_mode; |
1066 | u32 pixclock; | 1246 | u32 pixclock; |
1067 | 1247 | ||
@@ -1088,11 +1268,11 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in | |||
1088 | } | 1268 | } |
1089 | 1269 | ||
1090 | if(pixclock && htotal && vtotal) { | 1270 | if(pixclock && htotal && vtotal) { |
1091 | drate = 1000000000 / pixclock; | 1271 | drate = 1000000000 / pixclock; |
1092 | hrate = (drate * 1000) / htotal; | 1272 | hrate = (drate * 1000) / htotal; |
1093 | ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal); | 1273 | ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal); |
1094 | } else { | 1274 | } else { |
1095 | ivideo->refresh_rate = 60; | 1275 | ivideo->refresh_rate = 60; |
1096 | } | 1276 | } |
1097 | 1277 | ||
1098 | old_mode = ivideo->sisfb_mode_idx; | 1278 | old_mode = ivideo->sisfb_mode_idx; |
@@ -1113,6 +1293,7 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in | |||
1113 | if(found_mode) { | 1293 | if(found_mode) { |
1114 | ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo, | 1294 | ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo, |
1115 | ivideo->sisfb_mode_idx, ivideo->currentvbflags); | 1295 | ivideo->sisfb_mode_idx, ivideo->currentvbflags); |
1296 | ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]; | ||
1116 | } else { | 1297 | } else { |
1117 | ivideo->sisfb_mode_idx = -1; | 1298 | ivideo->sisfb_mode_idx = -1; |
1118 | } | 1299 | } |
@@ -1131,10 +1312,10 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in | |||
1131 | 1312 | ||
1132 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | 1313 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) |
1133 | if(ivideo->sisfb_thismonitor.datavalid) { | 1314 | if(ivideo->sisfb_thismonitor.datavalid) { |
1134 | if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx, | 1315 | if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx, |
1135 | ivideo->rate_idx, ivideo->refresh_rate)) { | 1316 | ivideo->rate_idx, ivideo->refresh_rate)) { |
1136 | printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n"); | 1317 | printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n"); |
1137 | } | 1318 | } |
1138 | } | 1319 | } |
1139 | #endif | 1320 | #endif |
1140 | 1321 | ||
@@ -1143,24 +1324,9 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in | |||
1143 | #else | 1324 | #else |
1144 | if(isactive) { | 1325 | if(isactive) { |
1145 | #endif | 1326 | #endif |
1146 | sisfb_pre_setmode(ivideo); | 1327 | /* If acceleration to be used? Need to know |
1147 | 1328 | * before pre/post_set_mode() | |
1148 | if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) { | 1329 | */ |
1149 | printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no); | ||
1150 | return -EINVAL; | ||
1151 | } | ||
1152 | |||
1153 | outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); | ||
1154 | |||
1155 | sisfb_post_setmode(ivideo); | ||
1156 | |||
1157 | ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp; | ||
1158 | ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres; | ||
1159 | ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres; | ||
1160 | |||
1161 | sisfb_calc_pitch(ivideo, var); | ||
1162 | sisfb_set_pitch(ivideo); | ||
1163 | |||
1164 | ivideo->accel = 0; | 1330 | ivideo->accel = 0; |
1165 | #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN) | 1331 | #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN) |
1166 | #ifdef STUPID_ACCELF_TEXT_SHIT | 1332 | #ifdef STUPID_ACCELF_TEXT_SHIT |
@@ -1175,6 +1341,17 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in | |||
1175 | if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1; | 1341 | if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1; |
1176 | #endif | 1342 | #endif |
1177 | 1343 | ||
1344 | if((ret = sisfb_set_mode(ivideo, 1))) { | ||
1345 | return ret; | ||
1346 | } | ||
1347 | |||
1348 | ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp; | ||
1349 | ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres; | ||
1350 | ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres; | ||
1351 | |||
1352 | sisfb_calc_pitch(ivideo, var); | ||
1353 | sisfb_set_pitch(ivideo); | ||
1354 | |||
1178 | sisfb_set_vparms(ivideo); | 1355 | sisfb_set_vparms(ivideo); |
1179 | 1356 | ||
1180 | ivideo->current_width = ivideo->video_width; | 1357 | ivideo->current_width = ivideo->video_width; |
@@ -1186,572 +1363,79 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in | |||
1186 | ivideo->current_pixclock = var->pixclock; | 1363 | ivideo->current_pixclock = var->pixclock; |
1187 | ivideo->current_refresh_rate = ivideo->refresh_rate; | 1364 | ivideo->current_refresh_rate = ivideo->refresh_rate; |
1188 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | 1365 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) |
1189 | ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate; | 1366 | ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate; |
1190 | #endif | 1367 | #endif |
1191 | } | 1368 | } |
1192 | 1369 | ||
1193 | return 0; | 1370 | return 0; |
1194 | } | 1371 | } |
1195 | 1372 | ||
1196 | static int | 1373 | static void |
1197 | sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) | 1374 | sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base) |
1198 | { | 1375 | { |
1199 | unsigned int base; | ||
1200 | |||
1201 | if(var->xoffset > (var->xres_virtual - var->xres)) { | ||
1202 | return -EINVAL; | ||
1203 | } | ||
1204 | if(var->yoffset > (var->yres_virtual - var->yres)) { | ||
1205 | return -EINVAL; | ||
1206 | } | ||
1207 | |||
1208 | base = (var->yoffset * var->xres_virtual) + var->xoffset; | ||
1209 | |||
1210 | /* calculate base bpp dep. */ | ||
1211 | switch(var->bits_per_pixel) { | ||
1212 | case 32: | ||
1213 | break; | ||
1214 | case 16: | ||
1215 | base >>= 1; | ||
1216 | break; | ||
1217 | case 8: | ||
1218 | default: | ||
1219 | base >>= 2; | ||
1220 | break; | ||
1221 | } | ||
1222 | |||
1223 | outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); | 1376 | outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); |
1224 | 1377 | ||
1225 | outSISIDXREG(SISCR, 0x0D, base & 0xFF); | 1378 | outSISIDXREG(SISCR, 0x0D, base & 0xFF); |
1226 | outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); | 1379 | outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); |
1227 | outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF); | 1380 | outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF); |
1228 | if(ivideo->sisvga_engine == SIS_315_VGA) { | 1381 | if(ivideo->sisvga_engine == SIS_315_VGA) { |
1229 | setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01); | 1382 | setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01); |
1230 | } | 1383 | } |
1231 | if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { | ||
1232 | orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01); | ||
1233 | outSISIDXREG(SISPART1, 0x06, (base & 0xFF)); | ||
1234 | outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF)); | ||
1235 | outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF)); | ||
1236 | if(ivideo->sisvga_engine == SIS_315_VGA) { | ||
1237 | setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7); | ||
1238 | } | ||
1239 | } | ||
1240 | return 0; | ||
1241 | } | 1384 | } |
1242 | 1385 | ||
1243 | /* ------------ FBDev related routines for 2.4 series ----------- */ | ||
1244 | |||
1245 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
1246 | |||
1247 | static void | 1386 | static void |
1248 | sisfb_crtc_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) | 1387 | sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base) |
1249 | { | ||
1250 | u16 VRE, VBE, VRS, VBS, VDE, VT; | ||
1251 | u16 HRE, HBE, HRS, HBS, HDE, HT; | ||
1252 | u8 sr_data, cr_data, cr_data2, cr_data3, mr_data; | ||
1253 | int A, B, C, D, E, F, temp; | ||
1254 | unsigned int hrate, drate, maxyres; | ||
1255 | |||
1256 | inSISIDXREG(SISSR, IND_SIS_COLOR_MODE, sr_data); | ||
1257 | |||
1258 | if(sr_data & SIS_INTERLACED_MODE) | ||
1259 | var->vmode = FB_VMODE_INTERLACED; | ||
1260 | else | ||
1261 | var->vmode = FB_VMODE_NONINTERLACED; | ||
1262 | |||
1263 | switch((sr_data & 0x1C) >> 2) { | ||
1264 | case SIS_8BPP_COLOR_MODE: | ||
1265 | var->bits_per_pixel = 8; | ||
1266 | break; | ||
1267 | case SIS_16BPP_COLOR_MODE: | ||
1268 | var->bits_per_pixel = 16; | ||
1269 | break; | ||
1270 | case SIS_32BPP_COLOR_MODE: | ||
1271 | var->bits_per_pixel = 32; | ||
1272 | break; | ||
1273 | } | ||
1274 | |||
1275 | sisfb_bpp_to_var(ivideo, var); | ||
1276 | |||
1277 | inSISIDXREG(SISSR, 0x0A, sr_data); | ||
1278 | inSISIDXREG(SISCR, 0x06, cr_data); | ||
1279 | inSISIDXREG(SISCR, 0x07, cr_data2); | ||
1280 | |||
1281 | VT = (cr_data & 0xFF) | | ||
1282 | ((u16) (cr_data2 & 0x01) << 8) | | ||
1283 | ((u16) (cr_data2 & 0x20) << 4) | | ||
1284 | ((u16) (sr_data & 0x01) << 10); | ||
1285 | A = VT + 2; | ||
1286 | |||
1287 | inSISIDXREG(SISCR, 0x12, cr_data); | ||
1288 | |||
1289 | VDE = (cr_data & 0xff) | | ||
1290 | ((u16) (cr_data2 & 0x02) << 7) | | ||
1291 | ((u16) (cr_data2 & 0x40) << 3) | | ||
1292 | ((u16) (sr_data & 0x02) << 9); | ||
1293 | E = VDE + 1; | ||
1294 | |||
1295 | inSISIDXREG(SISCR, 0x10, cr_data); | ||
1296 | |||
1297 | VRS = (cr_data & 0xff) | | ||
1298 | ((u16) (cr_data2 & 0x04) << 6) | | ||
1299 | ((u16) (cr_data2 & 0x80) << 2) | | ||
1300 | ((u16) (sr_data & 0x08) << 7); | ||
1301 | F = VRS + 1 - E; | ||
1302 | |||
1303 | inSISIDXREG(SISCR, 0x15, cr_data); | ||
1304 | inSISIDXREG(SISCR, 0x09, cr_data3); | ||
1305 | |||
1306 | if(cr_data3 & 0x80) var->vmode = FB_VMODE_DOUBLE; | ||
1307 | |||
1308 | VBS = (cr_data & 0xff) | | ||
1309 | ((u16) (cr_data2 & 0x08) << 5) | | ||
1310 | ((u16) (cr_data3 & 0x20) << 4) | | ||
1311 | ((u16) (sr_data & 0x04) << 8); | ||
1312 | |||
1313 | inSISIDXREG(SISCR, 0x16, cr_data); | ||
1314 | |||
1315 | VBE = (cr_data & 0xff) | ((u16) (sr_data & 0x10) << 4); | ||
1316 | temp = VBE - ((E - 1) & 511); | ||
1317 | B = (temp > 0) ? temp : (temp + 512); | ||
1318 | |||
1319 | inSISIDXREG(SISCR, 0x11, cr_data); | ||
1320 | |||
1321 | VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1); | ||
1322 | temp = VRE - ((E + F - 1) & 31); | ||
1323 | C = (temp > 0) ? temp : (temp + 32); | ||
1324 | |||
1325 | D = B - F - C; | ||
1326 | |||
1327 | var->yres = E; | ||
1328 | var->upper_margin = D; | ||
1329 | var->lower_margin = F; | ||
1330 | var->vsync_len = C; | ||
1331 | |||
1332 | if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { | ||
1333 | var->yres <<= 1; | ||
1334 | var->upper_margin <<= 1; | ||
1335 | var->lower_margin <<= 1; | ||
1336 | var->vsync_len <<= 1; | ||
1337 | } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { | ||
1338 | var->yres >>= 1; | ||
1339 | var->upper_margin >>= 1; | ||
1340 | var->lower_margin >>= 1; | ||
1341 | var->vsync_len >>= 1; | ||
1342 | } | ||
1343 | |||
1344 | inSISIDXREG(SISSR, 0x0b, sr_data); | ||
1345 | inSISIDXREG(SISCR, 0x00, cr_data); | ||
1346 | |||
1347 | HT = (cr_data & 0xff) | ((u16) (sr_data & 0x03) << 8); | ||
1348 | A = HT + 5; | ||
1349 | |||
1350 | inSISIDXREG(SISCR, 0x01, cr_data); | ||
1351 | |||
1352 | HDE = (cr_data & 0xff) | ((u16) (sr_data & 0x0C) << 6); | ||
1353 | E = HDE + 1; | ||
1354 | |||
1355 | inSISIDXREG(SISCR, 0x04, cr_data); | ||
1356 | |||
1357 | HRS = (cr_data & 0xff) | ((u16) (sr_data & 0xC0) << 2); | ||
1358 | F = HRS - E - 3; | ||
1359 | |||
1360 | inSISIDXREG(SISCR, 0x02, cr_data); | ||
1361 | |||
1362 | HBS = (cr_data & 0xff) | ((u16) (sr_data & 0x30) << 4); | ||
1363 | |||
1364 | inSISIDXREG(SISSR, 0x0c, sr_data); | ||
1365 | inSISIDXREG(SISCR, 0x03, cr_data); | ||
1366 | inSISIDXREG(SISCR, 0x05, cr_data2); | ||
1367 | |||
1368 | HBE = (cr_data & 0x1f) | | ||
1369 | ((u16) (cr_data2 & 0x80) >> 2) | | ||
1370 | ((u16) (sr_data & 0x03) << 6); | ||
1371 | HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3); | ||
1372 | |||
1373 | temp = HBE - ((E - 1) & 255); | ||
1374 | B = (temp > 0) ? temp : (temp + 256); | ||
1375 | |||
1376 | temp = HRE - ((E + F + 3) & 63); | ||
1377 | C = (temp > 0) ? temp : (temp + 64); | ||
1378 | |||
1379 | D = B - F - C; | ||
1380 | |||
1381 | var->xres = E * 8; | ||
1382 | if(var->xres_virtual < var->xres) { | ||
1383 | var->xres_virtual = var->xres; | ||
1384 | } | ||
1385 | |||
1386 | if((var->xres == 320) && | ||
1387 | (var->yres == 200 || var->yres == 240)) { | ||
1388 | /* Terrible hack, but the correct CRTC data for | ||
1389 | * these modes only produces a black screen... | ||
1390 | */ | ||
1391 | var->left_margin = (400 - 376); | ||
1392 | var->right_margin = (328 - 320); | ||
1393 | var->hsync_len = (376 - 328); | ||
1394 | } else { | ||
1395 | var->left_margin = D * 8; | ||
1396 | var->right_margin = F * 8; | ||
1397 | var->hsync_len = C * 8; | ||
1398 | } | ||
1399 | var->activate = FB_ACTIVATE_NOW; | ||
1400 | |||
1401 | var->sync = 0; | ||
1402 | |||
1403 | mr_data = inSISREG(SISMISCR); | ||
1404 | if(mr_data & 0x80) | ||
1405 | var->sync &= ~FB_SYNC_VERT_HIGH_ACT; | ||
1406 | else | ||
1407 | var->sync |= FB_SYNC_VERT_HIGH_ACT; | ||
1408 | |||
1409 | if(mr_data & 0x40) | ||
1410 | var->sync &= ~FB_SYNC_HOR_HIGH_ACT; | ||
1411 | else | ||
1412 | var->sync |= FB_SYNC_HOR_HIGH_ACT; | ||
1413 | |||
1414 | VT += 2; | ||
1415 | VT <<= 1; | ||
1416 | HT = (HT + 5) * 8; | ||
1417 | |||
1418 | if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { | ||
1419 | VT <<= 1; | ||
1420 | } | ||
1421 | hrate = ivideo->refresh_rate * VT / 2; | ||
1422 | drate = (hrate * HT) / 1000; | ||
1423 | var->pixclock = (u32) (1000000000 / drate); | ||
1424 | |||
1425 | if(ivideo->sisfb_ypan) { | ||
1426 | maxyres = sisfb_calc_maxyres(ivideo, var); | ||
1427 | if(ivideo->sisfb_max) { | ||
1428 | var->yres_virtual = maxyres; | ||
1429 | } else { | ||
1430 | if(var->yres_virtual > maxyres) { | ||
1431 | var->yres_virtual = maxyres; | ||
1432 | } | ||
1433 | } | ||
1434 | if(var->yres_virtual <= var->yres) { | ||
1435 | var->yres_virtual = var->yres; | ||
1436 | } | ||
1437 | } else { | ||
1438 | var->yres_virtual = var->yres; | ||
1439 | } | ||
1440 | |||
1441 | } | ||
1442 | |||
1443 | static int | ||
1444 | sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue, | ||
1445 | unsigned *transp, struct fb_info *info) | ||
1446 | { | 1388 | { |
1447 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; | 1389 | if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { |
1448 | 1390 | orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01); | |
1449 | if(regno >= ivideo->video_cmap_len) return 1; | 1391 | outSISIDXREG(SISPART1, 0x06, (base & 0xFF)); |
1450 | 1392 | outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF)); | |
1451 | *red = ivideo->sis_palette[regno].red; | 1393 | outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF)); |
1452 | *green = ivideo->sis_palette[regno].green; | 1394 | if(ivideo->sisvga_engine == SIS_315_VGA) { |
1453 | *blue = ivideo->sis_palette[regno].blue; | 1395 | setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7); |
1454 | *transp = 0; | ||
1455 | |||
1456 | return 0; | ||
1457 | } | ||
1458 | |||
1459 | static int | ||
1460 | sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, | ||
1461 | unsigned transp, struct fb_info *info) | ||
1462 | { | ||
1463 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; | ||
1464 | |||
1465 | if(regno >= ivideo->video_cmap_len) return 1; | ||
1466 | |||
1467 | ivideo->sis_palette[regno].red = red; | ||
1468 | ivideo->sis_palette[regno].green = green; | ||
1469 | ivideo->sis_palette[regno].blue = blue; | ||
1470 | |||
1471 | switch(ivideo->video_bpp) { | ||
1472 | #ifdef FBCON_HAS_CFB8 | ||
1473 | case 8: | ||
1474 | outSISREG(SISDACA, regno); | ||
1475 | outSISREG(SISDACD, (red >> 10)); | ||
1476 | outSISREG(SISDACD, (green >> 10)); | ||
1477 | outSISREG(SISDACD, (blue >> 10)); | ||
1478 | if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { | ||
1479 | outSISREG(SISDAC2A, regno); | ||
1480 | outSISREG(SISDAC2D, (red >> 8)); | ||
1481 | outSISREG(SISDAC2D, (green >> 8)); | ||
1482 | outSISREG(SISDAC2D, (blue >> 8)); | ||
1483 | } | 1396 | } |
1484 | break; | ||
1485 | #endif | ||
1486 | #ifdef FBCON_HAS_CFB16 | ||
1487 | case 16: | ||
1488 | ivideo->sis_fbcon_cmap.cfb16[regno] = | ||
1489 | ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); | ||
1490 | break; | ||
1491 | #endif | ||
1492 | #ifdef FBCON_HAS_CFB32 | ||
1493 | case 32: | ||
1494 | red >>= 8; | ||
1495 | green >>= 8; | ||
1496 | blue >>= 8; | ||
1497 | ivideo->sis_fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | (blue); | ||
1498 | break; | ||
1499 | #endif | ||
1500 | } | ||
1501 | |||
1502 | return 0; | ||
1503 | } | ||
1504 | |||
1505 | static void | ||
1506 | sisfb_set_disp(int con, struct fb_var_screeninfo *var, struct fb_info *info) | ||
1507 | { | ||
1508 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; | ||
1509 | struct display *display; | ||
1510 | struct display_switch *sw; | ||
1511 | struct fb_fix_screeninfo fix; | ||
1512 | long flags; | ||
1513 | |||
1514 | display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp; | ||
1515 | |||
1516 | sisfb_get_fix(&fix, con, info); | ||
1517 | |||
1518 | display->var = *var; | ||
1519 | display->screen_base = (char *)ivideo->video_vbase; | ||
1520 | display->visual = fix.visual; | ||
1521 | display->type = fix.type; | ||
1522 | display->type_aux = fix.type_aux; | ||
1523 | display->ypanstep = fix.ypanstep; | ||
1524 | display->ywrapstep = fix.ywrapstep; | ||
1525 | display->line_length = fix.line_length; | ||
1526 | display->can_soft_blank = 1; | ||
1527 | display->inverse = ivideo->sisfb_inverse; | ||
1528 | display->next_line = fix.line_length; | ||
1529 | |||
1530 | save_flags(flags); | ||
1531 | |||
1532 | switch(ivideo->video_bpp) { | ||
1533 | #ifdef FBCON_HAS_CFB8 | ||
1534 | case 8: sw = ivideo->accel ? &fbcon_sis8 : &fbcon_cfb8; | ||
1535 | break; | ||
1536 | #endif | ||
1537 | #ifdef FBCON_HAS_CFB16 | ||
1538 | case 16:sw = ivideo->accel ? &fbcon_sis16 : &fbcon_cfb16; | ||
1539 | display->dispsw_data = &ivideo->sis_fbcon_cmap.cfb16; | ||
1540 | break; | ||
1541 | #endif | ||
1542 | #ifdef FBCON_HAS_CFB32 | ||
1543 | case 32:sw = ivideo->accel ? &fbcon_sis32 : &fbcon_cfb32; | ||
1544 | display->dispsw_data = &ivideo->sis_fbcon_cmap.cfb32; | ||
1545 | break; | ||
1546 | #endif | ||
1547 | default:sw = &fbcon_dummy; | ||
1548 | break; | ||
1549 | } | ||
1550 | memcpy(&ivideo->sisfb_sw, sw, sizeof(*sw)); | ||
1551 | display->dispsw = &ivideo->sisfb_sw; | ||
1552 | |||
1553 | restore_flags(flags); | ||
1554 | |||
1555 | if(ivideo->sisfb_ypan) { | ||
1556 | /* display->scrollmode = 0; */ | ||
1557 | } else { | ||
1558 | display->scrollmode = SCROLL_YREDRAW; | ||
1559 | ivideo->sisfb_sw.bmove = fbcon_redraw_bmove; | ||
1560 | } | ||
1561 | } | ||
1562 | |||
1563 | static void | ||
1564 | sisfb_do_install_cmap(int con, struct fb_info *info) | ||
1565 | { | ||
1566 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; | ||
1567 | |||
1568 | if(con != ivideo->currcon) return; | ||
1569 | |||
1570 | if(fb_display[con].cmap.len) { | ||
1571 | fb_set_cmap(&fb_display[con].cmap, 1, sisfb_setcolreg, info); | ||
1572 | } else { | ||
1573 | int size = sisfb_get_cmap_len(&fb_display[con].var); | ||
1574 | fb_set_cmap(fb_default_cmap(size), 1, sisfb_setcolreg, info); | ||
1575 | } | 1397 | } |
1576 | } | 1398 | } |
1577 | 1399 | ||
1578 | static int | 1400 | static int |
1579 | sisfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) | 1401 | sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) |
1580 | { | ||
1581 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; | ||
1582 | |||
1583 | if(con == -1) { | ||
1584 | memcpy(var, &ivideo->default_var, sizeof(struct fb_var_screeninfo)); | ||
1585 | } else { | ||
1586 | *var = fb_display[con].var; | ||
1587 | } | ||
1588 | |||
1589 | if(ivideo->sisfb_fstn) { | ||
1590 | if(var->xres == 320 && var->yres == 480) var->yres = 240; | ||
1591 | } | ||
1592 | |||
1593 | return 0; | ||
1594 | } | ||
1595 | |||
1596 | static int | ||
1597 | sisfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) | ||
1598 | { | 1402 | { |
1599 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; | 1403 | if(var->xoffset > (var->xres_virtual - var->xres)) { |
1600 | int err; | ||
1601 | |||
1602 | fb_display[con].var.activate = FB_ACTIVATE_NOW; | ||
1603 | |||
1604 | if(sisfb_do_set_var(var, con == ivideo->currcon, info)) { | ||
1605 | sisfb_crtc_to_var(ivideo, var); | ||
1606 | return -EINVAL; | 1404 | return -EINVAL; |
1607 | } | 1405 | } |
1608 | 1406 | if(var->yoffset > (var->yres_virtual - var->yres)) { | |
1609 | sisfb_crtc_to_var(ivideo, var); | 1407 | return -EINVAL; |
1610 | |||
1611 | sisfb_set_disp(con, var, info); | ||
1612 | |||
1613 | if(info->changevar) { | ||
1614 | (*info->changevar)(con); | ||
1615 | } | ||
1616 | |||
1617 | if((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0))) { | ||
1618 | return err; | ||
1619 | } | ||
1620 | |||
1621 | sisfb_do_install_cmap(con, info); | ||
1622 | |||
1623 | #if 0 /* Why was this called here? */ | ||
1624 | unsigned int cols, rows; | ||
1625 | cols = sisbios_mode[ivideo->sisfb_mode_idx].cols; | ||
1626 | rows = sisbios_mode[ivideo->sisfb_mode_idx].rows; | ||
1627 | vc_resize_con(rows, cols, fb_display[con].conp->vc_num); | ||
1628 | #endif | ||
1629 | return 0; | ||
1630 | } | ||
1631 | |||
1632 | static int | ||
1633 | sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) | ||
1634 | { | ||
1635 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; | ||
1636 | struct display *display; | ||
1637 | |||
1638 | display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp; | ||
1639 | |||
1640 | if(con == ivideo->currcon) { | ||
1641 | |||
1642 | return fb_get_cmap(cmap, kspc, sis_getcolreg, info); | ||
1643 | |||
1644 | } else if(display->cmap.len) { | ||
1645 | |||
1646 | fb_copy_cmap(&display->cmap, cmap, kspc ? 0 : 2); | ||
1647 | |||
1648 | } else { | ||
1649 | |||
1650 | int size = sisfb_get_cmap_len(&display->var); | ||
1651 | fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2); | ||
1652 | |||
1653 | } | 1408 | } |
1654 | 1409 | ||
1655 | return 0; | 1410 | ivideo->current_base = (var->yoffset * var->xres_virtual) + var->xoffset; |
1656 | } | ||
1657 | 1411 | ||
1658 | static int | 1412 | /* calculate base bpp dep. */ |
1659 | sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) | 1413 | switch(var->bits_per_pixel) { |
1660 | { | 1414 | case 32: |
1661 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; | 1415 | break; |
1662 | struct display *display; | 1416 | case 16: |
1663 | int err, size; | 1417 | ivideo->current_base >>= 1; |
1664 | 1418 | break; | |
1665 | display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp; | 1419 | case 8: |
1666 | 1420 | default: | |
1667 | size = sisfb_get_cmap_len(&display->var); | 1421 | ivideo->current_base >>= 2; |
1668 | if(display->cmap.len != size) { | 1422 | break; |
1669 | err = fb_alloc_cmap(&display->cmap, size, 0); | ||
1670 | if(err) return err; | ||
1671 | } | ||
1672 | |||
1673 | if(con == ivideo->currcon) { | ||
1674 | return fb_set_cmap(cmap, kspc, sisfb_setcolreg, info); | ||
1675 | } else { | ||
1676 | fb_copy_cmap(cmap, &display->cmap, kspc ? 0 : 1); | ||
1677 | } | ||
1678 | |||
1679 | return 0; | ||
1680 | } | ||
1681 | |||
1682 | static int | ||
1683 | sisfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info* info) | ||
1684 | { | ||
1685 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; | ||
1686 | int err; | ||
1687 | |||
1688 | if(var->vmode & FB_VMODE_YWRAP) return -EINVAL; | ||
1689 | |||
1690 | if((var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual) || | ||
1691 | (var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual)) { | ||
1692 | return -EINVAL; | ||
1693 | } | 1423 | } |
1694 | 1424 | ||
1695 | if(con == ivideo->currcon) { | 1425 | ivideo->current_base += (ivideo->video_offset >> 2); |
1696 | if((err = sisfb_pan_var(ivideo, var)) < 0) return err; | ||
1697 | } | ||
1698 | 1426 | ||
1699 | fb_display[con].var.xoffset = var->xoffset; | 1427 | sisfb_set_base_CRT1(ivideo, ivideo->current_base); |
1700 | fb_display[con].var.yoffset = var->yoffset; | 1428 | sisfb_set_base_CRT2(ivideo, ivideo->current_base); |
1701 | 1429 | ||
1702 | return 0; | 1430 | return 0; |
1703 | } | 1431 | } |
1704 | 1432 | ||
1705 | static int | 1433 | /* ------------ FBDev related routines for 2.4 series ----------- */ |
1706 | sisfb_update_var(int con, struct fb_info *info) | ||
1707 | { | ||
1708 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; | ||
1709 | |||
1710 | return(sisfb_pan_var(ivideo, &fb_display[con].var)); | ||
1711 | } | ||
1712 | |||
1713 | static int | ||
1714 | sisfb_switch(int con, struct fb_info *info) | ||
1715 | { | ||
1716 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; | ||
1717 | int cols, rows; | ||
1718 | |||
1719 | if(fb_display[ivideo->currcon].cmap.len) { | ||
1720 | fb_get_cmap(&fb_display[ivideo->currcon].cmap, 1, sis_getcolreg, info); | ||
1721 | } | ||
1722 | |||
1723 | fb_display[con].var.activate = FB_ACTIVATE_NOW; | ||
1724 | |||
1725 | if(!memcmp(&fb_display[con].var, &fb_display[ivideo->currcon].var, | ||
1726 | sizeof(struct fb_var_screeninfo))) { | ||
1727 | ivideo->currcon = con; | ||
1728 | return 1; | ||
1729 | } | ||
1730 | |||
1731 | ivideo->currcon = con; | ||
1732 | |||
1733 | sisfb_do_set_var(&fb_display[con].var, 1, info); | ||
1734 | |||
1735 | sisfb_set_disp(con, &fb_display[con].var, info); | ||
1736 | |||
1737 | sisfb_do_install_cmap(con, info); | ||
1738 | |||
1739 | cols = sisbios_mode[ivideo->sisfb_mode_idx].cols; | ||
1740 | rows = sisbios_mode[ivideo->sisfb_mode_idx].rows; | ||
1741 | vc_resize_con(rows, cols, fb_display[con].conp->vc_num); | ||
1742 | |||
1743 | sisfb_update_var(con, info); | ||
1744 | 1434 | ||
1745 | return 1; | 1435 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) |
1746 | } | ||
1747 | 1436 | ||
1748 | static void | 1437 | #include "sisfb_fbdev_2_4.h" |
1749 | sisfb_blank(int blank, struct fb_info *info) | ||
1750 | { | ||
1751 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; | ||
1752 | 1438 | ||
1753 | sisfb_myblank(ivideo, blank); | ||
1754 | } | ||
1755 | #endif | 1439 | #endif |
1756 | 1440 | ||
1757 | /* ------------ FBDev related routines for 2.6 series ----------- */ | 1441 | /* ------------ FBDev related routines for 2.6 series ----------- */ |
@@ -1761,13 +1445,13 @@ sisfb_blank(int blank, struct fb_info *info) | |||
1761 | static int | 1445 | static int |
1762 | sisfb_open(struct fb_info *info, int user) | 1446 | sisfb_open(struct fb_info *info, int user) |
1763 | { | 1447 | { |
1764 | return 0; | 1448 | return 0; |
1765 | } | 1449 | } |
1766 | 1450 | ||
1767 | static int | 1451 | static int |
1768 | sisfb_release(struct fb_info *info, int user) | 1452 | sisfb_release(struct fb_info *info, int user) |
1769 | { | 1453 | { |
1770 | return 0; | 1454 | return 0; |
1771 | } | 1455 | } |
1772 | 1456 | ||
1773 | static int | 1457 | static int |
@@ -1776,16 +1460,17 @@ sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, | |||
1776 | { | 1460 | { |
1777 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; | 1461 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; |
1778 | 1462 | ||
1779 | if(regno >= sisfb_get_cmap_len(&info->var)) return 1; | 1463 | if(regno >= sisfb_get_cmap_len(&info->var)) |
1464 | return 1; | ||
1780 | 1465 | ||
1781 | switch(info->var.bits_per_pixel) { | 1466 | switch(info->var.bits_per_pixel) { |
1782 | case 8: | 1467 | case 8: |
1783 | outSISREG(SISDACA, regno); | 1468 | outSISREG(SISDACA, regno); |
1784 | outSISREG(SISDACD, (red >> 10)); | 1469 | outSISREG(SISDACD, (red >> 10)); |
1785 | outSISREG(SISDACD, (green >> 10)); | 1470 | outSISREG(SISDACD, (green >> 10)); |
1786 | outSISREG(SISDACD, (blue >> 10)); | 1471 | outSISREG(SISDACD, (blue >> 10)); |
1787 | if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { | 1472 | if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { |
1788 | outSISREG(SISDAC2A, regno); | 1473 | outSISREG(SISDAC2A, regno); |
1789 | outSISREG(SISDAC2D, (red >> 8)); | 1474 | outSISREG(SISDAC2D, (red >> 8)); |
1790 | outSISREG(SISDAC2D, (green >> 8)); | 1475 | outSISREG(SISDAC2D, (green >> 8)); |
1791 | outSISREG(SISDAC2D, (blue >> 8)); | 1476 | outSISREG(SISDAC2D, (blue >> 8)); |
@@ -1793,7 +1478,9 @@ sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, | |||
1793 | break; | 1478 | break; |
1794 | case 16: | 1479 | case 16: |
1795 | ((u32 *)(info->pseudo_palette))[regno] = | 1480 | ((u32 *)(info->pseudo_palette))[regno] = |
1796 | ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); | 1481 | (red & 0xf800) | |
1482 | ((green & 0xfc00) >> 5) | | ||
1483 | ((blue & 0xf800) >> 11); | ||
1797 | break; | 1484 | break; |
1798 | case 32: | 1485 | case 32: |
1799 | red >>= 8; | 1486 | red >>= 8; |
@@ -1811,13 +1498,13 @@ sisfb_set_par(struct fb_info *info) | |||
1811 | { | 1498 | { |
1812 | int err; | 1499 | int err; |
1813 | 1500 | ||
1814 | if((err = sisfb_do_set_var(&info->var, 1, info))) { | 1501 | if((err = sisfb_do_set_var(&info->var, 1, info))) |
1815 | return err; | 1502 | return err; |
1816 | } | 1503 | |
1817 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) | 1504 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) |
1818 | sisfb_get_fix(&info->fix, info->currcon, info); | 1505 | sisfb_get_fix(&info->fix, info->currcon, info); |
1819 | #else | 1506 | #else |
1820 | sisfb_get_fix(&info->fix, -1, info); | 1507 | sisfb_get_fix(&info->fix, -1, info); |
1821 | #endif | 1508 | #endif |
1822 | return 0; | 1509 | return 0; |
1823 | } | 1510 | } |
@@ -1829,7 +1516,7 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
1829 | unsigned int htotal = 0, vtotal = 0, myrateindex = 0; | 1516 | unsigned int htotal = 0, vtotal = 0, myrateindex = 0; |
1830 | unsigned int drate = 0, hrate = 0, maxyres; | 1517 | unsigned int drate = 0, hrate = 0, maxyres; |
1831 | int found_mode = 0; | 1518 | int found_mode = 0; |
1832 | int refresh_rate, search_idx; | 1519 | int refresh_rate, search_idx, tidx; |
1833 | BOOLEAN recalc_clock = FALSE; | 1520 | BOOLEAN recalc_clock = FALSE; |
1834 | u32 pixclock; | 1521 | u32 pixclock; |
1835 | 1522 | ||
@@ -1848,7 +1535,8 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
1848 | } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { | 1535 | } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { |
1849 | vtotal += var->yres; | 1536 | vtotal += var->yres; |
1850 | vtotal <<= 1; | 1537 | vtotal <<= 1; |
1851 | } else vtotal += var->yres; | 1538 | } else |
1539 | vtotal += var->yres; | ||
1852 | 1540 | ||
1853 | if(!(htotal) || !(vtotal)) { | 1541 | if(!(htotal) || !(vtotal)) { |
1854 | SISFAIL("sisfb: no valid timing data"); | 1542 | SISFAIL("sisfb: no valid timing data"); |
@@ -1860,60 +1548,68 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
1860 | if( (sisbios_mode[search_idx].xres == var->xres) && | 1548 | if( (sisbios_mode[search_idx].xres == var->xres) && |
1861 | (sisbios_mode[search_idx].yres == var->yres) && | 1549 | (sisbios_mode[search_idx].yres == var->yres) && |
1862 | (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) { | 1550 | (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) { |
1863 | if(sisfb_validate_mode(ivideo, search_idx, ivideo->currentvbflags) > 0) { | 1551 | if((tidx = sisfb_validate_mode(ivideo, search_idx, |
1864 | found_mode = 1; | 1552 | ivideo->currentvbflags)) > 0) { |
1865 | break; | 1553 | found_mode = 1; |
1554 | search_idx = tidx; | ||
1555 | break; | ||
1866 | } | 1556 | } |
1867 | } | 1557 | } |
1868 | search_idx++; | 1558 | search_idx++; |
1869 | } | 1559 | } |
1870 | 1560 | ||
1871 | if(!found_mode) { | 1561 | if(!found_mode) { |
1872 | search_idx = 0; | 1562 | search_idx = 0; |
1873 | while(sisbios_mode[search_idx].mode_no[0] != 0) { | 1563 | while(sisbios_mode[search_idx].mode_no[0] != 0) { |
1874 | if( (var->xres <= sisbios_mode[search_idx].xres) && | 1564 | if( (var->xres <= sisbios_mode[search_idx].xres) && |
1875 | (var->yres <= sisbios_mode[search_idx].yres) && | 1565 | (var->yres <= sisbios_mode[search_idx].yres) && |
1876 | (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) { | 1566 | (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) { |
1877 | if(sisfb_validate_mode(ivideo,search_idx, ivideo->currentvbflags) > 0) { | 1567 | if((tidx = sisfb_validate_mode(ivideo,search_idx, |
1878 | found_mode = 1; | 1568 | ivideo->currentvbflags)) > 0) { |
1879 | break; | 1569 | found_mode = 1; |
1880 | } | 1570 | search_idx = tidx; |
1571 | break; | ||
1572 | } | ||
1881 | } | 1573 | } |
1882 | search_idx++; | 1574 | search_idx++; |
1883 | } | 1575 | } |
1884 | if(found_mode) { | 1576 | if(found_mode) { |
1885 | printk(KERN_DEBUG "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n", | 1577 | printk(KERN_DEBUG |
1886 | var->xres, var->yres, var->bits_per_pixel, | 1578 | "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n", |
1579 | var->xres, var->yres, var->bits_per_pixel, | ||
1887 | sisbios_mode[search_idx].xres, | 1580 | sisbios_mode[search_idx].xres, |
1888 | sisbios_mode[search_idx].yres, | 1581 | sisbios_mode[search_idx].yres, |
1889 | var->bits_per_pixel); | 1582 | var->bits_per_pixel); |
1890 | var->xres = sisbios_mode[search_idx].xres; | 1583 | var->xres = sisbios_mode[search_idx].xres; |
1891 | var->yres = sisbios_mode[search_idx].yres; | 1584 | var->yres = sisbios_mode[search_idx].yres; |
1892 | |||
1893 | |||
1894 | } else { | 1585 | } else { |
1895 | printk(KERN_ERR "sisfb: Failed to find supported mode near %dx%dx%d\n", | 1586 | printk(KERN_ERR |
1587 | "sisfb: Failed to find supported mode near %dx%dx%d\n", | ||
1896 | var->xres, var->yres, var->bits_per_pixel); | 1588 | var->xres, var->yres, var->bits_per_pixel); |
1897 | return -EINVAL; | 1589 | return -EINVAL; |
1898 | } | 1590 | } |
1899 | } | 1591 | } |
1900 | 1592 | ||
1901 | if( ((ivideo->vbflags & VB_LVDS) || /* Slave modes on LVDS and 301B-DH */ | 1593 | if( ((ivideo->vbflags2 & VB2_LVDS) || |
1902 | ((ivideo->vbflags & VB_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) && | 1594 | ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) && |
1903 | (var->bits_per_pixel == 8) ) { | 1595 | (var->bits_per_pixel == 8) ) { |
1904 | refresh_rate = 60; | 1596 | /* Slave modes on LVDS and 301B-DH */ |
1597 | refresh_rate = 60; | ||
1905 | recalc_clock = TRUE; | 1598 | recalc_clock = TRUE; |
1906 | } else if( (ivideo->current_htotal == htotal) && /* x=x & y=y & c=c -> assume depth change */ | 1599 | } else if( (ivideo->current_htotal == htotal) && |
1907 | (ivideo->current_vtotal == vtotal) && | 1600 | (ivideo->current_vtotal == vtotal) && |
1908 | (ivideo->current_pixclock == pixclock) ) { | 1601 | (ivideo->current_pixclock == pixclock) ) { |
1602 | /* x=x & y=y & c=c -> assume depth change */ | ||
1909 | drate = 1000000000 / pixclock; | 1603 | drate = 1000000000 / pixclock; |
1910 | hrate = (drate * 1000) / htotal; | 1604 | hrate = (drate * 1000) / htotal; |
1911 | refresh_rate = (unsigned int) (hrate * 2 / vtotal); | 1605 | refresh_rate = (unsigned int) (hrate * 2 / vtotal); |
1912 | } else if( ( (ivideo->current_htotal != htotal) || /* x!=x | y!=y & c=c -> invalid pixclock */ | 1606 | } else if( ( (ivideo->current_htotal != htotal) || |
1913 | (ivideo->current_vtotal != vtotal) ) && | 1607 | (ivideo->current_vtotal != vtotal) ) && |
1914 | (ivideo->current_pixclock == var->pixclock) ) { | 1608 | (ivideo->current_pixclock == var->pixclock) ) { |
1609 | /* x!=x | y!=y & c=c -> invalid pixclock */ | ||
1915 | if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) { | 1610 | if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) { |
1916 | refresh_rate = ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]; | 1611 | refresh_rate = |
1612 | ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]; | ||
1917 | } else if(ivideo->sisfb_parm_rate != -1) { | 1613 | } else if(ivideo->sisfb_parm_rate != -1) { |
1918 | /* Sic, sisfb_parm_rate - want to know originally desired rate here */ | 1614 | /* Sic, sisfb_parm_rate - want to know originally desired rate here */ |
1919 | refresh_rate = ivideo->sisfb_parm_rate; | 1615 | refresh_rate = ivideo->sisfb_parm_rate; |
@@ -1923,8 +1619,8 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
1923 | recalc_clock = TRUE; | 1619 | recalc_clock = TRUE; |
1924 | } else if((pixclock) && (htotal) && (vtotal)) { | 1620 | } else if((pixclock) && (htotal) && (vtotal)) { |
1925 | drate = 1000000000 / pixclock; | 1621 | drate = 1000000000 / pixclock; |
1926 | hrate = (drate * 1000) / htotal; | 1622 | hrate = (drate * 1000) / htotal; |
1927 | refresh_rate = (unsigned int) (hrate * 2 / vtotal); | 1623 | refresh_rate = (unsigned int) (hrate * 2 / vtotal); |
1928 | } else if(ivideo->current_refresh_rate) { | 1624 | } else if(ivideo->current_refresh_rate) { |
1929 | refresh_rate = ivideo->current_refresh_rate; | 1625 | refresh_rate = ivideo->current_refresh_rate; |
1930 | recalc_clock = TRUE; | 1626 | recalc_clock = TRUE; |
@@ -1937,72 +1633,72 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
1937 | 1633 | ||
1938 | /* Eventually recalculate timing and clock */ | 1634 | /* Eventually recalculate timing and clock */ |
1939 | if(recalc_clock) { | 1635 | if(recalc_clock) { |
1940 | if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx; | 1636 | if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx; |
1941 | var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, | 1637 | var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, |
1942 | &ivideo->sishw_ext, | ||
1943 | sisbios_mode[search_idx].mode_no[ivideo->mni], | 1638 | sisbios_mode[search_idx].mode_no[ivideo->mni], |
1944 | myrateindex)); | 1639 | myrateindex)); |
1945 | sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, &ivideo->sishw_ext, | 1640 | sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, |
1946 | sisbios_mode[search_idx].mode_no[ivideo->mni], myrateindex, var); | 1641 | sisbios_mode[search_idx].mode_no[ivideo->mni], |
1947 | if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { | 1642 | myrateindex, var); |
1948 | var->pixclock <<= 1; | 1643 | if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { |
1949 | } | 1644 | var->pixclock <<= 1; |
1645 | } | ||
1950 | } | 1646 | } |
1951 | 1647 | ||
1952 | if(ivideo->sisfb_thismonitor.datavalid) { | 1648 | if(ivideo->sisfb_thismonitor.datavalid) { |
1953 | if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx, | 1649 | if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx, |
1954 | myrateindex, refresh_rate)) { | 1650 | myrateindex, refresh_rate)) { |
1955 | printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n"); | 1651 | printk(KERN_INFO |
1956 | } | 1652 | "sisfb: WARNING: Refresh rate exceeds monitor specs!\n"); |
1653 | } | ||
1957 | } | 1654 | } |
1958 | 1655 | ||
1959 | /* Adapt RGB settings */ | 1656 | /* Adapt RGB settings */ |
1960 | sisfb_bpp_to_var(ivideo, var); | 1657 | sisfb_bpp_to_var(ivideo, var); |
1961 | 1658 | ||
1962 | /* Sanity check for offsets */ | 1659 | /* Sanity check for offsets */ |
1963 | if(var->xoffset < 0) var->xoffset = 0; | 1660 | if(var->xoffset < 0) var->xoffset = 0; |
1964 | if(var->yoffset < 0) var->yoffset = 0; | 1661 | if(var->yoffset < 0) var->yoffset = 0; |
1965 | 1662 | ||
1966 | if(var->xres > var->xres_virtual) { | 1663 | if(var->xres > var->xres_virtual) |
1967 | var->xres_virtual = var->xres; | 1664 | var->xres_virtual = var->xres; |
1968 | } | ||
1969 | 1665 | ||
1970 | if(ivideo->sisfb_ypan) { | 1666 | if(ivideo->sisfb_ypan) { |
1971 | maxyres = sisfb_calc_maxyres(ivideo, var); | 1667 | maxyres = sisfb_calc_maxyres(ivideo, var); |
1972 | if(ivideo->sisfb_max) { | 1668 | if(ivideo->sisfb_max) { |
1973 | var->yres_virtual = maxyres; | 1669 | var->yres_virtual = maxyres; |
1974 | } else { | 1670 | } else { |
1975 | if(var->yres_virtual > maxyres) { | 1671 | if(var->yres_virtual > maxyres) { |
1976 | var->yres_virtual = maxyres; | 1672 | var->yres_virtual = maxyres; |
1977 | } | 1673 | } |
1978 | } | 1674 | } |
1979 | if(var->yres_virtual <= var->yres) { | 1675 | if(var->yres_virtual <= var->yres) { |
1980 | var->yres_virtual = var->yres; | 1676 | var->yres_virtual = var->yres; |
1981 | } | 1677 | } |
1982 | } else { | 1678 | } else { |
1983 | if(var->yres != var->yres_virtual) { | 1679 | if(var->yres != var->yres_virtual) { |
1984 | var->yres_virtual = var->yres; | 1680 | var->yres_virtual = var->yres; |
1985 | } | 1681 | } |
1986 | var->xoffset = 0; | 1682 | var->xoffset = 0; |
1987 | var->yoffset = 0; | 1683 | var->yoffset = 0; |
1988 | } | 1684 | } |
1989 | 1685 | ||
1990 | /* Truncate offsets to maximum if too high */ | 1686 | /* Truncate offsets to maximum if too high */ |
1991 | if(var->xoffset > var->xres_virtual - var->xres) { | 1687 | if(var->xoffset > var->xres_virtual - var->xres) { |
1992 | var->xoffset = var->xres_virtual - var->xres - 1; | 1688 | var->xoffset = var->xres_virtual - var->xres - 1; |
1993 | } | 1689 | } |
1994 | 1690 | ||
1995 | if(var->yoffset > var->yres_virtual - var->yres) { | 1691 | if(var->yoffset > var->yres_virtual - var->yres) { |
1996 | var->yoffset = var->yres_virtual - var->yres - 1; | 1692 | var->yoffset = var->yres_virtual - var->yres - 1; |
1997 | } | 1693 | } |
1998 | 1694 | ||
1999 | /* Set everything else to 0 */ | 1695 | /* Set everything else to 0 */ |
2000 | var->red.msb_right = | 1696 | var->red.msb_right = |
2001 | var->green.msb_right = | 1697 | var->green.msb_right = |
2002 | var->blue.msb_right = | 1698 | var->blue.msb_right = |
2003 | var->transp.offset = | 1699 | var->transp.offset = |
2004 | var->transp.length = | 1700 | var->transp.length = |
2005 | var->transp.msb_right = 0; | 1701 | var->transp.msb_right = 0; |
2006 | 1702 | ||
2007 | return 0; | 1703 | return 0; |
2008 | } | 1704 | } |
@@ -2013,21 +1709,21 @@ sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info) | |||
2013 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; | 1709 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; |
2014 | int err; | 1710 | int err; |
2015 | 1711 | ||
2016 | if(var->xoffset > (var->xres_virtual - var->xres)) { | 1712 | if(var->xoffset > (var->xres_virtual - var->xres)) |
2017 | return -EINVAL; | 1713 | return -EINVAL; |
2018 | } | 1714 | |
2019 | if(var->yoffset > (var->yres_virtual - var->yres)) { | 1715 | if(var->yoffset > (var->yres_virtual - var->yres)) |
2020 | return -EINVAL; | 1716 | return -EINVAL; |
2021 | } | ||
2022 | 1717 | ||
2023 | if(var->vmode & FB_VMODE_YWRAP) return -EINVAL; | 1718 | if(var->vmode & FB_VMODE_YWRAP) |
1719 | return -EINVAL; | ||
2024 | 1720 | ||
2025 | if(var->xoffset + info->var.xres > info->var.xres_virtual || | 1721 | if(var->xoffset + info->var.xres > info->var.xres_virtual || |
2026 | var->yoffset + info->var.yres > info->var.yres_virtual) { | 1722 | var->yoffset + info->var.yres > info->var.yres_virtual) |
2027 | return -EINVAL; | 1723 | return -EINVAL; |
2028 | } | ||
2029 | 1724 | ||
2030 | if((err = sisfb_pan_var(ivideo, var)) < 0) return err; | 1725 | if((err = sisfb_pan_var(ivideo, var)) < 0) |
1726 | return err; | ||
2031 | 1727 | ||
2032 | info->var.xoffset = var->xoffset; | 1728 | info->var.xoffset = var->xoffset; |
2033 | info->var.yoffset = var->yoffset; | 1729 | info->var.yoffset = var->yoffset; |
@@ -2040,7 +1736,7 @@ sisfb_blank(int blank, struct fb_info *info) | |||
2040 | { | 1736 | { |
2041 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; | 1737 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; |
2042 | 1738 | ||
2043 | return(sisfb_myblank(ivideo, blank)); | 1739 | return sisfb_myblank(ivideo, blank); |
2044 | } | 1740 | } |
2045 | 1741 | ||
2046 | #endif | 1742 | #endif |
@@ -2056,153 +1752,184 @@ sisfb_ioctl(struct inode *inode, struct file *file, | |||
2056 | struct fb_info *info) | 1752 | struct fb_info *info) |
2057 | { | 1753 | { |
2058 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; | 1754 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; |
2059 | struct sis_memreq sismemreq; | 1755 | struct sis_memreq sismemreq; |
2060 | struct fb_vblank sisvbblank; | 1756 | struct fb_vblank sisvbblank; |
2061 | sisfb_info x; | ||
2062 | u32 gpu32 = 0; | 1757 | u32 gpu32 = 0; |
2063 | #ifndef __user | 1758 | #ifndef __user |
2064 | #define __user | 1759 | #define __user |
2065 | #endif | 1760 | #endif |
2066 | u32 __user *argp = (u32 __user *)arg; | 1761 | u32 __user *argp = (u32 __user *)arg; |
2067 | 1762 | ||
2068 | switch (cmd) { | 1763 | switch(cmd) { |
2069 | case FBIO_ALLOC: | 1764 | case FBIO_ALLOC: |
2070 | if(!capable(CAP_SYS_RAWIO)) { | 1765 | if(!capable(CAP_SYS_RAWIO)) |
2071 | return -EPERM; | 1766 | return -EPERM; |
2072 | } | 1767 | |
2073 | if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq))) { | 1768 | if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq))) |
2074 | return -EFAULT; | 1769 | return -EFAULT; |
2075 | } | 1770 | |
2076 | sis_malloc(&sismemreq); | 1771 | sis_malloc(&sismemreq); |
1772 | |||
2077 | if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) { | 1773 | if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) { |
2078 | sis_free((u32)sismemreq.offset); | 1774 | sis_free((u32)sismemreq.offset); |
2079 | return -EFAULT; | 1775 | return -EFAULT; |
2080 | } | 1776 | } |
2081 | break; | 1777 | break; |
2082 | 1778 | ||
2083 | case FBIO_FREE: | 1779 | case FBIO_FREE: |
2084 | if(!capable(CAP_SYS_RAWIO)) { | 1780 | if(!capable(CAP_SYS_RAWIO)) |
2085 | return -EPERM; | 1781 | return -EPERM; |
2086 | } | 1782 | |
2087 | if(get_user(gpu32, argp)) { | 1783 | if(get_user(gpu32, argp)) |
2088 | return -EFAULT; | 1784 | return -EFAULT; |
2089 | } | 1785 | |
2090 | sis_free(gpu32); | 1786 | sis_free(gpu32); |
2091 | break; | 1787 | break; |
2092 | 1788 | ||
2093 | case FBIOGET_VBLANK: | 1789 | case FBIOGET_VBLANK: |
2094 | sisvbblank.count = 0; | 1790 | sisvbblank.count = 0; |
2095 | sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount); | 1791 | sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount); |
2096 | if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank))) { | 1792 | |
1793 | if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank))) | ||
2097 | return -EFAULT; | 1794 | return -EFAULT; |
2098 | } | 1795 | |
2099 | break; | 1796 | break; |
2100 | 1797 | ||
2101 | case SISFB_GET_INFO_SIZE: | 1798 | case SISFB_GET_INFO_SIZE: |
2102 | return put_user(sizeof(sisfb_info), argp); | 1799 | return put_user(sizeof(struct sisfb_info), argp); |
2103 | 1800 | ||
2104 | case SISFB_GET_INFO_OLD: | 1801 | case SISFB_GET_INFO_OLD: |
2105 | if(ivideo->warncount++ < 50) { | 1802 | if(ivideo->warncount++ < 10) |
2106 | printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n"); | 1803 | printk(KERN_INFO |
2107 | } | 1804 | "sisfb: Deprecated ioctl call received - update your application!\n"); |
2108 | case SISFB_GET_INFO: /* For communication with X driver */ | 1805 | case SISFB_GET_INFO: /* For communication with X driver */ |
2109 | x.sisfb_id = SISFB_ID; | 1806 | ivideo->sisfb_infoblock.sisfb_id = SISFB_ID; |
2110 | x.sisfb_version = VER_MAJOR; | 1807 | ivideo->sisfb_infoblock.sisfb_version = VER_MAJOR; |
2111 | x.sisfb_revision = VER_MINOR; | 1808 | ivideo->sisfb_infoblock.sisfb_revision = VER_MINOR; |
2112 | x.sisfb_patchlevel = VER_LEVEL; | 1809 | ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL; |
2113 | x.chip_id = ivideo->chip_id; | 1810 | ivideo->sisfb_infoblock.chip_id = ivideo->chip_id; |
2114 | x.memory = ivideo->video_size / 1024; | 1811 | ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor; |
2115 | x.heapstart = ivideo->heapstart / 1024; | 1812 | ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024; |
1813 | ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024; | ||
2116 | if(ivideo->modechanged) { | 1814 | if(ivideo->modechanged) { |
2117 | x.fbvidmode = ivideo->mode_no; | 1815 | ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no; |
2118 | } else { | 1816 | } else { |
2119 | x.fbvidmode = ivideo->modeprechange; | 1817 | ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange; |
2120 | } | ||
2121 | x.sisfb_caps = ivideo->caps; | ||
2122 | x.sisfb_tqlen = 512; /* yet fixed */ | ||
2123 | x.sisfb_pcibus = ivideo->pcibus; | ||
2124 | x.sisfb_pcislot = ivideo->pcislot; | ||
2125 | x.sisfb_pcifunc = ivideo->pcifunc; | ||
2126 | x.sisfb_lcdpdc = ivideo->detectedpdc; | ||
2127 | x.sisfb_lcdpdca = ivideo->detectedpdca; | ||
2128 | x.sisfb_lcda = ivideo->detectedlcda; | ||
2129 | x.sisfb_vbflags = ivideo->vbflags; | ||
2130 | x.sisfb_currentvbflags = ivideo->currentvbflags; | ||
2131 | x.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler; | ||
2132 | x.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT; | ||
2133 | x.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0; | ||
2134 | x.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0; | ||
2135 | x.sisfb_emi30 = ivideo->SiS_Pr.EMI_30; | ||
2136 | x.sisfb_emi31 = ivideo->SiS_Pr.EMI_31; | ||
2137 | x.sisfb_emi32 = ivideo->SiS_Pr.EMI_32; | ||
2138 | x.sisfb_emi33 = ivideo->SiS_Pr.EMI_33; | ||
2139 | x.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32); | ||
2140 | x.sisfb_tvypos = (u16)(ivideo->tvypos + 32); | ||
2141 | |||
2142 | if(copy_to_user((void __user *)arg, &x, sizeof(x))) { | ||
2143 | return -EFAULT; | ||
2144 | } | 1818 | } |
1819 | ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps; | ||
1820 | ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024; | ||
1821 | ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus; | ||
1822 | ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot; | ||
1823 | ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc; | ||
1824 | ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc; | ||
1825 | ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca; | ||
1826 | ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda; | ||
1827 | ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags; | ||
1828 | ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags; | ||
1829 | ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler; | ||
1830 | ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT; | ||
1831 | ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0; | ||
1832 | ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0; | ||
1833 | ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30; | ||
1834 | ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31; | ||
1835 | ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32; | ||
1836 | ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33; | ||
1837 | ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32); | ||
1838 | ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32); | ||
1839 | ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024; | ||
1840 | ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset; | ||
1841 | ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN; | ||
1842 | ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN; | ||
1843 | ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2; | ||
1844 | ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0; | ||
1845 | ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0; | ||
1846 | ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0; | ||
1847 | |||
1848 | if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock, | ||
1849 | sizeof(ivideo->sisfb_infoblock))) | ||
1850 | return -EFAULT; | ||
1851 | |||
2145 | break; | 1852 | break; |
2146 | 1853 | ||
2147 | case SISFB_GET_VBRSTATUS_OLD: | 1854 | case SISFB_GET_VBRSTATUS_OLD: |
2148 | if(ivideo->warncount++ < 50) { | 1855 | if(ivideo->warncount++ < 10) |
2149 | printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n"); | 1856 | printk(KERN_INFO |
2150 | } | 1857 | "sisfb: Deprecated ioctl call received - update your application!\n"); |
2151 | case SISFB_GET_VBRSTATUS: | 1858 | case SISFB_GET_VBRSTATUS: |
2152 | if(sisfb_CheckVBRetrace(ivideo)) { | 1859 | if(sisfb_CheckVBRetrace(ivideo)) |
2153 | return put_user((u32)1, argp); | 1860 | return put_user((u32)1, argp); |
2154 | } else { | 1861 | else |
2155 | return put_user((u32)0, argp); | 1862 | return put_user((u32)0, argp); |
2156 | } | ||
2157 | 1863 | ||
2158 | case SISFB_GET_AUTOMAXIMIZE_OLD: | 1864 | case SISFB_GET_AUTOMAXIMIZE_OLD: |
2159 | if(ivideo->warncount++ < 50) { | 1865 | if(ivideo->warncount++ < 10) |
2160 | printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n"); | 1866 | printk(KERN_INFO |
2161 | } | 1867 | "sisfb: Deprecated ioctl call received - update your application!\n"); |
2162 | case SISFB_GET_AUTOMAXIMIZE: | 1868 | case SISFB_GET_AUTOMAXIMIZE: |
2163 | if(ivideo->sisfb_max) return put_user((u32)1, argp); | 1869 | if(ivideo->sisfb_max) |
2164 | else return put_user((u32)0, argp); | 1870 | return put_user((u32)1, argp); |
1871 | else | ||
1872 | return put_user((u32)0, argp); | ||
2165 | 1873 | ||
2166 | case SISFB_SET_AUTOMAXIMIZE_OLD: | 1874 | case SISFB_SET_AUTOMAXIMIZE_OLD: |
2167 | if(ivideo->warncount++ < 50) { | 1875 | if(ivideo->warncount++ < 10) |
2168 | printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n"); | 1876 | printk(KERN_INFO |
2169 | } | 1877 | "sisfb: Deprecated ioctl call received - update your application!\n"); |
2170 | case SISFB_SET_AUTOMAXIMIZE: | 1878 | case SISFB_SET_AUTOMAXIMIZE: |
2171 | if(copy_from_user(&gpu32, argp, sizeof(gpu32))) { | 1879 | if(get_user(gpu32, argp)) |
2172 | return -EFAULT; | 1880 | return -EFAULT; |
2173 | } | 1881 | |
2174 | ivideo->sisfb_max = (gpu32) ? 1 : 0; | 1882 | ivideo->sisfb_max = (gpu32) ? 1 : 0; |
2175 | break; | 1883 | break; |
2176 | 1884 | ||
2177 | case SISFB_SET_TVPOSOFFSET: | 1885 | case SISFB_SET_TVPOSOFFSET: |
2178 | if(copy_from_user(&gpu32, argp, sizeof(gpu32))) { | 1886 | if(get_user(gpu32, argp)) |
2179 | return -EFAULT; | 1887 | return -EFAULT; |
2180 | } | 1888 | |
2181 | sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32); | 1889 | sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32); |
2182 | sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32); | 1890 | sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32); |
2183 | break; | 1891 | break; |
2184 | 1892 | ||
2185 | case SISFB_GET_TVPOSOFFSET: | 1893 | case SISFB_GET_TVPOSOFFSET: |
2186 | return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)), | 1894 | return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)), |
2187 | argp); | 1895 | argp); |
1896 | |||
1897 | case SISFB_COMMAND: | ||
1898 | if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg, | ||
1899 | sizeof(struct sisfb_cmd))) | ||
1900 | return -EFAULT; | ||
1901 | |||
1902 | sisfb_handle_command(ivideo, &ivideo->sisfb_command); | ||
1903 | |||
1904 | if(copy_to_user((void __user *)arg, &ivideo->sisfb_command, | ||
1905 | sizeof(struct sisfb_cmd))) | ||
1906 | return -EFAULT; | ||
1907 | |||
1908 | break; | ||
2188 | 1909 | ||
2189 | case SISFB_SET_LOCK: | 1910 | case SISFB_SET_LOCK: |
2190 | if(copy_from_user(&gpu32, argp, sizeof(gpu32))) { | 1911 | if(get_user(gpu32, argp)) |
2191 | return -EFAULT; | 1912 | return -EFAULT; |
2192 | } | 1913 | |
2193 | ivideo->sisfblocked = (gpu32) ? 1 : 0; | 1914 | ivideo->sisfblocked = (gpu32) ? 1 : 0; |
2194 | break; | 1915 | break; |
2195 | 1916 | ||
2196 | default: | 1917 | default: |
1918 | #ifdef SIS_NEW_CONFIG_COMPAT | ||
2197 | return -ENOIOCTLCMD; | 1919 | return -ENOIOCTLCMD; |
1920 | #else | ||
1921 | return -EINVAL; | ||
1922 | #endif | ||
2198 | } | 1923 | } |
2199 | return 0; | 1924 | return 0; |
2200 | } | 1925 | } |
2201 | 1926 | ||
2202 | #ifdef CONFIG_COMPAT | 1927 | #ifdef SIS_NEW_CONFIG_COMPAT |
2203 | static long sisfb_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg, struct fb_info *info) | 1928 | static long |
1929 | sisfb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg, struct fb_info *info) | ||
2204 | { | 1930 | { |
2205 | int ret; | 1931 | int ret; |
1932 | |||
2206 | lock_kernel(); | 1933 | lock_kernel(); |
2207 | ret = sisfb_ioctl(NULL, f, cmd, arg, info); | 1934 | ret = sisfb_ioctl(NULL, f, cmd, arg, info); |
2208 | unlock_kernel(); | 1935 | unlock_kernel(); |
@@ -2219,7 +1946,7 @@ sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) | |||
2219 | 1946 | ||
2220 | strcpy(fix->id, ivideo->myid); | 1947 | strcpy(fix->id, ivideo->myid); |
2221 | 1948 | ||
2222 | fix->smem_start = ivideo->video_base; | 1949 | fix->smem_start = ivideo->video_base + ivideo->video_offset; |
2223 | fix->smem_len = ivideo->sisfb_mem; | 1950 | fix->smem_len = ivideo->sisfb_mem; |
2224 | fix->type = FB_TYPE_PACKED_PIXELS; | 1951 | fix->type = FB_TYPE_PACKED_PIXELS; |
2225 | fix->type_aux = 0; | 1952 | fix->type_aux = 0; |
@@ -2231,11 +1958,17 @@ sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) | |||
2231 | fix->mmio_start = ivideo->mmio_base; | 1958 | fix->mmio_start = ivideo->mmio_base; |
2232 | fix->mmio_len = ivideo->mmio_size; | 1959 | fix->mmio_len = ivideo->mmio_size; |
2233 | if(ivideo->sisvga_engine == SIS_300_VGA) { | 1960 | if(ivideo->sisvga_engine == SIS_300_VGA) { |
2234 | fix->accel = FB_ACCEL_SIS_GLAMOUR; | 1961 | fix->accel = FB_ACCEL_SIS_GLAMOUR; |
2235 | } else if((ivideo->chip == SIS_330) || (ivideo->chip == SIS_760)) { | 1962 | } else if((ivideo->chip == SIS_330) || |
2236 | fix->accel = FB_ACCEL_SIS_XABRE; | 1963 | (ivideo->chip == SIS_760) || |
1964 | (ivideo->chip == SIS_761)) { | ||
1965 | fix->accel = FB_ACCEL_SIS_XABRE; | ||
1966 | } else if(ivideo->chip == XGI_20) { | ||
1967 | fix->accel = FB_ACCEL_XGI_VOLARI_Z; | ||
1968 | } else if(ivideo->chip >= XGI_40) { | ||
1969 | fix->accel = FB_ACCEL_XGI_VOLARI_V; | ||
2237 | } else { | 1970 | } else { |
2238 | fix->accel = FB_ACCEL_SIS_GLAMOUR_2; | 1971 | fix->accel = FB_ACCEL_SIS_GLAMOUR_2; |
2239 | } | 1972 | } |
2240 | 1973 | ||
2241 | return 0; | 1974 | return 0; |
@@ -2251,40 +1984,41 @@ static struct fb_ops sisfb_ops = { | |||
2251 | .fb_set_var = sisfb_set_var, | 1984 | .fb_set_var = sisfb_set_var, |
2252 | .fb_get_cmap = sisfb_get_cmap, | 1985 | .fb_get_cmap = sisfb_get_cmap, |
2253 | .fb_set_cmap = sisfb_set_cmap, | 1986 | .fb_set_cmap = sisfb_set_cmap, |
2254 | .fb_pan_display = sisfb_pan_display, | 1987 | .fb_pan_display = sisfb_pan_display, |
2255 | .fb_ioctl = sisfb_ioctl | 1988 | .fb_ioctl = sisfb_ioctl |
2256 | }; | 1989 | }; |
2257 | #endif | 1990 | #endif |
2258 | 1991 | ||
2259 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | 1992 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) |
2260 | static struct fb_ops sisfb_ops = { | 1993 | static struct fb_ops sisfb_ops = { |
2261 | .owner = THIS_MODULE, | 1994 | .owner = THIS_MODULE, |
2262 | .fb_open = sisfb_open, | 1995 | .fb_open = sisfb_open, |
2263 | .fb_release = sisfb_release, | 1996 | .fb_release = sisfb_release, |
2264 | .fb_check_var = sisfb_check_var, | 1997 | .fb_check_var = sisfb_check_var, |
2265 | .fb_set_par = sisfb_set_par, | 1998 | .fb_set_par = sisfb_set_par, |
2266 | .fb_setcolreg = sisfb_setcolreg, | 1999 | .fb_setcolreg = sisfb_setcolreg, |
2267 | .fb_pan_display = sisfb_pan_display, | 2000 | .fb_pan_display = sisfb_pan_display, |
2268 | .fb_blank = sisfb_blank, | 2001 | .fb_blank = sisfb_blank, |
2269 | .fb_fillrect = fbcon_sis_fillrect, | 2002 | .fb_fillrect = fbcon_sis_fillrect, |
2270 | .fb_copyarea = fbcon_sis_copyarea, | 2003 | .fb_copyarea = fbcon_sis_copyarea, |
2271 | .fb_imageblit = cfb_imageblit, | 2004 | .fb_imageblit = cfb_imageblit, |
2272 | .fb_cursor = soft_cursor, | 2005 | .fb_cursor = soft_cursor, |
2273 | .fb_sync = fbcon_sis_sync, | 2006 | .fb_sync = fbcon_sis_sync, |
2274 | .fb_ioctl = sisfb_ioctl, | 2007 | #ifdef SIS_NEW_CONFIG_COMPAT |
2275 | #ifdef CONFIG_COMPAT | 2008 | .fb_compat_ioctl= sisfb_compat_ioctl, |
2276 | .fb_compat_ioctl = sisfb_compat_ioctl, | ||
2277 | #endif | 2009 | #endif |
2010 | .fb_ioctl = sisfb_ioctl | ||
2278 | }; | 2011 | }; |
2279 | #endif | 2012 | #endif |
2280 | 2013 | ||
2281 | /* ---------------- Chip generation dependent routines ---------------- */ | 2014 | /* ---------------- Chip generation dependent routines ---------------- */ |
2282 | 2015 | ||
2283 | static struct pci_dev * sisfb_get_northbridge(int basechipid) | 2016 | static struct pci_dev * __devinit |
2017 | sisfb_get_northbridge(int basechipid) | ||
2284 | { | 2018 | { |
2285 | struct pci_dev *pdev = NULL; | 2019 | struct pci_dev *pdev = NULL; |
2286 | int nbridgenum, nbridgeidx, i; | 2020 | int nbridgenum, nbridgeidx, i; |
2287 | const unsigned short nbridgeids[] = { | 2021 | static const unsigned short nbridgeids[] = { |
2288 | PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */ | 2022 | PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */ |
2289 | PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */ | 2023 | PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */ |
2290 | PCI_DEVICE_ID_SI_730, | 2024 | PCI_DEVICE_ID_SI_730, |
@@ -2292,13 +2026,14 @@ static struct pci_dev * sisfb_get_northbridge(int basechipid) | |||
2292 | PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */ | 2026 | PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */ |
2293 | PCI_DEVICE_ID_SI_651, | 2027 | PCI_DEVICE_ID_SI_651, |
2294 | PCI_DEVICE_ID_SI_740, | 2028 | PCI_DEVICE_ID_SI_740, |
2295 | PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760 VGA */ | 2029 | PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760/761 VGA */ |
2296 | PCI_DEVICE_ID_SI_741, | 2030 | PCI_DEVICE_ID_SI_741, |
2297 | PCI_DEVICE_ID_SI_660, | 2031 | PCI_DEVICE_ID_SI_660, |
2298 | PCI_DEVICE_ID_SI_760 | 2032 | PCI_DEVICE_ID_SI_760, |
2033 | PCI_DEVICE_ID_SI_761 | ||
2299 | }; | 2034 | }; |
2300 | 2035 | ||
2301 | switch(basechipid) { | 2036 | switch(basechipid) { |
2302 | #ifdef CONFIG_FB_SIS_300 | 2037 | #ifdef CONFIG_FB_SIS_300 |
2303 | case SIS_540: nbridgeidx = 0; nbridgenum = 1; break; | 2038 | case SIS_540: nbridgeidx = 0; nbridgenum = 1; break; |
2304 | case SIS_630: nbridgeidx = 1; nbridgenum = 2; break; | 2039 | case SIS_630: nbridgeidx = 1; nbridgenum = 2; break; |
@@ -2306,35 +2041,40 @@ static struct pci_dev * sisfb_get_northbridge(int basechipid) | |||
2306 | #ifdef CONFIG_FB_SIS_315 | 2041 | #ifdef CONFIG_FB_SIS_315 |
2307 | case SIS_550: nbridgeidx = 3; nbridgenum = 1; break; | 2042 | case SIS_550: nbridgeidx = 3; nbridgenum = 1; break; |
2308 | case SIS_650: nbridgeidx = 4; nbridgenum = 3; break; | 2043 | case SIS_650: nbridgeidx = 4; nbridgenum = 3; break; |
2309 | case SIS_660: nbridgeidx = 7; nbridgenum = 4; break; | 2044 | case SIS_660: nbridgeidx = 7; nbridgenum = 5; break; |
2310 | #endif | 2045 | #endif |
2311 | default: return NULL; | 2046 | default: return NULL; |
2312 | } | 2047 | } |
2313 | for(i = 0; i < nbridgenum; i++) { | 2048 | for(i = 0; i < nbridgenum; i++) { |
2314 | if((pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridgeids[nbridgeidx+i], NULL))) break; | 2049 | if((pdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, |
2050 | nbridgeids[nbridgeidx+i], NULL))) | ||
2051 | break; | ||
2315 | } | 2052 | } |
2316 | return pdev; | 2053 | return pdev; |
2317 | } | 2054 | } |
2318 | 2055 | ||
2319 | static int __devinit sisfb_get_dram_size(struct sis_video_info *ivideo) | 2056 | static int __devinit |
2057 | sisfb_get_dram_size(struct sis_video_info *ivideo) | ||
2320 | { | 2058 | { |
2321 | #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315) | 2059 | #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315) |
2322 | u8 reg; | 2060 | u8 reg; |
2323 | #endif | 2061 | #endif |
2324 | 2062 | ||
2325 | ivideo->video_size = 0; | 2063 | ivideo->video_size = 0; |
2064 | ivideo->UMAsize = ivideo->LFBsize = 0; | ||
2326 | 2065 | ||
2327 | switch(ivideo->chip) { | 2066 | switch(ivideo->chip) { |
2328 | #ifdef CONFIG_FB_SIS_300 | 2067 | #ifdef CONFIG_FB_SIS_300 |
2329 | case SIS_300: | 2068 | case SIS_300: |
2330 | inSISIDXREG(SISSR, 0x14, reg); | 2069 | inSISIDXREG(SISSR, 0x14, reg); |
2331 | ivideo->video_size = ((reg & 0x3F) + 1) << 20; | 2070 | ivideo->video_size = ((reg & 0x3F) + 1) << 20; |
2332 | break; | 2071 | break; |
2333 | case SIS_540: | 2072 | case SIS_540: |
2334 | case SIS_630: | 2073 | case SIS_630: |
2335 | case SIS_730: | 2074 | case SIS_730: |
2336 | if(!ivideo->nbridge) return -1; | 2075 | if(!ivideo->nbridge) |
2337 | pci_read_config_byte(ivideo->nbridge, 0x63, ®); | 2076 | return -1; |
2077 | pci_read_config_byte(ivideo->nbridge, 0x63, ®); | ||
2338 | ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21); | 2078 | ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21); |
2339 | break; | 2079 | break; |
2340 | #endif | 2080 | #endif |
@@ -2342,45 +2082,68 @@ static int __devinit sisfb_get_dram_size(struct sis_video_info *ivideo) | |||
2342 | case SIS_315H: | 2082 | case SIS_315H: |
2343 | case SIS_315PRO: | 2083 | case SIS_315PRO: |
2344 | case SIS_315: | 2084 | case SIS_315: |
2345 | inSISIDXREG(SISSR, 0x14, reg); | 2085 | inSISIDXREG(SISSR, 0x14, reg); |
2346 | ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; | 2086 | ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; |
2347 | switch((reg >> 2) & 0x03) { | 2087 | switch((reg >> 2) & 0x03) { |
2348 | case 0x01: | 2088 | case 0x01: |
2349 | case 0x03: | 2089 | case 0x03: |
2350 | ivideo->video_size <<= 1; | 2090 | ivideo->video_size <<= 1; |
2351 | break; | 2091 | break; |
2352 | case 0x02: | 2092 | case 0x02: |
2353 | ivideo->video_size += (ivideo->video_size/2); | 2093 | ivideo->video_size += (ivideo->video_size/2); |
2354 | } | 2094 | } |
2355 | break; | 2095 | break; |
2356 | case SIS_330: | 2096 | case SIS_330: |
2357 | inSISIDXREG(SISSR, 0x14, reg); | 2097 | inSISIDXREG(SISSR, 0x14, reg); |
2358 | ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; | 2098 | ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; |
2359 | if(reg & 0x0c) ivideo->video_size <<= 1; | 2099 | if(reg & 0x0c) ivideo->video_size <<= 1; |
2360 | break; | 2100 | break; |
2361 | case SIS_550: | 2101 | case SIS_550: |
2362 | case SIS_650: | 2102 | case SIS_650: |
2363 | case SIS_740: | 2103 | case SIS_740: |
2364 | inSISIDXREG(SISSR, 0x14, reg); | 2104 | inSISIDXREG(SISSR, 0x14, reg); |
2365 | ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20; | 2105 | ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20; |
2366 | break; | 2106 | break; |
2367 | case SIS_661: | 2107 | case SIS_661: |
2368 | case SIS_741: | 2108 | case SIS_741: |
2369 | inSISIDXREG(SISCR, 0x79, reg); | 2109 | inSISIDXREG(SISCR, 0x79, reg); |
2370 | ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; | 2110 | ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; |
2371 | break; | 2111 | break; |
2372 | case SIS_660: | 2112 | case SIS_660: |
2373 | case SIS_760: | 2113 | case SIS_760: |
2114 | case SIS_761: | ||
2374 | inSISIDXREG(SISCR, 0x79, reg); | 2115 | inSISIDXREG(SISCR, 0x79, reg); |
2375 | reg = (reg & 0xf0) >> 4; | 2116 | reg = (reg & 0xf0) >> 4; |
2376 | if(reg) ivideo->video_size = (1 << reg) << 20; | 2117 | if(reg) { |
2118 | ivideo->video_size = (1 << reg) << 20; | ||
2119 | ivideo->UMAsize = ivideo->video_size; | ||
2120 | } | ||
2377 | inSISIDXREG(SISCR, 0x78, reg); | 2121 | inSISIDXREG(SISCR, 0x78, reg); |
2378 | reg &= 0x30; | 2122 | reg &= 0x30; |
2379 | if(reg) { | 2123 | if(reg) { |
2380 | if(reg == 0x10) ivideo->video_size += (32 << 20); | 2124 | if(reg == 0x10) { |
2381 | else ivideo->video_size += (64 << 20); | 2125 | ivideo->LFBsize = (32 << 20); |
2126 | } else { | ||
2127 | ivideo->LFBsize = (64 << 20); | ||
2128 | } | ||
2129 | ivideo->video_size += ivideo->LFBsize; | ||
2382 | } | 2130 | } |
2383 | break; | 2131 | break; |
2132 | case SIS_340: | ||
2133 | case XGI_20: | ||
2134 | case XGI_40: | ||
2135 | inSISIDXREG(SISSR, 0x14, reg); | ||
2136 | ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; | ||
2137 | if(ivideo->chip != XGI_20) { | ||
2138 | reg = (reg & 0x0c) >> 2; | ||
2139 | if(ivideo->revision_id == 2) { | ||
2140 | if(reg & 0x01) reg = 0x02; | ||
2141 | else reg = 0x00; | ||
2142 | } | ||
2143 | if(reg == 0x02) ivideo->video_size <<= 1; | ||
2144 | else if(reg == 0x03) ivideo->video_size <<= 2; | ||
2145 | } | ||
2146 | break; | ||
2384 | #endif | 2147 | #endif |
2385 | default: | 2148 | default: |
2386 | return -1; | 2149 | return -1; |
@@ -2390,17 +2153,24 @@ static int __devinit sisfb_get_dram_size(struct sis_video_info *ivideo) | |||
2390 | 2153 | ||
2391 | /* -------------- video bridge device detection --------------- */ | 2154 | /* -------------- video bridge device detection --------------- */ |
2392 | 2155 | ||
2393 | static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo) | 2156 | static void __devinit |
2157 | sisfb_detect_VB_connect(struct sis_video_info *ivideo) | ||
2394 | { | 2158 | { |
2395 | u8 cr32, temp; | 2159 | u8 cr32, temp; |
2396 | 2160 | ||
2161 | /* No CRT2 on XGI Z7 */ | ||
2162 | if(ivideo->chip == XGI_20) { | ||
2163 | ivideo->sisfb_crt1off = 0; | ||
2164 | return; | ||
2165 | } | ||
2166 | |||
2397 | #ifdef CONFIG_FB_SIS_300 | 2167 | #ifdef CONFIG_FB_SIS_300 |
2398 | if(ivideo->sisvga_engine == SIS_300_VGA) { | 2168 | if(ivideo->sisvga_engine == SIS_300_VGA) { |
2399 | inSISIDXREG(SISSR, 0x17, temp); | 2169 | inSISIDXREG(SISSR, 0x17, temp); |
2400 | if((temp & 0x0F) && (ivideo->chip != SIS_300)) { | 2170 | if((temp & 0x0F) && (ivideo->chip != SIS_300)) { |
2401 | /* PAL/NTSC is stored on SR16 on such machines */ | 2171 | /* PAL/NTSC is stored on SR16 on such machines */ |
2402 | if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) { | 2172 | if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) { |
2403 | inSISIDXREG(SISSR, 0x16, temp); | 2173 | inSISIDXREG(SISSR, 0x16, temp); |
2404 | if(temp & 0x20) | 2174 | if(temp & 0x20) |
2405 | ivideo->vbflags |= TV_PAL; | 2175 | ivideo->vbflags |= TV_PAL; |
2406 | else | 2176 | else |
@@ -2435,28 +2205,29 @@ static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo) | |||
2435 | 2205 | ||
2436 | if(ivideo->sisfb_tvplug != -1) { | 2206 | if(ivideo->sisfb_tvplug != -1) { |
2437 | if( (ivideo->sisvga_engine != SIS_315_VGA) || | 2207 | if( (ivideo->sisvga_engine != SIS_315_VGA) || |
2438 | (!(ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV))) ) { | 2208 | (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) { |
2439 | if(ivideo->sisfb_tvplug & TV_YPBPR) { | 2209 | if(ivideo->sisfb_tvplug & TV_YPBPR) { |
2440 | ivideo->sisfb_tvplug = -1; | 2210 | ivideo->sisfb_tvplug = -1; |
2441 | printk(KERN_ERR "sisfb: YPbPr not supported\n"); | 2211 | printk(KERN_ERR "sisfb: YPbPr not supported\n"); |
2442 | } | 2212 | } |
2443 | } | 2213 | } |
2444 | } | 2214 | } |
2445 | if(ivideo->sisfb_tvplug != -1) { | 2215 | if(ivideo->sisfb_tvplug != -1) { |
2446 | if( (ivideo->sisvga_engine != SIS_315_VGA) || | 2216 | if( (ivideo->sisvga_engine != SIS_315_VGA) || |
2447 | (!(ivideo->vbflags & (VB_301|VB_301B|VB_302B))) ) { | 2217 | (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) { |
2448 | if(ivideo->sisfb_tvplug & TV_HIVISION) { | 2218 | if(ivideo->sisfb_tvplug & TV_HIVISION) { |
2449 | ivideo->sisfb_tvplug = -1; | 2219 | ivideo->sisfb_tvplug = -1; |
2450 | printk(KERN_ERR "sisfb: HiVision not supported\n"); | 2220 | printk(KERN_ERR "sisfb: HiVision not supported\n"); |
2451 | } | 2221 | } |
2452 | } | 2222 | } |
2453 | } | 2223 | } |
2454 | if(ivideo->sisfb_tvstd != -1) { | 2224 | if(ivideo->sisfb_tvstd != -1) { |
2455 | if( (!(ivideo->vbflags & VB_SISBRIDGE)) && | 2225 | if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) && |
2456 | (!((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags & VB_CHRONTEL))) ) { | 2226 | (!((ivideo->sisvga_engine == SIS_315_VGA) && |
2227 | (ivideo->vbflags2 & VB2_CHRONTEL))) ) { | ||
2457 | if(ivideo->sisfb_tvstd & (TV_PALN | TV_PALN | TV_NTSCJ)) { | 2228 | if(ivideo->sisfb_tvstd & (TV_PALN | TV_PALN | TV_NTSCJ)) { |
2458 | ivideo->sisfb_tvstd = -1; | 2229 | ivideo->sisfb_tvstd = -1; |
2459 | printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n"); | 2230 | printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n"); |
2460 | } | 2231 | } |
2461 | } | 2232 | } |
2462 | } | 2233 | } |
@@ -2468,7 +2239,7 @@ static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo) | |||
2468 | if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */ | 2239 | if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */ |
2469 | else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION; | 2240 | else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION; |
2470 | else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART; | 2241 | else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART; |
2471 | else { | 2242 | else { |
2472 | if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO; | 2243 | if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO; |
2473 | if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO; | 2244 | if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO; |
2474 | } | 2245 | } |
@@ -2485,165 +2256,44 @@ static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo) | |||
2485 | } | 2256 | } |
2486 | if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) { | 2257 | if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) { |
2487 | if(ivideo->sisvga_engine == SIS_300_VGA) { | 2258 | if(ivideo->sisvga_engine == SIS_300_VGA) { |
2488 | inSISIDXREG(SISSR, 0x38, temp); | 2259 | inSISIDXREG(SISSR, 0x38, temp); |
2489 | if(temp & 0x01) ivideo->vbflags |= TV_PAL; | 2260 | if(temp & 0x01) ivideo->vbflags |= TV_PAL; |
2490 | else ivideo->vbflags |= TV_NTSC; | 2261 | else ivideo->vbflags |= TV_NTSC; |
2491 | } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) { | 2262 | } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) { |
2492 | inSISIDXREG(SISSR, 0x38, temp); | 2263 | inSISIDXREG(SISSR, 0x38, temp); |
2493 | if(temp & 0x01) ivideo->vbflags |= TV_PAL; | 2264 | if(temp & 0x01) ivideo->vbflags |= TV_PAL; |
2494 | else ivideo->vbflags |= TV_NTSC; | 2265 | else ivideo->vbflags |= TV_NTSC; |
2495 | } else { | 2266 | } else { |
2496 | inSISIDXREG(SISCR, 0x79, temp); | 2267 | inSISIDXREG(SISCR, 0x79, temp); |
2497 | if(temp & 0x20) ivideo->vbflags |= TV_PAL; | 2268 | if(temp & 0x20) ivideo->vbflags |= TV_PAL; |
2498 | else ivideo->vbflags |= TV_NTSC; | 2269 | else ivideo->vbflags |= TV_NTSC; |
2499 | } | 2270 | } |
2500 | } | 2271 | } |
2501 | } | 2272 | } |
2502 | 2273 | ||
2503 | /* Copy forceCRT1 option to CRT1off if option is given */ | 2274 | /* Copy forceCRT1 option to CRT1off if option is given */ |
2504 | if(ivideo->sisfb_forcecrt1 != -1) { | 2275 | if(ivideo->sisfb_forcecrt1 != -1) { |
2505 | ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1; | 2276 | ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1; |
2506 | } | ||
2507 | } | ||
2508 | |||
2509 | static void __devinit sisfb_get_VB_type(struct sis_video_info *ivideo) | ||
2510 | { | ||
2511 | char stdstr[] = "sisfb: Detected"; | ||
2512 | char bridgestr[] = "video bridge"; | ||
2513 | u8 vb_chipid; | ||
2514 | u8 reg; | ||
2515 | |||
2516 | inSISIDXREG(SISPART4, 0x00, vb_chipid); | ||
2517 | switch(vb_chipid) { | ||
2518 | case 0x01: | ||
2519 | inSISIDXREG(SISPART4, 0x01, reg); | ||
2520 | if(reg < 0xb0) { | ||
2521 | ivideo->vbflags |= VB_301; | ||
2522 | printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr); | ||
2523 | } else if(reg < 0xc0) { | ||
2524 | ivideo->vbflags |= VB_301B; | ||
2525 | inSISIDXREG(SISPART4,0x23,reg); | ||
2526 | if(!(reg & 0x02)) { | ||
2527 | ivideo->vbflags |= VB_30xBDH; | ||
2528 | printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr); | ||
2529 | } else { | ||
2530 | printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr); | ||
2531 | } | ||
2532 | } else if(reg < 0xd0) { | ||
2533 | ivideo->vbflags |= VB_301C; | ||
2534 | printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr); | ||
2535 | } else if(reg < 0xe0) { | ||
2536 | ivideo->vbflags |= VB_301LV; | ||
2537 | printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr); | ||
2538 | } else if(reg <= 0xe1) { | ||
2539 | inSISIDXREG(SISPART4,0x39,reg); | ||
2540 | if(reg == 0xff) { | ||
2541 | ivideo->vbflags |= VB_302LV; | ||
2542 | printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr); | ||
2543 | } else { | ||
2544 | ivideo->vbflags |= VB_301C; | ||
2545 | printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr); | ||
2546 | #if 0 | ||
2547 | ivideo->vbflags |= VB_302ELV; | ||
2548 | printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr); | ||
2549 | #endif | ||
2550 | } | ||
2551 | } | ||
2552 | break; | ||
2553 | case 0x02: | ||
2554 | ivideo->vbflags |= VB_302B; | ||
2555 | printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr); | ||
2556 | break; | ||
2557 | } | ||
2558 | |||
2559 | if((!(ivideo->vbflags & VB_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) { | ||
2560 | inSISIDXREG(SISCR, 0x37, reg); | ||
2561 | reg &= SIS_EXTERNAL_CHIP_MASK; | ||
2562 | reg >>= 1; | ||
2563 | if(ivideo->sisvga_engine == SIS_300_VGA) { | ||
2564 | #ifdef CONFIG_FB_SIS_300 | ||
2565 | switch(reg) { | ||
2566 | case SIS_EXTERNAL_CHIP_LVDS: | ||
2567 | ivideo->vbflags |= VB_LVDS; | ||
2568 | break; | ||
2569 | case SIS_EXTERNAL_CHIP_TRUMPION: | ||
2570 | ivideo->vbflags |= VB_TRUMPION; | ||
2571 | break; | ||
2572 | case SIS_EXTERNAL_CHIP_CHRONTEL: | ||
2573 | ivideo->vbflags |= VB_CHRONTEL; | ||
2574 | break; | ||
2575 | case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL: | ||
2576 | ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); | ||
2577 | break; | ||
2578 | } | ||
2579 | if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 1; | ||
2580 | #endif | ||
2581 | } else if(ivideo->chip < SIS_661) { | ||
2582 | #ifdef CONFIG_FB_SIS_315 | ||
2583 | switch (reg) { | ||
2584 | case SIS310_EXTERNAL_CHIP_LVDS: | ||
2585 | ivideo->vbflags |= VB_LVDS; | ||
2586 | break; | ||
2587 | case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL: | ||
2588 | ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); | ||
2589 | break; | ||
2590 | } | ||
2591 | if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 2; | ||
2592 | #endif | ||
2593 | } else if(ivideo->chip >= SIS_661) { | ||
2594 | #ifdef CONFIG_FB_SIS_315 | ||
2595 | inSISIDXREG(SISCR, 0x38, reg); | ||
2596 | reg >>= 5; | ||
2597 | switch(reg) { | ||
2598 | case 0x02: | ||
2599 | ivideo->vbflags |= VB_LVDS; | ||
2600 | break; | ||
2601 | case 0x03: | ||
2602 | ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); | ||
2603 | break; | ||
2604 | case 0x04: | ||
2605 | ivideo->vbflags |= (VB_LVDS | VB_CONEXANT); | ||
2606 | break; | ||
2607 | } | ||
2608 | if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 2; | ||
2609 | #endif | ||
2610 | } | ||
2611 | if(ivideo->vbflags & VB_LVDS) { | ||
2612 | printk(KERN_INFO "%s LVDS transmitter\n", stdstr); | ||
2613 | } | ||
2614 | if(ivideo->vbflags & VB_TRUMPION) { | ||
2615 | printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr); | ||
2616 | } | ||
2617 | if(ivideo->vbflags & VB_CHRONTEL) { | ||
2618 | printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr); | ||
2619 | } | ||
2620 | if(ivideo->vbflags & VB_CONEXANT) { | ||
2621 | printk(KERN_INFO "%s Conexant external device\n", stdstr); | ||
2622 | } | ||
2623 | } | ||
2624 | |||
2625 | if(ivideo->vbflags & VB_SISBRIDGE) { | ||
2626 | SiS_Sense30x(ivideo); | ||
2627 | } else if(ivideo->vbflags & VB_CHRONTEL) { | ||
2628 | SiS_SenseCh(ivideo); | ||
2629 | } | 2277 | } |
2630 | } | 2278 | } |
2631 | 2279 | ||
2632 | /* ------------------ Sensing routines ------------------ */ | 2280 | /* ------------------ Sensing routines ------------------ */ |
2633 | 2281 | ||
2634 | static BOOLEAN __devinit sisfb_test_DDC1(struct sis_video_info *ivideo) | 2282 | static BOOLEAN __devinit |
2283 | sisfb_test_DDC1(struct sis_video_info *ivideo) | ||
2635 | { | 2284 | { |
2636 | unsigned short old; | 2285 | unsigned short old; |
2637 | int count = 48; | 2286 | int count = 48; |
2638 | 2287 | ||
2639 | old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr); | 2288 | old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr); |
2640 | do { | 2289 | do { |
2641 | if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break; | 2290 | if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break; |
2642 | } while(count--); | 2291 | } while(count--); |
2643 | return (count == -1) ? FALSE : TRUE; | 2292 | return (count == -1) ? FALSE : TRUE; |
2644 | } | 2293 | } |
2645 | 2294 | ||
2646 | static void __devinit sisfb_sense_crt1(struct sis_video_info *ivideo) | 2295 | static void __devinit |
2296 | sisfb_sense_crt1(struct sis_video_info *ivideo) | ||
2647 | { | 2297 | { |
2648 | BOOLEAN mustwait = FALSE; | 2298 | BOOLEAN mustwait = FALSE; |
2649 | u8 sr1F, cr17; | 2299 | u8 sr1F, cr17; |
@@ -2699,7 +2349,8 @@ static void __devinit sisfb_sense_crt1(struct sis_video_info *ivideo) | |||
2699 | if(temp == 0xffff) { | 2349 | if(temp == 0xffff) { |
2700 | i = 3; | 2350 | i = 3; |
2701 | do { | 2351 | do { |
2702 | temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, 0, 0, NULL); | 2352 | temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, |
2353 | ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2); | ||
2703 | } while(((temp == 0) || (temp == 0xffff)) && i--); | 2354 | } while(((temp == 0) || (temp == 0xffff)) && i--); |
2704 | 2355 | ||
2705 | if((temp == 0) || (temp == 0xffff)) { | 2356 | if((temp == 0) || (temp == 0xffff)) { |
@@ -2723,7 +2374,96 @@ static void __devinit sisfb_sense_crt1(struct sis_video_info *ivideo) | |||
2723 | } | 2374 | } |
2724 | 2375 | ||
2725 | /* Determine and detect attached devices on SiS30x */ | 2376 | /* Determine and detect attached devices on SiS30x */ |
2726 | static int __devinit SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test) | 2377 | static void __devinit |
2378 | SiS_SenseLCD(struct sis_video_info *ivideo) | ||
2379 | { | ||
2380 | unsigned char buffer[256]; | ||
2381 | unsigned short temp, realcrtno, i; | ||
2382 | u8 reg, cr37 = 0, paneltype = 0; | ||
2383 | u16 xres, yres; | ||
2384 | |||
2385 | ivideo->SiS_Pr.PanelSelfDetected = FALSE; | ||
2386 | |||
2387 | /* LCD detection only for TMDS bridges */ | ||
2388 | if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE)) | ||
2389 | return; | ||
2390 | if(ivideo->vbflags2 & VB2_30xBDH) | ||
2391 | return; | ||
2392 | |||
2393 | /* If LCD already set up by BIOS, skip it */ | ||
2394 | inSISIDXREG(SISCR, 0x32, reg); | ||
2395 | if(reg & 0x08) | ||
2396 | return; | ||
2397 | |||
2398 | realcrtno = 1; | ||
2399 | if(ivideo->SiS_Pr.DDCPortMixup) | ||
2400 | realcrtno = 0; | ||
2401 | |||
2402 | /* Check DDC capabilities */ | ||
2403 | temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, | ||
2404 | realcrtno, 0, &buffer[0], ivideo->vbflags2); | ||
2405 | |||
2406 | if((!temp) || (temp == 0xffff) || (!(temp & 0x02))) | ||
2407 | return; | ||
2408 | |||
2409 | /* Read DDC data */ | ||
2410 | i = 3; /* Number of retrys */ | ||
2411 | do { | ||
2412 | temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, | ||
2413 | ivideo->sisvga_engine, realcrtno, 1, | ||
2414 | &buffer[0], ivideo->vbflags2); | ||
2415 | } while((temp) && i--); | ||
2416 | |||
2417 | if(temp) | ||
2418 | return; | ||
2419 | |||
2420 | /* No digital device */ | ||
2421 | if(!(buffer[0x14] & 0x80)) | ||
2422 | return; | ||
2423 | |||
2424 | /* First detailed timing preferred timing? */ | ||
2425 | if(!(buffer[0x18] & 0x02)) | ||
2426 | return; | ||
2427 | |||
2428 | xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4); | ||
2429 | yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4); | ||
2430 | |||
2431 | switch(xres) { | ||
2432 | case 1024: | ||
2433 | if(yres == 768) | ||
2434 | paneltype = 0x02; | ||
2435 | break; | ||
2436 | case 1280: | ||
2437 | if(yres == 1024) | ||
2438 | paneltype = 0x03; | ||
2439 | break; | ||
2440 | case 1600: | ||
2441 | if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC)) | ||
2442 | paneltype = 0x0b; | ||
2443 | break; | ||
2444 | } | ||
2445 | |||
2446 | if(!paneltype) | ||
2447 | return; | ||
2448 | |||
2449 | if(buffer[0x23]) | ||
2450 | cr37 |= 0x10; | ||
2451 | |||
2452 | if((buffer[0x47] & 0x18) == 0x18) | ||
2453 | cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20); | ||
2454 | else | ||
2455 | cr37 |= 0xc0; | ||
2456 | |||
2457 | outSISIDXREG(SISCR, 0x36, paneltype); | ||
2458 | cr37 &= 0xf1; | ||
2459 | setSISIDXREG(SISCR, 0x37, 0x0c, cr37); | ||
2460 | orSISIDXREG(SISCR, 0x32, 0x08); | ||
2461 | |||
2462 | ivideo->SiS_Pr.PanelSelfDetected = TRUE; | ||
2463 | } | ||
2464 | |||
2465 | static int __devinit | ||
2466 | SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test) | ||
2727 | { | 2467 | { |
2728 | int temp, mytest, result, i, j; | 2468 | int temp, mytest, result, i, j; |
2729 | 2469 | ||
@@ -2749,10 +2489,11 @@ static int __devinit SISDoSense(struct sis_video_info *ivideo, u16 type, u16 tes | |||
2749 | } | 2489 | } |
2750 | if((result == 0) || (result >= 2)) break; | 2490 | if((result == 0) || (result >= 2)) break; |
2751 | } | 2491 | } |
2752 | return(result); | 2492 | return result; |
2753 | } | 2493 | } |
2754 | 2494 | ||
2755 | static void __devinit SiS_Sense30x(struct sis_video_info *ivideo) | 2495 | static void __devinit |
2496 | SiS_Sense30x(struct sis_video_info *ivideo) | ||
2756 | { | 2497 | { |
2757 | u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0; | 2498 | u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0; |
2758 | u16 svhs=0, svhs_c=0; | 2499 | u16 svhs=0, svhs_c=0; |
@@ -2762,36 +2503,51 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo) | |||
2762 | char stdstr[] = "sisfb: Detected"; | 2503 | char stdstr[] = "sisfb: Detected"; |
2763 | char tvstr[] = "TV connected to"; | 2504 | char tvstr[] = "TV connected to"; |
2764 | 2505 | ||
2765 | if(ivideo->vbflags & VB_301) { | 2506 | if(ivideo->vbflags2 & VB2_301) { |
2766 | svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1; | 2507 | svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1; |
2767 | inSISIDXREG(SISPART4,0x01,myflag); | 2508 | inSISIDXREG(SISPART4,0x01,myflag); |
2768 | if(myflag & 0x04) { | 2509 | if(myflag & 0x04) { |
2769 | svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd; | 2510 | svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd; |
2770 | } | 2511 | } |
2771 | } else if(ivideo->vbflags & (VB_301B | VB_302B)) { | 2512 | } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) { |
2772 | svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190; | 2513 | svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190; |
2773 | } else if(ivideo->vbflags & (VB_301LV | VB_302LV)) { | 2514 | } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) { |
2774 | svhs = 0x0200; cvbs = 0x0100; | 2515 | svhs = 0x0200; cvbs = 0x0100; |
2775 | } else if(ivideo->vbflags & (VB_301C | VB_302ELV)) { | 2516 | } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) { |
2776 | svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190; | 2517 | svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190; |
2777 | } else return; | 2518 | } else |
2519 | return; | ||
2778 | 2520 | ||
2779 | vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804; | 2521 | vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804; |
2780 | if(ivideo->vbflags & (VB_301LV|VB_302LV|VB_302ELV)) { | 2522 | if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) { |
2781 | svhs_c = 0x0408; cvbs_c = 0x0808; | 2523 | svhs_c = 0x0408; cvbs_c = 0x0808; |
2782 | } | 2524 | } |
2525 | |||
2783 | biosflag = 2; | 2526 | biosflag = 2; |
2527 | if(ivideo->haveXGIROM) { | ||
2528 | biosflag = ivideo->bios_abase[0x58] & 0x03; | ||
2529 | } else if(ivideo->newrom) { | ||
2530 | if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01; | ||
2531 | } else if(ivideo->sisvga_engine == SIS_300_VGA) { | ||
2532 | if(ivideo->bios_abase) { | ||
2533 | biosflag = ivideo->bios_abase[0xfe] & 0x03; | ||
2534 | } | ||
2535 | } | ||
2784 | 2536 | ||
2785 | if(ivideo->chip == SIS_300) { | 2537 | if(ivideo->chip == SIS_300) { |
2786 | inSISIDXREG(SISSR,0x3b,myflag); | 2538 | inSISIDXREG(SISSR,0x3b,myflag); |
2787 | if(!(myflag & 0x01)) vga2 = vga2_c = 0; | 2539 | if(!(myflag & 0x01)) vga2 = vga2_c = 0; |
2788 | } | 2540 | } |
2789 | 2541 | ||
2542 | if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) { | ||
2543 | vga2 = vga2_c = 0; | ||
2544 | } | ||
2545 | |||
2790 | inSISIDXREG(SISSR,0x1e,backupSR_1e); | 2546 | inSISIDXREG(SISSR,0x1e,backupSR_1e); |
2791 | orSISIDXREG(SISSR,0x1e,0x20); | 2547 | orSISIDXREG(SISSR,0x1e,0x20); |
2792 | 2548 | ||
2793 | inSISIDXREG(SISPART4,0x0d,backupP4_0d); | 2549 | inSISIDXREG(SISPART4,0x0d,backupP4_0d); |
2794 | if(ivideo->vbflags & VB_301C) { | 2550 | if(ivideo->vbflags2 & VB2_30xC) { |
2795 | setSISIDXREG(SISPART4,0x0d,~0x07,0x01); | 2551 | setSISIDXREG(SISPART4,0x0d,~0x07,0x01); |
2796 | } else { | 2552 | } else { |
2797 | orSISIDXREG(SISPART4,0x0d,0x04); | 2553 | orSISIDXREG(SISPART4,0x0d,0x04); |
@@ -2802,11 +2558,11 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo) | |||
2802 | outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc)); | 2558 | outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc)); |
2803 | 2559 | ||
2804 | inSISIDXREG(SISPART2,0x4d,backupP2_4d); | 2560 | inSISIDXREG(SISPART2,0x4d,backupP2_4d); |
2805 | if(ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV|VB_302ELV)) { | 2561 | if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) { |
2806 | outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10)); | 2562 | outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10)); |
2807 | } | 2563 | } |
2808 | 2564 | ||
2809 | if(!(ivideo->vbflags & VB_301C)) { | 2565 | if(!(ivideo->vbflags2 & VB2_30xCLV)) { |
2810 | SISDoSense(ivideo, 0, 0); | 2566 | SISDoSense(ivideo, 0, 0); |
2811 | } | 2567 | } |
2812 | 2568 | ||
@@ -2826,12 +2582,11 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo) | |||
2826 | 2582 | ||
2827 | andSISIDXREG(SISCR, 0x32, 0x3f); | 2583 | andSISIDXREG(SISCR, 0x32, 0x3f); |
2828 | 2584 | ||
2829 | if(ivideo->vbflags & VB_301C) { | 2585 | if(ivideo->vbflags2 & VB2_30xCLV) { |
2830 | orSISIDXREG(SISPART4,0x0d,0x04); | 2586 | orSISIDXREG(SISPART4,0x0d,0x04); |
2831 | } | 2587 | } |
2832 | 2588 | ||
2833 | if((ivideo->sisvga_engine == SIS_315_VGA) && | 2589 | if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) { |
2834 | (ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV|VB_302ELV))) { | ||
2835 | outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10)); | 2590 | outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10)); |
2836 | SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000); | 2591 | SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000); |
2837 | if((result = SISDoSense(ivideo, svhs, 0x0604))) { | 2592 | if((result = SISDoSense(ivideo, svhs, 0x0604))) { |
@@ -2864,7 +2619,7 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo) | |||
2864 | outSISIDXREG(SISPART4,0x0d,backupP4_0d); | 2619 | outSISIDXREG(SISPART4,0x0d,backupP4_0d); |
2865 | outSISIDXREG(SISSR,0x1e,backupSR_1e); | 2620 | outSISIDXREG(SISSR,0x1e,backupSR_1e); |
2866 | 2621 | ||
2867 | if(ivideo->vbflags & VB_301C) { | 2622 | if(ivideo->vbflags2 & VB2_30xCLV) { |
2868 | inSISIDXREG(SISPART2,0x00,biosflag); | 2623 | inSISIDXREG(SISPART2,0x00,biosflag); |
2869 | if(biosflag & 0x20) { | 2624 | if(biosflag & 0x20) { |
2870 | for(myflag = 2; myflag > 0; myflag--) { | 2625 | for(myflag = 2; myflag > 0; myflag--) { |
@@ -2878,7 +2633,8 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo) | |||
2878 | } | 2633 | } |
2879 | 2634 | ||
2880 | /* Determine and detect attached TV's on Chrontel */ | 2635 | /* Determine and detect attached TV's on Chrontel */ |
2881 | static void __devinit SiS_SenseCh(struct sis_video_info *ivideo) | 2636 | static void __devinit |
2637 | SiS_SenseCh(struct sis_video_info *ivideo) | ||
2882 | { | 2638 | { |
2883 | #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315) | 2639 | #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315) |
2884 | u8 temp1, temp2; | 2640 | u8 temp1, temp2; |
@@ -2899,7 +2655,7 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo) | |||
2899 | /* See Chrontel TB31 for explanation */ | 2655 | /* See Chrontel TB31 for explanation */ |
2900 | temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e); | 2656 | temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e); |
2901 | if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) { | 2657 | if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) { |
2902 | SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b0e); | 2658 | SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b); |
2903 | SiS_DDC2Delay(&ivideo->SiS_Pr, 300); | 2659 | SiS_DDC2Delay(&ivideo->SiS_Pr, 300); |
2904 | } | 2660 | } |
2905 | temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25); | 2661 | temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25); |
@@ -2909,15 +2665,15 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo) | |||
2909 | /* Read power status */ | 2665 | /* Read power status */ |
2910 | temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e); | 2666 | temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e); |
2911 | if((temp1 & 0x03) != 0x03) { | 2667 | if((temp1 & 0x03) != 0x03) { |
2912 | /* Power all outputs */ | 2668 | /* Power all outputs */ |
2913 | SiS_SetCH700x(&ivideo->SiS_Pr, 0x0B0E); | 2669 | SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b); |
2914 | SiS_DDC2Delay(&ivideo->SiS_Pr, 300); | 2670 | SiS_DDC2Delay(&ivideo->SiS_Pr, 300); |
2915 | } | 2671 | } |
2916 | /* Sense connected TV devices */ | 2672 | /* Sense connected TV devices */ |
2917 | for(i = 0; i < 3; i++) { | 2673 | for(i = 0; i < 3; i++) { |
2918 | SiS_SetCH700x(&ivideo->SiS_Pr, 0x0110); | 2674 | SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01); |
2919 | SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); | 2675 | SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); |
2920 | SiS_SetCH700x(&ivideo->SiS_Pr, 0x0010); | 2676 | SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00); |
2921 | SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); | 2677 | SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); |
2922 | temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10); | 2678 | temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10); |
2923 | if(!(temp1 & 0x08)) test[i] = 0x02; | 2679 | if(!(temp1 & 0x08)) test[i] = 0x02; |
@@ -2930,7 +2686,7 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo) | |||
2930 | else if(test[0] == test[2]) temp1 = test[0]; | 2686 | else if(test[0] == test[2]) temp1 = test[0]; |
2931 | else if(test[1] == test[2]) temp1 = test[1]; | 2687 | else if(test[1] == test[2]) temp1 = test[1]; |
2932 | else { | 2688 | else { |
2933 | printk(KERN_INFO | 2689 | printk(KERN_INFO |
2934 | "sisfb: TV detection unreliable - test results varied\n"); | 2690 | "sisfb: TV detection unreliable - test results varied\n"); |
2935 | temp1 = test[2]; | 2691 | temp1 = test[2]; |
2936 | } | 2692 | } |
@@ -2945,11 +2701,11 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo) | |||
2945 | orSISIDXREG(SISCR, 0x32, 0x01); | 2701 | orSISIDXREG(SISCR, 0x32, 0x01); |
2946 | andSISIDXREG(SISCR, 0x32, ~0x06); | 2702 | andSISIDXREG(SISCR, 0x32, ~0x06); |
2947 | } else { | 2703 | } else { |
2948 | SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x010E,0xF8); | 2704 | SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8); |
2949 | andSISIDXREG(SISCR, 0x32, ~0x07); | 2705 | andSISIDXREG(SISCR, 0x32, ~0x07); |
2950 | } | 2706 | } |
2951 | } else if(temp1 == 0) { | 2707 | } else if(temp1 == 0) { |
2952 | SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x010E,0xF8); | 2708 | SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8); |
2953 | andSISIDXREG(SISCR, 0x32, ~0x07); | 2709 | andSISIDXREG(SISCR, 0x32, ~0x07); |
2954 | } | 2710 | } |
2955 | /* Set general purpose IO for Chrontel communication */ | 2711 | /* Set general purpose IO for Chrontel communication */ |
@@ -2960,19 +2716,19 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo) | |||
2960 | 2716 | ||
2961 | #ifdef CONFIG_FB_SIS_315 | 2717 | #ifdef CONFIG_FB_SIS_315 |
2962 | ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */ | 2718 | ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */ |
2963 | temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49); | 2719 | temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49); |
2964 | SiS_SetCH701x(&ivideo->SiS_Pr, 0x2049); | 2720 | SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20); |
2965 | SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); | 2721 | SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); |
2966 | temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20); | 2722 | temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20); |
2967 | temp2 |= 0x01; | 2723 | temp2 |= 0x01; |
2968 | SiS_SetCH701x(&ivideo->SiS_Pr, (temp2 << 8) | 0x20); | 2724 | SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2); |
2969 | SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); | 2725 | SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); |
2970 | temp2 ^= 0x01; | 2726 | temp2 ^= 0x01; |
2971 | SiS_SetCH701x(&ivideo->SiS_Pr, (temp2 << 8) | 0x20); | 2727 | SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2); |
2972 | SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); | 2728 | SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); |
2973 | temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20); | 2729 | temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20); |
2974 | SiS_SetCH701x(&ivideo->SiS_Pr, (temp1 << 8) | 0x49); | 2730 | SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1); |
2975 | temp1 = 0; | 2731 | temp1 = 0; |
2976 | if(temp2 & 0x02) temp1 |= 0x01; | 2732 | if(temp2 & 0x02) temp1 |= 0x01; |
2977 | if(temp2 & 0x10) temp1 |= 0x01; | 2733 | if(temp2 & 0x10) temp1 |= 0x01; |
2978 | if(temp2 & 0x04) temp1 |= 0x02; | 2734 | if(temp2 & 0x04) temp1 |= 0x02; |
@@ -2983,18 +2739,18 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo) | |||
2983 | ivideo->vbflags |= TV_AVIDEO; | 2739 | ivideo->vbflags |= TV_AVIDEO; |
2984 | orSISIDXREG(SISCR, 0x32, 0x01); | 2740 | orSISIDXREG(SISCR, 0x32, 0x01); |
2985 | andSISIDXREG(SISCR, 0x32, ~0x06); | 2741 | andSISIDXREG(SISCR, 0x32, ~0x06); |
2986 | break; | 2742 | break; |
2987 | case 0x02: | 2743 | case 0x02: |
2988 | printk(KERN_INFO "%s SVIDEO output\n", stdstr); | 2744 | printk(KERN_INFO "%s SVIDEO output\n", stdstr); |
2989 | ivideo->vbflags |= TV_SVIDEO; | 2745 | ivideo->vbflags |= TV_SVIDEO; |
2990 | orSISIDXREG(SISCR, 0x32, 0x02); | 2746 | orSISIDXREG(SISCR, 0x32, 0x02); |
2991 | andSISIDXREG(SISCR, 0x32, ~0x05); | 2747 | andSISIDXREG(SISCR, 0x32, ~0x05); |
2992 | break; | 2748 | break; |
2993 | case 0x04: | 2749 | case 0x04: |
2994 | printk(KERN_INFO "%s SCART output\n", stdstr); | 2750 | printk(KERN_INFO "%s SCART output\n", stdstr); |
2995 | orSISIDXREG(SISCR, 0x32, 0x04); | 2751 | orSISIDXREG(SISCR, 0x32, 0x04); |
2996 | andSISIDXREG(SISCR, 0x32, ~0x03); | 2752 | andSISIDXREG(SISCR, 0x32, ~0x03); |
2997 | break; | 2753 | break; |
2998 | default: | 2754 | default: |
2999 | andSISIDXREG(SISCR, 0x32, ~0x07); | 2755 | andSISIDXREG(SISCR, 0x32, ~0x07); |
3000 | } | 2756 | } |
@@ -3002,165 +2758,589 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo) | |||
3002 | } | 2758 | } |
3003 | } | 2759 | } |
3004 | 2760 | ||
3005 | /* ------------------------ Heap routines -------------------------- */ | 2761 | static void __devinit |
3006 | 2762 | sisfb_get_VB_type(struct sis_video_info *ivideo) | |
3007 | static u32 __devinit | ||
3008 | sisfb_getheapstart(struct sis_video_info *ivideo) | ||
3009 | { | 2763 | { |
3010 | u32 ret = ivideo->sisfb_parm_mem * 1024; | 2764 | char stdstr[] = "sisfb: Detected"; |
3011 | u32 max = ivideo->video_size - ivideo->hwcursor_size; | 2765 | char bridgestr[] = "video bridge"; |
3012 | u32 def; | 2766 | u8 vb_chipid; |
2767 | u8 reg; | ||
3013 | 2768 | ||
3014 | /* Calculate heap start = end of memory for console | 2769 | /* No CRT2 on XGI Z7 */ |
3015 | * | 2770 | if(ivideo->chip == XGI_20) |
3016 | * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ | 2771 | return; |
3017 | * C = console, D = heap, H = HWCursor, Q = cmd-queue | ||
3018 | * | ||
3019 | * Basically given by "mem" parameter | ||
3020 | * | ||
3021 | * maximum = videosize - cmd_queue - hwcursor | ||
3022 | * (results in a heap of size 0) | ||
3023 | * default = SiS 300: depends on videosize | ||
3024 | * SiS 315/330: 32k below max | ||
3025 | */ | ||
3026 | 2772 | ||
3027 | if(ivideo->sisvga_engine == SIS_300_VGA) { | 2773 | inSISIDXREG(SISPART4, 0x00, vb_chipid); |
3028 | max -= TURBO_QUEUE_AREA_SIZE; | 2774 | switch(vb_chipid) { |
3029 | if(ivideo->video_size > 0x1000000) { | 2775 | case 0x01: |
3030 | def = 0xc00000; | 2776 | inSISIDXREG(SISPART4, 0x01, reg); |
3031 | } else if(ivideo->video_size > 0x800000) { | 2777 | if(reg < 0xb0) { |
3032 | def = 0x800000; | 2778 | ivideo->vbflags |= VB_301; /* Deprecated */ |
3033 | } else { | 2779 | ivideo->vbflags2 |= VB2_301; |
3034 | def = 0x400000; | 2780 | printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr); |
3035 | } | 2781 | } else if(reg < 0xc0) { |
3036 | } else { | 2782 | ivideo->vbflags |= VB_301B; /* Deprecated */ |
3037 | max -= COMMAND_QUEUE_AREA_SIZE; | 2783 | ivideo->vbflags2 |= VB2_301B; |
3038 | def = max - 0x8000; | 2784 | inSISIDXREG(SISPART4,0x23,reg); |
2785 | if(!(reg & 0x02)) { | ||
2786 | ivideo->vbflags |= VB_30xBDH; /* Deprecated */ | ||
2787 | ivideo->vbflags2 |= VB2_30xBDH; | ||
2788 | printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr); | ||
2789 | } else { | ||
2790 | printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr); | ||
2791 | } | ||
2792 | } else if(reg < 0xd0) { | ||
2793 | ivideo->vbflags |= VB_301C; /* Deprecated */ | ||
2794 | ivideo->vbflags2 |= VB2_301C; | ||
2795 | printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr); | ||
2796 | } else if(reg < 0xe0) { | ||
2797 | ivideo->vbflags |= VB_301LV; /* Deprecated */ | ||
2798 | ivideo->vbflags2 |= VB2_301LV; | ||
2799 | printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr); | ||
2800 | } else if(reg <= 0xe1) { | ||
2801 | inSISIDXREG(SISPART4,0x39,reg); | ||
2802 | if(reg == 0xff) { | ||
2803 | ivideo->vbflags |= VB_302LV; /* Deprecated */ | ||
2804 | ivideo->vbflags2 |= VB2_302LV; | ||
2805 | printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr); | ||
2806 | } else { | ||
2807 | ivideo->vbflags |= VB_301C; /* Deprecated */ | ||
2808 | ivideo->vbflags2 |= VB2_301C; | ||
2809 | printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr); | ||
2810 | #if 0 | ||
2811 | ivideo->vbflags |= VB_302ELV; /* Deprecated */ | ||
2812 | ivideo->vbflags2 |= VB2_302ELV; | ||
2813 | printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr); | ||
2814 | #endif | ||
2815 | } | ||
2816 | } | ||
2817 | break; | ||
2818 | case 0x02: | ||
2819 | ivideo->vbflags |= VB_302B; /* Deprecated */ | ||
2820 | ivideo->vbflags2 |= VB2_302B; | ||
2821 | printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr); | ||
2822 | break; | ||
3039 | } | 2823 | } |
3040 | 2824 | ||
3041 | if((!ret) || (ret > max) || (ivideo->cardnumber != 0)) { | 2825 | if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) { |
3042 | ret = def; | 2826 | inSISIDXREG(SISCR, 0x37, reg); |
3043 | } | 2827 | reg &= SIS_EXTERNAL_CHIP_MASK; |
2828 | reg >>= 1; | ||
2829 | if(ivideo->sisvga_engine == SIS_300_VGA) { | ||
2830 | #ifdef CONFIG_FB_SIS_300 | ||
2831 | switch(reg) { | ||
2832 | case SIS_EXTERNAL_CHIP_LVDS: | ||
2833 | ivideo->vbflags |= VB_LVDS; /* Deprecated */ | ||
2834 | ivideo->vbflags2 |= VB2_LVDS; | ||
2835 | break; | ||
2836 | case SIS_EXTERNAL_CHIP_TRUMPION: | ||
2837 | ivideo->vbflags |= (VB_LVDS | VB_TRUMPION); /* Deprecated */ | ||
2838 | ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION); | ||
2839 | break; | ||
2840 | case SIS_EXTERNAL_CHIP_CHRONTEL: | ||
2841 | ivideo->vbflags |= VB_CHRONTEL; /* Deprecated */ | ||
2842 | ivideo->vbflags2 |= VB2_CHRONTEL; | ||
2843 | break; | ||
2844 | case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL: | ||
2845 | ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */ | ||
2846 | ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL); | ||
2847 | break; | ||
2848 | } | ||
2849 | if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1; | ||
2850 | #endif | ||
2851 | } else if(ivideo->chip < SIS_661) { | ||
2852 | #ifdef CONFIG_FB_SIS_315 | ||
2853 | switch (reg) { | ||
2854 | case SIS310_EXTERNAL_CHIP_LVDS: | ||
2855 | ivideo->vbflags |= VB_LVDS; /* Deprecated */ | ||
2856 | ivideo->vbflags2 |= VB2_LVDS; | ||
2857 | break; | ||
2858 | case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL: | ||
2859 | ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */ | ||
2860 | ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL); | ||
2861 | break; | ||
2862 | } | ||
2863 | if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2; | ||
2864 | #endif | ||
2865 | } else if(ivideo->chip >= SIS_661) { | ||
2866 | #ifdef CONFIG_FB_SIS_315 | ||
2867 | inSISIDXREG(SISCR, 0x38, reg); | ||
2868 | reg >>= 5; | ||
2869 | switch(reg) { | ||
2870 | case 0x02: | ||
2871 | ivideo->vbflags |= VB_LVDS; /* Deprecated */ | ||
2872 | ivideo->vbflags2 |= VB2_LVDS; | ||
2873 | break; | ||
2874 | case 0x03: | ||
2875 | ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */ | ||
2876 | ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL); | ||
2877 | break; | ||
2878 | case 0x04: | ||
2879 | ivideo->vbflags |= (VB_LVDS | VB_CONEXANT); /* Deprecated */ | ||
2880 | ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT); | ||
2881 | break; | ||
2882 | } | ||
2883 | if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2; | ||
2884 | #endif | ||
2885 | } | ||
2886 | if(ivideo->vbflags2 & VB2_LVDS) { | ||
2887 | printk(KERN_INFO "%s LVDS transmitter\n", stdstr); | ||
2888 | } | ||
2889 | if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) { | ||
2890 | printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr); | ||
2891 | } | ||
2892 | if(ivideo->vbflags2 & VB2_CHRONTEL) { | ||
2893 | printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr); | ||
2894 | } | ||
2895 | if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) { | ||
2896 | printk(KERN_INFO "%s Conexant external device\n", stdstr); | ||
2897 | } | ||
2898 | } | ||
3044 | 2899 | ||
3045 | return ret; | 2900 | if(ivideo->vbflags2 & VB2_SISBRIDGE) { |
2901 | SiS_SenseLCD(ivideo); | ||
2902 | SiS_Sense30x(ivideo); | ||
2903 | } else if(ivideo->vbflags2 & VB2_CHRONTEL) { | ||
2904 | SiS_SenseCh(ivideo); | ||
2905 | } | ||
3046 | } | 2906 | } |
3047 | 2907 | ||
3048 | static int __devinit | 2908 | /* ---------- Engine initialization routines ------------ */ |
3049 | sisfb_heap_init(struct sis_video_info *ivideo) | 2909 | |
2910 | static void | ||
2911 | sisfb_engine_init(struct sis_video_info *ivideo) | ||
3050 | { | 2912 | { |
3051 | SIS_OH *poh; | ||
3052 | 2913 | ||
3053 | ivideo->heapstart = ivideo->sisfb_mem = sisfb_getheapstart(ivideo); | 2914 | /* Initialize command queue (we use MMIO only) */ |
3054 | 2915 | ||
3055 | ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart; | 2916 | /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */ |
3056 | ivideo->sisfb_heap_end = ivideo->video_vbase + ivideo->video_size; | ||
3057 | 2917 | ||
3058 | /* Initialize command queue (We use MMIO only) */ | 2918 | ivideo->caps &= ~(TURBO_QUEUE_CAP | |
2919 | MMIO_CMD_QUEUE_CAP | | ||
2920 | VM_CMD_QUEUE_CAP | | ||
2921 | AGP_CMD_QUEUE_CAP); | ||
2922 | |||
2923 | #ifdef CONFIG_FB_SIS_300 | ||
2924 | if(ivideo->sisvga_engine == SIS_300_VGA) { | ||
2925 | u32 tqueue_pos; | ||
2926 | u8 tq_state; | ||
2927 | |||
2928 | tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024); | ||
2929 | |||
2930 | inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state); | ||
2931 | tq_state |= 0xf0; | ||
2932 | tq_state &= 0xfc; | ||
2933 | tq_state |= (u8)(tqueue_pos >> 8); | ||
2934 | outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state); | ||
2935 | |||
2936 | outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff)); | ||
2937 | |||
2938 | ivideo->caps |= TURBO_QUEUE_CAP; | ||
2939 | } | ||
2940 | #endif | ||
3059 | 2941 | ||
3060 | #ifdef CONFIG_FB_SIS_315 | 2942 | #ifdef CONFIG_FB_SIS_315 |
3061 | if(ivideo->sisvga_engine == SIS_315_VGA) { | 2943 | if(ivideo->sisvga_engine == SIS_315_VGA) { |
3062 | u32 tempq = 0; | 2944 | u32 tempq = 0, templ; |
3063 | u8 temp = 0; | 2945 | u8 temp; |
2946 | |||
2947 | if(ivideo->chip == XGI_20) { | ||
2948 | switch(ivideo->cmdQueueSize) { | ||
2949 | case (64 * 1024): | ||
2950 | temp = SIS_CMD_QUEUE_SIZE_Z7_64k; | ||
2951 | break; | ||
2952 | case (128 * 1024): | ||
2953 | default: | ||
2954 | temp = SIS_CMD_QUEUE_SIZE_Z7_128k; | ||
2955 | } | ||
2956 | } else { | ||
2957 | switch(ivideo->cmdQueueSize) { | ||
2958 | case (4 * 1024 * 1024): | ||
2959 | temp = SIS_CMD_QUEUE_SIZE_4M; | ||
2960 | break; | ||
2961 | case (2 * 1024 * 1024): | ||
2962 | temp = SIS_CMD_QUEUE_SIZE_2M; | ||
2963 | break; | ||
2964 | case (1 * 1024 * 1024): | ||
2965 | temp = SIS_CMD_QUEUE_SIZE_1M; | ||
2966 | break; | ||
2967 | default: | ||
2968 | case (512 * 1024): | ||
2969 | temp = SIS_CMD_QUEUE_SIZE_512k; | ||
2970 | } | ||
2971 | } | ||
2972 | |||
2973 | outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD); | ||
2974 | outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET); | ||
2975 | |||
2976 | if((ivideo->chip >= XGI_40) && ivideo->modechanged) { | ||
2977 | /* Must disable dual pipe on XGI_40. Can't do | ||
2978 | * this in MMIO mode, because it requires | ||
2979 | * setting/clearing a bit in the MMIO fire trigger | ||
2980 | * register. | ||
2981 | */ | ||
2982 | if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) { | ||
2983 | |||
2984 | MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0); | ||
2985 | |||
2986 | outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE)); | ||
2987 | |||
2988 | tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR); | ||
2989 | MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq); | ||
2990 | |||
2991 | tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize); | ||
2992 | MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq); | ||
2993 | |||
2994 | writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq); | ||
2995 | writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4); | ||
2996 | writel(0x168F0000, ivideo->video_vbase + tempq + 8); | ||
2997 | writel(0x168F0000, ivideo->video_vbase + tempq + 12); | ||
2998 | |||
2999 | MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16)); | ||
3000 | |||
3001 | sisfb_syncaccel(ivideo); | ||
3002 | |||
3003 | outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET); | ||
3004 | |||
3005 | } | ||
3006 | } | ||
3007 | |||
3008 | tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT); | ||
3009 | MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq); | ||
3010 | |||
3011 | temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR); | ||
3012 | outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp); | ||
3013 | |||
3014 | tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize); | ||
3015 | MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq); | ||
3064 | 3016 | ||
3065 | ivideo->sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE; | 3017 | ivideo->caps |= MMIO_CMD_QUEUE_CAP; |
3018 | } | ||
3019 | #endif | ||
3066 | 3020 | ||
3067 | outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD); | 3021 | ivideo->engineok = 1; |
3068 | outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET); | 3022 | } |
3069 | 3023 | ||
3070 | tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT); | 3024 | static void __devinit |
3071 | MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq); | 3025 | sisfb_detect_lcd_type(struct sis_video_info *ivideo) |
3026 | { | ||
3027 | u8 reg; | ||
3028 | int i; | ||
3072 | 3029 | ||
3073 | temp = SIS_CMD_QUEUE_SIZE_512k; | 3030 | inSISIDXREG(SISCR, 0x36, reg); |
3074 | temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR); | 3031 | reg &= 0x0f; |
3075 | outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp); | 3032 | if(ivideo->sisvga_engine == SIS_300_VGA) { |
3033 | ivideo->CRT2LCDType = sis300paneltype[reg]; | ||
3034 | } else if(ivideo->chip >= SIS_661) { | ||
3035 | ivideo->CRT2LCDType = sis661paneltype[reg]; | ||
3036 | } else { | ||
3037 | ivideo->CRT2LCDType = sis310paneltype[reg]; | ||
3038 | if((ivideo->chip == SIS_550) && (sisfb_fstn)) { | ||
3039 | if((ivideo->CRT2LCDType != LCD_320x240_2) && | ||
3040 | (ivideo->CRT2LCDType != LCD_320x240_3)) { | ||
3041 | ivideo->CRT2LCDType = LCD_320x240; | ||
3042 | } | ||
3043 | } | ||
3044 | } | ||
3076 | 3045 | ||
3077 | tempq = (u32)(ivideo->video_size - COMMAND_QUEUE_AREA_SIZE); | 3046 | if(ivideo->CRT2LCDType == LCD_UNKNOWN) { |
3078 | MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq); | 3047 | /* For broken BIOSes: Assume 1024x768, RGB18 */ |
3048 | ivideo->CRT2LCDType = LCD_1024x768; | ||
3049 | setSISIDXREG(SISCR,0x36,0xf0,0x02); | ||
3050 | setSISIDXREG(SISCR,0x37,0xee,0x01); | ||
3051 | printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg); | ||
3052 | } | ||
3079 | 3053 | ||
3080 | ivideo->caps |= MMIO_CMD_QUEUE_CAP; | 3054 | for(i = 0; i < SIS_LCD_NUMBER; i++) { |
3081 | } | 3055 | if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) { |
3056 | ivideo->lcdxres = sis_lcd_data[i].xres; | ||
3057 | ivideo->lcdyres = sis_lcd_data[i].yres; | ||
3058 | ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx; | ||
3059 | break; | ||
3060 | } | ||
3061 | } | ||
3062 | |||
3063 | #ifdef CONFIG_FB_SIS_300 | ||
3064 | if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) { | ||
3065 | ivideo->lcdxres = 1360; ivideo->lcdyres = 1024; | ||
3066 | ivideo->lcddefmodeidx = DEFAULT_MODE_1360; | ||
3067 | } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) { | ||
3068 | ivideo->lcdxres = 848; ivideo->lcdyres = 480; | ||
3069 | ivideo->lcddefmodeidx = DEFAULT_MODE_848; | ||
3070 | } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) { | ||
3071 | ivideo->lcdxres = 856; ivideo->lcdyres = 480; | ||
3072 | ivideo->lcddefmodeidx = DEFAULT_MODE_856; | ||
3073 | } | ||
3082 | #endif | 3074 | #endif |
3083 | 3075 | ||
3076 | printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n", | ||
3077 | ivideo->lcdxres, ivideo->lcdyres); | ||
3078 | } | ||
3079 | |||
3080 | static void __devinit | ||
3081 | sisfb_save_pdc_emi(struct sis_video_info *ivideo) | ||
3082 | { | ||
3084 | #ifdef CONFIG_FB_SIS_300 | 3083 | #ifdef CONFIG_FB_SIS_300 |
3085 | if(ivideo->sisvga_engine == SIS_300_VGA) { | 3084 | /* Save the current PanelDelayCompensation if the LCD is currently used */ |
3086 | unsigned long tqueue_pos; | 3085 | if(ivideo->sisvga_engine == SIS_300_VGA) { |
3087 | u8 tq_state; | 3086 | if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) { |
3087 | int tmp; | ||
3088 | inSISIDXREG(SISCR,0x30,tmp); | ||
3089 | if(tmp & 0x20) { | ||
3090 | /* Currently on LCD? If yes, read current pdc */ | ||
3091 | inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc); | ||
3092 | ivideo->detectedpdc &= 0x3c; | ||
3093 | if(ivideo->SiS_Pr.PDC == -1) { | ||
3094 | /* Let option override detection */ | ||
3095 | ivideo->SiS_Pr.PDC = ivideo->detectedpdc; | ||
3096 | } | ||
3097 | printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n", | ||
3098 | ivideo->detectedpdc); | ||
3099 | } | ||
3100 | if((ivideo->SiS_Pr.PDC != -1) && | ||
3101 | (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) { | ||
3102 | printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n", | ||
3103 | ivideo->SiS_Pr.PDC); | ||
3104 | } | ||
3105 | } | ||
3106 | } | ||
3107 | #endif | ||
3088 | 3108 | ||
3089 | ivideo->sisfb_heap_end -= TURBO_QUEUE_AREA_SIZE; | 3109 | #ifdef CONFIG_FB_SIS_315 |
3110 | if(ivideo->sisvga_engine == SIS_315_VGA) { | ||
3090 | 3111 | ||
3091 | tqueue_pos = (ivideo->video_size - TURBO_QUEUE_AREA_SIZE) / (64 * 1024); | 3112 | /* Try to find about LCDA */ |
3113 | if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) { | ||
3114 | int tmp; | ||
3115 | inSISIDXREG(SISPART1,0x13,tmp); | ||
3116 | if(tmp & 0x04) { | ||
3117 | ivideo->SiS_Pr.SiS_UseLCDA = TRUE; | ||
3118 | ivideo->detectedlcda = 0x03; | ||
3119 | } | ||
3120 | } | ||
3092 | 3121 | ||
3093 | inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state); | 3122 | /* Save PDC */ |
3094 | tq_state |= 0xf0; | 3123 | if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) { |
3095 | tq_state &= 0xfc; | 3124 | int tmp; |
3096 | tq_state |= (u8)(tqueue_pos >> 8); | 3125 | inSISIDXREG(SISCR,0x30,tmp); |
3097 | outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state); | 3126 | if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) { |
3127 | /* Currently on LCD? If yes, read current pdc */ | ||
3128 | u8 pdc; | ||
3129 | inSISIDXREG(SISPART1,0x2D,pdc); | ||
3130 | ivideo->detectedpdc = (pdc & 0x0f) << 1; | ||
3131 | ivideo->detectedpdca = (pdc & 0xf0) >> 3; | ||
3132 | inSISIDXREG(SISPART1,0x35,pdc); | ||
3133 | ivideo->detectedpdc |= ((pdc >> 7) & 0x01); | ||
3134 | inSISIDXREG(SISPART1,0x20,pdc); | ||
3135 | ivideo->detectedpdca |= ((pdc >> 6) & 0x01); | ||
3136 | if(ivideo->newrom) { | ||
3137 | /* New ROM invalidates other PDC resp. */ | ||
3138 | if(ivideo->detectedlcda != 0xff) { | ||
3139 | ivideo->detectedpdc = 0xff; | ||
3140 | } else { | ||
3141 | ivideo->detectedpdca = 0xff; | ||
3142 | } | ||
3143 | } | ||
3144 | if(ivideo->SiS_Pr.PDC == -1) { | ||
3145 | if(ivideo->detectedpdc != 0xff) { | ||
3146 | ivideo->SiS_Pr.PDC = ivideo->detectedpdc; | ||
3147 | } | ||
3148 | } | ||
3149 | if(ivideo->SiS_Pr.PDCA == -1) { | ||
3150 | if(ivideo->detectedpdca != 0xff) { | ||
3151 | ivideo->SiS_Pr.PDCA = ivideo->detectedpdca; | ||
3152 | } | ||
3153 | } | ||
3154 | if(ivideo->detectedpdc != 0xff) { | ||
3155 | printk(KERN_INFO | ||
3156 | "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n", | ||
3157 | ivideo->detectedpdc); | ||
3158 | } | ||
3159 | if(ivideo->detectedpdca != 0xff) { | ||
3160 | printk(KERN_INFO | ||
3161 | "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n", | ||
3162 | ivideo->detectedpdca); | ||
3163 | } | ||
3164 | } | ||
3098 | 3165 | ||
3099 | outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff)); | 3166 | /* Save EMI */ |
3167 | if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) { | ||
3168 | inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30); | ||
3169 | inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31); | ||
3170 | inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32); | ||
3171 | inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33); | ||
3172 | ivideo->SiS_Pr.HaveEMI = TRUE; | ||
3173 | if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) { | ||
3174 | ivideo->SiS_Pr.HaveEMILCD = TRUE; | ||
3175 | } | ||
3176 | } | ||
3177 | } | ||
3100 | 3178 | ||
3101 | ivideo->caps |= TURBO_QUEUE_CAP; | 3179 | /* Let user override detected PDCs (all bridges) */ |
3102 | } | 3180 | if(ivideo->vbflags2 & VB2_30xBLV) { |
3181 | if((ivideo->SiS_Pr.PDC != -1) && | ||
3182 | (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) { | ||
3183 | printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n", | ||
3184 | ivideo->SiS_Pr.PDC); | ||
3185 | } | ||
3186 | if((ivideo->SiS_Pr.PDCA != -1) && | ||
3187 | (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) { | ||
3188 | printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n", | ||
3189 | ivideo->SiS_Pr.PDCA); | ||
3190 | } | ||
3191 | } | ||
3192 | |||
3193 | } | ||
3103 | #endif | 3194 | #endif |
3195 | } | ||
3104 | 3196 | ||
3105 | /* Reserve memory for the HWCursor */ | 3197 | /* -------------------- Memory manager routines ---------------------- */ |
3106 | ivideo->sisfb_heap_end -= ivideo->hwcursor_size; | ||
3107 | ivideo->hwcursor_vbase = ivideo->sisfb_heap_end; | ||
3108 | ivideo->caps |= HW_CURSOR_CAP; | ||
3109 | 3198 | ||
3110 | ivideo->sisfb_heap_size = ivideo->sisfb_heap_end - ivideo->sisfb_heap_start; | 3199 | static u32 __devinit |
3200 | sisfb_getheapstart(struct sis_video_info *ivideo) | ||
3201 | { | ||
3202 | u32 ret = ivideo->sisfb_parm_mem * 1024; | ||
3203 | u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize; | ||
3204 | u32 def; | ||
3111 | 3205 | ||
3112 | if(ivideo->cardnumber == 0) { | 3206 | /* Calculate heap start = end of memory for console |
3207 | * | ||
3208 | * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ | ||
3209 | * C = console, D = heap, H = HWCursor, Q = cmd-queue | ||
3210 | * | ||
3211 | * On 76x in UMA+LFB mode, the layout is as follows: | ||
3212 | * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ | ||
3213 | * where the heap is the entire UMA area, eventually | ||
3214 | * into the LFB area if the given mem parameter is | ||
3215 | * higher than the size of the UMA memory. | ||
3216 | * | ||
3217 | * Basically given by "mem" parameter | ||
3218 | * | ||
3219 | * maximum = videosize - cmd_queue - hwcursor | ||
3220 | * (results in a heap of size 0) | ||
3221 | * default = SiS 300: depends on videosize | ||
3222 | * SiS 315/330/340/XGI: 32k below max | ||
3223 | */ | ||
3113 | 3224 | ||
3114 | printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n", | 3225 | if(ivideo->sisvga_engine == SIS_300_VGA) { |
3115 | (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024)); | 3226 | if(ivideo->video_size > 0x1000000) { |
3227 | def = 0xc00000; | ||
3228 | } else if(ivideo->video_size > 0x800000) { | ||
3229 | def = 0x800000; | ||
3230 | } else { | ||
3231 | def = 0x400000; | ||
3232 | } | ||
3233 | } else if(ivideo->UMAsize && ivideo->LFBsize) { | ||
3234 | ret = def = 0; | ||
3235 | } else { | ||
3236 | def = maxoffs - 0x8000; | ||
3237 | } | ||
3116 | 3238 | ||
3117 | sisfb_heap.vinfo = ivideo; | 3239 | /* Use default for secondary card for now (FIXME) */ |
3240 | if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0)) | ||
3241 | ret = def; | ||
3118 | 3242 | ||
3119 | sisfb_heap.poha_chain = NULL; | 3243 | return ret; |
3120 | sisfb_heap.poh_freelist = NULL; | 3244 | } |
3121 | 3245 | ||
3122 | poh = sisfb_poh_new_node(); | 3246 | static u32 __devinit |
3123 | if(poh == NULL) return 1; | 3247 | sisfb_getheapsize(struct sis_video_info *ivideo) |
3248 | { | ||
3249 | u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize; | ||
3250 | u32 ret = 0; | ||
3251 | |||
3252 | if(ivideo->UMAsize && ivideo->LFBsize) { | ||
3253 | if( (!ivideo->sisfb_parm_mem) || | ||
3254 | ((ivideo->sisfb_parm_mem * 1024) > max) || | ||
3255 | ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) { | ||
3256 | ret = ivideo->UMAsize; | ||
3257 | max -= ivideo->UMAsize; | ||
3258 | } else { | ||
3259 | ret = max - (ivideo->sisfb_parm_mem * 1024); | ||
3260 | max = ivideo->sisfb_parm_mem * 1024; | ||
3261 | } | ||
3262 | ivideo->video_offset = ret; | ||
3263 | ivideo->sisfb_mem = max; | ||
3264 | } else { | ||
3265 | ret = max - ivideo->heapstart; | ||
3266 | ivideo->sisfb_mem = ivideo->heapstart; | ||
3267 | } | ||
3124 | 3268 | ||
3125 | poh->poh_next = &sisfb_heap.oh_free; | 3269 | return ret; |
3126 | poh->poh_prev = &sisfb_heap.oh_free; | 3270 | } |
3127 | poh->size = ivideo->sisfb_heap_size; | ||
3128 | poh->offset = ivideo->heapstart; | ||
3129 | 3271 | ||
3130 | sisfb_heap.oh_free.poh_next = poh; | 3272 | static int __devinit |
3131 | sisfb_heap.oh_free.poh_prev = poh; | 3273 | sisfb_heap_init(struct sis_video_info *ivideo) |
3132 | sisfb_heap.oh_free.size = 0; | 3274 | { |
3133 | sisfb_heap.max_freesize = poh->size; | 3275 | struct SIS_OH *poh; |
3134 | 3276 | ||
3135 | sisfb_heap.oh_used.poh_next = &sisfb_heap.oh_used; | 3277 | ivideo->video_offset = 0; |
3136 | sisfb_heap.oh_used.poh_prev = &sisfb_heap.oh_used; | 3278 | if(ivideo->sisfb_parm_mem) { |
3137 | sisfb_heap.oh_used.size = SENTINEL; | 3279 | if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) || |
3280 | (ivideo->sisfb_parm_mem > ivideo->video_size) ) { | ||
3281 | ivideo->sisfb_parm_mem = 0; | ||
3282 | } | ||
3283 | } | ||
3138 | 3284 | ||
3139 | } else { | 3285 | ivideo->heapstart = sisfb_getheapstart(ivideo); |
3286 | ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo); | ||
3140 | 3287 | ||
3141 | printk(KERN_INFO "Skipped heap initialization for secondary cards\n"); | 3288 | ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart; |
3289 | ivideo->sisfb_heap_end = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size; | ||
3142 | 3290 | ||
3143 | } | 3291 | printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n", |
3292 | (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024)); | ||
3144 | 3293 | ||
3145 | return 0; | 3294 | ivideo->sisfb_heap.vinfo = ivideo; |
3295 | |||
3296 | ivideo->sisfb_heap.poha_chain = NULL; | ||
3297 | ivideo->sisfb_heap.poh_freelist = NULL; | ||
3298 | |||
3299 | poh = sisfb_poh_new_node(&ivideo->sisfb_heap); | ||
3300 | if(poh == NULL) | ||
3301 | return 1; | ||
3302 | |||
3303 | poh->poh_next = &ivideo->sisfb_heap.oh_free; | ||
3304 | poh->poh_prev = &ivideo->sisfb_heap.oh_free; | ||
3305 | poh->size = ivideo->sisfb_heap_size; | ||
3306 | poh->offset = ivideo->heapstart; | ||
3307 | |||
3308 | ivideo->sisfb_heap.oh_free.poh_next = poh; | ||
3309 | ivideo->sisfb_heap.oh_free.poh_prev = poh; | ||
3310 | ivideo->sisfb_heap.oh_free.size = 0; | ||
3311 | ivideo->sisfb_heap.max_freesize = poh->size; | ||
3312 | |||
3313 | ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used; | ||
3314 | ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used; | ||
3315 | ivideo->sisfb_heap.oh_used.size = SENTINEL; | ||
3316 | |||
3317 | if(ivideo->cardnumber == 0) { | ||
3318 | /* For the first card, make this heap the "global" one | ||
3319 | * for old DRM (which could handle only one card) | ||
3320 | */ | ||
3321 | sisfb_heap = &ivideo->sisfb_heap; | ||
3322 | } | ||
3323 | |||
3324 | return 0; | ||
3146 | } | 3325 | } |
3147 | 3326 | ||
3148 | static SIS_OH * | 3327 | static struct SIS_OH * |
3149 | sisfb_poh_new_node(void) | 3328 | sisfb_poh_new_node(struct SIS_HEAP *memheap) |
3150 | { | 3329 | { |
3151 | int i; | 3330 | struct SIS_OHALLOC *poha; |
3152 | unsigned long cOhs; | 3331 | struct SIS_OH *poh; |
3153 | SIS_OHALLOC *poha; | 3332 | unsigned long cOhs; |
3154 | SIS_OH *poh; | 3333 | int i; |
3155 | 3334 | ||
3156 | if(sisfb_heap.poh_freelist == NULL) { | 3335 | if(memheap->poh_freelist == NULL) { |
3157 | poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL); | 3336 | poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL); |
3158 | if(!poha) return NULL; | 3337 | if(!poha) |
3338 | return NULL; | ||
3159 | 3339 | ||
3160 | poha->poha_next = sisfb_heap.poha_chain; | 3340 | poha->poha_next = memheap->poha_chain; |
3161 | sisfb_heap.poha_chain = poha; | 3341 | memheap->poha_chain = poha; |
3162 | 3342 | ||
3163 | cOhs = (SIS_OH_ALLOC_SIZE - sizeof(SIS_OHALLOC)) / sizeof(SIS_OH) + 1; | 3343 | cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1; |
3164 | 3344 | ||
3165 | poh = &poha->aoh[0]; | 3345 | poh = &poha->aoh[0]; |
3166 | for(i = cOhs - 1; i != 0; i--) { | 3346 | for(i = cOhs - 1; i != 0; i--) { |
@@ -3169,32 +3349,32 @@ sisfb_poh_new_node(void) | |||
3169 | } | 3349 | } |
3170 | 3350 | ||
3171 | poh->poh_next = NULL; | 3351 | poh->poh_next = NULL; |
3172 | sisfb_heap.poh_freelist = &poha->aoh[0]; | 3352 | memheap->poh_freelist = &poha->aoh[0]; |
3173 | } | 3353 | } |
3174 | 3354 | ||
3175 | poh = sisfb_heap.poh_freelist; | 3355 | poh = memheap->poh_freelist; |
3176 | sisfb_heap.poh_freelist = poh->poh_next; | 3356 | memheap->poh_freelist = poh->poh_next; |
3177 | 3357 | ||
3178 | return (poh); | 3358 | return poh; |
3179 | } | 3359 | } |
3180 | 3360 | ||
3181 | static SIS_OH * | 3361 | static struct SIS_OH * |
3182 | sisfb_poh_allocate(u32 size) | 3362 | sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size) |
3183 | { | 3363 | { |
3184 | SIS_OH *pohThis; | 3364 | struct SIS_OH *pohThis; |
3185 | SIS_OH *pohRoot; | 3365 | struct SIS_OH *pohRoot; |
3186 | int bAllocated = 0; | 3366 | int bAllocated = 0; |
3187 | 3367 | ||
3188 | if(size > sisfb_heap.max_freesize) { | 3368 | if(size > memheap->max_freesize) { |
3189 | DPRINTK("sisfb: Can't allocate %dk video memory\n", | 3369 | DPRINTK("sisfb: Can't allocate %dk video memory\n", |
3190 | (unsigned int) size / 1024); | 3370 | (unsigned int) size / 1024); |
3191 | return (NULL); | 3371 | return NULL; |
3192 | } | 3372 | } |
3193 | 3373 | ||
3194 | pohThis = sisfb_heap.oh_free.poh_next; | 3374 | pohThis = memheap->oh_free.poh_next; |
3195 | 3375 | ||
3196 | while(pohThis != &sisfb_heap.oh_free) { | 3376 | while(pohThis != &memheap->oh_free) { |
3197 | if (size <= pohThis->size) { | 3377 | if(size <= pohThis->size) { |
3198 | bAllocated = 1; | 3378 | bAllocated = 1; |
3199 | break; | 3379 | break; |
3200 | } | 3380 | } |
@@ -3204,18 +3384,16 @@ sisfb_poh_allocate(u32 size) | |||
3204 | if(!bAllocated) { | 3384 | if(!bAllocated) { |
3205 | DPRINTK("sisfb: Can't allocate %dk video memory\n", | 3385 | DPRINTK("sisfb: Can't allocate %dk video memory\n", |
3206 | (unsigned int) size / 1024); | 3386 | (unsigned int) size / 1024); |
3207 | return (NULL); | 3387 | return NULL; |
3208 | } | 3388 | } |
3209 | 3389 | ||
3210 | if(size == pohThis->size) { | 3390 | if(size == pohThis->size) { |
3211 | pohRoot = pohThis; | 3391 | pohRoot = pohThis; |
3212 | sisfb_delete_node(pohThis); | 3392 | sisfb_delete_node(pohThis); |
3213 | } else { | 3393 | } else { |
3214 | pohRoot = sisfb_poh_new_node(); | 3394 | pohRoot = sisfb_poh_new_node(memheap); |
3215 | 3395 | if(pohRoot == NULL) | |
3216 | if(pohRoot == NULL) { | 3396 | return NULL; |
3217 | return (NULL); | ||
3218 | } | ||
3219 | 3397 | ||
3220 | pohRoot->offset = pohThis->offset; | 3398 | pohRoot->offset = pohThis->offset; |
3221 | pohRoot->size = size; | 3399 | pohRoot->size = size; |
@@ -3224,33 +3402,25 @@ sisfb_poh_allocate(u32 size) | |||
3224 | pohThis->size -= size; | 3402 | pohThis->size -= size; |
3225 | } | 3403 | } |
3226 | 3404 | ||
3227 | sisfb_heap.max_freesize -= size; | 3405 | memheap->max_freesize -= size; |
3228 | 3406 | ||
3229 | pohThis = &sisfb_heap.oh_used; | 3407 | pohThis = &memheap->oh_used; |
3230 | sisfb_insert_node(pohThis, pohRoot); | 3408 | sisfb_insert_node(pohThis, pohRoot); |
3231 | 3409 | ||
3232 | return (pohRoot); | 3410 | return pohRoot; |
3233 | } | 3411 | } |
3234 | 3412 | ||
3235 | static void | 3413 | static void |
3236 | sisfb_delete_node(SIS_OH *poh) | 3414 | sisfb_delete_node(struct SIS_OH *poh) |
3237 | { | 3415 | { |
3238 | SIS_OH *poh_prev; | 3416 | poh->poh_prev->poh_next = poh->poh_next; |
3239 | SIS_OH *poh_next; | 3417 | poh->poh_next->poh_prev = poh->poh_prev; |
3240 | |||
3241 | poh_prev = poh->poh_prev; | ||
3242 | poh_next = poh->poh_next; | ||
3243 | |||
3244 | poh_prev->poh_next = poh_next; | ||
3245 | poh_next->poh_prev = poh_prev; | ||
3246 | } | 3418 | } |
3247 | 3419 | ||
3248 | static void | 3420 | static void |
3249 | sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh) | 3421 | sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh) |
3250 | { | 3422 | { |
3251 | SIS_OH *pohTemp; | 3423 | struct SIS_OH *pohTemp = pohList->poh_next; |
3252 | |||
3253 | pohTemp = pohList->poh_next; | ||
3254 | 3424 | ||
3255 | pohList->poh_next = poh; | 3425 | pohList->poh_next = poh; |
3256 | pohTemp->poh_prev = poh; | 3426 | pohTemp->poh_prev = poh; |
@@ -3259,20 +3429,20 @@ sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh) | |||
3259 | poh->poh_next = pohTemp; | 3429 | poh->poh_next = pohTemp; |
3260 | } | 3430 | } |
3261 | 3431 | ||
3262 | static SIS_OH * | 3432 | static struct SIS_OH * |
3263 | sisfb_poh_free(u32 base) | 3433 | sisfb_poh_free(struct SIS_HEAP *memheap, u32 base) |
3264 | { | 3434 | { |
3265 | SIS_OH *pohThis; | 3435 | struct SIS_OH *pohThis; |
3266 | SIS_OH *poh_freed; | 3436 | struct SIS_OH *poh_freed; |
3267 | SIS_OH *poh_prev; | 3437 | struct SIS_OH *poh_prev; |
3268 | SIS_OH *poh_next; | 3438 | struct SIS_OH *poh_next; |
3269 | u32 ulUpper; | 3439 | u32 ulUpper; |
3270 | u32 ulLower; | 3440 | u32 ulLower; |
3271 | int foundNode = 0; | 3441 | int foundNode = 0; |
3272 | 3442 | ||
3273 | poh_freed = sisfb_heap.oh_used.poh_next; | 3443 | poh_freed = memheap->oh_used.poh_next; |
3274 | 3444 | ||
3275 | while(poh_freed != &sisfb_heap.oh_used) { | 3445 | while(poh_freed != &memheap->oh_used) { |
3276 | if(poh_freed->offset == base) { | 3446 | if(poh_freed->offset == base) { |
3277 | foundNode = 1; | 3447 | foundNode = 1; |
3278 | break; | 3448 | break; |
@@ -3281,17 +3451,18 @@ sisfb_poh_free(u32 base) | |||
3281 | poh_freed = poh_freed->poh_next; | 3451 | poh_freed = poh_freed->poh_next; |
3282 | } | 3452 | } |
3283 | 3453 | ||
3284 | if(!foundNode) return(NULL); | 3454 | if(!foundNode) |
3455 | return NULL; | ||
3285 | 3456 | ||
3286 | sisfb_heap.max_freesize += poh_freed->size; | 3457 | memheap->max_freesize += poh_freed->size; |
3287 | 3458 | ||
3288 | poh_prev = poh_next = NULL; | 3459 | poh_prev = poh_next = NULL; |
3289 | ulUpper = poh_freed->offset + poh_freed->size; | 3460 | ulUpper = poh_freed->offset + poh_freed->size; |
3290 | ulLower = poh_freed->offset; | 3461 | ulLower = poh_freed->offset; |
3291 | 3462 | ||
3292 | pohThis = sisfb_heap.oh_free.poh_next; | 3463 | pohThis = memheap->oh_free.poh_next; |
3293 | 3464 | ||
3294 | while(pohThis != &sisfb_heap.oh_free) { | 3465 | while(pohThis != &memheap->oh_free) { |
3295 | if(pohThis->offset == ulUpper) { | 3466 | if(pohThis->offset == ulUpper) { |
3296 | poh_next = pohThis; | 3467 | poh_next = pohThis; |
3297 | } else if((pohThis->offset + pohThis->size) == ulLower) { | 3468 | } else if((pohThis->offset + pohThis->size) == ulLower) { |
@@ -3305,70 +3476,88 @@ sisfb_poh_free(u32 base) | |||
3305 | if(poh_prev && poh_next) { | 3476 | if(poh_prev && poh_next) { |
3306 | poh_prev->size += (poh_freed->size + poh_next->size); | 3477 | poh_prev->size += (poh_freed->size + poh_next->size); |
3307 | sisfb_delete_node(poh_next); | 3478 | sisfb_delete_node(poh_next); |
3308 | sisfb_free_node(poh_freed); | 3479 | sisfb_free_node(memheap, poh_freed); |
3309 | sisfb_free_node(poh_next); | 3480 | sisfb_free_node(memheap, poh_next); |
3310 | return(poh_prev); | 3481 | return poh_prev; |
3311 | } | 3482 | } |
3312 | 3483 | ||
3313 | if(poh_prev) { | 3484 | if(poh_prev) { |
3314 | poh_prev->size += poh_freed->size; | 3485 | poh_prev->size += poh_freed->size; |
3315 | sisfb_free_node(poh_freed); | 3486 | sisfb_free_node(memheap, poh_freed); |
3316 | return(poh_prev); | 3487 | return poh_prev; |
3317 | } | 3488 | } |
3318 | 3489 | ||
3319 | if(poh_next) { | 3490 | if(poh_next) { |
3320 | poh_next->size += poh_freed->size; | 3491 | poh_next->size += poh_freed->size; |
3321 | poh_next->offset = poh_freed->offset; | 3492 | poh_next->offset = poh_freed->offset; |
3322 | sisfb_free_node(poh_freed); | 3493 | sisfb_free_node(memheap, poh_freed); |
3323 | return(poh_next); | 3494 | return poh_next; |
3324 | } | 3495 | } |
3325 | 3496 | ||
3326 | sisfb_insert_node(&sisfb_heap.oh_free, poh_freed); | 3497 | sisfb_insert_node(&memheap->oh_free, poh_freed); |
3327 | 3498 | ||
3328 | return(poh_freed); | 3499 | return poh_freed; |
3329 | } | 3500 | } |
3330 | 3501 | ||
3331 | static void | 3502 | static void |
3332 | sisfb_free_node(SIS_OH *poh) | 3503 | sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh) |
3333 | { | 3504 | { |
3334 | if(poh == NULL) return; | 3505 | if(poh == NULL) |
3506 | return; | ||
3335 | 3507 | ||
3336 | poh->poh_next = sisfb_heap.poh_freelist; | 3508 | poh->poh_next = memheap->poh_freelist; |
3337 | sisfb_heap.poh_freelist = poh; | 3509 | memheap->poh_freelist = poh; |
3338 | } | 3510 | } |
3339 | 3511 | ||
3340 | void | 3512 | static void |
3341 | sis_malloc(struct sis_memreq *req) | 3513 | sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req) |
3342 | { | 3514 | { |
3343 | struct sis_video_info *ivideo = sisfb_heap.vinfo; | 3515 | struct SIS_OH *poh = NULL; |
3344 | SIS_OH *poh = NULL; | ||
3345 | 3516 | ||
3346 | if((ivideo) && (!ivideo->havenoheap)) { | 3517 | if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap)) |
3347 | poh = sisfb_poh_allocate((u32)req->size); | 3518 | poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size); |
3348 | } | ||
3349 | 3519 | ||
3350 | if(poh == NULL) { | 3520 | if(poh == NULL) { |
3351 | req->offset = req->size = 0; | 3521 | req->offset = req->size = 0; |
3352 | DPRINTK("sisfb: Video RAM allocation failed\n"); | 3522 | DPRINTK("sisfb: Video RAM allocation failed\n"); |
3353 | } else { | 3523 | } else { |
3354 | req->offset = poh->offset; | 3524 | req->offset = poh->offset; |
3355 | req->size = poh->size; | 3525 | req->size = poh->size; |
3356 | DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n", | 3526 | DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n", |
3357 | (poh->offset + ivideo->video_vbase)); | 3527 | (poh->offset + ivideo->video_vbase)); |
3358 | } | 3528 | } |
3359 | } | 3529 | } |
3360 | 3530 | ||
3361 | /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */ | 3531 | void |
3532 | sis_malloc(struct sis_memreq *req) | ||
3533 | { | ||
3534 | struct sis_video_info *ivideo = sisfb_heap->vinfo; | ||
3535 | |||
3536 | if(&ivideo->sisfb_heap == sisfb_heap) | ||
3537 | sis_int_malloc(ivideo, req); | ||
3538 | else | ||
3539 | req->offset = req->size = 0; | ||
3540 | } | ||
3362 | 3541 | ||
3363 | void | 3542 | void |
3364 | sis_free(u32 base) | 3543 | sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req) |
3365 | { | 3544 | { |
3366 | struct sis_video_info *ivideo = sisfb_heap.vinfo; | 3545 | struct sis_video_info *ivideo = pci_get_drvdata(pdev); |
3367 | SIS_OH *poh; | 3546 | |
3547 | sis_int_malloc(ivideo, req); | ||
3548 | } | ||
3549 | |||
3550 | /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */ | ||
3368 | 3551 | ||
3369 | if((!ivideo) || (ivideo->havenoheap)) return; | 3552 | static void |
3553 | sis_int_free(struct sis_video_info *ivideo, u32 base) | ||
3554 | { | ||
3555 | struct SIS_OH *poh; | ||
3370 | 3556 | ||
3371 | poh = sisfb_poh_free((u32)base); | 3557 | if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap)) |
3558 | return; | ||
3559 | |||
3560 | poh = sisfb_poh_free(&ivideo->sisfb_heap, base); | ||
3372 | 3561 | ||
3373 | if(poh == NULL) { | 3562 | if(poh == NULL) { |
3374 | DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n", | 3563 | DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n", |
@@ -3376,9 +3565,63 @@ sis_free(u32 base) | |||
3376 | } | 3565 | } |
3377 | } | 3566 | } |
3378 | 3567 | ||
3568 | void | ||
3569 | sis_free(u32 base) | ||
3570 | { | ||
3571 | struct sis_video_info *ivideo = sisfb_heap->vinfo; | ||
3572 | |||
3573 | sis_int_free(ivideo, base); | ||
3574 | } | ||
3575 | |||
3576 | void | ||
3577 | sis_free_new(struct pci_dev *pdev, u32 base) | ||
3578 | { | ||
3579 | struct sis_video_info *ivideo = pci_get_drvdata(pdev); | ||
3580 | |||
3581 | sis_int_free(ivideo, base); | ||
3582 | } | ||
3583 | |||
3379 | /* --------------------- SetMode routines ------------------------- */ | 3584 | /* --------------------- SetMode routines ------------------------- */ |
3380 | 3585 | ||
3381 | static void | 3586 | static void |
3587 | sisfb_check_engine_and_sync(struct sis_video_info *ivideo) | ||
3588 | { | ||
3589 | u8 cr30, cr31; | ||
3590 | |||
3591 | /* Check if MMIO and engines are enabled, | ||
3592 | * and sync in case they are. Can't use | ||
3593 | * ivideo->accel here, as this might have | ||
3594 | * been changed before this is called. | ||
3595 | */ | ||
3596 | inSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, cr30); | ||
3597 | inSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, cr31); | ||
3598 | /* MMIO and 2D/3D engine enabled? */ | ||
3599 | if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) { | ||
3600 | #ifdef CONFIG_FB_SIS_300 | ||
3601 | if(ivideo->sisvga_engine == SIS_300_VGA) { | ||
3602 | /* Don't care about TurboQueue. It's | ||
3603 | * enough to know that the engines | ||
3604 | * are enabled | ||
3605 | */ | ||
3606 | sisfb_syncaccel(ivideo); | ||
3607 | } | ||
3608 | #endif | ||
3609 | #ifdef CONFIG_FB_SIS_315 | ||
3610 | if(ivideo->sisvga_engine == SIS_315_VGA) { | ||
3611 | /* Check that any queue mode is | ||
3612 | * enabled, and that the queue | ||
3613 | * is not in the state of "reset" | ||
3614 | */ | ||
3615 | inSISIDXREG(SISSR, 0x26, cr30); | ||
3616 | if((cr30 & 0xe0) && (!(cr30 & 0x01))) { | ||
3617 | sisfb_syncaccel(ivideo); | ||
3618 | } | ||
3619 | } | ||
3620 | #endif | ||
3621 | } | ||
3622 | } | ||
3623 | |||
3624 | static void | ||
3382 | sisfb_pre_setmode(struct sis_video_info *ivideo) | 3625 | sisfb_pre_setmode(struct sis_video_info *ivideo) |
3383 | { | 3626 | { |
3384 | u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0; | 3627 | u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0; |
@@ -3386,6 +3629,8 @@ sisfb_pre_setmode(struct sis_video_info *ivideo) | |||
3386 | 3629 | ||
3387 | ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2); | 3630 | ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2); |
3388 | 3631 | ||
3632 | outSISIDXREG(SISSR, 0x05, 0x86); | ||
3633 | |||
3389 | inSISIDXREG(SISCR, 0x31, cr31); | 3634 | inSISIDXREG(SISCR, 0x31, cr31); |
3390 | cr31 &= ~0x60; | 3635 | cr31 &= ~0x60; |
3391 | cr31 |= 0x04; | 3636 | cr31 |= 0x04; |
@@ -3413,41 +3658,43 @@ sisfb_pre_setmode(struct sis_video_info *ivideo) | |||
3413 | 3658 | ||
3414 | SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE); | 3659 | SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE); |
3415 | SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE); | 3660 | SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE); |
3661 | ivideo->curFSTN = ivideo->curDSTN = 0; | ||
3416 | 3662 | ||
3417 | switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { | 3663 | switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { |
3418 | 3664 | ||
3419 | case CRT2_TV: | 3665 | case CRT2_TV: |
3420 | cr38 &= ~0xc0; /* Clear PAL-M / PAL-N bits */ | 3666 | cr38 &= ~0xc0; /* Clear PAL-M / PAL-N bits */ |
3421 | if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV))) { | 3667 | if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) { |
3422 | #ifdef CONFIG_FB_SIS_315 | 3668 | #ifdef CONFIG_FB_SIS_315 |
3423 | if(ivideo->chip >= SIS_661) { | 3669 | if(ivideo->chip >= SIS_661) { |
3424 | cr38 |= 0x04; | 3670 | cr38 |= 0x04; |
3425 | if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20; | 3671 | if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20; |
3426 | else if(ivideo->vbflags & TV_YPBPR750P) cr35 |= 0x40; | 3672 | else if(ivideo->vbflags & TV_YPBPR750P) cr35 |= 0x40; |
3427 | else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60; | 3673 | else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60; |
3428 | cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE; | 3674 | cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE; |
3429 | cr35 &= ~0x01; | 3675 | cr35 &= ~0x01; |
3430 | ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL)); | 3676 | ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL)); |
3431 | } else if(ivideo->sisvga_engine == SIS_315_VGA) { | 3677 | } else if(ivideo->sisvga_engine == SIS_315_VGA) { |
3432 | cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE); | 3678 | cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE); |
3433 | cr38 |= 0x08; | 3679 | cr38 |= 0x08; |
3434 | if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10; | 3680 | if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10; |
3435 | else if(ivideo->vbflags & TV_YPBPR750P) cr38 |= 0x20; | 3681 | else if(ivideo->vbflags & TV_YPBPR750P) cr38 |= 0x20; |
3436 | else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30; | 3682 | else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30; |
3437 | cr31 &= ~0x01; | 3683 | cr31 &= ~0x01; |
3438 | ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL)); | 3684 | ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL)); |
3439 | } | 3685 | } |
3440 | #endif | 3686 | #endif |
3441 | } else if((ivideo->vbflags & TV_HIVISION) && (ivideo->vbflags & (VB_301|VB_301B|VB_302B))) { | 3687 | } else if((ivideo->vbflags & TV_HIVISION) && |
3442 | if(ivideo->chip >= SIS_661) { | 3688 | (ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) { |
3443 | cr38 |= 0x04; | 3689 | if(ivideo->chip >= SIS_661) { |
3444 | cr35 |= 0x60; | 3690 | cr38 |= 0x04; |
3445 | } else { | 3691 | cr35 |= 0x60; |
3446 | cr30 |= 0x80; | 3692 | } else { |
3447 | } | 3693 | cr30 |= 0x80; |
3694 | } | ||
3448 | cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE; | 3695 | cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE; |
3449 | cr31 |= 0x01; | 3696 | cr31 |= 0x01; |
3450 | cr35 |= 0x01; | 3697 | cr35 |= 0x01; |
3451 | ivideo->currentvbflags |= TV_HIVISION; | 3698 | ivideo->currentvbflags |= TV_HIVISION; |
3452 | } else if(ivideo->vbflags & TV_SCART) { | 3699 | } else if(ivideo->vbflags & TV_SCART) { |
3453 | cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE); | 3700 | cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE); |
@@ -3466,8 +3713,8 @@ sisfb_pre_setmode(struct sis_video_info *ivideo) | |||
3466 | } | 3713 | } |
3467 | cr31 |= SIS_DRIVER_MODE; | 3714 | cr31 |= SIS_DRIVER_MODE; |
3468 | 3715 | ||
3469 | if(ivideo->vbflags & (TV_AVIDEO|TV_SVIDEO)) { | 3716 | if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) { |
3470 | if(ivideo->vbflags & TV_PAL) { | 3717 | if(ivideo->vbflags & TV_PAL) { |
3471 | cr31 |= 0x01; cr35 |= 0x01; | 3718 | cr31 |= 0x01; cr35 |= 0x01; |
3472 | ivideo->currentvbflags |= TV_PAL; | 3719 | ivideo->currentvbflags |= TV_PAL; |
3473 | if(ivideo->vbflags & TV_PALM) { | 3720 | if(ivideo->vbflags & TV_PALM) { |
@@ -3476,14 +3723,14 @@ sisfb_pre_setmode(struct sis_video_info *ivideo) | |||
3476 | } else if(ivideo->vbflags & TV_PALN) { | 3723 | } else if(ivideo->vbflags & TV_PALN) { |
3477 | cr38 |= 0x80; cr35 |= 0x08; | 3724 | cr38 |= 0x80; cr35 |= 0x08; |
3478 | ivideo->currentvbflags |= TV_PALN; | 3725 | ivideo->currentvbflags |= TV_PALN; |
3479 | } | 3726 | } |
3480 | } else { | 3727 | } else { |
3481 | cr31 &= ~0x01; cr35 &= ~0x01; | 3728 | cr31 &= ~0x01; cr35 &= ~0x01; |
3482 | ivideo->currentvbflags |= TV_NTSC; | 3729 | ivideo->currentvbflags |= TV_NTSC; |
3483 | if(ivideo->vbflags & TV_NTSCJ) { | 3730 | if(ivideo->vbflags & TV_NTSCJ) { |
3484 | cr38 |= 0x40; cr35 |= 0x02; | 3731 | cr38 |= 0x40; cr35 |= 0x02; |
3485 | ivideo->currentvbflags |= TV_NTSCJ; | 3732 | ivideo->currentvbflags |= TV_NTSCJ; |
3486 | } | 3733 | } |
3487 | } | 3734 | } |
3488 | } | 3735 | } |
3489 | break; | 3736 | break; |
@@ -3493,6 +3740,8 @@ sisfb_pre_setmode(struct sis_video_info *ivideo) | |||
3493 | cr31 |= SIS_DRIVER_MODE; | 3740 | cr31 |= SIS_DRIVER_MODE; |
3494 | SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn); | 3741 | SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn); |
3495 | SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn); | 3742 | SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn); |
3743 | ivideo->curFSTN = ivideo->sisfb_fstn; | ||
3744 | ivideo->curDSTN = ivideo->sisfb_dstn; | ||
3496 | break; | 3745 | break; |
3497 | 3746 | ||
3498 | case CRT2_VGA: | 3747 | case CRT2_VGA: |
@@ -3525,9 +3774,9 @@ sisfb_pre_setmode(struct sis_video_info *ivideo) | |||
3525 | } | 3774 | } |
3526 | outSISIDXREG(SISCR, 0x31, cr31); | 3775 | outSISIDXREG(SISCR, 0x31, cr31); |
3527 | 3776 | ||
3528 | if(ivideo->accel) sisfb_syncaccel(ivideo); | ||
3529 | |||
3530 | ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem; | 3777 | ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem; |
3778 | |||
3779 | sisfb_check_engine_and_sync(ivideo); | ||
3531 | } | 3780 | } |
3532 | 3781 | ||
3533 | /* Fix SR11 for 661 and later */ | 3782 | /* Fix SR11 for 661 and later */ |
@@ -3535,125 +3784,129 @@ sisfb_pre_setmode(struct sis_video_info *ivideo) | |||
3535 | static void | 3784 | static void |
3536 | sisfb_fixup_SR11(struct sis_video_info *ivideo) | 3785 | sisfb_fixup_SR11(struct sis_video_info *ivideo) |
3537 | { | 3786 | { |
3538 | u8 tmpreg; | 3787 | u8 tmpreg; |
3539 | 3788 | ||
3540 | if(ivideo->chip >= SIS_661) { | 3789 | if(ivideo->chip >= SIS_661) { |
3541 | inSISIDXREG(SISSR,0x11,tmpreg); | 3790 | inSISIDXREG(SISSR,0x11,tmpreg); |
3542 | if(tmpreg & 0x20) { | 3791 | if(tmpreg & 0x20) { |
3543 | inSISIDXREG(SISSR,0x3e,tmpreg); | 3792 | inSISIDXREG(SISSR,0x3e,tmpreg); |
3544 | tmpreg = (tmpreg + 1) & 0xff; | 3793 | tmpreg = (tmpreg + 1) & 0xff; |
3545 | outSISIDXREG(SISSR,0x3e,tmpreg); | 3794 | outSISIDXREG(SISSR,0x3e,tmpreg); |
3546 | inSISIDXREG(SISSR,0x11,tmpreg); | 3795 | inSISIDXREG(SISSR,0x11,tmpreg); |
3547 | } | 3796 | } |
3548 | if(tmpreg & 0xf0) { | 3797 | if(tmpreg & 0xf0) { |
3549 | andSISIDXREG(SISSR,0x11,0x0f); | 3798 | andSISIDXREG(SISSR,0x11,0x0f); |
3550 | } | 3799 | } |
3551 | } | 3800 | } |
3552 | } | 3801 | } |
3553 | #endif | 3802 | #endif |
3554 | 3803 | ||
3555 | static void sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val) | 3804 | static void |
3805 | sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val) | ||
3556 | { | 3806 | { |
3557 | if(val > 32) val = 32; | 3807 | if(val > 32) val = 32; |
3558 | if(val < -32) val = -32; | 3808 | if(val < -32) val = -32; |
3559 | ivideo->tvxpos = val; | 3809 | ivideo->tvxpos = val; |
3560 | 3810 | ||
3561 | if(ivideo->sisfblocked) return; | 3811 | if(ivideo->sisfblocked) return; |
3562 | if(!ivideo->modechanged) return; | 3812 | if(!ivideo->modechanged) return; |
3563 | 3813 | ||
3564 | if(ivideo->currentvbflags & CRT2_TV) { | 3814 | if(ivideo->currentvbflags & CRT2_TV) { |
3565 | 3815 | ||
3566 | if(ivideo->vbflags & VB_CHRONTEL) { | 3816 | if(ivideo->vbflags2 & VB2_CHRONTEL) { |
3567 | 3817 | ||
3568 | int x = ivideo->tvx; | 3818 | int x = ivideo->tvx; |
3569 | 3819 | ||
3570 | switch(ivideo->chronteltype) { | 3820 | switch(ivideo->chronteltype) { |
3571 | case 1: | 3821 | case 1: |
3572 | x += val; | 3822 | x += val; |
3573 | if(x < 0) x = 0; | 3823 | if(x < 0) x = 0; |
3574 | outSISIDXREG(SISSR,0x05,0x86); | 3824 | outSISIDXREG(SISSR,0x05,0x86); |
3575 | SiS_SetCH700x(&ivideo->SiS_Pr, (((x & 0xff) << 8) | 0x0a)); | 3825 | SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff)); |
3576 | SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, (((x & 0x0100) << 1) | 0x08),0xFD); | 3826 | SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD); |
3577 | break; | 3827 | break; |
3578 | case 2: | 3828 | case 2: |
3579 | /* Not supported by hardware */ | 3829 | /* Not supported by hardware */ |
3580 | break; | 3830 | break; |
3581 | } | 3831 | } |
3582 | 3832 | ||
3583 | } else if(ivideo->vbflags & VB_SISBRIDGE) { | 3833 | } else if(ivideo->vbflags2 & VB2_SISBRIDGE) { |
3584 | 3834 | ||
3585 | u8 p2_1f,p2_20,p2_2b,p2_42,p2_43; | 3835 | u8 p2_1f,p2_20,p2_2b,p2_42,p2_43; |
3586 | unsigned short temp; | 3836 | unsigned short temp; |
3587 | 3837 | ||
3588 | p2_1f = ivideo->p2_1f; | 3838 | p2_1f = ivideo->p2_1f; |
3589 | p2_20 = ivideo->p2_20; | 3839 | p2_20 = ivideo->p2_20; |
3590 | p2_2b = ivideo->p2_2b; | 3840 | p2_2b = ivideo->p2_2b; |
3591 | p2_42 = ivideo->p2_42; | 3841 | p2_42 = ivideo->p2_42; |
3592 | p2_43 = ivideo->p2_43; | 3842 | p2_43 = ivideo->p2_43; |
3593 | 3843 | ||
3594 | temp = p2_1f | ((p2_20 & 0xf0) << 4); | 3844 | temp = p2_1f | ((p2_20 & 0xf0) << 4); |
3595 | temp += (val * 2); | 3845 | temp += (val * 2); |
3596 | p2_1f = temp & 0xff; | 3846 | p2_1f = temp & 0xff; |
3597 | p2_20 = (temp & 0xf00) >> 4; | 3847 | p2_20 = (temp & 0xf00) >> 4; |
3598 | p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f; | 3848 | p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f; |
3599 | temp = p2_43 | ((p2_42 & 0xf0) << 4); | 3849 | temp = p2_43 | ((p2_42 & 0xf0) << 4); |
3600 | temp += (val * 2); | 3850 | temp += (val * 2); |
3601 | p2_43 = temp & 0xff; | 3851 | p2_43 = temp & 0xff; |
3602 | p2_42 = (temp & 0xf00) >> 4; | 3852 | p2_42 = (temp & 0xf00) >> 4; |
3603 | outSISIDXREG(SISPART2,0x1f,p2_1f); | 3853 | outSISIDXREG(SISPART2,0x1f,p2_1f); |
3604 | setSISIDXREG(SISPART2,0x20,0x0F,p2_20); | 3854 | setSISIDXREG(SISPART2,0x20,0x0F,p2_20); |
3605 | setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b); | 3855 | setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b); |
3606 | setSISIDXREG(SISPART2,0x42,0x0F,p2_42); | 3856 | setSISIDXREG(SISPART2,0x42,0x0F,p2_42); |
3607 | outSISIDXREG(SISPART2,0x43,p2_43); | 3857 | outSISIDXREG(SISPART2,0x43,p2_43); |
3608 | } | 3858 | } |
3609 | } | 3859 | } |
3610 | } | 3860 | } |
3611 | 3861 | ||
3612 | static void sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val) | 3862 | static void |
3863 | sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val) | ||
3613 | { | 3864 | { |
3614 | if(val > 32) val = 32; | 3865 | if(val > 32) val = 32; |
3615 | if(val < -32) val = -32; | 3866 | if(val < -32) val = -32; |
3616 | ivideo->tvypos = val; | 3867 | ivideo->tvypos = val; |
3617 | 3868 | ||
3618 | if(ivideo->sisfblocked) return; | 3869 | if(ivideo->sisfblocked) return; |
3619 | if(!ivideo->modechanged) return; | 3870 | if(!ivideo->modechanged) return; |
3620 | 3871 | ||
3621 | if(ivideo->currentvbflags & CRT2_TV) { | 3872 | if(ivideo->currentvbflags & CRT2_TV) { |
3622 | 3873 | ||
3623 | if(ivideo->vbflags & VB_CHRONTEL) { | 3874 | if(ivideo->vbflags2 & VB2_CHRONTEL) { |
3624 | 3875 | ||
3625 | int y = ivideo->tvy; | 3876 | int y = ivideo->tvy; |
3626 | 3877 | ||
3627 | switch(ivideo->chronteltype) { | 3878 | switch(ivideo->chronteltype) { |
3628 | case 1: | 3879 | case 1: |
3629 | y -= val; | 3880 | y -= val; |
3630 | if(y < 0) y = 0; | 3881 | if(y < 0) y = 0; |
3631 | outSISIDXREG(SISSR,0x05,0x86); | 3882 | outSISIDXREG(SISSR,0x05,0x86); |
3632 | SiS_SetCH700x(&ivideo->SiS_Pr, (((y & 0xff) << 8) | 0x0b)); | 3883 | SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff)); |
3633 | SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, ((y & 0x0100) | 0x08),0xFE); | 3884 | SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE); |
3634 | break; | 3885 | break; |
3635 | case 2: | 3886 | case 2: |
3636 | /* Not supported by hardware */ | 3887 | /* Not supported by hardware */ |
3637 | break; | 3888 | break; |
3638 | } | 3889 | } |
3639 | 3890 | ||
3640 | } else if(ivideo->vbflags & VB_SISBRIDGE) { | 3891 | } else if(ivideo->vbflags2 & VB2_SISBRIDGE) { |
3641 | 3892 | ||
3642 | char p2_01, p2_02; | 3893 | char p2_01, p2_02; |
3643 | val /= 2; | 3894 | val /= 2; |
3644 | p2_01 = ivideo->p2_01; | 3895 | p2_01 = ivideo->p2_01; |
3645 | p2_02 = ivideo->p2_02; | 3896 | p2_02 = ivideo->p2_02; |
3646 | 3897 | ||
3647 | p2_01 += val; | 3898 | p2_01 += val; |
3648 | p2_02 += val; | 3899 | p2_02 += val; |
3649 | while((p2_01 <= 0) || (p2_02 <= 0)) { | 3900 | if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) { |
3650 | p2_01 += 2; | 3901 | while((p2_01 <= 0) || (p2_02 <= 0)) { |
3651 | p2_02 += 2; | 3902 | p2_01 += 2; |
3652 | } | 3903 | p2_02 += 2; |
3653 | outSISIDXREG(SISPART2,0x01,p2_01); | 3904 | } |
3654 | outSISIDXREG(SISPART2,0x02,p2_02); | 3905 | } |
3655 | } | 3906 | outSISIDXREG(SISPART2,0x01,p2_01); |
3656 | } | 3907 | outSISIDXREG(SISPART2,0x02,p2_02); |
3908 | } | ||
3909 | } | ||
3657 | } | 3910 | } |
3658 | 3911 | ||
3659 | static void | 3912 | static void |
@@ -3668,207 +3921,172 @@ sisfb_post_setmode(struct sis_video_info *ivideo) | |||
3668 | u8 reg1; | 3921 | u8 reg1; |
3669 | #endif | 3922 | #endif |
3670 | 3923 | ||
3671 | outSISIDXREG(SISSR,0x05,0x86); | 3924 | outSISIDXREG(SISSR, 0x05, 0x86); |
3672 | 3925 | ||
3673 | #ifdef CONFIG_FB_SIS_315 | 3926 | #ifdef CONFIG_FB_SIS_315 |
3674 | sisfb_fixup_SR11(ivideo); | 3927 | sisfb_fixup_SR11(ivideo); |
3675 | #endif | 3928 | #endif |
3676 | 3929 | ||
3677 | /* Now we actually HAVE changed the display mode */ | 3930 | /* Now we actually HAVE changed the display mode */ |
3678 | ivideo->modechanged = 1; | 3931 | ivideo->modechanged = 1; |
3679 | 3932 | ||
3680 | /* We can't switch off CRT1 if bridge is in slave mode */ | 3933 | /* We can't switch off CRT1 if bridge is in slave mode */ |
3681 | if(ivideo->vbflags & VB_VIDEOBRIDGE) { | 3934 | if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) { |
3682 | if(sisfb_bridgeisslave(ivideo)) doit = FALSE; | 3935 | if(sisfb_bridgeisslave(ivideo)) doit = FALSE; |
3683 | } else ivideo->sisfb_crt1off = 0; | 3936 | } else |
3937 | ivideo->sisfb_crt1off = 0; | ||
3684 | 3938 | ||
3685 | #ifdef CONFIG_FB_SIS_300 | 3939 | #ifdef CONFIG_FB_SIS_300 |
3686 | if(ivideo->sisvga_engine == SIS_300_VGA) { | 3940 | if(ivideo->sisvga_engine == SIS_300_VGA) { |
3687 | if((ivideo->sisfb_crt1off) && (doit)) { | 3941 | if((ivideo->sisfb_crt1off) && (doit)) { |
3688 | crt1isoff = TRUE; | 3942 | crt1isoff = TRUE; |
3689 | reg = 0x00; | 3943 | reg = 0x00; |
3690 | } else { | 3944 | } else { |
3691 | crt1isoff = FALSE; | 3945 | crt1isoff = FALSE; |
3692 | reg = 0x80; | 3946 | reg = 0x80; |
3693 | } | 3947 | } |
3694 | setSISIDXREG(SISCR, 0x17, 0x7f, reg); | 3948 | setSISIDXREG(SISCR, 0x17, 0x7f, reg); |
3695 | } | 3949 | } |
3696 | #endif | 3950 | #endif |
3697 | #ifdef CONFIG_FB_SIS_315 | 3951 | #ifdef CONFIG_FB_SIS_315 |
3698 | if(ivideo->sisvga_engine == SIS_315_VGA) { | 3952 | if(ivideo->sisvga_engine == SIS_315_VGA) { |
3699 | if((ivideo->sisfb_crt1off) && (doit)) { | 3953 | if((ivideo->sisfb_crt1off) && (doit)) { |
3700 | crt1isoff = TRUE; | 3954 | crt1isoff = TRUE; |
3701 | reg = 0x40; | 3955 | reg = 0x40; |
3702 | reg1 = 0xc0; | 3956 | reg1 = 0xc0; |
3703 | } else { | 3957 | } else { |
3704 | crt1isoff = FALSE; | 3958 | crt1isoff = FALSE; |
3705 | reg = 0x00; | 3959 | reg = 0x00; |
3706 | reg1 = 0x00; | 3960 | reg1 = 0x00; |
3707 | 3961 | } | |
3708 | } | 3962 | setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg); |
3709 | setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg); | 3963 | setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1); |
3710 | setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1); | ||
3711 | } | 3964 | } |
3712 | #endif | 3965 | #endif |
3713 | 3966 | ||
3714 | if(crt1isoff) { | 3967 | if(crt1isoff) { |
3715 | ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1; | 3968 | ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1; |
3716 | ivideo->currentvbflags |= VB_SINGLE_MODE; | 3969 | ivideo->currentvbflags |= VB_SINGLE_MODE; |
3717 | } else { | 3970 | } else { |
3718 | ivideo->currentvbflags |= VB_DISPTYPE_CRT1; | 3971 | ivideo->currentvbflags |= VB_DISPTYPE_CRT1; |
3719 | if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) { | 3972 | if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) { |
3720 | ivideo->currentvbflags |= VB_MIRROR_MODE; | 3973 | ivideo->currentvbflags |= VB_MIRROR_MODE; |
3721 | } else { | 3974 | } else { |
3722 | ivideo->currentvbflags |= VB_SINGLE_MODE; | 3975 | ivideo->currentvbflags |= VB_SINGLE_MODE; |
3723 | } | 3976 | } |
3724 | } | 3977 | } |
3725 | 3978 | ||
3726 | andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04); | 3979 | andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04); |
3727 | 3980 | ||
3728 | if(ivideo->currentvbflags & CRT2_TV) { | 3981 | if(ivideo->currentvbflags & CRT2_TV) { |
3729 | if(ivideo->vbflags & VB_SISBRIDGE) { | 3982 | if(ivideo->vbflags2 & VB2_SISBRIDGE) { |
3730 | inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f); | 3983 | inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f); |
3731 | inSISIDXREG(SISPART2,0x20,ivideo->p2_20); | 3984 | inSISIDXREG(SISPART2,0x20,ivideo->p2_20); |
3732 | inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b); | 3985 | inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b); |
3733 | inSISIDXREG(SISPART2,0x42,ivideo->p2_42); | 3986 | inSISIDXREG(SISPART2,0x42,ivideo->p2_42); |
3734 | inSISIDXREG(SISPART2,0x43,ivideo->p2_43); | 3987 | inSISIDXREG(SISPART2,0x43,ivideo->p2_43); |
3735 | inSISIDXREG(SISPART2,0x01,ivideo->p2_01); | 3988 | inSISIDXREG(SISPART2,0x01,ivideo->p2_01); |
3736 | inSISIDXREG(SISPART2,0x02,ivideo->p2_02); | 3989 | inSISIDXREG(SISPART2,0x02,ivideo->p2_02); |
3737 | } else if(ivideo->vbflags & VB_CHRONTEL) { | 3990 | } else if(ivideo->vbflags2 & VB2_CHRONTEL) { |
3738 | if(ivideo->chronteltype == 1) { | 3991 | if(ivideo->chronteltype == 1) { |
3739 | ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a); | 3992 | ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a); |
3740 | ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8); | 3993 | ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8); |
3741 | ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b); | 3994 | ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b); |
3742 | ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8); | 3995 | ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8); |
3743 | } | 3996 | } |
3744 | } | 3997 | } |
3745 | } | 3998 | } |
3746 | 3999 | ||
3747 | if(ivideo->tvxpos) { | 4000 | if(ivideo->tvxpos) { |
3748 | sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos); | 4001 | sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos); |
3749 | } | 4002 | } |
3750 | if(ivideo->tvypos) { | 4003 | if(ivideo->tvypos) { |
3751 | sisfb_set_TVyposoffset(ivideo, ivideo->tvypos); | 4004 | sisfb_set_TVyposoffset(ivideo, ivideo->tvypos); |
3752 | } | 4005 | } |
3753 | 4006 | ||
3754 | if((ivideo->currentvbflags & CRT2_TV) && (ivideo->vbflags & VB_301)) { /* Set filter for SiS301 */ | 4007 | /* Eventually sync engines */ |
4008 | sisfb_check_engine_and_sync(ivideo); | ||
3755 | 4009 | ||
3756 | unsigned char filter_tb = 0; | 4010 | /* (Re-)Initialize chip engines */ |
4011 | if(ivideo->accel) { | ||
4012 | sisfb_engine_init(ivideo); | ||
4013 | } else { | ||
4014 | ivideo->engineok = 0; | ||
4015 | } | ||
4016 | } | ||
3757 | 4017 | ||
3758 | switch (ivideo->video_width) { | 4018 | static int |
3759 | case 320: | 4019 | sisfb_reset_mode(struct sis_video_info *ivideo) |
3760 | filter_tb = (ivideo->vbflags & TV_NTSC) ? 4 : 12; | 4020 | { |
3761 | break; | 4021 | if(sisfb_set_mode(ivideo, 0)) |
3762 | case 640: | 4022 | return 1; |
3763 | filter_tb = (ivideo->vbflags & TV_NTSC) ? 5 : 13; | ||
3764 | break; | ||
3765 | case 720: | ||
3766 | filter_tb = (ivideo->vbflags & TV_NTSC) ? 6 : 14; | ||
3767 | break; | ||
3768 | case 400: | ||
3769 | case 800: | ||
3770 | filter_tb = (ivideo->vbflags & TV_NTSC) ? 7 : 15; | ||
3771 | break; | ||
3772 | default: | ||
3773 | ivideo->sisfb_filter = -1; | ||
3774 | break; | ||
3775 | } | ||
3776 | 4023 | ||
3777 | orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01); | 4024 | sisfb_set_pitch(ivideo); |
4025 | sisfb_set_base_CRT1(ivideo, ivideo->current_base); | ||
4026 | sisfb_set_base_CRT2(ivideo, ivideo->current_base); | ||
3778 | 4027 | ||
3779 | if(ivideo->vbflags & TV_NTSC) { | 4028 | return 0; |
3780 | 4029 | } | |
3781 | andSISIDXREG(SISPART2, 0x3a, 0x1f); | 4030 | |
3782 | 4031 | static void | |
3783 | if (ivideo->vbflags & TV_SVIDEO) { | 4032 | sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command) |
3784 | 4033 | { | |
3785 | andSISIDXREG(SISPART2, 0x30, 0xdf); | 4034 | int mycrt1off; |
3786 | |||
3787 | } else if (ivideo->vbflags & TV_AVIDEO) { | ||
3788 | |||
3789 | orSISIDXREG(SISPART2, 0x30, 0x20); | ||
3790 | |||
3791 | switch (ivideo->video_width) { | ||
3792 | case 640: | ||
3793 | outSISIDXREG(SISPART2, 0x35, 0xEB); | ||
3794 | outSISIDXREG(SISPART2, 0x36, 0x04); | ||
3795 | outSISIDXREG(SISPART2, 0x37, 0x25); | ||
3796 | outSISIDXREG(SISPART2, 0x38, 0x18); | ||
3797 | break; | ||
3798 | case 720: | ||
3799 | outSISIDXREG(SISPART2, 0x35, 0xEE); | ||
3800 | outSISIDXREG(SISPART2, 0x36, 0x0C); | ||
3801 | outSISIDXREG(SISPART2, 0x37, 0x22); | ||
3802 | outSISIDXREG(SISPART2, 0x38, 0x08); | ||
3803 | break; | ||
3804 | case 400: | ||
3805 | case 800: | ||
3806 | outSISIDXREG(SISPART2, 0x35, 0xEB); | ||
3807 | outSISIDXREG(SISPART2, 0x36, 0x15); | ||
3808 | outSISIDXREG(SISPART2, 0x37, 0x25); | ||
3809 | outSISIDXREG(SISPART2, 0x38, 0xF6); | ||
3810 | break; | ||
3811 | } | ||
3812 | } | ||
3813 | 4035 | ||
3814 | } else if(ivideo->vbflags & TV_PAL) { | 4036 | switch(sisfb_command->sisfb_cmd) { |
3815 | 4037 | case SISFB_CMD_GETVBFLAGS: | |
3816 | andSISIDXREG(SISPART2, 0x3A, 0x1F); | 4038 | if(!ivideo->modechanged) { |
3817 | 4039 | sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY; | |
3818 | if (ivideo->vbflags & TV_SVIDEO) { | 4040 | } else { |
3819 | 4041 | sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK; | |
3820 | andSISIDXREG(SISPART2, 0x30, 0xDF); | 4042 | sisfb_command->sisfb_result[1] = ivideo->currentvbflags; |
3821 | 4043 | sisfb_command->sisfb_result[2] = ivideo->vbflags2; | |
3822 | } else if (ivideo->vbflags & TV_AVIDEO) { | 4044 | } |
3823 | 4045 | break; | |
3824 | orSISIDXREG(SISPART2, 0x30, 0x20); | 4046 | case SISFB_CMD_SWITCHCRT1: |
3825 | 4047 | /* arg[0]: 0 = off, 1 = on, 99 = query */ | |
3826 | switch (ivideo->video_width) { | 4048 | if(!ivideo->modechanged) { |
3827 | case 640: | 4049 | sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY; |
3828 | outSISIDXREG(SISPART2, 0x35, 0xF1); | 4050 | } else if(sisfb_command->sisfb_arg[0] == 99) { |
3829 | outSISIDXREG(SISPART2, 0x36, 0xF7); | 4051 | /* Query */ |
3830 | outSISIDXREG(SISPART2, 0x37, 0x1F); | 4052 | sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1; |
3831 | outSISIDXREG(SISPART2, 0x38, 0x32); | 4053 | sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK; |
3832 | break; | 4054 | } else if(ivideo->sisfblocked) { |
3833 | case 720: | 4055 | sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED; |
3834 | outSISIDXREG(SISPART2, 0x35, 0xF3); | 4056 | } else if((!(ivideo->currentvbflags & CRT2_ENABLE)) && |
3835 | outSISIDXREG(SISPART2, 0x36, 0x00); | 4057 | (sisfb_command->sisfb_arg[0] == 0)) { |
3836 | outSISIDXREG(SISPART2, 0x37, 0x1D); | 4058 | sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2; |
3837 | outSISIDXREG(SISPART2, 0x38, 0x20); | 4059 | } else { |
3838 | break; | 4060 | sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK; |
3839 | case 400: | 4061 | mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1; |
3840 | case 800: | 4062 | if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) || |
3841 | outSISIDXREG(SISPART2, 0x35, 0xFC); | 4063 | ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) { |
3842 | outSISIDXREG(SISPART2, 0x36, 0xFB); | 4064 | ivideo->sisfb_crt1off = mycrt1off; |
3843 | outSISIDXREG(SISPART2, 0x37, 0x14); | 4065 | if(sisfb_reset_mode(ivideo)) { |
3844 | outSISIDXREG(SISPART2, 0x38, 0x2A); | 4066 | sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER; |
3845 | break; | ||
3846 | } | 4067 | } |
3847 | } | 4068 | } |
4069 | sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1; | ||
3848 | } | 4070 | } |
3849 | 4071 | break; | |
3850 | if((ivideo->sisfb_filter >= 0) && (ivideo->sisfb_filter <= 7)) { | 4072 | /* more to come */ |
3851 | outSISIDXREG(SISPART2,0x35,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][0])); | 4073 | default: |
3852 | outSISIDXREG(SISPART2,0x36,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][1])); | 4074 | sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN; |
3853 | outSISIDXREG(SISPART2,0x37,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][2])); | 4075 | printk(KERN_ERR "sisfb: Unknown command 0x%x\n", |
3854 | outSISIDXREG(SISPART2,0x38,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][3])); | 4076 | sisfb_command->sisfb_cmd); |
3855 | } | ||
3856 | |||
3857 | } | 4077 | } |
3858 | } | 4078 | } |
3859 | 4079 | ||
3860 | #ifndef MODULE | 4080 | #ifndef MODULE |
3861 | SISINITSTATIC int __init sisfb_setup(char *options) | 4081 | SISINITSTATIC int __init |
4082 | sisfb_setup(char *options) | ||
3862 | { | 4083 | { |
3863 | char *this_opt; | 4084 | char *this_opt; |
3864 | |||
3865 | sisfb_setdefaultparms(); | ||
3866 | 4085 | ||
3867 | printk(KERN_DEBUG "sisfb: Options %s\n", options); | 4086 | sisfb_setdefaultparms(); |
3868 | 4087 | ||
3869 | if(!options || !(*options)) { | 4088 | if(!options || !(*options)) |
3870 | return 0; | 4089 | return 0; |
3871 | } | ||
3872 | 4090 | ||
3873 | while((this_opt = strsep(&options, ",")) != NULL) { | 4091 | while((this_opt = strsep(&options, ",")) != NULL) { |
3874 | 4092 | ||
@@ -3880,9 +4098,9 @@ SISINITSTATIC int __init sisfb_setup(char *options) | |||
3880 | /* Need to check crt2 type first for fstn/dstn */ | 4098 | /* Need to check crt2 type first for fstn/dstn */ |
3881 | sisfb_search_crt2type(this_opt + 14); | 4099 | sisfb_search_crt2type(this_opt + 14); |
3882 | } else if(!strnicmp(this_opt, "tvmode:",7)) { | 4100 | } else if(!strnicmp(this_opt, "tvmode:",7)) { |
3883 | sisfb_search_tvstd(this_opt + 7); | ||
3884 | } else if(!strnicmp(this_opt, "tvstandard:",11)) { | ||
3885 | sisfb_search_tvstd(this_opt + 7); | 4101 | sisfb_search_tvstd(this_opt + 7); |
4102 | } else if(!strnicmp(this_opt, "tvstandard:",11)) { | ||
4103 | sisfb_search_tvstd(this_opt + 11); | ||
3886 | } else if(!strnicmp(this_opt, "mode:", 5)) { | 4104 | } else if(!strnicmp(this_opt, "mode:", 5)) { |
3887 | sisfb_search_mode(this_opt + 5, FALSE); | 4105 | sisfb_search_mode(this_opt + 5, FALSE); |
3888 | } else if(!strnicmp(this_opt, "vesa:", 5)) { | 4106 | } else if(!strnicmp(this_opt, "vesa:", 5)) { |
@@ -3892,74 +4110,72 @@ SISINITSTATIC int __init sisfb_setup(char *options) | |||
3892 | sisfb_inverse = 1; | 4110 | sisfb_inverse = 1; |
3893 | /* fb_invert_cmaps(); */ | 4111 | /* fb_invert_cmaps(); */ |
3894 | } else if(!strnicmp(this_opt, "font:", 5)) { | 4112 | } else if(!strnicmp(this_opt, "font:", 5)) { |
3895 | if(strlen(this_opt + 5) < 40) { | 4113 | if(strlen(this_opt + 5) < 40) { |
3896 | strncpy(sisfb_fontname, this_opt + 5, sizeof(sisfb_fontname) - 1); | 4114 | strncpy(sisfb_fontname, this_opt + 5, sizeof(sisfb_fontname) - 1); |
3897 | sisfb_fontname[sizeof(sisfb_fontname) - 1] = '\0'; | 4115 | sisfb_fontname[sizeof(sisfb_fontname) - 1] = '\0'; |
3898 | } | 4116 | } |
3899 | #endif | 4117 | #endif |
3900 | } else if(!strnicmp(this_opt, "rate:", 5)) { | 4118 | } else if(!strnicmp(this_opt, "rate:", 5)) { |
3901 | sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0); | 4119 | sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0); |
3902 | } else if(!strnicmp(this_opt, "filter:", 7)) { | ||
3903 | sisfb_filter = (int)simple_strtoul(this_opt + 7, NULL, 0); | ||
3904 | } else if(!strnicmp(this_opt, "forcecrt1:", 10)) { | 4120 | } else if(!strnicmp(this_opt, "forcecrt1:", 10)) { |
3905 | sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0); | 4121 | sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0); |
3906 | } else if(!strnicmp(this_opt, "mem:",4)) { | 4122 | } else if(!strnicmp(this_opt, "mem:",4)) { |
3907 | sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0); | 4123 | sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0); |
3908 | } else if(!strnicmp(this_opt, "pdc:", 4)) { | 4124 | } else if(!strnicmp(this_opt, "pdc:", 4)) { |
3909 | sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0); | 4125 | sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0); |
3910 | } else if(!strnicmp(this_opt, "pdc1:", 5)) { | 4126 | } else if(!strnicmp(this_opt, "pdc1:", 5)) { |
3911 | sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0); | 4127 | sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0); |
3912 | } else if(!strnicmp(this_opt, "noaccel", 7)) { | 4128 | } else if(!strnicmp(this_opt, "noaccel", 7)) { |
3913 | sisfb_accel = 0; | 4129 | sisfb_accel = 0; |
3914 | } else if(!strnicmp(this_opt, "accel", 5)) { | 4130 | } else if(!strnicmp(this_opt, "accel", 5)) { |
3915 | sisfb_accel = -1; | 4131 | sisfb_accel = -1; |
3916 | } else if(!strnicmp(this_opt, "noypan", 6)) { | 4132 | } else if(!strnicmp(this_opt, "noypan", 6)) { |
3917 | sisfb_ypan = 0; | 4133 | sisfb_ypan = 0; |
3918 | } else if(!strnicmp(this_opt, "ypan", 4)) { | 4134 | } else if(!strnicmp(this_opt, "ypan", 4)) { |
3919 | sisfb_ypan = -1; | 4135 | sisfb_ypan = -1; |
3920 | } else if(!strnicmp(this_opt, "nomax", 5)) { | 4136 | } else if(!strnicmp(this_opt, "nomax", 5)) { |
3921 | sisfb_max = 0; | 4137 | sisfb_max = 0; |
3922 | } else if(!strnicmp(this_opt, "max", 3)) { | 4138 | } else if(!strnicmp(this_opt, "max", 3)) { |
3923 | sisfb_max = -1; | 4139 | sisfb_max = -1; |
3924 | } else if(!strnicmp(this_opt, "userom:", 7)) { | 4140 | } else if(!strnicmp(this_opt, "userom:", 7)) { |
3925 | sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0); | 4141 | sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0); |
3926 | } else if(!strnicmp(this_opt, "useoem:", 7)) { | 4142 | } else if(!strnicmp(this_opt, "useoem:", 7)) { |
3927 | sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0); | 4143 | sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0); |
3928 | } else if(!strnicmp(this_opt, "nocrt2rate", 10)) { | 4144 | } else if(!strnicmp(this_opt, "nocrt2rate", 10)) { |
3929 | sisfb_nocrt2rate = 1; | 4145 | sisfb_nocrt2rate = 1; |
3930 | } else if(!strnicmp(this_opt, "scalelcd:", 9)) { | 4146 | } else if(!strnicmp(this_opt, "scalelcd:", 9)) { |
3931 | unsigned long temp = 2; | 4147 | unsigned long temp = 2; |
3932 | temp = simple_strtoul(this_opt + 9, NULL, 0); | 4148 | temp = simple_strtoul(this_opt + 9, NULL, 0); |
3933 | if((temp == 0) || (temp == 1)) { | 4149 | if((temp == 0) || (temp == 1)) { |
3934 | sisfb_scalelcd = temp ^ 1; | 4150 | sisfb_scalelcd = temp ^ 1; |
3935 | } | 4151 | } |
3936 | } else if(!strnicmp(this_opt, "tvxposoffset:", 13)) { | 4152 | } else if(!strnicmp(this_opt, "tvxposoffset:", 13)) { |
3937 | int temp = 0; | 4153 | int temp = 0; |
3938 | temp = (int)simple_strtol(this_opt + 13, NULL, 0); | 4154 | temp = (int)simple_strtol(this_opt + 13, NULL, 0); |
3939 | if((temp >= -32) && (temp <= 32)) { | 4155 | if((temp >= -32) && (temp <= 32)) { |
3940 | sisfb_tvxposoffset = temp; | 4156 | sisfb_tvxposoffset = temp; |
3941 | } | 4157 | } |
3942 | } else if(!strnicmp(this_opt, "tvyposoffset:", 13)) { | 4158 | } else if(!strnicmp(this_opt, "tvyposoffset:", 13)) { |
3943 | int temp = 0; | 4159 | int temp = 0; |
3944 | temp = (int)simple_strtol(this_opt + 13, NULL, 0); | 4160 | temp = (int)simple_strtol(this_opt + 13, NULL, 0); |
3945 | if((temp >= -32) && (temp <= 32)) { | 4161 | if((temp >= -32) && (temp <= 32)) { |
3946 | sisfb_tvyposoffset = temp; | 4162 | sisfb_tvyposoffset = temp; |
3947 | } | 4163 | } |
3948 | } else if(!strnicmp(this_opt, "specialtiming:", 14)) { | 4164 | } else if(!strnicmp(this_opt, "specialtiming:", 14)) { |
3949 | sisfb_search_specialtiming(this_opt + 14); | 4165 | sisfb_search_specialtiming(this_opt + 14); |
3950 | } else if(!strnicmp(this_opt, "lvdshl:", 7)) { | 4166 | } else if(!strnicmp(this_opt, "lvdshl:", 7)) { |
3951 | int temp = 4; | 4167 | int temp = 4; |
3952 | temp = simple_strtoul(this_opt + 7, NULL, 0); | 4168 | temp = simple_strtoul(this_opt + 7, NULL, 0); |
3953 | if((temp >= 0) && (temp <= 3)) { | 4169 | if((temp >= 0) && (temp <= 3)) { |
3954 | sisfb_lvdshl = temp; | 4170 | sisfb_lvdshl = temp; |
3955 | } | 4171 | } |
3956 | } else if(this_opt[0] >= '0' && this_opt[0] <= '9') { | 4172 | } else if(this_opt[0] >= '0' && this_opt[0] <= '9') { |
3957 | sisfb_search_mode(this_opt, TRUE); | 4173 | sisfb_search_mode(this_opt, TRUE); |
3958 | #if !defined(__i386__) && !defined(__x86_64__) | 4174 | #if !defined(__i386__) && !defined(__x86_64__) |
3959 | } else if(!strnicmp(this_opt, "resetcard", 9)) { | 4175 | } else if(!strnicmp(this_opt, "resetcard", 9)) { |
3960 | sisfb_resetcard = 1; | 4176 | sisfb_resetcard = 1; |
3961 | } else if(!strnicmp(this_opt, "videoram:", 9)) { | 4177 | } else if(!strnicmp(this_opt, "videoram:", 9)) { |
3962 | sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0); | 4178 | sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0); |
3963 | #endif | 4179 | #endif |
3964 | } else { | 4180 | } else { |
3965 | printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt); | 4181 | printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt); |
@@ -3967,63 +4183,99 @@ SISINITSTATIC int __init sisfb_setup(char *options) | |||
3967 | 4183 | ||
3968 | } | 4184 | } |
3969 | 4185 | ||
3970 | |||
3971 | |||
3972 | return 0; | 4186 | return 0; |
3973 | } | 4187 | } |
3974 | #endif | 4188 | #endif |
3975 | 4189 | ||
3976 | static UCHAR * __devinit sis_find_rom(struct pci_dev *pdev) | 4190 | static int __devinit |
4191 | sisfb_check_rom(SIS_IOTYPE1 *rom_base, struct sis_video_info *ivideo) | ||
4192 | { | ||
4193 | SIS_IOTYPE1 *rom; | ||
4194 | int romptr; | ||
4195 | |||
4196 | if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa)) | ||
4197 | return 0; | ||
4198 | |||
4199 | romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8)); | ||
4200 | if(romptr > (0x10000 - 8)) | ||
4201 | return 0; | ||
4202 | |||
4203 | rom = rom_base + romptr; | ||
4204 | |||
4205 | if((readb(rom) != 'P') || (readb(rom + 1) != 'C') || | ||
4206 | (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R')) | ||
4207 | return 0; | ||
4208 | |||
4209 | if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor) | ||
4210 | return 0; | ||
4211 | |||
4212 | if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id) | ||
4213 | return 0; | ||
4214 | |||
4215 | return 1; | ||
4216 | } | ||
4217 | |||
4218 | static unsigned char * __devinit | ||
4219 | sisfb_find_rom(struct pci_dev *pdev) | ||
3977 | { | 4220 | { |
3978 | struct sis_video_info *ivideo = pci_get_drvdata(pdev); | 4221 | struct sis_video_info *ivideo = pci_get_drvdata(pdev); |
3979 | USHORT pciid; | 4222 | SIS_IOTYPE1 *rom_base; |
3980 | int romptr; | 4223 | unsigned char *myrombase = NULL; |
3981 | UCHAR *myrombase; | 4224 | u32 temp; |
3982 | u32 temp; | 4225 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) |
3983 | SIS_IOTYPE1 *rom_base, *rom; | 4226 | size_t romsize; |
4227 | |||
4228 | /* First, try the official pci ROM functions (except | ||
4229 | * on integrated chipsets which have no ROM). | ||
4230 | */ | ||
3984 | 4231 | ||
3985 | if(!(myrombase = vmalloc(65536))) return NULL; | 4232 | if(!ivideo->nbridge) { |
3986 | 4233 | ||
3987 | #if defined(__i386__) || defined(__x86_64__) | 4234 | if((rom_base = pci_map_rom(pdev, &romsize))) { |
3988 | 4235 | ||
3989 | for(temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) { | 4236 | if(sisfb_check_rom(rom_base, ivideo)) { |
3990 | 4237 | ||
3991 | rom_base = ioremap(temp, 0x10000); | 4238 | if((myrombase = vmalloc(65536))) { |
3992 | if(!rom_base) continue; | ||
3993 | 4239 | ||
3994 | if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa)) { | 4240 | /* Work around bug in pci/rom.c: Folks forgot to check |
3995 | iounmap(rom_base); | 4241 | * whether the size retrieved from the BIOS image eventually |
3996 | continue; | 4242 | * is larger than the mapped size |
3997 | } | 4243 | */ |
4244 | if(pci_resource_len(pdev, PCI_ROM_RESOURCE) < romsize) | ||
4245 | romsize = pci_resource_len(pdev, PCI_ROM_RESOURCE); | ||
3998 | 4246 | ||
3999 | romptr = (unsigned short)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8)); | 4247 | memcpy_fromio(myrombase, rom_base, |
4000 | if(romptr > (0x10000 - 8)) { | 4248 | (romsize > 65536) ? 65536 : romsize); |
4001 | iounmap(rom_base); | 4249 | } |
4002 | continue; | 4250 | } |
4003 | } | 4251 | pci_unmap_rom(pdev, rom_base); |
4252 | } | ||
4253 | } | ||
4004 | 4254 | ||
4005 | rom = rom_base + romptr; | 4255 | if(myrombase) return myrombase; |
4256 | #endif | ||
4006 | 4257 | ||
4007 | if((readb(rom) != 'P') || (readb(rom + 1) != 'C') || | 4258 | /* Otherwise do it the conventional way. */ |
4008 | (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R')) { | ||
4009 | iounmap(rom_base); | ||
4010 | continue; | ||
4011 | } | ||
4012 | 4259 | ||
4013 | pciid = readb(rom + 4) | (readb(rom + 5) << 8); | 4260 | #if defined(__i386__) || defined(__x86_64__) |
4014 | if(pciid != 0x1039) { | ||
4015 | iounmap(rom_base); | ||
4016 | continue; | ||
4017 | } | ||
4018 | 4261 | ||
4019 | pciid = readb(rom + 6) | (readb(rom + 7) << 8); | 4262 | for(temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) { |
4020 | if(pciid == ivideo->chip_id) { | 4263 | |
4021 | memcpy_fromio(myrombase, rom_base, 65536); | 4264 | rom_base = ioremap(temp, 65536); |
4022 | iounmap(rom_base); | 4265 | if(!rom_base) |
4023 | return myrombase; | 4266 | continue; |
4024 | } | 4267 | |
4268 | if(!sisfb_check_rom(rom_base, ivideo)) { | ||
4269 | iounmap(rom_base); | ||
4270 | continue; | ||
4271 | } | ||
4272 | |||
4273 | if((myrombase = vmalloc(65536))) | ||
4274 | memcpy_fromio(myrombase, rom_base, 65536); | ||
4275 | |||
4276 | iounmap(rom_base); | ||
4277 | break; | ||
4025 | 4278 | ||
4026 | iounmap(rom_base); | ||
4027 | } | 4279 | } |
4028 | 4280 | ||
4029 | #else | 4281 | #else |
@@ -4034,752 +4286,1603 @@ static UCHAR * __devinit sis_find_rom(struct pci_dev *pdev) | |||
4034 | 4286 | ||
4035 | rom_base = ioremap(ivideo->video_base, 65536); | 4287 | rom_base = ioremap(ivideo->video_base, 65536); |
4036 | if(rom_base) { | 4288 | if(rom_base) { |
4037 | if((readb(rom_base) == 0x55) && (readb(rom_base + 1) == 0xaa)) { | 4289 | if(sisfb_check_rom(rom_base, ivideo)) { |
4038 | romptr = (u16)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8)); | 4290 | if((myrombase = vmalloc(65536))) |
4039 | if(romptr <= (0x10000 - 8)) { | 4291 | memcpy_fromio(myrombase, rom_base, 65536); |
4040 | rom = rom_base + romptr; | 4292 | } |
4041 | if((readb(rom) == 'P') && (readb(rom + 1) == 'C') && | 4293 | iounmap(rom_base); |
4042 | (readb(rom + 2) == 'I') && (readb(rom + 3) == 'R')) { | ||
4043 | pciid = readb(rom + 4) | (readb(rom + 5) << 8); | ||
4044 | if(pciid == 0x1039) { | ||
4045 | pciid = readb(rom + 6) | (readb(rom + 7) << 8); | ||
4046 | if(pciid == ivideo->chip_id) { | ||
4047 | memcpy_fromio(myrombase, rom_base, 65536); | ||
4048 | iounmap(rom_base); | ||
4049 | pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp); | ||
4050 | return myrombase; | ||
4051 | } | ||
4052 | } | ||
4053 | } | ||
4054 | } | ||
4055 | } | ||
4056 | iounmap(rom_base); | ||
4057 | } | 4294 | } |
4058 | pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp); | 4295 | |
4296 | pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp); | ||
4059 | 4297 | ||
4060 | #endif | 4298 | #endif |
4061 | 4299 | ||
4062 | vfree(myrombase); | 4300 | return myrombase; |
4063 | return NULL; | 4301 | } |
4302 | |||
4303 | static void __devinit | ||
4304 | sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize, | ||
4305 | unsigned int min) | ||
4306 | { | ||
4307 | ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize)); | ||
4308 | |||
4309 | if(!ivideo->video_vbase) { | ||
4310 | printk(KERN_ERR | ||
4311 | "sisfb: Unable to map maximum video RAM for size detection\n"); | ||
4312 | (*mapsize) >>= 1; | ||
4313 | while((!(ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize))))) { | ||
4314 | (*mapsize) >>= 1; | ||
4315 | if((*mapsize) < (min << 20)) | ||
4316 | break; | ||
4317 | } | ||
4318 | if(ivideo->video_vbase) { | ||
4319 | printk(KERN_ERR | ||
4320 | "sisfb: Video RAM size detection limited to %dMB\n", | ||
4321 | (int)((*mapsize) >> 20)); | ||
4322 | } | ||
4323 | } | ||
4064 | } | 4324 | } |
4065 | 4325 | ||
4066 | #ifdef CONFIG_FB_SIS_300 | 4326 | #ifdef CONFIG_FB_SIS_300 |
4067 | static int __devinit | 4327 | static int __devinit |
4068 | sisfb_chkbuswidth300(struct pci_dev *pdev, SIS_IOTYPE1 *FBAddress) | 4328 | sisfb_post_300_buswidth(struct sis_video_info *ivideo) |
4069 | { | 4329 | { |
4070 | struct sis_video_info *ivideo = pci_get_drvdata(pdev); | 4330 | SIS_IOTYPE1 *FBAddress = ivideo->video_vbase; |
4331 | unsigned short temp; | ||
4332 | unsigned char reg; | ||
4071 | int i, j; | 4333 | int i, j; |
4072 | USHORT temp; | 4334 | |
4073 | UCHAR reg; | 4335 | andSISIDXREG(SISSR, 0x15, 0xFB); |
4074 | 4336 | orSISIDXREG(SISSR, 0x15, 0x04); | |
4075 | andSISIDXREG(SISSR,0x15,0xFB); | 4337 | outSISIDXREG(SISSR, 0x13, 0x00); |
4076 | orSISIDXREG(SISSR,0x15,0x04); | 4338 | outSISIDXREG(SISSR, 0x14, 0xBF); |
4077 | outSISIDXREG(SISSR,0x13,0x00); | 4339 | |
4078 | outSISIDXREG(SISSR,0x14,0xBF); | 4340 | for(i = 0; i < 2; i++) { |
4079 | 4341 | temp = 0x1234; | |
4080 | for(i=0; i<2; i++) { | 4342 | for(j = 0; j < 4; j++) { |
4081 | temp = 0x1234; | 4343 | writew(temp, FBAddress); |
4082 | for(j=0; j<4; j++) { | 4344 | if(readw(FBAddress) == temp) |
4083 | writew(temp, FBAddress); | 4345 | break; |
4084 | if(readw(FBAddress) == temp) break; | 4346 | orSISIDXREG(SISSR, 0x3c, 0x01); |
4085 | orSISIDXREG(SISSR,0x3c,0x01); | 4347 | inSISIDXREG(SISSR, 0x05, reg); |
4086 | inSISIDXREG(SISSR,0x05,reg); | 4348 | inSISIDXREG(SISSR, 0x05, reg); |
4087 | inSISIDXREG(SISSR,0x05,reg); | 4349 | andSISIDXREG(SISSR, 0x3c, 0xfe); |
4088 | andSISIDXREG(SISSR,0x3c,0xfe); | 4350 | inSISIDXREG(SISSR, 0x05, reg); |
4089 | inSISIDXREG(SISSR,0x05,reg); | 4351 | inSISIDXREG(SISSR, 0x05, reg); |
4090 | inSISIDXREG(SISSR,0x05,reg); | 4352 | temp++; |
4091 | temp++; | 4353 | } |
4092 | } | ||
4093 | } | 4354 | } |
4094 | 4355 | ||
4095 | writel(0x01234567L, FBAddress); | 4356 | writel(0x01234567L, FBAddress); |
4096 | writel(0x456789ABL, (FBAddress+4)); | 4357 | writel(0x456789ABL, (FBAddress + 4)); |
4097 | writel(0x89ABCDEFL, (FBAddress+8)); | 4358 | writel(0x89ABCDEFL, (FBAddress + 8)); |
4098 | writel(0xCDEF0123L, (FBAddress+12)); | 4359 | writel(0xCDEF0123L, (FBAddress + 12)); |
4099 | inSISIDXREG(SISSR,0x3b,reg); | 4360 | |
4361 | inSISIDXREG(SISSR, 0x3b, reg); | ||
4100 | if(reg & 0x01) { | 4362 | if(reg & 0x01) { |
4101 | if(readl((FBAddress+12)) == 0xCDEF0123L) return(4); /* Channel A 128bit */ | 4363 | if(readl((FBAddress + 12)) == 0xCDEF0123L) |
4364 | return 4; /* Channel A 128bit */ | ||
4102 | } | 4365 | } |
4103 | if(readl((FBAddress+4)) == 0x456789ABL) return(2); /* Channel B 64bit */ | 4366 | |
4104 | return(1); /* 32bit */ | 4367 | if(readl((FBAddress + 4)) == 0x456789ABL) |
4368 | return 2; /* Channel B 64bit */ | ||
4369 | |||
4370 | return 1; /* 32bit */ | ||
4371 | } | ||
4372 | |||
4373 | static int __devinit | ||
4374 | sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth, | ||
4375 | int PseudoRankCapacity, int PseudoAdrPinCount, | ||
4376 | unsigned int mapsize) | ||
4377 | { | ||
4378 | SIS_IOTYPE1 *FBAddr = ivideo->video_vbase; | ||
4379 | unsigned short sr14; | ||
4380 | unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid; | ||
4381 | unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage; | ||
4382 | static const unsigned short SiS_DRAMType[17][5] = { | ||
4383 | {0x0C,0x0A,0x02,0x40,0x39}, | ||
4384 | {0x0D,0x0A,0x01,0x40,0x48}, | ||
4385 | {0x0C,0x09,0x02,0x20,0x35}, | ||
4386 | {0x0D,0x09,0x01,0x20,0x44}, | ||
4387 | {0x0C,0x08,0x02,0x10,0x31}, | ||
4388 | {0x0D,0x08,0x01,0x10,0x40}, | ||
4389 | {0x0C,0x0A,0x01,0x20,0x34}, | ||
4390 | {0x0C,0x09,0x01,0x08,0x32}, | ||
4391 | {0x0B,0x08,0x02,0x08,0x21}, | ||
4392 | {0x0C,0x08,0x01,0x08,0x30}, | ||
4393 | {0x0A,0x08,0x02,0x04,0x11}, | ||
4394 | {0x0B,0x0A,0x01,0x10,0x28}, | ||
4395 | {0x09,0x08,0x02,0x02,0x01}, | ||
4396 | {0x0B,0x09,0x01,0x08,0x24}, | ||
4397 | {0x0B,0x08,0x01,0x04,0x20}, | ||
4398 | {0x0A,0x08,0x01,0x02,0x10}, | ||
4399 | {0x09,0x08,0x01,0x01,0x00} | ||
4400 | }; | ||
4401 | |||
4402 | for(k = 0; k <= 16; k++) { | ||
4403 | |||
4404 | RankCapacity = buswidth * SiS_DRAMType[k][3]; | ||
4405 | |||
4406 | if(RankCapacity != PseudoRankCapacity) | ||
4407 | continue; | ||
4408 | |||
4409 | if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount) | ||
4410 | continue; | ||
4411 | |||
4412 | BankNumHigh = RankCapacity * 16 * iteration - 1; | ||
4413 | if(iteration == 3) { /* Rank No */ | ||
4414 | BankNumMid = RankCapacity * 16 - 1; | ||
4415 | } else { | ||
4416 | BankNumMid = RankCapacity * 16 * iteration / 2 - 1; | ||
4417 | } | ||
4418 | |||
4419 | PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4; | ||
4420 | PhysicalAdrHigh = BankNumHigh; | ||
4421 | PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity; | ||
4422 | PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh; | ||
4423 | |||
4424 | andSISIDXREG(SISSR, 0x15, 0xFB); /* Test */ | ||
4425 | orSISIDXREG(SISSR, 0x15, 0x04); /* Test */ | ||
4426 | sr14 = (SiS_DRAMType[k][3] * buswidth) - 1; | ||
4427 | if(buswidth == 4) sr14 |= 0x80; | ||
4428 | else if(buswidth == 2) sr14 |= 0x40; | ||
4429 | outSISIDXREG(SISSR, 0x13, SiS_DRAMType[k][4]); | ||
4430 | outSISIDXREG(SISSR, 0x14, sr14); | ||
4431 | |||
4432 | BankNumHigh <<= 16; | ||
4433 | BankNumMid <<= 16; | ||
4434 | |||
4435 | if((BankNumHigh + PhysicalAdrHigh >= mapsize) || | ||
4436 | (BankNumMid + PhysicalAdrHigh >= mapsize) || | ||
4437 | (BankNumHigh + PhysicalAdrHalfPage >= mapsize) || | ||
4438 | (BankNumHigh + PhysicalAdrOtherPage >= mapsize)) | ||
4439 | continue; | ||
4440 | |||
4441 | /* Write data */ | ||
4442 | writew(((unsigned short)PhysicalAdrHigh), | ||
4443 | (FBAddr + BankNumHigh + PhysicalAdrHigh)); | ||
4444 | writew(((unsigned short)BankNumMid), | ||
4445 | (FBAddr + BankNumMid + PhysicalAdrHigh)); | ||
4446 | writew(((unsigned short)PhysicalAdrHalfPage), | ||
4447 | (FBAddr + BankNumHigh + PhysicalAdrHalfPage)); | ||
4448 | writew(((unsigned short)PhysicalAdrOtherPage), | ||
4449 | (FBAddr + BankNumHigh + PhysicalAdrOtherPage)); | ||
4450 | |||
4451 | /* Read data */ | ||
4452 | if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh) | ||
4453 | return 1; | ||
4454 | } | ||
4455 | |||
4456 | return 0; | ||
4105 | } | 4457 | } |
4106 | 4458 | ||
4107 | static void __devinit | 4459 | static void __devinit |
4108 | sisfb_setramsize300(struct pci_dev *pdev) | 4460 | sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize) |
4109 | { | 4461 | { |
4110 | struct sis_video_info *ivideo = pci_get_drvdata(pdev); | 4462 | struct sis_video_info *ivideo = pci_get_drvdata(pdev); |
4111 | SIS_IOTYPE1 *FBAddr = ivideo->video_vbase; | 4463 | int i, j, buswidth; |
4112 | SIS_IOTYPE1 *Addr; | 4464 | int PseudoRankCapacity, PseudoAdrPinCount; |
4113 | USHORT sr13, sr14=0, buswidth, Done, data, TotalCapacity, PhysicalAdrOtherPage=0; | 4465 | |
4114 | int PseudoRankCapacity, PseudoTotalCapacity, PseudoAdrPinCount; | 4466 | buswidth = sisfb_post_300_buswidth(ivideo); |
4115 | int RankCapacity, AdrPinCount, BankNumHigh, BankNumMid, MB2Bank; | 4467 | |
4116 | int PageCapacity, PhysicalAdrHigh, PhysicalAdrHalfPage, i, j, k; | 4468 | for(i = 6; i >= 0; i--) { |
4117 | const USHORT SiS_DRAMType[17][5] = { | 4469 | PseudoRankCapacity = 1 << i; |
4118 | {0x0C,0x0A,0x02,0x40,0x39}, | 4470 | for(j = 4; j >= 1; j--) { |
4119 | {0x0D,0x0A,0x01,0x40,0x48}, | 4471 | PseudoAdrPinCount = 15 - j; |
4120 | {0x0C,0x09,0x02,0x20,0x35}, | 4472 | if((PseudoRankCapacity * j) <= 64) { |
4121 | {0x0D,0x09,0x01,0x20,0x44}, | 4473 | if(sisfb_post_300_rwtest(ivideo, |
4122 | {0x0C,0x08,0x02,0x10,0x31}, | 4474 | j, |
4123 | {0x0D,0x08,0x01,0x10,0x40}, | 4475 | buswidth, |
4124 | {0x0C,0x0A,0x01,0x20,0x34}, | 4476 | PseudoRankCapacity, |
4125 | {0x0C,0x09,0x01,0x08,0x32}, | 4477 | PseudoAdrPinCount, |
4126 | {0x0B,0x08,0x02,0x08,0x21}, | 4478 | mapsize)) |
4127 | {0x0C,0x08,0x01,0x08,0x30}, | 4479 | return; |
4128 | {0x0A,0x08,0x02,0x04,0x11}, | 4480 | } |
4129 | {0x0B,0x0A,0x01,0x10,0x28}, | 4481 | } |
4130 | {0x09,0x08,0x02,0x02,0x01}, | 4482 | } |
4131 | {0x0B,0x09,0x01,0x08,0x24}, | ||
4132 | {0x0B,0x08,0x01,0x04,0x20}, | ||
4133 | {0x0A,0x08,0x01,0x02,0x10}, | ||
4134 | {0x09,0x08,0x01,0x01,0x00} | ||
4135 | }; | ||
4136 | |||
4137 | buswidth = sisfb_chkbuswidth300(pdev, FBAddr); | ||
4138 | |||
4139 | MB2Bank = 16; | ||
4140 | Done = 0; | ||
4141 | for(i = 6; i >= 0; i--) { | ||
4142 | if(Done) break; | ||
4143 | PseudoRankCapacity = 1 << i; | ||
4144 | for(j = 4; j >= 1; j--) { | ||
4145 | if(Done) break; | ||
4146 | PseudoTotalCapacity = PseudoRankCapacity * j; | ||
4147 | PseudoAdrPinCount = 15 - j; | ||
4148 | if(PseudoTotalCapacity <= 64) { | ||
4149 | for(k = 0; k <= 16; k++) { | ||
4150 | if(Done) break; | ||
4151 | RankCapacity = buswidth * SiS_DRAMType[k][3]; | ||
4152 | AdrPinCount = SiS_DRAMType[k][2] + SiS_DRAMType[k][0]; | ||
4153 | if(RankCapacity == PseudoRankCapacity) | ||
4154 | if(AdrPinCount <= PseudoAdrPinCount) { | ||
4155 | if(j == 3) { /* Rank No */ | ||
4156 | BankNumHigh = RankCapacity * MB2Bank * 3 - 1; | ||
4157 | BankNumMid = RankCapacity * MB2Bank * 1 - 1; | ||
4158 | } else { | ||
4159 | BankNumHigh = RankCapacity * MB2Bank * j - 1; | ||
4160 | BankNumMid = RankCapacity * MB2Bank * j / 2 - 1; | ||
4161 | } | ||
4162 | PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4; | ||
4163 | PhysicalAdrHigh = BankNumHigh; | ||
4164 | PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity; | ||
4165 | PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh; | ||
4166 | /* Write data */ | ||
4167 | andSISIDXREG(SISSR,0x15,0xFB); /* Test */ | ||
4168 | orSISIDXREG(SISSR,0x15,0x04); /* Test */ | ||
4169 | TotalCapacity = SiS_DRAMType[k][3] * buswidth; | ||
4170 | sr13 = SiS_DRAMType[k][4]; | ||
4171 | if(buswidth == 4) sr14 = (TotalCapacity - 1) | 0x80; | ||
4172 | if(buswidth == 2) sr14 = (TotalCapacity - 1) | 0x40; | ||
4173 | if(buswidth == 1) sr14 = (TotalCapacity - 1) | 0x00; | ||
4174 | outSISIDXREG(SISSR,0x13,sr13); | ||
4175 | outSISIDXREG(SISSR,0x14,sr14); | ||
4176 | Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHigh; | ||
4177 | /* *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHigh; */ | ||
4178 | writew(((USHORT)PhysicalAdrHigh), Addr); | ||
4179 | Addr = FBAddr + BankNumMid * 64 * 1024 + PhysicalAdrHigh; | ||
4180 | /* *((USHORT *)(Addr)) = (USHORT)BankNumMid; */ | ||
4181 | writew(((USHORT)BankNumMid), Addr); | ||
4182 | Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHalfPage; | ||
4183 | /* *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHalfPage; */ | ||
4184 | writew(((USHORT)PhysicalAdrHalfPage), Addr); | ||
4185 | Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrOtherPage; | ||
4186 | /* *((USHORT *)(Addr)) = PhysicalAdrOtherPage; */ | ||
4187 | writew(((USHORT)PhysicalAdrOtherPage), Addr); | ||
4188 | /* Read data */ | ||
4189 | Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHigh; | ||
4190 | data = readw(Addr); /* *((USHORT *)(Addr)); */ | ||
4191 | if(data == PhysicalAdrHigh) Done = 1; | ||
4192 | } /* if */ | ||
4193 | } /* for k */ | ||
4194 | } /* if */ | ||
4195 | } /* for j */ | ||
4196 | } /* for i */ | ||
4197 | } | 4483 | } |
4198 | 4484 | ||
4199 | static void __devinit sisfb_post_sis300(struct pci_dev *pdev) | 4485 | static void __devinit |
4486 | sisfb_post_sis300(struct pci_dev *pdev) | ||
4200 | { | 4487 | { |
4201 | struct sis_video_info *ivideo = pci_get_drvdata(pdev); | 4488 | struct sis_video_info *ivideo = pci_get_drvdata(pdev); |
4489 | unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase; | ||
4202 | u8 reg, v1, v2, v3, v4, v5, v6, v7, v8; | 4490 | u8 reg, v1, v2, v3, v4, v5, v6, v7, v8; |
4203 | u16 index, rindex, memtype = 0; | 4491 | u16 index, rindex, memtype = 0; |
4492 | unsigned int mapsize; | ||
4204 | 4493 | ||
4205 | outSISIDXREG(SISSR,0x05,0x86); | 4494 | if(!ivideo->SiS_Pr.UseROM) |
4495 | bios = NULL; | ||
4206 | 4496 | ||
4207 | if(ivideo->sishw_ext.UseROM) { | 4497 | outSISIDXREG(SISSR, 0x05, 0x86); |
4208 | if(ivideo->sishw_ext.pjVirtualRomBase[0x52] & 0x80) { | 4498 | |
4209 | memtype = ivideo->sishw_ext.pjVirtualRomBase[0x52]; | 4499 | if(bios) { |
4210 | } else { | 4500 | if(bios[0x52] & 0x80) { |
4211 | inSISIDXREG(SISSR,0x3a,memtype); | 4501 | memtype = bios[0x52]; |
4212 | } | 4502 | } else { |
4213 | memtype &= 0x07; | 4503 | inSISIDXREG(SISSR, 0x3a, memtype); |
4504 | } | ||
4505 | memtype &= 0x07; | ||
4214 | } | 4506 | } |
4215 | 4507 | ||
4508 | v3 = 0x80; v6 = 0x80; | ||
4216 | if(ivideo->revision_id <= 0x13) { | 4509 | if(ivideo->revision_id <= 0x13) { |
4217 | v1 = 0x44; v2 = 0x42; v3 = 0x80; | 4510 | v1 = 0x44; v2 = 0x42; |
4218 | v4 = 0x44; v5 = 0x42; v6 = 0x80; | 4511 | v4 = 0x44; v5 = 0x42; |
4219 | } else { | 4512 | } else { |
4220 | v1 = 0x68; v2 = 0x43; v3 = 0x80; /* Assume 125Mhz MCLK */ | 4513 | v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */ |
4221 | v4 = 0x68; v5 = 0x43; v6 = 0x80; /* Assume 125Mhz ECLK */ | 4514 | v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */ |
4222 | if(ivideo->sishw_ext.UseROM) { | 4515 | if(bios) { |
4223 | index = memtype * 5; | 4516 | index = memtype * 5; |
4224 | rindex = index + 0x54; | 4517 | rindex = index + 0x54; |
4225 | v1 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; | 4518 | v1 = bios[rindex++]; |
4226 | v2 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; | 4519 | v2 = bios[rindex++]; |
4227 | v3 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; | 4520 | v3 = bios[rindex++]; |
4228 | rindex = index + 0x7c; | 4521 | rindex = index + 0x7c; |
4229 | v4 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; | 4522 | v4 = bios[rindex++]; |
4230 | v5 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; | 4523 | v5 = bios[rindex++]; |
4231 | v6 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; | 4524 | v6 = bios[rindex++]; |
4232 | } | 4525 | } |
4233 | } | 4526 | } |
4234 | outSISIDXREG(SISSR,0x28,v1); | 4527 | outSISIDXREG(SISSR, 0x28, v1); |
4235 | outSISIDXREG(SISSR,0x29,v2); | 4528 | outSISIDXREG(SISSR, 0x29, v2); |
4236 | outSISIDXREG(SISSR,0x2a,v3); | 4529 | outSISIDXREG(SISSR, 0x2a, v3); |
4237 | outSISIDXREG(SISSR,0x2e,v4); | 4530 | outSISIDXREG(SISSR, 0x2e, v4); |
4238 | outSISIDXREG(SISSR,0x2f,v5); | 4531 | outSISIDXREG(SISSR, 0x2f, v5); |
4239 | outSISIDXREG(SISSR,0x30,v6); | 4532 | outSISIDXREG(SISSR, 0x30, v6); |
4533 | |||
4240 | v1 = 0x10; | 4534 | v1 = 0x10; |
4241 | if(ivideo->sishw_ext.UseROM) v1 = ivideo->sishw_ext.pjVirtualRomBase[0xa4]; | 4535 | if(bios) |
4242 | outSISIDXREG(SISSR,0x07,v1); /* DAC speed */ | 4536 | v1 = bios[0xa4]; |
4243 | outSISIDXREG(SISSR,0x11,0x0f); /* DDC, power save */ | 4537 | outSISIDXREG(SISSR, 0x07, v1); /* DAC speed */ |
4538 | |||
4539 | outSISIDXREG(SISSR, 0x11, 0x0f); /* DDC, power save */ | ||
4540 | |||
4244 | v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a; | 4541 | v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a; |
4245 | v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00; | 4542 | v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00; |
4246 | if(ivideo->sishw_ext.UseROM) { | 4543 | if(bios) { |
4247 | memtype += 0xa5; | 4544 | memtype += 0xa5; |
4248 | v1 = ivideo->sishw_ext.pjVirtualRomBase[memtype]; | 4545 | v1 = bios[memtype]; |
4249 | v2 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 8]; | 4546 | v2 = bios[memtype + 8]; |
4250 | v3 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 16]; | 4547 | v3 = bios[memtype + 16]; |
4251 | v4 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 24]; | 4548 | v4 = bios[memtype + 24]; |
4252 | v5 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 32]; | 4549 | v5 = bios[memtype + 32]; |
4253 | v6 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 40]; | 4550 | v6 = bios[memtype + 40]; |
4254 | v7 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 48]; | 4551 | v7 = bios[memtype + 48]; |
4255 | v8 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 56]; | 4552 | v8 = bios[memtype + 56]; |
4256 | } | 4553 | } |
4257 | if(ivideo->revision_id >= 0x80) v3 &= 0xfd; | 4554 | if(ivideo->revision_id >= 0x80) |
4258 | outSISIDXREG(SISSR,0x15,v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */ | 4555 | v3 &= 0xfd; |
4259 | outSISIDXREG(SISSR,0x16,v2); | 4556 | outSISIDXREG(SISSR, 0x15, v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */ |
4260 | outSISIDXREG(SISSR,0x17,v3); | 4557 | outSISIDXREG(SISSR, 0x16, v2); |
4261 | outSISIDXREG(SISSR,0x18,v4); | 4558 | outSISIDXREG(SISSR, 0x17, v3); |
4262 | outSISIDXREG(SISSR,0x19,v5); | 4559 | outSISIDXREG(SISSR, 0x18, v4); |
4263 | outSISIDXREG(SISSR,0x1a,v6); | 4560 | outSISIDXREG(SISSR, 0x19, v5); |
4264 | outSISIDXREG(SISSR,0x1b,v7); | 4561 | outSISIDXREG(SISSR, 0x1a, v6); |
4265 | outSISIDXREG(SISSR,0x1c,v8); /* ---- */ | 4562 | outSISIDXREG(SISSR, 0x1b, v7); |
4266 | andSISIDXREG(SISSR,0x15,0xfb); | 4563 | outSISIDXREG(SISSR, 0x1c, v8); /* ---- */ |
4267 | orSISIDXREG(SISSR,0x15,0x04); | 4564 | andSISIDXREG(SISSR, 0x15 ,0xfb); |
4268 | if(ivideo->sishw_ext.UseROM) { | 4565 | orSISIDXREG(SISSR, 0x15, 0x04); |
4269 | if(ivideo->sishw_ext.pjVirtualRomBase[0x53] & 0x02) { | 4566 | if(bios) { |
4270 | orSISIDXREG(SISSR,0x19,0x20); | 4567 | if(bios[0x53] & 0x02) { |
4271 | } | 4568 | orSISIDXREG(SISSR, 0x19, 0x20); |
4569 | } | ||
4272 | } | 4570 | } |
4273 | v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */ | 4571 | v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */ |
4274 | if(ivideo->revision_id >= 0x80) v1 |= 0x01; | 4572 | if(ivideo->revision_id >= 0x80) |
4275 | outSISIDXREG(SISSR,0x1f,v1); | 4573 | v1 |= 0x01; |
4276 | outSISIDXREG(SISSR,0x20,0xa0); /* linear & relocated io */ | 4574 | outSISIDXREG(SISSR, 0x1f, v1); |
4575 | outSISIDXREG(SISSR, 0x20, 0xa4); /* linear & relocated io & disable a0000 */ | ||
4277 | v1 = 0xf6; v2 = 0x0d; v3 = 0x00; | 4576 | v1 = 0xf6; v2 = 0x0d; v3 = 0x00; |
4278 | if(ivideo->sishw_ext.UseROM) { | 4577 | if(bios) { |
4279 | v1 = ivideo->sishw_ext.pjVirtualRomBase[0xe8]; | 4578 | v1 = bios[0xe8]; |
4280 | v2 = ivideo->sishw_ext.pjVirtualRomBase[0xe9]; | 4579 | v2 = bios[0xe9]; |
4281 | v3 = ivideo->sishw_ext.pjVirtualRomBase[0xea]; | 4580 | v3 = bios[0xea]; |
4282 | } | 4581 | } |
4283 | outSISIDXREG(SISSR,0x23,v1); | 4582 | outSISIDXREG(SISSR, 0x23, v1); |
4284 | outSISIDXREG(SISSR,0x24,v2); | 4583 | outSISIDXREG(SISSR, 0x24, v2); |
4285 | outSISIDXREG(SISSR,0x25,v3); | 4584 | outSISIDXREG(SISSR, 0x25, v3); |
4286 | outSISIDXREG(SISSR,0x21,0x84); | 4585 | outSISIDXREG(SISSR, 0x21, 0x84); |
4287 | outSISIDXREG(SISSR,0x22,0x00); | 4586 | outSISIDXREG(SISSR, 0x22, 0x00); |
4288 | outSISIDXREG(SISCR,0x37,0x00); | 4587 | outSISIDXREG(SISCR, 0x37, 0x00); |
4289 | orSISIDXREG(SISPART1,0x24,0x01); /* unlock crt2 */ | 4588 | orSISIDXREG(SISPART1, 0x24, 0x01); /* unlock crt2 */ |
4290 | outSISIDXREG(SISPART1,0x00,0x00); | 4589 | outSISIDXREG(SISPART1, 0x00, 0x00); |
4291 | v1 = 0x40; v2 = 0x11; | 4590 | v1 = 0x40; v2 = 0x11; |
4292 | if(ivideo->sishw_ext.UseROM) { | 4591 | if(bios) { |
4293 | v1 = ivideo->sishw_ext.pjVirtualRomBase[0xec]; | 4592 | v1 = bios[0xec]; |
4294 | v2 = ivideo->sishw_ext.pjVirtualRomBase[0xeb]; | 4593 | v2 = bios[0xeb]; |
4295 | } | 4594 | } |
4296 | outSISIDXREG(SISPART1,0x02,v1); | 4595 | outSISIDXREG(SISPART1, 0x02, v1); |
4297 | if(ivideo->revision_id >= 0x80) v2 &= ~0x01; | 4596 | |
4298 | inSISIDXREG(SISPART4,0x00,reg); | 4597 | if(ivideo->revision_id >= 0x80) |
4598 | v2 &= ~0x01; | ||
4599 | |||
4600 | inSISIDXREG(SISPART4, 0x00, reg); | ||
4299 | if((reg == 1) || (reg == 2)) { | 4601 | if((reg == 1) || (reg == 2)) { |
4300 | outSISIDXREG(SISCR,0x37,0x02); | 4602 | outSISIDXREG(SISCR, 0x37, 0x02); |
4301 | outSISIDXREG(SISPART2,0x00,0x1c); | 4603 | outSISIDXREG(SISPART2, 0x00, 0x1c); |
4302 | v4 = 0x00; v5 = 0x00; v6 = 0x10; | 4604 | v4 = 0x00; v5 = 0x00; v6 = 0x10; |
4303 | if(ivideo->sishw_ext.UseROM) { | 4605 | if(ivideo->SiS_Pr.UseROM) { |
4304 | v4 = ivideo->sishw_ext.pjVirtualRomBase[0xf5]; | 4606 | v4 = bios[0xf5]; |
4305 | v5 = ivideo->sishw_ext.pjVirtualRomBase[0xf6]; | 4607 | v5 = bios[0xf6]; |
4306 | v6 = ivideo->sishw_ext.pjVirtualRomBase[0xf7]; | 4608 | v6 = bios[0xf7]; |
4307 | } | 4609 | } |
4308 | outSISIDXREG(SISPART4,0x0d,v4); | 4610 | outSISIDXREG(SISPART4, 0x0d, v4); |
4309 | outSISIDXREG(SISPART4,0x0e,v5); | 4611 | outSISIDXREG(SISPART4, 0x0e, v5); |
4310 | outSISIDXREG(SISPART4,0x10,v6); | 4612 | outSISIDXREG(SISPART4, 0x10, v6); |
4311 | outSISIDXREG(SISPART4,0x0f,0x3f); | 4613 | outSISIDXREG(SISPART4, 0x0f, 0x3f); |
4312 | inSISIDXREG(SISPART4,0x01,reg); | 4614 | inSISIDXREG(SISPART4, 0x01, reg); |
4313 | if(reg >= 0xb0) { | 4615 | if(reg >= 0xb0) { |
4314 | inSISIDXREG(SISPART4,0x23,reg); | 4616 | inSISIDXREG(SISPART4, 0x23, reg); |
4315 | reg &= 0x20; | 4617 | reg &= 0x20; |
4316 | reg <<= 1; | 4618 | reg <<= 1; |
4317 | outSISIDXREG(SISPART4,0x23,reg); | 4619 | outSISIDXREG(SISPART4, 0x23, reg); |
4318 | } | 4620 | } |
4319 | } else { | 4621 | } else { |
4320 | v2 &= ~0x10; | 4622 | v2 &= ~0x10; |
4321 | } | 4623 | } |
4322 | outSISIDXREG(SISSR,0x32,v2); | 4624 | outSISIDXREG(SISSR, 0x32, v2); |
4323 | andSISIDXREG(SISPART1,0x24,0xfe); /* Lock CRT2 */ | 4625 | |
4324 | inSISIDXREG(SISSR,0x16,reg); | 4626 | andSISIDXREG(SISPART1, 0x24, 0xfe); /* Lock CRT2 */ |
4627 | |||
4628 | inSISIDXREG(SISSR, 0x16, reg); | ||
4325 | reg &= 0xc3; | 4629 | reg &= 0xc3; |
4326 | outSISIDXREG(SISCR,0x35,reg); | 4630 | outSISIDXREG(SISCR, 0x35, reg); |
4327 | outSISIDXREG(SISCR,0x83,0x00); | 4631 | outSISIDXREG(SISCR, 0x83, 0x00); |
4328 | #if !defined(__i386__) && !defined(__x86_64__) | 4632 | #if !defined(__i386__) && !defined(__x86_64__) |
4329 | if(sisfb_videoram) { | 4633 | if(sisfb_videoram) { |
4330 | outSISIDXREG(SISSR,0x13,0x28); /* ? */ | 4634 | outSISIDXREG(SISSR, 0x13, 0x28); /* ? */ |
4331 | reg = ((sisfb_videoram >> 10) - 1) | 0x40; | 4635 | reg = ((sisfb_videoram >> 10) - 1) | 0x40; |
4332 | outSISIDXREG(SISSR,0x14,reg); | 4636 | outSISIDXREG(SISSR, 0x14, reg); |
4333 | } else { | 4637 | } else { |
4334 | #endif | 4638 | #endif |
4335 | /* Need to map max FB size for finding out about RAM size */ | 4639 | /* Need to map max FB size for finding out about RAM size */ |
4336 | ivideo->video_vbase = ioremap(ivideo->video_base, 0x4000000); | 4640 | mapsize = 64 << 20; |
4337 | if(ivideo->video_vbase) { | 4641 | sisfb_post_map_vram(ivideo, &mapsize, 4); |
4338 | sisfb_setramsize300(pdev); | 4642 | |
4339 | iounmap(ivideo->video_vbase); | 4643 | if(ivideo->video_vbase) { |
4340 | } else { | 4644 | sisfb_post_300_ramsize(pdev, mapsize); |
4341 | printk(KERN_DEBUG "sisfb: Failed to map memory for size detection, assuming 8MB\n"); | 4645 | iounmap(ivideo->video_vbase); |
4342 | outSISIDXREG(SISSR,0x13,0x28); /* ? */ | 4646 | } else { |
4343 | outSISIDXREG(SISSR,0x14,0x47); /* 8MB, 64bit default */ | 4647 | printk(KERN_DEBUG |
4344 | } | 4648 | "sisfb: Failed to map memory for size detection, assuming 8MB\n"); |
4649 | outSISIDXREG(SISSR, 0x13, 0x28); /* ? */ | ||
4650 | outSISIDXREG(SISSR, 0x14, 0x47); /* 8MB, 64bit default */ | ||
4651 | } | ||
4345 | #if !defined(__i386__) && !defined(__x86_64__) | 4652 | #if !defined(__i386__) && !defined(__x86_64__) |
4346 | } | 4653 | } |
4347 | #endif | 4654 | #endif |
4348 | if(ivideo->sishw_ext.UseROM) { | 4655 | if(bios) { |
4349 | v1 = ivideo->sishw_ext.pjVirtualRomBase[0xe6]; | 4656 | v1 = bios[0xe6]; |
4350 | v2 = ivideo->sishw_ext.pjVirtualRomBase[0xe7]; | 4657 | v2 = bios[0xe7]; |
4351 | } else { | 4658 | } else { |
4352 | inSISIDXREG(SISSR,0x3a,reg); | 4659 | inSISIDXREG(SISSR, 0x3a, reg); |
4353 | if((reg & 0x30) == 0x30) { | 4660 | if((reg & 0x30) == 0x30) { |
4354 | v1 = 0x04; /* PCI */ | 4661 | v1 = 0x04; /* PCI */ |
4355 | v2 = 0x92; | 4662 | v2 = 0x92; |
4356 | } else { | 4663 | } else { |
4357 | v1 = 0x14; /* AGP */ | 4664 | v1 = 0x14; /* AGP */ |
4358 | v2 = 0xb2; | 4665 | v2 = 0xb2; |
4359 | } | 4666 | } |
4360 | } | 4667 | } |
4361 | outSISIDXREG(SISSR,0x21,v1); | 4668 | outSISIDXREG(SISSR, 0x21, v1); |
4362 | outSISIDXREG(SISSR,0x22,v2); | 4669 | outSISIDXREG(SISSR, 0x22, v2); |
4670 | |||
4671 | /* Sense CRT1 */ | ||
4672 | sisfb_sense_crt1(ivideo); | ||
4673 | |||
4674 | /* Set default mode, don't clear screen */ | ||
4675 | ivideo->SiS_Pr.SiS_UseOEM = FALSE; | ||
4676 | SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE); | ||
4677 | SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE); | ||
4678 | ivideo->curFSTN = ivideo->curDSTN = 0; | ||
4679 | ivideo->SiS_Pr.VideoMemorySize = 8 << 20; | ||
4680 | SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80); | ||
4681 | |||
4682 | outSISIDXREG(SISSR, 0x05, 0x86); | ||
4683 | |||
4684 | /* Display off */ | ||
4685 | orSISIDXREG(SISSR, 0x01, 0x20); | ||
4686 | |||
4687 | /* Save mode number in CR34 */ | ||
4688 | outSISIDXREG(SISCR, 0x34, 0x2e); | ||
4689 | |||
4690 | /* Let everyone know what the current mode is */ | ||
4691 | ivideo->modeprechange = 0x2e; | ||
4363 | } | 4692 | } |
4364 | #endif | 4693 | #endif |
4365 | 4694 | ||
4366 | #ifdef CONFIG_FB_SIS_315 | 4695 | #ifdef CONFIG_FB_SIS_315 |
4367 | static void __devinit sisfb_post_sis315330(struct pci_dev *pdev) | 4696 | #if 0 |
4697 | static void __devinit | ||
4698 | sisfb_post_sis315330(struct pci_dev *pdev) | ||
4368 | { | 4699 | { |
4369 | #ifdef YET_TO_BE_DONE | 4700 | /* TODO */ |
4370 | struct sis_video_info *ivideo = pci_get_drvdata(pdev); | 4701 | } |
4371 | u8 reg, v1, v2, v3, v4, v5, v6, v7, v8; | 4702 | #endif |
4372 | u16 index, rindex, memtype = 0; | 4703 | |
4373 | u32 reg1_32, reg2_32, reg3_32; | 4704 | static void __devinit |
4705 | sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay) | ||
4706 | { | ||
4707 | unsigned int i; | ||
4708 | u8 reg; | ||
4709 | |||
4710 | for(i = 0; i <= (delay * 10 * 36); i++) { | ||
4711 | inSISIDXREG(SISSR, 0x05, reg); | ||
4712 | reg++; | ||
4713 | } | ||
4714 | } | ||
4715 | |||
4716 | static int __devinit | ||
4717 | sisfb_find_host_bridge(struct sis_video_info *ivideo, struct pci_dev *mypdev, | ||
4718 | unsigned short pcivendor) | ||
4719 | { | ||
4720 | struct pci_dev *pdev = NULL; | ||
4721 | unsigned short temp; | ||
4722 | int ret = 0; | ||
4723 | |||
4724 | while((pdev = SIS_PCI_GET_CLASS(PCI_CLASS_BRIDGE_HOST, pdev))) { | ||
4725 | temp = pdev->vendor; | ||
4726 | SIS_PCI_PUT_DEVICE(pdev); | ||
4727 | if(temp == pcivendor) { | ||
4728 | ret = 1; | ||
4729 | break; | ||
4730 | } | ||
4731 | } | ||
4732 | |||
4733 | return ret; | ||
4734 | } | ||
4735 | |||
4736 | static int __devinit | ||
4737 | sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta, | ||
4738 | unsigned int enda, unsigned int mapsize) | ||
4739 | { | ||
4740 | unsigned int pos; | ||
4374 | int i; | 4741 | int i; |
4375 | 4742 | ||
4376 | /* Unlock */ | 4743 | writel(0, ivideo->video_vbase); |
4377 | /* outSISIDXREG(0x3c4,0x05,0x86); */ | ||
4378 | outSISIDXREG(SISSR,0x05,0x86); | ||
4379 | 4744 | ||
4380 | /* Enable relocated i/o ports */ | 4745 | for(i = starta; i <= enda; i++) { |
4381 | /* setSISIDXREG(0x3c4,0x20,~0x10,0x20); */ | 4746 | pos = 1 << i; |
4382 | setSISIDXREG(SISSR,0x20,~0x10,0x20); | 4747 | if(pos < mapsize) |
4748 | writel(pos, ivideo->video_vbase + pos); | ||
4749 | } | ||
4750 | |||
4751 | sisfb_post_xgi_delay(ivideo, 150); | ||
4752 | |||
4753 | if(readl(ivideo->video_vbase) != 0) | ||
4754 | return 0; | ||
4383 | 4755 | ||
4384 | /* Clear regs */ | 4756 | for(i = starta; i <= enda; i++) { |
4757 | pos = 1 << i; | ||
4758 | if(pos < mapsize) { | ||
4759 | if(readl(ivideo->video_vbase + pos) != pos) | ||
4760 | return 0; | ||
4761 | } else | ||
4762 | return 0; | ||
4763 | } | ||
4764 | |||
4765 | return 1; | ||
4766 | } | ||
4767 | |||
4768 | static void __devinit | ||
4769 | sisfb_post_xgi_ramsize(struct sis_video_info *ivideo) | ||
4770 | { | ||
4771 | unsigned int buswidth, ranksize, channelab, mapsize; | ||
4772 | int i, j, k, l; | ||
4773 | u8 reg, sr14; | ||
4774 | static const u8 dramsr13[12 * 5] = { | ||
4775 | 0x02, 0x0e, 0x0b, 0x80, 0x5d, | ||
4776 | 0x02, 0x0e, 0x0a, 0x40, 0x59, | ||
4777 | 0x02, 0x0d, 0x0b, 0x40, 0x4d, | ||
4778 | 0x02, 0x0e, 0x09, 0x20, 0x55, | ||
4779 | 0x02, 0x0d, 0x0a, 0x20, 0x49, | ||
4780 | 0x02, 0x0c, 0x0b, 0x20, 0x3d, | ||
4781 | 0x02, 0x0e, 0x08, 0x10, 0x51, | ||
4782 | 0x02, 0x0d, 0x09, 0x10, 0x45, | ||
4783 | 0x02, 0x0c, 0x0a, 0x10, 0x39, | ||
4784 | 0x02, 0x0d, 0x08, 0x08, 0x41, | ||
4785 | 0x02, 0x0c, 0x09, 0x08, 0x35, | ||
4786 | 0x02, 0x0c, 0x08, 0x04, 0x31 | ||
4787 | }; | ||
4788 | static const u8 dramsr13_4[4 * 5] = { | ||
4789 | 0x02, 0x0d, 0x09, 0x40, 0x45, | ||
4790 | 0x02, 0x0c, 0x09, 0x20, 0x35, | ||
4791 | 0x02, 0x0c, 0x08, 0x10, 0x31, | ||
4792 | 0x02, 0x0b, 0x08, 0x08, 0x21 | ||
4793 | }; | ||
4794 | |||
4795 | /* Enable linear mode, disable 0xa0000 address decoding */ | ||
4796 | /* We disable a0000 address decoding, because | ||
4797 | * - if running on x86, if the card is disabled, it means | ||
4798 | * that another card is in the system. We don't want | ||
4799 | * to interphere with that primary card's textmode. | ||
4800 | * - if running on non-x86, there usually is no VGA window | ||
4801 | * at a0000. | ||
4802 | */ | ||
4803 | orSISIDXREG(SISSR, 0x20, (0x80 | 0x04)); | ||
4804 | |||
4805 | /* Need to map max FB size for finding out about RAM size */ | ||
4806 | mapsize = 256 << 20; | ||
4807 | sisfb_post_map_vram(ivideo, &mapsize, 32); | ||
4808 | |||
4809 | if(!ivideo->video_vbase) { | ||
4810 | printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n"); | ||
4811 | outSISIDXREG(SISSR, 0x13, 0x35); | ||
4812 | outSISIDXREG(SISSR, 0x14, 0x41); | ||
4813 | /* TODO */ | ||
4814 | return; | ||
4815 | } | ||
4816 | |||
4817 | /* Non-interleaving */ | ||
4818 | outSISIDXREG(SISSR, 0x15, 0x00); | ||
4819 | /* No tiling */ | ||
4820 | outSISIDXREG(SISSR, 0x1c, 0x00); | ||
4821 | |||
4822 | if(ivideo->chip == XGI_20) { | ||
4823 | |||
4824 | channelab = 1; | ||
4825 | inSISIDXREG(SISCR, 0x97, reg); | ||
4826 | if(!(reg & 0x01)) { /* Single 32/16 */ | ||
4827 | buswidth = 32; | ||
4828 | outSISIDXREG(SISSR, 0x13, 0xb1); | ||
4829 | outSISIDXREG(SISSR, 0x14, 0x52); | ||
4830 | sisfb_post_xgi_delay(ivideo, 1); | ||
4831 | sr14 = 0x02; | ||
4832 | if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) | ||
4833 | goto bail_out; | ||
4834 | |||
4835 | outSISIDXREG(SISSR, 0x13, 0x31); | ||
4836 | outSISIDXREG(SISSR, 0x14, 0x42); | ||
4837 | sisfb_post_xgi_delay(ivideo, 1); | ||
4838 | if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize)) | ||
4839 | goto bail_out; | ||
4840 | |||
4841 | buswidth = 16; | ||
4842 | outSISIDXREG(SISSR, 0x13, 0xb1); | ||
4843 | outSISIDXREG(SISSR, 0x14, 0x41); | ||
4844 | sisfb_post_xgi_delay(ivideo, 1); | ||
4845 | sr14 = 0x01; | ||
4846 | if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize)) | ||
4847 | goto bail_out; | ||
4848 | else | ||
4849 | outSISIDXREG(SISSR, 0x13, 0x31); | ||
4850 | } else { /* Dual 16/8 */ | ||
4851 | buswidth = 16; | ||
4852 | outSISIDXREG(SISSR, 0x13, 0xb1); | ||
4853 | outSISIDXREG(SISSR, 0x14, 0x41); | ||
4854 | sisfb_post_xgi_delay(ivideo, 1); | ||
4855 | sr14 = 0x01; | ||
4856 | if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize)) | ||
4857 | goto bail_out; | ||
4858 | |||
4859 | outSISIDXREG(SISSR, 0x13, 0x31); | ||
4860 | outSISIDXREG(SISSR, 0x14, 0x31); | ||
4861 | sisfb_post_xgi_delay(ivideo, 1); | ||
4862 | if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize)) | ||
4863 | goto bail_out; | ||
4864 | |||
4865 | buswidth = 8; | ||
4866 | outSISIDXREG(SISSR, 0x13, 0xb1); | ||
4867 | outSISIDXREG(SISSR, 0x14, 0x30); | ||
4868 | sisfb_post_xgi_delay(ivideo, 1); | ||
4869 | sr14 = 0x00; | ||
4870 | if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize)) | ||
4871 | goto bail_out; | ||
4872 | else | ||
4873 | outSISIDXREG(SISSR, 0x13, 0x31); | ||
4874 | } | ||
4875 | |||
4876 | } else { /* XGI_40 */ | ||
4877 | |||
4878 | inSISIDXREG(SISCR, 0x97, reg); | ||
4879 | if(!(reg & 0x10)) { | ||
4880 | inSISIDXREG(SISSR, 0x39, reg); | ||
4881 | reg >>= 1; | ||
4882 | } | ||
4883 | |||
4884 | if(reg & 0x01) { /* DDRII */ | ||
4885 | buswidth = 32; | ||
4886 | if(ivideo->revision_id == 2) { | ||
4887 | channelab = 2; | ||
4888 | outSISIDXREG(SISSR, 0x13, 0xa1); | ||
4889 | outSISIDXREG(SISSR, 0x14, 0x44); | ||
4890 | sr14 = 0x04; | ||
4891 | sisfb_post_xgi_delay(ivideo, 1); | ||
4892 | if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) | ||
4893 | goto bail_out; | ||
4894 | |||
4895 | outSISIDXREG(SISSR, 0x13, 0x21); | ||
4896 | outSISIDXREG(SISSR, 0x14, 0x34); | ||
4897 | if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize)) | ||
4898 | goto bail_out; | ||
4899 | |||
4900 | channelab = 1; | ||
4901 | outSISIDXREG(SISSR, 0x13, 0xa1); | ||
4902 | outSISIDXREG(SISSR, 0x14, 0x40); | ||
4903 | sr14 = 0x00; | ||
4904 | if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize)) | ||
4905 | goto bail_out; | ||
4906 | |||
4907 | outSISIDXREG(SISSR, 0x13, 0x21); | ||
4908 | outSISIDXREG(SISSR, 0x14, 0x30); | ||
4909 | } else { | ||
4910 | channelab = 3; | ||
4911 | outSISIDXREG(SISSR, 0x13, 0xa1); | ||
4912 | outSISIDXREG(SISSR, 0x14, 0x4c); | ||
4913 | sr14 = 0x0c; | ||
4914 | sisfb_post_xgi_delay(ivideo, 1); | ||
4915 | if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize)) | ||
4916 | goto bail_out; | ||
4917 | |||
4918 | channelab = 2; | ||
4919 | outSISIDXREG(SISSR, 0x14, 0x48); | ||
4920 | sisfb_post_xgi_delay(ivideo, 1); | ||
4921 | sr14 = 0x08; | ||
4922 | if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) | ||
4923 | goto bail_out; | ||
4924 | |||
4925 | outSISIDXREG(SISSR, 0x13, 0x21); | ||
4926 | outSISIDXREG(SISSR, 0x14, 0x3c); | ||
4927 | sr14 = 0x0c; | ||
4928 | |||
4929 | if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) { | ||
4930 | channelab = 3; | ||
4931 | } else { | ||
4932 | channelab = 2; | ||
4933 | outSISIDXREG(SISSR, 0x14, 0x38); | ||
4934 | sr14 = 0x08; | ||
4935 | } | ||
4936 | } | ||
4937 | sisfb_post_xgi_delay(ivideo, 1); | ||
4938 | |||
4939 | } else { /* DDR */ | ||
4940 | |||
4941 | buswidth = 64; | ||
4942 | if(ivideo->revision_id == 2) { | ||
4943 | channelab = 1; | ||
4944 | outSISIDXREG(SISSR, 0x13, 0xa1); | ||
4945 | outSISIDXREG(SISSR, 0x14, 0x52); | ||
4946 | sisfb_post_xgi_delay(ivideo, 1); | ||
4947 | sr14 = 0x02; | ||
4948 | if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) | ||
4949 | goto bail_out; | ||
4950 | |||
4951 | outSISIDXREG(SISSR, 0x13, 0x21); | ||
4952 | outSISIDXREG(SISSR, 0x14, 0x42); | ||
4953 | } else { | ||
4954 | channelab = 2; | ||
4955 | outSISIDXREG(SISSR, 0x13, 0xa1); | ||
4956 | outSISIDXREG(SISSR, 0x14, 0x5a); | ||
4957 | sisfb_post_xgi_delay(ivideo, 1); | ||
4958 | sr14 = 0x0a; | ||
4959 | if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize)) | ||
4960 | goto bail_out; | ||
4961 | |||
4962 | outSISIDXREG(SISSR, 0x13, 0x21); | ||
4963 | outSISIDXREG(SISSR, 0x14, 0x4a); | ||
4964 | } | ||
4965 | sisfb_post_xgi_delay(ivideo, 1); | ||
4966 | |||
4967 | } | ||
4968 | } | ||
4969 | |||
4970 | bail_out: | ||
4971 | setSISIDXREG(SISSR, 0x14, 0xf0, sr14); | ||
4972 | sisfb_post_xgi_delay(ivideo, 1); | ||
4973 | |||
4974 | j = (ivideo->chip == XGI_20) ? 5 : 9; | ||
4975 | k = (ivideo->chip == XGI_20) ? 12 : 4; | ||
4976 | |||
4977 | for(i = 0; i < k; i++) { | ||
4978 | |||
4979 | reg = (ivideo->chip == XGI_20) ? | ||
4980 | dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4]; | ||
4981 | setSISIDXREG(SISSR, 0x13, 0x80, reg); | ||
4982 | sisfb_post_xgi_delay(ivideo, 50); | ||
4983 | |||
4984 | ranksize = (ivideo->chip == XGI_20) ? | ||
4985 | dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3]; | ||
4986 | |||
4987 | inSISIDXREG(SISSR, 0x13, reg); | ||
4988 | if(reg & 0x80) ranksize <<= 1; | ||
4989 | |||
4990 | if(ivideo->chip == XGI_20) { | ||
4991 | if(buswidth == 16) ranksize <<= 1; | ||
4992 | else if(buswidth == 32) ranksize <<= 2; | ||
4993 | } else { | ||
4994 | if(buswidth == 64) ranksize <<= 1; | ||
4995 | } | ||
4996 | |||
4997 | reg = 0; | ||
4998 | l = channelab; | ||
4999 | if(l == 3) l = 4; | ||
5000 | if((ranksize * l) <= 256) { | ||
5001 | while((ranksize >>= 1)) reg += 0x10; | ||
5002 | } | ||
5003 | |||
5004 | if(!reg) continue; | ||
5005 | |||
5006 | setSISIDXREG(SISSR, 0x14, 0x0f, (reg & 0xf0)); | ||
5007 | sisfb_post_xgi_delay(ivideo, 1); | ||
5008 | |||
5009 | if(sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize)) | ||
5010 | break; | ||
5011 | } | ||
5012 | |||
5013 | iounmap(ivideo->video_vbase); | ||
5014 | } | ||
5015 | |||
5016 | static void __devinit | ||
5017 | sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb) | ||
5018 | { | ||
5019 | u8 v1, v2, v3; | ||
5020 | int index; | ||
5021 | static const u8 cs90[8 * 3] = { | ||
5022 | 0x16, 0x01, 0x01, | ||
5023 | 0x3e, 0x03, 0x01, | ||
5024 | 0x7c, 0x08, 0x01, | ||
5025 | 0x79, 0x06, 0x01, | ||
5026 | 0x29, 0x01, 0x81, | ||
5027 | 0x5c, 0x23, 0x01, | ||
5028 | 0x5c, 0x23, 0x01, | ||
5029 | 0x5c, 0x23, 0x01 | ||
5030 | }; | ||
5031 | static const u8 csb8[8 * 3] = { | ||
5032 | 0x5c, 0x23, 0x01, | ||
5033 | 0x29, 0x01, 0x01, | ||
5034 | 0x7c, 0x08, 0x01, | ||
5035 | 0x79, 0x06, 0x01, | ||
5036 | 0x29, 0x01, 0x81, | ||
5037 | 0x5c, 0x23, 0x01, | ||
5038 | 0x5c, 0x23, 0x01, | ||
5039 | 0x5c, 0x23, 0x01 | ||
5040 | }; | ||
5041 | |||
5042 | regb = 0; /* ! */ | ||
5043 | |||
5044 | index = regb * 3; | ||
5045 | v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2]; | ||
5046 | if(ivideo->haveXGIROM) { | ||
5047 | v1 = ivideo->bios_abase[0x90 + index]; | ||
5048 | v2 = ivideo->bios_abase[0x90 + index + 1]; | ||
5049 | v3 = ivideo->bios_abase[0x90 + index + 2]; | ||
5050 | } | ||
5051 | outSISIDXREG(SISSR, 0x28, v1); | ||
5052 | outSISIDXREG(SISSR, 0x29, v2); | ||
5053 | outSISIDXREG(SISSR, 0x2a, v3); | ||
5054 | sisfb_post_xgi_delay(ivideo, 0x43); | ||
5055 | sisfb_post_xgi_delay(ivideo, 0x43); | ||
5056 | sisfb_post_xgi_delay(ivideo, 0x43); | ||
5057 | index = regb * 3; | ||
5058 | v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2]; | ||
5059 | if(ivideo->haveXGIROM) { | ||
5060 | v1 = ivideo->bios_abase[0xb8 + index]; | ||
5061 | v2 = ivideo->bios_abase[0xb8 + index + 1]; | ||
5062 | v3 = ivideo->bios_abase[0xb8 + index + 2]; | ||
5063 | } | ||
5064 | outSISIDXREG(SISSR, 0x2e, v1); | ||
5065 | outSISIDXREG(SISSR, 0x2f, v2); | ||
5066 | outSISIDXREG(SISSR, 0x30, v3); | ||
5067 | sisfb_post_xgi_delay(ivideo, 0x43); | ||
5068 | sisfb_post_xgi_delay(ivideo, 0x43); | ||
5069 | sisfb_post_xgi_delay(ivideo, 0x43); | ||
5070 | } | ||
5071 | |||
5072 | static int __devinit | ||
5073 | sisfb_post_xgi(struct pci_dev *pdev) | ||
5074 | { | ||
5075 | struct sis_video_info *ivideo = pci_get_drvdata(pdev); | ||
5076 | unsigned char *bios = ivideo->bios_abase; | ||
5077 | struct pci_dev *mypdev = NULL; | ||
5078 | const u8 *ptr, *ptr2; | ||
5079 | u8 v1, v2, v3, v4, v5, reg, ramtype; | ||
5080 | u32 rega, regb, regd; | ||
5081 | int i, j, k, index; | ||
5082 | static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 }; | ||
5083 | static const u8 cs76[2] = { 0xa3, 0xfb }; | ||
5084 | static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 }; | ||
5085 | static const u8 cs158[8] = { | ||
5086 | 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
5087 | }; | ||
5088 | static const u8 cs160[8] = { | ||
5089 | 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
5090 | }; | ||
5091 | static const u8 cs168[8] = { | ||
5092 | 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
5093 | }; | ||
5094 | static const u8 cs128[3 * 8] = { | ||
5095 | 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
5096 | 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
5097 | 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
5098 | }; | ||
5099 | static const u8 cs148[2 * 8] = { | ||
5100 | 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
5101 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
5102 | }; | ||
5103 | static const u8 cs31a[8 * 4] = { | ||
5104 | 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, | ||
5105 | 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, | ||
5106 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
5107 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
5108 | }; | ||
5109 | static const u8 cs33a[8 * 4] = { | ||
5110 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
5111 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
5112 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
5113 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
5114 | }; | ||
5115 | static const u8 cs45a[8 * 2] = { | ||
5116 | 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00, | ||
5117 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
5118 | }; | ||
5119 | static const u8 cs170[7 * 8] = { | ||
5120 | 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
5121 | 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
5122 | 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
5123 | 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
5124 | 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
5125 | 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
5126 | 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
5127 | }; | ||
5128 | static const u8 cs1a8[3 * 8] = { | ||
5129 | 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
5130 | 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
5131 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
5132 | }; | ||
5133 | static const u8 cs100[2 * 8] = { | ||
5134 | 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
5135 | 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
5136 | }; | ||
5137 | |||
5138 | /* VGA enable */ | ||
5139 | reg = inSISREG(SISVGAENABLE) | 0x01; | ||
5140 | outSISREG(SISVGAENABLE, reg); | ||
5141 | |||
5142 | /* Misc */ | ||
5143 | reg = inSISREG(SISMISCR) | 0x01; | ||
5144 | outSISREG(SISMISCW, reg); | ||
5145 | |||
5146 | /* Unlock SR */ | ||
5147 | outSISIDXREG(SISSR, 0x05, 0x86); | ||
5148 | inSISIDXREG(SISSR, 0x05, reg); | ||
5149 | if(reg != 0xa1) | ||
5150 | return 0; | ||
5151 | |||
5152 | /* Clear some regs */ | ||
4385 | for(i = 0; i < 0x22; i++) { | 5153 | for(i = 0; i < 0x22; i++) { |
4386 | outSISIDXREG(SISSR,(0x06 + i),0x00); | 5154 | if(0x06 + i == 0x20) continue; |
5155 | outSISIDXREG(SISSR, 0x06 + i, 0x00); | ||
4387 | } | 5156 | } |
4388 | v1 = 0x0d; | 5157 | for(i = 0; i < 0x0b; i++) { |
4389 | if( is 330) v1 = 0x0b; | 5158 | outSISIDXREG(SISSR, 0x31 + i, 0x00); |
4390 | for(i = 0; i < v1; i++) { | ||
4391 | outSISIDXREG(SISSR,(0x31 + i),0x00); | ||
4392 | } | 5159 | } |
4393 | for(i = 0; i < 0x10; i++) { | 5160 | for(i = 0; i < 0x10; i++) { |
4394 | outSISIDXREG(SISCR,(0x30 + i),0x00); | 5161 | outSISIDXREG(SISCR, 0x30 + i, 0x00); |
4395 | } | ||
4396 | |||
4397 | /* Reset clocks */ | ||
4398 | reg = inSISREG(SISMISCR); | ||
4399 | outSISIDXREG(SISSR,0x28,0x81); | ||
4400 | outSISIDXREG(SISSR,0x2A,0x00); | ||
4401 | outSISIDXREG(SISSR,0x29,0xE1); | ||
4402 | outSISREG(SISMISCW,(reg | 0x0c)); | ||
4403 | outSISIDXREG(SISSR,0x2B,0x81); | ||
4404 | outSISIDXREG(SISSR,0x2D,0x00); | ||
4405 | outSISIDXREG(SISSR,0x2C,0xE1); | ||
4406 | outSISIDXREG(SISSR,0x2E,0x81); | ||
4407 | outSISIDXREG(SISSR,0x30,0x00); | ||
4408 | outSISIDXREG(SISSR,0x2F,0xE1); | ||
4409 | SiS_DDC2Delay(....); | ||
4410 | outSISREG(SISMISCW,reg); | ||
4411 | |||
4412 | /* Get memory type */ | ||
4413 | if(ivideo->sishw_ext.UseROM) { | ||
4414 | if(ivideo->sishw_ext.pjVirtualRomBase[0x52] & 0x80)) { | ||
4415 | memtype = ivideo->sishw_ext.pjVirtualRomBase[0x52]; | ||
4416 | } else { | ||
4417 | inSISIDXREG(SISSR,0x3a,memtype); | ||
4418 | } | ||
4419 | memtype &= 0x03; | ||
4420 | if( is 330 ) { | ||
4421 | if(memtype <= 1) memtype = 0; | ||
4422 | else { | ||
4423 | inSISIDXREG(SISCR,0x5F,reg); | ||
4424 | reg &= 0x30; | ||
4425 | switch(reg) { | ||
4426 | case 0x00: memtype = 1; break; | ||
4427 | case 0x10: memtype = 3; break; | ||
4428 | case 0x20: memtype = 3; break; | ||
4429 | default: memtype = 2; | ||
4430 | } | ||
4431 | } | ||
4432 | } | ||
4433 | } | 5162 | } |
4434 | 5163 | ||
4435 | /* Set clocks */ | 5164 | ptr = cs78; |
4436 | v1 = 0x3b; v2 = 0x22; v3 = 0x01; /* Assume 143Mhz MCLK */ | 5165 | if(ivideo->haveXGIROM) { |
4437 | v4 = 0x5c; v5 = 0x23; v6 = 0x01; /* Assume 166Mhz ECLK */ | 5166 | ptr = (const u8 *)&bios[0x78]; |
4438 | if(ivideo->sishw_ext.UseROM) { | 5167 | } |
4439 | index = memtype * 5; | 5168 | for(i = 0; i < 3; i++) { |
4440 | rindex = index + 0x54; | 5169 | outSISIDXREG(SISSR, 0x23 + i, ptr[i]); |
4441 | v1 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; | 5170 | } |
4442 | v2 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; | 5171 | |
4443 | v3 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; | 5172 | ptr = cs76; |
4444 | rindex = index + 0x68; | 5173 | if(ivideo->haveXGIROM) { |
4445 | v4 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; | 5174 | ptr = (const u8 *)&bios[0x76]; |
4446 | v5 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; | 5175 | } |
4447 | v6 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; | 5176 | for(i = 0; i < 2; i++) { |
4448 | } | 5177 | outSISIDXREG(SISSR, 0x21 + i, ptr[i]); |
4449 | outSISIDXREG(SISSR,0x28,v1); | 5178 | } |
4450 | outSISIDXREG(SISSR,0x29,v2); | 5179 | |
4451 | outSISIDXREG(SISSR,0x2a,v3); | 5180 | v1 = 0x18; v2 = 0x00; |
4452 | if( is 330 ) { | 5181 | if(ivideo->haveXGIROM) { |
4453 | inSISIDXREG(SISSR,0x3a,reg); | 5182 | v1 = bios[0x74]; |
4454 | reg &= 0x03; | 5183 | v2 = bios[0x75]; |
4455 | if(reg >= 2) { | 5184 | } |
4456 | ... | 5185 | outSISIDXREG(SISSR, 0x07, v1); |
4457 | } | 5186 | outSISIDXREG(SISSR, 0x11, 0x0f); |
5187 | outSISIDXREG(SISSR, 0x1f, v2); | ||
5188 | /* PCI linear mode, RelIO enabled, A0000 decoding disabled */ | ||
5189 | outSISIDXREG(SISSR, 0x20, 0x80 | 0x20 | 0x04); | ||
5190 | outSISIDXREG(SISSR, 0x27, 0x74); | ||
5191 | |||
5192 | ptr = cs7b; | ||
5193 | if(ivideo->haveXGIROM) { | ||
5194 | ptr = (const u8 *)&bios[0x7b]; | ||
5195 | } | ||
5196 | for(i = 0; i < 3; i++) { | ||
5197 | outSISIDXREG(SISSR, 0x31 + i, ptr[i]); | ||
4458 | } | 5198 | } |
4459 | outSISIDXREG(SISSR,0x2e,v4); | ||
4460 | outSISIDXREG(SISSR,0x2f,v5); | ||
4461 | outSISIDXREG(SISSR,0x30,v6); | ||
4462 | |||
4463 | /* End of comp with 330 */ | ||
4464 | |||
4465 | v1 = 0x18; | ||
4466 | if(ivideo->sishw_ext.UseROM) v1 = ivideo->sishw_ext.pjVirtualRomBase[0x7c]; | ||
4467 | outSISIDXREG(SISSR,0x07,v1); | ||
4468 | outSISIDXREG(SISSR,0x11,0x0f); | ||
4469 | |||
4470 | v1 = 0x00; v2 = 0x0f; v3 = 0xba; v4 = 0xa9; | ||
4471 | v5 = 0xa0; v6 = 0x00; v7 = 0x30; | ||
4472 | if(ivideo->sishw_ext.UseROM) { | ||
4473 | index = memtype + 0x7d; | ||
4474 | v1 = ivideo->sishw_ext.pjVirtualRomBase[index]; | ||
4475 | v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4]; | ||
4476 | v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8]; | ||
4477 | v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12]; | ||
4478 | v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16]; | ||
4479 | v6 = ivideo->sishw_ext.pjVirtualRomBase[index + 20]; | ||
4480 | v7 = ivideo->sishw_ext.pjVirtualRomBase[index + 24]; | ||
4481 | } | ||
4482 | outSISIDXREG(SISSR,0x15,v1); /* Ram type (assuming 0, BIOS 0x7d step 4) */ | ||
4483 | outSISIDXREG(SISSR,0x16,v2); | ||
4484 | outSISIDXREG(SISSR,0x17,v3); | ||
4485 | outSISIDXREG(SISSR,0x18,v4); | ||
4486 | outSISIDXREG(SISSR,0x19,v5); | ||
4487 | outSISIDXREG(SISSR,0x1a,v6); | ||
4488 | outSISIDXREG(SISSR,0x1b,v7); | ||
4489 | outSISIDXREG(SISSR,0x1c,v8); /* ---- */ | ||
4490 | |||
4491 | v1 = 0x77; v2 = 0x77; v3 = 0x00; v4 = 0x5b; v5 = 0x00; | ||
4492 | if(ivideo->sishw_ext.UseROM) { | ||
4493 | index = memtype + 0xa2; | ||
4494 | v1 = ivideo->sishw_ext.pjVirtualRomBase[index]; | ||
4495 | v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4]; | ||
4496 | v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8]; | ||
4497 | v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12]; | ||
4498 | v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16]; | ||
4499 | } | ||
4500 | outSISIDXREG(SISCR,0x40,v1); | ||
4501 | outSISIDXREG(SISCR,0x41,v2); | ||
4502 | outSISIDXREG(SISCR,0x42,v3); | ||
4503 | outSISIDXREG(SISCR,0x43,v4); | ||
4504 | outSISIDXREG(SISCR,0x44,v5); | ||
4505 | |||
4506 | if( is 330 ) { | ||
4507 | |||
4508 | v1 = 0x; | ||
4509 | if(ivideo->sishw_ext.UseROM) { | ||
4510 | v1 = ivideo->sishw_ext.pjVirtualRomBase[0xBA]; | ||
4511 | } | ||
4512 | outSISIDXREG(SISCR,0x59,v1); | ||
4513 | |||
4514 | v1 = 0x; v2 = 0x; v3 = 0x; v4 = 0x; | ||
4515 | v5 = 0x; v6 = 0x; v7 = 0x; v8 = 0x; | ||
4516 | if(ivideo->sishw_ext.UseROM) { | ||
4517 | index = memtype + 0xbe; | ||
4518 | v1 = ivideo->sishw_ext.pjVirtualRomBase[index]; | ||
4519 | v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4]; | ||
4520 | v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8]; | ||
4521 | v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12]; | ||
4522 | v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16]; | ||
4523 | v6 = ivideo->sishw_ext.pjVirtualRomBase[index + 20]; | ||
4524 | v7 = ivideo->sishw_ext.pjVirtualRomBase[index + 24]; | ||
4525 | v8 = ivideo->sishw_ext.pjVirtualRomBase[index + 28]; | ||
4526 | } | ||
4527 | outSISIDXREG(SISCR,0x68,v1); | ||
4528 | outSISIDXREG(SISCR,0x69,v2); | ||
4529 | outSISIDXREG(SISCR,0x6a,v3); | ||
4530 | outSISIDXREG(SISCR,0x6b,v4); | ||
4531 | outSISIDXREG(SISCR,0x6c,v5); | ||
4532 | outSISIDXREG(SISCR,0x6d,v6); | ||
4533 | outSISIDXREG(SISCR,0x6e,v7); | ||
4534 | outSISIDXREG(SISCR,0x6f,v8); | ||
4535 | |||
4536 | v1 = 0x20; | ||
4537 | inSISIDXREG(SISSR,0x3b,reg); | ||
4538 | |||
4539 | if(!(reg & 0x04)) { | ||
4540 | inSISIDXREG(SISCR,0x5F,reg); | ||
4541 | reg &= 0x30; | ||
4542 | if(reg) v1 = 0x23; | ||
4543 | } | ||
4544 | outSISIDXREG(SISCR,0x48,v1); | ||
4545 | outSISIDXREG(SISCR,0x4c,0x20); | ||
4546 | |||
4547 | xx= xxx(); | ||
4548 | if(xx >= 1) { | ||
4549 | v1 = 0x; | ||
4550 | if(ivideo->sishw_ext.UseROM) { | ||
4551 | v1 = ivideo->sishw_ext.pjVirtualRomBase[0xBA]; | ||
4552 | } | ||
4553 | outSISIDXREG(SISCR,0x59,v1); | ||
4554 | } | ||
4555 | 5199 | ||
5200 | if(ivideo->chip == XGI_40) { | ||
5201 | if(ivideo->revision_id == 2) { | ||
5202 | setSISIDXREG(SISSR, 0x3b, 0x3f, 0xc0); | ||
5203 | } | ||
5204 | outSISIDXREG(SISCR, 0x7d, 0xfe); | ||
5205 | outSISIDXREG(SISCR, 0x7e, 0x0f); | ||
5206 | } | ||
5207 | if(ivideo->revision_id == 0) { /* 40 *and* 20? */ | ||
5208 | andSISIDXREG(SISCR, 0x58, 0xd7); | ||
5209 | inSISIDXREG(SISCR, 0xcb, reg); | ||
5210 | if(reg & 0x20) { | ||
5211 | setSISIDXREG(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */ | ||
5212 | } | ||
5213 | } | ||
4556 | 5214 | ||
5215 | reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00; | ||
5216 | setSISIDXREG(SISCR, 0x38, 0x1f, reg); | ||
4557 | 5217 | ||
5218 | if(ivideo->chip == XGI_20) { | ||
5219 | outSISIDXREG(SISSR, 0x36, 0x70); | ||
4558 | } else { | 5220 | } else { |
5221 | outSISIDXREG(SISVID, 0x00, 0x86); | ||
5222 | outSISIDXREG(SISVID, 0x32, 0x00); | ||
5223 | outSISIDXREG(SISVID, 0x30, 0x00); | ||
5224 | outSISIDXREG(SISVID, 0x32, 0x01); | ||
5225 | outSISIDXREG(SISVID, 0x30, 0x00); | ||
5226 | andSISIDXREG(SISVID, 0x2f, 0xdf); | ||
5227 | andSISIDXREG(SISCAP, 0x00, 0x3f); | ||
5228 | |||
5229 | outSISIDXREG(SISPART1, 0x2f, 0x01); | ||
5230 | outSISIDXREG(SISPART1, 0x00, 0x00); | ||
5231 | outSISIDXREG(SISPART1, 0x02, bios[0x7e]); | ||
5232 | outSISIDXREG(SISPART1, 0x2e, 0x08); | ||
5233 | andSISIDXREG(SISPART1, 0x35, 0x7f); | ||
5234 | andSISIDXREG(SISPART1, 0x50, 0xfe); | ||
5235 | |||
5236 | inSISIDXREG(SISPART4, 0x00, reg); | ||
5237 | if(reg == 1 || reg == 2) { | ||
5238 | outSISIDXREG(SISPART2, 0x00, 0x1c); | ||
5239 | outSISIDXREG(SISPART4, 0x0d, bios[0x7f]); | ||
5240 | outSISIDXREG(SISPART4, 0x0e, bios[0x80]); | ||
5241 | outSISIDXREG(SISPART4, 0x10, bios[0x81]); | ||
5242 | andSISIDXREG(SISPART4, 0x0f, 0x3f); | ||
5243 | |||
5244 | inSISIDXREG(SISPART4, 0x01, reg); | ||
5245 | if((reg & 0xf0) >= 0xb0) { | ||
5246 | inSISIDXREG(SISPART4, 0x23, reg); | ||
5247 | if(reg & 0x20) reg |= 0x40; | ||
5248 | outSISIDXREG(SISPART4, 0x23, reg); | ||
5249 | reg = (reg & 0x20) ? 0x02 : 0x00; | ||
5250 | setSISIDXREG(SISPART1, 0x1e, 0xfd, reg); | ||
5251 | } | ||
5252 | } | ||
4559 | 5253 | ||
4560 | outSISIDXREG(SISCR,0x48,0x23); | 5254 | v1 = bios[0x77]; |
5255 | |||
5256 | inSISIDXREG(SISSR, 0x3b, reg); | ||
5257 | if(reg & 0x02) { | ||
5258 | inSISIDXREG(SISSR, 0x3a, reg); | ||
5259 | v2 = (reg & 0x30) >> 3; | ||
5260 | if(!(v2 & 0x04)) v2 ^= 0x02; | ||
5261 | inSISIDXREG(SISSR, 0x39, reg); | ||
5262 | if(reg & 0x80) v2 |= 0x80; | ||
5263 | v2 |= 0x01; | ||
5264 | |||
5265 | if((mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0730, NULL))) { | ||
5266 | SIS_PCI_PUT_DEVICE(mypdev); | ||
5267 | if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4)) | ||
5268 | v2 &= 0xf9; | ||
5269 | v2 |= 0x08; | ||
5270 | v1 &= 0xfe; | ||
5271 | } else { | ||
5272 | mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0735, NULL); | ||
5273 | if(!mypdev) | ||
5274 | mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0645, NULL); | ||
5275 | if(!mypdev) | ||
5276 | mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0650, NULL); | ||
5277 | if(mypdev) { | ||
5278 | pci_read_config_dword(mypdev, 0x94, ®d); | ||
5279 | regd &= 0xfffffeff; | ||
5280 | pci_write_config_dword(mypdev, 0x94, regd); | ||
5281 | v1 &= 0xfe; | ||
5282 | SIS_PCI_PUT_DEVICE(mypdev); | ||
5283 | } else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) { | ||
5284 | v1 &= 0xfe; | ||
5285 | } else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) || | ||
5286 | sisfb_find_host_bridge(ivideo, pdev, 0x1022) || | ||
5287 | sisfb_find_host_bridge(ivideo, pdev, 0x700e) || | ||
5288 | sisfb_find_host_bridge(ivideo, pdev, 0x10de)) { | ||
5289 | if((v2 & 0x06) == 4) | ||
5290 | v2 ^= 0x06; | ||
5291 | v2 |= 0x08; | ||
5292 | } | ||
5293 | } | ||
5294 | setSISIDXREG(SISCR, 0x5f, 0xf0, v2); | ||
5295 | } | ||
5296 | outSISIDXREG(SISSR, 0x22, v1); | ||
5297 | |||
5298 | if(ivideo->revision_id == 2) { | ||
5299 | inSISIDXREG(SISSR, 0x3b, v1); | ||
5300 | inSISIDXREG(SISSR, 0x3a, v2); | ||
5301 | regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8); | ||
5302 | if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) ) | ||
5303 | setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01); | ||
5304 | |||
5305 | if((mypdev = SIS_PCI_GET_DEVICE(0x10de, 0x01e0, NULL))) { | ||
5306 | /* TODO: set CR5f &0xf1 | 0x01 for version 6570 | ||
5307 | * of nforce 2 ROM | ||
5308 | */ | ||
5309 | if(0) | ||
5310 | setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01); | ||
5311 | SIS_PCI_PUT_DEVICE(mypdev); | ||
5312 | } | ||
5313 | } | ||
4561 | 5314 | ||
4562 | andSISIDXREG(SISSR,0x16,0x0f); | 5315 | v1 = 0x30; |
4563 | if(memtype <= 1) { | 5316 | inSISIDXREG(SISSR, 0x3b, reg); |
4564 | orSISIDXREG(SISSR,0x16,0x80); | 5317 | inSISIDXREG(SISCR, 0x5f, v2); |
4565 | } else { | 5318 | if((!(reg & 0x02)) && (v2 & 0x0e)) |
4566 | v1 = 0x0f; | 5319 | v1 |= 0x08; |
4567 | if(ivideo->sishw_ext.UseROM) { | 5320 | outSISIDXREG(SISSR, 0x27, v1); |
4568 | v1 = ivideo->sishw_ext.pjVirtualRomBase[0x81 + memtype]; | 5321 | |
4569 | } | 5322 | if(bios[0x64] & 0x01) { |
4570 | if(!(v1 & 0x10)) v2 = 0xc0; | 5323 | setSISIDXREG(SISCR, 0x5f, 0xf0, bios[0x64]); |
4571 | else v2 = 0xd0; | 5324 | } |
4572 | orSISIDXREG(SISSR,0x16,v2); | ||
4573 | andSISIDXREG(SISSR,0x16,0x0f); | ||
4574 | if(!(v1 & 0x10)) v2 = 0x80; | ||
4575 | else v2 = 0xA0; | ||
4576 | orSISIDXREG(SISSR,0x16,v2); | ||
4577 | } | ||
4578 | |||
4579 | if(memtype >= 2) { | ||
4580 | const u8 sr3cseq1[] = { 0xc0,0xe0,0xf0,0xe0,0xf0,0xa0,0xb0,0xa0,0xb0,0x90,0xd0 }; | ||
4581 | const u8 sr3cseq2[] = { 0xc0,0xa0,0xb0,0xa0,0xb0,0xe0,0xf0,0xa0,0xb0,0x90,0xd0 }; | ||
4582 | for(i = 0; i < 11; i++) { | ||
4583 | outSISIDXREG(SISSR,0x3c,sr3cseq1[i]); | ||
4584 | } | ||
4585 | outSISIDXREG(SISSR,0x3d,0x00); | ||
4586 | outSISIDXREG(SISSR,0x3d,0x04); | ||
4587 | SiS_DDC2Delay(0x200); | ||
4588 | v1 = inSISIDXREG(SISCR,0xEC); | ||
4589 | v2 = inSISIDXREG(SISCR,0xED); | ||
4590 | reg1_32 = (v2 << 8) | v1; | ||
4591 | outSISIDXREG(SISSR,0x3D,0x00); | ||
4592 | for(i = 0; i < 11; i++) { | ||
4593 | outSISIDXREG(SISSR,0x3c,sr3cseq2[i]); | ||
4594 | } | ||
4595 | outSISIDXREG(SISSR,0x3d,0x00); | ||
4596 | outSISIDXREG(SISSR,0x3d,0x04); | ||
4597 | SiS_DDC2Delay(0x200); | ||
4598 | v1 = inSISIDXREG(SISCR,0xEC); | ||
4599 | v2 = inSISIDXREG(SISCR,0xED); | ||
4600 | reg2_32 = (v2 << 8) | v1; | ||
4601 | outSISIDXREG(SISSR,0x3D,0x00); | ||
4602 | reg3_32 = reg2_32 << 1; | ||
4603 | reg2_32 >>= 1; | ||
4604 | reg3_32 += reg2_32; | ||
4605 | v1 = 0x40; | ||
4606 | if(reg3_32 > reg1_32) v1 = 0x10; | ||
4607 | outSISIDXREG(SISCR,0x59,v1); | ||
4608 | } | ||
4609 | 5325 | ||
5326 | v1 = bios[0x4f7]; | ||
5327 | pci_read_config_dword(pdev, 0x50, ®d); | ||
5328 | regd = (regd >> 20) & 0x0f; | ||
5329 | if(regd == 1) { | ||
5330 | v1 &= 0xfc; | ||
5331 | orSISIDXREG(SISCR, 0x5f, 0x08); | ||
5332 | } | ||
5333 | outSISIDXREG(SISCR, 0x48, v1); | ||
5334 | |||
5335 | setSISIDXREG(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb); | ||
5336 | setSISIDXREG(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f); | ||
5337 | setSISIDXREG(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f); | ||
5338 | setSISIDXREG(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7); | ||
5339 | setSISIDXREG(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f); | ||
5340 | outSISIDXREG(SISCR, 0x70, bios[0x4fc]); | ||
5341 | setSISIDXREG(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f); | ||
5342 | outSISIDXREG(SISCR, 0x74, 0xd0); | ||
5343 | setSISIDXREG(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30); | ||
5344 | setSISIDXREG(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f); | ||
5345 | setSISIDXREG(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f); | ||
5346 | v1 = bios[0x501]; | ||
5347 | if((mypdev = SIS_PCI_GET_DEVICE(0x8086, 0x2530, NULL))) { | ||
5348 | v1 = 0xf0; | ||
5349 | SIS_PCI_PUT_DEVICE(mypdev); | ||
5350 | } | ||
5351 | outSISIDXREG(SISCR, 0x77, v1); | ||
4610 | } | 5352 | } |
4611 | 5353 | ||
4612 | v1 = 0x00; | 5354 | /* RAM type */ |
4613 | if(ivideo->sishw_ext.UseROM) { | 5355 | |
4614 | v1 = ivideo->sishw_ext.pjVirtualRomBase[0x99]; | 5356 | regb = 0; /* ! */ |
5357 | |||
5358 | v1 = 0xff; | ||
5359 | if(ivideo->haveXGIROM) { | ||
5360 | v1 = bios[0x140 + regb]; | ||
4615 | } | 5361 | } |
4616 | outSISIDXREG(SISSR,0x1f,v1); | 5362 | outSISIDXREG(SISCR, 0x6d, v1); |
4617 | 5363 | ||
4618 | outSISIDXREG(SISSR,0x20,0x20); | 5364 | ptr = cs128; |
5365 | if(ivideo->haveXGIROM) { | ||
5366 | ptr = (const u8 *)&bios[0x128]; | ||
5367 | } | ||
5368 | for(i = 0, j = 0; i < 3; i++, j += 8) { | ||
5369 | outSISIDXREG(SISCR, 0x68 + i, ptr[j + regb]); | ||
5370 | } | ||
4619 | 5371 | ||
4620 | v1 = 0xf6; v2 = 0x0d; v3 = 0x33; | 5372 | ptr = cs31a; |
4621 | if(ivideo->sishw_ext.UseROM) { | 5373 | ptr2 = cs33a; |
4622 | v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9c]; | 5374 | if(ivideo->haveXGIROM) { |
4623 | v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9d]; | 5375 | index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6; |
4624 | v3 = ivideo->sishw_ext.pjVirtualRomBase[0x9e]; | 5376 | ptr = (const u8 *)&bios[index]; |
5377 | ptr2 = (const u8 *)&bios[index + 0x20]; | ||
5378 | } | ||
5379 | for(i = 0; i < 2; i++) { | ||
5380 | if(i == 0) { | ||
5381 | regd = le32_to_cpu(((u32 *)ptr)[regb]); | ||
5382 | rega = 0x6b; | ||
5383 | } else { | ||
5384 | regd = le32_to_cpu(((u32 *)ptr2)[regb]); | ||
5385 | rega = 0x6e; | ||
5386 | } | ||
5387 | reg = 0x00; | ||
5388 | for(j = 0; j < 16; j++) { | ||
5389 | reg &= 0xf3; | ||
5390 | if(regd & 0x01) reg |= 0x04; | ||
5391 | if(regd & 0x02) reg |= 0x08; | ||
5392 | regd >>= 2; | ||
5393 | outSISIDXREG(SISCR, rega, reg); | ||
5394 | inSISIDXREG(SISCR, rega, reg); | ||
5395 | inSISIDXREG(SISCR, rega, reg); | ||
5396 | reg += 0x10; | ||
5397 | } | ||
4625 | } | 5398 | } |
4626 | outSISIDXREG(SISSR,0x23,v1); | ||
4627 | outSISIDXREG(SISSR,0x24,v2); | ||
4628 | outSISIDXREG(SISSR,0x25,v3); | ||
4629 | 5399 | ||
4630 | outSISIDXREG(SISSR,0x21,0x84); | 5400 | andSISIDXREG(SISCR, 0x6e, 0xfc); |
4631 | outSISIDXREG(SISSR,0x22,0x00); | ||
4632 | outSISIDXREG(SISSR,0x27,0x1f); | ||
4633 | 5401 | ||
4634 | v1 = 0x00; v2 = 0x00; | 5402 | ptr = NULL; |
4635 | if(ivideo->sishw_ext.UseROM) { | 5403 | if(ivideo->haveXGIROM) { |
4636 | v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9F]; | 5404 | index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6; |
4637 | v2 = ivideo->sishw_ext.pjVirtualRomBase[0xA1]; | 5405 | ptr = (const u8 *)&bios[index]; |
4638 | } | 5406 | } |
4639 | outSISIDXREG(SISSR,0x31,v1); | 5407 | for(i = 0; i < 4; i++) { |
4640 | outSISIDXREG(SISSR,0x33,v2); | 5408 | setSISIDXREG(SISCR, 0x6e, 0xfc, i); |
4641 | 5409 | reg = 0x00; | |
4642 | v1 = 0x11; | 5410 | for(j = 0; j < 2; j++) { |
4643 | if(ivideo->sishw_ext.UseROM) { | 5411 | regd = 0; |
4644 | v1 = ivideo->sishw_ext.pjVirtualRomBase[0xA0]; | 5412 | if(ptr) { |
4645 | } | 5413 | regd = le32_to_cpu(((u32 *)ptr)[regb * 8]); |
4646 | v2 = inSISIDXREG(SISPART4,0x00); | 5414 | ptr += 4; |
4647 | if((v2 != 1) && (v2 != 2)) v1 &= 0xef; | 5415 | } |
4648 | outSISIDXREG(SISSR,0x32,v1); | 5416 | /* reg = 0x00; */ |
4649 | 5417 | for(k = 0; k < 16; k++) { | |
4650 | /* AGP */ | 5418 | reg &= 0xfc; |
4651 | pci_read_config_long(pdev, 0x50, ®1_32); | 5419 | if(regd & 0x01) reg |= 0x01; |
4652 | reg1_32 >>= 20; | 5420 | if(regd & 0x02) reg |= 0x02; |
4653 | reg1_32 &= 0x0f; | 5421 | regd >>= 2; |
4654 | if(reg1_32 == 1) { | 5422 | outSISIDXREG(SISCR, 0x6f, reg); |
4655 | v1 = 0xAA; v2 = 0x33; | 5423 | inSISIDXREG(SISCR, 0x6f, reg); |
4656 | if(ivideo->sishw_ext.UseROM) { | 5424 | inSISIDXREG(SISCR, 0x6f, reg); |
4657 | v1 = ivideo->sishw_ext.pjVirtualRomBase[0xF7]; | 5425 | reg += 0x08; |
4658 | v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9E]; | 5426 | } |
4659 | } | 5427 | } |
4660 | } else { | ||
4661 | v1 = 0x88; v2 = 0x03; | ||
4662 | if(ivideo->sishw_ext.UseROM) { | ||
4663 | v1 = ivideo->sishw_ext.pjVirtualRomBase[0xF8]; | ||
4664 | v2 = ivideo->sishw_ext.pjVirtualRomBase[0xF6]; | ||
4665 | } | ||
4666 | } | 5428 | } |
4667 | outSISIDXREG(SISCR,0x49,v1); | ||
4668 | outSISIDXREG(SISSR,0x25,v2); | ||
4669 | 5429 | ||
4670 | v1 = inSISIDXREG(SISPART4,0x00); | 5430 | ptr = cs148; |
4671 | if((v1 == 1) || (v1 == 2)) { | 5431 | if(ivideo->haveXGIROM) { |
4672 | orSISIDXREG(SISPART1,0x2F,0x01); /* Unlock CRT2 */ | 5432 | ptr = (const u8 *)&bios[0x148]; |
4673 | outSISIDXREG(SISPART1,0x00,0x00); | 5433 | } |
4674 | v1 = 0x00; | 5434 | for(i = 0, j = 0; i < 2; i++, j += 8) { |
4675 | if(ivideo->sishw_ext.UseROM) { | 5435 | outSISIDXREG(SISCR, 0x80 + i, ptr[j + regb]); |
4676 | v1 = ivideo->sishw_ext.pjVirtualRomBase[0xb6]; | ||
4677 | } | ||
4678 | outSISIDXREG(SISPART1,0x02,v1); | ||
4679 | outSISIDXREG(SISPART1,0x2E,0x08); | ||
4680 | outSISIDXREG(SISPART2,0x00,0x1c); | ||
4681 | v1 = 0x40; v2 = 0x00; v3 = 0x80; | ||
4682 | if(ivideo->sishw_ext.UseROM) { | ||
4683 | v1 = ivideo->sishw_ext.pjVirtualRomBase[0xb7]; | ||
4684 | v2 = ivideo->sishw_ext.pjVirtualRomBase[0xb8]; | ||
4685 | v3 = ivideo->sishw_ext.pjVirtualRomBase[0xbb]; | ||
4686 | } | ||
4687 | outSISIDXREG(SISPART4,0x0d,v1); | ||
4688 | outSISIDXREG(SISPART4,0x0e,v2); | ||
4689 | outSISIDXREG(SISPART4,0x10,v3); | ||
4690 | outSISIDXREG(SISPART4,0x0F,0x3F); | ||
4691 | |||
4692 | inSISIDXREG(SISPART4,0x01,reg); | ||
4693 | if(reg >= 0xb0) { | ||
4694 | inSISIDXREG(SISPART4,0x23,reg); | ||
4695 | reg &= 0x20; | ||
4696 | reg <<= 1; | ||
4697 | outSISIDXREG(SISPART4,0x23,reg); | ||
4698 | } | ||
4699 | } | 5436 | } |
4700 | outSISIDXREG(SISCR,0x37,0x02); /* Why? */ | ||
4701 | |||
4702 | outSISIDXREG(SISCR,0x83,0x00); | ||
4703 | outSISIDXREG(SISCR,0x90,0x00); | ||
4704 | andSISIDXREG(SISSR,0x5B,0xDF); | ||
4705 | outSISIDXREG(SISVID,0x00,0x86); | ||
4706 | outSISIDXREG(SISVID,0x32,0x00); | ||
4707 | outSISIDXREG(SISVID,0x30,0x00); | ||
4708 | outSISIDXREG(SISVID,0x32,0x01); | ||
4709 | outSISIDXREG(SISVID,0x30,0x00); | ||
4710 | orSISIDXREG(SISCR,0x63,0x80); | ||
4711 | /* End of Init1 */ | ||
4712 | |||
4713 | /* Set Mode 0x2e */ | ||
4714 | |||
4715 | /* Ramsize */ | ||
4716 | orSISIDXREG(SISSR,0x16,0x0f); | ||
4717 | orSISIDXREG(SISSR,0x18,0xA9); | ||
4718 | orSISIDXREG(SISSR,0x19,0xA0); | ||
4719 | orSISIDXREG(SISSR,0x1B,0x30); | ||
4720 | andSISIDXREG(SISSR,0x17,0xF8); | ||
4721 | orSISIDXREG(SISSR,0x19,0x03); | ||
4722 | andSIDIDXREG(SISSR,0x13,0x00); | ||
4723 | 5437 | ||
4724 | /* Need to map max FB size for finding out about RAM size */ | 5438 | andSISIDXREG(SISCR, 0x89, 0x8f); |
4725 | ivideo->video_vbase = ioremap(ivideo->video_base, 0x4000000); | ||
4726 | if(ivideo->video_vbase) { | ||
4727 | /* Find out about bus width */ | ||
4728 | if(memtype <= 1) { | ||
4729 | outSISIDXREG(SISSR,0x14,0x02); | ||
4730 | andSISIDXREG(SISSR,0x16,0x0F); | ||
4731 | orSISIDXREG(SISSR,0x16,0x80); | ||
4732 | 5439 | ||
4733 | ... | 5440 | ptr = cs45a; |
5441 | if(ivideo->haveXGIROM) { | ||
5442 | index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6; | ||
5443 | ptr = (const u8 *)&bios[index]; | ||
5444 | } | ||
5445 | regd = le16_to_cpu(((const u16 *)ptr)[regb]); | ||
5446 | reg = 0x80; | ||
5447 | for(i = 0; i < 5; i++) { | ||
5448 | reg &= 0xfc; | ||
5449 | if(regd & 0x01) reg |= 0x01; | ||
5450 | if(regd & 0x02) reg |= 0x02; | ||
5451 | regd >>= 2; | ||
5452 | outSISIDXREG(SISCR, 0x89, reg); | ||
5453 | inSISIDXREG(SISCR, 0x89, reg); | ||
5454 | inSISIDXREG(SISCR, 0x89, reg); | ||
5455 | reg += 0x10; | ||
5456 | } | ||
4734 | 5457 | ||
4735 | } else { | 5458 | v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13; |
5459 | if(ivideo->haveXGIROM) { | ||
5460 | v1 = bios[0x118 + regb]; | ||
5461 | v2 = bios[0xf8 + regb]; | ||
5462 | v3 = bios[0x120 + regb]; | ||
5463 | v4 = bios[0x1ca]; | ||
5464 | } | ||
5465 | outSISIDXREG(SISCR, 0x45, v1 & 0x0f); | ||
5466 | outSISIDXREG(SISCR, 0x99, (v1 >> 4) & 0x07); | ||
5467 | orSISIDXREG(SISCR, 0x40, v1 & 0x80); | ||
5468 | outSISIDXREG(SISCR, 0x41, v2); | ||
4736 | 5469 | ||
4737 | ... | 5470 | ptr = cs170; |
5471 | if(ivideo->haveXGIROM) { | ||
5472 | ptr = (const u8 *)&bios[0x170]; | ||
5473 | } | ||
5474 | for(i = 0, j = 0; i < 7; i++, j += 8) { | ||
5475 | outSISIDXREG(SISCR, 0x90 + i, ptr[j + regb]); | ||
5476 | } | ||
4738 | 5477 | ||
4739 | } | 5478 | outSISIDXREG(SISCR, 0x59, v3); |
4740 | 5479 | ||
4741 | /* Find out about size */ | 5480 | ptr = cs1a8; |
5481 | if(ivideo->haveXGIROM) { | ||
5482 | ptr = (const u8 *)&bios[0x1a8]; | ||
5483 | } | ||
5484 | for(i = 0, j = 0; i < 3; i++, j += 8) { | ||
5485 | outSISIDXREG(SISCR, 0xc3 + i, ptr[j + regb]); | ||
5486 | } | ||
4742 | 5487 | ||
5488 | ptr = cs100; | ||
5489 | if(ivideo->haveXGIROM) { | ||
5490 | ptr = (const u8 *)&bios[0x100]; | ||
5491 | } | ||
5492 | for(i = 0, j = 0; i < 2; i++, j += 8) { | ||
5493 | outSISIDXREG(SISCR, 0x8a + i, ptr[j + regb]); | ||
5494 | } | ||
4743 | 5495 | ||
4744 | iounmap(ivideo->video_vbase); | 5496 | outSISIDXREG(SISCR, 0xcf, v4); |
4745 | } else { | 5497 | |
4746 | printk(KERN_DEBUG "sisfb: Failed to map memory for size detection, assuming 8MB\n"); | 5498 | outSISIDXREG(SISCR, 0x83, 0x09); |
4747 | outSISIDXREG(SISSR,0x14,0x??); /* 8MB, 64bit default */ | 5499 | outSISIDXREG(SISCR, 0x87, 0x00); |
5500 | |||
5501 | if(ivideo->chip == XGI_40) { | ||
5502 | if( (ivideo->revision_id == 1) || | ||
5503 | (ivideo->revision_id == 2) ) { | ||
5504 | outSISIDXREG(SISCR, 0x8c, 0x87); | ||
5505 | } | ||
5506 | } | ||
5507 | |||
5508 | outSISIDXREG(SISSR, 0x17, 0x00); | ||
5509 | outSISIDXREG(SISSR, 0x1a, 0x87); | ||
5510 | |||
5511 | if(ivideo->chip == XGI_20) { | ||
5512 | outSISIDXREG(SISSR, 0x15, 0x00); | ||
5513 | outSISIDXREG(SISSR, 0x1c, 0x00); | ||
5514 | } | ||
5515 | |||
5516 | ramtype = 0x00; v1 = 0x10; | ||
5517 | if(ivideo->haveXGIROM) { | ||
5518 | ramtype = bios[0x62]; | ||
5519 | v1 = bios[0x1d2]; | ||
5520 | } | ||
5521 | if(!(ramtype & 0x80)) { | ||
5522 | if(ivideo->chip == XGI_20) { | ||
5523 | outSISIDXREG(SISCR, 0x97, v1); | ||
5524 | inSISIDXREG(SISCR, 0x97, reg); | ||
5525 | if(reg & 0x10) { | ||
5526 | ramtype = (reg & 0x01) << 1; | ||
5527 | } | ||
5528 | } else { | ||
5529 | inSISIDXREG(SISSR, 0x39, reg); | ||
5530 | ramtype = reg & 0x02; | ||
5531 | if(!(ramtype)) { | ||
5532 | inSISIDXREG(SISSR, 0x3a, reg); | ||
5533 | ramtype = (reg >> 1) & 0x01; | ||
5534 | } | ||
5535 | } | ||
5536 | } | ||
5537 | ramtype &= 0x07; | ||
5538 | |||
5539 | regb = 0; /* ! */ | ||
5540 | |||
5541 | switch(ramtype) { | ||
5542 | case 0: | ||
5543 | sisfb_post_xgi_setclocks(ivideo, regb); | ||
5544 | if((ivideo->chip == XGI_20) || | ||
5545 | (ivideo->revision_id == 1) || | ||
5546 | (ivideo->revision_id == 2)) { | ||
5547 | v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb]; | ||
5548 | if(ivideo->haveXGIROM) { | ||
5549 | v1 = bios[regb + 0x158]; | ||
5550 | v2 = bios[regb + 0x160]; | ||
5551 | v3 = bios[regb + 0x168]; | ||
5552 | } | ||
5553 | outSISIDXREG(SISCR, 0x82, v1); | ||
5554 | outSISIDXREG(SISCR, 0x85, v2); | ||
5555 | outSISIDXREG(SISCR, 0x86, v3); | ||
5556 | } else { | ||
5557 | outSISIDXREG(SISCR, 0x82, 0x88); | ||
5558 | outSISIDXREG(SISCR, 0x86, 0x00); | ||
5559 | inSISIDXREG(SISCR, 0x86, reg); | ||
5560 | outSISIDXREG(SISCR, 0x86, 0x88); | ||
5561 | inSISIDXREG(SISCR, 0x86, reg); | ||
5562 | outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]); | ||
5563 | outSISIDXREG(SISCR, 0x82, 0x77); | ||
5564 | outSISIDXREG(SISCR, 0x85, 0x00); | ||
5565 | inSISIDXREG(SISCR, 0x85, reg); | ||
5566 | outSISIDXREG(SISCR, 0x85, 0x88); | ||
5567 | inSISIDXREG(SISCR, 0x85, reg); | ||
5568 | outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]); | ||
5569 | outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]); | ||
5570 | } | ||
5571 | if(ivideo->chip == XGI_40) { | ||
5572 | outSISIDXREG(SISCR, 0x97, 0x00); | ||
5573 | } | ||
5574 | outSISIDXREG(SISCR, 0x98, 0x01); | ||
5575 | outSISIDXREG(SISCR, 0x9a, 0x02); | ||
5576 | |||
5577 | outSISIDXREG(SISSR, 0x18, 0x01); | ||
5578 | if((ivideo->chip == XGI_20) || | ||
5579 | (ivideo->revision_id == 2)) { | ||
5580 | outSISIDXREG(SISSR, 0x19, 0x40); | ||
5581 | } else { | ||
5582 | outSISIDXREG(SISSR, 0x19, 0x20); | ||
5583 | } | ||
5584 | outSISIDXREG(SISSR, 0x16, 0x00); | ||
5585 | outSISIDXREG(SISSR, 0x16, 0x80); | ||
5586 | if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) { | ||
5587 | sisfb_post_xgi_delay(ivideo, 0x43); | ||
5588 | sisfb_post_xgi_delay(ivideo, 0x43); | ||
5589 | sisfb_post_xgi_delay(ivideo, 0x43); | ||
5590 | outSISIDXREG(SISSR, 0x18, 0x00); | ||
5591 | if((ivideo->chip == XGI_20) || | ||
5592 | (ivideo->revision_id == 2)) { | ||
5593 | outSISIDXREG(SISSR, 0x19, 0x40); | ||
5594 | } else { | ||
5595 | outSISIDXREG(SISSR, 0x19, 0x20); | ||
5596 | } | ||
5597 | } else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) { | ||
5598 | /* outSISIDXREG(SISSR, 0x16, 0x0c); */ /* ? */ | ||
5599 | } | ||
5600 | outSISIDXREG(SISSR, 0x16, 0x00); | ||
5601 | outSISIDXREG(SISSR, 0x16, 0x80); | ||
5602 | sisfb_post_xgi_delay(ivideo, 4); | ||
5603 | v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83; | ||
5604 | if(ivideo->haveXGIROM) { | ||
5605 | v1 = bios[0xf0]; | ||
5606 | index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e; | ||
5607 | v2 = bios[index]; | ||
5608 | v3 = bios[index + 1]; | ||
5609 | v4 = bios[index + 2]; | ||
5610 | v5 = bios[index + 3]; | ||
5611 | } | ||
5612 | outSISIDXREG(SISSR, 0x18, v1); | ||
5613 | outSISIDXREG(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01)); | ||
5614 | outSISIDXREG(SISSR, 0x16, v2); | ||
5615 | outSISIDXREG(SISSR, 0x16, v3); | ||
5616 | sisfb_post_xgi_delay(ivideo, 0x43); | ||
5617 | outSISIDXREG(SISSR, 0x1b, 0x03); | ||
5618 | sisfb_post_xgi_delay(ivideo, 0x22); | ||
5619 | outSISIDXREG(SISSR, 0x18, v1); | ||
5620 | outSISIDXREG(SISSR, 0x19, 0x00); | ||
5621 | outSISIDXREG(SISSR, 0x16, v4); | ||
5622 | outSISIDXREG(SISSR, 0x16, v5); | ||
5623 | outSISIDXREG(SISSR, 0x1b, 0x00); | ||
5624 | break; | ||
5625 | case 1: | ||
5626 | outSISIDXREG(SISCR, 0x82, 0x77); | ||
5627 | outSISIDXREG(SISCR, 0x86, 0x00); | ||
5628 | inSISIDXREG(SISCR, 0x86, reg); | ||
5629 | outSISIDXREG(SISCR, 0x86, 0x88); | ||
5630 | inSISIDXREG(SISCR, 0x86, reg); | ||
5631 | v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb]; | ||
5632 | if(ivideo->haveXGIROM) { | ||
5633 | v1 = bios[regb + 0x168]; | ||
5634 | v2 = bios[regb + 0x160]; | ||
5635 | v3 = bios[regb + 0x158]; | ||
5636 | } | ||
5637 | outSISIDXREG(SISCR, 0x86, v1); | ||
5638 | outSISIDXREG(SISCR, 0x82, 0x77); | ||
5639 | outSISIDXREG(SISCR, 0x85, 0x00); | ||
5640 | inSISIDXREG(SISCR, 0x85, reg); | ||
5641 | outSISIDXREG(SISCR, 0x85, 0x88); | ||
5642 | inSISIDXREG(SISCR, 0x85, reg); | ||
5643 | outSISIDXREG(SISCR, 0x85, v2); | ||
5644 | outSISIDXREG(SISCR, 0x82, v3); | ||
5645 | outSISIDXREG(SISCR, 0x98, 0x01); | ||
5646 | outSISIDXREG(SISCR, 0x9a, 0x02); | ||
5647 | |||
5648 | outSISIDXREG(SISSR, 0x28, 0x64); | ||
5649 | outSISIDXREG(SISSR, 0x29, 0x63); | ||
5650 | sisfb_post_xgi_delay(ivideo, 15); | ||
5651 | outSISIDXREG(SISSR, 0x18, 0x00); | ||
5652 | outSISIDXREG(SISSR, 0x19, 0x20); | ||
5653 | outSISIDXREG(SISSR, 0x16, 0x00); | ||
5654 | outSISIDXREG(SISSR, 0x16, 0x80); | ||
5655 | outSISIDXREG(SISSR, 0x18, 0xc5); | ||
5656 | outSISIDXREG(SISSR, 0x19, 0x23); | ||
5657 | outSISIDXREG(SISSR, 0x16, 0x00); | ||
5658 | outSISIDXREG(SISSR, 0x16, 0x80); | ||
5659 | sisfb_post_xgi_delay(ivideo, 1); | ||
5660 | outSISIDXREG(SISCR, 0x97,0x11); | ||
5661 | sisfb_post_xgi_setclocks(ivideo, regb); | ||
5662 | sisfb_post_xgi_delay(ivideo, 0x46); | ||
5663 | outSISIDXREG(SISSR, 0x18, 0xc5); | ||
5664 | outSISIDXREG(SISSR, 0x19, 0x23); | ||
5665 | outSISIDXREG(SISSR, 0x16, 0x00); | ||
5666 | outSISIDXREG(SISSR, 0x16, 0x80); | ||
5667 | sisfb_post_xgi_delay(ivideo, 1); | ||
5668 | outSISIDXREG(SISSR, 0x1b, 0x04); | ||
5669 | sisfb_post_xgi_delay(ivideo, 1); | ||
5670 | outSISIDXREG(SISSR, 0x1b, 0x00); | ||
5671 | sisfb_post_xgi_delay(ivideo, 1); | ||
5672 | v1 = 0x31; | ||
5673 | if(ivideo->haveXGIROM) { | ||
5674 | v1 = bios[0xf0]; | ||
5675 | } | ||
5676 | outSISIDXREG(SISSR, 0x18, v1); | ||
5677 | outSISIDXREG(SISSR, 0x19, 0x06); | ||
5678 | outSISIDXREG(SISSR, 0x16, 0x04); | ||
5679 | outSISIDXREG(SISSR, 0x16, 0x84); | ||
5680 | sisfb_post_xgi_delay(ivideo, 1); | ||
5681 | break; | ||
5682 | default: | ||
5683 | sisfb_post_xgi_setclocks(ivideo, regb); | ||
5684 | if((ivideo->chip == XGI_40) && | ||
5685 | ((ivideo->revision_id == 1) || | ||
5686 | (ivideo->revision_id == 2))) { | ||
5687 | outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]); | ||
5688 | outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]); | ||
5689 | outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]); | ||
5690 | } else { | ||
5691 | outSISIDXREG(SISCR, 0x82, 0x88); | ||
5692 | outSISIDXREG(SISCR, 0x86, 0x00); | ||
5693 | inSISIDXREG(SISCR, 0x86, reg); | ||
5694 | outSISIDXREG(SISCR, 0x86, 0x88); | ||
5695 | outSISIDXREG(SISCR, 0x82, 0x77); | ||
5696 | outSISIDXREG(SISCR, 0x85, 0x00); | ||
5697 | inSISIDXREG(SISCR, 0x85, reg); | ||
5698 | outSISIDXREG(SISCR, 0x85, 0x88); | ||
5699 | inSISIDXREG(SISCR, 0x85, reg); | ||
5700 | v1 = cs160[regb]; v2 = cs158[regb]; | ||
5701 | if(ivideo->haveXGIROM) { | ||
5702 | v1 = bios[regb + 0x160]; | ||
5703 | v2 = bios[regb + 0x158]; | ||
5704 | } | ||
5705 | outSISIDXREG(SISCR, 0x85, v1); | ||
5706 | outSISIDXREG(SISCR, 0x82, v2); | ||
5707 | } | ||
5708 | if(ivideo->chip == XGI_40) { | ||
5709 | outSISIDXREG(SISCR, 0x97, 0x11); | ||
5710 | } | ||
5711 | if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) { | ||
5712 | outSISIDXREG(SISCR, 0x98, 0x01); | ||
5713 | } else { | ||
5714 | outSISIDXREG(SISCR, 0x98, 0x03); | ||
5715 | } | ||
5716 | outSISIDXREG(SISCR, 0x9a, 0x02); | ||
5717 | |||
5718 | if(ivideo->chip == XGI_40) { | ||
5719 | outSISIDXREG(SISSR, 0x18, 0x01); | ||
5720 | } else { | ||
5721 | outSISIDXREG(SISSR, 0x18, 0x00); | ||
5722 | } | ||
5723 | outSISIDXREG(SISSR, 0x19, 0x40); | ||
5724 | outSISIDXREG(SISSR, 0x16, 0x00); | ||
5725 | outSISIDXREG(SISSR, 0x16, 0x80); | ||
5726 | if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) { | ||
5727 | sisfb_post_xgi_delay(ivideo, 0x43); | ||
5728 | sisfb_post_xgi_delay(ivideo, 0x43); | ||
5729 | sisfb_post_xgi_delay(ivideo, 0x43); | ||
5730 | outSISIDXREG(SISSR, 0x18, 0x00); | ||
5731 | outSISIDXREG(SISSR, 0x19, 0x40); | ||
5732 | outSISIDXREG(SISSR, 0x16, 0x00); | ||
5733 | outSISIDXREG(SISSR, 0x16, 0x80); | ||
5734 | } | ||
5735 | sisfb_post_xgi_delay(ivideo, 4); | ||
5736 | v1 = 0x31; | ||
5737 | if(ivideo->haveXGIROM) { | ||
5738 | v1 = bios[0xf0]; | ||
5739 | } | ||
5740 | outSISIDXREG(SISSR, 0x18, v1); | ||
5741 | outSISIDXREG(SISSR, 0x19, 0x01); | ||
5742 | if(ivideo->chip == XGI_40) { | ||
5743 | outSISIDXREG(SISSR, 0x16, bios[0x53e]); | ||
5744 | outSISIDXREG(SISSR, 0x16, bios[0x53f]); | ||
5745 | } else { | ||
5746 | outSISIDXREG(SISSR, 0x16, 0x05); | ||
5747 | outSISIDXREG(SISSR, 0x16, 0x85); | ||
5748 | } | ||
5749 | sisfb_post_xgi_delay(ivideo, 0x43); | ||
5750 | if(ivideo->chip == XGI_40) { | ||
5751 | outSISIDXREG(SISSR, 0x1b, 0x01); | ||
5752 | } else { | ||
5753 | outSISIDXREG(SISSR, 0x1b, 0x03); | ||
5754 | } | ||
5755 | sisfb_post_xgi_delay(ivideo, 0x22); | ||
5756 | outSISIDXREG(SISSR, 0x18, v1); | ||
5757 | outSISIDXREG(SISSR, 0x19, 0x00); | ||
5758 | if(ivideo->chip == XGI_40) { | ||
5759 | outSISIDXREG(SISSR, 0x16, bios[0x540]); | ||
5760 | outSISIDXREG(SISSR, 0x16, bios[0x541]); | ||
5761 | } else { | ||
5762 | outSISIDXREG(SISSR, 0x16, 0x05); | ||
5763 | outSISIDXREG(SISSR, 0x16, 0x85); | ||
5764 | } | ||
5765 | outSISIDXREG(SISSR, 0x1b, 0x00); | ||
5766 | } | ||
5767 | |||
5768 | regb = 0; /* ! */ | ||
5769 | v1 = 0x03; | ||
5770 | if(ivideo->haveXGIROM) { | ||
5771 | v1 = bios[0x110 + regb]; | ||
5772 | } | ||
5773 | outSISIDXREG(SISSR, 0x1b, v1); | ||
5774 | |||
5775 | /* RAM size */ | ||
5776 | v1 = 0x00; v2 = 0x00; | ||
5777 | if(ivideo->haveXGIROM) { | ||
5778 | v1 = bios[0x62]; | ||
5779 | v2 = bios[0x63]; | ||
4748 | } | 5780 | } |
5781 | regb = 0; /* ! */ | ||
5782 | regd = 1 << regb; | ||
5783 | if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) { | ||
5784 | |||
5785 | outSISIDXREG(SISSR, 0x13, bios[regb + 0xe0]); | ||
5786 | outSISIDXREG(SISSR, 0x14, bios[regb + 0xe0 + 8]); | ||
5787 | |||
5788 | } else { | ||
5789 | |||
5790 | /* Set default mode, don't clear screen */ | ||
5791 | ivideo->SiS_Pr.SiS_UseOEM = FALSE; | ||
5792 | SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE); | ||
5793 | SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE); | ||
5794 | ivideo->curFSTN = ivideo->curDSTN = 0; | ||
5795 | ivideo->SiS_Pr.VideoMemorySize = 8 << 20; | ||
5796 | SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80); | ||
5797 | |||
5798 | outSISIDXREG(SISSR, 0x05, 0x86); | ||
5799 | |||
5800 | /* Disable read-cache */ | ||
5801 | andSISIDXREG(SISSR, 0x21, 0xdf); | ||
5802 | sisfb_post_xgi_ramsize(ivideo); | ||
5803 | /* Enable read-cache */ | ||
5804 | orSISIDXREG(SISSR, 0x21, 0x20); | ||
4749 | 5805 | ||
4750 | /* AGP (Missing: Checks for VIA and AMD hosts) */ | ||
4751 | v1 = 0xA5; v2 = 0xFB; | ||
4752 | if(ivideo->sishw_ext.UseROM) { | ||
4753 | v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9A]; | ||
4754 | v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9B]; | ||
4755 | } | 5806 | } |
4756 | outSISIDXREG(SISSR,0x21,v1); | ||
4757 | outSISIDXREG(SISSR,0x22,v2); | ||
4758 | 5807 | ||
5808 | #if 0 | ||
5809 | printk(KERN_DEBUG "-----------------\n"); | ||
5810 | for(i = 0; i < 0xff; i++) { | ||
5811 | inSISIDXREG(SISCR, i, reg); | ||
5812 | printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg); | ||
5813 | } | ||
5814 | for(i = 0; i < 0x40; i++) { | ||
5815 | inSISIDXREG(SISSR, i, reg); | ||
5816 | printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg); | ||
5817 | } | ||
5818 | printk(KERN_DEBUG "-----------------\n"); | ||
4759 | #endif | 5819 | #endif |
4760 | return; | 5820 | |
5821 | /* Sense CRT1 */ | ||
5822 | if(ivideo->chip == XGI_20) { | ||
5823 | orSISIDXREG(SISCR, 0x32, 0x20); | ||
5824 | } else { | ||
5825 | inSISIDXREG(SISPART4, 0x00, reg); | ||
5826 | if((reg == 1) || (reg == 2)) { | ||
5827 | sisfb_sense_crt1(ivideo); | ||
5828 | } else { | ||
5829 | orSISIDXREG(SISCR, 0x32, 0x20); | ||
5830 | } | ||
5831 | } | ||
5832 | |||
5833 | /* Set default mode, don't clear screen */ | ||
5834 | ivideo->SiS_Pr.SiS_UseOEM = FALSE; | ||
5835 | SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE); | ||
5836 | SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE); | ||
5837 | ivideo->curFSTN = ivideo->curDSTN = 0; | ||
5838 | SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80); | ||
5839 | |||
5840 | outSISIDXREG(SISSR, 0x05, 0x86); | ||
5841 | |||
5842 | /* Display off */ | ||
5843 | orSISIDXREG(SISSR, 0x01, 0x20); | ||
5844 | |||
5845 | /* Save mode number in CR34 */ | ||
5846 | outSISIDXREG(SISCR, 0x34, 0x2e); | ||
5847 | |||
5848 | /* Let everyone know what the current mode is */ | ||
5849 | ivideo->modeprechange = 0x2e; | ||
5850 | |||
5851 | if(ivideo->chip == XGI_40) { | ||
5852 | inSISIDXREG(SISCR, 0xca, reg); | ||
5853 | inSISIDXREG(SISCR, 0xcc, v1); | ||
5854 | if((reg & 0x10) && (!(v1 & 0x04))) { | ||
5855 | printk(KERN_ERR | ||
5856 | "sisfb: Please connect power to the card.\n"); | ||
5857 | return 0; | ||
5858 | } | ||
5859 | } | ||
5860 | |||
5861 | return 1; | ||
4761 | } | 5862 | } |
4762 | #endif | 5863 | #endif |
4763 | 5864 | ||
4764 | 5865 | static int __devinit | |
4765 | static int __devinit sisfb_probe(struct pci_dev *pdev, | 5866 | sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
4766 | const struct pci_device_id *ent) | ||
4767 | { | 5867 | { |
4768 | struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data]; | 5868 | struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data]; |
4769 | struct sis_video_info *ivideo = NULL; | 5869 | struct sis_video_info *ivideo = NULL; |
4770 | struct fb_info *sis_fb_info = NULL; | 5870 | struct fb_info *sis_fb_info = NULL; |
4771 | u16 reg16; | 5871 | u16 reg16; |
4772 | u8 reg; | 5872 | u8 reg; |
4773 | int sisvga_enabled = 0, i; | 5873 | int i, ret; |
4774 | 5874 | ||
4775 | if(sisfb_off) return -ENXIO; | 5875 | if(sisfb_off) |
5876 | return -ENXIO; | ||
4776 | 5877 | ||
4777 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3)) | 5878 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3)) |
4778 | sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev); | 5879 | sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev); |
4779 | if(!sis_fb_info) return -ENOMEM; | 5880 | if(!sis_fb_info) |
5881 | return -ENOMEM; | ||
4780 | #else | 5882 | #else |
4781 | sis_fb_info = kmalloc(sizeof(*sis_fb_info) + sizeof(*ivideo), GFP_KERNEL); | 5883 | sis_fb_info = kmalloc(sizeof(*sis_fb_info) + sizeof(*ivideo), GFP_KERNEL); |
4782 | if(!sis_fb_info) return -ENOMEM; | 5884 | if(!sis_fb_info) |
5885 | return -ENOMEM; | ||
4783 | memset(sis_fb_info, 0, sizeof(*sis_fb_info) + sizeof(*ivideo)); | 5886 | memset(sis_fb_info, 0, sizeof(*sis_fb_info) + sizeof(*ivideo)); |
4784 | sis_fb_info->par = ((char *)sis_fb_info + sizeof(*sis_fb_info)); | 5887 | sis_fb_info->par = ((char *)sis_fb_info + sizeof(*sis_fb_info)); |
4785 | #endif | 5888 | #endif |
@@ -4787,27 +5890,34 @@ static int __devinit sisfb_probe(struct pci_dev *pdev, | |||
4787 | ivideo = (struct sis_video_info *)sis_fb_info->par; | 5890 | ivideo = (struct sis_video_info *)sis_fb_info->par; |
4788 | ivideo->memyselfandi = sis_fb_info; | 5891 | ivideo->memyselfandi = sis_fb_info; |
4789 | 5892 | ||
5893 | ivideo->sisfb_id = SISFB_ID; | ||
5894 | |||
4790 | if(card_list == NULL) { | 5895 | if(card_list == NULL) { |
4791 | ivideo->cardnumber = 0; | 5896 | ivideo->cardnumber = 0; |
4792 | } else { | 5897 | } else { |
4793 | struct sis_video_info *countvideo = card_list; | 5898 | struct sis_video_info *countvideo = card_list; |
4794 | ivideo->cardnumber = 1; | 5899 | ivideo->cardnumber = 1; |
4795 | while((countvideo = countvideo->next) != NULL) ivideo->cardnumber++; | 5900 | while((countvideo = countvideo->next) != 0) |
5901 | ivideo->cardnumber++; | ||
4796 | } | 5902 | } |
4797 | 5903 | ||
4798 | strncpy(ivideo->myid, chipinfo->chip_name, 30); | 5904 | strncpy(ivideo->myid, chipinfo->chip_name, 30); |
4799 | 5905 | ||
4800 | ivideo->warncount = 0; | 5906 | ivideo->warncount = 0; |
4801 | ivideo->chip_id = pdev->device; | 5907 | ivideo->chip_id = pdev->device; |
5908 | ivideo->chip_vendor = pdev->vendor; | ||
4802 | pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo->revision_id); | 5909 | pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo->revision_id); |
4803 | ivideo->sishw_ext.jChipRevision = ivideo->revision_id; | 5910 | ivideo->SiS_Pr.ChipRevision = ivideo->revision_id; |
4804 | pci_read_config_word(pdev, PCI_COMMAND, ®16); | 5911 | pci_read_config_word(pdev, PCI_COMMAND, ®16); |
4805 | sisvga_enabled = reg16 & 0x01; | 5912 | ivideo->sisvga_enabled = reg16 & 0x01; |
4806 | ivideo->pcibus = pdev->bus->number; | 5913 | ivideo->pcibus = pdev->bus->number; |
4807 | ivideo->pcislot = PCI_SLOT(pdev->devfn); | 5914 | ivideo->pcislot = PCI_SLOT(pdev->devfn); |
4808 | ivideo->pcifunc = PCI_FUNC(pdev->devfn); | 5915 | ivideo->pcifunc = PCI_FUNC(pdev->devfn); |
4809 | ivideo->subsysvendor = pdev->subsystem_vendor; | 5916 | ivideo->subsysvendor = pdev->subsystem_vendor; |
4810 | ivideo->subsysdevice = pdev->subsystem_device; | 5917 | ivideo->subsysdevice = pdev->subsystem_device; |
5918 | #ifdef SIS_OLD_CONFIG_COMPAT | ||
5919 | ivideo->ioctl32registered = 0; | ||
5920 | #endif | ||
4811 | 5921 | ||
4812 | #ifndef MODULE | 5922 | #ifndef MODULE |
4813 | if(sisfb_mode_idx == -1) { | 5923 | if(sisfb_mode_idx == -1) { |
@@ -4827,6 +5937,24 @@ static int __devinit sisfb_probe(struct pci_dev *pdev, | |||
4827 | 5937 | ||
4828 | ivideo->sisfb_thismonitor.datavalid = FALSE; | 5938 | ivideo->sisfb_thismonitor.datavalid = FALSE; |
4829 | 5939 | ||
5940 | ivideo->current_base = 0; | ||
5941 | |||
5942 | ivideo->engineok = 0; | ||
5943 | |||
5944 | ivideo->sisfb_was_boot_device = 0; | ||
5945 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)) | ||
5946 | if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) { | ||
5947 | if(ivideo->sisvga_enabled) | ||
5948 | ivideo->sisfb_was_boot_device = 1; | ||
5949 | else { | ||
5950 | printk(KERN_DEBUG "sisfb: PCI device is disabled, " | ||
5951 | "but marked as boot video device ???\n"); | ||
5952 | printk(KERN_DEBUG "sisfb: I will not accept this " | ||
5953 | "as the primary VGA device\n"); | ||
5954 | } | ||
5955 | } | ||
5956 | #endif | ||
5957 | |||
4830 | ivideo->sisfb_parm_mem = sisfb_parm_mem; | 5958 | ivideo->sisfb_parm_mem = sisfb_parm_mem; |
4831 | ivideo->sisfb_accel = sisfb_accel; | 5959 | ivideo->sisfb_accel = sisfb_accel; |
4832 | ivideo->sisfb_ypan = sisfb_ypan; | 5960 | ivideo->sisfb_ypan = sisfb_ypan; |
@@ -4846,7 +5974,6 @@ static int __devinit sisfb_probe(struct pci_dev *pdev, | |||
4846 | ivideo->sisfb_tvstd = sisfb_tvstd; | 5974 | ivideo->sisfb_tvstd = sisfb_tvstd; |
4847 | ivideo->tvxpos = sisfb_tvxposoffset; | 5975 | ivideo->tvxpos = sisfb_tvxposoffset; |
4848 | ivideo->tvypos = sisfb_tvyposoffset; | 5976 | ivideo->tvypos = sisfb_tvyposoffset; |
4849 | ivideo->sisfb_filter = sisfb_filter; | ||
4850 | ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate; | 5977 | ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate; |
4851 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) | 5978 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) |
4852 | ivideo->sisfb_inverse = sisfb_inverse; | 5979 | ivideo->sisfb_inverse = sisfb_inverse; |
@@ -4854,7 +5981,7 @@ static int __devinit sisfb_probe(struct pci_dev *pdev, | |||
4854 | 5981 | ||
4855 | ivideo->refresh_rate = 0; | 5982 | ivideo->refresh_rate = 0; |
4856 | if(ivideo->sisfb_parm_rate != -1) { | 5983 | if(ivideo->sisfb_parm_rate != -1) { |
4857 | ivideo->refresh_rate = ivideo->sisfb_parm_rate; | 5984 | ivideo->refresh_rate = ivideo->sisfb_parm_rate; |
4858 | } | 5985 | } |
4859 | 5986 | ||
4860 | ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd; | 5987 | ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd; |
@@ -4863,8 +5990,8 @@ static int __devinit sisfb_probe(struct pci_dev *pdev, | |||
4863 | ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl; | 5990 | ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl; |
4864 | 5991 | ||
4865 | ivideo->SiS_Pr.SiS_Backup70xx = 0xff; | 5992 | ivideo->SiS_Pr.SiS_Backup70xx = 0xff; |
4866 | ivideo->SiS_Pr.SiS_CHOverScan = -1; | 5993 | ivideo->SiS_Pr.SiS_CHOverScan = -1; |
4867 | ivideo->SiS_Pr.SiS_ChSW = FALSE; | 5994 | ivideo->SiS_Pr.SiS_ChSW = FALSE; |
4868 | ivideo->SiS_Pr.SiS_UseLCDA = FALSE; | 5995 | ivideo->SiS_Pr.SiS_UseLCDA = FALSE; |
4869 | ivideo->SiS_Pr.HaveEMI = FALSE; | 5996 | ivideo->SiS_Pr.HaveEMI = FALSE; |
4870 | ivideo->SiS_Pr.HaveEMILCD = FALSE; | 5997 | ivideo->SiS_Pr.HaveEMILCD = FALSE; |
@@ -4873,12 +6000,13 @@ static int __devinit sisfb_probe(struct pci_dev *pdev, | |||
4873 | ivideo->SiS_Pr.SiS_MyCR63 = 0x63; | 6000 | ivideo->SiS_Pr.SiS_MyCR63 = 0x63; |
4874 | ivideo->SiS_Pr.PDC = -1; | 6001 | ivideo->SiS_Pr.PDC = -1; |
4875 | ivideo->SiS_Pr.PDCA = -1; | 6002 | ivideo->SiS_Pr.PDCA = -1; |
6003 | ivideo->SiS_Pr.DDCPortMixup = FALSE; | ||
4876 | #ifdef CONFIG_FB_SIS_315 | 6004 | #ifdef CONFIG_FB_SIS_315 |
4877 | if(ivideo->chip >= SIS_330) { | 6005 | if(ivideo->chip >= SIS_330) { |
4878 | ivideo->SiS_Pr.SiS_MyCR63 = 0x53; | 6006 | ivideo->SiS_Pr.SiS_MyCR63 = 0x53; |
4879 | if(ivideo->chip >= SIS_661) { | 6007 | if(ivideo->chip >= SIS_661) { |
4880 | ivideo->SiS_Pr.SiS_SensibleSR11 = TRUE; | 6008 | ivideo->SiS_Pr.SiS_SensibleSR11 = TRUE; |
4881 | } | 6009 | } |
4882 | } | 6010 | } |
4883 | #endif | 6011 | #endif |
4884 | 6012 | ||
@@ -4891,9 +6019,9 @@ static int __devinit sisfb_probe(struct pci_dev *pdev, | |||
4891 | switch(ivideo->nbridge->device) { | 6019 | switch(ivideo->nbridge->device) { |
4892 | #ifdef CONFIG_FB_SIS_300 | 6020 | #ifdef CONFIG_FB_SIS_300 |
4893 | case PCI_DEVICE_ID_SI_730: | 6021 | case PCI_DEVICE_ID_SI_730: |
4894 | ivideo->chip = SIS_730; | 6022 | ivideo->chip = SIS_730; |
4895 | strcpy(ivideo->myid, "SiS 730"); | 6023 | strcpy(ivideo->myid, "SiS 730"); |
4896 | break; | 6024 | break; |
4897 | #endif | 6025 | #endif |
4898 | #ifdef CONFIG_FB_SIS_315 | 6026 | #ifdef CONFIG_FB_SIS_315 |
4899 | case PCI_DEVICE_ID_SI_651: | 6027 | case PCI_DEVICE_ID_SI_651: |
@@ -4901,22 +6029,28 @@ static int __devinit sisfb_probe(struct pci_dev *pdev, | |||
4901 | strcpy(ivideo->myid, "SiS 651"); | 6029 | strcpy(ivideo->myid, "SiS 651"); |
4902 | break; | 6030 | break; |
4903 | case PCI_DEVICE_ID_SI_740: | 6031 | case PCI_DEVICE_ID_SI_740: |
4904 | ivideo->chip = SIS_740; | 6032 | ivideo->chip = SIS_740; |
4905 | strcpy(ivideo->myid, "SiS 740"); | 6033 | strcpy(ivideo->myid, "SiS 740"); |
4906 | break; | 6034 | break; |
4907 | case PCI_DEVICE_ID_SI_661: | 6035 | case PCI_DEVICE_ID_SI_661: |
4908 | ivideo->chip = SIS_661; | 6036 | ivideo->chip = SIS_661; |
4909 | strcpy(ivideo->myid, "SiS 661"); | 6037 | strcpy(ivideo->myid, "SiS 661"); |
4910 | break; | 6038 | break; |
4911 | case PCI_DEVICE_ID_SI_741: | 6039 | case PCI_DEVICE_ID_SI_741: |
4912 | ivideo->chip = SIS_741; | 6040 | ivideo->chip = SIS_741; |
4913 | strcpy(ivideo->myid, "SiS 741"); | 6041 | strcpy(ivideo->myid, "SiS 741"); |
4914 | break; | 6042 | break; |
4915 | case PCI_DEVICE_ID_SI_760: | 6043 | case PCI_DEVICE_ID_SI_760: |
4916 | ivideo->chip = SIS_760; | 6044 | ivideo->chip = SIS_760; |
4917 | strcpy(ivideo->myid, "SiS 760"); | 6045 | strcpy(ivideo->myid, "SiS 760"); |
4918 | break; | 6046 | break; |
6047 | case PCI_DEVICE_ID_SI_761: | ||
6048 | ivideo->chip = SIS_761; | ||
6049 | strcpy(ivideo->myid, "SiS 761"); | ||
6050 | break; | ||
4919 | #endif | 6051 | #endif |
6052 | default: | ||
6053 | break; | ||
4920 | } | 6054 | } |
4921 | } | 6055 | } |
4922 | 6056 | ||
@@ -4924,71 +6058,83 @@ static int __devinit sisfb_probe(struct pci_dev *pdev, | |||
4924 | strcpy(sis_fb_info->modename, ivideo->myid); | 6058 | strcpy(sis_fb_info->modename, ivideo->myid); |
4925 | #endif | 6059 | #endif |
4926 | 6060 | ||
4927 | ivideo->sishw_ext.jChipType = ivideo->chip; | 6061 | ivideo->SiS_Pr.ChipType = ivideo->chip; |
6062 | |||
6063 | ivideo->SiS_Pr.ivideo = (void *)ivideo; | ||
4928 | 6064 | ||
4929 | #ifdef CONFIG_FB_SIS_315 | 6065 | #ifdef CONFIG_FB_SIS_315 |
4930 | if((ivideo->sishw_ext.jChipType == SIS_315PRO) || | 6066 | if((ivideo->SiS_Pr.ChipType == SIS_315PRO) || |
4931 | (ivideo->sishw_ext.jChipType == SIS_315)) { | 6067 | (ivideo->SiS_Pr.ChipType == SIS_315)) { |
4932 | ivideo->sishw_ext.jChipType = SIS_315H; | 6068 | ivideo->SiS_Pr.ChipType = SIS_315H; |
4933 | } | 6069 | } |
4934 | #endif | 6070 | #endif |
4935 | 6071 | ||
6072 | if(!ivideo->sisvga_enabled) { | ||
6073 | if(pci_enable_device(pdev)) { | ||
6074 | if(ivideo->nbridge) SIS_PCI_PUT_DEVICE(ivideo->nbridge); | ||
6075 | pci_set_drvdata(pdev, NULL); | ||
6076 | kfree(sis_fb_info); | ||
6077 | return -EIO; | ||
6078 | } | ||
6079 | } | ||
6080 | |||
4936 | ivideo->video_base = pci_resource_start(pdev, 0); | 6081 | ivideo->video_base = pci_resource_start(pdev, 0); |
4937 | ivideo->mmio_base = pci_resource_start(pdev, 1); | 6082 | ivideo->mmio_base = pci_resource_start(pdev, 1); |
4938 | ivideo->mmio_size = pci_resource_len(pdev, 1); | 6083 | ivideo->mmio_size = pci_resource_len(pdev, 1); |
4939 | ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30; | 6084 | ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30; |
4940 | ivideo->sishw_ext.ulIOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO; | 6085 | ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO; |
4941 | 6086 | ||
4942 | if(!sisvga_enabled) { | 6087 | SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress); |
4943 | if(pci_enable_device(pdev)) { | ||
4944 | pci_set_drvdata(pdev, NULL); | ||
4945 | kfree(sis_fb_info); | ||
4946 | return -EIO; | ||
4947 | } | ||
4948 | } | ||
4949 | |||
4950 | SiSRegInit(&ivideo->SiS_Pr, ivideo->sishw_ext.ulIOAddress); | ||
4951 | 6088 | ||
4952 | #ifdef CONFIG_FB_SIS_300 | 6089 | #ifdef CONFIG_FB_SIS_300 |
4953 | /* Find PCI systems for Chrontel/GPIO communication setup */ | 6090 | /* Find PCI systems for Chrontel/GPIO communication setup */ |
4954 | if(ivideo->chip == SIS_630) { | 6091 | if(ivideo->chip == SIS_630) { |
4955 | i=0; | 6092 | i = 0; |
4956 | do { | 6093 | do { |
4957 | if(mychswtable[i].subsysVendor == ivideo->subsysvendor && | 6094 | if(mychswtable[i].subsysVendor == ivideo->subsysvendor && |
4958 | mychswtable[i].subsysCard == ivideo->subsysdevice) { | 6095 | mychswtable[i].subsysCard == ivideo->subsysdevice) { |
4959 | ivideo->SiS_Pr.SiS_ChSW = TRUE; | 6096 | ivideo->SiS_Pr.SiS_ChSW = TRUE; |
4960 | printk(KERN_DEBUG "sisfb: Identified [%s %s] requiring Chrontel/GPIO setup\n", | 6097 | printk(KERN_DEBUG "sisfb: Identified [%s %s] " |
4961 | mychswtable[i].vendorName, mychswtable[i].cardName); | 6098 | "requiring Chrontel/GPIO setup\n", |
4962 | break; | 6099 | mychswtable[i].vendorName, |
4963 | } | 6100 | mychswtable[i].cardName); |
4964 | i++; | 6101 | ivideo->lpcdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0008, NULL); |
4965 | } while(mychswtable[i].subsysVendor != 0); | 6102 | break; |
6103 | } | ||
6104 | i++; | ||
6105 | } while(mychswtable[i].subsysVendor != 0); | ||
6106 | } | ||
6107 | #endif | ||
6108 | |||
6109 | #ifdef CONFIG_FB_SIS_315 | ||
6110 | if((ivideo->chip == SIS_760) && (ivideo->nbridge)) { | ||
6111 | ivideo->lpcdev = SIS_PCI_GET_SLOT(ivideo->nbridge->bus, (2 << 3)); | ||
4966 | } | 6112 | } |
4967 | #endif | 6113 | #endif |
4968 | 6114 | ||
4969 | outSISIDXREG(SISSR, 0x05, 0x86); | 6115 | outSISIDXREG(SISSR, 0x05, 0x86); |
4970 | 6116 | ||
4971 | if( (!sisvga_enabled) | 6117 | if( (!ivideo->sisvga_enabled) |
4972 | #if !defined(__i386__) && !defined(__x86_64__) | 6118 | #if !defined(__i386__) && !defined(__x86_64__) |
4973 | || (sisfb_resetcard) | 6119 | || (sisfb_resetcard) |
4974 | #endif | 6120 | #endif |
4975 | ) { | 6121 | ) { |
4976 | for(i = 0x30; i <= 0x3f; i++) { | 6122 | for(i = 0x30; i <= 0x3f; i++) { |
4977 | outSISIDXREG(SISCR,i,0x00); | 6123 | outSISIDXREG(SISCR, i, 0x00); |
4978 | } | 6124 | } |
4979 | } | 6125 | } |
4980 | 6126 | ||
4981 | /* Find out about current video mode */ | 6127 | /* Find out about current video mode */ |
4982 | ivideo->modeprechange = 0x03; | 6128 | ivideo->modeprechange = 0x03; |
4983 | inSISIDXREG(SISCR,0x34,reg); | 6129 | inSISIDXREG(SISCR, 0x34, reg); |
4984 | if(reg & 0x7f) { | 6130 | if(reg & 0x7f) { |
4985 | ivideo->modeprechange = reg & 0x7f; | 6131 | ivideo->modeprechange = reg & 0x7f; |
4986 | } else if(sisvga_enabled) { | 6132 | } else if(ivideo->sisvga_enabled) { |
4987 | #if defined(__i386__) || defined(__x86_64__) | 6133 | #if defined(__i386__) || defined(__x86_64__) |
4988 | unsigned char SIS_IOTYPE2 *tt = ioremap(0, 0x1000); | 6134 | unsigned char SIS_IOTYPE2 *tt = ioremap(0x400, 0x100); |
4989 | if(tt) { | 6135 | if(tt) { |
4990 | ivideo->modeprechange = readb(tt + 0x449); | 6136 | ivideo->modeprechange = readb(tt + 0x49); |
4991 | iounmap(tt); | 6137 | iounmap(tt); |
4992 | } | 6138 | } |
4993 | #endif | 6139 | #endif |
4994 | } | 6140 | } |
@@ -4996,219 +6142,221 @@ static int __devinit sisfb_probe(struct pci_dev *pdev, | |||
4996 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | 6142 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) |
4997 | #ifdef MODULE | 6143 | #ifdef MODULE |
4998 | if((reg & 0x80) && (reg != 0xff)) { | 6144 | if((reg & 0x80) && (reg != 0xff)) { |
4999 | if((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF) { | 6145 | if((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) |
5000 | printk(KERN_INFO "sisfb: Cannot initialize display mode, X server is active\n"); | 6146 | != 0xFF) { |
5001 | pci_set_drvdata(pdev, NULL); | 6147 | printk(KERN_INFO "sisfb: Cannot initialize display mode, " |
5002 | kfree(sis_fb_info); | 6148 | "X server is active\n"); |
5003 | return -EBUSY; | 6149 | ret = -EBUSY; |
5004 | } | 6150 | goto error_4; |
6151 | } | ||
5005 | } | 6152 | } |
5006 | #endif | ||
5007 | #endif | 6153 | #endif |
5008 | |||
5009 | ivideo->sishw_ext.bIntegratedMMEnabled = TRUE; | ||
5010 | #ifdef CONFIG_FB_SIS_300 | ||
5011 | if(ivideo->sisvga_engine == SIS_300_VGA) { | ||
5012 | if(ivideo->chip != SIS_300) { | ||
5013 | inSISIDXREG(SISSR, 0x1a, reg); | ||
5014 | if(!(reg & 0x10)) { | ||
5015 | ivideo->sishw_ext.bIntegratedMMEnabled = FALSE; | ||
5016 | } | ||
5017 | } | ||
5018 | } | ||
5019 | #endif | 6154 | #endif |
5020 | 6155 | ||
6156 | /* Search and copy ROM image */ | ||
5021 | ivideo->bios_abase = NULL; | 6157 | ivideo->bios_abase = NULL; |
6158 | ivideo->SiS_Pr.VirtualRomBase = NULL; | ||
6159 | ivideo->SiS_Pr.UseROM = FALSE; | ||
6160 | ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = FALSE; | ||
5022 | if(ivideo->sisfb_userom) { | 6161 | if(ivideo->sisfb_userom) { |
5023 | ivideo->sishw_ext.pjVirtualRomBase = sis_find_rom(pdev); | 6162 | ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev); |
5024 | ivideo->bios_abase = ivideo->sishw_ext.pjVirtualRomBase; | 6163 | ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase; |
5025 | if(ivideo->sishw_ext.pjVirtualRomBase) { | 6164 | ivideo->SiS_Pr.UseROM = (ivideo->SiS_Pr.VirtualRomBase) ? TRUE : FALSE; |
5026 | printk(KERN_INFO "sisfb: Video ROM found and copied\n"); | 6165 | printk(KERN_INFO "sisfb: Video ROM %sfound\n", |
5027 | ivideo->sishw_ext.UseROM = TRUE; | 6166 | ivideo->SiS_Pr.UseROM ? "" : "not "); |
5028 | } else { | 6167 | if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) { |
5029 | ivideo->sishw_ext.UseROM = FALSE; | 6168 | ivideo->SiS_Pr.UseROM = FALSE; |
5030 | printk(KERN_INFO "sisfb: Video ROM not found\n"); | 6169 | ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = TRUE; |
5031 | } | 6170 | if( (ivideo->revision_id == 2) && |
6171 | (!(ivideo->bios_abase[0x1d1] & 0x01)) ) { | ||
6172 | ivideo->SiS_Pr.DDCPortMixup = TRUE; | ||
6173 | } | ||
6174 | } | ||
5032 | } else { | 6175 | } else { |
5033 | ivideo->sishw_ext.pjVirtualRomBase = NULL; | 6176 | printk(KERN_INFO "sisfb: Video ROM usage disabled\n"); |
5034 | ivideo->sishw_ext.UseROM = FALSE; | ||
5035 | printk(KERN_INFO "sisfb: Video ROM usage disabled\n"); | ||
5036 | } | 6177 | } |
5037 | 6178 | ||
5038 | /* Find systems for special custom timing */ | 6179 | /* Find systems for special custom timing */ |
5039 | if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) { | 6180 | if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) { |
5040 | int j; | 6181 | sisfb_detect_custom_timing(ivideo); |
5041 | unsigned char *biosver = NULL; | ||
5042 | unsigned char *biosdate = NULL; | ||
5043 | BOOLEAN footprint; | ||
5044 | u32 chksum = 0; | ||
5045 | |||
5046 | if(ivideo->sishw_ext.UseROM) { | ||
5047 | biosver = ivideo->sishw_ext.pjVirtualRomBase + 0x06; | ||
5048 | biosdate = ivideo->sishw_ext.pjVirtualRomBase + 0x2c; | ||
5049 | for(i=0; i<32768; i++) chksum += ivideo->sishw_ext.pjVirtualRomBase[i]; | ||
5050 | } | ||
5051 | |||
5052 | i=0; | ||
5053 | do { | ||
5054 | if( (mycustomttable[i].chipID == ivideo->chip) && | ||
5055 | ((!strlen(mycustomttable[i].biosversion)) || | ||
5056 | (ivideo->sishw_ext.UseROM && | ||
5057 | (!strncmp(mycustomttable[i].biosversion, biosver, strlen(mycustomttable[i].biosversion))))) && | ||
5058 | ((!strlen(mycustomttable[i].biosdate)) || | ||
5059 | (ivideo->sishw_ext.UseROM && | ||
5060 | (!strncmp(mycustomttable[i].biosdate, biosdate, strlen(mycustomttable[i].biosdate))))) && | ||
5061 | ((!mycustomttable[i].bioschksum) || | ||
5062 | (ivideo->sishw_ext.UseROM && | ||
5063 | (mycustomttable[i].bioschksum == chksum))) && | ||
5064 | (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) && | ||
5065 | (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) { | ||
5066 | footprint = TRUE; | ||
5067 | for(j = 0; j < 5; j++) { | ||
5068 | if(mycustomttable[i].biosFootprintAddr[j]) { | ||
5069 | if(ivideo->sishw_ext.UseROM) { | ||
5070 | if(ivideo->sishw_ext.pjVirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] != | ||
5071 | mycustomttable[i].biosFootprintData[j]) { | ||
5072 | footprint = FALSE; | ||
5073 | } | ||
5074 | } else footprint = FALSE; | ||
5075 | } | ||
5076 | } | ||
5077 | if(footprint) { | ||
5078 | ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID; | ||
5079 | printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n", | ||
5080 | mycustomttable[i].vendorName, | ||
5081 | mycustomttable[i].cardName); | ||
5082 | printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n", | ||
5083 | mycustomttable[i].optionName); | ||
5084 | break; | ||
5085 | } | ||
5086 | } | ||
5087 | i++; | ||
5088 | } while(mycustomttable[i].chipID); | ||
5089 | } | 6182 | } |
5090 | 6183 | ||
5091 | #ifdef CONFIG_FB_SIS_300 | 6184 | /* POST card in case this has not been done by the BIOS */ |
5092 | if(ivideo->sisvga_engine == SIS_300_VGA) { | 6185 | if( (!ivideo->sisvga_enabled) |
5093 | if( (!sisvga_enabled) | ||
5094 | #if !defined(__i386__) && !defined(__x86_64__) | 6186 | #if !defined(__i386__) && !defined(__x86_64__) |
5095 | || (sisfb_resetcard) | 6187 | || (sisfb_resetcard) |
5096 | #endif | 6188 | #endif |
5097 | ) { | 6189 | ) { |
6190 | #ifdef CONFIG_FB_SIS_300 | ||
6191 | if(ivideo->sisvga_engine == SIS_300_VGA) { | ||
5098 | if(ivideo->chip == SIS_300) { | 6192 | if(ivideo->chip == SIS_300) { |
5099 | sisfb_post_sis300(pdev); | 6193 | sisfb_post_sis300(pdev); |
6194 | ivideo->sisfb_can_post = 1; | ||
5100 | } | 6195 | } |
5101 | } | 6196 | } |
5102 | } | ||
5103 | #endif | 6197 | #endif |
5104 | 6198 | ||
5105 | #ifdef CONFIG_FB_SIS_315 | 6199 | #ifdef CONFIG_FB_SIS_315 |
5106 | if(ivideo->sisvga_engine == SIS_315_VGA) { | 6200 | if(ivideo->sisvga_engine == SIS_315_VGA) { |
5107 | if( (!sisvga_enabled) | 6201 | int result = 1; |
5108 | #if !defined(__i386__) && !defined(__x86_64__) | 6202 | /* if((ivideo->chip == SIS_315H) || |
5109 | || (sisfb_resetcard) | ||
5110 | #endif | ||
5111 | ) { | ||
5112 | if((ivideo->chip == SIS_315H) || | ||
5113 | (ivideo->chip == SIS_315) || | 6203 | (ivideo->chip == SIS_315) || |
5114 | (ivideo->chip == SIS_315PRO) || | 6204 | (ivideo->chip == SIS_315PRO) || |
5115 | (ivideo->chip == SIS_330)) { | 6205 | (ivideo->chip == SIS_330)) { |
5116 | sisfb_post_sis315330(pdev); | 6206 | sisfb_post_sis315330(pdev); |
6207 | } else */ if(ivideo->chip == XGI_20) { | ||
6208 | result = sisfb_post_xgi(pdev); | ||
6209 | ivideo->sisfb_can_post = 1; | ||
6210 | } else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) { | ||
6211 | result = sisfb_post_xgi(pdev); | ||
6212 | ivideo->sisfb_can_post = 1; | ||
6213 | } else { | ||
6214 | printk(KERN_INFO "sisfb: Card is not " | ||
6215 | "POSTed and sisfb can't do this either.\n"); | ||
6216 | } | ||
6217 | if(!result) { | ||
6218 | printk(KERN_ERR "sisfb: Failed to POST card\n"); | ||
6219 | ret = -ENODEV; | ||
6220 | goto error_3; | ||
5117 | } | 6221 | } |
5118 | } | 6222 | } |
5119 | } | ||
5120 | #endif | 6223 | #endif |
6224 | } | ||
5121 | 6225 | ||
6226 | ivideo->sisfb_card_posted = 1; | ||
6227 | |||
6228 | /* Find out about RAM size */ | ||
5122 | if(sisfb_get_dram_size(ivideo)) { | 6229 | if(sisfb_get_dram_size(ivideo)) { |
5123 | printk(KERN_INFO "sisfb: Fatal error: Unable to determine RAM size.\n"); | 6230 | printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n"); |
5124 | if(ivideo->bios_abase) vfree(ivideo->bios_abase); | 6231 | ret = -ENODEV; |
5125 | pci_set_drvdata(pdev, NULL); | 6232 | goto error_3; |
5126 | kfree(sis_fb_info); | ||
5127 | return -ENODEV; | ||
5128 | } | 6233 | } |
5129 | 6234 | ||
6235 | |||
6236 | /* Enable PCI addressing and MMIO */ | ||
5130 | if((ivideo->sisfb_mode_idx < 0) || | 6237 | if((ivideo->sisfb_mode_idx < 0) || |
5131 | ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) { | 6238 | ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) { |
5132 | /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */ | 6239 | /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */ |
5133 | orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE)); | 6240 | orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE)); |
5134 | /* Enable 2D accelerator engine */ | 6241 | /* Enable 2D accelerator engine */ |
5135 | orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D); | 6242 | orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D); |
5136 | } | 6243 | } |
5137 | 6244 | ||
5138 | if(sisfb_pdc != 0xff) { | 6245 | if(sisfb_pdc != 0xff) { |
5139 | if(ivideo->sisvga_engine == SIS_300_VGA) sisfb_pdc &= 0x3c; | 6246 | if(ivideo->sisvga_engine == SIS_300_VGA) |
5140 | else sisfb_pdc &= 0x1f; | 6247 | sisfb_pdc &= 0x3c; |
5141 | ivideo->SiS_Pr.PDC = sisfb_pdc; | 6248 | else |
6249 | sisfb_pdc &= 0x1f; | ||
6250 | ivideo->SiS_Pr.PDC = sisfb_pdc; | ||
5142 | } | 6251 | } |
5143 | #ifdef CONFIG_FB_SIS_315 | 6252 | #ifdef CONFIG_FB_SIS_315 |
5144 | if(ivideo->sisvga_engine == SIS_315_VGA) { | 6253 | if(ivideo->sisvga_engine == SIS_315_VGA) { |
5145 | if(sisfb_pdca != 0xff) ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f; | 6254 | if(sisfb_pdca != 0xff) |
6255 | ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f; | ||
5146 | } | 6256 | } |
5147 | #endif | 6257 | #endif |
5148 | 6258 | ||
5149 | if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) { | 6259 | if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) { |
5150 | printk(KERN_ERR "sisfb: Fatal error: Unable to reserve frame buffer memory\n"); | 6260 | printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n", |
6261 | (int)(ivideo->video_size >> 20)); | ||
5151 | printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n"); | 6262 | printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n"); |
5152 | if(ivideo->bios_abase) vfree(ivideo->bios_abase); | 6263 | ret = -ENODEV; |
5153 | pci_set_drvdata(pdev, NULL); | 6264 | goto error_3; |
5154 | kfree(sis_fb_info); | ||
5155 | return -ENODEV; | ||
5156 | } | 6265 | } |
5157 | 6266 | ||
5158 | if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) { | 6267 | if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) { |
5159 | printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n"); | 6268 | printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n"); |
5160 | release_mem_region(ivideo->video_base, ivideo->video_size); | 6269 | ret = -ENODEV; |
5161 | if(ivideo->bios_abase) vfree(ivideo->bios_abase); | 6270 | goto error_2; |
5162 | pci_set_drvdata(pdev, NULL); | ||
5163 | kfree(sis_fb_info); | ||
5164 | return -ENODEV; | ||
5165 | } | 6271 | } |
5166 | 6272 | ||
5167 | ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size); | 6273 | ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size); |
5168 | ivideo->sishw_ext.pjVideoMemoryAddress = ivideo->video_vbase; | 6274 | ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase; |
5169 | if(!ivideo->video_vbase) { | 6275 | if(!ivideo->video_vbase) { |
5170 | printk(KERN_ERR "sisfb: Fatal error: Unable to map frame buffer memory\n"); | 6276 | printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n"); |
5171 | release_mem_region(ivideo->video_base, ivideo->video_size); | 6277 | ret = -ENODEV; |
5172 | release_mem_region(ivideo->mmio_base, ivideo->mmio_size); | 6278 | goto error_1; |
5173 | if(ivideo->bios_abase) vfree(ivideo->bios_abase); | ||
5174 | pci_set_drvdata(pdev, NULL); | ||
5175 | kfree(sis_fb_info); | ||
5176 | return -ENODEV; | ||
5177 | } | 6279 | } |
5178 | 6280 | ||
5179 | ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size); | 6281 | ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size); |
5180 | if(!ivideo->mmio_vbase) { | 6282 | if(!ivideo->mmio_vbase) { |
5181 | printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n"); | 6283 | printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n"); |
5182 | iounmap(ivideo->video_vbase); | 6284 | ret = -ENODEV; |
5183 | release_mem_region(ivideo->video_base, ivideo->video_size); | 6285 | error_0: iounmap(ivideo->video_vbase); |
5184 | release_mem_region(ivideo->mmio_base, ivideo->mmio_size); | 6286 | error_1: release_mem_region(ivideo->video_base, ivideo->video_size); |
5185 | if(ivideo->bios_abase) vfree(ivideo->bios_abase); | 6287 | error_2: release_mem_region(ivideo->mmio_base, ivideo->mmio_size); |
6288 | error_3: vfree(ivideo->bios_abase); | ||
6289 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
6290 | error_4: | ||
6291 | #endif | ||
6292 | if(ivideo->lpcdev) | ||
6293 | SIS_PCI_PUT_DEVICE(ivideo->lpcdev); | ||
6294 | if(ivideo->nbridge) | ||
6295 | SIS_PCI_PUT_DEVICE(ivideo->nbridge); | ||
5186 | pci_set_drvdata(pdev, NULL); | 6296 | pci_set_drvdata(pdev, NULL); |
5187 | kfree(sis_fb_info); | 6297 | if(!ivideo->sisvga_enabled) |
5188 | return -ENODEV; | 6298 | pci_disable_device(pdev); |
6299 | kfree(sis_fb_info); | ||
6300 | return ret; | ||
5189 | } | 6301 | } |
5190 | 6302 | ||
5191 | printk(KERN_INFO "sisfb: Framebuffer at 0x%lx, mapped to 0x%lx, size %ldk\n", | 6303 | printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n", |
5192 | ivideo->video_base, (ULONG)ivideo->video_vbase, ivideo->video_size / 1024); | 6304 | ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024); |
6305 | |||
6306 | if(ivideo->video_offset) { | ||
6307 | printk(KERN_INFO "sisfb: Viewport offset %ldk\n", | ||
6308 | ivideo->video_offset / 1024); | ||
6309 | } | ||
5193 | 6310 | ||
5194 | printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n", | 6311 | printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n", |
5195 | ivideo->mmio_base, (ULONG)ivideo->mmio_vbase, ivideo->mmio_size / 1024); | 6312 | ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024); |
6313 | |||
5196 | 6314 | ||
6315 | /* Determine the size of the command queue */ | ||
6316 | if(ivideo->sisvga_engine == SIS_300_VGA) { | ||
6317 | ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE; | ||
6318 | } else { | ||
6319 | if(ivideo->chip == XGI_20) { | ||
6320 | ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7; | ||
6321 | } else { | ||
6322 | ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE; | ||
6323 | } | ||
6324 | } | ||
6325 | |||
6326 | /* Engines are no longer initialized here; this is | ||
6327 | * now done after the first mode-switch (if the | ||
6328 | * submitted var has its acceleration flags set). | ||
6329 | */ | ||
6330 | |||
6331 | /* Calculate the base of the (unused) hw cursor */ | ||
6332 | ivideo->hwcursor_vbase = ivideo->video_vbase | ||
6333 | + ivideo->video_size | ||
6334 | - ivideo->cmdQueueSize | ||
6335 | - ivideo->hwcursor_size; | ||
6336 | ivideo->caps |= HW_CURSOR_CAP; | ||
6337 | |||
6338 | /* Initialize offscreen memory manager */ | ||
5197 | if((ivideo->havenoheap = sisfb_heap_init(ivideo))) { | 6339 | if((ivideo->havenoheap = sisfb_heap_init(ivideo))) { |
5198 | printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n"); | 6340 | printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n"); |
5199 | } | 6341 | } |
5200 | 6342 | ||
5201 | /* Used for clearing the screen only, therefore respect our mem limit */ | 6343 | /* Used for clearing the screen only, therefore respect our mem limit */ |
5202 | ivideo->sishw_ext.ulVideoMemorySize = ivideo->sisfb_mem; | 6344 | ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset; |
6345 | ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem; | ||
5203 | 6346 | ||
5204 | ivideo->mtrr = 0; | 6347 | ivideo->mtrr = -1; |
5205 | 6348 | ||
5206 | ivideo->vbflags = 0; | 6349 | ivideo->vbflags = 0; |
5207 | ivideo->lcddefmodeidx = DEFAULT_LCDMODE; | 6350 | ivideo->lcddefmodeidx = DEFAULT_LCDMODE; |
5208 | ivideo->tvdefmodeidx = DEFAULT_TVMODE; | 6351 | ivideo->tvdefmodeidx = DEFAULT_TVMODE; |
5209 | ivideo->defmodeidx = DEFAULT_MODE; | 6352 | ivideo->defmodeidx = DEFAULT_MODE; |
5210 | 6353 | ||
5211 | ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr, &ivideo->sishw_ext); | 6354 | ivideo->newrom = 0; |
6355 | if(ivideo->chip < XGI_20) { | ||
6356 | if(ivideo->bios_abase) { | ||
6357 | ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr); | ||
6358 | } | ||
6359 | } | ||
5212 | 6360 | ||
5213 | if((ivideo->sisfb_mode_idx < 0) || | 6361 | if((ivideo->sisfb_mode_idx < 0) || |
5214 | ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) { | 6362 | ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) { |
@@ -5217,192 +6365,57 @@ static int __devinit sisfb_probe(struct pci_dev *pdev, | |||
5217 | 6365 | ||
5218 | sisfb_get_VB_type(ivideo); | 6366 | sisfb_get_VB_type(ivideo); |
5219 | 6367 | ||
5220 | if(ivideo->vbflags & VB_VIDEOBRIDGE) { | 6368 | if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) { |
5221 | sisfb_detect_VB_connect(ivideo); | 6369 | sisfb_detect_VB_connect(ivideo); |
5222 | } | 6370 | } |
5223 | 6371 | ||
5224 | ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD); | 6372 | ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD); |
5225 | 6373 | ||
5226 | if(ivideo->vbflags & VB_VIDEOBRIDGE) { | 6374 | /* Decide on which CRT2 device to use */ |
5227 | if(ivideo->sisfb_crt2type != -1) { | 6375 | if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) { |
5228 | if((ivideo->sisfb_crt2type == CRT2_LCD) && (ivideo->vbflags & CRT2_LCD)) { | 6376 | if(ivideo->sisfb_crt2type != -1) { |
5229 | ivideo->currentvbflags |= CRT2_LCD; | 6377 | if((ivideo->sisfb_crt2type == CRT2_LCD) && |
5230 | } else if(ivideo->sisfb_crt2type != CRT2_LCD) { | 6378 | (ivideo->vbflags & CRT2_LCD)) { |
5231 | ivideo->currentvbflags |= ivideo->sisfb_crt2type; | 6379 | ivideo->currentvbflags |= CRT2_LCD; |
5232 | } | 6380 | } else if(ivideo->sisfb_crt2type != CRT2_LCD) { |
5233 | } else { | 6381 | ivideo->currentvbflags |= ivideo->sisfb_crt2type; |
5234 | /* Chrontel 700x TV detection often unreliable, therefore use a | 6382 | } |
5235 | * different default order on such machines | 6383 | } else { |
5236 | */ | 6384 | /* Chrontel 700x TV detection often unreliable, therefore |
5237 | if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags & VB_CHRONTEL)) { | 6385 | * use a different default order on such machines |
5238 | if(ivideo->vbflags & CRT2_LCD) ivideo->currentvbflags |= CRT2_LCD; | 6386 | */ |
5239 | else if(ivideo->vbflags & CRT2_TV) ivideo->currentvbflags |= CRT2_TV; | 6387 | if((ivideo->sisvga_engine == SIS_300_VGA) && |
5240 | else if(ivideo->vbflags & CRT2_VGA) ivideo->currentvbflags |= CRT2_VGA; | 6388 | (ivideo->vbflags2 & VB2_CHRONTEL)) { |
5241 | } else { | 6389 | if(ivideo->vbflags & CRT2_LCD) |
5242 | if(ivideo->vbflags & CRT2_TV) ivideo->currentvbflags |= CRT2_TV; | 6390 | ivideo->currentvbflags |= CRT2_LCD; |
5243 | else if(ivideo->vbflags & CRT2_LCD) ivideo->currentvbflags |= CRT2_LCD; | 6391 | else if(ivideo->vbflags & CRT2_TV) |
5244 | else if(ivideo->vbflags & CRT2_VGA) ivideo->currentvbflags |= CRT2_VGA; | 6392 | ivideo->currentvbflags |= CRT2_TV; |
5245 | } | 6393 | else if(ivideo->vbflags & CRT2_VGA) |
5246 | } | 6394 | ivideo->currentvbflags |= CRT2_VGA; |
6395 | } else { | ||
6396 | if(ivideo->vbflags & CRT2_TV) | ||
6397 | ivideo->currentvbflags |= CRT2_TV; | ||
6398 | else if(ivideo->vbflags & CRT2_LCD) | ||
6399 | ivideo->currentvbflags |= CRT2_LCD; | ||
6400 | else if(ivideo->vbflags & CRT2_VGA) | ||
6401 | ivideo->currentvbflags |= CRT2_VGA; | ||
6402 | } | ||
6403 | } | ||
5247 | } | 6404 | } |
5248 | 6405 | ||
5249 | if(ivideo->vbflags & CRT2_LCD) { | 6406 | if(ivideo->vbflags & CRT2_LCD) { |
5250 | inSISIDXREG(SISCR, 0x36, reg); | 6407 | sisfb_detect_lcd_type(ivideo); |
5251 | reg &= 0x0f; | ||
5252 | if(ivideo->sisvga_engine == SIS_300_VGA) { | ||
5253 | ivideo->CRT2LCDType = sis300paneltype[reg]; | ||
5254 | } else if(ivideo->chip >= SIS_661) { | ||
5255 | ivideo->CRT2LCDType = sis661paneltype[reg]; | ||
5256 | } else { | ||
5257 | ivideo->CRT2LCDType = sis310paneltype[reg]; | ||
5258 | if((ivideo->chip == SIS_550) && (sisfb_fstn)) { | ||
5259 | if((ivideo->CRT2LCDType != LCD_640x480_2) && | ||
5260 | (ivideo->CRT2LCDType != LCD_640x480_3)) { | ||
5261 | ivideo->CRT2LCDType = LCD_320x480; | ||
5262 | } | ||
5263 | } | ||
5264 | } | ||
5265 | if(ivideo->CRT2LCDType == LCD_UNKNOWN) { | ||
5266 | /* For broken BIOSes: Assume 1024x768, RGB18 */ | ||
5267 | ivideo->CRT2LCDType = LCD_1024x768; | ||
5268 | setSISIDXREG(SISCR,0x36,0xf0,0x02); | ||
5269 | setSISIDXREG(SISCR,0x37,0xee,0x01); | ||
5270 | printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg); | ||
5271 | } | ||
5272 | for(i = 0; i < SIS_LCD_NUMBER; i++) { | ||
5273 | if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) { | ||
5274 | ivideo->lcdxres = sis_lcd_data[i].xres; | ||
5275 | ivideo->lcdyres = sis_lcd_data[i].yres; | ||
5276 | ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx; | ||
5277 | break; | ||
5278 | } | ||
5279 | } | ||
5280 | if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) { | ||
5281 | ivideo->lcdxres = 1360; ivideo->lcdyres = 1024; ivideo->lcddefmodeidx = 99; | ||
5282 | } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) { | ||
5283 | ivideo->lcdxres = 848; ivideo->lcdyres = 480; ivideo->lcddefmodeidx = 47; | ||
5284 | } | ||
5285 | printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n", | ||
5286 | ivideo->lcdxres, ivideo->lcdyres); | ||
5287 | } | ||
5288 | |||
5289 | #ifdef CONFIG_FB_SIS_300 | ||
5290 | /* Save the current PanelDelayCompensation if the LCD is currently used */ | ||
5291 | if(ivideo->sisvga_engine == SIS_300_VGA) { | ||
5292 | if(ivideo->vbflags & (VB_LVDS | VB_30xBDH)) { | ||
5293 | int tmp; | ||
5294 | inSISIDXREG(SISCR,0x30,tmp); | ||
5295 | if(tmp & 0x20) { | ||
5296 | /* Currently on LCD? If yes, read current pdc */ | ||
5297 | inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc); | ||
5298 | ivideo->detectedpdc &= 0x3c; | ||
5299 | if(ivideo->SiS_Pr.PDC == -1) { | ||
5300 | /* Let option override detection */ | ||
5301 | ivideo->SiS_Pr.PDC = ivideo->detectedpdc; | ||
5302 | } | ||
5303 | printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n", | ||
5304 | ivideo->detectedpdc); | ||
5305 | } | ||
5306 | if((ivideo->SiS_Pr.PDC != -1) && (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) { | ||
5307 | printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n", | ||
5308 | ivideo->SiS_Pr.PDC); | ||
5309 | } | ||
5310 | } | ||
5311 | } | 6408 | } |
5312 | #endif | ||
5313 | |||
5314 | #ifdef CONFIG_FB_SIS_315 | ||
5315 | if(ivideo->sisvga_engine == SIS_315_VGA) { | ||
5316 | |||
5317 | /* Try to find about LCDA */ | ||
5318 | if(ivideo->vbflags & (VB_301C | VB_302B | VB_301LV | VB_302LV | VB_302ELV)) { | ||
5319 | int tmp; | ||
5320 | inSISIDXREG(SISPART1,0x13,tmp); | ||
5321 | if(tmp & 0x04) { | ||
5322 | ivideo->SiS_Pr.SiS_UseLCDA = TRUE; | ||
5323 | ivideo->detectedlcda = 0x03; | ||
5324 | } | ||
5325 | } | ||
5326 | |||
5327 | /* Save PDC */ | ||
5328 | if(ivideo->vbflags & (VB_301LV | VB_302LV | VB_302ELV)) { | ||
5329 | int tmp; | ||
5330 | inSISIDXREG(SISCR,0x30,tmp); | ||
5331 | if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) { | ||
5332 | /* Currently on LCD? If yes, read current pdc */ | ||
5333 | u8 pdc; | ||
5334 | inSISIDXREG(SISPART1,0x2D,pdc); | ||
5335 | ivideo->detectedpdc = (pdc & 0x0f) << 1; | ||
5336 | ivideo->detectedpdca = (pdc & 0xf0) >> 3; | ||
5337 | inSISIDXREG(SISPART1,0x35,pdc); | ||
5338 | ivideo->detectedpdc |= ((pdc >> 7) & 0x01); | ||
5339 | inSISIDXREG(SISPART1,0x20,pdc); | ||
5340 | ivideo->detectedpdca |= ((pdc >> 6) & 0x01); | ||
5341 | if(ivideo->newrom) { | ||
5342 | /* New ROM invalidates other PDC resp. */ | ||
5343 | if(ivideo->detectedlcda != 0xff) { | ||
5344 | ivideo->detectedpdc = 0xff; | ||
5345 | } else { | ||
5346 | ivideo->detectedpdca = 0xff; | ||
5347 | } | ||
5348 | } | ||
5349 | if(ivideo->SiS_Pr.PDC == -1) { | ||
5350 | if(ivideo->detectedpdc != 0xff) { | ||
5351 | ivideo->SiS_Pr.PDC = ivideo->detectedpdc; | ||
5352 | } | ||
5353 | } | ||
5354 | if(ivideo->SiS_Pr.PDCA == -1) { | ||
5355 | if(ivideo->detectedpdca != 0xff) { | ||
5356 | ivideo->SiS_Pr.PDCA = ivideo->detectedpdca; | ||
5357 | } | ||
5358 | } | ||
5359 | if(ivideo->detectedpdc != 0xff) { | ||
5360 | printk(KERN_INFO | ||
5361 | "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n", | ||
5362 | ivideo->detectedpdc); | ||
5363 | } | ||
5364 | if(ivideo->detectedpdca != 0xff) { | ||
5365 | printk(KERN_INFO | ||
5366 | "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n", | ||
5367 | ivideo->detectedpdca); | ||
5368 | } | ||
5369 | } | ||
5370 | |||
5371 | /* Save EMI */ | ||
5372 | if(ivideo->vbflags & (VB_302LV | VB_302ELV)) { | ||
5373 | inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30); | ||
5374 | inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31); | ||
5375 | inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32); | ||
5376 | inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33); | ||
5377 | ivideo->SiS_Pr.HaveEMI = TRUE; | ||
5378 | if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) { | ||
5379 | ivideo->SiS_Pr.HaveEMILCD = TRUE; | ||
5380 | } | ||
5381 | } | ||
5382 | } | ||
5383 | |||
5384 | /* Let user override detected PDCs (all bridges) */ | ||
5385 | if(ivideo->vbflags & (VB_301B | VB_301C | VB_301LV | VB_302LV | VB_302ELV)) { | ||
5386 | if((ivideo->SiS_Pr.PDC != -1) && (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) { | ||
5387 | printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n", | ||
5388 | ivideo->SiS_Pr.PDC); | ||
5389 | } | ||
5390 | if((ivideo->SiS_Pr.PDCA != -1) && (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) { | ||
5391 | printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n", | ||
5392 | ivideo->SiS_Pr.PDCA); | ||
5393 | } | ||
5394 | } | ||
5395 | 6409 | ||
5396 | } | 6410 | sisfb_save_pdc_emi(ivideo); |
5397 | #endif | ||
5398 | 6411 | ||
5399 | if(!ivideo->sisfb_crt1off) { | 6412 | if(!ivideo->sisfb_crt1off) { |
5400 | sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0); | 6413 | sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0); |
5401 | } else { | 6414 | } else { |
5402 | if((ivideo->vbflags & (VB_301|VB_301B|VB_301C|VB_302B)) && | 6415 | if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) && |
5403 | (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) { | 6416 | (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) { |
5404 | sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1); | 6417 | sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1); |
5405 | } | 6418 | } |
5406 | } | 6419 | } |
5407 | 6420 | ||
5408 | if(ivideo->sisfb_mode_idx >= 0) { | 6421 | if(ivideo->sisfb_mode_idx >= 0) { |
@@ -5434,7 +6447,8 @@ static int __devinit sisfb_probe(struct pci_dev *pdev, | |||
5434 | ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]; | 6447 | ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]; |
5435 | 6448 | ||
5436 | if(ivideo->refresh_rate != 0) { | 6449 | if(ivideo->refresh_rate != 0) { |
5437 | sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx); | 6450 | sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, |
6451 | ivideo->sisfb_mode_idx); | ||
5438 | } | 6452 | } |
5439 | 6453 | ||
5440 | if(ivideo->rate_idx == 0) { | 6454 | if(ivideo->rate_idx == 0) { |
@@ -5443,9 +6457,12 @@ static int __devinit sisfb_probe(struct pci_dev *pdev, | |||
5443 | } | 6457 | } |
5444 | 6458 | ||
5445 | if(ivideo->sisfb_thismonitor.datavalid) { | 6459 | if(ivideo->sisfb_thismonitor.datavalid) { |
5446 | if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx, | 6460 | if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, |
5447 | ivideo->rate_idx, ivideo->refresh_rate)) { | 6461 | ivideo->sisfb_mode_idx, |
5448 | printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n"); | 6462 | ivideo->rate_idx, |
6463 | ivideo->refresh_rate)) { | ||
6464 | printk(KERN_INFO "sisfb: WARNING: Refresh rate " | ||
6465 | "exceeds monitor specs!\n"); | ||
5449 | } | 6466 | } |
5450 | } | 6467 | } |
5451 | 6468 | ||
@@ -5454,28 +6471,34 @@ static int __devinit sisfb_probe(struct pci_dev *pdev, | |||
5454 | ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres; | 6471 | ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres; |
5455 | 6472 | ||
5456 | sisfb_set_vparms(ivideo); | 6473 | sisfb_set_vparms(ivideo); |
5457 | |||
5458 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
5459 | 6474 | ||
5460 | /* ---------------- For 2.4: Now switch the mode ------------------ */ | 6475 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) |
5461 | 6476 | ||
5462 | printk(KERN_INFO "sisfb: Mode is %dx%dx%d (%dHz)\n", | 6477 | /* ---------------- For 2.4: Now switch the mode ------------------ */ |
5463 | ivideo->video_width, ivideo->video_height, ivideo->video_bpp, | 6478 | |
6479 | printk(KERN_INFO "sisfb: Setting mode %dx%dx%d (%dHz)\n", | ||
6480 | ivideo->video_width, ivideo->video_height, ivideo->video_bpp, | ||
5464 | ivideo->refresh_rate); | 6481 | ivideo->refresh_rate); |
5465 | 6482 | ||
6483 | /* Determine whether or not acceleration is to be | ||
6484 | * used. Need to know before pre/post_set_mode() | ||
6485 | */ | ||
6486 | ivideo->accel = 0; | ||
6487 | ivideo->default_var.accel_flags &= ~FB_ACCELF_TEXT; | ||
6488 | if(ivideo->sisfb_accel) { | ||
6489 | ivideo->accel = -1; | ||
6490 | ivideo->default_var.accel_flags |= FB_ACCELF_TEXT; | ||
6491 | } | ||
6492 | |||
6493 | /* Now switch the mode */ | ||
5466 | sisfb_pre_setmode(ivideo); | 6494 | sisfb_pre_setmode(ivideo); |
5467 | 6495 | ||
5468 | if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) { | 6496 | if(SiSSetMode(&ivideo->SiS_Pr, ivideo->mode_no) == 0) { |
5469 | printk(KERN_ERR "sisfb: Fatal error: Setting mode[0x%x] failed\n", | 6497 | printk(KERN_ERR "sisfb: Fatal error: Setting mode[0x%x] failed\n", |
5470 | ivideo->mode_no); | 6498 | ivideo->mode_no); |
5471 | iounmap(ivideo->video_vbase); | 6499 | ret = -EINVAL; |
5472 | iounmap(ivideo->mmio_vbase); | 6500 | iounmap(ivideo->mmio_vbase); |
5473 | release_mem_region(ivideo->video_base, ivideo->video_size); | 6501 | goto error_0; |
5474 | release_mem_region(ivideo->mmio_base, ivideo->mmio_size); | ||
5475 | if(ivideo->bios_abase) vfree(ivideo->bios_abase); | ||
5476 | pci_set_drvdata(pdev, NULL); | ||
5477 | kfree(sis_fb_info); | ||
5478 | return -EINVAL; | ||
5479 | } | 6502 | } |
5480 | 6503 | ||
5481 | outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); | 6504 | outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); |
@@ -5488,18 +6511,17 @@ static int __devinit sisfb_probe(struct pci_dev *pdev, | |||
5488 | /* Force reset of x virtual in crtc_to_var */ | 6511 | /* Force reset of x virtual in crtc_to_var */ |
5489 | ivideo->default_var.xres_virtual = 0; | 6512 | ivideo->default_var.xres_virtual = 0; |
5490 | 6513 | ||
6514 | /* Copy mode timing to var */ | ||
5491 | sisfb_crtc_to_var(ivideo, &ivideo->default_var); | 6515 | sisfb_crtc_to_var(ivideo, &ivideo->default_var); |
5492 | 6516 | ||
6517 | /* Find out about screen pitch */ | ||
5493 | sisfb_calc_pitch(ivideo, &ivideo->default_var); | 6518 | sisfb_calc_pitch(ivideo, &ivideo->default_var); |
5494 | sisfb_set_pitch(ivideo); | 6519 | sisfb_set_pitch(ivideo); |
5495 | 6520 | ||
5496 | ivideo->accel = 0; | 6521 | /* Init the accelerator (does nothing currently) */ |
5497 | if(ivideo->sisfb_accel) { | ||
5498 | ivideo->accel = -1; | ||
5499 | ivideo->default_var.accel_flags |= FB_ACCELF_TEXT; | ||
5500 | } | ||
5501 | sisfb_initaccel(ivideo); | 6522 | sisfb_initaccel(ivideo); |
5502 | 6523 | ||
6524 | /* Init some fbinfo entries */ | ||
5503 | sis_fb_info->node = -1; | 6525 | sis_fb_info->node = -1; |
5504 | sis_fb_info->flags = FBINFO_FLAG_DEFAULT; | 6526 | sis_fb_info->flags = FBINFO_FLAG_DEFAULT; |
5505 | sis_fb_info->fbops = &sisfb_ops; | 6527 | sis_fb_info->fbops = &sisfb_ops; |
@@ -5515,41 +6537,42 @@ static int __devinit sisfb_probe(struct pci_dev *pdev, | |||
5515 | #else /* --------- For 2.6: Setup a somewhat sane default var ------------ */ | 6537 | #else /* --------- For 2.6: Setup a somewhat sane default var ------------ */ |
5516 | 6538 | ||
5517 | printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n", | 6539 | printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n", |
5518 | ivideo->video_width, ivideo->video_height, ivideo->video_bpp, | 6540 | ivideo->video_width, ivideo->video_height, ivideo->video_bpp, |
5519 | ivideo->refresh_rate); | 6541 | ivideo->refresh_rate); |
5520 | 6542 | ||
6543 | /* Set up the default var according to chosen default display mode */ | ||
5521 | ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width; | 6544 | ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width; |
5522 | ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height; | 6545 | ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height; |
5523 | ivideo->default_var.bits_per_pixel = ivideo->video_bpp; | 6546 | ivideo->default_var.bits_per_pixel = ivideo->video_bpp; |
5524 | 6547 | ||
5525 | sisfb_bpp_to_var(ivideo, &ivideo->default_var); | 6548 | sisfb_bpp_to_var(ivideo, &ivideo->default_var); |
5526 | 6549 | ||
5527 | ivideo->default_var.pixclock = (u32) (1000000000 / | 6550 | ivideo->default_var.pixclock = (u32) (1000000000 / |
5528 | sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, &ivideo->sishw_ext, | 6551 | sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx)); |
5529 | ivideo->mode_no, ivideo->rate_idx)); | 6552 | |
5530 | 6553 | if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no, | |
5531 | if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, &ivideo->sishw_ext, | 6554 | ivideo->rate_idx, &ivideo->default_var)) { |
5532 | ivideo->mode_no, ivideo->rate_idx, &ivideo->default_var)) { | 6555 | if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { |
5533 | if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { | 6556 | ivideo->default_var.pixclock <<= 1; |
5534 | ivideo->default_var.pixclock <<= 1; | 6557 | } |
5535 | } | 6558 | } |
5536 | } | ||
5537 | 6559 | ||
5538 | if(ivideo->sisfb_ypan) { | 6560 | if(ivideo->sisfb_ypan) { |
5539 | /* Maximize regardless of sisfb_max at startup */ | 6561 | /* Maximize regardless of sisfb_max at startup */ |
5540 | ivideo->default_var.yres_virtual = sisfb_calc_maxyres(ivideo, &ivideo->default_var); | 6562 | ivideo->default_var.yres_virtual = |
5541 | if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) { | 6563 | sisfb_calc_maxyres(ivideo, &ivideo->default_var); |
5542 | ivideo->default_var.yres_virtual = ivideo->default_var.yres; | 6564 | if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) { |
5543 | } | 6565 | ivideo->default_var.yres_virtual = ivideo->default_var.yres; |
6566 | } | ||
5544 | } | 6567 | } |
5545 | 6568 | ||
5546 | sisfb_calc_pitch(ivideo, &ivideo->default_var); | 6569 | sisfb_calc_pitch(ivideo, &ivideo->default_var); |
5547 | 6570 | ||
5548 | ivideo->accel = 0; | 6571 | ivideo->accel = 0; |
5549 | if(ivideo->sisfb_accel) { | 6572 | if(ivideo->sisfb_accel) { |
5550 | ivideo->accel = -1; | 6573 | ivideo->accel = -1; |
5551 | #ifdef STUPID_ACCELF_TEXT_SHIT | 6574 | #ifdef STUPID_ACCELF_TEXT_SHIT |
5552 | ivideo->default_var.accel_flags |= FB_ACCELF_TEXT; | 6575 | ivideo->default_var.accel_flags |= FB_ACCELF_TEXT; |
5553 | #endif | 6576 | #endif |
5554 | } | 6577 | } |
5555 | sisfb_initaccel(ivideo); | 6578 | sisfb_initaccel(ivideo); |
@@ -5566,21 +6589,21 @@ static int __devinit sisfb_probe(struct pci_dev *pdev, | |||
5566 | #endif | 6589 | #endif |
5567 | sis_fb_info->var = ivideo->default_var; | 6590 | sis_fb_info->var = ivideo->default_var; |
5568 | sis_fb_info->fix = ivideo->sisfb_fix; | 6591 | sis_fb_info->fix = ivideo->sisfb_fix; |
5569 | sis_fb_info->screen_base = ivideo->video_vbase; | 6592 | sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset; |
5570 | sis_fb_info->fbops = &sisfb_ops; | 6593 | sis_fb_info->fbops = &sisfb_ops; |
5571 | 6594 | ||
5572 | sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info); | 6595 | sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info); |
5573 | sis_fb_info->pseudo_palette = ivideo->pseudo_palette; | 6596 | sis_fb_info->pseudo_palette = ivideo->pseudo_palette; |
5574 | 6597 | ||
5575 | fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0); | 6598 | fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0); |
5576 | #endif /* 2.6 */ | 6599 | #endif /* 2.6 */ |
5577 | 6600 | ||
5578 | printk(KERN_DEBUG "sisfb: Initial vbflags 0x%lx\n", (unsigned long)ivideo->vbflags); | 6601 | printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags); |
5579 | 6602 | ||
5580 | #ifdef CONFIG_MTRR | 6603 | #ifdef CONFIG_MTRR |
5581 | ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size, | 6604 | ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size, |
5582 | MTRR_TYPE_WRCOMB, 1); | 6605 | MTRR_TYPE_WRCOMB, 1); |
5583 | if(!ivideo->mtrr) { | 6606 | if(ivideo->mtrr < 0) { |
5584 | printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n"); | 6607 | printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n"); |
5585 | } | 6608 | } |
5586 | #endif | 6609 | #endif |
@@ -5591,14 +6614,9 @@ static int __devinit sisfb_probe(struct pci_dev *pdev, | |||
5591 | 6614 | ||
5592 | if(register_framebuffer(sis_fb_info) < 0) { | 6615 | if(register_framebuffer(sis_fb_info) < 0) { |
5593 | printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n"); | 6616 | printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n"); |
5594 | iounmap(ivideo->video_vbase); | 6617 | ret = -EINVAL; |
5595 | iounmap(ivideo->mmio_vbase); | 6618 | iounmap(ivideo->mmio_vbase); |
5596 | release_mem_region(ivideo->video_base, ivideo->video_size); | 6619 | goto error_0; |
5597 | release_mem_region(ivideo->mmio_base, ivideo->mmio_size); | ||
5598 | if(ivideo->bios_abase) vfree(ivideo->bios_abase); | ||
5599 | pci_set_drvdata(pdev, NULL); | ||
5600 | kfree(sis_fb_info); | ||
5601 | return -EINVAL; | ||
5602 | } | 6620 | } |
5603 | 6621 | ||
5604 | ivideo->registered = 1; | 6622 | ivideo->registered = 1; |
@@ -5607,21 +6625,47 @@ static int __devinit sisfb_probe(struct pci_dev *pdev, | |||
5607 | ivideo->next = card_list; | 6625 | ivideo->next = card_list; |
5608 | card_list = ivideo; | 6626 | card_list = ivideo; |
5609 | 6627 | ||
6628 | #ifdef SIS_OLD_CONFIG_COMPAT | ||
6629 | { | ||
6630 | int ret; | ||
6631 | /* Our ioctls are all "32/64bit compatible" */ | ||
6632 | ret = register_ioctl32_conversion(FBIO_ALLOC, NULL); | ||
6633 | ret |= register_ioctl32_conversion(FBIO_FREE, NULL); | ||
6634 | ret |= register_ioctl32_conversion(FBIOGET_VBLANK, NULL); | ||
6635 | ret |= register_ioctl32_conversion(SISFB_GET_INFO_SIZE, NULL); | ||
6636 | ret |= register_ioctl32_conversion(SISFB_GET_INFO, NULL); | ||
6637 | ret |= register_ioctl32_conversion(SISFB_GET_TVPOSOFFSET, NULL); | ||
6638 | ret |= register_ioctl32_conversion(SISFB_SET_TVPOSOFFSET, NULL); | ||
6639 | ret |= register_ioctl32_conversion(SISFB_SET_LOCK, NULL); | ||
6640 | ret |= register_ioctl32_conversion(SISFB_GET_VBRSTATUS, NULL); | ||
6641 | ret |= register_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE, NULL); | ||
6642 | ret |= register_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE, NULL); | ||
6643 | ret |= register_ioctl32_conversion(SISFB_COMMAND, NULL); | ||
6644 | if(ret) | ||
6645 | printk(KERN_ERR | ||
6646 | "sisfb: Error registering ioctl32 translations\n"); | ||
6647 | else | ||
6648 | ivideo->ioctl32registered = 1; | ||
6649 | } | ||
6650 | #endif | ||
6651 | |||
5610 | printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n", | 6652 | printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n", |
5611 | ivideo->sisfb_accel ? "enabled" : "disabled", | 6653 | ivideo->sisfb_accel ? "enabled" : "disabled", |
5612 | ivideo->sisfb_ypan ? | 6654 | ivideo->sisfb_ypan ? |
5613 | (ivideo->sisfb_max ? "enabled (auto-max)" : "enabled (no auto-max)") : "disabled"); | 6655 | (ivideo->sisfb_max ? "enabled (auto-max)" : |
6656 | "enabled (no auto-max)") : | ||
6657 | "disabled"); | ||
5614 | 6658 | ||
5615 | 6659 | ||
5616 | printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%d\n", | 6660 | printk(KERN_INFO "fb%d: %s frame buffer device version %d.%d.%d\n", |
5617 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | 6661 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) |
5618 | GET_FB_IDX(sis_fb_info->node), | 6662 | GET_FB_IDX(sis_fb_info->node), |
5619 | #else | 6663 | #else |
5620 | sis_fb_info->node, | 6664 | sis_fb_info->node, |
5621 | #endif | 6665 | #endif |
5622 | ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL); | 6666 | ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL); |
5623 | 6667 | ||
5624 | printk(KERN_INFO "sisfb: (C) 2001-2004 Thomas Winischhofer.\n"); | 6668 | printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n"); |
5625 | 6669 | ||
5626 | } /* if mode = "none" */ | 6670 | } /* if mode = "none" */ |
5627 | 6671 | ||
@@ -5634,26 +6678,62 @@ static int __devinit sisfb_probe(struct pci_dev *pdev, | |||
5634 | 6678 | ||
5635 | static void __devexit sisfb_remove(struct pci_dev *pdev) | 6679 | static void __devexit sisfb_remove(struct pci_dev *pdev) |
5636 | { | 6680 | { |
5637 | struct sis_video_info *ivideo = pci_get_drvdata(pdev); | 6681 | struct sis_video_info *ivideo = pci_get_drvdata(pdev); |
5638 | struct fb_info *sis_fb_info = ivideo->memyselfandi; | 6682 | struct fb_info *sis_fb_info = ivideo->memyselfandi; |
5639 | int registered = ivideo->registered; | 6683 | int registered = ivideo->registered; |
6684 | int modechanged = ivideo->modechanged; | ||
6685 | |||
6686 | #ifdef SIS_OLD_CONFIG_COMPAT | ||
6687 | if(ivideo->ioctl32registered) { | ||
6688 | int ret; | ||
6689 | ret = unregister_ioctl32_conversion(FBIO_ALLOC); | ||
6690 | ret |= unregister_ioctl32_conversion(FBIO_FREE); | ||
6691 | ret |= unregister_ioctl32_conversion(FBIOGET_VBLANK); | ||
6692 | ret |= unregister_ioctl32_conversion(SISFB_GET_INFO_SIZE); | ||
6693 | ret |= unregister_ioctl32_conversion(SISFB_GET_INFO); | ||
6694 | ret |= unregister_ioctl32_conversion(SISFB_GET_TVPOSOFFSET); | ||
6695 | ret |= unregister_ioctl32_conversion(SISFB_SET_TVPOSOFFSET); | ||
6696 | ret |= unregister_ioctl32_conversion(SISFB_SET_LOCK); | ||
6697 | ret |= unregister_ioctl32_conversion(SISFB_GET_VBRSTATUS); | ||
6698 | ret |= unregister_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE); | ||
6699 | ret |= unregister_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE); | ||
6700 | ret |= unregister_ioctl32_conversion(SISFB_COMMAND); | ||
6701 | if(ret) | ||
6702 | printk(KERN_ERR | ||
6703 | "sisfb: Error unregistering ioctl32 translations\n"); | ||
6704 | } | ||
6705 | #endif | ||
5640 | 6706 | ||
5641 | /* Unmap */ | 6707 | /* Unmap */ |
5642 | iounmap(ivideo->video_vbase); | ||
5643 | iounmap(ivideo->mmio_vbase); | 6708 | iounmap(ivideo->mmio_vbase); |
5644 | vfree(ivideo->bios_abase); | 6709 | iounmap(ivideo->video_vbase); |
5645 | 6710 | ||
5646 | /* Release mem regions */ | 6711 | /* Release mem regions */ |
5647 | release_mem_region(ivideo->video_base, ivideo->video_size); | 6712 | release_mem_region(ivideo->video_base, ivideo->video_size); |
5648 | release_mem_region(ivideo->mmio_base, ivideo->mmio_size); | 6713 | release_mem_region(ivideo->mmio_base, ivideo->mmio_size); |
5649 | 6714 | ||
6715 | vfree(ivideo->bios_abase); | ||
6716 | |||
6717 | if(ivideo->lpcdev) | ||
6718 | SIS_PCI_PUT_DEVICE(ivideo->lpcdev); | ||
6719 | |||
6720 | if(ivideo->nbridge) | ||
6721 | SIS_PCI_PUT_DEVICE(ivideo->nbridge); | ||
6722 | |||
5650 | #ifdef CONFIG_MTRR | 6723 | #ifdef CONFIG_MTRR |
5651 | /* Release MTRR region */ | 6724 | /* Release MTRR region */ |
5652 | if(ivideo->mtrr) { | 6725 | if(ivideo->mtrr >= 0) |
5653 | mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size); | 6726 | mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size); |
5654 | } | ||
5655 | #endif | 6727 | #endif |
5656 | 6728 | ||
6729 | pci_set_drvdata(pdev, NULL); | ||
6730 | |||
6731 | /* If device was disabled when starting, disable | ||
6732 | * it when quitting. | ||
6733 | */ | ||
6734 | if(!ivideo->sisvga_enabled) | ||
6735 | pci_disable_device(pdev); | ||
6736 | |||
5657 | /* Unregister the framebuffer */ | 6737 | /* Unregister the framebuffer */ |
5658 | if(ivideo->registered) { | 6738 | if(ivideo->registered) { |
5659 | unregister_framebuffer(sis_fb_info); | 6739 | unregister_framebuffer(sis_fb_info); |
@@ -5664,7 +6744,7 @@ static void __devexit sisfb_remove(struct pci_dev *pdev) | |||
5664 | #endif | 6744 | #endif |
5665 | } | 6745 | } |
5666 | 6746 | ||
5667 | pci_set_drvdata(pdev, NULL); | 6747 | /* OK, our ivideo is gone for good from here. */ |
5668 | 6748 | ||
5669 | /* TODO: Restore the initial mode | 6749 | /* TODO: Restore the initial mode |
5670 | * This sounds easy but is as good as impossible | 6750 | * This sounds easy but is as good as impossible |
@@ -5673,15 +6753,15 @@ static void __devexit sisfb_remove(struct pci_dev *pdev) | |||
5673 | * from machine to machine. Depends on the type | 6753 | * from machine to machine. Depends on the type |
5674 | * of integration between chipset and bridge. | 6754 | * of integration between chipset and bridge. |
5675 | */ | 6755 | */ |
5676 | if(registered) { | 6756 | if(registered && modechanged) |
5677 | printk(KERN_INFO "sisfb: Restoring of text mode not supported yet\n"); | 6757 | printk(KERN_INFO |
5678 | } | 6758 | "sisfb: Restoring of text mode not supported yet\n"); |
5679 | }; | 6759 | }; |
5680 | 6760 | ||
5681 | static struct pci_driver sisfb_driver = { | 6761 | static struct pci_driver sisfb_driver = { |
5682 | .name = "sisfb", | 6762 | .name = "sisfb", |
5683 | .id_table = sisfb_pci_table, | 6763 | .id_table = sisfb_pci_table, |
5684 | .probe = sisfb_probe, | 6764 | .probe = sisfb_probe, |
5685 | .remove = __devexit_p(sisfb_remove) | 6765 | .remove = __devexit_p(sisfb_remove) |
5686 | }; | 6766 | }; |
5687 | 6767 | ||
@@ -5693,10 +6773,11 @@ SISINITSTATIC int __init sisfb_init(void) | |||
5693 | 6773 | ||
5694 | if(fb_get_options("sisfb", &options)) | 6774 | if(fb_get_options("sisfb", &options)) |
5695 | return -ENODEV; | 6775 | return -ENODEV; |
6776 | |||
5696 | sisfb_setup(options); | 6777 | sisfb_setup(options); |
5697 | #endif | 6778 | #endif |
5698 | #endif | 6779 | #endif |
5699 | return(pci_register_driver(&sisfb_driver)); | 6780 | return pci_register_driver(&sisfb_driver); |
5700 | } | 6781 | } |
5701 | 6782 | ||
5702 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8) | 6783 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8) |
@@ -5711,36 +6792,129 @@ module_init(sisfb_init); | |||
5711 | 6792 | ||
5712 | #ifdef MODULE | 6793 | #ifdef MODULE |
5713 | 6794 | ||
5714 | static char *mode = NULL; | 6795 | static char *mode = NULL; |
5715 | static int vesa = -1; | 6796 | static int vesa = -1; |
5716 | static unsigned int rate = 0; | 6797 | static unsigned int rate = 0; |
5717 | static unsigned int crt1off = 1; | 6798 | static unsigned int crt1off = 1; |
5718 | static unsigned int mem = 0; | 6799 | static unsigned int mem = 0; |
5719 | static char *forcecrt2type = NULL; | 6800 | static char *forcecrt2type = NULL; |
5720 | static int forcecrt1 = -1; | 6801 | static int forcecrt1 = -1; |
5721 | static int pdc = -1; | 6802 | static int pdc = -1; |
5722 | static int pdc1 = -1; | 6803 | static int pdc1 = -1; |
5723 | static int noaccel = -1; | 6804 | static int noaccel = -1; |
5724 | static int noypan = -1; | 6805 | static int noypan = -1; |
5725 | static int nomax = -1; | 6806 | static int nomax = -1; |
6807 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
6808 | static int inverse = 0; | ||
6809 | #endif | ||
6810 | static int userom = -1; | ||
6811 | static int useoem = -1; | ||
6812 | static char *tvstandard = NULL; | ||
6813 | static int nocrt2rate = 0; | ||
6814 | static int scalelcd = -1; | ||
6815 | static char *specialtiming = NULL; | ||
6816 | static int lvdshl = -1; | ||
6817 | static int tvxposoffset = 0, tvyposoffset = 0; | ||
6818 | #if !defined(__i386__) && !defined(__x86_64__) | ||
6819 | static int resetcard = 0; | ||
6820 | static int videoram = 0; | ||
6821 | #endif | ||
6822 | |||
6823 | static int __init sisfb_init_module(void) | ||
6824 | { | ||
6825 | sisfb_setdefaultparms(); | ||
6826 | |||
6827 | if(rate) | ||
6828 | sisfb_parm_rate = rate; | ||
6829 | |||
6830 | if((scalelcd == 0) || (scalelcd == 1)) | ||
6831 | sisfb_scalelcd = scalelcd ^ 1; | ||
6832 | |||
6833 | /* Need to check crt2 type first for fstn/dstn */ | ||
6834 | |||
6835 | if(forcecrt2type) | ||
6836 | sisfb_search_crt2type(forcecrt2type); | ||
6837 | |||
6838 | if(tvstandard) | ||
6839 | sisfb_search_tvstd(tvstandard); | ||
6840 | |||
6841 | if(mode) | ||
6842 | sisfb_search_mode(mode, FALSE); | ||
6843 | else if(vesa != -1) | ||
6844 | sisfb_search_vesamode(vesa, FALSE); | ||
6845 | |||
6846 | sisfb_crt1off = (crt1off == 0) ? 1 : 0; | ||
6847 | |||
6848 | sisfb_forcecrt1 = forcecrt1; | ||
6849 | if(forcecrt1 == 1) | ||
6850 | sisfb_crt1off = 0; | ||
6851 | else if(forcecrt1 == 0) | ||
6852 | sisfb_crt1off = 1; | ||
6853 | |||
6854 | if(noaccel == 1) | ||
6855 | sisfb_accel = 0; | ||
6856 | else if(noaccel == 0) | ||
6857 | sisfb_accel = 1; | ||
6858 | |||
6859 | if(noypan == 1) | ||
6860 | sisfb_ypan = 0; | ||
6861 | else if(noypan == 0) | ||
6862 | sisfb_ypan = 1; | ||
6863 | |||
6864 | if(nomax == 1) | ||
6865 | sisfb_max = 0; | ||
6866 | else if(nomax == 0) | ||
6867 | sisfb_max = 1; | ||
6868 | |||
5726 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | 6869 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) |
5727 | static int inverse = 0; | 6870 | if(inverse) sisfb_inverse = 1; |
5728 | #endif | 6871 | #endif |
5729 | static int userom = -1; | 6872 | |
5730 | static int useoem = -1; | 6873 | if(mem) |
5731 | static char *tvstandard = NULL; | 6874 | sisfb_parm_mem = mem; |
5732 | static int nocrt2rate = 0; | 6875 | |
5733 | static int scalelcd = -1; | 6876 | if(userom != -1) |
5734 | static char *specialtiming = NULL; | 6877 | sisfb_userom = userom; |
5735 | static int lvdshl = -1; | 6878 | |
5736 | static int tvxposoffset = 0, tvyposoffset = 0; | 6879 | if(useoem != -1) |
5737 | static int filter = -1; | 6880 | sisfb_useoem = useoem; |
6881 | |||
6882 | if(pdc != -1) | ||
6883 | sisfb_pdc = (pdc & 0x7f); | ||
6884 | |||
6885 | if(pdc1 != -1) | ||
6886 | sisfb_pdca = (pdc1 & 0x1f); | ||
6887 | |||
6888 | sisfb_nocrt2rate = nocrt2rate; | ||
6889 | |||
6890 | if(specialtiming) | ||
6891 | sisfb_search_specialtiming(specialtiming); | ||
6892 | |||
6893 | if((lvdshl >= 0) && (lvdshl <= 3)) | ||
6894 | sisfb_lvdshl = lvdshl; | ||
6895 | |||
6896 | sisfb_tvxposoffset = tvxposoffset; | ||
6897 | sisfb_tvyposoffset = tvyposoffset; | ||
6898 | |||
5738 | #if !defined(__i386__) && !defined(__x86_64__) | 6899 | #if !defined(__i386__) && !defined(__x86_64__) |
5739 | static int resetcard = 0; | 6900 | sisfb_resetcard = (resetcard) ? 1 : 0; |
5740 | static int videoram = 0; | 6901 | if(videoram) |
6902 | sisfb_videoram = videoram; | ||
5741 | #endif | 6903 | #endif |
5742 | 6904 | ||
5743 | MODULE_DESCRIPTION("SiS 300/540/630/730/315/550/65x/661/74x/330/760 framebuffer device driver"); | 6905 | return sisfb_init(); |
6906 | } | ||
6907 | |||
6908 | static void __exit sisfb_remove_module(void) | ||
6909 | { | ||
6910 | pci_unregister_driver(&sisfb_driver); | ||
6911 | printk(KERN_DEBUG "sisfb: Module unloaded\n"); | ||
6912 | } | ||
6913 | |||
6914 | module_init(sisfb_init_module); | ||
6915 | module_exit(sisfb_remove_module); | ||
6916 | |||
6917 | MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver"); | ||
5744 | MODULE_LICENSE("GPL"); | 6918 | MODULE_LICENSE("GPL"); |
5745 | MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others"); | 6919 | MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others"); |
5746 | 6920 | ||
@@ -5764,7 +6938,6 @@ MODULE_PARM(lvdshl, "i"); | |||
5764 | MODULE_PARM(tvstandard, "s"); | 6938 | MODULE_PARM(tvstandard, "s"); |
5765 | MODULE_PARM(tvxposoffset, "i"); | 6939 | MODULE_PARM(tvxposoffset, "i"); |
5766 | MODULE_PARM(tvyposoffset, "i"); | 6940 | MODULE_PARM(tvyposoffset, "i"); |
5767 | MODULE_PARM(filter, "i"); | ||
5768 | MODULE_PARM(nocrt2rate, "i"); | 6941 | MODULE_PARM(nocrt2rate, "i"); |
5769 | MODULE_PARM(inverse, "i"); | 6942 | MODULE_PARM(inverse, "i"); |
5770 | #if !defined(__i386__) && !defined(__x86_64__) | 6943 | #if !defined(__i386__) && !defined(__x86_64__) |
@@ -5793,7 +6966,6 @@ module_param(lvdshl, int, 0); | |||
5793 | module_param(tvstandard, charp, 0); | 6966 | module_param(tvstandard, charp, 0); |
5794 | module_param(tvxposoffset, int, 0); | 6967 | module_param(tvxposoffset, int, 0); |
5795 | module_param(tvyposoffset, int, 0); | 6968 | module_param(tvyposoffset, int, 0); |
5796 | module_param(filter, int, 0); | ||
5797 | module_param(nocrt2rate, int, 0); | 6969 | module_param(nocrt2rate, int, 0); |
5798 | #if !defined(__i386__) && !defined(__x86_64__) | 6970 | #if !defined(__i386__) && !defined(__x86_64__) |
5799 | module_param(resetcard, int, 0); | 6971 | module_param(resetcard, int, 0); |
@@ -5801,25 +6973,35 @@ module_param(videoram, int, 0); | |||
5801 | #endif | 6973 | #endif |
5802 | #endif | 6974 | #endif |
5803 | 6975 | ||
6976 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
5804 | MODULE_PARM_DESC(mem, | 6977 | MODULE_PARM_DESC(mem, |
5805 | "\nDetermines the beginning of the video memory heap in KB. This heap is used\n" | 6978 | "\nDetermines the beginning of the video memory heap in KB. This heap is used\n" |
5806 | "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n" | 6979 | "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n" |
5807 | "on the amount of video RAM available. If 8MB of video RAM or less is available,\n" | 6980 | "on the amount of video RAM available. If 8MB of video RAM or less is available,\n" |
5808 | "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n" | 6981 | "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n" |
5809 | "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n" | 6982 | "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n" |
5810 | "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n" | 6983 | "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n" |
5811 | "for XFree86 4.x/X.org 6.7 and later.\n"); | 6984 | "for XFree86 4.x/X.org 6.7 and later.\n"); |
6985 | #else | ||
6986 | MODULE_PARM_DESC(mem, | ||
6987 | "\nDetermines the beginning of the video memory heap in KB. This heap is used\n" | ||
6988 | "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n" | ||
6989 | "on the amount of video RAM available. If 8MB of video RAM or less is available,\n" | ||
6990 | "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n" | ||
6991 | "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n" | ||
6992 | "The value is to be specified without 'KB'.\n"); | ||
6993 | #endif | ||
5812 | 6994 | ||
5813 | MODULE_PARM_DESC(noaccel, | 6995 | MODULE_PARM_DESC(noaccel, |
5814 | "\nIf set to anything other than 0, 2D acceleration will be disabled.\n" | 6996 | "\nIf set to anything other than 0, 2D acceleration will be disabled.\n" |
5815 | "(default: 0)\n"); | 6997 | "(default: 0)\n"); |
5816 | 6998 | ||
5817 | MODULE_PARM_DESC(noypan, | 6999 | MODULE_PARM_DESC(noypan, |
5818 | "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n" | 7000 | "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n" |
5819 | "will be performed by redrawing the screen. (default: 0)\n"); | 7001 | "will be performed by redrawing the screen. (default: 0)\n"); |
5820 | 7002 | ||
5821 | MODULE_PARM_DESC(nomax, | 7003 | MODULE_PARM_DESC(nomax, |
5822 | "\nIf y-panning is enabled, sisfb will by default use the entire available video\n" | 7004 | "\nIf y-panning is enabled, sisfb will by default use the entire available video\n" |
5823 | "memory for the virtual screen in order to optimize scrolling performance. If\n" | 7005 | "memory for the virtual screen in order to optimize scrolling performance. If\n" |
5824 | "this is set to anything other than 0, sisfb will not do this and thereby \n" | 7006 | "this is set to anything other than 0, sisfb will not do this and thereby \n" |
5825 | "enable the user to positively specify a virtual Y size of the screen using\n" | 7007 | "enable the user to positively specify a virtual Y size of the screen using\n" |
@@ -5827,30 +7009,30 @@ MODULE_PARM_DESC(nomax, | |||
5827 | 7009 | ||
5828 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | 7010 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) |
5829 | MODULE_PARM_DESC(mode, | 7011 | MODULE_PARM_DESC(mode, |
5830 | "\nSelects the desired display mode in the format [X]x[Y]x[Depth], eg.\n" | 7012 | "\nSelects the desired display mode in the format [X]x[Y]x[Depth], eg.\n" |
5831 | "1024x768x16. Other formats supported include XxY-Depth and\n" | 7013 | "1024x768x16. Other formats supported include XxY-Depth and\n" |
5832 | "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n" | 7014 | "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n" |
5833 | "number, it will be interpreted as a VESA mode number. (default: none if\n" | 7015 | "number, it will be interpreted as a VESA mode number. (default: none if\n" |
5834 | "sisfb is a module; this leaves the console untouched and the driver will\n" | 7016 | "sisfb is a module; this leaves the console untouched and the driver will\n" |
5835 | "only do the video memory management for eg. DRM/DRI; 800x600x8 if sisfb\n" | 7017 | "only do the video memory management for eg. DRM/DRI; 800x600x8 if sisfb\n" |
5836 | "is in the kernel)\n"); | 7018 | "is in the kernel)\n"); |
5837 | MODULE_PARM_DESC(vesa, | 7019 | MODULE_PARM_DESC(vesa, |
5838 | "\nSelects the desired display mode by VESA defined mode number, eg. 0x117\n" | 7020 | "\nSelects the desired display mode by VESA defined mode number, eg. 0x117\n" |
5839 | "(default: 0x0000 if sisfb is a module; this leaves the console untouched\n" | 7021 | "(default: 0x0000 if sisfb is a module; this leaves the console untouched\n" |
5840 | "and the driver will only do the video memory management for eg. DRM/DRI;\n" | 7022 | "and the driver will only do the video memory management for eg. DRM/DRI;\n" |
5841 | "0x0103 if sisfb is in the kernel)\n"); | 7023 | "0x0103 if sisfb is in the kernel)\n"); |
5842 | #endif | 7024 | #endif |
5843 | 7025 | ||
5844 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | 7026 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) |
5845 | MODULE_PARM_DESC(mode, | 7027 | MODULE_PARM_DESC(mode, |
5846 | "\nSelects the desired default display mode in the format XxYxDepth,\n" | 7028 | "\nSelects the desired default display mode in the format XxYxDepth,\n" |
5847 | "eg. 1024x768x16. Other formats supported include XxY-Depth and\n" | 7029 | "eg. 1024x768x16. Other formats supported include XxY-Depth and\n" |
5848 | "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n" | 7030 | "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n" |
5849 | "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n"); | 7031 | "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n"); |
5850 | 7032 | ||
5851 | MODULE_PARM_DESC(vesa, | 7033 | MODULE_PARM_DESC(vesa, |
5852 | "\nSelects the desired default display mode by VESA defined mode number, eg.\n" | 7034 | "\nSelects the desired default display mode by VESA defined mode number, eg.\n" |
5853 | "0x117 (default: 0x0103)\n"); | 7035 | "0x117 (default: 0x0103)\n"); |
5854 | #endif | 7036 | #endif |
5855 | 7037 | ||
5856 | MODULE_PARM_DESC(rate, | 7038 | MODULE_PARM_DESC(rate, |
@@ -5880,16 +7062,16 @@ MODULE_PARM_DESC(scalelcd, | |||
5880 | "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n"); | 7062 | "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n"); |
5881 | 7063 | ||
5882 | MODULE_PARM_DESC(pdc, | 7064 | MODULE_PARM_DESC(pdc, |
5883 | "\nThis is for manually selecting the LCD panel delay compensation. The driver\n" | 7065 | "\nThis is for manually selecting the LCD panel delay compensation. The driver\n" |
5884 | "should detect this correctly in most cases; however, sometimes this is not\n" | 7066 | "should detect this correctly in most cases; however, sometimes this is not\n" |
5885 | "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n" | 7067 | "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n" |
5886 | "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n" | 7068 | "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n" |
5887 | "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n" | 7069 | "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n" |
5888 | "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n"); | 7070 | "value from 0 to 31). (default: autodetected, if LCD is active during start)\n"); |
5889 | 7071 | ||
5890 | #ifdef CONFIG_FB_SIS_315 | 7072 | #ifdef CONFIG_FB_SIS_315 |
5891 | MODULE_PARM_DESC(pdc1, | 7073 | MODULE_PARM_DESC(pdc1, |
5892 | "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n" | 7074 | "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n" |
5893 | "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n" | 7075 | "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n" |
5894 | "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n" | 7076 | "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n" |
5895 | "implemented yet.\n"); | 7077 | "implemented yet.\n"); |
@@ -5913,17 +7095,13 @@ MODULE_PARM_DESC(tvyposoffset, | |||
5913 | "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n" | 7095 | "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n" |
5914 | "Default: 0\n"); | 7096 | "Default: 0\n"); |
5915 | 7097 | ||
5916 | MODULE_PARM_DESC(filter, | ||
5917 | "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n" | ||
5918 | "(Possible values 0-7, default: [no filter])\n"); | ||
5919 | |||
5920 | MODULE_PARM_DESC(nocrt2rate, | 7098 | MODULE_PARM_DESC(nocrt2rate, |
5921 | "\nSetting this to 1 will force the driver to use the default refresh rate for\n" | 7099 | "\nSetting this to 1 will force the driver to use the default refresh rate for\n" |
5922 | "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n"); | 7100 | "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n"); |
5923 | 7101 | ||
5924 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | 7102 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) |
5925 | MODULE_PARM_DESC(inverse, | 7103 | MODULE_PARM_DESC(inverse, |
5926 | "\nSetting this to anything but 0 should invert the display colors, but this\n" | 7104 | "\nSetting this to anything but 0 should invert the display colors, but this\n" |
5927 | "does not seem to work. (default: 0)\n"); | 7105 | "does not seem to work. (default: 0)\n"); |
5928 | #endif | 7106 | #endif |
5929 | 7107 | ||
@@ -5931,98 +7109,23 @@ MODULE_PARM_DESC(inverse, | |||
5931 | #ifdef CONFIG_FB_SIS_300 | 7109 | #ifdef CONFIG_FB_SIS_300 |
5932 | MODULE_PARM_DESC(resetcard, | 7110 | MODULE_PARM_DESC(resetcard, |
5933 | "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n" | 7111 | "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n" |
5934 | "the BIOS did not POST the card (only supported for SiS 300/305 currently).\n" | 7112 | "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n" |
5935 | "Default: 0\n"); | 7113 | "currently). Default: 0\n"); |
5936 | 7114 | ||
5937 | MODULE_PARM_DESC(videoram, | 7115 | MODULE_PARM_DESC(videoram, |
5938 | "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n" | 7116 | "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n" |
5939 | "some non-x86 architectures where the memory auto detection fails. Only\n" | 7117 | "some non-x86 architectures where the memory auto detection fails. Only\n" |
5940 | "relevant if resetcard is set, too. Default: [auto-detect]\n"); | 7118 | "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n"); |
5941 | #endif | ||
5942 | #endif | 7119 | #endif |
5943 | |||
5944 | static int __devinit sisfb_init_module(void) | ||
5945 | { | ||
5946 | sisfb_setdefaultparms(); | ||
5947 | |||
5948 | if(rate) sisfb_parm_rate = rate; | ||
5949 | |||
5950 | if((scalelcd == 0) || (scalelcd == 1)) { | ||
5951 | sisfb_scalelcd = scalelcd ^ 1; | ||
5952 | } | ||
5953 | |||
5954 | /* Need to check crt2 type first for fstn/dstn */ | ||
5955 | |||
5956 | if(forcecrt2type) | ||
5957 | sisfb_search_crt2type(forcecrt2type); | ||
5958 | |||
5959 | if(tvstandard) | ||
5960 | sisfb_search_tvstd(tvstandard); | ||
5961 | |||
5962 | if(mode) | ||
5963 | sisfb_search_mode(mode, FALSE); | ||
5964 | else if(vesa != -1) | ||
5965 | sisfb_search_vesamode(vesa, FALSE); | ||
5966 | |||
5967 | sisfb_crt1off = (crt1off == 0) ? 1 : 0; | ||
5968 | |||
5969 | sisfb_forcecrt1 = forcecrt1; | ||
5970 | if(forcecrt1 == 1) sisfb_crt1off = 0; | ||
5971 | else if(forcecrt1 == 0) sisfb_crt1off = 1; | ||
5972 | |||
5973 | if(noaccel == 1) sisfb_accel = 0; | ||
5974 | else if(noaccel == 0) sisfb_accel = 1; | ||
5975 | |||
5976 | if(noypan == 1) sisfb_ypan = 0; | ||
5977 | else if(noypan == 0) sisfb_ypan = 1; | ||
5978 | |||
5979 | if(nomax == 1) sisfb_max = 0; | ||
5980 | else if(nomax == 0) sisfb_max = 1; | ||
5981 | |||
5982 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
5983 | if(inverse) sisfb_inverse = 1; | ||
5984 | #endif | 7120 | #endif |
5985 | 7121 | ||
5986 | if(mem) sisfb_parm_mem = mem; | ||
5987 | |||
5988 | if(userom != -1) sisfb_userom = userom; | ||
5989 | if(useoem != -1) sisfb_useoem = useoem; | ||
5990 | |||
5991 | if(pdc != -1) sisfb_pdc = (pdc & 0x7f); | ||
5992 | if(pdc1 != -1) sisfb_pdca = (pdc1 & 0x1f); | ||
5993 | |||
5994 | sisfb_nocrt2rate = nocrt2rate; | ||
5995 | |||
5996 | if(specialtiming) | ||
5997 | sisfb_search_specialtiming(specialtiming); | ||
5998 | |||
5999 | if((lvdshl >= 0) && (lvdshl <= 3)) sisfb_lvdshl = lvdshl; | ||
6000 | |||
6001 | if(filter != -1) sisfb_filter = filter; | ||
6002 | |||
6003 | sisfb_tvxposoffset = tvxposoffset; | ||
6004 | sisfb_tvyposoffset = tvyposoffset; | ||
6005 | |||
6006 | #if !defined(__i386__) && !defined(__x86_64__) | ||
6007 | sisfb_resetcard = (resetcard) ? 1 : 0; | ||
6008 | if(videoram) sisfb_videoram = videoram; | ||
6009 | #endif | ||
6010 | |||
6011 | return(sisfb_init()); | ||
6012 | } | ||
6013 | |||
6014 | static void __exit sisfb_remove_module(void) | ||
6015 | { | ||
6016 | pci_unregister_driver(&sisfb_driver); | ||
6017 | printk(KERN_DEBUG "sisfb: Module unloaded\n"); | ||
6018 | } | ||
6019 | |||
6020 | module_init(sisfb_init_module); | ||
6021 | module_exit(sisfb_remove_module); | ||
6022 | |||
6023 | #endif /* /MODULE */ | 7122 | #endif /* /MODULE */ |
6024 | 7123 | ||
7124 | /* _GPL only for new symbols. */ | ||
6025 | EXPORT_SYMBOL(sis_malloc); | 7125 | EXPORT_SYMBOL(sis_malloc); |
6026 | EXPORT_SYMBOL(sis_free); | 7126 | EXPORT_SYMBOL(sis_free); |
7127 | EXPORT_SYMBOL_GPL(sis_malloc_new); | ||
7128 | EXPORT_SYMBOL_GPL(sis_free_new); | ||
7129 | |||
6027 | 7130 | ||
6028 | 7131 | ||