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