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