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