2 * SiS 300/540/630[S]/730[S],
3 * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
5 * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
7 * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the named License,
12 * or any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
23 * Author: Thomas Winischhofer <thomas@winischhofer.net>
25 * Author of (practically wiped) code base:
27 * Copyright (C) 1999 Silicon Integrated Systems, Inc.
29 * See http://www.winischhofer.net/ for more information and updates
31 * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver,
32 * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
36 #include <linux/module.h>
37 #include <linux/moduleparam.h>
38 #include <linux/kernel.h>
39 #include <linux/spinlock.h>
40 #include <linux/errno.h>
41 #include <linux/string.h>
43 #include <linux/screen_info.h>
44 #include <linux/slab.h>
46 #include <linux/selection.h>
47 #include <linux/ioport.h>
48 #include <linux/init.h>
49 #include <linux/pci.h>
50 #include <linux/vmalloc.h>
51 #include <linux/capability.h>
53 #include <linux/types.h>
54 #include <linux/uaccess.h>
63 #if !defined(CONFIG_FB_SIS_300) && !defined(CONFIG_FB_SIS_315)
64 #warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
65 #warning sisfb will not work!
68 static void sisfb_handle_command(struct sis_video_info *ivideo,
69 struct sisfb_cmd *sisfb_command);
71 /* ------------------ Internal helper routines ----------------- */
74 sisfb_setdefaultparms(void)
92 sisfb_specialtiming = CUT_NONE;
98 sisfb_tvxposoffset = 0;
99 sisfb_tvyposoffset = 0;
100 sisfb_nocrt2rate = 0;
101 #if !defined(__i386__) && !defined(__x86_64__)
107 /* ------------- Parameter parsing -------------- */
109 static void sisfb_search_vesamode(unsigned int vesamode, bool quiet)
113 /* We don't know the hardware specs yet and there is no ivideo */
117 printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
119 sisfb_mode_idx = DEFAULT_MODE;
124 vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
126 while(sisbios_mode[i++].mode_no[0] != 0) {
127 if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
128 (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
130 if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
131 sisbios_mode[i-1].mode_no[1] == 0x56 ||
132 sisbios_mode[i-1].mode_no[1] == 0x53)
135 if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
136 sisbios_mode[i-1].mode_no[1] == 0x5b)
139 sisfb_mode_idx = i - 1;
145 printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
148 static void sisfb_search_mode(char *name, bool quiet)
150 unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
152 char strbuf[16], strbuf1[20];
153 char *nameptr = name;
155 /* We don't know the hardware specs yet and there is no ivideo */
159 printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
161 sisfb_mode_idx = DEFAULT_MODE;
165 if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
167 printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
169 sisfb_mode_idx = DEFAULT_MODE;
173 if(strlen(name) <= 19) {
174 strcpy(strbuf1, name);
175 for(i = 0; i < strlen(strbuf1); i++) {
176 if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
179 /* This does some fuzzy mode naming detection */
180 if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
181 if((rate <= 32) || (depth > 32)) {
182 j = rate; rate = depth; depth = j;
184 sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
186 sisfb_parm_rate = rate;
187 } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
188 sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
192 if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
193 sprintf(strbuf, "%ux%ux8", xres, yres);
196 sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
203 while(sisbios_mode[i].mode_no[0] != 0) {
204 if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
206 if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
207 sisbios_mode[i-1].mode_no[1] == 0x56 ||
208 sisbios_mode[i-1].mode_no[1] == 0x53)
211 if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
212 sisbios_mode[i-1].mode_no[1] == 0x5b)
215 sisfb_mode_idx = i - 1;
222 printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
226 static void sisfb_get_vga_mode_from_kernel(void)
230 int mydepth = screen_info.lfb_depth;
232 if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
234 if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) &&
235 (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
236 (mydepth >= 8) && (mydepth <= 32) ) {
238 if(mydepth == 24) mydepth = 32;
240 sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
241 screen_info.lfb_height,
245 "sisfb: Using vga mode %s pre-set by kernel as default\n",
248 sisfb_search_mode(mymode, true);
256 sisfb_search_crt2type(const char *name)
260 /* We don't know the hardware specs yet and there is no ivideo */
262 if(name == NULL) return;
264 while(sis_crt2type[i].type_no != -1) {
265 if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
266 sisfb_crt2type = sis_crt2type[i].type_no;
267 sisfb_tvplug = sis_crt2type[i].tvplug_no;
268 sisfb_crt2flags = sis_crt2type[i].flags;
274 sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
275 sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
277 if(sisfb_crt2type < 0)
278 printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
282 sisfb_search_tvstd(const char *name)
286 /* We don't know the hardware specs yet and there is no ivideo */
291 while(sis_tvtype[i].type_no != -1) {
292 if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
293 sisfb_tvstd = sis_tvtype[i].type_no;
301 sisfb_search_specialtiming(const char *name)
306 /* We don't know the hardware specs yet and there is no ivideo */
311 if(!strnicmp(name, "none", 4)) {
312 sisfb_specialtiming = CUT_FORCENONE;
313 printk(KERN_DEBUG "sisfb: Special timing disabled\n");
315 while(mycustomttable[i].chipID != 0) {
316 if(!strnicmp(name,mycustomttable[i].optionName,
317 strlen(mycustomttable[i].optionName))) {
318 sisfb_specialtiming = mycustomttable[i].SpecialID;
320 printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
321 mycustomttable[i].vendorName,
322 mycustomttable[i].cardName,
323 mycustomttable[i].optionName);
329 printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
330 printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
332 while(mycustomttable[i].chipID != 0) {
333 printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
334 mycustomttable[i].optionName,
335 mycustomttable[i].vendorName,
336 mycustomttable[i].cardName);
343 /* ----------- Various detection routines ----------- */
345 static void sisfb_detect_custom_timing(struct sis_video_info *ivideo)
347 unsigned char *biosver = NULL;
348 unsigned char *biosdate = NULL;
353 if(ivideo->SiS_Pr.UseROM) {
354 biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06;
355 biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c;
356 for(i = 0; i < 32768; i++)
357 chksum += ivideo->SiS_Pr.VirtualRomBase[i];
362 if( (mycustomttable[i].chipID == ivideo->chip) &&
363 ((!strlen(mycustomttable[i].biosversion)) ||
364 (ivideo->SiS_Pr.UseROM &&
365 (!strncmp(mycustomttable[i].biosversion, biosver,
366 strlen(mycustomttable[i].biosversion))))) &&
367 ((!strlen(mycustomttable[i].biosdate)) ||
368 (ivideo->SiS_Pr.UseROM &&
369 (!strncmp(mycustomttable[i].biosdate, biosdate,
370 strlen(mycustomttable[i].biosdate))))) &&
371 ((!mycustomttable[i].bioschksum) ||
372 (ivideo->SiS_Pr.UseROM &&
373 (mycustomttable[i].bioschksum == chksum))) &&
374 (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
375 (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
377 for(j = 0; j < 5; j++) {
378 if(mycustomttable[i].biosFootprintAddr[j]) {
379 if(ivideo->SiS_Pr.UseROM) {
380 if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
381 mycustomttable[i].biosFootprintData[j]) {
389 ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
390 printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
391 mycustomttable[i].vendorName,
392 mycustomttable[i].cardName);
393 printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
394 mycustomttable[i].optionName);
399 } while(mycustomttable[i].chipID);
402 static bool sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
404 int i, j, xres, yres, refresh, index;
407 if(buffer[0] != 0x00 || buffer[1] != 0xff ||
408 buffer[2] != 0xff || buffer[3] != 0xff ||
409 buffer[4] != 0xff || buffer[5] != 0xff ||
410 buffer[6] != 0xff || buffer[7] != 0x00) {
411 printk(KERN_DEBUG "sisfb: Bad EDID header\n");
415 if(buffer[0x12] != 0x01) {
416 printk(KERN_INFO "sisfb: EDID version %d not supported\n",
421 monitor->feature = buffer[0x18];
423 if(!(buffer[0x14] & 0x80)) {
424 if(!(buffer[0x14] & 0x08)) {
426 "sisfb: WARNING: Monitor does not support separate syncs\n");
430 if(buffer[0x13] >= 0x01) {
431 /* EDID V1 rev 1 and 2: Search for monitor descriptor
436 if(buffer[j] == 0x00 && buffer[j + 1] == 0x00 &&
437 buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
438 buffer[j + 4] == 0x00) {
439 monitor->hmin = buffer[j + 7];
440 monitor->hmax = buffer[j + 8];
441 monitor->vmin = buffer[j + 5];
442 monitor->vmax = buffer[j + 6];
443 monitor->dclockmax = buffer[j + 9] * 10 * 1000;
444 monitor->datavalid = true;
451 if(!monitor->datavalid) {
452 /* Otherwise: Get a range from the list of supported
453 * Estabished Timings. This is not entirely accurate,
454 * because fixed frequency monitors are not supported
457 monitor->hmin = 65535; monitor->hmax = 0;
458 monitor->vmin = 65535; monitor->vmax = 0;
459 monitor->dclockmax = 0;
460 emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
461 for(i = 0; i < 13; i++) {
462 if(emodes & sisfb_ddcsmodes[i].mask) {
463 if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
464 if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
465 if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
466 if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
467 if(monitor->dclockmax < sisfb_ddcsmodes[i].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
471 for(i = 0; i < 8; i++) {
472 xres = (buffer[index] + 31) * 8;
473 switch(buffer[index + 1] & 0xc0) {
474 case 0xc0: yres = (xres * 9) / 16; break;
475 case 0x80: yres = (xres * 4) / 5; break;
476 case 0x40: yres = (xres * 3) / 4; break;
477 default: yres = xres; break;
479 refresh = (buffer[index + 1] & 0x3f) + 60;
480 if((xres >= 640) && (yres >= 480)) {
481 for(j = 0; j < 8; j++) {
482 if((xres == sisfb_ddcfmodes[j].x) &&
483 (yres == sisfb_ddcfmodes[j].y) &&
484 (refresh == sisfb_ddcfmodes[j].v)) {
485 if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
486 if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
487 if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
488 if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
489 if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d;
495 if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
496 monitor->datavalid = true;
500 return monitor->datavalid;
503 static void sisfb_handle_ddc(struct sis_video_info *ivideo,
504 struct sisfb_monitor *monitor, int crtno)
506 unsigned short temp, i, realcrtno = crtno;
507 unsigned char buffer[256];
509 monitor->datavalid = false;
512 if(ivideo->vbflags & CRT2_LCD) realcrtno = 1;
513 else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
517 if((ivideo->sisfb_crt1off) && (!crtno))
520 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
521 realcrtno, 0, &buffer[0], ivideo->vbflags2);
522 if((!temp) || (temp == 0xffff)) {
523 printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
526 printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
527 printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
529 (temp & 0x1a) ? "" : "[none of the supported]",
530 (temp & 0x02) ? "2 " : "",
531 (temp & 0x08) ? "D&P" : "",
532 (temp & 0x10) ? "FPDI-2" : "");
534 i = 3; /* Number of retrys */
536 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
537 realcrtno, 1, &buffer[0], ivideo->vbflags2);
538 } while((temp) && i--);
540 if(sisfb_interpret_edid(monitor, &buffer[0])) {
541 printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
542 monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
543 monitor->dclockmax / 1000);
545 printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
548 printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
551 printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
556 /* -------------- Mode validation --------------- */
559 sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
560 int mode_idx, int rate_idx, int rate)
563 unsigned int dclock, hsync;
565 if(!monitor->datavalid)
571 /* Skip for 320x200, 320x240, 640x400 */
572 switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
583 #ifdef CONFIG_FB_SIS_315
586 if(ivideo->sisvga_engine == SIS_315_VGA) return true;
590 if(rate < (monitor->vmin - 1))
592 if(rate > (monitor->vmax + 1))
595 if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
596 sisbios_mode[mode_idx].mode_no[ivideo->mni],
597 &htotal, &vtotal, rate_idx)) {
598 dclock = (htotal * vtotal * rate) / 1000;
599 if(dclock > (monitor->dclockmax + 1000))
601 hsync = dclock / htotal;
602 if(hsync < (monitor->hmin - 1))
604 if(hsync > (monitor->hmax + 1))
613 sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
615 u16 xres=0, yres, myres;
617 #ifdef CONFIG_FB_SIS_300
618 if(ivideo->sisvga_engine == SIS_300_VGA) {
619 if(!(sisbios_mode[myindex].chipset & MD_SIS300))
623 #ifdef CONFIG_FB_SIS_315
624 if(ivideo->sisvga_engine == SIS_315_VGA) {
625 if(!(sisbios_mode[myindex].chipset & MD_SIS315))
630 myres = sisbios_mode[myindex].yres;
632 switch(vbflags & VB_DISPTYPE_DISP2) {
635 xres = ivideo->lcdxres; yres = ivideo->lcdyres;
637 if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
638 (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
639 if(sisbios_mode[myindex].xres > xres)
645 if(ivideo->sisfb_fstn) {
646 if(sisbios_mode[myindex].xres == 320) {
648 switch(sisbios_mode[myindex].mode_no[1]) {
649 case 0x50: myindex = MODE_FSTN_8; break;
650 case 0x56: myindex = MODE_FSTN_16; break;
651 case 0x53: return -1;
657 if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
658 sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
659 ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
665 if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
666 sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
672 if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
673 sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
683 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
686 u16 xres = sisbios_mode[mode_idx].xres;
687 u16 yres = sisbios_mode[mode_idx].yres;
689 ivideo->rate_idx = 0;
690 while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
691 if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
692 if(sisfb_vrate[i].refresh == rate) {
693 ivideo->rate_idx = sisfb_vrate[i].idx;
695 } else if(sisfb_vrate[i].refresh > rate) {
696 if((sisfb_vrate[i].refresh - rate) <= 3) {
697 DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
698 rate, sisfb_vrate[i].refresh);
699 ivideo->rate_idx = sisfb_vrate[i].idx;
700 ivideo->refresh_rate = sisfb_vrate[i].refresh;
701 } else if((sisfb_vrate[i].idx != 1) &&
702 ((rate - sisfb_vrate[i-1].refresh) <= 2)) {
703 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
704 rate, sisfb_vrate[i-1].refresh);
705 ivideo->rate_idx = sisfb_vrate[i-1].idx;
706 ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
709 } else if((rate - sisfb_vrate[i].refresh) <= 2) {
710 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
711 rate, sisfb_vrate[i].refresh);
712 ivideo->rate_idx = sisfb_vrate[i].idx;
718 if(ivideo->rate_idx > 0) {
719 return ivideo->rate_idx;
721 printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n",
728 sisfb_bridgeisslave(struct sis_video_info *ivideo)
732 if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
735 P1_00 = SiS_GetReg(SISPART1, 0x00);
736 if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
737 ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
745 sisfballowretracecrt1(struct sis_video_info *ivideo)
749 temp = SiS_GetReg(SISCR, 0x17);
753 temp = SiS_GetReg(SISSR, 0x1f);
761 sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
763 if(!sisfballowretracecrt1(ivideo))
766 if (SiS_GetRegByte(SISINPSTAT) & 0x08)
773 sisfbwaitretracecrt1(struct sis_video_info *ivideo)
777 if(!sisfballowretracecrt1(ivideo))
781 while ((!(SiS_GetRegByte(SISINPSTAT) & 0x08)) && --watchdog);
783 while ((SiS_GetRegByte(SISINPSTAT) & 0x08) && --watchdog);
787 sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
789 unsigned char temp, reg;
791 switch(ivideo->sisvga_engine) {
792 case SIS_300_VGA: reg = 0x25; break;
793 case SIS_315_VGA: reg = 0x30; break;
794 default: return false;
797 temp = SiS_GetReg(SISPART1, reg);
805 sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
807 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
808 if(!sisfb_bridgeisslave(ivideo)) {
809 return sisfbcheckvretracecrt2(ivideo);
812 return sisfbcheckvretracecrt1(ivideo);
816 sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
818 u8 idx, reg1, reg2, reg3, reg4;
821 (*vcount) = (*hcount) = 0;
823 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
825 ret |= (FB_VBLANK_HAVE_VSYNC |
826 FB_VBLANK_HAVE_HBLANK |
827 FB_VBLANK_HAVE_VBLANK |
828 FB_VBLANK_HAVE_VCOUNT |
829 FB_VBLANK_HAVE_HCOUNT);
830 switch(ivideo->sisvga_engine) {
831 case SIS_300_VGA: idx = 0x25; break;
833 case SIS_315_VGA: idx = 0x30; break;
835 reg1 = SiS_GetReg(SISPART1, (idx+0)); /* 30 */
836 reg2 = SiS_GetReg(SISPART1, (idx+1)); /* 31 */
837 reg3 = SiS_GetReg(SISPART1, (idx+2)); /* 32 */
838 reg4 = SiS_GetReg(SISPART1, (idx+3)); /* 33 */
839 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
840 if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
841 if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
842 (*vcount) = reg3 | ((reg4 & 0x70) << 4);
843 (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
845 } else if(sisfballowretracecrt1(ivideo)) {
847 ret |= (FB_VBLANK_HAVE_VSYNC |
848 FB_VBLANK_HAVE_VBLANK |
849 FB_VBLANK_HAVE_VCOUNT |
850 FB_VBLANK_HAVE_HCOUNT);
851 reg1 = SiS_GetRegByte(SISINPSTAT);
852 if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
853 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
854 reg1 = SiS_GetReg(SISCR, 0x20);
855 reg1 = SiS_GetReg(SISCR, 0x1b);
856 reg2 = SiS_GetReg(SISCR, 0x1c);
857 reg3 = SiS_GetReg(SISCR, 0x1d);
858 (*vcount) = reg2 | ((reg3 & 0x07) << 8);
859 (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
866 sisfb_myblank(struct sis_video_info *ivideo, int blank)
868 u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
869 bool backlight = true;
872 case FB_BLANK_UNBLANK: /* on */
881 case FB_BLANK_NORMAL: /* blank */
890 case FB_BLANK_VSYNC_SUSPEND: /* no vsync */
899 case FB_BLANK_HSYNC_SUSPEND: /* no hsync */
908 case FB_BLANK_POWERDOWN: /* off */
921 if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
923 if( (!ivideo->sisfb_thismonitor.datavalid) ||
924 ((ivideo->sisfb_thismonitor.datavalid) &&
925 (ivideo->sisfb_thismonitor.feature & 0xe0))) {
927 if(ivideo->sisvga_engine == SIS_315_VGA) {
928 SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
931 if(!(sisfb_bridgeisslave(ivideo))) {
932 SiS_SetRegANDOR(SISSR, 0x01, ~0x20, sr01);
933 SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, sr1f);
939 if(ivideo->currentvbflags & CRT2_LCD) {
941 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
943 SiS_SiS30xBLOn(&ivideo->SiS_Pr);
945 SiS_SiS30xBLOff(&ivideo->SiS_Pr);
947 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
948 #ifdef CONFIG_FB_SIS_315
949 if(ivideo->vbflags2 & VB2_CHRONTEL) {
951 SiS_Chrontel701xBLOn(&ivideo->SiS_Pr);
953 SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
959 if(((ivideo->sisvga_engine == SIS_300_VGA) &&
960 (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
961 ((ivideo->sisvga_engine == SIS_315_VGA) &&
962 ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
963 SiS_SetRegANDOR(SISSR, 0x11, ~0x0c, sr11);
966 if(ivideo->sisvga_engine == SIS_300_VGA) {
967 if((ivideo->vbflags2 & VB2_30xB) &&
968 (!(ivideo->vbflags2 & VB2_30xBDH))) {
969 SiS_SetRegANDOR(SISPART1, 0x13, 0x3f, p1_13);
971 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
972 if((ivideo->vbflags2 & VB2_30xB) &&
973 (!(ivideo->vbflags2 & VB2_30xBDH))) {
974 SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
978 } else if(ivideo->currentvbflags & CRT2_VGA) {
980 if(ivideo->vbflags2 & VB2_30xB) {
981 SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
989 /* ------------- Callbacks from init.c/init301.c -------------- */
991 #ifdef CONFIG_FB_SIS_300
993 sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg)
995 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
998 pci_read_config_dword(ivideo->nbridge, reg, &val);
999 return (unsigned int)val;
1003 sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val)
1005 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1007 pci_write_config_dword(ivideo->nbridge, reg, (u32)val);
1011 sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg)
1013 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1016 if(!ivideo->lpcdev) return 0;
1018 pci_read_config_dword(ivideo->lpcdev, reg, &val);
1019 return (unsigned int)val;
1023 #ifdef CONFIG_FB_SIS_315
1025 sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val)
1027 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1029 pci_write_config_byte(ivideo->nbridge, reg, (u8)val);
1033 sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg)
1035 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1038 if(!ivideo->lpcdev) return 0;
1040 pci_read_config_word(ivideo->lpcdev, reg, &val);
1041 return (unsigned int)val;
1045 /* ----------- FBDev related routines for all series ----------- */
1048 sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
1050 return (var->bits_per_pixel == 8) ? 256 : 16;
1054 sisfb_set_vparms(struct sis_video_info *ivideo)
1056 switch(ivideo->video_bpp) {
1058 ivideo->DstColor = 0x0000;
1059 ivideo->SiS310_AccelDepth = 0x00000000;
1060 ivideo->video_cmap_len = 256;
1063 ivideo->DstColor = 0x8000;
1064 ivideo->SiS310_AccelDepth = 0x00010000;
1065 ivideo->video_cmap_len = 16;
1068 ivideo->DstColor = 0xC000;
1069 ivideo->SiS310_AccelDepth = 0x00020000;
1070 ivideo->video_cmap_len = 16;
1073 ivideo->video_cmap_len = 16;
1074 printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
1080 sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1082 int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3));
1084 if(maxyres > 32767) maxyres = 32767;
1090 sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1092 ivideo->video_linelength = var->xres_virtual * (var->bits_per_pixel >> 3);
1093 ivideo->scrnpitchCRT1 = ivideo->video_linelength;
1094 if(!(ivideo->currentvbflags & CRT1_LCDA)) {
1095 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1096 ivideo->scrnpitchCRT1 <<= 1;
1102 sisfb_set_pitch(struct sis_video_info *ivideo)
1104 bool isslavemode = false;
1105 unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
1106 unsigned short HDisplay2 = ivideo->video_linelength >> 3;
1108 if(sisfb_bridgeisslave(ivideo)) isslavemode = true;
1110 /* We need to set pitch for CRT1 if bridge is in slave mode, too */
1111 if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
1112 SiS_SetReg(SISCR, 0x13, (HDisplay1 & 0xFF));
1113 SiS_SetRegANDOR(SISSR, 0x0E, 0xF0, (HDisplay1 >> 8));
1116 /* We must not set the pitch for CRT2 if bridge is in slave mode */
1117 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
1118 SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
1119 SiS_SetReg(SISPART1, 0x07, (HDisplay2 & 0xFF));
1120 SiS_SetRegANDOR(SISPART1, 0x09, 0xF0, (HDisplay2 >> 8));
1125 sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1127 ivideo->video_cmap_len = sisfb_get_cmap_len(var);
1129 switch(var->bits_per_pixel) {
1131 var->red.offset = var->green.offset = var->blue.offset = 0;
1132 var->red.length = var->green.length = var->blue.length = 8;
1135 var->red.offset = 11;
1136 var->red.length = 5;
1137 var->green.offset = 5;
1138 var->green.length = 6;
1139 var->blue.offset = 0;
1140 var->blue.length = 5;
1141 var->transp.offset = 0;
1142 var->transp.length = 0;
1145 var->red.offset = 16;
1146 var->red.length = 8;
1147 var->green.offset = 8;
1148 var->green.length = 8;
1149 var->blue.offset = 0;
1150 var->blue.length = 8;
1151 var->transp.offset = 24;
1152 var->transp.length = 8;
1158 sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
1160 unsigned short modeno = ivideo->mode_no;
1162 /* >=2.6.12's fbcon clears the screen anyway */
1165 SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1167 sisfb_pre_setmode(ivideo);
1169 if(!SiSSetMode(&ivideo->SiS_Pr, modeno)) {
1170 printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
1174 SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1176 sisfb_post_setmode(ivideo);
1183 sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
1185 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1186 unsigned int htotal = 0, vtotal = 0;
1187 unsigned int drate = 0, hrate = 0;
1188 int found_mode = 0, ret;
1192 htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1194 vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1196 pixclock = var->pixclock;
1198 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1199 vtotal += var->yres;
1201 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1202 vtotal += var->yres;
1204 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1205 vtotal += var->yres;
1207 } else vtotal += var->yres;
1209 if(!(htotal) || !(vtotal)) {
1210 DPRINTK("sisfb: Invalid 'var' information\n");
1214 if(pixclock && htotal && vtotal) {
1215 drate = 1000000000 / pixclock;
1216 hrate = (drate * 1000) / htotal;
1217 ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1219 ivideo->refresh_rate = 60;
1222 old_mode = ivideo->sisfb_mode_idx;
1223 ivideo->sisfb_mode_idx = 0;
1225 while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) &&
1226 (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) {
1227 if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) &&
1228 (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) &&
1229 (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) {
1230 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1234 ivideo->sisfb_mode_idx++;
1238 ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
1239 ivideo->sisfb_mode_idx, ivideo->currentvbflags);
1241 ivideo->sisfb_mode_idx = -1;
1244 if(ivideo->sisfb_mode_idx < 0) {
1245 printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres,
1246 var->yres, var->bits_per_pixel);
1247 ivideo->sisfb_mode_idx = old_mode;
1251 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1253 if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
1254 ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
1255 ivideo->refresh_rate = 60;
1259 /* If acceleration to be used? Need to know
1260 * before pre/post_set_mode()
1263 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
1264 #ifdef STUPID_ACCELF_TEXT_SHIT
1265 if(var->accel_flags & FB_ACCELF_TEXT) {
1266 info->flags &= ~FBINFO_HWACCEL_DISABLED;
1268 info->flags |= FBINFO_HWACCEL_DISABLED;
1271 if(!(info->flags & FBINFO_HWACCEL_DISABLED)) ivideo->accel = -1;
1273 if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
1276 if((ret = sisfb_set_mode(ivideo, 1))) {
1280 ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
1281 ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
1282 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
1284 sisfb_calc_pitch(ivideo, var);
1285 sisfb_set_pitch(ivideo);
1287 sisfb_set_vparms(ivideo);
1289 ivideo->current_width = ivideo->video_width;
1290 ivideo->current_height = ivideo->video_height;
1291 ivideo->current_bpp = ivideo->video_bpp;
1292 ivideo->current_htotal = htotal;
1293 ivideo->current_vtotal = vtotal;
1294 ivideo->current_linelength = ivideo->video_linelength;
1295 ivideo->current_pixclock = var->pixclock;
1296 ivideo->current_refresh_rate = ivideo->refresh_rate;
1297 ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
1304 sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
1306 SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1308 SiS_SetReg(SISCR, 0x0D, base & 0xFF);
1309 SiS_SetReg(SISCR, 0x0C, (base >> 8) & 0xFF);
1310 SiS_SetReg(SISSR, 0x0D, (base >> 16) & 0xFF);
1311 if(ivideo->sisvga_engine == SIS_315_VGA) {
1312 SiS_SetRegANDOR(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
1317 sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
1319 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1320 SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
1321 SiS_SetReg(SISPART1, 0x06, (base & 0xFF));
1322 SiS_SetReg(SISPART1, 0x05, ((base >> 8) & 0xFF));
1323 SiS_SetReg(SISPART1, 0x04, ((base >> 16) & 0xFF));
1324 if(ivideo->sisvga_engine == SIS_315_VGA) {
1325 SiS_SetRegANDOR(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1331 sisfb_pan_var(struct sis_video_info *ivideo, struct fb_info *info,
1332 struct fb_var_screeninfo *var)
1334 ivideo->current_base = var->yoffset * info->var.xres_virtual
1337 /* calculate base bpp dep. */
1338 switch (info->var.bits_per_pixel) {
1342 ivideo->current_base >>= 1;
1346 ivideo->current_base >>= 2;
1350 ivideo->current_base += (ivideo->video_offset >> 2);
1352 sisfb_set_base_CRT1(ivideo, ivideo->current_base);
1353 sisfb_set_base_CRT2(ivideo, ivideo->current_base);
1359 sisfb_open(struct fb_info *info, int user)
1365 sisfb_release(struct fb_info *info, int user)
1371 sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
1372 unsigned transp, struct fb_info *info)
1374 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1376 if(regno >= sisfb_get_cmap_len(&info->var))
1379 switch(info->var.bits_per_pixel) {
1381 SiS_SetRegByte(SISDACA, regno);
1382 SiS_SetRegByte(SISDACD, (red >> 10));
1383 SiS_SetRegByte(SISDACD, (green >> 10));
1384 SiS_SetRegByte(SISDACD, (blue >> 10));
1385 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1386 SiS_SetRegByte(SISDAC2A, regno);
1387 SiS_SetRegByte(SISDAC2D, (red >> 8));
1388 SiS_SetRegByte(SISDAC2D, (green >> 8));
1389 SiS_SetRegByte(SISDAC2D, (blue >> 8));
1396 ((u32 *)(info->pseudo_palette))[regno] =
1398 ((green & 0xfc00) >> 5) |
1399 ((blue & 0xf800) >> 11);
1408 ((u32 *)(info->pseudo_palette))[regno] =
1409 (red << 16) | (green << 8) | (blue);
1416 sisfb_set_par(struct fb_info *info)
1420 if((err = sisfb_do_set_var(&info->var, 1, info)))
1423 sisfb_get_fix(&info->fix, -1, info);
1429 sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1431 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1432 unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
1433 unsigned int drate = 0, hrate = 0, maxyres;
1435 int refresh_rate, search_idx, tidx;
1436 bool recalc_clock = false;
1439 htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1441 vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1443 pixclock = var->pixclock;
1445 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1446 vtotal += var->yres;
1448 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1449 vtotal += var->yres;
1451 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1452 vtotal += var->yres;
1455 vtotal += var->yres;
1457 if(!(htotal) || !(vtotal)) {
1458 SISFAIL("sisfb: no valid timing data");
1462 while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
1463 (sisbios_mode[search_idx].xres <= var->xres) ) {
1464 if( (sisbios_mode[search_idx].xres == var->xres) &&
1465 (sisbios_mode[search_idx].yres == var->yres) &&
1466 (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1467 if((tidx = sisfb_validate_mode(ivideo, search_idx,
1468 ivideo->currentvbflags)) > 0) {
1479 while(sisbios_mode[search_idx].mode_no[0] != 0) {
1480 if( (var->xres <= sisbios_mode[search_idx].xres) &&
1481 (var->yres <= sisbios_mode[search_idx].yres) &&
1482 (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
1483 if((tidx = sisfb_validate_mode(ivideo,search_idx,
1484 ivideo->currentvbflags)) > 0) {
1494 "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
1495 var->xres, var->yres, var->bits_per_pixel,
1496 sisbios_mode[search_idx].xres,
1497 sisbios_mode[search_idx].yres,
1498 var->bits_per_pixel);
1499 var->xres = sisbios_mode[search_idx].xres;
1500 var->yres = sisbios_mode[search_idx].yres;
1503 "sisfb: Failed to find supported mode near %dx%dx%d\n",
1504 var->xres, var->yres, var->bits_per_pixel);
1509 if( ((ivideo->vbflags2 & VB2_LVDS) ||
1510 ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
1511 (var->bits_per_pixel == 8) ) {
1512 /* Slave modes on LVDS and 301B-DH */
1514 recalc_clock = true;
1515 } else if( (ivideo->current_htotal == htotal) &&
1516 (ivideo->current_vtotal == vtotal) &&
1517 (ivideo->current_pixclock == pixclock) ) {
1518 /* x=x & y=y & c=c -> assume depth change */
1519 drate = 1000000000 / pixclock;
1520 hrate = (drate * 1000) / htotal;
1521 refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1522 } else if( ( (ivideo->current_htotal != htotal) ||
1523 (ivideo->current_vtotal != vtotal) ) &&
1524 (ivideo->current_pixclock == var->pixclock) ) {
1525 /* x!=x | y!=y & c=c -> invalid pixclock */
1526 if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
1528 ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
1529 } else if(ivideo->sisfb_parm_rate != -1) {
1530 /* Sic, sisfb_parm_rate - want to know originally desired rate here */
1531 refresh_rate = ivideo->sisfb_parm_rate;
1535 recalc_clock = true;
1536 } else if((pixclock) && (htotal) && (vtotal)) {
1537 drate = 1000000000 / pixclock;
1538 hrate = (drate * 1000) / htotal;
1539 refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1540 } else if(ivideo->current_refresh_rate) {
1541 refresh_rate = ivideo->current_refresh_rate;
1542 recalc_clock = true;
1545 recalc_clock = true;
1548 myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
1550 /* Eventually recalculate timing and clock */
1552 if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
1553 var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
1554 sisbios_mode[search_idx].mode_no[ivideo->mni],
1556 sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr,
1557 sisbios_mode[search_idx].mode_no[ivideo->mni],
1559 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1560 var->pixclock <<= 1;
1564 if(ivideo->sisfb_thismonitor.datavalid) {
1565 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
1566 myrateindex, refresh_rate)) {
1568 "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1572 /* Adapt RGB settings */
1573 sisfb_bpp_to_var(ivideo, var);
1575 if(var->xres > var->xres_virtual)
1576 var->xres_virtual = var->xres;
1578 if(ivideo->sisfb_ypan) {
1579 maxyres = sisfb_calc_maxyres(ivideo, var);
1580 if(ivideo->sisfb_max) {
1581 var->yres_virtual = maxyres;
1583 if(var->yres_virtual > maxyres) {
1584 var->yres_virtual = maxyres;
1587 if(var->yres_virtual <= var->yres) {
1588 var->yres_virtual = var->yres;
1591 if(var->yres != var->yres_virtual) {
1592 var->yres_virtual = var->yres;
1598 /* Truncate offsets to maximum if too high */
1599 if(var->xoffset > var->xres_virtual - var->xres) {
1600 var->xoffset = var->xres_virtual - var->xres - 1;
1603 if(var->yoffset > var->yres_virtual - var->yres) {
1604 var->yoffset = var->yres_virtual - var->yres - 1;
1607 /* Set everything else to 0 */
1608 var->red.msb_right =
1609 var->green.msb_right =
1610 var->blue.msb_right =
1611 var->transp.offset =
1612 var->transp.length =
1613 var->transp.msb_right = 0;
1619 sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
1621 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1624 if (var->vmode & FB_VMODE_YWRAP)
1627 if (var->xoffset + info->var.xres > info->var.xres_virtual ||
1628 var->yoffset + info->var.yres > info->var.yres_virtual)
1631 err = sisfb_pan_var(ivideo, info, var);
1635 info->var.xoffset = var->xoffset;
1636 info->var.yoffset = var->yoffset;
1642 sisfb_blank(int blank, struct fb_info *info)
1644 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1646 return sisfb_myblank(ivideo, blank);
1649 /* ----------- FBDev related routines for all series ---------- */
1651 static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
1654 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1655 struct sis_memreq sismemreq;
1656 struct fb_vblank sisvbblank;
1661 u32 __user *argp = (u32 __user *)arg;
1665 if(!capable(CAP_SYS_RAWIO))
1668 if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))
1671 sis_malloc(&sismemreq);
1673 if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
1674 sis_free((u32)sismemreq.offset);
1680 if(!capable(CAP_SYS_RAWIO))
1683 if(get_user(gpu32, argp))
1689 case FBIOGET_VBLANK:
1691 memset(&sisvbblank, 0, sizeof(struct fb_vblank));
1693 sisvbblank.count = 0;
1694 sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
1696 if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))
1701 case SISFB_GET_INFO_SIZE:
1702 return put_user(sizeof(struct sisfb_info), argp);
1704 case SISFB_GET_INFO_OLD:
1705 if(ivideo->warncount++ < 10)
1707 "sisfb: Deprecated ioctl call received - update your application!\n");
1708 case SISFB_GET_INFO: /* For communication with X driver */
1709 ivideo->sisfb_infoblock.sisfb_id = SISFB_ID;
1710 ivideo->sisfb_infoblock.sisfb_version = VER_MAJOR;
1711 ivideo->sisfb_infoblock.sisfb_revision = VER_MINOR;
1712 ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;
1713 ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;
1714 ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;
1715 ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;
1716 ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;
1717 if(ivideo->modechanged) {
1718 ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;
1720 ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;
1722 ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;
1723 ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;
1724 ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;
1725 ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;
1726 ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;
1727 ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;
1728 ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;
1729 ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;
1730 ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;
1731 ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;
1732 ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
1733 ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
1734 ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
1735 ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
1736 ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
1737 ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
1738 ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
1739 ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
1740 ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
1741 ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
1742 ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;
1743 ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;
1744 ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;
1745 ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;
1746 ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;
1747 ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;
1748 ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;
1749 ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;
1751 if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,
1752 sizeof(ivideo->sisfb_infoblock)))
1757 case SISFB_GET_VBRSTATUS_OLD:
1758 if(ivideo->warncount++ < 10)
1760 "sisfb: Deprecated ioctl call received - update your application!\n");
1761 case SISFB_GET_VBRSTATUS:
1762 if(sisfb_CheckVBRetrace(ivideo))
1763 return put_user((u32)1, argp);
1765 return put_user((u32)0, argp);
1767 case SISFB_GET_AUTOMAXIMIZE_OLD:
1768 if(ivideo->warncount++ < 10)
1770 "sisfb: Deprecated ioctl call received - update your application!\n");
1771 case SISFB_GET_AUTOMAXIMIZE:
1772 if(ivideo->sisfb_max)
1773 return put_user((u32)1, argp);
1775 return put_user((u32)0, argp);
1777 case SISFB_SET_AUTOMAXIMIZE_OLD:
1778 if(ivideo->warncount++ < 10)
1780 "sisfb: Deprecated ioctl call received - update your application!\n");
1781 case SISFB_SET_AUTOMAXIMIZE:
1782 if(get_user(gpu32, argp))
1785 ivideo->sisfb_max = (gpu32) ? 1 : 0;
1788 case SISFB_SET_TVPOSOFFSET:
1789 if(get_user(gpu32, argp))
1792 sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
1793 sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
1796 case SISFB_GET_TVPOSOFFSET:
1797 return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
1801 if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,
1802 sizeof(struct sisfb_cmd)))
1805 sisfb_handle_command(ivideo, &ivideo->sisfb_command);
1807 if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,
1808 sizeof(struct sisfb_cmd)))
1813 case SISFB_SET_LOCK:
1814 if(get_user(gpu32, argp))
1817 ivideo->sisfblocked = (gpu32) ? 1 : 0;
1821 #ifdef SIS_NEW_CONFIG_COMPAT
1822 return -ENOIOCTLCMD;
1831 sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
1833 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1835 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1837 strlcpy(fix->id, ivideo->myid, sizeof(fix->id));
1839 mutex_lock(&info->mm_lock);
1840 fix->smem_start = ivideo->video_base + ivideo->video_offset;
1841 fix->smem_len = ivideo->sisfb_mem;
1842 mutex_unlock(&info->mm_lock);
1843 fix->type = FB_TYPE_PACKED_PIXELS;
1845 fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
1847 fix->ypanstep = (ivideo->sisfb_ypan) ? 1 : 0;
1849 fix->line_length = ivideo->video_linelength;
1850 fix->mmio_start = ivideo->mmio_base;
1851 fix->mmio_len = ivideo->mmio_size;
1852 if(ivideo->sisvga_engine == SIS_300_VGA) {
1853 fix->accel = FB_ACCEL_SIS_GLAMOUR;
1854 } else if((ivideo->chip == SIS_330) ||
1855 (ivideo->chip == SIS_760) ||
1856 (ivideo->chip == SIS_761)) {
1857 fix->accel = FB_ACCEL_SIS_XABRE;
1858 } else if(ivideo->chip == XGI_20) {
1859 fix->accel = FB_ACCEL_XGI_VOLARI_Z;
1860 } else if(ivideo->chip >= XGI_40) {
1861 fix->accel = FB_ACCEL_XGI_VOLARI_V;
1863 fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
1869 /* ---------------- fb_ops structures ----------------- */
1871 static struct fb_ops sisfb_ops = {
1872 .owner = THIS_MODULE,
1873 .fb_open = sisfb_open,
1874 .fb_release = sisfb_release,
1875 .fb_check_var = sisfb_check_var,
1876 .fb_set_par = sisfb_set_par,
1877 .fb_setcolreg = sisfb_setcolreg,
1878 .fb_pan_display = sisfb_pan_display,
1879 .fb_blank = sisfb_blank,
1880 .fb_fillrect = fbcon_sis_fillrect,
1881 .fb_copyarea = fbcon_sis_copyarea,
1882 .fb_imageblit = cfb_imageblit,
1883 .fb_sync = fbcon_sis_sync,
1884 #ifdef SIS_NEW_CONFIG_COMPAT
1885 .fb_compat_ioctl= sisfb_ioctl,
1887 .fb_ioctl = sisfb_ioctl
1890 /* ---------------- Chip generation dependent routines ---------------- */
1892 static struct pci_dev *sisfb_get_northbridge(int basechipid)
1894 struct pci_dev *pdev = NULL;
1895 int nbridgenum, nbridgeidx, i;
1896 static const unsigned short nbridgeids[] = {
1897 PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */
1898 PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */
1899 PCI_DEVICE_ID_SI_730,
1900 PCI_DEVICE_ID_SI_550, /* for SiS 550 VGA */
1901 PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */
1902 PCI_DEVICE_ID_SI_651,
1903 PCI_DEVICE_ID_SI_740,
1904 PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760/761 VGA */
1905 PCI_DEVICE_ID_SI_741,
1906 PCI_DEVICE_ID_SI_660,
1907 PCI_DEVICE_ID_SI_760,
1908 PCI_DEVICE_ID_SI_761
1911 switch(basechipid) {
1912 #ifdef CONFIG_FB_SIS_300
1913 case SIS_540: nbridgeidx = 0; nbridgenum = 1; break;
1914 case SIS_630: nbridgeidx = 1; nbridgenum = 2; break;
1916 #ifdef CONFIG_FB_SIS_315
1917 case SIS_550: nbridgeidx = 3; nbridgenum = 1; break;
1918 case SIS_650: nbridgeidx = 4; nbridgenum = 3; break;
1919 case SIS_660: nbridgeidx = 7; nbridgenum = 5; break;
1921 default: return NULL;
1923 for(i = 0; i < nbridgenum; i++) {
1924 if((pdev = pci_get_device(PCI_VENDOR_ID_SI,
1925 nbridgeids[nbridgeidx+i], NULL)))
1931 static int sisfb_get_dram_size(struct sis_video_info *ivideo)
1933 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1937 ivideo->video_size = 0;
1938 ivideo->UMAsize = ivideo->LFBsize = 0;
1940 switch(ivideo->chip) {
1941 #ifdef CONFIG_FB_SIS_300
1943 reg = SiS_GetReg(SISSR, 0x14);
1944 ivideo->video_size = ((reg & 0x3F) + 1) << 20;
1949 if(!ivideo->nbridge)
1951 pci_read_config_byte(ivideo->nbridge, 0x63, ®);
1952 ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
1955 #ifdef CONFIG_FB_SIS_315
1959 reg = SiS_GetReg(SISSR, 0x14);
1960 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
1961 switch((reg >> 2) & 0x03) {
1964 ivideo->video_size <<= 1;
1967 ivideo->video_size += (ivideo->video_size/2);
1971 reg = SiS_GetReg(SISSR, 0x14);
1972 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
1973 if(reg & 0x0c) ivideo->video_size <<= 1;
1978 reg = SiS_GetReg(SISSR, 0x14);
1979 ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
1983 reg = SiS_GetReg(SISCR, 0x79);
1984 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
1989 reg = SiS_GetReg(SISCR, 0x79);
1990 reg = (reg & 0xf0) >> 4;
1992 ivideo->video_size = (1 << reg) << 20;
1993 ivideo->UMAsize = ivideo->video_size;
1995 reg = SiS_GetReg(SISCR, 0x78);
1999 ivideo->LFBsize = (32 << 20);
2001 ivideo->LFBsize = (64 << 20);
2003 ivideo->video_size += ivideo->LFBsize;
2009 reg = SiS_GetReg(SISSR, 0x14);
2010 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2011 if(ivideo->chip != XGI_20) {
2012 reg = (reg & 0x0c) >> 2;
2013 if(ivideo->revision_id == 2) {
2014 if(reg & 0x01) reg = 0x02;
2017 if(reg == 0x02) ivideo->video_size <<= 1;
2018 else if(reg == 0x03) ivideo->video_size <<= 2;
2028 /* -------------- video bridge device detection --------------- */
2030 static void sisfb_detect_VB_connect(struct sis_video_info *ivideo)
2034 /* No CRT2 on XGI Z7 */
2035 if(ivideo->chip == XGI_20) {
2036 ivideo->sisfb_crt1off = 0;
2040 #ifdef CONFIG_FB_SIS_300
2041 if(ivideo->sisvga_engine == SIS_300_VGA) {
2042 temp = SiS_GetReg(SISSR, 0x17);
2043 if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
2044 /* PAL/NTSC is stored on SR16 on such machines */
2045 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
2046 temp = SiS_GetReg(SISSR, 0x16);
2048 ivideo->vbflags |= TV_PAL;
2050 ivideo->vbflags |= TV_NTSC;
2056 cr32 = SiS_GetReg(SISCR, 0x32);
2058 if(cr32 & SIS_CRT1) {
2059 ivideo->sisfb_crt1off = 0;
2061 ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0;
2064 ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
2066 if(cr32 & SIS_VB_TV) ivideo->vbflags |= CRT2_TV;
2067 if(cr32 & SIS_VB_LCD) ivideo->vbflags |= CRT2_LCD;
2068 if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA;
2070 /* Check given parms for hardware compatibility.
2071 * (Cannot do this in the search_xx routines since we don't
2072 * know what hardware we are running on then)
2075 if(ivideo->chip != SIS_550) {
2076 ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0;
2079 if(ivideo->sisfb_tvplug != -1) {
2080 if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2081 (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) {
2082 if(ivideo->sisfb_tvplug & TV_YPBPR) {
2083 ivideo->sisfb_tvplug = -1;
2084 printk(KERN_ERR "sisfb: YPbPr not supported\n");
2088 if(ivideo->sisfb_tvplug != -1) {
2089 if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2090 (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) {
2091 if(ivideo->sisfb_tvplug & TV_HIVISION) {
2092 ivideo->sisfb_tvplug = -1;
2093 printk(KERN_ERR "sisfb: HiVision not supported\n");
2097 if(ivideo->sisfb_tvstd != -1) {
2098 if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
2099 (!((ivideo->sisvga_engine == SIS_315_VGA) &&
2100 (ivideo->vbflags2 & VB2_CHRONTEL))) ) {
2101 if(ivideo->sisfb_tvstd & (TV_PALM | TV_PALN | TV_NTSCJ)) {
2102 ivideo->sisfb_tvstd = -1;
2103 printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
2108 /* Detect/set TV plug & type */
2109 if(ivideo->sisfb_tvplug != -1) {
2110 ivideo->vbflags |= ivideo->sisfb_tvplug;
2112 if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
2113 else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION;
2114 else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART;
2116 if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO;
2117 if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
2121 if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) {
2122 if(ivideo->sisfb_tvstd != -1) {
2123 ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ);
2124 ivideo->vbflags |= ivideo->sisfb_tvstd;
2126 if(ivideo->vbflags & TV_SCART) {
2127 ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ);
2128 ivideo->vbflags |= TV_PAL;
2130 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
2131 if(ivideo->sisvga_engine == SIS_300_VGA) {
2132 temp = SiS_GetReg(SISSR, 0x38);
2133 if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2134 else ivideo->vbflags |= TV_NTSC;
2135 } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
2136 temp = SiS_GetReg(SISSR, 0x38);
2137 if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2138 else ivideo->vbflags |= TV_NTSC;
2140 temp = SiS_GetReg(SISCR, 0x79);
2141 if(temp & 0x20) ivideo->vbflags |= TV_PAL;
2142 else ivideo->vbflags |= TV_NTSC;
2147 /* Copy forceCRT1 option to CRT1off if option is given */
2148 if(ivideo->sisfb_forcecrt1 != -1) {
2149 ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
2153 /* ------------------ Sensing routines ------------------ */
2155 static bool sisfb_test_DDC1(struct sis_video_info *ivideo)
2160 old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
2162 if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
2164 return (count != -1);
2167 static void sisfb_sense_crt1(struct sis_video_info *ivideo)
2169 bool mustwait = false;
2171 #ifdef CONFIG_FB_SIS_315
2177 sr1F = SiS_GetReg(SISSR, 0x1F);
2178 SiS_SetRegOR(SISSR, 0x1F, 0x04);
2179 SiS_SetRegAND(SISSR, 0x1F, 0x3F);
2180 if(sr1F & 0xc0) mustwait = true;
2182 #ifdef CONFIG_FB_SIS_315
2183 if(ivideo->sisvga_engine == SIS_315_VGA) {
2184 cr63 = SiS_GetReg(SISCR, ivideo->SiS_Pr.SiS_MyCR63);
2186 SiS_SetRegAND(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF);
2190 cr17 = SiS_GetReg(SISCR, 0x17);
2193 SiS_SetRegOR(SISCR, 0x17, 0x80);
2195 SiS_SetReg(SISSR, 0x00, 0x01);
2196 SiS_SetReg(SISSR, 0x00, 0x03);
2200 for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo);
2203 #ifdef CONFIG_FB_SIS_315
2204 if(ivideo->chip >= SIS_330) {
2205 SiS_SetRegAND(SISCR, 0x32, ~0x20);
2206 if(ivideo->chip >= SIS_340) {
2207 SiS_SetReg(SISCR, 0x57, 0x4a);
2209 SiS_SetReg(SISCR, 0x57, 0x5f);
2211 SiS_SetRegOR(SISCR, 0x53, 0x02);
2212 while ((SiS_GetRegByte(SISINPSTAT)) & 0x01) break;
2213 while (!((SiS_GetRegByte(SISINPSTAT)) & 0x01)) break;
2214 if ((SiS_GetRegByte(SISMISCW)) & 0x10) temp = 1;
2215 SiS_SetRegAND(SISCR, 0x53, 0xfd);
2216 SiS_SetRegAND(SISCR, 0x57, 0x00);
2220 if(temp == 0xffff) {
2223 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2224 ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
2225 } while(((temp == 0) || (temp == 0xffff)) && i--);
2227 if((temp == 0) || (temp == 0xffff)) {
2228 if(sisfb_test_DDC1(ivideo)) temp = 1;
2232 if((temp) && (temp != 0xffff)) {
2233 SiS_SetRegOR(SISCR, 0x32, 0x20);
2236 #ifdef CONFIG_FB_SIS_315
2237 if(ivideo->sisvga_engine == SIS_315_VGA) {
2238 SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF, cr63);
2242 SiS_SetRegANDOR(SISCR, 0x17, 0x7F, cr17);
2244 SiS_SetReg(SISSR, 0x1F, sr1F);
2247 /* Determine and detect attached devices on SiS30x */
2248 static void SiS_SenseLCD(struct sis_video_info *ivideo)
2250 unsigned char buffer[256];
2251 unsigned short temp, realcrtno, i;
2252 u8 reg, cr37 = 0, paneltype = 0;
2255 ivideo->SiS_Pr.PanelSelfDetected = false;
2257 /* LCD detection only for TMDS bridges */
2258 if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
2260 if(ivideo->vbflags2 & VB2_30xBDH)
2263 /* If LCD already set up by BIOS, skip it */
2264 reg = SiS_GetReg(SISCR, 0x32);
2269 if(ivideo->SiS_Pr.DDCPortMixup)
2272 /* Check DDC capabilities */
2273 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
2274 realcrtno, 0, &buffer[0], ivideo->vbflags2);
2276 if((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
2280 i = 3; /* Number of retrys */
2282 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2283 ivideo->sisvga_engine, realcrtno, 1,
2284 &buffer[0], ivideo->vbflags2);
2285 } while((temp) && i--);
2290 /* No digital device */
2291 if(!(buffer[0x14] & 0x80))
2294 /* First detailed timing preferred timing? */
2295 if(!(buffer[0x18] & 0x02))
2298 xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
2299 yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
2311 if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
2322 if((buffer[0x47] & 0x18) == 0x18)
2323 cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2327 SiS_SetReg(SISCR, 0x36, paneltype);
2329 SiS_SetRegANDOR(SISCR, 0x37, 0x0c, cr37);
2330 SiS_SetRegOR(SISCR, 0x32, 0x08);
2332 ivideo->SiS_Pr.PanelSelfDetected = true;
2335 static int SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
2337 int temp, mytest, result, i, j;
2339 for(j = 0; j < 10; j++) {
2341 for(i = 0; i < 3; i++) {
2343 SiS_SetReg(SISPART4, 0x11, (type & 0x00ff));
2344 temp = (type >> 8) | (mytest & 0x00ff);
2345 SiS_SetRegANDOR(SISPART4, 0x10, 0xe0, temp);
2346 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
2349 temp = SiS_GetReg(SISPART4, 0x03);
2352 if(temp == mytest) result++;
2354 SiS_SetReg(SISPART4, 0x11, 0x00);
2355 SiS_SetRegAND(SISPART4, 0x10, 0xe0);
2356 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
2359 if((result == 0) || (result >= 2)) break;
2364 static void SiS_Sense30x(struct sis_video_info *ivideo)
2366 u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
2367 u16 svhs=0, svhs_c=0;
2368 u16 cvbs=0, cvbs_c=0;
2369 u16 vga2=0, vga2_c=0;
2371 char stdstr[] = "sisfb: Detected";
2372 char tvstr[] = "TV connected to";
2374 if(ivideo->vbflags2 & VB2_301) {
2375 svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
2376 myflag = SiS_GetReg(SISPART4, 0x01);
2378 svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
2380 } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) {
2381 svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
2382 } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) {
2383 svhs = 0x0200; cvbs = 0x0100;
2384 } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
2385 svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
2389 vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
2390 if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
2391 svhs_c = 0x0408; cvbs_c = 0x0808;
2395 if(ivideo->haveXGIROM) {
2396 biosflag = ivideo->bios_abase[0x58] & 0x03;
2397 } else if(ivideo->newrom) {
2398 if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01;
2399 } else if(ivideo->sisvga_engine == SIS_300_VGA) {
2400 if(ivideo->bios_abase) {
2401 biosflag = ivideo->bios_abase[0xfe] & 0x03;
2405 if(ivideo->chip == SIS_300) {
2406 myflag = SiS_GetReg(SISSR, 0x3b);
2407 if(!(myflag & 0x01)) vga2 = vga2_c = 0;
2410 if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) {
2414 backupSR_1e = SiS_GetReg(SISSR, 0x1e);
2415 SiS_SetRegOR(SISSR, 0x1e, 0x20);
2417 backupP4_0d = SiS_GetReg(SISPART4, 0x0d);
2418 if(ivideo->vbflags2 & VB2_30xC) {
2419 SiS_SetRegANDOR(SISPART4, 0x0d, ~0x07, 0x01);
2421 SiS_SetRegOR(SISPART4, 0x0d, 0x04);
2423 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2425 backupP2_00 = SiS_GetReg(SISPART2, 0x00);
2426 SiS_SetReg(SISPART2, 0x00, ((backupP2_00 | 0x1c) & 0xfc));
2428 backupP2_4d = SiS_GetReg(SISPART2, 0x4d);
2429 if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
2430 SiS_SetReg(SISPART2, 0x4d, (backupP2_4d & ~0x10));
2433 if(!(ivideo->vbflags2 & VB2_30xCLV)) {
2434 SISDoSense(ivideo, 0, 0);
2437 SiS_SetRegAND(SISCR, 0x32, ~0x14);
2439 if(vga2_c || vga2) {
2440 if(SISDoSense(ivideo, vga2, vga2_c)) {
2441 if(biosflag & 0x01) {
2442 printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
2443 SiS_SetRegOR(SISCR, 0x32, 0x04);
2445 printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
2446 SiS_SetRegOR(SISCR, 0x32, 0x10);
2451 SiS_SetRegAND(SISCR, 0x32, 0x3f);
2453 if(ivideo->vbflags2 & VB2_30xCLV) {
2454 SiS_SetRegOR(SISPART4, 0x0d, 0x04);
2457 if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
2458 SiS_SetReg(SISPART2, 0x4d, (backupP2_4d | 0x10));
2459 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2460 if((result = SISDoSense(ivideo, svhs, 0x0604))) {
2461 if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
2462 printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
2463 SiS_SetRegOR(SISCR, 0x32, 0x80);
2466 SiS_SetReg(SISPART2, 0x4d, backupP2_4d);
2469 SiS_SetRegAND(SISCR, 0x32, ~0x03);
2471 if(!(ivideo->vbflags & TV_YPBPR)) {
2472 if((result = SISDoSense(ivideo, svhs, svhs_c))) {
2473 printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
2474 SiS_SetRegOR(SISCR, 0x32, 0x02);
2476 if((biosflag & 0x02) || (!result)) {
2477 if(SISDoSense(ivideo, cvbs, cvbs_c)) {
2478 printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
2479 SiS_SetRegOR(SISCR, 0x32, 0x01);
2484 SISDoSense(ivideo, 0, 0);
2486 SiS_SetReg(SISPART2, 0x00, backupP2_00);
2487 SiS_SetReg(SISPART4, 0x0d, backupP4_0d);
2488 SiS_SetReg(SISSR, 0x1e, backupSR_1e);
2490 if(ivideo->vbflags2 & VB2_30xCLV) {
2491 biosflag = SiS_GetReg(SISPART2, 0x00);
2492 if(biosflag & 0x20) {
2493 for(myflag = 2; myflag > 0; myflag--) {
2495 SiS_SetReg(SISPART2, 0x00, biosflag);
2500 SiS_SetReg(SISPART2, 0x00, backupP2_00);
2503 /* Determine and detect attached TV's on Chrontel */
2504 static void SiS_SenseCh(struct sis_video_info *ivideo)
2506 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2508 char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
2510 #ifdef CONFIG_FB_SIS_300
2511 unsigned char test[3];
2515 if(ivideo->chip < SIS_315H) {
2517 #ifdef CONFIG_FB_SIS_300
2518 ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1; /* Chrontel 700x */
2519 SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c); /* Set general purpose IO for Chrontel communication */
2520 SiS_DDC2Delay(&ivideo->SiS_Pr, 1000);
2521 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2522 /* See Chrontel TB31 for explanation */
2523 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2524 if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
2525 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b);
2526 SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2528 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2529 if(temp2 != temp1) temp1 = temp2;
2531 if((temp1 >= 0x22) && (temp1 <= 0x50)) {
2532 /* Read power status */
2533 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2534 if((temp1 & 0x03) != 0x03) {
2535 /* Power all outputs */
2536 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b);
2537 SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2539 /* Sense connected TV devices */
2540 for(i = 0; i < 3; i++) {
2541 SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01);
2542 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2543 SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00);
2544 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2545 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
2546 if(!(temp1 & 0x08)) test[i] = 0x02;
2547 else if(!(temp1 & 0x02)) test[i] = 0x01;
2549 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2552 if(test[0] == test[1]) temp1 = test[0];
2553 else if(test[0] == test[2]) temp1 = test[0];
2554 else if(test[1] == test[2]) temp1 = test[1];
2557 "sisfb: TV detection unreliable - test results varied\n");
2561 printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2562 ivideo->vbflags |= TV_SVIDEO;
2563 SiS_SetRegOR(SISCR, 0x32, 0x02);
2564 SiS_SetRegAND(SISCR, 0x32, ~0x05);
2565 } else if (temp1 == 0x01) {
2566 printk(KERN_INFO "%s CVBS output\n", stdstr);
2567 ivideo->vbflags |= TV_AVIDEO;
2568 SiS_SetRegOR(SISCR, 0x32, 0x01);
2569 SiS_SetRegAND(SISCR, 0x32, ~0x06);
2571 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2572 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2574 } else if(temp1 == 0) {
2575 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2576 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2578 /* Set general purpose IO for Chrontel communication */
2579 SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
2584 #ifdef CONFIG_FB_SIS_315
2585 ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */
2586 temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
2587 SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20);
2588 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2589 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2591 SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2592 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2594 SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2595 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2596 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2597 SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1);
2599 if(temp2 & 0x02) temp1 |= 0x01;
2600 if(temp2 & 0x10) temp1 |= 0x01;
2601 if(temp2 & 0x04) temp1 |= 0x02;
2602 if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
2605 printk(KERN_INFO "%s CVBS output\n", stdstr);
2606 ivideo->vbflags |= TV_AVIDEO;
2607 SiS_SetRegOR(SISCR, 0x32, 0x01);
2608 SiS_SetRegAND(SISCR, 0x32, ~0x06);
2611 printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2612 ivideo->vbflags |= TV_SVIDEO;
2613 SiS_SetRegOR(SISCR, 0x32, 0x02);
2614 SiS_SetRegAND(SISCR, 0x32, ~0x05);
2617 printk(KERN_INFO "%s SCART output\n", stdstr);
2618 SiS_SetRegOR(SISCR, 0x32, 0x04);
2619 SiS_SetRegAND(SISCR, 0x32, ~0x03);
2622 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2628 static void sisfb_get_VB_type(struct sis_video_info *ivideo)
2630 char stdstr[] = "sisfb: Detected";
2631 char bridgestr[] = "video bridge";
2635 /* No CRT2 on XGI Z7 */
2636 if(ivideo->chip == XGI_20)
2639 vb_chipid = SiS_GetReg(SISPART4, 0x00);
2642 reg = SiS_GetReg(SISPART4, 0x01);
2644 ivideo->vbflags |= VB_301; /* Deprecated */
2645 ivideo->vbflags2 |= VB2_301;
2646 printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
2647 } else if(reg < 0xc0) {
2648 ivideo->vbflags |= VB_301B; /* Deprecated */
2649 ivideo->vbflags2 |= VB2_301B;
2650 reg = SiS_GetReg(SISPART4, 0x23);
2652 ivideo->vbflags |= VB_30xBDH; /* Deprecated */
2653 ivideo->vbflags2 |= VB2_30xBDH;
2654 printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
2656 printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
2658 } else if(reg < 0xd0) {
2659 ivideo->vbflags |= VB_301C; /* Deprecated */
2660 ivideo->vbflags2 |= VB2_301C;
2661 printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
2662 } else if(reg < 0xe0) {
2663 ivideo->vbflags |= VB_301LV; /* Deprecated */
2664 ivideo->vbflags2 |= VB2_301LV;
2665 printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
2666 } else if(reg <= 0xe1) {
2667 reg = SiS_GetReg(SISPART4, 0x39);
2669 ivideo->vbflags |= VB_302LV; /* Deprecated */
2670 ivideo->vbflags2 |= VB2_302LV;
2671 printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
2673 ivideo->vbflags |= VB_301C; /* Deprecated */
2674 ivideo->vbflags2 |= VB2_301C;
2675 printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
2677 ivideo->vbflags |= VB_302ELV; /* Deprecated */
2678 ivideo->vbflags2 |= VB2_302ELV;
2679 printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
2685 ivideo->vbflags |= VB_302B; /* Deprecated */
2686 ivideo->vbflags2 |= VB2_302B;
2687 printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
2691 if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
2692 reg = SiS_GetReg(SISCR, 0x37);
2693 reg &= SIS_EXTERNAL_CHIP_MASK;
2695 if(ivideo->sisvga_engine == SIS_300_VGA) {
2696 #ifdef CONFIG_FB_SIS_300
2698 case SIS_EXTERNAL_CHIP_LVDS:
2699 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2700 ivideo->vbflags2 |= VB2_LVDS;
2702 case SIS_EXTERNAL_CHIP_TRUMPION:
2703 ivideo->vbflags |= (VB_LVDS | VB_TRUMPION); /* Deprecated */
2704 ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION);
2706 case SIS_EXTERNAL_CHIP_CHRONTEL:
2707 ivideo->vbflags |= VB_CHRONTEL; /* Deprecated */
2708 ivideo->vbflags2 |= VB2_CHRONTEL;
2710 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
2711 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2712 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2715 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1;
2717 } else if(ivideo->chip < SIS_661) {
2718 #ifdef CONFIG_FB_SIS_315
2720 case SIS310_EXTERNAL_CHIP_LVDS:
2721 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2722 ivideo->vbflags2 |= VB2_LVDS;
2724 case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
2725 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2726 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2729 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2731 } else if(ivideo->chip >= SIS_661) {
2732 #ifdef CONFIG_FB_SIS_315
2733 reg = SiS_GetReg(SISCR, 0x38);
2737 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2738 ivideo->vbflags2 |= VB2_LVDS;
2741 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2742 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2745 ivideo->vbflags |= (VB_LVDS | VB_CONEXANT); /* Deprecated */
2746 ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT);
2749 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2752 if(ivideo->vbflags2 & VB2_LVDS) {
2753 printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
2755 if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) {
2756 printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
2758 if(ivideo->vbflags2 & VB2_CHRONTEL) {
2759 printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
2761 if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) {
2762 printk(KERN_INFO "%s Conexant external device\n", stdstr);
2766 if(ivideo->vbflags2 & VB2_SISBRIDGE) {
2767 SiS_SenseLCD(ivideo);
2768 SiS_Sense30x(ivideo);
2769 } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
2770 SiS_SenseCh(ivideo);
2774 /* ---------- Engine initialization routines ------------ */
2777 sisfb_engine_init(struct sis_video_info *ivideo)
2780 /* Initialize command queue (we use MMIO only) */
2782 /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
2784 ivideo->caps &= ~(TURBO_QUEUE_CAP |
2785 MMIO_CMD_QUEUE_CAP |
2789 #ifdef CONFIG_FB_SIS_300
2790 if(ivideo->sisvga_engine == SIS_300_VGA) {
2794 tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
2796 tq_state = SiS_GetReg(SISSR, IND_SIS_TURBOQUEUE_SET);
2799 tq_state |= (u8)(tqueue_pos >> 8);
2800 SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
2802 SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
2804 ivideo->caps |= TURBO_QUEUE_CAP;
2808 #ifdef CONFIG_FB_SIS_315
2809 if(ivideo->sisvga_engine == SIS_315_VGA) {
2810 u32 tempq = 0, templ;
2813 if(ivideo->chip == XGI_20) {
2814 switch(ivideo->cmdQueueSize) {
2816 temp = SIS_CMD_QUEUE_SIZE_Z7_64k;
2820 temp = SIS_CMD_QUEUE_SIZE_Z7_128k;
2823 switch(ivideo->cmdQueueSize) {
2824 case (4 * 1024 * 1024):
2825 temp = SIS_CMD_QUEUE_SIZE_4M;
2827 case (2 * 1024 * 1024):
2828 temp = SIS_CMD_QUEUE_SIZE_2M;
2830 case (1 * 1024 * 1024):
2831 temp = SIS_CMD_QUEUE_SIZE_1M;
2835 temp = SIS_CMD_QUEUE_SIZE_512k;
2839 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2840 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2842 if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
2843 /* Must disable dual pipe on XGI_40. Can't do
2844 * this in MMIO mode, because it requires
2845 * setting/clearing a bit in the MMIO fire trigger
2848 if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) {
2850 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
2852 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
2854 tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
2855 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
2857 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2858 MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq);
2860 writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq);
2861 writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4);
2862 writel(0x168F0000, ivideo->video_vbase + tempq + 8);
2863 writel(0x168F0000, ivideo->video_vbase + tempq + 12);
2865 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16));
2867 sisfb_syncaccel(ivideo);
2869 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2874 tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
2875 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
2877 temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
2878 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, temp);
2880 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2881 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
2883 ivideo->caps |= MMIO_CMD_QUEUE_CAP;
2887 ivideo->engineok = 1;
2890 static void sisfb_detect_lcd_type(struct sis_video_info *ivideo)
2895 reg = SiS_GetReg(SISCR, 0x36);
2897 if(ivideo->sisvga_engine == SIS_300_VGA) {
2898 ivideo->CRT2LCDType = sis300paneltype[reg];
2899 } else if(ivideo->chip >= SIS_661) {
2900 ivideo->CRT2LCDType = sis661paneltype[reg];
2902 ivideo->CRT2LCDType = sis310paneltype[reg];
2903 if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
2904 if((ivideo->CRT2LCDType != LCD_320x240_2) &&
2905 (ivideo->CRT2LCDType != LCD_320x240_3)) {
2906 ivideo->CRT2LCDType = LCD_320x240;
2911 if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
2912 /* For broken BIOSes: Assume 1024x768, RGB18 */
2913 ivideo->CRT2LCDType = LCD_1024x768;
2914 SiS_SetRegANDOR(SISCR, 0x36, 0xf0, 0x02);
2915 SiS_SetRegANDOR(SISCR, 0x37, 0xee, 0x01);
2916 printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
2919 for(i = 0; i < SIS_LCD_NUMBER; i++) {
2920 if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
2921 ivideo->lcdxres = sis_lcd_data[i].xres;
2922 ivideo->lcdyres = sis_lcd_data[i].yres;
2923 ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
2928 #ifdef CONFIG_FB_SIS_300
2929 if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
2930 ivideo->lcdxres = 1360; ivideo->lcdyres = 1024;
2931 ivideo->lcddefmodeidx = DEFAULT_MODE_1360;
2932 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
2933 ivideo->lcdxres = 848; ivideo->lcdyres = 480;
2934 ivideo->lcddefmodeidx = DEFAULT_MODE_848;
2935 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) {
2936 ivideo->lcdxres = 856; ivideo->lcdyres = 480;
2937 ivideo->lcddefmodeidx = DEFAULT_MODE_856;
2941 printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
2942 ivideo->lcdxres, ivideo->lcdyres);
2945 static void sisfb_save_pdc_emi(struct sis_video_info *ivideo)
2947 #ifdef CONFIG_FB_SIS_300
2948 /* Save the current PanelDelayCompensation if the LCD is currently used */
2949 if(ivideo->sisvga_engine == SIS_300_VGA) {
2950 if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
2952 tmp = SiS_GetReg(SISCR, 0x30);
2954 /* Currently on LCD? If yes, read current pdc */
2955 ivideo->detectedpdc = SiS_GetReg(SISPART1, 0x13);
2956 ivideo->detectedpdc &= 0x3c;
2957 if(ivideo->SiS_Pr.PDC == -1) {
2958 /* Let option override detection */
2959 ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
2961 printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
2962 ivideo->detectedpdc);
2964 if((ivideo->SiS_Pr.PDC != -1) &&
2965 (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
2966 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
2967 ivideo->SiS_Pr.PDC);
2973 #ifdef CONFIG_FB_SIS_315
2974 if(ivideo->sisvga_engine == SIS_315_VGA) {
2976 /* Try to find about LCDA */
2977 if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
2979 tmp = SiS_GetReg(SISPART1, 0x13);
2981 ivideo->SiS_Pr.SiS_UseLCDA = true;
2982 ivideo->detectedlcda = 0x03;
2987 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
2989 tmp = SiS_GetReg(SISCR, 0x30);
2990 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
2991 /* Currently on LCD? If yes, read current pdc */
2993 pdc = SiS_GetReg(SISPART1, 0x2D);
2994 ivideo->detectedpdc = (pdc & 0x0f) << 1;
2995 ivideo->detectedpdca = (pdc & 0xf0) >> 3;
2996 pdc = SiS_GetReg(SISPART1, 0x35);
2997 ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
2998 pdc = SiS_GetReg(SISPART1, 0x20);
2999 ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
3000 if(ivideo->newrom) {
3001 /* New ROM invalidates other PDC resp. */
3002 if(ivideo->detectedlcda != 0xff) {
3003 ivideo->detectedpdc = 0xff;
3005 ivideo->detectedpdca = 0xff;
3008 if(ivideo->SiS_Pr.PDC == -1) {
3009 if(ivideo->detectedpdc != 0xff) {
3010 ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
3013 if(ivideo->SiS_Pr.PDCA == -1) {
3014 if(ivideo->detectedpdca != 0xff) {
3015 ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
3018 if(ivideo->detectedpdc != 0xff) {
3020 "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3021 ivideo->detectedpdc);
3023 if(ivideo->detectedpdca != 0xff) {
3025 "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3026 ivideo->detectedpdca);
3031 if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
3032 ivideo->SiS_Pr.EMI_30 = SiS_GetReg(SISPART4, 0x30);
3033 ivideo->SiS_Pr.EMI_31 = SiS_GetReg(SISPART4, 0x31);
3034 ivideo->SiS_Pr.EMI_32 = SiS_GetReg(SISPART4, 0x32);
3035 ivideo->SiS_Pr.EMI_33 = SiS_GetReg(SISPART4, 0x33);
3036 ivideo->SiS_Pr.HaveEMI = true;
3037 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3038 ivideo->SiS_Pr.HaveEMILCD = true;
3043 /* Let user override detected PDCs (all bridges) */
3044 if(ivideo->vbflags2 & VB2_30xBLV) {
3045 if((ivideo->SiS_Pr.PDC != -1) &&
3046 (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
3047 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3048 ivideo->SiS_Pr.PDC);
3050 if((ivideo->SiS_Pr.PDCA != -1) &&
3051 (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
3052 printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3053 ivideo->SiS_Pr.PDCA);
3061 /* -------------------- Memory manager routines ---------------------- */
3063 static u32 sisfb_getheapstart(struct sis_video_info *ivideo)
3065 u32 ret = ivideo->sisfb_parm_mem * 1024;
3066 u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3069 /* Calculate heap start = end of memory for console
3071 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3072 * C = console, D = heap, H = HWCursor, Q = cmd-queue
3074 * On 76x in UMA+LFB mode, the layout is as follows:
3075 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3076 * where the heap is the entire UMA area, eventually
3077 * into the LFB area if the given mem parameter is
3078 * higher than the size of the UMA memory.
3080 * Basically given by "mem" parameter
3082 * maximum = videosize - cmd_queue - hwcursor
3083 * (results in a heap of size 0)
3084 * default = SiS 300: depends on videosize
3085 * SiS 315/330/340/XGI: 32k below max
3088 if(ivideo->sisvga_engine == SIS_300_VGA) {
3089 if(ivideo->video_size > 0x1000000) {
3091 } else if(ivideo->video_size > 0x800000) {
3096 } else if(ivideo->UMAsize && ivideo->LFBsize) {
3099 def = maxoffs - 0x8000;
3102 /* Use default for secondary card for now (FIXME) */
3103 if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0))
3109 static u32 sisfb_getheapsize(struct sis_video_info *ivideo)
3111 u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3114 if(ivideo->UMAsize && ivideo->LFBsize) {
3115 if( (!ivideo->sisfb_parm_mem) ||
3116 ((ivideo->sisfb_parm_mem * 1024) > max) ||
3117 ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) {
3118 ret = ivideo->UMAsize;
3119 max -= ivideo->UMAsize;
3121 ret = max - (ivideo->sisfb_parm_mem * 1024);
3122 max = ivideo->sisfb_parm_mem * 1024;
3124 ivideo->video_offset = ret;
3125 ivideo->sisfb_mem = max;
3127 ret = max - ivideo->heapstart;
3128 ivideo->sisfb_mem = ivideo->heapstart;
3134 static int sisfb_heap_init(struct sis_video_info *ivideo)
3138 ivideo->video_offset = 0;
3139 if(ivideo->sisfb_parm_mem) {
3140 if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) ||
3141 (ivideo->sisfb_parm_mem > ivideo->video_size) ) {
3142 ivideo->sisfb_parm_mem = 0;
3146 ivideo->heapstart = sisfb_getheapstart(ivideo);
3147 ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo);
3149 ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
3150 ivideo->sisfb_heap_end = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size;
3152 printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
3153 (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
3155 ivideo->sisfb_heap.vinfo = ivideo;
3157 ivideo->sisfb_heap.poha_chain = NULL;
3158 ivideo->sisfb_heap.poh_freelist = NULL;
3160 poh = sisfb_poh_new_node(&ivideo->sisfb_heap);
3164 poh->poh_next = &ivideo->sisfb_heap.oh_free;
3165 poh->poh_prev = &ivideo->sisfb_heap.oh_free;
3166 poh->size = ivideo->sisfb_heap_size;
3167 poh->offset = ivideo->heapstart;
3169 ivideo->sisfb_heap.oh_free.poh_next = poh;
3170 ivideo->sisfb_heap.oh_free.poh_prev = poh;
3171 ivideo->sisfb_heap.oh_free.size = 0;
3172 ivideo->sisfb_heap.max_freesize = poh->size;
3174 ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used;
3175 ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used;
3176 ivideo->sisfb_heap.oh_used.size = SENTINEL;
3178 if(ivideo->cardnumber == 0) {
3179 /* For the first card, make this heap the "global" one
3180 * for old DRM (which could handle only one card)
3182 sisfb_heap = &ivideo->sisfb_heap;
3188 static struct SIS_OH *
3189 sisfb_poh_new_node(struct SIS_HEAP *memheap)
3191 struct SIS_OHALLOC *poha;
3196 if(memheap->poh_freelist == NULL) {
3197 poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
3201 poha->poha_next = memheap->poha_chain;
3202 memheap->poha_chain = poha;
3204 cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1;
3206 poh = &poha->aoh[0];
3207 for(i = cOhs - 1; i != 0; i--) {
3208 poh->poh_next = poh + 1;
3212 poh->poh_next = NULL;
3213 memheap->poh_freelist = &poha->aoh[0];
3216 poh = memheap->poh_freelist;
3217 memheap->poh_freelist = poh->poh_next;
3222 static struct SIS_OH *
3223 sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size)
3225 struct SIS_OH *pohThis;
3226 struct SIS_OH *pohRoot;
3229 if(size > memheap->max_freesize) {
3230 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3231 (unsigned int) size / 1024);
3235 pohThis = memheap->oh_free.poh_next;
3237 while(pohThis != &memheap->oh_free) {
3238 if(size <= pohThis->size) {
3242 pohThis = pohThis->poh_next;
3246 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3247 (unsigned int) size / 1024);
3251 if(size == pohThis->size) {
3253 sisfb_delete_node(pohThis);
3255 pohRoot = sisfb_poh_new_node(memheap);
3259 pohRoot->offset = pohThis->offset;
3260 pohRoot->size = size;
3262 pohThis->offset += size;
3263 pohThis->size -= size;
3266 memheap->max_freesize -= size;
3268 pohThis = &memheap->oh_used;
3269 sisfb_insert_node(pohThis, pohRoot);
3275 sisfb_delete_node(struct SIS_OH *poh)
3277 poh->poh_prev->poh_next = poh->poh_next;
3278 poh->poh_next->poh_prev = poh->poh_prev;
3282 sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh)
3284 struct SIS_OH *pohTemp = pohList->poh_next;
3286 pohList->poh_next = poh;
3287 pohTemp->poh_prev = poh;
3289 poh->poh_prev = pohList;
3290 poh->poh_next = pohTemp;
3293 static struct SIS_OH *
3294 sisfb_poh_free(struct SIS_HEAP *memheap, u32 base)
3296 struct SIS_OH *pohThis;
3297 struct SIS_OH *poh_freed;
3298 struct SIS_OH *poh_prev;
3299 struct SIS_OH *poh_next;
3304 poh_freed = memheap->oh_used.poh_next;
3306 while(poh_freed != &memheap->oh_used) {
3307 if(poh_freed->offset == base) {
3312 poh_freed = poh_freed->poh_next;
3318 memheap->max_freesize += poh_freed->size;
3320 poh_prev = poh_next = NULL;
3321 ulUpper = poh_freed->offset + poh_freed->size;
3322 ulLower = poh_freed->offset;
3324 pohThis = memheap->oh_free.poh_next;
3326 while(pohThis != &memheap->oh_free) {
3327 if(pohThis->offset == ulUpper) {
3329 } else if((pohThis->offset + pohThis->size) == ulLower) {
3332 pohThis = pohThis->poh_next;
3335 sisfb_delete_node(poh_freed);
3337 if(poh_prev && poh_next) {
3338 poh_prev->size += (poh_freed->size + poh_next->size);
3339 sisfb_delete_node(poh_next);
3340 sisfb_free_node(memheap, poh_freed);
3341 sisfb_free_node(memheap, poh_next);
3346 poh_prev->size += poh_freed->size;
3347 sisfb_free_node(memheap, poh_freed);
3352 poh_next->size += poh_freed->size;
3353 poh_next->offset = poh_freed->offset;
3354 sisfb_free_node(memheap, poh_freed);
3358 sisfb_insert_node(&memheap->oh_free, poh_freed);
3364 sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh)
3369 poh->poh_next = memheap->poh_freelist;
3370 memheap->poh_freelist = poh;
3374 sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req)
3376 struct SIS_OH *poh = NULL;
3378 if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap))
3379 poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size);
3382 req->offset = req->size = 0;
3383 DPRINTK("sisfb: Video RAM allocation failed\n");
3385 req->offset = poh->offset;
3386 req->size = poh->size;
3387 DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3388 (poh->offset + ivideo->video_vbase));
3393 sis_malloc(struct sis_memreq *req)
3395 struct sis_video_info *ivideo = sisfb_heap->vinfo;
3397 if(&ivideo->sisfb_heap == sisfb_heap)
3398 sis_int_malloc(ivideo, req);
3400 req->offset = req->size = 0;
3404 sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
3406 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3408 sis_int_malloc(ivideo, req);
3411 /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3414 sis_int_free(struct sis_video_info *ivideo, u32 base)