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