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],
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:
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>
43 #include <linux/screen_info.h>
44 #include <linux/slab.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>
53 #include <linux/types.h>
54 #include <linux/uaccess.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!
68 static void sisfb_handle_command(struct sis_video_info *ivideo,
69 struct sisfb_cmd *sisfb_command);
71 /* ------------------ Internal helper routines ----------------- */
74 sisfb_setdefaultparms(void)
92 sisfb_specialtiming = CUT_NONE;
98 sisfb_tvxposoffset = 0;
99 sisfb_tvyposoffset = 0;
100 sisfb_nocrt2rate = 0;
101 #if !defined(__i386__) && !defined(__x86_64__)
107 /* ------------- Parameter parsing -------------- */
109 static void sisfb_search_vesamode(unsigned int vesamode, bool quiet)
113 /* We don't know the hardware specs yet and there is no ivideo */
117 printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
119 sisfb_mode_idx = DEFAULT_MODE;
124 vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
126 while(sisbios_mode[i++].mode_no[0] != 0) {
127 if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
128 (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
130 if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
131 sisbios_mode[i-1].mode_no[1] == 0x56 ||
132 sisbios_mode[i-1].mode_no[1] == 0x53)
135 if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
136 sisbios_mode[i-1].mode_no[1] == 0x5b)
139 sisfb_mode_idx = i - 1;
145 printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
148 static void sisfb_search_mode(char *name, bool quiet)
150 unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
152 char strbuf[16], strbuf1[20];
153 char *nameptr = name;
155 /* We don't know the hardware specs yet and there is no ivideo */
159 printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
161 sisfb_mode_idx = DEFAULT_MODE;
165 if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
167 printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
169 sisfb_mode_idx = DEFAULT_MODE;
173 if(strlen(name) <= 19) {
174 strcpy(strbuf1, name);
175 for(i = 0; i < strlen(strbuf1); i++) {
176 if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
179 /* This does some fuzzy mode naming detection */
180 if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
181 if((rate <= 32) || (depth > 32)) {
182 j = rate; rate = depth; depth = j;
184 sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
186 sisfb_parm_rate = rate;
187 } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
188 sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
192 if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
193 sprintf(strbuf, "%ux%ux8", xres, yres);
196 sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
203 while(sisbios_mode[i].mode_no[0] != 0) {
204 if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
206 if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
207 sisbios_mode[i-1].mode_no[1] == 0x56 ||
208 sisbios_mode[i-1].mode_no[1] == 0x53)
211 if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
212 sisbios_mode[i-1].mode_no[1] == 0x5b)
215 sisfb_mode_idx = i - 1;
222 printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
226 static void sisfb_get_vga_mode_from_kernel(void)
230 int mydepth = screen_info.lfb_depth;
232 if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
234 if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) &&
235 (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
236 (mydepth >= 8) && (mydepth <= 32) ) {
238 if(mydepth == 24) mydepth = 32;
240 sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
241 screen_info.lfb_height,
245 "sisfb: Using vga mode %s pre-set by kernel as default\n",
248 sisfb_search_mode(mymode, true);
256 sisfb_search_crt2type(const char *name)
260 /* We don't know the hardware specs yet and there is no ivideo */
262 if(name == NULL) return;
264 while(sis_crt2type[i].type_no != -1) {
265 if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
266 sisfb_crt2type = sis_crt2type[i].type_no;
267 sisfb_tvplug = sis_crt2type[i].tvplug_no;
268 sisfb_crt2flags = sis_crt2type[i].flags;
274 sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
275 sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
277 if(sisfb_crt2type < 0)
278 printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
282 sisfb_search_tvstd(const char *name)
286 /* We don't know the hardware specs yet and there is no ivideo */
291 while(sis_tvtype[i].type_no != -1) {
292 if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
293 sisfb_tvstd = sis_tvtype[i].type_no;
301 sisfb_search_specialtiming(const char *name)
306 /* We don't know the hardware specs yet and there is no ivideo */
311 if(!strnicmp(name, "none", 4)) {
312 sisfb_specialtiming = CUT_FORCENONE;
313 printk(KERN_DEBUG "sisfb: Special timing disabled\n");
315 while(mycustomttable[i].chipID != 0) {
316 if(!strnicmp(name,mycustomttable[i].optionName,
317 strlen(mycustomttable[i].optionName))) {
318 sisfb_specialtiming = mycustomttable[i].SpecialID;
320 printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
321 mycustomttable[i].vendorName,
322 mycustomttable[i].cardName,
323 mycustomttable[i].optionName);
329 printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
330 printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
332 while(mycustomttable[i].chipID != 0) {
333 printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
334 mycustomttable[i].optionName,
335 mycustomttable[i].vendorName,
336 mycustomttable[i].cardName);
343 /* ----------- Various detection routines ----------- */
345 static void sisfb_detect_custom_timing(struct sis_video_info *ivideo)
347 unsigned char *biosver = NULL;
348 unsigned char *biosdate = NULL;
353 if(ivideo->SiS_Pr.UseROM) {
354 biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06;
355 biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c;
356 for(i = 0; i < 32768; i++)
357 chksum += ivideo->SiS_Pr.VirtualRomBase[i];
362 if( (mycustomttable[i].chipID == ivideo->chip) &&
363 ((!strlen(mycustomttable[i].biosversion)) ||
364 (ivideo->SiS_Pr.UseROM &&
365 (!strncmp(mycustomttable[i].biosversion, biosver,
366 strlen(mycustomttable[i].biosversion))))) &&
367 ((!strlen(mycustomttable[i].biosdate)) ||
368 (ivideo->SiS_Pr.UseROM &&
369 (!strncmp(mycustomttable[i].biosdate, biosdate,
370 strlen(mycustomttable[i].biosdate))))) &&
371 ((!mycustomttable[i].bioschksum) ||
372 (ivideo->SiS_Pr.UseROM &&
373 (mycustomttable[i].bioschksum == chksum))) &&
374 (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
375 (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
377 for(j = 0; j < 5; j++) {
378 if(mycustomttable[i].biosFootprintAddr[j]) {
379 if(ivideo->SiS_Pr.UseROM) {
380 if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
381 mycustomttable[i].biosFootprintData[j]) {
389 ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
390 printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
391 mycustomttable[i].vendorName,
392 mycustomttable[i].cardName);
393 printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
394 mycustomttable[i].optionName);
399 } while(mycustomttable[i].chipID);
402 static bool sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
404 int i, j, xres, yres, refresh, index;
407 if(buffer[0] != 0x00 || buffer[1] != 0xff ||
408 buffer[2] != 0xff || buffer[3] != 0xff ||
409 buffer[4] != 0xff || buffer[5] != 0xff ||
410 buffer[6] != 0xff || buffer[7] != 0x00) {
411 printk(KERN_DEBUG "sisfb: Bad EDID header\n");
415 if(buffer[0x12] != 0x01) {
416 printk(KERN_INFO "sisfb: EDID version %d not supported\n",
421 monitor->feature = buffer[0x18];
423 if(!(buffer[0x14] & 0x80)) {
424 if(!(buffer[0x14] & 0x08)) {
426 "sisfb: WARNING: Monitor does not support separate syncs\n");
430 if(buffer[0x13] >= 0x01) {
431 /* EDID V1 rev 1 and 2: Search for monitor descriptor
436 if(buffer[j] == 0x00 && buffer[j + 1] == 0x00 &&
437 buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
438 buffer[j + 4] == 0x00) {
439 monitor->hmin = buffer[j + 7];
440 monitor->hmax = buffer[j + 8];
441 monitor->vmin = buffer[j + 5];
442 monitor->vmax = buffer[j + 6];
443 monitor->dclockmax = buffer[j + 9] * 10 * 1000;
444 monitor->datavalid = true;
451 if(!monitor->datavalid) {
452 /* Otherwise: Get a range from the list of supported
453 * Estabished Timings. This is not entirely accurate,
454 * because fixed frequency monitors are not supported
457 monitor->hmin = 65535; monitor->hmax = 0;
458 monitor->vmin = 65535; monitor->vmax = 0;
459 monitor->dclockmax = 0;
460 emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
461 for(i = 0; i < 13; i++) {
462 if(emodes & sisfb_ddcsmodes[i].mask) {
463 if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
464 if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
465 if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
466 if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
467 if(monitor->dclockmax < sisfb_ddcsmodes[i].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
471 for(i = 0; i < 8; i++) {
472 xres = (buffer[index] + 31) * 8;
473 switch(buffer[index + 1] & 0xc0) {
474 case 0xc0: yres = (xres * 9) / 16; break;
475 case 0x80: yres = (xres * 4) / 5; break;
476 case 0x40: yres = (xres * 3) / 4; break;
477 default: yres = xres; break;
479 refresh = (buffer[index + 1] & 0x3f) + 60;
480 if((xres >= 640) && (yres >= 480)) {
481 for(j = 0; j < 8; j++) {
482 if((xres == sisfb_ddcfmodes[j].x) &&
483 (yres == sisfb_ddcfmodes[j].y) &&
484 (refresh == sisfb_ddcfmodes[j].v)) {
485 if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
486 if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
487 if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
488 if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
489 if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d;
495 if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
496 monitor->datavalid = true;
500 return monitor->datavalid;
503 static void sisfb_handle_ddc(struct sis_video_info *ivideo,
504 struct sisfb_monitor *monitor, int crtno)
506 unsigned short temp, i, realcrtno = crtno;
507 unsigned char buffer[256];
509 monitor->datavalid = false;
512 if(ivideo->vbflags & CRT2_LCD) realcrtno = 1;
513 else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
517 if((ivideo->sisfb_crt1off) && (!crtno))
520 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
521 realcrtno, 0, &buffer[0], ivideo->vbflags2);
522 if((!temp) || (temp == 0xffff)) {
523 printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
526 printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
527 printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
529 (temp & 0x1a) ? "" : "[none of the supported]",
530 (temp & 0x02) ? "2 " : "",
531 (temp & 0x08) ? "D&P" : "",
532 (temp & 0x10) ? "FPDI-2" : "");
534 i = 3; /* Number of retrys */
536 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
537 realcrtno, 1, &buffer[0], ivideo->vbflags2);
538 } while((temp) && i--);
540 if(sisfb_interpret_edid(monitor, &buffer[0])) {
541 printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
542 monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
543 monitor->dclockmax / 1000);
545 printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
548 printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
551 printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
556 /* -------------- Mode validation --------------- */
559 sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
560 int mode_idx, int rate_idx, int rate)
563 unsigned int dclock, hsync;
565 if(!monitor->datavalid)
571 /* Skip for 320x200, 320x240, 640x400 */
572 switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
583 #ifdef CONFIG_FB_SIS_315
586 if(ivideo->sisvga_engine == SIS_315_VGA) return true;
590 if(rate < (monitor->vmin - 1))
592 if(rate > (monitor->vmax + 1))
595 if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
596 sisbios_mode[mode_idx].mode_no[ivideo->mni],
597 &htotal, &vtotal, rate_idx)) {
598 dclock = (htotal * vtotal * rate) / 1000;
599 if(dclock > (monitor->dclockmax + 1000))
601 hsync = dclock / htotal;
602 if(hsync < (monitor->hmin - 1))
604 if(hsync > (monitor->hmax + 1))
613 sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
615 u16 xres=0, yres, myres;
617 #ifdef CONFIG_FB_SIS_300
618 if(ivideo->sisvga_engine == SIS_300_VGA) {
619 if(!(sisbios_mode[myindex].chipset & MD_SIS300))
623 #ifdef CONFIG_FB_SIS_315
624 if(ivideo->sisvga_engine == SIS_315_VGA) {
625 if(!(sisbios_mode[myindex].chipset & MD_SIS315))
630 myres = sisbios_mode[myindex].yres;
632 switch(vbflags & VB_DISPTYPE_DISP2) {
635 xres = ivideo->lcdxres; yres = ivideo->lcdyres;
637 if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
638 (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
639 if(sisbios_mode[myindex].xres > xres)
645 if(ivideo->sisfb_fstn) {
646 if(sisbios_mode[myindex].xres == 320) {
648 switch(sisbios_mode[myindex].mode_no[1]) {
649 case 0x50: myindex = MODE_FSTN_8; break;
650 case 0x56: myindex = MODE_FSTN_16; break;
651 case 0x53: return -1;
657 if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
658 sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
659 ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
665 if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
666 sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
672 if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
673 sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
683 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
686 u16 xres = sisbios_mode[mode_idx].xres;
687 u16 yres = sisbios_mode[mode_idx].yres;
689 ivideo->rate_idx = 0;
690 while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
691 if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
692 if(sisfb_vrate[i].refresh == rate) {
693 ivideo->rate_idx = sisfb_vrate[i].idx;
695 } else if(sisfb_vrate[i].refresh > rate) {
696 if((sisfb_vrate[i].refresh - rate) <= 3) {
697 DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
698 rate, sisfb_vrate[i].refresh);
699 ivideo->rate_idx = sisfb_vrate[i].idx;
700 ivideo->refresh_rate = sisfb_vrate[i].refresh;
701 } else if((sisfb_vrate[i].idx != 1) &&
702 ((rate - sisfb_vrate[i-1].refresh) <= 2)) {
703 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
704 rate, sisfb_vrate[i-1].refresh);
705 ivideo->rate_idx = sisfb_vrate[i-1].idx;
706 ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
709 } else if((rate - sisfb_vrate[i].refresh) <= 2) {
710 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
711 rate, sisfb_vrate[i].refresh);
712 ivideo->rate_idx = sisfb_vrate[i].idx;
718 if(ivideo->rate_idx > 0) {
719 return ivideo->rate_idx;
721 printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n",
728 sisfb_bridgeisslave(struct sis_video_info *ivideo)
732 if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
735 P1_00 = SiS_GetReg(SISPART1, 0x00);
736 if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
737 ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
745 sisfballowretracecrt1(struct sis_video_info *ivideo)
749 temp = SiS_GetReg(SISCR, 0x17);
753 temp = SiS_GetReg(SISSR, 0x1f);
761 sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
763 if(!sisfballowretracecrt1(ivideo))
766 if (SiS_GetRegByte(SISINPSTAT) & 0x08)
773 sisfbwaitretracecrt1(struct sis_video_info *ivideo)
777 if(!sisfballowretracecrt1(ivideo))
781 while ((!(SiS_GetRegByte(SISINPSTAT) & 0x08)) && --watchdog);
783 while ((SiS_GetRegByte(SISINPSTAT) & 0x08) && --watchdog);
787 sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
789 unsigned char temp, reg;
791 switch(ivideo->sisvga_engine) {
792 case SIS_300_VGA: reg = 0x25; break;
793 case SIS_315_VGA: reg = 0x30; break;
794 default: return false;
797 temp = SiS_GetReg(SISPART1, reg);
805 sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
807 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
808 if(!sisfb_bridgeisslave(ivideo)) {
809 return sisfbcheckvretracecrt2(ivideo);
812 return sisfbcheckvretracecrt1(ivideo);
816 sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
818 u8 idx, reg1, reg2, reg3, reg4;
821 (*vcount) = (*hcount) = 0;
823 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
825 ret |= (FB_VBLANK_HAVE_VSYNC |
826 FB_VBLANK_HAVE_HBLANK |
827 FB_VBLANK_HAVE_VBLANK |
828 FB_VBLANK_HAVE_VCOUNT |
829 FB_VBLANK_HAVE_HCOUNT);
830 switch(ivideo->sisvga_engine) {
831 case SIS_300_VGA: idx = 0x25; break;
833 case SIS_315_VGA: idx = 0x30; break;
835 reg1 = SiS_GetReg(SISPART1, (idx+0)); /* 30 */
836 reg2 = SiS_GetReg(SISPART1, (idx+1)); /* 31 */
837 reg3 = SiS_GetReg(SISPART1, (idx+2)); /* 32 */
838 reg4 = SiS_GetReg(SISPART1, (idx+3)); /* 33 */
839 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
840 if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
841 if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
842 (*vcount) = reg3 | ((reg4 & 0x70) << 4);
843 (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
845 } else if(sisfballowretracecrt1(ivideo)) {
847 ret |= (FB_VBLANK_HAVE_VSYNC |
848 FB_VBLANK_HAVE_VBLANK |
849 FB_VBLANK_HAVE_VCOUNT |
850 FB_VBLANK_HAVE_HCOUNT);
851 reg1 = SiS_GetRegByte(SISINPSTAT);
852 if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
853 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
854 reg1 = SiS_GetReg(SISCR, 0x20);
855 reg1 = SiS_GetReg(SISCR, 0x1b);
856 reg2 = SiS_GetReg(SISCR, 0x1c);
857 reg3 = SiS_GetReg(SISCR, 0x1d);
858 (*vcount) = reg2 | ((reg3 & 0x07) << 8);
859 (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
866 sisfb_myblank(struct sis_video_info *ivideo, int blank)
868 u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
869 bool backlight = true;
872 case FB_BLANK_UNBLANK: /* on */
881 case FB_BLANK_NORMAL: /* blank */
890 case FB_BLANK_VSYNC_SUSPEND: /* no vsync */
899 case FB_BLANK_HSYNC_SUSPEND: /* no hsync */
908 case FB_BLANK_POWERDOWN: /* off */
921 if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
923 if( (!ivideo->sisfb_thismonitor.datavalid) ||
924 ((ivideo->sisfb_thismonitor.datavalid) &&
925 (ivideo->sisfb_thismonitor.feature & 0xe0))) {
927 if(ivideo->sisvga_engine == SIS_315_VGA) {
928 SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
931 if(!(sisfb_bridgeisslave(ivideo))) {
932 SiS_SetRegANDOR(SISSR, 0x01, ~0x20, sr01);
933 SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, sr1f);
939 if(ivideo->currentvbflags & CRT2_LCD) {
941 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
943 SiS_SiS30xBLOn(&ivideo->SiS_Pr);
945 SiS_SiS30xBLOff(&ivideo->SiS_Pr);
947 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
948 #ifdef CONFIG_FB_SIS_315
949 if(ivideo->vbflags2 & VB2_CHRONTEL) {
951 SiS_Chrontel701xBLOn(&ivideo->SiS_Pr);
953 SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
959 if(((ivideo->sisvga_engine == SIS_300_VGA) &&
960 (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
961 ((ivideo->sisvga_engine == SIS_315_VGA) &&
962 ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
963 SiS_SetRegANDOR(SISSR, 0x11, ~0x0c, sr11);
966 if(ivideo->sisvga_engine == SIS_300_VGA) {
967 if((ivideo->vbflags2 & VB2_30xB) &&
968 (!(ivideo->vbflags2 & VB2_30xBDH))) {
969 SiS_SetRegANDOR(SISPART1, 0x13, 0x3f, p1_13);
971 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
972 if((ivideo->vbflags2 & VB2_30xB) &&
973 (!(ivideo->vbflags2 & VB2_30xBDH))) {
974 SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
978 } else if(ivideo->currentvbflags & CRT2_VGA) {
980 if(ivideo->vbflags2 & VB2_30xB) {
981 SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
989 /* ------------- Callbacks from init.c/init301.c -------------- */
991 #ifdef CONFIG_FB_SIS_300
993 sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg)
995 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
998 pci_read_config_dword(ivideo->nbridge, reg, &val);
999 return (unsigned int)val;
1003 sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val)
1005 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1007 pci_write_config_dword(ivideo->nbridge, reg, (u32)val);
1011 sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg)
1013 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1016 if(!ivideo->lpcdev) return 0;
1018 pci_read_config_dword(ivideo->lpcdev, reg, &val);
1019 return (unsigned int)val;
1023 #ifdef CONFIG_FB_SIS_315
1025 sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val)
1027 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1029 pci_write_config_byte(ivideo->nbridge, reg, (u8)val);
1033 sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg)
1035 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1038 if(!ivideo->lpcdev) return 0;
1040 pci_read_config_word(ivideo->lpcdev, reg, &val);
1041 return (unsigned int)val;
1045 /* ----------- FBDev related routines for all series ----------- */
1048 sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
1050 return (var->bits_per_pixel == 8) ? 256 : 16;
1054 sisfb_set_vparms(struct sis_video_info *ivideo)
1056 switch(ivideo->video_bpp) {
1058 ivideo->DstColor = 0x0000;
1059 ivideo->SiS310_AccelDepth = 0x00000000;
1060 ivideo->video_cmap_len = 256;
1063 ivideo->DstColor = 0x8000;
1064 ivideo->SiS310_AccelDepth = 0x00010000;
1065 ivideo->video_cmap_len = 16;
1068 ivideo->DstColor = 0xC000;
1069 ivideo->SiS310_AccelDepth = 0x00020000;
1070 ivideo->video_cmap_len = 16;
1073 ivideo->video_cmap_len = 16;
1074 printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
1080 sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1082 int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3));
1084 if(maxyres > 32767) maxyres = 32767;
1090 sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1092 ivideo->video_linelength = var->xres_virtual * (var->bits_per_pixel >> 3);
1093 ivideo->scrnpitchCRT1 = ivideo->video_linelength;
1094 if(!(ivideo->currentvbflags & CRT1_LCDA)) {
1095 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1096 ivideo->scrnpitchCRT1 <<= 1;
1102 sisfb_set_pitch(struct sis_video_info *ivideo)
1104 bool isslavemode = false;
1105 unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
1106 unsigned short HDisplay2 = ivideo->video_linelength >> 3;
1108 if(sisfb_bridgeisslave(ivideo)) isslavemode = true;
1110 /* We need to set pitch for CRT1 if bridge is in slave mode, too */
1111 if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
1112 SiS_SetReg(SISCR, 0x13, (HDisplay1 & 0xFF));
1113 SiS_SetRegANDOR(SISSR, 0x0E, 0xF0, (HDisplay1 >> 8));
1116 /* We must not set the pitch for CRT2 if bridge is in slave mode */
1117 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
1118 SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
1119 SiS_SetReg(SISPART1, 0x07, (HDisplay2 & 0xFF));
1120 SiS_SetRegANDOR(SISPART1, 0x09, 0xF0, (HDisplay2 >> 8));
1125 sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1127 ivideo->video_cmap_len = sisfb_get_cmap_len(var);
1129 switch(var->bits_per_pixel) {
1131 var->red.offset = var->green.offset = var->blue.offset = 0;
1132 var->red.length = var->green.length = var->blue.length = 8;
1135 var->red.offset = 11;
1136 var->red.length = 5;
1137 var->green.offset = 5;
1138 var->green.length = 6;
1139 var->blue.offset = 0;
1140 var->blue.length = 5;
1141 var->transp.offset = 0;
1142 var->transp.length = 0;
1145 var->red.offset = 16;
1146 var->red.length = 8;
1147 var->green.offset = 8;
1148 var->green.length = 8;
1149 var->blue.offset = 0;
1150 var->blue.length = 8;
1151 var->transp.offset = 24;
1152 var->transp.length = 8;
1158 sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
1160 unsigned short modeno = ivideo->mode_no;
1162 /* >=2.6.12's fbcon clears the screen anyway */
1165 SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1167 sisfb_pre_setmode(ivideo);
1169 if(!SiSSetMode(&ivideo->SiS_Pr, modeno)) {
1170 printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
1174 SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1176 sisfb_post_setmode(ivideo);
1183 sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
1185 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1186 unsigned int htotal = 0, vtotal = 0;
1187 unsigned int drate = 0, hrate = 0;
1188 int found_mode = 0, ret;
1192 htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1194 vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1196 pixclock = var->pixclock;
1198 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1199 vtotal += var->yres;
1201 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1202 vtotal += var->yres;
1204 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1205 vtotal += var->yres;
1207 } else vtotal += var->yres;
1209 if(!(htotal) || !(vtotal)) {
1210 DPRINTK("sisfb: Invalid 'var' information\n");
1214 if(pixclock && htotal && vtotal) {
1215 drate = 1000000000 / pixclock;
1216 hrate = (drate * 1000) / htotal;
1217 ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1219 ivideo->refresh_rate = 60;
1222 old_mode = ivideo->sisfb_mode_idx;
1223 ivideo->sisfb_mode_idx = 0;
1225 while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) &&
1226 (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) {
1227 if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) &&
1228 (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) &&
1229 (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) {
1230 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1234 ivideo->sisfb_mode_idx++;
1238 ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
1239 ivideo->sisfb_mode_idx, ivideo->currentvbflags);
1241 ivideo->sisfb_mode_idx = -1;
1244 if(ivideo->sisfb_mode_idx < 0) {
1245 printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres,
1246 var->yres, var->bits_per_pixel);
1247 ivideo->sisfb_mode_idx = old_mode;
1251 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1253 if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
1254 ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
1255 ivideo->refresh_rate = 60;
1259 /* If acceleration to be used? Need to know
1260 * before pre/post_set_mode()
1263 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
1264 #ifdef STUPID_ACCELF_TEXT_SHIT
1265 if(var->accel_flags & FB_ACCELF_TEXT) {
1266 info->flags &= ~FBINFO_HWACCEL_DISABLED;
1268 info->flags |= FBINFO_HWACCEL_DISABLED;
1271 if(!(info->flags & FBINFO_HWACCEL_DISABLED)) ivideo->accel = -1;
1273 if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
1276 if((ret = sisfb_set_mode(ivideo, 1))) {
1280 ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
1281 ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
1282 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
1284 sisfb_calc_pitch(ivideo, var);
1285 sisfb_set_pitch(ivideo);
1287 sisfb_set_vparms(ivideo);
1289 ivideo->current_width = ivideo->video_width;
1290 ivideo->current_height = ivideo->video_height;
1291 ivideo->current_bpp = ivideo->video_bpp;
1292 ivideo->current_htotal = htotal;
1293 ivideo->current_vtotal = vtotal;
1294 ivideo->current_linelength = ivideo->video_linelength;
1295 ivideo->current_pixclock = var->pixclock;
1296 ivideo->current_refresh_rate = ivideo->refresh_rate;
1297 ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
1304 sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
1306 SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1308 SiS_SetReg(SISCR, 0x0D, base & 0xFF);
1309 SiS_SetReg(SISCR, 0x0C, (base >> 8) & 0xFF);
1310 SiS_SetReg(SISSR, 0x0D, (base >> 16) & 0xFF);
1311 if(ivideo->sisvga_engine == SIS_315_VGA) {
1312 SiS_SetRegANDOR(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
1317 sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
1319 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1320 SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
1321 SiS_SetReg(SISPART1, 0x06, (base & 0xFF));
1322 SiS_SetReg(SISPART1, 0x05, ((base >> 8) & 0xFF));
1323 SiS_SetReg(SISPART1, 0x04, ((base >> 16) & 0xFF));
1324 if(ivideo->sisvga_engine == SIS_315_VGA) {
1325 SiS_SetRegANDOR(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1331 sisfb_pan_var(struct sis_video_info *ivideo, struct fb_info *info,
1332 struct fb_var_screeninfo *var)
1334 ivideo->current_base = var->yoffset * info->var.xres_virtual
1337 /* calculate base bpp dep. */
1338 switch (info->var.bits_per_pixel) {
1342 ivideo->current_base >>= 1;
1346 ivideo->current_base >>= 2;
1350 ivideo->current_base += (ivideo->video_offset >> 2);
1352 sisfb_set_base_CRT1(ivideo, ivideo->current_base);
1353 sisfb_set_base_CRT2(ivideo, ivideo->current_base);
1359 sisfb_open(struct fb_info *info, int user)
1365 sisfb_release(struct fb_info *info, int user)
1371 sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
1372 unsigned transp, struct fb_info *info)
1374 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1376 if(regno >= sisfb_get_cmap_len(&info->var))
1379 switch(info->var.bits_per_pixel) {
1381 SiS_SetRegByte(SISDACA, regno);
1382 SiS_SetRegByte(SISDACD, (red >> 10));
1383 SiS_SetRegByte(SISDACD, (green >> 10));
1384 SiS_SetRegByte(SISDACD, (blue >> 10));
1385 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1386 SiS_SetRegByte(SISDAC2A, regno);
1387 SiS_SetRegByte(SISDAC2D, (red >> 8));
1388 SiS_SetRegByte(SISDAC2D, (green >> 8));
1389 SiS_SetRegByte(SISDAC2D, (blue >> 8));
1396 ((u32 *)(info->pseudo_palette))[regno] =
1398 ((green & 0xfc00) >> 5) |
1399 ((blue & 0xf800) >> 11);
1408 ((u32 *)(info->pseudo_palette))[regno] =
1409 (red << 16) | (green << 8) | (blue);
1416 sisfb_set_par(struct fb_info *info)
1420 if((err = sisfb_do_set_var(&info->var, 1, info)))
1423 sisfb_get_fix(&info->fix, -1, info);
1429 sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1431 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1432 unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
1433 unsigned int drate = 0, hrate = 0, maxyres;
1435 int refresh_rate, search_idx, tidx;
1436 bool recalc_clock = false;
1439 htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1441 vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1443 pixclock = var->pixclock;
1445 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1446 vtotal += var->yres;
1448 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1449 vtotal += var->yres;
1451 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1452 vtotal += var->yres;
1455 vtotal += var->yres;
1457 if(!(htotal) || !(vtotal)) {
1458 SISFAIL("sisfb: no valid timing data");
1462 while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
1463 (sisbios_mode[search_idx].xres <= var->xres) ) {
1464 if( (sisbios_mode[search_idx].xres == var->xres) &&
1465 (sisbios_mode[search_idx].yres == var->yres) &&
1466 (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1467 if((tidx = sisfb_validate_mode(ivideo, search_idx,
1468 ivideo->currentvbflags)) > 0) {
1479 while(sisbios_mode[search_idx].mode_no[0] != 0) {
1480 if( (var->xres <= sisbios_mode[search_idx].xres) &&
1481 (var->yres <= sisbios_mode[search_idx].yres) &&
1482 (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
1483 if((tidx = sisfb_validate_mode(ivideo,search_idx,
1484 ivideo->currentvbflags)) > 0) {
1494 "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
1495 var->xres, var->yres, var->bits_per_pixel,
1496 sisbios_mode[search_idx].xres,
1497 sisbios_mode[search_idx].yres,
1498 var->bits_per_pixel);
1499 var->xres = sisbios_mode[search_idx].xres;
1500 var->yres = sisbios_mode[search_idx].yres;
1503 "sisfb: Failed to find supported mode near %dx%dx%d\n",
1504 var->xres, var->yres, var->bits_per_pixel);
1509 if( ((ivideo->vbflags2 & VB2_LVDS) ||
1510 ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
1511 (var->bits_per_pixel == 8) ) {
1512 /* Slave modes on LVDS and 301B-DH */
1514 recalc_clock = true;
1515 } else if( (ivideo->current_htotal == htotal) &&
1516 (ivideo->current_vtotal == vtotal) &&
1517 (ivideo->current_pixclock == pixclock) ) {
1518 /* x=x & y=y & c=c -> assume depth change */
1519 drate = 1000000000 / pixclock;
1520 hrate = (drate * 1000) / htotal;
1521 refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1522 } else if( ( (ivideo->current_htotal != htotal) ||
1523 (ivideo->current_vtotal != vtotal) ) &&
1524 (ivideo->current_pixclock == var->pixclock) ) {
1525 /* x!=x | y!=y & c=c -> invalid pixclock */
1526 if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
1528 ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
1529 } else if(ivideo->sisfb_parm_rate != -1) {
1530 /* Sic, sisfb_parm_rate - want to know originally desired rate here */
1531 refresh_rate = ivideo->sisfb_parm_rate;
1535 recalc_clock = true;
1536 } else if((pixclock) && (htotal) && (vtotal)) {
1537 drate = 1000000000 / pixclock;
1538 hrate = (drate * 1000) / htotal;
1539 refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1540 } else if(ivideo->current_refresh_rate) {
1541 refresh_rate = ivideo->current_refresh_rate;
1542 recalc_clock = true;
1545 recalc_clock = true;
1548 myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
1550 /* Eventually recalculate timing and clock */
1552 if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
1553 var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
1554 sisbios_mode[search_idx].mode_no[ivideo->mni],
1556 sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr,
1557 sisbios_mode[search_idx].mode_no[ivideo->mni],
1559 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1560 var->pixclock <<= 1;
1564 if(ivideo->sisfb_thismonitor.datavalid) {
1565 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
1566 myrateindex, refresh_rate)) {
1568 "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1572 /* Adapt RGB settings */
1573 sisfb_bpp_to_var(ivideo, var);
1575 if(var->xres > var->xres_virtual)
1576 var->xres_virtual = var->xres;
1578 if(ivideo->sisfb_ypan) {
1579 maxyres = sisfb_calc_maxyres(ivideo, var);
1580 if(ivideo->sisfb_max) {
1581 var->yres_virtual = maxyres;
1583 if(var->yres_virtual > maxyres) {
1584 var->yres_virtual = maxyres;
1587 if(var->yres_virtual <= var->yres) {
1588 var->yres_virtual = var->yres;
1591 if(var->yres != var->yres_virtual) {
1592 var->yres_virtual = var->yres;
1598 /* Truncate offsets to maximum if too high */
1599 if(var->xoffset > var->xres_virtual - var->xres) {
1600 var->xoffset = var->xres_virtual - var->xres - 1;
1603 if(var->yoffset > var->yres_virtual - var->yres) {
1604 var->yoffset = var->yres_virtual - var->yres - 1;
1607 /* Set everything else to 0 */
1608 var->red.msb_right =
1609 var->green.msb_right =
1610 var->blue.msb_right =
1611 var->transp.offset =
1612 var->transp.length =
1613 var->transp.msb_right = 0;
1619 sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
1621 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1624 if (var->vmode & FB_VMODE_YWRAP)
1627 if (var->xoffset + info->var.xres > info->var.xres_virtual ||
1628 var->yoffset + info->var.yres > info->var.yres_virtual)
1631 err = sisfb_pan_var(ivideo, info, var);
1635 info->var.xoffset = var->xoffset;
1636 info->var.yoffset = var->yoffset;
1642 sisfb_blank(int blank, struct fb_info *info)
1644 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1646 return sisfb_myblank(ivideo, blank);
1649 /* ----------- FBDev related routines for all series ---------- */
1651 static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
1654 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1655 struct sis_memreq sismemreq;
1656 struct fb_vblank sisvbblank;
1661 u32 __user *argp = (u32 __user *)arg;
1665 if(!capable(CAP_SYS_RAWIO))
1668 if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))
1671 sis_malloc(&sismemreq);
1673 if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
1674 sis_free((u32)sismemreq.offset);
1680 if(!capable(CAP_SYS_RAWIO))
1683 if(get_user(gpu32, argp))
1689 case FBIOGET_VBLANK:
1691 memset(&sisvbblank, 0, sizeof(struct fb_vblank));
1693 sisvbblank.count = 0;
1694 sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
1696 if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))
1701 case SISFB_GET_INFO_SIZE:
1702 return put_user(sizeof(struct sisfb_info), argp);
1704 case SISFB_GET_INFO_OLD:
1705 if(ivideo->warncount++ < 10)
1707 "sisfb: Deprecated ioctl call received - update your application!\n");
1708 case SISFB_GET_INFO: /* For communication with X driver */
1709 ivideo->sisfb_infoblock.sisfb_id = SISFB_ID;
1710 ivideo->sisfb_infoblock.sisfb_version = VER_MAJOR;
1711 ivideo->sisfb_infoblock.sisfb_revision = VER_MINOR;
1712 ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;
1713 ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;
1714 ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;
1715 ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;
1716 ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;
1717 if(ivideo->modechanged) {
1718 ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;
1720 ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;
1722 ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;
1723 ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;
1724 ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;
1725 ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;
1726 ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;
1727 ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;
1728 ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;
1729 ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;
1730 ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;
1731 ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;
1732 ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
1733 ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
1734 ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
1735 ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
1736 ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
1737 ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
1738 ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
1739 ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
1740 ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
1741 ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
1742 ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;
1743 ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;
1744 ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;
1745 ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;
1746 ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;
1747 ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;
1748 ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;
1749 ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;
1751 if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,
1752 sizeof(ivideo->sisfb_infoblock)))
1757 case SISFB_GET_VBRSTATUS_OLD:
1758 if(ivideo->warncount++ < 10)
1760 "sisfb: Deprecated ioctl call received - update your application!\n");
1761 case SISFB_GET_VBRSTATUS:
1762 if(sisfb_CheckVBRetrace(ivideo))
1763 return put_user((u32)1, argp);
1765 return put_user((u32)0, argp);
1767 case SISFB_GET_AUTOMAXIMIZE_OLD:
1768 if(ivideo->warncount++ < 10)
1770 "sisfb: Deprecated ioctl call received - update your application!\n");
1771 case SISFB_GET_AUTOMAXIMIZE:
1772 if(ivideo->sisfb_max)
1773 return put_user((u32)1, argp);
1775 return put_user((u32)0, argp);
1777 case SISFB_SET_AUTOMAXIMIZE_OLD:
1778 if(ivideo->warncount++ < 10)
1780 "sisfb: Deprecated ioctl call received - update your application!\n");
1781 case SISFB_SET_AUTOMAXIMIZE:
1782 if(get_user(gpu32, argp))
1785 ivideo->sisfb_max = (gpu32) ? 1 : 0;
1788 case SISFB_SET_TVPOSOFFSET:
1789 if(get_user(gpu32, argp))
1792 sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
1793 sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
1796 case SISFB_GET_TVPOSOFFSET:
1797 return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
1801 if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,
1802 sizeof(struct sisfb_cmd)))
1805 sisfb_handle_command(ivideo, &ivideo->sisfb_command);
1807 if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,
1808 sizeof(struct sisfb_cmd)))
1813 case SISFB_SET_LOCK:
1814 if(get_user(gpu32, argp))
1817 ivideo->sisfblocked = (gpu32) ? 1 : 0;
1821 #ifdef SIS_NEW_CONFIG_COMPAT
1822 return -ENOIOCTLCMD;
1831 sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
1833 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1835 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1837 strlcpy(fix->id, ivideo->myid, sizeof(fix->id));
1839 mutex_lock(&info->mm_lock);
1840 fix->smem_start = ivideo->video_base + ivideo->video_offset;
1841 fix->smem_len = ivideo->sisfb_mem;
1842 mutex_unlock(&info->mm_lock);
1843 fix->type = FB_TYPE_PACKED_PIXELS;
1845 fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
1847 fix->ypanstep = (ivideo->sisfb_ypan) ? 1 : 0;
1849 fix->line_length = ivideo->video_linelength;
1850 fix->mmio_start = ivideo->mmio_base;
1851 fix->mmio_len = ivideo->mmio_size;
1852 if(ivideo->sisvga_engine == SIS_300_VGA) {
1853 fix->accel = FB_ACCEL_SIS_GLAMOUR;
1854 } else if((ivideo->chip == SIS_330) ||
1855 (ivideo->chip == SIS_760) ||
1856 (ivideo->chip == SIS_761)) {
1857 fix->accel = FB_ACCEL_SIS_XABRE;
1858 } else if(ivideo->chip == XGI_20) {
1859 fix->accel = FB_ACCEL_XGI_VOLARI_Z;
1860 } else if(ivideo->chip >= XGI_40) {
1861 fix->accel = FB_ACCEL_XGI_VOLARI_V;
1863 fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
1869 /* ---------------- fb_ops structures ----------------- */
1871 static struct fb_ops sisfb_ops = {
1872 .owner = THIS_MODULE,
1873 .fb_open = sisfb_open,
1874 .fb_release = sisfb_release,
1875 .fb_check_var = sisfb_check_var,
1876 .fb_set_par = sisfb_set_par,
1877 .fb_setcolreg = sisfb_setcolreg,
1878 .fb_pan_display = sisfb_pan_display,
1879 .fb_blank = sisfb_blank,
1880 .fb_fillrect = fbcon_sis_fillrect,
1881 .fb_copyarea = fbcon_sis_copyarea,
1882 .fb_imageblit = cfb_imageblit,
1883 .fb_sync = fbcon_sis_sync,
1884 #ifdef SIS_NEW_CONFIG_COMPAT
1885 .fb_compat_ioctl= sisfb_ioctl,
1887 .fb_ioctl = sisfb_ioctl
1890 /* ---------------- Chip generation dependent routines ---------------- */
1892 static struct pci_dev *sisfb_get_northbridge(int basechipid)
1894 struct pci_dev *pdev = NULL;
1895 int nbridgenum, nbridgeidx, i;
1896 static const unsigned short nbridgeids[] = {
1897 PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */
1898 PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */
1899 PCI_DEVICE_ID_SI_730,
1900 PCI_DEVICE_ID_SI_550, /* for SiS 550 VGA */
1901 PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */
1902 PCI_DEVICE_ID_SI_651,
1903 PCI_DEVICE_ID_SI_740,
1904 PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760/761 VGA */
1905 PCI_DEVICE_ID_SI_741,
1906 PCI_DEVICE_ID_SI_660,
1907 PCI_DEVICE_ID_SI_760,
1908 PCI_DEVICE_ID_SI_761
1911 switch(basechipid) {
1912 #ifdef CONFIG_FB_SIS_300
1913 case SIS_540: nbridgeidx = 0; nbridgenum = 1; break;
1914 case SIS_630: nbridgeidx = 1; nbridgenum = 2; break;
1916 #ifdef CONFIG_FB_SIS_315
1917 case SIS_550: nbridgeidx = 3; nbridgenum = 1; break;
1918 case SIS_650: nbridgeidx = 4; nbridgenum = 3; break;
1919 case SIS_660: nbridgeidx = 7; nbridgenum = 5; break;
1921 default: return NULL;
1923 for(i = 0; i < nbridgenum; i++) {
1924 if((pdev = pci_get_device(PCI_VENDOR_ID_SI,
1925 nbridgeids[nbridgeidx+i], NULL)))
1931 static int sisfb_get_dram_size(struct sis_video_info *ivideo)
1933 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1937 ivideo->video_size = 0;
1938 ivideo->UMAsize = ivideo->LFBsize = 0;
1940 switch(ivideo->chip) {
1941 #ifdef CONFIG_FB_SIS_300
1943 reg = SiS_GetReg(SISSR, 0x14);
1944 ivideo->video_size = ((reg & 0x3F) + 1) << 20;
1949 if(!ivideo->nbridge)
1951 pci_read_config_byte(ivideo->nbridge, 0x63, ®);
1952 ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
1955 #ifdef CONFIG_FB_SIS_315
1959 reg = SiS_GetReg(SISSR, 0x14);
1960 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
1961 switch((reg >> 2) & 0x03) {
1964 ivideo->video_size <<= 1;
1967 ivideo->video_size += (ivideo->video_size/2);
1971 reg = SiS_GetReg(SISSR, 0x14);
1972 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
1973 if(reg & 0x0c) ivideo->video_size <<= 1;
1978 reg = SiS_GetReg(SISSR, 0x14);
1979 ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
1983 reg = SiS_GetReg(SISCR, 0x79);
1984 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
1989 reg = SiS_GetReg(SISCR, 0x79);
1990 reg = (reg & 0xf0) >> 4;
1992 ivideo->video_size = (1 << reg) << 20;
1993 ivideo->UMAsize = ivideo->video_size;
1995 reg = SiS_GetReg(SISCR, 0x78);
1999 ivideo->LFBsize = (32 << 20);
2001 ivideo->LFBsize = (64 << 20);
2003 ivideo->video_size += ivideo->LFBsize;
2009 reg = SiS_GetReg(SISSR, 0x14);
2010 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2011 if(ivideo->chip != XGI_20) {
2012 reg = (reg & 0x0c) >> 2;
2013 if(ivideo->revision_id == 2) {
2014 if(reg & 0x01) reg = 0x02;
2017 if(reg == 0x02) ivideo->video_size <<= 1;
2018 else if(reg == 0x03) ivideo->video_size <<= 2;
2028 /* -------------- video bridge device detection --------------- */
2030 static void sisfb_detect_VB_connect(struct sis_video_info *ivideo)
2034 /* No CRT2 on XGI Z7 */
2035 if(ivideo->chip == XGI_20) {
2036 ivideo->sisfb_crt1off = 0;
2040 #ifdef CONFIG_FB_SIS_300
2041 if(ivideo->sisvga_engine == SIS_300_VGA) {
2042 temp = SiS_GetReg(SISSR, 0x17);
2043 if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
2044 /* PAL/NTSC is stored on SR16 on such machines */
2045 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
2046 temp = SiS_GetReg(SISSR, 0x16);
2048 ivideo->vbflags |= TV_PAL;
2050 ivideo->vbflags |= TV_NTSC;
2056 cr32 = SiS_GetReg(SISCR, 0x32);
2058 if(cr32 & SIS_CRT1) {
2059 ivideo->sisfb_crt1off = 0;
2061 ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0;
2064 ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
2066 if(cr32 & SIS_VB_TV) ivideo->vbflags |= CRT2_TV;
2067 if(cr32 & SIS_VB_LCD) ivideo->vbflags |= CRT2_LCD;
2068 if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA;
2070 /* Check given parms for hardware compatibility.
2071 * (Cannot do this in the search_xx routines since we don't
2072 * know what hardware we are running on then)
2075 if(ivideo->chip != SIS_550) {
2076 ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0;
2079 if(ivideo->sisfb_tvplug != -1) {
2080 if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2081 (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) {
2082 if(ivideo->sisfb_tvplug & TV_YPBPR) {
2083 ivideo->sisfb_tvplug = -1;
2084 printk(KERN_ERR "sisfb: YPbPr not supported\n");
2088 if(ivideo->sisfb_tvplug != -1) {
2089 if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2090 (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) {
2091 if(ivideo->sisfb_tvplug & TV_HIVISION) {
2092 ivideo->sisfb_tvplug = -1;
2093 printk(KERN_ERR "sisfb: HiVision not supported\n");
2097 if(ivideo->sisfb_tvstd != -1) {
2098 if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
2099 (!((ivideo->sisvga_engine == SIS_315_VGA) &&
2100 (ivideo->vbflags2 & VB2_CHRONTEL))) ) {
2101 if(ivideo->sisfb_tvstd & (TV_PALM | TV_PALN | TV_NTSCJ)) {
2102 ivideo->sisfb_tvstd = -1;
2103 printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
2108 /* Detect/set TV plug & type */
2109 if(ivideo->sisfb_tvplug != -1) {
2110 ivideo->vbflags |= ivideo->sisfb_tvplug;
2112 if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
2113 else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION;
2114 else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART;
2116 if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO;
2117 if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
2121 if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) {
2122 if(ivideo->sisfb_tvstd != -1) {
2123 ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ);
2124 ivideo->vbflags |= ivideo->sisfb_tvstd;
2126 if(ivideo->vbflags & TV_SCART) {
2127 ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ);
2128 ivideo->vbflags |= TV_PAL;
2130 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
2131 if(ivideo->sisvga_engine == SIS_300_VGA) {
2132 temp = SiS_GetReg(SISSR, 0x38);
2133 if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2134 else ivideo->vbflags |= TV_NTSC;
2135 } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
2136 temp = SiS_GetReg(SISSR, 0x38);
2137 if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2138 else ivideo->vbflags |= TV_NTSC;
2140 temp = SiS_GetReg(SISCR, 0x79);
2141 if(temp & 0x20) ivideo->vbflags |= TV_PAL;
2142 else ivideo->vbflags |= TV_NTSC;
2147 /* Copy forceCRT1 option to CRT1off if option is given */
2148 if(ivideo->sisfb_forcecrt1 != -1) {
2149 ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
2153 /* ------------------ Sensing routines ------------------ */
2155 static bool sisfb_test_DDC1(struct sis_video_info *ivideo)
2160 old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
2162 if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
2164 return (count != -1);
2167 static void sisfb_sense_crt1(struct sis_video_info *ivideo)
2169 bool mustwait = false;
2171 #ifdef CONFIG_FB_SIS_315
2177 sr1F = SiS_GetReg(SISSR, 0x1F);
2178 SiS_SetRegOR(SISSR, 0x1F, 0x04);
2179 SiS_SetRegAND(SISSR, 0x1F, 0x3F);
2180 if(sr1F & 0xc0) mustwait = true;
2182 #ifdef CONFIG_FB_SIS_315
2183 if(ivideo->sisvga_engine == SIS_315_VGA) {
2184 cr63 = SiS_GetReg(SISCR, ivideo->SiS_Pr.SiS_MyCR63);
2186 SiS_SetRegAND(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF);
2190 cr17 = SiS_GetReg(SISCR, 0x17);
2193 SiS_SetRegOR(SISCR, 0x17, 0x80);
2195 SiS_SetReg(SISSR, 0x00, 0x01);
2196 SiS_SetReg(SISSR, 0x00, 0x03);
2200 for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo);
2203 #ifdef CONFIG_FB_SIS_315
2204 if(ivideo->chip >= SIS_330) {
2205 SiS_SetRegAND(SISCR, 0x32, ~0x20);
2206 if(ivideo->chip >= SIS_340) {
2207 SiS_SetReg(SISCR, 0x57, 0x4a);
2209 SiS_SetReg(SISCR, 0x57, 0x5f);
2211 SiS_SetRegOR(SISCR, 0x53, 0x02);
2212 while ((SiS_GetRegByte(SISINPSTAT)) & 0x01) break;
2213 while (!((SiS_GetRegByte(SISINPSTAT)) & 0x01)) break;
2214 if ((SiS_GetRegByte(SISMISCW)) & 0x10) temp = 1;
2215 SiS_SetRegAND(SISCR, 0x53, 0xfd);
2216 SiS_SetRegAND(SISCR, 0x57, 0x00);
2220 if(temp == 0xffff) {
2223 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2224 ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
2225 } while(((temp == 0) || (temp == 0xffff)) && i--);
2227 if((temp == 0) || (temp == 0xffff)) {
2228 if(sisfb_test_DDC1(ivideo)) temp = 1;
2232 if((temp) && (temp != 0xffff)) {
2233 SiS_SetRegOR(SISCR, 0x32, 0x20);
2236 #ifdef CONFIG_FB_SIS_315
2237 if(ivideo->sisvga_engine == SIS_315_VGA) {
2238 SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF, cr63);
2242 SiS_SetRegANDOR(SISCR, 0x17, 0x7F, cr17);
2244 SiS_SetReg(SISSR, 0x1F, sr1F);
2247 /* Determine and detect attached devices on SiS30x */
2248 static void SiS_SenseLCD(struct sis_video_info *ivideo)
2250 unsigned char buffer[256];
2251 unsigned short temp, realcrtno, i;
2252 u8 reg, cr37 = 0, paneltype = 0;
2255 ivideo->SiS_Pr.PanelSelfDetected = false;
2257 /* LCD detection only for TMDS bridges */
2258 if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
2260 if(ivideo->vbflags2 & VB2_30xBDH)
2263 /* If LCD already set up by BIOS, skip it */
2264 reg = SiS_GetReg(SISCR, 0x32);
2269 if(ivideo->SiS_Pr.DDCPortMixup)
2272 /* Check DDC capabilities */
2273 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
2274 realcrtno, 0, &buffer[0], ivideo->vbflags2);
2276 if((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
2280 i = 3; /* Number of retrys */
2282 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2283 ivideo->sisvga_engine, realcrtno, 1,
2284 &buffer[0], ivideo->vbflags2);
2285 } while((temp) && i--);
2290 /* No digital device */
2291 if(!(buffer[0x14] & 0x80))
2294 /* First detailed timing preferred timing? */
2295 if(!(buffer[0x18] & 0x02))
2298 xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
2299 yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
2311 if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
2322 if((buffer[0x47] & 0x18) == 0x18)
2323 cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2327 SiS_SetReg(SISCR, 0x36, paneltype);
2329 SiS_SetRegANDOR(SISCR, 0x37, 0x0c, cr37);
2330 SiS_SetRegOR(SISCR, 0x32, 0x08);
2332 ivideo->SiS_Pr.PanelSelfDetected = true;
2335 static int SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
2337 int temp, mytest, result, i, j;
2339 for(j = 0; j < 10; j++) {
2341 for(i = 0; i < 3; i++) {
2343 SiS_SetReg(SISPART4, 0x11, (type & 0x00ff));
2344 temp = (type >> 8) | (mytest & 0x00ff);
2345 SiS_SetRegANDOR(SISPART4, 0x10, 0xe0, temp);
2346 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
2349 temp = SiS_GetReg(SISPART4, 0x03);
2352 if(temp == mytest) result++;
2354 SiS_SetReg(SISPART4, 0x11, 0x00);
2355 SiS_SetRegAND(SISPART4, 0x10, 0xe0);
2356 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
2359 if((result == 0) || (result >= 2)) break;
2364 static void SiS_Sense30x(struct sis_video_info *ivideo)
2366 u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
2367 u16 svhs=0, svhs_c=0;
2368 u16 cvbs=0, cvbs_c=0;
2369 u16 vga2=0, vga2_c=0;
2371 char stdstr[] = "sisfb: Detected";
2372 char tvstr[] = "TV connected to";
2374 if(ivideo->vbflags2 & VB2_301) {
2375 svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
2376 myflag = SiS_GetReg(SISPART4, 0x01);
2378 svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
2380 } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) {
2381 svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
2382 } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) {
2383 svhs = 0x0200; cvbs = 0x0100;
2384 } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
2385 svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
2389 vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
2390 if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
2391 svhs_c = 0x0408; cvbs_c = 0x0808;
2395 if(ivideo->haveXGIROM) {
2396 biosflag = ivideo->bios_abase[0x58] & 0x03;
2397 } else if(ivideo->newrom) {
2398 if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01;
2399 } else if(ivideo->sisvga_engine == SIS_300_VGA) {
2400 if(ivideo->bios_abase) {
2401 biosflag = ivideo->bios_abase[0xfe] & 0x03;
2405 if(ivideo->chip == SIS_300) {
2406 myflag = SiS_GetReg(SISSR, 0x3b);
2407 if(!(myflag & 0x01)) vga2 = vga2_c = 0;
2410 if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) {
2414 backupSR_1e = SiS_GetReg(SISSR, 0x1e);
2415 SiS_SetRegOR(SISSR, 0x1e, 0x20);
2417 backupP4_0d = SiS_GetReg(SISPART4, 0x0d);
2418 if(ivideo->vbflags2 & VB2_30xC) {
2419 SiS_SetRegANDOR(SISPART4, 0x0d, ~0x07, 0x01);
2421 SiS_SetRegOR(SISPART4, 0x0d, 0x04);
2423 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2425 backupP2_00 = SiS_GetReg(SISPART2, 0x00);
2426 SiS_SetReg(SISPART2, 0x00, ((backupP2_00 | 0x1c) & 0xfc));
2428 backupP2_4d = SiS_GetReg(SISPART2, 0x4d);
2429 if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
2430 SiS_SetReg(SISPART2, 0x4d, (backupP2_4d & ~0x10));
2433 if(!(ivideo->vbflags2 & VB2_30xCLV)) {
2434 SISDoSense(ivideo, 0, 0);
2437 SiS_SetRegAND(SISCR, 0x32, ~0x14);
2439 if(vga2_c || vga2) {
2440 if(SISDoSense(ivideo, vga2, vga2_c)) {
2441 if(biosflag & 0x01) {
2442 printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
2443 SiS_SetRegOR(SISCR, 0x32, 0x04);
2445 printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
2446 SiS_SetRegOR(SISCR, 0x32, 0x10);
2451 SiS_SetRegAND(SISCR, 0x32, 0x3f);
2453 if(ivideo->vbflags2 & VB2_30xCLV) {
2454 SiS_SetRegOR(SISPART4, 0x0d, 0x04);
2457 if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
2458 SiS_SetReg(SISPART2, 0x4d, (backupP2_4d | 0x10));
2459 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2460 if((result = SISDoSense(ivideo, svhs, 0x0604))) {
2461 if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
2462 printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
2463 SiS_SetRegOR(SISCR, 0x32, 0x80);
2466 SiS_SetReg(SISPART2, 0x4d, backupP2_4d);
2469 SiS_SetRegAND(SISCR, 0x32, ~0x03);
2471 if(!(ivideo->vbflags & TV_YPBPR)) {
2472 if((result = SISDoSense(ivideo, svhs, svhs_c))) {
2473 printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
2474 SiS_SetRegOR(SISCR, 0x32, 0x02);
2476 if((biosflag & 0x02) || (!result)) {
2477 if(SISDoSense(ivideo, cvbs, cvbs_c)) {
2478 printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
2479 SiS_SetRegOR(SISCR, 0x32, 0x01);
2484 SISDoSense(ivideo, 0, 0);
2486 SiS_SetReg(SISPART2, 0x00, backupP2_00);
2487 SiS_SetReg(SISPART4, 0x0d, backupP4_0d);
2488 SiS_SetReg(SISSR, 0x1e, backupSR_1e);
2490 if(ivideo->vbflags2 & VB2_30xCLV) {
2491 biosflag = SiS_GetReg(SISPART2, 0x00);
2492 if(biosflag & 0x20) {
2493 for(myflag = 2; myflag > 0; myflag--) {
2495 SiS_SetReg(SISPART2, 0x00, biosflag);
2500 SiS_SetReg(SISPART2, 0x00, backupP2_00);
2503 /* Determine and detect attached TV's on Chrontel */
2504 static void SiS_SenseCh(struct sis_video_info *ivideo)
2506 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2508 char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
2510 #ifdef CONFIG_FB_SIS_300
2511 unsigned char test[3];
2515 if(ivideo->chip < SIS_315H) {
2517 #ifdef CONFIG_FB_SIS_300
2518 ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1; /* Chrontel 700x */
2519 SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c); /* Set general purpose IO for Chrontel communication */
2520 SiS_DDC2Delay(&ivideo->SiS_Pr, 1000);
2521 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2522 /* See Chrontel TB31 for explanation */
2523 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2524 if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
2525 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b);
2526 SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2528 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2529 if(temp2 != temp1) temp1 = temp2;
2531 if((temp1 >= 0x22) && (temp1 <= 0x50)) {
2532 /* Read power status */
2533 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2534 if((temp1 & 0x03) != 0x03) {
2535 /* Power all outputs */
2536 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b);
2537 SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2539 /* Sense connected TV devices */
2540 for(i = 0; i < 3; i++) {
2541 SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01);
2542 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2543 SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00);
2544 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2545 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
2546 if(!(temp1 & 0x08)) test[i] = 0x02;
2547 else if(!(temp1 & 0x02)) test[i] = 0x01;
2549 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2552 if(test[0] == test[1]) temp1 = test[0];
2553 else if(test[0] == test[2]) temp1 = test[0];
2554 else if(test[1] == test[2]) temp1 = test[1];
2557 "sisfb: TV detection unreliable - test results varied\n");
2561 printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2562 ivideo->vbflags |= TV_SVIDEO;
2563 SiS_SetRegOR(SISCR, 0x32, 0x02);
2564 SiS_SetRegAND(SISCR, 0x32, ~0x05);
2565 } else if (temp1 == 0x01) {
2566 printk(KERN_INFO "%s CVBS output\n", stdstr);
2567 ivideo->vbflags |= TV_AVIDEO;
2568 SiS_SetRegOR(SISCR, 0x32, 0x01);
2569 SiS_SetRegAND(SISCR, 0x32, ~0x06);
2571 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2572 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2574 } else if(temp1 == 0) {
2575 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2576 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2578 /* Set general purpose IO for Chrontel communication */
2579 SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
2584 #ifdef CONFIG_FB_SIS_315
2585 ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */
2586 temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
2587 SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20);
2588 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2589 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2591 SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2592 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2594 SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2595 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2596 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2597 SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1);
2599 if(temp2 & 0x02) temp1 |= 0x01;
2600 if(temp2 & 0x10) temp1 |= 0x01;
2601 if(temp2 & 0x04) temp1 |= 0x02;
2602 if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
2605 printk(KERN_INFO "%s CVBS output\n", stdstr);
2606 ivideo->vbflags |= TV_AVIDEO;
2607 SiS_SetRegOR(SISCR, 0x32, 0x01);
2608 SiS_SetRegAND(SISCR, 0x32, ~0x06);
2611 printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2612 ivideo->vbflags |= TV_SVIDEO;
2613 SiS_SetRegOR(SISCR, 0x32, 0x02);
2614 SiS_SetRegAND(SISCR, 0x32, ~0x05);
2617 printk(KERN_INFO "%s SCART output\n", stdstr);
2618 SiS_SetRegOR(SISCR, 0x32, 0x04);
2619 SiS_SetRegAND(SISCR, 0x32, ~0x03);
2622 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2628 static void sisfb_get_VB_type(struct sis_video_info *ivideo)
2630 char stdstr[] = "sisfb: Detected";
2631 char bridgestr[] = "video bridge";
2635 /* No CRT2 on XGI Z7 */
2636 if(ivideo->chip == XGI_20)
2639 vb_chipid = SiS_GetReg(SISPART4, 0x00);
2642 reg = SiS_GetReg(SISPART4, 0x01);
2644 ivideo->vbflags |= VB_301; /* Deprecated */
2645 ivideo->vbflags2 |= VB2_301;
2646 printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
2647 } else if(reg < 0xc0) {
2648 ivideo->vbflags |= VB_301B; /* Deprecated */
2649 ivideo->vbflags2 |= VB2_301B;
2650 reg = SiS_GetReg(SISPART4, 0x23);
2652 ivideo->vbflags |= VB_30xBDH; /* Deprecated */
2653 ivideo->vbflags2 |= VB2_30xBDH;
2654 printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
2656 printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
2658 } else if(reg < 0xd0) {
2659 ivideo->vbflags |= VB_301C; /* Deprecated */
2660 ivideo->vbflags2 |= VB2_301C;
2661 printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
2662 } else if(reg < 0xe0) {
2663 ivideo->vbflags |= VB_301LV; /* Deprecated */
2664 ivideo->vbflags2 |= VB2_301LV;
2665 printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
2666 } else if(reg <= 0xe1) {
2667 reg = SiS_GetReg(SISPART4, 0x39);
2669 ivideo->vbflags |= VB_302LV; /* Deprecated */
2670 ivideo->vbflags2 |= VB2_302LV;
2671 printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
2673 ivideo->vbflags |= VB_301C; /* Deprecated */
2674 ivideo->vbflags2 |= VB2_301C;
2675 printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
2677 ivideo->vbflags |= VB_302ELV; /* Deprecated */
2678 ivideo->vbflags2 |= VB2_302ELV;
2679 printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
2685 ivideo->vbflags |= VB_302B; /* Deprecated */
2686 ivideo->vbflags2 |= VB2_302B;
2687 printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
2691 if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
2692 reg = SiS_GetReg(SISCR, 0x37);
2693 reg &= SIS_EXTERNAL_CHIP_MASK;
2695 if(ivideo->sisvga_engine == SIS_300_VGA) {
2696 #ifdef CONFIG_FB_SIS_300
2698 case SIS_EXTERNAL_CHIP_LVDS:
2699 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2700 ivideo->vbflags2 |= VB2_LVDS;
2702 case SIS_EXTERNAL_CHIP_TRUMPION:
2703 ivideo->vbflags |= (VB_LVDS | VB_TRUMPION); /* Deprecated */
2704 ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION);
2706 case SIS_EXTERNAL_CHIP_CHRONTEL:
2707 ivideo->vbflags |= VB_CHRONTEL; /* Deprecated */
2708 ivideo->vbflags2 |= VB2_CHRONTEL;
2710 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
2711 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2712 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2715 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1;
2717 } else if(ivideo->chip < SIS_661) {
2718 #ifdef CONFIG_FB_SIS_315
2720 case SIS310_EXTERNAL_CHIP_LVDS:
2721 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2722 ivideo->vbflags2 |= VB2_LVDS;
2724 case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
2725 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2726 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2729 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2731 } else if(ivideo->chip >= SIS_661) {
2732 #ifdef CONFIG_FB_SIS_315
2733 reg = SiS_GetReg(SISCR, 0x38);
2737 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2738 ivideo->vbflags2 |= VB2_LVDS;
2741 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2742 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2745 ivideo->vbflags |= (VB_LVDS | VB_CONEXANT); /* Deprecated */
2746 ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT);
2749 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2752 if(ivideo->vbflags2 & VB2_LVDS) {
2753 printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
2755 if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) {
2756 printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
2758 if(ivideo->vbflags2 & VB2_CHRONTEL) {
2759 printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
2761 if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) {
2762 printk(KERN_INFO "%s Conexant external device\n", stdstr);
2766 if(ivideo->vbflags2 & VB2_SISBRIDGE) {
2767 SiS_SenseLCD(ivideo);
2768 SiS_Sense30x(ivideo);
2769 } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
2770 SiS_SenseCh(ivideo);
2774 /* ---------- Engine initialization routines ------------ */
2777 sisfb_engine_init(struct sis_video_info *ivideo)
2780 /* Initialize command queue (we use MMIO only) */
2782 /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
2784 ivideo->caps &= ~(TURBO_QUEUE_CAP |
2785 MMIO_CMD_QUEUE_CAP |
2789 #ifdef CONFIG_FB_SIS_300
2790 if(ivideo->sisvga_engine == SIS_300_VGA) {
2794 tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
2796 tq_state = SiS_GetReg(SISSR, IND_SIS_TURBOQUEUE_SET);
2799 tq_state |= (u8)(tqueue_pos >> 8);
2800 SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
2802 SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
2804 ivideo->caps |= TURBO_QUEUE_CAP;
2808 #ifdef CONFIG_FB_SIS_315
2809 if(ivideo->sisvga_engine == SIS_315_VGA) {
2810 u32 tempq = 0, templ;
2813 if(ivideo->chip == XGI_20) {
2814 switch(ivideo->cmdQueueSize) {
2816 temp = SIS_CMD_QUEUE_SIZE_Z7_64k;
2820 temp = SIS_CMD_QUEUE_SIZE_Z7_128k;
2823 switch(ivideo->cmdQueueSize) {
2824 case (4 * 1024 * 1024):
2825 temp = SIS_CMD_QUEUE_SIZE_4M;
2827 case (2 * 1024 * 1024):
2828 temp = SIS_CMD_QUEUE_SIZE_2M;
2830 case (1 * 1024 * 1024):
2831 temp = SIS_CMD_QUEUE_SIZE_1M;
2835 temp = SIS_CMD_QUEUE_SIZE_512k;
2839 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2840 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2842 if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
2843 /* Must disable dual pipe on XGI_40. Can't do
2844 * this in MMIO mode, because it requires
2845 * setting/clearing a bit in the MMIO fire trigger
2848 if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) {
2850 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
2852 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
2854 tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
2855 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
2857 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2858 MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq);
2860 writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq);
2861 writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4);
2862 writel(0x168F0000, ivideo->video_vbase + tempq + 8);
2863 writel(0x168F0000, ivideo->video_vbase + tempq + 12);
2865 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16));
2867 sisfb_syncaccel(ivideo);
2869 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2874 tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
2875 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
2877 temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
2878 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, temp);
2880 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2881 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
2883 ivideo->caps |= MMIO_CMD_QUEUE_CAP;
2887 ivideo->engineok = 1;
2890 static void sisfb_detect_lcd_type(struct sis_video_info *ivideo)
2895 reg = SiS_GetReg(SISCR, 0x36);
2897 if(ivideo->sisvga_engine == SIS_300_VGA) {
2898 ivideo->CRT2LCDType = sis300paneltype[reg];
2899 } else if(ivideo->chip >= SIS_661) {
2900 ivideo->CRT2LCDType = sis661paneltype[reg];
2902 ivideo->CRT2LCDType = sis310paneltype[reg];
2903 if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
2904 if((ivideo->CRT2LCDType != LCD_320x240_2) &&
2905 (ivideo->CRT2LCDType != LCD_320x240_3)) {
2906 ivideo->CRT2LCDType = LCD_320x240;
2911 if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
2912 /* For broken BIOSes: Assume 1024x768, RGB18 */
2913 ivideo->CRT2LCDType = LCD_1024x768;
2914 SiS_SetRegANDOR(SISCR, 0x36, 0xf0, 0x02);
2915 SiS_SetRegANDOR(SISCR, 0x37, 0xee, 0x01);
2916 printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
2919 for(i = 0; i < SIS_LCD_NUMBER; i++) {
2920 if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
2921 ivideo->lcdxres = sis_lcd_data[i].xres;
2922 ivideo->lcdyres = sis_lcd_data[i].yres;
2923 ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
2928 #ifdef CONFIG_FB_SIS_300
2929 if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
2930 ivideo->lcdxres = 1360; ivideo->lcdyres = 1024;
2931 ivideo->lcddefmodeidx = DEFAULT_MODE_1360;
2932 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
2933 ivideo->lcdxres = 848; ivideo->lcdyres = 480;
2934 ivideo->lcddefmodeidx = DEFAULT_MODE_848;
2935 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) {
2936 ivideo->lcdxres = 856; ivideo->lcdyres = 480;
2937 ivideo->lcddefmodeidx = DEFAULT_MODE_856;
2941 printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
2942 ivideo->lcdxres, ivideo->lcdyres);
2945 static void sisfb_save_pdc_emi(struct sis_video_info *ivideo)
2947 #ifdef CONFIG_FB_SIS_300
2948 /* Save the current PanelDelayCompensation if the LCD is currently used */
2949 if(ivideo->sisvga_engine == SIS_300_VGA) {
2950 if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
2952 tmp = SiS_GetReg(SISCR, 0x30);
2954 /* Currently on LCD? If yes, read current pdc */
2955 ivideo->detectedpdc = SiS_GetReg(SISPART1, 0x13);
2956 ivideo->detectedpdc &= 0x3c;
2957 if(ivideo->SiS_Pr.PDC == -1) {
2958 /* Let option override detection */
2959 ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
2961 printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
2962 ivideo->detectedpdc);
2964 if((ivideo->SiS_Pr.PDC != -1) &&
2965 (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
2966 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
2967 ivideo->SiS_Pr.PDC);
2973 #ifdef CONFIG_FB_SIS_315
2974 if(ivideo->sisvga_engine == SIS_315_VGA) {
2976 /* Try to find about LCDA */
2977 if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
2979 tmp = SiS_GetReg(SISPART1, 0x13);
2981 ivideo->SiS_Pr.SiS_UseLCDA = true;
2982 ivideo->detectedlcda = 0x03;
2987 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
2989 tmp = SiS_GetReg(SISCR, 0x30);
2990 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
2991 /* Currently on LCD? If yes, read current pdc */
2993 pdc = SiS_GetReg(SISPART1, 0x2D);
2994 ivideo->detectedpdc = (pdc & 0x0f) << 1;
2995 ivideo->detectedpdca = (pdc & 0xf0) >> 3;
2996 pdc = SiS_GetReg(SISPART1, 0x35);
2997 ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
2998 pdc = SiS_GetReg(SISPART1, 0x20);
2999 ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
3000 if(ivideo->newrom) {
3001 /* New ROM invalidates other PDC resp. */
3002 if(ivideo->detectedlcda != 0xff) {
3003 ivideo->detectedpdc = 0xff;
3005 ivideo->detectedpdca = 0xff;
3008 if(ivideo->SiS_Pr.PDC == -1) {
3009 if(ivideo->detectedpdc != 0xff) {
3010 ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
3013 if(ivideo->SiS_Pr.PDCA == -1) {
3014 if(ivideo->detectedpdca != 0xff) {
3015 ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
3018 if(ivideo->detectedpdc != 0xff) {
3020 "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3021 ivideo->detectedpdc);
3023 if(ivideo->detectedpdca != 0xff) {
3025 "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3026 ivideo->detectedpdca);
3031 if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
3032 ivideo->SiS_Pr.EMI_30 = SiS_GetReg(SISPART4, 0x30);
3033 ivideo->SiS_Pr.EMI_31 = SiS_GetReg(SISPART4, 0x31);
3034 ivideo->SiS_Pr.EMI_32 = SiS_GetReg(SISPART4, 0x32);
3035 ivideo->SiS_Pr.EMI_33 = SiS_GetReg(SISPART4, 0x33);
3036 ivideo->SiS_Pr.HaveEMI = true;
3037 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3038 ivideo->SiS_Pr.HaveEMILCD = true;
3043 /* Let user override detected PDCs (all bridges) */
3044 if(ivideo->vbflags2 & VB2_30xBLV) {
3045 if((ivideo->SiS_Pr.PDC != -1) &&
3046 (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
3047 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3048 ivideo->SiS_Pr.PDC);
3050 if((ivideo->SiS_Pr.PDCA != -1) &&
3051 (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
3052 printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3053 ivideo->SiS_Pr.PDCA);
3061 /* -------------------- Memory manager routines ---------------------- */
3063 static u32 sisfb_getheapstart(struct sis_video_info *ivideo)
3065 u32 ret = ivideo->sisfb_parm_mem * 1024;
3066 u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3069 /* Calculate heap start = end of memory for console
3071 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3072 * C = console, D = heap, H = HWCursor, Q = cmd-queue
3074 * On 76x in UMA+LFB mode, the layout is as follows:
3075 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3076 * where the heap is the entire UMA area, eventually
3077 * into the LFB area if the given mem parameter is
3078 * higher than the size of the UMA memory.
3080 * Basically given by "mem" parameter
3082 * maximum = videosize - cmd_queue - hwcursor
3083 * (results in a heap of size 0)
3084 * default = SiS 300: depends on videosize
3085 * SiS 315/330/340/XGI: 32k below max
3088 if(ivideo->sisvga_engine == SIS_300_VGA) {
3089 if(ivideo->video_size > 0x1000000) {
3091 } else if(ivideo->video_size > 0x800000) {
3096 } else if(ivideo->UMAsize && ivideo->LFBsize) {
3099 def = maxoffs - 0x8000;
3102 /* Use default for secondary card for now (FIXME) */
3103 if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0))
3109 static u32 sisfb_getheapsize(struct sis_video_info *ivideo)
3111 u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3114 if(ivideo->UMAsize && ivideo->LFBsize) {
3115 if( (!ivideo->sisfb_parm_mem) ||
3116 ((ivideo->sisfb_parm_mem * 1024) > max) ||
3117 ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) {
3118 ret = ivideo->UMAsize;
3119 max -= ivideo->UMAsize;
3121 ret = max - (ivideo->sisfb_parm_mem * 1024);
3122 max = ivideo->sisfb_parm_mem * 1024;
3124 ivideo->video_offset = ret;
3125 ivideo->sisfb_mem = max;
3127 ret = max - ivideo->heapstart;
3128 ivideo->sisfb_mem = ivideo->heapstart;
3134 static int sisfb_heap_init(struct sis_video_info *ivideo)
3138 ivideo->video_offset = 0;
3139 if(ivideo->sisfb_parm_mem) {
3140 if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) ||
3141 (ivideo->sisfb_parm_mem > ivideo->video_size) ) {
3142 ivideo->sisfb_parm_mem = 0;
3146 ivideo->heapstart = sisfb_getheapstart(ivideo);
3147 ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo);
3149 ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
3150 ivideo->sisfb_heap_end = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size;
3152 printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
3153 (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
3155 ivideo->sisfb_heap.vinfo = ivideo;
3157 ivideo->sisfb_heap.poha_chain = NULL;
3158 ivideo->sisfb_heap.poh_freelist = NULL;
3160 poh = sisfb_poh_new_node(&ivideo->sisfb_heap);
3164 poh->poh_next = &ivideo->sisfb_heap.oh_free;
3165 poh->poh_prev = &ivideo->sisfb_heap.oh_free;
3166 poh->size = ivideo->sisfb_heap_size;
3167 poh->offset = ivideo->heapstart;
3169 ivideo->sisfb_heap.oh_free.poh_next = poh;
3170 ivideo->sisfb_heap.oh_free.poh_prev = poh;
3171 ivideo->sisfb_heap.oh_free.size = 0;
3172 ivideo->sisfb_heap.max_freesize = poh->size;
3174 ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used;
3175 ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used;
3176 ivideo->sisfb_heap.oh_used.size = SENTINEL;
3178 if(ivideo->cardnumber == 0) {
3179 /* For the first card, make this heap the "global" one
3180 * for old DRM (which could handle only one card)
3182 sisfb_heap = &ivideo->sisfb_heap;
3188 static struct SIS_OH *
3189 sisfb_poh_new_node(struct SIS_HEAP *memheap)
3191 struct SIS_OHALLOC *poha;
3196 if(memheap->poh_freelist == NULL) {
3197 poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
3201 poha->poha_next = memheap->poha_chain;
3202 memheap->poha_chain = poha;
3204 cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1;
3206 poh = &poha->aoh[0];
3207 for(i = cOhs - 1; i != 0; i--) {
3208 poh->poh_next = poh + 1;
3212 poh->poh_next = NULL;
3213 memheap->poh_freelist = &poha->aoh[0];
3216 poh = memheap->poh_freelist;
3217 memheap->poh_freelist = poh->poh_next;
3222 static struct SIS_OH *
3223 sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size)
3225 struct SIS_OH *pohThis;
3226 struct SIS_OH *pohRoot;
3229 if(size > memheap->max_freesize) {
3230 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3231 (unsigned int) size / 1024);
3235 pohThis = memheap->oh_free.poh_next;
3237 while(pohThis != &memheap->oh_free) {
3238 if(size <= pohThis->size) {
3242 pohThis = pohThis->poh_next;
3246 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3247 (unsigned int) size / 1024);
3251 if(size == pohThis->size) {
3253 sisfb_delete_node(pohThis);
3255 pohRoot = sisfb_poh_new_node(memheap);
3259 pohRoot->offset = pohThis->offset;
3260 pohRoot->size = size;
3262 pohThis->offset += size;
3263 pohThis->size -= size;
3266 memheap->max_freesize -= size;
3268 pohThis = &memheap->oh_used;
3269 sisfb_insert_node(pohThis, pohRoot);
3275 sisfb_delete_node(struct SIS_OH *poh)
3277 poh->poh_prev->poh_next = poh->poh_next;
3278 poh->poh_next->poh_prev = poh->poh_prev;
3282 sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh)
3284 struct SIS_OH *pohTemp = pohList->poh_next;
3286 pohList->poh_next = poh;
3287 pohTemp->poh_prev = poh;
3289 poh->poh_prev = pohList;
3290 poh->poh_next = pohTemp;
3293 static struct SIS_OH *
3294 sisfb_poh_free(struct SIS_HEAP *memheap, u32 base)
3296 struct SIS_OH *pohThis;
3297 struct SIS_OH *poh_freed;
3298 struct SIS_OH *poh_prev;
3299 struct SIS_OH *poh_next;
3304 poh_freed = memheap->oh_used.poh_next;
3306 while(poh_freed != &memheap->oh_used) {
3307 if(poh_freed->offset == base) {
3312 poh_freed = poh_freed->poh_next;
3318 memheap->max_freesize += poh_freed->size;
3320 poh_prev = poh_next = NULL;
3321 ulUpper = poh_freed->offset + poh_freed->size;
3322 ulLower = poh_freed->offset;
3324 pohThis = memheap->oh_free.poh_next;
3326 while(pohThis != &memheap->oh_free) {
3327 if(pohThis->offset == ulUpper) {
3329 } else if((pohThis->offset + pohThis->size) == ulLower) {
3332 pohThis = pohThis->poh_next;
3335 sisfb_delete_node(poh_freed);
3337 if(poh_prev && poh_next) {
3338 poh_prev->size += (poh_freed->size + poh_next->size);
3339 sisfb_delete_node(poh_next);
3340 sisfb_free_node(memheap, poh_freed);
3341 sisfb_free_node(memheap, poh_next);
3346 poh_prev->size += poh_freed->size;
3347 sisfb_free_node(memheap, poh_freed);
3352 poh_next->size += poh_freed->size;
3353 poh_next->offset = poh_freed->offset;
3354 sisfb_free_node(memheap, poh_freed);
3358 sisfb_insert_node(&memheap->oh_free, poh_freed);
3364 sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh)
3369 poh->poh_next = memheap->poh_freelist;
3370 memheap->poh_freelist = poh;
3374 sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req)
3376 struct SIS_OH *poh = NULL;
3378 if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap))
3379 poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size);
3382 req->offset = req->size = 0;
3383 DPRINTK("sisfb: Video RAM allocation failed\n");
3385 req->offset = poh->offset;
3386 req->size = poh->size;
3387 DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3388 (poh->offset + ivideo->video_vbase));
3393 sis_malloc(struct sis_memreq *req)
3395 struct sis_video_info *ivideo = sisfb_heap->vinfo;
3397 if(&ivideo->sisfb_heap == sisfb_heap)
3398 sis_int_malloc(ivideo, req);
3400 req->offset = req->size = 0;
3404 sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
3406 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3408 sis_int_malloc(ivideo, req);
3411 /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3414 sis_int_free(struct sis_video_info *ivideo, u32 base)
3418 if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap))
3421 poh = sisfb_poh_free(&ivideo->sisfb_heap, base);
3424 DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
3425 (unsigned int) base);
3432 struct sis_video_info *ivideo = sisfb_heap->vinfo;
3434 sis_int_free(ivideo, base);
3438 sis_free_new(struct pci_dev *pdev, u32 base)
3440 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3442 sis_int_free(ivideo, base);
3445 /* --------------------- SetMode routines ------------------------- */
3448 sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
3452 /* Check if MMIO and engines are enabled,
3453 * and sync in case they are. Can't use
3454 * ivideo->accel here, as this might have
3455 * been changed before this is called.
3457 cr30 = SiS_GetReg(SISSR, IND_SIS_PCI_ADDRESS_SET);
3458 cr31 = SiS_GetReg(SISSR, IND_SIS_MODULE_ENABLE);
3459 /* MMIO and 2D/3D engine enabled? */
3460 if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
3461 #ifdef CONFIG_FB_SIS_300
3462 if(ivideo->sisvga_engine == SIS_300_VGA) {
3463 /* Don't care about TurboQueue. It's
3464 * enough to know that the engines
3467 sisfb_syncaccel(ivideo);
3470 #ifdef CONFIG_FB_SIS_315
3471 if(ivideo->sisvga_engine == SIS_315_VGA) {
3472 /* Check that any queue mode is
3473 * enabled, and that the queue
3474 * is not in the state of "reset"
3476 cr30 = SiS_GetReg(SISSR, 0x26);
3477 if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
3478 sisfb_syncaccel(ivideo);
3486 sisfb_pre_setmode(struct sis_video_info *ivideo)
3488 u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
3491 ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
3493 SiS_SetReg(SISSR, 0x05, 0x86);
3495 cr31 = SiS_GetReg(SISCR, 0x31);
3499 cr33 = ivideo->rate_idx & 0x0F;
3501 #ifdef CONFIG_FB_SIS_315
3502 if(ivideo->sisvga_engine == SIS_315_VGA) {
3503 if(ivideo->chip >= SIS_661) {
3504 cr38 = SiS_GetReg(SISCR, 0x38);
3505 cr38 &= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
3508 cr38 = SiS_GetReg(SISCR, tvregnum);
3509 cr38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
3513 #ifdef CONFIG_FB_SIS_300
3514 if(ivideo->sisvga_engine == SIS_300_VGA) {
3516 cr38 = SiS_GetReg(SISCR, tvregnum);
3520 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
3521 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
3522 ivideo->curFSTN = ivideo->curDSTN = 0;
3524 switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
3527 cr38 &= ~0xc0; /* Clear PAL-M / PAL-N bits */
3528 if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
3529 #ifdef CONFIG_FB_SIS_315
3530 if(ivideo->chip >= SIS_661) {
3532 if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20;
3533 else if(ivideo->vbflags & TV_YPBPR750P) cr35 |= 0x40;
3534 else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
3535 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3537 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3538 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
3539 cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3541 if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10;
3542 else if(ivideo->vbflags & TV_YPBPR750P) cr38 |= 0x20;
3543 else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
3545 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3548 } else if((ivideo->vbflags & TV_HIVISION) &&
3549 (ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) {
3550 if(ivideo->chip >= SIS_661) {
3556 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3559 ivideo->currentvbflags |= TV_HIVISION;
3560 } else if(ivideo->vbflags & TV_SCART) {
3561 cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
3564 ivideo->currentvbflags |= TV_SCART;
3566 if(ivideo->vbflags & TV_SVIDEO) {
3567 cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
3568 ivideo->currentvbflags |= TV_SVIDEO;
3570 if(ivideo->vbflags & TV_AVIDEO) {
3571 cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
3572 ivideo->currentvbflags |= TV_AVIDEO;
3575 cr31 |= SIS_DRIVER_MODE;
3577 if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) {
3578 if(ivideo->vbflags & TV_PAL) {
3579 cr31 |= 0x01; cr35 |= 0x01;
3580 ivideo->currentvbflags |= TV_PAL;
3581 if(ivideo->vbflags & TV_PALM) {
3582 cr38 |= 0x40; cr35 |= 0x04;
3583 ivideo->currentvbflags |= TV_PALM;
3584 } else if(ivideo->vbflags & TV_PALN) {
3585 cr38 |= 0x80; cr35 |= 0x08;
3586 ivideo->currentvbflags |= TV_PALN;
3589 cr31 &= ~0x01; cr35 &= ~0x01;
3590 ivideo->currentvbflags |= TV_NTSC;
3591 if(ivideo->vbflags & TV_NTSCJ) {
3592 cr38 |= 0x40; cr35 |= 0x02;
3593 ivideo->currentvbflags |= TV_NTSCJ;
3600 cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
3601 cr31 |= SIS_DRIVER_MODE;
3602 SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
3603 SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
3604 ivideo->curFSTN = ivideo->sisfb_fstn;
3605 ivideo->curDSTN = ivideo->sisfb_dstn;
3609 cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3610 cr31 |= SIS_DRIVER_MODE;
3611 if(ivideo->sisfb_nocrt2rate) {
3612 cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4);
3614 cr33 |= ((ivideo->rate_idx & 0x0F) << 4);
3618 default: /* disable CRT2 */
3620 cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
3623 SiS_SetReg(SISCR, 0x30, cr30);
3624 SiS_SetReg(SISCR, 0x33, cr33);
3626 if(ivideo->chip >= SIS_661) {
3627 #ifdef CONFIG_FB_SIS_315
3628 cr31 &= ~0x01; /* Clear PAL flag (now in CR35) */
3629 SiS_SetRegANDOR(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
3630 cr38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
3631 SiS_SetRegANDOR(SISCR, 0x38, 0xf8, cr38);
3633 } else if(ivideo->chip != SIS_300) {
3634 SiS_SetReg(SISCR, tvregnum, cr38);
3636 SiS_SetReg(SISCR, 0x31, cr31);
3638 ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
3640 sisfb_check_engine_and_sync(ivideo);
3643 /* Fix SR11 for 661 and later */
3644 #ifdef CONFIG_FB_SIS_315
3646 sisfb_fixup_SR11(struct sis_video_info *ivideo)
3650 if(ivideo->chip >= SIS_661) {
3651 tmpreg = SiS_GetReg(SISSR, 0x11);
3653 tmpreg = SiS_GetReg(SISSR, 0x3e);
3654 tmpreg = (tmpreg + 1) & 0xff;
3655 SiS_SetReg(SISSR, 0x3e, tmpreg);
3656 tmpreg = SiS_GetReg(SISSR, 0x11);
3659 SiS_SetRegAND(SISSR, 0x11, 0x0f);
3666 sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
3668 if(val > 32) val = 32;
3669 if(val < -32) val = -32;
3670 ivideo->tvxpos = val;
3672 if(ivideo->sisfblocked) return;
3673 if(!ivideo->modechanged) return;
3675 if(ivideo->currentvbflags & CRT2_TV) {
3677 if(ivideo->vbflags2 & VB2_CHRONTEL) {
3679 int x = ivideo->tvx;
3681 switch(ivideo->chronteltype) {
3685 SiS_SetReg(SISSR, 0x05, 0x86);
3686 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
3687 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
3690 /* Not supported by hardware */
3694 } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3696 u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
3697 unsigned short temp;
3699 p2_1f = ivideo->p2_1f;
3700 p2_20 = ivideo->p2_20;
3701 p2_2b = ivideo->p2_2b;
3702 p2_42 = ivideo->p2_42;
3703 p2_43 = ivideo->p2_43;
3705 temp = p2_1f | ((p2_20 & 0xf0) << 4);
3707 p2_1f = temp & 0xff;
3708 p2_20 = (temp & 0xf00) >> 4;
3709 p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
3710 temp = p2_43 | ((p2_42 & 0xf0) << 4);
3712 p2_43 = temp & 0xff;
3713 p2_42 = (temp & 0xf00) >> 4;
3714 SiS_SetReg(SISPART2, 0x1f, p2_1f);
3715 SiS_SetRegANDOR(SISPART2, 0x20, 0x0F, p2_20);
3716 SiS_SetRegANDOR(SISPART2, 0x2b, 0xF0, p2_2b);
3717 SiS_SetRegANDOR(SISPART2, 0x42, 0x0F, p2_42);
3718 SiS_SetReg(SISPART2, 0x43, p2_43);
3724 sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
3726 if(val > 32) val = 32;
3727 if(val < -32) val = -32;
3728 ivideo->tvypos = val;
3730 if(ivideo->sisfblocked) return;
3731 if(!ivideo->modechanged) return;
3733 if(ivideo->currentvbflags & CRT2_TV) {
3735 if(ivideo->vbflags2 & VB2_CHRONTEL) {
3737 int y = ivideo->tvy;
3739 switch(ivideo->chronteltype) {
3743 SiS_SetReg(SISSR, 0x05, 0x86);
3744 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
3745 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
3748 /* Not supported by hardware */
3752 } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3756 p2_01 = ivideo->p2_01;
3757 p2_02 = ivideo->p2_02;
3761 if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) {
3762 while((p2_01 <= 0) || (p2_02 <= 0)) {
3767 SiS_SetReg(SISPART2, 0x01, p2_01);
3768 SiS_SetReg(SISPART2, 0x02, p2_02);
3774 sisfb_post_setmode(struct sis_video_info *ivideo)
3776 bool crt1isoff = false;
3778 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
3781 #ifdef CONFIG_FB_SIS_315
3785 SiS_SetReg(SISSR, 0x05, 0x86);
3787 #ifdef CONFIG_FB_SIS_315
3788 sisfb_fixup_SR11(ivideo);
3791 /* Now we actually HAVE changed the display mode */
3792 ivideo->modechanged = 1;
3794 /* We can't switch off CRT1 if bridge is in slave mode */
3795 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
3796 if(sisfb_bridgeisslave(ivideo)) doit = false;
3798 ivideo->sisfb_crt1off = 0;
3800 #ifdef CONFIG_FB_SIS_300
3801 if(ivideo->sisvga_engine == SIS_300_VGA) {
3802 if((ivideo->sisfb_crt1off) && (doit)) {
3809 SiS_SetRegANDOR(SISCR, 0x17, 0x7f, reg);
3812 #ifdef CONFIG_FB_SIS_315
3813 if(ivideo->sisvga_engine == SIS_315_VGA) {
3814 if((ivideo->sisfb_crt1off) && (doit)) {
3823 SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
3824 SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, reg1);
3829 ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
3830 ivideo->currentvbflags |= VB_SINGLE_MODE;
3832 ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
3833 if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
3834 ivideo->currentvbflags |= VB_MIRROR_MODE;
3836 ivideo->currentvbflags |= VB_SINGLE_MODE;
3840 SiS_SetRegAND(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
3842 if(ivideo->currentvbflags & CRT2_TV) {
3843 if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3844 ivideo->p2_1f = SiS_GetReg(SISPART2, 0x1f);
3845 ivideo->p2_20 = SiS_GetReg(SISPART2, 0x20);
3846 ivideo->p2_2b = SiS_GetReg(SISPART2, 0x2b);
3847 ivideo->p2_42 = SiS_GetReg(SISPART2, 0x42);
3848 ivideo->p2_43 = SiS_GetReg(SISPART2, 0x43);
3849 ivideo->p2_01 = SiS_GetReg(SISPART2, 0x01);
3850 ivideo->p2_02 = SiS_GetReg(SISPART2, 0x02);
3851 } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
3852 if(ivideo->chronteltype == 1) {
3853 ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
3854 ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
3855 ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
3856 ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
3861 if(ivideo->tvxpos) {
3862 sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
3864 if(ivideo->tvypos) {
3865 sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
3868 /* Eventually sync engines */
3869 sisfb_check_engine_and_sync(ivideo);
3871 /* (Re-)Initialize chip engines */
3873 sisfb_engine_init(ivideo);
3875 ivideo->engineok = 0;
3880 sisfb_reset_mode(struct sis_video_info *ivideo)
3882 if(sisfb_set_mode(ivideo, 0))
3885 sisfb_set_pitch(ivideo);
3886 sisfb_set_base_CRT1(ivideo, ivideo->current_base);
3887 sisfb_set_base_CRT2(ivideo, ivideo->current_base);
3893 sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command)
3897 switch(sisfb_command->sisfb_cmd) {
3898 case SISFB_CMD_GETVBFLAGS:
3899 if(!ivideo->modechanged) {
3900 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3902 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3903 sisfb_command->sisfb_result[1] = ivideo->currentvbflags;
3904 sisfb_command->sisfb_result[2] = ivideo->vbflags2;
3907 case SISFB_CMD_SWITCHCRT1:
3908 /* arg[0]: 0 = off, 1 = on, 99 = query */
3909 if(!ivideo->modechanged) {
3910 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3911 } else if(sisfb_command->sisfb_arg[0] == 99) {
3913 sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3914 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3915 } else if(ivideo->sisfblocked) {
3916 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED;
3917 } else if((!(ivideo->currentvbflags & CRT2_ENABLE)) &&
3918 (sisfb_command->sisfb_arg[0] == 0)) {
3919 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2;
3921 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3922 mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1;
3923 if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) ||
3924 ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) {
3925 ivideo->sisfb_crt1off = mycrt1off;
3926 if(sisfb_reset_mode(ivideo)) {
3927 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER;
3930 sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3935 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN;
3936 printk(KERN_ERR "sisfb: Unknown command 0x%x\n",
3937 sisfb_command->sisfb_cmd);
3942 static int __init sisfb_setup(char *options)
3946 sisfb_setdefaultparms();
3948 if(!options || !(*options))
3951 while((this_opt = strsep(&options, ",")) != NULL) {
3953 if(!(*this_opt)) continue;
3955 if(!strnicmp(this_opt, "off", 3)) {
3957 } else if(!strnicmp(this_opt, "forcecrt2type:", 14)) {
3958 /* Need to check crt2 type first for fstn/dstn */
3959 sisfb_search_crt2type(this_opt + 14);
3960 } else if(!strnicmp(this_opt, "tvmode:",7)) {
3961 sisfb_search_tvstd(this_opt + 7);
3962 } else if(!strnicmp(this_opt, "tvstandard:",11)) {
3963 sisfb_search_tvstd(this_opt + 11);
3964 } else if(!strnicmp(this_opt, "mode:", 5)) {
3965 sisfb_search_mode(this_opt + 5, false);
3966 } else if(!strnicmp(this_opt, "vesa:", 5)) {
3967 sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false);
3968 } else if(!strnicmp(this_opt, "rate:", 5)) {
3969 sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
3970 } else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
3971 sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
3972 } else if(!strnicmp(this_opt, "mem:",4)) {
3973 sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
3974 } else if(!strnicmp(this_opt, "pdc:", 4)) {
3975 sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
3976 } else if(!strnicmp(this_opt, "pdc1:", 5)) {
3977 sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
3978 } else if(!strnicmp(this_opt, "noaccel", 7)) {
3980 } else if(!strnicmp(this_opt, "accel", 5)) {
3982 } else if(!strnicmp(this_opt, "noypan", 6)) {
3984 } else if(!strnicmp(this_opt, "ypan", 4)) {
3986 } else if(!strnicmp(this_opt, "nomax", 5)) {
3988 } else if(!strnicmp(this_opt, "max", 3)) {
3990 } else if(!strnicmp(this_opt, "userom:", 7)) {
3991 sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
3992 } else if(!strnicmp(this_opt, "useoem:", 7)) {
3993 sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
3994 } else if(!strnicmp(this_opt, "nocrt2rate", 10)) {
3995 sisfb_nocrt2rate = 1;
3996 } else if(!strnicmp(this_opt, "scalelcd:", 9)) {
3997 unsigned long temp = 2;
3998 temp = simple_strtoul(this_opt + 9, NULL, 0);
3999 if((temp == 0) || (temp == 1)) {
4000 sisfb_scalelcd = temp ^ 1;
4002 } else if(!strnicmp(this_opt, "tvxposoffset:", 13)) {
4004 temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4005 if((temp >= -32) && (temp <= 32)) {
4006 sisfb_tvxposoffset = temp;
4008 } else if(!strnicmp(this_opt, "tvyposoffset:", 13)) {
4010 temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4011 if((temp >= -32) && (temp <= 32)) {
4012 sisfb_tvyposoffset = temp;
4014 } else if(!strnicmp(this_opt, "specialtiming:", 14)) {
4015 sisfb_search_specialtiming(this_opt + 14);
4016 } else if(!strnicmp(this_opt, "lvdshl:", 7)) {
4018 temp = simple_strtoul(this_opt + 7, NULL, 0);
4019 if((temp >= 0) && (temp <= 3)) {
4020 sisfb_lvdshl = temp;
4022 } else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
4023 sisfb_search_mode(this_opt, true);
4024 #if !defined(__i386__) && !defined(__x86_64__)
4025 } else if(!strnicmp(this_opt, "resetcard", 9)) {
4026 sisfb_resetcard = 1;
4027 } else if(!strnicmp(this_opt, "videoram:", 9)) {
4028 sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
4031 printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
4040 static int sisfb_check_rom(void __iomem *rom_base,
4041 struct sis_video_info *ivideo)
4046 if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
4049 romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
4050 if(romptr > (0x10000 - 8))
4053 rom = rom_base + romptr;
4055 if((readb(rom) != 'P') || (readb(rom + 1) != 'C') ||
4056 (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R'))
4059 if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor)
4062 if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id)
4068 static unsigned char *sisfb_find_rom(struct pci_dev *pdev)
4070 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4071 void __iomem *rom_base;
4072 unsigned char *myrombase = NULL;
4075 /* First, try the official pci ROM functions (except
4076 * on integrated chipsets which have no ROM).
4079 if(!ivideo->nbridge) {
4081 if((rom_base = pci_map_rom(pdev, &romsize))) {
4083 if(sisfb_check_rom(rom_base, ivideo)) {
4085 if((myrombase = vmalloc(65536))) {
4086 memcpy_fromio(myrombase, rom_base,
4087 (romsize > 65536) ? 65536 : romsize);
4090 pci_unmap_rom(pdev, rom_base);
4094 if(myrombase) return myrombase;
4096 /* Otherwise do it the conventional way. */
4098 #if defined(__i386__) || defined(__x86_64__)
4102 for (temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
4104 rom_base = ioremap(temp, 65536);
4108 if (!sisfb_check_rom(rom_base, ivideo)) {
4113 if ((myrombase = vmalloc(65536)))
4114 memcpy_fromio(myrombase, rom_base, 65536);
4127 static void sisfb_post_map_vram(struct sis_video_info *ivideo,
4128 unsigned int *mapsize, unsigned int min)
4130 if (*mapsize < (min << 20))
4133 ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize));
4135 if(!ivideo->video_vbase) {
4137 "sisfb: Unable to map maximum video RAM for size detection\n");
4139 while((!(ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize))))) {
4141 if((*mapsize) < (min << 20))
4144 if(ivideo->video_vbase) {
4146 "sisfb: Video RAM size detection limited to %dMB\n",
4147 (int)((*mapsize) >> 20));
4152 #ifdef CONFIG_FB_SIS_300
4153 static int sisfb_post_300_buswidth(struct sis_video_info *ivideo)
4155 void __iomem *FBAddress = ivideo->video_vbase;
4156 unsigned short temp;
4160 SiS_SetRegAND(SISSR, 0x15, 0xFB);
4161 SiS_SetRegOR(SISSR, 0x15, 0x04);
4162 SiS_SetReg(SISSR, 0x13, 0x00);
4163 SiS_SetReg(SISSR, 0x14, 0xBF);
4165 for(i = 0; i < 2; i++) {
4167 for(j = 0; j < 4; j++) {
4168 writew(temp, FBAddress);
4169 if(readw(FBAddress) == temp)
4171 SiS_SetRegOR(SISSR, 0x3c, 0x01);
4172 reg = SiS_GetReg(SISSR, 0x05);
4173 reg = SiS_GetReg(SISSR, 0x05);
4174 SiS_SetRegAND(SISSR, 0x3c, 0xfe);
4175 reg = SiS_GetReg(SISSR, 0x05);
4176 reg = SiS_GetReg(SISSR, 0x05);
4181 writel(0x01234567L, FBAddress);
4182 writel(0x456789ABL, (FBAddress + 4));
4183 writel(0x89ABCDEFL, (FBAddress + 8));
4184 writel(0xCDEF0123L, (FBAddress + 12));
4186 reg = SiS_GetReg(SISSR, 0x3b);
4188 if(readl((FBAddress + 12)) == 0xCDEF0123L)
4189 return 4; /* Channel A 128bit */
4192 if(readl((FBAddress + 4)) == 0x456789ABL)
4193 return 2; /* Channel B 64bit */
4195 return 1; /* 32bit */
4198 static const unsigned short SiS_DRAMType[17][5] = {
4199 {0x0C,0x0A,0x02,0x40,0x39},
4200 {0x0D,0x0A,0x01,0x40,0x48},
4201 {0x0C,0x09,0x02,0x20,0x35},
4202 {0x0D,0x09,0x01,0x20,0x44},
4203 {0x0C,0x08,0x02,0x10,0x31},
4204 {0x0D,0x08,0x01,0x10,0x40},
4205 {0x0C,0x0A,0x01,0x20,0x34},
4206 {0x0C,0x09,0x01,0x08,0x32},
4207 {0x0B,0x08,0x02,0x08,0x21},
4208 {0x0C,0x08,0x01,0x08,0x30},
4209 {0x0A,0x08,0x02,0x04,0x11},
4210 {0x0B,0x0A,0x01,0x10,0x28},
4211 {0x09,0x08,0x02,0x02,0x01},
4212 {0x0B,0x09,0x01,0x08,0x24},
4213 {0x0B,0x08,0x01,0x04,0x20},
4214 {0x0A,0x08,0x01,0x02,0x10},
4215 {0x09,0x08,0x01,0x01,0x00}
4218 static int sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration,
4219 int buswidth, int PseudoRankCapacity,
4220 int PseudoAdrPinCount, unsigned int mapsize)
4222 void __iomem *FBAddr = ivideo->video_vbase;
4223 unsigned short sr14;
4224 unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
4225 unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
4227 for(k = 0; k < ARRAY_SIZE(SiS_DRAMType); k++) {
4229 RankCapacity = buswidth * SiS_DRAMType[k][3];
4231 if(RankCapacity != PseudoRankCapacity)
4234 if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
4237 BankNumHigh = RankCapacity * 16 * iteration - 1;
4238 if(iteration == 3) { /* Rank No */
4239 BankNumMid = RankCapacity * 16 - 1;
4241 BankNumMid = RankCapacity * 16 * iteration / 2 - 1;
4244 PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
4245 PhysicalAdrHigh = BankNumHigh;
4246 PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
4247 PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
4249 SiS_SetRegAND(SISSR, 0x15, 0xFB); /* Test */
4250 SiS_SetRegOR(SISSR, 0x15, 0x04); /* Test */
4251 sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
4252 if(buswidth == 4) sr14 |= 0x80;
4253 else if(buswidth == 2) sr14 |= 0x40;
4254 SiS_SetReg(SISSR, 0x13, SiS_DRAMType[k][4]);
4255 SiS_SetReg(SISSR, 0x14, sr14);
4260 if((BankNumHigh + PhysicalAdrHigh >= mapsize) ||
4261 (BankNumMid + PhysicalAdrHigh >= mapsize) ||
4262 (BankNumHigh + PhysicalAdrHalfPage >= mapsize) ||
4263 (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
4267 writew(((unsigned short)PhysicalAdrHigh),
4268 (FBAddr + BankNumHigh + PhysicalAdrHigh));
4269 writew(((unsigned short)BankNumMid),
4270 (FBAddr + BankNumMid + PhysicalAdrHigh));
4271 writew(((unsigned short)PhysicalAdrHalfPage),
4272 (FBAddr + BankNumHigh + PhysicalAdrHalfPage));
4273 writew(((unsigned short)PhysicalAdrOtherPage),
4274 (FBAddr + BankNumHigh + PhysicalAdrOtherPage));
4277 if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
4284 static void sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
4286 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4288 int PseudoRankCapacity, PseudoAdrPinCount;
4290 buswidth = sisfb_post_300_buswidth(ivideo);
4292 for(i = 6; i >= 0; i--) {
4293 PseudoRankCapacity = 1 << i;
4294 for(j = 4; j >= 1; j--) {
4295 PseudoAdrPinCount = 15 - j;
4296 if((PseudoRankCapacity * j) <= 64) {
4297 if(sisfb_post_300_rwtest(ivideo,
4309 static void sisfb_post_sis300(struct pci_dev *pdev)
4311 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4312 unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
4313 u8 reg, v1, v2, v3, v4, v5, v6, v7, v8;
4314 u16 index, rindex, memtype = 0;
4315 unsigned int mapsize;
4317 if(!ivideo->SiS_Pr.UseROM)
4320 SiS_SetReg(SISSR, 0x05, 0x86);
4323 if(bios[0x52] & 0x80) {
4324 memtype = bios[0x52];
4326 memtype = SiS_GetReg(SISSR, 0x3a);
4331 v3 = 0x80; v6 = 0x80;
4332 if(ivideo->revision_id <= 0x13) {
4333 v1 = 0x44; v2 = 0x42;
4334 v4 = 0x44; v5 = 0x42;
4336 v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */
4337 v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */
4339 index = memtype * 5;
4340 rindex = index + 0x54;
4341 v1 = bios[rindex++];
4342 v2 = bios[rindex++];
4343 v3 = bios[rindex++];
4344 rindex = index + 0x7c;
4345 v4 = bios[rindex++];
4346 v5 = bios[rindex++];
4347 v6 = bios[rindex++];
4350 SiS_SetReg(SISSR, 0x28, v1);
4351 SiS_SetReg(SISSR, 0x29, v2);
4352 SiS_SetReg(SISSR, 0x2a, v3);
4353 SiS_SetReg(SISSR, 0x2e, v4);
4354 SiS_SetReg(SISSR, 0x2f, v5);
4355 SiS_SetReg(SISSR, 0x30, v6);
4360 SiS_SetReg(SISSR, 0x07, v1); /* DAC speed */
4362 SiS_SetReg(SISSR, 0x11, 0x0f); /* DDC, power save */
4364 v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
4365 v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
4369 v2 = bios[memtype + 8];
4370 v3 = bios[memtype + 16];
4371 v4 = bios[memtype + 24];
4372 v5 = bios[memtype + 32];
4373 v6 = bios[memtype + 40];
4374 v7 = bios[memtype + 48];
4375 v8 = bios[memtype + 56];
4377 if(ivideo->revision_id >= 0x80)
4379 SiS_SetReg(SISSR, 0x15, v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4380 SiS_SetReg(SISSR, 0x16, v2);
4381 SiS_SetReg(SISSR, 0x17, v3);
4382 SiS_SetReg(SISSR, 0x18, v4);
4383 SiS_SetReg(SISSR, 0x19, v5);
4384 SiS_SetReg(SISSR, 0x1a, v6);
4385 SiS_SetReg(SISSR, 0x1b, v7);
4386 SiS_SetReg(SISSR, 0x1c, v8); /* ---- */
4387 SiS_SetRegAND(SISSR, 0x15, 0xfb);
4388 SiS_SetRegOR(SISSR, 0x15, 0x04);
4390 if(bios[0x53] & 0x02) {
4391 SiS_SetRegOR(SISSR, 0x19, 0x20);
4394 v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */
4395 if(ivideo->revision_id >= 0x80)
4397 SiS_SetReg(SISSR, 0x1f, v1);
4398 SiS_SetReg(SISSR, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
4399 v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
4405 SiS_SetReg(SISSR, 0x23, v1);
4406 SiS_SetReg(SISSR, 0x24, v2);
4407 SiS_SetReg(SISSR, 0x25, v3);
4408 SiS_SetReg(SISSR, 0x21, 0x84);
4409 SiS_SetReg(SISSR, 0x22, 0x00);
4410 SiS_SetReg(SISCR, 0x37, 0x00);
4411 SiS_SetRegOR(SISPART1, 0x24, 0x01); /* unlock crt2 */
4412 SiS_SetReg(SISPART1, 0x00, 0x00);
4413 v1 = 0x40; v2 = 0x11;
4418 SiS_SetReg(SISPART1, 0x02, v1);
4420 if(ivideo->revision_id >= 0x80)
4423 reg = SiS_GetReg(SISPART4, 0x00);
4424 if((reg == 1) || (reg == 2)) {
4425 SiS_SetReg(SISCR, 0x37, 0x02);
4426 SiS_SetReg(SISPART2, 0x00, 0x1c);
4427 v4 = 0x00; v5 = 0x00; v6 = 0x10;
4428 if(ivideo->SiS_Pr.UseROM) {
4433 SiS_SetReg(SISPART4, 0x0d, v4);
4434 SiS_SetReg(SISPART4, 0x0e, v5);
4435 SiS_SetReg(SISPART4, 0x10, v6);
4436 SiS_SetReg(SISPART4, 0x0f, 0x3f);
4437 reg = SiS_GetReg(SISPART4, 0x01);
4439 reg = SiS_GetReg(SISPART4, 0x23);
4442 SiS_SetReg(SISPART4, 0x23, reg);
4447 SiS_SetReg(SISSR, 0x32, v2);
4449 SiS_SetRegAND(SISPART1, 0x24, 0xfe); /* Lock CRT2 */
4451 reg = SiS_GetReg(SISSR, 0x16);
4453 SiS_SetReg(SISCR, 0x35, reg);
4454 SiS_SetReg(SISCR, 0x83, 0x00);
4455 #if !defined(__i386__) && !defined(__x86_64__)
4456 if(sisfb_videoram) {
4457 SiS_SetReg(SISSR, 0x13, 0x28); /* ? */
4458 reg = ((sisfb_videoram >> 10) - 1) | 0x40;
4459 SiS_SetReg(SISSR, 0x14, reg);
4462 /* Need to map max FB size for finding out about RAM size */
4463 mapsize = ivideo->video_size;
4464 sisfb_post_map_vram(ivideo, &mapsize, 4);
4466 if(ivideo->video_vbase) {
4467 sisfb_post_300_ramsize(pdev, mapsize);
4468 iounmap(ivideo->video_vbase);
4471 "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4472 SiS_SetReg(SISSR, 0x13, 0x28); /* ? */
4473 SiS_SetReg(SISSR, 0x14, 0x47); /* 8MB, 64bit default */
4475 #if !defined(__i386__) && !defined(__x86_64__)
4482 reg = SiS_GetReg(SISSR, 0x3a);
4483 if((reg & 0x30) == 0x30) {
4484 v1 = 0x04; /* PCI */
4487 v1 = 0x14; /* AGP */
4491 SiS_SetReg(SISSR, 0x21, v1);
4492 SiS_SetReg(SISSR, 0x22, v2);
4495 sisfb_sense_crt1(ivideo);
4497 /* Set default mode, don't clear screen */
4498 ivideo->SiS_Pr.SiS_UseOEM = false;
4499 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
4500 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
4501 ivideo->curFSTN = ivideo->curDSTN = 0;
4502 ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
4503 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
4505 SiS_SetReg(SISSR, 0x05, 0x86);
4508 SiS_SetRegOR(SISSR, 0x01, 0x20);
4510 /* Save mode number in CR34 */
4511 SiS_SetReg(SISCR, 0x34, 0x2e);
4513 /* Let everyone know what the current mode is */
4514 ivideo->modeprechange = 0x2e;
4518 #ifdef CONFIG_FB_SIS_315
4520 static void sisfb_post_sis315330(struct pci_dev *pdev)
4526 static inline int sisfb_xgi_is21(struct sis_video_info *ivideo)
4528 return ivideo->chip_real_id == XGI_21;
4531 static void sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
4536 for(i = 0; i <= (delay * 10 * 36); i++) {
4537 reg = SiS_GetReg(SISSR, 0x05);
4542 static int sisfb_find_host_bridge(struct sis_video_info *ivideo,
4543 struct pci_dev *mypdev,
4544 unsigned short pcivendor)
4546 struct pci_dev *pdev = NULL;
4547 unsigned short temp;
4550 while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) {
4551 temp = pdev->vendor;
4552 if(temp == pcivendor) {
4562 static int sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
4563 unsigned int enda, unsigned int mapsize)
4568 writel(0, ivideo->video_vbase);
4570 for(i = starta; i <= enda; i++) {
4573 writel(pos, ivideo->video_vbase + pos);
4576 sisfb_post_xgi_delay(ivideo, 150);
4578 if(readl(ivideo->video_vbase) != 0)
4581 for(i = starta; i <= enda; i++) {
4584 if(readl(ivideo->video_vbase + pos) != pos)
4593 static int sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
4595 unsigned int buswidth, ranksize, channelab, mapsize;
4596 int i, j, k, l, status;
4598 static const u8 dramsr13[12 * 5] = {
4599 0x02, 0x0e, 0x0b, 0x80, 0x5d,
4600 0x02, 0x0e, 0x0a, 0x40, 0x59,
4601 0x02, 0x0d, 0x0b, 0x40, 0x4d,
4602 0x02, 0x0e, 0x09, 0x20, 0x55,
4603 0x02, 0x0d, 0x0a, 0x20, 0x49,
4604 0x02, 0x0c, 0x0b, 0x20, 0x3d,
4605 0x02, 0x0e, 0x08, 0x10, 0x51,
4606 0x02, 0x0d, 0x09, 0x10, 0x45,
4607 0x02, 0x0c, 0x0a, 0x10, 0x39,
4608 0x02, 0x0d, 0x08, 0x08, 0x41,
4609 0x02, 0x0c, 0x09, 0x08, 0x35,
4610 0x02, 0x0c, 0x08, 0x04, 0x31
4612 static const u8 dramsr13_4[4 * 5] = {
4613 0x02, 0x0d, 0x09, 0x40, 0x45,
4614 0x02, 0x0c, 0x09, 0x20, 0x35,
4615 0x02, 0x0c, 0x08, 0x10, 0x31,
4616 0x02, 0x0b, 0x08, 0x08, 0x21
4619 /* Enable linear mode, disable 0xa0000 address decoding */
4620 /* We disable a0000 address decoding, because
4621 * - if running on x86, if the card is disabled, it means
4622 * that another card is in the system. We don't want
4623 * to interphere with that primary card's textmode.
4624 * - if running on non-x86, there usually is no VGA window
4627 SiS_SetRegOR(SISSR, 0x20, (0x80 | 0x04));
4629 /* Need to map max FB size for finding out about RAM size */
4630 mapsize = ivideo->video_size;
4631 sisfb_post_map_vram(ivideo, &mapsize, 32);
4633 if(!ivideo->video_vbase) {
4634 printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
4635 SiS_SetReg(SISSR, 0x13, 0x35);
4636 SiS_SetReg(SISSR, 0x14, 0x41);
4641 /* Non-interleaving */
4642 SiS_SetReg(SISSR, 0x15, 0x00);
4644 SiS_SetReg(SISSR, 0x1c, 0x00);
4646 if(ivideo->chip == XGI_20) {
4649 reg = SiS_GetReg(SISCR, 0x97);
4650 if(!(reg & 0x01)) { /* Single 32/16 */
4652 SiS_SetReg(SISSR, 0x13, 0xb1);
4653 SiS_SetReg(SISSR, 0x14, 0x52);
4654 sisfb_post_xgi_delay(ivideo, 1);
4656 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4659 SiS_SetReg(SISSR, 0x13, 0x31);
4660 SiS_SetReg(SISSR, 0x14, 0x42);
4661 sisfb_post_xgi_delay(ivideo, 1);
4662 if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
4666 SiS_SetReg(SISSR, 0x13, 0xb1);
4667 SiS_SetReg(SISSR, 0x14, 0x41);
4668 sisfb_post_xgi_delay(ivideo, 1);
4670 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4673 SiS_SetReg(SISSR, 0x13, 0x31);
4674 } else { /* Dual 16/8 */
4676 SiS_SetReg(SISSR, 0x13, 0xb1);
4677 SiS_SetReg(SISSR, 0x14, 0x41);
4678 sisfb_post_xgi_delay(ivideo, 1);
4680 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4683 SiS_SetReg(SISSR, 0x13, 0x31);
4684 SiS_SetReg(SISSR, 0x14, 0x31);
4685 sisfb_post_xgi_delay(ivideo, 1);
4686 if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
4690 SiS_SetReg(SISSR, 0x13, 0xb1);
4691 SiS_SetReg(SISSR, 0x14, 0x30);
4692 sisfb_post_xgi_delay(ivideo, 1);
4694 if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
4697 SiS_SetReg(SISSR, 0x13, 0x31);
4700 } else { /* XGI_40 */
4702 reg = SiS_GetReg(SISCR, 0x97);
4704 reg = SiS_GetReg(SISSR, 0x39);
4708 if(reg & 0x01) { /* DDRII */
4710 if(ivideo->revision_id == 2) {
4712 SiS_SetReg(SISSR, 0x13, 0xa1);
4713 SiS_SetReg(SISSR, 0x14, 0x44);
4715 sisfb_post_xgi_delay(ivideo, 1);
4716 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4719 SiS_SetReg(SISSR, 0x13, 0x21);
4720 SiS_SetReg(SISSR, 0x14, 0x34);
4721 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4725 SiS_SetReg(SISSR, 0x13, 0xa1);
4726 SiS_SetReg(SISSR, 0x14, 0x40);
4728 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4731 SiS_SetReg(SISSR, 0x13, 0x21);
4732 SiS_SetReg(SISSR, 0x14, 0x30);
4735 SiS_SetReg(SISSR, 0x13, 0xa1);
4736 SiS_SetReg(SISSR, 0x14, 0x4c);
4738 sisfb_post_xgi_delay(ivideo, 1);
4739 if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
4743 SiS_SetReg(SISSR, 0x14, 0x48);
4744 sisfb_post_xgi_delay(ivideo, 1);
4746 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4749 SiS_SetReg(SISSR, 0x13, 0x21);
4750 SiS_SetReg(SISSR, 0x14, 0x3c);
4753 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
4757 SiS_SetReg(SISSR, 0x14, 0x38);
4761 sisfb_post_xgi_delay(ivideo, 1);
4766 if(ivideo->revision_id == 2) {
4768 SiS_SetReg(SISSR, 0x13, 0xa1);
4769 SiS_SetReg(SISSR, 0x14, 0x52);
4770 sisfb_post_xgi_delay(ivideo, 1);
4772 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4775 SiS_SetReg(SISSR, 0x13, 0x21);
4776 SiS_SetReg(SISSR, 0x14, 0x42);
4779 SiS_SetReg(SISSR, 0x13, 0xa1);
4780 SiS_SetReg(SISSR, 0x14, 0x5a);
4781 sisfb_post_xgi_delay(ivideo, 1);
4783 if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
4786 SiS_SetReg(SISSR, 0x13, 0x21);
4787 SiS_SetReg(SISSR, 0x14, 0x4a);
4789 sisfb_post_xgi_delay(ivideo, 1);
4795 SiS_SetRegANDOR(SISSR, 0x14, 0xf0, sr14);
4796 sisfb_post_xgi_delay(ivideo, 1);
4798 j = (ivideo->chip == XGI_20) ? 5 : 9;
4799 k = (ivideo->chip == XGI_20) ? 12 : 4;
4802 for(i = 0; i < k; i++) {
4804 reg = (ivideo->chip == XGI_20) ?
4805 dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
4806 SiS_SetRegANDOR(SISSR, 0x13, 0x80, reg);
4807 sisfb_post_xgi_delay(ivideo, 50);
4809 ranksize = (ivideo->chip == XGI_20) ?
4810 dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
4812 reg = SiS_GetReg(SISSR, 0x13);
4813 if(reg & 0x80) ranksize <<= 1;
4815 if(ivideo->chip == XGI_20) {
4816 if(buswidth == 16) ranksize <<= 1;
4817 else if(buswidth == 32) ranksize <<= 2;
4819 if(buswidth == 64) ranksize <<= 1;
4825 if((ranksize * l) <= 256) {
4826 while((ranksize >>= 1)) reg += 0x10;
4831 SiS_SetRegANDOR(SISSR, 0x14, 0x0f, (reg & 0xf0));
4832 sisfb_post_xgi_delay(ivideo, 1);
4834 if (sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize)) {
4840 iounmap(ivideo->video_vbase);
4845 static void sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
4849 static const u8 cs90[8 * 3] = {
4859 static const u8 csb8[8 * 3] = {
4873 v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2];
4874 if(ivideo->haveXGIROM) {
4875 v1 = ivideo->bios_abase[0x90 + index];
4876 v2 = ivideo->bios_abase[0x90 + index + 1];
4877 v3 = ivideo->bios_abase[0x90 + index + 2];
4879 SiS_SetReg(SISSR, 0x28, v1);
4880 SiS_SetReg(SISSR, 0x29, v2);
4881 SiS_SetReg(SISSR, 0x2a, v3);
4882 sisfb_post_xgi_delay(ivideo, 0x43);
4883 sisfb_post_xgi_delay(ivideo, 0x43);
4884 sisfb_post_xgi_delay(ivideo, 0x43);
4886 v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2];
4887 if(ivideo->haveXGIROM) {
4888 v1 = ivideo->bios_abase[0xb8 + index];
4889 v2 = ivideo->bios_abase[0xb8 + index + 1];
4890 v3 = ivideo->bios_abase[0xb8 + index + 2];
4892 SiS_SetReg(SISSR, 0x2e, v1);
4893 SiS_SetReg(SISSR, 0x2f, v2);
4894 SiS_SetReg(SISSR, 0x30, v3);
4895 sisfb_post_xgi_delay(ivideo, 0x43);
4896 sisfb_post_xgi_delay(ivideo, 0x43);
4897 sisfb_post_xgi_delay(ivideo, 0x43);
4900 static void sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info *ivideo,
4903 unsigned char *bios = ivideo->bios_abase;
4906 SiS_SetReg(SISSR, 0x28, 0x64);
4907 SiS_SetReg(SISSR, 0x29, 0x63);
4908 sisfb_post_xgi_delay(ivideo, 15);
4909 SiS_SetReg(SISSR, 0x18, 0x00);
4910 SiS_SetReg(SISSR, 0x19, 0x20);
4911 SiS_SetReg(SISSR, 0x16, 0x00);
4912 SiS_SetReg(SISSR, 0x16, 0x80);
4913 SiS_SetReg(SISSR, 0x18, 0xc5);
4914 SiS_SetReg(SISSR, 0x19, 0x23);
4915 SiS_SetReg(SISSR, 0x16, 0x00);
4916 SiS_SetReg(SISSR, 0x16, 0x80);
4917 sisfb_post_xgi_delay(ivideo, 1);
4918 SiS_SetReg(SISCR, 0x97, 0x11);
4919 sisfb_post_xgi_setclocks(ivideo, regb);
4920 sisfb_post_xgi_delay(ivideo, 0x46);
4921 SiS_SetReg(SISSR, 0x18, 0xc5);
4922 SiS_SetReg(SISSR, 0x19, 0x23);
4923 SiS_SetReg(SISSR, 0x16, 0x00);
4924 SiS_SetReg(SISSR, 0x16, 0x80);
4925 sisfb_post_xgi_delay(ivideo, 1);
4926 SiS_SetReg(SISSR, 0x1b, 0x04);
4927 sisfb_post_xgi_delay(ivideo, 1);
4928 SiS_SetReg(SISSR, 0x1b, 0x00);
4929 sisfb_post_xgi_delay(ivideo, 1);
4931 if (ivideo->haveXGIROM) {
4934 SiS_SetReg(SISSR, 0x18, v1);
4935 SiS_SetReg(SISSR, 0x19, 0x06);
4936 SiS_SetReg(SISSR, 0x16, 0x04);
4937 SiS_SetReg(SISSR, 0x16, 0x84);
4938 sisfb_post_xgi_delay(ivideo, 1);
4941 static void sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info *ivideo)
4943 sisfb_post_xgi_setclocks(ivideo, 1);
4945 SiS_SetReg(SISCR, 0x97, 0x11);
4946 sisfb_post_xgi_delay(ivideo, 0x46);
4948 SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS2 */
4949 SiS_SetReg(SISSR, 0x19, 0x80);
4950 SiS_SetReg(SISSR, 0x16, 0x05);
4951 SiS_SetReg(SISSR, 0x16, 0x85);
4953 SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS3 */
4954 SiS_SetReg(SISSR, 0x19, 0xc0);
4955 SiS_SetReg(SISSR, 0x16, 0x05);
4956 SiS_SetReg(SISSR, 0x16, 0x85);
4958 SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS1 */
4959 SiS_SetReg(SISSR, 0x19, 0x40);
4960 SiS_SetReg(SISSR, 0x16, 0x05);
4961 SiS_SetReg(SISSR, 0x16, 0x85);
4963 SiS_SetReg(SISSR, 0x18, 0x42); /* MRS1 */
4964 SiS_SetReg(SISSR, 0x19, 0x02);
4965 SiS_SetReg(SISSR, 0x16, 0x05);
4966 SiS_SetReg(SISSR, 0x16, 0x85);
4967 sisfb_post_xgi_delay(ivideo, 1);
4969 SiS_SetReg(SISSR, 0x1b, 0x04);
4970 sisfb_post_xgi_delay(ivideo, 1);
4972 SiS_SetReg(SISSR, 0x1b, 0x00);
4973 sisfb_post_xgi_delay(ivideo, 1);
4975 SiS_SetReg(SISSR, 0x18, 0x42); /* MRS1 */
4976 SiS_SetReg(SISSR, 0x19, 0x00);
4977 SiS_SetReg(SISSR, 0x16, 0x05);
4978 SiS_SetReg(SISSR, 0x16, 0x85);
4979 sisfb_post_xgi_delay(ivideo, 1);
4982 static void sisfb_post_xgi_ddr2(struct sis_video_info *ivideo, u8 regb)
4984 unsigned char *bios = ivideo->bios_abase;
4985 static const u8 cs158[8] = {
4986 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
4988 static const u8 cs160[8] = {
4989 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
4991 static const u8 cs168[8] = {
4992 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
4999 SiS_SetReg(SISCR, 0xb0, 0x80); /* DDR2 dual frequency mode */
5000 SiS_SetReg(SISCR, 0x82, 0x77);
5001 SiS_SetReg(SISCR, 0x86, 0x00);
5002 reg = SiS_GetReg(SISCR, 0x86);
5003 SiS_SetReg(SISCR, 0x86, 0x88);
5004 reg = SiS_GetReg(SISCR, 0x86);
5005 v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
5006 if (ivideo->haveXGIROM) {
5007 v1 = bios[regb + 0x168];
5008 v2 = bios[regb + 0x160];
5009 v3 = bios[regb + 0x158];
5011 SiS_SetReg(SISCR, 0x86, v1);
5012 SiS_SetReg(SISCR, 0x82, 0x77);
5013 SiS_SetReg(SISCR, 0x85, 0x00);
5014 reg = SiS_GetReg(SISCR, 0x85);
5015 SiS_SetReg(SISCR, 0x85, 0x88);
5016 reg = SiS_GetReg(SISCR, 0x85);
5017 SiS_SetReg(SISCR, 0x85, v2);
5018 SiS_SetReg(SISCR, 0x82, v3);
5019 SiS_SetReg(SISCR, 0x98, 0x01);
5020 SiS_SetReg(SISCR, 0x9a, 0x02);
5021 if (sisfb_xgi_is21(ivideo))
5022 sisfb_post_xgi_ddr2_mrs_xg21(ivideo);
5024 sisfb_post_xgi_ddr2_mrs_default(ivideo, regb);
5027 static u8 sisfb_post_xgi_ramtype(struct sis_video_info *ivideo)
5029 unsigned char *bios = ivideo->bios_abase;
5034 ramtype = 0x00; v1 = 0x10;
5035 if (ivideo->haveXGIROM) {
5036 ramtype = bios[0x62];
5039 if (!(ramtype & 0x80)) {
5040 if (sisfb_xgi_is21(ivideo)) {
5041 SiS_SetRegAND(SISCR, 0xb4, 0xfd); /* GPIO control */
5042 SiS_SetRegOR(SISCR, 0x4a, 0x80); /* GPIOH EN */
5043 reg = SiS_GetReg(SISCR, 0x48);
5044 SiS_SetRegOR(SISCR, 0xb4, 0x02);
5045 ramtype = reg & 0x01; /* GPIOH */
5046 } else if (ivideo->chip == XGI_20) {
5047 SiS_SetReg(SISCR, 0x97, v1);
5048 reg = SiS_GetReg(SISCR, 0x97);
5050 ramtype = (reg & 0x01) << 1;
5053 reg = SiS_GetReg(SISSR, 0x39);
5054 ramtype = reg & 0x02;
5056 reg = SiS_GetReg(SISSR, 0x3a);
5057 ramtype = (reg >> 1) & 0x01;
5066 static int sisfb_post_xgi(struct pci_dev *pdev)
5068 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
5069 unsigned char *bios = ivideo->bios_abase;
5070 struct pci_dev *mypdev = NULL;
5071 const u8 *ptr, *ptr2;
5072 u8 v1, v2, v3, v4, v5, reg, ramtype;
5073 u32 rega, regb, regd;
5075 static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 };
5076 static const u8 cs76[2] = { 0xa3, 0xfb };
5077 static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 };
5078 static const u8 cs158[8] = {
5079 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5081 static const u8 cs160[8] = {
5082 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5084 static const u8 cs168[8] = {
5085 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5087 static const u8 cs128[3 * 8] = {
5088 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
5089 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5090 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
5092 static const u8 cs148[2 * 8] = {
5093 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
5094 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5096 static const u8 cs31a[8 * 4] = {
5097 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
5098 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
5099 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5102 static const u8 cs33a[8 * 4] = {
5103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5108 static const u8 cs45a[8 * 2] = {
5109 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
5110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5112 static const u8 cs170[7 * 8] = {
5113 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5114 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5115 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
5116 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5117 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5118 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5119 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5121 static const u8 cs1a8[3 * 8] = {
5122 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5123 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5126 static const u8 cs100[2 * 8] = {
5127 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5128 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5132 reg = SiS_GetRegByte(SISVGAENABLE) | 0x01;
5133 SiS_SetRegByte(SISVGAENABLE, reg);
5136 reg = SiS_GetRegByte(SISMISCR) | 0x01;
5137 SiS_SetRegByte(SISMISCW, reg);
5140 SiS_SetReg(SISSR, 0x05, 0x86);
5141 reg = SiS_GetReg(SISSR, 0x05);
5145 /* Clear some regs */
5146 for(i = 0; i < 0x22; i++) {
5147 if(0x06 + i == 0x20) continue;
5148 SiS_SetReg(SISSR, 0x06 + i, 0x00);
5150 for(i = 0; i < 0x0b; i++) {
5151 SiS_SetReg(SISSR, 0x31 + i, 0x00);
5153 for(i = 0; i < 0x10; i++) {
5154 SiS_SetReg(SISCR, 0x30 + i, 0x00);
5158 if(ivideo->haveXGIROM) {
5159 ptr = (const u8 *)&bios[0x78];
5161 for(i = 0; i < 3; i++) {
5162 SiS_SetReg(SISSR, 0x23 + i, ptr[i]);
5166 if(ivideo->haveXGIROM) {
5167 ptr = (const u8 *)&bios[0x76];
5169 for(i = 0; i < 2; i++) {
5170 SiS_SetReg(SISSR, 0x21 + i, ptr[i]);
5173 v1 = 0x18; v2 = 0x00;
5174 if(ivideo->haveXGIROM) {
5178 SiS_SetReg(SISSR, 0x07, v1);
5179 SiS_SetReg(SISSR, 0x11, 0x0f);
5180 SiS_SetReg(SISSR, 0x1f, v2);
5181 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5182 SiS_SetReg(SISSR, 0x20, 0x80 | 0x20 | 0x04);
5183 SiS_SetReg(SISSR, 0x27, 0x74);
5186 if(ivideo->haveXGIROM) {
5187 ptr = (const u8 *)&bios[0x7b];
5189 for(i = 0; i < 3; i++) {
5190 SiS_SetReg(SISSR, 0x31 + i, ptr[i]);
5193 if(ivideo->chip == XGI_40) {
5194 if(ivideo->revision_id == 2) {
5195 SiS_SetRegANDOR(SISSR, 0x3b, 0x3f, 0xc0);
5197 SiS_SetReg(SISCR, 0x7d, 0xfe);
5198 SiS_SetReg(SISCR, 0x7e, 0x0f);
5200 if(ivideo->revision_id == 0) { /* 40 *and* 20? */
5201 SiS_SetRegAND(SISCR, 0x58, 0xd7);
5202 reg = SiS_GetReg(SISCR, 0xcb);
5204 SiS_SetRegANDOR(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5208 reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
5209 SiS_SetRegANDOR(SISCR, 0x38, 0x1f, reg);
5211 if(ivideo->chip == XGI_20) {
5212 SiS_SetReg(SISSR, 0x36, 0x70);
5214 SiS_SetReg(SISVID, 0x00, 0x86);
5215 SiS_SetReg(SISVID, 0x32, 0x00);
5216 SiS_SetReg(SISVID, 0x30, 0x00);
5217 SiS_SetReg(SISVID, 0x32, 0x01);
5218 SiS_SetReg(SISVID, 0x30, 0x00);
5219 SiS_SetRegAND(SISVID, 0x2f, 0xdf);
5220 SiS_SetRegAND(SISCAP, 0x00, 0x3f);
5222 SiS_SetReg(SISPART1, 0x2f, 0x01);
5223 SiS_SetReg(SISPART1, 0x00, 0x00);
5224 SiS_SetReg(SISPART1, 0x02, bios[0x7e]);
5225 SiS_SetReg(SISPART1, 0x2e, 0x08);
5226 SiS_SetRegAND(SISPART1, 0x35, 0x7f);
5227 SiS_SetRegAND(SISPART1, 0x50, 0xfe);
5229 reg = SiS_GetReg(SISPART4, 0x00);
5230 if(reg == 1 || reg == 2) {
5231 SiS_SetReg(SISPART2, 0x00, 0x1c);
5232 SiS_SetReg(SISPART4, 0x0d, bios[0x7f]);
5233 SiS_SetReg(SISPART4, 0x0e, bios[0x80]);
5234 SiS_SetReg(SISPART4, 0x10, bios[0x81]);
5235 SiS_SetRegAND(SISPART4, 0x0f, 0x3f);
5237 reg = SiS_GetReg(SISPART4, 0x01);
5238 if((reg & 0xf0) >= 0xb0) {
5239 reg = SiS_GetReg(SISPART4, 0x23);
5240 if(reg & 0x20) reg |= 0x40;
5241 SiS_SetReg(SISPART4, 0x23, reg);
5242 reg = (reg & 0x20) ? 0x02 : 0x00;
5243 SiS_SetRegANDOR(SISPART1, 0x1e, 0xfd, reg);
5249 reg = SiS_GetReg(SISSR, 0x3b);
5251 reg = SiS_GetReg(SISSR, 0x3a);
5252 v2 = (reg & 0x30) >> 3;
5253 if(!(v2 & 0x04)) v2 ^= 0x02;
5254 reg = SiS_GetReg(SISSR, 0x39);
5255 if(reg & 0x80) v2 |= 0x80;
5258 if((mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
5259 pci_dev_put(mypdev);
5260 if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
5265 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0735, NULL);
5267 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0645, NULL);
5269 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0650, NULL);
5271 pci_read_config_dword(mypdev, 0x94, ®d);
5273 pci_write_config_dword(mypdev, 0x94, regd);
5275 pci_dev_put(mypdev);
5276 } else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) {
5278 } else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) ||
5279 sisfb_find_host_bridge(ivideo, pdev, 0x1022) ||
5280 sisfb_find_host_bridge(ivideo, pdev, 0x700e) ||
5281 sisfb_find_host_bridge(ivideo, pdev, 0x10de)) {
5282 if((v2 & 0x06) == 4)
5287 SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, v2);
5289 SiS_SetReg(SISSR, 0x22, v1);
5291 if(ivideo->revision_id == 2) {
5292 v1 = SiS_GetReg(SISSR, 0x3b);
5293 v2 = SiS_GetReg(SISSR, 0x3a);
5294 regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
5295 if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
5296 SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
5298 if((mypdev = pci_get_device(0x10de, 0x01e0, NULL))) {
5299 /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5303 SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
5304 pci_dev_put(mypdev);
5309 reg = SiS_GetReg(SISSR, 0x3b);
5310 v2 = SiS_GetReg(SISCR, 0x5f);
5311 if((!(reg & 0x02)) && (v2 & 0x0e))
5313 SiS_SetReg(SISSR, 0x27, v1);
5315 if(bios[0x64] & 0x01) {
5316 SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, bios[0x64]);
5320 pci_read_config_dword(pdev, 0x50, ®d);
5321 regd = (regd >> 20) & 0x0f;
5324 SiS_SetRegOR(SISCR, 0x5f, 0x08);
5326 SiS_SetReg(SISCR, 0x48, v1);
5328 SiS_SetRegANDOR(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
5329 SiS_SetRegANDOR(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
5330 SiS_SetRegANDOR(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
5331 SiS_SetRegANDOR(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
5332 SiS_SetRegANDOR(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
5333 SiS_SetReg(SISCR, 0x70, bios[0x4fc]);
5334 SiS_SetRegANDOR(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
5335 SiS_SetReg(SISCR, 0x74, 0xd0);
5336 SiS_SetRegANDOR(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
5337 SiS_SetRegANDOR(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
5338 SiS_SetRegANDOR(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
5340 if((mypdev = pci_get_device(0x8086, 0x2530, NULL))) {
5342 pci_dev_put(mypdev);
5344 SiS_SetReg(SISCR, 0x77, v1);
5349 * 0 == DDR1, 1 == DDR2, 2..7 == reserved?
5351 * The code seems to written so that regb should equal ramtype,
5352 * however, so far it has been hardcoded to 0. Enable other values only
5353 * on XGI Z9, as it passes the POST, and add a warning for others.
5355 ramtype = sisfb_post_xgi_ramtype(ivideo);
5356 if (!sisfb_xgi_is21(ivideo) && ramtype) {
5357 dev_warn(&pdev->dev,
5358 "RAM type something else than expected: %d\n",
5366 if(ivideo->haveXGIROM) {
5367 v1 = bios[0x140 + regb];
5369 SiS_SetReg(SISCR, 0x6d, v1);
5372 if(ivideo->haveXGIROM) {
5373 ptr = (const u8 *)&bios[0x128];
5375 for(i = 0, j = 0; i < 3; i++, j += 8) {
5376 SiS_SetReg(SISCR, 0x68 + i, ptr[j + regb]);
5381 if(ivideo->haveXGIROM) {
5382 index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6;
5383 ptr = (const u8 *)&bios[index];
5384 ptr2 = (const u8 *)&bios[index + 0x20];
5386 for(i = 0; i < 2; i++) {
5388 regd = le32_to_cpu(((u32 *)ptr)[regb]);
5391 regd = le32_to_cpu(((u32 *)ptr2)[regb]);
5395 for(j = 0; j < 16; j++) {
5397 if(regd & 0x01) reg |= 0x04;
5398 if(regd & 0x02) reg |= 0x08;
5400 SiS_SetReg(SISCR, rega, reg);
5401 reg = SiS_GetReg(SISCR, rega);
5402 reg = SiS_GetReg(SISCR, rega);
5407 SiS_SetRegAND(SISCR, 0x6e, 0xfc);
5410 if(ivideo->haveXGIROM) {
5411 index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6;
5412 ptr = (const u8 *)&bios[index];
5414 for(i = 0; i < 4; i++) {
5415 SiS_SetRegANDOR(SISCR, 0x6e, 0xfc, i);
5417 for(j = 0; j < 2; j++) {
5420 regd = le32_to_cpu(((u32 *)ptr)[regb * 8]);
5424 for(k = 0; k < 16; k++) {
5426 if(regd & 0x01) reg |= 0x01;
5427 if(regd & 0x02) reg |= 0x02;
5429 SiS_SetReg(SISCR, 0x6f, reg);
5430 reg = SiS_GetReg(SISCR, 0x6f);
5431 reg = SiS_GetReg(SISCR, 0x6f);
5438 if(ivideo->haveXGIROM) {
5439 ptr = (const u8 *)&bios[0x148];
5441 for(i = 0, j = 0; i < 2; i++, j += 8) {
5442 SiS_SetReg(SISCR, 0x80 + i, ptr[j + regb]);
5445 SiS_SetRegAND(SISCR, 0x89, 0x8f);
5448 if(ivideo->haveXGIROM) {
5449 index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6;
5450 ptr = (const u8 *)&bios[index];
5452 regd = le16_to_cpu(((const u16 *)ptr)[regb]);
5454 for(i = 0; i < 5; i++) {
5456 if(regd & 0x01) reg |= 0x01;
5457 if(regd & 0x02) reg |= 0x02;
5459 SiS_SetReg(SISCR, 0x89, reg);
5460 reg = SiS_GetReg(SISCR, 0x89);
5461 reg = SiS_GetReg(SISCR, 0x89);
5465 v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13;
5466 if(ivideo->haveXGIROM) {
5467 v1 = bios[0x118 + regb];
5468 v2 = bios[0xf8 + regb];
5469 v3 = bios[0x120 + regb];
5472 SiS_SetReg(SISCR, 0x45, v1 & 0x0f);
5473 SiS_SetReg(SISCR, 0x99, (v1 >> 4) & 0x07);
5474 SiS_SetRegOR(SISCR, 0x40, v1 & 0x80);
5475 SiS_SetReg(SISCR, 0x41, v2);
5478 if(ivideo->haveXGIROM) {
5479 ptr = (const u8 *)&bios[0x170];
5481 for(i = 0, j = 0; i < 7; i++, j += 8) {
5482 SiS_SetReg(SISCR, 0x90 + i, ptr[j + regb]);
5485 SiS_SetReg(SISCR, 0x59, v3);
5488 if(ivideo->haveXGIROM) {
5489 ptr = (const u8 *)&bios[0x1a8];
5491 for(i = 0, j = 0; i < 3; i++, j += 8) {
5492 SiS_SetReg(SISCR, 0xc3 + i, ptr[j + regb]);
5496 if(ivideo->haveXGIROM) {
5497 ptr = (const u8 *)&bios[0x100];
5499 for(i = 0, j = 0; i < 2; i++, j += 8) {
5500 SiS_SetReg(SISCR, 0x8a + i, ptr[j + regb]);
5503 SiS_SetReg(SISCR, 0xcf, v4);
5505 SiS_SetReg(SISCR, 0x83, 0x09);
5506 SiS_SetReg(SISCR, 0x87, 0x00);
5508 if(ivideo->chip == XGI_40) {
5509 if( (ivideo->revision_id == 1) ||
5510 (ivideo->revision_id == 2) ) {
5511 SiS_SetReg(SISCR, 0x8c, 0x87);
5516 SiS_SetReg(SISSR, 0x17, 0x80); /* DDR2 */
5518 SiS_SetReg(SISSR, 0x17, 0x00); /* DDR1 */
5519 SiS_SetReg(SISSR, 0x1a, 0x87);
5521 if(ivideo->chip == XGI_20) {
5522 SiS_SetReg(SISSR, 0x15, 0x00);
5523 SiS_SetReg(SISSR, 0x1c, 0x00);
5528 sisfb_post_xgi_setclocks(ivideo, regb);
5529 if((ivideo->chip == XGI_20) ||
5530 (ivideo->revision_id == 1) ||
5531 (ivideo->revision_id == 2)) {
5532 v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb];
5533 if(ivideo->haveXGIROM) {
5534 v1 = bios[regb + 0x158];
5535 v2 = bios[regb + 0x160];
5536 v3 = bios[regb + 0x168];
5538 SiS_SetReg(SISCR, 0x82, v1);
5539 SiS_SetReg(SISCR, 0x85, v2);
5540 SiS_SetReg(SISCR, 0x86, v3);
5542 SiS_SetReg(SISCR, 0x82, 0x88);
5543 SiS_SetReg(SISCR, 0x86, 0x00);
5544 reg = SiS_GetReg(SISCR, 0x86);
5545 SiS_SetReg(SISCR, 0x86, 0x88);
5546 reg = SiS_GetReg(SISCR, 0x86);
5547 SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
5548 SiS_SetReg(SISCR, 0x82, 0x77);
5549 SiS_SetReg(SISCR, 0x85, 0x00);
5550 reg = SiS_GetReg(SISCR, 0x85);
5551 SiS_SetReg(SISCR, 0x85, 0x88);
5552 reg = SiS_GetReg(SISCR, 0x85);
5553 SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
5554 SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
5556 if(ivideo->chip == XGI_40) {
5557 SiS_SetReg(SISCR, 0x97, 0x00);
5559 SiS_SetReg(SISCR, 0x98, 0x01);
5560 SiS_SetReg(SISCR, 0x9a, 0x02);
5562 SiS_SetReg(SISSR, 0x18, 0x01);
5563 if((ivideo->chip == XGI_20) ||
5564 (ivideo->revision_id == 2)) {
5565 SiS_SetReg(SISSR, 0x19, 0x40);
5567 SiS_SetReg(SISSR, 0x19, 0x20);
5569 SiS_SetReg(SISSR, 0x16, 0x00);
5570 SiS_SetReg(SISSR, 0x16, 0x80);
5571 if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
5572 sisfb_post_xgi_delay(ivideo, 0x43);
5573 sisfb_post_xgi_delay(ivideo, 0x43);
5574 sisfb_post_xgi_delay(ivideo, 0x43);
5575 SiS_SetReg(SISSR, 0x18, 0x00);
5576 if((ivideo->chip == XGI_20) ||
5577 (ivideo->revision_id == 2)) {
5578 SiS_SetReg(SISSR, 0x19, 0x40);
5580 SiS_SetReg(SISSR, 0x19, 0x20);
5582 } else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
5583 /* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
5585 SiS_SetReg(SISSR, 0x16, 0x00);
5586 SiS_SetReg(SISSR, 0x16, 0x80);
5587 sisfb_post_xgi_delay(ivideo, 4);
5588 v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
5589 if(ivideo->haveXGIROM) {
5591 index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e;
5593 v3 = bios[index + 1];
5594 v4 = bios[index + 2];
5595 v5 = bios[index + 3];
5597 SiS_SetReg(SISSR, 0x18, v1);
5598 SiS_SetReg(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
5599 SiS_SetReg(SISSR, 0x16, v2);
5600 SiS_SetReg(SISSR, 0x16, v3);
5601 sisfb_post_xgi_delay(ivideo, 0x43);
5602 SiS_SetReg(SISSR, 0x1b, 0x03);
5603 sisfb_post_xgi_delay(ivideo, 0x22);
5604 SiS_SetReg(SISSR, 0x18, v1);
5605 SiS_SetReg(SISSR, 0x19, 0x00);
5606 SiS_SetReg(SISSR, 0x16, v4);
5607 SiS_SetReg(SISSR, 0x16, v5);
5608 SiS_SetReg(SISSR, 0x1b, 0x00);
5611 sisfb_post_xgi_ddr2(ivideo, regb);
5614 sisfb_post_xgi_setclocks(ivideo, regb);
5615 if((ivideo->chip == XGI_40) &&
5616 ((ivideo->revision_id == 1) ||
5617 (ivideo->revision_id == 2))) {
5618 SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
5619 SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
5620 SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
5622 SiS_SetReg(SISCR, 0x82, 0x88);
5623 SiS_SetReg(SISCR, 0x86, 0x00);
5624 reg = SiS_GetReg(SISCR, 0x86);
5625 SiS_SetReg(SISCR, 0x86, 0x88);
5626 SiS_SetReg(SISCR, 0x82, 0x77);
5627 SiS_SetReg(SISCR, 0x85, 0x00);
5628 reg = SiS_GetReg(SISCR, 0x85);
5629 SiS_SetReg(SISCR, 0x85, 0x88);
5630 reg = SiS_GetReg(SISCR, 0x85);
5631 v1 = cs160[regb]; v2 = cs158[regb];
5632 if(ivideo->haveXGIROM) {
5633 v1 = bios[regb + 0x160];
5634 v2 = bios[regb + 0x158];
5636 SiS_SetReg(SISCR, 0x85, v1);
5637 SiS_SetReg(SISCR, 0x82, v2);
5639 if(ivideo->chip == XGI_40) {
5640 SiS_SetReg(SISCR, 0x97, 0x11);
5642 if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
5643 SiS_SetReg(SISCR, 0x98, 0x01);
5645 SiS_SetReg(SISCR, 0x98, 0x03);
5647 SiS_SetReg(SISCR, 0x9a, 0x02);
5649 if(ivideo->chip == XGI_40) {
5650 SiS_SetReg(SISSR, 0x18, 0x01);
5652 SiS_SetReg(SISSR, 0x18, 0x00);
5654 SiS_SetReg(SISSR, 0x19, 0x40);
5655 SiS_SetReg(SISSR, 0x16, 0x00);
5656 SiS_SetReg(SISSR, 0x16, 0x80);
5657 if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
5658 sisfb_post_xgi_delay(ivideo, 0x43);
5659 sisfb_post_xgi_delay(ivideo, 0x43);
5660 sisfb_post_xgi_delay(ivideo, 0x43);
5661 SiS_SetReg(SISSR, 0x18, 0x00);
5662 SiS_SetReg(SISSR, 0x19, 0x40);
5663 SiS_SetReg(SISSR, 0x16, 0x00);
5664 SiS_SetReg(SISSR, 0x16, 0x80);
5666 sisfb_post_xgi_delay(ivideo, 4);
5668 if(ivideo->haveXGIROM) {
5671 SiS_SetReg(SISSR, 0x18, v1);
5672 SiS_SetReg(SISSR, 0x19, 0x01);
5673 if(ivideo->chip == XGI_40) {
5674 SiS_SetReg(SISSR, 0x16, bios[0x53e]);
5675 SiS_SetReg(SISSR, 0x16, bios[0x53f]);
5677 SiS_SetReg(SISSR, 0x16, 0x05);
5678 SiS_SetReg(SISSR, 0x16, 0x85);
5680 sisfb_post_xgi_delay(ivideo, 0x43);
5681 if(ivideo->chip == XGI_40) {
5682 SiS_SetReg(SISSR, 0x1b, 0x01);
5684 SiS_SetReg(SISSR, 0x1b, 0x03);
5686 sisfb_post_xgi_delay(ivideo, 0x22);
5687 SiS_SetReg(SISSR, 0x18, v1);
5688 SiS_SetReg(SISSR, 0x19, 0x00);
5689 if(ivideo->chip == XGI_40) {
5690 SiS_SetReg(SISSR, 0x16, bios[0x540]);
5691 SiS_SetReg(SISSR, 0x16, bios[0x541]);
5693 SiS_SetReg(SISSR, 0x16, 0x05);
5694 SiS_SetReg(SISSR, 0x16, 0x85);
5696 SiS_SetReg(SISSR, 0x1b, 0x00);
5701 if(ivideo->haveXGIROM) {
5702 v1 = bios[0x110 + regb];
5704 SiS_SetReg(SISSR, 0x1b, v1);
5707 v1 = 0x00; v2 = 0x00;
5708 if(ivideo->haveXGIROM) {
5714 if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
5716 SiS_SetReg(SISSR, 0x13, bios[regb + 0xe0]);
5717 SiS_SetReg(SISSR, 0x14, bios[regb + 0xe0 + 8]);
5722 /* Set default mode, don't clear screen */
5723 ivideo->SiS_Pr.SiS_UseOEM = false;
5724 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
5725 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
5726 ivideo->curFSTN = ivideo->curDSTN = 0;
5727 ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
5728 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5730 SiS_SetReg(SISSR, 0x05, 0x86);
5732 /* Disable read-cache */
5733 SiS_SetRegAND(SISSR, 0x21, 0xdf);
5734 err = sisfb_post_xgi_ramsize(ivideo);
5735 /* Enable read-cache */
5736 SiS_SetRegOR(SISSR, 0x21, 0x20);
5740 "%s: RAM size detection failed: %d\n",
5747 printk(KERN_DEBUG "-----------------\n");
5748 for(i = 0; i < 0xff; i++) {
5749 reg = SiS_GetReg(SISCR, i);
5750 printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
5752 for(i = 0; i < 0x40; i++) {
5753 reg = SiS_GetReg(SISSR, i);
5754 printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
5756 printk(KERN_DEBUG "-----------------\n");
5760 if(ivideo->chip == XGI_20) {
5761 SiS_SetRegOR(SISCR, 0x32, 0x20);
5763 reg = SiS_GetReg(SISPART4, 0x00);
5764 if((reg == 1) || (reg == 2)) {
5765 sisfb_sense_crt1(ivideo);
5767 SiS_SetRegOR(SISCR, 0x32, 0x20);
5771 /* Set default mode, don't clear screen */
5772 ivideo->SiS_Pr.SiS_UseOEM = false;
5773 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
5774 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
5775 ivideo->curFSTN = ivideo->curDSTN = 0;
5776 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5778 SiS_SetReg(SISSR, 0x05, 0x86);
5781 SiS_SetRegOR(SISSR, 0x01, 0x20);
5783 /* Save mode number in CR34 */
5784 SiS_SetReg(SISCR, 0x34, 0x2e);
5786 /* Let everyone know what the current mode is */
5787 ivideo->modeprechange = 0x2e;
5789 if(ivideo->chip == XGI_40) {
5790 reg = SiS_GetReg(SISCR, 0xca);
5791 v1 = SiS_GetReg(SISCR, 0xcc);
5792 if((reg & 0x10) && (!(v1 & 0x04))) {
5794 "sisfb: Please connect power to the card.\n");
5803 static int sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
5805 struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data];
5806 struct sis_video_info *ivideo = NULL;
5807 struct fb_info *sis_fb_info = NULL;
5815 sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
5819 ivideo = (struct sis_video_info *)sis_fb_info->par;
5820 ivideo->memyselfandi = sis_fb_info;
5822 ivideo->sisfb_id = SISFB_ID;
5824 if(card_list == NULL) {
5825 ivideo->cardnumber = 0;
5827 struct sis_video_info *countvideo = card_list;
5828 ivideo->cardnumber = 1;
5829 while((countvideo = countvideo->next) != NULL)
5830 ivideo->cardnumber++;
5833 strncpy(ivideo->myid, chipinfo->chip_name, 30);
5835 ivideo->warncount = 0;
5836 ivideo->chip_id = pdev->device;
5837 ivideo->chip_vendor = pdev->vendor;
5838 ivideo->revision_id = pdev->revision;
5839 ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
5840 pci_read_config_word(pdev, PCI_COMMAND, ®16);
5841 ivideo->sisvga_enabled = reg16 & 0x01;
5842 ivideo->pcibus = pdev->bus->number;
5843 ivideo->pcislot = PCI_SLOT(pdev->devfn);
5844 ivideo->pcifunc = PCI_FUNC(pdev->devfn);
5845 ivideo->subsysvendor = pdev->subsystem_vendor;
5846 ivideo->subsysdevice = pdev->subsystem_device;
5849 if(sisfb_mode_idx == -1) {
5850 sisfb_get_vga_mode_from_kernel();
5854 ivideo->chip = chipinfo->chip;
5855 ivideo->chip_real_id = chipinfo->chip;
5856 ivideo->sisvga_engine = chipinfo->vgaengine;
5857 ivideo->hwcursor_size = chipinfo->hwcursor_size;
5858 ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
5859 ivideo->mni = chipinfo->mni;
5861 ivideo->detectedpdc = 0xff;
5862 ivideo->detectedpdca = 0xff;
5863 ivideo->detectedlcda = 0xff;
5865 ivideo->sisfb_thismonitor.datavalid = false;
5867 ivideo->current_base = 0;
5869 ivideo->engineok = 0;
5871 ivideo->sisfb_was_boot_device = 0;
5873 if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
5874 if(ivideo->sisvga_enabled)
5875 ivideo->sisfb_was_boot_device = 1;
5877 printk(KERN_DEBUG "sisfb: PCI device is disabled, "
5878 "but marked as boot video device ???\n");
5879 printk(KERN_DEBUG "sisfb: I will not accept this "
5880 "as the primary VGA device\n");
5884 ivideo->sisfb_parm_mem = sisfb_parm_mem;
5885 ivideo->sisfb_accel = sisfb_accel;
5886 ivideo->sisfb_ypan = sisfb_ypan;
5887 ivideo->sisfb_max = sisfb_max;
5888 ivideo->sisfb_userom = sisfb_userom;
5889 ivideo->sisfb_useoem = sisfb_useoem;
5890 ivideo->sisfb_mode_idx = sisfb_mode_idx;
5891 ivideo->sisfb_parm_rate = sisfb_parm_rate;
5892 ivideo->sisfb_crt1off = sisfb_crt1off;
5893 ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
5894 ivideo->sisfb_crt2type = sisfb_crt2type;
5895 ivideo->sisfb_crt2flags = sisfb_crt2flags;
5896 /* pdc(a), scalelcd, special timing, lvdshl handled below */
5897 ivideo->sisfb_dstn = sisfb_dstn;
5898 ivideo->sisfb_fstn = sisfb_fstn;
5899 ivideo->sisfb_tvplug = sisfb_tvplug;
5900 ivideo->sisfb_tvstd = sisfb_tvstd;
5901 ivideo->tvxpos = sisfb_tvxposoffset;
5902 ivideo->tvypos = sisfb_tvyposoffset;
5903 ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
5904 ivideo->refresh_rate = 0;
5905 if(ivideo->sisfb_parm_rate != -1) {
5906 ivideo->refresh_rate = ivideo->sisfb_parm_rate;
5909 ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
5910 ivideo->SiS_Pr.CenterScreen = -1;
5911 ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
5912 ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
5914 ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
5915 ivideo->SiS_Pr.SiS_CHOverScan = -1;
5916 ivideo->SiS_Pr.SiS_ChSW = false;
5917 ivideo->SiS_Pr.SiS_UseLCDA = false;
5918 ivideo->SiS_Pr.HaveEMI = false;
5919 ivideo->SiS_Pr.HaveEMILCD = false;
5920 ivideo->SiS_Pr.OverruleEMI = false;
5921 ivideo->SiS_Pr.SiS_SensibleSR11 = false;
5922 ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
5923 ivideo->SiS_Pr.PDC = -1;
5924 ivideo->SiS_Pr.PDCA = -1;
5925 ivideo->SiS_Pr.DDCPortMixup = false;
5926 #ifdef CONFIG_FB_SIS_315
5927 if(ivideo->chip >= SIS_330) {
5928 ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
5929 if(ivideo->chip >= SIS_661) {
5930 ivideo->SiS_Pr.SiS_SensibleSR11 = true;
5935 memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));
5937 pci_set_drvdata(pdev, ivideo);
5939 /* Patch special cases */
5940 if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) {
5941 switch(ivideo->nbridge->device) {
5942 #ifdef CONFIG_FB_SIS_300
5943 case PCI_DEVICE_ID_SI_730:
5944 ivideo->chip = SIS_730;
5945 strcpy(ivideo->myid, "SiS 730");
5948 #ifdef CONFIG_FB_SIS_315
5949 case PCI_DEVICE_ID_SI_651:
5950 /* ivideo->chip is ok */
5951 strcpy(ivideo->myid, "SiS 651");
5953 case PCI_DEVICE_ID_SI_740:
5954 ivideo->chip = SIS_740;
5955 strcpy(ivideo->myid, "SiS 740");
5957 case PCI_DEVICE_ID_SI_661:
5958 ivideo->chip = SIS_661;
5959 strcpy(ivideo->myid, "SiS 661");
5961 case PCI_DEVICE_ID_SI_741:
5962 ivideo->chip = SIS_741;
5963 strcpy(ivideo->myid, "SiS 741");
5965 case PCI_DEVICE_ID_SI_760:
5966 ivideo->chip = SIS_760;
5967 strcpy(ivideo->myid, "SiS 760");
5969 case PCI_DEVICE_ID_SI_761:
5970 ivideo->chip = SIS_761;
5971 strcpy(ivideo->myid, "SiS 761");
5979 ivideo->SiS_Pr.ChipType = ivideo->chip;
5981 ivideo->SiS_Pr.ivideo = (void *)ivideo;
5983 #ifdef CONFIG_FB_SIS_315
5984 if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
5985 (ivideo->SiS_Pr.ChipType == SIS_315)) {
5986 ivideo->SiS_Pr.ChipType = SIS_315H;
5990 if(!ivideo->sisvga_enabled) {
5991 if(pci_enable_device(pdev)) {
5992 if(ivideo->nbridge) pci_dev_put(ivideo->nbridge);
5993 framebuffer_release(sis_fb_info);
5998 ivideo->video_base = pci_resource_start(pdev, 0);
5999 ivideo->video_size = pci_resource_len(pdev, 0);
6000 ivideo->mmio_base = pci_resource_start(pdev, 1);
6001 ivideo->mmio_size = pci_resource_len(pdev, 1);
6002 ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
6003 ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
6005 SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress);
6007 #ifdef CONFIG_FB_SIS_300
6008 /* Find PCI systems for Chrontel/GPIO communication setup */
6009 if(ivideo->chip == SIS_630) {
6012 if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
6013 mychswtable[i].subsysCard == ivideo->subsysdevice) {
6014 ivideo->SiS_Pr.SiS_ChSW = true;
6015 printk(KERN_DEBUG "sisfb: Identified [%s %s] "
6016 "requiring Chrontel/GPIO setup\n",
6017 mychswtable[i].vendorName,
6018 mychswtable[i].cardName);
6019 ivideo->lpcdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, NULL);
6023 } while(mychswtable[i].subsysVendor != 0);
6027 #ifdef CONFIG_FB_SIS_315
6028 if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
6029 ivideo->lpcdev = pci_get_slot(ivideo->nbridge->bus, (2 << 3));
6033 SiS_SetReg(SISSR, 0x05, 0x86);
6035 if( (!ivideo->sisvga_enabled)
6036 #if !defined(__i386__) && !defined(__x86_64__)
6037 || (sisfb_resetcard)
6040 for(i = 0x30; i <= 0x3f; i++) {
6041 SiS_SetReg(SISCR, i, 0x00);
6045 /* Find out about current video mode */
6046 ivideo->modeprechange = 0x03;
6047 reg = SiS_GetReg(SISCR, 0x34);
6049 ivideo->modeprechange = reg & 0x7f;
6050 } else if(ivideo->sisvga_enabled) {
6051 #if defined(__i386__) || defined(__x86_64__)
6052 unsigned char __iomem *tt = ioremap(0x400, 0x100);
6054 ivideo->modeprechange = readb(tt + 0x49);
6060 /* Search and copy ROM image */
6061 ivideo->bios_abase = NULL;
6062 ivideo->SiS_Pr.VirtualRomBase = NULL;
6063 ivideo->SiS_Pr.UseROM = false;
6064 ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = false;
6065 if(ivideo->sisfb_userom) {
6066 ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
6067 ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
6068 ivideo->SiS_Pr.UseROM = (bool)(ivideo->SiS_Pr.VirtualRomBase);
6069 printk(KERN_INFO "sisfb: Video ROM %sfound\n",
6070 ivideo->SiS_Pr.UseROM ? "" : "not ");
6071 if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
6072 ivideo->SiS_Pr.UseROM = false;
6073 ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = true;
6074 if( (ivideo->revision_id == 2) &&
6075 (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
6076 ivideo->SiS_Pr.DDCPortMixup = true;
6080 printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
6083 /* Find systems for special custom timing */
6084 if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
6085 sisfb_detect_custom_timing(ivideo);
6088 #ifdef CONFIG_FB_SIS_315
6089 if (ivideo->chip == XGI_20) {
6090 /* Check if our Z7 chip is actually Z9 */
6091 SiS_SetRegOR(SISCR, 0x4a, 0x40); /* GPIOG EN */
6092 reg = SiS_GetReg(SISCR, 0x48);
6093 if (reg & 0x02) { /* GPIOG */
6094 ivideo->chip_real_id = XGI_21;
6095 dev_info(&pdev->dev, "Z9 detected\n");
6100 /* POST card in case this has not been done by the BIOS */
6101 if( (!ivideo->sisvga_enabled)
6102 #if !defined(__i386__) && !defined(__x86_64__)
6103 || (sisfb_resetcard)
6106 #ifdef CONFIG_FB_SIS_300
6107 if(ivideo->sisvga_engine == SIS_300_VGA) {
6108 if(ivideo->chip == SIS_300) {
6109 sisfb_post_sis300(pdev);
6110 ivideo->sisfb_can_post = 1;
6115 #ifdef CONFIG_FB_SIS_315
6116 if(ivideo->sisvga_engine == SIS_315_VGA) {
6118 /* if((ivideo->chip == SIS_315H) ||
6119 (ivideo->chip == SIS_315) ||
6120 (ivideo->chip == SIS_315PRO) ||
6121 (ivideo->chip == SIS_330)) {
6122 sisfb_post_sis315330(pdev);
6123 } else */ if(ivideo->chip == XGI_20) {
6124 result = sisfb_post_xgi(pdev);
6125 ivideo->sisfb_can_post = 1;
6126 } else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
6127 result = sisfb_post_xgi(pdev);
6128 ivideo->sisfb_can_post = 1;
6130 printk(KERN_INFO "sisfb: Card is not "
6131 "POSTed and sisfb can't do this either.\n");
6134 printk(KERN_ERR "sisfb: Failed to POST card\n");
6142 ivideo->sisfb_card_posted = 1;
6144 /* Find out about RAM size */
6145 if(sisfb_get_dram_size(ivideo)) {
6146 printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
6152 /* Enable PCI addressing and MMIO */
6153 if((ivideo->sisfb_mode_idx < 0) ||
6154 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6155 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
6156 SiS_SetRegOR(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
6157 /* Enable 2D accelerator engine */
6158 SiS_SetRegOR(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
6161 if(sisfb_pdc != 0xff) {
6162 if(ivideo->sisvga_engine == SIS_300_VGA)
6166 ivideo->SiS_Pr.PDC = sisfb_pdc;
6168 #ifdef CONFIG_FB_SIS_315
6169 if(ivideo->sisvga_engine == SIS_315_VGA) {
6170 if(sisfb_pdca != 0xff)
6171 ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
6175 if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
6176 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6177 (int)(ivideo->video_size >> 20));
6178 printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
6183 if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
6184 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
6189 ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size);
6190 ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
6191 if(!ivideo->video_vbase) {
6192 printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
6197 ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
6198 if(!ivideo->mmio_vbase) {
6199 printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
6201 error_0: iounmap(ivideo->video_vbase);
6202 error_1: release_mem_region(ivideo->video_base, ivideo->video_size);
6203 error_2: release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6204 error_3: vfree(ivideo->bios_abase);
6206 pci_dev_put(ivideo->lpcdev);
6208 pci_dev_put(ivideo->nbridge);
6209 if(!ivideo->sisvga_enabled)
6210 pci_disable_device(pdev);
6211 framebuffer_release(sis_fb_info);
6215 printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
6216 ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);
6218 if(ivideo->video_offset) {
6219 printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
6220 ivideo->video_offset / 1024);
6223 printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
6224 ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
6227 /* Determine the size of the command queue */
6228 if(ivideo->sisvga_engine == SIS_300_VGA) {
6229 ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
6231 if(ivideo->chip == XGI_20) {
6232 ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
6234 ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
6238 /* Engines are no longer initialized here; this is
6239 * now done after the first mode-switch (if the
6240 * submitted var has its acceleration flags set).
6243 /* Calculate the base of the (unused) hw cursor */
6244 ivideo->hwcursor_vbase = ivideo->video_vbase
6245 + ivideo->video_size
6246 - ivideo->cmdQueueSize
6247 - ivideo->hwcursor_size;
6248 ivideo->caps |= HW_CURSOR_CAP;
6250 /* Initialize offscreen memory manager */
6251 if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
6252 printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
6255 /* Used for clearing the screen only, therefore respect our mem limit */
6256 ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
6257 ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;
6261 ivideo->vbflags = 0;
6262 ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
6263 ivideo->tvdefmodeidx = DEFAULT_TVMODE;
6264 ivideo->defmodeidx = DEFAULT_MODE;
6267 if(ivideo->chip < XGI_20) {
6268 if(ivideo->bios_abase) {
6269 ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr);
6273 if((ivideo->sisfb_mode_idx < 0) ||
6274 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6276 sisfb_sense_crt1(ivideo);
6278 sisfb_get_VB_type(ivideo);
6280 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6281 sisfb_detect_VB_connect(ivideo);
6284 ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
6286 /* Decide on which CRT2 device to use */
6287 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6288 if(ivideo->sisfb_crt2type != -1) {
6289 if((ivideo->sisfb_crt2type == CRT2_LCD) &&
6290 (ivideo->vbflags & CRT2_LCD)) {
6291 ivideo->currentvbflags |= CRT2_LCD;
6292 } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
6293 ivideo->currentvbflags |= ivideo->sisfb_crt2type;
6296 /* Chrontel 700x TV detection often unreliable, therefore
6297 * use a different default order on such machines
6299 if((ivideo->sisvga_engine == SIS_300_VGA) &&
6300 (ivideo->vbflags2 & VB2_CHRONTEL)) {
6301 if(ivideo->vbflags & CRT2_LCD)
6302 ivideo->currentvbflags |= CRT2_LCD;
6303 else if(ivideo->vbflags & CRT2_TV)
6304 ivideo->currentvbflags |= CRT2_TV;
6305 else if(ivideo->vbflags & CRT2_VGA)
6306 ivideo->currentvbflags |= CRT2_VGA;
6308 if(ivideo->vbflags & CRT2_TV)
6309 ivideo->currentvbflags |= CRT2_TV;
6310 else if(ivideo->vbflags & CRT2_LCD)
6311 ivideo->currentvbflags |= CRT2_LCD;
6312 else if(ivideo->vbflags & CRT2_VGA)
6313 ivideo->currentvbflags |= CRT2_VGA;
6318 if(ivideo->vbflags & CRT2_LCD) {
6319 sisfb_detect_lcd_type(ivideo);
6322 sisfb_save_pdc_emi(ivideo);
6324 if(!ivideo->sisfb_crt1off) {
6325 sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
6327 if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
6328 (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
6329 sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
6333 if(ivideo->sisfb_mode_idx >= 0) {
6334 int bu = ivideo->sisfb_mode_idx;
6335 ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
6336 ivideo->sisfb_mode_idx, ivideo->currentvbflags);
6337 if(bu != ivideo->sisfb_mode_idx) {
6338 printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
6339 sisbios_mode[bu].xres,
6340 sisbios_mode[bu].yres,
6341 sisbios_mode[bu].bpp);
6345 if(ivideo->sisfb_mode_idx < 0) {
6346 switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
6348 ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
6351 ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
6354 ivideo->sisfb_mode_idx = ivideo->defmodeidx;
6359 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
6361 if(ivideo->refresh_rate != 0) {
6362 sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate,
6363 ivideo->sisfb_mode_idx);
6366 if(ivideo->rate_idx == 0) {
6367 ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
6368 ivideo->refresh_rate = 60;
6371 if(ivideo->sisfb_thismonitor.datavalid) {
6372 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor,
6373 ivideo->sisfb_mode_idx,
6375 ivideo->refresh_rate)) {
6376 printk(KERN_INFO "sisfb: WARNING: Refresh rate "
6377 "exceeds monitor specs!\n");
6381 ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
6382 ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
6383 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
6385 sisfb_set_vparms(ivideo);
6387 printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
6388 ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
6389 ivideo->refresh_rate);
6391 /* Set up the default var according to chosen default display mode */
6392 ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
6393 ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
6394 ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
6396 sisfb_bpp_to_var(ivideo, &ivideo->default_var);
6398 ivideo->default_var.pixclock = (u32) (1000000000 /
6399 sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx));
6401 if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no,
6402 ivideo->rate_idx, &ivideo->default_var)) {
6403 if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
6404 ivideo->default_var.pixclock <<= 1;
6408 if(ivideo->sisfb_ypan) {
6409 /* Maximize regardless of sisfb_max at startup */
6410 ivideo->default_var.yres_virtual =
6411 sisfb_calc_maxyres(ivideo, &ivideo->default_var);
6412 if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
6413 ivideo->default_var.yres_virtual = ivideo->default_var.yres;
6417 sisfb_calc_pitch(ivideo, &ivideo->default_var);
6420 if(ivideo->sisfb_accel) {
6422 #ifdef STUPID_ACCELF_TEXT_SHIT
6423 ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
6426 sisfb_initaccel(ivideo);
6428 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
6429 sis_fb_info->flags = FBINFO_DEFAULT |
6430 FBINFO_HWACCEL_YPAN |
6431 FBINFO_HWACCEL_XPAN |
6432 FBINFO_HWACCEL_COPYAREA |
6433 FBINFO_HWACCEL_FILLRECT |
6434 ((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED);
6436 sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
6438 sis_fb_info->var = ivideo->default_var;
6439 sis_fb_info->fix = ivideo->sisfb_fix;
6440 sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
6441 sis_fb_info->fbops = &sisfb_ops;
6442 sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
6444 fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
6446 printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
6449 ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size,
6450 MTRR_TYPE_WRCOMB, 1);
6451 if(ivideo->mtrr < 0) {
6452 printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n");
6456 if(register_framebuffer(sis_fb_info) < 0) {
6457 printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
6459 iounmap(ivideo->mmio_vbase);
6463 ivideo->registered = 1;
6466 ivideo->next = card_list;
6469 printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
6470 ivideo->sisfb_accel ? "enabled" : "disabled",
6471 ivideo->sisfb_ypan ?
6472 (ivideo->sisfb_max ? "enabled (auto-max)" :
6473 "enabled (no auto-max)") :
6477 fb_info(sis_fb_info, "%s frame buffer device version %d.%d.%d\n",
6478 ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
6480 printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
6482 } /* if mode = "none" */
6487 /*****************************************************/
6488 /* PCI DEVICE HANDLING */
6489 /*****************************************************/
6491 static void sisfb_remove(struct pci_dev *pdev)
6493 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
6494 struct fb_info *sis_fb_info = ivideo->memyselfandi;
6495 int registered = ivideo->registered;
6496 int modechanged = ivideo->modechanged;
6499 iounmap(ivideo->mmio_vbase);
6500 iounmap(ivideo->video_vbase);
6502 /* Release mem regions */
6503 release_mem_region(ivideo->video_base, ivideo->video_size);
6504 release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6506 vfree(ivideo->bios_abase);
6509 pci_dev_put(ivideo->lpcdev);
6512 pci_dev_put(ivideo->nbridge);
6515 /* Release MTRR region */
6516 if(ivideo->mtrr >= 0)
6517 mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size);
6520 /* If device was disabled when starting, disable
6523 if(!ivideo->sisvga_enabled)
6524 pci_disable_device(pdev);
6526 /* Unregister the framebuffer */
6527 if(ivideo->registered) {
6528 unregister_framebuffer(sis_fb_info);
6529 framebuffer_release(sis_fb_info);
6532 /* OK, our ivideo is gone for good from here. */
6534 /* TODO: Restore the initial mode
6535 * This sounds easy but is as good as impossible
6536 * on many machines with SiS chip and video bridge
6537 * since text modes are always set up differently
6538 * from machine to machine. Depends on the type
6539 * of integration between chipset and bridge.
6541 if(registered && modechanged)
6543 "sisfb: Restoring of text mode not supported yet\n");
6546 static struct pci_driver sisfb_driver = {
6548 .id_table = sisfb_pci_table,
6549 .probe = sisfb_probe,
6550 .remove = sisfb_remove,
6553 static int __init sisfb_init(void)
6556 char *options = NULL;
6558 if(fb_get_options("sisfb", &options))
6561 sisfb_setup(options);
6563 return pci_register_driver(&sisfb_driver);
6567 module_init(sisfb_init);
6570 /*****************************************************/
6572 /*****************************************************/
6576 static char *mode = NULL;
6577 static int vesa = -1;
6578 static unsigned int rate = 0;
6579 static unsigned int crt1off = 1;
6580 static unsigned int mem = 0;
6581 static char *forcecrt2type = NULL;
6582 static int forcecrt1 = -1;
6583 static int pdc = -1;
6584 static int pdc1 = -1;
6585 static int noaccel = -1;
6586 static int noypan = -1;
6587 static int nomax = -1;
6588 static int userom = -1;
6589 static int useoem = -1;
6590 static char *tvstandard = NULL;
6591 static int nocrt2rate = 0;
6592 static int scalelcd = -1;
6593 static char *specialtiming = NULL;
6594 static int lvdshl = -1;
6595 static int tvxposoffset = 0, tvyposoffset = 0;
6596 #if !defined(__i386__) && !defined(__x86_64__)
6597 static int resetcard = 0;
6598 static int videoram = 0;
6601 static int __init sisfb_init_module(void)
6603 sisfb_setdefaultparms();
6606 sisfb_parm_rate = rate;
6608 if((scalelcd == 0) || (scalelcd == 1))
6609 sisfb_scalelcd = scalelcd ^ 1;
6611 /* Need to check crt2 type first for fstn/dstn */
6614 sisfb_search_crt2type(forcecrt2type);
6617 sisfb_search_tvstd(tvstandard);
6620 sisfb_search_mode(mode, false);
6622 sisfb_search_vesamode(vesa, false);
6624 sisfb_crt1off = (crt1off == 0) ? 1 : 0;
6626 sisfb_forcecrt1 = forcecrt1;
6629 else if(forcecrt1 == 0)
6634 else if(noaccel == 0)
6639 else if(noypan == 0)
6648 sisfb_parm_mem = mem;
6651 sisfb_userom = userom;
6654 sisfb_useoem = useoem;
6657 sisfb_pdc = (pdc & 0x7f);
6660 sisfb_pdca = (pdc1 & 0x1f);
6662 sisfb_nocrt2rate = nocrt2rate;
6665 sisfb_search_specialtiming(specialtiming);
6667 if((lvdshl >= 0) && (lvdshl <= 3))
6668 sisfb_lvdshl = lvdshl;
6670 sisfb_tvxposoffset = tvxposoffset;
6671 sisfb_tvyposoffset = tvyposoffset;
6673 #if !defined(__i386__) && !defined(__x86_64__)
6674 sisfb_resetcard = (resetcard) ? 1 : 0;
6676 sisfb_videoram = videoram;
6679 return sisfb_init();
6682 static void __exit sisfb_remove_module(void)
6684 pci_unregister_driver(&sisfb_driver);
6685 printk(KERN_DEBUG "sisfb: Module unloaded\n");
6688 module_init(sisfb_init_module);
6689 module_exit(sisfb_remove_module);
6691 MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
6692 MODULE_LICENSE("GPL");
6693 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
6695 module_param(mem, int, 0);
6696 module_param(noaccel, int, 0);
6697 module_param(noypan, int, 0);
6698 module_param(nomax, int, 0);
6699 module_param(userom, int, 0);
6700 module_param(useoem, int, 0);
6701 module_param(mode, charp, 0);
6702 module_param(vesa, int, 0);
6703 module_param(rate, int, 0);
6704 module_param(forcecrt1, int, 0);
6705 module_param(forcecrt2type, charp, 0);
6706 module_param(scalelcd, int, 0);
6707 module_param(pdc, int, 0);
6708 module_param(pdc1, int, 0);
6709 module_param(specialtiming, charp, 0);
6710 module_param(lvdshl, int, 0);
6711 module_param(tvstandard, charp, 0);
6712 module_param(tvxposoffset, int, 0);
6713 module_param(tvyposoffset, int, 0);
6714 module_param(nocrt2rate, int, 0);
6715 #if !defined(__i386__) && !defined(__x86_64__)
6716 module_param(resetcard, int, 0);
6717 module_param(videoram, int, 0);
6720 MODULE_PARM_DESC(mem,
6721 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6722 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6723 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6724 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6725 "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6726 "The value is to be specified without 'KB'.\n");
6728 MODULE_PARM_DESC(noaccel,
6729 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
6732 MODULE_PARM_DESC(noypan,
6733 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
6734 "will be performed by redrawing the screen. (default: 0)\n");
6736 MODULE_PARM_DESC(nomax,
6737 "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
6738 "memory for the virtual screen in order to optimize scrolling performance. If\n"
6739 "this is set to anything other than 0, sisfb will not do this and thereby \n"
6740 "enable the user to positively specify a virtual Y size of the screen using\n"
6741 "fbset. (default: 0)\n");
6743 MODULE_PARM_DESC(mode,
6744 "\nSelects the desired default display mode in the format XxYxDepth,\n"
6745 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
6746 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
6747 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
6749 MODULE_PARM_DESC(vesa,
6750 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
6751 "0x117 (default: 0x0103)\n");
6753 MODULE_PARM_DESC(rate,
6754 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
6755 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
6756 "will be ignored (default: 60)\n");
6758 MODULE_PARM_DESC(forcecrt1,
6759 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
6760 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
6761 "0=CRT1 OFF) (default: [autodetected])\n");
6763 MODULE_PARM_DESC(forcecrt2type,
6764 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
6765 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
6766 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
6767 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
6768 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
6769 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
6770 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
6771 "depends on the very hardware in use. (default: [autodetected])\n");
6773 MODULE_PARM_DESC(scalelcd,
6774 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
6775 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
6776 "show black bars around the image, TMDS panels will probably do the scaling\n"
6777 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
6779 MODULE_PARM_DESC(pdc,
6780 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
6781 "should detect this correctly in most cases; however, sometimes this is not\n"
6782 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
6783 "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
6784 "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
6785 "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
6787 #ifdef CONFIG_FB_SIS_315
6788 MODULE_PARM_DESC(pdc1,
6789 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
6790 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
6791 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
6792 "implemented yet.\n");
6795 MODULE_PARM_DESC(specialtiming,
6796 "\nPlease refer to documentation for more information on this option.\n");
6798 MODULE_PARM_DESC(lvdshl,
6799 "\nPlease refer to documentation for more information on this option.\n");
6801 MODULE_PARM_DESC(tvstandard,
6802 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
6803 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
6805 MODULE_PARM_DESC(tvxposoffset,
6806 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
6809 MODULE_PARM_DESC(tvyposoffset,
6810 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
6813 MODULE_PARM_DESC(nocrt2rate,
6814 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
6815 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
6817 #if !defined(__i386__) && !defined(__x86_64__)
6818 #ifdef CONFIG_FB_SIS_300
6819 MODULE_PARM_DESC(resetcard,
6820 "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
6821 "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
6822 "currently). Default: 0\n");
6824 MODULE_PARM_DESC(videoram,
6825 "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
6826 "some non-x86 architectures where the memory auto detection fails. Only\n"
6827 "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
6831 #endif /* /MODULE */
6833 /* _GPL only for new symbols. */
6834 EXPORT_SYMBOL(sis_malloc);
6835 EXPORT_SYMBOL(sis_free);
6836 EXPORT_SYMBOL_GPL(sis_malloc_new);
6837 EXPORT_SYMBOL_GPL(sis_free_new);