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