1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * SiS 300/540/630[S]/730[S],
4 * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
5 * XGI V3XT/V5/V8, Z7
6 * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
7 *
8 * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
9 *
10 * Author: Thomas Winischhofer <thomas@winischhofer.net>
11 *
12 * Author of (practically wiped) code base:
13 * SiS (www.sis.com)
14 * Copyright (C) 1999 Silicon Integrated Systems, Inc.
15 *
16 * See http://www.winischhofer.net/ for more information and updates
17 *
18 * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver,
19 * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
20 */
21
22 #include <linux/aperture.h>
23 #include <linux/module.h>
24 #include <linux/moduleparam.h>
25 #include <linux/kernel.h>
26 #include <linux/spinlock.h>
27 #include <linux/errno.h>
28 #include <linux/string.h>
29 #include <linux/mm.h>
30 #include <linux/screen_info.h>
31 #include <linux/slab.h>
32 #include <linux/fb.h>
33 #include <linux/selection.h>
34 #include <linux/ioport.h>
35 #include <linux/init.h>
36 #include <linux/pci.h>
37 #include <linux/vmalloc.h>
38 #include <linux/capability.h>
39 #include <linux/fs.h>
40 #include <linux/types.h>
41 #include <linux/uaccess.h>
42 #include <asm/io.h>
43
44 #include "sis.h"
45 #include "sis_main.h"
46 #include "init301.h"
47
48 #if !defined(CONFIG_FB_SIS_300) && !defined(CONFIG_FB_SIS_315)
49 #warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
50 #warning sisfb will not work!
51 #endif
52
53 /* ---------------------- Prototypes ------------------------- */
54
55 /* Interface used by the world */
56 #ifndef MODULE
57 static int sisfb_setup(char *options);
58 #endif
59
60 /* Interface to the low level console driver */
61 static int sisfb_init(void);
62
63 /* fbdev routines */
64 static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
65 struct fb_info *info);
66
67 static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
68 unsigned long arg);
69 static int sisfb_set_par(struct fb_info *info);
70 static int sisfb_blank(int blank,
71 struct fb_info *info);
72
73 static void sisfb_handle_command(struct sis_video_info *ivideo,
74 struct sisfb_cmd *sisfb_command);
75
76 static void sisfb_search_mode(char *name, bool quiet);
77 static int sisfb_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags);
78 static u8 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate,
79 int index);
80 static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green,
81 unsigned blue, unsigned transp,
82 struct fb_info *fb_info);
83 static int sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
84 struct fb_info *info);
85 static void sisfb_pre_setmode(struct sis_video_info *ivideo);
86 static void sisfb_post_setmode(struct sis_video_info *ivideo);
87 static bool sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
88 static bool sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
89 static bool sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
90 static bool sisfb_bridgeisslave(struct sis_video_info *ivideo);
91 static void sisfb_detect_VB_connect(struct sis_video_info *ivideo);
92 static void sisfb_get_VB_type(struct sis_video_info *ivideo);
93 static void sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val);
94 static void sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val);
95
96 /* Internal heap routines */
97 static int sisfb_heap_init(struct sis_video_info *ivideo);
98 static struct SIS_OH * sisfb_poh_new_node(struct SIS_HEAP *memheap);
99 static struct SIS_OH * sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size);
100 static void sisfb_delete_node(struct SIS_OH *poh);
101 static void sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh);
102 static struct SIS_OH * sisfb_poh_free(struct SIS_HEAP *memheap, u32 base);
103 static void sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh);
104
105
106 /* ------------------ Internal helper routines ----------------- */
107
108 static void __init
sisfb_setdefaultparms(void)109 sisfb_setdefaultparms(void)
110 {
111 sisfb_off = 0;
112 sisfb_parm_mem = 0;
113 sisfb_accel = -1;
114 sisfb_ypan = -1;
115 sisfb_max = -1;
116 sisfb_userom = -1;
117 sisfb_useoem = -1;
118 sisfb_mode_idx = -1;
119 sisfb_parm_rate = -1;
120 sisfb_crt1off = 0;
121 sisfb_forcecrt1 = -1;
122 sisfb_crt2type = -1;
123 sisfb_crt2flags = 0;
124 sisfb_pdc = 0xff;
125 sisfb_pdca = 0xff;
126 sisfb_scalelcd = -1;
127 sisfb_specialtiming = CUT_NONE;
128 sisfb_lvdshl = -1;
129 sisfb_dstn = 0;
130 sisfb_fstn = 0;
131 sisfb_tvplug = -1;
132 sisfb_tvstd = -1;
133 sisfb_tvxposoffset = 0;
134 sisfb_tvyposoffset = 0;
135 sisfb_nocrt2rate = 0;
136 #if !defined(__i386__) && !defined(__x86_64__)
137 sisfb_resetcard = 0;
138 sisfb_videoram = 0;
139 #endif
140 }
141
142 /* ------------- Parameter parsing -------------- */
143
sisfb_search_vesamode(unsigned int vesamode,bool quiet)144 static void sisfb_search_vesamode(unsigned int vesamode, bool quiet)
145 {
146 int i = 0, j = 0;
147
148 /* We don't know the hardware specs yet and there is no ivideo */
149
150 if(vesamode == 0) {
151 if(!quiet)
152 printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
153
154 sisfb_mode_idx = DEFAULT_MODE;
155
156 return;
157 }
158
159 vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
160
161 while(sisbios_mode[i++].mode_no[0] != 0) {
162 if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
163 (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
164 if(sisfb_fstn) {
165 if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
166 sisbios_mode[i-1].mode_no[1] == 0x56 ||
167 sisbios_mode[i-1].mode_no[1] == 0x53)
168 continue;
169 } else {
170 if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
171 sisbios_mode[i-1].mode_no[1] == 0x5b)
172 continue;
173 }
174 sisfb_mode_idx = i - 1;
175 j = 1;
176 break;
177 }
178 }
179 if((!j) && !quiet)
180 printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
181 }
182
sisfb_search_mode(char * name,bool quiet)183 static void sisfb_search_mode(char *name, bool quiet)
184 {
185 unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
186 int i = 0;
187 char strbuf[16], strbuf1[20];
188 char *nameptr = name;
189
190 /* We don't know the hardware specs yet and there is no ivideo */
191
192 if(name == NULL) {
193 if(!quiet)
194 printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
195
196 sisfb_mode_idx = DEFAULT_MODE;
197 return;
198 }
199
200 if(!strncasecmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
201 if(!quiet)
202 printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
203
204 sisfb_mode_idx = DEFAULT_MODE;
205 return;
206 }
207
208 if(strlen(name) <= 19) {
209 strcpy(strbuf1, name);
210 for(i = 0; i < strlen(strbuf1); i++) {
211 if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
212 }
213
214 /* This does some fuzzy mode naming detection */
215 if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
216 if((rate <= 32) || (depth > 32)) {
217 swap(rate, depth);
218 }
219 sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
220 nameptr = strbuf;
221 sisfb_parm_rate = rate;
222 } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
223 sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
224 nameptr = strbuf;
225 } else {
226 xres = 0;
227 if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
228 sprintf(strbuf, "%ux%ux8", xres, yres);
229 nameptr = strbuf;
230 } else {
231 sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
232 return;
233 }
234 }
235 }
236
237 i = 0; j = 0;
238 while(sisbios_mode[i].mode_no[0] != 0) {
239 if(!strncasecmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
240 if(sisfb_fstn) {
241 if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
242 sisbios_mode[i-1].mode_no[1] == 0x56 ||
243 sisbios_mode[i-1].mode_no[1] == 0x53)
244 continue;
245 } else {
246 if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
247 sisbios_mode[i-1].mode_no[1] == 0x5b)
248 continue;
249 }
250 sisfb_mode_idx = i - 1;
251 j = 1;
252 break;
253 }
254 }
255
256 if((!j) && !quiet)
257 printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
258 }
259
260 #ifndef MODULE
sisfb_get_vga_mode_from_kernel(void)261 static void sisfb_get_vga_mode_from_kernel(void)
262 {
263 #ifdef CONFIG_X86
264 char mymode[32];
265 int mydepth = screen_info.lfb_depth;
266
267 if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
268
269 if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) &&
270 (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
271 (mydepth >= 8) && (mydepth <= 32) ) {
272
273 if(mydepth == 24) mydepth = 32;
274
275 sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
276 screen_info.lfb_height,
277 mydepth);
278
279 printk(KERN_DEBUG
280 "sisfb: Using vga mode %s pre-set by kernel as default\n",
281 mymode);
282
283 sisfb_search_mode(mymode, true);
284 }
285 #endif
286 return;
287 }
288 #endif
289
290 static void __init
sisfb_search_crt2type(const char * name)291 sisfb_search_crt2type(const char *name)
292 {
293 int i = 0;
294
295 /* We don't know the hardware specs yet and there is no ivideo */
296
297 if(name == NULL) return;
298
299 while(sis_crt2type[i].type_no != -1) {
300 if(!strncasecmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
301 sisfb_crt2type = sis_crt2type[i].type_no;
302 sisfb_tvplug = sis_crt2type[i].tvplug_no;
303 sisfb_crt2flags = sis_crt2type[i].flags;
304 break;
305 }
306 i++;
307 }
308
309 sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
310 sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
311
312 if(sisfb_crt2type < 0)
313 printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
314 }
315
316 static void __init
sisfb_search_tvstd(const char * name)317 sisfb_search_tvstd(const char *name)
318 {
319 int i = 0;
320
321 /* We don't know the hardware specs yet and there is no ivideo */
322
323 if(name == NULL)
324 return;
325
326 while(sis_tvtype[i].type_no != -1) {
327 if(!strncasecmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
328 sisfb_tvstd = sis_tvtype[i].type_no;
329 break;
330 }
331 i++;
332 }
333 }
334
335 static void __init
sisfb_search_specialtiming(const char * name)336 sisfb_search_specialtiming(const char *name)
337 {
338 int i = 0;
339 bool found = false;
340
341 /* We don't know the hardware specs yet and there is no ivideo */
342
343 if(name == NULL)
344 return;
345
346 if(!strncasecmp(name, "none", 4)) {
347 sisfb_specialtiming = CUT_FORCENONE;
348 printk(KERN_DEBUG "sisfb: Special timing disabled\n");
349 } else {
350 while(mycustomttable[i].chipID != 0) {
351 if(!strncasecmp(name,mycustomttable[i].optionName,
352 strlen(mycustomttable[i].optionName))) {
353 sisfb_specialtiming = mycustomttable[i].SpecialID;
354 found = true;
355 printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
356 mycustomttable[i].vendorName,
357 mycustomttable[i].cardName,
358 mycustomttable[i].optionName);
359 break;
360 }
361 i++;
362 }
363 if(!found) {
364 printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
365 printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
366 i = 0;
367 while(mycustomttable[i].chipID != 0) {
368 printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
369 mycustomttable[i].optionName,
370 mycustomttable[i].vendorName,
371 mycustomttable[i].cardName);
372 i++;
373 }
374 }
375 }
376 }
377
378 /* ----------- Various detection routines ----------- */
379
sisfb_detect_custom_timing(struct sis_video_info * ivideo)380 static void sisfb_detect_custom_timing(struct sis_video_info *ivideo)
381 {
382 unsigned char *biosver = NULL;
383 unsigned char *biosdate = NULL;
384 bool footprint;
385 u32 chksum = 0;
386 int i, j;
387
388 if(ivideo->SiS_Pr.UseROM) {
389 biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06;
390 biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c;
391 for(i = 0; i < 32768; i++)
392 chksum += ivideo->SiS_Pr.VirtualRomBase[i];
393 }
394
395 i = 0;
396 do {
397 if( (mycustomttable[i].chipID == ivideo->chip) &&
398 ((!strlen(mycustomttable[i].biosversion)) ||
399 (ivideo->SiS_Pr.UseROM &&
400 (!strncmp(mycustomttable[i].biosversion, biosver,
401 strlen(mycustomttable[i].biosversion))))) &&
402 ((!strlen(mycustomttable[i].biosdate)) ||
403 (ivideo->SiS_Pr.UseROM &&
404 (!strncmp(mycustomttable[i].biosdate, biosdate,
405 strlen(mycustomttable[i].biosdate))))) &&
406 ((!mycustomttable[i].bioschksum) ||
407 (ivideo->SiS_Pr.UseROM &&
408 (mycustomttable[i].bioschksum == chksum))) &&
409 (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
410 (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
411 footprint = true;
412 for(j = 0; j < 5; j++) {
413 if(mycustomttable[i].biosFootprintAddr[j]) {
414 if(ivideo->SiS_Pr.UseROM) {
415 if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
416 mycustomttable[i].biosFootprintData[j]) {
417 footprint = false;
418 }
419 } else
420 footprint = false;
421 }
422 }
423 if(footprint) {
424 ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
425 printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
426 mycustomttable[i].vendorName,
427 mycustomttable[i].cardName);
428 printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
429 mycustomttable[i].optionName);
430 break;
431 }
432 }
433 i++;
434 } while(mycustomttable[i].chipID);
435 }
436
sisfb_interpret_edid(struct sisfb_monitor * monitor,u8 * buffer)437 static bool sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
438 {
439 int i, j, xres, yres, refresh, index;
440 u32 emodes;
441
442 if(buffer[0] != 0x00 || buffer[1] != 0xff ||
443 buffer[2] != 0xff || buffer[3] != 0xff ||
444 buffer[4] != 0xff || buffer[5] != 0xff ||
445 buffer[6] != 0xff || buffer[7] != 0x00) {
446 printk(KERN_DEBUG "sisfb: Bad EDID header\n");
447 return false;
448 }
449
450 if(buffer[0x12] != 0x01) {
451 printk(KERN_INFO "sisfb: EDID version %d not supported\n",
452 buffer[0x12]);
453 return false;
454 }
455
456 monitor->feature = buffer[0x18];
457
458 if(!(buffer[0x14] & 0x80)) {
459 if(!(buffer[0x14] & 0x08)) {
460 printk(KERN_INFO
461 "sisfb: WARNING: Monitor does not support separate syncs\n");
462 }
463 }
464
465 if(buffer[0x13] >= 0x01) {
466 /* EDID V1 rev 1 and 2: Search for monitor descriptor
467 * to extract ranges
468 */
469 j = 0x36;
470 for(i=0; i<4; i++) {
471 if(buffer[j] == 0x00 && buffer[j + 1] == 0x00 &&
472 buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
473 buffer[j + 4] == 0x00) {
474 monitor->hmin = buffer[j + 7];
475 monitor->hmax = buffer[j + 8];
476 monitor->vmin = buffer[j + 5];
477 monitor->vmax = buffer[j + 6];
478 monitor->dclockmax = buffer[j + 9] * 10 * 1000;
479 monitor->datavalid = true;
480 break;
481 }
482 j += 18;
483 }
484 }
485
486 if(!monitor->datavalid) {
487 /* Otherwise: Get a range from the list of supported
488 * Estabished Timings. This is not entirely accurate,
489 * because fixed frequency monitors are not supported
490 * that way.
491 */
492 monitor->hmin = 65535; monitor->hmax = 0;
493 monitor->vmin = 65535; monitor->vmax = 0;
494 monitor->dclockmax = 0;
495 emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
496 for(i = 0; i < 13; i++) {
497 if(emodes & sisfb_ddcsmodes[i].mask) {
498 if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
499 if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
500 if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
501 if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
502 if(monitor->dclockmax < sisfb_ddcsmodes[i].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
503 }
504 }
505 index = 0x26;
506 for(i = 0; i < 8; i++) {
507 xres = (buffer[index] + 31) * 8;
508 switch(buffer[index + 1] & 0xc0) {
509 case 0xc0: yres = (xres * 9) / 16; break;
510 case 0x80: yres = (xres * 4) / 5; break;
511 case 0x40: yres = (xres * 3) / 4; break;
512 default: yres = xres; break;
513 }
514 refresh = (buffer[index + 1] & 0x3f) + 60;
515 if((xres >= 640) && (yres >= 480)) {
516 for(j = 0; j < 8; j++) {
517 if((xres == sisfb_ddcfmodes[j].x) &&
518 (yres == sisfb_ddcfmodes[j].y) &&
519 (refresh == sisfb_ddcfmodes[j].v)) {
520 if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
521 if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
522 if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
523 if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
524 if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d;
525 }
526 }
527 }
528 index += 2;
529 }
530 if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
531 monitor->datavalid = true;
532 }
533 }
534
535 return monitor->datavalid;
536 }
537
sisfb_handle_ddc(struct sis_video_info * ivideo,struct sisfb_monitor * monitor,int crtno)538 static void sisfb_handle_ddc(struct sis_video_info *ivideo,
539 struct sisfb_monitor *monitor, int crtno)
540 {
541 unsigned short temp, i, realcrtno = crtno;
542 unsigned char buffer[256];
543
544 monitor->datavalid = false;
545
546 if(crtno) {
547 if(ivideo->vbflags & CRT2_LCD) realcrtno = 1;
548 else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
549 else return;
550 }
551
552 if((ivideo->sisfb_crt1off) && (!crtno))
553 return;
554
555 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
556 realcrtno, 0, &buffer[0], ivideo->vbflags2);
557 if((!temp) || (temp == 0xffff)) {
558 printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
559 return;
560 } else {
561 printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
562 printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
563 crtno + 1,
564 (temp & 0x1a) ? "" : "[none of the supported]",
565 (temp & 0x02) ? "2 " : "",
566 (temp & 0x08) ? "D&P" : "",
567 (temp & 0x10) ? "FPDI-2" : "");
568 if(temp & 0x02) {
569 i = 3; /* Number of retrys */
570 do {
571 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
572 realcrtno, 1, &buffer[0], ivideo->vbflags2);
573 } while((temp) && i--);
574 if(!temp) {
575 if(sisfb_interpret_edid(monitor, &buffer[0])) {
576 printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
577 monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
578 monitor->dclockmax / 1000);
579 } else {
580 printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
581 }
582 } else {
583 printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
584 }
585 } else {
586 printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
587 }
588 }
589 }
590
591 /* -------------- Mode validation --------------- */
592
593 static bool
sisfb_verify_rate(struct sis_video_info * ivideo,struct sisfb_monitor * monitor,int mode_idx,int rate_idx,int rate)594 sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
595 int mode_idx, int rate_idx, int rate)
596 {
597 int htotal, vtotal;
598 unsigned int dclock, hsync;
599
600 if(!monitor->datavalid)
601 return true;
602
603 if(mode_idx < 0)
604 return false;
605
606 /* Skip for 320x200, 320x240, 640x400 */
607 switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
608 case 0x59:
609 case 0x41:
610 case 0x4f:
611 case 0x50:
612 case 0x56:
613 case 0x53:
614 case 0x2f:
615 case 0x5d:
616 case 0x5e:
617 return true;
618 #ifdef CONFIG_FB_SIS_315
619 case 0x5a:
620 case 0x5b:
621 if(ivideo->sisvga_engine == SIS_315_VGA) return true;
622 #endif
623 }
624
625 if(rate < (monitor->vmin - 1))
626 return false;
627 if(rate > (monitor->vmax + 1))
628 return false;
629
630 if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
631 sisbios_mode[mode_idx].mode_no[ivideo->mni],
632 &htotal, &vtotal, rate_idx)) {
633 dclock = (htotal * vtotal * rate) / 1000;
634 if(dclock > (monitor->dclockmax + 1000))
635 return false;
636 hsync = dclock / htotal;
637 if(hsync < (monitor->hmin - 1))
638 return false;
639 if(hsync > (monitor->hmax + 1))
640 return false;
641 } else {
642 return false;
643 }
644 return true;
645 }
646
647 static int
sisfb_validate_mode(struct sis_video_info * ivideo,int myindex,u32 vbflags)648 sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
649 {
650 u16 xres=0, yres, myres;
651
652 #ifdef CONFIG_FB_SIS_300
653 if (ivideo->sisvga_engine == SIS_300_VGA) {
654 if (!(sisbios_mode[myindex].chipset & MD_SIS300))
655 return -1 ;
656 }
657 #endif
658 #ifdef CONFIG_FB_SIS_315
659 if (ivideo->sisvga_engine == SIS_315_VGA) {
660 if (!(sisbios_mode[myindex].chipset & MD_SIS315))
661 return -1;
662 }
663 #endif
664
665 myres = sisbios_mode[myindex].yres;
666
667 switch (vbflags & VB_DISPTYPE_DISP2) {
668
669 case CRT2_LCD:
670 xres = ivideo->lcdxres; yres = ivideo->lcdyres;
671
672 if ((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
673 (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
674 if (sisbios_mode[myindex].xres > xres)
675 return -1;
676 if (myres > yres)
677 return -1;
678 }
679
680 if (ivideo->sisfb_fstn) {
681 if (sisbios_mode[myindex].xres == 320) {
682 if (myres == 240) {
683 switch (sisbios_mode[myindex].mode_no[1]) {
684 case 0x50: myindex = MODE_FSTN_8; break;
685 case 0x56: myindex = MODE_FSTN_16; break;
686 case 0x53: return -1;
687 }
688 }
689 }
690 }
691
692 if (SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
693 sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
694 ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
695 return -1;
696 }
697 break;
698
699 case CRT2_TV:
700 if (SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
701 sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
702 return -1;
703 }
704 break;
705
706 case CRT2_VGA:
707 if (SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
708 sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
709 return -1;
710 }
711 break;
712 }
713
714 return myindex;
715 }
716
717 static u8
sisfb_search_refresh_rate(struct sis_video_info * ivideo,unsigned int rate,int mode_idx)718 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
719 {
720 int i = 0;
721 u16 xres = sisbios_mode[mode_idx].xres;
722 u16 yres = sisbios_mode[mode_idx].yres;
723
724 ivideo->rate_idx = 0;
725 while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
726 if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
727 if(sisfb_vrate[i].refresh == rate) {
728 ivideo->rate_idx = sisfb_vrate[i].idx;
729 break;
730 } else if(sisfb_vrate[i].refresh > rate) {
731 if((sisfb_vrate[i].refresh - rate) <= 3) {
732 DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
733 rate, sisfb_vrate[i].refresh);
734 ivideo->rate_idx = sisfb_vrate[i].idx;
735 ivideo->refresh_rate = sisfb_vrate[i].refresh;
736 } else if((sisfb_vrate[i].idx != 1) &&
737 ((rate - sisfb_vrate[i-1].refresh) <= 2)) {
738 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
739 rate, sisfb_vrate[i-1].refresh);
740 ivideo->rate_idx = sisfb_vrate[i-1].idx;
741 ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
742 }
743 break;
744 } else if((rate - sisfb_vrate[i].refresh) <= 2) {
745 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
746 rate, sisfb_vrate[i].refresh);
747 ivideo->rate_idx = sisfb_vrate[i].idx;
748 break;
749 }
750 }
751 i++;
752 }
753 if(ivideo->rate_idx > 0) {
754 return ivideo->rate_idx;
755 } else {
756 printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n",
757 rate, xres, yres);
758 return 0;
759 }
760 }
761
762 static bool
sisfb_bridgeisslave(struct sis_video_info * ivideo)763 sisfb_bridgeisslave(struct sis_video_info *ivideo)
764 {
765 unsigned char P1_00;
766
767 if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
768 return false;
769
770 P1_00 = SiS_GetReg(SISPART1, 0x00);
771 if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
772 ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
773 return true;
774 } else {
775 return false;
776 }
777 }
778
779 static bool
sisfballowretracecrt1(struct sis_video_info * ivideo)780 sisfballowretracecrt1(struct sis_video_info *ivideo)
781 {
782 u8 temp;
783
784 temp = SiS_GetReg(SISCR, 0x17);
785 if(!(temp & 0x80))
786 return false;
787
788 temp = SiS_GetReg(SISSR, 0x1f);
789 if(temp & 0xc0)
790 return false;
791
792 return true;
793 }
794
795 static bool
sisfbcheckvretracecrt1(struct sis_video_info * ivideo)796 sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
797 {
798 if(!sisfballowretracecrt1(ivideo))
799 return false;
800
801 if (SiS_GetRegByte(SISINPSTAT) & 0x08)
802 return true;
803 else
804 return false;
805 }
806
807 static void
sisfbwaitretracecrt1(struct sis_video_info * ivideo)808 sisfbwaitretracecrt1(struct sis_video_info *ivideo)
809 {
810 int watchdog;
811
812 if(!sisfballowretracecrt1(ivideo))
813 return;
814
815 watchdog = 65536;
816 while ((!(SiS_GetRegByte(SISINPSTAT) & 0x08)) && --watchdog);
817 watchdog = 65536;
818 while ((SiS_GetRegByte(SISINPSTAT) & 0x08) && --watchdog);
819 }
820
821 static bool
sisfbcheckvretracecrt2(struct sis_video_info * ivideo)822 sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
823 {
824 unsigned char temp, reg;
825
826 switch(ivideo->sisvga_engine) {
827 case SIS_300_VGA: reg = 0x25; break;
828 case SIS_315_VGA: reg = 0x30; break;
829 default: return false;
830 }
831
832 temp = SiS_GetReg(SISPART1, reg);
833 if(temp & 0x02)
834 return true;
835 else
836 return false;
837 }
838
839 static bool
sisfb_CheckVBRetrace(struct sis_video_info * ivideo)840 sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
841 {
842 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
843 if(!sisfb_bridgeisslave(ivideo)) {
844 return sisfbcheckvretracecrt2(ivideo);
845 }
846 }
847 return sisfbcheckvretracecrt1(ivideo);
848 }
849
850 static u32
sisfb_setupvbblankflags(struct sis_video_info * ivideo,u32 * vcount,u32 * hcount)851 sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
852 {
853 u8 idx, reg1, reg2, reg3, reg4;
854 u32 ret = 0;
855
856 (*vcount) = (*hcount) = 0;
857
858 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
859
860 ret |= (FB_VBLANK_HAVE_VSYNC |
861 FB_VBLANK_HAVE_HBLANK |
862 FB_VBLANK_HAVE_VBLANK |
863 FB_VBLANK_HAVE_VCOUNT |
864 FB_VBLANK_HAVE_HCOUNT);
865 switch(ivideo->sisvga_engine) {
866 case SIS_300_VGA: idx = 0x25; break;
867 default:
868 case SIS_315_VGA: idx = 0x30; break;
869 }
870 reg1 = SiS_GetReg(SISPART1, (idx+0)); /* 30 */
871 reg2 = SiS_GetReg(SISPART1, (idx+1)); /* 31 */
872 reg3 = SiS_GetReg(SISPART1, (idx+2)); /* 32 */
873 reg4 = SiS_GetReg(SISPART1, (idx+3)); /* 33 */
874 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
875 if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
876 if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
877 (*vcount) = reg3 | ((reg4 & 0x70) << 4);
878 (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
879
880 } else if(sisfballowretracecrt1(ivideo)) {
881
882 ret |= (FB_VBLANK_HAVE_VSYNC |
883 FB_VBLANK_HAVE_VBLANK |
884 FB_VBLANK_HAVE_VCOUNT |
885 FB_VBLANK_HAVE_HCOUNT);
886 reg1 = SiS_GetRegByte(SISINPSTAT);
887 if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
888 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
889 reg1 = SiS_GetReg(SISCR, 0x20);
890 reg1 = SiS_GetReg(SISCR, 0x1b);
891 reg2 = SiS_GetReg(SISCR, 0x1c);
892 reg3 = SiS_GetReg(SISCR, 0x1d);
893 (*vcount) = reg2 | ((reg3 & 0x07) << 8);
894 (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
895 }
896
897 return ret;
898 }
899
900 static int
sisfb_myblank(struct sis_video_info * ivideo,int blank)901 sisfb_myblank(struct sis_video_info *ivideo, int blank)
902 {
903 u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
904 bool backlight = true;
905
906 switch(blank) {
907 case FB_BLANK_UNBLANK: /* on */
908 sr01 = 0x00;
909 sr11 = 0x00;
910 sr1f = 0x00;
911 cr63 = 0x00;
912 p2_0 = 0x20;
913 p1_13 = 0x00;
914 backlight = true;
915 break;
916 case FB_BLANK_NORMAL: /* blank */
917 sr01 = 0x20;
918 sr11 = 0x00;
919 sr1f = 0x00;
920 cr63 = 0x00;
921 p2_0 = 0x20;
922 p1_13 = 0x00;
923 backlight = true;
924 break;
925 case FB_BLANK_VSYNC_SUSPEND: /* no vsync */
926 sr01 = 0x20;
927 sr11 = 0x08;
928 sr1f = 0x80;
929 cr63 = 0x40;
930 p2_0 = 0x40;
931 p1_13 = 0x80;
932 backlight = false;
933 break;
934 case FB_BLANK_HSYNC_SUSPEND: /* no hsync */
935 sr01 = 0x20;
936 sr11 = 0x08;
937 sr1f = 0x40;
938 cr63 = 0x40;
939 p2_0 = 0x80;
940 p1_13 = 0x40;
941 backlight = false;
942 break;
943 case FB_BLANK_POWERDOWN: /* off */
944 sr01 = 0x20;
945 sr11 = 0x08;
946 sr1f = 0xc0;
947 cr63 = 0x40;
948 p2_0 = 0xc0;
949 p1_13 = 0xc0;
950 backlight = false;
951 break;
952 default:
953 return 1;
954 }
955
956 if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
957
958 if( (!ivideo->sisfb_thismonitor.datavalid) ||
959 ((ivideo->sisfb_thismonitor.datavalid) &&
960 (ivideo->sisfb_thismonitor.feature & 0xe0))) {
961
962 if(ivideo->sisvga_engine == SIS_315_VGA) {
963 SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
964 }
965
966 if(!(sisfb_bridgeisslave(ivideo))) {
967 SiS_SetRegANDOR(SISSR, 0x01, ~0x20, sr01);
968 SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, sr1f);
969 }
970 }
971
972 }
973
974 if(ivideo->currentvbflags & CRT2_LCD) {
975
976 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
977 if(backlight) {
978 SiS_SiS30xBLOn(&ivideo->SiS_Pr);
979 } else {
980 SiS_SiS30xBLOff(&ivideo->SiS_Pr);
981 }
982 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
983 #ifdef CONFIG_FB_SIS_315
984 if(ivideo->vbflags2 & VB2_CHRONTEL) {
985 if(backlight) {
986 SiS_Chrontel701xBLOn(&ivideo->SiS_Pr);
987 } else {
988 SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
989 }
990 }
991 #endif
992 }
993
994 if(((ivideo->sisvga_engine == SIS_300_VGA) &&
995 (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
996 ((ivideo->sisvga_engine == SIS_315_VGA) &&
997 ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
998 SiS_SetRegANDOR(SISSR, 0x11, ~0x0c, sr11);
999 }
1000
1001 if(ivideo->sisvga_engine == SIS_300_VGA) {
1002 if((ivideo->vbflags2 & VB2_30xB) &&
1003 (!(ivideo->vbflags2 & VB2_30xBDH))) {
1004 SiS_SetRegANDOR(SISPART1, 0x13, 0x3f, p1_13);
1005 }
1006 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
1007 if((ivideo->vbflags2 & VB2_30xB) &&
1008 (!(ivideo->vbflags2 & VB2_30xBDH))) {
1009 SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
1010 }
1011 }
1012
1013 } else if(ivideo->currentvbflags & CRT2_VGA) {
1014
1015 if(ivideo->vbflags2 & VB2_30xB) {
1016 SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
1017 }
1018
1019 }
1020
1021 return 0;
1022 }
1023
1024 /* ------------- Callbacks from init.c/init301.c -------------- */
1025
1026 #ifdef CONFIG_FB_SIS_300
1027 unsigned int
sisfb_read_nbridge_pci_dword(struct SiS_Private * SiS_Pr,int reg)1028 sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg)
1029 {
1030 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1031 u32 val = 0;
1032
1033 pci_read_config_dword(ivideo->nbridge, reg, &val);
1034 return (unsigned int)val;
1035 }
1036
1037 void
sisfb_write_nbridge_pci_dword(struct SiS_Private * SiS_Pr,int reg,unsigned int val)1038 sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val)
1039 {
1040 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1041
1042 pci_write_config_dword(ivideo->nbridge, reg, (u32)val);
1043 }
1044
1045 unsigned int
sisfb_read_lpc_pci_dword(struct SiS_Private * SiS_Pr,int reg)1046 sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg)
1047 {
1048 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1049 u32 val = 0;
1050
1051 if(!ivideo->lpcdev) return 0;
1052
1053 pci_read_config_dword(ivideo->lpcdev, reg, &val);
1054 return (unsigned int)val;
1055 }
1056 #endif
1057
1058 #ifdef CONFIG_FB_SIS_315
1059 void
sisfb_write_nbridge_pci_byte(struct SiS_Private * SiS_Pr,int reg,unsigned char val)1060 sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val)
1061 {
1062 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1063
1064 pci_write_config_byte(ivideo->nbridge, reg, (u8)val);
1065 }
1066
1067 unsigned int
sisfb_read_mio_pci_word(struct SiS_Private * SiS_Pr,int reg)1068 sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg)
1069 {
1070 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1071 u16 val = 0;
1072
1073 if(!ivideo->lpcdev) return 0;
1074
1075 pci_read_config_word(ivideo->lpcdev, reg, &val);
1076 return (unsigned int)val;
1077 }
1078 #endif
1079
1080 /* ----------- FBDev related routines for all series ----------- */
1081
1082 static int
sisfb_get_cmap_len(const struct fb_var_screeninfo * var)1083 sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
1084 {
1085 return (var->bits_per_pixel == 8) ? 256 : 16;
1086 }
1087
1088 static void
sisfb_set_vparms(struct sis_video_info * ivideo)1089 sisfb_set_vparms(struct sis_video_info *ivideo)
1090 {
1091 switch(ivideo->video_bpp) {
1092 case 8:
1093 ivideo->DstColor = 0x0000;
1094 ivideo->SiS310_AccelDepth = 0x00000000;
1095 ivideo->video_cmap_len = 256;
1096 break;
1097 case 16:
1098 ivideo->DstColor = 0x8000;
1099 ivideo->SiS310_AccelDepth = 0x00010000;
1100 ivideo->video_cmap_len = 16;
1101 break;
1102 case 32:
1103 ivideo->DstColor = 0xC000;
1104 ivideo->SiS310_AccelDepth = 0x00020000;
1105 ivideo->video_cmap_len = 16;
1106 break;
1107 default:
1108 ivideo->video_cmap_len = 16;
1109 printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
1110 ivideo->accel = 0;
1111 }
1112 }
1113
1114 static int
sisfb_calc_maxyres(struct sis_video_info * ivideo,struct fb_var_screeninfo * var)1115 sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1116 {
1117 int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3));
1118
1119 if(maxyres > 32767) maxyres = 32767;
1120
1121 return maxyres;
1122 }
1123
1124 static void
sisfb_calc_pitch(struct sis_video_info * ivideo,struct fb_var_screeninfo * var)1125 sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1126 {
1127 ivideo->video_linelength = var->xres_virtual * (var->bits_per_pixel >> 3);
1128 ivideo->scrnpitchCRT1 = ivideo->video_linelength;
1129 if(!(ivideo->currentvbflags & CRT1_LCDA)) {
1130 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1131 ivideo->scrnpitchCRT1 <<= 1;
1132 }
1133 }
1134 }
1135
1136 static void
sisfb_set_pitch(struct sis_video_info * ivideo)1137 sisfb_set_pitch(struct sis_video_info *ivideo)
1138 {
1139 bool isslavemode = false;
1140 unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
1141 unsigned short HDisplay2 = ivideo->video_linelength >> 3;
1142
1143 if(sisfb_bridgeisslave(ivideo)) isslavemode = true;
1144
1145 /* We need to set pitch for CRT1 if bridge is in slave mode, too */
1146 if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
1147 SiS_SetReg(SISCR, 0x13, (HDisplay1 & 0xFF));
1148 SiS_SetRegANDOR(SISSR, 0x0E, 0xF0, (HDisplay1 >> 8));
1149 }
1150
1151 /* We must not set the pitch for CRT2 if bridge is in slave mode */
1152 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
1153 SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
1154 SiS_SetReg(SISPART1, 0x07, (HDisplay2 & 0xFF));
1155 SiS_SetRegANDOR(SISPART1, 0x09, 0xF0, (HDisplay2 >> 8));
1156 }
1157 }
1158
1159 static void
sisfb_bpp_to_var(struct sis_video_info * ivideo,struct fb_var_screeninfo * var)1160 sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1161 {
1162 ivideo->video_cmap_len = sisfb_get_cmap_len(var);
1163
1164 switch(var->bits_per_pixel) {
1165 case 8:
1166 var->red.offset = var->green.offset = var->blue.offset = 0;
1167 var->red.length = var->green.length = var->blue.length = 8;
1168 break;
1169 case 16:
1170 var->red.offset = 11;
1171 var->red.length = 5;
1172 var->green.offset = 5;
1173 var->green.length = 6;
1174 var->blue.offset = 0;
1175 var->blue.length = 5;
1176 var->transp.offset = 0;
1177 var->transp.length = 0;
1178 break;
1179 case 32:
1180 var->red.offset = 16;
1181 var->red.length = 8;
1182 var->green.offset = 8;
1183 var->green.length = 8;
1184 var->blue.offset = 0;
1185 var->blue.length = 8;
1186 var->transp.offset = 24;
1187 var->transp.length = 8;
1188 break;
1189 }
1190 }
1191
1192 static int
sisfb_set_mode(struct sis_video_info * ivideo,int clrscrn)1193 sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
1194 {
1195 unsigned short modeno = ivideo->mode_no;
1196
1197 /* >=2.6.12's fbcon clears the screen anyway */
1198 modeno |= 0x80;
1199
1200 SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1201
1202 sisfb_pre_setmode(ivideo);
1203
1204 if(!SiSSetMode(&ivideo->SiS_Pr, modeno)) {
1205 printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
1206 return -EINVAL;
1207 }
1208
1209 SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1210
1211 sisfb_post_setmode(ivideo);
1212
1213 return 0;
1214 }
1215
1216
1217 static int
sisfb_do_set_var(struct fb_var_screeninfo * var,int isactive,struct fb_info * info)1218 sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
1219 {
1220 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1221 unsigned int htotal = 0, vtotal = 0;
1222 unsigned int drate = 0, hrate = 0;
1223 int found_mode = 0, ret;
1224 int old_mode;
1225 u32 pixclock;
1226
1227 htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1228
1229 vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1230
1231 pixclock = var->pixclock;
1232
1233 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1234 vtotal += var->yres;
1235 vtotal <<= 1;
1236 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1237 vtotal += var->yres;
1238 vtotal <<= 2;
1239 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1240 vtotal += var->yres;
1241 vtotal <<= 1;
1242 } else vtotal += var->yres;
1243
1244 if(!(htotal) || !(vtotal)) {
1245 DPRINTK("sisfb: Invalid 'var' information\n");
1246 return -EINVAL;
1247 }
1248
1249 if(pixclock && htotal && vtotal) {
1250 drate = 1000000000 / pixclock;
1251 hrate = (drate * 1000) / htotal;
1252 ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1253 } else {
1254 ivideo->refresh_rate = 60;
1255 }
1256
1257 old_mode = ivideo->sisfb_mode_idx;
1258 ivideo->sisfb_mode_idx = 0;
1259
1260 while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) &&
1261 (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) {
1262 if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) &&
1263 (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) &&
1264 (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) {
1265 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1266 found_mode = 1;
1267 break;
1268 }
1269 ivideo->sisfb_mode_idx++;
1270 }
1271
1272 if(found_mode) {
1273 ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
1274 ivideo->sisfb_mode_idx, ivideo->currentvbflags);
1275 } else {
1276 ivideo->sisfb_mode_idx = -1;
1277 }
1278
1279 if(ivideo->sisfb_mode_idx < 0) {
1280 printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres,
1281 var->yres, var->bits_per_pixel);
1282 ivideo->sisfb_mode_idx = old_mode;
1283 return -EINVAL;
1284 }
1285
1286 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1287
1288 if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
1289 ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
1290 ivideo->refresh_rate = 60;
1291 }
1292
1293 if(isactive) {
1294 /* If acceleration to be used? Need to know
1295 * before pre/post_set_mode()
1296 */
1297 ivideo->accel = 0;
1298 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
1299 #ifdef STUPID_ACCELF_TEXT_SHIT
1300 if(var->accel_flags & FB_ACCELF_TEXT) {
1301 info->flags &= ~FBINFO_HWACCEL_DISABLED;
1302 } else {
1303 info->flags |= FBINFO_HWACCEL_DISABLED;
1304 }
1305 #endif
1306 if(!(info->flags & FBINFO_HWACCEL_DISABLED)) ivideo->accel = -1;
1307 #else
1308 if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
1309 #endif
1310
1311 if((ret = sisfb_set_mode(ivideo, 1))) {
1312 return ret;
1313 }
1314
1315 ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
1316 ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
1317 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
1318
1319 sisfb_calc_pitch(ivideo, var);
1320 sisfb_set_pitch(ivideo);
1321
1322 sisfb_set_vparms(ivideo);
1323
1324 ivideo->current_width = ivideo->video_width;
1325 ivideo->current_height = ivideo->video_height;
1326 ivideo->current_bpp = ivideo->video_bpp;
1327 ivideo->current_htotal = htotal;
1328 ivideo->current_vtotal = vtotal;
1329 ivideo->current_linelength = ivideo->video_linelength;
1330 ivideo->current_pixclock = var->pixclock;
1331 ivideo->current_refresh_rate = ivideo->refresh_rate;
1332 ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
1333 }
1334
1335 return 0;
1336 }
1337
1338 static void
sisfb_set_base_CRT1(struct sis_video_info * ivideo,unsigned int base)1339 sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
1340 {
1341 SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1342
1343 SiS_SetReg(SISCR, 0x0D, base & 0xFF);
1344 SiS_SetReg(SISCR, 0x0C, (base >> 8) & 0xFF);
1345 SiS_SetReg(SISSR, 0x0D, (base >> 16) & 0xFF);
1346 if(ivideo->sisvga_engine == SIS_315_VGA) {
1347 SiS_SetRegANDOR(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
1348 }
1349 }
1350
1351 static void
sisfb_set_base_CRT2(struct sis_video_info * ivideo,unsigned int base)1352 sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
1353 {
1354 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1355 SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
1356 SiS_SetReg(SISPART1, 0x06, (base & 0xFF));
1357 SiS_SetReg(SISPART1, 0x05, ((base >> 8) & 0xFF));
1358 SiS_SetReg(SISPART1, 0x04, ((base >> 16) & 0xFF));
1359 if(ivideo->sisvga_engine == SIS_315_VGA) {
1360 SiS_SetRegANDOR(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1361 }
1362 }
1363 }
1364
1365 static int
sisfb_pan_var(struct sis_video_info * ivideo,struct fb_info * info,struct fb_var_screeninfo * var)1366 sisfb_pan_var(struct sis_video_info *ivideo, struct fb_info *info,
1367 struct fb_var_screeninfo *var)
1368 {
1369 ivideo->current_base = var->yoffset * info->var.xres_virtual
1370 + var->xoffset;
1371
1372 /* calculate base bpp dep. */
1373 switch (info->var.bits_per_pixel) {
1374 case 32:
1375 break;
1376 case 16:
1377 ivideo->current_base >>= 1;
1378 break;
1379 case 8:
1380 default:
1381 ivideo->current_base >>= 2;
1382 break;
1383 }
1384
1385 ivideo->current_base += (ivideo->video_offset >> 2);
1386
1387 sisfb_set_base_CRT1(ivideo, ivideo->current_base);
1388 sisfb_set_base_CRT2(ivideo, ivideo->current_base);
1389
1390 return 0;
1391 }
1392
1393 static int
sisfb_open(struct fb_info * info,int user)1394 sisfb_open(struct fb_info *info, int user)
1395 {
1396 return 0;
1397 }
1398
1399 static int
sisfb_release(struct fb_info * info,int user)1400 sisfb_release(struct fb_info *info, int user)
1401 {
1402 return 0;
1403 }
1404
1405 static int
sisfb_setcolreg(unsigned regno,unsigned red,unsigned green,unsigned blue,unsigned transp,struct fb_info * info)1406 sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
1407 unsigned transp, struct fb_info *info)
1408 {
1409 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1410
1411 if(regno >= sisfb_get_cmap_len(&info->var))
1412 return 1;
1413
1414 switch(info->var.bits_per_pixel) {
1415 case 8:
1416 SiS_SetRegByte(SISDACA, regno);
1417 SiS_SetRegByte(SISDACD, (red >> 10));
1418 SiS_SetRegByte(SISDACD, (green >> 10));
1419 SiS_SetRegByte(SISDACD, (blue >> 10));
1420 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1421 SiS_SetRegByte(SISDAC2A, regno);
1422 SiS_SetRegByte(SISDAC2D, (red >> 8));
1423 SiS_SetRegByte(SISDAC2D, (green >> 8));
1424 SiS_SetRegByte(SISDAC2D, (blue >> 8));
1425 }
1426 break;
1427 case 16:
1428 if (regno >= 16)
1429 break;
1430
1431 ((u32 *)(info->pseudo_palette))[regno] =
1432 (red & 0xf800) |
1433 ((green & 0xfc00) >> 5) |
1434 ((blue & 0xf800) >> 11);
1435 break;
1436 case 32:
1437 if (regno >= 16)
1438 break;
1439
1440 red >>= 8;
1441 green >>= 8;
1442 blue >>= 8;
1443 ((u32 *)(info->pseudo_palette))[regno] =
1444 (red << 16) | (green << 8) | (blue);
1445 break;
1446 }
1447 return 0;
1448 }
1449
1450 static int
sisfb_set_par(struct fb_info * info)1451 sisfb_set_par(struct fb_info *info)
1452 {
1453 int err;
1454
1455 if((err = sisfb_do_set_var(&info->var, 1, info)))
1456 return err;
1457
1458 sisfb_get_fix(&info->fix, -1, info);
1459
1460 return 0;
1461 }
1462
1463 static int
sisfb_check_var(struct fb_var_screeninfo * var,struct fb_info * info)1464 sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1465 {
1466 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1467 unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
1468 unsigned int drate = 0, hrate = 0, maxyres;
1469 int found_mode = 0;
1470 int refresh_rate, search_idx, tidx;
1471 bool recalc_clock = false;
1472 u32 pixclock;
1473
1474 htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1475
1476 vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1477
1478 pixclock = var->pixclock;
1479
1480 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1481 vtotal += var->yres;
1482 vtotal <<= 1;
1483 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1484 vtotal += var->yres;
1485 vtotal <<= 2;
1486 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1487 vtotal += var->yres;
1488 vtotal <<= 1;
1489 } else
1490 vtotal += var->yres;
1491
1492 if(!(htotal) || !(vtotal)) {
1493 SISFAIL("sisfb: no valid timing data");
1494 }
1495
1496 search_idx = 0;
1497 while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
1498 (sisbios_mode[search_idx].xres <= var->xres) ) {
1499 if( (sisbios_mode[search_idx].xres == var->xres) &&
1500 (sisbios_mode[search_idx].yres == var->yres) &&
1501 (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1502 if((tidx = sisfb_validate_mode(ivideo, search_idx,
1503 ivideo->currentvbflags)) > 0) {
1504 found_mode = 1;
1505 search_idx = tidx;
1506 break;
1507 }
1508 }
1509 search_idx++;
1510 }
1511
1512 if(!found_mode) {
1513 search_idx = 0;
1514 while(sisbios_mode[search_idx].mode_no[0] != 0) {
1515 if( (var->xres <= sisbios_mode[search_idx].xres) &&
1516 (var->yres <= sisbios_mode[search_idx].yres) &&
1517 (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
1518 if((tidx = sisfb_validate_mode(ivideo,search_idx,
1519 ivideo->currentvbflags)) > 0) {
1520 found_mode = 1;
1521 search_idx = tidx;
1522 break;
1523 }
1524 }
1525 search_idx++;
1526 }
1527 if(found_mode) {
1528 printk(KERN_DEBUG
1529 "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
1530 var->xres, var->yres, var->bits_per_pixel,
1531 sisbios_mode[search_idx].xres,
1532 sisbios_mode[search_idx].yres,
1533 var->bits_per_pixel);
1534 var->xres = sisbios_mode[search_idx].xres;
1535 var->yres = sisbios_mode[search_idx].yres;
1536 } else {
1537 printk(KERN_ERR
1538 "sisfb: Failed to find supported mode near %dx%dx%d\n",
1539 var->xres, var->yres, var->bits_per_pixel);
1540 return -EINVAL;
1541 }
1542 }
1543
1544 if( ((ivideo->vbflags2 & VB2_LVDS) ||
1545 ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
1546 (var->bits_per_pixel == 8) ) {
1547 /* Slave modes on LVDS and 301B-DH */
1548 refresh_rate = 60;
1549 recalc_clock = true;
1550 } else if( (ivideo->current_htotal == htotal) &&
1551 (ivideo->current_vtotal == vtotal) &&
1552 (ivideo->current_pixclock == pixclock) ) {
1553 /* x=x & y=y & c=c -> assume depth change */
1554 drate = 1000000000 / pixclock;
1555 hrate = (drate * 1000) / htotal;
1556 refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1557 } else if( ( (ivideo->current_htotal != htotal) ||
1558 (ivideo->current_vtotal != vtotal) ) &&
1559 (ivideo->current_pixclock == var->pixclock) ) {
1560 /* x!=x | y!=y & c=c -> invalid pixclock */
1561 if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
1562 refresh_rate =
1563 ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
1564 } else if(ivideo->sisfb_parm_rate != -1) {
1565 /* Sic, sisfb_parm_rate - want to know originally desired rate here */
1566 refresh_rate = ivideo->sisfb_parm_rate;
1567 } else {
1568 refresh_rate = 60;
1569 }
1570 recalc_clock = true;
1571 } else if((pixclock) && (htotal) && (vtotal)) {
1572 drate = 1000000000 / pixclock;
1573 hrate = (drate * 1000) / htotal;
1574 refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1575 } else if(ivideo->current_refresh_rate) {
1576 refresh_rate = ivideo->current_refresh_rate;
1577 recalc_clock = true;
1578 } else {
1579 refresh_rate = 60;
1580 recalc_clock = true;
1581 }
1582
1583 myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
1584
1585 /* Eventually recalculate timing and clock */
1586 if(recalc_clock) {
1587 if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
1588 var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
1589 sisbios_mode[search_idx].mode_no[ivideo->mni],
1590 myrateindex));
1591 sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr,
1592 sisbios_mode[search_idx].mode_no[ivideo->mni],
1593 myrateindex, var);
1594 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1595 var->pixclock <<= 1;
1596 }
1597 }
1598
1599 if(ivideo->sisfb_thismonitor.datavalid) {
1600 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
1601 myrateindex, refresh_rate)) {
1602 printk(KERN_INFO
1603 "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1604 }
1605 }
1606
1607 /* Adapt RGB settings */
1608 sisfb_bpp_to_var(ivideo, var);
1609
1610 if(var->xres > var->xres_virtual)
1611 var->xres_virtual = var->xres;
1612
1613 if(ivideo->sisfb_ypan) {
1614 maxyres = sisfb_calc_maxyres(ivideo, var);
1615 if(ivideo->sisfb_max) {
1616 var->yres_virtual = maxyres;
1617 } else {
1618 if(var->yres_virtual > maxyres) {
1619 var->yres_virtual = maxyres;
1620 }
1621 }
1622 if(var->yres_virtual <= var->yres) {
1623 var->yres_virtual = var->yres;
1624 }
1625 } else {
1626 if(var->yres != var->yres_virtual) {
1627 var->yres_virtual = var->yres;
1628 }
1629 var->xoffset = 0;
1630 var->yoffset = 0;
1631 }
1632
1633 /* Truncate offsets to maximum if too high */
1634 if(var->xoffset > var->xres_virtual - var->xres) {
1635 var->xoffset = var->xres_virtual - var->xres - 1;
1636 }
1637
1638 if(var->yoffset > var->yres_virtual - var->yres) {
1639 var->yoffset = var->yres_virtual - var->yres - 1;
1640 }
1641
1642 /* Set everything else to 0 */
1643 var->red.msb_right =
1644 var->green.msb_right =
1645 var->blue.msb_right =
1646 var->transp.offset =
1647 var->transp.length =
1648 var->transp.msb_right = 0;
1649
1650 return 0;
1651 }
1652
1653 static int
sisfb_pan_display(struct fb_var_screeninfo * var,struct fb_info * info)1654 sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
1655 {
1656 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1657 int err;
1658
1659 if (var->vmode & FB_VMODE_YWRAP)
1660 return -EINVAL;
1661
1662 if (var->xoffset + info->var.xres > info->var.xres_virtual ||
1663 var->yoffset + info->var.yres > info->var.yres_virtual)
1664 return -EINVAL;
1665
1666 err = sisfb_pan_var(ivideo, info, var);
1667 if (err < 0)
1668 return err;
1669
1670 info->var.xoffset = var->xoffset;
1671 info->var.yoffset = var->yoffset;
1672
1673 return 0;
1674 }
1675
1676 static int
sisfb_blank(int blank,struct fb_info * info)1677 sisfb_blank(int blank, struct fb_info *info)
1678 {
1679 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1680
1681 return sisfb_myblank(ivideo, blank);
1682 }
1683
1684 /* ----------- FBDev related routines for all series ---------- */
1685
sisfb_ioctl(struct fb_info * info,unsigned int cmd,unsigned long arg)1686 static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
1687 unsigned long arg)
1688 {
1689 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1690 struct sis_memreq sismemreq;
1691 struct fb_vblank sisvbblank;
1692 u32 gpu32 = 0;
1693 #ifndef __user
1694 #define __user
1695 #endif
1696 u32 __user *argp = (u32 __user *)arg;
1697
1698 switch(cmd) {
1699 case FBIO_ALLOC:
1700 if(!capable(CAP_SYS_RAWIO))
1701 return -EPERM;
1702
1703 if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))
1704 return -EFAULT;
1705
1706 sis_malloc(&sismemreq);
1707
1708 if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
1709 sis_free((u32)sismemreq.offset);
1710 return -EFAULT;
1711 }
1712 break;
1713
1714 case FBIO_FREE:
1715 if(!capable(CAP_SYS_RAWIO))
1716 return -EPERM;
1717
1718 if(get_user(gpu32, argp))
1719 return -EFAULT;
1720
1721 sis_free(gpu32);
1722 break;
1723
1724 case FBIOGET_VBLANK:
1725
1726 memset(&sisvbblank, 0, sizeof(struct fb_vblank));
1727
1728 sisvbblank.count = 0;
1729 sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
1730
1731 if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))
1732 return -EFAULT;
1733
1734 break;
1735
1736 case SISFB_GET_INFO_SIZE:
1737 return put_user(sizeof(struct sisfb_info), argp);
1738
1739 case SISFB_GET_INFO_OLD:
1740 if(ivideo->warncount++ < 10)
1741 printk(KERN_INFO
1742 "sisfb: Deprecated ioctl call received - update your application!\n");
1743 fallthrough;
1744 case SISFB_GET_INFO: /* For communication with X driver */
1745 ivideo->sisfb_infoblock.sisfb_id = SISFB_ID;
1746 ivideo->sisfb_infoblock.sisfb_version = VER_MAJOR;
1747 ivideo->sisfb_infoblock.sisfb_revision = VER_MINOR;
1748 ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;
1749 ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;
1750 ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;
1751 ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;
1752 ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;
1753 if(ivideo->modechanged) {
1754 ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;
1755 } else {
1756 ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;
1757 }
1758 ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;
1759 ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;
1760 ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;
1761 ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;
1762 ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;
1763 ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;
1764 ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;
1765 ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;
1766 ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;
1767 ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;
1768 ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
1769 ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
1770 ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
1771 ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
1772 ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
1773 ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
1774 ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
1775 ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
1776 ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
1777 ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
1778 ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;
1779 ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;
1780 ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;
1781 ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;
1782 ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;
1783 ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;
1784 ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;
1785 ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;
1786
1787 if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,
1788 sizeof(ivideo->sisfb_infoblock)))
1789 return -EFAULT;
1790
1791 break;
1792
1793 case SISFB_GET_VBRSTATUS_OLD:
1794 if(ivideo->warncount++ < 10)
1795 printk(KERN_INFO
1796 "sisfb: Deprecated ioctl call received - update your application!\n");
1797 fallthrough;
1798 case SISFB_GET_VBRSTATUS:
1799 if(sisfb_CheckVBRetrace(ivideo))
1800 return put_user((u32)1, argp);
1801 else
1802 return put_user((u32)0, argp);
1803
1804 case SISFB_GET_AUTOMAXIMIZE_OLD:
1805 if(ivideo->warncount++ < 10)
1806 printk(KERN_INFO
1807 "sisfb: Deprecated ioctl call received - update your application!\n");
1808 fallthrough;
1809 case SISFB_GET_AUTOMAXIMIZE:
1810 if(ivideo->sisfb_max)
1811 return put_user((u32)1, argp);
1812 else
1813 return put_user((u32)0, argp);
1814
1815 case SISFB_SET_AUTOMAXIMIZE_OLD:
1816 if(ivideo->warncount++ < 10)
1817 printk(KERN_INFO
1818 "sisfb: Deprecated ioctl call received - update your application!\n");
1819 fallthrough;
1820 case SISFB_SET_AUTOMAXIMIZE:
1821 if(get_user(gpu32, argp))
1822 return -EFAULT;
1823
1824 ivideo->sisfb_max = (gpu32) ? 1 : 0;
1825 break;
1826
1827 case SISFB_SET_TVPOSOFFSET:
1828 if(get_user(gpu32, argp))
1829 return -EFAULT;
1830
1831 sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
1832 sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
1833 break;
1834
1835 case SISFB_GET_TVPOSOFFSET:
1836 return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
1837 argp);
1838
1839 case SISFB_COMMAND:
1840 if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,
1841 sizeof(struct sisfb_cmd)))
1842 return -EFAULT;
1843
1844 sisfb_handle_command(ivideo, &ivideo->sisfb_command);
1845
1846 if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,
1847 sizeof(struct sisfb_cmd)))
1848 return -EFAULT;
1849
1850 break;
1851
1852 case SISFB_SET_LOCK:
1853 if(get_user(gpu32, argp))
1854 return -EFAULT;
1855
1856 ivideo->sisfblocked = (gpu32) ? 1 : 0;
1857 break;
1858
1859 default:
1860 #ifdef SIS_NEW_CONFIG_COMPAT
1861 return -ENOIOCTLCMD;
1862 #else
1863 return -EINVAL;
1864 #endif
1865 }
1866 return 0;
1867 }
1868
1869 static int
sisfb_get_fix(struct fb_fix_screeninfo * fix,int con,struct fb_info * info)1870 sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
1871 {
1872 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1873
1874 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1875
1876 strscpy(fix->id, ivideo->myid, sizeof(fix->id));
1877
1878 mutex_lock(&info->mm_lock);
1879 fix->smem_start = ivideo->video_base + ivideo->video_offset;
1880 fix->smem_len = ivideo->sisfb_mem;
1881 mutex_unlock(&info->mm_lock);
1882 fix->type = FB_TYPE_PACKED_PIXELS;
1883 fix->type_aux = 0;
1884 fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
1885 fix->xpanstep = 1;
1886 fix->ypanstep = (ivideo->sisfb_ypan) ? 1 : 0;
1887 fix->ywrapstep = 0;
1888 fix->line_length = ivideo->video_linelength;
1889 fix->mmio_start = ivideo->mmio_base;
1890 fix->mmio_len = ivideo->mmio_size;
1891 if(ivideo->sisvga_engine == SIS_300_VGA) {
1892 fix->accel = FB_ACCEL_SIS_GLAMOUR;
1893 } else if((ivideo->chip == SIS_330) ||
1894 (ivideo->chip == SIS_760) ||
1895 (ivideo->chip == SIS_761)) {
1896 fix->accel = FB_ACCEL_SIS_XABRE;
1897 } else if(ivideo->chip == XGI_20) {
1898 fix->accel = FB_ACCEL_XGI_VOLARI_Z;
1899 } else if(ivideo->chip >= XGI_40) {
1900 fix->accel = FB_ACCEL_XGI_VOLARI_V;
1901 } else {
1902 fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
1903 }
1904
1905 return 0;
1906 }
1907
1908 /* ---------------- fb_ops structures ----------------- */
1909
1910 static const struct fb_ops sisfb_ops = {
1911 .owner = THIS_MODULE,
1912 .fb_open = sisfb_open,
1913 .fb_release = sisfb_release,
1914 .fb_check_var = sisfb_check_var,
1915 .fb_set_par = sisfb_set_par,
1916 .fb_setcolreg = sisfb_setcolreg,
1917 .fb_pan_display = sisfb_pan_display,
1918 .fb_blank = sisfb_blank,
1919 .fb_fillrect = fbcon_sis_fillrect,
1920 .fb_copyarea = fbcon_sis_copyarea,
1921 .fb_imageblit = cfb_imageblit,
1922 .fb_sync = fbcon_sis_sync,
1923 #ifdef SIS_NEW_CONFIG_COMPAT
1924 .fb_compat_ioctl= sisfb_ioctl,
1925 #endif
1926 .fb_ioctl = sisfb_ioctl
1927 };
1928
1929 /* ---------------- Chip generation dependent routines ---------------- */
1930
sisfb_get_northbridge(int basechipid)1931 static struct pci_dev *sisfb_get_northbridge(int basechipid)
1932 {
1933 struct pci_dev *pdev = NULL;
1934 int nbridgenum, nbridgeidx, i;
1935 static const unsigned short nbridgeids[] = {
1936 PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */
1937 PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */
1938 PCI_DEVICE_ID_SI_730,
1939 PCI_DEVICE_ID_SI_550, /* for SiS 550 VGA */
1940 PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */
1941 PCI_DEVICE_ID_SI_651,
1942 PCI_DEVICE_ID_SI_740,
1943 PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760/761 VGA */
1944 PCI_DEVICE_ID_SI_741,
1945 PCI_DEVICE_ID_SI_660,
1946 PCI_DEVICE_ID_SI_760,
1947 PCI_DEVICE_ID_SI_761
1948 };
1949
1950 switch(basechipid) {
1951 #ifdef CONFIG_FB_SIS_300
1952 case SIS_540: nbridgeidx = 0; nbridgenum = 1; break;
1953 case SIS_630: nbridgeidx = 1; nbridgenum = 2; break;
1954 #endif
1955 #ifdef CONFIG_FB_SIS_315
1956 case SIS_550: nbridgeidx = 3; nbridgenum = 1; break;
1957 case SIS_650: nbridgeidx = 4; nbridgenum = 3; break;
1958 case SIS_660: nbridgeidx = 7; nbridgenum = 5; break;
1959 #endif
1960 default: return NULL;
1961 }
1962 for(i = 0; i < nbridgenum; i++) {
1963 if((pdev = pci_get_device(PCI_VENDOR_ID_SI,
1964 nbridgeids[nbridgeidx+i], NULL)))
1965 break;
1966 }
1967 return pdev;
1968 }
1969
sisfb_get_dram_size(struct sis_video_info * ivideo)1970 static int sisfb_get_dram_size(struct sis_video_info *ivideo)
1971 {
1972 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1973 u8 reg;
1974 #endif
1975
1976 ivideo->video_size = 0;
1977 ivideo->UMAsize = ivideo->LFBsize = 0;
1978
1979 switch(ivideo->chip) {
1980 #ifdef CONFIG_FB_SIS_300
1981 case SIS_300:
1982 reg = SiS_GetReg(SISSR, 0x14);
1983 ivideo->video_size = ((reg & 0x3F) + 1) << 20;
1984 break;
1985 case SIS_540:
1986 case SIS_630:
1987 case SIS_730:
1988 if(!ivideo->nbridge)
1989 return -1;
1990 pci_read_config_byte(ivideo->nbridge, 0x63, ®);
1991 ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
1992 break;
1993 #endif
1994 #ifdef CONFIG_FB_SIS_315
1995 case SIS_315H:
1996 case SIS_315PRO:
1997 case SIS_315:
1998 reg = SiS_GetReg(SISSR, 0x14);
1999 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2000 switch((reg >> 2) & 0x03) {
2001 case 0x01:
2002 case 0x03:
2003 ivideo->video_size <<= 1;
2004 break;
2005 case 0x02:
2006 ivideo->video_size += (ivideo->video_size/2);
2007 }
2008 break;
2009 case SIS_330:
2010 reg = SiS_GetReg(SISSR, 0x14);
2011 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2012 if(reg & 0x0c) ivideo->video_size <<= 1;
2013 break;
2014 case SIS_550:
2015 case SIS_650:
2016 case SIS_740:
2017 reg = SiS_GetReg(SISSR, 0x14);
2018 ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
2019 break;
2020 case SIS_661:
2021 case SIS_741:
2022 reg = SiS_GetReg(SISCR, 0x79);
2023 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2024 break;
2025 case SIS_660:
2026 case SIS_760:
2027 case SIS_761:
2028 reg = SiS_GetReg(SISCR, 0x79);
2029 reg = (reg & 0xf0) >> 4;
2030 if(reg) {
2031 ivideo->video_size = (1 << reg) << 20;
2032 ivideo->UMAsize = ivideo->video_size;
2033 }
2034 reg = SiS_GetReg(SISCR, 0x78);
2035 reg &= 0x30;
2036 if(reg) {
2037 if(reg == 0x10) {
2038 ivideo->LFBsize = (32 << 20);
2039 } else {
2040 ivideo->LFBsize = (64 << 20);
2041 }
2042 ivideo->video_size += ivideo->LFBsize;
2043 }
2044 break;
2045 case SIS_340:
2046 case XGI_20:
2047 case XGI_40:
2048 reg = SiS_GetReg(SISSR, 0x14);
2049 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2050 if(ivideo->chip != XGI_20) {
2051 reg = (reg & 0x0c) >> 2;
2052 if(ivideo->revision_id == 2) {
2053 if(reg & 0x01) reg = 0x02;
2054 else reg = 0x00;
2055 }
2056 if(reg == 0x02) ivideo->video_size <<= 1;
2057 else if(reg == 0x03) ivideo->video_size <<= 2;
2058 }
2059 break;
2060 #endif
2061 default:
2062 return -1;
2063 }
2064 return 0;
2065 }
2066
2067 /* -------------- video bridge device detection --------------- */
2068
sisfb_detect_VB_connect(struct sis_video_info * ivideo)2069 static void sisfb_detect_VB_connect(struct sis_video_info *ivideo)
2070 {
2071 u8 cr32, temp;
2072
2073 /* No CRT2 on XGI Z7 */
2074 if(ivideo->chip == XGI_20) {
2075 ivideo->sisfb_crt1off = 0;
2076 return;
2077 }
2078
2079 #ifdef CONFIG_FB_SIS_300
2080 if(ivideo->sisvga_engine == SIS_300_VGA) {
2081 temp = SiS_GetReg(SISSR, 0x17);
2082 if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
2083 /* PAL/NTSC is stored on SR16 on such machines */
2084 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
2085 temp = SiS_GetReg(SISSR, 0x16);
2086 if(temp & 0x20)
2087 ivideo->vbflags |= TV_PAL;
2088 else
2089 ivideo->vbflags |= TV_NTSC;
2090 }
2091 }
2092 }
2093 #endif
2094
2095 cr32 = SiS_GetReg(SISCR, 0x32);
2096
2097 if(cr32 & SIS_CRT1) {
2098 ivideo->sisfb_crt1off = 0;
2099 } else {
2100 ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0;
2101 }
2102
2103 ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
2104
2105 if(cr32 & SIS_VB_TV) ivideo->vbflags |= CRT2_TV;
2106 if(cr32 & SIS_VB_LCD) ivideo->vbflags |= CRT2_LCD;
2107 if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA;
2108
2109 /* Check given parms for hardware compatibility.
2110 * (Cannot do this in the search_xx routines since we don't
2111 * know what hardware we are running on then)
2112 */
2113
2114 if(ivideo->chip != SIS_550) {
2115 ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0;
2116 }
2117
2118 if(ivideo->sisfb_tvplug != -1) {
2119 if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2120 (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) {
2121 if(ivideo->sisfb_tvplug & TV_YPBPR) {
2122 ivideo->sisfb_tvplug = -1;
2123 printk(KERN_ERR "sisfb: YPbPr not supported\n");
2124 }
2125 }
2126 }
2127 if(ivideo->sisfb_tvplug != -1) {
2128 if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2129 (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) {
2130 if(ivideo->sisfb_tvplug & TV_HIVISION) {
2131 ivideo->sisfb_tvplug = -1;
2132 printk(KERN_ERR "sisfb: HiVision not supported\n");
2133 }
2134 }
2135 }
2136 if(ivideo->sisfb_tvstd != -1) {
2137 if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
2138 (!((ivideo->sisvga_engine == SIS_315_VGA) &&
2139 (ivideo->vbflags2 & VB2_CHRONTEL))) ) {
2140 if(ivideo->sisfb_tvstd & (TV_PALM | TV_PALN | TV_NTSCJ)) {
2141 ivideo->sisfb_tvstd = -1;
2142 printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
2143 }
2144 }
2145 }
2146
2147 /* Detect/set TV plug & type */
2148 if(ivideo->sisfb_tvplug != -1) {
2149 ivideo->vbflags |= ivideo->sisfb_tvplug;
2150 } else {
2151 if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
2152 else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION;
2153 else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART;
2154 else {
2155 if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO;
2156 if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
2157 }
2158 }
2159
2160 if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) {
2161 if(ivideo->sisfb_tvstd != -1) {
2162 ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ);
2163 ivideo->vbflags |= ivideo->sisfb_tvstd;
2164 }
2165 if(ivideo->vbflags & TV_SCART) {
2166 ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ);
2167 ivideo->vbflags |= TV_PAL;
2168 }
2169 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
2170 if(ivideo->sisvga_engine == SIS_300_VGA) {
2171 temp = SiS_GetReg(SISSR, 0x38);
2172 if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2173 else ivideo->vbflags |= TV_NTSC;
2174 } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
2175 temp = SiS_GetReg(SISSR, 0x38);
2176 if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2177 else ivideo->vbflags |= TV_NTSC;
2178 } else {
2179 temp = SiS_GetReg(SISCR, 0x79);
2180 if(temp & 0x20) ivideo->vbflags |= TV_PAL;
2181 else ivideo->vbflags |= TV_NTSC;
2182 }
2183 }
2184 }
2185
2186 /* Copy forceCRT1 option to CRT1off if option is given */
2187 if(ivideo->sisfb_forcecrt1 != -1) {
2188 ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
2189 }
2190 }
2191
2192 /* ------------------ Sensing routines ------------------ */
2193
sisfb_test_DDC1(struct sis_video_info * ivideo)2194 static bool sisfb_test_DDC1(struct sis_video_info *ivideo)
2195 {
2196 unsigned short old;
2197 int count = 48;
2198
2199 old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
2200 do {
2201 if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
2202 } while(count--);
2203 return (count != -1);
2204 }
2205
sisfb_sense_crt1(struct sis_video_info * ivideo)2206 static void sisfb_sense_crt1(struct sis_video_info *ivideo)
2207 {
2208 bool mustwait = false;
2209 u8 sr1F, cr17;
2210 #ifdef CONFIG_FB_SIS_315
2211 u8 cr63 = 0;
2212 #endif
2213 u16 temp = 0xffff;
2214 int i;
2215
2216 sr1F = SiS_GetReg(SISSR, 0x1F);
2217 SiS_SetRegOR(SISSR, 0x1F, 0x04);
2218 SiS_SetRegAND(SISSR, 0x1F, 0x3F);
2219
2220 if (sr1F & 0xc0)
2221 mustwait = true;
2222
2223 #ifdef CONFIG_FB_SIS_315
2224 if (ivideo->sisvga_engine == SIS_315_VGA) {
2225 cr63 = SiS_GetReg(SISCR, ivideo->SiS_Pr.SiS_MyCR63);
2226 cr63 &= 0x40;
2227 SiS_SetRegAND(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF);
2228 }
2229 #endif
2230
2231 cr17 = SiS_GetReg(SISCR, 0x17);
2232 cr17 &= 0x80;
2233
2234 if (!cr17) {
2235 SiS_SetRegOR(SISCR, 0x17, 0x80);
2236 mustwait = true;
2237 SiS_SetReg(SISSR, 0x00, 0x01);
2238 SiS_SetReg(SISSR, 0x00, 0x03);
2239 }
2240
2241 if (mustwait) {
2242 for (i = 0; i < 10; i++)
2243 sisfbwaitretracecrt1(ivideo);
2244 }
2245 #ifdef CONFIG_FB_SIS_315
2246 if (ivideo->chip >= SIS_330) {
2247 SiS_SetRegAND(SISCR, 0x32, ~0x20);
2248 if (ivideo->chip >= SIS_340)
2249 SiS_SetReg(SISCR, 0x57, 0x4a);
2250 else
2251 SiS_SetReg(SISCR, 0x57, 0x5f);
2252
2253 SiS_SetRegOR(SISCR, 0x53, 0x02);
2254 while ((SiS_GetRegByte(SISINPSTAT)) & 0x01)
2255 break;
2256 while (!((SiS_GetRegByte(SISINPSTAT)) & 0x01))
2257 break;
2258 if ((SiS_GetRegByte(SISMISCW)) & 0x10)
2259 temp = 1;
2260
2261 SiS_SetRegAND(SISCR, 0x53, 0xfd);
2262 SiS_SetRegAND(SISCR, 0x57, 0x00);
2263 }
2264 #endif
2265
2266 if (temp == 0xffff) {
2267 i = 3;
2268
2269 do {
2270 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2271 ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
2272 } while (((temp == 0) || (temp == 0xffff)) && i--);
2273
2274 if ((temp == 0) || (temp == 0xffff)) {
2275 if (sisfb_test_DDC1(ivideo))
2276 temp = 1;
2277 }
2278 }
2279
2280 if ((temp) && (temp != 0xffff))
2281 SiS_SetRegOR(SISCR, 0x32, 0x20);
2282
2283 #ifdef CONFIG_FB_SIS_315
2284 if (ivideo->sisvga_engine == SIS_315_VGA)
2285 SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF, cr63);
2286 #endif
2287
2288 SiS_SetRegANDOR(SISCR, 0x17, 0x7F, cr17);
2289 SiS_SetReg(SISSR, 0x1F, sr1F);
2290 }
2291
2292 /* Determine and detect attached devices on SiS30x */
SiS_SenseLCD(struct sis_video_info * ivideo)2293 static void SiS_SenseLCD(struct sis_video_info *ivideo)
2294 {
2295 unsigned char buffer[256];
2296 unsigned short temp, realcrtno, i;
2297 u8 reg, cr37 = 0, paneltype = 0;
2298 u16 xres, yres;
2299
2300 ivideo->SiS_Pr.PanelSelfDetected = false;
2301
2302 /* LCD detection only for TMDS bridges */
2303 if (!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
2304 return;
2305 if (ivideo->vbflags2 & VB2_30xBDH)
2306 return;
2307
2308 /* If LCD already set up by BIOS, skip it */
2309 reg = SiS_GetReg(SISCR, 0x32);
2310 if (reg & 0x08)
2311 return;
2312
2313 realcrtno = 1;
2314 if (ivideo->SiS_Pr.DDCPortMixup)
2315 realcrtno = 0;
2316
2317 /* Check DDC capabilities */
2318 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
2319 realcrtno, 0, &buffer[0], ivideo->vbflags2);
2320
2321 if ((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
2322 return;
2323
2324 /* Read DDC data */
2325 i = 3; /* Number of retrys */
2326 do {
2327 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2328 ivideo->sisvga_engine, realcrtno, 1,
2329 &buffer[0], ivideo->vbflags2);
2330 } while ((temp) && i--);
2331
2332 if (temp)
2333 return;
2334
2335 /* No digital device */
2336 if (!(buffer[0x14] & 0x80))
2337 return;
2338
2339 /* First detailed timing preferred timing? */
2340 if (!(buffer[0x18] & 0x02))
2341 return;
2342
2343 xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
2344 yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
2345
2346 switch(xres) {
2347 case 1024:
2348 if (yres == 768)
2349 paneltype = 0x02;
2350 break;
2351 case 1280:
2352 if (yres == 1024)
2353 paneltype = 0x03;
2354 break;
2355 case 1600:
2356 if ((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
2357 paneltype = 0x0b;
2358 break;
2359 }
2360
2361 if (!paneltype)
2362 return;
2363
2364 if (buffer[0x23])
2365 cr37 |= 0x10;
2366
2367 if ((buffer[0x47] & 0x18) == 0x18)
2368 cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2369 else
2370 cr37 |= 0xc0;
2371
2372 SiS_SetReg(SISCR, 0x36, paneltype);
2373 cr37 &= 0xf1;
2374 SiS_SetRegANDOR(SISCR, 0x37, 0x0c, cr37);
2375 SiS_SetRegOR(SISCR, 0x32, 0x08);
2376
2377 ivideo->SiS_Pr.PanelSelfDetected = true;
2378 }
2379
SISDoSense(struct sis_video_info * ivideo,u16 type,u16 test)2380 static int SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
2381 {
2382 int temp, mytest, result, i, j;
2383
2384 for (j = 0; j < 10; j++) {
2385 result = 0;
2386 for (i = 0; i < 3; i++) {
2387 mytest = test;
2388 SiS_SetReg(SISPART4, 0x11, (type & 0x00ff));
2389 temp = (type >> 8) | (mytest & 0x00ff);
2390 SiS_SetRegANDOR(SISPART4, 0x10, 0xe0, temp);
2391 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
2392 mytest >>= 8;
2393 mytest &= 0x7f;
2394 temp = SiS_GetReg(SISPART4, 0x03);
2395 temp ^= 0x0e;
2396 temp &= mytest;
2397 if (temp == mytest)
2398 result++;
2399 #if 1
2400 SiS_SetReg(SISPART4, 0x11, 0x00);
2401 SiS_SetRegAND(SISPART4, 0x10, 0xe0);
2402 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
2403 #endif
2404 }
2405
2406 if ((result == 0) || (result >= 2))
2407 break;
2408 }
2409 return result;
2410 }
2411
SiS_Sense30x(struct sis_video_info * ivideo)2412 static void SiS_Sense30x(struct sis_video_info *ivideo)
2413 {
2414 u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
2415 u16 svhs=0, svhs_c=0;
2416 u16 cvbs=0, cvbs_c=0;
2417 u16 vga2=0, vga2_c=0;
2418 int myflag, result;
2419 char stdstr[] = "sisfb: Detected";
2420 char tvstr[] = "TV connected to";
2421
2422 if(ivideo->vbflags2 & VB2_301) {
2423 svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
2424 myflag = SiS_GetReg(SISPART4, 0x01);
2425 if(myflag & 0x04) {
2426 svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
2427 }
2428 } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) {
2429 svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
2430 } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) {
2431 svhs = 0x0200; cvbs = 0x0100;
2432 } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
2433 svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
2434 } else
2435 return;
2436
2437 vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
2438 if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
2439 svhs_c = 0x0408; cvbs_c = 0x0808;
2440 }
2441
2442 biosflag = 2;
2443 if(ivideo->haveXGIROM) {
2444 biosflag = ivideo->bios_abase[0x58] & 0x03;
2445 } else if(ivideo->newrom) {
2446 if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01;
2447 } else if(ivideo->sisvga_engine == SIS_300_VGA) {
2448 if(ivideo->bios_abase) {
2449 biosflag = ivideo->bios_abase[0xfe] & 0x03;
2450 }
2451 }
2452
2453 if(ivideo->chip == SIS_300) {
2454 myflag = SiS_GetReg(SISSR, 0x3b);
2455 if(!(myflag & 0x01)) vga2 = vga2_c = 0;
2456 }
2457
2458 if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) {
2459 vga2 = vga2_c = 0;
2460 }
2461
2462 backupSR_1e = SiS_GetReg(SISSR, 0x1e);
2463 SiS_SetRegOR(SISSR, 0x1e, 0x20);
2464
2465 backupP4_0d = SiS_GetReg(SISPART4, 0x0d);
2466 if(ivideo->vbflags2 & VB2_30xC) {
2467 SiS_SetRegANDOR(SISPART4, 0x0d, ~0x07, 0x01);
2468 } else {
2469 SiS_SetRegOR(SISPART4, 0x0d, 0x04);
2470 }
2471 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2472
2473 backupP2_00 = SiS_GetReg(SISPART2, 0x00);
2474 SiS_SetReg(SISPART2, 0x00, ((backupP2_00 | 0x1c) & 0xfc));
2475
2476 backupP2_4d = SiS_GetReg(SISPART2, 0x4d);
2477 if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
2478 SiS_SetReg(SISPART2, 0x4d, (backupP2_4d & ~0x10));
2479 }
2480
2481 if(!(ivideo->vbflags2 & VB2_30xCLV)) {
2482 SISDoSense(ivideo, 0, 0);
2483 }
2484
2485 SiS_SetRegAND(SISCR, 0x32, ~0x14);
2486
2487 if(vga2_c || vga2) {
2488 if(SISDoSense(ivideo, vga2, vga2_c)) {
2489 if(biosflag & 0x01) {
2490 printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
2491 SiS_SetRegOR(SISCR, 0x32, 0x04);
2492 } else {
2493 printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
2494 SiS_SetRegOR(SISCR, 0x32, 0x10);
2495 }
2496 }
2497 }
2498
2499 SiS_SetRegAND(SISCR, 0x32, 0x3f);
2500
2501 if(ivideo->vbflags2 & VB2_30xCLV) {
2502 SiS_SetRegOR(SISPART4, 0x0d, 0x04);
2503 }
2504
2505 if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
2506 SiS_SetReg(SISPART2, 0x4d, (backupP2_4d | 0x10));
2507 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2508 if((result = SISDoSense(ivideo, svhs, 0x0604))) {
2509 if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
2510 printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
2511 SiS_SetRegOR(SISCR, 0x32, 0x80);
2512 }
2513 }
2514 SiS_SetReg(SISPART2, 0x4d, backupP2_4d);
2515 }
2516
2517 SiS_SetRegAND(SISCR, 0x32, ~0x03);
2518
2519 if(!(ivideo->vbflags & TV_YPBPR)) {
2520 if((result = SISDoSense(ivideo, svhs, svhs_c))) {
2521 printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
2522 SiS_SetRegOR(SISCR, 0x32, 0x02);
2523 }
2524 if((biosflag & 0x02) || (!result)) {
2525 if(SISDoSense(ivideo, cvbs, cvbs_c)) {
2526 printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
2527 SiS_SetRegOR(SISCR, 0x32, 0x01);
2528 }
2529 }
2530 }
2531
2532 SISDoSense(ivideo, 0, 0);
2533
2534 SiS_SetReg(SISPART2, 0x00, backupP2_00);
2535 SiS_SetReg(SISPART4, 0x0d, backupP4_0d);
2536 SiS_SetReg(SISSR, 0x1e, backupSR_1e);
2537
2538 if(ivideo->vbflags2 & VB2_30xCLV) {
2539 biosflag = SiS_GetReg(SISPART2, 0x00);
2540 if(biosflag & 0x20) {
2541 for(myflag = 2; myflag > 0; myflag--) {
2542 biosflag ^= 0x20;
2543 SiS_SetReg(SISPART2, 0x00, biosflag);
2544 }
2545 }
2546 }
2547
2548 SiS_SetReg(SISPART2, 0x00, backupP2_00);
2549 }
2550
2551 /* Determine and detect attached TV's on Chrontel */
SiS_SenseCh(struct sis_video_info * ivideo)2552 static void SiS_SenseCh(struct sis_video_info *ivideo)
2553 {
2554 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2555 u8 temp1, temp2;
2556 char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
2557 #endif
2558 #ifdef CONFIG_FB_SIS_300
2559 unsigned char test[3];
2560 int i;
2561 #endif
2562
2563 if(ivideo->chip < SIS_315H) {
2564
2565 #ifdef CONFIG_FB_SIS_300
2566 ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1; /* Chrontel 700x */
2567 SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c); /* Set general purpose IO for Chrontel communication */
2568 SiS_DDC2Delay(&ivideo->SiS_Pr, 1000);
2569 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2570 /* See Chrontel TB31 for explanation */
2571 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2572 if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
2573 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b);
2574 SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2575 }
2576 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2577 if(temp2 != temp1) temp1 = temp2;
2578
2579 if((temp1 >= 0x22) && (temp1 <= 0x50)) {
2580 /* Read power status */
2581 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2582 if((temp1 & 0x03) != 0x03) {
2583 /* Power all outputs */
2584 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b);
2585 SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2586 }
2587 /* Sense connected TV devices */
2588 for(i = 0; i < 3; i++) {
2589 SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01);
2590 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2591 SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00);
2592 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2593 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
2594 if(!(temp1 & 0x08)) test[i] = 0x02;
2595 else if(!(temp1 & 0x02)) test[i] = 0x01;
2596 else test[i] = 0;
2597 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2598 }
2599
2600 if(test[0] == test[1]) temp1 = test[0];
2601 else if(test[0] == test[2]) temp1 = test[0];
2602 else if(test[1] == test[2]) temp1 = test[1];
2603 else {
2604 printk(KERN_INFO
2605 "sisfb: TV detection unreliable - test results varied\n");
2606 temp1 = test[2];
2607 }
2608 if(temp1 == 0x02) {
2609 printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2610 ivideo->vbflags |= TV_SVIDEO;
2611 SiS_SetRegOR(SISCR, 0x32, 0x02);
2612 SiS_SetRegAND(SISCR, 0x32, ~0x05);
2613 } else if (temp1 == 0x01) {
2614 printk(KERN_INFO "%s CVBS output\n", stdstr);
2615 ivideo->vbflags |= TV_AVIDEO;
2616 SiS_SetRegOR(SISCR, 0x32, 0x01);
2617 SiS_SetRegAND(SISCR, 0x32, ~0x06);
2618 } else {
2619 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2620 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2621 }
2622 } else if(temp1 == 0) {
2623 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2624 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2625 }
2626 /* Set general purpose IO for Chrontel communication */
2627 SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
2628 #endif
2629
2630 } else {
2631
2632 #ifdef CONFIG_FB_SIS_315
2633 ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */
2634 temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
2635 SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20);
2636 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2637 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2638 temp2 |= 0x01;
2639 SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2640 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2641 temp2 ^= 0x01;
2642 SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2643 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2644 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2645 SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1);
2646 temp1 = 0;
2647 if(temp2 & 0x02) temp1 |= 0x01;
2648 if(temp2 & 0x10) temp1 |= 0x01;
2649 if(temp2 & 0x04) temp1 |= 0x02;
2650 if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
2651 switch(temp1) {
2652 case 0x01:
2653 printk(KERN_INFO "%s CVBS output\n", stdstr);
2654 ivideo->vbflags |= TV_AVIDEO;
2655 SiS_SetRegOR(SISCR, 0x32, 0x01);
2656 SiS_SetRegAND(SISCR, 0x32, ~0x06);
2657 break;
2658 case 0x02:
2659 printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2660 ivideo->vbflags |= TV_SVIDEO;
2661 SiS_SetRegOR(SISCR, 0x32, 0x02);
2662 SiS_SetRegAND(SISCR, 0x32, ~0x05);
2663 break;
2664 case 0x04:
2665 printk(KERN_INFO "%s SCART output\n", stdstr);
2666 SiS_SetRegOR(SISCR, 0x32, 0x04);
2667 SiS_SetRegAND(SISCR, 0x32, ~0x03);
2668 break;
2669 default:
2670 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2671 }
2672 #endif
2673 }
2674 }
2675
sisfb_get_VB_type(struct sis_video_info * ivideo)2676 static void sisfb_get_VB_type(struct sis_video_info *ivideo)
2677 {
2678 char stdstr[] = "sisfb: Detected";
2679 char bridgestr[] = "video bridge";
2680 u8 vb_chipid;
2681 u8 reg;
2682
2683 /* No CRT2 on XGI Z7 */
2684 if(ivideo->chip == XGI_20)
2685 return;
2686
2687 vb_chipid = SiS_GetReg(SISPART4, 0x00);
2688 switch(vb_chipid) {
2689 case 0x01:
2690 reg = SiS_GetReg(SISPART4, 0x01);
2691 if(reg < 0xb0) {
2692 ivideo->vbflags |= VB_301; /* Deprecated */
2693 ivideo->vbflags2 |= VB2_301;
2694 printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
2695 } else if(reg < 0xc0) {
2696 ivideo->vbflags |= VB_301B; /* Deprecated */
2697 ivideo->vbflags2 |= VB2_301B;
2698 reg = SiS_GetReg(SISPART4, 0x23);
2699 if(!(reg & 0x02)) {
2700 ivideo->vbflags |= VB_30xBDH; /* Deprecated */
2701 ivideo->vbflags2 |= VB2_30xBDH;
2702 printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
2703 } else {
2704 printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
2705 }
2706 } else if(reg < 0xd0) {
2707 ivideo->vbflags |= VB_301C; /* Deprecated */
2708 ivideo->vbflags2 |= VB2_301C;
2709 printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
2710 } else if(reg < 0xe0) {
2711 ivideo->vbflags |= VB_301LV; /* Deprecated */
2712 ivideo->vbflags2 |= VB2_301LV;
2713 printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
2714 } else if(reg <= 0xe1) {
2715 reg = SiS_GetReg(SISPART4, 0x39);
2716 if(reg == 0xff) {
2717 ivideo->vbflags |= VB_302LV; /* Deprecated */
2718 ivideo->vbflags2 |= VB2_302LV;
2719 printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
2720 } else {
2721 ivideo->vbflags |= VB_301C; /* Deprecated */
2722 ivideo->vbflags2 |= VB2_301C;
2723 printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
2724 #if 0
2725 ivideo->vbflags |= VB_302ELV; /* Deprecated */
2726 ivideo->vbflags2 |= VB2_302ELV;
2727 printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
2728 #endif
2729 }
2730 }
2731 break;
2732 case 0x02:
2733 ivideo->vbflags |= VB_302B; /* Deprecated */
2734 ivideo->vbflags2 |= VB2_302B;
2735 printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
2736 break;
2737 }
2738
2739 if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
2740 reg = SiS_GetReg(SISCR, 0x37);
2741 reg &= SIS_EXTERNAL_CHIP_MASK;
2742 reg >>= 1;
2743 if(ivideo->sisvga_engine == SIS_300_VGA) {
2744 #ifdef CONFIG_FB_SIS_300
2745 switch(reg) {
2746 case SIS_EXTERNAL_CHIP_LVDS:
2747 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2748 ivideo->vbflags2 |= VB2_LVDS;
2749 break;
2750 case SIS_EXTERNAL_CHIP_TRUMPION:
2751 ivideo->vbflags |= (VB_LVDS | VB_TRUMPION); /* Deprecated */
2752 ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION);
2753 break;
2754 case SIS_EXTERNAL_CHIP_CHRONTEL:
2755 ivideo->vbflags |= VB_CHRONTEL; /* Deprecated */
2756 ivideo->vbflags2 |= VB2_CHRONTEL;
2757 break;
2758 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
2759 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2760 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2761 break;
2762 }
2763 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1;
2764 #endif
2765 } else if(ivideo->chip < SIS_661) {
2766 #ifdef CONFIG_FB_SIS_315
2767 switch (reg) {
2768 case SIS310_EXTERNAL_CHIP_LVDS:
2769 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2770 ivideo->vbflags2 |= VB2_LVDS;
2771 break;
2772 case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
2773 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2774 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2775 break;
2776 }
2777 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2778 #endif
2779 } else if(ivideo->chip >= SIS_661) {
2780 #ifdef CONFIG_FB_SIS_315
2781 reg = SiS_GetReg(SISCR, 0x38);
2782 reg >>= 5;
2783 switch(reg) {
2784 case 0x02:
2785 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2786 ivideo->vbflags2 |= VB2_LVDS;
2787 break;
2788 case 0x03:
2789 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2790 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2791 break;
2792 case 0x04:
2793 ivideo->vbflags |= (VB_LVDS | VB_CONEXANT); /* Deprecated */
2794 ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT);
2795 break;
2796 }
2797 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2798 #endif
2799 }
2800 if(ivideo->vbflags2 & VB2_LVDS) {
2801 printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
2802 }
2803 if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) {
2804 printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
2805 }
2806 if(ivideo->vbflags2 & VB2_CHRONTEL) {
2807 printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
2808 }
2809 if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) {
2810 printk(KERN_INFO "%s Conexant external device\n", stdstr);
2811 }
2812 }
2813
2814 if(ivideo->vbflags2 & VB2_SISBRIDGE) {
2815 SiS_SenseLCD(ivideo);
2816 SiS_Sense30x(ivideo);
2817 } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
2818 SiS_SenseCh(ivideo);
2819 }
2820 }
2821
2822 /* ---------- Engine initialization routines ------------ */
2823
2824 static void
sisfb_engine_init(struct sis_video_info * ivideo)2825 sisfb_engine_init(struct sis_video_info *ivideo)
2826 {
2827
2828 /* Initialize command queue (we use MMIO only) */
2829
2830 /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
2831
2832 ivideo->caps &= ~(TURBO_QUEUE_CAP |
2833 MMIO_CMD_QUEUE_CAP |
2834 VM_CMD_QUEUE_CAP |
2835 AGP_CMD_QUEUE_CAP);
2836
2837 #ifdef CONFIG_FB_SIS_300
2838 if(ivideo->sisvga_engine == SIS_300_VGA) {
2839 u32 tqueue_pos;
2840 u8 tq_state;
2841
2842 tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
2843
2844 tq_state = SiS_GetReg(SISSR, IND_SIS_TURBOQUEUE_SET);
2845 tq_state |= 0xf0;
2846 tq_state &= 0xfc;
2847 tq_state |= (u8)(tqueue_pos >> 8);
2848 SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
2849
2850 SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
2851
2852 ivideo->caps |= TURBO_QUEUE_CAP;
2853 }
2854 #endif
2855
2856 #ifdef CONFIG_FB_SIS_315
2857 if(ivideo->sisvga_engine == SIS_315_VGA) {
2858 u32 tempq = 0, templ;
2859 u8 temp;
2860
2861 if(ivideo->chip == XGI_20) {
2862 switch(ivideo->cmdQueueSize) {
2863 case (64 * 1024):
2864 temp = SIS_CMD_QUEUE_SIZE_Z7_64k;
2865 break;
2866 case (128 * 1024):
2867 default:
2868 temp = SIS_CMD_QUEUE_SIZE_Z7_128k;
2869 }
2870 } else {
2871 switch(ivideo->cmdQueueSize) {
2872 case (4 * 1024 * 1024):
2873 temp = SIS_CMD_QUEUE_SIZE_4M;
2874 break;
2875 case (2 * 1024 * 1024):
2876 temp = SIS_CMD_QUEUE_SIZE_2M;
2877 break;
2878 case (1 * 1024 * 1024):
2879 temp = SIS_CMD_QUEUE_SIZE_1M;
2880 break;
2881 default:
2882 case (512 * 1024):
2883 temp = SIS_CMD_QUEUE_SIZE_512k;
2884 }
2885 }
2886
2887 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2888 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2889
2890 if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
2891 /* Must disable dual pipe on XGI_40. Can't do
2892 * this in MMIO mode, because it requires
2893 * setting/clearing a bit in the MMIO fire trigger
2894 * register.
2895 */
2896 if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) {
2897
2898 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
2899
2900 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
2901
2902 tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
2903 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
2904
2905 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2906 MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq);
2907
2908 writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq);
2909 writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4);
2910 writel(0x168F0000, ivideo->video_vbase + tempq + 8);
2911 writel(0x168F0000, ivideo->video_vbase + tempq + 12);
2912
2913 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16));
2914
2915 sisfb_syncaccel(ivideo);
2916
2917 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2918
2919 }
2920 }
2921
2922 tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
2923 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
2924
2925 temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
2926 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, temp);
2927
2928 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2929 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
2930
2931 ivideo->caps |= MMIO_CMD_QUEUE_CAP;
2932 }
2933 #endif
2934
2935 ivideo->engineok = 1;
2936 }
2937
sisfb_detect_lcd_type(struct sis_video_info * ivideo)2938 static void sisfb_detect_lcd_type(struct sis_video_info *ivideo)
2939 {
2940 u8 reg;
2941 int i;
2942
2943 reg = SiS_GetReg(SISCR, 0x36);
2944 reg &= 0x0f;
2945 if(ivideo->sisvga_engine == SIS_300_VGA) {
2946 ivideo->CRT2LCDType = sis300paneltype[reg];
2947 } else if(ivideo->chip >= SIS_661) {
2948 ivideo->CRT2LCDType = sis661paneltype[reg];
2949 } else {
2950 ivideo->CRT2LCDType = sis310paneltype[reg];
2951 if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
2952 if((ivideo->CRT2LCDType != LCD_320x240_2) &&
2953 (ivideo->CRT2LCDType != LCD_320x240_3)) {
2954 ivideo->CRT2LCDType = LCD_320x240;
2955 }
2956 }
2957 }
2958
2959 if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
2960 /* For broken BIOSes: Assume 1024x768, RGB18 */
2961 ivideo->CRT2LCDType = LCD_1024x768;
2962 SiS_SetRegANDOR(SISCR, 0x36, 0xf0, 0x02);
2963 SiS_SetRegANDOR(SISCR, 0x37, 0xee, 0x01);
2964 printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
2965 }
2966
2967 for(i = 0; i < SIS_LCD_NUMBER; i++) {
2968 if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
2969 ivideo->lcdxres = sis_lcd_data[i].xres;
2970 ivideo->lcdyres = sis_lcd_data[i].yres;
2971 ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
2972 break;
2973 }
2974 }
2975
2976 #ifdef CONFIG_FB_SIS_300
2977 if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
2978 ivideo->lcdxres = 1360; ivideo->lcdyres = 1024;
2979 ivideo->lcddefmodeidx = DEFAULT_MODE_1360;
2980 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
2981 ivideo->lcdxres = 848; ivideo->lcdyres = 480;
2982 ivideo->lcddefmodeidx = DEFAULT_MODE_848;
2983 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) {
2984 ivideo->lcdxres = 856; ivideo->lcdyres = 480;
2985 ivideo->lcddefmodeidx = DEFAULT_MODE_856;
2986 }
2987 #endif
2988
2989 printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
2990 ivideo->lcdxres, ivideo->lcdyres);
2991 }
2992
sisfb_save_pdc_emi(struct sis_video_info * ivideo)2993 static void sisfb_save_pdc_emi(struct sis_video_info *ivideo)
2994 {
2995 #ifdef CONFIG_FB_SIS_300
2996 /* Save the current PanelDelayCompensation if the LCD is currently used */
2997 if(ivideo->sisvga_engine == SIS_300_VGA) {
2998 if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
2999 int tmp;
3000 tmp = SiS_GetReg(SISCR, 0x30);
3001 if(tmp & 0x20) {
3002 /* Currently on LCD? If yes, read current pdc */
3003 ivideo->detectedpdc = SiS_GetReg(SISPART1, 0x13);
3004 ivideo->detectedpdc &= 0x3c;
3005 if(ivideo->SiS_Pr.PDC == -1) {
3006 /* Let option override detection */
3007 ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
3008 }
3009 printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
3010 ivideo->detectedpdc);
3011 }
3012 if((ivideo->SiS_Pr.PDC != -1) &&
3013 (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
3014 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
3015 ivideo->SiS_Pr.PDC);
3016 }
3017 }
3018 }
3019 #endif
3020
3021 #ifdef CONFIG_FB_SIS_315
3022 if(ivideo->sisvga_engine == SIS_315_VGA) {
3023
3024 /* Try to find about LCDA */
3025 if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
3026 int tmp;
3027 tmp = SiS_GetReg(SISPART1, 0x13);
3028 if(tmp & 0x04) {
3029 ivideo->SiS_Pr.SiS_UseLCDA = true;
3030 ivideo->detectedlcda = 0x03;
3031 }
3032 }
3033
3034 /* Save PDC */
3035 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
3036 int tmp;
3037 tmp = SiS_GetReg(SISCR, 0x30);
3038 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3039 /* Currently on LCD? If yes, read current pdc */
3040 u8 pdc;
3041 pdc = SiS_GetReg(SISPART1, 0x2D);
3042 ivideo->detectedpdc = (pdc & 0x0f) << 1;
3043 ivideo->detectedpdca = (pdc & 0xf0) >> 3;
3044 pdc = SiS_GetReg(SISPART1, 0x35);
3045 ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
3046 pdc = SiS_GetReg(SISPART1, 0x20);
3047 ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
3048 if(ivideo->newrom) {
3049 /* New ROM invalidates other PDC resp. */
3050 if(ivideo->detectedlcda != 0xff) {
3051 ivideo->detectedpdc = 0xff;
3052 } else {
3053 ivideo->detectedpdca = 0xff;
3054 }
3055 }
3056 if(ivideo->SiS_Pr.PDC == -1) {
3057 if(ivideo->detectedpdc != 0xff) {
3058 ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
3059 }
3060 }
3061 if(ivideo->SiS_Pr.PDCA == -1) {
3062 if(ivideo->detectedpdca != 0xff) {
3063 ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
3064 }
3065 }
3066 if(ivideo->detectedpdc != 0xff) {
3067 printk(KERN_INFO
3068 "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3069 ivideo->detectedpdc);
3070 }
3071 if(ivideo->detectedpdca != 0xff) {
3072 printk(KERN_INFO
3073 "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3074 ivideo->detectedpdca);
3075 }
3076 }
3077
3078 /* Save EMI */
3079 if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
3080 ivideo->SiS_Pr.EMI_30 = SiS_GetReg(SISPART4, 0x30);
3081 ivideo->SiS_Pr.EMI_31 = SiS_GetReg(SISPART4, 0x31);
3082 ivideo->SiS_Pr.EMI_32 = SiS_GetReg(SISPART4, 0x32);
3083 ivideo->SiS_Pr.EMI_33 = SiS_GetReg(SISPART4, 0x33);
3084 ivideo->SiS_Pr.HaveEMI = true;
3085 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3086 ivideo->SiS_Pr.HaveEMILCD = true;
3087 }
3088 }
3089 }
3090
3091 /* Let user override detected PDCs (all bridges) */
3092 if(ivideo->vbflags2 & VB2_30xBLV) {
3093 if((ivideo->SiS_Pr.PDC != -1) &&
3094 (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
3095 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3096 ivideo->SiS_Pr.PDC);
3097 }
3098 if((ivideo->SiS_Pr.PDCA != -1) &&
3099 (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
3100 printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3101 ivideo->SiS_Pr.PDCA);
3102 }
3103 }
3104
3105 }
3106 #endif
3107 }
3108
3109 /* -------------------- Memory manager routines ---------------------- */
3110
sisfb_getheapstart(struct sis_video_info * ivideo)3111 static u32 sisfb_getheapstart(struct sis_video_info *ivideo)
3112 {
3113 u32 ret = ivideo->sisfb_parm_mem * 1024;
3114 u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3115 u32 def;
3116
3117 /* Calculate heap start = end of memory for console
3118 *
3119 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3120 * C = console, D = heap, H = HWCursor, Q = cmd-queue
3121 *
3122 * On 76x in UMA+LFB mode, the layout is as follows:
3123 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3124 * where the heap is the entire UMA area, eventually
3125 * into the LFB area if the given mem parameter is
3126 * higher than the size of the UMA memory.
3127 *
3128 * Basically given by "mem" parameter
3129 *
3130 * maximum = videosize - cmd_queue - hwcursor
3131 * (results in a heap of size 0)
3132 * default = SiS 300: depends on videosize
3133 * SiS 315/330/340/XGI: 32k below max
3134 */
3135
3136 if(ivideo->sisvga_engine == SIS_300_VGA) {
3137 if(ivideo->video_size > 0x1000000) {
3138 def = 0xc00000;
3139 } else if(ivideo->video_size > 0x800000) {
3140 def = 0x800000;
3141 } else {
3142 def = 0x400000;
3143 }
3144 } else if(ivideo->UMAsize && ivideo->LFBsize) {
3145 ret = def = 0;
3146 } else {
3147 def = maxoffs - 0x8000;
3148 }
3149
3150 /* Use default for secondary card for now (FIXME) */
3151 if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0))
3152 ret = def;
3153
3154 return ret;
3155 }
3156
sisfb_getheapsize(struct sis_video_info * ivideo)3157 static u32 sisfb_getheapsize(struct sis_video_info *ivideo)
3158 {
3159 u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3160 u32 ret = 0;
3161
3162 if(ivideo->UMAsize && ivideo->LFBsize) {
3163 if( (!ivideo->sisfb_parm_mem) ||
3164 ((ivideo->sisfb_parm_mem * 1024) > max) ||
3165 ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) {
3166 ret = ivideo->UMAsize;
3167 max -= ivideo->UMAsize;
3168 } else {
3169 ret = max - (ivideo->sisfb_parm_mem * 1024);
3170 max = ivideo->sisfb_parm_mem * 1024;
3171 }
3172 ivideo->video_offset = ret;
3173 ivideo->sisfb_mem = max;
3174 } else {
3175 ret = max - ivideo->heapstart;
3176 ivideo->sisfb_mem = ivideo->heapstart;
3177 }
3178
3179 return ret;
3180 }
3181
sisfb_heap_init(struct sis_video_info * ivideo)3182 static int sisfb_heap_init(struct sis_video_info *ivideo)
3183 {
3184 struct SIS_OH *poh;
3185
3186 ivideo->video_offset = 0;
3187 if(ivideo->sisfb_parm_mem) {
3188 if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) ||
3189 (ivideo->sisfb_parm_mem > ivideo->video_size) ) {
3190 ivideo->sisfb_parm_mem = 0;
3191 }
3192 }
3193
3194 ivideo->heapstart = sisfb_getheapstart(ivideo);
3195 ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo);
3196
3197 ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
3198 ivideo->sisfb_heap_end = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size;
3199
3200 printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
3201 (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
3202
3203 ivideo->sisfb_heap.vinfo = ivideo;
3204
3205 ivideo->sisfb_heap.poha_chain = NULL;
3206 ivideo->sisfb_heap.poh_freelist = NULL;
3207
3208 poh = sisfb_poh_new_node(&ivideo->sisfb_heap);
3209 if(poh == NULL)
3210 return 1;
3211
3212 poh->poh_next = &ivideo->sisfb_heap.oh_free;
3213 poh->poh_prev = &ivideo->sisfb_heap.oh_free;
3214 poh->size = ivideo->sisfb_heap_size;
3215 poh->offset = ivideo->heapstart;
3216
3217 ivideo->sisfb_heap.oh_free.poh_next = poh;
3218 ivideo->sisfb_heap.oh_free.poh_prev = poh;
3219 ivideo->sisfb_heap.oh_free.size = 0;
3220 ivideo->sisfb_heap.max_freesize = poh->size;
3221
3222 ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used;
3223 ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used;
3224 ivideo->sisfb_heap.oh_used.size = SENTINEL;
3225
3226 if(ivideo->cardnumber == 0) {
3227 /* For the first card, make this heap the "global" one
3228 * for old DRM (which could handle only one card)
3229 */
3230 sisfb_heap = &ivideo->sisfb_heap;
3231 }
3232
3233 return 0;
3234 }
3235
3236 static struct SIS_OH *
sisfb_poh_new_node(struct SIS_HEAP * memheap)3237 sisfb_poh_new_node(struct SIS_HEAP *memheap)
3238 {
3239 struct SIS_OHALLOC *poha;
3240 struct SIS_OH *poh;
3241 unsigned long cOhs;
3242 int i;
3243
3244 if(memheap->poh_freelist == NULL) {
3245 poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
3246 if(!poha)
3247 return NULL;
3248
3249 poha->poha_next = memheap->poha_chain;
3250 memheap->poha_chain = poha;
3251
3252 cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1;
3253
3254 poh = &poha->aoh[0];
3255 for(i = cOhs - 1; i != 0; i--) {
3256 poh->poh_next = poh + 1;
3257 poh = poh + 1;
3258 }
3259
3260 poh->poh_next = NULL;
3261 memheap->poh_freelist = &poha->aoh[0];
3262 }
3263
3264 poh = memheap->poh_freelist;
3265 memheap->poh_freelist = poh->poh_next;
3266
3267 return poh;
3268 }
3269
3270 static struct SIS_OH *
sisfb_poh_allocate(struct SIS_HEAP * memheap,u32 size)3271 sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size)
3272 {
3273 struct SIS_OH *pohThis;
3274 struct SIS_OH *pohRoot;
3275 int bAllocated = 0;
3276
3277 if(size > memheap->max_freesize) {
3278 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3279 (unsigned int) size / 1024);
3280 return NULL;
3281 }
3282
3283 pohThis = memheap->oh_free.poh_next;
3284
3285 while(pohThis != &memheap->oh_free) {
3286 if(size <= pohThis->size) {
3287 bAllocated = 1;
3288 break;
3289 }
3290 pohThis = pohThis->poh_next;
3291 }
3292
3293 if(!bAllocated) {
3294 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3295 (unsigned int) size / 1024);
3296 return NULL;
3297 }
3298
3299 if(size == pohThis->size) {
3300 pohRoot = pohThis;
3301 sisfb_delete_node(pohThis);
3302 } else {
3303 pohRoot = sisfb_poh_new_node(memheap);
3304 if(pohRoot == NULL)
3305 return NULL;
3306
3307 pohRoot->offset = pohThis->offset;
3308 pohRoot->size = size;
3309
3310 pohThis->offset += size;
3311 pohThis->size -= size;
3312 }
3313
3314 memheap->max_freesize -= size;
3315
3316 pohThis = &memheap->oh_used;
3317 sisfb_insert_node(pohThis, pohRoot);
3318
3319 return pohRoot;
3320 }
3321
3322 static void
sisfb_delete_node(struct SIS_OH * poh)3323 sisfb_delete_node(struct SIS_OH *poh)
3324 {
3325 poh->poh_prev->poh_next = poh->poh_next;
3326 poh->poh_next->poh_prev = poh->poh_prev;
3327 }
3328
3329 static void
sisfb_insert_node(struct SIS_OH * pohList,struct SIS_OH * poh)3330 sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh)
3331 {
3332 struct SIS_OH *pohTemp = pohList->poh_next;
3333
3334 pohList->poh_next = poh;
3335 pohTemp->poh_prev = poh;
3336
3337 poh->poh_prev = pohList;
3338 poh->poh_next = pohTemp;
3339 }
3340
3341 static struct SIS_OH *
sisfb_poh_free(struct SIS_HEAP * memheap,u32 base)3342 sisfb_poh_free(struct SIS_HEAP *memheap, u32 base)
3343 {
3344 struct SIS_OH *pohThis;
3345 struct SIS_OH *poh_freed;
3346 struct SIS_OH *poh_prev;
3347 struct SIS_OH *poh_next;
3348 u32 ulUpper;
3349 u32 ulLower;
3350 int foundNode = 0;
3351
3352 poh_freed = memheap->oh_used.poh_next;
3353
3354 while(poh_freed != &memheap->oh_used) {
3355 if(poh_freed->offset == base) {
3356 foundNode = 1;
3357 break;
3358 }
3359
3360 poh_freed = poh_freed->poh_next;
3361 }
3362
3363 if(!foundNode)
3364 return NULL;
3365
3366 memheap->max_freesize += poh_freed->size;
3367
3368 poh_prev = poh_next = NULL;
3369 ulUpper = poh_freed->offset + poh_freed->size;
3370 ulLower = poh_freed->offset;
3371
3372 pohThis = memheap->oh_free.poh_next;
3373
3374 while(pohThis != &memheap->oh_free) {
3375 if(pohThis->offset == ulUpper) {
3376 poh_next = pohThis;
3377 } else if((pohThis->offset + pohThis->size) == ulLower) {
3378 poh_prev = pohThis;
3379 }
3380 pohThis = pohThis->poh_next;
3381 }
3382
3383 sisfb_delete_node(poh_freed);
3384
3385 if(poh_prev && poh_next) {
3386 poh_prev->size += (poh_freed->size + poh_next->size);
3387 sisfb_delete_node(poh_next);
3388 sisfb_free_node(memheap, poh_freed);
3389 sisfb_free_node(memheap, poh_next);
3390 return poh_prev;
3391 }
3392
3393 if(poh_prev) {
3394 poh_prev->size += poh_freed->size;
3395 sisfb_free_node(memheap, poh_freed);
3396 return poh_prev;
3397 }
3398
3399 if(poh_next) {
3400 poh_next->size += poh_freed->size;
3401 poh_next->offset = poh_freed->offset;
3402 sisfb_free_node(memheap, poh_freed);
3403 return poh_next;
3404 }
3405
3406 sisfb_insert_node(&memheap->oh_free, poh_freed);
3407
3408 return poh_freed;
3409 }
3410
3411 static void
sisfb_free_node(struct SIS_HEAP * memheap,struct SIS_OH * poh)3412 sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh)
3413 {
3414 if(poh == NULL)
3415 return;
3416
3417 poh->poh_next = memheap->poh_freelist;
3418 memheap->poh_freelist = poh;
3419 }
3420
3421 static void
sis_int_malloc(struct sis_video_info * ivideo,struct sis_memreq * req)3422 sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req)
3423 {
3424 struct SIS_OH *poh = NULL;
3425
3426 if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap))
3427 poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size);
3428
3429 if(poh == NULL) {
3430 req->offset = req->size = 0;
3431 DPRINTK("sisfb: Video RAM allocation failed\n");
3432 } else {
3433 req->offset = poh->offset;
3434 req->size = poh->size;
3435 DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3436 (poh->offset + ivideo->video_vbase));
3437 }
3438 }
3439
3440 void
sis_malloc(struct sis_memreq * req)3441 sis_malloc(struct sis_memreq *req)
3442 {
3443 struct sis_video_info *ivideo = sisfb_heap->vinfo;
3444
3445 if(&ivideo->sisfb_heap == sisfb_heap)
3446 sis_int_malloc(ivideo, req);
3447 else
3448 req->offset = req->size = 0;
3449 }
3450
3451 void
sis_malloc_new(struct pci_dev * pdev,struct sis_memreq * req)3452 sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
3453 {
3454 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3455
3456 sis_int_malloc(ivideo, req);
3457 }
3458
3459 /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3460
3461 static void
sis_int_free(struct sis_video_info * ivideo,u32 base)3462 sis_int_free(struct sis_video_info *ivideo, u32 base)
3463 {
3464 struct SIS_OH *poh;
3465
3466 if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap))
3467 return;
3468
3469 poh = sisfb_poh_free(&ivideo->sisfb_heap, base);
3470
3471 if(poh == NULL) {
3472 DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
3473 (unsigned int) base);
3474 }
3475 }
3476
3477 void
sis_free(u32 base)3478 sis_free(u32 base)
3479 {
3480 struct sis_video_info *ivideo = sisfb_heap->vinfo;
3481
3482 sis_int_free(ivideo, base);
3483 }
3484
3485 void
sis_free_new(struct pci_dev * pdev,u32 base)3486 sis_free_new(struct pci_dev *pdev, u32 base)
3487 {
3488 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3489
3490 sis_int_free(ivideo, base);
3491 }
3492
3493 /* --------------------- SetMode routines ------------------------- */
3494
3495 static void
sisfb_check_engine_and_sync(struct sis_video_info * ivideo)3496 sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
3497 {
3498 u8 cr30, cr31;
3499
3500 /* Check if MMIO and engines are enabled,
3501 * and sync in case they are. Can't use
3502 * ivideo->accel here, as this might have
3503 * been changed before this is called.
3504 */
3505 cr30 = SiS_GetReg(SISSR, IND_SIS_PCI_ADDRESS_SET);
3506 cr31 = SiS_GetReg(SISSR, IND_SIS_MODULE_ENABLE);
3507 /* MMIO and 2D/3D engine enabled? */
3508 if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
3509 #ifdef CONFIG_FB_SIS_300
3510 if(ivideo->sisvga_engine == SIS_300_VGA) {
3511 /* Don't care about TurboQueue. It's
3512 * enough to know that the engines
3513 * are enabled
3514 */
3515 sisfb_syncaccel(ivideo);
3516 }
3517 #endif
3518 #ifdef CONFIG_FB_SIS_315
3519 if(ivideo->sisvga_engine == SIS_315_VGA) {
3520 /* Check that any queue mode is
3521 * enabled, and that the queue
3522 * is not in the state of "reset"
3523 */
3524 cr30 = SiS_GetReg(SISSR, 0x26);
3525 if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
3526 sisfb_syncaccel(ivideo);
3527 }
3528 }
3529 #endif
3530 }
3531 }
3532
3533 static void
sisfb_pre_setmode(struct sis_video_info * ivideo)3534 sisfb_pre_setmode(struct sis_video_info *ivideo)
3535 {
3536 u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
3537 int tvregnum = 0;
3538
3539 ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
3540
3541 SiS_SetReg(SISSR, 0x05, 0x86);
3542
3543 cr31 = SiS_GetReg(SISCR, 0x31);
3544 cr31 &= ~0x60;
3545 cr31 |= 0x04;
3546
3547 cr33 = ivideo->rate_idx & 0x0F;
3548
3549 #ifdef CONFIG_FB_SIS_315
3550 if(ivideo->sisvga_engine == SIS_315_VGA) {
3551 if(ivideo->chip >= SIS_661) {
3552 cr38 = SiS_GetReg(SISCR, 0x38);
3553 cr38 &= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
3554 } else {
3555 tvregnum = 0x38;
3556 cr38 = SiS_GetReg(SISCR, tvregnum);
3557 cr38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
3558 }
3559 }
3560 #endif
3561 #ifdef CONFIG_FB_SIS_300
3562 if(ivideo->sisvga_engine == SIS_300_VGA) {
3563 tvregnum = 0x35;
3564 cr38 = SiS_GetReg(SISCR, tvregnum);
3565 }
3566 #endif
3567
3568 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
3569 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
3570 ivideo->curFSTN = ivideo->curDSTN = 0;
3571
3572 switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
3573
3574 case CRT2_TV:
3575 cr38 &= ~0xc0; /* Clear PAL-M / PAL-N bits */
3576 if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
3577 #ifdef CONFIG_FB_SIS_315
3578 if(ivideo->chip >= SIS_661) {
3579 cr38 |= 0x04;
3580 if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20;
3581 else if(ivideo->vbflags & TV_YPBPR750P) cr35 |= 0x40;
3582 else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
3583 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3584 cr35 &= ~0x01;
3585 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3586 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
3587 cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3588 cr38 |= 0x08;
3589 if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10;
3590 else if(ivideo->vbflags & TV_YPBPR750P) cr38 |= 0x20;
3591 else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
3592 cr31 &= ~0x01;
3593 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3594 }
3595 #endif
3596 } else if((ivideo->vbflags & TV_HIVISION) &&
3597 (ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) {
3598 if(ivideo->chip >= SIS_661) {
3599 cr38 |= 0x04;
3600 cr35 |= 0x60;
3601 } else {
3602 cr30 |= 0x80;
3603 }
3604 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3605 cr31 |= 0x01;
3606 cr35 |= 0x01;
3607 ivideo->currentvbflags |= TV_HIVISION;
3608 } else if(ivideo->vbflags & TV_SCART) {
3609 cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
3610 cr31 |= 0x01;
3611 cr35 |= 0x01;
3612 ivideo->currentvbflags |= TV_SCART;
3613 } else {
3614 if(ivideo->vbflags & TV_SVIDEO) {
3615 cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
3616 ivideo->currentvbflags |= TV_SVIDEO;
3617 }
3618 if(ivideo->vbflags & TV_AVIDEO) {
3619 cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
3620 ivideo->currentvbflags |= TV_AVIDEO;
3621 }
3622 }
3623 cr31 |= SIS_DRIVER_MODE;
3624
3625 if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) {
3626 if(ivideo->vbflags & TV_PAL) {
3627 cr31 |= 0x01; cr35 |= 0x01;
3628 ivideo->currentvbflags |= TV_PAL;
3629 if(ivideo->vbflags & TV_PALM) {
3630 cr38 |= 0x40; cr35 |= 0x04;
3631 ivideo->currentvbflags |= TV_PALM;
3632 } else if(ivideo->vbflags & TV_PALN) {
3633 cr38 |= 0x80; cr35 |= 0x08;
3634 ivideo->currentvbflags |= TV_PALN;
3635 }
3636 } else {
3637 cr31 &= ~0x01; cr35 &= ~0x01;
3638 ivideo->currentvbflags |= TV_NTSC;
3639 if(ivideo->vbflags & TV_NTSCJ) {
3640 cr38 |= 0x40; cr35 |= 0x02;
3641 ivideo->currentvbflags |= TV_NTSCJ;
3642 }
3643 }
3644 }
3645 break;
3646
3647 case CRT2_LCD:
3648 cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
3649 cr31 |= SIS_DRIVER_MODE;
3650 SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
3651 SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
3652 ivideo->curFSTN = ivideo->sisfb_fstn;
3653 ivideo->curDSTN = ivideo->sisfb_dstn;
3654 break;
3655
3656 case CRT2_VGA:
3657 cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3658 cr31 |= SIS_DRIVER_MODE;
3659 if(ivideo->sisfb_nocrt2rate) {
3660 cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4);
3661 } else {
3662 cr33 |= ((ivideo->rate_idx & 0x0F) << 4);
3663 }
3664 break;
3665
3666 default: /* disable CRT2 */
3667 cr30 = 0x00;
3668 cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
3669 }
3670
3671 SiS_SetReg(SISCR, 0x30, cr30);
3672 SiS_SetReg(SISCR, 0x33, cr33);
3673
3674 if(ivideo->chip >= SIS_661) {
3675 #ifdef CONFIG_FB_SIS_315
3676 cr31 &= ~0x01; /* Clear PAL flag (now in CR35) */
3677 SiS_SetRegANDOR(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
3678 cr38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
3679 SiS_SetRegANDOR(SISCR, 0x38, 0xf8, cr38);
3680 #endif
3681 } else if(ivideo->chip != SIS_300) {
3682 SiS_SetReg(SISCR, tvregnum, cr38);
3683 }
3684 SiS_SetReg(SISCR, 0x31, cr31);
3685
3686 ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
3687
3688 sisfb_check_engine_and_sync(ivideo);
3689 }
3690
3691 /* Fix SR11 for 661 and later */
3692 #ifdef CONFIG_FB_SIS_315
3693 static void
sisfb_fixup_SR11(struct sis_video_info * ivideo)3694 sisfb_fixup_SR11(struct sis_video_info *ivideo)
3695 {
3696 u8 tmpreg;
3697
3698 if(ivideo->chip >= SIS_661) {
3699 tmpreg = SiS_GetReg(SISSR, 0x11);
3700 if(tmpreg & 0x20) {
3701 tmpreg = SiS_GetReg(SISSR, 0x3e);
3702 tmpreg = (tmpreg + 1) & 0xff;
3703 SiS_SetReg(SISSR, 0x3e, tmpreg);
3704 tmpreg = SiS_GetReg(SISSR, 0x11);
3705 }
3706 if(tmpreg & 0xf0) {
3707 SiS_SetRegAND(SISSR, 0x11, 0x0f);
3708 }
3709 }
3710 }
3711 #endif
3712
3713 static void
sisfb_set_TVxposoffset(struct sis_video_info * ivideo,int val)3714 sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
3715 {
3716 if(val > 32) val = 32;
3717 if(val < -32) val = -32;
3718 ivideo->tvxpos = val;
3719
3720 if(ivideo->sisfblocked) return;
3721 if(!ivideo->modechanged) return;
3722
3723 if(ivideo->currentvbflags & CRT2_TV) {
3724
3725 if(ivideo->vbflags2 & VB2_CHRONTEL) {
3726
3727 int x = ivideo->tvx;
3728
3729 switch(ivideo->chronteltype) {
3730 case 1:
3731 x += val;
3732 if(x < 0) x = 0;
3733 SiS_SetReg(SISSR, 0x05, 0x86);
3734 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
3735 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
3736 break;
3737 case 2:
3738 /* Not supported by hardware */
3739 break;
3740 }
3741
3742 } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3743
3744 u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
3745 unsigned short temp;
3746
3747 p2_1f = ivideo->p2_1f;
3748 p2_20 = ivideo->p2_20;
3749 p2_2b = ivideo->p2_2b;
3750 p2_42 = ivideo->p2_42;
3751 p2_43 = ivideo->p2_43;
3752
3753 temp = p2_1f | ((p2_20 & 0xf0) << 4);
3754 temp += (val * 2);
3755 p2_1f = temp & 0xff;
3756 p2_20 = (temp & 0xf00) >> 4;
3757 p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
3758 temp = p2_43 | ((p2_42 & 0xf0) << 4);
3759 temp += (val * 2);
3760 p2_43 = temp & 0xff;
3761 p2_42 = (temp & 0xf00) >> 4;
3762 SiS_SetReg(SISPART2, 0x1f, p2_1f);
3763 SiS_SetRegANDOR(SISPART2, 0x20, 0x0F, p2_20);
3764 SiS_SetRegANDOR(SISPART2, 0x2b, 0xF0, p2_2b);
3765 SiS_SetRegANDOR(SISPART2, 0x42, 0x0F, p2_42);
3766 SiS_SetReg(SISPART2, 0x43, p2_43);
3767 }
3768 }
3769 }
3770
3771 static void
sisfb_set_TVyposoffset(struct sis_video_info * ivideo,int val)3772 sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
3773 {
3774 if(val > 32) val = 32;
3775 if(val < -32) val = -32;
3776 ivideo->tvypos = val;
3777
3778 if(ivideo->sisfblocked) return;
3779 if(!ivideo->modechanged) return;
3780
3781 if(ivideo->currentvbflags & CRT2_TV) {
3782
3783 if(ivideo->vbflags2 & VB2_CHRONTEL) {
3784
3785 int y = ivideo->tvy;
3786
3787 switch(ivideo->chronteltype) {
3788 case 1:
3789 y -= val;
3790 if(y < 0) y = 0;
3791 SiS_SetReg(SISSR, 0x05, 0x86);
3792 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
3793 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
3794 break;
3795 case 2:
3796 /* Not supported by hardware */
3797 break;
3798 }
3799
3800 } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3801
3802 char p2_01, p2_02;
3803 val /= 2;
3804 p2_01 = ivideo->p2_01;
3805 p2_02 = ivideo->p2_02;
3806
3807 p2_01 += val;
3808 p2_02 += val;
3809 if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) {
3810 while((p2_01 <= 0) || (p2_02 <= 0)) {
3811 p2_01 += 2;
3812 p2_02 += 2;
3813 }
3814 }
3815 SiS_SetReg(SISPART2, 0x01, p2_01);
3816 SiS_SetReg(SISPART2, 0x02, p2_02);
3817 }
3818 }
3819 }
3820
3821 static void
sisfb_post_setmode(struct sis_video_info * ivideo)3822 sisfb_post_setmode(struct sis_video_info *ivideo)
3823 {
3824 bool crt1isoff = false;
3825 bool doit = true;
3826 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
3827 u8 reg;
3828 #endif
3829 #ifdef CONFIG_FB_SIS_315
3830 u8 reg1;
3831 #endif
3832
3833 SiS_SetReg(SISSR, 0x05, 0x86);
3834
3835 #ifdef CONFIG_FB_SIS_315
3836 sisfb_fixup_SR11(ivideo);
3837 #endif
3838
3839 /* Now we actually HAVE changed the display mode */
3840 ivideo->modechanged = 1;
3841
3842 /* We can't switch off CRT1 if bridge is in slave mode */
3843 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
3844 if(sisfb_bridgeisslave(ivideo)) doit = false;
3845 } else
3846 ivideo->sisfb_crt1off = 0;
3847
3848 #ifdef CONFIG_FB_SIS_300
3849 if(ivideo->sisvga_engine == SIS_300_VGA) {
3850 if((ivideo->sisfb_crt1off) && (doit)) {
3851 crt1isoff = true;
3852 reg = 0x00;
3853 } else {
3854 crt1isoff = false;
3855 reg = 0x80;
3856 }
3857 SiS_SetRegANDOR(SISCR, 0x17, 0x7f, reg);
3858 }
3859 #endif
3860 #ifdef CONFIG_FB_SIS_315
3861 if(ivideo->sisvga_engine == SIS_315_VGA) {
3862 if((ivideo->sisfb_crt1off) && (doit)) {
3863 crt1isoff = true;
3864 reg = 0x40;
3865 reg1 = 0xc0;
3866 } else {
3867 crt1isoff = false;
3868 reg = 0x00;
3869 reg1 = 0x00;
3870 }
3871 SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
3872 SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, reg1);
3873 }
3874 #endif
3875
3876 if(crt1isoff) {
3877 ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
3878 ivideo->currentvbflags |= VB_SINGLE_MODE;
3879 } else {
3880 ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
3881 if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
3882 ivideo->currentvbflags |= VB_MIRROR_MODE;
3883 } else {
3884 ivideo->currentvbflags |= VB_SINGLE_MODE;
3885 }
3886 }
3887
3888 SiS_SetRegAND(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
3889
3890 if(ivideo->currentvbflags & CRT2_TV) {
3891 if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3892 ivideo->p2_1f = SiS_GetReg(SISPART2, 0x1f);
3893 ivideo->p2_20 = SiS_GetReg(SISPART2, 0x20);
3894 ivideo->p2_2b = SiS_GetReg(SISPART2, 0x2b);
3895 ivideo->p2_42 = SiS_GetReg(SISPART2, 0x42);
3896 ivideo->p2_43 = SiS_GetReg(SISPART2, 0x43);
3897 ivideo->p2_01 = SiS_GetReg(SISPART2, 0x01);
3898 ivideo->p2_02 = SiS_GetReg(SISPART2, 0x02);
3899 } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
3900 if(ivideo->chronteltype == 1) {
3901 ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
3902 ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
3903 ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
3904 ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
3905 }
3906 }
3907 }
3908
3909 if(ivideo->tvxpos) {
3910 sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
3911 }
3912 if(ivideo->tvypos) {
3913 sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
3914 }
3915
3916 /* Eventually sync engines */
3917 sisfb_check_engine_and_sync(ivideo);
3918
3919 /* (Re-)Initialize chip engines */
3920 if(ivideo->accel) {
3921 sisfb_engine_init(ivideo);
3922 } else {
3923 ivideo->engineok = 0;
3924 }
3925 }
3926
3927 static int
sisfb_reset_mode(struct sis_video_info * ivideo)3928 sisfb_reset_mode(struct sis_video_info *ivideo)
3929 {
3930 if(sisfb_set_mode(ivideo, 0))
3931 return 1;
3932
3933 sisfb_set_pitch(ivideo);
3934 sisfb_set_base_CRT1(ivideo, ivideo->current_base);
3935 sisfb_set_base_CRT2(ivideo, ivideo->current_base);
3936
3937 return 0;
3938 }
3939
3940 static void
sisfb_handle_command(struct sis_video_info * ivideo,struct sisfb_cmd * sisfb_command)3941 sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command)
3942 {
3943 int mycrt1off;
3944
3945 switch(sisfb_command->sisfb_cmd) {
3946 case SISFB_CMD_GETVBFLAGS:
3947 if(!ivideo->modechanged) {
3948 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3949 } else {
3950 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3951 sisfb_command->sisfb_result[1] = ivideo->currentvbflags;
3952 sisfb_command->sisfb_result[2] = ivideo->vbflags2;
3953 }
3954 break;
3955 case SISFB_CMD_SWITCHCRT1:
3956 /* arg[0]: 0 = off, 1 = on, 99 = query */
3957 if(!ivideo->modechanged) {
3958 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3959 } else if(sisfb_command->sisfb_arg[0] == 99) {
3960 /* Query */
3961 sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3962 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3963 } else if(ivideo->sisfblocked) {
3964 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED;
3965 } else if((!(ivideo->currentvbflags & CRT2_ENABLE)) &&
3966 (sisfb_command->sisfb_arg[0] == 0)) {
3967 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2;
3968 } else {
3969 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3970 mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1;
3971 if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) ||
3972 ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) {
3973 ivideo->sisfb_crt1off = mycrt1off;
3974 if(sisfb_reset_mode(ivideo)) {
3975 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER;
3976 }
3977 }
3978 sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3979 }
3980 break;
3981 /* more to come */
3982 default:
3983 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN;
3984 printk(KERN_ERR "sisfb: Unknown command 0x%x\n",
3985 sisfb_command->sisfb_cmd);
3986 }
3987 }
3988
3989 #ifndef MODULE
sisfb_setup(char * options)3990 static int __init sisfb_setup(char *options)
3991 {
3992 char *this_opt;
3993
3994 sisfb_setdefaultparms();
3995
3996 if(!options || !(*options))
3997 return 0;
3998
3999 while((this_opt = strsep(&options, ",")) != NULL) {
4000
4001 if(!(*this_opt)) continue;
4002
4003 if(!strncasecmp(this_opt, "off", 3)) {
4004 sisfb_off = 1;
4005 } else if(!strncasecmp(this_opt, "forcecrt2type:", 14)) {
4006 /* Need to check crt2 type first for fstn/dstn */
4007 sisfb_search_crt2type(this_opt + 14);
4008 } else if(!strncasecmp(this_opt, "tvmode:",7)) {
4009 sisfb_search_tvstd(this_opt + 7);
4010 } else if(!strncasecmp(this_opt, "tvstandard:",11)) {
4011 sisfb_search_tvstd(this_opt + 11);
4012 } else if(!strncasecmp(this_opt, "mode:", 5)) {
4013 sisfb_search_mode(this_opt + 5, false);
4014 } else if(!strncasecmp(this_opt, "vesa:", 5)) {
4015 sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false);
4016 } else if(!strncasecmp(this_opt, "rate:", 5)) {
4017 sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
4018 } else if(!strncasecmp(this_opt, "forcecrt1:", 10)) {
4019 sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
4020 } else if(!strncasecmp(this_opt, "mem:",4)) {
4021 sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
4022 } else if(!strncasecmp(this_opt, "pdc:", 4)) {
4023 sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
4024 } else if(!strncasecmp(this_opt, "pdc1:", 5)) {
4025 sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
4026 } else if(!strncasecmp(this_opt, "noaccel", 7)) {
4027 sisfb_accel = 0;
4028 } else if(!strncasecmp(this_opt, "accel", 5)) {
4029 sisfb_accel = -1;
4030 } else if(!strncasecmp(this_opt, "noypan", 6)) {
4031 sisfb_ypan = 0;
4032 } else if(!strncasecmp(this_opt, "ypan", 4)) {
4033 sisfb_ypan = -1;
4034 } else if(!strncasecmp(this_opt, "nomax", 5)) {
4035 sisfb_max = 0;
4036 } else if(!strncasecmp(this_opt, "max", 3)) {
4037 sisfb_max = -1;
4038 } else if(!strncasecmp(this_opt, "userom:", 7)) {
4039 sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
4040 } else if(!strncasecmp(this_opt, "useoem:", 7)) {
4041 sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
4042 } else if(!strncasecmp(this_opt, "nocrt2rate", 10)) {
4043 sisfb_nocrt2rate = 1;
4044 } else if(!strncasecmp(this_opt, "scalelcd:", 9)) {
4045 unsigned long temp = 2;
4046 temp = simple_strtoul(this_opt + 9, NULL, 0);
4047 if((temp == 0) || (temp == 1)) {
4048 sisfb_scalelcd = temp ^ 1;
4049 }
4050 } else if(!strncasecmp(this_opt, "tvxposoffset:", 13)) {
4051 int temp = 0;
4052 temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4053 if((temp >= -32) && (temp <= 32)) {
4054 sisfb_tvxposoffset = temp;
4055 }
4056 } else if(!strncasecmp(this_opt, "tvyposoffset:", 13)) {
4057 int temp = 0;
4058 temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4059 if((temp >= -32) && (temp <= 32)) {
4060 sisfb_tvyposoffset = temp;
4061 }
4062 } else if(!strncasecmp(this_opt, "specialtiming:", 14)) {
4063 sisfb_search_specialtiming(this_opt + 14);
4064 } else if(!strncasecmp(this_opt, "lvdshl:", 7)) {
4065 int temp = 4;
4066 temp = simple_strtoul(this_opt + 7, NULL, 0);
4067 if((temp >= 0) && (temp <= 3)) {
4068 sisfb_lvdshl = temp;
4069 }
4070 } else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
4071 sisfb_search_mode(this_opt, true);
4072 #if !defined(__i386__) && !defined(__x86_64__)
4073 } else if(!strncasecmp(this_opt, "resetcard", 9)) {
4074 sisfb_resetcard = 1;
4075 } else if(!strncasecmp(this_opt, "videoram:", 9)) {
4076 sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
4077 #endif
4078 } else {
4079 printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
4080 }
4081
4082 }
4083
4084 return 0;
4085 }
4086 #endif
4087
sisfb_check_rom(void __iomem * rom_base,struct sis_video_info * ivideo)4088 static int sisfb_check_rom(void __iomem *rom_base,
4089 struct sis_video_info *ivideo)
4090 {
4091 void __iomem *rom;
4092 int romptr;
4093
4094 if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
4095 return 0;
4096
4097 romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
4098 if(romptr > (0x10000 - 8))
4099 return 0;
4100
4101 rom = rom_base + romptr;
4102
4103 if((readb(rom) != 'P') || (readb(rom + 1) != 'C') ||
4104 (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R'))
4105 return 0;
4106
4107 if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor)
4108 return 0;
4109
4110 if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id)
4111 return 0;
4112
4113 return 1;
4114 }
4115
sisfb_find_rom(struct pci_dev * pdev)4116 static unsigned char *sisfb_find_rom(struct pci_dev *pdev)
4117 {
4118 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4119 void __iomem *rom_base;
4120 unsigned char *myrombase = NULL;
4121 size_t romsize;
4122
4123 /* First, try the official pci ROM functions (except
4124 * on integrated chipsets which have no ROM).
4125 */
4126
4127 if(!ivideo->nbridge) {
4128
4129 if((rom_base = pci_map_rom(pdev, &romsize))) {
4130
4131 if(sisfb_check_rom(rom_base, ivideo)) {
4132
4133 if((myrombase = vmalloc(65536))) {
4134 memcpy_fromio(myrombase, rom_base,
4135 (romsize > 65536) ? 65536 : romsize);
4136 }
4137 }
4138 pci_unmap_rom(pdev, rom_base);
4139 }
4140 }
4141
4142 if(myrombase) return myrombase;
4143
4144 /* Otherwise do it the conventional way. */
4145
4146 #if defined(__i386__) || defined(__x86_64__)
4147 {
4148 u32 temp;
4149
4150 for (temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
4151
4152 rom_base = ioremap(temp, 65536);
4153 if (!rom_base)
4154 continue;
4155
4156 if (!sisfb_check_rom(rom_base, ivideo)) {
4157 iounmap(rom_base);
4158 continue;
4159 }
4160
4161 if ((myrombase = vmalloc(65536)))
4162 memcpy_fromio(myrombase, rom_base, 65536);
4163
4164 iounmap(rom_base);
4165 break;
4166
4167 }
4168
4169 }
4170 #endif
4171
4172 return myrombase;
4173 }
4174
sisfb_post_map_vram(struct sis_video_info * ivideo,unsigned int * mapsize,unsigned int min)4175 static void sisfb_post_map_vram(struct sis_video_info *ivideo,
4176 unsigned int *mapsize, unsigned int min)
4177 {
4178 if (*mapsize < (min << 20))
4179 return;
4180
4181 ivideo->video_vbase = ioremap_wc(ivideo->video_base, (*mapsize));
4182
4183 if(!ivideo->video_vbase) {
4184 printk(KERN_ERR
4185 "sisfb: Unable to map maximum video RAM for size detection\n");
4186 (*mapsize) >>= 1;
4187 while((!(ivideo->video_vbase = ioremap_wc(ivideo->video_base, (*mapsize))))) {
4188 (*mapsize) >>= 1;
4189 if((*mapsize) < (min << 20))
4190 break;
4191 }
4192 if(ivideo->video_vbase) {
4193 printk(KERN_ERR
4194 "sisfb: Video RAM size detection limited to %dMB\n",
4195 (int)((*mapsize) >> 20));
4196 }
4197 }
4198 }
4199
4200 #ifdef CONFIG_FB_SIS_300
sisfb_post_300_buswidth(struct sis_video_info * ivideo)4201 static int sisfb_post_300_buswidth(struct sis_video_info *ivideo)
4202 {
4203 void __iomem *FBAddress = ivideo->video_vbase;
4204 unsigned short temp;
4205 unsigned char reg;
4206 int i, j;
4207
4208 SiS_SetRegAND(SISSR, 0x15, 0xFB);
4209 SiS_SetRegOR(SISSR, 0x15, 0x04);
4210 SiS_SetReg(SISSR, 0x13, 0x00);
4211 SiS_SetReg(SISSR, 0x14, 0xBF);
4212
4213 for(i = 0; i < 2; i++) {
4214 temp = 0x1234;
4215 for(j = 0; j < 4; j++) {
4216 writew(temp, FBAddress);
4217 if(readw(FBAddress) == temp)
4218 break;
4219 SiS_SetRegOR(SISSR, 0x3c, 0x01);
4220 reg = SiS_GetReg(SISSR, 0x05);
4221 reg = SiS_GetReg(SISSR, 0x05);
4222 SiS_SetRegAND(SISSR, 0x3c, 0xfe);
4223 reg = SiS_GetReg(SISSR, 0x05);
4224 reg = SiS_GetReg(SISSR, 0x05);
4225 temp++;
4226 }
4227 }
4228
4229 writel(0x01234567L, FBAddress);
4230 writel(0x456789ABL, (FBAddress + 4));
4231 writel(0x89ABCDEFL, (FBAddress + 8));
4232 writel(0xCDEF0123L, (FBAddress + 12));
4233
4234 reg = SiS_GetReg(SISSR, 0x3b);
4235 if(reg & 0x01) {
4236 if(readl((FBAddress + 12)) == 0xCDEF0123L)
4237 return 4; /* Channel A 128bit */
4238 }
4239
4240 if(readl((FBAddress + 4)) == 0x456789ABL)
4241 return 2; /* Channel B 64bit */
4242
4243 return 1; /* 32bit */
4244 }
4245
4246 static const unsigned short SiS_DRAMType[17][5] = {
4247 {0x0C,0x0A,0x02,0x40,0x39},
4248 {0x0D,0x0A,0x01,0x40,0x48},
4249 {0x0C,0x09,0x02,0x20,0x35},
4250 {0x0D,0x09,0x01,0x20,0x44},
4251 {0x0C,0x08,0x02,0x10,0x31},
4252 {0x0D,0x08,0x01,0x10,0x40},
4253 {0x0C,0x0A,0x01,0x20,0x34},
4254 {0x0C,0x09,0x01,0x08,0x32},
4255 {0x0B,0x08,0x02,0x08,0x21},
4256 {0x0C,0x08,0x01,0x08,0x30},
4257 {0x0A,0x08,0x02,0x04,0x11},
4258 {0x0B,0x0A,0x01,0x10,0x28},
4259 {0x09,0x08,0x02,0x02,0x01},
4260 {0x0B,0x09,0x01,0x08,0x24},
4261 {0x0B,0x08,0x01,0x04,0x20},
4262 {0x0A,0x08,0x01,0x02,0x10},
4263 {0x09,0x08,0x01,0x01,0x00}
4264 };
4265
sisfb_post_300_rwtest(struct sis_video_info * ivideo,int iteration,int buswidth,int PseudoRankCapacity,int PseudoAdrPinCount,unsigned int mapsize)4266 static int sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration,
4267 int buswidth, int PseudoRankCapacity,
4268 int PseudoAdrPinCount, unsigned int mapsize)
4269 {
4270 void __iomem *FBAddr = ivideo->video_vbase;
4271 unsigned short sr14;
4272 unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
4273 unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
4274
4275 for (k = 0; k < ARRAY_SIZE(SiS_DRAMType); k++) {
4276 RankCapacity = buswidth * SiS_DRAMType[k][3];
4277
4278 if (RankCapacity != PseudoRankCapacity)
4279 continue;
4280
4281 if ((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
4282 continue;
4283
4284 BankNumHigh = RankCapacity * 16 * iteration - 1;
4285 if (iteration == 3) { /* Rank No */
4286 BankNumMid = RankCapacity * 16 - 1;
4287 } else {
4288 BankNumMid = RankCapacity * 16 * iteration / 2 - 1;
4289 }
4290
4291 PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
4292 PhysicalAdrHigh = BankNumHigh;
4293 PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
4294 PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
4295
4296 SiS_SetRegAND(SISSR, 0x15, 0xFB); /* Test */
4297 SiS_SetRegOR(SISSR, 0x15, 0x04); /* Test */
4298 sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
4299
4300 if (buswidth == 4)
4301 sr14 |= 0x80;
4302 else if (buswidth == 2)
4303 sr14 |= 0x40;
4304
4305 SiS_SetReg(SISSR, 0x13, SiS_DRAMType[k][4]);
4306 SiS_SetReg(SISSR, 0x14, sr14);
4307
4308 BankNumHigh <<= 16;
4309 BankNumMid <<= 16;
4310
4311 if ((BankNumHigh + PhysicalAdrHigh >= mapsize) ||
4312 (BankNumMid + PhysicalAdrHigh >= mapsize) ||
4313 (BankNumHigh + PhysicalAdrHalfPage >= mapsize) ||
4314 (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
4315 continue;
4316
4317 /* Write data */
4318 writew(((unsigned short)PhysicalAdrHigh),
4319 (FBAddr + BankNumHigh + PhysicalAdrHigh));
4320 writew(((unsigned short)BankNumMid),
4321 (FBAddr + BankNumMid + PhysicalAdrHigh));
4322 writew(((unsigned short)PhysicalAdrHalfPage),
4323 (FBAddr + BankNumHigh + PhysicalAdrHalfPage));
4324 writew(((unsigned short)PhysicalAdrOtherPage),
4325 (FBAddr + BankNumHigh + PhysicalAdrOtherPage));
4326
4327 /* Read data */
4328 if (readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
4329 return 1;
4330 }
4331
4332 return 0;
4333 }
4334
sisfb_post_300_ramsize(struct pci_dev * pdev,unsigned int mapsize)4335 static void sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
4336 {
4337 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4338 int i, j, buswidth;
4339 int PseudoRankCapacity, PseudoAdrPinCount;
4340
4341 buswidth = sisfb_post_300_buswidth(ivideo);
4342
4343 for(i = 6; i >= 0; i--) {
4344 PseudoRankCapacity = 1 << i;
4345 for(j = 4; j >= 1; j--) {
4346 PseudoAdrPinCount = 15 - j;
4347 if((PseudoRankCapacity * j) <= 64) {
4348 if(sisfb_post_300_rwtest(ivideo,
4349 j,
4350 buswidth,
4351 PseudoRankCapacity,
4352 PseudoAdrPinCount,
4353 mapsize))
4354 return;
4355 }
4356 }
4357 }
4358 }
4359
sisfb_post_sis300(struct pci_dev * pdev)4360 static void sisfb_post_sis300(struct pci_dev *pdev)
4361 {
4362 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4363 unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
4364 u8 reg, v1, v2, v3, v4, v5, v6, v7, v8;
4365 u16 index, rindex, memtype = 0;
4366 unsigned int mapsize;
4367
4368 if(!ivideo->SiS_Pr.UseROM)
4369 bios = NULL;
4370
4371 SiS_SetReg(SISSR, 0x05, 0x86);
4372
4373 if(bios) {
4374 if(bios[0x52] & 0x80) {
4375 memtype = bios[0x52];
4376 } else {
4377 memtype = SiS_GetReg(SISSR, 0x3a);
4378 }
4379 memtype &= 0x07;
4380 }
4381
4382 v3 = 0x80; v6 = 0x80;
4383 if(ivideo->revision_id <= 0x13) {
4384 v1 = 0x44; v2 = 0x42;
4385 v4 = 0x44; v5 = 0x42;
4386 } else {
4387 v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */
4388 v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */
4389 if(bios) {
4390 index = memtype * 5;
4391 rindex = index + 0x54;
4392 v1 = bios[rindex++];
4393 v2 = bios[rindex++];
4394 v3 = bios[rindex++];
4395 rindex = index + 0x7c;
4396 v4 = bios[rindex++];
4397 v5 = bios[rindex++];
4398 v6 = bios[rindex++];
4399 }
4400 }
4401 SiS_SetReg(SISSR, 0x28, v1);
4402 SiS_SetReg(SISSR, 0x29, v2);
4403 SiS_SetReg(SISSR, 0x2a, v3);
4404 SiS_SetReg(SISSR, 0x2e, v4);
4405 SiS_SetReg(SISSR, 0x2f, v5);
4406 SiS_SetReg(SISSR, 0x30, v6);
4407
4408 v1 = 0x10;
4409 if(bios)
4410 v1 = bios[0xa4];
4411 SiS_SetReg(SISSR, 0x07, v1); /* DAC speed */
4412
4413 SiS_SetReg(SISSR, 0x11, 0x0f); /* DDC, power save */
4414
4415 v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
4416 v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
4417 if(bios) {
4418 memtype += 0xa5;
4419 v1 = bios[memtype];
4420 v2 = bios[memtype + 8];
4421 v3 = bios[memtype + 16];
4422 v4 = bios[memtype + 24];
4423 v5 = bios[memtype + 32];
4424 v6 = bios[memtype + 40];
4425 v7 = bios[memtype + 48];
4426 v8 = bios[memtype + 56];
4427 }
4428 if(ivideo->revision_id >= 0x80)
4429 v3 &= 0xfd;
4430 SiS_SetReg(SISSR, 0x15, v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4431 SiS_SetReg(SISSR, 0x16, v2);
4432 SiS_SetReg(SISSR, 0x17, v3);
4433 SiS_SetReg(SISSR, 0x18, v4);
4434 SiS_SetReg(SISSR, 0x19, v5);
4435 SiS_SetReg(SISSR, 0x1a, v6);
4436 SiS_SetReg(SISSR, 0x1b, v7);
4437 SiS_SetReg(SISSR, 0x1c, v8); /* ---- */
4438 SiS_SetRegAND(SISSR, 0x15, 0xfb);
4439 SiS_SetRegOR(SISSR, 0x15, 0x04);
4440 if(bios) {
4441 if(bios[0x53] & 0x02) {
4442 SiS_SetRegOR(SISSR, 0x19, 0x20);
4443 }
4444 }
4445 v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */
4446 if(ivideo->revision_id >= 0x80)
4447 v1 |= 0x01;
4448 SiS_SetReg(SISSR, 0x1f, v1);
4449 SiS_SetReg(SISSR, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
4450 v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
4451 if(bios) {
4452 v1 = bios[0xe8];
4453 v2 = bios[0xe9];
4454 v3 = bios[0xea];
4455 }
4456 SiS_SetReg(SISSR, 0x23, v1);
4457 SiS_SetReg(SISSR, 0x24, v2);
4458 SiS_SetReg(SISSR, 0x25, v3);
4459 SiS_SetReg(SISSR, 0x21, 0x84);
4460 SiS_SetReg(SISSR, 0x22, 0x00);
4461 SiS_SetReg(SISCR, 0x37, 0x00);
4462 SiS_SetRegOR(SISPART1, 0x24, 0x01); /* unlock crt2 */
4463 SiS_SetReg(SISPART1, 0x00, 0x00);
4464 v1 = 0x40; v2 = 0x11;
4465 if(bios) {
4466 v1 = bios[0xec];
4467 v2 = bios[0xeb];
4468 }
4469 SiS_SetReg(SISPART1, 0x02, v1);
4470
4471 if(ivideo->revision_id >= 0x80)
4472 v2 &= ~0x01;
4473
4474 reg = SiS_GetReg(SISPART4, 0x00);
4475 if((reg == 1) || (reg == 2)) {
4476 SiS_SetReg(SISCR, 0x37, 0x02);
4477 SiS_SetReg(SISPART2, 0x00, 0x1c);
4478 v4 = 0x00; v5 = 0x00; v6 = 0x10;
4479 if (ivideo->SiS_Pr.UseROM && bios) {
4480 v4 = bios[0xf5];
4481 v5 = bios[0xf6];
4482 v6 = bios[0xf7];
4483 }
4484 SiS_SetReg(SISPART4, 0x0d, v4);
4485 SiS_SetReg(SISPART4, 0x0e, v5);
4486 SiS_SetReg(SISPART4, 0x10, v6);
4487 SiS_SetReg(SISPART4, 0x0f, 0x3f);
4488 reg = SiS_GetReg(SISPART4, 0x01);
4489 if(reg >= 0xb0) {
4490 reg = SiS_GetReg(SISPART4, 0x23);
4491 reg &= 0x20;
4492 reg <<= 1;
4493 SiS_SetReg(SISPART4, 0x23, reg);
4494 }
4495 } else {
4496 v2 &= ~0x10;
4497 }
4498 SiS_SetReg(SISSR, 0x32, v2);
4499
4500 SiS_SetRegAND(SISPART1, 0x24, 0xfe); /* Lock CRT2 */
4501
4502 reg = SiS_GetReg(SISSR, 0x16);
4503 reg &= 0xc3;
4504 SiS_SetReg(SISCR, 0x35, reg);
4505 SiS_SetReg(SISCR, 0x83, 0x00);
4506 #if !defined(__i386__) && !defined(__x86_64__)
4507 if(sisfb_videoram) {
4508 SiS_SetReg(SISSR, 0x13, 0x28); /* ? */
4509 reg = ((sisfb_videoram >> 10) - 1) | 0x40;
4510 SiS_SetReg(SISSR, 0x14, reg);
4511 } else {
4512 #endif
4513 /* Need to map max FB size for finding out about RAM size */
4514 mapsize = ivideo->video_size;
4515 sisfb_post_map_vram(ivideo, &mapsize, 4);
4516
4517 if(ivideo->video_vbase) {
4518 sisfb_post_300_ramsize(pdev, mapsize);
4519 iounmap(ivideo->video_vbase);
4520 } else {
4521 printk(KERN_DEBUG
4522 "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4523 SiS_SetReg(SISSR, 0x13, 0x28); /* ? */
4524 SiS_SetReg(SISSR, 0x14, 0x47); /* 8MB, 64bit default */
4525 }
4526 #if !defined(__i386__) && !defined(__x86_64__)
4527 }
4528 #endif
4529 if(bios) {
4530 v1 = bios[0xe6];
4531 v2 = bios[0xe7];
4532 } else {
4533 reg = SiS_GetReg(SISSR, 0x3a);
4534 if((reg & 0x30) == 0x30) {
4535 v1 = 0x04; /* PCI */
4536 v2 = 0x92;
4537 } else {
4538 v1 = 0x14; /* AGP */
4539 v2 = 0xb2;
4540 }
4541 }
4542 SiS_SetReg(SISSR, 0x21, v1);
4543 SiS_SetReg(SISSR, 0x22, v2);
4544
4545 /* Sense CRT1 */
4546 sisfb_sense_crt1(ivideo);
4547
4548 /* Set default mode, don't clear screen */
4549 ivideo->SiS_Pr.SiS_UseOEM = false;
4550 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
4551 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
4552 ivideo->curFSTN = ivideo->curDSTN = 0;
4553 ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
4554 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
4555
4556 SiS_SetReg(SISSR, 0x05, 0x86);
4557
4558 /* Display off */
4559 SiS_SetRegOR(SISSR, 0x01, 0x20);
4560
4561 /* Save mode number in CR34 */
4562 SiS_SetReg(SISCR, 0x34, 0x2e);
4563
4564 /* Let everyone know what the current mode is */
4565 ivideo->modeprechange = 0x2e;
4566 }
4567 #endif
4568
4569 #ifdef CONFIG_FB_SIS_315
4570 #if 0
4571 static void sisfb_post_sis315330(struct pci_dev *pdev)
4572 {
4573 /* TODO */
4574 }
4575 #endif
4576
sisfb_xgi_is21(struct sis_video_info * ivideo)4577 static inline int sisfb_xgi_is21(struct sis_video_info *ivideo)
4578 {
4579 return ivideo->chip_real_id == XGI_21;
4580 }
4581
sisfb_post_xgi_delay(struct sis_video_info * ivideo,int delay)4582 static void sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
4583 {
4584 unsigned int i;
4585 u8 reg;
4586
4587 for(i = 0; i <= (delay * 10 * 36); i++) {
4588 reg = SiS_GetReg(SISSR, 0x05);
4589 reg++;
4590 }
4591 }
4592
sisfb_find_host_bridge(struct sis_video_info * ivideo,struct pci_dev * mypdev,unsigned short pcivendor)4593 static int sisfb_find_host_bridge(struct sis_video_info *ivideo,
4594 struct pci_dev *mypdev,
4595 unsigned short pcivendor)
4596 {
4597 struct pci_dev *pdev = NULL;
4598 unsigned short temp;
4599 int ret = 0;
4600
4601 while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) {
4602 temp = pdev->vendor;
4603 if(temp == pcivendor) {
4604 ret = 1;
4605 pci_dev_put(pdev);
4606 break;
4607 }
4608 }
4609
4610 return ret;
4611 }
4612
sisfb_post_xgi_rwtest(struct sis_video_info * ivideo,int starta,unsigned int enda,unsigned int mapsize)4613 static int sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
4614 unsigned int enda, unsigned int mapsize)
4615 {
4616 unsigned int pos;
4617 int i;
4618
4619 writel(0, ivideo->video_vbase);
4620
4621 for(i = starta; i <= enda; i++) {
4622 pos = 1 << i;
4623 if(pos < mapsize)
4624 writel(pos, ivideo->video_vbase + pos);
4625 }
4626
4627 sisfb_post_xgi_delay(ivideo, 150);
4628
4629 if(readl(ivideo->video_vbase) != 0)
4630 return 0;
4631
4632 for(i = starta; i <= enda; i++) {
4633 pos = 1 << i;
4634 if(pos < mapsize) {
4635 if(readl(ivideo->video_vbase + pos) != pos)
4636 return 0;
4637 } else
4638 return 0;
4639 }
4640
4641 return 1;
4642 }
4643
sisfb_post_xgi_ramsize(struct sis_video_info * ivideo)4644 static int sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
4645 {
4646 unsigned int buswidth, ranksize, channelab, mapsize;
4647 int i, j, k, l, status;
4648 u8 reg, sr14;
4649 static const u8 dramsr13[12 * 5] = {
4650 0x02, 0x0e, 0x0b, 0x80, 0x5d,
4651 0x02, 0x0e, 0x0a, 0x40, 0x59,
4652 0x02, 0x0d, 0x0b, 0x40, 0x4d,
4653 0x02, 0x0e, 0x09, 0x20, 0x55,
4654 0x02, 0x0d, 0x0a, 0x20, 0x49,
4655 0x02, 0x0c, 0x0b, 0x20, 0x3d,
4656 0x02, 0x0e, 0x08, 0x10, 0x51,
4657 0x02, 0x0d, 0x09, 0x10, 0x45,
4658 0x02, 0x0c, 0x0a, 0x10, 0x39,
4659 0x02, 0x0d, 0x08, 0x08, 0x41,
4660 0x02, 0x0c, 0x09, 0x08, 0x35,
4661 0x02, 0x0c, 0x08, 0x04, 0x31
4662 };
4663 static const u8 dramsr13_4[4 * 5] = {
4664 0x02, 0x0d, 0x09, 0x40, 0x45,
4665 0x02, 0x0c, 0x09, 0x20, 0x35,
4666 0x02, 0x0c, 0x08, 0x10, 0x31,
4667 0x02, 0x0b, 0x08, 0x08, 0x21
4668 };
4669
4670 /* Enable linear mode, disable 0xa0000 address decoding */
4671 /* We disable a0000 address decoding, because
4672 * - if running on x86, if the card is disabled, it means
4673 * that another card is in the system. We don't want
4674 * to interphere with that primary card's textmode.
4675 * - if running on non-x86, there usually is no VGA window
4676 * at a0000.
4677 */
4678 SiS_SetRegOR(SISSR, 0x20, (0x80 | 0x04));
4679
4680 /* Need to map max FB size for finding out about RAM size */
4681 mapsize = ivideo->video_size;
4682 sisfb_post_map_vram(ivideo, &mapsize, 32);
4683
4684 if(!ivideo->video_vbase) {
4685 printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
4686 SiS_SetReg(SISSR, 0x13, 0x35);
4687 SiS_SetReg(SISSR, 0x14, 0x41);
4688 /* TODO */
4689 return -ENOMEM;
4690 }
4691
4692 /* Non-interleaving */
4693 SiS_SetReg(SISSR, 0x15, 0x00);
4694 /* No tiling */
4695 SiS_SetReg(SISSR, 0x1c, 0x00);
4696
4697 if(ivideo->chip == XGI_20) {
4698
4699 channelab = 1;
4700 reg = SiS_GetReg(SISCR, 0x97);
4701 if(!(reg & 0x01)) { /* Single 32/16 */
4702 buswidth = 32;
4703 SiS_SetReg(SISSR, 0x13, 0xb1);
4704 SiS_SetReg(SISSR, 0x14, 0x52);
4705 sisfb_post_xgi_delay(ivideo, 1);
4706 sr14 = 0x02;
4707 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4708 goto bail_out;
4709
4710 SiS_SetReg(SISSR, 0x13, 0x31);
4711 SiS_SetReg(SISSR, 0x14, 0x42);
4712 sisfb_post_xgi_delay(ivideo, 1);
4713 if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
4714 goto bail_out;
4715
4716 buswidth = 16;
4717 SiS_SetReg(SISSR, 0x13, 0xb1);
4718 SiS_SetReg(SISSR, 0x14, 0x41);
4719 sisfb_post_xgi_delay(ivideo, 1);
4720 sr14 = 0x01;
4721 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4722 goto bail_out;
4723 else
4724 SiS_SetReg(SISSR, 0x13, 0x31);
4725 } else { /* Dual 16/8 */
4726 buswidth = 16;
4727 SiS_SetReg(SISSR, 0x13, 0xb1);
4728 SiS_SetReg(SISSR, 0x14, 0x41);
4729 sisfb_post_xgi_delay(ivideo, 1);
4730 sr14 = 0x01;
4731 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4732 goto bail_out;
4733
4734 SiS_SetReg(SISSR, 0x13, 0x31);
4735 SiS_SetReg(SISSR, 0x14, 0x31);
4736 sisfb_post_xgi_delay(ivideo, 1);
4737 if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
4738 goto bail_out;
4739
4740 buswidth = 8;
4741 SiS_SetReg(SISSR, 0x13, 0xb1);
4742 SiS_SetReg(SISSR, 0x14, 0x30);
4743 sisfb_post_xgi_delay(ivideo, 1);
4744 sr14 = 0x00;
4745 if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
4746 goto bail_out;
4747 else
4748 SiS_SetReg(SISSR, 0x13, 0x31);
4749 }
4750
4751 } else { /* XGI_40 */
4752
4753 reg = SiS_GetReg(SISCR, 0x97);
4754 if(!(reg & 0x10)) {
4755 reg = SiS_GetReg(SISSR, 0x39);
4756 reg >>= 1;
4757 }
4758
4759 if(reg & 0x01) { /* DDRII */
4760 buswidth = 32;
4761 if(ivideo->revision_id == 2) {
4762 channelab = 2;
4763 SiS_SetReg(SISSR, 0x13, 0xa1);
4764 SiS_SetReg(SISSR, 0x14, 0x44);
4765 sr14 = 0x04;
4766 sisfb_post_xgi_delay(ivideo, 1);
4767 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4768 goto bail_out;
4769
4770 SiS_SetReg(SISSR, 0x13, 0x21);
4771 SiS_SetReg(SISSR, 0x14, 0x34);
4772 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4773 goto bail_out;
4774
4775 channelab = 1;
4776 SiS_SetReg(SISSR, 0x13, 0xa1);
4777 SiS_SetReg(SISSR, 0x14, 0x40);
4778 sr14 = 0x00;
4779 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4780 goto bail_out;
4781
4782 SiS_SetReg(SISSR, 0x13, 0x21);
4783 SiS_SetReg(SISSR, 0x14, 0x30);
4784 } else {
4785 channelab = 3;
4786 SiS_SetReg(SISSR, 0x13, 0xa1);
4787 SiS_SetReg(SISSR, 0x14, 0x4c);
4788 sr14 = 0x0c;
4789 sisfb_post_xgi_delay(ivideo, 1);
4790 if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
4791 goto bail_out;
4792
4793 channelab = 2;
4794 SiS_SetReg(SISSR, 0x14, 0x48);
4795 sisfb_post_xgi_delay(ivideo, 1);
4796 sr14 = 0x08;
4797 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4798 goto bail_out;
4799
4800 SiS_SetReg(SISSR, 0x13, 0x21);
4801 SiS_SetReg(SISSR, 0x14, 0x3c);
4802 sr14 = 0x0c;
4803
4804 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
4805 channelab = 3;
4806 } else {
4807 channelab = 2;
4808 SiS_SetReg(SISSR, 0x14, 0x38);
4809 sr14 = 0x08;
4810 }
4811 }
4812 sisfb_post_xgi_delay(ivideo, 1);
4813
4814 } else { /* DDR */
4815
4816 buswidth = 64;
4817 if(ivideo->revision_id == 2) {
4818 channelab = 1;
4819 SiS_SetReg(SISSR, 0x13, 0xa1);
4820 SiS_SetReg(SISSR, 0x14, 0x52);
4821 sisfb_post_xgi_delay(ivideo, 1);
4822 sr14 = 0x02;
4823 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4824 goto bail_out;
4825
4826 SiS_SetReg(SISSR, 0x13, 0x21);
4827 SiS_SetReg(SISSR, 0x14, 0x42);
4828 } else {
4829 channelab = 2;
4830 SiS_SetReg(SISSR, 0x13, 0xa1);
4831 SiS_SetReg(SISSR, 0x14, 0x5a);
4832 sisfb_post_xgi_delay(ivideo, 1);
4833 sr14 = 0x0a;
4834 if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
4835 goto bail_out;
4836
4837 SiS_SetReg(SISSR, 0x13, 0x21);
4838 SiS_SetReg(SISSR, 0x14, 0x4a);
4839 }
4840 sisfb_post_xgi_delay(ivideo, 1);
4841
4842 }
4843 }
4844
4845 bail_out:
4846 SiS_SetRegANDOR(SISSR, 0x14, 0xf0, sr14);
4847 sisfb_post_xgi_delay(ivideo, 1);
4848
4849 j = (ivideo->chip == XGI_20) ? 5 : 9;
4850 k = (ivideo->chip == XGI_20) ? 12 : 4;
4851 status = -EIO;
4852
4853 for(i = 0; i < k; i++) {
4854
4855 reg = (ivideo->chip == XGI_20) ?
4856 dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
4857 SiS_SetRegANDOR(SISSR, 0x13, 0x80, reg);
4858 sisfb_post_xgi_delay(ivideo, 50);
4859
4860 ranksize = (ivideo->chip == XGI_20) ?
4861 dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
4862
4863 reg = SiS_GetReg(SISSR, 0x13);
4864 if(reg & 0x80) ranksize <<= 1;
4865
4866 if(ivideo->chip == XGI_20) {
4867 if(buswidth == 16) ranksize <<= 1;
4868 else if(buswidth == 32) ranksize <<= 2;
4869 } else {
4870 if(buswidth == 64) ranksize <<= 1;
4871 }
4872
4873 reg = 0;
4874 l = channelab;
4875 if(l == 3) l = 4;
4876 if((ranksize * l) <= 256) {
4877 while((ranksize >>= 1)) reg += 0x10;
4878 }
4879
4880 if(!reg) continue;
4881
4882 SiS_SetRegANDOR(SISSR, 0x14, 0x0f, (reg & 0xf0));
4883 sisfb_post_xgi_delay(ivideo, 1);
4884
4885 if (sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize)) {
4886 status = 0;
4887 break;
4888 }
4889 }
4890
4891 iounmap(ivideo->video_vbase);
4892
4893 return status;
4894 }
4895
sisfb_post_xgi_setclocks(struct sis_video_info * ivideo,u8 regb)4896 static void sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
4897 {
4898 u8 v1, v2, v3;
4899 int index;
4900 static const u8 cs90[8 * 3] = {
4901 0x16, 0x01, 0x01,
4902 0x3e, 0x03, 0x01,
4903 0x7c, 0x08, 0x01,
4904 0x79, 0x06, 0x01,
4905 0x29, 0x01, 0x81,
4906 0x5c, 0x23, 0x01,
4907 0x5c, 0x23, 0x01,
4908 0x5c, 0x23, 0x01
4909 };
4910 static const u8 csb8[8 * 3] = {
4911 0x5c, 0x23, 0x01,
4912 0x29, 0x01, 0x01,
4913 0x7c, 0x08, 0x01,
4914 0x79, 0x06, 0x01,
4915 0x29, 0x01, 0x81,
4916 0x5c, 0x23, 0x01,
4917 0x5c, 0x23, 0x01,
4918 0x5c, 0x23, 0x01
4919 };
4920
4921 regb = 0; /* ! */
4922
4923 index = regb * 3;
4924 v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2];
4925 if(ivideo->haveXGIROM) {
4926 v1 = ivideo->bios_abase[0x90 + index];
4927 v2 = ivideo->bios_abase[0x90 + index + 1];
4928 v3 = ivideo->bios_abase[0x90 + index + 2];
4929 }
4930 SiS_SetReg(SISSR, 0x28, v1);
4931 SiS_SetReg(SISSR, 0x29, v2);
4932 SiS_SetReg(SISSR, 0x2a, v3);
4933 sisfb_post_xgi_delay(ivideo, 0x43);
4934 sisfb_post_xgi_delay(ivideo, 0x43);
4935 sisfb_post_xgi_delay(ivideo, 0x43);
4936 index = regb * 3;
4937 v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2];
4938 if(ivideo->haveXGIROM) {
4939 v1 = ivideo->bios_abase[0xb8 + index];
4940 v2 = ivideo->bios_abase[0xb8 + index + 1];
4941 v3 = ivideo->bios_abase[0xb8 + index + 2];
4942 }
4943 SiS_SetReg(SISSR, 0x2e, v1);
4944 SiS_SetReg(SISSR, 0x2f, v2);
4945 SiS_SetReg(SISSR, 0x30, v3);
4946 sisfb_post_xgi_delay(ivideo, 0x43);
4947 sisfb_post_xgi_delay(ivideo, 0x43);
4948 sisfb_post_xgi_delay(ivideo, 0x43);
4949 }
4950
sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info * ivideo,u8 regb)4951 static void sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info *ivideo,
4952 u8 regb)
4953 {
4954 unsigned char *bios = ivideo->bios_abase;
4955 u8 v1;
4956
4957 SiS_SetReg(SISSR, 0x28, 0x64);
4958 SiS_SetReg(SISSR, 0x29, 0x63);
4959 sisfb_post_xgi_delay(ivideo, 15);
4960 SiS_SetReg(SISSR, 0x18, 0x00);
4961 SiS_SetReg(SISSR, 0x19, 0x20);
4962 SiS_SetReg(SISSR, 0x16, 0x00);
4963 SiS_SetReg(SISSR, 0x16, 0x80);
4964 SiS_SetReg(SISSR, 0x18, 0xc5);
4965 SiS_SetReg(SISSR, 0x19, 0x23);
4966 SiS_SetReg(SISSR, 0x16, 0x00);
4967 SiS_SetReg(SISSR, 0x16, 0x80);
4968 sisfb_post_xgi_delay(ivideo, 1);
4969 SiS_SetReg(SISCR, 0x97, 0x11);
4970 sisfb_post_xgi_setclocks(ivideo, regb);
4971 sisfb_post_xgi_delay(ivideo, 0x46);
4972 SiS_SetReg(SISSR, 0x18, 0xc5);
4973 SiS_SetReg(SISSR, 0x19, 0x23);
4974 SiS_SetReg(SISSR, 0x16, 0x00);
4975 SiS_SetReg(SISSR, 0x16, 0x80);
4976 sisfb_post_xgi_delay(ivideo, 1);
4977 SiS_SetReg(SISSR, 0x1b, 0x04);
4978 sisfb_post_xgi_delay(ivideo, 1);
4979 SiS_SetReg(SISSR, 0x1b, 0x00);
4980 sisfb_post_xgi_delay(ivideo, 1);
4981 v1 = 0x31;
4982 if (ivideo->haveXGIROM) {
4983 v1 = bios[0xf0];
4984 }
4985 SiS_SetReg(SISSR, 0x18, v1);
4986 SiS_SetReg(SISSR, 0x19, 0x06);
4987 SiS_SetReg(SISSR, 0x16, 0x04);
4988 SiS_SetReg(SISSR, 0x16, 0x84);
4989 sisfb_post_xgi_delay(ivideo, 1);
4990 }
4991
sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info * ivideo)4992 static void sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info *ivideo)
4993 {
4994 sisfb_post_xgi_setclocks(ivideo, 1);
4995
4996 SiS_SetReg(SISCR, 0x97, 0x11);
4997 sisfb_post_xgi_delay(ivideo, 0x46);
4998
4999 SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS2 */
5000 SiS_SetReg(SISSR, 0x19, 0x80);
5001 SiS_SetReg(SISSR, 0x16, 0x05);
5002 SiS_SetReg(SISSR, 0x16, 0x85);
5003
5004 SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS3 */
5005 SiS_SetReg(SISSR, 0x19, 0xc0);
5006 SiS_SetReg(SISSR, 0x16, 0x05);
5007 SiS_SetReg(SISSR, 0x16, 0x85);
5008
5009 SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS1 */
5010 SiS_SetReg(SISSR, 0x19, 0x40);
5011 SiS_SetReg(SISSR, 0x16, 0x05);
5012 SiS_SetReg(SISSR, 0x16, 0x85);
5013
5014 SiS_SetReg(SISSR, 0x18, 0x42); /* MRS1 */
5015 SiS_SetReg(SISSR, 0x19, 0x02);
5016 SiS_SetReg(SISSR, 0x16, 0x05);
5017 SiS_SetReg(SISSR, 0x16, 0x85);
5018 sisfb_post_xgi_delay(ivideo, 1);
5019
5020 SiS_SetReg(SISSR, 0x1b, 0x04);
5021 sisfb_post_xgi_delay(ivideo, 1);
5022
5023 SiS_SetReg(SISSR, 0x1b, 0x00);
5024 sisfb_post_xgi_delay(ivideo, 1);
5025
5026 SiS_SetReg(SISSR, 0x18, 0x42); /* MRS1 */
5027 SiS_SetReg(SISSR, 0x19, 0x00);
5028 SiS_SetReg(SISSR, 0x16, 0x05);
5029 SiS_SetReg(SISSR, 0x16, 0x85);
5030 sisfb_post_xgi_delay(ivideo, 1);
5031 }
5032
sisfb_post_xgi_ddr2(struct sis_video_info * ivideo,u8 regb)5033 static void sisfb_post_xgi_ddr2(struct sis_video_info *ivideo, u8 regb)
5034 {
5035 unsigned char *bios = ivideo->bios_abase;
5036 static const u8 cs158[8] = {
5037 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5038 };
5039 static const u8 cs160[8] = {
5040 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5041 };
5042 static const u8 cs168[8] = {
5043 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5044 };
5045 u8 v1;
5046 u8 v2;
5047 u8 v3;
5048
5049 SiS_SetReg(SISCR, 0xb0, 0x80); /* DDR2 dual frequency mode */
5050 SiS_SetReg(SISCR, 0x82, 0x77);
5051 SiS_SetReg(SISCR, 0x86, 0x00);
5052 SiS_GetReg(SISCR, 0x86);
5053 SiS_SetReg(SISCR, 0x86, 0x88);
5054 SiS_GetReg(SISCR, 0x86);
5055 v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
5056 if (ivideo->haveXGIROM) {
5057 v1 = bios[regb + 0x168];
5058 v2 = bios[regb + 0x160];
5059 v3 = bios[regb + 0x158];
5060 }
5061 SiS_SetReg(SISCR, 0x86, v1);
5062 SiS_SetReg(SISCR, 0x82, 0x77);
5063 SiS_SetReg(SISCR, 0x85, 0x00);
5064 SiS_GetReg(SISCR, 0x85);
5065 SiS_SetReg(SISCR, 0x85, 0x88);
5066 SiS_GetReg(SISCR, 0x85);
5067 SiS_SetReg(SISCR, 0x85, v2);
5068 SiS_SetReg(SISCR, 0x82, v3);
5069 SiS_SetReg(SISCR, 0x98, 0x01);
5070 SiS_SetReg(SISCR, 0x9a, 0x02);
5071 if (sisfb_xgi_is21(ivideo))
5072 sisfb_post_xgi_ddr2_mrs_xg21(ivideo);
5073 else
5074 sisfb_post_xgi_ddr2_mrs_default(ivideo, regb);
5075 }
5076
sisfb_post_xgi_ramtype(struct sis_video_info * ivideo)5077 static u8 sisfb_post_xgi_ramtype(struct sis_video_info *ivideo)
5078 {
5079 unsigned char *bios = ivideo->bios_abase;
5080 u8 ramtype;
5081 u8 reg;
5082 u8 v1;
5083
5084 ramtype = 0x00; v1 = 0x10;
5085 if (ivideo->haveXGIROM) {
5086 ramtype = bios[0x62];
5087 v1 = bios[0x1d2];
5088 }
5089 if (!(ramtype & 0x80)) {
5090 if (sisfb_xgi_is21(ivideo)) {
5091 SiS_SetRegAND(SISCR, 0xb4, 0xfd); /* GPIO control */
5092 SiS_SetRegOR(SISCR, 0x4a, 0x80); /* GPIOH EN */
5093 reg = SiS_GetReg(SISCR, 0x48);
5094 SiS_SetRegOR(SISCR, 0xb4, 0x02);
5095 ramtype = reg & 0x01; /* GPIOH */
5096 } else if (ivideo->chip == XGI_20) {
5097 SiS_SetReg(SISCR, 0x97, v1);
5098 reg = SiS_GetReg(SISCR, 0x97);
5099 if (reg & 0x10) {
5100 ramtype = (reg & 0x01) << 1;
5101 }
5102 } else {
5103 reg = SiS_GetReg(SISSR, 0x39);
5104 ramtype = reg & 0x02;
5105 if (!(ramtype)) {
5106 reg = SiS_GetReg(SISSR, 0x3a);
5107 ramtype = (reg >> 1) & 0x01;
5108 }
5109 }
5110 }
5111 ramtype &= 0x07;
5112
5113 return ramtype;
5114 }
5115
sisfb_post_xgi(struct pci_dev * pdev)5116 static int sisfb_post_xgi(struct pci_dev *pdev)
5117 {
5118 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
5119 unsigned char *bios = ivideo->bios_abase;
5120 struct pci_dev *mypdev = NULL;
5121 const u8 *ptr, *ptr2;
5122 u8 v1, v2, v3, v4, v5, reg, ramtype;
5123 u32 rega, regb, regd;
5124 int i, j, k, index;
5125 static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 };
5126 static const u8 cs76[2] = { 0xa3, 0xfb };
5127 static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 };
5128 static const u8 cs158[8] = {
5129 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5130 };
5131 static const u8 cs160[8] = {
5132 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5133 };
5134 static const u8 cs168[8] = {
5135 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5136 };
5137 static const u8 cs128[3 * 8] = {
5138 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
5139 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5140 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
5141 };
5142 static const u8 cs148[2 * 8] = {
5143 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
5144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5145 };
5146 static const u8 cs31a[8 * 4] = {
5147 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
5148 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
5149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5151 };
5152 static const u8 cs33a[8 * 4] = {
5153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5157 };
5158 static const u8 cs45a[8 * 2] = {
5159 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
5160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5161 };
5162 static const u8 cs170[7 * 8] = {
5163 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5164 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5165 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
5166 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5167 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5168 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5169 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5170 };
5171 static const u8 cs1a8[3 * 8] = {
5172 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5173 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5175 };
5176 static const u8 cs100[2 * 8] = {
5177 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5178 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5179 };
5180
5181 /* VGA enable */
5182 reg = SiS_GetRegByte(SISVGAENABLE) | 0x01;
5183 SiS_SetRegByte(SISVGAENABLE, reg);
5184
5185 /* Misc */
5186 reg = SiS_GetRegByte(SISMISCR) | 0x01;
5187 SiS_SetRegByte(SISMISCW, reg);
5188
5189 /* Unlock SR */
5190 SiS_SetReg(SISSR, 0x05, 0x86);
5191 reg = SiS_GetReg(SISSR, 0x05);
5192 if(reg != 0xa1)
5193 return 0;
5194
5195 /* Clear some regs */
5196 for(i = 0; i < 0x22; i++) {
5197 if(0x06 + i == 0x20) continue;
5198 SiS_SetReg(SISSR, 0x06 + i, 0x00);
5199 }
5200 for(i = 0; i < 0x0b; i++) {
5201 SiS_SetReg(SISSR, 0x31 + i, 0x00);
5202 }
5203 for(i = 0; i < 0x10; i++) {
5204 SiS_SetReg(SISCR, 0x30 + i, 0x00);
5205 }
5206
5207 ptr = cs78;
5208 if(ivideo->haveXGIROM) {
5209 ptr = (const u8 *)&bios[0x78];
5210 }
5211 for(i = 0; i < 3; i++) {
5212 SiS_SetReg(SISSR, 0x23 + i, ptr[i]);
5213 }
5214
5215 ptr = cs76;
5216 if(ivideo->haveXGIROM) {
5217 ptr = (const u8 *)&bios[0x76];
5218 }
5219 for(i = 0; i < 2; i++) {
5220 SiS_SetReg(SISSR, 0x21 + i, ptr[i]);
5221 }
5222
5223 v1 = 0x18; v2 = 0x00;
5224 if(ivideo->haveXGIROM) {
5225 v1 = bios[0x74];
5226 v2 = bios[0x75];
5227 }
5228 SiS_SetReg(SISSR, 0x07, v1);
5229 SiS_SetReg(SISSR, 0x11, 0x0f);
5230 SiS_SetReg(SISSR, 0x1f, v2);
5231 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5232 SiS_SetReg(SISSR, 0x20, 0x80 | 0x20 | 0x04);
5233 SiS_SetReg(SISSR, 0x27, 0x74);
5234
5235 ptr = cs7b;
5236 if(ivideo->haveXGIROM) {
5237 ptr = (const u8 *)&bios[0x7b];
5238 }
5239 for(i = 0; i < 3; i++) {
5240 SiS_SetReg(SISSR, 0x31 + i, ptr[i]);
5241 }
5242
5243 if(ivideo->chip == XGI_40) {
5244 if(ivideo->revision_id == 2) {
5245 SiS_SetRegANDOR(SISSR, 0x3b, 0x3f, 0xc0);
5246 }
5247 SiS_SetReg(SISCR, 0x7d, 0xfe);
5248 SiS_SetReg(SISCR, 0x7e, 0x0f);
5249 }
5250 if(ivideo->revision_id == 0) { /* 40 *and* 20? */
5251 SiS_SetRegAND(SISCR, 0x58, 0xd7);
5252 reg = SiS_GetReg(SISCR, 0xcb);
5253 if(reg & 0x20) {
5254 SiS_SetRegANDOR(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5255 }
5256 }
5257
5258 reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
5259 SiS_SetRegANDOR(SISCR, 0x38, 0x1f, reg);
5260
5261 if(ivideo->chip == XGI_20) {
5262 SiS_SetReg(SISSR, 0x36, 0x70);
5263 } else {
5264 SiS_SetReg(SISVID, 0x00, 0x86);
5265 SiS_SetReg(SISVID, 0x32, 0x00);
5266 SiS_SetReg(SISVID, 0x30, 0x00);
5267 SiS_SetReg(SISVID, 0x32, 0x01);
5268 SiS_SetReg(SISVID, 0x30, 0x00);
5269 SiS_SetRegAND(SISVID, 0x2f, 0xdf);
5270 SiS_SetRegAND(SISCAP, 0x00, 0x3f);
5271
5272 SiS_SetReg(SISPART1, 0x2f, 0x01);
5273 SiS_SetReg(SISPART1, 0x00, 0x00);
5274 SiS_SetReg(SISPART1, 0x02, bios[0x7e]);
5275 SiS_SetReg(SISPART1, 0x2e, 0x08);
5276 SiS_SetRegAND(SISPART1, 0x35, 0x7f);
5277 SiS_SetRegAND(SISPART1, 0x50, 0xfe);
5278
5279 reg = SiS_GetReg(SISPART4, 0x00);
5280 if(reg == 1 || reg == 2) {
5281 SiS_SetReg(SISPART2, 0x00, 0x1c);
5282 SiS_SetReg(SISPART4, 0x0d, bios[0x7f]);
5283 SiS_SetReg(SISPART4, 0x0e, bios[0x80]);
5284 SiS_SetReg(SISPART4, 0x10, bios[0x81]);
5285 SiS_SetRegAND(SISPART4, 0x0f, 0x3f);
5286
5287 reg = SiS_GetReg(SISPART4, 0x01);
5288 if((reg & 0xf0) >= 0xb0) {
5289 reg = SiS_GetReg(SISPART4, 0x23);
5290 if(reg & 0x20) reg |= 0x40;
5291 SiS_SetReg(SISPART4, 0x23, reg);
5292 reg = (reg & 0x20) ? 0x02 : 0x00;
5293 SiS_SetRegANDOR(SISPART1, 0x1e, 0xfd, reg);
5294 }
5295 }
5296
5297 v1 = bios[0x77];
5298
5299 reg = SiS_GetReg(SISSR, 0x3b);
5300 if(reg & 0x02) {
5301 reg = SiS_GetReg(SISSR, 0x3a);
5302 v2 = (reg & 0x30) >> 3;
5303 if(!(v2 & 0x04)) v2 ^= 0x02;
5304 reg = SiS_GetReg(SISSR, 0x39);
5305 if(reg & 0x80) v2 |= 0x80;
5306 v2 |= 0x01;
5307
5308 if((mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
5309 pci_dev_put(mypdev);
5310 if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
5311 v2 &= 0xf9;
5312 v2 |= 0x08;
5313 v1 &= 0xfe;
5314 } else {
5315 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0735, NULL);
5316 if(!mypdev)
5317 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0645, NULL);
5318 if(!mypdev)
5319 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0650, NULL);
5320 if(mypdev) {
5321 pci_read_config_dword(mypdev, 0x94, ®d);
5322 regd &= 0xfffffeff;
5323 pci_write_config_dword(mypdev, 0x94, regd);
5324 v1 &= 0xfe;
5325 pci_dev_put(mypdev);
5326 } else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) {
5327 v1 &= 0xfe;
5328 } else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) ||
5329 sisfb_find_host_bridge(ivideo, pdev, 0x1022) ||
5330 sisfb_find_host_bridge(ivideo, pdev, 0x700e) ||
5331 sisfb_find_host_bridge(ivideo, pdev, 0x10de)) {
5332 if((v2 & 0x06) == 4)
5333 v2 ^= 0x06;
5334 v2 |= 0x08;
5335 }
5336 }
5337 SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, v2);
5338 }
5339 SiS_SetReg(SISSR, 0x22, v1);
5340
5341 if(ivideo->revision_id == 2) {
5342 v1 = SiS_GetReg(SISSR, 0x3b);
5343 v2 = SiS_GetReg(SISSR, 0x3a);
5344 regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
5345 if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
5346 SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
5347
5348 if((mypdev = pci_get_device(0x10de, 0x01e0, NULL))) {
5349 /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5350 * of nforce 2 ROM
5351 */
5352 if(0)
5353 SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
5354 pci_dev_put(mypdev);
5355 }
5356 }
5357
5358 v1 = 0x30;
5359 reg = SiS_GetReg(SISSR, 0x3b);
5360 v2 = SiS_GetReg(SISCR, 0x5f);
5361 if((!(reg & 0x02)) && (v2 & 0x0e))
5362 v1 |= 0x08;
5363 SiS_SetReg(SISSR, 0x27, v1);
5364
5365 if(bios[0x64] & 0x01) {
5366 SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, bios[0x64]);
5367 }
5368
5369 v1 = bios[0x4f7];
5370 pci_read_config_dword(pdev, 0x50, ®d);
5371 regd = (regd >> 20) & 0x0f;
5372 if(regd == 1) {
5373 v1 &= 0xfc;
5374 SiS_SetRegOR(SISCR, 0x5f, 0x08);
5375 }
5376 SiS_SetReg(SISCR, 0x48, v1);
5377
5378 SiS_SetRegANDOR(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
5379 SiS_SetRegANDOR(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
5380 SiS_SetRegANDOR(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
5381 SiS_SetRegANDOR(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
5382 SiS_SetRegANDOR(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
5383 SiS_SetReg(SISCR, 0x70, bios[0x4fc]);
5384 SiS_SetRegANDOR(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
5385 SiS_SetReg(SISCR, 0x74, 0xd0);
5386 SiS_SetRegANDOR(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
5387 SiS_SetRegANDOR(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
5388 SiS_SetRegANDOR(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
5389 v1 = bios[0x501];
5390 if((mypdev = pci_get_device(0x8086, 0x2530, NULL))) {
5391 v1 = 0xf0;
5392 pci_dev_put(mypdev);
5393 }
5394 SiS_SetReg(SISCR, 0x77, v1);
5395 }
5396
5397 /* RAM type:
5398 *
5399 * 0 == DDR1, 1 == DDR2, 2..7 == reserved?
5400 *
5401 * The code seems to written so that regb should equal ramtype,
5402 * however, so far it has been hardcoded to 0. Enable other values only
5403 * on XGI Z9, as it passes the POST, and add a warning for others.
5404 */
5405 ramtype = sisfb_post_xgi_ramtype(ivideo);
5406 if (!sisfb_xgi_is21(ivideo) && ramtype) {
5407 dev_warn(&pdev->dev,
5408 "RAM type something else than expected: %d\n",
5409 ramtype);
5410 regb = 0;
5411 } else {
5412 regb = ramtype;
5413 }
5414
5415 v1 = 0xff;
5416 if(ivideo->haveXGIROM) {
5417 v1 = bios[0x140 + regb];
5418 }
5419 SiS_SetReg(SISCR, 0x6d, v1);
5420
5421 ptr = cs128;
5422 if(ivideo->haveXGIROM) {
5423 ptr = (const u8 *)&bios[0x128];
5424 }
5425 for(i = 0, j = 0; i < 3; i++, j += 8) {
5426 SiS_SetReg(SISCR, 0x68 + i, ptr[j + regb]);
5427 }
5428
5429 ptr = cs31a;
5430 ptr2 = cs33a;
5431 if(ivideo->haveXGIROM) {
5432 index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6;
5433 ptr = (const u8 *)&bios[index];
5434 ptr2 = (const u8 *)&bios[index + 0x20];
5435 }
5436 for(i = 0; i < 2; i++) {
5437 if(i == 0) {
5438 regd = le32_to_cpu(((u32 *)ptr)[regb]);
5439 rega = 0x6b;
5440 } else {
5441 regd = le32_to_cpu(((u32 *)ptr2)[regb]);
5442 rega = 0x6e;
5443 }
5444 reg = 0x00;
5445 for(j = 0; j < 16; j++) {
5446 reg &= 0xf3;
5447 if(regd & 0x01) reg |= 0x04;
5448 if(regd & 0x02) reg |= 0x08;
5449 regd >>= 2;
5450 SiS_SetReg(SISCR, rega, reg);
5451 reg = SiS_GetReg(SISCR, rega);
5452 reg = SiS_GetReg(SISCR, rega);
5453 reg += 0x10;
5454 }
5455 }
5456
5457 SiS_SetRegAND(SISCR, 0x6e, 0xfc);
5458
5459 ptr = NULL;
5460 if(ivideo->haveXGIROM) {
5461 index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6;
5462 ptr = (const u8 *)&bios[index];
5463 }
5464 for(i = 0; i < 4; i++) {
5465 SiS_SetRegANDOR(SISCR, 0x6e, 0xfc, i);
5466 reg = 0x00;
5467 for(j = 0; j < 2; j++) {
5468 regd = 0;
5469 if(ptr) {
5470 regd = le32_to_cpu(((u32 *)ptr)[regb * 8]);
5471 ptr += 4;
5472 }
5473 /* reg = 0x00; */
5474 for(k = 0; k < 16; k++) {
5475 reg &= 0xfc;
5476 if(regd & 0x01) reg |= 0x01;
5477 if(regd & 0x02) reg |= 0x02;
5478 regd >>= 2;
5479 SiS_SetReg(SISCR, 0x6f, reg);
5480 reg = SiS_GetReg(SISCR, 0x6f);
5481 reg = SiS_GetReg(SISCR, 0x6f);
5482 reg += 0x08;
5483 }
5484 }
5485 }
5486
5487 ptr = cs148;
5488 if(ivideo->haveXGIROM) {
5489 ptr = (const u8 *)&bios[0x148];
5490 }
5491 for(i = 0, j = 0; i < 2; i++, j += 8) {
5492 SiS_SetReg(SISCR, 0x80 + i, ptr[j + regb]);
5493 }
5494
5495 SiS_SetRegAND(SISCR, 0x89, 0x8f);
5496
5497 ptr = cs45a;
5498 if(ivideo->haveXGIROM) {
5499 index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6;
5500 ptr = (const u8 *)&bios[index];
5501 }
5502 regd = le16_to_cpu(((const u16 *)ptr)[regb]);
5503 reg = 0x80;
5504 for(i = 0; i < 5; i++) {
5505 reg &= 0xfc;
5506 if(regd & 0x01) reg |= 0x01;
5507 if(regd & 0x02) reg |= 0x02;
5508 regd >>= 2;
5509 SiS_SetReg(SISCR, 0x89, reg);
5510 reg = SiS_GetReg(SISCR, 0x89);
5511 reg = SiS_GetReg(SISCR, 0x89);
5512 reg += 0x10;
5513 }
5514
5515 v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13;
5516 if(ivideo->haveXGIROM) {
5517 v1 = bios[0x118 + regb];
5518 v2 = bios[0xf8 + regb];
5519 v3 = bios[0x120 + regb];
5520 v4 = bios[0x1ca];
5521 }
5522 SiS_SetReg(SISCR, 0x45, v1 & 0x0f);
5523 SiS_SetReg(SISCR, 0x99, (v1 >> 4) & 0x07);
5524 SiS_SetRegOR(SISCR, 0x40, v1 & 0x80);
5525 SiS_SetReg(SISCR, 0x41, v2);
5526
5527 ptr = cs170;
5528 if(ivideo->haveXGIROM) {
5529 ptr = (const u8 *)&bios[0x170];
5530 }
5531 for(i = 0, j = 0; i < 7; i++, j += 8) {
5532 SiS_SetReg(SISCR, 0x90 + i, ptr[j + regb]);
5533 }
5534
5535 SiS_SetReg(SISCR, 0x59, v3);
5536
5537 ptr = cs1a8;
5538 if(ivideo->haveXGIROM) {
5539 ptr = (const u8 *)&bios[0x1a8];
5540 }
5541 for(i = 0, j = 0; i < 3; i++, j += 8) {
5542 SiS_SetReg(SISCR, 0xc3 + i, ptr[j + regb]);
5543 }
5544
5545 ptr = cs100;
5546 if(ivideo->haveXGIROM) {
5547 ptr = (const u8 *)&bios[0x100];
5548 }
5549 for(i = 0, j = 0; i < 2; i++, j += 8) {
5550 SiS_SetReg(SISCR, 0x8a + i, ptr[j + regb]);
5551 }
5552
5553 SiS_SetReg(SISCR, 0xcf, v4);
5554
5555 SiS_SetReg(SISCR, 0x83, 0x09);
5556 SiS_SetReg(SISCR, 0x87, 0x00);
5557
5558 if(ivideo->chip == XGI_40) {
5559 if( (ivideo->revision_id == 1) ||
5560 (ivideo->revision_id == 2) ) {
5561 SiS_SetReg(SISCR, 0x8c, 0x87);
5562 }
5563 }
5564
5565 if (regb == 1)
5566 SiS_SetReg(SISSR, 0x17, 0x80); /* DDR2 */
5567 else
5568 SiS_SetReg(SISSR, 0x17, 0x00); /* DDR1 */
5569 SiS_SetReg(SISSR, 0x1a, 0x87);
5570
5571 if(ivideo->chip == XGI_20) {
5572 SiS_SetReg(SISSR, 0x15, 0x00);
5573 SiS_SetReg(SISSR, 0x1c, 0x00);
5574 }
5575
5576 switch(ramtype) {
5577 case 0:
5578 sisfb_post_xgi_setclocks(ivideo, regb);
5579 if((ivideo->chip == XGI_20) ||
5580 (ivideo->revision_id == 1) ||
5581 (ivideo->revision_id == 2)) {
5582 v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb];
5583 if(ivideo->haveXGIROM) {
5584 v1 = bios[regb + 0x158];
5585 v2 = bios[regb + 0x160];
5586 v3 = bios[regb + 0x168];
5587 }
5588 SiS_SetReg(SISCR, 0x82, v1);
5589 SiS_SetReg(SISCR, 0x85, v2);
5590 SiS_SetReg(SISCR, 0x86, v3);
5591 } else {
5592 SiS_SetReg(SISCR, 0x82, 0x88);
5593 SiS_SetReg(SISCR, 0x86, 0x00);
5594 reg = SiS_GetReg(SISCR, 0x86);
5595 SiS_SetReg(SISCR, 0x86, 0x88);
5596 reg = SiS_GetReg(SISCR, 0x86);
5597 SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
5598 SiS_SetReg(SISCR, 0x82, 0x77);
5599 SiS_SetReg(SISCR, 0x85, 0x00);
5600 reg = SiS_GetReg(SISCR, 0x85);
5601 SiS_SetReg(SISCR, 0x85, 0x88);
5602 reg = SiS_GetReg(SISCR, 0x85);
5603 SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
5604 SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
5605 }
5606 if(ivideo->chip == XGI_40) {
5607 SiS_SetReg(SISCR, 0x97, 0x00);
5608 }
5609 SiS_SetReg(SISCR, 0x98, 0x01);
5610 SiS_SetReg(SISCR, 0x9a, 0x02);
5611
5612 SiS_SetReg(SISSR, 0x18, 0x01);
5613 if((ivideo->chip == XGI_20) ||
5614 (ivideo->revision_id == 2)) {
5615 SiS_SetReg(SISSR, 0x19, 0x40);
5616 } else {
5617 SiS_SetReg(SISSR, 0x19, 0x20);
5618 }
5619 SiS_SetReg(SISSR, 0x16, 0x00);
5620 SiS_SetReg(SISSR, 0x16, 0x80);
5621 if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
5622 sisfb_post_xgi_delay(ivideo, 0x43);
5623 sisfb_post_xgi_delay(ivideo, 0x43);
5624 sisfb_post_xgi_delay(ivideo, 0x43);
5625 SiS_SetReg(SISSR, 0x18, 0x00);
5626 if((ivideo->chip == XGI_20) ||
5627 (ivideo->revision_id == 2)) {
5628 SiS_SetReg(SISSR, 0x19, 0x40);
5629 } else {
5630 SiS_SetReg(SISSR, 0x19, 0x20);
5631 }
5632 } else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
5633 /* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
5634 }
5635 SiS_SetReg(SISSR, 0x16, 0x00);
5636 SiS_SetReg(SISSR, 0x16, 0x80);
5637 sisfb_post_xgi_delay(ivideo, 4);
5638 v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
5639 if(ivideo->haveXGIROM) {
5640 v1 = bios[0xf0];
5641 index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e;
5642 v2 = bios[index];
5643 v3 = bios[index + 1];
5644 v4 = bios[index + 2];
5645 v5 = bios[index + 3];
5646 }
5647 SiS_SetReg(SISSR, 0x18, v1);
5648 SiS_SetReg(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
5649 SiS_SetReg(SISSR, 0x16, v2);
5650 SiS_SetReg(SISSR, 0x16, v3);
5651 sisfb_post_xgi_delay(ivideo, 0x43);
5652 SiS_SetReg(SISSR, 0x1b, 0x03);
5653 sisfb_post_xgi_delay(ivideo, 0x22);
5654 SiS_SetReg(SISSR, 0x18, v1);
5655 SiS_SetReg(SISSR, 0x19, 0x00);
5656 SiS_SetReg(SISSR, 0x16, v4);
5657 SiS_SetReg(SISSR, 0x16, v5);
5658 SiS_SetReg(SISSR, 0x1b, 0x00);
5659 break;
5660 case 1:
5661 sisfb_post_xgi_ddr2(ivideo, regb);
5662 break;
5663 default:
5664 sisfb_post_xgi_setclocks(ivideo, regb);
5665 if((ivideo->chip == XGI_40) &&
5666 ((ivideo->revision_id == 1) ||
5667 (ivideo->revision_id == 2))) {
5668 SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
5669 SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
5670 SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
5671 } else {
5672 SiS_SetReg(SISCR, 0x82, 0x88);
5673 SiS_SetReg(SISCR, 0x86, 0x00);
5674 reg = SiS_GetReg(SISCR, 0x86);
5675 SiS_SetReg(SISCR, 0x86, 0x88);
5676 SiS_SetReg(SISCR, 0x82, 0x77);
5677 SiS_SetReg(SISCR, 0x85, 0x00);
5678 reg = SiS_GetReg(SISCR, 0x85);
5679 SiS_SetReg(SISCR, 0x85, 0x88);
5680 reg = SiS_GetReg(SISCR, 0x85);
5681 v1 = cs160[regb]; v2 = cs158[regb];
5682 if(ivideo->haveXGIROM) {
5683 v1 = bios[regb + 0x160];
5684 v2 = bios[regb + 0x158];
5685 }
5686 SiS_SetReg(SISCR, 0x85, v1);
5687 SiS_SetReg(SISCR, 0x82, v2);
5688 }
5689 if(ivideo->chip == XGI_40) {
5690 SiS_SetReg(SISCR, 0x97, 0x11);
5691 }
5692 if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
5693 SiS_SetReg(SISCR, 0x98, 0x01);
5694 } else {
5695 SiS_SetReg(SISCR, 0x98, 0x03);
5696 }
5697 SiS_SetReg(SISCR, 0x9a, 0x02);
5698
5699 if(ivideo->chip == XGI_40) {
5700 SiS_SetReg(SISSR, 0x18, 0x01);
5701 } else {
5702 SiS_SetReg(SISSR, 0x18, 0x00);
5703 }
5704 SiS_SetReg(SISSR, 0x19, 0x40);
5705 SiS_SetReg(SISSR, 0x16, 0x00);
5706 SiS_SetReg(SISSR, 0x16, 0x80);
5707 if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
5708 sisfb_post_xgi_delay(ivideo, 0x43);
5709 sisfb_post_xgi_delay(ivideo, 0x43);
5710 sisfb_post_xgi_delay(ivideo, 0x43);
5711 SiS_SetReg(SISSR, 0x18, 0x00);
5712 SiS_SetReg(SISSR, 0x19, 0x40);
5713 SiS_SetReg(SISSR, 0x16, 0x00);
5714 SiS_SetReg(SISSR, 0x16, 0x80);
5715 }
5716 sisfb_post_xgi_delay(ivideo, 4);
5717 v1 = 0x31;
5718 if(ivideo->haveXGIROM) {
5719 v1 = bios[0xf0];
5720 }
5721 SiS_SetReg(SISSR, 0x18, v1);
5722 SiS_SetReg(SISSR, 0x19, 0x01);
5723 if(ivideo->chip == XGI_40) {
5724 SiS_SetReg(SISSR, 0x16, bios[0x53e]);
5725 SiS_SetReg(SISSR, 0x16, bios[0x53f]);
5726 } else {
5727 SiS_SetReg(SISSR, 0x16, 0x05);
5728 SiS_SetReg(SISSR, 0x16, 0x85);
5729 }
5730 sisfb_post_xgi_delay(ivideo, 0x43);
5731 if(ivideo->chip == XGI_40) {
5732 SiS_SetReg(SISSR, 0x1b, 0x01);
5733 } else {
5734 SiS_SetReg(SISSR, 0x1b, 0x03);
5735 }
5736 sisfb_post_xgi_delay(ivideo, 0x22);
5737 SiS_SetReg(SISSR, 0x18, v1);
5738 SiS_SetReg(SISSR, 0x19, 0x00);
5739 if(ivideo->chip == XGI_40) {
5740 SiS_SetReg(SISSR, 0x16, bios[0x540]);
5741 SiS_SetReg(SISSR, 0x16, bios[0x541]);
5742 } else {
5743 SiS_SetReg(SISSR, 0x16, 0x05);
5744 SiS_SetReg(SISSR, 0x16, 0x85);
5745 }
5746 SiS_SetReg(SISSR, 0x1b, 0x00);
5747 }
5748
5749 regb = 0; /* ! */
5750 v1 = 0x03;
5751 if(ivideo->haveXGIROM) {
5752 v1 = bios[0x110 + regb];
5753 }
5754 SiS_SetReg(SISSR, 0x1b, v1);
5755
5756 /* RAM size */
5757 v1 = 0x00; v2 = 0x00;
5758 if(ivideo->haveXGIROM) {
5759 v1 = bios[0x62];
5760 v2 = bios[0x63];
5761 }
5762 regb = 0; /* ! */
5763 regd = 1 << regb;
5764 if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
5765
5766 SiS_SetReg(SISSR, 0x13, bios[regb + 0xe0]);
5767 SiS_SetReg(SISSR, 0x14, bios[regb + 0xe0 + 8]);
5768
5769 } else {
5770 int err;
5771
5772 /* Set default mode, don't clear screen */
5773 ivideo->SiS_Pr.SiS_UseOEM = false;
5774 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
5775 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
5776 ivideo->curFSTN = ivideo->curDSTN = 0;
5777 ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
5778 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5779
5780 SiS_SetReg(SISSR, 0x05, 0x86);
5781
5782 /* Disable read-cache */
5783 SiS_SetRegAND(SISSR, 0x21, 0xdf);
5784 err = sisfb_post_xgi_ramsize(ivideo);
5785 /* Enable read-cache */
5786 SiS_SetRegOR(SISSR, 0x21, 0x20);
5787
5788 if (err) {
5789 dev_err(&pdev->dev,
5790 "%s: RAM size detection failed: %d\n",
5791 __func__, err);
5792 return 0;
5793 }
5794 }
5795
5796 #if 0
5797 printk(KERN_DEBUG "-----------------\n");
5798 for(i = 0; i < 0xff; i++) {
5799 reg = SiS_GetReg(SISCR, i);
5800 printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
5801 }
5802 for(i = 0; i < 0x40; i++) {
5803 reg = SiS_GetReg(SISSR, i);
5804 printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
5805 }
5806 printk(KERN_DEBUG "-----------------\n");
5807 #endif
5808
5809 /* Sense CRT1 */
5810 if(ivideo->chip == XGI_20) {
5811 SiS_SetRegOR(SISCR, 0x32, 0x20);
5812 } else {
5813 reg = SiS_GetReg(SISPART4, 0x00);
5814 if((reg == 1) || (reg == 2)) {
5815 sisfb_sense_crt1(ivideo);
5816 } else {
5817 SiS_SetRegOR(SISCR, 0x32, 0x20);
5818 }
5819 }
5820
5821 /* Set default mode, don't clear screen */
5822 ivideo->SiS_Pr.SiS_UseOEM = false;
5823 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
5824 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
5825 ivideo->curFSTN = ivideo->curDSTN = 0;
5826 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5827
5828 SiS_SetReg(SISSR, 0x05, 0x86);
5829
5830 /* Display off */
5831 SiS_SetRegOR(SISSR, 0x01, 0x20);
5832
5833 /* Save mode number in CR34 */
5834 SiS_SetReg(SISCR, 0x34, 0x2e);
5835
5836 /* Let everyone know what the current mode is */
5837 ivideo->modeprechange = 0x2e;
5838
5839 if(ivideo->chip == XGI_40) {
5840 reg = SiS_GetReg(SISCR, 0xca);
5841 v1 = SiS_GetReg(SISCR, 0xcc);
5842 if((reg & 0x10) && (!(v1 & 0x04))) {
5843 printk(KERN_ERR
5844 "sisfb: Please connect power to the card.\n");
5845 return 0;
5846 }
5847 }
5848
5849 return 1;
5850 }
5851 #endif
5852
sisfb_probe(struct pci_dev * pdev,const struct pci_device_id * ent)5853 static int sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
5854 {
5855 struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data];
5856 struct sis_video_info *ivideo = NULL;
5857 struct fb_info *sis_fb_info = NULL;
5858 u16 reg16;
5859 u8 reg;
5860 int i, ret;
5861
5862 if(sisfb_off)
5863 return -ENXIO;
5864
5865 ret = aperture_remove_conflicting_pci_devices(pdev, "sisfb");
5866 if (ret)
5867 return ret;
5868
5869 sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
5870 if(!sis_fb_info)
5871 return -ENOMEM;
5872
5873 ivideo = (struct sis_video_info *)sis_fb_info->par;
5874 ivideo->memyselfandi = sis_fb_info;
5875
5876 ivideo->sisfb_id = SISFB_ID;
5877
5878 if(card_list == NULL) {
5879 ivideo->cardnumber = 0;
5880 } else {
5881 struct sis_video_info *countvideo = card_list;
5882 ivideo->cardnumber = 1;
5883 while((countvideo = countvideo->next) != NULL)
5884 ivideo->cardnumber++;
5885 }
5886
5887 strscpy(ivideo->myid, chipinfo->chip_name, sizeof(ivideo->myid));
5888
5889 ivideo->warncount = 0;
5890 ivideo->chip_id = pdev->device;
5891 ivideo->chip_vendor = pdev->vendor;
5892 ivideo->revision_id = pdev->revision;
5893 ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
5894 pci_read_config_word(pdev, PCI_COMMAND, ®16);
5895 ivideo->sisvga_enabled = reg16 & 0x01;
5896 ivideo->pcibus = pdev->bus->number;
5897 ivideo->pcislot = PCI_SLOT(pdev->devfn);
5898 ivideo->pcifunc = PCI_FUNC(pdev->devfn);
5899 ivideo->subsysvendor = pdev->subsystem_vendor;
5900 ivideo->subsysdevice = pdev->subsystem_device;
5901
5902 #ifndef MODULE
5903 if(sisfb_mode_idx == -1) {
5904 sisfb_get_vga_mode_from_kernel();
5905 }
5906 #endif
5907
5908 ivideo->chip = chipinfo->chip;
5909 ivideo->chip_real_id = chipinfo->chip;
5910 ivideo->sisvga_engine = chipinfo->vgaengine;
5911 ivideo->hwcursor_size = chipinfo->hwcursor_size;
5912 ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
5913 ivideo->mni = chipinfo->mni;
5914
5915 ivideo->detectedpdc = 0xff;
5916 ivideo->detectedpdca = 0xff;
5917 ivideo->detectedlcda = 0xff;
5918
5919 ivideo->sisfb_thismonitor.datavalid = false;
5920
5921 ivideo->current_base = 0;
5922
5923 ivideo->engineok = 0;
5924
5925 ivideo->sisfb_was_boot_device = 0;
5926
5927 if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
5928 if(ivideo->sisvga_enabled)
5929 ivideo->sisfb_was_boot_device = 1;
5930 else {
5931 printk(KERN_DEBUG "sisfb: PCI device is disabled, "
5932 "but marked as boot video device ???\n");
5933 printk(KERN_DEBUG "sisfb: I will not accept this "
5934 "as the primary VGA device\n");
5935 }
5936 }
5937
5938 ivideo->sisfb_parm_mem = sisfb_parm_mem;
5939 ivideo->sisfb_accel = sisfb_accel;
5940 ivideo->sisfb_ypan = sisfb_ypan;
5941 ivideo->sisfb_max = sisfb_max;
5942 ivideo->sisfb_userom = sisfb_userom;
5943 ivideo->sisfb_useoem = sisfb_useoem;
5944 ivideo->sisfb_mode_idx = sisfb_mode_idx;
5945 ivideo->sisfb_parm_rate = sisfb_parm_rate;
5946 ivideo->sisfb_crt1off = sisfb_crt1off;
5947 ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
5948 ivideo->sisfb_crt2type = sisfb_crt2type;
5949 ivideo->sisfb_crt2flags = sisfb_crt2flags;
5950 /* pdc(a), scalelcd, special timing, lvdshl handled below */
5951 ivideo->sisfb_dstn = sisfb_dstn;
5952 ivideo->sisfb_fstn = sisfb_fstn;
5953 ivideo->sisfb_tvplug = sisfb_tvplug;
5954 ivideo->sisfb_tvstd = sisfb_tvstd;
5955 ivideo->tvxpos = sisfb_tvxposoffset;
5956 ivideo->tvypos = sisfb_tvyposoffset;
5957 ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
5958 ivideo->refresh_rate = 0;
5959 if(ivideo->sisfb_parm_rate != -1) {
5960 ivideo->refresh_rate = ivideo->sisfb_parm_rate;
5961 }
5962
5963 ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
5964 ivideo->SiS_Pr.CenterScreen = -1;
5965 ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
5966 ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
5967
5968 ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
5969 ivideo->SiS_Pr.SiS_CHOverScan = -1;
5970 ivideo->SiS_Pr.SiS_ChSW = false;
5971 ivideo->SiS_Pr.SiS_UseLCDA = false;
5972 ivideo->SiS_Pr.HaveEMI = false;
5973 ivideo->SiS_Pr.HaveEMILCD = false;
5974 ivideo->SiS_Pr.OverruleEMI = false;
5975 ivideo->SiS_Pr.SiS_SensibleSR11 = false;
5976 ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
5977 ivideo->SiS_Pr.PDC = -1;
5978 ivideo->SiS_Pr.PDCA = -1;
5979 ivideo->SiS_Pr.DDCPortMixup = false;
5980 #ifdef CONFIG_FB_SIS_315
5981 if(ivideo->chip >= SIS_330) {
5982 ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
5983 if(ivideo->chip >= SIS_661) {
5984 ivideo->SiS_Pr.SiS_SensibleSR11 = true;
5985 }
5986 }
5987 #endif
5988
5989 memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));
5990
5991 pci_set_drvdata(pdev, ivideo);
5992
5993 /* Patch special cases */
5994 if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) {
5995 switch(ivideo->nbridge->device) {
5996 #ifdef CONFIG_FB_SIS_300
5997 case PCI_DEVICE_ID_SI_730:
5998 ivideo->chip = SIS_730;
5999 strcpy(ivideo->myid, "SiS 730");
6000 break;
6001 #endif
6002 #ifdef CONFIG_FB_SIS_315
6003 case PCI_DEVICE_ID_SI_651:
6004 /* ivideo->chip is ok */
6005 strcpy(ivideo->myid, "SiS 651");
6006 break;
6007 case PCI_DEVICE_ID_SI_740:
6008 ivideo->chip = SIS_740;
6009 strcpy(ivideo->myid, "SiS 740");
6010 break;
6011 case PCI_DEVICE_ID_SI_661:
6012 ivideo->chip = SIS_661;
6013 strcpy(ivideo->myid, "SiS 661");
6014 break;
6015 case PCI_DEVICE_ID_SI_741:
6016 ivideo->chip = SIS_741;
6017 strcpy(ivideo->myid, "SiS 741");
6018 break;
6019 case PCI_DEVICE_ID_SI_760:
6020 ivideo->chip = SIS_760;
6021 strcpy(ivideo->myid, "SiS 760");
6022 break;
6023 case PCI_DEVICE_ID_SI_761:
6024 ivideo->chip = SIS_761;
6025 strcpy(ivideo->myid, "SiS 761");
6026 break;
6027 #endif
6028 default:
6029 break;
6030 }
6031 }
6032
6033 ivideo->SiS_Pr.ChipType = ivideo->chip;
6034
6035 ivideo->SiS_Pr.ivideo = (void *)ivideo;
6036
6037 #ifdef CONFIG_FB_SIS_315
6038 if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
6039 (ivideo->SiS_Pr.ChipType == SIS_315)) {
6040 ivideo->SiS_Pr.ChipType = SIS_315H;
6041 }
6042 #endif
6043
6044 if(!ivideo->sisvga_enabled) {
6045 if(pci_enable_device(pdev)) {
6046 pci_dev_put(ivideo->nbridge);
6047 framebuffer_release(sis_fb_info);
6048 return -EIO;
6049 }
6050 }
6051
6052 ivideo->video_base = pci_resource_start(pdev, 0);
6053 ivideo->video_size = pci_resource_len(pdev, 0);
6054 ivideo->mmio_base = pci_resource_start(pdev, 1);
6055 ivideo->mmio_size = pci_resource_len(pdev, 1);
6056 ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
6057 ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
6058
6059 SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress);
6060
6061 #ifdef CONFIG_FB_SIS_300
6062 /* Find PCI systems for Chrontel/GPIO communication setup */
6063 if(ivideo->chip == SIS_630) {
6064 i = 0;
6065 do {
6066 if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
6067 mychswtable[i].subsysCard == ivideo->subsysdevice) {
6068 ivideo->SiS_Pr.SiS_ChSW = true;
6069 printk(KERN_DEBUG "sisfb: Identified [%s %s] "
6070 "requiring Chrontel/GPIO setup\n",
6071 mychswtable[i].vendorName,
6072 mychswtable[i].cardName);
6073 ivideo->lpcdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, NULL);
6074 break;
6075 }
6076 i++;
6077 } while(mychswtable[i].subsysVendor != 0);
6078 }
6079 #endif
6080
6081 #ifdef CONFIG_FB_SIS_315
6082 if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
6083 ivideo->lpcdev = pci_get_slot(ivideo->nbridge->bus, (2 << 3));
6084 }
6085 #endif
6086
6087 SiS_SetReg(SISSR, 0x05, 0x86);
6088
6089 if( (!ivideo->sisvga_enabled)
6090 #if !defined(__i386__) && !defined(__x86_64__)
6091 || (sisfb_resetcard)
6092 #endif
6093 ) {
6094 for(i = 0x30; i <= 0x3f; i++) {
6095 SiS_SetReg(SISCR, i, 0x00);
6096 }
6097 }
6098
6099 /* Find out about current video mode */
6100 ivideo->modeprechange = 0x03;
6101 reg = SiS_GetReg(SISCR, 0x34);
6102 if(reg & 0x7f) {
6103 ivideo->modeprechange = reg & 0x7f;
6104 } else if(ivideo->sisvga_enabled) {
6105 #if defined(__i386__) || defined(__x86_64__)
6106 unsigned char __iomem *tt = ioremap(0x400, 0x100);
6107 if(tt) {
6108 ivideo->modeprechange = readb(tt + 0x49);
6109 iounmap(tt);
6110 }
6111 #endif
6112 }
6113
6114 /* Search and copy ROM image */
6115 ivideo->bios_abase = NULL;
6116 ivideo->SiS_Pr.VirtualRomBase = NULL;
6117 ivideo->SiS_Pr.UseROM = false;
6118 ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = false;
6119 if(ivideo->sisfb_userom) {
6120 ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
6121 ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
6122 ivideo->SiS_Pr.UseROM = (bool)(ivideo->SiS_Pr.VirtualRomBase);
6123 printk(KERN_INFO "sisfb: Video ROM %sfound\n",
6124 ivideo->SiS_Pr.UseROM ? "" : "not ");
6125 if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
6126 ivideo->SiS_Pr.UseROM = false;
6127 ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = true;
6128 if( (ivideo->revision_id == 2) &&
6129 (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
6130 ivideo->SiS_Pr.DDCPortMixup = true;
6131 }
6132 }
6133 } else {
6134 printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
6135 }
6136
6137 /* Find systems for special custom timing */
6138 if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
6139 sisfb_detect_custom_timing(ivideo);
6140 }
6141
6142 #ifdef CONFIG_FB_SIS_315
6143 if (ivideo->chip == XGI_20) {
6144 /* Check if our Z7 chip is actually Z9 */
6145 SiS_SetRegOR(SISCR, 0x4a, 0x40); /* GPIOG EN */
6146 reg = SiS_GetReg(SISCR, 0x48);
6147 if (reg & 0x02) { /* GPIOG */
6148 ivideo->chip_real_id = XGI_21;
6149 dev_info(&pdev->dev, "Z9 detected\n");
6150 }
6151 }
6152 #endif
6153
6154 /* POST card in case this has not been done by the BIOS */
6155 if( (!ivideo->sisvga_enabled)
6156 #if !defined(__i386__) && !defined(__x86_64__)
6157 || (sisfb_resetcard)
6158 #endif
6159 ) {
6160 #ifdef CONFIG_FB_SIS_300
6161 if(ivideo->sisvga_engine == SIS_300_VGA) {
6162 if(ivideo->chip == SIS_300) {
6163 sisfb_post_sis300(pdev);
6164 ivideo->sisfb_can_post = 1;
6165 }
6166 }
6167 #endif
6168
6169 #ifdef CONFIG_FB_SIS_315
6170 if (ivideo->sisvga_engine == SIS_315_VGA) {
6171 int result = 1;
6172
6173 if (ivideo->chip == XGI_20) {
6174 result = sisfb_post_xgi(pdev);
6175 ivideo->sisfb_can_post = 1;
6176 } else if ((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
6177 result = sisfb_post_xgi(pdev);
6178 ivideo->sisfb_can_post = 1;
6179 } else {
6180 printk(KERN_INFO "sisfb: Card is not "
6181 "POSTed and sisfb can't do this either.\n");
6182 }
6183 if (!result) {
6184 printk(KERN_ERR "sisfb: Failed to POST card\n");
6185 ret = -ENODEV;
6186 goto error_3;
6187 }
6188 }
6189 #endif
6190 }
6191
6192 ivideo->sisfb_card_posted = 1;
6193
6194 /* Find out about RAM size */
6195 if(sisfb_get_dram_size(ivideo)) {
6196 printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
6197 ret = -ENODEV;
6198 goto error_3;
6199 }
6200
6201
6202 /* Enable PCI addressing and MMIO */
6203 if((ivideo->sisfb_mode_idx < 0) ||
6204 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6205 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
6206 SiS_SetRegOR(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
6207 /* Enable 2D accelerator engine */
6208 SiS_SetRegOR(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
6209 }
6210
6211 if(sisfb_pdc != 0xff) {
6212 if(ivideo->sisvga_engine == SIS_300_VGA)
6213 sisfb_pdc &= 0x3c;
6214 else
6215 sisfb_pdc &= 0x1f;
6216 ivideo->SiS_Pr.PDC = sisfb_pdc;
6217 }
6218 #ifdef CONFIG_FB_SIS_315
6219 if(ivideo->sisvga_engine == SIS_315_VGA) {
6220 if(sisfb_pdca != 0xff)
6221 ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
6222 }
6223 #endif
6224
6225 if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
6226 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6227 (int)(ivideo->video_size >> 20));
6228 printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
6229 ret = -ENODEV;
6230 goto error_3;
6231 }
6232
6233 if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
6234 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
6235 ret = -ENODEV;
6236 goto error_2;
6237 }
6238
6239 ivideo->video_vbase = ioremap_wc(ivideo->video_base, ivideo->video_size);
6240 ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
6241 if(!ivideo->video_vbase) {
6242 printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
6243 ret = -ENODEV;
6244 goto error_1;
6245 }
6246
6247 ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
6248 if(!ivideo->mmio_vbase) {
6249 printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
6250 ret = -ENODEV;
6251 error_0: iounmap(ivideo->video_vbase);
6252 error_1: release_mem_region(ivideo->video_base, ivideo->video_size);
6253 error_2: release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6254 error_3: vfree(ivideo->bios_abase);
6255 pci_dev_put(ivideo->lpcdev);
6256 pci_dev_put(ivideo->nbridge);
6257 if(!ivideo->sisvga_enabled)
6258 pci_disable_device(pdev);
6259 framebuffer_release(sis_fb_info);
6260 return ret;
6261 }
6262
6263 printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
6264 ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);
6265
6266 if(ivideo->video_offset) {
6267 printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
6268 ivideo->video_offset / 1024);
6269 }
6270
6271 printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
6272 ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
6273
6274
6275 /* Determine the size of the command queue */
6276 if(ivideo->sisvga_engine == SIS_300_VGA) {
6277 ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
6278 } else {
6279 if(ivideo->chip == XGI_20) {
6280 ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
6281 } else {
6282 ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
6283 }
6284 }
6285
6286 /* Engines are no longer initialized here; this is
6287 * now done after the first mode-switch (if the
6288 * submitted var has its acceleration flags set).
6289 */
6290
6291 /* Calculate the base of the (unused) hw cursor */
6292 ivideo->hwcursor_vbase = ivideo->video_vbase
6293 + ivideo->video_size
6294 - ivideo->cmdQueueSize
6295 - ivideo->hwcursor_size;
6296 ivideo->caps |= HW_CURSOR_CAP;
6297
6298 /* Initialize offscreen memory manager */
6299 if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
6300 printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
6301 }
6302
6303 /* Used for clearing the screen only, therefore respect our mem limit */
6304 ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
6305 ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;
6306
6307 ivideo->vbflags = 0;
6308 ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
6309 ivideo->tvdefmodeidx = DEFAULT_TVMODE;
6310 ivideo->defmodeidx = DEFAULT_MODE;
6311
6312 ivideo->newrom = 0;
6313 if(ivideo->chip < XGI_20) {
6314 if(ivideo->bios_abase) {
6315 ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr);
6316 }
6317 }
6318
6319 if((ivideo->sisfb_mode_idx < 0) ||
6320 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6321
6322 sisfb_sense_crt1(ivideo);
6323
6324 sisfb_get_VB_type(ivideo);
6325
6326 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6327 sisfb_detect_VB_connect(ivideo);
6328 }
6329
6330 ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
6331
6332 /* Decide on which CRT2 device to use */
6333 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6334 if(ivideo->sisfb_crt2type != -1) {
6335 if((ivideo->sisfb_crt2type == CRT2_LCD) &&
6336 (ivideo->vbflags & CRT2_LCD)) {
6337 ivideo->currentvbflags |= CRT2_LCD;
6338 } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
6339 ivideo->currentvbflags |= ivideo->sisfb_crt2type;
6340 }
6341 } else {
6342 /* Chrontel 700x TV detection often unreliable, therefore
6343 * use a different default order on such machines
6344 */
6345 if((ivideo->sisvga_engine == SIS_300_VGA) &&
6346 (ivideo->vbflags2 & VB2_CHRONTEL)) {
6347 if(ivideo->vbflags & CRT2_LCD)
6348 ivideo->currentvbflags |= CRT2_LCD;
6349 else if(ivideo->vbflags & CRT2_TV)
6350 ivideo->currentvbflags |= CRT2_TV;
6351 else if(ivideo->vbflags & CRT2_VGA)
6352 ivideo->currentvbflags |= CRT2_VGA;
6353 } else {
6354 if(ivideo->vbflags & CRT2_TV)
6355 ivideo->currentvbflags |= CRT2_TV;
6356 else if(ivideo->vbflags & CRT2_LCD)
6357 ivideo->currentvbflags |= CRT2_LCD;
6358 else if(ivideo->vbflags & CRT2_VGA)
6359 ivideo->currentvbflags |= CRT2_VGA;
6360 }
6361 }
6362 }
6363
6364 if(ivideo->vbflags & CRT2_LCD) {
6365 sisfb_detect_lcd_type(ivideo);
6366 }
6367
6368 sisfb_save_pdc_emi(ivideo);
6369
6370 if(!ivideo->sisfb_crt1off) {
6371 sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
6372 } else {
6373 if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
6374 (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
6375 sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
6376 }
6377 }
6378
6379 if(ivideo->sisfb_mode_idx >= 0) {
6380 int bu = ivideo->sisfb_mode_idx;
6381 ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
6382 ivideo->sisfb_mode_idx, ivideo->currentvbflags);
6383 if(bu != ivideo->sisfb_mode_idx) {
6384 printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
6385 sisbios_mode[bu].xres,
6386 sisbios_mode[bu].yres,
6387 sisbios_mode[bu].bpp);
6388 }
6389 }
6390
6391 if(ivideo->sisfb_mode_idx < 0) {
6392 switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
6393 case CRT2_LCD:
6394 ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
6395 break;
6396 case CRT2_TV:
6397 ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
6398 break;
6399 default:
6400 ivideo->sisfb_mode_idx = ivideo->defmodeidx;
6401 break;
6402 }
6403 }
6404
6405 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
6406
6407 if(ivideo->refresh_rate != 0) {
6408 sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate,
6409 ivideo->sisfb_mode_idx);
6410 }
6411
6412 if(ivideo->rate_idx == 0) {
6413 ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
6414 ivideo->refresh_rate = 60;
6415 }
6416
6417 if(ivideo->sisfb_thismonitor.datavalid) {
6418 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor,
6419 ivideo->sisfb_mode_idx,
6420 ivideo->rate_idx,
6421 ivideo->refresh_rate)) {
6422 printk(KERN_INFO "sisfb: WARNING: Refresh rate "
6423 "exceeds monitor specs!\n");
6424 }
6425 }
6426
6427 ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
6428 ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
6429 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
6430
6431 sisfb_set_vparms(ivideo);
6432
6433 printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
6434 ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
6435 ivideo->refresh_rate);
6436
6437 /* Set up the default var according to chosen default display mode */
6438 ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
6439 ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
6440 ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
6441
6442 sisfb_bpp_to_var(ivideo, &ivideo->default_var);
6443
6444 ivideo->default_var.pixclock = (u32) (1000000000 /
6445 sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx));
6446
6447 if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no,
6448 ivideo->rate_idx, &ivideo->default_var)) {
6449 if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
6450 ivideo->default_var.pixclock <<= 1;
6451 }
6452 }
6453
6454 if(ivideo->sisfb_ypan) {
6455 /* Maximize regardless of sisfb_max at startup */
6456 ivideo->default_var.yres_virtual =
6457 sisfb_calc_maxyres(ivideo, &ivideo->default_var);
6458 if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
6459 ivideo->default_var.yres_virtual = ivideo->default_var.yres;
6460 }
6461 }
6462
6463 sisfb_calc_pitch(ivideo, &ivideo->default_var);
6464
6465 ivideo->accel = 0;
6466 if(ivideo->sisfb_accel) {
6467 ivideo->accel = -1;
6468 #ifdef STUPID_ACCELF_TEXT_SHIT
6469 ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
6470 #endif
6471 }
6472 sisfb_initaccel(ivideo);
6473
6474 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
6475 sis_fb_info->flags = FBINFO_DEFAULT |
6476 FBINFO_HWACCEL_YPAN |
6477 FBINFO_HWACCEL_XPAN |
6478 FBINFO_HWACCEL_COPYAREA |
6479 FBINFO_HWACCEL_FILLRECT |
6480 ((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED);
6481 #else
6482 sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
6483 #endif
6484 sis_fb_info->var = ivideo->default_var;
6485 sis_fb_info->fix = ivideo->sisfb_fix;
6486 sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
6487 sis_fb_info->fbops = &sisfb_ops;
6488 sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
6489
6490 fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
6491
6492 printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
6493
6494 ivideo->wc_cookie = arch_phys_wc_add(ivideo->video_base,
6495 ivideo->video_size);
6496 if(register_framebuffer(sis_fb_info) < 0) {
6497 printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
6498 ret = -EINVAL;
6499 iounmap(ivideo->mmio_vbase);
6500 goto error_0;
6501 }
6502
6503 ivideo->registered = 1;
6504
6505 /* Enlist us */
6506 ivideo->next = card_list;
6507 card_list = ivideo;
6508
6509 printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
6510 ivideo->sisfb_accel ? "enabled" : "disabled",
6511 ivideo->sisfb_ypan ?
6512 (ivideo->sisfb_max ? "enabled (auto-max)" :
6513 "enabled (no auto-max)") :
6514 "disabled");
6515
6516
6517 fb_info(sis_fb_info, "%s frame buffer device version %d.%d.%d\n",
6518 ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
6519
6520 printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
6521
6522 } /* if mode = "none" */
6523
6524 return 0;
6525 }
6526
6527 /*****************************************************/
6528 /* PCI DEVICE HANDLING */
6529 /*****************************************************/
6530
sisfb_remove(struct pci_dev * pdev)6531 static void sisfb_remove(struct pci_dev *pdev)
6532 {
6533 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
6534 struct fb_info *sis_fb_info = ivideo->memyselfandi;
6535 int registered = ivideo->registered;
6536 int modechanged = ivideo->modechanged;
6537
6538 /* Unmap */
6539 iounmap(ivideo->mmio_vbase);
6540 iounmap(ivideo->video_vbase);
6541
6542 /* Release mem regions */
6543 release_mem_region(ivideo->video_base, ivideo->video_size);
6544 release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6545
6546 vfree(ivideo->bios_abase);
6547
6548 pci_dev_put(ivideo->lpcdev);
6549
6550 pci_dev_put(ivideo->nbridge);
6551
6552 arch_phys_wc_del(ivideo->wc_cookie);
6553
6554 /* If device was disabled when starting, disable
6555 * it when quitting.
6556 */
6557 if(!ivideo->sisvga_enabled)
6558 pci_disable_device(pdev);
6559
6560 /* Unregister the framebuffer */
6561 if(ivideo->registered) {
6562 unregister_framebuffer(sis_fb_info);
6563 framebuffer_release(sis_fb_info);
6564 }
6565
6566 /* OK, our ivideo is gone for good from here. */
6567
6568 /* TODO: Restore the initial mode
6569 * This sounds easy but is as good as impossible
6570 * on many machines with SiS chip and video bridge
6571 * since text modes are always set up differently
6572 * from machine to machine. Depends on the type
6573 * of integration between chipset and bridge.
6574 */
6575 if(registered && modechanged)
6576 printk(KERN_INFO
6577 "sisfb: Restoring of text mode not supported yet\n");
6578 };
6579
6580 static struct pci_driver sisfb_driver = {
6581 .name = "sisfb",
6582 .id_table = sisfb_pci_table,
6583 .probe = sisfb_probe,
6584 .remove = sisfb_remove,
6585 };
6586
sisfb_init(void)6587 static int __init sisfb_init(void)
6588 {
6589 #ifndef MODULE
6590 char *options = NULL;
6591
6592 if(fb_get_options("sisfb", &options))
6593 return -ENODEV;
6594
6595 sisfb_setup(options);
6596 #endif
6597 return pci_register_driver(&sisfb_driver);
6598 }
6599
6600 #ifndef MODULE
6601 module_init(sisfb_init);
6602 #endif
6603
6604 /*****************************************************/
6605 /* MODULE */
6606 /*****************************************************/
6607
6608 #ifdef MODULE
6609
6610 static char *mode = NULL;
6611 static int vesa = -1;
6612 static unsigned int rate = 0;
6613 static unsigned int crt1off = 1;
6614 static unsigned int mem = 0;
6615 static char *forcecrt2type = NULL;
6616 static int forcecrt1 = -1;
6617 static int pdc = -1;
6618 static int pdc1 = -1;
6619 static int noaccel = -1;
6620 static int noypan = -1;
6621 static int nomax = -1;
6622 static int userom = -1;
6623 static int useoem = -1;
6624 static char *tvstandard = NULL;
6625 static int nocrt2rate = 0;
6626 static int scalelcd = -1;
6627 static char *specialtiming = NULL;
6628 static int lvdshl = -1;
6629 static int tvxposoffset = 0, tvyposoffset = 0;
6630 #if !defined(__i386__) && !defined(__x86_64__)
6631 static int resetcard = 0;
6632 static int videoram = 0;
6633 #endif
6634
sisfb_init_module(void)6635 static int __init sisfb_init_module(void)
6636 {
6637 sisfb_setdefaultparms();
6638
6639 if(rate)
6640 sisfb_parm_rate = rate;
6641
6642 if((scalelcd == 0) || (scalelcd == 1))
6643 sisfb_scalelcd = scalelcd ^ 1;
6644
6645 /* Need to check crt2 type first for fstn/dstn */
6646
6647 if(forcecrt2type)
6648 sisfb_search_crt2type(forcecrt2type);
6649
6650 if(tvstandard)
6651 sisfb_search_tvstd(tvstandard);
6652
6653 if(mode)
6654 sisfb_search_mode(mode, false);
6655 else if(vesa != -1)
6656 sisfb_search_vesamode(vesa, false);
6657
6658 sisfb_crt1off = (crt1off == 0) ? 1 : 0;
6659
6660 sisfb_forcecrt1 = forcecrt1;
6661 if(forcecrt1 == 1)
6662 sisfb_crt1off = 0;
6663 else if(forcecrt1 == 0)
6664 sisfb_crt1off = 1;
6665
6666 if(noaccel == 1)
6667 sisfb_accel = 0;
6668 else if(noaccel == 0)
6669 sisfb_accel = 1;
6670
6671 if(noypan == 1)
6672 sisfb_ypan = 0;
6673 else if(noypan == 0)
6674 sisfb_ypan = 1;
6675
6676 if(nomax == 1)
6677 sisfb_max = 0;
6678 else if(nomax == 0)
6679 sisfb_max = 1;
6680
6681 if(mem)
6682 sisfb_parm_mem = mem;
6683
6684 if(userom != -1)
6685 sisfb_userom = userom;
6686
6687 if(useoem != -1)
6688 sisfb_useoem = useoem;
6689
6690 if(pdc != -1)
6691 sisfb_pdc = (pdc & 0x7f);
6692
6693 if(pdc1 != -1)
6694 sisfb_pdca = (pdc1 & 0x1f);
6695
6696 sisfb_nocrt2rate = nocrt2rate;
6697
6698 if(specialtiming)
6699 sisfb_search_specialtiming(specialtiming);
6700
6701 if((lvdshl >= 0) && (lvdshl <= 3))
6702 sisfb_lvdshl = lvdshl;
6703
6704 sisfb_tvxposoffset = tvxposoffset;
6705 sisfb_tvyposoffset = tvyposoffset;
6706
6707 #if !defined(__i386__) && !defined(__x86_64__)
6708 sisfb_resetcard = (resetcard) ? 1 : 0;
6709 if(videoram)
6710 sisfb_videoram = videoram;
6711 #endif
6712
6713 return sisfb_init();
6714 }
6715
sisfb_remove_module(void)6716 static void __exit sisfb_remove_module(void)
6717 {
6718 pci_unregister_driver(&sisfb_driver);
6719 printk(KERN_DEBUG "sisfb: Module unloaded\n");
6720 }
6721
6722 module_init(sisfb_init_module);
6723 module_exit(sisfb_remove_module);
6724
6725 MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
6726 MODULE_LICENSE("GPL");
6727 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
6728
6729 module_param(mem, int, 0);
6730 module_param(noaccel, int, 0);
6731 module_param(noypan, int, 0);
6732 module_param(nomax, int, 0);
6733 module_param(userom, int, 0);
6734 module_param(useoem, int, 0);
6735 module_param(mode, charp, 0);
6736 module_param(vesa, int, 0);
6737 module_param(rate, int, 0);
6738 module_param(forcecrt1, int, 0);
6739 module_param(forcecrt2type, charp, 0);
6740 module_param(scalelcd, int, 0);
6741 module_param(pdc, int, 0);
6742 module_param(pdc1, int, 0);
6743 module_param(specialtiming, charp, 0);
6744 module_param(lvdshl, int, 0);
6745 module_param(tvstandard, charp, 0);
6746 module_param(tvxposoffset, int, 0);
6747 module_param(tvyposoffset, int, 0);
6748 module_param(nocrt2rate, int, 0);
6749 #if !defined(__i386__) && !defined(__x86_64__)
6750 module_param(resetcard, int, 0);
6751 module_param(videoram, int, 0);
6752 #endif
6753
6754 MODULE_PARM_DESC(mem,
6755 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6756 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6757 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6758 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6759 "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6760 "The value is to be specified without 'KB'.\n");
6761
6762 MODULE_PARM_DESC(noaccel,
6763 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
6764 "(default: 0)\n");
6765
6766 MODULE_PARM_DESC(noypan,
6767 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
6768 "will be performed by redrawing the screen. (default: 0)\n");
6769
6770 MODULE_PARM_DESC(nomax,
6771 "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
6772 "memory for the virtual screen in order to optimize scrolling performance. If\n"
6773 "this is set to anything other than 0, sisfb will not do this and thereby \n"
6774 "enable the user to positively specify a virtual Y size of the screen using\n"
6775 "fbset. (default: 0)\n");
6776
6777 MODULE_PARM_DESC(mode,
6778 "\nSelects the desired default display mode in the format XxYxDepth,\n"
6779 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
6780 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
6781 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
6782
6783 MODULE_PARM_DESC(vesa,
6784 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
6785 "0x117 (default: 0x0103)\n");
6786
6787 MODULE_PARM_DESC(rate,
6788 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
6789 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
6790 "will be ignored (default: 60)\n");
6791
6792 MODULE_PARM_DESC(forcecrt1,
6793 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
6794 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
6795 "0=CRT1 OFF) (default: [autodetected])\n");
6796
6797 MODULE_PARM_DESC(forcecrt2type,
6798 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
6799 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
6800 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
6801 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
6802 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
6803 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
6804 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
6805 "depends on the very hardware in use. (default: [autodetected])\n");
6806
6807 MODULE_PARM_DESC(scalelcd,
6808 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
6809 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
6810 "show black bars around the image, TMDS panels will probably do the scaling\n"
6811 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
6812
6813 MODULE_PARM_DESC(pdc,
6814 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
6815 "should detect this correctly in most cases; however, sometimes this is not\n"
6816 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
6817 "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
6818 "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
6819 "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
6820
6821 #ifdef CONFIG_FB_SIS_315
6822 MODULE_PARM_DESC(pdc1,
6823 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
6824 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
6825 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
6826 "implemented yet.\n");
6827 #endif
6828
6829 MODULE_PARM_DESC(specialtiming,
6830 "\nPlease refer to documentation for more information on this option.\n");
6831
6832 MODULE_PARM_DESC(lvdshl,
6833 "\nPlease refer to documentation for more information on this option.\n");
6834
6835 MODULE_PARM_DESC(tvstandard,
6836 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
6837 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
6838
6839 MODULE_PARM_DESC(tvxposoffset,
6840 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
6841 "Default: 0\n");
6842
6843 MODULE_PARM_DESC(tvyposoffset,
6844 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
6845 "Default: 0\n");
6846
6847 MODULE_PARM_DESC(nocrt2rate,
6848 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
6849 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
6850
6851 #if !defined(__i386__) && !defined(__x86_64__)
6852 #ifdef CONFIG_FB_SIS_300
6853 MODULE_PARM_DESC(resetcard,
6854 "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
6855 "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
6856 "currently). Default: 0\n");
6857
6858 MODULE_PARM_DESC(videoram,
6859 "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
6860 "some non-x86 architectures where the memory auto detection fails. Only\n"
6861 "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
6862 #endif
6863 #endif
6864
6865 #endif /* /MODULE */
6866
6867 /* _GPL only for new symbols. */
6868 EXPORT_SYMBOL(sis_malloc);
6869 EXPORT_SYMBOL(sis_free);
6870 EXPORT_SYMBOL_GPL(sis_malloc_new);
6871 EXPORT_SYMBOL_GPL(sis_free_new);
6872
6873
6874
6875