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