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