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/version.h>
37 #include <linux/module.h>
38 #include <linux/moduleparam.h>
39 #include <linux/kernel.h>
40 #include <linux/spinlock.h>
41 #include <linux/errno.h>
42 #include <linux/string.h>
45 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
46 #include <linux/tty.h>
48 #include <linux/screen_info.h>
51 #include <linux/slab.h>
53 #include <linux/selection.h>
54 #include <linux/ioport.h>
55 #include <linux/init.h>
56 #include <linux/pci.h>
57 #include <linux/vmalloc.h>
58 #include <linux/capability.h>
60 #include <linux/types.h>
61 #include <asm/uaccess.h>
70 static void sisfb_handle_command(struct sis_video_info *ivideo,
71 struct sisfb_cmd *sisfb_command);
73 /* ------------------ Internal helper routines ----------------- */
76 sisfb_setdefaultparms(void)
94 sisfb_specialtiming = CUT_NONE;
100 sisfb_tvxposoffset = 0;
101 sisfb_tvyposoffset = 0;
102 sisfb_nocrt2rate = 0;
103 #if !defined(__i386__) && !defined(__x86_64__)
109 /* ------------- Parameter parsing -------------- */
111 static void __devinit
112 sisfb_search_vesamode(unsigned int vesamode, bool quiet)
116 /* We don't know the hardware specs yet and there is no ivideo */
120 printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
122 sisfb_mode_idx = DEFAULT_MODE;
127 vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
129 while(sisbios_mode[i++].mode_no[0] != 0) {
130 if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
131 (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
133 if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
134 sisbios_mode[i-1].mode_no[1] == 0x56 ||
135 sisbios_mode[i-1].mode_no[1] == 0x53)
138 if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
139 sisbios_mode[i-1].mode_no[1] == 0x5b)
142 sisfb_mode_idx = i - 1;
148 printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
151 static void __devinit
152 sisfb_search_mode(char *name, bool quiet)
154 unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
156 char strbuf[16], strbuf1[20];
157 char *nameptr = name;
159 /* We don't know the hardware specs yet and there is no ivideo */
163 printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
165 sisfb_mode_idx = DEFAULT_MODE;
169 if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
171 printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
173 sisfb_mode_idx = DEFAULT_MODE;
177 if(strlen(name) <= 19) {
178 strcpy(strbuf1, name);
179 for(i = 0; i < strlen(strbuf1); i++) {
180 if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
183 /* This does some fuzzy mode naming detection */
184 if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
185 if((rate <= 32) || (depth > 32)) {
186 j = rate; rate = depth; depth = j;
188 sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
190 sisfb_parm_rate = rate;
191 } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
192 sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
196 if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
197 sprintf(strbuf, "%ux%ux8", xres, yres);
200 sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
207 while(sisbios_mode[i].mode_no[0] != 0) {
208 if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
210 if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
211 sisbios_mode[i-1].mode_no[1] == 0x56 ||
212 sisbios_mode[i-1].mode_no[1] == 0x53)
215 if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
216 sisbios_mode[i-1].mode_no[1] == 0x5b)
219 sisfb_mode_idx = i - 1;
226 printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
230 static void __devinit
231 sisfb_get_vga_mode_from_kernel(void)
235 int mydepth = screen_info.lfb_depth;
237 if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
239 if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) &&
240 (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
241 (mydepth >= 8) && (mydepth <= 32) ) {
243 if(mydepth == 24) mydepth = 32;
245 sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
246 screen_info.lfb_height,
250 "sisfb: Using vga mode %s pre-set by kernel as default\n",
253 sisfb_search_mode(mymode, true);
261 sisfb_search_crt2type(const char *name)
265 /* We don't know the hardware specs yet and there is no ivideo */
267 if(name == NULL) return;
269 while(sis_crt2type[i].type_no != -1) {
270 if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
271 sisfb_crt2type = sis_crt2type[i].type_no;
272 sisfb_tvplug = sis_crt2type[i].tvplug_no;
273 sisfb_crt2flags = sis_crt2type[i].flags;
279 sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
280 sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
282 if(sisfb_crt2type < 0)
283 printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
287 sisfb_search_tvstd(const char *name)
291 /* We don't know the hardware specs yet and there is no ivideo */
296 while(sis_tvtype[i].type_no != -1) {
297 if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
298 sisfb_tvstd = sis_tvtype[i].type_no;
306 sisfb_search_specialtiming(const char *name)
311 /* We don't know the hardware specs yet and there is no ivideo */
316 if(!strnicmp(name, "none", 4)) {
317 sisfb_specialtiming = CUT_FORCENONE;
318 printk(KERN_DEBUG "sisfb: Special timing disabled\n");
320 while(mycustomttable[i].chipID != 0) {
321 if(!strnicmp(name,mycustomttable[i].optionName,
322 strlen(mycustomttable[i].optionName))) {
323 sisfb_specialtiming = mycustomttable[i].SpecialID;
325 printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
326 mycustomttable[i].vendorName,
327 mycustomttable[i].cardName,
328 mycustomttable[i].optionName);
334 printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
335 printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
337 while(mycustomttable[i].chipID != 0) {
338 printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
339 mycustomttable[i].optionName,
340 mycustomttable[i].vendorName,
341 mycustomttable[i].cardName);
348 /* ----------- Various detection routines ----------- */
350 static void __devinit
351 sisfb_detect_custom_timing(struct sis_video_info *ivideo)
353 unsigned char *biosver = NULL;
354 unsigned char *biosdate = NULL;
359 if(ivideo->SiS_Pr.UseROM) {
360 biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06;
361 biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c;
362 for(i = 0; i < 32768; i++)
363 chksum += ivideo->SiS_Pr.VirtualRomBase[i];
368 if( (mycustomttable[i].chipID == ivideo->chip) &&
369 ((!strlen(mycustomttable[i].biosversion)) ||
370 (ivideo->SiS_Pr.UseROM &&
371 (!strncmp(mycustomttable[i].biosversion, biosver,
372 strlen(mycustomttable[i].biosversion))))) &&
373 ((!strlen(mycustomttable[i].biosdate)) ||
374 (ivideo->SiS_Pr.UseROM &&
375 (!strncmp(mycustomttable[i].biosdate, biosdate,
376 strlen(mycustomttable[i].biosdate))))) &&
377 ((!mycustomttable[i].bioschksum) ||
378 (ivideo->SiS_Pr.UseROM &&
379 (mycustomttable[i].bioschksum == chksum))) &&
380 (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
381 (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
383 for(j = 0; j < 5; j++) {
384 if(mycustomttable[i].biosFootprintAddr[j]) {
385 if(ivideo->SiS_Pr.UseROM) {
386 if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
387 mycustomttable[i].biosFootprintData[j]) {
395 ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
396 printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
397 mycustomttable[i].vendorName,
398 mycustomttable[i].cardName);
399 printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
400 mycustomttable[i].optionName);
405 } while(mycustomttable[i].chipID);
408 static bool __devinit
409 sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
411 int i, j, xres, yres, refresh, index;
414 if(buffer[0] != 0x00 || buffer[1] != 0xff ||
415 buffer[2] != 0xff || buffer[3] != 0xff ||
416 buffer[4] != 0xff || buffer[5] != 0xff ||
417 buffer[6] != 0xff || buffer[7] != 0x00) {
418 printk(KERN_DEBUG "sisfb: Bad EDID header\n");
422 if(buffer[0x12] != 0x01) {
423 printk(KERN_INFO "sisfb: EDID version %d not supported\n",
428 monitor->feature = buffer[0x18];
430 if(!buffer[0x14] & 0x80) {
431 if(!(buffer[0x14] & 0x08)) {
433 "sisfb: WARNING: Monitor does not support separate syncs\n");
437 if(buffer[0x13] >= 0x01) {
438 /* EDID V1 rev 1 and 2: Search for monitor descriptor
443 if(buffer[j] == 0x00 && buffer[j + 1] == 0x00 &&
444 buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
445 buffer[j + 4] == 0x00) {
446 monitor->hmin = buffer[j + 7];
447 monitor->hmax = buffer[j + 8];
448 monitor->vmin = buffer[j + 5];
449 monitor->vmax = buffer[j + 6];
450 monitor->dclockmax = buffer[j + 9] * 10 * 1000;
451 monitor->datavalid = true;
458 if(!monitor->datavalid) {
459 /* Otherwise: Get a range from the list of supported
460 * Estabished Timings. This is not entirely accurate,
461 * because fixed frequency monitors are not supported
464 monitor->hmin = 65535; monitor->hmax = 0;
465 monitor->vmin = 65535; monitor->vmax = 0;
466 monitor->dclockmax = 0;
467 emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
468 for(i = 0; i < 13; i++) {
469 if(emodes & sisfb_ddcsmodes[i].mask) {
470 if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
471 if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
472 if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
473 if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
474 if(monitor->dclockmax < sisfb_ddcsmodes[i].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
478 for(i = 0; i < 8; i++) {
479 xres = (buffer[index] + 31) * 8;
480 switch(buffer[index + 1] & 0xc0) {
481 case 0xc0: yres = (xres * 9) / 16; break;
482 case 0x80: yres = (xres * 4) / 5; break;
483 case 0x40: yres = (xres * 3) / 4; break;
484 default: yres = xres; break;
486 refresh = (buffer[index + 1] & 0x3f) + 60;
487 if((xres >= 640) && (yres >= 480)) {
488 for(j = 0; j < 8; j++) {
489 if((xres == sisfb_ddcfmodes[j].x) &&
490 (yres == sisfb_ddcfmodes[j].y) &&
491 (refresh == sisfb_ddcfmodes[j].v)) {
492 if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
493 if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
494 if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
495 if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
496 if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d;
502 if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
503 monitor->datavalid = true;
507 return monitor->datavalid;
510 static void __devinit
511 sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, int crtno)
513 unsigned short temp, i, realcrtno = crtno;
514 unsigned char buffer[256];
516 monitor->datavalid = false;
519 if(ivideo->vbflags & CRT2_LCD) realcrtno = 1;
520 else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
524 if((ivideo->sisfb_crt1off) && (!crtno))
527 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
528 realcrtno, 0, &buffer[0], ivideo->vbflags2);
529 if((!temp) || (temp == 0xffff)) {
530 printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
533 printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
534 printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
536 (temp & 0x1a) ? "" : "[none of the supported]",
537 (temp & 0x02) ? "2 " : "",
538 (temp & 0x08) ? "D&P" : "",
539 (temp & 0x10) ? "FPDI-2" : "");
541 i = 3; /* Number of retrys */
543 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
544 realcrtno, 1, &buffer[0], ivideo->vbflags2);
545 } while((temp) && i--);
547 if(sisfb_interpret_edid(monitor, &buffer[0])) {
548 printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
549 monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
550 monitor->dclockmax / 1000);
552 printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
555 printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
558 printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
563 /* -------------- Mode validation --------------- */
566 sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
567 int mode_idx, int rate_idx, int rate)
570 unsigned int dclock, hsync;
572 if(!monitor->datavalid)
578 /* Skip for 320x200, 320x240, 640x400 */
579 switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
590 #ifdef CONFIG_FB_SIS_315
593 if(ivideo->sisvga_engine == SIS_315_VGA) return true;
597 if(rate < (monitor->vmin - 1))
599 if(rate > (monitor->vmax + 1))
602 if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
603 sisbios_mode[mode_idx].mode_no[ivideo->mni],
604 &htotal, &vtotal, rate_idx)) {
605 dclock = (htotal * vtotal * rate) / 1000;
606 if(dclock > (monitor->dclockmax + 1000))
608 hsync = dclock / htotal;
609 if(hsync < (monitor->hmin - 1))
611 if(hsync > (monitor->hmax + 1))
620 sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
622 u16 xres=0, yres, myres;
624 #ifdef CONFIG_FB_SIS_300
625 if(ivideo->sisvga_engine == SIS_300_VGA) {
626 if(!(sisbios_mode[myindex].chipset & MD_SIS300))
630 #ifdef CONFIG_FB_SIS_315
631 if(ivideo->sisvga_engine == SIS_315_VGA) {
632 if(!(sisbios_mode[myindex].chipset & MD_SIS315))
637 myres = sisbios_mode[myindex].yres;
639 switch(vbflags & VB_DISPTYPE_DISP2) {
642 xres = ivideo->lcdxres; yres = ivideo->lcdyres;
644 if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
645 (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
646 if(sisbios_mode[myindex].xres > xres)
652 if(ivideo->sisfb_fstn) {
653 if(sisbios_mode[myindex].xres == 320) {
655 switch(sisbios_mode[myindex].mode_no[1]) {
656 case 0x50: myindex = MODE_FSTN_8; break;
657 case 0x56: myindex = MODE_FSTN_16; break;
658 case 0x53: return -1;
664 if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
665 sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
666 ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
672 if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
673 sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
679 if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
680 sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
690 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
693 u16 xres = sisbios_mode[mode_idx].xres;
694 u16 yres = sisbios_mode[mode_idx].yres;
696 ivideo->rate_idx = 0;
697 while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
698 if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
699 if(sisfb_vrate[i].refresh == rate) {
700 ivideo->rate_idx = sisfb_vrate[i].idx;
702 } else if(sisfb_vrate[i].refresh > rate) {
703 if((sisfb_vrate[i].refresh - rate) <= 3) {
704 DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
705 rate, sisfb_vrate[i].refresh);
706 ivideo->rate_idx = sisfb_vrate[i].idx;
707 ivideo->refresh_rate = sisfb_vrate[i].refresh;
708 } else if(((rate - sisfb_vrate[i-1].refresh) <= 2)
709 && (sisfb_vrate[i].idx != 1)) {
710 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
711 rate, sisfb_vrate[i-1].refresh);
712 ivideo->rate_idx = sisfb_vrate[i-1].idx;
713 ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
716 } else if((rate - sisfb_vrate[i].refresh) <= 2) {
717 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
718 rate, sisfb_vrate[i].refresh);
719 ivideo->rate_idx = sisfb_vrate[i].idx;
725 if(ivideo->rate_idx > 0) {
726 return ivideo->rate_idx;
728 printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n",
735 sisfb_bridgeisslave(struct sis_video_info *ivideo)
739 if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
742 inSISIDXREG(SISPART1,0x00,P1_00);
743 if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
744 ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
752 sisfballowretracecrt1(struct sis_video_info *ivideo)
756 inSISIDXREG(SISCR,0x17,temp);
760 inSISIDXREG(SISSR,0x1f,temp);
768 sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
770 if(!sisfballowretracecrt1(ivideo))
773 if(inSISREG(SISINPSTAT) & 0x08)
780 sisfbwaitretracecrt1(struct sis_video_info *ivideo)
784 if(!sisfballowretracecrt1(ivideo))
788 while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog);
790 while((inSISREG(SISINPSTAT) & 0x08) && --watchdog);
794 sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
796 unsigned char temp, reg;
798 switch(ivideo->sisvga_engine) {
799 case SIS_300_VGA: reg = 0x25; break;
800 case SIS_315_VGA: reg = 0x30; break;
801 default: return false;
804 inSISIDXREG(SISPART1, reg, temp);
812 sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
814 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
815 if(!sisfb_bridgeisslave(ivideo)) {
816 return sisfbcheckvretracecrt2(ivideo);
819 return sisfbcheckvretracecrt1(ivideo);
823 sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
825 u8 idx, reg1, reg2, reg3, reg4;
828 (*vcount) = (*hcount) = 0;
830 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
832 ret |= (FB_VBLANK_HAVE_VSYNC |
833 FB_VBLANK_HAVE_HBLANK |
834 FB_VBLANK_HAVE_VBLANK |
835 FB_VBLANK_HAVE_VCOUNT |
836 FB_VBLANK_HAVE_HCOUNT);
837 switch(ivideo->sisvga_engine) {
838 case SIS_300_VGA: idx = 0x25; break;
840 case SIS_315_VGA: idx = 0x30; break;
842 inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */
843 inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */
844 inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */
845 inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */
846 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
847 if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
848 if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
849 (*vcount) = reg3 | ((reg4 & 0x70) << 4);
850 (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
852 } else if(sisfballowretracecrt1(ivideo)) {
854 ret |= (FB_VBLANK_HAVE_VSYNC |
855 FB_VBLANK_HAVE_VBLANK |
856 FB_VBLANK_HAVE_VCOUNT |
857 FB_VBLANK_HAVE_HCOUNT);
858 reg1 = inSISREG(SISINPSTAT);
859 if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
860 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
861 inSISIDXREG(SISCR,0x20,reg1);
862 inSISIDXREG(SISCR,0x1b,reg1);
863 inSISIDXREG(SISCR,0x1c,reg2);
864 inSISIDXREG(SISCR,0x1d,reg3);
865 (*vcount) = reg2 | ((reg3 & 0x07) << 8);
866 (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
873 sisfb_myblank(struct sis_video_info *ivideo, int blank)
875 u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
876 bool backlight = true;
879 case FB_BLANK_UNBLANK: /* on */
888 case FB_BLANK_NORMAL: /* blank */
897 case FB_BLANK_VSYNC_SUSPEND: /* no vsync */
906 case FB_BLANK_HSYNC_SUSPEND: /* no hsync */
915 case FB_BLANK_POWERDOWN: /* off */
928 if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
930 if( (!ivideo->sisfb_thismonitor.datavalid) ||
931 ((ivideo->sisfb_thismonitor.datavalid) &&
932 (ivideo->sisfb_thismonitor.feature & 0xe0))) {
934 if(ivideo->sisvga_engine == SIS_315_VGA) {
935 setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
938 if(!(sisfb_bridgeisslave(ivideo))) {
939 setSISIDXREG(SISSR, 0x01, ~0x20, sr01);
940 setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f);
946 if(ivideo->currentvbflags & CRT2_LCD) {
948 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
950 SiS_SiS30xBLOn(&ivideo->SiS_Pr);
952 SiS_SiS30xBLOff(&ivideo->SiS_Pr);
954 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
955 #ifdef CONFIG_FB_SIS_315
956 if(ivideo->vbflags2 & VB2_CHRONTEL) {
958 SiS_Chrontel701xBLOn(&ivideo->SiS_Pr);
960 SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
966 if(((ivideo->sisvga_engine == SIS_300_VGA) &&
967 (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
968 ((ivideo->sisvga_engine == SIS_315_VGA) &&
969 ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
970 setSISIDXREG(SISSR, 0x11, ~0x0c, sr11);
973 if(ivideo->sisvga_engine == SIS_300_VGA) {
974 if((ivideo->vbflags2 & VB2_30xB) &&
975 (!(ivideo->vbflags2 & VB2_30xBDH))) {
976 setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13);
978 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
979 if((ivideo->vbflags2 & VB2_30xB) &&
980 (!(ivideo->vbflags2 & VB2_30xBDH))) {
981 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
985 } else if(ivideo->currentvbflags & CRT2_VGA) {
987 if(ivideo->vbflags2 & VB2_30xB) {
988 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
996 /* ------------- Callbacks from init.c/init301.c -------------- */
998 #ifdef CONFIG_FB_SIS_300
1000 sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg)
1002 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1005 pci_read_config_dword(ivideo->nbridge, reg, &val);
1006 return (unsigned int)val;
1010 sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val)
1012 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1014 pci_write_config_dword(ivideo->nbridge, reg, (u32)val);
1018 sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg)
1020 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1023 if(!ivideo->lpcdev) return 0;
1025 pci_read_config_dword(ivideo->lpcdev, reg, &val);
1026 return (unsigned int)val;
1030 #ifdef CONFIG_FB_SIS_315
1032 sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val)
1034 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1036 pci_write_config_byte(ivideo->nbridge, reg, (u8)val);
1040 sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg)
1042 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1045 if(!ivideo->lpcdev) return 0;
1047 pci_read_config_word(ivideo->lpcdev, reg, &val);
1048 return (unsigned int)val;
1052 /* ----------- FBDev related routines for all series ----------- */
1055 sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
1057 return (var->bits_per_pixel == 8) ? 256 : 16;
1061 sisfb_set_vparms(struct sis_video_info *ivideo)
1063 switch(ivideo->video_bpp) {
1065 ivideo->DstColor = 0x0000;
1066 ivideo->SiS310_AccelDepth = 0x00000000;
1067 ivideo->video_cmap_len = 256;
1070 ivideo->DstColor = 0x8000;
1071 ivideo->SiS310_AccelDepth = 0x00010000;
1072 ivideo->video_cmap_len = 16;
1075 ivideo->DstColor = 0xC000;
1076 ivideo->SiS310_AccelDepth = 0x00020000;
1077 ivideo->video_cmap_len = 16;
1080 ivideo->video_cmap_len = 16;
1081 printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
1087 sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1089 int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3));
1091 if(maxyres > 32767) maxyres = 32767;
1097 sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1099 ivideo->video_linelength = var->xres_virtual * (var->bits_per_pixel >> 3);
1100 ivideo->scrnpitchCRT1 = ivideo->video_linelength;
1101 if(!(ivideo->currentvbflags & CRT1_LCDA)) {
1102 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1103 ivideo->scrnpitchCRT1 <<= 1;
1109 sisfb_set_pitch(struct sis_video_info *ivideo)
1111 bool isslavemode = false;
1112 unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
1113 unsigned short HDisplay2 = ivideo->video_linelength >> 3;
1115 if(sisfb_bridgeisslave(ivideo)) isslavemode = true;
1117 /* We need to set pitch for CRT1 if bridge is in slave mode, too */
1118 if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
1119 outSISIDXREG(SISCR,0x13,(HDisplay1 & 0xFF));
1120 setSISIDXREG(SISSR,0x0E,0xF0,(HDisplay1 >> 8));
1123 /* We must not set the pitch for CRT2 if bridge is in slave mode */
1124 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
1125 orSISIDXREG(SISPART1,ivideo->CRT2_write_enable,0x01);
1126 outSISIDXREG(SISPART1,0x07,(HDisplay2 & 0xFF));
1127 setSISIDXREG(SISPART1,0x09,0xF0,(HDisplay2 >> 8));
1132 sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1134 ivideo->video_cmap_len = sisfb_get_cmap_len(var);
1136 switch(var->bits_per_pixel) {
1138 var->red.offset = var->green.offset = var->blue.offset = 0;
1139 var->red.length = var->green.length = var->blue.length = 6;
1142 var->red.offset = 11;
1143 var->red.length = 5;
1144 var->green.offset = 5;
1145 var->green.length = 6;
1146 var->blue.offset = 0;
1147 var->blue.length = 5;
1148 var->transp.offset = 0;
1149 var->transp.length = 0;
1152 var->red.offset = 16;
1153 var->red.length = 8;
1154 var->green.offset = 8;
1155 var->green.length = 8;
1156 var->blue.offset = 0;
1157 var->blue.length = 8;
1158 var->transp.offset = 24;
1159 var->transp.length = 8;
1165 sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
1167 unsigned short modeno = ivideo->mode_no;
1169 /* >=2.6.12's fbcon clears the screen anyway */
1170 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
1171 if(!clrscrn) modeno |= 0x80;
1176 outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1178 sisfb_pre_setmode(ivideo);
1180 if(!SiSSetMode(&ivideo->SiS_Pr, modeno)) {
1181 printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
1185 outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1187 sisfb_post_setmode(ivideo);
1194 sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
1196 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1197 unsigned int htotal = 0, vtotal = 0;
1198 unsigned int drate = 0, hrate = 0;
1199 int found_mode = 0, ret;
1203 htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1205 vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1207 pixclock = var->pixclock;
1209 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1210 vtotal += var->yres;
1212 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1213 vtotal += var->yres;
1215 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1216 vtotal += var->yres;
1218 } else vtotal += var->yres;
1220 if(!(htotal) || !(vtotal)) {
1221 DPRINTK("sisfb: Invalid 'var' information\n");
1225 if(pixclock && htotal && vtotal) {
1226 drate = 1000000000 / pixclock;
1227 hrate = (drate * 1000) / htotal;
1228 ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1230 ivideo->refresh_rate = 60;
1233 old_mode = ivideo->sisfb_mode_idx;
1234 ivideo->sisfb_mode_idx = 0;
1236 while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) &&
1237 (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) {
1238 if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) &&
1239 (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) &&
1240 (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) {
1241 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1245 ivideo->sisfb_mode_idx++;
1249 ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
1250 ivideo->sisfb_mode_idx, ivideo->currentvbflags);
1251 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1253 ivideo->sisfb_mode_idx = -1;
1256 if(ivideo->sisfb_mode_idx < 0) {
1257 printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres,
1258 var->yres, var->bits_per_pixel);
1259 ivideo->sisfb_mode_idx = old_mode;
1263 if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
1264 ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
1265 ivideo->refresh_rate = 60;
1269 /* If acceleration to be used? Need to know
1270 * before pre/post_set_mode()
1273 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
1274 #ifdef STUPID_ACCELF_TEXT_SHIT
1275 if(var->accel_flags & FB_ACCELF_TEXT) {
1276 info->flags &= ~FBINFO_HWACCEL_DISABLED;
1278 info->flags |= FBINFO_HWACCEL_DISABLED;
1281 if(!(info->flags & FBINFO_HWACCEL_DISABLED)) ivideo->accel = -1;
1283 if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
1286 if((ret = sisfb_set_mode(ivideo, 1))) {
1290 ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
1291 ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
1292 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
1294 sisfb_calc_pitch(ivideo, var);
1295 sisfb_set_pitch(ivideo);
1297 sisfb_set_vparms(ivideo);
1299 ivideo->current_width = ivideo->video_width;
1300 ivideo->current_height = ivideo->video_height;
1301 ivideo->current_bpp = ivideo->video_bpp;
1302 ivideo->current_htotal = htotal;
1303 ivideo->current_vtotal = vtotal;
1304 ivideo->current_linelength = ivideo->video_linelength;
1305 ivideo->current_pixclock = var->pixclock;
1306 ivideo->current_refresh_rate = ivideo->refresh_rate;
1307 ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
1314 sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
1316 outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1318 outSISIDXREG(SISCR, 0x0D, base & 0xFF);
1319 outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF);
1320 outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF);
1321 if(ivideo->sisvga_engine == SIS_315_VGA) {
1322 setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
1327 sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
1329 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1330 orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
1331 outSISIDXREG(SISPART1, 0x06, (base & 0xFF));
1332 outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF));
1333 outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF));
1334 if(ivideo->sisvga_engine == SIS_315_VGA) {
1335 setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1341 sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1343 if(var->xoffset > (var->xres_virtual - var->xres)) {
1346 if(var->yoffset > (var->yres_virtual - var->yres)) {
1350 ivideo->current_base = (var->yoffset * var->xres_virtual) + var->xoffset;
1352 /* calculate base bpp dep. */
1353 switch(var->bits_per_pixel) {
1357 ivideo->current_base >>= 1;
1361 ivideo->current_base >>= 2;
1365 ivideo->current_base += (ivideo->video_offset >> 2);
1367 sisfb_set_base_CRT1(ivideo, ivideo->current_base);
1368 sisfb_set_base_CRT2(ivideo, ivideo->current_base);
1374 sisfb_open(struct fb_info *info, int user)
1380 sisfb_release(struct fb_info *info, int user)
1386 sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
1387 unsigned transp, struct fb_info *info)
1389 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1391 if(regno >= sisfb_get_cmap_len(&info->var))
1394 switch(info->var.bits_per_pixel) {
1396 outSISREG(SISDACA, regno);
1397 outSISREG(SISDACD, (red >> 10));
1398 outSISREG(SISDACD, (green >> 10));
1399 outSISREG(SISDACD, (blue >> 10));
1400 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1401 outSISREG(SISDAC2A, regno);
1402 outSISREG(SISDAC2D, (red >> 8));
1403 outSISREG(SISDAC2D, (green >> 8));
1404 outSISREG(SISDAC2D, (blue >> 8));
1408 ((u32 *)(info->pseudo_palette))[regno] =
1410 ((green & 0xfc00) >> 5) |
1411 ((blue & 0xf800) >> 11);
1417 ((u32 *)(info->pseudo_palette))[regno] =
1418 (red << 16) | (green << 8) | (blue);
1425 sisfb_set_par(struct fb_info *info)
1429 if((err = sisfb_do_set_var(&info->var, 1, info)))
1432 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
1433 sisfb_get_fix(&info->fix, info->currcon, info);
1435 sisfb_get_fix(&info->fix, -1, info);
1441 sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1443 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1444 unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
1445 unsigned int drate = 0, hrate = 0, maxyres;
1447 int refresh_rate, search_idx, tidx;
1448 bool recalc_clock = false;
1451 htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1453 vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1455 pixclock = var->pixclock;
1457 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1458 vtotal += var->yres;
1460 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1461 vtotal += var->yres;
1463 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1464 vtotal += var->yres;
1467 vtotal += var->yres;
1469 if(!(htotal) || !(vtotal)) {
1470 SISFAIL("sisfb: no valid timing data");
1474 while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
1475 (sisbios_mode[search_idx].xres <= var->xres) ) {
1476 if( (sisbios_mode[search_idx].xres == var->xres) &&
1477 (sisbios_mode[search_idx].yres == var->yres) &&
1478 (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1479 if((tidx = sisfb_validate_mode(ivideo, search_idx,
1480 ivideo->currentvbflags)) > 0) {
1491 while(sisbios_mode[search_idx].mode_no[0] != 0) {
1492 if( (var->xres <= sisbios_mode[search_idx].xres) &&
1493 (var->yres <= sisbios_mode[search_idx].yres) &&
1494 (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
1495 if((tidx = sisfb_validate_mode(ivideo,search_idx,
1496 ivideo->currentvbflags)) > 0) {
1506 "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
1507 var->xres, var->yres, var->bits_per_pixel,
1508 sisbios_mode[search_idx].xres,
1509 sisbios_mode[search_idx].yres,
1510 var->bits_per_pixel);
1511 var->xres = sisbios_mode[search_idx].xres;
1512 var->yres = sisbios_mode[search_idx].yres;
1515 "sisfb: Failed to find supported mode near %dx%dx%d\n",
1516 var->xres, var->yres, var->bits_per_pixel);
1521 if( ((ivideo->vbflags2 & VB2_LVDS) ||
1522 ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
1523 (var->bits_per_pixel == 8) ) {
1524 /* Slave modes on LVDS and 301B-DH */
1526 recalc_clock = true;
1527 } else if( (ivideo->current_htotal == htotal) &&
1528 (ivideo->current_vtotal == vtotal) &&
1529 (ivideo->current_pixclock == pixclock) ) {
1530 /* x=x & y=y & c=c -> assume depth change */
1531 drate = 1000000000 / pixclock;
1532 hrate = (drate * 1000) / htotal;
1533 refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1534 } else if( ( (ivideo->current_htotal != htotal) ||
1535 (ivideo->current_vtotal != vtotal) ) &&
1536 (ivideo->current_pixclock == var->pixclock) ) {
1537 /* x!=x | y!=y & c=c -> invalid pixclock */
1538 if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
1540 ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
1541 } else if(ivideo->sisfb_parm_rate != -1) {
1542 /* Sic, sisfb_parm_rate - want to know originally desired rate here */
1543 refresh_rate = ivideo->sisfb_parm_rate;
1547 recalc_clock = true;
1548 } else if((pixclock) && (htotal) && (vtotal)) {
1549 drate = 1000000000 / pixclock;
1550 hrate = (drate * 1000) / htotal;
1551 refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1552 } else if(ivideo->current_refresh_rate) {
1553 refresh_rate = ivideo->current_refresh_rate;
1554 recalc_clock = true;
1557 recalc_clock = true;
1560 myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
1562 /* Eventually recalculate timing and clock */
1564 if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
1565 var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
1566 sisbios_mode[search_idx].mode_no[ivideo->mni],
1568 sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr,
1569 sisbios_mode[search_idx].mode_no[ivideo->mni],
1571 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1572 var->pixclock <<= 1;
1576 if(ivideo->sisfb_thismonitor.datavalid) {
1577 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
1578 myrateindex, refresh_rate)) {
1580 "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1584 /* Adapt RGB settings */
1585 sisfb_bpp_to_var(ivideo, var);
1587 /* Sanity check for offsets */
1588 if(var->xoffset < 0) var->xoffset = 0;
1589 if(var->yoffset < 0) var->yoffset = 0;
1591 if(var->xres > var->xres_virtual)
1592 var->xres_virtual = var->xres;
1594 if(ivideo->sisfb_ypan) {
1595 maxyres = sisfb_calc_maxyres(ivideo, var);
1596 if(ivideo->sisfb_max) {
1597 var->yres_virtual = maxyres;
1599 if(var->yres_virtual > maxyres) {
1600 var->yres_virtual = maxyres;
1603 if(var->yres_virtual <= var->yres) {
1604 var->yres_virtual = var->yres;
1607 if(var->yres != var->yres_virtual) {
1608 var->yres_virtual = var->yres;
1614 /* Truncate offsets to maximum if too high */
1615 if(var->xoffset > var->xres_virtual - var->xres) {
1616 var->xoffset = var->xres_virtual - var->xres - 1;
1619 if(var->yoffset > var->yres_virtual - var->yres) {
1620 var->yoffset = var->yres_virtual - var->yres - 1;
1623 /* Set everything else to 0 */
1624 var->red.msb_right =
1625 var->green.msb_right =
1626 var->blue.msb_right =
1627 var->transp.offset =
1628 var->transp.length =
1629 var->transp.msb_right = 0;
1635 sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
1637 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1640 if(var->xoffset > (var->xres_virtual - var->xres))
1643 if(var->yoffset > (var->yres_virtual - var->yres))
1646 if(var->vmode & FB_VMODE_YWRAP)
1649 if(var->xoffset + info->var.xres > info->var.xres_virtual ||
1650 var->yoffset + info->var.yres > info->var.yres_virtual)
1653 if((err = sisfb_pan_var(ivideo, var)) < 0)
1656 info->var.xoffset = var->xoffset;
1657 info->var.yoffset = var->yoffset;
1663 sisfb_blank(int blank, struct fb_info *info)
1665 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1667 return sisfb_myblank(ivideo, blank);
1670 /* ----------- FBDev related routines for all series ---------- */
1672 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
1673 static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
1676 static int sisfb_ioctl(struct inode *inode, struct file *file,
1677 unsigned int cmd, unsigned long arg,
1678 struct fb_info *info)
1681 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1682 struct sis_memreq sismemreq;
1683 struct fb_vblank sisvbblank;
1688 u32 __user *argp = (u32 __user *)arg;
1692 if(!capable(CAP_SYS_RAWIO))
1695 if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))
1698 sis_malloc(&sismemreq);
1700 if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
1701 sis_free((u32)sismemreq.offset);
1707 if(!capable(CAP_SYS_RAWIO))
1710 if(get_user(gpu32, argp))
1716 case FBIOGET_VBLANK:
1717 sisvbblank.count = 0;
1718 sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
1720 if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))
1725 case SISFB_GET_INFO_SIZE:
1726 return put_user(sizeof(struct sisfb_info), argp);
1728 case SISFB_GET_INFO_OLD:
1729 if(ivideo->warncount++ < 10)
1731 "sisfb: Deprecated ioctl call received - update your application!\n");
1732 case SISFB_GET_INFO: /* For communication with X driver */
1733 ivideo->sisfb_infoblock.sisfb_id = SISFB_ID;
1734 ivideo->sisfb_infoblock.sisfb_version = VER_MAJOR;
1735 ivideo->sisfb_infoblock.sisfb_revision = VER_MINOR;
1736 ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;
1737 ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;
1738 ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;
1739 ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;
1740 ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;
1741 if(ivideo->modechanged) {
1742 ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;
1744 ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;
1746 ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;
1747 ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;
1748 ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;
1749 ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;
1750 ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;
1751 ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;
1752 ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;
1753 ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;
1754 ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;
1755 ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;
1756 ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
1757 ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
1758 ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
1759 ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
1760 ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
1761 ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
1762 ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
1763 ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
1764 ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
1765 ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
1766 ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;
1767 ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;
1768 ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;
1769 ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;
1770 ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;
1771 ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;
1772 ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;
1773 ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;
1775 if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,
1776 sizeof(ivideo->sisfb_infoblock)))
1781 case SISFB_GET_VBRSTATUS_OLD:
1782 if(ivideo->warncount++ < 10)
1784 "sisfb: Deprecated ioctl call received - update your application!\n");
1785 case SISFB_GET_VBRSTATUS:
1786 if(sisfb_CheckVBRetrace(ivideo))
1787 return put_user((u32)1, argp);
1789 return put_user((u32)0, argp);
1791 case SISFB_GET_AUTOMAXIMIZE_OLD:
1792 if(ivideo->warncount++ < 10)
1794 "sisfb: Deprecated ioctl call received - update your application!\n");
1795 case SISFB_GET_AUTOMAXIMIZE:
1796 if(ivideo->sisfb_max)
1797 return put_user((u32)1, argp);
1799 return put_user((u32)0, argp);
1801 case SISFB_SET_AUTOMAXIMIZE_OLD:
1802 if(ivideo->warncount++ < 10)
1804 "sisfb: Deprecated ioctl call received - update your application!\n");
1805 case SISFB_SET_AUTOMAXIMIZE:
1806 if(get_user(gpu32, argp))
1809 ivideo->sisfb_max = (gpu32) ? 1 : 0;
1812 case SISFB_SET_TVPOSOFFSET:
1813 if(get_user(gpu32, argp))
1816 sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
1817 sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
1820 case SISFB_GET_TVPOSOFFSET:
1821 return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
1825 if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,
1826 sizeof(struct sisfb_cmd)))
1829 sisfb_handle_command(ivideo, &ivideo->sisfb_command);
1831 if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,
1832 sizeof(struct sisfb_cmd)))
1837 case SISFB_SET_LOCK:
1838 if(get_user(gpu32, argp))
1841 ivideo->sisfblocked = (gpu32) ? 1 : 0;
1845 #ifdef SIS_NEW_CONFIG_COMPAT
1846 return -ENOIOCTLCMD;
1855 sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
1857 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1859 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1861 strcpy(fix->id, ivideo->myid);
1863 fix->smem_start = ivideo->video_base + ivideo->video_offset;
1864 fix->smem_len = ivideo->sisfb_mem;
1865 fix->type = FB_TYPE_PACKED_PIXELS;
1867 fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
1869 fix->ypanstep = (ivideo->sisfb_ypan) ? 1 : 0;
1871 fix->line_length = ivideo->video_linelength;
1872 fix->mmio_start = ivideo->mmio_base;
1873 fix->mmio_len = ivideo->mmio_size;
1874 if(ivideo->sisvga_engine == SIS_300_VGA) {
1875 fix->accel = FB_ACCEL_SIS_GLAMOUR;
1876 } else if((ivideo->chip == SIS_330) ||
1877 (ivideo->chip == SIS_760) ||
1878 (ivideo->chip == SIS_761)) {
1879 fix->accel = FB_ACCEL_SIS_XABRE;
1880 } else if(ivideo->chip == XGI_20) {
1881 fix->accel = FB_ACCEL_XGI_VOLARI_Z;
1882 } else if(ivideo->chip >= XGI_40) {
1883 fix->accel = FB_ACCEL_XGI_VOLARI_V;
1885 fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
1891 /* ---------------- fb_ops structures ----------------- */
1893 static struct fb_ops sisfb_ops = {
1894 .owner = THIS_MODULE,
1895 .fb_open = sisfb_open,
1896 .fb_release = sisfb_release,
1897 .fb_check_var = sisfb_check_var,
1898 .fb_set_par = sisfb_set_par,
1899 .fb_setcolreg = sisfb_setcolreg,
1900 .fb_pan_display = sisfb_pan_display,
1901 .fb_blank = sisfb_blank,
1902 .fb_fillrect = fbcon_sis_fillrect,
1903 .fb_copyarea = fbcon_sis_copyarea,
1904 .fb_imageblit = cfb_imageblit,
1905 #ifdef CONFIG_FB_SOFT_CURSOR
1906 .fb_cursor = soft_cursor,
1908 .fb_sync = fbcon_sis_sync,
1909 #ifdef SIS_NEW_CONFIG_COMPAT
1910 .fb_compat_ioctl= sisfb_ioctl,
1912 .fb_ioctl = sisfb_ioctl
1915 /* ---------------- Chip generation dependent routines ---------------- */
1917 static struct pci_dev * __devinit
1918 sisfb_get_northbridge(int basechipid)
1920 struct pci_dev *pdev = NULL;
1921 int nbridgenum, nbridgeidx, i;
1922 static const unsigned short nbridgeids[] = {
1923 PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */
1924 PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */
1925 PCI_DEVICE_ID_SI_730,
1926 PCI_DEVICE_ID_SI_550, /* for SiS 550 VGA */
1927 PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */
1928 PCI_DEVICE_ID_SI_651,
1929 PCI_DEVICE_ID_SI_740,
1930 PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760/761 VGA */
1931 PCI_DEVICE_ID_SI_741,
1932 PCI_DEVICE_ID_SI_660,
1933 PCI_DEVICE_ID_SI_760,
1934 PCI_DEVICE_ID_SI_761
1937 switch(basechipid) {
1938 #ifdef CONFIG_FB_SIS_300
1939 case SIS_540: nbridgeidx = 0; nbridgenum = 1; break;
1940 case SIS_630: nbridgeidx = 1; nbridgenum = 2; break;
1942 #ifdef CONFIG_FB_SIS_315
1943 case SIS_550: nbridgeidx = 3; nbridgenum = 1; break;
1944 case SIS_650: nbridgeidx = 4; nbridgenum = 3; break;
1945 case SIS_660: nbridgeidx = 7; nbridgenum = 5; break;
1947 default: return NULL;
1949 for(i = 0; i < nbridgenum; i++) {
1950 if((pdev = pci_get_device(PCI_VENDOR_ID_SI,
1951 nbridgeids[nbridgeidx+i], NULL)))
1957 static int __devinit
1958 sisfb_get_dram_size(struct sis_video_info *ivideo)
1960 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1964 ivideo->video_size = 0;
1965 ivideo->UMAsize = ivideo->LFBsize = 0;
1967 switch(ivideo->chip) {
1968 #ifdef CONFIG_FB_SIS_300
1970 inSISIDXREG(SISSR, 0x14, reg);
1971 ivideo->video_size = ((reg & 0x3F) + 1) << 20;
1976 if(!ivideo->nbridge)
1978 pci_read_config_byte(ivideo->nbridge, 0x63, ®);
1979 ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
1982 #ifdef CONFIG_FB_SIS_315
1986 inSISIDXREG(SISSR, 0x14, reg);
1987 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
1988 switch((reg >> 2) & 0x03) {
1991 ivideo->video_size <<= 1;
1994 ivideo->video_size += (ivideo->video_size/2);
1998 inSISIDXREG(SISSR, 0x14, reg);
1999 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2000 if(reg & 0x0c) ivideo->video_size <<= 1;
2005 inSISIDXREG(SISSR, 0x14, reg);
2006 ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
2010 inSISIDXREG(SISCR, 0x79, reg);
2011 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2016 inSISIDXREG(SISCR, 0x79, reg);
2017 reg = (reg & 0xf0) >> 4;
2019 ivideo->video_size = (1 << reg) << 20;
2020 ivideo->UMAsize = ivideo->video_size;
2022 inSISIDXREG(SISCR, 0x78, reg);
2026 ivideo->LFBsize = (32 << 20);
2028 ivideo->LFBsize = (64 << 20);
2030 ivideo->video_size += ivideo->LFBsize;
2036 inSISIDXREG(SISSR, 0x14, reg);
2037 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2038 if(ivideo->chip != XGI_20) {
2039 reg = (reg & 0x0c) >> 2;
2040 if(ivideo->revision_id == 2) {
2041 if(reg & 0x01) reg = 0x02;
2044 if(reg == 0x02) ivideo->video_size <<= 1;
2045 else if(reg == 0x03) ivideo->video_size <<= 2;
2055 /* -------------- video bridge device detection --------------- */
2057 static void __devinit
2058 sisfb_detect_VB_connect(struct sis_video_info *ivideo)
2062 /* No CRT2 on XGI Z7 */
2063 if(ivideo->chip == XGI_20) {
2064 ivideo->sisfb_crt1off = 0;
2068 #ifdef CONFIG_FB_SIS_300
2069 if(ivideo->sisvga_engine == SIS_300_VGA) {
2070 inSISIDXREG(SISSR, 0x17, temp);
2071 if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
2072 /* PAL/NTSC is stored on SR16 on such machines */
2073 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
2074 inSISIDXREG(SISSR, 0x16, temp);
2076 ivideo->vbflags |= TV_PAL;
2078 ivideo->vbflags |= TV_NTSC;
2084 inSISIDXREG(SISCR, 0x32, cr32);
2086 if(cr32 & SIS_CRT1) {
2087 ivideo->sisfb_crt1off = 0;
2089 ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0;
2092 ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
2094 if(cr32 & SIS_VB_TV) ivideo->vbflags |= CRT2_TV;
2095 if(cr32 & SIS_VB_LCD) ivideo->vbflags |= CRT2_LCD;
2096 if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA;
2098 /* Check given parms for hardware compatibility.
2099 * (Cannot do this in the search_xx routines since we don't
2100 * know what hardware we are running on then)
2103 if(ivideo->chip != SIS_550) {
2104 ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0;
2107 if(ivideo->sisfb_tvplug != -1) {
2108 if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2109 (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) {
2110 if(ivideo->sisfb_tvplug & TV_YPBPR) {
2111 ivideo->sisfb_tvplug = -1;
2112 printk(KERN_ERR "sisfb: YPbPr not supported\n");
2116 if(ivideo->sisfb_tvplug != -1) {
2117 if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2118 (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) {
2119 if(ivideo->sisfb_tvplug & TV_HIVISION) {
2120 ivideo->sisfb_tvplug = -1;
2121 printk(KERN_ERR "sisfb: HiVision not supported\n");
2125 if(ivideo->sisfb_tvstd != -1) {
2126 if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
2127 (!((ivideo->sisvga_engine == SIS_315_VGA) &&
2128 (ivideo->vbflags2 & VB2_CHRONTEL))) ) {
2129 if(ivideo->sisfb_tvstd & (TV_PALN | TV_PALN | TV_NTSCJ)) {
2130 ivideo->sisfb_tvstd = -1;
2131 printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
2136 /* Detect/set TV plug & type */
2137 if(ivideo->sisfb_tvplug != -1) {
2138 ivideo->vbflags |= ivideo->sisfb_tvplug;
2140 if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
2141 else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION;
2142 else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART;
2144 if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO;
2145 if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
2149 if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) {
2150 if(ivideo->sisfb_tvstd != -1) {
2151 ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ);
2152 ivideo->vbflags |= ivideo->sisfb_tvstd;
2154 if(ivideo->vbflags & TV_SCART) {
2155 ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ);
2156 ivideo->vbflags |= TV_PAL;
2158 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
2159 if(ivideo->sisvga_engine == SIS_300_VGA) {
2160 inSISIDXREG(SISSR, 0x38, temp);
2161 if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2162 else ivideo->vbflags |= TV_NTSC;
2163 } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
2164 inSISIDXREG(SISSR, 0x38, temp);
2165 if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2166 else ivideo->vbflags |= TV_NTSC;
2168 inSISIDXREG(SISCR, 0x79, temp);
2169 if(temp & 0x20) ivideo->vbflags |= TV_PAL;
2170 else ivideo->vbflags |= TV_NTSC;
2175 /* Copy forceCRT1 option to CRT1off if option is given */
2176 if(ivideo->sisfb_forcecrt1 != -1) {
2177 ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
2181 /* ------------------ Sensing routines ------------------ */
2183 static bool __devinit
2184 sisfb_test_DDC1(struct sis_video_info *ivideo)
2189 old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
2191 if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
2193 return (count != -1);
2196 static void __devinit
2197 sisfb_sense_crt1(struct sis_video_info *ivideo)
2199 bool mustwait = false;
2201 #ifdef CONFIG_FB_SIS_315
2207 inSISIDXREG(SISSR,0x1F,sr1F);
2208 orSISIDXREG(SISSR,0x1F,0x04);
2209 andSISIDXREG(SISSR,0x1F,0x3F);
2210 if(sr1F & 0xc0) mustwait = true;
2212 #ifdef CONFIG_FB_SIS_315
2213 if(ivideo->sisvga_engine == SIS_315_VGA) {
2214 inSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,cr63);
2216 andSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF);
2220 inSISIDXREG(SISCR,0x17,cr17);
2223 orSISIDXREG(SISCR,0x17,0x80);
2225 outSISIDXREG(SISSR, 0x00, 0x01);
2226 outSISIDXREG(SISSR, 0x00, 0x03);
2230 for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo);
2233 #ifdef CONFIG_FB_SIS_315
2234 if(ivideo->chip >= SIS_330) {
2235 andSISIDXREG(SISCR,0x32,~0x20);
2236 if(ivideo->chip >= SIS_340) {
2237 outSISIDXREG(SISCR, 0x57, 0x4a);
2239 outSISIDXREG(SISCR, 0x57, 0x5f);
2241 orSISIDXREG(SISCR, 0x53, 0x02);
2242 while((inSISREG(SISINPSTAT)) & 0x01) break;
2243 while(!((inSISREG(SISINPSTAT)) & 0x01)) break;
2244 if((inSISREG(SISMISCW)) & 0x10) temp = 1;
2245 andSISIDXREG(SISCR, 0x53, 0xfd);
2246 andSISIDXREG(SISCR, 0x57, 0x00);
2250 if(temp == 0xffff) {
2253 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2254 ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
2255 } while(((temp == 0) || (temp == 0xffff)) && i--);
2257 if((temp == 0) || (temp == 0xffff)) {
2258 if(sisfb_test_DDC1(ivideo)) temp = 1;
2262 if((temp) && (temp != 0xffff)) {
2263 orSISIDXREG(SISCR,0x32,0x20);
2266 #ifdef CONFIG_FB_SIS_315
2267 if(ivideo->sisvga_engine == SIS_315_VGA) {
2268 setSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF,cr63);
2272 setSISIDXREG(SISCR,0x17,0x7F,cr17);
2274 outSISIDXREG(SISSR,0x1F,sr1F);
2277 /* Determine and detect attached devices on SiS30x */
2278 static void __devinit
2279 SiS_SenseLCD(struct sis_video_info *ivideo)
2281 unsigned char buffer[256];
2282 unsigned short temp, realcrtno, i;
2283 u8 reg, cr37 = 0, paneltype = 0;
2286 ivideo->SiS_Pr.PanelSelfDetected = false;
2288 /* LCD detection only for TMDS bridges */
2289 if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
2291 if(ivideo->vbflags2 & VB2_30xBDH)
2294 /* If LCD already set up by BIOS, skip it */
2295 inSISIDXREG(SISCR, 0x32, reg);
2300 if(ivideo->SiS_Pr.DDCPortMixup)
2303 /* Check DDC capabilities */
2304 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
2305 realcrtno, 0, &buffer[0], ivideo->vbflags2);
2307 if((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
2311 i = 3; /* Number of retrys */
2313 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2314 ivideo->sisvga_engine, realcrtno, 1,
2315 &buffer[0], ivideo->vbflags2);
2316 } while((temp) && i--);
2321 /* No digital device */
2322 if(!(buffer[0x14] & 0x80))
2325 /* First detailed timing preferred timing? */
2326 if(!(buffer[0x18] & 0x02))
2329 xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
2330 yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
2342 if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
2353 if((buffer[0x47] & 0x18) == 0x18)
2354 cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2358 outSISIDXREG(SISCR, 0x36, paneltype);
2360 setSISIDXREG(SISCR, 0x37, 0x0c, cr37);
2361 orSISIDXREG(SISCR, 0x32, 0x08);
2363 ivideo->SiS_Pr.PanelSelfDetected = true;
2366 static int __devinit
2367 SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
2369 int temp, mytest, result, i, j;
2371 for(j = 0; j < 10; j++) {
2373 for(i = 0; i < 3; i++) {
2375 outSISIDXREG(SISPART4,0x11,(type & 0x00ff));
2376 temp = (type >> 8) | (mytest & 0x00ff);
2377 setSISIDXREG(SISPART4,0x10,0xe0,temp);
2378 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
2381 inSISIDXREG(SISPART4,0x03,temp);
2384 if(temp == mytest) result++;
2386 outSISIDXREG(SISPART4,0x11,0x00);
2387 andSISIDXREG(SISPART4,0x10,0xe0);
2388 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
2391 if((result == 0) || (result >= 2)) break;
2396 static void __devinit
2397 SiS_Sense30x(struct sis_video_info *ivideo)
2399 u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
2400 u16 svhs=0, svhs_c=0;
2401 u16 cvbs=0, cvbs_c=0;
2402 u16 vga2=0, vga2_c=0;
2404 char stdstr[] = "sisfb: Detected";
2405 char tvstr[] = "TV connected to";
2407 if(ivideo->vbflags2 & VB2_301) {
2408 svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
2409 inSISIDXREG(SISPART4,0x01,myflag);
2411 svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
2413 } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) {
2414 svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
2415 } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) {
2416 svhs = 0x0200; cvbs = 0x0100;
2417 } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
2418 svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
2422 vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
2423 if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
2424 svhs_c = 0x0408; cvbs_c = 0x0808;
2428 if(ivideo->haveXGIROM) {
2429 biosflag = ivideo->bios_abase[0x58] & 0x03;
2430 } else if(ivideo->newrom) {
2431 if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01;
2432 } else if(ivideo->sisvga_engine == SIS_300_VGA) {
2433 if(ivideo->bios_abase) {
2434 biosflag = ivideo->bios_abase[0xfe] & 0x03;
2438 if(ivideo->chip == SIS_300) {
2439 inSISIDXREG(SISSR,0x3b,myflag);
2440 if(!(myflag & 0x01)) vga2 = vga2_c = 0;
2443 if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) {
2447 inSISIDXREG(SISSR,0x1e,backupSR_1e);
2448 orSISIDXREG(SISSR,0x1e,0x20);
2450 inSISIDXREG(SISPART4,0x0d,backupP4_0d);
2451 if(ivideo->vbflags2 & VB2_30xC) {
2452 setSISIDXREG(SISPART4,0x0d,~0x07,0x01);
2454 orSISIDXREG(SISPART4,0x0d,0x04);
2456 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2458 inSISIDXREG(SISPART2,0x00,backupP2_00);
2459 outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc));
2461 inSISIDXREG(SISPART2,0x4d,backupP2_4d);
2462 if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
2463 outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10));
2466 if(!(ivideo->vbflags2 & VB2_30xCLV)) {
2467 SISDoSense(ivideo, 0, 0);
2470 andSISIDXREG(SISCR, 0x32, ~0x14);
2472 if(vga2_c || vga2) {
2473 if(SISDoSense(ivideo, vga2, vga2_c)) {
2474 if(biosflag & 0x01) {
2475 printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
2476 orSISIDXREG(SISCR, 0x32, 0x04);
2478 printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
2479 orSISIDXREG(SISCR, 0x32, 0x10);
2484 andSISIDXREG(SISCR, 0x32, 0x3f);
2486 if(ivideo->vbflags2 & VB2_30xCLV) {
2487 orSISIDXREG(SISPART4,0x0d,0x04);
2490 if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
2491 outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10));
2492 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2493 if((result = SISDoSense(ivideo, svhs, 0x0604))) {
2494 if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
2495 printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
2496 orSISIDXREG(SISCR,0x32,0x80);
2499 outSISIDXREG(SISPART2,0x4d,backupP2_4d);
2502 andSISIDXREG(SISCR, 0x32, ~0x03);
2504 if(!(ivideo->vbflags & TV_YPBPR)) {
2505 if((result = SISDoSense(ivideo, svhs, svhs_c))) {
2506 printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
2507 orSISIDXREG(SISCR, 0x32, 0x02);
2509 if((biosflag & 0x02) || (!result)) {
2510 if(SISDoSense(ivideo, cvbs, cvbs_c)) {
2511 printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
2512 orSISIDXREG(SISCR, 0x32, 0x01);
2517 SISDoSense(ivideo, 0, 0);
2519 outSISIDXREG(SISPART2,0x00,backupP2_00);
2520 outSISIDXREG(SISPART4,0x0d,backupP4_0d);
2521 outSISIDXREG(SISSR,0x1e,backupSR_1e);
2523 if(ivideo->vbflags2 & VB2_30xCLV) {
2524 inSISIDXREG(SISPART2,0x00,biosflag);
2525 if(biosflag & 0x20) {
2526 for(myflag = 2; myflag > 0; myflag--) {
2528 outSISIDXREG(SISPART2,0x00,biosflag);
2533 outSISIDXREG(SISPART2,0x00,backupP2_00);
2536 /* Determine and detect attached TV's on Chrontel */
2537 static void __devinit
2538 SiS_SenseCh(struct sis_video_info *ivideo)
2540 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2542 char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
2544 #ifdef CONFIG_FB_SIS_300
2545 unsigned char test[3];
2549 if(ivideo->chip < SIS_315H) {
2551 #ifdef CONFIG_FB_SIS_300
2552 ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1; /* Chrontel 700x */
2553 SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c); /* Set general purpose IO for Chrontel communication */
2554 SiS_DDC2Delay(&ivideo->SiS_Pr, 1000);
2555 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2556 /* See Chrontel TB31 for explanation */
2557 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2558 if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
2559 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b);
2560 SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2562 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2563 if(temp2 != temp1) temp1 = temp2;
2565 if((temp1 >= 0x22) && (temp1 <= 0x50)) {
2566 /* Read power status */
2567 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2568 if((temp1 & 0x03) != 0x03) {
2569 /* Power all outputs */
2570 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b);
2571 SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2573 /* Sense connected TV devices */
2574 for(i = 0; i < 3; i++) {
2575 SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01);
2576 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2577 SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00);
2578 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2579 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
2580 if(!(temp1 & 0x08)) test[i] = 0x02;
2581 else if(!(temp1 & 0x02)) test[i] = 0x01;
2583 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2586 if(test[0] == test[1]) temp1 = test[0];
2587 else if(test[0] == test[2]) temp1 = test[0];
2588 else if(test[1] == test[2]) temp1 = test[1];
2591 "sisfb: TV detection unreliable - test results varied\n");
2595 printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2596 ivideo->vbflags |= TV_SVIDEO;
2597 orSISIDXREG(SISCR, 0x32, 0x02);
2598 andSISIDXREG(SISCR, 0x32, ~0x05);
2599 } else if (temp1 == 0x01) {
2600 printk(KERN_INFO "%s CVBS output\n", stdstr);
2601 ivideo->vbflags |= TV_AVIDEO;
2602 orSISIDXREG(SISCR, 0x32, 0x01);
2603 andSISIDXREG(SISCR, 0x32, ~0x06);
2605 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2606 andSISIDXREG(SISCR, 0x32, ~0x07);
2608 } else if(temp1 == 0) {
2609 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2610 andSISIDXREG(SISCR, 0x32, ~0x07);
2612 /* Set general purpose IO for Chrontel communication */
2613 SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
2618 #ifdef CONFIG_FB_SIS_315
2619 ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */
2620 temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
2621 SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20);
2622 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2623 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2625 SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2626 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2628 SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2629 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2630 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2631 SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1);
2633 if(temp2 & 0x02) temp1 |= 0x01;
2634 if(temp2 & 0x10) temp1 |= 0x01;
2635 if(temp2 & 0x04) temp1 |= 0x02;
2636 if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
2639 printk(KERN_INFO "%s CVBS output\n", stdstr);
2640 ivideo->vbflags |= TV_AVIDEO;
2641 orSISIDXREG(SISCR, 0x32, 0x01);
2642 andSISIDXREG(SISCR, 0x32, ~0x06);
2645 printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2646 ivideo->vbflags |= TV_SVIDEO;
2647 orSISIDXREG(SISCR, 0x32, 0x02);
2648 andSISIDXREG(SISCR, 0x32, ~0x05);
2651 printk(KERN_INFO "%s SCART output\n", stdstr);
2652 orSISIDXREG(SISCR, 0x32, 0x04);
2653 andSISIDXREG(SISCR, 0x32, ~0x03);
2656 andSISIDXREG(SISCR, 0x32, ~0x07);
2662 static void __devinit
2663 sisfb_get_VB_type(struct sis_video_info *ivideo)
2665 char stdstr[] = "sisfb: Detected";
2666 char bridgestr[] = "video bridge";
2670 /* No CRT2 on XGI Z7 */
2671 if(ivideo->chip == XGI_20)
2674 inSISIDXREG(SISPART4, 0x00, vb_chipid);
2677 inSISIDXREG(SISPART4, 0x01, reg);
2679 ivideo->vbflags |= VB_301; /* Deprecated */
2680 ivideo->vbflags2 |= VB2_301;
2681 printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
2682 } else if(reg < 0xc0) {
2683 ivideo->vbflags |= VB_301B; /* Deprecated */
2684 ivideo->vbflags2 |= VB2_301B;
2685 inSISIDXREG(SISPART4,0x23,reg);
2687 ivideo->vbflags |= VB_30xBDH; /* Deprecated */
2688 ivideo->vbflags2 |= VB2_30xBDH;
2689 printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
2691 printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
2693 } else if(reg < 0xd0) {
2694 ivideo->vbflags |= VB_301C; /* Deprecated */
2695 ivideo->vbflags2 |= VB2_301C;
2696 printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
2697 } else if(reg < 0xe0) {
2698 ivideo->vbflags |= VB_301LV; /* Deprecated */
2699 ivideo->vbflags2 |= VB2_301LV;
2700 printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
2701 } else if(reg <= 0xe1) {
2702 inSISIDXREG(SISPART4,0x39,reg);
2704 ivideo->vbflags |= VB_302LV; /* Deprecated */
2705 ivideo->vbflags2 |= VB2_302LV;
2706 printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
2708 ivideo->vbflags |= VB_301C; /* Deprecated */
2709 ivideo->vbflags2 |= VB2_301C;
2710 printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
2712 ivideo->vbflags |= VB_302ELV; /* Deprecated */
2713 ivideo->vbflags2 |= VB2_302ELV;
2714 printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
2720 ivideo->vbflags |= VB_302B; /* Deprecated */
2721 ivideo->vbflags2 |= VB2_302B;
2722 printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
2726 if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
2727 inSISIDXREG(SISCR, 0x37, reg);
2728 reg &= SIS_EXTERNAL_CHIP_MASK;
2730 if(ivideo->sisvga_engine == SIS_300_VGA) {
2731 #ifdef CONFIG_FB_SIS_300
2733 case SIS_EXTERNAL_CHIP_LVDS:
2734 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2735 ivideo->vbflags2 |= VB2_LVDS;
2737 case SIS_EXTERNAL_CHIP_TRUMPION:
2738 ivideo->vbflags |= (VB_LVDS | VB_TRUMPION); /* Deprecated */
2739 ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION);
2741 case SIS_EXTERNAL_CHIP_CHRONTEL:
2742 ivideo->vbflags |= VB_CHRONTEL; /* Deprecated */
2743 ivideo->vbflags2 |= VB2_CHRONTEL;
2745 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
2746 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2747 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2750 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1;
2752 } else if(ivideo->chip < SIS_661) {
2753 #ifdef CONFIG_FB_SIS_315
2755 case SIS310_EXTERNAL_CHIP_LVDS:
2756 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2757 ivideo->vbflags2 |= VB2_LVDS;
2759 case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
2760 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2761 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2764 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2766 } else if(ivideo->chip >= SIS_661) {
2767 #ifdef CONFIG_FB_SIS_315
2768 inSISIDXREG(SISCR, 0x38, reg);
2772 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2773 ivideo->vbflags2 |= VB2_LVDS;
2776 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2777 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2780 ivideo->vbflags |= (VB_LVDS | VB_CONEXANT); /* Deprecated */
2781 ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT);
2784 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2787 if(ivideo->vbflags2 & VB2_LVDS) {
2788 printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
2790 if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) {
2791 printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
2793 if(ivideo->vbflags2 & VB2_CHRONTEL) {
2794 printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
2796 if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) {
2797 printk(KERN_INFO "%s Conexant external device\n", stdstr);
2801 if(ivideo->vbflags2 & VB2_SISBRIDGE) {
2802 SiS_SenseLCD(ivideo);
2803 SiS_Sense30x(ivideo);
2804 } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
2805 SiS_SenseCh(ivideo);
2809 /* ---------- Engine initialization routines ------------ */
2812 sisfb_engine_init(struct sis_video_info *ivideo)
2815 /* Initialize command queue (we use MMIO only) */
2817 /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
2819 ivideo->caps &= ~(TURBO_QUEUE_CAP |
2820 MMIO_CMD_QUEUE_CAP |
2824 #ifdef CONFIG_FB_SIS_300
2825 if(ivideo->sisvga_engine == SIS_300_VGA) {
2829 tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
2831 inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
2834 tq_state |= (u8)(tqueue_pos >> 8);
2835 outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
2837 outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
2839 ivideo->caps |= TURBO_QUEUE_CAP;
2843 #ifdef CONFIG_FB_SIS_315
2844 if(ivideo->sisvga_engine == SIS_315_VGA) {
2845 u32 tempq = 0, templ;
2848 if(ivideo->chip == XGI_20) {
2849 switch(ivideo->cmdQueueSize) {
2851 temp = SIS_CMD_QUEUE_SIZE_Z7_64k;
2855 temp = SIS_CMD_QUEUE_SIZE_Z7_128k;
2858 switch(ivideo->cmdQueueSize) {
2859 case (4 * 1024 * 1024):
2860 temp = SIS_CMD_QUEUE_SIZE_4M;
2862 case (2 * 1024 * 1024):
2863 temp = SIS_CMD_QUEUE_SIZE_2M;
2865 case (1 * 1024 * 1024):
2866 temp = SIS_CMD_QUEUE_SIZE_1M;
2870 temp = SIS_CMD_QUEUE_SIZE_512k;
2874 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2875 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2877 if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
2878 /* Must disable dual pipe on XGI_40. Can't do
2879 * this in MMIO mode, because it requires
2880 * setting/clearing a bit in the MMIO fire trigger
2883 if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) {
2885 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
2887 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
2889 tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
2890 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
2892 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2893 MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq);
2895 writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq);
2896 writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4);
2897 writel(0x168F0000, ivideo->video_vbase + tempq + 8);
2898 writel(0x168F0000, ivideo->video_vbase + tempq + 12);
2900 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16));
2902 sisfb_syncaccel(ivideo);
2904 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2909 tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
2910 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
2912 temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
2913 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
2915 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2916 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
2918 ivideo->caps |= MMIO_CMD_QUEUE_CAP;
2922 ivideo->engineok = 1;
2925 static void __devinit
2926 sisfb_detect_lcd_type(struct sis_video_info *ivideo)
2931 inSISIDXREG(SISCR, 0x36, reg);
2933 if(ivideo->sisvga_engine == SIS_300_VGA) {
2934 ivideo->CRT2LCDType = sis300paneltype[reg];
2935 } else if(ivideo->chip >= SIS_661) {
2936 ivideo->CRT2LCDType = sis661paneltype[reg];
2938 ivideo->CRT2LCDType = sis310paneltype[reg];
2939 if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
2940 if((ivideo->CRT2LCDType != LCD_320x240_2) &&
2941 (ivideo->CRT2LCDType != LCD_320x240_3)) {
2942 ivideo->CRT2LCDType = LCD_320x240;
2947 if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
2948 /* For broken BIOSes: Assume 1024x768, RGB18 */
2949 ivideo->CRT2LCDType = LCD_1024x768;
2950 setSISIDXREG(SISCR,0x36,0xf0,0x02);
2951 setSISIDXREG(SISCR,0x37,0xee,0x01);
2952 printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
2955 for(i = 0; i < SIS_LCD_NUMBER; i++) {
2956 if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
2957 ivideo->lcdxres = sis_lcd_data[i].xres;
2958 ivideo->lcdyres = sis_lcd_data[i].yres;
2959 ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
2964 #ifdef CONFIG_FB_SIS_300
2965 if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
2966 ivideo->lcdxres = 1360; ivideo->lcdyres = 1024;
2967 ivideo->lcddefmodeidx = DEFAULT_MODE_1360;
2968 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
2969 ivideo->lcdxres = 848; ivideo->lcdyres = 480;
2970 ivideo->lcddefmodeidx = DEFAULT_MODE_848;
2971 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) {
2972 ivideo->lcdxres = 856; ivideo->lcdyres = 480;
2973 ivideo->lcddefmodeidx = DEFAULT_MODE_856;
2977 printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
2978 ivideo->lcdxres, ivideo->lcdyres);
2981 static void __devinit
2982 sisfb_save_pdc_emi(struct sis_video_info *ivideo)
2984 #ifdef CONFIG_FB_SIS_300
2985 /* Save the current PanelDelayCompensation if the LCD is currently used */
2986 if(ivideo->sisvga_engine == SIS_300_VGA) {
2987 if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
2989 inSISIDXREG(SISCR,0x30,tmp);
2991 /* Currently on LCD? If yes, read current pdc */
2992 inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc);
2993 ivideo->detectedpdc &= 0x3c;
2994 if(ivideo->SiS_Pr.PDC == -1) {
2995 /* Let option override detection */
2996 ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
2998 printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
2999 ivideo->detectedpdc);
3001 if((ivideo->SiS_Pr.PDC != -1) &&
3002 (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
3003 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
3004 ivideo->SiS_Pr.PDC);
3010 #ifdef CONFIG_FB_SIS_315
3011 if(ivideo->sisvga_engine == SIS_315_VGA) {
3013 /* Try to find about LCDA */
3014 if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
3016 inSISIDXREG(SISPART1,0x13,tmp);
3018 ivideo->SiS_Pr.SiS_UseLCDA = true;
3019 ivideo->detectedlcda = 0x03;
3024 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
3026 inSISIDXREG(SISCR,0x30,tmp);
3027 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3028 /* Currently on LCD? If yes, read current pdc */
3030 inSISIDXREG(SISPART1,0x2D,pdc);
3031 ivideo->detectedpdc = (pdc & 0x0f) << 1;
3032 ivideo->detectedpdca = (pdc & 0xf0) >> 3;
3033 inSISIDXREG(SISPART1,0x35,pdc);
3034 ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
3035 inSISIDXREG(SISPART1,0x20,pdc);
3036 ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
3037 if(ivideo->newrom) {
3038 /* New ROM invalidates other PDC resp. */
3039 if(ivideo->detectedlcda != 0xff) {
3040 ivideo->detectedpdc = 0xff;
3042 ivideo->detectedpdca = 0xff;
3045 if(ivideo->SiS_Pr.PDC == -1) {
3046 if(ivideo->detectedpdc != 0xff) {
3047 ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
3050 if(ivideo->SiS_Pr.PDCA == -1) {
3051 if(ivideo->detectedpdca != 0xff) {
3052 ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
3055 if(ivideo->detectedpdc != 0xff) {
3057 "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3058 ivideo->detectedpdc);
3060 if(ivideo->detectedpdca != 0xff) {
3062 "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3063 ivideo->detectedpdca);
3068 if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
3069 inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30);
3070 inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31);
3071 inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32);
3072 inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33);
3073 ivideo->SiS_Pr.HaveEMI = true;
3074 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3075 ivideo->SiS_Pr.HaveEMILCD = true;
3080 /* Let user override detected PDCs (all bridges) */
3081 if(ivideo->vbflags2 & VB2_30xBLV) {
3082 if((ivideo->SiS_Pr.PDC != -1) &&
3083 (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
3084 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3085 ivideo->SiS_Pr.PDC);
3087 if((ivideo->SiS_Pr.PDCA != -1) &&
3088 (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
3089 printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3090 ivideo->SiS_Pr.PDCA);
3098 /* -------------------- Memory manager routines ---------------------- */
3100 static u32 __devinit
3101 sisfb_getheapstart(struct sis_video_info *ivideo)
3103 u32 ret = ivideo->sisfb_parm_mem * 1024;
3104 u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3107 /* Calculate heap start = end of memory for console
3109 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3110 * C = console, D = heap, H = HWCursor, Q = cmd-queue
3112 * On 76x in UMA+LFB mode, the layout is as follows:
3113 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3114 * where the heap is the entire UMA area, eventually
3115 * into the LFB area if the given mem parameter is
3116 * higher than the size of the UMA memory.
3118 * Basically given by "mem" parameter
3120 * maximum = videosize - cmd_queue - hwcursor
3121 * (results in a heap of size 0)
3122 * default = SiS 300: depends on videosize
3123 * SiS 315/330/340/XGI: 32k below max
3126 if(ivideo->sisvga_engine == SIS_300_VGA) {
3127 if(ivideo->video_size > 0x1000000) {
3129 } else if(ivideo->video_size > 0x800000) {
3134 } else if(ivideo->UMAsize && ivideo->LFBsize) {
3137 def = maxoffs - 0x8000;
3140 /* Use default for secondary card for now (FIXME) */
3141 if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0))
3147 static u32 __devinit
3148 sisfb_getheapsize(struct sis_video_info *ivideo)
3150 u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3153 if(ivideo->UMAsize && ivideo->LFBsize) {
3154 if( (!ivideo->sisfb_parm_mem) ||
3155 ((ivideo->sisfb_parm_mem * 1024) > max) ||
3156 ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) {
3157 ret = ivideo->UMAsize;
3158 max -= ivideo->UMAsize;
3160 ret = max - (ivideo->sisfb_parm_mem * 1024);
3161 max = ivideo->sisfb_parm_mem * 1024;
3163 ivideo->video_offset = ret;
3164 ivideo->sisfb_mem = max;
3166 ret = max - ivideo->heapstart;
3167 ivideo->sisfb_mem = ivideo->heapstart;
3173 static int __devinit
3174 sisfb_heap_init(struct sis_video_info *ivideo)
3178 ivideo->video_offset = 0;
3179 if(ivideo->sisfb_parm_mem) {
3180 if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) ||
3181 (ivideo->sisfb_parm_mem > ivideo->video_size) ) {
3182 ivideo->sisfb_parm_mem = 0;
3186 ivideo->heapstart = sisfb_getheapstart(ivideo);
3187 ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo);
3189 ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
3190 ivideo->sisfb_heap_end = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size;
3192 printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
3193 (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
3195 ivideo->sisfb_heap.vinfo = ivideo;
3197 ivideo->sisfb_heap.poha_chain = NULL;
3198 ivideo->sisfb_heap.poh_freelist = NULL;
3200 poh = sisfb_poh_new_node(&ivideo->sisfb_heap);
3204 poh->poh_next = &ivideo->sisfb_heap.oh_free;
3205 poh->poh_prev = &ivideo->sisfb_heap.oh_free;
3206 poh->size = ivideo->sisfb_heap_size;
3207 poh->offset = ivideo->heapstart;
3209 ivideo->sisfb_heap.oh_free.poh_next = poh;
3210 ivideo->sisfb_heap.oh_free.poh_prev = poh;
3211 ivideo->sisfb_heap.oh_free.size = 0;
3212 ivideo->sisfb_heap.max_freesize = poh->size;
3214 ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used;
3215 ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used;
3216 ivideo->sisfb_heap.oh_used.size = SENTINEL;
3218 if(ivideo->cardnumber == 0) {
3219 /* For the first card, make this heap the "global" one
3220 * for old DRM (which could handle only one card)
3222 sisfb_heap = &ivideo->sisfb_heap;
3228 static struct SIS_OH *
3229 sisfb_poh_new_node(struct SIS_HEAP *memheap)
3231 struct SIS_OHALLOC *poha;
3236 if(memheap->poh_freelist == NULL) {
3237 poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
3241 poha->poha_next = memheap->poha_chain;
3242 memheap->poha_chain = poha;
3244 cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1;
3246 poh = &poha->aoh[0];
3247 for(i = cOhs - 1; i != 0; i--) {
3248 poh->poh_next = poh + 1;
3252 poh->poh_next = NULL;
3253 memheap->poh_freelist = &poha->aoh[0];
3256 poh = memheap->poh_freelist;
3257 memheap->poh_freelist = poh->poh_next;
3262 static struct SIS_OH *
3263 sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size)
3265 struct SIS_OH *pohThis;
3266 struct SIS_OH *pohRoot;
3269 if(size > memheap->max_freesize) {
3270 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3271 (unsigned int) size / 1024);
3275 pohThis = memheap->oh_free.poh_next;
3277 while(pohThis != &memheap->oh_free) {
3278 if(size <= pohThis->size) {
3282 pohThis = pohThis->poh_next;
3286 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3287 (unsigned int) size / 1024);
3291 if(size == pohThis->size) {
3293 sisfb_delete_node(pohThis);
3295 pohRoot = sisfb_poh_new_node(memheap);
3299 pohRoot->offset = pohThis->offset;
3300 pohRoot->size = size;
3302 pohThis->offset += size;
3303 pohThis->size -= size;
3306 memheap->max_freesize -= size;
3308 pohThis = &memheap->oh_used;
3309 sisfb_insert_node(pohThis, pohRoot);
3315 sisfb_delete_node(struct SIS_OH *poh)
3317 poh->poh_prev->poh_next = poh->poh_next;
3318 poh->poh_next->poh_prev = poh->poh_prev;
3322 sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh)
3324 struct SIS_OH *pohTemp = pohList->poh_next;
3326 pohList->poh_next = poh;
3327 pohTemp->poh_prev = poh;
3329 poh->poh_prev = pohList;
3330 poh->poh_next = pohTemp;
3333 static struct SIS_OH *
3334 sisfb_poh_free(struct SIS_HEAP *memheap, u32 base)
3336 struct SIS_OH *pohThis;
3337 struct SIS_OH *poh_freed;
3338 struct SIS_OH *poh_prev;
3339 struct SIS_OH *poh_next;
3344 poh_freed = memheap->oh_used.poh_next;
3346 while(poh_freed != &memheap->oh_used) {
3347 if(poh_freed->offset == base) {
3352 poh_freed = poh_freed->poh_next;
3358 memheap->max_freesize += poh_freed->size;
3360 poh_prev = poh_next = NULL;
3361 ulUpper = poh_freed->offset + poh_freed->size;
3362 ulLower = poh_freed->offset;
3364 pohThis = memheap->oh_free.poh_next;
3366 while(pohThis != &memheap->oh_free) {
3367 if(pohThis->offset == ulUpper) {
3369 } else if((pohThis->offset + pohThis->size) == ulLower) {
3372 pohThis = pohThis->poh_next;
3375 sisfb_delete_node(poh_freed);
3377 if(poh_prev && poh_next) {
3378 poh_prev->size += (poh_freed->size + poh_next->size);
3379 sisfb_delete_node(poh_next);
3380 sisfb_free_node(memheap, poh_freed);
3381 sisfb_free_node(memheap, poh_next);
3386 poh_prev->size += poh_freed->size;
3387 sisfb_free_node(memheap, poh_freed);
3392 poh_next->size += poh_freed->size;
3393 poh_next->offset = poh_freed->offset;
3394 sisfb_free_node(memheap, poh_freed);
3398 sisfb_insert_node(&memheap->oh_free, poh_freed);
3404 sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh)
3409 poh->poh_next = memheap->poh_freelist;
3410 memheap->poh_freelist = poh;
3414 sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req)
3416 struct SIS_OH *poh = NULL;
3418 if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap))
3419 poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size);
3422 req->offset = req->size = 0;
3423 DPRINTK("sisfb: Video RAM allocation failed\n");
3425 req->offset = poh->offset;
3426 req->size = poh->size;
3427 DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3428 (poh->offset + ivideo->video_vbase));
3433 sis_malloc(struct sis_memreq *req)
3435 struct sis_video_info *ivideo = sisfb_heap->vinfo;
3437 if(&ivideo->sisfb_heap == sisfb_heap)
3438 sis_int_malloc(ivideo, req);
3440 req->offset = req->size = 0;
3444 sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
3446 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3448 sis_int_malloc(ivideo, req);
3451 /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3454 sis_int_free(struct sis_video_info *ivideo, u32 base)
3458 if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap))
3461 poh = sisfb_poh_free(&ivideo->sisfb_heap, base);
3464 DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
3465 (unsigned int) base);
3472 struct sis_video_info *ivideo = sisfb_heap->vinfo;
3474 sis_int_free(ivideo, base);
3478 sis_free_new(struct pci_dev *pdev, u32 base)
3480 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3482 sis_int_free(ivideo, base);
3485 /* --------------------- SetMode routines ------------------------- */
3488 sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
3492 /* Check if MMIO and engines are enabled,
3493 * and sync in case they are. Can't use
3494 * ivideo->accel here, as this might have
3495 * been changed before this is called.
3497 inSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, cr30);
3498 inSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, cr31);
3499 /* MMIO and 2D/3D engine enabled? */
3500 if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
3501 #ifdef CONFIG_FB_SIS_300
3502 if(ivideo->sisvga_engine == SIS_300_VGA) {
3503 /* Don't care about TurboQueue. It's
3504 * enough to know that the engines
3507 sisfb_syncaccel(ivideo);
3510 #ifdef CONFIG_FB_SIS_315
3511 if(ivideo->sisvga_engine == SIS_315_VGA) {
3512 /* Check that any queue mode is
3513 * enabled, and that the queue
3514 * is not in the state of "reset"
3516 inSISIDXREG(SISSR, 0x26, cr30);
3517 if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
3518 sisfb_syncaccel(ivideo);
3526 sisfb_pre_setmode(struct sis_video_info *ivideo)
3528 u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
3531 ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
3533 outSISIDXREG(SISSR, 0x05, 0x86);
3535 inSISIDXREG(SISCR, 0x31, cr31);
3539 cr33 = ivideo->rate_idx & 0x0F;
3541 #ifdef CONFIG_FB_SIS_315
3542 if(ivideo->sisvga_engine == SIS_315_VGA) {
3543 if(ivideo->chip >= SIS_661) {
3544 inSISIDXREG(SISCR, 0x38, cr38);
3545 cr38 &= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
3548 inSISIDXREG(SISCR, tvregnum, cr38);
3549 cr38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
3553 #ifdef CONFIG_FB_SIS_300
3554 if(ivideo->sisvga_engine == SIS_300_VGA) {
3556 inSISIDXREG(SISCR, tvregnum, cr38);
3560 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
3561 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
3562 ivideo->curFSTN = ivideo->curDSTN = 0;
3564 switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
3567 cr38 &= ~0xc0; /* Clear PAL-M / PAL-N bits */
3568 if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
3569 #ifdef CONFIG_FB_SIS_315
3570 if(ivideo->chip >= SIS_661) {
3572 if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20;
3573 else if(ivideo->vbflags & TV_YPBPR750P) cr35 |= 0x40;
3574 else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
3575 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3577 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3578 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
3579 cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3581 if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10;
3582 else if(ivideo->vbflags & TV_YPBPR750P) cr38 |= 0x20;
3583 else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
3585 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3588 } else if((ivideo->vbflags & TV_HIVISION) &&
3589 (ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) {
3590 if(ivideo->chip >= SIS_661) {
3596 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3599 ivideo->currentvbflags |= TV_HIVISION;
3600 } else if(ivideo->vbflags & TV_SCART) {
3601 cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
3604 ivideo->currentvbflags |= TV_SCART;
3606 if(ivideo->vbflags & TV_SVIDEO) {
3607 cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
3608 ivideo->currentvbflags |= TV_SVIDEO;
3610 if(ivideo->vbflags & TV_AVIDEO) {
3611 cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
3612 ivideo->currentvbflags |= TV_AVIDEO;
3615 cr31 |= SIS_DRIVER_MODE;
3617 if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) {
3618 if(ivideo->vbflags & TV_PAL) {
3619 cr31 |= 0x01; cr35 |= 0x01;
3620 ivideo->currentvbflags |= TV_PAL;
3621 if(ivideo->vbflags & TV_PALM) {
3622 cr38 |= 0x40; cr35 |= 0x04;
3623 ivideo->currentvbflags |= TV_PALM;
3624 } else if(ivideo->vbflags & TV_PALN) {
3625 cr38 |= 0x80; cr35 |= 0x08;
3626 ivideo->currentvbflags |= TV_PALN;
3629 cr31 &= ~0x01; cr35 &= ~0x01;
3630 ivideo->currentvbflags |= TV_NTSC;
3631 if(ivideo->vbflags & TV_NTSCJ) {
3632 cr38 |= 0x40; cr35 |= 0x02;
3633 ivideo->currentvbflags |= TV_NTSCJ;
3640 cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
3641 cr31 |= SIS_DRIVER_MODE;
3642 SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
3643 SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
3644 ivideo->curFSTN = ivideo->sisfb_fstn;
3645 ivideo->curDSTN = ivideo->sisfb_dstn;
3649 cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3650 cr31 |= SIS_DRIVER_MODE;
3651 if(ivideo->sisfb_nocrt2rate) {
3652 cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4);
3654 cr33 |= ((ivideo->rate_idx & 0x0F) << 4);
3658 default: /* disable CRT2 */
3660 cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
3663 outSISIDXREG(SISCR, 0x30, cr30);
3664 outSISIDXREG(SISCR, 0x33, cr33);
3666 if(ivideo->chip >= SIS_661) {
3667 #ifdef CONFIG_FB_SIS_315
3668 cr31 &= ~0x01; /* Clear PAL flag (now in CR35) */
3669 setSISIDXREG(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
3670 cr38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
3671 setSISIDXREG(SISCR, 0x38, 0xf8, cr38);
3673 } else if(ivideo->chip != SIS_300) {
3674 outSISIDXREG(SISCR, tvregnum, cr38);
3676 outSISIDXREG(SISCR, 0x31, cr31);
3678 ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
3680 sisfb_check_engine_and_sync(ivideo);
3683 /* Fix SR11 for 661 and later */
3684 #ifdef CONFIG_FB_SIS_315
3686 sisfb_fixup_SR11(struct sis_video_info *ivideo)
3690 if(ivideo->chip >= SIS_661) {
3691 inSISIDXREG(SISSR,0x11,tmpreg);
3693 inSISIDXREG(SISSR,0x3e,tmpreg);
3694 tmpreg = (tmpreg + 1) & 0xff;
3695 outSISIDXREG(SISSR,0x3e,tmpreg);
3696 inSISIDXREG(SISSR,0x11,tmpreg);
3699 andSISIDXREG(SISSR,0x11,0x0f);
3706 sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
3708 if(val > 32) val = 32;
3709 if(val < -32) val = -32;
3710 ivideo->tvxpos = val;
3712 if(ivideo->sisfblocked) return;
3713 if(!ivideo->modechanged) return;
3715 if(ivideo->currentvbflags & CRT2_TV) {
3717 if(ivideo->vbflags2 & VB2_CHRONTEL) {
3719 int x = ivideo->tvx;
3721 switch(ivideo->chronteltype) {
3725 outSISIDXREG(SISSR,0x05,0x86);
3726 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
3727 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
3730 /* Not supported by hardware */
3734 } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3736 u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
3737 unsigned short temp;
3739 p2_1f = ivideo->p2_1f;
3740 p2_20 = ivideo->p2_20;
3741 p2_2b = ivideo->p2_2b;
3742 p2_42 = ivideo->p2_42;
3743 p2_43 = ivideo->p2_43;
3745 temp = p2_1f | ((p2_20 & 0xf0) << 4);
3747 p2_1f = temp & 0xff;
3748 p2_20 = (temp & 0xf00) >> 4;
3749 p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
3750 temp = p2_43 | ((p2_42 & 0xf0) << 4);
3752 p2_43 = temp & 0xff;
3753 p2_42 = (temp & 0xf00) >> 4;
3754 outSISIDXREG(SISPART2,0x1f,p2_1f);
3755 setSISIDXREG(SISPART2,0x20,0x0F,p2_20);
3756 setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b);
3757 setSISIDXREG(SISPART2,0x42,0x0F,p2_42);
3758 outSISIDXREG(SISPART2,0x43,p2_43);
3764 sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
3766 if(val > 32) val = 32;
3767 if(val < -32) val = -32;
3768 ivideo->tvypos = val;
3770 if(ivideo->sisfblocked) return;
3771 if(!ivideo->modechanged) return;
3773 if(ivideo->currentvbflags & CRT2_TV) {
3775 if(ivideo->vbflags2 & VB2_CHRONTEL) {
3777 int y = ivideo->tvy;
3779 switch(ivideo->chronteltype) {
3783 outSISIDXREG(SISSR,0x05,0x86);
3784 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
3785 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
3788 /* Not supported by hardware */
3792 } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3796 p2_01 = ivideo->p2_01;
3797 p2_02 = ivideo->p2_02;
3801 if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) {
3802 while((p2_01 <= 0) || (p2_02 <= 0)) {
3807 outSISIDXREG(SISPART2,0x01,p2_01);
3808 outSISIDXREG(SISPART2,0x02,p2_02);
3814 sisfb_post_setmode(struct sis_video_info *ivideo)
3816 bool crt1isoff = false;
3818 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
3821 #ifdef CONFIG_FB_SIS_315
3825 outSISIDXREG(SISSR, 0x05, 0x86);
3827 #ifdef CONFIG_FB_SIS_315
3828 sisfb_fixup_SR11(ivideo);
3831 /* Now we actually HAVE changed the display mode */
3832 ivideo->modechanged = 1;
3834 /* We can't switch off CRT1 if bridge is in slave mode */
3835 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
3836 if(sisfb_bridgeisslave(ivideo)) doit = false;
3838 ivideo->sisfb_crt1off = 0;
3840 #ifdef CONFIG_FB_SIS_300
3841 if(ivideo->sisvga_engine == SIS_300_VGA) {
3842 if((ivideo->sisfb_crt1off) && (doit)) {
3849 setSISIDXREG(SISCR, 0x17, 0x7f, reg);
3852 #ifdef CONFIG_FB_SIS_315
3853 if(ivideo->sisvga_engine == SIS_315_VGA) {
3854 if((ivideo->sisfb_crt1off) && (doit)) {
3863 setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
3864 setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1);
3869 ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
3870 ivideo->currentvbflags |= VB_SINGLE_MODE;
3872 ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
3873 if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
3874 ivideo->currentvbflags |= VB_MIRROR_MODE;
3876 ivideo->currentvbflags |= VB_SINGLE_MODE;
3880 andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
3882 if(ivideo->currentvbflags & CRT2_TV) {
3883 if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3884 inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f);
3885 inSISIDXREG(SISPART2,0x20,ivideo->p2_20);
3886 inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b);
3887 inSISIDXREG(SISPART2,0x42,ivideo->p2_42);
3888 inSISIDXREG(SISPART2,0x43,ivideo->p2_43);
3889 inSISIDXREG(SISPART2,0x01,ivideo->p2_01);
3890 inSISIDXREG(SISPART2,0x02,ivideo->p2_02);
3891 } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
3892 if(ivideo->chronteltype == 1) {
3893 ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
3894 ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
3895 ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
3896 ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
3901 if(ivideo->tvxpos) {
3902 sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
3904 if(ivideo->tvypos) {
3905 sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
3908 /* Eventually sync engines */
3909 sisfb_check_engine_and_sync(ivideo);
3911 /* (Re-)Initialize chip engines */
3913 sisfb_engine_init(ivideo);
3915 ivideo->engineok = 0;
3920 sisfb_reset_mode(struct sis_video_info *ivideo)
3922 if(sisfb_set_mode(ivideo, 0))
3925 sisfb_set_pitch(ivideo);
3926 sisfb_set_base_CRT1(ivideo, ivideo->current_base);
3927 sisfb_set_base_CRT2(ivideo, ivideo->current_base);
3933 sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command)
3937 switch(sisfb_command->sisfb_cmd) {
3938 case SISFB_CMD_GETVBFLAGS:
3939 if(!ivideo->modechanged) {
3940 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3942 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3943 sisfb_command->sisfb_result[1] = ivideo->currentvbflags;
3944 sisfb_command->sisfb_result[2] = ivideo->vbflags2;
3947 case SISFB_CMD_SWITCHCRT1:
3948 /* arg[0]: 0 = off, 1 = on, 99 = query */
3949 if(!ivideo->modechanged) {
3950 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3951 } else if(sisfb_command->sisfb_arg[0] == 99) {
3953 sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3954 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3955 } else if(ivideo->sisfblocked) {
3956 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED;
3957 } else if((!(ivideo->currentvbflags & CRT2_ENABLE)) &&
3958 (sisfb_command->sisfb_arg[0] == 0)) {
3959 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2;
3961 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3962 mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1;
3963 if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) ||
3964 ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) {
3965 ivideo->sisfb_crt1off = mycrt1off;
3966 if(sisfb_reset_mode(ivideo)) {
3967 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER;
3970 sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3975 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN;
3976 printk(KERN_ERR "sisfb: Unknown command 0x%x\n",
3977 sisfb_command->sisfb_cmd);
3982 SISINITSTATIC int __init
3983 sisfb_setup(char *options)
3987 sisfb_setdefaultparms();
3989 if(!options || !(*options))
3992 while((this_opt = strsep(&options, ",")) != NULL) {
3994 if(!(*this_opt)) continue;
3996 if(!strnicmp(this_opt, "off", 3)) {
3998 } else if(!strnicmp(this_opt, "forcecrt2type:", 14)) {
3999 /* Need to check crt2 type first for fstn/dstn */
4000 sisfb_search_crt2type(this_opt + 14);
4001 } else if(!strnicmp(this_opt, "tvmode:",7)) {
4002 sisfb_search_tvstd(this_opt + 7);
4003 } else if(!strnicmp(this_opt, "tvstandard:",11)) {
4004 sisfb_search_tvstd(this_opt + 11);
4005 } else if(!strnicmp(this_opt, "mode:", 5)) {
4006 sisfb_search_mode(this_opt + 5, false);
4007 } else if(!strnicmp(this_opt, "vesa:", 5)) {
4008 sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false);
4009 } else if(!strnicmp(this_opt, "rate:", 5)) {
4010 sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
4011 } else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
4012 sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
4013 } else if(!strnicmp(this_opt, "mem:",4)) {
4014 sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
4015 } else if(!strnicmp(this_opt, "pdc:", 4)) {
4016 sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
4017 } else if(!strnicmp(this_opt, "pdc1:", 5)) {
4018 sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
4019 } else if(!strnicmp(this_opt, "noaccel", 7)) {
4021 } else if(!strnicmp(this_opt, "accel", 5)) {
4023 } else if(!strnicmp(this_opt, "noypan", 6)) {
4025 } else if(!strnicmp(this_opt, "ypan", 4)) {
4027 } else if(!strnicmp(this_opt, "nomax", 5)) {
4029 } else if(!strnicmp(this_opt, "max", 3)) {
4031 } else if(!strnicmp(this_opt, "userom:", 7)) {
4032 sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
4033 } else if(!strnicmp(this_opt, "useoem:", 7)) {
4034 sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
4035 } else if(!strnicmp(this_opt, "nocrt2rate", 10)) {
4036 sisfb_nocrt2rate = 1;
4037 } else if(!strnicmp(this_opt, "scalelcd:", 9)) {
4038 unsigned long temp = 2;
4039 temp = simple_strtoul(this_opt + 9, NULL, 0);
4040 if((temp == 0) || (temp == 1)) {
4041 sisfb_scalelcd = temp ^ 1;
4043 } else if(!strnicmp(this_opt, "tvxposoffset:", 13)) {
4045 temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4046 if((temp >= -32) && (temp <= 32)) {
4047 sisfb_tvxposoffset = temp;
4049 } else if(!strnicmp(this_opt, "tvyposoffset:", 13)) {
4051 temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4052 if((temp >= -32) && (temp <= 32)) {
4053 sisfb_tvyposoffset = temp;
4055 } else if(!strnicmp(this_opt, "specialtiming:", 14)) {
4056 sisfb_search_specialtiming(this_opt + 14);
4057 } else if(!strnicmp(this_opt, "lvdshl:", 7)) {
4059 temp = simple_strtoul(this_opt + 7, NULL, 0);
4060 if((temp >= 0) && (temp <= 3)) {
4061 sisfb_lvdshl = temp;
4063 } else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
4064 sisfb_search_mode(this_opt, true);
4065 #if !defined(__i386__) && !defined(__x86_64__)
4066 } else if(!strnicmp(this_opt, "resetcard", 9)) {
4067 sisfb_resetcard = 1;
4068 } else if(!strnicmp(this_opt, "videoram:", 9)) {
4069 sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
4072 printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
4081 static int __devinit
4082 sisfb_check_rom(SIS_IOTYPE1 *rom_base, struct sis_video_info *ivideo)
4087 if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
4090 romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
4091 if(romptr > (0x10000 - 8))
4094 rom = rom_base + romptr;
4096 if((readb(rom) != 'P') || (readb(rom + 1) != 'C') ||
4097 (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R'))
4100 if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor)
4103 if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id)
4109 static unsigned char * __devinit
4110 sisfb_find_rom(struct pci_dev *pdev)
4112 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4113 SIS_IOTYPE1 *rom_base;
4114 unsigned char *myrombase = NULL;
4116 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
4119 /* First, try the official pci ROM functions (except
4120 * on integrated chipsets which have no ROM).
4123 if(!ivideo->nbridge) {
4125 if((rom_base = pci_map_rom(pdev, &romsize))) {
4127 if(sisfb_check_rom(rom_base, ivideo)) {
4129 if((myrombase = vmalloc(65536))) {
4131 /* Work around bug in pci/rom.c: Folks forgot to check
4132 * whether the size retrieved from the BIOS image eventually
4133 * is larger than the mapped size
4135 if(pci_resource_len(pdev, PCI_ROM_RESOURCE) < romsize)
4136 romsize = pci_resource_len(pdev, PCI_ROM_RESOURCE);
4138 memcpy_fromio(myrombase, rom_base,
4139 (romsize > 65536) ? 65536 : romsize);
4142 pci_unmap_rom(pdev, rom_base);
4146 if(myrombase) return myrombase;
4149 /* Otherwise do it the conventional way. */
4151 #if defined(__i386__) || defined(__x86_64__)
4153 for(temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
4155 rom_base = ioremap(temp, 65536);
4159 if(!sisfb_check_rom(rom_base, ivideo)) {
4164 if((myrombase = vmalloc(65536)))
4165 memcpy_fromio(myrombase, rom_base, 65536);
4174 pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &temp);
4175 pci_write_config_dword(pdev, PCI_ROM_ADDRESS,
4176 (ivideo->video_base & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
4178 rom_base = ioremap(ivideo->video_base, 65536);
4180 if(sisfb_check_rom(rom_base, ivideo)) {
4181 if((myrombase = vmalloc(65536)))
4182 memcpy_fromio(myrombase, rom_base, 65536);
4187 pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp);
4194 static void __devinit
4195 sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize,
4198 ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize));
4200 if(!ivideo->video_vbase) {
4202 "sisfb: Unable to map maximum video RAM for size detection\n");
4204 while((!(ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize))))) {
4206 if((*mapsize) < (min << 20))
4209 if(ivideo->video_vbase) {
4211 "sisfb: Video RAM size detection limited to %dMB\n",
4212 (int)((*mapsize) >> 20));
4217 #ifdef CONFIG_FB_SIS_300
4218 static int __devinit
4219 sisfb_post_300_buswidth(struct sis_video_info *ivideo)
4221 SIS_IOTYPE1 *FBAddress = ivideo->video_vbase;
4222 unsigned short temp;
4226 andSISIDXREG(SISSR, 0x15, 0xFB);
4227 orSISIDXREG(SISSR, 0x15, 0x04);
4228 outSISIDXREG(SISSR, 0x13, 0x00);
4229 outSISIDXREG(SISSR, 0x14, 0xBF);
4231 for(i = 0; i < 2; i++) {
4233 for(j = 0; j < 4; j++) {
4234 writew(temp, FBAddress);
4235 if(readw(FBAddress) == temp)
4237 orSISIDXREG(SISSR, 0x3c, 0x01);
4238 inSISIDXREG(SISSR, 0x05, reg);
4239 inSISIDXREG(SISSR, 0x05, reg);
4240 andSISIDXREG(SISSR, 0x3c, 0xfe);
4241 inSISIDXREG(SISSR, 0x05, reg);
4242 inSISIDXREG(SISSR, 0x05, reg);
4247 writel(0x01234567L, FBAddress);
4248 writel(0x456789ABL, (FBAddress + 4));
4249 writel(0x89ABCDEFL, (FBAddress + 8));
4250 writel(0xCDEF0123L, (FBAddress + 12));
4252 inSISIDXREG(SISSR, 0x3b, reg);
4254 if(readl((FBAddress + 12)) == 0xCDEF0123L)
4255 return 4; /* Channel A 128bit */
4258 if(readl((FBAddress + 4)) == 0x456789ABL)
4259 return 2; /* Channel B 64bit */
4261 return 1; /* 32bit */
4264 static int __devinit
4265 sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth,
4266 int PseudoRankCapacity, int PseudoAdrPinCount,
4267 unsigned int mapsize)
4269 SIS_IOTYPE1 *FBAddr = ivideo->video_vbase;
4270 unsigned short sr14;
4271 unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
4272 unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
4273 static const unsigned short SiS_DRAMType[17][5] = {
4274 {0x0C,0x0A,0x02,0x40,0x39},
4275 {0x0D,0x0A,0x01,0x40,0x48},
4276 {0x0C,0x09,0x02,0x20,0x35},
4277 {0x0D,0x09,0x01,0x20,0x44},
4278 {0x0C,0x08,0x02,0x10,0x31},
4279 {0x0D,0x08,0x01,0x10,0x40},
4280 {0x0C,0x0A,0x01,0x20,0x34},
4281 {0x0C,0x09,0x01,0x08,0x32},
4282 {0x0B,0x08,0x02,0x08,0x21},
4283 {0x0C,0x08,0x01,0x08,0x30},
4284 {0x0A,0x08,0x02,0x04,0x11},
4285 {0x0B,0x0A,0x01,0x10,0x28},
4286 {0x09,0x08,0x02,0x02,0x01},
4287 {0x0B,0x09,0x01,0x08,0x24},
4288 {0x0B,0x08,0x01,0x04,0x20},
4289 {0x0A,0x08,0x01,0x02,0x10},
4290 {0x09,0x08,0x01,0x01,0x00}
4293 for(k = 0; k <= 16; k++) {
4295 RankCapacity = buswidth * SiS_DRAMType[k][3];
4297 if(RankCapacity != PseudoRankCapacity)
4300 if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
4303 BankNumHigh = RankCapacity * 16 * iteration - 1;
4304 if(iteration == 3) { /* Rank No */
4305 BankNumMid = RankCapacity * 16 - 1;
4307 BankNumMid = RankCapacity * 16 * iteration / 2 - 1;
4310 PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
4311 PhysicalAdrHigh = BankNumHigh;
4312 PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
4313 PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
4315 andSISIDXREG(SISSR, 0x15, 0xFB); /* Test */
4316 orSISIDXREG(SISSR, 0x15, 0x04); /* Test */
4317 sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
4318 if(buswidth == 4) sr14 |= 0x80;
4319 else if(buswidth == 2) sr14 |= 0x40;
4320 outSISIDXREG(SISSR, 0x13, SiS_DRAMType[k][4]);
4321 outSISIDXREG(SISSR, 0x14, sr14);
4326 if((BankNumHigh + PhysicalAdrHigh >= mapsize) ||
4327 (BankNumMid + PhysicalAdrHigh >= mapsize) ||
4328 (BankNumHigh + PhysicalAdrHalfPage >= mapsize) ||
4329 (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
4333 writew(((unsigned short)PhysicalAdrHigh),
4334 (FBAddr + BankNumHigh + PhysicalAdrHigh));
4335 writew(((unsigned short)BankNumMid),
4336 (FBAddr + BankNumMid + PhysicalAdrHigh));
4337 writew(((unsigned short)PhysicalAdrHalfPage),
4338 (FBAddr + BankNumHigh + PhysicalAdrHalfPage));
4339 writew(((unsigned short)PhysicalAdrOtherPage),
4340 (FBAddr + BankNumHigh + PhysicalAdrOtherPage));
4343 if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
4350 static void __devinit
4351 sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
4353 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4355 int PseudoRankCapacity, PseudoAdrPinCount;
4357 buswidth = sisfb_post_300_buswidth(ivideo);
4359 for(i = 6; i >= 0; i--) {
4360 PseudoRankCapacity = 1 << i;
4361 for(j = 4; j >= 1; j--) {
4362 PseudoAdrPinCount = 15 - j;
4363 if((PseudoRankCapacity * j) <= 64) {
4364 if(sisfb_post_300_rwtest(ivideo,
4376 static void __devinit
4377 sisfb_post_sis300(struct pci_dev *pdev)
4379 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4380 unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
4381 u8 reg, v1, v2, v3, v4, v5, v6, v7, v8;
4382 u16 index, rindex, memtype = 0;
4383 unsigned int mapsize;
4385 if(!ivideo->SiS_Pr.UseROM)
4388 outSISIDXREG(SISSR, 0x05, 0x86);
4391 if(bios[0x52] & 0x80) {
4392 memtype = bios[0x52];
4394 inSISIDXREG(SISSR, 0x3a, memtype);
4399 v3 = 0x80; v6 = 0x80;
4400 if(ivideo->revision_id <= 0x13) {
4401 v1 = 0x44; v2 = 0x42;
4402 v4 = 0x44; v5 = 0x42;
4404 v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */
4405 v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */
4407 index = memtype * 5;
4408 rindex = index + 0x54;
4409 v1 = bios[rindex++];
4410 v2 = bios[rindex++];
4411 v3 = bios[rindex++];
4412 rindex = index + 0x7c;
4413 v4 = bios[rindex++];
4414 v5 = bios[rindex++];
4415 v6 = bios[rindex++];
4418 outSISIDXREG(SISSR, 0x28, v1);
4419 outSISIDXREG(SISSR, 0x29, v2);
4420 outSISIDXREG(SISSR, 0x2a, v3);
4421 outSISIDXREG(SISSR, 0x2e, v4);
4422 outSISIDXREG(SISSR, 0x2f, v5);
4423 outSISIDXREG(SISSR, 0x30, v6);
4428 outSISIDXREG(SISSR, 0x07, v1); /* DAC speed */
4430 outSISIDXREG(SISSR, 0x11, 0x0f); /* DDC, power save */
4432 v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
4433 v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
4437 v2 = bios[memtype + 8];
4438 v3 = bios[memtype + 16];
4439 v4 = bios[memtype + 24];
4440 v5 = bios[memtype + 32];
4441 v6 = bios[memtype + 40];
4442 v7 = bios[memtype + 48];
4443 v8 = bios[memtype + 56];
4445 if(ivideo->revision_id >= 0x80)
4447 outSISIDXREG(SISSR, 0x15, v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4448 outSISIDXREG(SISSR, 0x16, v2);
4449 outSISIDXREG(SISSR, 0x17, v3);
4450 outSISIDXREG(SISSR, 0x18, v4);
4451 outSISIDXREG(SISSR, 0x19, v5);
4452 outSISIDXREG(SISSR, 0x1a, v6);
4453 outSISIDXREG(SISSR, 0x1b, v7);
4454 outSISIDXREG(SISSR, 0x1c, v8); /* ---- */
4455 andSISIDXREG(SISSR, 0x15 ,0xfb);
4456 orSISIDXREG(SISSR, 0x15, 0x04);
4458 if(bios[0x53] & 0x02) {
4459 orSISIDXREG(SISSR, 0x19, 0x20);
4462 v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */
4463 if(ivideo->revision_id >= 0x80)
4465 outSISIDXREG(SISSR, 0x1f, v1);
4466 outSISIDXREG(SISSR, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
4467 v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
4473 outSISIDXREG(SISSR, 0x23, v1);
4474 outSISIDXREG(SISSR, 0x24, v2);
4475 outSISIDXREG(SISSR, 0x25, v3);
4476 outSISIDXREG(SISSR, 0x21, 0x84);
4477 outSISIDXREG(SISSR, 0x22, 0x00);
4478 outSISIDXREG(SISCR, 0x37, 0x00);
4479 orSISIDXREG(SISPART1, 0x24, 0x01); /* unlock crt2 */
4480 outSISIDXREG(SISPART1, 0x00, 0x00);
4481 v1 = 0x40; v2 = 0x11;
4486 outSISIDXREG(SISPART1, 0x02, v1);
4488 if(ivideo->revision_id >= 0x80)
4491 inSISIDXREG(SISPART4, 0x00, reg);
4492 if((reg == 1) || (reg == 2)) {
4493 outSISIDXREG(SISCR, 0x37, 0x02);
4494 outSISIDXREG(SISPART2, 0x00, 0x1c);
4495 v4 = 0x00; v5 = 0x00; v6 = 0x10;
4496 if(ivideo->SiS_Pr.UseROM) {
4501 outSISIDXREG(SISPART4, 0x0d, v4);
4502 outSISIDXREG(SISPART4, 0x0e, v5);
4503 outSISIDXREG(SISPART4, 0x10, v6);
4504 outSISIDXREG(SISPART4, 0x0f, 0x3f);
4505 inSISIDXREG(SISPART4, 0x01, reg);
4507 inSISIDXREG(SISPART4, 0x23, reg);
4510 outSISIDXREG(SISPART4, 0x23, reg);
4515 outSISIDXREG(SISSR, 0x32, v2);
4517 andSISIDXREG(SISPART1, 0x24, 0xfe); /* Lock CRT2 */
4519 inSISIDXREG(SISSR, 0x16, reg);
4521 outSISIDXREG(SISCR, 0x35, reg);
4522 outSISIDXREG(SISCR, 0x83, 0x00);
4523 #if !defined(__i386__) && !defined(__x86_64__)
4524 if(sisfb_videoram) {
4525 outSISIDXREG(SISSR, 0x13, 0x28); /* ? */
4526 reg = ((sisfb_videoram >> 10) - 1) | 0x40;
4527 outSISIDXREG(SISSR, 0x14, reg);
4530 /* Need to map max FB size for finding out about RAM size */
4532 sisfb_post_map_vram(ivideo, &mapsize, 4);
4534 if(ivideo->video_vbase) {
4535 sisfb_post_300_ramsize(pdev, mapsize);
4536 iounmap(ivideo->video_vbase);
4539 "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4540 outSISIDXREG(SISSR, 0x13, 0x28); /* ? */
4541 outSISIDXREG(SISSR, 0x14, 0x47); /* 8MB, 64bit default */
4543 #if !defined(__i386__) && !defined(__x86_64__)
4550 inSISIDXREG(SISSR, 0x3a, reg);
4551 if((reg & 0x30) == 0x30) {
4552 v1 = 0x04; /* PCI */
4555 v1 = 0x14; /* AGP */
4559 outSISIDXREG(SISSR, 0x21, v1);
4560 outSISIDXREG(SISSR, 0x22, v2);
4563 sisfb_sense_crt1(ivideo);
4565 /* Set default mode, don't clear screen */
4566 ivideo->SiS_Pr.SiS_UseOEM = false;
4567 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
4568 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
4569 ivideo->curFSTN = ivideo->curDSTN = 0;
4570 ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
4571 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
4573 outSISIDXREG(SISSR, 0x05, 0x86);
4576 orSISIDXREG(SISSR, 0x01, 0x20);
4578 /* Save mode number in CR34 */
4579 outSISIDXREG(SISCR, 0x34, 0x2e);
4581 /* Let everyone know what the current mode is */
4582 ivideo->modeprechange = 0x2e;
4586 #ifdef CONFIG_FB_SIS_315
4588 static void __devinit
4589 sisfb_post_sis315330(struct pci_dev *pdev)
4595 static void __devinit
4596 sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
4601 for(i = 0; i <= (delay * 10 * 36); i++) {
4602 inSISIDXREG(SISSR, 0x05, reg);
4607 static int __devinit
4608 sisfb_find_host_bridge(struct sis_video_info *ivideo, struct pci_dev *mypdev,
4609 unsigned short pcivendor)
4611 struct pci_dev *pdev = NULL;
4612 unsigned short temp;
4615 while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) {
4616 temp = pdev->vendor;
4618 if(temp == pcivendor) {
4627 static int __devinit
4628 sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
4629 unsigned int enda, unsigned int mapsize)
4634 writel(0, ivideo->video_vbase);
4636 for(i = starta; i <= enda; i++) {
4639 writel(pos, ivideo->video_vbase + pos);
4642 sisfb_post_xgi_delay(ivideo, 150);
4644 if(readl(ivideo->video_vbase) != 0)
4647 for(i = starta; i <= enda; i++) {
4650 if(readl(ivideo->video_vbase + pos) != pos)
4659 static void __devinit
4660 sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
4662 unsigned int buswidth, ranksize, channelab, mapsize;
4665 static const u8 dramsr13[12 * 5] = {
4666 0x02, 0x0e, 0x0b, 0x80, 0x5d,
4667 0x02, 0x0e, 0x0a, 0x40, 0x59,
4668 0x02, 0x0d, 0x0b, 0x40, 0x4d,
4669 0x02, 0x0e, 0x09, 0x20, 0x55,
4670 0x02, 0x0d, 0x0a, 0x20, 0x49,
4671 0x02, 0x0c, 0x0b, 0x20, 0x3d,
4672 0x02, 0x0e, 0x08, 0x10, 0x51,
4673 0x02, 0x0d, 0x09, 0x10, 0x45,
4674 0x02, 0x0c, 0x0a, 0x10, 0x39,
4675 0x02, 0x0d, 0x08, 0x08, 0x41,
4676 0x02, 0x0c, 0x09, 0x08, 0x35,
4677 0x02, 0x0c, 0x08, 0x04, 0x31
4679 static const u8 dramsr13_4[4 * 5] = {
4680 0x02, 0x0d, 0x09, 0x40, 0x45,
4681 0x02, 0x0c, 0x09, 0x20, 0x35,
4682 0x02, 0x0c, 0x08, 0x10, 0x31,
4683 0x02, 0x0b, 0x08, 0x08, 0x21
4686 /* Enable linear mode, disable 0xa0000 address decoding */
4687 /* We disable a0000 address decoding, because
4688 * - if running on x86, if the card is disabled, it means
4689 * that another card is in the system. We don't want
4690 * to interphere with that primary card's textmode.
4691 * - if running on non-x86, there usually is no VGA window
4694 orSISIDXREG(SISSR, 0x20, (0x80 | 0x04));
4696 /* Need to map max FB size for finding out about RAM size */
4697 mapsize = 256 << 20;
4698 sisfb_post_map_vram(ivideo, &mapsize, 32);
4700 if(!ivideo->video_vbase) {
4701 printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
4702 outSISIDXREG(SISSR, 0x13, 0x35);
4703 outSISIDXREG(SISSR, 0x14, 0x41);
4708 /* Non-interleaving */
4709 outSISIDXREG(SISSR, 0x15, 0x00);
4711 outSISIDXREG(SISSR, 0x1c, 0x00);
4713 if(ivideo->chip == XGI_20) {
4716 inSISIDXREG(SISCR, 0x97, reg);
4717 if(!(reg & 0x01)) { /* Single 32/16 */
4719 outSISIDXREG(SISSR, 0x13, 0xb1);
4720 outSISIDXREG(SISSR, 0x14, 0x52);
4721 sisfb_post_xgi_delay(ivideo, 1);
4723 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4726 outSISIDXREG(SISSR, 0x13, 0x31);
4727 outSISIDXREG(SISSR, 0x14, 0x42);
4728 sisfb_post_xgi_delay(ivideo, 1);
4729 if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
4733 outSISIDXREG(SISSR, 0x13, 0xb1);
4734 outSISIDXREG(SISSR, 0x14, 0x41);
4735 sisfb_post_xgi_delay(ivideo, 1);
4737 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4740 outSISIDXREG(SISSR, 0x13, 0x31);
4741 } else { /* Dual 16/8 */
4743 outSISIDXREG(SISSR, 0x13, 0xb1);
4744 outSISIDXREG(SISSR, 0x14, 0x41);
4745 sisfb_post_xgi_delay(ivideo, 1);
4747 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4750 outSISIDXREG(SISSR, 0x13, 0x31);
4751 outSISIDXREG(SISSR, 0x14, 0x31);
4752 sisfb_post_xgi_delay(ivideo, 1);
4753 if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
4757 outSISIDXREG(SISSR, 0x13, 0xb1);
4758 outSISIDXREG(SISSR, 0x14, 0x30);
4759 sisfb_post_xgi_delay(ivideo, 1);
4761 if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
4764 outSISIDXREG(SISSR, 0x13, 0x31);
4767 } else { /* XGI_40 */
4769 inSISIDXREG(SISCR, 0x97, reg);
4771 inSISIDXREG(SISSR, 0x39, reg);
4775 if(reg & 0x01) { /* DDRII */
4777 if(ivideo->revision_id == 2) {
4779 outSISIDXREG(SISSR, 0x13, 0xa1);
4780 outSISIDXREG(SISSR, 0x14, 0x44);
4782 sisfb_post_xgi_delay(ivideo, 1);
4783 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4786 outSISIDXREG(SISSR, 0x13, 0x21);
4787 outSISIDXREG(SISSR, 0x14, 0x34);
4788 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4792 outSISIDXREG(SISSR, 0x13, 0xa1);
4793 outSISIDXREG(SISSR, 0x14, 0x40);
4795 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4798 outSISIDXREG(SISSR, 0x13, 0x21);
4799 outSISIDXREG(SISSR, 0x14, 0x30);
4802 outSISIDXREG(SISSR, 0x13, 0xa1);
4803 outSISIDXREG(SISSR, 0x14, 0x4c);
4805 sisfb_post_xgi_delay(ivideo, 1);
4806 if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
4810 outSISIDXREG(SISSR, 0x14, 0x48);
4811 sisfb_post_xgi_delay(ivideo, 1);
4813 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4816 outSISIDXREG(SISSR, 0x13, 0x21);
4817 outSISIDXREG(SISSR, 0x14, 0x3c);
4820 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
4824 outSISIDXREG(SISSR, 0x14, 0x38);
4828 sisfb_post_xgi_delay(ivideo, 1);
4833 if(ivideo->revision_id == 2) {
4835 outSISIDXREG(SISSR, 0x13, 0xa1);
4836 outSISIDXREG(SISSR, 0x14, 0x52);
4837 sisfb_post_xgi_delay(ivideo, 1);
4839 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4842 outSISIDXREG(SISSR, 0x13, 0x21);
4843 outSISIDXREG(SISSR, 0x14, 0x42);
4846 outSISIDXREG(SISSR, 0x13, 0xa1);
4847 outSISIDXREG(SISSR, 0x14, 0x5a);
4848 sisfb_post_xgi_delay(ivideo, 1);
4850 if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
4853 outSISIDXREG(SISSR, 0x13, 0x21);
4854 outSISIDXREG(SISSR, 0x14, 0x4a);
4856 sisfb_post_xgi_delay(ivideo, 1);
4862 setSISIDXREG(SISSR, 0x14, 0xf0, sr14);
4863 sisfb_post_xgi_delay(ivideo, 1);
4865 j = (ivideo->chip == XGI_20) ? 5 : 9;
4866 k = (ivideo->chip == XGI_20) ? 12 : 4;
4868 for(i = 0; i < k; i++) {
4870 reg = (ivideo->chip == XGI_20) ?
4871 dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
4872 setSISIDXREG(SISSR, 0x13, 0x80, reg);
4873 sisfb_post_xgi_delay(ivideo, 50);
4875 ranksize = (ivideo->chip == XGI_20) ?
4876 dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
4878 inSISIDXREG(SISSR, 0x13, reg);
4879 if(reg & 0x80) ranksize <<= 1;
4881 if(ivideo->chip == XGI_20) {
4882 if(buswidth == 16) ranksize <<= 1;
4883 else if(buswidth == 32) ranksize <<= 2;
4885 if(buswidth == 64) ranksize <<= 1;
4891 if((ranksize * l) <= 256) {
4892 while((ranksize >>= 1)) reg += 0x10;
4897 setSISIDXREG(SISSR, 0x14, 0x0f, (reg & 0xf0));
4898 sisfb_post_xgi_delay(ivideo, 1);
4900 if(sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize))
4904 iounmap(ivideo->video_vbase);
4907 static void __devinit
4908 sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
4912 static const u8 cs90[8 * 3] = {
4922 static const u8 csb8[8 * 3] = {
4936 v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2];
4937 if(ivideo->haveXGIROM) {
4938 v1 = ivideo->bios_abase[0x90 + index];
4939 v2 = ivideo->bios_abase[0x90 + index + 1];
4940 v3 = ivideo->bios_abase[0x90 + index + 2];
4942 outSISIDXREG(SISSR, 0x28, v1);
4943 outSISIDXREG(SISSR, 0x29, v2);
4944 outSISIDXREG(SISSR, 0x2a, v3);
4945 sisfb_post_xgi_delay(ivideo, 0x43);
4946 sisfb_post_xgi_delay(ivideo, 0x43);
4947 sisfb_post_xgi_delay(ivideo, 0x43);
4949 v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2];
4950 if(ivideo->haveXGIROM) {
4951 v1 = ivideo->bios_abase[0xb8 + index];
4952 v2 = ivideo->bios_abase[0xb8 + index + 1];
4953 v3 = ivideo->bios_abase[0xb8 + index + 2];
4955 outSISIDXREG(SISSR, 0x2e, v1);
4956 outSISIDXREG(SISSR, 0x2f, v2);
4957 outSISIDXREG(SISSR, 0x30, v3);
4958 sisfb_post_xgi_delay(ivideo, 0x43);
4959 sisfb_post_xgi_delay(ivideo, 0x43);
4960 sisfb_post_xgi_delay(ivideo, 0x43);
4963 static int __devinit
4964 sisfb_post_xgi(struct pci_dev *pdev)
4966 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4967 unsigned char *bios = ivideo->bios_abase;
4968 struct pci_dev *mypdev = NULL;
4969 const u8 *ptr, *ptr2;
4970 u8 v1, v2, v3, v4, v5, reg, ramtype;
4971 u32 rega, regb, regd;
4973 static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 };
4974 static const u8 cs76[2] = { 0xa3, 0xfb };
4975 static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 };
4976 static const u8 cs158[8] = {
4977 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
4979 static const u8 cs160[8] = {
4980 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
4982 static const u8 cs168[8] = {
4983 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
4985 static const u8 cs128[3 * 8] = {
4986 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
4987 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
4988 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
4990 static const u8 cs148[2 * 8] = {
4991 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
4992 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4994 static const u8 cs31a[8 * 4] = {
4995 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
4996 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
4997 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4998 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5000 static const u8 cs33a[8 * 4] = {
5001 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5002 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5003 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5004 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5006 static const u8 cs45a[8 * 2] = {
5007 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
5008 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5010 static const u8 cs170[7 * 8] = {
5011 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5012 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5013 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
5014 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5015 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5016 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5017 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5019 static const u8 cs1a8[3 * 8] = {
5020 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5021 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5022 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5024 static const u8 cs100[2 * 8] = {
5025 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5026 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5030 reg = inSISREG(SISVGAENABLE) | 0x01;
5031 outSISREG(SISVGAENABLE, reg);
5034 reg = inSISREG(SISMISCR) | 0x01;
5035 outSISREG(SISMISCW, reg);
5038 outSISIDXREG(SISSR, 0x05, 0x86);
5039 inSISIDXREG(SISSR, 0x05, reg);
5043 /* Clear some regs */
5044 for(i = 0; i < 0x22; i++) {
5045 if(0x06 + i == 0x20) continue;
5046 outSISIDXREG(SISSR, 0x06 + i, 0x00);
5048 for(i = 0; i < 0x0b; i++) {
5049 outSISIDXREG(SISSR, 0x31 + i, 0x00);
5051 for(i = 0; i < 0x10; i++) {
5052 outSISIDXREG(SISCR, 0x30 + i, 0x00);
5056 if(ivideo->haveXGIROM) {
5057 ptr = (const u8 *)&bios[0x78];
5059 for(i = 0; i < 3; i++) {
5060 outSISIDXREG(SISSR, 0x23 + i, ptr[i]);
5064 if(ivideo->haveXGIROM) {
5065 ptr = (const u8 *)&bios[0x76];
5067 for(i = 0; i < 2; i++) {
5068 outSISIDXREG(SISSR, 0x21 + i, ptr[i]);
5071 v1 = 0x18; v2 = 0x00;
5072 if(ivideo->haveXGIROM) {
5076 outSISIDXREG(SISSR, 0x07, v1);
5077 outSISIDXREG(SISSR, 0x11, 0x0f);
5078 outSISIDXREG(SISSR, 0x1f, v2);
5079 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5080 outSISIDXREG(SISSR, 0x20, 0x80 | 0x20 | 0x04);
5081 outSISIDXREG(SISSR, 0x27, 0x74);
5084 if(ivideo->haveXGIROM) {
5085 ptr = (const u8 *)&bios[0x7b];
5087 for(i = 0; i < 3; i++) {
5088 outSISIDXREG(SISSR, 0x31 + i, ptr[i]);
5091 if(ivideo->chip == XGI_40) {
5092 if(ivideo->revision_id == 2) {
5093 setSISIDXREG(SISSR, 0x3b, 0x3f, 0xc0);
5095 outSISIDXREG(SISCR, 0x7d, 0xfe);
5096 outSISIDXREG(SISCR, 0x7e, 0x0f);
5098 if(ivideo->revision_id == 0) { /* 40 *and* 20? */
5099 andSISIDXREG(SISCR, 0x58, 0xd7);
5100 inSISIDXREG(SISCR, 0xcb, reg);
5102 setSISIDXREG(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5106 reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
5107 setSISIDXREG(SISCR, 0x38, 0x1f, reg);
5109 if(ivideo->chip == XGI_20) {
5110 outSISIDXREG(SISSR, 0x36, 0x70);
5112 outSISIDXREG(SISVID, 0x00, 0x86);
5113 outSISIDXREG(SISVID, 0x32, 0x00);
5114 outSISIDXREG(SISVID, 0x30, 0x00);
5115 outSISIDXREG(SISVID, 0x32, 0x01);
5116 outSISIDXREG(SISVID, 0x30, 0x00);
5117 andSISIDXREG(SISVID, 0x2f, 0xdf);
5118 andSISIDXREG(SISCAP, 0x00, 0x3f);
5120 outSISIDXREG(SISPART1, 0x2f, 0x01);
5121 outSISIDXREG(SISPART1, 0x00, 0x00);
5122 outSISIDXREG(SISPART1, 0x02, bios[0x7e]);
5123 outSISIDXREG(SISPART1, 0x2e, 0x08);
5124 andSISIDXREG(SISPART1, 0x35, 0x7f);
5125 andSISIDXREG(SISPART1, 0x50, 0xfe);
5127 inSISIDXREG(SISPART4, 0x00, reg);
5128 if(reg == 1 || reg == 2) {
5129 outSISIDXREG(SISPART2, 0x00, 0x1c);
5130 outSISIDXREG(SISPART4, 0x0d, bios[0x7f]);
5131 outSISIDXREG(SISPART4, 0x0e, bios[0x80]);
5132 outSISIDXREG(SISPART4, 0x10, bios[0x81]);
5133 andSISIDXREG(SISPART4, 0x0f, 0x3f);
5135 inSISIDXREG(SISPART4, 0x01, reg);
5136 if((reg & 0xf0) >= 0xb0) {
5137 inSISIDXREG(SISPART4, 0x23, reg);
5138 if(reg & 0x20) reg |= 0x40;
5139 outSISIDXREG(SISPART4, 0x23, reg);
5140 reg = (reg & 0x20) ? 0x02 : 0x00;
5141 setSISIDXREG(SISPART1, 0x1e, 0xfd, reg);
5147 inSISIDXREG(SISSR, 0x3b, reg);
5149 inSISIDXREG(SISSR, 0x3a, reg);
5150 v2 = (reg & 0x30) >> 3;
5151 if(!(v2 & 0x04)) v2 ^= 0x02;
5152 inSISIDXREG(SISSR, 0x39, reg);
5153 if(reg & 0x80) v2 |= 0x80;
5156 if((mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
5157 pci_dev_put(mypdev);
5158 if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
5163 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0735, NULL);
5165 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0645, NULL);
5167 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0650, NULL);
5169 pci_read_config_dword(mypdev, 0x94, ®d);
5171 pci_write_config_dword(mypdev, 0x94, regd);
5173 pci_dev_put(mypdev);
5174 } else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) {
5176 } else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) ||
5177 sisfb_find_host_bridge(ivideo, pdev, 0x1022) ||
5178 sisfb_find_host_bridge(ivideo, pdev, 0x700e) ||
5179 sisfb_find_host_bridge(ivideo, pdev, 0x10de)) {
5180 if((v2 & 0x06) == 4)
5185 setSISIDXREG(SISCR, 0x5f, 0xf0, v2);
5187 outSISIDXREG(SISSR, 0x22, v1);
5189 if(ivideo->revision_id == 2) {
5190 inSISIDXREG(SISSR, 0x3b, v1);
5191 inSISIDXREG(SISSR, 0x3a, v2);
5192 regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
5193 if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
5194 setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01);
5196 if((mypdev = pci_get_device(0x10de, 0x01e0, NULL))) {
5197 /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5201 setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01);
5202 pci_dev_put(mypdev);
5207 inSISIDXREG(SISSR, 0x3b, reg);
5208 inSISIDXREG(SISCR, 0x5f, v2);
5209 if((!(reg & 0x02)) && (v2 & 0x0e))
5211 outSISIDXREG(SISSR, 0x27, v1);
5213 if(bios[0x64] & 0x01) {
5214 setSISIDXREG(SISCR, 0x5f, 0xf0, bios[0x64]);
5218 pci_read_config_dword(pdev, 0x50, ®d);
5219 regd = (regd >> 20) & 0x0f;
5222 orSISIDXREG(SISCR, 0x5f, 0x08);
5224 outSISIDXREG(SISCR, 0x48, v1);
5226 setSISIDXREG(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
5227 setSISIDXREG(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
5228 setSISIDXREG(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
5229 setSISIDXREG(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
5230 setSISIDXREG(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
5231 outSISIDXREG(SISCR, 0x70, bios[0x4fc]);
5232 setSISIDXREG(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
5233 outSISIDXREG(SISCR, 0x74, 0xd0);
5234 setSISIDXREG(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
5235 setSISIDXREG(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
5236 setSISIDXREG(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
5238 if((mypdev = pci_get_device(0x8086, 0x2530, NULL))) {
5240 pci_dev_put(mypdev);
5242 outSISIDXREG(SISCR, 0x77, v1);
5250 if(ivideo->haveXGIROM) {
5251 v1 = bios[0x140 + regb];
5253 outSISIDXREG(SISCR, 0x6d, v1);
5256 if(ivideo->haveXGIROM) {
5257 ptr = (const u8 *)&bios[0x128];
5259 for(i = 0, j = 0; i < 3; i++, j += 8) {
5260 outSISIDXREG(SISCR, 0x68 + i, ptr[j + regb]);
5265 if(ivideo->haveXGIROM) {
5266 index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6;
5267 ptr = (const u8 *)&bios[index];
5268 ptr2 = (const u8 *)&bios[index + 0x20];
5270 for(i = 0; i < 2; i++) {
5272 regd = le32_to_cpu(((u32 *)ptr)[regb]);
5275 regd = le32_to_cpu(((u32 *)ptr2)[regb]);
5279 for(j = 0; j < 16; j++) {
5281 if(regd & 0x01) reg |= 0x04;
5282 if(regd & 0x02) reg |= 0x08;
5284 outSISIDXREG(SISCR, rega, reg);
5285 inSISIDXREG(SISCR, rega, reg);
5286 inSISIDXREG(SISCR, rega, reg);
5291 andSISIDXREG(SISCR, 0x6e, 0xfc);
5294 if(ivideo->haveXGIROM) {
5295 index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6;
5296 ptr = (const u8 *)&bios[index];
5298 for(i = 0; i < 4; i++) {
5299 setSISIDXREG(SISCR, 0x6e, 0xfc, i);
5301 for(j = 0; j < 2; j++) {
5304 regd = le32_to_cpu(((u32 *)ptr)[regb * 8]);
5308 for(k = 0; k < 16; k++) {
5310 if(regd & 0x01) reg |= 0x01;
5311 if(regd & 0x02) reg |= 0x02;
5313 outSISIDXREG(SISCR, 0x6f, reg);
5314 inSISIDXREG(SISCR, 0x6f, reg);
5315 inSISIDXREG(SISCR, 0x6f, reg);
5322 if(ivideo->haveXGIROM) {
5323 ptr = (const u8 *)&bios[0x148];
5325 for(i = 0, j = 0; i < 2; i++, j += 8) {
5326 outSISIDXREG(SISCR, 0x80 + i, ptr[j + regb]);
5329 andSISIDXREG(SISCR, 0x89, 0x8f);
5332 if(ivideo->haveXGIROM) {
5333 index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6;
5334 ptr = (const u8 *)&bios[index];
5336 regd = le16_to_cpu(((const u16 *)ptr)[regb]);
5338 for(i = 0; i < 5; i++) {
5340 if(regd & 0x01) reg |= 0x01;
5341 if(regd & 0x02) reg |= 0x02;
5343 outSISIDXREG(SISCR, 0x89, reg);
5344 inSISIDXREG(SISCR, 0x89, reg);
5345 inSISIDXREG(SISCR, 0x89, reg);
5349 v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13;
5350 if(ivideo->haveXGIROM) {
5351 v1 = bios[0x118 + regb];
5352 v2 = bios[0xf8 + regb];
5353 v3 = bios[0x120 + regb];
5356 outSISIDXREG(SISCR, 0x45, v1 & 0x0f);
5357 outSISIDXREG(SISCR, 0x99, (v1 >> 4) & 0x07);
5358 orSISIDXREG(SISCR, 0x40, v1 & 0x80);
5359 outSISIDXREG(SISCR, 0x41, v2);
5362 if(ivideo->haveXGIROM) {
5363 ptr = (const u8 *)&bios[0x170];
5365 for(i = 0, j = 0; i < 7; i++, j += 8) {
5366 outSISIDXREG(SISCR, 0x90 + i, ptr[j + regb]);
5369 outSISIDXREG(SISCR, 0x59, v3);
5372 if(ivideo->haveXGIROM) {
5373 ptr = (const u8 *)&bios[0x1a8];
5375 for(i = 0, j = 0; i < 3; i++, j += 8) {
5376 outSISIDXREG(SISCR, 0xc3 + i, ptr[j + regb]);
5380 if(ivideo->haveXGIROM) {
5381 ptr = (const u8 *)&bios[0x100];
5383 for(i = 0, j = 0; i < 2; i++, j += 8) {
5384 outSISIDXREG(SISCR, 0x8a + i, ptr[j + regb]);
5387 outSISIDXREG(SISCR, 0xcf, v4);
5389 outSISIDXREG(SISCR, 0x83, 0x09);
5390 outSISIDXREG(SISCR, 0x87, 0x00);
5392 if(ivideo->chip == XGI_40) {
5393 if( (ivideo->revision_id == 1) ||
5394 (ivideo->revision_id == 2) ) {
5395 outSISIDXREG(SISCR, 0x8c, 0x87);
5399 outSISIDXREG(SISSR, 0x17, 0x00);
5400 outSISIDXREG(SISSR, 0x1a, 0x87);
5402 if(ivideo->chip == XGI_20) {
5403 outSISIDXREG(SISSR, 0x15, 0x00);
5404 outSISIDXREG(SISSR, 0x1c, 0x00);
5407 ramtype = 0x00; v1 = 0x10;
5408 if(ivideo->haveXGIROM) {
5409 ramtype = bios[0x62];
5412 if(!(ramtype & 0x80)) {
5413 if(ivideo->chip == XGI_20) {
5414 outSISIDXREG(SISCR, 0x97, v1);
5415 inSISIDXREG(SISCR, 0x97, reg);
5417 ramtype = (reg & 0x01) << 1;
5420 inSISIDXREG(SISSR, 0x39, reg);
5421 ramtype = reg & 0x02;
5423 inSISIDXREG(SISSR, 0x3a, reg);
5424 ramtype = (reg >> 1) & 0x01;
5434 sisfb_post_xgi_setclocks(ivideo, regb);
5435 if((ivideo->chip == XGI_20) ||
5436 (ivideo->revision_id == 1) ||
5437 (ivideo->revision_id == 2)) {
5438 v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb];
5439 if(ivideo->haveXGIROM) {
5440 v1 = bios[regb + 0x158];
5441 v2 = bios[regb + 0x160];
5442 v3 = bios[regb + 0x168];
5444 outSISIDXREG(SISCR, 0x82, v1);
5445 outSISIDXREG(SISCR, 0x85, v2);
5446 outSISIDXREG(SISCR, 0x86, v3);
5448 outSISIDXREG(SISCR, 0x82, 0x88);
5449 outSISIDXREG(SISCR, 0x86, 0x00);
5450 inSISIDXREG(SISCR, 0x86, reg);
5451 outSISIDXREG(SISCR, 0x86, 0x88);
5452 inSISIDXREG(SISCR, 0x86, reg);
5453 outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]);
5454 outSISIDXREG(SISCR, 0x82, 0x77);
5455 outSISIDXREG(SISCR, 0x85, 0x00);
5456 inSISIDXREG(SISCR, 0x85, reg);
5457 outSISIDXREG(SISCR, 0x85, 0x88);
5458 inSISIDXREG(SISCR, 0x85, reg);
5459 outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]);
5460 outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]);
5462 if(ivideo->chip == XGI_40) {
5463 outSISIDXREG(SISCR, 0x97, 0x00);
5465 outSISIDXREG(SISCR, 0x98, 0x01);
5466 outSISIDXREG(SISCR, 0x9a, 0x02);
5468 outSISIDXREG(SISSR, 0x18, 0x01);
5469 if((ivideo->chip == XGI_20) ||
5470 (ivideo->revision_id == 2)) {
5471 outSISIDXREG(SISSR, 0x19, 0x40);
5473 outSISIDXREG(SISSR, 0x19, 0x20);
5475 outSISIDXREG(SISSR, 0x16, 0x00);
5476 outSISIDXREG(SISSR, 0x16, 0x80);
5477 if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
5478 sisfb_post_xgi_delay(ivideo, 0x43);
5479 sisfb_post_xgi_delay(ivideo, 0x43);
5480 sisfb_post_xgi_delay(ivideo, 0x43);
5481 outSISIDXREG(SISSR, 0x18, 0x00);
5482 if((ivideo->chip == XGI_20) ||
5483 (ivideo->revision_id == 2)) {
5484 outSISIDXREG(SISSR, 0x19, 0x40);
5486 outSISIDXREG(SISSR, 0x19, 0x20);
5488 } else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
5489 /* outSISIDXREG(SISSR, 0x16, 0x0c); */ /* ? */
5491 outSISIDXREG(SISSR, 0x16, 0x00);
5492 outSISIDXREG(SISSR, 0x16, 0x80);
5493 sisfb_post_xgi_delay(ivideo, 4);
5494 v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
5495 if(ivideo->haveXGIROM) {
5497 index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e;
5499 v3 = bios[index + 1];
5500 v4 = bios[index + 2];
5501 v5 = bios[index + 3];
5503 outSISIDXREG(SISSR, 0x18, v1);
5504 outSISIDXREG(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
5505 outSISIDXREG(SISSR, 0x16, v2);
5506 outSISIDXREG(SISSR, 0x16, v3);
5507 sisfb_post_xgi_delay(ivideo, 0x43);
5508 outSISIDXREG(SISSR, 0x1b, 0x03);
5509 sisfb_post_xgi_delay(ivideo, 0x22);
5510 outSISIDXREG(SISSR, 0x18, v1);
5511 outSISIDXREG(SISSR, 0x19, 0x00);
5512 outSISIDXREG(SISSR, 0x16, v4);
5513 outSISIDXREG(SISSR, 0x16, v5);
5514 outSISIDXREG(SISSR, 0x1b, 0x00);
5517 outSISIDXREG(SISCR, 0x82, 0x77);
5518 outSISIDXREG(SISCR, 0x86, 0x00);
5519 inSISIDXREG(SISCR, 0x86, reg);
5520 outSISIDXREG(SISCR, 0x86, 0x88);
5521 inSISIDXREG(SISCR, 0x86, reg);
5522 v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
5523 if(ivideo->haveXGIROM) {
5524 v1 = bios[regb + 0x168];
5525 v2 = bios[regb + 0x160];
5526 v3 = bios[regb + 0x158];
5528 outSISIDXREG(SISCR, 0x86, v1);
5529 outSISIDXREG(SISCR, 0x82, 0x77);
5530 outSISIDXREG(SISCR, 0x85, 0x00);
5531 inSISIDXREG(SISCR, 0x85, reg);
5532 outSISIDXREG(SISCR, 0x85, 0x88);
5533 inSISIDXREG(SISCR, 0x85, reg);
5534 outSISIDXREG(SISCR, 0x85, v2);
5535 outSISIDXREG(SISCR, 0x82, v3);
5536 outSISIDXREG(SISCR, 0x98, 0x01);
5537 outSISIDXREG(SISCR, 0x9a, 0x02);
5539 outSISIDXREG(SISSR, 0x28, 0x64);
5540 outSISIDXREG(SISSR, 0x29, 0x63);
5541 sisfb_post_xgi_delay(ivideo, 15);
5542 outSISIDXREG(SISSR, 0x18, 0x00);
5543 outSISIDXREG(SISSR, 0x19, 0x20);
5544 outSISIDXREG(SISSR, 0x16, 0x00);
5545 outSISIDXREG(SISSR, 0x16, 0x80);
5546 outSISIDXREG(SISSR, 0x18, 0xc5);
5547 outSISIDXREG(SISSR, 0x19, 0x23);
5548 outSISIDXREG(SISSR, 0x16, 0x00);
5549 outSISIDXREG(SISSR, 0x16, 0x80);
5550 sisfb_post_xgi_delay(ivideo, 1);
5551 outSISIDXREG(SISCR, 0x97,0x11);
5552 sisfb_post_xgi_setclocks(ivideo, regb);
5553 sisfb_post_xgi_delay(ivideo, 0x46);
5554 outSISIDXREG(SISSR, 0x18, 0xc5);
5555 outSISIDXREG(SISSR, 0x19, 0x23);
5556 outSISIDXREG(SISSR, 0x16, 0x00);
5557 outSISIDXREG(SISSR, 0x16, 0x80);
5558 sisfb_post_xgi_delay(ivideo, 1);
5559 outSISIDXREG(SISSR, 0x1b, 0x04);
5560 sisfb_post_xgi_delay(ivideo, 1);
5561 outSISIDXREG(SISSR, 0x1b, 0x00);
5562 sisfb_post_xgi_delay(ivideo, 1);
5564 if(ivideo->haveXGIROM) {
5567 outSISIDXREG(SISSR, 0x18, v1);
5568 outSISIDXREG(SISSR, 0x19, 0x06);
5569 outSISIDXREG(SISSR, 0x16, 0x04);
5570 outSISIDXREG(SISSR, 0x16, 0x84);
5571 sisfb_post_xgi_delay(ivideo, 1);
5574 sisfb_post_xgi_setclocks(ivideo, regb);
5575 if((ivideo->chip == XGI_40) &&
5576 ((ivideo->revision_id == 1) ||
5577 (ivideo->revision_id == 2))) {
5578 outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]);
5579 outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]);
5580 outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]);
5582 outSISIDXREG(SISCR, 0x82, 0x88);
5583 outSISIDXREG(SISCR, 0x86, 0x00);
5584 inSISIDXREG(SISCR, 0x86, reg);
5585 outSISIDXREG(SISCR, 0x86, 0x88);
5586 outSISIDXREG(SISCR, 0x82, 0x77);
5587 outSISIDXREG(SISCR, 0x85, 0x00);
5588 inSISIDXREG(SISCR, 0x85, reg);
5589 outSISIDXREG(SISCR, 0x85, 0x88);
5590 inSISIDXREG(SISCR, 0x85, reg);
5591 v1 = cs160[regb]; v2 = cs158[regb];
5592 if(ivideo->haveXGIROM) {
5593 v1 = bios[regb + 0x160];
5594 v2 = bios[regb + 0x158];
5596 outSISIDXREG(SISCR, 0x85, v1);
5597 outSISIDXREG(SISCR, 0x82, v2);
5599 if(ivideo->chip == XGI_40) {
5600 outSISIDXREG(SISCR, 0x97, 0x11);
5602 if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
5603 outSISIDXREG(SISCR, 0x98, 0x01);
5605 outSISIDXREG(SISCR, 0x98, 0x03);
5607 outSISIDXREG(SISCR, 0x9a, 0x02);
5609 if(ivideo->chip == XGI_40) {
5610 outSISIDXREG(SISSR, 0x18, 0x01);
5612 outSISIDXREG(SISSR, 0x18, 0x00);
5614 outSISIDXREG(SISSR, 0x19, 0x40);
5615 outSISIDXREG(SISSR, 0x16, 0x00);
5616 outSISIDXREG(SISSR, 0x16, 0x80);
5617 if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
5618 sisfb_post_xgi_delay(ivideo, 0x43);
5619 sisfb_post_xgi_delay(ivideo, 0x43);
5620 sisfb_post_xgi_delay(ivideo, 0x43);
5621 outSISIDXREG(SISSR, 0x18, 0x00);
5622 outSISIDXREG(SISSR, 0x19, 0x40);
5623 outSISIDXREG(SISSR, 0x16, 0x00);
5624 outSISIDXREG(SISSR, 0x16, 0x80);
5626 sisfb_post_xgi_delay(ivideo, 4);
5628 if(ivideo->haveXGIROM) {
5631 outSISIDXREG(SISSR, 0x18, v1);
5632 outSISIDXREG(SISSR, 0x19, 0x01);
5633 if(ivideo->chip == XGI_40) {
5634 outSISIDXREG(SISSR, 0x16, bios[0x53e]);
5635 outSISIDXREG(SISSR, 0x16, bios[0x53f]);
5637 outSISIDXREG(SISSR, 0x16, 0x05);
5638 outSISIDXREG(SISSR, 0x16, 0x85);
5640 sisfb_post_xgi_delay(ivideo, 0x43);
5641 if(ivideo->chip == XGI_40) {
5642 outSISIDXREG(SISSR, 0x1b, 0x01);
5644 outSISIDXREG(SISSR, 0x1b, 0x03);
5646 sisfb_post_xgi_delay(ivideo, 0x22);
5647 outSISIDXREG(SISSR, 0x18, v1);
5648 outSISIDXREG(SISSR, 0x19, 0x00);
5649 if(ivideo->chip == XGI_40) {
5650 outSISIDXREG(SISSR, 0x16, bios[0x540]);
5651 outSISIDXREG(SISSR, 0x16, bios[0x541]);
5653 outSISIDXREG(SISSR, 0x16, 0x05);
5654 outSISIDXREG(SISSR, 0x16, 0x85);
5656 outSISIDXREG(SISSR, 0x1b, 0x00);
5661 if(ivideo->haveXGIROM) {
5662 v1 = bios[0x110 + regb];
5664 outSISIDXREG(SISSR, 0x1b, v1);
5667 v1 = 0x00; v2 = 0x00;
5668 if(ivideo->haveXGIROM) {
5674 if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
5676 outSISIDXREG(SISSR, 0x13, bios[regb + 0xe0]);
5677 outSISIDXREG(SISSR, 0x14, bios[regb + 0xe0 + 8]);
5681 /* Set default mode, don't clear screen */
5682 ivideo->SiS_Pr.SiS_UseOEM = false;
5683 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
5684 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
5685 ivideo->curFSTN = ivideo->curDSTN = 0;
5686 ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
5687 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5689 outSISIDXREG(SISSR, 0x05, 0x86);
5691 /* Disable read-cache */
5692 andSISIDXREG(SISSR, 0x21, 0xdf);
5693 sisfb_post_xgi_ramsize(ivideo);
5694 /* Enable read-cache */
5695 orSISIDXREG(SISSR, 0x21, 0x20);
5700 printk(KERN_DEBUG "-----------------\n");
5701 for(i = 0; i < 0xff; i++) {
5702 inSISIDXREG(SISCR, i, reg);
5703 printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
5705 for(i = 0; i < 0x40; i++) {
5706 inSISIDXREG(SISSR, i, reg);
5707 printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
5709 printk(KERN_DEBUG "-----------------\n");
5713 if(ivideo->chip == XGI_20) {
5714 orSISIDXREG(SISCR, 0x32, 0x20);
5716 inSISIDXREG(SISPART4, 0x00, reg);
5717 if((reg == 1) || (reg == 2)) {
5718 sisfb_sense_crt1(ivideo);
5720 orSISIDXREG(SISCR, 0x32, 0x20);
5724 /* Set default mode, don't clear screen */
5725 ivideo->SiS_Pr.SiS_UseOEM = false;
5726 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
5727 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
5728 ivideo->curFSTN = ivideo->curDSTN = 0;
5729 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5731 outSISIDXREG(SISSR, 0x05, 0x86);
5734 orSISIDXREG(SISSR, 0x01, 0x20);
5736 /* Save mode number in CR34 */
5737 outSISIDXREG(SISCR, 0x34, 0x2e);
5739 /* Let everyone know what the current mode is */
5740 ivideo->modeprechange = 0x2e;
5742 if(ivideo->chip == XGI_40) {
5743 inSISIDXREG(SISCR, 0xca, reg);
5744 inSISIDXREG(SISCR, 0xcc, v1);
5745 if((reg & 0x10) && (!(v1 & 0x04))) {
5747 "sisfb: Please connect power to the card.\n");
5756 static int __devinit
5757 sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
5759 struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data];
5760 struct sis_video_info *ivideo = NULL;
5761 struct fb_info *sis_fb_info = NULL;
5769 sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
5773 ivideo = (struct sis_video_info *)sis_fb_info->par;
5774 ivideo->memyselfandi = sis_fb_info;
5776 ivideo->sisfb_id = SISFB_ID;
5778 if(card_list == NULL) {
5779 ivideo->cardnumber = 0;
5781 struct sis_video_info *countvideo = card_list;
5782 ivideo->cardnumber = 1;
5783 while((countvideo = countvideo->next) != 0)
5784 ivideo->cardnumber++;
5787 strncpy(ivideo->myid, chipinfo->chip_name, 30);
5789 ivideo->warncount = 0;
5790 ivideo->chip_id = pdev->device;
5791 ivideo->chip_vendor = pdev->vendor;
5792 pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo->revision_id);
5793 ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
5794 pci_read_config_word(pdev, PCI_COMMAND, ®16);
5795 ivideo->sisvga_enabled = reg16 & 0x01;
5796 ivideo->pcibus = pdev->bus->number;
5797 ivideo->pcislot = PCI_SLOT(pdev->devfn);
5798 ivideo->pcifunc = PCI_FUNC(pdev->devfn);
5799 ivideo->subsysvendor = pdev->subsystem_vendor;
5800 ivideo->subsysdevice = pdev->subsystem_device;
5801 #ifdef SIS_OLD_CONFIG_COMPAT
5802 ivideo->ioctl32registered = 0;
5806 if(sisfb_mode_idx == -1) {
5807 sisfb_get_vga_mode_from_kernel();
5811 ivideo->chip = chipinfo->chip;
5812 ivideo->sisvga_engine = chipinfo->vgaengine;
5813 ivideo->hwcursor_size = chipinfo->hwcursor_size;
5814 ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
5815 ivideo->mni = chipinfo->mni;
5817 ivideo->detectedpdc = 0xff;
5818 ivideo->detectedpdca = 0xff;
5819 ivideo->detectedlcda = 0xff;
5821 ivideo->sisfb_thismonitor.datavalid = false;
5823 ivideo->current_base = 0;
5825 ivideo->engineok = 0;
5827 ivideo->sisfb_was_boot_device = 0;
5828 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))
5829 if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
5830 if(ivideo->sisvga_enabled)
5831 ivideo->sisfb_was_boot_device = 1;
5833 printk(KERN_DEBUG "sisfb: PCI device is disabled, "
5834 "but marked as boot video device ???\n");
5835 printk(KERN_DEBUG "sisfb: I will not accept this "
5836 "as the primary VGA device\n");
5841 ivideo->sisfb_parm_mem = sisfb_parm_mem;
5842 ivideo->sisfb_accel = sisfb_accel;
5843 ivideo->sisfb_ypan = sisfb_ypan;
5844 ivideo->sisfb_max = sisfb_max;
5845 ivideo->sisfb_userom = sisfb_userom;
5846 ivideo->sisfb_useoem = sisfb_useoem;
5847 ivideo->sisfb_mode_idx = sisfb_mode_idx;
5848 ivideo->sisfb_parm_rate = sisfb_parm_rate;
5849 ivideo->sisfb_crt1off = sisfb_crt1off;
5850 ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
5851 ivideo->sisfb_crt2type = sisfb_crt2type;
5852 ivideo->sisfb_crt2flags = sisfb_crt2flags;
5853 /* pdc(a), scalelcd, special timing, lvdshl handled below */
5854 ivideo->sisfb_dstn = sisfb_dstn;
5855 ivideo->sisfb_fstn = sisfb_fstn;
5856 ivideo->sisfb_tvplug = sisfb_tvplug;
5857 ivideo->sisfb_tvstd = sisfb_tvstd;
5858 ivideo->tvxpos = sisfb_tvxposoffset;
5859 ivideo->tvypos = sisfb_tvyposoffset;
5860 ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
5861 ivideo->refresh_rate = 0;
5862 if(ivideo->sisfb_parm_rate != -1) {
5863 ivideo->refresh_rate = ivideo->sisfb_parm_rate;
5866 ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
5867 ivideo->SiS_Pr.CenterScreen = -1;
5868 ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
5869 ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
5871 ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
5872 ivideo->SiS_Pr.SiS_CHOverScan = -1;
5873 ivideo->SiS_Pr.SiS_ChSW = false;
5874 ivideo->SiS_Pr.SiS_UseLCDA = false;
5875 ivideo->SiS_Pr.HaveEMI = false;
5876 ivideo->SiS_Pr.HaveEMILCD = false;
5877 ivideo->SiS_Pr.OverruleEMI = false;
5878 ivideo->SiS_Pr.SiS_SensibleSR11 = false;
5879 ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
5880 ivideo->SiS_Pr.PDC = -1;
5881 ivideo->SiS_Pr.PDCA = -1;
5882 ivideo->SiS_Pr.DDCPortMixup = false;
5883 #ifdef CONFIG_FB_SIS_315
5884 if(ivideo->chip >= SIS_330) {
5885 ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
5886 if(ivideo->chip >= SIS_661) {
5887 ivideo->SiS_Pr.SiS_SensibleSR11 = true;
5892 memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));
5894 pci_set_drvdata(pdev, ivideo);
5896 /* Patch special cases */
5897 if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) {
5898 switch(ivideo->nbridge->device) {
5899 #ifdef CONFIG_FB_SIS_300
5900 case PCI_DEVICE_ID_SI_730:
5901 ivideo->chip = SIS_730;
5902 strcpy(ivideo->myid, "SiS 730");
5905 #ifdef CONFIG_FB_SIS_315
5906 case PCI_DEVICE_ID_SI_651:
5907 /* ivideo->chip is ok */
5908 strcpy(ivideo->myid, "SiS 651");
5910 case PCI_DEVICE_ID_SI_740:
5911 ivideo->chip = SIS_740;
5912 strcpy(ivideo->myid, "SiS 740");
5914 case PCI_DEVICE_ID_SI_661:
5915 ivideo->chip = SIS_661;
5916 strcpy(ivideo->myid, "SiS 661");
5918 case PCI_DEVICE_ID_SI_741:
5919 ivideo->chip = SIS_741;
5920 strcpy(ivideo->myid, "SiS 741");
5922 case PCI_DEVICE_ID_SI_760:
5923 ivideo->chip = SIS_760;
5924 strcpy(ivideo->myid, "SiS 760");
5926 case PCI_DEVICE_ID_SI_761:
5927 ivideo->chip = SIS_761;
5928 strcpy(ivideo->myid, "SiS 761");
5936 ivideo->SiS_Pr.ChipType = ivideo->chip;
5938 ivideo->SiS_Pr.ivideo = (void *)ivideo;
5940 #ifdef CONFIG_FB_SIS_315
5941 if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
5942 (ivideo->SiS_Pr.ChipType == SIS_315)) {
5943 ivideo->SiS_Pr.ChipType = SIS_315H;
5947 if(!ivideo->sisvga_enabled) {
5948 if(pci_enable_device(pdev)) {
5949 if(ivideo->nbridge) pci_dev_put(ivideo->nbridge);
5950 pci_set_drvdata(pdev, NULL);
5956 ivideo->video_base = pci_resource_start(pdev, 0);
5957 ivideo->mmio_base = pci_resource_start(pdev, 1);
5958 ivideo->mmio_size = pci_resource_len(pdev, 1);
5959 ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
5960 ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
5962 SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress);
5964 #ifdef CONFIG_FB_SIS_300
5965 /* Find PCI systems for Chrontel/GPIO communication setup */
5966 if(ivideo->chip == SIS_630) {
5969 if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
5970 mychswtable[i].subsysCard == ivideo->subsysdevice) {
5971 ivideo->SiS_Pr.SiS_ChSW = true;
5972 printk(KERN_DEBUG "sisfb: Identified [%s %s] "
5973 "requiring Chrontel/GPIO setup\n",
5974 mychswtable[i].vendorName,
5975 mychswtable[i].cardName);
5976 ivideo->lpcdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, NULL);
5980 } while(mychswtable[i].subsysVendor != 0);
5984 #ifdef CONFIG_FB_SIS_315
5985 if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
5986 ivideo->lpcdev = pci_get_slot(ivideo->nbridge->bus, (2 << 3));
5990 outSISIDXREG(SISSR, 0x05, 0x86);
5992 if( (!ivideo->sisvga_enabled)
5993 #if !defined(__i386__) && !defined(__x86_64__)
5994 || (sisfb_resetcard)
5997 for(i = 0x30; i <= 0x3f; i++) {
5998 outSISIDXREG(SISCR, i, 0x00);
6002 /* Find out about current video mode */
6003 ivideo->modeprechange = 0x03;
6004 inSISIDXREG(SISCR, 0x34, reg);
6006 ivideo->modeprechange = reg & 0x7f;
6007 } else if(ivideo->sisvga_enabled) {
6008 #if defined(__i386__) || defined(__x86_64__)
6009 unsigned char SIS_IOTYPE2 *tt = ioremap(0x400, 0x100);
6011 ivideo->modeprechange = readb(tt + 0x49);
6017 /* Search and copy ROM image */
6018 ivideo->bios_abase = NULL;
6019 ivideo->SiS_Pr.VirtualRomBase = NULL;
6020 ivideo->SiS_Pr.UseROM = false;
6021 ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = false;
6022 if(ivideo->sisfb_userom) {
6023 ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
6024 ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
6025 ivideo->SiS_Pr.UseROM = (bool)(ivideo->SiS_Pr.VirtualRomBase);
6026 printk(KERN_INFO "sisfb: Video ROM %sfound\n",
6027 ivideo->SiS_Pr.UseROM ? "" : "not ");
6028 if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
6029 ivideo->SiS_Pr.UseROM = false;
6030 ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = true;
6031 if( (ivideo->revision_id == 2) &&
6032 (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
6033 ivideo->SiS_Pr.DDCPortMixup = true;
6037 printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
6040 /* Find systems for special custom timing */
6041 if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
6042 sisfb_detect_custom_timing(ivideo);
6045 /* POST card in case this has not been done by the BIOS */
6046 if( (!ivideo->sisvga_enabled)
6047 #if !defined(__i386__) && !defined(__x86_64__)
6048 || (sisfb_resetcard)
6051 #ifdef CONFIG_FB_SIS_300
6052 if(ivideo->sisvga_engine == SIS_300_VGA) {
6053 if(ivideo->chip == SIS_300) {
6054 sisfb_post_sis300(pdev);
6055 ivideo->sisfb_can_post = 1;
6060 #ifdef CONFIG_FB_SIS_315
6061 if(ivideo->sisvga_engine == SIS_315_VGA) {
6063 /* if((ivideo->chip == SIS_315H) ||
6064 (ivideo->chip == SIS_315) ||
6065 (ivideo->chip == SIS_315PRO) ||
6066 (ivideo->chip == SIS_330)) {
6067 sisfb_post_sis315330(pdev);
6068 } else */ if(ivideo->chip == XGI_20) {
6069 result = sisfb_post_xgi(pdev);
6070 ivideo->sisfb_can_post = 1;
6071 } else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
6072 result = sisfb_post_xgi(pdev);
6073 ivideo->sisfb_can_post = 1;
6075 printk(KERN_INFO "sisfb: Card is not "
6076 "POSTed and sisfb can't do this either.\n");
6079 printk(KERN_ERR "sisfb: Failed to POST card\n");
6087 ivideo->sisfb_card_posted = 1;
6089 /* Find out about RAM size */
6090 if(sisfb_get_dram_size(ivideo)) {
6091 printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
6097 /* Enable PCI addressing and MMIO */
6098 if((ivideo->sisfb_mode_idx < 0) ||
6099 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6100 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
6101 orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
6102 /* Enable 2D accelerator engine */
6103 orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
6106 if(sisfb_pdc != 0xff) {
6107 if(ivideo->sisvga_engine == SIS_300_VGA)
6111 ivideo->SiS_Pr.PDC = sisfb_pdc;
6113 #ifdef CONFIG_FB_SIS_315
6114 if(ivideo->sisvga_engine == SIS_315_VGA) {
6115 if(sisfb_pdca != 0xff)
6116 ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
6120 if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
6121 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6122 (int)(ivideo->video_size >> 20));
6123 printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
6128 if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
6129 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
6134 ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size);
6135 ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
6136 if(!ivideo->video_vbase) {
6137 printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
6142 ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
6143 if(!ivideo->mmio_vbase) {
6144 printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
6146 error_0: iounmap(ivideo->video_vbase);
6147 error_1: release_mem_region(ivideo->video_base, ivideo->video_size);
6148 error_2: release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6149 error_3: vfree(ivideo->bios_abase);
6151 pci_dev_put(ivideo->lpcdev);
6153 pci_dev_put(ivideo->nbridge);
6154 pci_set_drvdata(pdev, NULL);
6155 if(!ivideo->sisvga_enabled)
6156 pci_disable_device(pdev);
6161 printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
6162 ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);
6164 if(ivideo->video_offset) {
6165 printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
6166 ivideo->video_offset / 1024);
6169 printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
6170 ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
6173 /* Determine the size of the command queue */
6174 if(ivideo->sisvga_engine == SIS_300_VGA) {
6175 ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
6177 if(ivideo->chip == XGI_20) {
6178 ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
6180 ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
6184 /* Engines are no longer initialized here; this is
6185 * now done after the first mode-switch (if the
6186 * submitted var has its acceleration flags set).
6189 /* Calculate the base of the (unused) hw cursor */
6190 ivideo->hwcursor_vbase = ivideo->video_vbase
6191 + ivideo->video_size
6192 - ivideo->cmdQueueSize
6193 - ivideo->hwcursor_size;
6194 ivideo->caps |= HW_CURSOR_CAP;
6196 /* Initialize offscreen memory manager */
6197 if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
6198 printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
6201 /* Used for clearing the screen only, therefore respect our mem limit */
6202 ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
6203 ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;
6207 ivideo->vbflags = 0;
6208 ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
6209 ivideo->tvdefmodeidx = DEFAULT_TVMODE;
6210 ivideo->defmodeidx = DEFAULT_MODE;
6213 if(ivideo->chip < XGI_20) {
6214 if(ivideo->bios_abase) {
6215 ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr);
6219 if((ivideo->sisfb_mode_idx < 0) ||
6220 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6222 sisfb_sense_crt1(ivideo);
6224 sisfb_get_VB_type(ivideo);
6226 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6227 sisfb_detect_VB_connect(ivideo);
6230 ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
6232 /* Decide on which CRT2 device to use */
6233 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6234 if(ivideo->sisfb_crt2type != -1) {
6235 if((ivideo->sisfb_crt2type == CRT2_LCD) &&
6236 (ivideo->vbflags & CRT2_LCD)) {
6237 ivideo->currentvbflags |= CRT2_LCD;
6238 } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
6239 ivideo->currentvbflags |= ivideo->sisfb_crt2type;
6242 /* Chrontel 700x TV detection often unreliable, therefore
6243 * use a different default order on such machines
6245 if((ivideo->sisvga_engine == SIS_300_VGA) &&
6246 (ivideo->vbflags2 & VB2_CHRONTEL)) {
6247 if(ivideo->vbflags & CRT2_LCD)
6248 ivideo->currentvbflags |= CRT2_LCD;
6249 else if(ivideo->vbflags & CRT2_TV)
6250 ivideo->currentvbflags |= CRT2_TV;
6251 else if(ivideo->vbflags & CRT2_VGA)
6252 ivideo->currentvbflags |= CRT2_VGA;
6254 if(ivideo->vbflags & CRT2_TV)
6255 ivideo->currentvbflags |= CRT2_TV;
6256 else if(ivideo->vbflags & CRT2_LCD)
6257 ivideo->currentvbflags |= CRT2_LCD;
6258 else if(ivideo->vbflags & CRT2_VGA)
6259 ivideo->currentvbflags |= CRT2_VGA;
6264 if(ivideo->vbflags & CRT2_LCD) {
6265 sisfb_detect_lcd_type(ivideo);
6268 sisfb_save_pdc_emi(ivideo);
6270 if(!ivideo->sisfb_crt1off) {
6271 sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
6273 if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
6274 (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
6275 sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
6279 if(ivideo->sisfb_mode_idx >= 0) {
6280 int bu = ivideo->sisfb_mode_idx;
6281 ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
6282 ivideo->sisfb_mode_idx, ivideo->currentvbflags);
6283 if(bu != ivideo->sisfb_mode_idx) {
6284 printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
6285 sisbios_mode[bu].xres,
6286 sisbios_mode[bu].yres,
6287 sisbios_mode[bu].bpp);
6291 if(ivideo->sisfb_mode_idx < 0) {
6292 switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
6294 ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
6297 ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
6300 ivideo->sisfb_mode_idx = ivideo->defmodeidx;
6305 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
6307 if(ivideo->refresh_rate != 0) {
6308 sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate,
6309 ivideo->sisfb_mode_idx);
6312 if(ivideo->rate_idx == 0) {
6313 ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
6314 ivideo->refresh_rate = 60;
6317 if(ivideo->sisfb_thismonitor.datavalid) {
6318 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor,
6319 ivideo->sisfb_mode_idx,
6321 ivideo->refresh_rate)) {
6322 printk(KERN_INFO "sisfb: WARNING: Refresh rate "
6323 "exceeds monitor specs!\n");
6327 ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
6328 ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
6329 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
6331 sisfb_set_vparms(ivideo);
6333 printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
6334 ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
6335 ivideo->refresh_rate);
6337 /* Set up the default var according to chosen default display mode */
6338 ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
6339 ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
6340 ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
6342 sisfb_bpp_to_var(ivideo, &ivideo->default_var);
6344 ivideo->default_var.pixclock = (u32) (1000000000 /
6345 sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx));
6347 if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no,
6348 ivideo->rate_idx, &ivideo->default_var)) {
6349 if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
6350 ivideo->default_var.pixclock <<= 1;
6354 if(ivideo->sisfb_ypan) {
6355 /* Maximize regardless of sisfb_max at startup */
6356 ivideo->default_var.yres_virtual =
6357 sisfb_calc_maxyres(ivideo, &ivideo->default_var);
6358 if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
6359 ivideo->default_var.yres_virtual = ivideo->default_var.yres;
6363 sisfb_calc_pitch(ivideo, &ivideo->default_var);
6366 if(ivideo->sisfb_accel) {
6368 #ifdef STUPID_ACCELF_TEXT_SHIT
6369 ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
6372 sisfb_initaccel(ivideo);
6374 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
6375 sis_fb_info->flags = FBINFO_DEFAULT |
6376 FBINFO_HWACCEL_YPAN |
6377 FBINFO_HWACCEL_XPAN |
6378 FBINFO_HWACCEL_COPYAREA |
6379 FBINFO_HWACCEL_FILLRECT |
6380 ((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED);
6382 sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
6384 sis_fb_info->var = ivideo->default_var;
6385 sis_fb_info->fix = ivideo->sisfb_fix;
6386 sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
6387 sis_fb_info->fbops = &sisfb_ops;
6388 sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info);
6389 sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
6391 fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
6393 printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
6396 ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size,
6397 MTRR_TYPE_WRCOMB, 1);
6398 if(ivideo->mtrr < 0) {
6399 printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n");
6403 if(register_framebuffer(sis_fb_info) < 0) {
6404 printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
6406 iounmap(ivideo->mmio_vbase);
6410 ivideo->registered = 1;
6413 ivideo->next = card_list;
6416 #ifdef SIS_OLD_CONFIG_COMPAT
6419 /* Our ioctls are all "32/64bit compatible" */
6420 ret = register_ioctl32_conversion(FBIO_ALLOC, NULL);
6421 ret |= register_ioctl32_conversion(FBIO_FREE, NULL);
6422 ret |= register_ioctl32_conversion(FBIOGET_VBLANK, NULL);
6423 ret |= register_ioctl32_conversion(SISFB_GET_INFO_SIZE, NULL);
6424 ret |= register_ioctl32_conversion(SISFB_GET_INFO, NULL);
6425 ret |= register_ioctl32_conversion(SISFB_GET_TVPOSOFFSET, NULL);
6426 ret |= register_ioctl32_conversion(SISFB_SET_TVPOSOFFSET, NULL);
6427 ret |= register_ioctl32_conversion(SISFB_SET_LOCK, NULL);
6428 ret |= register_ioctl32_conversion(SISFB_GET_VBRSTATUS, NULL);
6429 ret |= register_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE, NULL);
6430 ret |= register_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE, NULL);
6431 ret |= register_ioctl32_conversion(SISFB_COMMAND, NULL);
6434 "sisfb: Error registering ioctl32 translations\n");
6436 ivideo->ioctl32registered = 1;
6440 printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
6441 ivideo->sisfb_accel ? "enabled" : "disabled",
6442 ivideo->sisfb_ypan ?
6443 (ivideo->sisfb_max ? "enabled (auto-max)" :
6444 "enabled (no auto-max)") :
6448 printk(KERN_INFO "fb%d: %s frame buffer device version %d.%d.%d\n",
6449 sis_fb_info->node, ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
6451 printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
6453 } /* if mode = "none" */
6458 /*****************************************************/
6459 /* PCI DEVICE HANDLING */
6460 /*****************************************************/
6462 static void __devexit sisfb_remove(struct pci_dev *pdev)
6464 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
6465 struct fb_info *sis_fb_info = ivideo->memyselfandi;
6466 int registered = ivideo->registered;
6467 int modechanged = ivideo->modechanged;
6469 #ifdef SIS_OLD_CONFIG_COMPAT
6470 if(ivideo->ioctl32registered) {
6472 ret = unregister_ioctl32_conversion(FBIO_ALLOC);
6473 ret |= unregister_ioctl32_conversion(FBIO_FREE);
6474 ret |= unregister_ioctl32_conversion(FBIOGET_VBLANK);
6475 ret |= unregister_ioctl32_conversion(SISFB_GET_INFO_SIZE);
6476 ret |= unregister_ioctl32_conversion(SISFB_GET_INFO);
6477 ret |= unregister_ioctl32_conversion(SISFB_GET_TVPOSOFFSET);
6478 ret |= unregister_ioctl32_conversion(SISFB_SET_TVPOSOFFSET);
6479 ret |= unregister_ioctl32_conversion(SISFB_SET_LOCK);
6480 ret |= unregister_ioctl32_conversion(SISFB_GET_VBRSTATUS);
6481 ret |= unregister_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE);
6482 ret |= unregister_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE);
6483 ret |= unregister_ioctl32_conversion(SISFB_COMMAND);
6486 "sisfb: Error unregistering ioctl32 translations\n");
6491 iounmap(ivideo->mmio_vbase);
6492 iounmap(ivideo->video_vbase);
6494 /* Release mem regions */
6495 release_mem_region(ivideo->video_base, ivideo->video_size);
6496 release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6498 vfree(ivideo->bios_abase);
6501 pci_dev_put(ivideo->lpcdev);
6504 pci_dev_put(ivideo->nbridge);
6507 /* Release MTRR region */
6508 if(ivideo->mtrr >= 0)
6509 mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size);
6512 pci_set_drvdata(pdev, NULL);
6514 /* If device was disabled when starting, disable
6517 if(!ivideo->sisvga_enabled)
6518 pci_disable_device(pdev);
6520 /* Unregister the framebuffer */
6521 if(ivideo->registered) {
6522 unregister_framebuffer(sis_fb_info);
6523 framebuffer_release(sis_fb_info);
6526 /* OK, our ivideo is gone for good from here. */
6528 /* TODO: Restore the initial mode
6529 * This sounds easy but is as good as impossible
6530 * on many machines with SiS chip and video bridge
6531 * since text modes are always set up differently
6532 * from machine to machine. Depends on the type
6533 * of integration between chipset and bridge.
6535 if(registered && modechanged)
6537 "sisfb: Restoring of text mode not supported yet\n");
6540 static struct pci_driver sisfb_driver = {
6542 .id_table = sisfb_pci_table,
6543 .probe = sisfb_probe,
6544 .remove = __devexit_p(sisfb_remove)
6547 SISINITSTATIC int __init sisfb_init(void)
6550 char *options = NULL;
6552 if(fb_get_options("sisfb", &options))
6555 sisfb_setup(options);
6557 return pci_register_driver(&sisfb_driver);
6561 module_init(sisfb_init);
6564 /*****************************************************/
6566 /*****************************************************/
6570 static char *mode = NULL;
6571 static int vesa = -1;
6572 static unsigned int rate = 0;
6573 static unsigned int crt1off = 1;
6574 static unsigned int mem = 0;
6575 static char *forcecrt2type = NULL;
6576 static int forcecrt1 = -1;
6577 static int pdc = -1;
6578 static int pdc1 = -1;
6579 static int noaccel = -1;
6580 static int noypan = -1;
6581 static int nomax = -1;
6582 static int userom = -1;
6583 static int useoem = -1;
6584 static char *tvstandard = NULL;
6585 static int nocrt2rate = 0;
6586 static int scalelcd = -1;
6587 static char *specialtiming = NULL;
6588 static int lvdshl = -1;
6589 static int tvxposoffset = 0, tvyposoffset = 0;
6590 #if !defined(__i386__) && !defined(__x86_64__)
6591 static int resetcard = 0;
6592 static int videoram = 0;
6595 static int __init sisfb_init_module(void)
6597 sisfb_setdefaultparms();
6600 sisfb_parm_rate = rate;
6602 if((scalelcd == 0) || (scalelcd == 1))
6603 sisfb_scalelcd = scalelcd ^ 1;
6605 /* Need to check crt2 type first for fstn/dstn */
6608 sisfb_search_crt2type(forcecrt2type);
6611 sisfb_search_tvstd(tvstandard);
6614 sisfb_search_mode(mode, false);
6616 sisfb_search_vesamode(vesa, false);
6618 sisfb_crt1off = (crt1off == 0) ? 1 : 0;
6620 sisfb_forcecrt1 = forcecrt1;
6623 else if(forcecrt1 == 0)
6628 else if(noaccel == 0)
6633 else if(noypan == 0)
6642 sisfb_parm_mem = mem;
6645 sisfb_userom = userom;
6648 sisfb_useoem = useoem;
6651 sisfb_pdc = (pdc & 0x7f);
6654 sisfb_pdca = (pdc1 & 0x1f);
6656 sisfb_nocrt2rate = nocrt2rate;
6659 sisfb_search_specialtiming(specialtiming);
6661 if((lvdshl >= 0) && (lvdshl <= 3))
6662 sisfb_lvdshl = lvdshl;
6664 sisfb_tvxposoffset = tvxposoffset;
6665 sisfb_tvyposoffset = tvyposoffset;
6667 #if !defined(__i386__) && !defined(__x86_64__)
6668 sisfb_resetcard = (resetcard) ? 1 : 0;
6670 sisfb_videoram = videoram;
6673 return sisfb_init();
6676 static void __exit sisfb_remove_module(void)
6678 pci_unregister_driver(&sisfb_driver);
6679 printk(KERN_DEBUG "sisfb: Module unloaded\n");
6682 module_init(sisfb_init_module);
6683 module_exit(sisfb_remove_module);
6685 MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
6686 MODULE_LICENSE("GPL");
6687 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
6689 module_param(mem, int, 0);
6690 module_param(noaccel, int, 0);
6691 module_param(noypan, int, 0);
6692 module_param(nomax, int, 0);
6693 module_param(userom, int, 0);
6694 module_param(useoem, int, 0);
6695 module_param(mode, charp, 0);
6696 module_param(vesa, int, 0);
6697 module_param(rate, int, 0);
6698 module_param(forcecrt1, int, 0);
6699 module_param(forcecrt2type, charp, 0);
6700 module_param(scalelcd, int, 0);
6701 module_param(pdc, int, 0);
6702 module_param(pdc1, int, 0);
6703 module_param(specialtiming, charp, 0);
6704 module_param(lvdshl, int, 0);
6705 module_param(tvstandard, charp, 0);
6706 module_param(tvxposoffset, int, 0);
6707 module_param(tvyposoffset, int, 0);
6708 module_param(nocrt2rate, int, 0);
6709 #if !defined(__i386__) && !defined(__x86_64__)
6710 module_param(resetcard, int, 0);
6711 module_param(videoram, int, 0);
6714 MODULE_PARM_DESC(mem,
6715 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6716 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6717 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6718 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6719 "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6720 "The value is to be specified without 'KB'.\n");
6722 MODULE_PARM_DESC(noaccel,
6723 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
6726 MODULE_PARM_DESC(noypan,
6727 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
6728 "will be performed by redrawing the screen. (default: 0)\n");
6730 MODULE_PARM_DESC(nomax,
6731 "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
6732 "memory for the virtual screen in order to optimize scrolling performance. If\n"
6733 "this is set to anything other than 0, sisfb will not do this and thereby \n"
6734 "enable the user to positively specify a virtual Y size of the screen using\n"
6735 "fbset. (default: 0)\n");
6737 MODULE_PARM_DESC(mode,
6738 "\nSelects the desired default display mode in the format XxYxDepth,\n"
6739 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
6740 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
6741 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
6743 MODULE_PARM_DESC(vesa,
6744 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
6745 "0x117 (default: 0x0103)\n");
6747 MODULE_PARM_DESC(rate,
6748 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
6749 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
6750 "will be ignored (default: 60)\n");
6752 MODULE_PARM_DESC(forcecrt1,
6753 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
6754 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
6755 "0=CRT1 OFF) (default: [autodetected])\n");
6757 MODULE_PARM_DESC(forcecrt2type,
6758 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
6759 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
6760 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
6761 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
6762 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
6763 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
6764 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
6765 "depends on the very hardware in use. (default: [autodetected])\n");
6767 MODULE_PARM_DESC(scalelcd,
6768 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
6769 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
6770 "show black bars around the image, TMDS panels will probably do the scaling\n"
6771 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
6773 MODULE_PARM_DESC(pdc,
6774 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
6775 "should detect this correctly in most cases; however, sometimes this is not\n"
6776 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
6777 "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
6778 "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
6779 "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
6781 #ifdef CONFIG_FB_SIS_315
6782 MODULE_PARM_DESC(pdc1,
6783 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
6784 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
6785 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
6786 "implemented yet.\n");
6789 MODULE_PARM_DESC(specialtiming,
6790 "\nPlease refer to documentation for more information on this option.\n");
6792 MODULE_PARM_DESC(lvdshl,
6793 "\nPlease refer to documentation for more information on this option.\n");
6795 MODULE_PARM_DESC(tvstandard,
6796 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
6797 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
6799 MODULE_PARM_DESC(tvxposoffset,
6800 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
6803 MODULE_PARM_DESC(tvyposoffset,
6804 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
6807 MODULE_PARM_DESC(nocrt2rate,
6808 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
6809 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
6811 #if !defined(__i386__) && !defined(__x86_64__)
6812 #ifdef CONFIG_FB_SIS_300
6813 MODULE_PARM_DESC(resetcard,
6814 "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
6815 "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
6816 "currently). Default: 0\n");
6818 MODULE_PARM_DESC(videoram,
6819 "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
6820 "some non-x86 architectures where the memory auto detection fails. Only\n"
6821 "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
6825 #endif /* /MODULE */
6827 /* _GPL only for new symbols. */
6828 EXPORT_SYMBOL(sis_malloc);
6829 EXPORT_SYMBOL(sis_free);
6830 EXPORT_SYMBOL_GPL(sis_malloc_new);
6831 EXPORT_SYMBOL_GPL(sis_free_new);