1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * SiS 300/540/630[S]/730[S],
4 * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
6 * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
8 * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
10 * Author: Thomas Winischhofer <thomas@winischhofer.net>
12 * Author of (practically wiped) code base:
14 * Copyright (C) 1999 Silicon Integrated Systems, Inc.
16 * See http://www.winischhofer.net/ for more information and updates
18 * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver,
19 * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
22 #include <linux/module.h>
23 #include <linux/moduleparam.h>
24 #include <linux/kernel.h>
25 #include <linux/spinlock.h>
26 #include <linux/errno.h>
27 #include <linux/string.h>
29 #include <linux/screen_info.h>
30 #include <linux/slab.h>
32 #include <linux/selection.h>
33 #include <linux/ioport.h>
34 #include <linux/init.h>
35 #include <linux/pci.h>
36 #include <linux/vmalloc.h>
37 #include <linux/capability.h>
39 #include <linux/types.h>
40 #include <linux/uaccess.h>
47 #if !defined(CONFIG_FB_SIS_300) && !defined(CONFIG_FB_SIS_315)
48 #warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
49 #warning sisfb will not work!
52 /* ---------------------- Prototypes ------------------------- */
54 /* Interface used by the world */
56 static int sisfb_setup(char *options);
59 /* Interface to the low level console driver */
60 static int sisfb_init(void);
63 static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
64 struct fb_info *info);
66 static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
68 static int sisfb_set_par(struct fb_info *info);
69 static int sisfb_blank(int blank,
70 struct fb_info *info);
72 static void sisfb_handle_command(struct sis_video_info *ivideo,
73 struct sisfb_cmd *sisfb_command);
75 static void sisfb_search_mode(char *name, bool quiet);
76 static int sisfb_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags);
77 static u8 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate,
79 static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green,
80 unsigned blue, unsigned transp,
81 struct fb_info *fb_info);
82 static int sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
83 struct fb_info *info);
84 static void sisfb_pre_setmode(struct sis_video_info *ivideo);
85 static void sisfb_post_setmode(struct sis_video_info *ivideo);
86 static bool sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
87 static bool sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
88 static bool sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
89 static bool sisfb_bridgeisslave(struct sis_video_info *ivideo);
90 static void sisfb_detect_VB_connect(struct sis_video_info *ivideo);
91 static void sisfb_get_VB_type(struct sis_video_info *ivideo);
92 static void sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val);
93 static void sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val);
95 /* Internal heap routines */
96 static int sisfb_heap_init(struct sis_video_info *ivideo);
97 static struct SIS_OH * sisfb_poh_new_node(struct SIS_HEAP *memheap);
98 static struct SIS_OH * sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size);
99 static void sisfb_delete_node(struct SIS_OH *poh);
100 static void sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh);
101 static struct SIS_OH * sisfb_poh_free(struct SIS_HEAP *memheap, u32 base);
102 static void sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh);
105 /* ------------------ Internal helper routines ----------------- */
108 sisfb_setdefaultparms(void)
118 sisfb_parm_rate = -1;
120 sisfb_forcecrt1 = -1;
126 sisfb_specialtiming = CUT_NONE;
132 sisfb_tvxposoffset = 0;
133 sisfb_tvyposoffset = 0;
134 sisfb_nocrt2rate = 0;
135 #if !defined(__i386__) && !defined(__x86_64__)
141 /* ------------- Parameter parsing -------------- */
143 static void sisfb_search_vesamode(unsigned int vesamode, bool quiet)
147 /* We don't know the hardware specs yet and there is no ivideo */
151 printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
153 sisfb_mode_idx = DEFAULT_MODE;
158 vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
160 while(sisbios_mode[i++].mode_no[0] != 0) {
161 if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
162 (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
164 if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
165 sisbios_mode[i-1].mode_no[1] == 0x56 ||
166 sisbios_mode[i-1].mode_no[1] == 0x53)
169 if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
170 sisbios_mode[i-1].mode_no[1] == 0x5b)
173 sisfb_mode_idx = i - 1;
179 printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
182 static void sisfb_search_mode(char *name, bool quiet)
184 unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
186 char strbuf[16], strbuf1[20];
187 char *nameptr = name;
189 /* We don't know the hardware specs yet and there is no ivideo */
193 printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
195 sisfb_mode_idx = DEFAULT_MODE;
199 if(!strncasecmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
201 printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
203 sisfb_mode_idx = DEFAULT_MODE;
207 if(strlen(name) <= 19) {
208 strcpy(strbuf1, name);
209 for(i = 0; i < strlen(strbuf1); i++) {
210 if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
213 /* This does some fuzzy mode naming detection */
214 if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
215 if((rate <= 32) || (depth > 32)) {
216 j = rate; rate = depth; depth = j;
218 sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
220 sisfb_parm_rate = rate;
221 } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
222 sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
226 if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
227 sprintf(strbuf, "%ux%ux8", xres, yres);
230 sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
237 while(sisbios_mode[i].mode_no[0] != 0) {
238 if(!strncasecmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
240 if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
241 sisbios_mode[i-1].mode_no[1] == 0x56 ||
242 sisbios_mode[i-1].mode_no[1] == 0x53)
245 if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
246 sisbios_mode[i-1].mode_no[1] == 0x5b)
249 sisfb_mode_idx = i - 1;
256 printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
260 static void sisfb_get_vga_mode_from_kernel(void)
264 int mydepth = screen_info.lfb_depth;
266 if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
268 if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) &&
269 (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
270 (mydepth >= 8) && (mydepth <= 32) ) {
272 if(mydepth == 24) mydepth = 32;
274 sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
275 screen_info.lfb_height,
279 "sisfb: Using vga mode %s pre-set by kernel as default\n",
282 sisfb_search_mode(mymode, true);
290 sisfb_search_crt2type(const char *name)
294 /* We don't know the hardware specs yet and there is no ivideo */
296 if(name == NULL) return;
298 while(sis_crt2type[i].type_no != -1) {
299 if(!strncasecmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
300 sisfb_crt2type = sis_crt2type[i].type_no;
301 sisfb_tvplug = sis_crt2type[i].tvplug_no;
302 sisfb_crt2flags = sis_crt2type[i].flags;
308 sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
309 sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
311 if(sisfb_crt2type < 0)
312 printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
316 sisfb_search_tvstd(const char *name)
320 /* We don't know the hardware specs yet and there is no ivideo */
325 while(sis_tvtype[i].type_no != -1) {
326 if(!strncasecmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
327 sisfb_tvstd = sis_tvtype[i].type_no;
335 sisfb_search_specialtiming(const char *name)
340 /* We don't know the hardware specs yet and there is no ivideo */
345 if(!strncasecmp(name, "none", 4)) {
346 sisfb_specialtiming = CUT_FORCENONE;
347 printk(KERN_DEBUG "sisfb: Special timing disabled\n");
349 while(mycustomttable[i].chipID != 0) {
350 if(!strncasecmp(name,mycustomttable[i].optionName,
351 strlen(mycustomttable[i].optionName))) {
352 sisfb_specialtiming = mycustomttable[i].SpecialID;
354 printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
355 mycustomttable[i].vendorName,
356 mycustomttable[i].cardName,
357 mycustomttable[i].optionName);
363 printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
364 printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
366 while(mycustomttable[i].chipID != 0) {
367 printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
368 mycustomttable[i].optionName,
369 mycustomttable[i].vendorName,
370 mycustomttable[i].cardName);
377 /* ----------- Various detection routines ----------- */
379 static void sisfb_detect_custom_timing(struct sis_video_info *ivideo)
381 unsigned char *biosver = NULL;
382 unsigned char *biosdate = NULL;
387 if(ivideo->SiS_Pr.UseROM) {
388 biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06;
389 biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c;
390 for(i = 0; i < 32768; i++)
391 chksum += ivideo->SiS_Pr.VirtualRomBase[i];
396 if( (mycustomttable[i].chipID == ivideo->chip) &&
397 ((!strlen(mycustomttable[i].biosversion)) ||
398 (ivideo->SiS_Pr.UseROM &&
399 (!strncmp(mycustomttable[i].biosversion, biosver,
400 strlen(mycustomttable[i].biosversion))))) &&
401 ((!strlen(mycustomttable[i].biosdate)) ||
402 (ivideo->SiS_Pr.UseROM &&
403 (!strncmp(mycustomttable[i].biosdate, biosdate,
404 strlen(mycustomttable[i].biosdate))))) &&
405 ((!mycustomttable[i].bioschksum) ||
406 (ivideo->SiS_Pr.UseROM &&
407 (mycustomttable[i].bioschksum == chksum))) &&
408 (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
409 (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
411 for(j = 0; j < 5; j++) {
412 if(mycustomttable[i].biosFootprintAddr[j]) {
413 if(ivideo->SiS_Pr.UseROM) {
414 if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
415 mycustomttable[i].biosFootprintData[j]) {
423 ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
424 printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
425 mycustomttable[i].vendorName,
426 mycustomttable[i].cardName);
427 printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
428 mycustomttable[i].optionName);
433 } while(mycustomttable[i].chipID);
436 static bool sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
438 int i, j, xres, yres, refresh, index;
441 if(buffer[0] != 0x00 || buffer[1] != 0xff ||
442 buffer[2] != 0xff || buffer[3] != 0xff ||
443 buffer[4] != 0xff || buffer[5] != 0xff ||
444 buffer[6] != 0xff || buffer[7] != 0x00) {
445 printk(KERN_DEBUG "sisfb: Bad EDID header\n");
449 if(buffer[0x12] != 0x01) {
450 printk(KERN_INFO "sisfb: EDID version %d not supported\n",
455 monitor->feature = buffer[0x18];
457 if(!(buffer[0x14] & 0x80)) {
458 if(!(buffer[0x14] & 0x08)) {
460 "sisfb: WARNING: Monitor does not support separate syncs\n");
464 if(buffer[0x13] >= 0x01) {
465 /* EDID V1 rev 1 and 2: Search for monitor descriptor
470 if(buffer[j] == 0x00 && buffer[j + 1] == 0x00 &&
471 buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
472 buffer[j + 4] == 0x00) {
473 monitor->hmin = buffer[j + 7];
474 monitor->hmax = buffer[j + 8];
475 monitor->vmin = buffer[j + 5];
476 monitor->vmax = buffer[j + 6];
477 monitor->dclockmax = buffer[j + 9] * 10 * 1000;
478 monitor->datavalid = true;
485 if(!monitor->datavalid) {
486 /* Otherwise: Get a range from the list of supported
487 * Estabished Timings. This is not entirely accurate,
488 * because fixed frequency monitors are not supported
491 monitor->hmin = 65535; monitor->hmax = 0;
492 monitor->vmin = 65535; monitor->vmax = 0;
493 monitor->dclockmax = 0;
494 emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
495 for(i = 0; i < 13; i++) {
496 if(emodes & sisfb_ddcsmodes[i].mask) {
497 if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
498 if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
499 if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
500 if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
501 if(monitor->dclockmax < sisfb_ddcsmodes[i].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
505 for(i = 0; i < 8; i++) {
506 xres = (buffer[index] + 31) * 8;
507 switch(buffer[index + 1] & 0xc0) {
508 case 0xc0: yres = (xres * 9) / 16; break;
509 case 0x80: yres = (xres * 4) / 5; break;
510 case 0x40: yres = (xres * 3) / 4; break;
511 default: yres = xres; break;
513 refresh = (buffer[index + 1] & 0x3f) + 60;
514 if((xres >= 640) && (yres >= 480)) {
515 for(j = 0; j < 8; j++) {
516 if((xres == sisfb_ddcfmodes[j].x) &&
517 (yres == sisfb_ddcfmodes[j].y) &&
518 (refresh == sisfb_ddcfmodes[j].v)) {
519 if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
520 if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
521 if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
522 if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
523 if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d;
529 if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
530 monitor->datavalid = true;
534 return monitor->datavalid;
537 static void sisfb_handle_ddc(struct sis_video_info *ivideo,
538 struct sisfb_monitor *monitor, int crtno)
540 unsigned short temp, i, realcrtno = crtno;
541 unsigned char buffer[256];
543 monitor->datavalid = false;
546 if(ivideo->vbflags & CRT2_LCD) realcrtno = 1;
547 else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
551 if((ivideo->sisfb_crt1off) && (!crtno))
554 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
555 realcrtno, 0, &buffer[0], ivideo->vbflags2);
556 if((!temp) || (temp == 0xffff)) {
557 printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
560 printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
561 printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
563 (temp & 0x1a) ? "" : "[none of the supported]",
564 (temp & 0x02) ? "2 " : "",
565 (temp & 0x08) ? "D&P" : "",
566 (temp & 0x10) ? "FPDI-2" : "");
568 i = 3; /* Number of retrys */
570 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
571 realcrtno, 1, &buffer[0], ivideo->vbflags2);
572 } while((temp) && i--);
574 if(sisfb_interpret_edid(monitor, &buffer[0])) {
575 printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
576 monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
577 monitor->dclockmax / 1000);
579 printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
582 printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
585 printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
590 /* -------------- Mode validation --------------- */
593 sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
594 int mode_idx, int rate_idx, int rate)
597 unsigned int dclock, hsync;
599 if(!monitor->datavalid)
605 /* Skip for 320x200, 320x240, 640x400 */
606 switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
617 #ifdef CONFIG_FB_SIS_315
620 if(ivideo->sisvga_engine == SIS_315_VGA) return true;
624 if(rate < (monitor->vmin - 1))
626 if(rate > (monitor->vmax + 1))
629 if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
630 sisbios_mode[mode_idx].mode_no[ivideo->mni],
631 &htotal, &vtotal, rate_idx)) {
632 dclock = (htotal * vtotal * rate) / 1000;
633 if(dclock > (monitor->dclockmax + 1000))
635 hsync = dclock / htotal;
636 if(hsync < (monitor->hmin - 1))
638 if(hsync > (monitor->hmax + 1))
647 sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
649 u16 xres=0, yres, myres;
651 #ifdef CONFIG_FB_SIS_300
652 if(ivideo->sisvga_engine == SIS_300_VGA) {
653 if(!(sisbios_mode[myindex].chipset & MD_SIS300))
657 #ifdef CONFIG_FB_SIS_315
658 if(ivideo->sisvga_engine == SIS_315_VGA) {
659 if(!(sisbios_mode[myindex].chipset & MD_SIS315))
664 myres = sisbios_mode[myindex].yres;
666 switch(vbflags & VB_DISPTYPE_DISP2) {
669 xres = ivideo->lcdxres; yres = ivideo->lcdyres;
671 if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
672 (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
673 if(sisbios_mode[myindex].xres > xres)
679 if(ivideo->sisfb_fstn) {
680 if(sisbios_mode[myindex].xres == 320) {
682 switch(sisbios_mode[myindex].mode_no[1]) {
683 case 0x50: myindex = MODE_FSTN_8; break;
684 case 0x56: myindex = MODE_FSTN_16; break;
685 case 0x53: return -1;
691 if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
692 sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
693 ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
699 if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
700 sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
706 if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
707 sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
717 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
720 u16 xres = sisbios_mode[mode_idx].xres;
721 u16 yres = sisbios_mode[mode_idx].yres;
723 ivideo->rate_idx = 0;
724 while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
725 if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
726 if(sisfb_vrate[i].refresh == rate) {
727 ivideo->rate_idx = sisfb_vrate[i].idx;
729 } else if(sisfb_vrate[i].refresh > rate) {
730 if((sisfb_vrate[i].refresh - rate) <= 3) {
731 DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
732 rate, sisfb_vrate[i].refresh);
733 ivideo->rate_idx = sisfb_vrate[i].idx;
734 ivideo->refresh_rate = sisfb_vrate[i].refresh;
735 } else if((sisfb_vrate[i].idx != 1) &&
736 ((rate - sisfb_vrate[i-1].refresh) <= 2)) {
737 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
738 rate, sisfb_vrate[i-1].refresh);
739 ivideo->rate_idx = sisfb_vrate[i-1].idx;
740 ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
743 } else if((rate - sisfb_vrate[i].refresh) <= 2) {
744 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
745 rate, sisfb_vrate[i].refresh);
746 ivideo->rate_idx = sisfb_vrate[i].idx;
752 if(ivideo->rate_idx > 0) {
753 return ivideo->rate_idx;
755 printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n",
762 sisfb_bridgeisslave(struct sis_video_info *ivideo)
766 if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
769 P1_00 = SiS_GetReg(SISPART1, 0x00);
770 if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
771 ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
779 sisfballowretracecrt1(struct sis_video_info *ivideo)
783 temp = SiS_GetReg(SISCR, 0x17);
787 temp = SiS_GetReg(SISSR, 0x1f);
795 sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
797 if(!sisfballowretracecrt1(ivideo))
800 if (SiS_GetRegByte(SISINPSTAT) & 0x08)
807 sisfbwaitretracecrt1(struct sis_video_info *ivideo)
811 if(!sisfballowretracecrt1(ivideo))
815 while ((!(SiS_GetRegByte(SISINPSTAT) & 0x08)) && --watchdog);
817 while ((SiS_GetRegByte(SISINPSTAT) & 0x08) && --watchdog);
821 sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
823 unsigned char temp, reg;
825 switch(ivideo->sisvga_engine) {
826 case SIS_300_VGA: reg = 0x25; break;
827 case SIS_315_VGA: reg = 0x30; break;
828 default: return false;
831 temp = SiS_GetReg(SISPART1, reg);
839 sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
841 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
842 if(!sisfb_bridgeisslave(ivideo)) {
843 return sisfbcheckvretracecrt2(ivideo);
846 return sisfbcheckvretracecrt1(ivideo);
850 sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
852 u8 idx, reg1, reg2, reg3, reg4;
855 (*vcount) = (*hcount) = 0;
857 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
859 ret |= (FB_VBLANK_HAVE_VSYNC |
860 FB_VBLANK_HAVE_HBLANK |
861 FB_VBLANK_HAVE_VBLANK |
862 FB_VBLANK_HAVE_VCOUNT |
863 FB_VBLANK_HAVE_HCOUNT);
864 switch(ivideo->sisvga_engine) {
865 case SIS_300_VGA: idx = 0x25; break;
867 case SIS_315_VGA: idx = 0x30; break;
869 reg1 = SiS_GetReg(SISPART1, (idx+0)); /* 30 */
870 reg2 = SiS_GetReg(SISPART1, (idx+1)); /* 31 */
871 reg3 = SiS_GetReg(SISPART1, (idx+2)); /* 32 */
872 reg4 = SiS_GetReg(SISPART1, (idx+3)); /* 33 */
873 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
874 if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
875 if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
876 (*vcount) = reg3 | ((reg4 & 0x70) << 4);
877 (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
879 } else if(sisfballowretracecrt1(ivideo)) {
881 ret |= (FB_VBLANK_HAVE_VSYNC |
882 FB_VBLANK_HAVE_VBLANK |
883 FB_VBLANK_HAVE_VCOUNT |
884 FB_VBLANK_HAVE_HCOUNT);
885 reg1 = SiS_GetRegByte(SISINPSTAT);
886 if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
887 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
888 reg1 = SiS_GetReg(SISCR, 0x20);
889 reg1 = SiS_GetReg(SISCR, 0x1b);
890 reg2 = SiS_GetReg(SISCR, 0x1c);
891 reg3 = SiS_GetReg(SISCR, 0x1d);
892 (*vcount) = reg2 | ((reg3 & 0x07) << 8);
893 (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
900 sisfb_myblank(struct sis_video_info *ivideo, int blank)
902 u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
903 bool backlight = true;
906 case FB_BLANK_UNBLANK: /* on */
915 case FB_BLANK_NORMAL: /* blank */
924 case FB_BLANK_VSYNC_SUSPEND: /* no vsync */
933 case FB_BLANK_HSYNC_SUSPEND: /* no hsync */
942 case FB_BLANK_POWERDOWN: /* off */
955 if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
957 if( (!ivideo->sisfb_thismonitor.datavalid) ||
958 ((ivideo->sisfb_thismonitor.datavalid) &&
959 (ivideo->sisfb_thismonitor.feature & 0xe0))) {
961 if(ivideo->sisvga_engine == SIS_315_VGA) {
962 SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
965 if(!(sisfb_bridgeisslave(ivideo))) {
966 SiS_SetRegANDOR(SISSR, 0x01, ~0x20, sr01);
967 SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, sr1f);
973 if(ivideo->currentvbflags & CRT2_LCD) {
975 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
977 SiS_SiS30xBLOn(&ivideo->SiS_Pr);
979 SiS_SiS30xBLOff(&ivideo->SiS_Pr);
981 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
982 #ifdef CONFIG_FB_SIS_315
983 if(ivideo->vbflags2 & VB2_CHRONTEL) {
985 SiS_Chrontel701xBLOn(&ivideo->SiS_Pr);
987 SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
993 if(((ivideo->sisvga_engine == SIS_300_VGA) &&
994 (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
995 ((ivideo->sisvga_engine == SIS_315_VGA) &&
996 ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
997 SiS_SetRegANDOR(SISSR, 0x11, ~0x0c, sr11);
1000 if(ivideo->sisvga_engine == SIS_300_VGA) {
1001 if((ivideo->vbflags2 & VB2_30xB) &&
1002 (!(ivideo->vbflags2 & VB2_30xBDH))) {
1003 SiS_SetRegANDOR(SISPART1, 0x13, 0x3f, p1_13);
1005 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
1006 if((ivideo->vbflags2 & VB2_30xB) &&
1007 (!(ivideo->vbflags2 & VB2_30xBDH))) {
1008 SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
1012 } else if(ivideo->currentvbflags & CRT2_VGA) {
1014 if(ivideo->vbflags2 & VB2_30xB) {
1015 SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
1023 /* ------------- Callbacks from init.c/init301.c -------------- */
1025 #ifdef CONFIG_FB_SIS_300
1027 sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg)
1029 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1032 pci_read_config_dword(ivideo->nbridge, reg, &val);
1033 return (unsigned int)val;
1037 sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val)
1039 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1041 pci_write_config_dword(ivideo->nbridge, reg, (u32)val);
1045 sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg)
1047 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1050 if(!ivideo->lpcdev) return 0;
1052 pci_read_config_dword(ivideo->lpcdev, reg, &val);
1053 return (unsigned int)val;
1057 #ifdef CONFIG_FB_SIS_315
1059 sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val)
1061 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1063 pci_write_config_byte(ivideo->nbridge, reg, (u8)val);
1067 sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg)
1069 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1072 if(!ivideo->lpcdev) return 0;
1074 pci_read_config_word(ivideo->lpcdev, reg, &val);
1075 return (unsigned int)val;
1079 /* ----------- FBDev related routines for all series ----------- */
1082 sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
1084 return (var->bits_per_pixel == 8) ? 256 : 16;
1088 sisfb_set_vparms(struct sis_video_info *ivideo)
1090 switch(ivideo->video_bpp) {
1092 ivideo->DstColor = 0x0000;
1093 ivideo->SiS310_AccelDepth = 0x00000000;
1094 ivideo->video_cmap_len = 256;
1097 ivideo->DstColor = 0x8000;
1098 ivideo->SiS310_AccelDepth = 0x00010000;
1099 ivideo->video_cmap_len = 16;
1102 ivideo->DstColor = 0xC000;
1103 ivideo->SiS310_AccelDepth = 0x00020000;
1104 ivideo->video_cmap_len = 16;
1107 ivideo->video_cmap_len = 16;
1108 printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
1114 sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1116 int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3));
1118 if(maxyres > 32767) maxyres = 32767;
1124 sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1126 ivideo->video_linelength = var->xres_virtual * (var->bits_per_pixel >> 3);
1127 ivideo->scrnpitchCRT1 = ivideo->video_linelength;
1128 if(!(ivideo->currentvbflags & CRT1_LCDA)) {
1129 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1130 ivideo->scrnpitchCRT1 <<= 1;
1136 sisfb_set_pitch(struct sis_video_info *ivideo)
1138 bool isslavemode = false;
1139 unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
1140 unsigned short HDisplay2 = ivideo->video_linelength >> 3;
1142 if(sisfb_bridgeisslave(ivideo)) isslavemode = true;
1144 /* We need to set pitch for CRT1 if bridge is in slave mode, too */
1145 if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
1146 SiS_SetReg(SISCR, 0x13, (HDisplay1 & 0xFF));
1147 SiS_SetRegANDOR(SISSR, 0x0E, 0xF0, (HDisplay1 >> 8));
1150 /* We must not set the pitch for CRT2 if bridge is in slave mode */
1151 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
1152 SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
1153 SiS_SetReg(SISPART1, 0x07, (HDisplay2 & 0xFF));
1154 SiS_SetRegANDOR(SISPART1, 0x09, 0xF0, (HDisplay2 >> 8));
1159 sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1161 ivideo->video_cmap_len = sisfb_get_cmap_len(var);
1163 switch(var->bits_per_pixel) {
1165 var->red.offset = var->green.offset = var->blue.offset = 0;
1166 var->red.length = var->green.length = var->blue.length = 8;
1169 var->red.offset = 11;
1170 var->red.length = 5;
1171 var->green.offset = 5;
1172 var->green.length = 6;
1173 var->blue.offset = 0;
1174 var->blue.length = 5;
1175 var->transp.offset = 0;
1176 var->transp.length = 0;
1179 var->red.offset = 16;
1180 var->red.length = 8;
1181 var->green.offset = 8;
1182 var->green.length = 8;
1183 var->blue.offset = 0;
1184 var->blue.length = 8;
1185 var->transp.offset = 24;
1186 var->transp.length = 8;
1192 sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
1194 unsigned short modeno = ivideo->mode_no;
1196 /* >=2.6.12's fbcon clears the screen anyway */
1199 SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1201 sisfb_pre_setmode(ivideo);
1203 if(!SiSSetMode(&ivideo->SiS_Pr, modeno)) {
1204 printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
1208 SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1210 sisfb_post_setmode(ivideo);
1217 sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
1219 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1220 unsigned int htotal = 0, vtotal = 0;
1221 unsigned int drate = 0, hrate = 0;
1222 int found_mode = 0, ret;
1226 htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1228 vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1230 pixclock = var->pixclock;
1232 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1233 vtotal += var->yres;
1235 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1236 vtotal += var->yres;
1238 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1239 vtotal += var->yres;
1241 } else vtotal += var->yres;
1243 if(!(htotal) || !(vtotal)) {
1244 DPRINTK("sisfb: Invalid 'var' information\n");
1248 if(pixclock && htotal && vtotal) {
1249 drate = 1000000000 / pixclock;
1250 hrate = (drate * 1000) / htotal;
1251 ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1253 ivideo->refresh_rate = 60;
1256 old_mode = ivideo->sisfb_mode_idx;
1257 ivideo->sisfb_mode_idx = 0;
1259 while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) &&
1260 (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) {
1261 if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) &&
1262 (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) &&
1263 (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) {
1264 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1268 ivideo->sisfb_mode_idx++;
1272 ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
1273 ivideo->sisfb_mode_idx, ivideo->currentvbflags);
1275 ivideo->sisfb_mode_idx = -1;
1278 if(ivideo->sisfb_mode_idx < 0) {
1279 printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres,
1280 var->yres, var->bits_per_pixel);
1281 ivideo->sisfb_mode_idx = old_mode;
1285 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1287 if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
1288 ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
1289 ivideo->refresh_rate = 60;
1293 /* If acceleration to be used? Need to know
1294 * before pre/post_set_mode()
1297 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
1298 #ifdef STUPID_ACCELF_TEXT_SHIT
1299 if(var->accel_flags & FB_ACCELF_TEXT) {
1300 info->flags &= ~FBINFO_HWACCEL_DISABLED;
1302 info->flags |= FBINFO_HWACCEL_DISABLED;
1305 if(!(info->flags & FBINFO_HWACCEL_DISABLED)) ivideo->accel = -1;
1307 if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
1310 if((ret = sisfb_set_mode(ivideo, 1))) {
1314 ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
1315 ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
1316 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
1318 sisfb_calc_pitch(ivideo, var);
1319 sisfb_set_pitch(ivideo);
1321 sisfb_set_vparms(ivideo);
1323 ivideo->current_width = ivideo->video_width;
1324 ivideo->current_height = ivideo->video_height;
1325 ivideo->current_bpp = ivideo->video_bpp;
1326 ivideo->current_htotal = htotal;
1327 ivideo->current_vtotal = vtotal;
1328 ivideo->current_linelength = ivideo->video_linelength;
1329 ivideo->current_pixclock = var->pixclock;
1330 ivideo->current_refresh_rate = ivideo->refresh_rate;
1331 ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
1338 sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
1340 SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1342 SiS_SetReg(SISCR, 0x0D, base & 0xFF);
1343 SiS_SetReg(SISCR, 0x0C, (base >> 8) & 0xFF);
1344 SiS_SetReg(SISSR, 0x0D, (base >> 16) & 0xFF);
1345 if(ivideo->sisvga_engine == SIS_315_VGA) {
1346 SiS_SetRegANDOR(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
1351 sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
1353 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1354 SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
1355 SiS_SetReg(SISPART1, 0x06, (base & 0xFF));
1356 SiS_SetReg(SISPART1, 0x05, ((base >> 8) & 0xFF));
1357 SiS_SetReg(SISPART1, 0x04, ((base >> 16) & 0xFF));
1358 if(ivideo->sisvga_engine == SIS_315_VGA) {
1359 SiS_SetRegANDOR(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1365 sisfb_pan_var(struct sis_video_info *ivideo, struct fb_info *info,
1366 struct fb_var_screeninfo *var)
1368 ivideo->current_base = var->yoffset * info->var.xres_virtual
1371 /* calculate base bpp dep. */
1372 switch (info->var.bits_per_pixel) {
1376 ivideo->current_base >>= 1;
1380 ivideo->current_base >>= 2;
1384 ivideo->current_base += (ivideo->video_offset >> 2);
1386 sisfb_set_base_CRT1(ivideo, ivideo->current_base);
1387 sisfb_set_base_CRT2(ivideo, ivideo->current_base);
1393 sisfb_open(struct fb_info *info, int user)
1399 sisfb_release(struct fb_info *info, int user)
1405 sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
1406 unsigned transp, struct fb_info *info)
1408 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1410 if(regno >= sisfb_get_cmap_len(&info->var))
1413 switch(info->var.bits_per_pixel) {
1415 SiS_SetRegByte(SISDACA, regno);
1416 SiS_SetRegByte(SISDACD, (red >> 10));
1417 SiS_SetRegByte(SISDACD, (green >> 10));
1418 SiS_SetRegByte(SISDACD, (blue >> 10));
1419 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1420 SiS_SetRegByte(SISDAC2A, regno);
1421 SiS_SetRegByte(SISDAC2D, (red >> 8));
1422 SiS_SetRegByte(SISDAC2D, (green >> 8));
1423 SiS_SetRegByte(SISDAC2D, (blue >> 8));
1430 ((u32 *)(info->pseudo_palette))[regno] =
1432 ((green & 0xfc00) >> 5) |
1433 ((blue & 0xf800) >> 11);
1442 ((u32 *)(info->pseudo_palette))[regno] =
1443 (red << 16) | (green << 8) | (blue);
1450 sisfb_set_par(struct fb_info *info)
1454 if((err = sisfb_do_set_var(&info->var, 1, info)))
1457 sisfb_get_fix(&info->fix, -1, info);
1463 sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1465 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1466 unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
1467 unsigned int drate = 0, hrate = 0, maxyres;
1469 int refresh_rate, search_idx, tidx;
1470 bool recalc_clock = false;
1473 htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1475 vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1479 pixclock = var->pixclock;
1481 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1482 vtotal += var->yres;
1484 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1485 vtotal += var->yres;
1487 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1488 vtotal += var->yres;
1491 vtotal += var->yres;
1493 if(!(htotal) || !(vtotal)) {
1494 SISFAIL("sisfb: no valid timing data");
1498 while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
1499 (sisbios_mode[search_idx].xres <= var->xres) ) {
1500 if( (sisbios_mode[search_idx].xres == var->xres) &&
1501 (sisbios_mode[search_idx].yres == var->yres) &&
1502 (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1503 if((tidx = sisfb_validate_mode(ivideo, search_idx,
1504 ivideo->currentvbflags)) > 0) {
1515 while(sisbios_mode[search_idx].mode_no[0] != 0) {
1516 if( (var->xres <= sisbios_mode[search_idx].xres) &&
1517 (var->yres <= sisbios_mode[search_idx].yres) &&
1518 (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
1519 if((tidx = sisfb_validate_mode(ivideo,search_idx,
1520 ivideo->currentvbflags)) > 0) {
1530 "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
1531 var->xres, var->yres, var->bits_per_pixel,
1532 sisbios_mode[search_idx].xres,
1533 sisbios_mode[search_idx].yres,
1534 var->bits_per_pixel);
1535 var->xres = sisbios_mode[search_idx].xres;
1536 var->yres = sisbios_mode[search_idx].yres;
1539 "sisfb: Failed to find supported mode near %dx%dx%d\n",
1540 var->xres, var->yres, var->bits_per_pixel);
1545 if( ((ivideo->vbflags2 & VB2_LVDS) ||
1546 ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
1547 (var->bits_per_pixel == 8) ) {
1548 /* Slave modes on LVDS and 301B-DH */
1550 recalc_clock = true;
1551 } else if( (ivideo->current_htotal == htotal) &&
1552 (ivideo->current_vtotal == vtotal) &&
1553 (ivideo->current_pixclock == pixclock) ) {
1554 /* x=x & y=y & c=c -> assume depth change */
1555 drate = 1000000000 / pixclock;
1556 hrate = (drate * 1000) / htotal;
1557 refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1558 } else if( ( (ivideo->current_htotal != htotal) ||
1559 (ivideo->current_vtotal != vtotal) ) &&
1560 (ivideo->current_pixclock == var->pixclock) ) {
1561 /* x!=x | y!=y & c=c -> invalid pixclock */
1562 if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
1564 ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
1565 } else if(ivideo->sisfb_parm_rate != -1) {
1566 /* Sic, sisfb_parm_rate - want to know originally desired rate here */
1567 refresh_rate = ivideo->sisfb_parm_rate;
1571 recalc_clock = true;
1572 } else if((pixclock) && (htotal) && (vtotal)) {
1573 drate = 1000000000 / pixclock;
1574 hrate = (drate * 1000) / htotal;
1575 refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1576 } else if(ivideo->current_refresh_rate) {
1577 refresh_rate = ivideo->current_refresh_rate;
1578 recalc_clock = true;
1581 recalc_clock = true;
1584 myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
1586 /* Eventually recalculate timing and clock */
1588 if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
1589 var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
1590 sisbios_mode[search_idx].mode_no[ivideo->mni],
1592 sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr,
1593 sisbios_mode[search_idx].mode_no[ivideo->mni],
1595 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1596 var->pixclock <<= 1;
1600 if(ivideo->sisfb_thismonitor.datavalid) {
1601 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
1602 myrateindex, refresh_rate)) {
1604 "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1608 /* Adapt RGB settings */
1609 sisfb_bpp_to_var(ivideo, var);
1611 if(var->xres > var->xres_virtual)
1612 var->xres_virtual = var->xres;
1614 if(ivideo->sisfb_ypan) {
1615 maxyres = sisfb_calc_maxyres(ivideo, var);
1616 if(ivideo->sisfb_max) {
1617 var->yres_virtual = maxyres;
1619 if(var->yres_virtual > maxyres) {
1620 var->yres_virtual = maxyres;
1623 if(var->yres_virtual <= var->yres) {
1624 var->yres_virtual = var->yres;
1627 if(var->yres != var->yres_virtual) {
1628 var->yres_virtual = var->yres;
1634 /* Truncate offsets to maximum if too high */
1635 if(var->xoffset > var->xres_virtual - var->xres) {
1636 var->xoffset = var->xres_virtual - var->xres - 1;
1639 if(var->yoffset > var->yres_virtual - var->yres) {
1640 var->yoffset = var->yres_virtual - var->yres - 1;
1643 /* Set everything else to 0 */
1644 var->red.msb_right =
1645 var->green.msb_right =
1646 var->blue.msb_right =
1647 var->transp.offset =
1648 var->transp.length =
1649 var->transp.msb_right = 0;
1655 sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
1657 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1660 if (var->vmode & FB_VMODE_YWRAP)
1663 if (var->xoffset + info->var.xres > info->var.xres_virtual ||
1664 var->yoffset + info->var.yres > info->var.yres_virtual)
1667 err = sisfb_pan_var(ivideo, info, var);
1671 info->var.xoffset = var->xoffset;
1672 info->var.yoffset = var->yoffset;
1678 sisfb_blank(int blank, struct fb_info *info)
1680 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1682 return sisfb_myblank(ivideo, blank);
1685 /* ----------- FBDev related routines for all series ---------- */
1687 static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
1690 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1691 struct sis_memreq sismemreq;
1692 struct fb_vblank sisvbblank;
1697 u32 __user *argp = (u32 __user *)arg;
1701 if(!capable(CAP_SYS_RAWIO))
1704 if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))
1707 sis_malloc(&sismemreq);
1709 if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
1710 sis_free((u32)sismemreq.offset);
1716 if(!capable(CAP_SYS_RAWIO))
1719 if(get_user(gpu32, argp))
1725 case FBIOGET_VBLANK:
1727 memset(&sisvbblank, 0, sizeof(struct fb_vblank));
1729 sisvbblank.count = 0;
1730 sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
1732 if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))
1737 case SISFB_GET_INFO_SIZE:
1738 return put_user(sizeof(struct sisfb_info), argp);
1740 case SISFB_GET_INFO_OLD:
1741 if(ivideo->warncount++ < 10)
1743 "sisfb: Deprecated ioctl call received - update your application!\n");
1745 case SISFB_GET_INFO: /* For communication with X driver */
1746 ivideo->sisfb_infoblock.sisfb_id = SISFB_ID;
1747 ivideo->sisfb_infoblock.sisfb_version = VER_MAJOR;
1748 ivideo->sisfb_infoblock.sisfb_revision = VER_MINOR;
1749 ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;
1750 ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;
1751 ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;
1752 ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;
1753 ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;
1754 if(ivideo->modechanged) {
1755 ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;
1757 ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;
1759 ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;
1760 ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;
1761 ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;
1762 ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;
1763 ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;
1764 ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;
1765 ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;
1766 ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;
1767 ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;
1768 ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;
1769 ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
1770 ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
1771 ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
1772 ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
1773 ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
1774 ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
1775 ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
1776 ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
1777 ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
1778 ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
1779 ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;
1780 ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;
1781 ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;
1782 ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;
1783 ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;
1784 ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;
1785 ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;
1786 ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;
1788 if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,
1789 sizeof(ivideo->sisfb_infoblock)))
1794 case SISFB_GET_VBRSTATUS_OLD:
1795 if(ivideo->warncount++ < 10)
1797 "sisfb: Deprecated ioctl call received - update your application!\n");
1799 case SISFB_GET_VBRSTATUS:
1800 if(sisfb_CheckVBRetrace(ivideo))
1801 return put_user((u32)1, argp);
1803 return put_user((u32)0, argp);
1805 case SISFB_GET_AUTOMAXIMIZE_OLD:
1806 if(ivideo->warncount++ < 10)
1808 "sisfb: Deprecated ioctl call received - update your application!\n");
1810 case SISFB_GET_AUTOMAXIMIZE:
1811 if(ivideo->sisfb_max)
1812 return put_user((u32)1, argp);
1814 return put_user((u32)0, argp);
1816 case SISFB_SET_AUTOMAXIMIZE_OLD:
1817 if(ivideo->warncount++ < 10)
1819 "sisfb: Deprecated ioctl call received - update your application!\n");
1821 case SISFB_SET_AUTOMAXIMIZE:
1822 if(get_user(gpu32, argp))
1825 ivideo->sisfb_max = (gpu32) ? 1 : 0;
1828 case SISFB_SET_TVPOSOFFSET:
1829 if(get_user(gpu32, argp))
1832 sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
1833 sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
1836 case SISFB_GET_TVPOSOFFSET:
1837 return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
1841 if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,
1842 sizeof(struct sisfb_cmd)))
1845 sisfb_handle_command(ivideo, &ivideo->sisfb_command);
1847 if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,
1848 sizeof(struct sisfb_cmd)))
1853 case SISFB_SET_LOCK:
1854 if(get_user(gpu32, argp))
1857 ivideo->sisfblocked = (gpu32) ? 1 : 0;
1861 #ifdef SIS_NEW_CONFIG_COMPAT
1862 return -ENOIOCTLCMD;
1871 sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
1873 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1875 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1877 strlcpy(fix->id, ivideo->myid, sizeof(fix->id));
1879 mutex_lock(&info->mm_lock);
1880 fix->smem_start = ivideo->video_base + ivideo->video_offset;
1881 fix->smem_len = ivideo->sisfb_mem;
1882 mutex_unlock(&info->mm_lock);
1883 fix->type = FB_TYPE_PACKED_PIXELS;
1885 fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
1887 fix->ypanstep = (ivideo->sisfb_ypan) ? 1 : 0;
1889 fix->line_length = ivideo->video_linelength;
1890 fix->mmio_start = ivideo->mmio_base;
1891 fix->mmio_len = ivideo->mmio_size;
1892 if(ivideo->sisvga_engine == SIS_300_VGA) {
1893 fix->accel = FB_ACCEL_SIS_GLAMOUR;
1894 } else if((ivideo->chip == SIS_330) ||
1895 (ivideo->chip == SIS_760) ||
1896 (ivideo->chip == SIS_761)) {
1897 fix->accel = FB_ACCEL_SIS_XABRE;
1898 } else if(ivideo->chip == XGI_20) {
1899 fix->accel = FB_ACCEL_XGI_VOLARI_Z;
1900 } else if(ivideo->chip >= XGI_40) {
1901 fix->accel = FB_ACCEL_XGI_VOLARI_V;
1903 fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
1909 /* ---------------- fb_ops structures ----------------- */
1911 static const struct fb_ops sisfb_ops = {
1912 .owner = THIS_MODULE,
1913 .fb_open = sisfb_open,
1914 .fb_release = sisfb_release,
1915 .fb_check_var = sisfb_check_var,
1916 .fb_set_par = sisfb_set_par,
1917 .fb_setcolreg = sisfb_setcolreg,
1918 .fb_pan_display = sisfb_pan_display,
1919 .fb_blank = sisfb_blank,
1920 .fb_fillrect = fbcon_sis_fillrect,
1921 .fb_copyarea = fbcon_sis_copyarea,
1922 .fb_imageblit = cfb_imageblit,
1923 .fb_sync = fbcon_sis_sync,
1924 #ifdef SIS_NEW_CONFIG_COMPAT
1925 .fb_compat_ioctl= sisfb_ioctl,
1927 .fb_ioctl = sisfb_ioctl
1930 /* ---------------- Chip generation dependent routines ---------------- */
1932 static struct pci_dev *sisfb_get_northbridge(int basechipid)
1934 struct pci_dev *pdev = NULL;
1935 int nbridgenum, nbridgeidx, i;
1936 static const unsigned short nbridgeids[] = {
1937 PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */
1938 PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */
1939 PCI_DEVICE_ID_SI_730,
1940 PCI_DEVICE_ID_SI_550, /* for SiS 550 VGA */
1941 PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */
1942 PCI_DEVICE_ID_SI_651,
1943 PCI_DEVICE_ID_SI_740,
1944 PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760/761 VGA */
1945 PCI_DEVICE_ID_SI_741,
1946 PCI_DEVICE_ID_SI_660,
1947 PCI_DEVICE_ID_SI_760,
1948 PCI_DEVICE_ID_SI_761
1951 switch(basechipid) {
1952 #ifdef CONFIG_FB_SIS_300
1953 case SIS_540: nbridgeidx = 0; nbridgenum = 1; break;
1954 case SIS_630: nbridgeidx = 1; nbridgenum = 2; break;
1956 #ifdef CONFIG_FB_SIS_315
1957 case SIS_550: nbridgeidx = 3; nbridgenum = 1; break;
1958 case SIS_650: nbridgeidx = 4; nbridgenum = 3; break;
1959 case SIS_660: nbridgeidx = 7; nbridgenum = 5; break;
1961 default: return NULL;
1963 for(i = 0; i < nbridgenum; i++) {
1964 if((pdev = pci_get_device(PCI_VENDOR_ID_SI,
1965 nbridgeids[nbridgeidx+i], NULL)))
1971 static int sisfb_get_dram_size(struct sis_video_info *ivideo)
1973 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1977 ivideo->video_size = 0;
1978 ivideo->UMAsize = ivideo->LFBsize = 0;
1980 switch(ivideo->chip) {
1981 #ifdef CONFIG_FB_SIS_300
1983 reg = SiS_GetReg(SISSR, 0x14);
1984 ivideo->video_size = ((reg & 0x3F) + 1) << 20;
1989 if(!ivideo->nbridge)
1991 pci_read_config_byte(ivideo->nbridge, 0x63, ®);
1992 ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
1995 #ifdef CONFIG_FB_SIS_315
1999 reg = SiS_GetReg(SISSR, 0x14);
2000 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2001 switch((reg >> 2) & 0x03) {
2004 ivideo->video_size <<= 1;
2007 ivideo->video_size += (ivideo->video_size/2);
2011 reg = SiS_GetReg(SISSR, 0x14);
2012 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2013 if(reg & 0x0c) ivideo->video_size <<= 1;
2018 reg = SiS_GetReg(SISSR, 0x14);
2019 ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
2023 reg = SiS_GetReg(SISCR, 0x79);
2024 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2029 reg = SiS_GetReg(SISCR, 0x79);
2030 reg = (reg & 0xf0) >> 4;
2032 ivideo->video_size = (1 << reg) << 20;
2033 ivideo->UMAsize = ivideo->video_size;
2035 reg = SiS_GetReg(SISCR, 0x78);
2039 ivideo->LFBsize = (32 << 20);
2041 ivideo->LFBsize = (64 << 20);
2043 ivideo->video_size += ivideo->LFBsize;
2049 reg = SiS_GetReg(SISSR, 0x14);
2050 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2051 if(ivideo->chip != XGI_20) {
2052 reg = (reg & 0x0c) >> 2;
2053 if(ivideo->revision_id == 2) {
2054 if(reg & 0x01) reg = 0x02;
2057 if(reg == 0x02) ivideo->video_size <<= 1;
2058 else if(reg == 0x03) ivideo->video_size <<= 2;
2068 /* -------------- video bridge device detection --------------- */
2070 static void sisfb_detect_VB_connect(struct sis_video_info *ivideo)
2074 /* No CRT2 on XGI Z7 */
2075 if(ivideo->chip == XGI_20) {
2076 ivideo->sisfb_crt1off = 0;
2080 #ifdef CONFIG_FB_SIS_300
2081 if(ivideo->sisvga_engine == SIS_300_VGA) {
2082 temp = SiS_GetReg(SISSR, 0x17);
2083 if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
2084 /* PAL/NTSC is stored on SR16 on such machines */
2085 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
2086 temp = SiS_GetReg(SISSR, 0x16);
2088 ivideo->vbflags |= TV_PAL;
2090 ivideo->vbflags |= TV_NTSC;
2096 cr32 = SiS_GetReg(SISCR, 0x32);
2098 if(cr32 & SIS_CRT1) {
2099 ivideo->sisfb_crt1off = 0;
2101 ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0;
2104 ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
2106 if(cr32 & SIS_VB_TV) ivideo->vbflags |= CRT2_TV;
2107 if(cr32 & SIS_VB_LCD) ivideo->vbflags |= CRT2_LCD;
2108 if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA;
2110 /* Check given parms for hardware compatibility.
2111 * (Cannot do this in the search_xx routines since we don't
2112 * know what hardware we are running on then)
2115 if(ivideo->chip != SIS_550) {
2116 ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0;
2119 if(ivideo->sisfb_tvplug != -1) {
2120 if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2121 (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) {
2122 if(ivideo->sisfb_tvplug & TV_YPBPR) {
2123 ivideo->sisfb_tvplug = -1;
2124 printk(KERN_ERR "sisfb: YPbPr not supported\n");
2128 if(ivideo->sisfb_tvplug != -1) {
2129 if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2130 (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) {
2131 if(ivideo->sisfb_tvplug & TV_HIVISION) {
2132 ivideo->sisfb_tvplug = -1;
2133 printk(KERN_ERR "sisfb: HiVision not supported\n");
2137 if(ivideo->sisfb_tvstd != -1) {
2138 if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
2139 (!((ivideo->sisvga_engine == SIS_315_VGA) &&
2140 (ivideo->vbflags2 & VB2_CHRONTEL))) ) {
2141 if(ivideo->sisfb_tvstd & (TV_PALM | TV_PALN | TV_NTSCJ)) {
2142 ivideo->sisfb_tvstd = -1;
2143 printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
2148 /* Detect/set TV plug & type */
2149 if(ivideo->sisfb_tvplug != -1) {
2150 ivideo->vbflags |= ivideo->sisfb_tvplug;
2152 if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
2153 else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION;
2154 else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART;
2156 if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO;
2157 if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
2161 if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) {
2162 if(ivideo->sisfb_tvstd != -1) {
2163 ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ);
2164 ivideo->vbflags |= ivideo->sisfb_tvstd;
2166 if(ivideo->vbflags & TV_SCART) {
2167 ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ);
2168 ivideo->vbflags |= TV_PAL;
2170 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
2171 if(ivideo->sisvga_engine == SIS_300_VGA) {
2172 temp = SiS_GetReg(SISSR, 0x38);
2173 if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2174 else ivideo->vbflags |= TV_NTSC;
2175 } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
2176 temp = SiS_GetReg(SISSR, 0x38);
2177 if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2178 else ivideo->vbflags |= TV_NTSC;
2180 temp = SiS_GetReg(SISCR, 0x79);
2181 if(temp & 0x20) ivideo->vbflags |= TV_PAL;
2182 else ivideo->vbflags |= TV_NTSC;
2187 /* Copy forceCRT1 option to CRT1off if option is given */
2188 if(ivideo->sisfb_forcecrt1 != -1) {
2189 ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
2193 /* ------------------ Sensing routines ------------------ */
2195 static bool sisfb_test_DDC1(struct sis_video_info *ivideo)
2200 old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
2202 if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
2204 return (count != -1);
2207 static void sisfb_sense_crt1(struct sis_video_info *ivideo)
2209 bool mustwait = false;
2211 #ifdef CONFIG_FB_SIS_315
2217 sr1F = SiS_GetReg(SISSR, 0x1F);
2218 SiS_SetRegOR(SISSR, 0x1F, 0x04);
2219 SiS_SetRegAND(SISSR, 0x1F, 0x3F);
2220 if(sr1F & 0xc0) mustwait = true;
2222 #ifdef CONFIG_FB_SIS_315
2223 if(ivideo->sisvga_engine == SIS_315_VGA) {
2224 cr63 = SiS_GetReg(SISCR, ivideo->SiS_Pr.SiS_MyCR63);
2226 SiS_SetRegAND(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF);
2230 cr17 = SiS_GetReg(SISCR, 0x17);
2233 SiS_SetRegOR(SISCR, 0x17, 0x80);
2235 SiS_SetReg(SISSR, 0x00, 0x01);
2236 SiS_SetReg(SISSR, 0x00, 0x03);
2240 for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo);
2243 #ifdef CONFIG_FB_SIS_315
2244 if(ivideo->chip >= SIS_330) {
2245 SiS_SetRegAND(SISCR, 0x32, ~0x20);
2246 if(ivideo->chip >= SIS_340) {
2247 SiS_SetReg(SISCR, 0x57, 0x4a);
2249 SiS_SetReg(SISCR, 0x57, 0x5f);
2251 SiS_SetRegOR(SISCR, 0x53, 0x02);
2252 while ((SiS_GetRegByte(SISINPSTAT)) & 0x01) break;
2253 while (!((SiS_GetRegByte(SISINPSTAT)) & 0x01)) break;
2254 if ((SiS_GetRegByte(SISMISCW)) & 0x10) temp = 1;
2255 SiS_SetRegAND(SISCR, 0x53, 0xfd);
2256 SiS_SetRegAND(SISCR, 0x57, 0x00);
2260 if(temp == 0xffff) {
2263 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2264 ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
2265 } while(((temp == 0) || (temp == 0xffff)) && i--);
2267 if((temp == 0) || (temp == 0xffff)) {
2268 if(sisfb_test_DDC1(ivideo)) temp = 1;
2272 if((temp) && (temp != 0xffff)) {
2273 SiS_SetRegOR(SISCR, 0x32, 0x20);
2276 #ifdef CONFIG_FB_SIS_315
2277 if(ivideo->sisvga_engine == SIS_315_VGA) {
2278 SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF, cr63);
2282 SiS_SetRegANDOR(SISCR, 0x17, 0x7F, cr17);
2284 SiS_SetReg(SISSR, 0x1F, sr1F);
2287 /* Determine and detect attached devices on SiS30x */
2288 static void SiS_SenseLCD(struct sis_video_info *ivideo)
2290 unsigned char buffer[256];
2291 unsigned short temp, realcrtno, i;
2292 u8 reg, cr37 = 0, paneltype = 0;
2295 ivideo->SiS_Pr.PanelSelfDetected = false;
2297 /* LCD detection only for TMDS bridges */
2298 if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
2300 if(ivideo->vbflags2 & VB2_30xBDH)
2303 /* If LCD already set up by BIOS, skip it */
2304 reg = SiS_GetReg(SISCR, 0x32);
2309 if(ivideo->SiS_Pr.DDCPortMixup)
2312 /* Check DDC capabilities */
2313 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
2314 realcrtno, 0, &buffer[0], ivideo->vbflags2);
2316 if((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
2320 i = 3; /* Number of retrys */
2322 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2323 ivideo->sisvga_engine, realcrtno, 1,
2324 &buffer[0], ivideo->vbflags2);
2325 } while((temp) && i--);
2330 /* No digital device */
2331 if(!(buffer[0x14] & 0x80))
2334 /* First detailed timing preferred timing? */
2335 if(!(buffer[0x18] & 0x02))
2338 xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
2339 yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
2351 if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
2362 if((buffer[0x47] & 0x18) == 0x18)
2363 cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2367 SiS_SetReg(SISCR, 0x36, paneltype);
2369 SiS_SetRegANDOR(SISCR, 0x37, 0x0c, cr37);
2370 SiS_SetRegOR(SISCR, 0x32, 0x08);
2372 ivideo->SiS_Pr.PanelSelfDetected = true;
2375 static int SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
2377 int temp, mytest, result, i, j;
2379 for(j = 0; j < 10; j++) {
2381 for(i = 0; i < 3; i++) {
2383 SiS_SetReg(SISPART4, 0x11, (type & 0x00ff));
2384 temp = (type >> 8) | (mytest & 0x00ff);
2385 SiS_SetRegANDOR(SISPART4, 0x10, 0xe0, temp);
2386 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
2389 temp = SiS_GetReg(SISPART4, 0x03);
2392 if(temp == mytest) result++;
2394 SiS_SetReg(SISPART4, 0x11, 0x00);
2395 SiS_SetRegAND(SISPART4, 0x10, 0xe0);
2396 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
2399 if((result == 0) || (result >= 2)) break;
2404 static void SiS_Sense30x(struct sis_video_info *ivideo)
2406 u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
2407 u16 svhs=0, svhs_c=0;
2408 u16 cvbs=0, cvbs_c=0;
2409 u16 vga2=0, vga2_c=0;
2411 char stdstr[] = "sisfb: Detected";
2412 char tvstr[] = "TV connected to";
2414 if(ivideo->vbflags2 & VB2_301) {
2415 svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
2416 myflag = SiS_GetReg(SISPART4, 0x01);
2418 svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
2420 } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) {
2421 svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
2422 } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) {
2423 svhs = 0x0200; cvbs = 0x0100;
2424 } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
2425 svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
2429 vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
2430 if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
2431 svhs_c = 0x0408; cvbs_c = 0x0808;
2435 if(ivideo->haveXGIROM) {
2436 biosflag = ivideo->bios_abase[0x58] & 0x03;
2437 } else if(ivideo->newrom) {
2438 if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01;
2439 } else if(ivideo->sisvga_engine == SIS_300_VGA) {
2440 if(ivideo->bios_abase) {
2441 biosflag = ivideo->bios_abase[0xfe] & 0x03;
2445 if(ivideo->chip == SIS_300) {
2446 myflag = SiS_GetReg(SISSR, 0x3b);
2447 if(!(myflag & 0x01)) vga2 = vga2_c = 0;
2450 if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) {
2454 backupSR_1e = SiS_GetReg(SISSR, 0x1e);
2455 SiS_SetRegOR(SISSR, 0x1e, 0x20);
2457 backupP4_0d = SiS_GetReg(SISPART4, 0x0d);
2458 if(ivideo->vbflags2 & VB2_30xC) {
2459 SiS_SetRegANDOR(SISPART4, 0x0d, ~0x07, 0x01);
2461 SiS_SetRegOR(SISPART4, 0x0d, 0x04);
2463 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2465 backupP2_00 = SiS_GetReg(SISPART2, 0x00);
2466 SiS_SetReg(SISPART2, 0x00, ((backupP2_00 | 0x1c) & 0xfc));
2468 backupP2_4d = SiS_GetReg(SISPART2, 0x4d);
2469 if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
2470 SiS_SetReg(SISPART2, 0x4d, (backupP2_4d & ~0x10));
2473 if(!(ivideo->vbflags2 & VB2_30xCLV)) {
2474 SISDoSense(ivideo, 0, 0);
2477 SiS_SetRegAND(SISCR, 0x32, ~0x14);
2479 if(vga2_c || vga2) {
2480 if(SISDoSense(ivideo, vga2, vga2_c)) {
2481 if(biosflag & 0x01) {
2482 printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
2483 SiS_SetRegOR(SISCR, 0x32, 0x04);
2485 printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
2486 SiS_SetRegOR(SISCR, 0x32, 0x10);
2491 SiS_SetRegAND(SISCR, 0x32, 0x3f);
2493 if(ivideo->vbflags2 & VB2_30xCLV) {
2494 SiS_SetRegOR(SISPART4, 0x0d, 0x04);
2497 if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
2498 SiS_SetReg(SISPART2, 0x4d, (backupP2_4d | 0x10));
2499 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2500 if((result = SISDoSense(ivideo, svhs, 0x0604))) {
2501 if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
2502 printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
2503 SiS_SetRegOR(SISCR, 0x32, 0x80);
2506 SiS_SetReg(SISPART2, 0x4d, backupP2_4d);
2509 SiS_SetRegAND(SISCR, 0x32, ~0x03);
2511 if(!(ivideo->vbflags & TV_YPBPR)) {
2512 if((result = SISDoSense(ivideo, svhs, svhs_c))) {
2513 printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
2514 SiS_SetRegOR(SISCR, 0x32, 0x02);
2516 if((biosflag & 0x02) || (!result)) {
2517 if(SISDoSense(ivideo, cvbs, cvbs_c)) {
2518 printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
2519 SiS_SetRegOR(SISCR, 0x32, 0x01);
2524 SISDoSense(ivideo, 0, 0);
2526 SiS_SetReg(SISPART2, 0x00, backupP2_00);
2527 SiS_SetReg(SISPART4, 0x0d, backupP4_0d);
2528 SiS_SetReg(SISSR, 0x1e, backupSR_1e);
2530 if(ivideo->vbflags2 & VB2_30xCLV) {
2531 biosflag = SiS_GetReg(SISPART2, 0x00);
2532 if(biosflag & 0x20) {
2533 for(myflag = 2; myflag > 0; myflag--) {
2535 SiS_SetReg(SISPART2, 0x00, biosflag);
2540 SiS_SetReg(SISPART2, 0x00, backupP2_00);
2543 /* Determine and detect attached TV's on Chrontel */
2544 static void SiS_SenseCh(struct sis_video_info *ivideo)
2546 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2548 char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
2550 #ifdef CONFIG_FB_SIS_300
2551 unsigned char test[3];
2555 if(ivideo->chip < SIS_315H) {
2557 #ifdef CONFIG_FB_SIS_300
2558 ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1; /* Chrontel 700x */
2559 SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c); /* Set general purpose IO for Chrontel communication */
2560 SiS_DDC2Delay(&ivideo->SiS_Pr, 1000);
2561 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2562 /* See Chrontel TB31 for explanation */
2563 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2564 if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
2565 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b);
2566 SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2568 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2569 if(temp2 != temp1) temp1 = temp2;
2571 if((temp1 >= 0x22) && (temp1 <= 0x50)) {
2572 /* Read power status */
2573 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2574 if((temp1 & 0x03) != 0x03) {
2575 /* Power all outputs */
2576 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b);
2577 SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2579 /* Sense connected TV devices */
2580 for(i = 0; i < 3; i++) {
2581 SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01);
2582 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2583 SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00);
2584 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2585 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
2586 if(!(temp1 & 0x08)) test[i] = 0x02;
2587 else if(!(temp1 & 0x02)) test[i] = 0x01;
2589 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2592 if(test[0] == test[1]) temp1 = test[0];
2593 else if(test[0] == test[2]) temp1 = test[0];
2594 else if(test[1] == test[2]) temp1 = test[1];
2597 "sisfb: TV detection unreliable - test results varied\n");
2601 printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2602 ivideo->vbflags |= TV_SVIDEO;
2603 SiS_SetRegOR(SISCR, 0x32, 0x02);
2604 SiS_SetRegAND(SISCR, 0x32, ~0x05);
2605 } else if (temp1 == 0x01) {
2606 printk(KERN_INFO "%s CVBS output\n", stdstr);
2607 ivideo->vbflags |= TV_AVIDEO;
2608 SiS_SetRegOR(SISCR, 0x32, 0x01);
2609 SiS_SetRegAND(SISCR, 0x32, ~0x06);
2611 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2612 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2614 } else if(temp1 == 0) {
2615 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2616 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2618 /* Set general purpose IO for Chrontel communication */
2619 SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
2624 #ifdef CONFIG_FB_SIS_315
2625 ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */
2626 temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
2627 SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20);
2628 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2629 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2631 SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2632 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2634 SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2635 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2636 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2637 SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1);
2639 if(temp2 & 0x02) temp1 |= 0x01;
2640 if(temp2 & 0x10) temp1 |= 0x01;
2641 if(temp2 & 0x04) temp1 |= 0x02;
2642 if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
2645 printk(KERN_INFO "%s CVBS output\n", stdstr);
2646 ivideo->vbflags |= TV_AVIDEO;
2647 SiS_SetRegOR(SISCR, 0x32, 0x01);
2648 SiS_SetRegAND(SISCR, 0x32, ~0x06);
2651 printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2652 ivideo->vbflags |= TV_SVIDEO;
2653 SiS_SetRegOR(SISCR, 0x32, 0x02);
2654 SiS_SetRegAND(SISCR, 0x32, ~0x05);
2657 printk(KERN_INFO "%s SCART output\n", stdstr);
2658 SiS_SetRegOR(SISCR, 0x32, 0x04);
2659 SiS_SetRegAND(SISCR, 0x32, ~0x03);
2662 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2668 static void sisfb_get_VB_type(struct sis_video_info *ivideo)
2670 char stdstr[] = "sisfb: Detected";
2671 char bridgestr[] = "video bridge";
2675 /* No CRT2 on XGI Z7 */
2676 if(ivideo->chip == XGI_20)
2679 vb_chipid = SiS_GetReg(SISPART4, 0x00);
2682 reg = SiS_GetReg(SISPART4, 0x01);
2684 ivideo->vbflags |= VB_301; /* Deprecated */
2685 ivideo->vbflags2 |= VB2_301;
2686 printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
2687 } else if(reg < 0xc0) {
2688 ivideo->vbflags |= VB_301B; /* Deprecated */
2689 ivideo->vbflags2 |= VB2_301B;
2690 reg = SiS_GetReg(SISPART4, 0x23);
2692 ivideo->vbflags |= VB_30xBDH; /* Deprecated */
2693 ivideo->vbflags2 |= VB2_30xBDH;
2694 printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
2696 printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
2698 } else if(reg < 0xd0) {
2699 ivideo->vbflags |= VB_301C; /* Deprecated */
2700 ivideo->vbflags2 |= VB2_301C;
2701 printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
2702 } else if(reg < 0xe0) {
2703 ivideo->vbflags |= VB_301LV; /* Deprecated */
2704 ivideo->vbflags2 |= VB2_301LV;
2705 printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
2706 } else if(reg <= 0xe1) {
2707 reg = SiS_GetReg(SISPART4, 0x39);
2709 ivideo->vbflags |= VB_302LV; /* Deprecated */
2710 ivideo->vbflags2 |= VB2_302LV;
2711 printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
2713 ivideo->vbflags |= VB_301C; /* Deprecated */
2714 ivideo->vbflags2 |= VB2_301C;
2715 printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
2717 ivideo->vbflags |= VB_302ELV; /* Deprecated */
2718 ivideo->vbflags2 |= VB2_302ELV;
2719 printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
2725 ivideo->vbflags |= VB_302B; /* Deprecated */
2726 ivideo->vbflags2 |= VB2_302B;
2727 printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
2731 if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
2732 reg = SiS_GetReg(SISCR, 0x37);
2733 reg &= SIS_EXTERNAL_CHIP_MASK;
2735 if(ivideo->sisvga_engine == SIS_300_VGA) {
2736 #ifdef CONFIG_FB_SIS_300
2738 case SIS_EXTERNAL_CHIP_LVDS:
2739 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2740 ivideo->vbflags2 |= VB2_LVDS;
2742 case SIS_EXTERNAL_CHIP_TRUMPION:
2743 ivideo->vbflags |= (VB_LVDS | VB_TRUMPION); /* Deprecated */
2744 ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION);
2746 case SIS_EXTERNAL_CHIP_CHRONTEL:
2747 ivideo->vbflags |= VB_CHRONTEL; /* Deprecated */
2748 ivideo->vbflags2 |= VB2_CHRONTEL;
2750 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
2751 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2752 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2755 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1;
2757 } else if(ivideo->chip < SIS_661) {
2758 #ifdef CONFIG_FB_SIS_315
2760 case SIS310_EXTERNAL_CHIP_LVDS:
2761 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2762 ivideo->vbflags2 |= VB2_LVDS;
2764 case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
2765 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2766 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2769 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2771 } else if(ivideo->chip >= SIS_661) {
2772 #ifdef CONFIG_FB_SIS_315
2773 reg = SiS_GetReg(SISCR, 0x38);
2777 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2778 ivideo->vbflags2 |= VB2_LVDS;
2781 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2782 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2785 ivideo->vbflags |= (VB_LVDS | VB_CONEXANT); /* Deprecated */
2786 ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT);
2789 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2792 if(ivideo->vbflags2 & VB2_LVDS) {
2793 printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
2795 if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) {
2796 printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
2798 if(ivideo->vbflags2 & VB2_CHRONTEL) {
2799 printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
2801 if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) {
2802 printk(KERN_INFO "%s Conexant external device\n", stdstr);
2806 if(ivideo->vbflags2 & VB2_SISBRIDGE) {
2807 SiS_SenseLCD(ivideo);
2808 SiS_Sense30x(ivideo);
2809 } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
2810 SiS_SenseCh(ivideo);
2814 /* ---------- Engine initialization routines ------------ */
2817 sisfb_engine_init(struct sis_video_info *ivideo)
2820 /* Initialize command queue (we use MMIO only) */
2822 /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
2824 ivideo->caps &= ~(TURBO_QUEUE_CAP |
2825 MMIO_CMD_QUEUE_CAP |
2829 #ifdef CONFIG_FB_SIS_300
2830 if(ivideo->sisvga_engine == SIS_300_VGA) {
2834 tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
2836 tq_state = SiS_GetReg(SISSR, IND_SIS_TURBOQUEUE_SET);
2839 tq_state |= (u8)(tqueue_pos >> 8);
2840 SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
2842 SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
2844 ivideo->caps |= TURBO_QUEUE_CAP;
2848 #ifdef CONFIG_FB_SIS_315
2849 if(ivideo->sisvga_engine == SIS_315_VGA) {
2850 u32 tempq = 0, templ;
2853 if(ivideo->chip == XGI_20) {
2854 switch(ivideo->cmdQueueSize) {
2856 temp = SIS_CMD_QUEUE_SIZE_Z7_64k;
2860 temp = SIS_CMD_QUEUE_SIZE_Z7_128k;
2863 switch(ivideo->cmdQueueSize) {
2864 case (4 * 1024 * 1024):
2865 temp = SIS_CMD_QUEUE_SIZE_4M;
2867 case (2 * 1024 * 1024):
2868 temp = SIS_CMD_QUEUE_SIZE_2M;
2870 case (1 * 1024 * 1024):
2871 temp = SIS_CMD_QUEUE_SIZE_1M;
2875 temp = SIS_CMD_QUEUE_SIZE_512k;
2879 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2880 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2882 if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
2883 /* Must disable dual pipe on XGI_40. Can't do
2884 * this in MMIO mode, because it requires
2885 * setting/clearing a bit in the MMIO fire trigger
2888 if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) {
2890 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
2892 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
2894 tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
2895 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
2897 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2898 MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq);
2900 writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq);
2901 writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4);
2902 writel(0x168F0000, ivideo->video_vbase + tempq + 8);
2903 writel(0x168F0000, ivideo->video_vbase + tempq + 12);
2905 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16));
2907 sisfb_syncaccel(ivideo);
2909 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2914 tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
2915 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
2917 temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
2918 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, temp);
2920 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2921 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
2923 ivideo->caps |= MMIO_CMD_QUEUE_CAP;
2927 ivideo->engineok = 1;
2930 static void sisfb_detect_lcd_type(struct sis_video_info *ivideo)
2935 reg = SiS_GetReg(SISCR, 0x36);
2937 if(ivideo->sisvga_engine == SIS_300_VGA) {
2938 ivideo->CRT2LCDType = sis300paneltype[reg];
2939 } else if(ivideo->chip >= SIS_661) {
2940 ivideo->CRT2LCDType = sis661paneltype[reg];
2942 ivideo->CRT2LCDType = sis310paneltype[reg];
2943 if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
2944 if((ivideo->CRT2LCDType != LCD_320x240_2) &&
2945 (ivideo->CRT2LCDType != LCD_320x240_3)) {
2946 ivideo->CRT2LCDType = LCD_320x240;
2951 if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
2952 /* For broken BIOSes: Assume 1024x768, RGB18 */
2953 ivideo->CRT2LCDType = LCD_1024x768;
2954 SiS_SetRegANDOR(SISCR, 0x36, 0xf0, 0x02);
2955 SiS_SetRegANDOR(SISCR, 0x37, 0xee, 0x01);
2956 printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
2959 for(i = 0; i < SIS_LCD_NUMBER; i++) {
2960 if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
2961 ivideo->lcdxres = sis_lcd_data[i].xres;
2962 ivideo->lcdyres = sis_lcd_data[i].yres;
2963 ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
2968 #ifdef CONFIG_FB_SIS_300
2969 if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
2970 ivideo->lcdxres = 1360; ivideo->lcdyres = 1024;
2971 ivideo->lcddefmodeidx = DEFAULT_MODE_1360;
2972 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
2973 ivideo->lcdxres = 848; ivideo->lcdyres = 480;
2974 ivideo->lcddefmodeidx = DEFAULT_MODE_848;
2975 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) {
2976 ivideo->lcdxres = 856; ivideo->lcdyres = 480;
2977 ivideo->lcddefmodeidx = DEFAULT_MODE_856;
2981 printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
2982 ivideo->lcdxres, ivideo->lcdyres);
2985 static void sisfb_save_pdc_emi(struct sis_video_info *ivideo)
2987 #ifdef CONFIG_FB_SIS_300
2988 /* Save the current PanelDelayCompensation if the LCD is currently used */
2989 if(ivideo->sisvga_engine == SIS_300_VGA) {
2990 if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
2992 tmp = SiS_GetReg(SISCR, 0x30);
2994 /* Currently on LCD? If yes, read current pdc */
2995 ivideo->detectedpdc = SiS_GetReg(SISPART1, 0x13);
2996 ivideo->detectedpdc &= 0x3c;
2997 if(ivideo->SiS_Pr.PDC == -1) {
2998 /* Let option override detection */
2999 ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
3001 printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
3002 ivideo->detectedpdc);
3004 if((ivideo->SiS_Pr.PDC != -1) &&
3005 (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
3006 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
3007 ivideo->SiS_Pr.PDC);
3013 #ifdef CONFIG_FB_SIS_315
3014 if(ivideo->sisvga_engine == SIS_315_VGA) {
3016 /* Try to find about LCDA */
3017 if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
3019 tmp = SiS_GetReg(SISPART1, 0x13);
3021 ivideo->SiS_Pr.SiS_UseLCDA = true;
3022 ivideo->detectedlcda = 0x03;
3027 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
3029 tmp = SiS_GetReg(SISCR, 0x30);
3030 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3031 /* Currently on LCD? If yes, read current pdc */
3033 pdc = SiS_GetReg(SISPART1, 0x2D);
3034 ivideo->detectedpdc = (pdc & 0x0f) << 1;
3035 ivideo->detectedpdca = (pdc & 0xf0) >> 3;
3036 pdc = SiS_GetReg(SISPART1, 0x35);
3037 ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
3038 pdc = SiS_GetReg(SISPART1, 0x20);
3039 ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
3040 if(ivideo->newrom) {
3041 /* New ROM invalidates other PDC resp. */
3042 if(ivideo->detectedlcda != 0xff) {
3043 ivideo->detectedpdc = 0xff;
3045 ivideo->detectedpdca = 0xff;
3048 if(ivideo->SiS_Pr.PDC == -1) {
3049 if(ivideo->detectedpdc != 0xff) {
3050 ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
3053 if(ivideo->SiS_Pr.PDCA == -1) {
3054 if(ivideo->detectedpdca != 0xff) {
3055 ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
3058 if(ivideo->detectedpdc != 0xff) {
3060 "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3061 ivideo->detectedpdc);
3063 if(ivideo->detectedpdca != 0xff) {
3065 "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3066 ivideo->detectedpdca);
3071 if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
3072 ivideo->SiS_Pr.EMI_30 = SiS_GetReg(SISPART4, 0x30);
3073 ivideo->SiS_Pr.EMI_31 = SiS_GetReg(SISPART4, 0x31);
3074 ivideo->SiS_Pr.EMI_32 = SiS_GetReg(SISPART4, 0x32);
3075 ivideo->SiS_Pr.EMI_33 = SiS_GetReg(SISPART4, 0x33);
3076 ivideo->SiS_Pr.HaveEMI = true;
3077 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3078 ivideo->SiS_Pr.HaveEMILCD = true;
3083 /* Let user override detected PDCs (all bridges) */
3084 if(ivideo->vbflags2 & VB2_30xBLV) {
3085 if((ivideo->SiS_Pr.PDC != -1) &&
3086 (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
3087 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3088 ivideo->SiS_Pr.PDC);
3090 if((ivideo->SiS_Pr.PDCA != -1) &&
3091 (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
3092 printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3093 ivideo->SiS_Pr.PDCA);
3101 /* -------------------- Memory manager routines ---------------------- */
3103 static u32 sisfb_getheapstart(struct sis_video_info *ivideo)
3105 u32 ret = ivideo->sisfb_parm_mem * 1024;
3106 u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3109 /* Calculate heap start = end of memory for console
3111 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3112 * C = console, D = heap, H = HWCursor, Q = cmd-queue
3114 * On 76x in UMA+LFB mode, the layout is as follows:
3115 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3116 * where the heap is the entire UMA area, eventually
3117 * into the LFB area if the given mem parameter is
3118 * higher than the size of the UMA memory.
3120 * Basically given by "mem" parameter
3122 * maximum = videosize - cmd_queue - hwcursor
3123 * (results in a heap of size 0)
3124 * default = SiS 300: depends on videosize
3125 * SiS 315/330/340/XGI: 32k below max
3128 if(ivideo->sisvga_engine == SIS_300_VGA) {
3129 if(ivideo->video_size > 0x1000000) {
3131 } else if(ivideo->video_size > 0x800000) {
3136 } else if(ivideo->UMAsize && ivideo->LFBsize) {
3139 def = maxoffs - 0x8000;
3142 /* Use default for secondary card for now (FIXME) */
3143 if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0))
3149 static u32 sisfb_getheapsize(struct sis_video_info *ivideo)
3151 u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3154 if(ivideo->UMAsize && ivideo->LFBsize) {
3155 if( (!ivideo->sisfb_parm_mem) ||
3156 ((ivideo->sisfb_parm_mem * 1024) > max) ||
3157 ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) {
3158 ret = ivideo->UMAsize;
3159 max -= ivideo->UMAsize;
3161 ret = max - (ivideo->sisfb_parm_mem * 1024);
3162 max = ivideo->sisfb_parm_mem * 1024;
3164 ivideo->video_offset = ret;
3165 ivideo->sisfb_mem = max;
3167 ret = max - ivideo->heapstart;
3168 ivideo->sisfb_mem = ivideo->heapstart;
3174 static int sisfb_heap_init(struct sis_video_info *ivideo)
3178 ivideo->video_offset = 0;
3179 if(ivideo->sisfb_parm_mem) {
3180 if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) ||
3181 (ivideo->sisfb_parm_mem > ivideo->video_size) ) {
3182 ivideo->sisfb_parm_mem = 0;
3186 ivideo->heapstart = sisfb_getheapstart(ivideo);
3187 ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo);
3189 ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
3190 ivideo->sisfb_heap_end = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size;
3192 printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
3193 (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
3195 ivideo->sisfb_heap.vinfo = ivideo;
3197 ivideo->sisfb_heap.poha_chain = NULL;
3198 ivideo->sisfb_heap.poh_freelist = NULL;
3200 poh = sisfb_poh_new_node(&ivideo->sisfb_heap);
3204 poh->poh_next = &ivideo->sisfb_heap.oh_free;
3205 poh->poh_prev = &ivideo->sisfb_heap.oh_free;
3206 poh->size = ivideo->sisfb_heap_size;
3207 poh->offset = ivideo->heapstart;
3209 ivideo->sisfb_heap.oh_free.poh_next = poh;
3210 ivideo->sisfb_heap.oh_free.poh_prev = poh;
3211 ivideo->sisfb_heap.oh_free.size = 0;
3212 ivideo->sisfb_heap.max_freesize = poh->size;
3214 ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used;
3215 ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used;
3216 ivideo->sisfb_heap.oh_used.size = SENTINEL;
3218 if(ivideo->cardnumber == 0) {
3219 /* For the first card, make this heap the "global" one
3220 * for old DRM (which could handle only one card)
3222 sisfb_heap = &ivideo->sisfb_heap;
3228 static struct SIS_OH *
3229 sisfb_poh_new_node(struct SIS_HEAP *memheap)
3231 struct SIS_OHALLOC *poha;
3236 if(memheap->poh_freelist == NULL) {
3237 poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
3241 poha->poha_next = memheap->poha_chain;
3242 memheap->poha_chain = poha;
3244 cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1;
3246 poh = &poha->aoh[0];
3247 for(i = cOhs - 1; i != 0; i--) {
3248 poh->poh_next = poh + 1;
3252 poh->poh_next = NULL;
3253 memheap->poh_freelist = &poha->aoh[0];
3256 poh = memheap->poh_freelist;
3257 memheap->poh_freelist = poh->poh_next;
3262 static struct SIS_OH *
3263 sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size)
3265 struct SIS_OH *pohThis;
3266 struct SIS_OH *pohRoot;
3269 if(size > memheap->max_freesize) {
3270 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3271 (unsigned int) size / 1024);
3275 pohThis = memheap->oh_free.poh_next;
3277 while(pohThis != &memheap->oh_free) {
3278 if(size <= pohThis->size) {
3282 pohThis = pohThis->poh_next;
3286 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3287 (unsigned int) size / 1024);
3291 if(size == pohThis->size) {
3293 sisfb_delete_node(pohThis);
3295 pohRoot = sisfb_poh_new_node(memheap);
3299 pohRoot->offset = pohThis->offset;
3300 pohRoot->size = size;
3302 pohThis->offset += size;
3303 pohThis->size -= size;
3306 memheap->max_freesize -= size;
3308 pohThis = &memheap->oh_used;
3309 sisfb_insert_node(pohThis, pohRoot);
3315 sisfb_delete_node(struct SIS_OH *poh)
3317 poh->poh_prev->poh_next = poh->poh_next;
3318 poh->poh_next->poh_prev = poh->poh_prev;
3322 sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh)
3324 struct SIS_OH *pohTemp = pohList->poh_next;
3326 pohList->poh_next = poh;
3327 pohTemp->poh_prev = poh;
3329 poh->poh_prev = pohList;
3330 poh->poh_next = pohTemp;
3333 static struct SIS_OH *
3334 sisfb_poh_free(struct SIS_HEAP *memheap, u32 base)
3336 struct SIS_OH *pohThis;
3337 struct SIS_OH *poh_freed;
3338 struct SIS_OH *poh_prev;
3339 struct SIS_OH *poh_next;
3344 poh_freed = memheap->oh_used.poh_next;
3346 while(poh_freed != &memheap->oh_used) {
3347 if(poh_freed->offset == base) {
3352 poh_freed = poh_freed->poh_next;
3358 memheap->max_freesize += poh_freed->size;
3360 poh_prev = poh_next = NULL;
3361 ulUpper = poh_freed->offset + poh_freed->size;
3362 ulLower = poh_freed->offset;
3364 pohThis = memheap->oh_free.poh_next;
3366 while(pohThis != &memheap->oh_free) {
3367 if(pohThis->offset == ulUpper) {
3369 } else if((pohThis->offset + pohThis->size) == ulLower) {
3372 pohThis = pohThis->poh_next;
3375 sisfb_delete_node(poh_freed);
3377 if(poh_prev && poh_next) {
3378 poh_prev->size += (poh_freed->size + poh_next->size);
3379 sisfb_delete_node(poh_next);
3380 sisfb_free_node(memheap, poh_freed);
3381 sisfb_free_node(memheap, poh_next);
3386 poh_prev->size += poh_freed->size;
3387 sisfb_free_node(memheap, poh_freed);
3392 poh_next->size += poh_freed->size;
3393 poh_next->offset = poh_freed->offset;
3394 sisfb_free_node(memheap, poh_freed);
3398 sisfb_insert_node(&memheap->oh_free, poh_freed);
3404 sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh)
3409 poh->poh_next = memheap->poh_freelist;
3410 memheap->poh_freelist = poh;
3414 sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req)
3416 struct SIS_OH *poh = NULL;
3418 if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap))
3419 poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size);
3422 req->offset = req->size = 0;
3423 DPRINTK("sisfb: Video RAM allocation failed\n");
3425 req->offset = poh->offset;
3426 req->size = poh->size;
3427 DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3428 (poh->offset + ivideo->video_vbase));
3433 sis_malloc(struct sis_memreq *req)
3435 struct sis_video_info *ivideo = sisfb_heap->vinfo;
3437 if(&ivideo->sisfb_heap == sisfb_heap)
3438 sis_int_malloc(ivideo, req);
3440 req->offset = req->size = 0;
3444 sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
3446 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3448 sis_int_malloc(ivideo, req);
3451 /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3454 sis_int_free(struct sis_video_info *ivideo, u32 base)
3458 if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap))
3461 poh = sisfb_poh_free(&ivideo->sisfb_heap, base);
3464 DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
3465 (unsigned int) base);
3472 struct sis_video_info *ivideo = sisfb_heap->vinfo;
3474 sis_int_free(ivideo, base);
3478 sis_free_new(struct pci_dev *pdev, u32 base)
3480 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3482 sis_int_free(ivideo, base);
3485 /* --------------------- SetMode routines ------------------------- */
3488 sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
3492 /* Check if MMIO and engines are enabled,
3493 * and sync in case they are. Can't use
3494 * ivideo->accel here, as this might have
3495 * been changed before this is called.
3497 cr30 = SiS_GetReg(SISSR, IND_SIS_PCI_ADDRESS_SET);
3498 cr31 = SiS_GetReg(SISSR, IND_SIS_MODULE_ENABLE);
3499 /* MMIO and 2D/3D engine enabled? */
3500 if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
3501 #ifdef CONFIG_FB_SIS_300
3502 if(ivideo->sisvga_engine == SIS_300_VGA) {
3503 /* Don't care about TurboQueue. It's
3504 * enough to know that the engines
3507 sisfb_syncaccel(ivideo);
3510 #ifdef CONFIG_FB_SIS_315
3511 if(ivideo->sisvga_engine == SIS_315_VGA) {
3512 /* Check that any queue mode is
3513 * enabled, and that the queue
3514 * is not in the state of "reset"
3516 cr30 = SiS_GetReg(SISSR, 0x26);
3517 if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
3518 sisfb_syncaccel(ivideo);
3526 sisfb_pre_setmode(struct sis_video_info *ivideo)
3528 u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
3531 ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
3533 SiS_SetReg(SISSR, 0x05, 0x86);
3535 cr31 = SiS_GetReg(SISCR, 0x31);
3539 cr33 = ivideo->rate_idx & 0x0F;
3541 #ifdef CONFIG_FB_SIS_315
3542 if(ivideo->sisvga_engine == SIS_315_VGA) {
3543 if(ivideo->chip >= SIS_661) {
3544 cr38 = SiS_GetReg(SISCR, 0x38);
3545 cr38 &= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
3548 cr38 = SiS_GetReg(SISCR, tvregnum);
3549 cr38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
3553 #ifdef CONFIG_FB_SIS_300
3554 if(ivideo->sisvga_engine == SIS_300_VGA) {
3556 cr38 = SiS_GetReg(SISCR, tvregnum);
3560 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
3561 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
3562 ivideo->curFSTN = ivideo->curDSTN = 0;
3564 switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
3567 cr38 &= ~0xc0; /* Clear PAL-M / PAL-N bits */
3568 if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
3569 #ifdef CONFIG_FB_SIS_315
3570 if(ivideo->chip >= SIS_661) {
3572 if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20;
3573 else if(ivideo->vbflags & TV_YPBPR750P) cr35 |= 0x40;
3574 else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
3575 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3577 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3578 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
3579 cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3581 if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10;
3582 else if(ivideo->vbflags & TV_YPBPR750P) cr38 |= 0x20;
3583 else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
3585 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3588 } else if((ivideo->vbflags & TV_HIVISION) &&
3589 (ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) {
3590 if(ivideo->chip >= SIS_661) {
3596 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3599 ivideo->currentvbflags |= TV_HIVISION;
3600 } else if(ivideo->vbflags & TV_SCART) {
3601 cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
3604 ivideo->currentvbflags |= TV_SCART;
3606 if(ivideo->vbflags & TV_SVIDEO) {
3607 cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
3608 ivideo->currentvbflags |= TV_SVIDEO;
3610 if(ivideo->vbflags & TV_AVIDEO) {
3611 cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
3612 ivideo->currentvbflags |= TV_AVIDEO;
3615 cr31 |= SIS_DRIVER_MODE;
3617 if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) {
3618 if(ivideo->vbflags & TV_PAL) {
3619 cr31 |= 0x01; cr35 |= 0x01;
3620 ivideo->currentvbflags |= TV_PAL;
3621 if(ivideo->vbflags & TV_PALM) {
3622 cr38 |= 0x40; cr35 |= 0x04;
3623 ivideo->currentvbflags |= TV_PALM;
3624 } else if(ivideo->vbflags & TV_PALN) {
3625 cr38 |= 0x80; cr35 |= 0x08;
3626 ivideo->currentvbflags |= TV_PALN;
3629 cr31 &= ~0x01; cr35 &= ~0x01;
3630 ivideo->currentvbflags |= TV_NTSC;
3631 if(ivideo->vbflags & TV_NTSCJ) {
3632 cr38 |= 0x40; cr35 |= 0x02;
3633 ivideo->currentvbflags |= TV_NTSCJ;
3640 cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
3641 cr31 |= SIS_DRIVER_MODE;
3642 SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
3643 SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
3644 ivideo->curFSTN = ivideo->sisfb_fstn;
3645 ivideo->curDSTN = ivideo->sisfb_dstn;
3649 cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3650 cr31 |= SIS_DRIVER_MODE;
3651 if(ivideo->sisfb_nocrt2rate) {
3652 cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4);
3654 cr33 |= ((ivideo->rate_idx & 0x0F) << 4);
3658 default: /* disable CRT2 */
3660 cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
3663 SiS_SetReg(SISCR, 0x30, cr30);
3664 SiS_SetReg(SISCR, 0x33, cr33);
3666 if(ivideo->chip >= SIS_661) {
3667 #ifdef CONFIG_FB_SIS_315
3668 cr31 &= ~0x01; /* Clear PAL flag (now in CR35) */
3669 SiS_SetRegANDOR(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
3670 cr38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
3671 SiS_SetRegANDOR(SISCR, 0x38, 0xf8, cr38);
3673 } else if(ivideo->chip != SIS_300) {
3674 SiS_SetReg(SISCR, tvregnum, cr38);
3676 SiS_SetReg(SISCR, 0x31, cr31);
3678 ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
3680 sisfb_check_engine_and_sync(ivideo);
3683 /* Fix SR11 for 661 and later */
3684 #ifdef CONFIG_FB_SIS_315
3686 sisfb_fixup_SR11(struct sis_video_info *ivideo)
3690 if(ivideo->chip >= SIS_661) {
3691 tmpreg = SiS_GetReg(SISSR, 0x11);
3693 tmpreg = SiS_GetReg(SISSR, 0x3e);
3694 tmpreg = (tmpreg + 1) & 0xff;
3695 SiS_SetReg(SISSR, 0x3e, tmpreg);
3696 tmpreg = SiS_GetReg(SISSR, 0x11);
3699 SiS_SetRegAND(SISSR, 0x11, 0x0f);
3706 sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
3708 if(val > 32) val = 32;
3709 if(val < -32) val = -32;
3710 ivideo->tvxpos = val;
3712 if(ivideo->sisfblocked) return;
3713 if(!ivideo->modechanged) return;
3715 if(ivideo->currentvbflags & CRT2_TV) {
3717 if(ivideo->vbflags2 & VB2_CHRONTEL) {
3719 int x = ivideo->tvx;
3721 switch(ivideo->chronteltype) {
3725 SiS_SetReg(SISSR, 0x05, 0x86);
3726 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
3727 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
3730 /* Not supported by hardware */
3734 } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3736 u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
3737 unsigned short temp;
3739 p2_1f = ivideo->p2_1f;
3740 p2_20 = ivideo->p2_20;
3741 p2_2b = ivideo->p2_2b;
3742 p2_42 = ivideo->p2_42;
3743 p2_43 = ivideo->p2_43;
3745 temp = p2_1f | ((p2_20 & 0xf0) << 4);
3747 p2_1f = temp & 0xff;
3748 p2_20 = (temp & 0xf00) >> 4;
3749 p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
3750 temp = p2_43 | ((p2_42 & 0xf0) << 4);
3752 p2_43 = temp & 0xff;
3753 p2_42 = (temp & 0xf00) >> 4;
3754 SiS_SetReg(SISPART2, 0x1f, p2_1f);
3755 SiS_SetRegANDOR(SISPART2, 0x20, 0x0F, p2_20);
3756 SiS_SetRegANDOR(SISPART2, 0x2b, 0xF0, p2_2b);
3757 SiS_SetRegANDOR(SISPART2, 0x42, 0x0F, p2_42);
3758 SiS_SetReg(SISPART2, 0x43, p2_43);
3764 sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
3766 if(val > 32) val = 32;
3767 if(val < -32) val = -32;
3768 ivideo->tvypos = val;
3770 if(ivideo->sisfblocked) return;
3771 if(!ivideo->modechanged) return;
3773 if(ivideo->currentvbflags & CRT2_TV) {
3775 if(ivideo->vbflags2 & VB2_CHRONTEL) {
3777 int y = ivideo->tvy;
3779 switch(ivideo->chronteltype) {
3783 SiS_SetReg(SISSR, 0x05, 0x86);
3784 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
3785 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
3788 /* Not supported by hardware */
3792 } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3796 p2_01 = ivideo->p2_01;
3797 p2_02 = ivideo->p2_02;
3801 if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) {
3802 while((p2_01 <= 0) || (p2_02 <= 0)) {
3807 SiS_SetReg(SISPART2, 0x01, p2_01);
3808 SiS_SetReg(SISPART2, 0x02, p2_02);
3814 sisfb_post_setmode(struct sis_video_info *ivideo)
3816 bool crt1isoff = false;
3818 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
3821 #ifdef CONFIG_FB_SIS_315
3825 SiS_SetReg(SISSR, 0x05, 0x86);
3827 #ifdef CONFIG_FB_SIS_315
3828 sisfb_fixup_SR11(ivideo);
3831 /* Now we actually HAVE changed the display mode */
3832 ivideo->modechanged = 1;
3834 /* We can't switch off CRT1 if bridge is in slave mode */
3835 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
3836 if(sisfb_bridgeisslave(ivideo)) doit = false;
3838 ivideo->sisfb_crt1off = 0;
3840 #ifdef CONFIG_FB_SIS_300
3841 if(ivideo->sisvga_engine == SIS_300_VGA) {
3842 if((ivideo->sisfb_crt1off) && (doit)) {
3849 SiS_SetRegANDOR(SISCR, 0x17, 0x7f, reg);
3852 #ifdef CONFIG_FB_SIS_315
3853 if(ivideo->sisvga_engine == SIS_315_VGA) {
3854 if((ivideo->sisfb_crt1off) && (doit)) {
3863 SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
3864 SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, reg1);
3869 ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
3870 ivideo->currentvbflags |= VB_SINGLE_MODE;
3872 ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
3873 if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
3874 ivideo->currentvbflags |= VB_MIRROR_MODE;
3876 ivideo->currentvbflags |= VB_SINGLE_MODE;
3880 SiS_SetRegAND(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
3882 if(ivideo->currentvbflags & CRT2_TV) {
3883 if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3884 ivideo->p2_1f = SiS_GetReg(SISPART2, 0x1f);
3885 ivideo->p2_20 = SiS_GetReg(SISPART2, 0x20);
3886 ivideo->p2_2b = SiS_GetReg(SISPART2, 0x2b);
3887 ivideo->p2_42 = SiS_GetReg(SISPART2, 0x42);
3888 ivideo->p2_43 = SiS_GetReg(SISPART2, 0x43);
3889 ivideo->p2_01 = SiS_GetReg(SISPART2, 0x01);
3890 ivideo->p2_02 = SiS_GetReg(SISPART2, 0x02);
3891 } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
3892 if(ivideo->chronteltype == 1) {
3893 ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
3894 ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
3895 ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
3896 ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
3901 if(ivideo->tvxpos) {
3902 sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
3904 if(ivideo->tvypos) {
3905 sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
3908 /* Eventually sync engines */
3909 sisfb_check_engine_and_sync(ivideo);
3911 /* (Re-)Initialize chip engines */
3913 sisfb_engine_init(ivideo);
3915 ivideo->engineok = 0;
3920 sisfb_reset_mode(struct sis_video_info *ivideo)
3922 if(sisfb_set_mode(ivideo, 0))
3925 sisfb_set_pitch(ivideo);
3926 sisfb_set_base_CRT1(ivideo, ivideo->current_base);
3927 sisfb_set_base_CRT2(ivideo, ivideo->current_base);
3933 sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command)
3937 switch(sisfb_command->sisfb_cmd) {
3938 case SISFB_CMD_GETVBFLAGS:
3939 if(!ivideo->modechanged) {
3940 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3942 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3943 sisfb_command->sisfb_result[1] = ivideo->currentvbflags;
3944 sisfb_command->sisfb_result[2] = ivideo->vbflags2;
3947 case SISFB_CMD_SWITCHCRT1:
3948 /* arg[0]: 0 = off, 1 = on, 99 = query */
3949 if(!ivideo->modechanged) {
3950 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3951 } else if(sisfb_command->sisfb_arg[0] == 99) {
3953 sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3954 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3955 } else if(ivideo->sisfblocked) {
3956 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED;
3957 } else if((!(ivideo->currentvbflags & CRT2_ENABLE)) &&
3958 (sisfb_command->sisfb_arg[0] == 0)) {
3959 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2;
3961 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3962 mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1;
3963 if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) ||
3964 ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) {
3965 ivideo->sisfb_crt1off = mycrt1off;
3966 if(sisfb_reset_mode(ivideo)) {
3967 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER;
3970 sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3975 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN;
3976 printk(KERN_ERR "sisfb: Unknown command 0x%x\n",
3977 sisfb_command->sisfb_cmd);
3982 static int __init sisfb_setup(char *options)
3986 sisfb_setdefaultparms();
3988 if(!options || !(*options))
3991 while((this_opt = strsep(&options, ",")) != NULL) {
3993 if(!(*this_opt)) continue;
3995 if(!strncasecmp(this_opt, "off", 3)) {
3997 } else if(!strncasecmp(this_opt, "forcecrt2type:", 14)) {
3998 /* Need to check crt2 type first for fstn/dstn */
3999 sisfb_search_crt2type(this_opt + 14);
4000 } else if(!strncasecmp(this_opt, "tvmode:",7)) {
4001 sisfb_search_tvstd(this_opt + 7);
4002 } else if(!strncasecmp(this_opt, "tvstandard:",11)) {
4003 sisfb_search_tvstd(this_opt + 11);
4004 } else if(!strncasecmp(this_opt, "mode:", 5)) {
4005 sisfb_search_mode(this_opt + 5, false);
4006 } else if(!strncasecmp(this_opt, "vesa:", 5)) {
4007 sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false);
4008 } else if(!strncasecmp(this_opt, "rate:", 5)) {
4009 sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
4010 } else if(!strncasecmp(this_opt, "forcecrt1:", 10)) {
4011 sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
4012 } else if(!strncasecmp(this_opt, "mem:",4)) {
4013 sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
4014 } else if(!strncasecmp(this_opt, "pdc:", 4)) {
4015 sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
4016 } else if(!strncasecmp(this_opt, "pdc1:", 5)) {
4017 sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
4018 } else if(!strncasecmp(this_opt, "noaccel", 7)) {
4020 } else if(!strncasecmp(this_opt, "accel", 5)) {
4022 } else if(!strncasecmp(this_opt, "noypan", 6)) {
4024 } else if(!strncasecmp(this_opt, "ypan", 4)) {
4026 } else if(!strncasecmp(this_opt, "nomax", 5)) {
4028 } else if(!strncasecmp(this_opt, "max", 3)) {
4030 } else if(!strncasecmp(this_opt, "userom:", 7)) {
4031 sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
4032 } else if(!strncasecmp(this_opt, "useoem:", 7)) {
4033 sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
4034 } else if(!strncasecmp(this_opt, "nocrt2rate", 10)) {
4035 sisfb_nocrt2rate = 1;
4036 } else if(!strncasecmp(this_opt, "scalelcd:", 9)) {
4037 unsigned long temp = 2;
4038 temp = simple_strtoul(this_opt + 9, NULL, 0);
4039 if((temp == 0) || (temp == 1)) {
4040 sisfb_scalelcd = temp ^ 1;
4042 } else if(!strncasecmp(this_opt, "tvxposoffset:", 13)) {
4044 temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4045 if((temp >= -32) && (temp <= 32)) {
4046 sisfb_tvxposoffset = temp;
4048 } else if(!strncasecmp(this_opt, "tvyposoffset:", 13)) {
4050 temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4051 if((temp >= -32) && (temp <= 32)) {
4052 sisfb_tvyposoffset = temp;
4054 } else if(!strncasecmp(this_opt, "specialtiming:", 14)) {
4055 sisfb_search_specialtiming(this_opt + 14);
4056 } else if(!strncasecmp(this_opt, "lvdshl:", 7)) {
4058 temp = simple_strtoul(this_opt + 7, NULL, 0);
4059 if((temp >= 0) && (temp <= 3)) {
4060 sisfb_lvdshl = temp;
4062 } else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
4063 sisfb_search_mode(this_opt, true);
4064 #if !defined(__i386__) && !defined(__x86_64__)
4065 } else if(!strncasecmp(this_opt, "resetcard", 9)) {
4066 sisfb_resetcard = 1;
4067 } else if(!strncasecmp(this_opt, "videoram:", 9)) {
4068 sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
4071 printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
4080 static int sisfb_check_rom(void __iomem *rom_base,
4081 struct sis_video_info *ivideo)
4086 if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
4089 romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
4090 if(romptr > (0x10000 - 8))
4093 rom = rom_base + romptr;
4095 if((readb(rom) != 'P') || (readb(rom + 1) != 'C') ||
4096 (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R'))
4099 if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor)
4102 if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id)
4108 static unsigned char *sisfb_find_rom(struct pci_dev *pdev)
4110 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4111 void __iomem *rom_base;
4112 unsigned char *myrombase = NULL;
4115 /* First, try the official pci ROM functions (except
4116 * on integrated chipsets which have no ROM).
4119 if(!ivideo->nbridge) {
4121 if((rom_base = pci_map_rom(pdev, &romsize))) {
4123 if(sisfb_check_rom(rom_base, ivideo)) {
4125 if((myrombase = vmalloc(65536))) {
4126 memcpy_fromio(myrombase, rom_base,
4127 (romsize > 65536) ? 65536 : romsize);
4130 pci_unmap_rom(pdev, rom_base);
4134 if(myrombase) return myrombase;
4136 /* Otherwise do it the conventional way. */
4138 #if defined(__i386__) || defined(__x86_64__)
4142 for (temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
4144 rom_base = ioremap(temp, 65536);
4148 if (!sisfb_check_rom(rom_base, ivideo)) {
4153 if ((myrombase = vmalloc(65536)))
4154 memcpy_fromio(myrombase, rom_base, 65536);
4167 static void sisfb_post_map_vram(struct sis_video_info *ivideo,
4168 unsigned int *mapsize, unsigned int min)
4170 if (*mapsize < (min << 20))
4173 ivideo->video_vbase = ioremap_wc(ivideo->video_base, (*mapsize));
4175 if(!ivideo->video_vbase) {
4177 "sisfb: Unable to map maximum video RAM for size detection\n");
4179 while((!(ivideo->video_vbase = ioremap_wc(ivideo->video_base, (*mapsize))))) {
4181 if((*mapsize) < (min << 20))
4184 if(ivideo->video_vbase) {
4186 "sisfb: Video RAM size detection limited to %dMB\n",
4187 (int)((*mapsize) >> 20));
4192 #ifdef CONFIG_FB_SIS_300
4193 static int sisfb_post_300_buswidth(struct sis_video_info *ivideo)
4195 void __iomem *FBAddress = ivideo->video_vbase;
4196 unsigned short temp;
4200 SiS_SetRegAND(SISSR, 0x15, 0xFB);
4201 SiS_SetRegOR(SISSR, 0x15, 0x04);
4202 SiS_SetReg(SISSR, 0x13, 0x00);
4203 SiS_SetReg(SISSR, 0x14, 0xBF);
4205 for(i = 0; i < 2; i++) {
4207 for(j = 0; j < 4; j++) {
4208 writew(temp, FBAddress);
4209 if(readw(FBAddress) == temp)
4211 SiS_SetRegOR(SISSR, 0x3c, 0x01);
4212 reg = SiS_GetReg(SISSR, 0x05);
4213 reg = SiS_GetReg(SISSR, 0x05);
4214 SiS_SetRegAND(SISSR, 0x3c, 0xfe);
4215 reg = SiS_GetReg(SISSR, 0x05);
4216 reg = SiS_GetReg(SISSR, 0x05);
4221 writel(0x01234567L, FBAddress);
4222 writel(0x456789ABL, (FBAddress + 4));
4223 writel(0x89ABCDEFL, (FBAddress + 8));
4224 writel(0xCDEF0123L, (FBAddress + 12));
4226 reg = SiS_GetReg(SISSR, 0x3b);
4228 if(readl((FBAddress + 12)) == 0xCDEF0123L)
4229 return 4; /* Channel A 128bit */
4232 if(readl((FBAddress + 4)) == 0x456789ABL)
4233 return 2; /* Channel B 64bit */
4235 return 1; /* 32bit */
4238 static const unsigned short SiS_DRAMType[17][5] = {
4239 {0x0C,0x0A,0x02,0x40,0x39},
4240 {0x0D,0x0A,0x01,0x40,0x48},
4241 {0x0C,0x09,0x02,0x20,0x35},
4242 {0x0D,0x09,0x01,0x20,0x44},
4243 {0x0C,0x08,0x02,0x10,0x31},
4244 {0x0D,0x08,0x01,0x10,0x40},
4245 {0x0C,0x0A,0x01,0x20,0x34},
4246 {0x0C,0x09,0x01,0x08,0x32},
4247 {0x0B,0x08,0x02,0x08,0x21},
4248 {0x0C,0x08,0x01,0x08,0x30},
4249 {0x0A,0x08,0x02,0x04,0x11},
4250 {0x0B,0x0A,0x01,0x10,0x28},
4251 {0x09,0x08,0x02,0x02,0x01},
4252 {0x0B,0x09,0x01,0x08,0x24},
4253 {0x0B,0x08,0x01,0x04,0x20},
4254 {0x0A,0x08,0x01,0x02,0x10},
4255 {0x09,0x08,0x01,0x01,0x00}
4258 static int sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration,
4259 int buswidth, int PseudoRankCapacity,
4260 int PseudoAdrPinCount, unsigned int mapsize)
4262 void __iomem *FBAddr = ivideo->video_vbase;
4263 unsigned short sr14;
4264 unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
4265 unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
4267 for(k = 0; k < ARRAY_SIZE(SiS_DRAMType); k++) {
4269 RankCapacity = buswidth * SiS_DRAMType[k][3];
4271 if(RankCapacity != PseudoRankCapacity)
4274 if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
4277 BankNumHigh = RankCapacity * 16 * iteration - 1;
4278 if(iteration == 3) { /* Rank No */
4279 BankNumMid = RankCapacity * 16 - 1;
4281 BankNumMid = RankCapacity * 16 * iteration / 2 - 1;
4284 PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
4285 PhysicalAdrHigh = BankNumHigh;
4286 PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
4287 PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
4289 SiS_SetRegAND(SISSR, 0x15, 0xFB); /* Test */
4290 SiS_SetRegOR(SISSR, 0x15, 0x04); /* Test */
4291 sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
4292 if(buswidth == 4) sr14 |= 0x80;
4293 else if(buswidth == 2) sr14 |= 0x40;
4294 SiS_SetReg(SISSR, 0x13, SiS_DRAMType[k][4]);
4295 SiS_SetReg(SISSR, 0x14, sr14);
4300 if((BankNumHigh + PhysicalAdrHigh >= mapsize) ||
4301 (BankNumMid + PhysicalAdrHigh >= mapsize) ||
4302 (BankNumHigh + PhysicalAdrHalfPage >= mapsize) ||
4303 (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
4307 writew(((unsigned short)PhysicalAdrHigh),
4308 (FBAddr + BankNumHigh + PhysicalAdrHigh));
4309 writew(((unsigned short)BankNumMid),
4310 (FBAddr + BankNumMid + PhysicalAdrHigh));
4311 writew(((unsigned short)PhysicalAdrHalfPage),
4312 (FBAddr + BankNumHigh + PhysicalAdrHalfPage));
4313 writew(((unsigned short)PhysicalAdrOtherPage),
4314 (FBAddr + BankNumHigh + PhysicalAdrOtherPage));
4317 if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
4324 static void sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
4326 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4328 int PseudoRankCapacity, PseudoAdrPinCount;
4330 buswidth = sisfb_post_300_buswidth(ivideo);
4332 for(i = 6; i >= 0; i--) {
4333 PseudoRankCapacity = 1 << i;
4334 for(j = 4; j >= 1; j--) {
4335 PseudoAdrPinCount = 15 - j;
4336 if((PseudoRankCapacity * j) <= 64) {
4337 if(sisfb_post_300_rwtest(ivideo,
4349 static void sisfb_post_sis300(struct pci_dev *pdev)
4351 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4352 unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
4353 u8 reg, v1, v2, v3, v4, v5, v6, v7, v8;
4354 u16 index, rindex, memtype = 0;
4355 unsigned int mapsize;
4357 if(!ivideo->SiS_Pr.UseROM)
4360 SiS_SetReg(SISSR, 0x05, 0x86);
4363 if(bios[0x52] & 0x80) {
4364 memtype = bios[0x52];
4366 memtype = SiS_GetReg(SISSR, 0x3a);
4371 v3 = 0x80; v6 = 0x80;
4372 if(ivideo->revision_id <= 0x13) {
4373 v1 = 0x44; v2 = 0x42;
4374 v4 = 0x44; v5 = 0x42;
4376 v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */
4377 v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */
4379 index = memtype * 5;
4380 rindex = index + 0x54;
4381 v1 = bios[rindex++];
4382 v2 = bios[rindex++];
4383 v3 = bios[rindex++];
4384 rindex = index + 0x7c;
4385 v4 = bios[rindex++];
4386 v5 = bios[rindex++];
4387 v6 = bios[rindex++];
4390 SiS_SetReg(SISSR, 0x28, v1);
4391 SiS_SetReg(SISSR, 0x29, v2);
4392 SiS_SetReg(SISSR, 0x2a, v3);
4393 SiS_SetReg(SISSR, 0x2e, v4);
4394 SiS_SetReg(SISSR, 0x2f, v5);
4395 SiS_SetReg(SISSR, 0x30, v6);
4400 SiS_SetReg(SISSR, 0x07, v1); /* DAC speed */
4402 SiS_SetReg(SISSR, 0x11, 0x0f); /* DDC, power save */
4404 v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
4405 v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
4409 v2 = bios[memtype + 8];
4410 v3 = bios[memtype + 16];
4411 v4 = bios[memtype + 24];
4412 v5 = bios[memtype + 32];
4413 v6 = bios[memtype + 40];
4414 v7 = bios[memtype + 48];
4415 v8 = bios[memtype + 56];
4417 if(ivideo->revision_id >= 0x80)
4419 SiS_SetReg(SISSR, 0x15, v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4420 SiS_SetReg(SISSR, 0x16, v2);
4421 SiS_SetReg(SISSR, 0x17, v3);
4422 SiS_SetReg(SISSR, 0x18, v4);
4423 SiS_SetReg(SISSR, 0x19, v5);
4424 SiS_SetReg(SISSR, 0x1a, v6);
4425 SiS_SetReg(SISSR, 0x1b, v7);
4426 SiS_SetReg(SISSR, 0x1c, v8); /* ---- */
4427 SiS_SetRegAND(SISSR, 0x15, 0xfb);
4428 SiS_SetRegOR(SISSR, 0x15, 0x04);
4430 if(bios[0x53] & 0x02) {
4431 SiS_SetRegOR(SISSR, 0x19, 0x20);
4434 v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */
4435 if(ivideo->revision_id >= 0x80)
4437 SiS_SetReg(SISSR, 0x1f, v1);
4438 SiS_SetReg(SISSR, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
4439 v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
4445 SiS_SetReg(SISSR, 0x23, v1);
4446 SiS_SetReg(SISSR, 0x24, v2);
4447 SiS_SetReg(SISSR, 0x25, v3);
4448 SiS_SetReg(SISSR, 0x21, 0x84);
4449 SiS_SetReg(SISSR, 0x22, 0x00);
4450 SiS_SetReg(SISCR, 0x37, 0x00);
4451 SiS_SetRegOR(SISPART1, 0x24, 0x01); /* unlock crt2 */
4452 SiS_SetReg(SISPART1, 0x00, 0x00);
4453 v1 = 0x40; v2 = 0x11;
4458 SiS_SetReg(SISPART1, 0x02, v1);
4460 if(ivideo->revision_id >= 0x80)
4463 reg = SiS_GetReg(SISPART4, 0x00);
4464 if((reg == 1) || (reg == 2)) {
4465 SiS_SetReg(SISCR, 0x37, 0x02);
4466 SiS_SetReg(SISPART2, 0x00, 0x1c);
4467 v4 = 0x00; v5 = 0x00; v6 = 0x10;
4468 if(ivideo->SiS_Pr.UseROM) {
4473 SiS_SetReg(SISPART4, 0x0d, v4);
4474 SiS_SetReg(SISPART4, 0x0e, v5);
4475 SiS_SetReg(SISPART4, 0x10, v6);
4476 SiS_SetReg(SISPART4, 0x0f, 0x3f);
4477 reg = SiS_GetReg(SISPART4, 0x01);
4479 reg = SiS_GetReg(SISPART4, 0x23);
4482 SiS_SetReg(SISPART4, 0x23, reg);
4487 SiS_SetReg(SISSR, 0x32, v2);
4489 SiS_SetRegAND(SISPART1, 0x24, 0xfe); /* Lock CRT2 */
4491 reg = SiS_GetReg(SISSR, 0x16);
4493 SiS_SetReg(SISCR, 0x35, reg);
4494 SiS_SetReg(SISCR, 0x83, 0x00);
4495 #if !defined(__i386__) && !defined(__x86_64__)
4496 if(sisfb_videoram) {
4497 SiS_SetReg(SISSR, 0x13, 0x28); /* ? */
4498 reg = ((sisfb_videoram >> 10) - 1) | 0x40;
4499 SiS_SetReg(SISSR, 0x14, reg);
4502 /* Need to map max FB size for finding out about RAM size */
4503 mapsize = ivideo->video_size;
4504 sisfb_post_map_vram(ivideo, &mapsize, 4);
4506 if(ivideo->video_vbase) {
4507 sisfb_post_300_ramsize(pdev, mapsize);
4508 iounmap(ivideo->video_vbase);
4511 "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4512 SiS_SetReg(SISSR, 0x13, 0x28); /* ? */
4513 SiS_SetReg(SISSR, 0x14, 0x47); /* 8MB, 64bit default */
4515 #if !defined(__i386__) && !defined(__x86_64__)
4522 reg = SiS_GetReg(SISSR, 0x3a);
4523 if((reg & 0x30) == 0x30) {
4524 v1 = 0x04; /* PCI */
4527 v1 = 0x14; /* AGP */
4531 SiS_SetReg(SISSR, 0x21, v1);
4532 SiS_SetReg(SISSR, 0x22, v2);
4535 sisfb_sense_crt1(ivideo);
4537 /* Set default mode, don't clear screen */
4538 ivideo->SiS_Pr.SiS_UseOEM = false;
4539 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
4540 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
4541 ivideo->curFSTN = ivideo->curDSTN = 0;
4542 ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
4543 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
4545 SiS_SetReg(SISSR, 0x05, 0x86);
4548 SiS_SetRegOR(SISSR, 0x01, 0x20);
4550 /* Save mode number in CR34 */
4551 SiS_SetReg(SISCR, 0x34, 0x2e);
4553 /* Let everyone know what the current mode is */
4554 ivideo->modeprechange = 0x2e;
4558 #ifdef CONFIG_FB_SIS_315
4560 static void sisfb_post_sis315330(struct pci_dev *pdev)
4566 static inline int sisfb_xgi_is21(struct sis_video_info *ivideo)
4568 return ivideo->chip_real_id == XGI_21;
4571 static void sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
4576 for(i = 0; i <= (delay * 10 * 36); i++) {
4577 reg = SiS_GetReg(SISSR, 0x05);
4582 static int sisfb_find_host_bridge(struct sis_video_info *ivideo,
4583 struct pci_dev *mypdev,
4584 unsigned short pcivendor)
4586 struct pci_dev *pdev = NULL;
4587 unsigned short temp;
4590 while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) {
4591 temp = pdev->vendor;
4592 if(temp == pcivendor) {
4602 static int sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
4603 unsigned int enda, unsigned int mapsize)
4608 writel(0, ivideo->video_vbase);
4610 for(i = starta; i <= enda; i++) {
4613 writel(pos, ivideo->video_vbase + pos);
4616 sisfb_post_xgi_delay(ivideo, 150);
4618 if(readl(ivideo->video_vbase) != 0)
4621 for(i = starta; i <= enda; i++) {
4624 if(readl(ivideo->video_vbase + pos) != pos)
4633 static int sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
4635 unsigned int buswidth, ranksize, channelab, mapsize;
4636 int i, j, k, l, status;
4638 static const u8 dramsr13[12 * 5] = {
4639 0x02, 0x0e, 0x0b, 0x80, 0x5d,
4640 0x02, 0x0e, 0x0a, 0x40, 0x59,
4641 0x02, 0x0d, 0x0b, 0x40, 0x4d,
4642 0x02, 0x0e, 0x09, 0x20, 0x55,
4643 0x02, 0x0d, 0x0a, 0x20, 0x49,
4644 0x02, 0x0c, 0x0b, 0x20, 0x3d,
4645 0x02, 0x0e, 0x08, 0x10, 0x51,
4646 0x02, 0x0d, 0x09, 0x10, 0x45,
4647 0x02, 0x0c, 0x0a, 0x10, 0x39,
4648 0x02, 0x0d, 0x08, 0x08, 0x41,
4649 0x02, 0x0c, 0x09, 0x08, 0x35,
4650 0x02, 0x0c, 0x08, 0x04, 0x31
4652 static const u8 dramsr13_4[4 * 5] = {
4653 0x02, 0x0d, 0x09, 0x40, 0x45,
4654 0x02, 0x0c, 0x09, 0x20, 0x35,
4655 0x02, 0x0c, 0x08, 0x10, 0x31,
4656 0x02, 0x0b, 0x08, 0x08, 0x21
4659 /* Enable linear mode, disable 0xa0000 address decoding */
4660 /* We disable a0000 address decoding, because
4661 * - if running on x86, if the card is disabled, it means
4662 * that another card is in the system. We don't want
4663 * to interphere with that primary card's textmode.
4664 * - if running on non-x86, there usually is no VGA window
4667 SiS_SetRegOR(SISSR, 0x20, (0x80 | 0x04));
4669 /* Need to map max FB size for finding out about RAM size */
4670 mapsize = ivideo->video_size;
4671 sisfb_post_map_vram(ivideo, &mapsize, 32);
4673 if(!ivideo->video_vbase) {
4674 printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
4675 SiS_SetReg(SISSR, 0x13, 0x35);
4676 SiS_SetReg(SISSR, 0x14, 0x41);
4681 /* Non-interleaving */
4682 SiS_SetReg(SISSR, 0x15, 0x00);
4684 SiS_SetReg(SISSR, 0x1c, 0x00);
4686 if(ivideo->chip == XGI_20) {
4689 reg = SiS_GetReg(SISCR, 0x97);
4690 if(!(reg & 0x01)) { /* Single 32/16 */
4692 SiS_SetReg(SISSR, 0x13, 0xb1);
4693 SiS_SetReg(SISSR, 0x14, 0x52);
4694 sisfb_post_xgi_delay(ivideo, 1);
4696 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4699 SiS_SetReg(SISSR, 0x13, 0x31);
4700 SiS_SetReg(SISSR, 0x14, 0x42);
4701 sisfb_post_xgi_delay(ivideo, 1);
4702 if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
4706 SiS_SetReg(SISSR, 0x13, 0xb1);
4707 SiS_SetReg(SISSR, 0x14, 0x41);
4708 sisfb_post_xgi_delay(ivideo, 1);
4710 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4713 SiS_SetReg(SISSR, 0x13, 0x31);
4714 } else { /* Dual 16/8 */
4716 SiS_SetReg(SISSR, 0x13, 0xb1);
4717 SiS_SetReg(SISSR, 0x14, 0x41);
4718 sisfb_post_xgi_delay(ivideo, 1);
4720 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4723 SiS_SetReg(SISSR, 0x13, 0x31);
4724 SiS_SetReg(SISSR, 0x14, 0x31);
4725 sisfb_post_xgi_delay(ivideo, 1);
4726 if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
4730 SiS_SetReg(SISSR, 0x13, 0xb1);
4731 SiS_SetReg(SISSR, 0x14, 0x30);
4732 sisfb_post_xgi_delay(ivideo, 1);
4734 if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
4737 SiS_SetReg(SISSR, 0x13, 0x31);
4740 } else { /* XGI_40 */
4742 reg = SiS_GetReg(SISCR, 0x97);
4744 reg = SiS_GetReg(SISSR, 0x39);
4748 if(reg & 0x01) { /* DDRII */
4750 if(ivideo->revision_id == 2) {
4752 SiS_SetReg(SISSR, 0x13, 0xa1);
4753 SiS_SetReg(SISSR, 0x14, 0x44);
4755 sisfb_post_xgi_delay(ivideo, 1);
4756 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4759 SiS_SetReg(SISSR, 0x13, 0x21);
4760 SiS_SetReg(SISSR, 0x14, 0x34);
4761 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4765 SiS_SetReg(SISSR, 0x13, 0xa1);
4766 SiS_SetReg(SISSR, 0x14, 0x40);
4768 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4771 SiS_SetReg(SISSR, 0x13, 0x21);
4772 SiS_SetReg(SISSR, 0x14, 0x30);
4775 SiS_SetReg(SISSR, 0x13, 0xa1);
4776 SiS_SetReg(SISSR, 0x14, 0x4c);
4778 sisfb_post_xgi_delay(ivideo, 1);
4779 if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
4783 SiS_SetReg(SISSR, 0x14, 0x48);
4784 sisfb_post_xgi_delay(ivideo, 1);
4786 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4789 SiS_SetReg(SISSR, 0x13, 0x21);
4790 SiS_SetReg(SISSR, 0x14, 0x3c);
4793 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
4797 SiS_SetReg(SISSR, 0x14, 0x38);
4801 sisfb_post_xgi_delay(ivideo, 1);
4806 if(ivideo->revision_id == 2) {
4808 SiS_SetReg(SISSR, 0x13, 0xa1);
4809 SiS_SetReg(SISSR, 0x14, 0x52);
4810 sisfb_post_xgi_delay(ivideo, 1);
4812 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4815 SiS_SetReg(SISSR, 0x13, 0x21);
4816 SiS_SetReg(SISSR, 0x14, 0x42);
4819 SiS_SetReg(SISSR, 0x13, 0xa1);
4820 SiS_SetReg(SISSR, 0x14, 0x5a);
4821 sisfb_post_xgi_delay(ivideo, 1);
4823 if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
4826 SiS_SetReg(SISSR, 0x13, 0x21);
4827 SiS_SetReg(SISSR, 0x14, 0x4a);
4829 sisfb_post_xgi_delay(ivideo, 1);
4835 SiS_SetRegANDOR(SISSR, 0x14, 0xf0, sr14);
4836 sisfb_post_xgi_delay(ivideo, 1);
4838 j = (ivideo->chip == XGI_20) ? 5 : 9;
4839 k = (ivideo->chip == XGI_20) ? 12 : 4;
4842 for(i = 0; i < k; i++) {
4844 reg = (ivideo->chip == XGI_20) ?
4845 dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
4846 SiS_SetRegANDOR(SISSR, 0x13, 0x80, reg);
4847 sisfb_post_xgi_delay(ivideo, 50);
4849 ranksize = (ivideo->chip == XGI_20) ?
4850 dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
4852 reg = SiS_GetReg(SISSR, 0x13);
4853 if(reg & 0x80) ranksize <<= 1;
4855 if(ivideo->chip == XGI_20) {
4856 if(buswidth == 16) ranksize <<= 1;
4857 else if(buswidth == 32) ranksize <<= 2;
4859 if(buswidth == 64) ranksize <<= 1;
4865 if((ranksize * l) <= 256) {
4866 while((ranksize >>= 1)) reg += 0x10;
4871 SiS_SetRegANDOR(SISSR, 0x14, 0x0f, (reg & 0xf0));
4872 sisfb_post_xgi_delay(ivideo, 1);
4874 if (sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize)) {
4880 iounmap(ivideo->video_vbase);
4885 static void sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
4889 static const u8 cs90[8 * 3] = {
4899 static const u8 csb8[8 * 3] = {
4913 v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2];
4914 if(ivideo->haveXGIROM) {
4915 v1 = ivideo->bios_abase[0x90 + index];
4916 v2 = ivideo->bios_abase[0x90 + index + 1];
4917 v3 = ivideo->bios_abase[0x90 + index + 2];
4919 SiS_SetReg(SISSR, 0x28, v1);
4920 SiS_SetReg(SISSR, 0x29, v2);
4921 SiS_SetReg(SISSR, 0x2a, v3);
4922 sisfb_post_xgi_delay(ivideo, 0x43);
4923 sisfb_post_xgi_delay(ivideo, 0x43);
4924 sisfb_post_xgi_delay(ivideo, 0x43);
4926 v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2];
4927 if(ivideo->haveXGIROM) {
4928 v1 = ivideo->bios_abase[0xb8 + index];
4929 v2 = ivideo->bios_abase[0xb8 + index + 1];
4930 v3 = ivideo->bios_abase[0xb8 + index + 2];
4932 SiS_SetReg(SISSR, 0x2e, v1);
4933 SiS_SetReg(SISSR, 0x2f, v2);
4934 SiS_SetReg(SISSR, 0x30, v3);
4935 sisfb_post_xgi_delay(ivideo, 0x43);
4936 sisfb_post_xgi_delay(ivideo, 0x43);
4937 sisfb_post_xgi_delay(ivideo, 0x43);
4940 static void sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info *ivideo,
4943 unsigned char *bios = ivideo->bios_abase;
4946 SiS_SetReg(SISSR, 0x28, 0x64);
4947 SiS_SetReg(SISSR, 0x29, 0x63);
4948 sisfb_post_xgi_delay(ivideo, 15);
4949 SiS_SetReg(SISSR, 0x18, 0x00);
4950 SiS_SetReg(SISSR, 0x19, 0x20);
4951 SiS_SetReg(SISSR, 0x16, 0x00);
4952 SiS_SetReg(SISSR, 0x16, 0x80);
4953 SiS_SetReg(SISSR, 0x18, 0xc5);
4954 SiS_SetReg(SISSR, 0x19, 0x23);
4955 SiS_SetReg(SISSR, 0x16, 0x00);
4956 SiS_SetReg(SISSR, 0x16, 0x80);
4957 sisfb_post_xgi_delay(ivideo, 1);
4958 SiS_SetReg(SISCR, 0x97, 0x11);
4959 sisfb_post_xgi_setclocks(ivideo, regb);
4960 sisfb_post_xgi_delay(ivideo, 0x46);
4961 SiS_SetReg(SISSR, 0x18, 0xc5);
4962 SiS_SetReg(SISSR, 0x19, 0x23);
4963 SiS_SetReg(SISSR, 0x16, 0x00);
4964 SiS_SetReg(SISSR, 0x16, 0x80);
4965 sisfb_post_xgi_delay(ivideo, 1);
4966 SiS_SetReg(SISSR, 0x1b, 0x04);
4967 sisfb_post_xgi_delay(ivideo, 1);
4968 SiS_SetReg(SISSR, 0x1b, 0x00);
4969 sisfb_post_xgi_delay(ivideo, 1);
4971 if (ivideo->haveXGIROM) {
4974 SiS_SetReg(SISSR, 0x18, v1);
4975 SiS_SetReg(SISSR, 0x19, 0x06);
4976 SiS_SetReg(SISSR, 0x16, 0x04);
4977 SiS_SetReg(SISSR, 0x16, 0x84);
4978 sisfb_post_xgi_delay(ivideo, 1);
4981 static void sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info *ivideo)
4983 sisfb_post_xgi_setclocks(ivideo, 1);
4985 SiS_SetReg(SISCR, 0x97, 0x11);
4986 sisfb_post_xgi_delay(ivideo, 0x46);
4988 SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS2 */
4989 SiS_SetReg(SISSR, 0x19, 0x80);
4990 SiS_SetReg(SISSR, 0x16, 0x05);
4991 SiS_SetReg(SISSR, 0x16, 0x85);
4993 SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS3 */
4994 SiS_SetReg(SISSR, 0x19, 0xc0);
4995 SiS_SetReg(SISSR, 0x16, 0x05);
4996 SiS_SetReg(SISSR, 0x16, 0x85);
4998 SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS1 */
4999 SiS_SetReg(SISSR, 0x19, 0x40);
5000 SiS_SetReg(SISSR, 0x16, 0x05);
5001 SiS_SetReg(SISSR, 0x16, 0x85);
5003 SiS_SetReg(SISSR, 0x18, 0x42); /* MRS1 */
5004 SiS_SetReg(SISSR, 0x19, 0x02);
5005 SiS_SetReg(SISSR, 0x16, 0x05);
5006 SiS_SetReg(SISSR, 0x16, 0x85);
5007 sisfb_post_xgi_delay(ivideo, 1);
5009 SiS_SetReg(SISSR, 0x1b, 0x04);
5010 sisfb_post_xgi_delay(ivideo, 1);
5012 SiS_SetReg(SISSR, 0x1b, 0x00);
5013 sisfb_post_xgi_delay(ivideo, 1);
5015 SiS_SetReg(SISSR, 0x18, 0x42); /* MRS1 */
5016 SiS_SetReg(SISSR, 0x19, 0x00);
5017 SiS_SetReg(SISSR, 0x16, 0x05);
5018 SiS_SetReg(SISSR, 0x16, 0x85);
5019 sisfb_post_xgi_delay(ivideo, 1);
5022 static void sisfb_post_xgi_ddr2(struct sis_video_info *ivideo, u8 regb)
5024 unsigned char *bios = ivideo->bios_abase;
5025 static const u8 cs158[8] = {
5026 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5028 static const u8 cs160[8] = {
5029 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5031 static const u8 cs168[8] = {
5032 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5039 SiS_SetReg(SISCR, 0xb0, 0x80); /* DDR2 dual frequency mode */
5040 SiS_SetReg(SISCR, 0x82, 0x77);
5041 SiS_SetReg(SISCR, 0x86, 0x00);
5042 reg = SiS_GetReg(SISCR, 0x86);
5043 SiS_SetReg(SISCR, 0x86, 0x88);
5044 reg = SiS_GetReg(SISCR, 0x86);
5045 v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
5046 if (ivideo->haveXGIROM) {
5047 v1 = bios[regb + 0x168];
5048 v2 = bios[regb + 0x160];
5049 v3 = bios[regb + 0x158];
5051 SiS_SetReg(SISCR, 0x86, v1);
5052 SiS_SetReg(SISCR, 0x82, 0x77);
5053 SiS_SetReg(SISCR, 0x85, 0x00);
5054 reg = SiS_GetReg(SISCR, 0x85);
5055 SiS_SetReg(SISCR, 0x85, 0x88);
5056 reg = SiS_GetReg(SISCR, 0x85);
5057 SiS_SetReg(SISCR, 0x85, v2);
5058 SiS_SetReg(SISCR, 0x82, v3);
5059 SiS_SetReg(SISCR, 0x98, 0x01);
5060 SiS_SetReg(SISCR, 0x9a, 0x02);
5061 if (sisfb_xgi_is21(ivideo))
5062 sisfb_post_xgi_ddr2_mrs_xg21(ivideo);
5064 sisfb_post_xgi_ddr2_mrs_default(ivideo, regb);
5067 static u8 sisfb_post_xgi_ramtype(struct sis_video_info *ivideo)
5069 unsigned char *bios = ivideo->bios_abase;
5074 ramtype = 0x00; v1 = 0x10;
5075 if (ivideo->haveXGIROM) {
5076 ramtype = bios[0x62];
5079 if (!(ramtype & 0x80)) {
5080 if (sisfb_xgi_is21(ivideo)) {
5081 SiS_SetRegAND(SISCR, 0xb4, 0xfd); /* GPIO control */
5082 SiS_SetRegOR(SISCR, 0x4a, 0x80); /* GPIOH EN */
5083 reg = SiS_GetReg(SISCR, 0x48);
5084 SiS_SetRegOR(SISCR, 0xb4, 0x02);
5085 ramtype = reg & 0x01; /* GPIOH */
5086 } else if (ivideo->chip == XGI_20) {
5087 SiS_SetReg(SISCR, 0x97, v1);
5088 reg = SiS_GetReg(SISCR, 0x97);
5090 ramtype = (reg & 0x01) << 1;
5093 reg = SiS_GetReg(SISSR, 0x39);
5094 ramtype = reg & 0x02;
5096 reg = SiS_GetReg(SISSR, 0x3a);
5097 ramtype = (reg >> 1) & 0x01;
5106 static int sisfb_post_xgi(struct pci_dev *pdev)
5108 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
5109 unsigned char *bios = ivideo->bios_abase;
5110 struct pci_dev *mypdev = NULL;
5111 const u8 *ptr, *ptr2;
5112 u8 v1, v2, v3, v4, v5, reg, ramtype;
5113 u32 rega, regb, regd;
5115 static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 };
5116 static const u8 cs76[2] = { 0xa3, 0xfb };
5117 static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 };
5118 static const u8 cs158[8] = {
5119 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5121 static const u8 cs160[8] = {
5122 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5124 static const u8 cs168[8] = {
5125 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5127 static const u8 cs128[3 * 8] = {
5128 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
5129 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5130 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
5132 static const u8 cs148[2 * 8] = {
5133 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
5134 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5136 static const u8 cs31a[8 * 4] = {
5137 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
5138 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
5139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5142 static const u8 cs33a[8 * 4] = {
5143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5148 static const u8 cs45a[8 * 2] = {
5149 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
5150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5152 static const u8 cs170[7 * 8] = {
5153 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5154 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5155 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
5156 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5157 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5158 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5159 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5161 static const u8 cs1a8[3 * 8] = {
5162 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5163 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5164 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5166 static const u8 cs100[2 * 8] = {
5167 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5168 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5172 reg = SiS_GetRegByte(SISVGAENABLE) | 0x01;
5173 SiS_SetRegByte(SISVGAENABLE, reg);
5176 reg = SiS_GetRegByte(SISMISCR) | 0x01;
5177 SiS_SetRegByte(SISMISCW, reg);
5180 SiS_SetReg(SISSR, 0x05, 0x86);
5181 reg = SiS_GetReg(SISSR, 0x05);
5185 /* Clear some regs */
5186 for(i = 0; i < 0x22; i++) {
5187 if(0x06 + i == 0x20) continue;
5188 SiS_SetReg(SISSR, 0x06 + i, 0x00);
5190 for(i = 0; i < 0x0b; i++) {
5191 SiS_SetReg(SISSR, 0x31 + i, 0x00);
5193 for(i = 0; i < 0x10; i++) {
5194 SiS_SetReg(SISCR, 0x30 + i, 0x00);
5198 if(ivideo->haveXGIROM) {
5199 ptr = (const u8 *)&bios[0x78];
5201 for(i = 0; i < 3; i++) {
5202 SiS_SetReg(SISSR, 0x23 + i, ptr[i]);
5206 if(ivideo->haveXGIROM) {
5207 ptr = (const u8 *)&bios[0x76];
5209 for(i = 0; i < 2; i++) {
5210 SiS_SetReg(SISSR, 0x21 + i, ptr[i]);
5213 v1 = 0x18; v2 = 0x00;
5214 if(ivideo->haveXGIROM) {
5218 SiS_SetReg(SISSR, 0x07, v1);
5219 SiS_SetReg(SISSR, 0x11, 0x0f);
5220 SiS_SetReg(SISSR, 0x1f, v2);
5221 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5222 SiS_SetReg(SISSR, 0x20, 0x80 | 0x20 | 0x04);
5223 SiS_SetReg(SISSR, 0x27, 0x74);
5226 if(ivideo->haveXGIROM) {
5227 ptr = (const u8 *)&bios[0x7b];
5229 for(i = 0; i < 3; i++) {
5230 SiS_SetReg(SISSR, 0x31 + i, ptr[i]);
5233 if(ivideo->chip == XGI_40) {
5234 if(ivideo->revision_id == 2) {
5235 SiS_SetRegANDOR(SISSR, 0x3b, 0x3f, 0xc0);
5237 SiS_SetReg(SISCR, 0x7d, 0xfe);
5238 SiS_SetReg(SISCR, 0x7e, 0x0f);
5240 if(ivideo->revision_id == 0) { /* 40 *and* 20? */
5241 SiS_SetRegAND(SISCR, 0x58, 0xd7);
5242 reg = SiS_GetReg(SISCR, 0xcb);
5244 SiS_SetRegANDOR(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5248 reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
5249 SiS_SetRegANDOR(SISCR, 0x38, 0x1f, reg);
5251 if(ivideo->chip == XGI_20) {
5252 SiS_SetReg(SISSR, 0x36, 0x70);
5254 SiS_SetReg(SISVID, 0x00, 0x86);
5255 SiS_SetReg(SISVID, 0x32, 0x00);
5256 SiS_SetReg(SISVID, 0x30, 0x00);
5257 SiS_SetReg(SISVID, 0x32, 0x01);
5258 SiS_SetReg(SISVID, 0x30, 0x00);
5259 SiS_SetRegAND(SISVID, 0x2f, 0xdf);
5260 SiS_SetRegAND(SISCAP, 0x00, 0x3f);
5262 SiS_SetReg(SISPART1, 0x2f, 0x01);
5263 SiS_SetReg(SISPART1, 0x00, 0x00);
5264 SiS_SetReg(SISPART1, 0x02, bios[0x7e]);
5265 SiS_SetReg(SISPART1, 0x2e, 0x08);
5266 SiS_SetRegAND(SISPART1, 0x35, 0x7f);
5267 SiS_SetRegAND(SISPART1, 0x50, 0xfe);
5269 reg = SiS_GetReg(SISPART4, 0x00);
5270 if(reg == 1 || reg == 2) {
5271 SiS_SetReg(SISPART2, 0x00, 0x1c);
5272 SiS_SetReg(SISPART4, 0x0d, bios[0x7f]);
5273 SiS_SetReg(SISPART4, 0x0e, bios[0x80]);
5274 SiS_SetReg(SISPART4, 0x10, bios[0x81]);
5275 SiS_SetRegAND(SISPART4, 0x0f, 0x3f);
5277 reg = SiS_GetReg(SISPART4, 0x01);
5278 if((reg & 0xf0) >= 0xb0) {
5279 reg = SiS_GetReg(SISPART4, 0x23);
5280 if(reg & 0x20) reg |= 0x40;
5281 SiS_SetReg(SISPART4, 0x23, reg);
5282 reg = (reg & 0x20) ? 0x02 : 0x00;
5283 SiS_SetRegANDOR(SISPART1, 0x1e, 0xfd, reg);
5289 reg = SiS_GetReg(SISSR, 0x3b);
5291 reg = SiS_GetReg(SISSR, 0x3a);
5292 v2 = (reg & 0x30) >> 3;
5293 if(!(v2 & 0x04)) v2 ^= 0x02;
5294 reg = SiS_GetReg(SISSR, 0x39);
5295 if(reg & 0x80) v2 |= 0x80;
5298 if((mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
5299 pci_dev_put(mypdev);
5300 if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
5305 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0735, NULL);
5307 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0645, NULL);
5309 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0650, NULL);
5311 pci_read_config_dword(mypdev, 0x94, ®d);
5313 pci_write_config_dword(mypdev, 0x94, regd);
5315 pci_dev_put(mypdev);
5316 } else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) {
5318 } else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) ||
5319 sisfb_find_host_bridge(ivideo, pdev, 0x1022) ||
5320 sisfb_find_host_bridge(ivideo, pdev, 0x700e) ||
5321 sisfb_find_host_bridge(ivideo, pdev, 0x10de)) {
5322 if((v2 & 0x06) == 4)
5327 SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, v2);
5329 SiS_SetReg(SISSR, 0x22, v1);
5331 if(ivideo->revision_id == 2) {
5332 v1 = SiS_GetReg(SISSR, 0x3b);
5333 v2 = SiS_GetReg(SISSR, 0x3a);
5334 regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
5335 if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
5336 SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
5338 if((mypdev = pci_get_device(0x10de, 0x01e0, NULL))) {
5339 /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5343 SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
5344 pci_dev_put(mypdev);
5349 reg = SiS_GetReg(SISSR, 0x3b);
5350 v2 = SiS_GetReg(SISCR, 0x5f);
5351 if((!(reg & 0x02)) && (v2 & 0x0e))
5353 SiS_SetReg(SISSR, 0x27, v1);
5355 if(bios[0x64] & 0x01) {
5356 SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, bios[0x64]);
5360 pci_read_config_dword(pdev, 0x50, ®d);
5361 regd = (regd >> 20) & 0x0f;
5364 SiS_SetRegOR(SISCR, 0x5f, 0x08);
5366 SiS_SetReg(SISCR, 0x48, v1);
5368 SiS_SetRegANDOR(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
5369 SiS_SetRegANDOR(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
5370 SiS_SetRegANDOR(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
5371 SiS_SetRegANDOR(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
5372 SiS_SetRegANDOR(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
5373 SiS_SetReg(SISCR, 0x70, bios[0x4fc]);
5374 SiS_SetRegANDOR(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
5375 SiS_SetReg(SISCR, 0x74, 0xd0);
5376 SiS_SetRegANDOR(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
5377 SiS_SetRegANDOR(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
5378 SiS_SetRegANDOR(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
5380 if((mypdev = pci_get_device(0x8086, 0x2530, NULL))) {
5382 pci_dev_put(mypdev);
5384 SiS_SetReg(SISCR, 0x77, v1);
5389 * 0 == DDR1, 1 == DDR2, 2..7 == reserved?
5391 * The code seems to written so that regb should equal ramtype,
5392 * however, so far it has been hardcoded to 0. Enable other values only
5393 * on XGI Z9, as it passes the POST, and add a warning for others.
5395 ramtype = sisfb_post_xgi_ramtype(ivideo);
5396 if (!sisfb_xgi_is21(ivideo) && ramtype) {
5397 dev_warn(&pdev->dev,
5398 "RAM type something else than expected: %d\n",
5406 if(ivideo->haveXGIROM) {
5407 v1 = bios[0x140 + regb];
5409 SiS_SetReg(SISCR, 0x6d, v1);
5412 if(ivideo->haveXGIROM) {
5413 ptr = (const u8 *)&bios[0x128];
5415 for(i = 0, j = 0; i < 3; i++, j += 8) {
5416 SiS_SetReg(SISCR, 0x68 + i, ptr[j + regb]);
5421 if(ivideo->haveXGIROM) {
5422 index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6;
5423 ptr = (const u8 *)&bios[index];
5424 ptr2 = (const u8 *)&bios[index + 0x20];
5426 for(i = 0; i < 2; i++) {
5428 regd = le32_to_cpu(((u32 *)ptr)[regb]);
5431 regd = le32_to_cpu(((u32 *)ptr2)[regb]);
5435 for(j = 0; j < 16; j++) {
5437 if(regd & 0x01) reg |= 0x04;
5438 if(regd & 0x02) reg |= 0x08;
5440 SiS_SetReg(SISCR, rega, reg);
5441 reg = SiS_GetReg(SISCR, rega);
5442 reg = SiS_GetReg(SISCR, rega);
5447 SiS_SetRegAND(SISCR, 0x6e, 0xfc);
5450 if(ivideo->haveXGIROM) {
5451 index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6;
5452 ptr = (const u8 *)&bios[index];
5454 for(i = 0; i < 4; i++) {
5455 SiS_SetRegANDOR(SISCR, 0x6e, 0xfc, i);
5457 for(j = 0; j < 2; j++) {
5460 regd = le32_to_cpu(((u32 *)ptr)[regb * 8]);
5464 for(k = 0; k < 16; k++) {
5466 if(regd & 0x01) reg |= 0x01;
5467 if(regd & 0x02) reg |= 0x02;
5469 SiS_SetReg(SISCR, 0x6f, reg);
5470 reg = SiS_GetReg(SISCR, 0x6f);
5471 reg = SiS_GetReg(SISCR, 0x6f);
5478 if(ivideo->haveXGIROM) {
5479 ptr = (const u8 *)&bios[0x148];
5481 for(i = 0, j = 0; i < 2; i++, j += 8) {
5482 SiS_SetReg(SISCR, 0x80 + i, ptr[j + regb]);
5485 SiS_SetRegAND(SISCR, 0x89, 0x8f);
5488 if(ivideo->haveXGIROM) {
5489 index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6;
5490 ptr = (const u8 *)&bios[index];
5492 regd = le16_to_cpu(((const u16 *)ptr)[regb]);
5494 for(i = 0; i < 5; i++) {
5496 if(regd & 0x01) reg |= 0x01;
5497 if(regd & 0x02) reg |= 0x02;
5499 SiS_SetReg(SISCR, 0x89, reg);
5500 reg = SiS_GetReg(SISCR, 0x89);
5501 reg = SiS_GetReg(SISCR, 0x89);
5505 v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13;
5506 if(ivideo->haveXGIROM) {
5507 v1 = bios[0x118 + regb];
5508 v2 = bios[0xf8 + regb];
5509 v3 = bios[0x120 + regb];
5512 SiS_SetReg(SISCR, 0x45, v1 & 0x0f);
5513 SiS_SetReg(SISCR, 0x99, (v1 >> 4) & 0x07);
5514 SiS_SetRegOR(SISCR, 0x40, v1 & 0x80);
5515 SiS_SetReg(SISCR, 0x41, v2);
5518 if(ivideo->haveXGIROM) {
5519 ptr = (const u8 *)&bios[0x170];
5521 for(i = 0, j = 0; i < 7; i++, j += 8) {
5522 SiS_SetReg(SISCR, 0x90 + i, ptr[j + regb]);
5525 SiS_SetReg(SISCR, 0x59, v3);
5528 if(ivideo->haveXGIROM) {
5529 ptr = (const u8 *)&bios[0x1a8];
5531 for(i = 0, j = 0; i < 3; i++, j += 8) {
5532 SiS_SetReg(SISCR, 0xc3 + i, ptr[j + regb]);
5536 if(ivideo->haveXGIROM) {
5537 ptr = (const u8 *)&bios[0x100];
5539 for(i = 0, j = 0; i < 2; i++, j += 8) {
5540 SiS_SetReg(SISCR, 0x8a + i, ptr[j + regb]);
5543 SiS_SetReg(SISCR, 0xcf, v4);
5545 SiS_SetReg(SISCR, 0x83, 0x09);
5546 SiS_SetReg(SISCR, 0x87, 0x00);
5548 if(ivideo->chip == XGI_40) {
5549 if( (ivideo->revision_id == 1) ||
5550 (ivideo->revision_id == 2) ) {
5551 SiS_SetReg(SISCR, 0x8c, 0x87);
5556 SiS_SetReg(SISSR, 0x17, 0x80); /* DDR2 */
5558 SiS_SetReg(SISSR, 0x17, 0x00); /* DDR1 */
5559 SiS_SetReg(SISSR, 0x1a, 0x87);
5561 if(ivideo->chip == XGI_20) {
5562 SiS_SetReg(SISSR, 0x15, 0x00);
5563 SiS_SetReg(SISSR, 0x1c, 0x00);
5568 sisfb_post_xgi_setclocks(ivideo, regb);
5569 if((ivideo->chip == XGI_20) ||
5570 (ivideo->revision_id == 1) ||
5571 (ivideo->revision_id == 2)) {
5572 v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb];
5573 if(ivideo->haveXGIROM) {
5574 v1 = bios[regb + 0x158];
5575 v2 = bios[regb + 0x160];
5576 v3 = bios[regb + 0x168];
5578 SiS_SetReg(SISCR, 0x82, v1);
5579 SiS_SetReg(SISCR, 0x85, v2);
5580 SiS_SetReg(SISCR, 0x86, v3);
5582 SiS_SetReg(SISCR, 0x82, 0x88);
5583 SiS_SetReg(SISCR, 0x86, 0x00);
5584 reg = SiS_GetReg(SISCR, 0x86);
5585 SiS_SetReg(SISCR, 0x86, 0x88);
5586 reg = SiS_GetReg(SISCR, 0x86);
5587 SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
5588 SiS_SetReg(SISCR, 0x82, 0x77);
5589 SiS_SetReg(SISCR, 0x85, 0x00);
5590 reg = SiS_GetReg(SISCR, 0x85);
5591 SiS_SetReg(SISCR, 0x85, 0x88);
5592 reg = SiS_GetReg(SISCR, 0x85);
5593 SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
5594 SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
5596 if(ivideo->chip == XGI_40) {
5597 SiS_SetReg(SISCR, 0x97, 0x00);
5599 SiS_SetReg(SISCR, 0x98, 0x01);
5600 SiS_SetReg(SISCR, 0x9a, 0x02);
5602 SiS_SetReg(SISSR, 0x18, 0x01);
5603 if((ivideo->chip == XGI_20) ||
5604 (ivideo->revision_id == 2)) {
5605 SiS_SetReg(SISSR, 0x19, 0x40);
5607 SiS_SetReg(SISSR, 0x19, 0x20);
5609 SiS_SetReg(SISSR, 0x16, 0x00);
5610 SiS_SetReg(SISSR, 0x16, 0x80);
5611 if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
5612 sisfb_post_xgi_delay(ivideo, 0x43);
5613 sisfb_post_xgi_delay(ivideo, 0x43);
5614 sisfb_post_xgi_delay(ivideo, 0x43);
5615 SiS_SetReg(SISSR, 0x18, 0x00);
5616 if((ivideo->chip == XGI_20) ||
5617 (ivideo->revision_id == 2)) {
5618 SiS_SetReg(SISSR, 0x19, 0x40);
5620 SiS_SetReg(SISSR, 0x19, 0x20);
5622 } else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
5623 /* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
5625 SiS_SetReg(SISSR, 0x16, 0x00);
5626 SiS_SetReg(SISSR, 0x16, 0x80);
5627 sisfb_post_xgi_delay(ivideo, 4);
5628 v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
5629 if(ivideo->haveXGIROM) {
5631 index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e;
5633 v3 = bios[index + 1];
5634 v4 = bios[index + 2];
5635 v5 = bios[index + 3];
5637 SiS_SetReg(SISSR, 0x18, v1);
5638 SiS_SetReg(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
5639 SiS_SetReg(SISSR, 0x16, v2);
5640 SiS_SetReg(SISSR, 0x16, v3);
5641 sisfb_post_xgi_delay(ivideo, 0x43);
5642 SiS_SetReg(SISSR, 0x1b, 0x03);
5643 sisfb_post_xgi_delay(ivideo, 0x22);
5644 SiS_SetReg(SISSR, 0x18, v1);
5645 SiS_SetReg(SISSR, 0x19, 0x00);
5646 SiS_SetReg(SISSR, 0x16, v4);
5647 SiS_SetReg(SISSR, 0x16, v5);
5648 SiS_SetReg(SISSR, 0x1b, 0x00);
5651 sisfb_post_xgi_ddr2(ivideo, regb);
5654 sisfb_post_xgi_setclocks(ivideo, regb);
5655 if((ivideo->chip == XGI_40) &&
5656 ((ivideo->revision_id == 1) ||
5657 (ivideo->revision_id == 2))) {
5658 SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
5659 SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
5660 SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
5662 SiS_SetReg(SISCR, 0x82, 0x88);
5663 SiS_SetReg(SISCR, 0x86, 0x00);
5664 reg = SiS_GetReg(SISCR, 0x86);
5665 SiS_SetReg(SISCR, 0x86, 0x88);
5666 SiS_SetReg(SISCR, 0x82, 0x77);
5667 SiS_SetReg(SISCR, 0x85, 0x00);
5668 reg = SiS_GetReg(SISCR, 0x85);
5669 SiS_SetReg(SISCR, 0x85, 0x88);
5670 reg = SiS_GetReg(SISCR, 0x85);
5671 v1 = cs160[regb]; v2 = cs158[regb];
5672 if(ivideo->haveXGIROM) {
5673 v1 = bios[regb + 0x160];
5674 v2 = bios[regb + 0x158];
5676 SiS_SetReg(SISCR, 0x85, v1);
5677 SiS_SetReg(SISCR, 0x82, v2);
5679 if(ivideo->chip == XGI_40) {
5680 SiS_SetReg(SISCR, 0x97, 0x11);
5682 if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
5683 SiS_SetReg(SISCR, 0x98, 0x01);
5685 SiS_SetReg(SISCR, 0x98, 0x03);
5687 SiS_SetReg(SISCR, 0x9a, 0x02);
5689 if(ivideo->chip == XGI_40) {
5690 SiS_SetReg(SISSR, 0x18, 0x01);
5692 SiS_SetReg(SISSR, 0x18, 0x00);
5694 SiS_SetReg(SISSR, 0x19, 0x40);
5695 SiS_SetReg(SISSR, 0x16, 0x00);
5696 SiS_SetReg(SISSR, 0x16, 0x80);
5697 if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
5698 sisfb_post_xgi_delay(ivideo, 0x43);
5699 sisfb_post_xgi_delay(ivideo, 0x43);
5700 sisfb_post_xgi_delay(ivideo, 0x43);
5701 SiS_SetReg(SISSR, 0x18, 0x00);
5702 SiS_SetReg(SISSR, 0x19, 0x40);
5703 SiS_SetReg(SISSR, 0x16, 0x00);
5704 SiS_SetReg(SISSR, 0x16, 0x80);
5706 sisfb_post_xgi_delay(ivideo, 4);
5708 if(ivideo->haveXGIROM) {
5711 SiS_SetReg(SISSR, 0x18, v1);
5712 SiS_SetReg(SISSR, 0x19, 0x01);
5713 if(ivideo->chip == XGI_40) {
5714 SiS_SetReg(SISSR, 0x16, bios[0x53e]);
5715 SiS_SetReg(SISSR, 0x16, bios[0x53f]);
5717 SiS_SetReg(SISSR, 0x16, 0x05);
5718 SiS_SetReg(SISSR, 0x16, 0x85);
5720 sisfb_post_xgi_delay(ivideo, 0x43);
5721 if(ivideo->chip == XGI_40) {
5722 SiS_SetReg(SISSR, 0x1b, 0x01);
5724 SiS_SetReg(SISSR, 0x1b, 0x03);
5726 sisfb_post_xgi_delay(ivideo, 0x22);
5727 SiS_SetReg(SISSR, 0x18, v1);
5728 SiS_SetReg(SISSR, 0x19, 0x00);
5729 if(ivideo->chip == XGI_40) {
5730 SiS_SetReg(SISSR, 0x16, bios[0x540]);
5731 SiS_SetReg(SISSR, 0x16, bios[0x541]);
5733 SiS_SetReg(SISSR, 0x16, 0x05);
5734 SiS_SetReg(SISSR, 0x16, 0x85);
5736 SiS_SetReg(SISSR, 0x1b, 0x00);
5741 if(ivideo->haveXGIROM) {
5742 v1 = bios[0x110 + regb];
5744 SiS_SetReg(SISSR, 0x1b, v1);
5747 v1 = 0x00; v2 = 0x00;
5748 if(ivideo->haveXGIROM) {
5754 if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
5756 SiS_SetReg(SISSR, 0x13, bios[regb + 0xe0]);
5757 SiS_SetReg(SISSR, 0x14, bios[regb + 0xe0 + 8]);
5762 /* Set default mode, don't clear screen */
5763 ivideo->SiS_Pr.SiS_UseOEM = false;
5764 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
5765 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
5766 ivideo->curFSTN = ivideo->curDSTN = 0;
5767 ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
5768 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5770 SiS_SetReg(SISSR, 0x05, 0x86);
5772 /* Disable read-cache */
5773 SiS_SetRegAND(SISSR, 0x21, 0xdf);
5774 err = sisfb_post_xgi_ramsize(ivideo);
5775 /* Enable read-cache */
5776 SiS_SetRegOR(SISSR, 0x21, 0x20);
5780 "%s: RAM size detection failed: %d\n",
5787 printk(KERN_DEBUG "-----------------\n");
5788 for(i = 0; i < 0xff; i++) {
5789 reg = SiS_GetReg(SISCR, i);
5790 printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
5792 for(i = 0; i < 0x40; i++) {
5793 reg = SiS_GetReg(SISSR, i);
5794 printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
5796 printk(KERN_DEBUG "-----------------\n");
5800 if(ivideo->chip == XGI_20) {
5801 SiS_SetRegOR(SISCR, 0x32, 0x20);
5803 reg = SiS_GetReg(SISPART4, 0x00);
5804 if((reg == 1) || (reg == 2)) {
5805 sisfb_sense_crt1(ivideo);
5807 SiS_SetRegOR(SISCR, 0x32, 0x20);
5811 /* Set default mode, don't clear screen */
5812 ivideo->SiS_Pr.SiS_UseOEM = false;
5813 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
5814 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
5815 ivideo->curFSTN = ivideo->curDSTN = 0;
5816 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5818 SiS_SetReg(SISSR, 0x05, 0x86);
5821 SiS_SetRegOR(SISSR, 0x01, 0x20);
5823 /* Save mode number in CR34 */
5824 SiS_SetReg(SISCR, 0x34, 0x2e);
5826 /* Let everyone know what the current mode is */
5827 ivideo->modeprechange = 0x2e;
5829 if(ivideo->chip == XGI_40) {
5830 reg = SiS_GetReg(SISCR, 0xca);
5831 v1 = SiS_GetReg(SISCR, 0xcc);
5832 if((reg & 0x10) && (!(v1 & 0x04))) {
5834 "sisfb: Please connect power to the card.\n");
5843 static int sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
5845 struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data];
5846 struct sis_video_info *ivideo = NULL;
5847 struct fb_info *sis_fb_info = NULL;
5855 sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
5859 ivideo = (struct sis_video_info *)sis_fb_info->par;
5860 ivideo->memyselfandi = sis_fb_info;
5862 ivideo->sisfb_id = SISFB_ID;
5864 if(card_list == NULL) {
5865 ivideo->cardnumber = 0;
5867 struct sis_video_info *countvideo = card_list;
5868 ivideo->cardnumber = 1;
5869 while((countvideo = countvideo->next) != NULL)
5870 ivideo->cardnumber++;
5873 strlcpy(ivideo->myid, chipinfo->chip_name, sizeof(ivideo->myid));
5875 ivideo->warncount = 0;
5876 ivideo->chip_id = pdev->device;
5877 ivideo->chip_vendor = pdev->vendor;
5878 ivideo->revision_id = pdev->revision;
5879 ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
5880 pci_read_config_word(pdev, PCI_COMMAND, ®16);
5881 ivideo->sisvga_enabled = reg16 & 0x01;
5882 ivideo->pcibus = pdev->bus->number;
5883 ivideo->pcislot = PCI_SLOT(pdev->devfn);
5884 ivideo->pcifunc = PCI_FUNC(pdev->devfn);
5885 ivideo->subsysvendor = pdev->subsystem_vendor;
5886 ivideo->subsysdevice = pdev->subsystem_device;
5889 if(sisfb_mode_idx == -1) {
5890 sisfb_get_vga_mode_from_kernel();
5894 ivideo->chip = chipinfo->chip;
5895 ivideo->chip_real_id = chipinfo->chip;
5896 ivideo->sisvga_engine = chipinfo->vgaengine;
5897 ivideo->hwcursor_size = chipinfo->hwcursor_size;
5898 ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
5899 ivideo->mni = chipinfo->mni;
5901 ivideo->detectedpdc = 0xff;
5902 ivideo->detectedpdca = 0xff;
5903 ivideo->detectedlcda = 0xff;
5905 ivideo->sisfb_thismonitor.datavalid = false;
5907 ivideo->current_base = 0;
5909 ivideo->engineok = 0;
5911 ivideo->sisfb_was_boot_device = 0;
5913 if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
5914 if(ivideo->sisvga_enabled)
5915 ivideo->sisfb_was_boot_device = 1;
5917 printk(KERN_DEBUG "sisfb: PCI device is disabled, "
5918 "but marked as boot video device ???\n");
5919 printk(KERN_DEBUG "sisfb: I will not accept this "
5920 "as the primary VGA device\n");
5924 ivideo->sisfb_parm_mem = sisfb_parm_mem;
5925 ivideo->sisfb_accel = sisfb_accel;
5926 ivideo->sisfb_ypan = sisfb_ypan;
5927 ivideo->sisfb_max = sisfb_max;
5928 ivideo->sisfb_userom = sisfb_userom;
5929 ivideo->sisfb_useoem = sisfb_useoem;
5930 ivideo->sisfb_mode_idx = sisfb_mode_idx;
5931 ivideo->sisfb_parm_rate = sisfb_parm_rate;
5932 ivideo->sisfb_crt1off = sisfb_crt1off;
5933 ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
5934 ivideo->sisfb_crt2type = sisfb_crt2type;
5935 ivideo->sisfb_crt2flags = sisfb_crt2flags;
5936 /* pdc(a), scalelcd, special timing, lvdshl handled below */
5937 ivideo->sisfb_dstn = sisfb_dstn;
5938 ivideo->sisfb_fstn = sisfb_fstn;
5939 ivideo->sisfb_tvplug = sisfb_tvplug;
5940 ivideo->sisfb_tvstd = sisfb_tvstd;
5941 ivideo->tvxpos = sisfb_tvxposoffset;
5942 ivideo->tvypos = sisfb_tvyposoffset;
5943 ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
5944 ivideo->refresh_rate = 0;
5945 if(ivideo->sisfb_parm_rate != -1) {
5946 ivideo->refresh_rate = ivideo->sisfb_parm_rate;
5949 ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
5950 ivideo->SiS_Pr.CenterScreen = -1;
5951 ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
5952 ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
5954 ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
5955 ivideo->SiS_Pr.SiS_CHOverScan = -1;
5956 ivideo->SiS_Pr.SiS_ChSW = false;
5957 ivideo->SiS_Pr.SiS_UseLCDA = false;
5958 ivideo->SiS_Pr.HaveEMI = false;
5959 ivideo->SiS_Pr.HaveEMILCD = false;
5960 ivideo->SiS_Pr.OverruleEMI = false;
5961 ivideo->SiS_Pr.SiS_SensibleSR11 = false;
5962 ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
5963 ivideo->SiS_Pr.PDC = -1;
5964 ivideo->SiS_Pr.PDCA = -1;
5965 ivideo->SiS_Pr.DDCPortMixup = false;
5966 #ifdef CONFIG_FB_SIS_315
5967 if(ivideo->chip >= SIS_330) {
5968 ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
5969 if(ivideo->chip >= SIS_661) {
5970 ivideo->SiS_Pr.SiS_SensibleSR11 = true;
5975 memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));
5977 pci_set_drvdata(pdev, ivideo);
5979 /* Patch special cases */
5980 if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) {
5981 switch(ivideo->nbridge->device) {
5982 #ifdef CONFIG_FB_SIS_300
5983 case PCI_DEVICE_ID_SI_730:
5984 ivideo->chip = SIS_730;
5985 strcpy(ivideo->myid, "SiS 730");
5988 #ifdef CONFIG_FB_SIS_315
5989 case PCI_DEVICE_ID_SI_651:
5990 /* ivideo->chip is ok */
5991 strcpy(ivideo->myid, "SiS 651");
5993 case PCI_DEVICE_ID_SI_740:
5994 ivideo->chip = SIS_740;
5995 strcpy(ivideo->myid, "SiS 740");
5997 case PCI_DEVICE_ID_SI_661:
5998 ivideo->chip = SIS_661;
5999 strcpy(ivideo->myid, "SiS 661");
6001 case PCI_DEVICE_ID_SI_741:
6002 ivideo->chip = SIS_741;
6003 strcpy(ivideo->myid, "SiS 741");
6005 case PCI_DEVICE_ID_SI_760:
6006 ivideo->chip = SIS_760;
6007 strcpy(ivideo->myid, "SiS 760");
6009 case PCI_DEVICE_ID_SI_761:
6010 ivideo->chip = SIS_761;
6011 strcpy(ivideo->myid, "SiS 761");
6019 ivideo->SiS_Pr.ChipType = ivideo->chip;
6021 ivideo->SiS_Pr.ivideo = (void *)ivideo;
6023 #ifdef CONFIG_FB_SIS_315
6024 if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
6025 (ivideo->SiS_Pr.ChipType == SIS_315)) {
6026 ivideo->SiS_Pr.ChipType = SIS_315H;
6030 if(!ivideo->sisvga_enabled) {
6031 if(pci_enable_device(pdev)) {
6032 pci_dev_put(ivideo->nbridge);
6033 framebuffer_release(sis_fb_info);
6038 ivideo->video_base = pci_resource_start(pdev, 0);
6039 ivideo->video_size = pci_resource_len(pdev, 0);
6040 ivideo->mmio_base = pci_resource_start(pdev, 1);
6041 ivideo->mmio_size = pci_resource_len(pdev, 1);
6042 ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
6043 ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
6045 SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress);
6047 #ifdef CONFIG_FB_SIS_300
6048 /* Find PCI systems for Chrontel/GPIO communication setup */
6049 if(ivideo->chip == SIS_630) {
6052 if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
6053 mychswtable[i].subsysCard == ivideo->subsysdevice) {
6054 ivideo->SiS_Pr.SiS_ChSW = true;
6055 printk(KERN_DEBUG "sisfb: Identified [%s %s] "
6056 "requiring Chrontel/GPIO setup\n",
6057 mychswtable[i].vendorName,
6058 mychswtable[i].cardName);
6059 ivideo->lpcdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, NULL);
6063 } while(mychswtable[i].subsysVendor != 0);
6067 #ifdef CONFIG_FB_SIS_315
6068 if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
6069 ivideo->lpcdev = pci_get_slot(ivideo->nbridge->bus, (2 << 3));
6073 SiS_SetReg(SISSR, 0x05, 0x86);
6075 if( (!ivideo->sisvga_enabled)
6076 #if !defined(__i386__) && !defined(__x86_64__)
6077 || (sisfb_resetcard)
6080 for(i = 0x30; i <= 0x3f; i++) {
6081 SiS_SetReg(SISCR, i, 0x00);
6085 /* Find out about current video mode */
6086 ivideo->modeprechange = 0x03;
6087 reg = SiS_GetReg(SISCR, 0x34);
6089 ivideo->modeprechange = reg & 0x7f;
6090 } else if(ivideo->sisvga_enabled) {
6091 #if defined(__i386__) || defined(__x86_64__)
6092 unsigned char __iomem *tt = ioremap(0x400, 0x100);
6094 ivideo->modeprechange = readb(tt + 0x49);
6100 /* Search and copy ROM image */
6101 ivideo->bios_abase = NULL;
6102 ivideo->SiS_Pr.VirtualRomBase = NULL;
6103 ivideo->SiS_Pr.UseROM = false;
6104 ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = false;
6105 if(ivideo->sisfb_userom) {
6106 ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
6107 ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
6108 ivideo->SiS_Pr.UseROM = (bool)(ivideo->SiS_Pr.VirtualRomBase);
6109 printk(KERN_INFO "sisfb: Video ROM %sfound\n",
6110 ivideo->SiS_Pr.UseROM ? "" : "not ");
6111 if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
6112 ivideo->SiS_Pr.UseROM = false;
6113 ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = true;
6114 if( (ivideo->revision_id == 2) &&
6115 (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
6116 ivideo->SiS_Pr.DDCPortMixup = true;
6120 printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
6123 /* Find systems for special custom timing */
6124 if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
6125 sisfb_detect_custom_timing(ivideo);
6128 #ifdef CONFIG_FB_SIS_315
6129 if (ivideo->chip == XGI_20) {
6130 /* Check if our Z7 chip is actually Z9 */
6131 SiS_SetRegOR(SISCR, 0x4a, 0x40); /* GPIOG EN */
6132 reg = SiS_GetReg(SISCR, 0x48);
6133 if (reg & 0x02) { /* GPIOG */
6134 ivideo->chip_real_id = XGI_21;
6135 dev_info(&pdev->dev, "Z9 detected\n");
6140 /* POST card in case this has not been done by the BIOS */
6141 if( (!ivideo->sisvga_enabled)
6142 #if !defined(__i386__) && !defined(__x86_64__)
6143 || (sisfb_resetcard)
6146 #ifdef CONFIG_FB_SIS_300
6147 if(ivideo->sisvga_engine == SIS_300_VGA) {
6148 if(ivideo->chip == SIS_300) {
6149 sisfb_post_sis300(pdev);
6150 ivideo->sisfb_can_post = 1;
6155 #ifdef CONFIG_FB_SIS_315
6156 if(ivideo->sisvga_engine == SIS_315_VGA) {
6158 /* if((ivideo->chip == SIS_315H) ||
6159 (ivideo->chip == SIS_315) ||
6160 (ivideo->chip == SIS_315PRO) ||
6161 (ivideo->chip == SIS_330)) {
6162 sisfb_post_sis315330(pdev);
6163 } else */ if(ivideo->chip == XGI_20) {
6164 result = sisfb_post_xgi(pdev);
6165 ivideo->sisfb_can_post = 1;
6166 } else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
6167 result = sisfb_post_xgi(pdev);
6168 ivideo->sisfb_can_post = 1;
6170 printk(KERN_INFO "sisfb: Card is not "
6171 "POSTed and sisfb can't do this either.\n");
6174 printk(KERN_ERR "sisfb: Failed to POST card\n");
6182 ivideo->sisfb_card_posted = 1;
6184 /* Find out about RAM size */
6185 if(sisfb_get_dram_size(ivideo)) {
6186 printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
6192 /* Enable PCI addressing and MMIO */
6193 if((ivideo->sisfb_mode_idx < 0) ||
6194 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6195 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
6196 SiS_SetRegOR(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
6197 /* Enable 2D accelerator engine */
6198 SiS_SetRegOR(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
6201 if(sisfb_pdc != 0xff) {
6202 if(ivideo->sisvga_engine == SIS_300_VGA)
6206 ivideo->SiS_Pr.PDC = sisfb_pdc;
6208 #ifdef CONFIG_FB_SIS_315
6209 if(ivideo->sisvga_engine == SIS_315_VGA) {
6210 if(sisfb_pdca != 0xff)
6211 ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
6215 if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
6216 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6217 (int)(ivideo->video_size >> 20));
6218 printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
6223 if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
6224 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
6229 ivideo->video_vbase = ioremap_wc(ivideo->video_base, ivideo->video_size);
6230 ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
6231 if(!ivideo->video_vbase) {
6232 printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
6237 ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
6238 if(!ivideo->mmio_vbase) {
6239 printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
6241 error_0: iounmap(ivideo->video_vbase);
6242 error_1: release_mem_region(ivideo->video_base, ivideo->video_size);
6243 error_2: release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6244 error_3: vfree(ivideo->bios_abase);
6245 pci_dev_put(ivideo->lpcdev);
6246 pci_dev_put(ivideo->nbridge);
6247 if(!ivideo->sisvga_enabled)
6248 pci_disable_device(pdev);
6249 framebuffer_release(sis_fb_info);
6253 printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
6254 ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);
6256 if(ivideo->video_offset) {
6257 printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
6258 ivideo->video_offset / 1024);
6261 printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
6262 ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
6265 /* Determine the size of the command queue */
6266 if(ivideo->sisvga_engine == SIS_300_VGA) {
6267 ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
6269 if(ivideo->chip == XGI_20) {
6270 ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
6272 ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
6276 /* Engines are no longer initialized here; this is
6277 * now done after the first mode-switch (if the
6278 * submitted var has its acceleration flags set).
6281 /* Calculate the base of the (unused) hw cursor */
6282 ivideo->hwcursor_vbase = ivideo->video_vbase
6283 + ivideo->video_size
6284 - ivideo->cmdQueueSize
6285 - ivideo->hwcursor_size;
6286 ivideo->caps |= HW_CURSOR_CAP;
6288 /* Initialize offscreen memory manager */
6289 if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
6290 printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
6293 /* Used for clearing the screen only, therefore respect our mem limit */
6294 ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
6295 ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;
6297 ivideo->vbflags = 0;
6298 ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
6299 ivideo->tvdefmodeidx = DEFAULT_TVMODE;
6300 ivideo->defmodeidx = DEFAULT_MODE;
6303 if(ivideo->chip < XGI_20) {
6304 if(ivideo->bios_abase) {
6305 ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr);
6309 if((ivideo->sisfb_mode_idx < 0) ||
6310 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6312 sisfb_sense_crt1(ivideo);
6314 sisfb_get_VB_type(ivideo);
6316 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6317 sisfb_detect_VB_connect(ivideo);
6320 ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
6322 /* Decide on which CRT2 device to use */
6323 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6324 if(ivideo->sisfb_crt2type != -1) {
6325 if((ivideo->sisfb_crt2type == CRT2_LCD) &&
6326 (ivideo->vbflags & CRT2_LCD)) {
6327 ivideo->currentvbflags |= CRT2_LCD;
6328 } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
6329 ivideo->currentvbflags |= ivideo->sisfb_crt2type;
6332 /* Chrontel 700x TV detection often unreliable, therefore
6333 * use a different default order on such machines
6335 if((ivideo->sisvga_engine == SIS_300_VGA) &&
6336 (ivideo->vbflags2 & VB2_CHRONTEL)) {
6337 if(ivideo->vbflags & CRT2_LCD)
6338 ivideo->currentvbflags |= CRT2_LCD;
6339 else if(ivideo->vbflags & CRT2_TV)
6340 ivideo->currentvbflags |= CRT2_TV;
6341 else if(ivideo->vbflags & CRT2_VGA)
6342 ivideo->currentvbflags |= CRT2_VGA;
6344 if(ivideo->vbflags & CRT2_TV)
6345 ivideo->currentvbflags |= CRT2_TV;
6346 else if(ivideo->vbflags & CRT2_LCD)
6347 ivideo->currentvbflags |= CRT2_LCD;
6348 else if(ivideo->vbflags & CRT2_VGA)
6349 ivideo->currentvbflags |= CRT2_VGA;
6354 if(ivideo->vbflags & CRT2_LCD) {
6355 sisfb_detect_lcd_type(ivideo);
6358 sisfb_save_pdc_emi(ivideo);
6360 if(!ivideo->sisfb_crt1off) {
6361 sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
6363 if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
6364 (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
6365 sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
6369 if(ivideo->sisfb_mode_idx >= 0) {
6370 int bu = ivideo->sisfb_mode_idx;
6371 ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
6372 ivideo->sisfb_mode_idx, ivideo->currentvbflags);
6373 if(bu != ivideo->sisfb_mode_idx) {
6374 printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
6375 sisbios_mode[bu].xres,
6376 sisbios_mode[bu].yres,
6377 sisbios_mode[bu].bpp);
6381 if(ivideo->sisfb_mode_idx < 0) {
6382 switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
6384 ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
6387 ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
6390 ivideo->sisfb_mode_idx = ivideo->defmodeidx;
6395 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
6397 if(ivideo->refresh_rate != 0) {
6398 sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate,
6399 ivideo->sisfb_mode_idx);
6402 if(ivideo->rate_idx == 0) {
6403 ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
6404 ivideo->refresh_rate = 60;
6407 if(ivideo->sisfb_thismonitor.datavalid) {
6408 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor,
6409 ivideo->sisfb_mode_idx,
6411 ivideo->refresh_rate)) {
6412 printk(KERN_INFO "sisfb: WARNING: Refresh rate "
6413 "exceeds monitor specs!\n");
6417 ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
6418 ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
6419 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
6421 sisfb_set_vparms(ivideo);
6423 printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
6424 ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
6425 ivideo->refresh_rate);
6427 /* Set up the default var according to chosen default display mode */
6428 ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
6429 ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
6430 ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
6432 sisfb_bpp_to_var(ivideo, &ivideo->default_var);
6434 ivideo->default_var.pixclock = (u32) (1000000000 /
6435 sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx));
6437 if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no,
6438 ivideo->rate_idx, &ivideo->default_var)) {
6439 if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
6440 ivideo->default_var.pixclock <<= 1;
6444 if(ivideo->sisfb_ypan) {
6445 /* Maximize regardless of sisfb_max at startup */
6446 ivideo->default_var.yres_virtual =
6447 sisfb_calc_maxyres(ivideo, &ivideo->default_var);
6448 if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
6449 ivideo->default_var.yres_virtual = ivideo->default_var.yres;
6453 sisfb_calc_pitch(ivideo, &ivideo->default_var);
6456 if(ivideo->sisfb_accel) {
6458 #ifdef STUPID_ACCELF_TEXT_SHIT
6459 ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
6462 sisfb_initaccel(ivideo);
6464 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
6465 sis_fb_info->flags = FBINFO_DEFAULT |
6466 FBINFO_HWACCEL_YPAN |
6467 FBINFO_HWACCEL_XPAN |
6468 FBINFO_HWACCEL_COPYAREA |
6469 FBINFO_HWACCEL_FILLRECT |
6470 ((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED);
6472 sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
6474 sis_fb_info->var = ivideo->default_var;
6475 sis_fb_info->fix = ivideo->sisfb_fix;
6476 sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
6477 sis_fb_info->fbops = &sisfb_ops;
6478 sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
6480 fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
6482 printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
6484 ivideo->wc_cookie = arch_phys_wc_add(ivideo->video_base,
6485 ivideo->video_size);
6486 if(register_framebuffer(sis_fb_info) < 0) {
6487 printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
6489 iounmap(ivideo->mmio_vbase);
6493 ivideo->registered = 1;
6496 ivideo->next = card_list;
6499 printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
6500 ivideo->sisfb_accel ? "enabled" : "disabled",
6501 ivideo->sisfb_ypan ?
6502 (ivideo->sisfb_max ? "enabled (auto-max)" :
6503 "enabled (no auto-max)") :
6507 fb_info(sis_fb_info, "%s frame buffer device version %d.%d.%d\n",
6508 ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
6510 printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
6512 } /* if mode = "none" */
6517 /*****************************************************/
6518 /* PCI DEVICE HANDLING */
6519 /*****************************************************/
6521 static void sisfb_remove(struct pci_dev *pdev)
6523 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
6524 struct fb_info *sis_fb_info = ivideo->memyselfandi;
6525 int registered = ivideo->registered;
6526 int modechanged = ivideo->modechanged;
6529 iounmap(ivideo->mmio_vbase);
6530 iounmap(ivideo->video_vbase);
6532 /* Release mem regions */
6533 release_mem_region(ivideo->video_base, ivideo->video_size);
6534 release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6536 vfree(ivideo->bios_abase);
6538 pci_dev_put(ivideo->lpcdev);
6540 pci_dev_put(ivideo->nbridge);
6542 arch_phys_wc_del(ivideo->wc_cookie);
6544 /* If device was disabled when starting, disable
6547 if(!ivideo->sisvga_enabled)
6548 pci_disable_device(pdev);
6550 /* Unregister the framebuffer */
6551 if(ivideo->registered) {
6552 unregister_framebuffer(sis_fb_info);
6553 framebuffer_release(sis_fb_info);
6556 /* OK, our ivideo is gone for good from here. */
6558 /* TODO: Restore the initial mode
6559 * This sounds easy but is as good as impossible
6560 * on many machines with SiS chip and video bridge
6561 * since text modes are always set up differently
6562 * from machine to machine. Depends on the type
6563 * of integration between chipset and bridge.
6565 if(registered && modechanged)
6567 "sisfb: Restoring of text mode not supported yet\n");
6570 static struct pci_driver sisfb_driver = {
6572 .id_table = sisfb_pci_table,
6573 .probe = sisfb_probe,
6574 .remove = sisfb_remove,
6577 static int __init sisfb_init(void)
6580 char *options = NULL;
6582 if(fb_get_options("sisfb", &options))
6585 sisfb_setup(options);
6587 return pci_register_driver(&sisfb_driver);
6591 module_init(sisfb_init);
6594 /*****************************************************/
6596 /*****************************************************/
6600 static char *mode = NULL;
6601 static int vesa = -1;
6602 static unsigned int rate = 0;
6603 static unsigned int crt1off = 1;
6604 static unsigned int mem = 0;
6605 static char *forcecrt2type = NULL;
6606 static int forcecrt1 = -1;
6607 static int pdc = -1;
6608 static int pdc1 = -1;
6609 static int noaccel = -1;
6610 static int noypan = -1;
6611 static int nomax = -1;
6612 static int userom = -1;
6613 static int useoem = -1;
6614 static char *tvstandard = NULL;
6615 static int nocrt2rate = 0;
6616 static int scalelcd = -1;
6617 static char *specialtiming = NULL;
6618 static int lvdshl = -1;
6619 static int tvxposoffset = 0, tvyposoffset = 0;
6620 #if !defined(__i386__) && !defined(__x86_64__)
6621 static int resetcard = 0;
6622 static int videoram = 0;
6625 static int __init sisfb_init_module(void)
6627 sisfb_setdefaultparms();
6630 sisfb_parm_rate = rate;
6632 if((scalelcd == 0) || (scalelcd == 1))
6633 sisfb_scalelcd = scalelcd ^ 1;
6635 /* Need to check crt2 type first for fstn/dstn */
6638 sisfb_search_crt2type(forcecrt2type);
6641 sisfb_search_tvstd(tvstandard);
6644 sisfb_search_mode(mode, false);
6646 sisfb_search_vesamode(vesa, false);
6648 sisfb_crt1off = (crt1off == 0) ? 1 : 0;
6650 sisfb_forcecrt1 = forcecrt1;
6653 else if(forcecrt1 == 0)
6658 else if(noaccel == 0)
6663 else if(noypan == 0)
6672 sisfb_parm_mem = mem;
6675 sisfb_userom = userom;
6678 sisfb_useoem = useoem;
6681 sisfb_pdc = (pdc & 0x7f);
6684 sisfb_pdca = (pdc1 & 0x1f);
6686 sisfb_nocrt2rate = nocrt2rate;
6689 sisfb_search_specialtiming(specialtiming);
6691 if((lvdshl >= 0) && (lvdshl <= 3))
6692 sisfb_lvdshl = lvdshl;
6694 sisfb_tvxposoffset = tvxposoffset;
6695 sisfb_tvyposoffset = tvyposoffset;
6697 #if !defined(__i386__) && !defined(__x86_64__)
6698 sisfb_resetcard = (resetcard) ? 1 : 0;
6700 sisfb_videoram = videoram;
6703 return sisfb_init();
6706 static void __exit sisfb_remove_module(void)
6708 pci_unregister_driver(&sisfb_driver);
6709 printk(KERN_DEBUG "sisfb: Module unloaded\n");
6712 module_init(sisfb_init_module);
6713 module_exit(sisfb_remove_module);
6715 MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
6716 MODULE_LICENSE("GPL");
6717 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
6719 module_param(mem, int, 0);
6720 module_param(noaccel, int, 0);
6721 module_param(noypan, int, 0);
6722 module_param(nomax, int, 0);
6723 module_param(userom, int, 0);
6724 module_param(useoem, int, 0);
6725 module_param(mode, charp, 0);
6726 module_param(vesa, int, 0);
6727 module_param(rate, int, 0);
6728 module_param(forcecrt1, int, 0);
6729 module_param(forcecrt2type, charp, 0);
6730 module_param(scalelcd, int, 0);
6731 module_param(pdc, int, 0);
6732 module_param(pdc1, int, 0);
6733 module_param(specialtiming, charp, 0);
6734 module_param(lvdshl, int, 0);
6735 module_param(tvstandard, charp, 0);
6736 module_param(tvxposoffset, int, 0);
6737 module_param(tvyposoffset, int, 0);
6738 module_param(nocrt2rate, int, 0);
6739 #if !defined(__i386__) && !defined(__x86_64__)
6740 module_param(resetcard, int, 0);
6741 module_param(videoram, int, 0);
6744 MODULE_PARM_DESC(mem,
6745 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6746 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6747 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6748 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6749 "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6750 "The value is to be specified without 'KB'.\n");
6752 MODULE_PARM_DESC(noaccel,
6753 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
6756 MODULE_PARM_DESC(noypan,
6757 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
6758 "will be performed by redrawing the screen. (default: 0)\n");
6760 MODULE_PARM_DESC(nomax,
6761 "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
6762 "memory for the virtual screen in order to optimize scrolling performance. If\n"
6763 "this is set to anything other than 0, sisfb will not do this and thereby \n"
6764 "enable the user to positively specify a virtual Y size of the screen using\n"
6765 "fbset. (default: 0)\n");
6767 MODULE_PARM_DESC(mode,
6768 "\nSelects the desired default display mode in the format XxYxDepth,\n"
6769 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
6770 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
6771 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
6773 MODULE_PARM_DESC(vesa,
6774 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
6775 "0x117 (default: 0x0103)\n");
6777 MODULE_PARM_DESC(rate,
6778 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
6779 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
6780 "will be ignored (default: 60)\n");
6782 MODULE_PARM_DESC(forcecrt1,
6783 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
6784 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
6785 "0=CRT1 OFF) (default: [autodetected])\n");
6787 MODULE_PARM_DESC(forcecrt2type,
6788 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
6789 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
6790 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
6791 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
6792 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
6793 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
6794 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
6795 "depends on the very hardware in use. (default: [autodetected])\n");
6797 MODULE_PARM_DESC(scalelcd,
6798 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
6799 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
6800 "show black bars around the image, TMDS panels will probably do the scaling\n"
6801 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
6803 MODULE_PARM_DESC(pdc,
6804 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
6805 "should detect this correctly in most cases; however, sometimes this is not\n"
6806 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
6807 "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
6808 "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
6809 "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
6811 #ifdef CONFIG_FB_SIS_315
6812 MODULE_PARM_DESC(pdc1,
6813 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
6814 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
6815 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
6816 "implemented yet.\n");
6819 MODULE_PARM_DESC(specialtiming,
6820 "\nPlease refer to documentation for more information on this option.\n");
6822 MODULE_PARM_DESC(lvdshl,
6823 "\nPlease refer to documentation for more information on this option.\n");
6825 MODULE_PARM_DESC(tvstandard,
6826 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
6827 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
6829 MODULE_PARM_DESC(tvxposoffset,
6830 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
6833 MODULE_PARM_DESC(tvyposoffset,
6834 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
6837 MODULE_PARM_DESC(nocrt2rate,
6838 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
6839 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
6841 #if !defined(__i386__) && !defined(__x86_64__)
6842 #ifdef CONFIG_FB_SIS_300
6843 MODULE_PARM_DESC(resetcard,
6844 "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
6845 "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
6846 "currently). Default: 0\n");
6848 MODULE_PARM_DESC(videoram,
6849 "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
6850 "some non-x86 architectures where the memory auto detection fails. Only\n"
6851 "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
6855 #endif /* /MODULE */
6857 /* _GPL only for new symbols. */
6858 EXPORT_SYMBOL(sis_malloc);
6859 EXPORT_SYMBOL(sis_free);
6860 EXPORT_SYMBOL_GPL(sis_malloc_new);
6861 EXPORT_SYMBOL_GPL(sis_free_new);