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 <linux/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));
1411 ((u32 *)(info->pseudo_palette))[regno] =
1413 ((green & 0xfc00) >> 5) |
1414 ((blue & 0xf800) >> 11);
1423 ((u32 *)(info->pseudo_palette))[regno] =
1424 (red << 16) | (green << 8) | (blue);
1431 sisfb_set_par(struct fb_info *info)
1435 if((err = sisfb_do_set_var(&info->var, 1, info)))
1438 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
1439 sisfb_get_fix(&info->fix, info->currcon, info);
1441 sisfb_get_fix(&info->fix, -1, info);
1447 sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1449 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1450 unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
1451 unsigned int drate = 0, hrate = 0, maxyres;
1453 int refresh_rate, search_idx, tidx;
1454 bool recalc_clock = false;
1457 htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1459 vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1461 pixclock = var->pixclock;
1463 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1464 vtotal += var->yres;
1466 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1467 vtotal += var->yres;
1469 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1470 vtotal += var->yres;
1473 vtotal += var->yres;
1475 if(!(htotal) || !(vtotal)) {
1476 SISFAIL("sisfb: no valid timing data");
1480 while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
1481 (sisbios_mode[search_idx].xres <= var->xres) ) {
1482 if( (sisbios_mode[search_idx].xres == var->xres) &&
1483 (sisbios_mode[search_idx].yres == var->yres) &&
1484 (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1485 if((tidx = sisfb_validate_mode(ivideo, search_idx,
1486 ivideo->currentvbflags)) > 0) {
1497 while(sisbios_mode[search_idx].mode_no[0] != 0) {
1498 if( (var->xres <= sisbios_mode[search_idx].xres) &&
1499 (var->yres <= sisbios_mode[search_idx].yres) &&
1500 (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
1501 if((tidx = sisfb_validate_mode(ivideo,search_idx,
1502 ivideo->currentvbflags)) > 0) {
1512 "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
1513 var->xres, var->yres, var->bits_per_pixel,
1514 sisbios_mode[search_idx].xres,
1515 sisbios_mode[search_idx].yres,
1516 var->bits_per_pixel);
1517 var->xres = sisbios_mode[search_idx].xres;
1518 var->yres = sisbios_mode[search_idx].yres;
1521 "sisfb: Failed to find supported mode near %dx%dx%d\n",
1522 var->xres, var->yres, var->bits_per_pixel);
1527 if( ((ivideo->vbflags2 & VB2_LVDS) ||
1528 ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
1529 (var->bits_per_pixel == 8) ) {
1530 /* Slave modes on LVDS and 301B-DH */
1532 recalc_clock = true;
1533 } else if( (ivideo->current_htotal == htotal) &&
1534 (ivideo->current_vtotal == vtotal) &&
1535 (ivideo->current_pixclock == pixclock) ) {
1536 /* x=x & y=y & c=c -> assume depth change */
1537 drate = 1000000000 / pixclock;
1538 hrate = (drate * 1000) / htotal;
1539 refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1540 } else if( ( (ivideo->current_htotal != htotal) ||
1541 (ivideo->current_vtotal != vtotal) ) &&
1542 (ivideo->current_pixclock == var->pixclock) ) {
1543 /* x!=x | y!=y & c=c -> invalid pixclock */
1544 if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
1546 ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
1547 } else if(ivideo->sisfb_parm_rate != -1) {
1548 /* Sic, sisfb_parm_rate - want to know originally desired rate here */
1549 refresh_rate = ivideo->sisfb_parm_rate;
1553 recalc_clock = true;
1554 } else if((pixclock) && (htotal) && (vtotal)) {
1555 drate = 1000000000 / pixclock;
1556 hrate = (drate * 1000) / htotal;
1557 refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1558 } else if(ivideo->current_refresh_rate) {
1559 refresh_rate = ivideo->current_refresh_rate;
1560 recalc_clock = true;
1563 recalc_clock = true;
1566 myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
1568 /* Eventually recalculate timing and clock */
1570 if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
1571 var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
1572 sisbios_mode[search_idx].mode_no[ivideo->mni],
1574 sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr,
1575 sisbios_mode[search_idx].mode_no[ivideo->mni],
1577 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1578 var->pixclock <<= 1;
1582 if(ivideo->sisfb_thismonitor.datavalid) {
1583 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
1584 myrateindex, refresh_rate)) {
1586 "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1590 /* Adapt RGB settings */
1591 sisfb_bpp_to_var(ivideo, var);
1593 /* Sanity check for offsets */
1594 if(var->xoffset < 0) var->xoffset = 0;
1595 if(var->yoffset < 0) var->yoffset = 0;
1597 if(var->xres > var->xres_virtual)
1598 var->xres_virtual = var->xres;
1600 if(ivideo->sisfb_ypan) {
1601 maxyres = sisfb_calc_maxyres(ivideo, var);
1602 if(ivideo->sisfb_max) {
1603 var->yres_virtual = maxyres;
1605 if(var->yres_virtual > maxyres) {
1606 var->yres_virtual = maxyres;
1609 if(var->yres_virtual <= var->yres) {
1610 var->yres_virtual = var->yres;
1613 if(var->yres != var->yres_virtual) {
1614 var->yres_virtual = var->yres;
1620 /* Truncate offsets to maximum if too high */
1621 if(var->xoffset > var->xres_virtual - var->xres) {
1622 var->xoffset = var->xres_virtual - var->xres - 1;
1625 if(var->yoffset > var->yres_virtual - var->yres) {
1626 var->yoffset = var->yres_virtual - var->yres - 1;
1629 /* Set everything else to 0 */
1630 var->red.msb_right =
1631 var->green.msb_right =
1632 var->blue.msb_right =
1633 var->transp.offset =
1634 var->transp.length =
1635 var->transp.msb_right = 0;
1641 sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
1643 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1646 if(var->xoffset > (var->xres_virtual - var->xres))
1649 if(var->yoffset > (var->yres_virtual - var->yres))
1652 if(var->vmode & FB_VMODE_YWRAP)
1655 if(var->xoffset + info->var.xres > info->var.xres_virtual ||
1656 var->yoffset + info->var.yres > info->var.yres_virtual)
1659 if((err = sisfb_pan_var(ivideo, var)) < 0)
1662 info->var.xoffset = var->xoffset;
1663 info->var.yoffset = var->yoffset;
1669 sisfb_blank(int blank, struct fb_info *info)
1671 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1673 return sisfb_myblank(ivideo, blank);
1676 /* ----------- FBDev related routines for all series ---------- */
1678 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
1679 static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
1682 static int sisfb_ioctl(struct inode *inode, struct file *file,
1683 unsigned int cmd, unsigned long arg,
1684 struct fb_info *info)
1687 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1688 struct sis_memreq sismemreq;
1689 struct fb_vblank sisvbblank;
1694 u32 __user *argp = (u32 __user *)arg;
1698 if(!capable(CAP_SYS_RAWIO))
1701 if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))
1704 sis_malloc(&sismemreq);
1706 if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
1707 sis_free((u32)sismemreq.offset);
1713 if(!capable(CAP_SYS_RAWIO))
1716 if(get_user(gpu32, argp))
1722 case FBIOGET_VBLANK:
1723 sisvbblank.count = 0;
1724 sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
1726 if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))
1731 case SISFB_GET_INFO_SIZE:
1732 return put_user(sizeof(struct sisfb_info), argp);
1734 case SISFB_GET_INFO_OLD:
1735 if(ivideo->warncount++ < 10)
1737 "sisfb: Deprecated ioctl call received - update your application!\n");
1738 case SISFB_GET_INFO: /* For communication with X driver */
1739 ivideo->sisfb_infoblock.sisfb_id = SISFB_ID;
1740 ivideo->sisfb_infoblock.sisfb_version = VER_MAJOR;
1741 ivideo->sisfb_infoblock.sisfb_revision = VER_MINOR;
1742 ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;
1743 ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;
1744 ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;
1745 ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;
1746 ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;
1747 if(ivideo->modechanged) {
1748 ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;
1750 ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;
1752 ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;
1753 ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;
1754 ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;
1755 ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;
1756 ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;
1757 ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;
1758 ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;
1759 ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;
1760 ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;
1761 ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;
1762 ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
1763 ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
1764 ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
1765 ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
1766 ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
1767 ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
1768 ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
1769 ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
1770 ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
1771 ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
1772 ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;
1773 ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;
1774 ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;
1775 ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;
1776 ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;
1777 ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;
1778 ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;
1779 ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;
1781 if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,
1782 sizeof(ivideo->sisfb_infoblock)))
1787 case SISFB_GET_VBRSTATUS_OLD:
1788 if(ivideo->warncount++ < 10)
1790 "sisfb: Deprecated ioctl call received - update your application!\n");
1791 case SISFB_GET_VBRSTATUS:
1792 if(sisfb_CheckVBRetrace(ivideo))
1793 return put_user((u32)1, argp);
1795 return put_user((u32)0, argp);
1797 case SISFB_GET_AUTOMAXIMIZE_OLD:
1798 if(ivideo->warncount++ < 10)
1800 "sisfb: Deprecated ioctl call received - update your application!\n");
1801 case SISFB_GET_AUTOMAXIMIZE:
1802 if(ivideo->sisfb_max)
1803 return put_user((u32)1, argp);
1805 return put_user((u32)0, argp);
1807 case SISFB_SET_AUTOMAXIMIZE_OLD:
1808 if(ivideo->warncount++ < 10)
1810 "sisfb: Deprecated ioctl call received - update your application!\n");
1811 case SISFB_SET_AUTOMAXIMIZE:
1812 if(get_user(gpu32, argp))
1815 ivideo->sisfb_max = (gpu32) ? 1 : 0;
1818 case SISFB_SET_TVPOSOFFSET:
1819 if(get_user(gpu32, argp))
1822 sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
1823 sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
1826 case SISFB_GET_TVPOSOFFSET:
1827 return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
1831 if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,
1832 sizeof(struct sisfb_cmd)))
1835 sisfb_handle_command(ivideo, &ivideo->sisfb_command);
1837 if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,
1838 sizeof(struct sisfb_cmd)))
1843 case SISFB_SET_LOCK:
1844 if(get_user(gpu32, argp))
1847 ivideo->sisfblocked = (gpu32) ? 1 : 0;
1851 #ifdef SIS_NEW_CONFIG_COMPAT
1852 return -ENOIOCTLCMD;
1861 sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
1863 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1865 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1867 strcpy(fix->id, ivideo->myid);
1869 fix->smem_start = ivideo->video_base + ivideo->video_offset;
1870 fix->smem_len = ivideo->sisfb_mem;
1871 fix->type = FB_TYPE_PACKED_PIXELS;
1873 fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
1875 fix->ypanstep = (ivideo->sisfb_ypan) ? 1 : 0;
1877 fix->line_length = ivideo->video_linelength;
1878 fix->mmio_start = ivideo->mmio_base;
1879 fix->mmio_len = ivideo->mmio_size;
1880 if(ivideo->sisvga_engine == SIS_300_VGA) {
1881 fix->accel = FB_ACCEL_SIS_GLAMOUR;
1882 } else if((ivideo->chip == SIS_330) ||
1883 (ivideo->chip == SIS_760) ||
1884 (ivideo->chip == SIS_761)) {
1885 fix->accel = FB_ACCEL_SIS_XABRE;
1886 } else if(ivideo->chip == XGI_20) {
1887 fix->accel = FB_ACCEL_XGI_VOLARI_Z;
1888 } else if(ivideo->chip >= XGI_40) {
1889 fix->accel = FB_ACCEL_XGI_VOLARI_V;
1891 fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
1897 /* ---------------- fb_ops structures ----------------- */
1899 static struct fb_ops sisfb_ops = {
1900 .owner = THIS_MODULE,
1901 .fb_open = sisfb_open,
1902 .fb_release = sisfb_release,
1903 .fb_check_var = sisfb_check_var,
1904 .fb_set_par = sisfb_set_par,
1905 .fb_setcolreg = sisfb_setcolreg,
1906 .fb_pan_display = sisfb_pan_display,
1907 .fb_blank = sisfb_blank,
1908 .fb_fillrect = fbcon_sis_fillrect,
1909 .fb_copyarea = fbcon_sis_copyarea,
1910 .fb_imageblit = cfb_imageblit,
1911 #ifdef CONFIG_FB_SOFT_CURSOR
1912 .fb_cursor = soft_cursor,
1914 .fb_sync = fbcon_sis_sync,
1915 #ifdef SIS_NEW_CONFIG_COMPAT
1916 .fb_compat_ioctl= sisfb_ioctl,
1918 .fb_ioctl = sisfb_ioctl
1921 /* ---------------- Chip generation dependent routines ---------------- */
1923 static struct pci_dev * __devinit
1924 sisfb_get_northbridge(int basechipid)
1926 struct pci_dev *pdev = NULL;
1927 int nbridgenum, nbridgeidx, i;
1928 static const unsigned short nbridgeids[] = {
1929 PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */
1930 PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */
1931 PCI_DEVICE_ID_SI_730,
1932 PCI_DEVICE_ID_SI_550, /* for SiS 550 VGA */
1933 PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */
1934 PCI_DEVICE_ID_SI_651,
1935 PCI_DEVICE_ID_SI_740,
1936 PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760/761 VGA */
1937 PCI_DEVICE_ID_SI_741,
1938 PCI_DEVICE_ID_SI_660,
1939 PCI_DEVICE_ID_SI_760,
1940 PCI_DEVICE_ID_SI_761
1943 switch(basechipid) {
1944 #ifdef CONFIG_FB_SIS_300
1945 case SIS_540: nbridgeidx = 0; nbridgenum = 1; break;
1946 case SIS_630: nbridgeidx = 1; nbridgenum = 2; break;
1948 #ifdef CONFIG_FB_SIS_315
1949 case SIS_550: nbridgeidx = 3; nbridgenum = 1; break;
1950 case SIS_650: nbridgeidx = 4; nbridgenum = 3; break;
1951 case SIS_660: nbridgeidx = 7; nbridgenum = 5; break;
1953 default: return NULL;
1955 for(i = 0; i < nbridgenum; i++) {
1956 if((pdev = pci_get_device(PCI_VENDOR_ID_SI,
1957 nbridgeids[nbridgeidx+i], NULL)))
1963 static int __devinit
1964 sisfb_get_dram_size(struct sis_video_info *ivideo)
1966 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1970 ivideo->video_size = 0;
1971 ivideo->UMAsize = ivideo->LFBsize = 0;
1973 switch(ivideo->chip) {
1974 #ifdef CONFIG_FB_SIS_300
1976 inSISIDXREG(SISSR, 0x14, reg);
1977 ivideo->video_size = ((reg & 0x3F) + 1) << 20;
1982 if(!ivideo->nbridge)
1984 pci_read_config_byte(ivideo->nbridge, 0x63, ®);
1985 ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
1988 #ifdef CONFIG_FB_SIS_315
1992 inSISIDXREG(SISSR, 0x14, reg);
1993 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
1994 switch((reg >> 2) & 0x03) {
1997 ivideo->video_size <<= 1;
2000 ivideo->video_size += (ivideo->video_size/2);
2004 inSISIDXREG(SISSR, 0x14, reg);
2005 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2006 if(reg & 0x0c) ivideo->video_size <<= 1;
2011 inSISIDXREG(SISSR, 0x14, reg);
2012 ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
2016 inSISIDXREG(SISCR, 0x79, reg);
2017 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2022 inSISIDXREG(SISCR, 0x79, reg);
2023 reg = (reg & 0xf0) >> 4;
2025 ivideo->video_size = (1 << reg) << 20;
2026 ivideo->UMAsize = ivideo->video_size;
2028 inSISIDXREG(SISCR, 0x78, reg);
2032 ivideo->LFBsize = (32 << 20);
2034 ivideo->LFBsize = (64 << 20);
2036 ivideo->video_size += ivideo->LFBsize;
2042 inSISIDXREG(SISSR, 0x14, reg);
2043 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2044 if(ivideo->chip != XGI_20) {
2045 reg = (reg & 0x0c) >> 2;
2046 if(ivideo->revision_id == 2) {
2047 if(reg & 0x01) reg = 0x02;
2050 if(reg == 0x02) ivideo->video_size <<= 1;
2051 else if(reg == 0x03) ivideo->video_size <<= 2;
2061 /* -------------- video bridge device detection --------------- */
2063 static void __devinit
2064 sisfb_detect_VB_connect(struct sis_video_info *ivideo)
2068 /* No CRT2 on XGI Z7 */
2069 if(ivideo->chip == XGI_20) {
2070 ivideo->sisfb_crt1off = 0;
2074 #ifdef CONFIG_FB_SIS_300
2075 if(ivideo->sisvga_engine == SIS_300_VGA) {
2076 inSISIDXREG(SISSR, 0x17, temp);
2077 if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
2078 /* PAL/NTSC is stored on SR16 on such machines */
2079 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
2080 inSISIDXREG(SISSR, 0x16, temp);
2082 ivideo->vbflags |= TV_PAL;
2084 ivideo->vbflags |= TV_NTSC;
2090 inSISIDXREG(SISCR, 0x32, cr32);
2092 if(cr32 & SIS_CRT1) {
2093 ivideo->sisfb_crt1off = 0;
2095 ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0;
2098 ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
2100 if(cr32 & SIS_VB_TV) ivideo->vbflags |= CRT2_TV;
2101 if(cr32 & SIS_VB_LCD) ivideo->vbflags |= CRT2_LCD;
2102 if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA;
2104 /* Check given parms for hardware compatibility.
2105 * (Cannot do this in the search_xx routines since we don't
2106 * know what hardware we are running on then)
2109 if(ivideo->chip != SIS_550) {
2110 ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0;
2113 if(ivideo->sisfb_tvplug != -1) {
2114 if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2115 (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) {
2116 if(ivideo->sisfb_tvplug & TV_YPBPR) {
2117 ivideo->sisfb_tvplug = -1;
2118 printk(KERN_ERR "sisfb: YPbPr not supported\n");
2122 if(ivideo->sisfb_tvplug != -1) {
2123 if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2124 (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) {
2125 if(ivideo->sisfb_tvplug & TV_HIVISION) {
2126 ivideo->sisfb_tvplug = -1;
2127 printk(KERN_ERR "sisfb: HiVision not supported\n");
2131 if(ivideo->sisfb_tvstd != -1) {
2132 if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
2133 (!((ivideo->sisvga_engine == SIS_315_VGA) &&
2134 (ivideo->vbflags2 & VB2_CHRONTEL))) ) {
2135 if(ivideo->sisfb_tvstd & (TV_PALN | TV_PALN | TV_NTSCJ)) {
2136 ivideo->sisfb_tvstd = -1;
2137 printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
2142 /* Detect/set TV plug & type */
2143 if(ivideo->sisfb_tvplug != -1) {
2144 ivideo->vbflags |= ivideo->sisfb_tvplug;
2146 if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
2147 else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION;
2148 else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART;
2150 if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO;
2151 if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
2155 if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) {
2156 if(ivideo->sisfb_tvstd != -1) {
2157 ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ);
2158 ivideo->vbflags |= ivideo->sisfb_tvstd;
2160 if(ivideo->vbflags & TV_SCART) {
2161 ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ);
2162 ivideo->vbflags |= TV_PAL;
2164 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
2165 if(ivideo->sisvga_engine == SIS_300_VGA) {
2166 inSISIDXREG(SISSR, 0x38, temp);
2167 if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2168 else ivideo->vbflags |= TV_NTSC;
2169 } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
2170 inSISIDXREG(SISSR, 0x38, temp);
2171 if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2172 else ivideo->vbflags |= TV_NTSC;
2174 inSISIDXREG(SISCR, 0x79, temp);
2175 if(temp & 0x20) ivideo->vbflags |= TV_PAL;
2176 else ivideo->vbflags |= TV_NTSC;
2181 /* Copy forceCRT1 option to CRT1off if option is given */
2182 if(ivideo->sisfb_forcecrt1 != -1) {
2183 ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
2187 /* ------------------ Sensing routines ------------------ */
2189 static bool __devinit
2190 sisfb_test_DDC1(struct sis_video_info *ivideo)
2195 old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
2197 if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
2199 return (count != -1);
2202 static void __devinit
2203 sisfb_sense_crt1(struct sis_video_info *ivideo)
2205 bool mustwait = false;
2207 #ifdef CONFIG_FB_SIS_315
2213 inSISIDXREG(SISSR,0x1F,sr1F);
2214 orSISIDXREG(SISSR,0x1F,0x04);
2215 andSISIDXREG(SISSR,0x1F,0x3F);
2216 if(sr1F & 0xc0) mustwait = true;
2218 #ifdef CONFIG_FB_SIS_315
2219 if(ivideo->sisvga_engine == SIS_315_VGA) {
2220 inSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,cr63);
2222 andSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF);
2226 inSISIDXREG(SISCR,0x17,cr17);
2229 orSISIDXREG(SISCR,0x17,0x80);
2231 outSISIDXREG(SISSR, 0x00, 0x01);
2232 outSISIDXREG(SISSR, 0x00, 0x03);
2236 for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo);
2239 #ifdef CONFIG_FB_SIS_315
2240 if(ivideo->chip >= SIS_330) {
2241 andSISIDXREG(SISCR,0x32,~0x20);
2242 if(ivideo->chip >= SIS_340) {
2243 outSISIDXREG(SISCR, 0x57, 0x4a);
2245 outSISIDXREG(SISCR, 0x57, 0x5f);
2247 orSISIDXREG(SISCR, 0x53, 0x02);
2248 while((inSISREG(SISINPSTAT)) & 0x01) break;
2249 while(!((inSISREG(SISINPSTAT)) & 0x01)) break;
2250 if((inSISREG(SISMISCW)) & 0x10) temp = 1;
2251 andSISIDXREG(SISCR, 0x53, 0xfd);
2252 andSISIDXREG(SISCR, 0x57, 0x00);
2256 if(temp == 0xffff) {
2259 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2260 ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
2261 } while(((temp == 0) || (temp == 0xffff)) && i--);
2263 if((temp == 0) || (temp == 0xffff)) {
2264 if(sisfb_test_DDC1(ivideo)) temp = 1;
2268 if((temp) && (temp != 0xffff)) {
2269 orSISIDXREG(SISCR,0x32,0x20);
2272 #ifdef CONFIG_FB_SIS_315
2273 if(ivideo->sisvga_engine == SIS_315_VGA) {
2274 setSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF,cr63);
2278 setSISIDXREG(SISCR,0x17,0x7F,cr17);
2280 outSISIDXREG(SISSR,0x1F,sr1F);
2283 /* Determine and detect attached devices on SiS30x */
2284 static void __devinit
2285 SiS_SenseLCD(struct sis_video_info *ivideo)
2287 unsigned char buffer[256];
2288 unsigned short temp, realcrtno, i;
2289 u8 reg, cr37 = 0, paneltype = 0;
2292 ivideo->SiS_Pr.PanelSelfDetected = false;
2294 /* LCD detection only for TMDS bridges */
2295 if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
2297 if(ivideo->vbflags2 & VB2_30xBDH)
2300 /* If LCD already set up by BIOS, skip it */
2301 inSISIDXREG(SISCR, 0x32, reg);
2306 if(ivideo->SiS_Pr.DDCPortMixup)
2309 /* Check DDC capabilities */
2310 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
2311 realcrtno, 0, &buffer[0], ivideo->vbflags2);
2313 if((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
2317 i = 3; /* Number of retrys */
2319 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2320 ivideo->sisvga_engine, realcrtno, 1,
2321 &buffer[0], ivideo->vbflags2);
2322 } while((temp) && i--);
2327 /* No digital device */
2328 if(!(buffer[0x14] & 0x80))
2331 /* First detailed timing preferred timing? */
2332 if(!(buffer[0x18] & 0x02))
2335 xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
2336 yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
2348 if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
2359 if((buffer[0x47] & 0x18) == 0x18)
2360 cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2364 outSISIDXREG(SISCR, 0x36, paneltype);
2366 setSISIDXREG(SISCR, 0x37, 0x0c, cr37);
2367 orSISIDXREG(SISCR, 0x32, 0x08);
2369 ivideo->SiS_Pr.PanelSelfDetected = true;
2372 static int __devinit
2373 SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
2375 int temp, mytest, result, i, j;
2377 for(j = 0; j < 10; j++) {
2379 for(i = 0; i < 3; i++) {
2381 outSISIDXREG(SISPART4,0x11,(type & 0x00ff));
2382 temp = (type >> 8) | (mytest & 0x00ff);
2383 setSISIDXREG(SISPART4,0x10,0xe0,temp);
2384 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
2387 inSISIDXREG(SISPART4,0x03,temp);
2390 if(temp == mytest) result++;
2392 outSISIDXREG(SISPART4,0x11,0x00);
2393 andSISIDXREG(SISPART4,0x10,0xe0);
2394 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
2397 if((result == 0) || (result >= 2)) break;
2402 static void __devinit
2403 SiS_Sense30x(struct sis_video_info *ivideo)
2405 u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
2406 u16 svhs=0, svhs_c=0;
2407 u16 cvbs=0, cvbs_c=0;
2408 u16 vga2=0, vga2_c=0;
2410 char stdstr[] = "sisfb: Detected";
2411 char tvstr[] = "TV connected to";
2413 if(ivideo->vbflags2 & VB2_301) {
2414 svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
2415 inSISIDXREG(SISPART4,0x01,myflag);
2417 svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
2419 } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) {
2420 svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
2421 } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) {
2422 svhs = 0x0200; cvbs = 0x0100;
2423 } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
2424 svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
2428 vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
2429 if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
2430 svhs_c = 0x0408; cvbs_c = 0x0808;
2434 if(ivideo->haveXGIROM) {
2435 biosflag = ivideo->bios_abase[0x58] & 0x03;
2436 } else if(ivideo->newrom) {
2437 if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01;
2438 } else if(ivideo->sisvga_engine == SIS_300_VGA) {
2439 if(ivideo->bios_abase) {
2440 biosflag = ivideo->bios_abase[0xfe] & 0x03;
2444 if(ivideo->chip == SIS_300) {
2445 inSISIDXREG(SISSR,0x3b,myflag);
2446 if(!(myflag & 0x01)) vga2 = vga2_c = 0;
2449 if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) {
2453 inSISIDXREG(SISSR,0x1e,backupSR_1e);
2454 orSISIDXREG(SISSR,0x1e,0x20);
2456 inSISIDXREG(SISPART4,0x0d,backupP4_0d);
2457 if(ivideo->vbflags2 & VB2_30xC) {
2458 setSISIDXREG(SISPART4,0x0d,~0x07,0x01);
2460 orSISIDXREG(SISPART4,0x0d,0x04);
2462 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2464 inSISIDXREG(SISPART2,0x00,backupP2_00);
2465 outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc));
2467 inSISIDXREG(SISPART2,0x4d,backupP2_4d);
2468 if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
2469 outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10));
2472 if(!(ivideo->vbflags2 & VB2_30xCLV)) {
2473 SISDoSense(ivideo, 0, 0);
2476 andSISIDXREG(SISCR, 0x32, ~0x14);
2478 if(vga2_c || vga2) {
2479 if(SISDoSense(ivideo, vga2, vga2_c)) {
2480 if(biosflag & 0x01) {
2481 printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
2482 orSISIDXREG(SISCR, 0x32, 0x04);
2484 printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
2485 orSISIDXREG(SISCR, 0x32, 0x10);
2490 andSISIDXREG(SISCR, 0x32, 0x3f);
2492 if(ivideo->vbflags2 & VB2_30xCLV) {
2493 orSISIDXREG(SISPART4,0x0d,0x04);
2496 if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
2497 outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10));
2498 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2499 if((result = SISDoSense(ivideo, svhs, 0x0604))) {
2500 if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
2501 printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
2502 orSISIDXREG(SISCR,0x32,0x80);
2505 outSISIDXREG(SISPART2,0x4d,backupP2_4d);
2508 andSISIDXREG(SISCR, 0x32, ~0x03);
2510 if(!(ivideo->vbflags & TV_YPBPR)) {
2511 if((result = SISDoSense(ivideo, svhs, svhs_c))) {
2512 printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
2513 orSISIDXREG(SISCR, 0x32, 0x02);
2515 if((biosflag & 0x02) || (!result)) {
2516 if(SISDoSense(ivideo, cvbs, cvbs_c)) {
2517 printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
2518 orSISIDXREG(SISCR, 0x32, 0x01);
2523 SISDoSense(ivideo, 0, 0);
2525 outSISIDXREG(SISPART2,0x00,backupP2_00);
2526 outSISIDXREG(SISPART4,0x0d,backupP4_0d);
2527 outSISIDXREG(SISSR,0x1e,backupSR_1e);
2529 if(ivideo->vbflags2 & VB2_30xCLV) {
2530 inSISIDXREG(SISPART2,0x00,biosflag);
2531 if(biosflag & 0x20) {
2532 for(myflag = 2; myflag > 0; myflag--) {
2534 outSISIDXREG(SISPART2,0x00,biosflag);
2539 outSISIDXREG(SISPART2,0x00,backupP2_00);
2542 /* Determine and detect attached TV's on Chrontel */
2543 static void __devinit
2544 SiS_SenseCh(struct sis_video_info *ivideo)
2546 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2548 char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
2550 #ifdef CONFIG_FB_SIS_300
2551 unsigned char test[3];
2555 if(ivideo->chip < SIS_315H) {
2557 #ifdef CONFIG_FB_SIS_300
2558 ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1; /* Chrontel 700x */
2559 SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c); /* Set general purpose IO for Chrontel communication */
2560 SiS_DDC2Delay(&ivideo->SiS_Pr, 1000);
2561 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2562 /* See Chrontel TB31 for explanation */
2563 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2564 if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
2565 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b);
2566 SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2568 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2569 if(temp2 != temp1) temp1 = temp2;
2571 if((temp1 >= 0x22) && (temp1 <= 0x50)) {
2572 /* Read power status */
2573 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2574 if((temp1 & 0x03) != 0x03) {
2575 /* Power all outputs */
2576 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b);
2577 SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2579 /* Sense connected TV devices */
2580 for(i = 0; i < 3; i++) {
2581 SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01);
2582 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2583 SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00);
2584 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2585 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
2586 if(!(temp1 & 0x08)) test[i] = 0x02;
2587 else if(!(temp1 & 0x02)) test[i] = 0x01;
2589 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2592 if(test[0] == test[1]) temp1 = test[0];
2593 else if(test[0] == test[2]) temp1 = test[0];
2594 else if(test[1] == test[2]) temp1 = test[1];
2597 "sisfb: TV detection unreliable - test results varied\n");
2601 printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2602 ivideo->vbflags |= TV_SVIDEO;
2603 orSISIDXREG(SISCR, 0x32, 0x02);
2604 andSISIDXREG(SISCR, 0x32, ~0x05);
2605 } else if (temp1 == 0x01) {
2606 printk(KERN_INFO "%s CVBS output\n", stdstr);
2607 ivideo->vbflags |= TV_AVIDEO;
2608 orSISIDXREG(SISCR, 0x32, 0x01);
2609 andSISIDXREG(SISCR, 0x32, ~0x06);
2611 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2612 andSISIDXREG(SISCR, 0x32, ~0x07);
2614 } else if(temp1 == 0) {
2615 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2616 andSISIDXREG(SISCR, 0x32, ~0x07);
2618 /* Set general purpose IO for Chrontel communication */
2619 SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
2624 #ifdef CONFIG_FB_SIS_315
2625 ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */
2626 temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
2627 SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20);
2628 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2629 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2631 SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2632 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2634 SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2635 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2636 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2637 SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1);
2639 if(temp2 & 0x02) temp1 |= 0x01;
2640 if(temp2 & 0x10) temp1 |= 0x01;
2641 if(temp2 & 0x04) temp1 |= 0x02;
2642 if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
2645 printk(KERN_INFO "%s CVBS output\n", stdstr);
2646 ivideo->vbflags |= TV_AVIDEO;
2647 orSISIDXREG(SISCR, 0x32, 0x01);
2648 andSISIDXREG(SISCR, 0x32, ~0x06);
2651 printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2652 ivideo->vbflags |= TV_SVIDEO;
2653 orSISIDXREG(SISCR, 0x32, 0x02);
2654 andSISIDXREG(SISCR, 0x32, ~0x05);
2657 printk(KERN_INFO "%s SCART output\n", stdstr);
2658 orSISIDXREG(SISCR, 0x32, 0x04);
2659 andSISIDXREG(SISCR, 0x32, ~0x03);
2662 andSISIDXREG(SISCR, 0x32, ~0x07);
2668 static void __devinit
2669 sisfb_get_VB_type(struct sis_video_info *ivideo)
2671 char stdstr[] = "sisfb: Detected";
2672 char bridgestr[] = "video bridge";
2676 /* No CRT2 on XGI Z7 */
2677 if(ivideo->chip == XGI_20)
2680 inSISIDXREG(SISPART4, 0x00, vb_chipid);
2683 inSISIDXREG(SISPART4, 0x01, reg);
2685 ivideo->vbflags |= VB_301; /* Deprecated */
2686 ivideo->vbflags2 |= VB2_301;
2687 printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
2688 } else if(reg < 0xc0) {
2689 ivideo->vbflags |= VB_301B; /* Deprecated */
2690 ivideo->vbflags2 |= VB2_301B;
2691 inSISIDXREG(SISPART4,0x23,reg);
2693 ivideo->vbflags |= VB_30xBDH; /* Deprecated */
2694 ivideo->vbflags2 |= VB2_30xBDH;
2695 printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
2697 printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
2699 } else if(reg < 0xd0) {
2700 ivideo->vbflags |= VB_301C; /* Deprecated */
2701 ivideo->vbflags2 |= VB2_301C;
2702 printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
2703 } else if(reg < 0xe0) {
2704 ivideo->vbflags |= VB_301LV; /* Deprecated */
2705 ivideo->vbflags2 |= VB2_301LV;
2706 printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
2707 } else if(reg <= 0xe1) {
2708 inSISIDXREG(SISPART4,0x39,reg);
2710 ivideo->vbflags |= VB_302LV; /* Deprecated */
2711 ivideo->vbflags2 |= VB2_302LV;
2712 printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
2714 ivideo->vbflags |= VB_301C; /* Deprecated */
2715 ivideo->vbflags2 |= VB2_301C;
2716 printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
2718 ivideo->vbflags |= VB_302ELV; /* Deprecated */
2719 ivideo->vbflags2 |= VB2_302ELV;
2720 printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
2726 ivideo->vbflags |= VB_302B; /* Deprecated */
2727 ivideo->vbflags2 |= VB2_302B;
2728 printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
2732 if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
2733 inSISIDXREG(SISCR, 0x37, reg);
2734 reg &= SIS_EXTERNAL_CHIP_MASK;
2736 if(ivideo->sisvga_engine == SIS_300_VGA) {
2737 #ifdef CONFIG_FB_SIS_300
2739 case SIS_EXTERNAL_CHIP_LVDS:
2740 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2741 ivideo->vbflags2 |= VB2_LVDS;
2743 case SIS_EXTERNAL_CHIP_TRUMPION:
2744 ivideo->vbflags |= (VB_LVDS | VB_TRUMPION); /* Deprecated */
2745 ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION);
2747 case SIS_EXTERNAL_CHIP_CHRONTEL:
2748 ivideo->vbflags |= VB_CHRONTEL; /* Deprecated */
2749 ivideo->vbflags2 |= VB2_CHRONTEL;
2751 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
2752 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2753 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2756 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1;
2758 } else if(ivideo->chip < SIS_661) {
2759 #ifdef CONFIG_FB_SIS_315
2761 case SIS310_EXTERNAL_CHIP_LVDS:
2762 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2763 ivideo->vbflags2 |= VB2_LVDS;
2765 case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
2766 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2767 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2770 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2772 } else if(ivideo->chip >= SIS_661) {
2773 #ifdef CONFIG_FB_SIS_315
2774 inSISIDXREG(SISCR, 0x38, reg);
2778 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2779 ivideo->vbflags2 |= VB2_LVDS;
2782 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2783 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2786 ivideo->vbflags |= (VB_LVDS | VB_CONEXANT); /* Deprecated */
2787 ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT);
2790 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2793 if(ivideo->vbflags2 & VB2_LVDS) {
2794 printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
2796 if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) {
2797 printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
2799 if(ivideo->vbflags2 & VB2_CHRONTEL) {
2800 printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
2802 if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) {
2803 printk(KERN_INFO "%s Conexant external device\n", stdstr);
2807 if(ivideo->vbflags2 & VB2_SISBRIDGE) {
2808 SiS_SenseLCD(ivideo);
2809 SiS_Sense30x(ivideo);
2810 } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
2811 SiS_SenseCh(ivideo);
2815 /* ---------- Engine initialization routines ------------ */
2818 sisfb_engine_init(struct sis_video_info *ivideo)
2821 /* Initialize command queue (we use MMIO only) */
2823 /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
2825 ivideo->caps &= ~(TURBO_QUEUE_CAP |
2826 MMIO_CMD_QUEUE_CAP |
2830 #ifdef CONFIG_FB_SIS_300
2831 if(ivideo->sisvga_engine == SIS_300_VGA) {
2835 tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
2837 inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
2840 tq_state |= (u8)(tqueue_pos >> 8);
2841 outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
2843 outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
2845 ivideo->caps |= TURBO_QUEUE_CAP;
2849 #ifdef CONFIG_FB_SIS_315
2850 if(ivideo->sisvga_engine == SIS_315_VGA) {
2851 u32 tempq = 0, templ;
2854 if(ivideo->chip == XGI_20) {
2855 switch(ivideo->cmdQueueSize) {
2857 temp = SIS_CMD_QUEUE_SIZE_Z7_64k;
2861 temp = SIS_CMD_QUEUE_SIZE_Z7_128k;
2864 switch(ivideo->cmdQueueSize) {
2865 case (4 * 1024 * 1024):
2866 temp = SIS_CMD_QUEUE_SIZE_4M;
2868 case (2 * 1024 * 1024):
2869 temp = SIS_CMD_QUEUE_SIZE_2M;
2871 case (1 * 1024 * 1024):
2872 temp = SIS_CMD_QUEUE_SIZE_1M;
2876 temp = SIS_CMD_QUEUE_SIZE_512k;
2880 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2881 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2883 if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
2884 /* Must disable dual pipe on XGI_40. Can't do
2885 * this in MMIO mode, because it requires
2886 * setting/clearing a bit in the MMIO fire trigger
2889 if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) {
2891 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
2893 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
2895 tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
2896 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
2898 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2899 MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq);
2901 writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq);
2902 writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4);
2903 writel(0x168F0000, ivideo->video_vbase + tempq + 8);
2904 writel(0x168F0000, ivideo->video_vbase + tempq + 12);
2906 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16));
2908 sisfb_syncaccel(ivideo);
2910 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2915 tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
2916 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
2918 temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
2919 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
2921 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2922 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
2924 ivideo->caps |= MMIO_CMD_QUEUE_CAP;
2928 ivideo->engineok = 1;
2931 static void __devinit
2932 sisfb_detect_lcd_type(struct sis_video_info *ivideo)
2937 inSISIDXREG(SISCR, 0x36, reg);
2939 if(ivideo->sisvga_engine == SIS_300_VGA) {
2940 ivideo->CRT2LCDType = sis300paneltype[reg];
2941 } else if(ivideo->chip >= SIS_661) {
2942 ivideo->CRT2LCDType = sis661paneltype[reg];
2944 ivideo->CRT2LCDType = sis310paneltype[reg];
2945 if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
2946 if((ivideo->CRT2LCDType != LCD_320x240_2) &&
2947 (ivideo->CRT2LCDType != LCD_320x240_3)) {
2948 ivideo->CRT2LCDType = LCD_320x240;
2953 if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
2954 /* For broken BIOSes: Assume 1024x768, RGB18 */
2955 ivideo->CRT2LCDType = LCD_1024x768;
2956 setSISIDXREG(SISCR,0x36,0xf0,0x02);
2957 setSISIDXREG(SISCR,0x37,0xee,0x01);
2958 printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
2961 for(i = 0; i < SIS_LCD_NUMBER; i++) {
2962 if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
2963 ivideo->lcdxres = sis_lcd_data[i].xres;
2964 ivideo->lcdyres = sis_lcd_data[i].yres;
2965 ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
2970 #ifdef CONFIG_FB_SIS_300
2971 if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
2972 ivideo->lcdxres = 1360; ivideo->lcdyres = 1024;
2973 ivideo->lcddefmodeidx = DEFAULT_MODE_1360;
2974 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
2975 ivideo->lcdxres = 848; ivideo->lcdyres = 480;
2976 ivideo->lcddefmodeidx = DEFAULT_MODE_848;
2977 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) {
2978 ivideo->lcdxres = 856; ivideo->lcdyres = 480;
2979 ivideo->lcddefmodeidx = DEFAULT_MODE_856;
2983 printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
2984 ivideo->lcdxres, ivideo->lcdyres);
2987 static void __devinit
2988 sisfb_save_pdc_emi(struct sis_video_info *ivideo)
2990 #ifdef CONFIG_FB_SIS_300
2991 /* Save the current PanelDelayCompensation if the LCD is currently used */
2992 if(ivideo->sisvga_engine == SIS_300_VGA) {
2993 if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
2995 inSISIDXREG(SISCR,0x30,tmp);
2997 /* Currently on LCD? If yes, read current pdc */
2998 inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc);
2999 ivideo->detectedpdc &= 0x3c;
3000 if(ivideo->SiS_Pr.PDC == -1) {
3001 /* Let option override detection */
3002 ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
3004 printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
3005 ivideo->detectedpdc);
3007 if((ivideo->SiS_Pr.PDC != -1) &&
3008 (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
3009 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
3010 ivideo->SiS_Pr.PDC);
3016 #ifdef CONFIG_FB_SIS_315
3017 if(ivideo->sisvga_engine == SIS_315_VGA) {
3019 /* Try to find about LCDA */
3020 if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
3022 inSISIDXREG(SISPART1,0x13,tmp);
3024 ivideo->SiS_Pr.SiS_UseLCDA = true;
3025 ivideo->detectedlcda = 0x03;
3030 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
3032 inSISIDXREG(SISCR,0x30,tmp);
3033 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3034 /* Currently on LCD? If yes, read current pdc */
3036 inSISIDXREG(SISPART1,0x2D,pdc);
3037 ivideo->detectedpdc = (pdc & 0x0f) << 1;
3038 ivideo->detectedpdca = (pdc & 0xf0) >> 3;
3039 inSISIDXREG(SISPART1,0x35,pdc);
3040 ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
3041 inSISIDXREG(SISPART1,0x20,pdc);
3042 ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
3043 if(ivideo->newrom) {
3044 /* New ROM invalidates other PDC resp. */
3045 if(ivideo->detectedlcda != 0xff) {
3046 ivideo->detectedpdc = 0xff;
3048 ivideo->detectedpdca = 0xff;
3051 if(ivideo->SiS_Pr.PDC == -1) {
3052 if(ivideo->detectedpdc != 0xff) {
3053 ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
3056 if(ivideo->SiS_Pr.PDCA == -1) {
3057 if(ivideo->detectedpdca != 0xff) {
3058 ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
3061 if(ivideo->detectedpdc != 0xff) {
3063 "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3064 ivideo->detectedpdc);
3066 if(ivideo->detectedpdca != 0xff) {
3068 "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3069 ivideo->detectedpdca);
3074 if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
3075 inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30);
3076 inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31);
3077 inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32);
3078 inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33);
3079 ivideo->SiS_Pr.HaveEMI = true;
3080 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3081 ivideo->SiS_Pr.HaveEMILCD = true;
3086 /* Let user override detected PDCs (all bridges) */
3087 if(ivideo->vbflags2 & VB2_30xBLV) {
3088 if((ivideo->SiS_Pr.PDC != -1) &&
3089 (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
3090 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3091 ivideo->SiS_Pr.PDC);
3093 if((ivideo->SiS_Pr.PDCA != -1) &&
3094 (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
3095 printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3096 ivideo->SiS_Pr.PDCA);
3104 /* -------------------- Memory manager routines ---------------------- */
3106 static u32 __devinit
3107 sisfb_getheapstart(struct sis_video_info *ivideo)
3109 u32 ret = ivideo->sisfb_parm_mem * 1024;
3110 u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3113 /* Calculate heap start = end of memory for console
3115 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3116 * C = console, D = heap, H = HWCursor, Q = cmd-queue
3118 * On 76x in UMA+LFB mode, the layout is as follows:
3119 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3120 * where the heap is the entire UMA area, eventually
3121 * into the LFB area if the given mem parameter is
3122 * higher than the size of the UMA memory.
3124 * Basically given by "mem" parameter
3126 * maximum = videosize - cmd_queue - hwcursor
3127 * (results in a heap of size 0)
3128 * default = SiS 300: depends on videosize
3129 * SiS 315/330/340/XGI: 32k below max
3132 if(ivideo->sisvga_engine == SIS_300_VGA) {
3133 if(ivideo->video_size > 0x1000000) {
3135 } else if(ivideo->video_size > 0x800000) {
3140 } else if(ivideo->UMAsize && ivideo->LFBsize) {
3143 def = maxoffs - 0x8000;
3146 /* Use default for secondary card for now (FIXME) */
3147 if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0))
3153 static u32 __devinit
3154 sisfb_getheapsize(struct sis_video_info *ivideo)
3156 u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3159 if(ivideo->UMAsize && ivideo->LFBsize) {
3160 if( (!ivideo->sisfb_parm_mem) ||
3161 ((ivideo->sisfb_parm_mem * 1024) > max) ||
3162 ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) {
3163 ret = ivideo->UMAsize;
3164 max -= ivideo->UMAsize;
3166 ret = max - (ivideo->sisfb_parm_mem * 1024);
3167 max = ivideo->sisfb_parm_mem * 1024;
3169 ivideo->video_offset = ret;
3170 ivideo->sisfb_mem = max;
3172 ret = max - ivideo->heapstart;
3173 ivideo->sisfb_mem = ivideo->heapstart;
3179 static int __devinit
3180 sisfb_heap_init(struct sis_video_info *ivideo)
3184 ivideo->video_offset = 0;
3185 if(ivideo->sisfb_parm_mem) {
3186 if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) ||
3187 (ivideo->sisfb_parm_mem > ivideo->video_size) ) {
3188 ivideo->sisfb_parm_mem = 0;
3192 ivideo->heapstart = sisfb_getheapstart(ivideo);
3193 ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo);
3195 ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
3196 ivideo->sisfb_heap_end = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size;
3198 printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
3199 (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
3201 ivideo->sisfb_heap.vinfo = ivideo;
3203 ivideo->sisfb_heap.poha_chain = NULL;
3204 ivideo->sisfb_heap.poh_freelist = NULL;
3206 poh = sisfb_poh_new_node(&ivideo->sisfb_heap);
3210 poh->poh_next = &ivideo->sisfb_heap.oh_free;
3211 poh->poh_prev = &ivideo->sisfb_heap.oh_free;
3212 poh->size = ivideo->sisfb_heap_size;
3213 poh->offset = ivideo->heapstart;
3215 ivideo->sisfb_heap.oh_free.poh_next = poh;
3216 ivideo->sisfb_heap.oh_free.poh_prev = poh;
3217 ivideo->sisfb_heap.oh_free.size = 0;
3218 ivideo->sisfb_heap.max_freesize = poh->size;
3220 ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used;
3221 ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used;
3222 ivideo->sisfb_heap.oh_used.size = SENTINEL;
3224 if(ivideo->cardnumber == 0) {
3225 /* For the first card, make this heap the "global" one
3226 * for old DRM (which could handle only one card)
3228 sisfb_heap = &ivideo->sisfb_heap;
3234 static struct SIS_OH *
3235 sisfb_poh_new_node(struct SIS_HEAP *memheap)
3237 struct SIS_OHALLOC *poha;
3242 if(memheap->poh_freelist == NULL) {
3243 poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
3247 poha->poha_next = memheap->poha_chain;
3248 memheap->poha_chain = poha;
3250 cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1;
3252 poh = &poha->aoh[0];
3253 for(i = cOhs - 1; i != 0; i--) {
3254 poh->poh_next = poh + 1;
3258 poh->poh_next = NULL;
3259 memheap->poh_freelist = &poha->aoh[0];
3262 poh = memheap->poh_freelist;
3263 memheap->poh_freelist = poh->poh_next;
3268 static struct SIS_OH *
3269 sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size)
3271 struct SIS_OH *pohThis;
3272 struct SIS_OH *pohRoot;
3275 if(size > memheap->max_freesize) {
3276 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3277 (unsigned int) size / 1024);
3281 pohThis = memheap->oh_free.poh_next;
3283 while(pohThis != &memheap->oh_free) {
3284 if(size <= pohThis->size) {
3288 pohThis = pohThis->poh_next;
3292 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3293 (unsigned int) size / 1024);
3297 if(size == pohThis->size) {
3299 sisfb_delete_node(pohThis);
3301 pohRoot = sisfb_poh_new_node(memheap);
3305 pohRoot->offset = pohThis->offset;
3306 pohRoot->size = size;
3308 pohThis->offset += size;
3309 pohThis->size -= size;
3312 memheap->max_freesize -= size;
3314 pohThis = &memheap->oh_used;
3315 sisfb_insert_node(pohThis, pohRoot);
3321 sisfb_delete_node(struct SIS_OH *poh)
3323 poh->poh_prev->poh_next = poh->poh_next;
3324 poh->poh_next->poh_prev = poh->poh_prev;
3328 sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh)
3330 struct SIS_OH *pohTemp = pohList->poh_next;
3332 pohList->poh_next = poh;
3333 pohTemp->poh_prev = poh;
3335 poh->poh_prev = pohList;
3336 poh->poh_next = pohTemp;
3339 static struct SIS_OH *
3340 sisfb_poh_free(struct SIS_HEAP *memheap, u32 base)
3342 struct SIS_OH *pohThis;
3343 struct SIS_OH *poh_freed;
3344 struct SIS_OH *poh_prev;
3345 struct SIS_OH *poh_next;
3350 poh_freed = memheap->oh_used.poh_next;
3352 while(poh_freed != &memheap->oh_used) {
3353 if(poh_freed->offset == base) {
3358 poh_freed = poh_freed->poh_next;
3364 memheap->max_freesize += poh_freed->size;
3366 poh_prev = poh_next = NULL;
3367 ulUpper = poh_freed->offset + poh_freed->size;
3368 ulLower = poh_freed->offset;
3370 pohThis = memheap->oh_free.poh_next;
3372 while(pohThis != &memheap->oh_free) {
3373 if(pohThis->offset == ulUpper) {
3375 } else if((pohThis->offset + pohThis->size) == ulLower) {
3378 pohThis = pohThis->poh_next;
3381 sisfb_delete_node(poh_freed);
3383 if(poh_prev && poh_next) {
3384 poh_prev->size += (poh_freed->size + poh_next->size);
3385 sisfb_delete_node(poh_next);
3386 sisfb_free_node(memheap, poh_freed);
3387 sisfb_free_node(memheap, poh_next);
3392 poh_prev->size += poh_freed->size;
3393 sisfb_free_node(memheap, poh_freed);
3398 poh_next->size += poh_freed->size;
3399 poh_next->offset = poh_freed->offset;
3400 sisfb_free_node(memheap, poh_freed);
3404 sisfb_insert_node(&memheap->oh_free, poh_freed);
3410 sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh)
3415 poh->poh_next = memheap->poh_freelist;
3416 memheap->poh_freelist = poh;
3420 sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req)
3422 struct SIS_OH *poh = NULL;
3424 if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap))
3425 poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size);
3428 req->offset = req->size = 0;
3429 DPRINTK("sisfb: Video RAM allocation failed\n");
3431 req->offset = poh->offset;
3432 req->size = poh->size;
3433 DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3434 (poh->offset + ivideo->video_vbase));
3439 sis_malloc(struct sis_memreq *req)
3441 struct sis_video_info *ivideo = sisfb_heap->vinfo;
3443 if(&ivideo->sisfb_heap == sisfb_heap)
3444 sis_int_malloc(ivideo, req);
3446 req->offset = req->size = 0;
3450 sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
3452 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3454 sis_int_malloc(ivideo, req);
3457 /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3460 sis_int_free(struct sis_video_info *ivideo, u32 base)
3464 if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap))
3467 poh = sisfb_poh_free(&ivideo->sisfb_heap, base);
3470 DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
3471 (unsigned int) base);
3478 struct sis_video_info *ivideo = sisfb_heap->vinfo;
3480 sis_int_free(ivideo, base);
3484 sis_free_new(struct pci_dev *pdev, u32 base)
3486 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3488 sis_int_free(ivideo, base);
3491 /* --------------------- SetMode routines ------------------------- */
3494 sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
3498 /* Check if MMIO and engines are enabled,
3499 * and sync in case they are. Can't use
3500 * ivideo->accel here, as this might have
3501 * been changed before this is called.
3503 inSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, cr30);
3504 inSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, cr31);
3505 /* MMIO and 2D/3D engine enabled? */
3506 if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
3507 #ifdef CONFIG_FB_SIS_300
3508 if(ivideo->sisvga_engine == SIS_300_VGA) {
3509 /* Don't care about TurboQueue. It's
3510 * enough to know that the engines
3513 sisfb_syncaccel(ivideo);
3516 #ifdef CONFIG_FB_SIS_315
3517 if(ivideo->sisvga_engine == SIS_315_VGA) {
3518 /* Check that any queue mode is
3519 * enabled, and that the queue
3520 * is not in the state of "reset"
3522 inSISIDXREG(SISSR, 0x26, cr30);
3523 if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
3524 sisfb_syncaccel(ivideo);
3532 sisfb_pre_setmode(struct sis_video_info *ivideo)
3534 u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
3537 ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
3539 outSISIDXREG(SISSR, 0x05, 0x86);
3541 inSISIDXREG(SISCR, 0x31, cr31);
3545 cr33 = ivideo->rate_idx & 0x0F;
3547 #ifdef CONFIG_FB_SIS_315
3548 if(ivideo->sisvga_engine == SIS_315_VGA) {
3549 if(ivideo->chip >= SIS_661) {
3550 inSISIDXREG(SISCR, 0x38, cr38);
3551 cr38 &= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
3554 inSISIDXREG(SISCR, tvregnum, cr38);
3555 cr38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
3559 #ifdef CONFIG_FB_SIS_300
3560 if(ivideo->sisvga_engine == SIS_300_VGA) {
3562 inSISIDXREG(SISCR, tvregnum, cr38);
3566 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
3567 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
3568 ivideo->curFSTN = ivideo->curDSTN = 0;
3570 switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
3573 cr38 &= ~0xc0; /* Clear PAL-M / PAL-N bits */
3574 if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
3575 #ifdef CONFIG_FB_SIS_315
3576 if(ivideo->chip >= SIS_661) {
3578 if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20;
3579 else if(ivideo->vbflags & TV_YPBPR750P) cr35 |= 0x40;
3580 else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
3581 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3583 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3584 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
3585 cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3587 if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10;
3588 else if(ivideo->vbflags & TV_YPBPR750P) cr38 |= 0x20;
3589 else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
3591 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3594 } else if((ivideo->vbflags & TV_HIVISION) &&
3595 (ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) {
3596 if(ivideo->chip >= SIS_661) {
3602 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3605 ivideo->currentvbflags |= TV_HIVISION;
3606 } else if(ivideo->vbflags & TV_SCART) {
3607 cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
3610 ivideo->currentvbflags |= TV_SCART;
3612 if(ivideo->vbflags & TV_SVIDEO) {
3613 cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
3614 ivideo->currentvbflags |= TV_SVIDEO;
3616 if(ivideo->vbflags & TV_AVIDEO) {
3617 cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
3618 ivideo->currentvbflags |= TV_AVIDEO;
3621 cr31 |= SIS_DRIVER_MODE;
3623 if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) {
3624 if(ivideo->vbflags & TV_PAL) {
3625 cr31 |= 0x01; cr35 |= 0x01;
3626 ivideo->currentvbflags |= TV_PAL;
3627 if(ivideo->vbflags & TV_PALM) {
3628 cr38 |= 0x40; cr35 |= 0x04;
3629 ivideo->currentvbflags |= TV_PALM;
3630 } else if(ivideo->vbflags & TV_PALN) {
3631 cr38 |= 0x80; cr35 |= 0x08;
3632 ivideo->currentvbflags |= TV_PALN;
3635 cr31 &= ~0x01; cr35 &= ~0x01;
3636 ivideo->currentvbflags |= TV_NTSC;
3637 if(ivideo->vbflags & TV_NTSCJ) {
3638 cr38 |= 0x40; cr35 |= 0x02;
3639 ivideo->currentvbflags |= TV_NTSCJ;
3646 cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
3647 cr31 |= SIS_DRIVER_MODE;
3648 SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
3649 SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
3650 ivideo->curFSTN = ivideo->sisfb_fstn;
3651 ivideo->curDSTN = ivideo->sisfb_dstn;
3655 cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3656 cr31 |= SIS_DRIVER_MODE;
3657 if(ivideo->sisfb_nocrt2rate) {
3658 cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4);
3660 cr33 |= ((ivideo->rate_idx & 0x0F) << 4);
3664 default: /* disable CRT2 */
3666 cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
3669 outSISIDXREG(SISCR, 0x30, cr30);
3670 outSISIDXREG(SISCR, 0x33, cr33);
3672 if(ivideo->chip >= SIS_661) {
3673 #ifdef CONFIG_FB_SIS_315
3674 cr31 &= ~0x01; /* Clear PAL flag (now in CR35) */
3675 setSISIDXREG(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
3676 cr38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
3677 setSISIDXREG(SISCR, 0x38, 0xf8, cr38);
3679 } else if(ivideo->chip != SIS_300) {
3680 outSISIDXREG(SISCR, tvregnum, cr38);
3682 outSISIDXREG(SISCR, 0x31, cr31);
3684 ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
3686 sisfb_check_engine_and_sync(ivideo);
3689 /* Fix SR11 for 661 and later */
3690 #ifdef CONFIG_FB_SIS_315
3692 sisfb_fixup_SR11(struct sis_video_info *ivideo)
3696 if(ivideo->chip >= SIS_661) {
3697 inSISIDXREG(SISSR,0x11,tmpreg);
3699 inSISIDXREG(SISSR,0x3e,tmpreg);
3700 tmpreg = (tmpreg + 1) & 0xff;
3701 outSISIDXREG(SISSR,0x3e,tmpreg);
3702 inSISIDXREG(SISSR,0x11,tmpreg);
3705 andSISIDXREG(SISSR,0x11,0x0f);
3712 sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
3714 if(val > 32) val = 32;
3715 if(val < -32) val = -32;
3716 ivideo->tvxpos = val;
3718 if(ivideo->sisfblocked) return;
3719 if(!ivideo->modechanged) return;
3721 if(ivideo->currentvbflags & CRT2_TV) {
3723 if(ivideo->vbflags2 & VB2_CHRONTEL) {
3725 int x = ivideo->tvx;
3727 switch(ivideo->chronteltype) {
3731 outSISIDXREG(SISSR,0x05,0x86);
3732 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
3733 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
3736 /* Not supported by hardware */
3740 } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3742 u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
3743 unsigned short temp;
3745 p2_1f = ivideo->p2_1f;
3746 p2_20 = ivideo->p2_20;
3747 p2_2b = ivideo->p2_2b;
3748 p2_42 = ivideo->p2_42;
3749 p2_43 = ivideo->p2_43;
3751 temp = p2_1f | ((p2_20 & 0xf0) << 4);
3753 p2_1f = temp & 0xff;
3754 p2_20 = (temp & 0xf00) >> 4;
3755 p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
3756 temp = p2_43 | ((p2_42 & 0xf0) << 4);
3758 p2_43 = temp & 0xff;
3759 p2_42 = (temp & 0xf00) >> 4;
3760 outSISIDXREG(SISPART2,0x1f,p2_1f);
3761 setSISIDXREG(SISPART2,0x20,0x0F,p2_20);
3762 setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b);
3763 setSISIDXREG(SISPART2,0x42,0x0F,p2_42);
3764 outSISIDXREG(SISPART2,0x43,p2_43);
3770 sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
3772 if(val > 32) val = 32;
3773 if(val < -32) val = -32;
3774 ivideo->tvypos = val;
3776 if(ivideo->sisfblocked) return;
3777 if(!ivideo->modechanged) return;
3779 if(ivideo->currentvbflags & CRT2_TV) {
3781 if(ivideo->vbflags2 & VB2_CHRONTEL) {
3783 int y = ivideo->tvy;
3785 switch(ivideo->chronteltype) {
3789 outSISIDXREG(SISSR,0x05,0x86);
3790 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
3791 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
3794 /* Not supported by hardware */
3798 } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3802 p2_01 = ivideo->p2_01;
3803 p2_02 = ivideo->p2_02;
3807 if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) {
3808 while((p2_01 <= 0) || (p2_02 <= 0)) {
3813 outSISIDXREG(SISPART2,0x01,p2_01);
3814 outSISIDXREG(SISPART2,0x02,p2_02);
3820 sisfb_post_setmode(struct sis_video_info *ivideo)
3822 bool crt1isoff = false;
3824 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
3827 #ifdef CONFIG_FB_SIS_315
3831 outSISIDXREG(SISSR, 0x05, 0x86);
3833 #ifdef CONFIG_FB_SIS_315
3834 sisfb_fixup_SR11(ivideo);
3837 /* Now we actually HAVE changed the display mode */
3838 ivideo->modechanged = 1;
3840 /* We can't switch off CRT1 if bridge is in slave mode */
3841 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
3842 if(sisfb_bridgeisslave(ivideo)) doit = false;
3844 ivideo->sisfb_crt1off = 0;
3846 #ifdef CONFIG_FB_SIS_300
3847 if(ivideo->sisvga_engine == SIS_300_VGA) {
3848 if((ivideo->sisfb_crt1off) && (doit)) {
3855 setSISIDXREG(SISCR, 0x17, 0x7f, reg);
3858 #ifdef CONFIG_FB_SIS_315
3859 if(ivideo->sisvga_engine == SIS_315_VGA) {
3860 if((ivideo->sisfb_crt1off) && (doit)) {
3869 setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
3870 setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1);
3875 ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
3876 ivideo->currentvbflags |= VB_SINGLE_MODE;
3878 ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
3879 if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
3880 ivideo->currentvbflags |= VB_MIRROR_MODE;
3882 ivideo->currentvbflags |= VB_SINGLE_MODE;
3886 andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
3888 if(ivideo->currentvbflags & CRT2_TV) {
3889 if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3890 inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f);
3891 inSISIDXREG(SISPART2,0x20,ivideo->p2_20);
3892 inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b);
3893 inSISIDXREG(SISPART2,0x42,ivideo->p2_42);
3894 inSISIDXREG(SISPART2,0x43,ivideo->p2_43);
3895 inSISIDXREG(SISPART2,0x01,ivideo->p2_01);
3896 inSISIDXREG(SISPART2,0x02,ivideo->p2_02);
3897 } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
3898 if(ivideo->chronteltype == 1) {
3899 ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
3900 ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
3901 ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
3902 ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
3907 if(ivideo->tvxpos) {
3908 sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
3910 if(ivideo->tvypos) {
3911 sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
3914 /* Eventually sync engines */
3915 sisfb_check_engine_and_sync(ivideo);
3917 /* (Re-)Initialize chip engines */
3919 sisfb_engine_init(ivideo);
3921 ivideo->engineok = 0;
3926 sisfb_reset_mode(struct sis_video_info *ivideo)
3928 if(sisfb_set_mode(ivideo, 0))
3931 sisfb_set_pitch(ivideo);
3932 sisfb_set_base_CRT1(ivideo, ivideo->current_base);
3933 sisfb_set_base_CRT2(ivideo, ivideo->current_base);
3939 sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command)
3943 switch(sisfb_command->sisfb_cmd) {
3944 case SISFB_CMD_GETVBFLAGS:
3945 if(!ivideo->modechanged) {
3946 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3948 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3949 sisfb_command->sisfb_result[1] = ivideo->currentvbflags;
3950 sisfb_command->sisfb_result[2] = ivideo->vbflags2;
3953 case SISFB_CMD_SWITCHCRT1:
3954 /* arg[0]: 0 = off, 1 = on, 99 = query */
3955 if(!ivideo->modechanged) {
3956 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3957 } else if(sisfb_command->sisfb_arg[0] == 99) {
3959 sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3960 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3961 } else if(ivideo->sisfblocked) {
3962 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED;
3963 } else if((!(ivideo->currentvbflags & CRT2_ENABLE)) &&
3964 (sisfb_command->sisfb_arg[0] == 0)) {
3965 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2;
3967 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3968 mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1;
3969 if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) ||
3970 ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) {
3971 ivideo->sisfb_crt1off = mycrt1off;
3972 if(sisfb_reset_mode(ivideo)) {
3973 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER;
3976 sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3981 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN;
3982 printk(KERN_ERR "sisfb: Unknown command 0x%x\n",
3983 sisfb_command->sisfb_cmd);
3988 SISINITSTATIC int __init
3989 sisfb_setup(char *options)
3993 sisfb_setdefaultparms();
3995 if(!options || !(*options))
3998 while((this_opt = strsep(&options, ",")) != NULL) {
4000 if(!(*this_opt)) continue;
4002 if(!strnicmp(this_opt, "off", 3)) {
4004 } else if(!strnicmp(this_opt, "forcecrt2type:", 14)) {
4005 /* Need to check crt2 type first for fstn/dstn */
4006 sisfb_search_crt2type(this_opt + 14);
4007 } else if(!strnicmp(this_opt, "tvmode:",7)) {
4008 sisfb_search_tvstd(this_opt + 7);
4009 } else if(!strnicmp(this_opt, "tvstandard:",11)) {
4010 sisfb_search_tvstd(this_opt + 11);
4011 } else if(!strnicmp(this_opt, "mode:", 5)) {
4012 sisfb_search_mode(this_opt + 5, false);
4013 } else if(!strnicmp(this_opt, "vesa:", 5)) {
4014 sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false);
4015 } else if(!strnicmp(this_opt, "rate:", 5)) {
4016 sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
4017 } else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
4018 sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
4019 } else if(!strnicmp(this_opt, "mem:",4)) {
4020 sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
4021 } else if(!strnicmp(this_opt, "pdc:", 4)) {
4022 sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
4023 } else if(!strnicmp(this_opt, "pdc1:", 5)) {
4024 sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
4025 } else if(!strnicmp(this_opt, "noaccel", 7)) {
4027 } else if(!strnicmp(this_opt, "accel", 5)) {
4029 } else if(!strnicmp(this_opt, "noypan", 6)) {
4031 } else if(!strnicmp(this_opt, "ypan", 4)) {
4033 } else if(!strnicmp(this_opt, "nomax", 5)) {
4035 } else if(!strnicmp(this_opt, "max", 3)) {
4037 } else if(!strnicmp(this_opt, "userom:", 7)) {
4038 sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
4039 } else if(!strnicmp(this_opt, "useoem:", 7)) {
4040 sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
4041 } else if(!strnicmp(this_opt, "nocrt2rate", 10)) {
4042 sisfb_nocrt2rate = 1;
4043 } else if(!strnicmp(this_opt, "scalelcd:", 9)) {
4044 unsigned long temp = 2;
4045 temp = simple_strtoul(this_opt + 9, NULL, 0);
4046 if((temp == 0) || (temp == 1)) {
4047 sisfb_scalelcd = temp ^ 1;
4049 } else if(!strnicmp(this_opt, "tvxposoffset:", 13)) {
4051 temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4052 if((temp >= -32) && (temp <= 32)) {
4053 sisfb_tvxposoffset = temp;
4055 } else if(!strnicmp(this_opt, "tvyposoffset:", 13)) {
4057 temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4058 if((temp >= -32) && (temp <= 32)) {
4059 sisfb_tvyposoffset = temp;
4061 } else if(!strnicmp(this_opt, "specialtiming:", 14)) {
4062 sisfb_search_specialtiming(this_opt + 14);
4063 } else if(!strnicmp(this_opt, "lvdshl:", 7)) {
4065 temp = simple_strtoul(this_opt + 7, NULL, 0);
4066 if((temp >= 0) && (temp <= 3)) {
4067 sisfb_lvdshl = temp;
4069 } else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
4070 sisfb_search_mode(this_opt, true);
4071 #if !defined(__i386__) && !defined(__x86_64__)
4072 } else if(!strnicmp(this_opt, "resetcard", 9)) {
4073 sisfb_resetcard = 1;
4074 } else if(!strnicmp(this_opt, "videoram:", 9)) {
4075 sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
4078 printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
4087 static int __devinit
4088 sisfb_check_rom(SIS_IOTYPE1 *rom_base, struct sis_video_info *ivideo)
4093 if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
4096 romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
4097 if(romptr > (0x10000 - 8))
4100 rom = rom_base + romptr;
4102 if((readb(rom) != 'P') || (readb(rom + 1) != 'C') ||
4103 (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R'))
4106 if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor)
4109 if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id)
4115 static unsigned char * __devinit
4116 sisfb_find_rom(struct pci_dev *pdev)
4118 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4119 SIS_IOTYPE1 *rom_base;
4120 unsigned char *myrombase = NULL;
4122 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
4125 /* First, try the official pci ROM functions (except
4126 * on integrated chipsets which have no ROM).
4129 if(!ivideo->nbridge) {
4131 if((rom_base = pci_map_rom(pdev, &romsize))) {
4133 if(sisfb_check_rom(rom_base, ivideo)) {
4135 if((myrombase = vmalloc(65536))) {
4137 /* Work around bug in pci/rom.c: Folks forgot to check
4138 * whether the size retrieved from the BIOS image eventually
4139 * is larger than the mapped size
4141 if(pci_resource_len(pdev, PCI_ROM_RESOURCE) < romsize)
4142 romsize = pci_resource_len(pdev, PCI_ROM_RESOURCE);
4144 memcpy_fromio(myrombase, rom_base,
4145 (romsize > 65536) ? 65536 : romsize);
4148 pci_unmap_rom(pdev, rom_base);
4152 if(myrombase) return myrombase;
4155 /* Otherwise do it the conventional way. */
4157 #if defined(__i386__) || defined(__x86_64__)
4159 for(temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
4161 rom_base = ioremap(temp, 65536);
4165 if(!sisfb_check_rom(rom_base, ivideo)) {
4170 if((myrombase = vmalloc(65536)))
4171 memcpy_fromio(myrombase, rom_base, 65536);
4180 pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &temp);
4181 pci_write_config_dword(pdev, PCI_ROM_ADDRESS,
4182 (ivideo->video_base & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
4184 rom_base = ioremap(ivideo->video_base, 65536);
4186 if(sisfb_check_rom(rom_base, ivideo)) {
4187 if((myrombase = vmalloc(65536)))
4188 memcpy_fromio(myrombase, rom_base, 65536);
4193 pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp);
4200 static void __devinit
4201 sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize,
4204 ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize));
4206 if(!ivideo->video_vbase) {
4208 "sisfb: Unable to map maximum video RAM for size detection\n");
4210 while((!(ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize))))) {
4212 if((*mapsize) < (min << 20))
4215 if(ivideo->video_vbase) {
4217 "sisfb: Video RAM size detection limited to %dMB\n",
4218 (int)((*mapsize) >> 20));
4223 #ifdef CONFIG_FB_SIS_300
4224 static int __devinit
4225 sisfb_post_300_buswidth(struct sis_video_info *ivideo)
4227 SIS_IOTYPE1 *FBAddress = ivideo->video_vbase;
4228 unsigned short temp;
4232 andSISIDXREG(SISSR, 0x15, 0xFB);
4233 orSISIDXREG(SISSR, 0x15, 0x04);
4234 outSISIDXREG(SISSR, 0x13, 0x00);
4235 outSISIDXREG(SISSR, 0x14, 0xBF);
4237 for(i = 0; i < 2; i++) {
4239 for(j = 0; j < 4; j++) {
4240 writew(temp, FBAddress);
4241 if(readw(FBAddress) == temp)
4243 orSISIDXREG(SISSR, 0x3c, 0x01);
4244 inSISIDXREG(SISSR, 0x05, reg);
4245 inSISIDXREG(SISSR, 0x05, reg);
4246 andSISIDXREG(SISSR, 0x3c, 0xfe);
4247 inSISIDXREG(SISSR, 0x05, reg);
4248 inSISIDXREG(SISSR, 0x05, reg);
4253 writel(0x01234567L, FBAddress);
4254 writel(0x456789ABL, (FBAddress + 4));
4255 writel(0x89ABCDEFL, (FBAddress + 8));
4256 writel(0xCDEF0123L, (FBAddress + 12));
4258 inSISIDXREG(SISSR, 0x3b, reg);
4260 if(readl((FBAddress + 12)) == 0xCDEF0123L)
4261 return 4; /* Channel A 128bit */
4264 if(readl((FBAddress + 4)) == 0x456789ABL)
4265 return 2; /* Channel B 64bit */
4267 return 1; /* 32bit */
4270 static int __devinit
4271 sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth,
4272 int PseudoRankCapacity, int PseudoAdrPinCount,
4273 unsigned int mapsize)
4275 SIS_IOTYPE1 *FBAddr = ivideo->video_vbase;
4276 unsigned short sr14;
4277 unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
4278 unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
4279 static const unsigned short SiS_DRAMType[17][5] = {
4280 {0x0C,0x0A,0x02,0x40,0x39},
4281 {0x0D,0x0A,0x01,0x40,0x48},
4282 {0x0C,0x09,0x02,0x20,0x35},
4283 {0x0D,0x09,0x01,0x20,0x44},
4284 {0x0C,0x08,0x02,0x10,0x31},
4285 {0x0D,0x08,0x01,0x10,0x40},
4286 {0x0C,0x0A,0x01,0x20,0x34},
4287 {0x0C,0x09,0x01,0x08,0x32},
4288 {0x0B,0x08,0x02,0x08,0x21},
4289 {0x0C,0x08,0x01,0x08,0x30},
4290 {0x0A,0x08,0x02,0x04,0x11},
4291 {0x0B,0x0A,0x01,0x10,0x28},
4292 {0x09,0x08,0x02,0x02,0x01},
4293 {0x0B,0x09,0x01,0x08,0x24},
4294 {0x0B,0x08,0x01,0x04,0x20},
4295 {0x0A,0x08,0x01,0x02,0x10},
4296 {0x09,0x08,0x01,0x01,0x00}
4299 for(k = 0; k <= 16; k++) {
4301 RankCapacity = buswidth * SiS_DRAMType[k][3];
4303 if(RankCapacity != PseudoRankCapacity)
4306 if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
4309 BankNumHigh = RankCapacity * 16 * iteration - 1;
4310 if(iteration == 3) { /* Rank No */
4311 BankNumMid = RankCapacity * 16 - 1;
4313 BankNumMid = RankCapacity * 16 * iteration / 2 - 1;
4316 PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
4317 PhysicalAdrHigh = BankNumHigh;
4318 PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
4319 PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
4321 andSISIDXREG(SISSR, 0x15, 0xFB); /* Test */
4322 orSISIDXREG(SISSR, 0x15, 0x04); /* Test */
4323 sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
4324 if(buswidth == 4) sr14 |= 0x80;
4325 else if(buswidth == 2) sr14 |= 0x40;
4326 outSISIDXREG(SISSR, 0x13, SiS_DRAMType[k][4]);
4327 outSISIDXREG(SISSR, 0x14, sr14);
4332 if((BankNumHigh + PhysicalAdrHigh >= mapsize) ||
4333 (BankNumMid + PhysicalAdrHigh >= mapsize) ||
4334 (BankNumHigh + PhysicalAdrHalfPage >= mapsize) ||
4335 (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
4339 writew(((unsigned short)PhysicalAdrHigh),
4340 (FBAddr + BankNumHigh + PhysicalAdrHigh));
4341 writew(((unsigned short)BankNumMid),
4342 (FBAddr + BankNumMid + PhysicalAdrHigh));
4343 writew(((unsigned short)PhysicalAdrHalfPage),
4344 (FBAddr + BankNumHigh + PhysicalAdrHalfPage));
4345 writew(((unsigned short)PhysicalAdrOtherPage),
4346 (FBAddr + BankNumHigh + PhysicalAdrOtherPage));
4349 if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
4356 static void __devinit
4357 sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
4359 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4361 int PseudoRankCapacity, PseudoAdrPinCount;
4363 buswidth = sisfb_post_300_buswidth(ivideo);
4365 for(i = 6; i >= 0; i--) {
4366 PseudoRankCapacity = 1 << i;
4367 for(j = 4; j >= 1; j--) {
4368 PseudoAdrPinCount = 15 - j;
4369 if((PseudoRankCapacity * j) <= 64) {
4370 if(sisfb_post_300_rwtest(ivideo,
4382 static void __devinit
4383 sisfb_post_sis300(struct pci_dev *pdev)
4385 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4386 unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
4387 u8 reg, v1, v2, v3, v4, v5, v6, v7, v8;
4388 u16 index, rindex, memtype = 0;
4389 unsigned int mapsize;
4391 if(!ivideo->SiS_Pr.UseROM)
4394 outSISIDXREG(SISSR, 0x05, 0x86);
4397 if(bios[0x52] & 0x80) {
4398 memtype = bios[0x52];
4400 inSISIDXREG(SISSR, 0x3a, memtype);
4405 v3 = 0x80; v6 = 0x80;
4406 if(ivideo->revision_id <= 0x13) {
4407 v1 = 0x44; v2 = 0x42;
4408 v4 = 0x44; v5 = 0x42;
4410 v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */
4411 v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */
4413 index = memtype * 5;
4414 rindex = index + 0x54;
4415 v1 = bios[rindex++];
4416 v2 = bios[rindex++];
4417 v3 = bios[rindex++];
4418 rindex = index + 0x7c;
4419 v4 = bios[rindex++];
4420 v5 = bios[rindex++];
4421 v6 = bios[rindex++];
4424 outSISIDXREG(SISSR, 0x28, v1);
4425 outSISIDXREG(SISSR, 0x29, v2);
4426 outSISIDXREG(SISSR, 0x2a, v3);
4427 outSISIDXREG(SISSR, 0x2e, v4);
4428 outSISIDXREG(SISSR, 0x2f, v5);
4429 outSISIDXREG(SISSR, 0x30, v6);
4434 outSISIDXREG(SISSR, 0x07, v1); /* DAC speed */
4436 outSISIDXREG(SISSR, 0x11, 0x0f); /* DDC, power save */
4438 v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
4439 v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
4443 v2 = bios[memtype + 8];
4444 v3 = bios[memtype + 16];
4445 v4 = bios[memtype + 24];
4446 v5 = bios[memtype + 32];
4447 v6 = bios[memtype + 40];
4448 v7 = bios[memtype + 48];
4449 v8 = bios[memtype + 56];
4451 if(ivideo->revision_id >= 0x80)
4453 outSISIDXREG(SISSR, 0x15, v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4454 outSISIDXREG(SISSR, 0x16, v2);
4455 outSISIDXREG(SISSR, 0x17, v3);
4456 outSISIDXREG(SISSR, 0x18, v4);
4457 outSISIDXREG(SISSR, 0x19, v5);
4458 outSISIDXREG(SISSR, 0x1a, v6);
4459 outSISIDXREG(SISSR, 0x1b, v7);
4460 outSISIDXREG(SISSR, 0x1c, v8); /* ---- */
4461 andSISIDXREG(SISSR, 0x15 ,0xfb);
4462 orSISIDXREG(SISSR, 0x15, 0x04);
4464 if(bios[0x53] & 0x02) {
4465 orSISIDXREG(SISSR, 0x19, 0x20);
4468 v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */
4469 if(ivideo->revision_id >= 0x80)
4471 outSISIDXREG(SISSR, 0x1f, v1);
4472 outSISIDXREG(SISSR, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
4473 v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
4479 outSISIDXREG(SISSR, 0x23, v1);
4480 outSISIDXREG(SISSR, 0x24, v2);
4481 outSISIDXREG(SISSR, 0x25, v3);
4482 outSISIDXREG(SISSR, 0x21, 0x84);
4483 outSISIDXREG(SISSR, 0x22, 0x00);
4484 outSISIDXREG(SISCR, 0x37, 0x00);
4485 orSISIDXREG(SISPART1, 0x24, 0x01); /* unlock crt2 */
4486 outSISIDXREG(SISPART1, 0x00, 0x00);
4487 v1 = 0x40; v2 = 0x11;
4492 outSISIDXREG(SISPART1, 0x02, v1);
4494 if(ivideo->revision_id >= 0x80)
4497 inSISIDXREG(SISPART4, 0x00, reg);
4498 if((reg == 1) || (reg == 2)) {
4499 outSISIDXREG(SISCR, 0x37, 0x02);
4500 outSISIDXREG(SISPART2, 0x00, 0x1c);
4501 v4 = 0x00; v5 = 0x00; v6 = 0x10;
4502 if(ivideo->SiS_Pr.UseROM) {
4507 outSISIDXREG(SISPART4, 0x0d, v4);
4508 outSISIDXREG(SISPART4, 0x0e, v5);
4509 outSISIDXREG(SISPART4, 0x10, v6);
4510 outSISIDXREG(SISPART4, 0x0f, 0x3f);
4511 inSISIDXREG(SISPART4, 0x01, reg);
4513 inSISIDXREG(SISPART4, 0x23, reg);
4516 outSISIDXREG(SISPART4, 0x23, reg);
4521 outSISIDXREG(SISSR, 0x32, v2);
4523 andSISIDXREG(SISPART1, 0x24, 0xfe); /* Lock CRT2 */
4525 inSISIDXREG(SISSR, 0x16, reg);
4527 outSISIDXREG(SISCR, 0x35, reg);
4528 outSISIDXREG(SISCR, 0x83, 0x00);
4529 #if !defined(__i386__) && !defined(__x86_64__)
4530 if(sisfb_videoram) {
4531 outSISIDXREG(SISSR, 0x13, 0x28); /* ? */
4532 reg = ((sisfb_videoram >> 10) - 1) | 0x40;
4533 outSISIDXREG(SISSR, 0x14, reg);
4536 /* Need to map max FB size for finding out about RAM size */
4538 sisfb_post_map_vram(ivideo, &mapsize, 4);
4540 if(ivideo->video_vbase) {
4541 sisfb_post_300_ramsize(pdev, mapsize);
4542 iounmap(ivideo->video_vbase);
4545 "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4546 outSISIDXREG(SISSR, 0x13, 0x28); /* ? */
4547 outSISIDXREG(SISSR, 0x14, 0x47); /* 8MB, 64bit default */
4549 #if !defined(__i386__) && !defined(__x86_64__)
4556 inSISIDXREG(SISSR, 0x3a, reg);
4557 if((reg & 0x30) == 0x30) {
4558 v1 = 0x04; /* PCI */
4561 v1 = 0x14; /* AGP */
4565 outSISIDXREG(SISSR, 0x21, v1);
4566 outSISIDXREG(SISSR, 0x22, v2);
4569 sisfb_sense_crt1(ivideo);
4571 /* Set default mode, don't clear screen */
4572 ivideo->SiS_Pr.SiS_UseOEM = false;
4573 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
4574 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
4575 ivideo->curFSTN = ivideo->curDSTN = 0;
4576 ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
4577 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
4579 outSISIDXREG(SISSR, 0x05, 0x86);
4582 orSISIDXREG(SISSR, 0x01, 0x20);
4584 /* Save mode number in CR34 */
4585 outSISIDXREG(SISCR, 0x34, 0x2e);
4587 /* Let everyone know what the current mode is */
4588 ivideo->modeprechange = 0x2e;
4592 #ifdef CONFIG_FB_SIS_315
4594 static void __devinit
4595 sisfb_post_sis315330(struct pci_dev *pdev)
4601 static void __devinit
4602 sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
4607 for(i = 0; i <= (delay * 10 * 36); i++) {
4608 inSISIDXREG(SISSR, 0x05, reg);
4613 static int __devinit
4614 sisfb_find_host_bridge(struct sis_video_info *ivideo, struct pci_dev *mypdev,
4615 unsigned short pcivendor)
4617 struct pci_dev *pdev = NULL;
4618 unsigned short temp;
4621 while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) {
4622 temp = pdev->vendor;
4624 if(temp == pcivendor) {
4633 static int __devinit
4634 sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
4635 unsigned int enda, unsigned int mapsize)
4640 writel(0, ivideo->video_vbase);
4642 for(i = starta; i <= enda; i++) {
4645 writel(pos, ivideo->video_vbase + pos);
4648 sisfb_post_xgi_delay(ivideo, 150);
4650 if(readl(ivideo->video_vbase) != 0)
4653 for(i = starta; i <= enda; i++) {
4656 if(readl(ivideo->video_vbase + pos) != pos)
4665 static void __devinit
4666 sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
4668 unsigned int buswidth, ranksize, channelab, mapsize;
4671 static const u8 dramsr13[12 * 5] = {
4672 0x02, 0x0e, 0x0b, 0x80, 0x5d,
4673 0x02, 0x0e, 0x0a, 0x40, 0x59,
4674 0x02, 0x0d, 0x0b, 0x40, 0x4d,
4675 0x02, 0x0e, 0x09, 0x20, 0x55,
4676 0x02, 0x0d, 0x0a, 0x20, 0x49,
4677 0x02, 0x0c, 0x0b, 0x20, 0x3d,
4678 0x02, 0x0e, 0x08, 0x10, 0x51,
4679 0x02, 0x0d, 0x09, 0x10, 0x45,
4680 0x02, 0x0c, 0x0a, 0x10, 0x39,
4681 0x02, 0x0d, 0x08, 0x08, 0x41,
4682 0x02, 0x0c, 0x09, 0x08, 0x35,
4683 0x02, 0x0c, 0x08, 0x04, 0x31
4685 static const u8 dramsr13_4[4 * 5] = {
4686 0x02, 0x0d, 0x09, 0x40, 0x45,
4687 0x02, 0x0c, 0x09, 0x20, 0x35,
4688 0x02, 0x0c, 0x08, 0x10, 0x31,
4689 0x02, 0x0b, 0x08, 0x08, 0x21
4692 /* Enable linear mode, disable 0xa0000 address decoding */
4693 /* We disable a0000 address decoding, because
4694 * - if running on x86, if the card is disabled, it means
4695 * that another card is in the system. We don't want
4696 * to interphere with that primary card's textmode.
4697 * - if running on non-x86, there usually is no VGA window
4700 orSISIDXREG(SISSR, 0x20, (0x80 | 0x04));
4702 /* Need to map max FB size for finding out about RAM size */
4703 mapsize = 256 << 20;
4704 sisfb_post_map_vram(ivideo, &mapsize, 32);
4706 if(!ivideo->video_vbase) {
4707 printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
4708 outSISIDXREG(SISSR, 0x13, 0x35);
4709 outSISIDXREG(SISSR, 0x14, 0x41);
4714 /* Non-interleaving */
4715 outSISIDXREG(SISSR, 0x15, 0x00);
4717 outSISIDXREG(SISSR, 0x1c, 0x00);
4719 if(ivideo->chip == XGI_20) {
4722 inSISIDXREG(SISCR, 0x97, reg);
4723 if(!(reg & 0x01)) { /* Single 32/16 */
4725 outSISIDXREG(SISSR, 0x13, 0xb1);
4726 outSISIDXREG(SISSR, 0x14, 0x52);
4727 sisfb_post_xgi_delay(ivideo, 1);
4729 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4732 outSISIDXREG(SISSR, 0x13, 0x31);
4733 outSISIDXREG(SISSR, 0x14, 0x42);
4734 sisfb_post_xgi_delay(ivideo, 1);
4735 if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
4739 outSISIDXREG(SISSR, 0x13, 0xb1);
4740 outSISIDXREG(SISSR, 0x14, 0x41);
4741 sisfb_post_xgi_delay(ivideo, 1);
4743 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4746 outSISIDXREG(SISSR, 0x13, 0x31);
4747 } else { /* Dual 16/8 */
4749 outSISIDXREG(SISSR, 0x13, 0xb1);
4750 outSISIDXREG(SISSR, 0x14, 0x41);
4751 sisfb_post_xgi_delay(ivideo, 1);
4753 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4756 outSISIDXREG(SISSR, 0x13, 0x31);
4757 outSISIDXREG(SISSR, 0x14, 0x31);
4758 sisfb_post_xgi_delay(ivideo, 1);
4759 if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
4763 outSISIDXREG(SISSR, 0x13, 0xb1);
4764 outSISIDXREG(SISSR, 0x14, 0x30);
4765 sisfb_post_xgi_delay(ivideo, 1);
4767 if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
4770 outSISIDXREG(SISSR, 0x13, 0x31);
4773 } else { /* XGI_40 */
4775 inSISIDXREG(SISCR, 0x97, reg);
4777 inSISIDXREG(SISSR, 0x39, reg);
4781 if(reg & 0x01) { /* DDRII */
4783 if(ivideo->revision_id == 2) {
4785 outSISIDXREG(SISSR, 0x13, 0xa1);
4786 outSISIDXREG(SISSR, 0x14, 0x44);
4788 sisfb_post_xgi_delay(ivideo, 1);
4789 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4792 outSISIDXREG(SISSR, 0x13, 0x21);
4793 outSISIDXREG(SISSR, 0x14, 0x34);
4794 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4798 outSISIDXREG(SISSR, 0x13, 0xa1);
4799 outSISIDXREG(SISSR, 0x14, 0x40);
4801 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4804 outSISIDXREG(SISSR, 0x13, 0x21);
4805 outSISIDXREG(SISSR, 0x14, 0x30);
4808 outSISIDXREG(SISSR, 0x13, 0xa1);
4809 outSISIDXREG(SISSR, 0x14, 0x4c);
4811 sisfb_post_xgi_delay(ivideo, 1);
4812 if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
4816 outSISIDXREG(SISSR, 0x14, 0x48);
4817 sisfb_post_xgi_delay(ivideo, 1);
4819 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4822 outSISIDXREG(SISSR, 0x13, 0x21);
4823 outSISIDXREG(SISSR, 0x14, 0x3c);
4826 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
4830 outSISIDXREG(SISSR, 0x14, 0x38);
4834 sisfb_post_xgi_delay(ivideo, 1);
4839 if(ivideo->revision_id == 2) {
4841 outSISIDXREG(SISSR, 0x13, 0xa1);
4842 outSISIDXREG(SISSR, 0x14, 0x52);
4843 sisfb_post_xgi_delay(ivideo, 1);
4845 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4848 outSISIDXREG(SISSR, 0x13, 0x21);
4849 outSISIDXREG(SISSR, 0x14, 0x42);
4852 outSISIDXREG(SISSR, 0x13, 0xa1);
4853 outSISIDXREG(SISSR, 0x14, 0x5a);
4854 sisfb_post_xgi_delay(ivideo, 1);
4856 if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
4859 outSISIDXREG(SISSR, 0x13, 0x21);
4860 outSISIDXREG(SISSR, 0x14, 0x4a);
4862 sisfb_post_xgi_delay(ivideo, 1);
4868 setSISIDXREG(SISSR, 0x14, 0xf0, sr14);
4869 sisfb_post_xgi_delay(ivideo, 1);
4871 j = (ivideo->chip == XGI_20) ? 5 : 9;
4872 k = (ivideo->chip == XGI_20) ? 12 : 4;
4874 for(i = 0; i < k; i++) {
4876 reg = (ivideo->chip == XGI_20) ?
4877 dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
4878 setSISIDXREG(SISSR, 0x13, 0x80, reg);
4879 sisfb_post_xgi_delay(ivideo, 50);
4881 ranksize = (ivideo->chip == XGI_20) ?
4882 dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
4884 inSISIDXREG(SISSR, 0x13, reg);
4885 if(reg & 0x80) ranksize <<= 1;
4887 if(ivideo->chip == XGI_20) {
4888 if(buswidth == 16) ranksize <<= 1;
4889 else if(buswidth == 32) ranksize <<= 2;
4891 if(buswidth == 64) ranksize <<= 1;
4897 if((ranksize * l) <= 256) {
4898 while((ranksize >>= 1)) reg += 0x10;
4903 setSISIDXREG(SISSR, 0x14, 0x0f, (reg & 0xf0));
4904 sisfb_post_xgi_delay(ivideo, 1);
4906 if(sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize))
4910 iounmap(ivideo->video_vbase);
4913 static void __devinit
4914 sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
4918 static const u8 cs90[8 * 3] = {
4928 static const u8 csb8[8 * 3] = {
4942 v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2];
4943 if(ivideo->haveXGIROM) {
4944 v1 = ivideo->bios_abase[0x90 + index];
4945 v2 = ivideo->bios_abase[0x90 + index + 1];
4946 v3 = ivideo->bios_abase[0x90 + index + 2];
4948 outSISIDXREG(SISSR, 0x28, v1);
4949 outSISIDXREG(SISSR, 0x29, v2);
4950 outSISIDXREG(SISSR, 0x2a, v3);
4951 sisfb_post_xgi_delay(ivideo, 0x43);
4952 sisfb_post_xgi_delay(ivideo, 0x43);
4953 sisfb_post_xgi_delay(ivideo, 0x43);
4955 v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2];
4956 if(ivideo->haveXGIROM) {
4957 v1 = ivideo->bios_abase[0xb8 + index];
4958 v2 = ivideo->bios_abase[0xb8 + index + 1];
4959 v3 = ivideo->bios_abase[0xb8 + index + 2];
4961 outSISIDXREG(SISSR, 0x2e, v1);
4962 outSISIDXREG(SISSR, 0x2f, v2);
4963 outSISIDXREG(SISSR, 0x30, v3);
4964 sisfb_post_xgi_delay(ivideo, 0x43);
4965 sisfb_post_xgi_delay(ivideo, 0x43);
4966 sisfb_post_xgi_delay(ivideo, 0x43);
4969 static int __devinit
4970 sisfb_post_xgi(struct pci_dev *pdev)
4972 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4973 unsigned char *bios = ivideo->bios_abase;
4974 struct pci_dev *mypdev = NULL;
4975 const u8 *ptr, *ptr2;
4976 u8 v1, v2, v3, v4, v5, reg, ramtype;
4977 u32 rega, regb, regd;
4979 static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 };
4980 static const u8 cs76[2] = { 0xa3, 0xfb };
4981 static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 };
4982 static const u8 cs158[8] = {
4983 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
4985 static const u8 cs160[8] = {
4986 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
4988 static const u8 cs168[8] = {
4989 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
4991 static const u8 cs128[3 * 8] = {
4992 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
4993 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
4994 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
4996 static const u8 cs148[2 * 8] = {
4997 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
4998 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5000 static const u8 cs31a[8 * 4] = {
5001 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
5002 0xaa, 0xaa, 0xaa, 0xaa, 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 cs33a[8 * 4] = {
5007 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5008 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5009 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5010 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5012 static const u8 cs45a[8 * 2] = {
5013 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
5014 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5016 static const u8 cs170[7 * 8] = {
5017 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5018 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5019 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
5020 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5021 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5022 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5023 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5025 static const u8 cs1a8[3 * 8] = {
5026 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5027 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5028 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5030 static const u8 cs100[2 * 8] = {
5031 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5032 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5036 reg = inSISREG(SISVGAENABLE) | 0x01;
5037 outSISREG(SISVGAENABLE, reg);
5040 reg = inSISREG(SISMISCR) | 0x01;
5041 outSISREG(SISMISCW, reg);
5044 outSISIDXREG(SISSR, 0x05, 0x86);
5045 inSISIDXREG(SISSR, 0x05, reg);
5049 /* Clear some regs */
5050 for(i = 0; i < 0x22; i++) {
5051 if(0x06 + i == 0x20) continue;
5052 outSISIDXREG(SISSR, 0x06 + i, 0x00);
5054 for(i = 0; i < 0x0b; i++) {
5055 outSISIDXREG(SISSR, 0x31 + i, 0x00);
5057 for(i = 0; i < 0x10; i++) {
5058 outSISIDXREG(SISCR, 0x30 + i, 0x00);
5062 if(ivideo->haveXGIROM) {
5063 ptr = (const u8 *)&bios[0x78];
5065 for(i = 0; i < 3; i++) {
5066 outSISIDXREG(SISSR, 0x23 + i, ptr[i]);
5070 if(ivideo->haveXGIROM) {
5071 ptr = (const u8 *)&bios[0x76];
5073 for(i = 0; i < 2; i++) {
5074 outSISIDXREG(SISSR, 0x21 + i, ptr[i]);
5077 v1 = 0x18; v2 = 0x00;
5078 if(ivideo->haveXGIROM) {
5082 outSISIDXREG(SISSR, 0x07, v1);
5083 outSISIDXREG(SISSR, 0x11, 0x0f);
5084 outSISIDXREG(SISSR, 0x1f, v2);
5085 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5086 outSISIDXREG(SISSR, 0x20, 0x80 | 0x20 | 0x04);
5087 outSISIDXREG(SISSR, 0x27, 0x74);
5090 if(ivideo->haveXGIROM) {
5091 ptr = (const u8 *)&bios[0x7b];
5093 for(i = 0; i < 3; i++) {
5094 outSISIDXREG(SISSR, 0x31 + i, ptr[i]);
5097 if(ivideo->chip == XGI_40) {
5098 if(ivideo->revision_id == 2) {
5099 setSISIDXREG(SISSR, 0x3b, 0x3f, 0xc0);
5101 outSISIDXREG(SISCR, 0x7d, 0xfe);
5102 outSISIDXREG(SISCR, 0x7e, 0x0f);
5104 if(ivideo->revision_id == 0) { /* 40 *and* 20? */
5105 andSISIDXREG(SISCR, 0x58, 0xd7);
5106 inSISIDXREG(SISCR, 0xcb, reg);
5108 setSISIDXREG(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5112 reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
5113 setSISIDXREG(SISCR, 0x38, 0x1f, reg);
5115 if(ivideo->chip == XGI_20) {
5116 outSISIDXREG(SISSR, 0x36, 0x70);
5118 outSISIDXREG(SISVID, 0x00, 0x86);
5119 outSISIDXREG(SISVID, 0x32, 0x00);
5120 outSISIDXREG(SISVID, 0x30, 0x00);
5121 outSISIDXREG(SISVID, 0x32, 0x01);
5122 outSISIDXREG(SISVID, 0x30, 0x00);
5123 andSISIDXREG(SISVID, 0x2f, 0xdf);
5124 andSISIDXREG(SISCAP, 0x00, 0x3f);
5126 outSISIDXREG(SISPART1, 0x2f, 0x01);
5127 outSISIDXREG(SISPART1, 0x00, 0x00);
5128 outSISIDXREG(SISPART1, 0x02, bios[0x7e]);
5129 outSISIDXREG(SISPART1, 0x2e, 0x08);
5130 andSISIDXREG(SISPART1, 0x35, 0x7f);
5131 andSISIDXREG(SISPART1, 0x50, 0xfe);
5133 inSISIDXREG(SISPART4, 0x00, reg);
5134 if(reg == 1 || reg == 2) {
5135 outSISIDXREG(SISPART2, 0x00, 0x1c);
5136 outSISIDXREG(SISPART4, 0x0d, bios[0x7f]);
5137 outSISIDXREG(SISPART4, 0x0e, bios[0x80]);
5138 outSISIDXREG(SISPART4, 0x10, bios[0x81]);
5139 andSISIDXREG(SISPART4, 0x0f, 0x3f);
5141 inSISIDXREG(SISPART4, 0x01, reg);
5142 if((reg & 0xf0) >= 0xb0) {
5143 inSISIDXREG(SISPART4, 0x23, reg);
5144 if(reg & 0x20) reg |= 0x40;
5145 outSISIDXREG(SISPART4, 0x23, reg);
5146 reg = (reg & 0x20) ? 0x02 : 0x00;
5147 setSISIDXREG(SISPART1, 0x1e, 0xfd, reg);
5153 inSISIDXREG(SISSR, 0x3b, reg);
5155 inSISIDXREG(SISSR, 0x3a, reg);
5156 v2 = (reg & 0x30) >> 3;
5157 if(!(v2 & 0x04)) v2 ^= 0x02;
5158 inSISIDXREG(SISSR, 0x39, reg);
5159 if(reg & 0x80) v2 |= 0x80;
5162 if((mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
5163 pci_dev_put(mypdev);
5164 if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
5169 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0735, NULL);
5171 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0645, NULL);
5173 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0650, NULL);
5175 pci_read_config_dword(mypdev, 0x94, ®d);
5177 pci_write_config_dword(mypdev, 0x94, regd);
5179 pci_dev_put(mypdev);
5180 } else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) {
5182 } else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) ||
5183 sisfb_find_host_bridge(ivideo, pdev, 0x1022) ||
5184 sisfb_find_host_bridge(ivideo, pdev, 0x700e) ||
5185 sisfb_find_host_bridge(ivideo, pdev, 0x10de)) {
5186 if((v2 & 0x06) == 4)
5191 setSISIDXREG(SISCR, 0x5f, 0xf0, v2);
5193 outSISIDXREG(SISSR, 0x22, v1);
5195 if(ivideo->revision_id == 2) {
5196 inSISIDXREG(SISSR, 0x3b, v1);
5197 inSISIDXREG(SISSR, 0x3a, v2);
5198 regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
5199 if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
5200 setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01);
5202 if((mypdev = pci_get_device(0x10de, 0x01e0, NULL))) {
5203 /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5207 setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01);
5208 pci_dev_put(mypdev);
5213 inSISIDXREG(SISSR, 0x3b, reg);
5214 inSISIDXREG(SISCR, 0x5f, v2);
5215 if((!(reg & 0x02)) && (v2 & 0x0e))
5217 outSISIDXREG(SISSR, 0x27, v1);
5219 if(bios[0x64] & 0x01) {
5220 setSISIDXREG(SISCR, 0x5f, 0xf0, bios[0x64]);
5224 pci_read_config_dword(pdev, 0x50, ®d);
5225 regd = (regd >> 20) & 0x0f;
5228 orSISIDXREG(SISCR, 0x5f, 0x08);
5230 outSISIDXREG(SISCR, 0x48, v1);
5232 setSISIDXREG(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
5233 setSISIDXREG(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
5234 setSISIDXREG(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
5235 setSISIDXREG(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
5236 setSISIDXREG(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
5237 outSISIDXREG(SISCR, 0x70, bios[0x4fc]);
5238 setSISIDXREG(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
5239 outSISIDXREG(SISCR, 0x74, 0xd0);
5240 setSISIDXREG(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
5241 setSISIDXREG(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
5242 setSISIDXREG(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
5244 if((mypdev = pci_get_device(0x8086, 0x2530, NULL))) {
5246 pci_dev_put(mypdev);
5248 outSISIDXREG(SISCR, 0x77, v1);
5256 if(ivideo->haveXGIROM) {
5257 v1 = bios[0x140 + regb];
5259 outSISIDXREG(SISCR, 0x6d, v1);
5262 if(ivideo->haveXGIROM) {
5263 ptr = (const u8 *)&bios[0x128];
5265 for(i = 0, j = 0; i < 3; i++, j += 8) {
5266 outSISIDXREG(SISCR, 0x68 + i, ptr[j + regb]);
5271 if(ivideo->haveXGIROM) {
5272 index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6;
5273 ptr = (const u8 *)&bios[index];
5274 ptr2 = (const u8 *)&bios[index + 0x20];
5276 for(i = 0; i < 2; i++) {
5278 regd = le32_to_cpu(((u32 *)ptr)[regb]);
5281 regd = le32_to_cpu(((u32 *)ptr2)[regb]);
5285 for(j = 0; j < 16; j++) {
5287 if(regd & 0x01) reg |= 0x04;
5288 if(regd & 0x02) reg |= 0x08;
5290 outSISIDXREG(SISCR, rega, reg);
5291 inSISIDXREG(SISCR, rega, reg);
5292 inSISIDXREG(SISCR, rega, reg);
5297 andSISIDXREG(SISCR, 0x6e, 0xfc);
5300 if(ivideo->haveXGIROM) {
5301 index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6;
5302 ptr = (const u8 *)&bios[index];
5304 for(i = 0; i < 4; i++) {
5305 setSISIDXREG(SISCR, 0x6e, 0xfc, i);
5307 for(j = 0; j < 2; j++) {
5310 regd = le32_to_cpu(((u32 *)ptr)[regb * 8]);
5314 for(k = 0; k < 16; k++) {
5316 if(regd & 0x01) reg |= 0x01;
5317 if(regd & 0x02) reg |= 0x02;
5319 outSISIDXREG(SISCR, 0x6f, reg);
5320 inSISIDXREG(SISCR, 0x6f, reg);
5321 inSISIDXREG(SISCR, 0x6f, reg);
5328 if(ivideo->haveXGIROM) {
5329 ptr = (const u8 *)&bios[0x148];
5331 for(i = 0, j = 0; i < 2; i++, j += 8) {
5332 outSISIDXREG(SISCR, 0x80 + i, ptr[j + regb]);
5335 andSISIDXREG(SISCR, 0x89, 0x8f);
5338 if(ivideo->haveXGIROM) {
5339 index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6;
5340 ptr = (const u8 *)&bios[index];
5342 regd = le16_to_cpu(((const u16 *)ptr)[regb]);
5344 for(i = 0; i < 5; i++) {
5346 if(regd & 0x01) reg |= 0x01;
5347 if(regd & 0x02) reg |= 0x02;
5349 outSISIDXREG(SISCR, 0x89, reg);
5350 inSISIDXREG(SISCR, 0x89, reg);
5351 inSISIDXREG(SISCR, 0x89, reg);
5355 v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13;
5356 if(ivideo->haveXGIROM) {
5357 v1 = bios[0x118 + regb];
5358 v2 = bios[0xf8 + regb];
5359 v3 = bios[0x120 + regb];
5362 outSISIDXREG(SISCR, 0x45, v1 & 0x0f);
5363 outSISIDXREG(SISCR, 0x99, (v1 >> 4) & 0x07);
5364 orSISIDXREG(SISCR, 0x40, v1 & 0x80);
5365 outSISIDXREG(SISCR, 0x41, v2);
5368 if(ivideo->haveXGIROM) {
5369 ptr = (const u8 *)&bios[0x170];
5371 for(i = 0, j = 0; i < 7; i++, j += 8) {
5372 outSISIDXREG(SISCR, 0x90 + i, ptr[j + regb]);
5375 outSISIDXREG(SISCR, 0x59, v3);
5378 if(ivideo->haveXGIROM) {
5379 ptr = (const u8 *)&bios[0x1a8];
5381 for(i = 0, j = 0; i < 3; i++, j += 8) {
5382 outSISIDXREG(SISCR, 0xc3 + i, ptr[j + regb]);
5386 if(ivideo->haveXGIROM) {
5387 ptr = (const u8 *)&bios[0x100];
5389 for(i = 0, j = 0; i < 2; i++, j += 8) {
5390 outSISIDXREG(SISCR, 0x8a + i, ptr[j + regb]);
5393 outSISIDXREG(SISCR, 0xcf, v4);
5395 outSISIDXREG(SISCR, 0x83, 0x09);
5396 outSISIDXREG(SISCR, 0x87, 0x00);
5398 if(ivideo->chip == XGI_40) {
5399 if( (ivideo->revision_id == 1) ||
5400 (ivideo->revision_id == 2) ) {
5401 outSISIDXREG(SISCR, 0x8c, 0x87);
5405 outSISIDXREG(SISSR, 0x17, 0x00);
5406 outSISIDXREG(SISSR, 0x1a, 0x87);
5408 if(ivideo->chip == XGI_20) {
5409 outSISIDXREG(SISSR, 0x15, 0x00);
5410 outSISIDXREG(SISSR, 0x1c, 0x00);
5413 ramtype = 0x00; v1 = 0x10;
5414 if(ivideo->haveXGIROM) {
5415 ramtype = bios[0x62];
5418 if(!(ramtype & 0x80)) {
5419 if(ivideo->chip == XGI_20) {
5420 outSISIDXREG(SISCR, 0x97, v1);
5421 inSISIDXREG(SISCR, 0x97, reg);
5423 ramtype = (reg & 0x01) << 1;
5426 inSISIDXREG(SISSR, 0x39, reg);
5427 ramtype = reg & 0x02;
5429 inSISIDXREG(SISSR, 0x3a, reg);
5430 ramtype = (reg >> 1) & 0x01;
5440 sisfb_post_xgi_setclocks(ivideo, regb);
5441 if((ivideo->chip == XGI_20) ||
5442 (ivideo->revision_id == 1) ||
5443 (ivideo->revision_id == 2)) {
5444 v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb];
5445 if(ivideo->haveXGIROM) {
5446 v1 = bios[regb + 0x158];
5447 v2 = bios[regb + 0x160];
5448 v3 = bios[regb + 0x168];
5450 outSISIDXREG(SISCR, 0x82, v1);
5451 outSISIDXREG(SISCR, 0x85, v2);
5452 outSISIDXREG(SISCR, 0x86, v3);
5454 outSISIDXREG(SISCR, 0x82, 0x88);
5455 outSISIDXREG(SISCR, 0x86, 0x00);
5456 inSISIDXREG(SISCR, 0x86, reg);
5457 outSISIDXREG(SISCR, 0x86, 0x88);
5458 inSISIDXREG(SISCR, 0x86, reg);
5459 outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]);
5460 outSISIDXREG(SISCR, 0x82, 0x77);
5461 outSISIDXREG(SISCR, 0x85, 0x00);
5462 inSISIDXREG(SISCR, 0x85, reg);
5463 outSISIDXREG(SISCR, 0x85, 0x88);
5464 inSISIDXREG(SISCR, 0x85, reg);
5465 outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]);
5466 outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]);
5468 if(ivideo->chip == XGI_40) {
5469 outSISIDXREG(SISCR, 0x97, 0x00);
5471 outSISIDXREG(SISCR, 0x98, 0x01);
5472 outSISIDXREG(SISCR, 0x9a, 0x02);
5474 outSISIDXREG(SISSR, 0x18, 0x01);
5475 if((ivideo->chip == XGI_20) ||
5476 (ivideo->revision_id == 2)) {
5477 outSISIDXREG(SISSR, 0x19, 0x40);
5479 outSISIDXREG(SISSR, 0x19, 0x20);
5481 outSISIDXREG(SISSR, 0x16, 0x00);
5482 outSISIDXREG(SISSR, 0x16, 0x80);
5483 if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
5484 sisfb_post_xgi_delay(ivideo, 0x43);
5485 sisfb_post_xgi_delay(ivideo, 0x43);
5486 sisfb_post_xgi_delay(ivideo, 0x43);
5487 outSISIDXREG(SISSR, 0x18, 0x00);
5488 if((ivideo->chip == XGI_20) ||
5489 (ivideo->revision_id == 2)) {
5490 outSISIDXREG(SISSR, 0x19, 0x40);
5492 outSISIDXREG(SISSR, 0x19, 0x20);
5494 } else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
5495 /* outSISIDXREG(SISSR, 0x16, 0x0c); */ /* ? */
5497 outSISIDXREG(SISSR, 0x16, 0x00);
5498 outSISIDXREG(SISSR, 0x16, 0x80);
5499 sisfb_post_xgi_delay(ivideo, 4);
5500 v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
5501 if(ivideo->haveXGIROM) {
5503 index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e;
5505 v3 = bios[index + 1];
5506 v4 = bios[index + 2];
5507 v5 = bios[index + 3];
5509 outSISIDXREG(SISSR, 0x18, v1);
5510 outSISIDXREG(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
5511 outSISIDXREG(SISSR, 0x16, v2);
5512 outSISIDXREG(SISSR, 0x16, v3);
5513 sisfb_post_xgi_delay(ivideo, 0x43);
5514 outSISIDXREG(SISSR, 0x1b, 0x03);
5515 sisfb_post_xgi_delay(ivideo, 0x22);
5516 outSISIDXREG(SISSR, 0x18, v1);
5517 outSISIDXREG(SISSR, 0x19, 0x00);
5518 outSISIDXREG(SISSR, 0x16, v4);
5519 outSISIDXREG(SISSR, 0x16, v5);
5520 outSISIDXREG(SISSR, 0x1b, 0x00);
5523 outSISIDXREG(SISCR, 0x82, 0x77);
5524 outSISIDXREG(SISCR, 0x86, 0x00);
5525 inSISIDXREG(SISCR, 0x86, reg);
5526 outSISIDXREG(SISCR, 0x86, 0x88);
5527 inSISIDXREG(SISCR, 0x86, reg);
5528 v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
5529 if(ivideo->haveXGIROM) {
5530 v1 = bios[regb + 0x168];
5531 v2 = bios[regb + 0x160];
5532 v3 = bios[regb + 0x158];
5534 outSISIDXREG(SISCR, 0x86, v1);
5535 outSISIDXREG(SISCR, 0x82, 0x77);
5536 outSISIDXREG(SISCR, 0x85, 0x00);
5537 inSISIDXREG(SISCR, 0x85, reg);
5538 outSISIDXREG(SISCR, 0x85, 0x88);
5539 inSISIDXREG(SISCR, 0x85, reg);
5540 outSISIDXREG(SISCR, 0x85, v2);
5541 outSISIDXREG(SISCR, 0x82, v3);
5542 outSISIDXREG(SISCR, 0x98, 0x01);
5543 outSISIDXREG(SISCR, 0x9a, 0x02);
5545 outSISIDXREG(SISSR, 0x28, 0x64);
5546 outSISIDXREG(SISSR, 0x29, 0x63);
5547 sisfb_post_xgi_delay(ivideo, 15);
5548 outSISIDXREG(SISSR, 0x18, 0x00);
5549 outSISIDXREG(SISSR, 0x19, 0x20);
5550 outSISIDXREG(SISSR, 0x16, 0x00);
5551 outSISIDXREG(SISSR, 0x16, 0x80);
5552 outSISIDXREG(SISSR, 0x18, 0xc5);
5553 outSISIDXREG(SISSR, 0x19, 0x23);
5554 outSISIDXREG(SISSR, 0x16, 0x00);
5555 outSISIDXREG(SISSR, 0x16, 0x80);
5556 sisfb_post_xgi_delay(ivideo, 1);
5557 outSISIDXREG(SISCR, 0x97,0x11);
5558 sisfb_post_xgi_setclocks(ivideo, regb);
5559 sisfb_post_xgi_delay(ivideo, 0x46);
5560 outSISIDXREG(SISSR, 0x18, 0xc5);
5561 outSISIDXREG(SISSR, 0x19, 0x23);
5562 outSISIDXREG(SISSR, 0x16, 0x00);
5563 outSISIDXREG(SISSR, 0x16, 0x80);
5564 sisfb_post_xgi_delay(ivideo, 1);
5565 outSISIDXREG(SISSR, 0x1b, 0x04);
5566 sisfb_post_xgi_delay(ivideo, 1);
5567 outSISIDXREG(SISSR, 0x1b, 0x00);
5568 sisfb_post_xgi_delay(ivideo, 1);
5570 if(ivideo->haveXGIROM) {
5573 outSISIDXREG(SISSR, 0x18, v1);
5574 outSISIDXREG(SISSR, 0x19, 0x06);
5575 outSISIDXREG(SISSR, 0x16, 0x04);
5576 outSISIDXREG(SISSR, 0x16, 0x84);
5577 sisfb_post_xgi_delay(ivideo, 1);
5580 sisfb_post_xgi_setclocks(ivideo, regb);
5581 if((ivideo->chip == XGI_40) &&
5582 ((ivideo->revision_id == 1) ||
5583 (ivideo->revision_id == 2))) {
5584 outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]);
5585 outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]);
5586 outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]);
5588 outSISIDXREG(SISCR, 0x82, 0x88);
5589 outSISIDXREG(SISCR, 0x86, 0x00);
5590 inSISIDXREG(SISCR, 0x86, reg);
5591 outSISIDXREG(SISCR, 0x86, 0x88);
5592 outSISIDXREG(SISCR, 0x82, 0x77);
5593 outSISIDXREG(SISCR, 0x85, 0x00);
5594 inSISIDXREG(SISCR, 0x85, reg);
5595 outSISIDXREG(SISCR, 0x85, 0x88);
5596 inSISIDXREG(SISCR, 0x85, reg);
5597 v1 = cs160[regb]; v2 = cs158[regb];
5598 if(ivideo->haveXGIROM) {
5599 v1 = bios[regb + 0x160];
5600 v2 = bios[regb + 0x158];
5602 outSISIDXREG(SISCR, 0x85, v1);
5603 outSISIDXREG(SISCR, 0x82, v2);
5605 if(ivideo->chip == XGI_40) {
5606 outSISIDXREG(SISCR, 0x97, 0x11);
5608 if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
5609 outSISIDXREG(SISCR, 0x98, 0x01);
5611 outSISIDXREG(SISCR, 0x98, 0x03);
5613 outSISIDXREG(SISCR, 0x9a, 0x02);
5615 if(ivideo->chip == XGI_40) {
5616 outSISIDXREG(SISSR, 0x18, 0x01);
5618 outSISIDXREG(SISSR, 0x18, 0x00);
5620 outSISIDXREG(SISSR, 0x19, 0x40);
5621 outSISIDXREG(SISSR, 0x16, 0x00);
5622 outSISIDXREG(SISSR, 0x16, 0x80);
5623 if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
5624 sisfb_post_xgi_delay(ivideo, 0x43);
5625 sisfb_post_xgi_delay(ivideo, 0x43);
5626 sisfb_post_xgi_delay(ivideo, 0x43);
5627 outSISIDXREG(SISSR, 0x18, 0x00);
5628 outSISIDXREG(SISSR, 0x19, 0x40);
5629 outSISIDXREG(SISSR, 0x16, 0x00);
5630 outSISIDXREG(SISSR, 0x16, 0x80);
5632 sisfb_post_xgi_delay(ivideo, 4);
5634 if(ivideo->haveXGIROM) {
5637 outSISIDXREG(SISSR, 0x18, v1);
5638 outSISIDXREG(SISSR, 0x19, 0x01);
5639 if(ivideo->chip == XGI_40) {
5640 outSISIDXREG(SISSR, 0x16, bios[0x53e]);
5641 outSISIDXREG(SISSR, 0x16, bios[0x53f]);
5643 outSISIDXREG(SISSR, 0x16, 0x05);
5644 outSISIDXREG(SISSR, 0x16, 0x85);
5646 sisfb_post_xgi_delay(ivideo, 0x43);
5647 if(ivideo->chip == XGI_40) {
5648 outSISIDXREG(SISSR, 0x1b, 0x01);
5650 outSISIDXREG(SISSR, 0x1b, 0x03);
5652 sisfb_post_xgi_delay(ivideo, 0x22);
5653 outSISIDXREG(SISSR, 0x18, v1);
5654 outSISIDXREG(SISSR, 0x19, 0x00);
5655 if(ivideo->chip == XGI_40) {
5656 outSISIDXREG(SISSR, 0x16, bios[0x540]);
5657 outSISIDXREG(SISSR, 0x16, bios[0x541]);
5659 outSISIDXREG(SISSR, 0x16, 0x05);
5660 outSISIDXREG(SISSR, 0x16, 0x85);
5662 outSISIDXREG(SISSR, 0x1b, 0x00);
5667 if(ivideo->haveXGIROM) {
5668 v1 = bios[0x110 + regb];
5670 outSISIDXREG(SISSR, 0x1b, v1);
5673 v1 = 0x00; v2 = 0x00;
5674 if(ivideo->haveXGIROM) {
5680 if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
5682 outSISIDXREG(SISSR, 0x13, bios[regb + 0xe0]);
5683 outSISIDXREG(SISSR, 0x14, bios[regb + 0xe0 + 8]);
5687 /* Set default mode, don't clear screen */
5688 ivideo->SiS_Pr.SiS_UseOEM = false;
5689 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
5690 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
5691 ivideo->curFSTN = ivideo->curDSTN = 0;
5692 ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
5693 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5695 outSISIDXREG(SISSR, 0x05, 0x86);
5697 /* Disable read-cache */
5698 andSISIDXREG(SISSR, 0x21, 0xdf);
5699 sisfb_post_xgi_ramsize(ivideo);
5700 /* Enable read-cache */
5701 orSISIDXREG(SISSR, 0x21, 0x20);
5706 printk(KERN_DEBUG "-----------------\n");
5707 for(i = 0; i < 0xff; i++) {
5708 inSISIDXREG(SISCR, i, reg);
5709 printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
5711 for(i = 0; i < 0x40; i++) {
5712 inSISIDXREG(SISSR, i, reg);
5713 printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
5715 printk(KERN_DEBUG "-----------------\n");
5719 if(ivideo->chip == XGI_20) {
5720 orSISIDXREG(SISCR, 0x32, 0x20);
5722 inSISIDXREG(SISPART4, 0x00, reg);
5723 if((reg == 1) || (reg == 2)) {
5724 sisfb_sense_crt1(ivideo);
5726 orSISIDXREG(SISCR, 0x32, 0x20);
5730 /* Set default mode, don't clear screen */
5731 ivideo->SiS_Pr.SiS_UseOEM = false;
5732 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
5733 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
5734 ivideo->curFSTN = ivideo->curDSTN = 0;
5735 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5737 outSISIDXREG(SISSR, 0x05, 0x86);
5740 orSISIDXREG(SISSR, 0x01, 0x20);
5742 /* Save mode number in CR34 */
5743 outSISIDXREG(SISCR, 0x34, 0x2e);
5745 /* Let everyone know what the current mode is */
5746 ivideo->modeprechange = 0x2e;
5748 if(ivideo->chip == XGI_40) {
5749 inSISIDXREG(SISCR, 0xca, reg);
5750 inSISIDXREG(SISCR, 0xcc, v1);
5751 if((reg & 0x10) && (!(v1 & 0x04))) {
5753 "sisfb: Please connect power to the card.\n");
5762 static int __devinit
5763 sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
5765 struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data];
5766 struct sis_video_info *ivideo = NULL;
5767 struct fb_info *sis_fb_info = NULL;
5775 sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
5779 ivideo = (struct sis_video_info *)sis_fb_info->par;
5780 ivideo->memyselfandi = sis_fb_info;
5782 ivideo->sisfb_id = SISFB_ID;
5784 if(card_list == NULL) {
5785 ivideo->cardnumber = 0;
5787 struct sis_video_info *countvideo = card_list;
5788 ivideo->cardnumber = 1;
5789 while((countvideo = countvideo->next) != 0)
5790 ivideo->cardnumber++;
5793 strncpy(ivideo->myid, chipinfo->chip_name, 30);
5795 ivideo->warncount = 0;
5796 ivideo->chip_id = pdev->device;
5797 ivideo->chip_vendor = pdev->vendor;
5798 ivideo->revision_id = pdev->revision;
5799 ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
5800 pci_read_config_word(pdev, PCI_COMMAND, ®16);
5801 ivideo->sisvga_enabled = reg16 & 0x01;
5802 ivideo->pcibus = pdev->bus->number;
5803 ivideo->pcislot = PCI_SLOT(pdev->devfn);
5804 ivideo->pcifunc = PCI_FUNC(pdev->devfn);
5805 ivideo->subsysvendor = pdev->subsystem_vendor;
5806 ivideo->subsysdevice = pdev->subsystem_device;
5807 #ifdef SIS_OLD_CONFIG_COMPAT
5808 ivideo->ioctl32registered = 0;
5812 if(sisfb_mode_idx == -1) {
5813 sisfb_get_vga_mode_from_kernel();
5817 ivideo->chip = chipinfo->chip;
5818 ivideo->sisvga_engine = chipinfo->vgaengine;
5819 ivideo->hwcursor_size = chipinfo->hwcursor_size;
5820 ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
5821 ivideo->mni = chipinfo->mni;
5823 ivideo->detectedpdc = 0xff;
5824 ivideo->detectedpdca = 0xff;
5825 ivideo->detectedlcda = 0xff;
5827 ivideo->sisfb_thismonitor.datavalid = false;
5829 ivideo->current_base = 0;
5831 ivideo->engineok = 0;
5833 ivideo->sisfb_was_boot_device = 0;
5834 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))
5835 if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
5836 if(ivideo->sisvga_enabled)
5837 ivideo->sisfb_was_boot_device = 1;
5839 printk(KERN_DEBUG "sisfb: PCI device is disabled, "
5840 "but marked as boot video device ???\n");
5841 printk(KERN_DEBUG "sisfb: I will not accept this "
5842 "as the primary VGA device\n");
5847 ivideo->sisfb_parm_mem = sisfb_parm_mem;
5848 ivideo->sisfb_accel = sisfb_accel;
5849 ivideo->sisfb_ypan = sisfb_ypan;
5850 ivideo->sisfb_max = sisfb_max;
5851 ivideo->sisfb_userom = sisfb_userom;
5852 ivideo->sisfb_useoem = sisfb_useoem;
5853 ivideo->sisfb_mode_idx = sisfb_mode_idx;
5854 ivideo->sisfb_parm_rate = sisfb_parm_rate;
5855 ivideo->sisfb_crt1off = sisfb_crt1off;
5856 ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
5857 ivideo->sisfb_crt2type = sisfb_crt2type;
5858 ivideo->sisfb_crt2flags = sisfb_crt2flags;
5859 /* pdc(a), scalelcd, special timing, lvdshl handled below */
5860 ivideo->sisfb_dstn = sisfb_dstn;
5861 ivideo->sisfb_fstn = sisfb_fstn;
5862 ivideo->sisfb_tvplug = sisfb_tvplug;
5863 ivideo->sisfb_tvstd = sisfb_tvstd;
5864 ivideo->tvxpos = sisfb_tvxposoffset;
5865 ivideo->tvypos = sisfb_tvyposoffset;
5866 ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
5867 ivideo->refresh_rate = 0;
5868 if(ivideo->sisfb_parm_rate != -1) {
5869 ivideo->refresh_rate = ivideo->sisfb_parm_rate;
5872 ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
5873 ivideo->SiS_Pr.CenterScreen = -1;
5874 ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
5875 ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
5877 ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
5878 ivideo->SiS_Pr.SiS_CHOverScan = -1;
5879 ivideo->SiS_Pr.SiS_ChSW = false;
5880 ivideo->SiS_Pr.SiS_UseLCDA = false;
5881 ivideo->SiS_Pr.HaveEMI = false;
5882 ivideo->SiS_Pr.HaveEMILCD = false;
5883 ivideo->SiS_Pr.OverruleEMI = false;
5884 ivideo->SiS_Pr.SiS_SensibleSR11 = false;
5885 ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
5886 ivideo->SiS_Pr.PDC = -1;
5887 ivideo->SiS_Pr.PDCA = -1;
5888 ivideo->SiS_Pr.DDCPortMixup = false;
5889 #ifdef CONFIG_FB_SIS_315
5890 if(ivideo->chip >= SIS_330) {
5891 ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
5892 if(ivideo->chip >= SIS_661) {
5893 ivideo->SiS_Pr.SiS_SensibleSR11 = true;
5898 memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));
5900 pci_set_drvdata(pdev, ivideo);
5902 /* Patch special cases */
5903 if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) {
5904 switch(ivideo->nbridge->device) {
5905 #ifdef CONFIG_FB_SIS_300
5906 case PCI_DEVICE_ID_SI_730:
5907 ivideo->chip = SIS_730;
5908 strcpy(ivideo->myid, "SiS 730");
5911 #ifdef CONFIG_FB_SIS_315
5912 case PCI_DEVICE_ID_SI_651:
5913 /* ivideo->chip is ok */
5914 strcpy(ivideo->myid, "SiS 651");
5916 case PCI_DEVICE_ID_SI_740:
5917 ivideo->chip = SIS_740;
5918 strcpy(ivideo->myid, "SiS 740");
5920 case PCI_DEVICE_ID_SI_661:
5921 ivideo->chip = SIS_661;
5922 strcpy(ivideo->myid, "SiS 661");
5924 case PCI_DEVICE_ID_SI_741:
5925 ivideo->chip = SIS_741;
5926 strcpy(ivideo->myid, "SiS 741");
5928 case PCI_DEVICE_ID_SI_760:
5929 ivideo->chip = SIS_760;
5930 strcpy(ivideo->myid, "SiS 760");
5932 case PCI_DEVICE_ID_SI_761:
5933 ivideo->chip = SIS_761;
5934 strcpy(ivideo->myid, "SiS 761");
5942 ivideo->SiS_Pr.ChipType = ivideo->chip;
5944 ivideo->SiS_Pr.ivideo = (void *)ivideo;
5946 #ifdef CONFIG_FB_SIS_315
5947 if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
5948 (ivideo->SiS_Pr.ChipType == SIS_315)) {
5949 ivideo->SiS_Pr.ChipType = SIS_315H;
5953 if(!ivideo->sisvga_enabled) {
5954 if(pci_enable_device(pdev)) {
5955 if(ivideo->nbridge) pci_dev_put(ivideo->nbridge);
5956 pci_set_drvdata(pdev, NULL);
5962 ivideo->video_base = pci_resource_start(pdev, 0);
5963 ivideo->mmio_base = pci_resource_start(pdev, 1);
5964 ivideo->mmio_size = pci_resource_len(pdev, 1);
5965 ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
5966 ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
5968 SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress);
5970 #ifdef CONFIG_FB_SIS_300
5971 /* Find PCI systems for Chrontel/GPIO communication setup */
5972 if(ivideo->chip == SIS_630) {
5975 if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
5976 mychswtable[i].subsysCard == ivideo->subsysdevice) {
5977 ivideo->SiS_Pr.SiS_ChSW = true;
5978 printk(KERN_DEBUG "sisfb: Identified [%s %s] "
5979 "requiring Chrontel/GPIO setup\n",
5980 mychswtable[i].vendorName,
5981 mychswtable[i].cardName);
5982 ivideo->lpcdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, NULL);
5986 } while(mychswtable[i].subsysVendor != 0);
5990 #ifdef CONFIG_FB_SIS_315
5991 if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
5992 ivideo->lpcdev = pci_get_slot(ivideo->nbridge->bus, (2 << 3));
5996 outSISIDXREG(SISSR, 0x05, 0x86);
5998 if( (!ivideo->sisvga_enabled)
5999 #if !defined(__i386__) && !defined(__x86_64__)
6000 || (sisfb_resetcard)
6003 for(i = 0x30; i <= 0x3f; i++) {
6004 outSISIDXREG(SISCR, i, 0x00);
6008 /* Find out about current video mode */
6009 ivideo->modeprechange = 0x03;
6010 inSISIDXREG(SISCR, 0x34, reg);
6012 ivideo->modeprechange = reg & 0x7f;
6013 } else if(ivideo->sisvga_enabled) {
6014 #if defined(__i386__) || defined(__x86_64__)
6015 unsigned char SIS_IOTYPE2 *tt = ioremap(0x400, 0x100);
6017 ivideo->modeprechange = readb(tt + 0x49);
6023 /* Search and copy ROM image */
6024 ivideo->bios_abase = NULL;
6025 ivideo->SiS_Pr.VirtualRomBase = NULL;
6026 ivideo->SiS_Pr.UseROM = false;
6027 ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = false;
6028 if(ivideo->sisfb_userom) {
6029 ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
6030 ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
6031 ivideo->SiS_Pr.UseROM = (bool)(ivideo->SiS_Pr.VirtualRomBase);
6032 printk(KERN_INFO "sisfb: Video ROM %sfound\n",
6033 ivideo->SiS_Pr.UseROM ? "" : "not ");
6034 if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
6035 ivideo->SiS_Pr.UseROM = false;
6036 ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = true;
6037 if( (ivideo->revision_id == 2) &&
6038 (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
6039 ivideo->SiS_Pr.DDCPortMixup = true;
6043 printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
6046 /* Find systems for special custom timing */
6047 if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
6048 sisfb_detect_custom_timing(ivideo);
6051 /* POST card in case this has not been done by the BIOS */
6052 if( (!ivideo->sisvga_enabled)
6053 #if !defined(__i386__) && !defined(__x86_64__)
6054 || (sisfb_resetcard)
6057 #ifdef CONFIG_FB_SIS_300
6058 if(ivideo->sisvga_engine == SIS_300_VGA) {
6059 if(ivideo->chip == SIS_300) {
6060 sisfb_post_sis300(pdev);
6061 ivideo->sisfb_can_post = 1;
6066 #ifdef CONFIG_FB_SIS_315
6067 if(ivideo->sisvga_engine == SIS_315_VGA) {
6069 /* if((ivideo->chip == SIS_315H) ||
6070 (ivideo->chip == SIS_315) ||
6071 (ivideo->chip == SIS_315PRO) ||
6072 (ivideo->chip == SIS_330)) {
6073 sisfb_post_sis315330(pdev);
6074 } else */ if(ivideo->chip == XGI_20) {
6075 result = sisfb_post_xgi(pdev);
6076 ivideo->sisfb_can_post = 1;
6077 } else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
6078 result = sisfb_post_xgi(pdev);
6079 ivideo->sisfb_can_post = 1;
6081 printk(KERN_INFO "sisfb: Card is not "
6082 "POSTed and sisfb can't do this either.\n");
6085 printk(KERN_ERR "sisfb: Failed to POST card\n");
6093 ivideo->sisfb_card_posted = 1;
6095 /* Find out about RAM size */
6096 if(sisfb_get_dram_size(ivideo)) {
6097 printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
6103 /* Enable PCI addressing and MMIO */
6104 if((ivideo->sisfb_mode_idx < 0) ||
6105 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6106 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
6107 orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
6108 /* Enable 2D accelerator engine */
6109 orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
6112 if(sisfb_pdc != 0xff) {
6113 if(ivideo->sisvga_engine == SIS_300_VGA)
6117 ivideo->SiS_Pr.PDC = sisfb_pdc;
6119 #ifdef CONFIG_FB_SIS_315
6120 if(ivideo->sisvga_engine == SIS_315_VGA) {
6121 if(sisfb_pdca != 0xff)
6122 ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
6126 if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
6127 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6128 (int)(ivideo->video_size >> 20));
6129 printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
6134 if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
6135 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
6140 ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size);
6141 ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
6142 if(!ivideo->video_vbase) {
6143 printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
6148 ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
6149 if(!ivideo->mmio_vbase) {
6150 printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
6152 error_0: iounmap(ivideo->video_vbase);
6153 error_1: release_mem_region(ivideo->video_base, ivideo->video_size);
6154 error_2: release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6155 error_3: vfree(ivideo->bios_abase);
6157 pci_dev_put(ivideo->lpcdev);
6159 pci_dev_put(ivideo->nbridge);
6160 pci_set_drvdata(pdev, NULL);
6161 if(!ivideo->sisvga_enabled)
6162 pci_disable_device(pdev);
6167 printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
6168 ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);
6170 if(ivideo->video_offset) {
6171 printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
6172 ivideo->video_offset / 1024);
6175 printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
6176 ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
6179 /* Determine the size of the command queue */
6180 if(ivideo->sisvga_engine == SIS_300_VGA) {
6181 ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
6183 if(ivideo->chip == XGI_20) {
6184 ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
6186 ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
6190 /* Engines are no longer initialized here; this is
6191 * now done after the first mode-switch (if the
6192 * submitted var has its acceleration flags set).
6195 /* Calculate the base of the (unused) hw cursor */
6196 ivideo->hwcursor_vbase = ivideo->video_vbase
6197 + ivideo->video_size
6198 - ivideo->cmdQueueSize
6199 - ivideo->hwcursor_size;
6200 ivideo->caps |= HW_CURSOR_CAP;
6202 /* Initialize offscreen memory manager */
6203 if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
6204 printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
6207 /* Used for clearing the screen only, therefore respect our mem limit */
6208 ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
6209 ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;
6213 ivideo->vbflags = 0;
6214 ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
6215 ivideo->tvdefmodeidx = DEFAULT_TVMODE;
6216 ivideo->defmodeidx = DEFAULT_MODE;
6219 if(ivideo->chip < XGI_20) {
6220 if(ivideo->bios_abase) {
6221 ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr);
6225 if((ivideo->sisfb_mode_idx < 0) ||
6226 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6228 sisfb_sense_crt1(ivideo);
6230 sisfb_get_VB_type(ivideo);
6232 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6233 sisfb_detect_VB_connect(ivideo);
6236 ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
6238 /* Decide on which CRT2 device to use */
6239 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6240 if(ivideo->sisfb_crt2type != -1) {
6241 if((ivideo->sisfb_crt2type == CRT2_LCD) &&
6242 (ivideo->vbflags & CRT2_LCD)) {
6243 ivideo->currentvbflags |= CRT2_LCD;
6244 } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
6245 ivideo->currentvbflags |= ivideo->sisfb_crt2type;
6248 /* Chrontel 700x TV detection often unreliable, therefore
6249 * use a different default order on such machines
6251 if((ivideo->sisvga_engine == SIS_300_VGA) &&
6252 (ivideo->vbflags2 & VB2_CHRONTEL)) {
6253 if(ivideo->vbflags & CRT2_LCD)
6254 ivideo->currentvbflags |= CRT2_LCD;
6255 else if(ivideo->vbflags & CRT2_TV)
6256 ivideo->currentvbflags |= CRT2_TV;
6257 else if(ivideo->vbflags & CRT2_VGA)
6258 ivideo->currentvbflags |= CRT2_VGA;
6260 if(ivideo->vbflags & CRT2_TV)
6261 ivideo->currentvbflags |= CRT2_TV;
6262 else if(ivideo->vbflags & CRT2_LCD)
6263 ivideo->currentvbflags |= CRT2_LCD;
6264 else if(ivideo->vbflags & CRT2_VGA)
6265 ivideo->currentvbflags |= CRT2_VGA;
6270 if(ivideo->vbflags & CRT2_LCD) {
6271 sisfb_detect_lcd_type(ivideo);
6274 sisfb_save_pdc_emi(ivideo);
6276 if(!ivideo->sisfb_crt1off) {
6277 sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
6279 if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
6280 (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
6281 sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
6285 if(ivideo->sisfb_mode_idx >= 0) {
6286 int bu = ivideo->sisfb_mode_idx;
6287 ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
6288 ivideo->sisfb_mode_idx, ivideo->currentvbflags);
6289 if(bu != ivideo->sisfb_mode_idx) {
6290 printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
6291 sisbios_mode[bu].xres,
6292 sisbios_mode[bu].yres,
6293 sisbios_mode[bu].bpp);
6297 if(ivideo->sisfb_mode_idx < 0) {
6298 switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
6300 ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
6303 ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
6306 ivideo->sisfb_mode_idx = ivideo->defmodeidx;
6311 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
6313 if(ivideo->refresh_rate != 0) {
6314 sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate,
6315 ivideo->sisfb_mode_idx);
6318 if(ivideo->rate_idx == 0) {
6319 ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
6320 ivideo->refresh_rate = 60;
6323 if(ivideo->sisfb_thismonitor.datavalid) {
6324 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor,
6325 ivideo->sisfb_mode_idx,
6327 ivideo->refresh_rate)) {
6328 printk(KERN_INFO "sisfb: WARNING: Refresh rate "
6329 "exceeds monitor specs!\n");
6333 ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
6334 ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
6335 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
6337 sisfb_set_vparms(ivideo);
6339 printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
6340 ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
6341 ivideo->refresh_rate);
6343 /* Set up the default var according to chosen default display mode */
6344 ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
6345 ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
6346 ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
6348 sisfb_bpp_to_var(ivideo, &ivideo->default_var);
6350 ivideo->default_var.pixclock = (u32) (1000000000 /
6351 sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx));
6353 if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no,
6354 ivideo->rate_idx, &ivideo->default_var)) {
6355 if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
6356 ivideo->default_var.pixclock <<= 1;
6360 if(ivideo->sisfb_ypan) {
6361 /* Maximize regardless of sisfb_max at startup */
6362 ivideo->default_var.yres_virtual =
6363 sisfb_calc_maxyres(ivideo, &ivideo->default_var);
6364 if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
6365 ivideo->default_var.yres_virtual = ivideo->default_var.yres;
6369 sisfb_calc_pitch(ivideo, &ivideo->default_var);
6372 if(ivideo->sisfb_accel) {
6374 #ifdef STUPID_ACCELF_TEXT_SHIT
6375 ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
6378 sisfb_initaccel(ivideo);
6380 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
6381 sis_fb_info->flags = FBINFO_DEFAULT |
6382 FBINFO_HWACCEL_YPAN |
6383 FBINFO_HWACCEL_XPAN |
6384 FBINFO_HWACCEL_COPYAREA |
6385 FBINFO_HWACCEL_FILLRECT |
6386 ((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED);
6388 sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
6390 sis_fb_info->var = ivideo->default_var;
6391 sis_fb_info->fix = ivideo->sisfb_fix;
6392 sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
6393 sis_fb_info->fbops = &sisfb_ops;
6394 sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info);
6395 sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
6397 fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
6399 printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
6402 ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size,
6403 MTRR_TYPE_WRCOMB, 1);
6404 if(ivideo->mtrr < 0) {
6405 printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n");
6409 if(register_framebuffer(sis_fb_info) < 0) {
6410 printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
6412 iounmap(ivideo->mmio_vbase);
6416 ivideo->registered = 1;
6419 ivideo->next = card_list;
6422 #ifdef SIS_OLD_CONFIG_COMPAT
6425 /* Our ioctls are all "32/64bit compatible" */
6426 ret = register_ioctl32_conversion(FBIO_ALLOC, NULL);
6427 ret |= register_ioctl32_conversion(FBIO_FREE, NULL);
6428 ret |= register_ioctl32_conversion(FBIOGET_VBLANK, NULL);
6429 ret |= register_ioctl32_conversion(SISFB_GET_INFO_SIZE, NULL);
6430 ret |= register_ioctl32_conversion(SISFB_GET_INFO, NULL);
6431 ret |= register_ioctl32_conversion(SISFB_GET_TVPOSOFFSET, NULL);
6432 ret |= register_ioctl32_conversion(SISFB_SET_TVPOSOFFSET, NULL);
6433 ret |= register_ioctl32_conversion(SISFB_SET_LOCK, NULL);
6434 ret |= register_ioctl32_conversion(SISFB_GET_VBRSTATUS, NULL);
6435 ret |= register_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE, NULL);
6436 ret |= register_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE, NULL);
6437 ret |= register_ioctl32_conversion(SISFB_COMMAND, NULL);
6440 "sisfb: Error registering ioctl32 translations\n");
6442 ivideo->ioctl32registered = 1;
6446 printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
6447 ivideo->sisfb_accel ? "enabled" : "disabled",
6448 ivideo->sisfb_ypan ?
6449 (ivideo->sisfb_max ? "enabled (auto-max)" :
6450 "enabled (no auto-max)") :
6454 printk(KERN_INFO "fb%d: %s frame buffer device version %d.%d.%d\n",
6455 sis_fb_info->node, ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
6457 printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
6459 } /* if mode = "none" */
6464 /*****************************************************/
6465 /* PCI DEVICE HANDLING */
6466 /*****************************************************/
6468 static void __devexit sisfb_remove(struct pci_dev *pdev)
6470 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
6471 struct fb_info *sis_fb_info = ivideo->memyselfandi;
6472 int registered = ivideo->registered;
6473 int modechanged = ivideo->modechanged;
6475 #ifdef SIS_OLD_CONFIG_COMPAT
6476 if(ivideo->ioctl32registered) {
6478 ret = unregister_ioctl32_conversion(FBIO_ALLOC);
6479 ret |= unregister_ioctl32_conversion(FBIO_FREE);
6480 ret |= unregister_ioctl32_conversion(FBIOGET_VBLANK);
6481 ret |= unregister_ioctl32_conversion(SISFB_GET_INFO_SIZE);
6482 ret |= unregister_ioctl32_conversion(SISFB_GET_INFO);
6483 ret |= unregister_ioctl32_conversion(SISFB_GET_TVPOSOFFSET);
6484 ret |= unregister_ioctl32_conversion(SISFB_SET_TVPOSOFFSET);
6485 ret |= unregister_ioctl32_conversion(SISFB_SET_LOCK);
6486 ret |= unregister_ioctl32_conversion(SISFB_GET_VBRSTATUS);
6487 ret |= unregister_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE);
6488 ret |= unregister_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE);
6489 ret |= unregister_ioctl32_conversion(SISFB_COMMAND);
6492 "sisfb: Error unregistering ioctl32 translations\n");
6497 iounmap(ivideo->mmio_vbase);
6498 iounmap(ivideo->video_vbase);
6500 /* Release mem regions */
6501 release_mem_region(ivideo->video_base, ivideo->video_size);
6502 release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6504 vfree(ivideo->bios_abase);
6507 pci_dev_put(ivideo->lpcdev);
6510 pci_dev_put(ivideo->nbridge);
6513 /* Release MTRR region */
6514 if(ivideo->mtrr >= 0)
6515 mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size);
6518 pci_set_drvdata(pdev, NULL);
6520 /* If device was disabled when starting, disable
6523 if(!ivideo->sisvga_enabled)
6524 pci_disable_device(pdev);
6526 /* Unregister the framebuffer */
6527 if(ivideo->registered) {
6528 unregister_framebuffer(sis_fb_info);
6529 framebuffer_release(sis_fb_info);
6532 /* OK, our ivideo is gone for good from here. */
6534 /* TODO: Restore the initial mode
6535 * This sounds easy but is as good as impossible
6536 * on many machines with SiS chip and video bridge
6537 * since text modes are always set up differently
6538 * from machine to machine. Depends on the type
6539 * of integration between chipset and bridge.
6541 if(registered && modechanged)
6543 "sisfb: Restoring of text mode not supported yet\n");
6546 static struct pci_driver sisfb_driver = {
6548 .id_table = sisfb_pci_table,
6549 .probe = sisfb_probe,
6550 .remove = __devexit_p(sisfb_remove)
6553 SISINITSTATIC int __init sisfb_init(void)
6556 char *options = NULL;
6558 if(fb_get_options("sisfb", &options))
6561 sisfb_setup(options);
6563 return pci_register_driver(&sisfb_driver);
6567 module_init(sisfb_init);
6570 /*****************************************************/
6572 /*****************************************************/
6576 static char *mode = NULL;
6577 static int vesa = -1;
6578 static unsigned int rate = 0;
6579 static unsigned int crt1off = 1;
6580 static unsigned int mem = 0;
6581 static char *forcecrt2type = NULL;
6582 static int forcecrt1 = -1;
6583 static int pdc = -1;
6584 static int pdc1 = -1;
6585 static int noaccel = -1;
6586 static int noypan = -1;
6587 static int nomax = -1;
6588 static int userom = -1;
6589 static int useoem = -1;
6590 static char *tvstandard = NULL;
6591 static int nocrt2rate = 0;
6592 static int scalelcd = -1;
6593 static char *specialtiming = NULL;
6594 static int lvdshl = -1;
6595 static int tvxposoffset = 0, tvyposoffset = 0;
6596 #if !defined(__i386__) && !defined(__x86_64__)
6597 static int resetcard = 0;
6598 static int videoram = 0;
6601 static int __init sisfb_init_module(void)
6603 sisfb_setdefaultparms();
6606 sisfb_parm_rate = rate;
6608 if((scalelcd == 0) || (scalelcd == 1))
6609 sisfb_scalelcd = scalelcd ^ 1;
6611 /* Need to check crt2 type first for fstn/dstn */
6614 sisfb_search_crt2type(forcecrt2type);
6617 sisfb_search_tvstd(tvstandard);
6620 sisfb_search_mode(mode, false);
6622 sisfb_search_vesamode(vesa, false);
6624 sisfb_crt1off = (crt1off == 0) ? 1 : 0;
6626 sisfb_forcecrt1 = forcecrt1;
6629 else if(forcecrt1 == 0)
6634 else if(noaccel == 0)
6639 else if(noypan == 0)
6648 sisfb_parm_mem = mem;
6651 sisfb_userom = userom;
6654 sisfb_useoem = useoem;
6657 sisfb_pdc = (pdc & 0x7f);
6660 sisfb_pdca = (pdc1 & 0x1f);
6662 sisfb_nocrt2rate = nocrt2rate;
6665 sisfb_search_specialtiming(specialtiming);
6667 if((lvdshl >= 0) && (lvdshl <= 3))
6668 sisfb_lvdshl = lvdshl;
6670 sisfb_tvxposoffset = tvxposoffset;
6671 sisfb_tvyposoffset = tvyposoffset;
6673 #if !defined(__i386__) && !defined(__x86_64__)
6674 sisfb_resetcard = (resetcard) ? 1 : 0;
6676 sisfb_videoram = videoram;
6679 return sisfb_init();
6682 static void __exit sisfb_remove_module(void)
6684 pci_unregister_driver(&sisfb_driver);
6685 printk(KERN_DEBUG "sisfb: Module unloaded\n");
6688 module_init(sisfb_init_module);
6689 module_exit(sisfb_remove_module);
6691 MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
6692 MODULE_LICENSE("GPL");
6693 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
6695 module_param(mem, int, 0);
6696 module_param(noaccel, int, 0);
6697 module_param(noypan, int, 0);
6698 module_param(nomax, int, 0);
6699 module_param(userom, int, 0);
6700 module_param(useoem, int, 0);
6701 module_param(mode, charp, 0);
6702 module_param(vesa, int, 0);
6703 module_param(rate, int, 0);
6704 module_param(forcecrt1, int, 0);
6705 module_param(forcecrt2type, charp, 0);
6706 module_param(scalelcd, int, 0);
6707 module_param(pdc, int, 0);
6708 module_param(pdc1, int, 0);
6709 module_param(specialtiming, charp, 0);
6710 module_param(lvdshl, int, 0);
6711 module_param(tvstandard, charp, 0);
6712 module_param(tvxposoffset, int, 0);
6713 module_param(tvyposoffset, int, 0);
6714 module_param(nocrt2rate, int, 0);
6715 #if !defined(__i386__) && !defined(__x86_64__)
6716 module_param(resetcard, int, 0);
6717 module_param(videoram, int, 0);
6720 MODULE_PARM_DESC(mem,
6721 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6722 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6723 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6724 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6725 "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6726 "The value is to be specified without 'KB'.\n");
6728 MODULE_PARM_DESC(noaccel,
6729 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
6732 MODULE_PARM_DESC(noypan,
6733 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
6734 "will be performed by redrawing the screen. (default: 0)\n");
6736 MODULE_PARM_DESC(nomax,
6737 "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
6738 "memory for the virtual screen in order to optimize scrolling performance. If\n"
6739 "this is set to anything other than 0, sisfb will not do this and thereby \n"
6740 "enable the user to positively specify a virtual Y size of the screen using\n"
6741 "fbset. (default: 0)\n");
6743 MODULE_PARM_DESC(mode,
6744 "\nSelects the desired default display mode in the format XxYxDepth,\n"
6745 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
6746 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
6747 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
6749 MODULE_PARM_DESC(vesa,
6750 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
6751 "0x117 (default: 0x0103)\n");
6753 MODULE_PARM_DESC(rate,
6754 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
6755 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
6756 "will be ignored (default: 60)\n");
6758 MODULE_PARM_DESC(forcecrt1,
6759 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
6760 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
6761 "0=CRT1 OFF) (default: [autodetected])\n");
6763 MODULE_PARM_DESC(forcecrt2type,
6764 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
6765 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
6766 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
6767 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
6768 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
6769 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
6770 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
6771 "depends on the very hardware in use. (default: [autodetected])\n");
6773 MODULE_PARM_DESC(scalelcd,
6774 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
6775 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
6776 "show black bars around the image, TMDS panels will probably do the scaling\n"
6777 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
6779 MODULE_PARM_DESC(pdc,
6780 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
6781 "should detect this correctly in most cases; however, sometimes this is not\n"
6782 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
6783 "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
6784 "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
6785 "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
6787 #ifdef CONFIG_FB_SIS_315
6788 MODULE_PARM_DESC(pdc1,
6789 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
6790 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
6791 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
6792 "implemented yet.\n");
6795 MODULE_PARM_DESC(specialtiming,
6796 "\nPlease refer to documentation for more information on this option.\n");
6798 MODULE_PARM_DESC(lvdshl,
6799 "\nPlease refer to documentation for more information on this option.\n");
6801 MODULE_PARM_DESC(tvstandard,
6802 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
6803 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
6805 MODULE_PARM_DESC(tvxposoffset,
6806 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
6809 MODULE_PARM_DESC(tvyposoffset,
6810 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
6813 MODULE_PARM_DESC(nocrt2rate,
6814 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
6815 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
6817 #if !defined(__i386__) && !defined(__x86_64__)
6818 #ifdef CONFIG_FB_SIS_300
6819 MODULE_PARM_DESC(resetcard,
6820 "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
6821 "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
6822 "currently). Default: 0\n");
6824 MODULE_PARM_DESC(videoram,
6825 "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
6826 "some non-x86 architectures where the memory auto detection fails. Only\n"
6827 "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
6831 #endif /* /MODULE */
6833 /* _GPL only for new symbols. */
6834 EXPORT_SYMBOL(sis_malloc);
6835 EXPORT_SYMBOL(sis_free);
6836 EXPORT_SYMBOL_GPL(sis_malloc_new);
6837 EXPORT_SYMBOL_GPL(sis_free_new);