2 * SiS 300/540/630[S]/730[S],
3 * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
5 * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
7 * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the named License,
12 * or any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
23 * Author: Thomas Winischhofer <thomas@winischhofer.net>
25 * Author of (practically wiped) code base:
27 * Copyright (C) 1999 Silicon Integrated Systems, Inc.
29 * See http://www.winischhofer.net/ for more information and updates
31 * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver,
32 * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
36 #include <linux/module.h>
37 #include <linux/moduleparam.h>
38 #include <linux/kernel.h>
39 #include <linux/spinlock.h>
40 #include <linux/errno.h>
41 #include <linux/string.h>
43 #include <linux/screen_info.h>
44 #include <linux/slab.h>
46 #include <linux/selection.h>
47 #include <linux/ioport.h>
48 #include <linux/init.h>
49 #include <linux/pci.h>
50 #include <linux/vmalloc.h>
51 #include <linux/capability.h>
53 #include <linux/types.h>
54 #include <linux/uaccess.h>
63 static void sisfb_handle_command(struct sis_video_info *ivideo,
64 struct sisfb_cmd *sisfb_command);
66 /* ------------------ Internal helper routines ----------------- */
69 sisfb_setdefaultparms(void)
87 sisfb_specialtiming = CUT_NONE;
93 sisfb_tvxposoffset = 0;
94 sisfb_tvyposoffset = 0;
96 #if !defined(__i386__) && !defined(__x86_64__)
102 /* ------------- Parameter parsing -------------- */
104 static void __devinit
105 sisfb_search_vesamode(unsigned int vesamode, bool quiet)
109 /* We don't know the hardware specs yet and there is no ivideo */
113 printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
115 sisfb_mode_idx = DEFAULT_MODE;
120 vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
122 while(sisbios_mode[i++].mode_no[0] != 0) {
123 if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
124 (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
126 if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
127 sisbios_mode[i-1].mode_no[1] == 0x56 ||
128 sisbios_mode[i-1].mode_no[1] == 0x53)
131 if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
132 sisbios_mode[i-1].mode_no[1] == 0x5b)
135 sisfb_mode_idx = i - 1;
141 printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
144 static void __devinit
145 sisfb_search_mode(char *name, bool quiet)
147 unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
149 char strbuf[16], strbuf1[20];
150 char *nameptr = name;
152 /* We don't know the hardware specs yet and there is no ivideo */
156 printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
158 sisfb_mode_idx = DEFAULT_MODE;
162 if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
164 printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
166 sisfb_mode_idx = DEFAULT_MODE;
170 if(strlen(name) <= 19) {
171 strcpy(strbuf1, name);
172 for(i = 0; i < strlen(strbuf1); i++) {
173 if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
176 /* This does some fuzzy mode naming detection */
177 if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
178 if((rate <= 32) || (depth > 32)) {
179 j = rate; rate = depth; depth = j;
181 sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
183 sisfb_parm_rate = rate;
184 } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
185 sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
189 if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
190 sprintf(strbuf, "%ux%ux8", xres, yres);
193 sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
200 while(sisbios_mode[i].mode_no[0] != 0) {
201 if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
203 if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
204 sisbios_mode[i-1].mode_no[1] == 0x56 ||
205 sisbios_mode[i-1].mode_no[1] == 0x53)
208 if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
209 sisbios_mode[i-1].mode_no[1] == 0x5b)
212 sisfb_mode_idx = i - 1;
219 printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
223 static void __devinit
224 sisfb_get_vga_mode_from_kernel(void)
228 int mydepth = screen_info.lfb_depth;
230 if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
232 if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) &&
233 (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
234 (mydepth >= 8) && (mydepth <= 32) ) {
236 if(mydepth == 24) mydepth = 32;
238 sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
239 screen_info.lfb_height,
243 "sisfb: Using vga mode %s pre-set by kernel as default\n",
246 sisfb_search_mode(mymode, true);
254 sisfb_search_crt2type(const char *name)
258 /* We don't know the hardware specs yet and there is no ivideo */
260 if(name == NULL) return;
262 while(sis_crt2type[i].type_no != -1) {
263 if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
264 sisfb_crt2type = sis_crt2type[i].type_no;
265 sisfb_tvplug = sis_crt2type[i].tvplug_no;
266 sisfb_crt2flags = sis_crt2type[i].flags;
272 sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
273 sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
275 if(sisfb_crt2type < 0)
276 printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
280 sisfb_search_tvstd(const char *name)
284 /* We don't know the hardware specs yet and there is no ivideo */
289 while(sis_tvtype[i].type_no != -1) {
290 if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
291 sisfb_tvstd = sis_tvtype[i].type_no;
299 sisfb_search_specialtiming(const char *name)
304 /* We don't know the hardware specs yet and there is no ivideo */
309 if(!strnicmp(name, "none", 4)) {
310 sisfb_specialtiming = CUT_FORCENONE;
311 printk(KERN_DEBUG "sisfb: Special timing disabled\n");
313 while(mycustomttable[i].chipID != 0) {
314 if(!strnicmp(name,mycustomttable[i].optionName,
315 strlen(mycustomttable[i].optionName))) {
316 sisfb_specialtiming = mycustomttable[i].SpecialID;
318 printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
319 mycustomttable[i].vendorName,
320 mycustomttable[i].cardName,
321 mycustomttable[i].optionName);
327 printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
328 printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
330 while(mycustomttable[i].chipID != 0) {
331 printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
332 mycustomttable[i].optionName,
333 mycustomttable[i].vendorName,
334 mycustomttable[i].cardName);
341 /* ----------- Various detection routines ----------- */
343 static void __devinit
344 sisfb_detect_custom_timing(struct sis_video_info *ivideo)
346 unsigned char *biosver = NULL;
347 unsigned char *biosdate = NULL;
352 if(ivideo->SiS_Pr.UseROM) {
353 biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06;
354 biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c;
355 for(i = 0; i < 32768; i++)
356 chksum += ivideo->SiS_Pr.VirtualRomBase[i];
361 if( (mycustomttable[i].chipID == ivideo->chip) &&
362 ((!strlen(mycustomttable[i].biosversion)) ||
363 (ivideo->SiS_Pr.UseROM &&
364 (!strncmp(mycustomttable[i].biosversion, biosver,
365 strlen(mycustomttable[i].biosversion))))) &&
366 ((!strlen(mycustomttable[i].biosdate)) ||
367 (ivideo->SiS_Pr.UseROM &&
368 (!strncmp(mycustomttable[i].biosdate, biosdate,
369 strlen(mycustomttable[i].biosdate))))) &&
370 ((!mycustomttable[i].bioschksum) ||
371 (ivideo->SiS_Pr.UseROM &&
372 (mycustomttable[i].bioschksum == chksum))) &&
373 (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
374 (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
376 for(j = 0; j < 5; j++) {
377 if(mycustomttable[i].biosFootprintAddr[j]) {
378 if(ivideo->SiS_Pr.UseROM) {
379 if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
380 mycustomttable[i].biosFootprintData[j]) {
388 ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
389 printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
390 mycustomttable[i].vendorName,
391 mycustomttable[i].cardName);
392 printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
393 mycustomttable[i].optionName);
398 } while(mycustomttable[i].chipID);
401 static bool __devinit
402 sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
404 int i, j, xres, yres, refresh, index;
407 if(buffer[0] != 0x00 || buffer[1] != 0xff ||
408 buffer[2] != 0xff || buffer[3] != 0xff ||
409 buffer[4] != 0xff || buffer[5] != 0xff ||
410 buffer[6] != 0xff || buffer[7] != 0x00) {
411 printk(KERN_DEBUG "sisfb: Bad EDID header\n");
415 if(buffer[0x12] != 0x01) {
416 printk(KERN_INFO "sisfb: EDID version %d not supported\n",
421 monitor->feature = buffer[0x18];
423 if(!(buffer[0x14] & 0x80)) {
424 if(!(buffer[0x14] & 0x08)) {
426 "sisfb: WARNING: Monitor does not support separate syncs\n");
430 if(buffer[0x13] >= 0x01) {
431 /* EDID V1 rev 1 and 2: Search for monitor descriptor
436 if(buffer[j] == 0x00 && buffer[j + 1] == 0x00 &&
437 buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
438 buffer[j + 4] == 0x00) {
439 monitor->hmin = buffer[j + 7];
440 monitor->hmax = buffer[j + 8];
441 monitor->vmin = buffer[j + 5];
442 monitor->vmax = buffer[j + 6];
443 monitor->dclockmax = buffer[j + 9] * 10 * 1000;
444 monitor->datavalid = true;
451 if(!monitor->datavalid) {
452 /* Otherwise: Get a range from the list of supported
453 * Estabished Timings. This is not entirely accurate,
454 * because fixed frequency monitors are not supported
457 monitor->hmin = 65535; monitor->hmax = 0;
458 monitor->vmin = 65535; monitor->vmax = 0;
459 monitor->dclockmax = 0;
460 emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
461 for(i = 0; i < 13; i++) {
462 if(emodes & sisfb_ddcsmodes[i].mask) {
463 if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
464 if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
465 if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
466 if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
467 if(monitor->dclockmax < sisfb_ddcsmodes[i].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
471 for(i = 0; i < 8; i++) {
472 xres = (buffer[index] + 31) * 8;
473 switch(buffer[index + 1] & 0xc0) {
474 case 0xc0: yres = (xres * 9) / 16; break;
475 case 0x80: yres = (xres * 4) / 5; break;
476 case 0x40: yres = (xres * 3) / 4; break;
477 default: yres = xres; break;
479 refresh = (buffer[index + 1] & 0x3f) + 60;
480 if((xres >= 640) && (yres >= 480)) {
481 for(j = 0; j < 8; j++) {
482 if((xres == sisfb_ddcfmodes[j].x) &&
483 (yres == sisfb_ddcfmodes[j].y) &&
484 (refresh == sisfb_ddcfmodes[j].v)) {
485 if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
486 if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
487 if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
488 if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
489 if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d;
495 if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
496 monitor->datavalid = true;
500 return monitor->datavalid;
503 static void __devinit
504 sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, int crtno)
506 unsigned short temp, i, realcrtno = crtno;
507 unsigned char buffer[256];
509 monitor->datavalid = false;
512 if(ivideo->vbflags & CRT2_LCD) realcrtno = 1;
513 else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
517 if((ivideo->sisfb_crt1off) && (!crtno))
520 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
521 realcrtno, 0, &buffer[0], ivideo->vbflags2);
522 if((!temp) || (temp == 0xffff)) {
523 printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
526 printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
527 printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
529 (temp & 0x1a) ? "" : "[none of the supported]",
530 (temp & 0x02) ? "2 " : "",
531 (temp & 0x08) ? "D&P" : "",
532 (temp & 0x10) ? "FPDI-2" : "");
534 i = 3; /* Number of retrys */
536 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
537 realcrtno, 1, &buffer[0], ivideo->vbflags2);
538 } while((temp) && i--);
540 if(sisfb_interpret_edid(monitor, &buffer[0])) {
541 printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
542 monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
543 monitor->dclockmax / 1000);
545 printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
548 printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
551 printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
556 /* -------------- Mode validation --------------- */
559 sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
560 int mode_idx, int rate_idx, int rate)
563 unsigned int dclock, hsync;
565 if(!monitor->datavalid)
571 /* Skip for 320x200, 320x240, 640x400 */
572 switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
583 #ifdef CONFIG_FB_SIS_315
586 if(ivideo->sisvga_engine == SIS_315_VGA) return true;
590 if(rate < (monitor->vmin - 1))
592 if(rate > (monitor->vmax + 1))
595 if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
596 sisbios_mode[mode_idx].mode_no[ivideo->mni],
597 &htotal, &vtotal, rate_idx)) {
598 dclock = (htotal * vtotal * rate) / 1000;
599 if(dclock > (monitor->dclockmax + 1000))
601 hsync = dclock / htotal;
602 if(hsync < (monitor->hmin - 1))
604 if(hsync > (monitor->hmax + 1))
613 sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
615 u16 xres=0, yres, myres;
617 #ifdef CONFIG_FB_SIS_300
618 if(ivideo->sisvga_engine == SIS_300_VGA) {
619 if(!(sisbios_mode[myindex].chipset & MD_SIS300))
623 #ifdef CONFIG_FB_SIS_315
624 if(ivideo->sisvga_engine == SIS_315_VGA) {
625 if(!(sisbios_mode[myindex].chipset & MD_SIS315))
630 myres = sisbios_mode[myindex].yres;
632 switch(vbflags & VB_DISPTYPE_DISP2) {
635 xres = ivideo->lcdxres; yres = ivideo->lcdyres;
637 if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
638 (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
639 if(sisbios_mode[myindex].xres > xres)
645 if(ivideo->sisfb_fstn) {
646 if(sisbios_mode[myindex].xres == 320) {
648 switch(sisbios_mode[myindex].mode_no[1]) {
649 case 0x50: myindex = MODE_FSTN_8; break;
650 case 0x56: myindex = MODE_FSTN_16; break;
651 case 0x53: return -1;
657 if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
658 sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
659 ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
665 if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
666 sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
672 if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
673 sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
683 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
686 u16 xres = sisbios_mode[mode_idx].xres;
687 u16 yres = sisbios_mode[mode_idx].yres;
689 ivideo->rate_idx = 0;
690 while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
691 if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
692 if(sisfb_vrate[i].refresh == rate) {
693 ivideo->rate_idx = sisfb_vrate[i].idx;
695 } else if(sisfb_vrate[i].refresh > rate) {
696 if((sisfb_vrate[i].refresh - rate) <= 3) {
697 DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
698 rate, sisfb_vrate[i].refresh);
699 ivideo->rate_idx = sisfb_vrate[i].idx;
700 ivideo->refresh_rate = sisfb_vrate[i].refresh;
701 } else if(((rate - sisfb_vrate[i-1].refresh) <= 2)
702 && (sisfb_vrate[i].idx != 1)) {
703 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
704 rate, sisfb_vrate[i-1].refresh);
705 ivideo->rate_idx = sisfb_vrate[i-1].idx;
706 ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
709 } else if((rate - sisfb_vrate[i].refresh) <= 2) {
710 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
711 rate, sisfb_vrate[i].refresh);
712 ivideo->rate_idx = sisfb_vrate[i].idx;
718 if(ivideo->rate_idx > 0) {
719 return ivideo->rate_idx;
721 printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n",
728 sisfb_bridgeisslave(struct sis_video_info *ivideo)
732 if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
735 inSISIDXREG(SISPART1,0x00,P1_00);
736 if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
737 ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
745 sisfballowretracecrt1(struct sis_video_info *ivideo)
749 inSISIDXREG(SISCR,0x17,temp);
753 inSISIDXREG(SISSR,0x1f,temp);
761 sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
763 if(!sisfballowretracecrt1(ivideo))
766 if(inSISREG(SISINPSTAT) & 0x08)
773 sisfbwaitretracecrt1(struct sis_video_info *ivideo)
777 if(!sisfballowretracecrt1(ivideo))
781 while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog);
783 while((inSISREG(SISINPSTAT) & 0x08) && --watchdog);
787 sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
789 unsigned char temp, reg;
791 switch(ivideo->sisvga_engine) {
792 case SIS_300_VGA: reg = 0x25; break;
793 case SIS_315_VGA: reg = 0x30; break;
794 default: return false;
797 inSISIDXREG(SISPART1, reg, temp);
805 sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
807 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
808 if(!sisfb_bridgeisslave(ivideo)) {
809 return sisfbcheckvretracecrt2(ivideo);
812 return sisfbcheckvretracecrt1(ivideo);
816 sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
818 u8 idx, reg1, reg2, reg3, reg4;
821 (*vcount) = (*hcount) = 0;
823 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
825 ret |= (FB_VBLANK_HAVE_VSYNC |
826 FB_VBLANK_HAVE_HBLANK |
827 FB_VBLANK_HAVE_VBLANK |
828 FB_VBLANK_HAVE_VCOUNT |
829 FB_VBLANK_HAVE_HCOUNT);
830 switch(ivideo->sisvga_engine) {
831 case SIS_300_VGA: idx = 0x25; break;
833 case SIS_315_VGA: idx = 0x30; break;
835 inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */
836 inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */
837 inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */
838 inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */
839 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
840 if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
841 if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
842 (*vcount) = reg3 | ((reg4 & 0x70) << 4);
843 (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
845 } else if(sisfballowretracecrt1(ivideo)) {
847 ret |= (FB_VBLANK_HAVE_VSYNC |
848 FB_VBLANK_HAVE_VBLANK |
849 FB_VBLANK_HAVE_VCOUNT |
850 FB_VBLANK_HAVE_HCOUNT);
851 reg1 = inSISREG(SISINPSTAT);
852 if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
853 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
854 inSISIDXREG(SISCR,0x20,reg1);
855 inSISIDXREG(SISCR,0x1b,reg1);
856 inSISIDXREG(SISCR,0x1c,reg2);
857 inSISIDXREG(SISCR,0x1d,reg3);
858 (*vcount) = reg2 | ((reg3 & 0x07) << 8);
859 (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
866 sisfb_myblank(struct sis_video_info *ivideo, int blank)
868 u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
869 bool backlight = true;
872 case FB_BLANK_UNBLANK: /* on */
881 case FB_BLANK_NORMAL: /* blank */
890 case FB_BLANK_VSYNC_SUSPEND: /* no vsync */
899 case FB_BLANK_HSYNC_SUSPEND: /* no hsync */
908 case FB_BLANK_POWERDOWN: /* off */
921 if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
923 if( (!ivideo->sisfb_thismonitor.datavalid) ||
924 ((ivideo->sisfb_thismonitor.datavalid) &&
925 (ivideo->sisfb_thismonitor.feature & 0xe0))) {
927 if(ivideo->sisvga_engine == SIS_315_VGA) {
928 setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
931 if(!(sisfb_bridgeisslave(ivideo))) {
932 setSISIDXREG(SISSR, 0x01, ~0x20, sr01);
933 setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f);
939 if(ivideo->currentvbflags & CRT2_LCD) {
941 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
943 SiS_SiS30xBLOn(&ivideo->SiS_Pr);
945 SiS_SiS30xBLOff(&ivideo->SiS_Pr);
947 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
948 #ifdef CONFIG_FB_SIS_315
949 if(ivideo->vbflags2 & VB2_CHRONTEL) {
951 SiS_Chrontel701xBLOn(&ivideo->SiS_Pr);
953 SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
959 if(((ivideo->sisvga_engine == SIS_300_VGA) &&
960 (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
961 ((ivideo->sisvga_engine == SIS_315_VGA) &&
962 ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
963 setSISIDXREG(SISSR, 0x11, ~0x0c, sr11);
966 if(ivideo->sisvga_engine == SIS_300_VGA) {
967 if((ivideo->vbflags2 & VB2_30xB) &&
968 (!(ivideo->vbflags2 & VB2_30xBDH))) {
969 setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13);
971 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
972 if((ivideo->vbflags2 & VB2_30xB) &&
973 (!(ivideo->vbflags2 & VB2_30xBDH))) {
974 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
978 } else if(ivideo->currentvbflags & CRT2_VGA) {
980 if(ivideo->vbflags2 & VB2_30xB) {
981 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
989 /* ------------- Callbacks from init.c/init301.c -------------- */
991 #ifdef CONFIG_FB_SIS_300
993 sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg)
995 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
998 pci_read_config_dword(ivideo->nbridge, reg, &val);
999 return (unsigned int)val;
1003 sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val)
1005 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1007 pci_write_config_dword(ivideo->nbridge, reg, (u32)val);
1011 sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg)
1013 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1016 if(!ivideo->lpcdev) return 0;
1018 pci_read_config_dword(ivideo->lpcdev, reg, &val);
1019 return (unsigned int)val;
1023 #ifdef CONFIG_FB_SIS_315
1025 sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val)
1027 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1029 pci_write_config_byte(ivideo->nbridge, reg, (u8)val);
1033 sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg)
1035 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1038 if(!ivideo->lpcdev) return 0;
1040 pci_read_config_word(ivideo->lpcdev, reg, &val);
1041 return (unsigned int)val;
1045 /* ----------- FBDev related routines for all series ----------- */
1048 sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
1050 return (var->bits_per_pixel == 8) ? 256 : 16;
1054 sisfb_set_vparms(struct sis_video_info *ivideo)
1056 switch(ivideo->video_bpp) {
1058 ivideo->DstColor = 0x0000;
1059 ivideo->SiS310_AccelDepth = 0x00000000;
1060 ivideo->video_cmap_len = 256;
1063 ivideo->DstColor = 0x8000;
1064 ivideo->SiS310_AccelDepth = 0x00010000;
1065 ivideo->video_cmap_len = 16;
1068 ivideo->DstColor = 0xC000;
1069 ivideo->SiS310_AccelDepth = 0x00020000;
1070 ivideo->video_cmap_len = 16;
1073 ivideo->video_cmap_len = 16;
1074 printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
1080 sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1082 int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3));
1084 if(maxyres > 32767) maxyres = 32767;
1090 sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1092 ivideo->video_linelength = var->xres_virtual * (var->bits_per_pixel >> 3);
1093 ivideo->scrnpitchCRT1 = ivideo->video_linelength;
1094 if(!(ivideo->currentvbflags & CRT1_LCDA)) {
1095 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1096 ivideo->scrnpitchCRT1 <<= 1;
1102 sisfb_set_pitch(struct sis_video_info *ivideo)
1104 bool isslavemode = false;
1105 unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
1106 unsigned short HDisplay2 = ivideo->video_linelength >> 3;
1108 if(sisfb_bridgeisslave(ivideo)) isslavemode = true;
1110 /* We need to set pitch for CRT1 if bridge is in slave mode, too */
1111 if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
1112 outSISIDXREG(SISCR,0x13,(HDisplay1 & 0xFF));
1113 setSISIDXREG(SISSR,0x0E,0xF0,(HDisplay1 >> 8));
1116 /* We must not set the pitch for CRT2 if bridge is in slave mode */
1117 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
1118 orSISIDXREG(SISPART1,ivideo->CRT2_write_enable,0x01);
1119 outSISIDXREG(SISPART1,0x07,(HDisplay2 & 0xFF));
1120 setSISIDXREG(SISPART1,0x09,0xF0,(HDisplay2 >> 8));
1125 sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1127 ivideo->video_cmap_len = sisfb_get_cmap_len(var);
1129 switch(var->bits_per_pixel) {
1131 var->red.offset = var->green.offset = var->blue.offset = 0;
1132 var->red.length = var->green.length = var->blue.length = 6;
1135 var->red.offset = 11;
1136 var->red.length = 5;
1137 var->green.offset = 5;
1138 var->green.length = 6;
1139 var->blue.offset = 0;
1140 var->blue.length = 5;
1141 var->transp.offset = 0;
1142 var->transp.length = 0;
1145 var->red.offset = 16;
1146 var->red.length = 8;
1147 var->green.offset = 8;
1148 var->green.length = 8;
1149 var->blue.offset = 0;
1150 var->blue.length = 8;
1151 var->transp.offset = 24;
1152 var->transp.length = 8;
1158 sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
1160 unsigned short modeno = ivideo->mode_no;
1162 /* >=2.6.12's fbcon clears the screen anyway */
1165 outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1167 sisfb_pre_setmode(ivideo);
1169 if(!SiSSetMode(&ivideo->SiS_Pr, modeno)) {
1170 printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
1174 outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1176 sisfb_post_setmode(ivideo);
1183 sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
1185 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1186 unsigned int htotal = 0, vtotal = 0;
1187 unsigned int drate = 0, hrate = 0;
1188 int found_mode = 0, ret;
1192 htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1194 vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1196 pixclock = var->pixclock;
1198 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1199 vtotal += var->yres;
1201 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1202 vtotal += var->yres;
1204 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1205 vtotal += var->yres;
1207 } else vtotal += var->yres;
1209 if(!(htotal) || !(vtotal)) {
1210 DPRINTK("sisfb: Invalid 'var' information\n");
1214 if(pixclock && htotal && vtotal) {
1215 drate = 1000000000 / pixclock;
1216 hrate = (drate * 1000) / htotal;
1217 ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1219 ivideo->refresh_rate = 60;
1222 old_mode = ivideo->sisfb_mode_idx;
1223 ivideo->sisfb_mode_idx = 0;
1225 while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) &&
1226 (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) {
1227 if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) &&
1228 (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) &&
1229 (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) {
1230 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1234 ivideo->sisfb_mode_idx++;
1238 ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
1239 ivideo->sisfb_mode_idx, ivideo->currentvbflags);
1241 ivideo->sisfb_mode_idx = -1;
1244 if(ivideo->sisfb_mode_idx < 0) {
1245 printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres,
1246 var->yres, var->bits_per_pixel);
1247 ivideo->sisfb_mode_idx = old_mode;
1251 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1253 if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
1254 ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
1255 ivideo->refresh_rate = 60;
1259 /* If acceleration to be used? Need to know
1260 * before pre/post_set_mode()
1263 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
1264 #ifdef STUPID_ACCELF_TEXT_SHIT
1265 if(var->accel_flags & FB_ACCELF_TEXT) {
1266 info->flags &= ~FBINFO_HWACCEL_DISABLED;
1268 info->flags |= FBINFO_HWACCEL_DISABLED;
1271 if(!(info->flags & FBINFO_HWACCEL_DISABLED)) ivideo->accel = -1;
1273 if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
1276 if((ret = sisfb_set_mode(ivideo, 1))) {
1280 ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
1281 ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
1282 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
1284 sisfb_calc_pitch(ivideo, var);
1285 sisfb_set_pitch(ivideo);
1287 sisfb_set_vparms(ivideo);
1289 ivideo->current_width = ivideo->video_width;
1290 ivideo->current_height = ivideo->video_height;
1291 ivideo->current_bpp = ivideo->video_bpp;
1292 ivideo->current_htotal = htotal;
1293 ivideo->current_vtotal = vtotal;
1294 ivideo->current_linelength = ivideo->video_linelength;
1295 ivideo->current_pixclock = var->pixclock;
1296 ivideo->current_refresh_rate = ivideo->refresh_rate;
1297 ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
1304 sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
1306 outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1308 outSISIDXREG(SISCR, 0x0D, base & 0xFF);
1309 outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF);
1310 outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF);
1311 if(ivideo->sisvga_engine == SIS_315_VGA) {
1312 setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
1317 sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
1319 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1320 orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
1321 outSISIDXREG(SISPART1, 0x06, (base & 0xFF));
1322 outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF));
1323 outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF));
1324 if(ivideo->sisvga_engine == SIS_315_VGA) {
1325 setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1331 sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1333 if(var->xoffset > (var->xres_virtual - var->xres)) {
1336 if(var->yoffset > (var->yres_virtual - var->yres)) {
1340 ivideo->current_base = (var->yoffset * var->xres_virtual) + var->xoffset;
1342 /* calculate base bpp dep. */
1343 switch(var->bits_per_pixel) {
1347 ivideo->current_base >>= 1;
1351 ivideo->current_base >>= 2;
1355 ivideo->current_base += (ivideo->video_offset >> 2);
1357 sisfb_set_base_CRT1(ivideo, ivideo->current_base);
1358 sisfb_set_base_CRT2(ivideo, ivideo->current_base);
1364 sisfb_open(struct fb_info *info, int user)
1370 sisfb_release(struct fb_info *info, int user)
1376 sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
1377 unsigned transp, struct fb_info *info)
1379 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1381 if(regno >= sisfb_get_cmap_len(&info->var))
1384 switch(info->var.bits_per_pixel) {
1386 outSISREG(SISDACA, regno);
1387 outSISREG(SISDACD, (red >> 10));
1388 outSISREG(SISDACD, (green >> 10));
1389 outSISREG(SISDACD, (blue >> 10));
1390 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1391 outSISREG(SISDAC2A, regno);
1392 outSISREG(SISDAC2D, (red >> 8));
1393 outSISREG(SISDAC2D, (green >> 8));
1394 outSISREG(SISDAC2D, (blue >> 8));
1401 ((u32 *)(info->pseudo_palette))[regno] =
1403 ((green & 0xfc00) >> 5) |
1404 ((blue & 0xf800) >> 11);
1413 ((u32 *)(info->pseudo_palette))[regno] =
1414 (red << 16) | (green << 8) | (blue);
1421 sisfb_set_par(struct fb_info *info)
1425 if((err = sisfb_do_set_var(&info->var, 1, info)))
1428 sisfb_get_fix(&info->fix, -1, info);
1434 sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1436 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1437 unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
1438 unsigned int drate = 0, hrate = 0, maxyres;
1440 int refresh_rate, search_idx, tidx;
1441 bool recalc_clock = false;
1444 htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1446 vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1448 pixclock = var->pixclock;
1450 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1451 vtotal += var->yres;
1453 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1454 vtotal += var->yres;
1456 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1457 vtotal += var->yres;
1460 vtotal += var->yres;
1462 if(!(htotal) || !(vtotal)) {
1463 SISFAIL("sisfb: no valid timing data");
1467 while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
1468 (sisbios_mode[search_idx].xres <= var->xres) ) {
1469 if( (sisbios_mode[search_idx].xres == var->xres) &&
1470 (sisbios_mode[search_idx].yres == var->yres) &&
1471 (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1472 if((tidx = sisfb_validate_mode(ivideo, search_idx,
1473 ivideo->currentvbflags)) > 0) {
1484 while(sisbios_mode[search_idx].mode_no[0] != 0) {
1485 if( (var->xres <= sisbios_mode[search_idx].xres) &&
1486 (var->yres <= sisbios_mode[search_idx].yres) &&
1487 (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
1488 if((tidx = sisfb_validate_mode(ivideo,search_idx,
1489 ivideo->currentvbflags)) > 0) {
1499 "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
1500 var->xres, var->yres, var->bits_per_pixel,
1501 sisbios_mode[search_idx].xres,
1502 sisbios_mode[search_idx].yres,
1503 var->bits_per_pixel);
1504 var->xres = sisbios_mode[search_idx].xres;
1505 var->yres = sisbios_mode[search_idx].yres;
1508 "sisfb: Failed to find supported mode near %dx%dx%d\n",
1509 var->xres, var->yres, var->bits_per_pixel);
1514 if( ((ivideo->vbflags2 & VB2_LVDS) ||
1515 ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
1516 (var->bits_per_pixel == 8) ) {
1517 /* Slave modes on LVDS and 301B-DH */
1519 recalc_clock = true;
1520 } else if( (ivideo->current_htotal == htotal) &&
1521 (ivideo->current_vtotal == vtotal) &&
1522 (ivideo->current_pixclock == pixclock) ) {
1523 /* x=x & y=y & c=c -> assume depth change */
1524 drate = 1000000000 / pixclock;
1525 hrate = (drate * 1000) / htotal;
1526 refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1527 } else if( ( (ivideo->current_htotal != htotal) ||
1528 (ivideo->current_vtotal != vtotal) ) &&
1529 (ivideo->current_pixclock == var->pixclock) ) {
1530 /* x!=x | y!=y & c=c -> invalid pixclock */
1531 if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
1533 ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
1534 } else if(ivideo->sisfb_parm_rate != -1) {
1535 /* Sic, sisfb_parm_rate - want to know originally desired rate here */
1536 refresh_rate = ivideo->sisfb_parm_rate;
1540 recalc_clock = true;
1541 } else if((pixclock) && (htotal) && (vtotal)) {
1542 drate = 1000000000 / pixclock;
1543 hrate = (drate * 1000) / htotal;
1544 refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1545 } else if(ivideo->current_refresh_rate) {
1546 refresh_rate = ivideo->current_refresh_rate;
1547 recalc_clock = true;
1550 recalc_clock = true;
1553 myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
1555 /* Eventually recalculate timing and clock */
1557 if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
1558 var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
1559 sisbios_mode[search_idx].mode_no[ivideo->mni],
1561 sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr,
1562 sisbios_mode[search_idx].mode_no[ivideo->mni],
1564 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1565 var->pixclock <<= 1;
1569 if(ivideo->sisfb_thismonitor.datavalid) {
1570 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
1571 myrateindex, refresh_rate)) {
1573 "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1577 /* Adapt RGB settings */
1578 sisfb_bpp_to_var(ivideo, var);
1580 /* Sanity check for offsets */
1581 if(var->xoffset < 0) var->xoffset = 0;
1582 if(var->yoffset < 0) var->yoffset = 0;
1584 if(var->xres > var->xres_virtual)
1585 var->xres_virtual = var->xres;
1587 if(ivideo->sisfb_ypan) {
1588 maxyres = sisfb_calc_maxyres(ivideo, var);
1589 if(ivideo->sisfb_max) {
1590 var->yres_virtual = maxyres;
1592 if(var->yres_virtual > maxyres) {
1593 var->yres_virtual = maxyres;
1596 if(var->yres_virtual <= var->yres) {
1597 var->yres_virtual = var->yres;
1600 if(var->yres != var->yres_virtual) {
1601 var->yres_virtual = var->yres;
1607 /* Truncate offsets to maximum if too high */
1608 if(var->xoffset > var->xres_virtual - var->xres) {
1609 var->xoffset = var->xres_virtual - var->xres - 1;
1612 if(var->yoffset > var->yres_virtual - var->yres) {
1613 var->yoffset = var->yres_virtual - var->yres - 1;
1616 /* Set everything else to 0 */
1617 var->red.msb_right =
1618 var->green.msb_right =
1619 var->blue.msb_right =
1620 var->transp.offset =
1621 var->transp.length =
1622 var->transp.msb_right = 0;
1628 sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
1630 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1633 if(var->xoffset > (var->xres_virtual - var->xres))
1636 if(var->yoffset > (var->yres_virtual - var->yres))
1639 if(var->vmode & FB_VMODE_YWRAP)
1642 if(var->xoffset + info->var.xres > info->var.xres_virtual ||
1643 var->yoffset + info->var.yres > info->var.yres_virtual)
1646 if((err = sisfb_pan_var(ivideo, var)) < 0)
1649 info->var.xoffset = var->xoffset;
1650 info->var.yoffset = var->yoffset;
1656 sisfb_blank(int blank, struct fb_info *info)
1658 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1660 return sisfb_myblank(ivideo, blank);
1663 /* ----------- FBDev related routines for all series ---------- */
1665 static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
1668 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1669 struct sis_memreq sismemreq;
1670 struct fb_vblank sisvbblank;
1675 u32 __user *argp = (u32 __user *)arg;
1679 if(!capable(CAP_SYS_RAWIO))
1682 if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))
1685 sis_malloc(&sismemreq);
1687 if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
1688 sis_free((u32)sismemreq.offset);
1694 if(!capable(CAP_SYS_RAWIO))
1697 if(get_user(gpu32, argp))
1703 case FBIOGET_VBLANK:
1704 sisvbblank.count = 0;
1705 sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
1707 if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))
1712 case SISFB_GET_INFO_SIZE:
1713 return put_user(sizeof(struct sisfb_info), argp);
1715 case SISFB_GET_INFO_OLD:
1716 if(ivideo->warncount++ < 10)
1718 "sisfb: Deprecated ioctl call received - update your application!\n");
1719 case SISFB_GET_INFO: /* For communication with X driver */
1720 ivideo->sisfb_infoblock.sisfb_id = SISFB_ID;
1721 ivideo->sisfb_infoblock.sisfb_version = VER_MAJOR;
1722 ivideo->sisfb_infoblock.sisfb_revision = VER_MINOR;
1723 ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;
1724 ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;
1725 ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;
1726 ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;
1727 ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;
1728 if(ivideo->modechanged) {
1729 ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;
1731 ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;
1733 ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;
1734 ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;
1735 ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;
1736 ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;
1737 ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;
1738 ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;
1739 ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;
1740 ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;
1741 ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;
1742 ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;
1743 ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
1744 ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
1745 ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
1746 ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
1747 ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
1748 ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
1749 ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
1750 ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
1751 ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
1752 ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
1753 ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;
1754 ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;
1755 ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;
1756 ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;
1757 ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;
1758 ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;
1759 ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;
1760 ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;
1762 if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,
1763 sizeof(ivideo->sisfb_infoblock)))
1768 case SISFB_GET_VBRSTATUS_OLD:
1769 if(ivideo->warncount++ < 10)
1771 "sisfb: Deprecated ioctl call received - update your application!\n");
1772 case SISFB_GET_VBRSTATUS:
1773 if(sisfb_CheckVBRetrace(ivideo))
1774 return put_user((u32)1, argp);
1776 return put_user((u32)0, argp);
1778 case SISFB_GET_AUTOMAXIMIZE_OLD:
1779 if(ivideo->warncount++ < 10)
1781 "sisfb: Deprecated ioctl call received - update your application!\n");
1782 case SISFB_GET_AUTOMAXIMIZE:
1783 if(ivideo->sisfb_max)
1784 return put_user((u32)1, argp);
1786 return put_user((u32)0, argp);
1788 case SISFB_SET_AUTOMAXIMIZE_OLD:
1789 if(ivideo->warncount++ < 10)
1791 "sisfb: Deprecated ioctl call received - update your application!\n");
1792 case SISFB_SET_AUTOMAXIMIZE:
1793 if(get_user(gpu32, argp))
1796 ivideo->sisfb_max = (gpu32) ? 1 : 0;
1799 case SISFB_SET_TVPOSOFFSET:
1800 if(get_user(gpu32, argp))
1803 sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
1804 sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
1807 case SISFB_GET_TVPOSOFFSET:
1808 return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
1812 if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,
1813 sizeof(struct sisfb_cmd)))
1816 sisfb_handle_command(ivideo, &ivideo->sisfb_command);
1818 if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,
1819 sizeof(struct sisfb_cmd)))
1824 case SISFB_SET_LOCK:
1825 if(get_user(gpu32, argp))
1828 ivideo->sisfblocked = (gpu32) ? 1 : 0;
1832 #ifdef SIS_NEW_CONFIG_COMPAT
1833 return -ENOIOCTLCMD;
1842 sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
1844 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1846 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1848 strcpy(fix->id, ivideo->myid);
1850 fix->smem_start = ivideo->video_base + ivideo->video_offset;
1851 fix->smem_len = ivideo->sisfb_mem;
1852 fix->type = FB_TYPE_PACKED_PIXELS;
1854 fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
1856 fix->ypanstep = (ivideo->sisfb_ypan) ? 1 : 0;
1858 fix->line_length = ivideo->video_linelength;
1859 fix->mmio_start = ivideo->mmio_base;
1860 fix->mmio_len = ivideo->mmio_size;
1861 if(ivideo->sisvga_engine == SIS_300_VGA) {
1862 fix->accel = FB_ACCEL_SIS_GLAMOUR;
1863 } else if((ivideo->chip == SIS_330) ||
1864 (ivideo->chip == SIS_760) ||
1865 (ivideo->chip == SIS_761)) {
1866 fix->accel = FB_ACCEL_SIS_XABRE;
1867 } else if(ivideo->chip == XGI_20) {
1868 fix->accel = FB_ACCEL_XGI_VOLARI_Z;
1869 } else if(ivideo->chip >= XGI_40) {
1870 fix->accel = FB_ACCEL_XGI_VOLARI_V;
1872 fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
1878 /* ---------------- fb_ops structures ----------------- */
1880 static struct fb_ops sisfb_ops = {
1881 .owner = THIS_MODULE,
1882 .fb_open = sisfb_open,
1883 .fb_release = sisfb_release,
1884 .fb_check_var = sisfb_check_var,
1885 .fb_set_par = sisfb_set_par,
1886 .fb_setcolreg = sisfb_setcolreg,
1887 .fb_pan_display = sisfb_pan_display,
1888 .fb_blank = sisfb_blank,
1889 .fb_fillrect = fbcon_sis_fillrect,
1890 .fb_copyarea = fbcon_sis_copyarea,
1891 .fb_imageblit = cfb_imageblit,
1892 #ifdef CONFIG_FB_SOFT_CURSOR
1893 .fb_cursor = soft_cursor,
1895 .fb_sync = fbcon_sis_sync,
1896 #ifdef SIS_NEW_CONFIG_COMPAT
1897 .fb_compat_ioctl= sisfb_ioctl,
1899 .fb_ioctl = sisfb_ioctl
1902 /* ---------------- Chip generation dependent routines ---------------- */
1904 static struct pci_dev * __devinit
1905 sisfb_get_northbridge(int basechipid)
1907 struct pci_dev *pdev = NULL;
1908 int nbridgenum, nbridgeidx, i;
1909 static const unsigned short nbridgeids[] = {
1910 PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */
1911 PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */
1912 PCI_DEVICE_ID_SI_730,
1913 PCI_DEVICE_ID_SI_550, /* for SiS 550 VGA */
1914 PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */
1915 PCI_DEVICE_ID_SI_651,
1916 PCI_DEVICE_ID_SI_740,
1917 PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760/761 VGA */
1918 PCI_DEVICE_ID_SI_741,
1919 PCI_DEVICE_ID_SI_660,
1920 PCI_DEVICE_ID_SI_760,
1921 PCI_DEVICE_ID_SI_761
1924 switch(basechipid) {
1925 #ifdef CONFIG_FB_SIS_300
1926 case SIS_540: nbridgeidx = 0; nbridgenum = 1; break;
1927 case SIS_630: nbridgeidx = 1; nbridgenum = 2; break;
1929 #ifdef CONFIG_FB_SIS_315
1930 case SIS_550: nbridgeidx = 3; nbridgenum = 1; break;
1931 case SIS_650: nbridgeidx = 4; nbridgenum = 3; break;
1932 case SIS_660: nbridgeidx = 7; nbridgenum = 5; break;
1934 default: return NULL;
1936 for(i = 0; i < nbridgenum; i++) {
1937 if((pdev = pci_get_device(PCI_VENDOR_ID_SI,
1938 nbridgeids[nbridgeidx+i], NULL)))
1944 static int __devinit
1945 sisfb_get_dram_size(struct sis_video_info *ivideo)
1947 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1951 ivideo->video_size = 0;
1952 ivideo->UMAsize = ivideo->LFBsize = 0;
1954 switch(ivideo->chip) {
1955 #ifdef CONFIG_FB_SIS_300
1957 inSISIDXREG(SISSR, 0x14, reg);
1958 ivideo->video_size = ((reg & 0x3F) + 1) << 20;
1963 if(!ivideo->nbridge)
1965 pci_read_config_byte(ivideo->nbridge, 0x63, ®);
1966 ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
1969 #ifdef CONFIG_FB_SIS_315
1973 inSISIDXREG(SISSR, 0x14, reg);
1974 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
1975 switch((reg >> 2) & 0x03) {
1978 ivideo->video_size <<= 1;
1981 ivideo->video_size += (ivideo->video_size/2);
1985 inSISIDXREG(SISSR, 0x14, reg);
1986 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
1987 if(reg & 0x0c) ivideo->video_size <<= 1;
1992 inSISIDXREG(SISSR, 0x14, reg);
1993 ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
1997 inSISIDXREG(SISCR, 0x79, reg);
1998 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2003 inSISIDXREG(SISCR, 0x79, reg);
2004 reg = (reg & 0xf0) >> 4;
2006 ivideo->video_size = (1 << reg) << 20;
2007 ivideo->UMAsize = ivideo->video_size;
2009 inSISIDXREG(SISCR, 0x78, reg);
2013 ivideo->LFBsize = (32 << 20);
2015 ivideo->LFBsize = (64 << 20);
2017 ivideo->video_size += ivideo->LFBsize;
2023 inSISIDXREG(SISSR, 0x14, reg);
2024 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2025 if(ivideo->chip != XGI_20) {
2026 reg = (reg & 0x0c) >> 2;
2027 if(ivideo->revision_id == 2) {
2028 if(reg & 0x01) reg = 0x02;
2031 if(reg == 0x02) ivideo->video_size <<= 1;
2032 else if(reg == 0x03) ivideo->video_size <<= 2;
2042 /* -------------- video bridge device detection --------------- */
2044 static void __devinit
2045 sisfb_detect_VB_connect(struct sis_video_info *ivideo)
2049 /* No CRT2 on XGI Z7 */
2050 if(ivideo->chip == XGI_20) {
2051 ivideo->sisfb_crt1off = 0;
2055 #ifdef CONFIG_FB_SIS_300
2056 if(ivideo->sisvga_engine == SIS_300_VGA) {
2057 inSISIDXREG(SISSR, 0x17, temp);
2058 if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
2059 /* PAL/NTSC is stored on SR16 on such machines */
2060 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
2061 inSISIDXREG(SISSR, 0x16, temp);
2063 ivideo->vbflags |= TV_PAL;
2065 ivideo->vbflags |= TV_NTSC;
2071 inSISIDXREG(SISCR, 0x32, cr32);
2073 if(cr32 & SIS_CRT1) {
2074 ivideo->sisfb_crt1off = 0;
2076 ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0;
2079 ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
2081 if(cr32 & SIS_VB_TV) ivideo->vbflags |= CRT2_TV;
2082 if(cr32 & SIS_VB_LCD) ivideo->vbflags |= CRT2_LCD;
2083 if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA;
2085 /* Check given parms for hardware compatibility.
2086 * (Cannot do this in the search_xx routines since we don't
2087 * know what hardware we are running on then)
2090 if(ivideo->chip != SIS_550) {
2091 ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0;
2094 if(ivideo->sisfb_tvplug != -1) {
2095 if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2096 (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) {
2097 if(ivideo->sisfb_tvplug & TV_YPBPR) {
2098 ivideo->sisfb_tvplug = -1;
2099 printk(KERN_ERR "sisfb: YPbPr not supported\n");
2103 if(ivideo->sisfb_tvplug != -1) {
2104 if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2105 (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) {
2106 if(ivideo->sisfb_tvplug & TV_HIVISION) {
2107 ivideo->sisfb_tvplug = -1;
2108 printk(KERN_ERR "sisfb: HiVision not supported\n");
2112 if(ivideo->sisfb_tvstd != -1) {
2113 if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
2114 (!((ivideo->sisvga_engine == SIS_315_VGA) &&
2115 (ivideo->vbflags2 & VB2_CHRONTEL))) ) {
2116 if(ivideo->sisfb_tvstd & (TV_PALN | TV_PALN | TV_NTSCJ)) {
2117 ivideo->sisfb_tvstd = -1;
2118 printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
2123 /* Detect/set TV plug & type */
2124 if(ivideo->sisfb_tvplug != -1) {
2125 ivideo->vbflags |= ivideo->sisfb_tvplug;
2127 if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
2128 else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION;
2129 else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART;
2131 if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO;
2132 if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
2136 if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) {
2137 if(ivideo->sisfb_tvstd != -1) {
2138 ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ);
2139 ivideo->vbflags |= ivideo->sisfb_tvstd;
2141 if(ivideo->vbflags & TV_SCART) {
2142 ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ);
2143 ivideo->vbflags |= TV_PAL;
2145 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
2146 if(ivideo->sisvga_engine == SIS_300_VGA) {
2147 inSISIDXREG(SISSR, 0x38, temp);
2148 if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2149 else ivideo->vbflags |= TV_NTSC;
2150 } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
2151 inSISIDXREG(SISSR, 0x38, temp);
2152 if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2153 else ivideo->vbflags |= TV_NTSC;
2155 inSISIDXREG(SISCR, 0x79, temp);
2156 if(temp & 0x20) ivideo->vbflags |= TV_PAL;
2157 else ivideo->vbflags |= TV_NTSC;
2162 /* Copy forceCRT1 option to CRT1off if option is given */
2163 if(ivideo->sisfb_forcecrt1 != -1) {
2164 ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
2168 /* ------------------ Sensing routines ------------------ */
2170 static bool __devinit
2171 sisfb_test_DDC1(struct sis_video_info *ivideo)
2176 old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
2178 if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
2180 return (count != -1);
2183 static void __devinit
2184 sisfb_sense_crt1(struct sis_video_info *ivideo)
2186 bool mustwait = false;
2188 #ifdef CONFIG_FB_SIS_315
2194 inSISIDXREG(SISSR,0x1F,sr1F);
2195 orSISIDXREG(SISSR,0x1F,0x04);
2196 andSISIDXREG(SISSR,0x1F,0x3F);
2197 if(sr1F & 0xc0) mustwait = true;
2199 #ifdef CONFIG_FB_SIS_315
2200 if(ivideo->sisvga_engine == SIS_315_VGA) {
2201 inSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,cr63);
2203 andSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF);
2207 inSISIDXREG(SISCR,0x17,cr17);
2210 orSISIDXREG(SISCR,0x17,0x80);
2212 outSISIDXREG(SISSR, 0x00, 0x01);
2213 outSISIDXREG(SISSR, 0x00, 0x03);
2217 for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo);
2220 #ifdef CONFIG_FB_SIS_315
2221 if(ivideo->chip >= SIS_330) {
2222 andSISIDXREG(SISCR,0x32,~0x20);
2223 if(ivideo->chip >= SIS_340) {
2224 outSISIDXREG(SISCR, 0x57, 0x4a);
2226 outSISIDXREG(SISCR, 0x57, 0x5f);
2228 orSISIDXREG(SISCR, 0x53, 0x02);
2229 while((inSISREG(SISINPSTAT)) & 0x01) break;
2230 while(!((inSISREG(SISINPSTAT)) & 0x01)) break;
2231 if((inSISREG(SISMISCW)) & 0x10) temp = 1;
2232 andSISIDXREG(SISCR, 0x53, 0xfd);
2233 andSISIDXREG(SISCR, 0x57, 0x00);
2237 if(temp == 0xffff) {
2240 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2241 ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
2242 } while(((temp == 0) || (temp == 0xffff)) && i--);
2244 if((temp == 0) || (temp == 0xffff)) {
2245 if(sisfb_test_DDC1(ivideo)) temp = 1;
2249 if((temp) && (temp != 0xffff)) {
2250 orSISIDXREG(SISCR,0x32,0x20);
2253 #ifdef CONFIG_FB_SIS_315
2254 if(ivideo->sisvga_engine == SIS_315_VGA) {
2255 setSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF,cr63);
2259 setSISIDXREG(SISCR,0x17,0x7F,cr17);
2261 outSISIDXREG(SISSR,0x1F,sr1F);
2264 /* Determine and detect attached devices on SiS30x */
2265 static void __devinit
2266 SiS_SenseLCD(struct sis_video_info *ivideo)
2268 unsigned char buffer[256];
2269 unsigned short temp, realcrtno, i;
2270 u8 reg, cr37 = 0, paneltype = 0;
2273 ivideo->SiS_Pr.PanelSelfDetected = false;
2275 /* LCD detection only for TMDS bridges */
2276 if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
2278 if(ivideo->vbflags2 & VB2_30xBDH)
2281 /* If LCD already set up by BIOS, skip it */
2282 inSISIDXREG(SISCR, 0x32, reg);
2287 if(ivideo->SiS_Pr.DDCPortMixup)
2290 /* Check DDC capabilities */
2291 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
2292 realcrtno, 0, &buffer[0], ivideo->vbflags2);
2294 if((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
2298 i = 3; /* Number of retrys */
2300 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2301 ivideo->sisvga_engine, realcrtno, 1,
2302 &buffer[0], ivideo->vbflags2);
2303 } while((temp) && i--);
2308 /* No digital device */
2309 if(!(buffer[0x14] & 0x80))
2312 /* First detailed timing preferred timing? */
2313 if(!(buffer[0x18] & 0x02))
2316 xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
2317 yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
2329 if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
2340 if((buffer[0x47] & 0x18) == 0x18)
2341 cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2345 outSISIDXREG(SISCR, 0x36, paneltype);
2347 setSISIDXREG(SISCR, 0x37, 0x0c, cr37);
2348 orSISIDXREG(SISCR, 0x32, 0x08);
2350 ivideo->SiS_Pr.PanelSelfDetected = true;
2353 static int __devinit
2354 SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
2356 int temp, mytest, result, i, j;
2358 for(j = 0; j < 10; j++) {
2360 for(i = 0; i < 3; i++) {
2362 outSISIDXREG(SISPART4,0x11,(type & 0x00ff));
2363 temp = (type >> 8) | (mytest & 0x00ff);
2364 setSISIDXREG(SISPART4,0x10,0xe0,temp);
2365 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
2368 inSISIDXREG(SISPART4,0x03,temp);
2371 if(temp == mytest) result++;
2373 outSISIDXREG(SISPART4,0x11,0x00);
2374 andSISIDXREG(SISPART4,0x10,0xe0);
2375 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
2378 if((result == 0) || (result >= 2)) break;
2383 static void __devinit
2384 SiS_Sense30x(struct sis_video_info *ivideo)
2386 u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
2387 u16 svhs=0, svhs_c=0;
2388 u16 cvbs=0, cvbs_c=0;
2389 u16 vga2=0, vga2_c=0;
2391 char stdstr[] = "sisfb: Detected";
2392 char tvstr[] = "TV connected to";
2394 if(ivideo->vbflags2 & VB2_301) {
2395 svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
2396 inSISIDXREG(SISPART4,0x01,myflag);
2398 svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
2400 } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) {
2401 svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
2402 } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) {
2403 svhs = 0x0200; cvbs = 0x0100;
2404 } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
2405 svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
2409 vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
2410 if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
2411 svhs_c = 0x0408; cvbs_c = 0x0808;
2415 if(ivideo->haveXGIROM) {
2416 biosflag = ivideo->bios_abase[0x58] & 0x03;
2417 } else if(ivideo->newrom) {
2418 if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01;
2419 } else if(ivideo->sisvga_engine == SIS_300_VGA) {
2420 if(ivideo->bios_abase) {
2421 biosflag = ivideo->bios_abase[0xfe] & 0x03;
2425 if(ivideo->chip == SIS_300) {
2426 inSISIDXREG(SISSR,0x3b,myflag);
2427 if(!(myflag & 0x01)) vga2 = vga2_c = 0;
2430 if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) {
2434 inSISIDXREG(SISSR,0x1e,backupSR_1e);
2435 orSISIDXREG(SISSR,0x1e,0x20);
2437 inSISIDXREG(SISPART4,0x0d,backupP4_0d);
2438 if(ivideo->vbflags2 & VB2_30xC) {
2439 setSISIDXREG(SISPART4,0x0d,~0x07,0x01);
2441 orSISIDXREG(SISPART4,0x0d,0x04);
2443 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2445 inSISIDXREG(SISPART2,0x00,backupP2_00);
2446 outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc));
2448 inSISIDXREG(SISPART2,0x4d,backupP2_4d);
2449 if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
2450 outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10));
2453 if(!(ivideo->vbflags2 & VB2_30xCLV)) {
2454 SISDoSense(ivideo, 0, 0);
2457 andSISIDXREG(SISCR, 0x32, ~0x14);
2459 if(vga2_c || vga2) {
2460 if(SISDoSense(ivideo, vga2, vga2_c)) {
2461 if(biosflag & 0x01) {
2462 printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
2463 orSISIDXREG(SISCR, 0x32, 0x04);
2465 printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
2466 orSISIDXREG(SISCR, 0x32, 0x10);
2471 andSISIDXREG(SISCR, 0x32, 0x3f);
2473 if(ivideo->vbflags2 & VB2_30xCLV) {
2474 orSISIDXREG(SISPART4,0x0d,0x04);
2477 if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
2478 outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10));
2479 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2480 if((result = SISDoSense(ivideo, svhs, 0x0604))) {
2481 if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
2482 printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
2483 orSISIDXREG(SISCR,0x32,0x80);
2486 outSISIDXREG(SISPART2,0x4d,backupP2_4d);
2489 andSISIDXREG(SISCR, 0x32, ~0x03);
2491 if(!(ivideo->vbflags & TV_YPBPR)) {
2492 if((result = SISDoSense(ivideo, svhs, svhs_c))) {
2493 printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
2494 orSISIDXREG(SISCR, 0x32, 0x02);
2496 if((biosflag & 0x02) || (!result)) {
2497 if(SISDoSense(ivideo, cvbs, cvbs_c)) {
2498 printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
2499 orSISIDXREG(SISCR, 0x32, 0x01);
2504 SISDoSense(ivideo, 0, 0);
2506 outSISIDXREG(SISPART2,0x00,backupP2_00);
2507 outSISIDXREG(SISPART4,0x0d,backupP4_0d);
2508 outSISIDXREG(SISSR,0x1e,backupSR_1e);
2510 if(ivideo->vbflags2 & VB2_30xCLV) {
2511 inSISIDXREG(SISPART2,0x00,biosflag);
2512 if(biosflag & 0x20) {
2513 for(myflag = 2; myflag > 0; myflag--) {
2515 outSISIDXREG(SISPART2,0x00,biosflag);
2520 outSISIDXREG(SISPART2,0x00,backupP2_00);
2523 /* Determine and detect attached TV's on Chrontel */
2524 static void __devinit
2525 SiS_SenseCh(struct sis_video_info *ivideo)
2527 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2529 char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
2531 #ifdef CONFIG_FB_SIS_300
2532 unsigned char test[3];
2536 if(ivideo->chip < SIS_315H) {
2538 #ifdef CONFIG_FB_SIS_300
2539 ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1; /* Chrontel 700x */
2540 SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c); /* Set general purpose IO for Chrontel communication */
2541 SiS_DDC2Delay(&ivideo->SiS_Pr, 1000);
2542 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2543 /* See Chrontel TB31 for explanation */
2544 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2545 if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
2546 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b);
2547 SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2549 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2550 if(temp2 != temp1) temp1 = temp2;
2552 if((temp1 >= 0x22) && (temp1 <= 0x50)) {
2553 /* Read power status */
2554 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2555 if((temp1 & 0x03) != 0x03) {
2556 /* Power all outputs */
2557 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b);
2558 SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2560 /* Sense connected TV devices */
2561 for(i = 0; i < 3; i++) {
2562 SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01);
2563 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2564 SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00);
2565 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2566 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
2567 if(!(temp1 & 0x08)) test[i] = 0x02;
2568 else if(!(temp1 & 0x02)) test[i] = 0x01;
2570 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2573 if(test[0] == test[1]) temp1 = test[0];
2574 else if(test[0] == test[2]) temp1 = test[0];
2575 else if(test[1] == test[2]) temp1 = test[1];
2578 "sisfb: TV detection unreliable - test results varied\n");
2582 printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2583 ivideo->vbflags |= TV_SVIDEO;
2584 orSISIDXREG(SISCR, 0x32, 0x02);
2585 andSISIDXREG(SISCR, 0x32, ~0x05);
2586 } else if (temp1 == 0x01) {
2587 printk(KERN_INFO "%s CVBS output\n", stdstr);
2588 ivideo->vbflags |= TV_AVIDEO;
2589 orSISIDXREG(SISCR, 0x32, 0x01);
2590 andSISIDXREG(SISCR, 0x32, ~0x06);
2592 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2593 andSISIDXREG(SISCR, 0x32, ~0x07);
2595 } else if(temp1 == 0) {
2596 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2597 andSISIDXREG(SISCR, 0x32, ~0x07);
2599 /* Set general purpose IO for Chrontel communication */
2600 SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
2605 #ifdef CONFIG_FB_SIS_315
2606 ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */
2607 temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
2608 SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20);
2609 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2610 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2612 SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2613 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2615 SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2616 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2617 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2618 SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1);
2620 if(temp2 & 0x02) temp1 |= 0x01;
2621 if(temp2 & 0x10) temp1 |= 0x01;
2622 if(temp2 & 0x04) temp1 |= 0x02;
2623 if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
2626 printk(KERN_INFO "%s CVBS output\n", stdstr);
2627 ivideo->vbflags |= TV_AVIDEO;
2628 orSISIDXREG(SISCR, 0x32, 0x01);
2629 andSISIDXREG(SISCR, 0x32, ~0x06);
2632 printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2633 ivideo->vbflags |= TV_SVIDEO;
2634 orSISIDXREG(SISCR, 0x32, 0x02);
2635 andSISIDXREG(SISCR, 0x32, ~0x05);
2638 printk(KERN_INFO "%s SCART output\n", stdstr);
2639 orSISIDXREG(SISCR, 0x32, 0x04);
2640 andSISIDXREG(SISCR, 0x32, ~0x03);
2643 andSISIDXREG(SISCR, 0x32, ~0x07);
2649 static void __devinit
2650 sisfb_get_VB_type(struct sis_video_info *ivideo)
2652 char stdstr[] = "sisfb: Detected";
2653 char bridgestr[] = "video bridge";
2657 /* No CRT2 on XGI Z7 */
2658 if(ivideo->chip == XGI_20)
2661 inSISIDXREG(SISPART4, 0x00, vb_chipid);
2664 inSISIDXREG(SISPART4, 0x01, reg);
2666 ivideo->vbflags |= VB_301; /* Deprecated */
2667 ivideo->vbflags2 |= VB2_301;
2668 printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
2669 } else if(reg < 0xc0) {
2670 ivideo->vbflags |= VB_301B; /* Deprecated */
2671 ivideo->vbflags2 |= VB2_301B;
2672 inSISIDXREG(SISPART4,0x23,reg);
2674 ivideo->vbflags |= VB_30xBDH; /* Deprecated */
2675 ivideo->vbflags2 |= VB2_30xBDH;
2676 printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
2678 printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
2680 } else if(reg < 0xd0) {
2681 ivideo->vbflags |= VB_301C; /* Deprecated */
2682 ivideo->vbflags2 |= VB2_301C;
2683 printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
2684 } else if(reg < 0xe0) {
2685 ivideo->vbflags |= VB_301LV; /* Deprecated */
2686 ivideo->vbflags2 |= VB2_301LV;
2687 printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
2688 } else if(reg <= 0xe1) {
2689 inSISIDXREG(SISPART4,0x39,reg);
2691 ivideo->vbflags |= VB_302LV; /* Deprecated */
2692 ivideo->vbflags2 |= VB2_302LV;
2693 printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
2695 ivideo->vbflags |= VB_301C; /* Deprecated */
2696 ivideo->vbflags2 |= VB2_301C;
2697 printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
2699 ivideo->vbflags |= VB_302ELV; /* Deprecated */
2700 ivideo->vbflags2 |= VB2_302ELV;
2701 printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
2707 ivideo->vbflags |= VB_302B; /* Deprecated */
2708 ivideo->vbflags2 |= VB2_302B;
2709 printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
2713 if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
2714 inSISIDXREG(SISCR, 0x37, reg);
2715 reg &= SIS_EXTERNAL_CHIP_MASK;
2717 if(ivideo->sisvga_engine == SIS_300_VGA) {
2718 #ifdef CONFIG_FB_SIS_300
2720 case SIS_EXTERNAL_CHIP_LVDS:
2721 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2722 ivideo->vbflags2 |= VB2_LVDS;
2724 case SIS_EXTERNAL_CHIP_TRUMPION:
2725 ivideo->vbflags |= (VB_LVDS | VB_TRUMPION); /* Deprecated */
2726 ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION);
2728 case SIS_EXTERNAL_CHIP_CHRONTEL:
2729 ivideo->vbflags |= VB_CHRONTEL; /* Deprecated */
2730 ivideo->vbflags2 |= VB2_CHRONTEL;
2732 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
2733 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2734 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2737 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1;
2739 } else if(ivideo->chip < SIS_661) {
2740 #ifdef CONFIG_FB_SIS_315
2742 case SIS310_EXTERNAL_CHIP_LVDS:
2743 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2744 ivideo->vbflags2 |= VB2_LVDS;
2746 case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
2747 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2748 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2751 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2753 } else if(ivideo->chip >= SIS_661) {
2754 #ifdef CONFIG_FB_SIS_315
2755 inSISIDXREG(SISCR, 0x38, reg);
2759 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2760 ivideo->vbflags2 |= VB2_LVDS;
2763 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2764 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2767 ivideo->vbflags |= (VB_LVDS | VB_CONEXANT); /* Deprecated */
2768 ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT);
2771 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2774 if(ivideo->vbflags2 & VB2_LVDS) {
2775 printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
2777 if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) {
2778 printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
2780 if(ivideo->vbflags2 & VB2_CHRONTEL) {
2781 printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
2783 if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) {
2784 printk(KERN_INFO "%s Conexant external device\n", stdstr);
2788 if(ivideo->vbflags2 & VB2_SISBRIDGE) {
2789 SiS_SenseLCD(ivideo);
2790 SiS_Sense30x(ivideo);
2791 } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
2792 SiS_SenseCh(ivideo);
2796 /* ---------- Engine initialization routines ------------ */
2799 sisfb_engine_init(struct sis_video_info *ivideo)
2802 /* Initialize command queue (we use MMIO only) */
2804 /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
2806 ivideo->caps &= ~(TURBO_QUEUE_CAP |
2807 MMIO_CMD_QUEUE_CAP |
2811 #ifdef CONFIG_FB_SIS_300
2812 if(ivideo->sisvga_engine == SIS_300_VGA) {
2816 tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
2818 inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
2821 tq_state |= (u8)(tqueue_pos >> 8);
2822 outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
2824 outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
2826 ivideo->caps |= TURBO_QUEUE_CAP;
2830 #ifdef CONFIG_FB_SIS_315
2831 if(ivideo->sisvga_engine == SIS_315_VGA) {
2832 u32 tempq = 0, templ;
2835 if(ivideo->chip == XGI_20) {
2836 switch(ivideo->cmdQueueSize) {
2838 temp = SIS_CMD_QUEUE_SIZE_Z7_64k;
2842 temp = SIS_CMD_QUEUE_SIZE_Z7_128k;
2845 switch(ivideo->cmdQueueSize) {
2846 case (4 * 1024 * 1024):
2847 temp = SIS_CMD_QUEUE_SIZE_4M;
2849 case (2 * 1024 * 1024):
2850 temp = SIS_CMD_QUEUE_SIZE_2M;
2852 case (1 * 1024 * 1024):
2853 temp = SIS_CMD_QUEUE_SIZE_1M;
2857 temp = SIS_CMD_QUEUE_SIZE_512k;
2861 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2862 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2864 if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
2865 /* Must disable dual pipe on XGI_40. Can't do
2866 * this in MMIO mode, because it requires
2867 * setting/clearing a bit in the MMIO fire trigger
2870 if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) {
2872 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
2874 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
2876 tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
2877 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
2879 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2880 MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq);
2882 writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq);
2883 writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4);
2884 writel(0x168F0000, ivideo->video_vbase + tempq + 8);
2885 writel(0x168F0000, ivideo->video_vbase + tempq + 12);
2887 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16));
2889 sisfb_syncaccel(ivideo);
2891 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2896 tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
2897 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
2899 temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
2900 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
2902 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2903 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
2905 ivideo->caps |= MMIO_CMD_QUEUE_CAP;
2909 ivideo->engineok = 1;
2912 static void __devinit
2913 sisfb_detect_lcd_type(struct sis_video_info *ivideo)
2918 inSISIDXREG(SISCR, 0x36, reg);
2920 if(ivideo->sisvga_engine == SIS_300_VGA) {
2921 ivideo->CRT2LCDType = sis300paneltype[reg];
2922 } else if(ivideo->chip >= SIS_661) {
2923 ivideo->CRT2LCDType = sis661paneltype[reg];
2925 ivideo->CRT2LCDType = sis310paneltype[reg];
2926 if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
2927 if((ivideo->CRT2LCDType != LCD_320x240_2) &&
2928 (ivideo->CRT2LCDType != LCD_320x240_3)) {
2929 ivideo->CRT2LCDType = LCD_320x240;
2934 if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
2935 /* For broken BIOSes: Assume 1024x768, RGB18 */
2936 ivideo->CRT2LCDType = LCD_1024x768;
2937 setSISIDXREG(SISCR,0x36,0xf0,0x02);
2938 setSISIDXREG(SISCR,0x37,0xee,0x01);
2939 printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
2942 for(i = 0; i < SIS_LCD_NUMBER; i++) {
2943 if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
2944 ivideo->lcdxres = sis_lcd_data[i].xres;
2945 ivideo->lcdyres = sis_lcd_data[i].yres;
2946 ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
2951 #ifdef CONFIG_FB_SIS_300
2952 if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
2953 ivideo->lcdxres = 1360; ivideo->lcdyres = 1024;
2954 ivideo->lcddefmodeidx = DEFAULT_MODE_1360;
2955 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
2956 ivideo->lcdxres = 848; ivideo->lcdyres = 480;
2957 ivideo->lcddefmodeidx = DEFAULT_MODE_848;
2958 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) {
2959 ivideo->lcdxres = 856; ivideo->lcdyres = 480;
2960 ivideo->lcddefmodeidx = DEFAULT_MODE_856;
2964 printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
2965 ivideo->lcdxres, ivideo->lcdyres);
2968 static void __devinit
2969 sisfb_save_pdc_emi(struct sis_video_info *ivideo)
2971 #ifdef CONFIG_FB_SIS_300
2972 /* Save the current PanelDelayCompensation if the LCD is currently used */
2973 if(ivideo->sisvga_engine == SIS_300_VGA) {
2974 if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
2976 inSISIDXREG(SISCR,0x30,tmp);
2978 /* Currently on LCD? If yes, read current pdc */
2979 inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc);
2980 ivideo->detectedpdc &= 0x3c;
2981 if(ivideo->SiS_Pr.PDC == -1) {
2982 /* Let option override detection */
2983 ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
2985 printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
2986 ivideo->detectedpdc);
2988 if((ivideo->SiS_Pr.PDC != -1) &&
2989 (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
2990 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
2991 ivideo->SiS_Pr.PDC);
2997 #ifdef CONFIG_FB_SIS_315
2998 if(ivideo->sisvga_engine == SIS_315_VGA) {
3000 /* Try to find about LCDA */
3001 if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
3003 inSISIDXREG(SISPART1,0x13,tmp);
3005 ivideo->SiS_Pr.SiS_UseLCDA = true;
3006 ivideo->detectedlcda = 0x03;
3011 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
3013 inSISIDXREG(SISCR,0x30,tmp);
3014 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3015 /* Currently on LCD? If yes, read current pdc */
3017 inSISIDXREG(SISPART1,0x2D,pdc);
3018 ivideo->detectedpdc = (pdc & 0x0f) << 1;
3019 ivideo->detectedpdca = (pdc & 0xf0) >> 3;
3020 inSISIDXREG(SISPART1,0x35,pdc);
3021 ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
3022 inSISIDXREG(SISPART1,0x20,pdc);
3023 ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
3024 if(ivideo->newrom) {
3025 /* New ROM invalidates other PDC resp. */
3026 if(ivideo->detectedlcda != 0xff) {
3027 ivideo->detectedpdc = 0xff;
3029 ivideo->detectedpdca = 0xff;
3032 if(ivideo->SiS_Pr.PDC == -1) {
3033 if(ivideo->detectedpdc != 0xff) {
3034 ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
3037 if(ivideo->SiS_Pr.PDCA == -1) {
3038 if(ivideo->detectedpdca != 0xff) {
3039 ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
3042 if(ivideo->detectedpdc != 0xff) {
3044 "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3045 ivideo->detectedpdc);
3047 if(ivideo->detectedpdca != 0xff) {
3049 "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3050 ivideo->detectedpdca);
3055 if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
3056 inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30);
3057 inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31);
3058 inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32);
3059 inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33);
3060 ivideo->SiS_Pr.HaveEMI = true;
3061 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3062 ivideo->SiS_Pr.HaveEMILCD = true;
3067 /* Let user override detected PDCs (all bridges) */
3068 if(ivideo->vbflags2 & VB2_30xBLV) {
3069 if((ivideo->SiS_Pr.PDC != -1) &&
3070 (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
3071 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3072 ivideo->SiS_Pr.PDC);
3074 if((ivideo->SiS_Pr.PDCA != -1) &&
3075 (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
3076 printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3077 ivideo->SiS_Pr.PDCA);
3085 /* -------------------- Memory manager routines ---------------------- */
3087 static u32 __devinit
3088 sisfb_getheapstart(struct sis_video_info *ivideo)
3090 u32 ret = ivideo->sisfb_parm_mem * 1024;
3091 u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3094 /* Calculate heap start = end of memory for console
3096 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3097 * C = console, D = heap, H = HWCursor, Q = cmd-queue
3099 * On 76x in UMA+LFB mode, the layout is as follows:
3100 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3101 * where the heap is the entire UMA area, eventually
3102 * into the LFB area if the given mem parameter is
3103 * higher than the size of the UMA memory.
3105 * Basically given by "mem" parameter
3107 * maximum = videosize - cmd_queue - hwcursor
3108 * (results in a heap of size 0)
3109 * default = SiS 300: depends on videosize
3110 * SiS 315/330/340/XGI: 32k below max
3113 if(ivideo->sisvga_engine == SIS_300_VGA) {
3114 if(ivideo->video_size > 0x1000000) {
3116 } else if(ivideo->video_size > 0x800000) {
3121 } else if(ivideo->UMAsize && ivideo->LFBsize) {
3124 def = maxoffs - 0x8000;
3127 /* Use default for secondary card for now (FIXME) */
3128 if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0))
3134 static u32 __devinit
3135 sisfb_getheapsize(struct sis_video_info *ivideo)
3137 u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3140 if(ivideo->UMAsize && ivideo->LFBsize) {
3141 if( (!ivideo->sisfb_parm_mem) ||
3142 ((ivideo->sisfb_parm_mem * 1024) > max) ||
3143 ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) {
3144 ret = ivideo->UMAsize;
3145 max -= ivideo->UMAsize;
3147 ret = max - (ivideo->sisfb_parm_mem * 1024);
3148 max = ivideo->sisfb_parm_mem * 1024;
3150 ivideo->video_offset = ret;
3151 ivideo->sisfb_mem = max;
3153 ret = max - ivideo->heapstart;
3154 ivideo->sisfb_mem = ivideo->heapstart;
3160 static int __devinit
3161 sisfb_heap_init(struct sis_video_info *ivideo)
3165 ivideo->video_offset = 0;
3166 if(ivideo->sisfb_parm_mem) {
3167 if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) ||
3168 (ivideo->sisfb_parm_mem > ivideo->video_size) ) {
3169 ivideo->sisfb_parm_mem = 0;
3173 ivideo->heapstart = sisfb_getheapstart(ivideo);
3174 ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo);
3176 ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
3177 ivideo->sisfb_heap_end = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size;
3179 printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
3180 (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
3182 ivideo->sisfb_heap.vinfo = ivideo;
3184 ivideo->sisfb_heap.poha_chain = NULL;
3185 ivideo->sisfb_heap.poh_freelist = NULL;
3187 poh = sisfb_poh_new_node(&ivideo->sisfb_heap);
3191 poh->poh_next = &ivideo->sisfb_heap.oh_free;
3192 poh->poh_prev = &ivideo->sisfb_heap.oh_free;
3193 poh->size = ivideo->sisfb_heap_size;
3194 poh->offset = ivideo->heapstart;
3196 ivideo->sisfb_heap.oh_free.poh_next = poh;
3197 ivideo->sisfb_heap.oh_free.poh_prev = poh;
3198 ivideo->sisfb_heap.oh_free.size = 0;
3199 ivideo->sisfb_heap.max_freesize = poh->size;
3201 ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used;
3202 ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used;
3203 ivideo->sisfb_heap.oh_used.size = SENTINEL;
3205 if(ivideo->cardnumber == 0) {
3206 /* For the first card, make this heap the "global" one
3207 * for old DRM (which could handle only one card)
3209 sisfb_heap = &ivideo->sisfb_heap;
3215 static struct SIS_OH *
3216 sisfb_poh_new_node(struct SIS_HEAP *memheap)
3218 struct SIS_OHALLOC *poha;
3223 if(memheap->poh_freelist == NULL) {
3224 poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
3228 poha->poha_next = memheap->poha_chain;
3229 memheap->poha_chain = poha;
3231 cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1;
3233 poh = &poha->aoh[0];
3234 for(i = cOhs - 1; i != 0; i--) {
3235 poh->poh_next = poh + 1;
3239 poh->poh_next = NULL;
3240 memheap->poh_freelist = &poha->aoh[0];
3243 poh = memheap->poh_freelist;
3244 memheap->poh_freelist = poh->poh_next;
3249 static struct SIS_OH *
3250 sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size)
3252 struct SIS_OH *pohThis;
3253 struct SIS_OH *pohRoot;
3256 if(size > memheap->max_freesize) {
3257 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3258 (unsigned int) size / 1024);
3262 pohThis = memheap->oh_free.poh_next;
3264 while(pohThis != &memheap->oh_free) {
3265 if(size <= pohThis->size) {
3269 pohThis = pohThis->poh_next;
3273 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3274 (unsigned int) size / 1024);
3278 if(size == pohThis->size) {
3280 sisfb_delete_node(pohThis);
3282 pohRoot = sisfb_poh_new_node(memheap);
3286 pohRoot->offset = pohThis->offset;
3287 pohRoot->size = size;
3289 pohThis->offset += size;
3290 pohThis->size -= size;
3293 memheap->max_freesize -= size;
3295 pohThis = &memheap->oh_used;
3296 sisfb_insert_node(pohThis, pohRoot);
3302 sisfb_delete_node(struct SIS_OH *poh)
3304 poh->poh_prev->poh_next = poh->poh_next;
3305 poh->poh_next->poh_prev = poh->poh_prev;
3309 sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh)
3311 struct SIS_OH *pohTemp = pohList->poh_next;
3313 pohList->poh_next = poh;
3314 pohTemp->poh_prev = poh;
3316 poh->poh_prev = pohList;
3317 poh->poh_next = pohTemp;
3320 static struct SIS_OH *
3321 sisfb_poh_free(struct SIS_HEAP *memheap, u32 base)
3323 struct SIS_OH *pohThis;
3324 struct SIS_OH *poh_freed;
3325 struct SIS_OH *poh_prev;
3326 struct SIS_OH *poh_next;
3331 poh_freed = memheap->oh_used.poh_next;
3333 while(poh_freed != &memheap->oh_used) {
3334 if(poh_freed->offset == base) {
3339 poh_freed = poh_freed->poh_next;
3345 memheap->max_freesize += poh_freed->size;
3347 poh_prev = poh_next = NULL;
3348 ulUpper = poh_freed->offset + poh_freed->size;
3349 ulLower = poh_freed->offset;
3351 pohThis = memheap->oh_free.poh_next;
3353 while(pohThis != &memheap->oh_free) {
3354 if(pohThis->offset == ulUpper) {
3356 } else if((pohThis->offset + pohThis->size) == ulLower) {
3359 pohThis = pohThis->poh_next;
3362 sisfb_delete_node(poh_freed);
3364 if(poh_prev && poh_next) {
3365 poh_prev->size += (poh_freed->size + poh_next->size);
3366 sisfb_delete_node(poh_next);
3367 sisfb_free_node(memheap, poh_freed);
3368 sisfb_free_node(memheap, poh_next);
3373 poh_prev->size += poh_freed->size;
3374 sisfb_free_node(memheap, poh_freed);
3379 poh_next->size += poh_freed->size;
3380 poh_next->offset = poh_freed->offset;
3381 sisfb_free_node(memheap, poh_freed);
3385 sisfb_insert_node(&memheap->oh_free, poh_freed);
3391 sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh)
3396 poh->poh_next = memheap->poh_freelist;
3397 memheap->poh_freelist = poh;
3401 sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req)
3403 struct SIS_OH *poh = NULL;
3405 if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap))
3406 poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size);
3409 req->offset = req->size = 0;
3410 DPRINTK("sisfb: Video RAM allocation failed\n");
3412 req->offset = poh->offset;
3413 req->size = poh->size;
3414 DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3415 (poh->offset + ivideo->video_vbase));
3420 sis_malloc(struct sis_memreq *req)
3422 struct sis_video_info *ivideo = sisfb_heap->vinfo;
3424 if(&ivideo->sisfb_heap == sisfb_heap)
3425 sis_int_malloc(ivideo, req);
3427 req->offset = req->size = 0;
3431 sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
3433 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3435 sis_int_malloc(ivideo, req);
3438 /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3441 sis_int_free(struct sis_video_info *ivideo, u32 base)
3445 if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap))
3448 poh = sisfb_poh_free(&ivideo->sisfb_heap, base);
3451 DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
3452 (unsigned int) base);
3459 struct sis_video_info *ivideo = sisfb_heap->vinfo;
3461 sis_int_free(ivideo, base);
3465 sis_free_new(struct pci_dev *pdev, u32 base)
3467 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3469 sis_int_free(ivideo, base);
3472 /* --------------------- SetMode routines ------------------------- */
3475 sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
3479 /* Check if MMIO and engines are enabled,
3480 * and sync in case they are. Can't use
3481 * ivideo->accel here, as this might have
3482 * been changed before this is called.
3484 inSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, cr30);
3485 inSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, cr31);
3486 /* MMIO and 2D/3D engine enabled? */
3487 if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
3488 #ifdef CONFIG_FB_SIS_300
3489 if(ivideo->sisvga_engine == SIS_300_VGA) {
3490 /* Don't care about TurboQueue. It's
3491 * enough to know that the engines
3494 sisfb_syncaccel(ivideo);
3497 #ifdef CONFIG_FB_SIS_315
3498 if(ivideo->sisvga_engine == SIS_315_VGA) {
3499 /* Check that any queue mode is
3500 * enabled, and that the queue
3501 * is not in the state of "reset"
3503 inSISIDXREG(SISSR, 0x26, cr30);
3504 if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
3505 sisfb_syncaccel(ivideo);
3513 sisfb_pre_setmode(struct sis_video_info *ivideo)
3515 u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
3518 ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
3520 outSISIDXREG(SISSR, 0x05, 0x86);
3522 inSISIDXREG(SISCR, 0x31, cr31);
3526 cr33 = ivideo->rate_idx & 0x0F;
3528 #ifdef CONFIG_FB_SIS_315
3529 if(ivideo->sisvga_engine == SIS_315_VGA) {
3530 if(ivideo->chip >= SIS_661) {
3531 inSISIDXREG(SISCR, 0x38, cr38);
3532 cr38 &= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
3535 inSISIDXREG(SISCR, tvregnum, cr38);
3536 cr38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
3540 #ifdef CONFIG_FB_SIS_300
3541 if(ivideo->sisvga_engine == SIS_300_VGA) {
3543 inSISIDXREG(SISCR, tvregnum, cr38);
3547 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
3548 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
3549 ivideo->curFSTN = ivideo->curDSTN = 0;
3551 switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
3554 cr38 &= ~0xc0; /* Clear PAL-M / PAL-N bits */
3555 if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
3556 #ifdef CONFIG_FB_SIS_315
3557 if(ivideo->chip >= SIS_661) {
3559 if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20;
3560 else if(ivideo->vbflags & TV_YPBPR750P) cr35 |= 0x40;
3561 else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
3562 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3564 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3565 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
3566 cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3568 if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10;
3569 else if(ivideo->vbflags & TV_YPBPR750P) cr38 |= 0x20;
3570 else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
3572 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3575 } else if((ivideo->vbflags & TV_HIVISION) &&
3576 (ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) {
3577 if(ivideo->chip >= SIS_661) {
3583 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3586 ivideo->currentvbflags |= TV_HIVISION;
3587 } else if(ivideo->vbflags & TV_SCART) {
3588 cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
3591 ivideo->currentvbflags |= TV_SCART;
3593 if(ivideo->vbflags & TV_SVIDEO) {
3594 cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
3595 ivideo->currentvbflags |= TV_SVIDEO;
3597 if(ivideo->vbflags & TV_AVIDEO) {
3598 cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
3599 ivideo->currentvbflags |= TV_AVIDEO;
3602 cr31 |= SIS_DRIVER_MODE;
3604 if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) {
3605 if(ivideo->vbflags & TV_PAL) {
3606 cr31 |= 0x01; cr35 |= 0x01;
3607 ivideo->currentvbflags |= TV_PAL;
3608 if(ivideo->vbflags & TV_PALM) {
3609 cr38 |= 0x40; cr35 |= 0x04;
3610 ivideo->currentvbflags |= TV_PALM;
3611 } else if(ivideo->vbflags & TV_PALN) {
3612 cr38 |= 0x80; cr35 |= 0x08;
3613 ivideo->currentvbflags |= TV_PALN;
3616 cr31 &= ~0x01; cr35 &= ~0x01;
3617 ivideo->currentvbflags |= TV_NTSC;
3618 if(ivideo->vbflags & TV_NTSCJ) {
3619 cr38 |= 0x40; cr35 |= 0x02;
3620 ivideo->currentvbflags |= TV_NTSCJ;
3627 cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
3628 cr31 |= SIS_DRIVER_MODE;
3629 SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
3630 SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
3631 ivideo->curFSTN = ivideo->sisfb_fstn;
3632 ivideo->curDSTN = ivideo->sisfb_dstn;
3636 cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3637 cr31 |= SIS_DRIVER_MODE;
3638 if(ivideo->sisfb_nocrt2rate) {
3639 cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4);
3641 cr33 |= ((ivideo->rate_idx & 0x0F) << 4);
3645 default: /* disable CRT2 */
3647 cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
3650 outSISIDXREG(SISCR, 0x30, cr30);
3651 outSISIDXREG(SISCR, 0x33, cr33);
3653 if(ivideo->chip >= SIS_661) {
3654 #ifdef CONFIG_FB_SIS_315
3655 cr31 &= ~0x01; /* Clear PAL flag (now in CR35) */
3656 setSISIDXREG(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
3657 cr38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
3658 setSISIDXREG(SISCR, 0x38, 0xf8, cr38);
3660 } else if(ivideo->chip != SIS_300) {
3661 outSISIDXREG(SISCR, tvregnum, cr38);
3663 outSISIDXREG(SISCR, 0x31, cr31);
3665 ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
3667 sisfb_check_engine_and_sync(ivideo);
3670 /* Fix SR11 for 661 and later */
3671 #ifdef CONFIG_FB_SIS_315
3673 sisfb_fixup_SR11(struct sis_video_info *ivideo)
3677 if(ivideo->chip >= SIS_661) {
3678 inSISIDXREG(SISSR,0x11,tmpreg);
3680 inSISIDXREG(SISSR,0x3e,tmpreg);
3681 tmpreg = (tmpreg + 1) & 0xff;
3682 outSISIDXREG(SISSR,0x3e,tmpreg);
3683 inSISIDXREG(SISSR,0x11,tmpreg);
3686 andSISIDXREG(SISSR,0x11,0x0f);
3693 sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
3695 if(val > 32) val = 32;
3696 if(val < -32) val = -32;
3697 ivideo->tvxpos = val;
3699 if(ivideo->sisfblocked) return;
3700 if(!ivideo->modechanged) return;
3702 if(ivideo->currentvbflags & CRT2_TV) {
3704 if(ivideo->vbflags2 & VB2_CHRONTEL) {
3706 int x = ivideo->tvx;
3708 switch(ivideo->chronteltype) {
3712 outSISIDXREG(SISSR,0x05,0x86);
3713 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
3714 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
3717 /* Not supported by hardware */
3721 } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3723 u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
3724 unsigned short temp;
3726 p2_1f = ivideo->p2_1f;
3727 p2_20 = ivideo->p2_20;
3728 p2_2b = ivideo->p2_2b;
3729 p2_42 = ivideo->p2_42;
3730 p2_43 = ivideo->p2_43;
3732 temp = p2_1f | ((p2_20 & 0xf0) << 4);
3734 p2_1f = temp & 0xff;
3735 p2_20 = (temp & 0xf00) >> 4;
3736 p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
3737 temp = p2_43 | ((p2_42 & 0xf0) << 4);
3739 p2_43 = temp & 0xff;
3740 p2_42 = (temp & 0xf00) >> 4;
3741 outSISIDXREG(SISPART2,0x1f,p2_1f);
3742 setSISIDXREG(SISPART2,0x20,0x0F,p2_20);
3743 setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b);
3744 setSISIDXREG(SISPART2,0x42,0x0F,p2_42);
3745 outSISIDXREG(SISPART2,0x43,p2_43);
3751 sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
3753 if(val > 32) val = 32;
3754 if(val < -32) val = -32;
3755 ivideo->tvypos = val;
3757 if(ivideo->sisfblocked) return;
3758 if(!ivideo->modechanged) return;
3760 if(ivideo->currentvbflags & CRT2_TV) {
3762 if(ivideo->vbflags2 & VB2_CHRONTEL) {
3764 int y = ivideo->tvy;
3766 switch(ivideo->chronteltype) {
3770 outSISIDXREG(SISSR,0x05,0x86);
3771 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
3772 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
3775 /* Not supported by hardware */
3779 } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3783 p2_01 = ivideo->p2_01;
3784 p2_02 = ivideo->p2_02;
3788 if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) {
3789 while((p2_01 <= 0) || (p2_02 <= 0)) {
3794 outSISIDXREG(SISPART2,0x01,p2_01);
3795 outSISIDXREG(SISPART2,0x02,p2_02);
3801 sisfb_post_setmode(struct sis_video_info *ivideo)
3803 bool crt1isoff = false;
3805 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
3808 #ifdef CONFIG_FB_SIS_315
3812 outSISIDXREG(SISSR, 0x05, 0x86);
3814 #ifdef CONFIG_FB_SIS_315
3815 sisfb_fixup_SR11(ivideo);
3818 /* Now we actually HAVE changed the display mode */
3819 ivideo->modechanged = 1;
3821 /* We can't switch off CRT1 if bridge is in slave mode */
3822 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
3823 if(sisfb_bridgeisslave(ivideo)) doit = false;
3825 ivideo->sisfb_crt1off = 0;
3827 #ifdef CONFIG_FB_SIS_300
3828 if(ivideo->sisvga_engine == SIS_300_VGA) {
3829 if((ivideo->sisfb_crt1off) && (doit)) {
3836 setSISIDXREG(SISCR, 0x17, 0x7f, reg);
3839 #ifdef CONFIG_FB_SIS_315
3840 if(ivideo->sisvga_engine == SIS_315_VGA) {
3841 if((ivideo->sisfb_crt1off) && (doit)) {
3850 setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
3851 setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1);
3856 ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
3857 ivideo->currentvbflags |= VB_SINGLE_MODE;
3859 ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
3860 if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
3861 ivideo->currentvbflags |= VB_MIRROR_MODE;
3863 ivideo->currentvbflags |= VB_SINGLE_MODE;
3867 andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
3869 if(ivideo->currentvbflags & CRT2_TV) {
3870 if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3871 inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f);
3872 inSISIDXREG(SISPART2,0x20,ivideo->p2_20);
3873 inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b);
3874 inSISIDXREG(SISPART2,0x42,ivideo->p2_42);
3875 inSISIDXREG(SISPART2,0x43,ivideo->p2_43);
3876 inSISIDXREG(SISPART2,0x01,ivideo->p2_01);
3877 inSISIDXREG(SISPART2,0x02,ivideo->p2_02);
3878 } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
3879 if(ivideo->chronteltype == 1) {
3880 ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
3881 ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
3882 ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
3883 ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
3888 if(ivideo->tvxpos) {
3889 sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
3891 if(ivideo->tvypos) {
3892 sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
3895 /* Eventually sync engines */
3896 sisfb_check_engine_and_sync(ivideo);
3898 /* (Re-)Initialize chip engines */
3900 sisfb_engine_init(ivideo);
3902 ivideo->engineok = 0;
3907 sisfb_reset_mode(struct sis_video_info *ivideo)
3909 if(sisfb_set_mode(ivideo, 0))
3912 sisfb_set_pitch(ivideo);
3913 sisfb_set_base_CRT1(ivideo, ivideo->current_base);
3914 sisfb_set_base_CRT2(ivideo, ivideo->current_base);
3920 sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command)
3924 switch(sisfb_command->sisfb_cmd) {
3925 case SISFB_CMD_GETVBFLAGS:
3926 if(!ivideo->modechanged) {
3927 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3929 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3930 sisfb_command->sisfb_result[1] = ivideo->currentvbflags;
3931 sisfb_command->sisfb_result[2] = ivideo->vbflags2;
3934 case SISFB_CMD_SWITCHCRT1:
3935 /* arg[0]: 0 = off, 1 = on, 99 = query */
3936 if(!ivideo->modechanged) {
3937 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3938 } else if(sisfb_command->sisfb_arg[0] == 99) {
3940 sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3941 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3942 } else if(ivideo->sisfblocked) {
3943 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED;
3944 } else if((!(ivideo->currentvbflags & CRT2_ENABLE)) &&
3945 (sisfb_command->sisfb_arg[0] == 0)) {
3946 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2;
3948 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3949 mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1;
3950 if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) ||
3951 ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) {
3952 ivideo->sisfb_crt1off = mycrt1off;
3953 if(sisfb_reset_mode(ivideo)) {
3954 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER;
3957 sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3962 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN;
3963 printk(KERN_ERR "sisfb: Unknown command 0x%x\n",
3964 sisfb_command->sisfb_cmd);
3969 static int __init sisfb_setup(char *options)
3973 sisfb_setdefaultparms();
3975 if(!options || !(*options))
3978 while((this_opt = strsep(&options, ",")) != NULL) {
3980 if(!(*this_opt)) continue;
3982 if(!strnicmp(this_opt, "off", 3)) {
3984 } else if(!strnicmp(this_opt, "forcecrt2type:", 14)) {
3985 /* Need to check crt2 type first for fstn/dstn */
3986 sisfb_search_crt2type(this_opt + 14);
3987 } else if(!strnicmp(this_opt, "tvmode:",7)) {
3988 sisfb_search_tvstd(this_opt + 7);
3989 } else if(!strnicmp(this_opt, "tvstandard:",11)) {
3990 sisfb_search_tvstd(this_opt + 11);
3991 } else if(!strnicmp(this_opt, "mode:", 5)) {
3992 sisfb_search_mode(this_opt + 5, false);
3993 } else if(!strnicmp(this_opt, "vesa:", 5)) {
3994 sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false);
3995 } else if(!strnicmp(this_opt, "rate:", 5)) {
3996 sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
3997 } else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
3998 sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
3999 } else if(!strnicmp(this_opt, "mem:",4)) {
4000 sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
4001 } else if(!strnicmp(this_opt, "pdc:", 4)) {
4002 sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
4003 } else if(!strnicmp(this_opt, "pdc1:", 5)) {
4004 sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
4005 } else if(!strnicmp(this_opt, "noaccel", 7)) {
4007 } else if(!strnicmp(this_opt, "accel", 5)) {
4009 } else if(!strnicmp(this_opt, "noypan", 6)) {
4011 } else if(!strnicmp(this_opt, "ypan", 4)) {
4013 } else if(!strnicmp(this_opt, "nomax", 5)) {
4015 } else if(!strnicmp(this_opt, "max", 3)) {
4017 } else if(!strnicmp(this_opt, "userom:", 7)) {
4018 sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
4019 } else if(!strnicmp(this_opt, "useoem:", 7)) {
4020 sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
4021 } else if(!strnicmp(this_opt, "nocrt2rate", 10)) {
4022 sisfb_nocrt2rate = 1;
4023 } else if(!strnicmp(this_opt, "scalelcd:", 9)) {
4024 unsigned long temp = 2;
4025 temp = simple_strtoul(this_opt + 9, NULL, 0);
4026 if((temp == 0) || (temp == 1)) {
4027 sisfb_scalelcd = temp ^ 1;
4029 } else if(!strnicmp(this_opt, "tvxposoffset:", 13)) {
4031 temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4032 if((temp >= -32) && (temp <= 32)) {
4033 sisfb_tvxposoffset = temp;
4035 } else if(!strnicmp(this_opt, "tvyposoffset:", 13)) {
4037 temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4038 if((temp >= -32) && (temp <= 32)) {
4039 sisfb_tvyposoffset = temp;
4041 } else if(!strnicmp(this_opt, "specialtiming:", 14)) {
4042 sisfb_search_specialtiming(this_opt + 14);
4043 } else if(!strnicmp(this_opt, "lvdshl:", 7)) {
4045 temp = simple_strtoul(this_opt + 7, NULL, 0);
4046 if((temp >= 0) && (temp <= 3)) {
4047 sisfb_lvdshl = temp;
4049 } else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
4050 sisfb_search_mode(this_opt, true);
4051 #if !defined(__i386__) && !defined(__x86_64__)
4052 } else if(!strnicmp(this_opt, "resetcard", 9)) {
4053 sisfb_resetcard = 1;
4054 } else if(!strnicmp(this_opt, "videoram:", 9)) {
4055 sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
4058 printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
4067 static int __devinit
4068 sisfb_check_rom(void __iomem *rom_base, struct sis_video_info *ivideo)
4073 if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
4076 romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
4077 if(romptr > (0x10000 - 8))
4080 rom = rom_base + romptr;
4082 if((readb(rom) != 'P') || (readb(rom + 1) != 'C') ||
4083 (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R'))
4086 if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor)
4089 if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id)
4095 static unsigned char * __devinit
4096 sisfb_find_rom(struct pci_dev *pdev)
4098 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4099 void __iomem *rom_base;
4100 unsigned char *myrombase = NULL;
4104 /* First, try the official pci ROM functions (except
4105 * on integrated chipsets which have no ROM).
4108 if(!ivideo->nbridge) {
4110 if((rom_base = pci_map_rom(pdev, &romsize))) {
4112 if(sisfb_check_rom(rom_base, ivideo)) {
4114 if((myrombase = vmalloc(65536))) {
4116 /* Work around bug in pci/rom.c: Folks forgot to check
4117 * whether the size retrieved from the BIOS image eventually
4118 * is larger than the mapped size
4120 if(pci_resource_len(pdev, PCI_ROM_RESOURCE) < romsize)
4121 romsize = pci_resource_len(pdev, PCI_ROM_RESOURCE);
4123 memcpy_fromio(myrombase, rom_base,
4124 (romsize > 65536) ? 65536 : romsize);
4127 pci_unmap_rom(pdev, rom_base);
4131 if(myrombase) return myrombase;
4133 /* Otherwise do it the conventional way. */
4135 #if defined(__i386__) || defined(__x86_64__)
4137 for(temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
4139 rom_base = ioremap(temp, 65536);
4143 if(!sisfb_check_rom(rom_base, ivideo)) {
4148 if((myrombase = vmalloc(65536)))
4149 memcpy_fromio(myrombase, rom_base, 65536);
4158 pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &temp);
4159 pci_write_config_dword(pdev, PCI_ROM_ADDRESS,
4160 (ivideo->video_base & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
4162 rom_base = ioremap(ivideo->video_base, 65536);
4164 if(sisfb_check_rom(rom_base, ivideo)) {
4165 if((myrombase = vmalloc(65536)))
4166 memcpy_fromio(myrombase, rom_base, 65536);
4171 pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp);
4178 static void __devinit
4179 sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize,
4182 ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize));
4184 if(!ivideo->video_vbase) {
4186 "sisfb: Unable to map maximum video RAM for size detection\n");
4188 while((!(ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize))))) {
4190 if((*mapsize) < (min << 20))
4193 if(ivideo->video_vbase) {
4195 "sisfb: Video RAM size detection limited to %dMB\n",
4196 (int)((*mapsize) >> 20));
4201 #ifdef CONFIG_FB_SIS_300
4202 static int __devinit
4203 sisfb_post_300_buswidth(struct sis_video_info *ivideo)
4205 void __iomem *FBAddress = ivideo->video_vbase;
4206 unsigned short temp;
4210 andSISIDXREG(SISSR, 0x15, 0xFB);
4211 orSISIDXREG(SISSR, 0x15, 0x04);
4212 outSISIDXREG(SISSR, 0x13, 0x00);
4213 outSISIDXREG(SISSR, 0x14, 0xBF);
4215 for(i = 0; i < 2; i++) {
4217 for(j = 0; j < 4; j++) {
4218 writew(temp, FBAddress);
4219 if(readw(FBAddress) == temp)
4221 orSISIDXREG(SISSR, 0x3c, 0x01);
4222 inSISIDXREG(SISSR, 0x05, reg);
4223 inSISIDXREG(SISSR, 0x05, reg);
4224 andSISIDXREG(SISSR, 0x3c, 0xfe);
4225 inSISIDXREG(SISSR, 0x05, reg);
4226 inSISIDXREG(SISSR, 0x05, reg);
4231 writel(0x01234567L, FBAddress);
4232 writel(0x456789ABL, (FBAddress + 4));
4233 writel(0x89ABCDEFL, (FBAddress + 8));
4234 writel(0xCDEF0123L, (FBAddress + 12));
4236 inSISIDXREG(SISSR, 0x3b, reg);
4238 if(readl((FBAddress + 12)) == 0xCDEF0123L)
4239 return 4; /* Channel A 128bit */
4242 if(readl((FBAddress + 4)) == 0x456789ABL)
4243 return 2; /* Channel B 64bit */
4245 return 1; /* 32bit */
4248 static int __devinit
4249 sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth,
4250 int PseudoRankCapacity, int PseudoAdrPinCount,
4251 unsigned int mapsize)
4253 void __iomem *FBAddr = ivideo->video_vbase;
4254 unsigned short sr14;
4255 unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
4256 unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
4257 static const unsigned short SiS_DRAMType[17][5] = {
4258 {0x0C,0x0A,0x02,0x40,0x39},
4259 {0x0D,0x0A,0x01,0x40,0x48},
4260 {0x0C,0x09,0x02,0x20,0x35},
4261 {0x0D,0x09,0x01,0x20,0x44},
4262 {0x0C,0x08,0x02,0x10,0x31},
4263 {0x0D,0x08,0x01,0x10,0x40},
4264 {0x0C,0x0A,0x01,0x20,0x34},
4265 {0x0C,0x09,0x01,0x08,0x32},
4266 {0x0B,0x08,0x02,0x08,0x21},
4267 {0x0C,0x08,0x01,0x08,0x30},
4268 {0x0A,0x08,0x02,0x04,0x11},
4269 {0x0B,0x0A,0x01,0x10,0x28},
4270 {0x09,0x08,0x02,0x02,0x01},
4271 {0x0B,0x09,0x01,0x08,0x24},
4272 {0x0B,0x08,0x01,0x04,0x20},
4273 {0x0A,0x08,0x01,0x02,0x10},
4274 {0x09,0x08,0x01,0x01,0x00}
4277 for(k = 0; k <= 16; k++) {
4279 RankCapacity = buswidth * SiS_DRAMType[k][3];
4281 if(RankCapacity != PseudoRankCapacity)
4284 if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
4287 BankNumHigh = RankCapacity * 16 * iteration - 1;
4288 if(iteration == 3) { /* Rank No */
4289 BankNumMid = RankCapacity * 16 - 1;
4291 BankNumMid = RankCapacity * 16 * iteration / 2 - 1;
4294 PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
4295 PhysicalAdrHigh = BankNumHigh;
4296 PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
4297 PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
4299 andSISIDXREG(SISSR, 0x15, 0xFB); /* Test */
4300 orSISIDXREG(SISSR, 0x15, 0x04); /* Test */
4301 sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
4302 if(buswidth == 4) sr14 |= 0x80;
4303 else if(buswidth == 2) sr14 |= 0x40;
4304 outSISIDXREG(SISSR, 0x13, SiS_DRAMType[k][4]);
4305 outSISIDXREG(SISSR, 0x14, sr14);
4310 if((BankNumHigh + PhysicalAdrHigh >= mapsize) ||
4311 (BankNumMid + PhysicalAdrHigh >= mapsize) ||
4312 (BankNumHigh + PhysicalAdrHalfPage >= mapsize) ||
4313 (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
4317 writew(((unsigned short)PhysicalAdrHigh),
4318 (FBAddr + BankNumHigh + PhysicalAdrHigh));
4319 writew(((unsigned short)BankNumMid),
4320 (FBAddr + BankNumMid + PhysicalAdrHigh));
4321 writew(((unsigned short)PhysicalAdrHalfPage),
4322 (FBAddr + BankNumHigh + PhysicalAdrHalfPage));
4323 writew(((unsigned short)PhysicalAdrOtherPage),
4324 (FBAddr + BankNumHigh + PhysicalAdrOtherPage));
4327 if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
4334 static void __devinit
4335 sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
4337 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4339 int PseudoRankCapacity, PseudoAdrPinCount;
4341 buswidth = sisfb_post_300_buswidth(ivideo);
4343 for(i = 6; i >= 0; i--) {
4344 PseudoRankCapacity = 1 << i;
4345 for(j = 4; j >= 1; j--) {
4346 PseudoAdrPinCount = 15 - j;
4347 if((PseudoRankCapacity * j) <= 64) {
4348 if(sisfb_post_300_rwtest(ivideo,
4360 static void __devinit
4361 sisfb_post_sis300(struct pci_dev *pdev)
4363 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4364 unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
4365 u8 reg, v1, v2, v3, v4, v5, v6, v7, v8;
4366 u16 index, rindex, memtype = 0;
4367 unsigned int mapsize;
4369 if(!ivideo->SiS_Pr.UseROM)
4372 outSISIDXREG(SISSR, 0x05, 0x86);
4375 if(bios[0x52] & 0x80) {
4376 memtype = bios[0x52];
4378 inSISIDXREG(SISSR, 0x3a, memtype);
4383 v3 = 0x80; v6 = 0x80;
4384 if(ivideo->revision_id <= 0x13) {
4385 v1 = 0x44; v2 = 0x42;
4386 v4 = 0x44; v5 = 0x42;
4388 v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */
4389 v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */
4391 index = memtype * 5;
4392 rindex = index + 0x54;
4393 v1 = bios[rindex++];
4394 v2 = bios[rindex++];
4395 v3 = bios[rindex++];
4396 rindex = index + 0x7c;
4397 v4 = bios[rindex++];
4398 v5 = bios[rindex++];
4399 v6 = bios[rindex++];
4402 outSISIDXREG(SISSR, 0x28, v1);
4403 outSISIDXREG(SISSR, 0x29, v2);
4404 outSISIDXREG(SISSR, 0x2a, v3);
4405 outSISIDXREG(SISSR, 0x2e, v4);
4406 outSISIDXREG(SISSR, 0x2f, v5);
4407 outSISIDXREG(SISSR, 0x30, v6);
4412 outSISIDXREG(SISSR, 0x07, v1); /* DAC speed */
4414 outSISIDXREG(SISSR, 0x11, 0x0f); /* DDC, power save */
4416 v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
4417 v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
4421 v2 = bios[memtype + 8];
4422 v3 = bios[memtype + 16];
4423 v4 = bios[memtype + 24];
4424 v5 = bios[memtype + 32];
4425 v6 = bios[memtype + 40];
4426 v7 = bios[memtype + 48];
4427 v8 = bios[memtype + 56];
4429 if(ivideo->revision_id >= 0x80)
4431 outSISIDXREG(SISSR, 0x15, v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4432 outSISIDXREG(SISSR, 0x16, v2);
4433 outSISIDXREG(SISSR, 0x17, v3);
4434 outSISIDXREG(SISSR, 0x18, v4);
4435 outSISIDXREG(SISSR, 0x19, v5);
4436 outSISIDXREG(SISSR, 0x1a, v6);
4437 outSISIDXREG(SISSR, 0x1b, v7);
4438 outSISIDXREG(SISSR, 0x1c, v8); /* ---- */
4439 andSISIDXREG(SISSR, 0x15 ,0xfb);
4440 orSISIDXREG(SISSR, 0x15, 0x04);
4442 if(bios[0x53] & 0x02) {
4443 orSISIDXREG(SISSR, 0x19, 0x20);
4446 v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */
4447 if(ivideo->revision_id >= 0x80)
4449 outSISIDXREG(SISSR, 0x1f, v1);
4450 outSISIDXREG(SISSR, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
4451 v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
4457 outSISIDXREG(SISSR, 0x23, v1);
4458 outSISIDXREG(SISSR, 0x24, v2);
4459 outSISIDXREG(SISSR, 0x25, v3);
4460 outSISIDXREG(SISSR, 0x21, 0x84);
4461 outSISIDXREG(SISSR, 0x22, 0x00);
4462 outSISIDXREG(SISCR, 0x37, 0x00);
4463 orSISIDXREG(SISPART1, 0x24, 0x01); /* unlock crt2 */
4464 outSISIDXREG(SISPART1, 0x00, 0x00);
4465 v1 = 0x40; v2 = 0x11;
4470 outSISIDXREG(SISPART1, 0x02, v1);
4472 if(ivideo->revision_id >= 0x80)
4475 inSISIDXREG(SISPART4, 0x00, reg);
4476 if((reg == 1) || (reg == 2)) {
4477 outSISIDXREG(SISCR, 0x37, 0x02);
4478 outSISIDXREG(SISPART2, 0x00, 0x1c);
4479 v4 = 0x00; v5 = 0x00; v6 = 0x10;
4480 if(ivideo->SiS_Pr.UseROM) {
4485 outSISIDXREG(SISPART4, 0x0d, v4);
4486 outSISIDXREG(SISPART4, 0x0e, v5);
4487 outSISIDXREG(SISPART4, 0x10, v6);
4488 outSISIDXREG(SISPART4, 0x0f, 0x3f);
4489 inSISIDXREG(SISPART4, 0x01, reg);
4491 inSISIDXREG(SISPART4, 0x23, reg);
4494 outSISIDXREG(SISPART4, 0x23, reg);
4499 outSISIDXREG(SISSR, 0x32, v2);
4501 andSISIDXREG(SISPART1, 0x24, 0xfe); /* Lock CRT2 */
4503 inSISIDXREG(SISSR, 0x16, reg);
4505 outSISIDXREG(SISCR, 0x35, reg);
4506 outSISIDXREG(SISCR, 0x83, 0x00);
4507 #if !defined(__i386__) && !defined(__x86_64__)
4508 if(sisfb_videoram) {
4509 outSISIDXREG(SISSR, 0x13, 0x28); /* ? */
4510 reg = ((sisfb_videoram >> 10) - 1) | 0x40;
4511 outSISIDXREG(SISSR, 0x14, reg);
4514 /* Need to map max FB size for finding out about RAM size */
4516 sisfb_post_map_vram(ivideo, &mapsize, 4);
4518 if(ivideo->video_vbase) {
4519 sisfb_post_300_ramsize(pdev, mapsize);
4520 iounmap(ivideo->video_vbase);
4523 "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4524 outSISIDXREG(SISSR, 0x13, 0x28); /* ? */
4525 outSISIDXREG(SISSR, 0x14, 0x47); /* 8MB, 64bit default */
4527 #if !defined(__i386__) && !defined(__x86_64__)
4534 inSISIDXREG(SISSR, 0x3a, reg);
4535 if((reg & 0x30) == 0x30) {
4536 v1 = 0x04; /* PCI */
4539 v1 = 0x14; /* AGP */
4543 outSISIDXREG(SISSR, 0x21, v1);
4544 outSISIDXREG(SISSR, 0x22, v2);
4547 sisfb_sense_crt1(ivideo);
4549 /* Set default mode, don't clear screen */
4550 ivideo->SiS_Pr.SiS_UseOEM = false;
4551 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
4552 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
4553 ivideo->curFSTN = ivideo->curDSTN = 0;
4554 ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
4555 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
4557 outSISIDXREG(SISSR, 0x05, 0x86);
4560 orSISIDXREG(SISSR, 0x01, 0x20);
4562 /* Save mode number in CR34 */
4563 outSISIDXREG(SISCR, 0x34, 0x2e);
4565 /* Let everyone know what the current mode is */
4566 ivideo->modeprechange = 0x2e;
4570 #ifdef CONFIG_FB_SIS_315
4572 static void __devinit
4573 sisfb_post_sis315330(struct pci_dev *pdev)
4579 static void __devinit
4580 sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
4585 for(i = 0; i <= (delay * 10 * 36); i++) {
4586 inSISIDXREG(SISSR, 0x05, reg);
4591 static int __devinit
4592 sisfb_find_host_bridge(struct sis_video_info *ivideo, struct pci_dev *mypdev,
4593 unsigned short pcivendor)
4595 struct pci_dev *pdev = NULL;
4596 unsigned short temp;
4599 while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) {
4600 temp = pdev->vendor;
4601 if(temp == pcivendor) {
4611 static int __devinit
4612 sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
4613 unsigned int enda, unsigned int mapsize)
4618 writel(0, ivideo->video_vbase);
4620 for(i = starta; i <= enda; i++) {
4623 writel(pos, ivideo->video_vbase + pos);
4626 sisfb_post_xgi_delay(ivideo, 150);
4628 if(readl(ivideo->video_vbase) != 0)
4631 for(i = starta; i <= enda; i++) {
4634 if(readl(ivideo->video_vbase + pos) != pos)
4643 static void __devinit
4644 sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
4646 unsigned int buswidth, ranksize, channelab, mapsize;
4649 static const u8 dramsr13[12 * 5] = {
4650 0x02, 0x0e, 0x0b, 0x80, 0x5d,
4651 0x02, 0x0e, 0x0a, 0x40, 0x59,
4652 0x02, 0x0d, 0x0b, 0x40, 0x4d,
4653 0x02, 0x0e, 0x09, 0x20, 0x55,
4654 0x02, 0x0d, 0x0a, 0x20, 0x49,
4655 0x02, 0x0c, 0x0b, 0x20, 0x3d,
4656 0x02, 0x0e, 0x08, 0x10, 0x51,
4657 0x02, 0x0d, 0x09, 0x10, 0x45,
4658 0x02, 0x0c, 0x0a, 0x10, 0x39,
4659 0x02, 0x0d, 0x08, 0x08, 0x41,
4660 0x02, 0x0c, 0x09, 0x08, 0x35,
4661 0x02, 0x0c, 0x08, 0x04, 0x31
4663 static const u8 dramsr13_4[4 * 5] = {
4664 0x02, 0x0d, 0x09, 0x40, 0x45,
4665 0x02, 0x0c, 0x09, 0x20, 0x35,
4666 0x02, 0x0c, 0x08, 0x10, 0x31,
4667 0x02, 0x0b, 0x08, 0x08, 0x21
4670 /* Enable linear mode, disable 0xa0000 address decoding */
4671 /* We disable a0000 address decoding, because
4672 * - if running on x86, if the card is disabled, it means
4673 * that another card is in the system. We don't want
4674 * to interphere with that primary card's textmode.
4675 * - if running on non-x86, there usually is no VGA window
4678 orSISIDXREG(SISSR, 0x20, (0x80 | 0x04));
4680 /* Need to map max FB size for finding out about RAM size */
4681 mapsize = 256 << 20;
4682 sisfb_post_map_vram(ivideo, &mapsize, 32);
4684 if(!ivideo->video_vbase) {
4685 printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
4686 outSISIDXREG(SISSR, 0x13, 0x35);
4687 outSISIDXREG(SISSR, 0x14, 0x41);
4692 /* Non-interleaving */
4693 outSISIDXREG(SISSR, 0x15, 0x00);
4695 outSISIDXREG(SISSR, 0x1c, 0x00);
4697 if(ivideo->chip == XGI_20) {
4700 inSISIDXREG(SISCR, 0x97, reg);
4701 if(!(reg & 0x01)) { /* Single 32/16 */
4703 outSISIDXREG(SISSR, 0x13, 0xb1);
4704 outSISIDXREG(SISSR, 0x14, 0x52);
4705 sisfb_post_xgi_delay(ivideo, 1);
4707 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4710 outSISIDXREG(SISSR, 0x13, 0x31);
4711 outSISIDXREG(SISSR, 0x14, 0x42);
4712 sisfb_post_xgi_delay(ivideo, 1);
4713 if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
4717 outSISIDXREG(SISSR, 0x13, 0xb1);
4718 outSISIDXREG(SISSR, 0x14, 0x41);
4719 sisfb_post_xgi_delay(ivideo, 1);
4721 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4724 outSISIDXREG(SISSR, 0x13, 0x31);
4725 } else { /* Dual 16/8 */
4727 outSISIDXREG(SISSR, 0x13, 0xb1);
4728 outSISIDXREG(SISSR, 0x14, 0x41);
4729 sisfb_post_xgi_delay(ivideo, 1);
4731 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4734 outSISIDXREG(SISSR, 0x13, 0x31);
4735 outSISIDXREG(SISSR, 0x14, 0x31);
4736 sisfb_post_xgi_delay(ivideo, 1);
4737 if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
4741 outSISIDXREG(SISSR, 0x13, 0xb1);
4742 outSISIDXREG(SISSR, 0x14, 0x30);
4743 sisfb_post_xgi_delay(ivideo, 1);
4745 if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
4748 outSISIDXREG(SISSR, 0x13, 0x31);
4751 } else { /* XGI_40 */
4753 inSISIDXREG(SISCR, 0x97, reg);
4755 inSISIDXREG(SISSR, 0x39, reg);
4759 if(reg & 0x01) { /* DDRII */
4761 if(ivideo->revision_id == 2) {
4763 outSISIDXREG(SISSR, 0x13, 0xa1);
4764 outSISIDXREG(SISSR, 0x14, 0x44);
4766 sisfb_post_xgi_delay(ivideo, 1);
4767 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4770 outSISIDXREG(SISSR, 0x13, 0x21);
4771 outSISIDXREG(SISSR, 0x14, 0x34);
4772 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4776 outSISIDXREG(SISSR, 0x13, 0xa1);
4777 outSISIDXREG(SISSR, 0x14, 0x40);
4779 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4782 outSISIDXREG(SISSR, 0x13, 0x21);
4783 outSISIDXREG(SISSR, 0x14, 0x30);
4786 outSISIDXREG(SISSR, 0x13, 0xa1);
4787 outSISIDXREG(SISSR, 0x14, 0x4c);
4789 sisfb_post_xgi_delay(ivideo, 1);
4790 if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
4794 outSISIDXREG(SISSR, 0x14, 0x48);
4795 sisfb_post_xgi_delay(ivideo, 1);
4797 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4800 outSISIDXREG(SISSR, 0x13, 0x21);
4801 outSISIDXREG(SISSR, 0x14, 0x3c);
4804 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
4808 outSISIDXREG(SISSR, 0x14, 0x38);
4812 sisfb_post_xgi_delay(ivideo, 1);
4817 if(ivideo->revision_id == 2) {
4819 outSISIDXREG(SISSR, 0x13, 0xa1);
4820 outSISIDXREG(SISSR, 0x14, 0x52);
4821 sisfb_post_xgi_delay(ivideo, 1);
4823 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4826 outSISIDXREG(SISSR, 0x13, 0x21);
4827 outSISIDXREG(SISSR, 0x14, 0x42);
4830 outSISIDXREG(SISSR, 0x13, 0xa1);
4831 outSISIDXREG(SISSR, 0x14, 0x5a);
4832 sisfb_post_xgi_delay(ivideo, 1);
4834 if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
4837 outSISIDXREG(SISSR, 0x13, 0x21);
4838 outSISIDXREG(SISSR, 0x14, 0x4a);
4840 sisfb_post_xgi_delay(ivideo, 1);
4846 setSISIDXREG(SISSR, 0x14, 0xf0, sr14);
4847 sisfb_post_xgi_delay(ivideo, 1);
4849 j = (ivideo->chip == XGI_20) ? 5 : 9;
4850 k = (ivideo->chip == XGI_20) ? 12 : 4;
4852 for(i = 0; i < k; i++) {
4854 reg = (ivideo->chip == XGI_20) ?
4855 dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
4856 setSISIDXREG(SISSR, 0x13, 0x80, reg);
4857 sisfb_post_xgi_delay(ivideo, 50);
4859 ranksize = (ivideo->chip == XGI_20) ?
4860 dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
4862 inSISIDXREG(SISSR, 0x13, reg);
4863 if(reg & 0x80) ranksize <<= 1;
4865 if(ivideo->chip == XGI_20) {
4866 if(buswidth == 16) ranksize <<= 1;
4867 else if(buswidth == 32) ranksize <<= 2;
4869 if(buswidth == 64) ranksize <<= 1;
4875 if((ranksize * l) <= 256) {
4876 while((ranksize >>= 1)) reg += 0x10;
4881 setSISIDXREG(SISSR, 0x14, 0x0f, (reg & 0xf0));
4882 sisfb_post_xgi_delay(ivideo, 1);
4884 if(sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize))
4888 iounmap(ivideo->video_vbase);
4891 static void __devinit
4892 sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
4896 static const u8 cs90[8 * 3] = {
4906 static const u8 csb8[8 * 3] = {
4920 v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2];
4921 if(ivideo->haveXGIROM) {
4922 v1 = ivideo->bios_abase[0x90 + index];
4923 v2 = ivideo->bios_abase[0x90 + index + 1];
4924 v3 = ivideo->bios_abase[0x90 + index + 2];
4926 outSISIDXREG(SISSR, 0x28, v1);
4927 outSISIDXREG(SISSR, 0x29, v2);
4928 outSISIDXREG(SISSR, 0x2a, v3);
4929 sisfb_post_xgi_delay(ivideo, 0x43);
4930 sisfb_post_xgi_delay(ivideo, 0x43);
4931 sisfb_post_xgi_delay(ivideo, 0x43);
4933 v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2];
4934 if(ivideo->haveXGIROM) {
4935 v1 = ivideo->bios_abase[0xb8 + index];
4936 v2 = ivideo->bios_abase[0xb8 + index + 1];
4937 v3 = ivideo->bios_abase[0xb8 + index + 2];
4939 outSISIDXREG(SISSR, 0x2e, v1);
4940 outSISIDXREG(SISSR, 0x2f, v2);
4941 outSISIDXREG(SISSR, 0x30, v3);
4942 sisfb_post_xgi_delay(ivideo, 0x43);
4943 sisfb_post_xgi_delay(ivideo, 0x43);
4944 sisfb_post_xgi_delay(ivideo, 0x43);
4947 static int __devinit
4948 sisfb_post_xgi(struct pci_dev *pdev)
4950 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4951 unsigned char *bios = ivideo->bios_abase;
4952 struct pci_dev *mypdev = NULL;
4953 const u8 *ptr, *ptr2;
4954 u8 v1, v2, v3, v4, v5, reg, ramtype;
4955 u32 rega, regb, regd;
4957 static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 };
4958 static const u8 cs76[2] = { 0xa3, 0xfb };
4959 static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 };
4960 static const u8 cs158[8] = {
4961 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
4963 static const u8 cs160[8] = {
4964 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
4966 static const u8 cs168[8] = {
4967 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
4969 static const u8 cs128[3 * 8] = {
4970 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
4971 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
4972 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
4974 static const u8 cs148[2 * 8] = {
4975 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
4976 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4978 static const u8 cs31a[8 * 4] = {
4979 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
4980 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
4981 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4982 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4984 static const u8 cs33a[8 * 4] = {
4985 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4986 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4987 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4988 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4990 static const u8 cs45a[8 * 2] = {
4991 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
4992 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4994 static const u8 cs170[7 * 8] = {
4995 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
4996 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
4997 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
4998 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
4999 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5000 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5001 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5003 static const u8 cs1a8[3 * 8] = {
5004 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5005 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5006 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5008 static const u8 cs100[2 * 8] = {
5009 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5010 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5014 reg = inSISREG(SISVGAENABLE) | 0x01;
5015 outSISREG(SISVGAENABLE, reg);
5018 reg = inSISREG(SISMISCR) | 0x01;
5019 outSISREG(SISMISCW, reg);
5022 outSISIDXREG(SISSR, 0x05, 0x86);
5023 inSISIDXREG(SISSR, 0x05, reg);
5027 /* Clear some regs */
5028 for(i = 0; i < 0x22; i++) {
5029 if(0x06 + i == 0x20) continue;
5030 outSISIDXREG(SISSR, 0x06 + i, 0x00);
5032 for(i = 0; i < 0x0b; i++) {
5033 outSISIDXREG(SISSR, 0x31 + i, 0x00);
5035 for(i = 0; i < 0x10; i++) {
5036 outSISIDXREG(SISCR, 0x30 + i, 0x00);
5040 if(ivideo->haveXGIROM) {
5041 ptr = (const u8 *)&bios[0x78];
5043 for(i = 0; i < 3; i++) {
5044 outSISIDXREG(SISSR, 0x23 + i, ptr[i]);
5048 if(ivideo->haveXGIROM) {
5049 ptr = (const u8 *)&bios[0x76];
5051 for(i = 0; i < 2; i++) {
5052 outSISIDXREG(SISSR, 0x21 + i, ptr[i]);
5055 v1 = 0x18; v2 = 0x00;
5056 if(ivideo->haveXGIROM) {
5060 outSISIDXREG(SISSR, 0x07, v1);
5061 outSISIDXREG(SISSR, 0x11, 0x0f);
5062 outSISIDXREG(SISSR, 0x1f, v2);
5063 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5064 outSISIDXREG(SISSR, 0x20, 0x80 | 0x20 | 0x04);
5065 outSISIDXREG(SISSR, 0x27, 0x74);
5068 if(ivideo->haveXGIROM) {
5069 ptr = (const u8 *)&bios[0x7b];
5071 for(i = 0; i < 3; i++) {
5072 outSISIDXREG(SISSR, 0x31 + i, ptr[i]);
5075 if(ivideo->chip == XGI_40) {
5076 if(ivideo->revision_id == 2) {
5077 setSISIDXREG(SISSR, 0x3b, 0x3f, 0xc0);
5079 outSISIDXREG(SISCR, 0x7d, 0xfe);
5080 outSISIDXREG(SISCR, 0x7e, 0x0f);
5082 if(ivideo->revision_id == 0) { /* 40 *and* 20? */
5083 andSISIDXREG(SISCR, 0x58, 0xd7);
5084 inSISIDXREG(SISCR, 0xcb, reg);
5086 setSISIDXREG(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5090 reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
5091 setSISIDXREG(SISCR, 0x38, 0x1f, reg);
5093 if(ivideo->chip == XGI_20) {
5094 outSISIDXREG(SISSR, 0x36, 0x70);
5096 outSISIDXREG(SISVID, 0x00, 0x86);
5097 outSISIDXREG(SISVID, 0x32, 0x00);
5098 outSISIDXREG(SISVID, 0x30, 0x00);
5099 outSISIDXREG(SISVID, 0x32, 0x01);
5100 outSISIDXREG(SISVID, 0x30, 0x00);
5101 andSISIDXREG(SISVID, 0x2f, 0xdf);
5102 andSISIDXREG(SISCAP, 0x00, 0x3f);
5104 outSISIDXREG(SISPART1, 0x2f, 0x01);
5105 outSISIDXREG(SISPART1, 0x00, 0x00);
5106 outSISIDXREG(SISPART1, 0x02, bios[0x7e]);
5107 outSISIDXREG(SISPART1, 0x2e, 0x08);
5108 andSISIDXREG(SISPART1, 0x35, 0x7f);
5109 andSISIDXREG(SISPART1, 0x50, 0xfe);
5111 inSISIDXREG(SISPART4, 0x00, reg);
5112 if(reg == 1 || reg == 2) {
5113 outSISIDXREG(SISPART2, 0x00, 0x1c);
5114 outSISIDXREG(SISPART4, 0x0d, bios[0x7f]);
5115 outSISIDXREG(SISPART4, 0x0e, bios[0x80]);
5116 outSISIDXREG(SISPART4, 0x10, bios[0x81]);
5117 andSISIDXREG(SISPART4, 0x0f, 0x3f);
5119 inSISIDXREG(SISPART4, 0x01, reg);
5120 if((reg & 0xf0) >= 0xb0) {
5121 inSISIDXREG(SISPART4, 0x23, reg);
5122 if(reg & 0x20) reg |= 0x40;
5123 outSISIDXREG(SISPART4, 0x23, reg);
5124 reg = (reg & 0x20) ? 0x02 : 0x00;
5125 setSISIDXREG(SISPART1, 0x1e, 0xfd, reg);
5131 inSISIDXREG(SISSR, 0x3b, reg);
5133 inSISIDXREG(SISSR, 0x3a, reg);
5134 v2 = (reg & 0x30) >> 3;
5135 if(!(v2 & 0x04)) v2 ^= 0x02;
5136 inSISIDXREG(SISSR, 0x39, reg);
5137 if(reg & 0x80) v2 |= 0x80;
5140 if((mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
5141 pci_dev_put(mypdev);
5142 if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
5147 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0735, NULL);
5149 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0645, NULL);
5151 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0650, NULL);
5153 pci_read_config_dword(mypdev, 0x94, ®d);
5155 pci_write_config_dword(mypdev, 0x94, regd);
5157 pci_dev_put(mypdev);
5158 } else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) {
5160 } else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) ||
5161 sisfb_find_host_bridge(ivideo, pdev, 0x1022) ||
5162 sisfb_find_host_bridge(ivideo, pdev, 0x700e) ||
5163 sisfb_find_host_bridge(ivideo, pdev, 0x10de)) {
5164 if((v2 & 0x06) == 4)
5169 setSISIDXREG(SISCR, 0x5f, 0xf0, v2);
5171 outSISIDXREG(SISSR, 0x22, v1);
5173 if(ivideo->revision_id == 2) {
5174 inSISIDXREG(SISSR, 0x3b, v1);
5175 inSISIDXREG(SISSR, 0x3a, v2);
5176 regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
5177 if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
5178 setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01);
5180 if((mypdev = pci_get_device(0x10de, 0x01e0, NULL))) {
5181 /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5185 setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01);
5186 pci_dev_put(mypdev);
5191 inSISIDXREG(SISSR, 0x3b, reg);
5192 inSISIDXREG(SISCR, 0x5f, v2);
5193 if((!(reg & 0x02)) && (v2 & 0x0e))
5195 outSISIDXREG(SISSR, 0x27, v1);
5197 if(bios[0x64] & 0x01) {
5198 setSISIDXREG(SISCR, 0x5f, 0xf0, bios[0x64]);
5202 pci_read_config_dword(pdev, 0x50, ®d);
5203 regd = (regd >> 20) & 0x0f;
5206 orSISIDXREG(SISCR, 0x5f, 0x08);
5208 outSISIDXREG(SISCR, 0x48, v1);
5210 setSISIDXREG(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
5211 setSISIDXREG(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
5212 setSISIDXREG(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
5213 setSISIDXREG(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
5214 setSISIDXREG(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
5215 outSISIDXREG(SISCR, 0x70, bios[0x4fc]);
5216 setSISIDXREG(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
5217 outSISIDXREG(SISCR, 0x74, 0xd0);
5218 setSISIDXREG(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
5219 setSISIDXREG(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
5220 setSISIDXREG(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
5222 if((mypdev = pci_get_device(0x8086, 0x2530, NULL))) {
5224 pci_dev_put(mypdev);
5226 outSISIDXREG(SISCR, 0x77, v1);
5234 if(ivideo->haveXGIROM) {
5235 v1 = bios[0x140 + regb];
5237 outSISIDXREG(SISCR, 0x6d, v1);
5240 if(ivideo->haveXGIROM) {
5241 ptr = (const u8 *)&bios[0x128];
5243 for(i = 0, j = 0; i < 3; i++, j += 8) {
5244 outSISIDXREG(SISCR, 0x68 + i, ptr[j + regb]);
5249 if(ivideo->haveXGIROM) {
5250 index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6;
5251 ptr = (const u8 *)&bios[index];
5252 ptr2 = (const u8 *)&bios[index + 0x20];
5254 for(i = 0; i < 2; i++) {
5256 regd = le32_to_cpu(((u32 *)ptr)[regb]);
5259 regd = le32_to_cpu(((u32 *)ptr2)[regb]);
5263 for(j = 0; j < 16; j++) {
5265 if(regd & 0x01) reg |= 0x04;
5266 if(regd & 0x02) reg |= 0x08;
5268 outSISIDXREG(SISCR, rega, reg);
5269 inSISIDXREG(SISCR, rega, reg);
5270 inSISIDXREG(SISCR, rega, reg);
5275 andSISIDXREG(SISCR, 0x6e, 0xfc);
5278 if(ivideo->haveXGIROM) {
5279 index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6;
5280 ptr = (const u8 *)&bios[index];
5282 for(i = 0; i < 4; i++) {
5283 setSISIDXREG(SISCR, 0x6e, 0xfc, i);
5285 for(j = 0; j < 2; j++) {
5288 regd = le32_to_cpu(((u32 *)ptr)[regb * 8]);
5292 for(k = 0; k < 16; k++) {
5294 if(regd & 0x01) reg |= 0x01;
5295 if(regd & 0x02) reg |= 0x02;
5297 outSISIDXREG(SISCR, 0x6f, reg);
5298 inSISIDXREG(SISCR, 0x6f, reg);
5299 inSISIDXREG(SISCR, 0x6f, reg);
5306 if(ivideo->haveXGIROM) {
5307 ptr = (const u8 *)&bios[0x148];
5309 for(i = 0, j = 0; i < 2; i++, j += 8) {
5310 outSISIDXREG(SISCR, 0x80 + i, ptr[j + regb]);
5313 andSISIDXREG(SISCR, 0x89, 0x8f);
5316 if(ivideo->haveXGIROM) {
5317 index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6;
5318 ptr = (const u8 *)&bios[index];
5320 regd = le16_to_cpu(((const u16 *)ptr)[regb]);
5322 for(i = 0; i < 5; i++) {
5324 if(regd & 0x01) reg |= 0x01;
5325 if(regd & 0x02) reg |= 0x02;
5327 outSISIDXREG(SISCR, 0x89, reg);
5328 inSISIDXREG(SISCR, 0x89, reg);
5329 inSISIDXREG(SISCR, 0x89, reg);
5333 v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13;
5334 if(ivideo->haveXGIROM) {
5335 v1 = bios[0x118 + regb];
5336 v2 = bios[0xf8 + regb];
5337 v3 = bios[0x120 + regb];
5340 outSISIDXREG(SISCR, 0x45, v1 & 0x0f);
5341 outSISIDXREG(SISCR, 0x99, (v1 >> 4) & 0x07);
5342 orSISIDXREG(SISCR, 0x40, v1 & 0x80);
5343 outSISIDXREG(SISCR, 0x41, v2);
5346 if(ivideo->haveXGIROM) {
5347 ptr = (const u8 *)&bios[0x170];
5349 for(i = 0, j = 0; i < 7; i++, j += 8) {
5350 outSISIDXREG(SISCR, 0x90 + i, ptr[j + regb]);
5353 outSISIDXREG(SISCR, 0x59, v3);
5356 if(ivideo->haveXGIROM) {
5357 ptr = (const u8 *)&bios[0x1a8];
5359 for(i = 0, j = 0; i < 3; i++, j += 8) {
5360 outSISIDXREG(SISCR, 0xc3 + i, ptr[j + regb]);
5364 if(ivideo->haveXGIROM) {
5365 ptr = (const u8 *)&bios[0x100];
5367 for(i = 0, j = 0; i < 2; i++, j += 8) {
5368 outSISIDXREG(SISCR, 0x8a + i, ptr[j + regb]);
5371 outSISIDXREG(SISCR, 0xcf, v4);
5373 outSISIDXREG(SISCR, 0x83, 0x09);
5374 outSISIDXREG(SISCR, 0x87, 0x00);
5376 if(ivideo->chip == XGI_40) {
5377 if( (ivideo->revision_id == 1) ||
5378 (ivideo->revision_id == 2) ) {
5379 outSISIDXREG(SISCR, 0x8c, 0x87);
5383 outSISIDXREG(SISSR, 0x17, 0x00);
5384 outSISIDXREG(SISSR, 0x1a, 0x87);
5386 if(ivideo->chip == XGI_20) {
5387 outSISIDXREG(SISSR, 0x15, 0x00);
5388 outSISIDXREG(SISSR, 0x1c, 0x00);
5391 ramtype = 0x00; v1 = 0x10;
5392 if(ivideo->haveXGIROM) {
5393 ramtype = bios[0x62];
5396 if(!(ramtype & 0x80)) {
5397 if(ivideo->chip == XGI_20) {
5398 outSISIDXREG(SISCR, 0x97, v1);
5399 inSISIDXREG(SISCR, 0x97, reg);
5401 ramtype = (reg & 0x01) << 1;
5404 inSISIDXREG(SISSR, 0x39, reg);
5405 ramtype = reg & 0x02;
5407 inSISIDXREG(SISSR, 0x3a, reg);
5408 ramtype = (reg >> 1) & 0x01;
5418 sisfb_post_xgi_setclocks(ivideo, regb);
5419 if((ivideo->chip == XGI_20) ||
5420 (ivideo->revision_id == 1) ||
5421 (ivideo->revision_id == 2)) {
5422 v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb];
5423 if(ivideo->haveXGIROM) {
5424 v1 = bios[regb + 0x158];
5425 v2 = bios[regb + 0x160];
5426 v3 = bios[regb + 0x168];
5428 outSISIDXREG(SISCR, 0x82, v1);
5429 outSISIDXREG(SISCR, 0x85, v2);
5430 outSISIDXREG(SISCR, 0x86, v3);
5432 outSISIDXREG(SISCR, 0x82, 0x88);
5433 outSISIDXREG(SISCR, 0x86, 0x00);
5434 inSISIDXREG(SISCR, 0x86, reg);
5435 outSISIDXREG(SISCR, 0x86, 0x88);
5436 inSISIDXREG(SISCR, 0x86, reg);
5437 outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]);
5438 outSISIDXREG(SISCR, 0x82, 0x77);
5439 outSISIDXREG(SISCR, 0x85, 0x00);
5440 inSISIDXREG(SISCR, 0x85, reg);
5441 outSISIDXREG(SISCR, 0x85, 0x88);
5442 inSISIDXREG(SISCR, 0x85, reg);
5443 outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]);
5444 outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]);
5446 if(ivideo->chip == XGI_40) {
5447 outSISIDXREG(SISCR, 0x97, 0x00);
5449 outSISIDXREG(SISCR, 0x98, 0x01);
5450 outSISIDXREG(SISCR, 0x9a, 0x02);
5452 outSISIDXREG(SISSR, 0x18, 0x01);
5453 if((ivideo->chip == XGI_20) ||
5454 (ivideo->revision_id == 2)) {
5455 outSISIDXREG(SISSR, 0x19, 0x40);
5457 outSISIDXREG(SISSR, 0x19, 0x20);
5459 outSISIDXREG(SISSR, 0x16, 0x00);
5460 outSISIDXREG(SISSR, 0x16, 0x80);
5461 if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
5462 sisfb_post_xgi_delay(ivideo, 0x43);
5463 sisfb_post_xgi_delay(ivideo, 0x43);
5464 sisfb_post_xgi_delay(ivideo, 0x43);
5465 outSISIDXREG(SISSR, 0x18, 0x00);
5466 if((ivideo->chip == XGI_20) ||
5467 (ivideo->revision_id == 2)) {
5468 outSISIDXREG(SISSR, 0x19, 0x40);
5470 outSISIDXREG(SISSR, 0x19, 0x20);
5472 } else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
5473 /* outSISIDXREG(SISSR, 0x16, 0x0c); */ /* ? */
5475 outSISIDXREG(SISSR, 0x16, 0x00);
5476 outSISIDXREG(SISSR, 0x16, 0x80);
5477 sisfb_post_xgi_delay(ivideo, 4);
5478 v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
5479 if(ivideo->haveXGIROM) {
5481 index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e;
5483 v3 = bios[index + 1];
5484 v4 = bios[index + 2];
5485 v5 = bios[index + 3];
5487 outSISIDXREG(SISSR, 0x18, v1);
5488 outSISIDXREG(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
5489 outSISIDXREG(SISSR, 0x16, v2);
5490 outSISIDXREG(SISSR, 0x16, v3);
5491 sisfb_post_xgi_delay(ivideo, 0x43);
5492 outSISIDXREG(SISSR, 0x1b, 0x03);
5493 sisfb_post_xgi_delay(ivideo, 0x22);
5494 outSISIDXREG(SISSR, 0x18, v1);
5495 outSISIDXREG(SISSR, 0x19, 0x00);
5496 outSISIDXREG(SISSR, 0x16, v4);
5497 outSISIDXREG(SISSR, 0x16, v5);
5498 outSISIDXREG(SISSR, 0x1b, 0x00);
5501 outSISIDXREG(SISCR, 0x82, 0x77);
5502 outSISIDXREG(SISCR, 0x86, 0x00);
5503 inSISIDXREG(SISCR, 0x86, reg);
5504 outSISIDXREG(SISCR, 0x86, 0x88);
5505 inSISIDXREG(SISCR, 0x86, reg);
5506 v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
5507 if(ivideo->haveXGIROM) {
5508 v1 = bios[regb + 0x168];
5509 v2 = bios[regb + 0x160];
5510 v3 = bios[regb + 0x158];
5512 outSISIDXREG(SISCR, 0x86, v1);
5513 outSISIDXREG(SISCR, 0x82, 0x77);
5514 outSISIDXREG(SISCR, 0x85, 0x00);
5515 inSISIDXREG(SISCR, 0x85, reg);
5516 outSISIDXREG(SISCR, 0x85, 0x88);
5517 inSISIDXREG(SISCR, 0x85, reg);
5518 outSISIDXREG(SISCR, 0x85, v2);
5519 outSISIDXREG(SISCR, 0x82, v3);
5520 outSISIDXREG(SISCR, 0x98, 0x01);
5521 outSISIDXREG(SISCR, 0x9a, 0x02);
5523 outSISIDXREG(SISSR, 0x28, 0x64);
5524 outSISIDXREG(SISSR, 0x29, 0x63);
5525 sisfb_post_xgi_delay(ivideo, 15);
5526 outSISIDXREG(SISSR, 0x18, 0x00);
5527 outSISIDXREG(SISSR, 0x19, 0x20);
5528 outSISIDXREG(SISSR, 0x16, 0x00);
5529 outSISIDXREG(SISSR, 0x16, 0x80);
5530 outSISIDXREG(SISSR, 0x18, 0xc5);
5531 outSISIDXREG(SISSR, 0x19, 0x23);
5532 outSISIDXREG(SISSR, 0x16, 0x00);
5533 outSISIDXREG(SISSR, 0x16, 0x80);
5534 sisfb_post_xgi_delay(ivideo, 1);
5535 outSISIDXREG(SISCR, 0x97,0x11);
5536 sisfb_post_xgi_setclocks(ivideo, regb);
5537 sisfb_post_xgi_delay(ivideo, 0x46);
5538 outSISIDXREG(SISSR, 0x18, 0xc5);
5539 outSISIDXREG(SISSR, 0x19, 0x23);
5540 outSISIDXREG(SISSR, 0x16, 0x00);
5541 outSISIDXREG(SISSR, 0x16, 0x80);
5542 sisfb_post_xgi_delay(ivideo, 1);
5543 outSISIDXREG(SISSR, 0x1b, 0x04);
5544 sisfb_post_xgi_delay(ivideo, 1);
5545 outSISIDXREG(SISSR, 0x1b, 0x00);
5546 sisfb_post_xgi_delay(ivideo, 1);
5548 if(ivideo->haveXGIROM) {
5551 outSISIDXREG(SISSR, 0x18, v1);
5552 outSISIDXREG(SISSR, 0x19, 0x06);
5553 outSISIDXREG(SISSR, 0x16, 0x04);
5554 outSISIDXREG(SISSR, 0x16, 0x84);
5555 sisfb_post_xgi_delay(ivideo, 1);
5558 sisfb_post_xgi_setclocks(ivideo, regb);
5559 if((ivideo->chip == XGI_40) &&
5560 ((ivideo->revision_id == 1) ||
5561 (ivideo->revision_id == 2))) {
5562 outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]);
5563 outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]);
5564 outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]);
5566 outSISIDXREG(SISCR, 0x82, 0x88);
5567 outSISIDXREG(SISCR, 0x86, 0x00);
5568 inSISIDXREG(SISCR, 0x86, reg);
5569 outSISIDXREG(SISCR, 0x86, 0x88);
5570 outSISIDXREG(SISCR, 0x82, 0x77);
5571 outSISIDXREG(SISCR, 0x85, 0x00);
5572 inSISIDXREG(SISCR, 0x85, reg);
5573 outSISIDXREG(SISCR, 0x85, 0x88);
5574 inSISIDXREG(SISCR, 0x85, reg);
5575 v1 = cs160[regb]; v2 = cs158[regb];
5576 if(ivideo->haveXGIROM) {
5577 v1 = bios[regb + 0x160];
5578 v2 = bios[regb + 0x158];
5580 outSISIDXREG(SISCR, 0x85, v1);
5581 outSISIDXREG(SISCR, 0x82, v2);
5583 if(ivideo->chip == XGI_40) {
5584 outSISIDXREG(SISCR, 0x97, 0x11);
5586 if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
5587 outSISIDXREG(SISCR, 0x98, 0x01);
5589 outSISIDXREG(SISCR, 0x98, 0x03);
5591 outSISIDXREG(SISCR, 0x9a, 0x02);
5593 if(ivideo->chip == XGI_40) {
5594 outSISIDXREG(SISSR, 0x18, 0x01);
5596 outSISIDXREG(SISSR, 0x18, 0x00);
5598 outSISIDXREG(SISSR, 0x19, 0x40);
5599 outSISIDXREG(SISSR, 0x16, 0x00);
5600 outSISIDXREG(SISSR, 0x16, 0x80);
5601 if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
5602 sisfb_post_xgi_delay(ivideo, 0x43);
5603 sisfb_post_xgi_delay(ivideo, 0x43);
5604 sisfb_post_xgi_delay(ivideo, 0x43);
5605 outSISIDXREG(SISSR, 0x18, 0x00);
5606 outSISIDXREG(SISSR, 0x19, 0x40);
5607 outSISIDXREG(SISSR, 0x16, 0x00);
5608 outSISIDXREG(SISSR, 0x16, 0x80);
5610 sisfb_post_xgi_delay(ivideo, 4);
5612 if(ivideo->haveXGIROM) {
5615 outSISIDXREG(SISSR, 0x18, v1);
5616 outSISIDXREG(SISSR, 0x19, 0x01);
5617 if(ivideo->chip == XGI_40) {
5618 outSISIDXREG(SISSR, 0x16, bios[0x53e]);
5619 outSISIDXREG(SISSR, 0x16, bios[0x53f]);
5621 outSISIDXREG(SISSR, 0x16, 0x05);
5622 outSISIDXREG(SISSR, 0x16, 0x85);
5624 sisfb_post_xgi_delay(ivideo, 0x43);
5625 if(ivideo->chip == XGI_40) {
5626 outSISIDXREG(SISSR, 0x1b, 0x01);
5628 outSISIDXREG(SISSR, 0x1b, 0x03);
5630 sisfb_post_xgi_delay(ivideo, 0x22);
5631 outSISIDXREG(SISSR, 0x18, v1);
5632 outSISIDXREG(SISSR, 0x19, 0x00);
5633 if(ivideo->chip == XGI_40) {
5634 outSISIDXREG(SISSR, 0x16, bios[0x540]);
5635 outSISIDXREG(SISSR, 0x16, bios[0x541]);
5637 outSISIDXREG(SISSR, 0x16, 0x05);
5638 outSISIDXREG(SISSR, 0x16, 0x85);
5640 outSISIDXREG(SISSR, 0x1b, 0x00);
5645 if(ivideo->haveXGIROM) {
5646 v1 = bios[0x110 + regb];
5648 outSISIDXREG(SISSR, 0x1b, v1);
5651 v1 = 0x00; v2 = 0x00;
5652 if(ivideo->haveXGIROM) {
5658 if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
5660 outSISIDXREG(SISSR, 0x13, bios[regb + 0xe0]);
5661 outSISIDXREG(SISSR, 0x14, bios[regb + 0xe0 + 8]);
5665 /* Set default mode, don't clear screen */
5666 ivideo->SiS_Pr.SiS_UseOEM = false;
5667 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
5668 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
5669 ivideo->curFSTN = ivideo->curDSTN = 0;
5670 ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
5671 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5673 outSISIDXREG(SISSR, 0x05, 0x86);
5675 /* Disable read-cache */
5676 andSISIDXREG(SISSR, 0x21, 0xdf);
5677 sisfb_post_xgi_ramsize(ivideo);
5678 /* Enable read-cache */
5679 orSISIDXREG(SISSR, 0x21, 0x20);
5684 printk(KERN_DEBUG "-----------------\n");
5685 for(i = 0; i < 0xff; i++) {
5686 inSISIDXREG(SISCR, i, reg);
5687 printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
5689 for(i = 0; i < 0x40; i++) {
5690 inSISIDXREG(SISSR, i, reg);
5691 printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
5693 printk(KERN_DEBUG "-----------------\n");
5697 if(ivideo->chip == XGI_20) {
5698 orSISIDXREG(SISCR, 0x32, 0x20);
5700 inSISIDXREG(SISPART4, 0x00, reg);
5701 if((reg == 1) || (reg == 2)) {
5702 sisfb_sense_crt1(ivideo);
5704 orSISIDXREG(SISCR, 0x32, 0x20);
5708 /* Set default mode, don't clear screen */
5709 ivideo->SiS_Pr.SiS_UseOEM = false;
5710 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
5711 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
5712 ivideo->curFSTN = ivideo->curDSTN = 0;
5713 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5715 outSISIDXREG(SISSR, 0x05, 0x86);
5718 orSISIDXREG(SISSR, 0x01, 0x20);
5720 /* Save mode number in CR34 */
5721 outSISIDXREG(SISCR, 0x34, 0x2e);
5723 /* Let everyone know what the current mode is */
5724 ivideo->modeprechange = 0x2e;
5726 if(ivideo->chip == XGI_40) {
5727 inSISIDXREG(SISCR, 0xca, reg);
5728 inSISIDXREG(SISCR, 0xcc, v1);
5729 if((reg & 0x10) && (!(v1 & 0x04))) {
5731 "sisfb: Please connect power to the card.\n");
5740 static int __devinit
5741 sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
5743 struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data];
5744 struct sis_video_info *ivideo = NULL;
5745 struct fb_info *sis_fb_info = NULL;
5753 sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
5757 ivideo = (struct sis_video_info *)sis_fb_info->par;
5758 ivideo->memyselfandi = sis_fb_info;
5760 ivideo->sisfb_id = SISFB_ID;
5762 if(card_list == NULL) {
5763 ivideo->cardnumber = 0;
5765 struct sis_video_info *countvideo = card_list;
5766 ivideo->cardnumber = 1;
5767 while((countvideo = countvideo->next) != NULL)
5768 ivideo->cardnumber++;
5771 strncpy(ivideo->myid, chipinfo->chip_name, 30);
5773 ivideo->warncount = 0;
5774 ivideo->chip_id = pdev->device;
5775 ivideo->chip_vendor = pdev->vendor;
5776 ivideo->revision_id = pdev->revision;
5777 ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
5778 pci_read_config_word(pdev, PCI_COMMAND, ®16);
5779 ivideo->sisvga_enabled = reg16 & 0x01;
5780 ivideo->pcibus = pdev->bus->number;
5781 ivideo->pcislot = PCI_SLOT(pdev->devfn);
5782 ivideo->pcifunc = PCI_FUNC(pdev->devfn);
5783 ivideo->subsysvendor = pdev->subsystem_vendor;
5784 ivideo->subsysdevice = pdev->subsystem_device;
5787 if(sisfb_mode_idx == -1) {
5788 sisfb_get_vga_mode_from_kernel();
5792 ivideo->chip = chipinfo->chip;
5793 ivideo->sisvga_engine = chipinfo->vgaengine;
5794 ivideo->hwcursor_size = chipinfo->hwcursor_size;
5795 ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
5796 ivideo->mni = chipinfo->mni;
5798 ivideo->detectedpdc = 0xff;
5799 ivideo->detectedpdca = 0xff;
5800 ivideo->detectedlcda = 0xff;
5802 ivideo->sisfb_thismonitor.datavalid = false;
5804 ivideo->current_base = 0;
5806 ivideo->engineok = 0;
5808 ivideo->sisfb_was_boot_device = 0;
5810 if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
5811 if(ivideo->sisvga_enabled)
5812 ivideo->sisfb_was_boot_device = 1;
5814 printk(KERN_DEBUG "sisfb: PCI device is disabled, "
5815 "but marked as boot video device ???\n");
5816 printk(KERN_DEBUG "sisfb: I will not accept this "
5817 "as the primary VGA device\n");
5821 ivideo->sisfb_parm_mem = sisfb_parm_mem;
5822 ivideo->sisfb_accel = sisfb_accel;
5823 ivideo->sisfb_ypan = sisfb_ypan;
5824 ivideo->sisfb_max = sisfb_max;
5825 ivideo->sisfb_userom = sisfb_userom;
5826 ivideo->sisfb_useoem = sisfb_useoem;
5827 ivideo->sisfb_mode_idx = sisfb_mode_idx;
5828 ivideo->sisfb_parm_rate = sisfb_parm_rate;
5829 ivideo->sisfb_crt1off = sisfb_crt1off;
5830 ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
5831 ivideo->sisfb_crt2type = sisfb_crt2type;
5832 ivideo->sisfb_crt2flags = sisfb_crt2flags;
5833 /* pdc(a), scalelcd, special timing, lvdshl handled below */
5834 ivideo->sisfb_dstn = sisfb_dstn;
5835 ivideo->sisfb_fstn = sisfb_fstn;
5836 ivideo->sisfb_tvplug = sisfb_tvplug;
5837 ivideo->sisfb_tvstd = sisfb_tvstd;
5838 ivideo->tvxpos = sisfb_tvxposoffset;
5839 ivideo->tvypos = sisfb_tvyposoffset;
5840 ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
5841 ivideo->refresh_rate = 0;
5842 if(ivideo->sisfb_parm_rate != -1) {
5843 ivideo->refresh_rate = ivideo->sisfb_parm_rate;
5846 ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
5847 ivideo->SiS_Pr.CenterScreen = -1;
5848 ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
5849 ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
5851 ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
5852 ivideo->SiS_Pr.SiS_CHOverScan = -1;
5853 ivideo->SiS_Pr.SiS_ChSW = false;
5854 ivideo->SiS_Pr.SiS_UseLCDA = false;
5855 ivideo->SiS_Pr.HaveEMI = false;
5856 ivideo->SiS_Pr.HaveEMILCD = false;
5857 ivideo->SiS_Pr.OverruleEMI = false;
5858 ivideo->SiS_Pr.SiS_SensibleSR11 = false;
5859 ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
5860 ivideo->SiS_Pr.PDC = -1;
5861 ivideo->SiS_Pr.PDCA = -1;
5862 ivideo->SiS_Pr.DDCPortMixup = false;
5863 #ifdef CONFIG_FB_SIS_315
5864 if(ivideo->chip >= SIS_330) {
5865 ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
5866 if(ivideo->chip >= SIS_661) {
5867 ivideo->SiS_Pr.SiS_SensibleSR11 = true;
5872 memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));
5874 pci_set_drvdata(pdev, ivideo);
5876 /* Patch special cases */
5877 if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) {
5878 switch(ivideo->nbridge->device) {
5879 #ifdef CONFIG_FB_SIS_300
5880 case PCI_DEVICE_ID_SI_730:
5881 ivideo->chip = SIS_730;
5882 strcpy(ivideo->myid, "SiS 730");
5885 #ifdef CONFIG_FB_SIS_315
5886 case PCI_DEVICE_ID_SI_651:
5887 /* ivideo->chip is ok */
5888 strcpy(ivideo->myid, "SiS 651");
5890 case PCI_DEVICE_ID_SI_740:
5891 ivideo->chip = SIS_740;
5892 strcpy(ivideo->myid, "SiS 740");
5894 case PCI_DEVICE_ID_SI_661:
5895 ivideo->chip = SIS_661;
5896 strcpy(ivideo->myid, "SiS 661");
5898 case PCI_DEVICE_ID_SI_741:
5899 ivideo->chip = SIS_741;
5900 strcpy(ivideo->myid, "SiS 741");
5902 case PCI_DEVICE_ID_SI_760:
5903 ivideo->chip = SIS_760;
5904 strcpy(ivideo->myid, "SiS 760");
5906 case PCI_DEVICE_ID_SI_761:
5907 ivideo->chip = SIS_761;
5908 strcpy(ivideo->myid, "SiS 761");
5916 ivideo->SiS_Pr.ChipType = ivideo->chip;
5918 ivideo->SiS_Pr.ivideo = (void *)ivideo;
5920 #ifdef CONFIG_FB_SIS_315
5921 if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
5922 (ivideo->SiS_Pr.ChipType == SIS_315)) {
5923 ivideo->SiS_Pr.ChipType = SIS_315H;
5927 if(!ivideo->sisvga_enabled) {
5928 if(pci_enable_device(pdev)) {
5929 if(ivideo->nbridge) pci_dev_put(ivideo->nbridge);
5930 pci_set_drvdata(pdev, NULL);
5936 ivideo->video_base = pci_resource_start(pdev, 0);
5937 ivideo->mmio_base = pci_resource_start(pdev, 1);
5938 ivideo->mmio_size = pci_resource_len(pdev, 1);
5939 ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
5940 ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
5942 SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress);
5944 #ifdef CONFIG_FB_SIS_300
5945 /* Find PCI systems for Chrontel/GPIO communication setup */
5946 if(ivideo->chip == SIS_630) {
5949 if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
5950 mychswtable[i].subsysCard == ivideo->subsysdevice) {
5951 ivideo->SiS_Pr.SiS_ChSW = true;
5952 printk(KERN_DEBUG "sisfb: Identified [%s %s] "
5953 "requiring Chrontel/GPIO setup\n",
5954 mychswtable[i].vendorName,
5955 mychswtable[i].cardName);
5956 ivideo->lpcdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, NULL);
5960 } while(mychswtable[i].subsysVendor != 0);
5964 #ifdef CONFIG_FB_SIS_315
5965 if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
5966 ivideo->lpcdev = pci_get_slot(ivideo->nbridge->bus, (2 << 3));
5970 outSISIDXREG(SISSR, 0x05, 0x86);
5972 if( (!ivideo->sisvga_enabled)
5973 #if !defined(__i386__) && !defined(__x86_64__)
5974 || (sisfb_resetcard)
5977 for(i = 0x30; i <= 0x3f; i++) {
5978 outSISIDXREG(SISCR, i, 0x00);
5982 /* Find out about current video mode */
5983 ivideo->modeprechange = 0x03;
5984 inSISIDXREG(SISCR, 0x34, reg);
5986 ivideo->modeprechange = reg & 0x7f;
5987 } else if(ivideo->sisvga_enabled) {
5988 #if defined(__i386__) || defined(__x86_64__)
5989 unsigned char __iomem *tt = ioremap(0x400, 0x100);
5991 ivideo->modeprechange = readb(tt + 0x49);
5997 /* Search and copy ROM image */
5998 ivideo->bios_abase = NULL;
5999 ivideo->SiS_Pr.VirtualRomBase = NULL;
6000 ivideo->SiS_Pr.UseROM = false;
6001 ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = false;
6002 if(ivideo->sisfb_userom) {
6003 ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
6004 ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
6005 ivideo->SiS_Pr.UseROM = (bool)(ivideo->SiS_Pr.VirtualRomBase);
6006 printk(KERN_INFO "sisfb: Video ROM %sfound\n",
6007 ivideo->SiS_Pr.UseROM ? "" : "not ");
6008 if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
6009 ivideo->SiS_Pr.UseROM = false;
6010 ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = true;
6011 if( (ivideo->revision_id == 2) &&
6012 (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
6013 ivideo->SiS_Pr.DDCPortMixup = true;
6017 printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
6020 /* Find systems for special custom timing */
6021 if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
6022 sisfb_detect_custom_timing(ivideo);
6025 /* POST card in case this has not been done by the BIOS */
6026 if( (!ivideo->sisvga_enabled)
6027 #if !defined(__i386__) && !defined(__x86_64__)
6028 || (sisfb_resetcard)
6031 #ifdef CONFIG_FB_SIS_300
6032 if(ivideo->sisvga_engine == SIS_300_VGA) {
6033 if(ivideo->chip == SIS_300) {
6034 sisfb_post_sis300(pdev);
6035 ivideo->sisfb_can_post = 1;
6040 #ifdef CONFIG_FB_SIS_315
6041 if(ivideo->sisvga_engine == SIS_315_VGA) {
6043 /* if((ivideo->chip == SIS_315H) ||
6044 (ivideo->chip == SIS_315) ||
6045 (ivideo->chip == SIS_315PRO) ||
6046 (ivideo->chip == SIS_330)) {
6047 sisfb_post_sis315330(pdev);
6048 } else */ if(ivideo->chip == XGI_20) {
6049 result = sisfb_post_xgi(pdev);
6050 ivideo->sisfb_can_post = 1;
6051 } else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
6052 result = sisfb_post_xgi(pdev);
6053 ivideo->sisfb_can_post = 1;
6055 printk(KERN_INFO "sisfb: Card is not "
6056 "POSTed and sisfb can't do this either.\n");
6059 printk(KERN_ERR "sisfb: Failed to POST card\n");
6067 ivideo->sisfb_card_posted = 1;
6069 /* Find out about RAM size */
6070 if(sisfb_get_dram_size(ivideo)) {
6071 printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
6077 /* Enable PCI addressing and MMIO */
6078 if((ivideo->sisfb_mode_idx < 0) ||
6079 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6080 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
6081 orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
6082 /* Enable 2D accelerator engine */
6083 orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
6086 if(sisfb_pdc != 0xff) {
6087 if(ivideo->sisvga_engine == SIS_300_VGA)
6091 ivideo->SiS_Pr.PDC = sisfb_pdc;
6093 #ifdef CONFIG_FB_SIS_315
6094 if(ivideo->sisvga_engine == SIS_315_VGA) {
6095 if(sisfb_pdca != 0xff)
6096 ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
6100 if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
6101 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6102 (int)(ivideo->video_size >> 20));
6103 printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
6108 if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
6109 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
6114 ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size);
6115 ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
6116 if(!ivideo->video_vbase) {
6117 printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
6122 ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
6123 if(!ivideo->mmio_vbase) {
6124 printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
6126 error_0: iounmap(ivideo->video_vbase);
6127 error_1: release_mem_region(ivideo->video_base, ivideo->video_size);
6128 error_2: release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6129 error_3: vfree(ivideo->bios_abase);
6131 pci_dev_put(ivideo->lpcdev);
6133 pci_dev_put(ivideo->nbridge);
6134 pci_set_drvdata(pdev, NULL);
6135 if(!ivideo->sisvga_enabled)
6136 pci_disable_device(pdev);
6141 printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
6142 ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);
6144 if(ivideo->video_offset) {
6145 printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
6146 ivideo->video_offset / 1024);
6149 printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
6150 ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
6153 /* Determine the size of the command queue */
6154 if(ivideo->sisvga_engine == SIS_300_VGA) {
6155 ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
6157 if(ivideo->chip == XGI_20) {
6158 ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
6160 ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
6164 /* Engines are no longer initialized here; this is
6165 * now done after the first mode-switch (if the
6166 * submitted var has its acceleration flags set).
6169 /* Calculate the base of the (unused) hw cursor */
6170 ivideo->hwcursor_vbase = ivideo->video_vbase
6171 + ivideo->video_size
6172 - ivideo->cmdQueueSize
6173 - ivideo->hwcursor_size;
6174 ivideo->caps |= HW_CURSOR_CAP;
6176 /* Initialize offscreen memory manager */
6177 if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
6178 printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
6181 /* Used for clearing the screen only, therefore respect our mem limit */
6182 ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
6183 ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;
6187 ivideo->vbflags = 0;
6188 ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
6189 ivideo->tvdefmodeidx = DEFAULT_TVMODE;
6190 ivideo->defmodeidx = DEFAULT_MODE;
6193 if(ivideo->chip < XGI_20) {
6194 if(ivideo->bios_abase) {
6195 ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr);
6199 if((ivideo->sisfb_mode_idx < 0) ||
6200 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6202 sisfb_sense_crt1(ivideo);
6204 sisfb_get_VB_type(ivideo);
6206 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6207 sisfb_detect_VB_connect(ivideo);
6210 ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
6212 /* Decide on which CRT2 device to use */
6213 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6214 if(ivideo->sisfb_crt2type != -1) {
6215 if((ivideo->sisfb_crt2type == CRT2_LCD) &&
6216 (ivideo->vbflags & CRT2_LCD)) {
6217 ivideo->currentvbflags |= CRT2_LCD;
6218 } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
6219 ivideo->currentvbflags |= ivideo->sisfb_crt2type;
6222 /* Chrontel 700x TV detection often unreliable, therefore
6223 * use a different default order on such machines
6225 if((ivideo->sisvga_engine == SIS_300_VGA) &&
6226 (ivideo->vbflags2 & VB2_CHRONTEL)) {
6227 if(ivideo->vbflags & CRT2_LCD)
6228 ivideo->currentvbflags |= CRT2_LCD;
6229 else if(ivideo->vbflags & CRT2_TV)
6230 ivideo->currentvbflags |= CRT2_TV;
6231 else if(ivideo->vbflags & CRT2_VGA)
6232 ivideo->currentvbflags |= CRT2_VGA;
6234 if(ivideo->vbflags & CRT2_TV)
6235 ivideo->currentvbflags |= CRT2_TV;
6236 else if(ivideo->vbflags & CRT2_LCD)
6237 ivideo->currentvbflags |= CRT2_LCD;
6238 else if(ivideo->vbflags & CRT2_VGA)
6239 ivideo->currentvbflags |= CRT2_VGA;
6244 if(ivideo->vbflags & CRT2_LCD) {
6245 sisfb_detect_lcd_type(ivideo);
6248 sisfb_save_pdc_emi(ivideo);
6250 if(!ivideo->sisfb_crt1off) {
6251 sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
6253 if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
6254 (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
6255 sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
6259 if(ivideo->sisfb_mode_idx >= 0) {
6260 int bu = ivideo->sisfb_mode_idx;
6261 ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
6262 ivideo->sisfb_mode_idx, ivideo->currentvbflags);
6263 if(bu != ivideo->sisfb_mode_idx) {
6264 printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
6265 sisbios_mode[bu].xres,
6266 sisbios_mode[bu].yres,
6267 sisbios_mode[bu].bpp);
6271 if(ivideo->sisfb_mode_idx < 0) {
6272 switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
6274 ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
6277 ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
6280 ivideo->sisfb_mode_idx = ivideo->defmodeidx;
6285 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
6287 if(ivideo->refresh_rate != 0) {
6288 sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate,
6289 ivideo->sisfb_mode_idx);
6292 if(ivideo->rate_idx == 0) {
6293 ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
6294 ivideo->refresh_rate = 60;
6297 if(ivideo->sisfb_thismonitor.datavalid) {
6298 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor,
6299 ivideo->sisfb_mode_idx,
6301 ivideo->refresh_rate)) {
6302 printk(KERN_INFO "sisfb: WARNING: Refresh rate "
6303 "exceeds monitor specs!\n");
6307 ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
6308 ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
6309 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
6311 sisfb_set_vparms(ivideo);
6313 printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
6314 ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
6315 ivideo->refresh_rate);
6317 /* Set up the default var according to chosen default display mode */
6318 ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
6319 ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
6320 ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
6322 sisfb_bpp_to_var(ivideo, &ivideo->default_var);
6324 ivideo->default_var.pixclock = (u32) (1000000000 /
6325 sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx));
6327 if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no,
6328 ivideo->rate_idx, &ivideo->default_var)) {
6329 if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
6330 ivideo->default_var.pixclock <<= 1;
6334 if(ivideo->sisfb_ypan) {
6335 /* Maximize regardless of sisfb_max at startup */
6336 ivideo->default_var.yres_virtual =
6337 sisfb_calc_maxyres(ivideo, &ivideo->default_var);
6338 if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
6339 ivideo->default_var.yres_virtual = ivideo->default_var.yres;
6343 sisfb_calc_pitch(ivideo, &ivideo->default_var);
6346 if(ivideo->sisfb_accel) {
6348 #ifdef STUPID_ACCELF_TEXT_SHIT
6349 ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
6352 sisfb_initaccel(ivideo);
6354 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
6355 sis_fb_info->flags = FBINFO_DEFAULT |
6356 FBINFO_HWACCEL_YPAN |
6357 FBINFO_HWACCEL_XPAN |
6358 FBINFO_HWACCEL_COPYAREA |
6359 FBINFO_HWACCEL_FILLRECT |
6360 ((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED);
6362 sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
6364 sis_fb_info->var = ivideo->default_var;
6365 sis_fb_info->fix = ivideo->sisfb_fix;
6366 sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
6367 sis_fb_info->fbops = &sisfb_ops;
6368 sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info);
6369 sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
6371 fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
6373 printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
6376 ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size,
6377 MTRR_TYPE_WRCOMB, 1);
6378 if(ivideo->mtrr < 0) {
6379 printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n");
6383 if(register_framebuffer(sis_fb_info) < 0) {
6384 printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
6386 iounmap(ivideo->mmio_vbase);
6390 ivideo->registered = 1;
6393 ivideo->next = card_list;
6396 printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
6397 ivideo->sisfb_accel ? "enabled" : "disabled",
6398 ivideo->sisfb_ypan ?
6399 (ivideo->sisfb_max ? "enabled (auto-max)" :
6400 "enabled (no auto-max)") :
6404 printk(KERN_INFO "fb%d: %s frame buffer device version %d.%d.%d\n",
6405 sis_fb_info->node, ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
6407 printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
6409 } /* if mode = "none" */
6414 /*****************************************************/
6415 /* PCI DEVICE HANDLING */
6416 /*****************************************************/
6418 static void __devexit sisfb_remove(struct pci_dev *pdev)
6420 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
6421 struct fb_info *sis_fb_info = ivideo->memyselfandi;
6422 int registered = ivideo->registered;
6423 int modechanged = ivideo->modechanged;
6426 iounmap(ivideo->mmio_vbase);
6427 iounmap(ivideo->video_vbase);
6429 /* Release mem regions */
6430 release_mem_region(ivideo->video_base, ivideo->video_size);
6431 release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6433 vfree(ivideo->bios_abase);
6436 pci_dev_put(ivideo->lpcdev);
6439 pci_dev_put(ivideo->nbridge);
6442 /* Release MTRR region */
6443 if(ivideo->mtrr >= 0)
6444 mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size);
6447 pci_set_drvdata(pdev, NULL);
6449 /* If device was disabled when starting, disable
6452 if(!ivideo->sisvga_enabled)
6453 pci_disable_device(pdev);
6455 /* Unregister the framebuffer */
6456 if(ivideo->registered) {
6457 unregister_framebuffer(sis_fb_info);
6458 framebuffer_release(sis_fb_info);
6461 /* OK, our ivideo is gone for good from here. */
6463 /* TODO: Restore the initial mode
6464 * This sounds easy but is as good as impossible
6465 * on many machines with SiS chip and video bridge
6466 * since text modes are always set up differently
6467 * from machine to machine. Depends on the type
6468 * of integration between chipset and bridge.
6470 if(registered && modechanged)
6472 "sisfb: Restoring of text mode not supported yet\n");
6475 static struct pci_driver sisfb_driver = {
6477 .id_table = sisfb_pci_table,
6478 .probe = sisfb_probe,
6479 .remove = __devexit_p(sisfb_remove)
6482 static int __init sisfb_init(void)
6485 char *options = NULL;
6487 if(fb_get_options("sisfb", &options))
6490 sisfb_setup(options);
6492 return pci_register_driver(&sisfb_driver);
6496 module_init(sisfb_init);
6499 /*****************************************************/
6501 /*****************************************************/
6505 static char *mode = NULL;
6506 static int vesa = -1;
6507 static unsigned int rate = 0;
6508 static unsigned int crt1off = 1;
6509 static unsigned int mem = 0;
6510 static char *forcecrt2type = NULL;
6511 static int forcecrt1 = -1;
6512 static int pdc = -1;
6513 static int pdc1 = -1;
6514 static int noaccel = -1;
6515 static int noypan = -1;
6516 static int nomax = -1;
6517 static int userom = -1;
6518 static int useoem = -1;
6519 static char *tvstandard = NULL;
6520 static int nocrt2rate = 0;
6521 static int scalelcd = -1;
6522 static char *specialtiming = NULL;
6523 static int lvdshl = -1;
6524 static int tvxposoffset = 0, tvyposoffset = 0;
6525 #if !defined(__i386__) && !defined(__x86_64__)
6526 static int resetcard = 0;
6527 static int videoram = 0;
6530 static int __init sisfb_init_module(void)
6532 sisfb_setdefaultparms();
6535 sisfb_parm_rate = rate;
6537 if((scalelcd == 0) || (scalelcd == 1))
6538 sisfb_scalelcd = scalelcd ^ 1;
6540 /* Need to check crt2 type first for fstn/dstn */
6543 sisfb_search_crt2type(forcecrt2type);
6546 sisfb_search_tvstd(tvstandard);
6549 sisfb_search_mode(mode, false);
6551 sisfb_search_vesamode(vesa, false);
6553 sisfb_crt1off = (crt1off == 0) ? 1 : 0;
6555 sisfb_forcecrt1 = forcecrt1;
6558 else if(forcecrt1 == 0)
6563 else if(noaccel == 0)
6568 else if(noypan == 0)
6577 sisfb_parm_mem = mem;
6580 sisfb_userom = userom;
6583 sisfb_useoem = useoem;
6586 sisfb_pdc = (pdc & 0x7f);
6589 sisfb_pdca = (pdc1 & 0x1f);
6591 sisfb_nocrt2rate = nocrt2rate;
6594 sisfb_search_specialtiming(specialtiming);
6596 if((lvdshl >= 0) && (lvdshl <= 3))
6597 sisfb_lvdshl = lvdshl;
6599 sisfb_tvxposoffset = tvxposoffset;
6600 sisfb_tvyposoffset = tvyposoffset;
6602 #if !defined(__i386__) && !defined(__x86_64__)
6603 sisfb_resetcard = (resetcard) ? 1 : 0;
6605 sisfb_videoram = videoram;
6608 return sisfb_init();
6611 static void __exit sisfb_remove_module(void)
6613 pci_unregister_driver(&sisfb_driver);
6614 printk(KERN_DEBUG "sisfb: Module unloaded\n");
6617 module_init(sisfb_init_module);
6618 module_exit(sisfb_remove_module);
6620 MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
6621 MODULE_LICENSE("GPL");
6622 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
6624 module_param(mem, int, 0);
6625 module_param(noaccel, int, 0);
6626 module_param(noypan, int, 0);
6627 module_param(nomax, int, 0);
6628 module_param(userom, int, 0);
6629 module_param(useoem, int, 0);
6630 module_param(mode, charp, 0);
6631 module_param(vesa, int, 0);
6632 module_param(rate, int, 0);
6633 module_param(forcecrt1, int, 0);
6634 module_param(forcecrt2type, charp, 0);
6635 module_param(scalelcd, int, 0);
6636 module_param(pdc, int, 0);
6637 module_param(pdc1, int, 0);
6638 module_param(specialtiming, charp, 0);
6639 module_param(lvdshl, int, 0);
6640 module_param(tvstandard, charp, 0);
6641 module_param(tvxposoffset, int, 0);
6642 module_param(tvyposoffset, int, 0);
6643 module_param(nocrt2rate, int, 0);
6644 #if !defined(__i386__) && !defined(__x86_64__)
6645 module_param(resetcard, int, 0);
6646 module_param(videoram, int, 0);
6649 MODULE_PARM_DESC(mem,
6650 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6651 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6652 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6653 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6654 "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6655 "The value is to be specified without 'KB'.\n");
6657 MODULE_PARM_DESC(noaccel,
6658 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
6661 MODULE_PARM_DESC(noypan,
6662 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
6663 "will be performed by redrawing the screen. (default: 0)\n");
6665 MODULE_PARM_DESC(nomax,
6666 "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
6667 "memory for the virtual screen in order to optimize scrolling performance. If\n"
6668 "this is set to anything other than 0, sisfb will not do this and thereby \n"
6669 "enable the user to positively specify a virtual Y size of the screen using\n"
6670 "fbset. (default: 0)\n");
6672 MODULE_PARM_DESC(mode,
6673 "\nSelects the desired default display mode in the format XxYxDepth,\n"
6674 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
6675 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
6676 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
6678 MODULE_PARM_DESC(vesa,
6679 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
6680 "0x117 (default: 0x0103)\n");
6682 MODULE_PARM_DESC(rate,
6683 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
6684 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
6685 "will be ignored (default: 60)\n");
6687 MODULE_PARM_DESC(forcecrt1,
6688 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
6689 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
6690 "0=CRT1 OFF) (default: [autodetected])\n");
6692 MODULE_PARM_DESC(forcecrt2type,
6693 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
6694 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
6695 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
6696 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
6697 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
6698 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
6699 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
6700 "depends on the very hardware in use. (default: [autodetected])\n");
6702 MODULE_PARM_DESC(scalelcd,
6703 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
6704 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
6705 "show black bars around the image, TMDS panels will probably do the scaling\n"
6706 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
6708 MODULE_PARM_DESC(pdc,
6709 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
6710 "should detect this correctly in most cases; however, sometimes this is not\n"
6711 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
6712 "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
6713 "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
6714 "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
6716 #ifdef CONFIG_FB_SIS_315
6717 MODULE_PARM_DESC(pdc1,
6718 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
6719 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
6720 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
6721 "implemented yet.\n");
6724 MODULE_PARM_DESC(specialtiming,
6725 "\nPlease refer to documentation for more information on this option.\n");
6727 MODULE_PARM_DESC(lvdshl,
6728 "\nPlease refer to documentation for more information on this option.\n");
6730 MODULE_PARM_DESC(tvstandard,
6731 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
6732 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
6734 MODULE_PARM_DESC(tvxposoffset,
6735 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
6738 MODULE_PARM_DESC(tvyposoffset,
6739 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
6742 MODULE_PARM_DESC(nocrt2rate,
6743 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
6744 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
6746 #if !defined(__i386__) && !defined(__x86_64__)
6747 #ifdef CONFIG_FB_SIS_300
6748 MODULE_PARM_DESC(resetcard,
6749 "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
6750 "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
6751 "currently). Default: 0\n");
6753 MODULE_PARM_DESC(videoram,
6754 "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
6755 "some non-x86 architectures where the memory auto detection fails. Only\n"
6756 "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
6760 #endif /* /MODULE */
6762 /* _GPL only for new symbols. */
6763 EXPORT_SYMBOL(sis_malloc);
6764 EXPORT_SYMBOL(sis_free);
6765 EXPORT_SYMBOL_GPL(sis_malloc_new);
6766 EXPORT_SYMBOL_GPL(sis_free_new);