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.
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,
22 #include <linux/aperture.h>
23 #include <linux/module.h>
24 #include <linux/moduleparam.h>
25 #include <linux/kernel.h>
26 #include <linux/spinlock.h>
27 #include <linux/errno.h>
28 #include <linux/string.h>
30 #include <linux/screen_info.h>
31 #include <linux/slab.h>
33 #include <linux/selection.h>
34 #include <linux/ioport.h>
35 #include <linux/init.h>
36 #include <linux/pci.h>
37 #include <linux/vmalloc.h>
38 #include <linux/capability.h>
40 #include <linux/types.h>
41 #include <linux/uaccess.h>
48 #if !defined(CONFIG_FB_SIS_300) && !defined(CONFIG_FB_SIS_315)
49 #warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
50 #warning sisfb will not work!
53 /* ---------------------- Prototypes ------------------------- */
55 /* Interface used by the world */
57 static int sisfb_setup(char *options);
60 /* Interface to the low level console driver */
61 static int sisfb_init(void);
64 static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
65 struct fb_info *info);
67 static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
69 static int sisfb_set_par(struct fb_info *info);
70 static int sisfb_blank(int blank,
71 struct fb_info *info);
73 static void sisfb_handle_command(struct sis_video_info *ivideo,
74 struct sisfb_cmd *sisfb_command);
76 static void sisfb_search_mode(char *name, bool quiet);
77 static int sisfb_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags);
78 static u8 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate,
80 static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green,
81 unsigned blue, unsigned transp,
82 struct fb_info *fb_info);
83 static int sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
84 struct fb_info *info);
85 static void sisfb_pre_setmode(struct sis_video_info *ivideo);
86 static void sisfb_post_setmode(struct sis_video_info *ivideo);
87 static bool sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
88 static bool sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
89 static bool sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
90 static bool sisfb_bridgeisslave(struct sis_video_info *ivideo);
91 static void sisfb_detect_VB_connect(struct sis_video_info *ivideo);
92 static void sisfb_get_VB_type(struct sis_video_info *ivideo);
93 static void sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val);
94 static void sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val);
96 /* Internal heap routines */
97 static int sisfb_heap_init(struct sis_video_info *ivideo);
98 static struct SIS_OH * sisfb_poh_new_node(struct SIS_HEAP *memheap);
99 static struct SIS_OH * sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size);
100 static void sisfb_delete_node(struct SIS_OH *poh);
101 static void sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh);
102 static struct SIS_OH * sisfb_poh_free(struct SIS_HEAP *memheap, u32 base);
103 static void sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh);
106 /* ------------------ Internal helper routines ----------------- */
109 sisfb_setdefaultparms(void)
119 sisfb_parm_rate = -1;
121 sisfb_forcecrt1 = -1;
127 sisfb_specialtiming = CUT_NONE;
133 sisfb_tvxposoffset = 0;
134 sisfb_tvyposoffset = 0;
135 sisfb_nocrt2rate = 0;
136 #if !defined(__i386__) && !defined(__x86_64__)
142 /* ------------- Parameter parsing -------------- */
144 static void sisfb_search_vesamode(unsigned int vesamode, bool quiet)
148 /* We don't know the hardware specs yet and there is no ivideo */
152 printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
154 sisfb_mode_idx = DEFAULT_MODE;
159 vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
161 while(sisbios_mode[i++].mode_no[0] != 0) {
162 if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
163 (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
165 if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
166 sisbios_mode[i-1].mode_no[1] == 0x56 ||
167 sisbios_mode[i-1].mode_no[1] == 0x53)
170 if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
171 sisbios_mode[i-1].mode_no[1] == 0x5b)
174 sisfb_mode_idx = i - 1;
180 printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
183 static void sisfb_search_mode(char *name, bool quiet)
185 unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
187 char strbuf[16], strbuf1[20];
188 char *nameptr = name;
190 /* We don't know the hardware specs yet and there is no ivideo */
194 printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
196 sisfb_mode_idx = DEFAULT_MODE;
200 if(!strncasecmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
202 printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
204 sisfb_mode_idx = DEFAULT_MODE;
208 if(strlen(name) <= 19) {
209 strcpy(strbuf1, name);
210 for(i = 0; i < strlen(strbuf1); i++) {
211 if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
214 /* This does some fuzzy mode naming detection */
215 if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
216 if((rate <= 32) || (depth > 32)) {
219 sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
221 sisfb_parm_rate = rate;
222 } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
223 sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
227 if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
228 sprintf(strbuf, "%ux%ux8", xres, yres);
231 sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
238 while(sisbios_mode[i].mode_no[0] != 0) {
239 if(!strncasecmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
241 if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
242 sisbios_mode[i-1].mode_no[1] == 0x56 ||
243 sisbios_mode[i-1].mode_no[1] == 0x53)
246 if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
247 sisbios_mode[i-1].mode_no[1] == 0x5b)
250 sisfb_mode_idx = i - 1;
257 printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
261 static void sisfb_get_vga_mode_from_kernel(void)
265 int mydepth = screen_info.lfb_depth;
267 if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
269 if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) &&
270 (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
271 (mydepth >= 8) && (mydepth <= 32) ) {
273 if(mydepth == 24) mydepth = 32;
275 sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
276 screen_info.lfb_height,
280 "sisfb: Using vga mode %s pre-set by kernel as default\n",
283 sisfb_search_mode(mymode, true);
291 sisfb_search_crt2type(const char *name)
295 /* We don't know the hardware specs yet and there is no ivideo */
297 if(name == NULL) return;
299 while(sis_crt2type[i].type_no != -1) {
300 if(!strncasecmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
301 sisfb_crt2type = sis_crt2type[i].type_no;
302 sisfb_tvplug = sis_crt2type[i].tvplug_no;
303 sisfb_crt2flags = sis_crt2type[i].flags;
309 sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
310 sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
312 if(sisfb_crt2type < 0)
313 printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
317 sisfb_search_tvstd(const char *name)
321 /* We don't know the hardware specs yet and there is no ivideo */
326 while(sis_tvtype[i].type_no != -1) {
327 if(!strncasecmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
328 sisfb_tvstd = sis_tvtype[i].type_no;
336 sisfb_search_specialtiming(const char *name)
341 /* We don't know the hardware specs yet and there is no ivideo */
346 if(!strncasecmp(name, "none", 4)) {
347 sisfb_specialtiming = CUT_FORCENONE;
348 printk(KERN_DEBUG "sisfb: Special timing disabled\n");
350 while(mycustomttable[i].chipID != 0) {
351 if(!strncasecmp(name,mycustomttable[i].optionName,
352 strlen(mycustomttable[i].optionName))) {
353 sisfb_specialtiming = mycustomttable[i].SpecialID;
355 printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
356 mycustomttable[i].vendorName,
357 mycustomttable[i].cardName,
358 mycustomttable[i].optionName);
364 printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
365 printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
367 while(mycustomttable[i].chipID != 0) {
368 printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
369 mycustomttable[i].optionName,
370 mycustomttable[i].vendorName,
371 mycustomttable[i].cardName);
378 /* ----------- Various detection routines ----------- */
380 static void sisfb_detect_custom_timing(struct sis_video_info *ivideo)
382 unsigned char *biosver = NULL;
383 unsigned char *biosdate = NULL;
388 if(ivideo->SiS_Pr.UseROM) {
389 biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06;
390 biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c;
391 for(i = 0; i < 32768; i++)
392 chksum += ivideo->SiS_Pr.VirtualRomBase[i];
397 if( (mycustomttable[i].chipID == ivideo->chip) &&
398 ((!strlen(mycustomttable[i].biosversion)) ||
399 (ivideo->SiS_Pr.UseROM &&
400 (!strncmp(mycustomttable[i].biosversion, biosver,
401 strlen(mycustomttable[i].biosversion))))) &&
402 ((!strlen(mycustomttable[i].biosdate)) ||
403 (ivideo->SiS_Pr.UseROM &&
404 (!strncmp(mycustomttable[i].biosdate, biosdate,
405 strlen(mycustomttable[i].biosdate))))) &&
406 ((!mycustomttable[i].bioschksum) ||
407 (ivideo->SiS_Pr.UseROM &&
408 (mycustomttable[i].bioschksum == chksum))) &&
409 (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
410 (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
412 for(j = 0; j < 5; j++) {
413 if(mycustomttable[i].biosFootprintAddr[j]) {
414 if(ivideo->SiS_Pr.UseROM) {
415 if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
416 mycustomttable[i].biosFootprintData[j]) {
424 ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
425 printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
426 mycustomttable[i].vendorName,
427 mycustomttable[i].cardName);
428 printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
429 mycustomttable[i].optionName);
434 } while(mycustomttable[i].chipID);
437 static bool sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
439 int i, j, xres, yres, refresh, index;
442 if(buffer[0] != 0x00 || buffer[1] != 0xff ||
443 buffer[2] != 0xff || buffer[3] != 0xff ||
444 buffer[4] != 0xff || buffer[5] != 0xff ||
445 buffer[6] != 0xff || buffer[7] != 0x00) {
446 printk(KERN_DEBUG "sisfb: Bad EDID header\n");
450 if(buffer[0x12] != 0x01) {
451 printk(KERN_INFO "sisfb: EDID version %d not supported\n",
456 monitor->feature = buffer[0x18];
458 if(!(buffer[0x14] & 0x80)) {
459 if(!(buffer[0x14] & 0x08)) {
461 "sisfb: WARNING: Monitor does not support separate syncs\n");
465 if(buffer[0x13] >= 0x01) {
466 /* EDID V1 rev 1 and 2: Search for monitor descriptor
471 if(buffer[j] == 0x00 && buffer[j + 1] == 0x00 &&
472 buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
473 buffer[j + 4] == 0x00) {
474 monitor->hmin = buffer[j + 7];
475 monitor->hmax = buffer[j + 8];
476 monitor->vmin = buffer[j + 5];
477 monitor->vmax = buffer[j + 6];
478 monitor->dclockmax = buffer[j + 9] * 10 * 1000;
479 monitor->datavalid = true;
486 if(!monitor->datavalid) {
487 /* Otherwise: Get a range from the list of supported
488 * Estabished Timings. This is not entirely accurate,
489 * because fixed frequency monitors are not supported
492 monitor->hmin = 65535; monitor->hmax = 0;
493 monitor->vmin = 65535; monitor->vmax = 0;
494 monitor->dclockmax = 0;
495 emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
496 for(i = 0; i < 13; i++) {
497 if(emodes & sisfb_ddcsmodes[i].mask) {
498 if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
499 if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
500 if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
501 if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
502 if(monitor->dclockmax < sisfb_ddcsmodes[i].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
506 for(i = 0; i < 8; i++) {
507 xres = (buffer[index] + 31) * 8;
508 switch(buffer[index + 1] & 0xc0) {
509 case 0xc0: yres = (xres * 9) / 16; break;
510 case 0x80: yres = (xres * 4) / 5; break;
511 case 0x40: yres = (xres * 3) / 4; break;
512 default: yres = xres; break;
514 refresh = (buffer[index + 1] & 0x3f) + 60;
515 if((xres >= 640) && (yres >= 480)) {
516 for(j = 0; j < 8; j++) {
517 if((xres == sisfb_ddcfmodes[j].x) &&
518 (yres == sisfb_ddcfmodes[j].y) &&
519 (refresh == sisfb_ddcfmodes[j].v)) {
520 if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
521 if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
522 if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
523 if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
524 if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d;
530 if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
531 monitor->datavalid = true;
535 return monitor->datavalid;
538 static void sisfb_handle_ddc(struct sis_video_info *ivideo,
539 struct sisfb_monitor *monitor, int crtno)
541 unsigned short temp, i, realcrtno = crtno;
542 unsigned char buffer[256];
544 monitor->datavalid = false;
547 if(ivideo->vbflags & CRT2_LCD) realcrtno = 1;
548 else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
552 if((ivideo->sisfb_crt1off) && (!crtno))
555 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
556 realcrtno, 0, &buffer[0], ivideo->vbflags2);
557 if((!temp) || (temp == 0xffff)) {
558 printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
561 printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
562 printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
564 (temp & 0x1a) ? "" : "[none of the supported]",
565 (temp & 0x02) ? "2 " : "",
566 (temp & 0x08) ? "D&P" : "",
567 (temp & 0x10) ? "FPDI-2" : "");
569 i = 3; /* Number of retrys */
571 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
572 realcrtno, 1, &buffer[0], ivideo->vbflags2);
573 } while((temp) && i--);
575 if(sisfb_interpret_edid(monitor, &buffer[0])) {
576 printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
577 monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
578 monitor->dclockmax / 1000);
580 printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
583 printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
586 printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
591 /* -------------- Mode validation --------------- */
594 sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
595 int mode_idx, int rate_idx, int rate)
598 unsigned int dclock, hsync;
600 if(!monitor->datavalid)
606 /* Skip for 320x200, 320x240, 640x400 */
607 switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
618 #ifdef CONFIG_FB_SIS_315
621 if(ivideo->sisvga_engine == SIS_315_VGA) return true;
625 if(rate < (monitor->vmin - 1))
627 if(rate > (monitor->vmax + 1))
630 if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
631 sisbios_mode[mode_idx].mode_no[ivideo->mni],
632 &htotal, &vtotal, rate_idx)) {
633 dclock = (htotal * vtotal * rate) / 1000;
634 if(dclock > (monitor->dclockmax + 1000))
636 hsync = dclock / htotal;
637 if(hsync < (monitor->hmin - 1))
639 if(hsync > (monitor->hmax + 1))
648 sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
650 u16 xres=0, yres, myres;
652 #ifdef CONFIG_FB_SIS_300
653 if (ivideo->sisvga_engine == SIS_300_VGA) {
654 if (!(sisbios_mode[myindex].chipset & MD_SIS300))
658 #ifdef CONFIG_FB_SIS_315
659 if (ivideo->sisvga_engine == SIS_315_VGA) {
660 if (!(sisbios_mode[myindex].chipset & MD_SIS315))
665 myres = sisbios_mode[myindex].yres;
667 switch (vbflags & VB_DISPTYPE_DISP2) {
670 xres = ivideo->lcdxres; yres = ivideo->lcdyres;
672 if ((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
673 (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
674 if (sisbios_mode[myindex].xres > xres)
680 if (ivideo->sisfb_fstn) {
681 if (sisbios_mode[myindex].xres == 320) {
683 switch (sisbios_mode[myindex].mode_no[1]) {
684 case 0x50: myindex = MODE_FSTN_8; break;
685 case 0x56: myindex = MODE_FSTN_16; break;
686 case 0x53: return -1;
692 if (SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
693 sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
694 ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
700 if (SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
701 sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
707 if (SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
708 sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
718 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
721 u16 xres = sisbios_mode[mode_idx].xres;
722 u16 yres = sisbios_mode[mode_idx].yres;
724 ivideo->rate_idx = 0;
725 while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
726 if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
727 if(sisfb_vrate[i].refresh == rate) {
728 ivideo->rate_idx = sisfb_vrate[i].idx;
730 } else if(sisfb_vrate[i].refresh > rate) {
731 if((sisfb_vrate[i].refresh - rate) <= 3) {
732 DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
733 rate, sisfb_vrate[i].refresh);
734 ivideo->rate_idx = sisfb_vrate[i].idx;
735 ivideo->refresh_rate = sisfb_vrate[i].refresh;
736 } else if((sisfb_vrate[i].idx != 1) &&
737 ((rate - sisfb_vrate[i-1].refresh) <= 2)) {
738 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
739 rate, sisfb_vrate[i-1].refresh);
740 ivideo->rate_idx = sisfb_vrate[i-1].idx;
741 ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
744 } else if((rate - sisfb_vrate[i].refresh) <= 2) {
745 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
746 rate, sisfb_vrate[i].refresh);
747 ivideo->rate_idx = sisfb_vrate[i].idx;
753 if(ivideo->rate_idx > 0) {
754 return ivideo->rate_idx;
756 printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n",
763 sisfb_bridgeisslave(struct sis_video_info *ivideo)
767 if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
770 P1_00 = SiS_GetReg(SISPART1, 0x00);
771 if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
772 ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
780 sisfballowretracecrt1(struct sis_video_info *ivideo)
784 temp = SiS_GetReg(SISCR, 0x17);
788 temp = SiS_GetReg(SISSR, 0x1f);
796 sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
798 if(!sisfballowretracecrt1(ivideo))
801 if (SiS_GetRegByte(SISINPSTAT) & 0x08)
808 sisfbwaitretracecrt1(struct sis_video_info *ivideo)
812 if(!sisfballowretracecrt1(ivideo))
816 while ((!(SiS_GetRegByte(SISINPSTAT) & 0x08)) && --watchdog);
818 while ((SiS_GetRegByte(SISINPSTAT) & 0x08) && --watchdog);
822 sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
824 unsigned char temp, reg;
826 switch(ivideo->sisvga_engine) {
827 case SIS_300_VGA: reg = 0x25; break;
828 case SIS_315_VGA: reg = 0x30; break;
829 default: return false;
832 temp = SiS_GetReg(SISPART1, reg);
840 sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
842 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
843 if(!sisfb_bridgeisslave(ivideo)) {
844 return sisfbcheckvretracecrt2(ivideo);
847 return sisfbcheckvretracecrt1(ivideo);
851 sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
853 u8 idx, reg1, reg2, reg3, reg4;
856 (*vcount) = (*hcount) = 0;
858 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
860 ret |= (FB_VBLANK_HAVE_VSYNC |
861 FB_VBLANK_HAVE_HBLANK |
862 FB_VBLANK_HAVE_VBLANK |
863 FB_VBLANK_HAVE_VCOUNT |
864 FB_VBLANK_HAVE_HCOUNT);
865 switch(ivideo->sisvga_engine) {
866 case SIS_300_VGA: idx = 0x25; break;
868 case SIS_315_VGA: idx = 0x30; break;
870 reg1 = SiS_GetReg(SISPART1, (idx+0)); /* 30 */
871 reg2 = SiS_GetReg(SISPART1, (idx+1)); /* 31 */
872 reg3 = SiS_GetReg(SISPART1, (idx+2)); /* 32 */
873 reg4 = SiS_GetReg(SISPART1, (idx+3)); /* 33 */
874 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
875 if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
876 if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
877 (*vcount) = reg3 | ((reg4 & 0x70) << 4);
878 (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
880 } else if(sisfballowretracecrt1(ivideo)) {
882 ret |= (FB_VBLANK_HAVE_VSYNC |
883 FB_VBLANK_HAVE_VBLANK |
884 FB_VBLANK_HAVE_VCOUNT |
885 FB_VBLANK_HAVE_HCOUNT);
886 reg1 = SiS_GetRegByte(SISINPSTAT);
887 if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
888 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
889 reg1 = SiS_GetReg(SISCR, 0x20);
890 reg1 = SiS_GetReg(SISCR, 0x1b);
891 reg2 = SiS_GetReg(SISCR, 0x1c);
892 reg3 = SiS_GetReg(SISCR, 0x1d);
893 (*vcount) = reg2 | ((reg3 & 0x07) << 8);
894 (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
901 sisfb_myblank(struct sis_video_info *ivideo, int blank)
903 u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
904 bool backlight = true;
907 case FB_BLANK_UNBLANK: /* on */
916 case FB_BLANK_NORMAL: /* blank */
925 case FB_BLANK_VSYNC_SUSPEND: /* no vsync */
934 case FB_BLANK_HSYNC_SUSPEND: /* no hsync */
943 case FB_BLANK_POWERDOWN: /* off */
956 if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
958 if( (!ivideo->sisfb_thismonitor.datavalid) ||
959 ((ivideo->sisfb_thismonitor.datavalid) &&
960 (ivideo->sisfb_thismonitor.feature & 0xe0))) {
962 if(ivideo->sisvga_engine == SIS_315_VGA) {
963 SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
966 if(!(sisfb_bridgeisslave(ivideo))) {
967 SiS_SetRegANDOR(SISSR, 0x01, ~0x20, sr01);
968 SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, sr1f);
974 if(ivideo->currentvbflags & CRT2_LCD) {
976 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
978 SiS_SiS30xBLOn(&ivideo->SiS_Pr);
980 SiS_SiS30xBLOff(&ivideo->SiS_Pr);
982 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
983 #ifdef CONFIG_FB_SIS_315
984 if(ivideo->vbflags2 & VB2_CHRONTEL) {
986 SiS_Chrontel701xBLOn(&ivideo->SiS_Pr);
988 SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
994 if(((ivideo->sisvga_engine == SIS_300_VGA) &&
995 (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
996 ((ivideo->sisvga_engine == SIS_315_VGA) &&
997 ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
998 SiS_SetRegANDOR(SISSR, 0x11, ~0x0c, sr11);
1001 if(ivideo->sisvga_engine == SIS_300_VGA) {
1002 if((ivideo->vbflags2 & VB2_30xB) &&
1003 (!(ivideo->vbflags2 & VB2_30xBDH))) {
1004 SiS_SetRegANDOR(SISPART1, 0x13, 0x3f, p1_13);
1006 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
1007 if((ivideo->vbflags2 & VB2_30xB) &&
1008 (!(ivideo->vbflags2 & VB2_30xBDH))) {
1009 SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
1013 } else if(ivideo->currentvbflags & CRT2_VGA) {
1015 if(ivideo->vbflags2 & VB2_30xB) {
1016 SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
1024 /* ------------- Callbacks from init.c/init301.c -------------- */
1026 #ifdef CONFIG_FB_SIS_300
1028 sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg)
1030 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1033 pci_read_config_dword(ivideo->nbridge, reg, &val);
1034 return (unsigned int)val;
1038 sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val)
1040 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1042 pci_write_config_dword(ivideo->nbridge, reg, (u32)val);
1046 sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg)
1048 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1051 if(!ivideo->lpcdev) return 0;
1053 pci_read_config_dword(ivideo->lpcdev, reg, &val);
1054 return (unsigned int)val;
1058 #ifdef CONFIG_FB_SIS_315
1060 sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val)
1062 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1064 pci_write_config_byte(ivideo->nbridge, reg, (u8)val);
1068 sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg)
1070 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1073 if(!ivideo->lpcdev) return 0;
1075 pci_read_config_word(ivideo->lpcdev, reg, &val);
1076 return (unsigned int)val;
1080 /* ----------- FBDev related routines for all series ----------- */
1083 sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
1085 return (var->bits_per_pixel == 8) ? 256 : 16;
1089 sisfb_set_vparms(struct sis_video_info *ivideo)
1091 switch(ivideo->video_bpp) {
1093 ivideo->DstColor = 0x0000;
1094 ivideo->SiS310_AccelDepth = 0x00000000;
1095 ivideo->video_cmap_len = 256;
1098 ivideo->DstColor = 0x8000;
1099 ivideo->SiS310_AccelDepth = 0x00010000;
1100 ivideo->video_cmap_len = 16;
1103 ivideo->DstColor = 0xC000;
1104 ivideo->SiS310_AccelDepth = 0x00020000;
1105 ivideo->video_cmap_len = 16;
1108 ivideo->video_cmap_len = 16;
1109 printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
1115 sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1117 int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3));
1119 if(maxyres > 32767) maxyres = 32767;
1125 sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1127 ivideo->video_linelength = var->xres_virtual * (var->bits_per_pixel >> 3);
1128 ivideo->scrnpitchCRT1 = ivideo->video_linelength;
1129 if(!(ivideo->currentvbflags & CRT1_LCDA)) {
1130 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1131 ivideo->scrnpitchCRT1 <<= 1;
1137 sisfb_set_pitch(struct sis_video_info *ivideo)
1139 bool isslavemode = false;
1140 unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
1141 unsigned short HDisplay2 = ivideo->video_linelength >> 3;
1143 if(sisfb_bridgeisslave(ivideo)) isslavemode = true;
1145 /* We need to set pitch for CRT1 if bridge is in slave mode, too */
1146 if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
1147 SiS_SetReg(SISCR, 0x13, (HDisplay1 & 0xFF));
1148 SiS_SetRegANDOR(SISSR, 0x0E, 0xF0, (HDisplay1 >> 8));
1151 /* We must not set the pitch for CRT2 if bridge is in slave mode */
1152 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
1153 SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
1154 SiS_SetReg(SISPART1, 0x07, (HDisplay2 & 0xFF));
1155 SiS_SetRegANDOR(SISPART1, 0x09, 0xF0, (HDisplay2 >> 8));
1160 sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1162 ivideo->video_cmap_len = sisfb_get_cmap_len(var);
1164 switch(var->bits_per_pixel) {
1166 var->red.offset = var->green.offset = var->blue.offset = 0;
1167 var->red.length = var->green.length = var->blue.length = 8;
1170 var->red.offset = 11;
1171 var->red.length = 5;
1172 var->green.offset = 5;
1173 var->green.length = 6;
1174 var->blue.offset = 0;
1175 var->blue.length = 5;
1176 var->transp.offset = 0;
1177 var->transp.length = 0;
1180 var->red.offset = 16;
1181 var->red.length = 8;
1182 var->green.offset = 8;
1183 var->green.length = 8;
1184 var->blue.offset = 0;
1185 var->blue.length = 8;
1186 var->transp.offset = 24;
1187 var->transp.length = 8;
1193 sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
1195 unsigned short modeno = ivideo->mode_no;
1197 /* >=2.6.12's fbcon clears the screen anyway */
1200 SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1202 sisfb_pre_setmode(ivideo);
1204 if(!SiSSetMode(&ivideo->SiS_Pr, modeno)) {
1205 printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
1209 SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1211 sisfb_post_setmode(ivideo);
1218 sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
1220 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1221 unsigned int htotal = 0, vtotal = 0;
1222 unsigned int drate = 0, hrate = 0;
1223 int found_mode = 0, ret;
1227 htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1229 vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1231 pixclock = var->pixclock;
1233 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1234 vtotal += var->yres;
1236 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1237 vtotal += var->yres;
1239 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1240 vtotal += var->yres;
1242 } else vtotal += var->yres;
1244 if(!(htotal) || !(vtotal)) {
1245 DPRINTK("sisfb: Invalid 'var' information\n");
1249 if(pixclock && htotal && vtotal) {
1250 drate = 1000000000 / pixclock;
1251 hrate = (drate * 1000) / htotal;
1252 ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1254 ivideo->refresh_rate = 60;
1257 old_mode = ivideo->sisfb_mode_idx;
1258 ivideo->sisfb_mode_idx = 0;
1260 while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) &&
1261 (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) {
1262 if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) &&
1263 (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) &&
1264 (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) {
1265 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1269 ivideo->sisfb_mode_idx++;
1273 ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
1274 ivideo->sisfb_mode_idx, ivideo->currentvbflags);
1276 ivideo->sisfb_mode_idx = -1;
1279 if(ivideo->sisfb_mode_idx < 0) {
1280 printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres,
1281 var->yres, var->bits_per_pixel);
1282 ivideo->sisfb_mode_idx = old_mode;
1286 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1288 if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
1289 ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
1290 ivideo->refresh_rate = 60;
1294 /* If acceleration to be used? Need to know
1295 * before pre/post_set_mode()
1298 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
1299 #ifdef STUPID_ACCELF_TEXT_SHIT
1300 if(var->accel_flags & FB_ACCELF_TEXT) {
1301 info->flags &= ~FBINFO_HWACCEL_DISABLED;
1303 info->flags |= FBINFO_HWACCEL_DISABLED;
1306 if(!(info->flags & FBINFO_HWACCEL_DISABLED)) ivideo->accel = -1;
1308 if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
1311 if((ret = sisfb_set_mode(ivideo, 1))) {
1315 ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
1316 ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
1317 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
1319 sisfb_calc_pitch(ivideo, var);
1320 sisfb_set_pitch(ivideo);
1322 sisfb_set_vparms(ivideo);
1324 ivideo->current_width = ivideo->video_width;
1325 ivideo->current_height = ivideo->video_height;
1326 ivideo->current_bpp = ivideo->video_bpp;
1327 ivideo->current_htotal = htotal;
1328 ivideo->current_vtotal = vtotal;
1329 ivideo->current_linelength = ivideo->video_linelength;
1330 ivideo->current_pixclock = var->pixclock;
1331 ivideo->current_refresh_rate = ivideo->refresh_rate;
1332 ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
1339 sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
1341 SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1343 SiS_SetReg(SISCR, 0x0D, base & 0xFF);
1344 SiS_SetReg(SISCR, 0x0C, (base >> 8) & 0xFF);
1345 SiS_SetReg(SISSR, 0x0D, (base >> 16) & 0xFF);
1346 if(ivideo->sisvga_engine == SIS_315_VGA) {
1347 SiS_SetRegANDOR(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
1352 sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
1354 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1355 SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
1356 SiS_SetReg(SISPART1, 0x06, (base & 0xFF));
1357 SiS_SetReg(SISPART1, 0x05, ((base >> 8) & 0xFF));
1358 SiS_SetReg(SISPART1, 0x04, ((base >> 16) & 0xFF));
1359 if(ivideo->sisvga_engine == SIS_315_VGA) {
1360 SiS_SetRegANDOR(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1366 sisfb_pan_var(struct sis_video_info *ivideo, struct fb_info *info,
1367 struct fb_var_screeninfo *var)
1369 ivideo->current_base = var->yoffset * info->var.xres_virtual
1372 /* calculate base bpp dep. */
1373 switch (info->var.bits_per_pixel) {
1377 ivideo->current_base >>= 1;
1381 ivideo->current_base >>= 2;
1385 ivideo->current_base += (ivideo->video_offset >> 2);
1387 sisfb_set_base_CRT1(ivideo, ivideo->current_base);
1388 sisfb_set_base_CRT2(ivideo, ivideo->current_base);
1394 sisfb_open(struct fb_info *info, int user)
1400 sisfb_release(struct fb_info *info, int user)
1406 sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
1407 unsigned transp, struct fb_info *info)
1409 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1411 if(regno >= sisfb_get_cmap_len(&info->var))
1414 switch(info->var.bits_per_pixel) {
1416 SiS_SetRegByte(SISDACA, regno);
1417 SiS_SetRegByte(SISDACD, (red >> 10));
1418 SiS_SetRegByte(SISDACD, (green >> 10));
1419 SiS_SetRegByte(SISDACD, (blue >> 10));
1420 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1421 SiS_SetRegByte(SISDAC2A, regno);
1422 SiS_SetRegByte(SISDAC2D, (red >> 8));
1423 SiS_SetRegByte(SISDAC2D, (green >> 8));
1424 SiS_SetRegByte(SISDAC2D, (blue >> 8));
1431 ((u32 *)(info->pseudo_palette))[regno] =
1433 ((green & 0xfc00) >> 5) |
1434 ((blue & 0xf800) >> 11);
1443 ((u32 *)(info->pseudo_palette))[regno] =
1444 (red << 16) | (green << 8) | (blue);
1451 sisfb_set_par(struct fb_info *info)
1455 if((err = sisfb_do_set_var(&info->var, 1, info)))
1458 sisfb_get_fix(&info->fix, -1, info);
1464 sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1466 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1467 unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
1468 unsigned int drate = 0, hrate = 0, maxyres;
1470 int refresh_rate, search_idx, tidx;
1471 bool recalc_clock = false;
1474 htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1476 vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1478 pixclock = var->pixclock;
1480 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1481 vtotal += var->yres;
1483 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1484 vtotal += var->yres;
1486 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1487 vtotal += var->yres;
1490 vtotal += var->yres;
1492 if(!(htotal) || !(vtotal)) {
1493 SISFAIL("sisfb: no valid timing data");
1497 while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
1498 (sisbios_mode[search_idx].xres <= var->xres) ) {
1499 if( (sisbios_mode[search_idx].xres == var->xres) &&
1500 (sisbios_mode[search_idx].yres == var->yres) &&
1501 (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1502 if((tidx = sisfb_validate_mode(ivideo, search_idx,
1503 ivideo->currentvbflags)) > 0) {
1514 while(sisbios_mode[search_idx].mode_no[0] != 0) {
1515 if( (var->xres <= sisbios_mode[search_idx].xres) &&
1516 (var->yres <= sisbios_mode[search_idx].yres) &&
1517 (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
1518 if((tidx = sisfb_validate_mode(ivideo,search_idx,
1519 ivideo->currentvbflags)) > 0) {
1529 "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
1530 var->xres, var->yres, var->bits_per_pixel,
1531 sisbios_mode[search_idx].xres,
1532 sisbios_mode[search_idx].yres,
1533 var->bits_per_pixel);
1534 var->xres = sisbios_mode[search_idx].xres;
1535 var->yres = sisbios_mode[search_idx].yres;
1538 "sisfb: Failed to find supported mode near %dx%dx%d\n",
1539 var->xres, var->yres, var->bits_per_pixel);
1544 if( ((ivideo->vbflags2 & VB2_LVDS) ||
1545 ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
1546 (var->bits_per_pixel == 8) ) {
1547 /* Slave modes on LVDS and 301B-DH */
1549 recalc_clock = true;
1550 } else if( (ivideo->current_htotal == htotal) &&
1551 (ivideo->current_vtotal == vtotal) &&
1552 (ivideo->current_pixclock == pixclock) ) {
1553 /* x=x & y=y & c=c -> assume depth change */
1554 drate = 1000000000 / pixclock;
1555 hrate = (drate * 1000) / htotal;
1556 refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1557 } else if( ( (ivideo->current_htotal != htotal) ||
1558 (ivideo->current_vtotal != vtotal) ) &&
1559 (ivideo->current_pixclock == var->pixclock) ) {
1560 /* x!=x | y!=y & c=c -> invalid pixclock */
1561 if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
1563 ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
1564 } else if(ivideo->sisfb_parm_rate != -1) {
1565 /* Sic, sisfb_parm_rate - want to know originally desired rate here */
1566 refresh_rate = ivideo->sisfb_parm_rate;
1570 recalc_clock = true;
1571 } else if((pixclock) && (htotal) && (vtotal)) {
1572 drate = 1000000000 / pixclock;
1573 hrate = (drate * 1000) / htotal;
1574 refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1575 } else if(ivideo->current_refresh_rate) {
1576 refresh_rate = ivideo->current_refresh_rate;
1577 recalc_clock = true;
1580 recalc_clock = true;
1583 myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
1585 /* Eventually recalculate timing and clock */
1587 if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
1588 var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
1589 sisbios_mode[search_idx].mode_no[ivideo->mni],
1591 sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr,
1592 sisbios_mode[search_idx].mode_no[ivideo->mni],
1594 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1595 var->pixclock <<= 1;
1599 if(ivideo->sisfb_thismonitor.datavalid) {
1600 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
1601 myrateindex, refresh_rate)) {
1603 "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1607 /* Adapt RGB settings */
1608 sisfb_bpp_to_var(ivideo, var);
1610 if(var->xres > var->xres_virtual)
1611 var->xres_virtual = var->xres;
1613 if(ivideo->sisfb_ypan) {
1614 maxyres = sisfb_calc_maxyres(ivideo, var);
1615 if(ivideo->sisfb_max) {
1616 var->yres_virtual = maxyres;
1618 if(var->yres_virtual > maxyres) {
1619 var->yres_virtual = maxyres;
1622 if(var->yres_virtual <= var->yres) {
1623 var->yres_virtual = var->yres;
1626 if(var->yres != var->yres_virtual) {
1627 var->yres_virtual = var->yres;
1633 /* Truncate offsets to maximum if too high */
1634 if(var->xoffset > var->xres_virtual - var->xres) {
1635 var->xoffset = var->xres_virtual - var->xres - 1;
1638 if(var->yoffset > var->yres_virtual - var->yres) {
1639 var->yoffset = var->yres_virtual - var->yres - 1;
1642 /* Set everything else to 0 */
1643 var->red.msb_right =
1644 var->green.msb_right =
1645 var->blue.msb_right =
1646 var->transp.offset =
1647 var->transp.length =
1648 var->transp.msb_right = 0;
1654 sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
1656 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1659 if (var->vmode & FB_VMODE_YWRAP)
1662 if (var->xoffset + info->var.xres > info->var.xres_virtual ||
1663 var->yoffset + info->var.yres > info->var.yres_virtual)
1666 err = sisfb_pan_var(ivideo, info, var);
1670 info->var.xoffset = var->xoffset;
1671 info->var.yoffset = var->yoffset;
1677 sisfb_blank(int blank, struct fb_info *info)
1679 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1681 return sisfb_myblank(ivideo, blank);
1684 /* ----------- FBDev related routines for all series ---------- */
1686 static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
1689 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1690 struct sis_memreq sismemreq;
1691 struct fb_vblank sisvbblank;
1696 u32 __user *argp = (u32 __user *)arg;
1700 if(!capable(CAP_SYS_RAWIO))
1703 if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))
1706 sis_malloc(&sismemreq);
1708 if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
1709 sis_free((u32)sismemreq.offset);
1715 if(!capable(CAP_SYS_RAWIO))
1718 if(get_user(gpu32, argp))
1724 case FBIOGET_VBLANK:
1726 memset(&sisvbblank, 0, sizeof(struct fb_vblank));
1728 sisvbblank.count = 0;
1729 sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
1731 if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))
1736 case SISFB_GET_INFO_SIZE:
1737 return put_user(sizeof(struct sisfb_info), argp);
1739 case SISFB_GET_INFO_OLD:
1740 if(ivideo->warncount++ < 10)
1742 "sisfb: Deprecated ioctl call received - update your application!\n");
1744 case SISFB_GET_INFO: /* For communication with X driver */
1745 ivideo->sisfb_infoblock.sisfb_id = SISFB_ID;
1746 ivideo->sisfb_infoblock.sisfb_version = VER_MAJOR;
1747 ivideo->sisfb_infoblock.sisfb_revision = VER_MINOR;
1748 ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;
1749 ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;
1750 ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;
1751 ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;
1752 ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;
1753 if(ivideo->modechanged) {
1754 ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;
1756 ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;
1758 ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;
1759 ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;
1760 ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;
1761 ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;
1762 ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;
1763 ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;
1764 ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;
1765 ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;
1766 ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;
1767 ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;
1768 ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
1769 ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
1770 ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
1771 ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
1772 ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
1773 ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
1774 ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
1775 ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
1776 ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
1777 ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
1778 ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;
1779 ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;
1780 ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;
1781 ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;
1782 ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;
1783 ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;
1784 ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;
1785 ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;
1787 if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,
1788 sizeof(ivideo->sisfb_infoblock)))
1793 case SISFB_GET_VBRSTATUS_OLD:
1794 if(ivideo->warncount++ < 10)
1796 "sisfb: Deprecated ioctl call received - update your application!\n");
1798 case SISFB_GET_VBRSTATUS:
1799 if(sisfb_CheckVBRetrace(ivideo))
1800 return put_user((u32)1, argp);
1802 return put_user((u32)0, argp);
1804 case SISFB_GET_AUTOMAXIMIZE_OLD:
1805 if(ivideo->warncount++ < 10)
1807 "sisfb: Deprecated ioctl call received - update your application!\n");
1809 case SISFB_GET_AUTOMAXIMIZE:
1810 if(ivideo->sisfb_max)
1811 return put_user((u32)1, argp);
1813 return put_user((u32)0, argp);
1815 case SISFB_SET_AUTOMAXIMIZE_OLD:
1816 if(ivideo->warncount++ < 10)
1818 "sisfb: Deprecated ioctl call received - update your application!\n");
1820 case SISFB_SET_AUTOMAXIMIZE:
1821 if(get_user(gpu32, argp))
1824 ivideo->sisfb_max = (gpu32) ? 1 : 0;
1827 case SISFB_SET_TVPOSOFFSET:
1828 if(get_user(gpu32, argp))
1831 sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
1832 sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
1835 case SISFB_GET_TVPOSOFFSET:
1836 return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
1840 if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,
1841 sizeof(struct sisfb_cmd)))
1844 sisfb_handle_command(ivideo, &ivideo->sisfb_command);
1846 if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,
1847 sizeof(struct sisfb_cmd)))
1852 case SISFB_SET_LOCK:
1853 if(get_user(gpu32, argp))
1856 ivideo->sisfblocked = (gpu32) ? 1 : 0;
1860 #ifdef SIS_NEW_CONFIG_COMPAT
1861 return -ENOIOCTLCMD;
1870 sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
1872 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1874 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1876 strscpy(fix->id, ivideo->myid, sizeof(fix->id));
1878 mutex_lock(&info->mm_lock);
1879 fix->smem_start = ivideo->video_base + ivideo->video_offset;
1880 fix->smem_len = ivideo->sisfb_mem;
1881 mutex_unlock(&info->mm_lock);
1882 fix->type = FB_TYPE_PACKED_PIXELS;
1884 fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
1886 fix->ypanstep = (ivideo->sisfb_ypan) ? 1 : 0;
1888 fix->line_length = ivideo->video_linelength;
1889 fix->mmio_start = ivideo->mmio_base;
1890 fix->mmio_len = ivideo->mmio_size;
1891 if(ivideo->sisvga_engine == SIS_300_VGA) {
1892 fix->accel = FB_ACCEL_SIS_GLAMOUR;
1893 } else if((ivideo->chip == SIS_330) ||
1894 (ivideo->chip == SIS_760) ||
1895 (ivideo->chip == SIS_761)) {
1896 fix->accel = FB_ACCEL_SIS_XABRE;
1897 } else if(ivideo->chip == XGI_20) {
1898 fix->accel = FB_ACCEL_XGI_VOLARI_Z;
1899 } else if(ivideo->chip >= XGI_40) {
1900 fix->accel = FB_ACCEL_XGI_VOLARI_V;
1902 fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
1908 /* ---------------- fb_ops structures ----------------- */
1910 static const struct fb_ops sisfb_ops = {
1911 .owner = THIS_MODULE,
1912 .fb_open = sisfb_open,
1913 .fb_release = sisfb_release,
1914 .fb_check_var = sisfb_check_var,
1915 .fb_set_par = sisfb_set_par,
1916 .fb_setcolreg = sisfb_setcolreg,
1917 .fb_pan_display = sisfb_pan_display,
1918 .fb_blank = sisfb_blank,
1919 .fb_fillrect = fbcon_sis_fillrect,
1920 .fb_copyarea = fbcon_sis_copyarea,
1921 .fb_imageblit = cfb_imageblit,
1922 .fb_sync = fbcon_sis_sync,
1923 #ifdef SIS_NEW_CONFIG_COMPAT
1924 .fb_compat_ioctl= sisfb_ioctl,
1926 .fb_ioctl = sisfb_ioctl
1929 /* ---------------- Chip generation dependent routines ---------------- */
1931 static struct pci_dev *sisfb_get_northbridge(int basechipid)
1933 struct pci_dev *pdev = NULL;
1934 int nbridgenum, nbridgeidx, i;
1935 static const unsigned short nbridgeids[] = {
1936 PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */
1937 PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */
1938 PCI_DEVICE_ID_SI_730,
1939 PCI_DEVICE_ID_SI_550, /* for SiS 550 VGA */
1940 PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */
1941 PCI_DEVICE_ID_SI_651,
1942 PCI_DEVICE_ID_SI_740,
1943 PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760/761 VGA */
1944 PCI_DEVICE_ID_SI_741,
1945 PCI_DEVICE_ID_SI_660,
1946 PCI_DEVICE_ID_SI_760,
1947 PCI_DEVICE_ID_SI_761
1950 switch(basechipid) {
1951 #ifdef CONFIG_FB_SIS_300
1952 case SIS_540: nbridgeidx = 0; nbridgenum = 1; break;
1953 case SIS_630: nbridgeidx = 1; nbridgenum = 2; break;
1955 #ifdef CONFIG_FB_SIS_315
1956 case SIS_550: nbridgeidx = 3; nbridgenum = 1; break;
1957 case SIS_650: nbridgeidx = 4; nbridgenum = 3; break;
1958 case SIS_660: nbridgeidx = 7; nbridgenum = 5; break;
1960 default: return NULL;
1962 for(i = 0; i < nbridgenum; i++) {
1963 if((pdev = pci_get_device(PCI_VENDOR_ID_SI,
1964 nbridgeids[nbridgeidx+i], NULL)))
1970 static int sisfb_get_dram_size(struct sis_video_info *ivideo)
1972 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1976 ivideo->video_size = 0;
1977 ivideo->UMAsize = ivideo->LFBsize = 0;
1979 switch(ivideo->chip) {
1980 #ifdef CONFIG_FB_SIS_300
1982 reg = SiS_GetReg(SISSR, 0x14);
1983 ivideo->video_size = ((reg & 0x3F) + 1) << 20;
1988 if(!ivideo->nbridge)
1990 pci_read_config_byte(ivideo->nbridge, 0x63, ®);
1991 ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
1994 #ifdef CONFIG_FB_SIS_315
1998 reg = SiS_GetReg(SISSR, 0x14);
1999 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2000 switch((reg >> 2) & 0x03) {
2003 ivideo->video_size <<= 1;
2006 ivideo->video_size += (ivideo->video_size/2);
2010 reg = SiS_GetReg(SISSR, 0x14);
2011 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2012 if(reg & 0x0c) ivideo->video_size <<= 1;
2017 reg = SiS_GetReg(SISSR, 0x14);
2018 ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
2022 reg = SiS_GetReg(SISCR, 0x79);
2023 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2028 reg = SiS_GetReg(SISCR, 0x79);
2029 reg = (reg & 0xf0) >> 4;
2031 ivideo->video_size = (1 << reg) << 20;
2032 ivideo->UMAsize = ivideo->video_size;
2034 reg = SiS_GetReg(SISCR, 0x78);
2038 ivideo->LFBsize = (32 << 20);
2040 ivideo->LFBsize = (64 << 20);
2042 ivideo->video_size += ivideo->LFBsize;
2048 reg = SiS_GetReg(SISSR, 0x14);
2049 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2050 if(ivideo->chip != XGI_20) {
2051 reg = (reg & 0x0c) >> 2;
2052 if(ivideo->revision_id == 2) {
2053 if(reg & 0x01) reg = 0x02;
2056 if(reg == 0x02) ivideo->video_size <<= 1;
2057 else if(reg == 0x03) ivideo->video_size <<= 2;
2067 /* -------------- video bridge device detection --------------- */
2069 static void sisfb_detect_VB_connect(struct sis_video_info *ivideo)
2073 /* No CRT2 on XGI Z7 */
2074 if(ivideo->chip == XGI_20) {
2075 ivideo->sisfb_crt1off = 0;
2079 #ifdef CONFIG_FB_SIS_300
2080 if(ivideo->sisvga_engine == SIS_300_VGA) {
2081 temp = SiS_GetReg(SISSR, 0x17);
2082 if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
2083 /* PAL/NTSC is stored on SR16 on such machines */
2084 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
2085 temp = SiS_GetReg(SISSR, 0x16);
2087 ivideo->vbflags |= TV_PAL;
2089 ivideo->vbflags |= TV_NTSC;
2095 cr32 = SiS_GetReg(SISCR, 0x32);
2097 if(cr32 & SIS_CRT1) {
2098 ivideo->sisfb_crt1off = 0;
2100 ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0;
2103 ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
2105 if(cr32 & SIS_VB_TV) ivideo->vbflags |= CRT2_TV;
2106 if(cr32 & SIS_VB_LCD) ivideo->vbflags |= CRT2_LCD;
2107 if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA;
2109 /* Check given parms for hardware compatibility.
2110 * (Cannot do this in the search_xx routines since we don't
2111 * know what hardware we are running on then)
2114 if(ivideo->chip != SIS_550) {
2115 ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0;
2118 if(ivideo->sisfb_tvplug != -1) {
2119 if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2120 (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) {
2121 if(ivideo->sisfb_tvplug & TV_YPBPR) {
2122 ivideo->sisfb_tvplug = -1;
2123 printk(KERN_ERR "sisfb: YPbPr not supported\n");
2127 if(ivideo->sisfb_tvplug != -1) {
2128 if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2129 (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) {
2130 if(ivideo->sisfb_tvplug & TV_HIVISION) {
2131 ivideo->sisfb_tvplug = -1;
2132 printk(KERN_ERR "sisfb: HiVision not supported\n");
2136 if(ivideo->sisfb_tvstd != -1) {
2137 if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
2138 (!((ivideo->sisvga_engine == SIS_315_VGA) &&
2139 (ivideo->vbflags2 & VB2_CHRONTEL))) ) {
2140 if(ivideo->sisfb_tvstd & (TV_PALM | TV_PALN | TV_NTSCJ)) {
2141 ivideo->sisfb_tvstd = -1;
2142 printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
2147 /* Detect/set TV plug & type */
2148 if(ivideo->sisfb_tvplug != -1) {
2149 ivideo->vbflags |= ivideo->sisfb_tvplug;
2151 if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
2152 else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION;
2153 else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART;
2155 if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO;
2156 if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
2160 if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) {
2161 if(ivideo->sisfb_tvstd != -1) {
2162 ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ);
2163 ivideo->vbflags |= ivideo->sisfb_tvstd;
2165 if(ivideo->vbflags & TV_SCART) {
2166 ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ);
2167 ivideo->vbflags |= TV_PAL;
2169 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
2170 if(ivideo->sisvga_engine == SIS_300_VGA) {
2171 temp = SiS_GetReg(SISSR, 0x38);
2172 if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2173 else ivideo->vbflags |= TV_NTSC;
2174 } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
2175 temp = SiS_GetReg(SISSR, 0x38);
2176 if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2177 else ivideo->vbflags |= TV_NTSC;
2179 temp = SiS_GetReg(SISCR, 0x79);
2180 if(temp & 0x20) ivideo->vbflags |= TV_PAL;
2181 else ivideo->vbflags |= TV_NTSC;
2186 /* Copy forceCRT1 option to CRT1off if option is given */
2187 if(ivideo->sisfb_forcecrt1 != -1) {
2188 ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
2192 /* ------------------ Sensing routines ------------------ */
2194 static bool sisfb_test_DDC1(struct sis_video_info *ivideo)
2199 old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
2201 if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
2203 return (count != -1);
2206 static void sisfb_sense_crt1(struct sis_video_info *ivideo)
2208 bool mustwait = false;
2210 #ifdef CONFIG_FB_SIS_315
2216 sr1F = SiS_GetReg(SISSR, 0x1F);
2217 SiS_SetRegOR(SISSR, 0x1F, 0x04);
2218 SiS_SetRegAND(SISSR, 0x1F, 0x3F);
2223 #ifdef CONFIG_FB_SIS_315
2224 if (ivideo->sisvga_engine == SIS_315_VGA) {
2225 cr63 = SiS_GetReg(SISCR, ivideo->SiS_Pr.SiS_MyCR63);
2227 SiS_SetRegAND(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF);
2231 cr17 = SiS_GetReg(SISCR, 0x17);
2235 SiS_SetRegOR(SISCR, 0x17, 0x80);
2237 SiS_SetReg(SISSR, 0x00, 0x01);
2238 SiS_SetReg(SISSR, 0x00, 0x03);
2242 for (i = 0; i < 10; i++)
2243 sisfbwaitretracecrt1(ivideo);
2245 #ifdef CONFIG_FB_SIS_315
2246 if (ivideo->chip >= SIS_330) {
2247 SiS_SetRegAND(SISCR, 0x32, ~0x20);
2248 if (ivideo->chip >= SIS_340)
2249 SiS_SetReg(SISCR, 0x57, 0x4a);
2251 SiS_SetReg(SISCR, 0x57, 0x5f);
2253 SiS_SetRegOR(SISCR, 0x53, 0x02);
2254 while ((SiS_GetRegByte(SISINPSTAT)) & 0x01)
2256 while (!((SiS_GetRegByte(SISINPSTAT)) & 0x01))
2258 if ((SiS_GetRegByte(SISMISCW)) & 0x10)
2261 SiS_SetRegAND(SISCR, 0x53, 0xfd);
2262 SiS_SetRegAND(SISCR, 0x57, 0x00);
2266 if (temp == 0xffff) {
2270 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2271 ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
2272 } while (((temp == 0) || (temp == 0xffff)) && i--);
2274 if ((temp == 0) || (temp == 0xffff)) {
2275 if (sisfb_test_DDC1(ivideo))
2280 if ((temp) && (temp != 0xffff))
2281 SiS_SetRegOR(SISCR, 0x32, 0x20);
2283 #ifdef CONFIG_FB_SIS_315
2284 if (ivideo->sisvga_engine == SIS_315_VGA)
2285 SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF, cr63);
2288 SiS_SetRegANDOR(SISCR, 0x17, 0x7F, cr17);
2289 SiS_SetReg(SISSR, 0x1F, sr1F);
2292 /* Determine and detect attached devices on SiS30x */
2293 static void SiS_SenseLCD(struct sis_video_info *ivideo)
2295 unsigned char buffer[256];
2296 unsigned short temp, realcrtno, i;
2297 u8 reg, cr37 = 0, paneltype = 0;
2300 ivideo->SiS_Pr.PanelSelfDetected = false;
2302 /* LCD detection only for TMDS bridges */
2303 if (!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
2305 if (ivideo->vbflags2 & VB2_30xBDH)
2308 /* If LCD already set up by BIOS, skip it */
2309 reg = SiS_GetReg(SISCR, 0x32);
2314 if (ivideo->SiS_Pr.DDCPortMixup)
2317 /* Check DDC capabilities */
2318 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
2319 realcrtno, 0, &buffer[0], ivideo->vbflags2);
2321 if ((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
2325 i = 3; /* Number of retrys */
2327 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2328 ivideo->sisvga_engine, realcrtno, 1,
2329 &buffer[0], ivideo->vbflags2);
2330 } while ((temp) && i--);
2335 /* No digital device */
2336 if (!(buffer[0x14] & 0x80))
2339 /* First detailed timing preferred timing? */
2340 if (!(buffer[0x18] & 0x02))
2343 xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
2344 yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
2356 if ((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
2367 if ((buffer[0x47] & 0x18) == 0x18)
2368 cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2372 SiS_SetReg(SISCR, 0x36, paneltype);
2374 SiS_SetRegANDOR(SISCR, 0x37, 0x0c, cr37);
2375 SiS_SetRegOR(SISCR, 0x32, 0x08);
2377 ivideo->SiS_Pr.PanelSelfDetected = true;
2380 static int SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
2382 int temp, mytest, result, i, j;
2384 for (j = 0; j < 10; j++) {
2386 for (i = 0; i < 3; i++) {
2388 SiS_SetReg(SISPART4, 0x11, (type & 0x00ff));
2389 temp = (type >> 8) | (mytest & 0x00ff);
2390 SiS_SetRegANDOR(SISPART4, 0x10, 0xe0, temp);
2391 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
2394 temp = SiS_GetReg(SISPART4, 0x03);
2400 SiS_SetReg(SISPART4, 0x11, 0x00);
2401 SiS_SetRegAND(SISPART4, 0x10, 0xe0);
2402 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
2406 if ((result == 0) || (result >= 2))
2412 static void SiS_Sense30x(struct sis_video_info *ivideo)
2414 u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
2415 u16 svhs=0, svhs_c=0;
2416 u16 cvbs=0, cvbs_c=0;
2417 u16 vga2=0, vga2_c=0;
2419 char stdstr[] = "sisfb: Detected";
2420 char tvstr[] = "TV connected to";
2422 if(ivideo->vbflags2 & VB2_301) {
2423 svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
2424 myflag = SiS_GetReg(SISPART4, 0x01);
2426 svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
2428 } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) {
2429 svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
2430 } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) {
2431 svhs = 0x0200; cvbs = 0x0100;
2432 } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
2433 svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
2437 vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
2438 if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
2439 svhs_c = 0x0408; cvbs_c = 0x0808;
2443 if(ivideo->haveXGIROM) {
2444 biosflag = ivideo->bios_abase[0x58] & 0x03;
2445 } else if(ivideo->newrom) {
2446 if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01;
2447 } else if(ivideo->sisvga_engine == SIS_300_VGA) {
2448 if(ivideo->bios_abase) {
2449 biosflag = ivideo->bios_abase[0xfe] & 0x03;
2453 if(ivideo->chip == SIS_300) {
2454 myflag = SiS_GetReg(SISSR, 0x3b);
2455 if(!(myflag & 0x01)) vga2 = vga2_c = 0;
2458 if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) {
2462 backupSR_1e = SiS_GetReg(SISSR, 0x1e);
2463 SiS_SetRegOR(SISSR, 0x1e, 0x20);
2465 backupP4_0d = SiS_GetReg(SISPART4, 0x0d);
2466 if(ivideo->vbflags2 & VB2_30xC) {
2467 SiS_SetRegANDOR(SISPART4, 0x0d, ~0x07, 0x01);
2469 SiS_SetRegOR(SISPART4, 0x0d, 0x04);
2471 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2473 backupP2_00 = SiS_GetReg(SISPART2, 0x00);
2474 SiS_SetReg(SISPART2, 0x00, ((backupP2_00 | 0x1c) & 0xfc));
2476 backupP2_4d = SiS_GetReg(SISPART2, 0x4d);
2477 if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
2478 SiS_SetReg(SISPART2, 0x4d, (backupP2_4d & ~0x10));
2481 if(!(ivideo->vbflags2 & VB2_30xCLV)) {
2482 SISDoSense(ivideo, 0, 0);
2485 SiS_SetRegAND(SISCR, 0x32, ~0x14);
2487 if(vga2_c || vga2) {
2488 if(SISDoSense(ivideo, vga2, vga2_c)) {
2489 if(biosflag & 0x01) {
2490 printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
2491 SiS_SetRegOR(SISCR, 0x32, 0x04);
2493 printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
2494 SiS_SetRegOR(SISCR, 0x32, 0x10);
2499 SiS_SetRegAND(SISCR, 0x32, 0x3f);
2501 if(ivideo->vbflags2 & VB2_30xCLV) {
2502 SiS_SetRegOR(SISPART4, 0x0d, 0x04);
2505 if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
2506 SiS_SetReg(SISPART2, 0x4d, (backupP2_4d | 0x10));
2507 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2508 if((result = SISDoSense(ivideo, svhs, 0x0604))) {
2509 if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
2510 printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
2511 SiS_SetRegOR(SISCR, 0x32, 0x80);
2514 SiS_SetReg(SISPART2, 0x4d, backupP2_4d);
2517 SiS_SetRegAND(SISCR, 0x32, ~0x03);
2519 if(!(ivideo->vbflags & TV_YPBPR)) {
2520 if((result = SISDoSense(ivideo, svhs, svhs_c))) {
2521 printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
2522 SiS_SetRegOR(SISCR, 0x32, 0x02);
2524 if((biosflag & 0x02) || (!result)) {
2525 if(SISDoSense(ivideo, cvbs, cvbs_c)) {
2526 printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
2527 SiS_SetRegOR(SISCR, 0x32, 0x01);
2532 SISDoSense(ivideo, 0, 0);
2534 SiS_SetReg(SISPART2, 0x00, backupP2_00);
2535 SiS_SetReg(SISPART4, 0x0d, backupP4_0d);
2536 SiS_SetReg(SISSR, 0x1e, backupSR_1e);
2538 if(ivideo->vbflags2 & VB2_30xCLV) {
2539 biosflag = SiS_GetReg(SISPART2, 0x00);
2540 if(biosflag & 0x20) {
2541 for(myflag = 2; myflag > 0; myflag--) {
2543 SiS_SetReg(SISPART2, 0x00, biosflag);
2548 SiS_SetReg(SISPART2, 0x00, backupP2_00);
2551 /* Determine and detect attached TV's on Chrontel */
2552 static void SiS_SenseCh(struct sis_video_info *ivideo)
2554 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2556 char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
2558 #ifdef CONFIG_FB_SIS_300
2559 unsigned char test[3];
2563 if(ivideo->chip < SIS_315H) {
2565 #ifdef CONFIG_FB_SIS_300
2566 ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1; /* Chrontel 700x */
2567 SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c); /* Set general purpose IO for Chrontel communication */
2568 SiS_DDC2Delay(&ivideo->SiS_Pr, 1000);
2569 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2570 /* See Chrontel TB31 for explanation */
2571 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2572 if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
2573 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b);
2574 SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2576 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2577 if(temp2 != temp1) temp1 = temp2;
2579 if((temp1 >= 0x22) && (temp1 <= 0x50)) {
2580 /* Read power status */
2581 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2582 if((temp1 & 0x03) != 0x03) {
2583 /* Power all outputs */
2584 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b);
2585 SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2587 /* Sense connected TV devices */
2588 for(i = 0; i < 3; i++) {
2589 SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01);
2590 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2591 SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00);
2592 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2593 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
2594 if(!(temp1 & 0x08)) test[i] = 0x02;
2595 else if(!(temp1 & 0x02)) test[i] = 0x01;
2597 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2600 if(test[0] == test[1]) temp1 = test[0];
2601 else if(test[0] == test[2]) temp1 = test[0];
2602 else if(test[1] == test[2]) temp1 = test[1];
2605 "sisfb: TV detection unreliable - test results varied\n");
2609 printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2610 ivideo->vbflags |= TV_SVIDEO;
2611 SiS_SetRegOR(SISCR, 0x32, 0x02);
2612 SiS_SetRegAND(SISCR, 0x32, ~0x05);
2613 } else if (temp1 == 0x01) {
2614 printk(KERN_INFO "%s CVBS output\n", stdstr);
2615 ivideo->vbflags |= TV_AVIDEO;
2616 SiS_SetRegOR(SISCR, 0x32, 0x01);
2617 SiS_SetRegAND(SISCR, 0x32, ~0x06);
2619 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2620 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2622 } else if(temp1 == 0) {
2623 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2624 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2626 /* Set general purpose IO for Chrontel communication */
2627 SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
2632 #ifdef CONFIG_FB_SIS_315
2633 ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */
2634 temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
2635 SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20);
2636 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2637 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2639 SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2640 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2642 SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2643 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2644 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2645 SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1);
2647 if(temp2 & 0x02) temp1 |= 0x01;
2648 if(temp2 & 0x10) temp1 |= 0x01;
2649 if(temp2 & 0x04) temp1 |= 0x02;
2650 if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
2653 printk(KERN_INFO "%s CVBS output\n", stdstr);
2654 ivideo->vbflags |= TV_AVIDEO;
2655 SiS_SetRegOR(SISCR, 0x32, 0x01);
2656 SiS_SetRegAND(SISCR, 0x32, ~0x06);
2659 printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2660 ivideo->vbflags |= TV_SVIDEO;
2661 SiS_SetRegOR(SISCR, 0x32, 0x02);
2662 SiS_SetRegAND(SISCR, 0x32, ~0x05);
2665 printk(KERN_INFO "%s SCART output\n", stdstr);
2666 SiS_SetRegOR(SISCR, 0x32, 0x04);
2667 SiS_SetRegAND(SISCR, 0x32, ~0x03);
2670 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2676 static void sisfb_get_VB_type(struct sis_video_info *ivideo)
2678 char stdstr[] = "sisfb: Detected";
2679 char bridgestr[] = "video bridge";
2683 /* No CRT2 on XGI Z7 */
2684 if(ivideo->chip == XGI_20)
2687 vb_chipid = SiS_GetReg(SISPART4, 0x00);
2690 reg = SiS_GetReg(SISPART4, 0x01);
2692 ivideo->vbflags |= VB_301; /* Deprecated */
2693 ivideo->vbflags2 |= VB2_301;
2694 printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
2695 } else if(reg < 0xc0) {
2696 ivideo->vbflags |= VB_301B; /* Deprecated */
2697 ivideo->vbflags2 |= VB2_301B;
2698 reg = SiS_GetReg(SISPART4, 0x23);
2700 ivideo->vbflags |= VB_30xBDH; /* Deprecated */
2701 ivideo->vbflags2 |= VB2_30xBDH;
2702 printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
2704 printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
2706 } else if(reg < 0xd0) {
2707 ivideo->vbflags |= VB_301C; /* Deprecated */
2708 ivideo->vbflags2 |= VB2_301C;
2709 printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
2710 } else if(reg < 0xe0) {
2711 ivideo->vbflags |= VB_301LV; /* Deprecated */
2712 ivideo->vbflags2 |= VB2_301LV;
2713 printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
2714 } else if(reg <= 0xe1) {
2715 reg = SiS_GetReg(SISPART4, 0x39);
2717 ivideo->vbflags |= VB_302LV; /* Deprecated */
2718 ivideo->vbflags2 |= VB2_302LV;
2719 printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
2721 ivideo->vbflags |= VB_301C; /* Deprecated */
2722 ivideo->vbflags2 |= VB2_301C;
2723 printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
2725 ivideo->vbflags |= VB_302ELV; /* Deprecated */
2726 ivideo->vbflags2 |= VB2_302ELV;
2727 printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
2733 ivideo->vbflags |= VB_302B; /* Deprecated */
2734 ivideo->vbflags2 |= VB2_302B;
2735 printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
2739 if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
2740 reg = SiS_GetReg(SISCR, 0x37);
2741 reg &= SIS_EXTERNAL_CHIP_MASK;
2743 if(ivideo->sisvga_engine == SIS_300_VGA) {
2744 #ifdef CONFIG_FB_SIS_300
2746 case SIS_EXTERNAL_CHIP_LVDS:
2747 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2748 ivideo->vbflags2 |= VB2_LVDS;
2750 case SIS_EXTERNAL_CHIP_TRUMPION:
2751 ivideo->vbflags |= (VB_LVDS | VB_TRUMPION); /* Deprecated */
2752 ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION);
2754 case SIS_EXTERNAL_CHIP_CHRONTEL:
2755 ivideo->vbflags |= VB_CHRONTEL; /* Deprecated */
2756 ivideo->vbflags2 |= VB2_CHRONTEL;
2758 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
2759 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2760 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2763 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1;
2765 } else if(ivideo->chip < SIS_661) {
2766 #ifdef CONFIG_FB_SIS_315
2768 case SIS310_EXTERNAL_CHIP_LVDS:
2769 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2770 ivideo->vbflags2 |= VB2_LVDS;
2772 case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
2773 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2774 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2777 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2779 } else if(ivideo->chip >= SIS_661) {
2780 #ifdef CONFIG_FB_SIS_315
2781 reg = SiS_GetReg(SISCR, 0x38);
2785 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2786 ivideo->vbflags2 |= VB2_LVDS;
2789 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2790 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2793 ivideo->vbflags |= (VB_LVDS | VB_CONEXANT); /* Deprecated */
2794 ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT);
2797 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2800 if(ivideo->vbflags2 & VB2_LVDS) {
2801 printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
2803 if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) {
2804 printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
2806 if(ivideo->vbflags2 & VB2_CHRONTEL) {
2807 printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
2809 if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) {
2810 printk(KERN_INFO "%s Conexant external device\n", stdstr);
2814 if(ivideo->vbflags2 & VB2_SISBRIDGE) {
2815 SiS_SenseLCD(ivideo);
2816 SiS_Sense30x(ivideo);
2817 } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
2818 SiS_SenseCh(ivideo);
2822 /* ---------- Engine initialization routines ------------ */
2825 sisfb_engine_init(struct sis_video_info *ivideo)
2828 /* Initialize command queue (we use MMIO only) */
2830 /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
2832 ivideo->caps &= ~(TURBO_QUEUE_CAP |
2833 MMIO_CMD_QUEUE_CAP |
2837 #ifdef CONFIG_FB_SIS_300
2838 if(ivideo->sisvga_engine == SIS_300_VGA) {
2842 tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
2844 tq_state = SiS_GetReg(SISSR, IND_SIS_TURBOQUEUE_SET);
2847 tq_state |= (u8)(tqueue_pos >> 8);
2848 SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
2850 SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
2852 ivideo->caps |= TURBO_QUEUE_CAP;
2856 #ifdef CONFIG_FB_SIS_315
2857 if(ivideo->sisvga_engine == SIS_315_VGA) {
2858 u32 tempq = 0, templ;
2861 if(ivideo->chip == XGI_20) {
2862 switch(ivideo->cmdQueueSize) {
2864 temp = SIS_CMD_QUEUE_SIZE_Z7_64k;
2868 temp = SIS_CMD_QUEUE_SIZE_Z7_128k;
2871 switch(ivideo->cmdQueueSize) {
2872 case (4 * 1024 * 1024):
2873 temp = SIS_CMD_QUEUE_SIZE_4M;
2875 case (2 * 1024 * 1024):
2876 temp = SIS_CMD_QUEUE_SIZE_2M;
2878 case (1 * 1024 * 1024):
2879 temp = SIS_CMD_QUEUE_SIZE_1M;
2883 temp = SIS_CMD_QUEUE_SIZE_512k;
2887 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2888 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2890 if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
2891 /* Must disable dual pipe on XGI_40. Can't do
2892 * this in MMIO mode, because it requires
2893 * setting/clearing a bit in the MMIO fire trigger
2896 if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) {
2898 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
2900 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
2902 tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
2903 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
2905 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2906 MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq);
2908 writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq);
2909 writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4);
2910 writel(0x168F0000, ivideo->video_vbase + tempq + 8);
2911 writel(0x168F0000, ivideo->video_vbase + tempq + 12);
2913 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16));
2915 sisfb_syncaccel(ivideo);
2917 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2922 tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
2923 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
2925 temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
2926 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, temp);
2928 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2929 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
2931 ivideo->caps |= MMIO_CMD_QUEUE_CAP;
2935 ivideo->engineok = 1;
2938 static void sisfb_detect_lcd_type(struct sis_video_info *ivideo)
2943 reg = SiS_GetReg(SISCR, 0x36);
2945 if(ivideo->sisvga_engine == SIS_300_VGA) {
2946 ivideo->CRT2LCDType = sis300paneltype[reg];
2947 } else if(ivideo->chip >= SIS_661) {
2948 ivideo->CRT2LCDType = sis661paneltype[reg];
2950 ivideo->CRT2LCDType = sis310paneltype[reg];
2951 if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
2952 if((ivideo->CRT2LCDType != LCD_320x240_2) &&
2953 (ivideo->CRT2LCDType != LCD_320x240_3)) {
2954 ivideo->CRT2LCDType = LCD_320x240;
2959 if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
2960 /* For broken BIOSes: Assume 1024x768, RGB18 */
2961 ivideo->CRT2LCDType = LCD_1024x768;
2962 SiS_SetRegANDOR(SISCR, 0x36, 0xf0, 0x02);
2963 SiS_SetRegANDOR(SISCR, 0x37, 0xee, 0x01);
2964 printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
2967 for(i = 0; i < SIS_LCD_NUMBER; i++) {
2968 if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
2969 ivideo->lcdxres = sis_lcd_data[i].xres;
2970 ivideo->lcdyres = sis_lcd_data[i].yres;
2971 ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
2976 #ifdef CONFIG_FB_SIS_300
2977 if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
2978 ivideo->lcdxres = 1360; ivideo->lcdyres = 1024;
2979 ivideo->lcddefmodeidx = DEFAULT_MODE_1360;
2980 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
2981 ivideo->lcdxres = 848; ivideo->lcdyres = 480;
2982 ivideo->lcddefmodeidx = DEFAULT_MODE_848;
2983 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) {
2984 ivideo->lcdxres = 856; ivideo->lcdyres = 480;
2985 ivideo->lcddefmodeidx = DEFAULT_MODE_856;
2989 printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
2990 ivideo->lcdxres, ivideo->lcdyres);
2993 static void sisfb_save_pdc_emi(struct sis_video_info *ivideo)
2995 #ifdef CONFIG_FB_SIS_300
2996 /* Save the current PanelDelayCompensation if the LCD is currently used */
2997 if(ivideo->sisvga_engine == SIS_300_VGA) {
2998 if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
3000 tmp = SiS_GetReg(SISCR, 0x30);
3002 /* Currently on LCD? If yes, read current pdc */
3003 ivideo->detectedpdc = SiS_GetReg(SISPART1, 0x13);
3004 ivideo->detectedpdc &= 0x3c;
3005 if(ivideo->SiS_Pr.PDC == -1) {
3006 /* Let option override detection */
3007 ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
3009 printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
3010 ivideo->detectedpdc);
3012 if((ivideo->SiS_Pr.PDC != -1) &&
3013 (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
3014 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
3015 ivideo->SiS_Pr.PDC);
3021 #ifdef CONFIG_FB_SIS_315
3022 if(ivideo->sisvga_engine == SIS_315_VGA) {
3024 /* Try to find about LCDA */
3025 if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
3027 tmp = SiS_GetReg(SISPART1, 0x13);
3029 ivideo->SiS_Pr.SiS_UseLCDA = true;
3030 ivideo->detectedlcda = 0x03;
3035 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
3037 tmp = SiS_GetReg(SISCR, 0x30);
3038 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3039 /* Currently on LCD? If yes, read current pdc */
3041 pdc = SiS_GetReg(SISPART1, 0x2D);
3042 ivideo->detectedpdc = (pdc & 0x0f) << 1;
3043 ivideo->detectedpdca = (pdc & 0xf0) >> 3;
3044 pdc = SiS_GetReg(SISPART1, 0x35);
3045 ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
3046 pdc = SiS_GetReg(SISPART1, 0x20);
3047 ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
3048 if(ivideo->newrom) {
3049 /* New ROM invalidates other PDC resp. */
3050 if(ivideo->detectedlcda != 0xff) {
3051 ivideo->detectedpdc = 0xff;
3053 ivideo->detectedpdca = 0xff;
3056 if(ivideo->SiS_Pr.PDC == -1) {
3057 if(ivideo->detectedpdc != 0xff) {
3058 ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
3061 if(ivideo->SiS_Pr.PDCA == -1) {
3062 if(ivideo->detectedpdca != 0xff) {
3063 ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
3066 if(ivideo->detectedpdc != 0xff) {
3068 "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3069 ivideo->detectedpdc);
3071 if(ivideo->detectedpdca != 0xff) {
3073 "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3074 ivideo->detectedpdca);
3079 if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
3080 ivideo->SiS_Pr.EMI_30 = SiS_GetReg(SISPART4, 0x30);
3081 ivideo->SiS_Pr.EMI_31 = SiS_GetReg(SISPART4, 0x31);
3082 ivideo->SiS_Pr.EMI_32 = SiS_GetReg(SISPART4, 0x32);
3083 ivideo->SiS_Pr.EMI_33 = SiS_GetReg(SISPART4, 0x33);
3084 ivideo->SiS_Pr.HaveEMI = true;
3085 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3086 ivideo->SiS_Pr.HaveEMILCD = true;
3091 /* Let user override detected PDCs (all bridges) */
3092 if(ivideo->vbflags2 & VB2_30xBLV) {
3093 if((ivideo->SiS_Pr.PDC != -1) &&
3094 (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
3095 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3096 ivideo->SiS_Pr.PDC);
3098 if((ivideo->SiS_Pr.PDCA != -1) &&
3099 (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
3100 printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3101 ivideo->SiS_Pr.PDCA);
3109 /* -------------------- Memory manager routines ---------------------- */
3111 static u32 sisfb_getheapstart(struct sis_video_info *ivideo)
3113 u32 ret = ivideo->sisfb_parm_mem * 1024;
3114 u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3117 /* Calculate heap start = end of memory for console
3119 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3120 * C = console, D = heap, H = HWCursor, Q = cmd-queue
3122 * On 76x in UMA+LFB mode, the layout is as follows:
3123 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3124 * where the heap is the entire UMA area, eventually
3125 * into the LFB area if the given mem parameter is
3126 * higher than the size of the UMA memory.
3128 * Basically given by "mem" parameter
3130 * maximum = videosize - cmd_queue - hwcursor
3131 * (results in a heap of size 0)
3132 * default = SiS 300: depends on videosize
3133 * SiS 315/330/340/XGI: 32k below max
3136 if(ivideo->sisvga_engine == SIS_300_VGA) {
3137 if(ivideo->video_size > 0x1000000) {
3139 } else if(ivideo->video_size > 0x800000) {
3144 } else if(ivideo->UMAsize && ivideo->LFBsize) {
3147 def = maxoffs - 0x8000;
3150 /* Use default for secondary card for now (FIXME) */
3151 if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0))
3157 static u32 sisfb_getheapsize(struct sis_video_info *ivideo)
3159 u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3162 if(ivideo->UMAsize && ivideo->LFBsize) {
3163 if( (!ivideo->sisfb_parm_mem) ||
3164 ((ivideo->sisfb_parm_mem * 1024) > max) ||
3165 ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) {
3166 ret = ivideo->UMAsize;
3167 max -= ivideo->UMAsize;
3169 ret = max - (ivideo->sisfb_parm_mem * 1024);
3170 max = ivideo->sisfb_parm_mem * 1024;
3172 ivideo->video_offset = ret;
3173 ivideo->sisfb_mem = max;
3175 ret = max - ivideo->heapstart;
3176 ivideo->sisfb_mem = ivideo->heapstart;
3182 static int sisfb_heap_init(struct sis_video_info *ivideo)
3186 ivideo->video_offset = 0;
3187 if(ivideo->sisfb_parm_mem) {
3188 if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) ||
3189 (ivideo->sisfb_parm_mem > ivideo->video_size) ) {
3190 ivideo->sisfb_parm_mem = 0;
3194 ivideo->heapstart = sisfb_getheapstart(ivideo);
3195 ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo);
3197 ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
3198 ivideo->sisfb_heap_end = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size;
3200 printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
3201 (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
3203 ivideo->sisfb_heap.vinfo = ivideo;
3205 ivideo->sisfb_heap.poha_chain = NULL;
3206 ivideo->sisfb_heap.poh_freelist = NULL;
3208 poh = sisfb_poh_new_node(&ivideo->sisfb_heap);
3212 poh->poh_next = &ivideo->sisfb_heap.oh_free;
3213 poh->poh_prev = &ivideo->sisfb_heap.oh_free;
3214 poh->size = ivideo->sisfb_heap_size;
3215 poh->offset = ivideo->heapstart;
3217 ivideo->sisfb_heap.oh_free.poh_next = poh;
3218 ivideo->sisfb_heap.oh_free.poh_prev = poh;
3219 ivideo->sisfb_heap.oh_free.size = 0;
3220 ivideo->sisfb_heap.max_freesize = poh->size;
3222 ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used;
3223 ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used;
3224 ivideo->sisfb_heap.oh_used.size = SENTINEL;
3226 if(ivideo->cardnumber == 0) {
3227 /* For the first card, make this heap the "global" one
3228 * for old DRM (which could handle only one card)
3230 sisfb_heap = &ivideo->sisfb_heap;
3236 static struct SIS_OH *
3237 sisfb_poh_new_node(struct SIS_HEAP *memheap)
3239 struct SIS_OHALLOC *poha;
3244 if(memheap->poh_freelist == NULL) {
3245 poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
3249 poha->poha_next = memheap->poha_chain;
3250 memheap->poha_chain = poha;
3252 cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1;
3254 poh = &poha->aoh[0];
3255 for(i = cOhs - 1; i != 0; i--) {
3256 poh->poh_next = poh + 1;
3260 poh->poh_next = NULL;
3261 memheap->poh_freelist = &poha->aoh[0];
3264 poh = memheap->poh_freelist;
3265 memheap->poh_freelist = poh->poh_next;
3270 static struct SIS_OH *
3271 sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size)
3273 struct SIS_OH *pohThis;
3274 struct SIS_OH *pohRoot;
3277 if(size > memheap->max_freesize) {
3278 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3279 (unsigned int) size / 1024);
3283 pohThis = memheap->oh_free.poh_next;
3285 while(pohThis != &memheap->oh_free) {
3286 if(size <= pohThis->size) {
3290 pohThis = pohThis->poh_next;
3294 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3295 (unsigned int) size / 1024);
3299 if(size == pohThis->size) {
3301 sisfb_delete_node(pohThis);
3303 pohRoot = sisfb_poh_new_node(memheap);
3307 pohRoot->offset = pohThis->offset;
3308 pohRoot->size = size;
3310 pohThis->offset += size;
3311 pohThis->size -= size;
3314 memheap->max_freesize -= size;
3316 pohThis = &memheap->oh_used;
3317 sisfb_insert_node(pohThis, pohRoot);
3323 sisfb_delete_node(struct SIS_OH *poh)
3325 poh->poh_prev->poh_next = poh->poh_next;
3326 poh->poh_next->poh_prev = poh->poh_prev;
3330 sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh)
3332 struct SIS_OH *pohTemp = pohList->poh_next;
3334 pohList->poh_next = poh;
3335 pohTemp->poh_prev = poh;
3337 poh->poh_prev = pohList;
3338 poh->poh_next = pohTemp;
3341 static struct SIS_OH *
3342 sisfb_poh_free(struct SIS_HEAP *memheap, u32 base)
3344 struct SIS_OH *pohThis;
3345 struct SIS_OH *poh_freed;
3346 struct SIS_OH *poh_prev;
3347 struct SIS_OH *poh_next;
3352 poh_freed = memheap->oh_used.poh_next;
3354 while(poh_freed != &memheap->oh_used) {
3355 if(poh_freed->offset == base) {
3360 poh_freed = poh_freed->poh_next;
3366 memheap->max_freesize += poh_freed->size;
3368 poh_prev = poh_next = NULL;
3369 ulUpper = poh_freed->offset + poh_freed->size;
3370 ulLower = poh_freed->offset;
3372 pohThis = memheap->oh_free.poh_next;
3374 while(pohThis != &memheap->oh_free) {
3375 if(pohThis->offset == ulUpper) {
3377 } else if((pohThis->offset + pohThis->size) == ulLower) {
3380 pohThis = pohThis->poh_next;
3383 sisfb_delete_node(poh_freed);
3385 if(poh_prev && poh_next) {
3386 poh_prev->size += (poh_freed->size + poh_next->size);
3387 sisfb_delete_node(poh_next);
3388 sisfb_free_node(memheap, poh_freed);
3389 sisfb_free_node(memheap, poh_next);
3394 poh_prev->size += poh_freed->size;
3395 sisfb_free_node(memheap, poh_freed);
3400 poh_next->size += poh_freed->size;
3401 poh_next->offset = poh_freed->offset;
3402 sisfb_free_node(memheap, poh_freed);
3406 sisfb_insert_node(&memheap->oh_free, poh_freed);
3412 sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh)
3417 poh->poh_next = memheap->poh_freelist;
3418 memheap->poh_freelist = poh;
3422 sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req)
3424 struct SIS_OH *poh = NULL;
3426 if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap))
3427 poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size);
3430 req->offset = req->size = 0;
3431 DPRINTK("sisfb: Video RAM allocation failed\n");
3433 req->offset = poh->offset;
3434 req->size = poh->size;
3435 DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3436 (poh->offset + ivideo->video_vbase));
3441 sis_malloc(struct sis_memreq *req)
3443 struct sis_video_info *ivideo = sisfb_heap->vinfo;
3445 if(&ivideo->sisfb_heap == sisfb_heap)
3446 sis_int_malloc(ivideo, req);
3448 req->offset = req->size = 0;
3452 sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
3454 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3456 sis_int_malloc(ivideo, req);
3459 /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3462 sis_int_free(struct sis_video_info *ivideo, u32 base)
3466 if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap))
3469 poh = sisfb_poh_free(&ivideo->sisfb_heap, base);
3472 DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
3473 (unsigned int) base);
3480 struct sis_video_info *ivideo = sisfb_heap->vinfo;
3482 sis_int_free(ivideo, base);
3486 sis_free_new(struct pci_dev *pdev, u32 base)
3488 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3490 sis_int_free(ivideo, base);
3493 /* --------------------- SetMode routines ------------------------- */
3496 sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
3500 /* Check if MMIO and engines are enabled,
3501 * and sync in case they are. Can't use
3502 * ivideo->accel here, as this might have
3503 * been changed before this is called.
3505 cr30 = SiS_GetReg(SISSR, IND_SIS_PCI_ADDRESS_SET);
3506 cr31 = SiS_GetReg(SISSR, IND_SIS_MODULE_ENABLE);
3507 /* MMIO and 2D/3D engine enabled? */
3508 if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
3509 #ifdef CONFIG_FB_SIS_300
3510 if(ivideo->sisvga_engine == SIS_300_VGA) {
3511 /* Don't care about TurboQueue. It's
3512 * enough to know that the engines
3515 sisfb_syncaccel(ivideo);
3518 #ifdef CONFIG_FB_SIS_315
3519 if(ivideo->sisvga_engine == SIS_315_VGA) {
3520 /* Check that any queue mode is
3521 * enabled, and that the queue
3522 * is not in the state of "reset"
3524 cr30 = SiS_GetReg(SISSR, 0x26);
3525 if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
3526 sisfb_syncaccel(ivideo);
3534 sisfb_pre_setmode(struct sis_video_info *ivideo)
3536 u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
3539 ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
3541 SiS_SetReg(SISSR, 0x05, 0x86);
3543 cr31 = SiS_GetReg(SISCR, 0x31);
3547 cr33 = ivideo->rate_idx & 0x0F;
3549 #ifdef CONFIG_FB_SIS_315
3550 if(ivideo->sisvga_engine == SIS_315_VGA) {
3551 if(ivideo->chip >= SIS_661) {
3552 cr38 = SiS_GetReg(SISCR, 0x38);
3553 cr38 &= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
3556 cr38 = SiS_GetReg(SISCR, tvregnum);
3557 cr38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
3561 #ifdef CONFIG_FB_SIS_300
3562 if(ivideo->sisvga_engine == SIS_300_VGA) {
3564 cr38 = SiS_GetReg(SISCR, tvregnum);
3568 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
3569 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
3570 ivideo->curFSTN = ivideo->curDSTN = 0;
3572 switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
3575 cr38 &= ~0xc0; /* Clear PAL-M / PAL-N bits */
3576 if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
3577 #ifdef CONFIG_FB_SIS_315
3578 if(ivideo->chip >= SIS_661) {
3580 if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20;
3581 else if(ivideo->vbflags & TV_YPBPR750P) cr35 |= 0x40;
3582 else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
3583 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3585 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3586 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
3587 cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3589 if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10;
3590 else if(ivideo->vbflags & TV_YPBPR750P) cr38 |= 0x20;
3591 else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
3593 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3596 } else if((ivideo->vbflags & TV_HIVISION) &&
3597 (ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) {
3598 if(ivideo->chip >= SIS_661) {
3604 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3607 ivideo->currentvbflags |= TV_HIVISION;
3608 } else if(ivideo->vbflags & TV_SCART) {
3609 cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
3612 ivideo->currentvbflags |= TV_SCART;
3614 if(ivideo->vbflags & TV_SVIDEO) {
3615 cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
3616 ivideo->currentvbflags |= TV_SVIDEO;
3618 if(ivideo->vbflags & TV_AVIDEO) {
3619 cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
3620 ivideo->currentvbflags |= TV_AVIDEO;
3623 cr31 |= SIS_DRIVER_MODE;
3625 if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) {
3626 if(ivideo->vbflags & TV_PAL) {
3627 cr31 |= 0x01; cr35 |= 0x01;
3628 ivideo->currentvbflags |= TV_PAL;
3629 if(ivideo->vbflags & TV_PALM) {
3630 cr38 |= 0x40; cr35 |= 0x04;
3631 ivideo->currentvbflags |= TV_PALM;
3632 } else if(ivideo->vbflags & TV_PALN) {
3633 cr38 |= 0x80; cr35 |= 0x08;
3634 ivideo->currentvbflags |= TV_PALN;
3637 cr31 &= ~0x01; cr35 &= ~0x01;
3638 ivideo->currentvbflags |= TV_NTSC;
3639 if(ivideo->vbflags & TV_NTSCJ) {
3640 cr38 |= 0x40; cr35 |= 0x02;
3641 ivideo->currentvbflags |= TV_NTSCJ;
3648 cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
3649 cr31 |= SIS_DRIVER_MODE;
3650 SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
3651 SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
3652 ivideo->curFSTN = ivideo->sisfb_fstn;
3653 ivideo->curDSTN = ivideo->sisfb_dstn;
3657 cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3658 cr31 |= SIS_DRIVER_MODE;
3659 if(ivideo->sisfb_nocrt2rate) {
3660 cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4);
3662 cr33 |= ((ivideo->rate_idx & 0x0F) << 4);
3666 default: /* disable CRT2 */
3668 cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
3671 SiS_SetReg(SISCR, 0x30, cr30);
3672 SiS_SetReg(SISCR, 0x33, cr33);
3674 if(ivideo->chip >= SIS_661) {
3675 #ifdef CONFIG_FB_SIS_315
3676 cr31 &= ~0x01; /* Clear PAL flag (now in CR35) */
3677 SiS_SetRegANDOR(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
3678 cr38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
3679 SiS_SetRegANDOR(SISCR, 0x38, 0xf8, cr38);
3681 } else if(ivideo->chip != SIS_300) {
3682 SiS_SetReg(SISCR, tvregnum, cr38);
3684 SiS_SetReg(SISCR, 0x31, cr31);
3686 ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
3688 sisfb_check_engine_and_sync(ivideo);
3691 /* Fix SR11 for 661 and later */
3692 #ifdef CONFIG_FB_SIS_315
3694 sisfb_fixup_SR11(struct sis_video_info *ivideo)
3698 if(ivideo->chip >= SIS_661) {
3699 tmpreg = SiS_GetReg(SISSR, 0x11);
3701 tmpreg = SiS_GetReg(SISSR, 0x3e);
3702 tmpreg = (tmpreg + 1) & 0xff;
3703 SiS_SetReg(SISSR, 0x3e, tmpreg);
3704 tmpreg = SiS_GetReg(SISSR, 0x11);
3707 SiS_SetRegAND(SISSR, 0x11, 0x0f);
3714 sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
3716 if(val > 32) val = 32;
3717 if(val < -32) val = -32;
3718 ivideo->tvxpos = val;
3720 if(ivideo->sisfblocked) return;
3721 if(!ivideo->modechanged) return;
3723 if(ivideo->currentvbflags & CRT2_TV) {
3725 if(ivideo->vbflags2 & VB2_CHRONTEL) {
3727 int x = ivideo->tvx;
3729 switch(ivideo->chronteltype) {
3733 SiS_SetReg(SISSR, 0x05, 0x86);
3734 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
3735 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
3738 /* Not supported by hardware */
3742 } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3744 u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
3745 unsigned short temp;
3747 p2_1f = ivideo->p2_1f;
3748 p2_20 = ivideo->p2_20;
3749 p2_2b = ivideo->p2_2b;
3750 p2_42 = ivideo->p2_42;
3751 p2_43 = ivideo->p2_43;
3753 temp = p2_1f | ((p2_20 & 0xf0) << 4);
3755 p2_1f = temp & 0xff;
3756 p2_20 = (temp & 0xf00) >> 4;
3757 p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
3758 temp = p2_43 | ((p2_42 & 0xf0) << 4);
3760 p2_43 = temp & 0xff;
3761 p2_42 = (temp & 0xf00) >> 4;
3762 SiS_SetReg(SISPART2, 0x1f, p2_1f);
3763 SiS_SetRegANDOR(SISPART2, 0x20, 0x0F, p2_20);
3764 SiS_SetRegANDOR(SISPART2, 0x2b, 0xF0, p2_2b);
3765 SiS_SetRegANDOR(SISPART2, 0x42, 0x0F, p2_42);
3766 SiS_SetReg(SISPART2, 0x43, p2_43);
3772 sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
3774 if(val > 32) val = 32;
3775 if(val < -32) val = -32;
3776 ivideo->tvypos = val;
3778 if(ivideo->sisfblocked) return;
3779 if(!ivideo->modechanged) return;
3781 if(ivideo->currentvbflags & CRT2_TV) {
3783 if(ivideo->vbflags2 & VB2_CHRONTEL) {
3785 int y = ivideo->tvy;
3787 switch(ivideo->chronteltype) {
3791 SiS_SetReg(SISSR, 0x05, 0x86);
3792 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
3793 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
3796 /* Not supported by hardware */
3800 } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3804 p2_01 = ivideo->p2_01;
3805 p2_02 = ivideo->p2_02;
3809 if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) {
3810 while((p2_01 <= 0) || (p2_02 <= 0)) {
3815 SiS_SetReg(SISPART2, 0x01, p2_01);
3816 SiS_SetReg(SISPART2, 0x02, p2_02);
3822 sisfb_post_setmode(struct sis_video_info *ivideo)
3824 bool crt1isoff = false;
3826 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
3829 #ifdef CONFIG_FB_SIS_315
3833 SiS_SetReg(SISSR, 0x05, 0x86);
3835 #ifdef CONFIG_FB_SIS_315
3836 sisfb_fixup_SR11(ivideo);
3839 /* Now we actually HAVE changed the display mode */
3840 ivideo->modechanged = 1;
3842 /* We can't switch off CRT1 if bridge is in slave mode */
3843 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
3844 if(sisfb_bridgeisslave(ivideo)) doit = false;
3846 ivideo->sisfb_crt1off = 0;
3848 #ifdef CONFIG_FB_SIS_300
3849 if(ivideo->sisvga_engine == SIS_300_VGA) {
3850 if((ivideo->sisfb_crt1off) && (doit)) {
3857 SiS_SetRegANDOR(SISCR, 0x17, 0x7f, reg);
3860 #ifdef CONFIG_FB_SIS_315
3861 if(ivideo->sisvga_engine == SIS_315_VGA) {
3862 if((ivideo->sisfb_crt1off) && (doit)) {
3871 SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
3872 SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, reg1);
3877 ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
3878 ivideo->currentvbflags |= VB_SINGLE_MODE;
3880 ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
3881 if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
3882 ivideo->currentvbflags |= VB_MIRROR_MODE;
3884 ivideo->currentvbflags |= VB_SINGLE_MODE;
3888 SiS_SetRegAND(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
3890 if(ivideo->currentvbflags & CRT2_TV) {
3891 if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3892 ivideo->p2_1f = SiS_GetReg(SISPART2, 0x1f);
3893 ivideo->p2_20 = SiS_GetReg(SISPART2, 0x20);
3894 ivideo->p2_2b = SiS_GetReg(SISPART2, 0x2b);
3895 ivideo->p2_42 = SiS_GetReg(SISPART2, 0x42);
3896 ivideo->p2_43 = SiS_GetReg(SISPART2, 0x43);
3897 ivideo->p2_01 = SiS_GetReg(SISPART2, 0x01);
3898 ivideo->p2_02 = SiS_GetReg(SISPART2, 0x02);
3899 } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
3900 if(ivideo->chronteltype == 1) {
3901 ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
3902 ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
3903 ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
3904 ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
3909 if(ivideo->tvxpos) {
3910 sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
3912 if(ivideo->tvypos) {
3913 sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
3916 /* Eventually sync engines */
3917 sisfb_check_engine_and_sync(ivideo);
3919 /* (Re-)Initialize chip engines */
3921 sisfb_engine_init(ivideo);
3923 ivideo->engineok = 0;
3928 sisfb_reset_mode(struct sis_video_info *ivideo)
3930 if(sisfb_set_mode(ivideo, 0))
3933 sisfb_set_pitch(ivideo);
3934 sisfb_set_base_CRT1(ivideo, ivideo->current_base);
3935 sisfb_set_base_CRT2(ivideo, ivideo->current_base);
3941 sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command)
3945 switch(sisfb_command->sisfb_cmd) {
3946 case SISFB_CMD_GETVBFLAGS:
3947 if(!ivideo->modechanged) {
3948 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3950 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3951 sisfb_command->sisfb_result[1] = ivideo->currentvbflags;
3952 sisfb_command->sisfb_result[2] = ivideo->vbflags2;
3955 case SISFB_CMD_SWITCHCRT1:
3956 /* arg[0]: 0 = off, 1 = on, 99 = query */
3957 if(!ivideo->modechanged) {
3958 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3959 } else if(sisfb_command->sisfb_arg[0] == 99) {
3961 sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3962 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3963 } else if(ivideo->sisfblocked) {
3964 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED;
3965 } else if((!(ivideo->currentvbflags & CRT2_ENABLE)) &&
3966 (sisfb_command->sisfb_arg[0] == 0)) {
3967 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2;
3969 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3970 mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1;
3971 if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) ||
3972 ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) {
3973 ivideo->sisfb_crt1off = mycrt1off;
3974 if(sisfb_reset_mode(ivideo)) {
3975 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER;
3978 sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3983 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN;
3984 printk(KERN_ERR "sisfb: Unknown command 0x%x\n",
3985 sisfb_command->sisfb_cmd);
3990 static int __init sisfb_setup(char *options)
3994 sisfb_setdefaultparms();
3996 if(!options || !(*options))
3999 while((this_opt = strsep(&options, ",")) != NULL) {
4001 if(!(*this_opt)) continue;
4003 if(!strncasecmp(this_opt, "off", 3)) {
4005 } else if(!strncasecmp(this_opt, "forcecrt2type:", 14)) {
4006 /* Need to check crt2 type first for fstn/dstn */
4007 sisfb_search_crt2type(this_opt + 14);
4008 } else if(!strncasecmp(this_opt, "tvmode:",7)) {
4009 sisfb_search_tvstd(this_opt + 7);
4010 } else if(!strncasecmp(this_opt, "tvstandard:",11)) {
4011 sisfb_search_tvstd(this_opt + 11);
4012 } else if(!strncasecmp(this_opt, "mode:", 5)) {
4013 sisfb_search_mode(this_opt + 5, false);
4014 } else if(!strncasecmp(this_opt, "vesa:", 5)) {
4015 sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false);
4016 } else if(!strncasecmp(this_opt, "rate:", 5)) {
4017 sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
4018 } else if(!strncasecmp(this_opt, "forcecrt1:", 10)) {
4019 sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
4020 } else if(!strncasecmp(this_opt, "mem:",4)) {
4021 sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
4022 } else if(!strncasecmp(this_opt, "pdc:", 4)) {
4023 sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
4024 } else if(!strncasecmp(this_opt, "pdc1:", 5)) {
4025 sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
4026 } else if(!strncasecmp(this_opt, "noaccel", 7)) {
4028 } else if(!strncasecmp(this_opt, "accel", 5)) {
4030 } else if(!strncasecmp(this_opt, "noypan", 6)) {
4032 } else if(!strncasecmp(this_opt, "ypan", 4)) {
4034 } else if(!strncasecmp(this_opt, "nomax", 5)) {
4036 } else if(!strncasecmp(this_opt, "max", 3)) {
4038 } else if(!strncasecmp(this_opt, "userom:", 7)) {
4039 sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
4040 } else if(!strncasecmp(this_opt, "useoem:", 7)) {
4041 sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
4042 } else if(!strncasecmp(this_opt, "nocrt2rate", 10)) {
4043 sisfb_nocrt2rate = 1;
4044 } else if(!strncasecmp(this_opt, "scalelcd:", 9)) {
4045 unsigned long temp = 2;
4046 temp = simple_strtoul(this_opt + 9, NULL, 0);
4047 if((temp == 0) || (temp == 1)) {
4048 sisfb_scalelcd = temp ^ 1;
4050 } else if(!strncasecmp(this_opt, "tvxposoffset:", 13)) {
4052 temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4053 if((temp >= -32) && (temp <= 32)) {
4054 sisfb_tvxposoffset = temp;
4056 } else if(!strncasecmp(this_opt, "tvyposoffset:", 13)) {
4058 temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4059 if((temp >= -32) && (temp <= 32)) {
4060 sisfb_tvyposoffset = temp;
4062 } else if(!strncasecmp(this_opt, "specialtiming:", 14)) {
4063 sisfb_search_specialtiming(this_opt + 14);
4064 } else if(!strncasecmp(this_opt, "lvdshl:", 7)) {
4066 temp = simple_strtoul(this_opt + 7, NULL, 0);
4067 if((temp >= 0) && (temp <= 3)) {
4068 sisfb_lvdshl = temp;
4070 } else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
4071 sisfb_search_mode(this_opt, true);
4072 #if !defined(__i386__) && !defined(__x86_64__)
4073 } else if(!strncasecmp(this_opt, "resetcard", 9)) {
4074 sisfb_resetcard = 1;
4075 } else if(!strncasecmp(this_opt, "videoram:", 9)) {
4076 sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
4079 printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
4088 static int sisfb_check_rom(void __iomem *rom_base,
4089 struct sis_video_info *ivideo)
4094 if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
4097 romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
4098 if(romptr > (0x10000 - 8))
4101 rom = rom_base + romptr;
4103 if((readb(rom) != 'P') || (readb(rom + 1) != 'C') ||
4104 (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R'))
4107 if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor)
4110 if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id)
4116 static unsigned char *sisfb_find_rom(struct pci_dev *pdev)
4118 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4119 void __iomem *rom_base;
4120 unsigned char *myrombase = NULL;
4123 /* First, try the official pci ROM functions (except
4124 * on integrated chipsets which have no ROM).
4127 if(!ivideo->nbridge) {
4129 if((rom_base = pci_map_rom(pdev, &romsize))) {
4131 if(sisfb_check_rom(rom_base, ivideo)) {
4133 if((myrombase = vmalloc(65536))) {
4134 memcpy_fromio(myrombase, rom_base,
4135 (romsize > 65536) ? 65536 : romsize);
4138 pci_unmap_rom(pdev, rom_base);
4142 if(myrombase) return myrombase;
4144 /* Otherwise do it the conventional way. */
4146 #if defined(__i386__) || defined(__x86_64__)
4150 for (temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
4152 rom_base = ioremap(temp, 65536);
4156 if (!sisfb_check_rom(rom_base, ivideo)) {
4161 if ((myrombase = vmalloc(65536)))
4162 memcpy_fromio(myrombase, rom_base, 65536);
4175 static void sisfb_post_map_vram(struct sis_video_info *ivideo,
4176 unsigned int *mapsize, unsigned int min)
4178 if (*mapsize < (min << 20))
4181 ivideo->video_vbase = ioremap_wc(ivideo->video_base, (*mapsize));
4183 if(!ivideo->video_vbase) {
4185 "sisfb: Unable to map maximum video RAM for size detection\n");
4187 while((!(ivideo->video_vbase = ioremap_wc(ivideo->video_base, (*mapsize))))) {
4189 if((*mapsize) < (min << 20))
4192 if(ivideo->video_vbase) {
4194 "sisfb: Video RAM size detection limited to %dMB\n",
4195 (int)((*mapsize) >> 20));
4200 #ifdef CONFIG_FB_SIS_300
4201 static int sisfb_post_300_buswidth(struct sis_video_info *ivideo)
4203 void __iomem *FBAddress = ivideo->video_vbase;
4204 unsigned short temp;
4208 SiS_SetRegAND(SISSR, 0x15, 0xFB);
4209 SiS_SetRegOR(SISSR, 0x15, 0x04);
4210 SiS_SetReg(SISSR, 0x13, 0x00);
4211 SiS_SetReg(SISSR, 0x14, 0xBF);
4213 for(i = 0; i < 2; i++) {
4215 for(j = 0; j < 4; j++) {
4216 writew(temp, FBAddress);
4217 if(readw(FBAddress) == temp)
4219 SiS_SetRegOR(SISSR, 0x3c, 0x01);
4220 reg = SiS_GetReg(SISSR, 0x05);
4221 reg = SiS_GetReg(SISSR, 0x05);
4222 SiS_SetRegAND(SISSR, 0x3c, 0xfe);
4223 reg = SiS_GetReg(SISSR, 0x05);
4224 reg = SiS_GetReg(SISSR, 0x05);
4229 writel(0x01234567L, FBAddress);
4230 writel(0x456789ABL, (FBAddress + 4));
4231 writel(0x89ABCDEFL, (FBAddress + 8));
4232 writel(0xCDEF0123L, (FBAddress + 12));
4234 reg = SiS_GetReg(SISSR, 0x3b);
4236 if(readl((FBAddress + 12)) == 0xCDEF0123L)
4237 return 4; /* Channel A 128bit */
4240 if(readl((FBAddress + 4)) == 0x456789ABL)
4241 return 2; /* Channel B 64bit */
4243 return 1; /* 32bit */
4246 static const unsigned short SiS_DRAMType[17][5] = {
4247 {0x0C,0x0A,0x02,0x40,0x39},
4248 {0x0D,0x0A,0x01,0x40,0x48},
4249 {0x0C,0x09,0x02,0x20,0x35},
4250 {0x0D,0x09,0x01,0x20,0x44},
4251 {0x0C,0x08,0x02,0x10,0x31},
4252 {0x0D,0x08,0x01,0x10,0x40},
4253 {0x0C,0x0A,0x01,0x20,0x34},
4254 {0x0C,0x09,0x01,0x08,0x32},
4255 {0x0B,0x08,0x02,0x08,0x21},
4256 {0x0C,0x08,0x01,0x08,0x30},
4257 {0x0A,0x08,0x02,0x04,0x11},
4258 {0x0B,0x0A,0x01,0x10,0x28},
4259 {0x09,0x08,0x02,0x02,0x01},
4260 {0x0B,0x09,0x01,0x08,0x24},
4261 {0x0B,0x08,0x01,0x04,0x20},
4262 {0x0A,0x08,0x01,0x02,0x10},
4263 {0x09,0x08,0x01,0x01,0x00}
4266 static int sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration,
4267 int buswidth, int PseudoRankCapacity,
4268 int PseudoAdrPinCount, unsigned int mapsize)
4270 void __iomem *FBAddr = ivideo->video_vbase;
4271 unsigned short sr14;
4272 unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
4273 unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
4275 for (k = 0; k < ARRAY_SIZE(SiS_DRAMType); k++) {
4276 RankCapacity = buswidth * SiS_DRAMType[k][3];
4278 if (RankCapacity != PseudoRankCapacity)
4281 if ((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
4284 BankNumHigh = RankCapacity * 16 * iteration - 1;
4285 if (iteration == 3) { /* Rank No */
4286 BankNumMid = RankCapacity * 16 - 1;
4288 BankNumMid = RankCapacity * 16 * iteration / 2 - 1;
4291 PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
4292 PhysicalAdrHigh = BankNumHigh;
4293 PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
4294 PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
4296 SiS_SetRegAND(SISSR, 0x15, 0xFB); /* Test */
4297 SiS_SetRegOR(SISSR, 0x15, 0x04); /* Test */
4298 sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
4302 else if (buswidth == 2)
4305 SiS_SetReg(SISSR, 0x13, SiS_DRAMType[k][4]);
4306 SiS_SetReg(SISSR, 0x14, sr14);
4311 if ((BankNumHigh + PhysicalAdrHigh >= mapsize) ||
4312 (BankNumMid + PhysicalAdrHigh >= mapsize) ||
4313 (BankNumHigh + PhysicalAdrHalfPage >= mapsize) ||
4314 (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
4318 writew(((unsigned short)PhysicalAdrHigh),
4319 (FBAddr + BankNumHigh + PhysicalAdrHigh));
4320 writew(((unsigned short)BankNumMid),
4321 (FBAddr + BankNumMid + PhysicalAdrHigh));
4322 writew(((unsigned short)PhysicalAdrHalfPage),
4323 (FBAddr + BankNumHigh + PhysicalAdrHalfPage));
4324 writew(((unsigned short)PhysicalAdrOtherPage),
4325 (FBAddr + BankNumHigh + PhysicalAdrOtherPage));
4328 if (readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
4335 static void sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
4337 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4339 int PseudoRankCapacity, PseudoAdrPinCount;
4341 buswidth = sisfb_post_300_buswidth(ivideo);
4343 for(i = 6; i >= 0; i--) {
4344 PseudoRankCapacity = 1 << i;
4345 for(j = 4; j >= 1; j--) {
4346 PseudoAdrPinCount = 15 - j;
4347 if((PseudoRankCapacity * j) <= 64) {
4348 if(sisfb_post_300_rwtest(ivideo,
4360 static void sisfb_post_sis300(struct pci_dev *pdev)
4362 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4363 unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
4364 u8 reg, v1, v2, v3, v4, v5, v6, v7, v8;
4365 u16 index, rindex, memtype = 0;
4366 unsigned int mapsize;
4368 if(!ivideo->SiS_Pr.UseROM)
4371 SiS_SetReg(SISSR, 0x05, 0x86);
4374 if(bios[0x52] & 0x80) {
4375 memtype = bios[0x52];
4377 memtype = SiS_GetReg(SISSR, 0x3a);
4382 v3 = 0x80; v6 = 0x80;
4383 if(ivideo->revision_id <= 0x13) {
4384 v1 = 0x44; v2 = 0x42;
4385 v4 = 0x44; v5 = 0x42;
4387 v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */
4388 v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */
4390 index = memtype * 5;
4391 rindex = index + 0x54;
4392 v1 = bios[rindex++];
4393 v2 = bios[rindex++];
4394 v3 = bios[rindex++];
4395 rindex = index + 0x7c;
4396 v4 = bios[rindex++];
4397 v5 = bios[rindex++];
4398 v6 = bios[rindex++];
4401 SiS_SetReg(SISSR, 0x28, v1);
4402 SiS_SetReg(SISSR, 0x29, v2);
4403 SiS_SetReg(SISSR, 0x2a, v3);
4404 SiS_SetReg(SISSR, 0x2e, v4);
4405 SiS_SetReg(SISSR, 0x2f, v5);
4406 SiS_SetReg(SISSR, 0x30, v6);
4411 SiS_SetReg(SISSR, 0x07, v1); /* DAC speed */
4413 SiS_SetReg(SISSR, 0x11, 0x0f); /* DDC, power save */
4415 v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
4416 v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
4420 v2 = bios[memtype + 8];
4421 v3 = bios[memtype + 16];
4422 v4 = bios[memtype + 24];
4423 v5 = bios[memtype + 32];
4424 v6 = bios[memtype + 40];
4425 v7 = bios[memtype + 48];
4426 v8 = bios[memtype + 56];
4428 if(ivideo->revision_id >= 0x80)
4430 SiS_SetReg(SISSR, 0x15, v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4431 SiS_SetReg(SISSR, 0x16, v2);
4432 SiS_SetReg(SISSR, 0x17, v3);
4433 SiS_SetReg(SISSR, 0x18, v4);
4434 SiS_SetReg(SISSR, 0x19, v5);
4435 SiS_SetReg(SISSR, 0x1a, v6);
4436 SiS_SetReg(SISSR, 0x1b, v7);
4437 SiS_SetReg(SISSR, 0x1c, v8); /* ---- */
4438 SiS_SetRegAND(SISSR, 0x15, 0xfb);
4439 SiS_SetRegOR(SISSR, 0x15, 0x04);
4441 if(bios[0x53] & 0x02) {
4442 SiS_SetRegOR(SISSR, 0x19, 0x20);
4445 v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */
4446 if(ivideo->revision_id >= 0x80)
4448 SiS_SetReg(SISSR, 0x1f, v1);
4449 SiS_SetReg(SISSR, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
4450 v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
4456 SiS_SetReg(SISSR, 0x23, v1);
4457 SiS_SetReg(SISSR, 0x24, v2);
4458 SiS_SetReg(SISSR, 0x25, v3);
4459 SiS_SetReg(SISSR, 0x21, 0x84);
4460 SiS_SetReg(SISSR, 0x22, 0x00);
4461 SiS_SetReg(SISCR, 0x37, 0x00);
4462 SiS_SetRegOR(SISPART1, 0x24, 0x01); /* unlock crt2 */
4463 SiS_SetReg(SISPART1, 0x00, 0x00);
4464 v1 = 0x40; v2 = 0x11;
4469 SiS_SetReg(SISPART1, 0x02, v1);
4471 if(ivideo->revision_id >= 0x80)
4474 reg = SiS_GetReg(SISPART4, 0x00);
4475 if((reg == 1) || (reg == 2)) {
4476 SiS_SetReg(SISCR, 0x37, 0x02);
4477 SiS_SetReg(SISPART2, 0x00, 0x1c);
4478 v4 = 0x00; v5 = 0x00; v6 = 0x10;
4479 if (ivideo->SiS_Pr.UseROM && bios) {
4484 SiS_SetReg(SISPART4, 0x0d, v4);
4485 SiS_SetReg(SISPART4, 0x0e, v5);
4486 SiS_SetReg(SISPART4, 0x10, v6);
4487 SiS_SetReg(SISPART4, 0x0f, 0x3f);
4488 reg = SiS_GetReg(SISPART4, 0x01);
4490 reg = SiS_GetReg(SISPART4, 0x23);
4493 SiS_SetReg(SISPART4, 0x23, reg);
4498 SiS_SetReg(SISSR, 0x32, v2);
4500 SiS_SetRegAND(SISPART1, 0x24, 0xfe); /* Lock CRT2 */
4502 reg = SiS_GetReg(SISSR, 0x16);
4504 SiS_SetReg(SISCR, 0x35, reg);
4505 SiS_SetReg(SISCR, 0x83, 0x00);
4506 #if !defined(__i386__) && !defined(__x86_64__)
4507 if(sisfb_videoram) {
4508 SiS_SetReg(SISSR, 0x13, 0x28); /* ? */
4509 reg = ((sisfb_videoram >> 10) - 1) | 0x40;
4510 SiS_SetReg(SISSR, 0x14, reg);
4513 /* Need to map max FB size for finding out about RAM size */
4514 mapsize = ivideo->video_size;
4515 sisfb_post_map_vram(ivideo, &mapsize, 4);
4517 if(ivideo->video_vbase) {
4518 sisfb_post_300_ramsize(pdev, mapsize);
4519 iounmap(ivideo->video_vbase);
4522 "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4523 SiS_SetReg(SISSR, 0x13, 0x28); /* ? */
4524 SiS_SetReg(SISSR, 0x14, 0x47); /* 8MB, 64bit default */
4526 #if !defined(__i386__) && !defined(__x86_64__)
4533 reg = SiS_GetReg(SISSR, 0x3a);
4534 if((reg & 0x30) == 0x30) {
4535 v1 = 0x04; /* PCI */
4538 v1 = 0x14; /* AGP */
4542 SiS_SetReg(SISSR, 0x21, v1);
4543 SiS_SetReg(SISSR, 0x22, v2);
4546 sisfb_sense_crt1(ivideo);
4548 /* Set default mode, don't clear screen */
4549 ivideo->SiS_Pr.SiS_UseOEM = false;
4550 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
4551 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
4552 ivideo->curFSTN = ivideo->curDSTN = 0;
4553 ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
4554 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
4556 SiS_SetReg(SISSR, 0x05, 0x86);
4559 SiS_SetRegOR(SISSR, 0x01, 0x20);
4561 /* Save mode number in CR34 */
4562 SiS_SetReg(SISCR, 0x34, 0x2e);
4564 /* Let everyone know what the current mode is */
4565 ivideo->modeprechange = 0x2e;
4569 #ifdef CONFIG_FB_SIS_315
4571 static void sisfb_post_sis315330(struct pci_dev *pdev)
4577 static inline int sisfb_xgi_is21(struct sis_video_info *ivideo)
4579 return ivideo->chip_real_id == XGI_21;
4582 static void sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
4587 for(i = 0; i <= (delay * 10 * 36); i++) {
4588 reg = SiS_GetReg(SISSR, 0x05);
4593 static int sisfb_find_host_bridge(struct sis_video_info *ivideo,
4594 struct pci_dev *mypdev,
4595 unsigned short pcivendor)
4597 struct pci_dev *pdev = NULL;
4598 unsigned short temp;
4601 while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) {
4602 temp = pdev->vendor;
4603 if(temp == pcivendor) {
4613 static int sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
4614 unsigned int enda, unsigned int mapsize)
4619 writel(0, ivideo->video_vbase);
4621 for(i = starta; i <= enda; i++) {
4624 writel(pos, ivideo->video_vbase + pos);
4627 sisfb_post_xgi_delay(ivideo, 150);
4629 if(readl(ivideo->video_vbase) != 0)
4632 for(i = starta; i <= enda; i++) {
4635 if(readl(ivideo->video_vbase + pos) != pos)
4644 static int sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
4646 unsigned int buswidth, ranksize, channelab, mapsize;
4647 int i, j, k, l, status;
4649 static const u8 dramsr13[12 * 5] = {
4650 0x02, 0x0e, 0x0b, 0x80, 0x5d,
4651 0x02, 0x0e, 0x0a, 0x40, 0x59,
4652 0x02, 0x0d, 0x0b, 0x40, 0x4d,
4653 0x02, 0x0e, 0x09, 0x20, 0x55,
4654 0x02, 0x0d, 0x0a, 0x20, 0x49,
4655 0x02, 0x0c, 0x0b, 0x20, 0x3d,
4656 0x02, 0x0e, 0x08, 0x10, 0x51,
4657 0x02, 0x0d, 0x09, 0x10, 0x45,
4658 0x02, 0x0c, 0x0a, 0x10, 0x39,
4659 0x02, 0x0d, 0x08, 0x08, 0x41,
4660 0x02, 0x0c, 0x09, 0x08, 0x35,
4661 0x02, 0x0c, 0x08, 0x04, 0x31
4663 static const u8 dramsr13_4[4 * 5] = {
4664 0x02, 0x0d, 0x09, 0x40, 0x45,
4665 0x02, 0x0c, 0x09, 0x20, 0x35,
4666 0x02, 0x0c, 0x08, 0x10, 0x31,
4667 0x02, 0x0b, 0x08, 0x08, 0x21
4670 /* Enable linear mode, disable 0xa0000 address decoding */
4671 /* We disable a0000 address decoding, because
4672 * - if running on x86, if the card is disabled, it means
4673 * that another card is in the system. We don't want
4674 * to interphere with that primary card's textmode.
4675 * - if running on non-x86, there usually is no VGA window
4678 SiS_SetRegOR(SISSR, 0x20, (0x80 | 0x04));
4680 /* Need to map max FB size for finding out about RAM size */
4681 mapsize = ivideo->video_size;
4682 sisfb_post_map_vram(ivideo, &mapsize, 32);
4684 if(!ivideo->video_vbase) {
4685 printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
4686 SiS_SetReg(SISSR, 0x13, 0x35);
4687 SiS_SetReg(SISSR, 0x14, 0x41);
4692 /* Non-interleaving */
4693 SiS_SetReg(SISSR, 0x15, 0x00);
4695 SiS_SetReg(SISSR, 0x1c, 0x00);
4697 if(ivideo->chip == XGI_20) {
4700 reg = SiS_GetReg(SISCR, 0x97);
4701 if(!(reg & 0x01)) { /* Single 32/16 */
4703 SiS_SetReg(SISSR, 0x13, 0xb1);
4704 SiS_SetReg(SISSR, 0x14, 0x52);
4705 sisfb_post_xgi_delay(ivideo, 1);
4707 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4710 SiS_SetReg(SISSR, 0x13, 0x31);
4711 SiS_SetReg(SISSR, 0x14, 0x42);
4712 sisfb_post_xgi_delay(ivideo, 1);
4713 if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
4717 SiS_SetReg(SISSR, 0x13, 0xb1);
4718 SiS_SetReg(SISSR, 0x14, 0x41);
4719 sisfb_post_xgi_delay(ivideo, 1);
4721 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4724 SiS_SetReg(SISSR, 0x13, 0x31);
4725 } else { /* Dual 16/8 */
4727 SiS_SetReg(SISSR, 0x13, 0xb1);
4728 SiS_SetReg(SISSR, 0x14, 0x41);
4729 sisfb_post_xgi_delay(ivideo, 1);
4731 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4734 SiS_SetReg(SISSR, 0x13, 0x31);
4735 SiS_SetReg(SISSR, 0x14, 0x31);
4736 sisfb_post_xgi_delay(ivideo, 1);
4737 if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
4741 SiS_SetReg(SISSR, 0x13, 0xb1);
4742 SiS_SetReg(SISSR, 0x14, 0x30);
4743 sisfb_post_xgi_delay(ivideo, 1);
4745 if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
4748 SiS_SetReg(SISSR, 0x13, 0x31);
4751 } else { /* XGI_40 */
4753 reg = SiS_GetReg(SISCR, 0x97);
4755 reg = SiS_GetReg(SISSR, 0x39);
4759 if(reg & 0x01) { /* DDRII */
4761 if(ivideo->revision_id == 2) {
4763 SiS_SetReg(SISSR, 0x13, 0xa1);
4764 SiS_SetReg(SISSR, 0x14, 0x44);
4766 sisfb_post_xgi_delay(ivideo, 1);
4767 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4770 SiS_SetReg(SISSR, 0x13, 0x21);
4771 SiS_SetReg(SISSR, 0x14, 0x34);
4772 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4776 SiS_SetReg(SISSR, 0x13, 0xa1);
4777 SiS_SetReg(SISSR, 0x14, 0x40);
4779 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4782 SiS_SetReg(SISSR, 0x13, 0x21);
4783 SiS_SetReg(SISSR, 0x14, 0x30);
4786 SiS_SetReg(SISSR, 0x13, 0xa1);
4787 SiS_SetReg(SISSR, 0x14, 0x4c);
4789 sisfb_post_xgi_delay(ivideo, 1);
4790 if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
4794 SiS_SetReg(SISSR, 0x14, 0x48);
4795 sisfb_post_xgi_delay(ivideo, 1);
4797 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4800 SiS_SetReg(SISSR, 0x13, 0x21);
4801 SiS_SetReg(SISSR, 0x14, 0x3c);
4804 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
4808 SiS_SetReg(SISSR, 0x14, 0x38);
4812 sisfb_post_xgi_delay(ivideo, 1);
4817 if(ivideo->revision_id == 2) {
4819 SiS_SetReg(SISSR, 0x13, 0xa1);
4820 SiS_SetReg(SISSR, 0x14, 0x52);
4821 sisfb_post_xgi_delay(ivideo, 1);
4823 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4826 SiS_SetReg(SISSR, 0x13, 0x21);
4827 SiS_SetReg(SISSR, 0x14, 0x42);
4830 SiS_SetReg(SISSR, 0x13, 0xa1);
4831 SiS_SetReg(SISSR, 0x14, 0x5a);
4832 sisfb_post_xgi_delay(ivideo, 1);
4834 if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
4837 SiS_SetReg(SISSR, 0x13, 0x21);
4838 SiS_SetReg(SISSR, 0x14, 0x4a);
4840 sisfb_post_xgi_delay(ivideo, 1);
4846 SiS_SetRegANDOR(SISSR, 0x14, 0xf0, sr14);
4847 sisfb_post_xgi_delay(ivideo, 1);
4849 j = (ivideo->chip == XGI_20) ? 5 : 9;
4850 k = (ivideo->chip == XGI_20) ? 12 : 4;
4853 for(i = 0; i < k; i++) {
4855 reg = (ivideo->chip == XGI_20) ?
4856 dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
4857 SiS_SetRegANDOR(SISSR, 0x13, 0x80, reg);
4858 sisfb_post_xgi_delay(ivideo, 50);
4860 ranksize = (ivideo->chip == XGI_20) ?
4861 dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
4863 reg = SiS_GetReg(SISSR, 0x13);
4864 if(reg & 0x80) ranksize <<= 1;
4866 if(ivideo->chip == XGI_20) {
4867 if(buswidth == 16) ranksize <<= 1;
4868 else if(buswidth == 32) ranksize <<= 2;
4870 if(buswidth == 64) ranksize <<= 1;
4876 if((ranksize * l) <= 256) {
4877 while((ranksize >>= 1)) reg += 0x10;
4882 SiS_SetRegANDOR(SISSR, 0x14, 0x0f, (reg & 0xf0));
4883 sisfb_post_xgi_delay(ivideo, 1);
4885 if (sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize)) {
4891 iounmap(ivideo->video_vbase);
4896 static void sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
4900 static const u8 cs90[8 * 3] = {
4910 static const u8 csb8[8 * 3] = {
4924 v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2];
4925 if(ivideo->haveXGIROM) {
4926 v1 = ivideo->bios_abase[0x90 + index];
4927 v2 = ivideo->bios_abase[0x90 + index + 1];
4928 v3 = ivideo->bios_abase[0x90 + index + 2];
4930 SiS_SetReg(SISSR, 0x28, v1);
4931 SiS_SetReg(SISSR, 0x29, v2);
4932 SiS_SetReg(SISSR, 0x2a, v3);
4933 sisfb_post_xgi_delay(ivideo, 0x43);
4934 sisfb_post_xgi_delay(ivideo, 0x43);
4935 sisfb_post_xgi_delay(ivideo, 0x43);
4937 v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2];
4938 if(ivideo->haveXGIROM) {
4939 v1 = ivideo->bios_abase[0xb8 + index];
4940 v2 = ivideo->bios_abase[0xb8 + index + 1];
4941 v3 = ivideo->bios_abase[0xb8 + index + 2];
4943 SiS_SetReg(SISSR, 0x2e, v1);
4944 SiS_SetReg(SISSR, 0x2f, v2);
4945 SiS_SetReg(SISSR, 0x30, v3);
4946 sisfb_post_xgi_delay(ivideo, 0x43);
4947 sisfb_post_xgi_delay(ivideo, 0x43);
4948 sisfb_post_xgi_delay(ivideo, 0x43);
4951 static void sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info *ivideo,
4954 unsigned char *bios = ivideo->bios_abase;
4957 SiS_SetReg(SISSR, 0x28, 0x64);
4958 SiS_SetReg(SISSR, 0x29, 0x63);
4959 sisfb_post_xgi_delay(ivideo, 15);
4960 SiS_SetReg(SISSR, 0x18, 0x00);
4961 SiS_SetReg(SISSR, 0x19, 0x20);
4962 SiS_SetReg(SISSR, 0x16, 0x00);
4963 SiS_SetReg(SISSR, 0x16, 0x80);
4964 SiS_SetReg(SISSR, 0x18, 0xc5);
4965 SiS_SetReg(SISSR, 0x19, 0x23);
4966 SiS_SetReg(SISSR, 0x16, 0x00);
4967 SiS_SetReg(SISSR, 0x16, 0x80);
4968 sisfb_post_xgi_delay(ivideo, 1);
4969 SiS_SetReg(SISCR, 0x97, 0x11);
4970 sisfb_post_xgi_setclocks(ivideo, regb);
4971 sisfb_post_xgi_delay(ivideo, 0x46);
4972 SiS_SetReg(SISSR, 0x18, 0xc5);
4973 SiS_SetReg(SISSR, 0x19, 0x23);
4974 SiS_SetReg(SISSR, 0x16, 0x00);
4975 SiS_SetReg(SISSR, 0x16, 0x80);
4976 sisfb_post_xgi_delay(ivideo, 1);
4977 SiS_SetReg(SISSR, 0x1b, 0x04);
4978 sisfb_post_xgi_delay(ivideo, 1);
4979 SiS_SetReg(SISSR, 0x1b, 0x00);
4980 sisfb_post_xgi_delay(ivideo, 1);
4982 if (ivideo->haveXGIROM) {
4985 SiS_SetReg(SISSR, 0x18, v1);
4986 SiS_SetReg(SISSR, 0x19, 0x06);
4987 SiS_SetReg(SISSR, 0x16, 0x04);
4988 SiS_SetReg(SISSR, 0x16, 0x84);
4989 sisfb_post_xgi_delay(ivideo, 1);
4992 static void sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info *ivideo)
4994 sisfb_post_xgi_setclocks(ivideo, 1);
4996 SiS_SetReg(SISCR, 0x97, 0x11);
4997 sisfb_post_xgi_delay(ivideo, 0x46);
4999 SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS2 */
5000 SiS_SetReg(SISSR, 0x19, 0x80);
5001 SiS_SetReg(SISSR, 0x16, 0x05);
5002 SiS_SetReg(SISSR, 0x16, 0x85);
5004 SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS3 */
5005 SiS_SetReg(SISSR, 0x19, 0xc0);
5006 SiS_SetReg(SISSR, 0x16, 0x05);
5007 SiS_SetReg(SISSR, 0x16, 0x85);
5009 SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS1 */
5010 SiS_SetReg(SISSR, 0x19, 0x40);
5011 SiS_SetReg(SISSR, 0x16, 0x05);
5012 SiS_SetReg(SISSR, 0x16, 0x85);
5014 SiS_SetReg(SISSR, 0x18, 0x42); /* MRS1 */
5015 SiS_SetReg(SISSR, 0x19, 0x02);
5016 SiS_SetReg(SISSR, 0x16, 0x05);
5017 SiS_SetReg(SISSR, 0x16, 0x85);
5018 sisfb_post_xgi_delay(ivideo, 1);
5020 SiS_SetReg(SISSR, 0x1b, 0x04);
5021 sisfb_post_xgi_delay(ivideo, 1);
5023 SiS_SetReg(SISSR, 0x1b, 0x00);
5024 sisfb_post_xgi_delay(ivideo, 1);
5026 SiS_SetReg(SISSR, 0x18, 0x42); /* MRS1 */
5027 SiS_SetReg(SISSR, 0x19, 0x00);
5028 SiS_SetReg(SISSR, 0x16, 0x05);
5029 SiS_SetReg(SISSR, 0x16, 0x85);
5030 sisfb_post_xgi_delay(ivideo, 1);
5033 static void sisfb_post_xgi_ddr2(struct sis_video_info *ivideo, u8 regb)
5035 unsigned char *bios = ivideo->bios_abase;
5036 static const u8 cs158[8] = {
5037 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5039 static const u8 cs160[8] = {
5040 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5042 static const u8 cs168[8] = {
5043 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5049 SiS_SetReg(SISCR, 0xb0, 0x80); /* DDR2 dual frequency mode */
5050 SiS_SetReg(SISCR, 0x82, 0x77);
5051 SiS_SetReg(SISCR, 0x86, 0x00);
5052 SiS_GetReg(SISCR, 0x86);
5053 SiS_SetReg(SISCR, 0x86, 0x88);
5054 SiS_GetReg(SISCR, 0x86);
5055 v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
5056 if (ivideo->haveXGIROM) {
5057 v1 = bios[regb + 0x168];
5058 v2 = bios[regb + 0x160];
5059 v3 = bios[regb + 0x158];
5061 SiS_SetReg(SISCR, 0x86, v1);
5062 SiS_SetReg(SISCR, 0x82, 0x77);
5063 SiS_SetReg(SISCR, 0x85, 0x00);
5064 SiS_GetReg(SISCR, 0x85);
5065 SiS_SetReg(SISCR, 0x85, 0x88);
5066 SiS_GetReg(SISCR, 0x85);
5067 SiS_SetReg(SISCR, 0x85, v2);
5068 SiS_SetReg(SISCR, 0x82, v3);
5069 SiS_SetReg(SISCR, 0x98, 0x01);
5070 SiS_SetReg(SISCR, 0x9a, 0x02);
5071 if (sisfb_xgi_is21(ivideo))
5072 sisfb_post_xgi_ddr2_mrs_xg21(ivideo);
5074 sisfb_post_xgi_ddr2_mrs_default(ivideo, regb);
5077 static u8 sisfb_post_xgi_ramtype(struct sis_video_info *ivideo)
5079 unsigned char *bios = ivideo->bios_abase;
5084 ramtype = 0x00; v1 = 0x10;
5085 if (ivideo->haveXGIROM) {
5086 ramtype = bios[0x62];
5089 if (!(ramtype & 0x80)) {
5090 if (sisfb_xgi_is21(ivideo)) {
5091 SiS_SetRegAND(SISCR, 0xb4, 0xfd); /* GPIO control */
5092 SiS_SetRegOR(SISCR, 0x4a, 0x80); /* GPIOH EN */
5093 reg = SiS_GetReg(SISCR, 0x48);
5094 SiS_SetRegOR(SISCR, 0xb4, 0x02);
5095 ramtype = reg & 0x01; /* GPIOH */
5096 } else if (ivideo->chip == XGI_20) {
5097 SiS_SetReg(SISCR, 0x97, v1);
5098 reg = SiS_GetReg(SISCR, 0x97);
5100 ramtype = (reg & 0x01) << 1;
5103 reg = SiS_GetReg(SISSR, 0x39);
5104 ramtype = reg & 0x02;
5106 reg = SiS_GetReg(SISSR, 0x3a);
5107 ramtype = (reg >> 1) & 0x01;
5116 static int sisfb_post_xgi(struct pci_dev *pdev)
5118 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
5119 unsigned char *bios = ivideo->bios_abase;
5120 struct pci_dev *mypdev = NULL;
5121 const u8 *ptr, *ptr2;
5122 u8 v1, v2, v3, v4, v5, reg, ramtype;
5123 u32 rega, regb, regd;
5125 static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 };
5126 static const u8 cs76[2] = { 0xa3, 0xfb };
5127 static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 };
5128 static const u8 cs158[8] = {
5129 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5131 static const u8 cs160[8] = {
5132 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5134 static const u8 cs168[8] = {
5135 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5137 static const u8 cs128[3 * 8] = {
5138 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
5139 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5140 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
5142 static const u8 cs148[2 * 8] = {
5143 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
5144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5146 static const u8 cs31a[8 * 4] = {
5147 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
5148 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
5149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5152 static const u8 cs33a[8 * 4] = {
5153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5158 static const u8 cs45a[8 * 2] = {
5159 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
5160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5162 static const u8 cs170[7 * 8] = {
5163 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5164 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5165 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
5166 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5167 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5168 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5169 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5171 static const u8 cs1a8[3 * 8] = {
5172 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5173 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5176 static const u8 cs100[2 * 8] = {
5177 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5178 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5182 reg = SiS_GetRegByte(SISVGAENABLE) | 0x01;
5183 SiS_SetRegByte(SISVGAENABLE, reg);
5186 reg = SiS_GetRegByte(SISMISCR) | 0x01;
5187 SiS_SetRegByte(SISMISCW, reg);
5190 SiS_SetReg(SISSR, 0x05, 0x86);
5191 reg = SiS_GetReg(SISSR, 0x05);
5195 /* Clear some regs */
5196 for(i = 0; i < 0x22; i++) {
5197 if(0x06 + i == 0x20) continue;
5198 SiS_SetReg(SISSR, 0x06 + i, 0x00);
5200 for(i = 0; i < 0x0b; i++) {
5201 SiS_SetReg(SISSR, 0x31 + i, 0x00);
5203 for(i = 0; i < 0x10; i++) {
5204 SiS_SetReg(SISCR, 0x30 + i, 0x00);
5208 if(ivideo->haveXGIROM) {
5209 ptr = (const u8 *)&bios[0x78];
5211 for(i = 0; i < 3; i++) {
5212 SiS_SetReg(SISSR, 0x23 + i, ptr[i]);
5216 if(ivideo->haveXGIROM) {
5217 ptr = (const u8 *)&bios[0x76];
5219 for(i = 0; i < 2; i++) {
5220 SiS_SetReg(SISSR, 0x21 + i, ptr[i]);
5223 v1 = 0x18; v2 = 0x00;
5224 if(ivideo->haveXGIROM) {
5228 SiS_SetReg(SISSR, 0x07, v1);
5229 SiS_SetReg(SISSR, 0x11, 0x0f);
5230 SiS_SetReg(SISSR, 0x1f, v2);
5231 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5232 SiS_SetReg(SISSR, 0x20, 0x80 | 0x20 | 0x04);
5233 SiS_SetReg(SISSR, 0x27, 0x74);
5236 if(ivideo->haveXGIROM) {
5237 ptr = (const u8 *)&bios[0x7b];
5239 for(i = 0; i < 3; i++) {
5240 SiS_SetReg(SISSR, 0x31 + i, ptr[i]);
5243 if(ivideo->chip == XGI_40) {
5244 if(ivideo->revision_id == 2) {
5245 SiS_SetRegANDOR(SISSR, 0x3b, 0x3f, 0xc0);
5247 SiS_SetReg(SISCR, 0x7d, 0xfe);
5248 SiS_SetReg(SISCR, 0x7e, 0x0f);
5250 if(ivideo->revision_id == 0) { /* 40 *and* 20? */
5251 SiS_SetRegAND(SISCR, 0x58, 0xd7);
5252 reg = SiS_GetReg(SISCR, 0xcb);
5254 SiS_SetRegANDOR(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5258 reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
5259 SiS_SetRegANDOR(SISCR, 0x38, 0x1f, reg);
5261 if(ivideo->chip == XGI_20) {
5262 SiS_SetReg(SISSR, 0x36, 0x70);
5264 SiS_SetReg(SISVID, 0x00, 0x86);
5265 SiS_SetReg(SISVID, 0x32, 0x00);
5266 SiS_SetReg(SISVID, 0x30, 0x00);
5267 SiS_SetReg(SISVID, 0x32, 0x01);
5268 SiS_SetReg(SISVID, 0x30, 0x00);
5269 SiS_SetRegAND(SISVID, 0x2f, 0xdf);
5270 SiS_SetRegAND(SISCAP, 0x00, 0x3f);
5272 SiS_SetReg(SISPART1, 0x2f, 0x01);
5273 SiS_SetReg(SISPART1, 0x00, 0x00);
5274 SiS_SetReg(SISPART1, 0x02, bios[0x7e]);
5275 SiS_SetReg(SISPART1, 0x2e, 0x08);
5276 SiS_SetRegAND(SISPART1, 0x35, 0x7f);
5277 SiS_SetRegAND(SISPART1, 0x50, 0xfe);
5279 reg = SiS_GetReg(SISPART4, 0x00);
5280 if(reg == 1 || reg == 2) {
5281 SiS_SetReg(SISPART2, 0x00, 0x1c);
5282 SiS_SetReg(SISPART4, 0x0d, bios[0x7f]);
5283 SiS_SetReg(SISPART4, 0x0e, bios[0x80]);
5284 SiS_SetReg(SISPART4, 0x10, bios[0x81]);
5285 SiS_SetRegAND(SISPART4, 0x0f, 0x3f);
5287 reg = SiS_GetReg(SISPART4, 0x01);
5288 if((reg & 0xf0) >= 0xb0) {
5289 reg = SiS_GetReg(SISPART4, 0x23);
5290 if(reg & 0x20) reg |= 0x40;
5291 SiS_SetReg(SISPART4, 0x23, reg);
5292 reg = (reg & 0x20) ? 0x02 : 0x00;
5293 SiS_SetRegANDOR(SISPART1, 0x1e, 0xfd, reg);
5299 reg = SiS_GetReg(SISSR, 0x3b);
5301 reg = SiS_GetReg(SISSR, 0x3a);
5302 v2 = (reg & 0x30) >> 3;
5303 if(!(v2 & 0x04)) v2 ^= 0x02;
5304 reg = SiS_GetReg(SISSR, 0x39);
5305 if(reg & 0x80) v2 |= 0x80;
5308 if((mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
5309 pci_dev_put(mypdev);
5310 if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
5315 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0735, NULL);
5317 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0645, NULL);
5319 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0650, NULL);
5321 pci_read_config_dword(mypdev, 0x94, ®d);
5323 pci_write_config_dword(mypdev, 0x94, regd);
5325 pci_dev_put(mypdev);
5326 } else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) {
5328 } else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) ||
5329 sisfb_find_host_bridge(ivideo, pdev, 0x1022) ||
5330 sisfb_find_host_bridge(ivideo, pdev, 0x700e) ||
5331 sisfb_find_host_bridge(ivideo, pdev, 0x10de)) {
5332 if((v2 & 0x06) == 4)
5337 SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, v2);
5339 SiS_SetReg(SISSR, 0x22, v1);
5341 if(ivideo->revision_id == 2) {
5342 v1 = SiS_GetReg(SISSR, 0x3b);
5343 v2 = SiS_GetReg(SISSR, 0x3a);
5344 regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
5345 if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
5346 SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
5348 if((mypdev = pci_get_device(0x10de, 0x01e0, NULL))) {
5349 /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5353 SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
5354 pci_dev_put(mypdev);
5359 reg = SiS_GetReg(SISSR, 0x3b);
5360 v2 = SiS_GetReg(SISCR, 0x5f);
5361 if((!(reg & 0x02)) && (v2 & 0x0e))
5363 SiS_SetReg(SISSR, 0x27, v1);
5365 if(bios[0x64] & 0x01) {
5366 SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, bios[0x64]);
5370 pci_read_config_dword(pdev, 0x50, ®d);
5371 regd = (regd >> 20) & 0x0f;
5374 SiS_SetRegOR(SISCR, 0x5f, 0x08);
5376 SiS_SetReg(SISCR, 0x48, v1);
5378 SiS_SetRegANDOR(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
5379 SiS_SetRegANDOR(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
5380 SiS_SetRegANDOR(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
5381 SiS_SetRegANDOR(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
5382 SiS_SetRegANDOR(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
5383 SiS_SetReg(SISCR, 0x70, bios[0x4fc]);
5384 SiS_SetRegANDOR(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
5385 SiS_SetReg(SISCR, 0x74, 0xd0);
5386 SiS_SetRegANDOR(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
5387 SiS_SetRegANDOR(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
5388 SiS_SetRegANDOR(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
5390 if((mypdev = pci_get_device(0x8086, 0x2530, NULL))) {
5392 pci_dev_put(mypdev);
5394 SiS_SetReg(SISCR, 0x77, v1);
5399 * 0 == DDR1, 1 == DDR2, 2..7 == reserved?
5401 * The code seems to written so that regb should equal ramtype,
5402 * however, so far it has been hardcoded to 0. Enable other values only
5403 * on XGI Z9, as it passes the POST, and add a warning for others.
5405 ramtype = sisfb_post_xgi_ramtype(ivideo);
5406 if (!sisfb_xgi_is21(ivideo) && ramtype) {
5407 dev_warn(&pdev->dev,
5408 "RAM type something else than expected: %d\n",
5416 if(ivideo->haveXGIROM) {
5417 v1 = bios[0x140 + regb];
5419 SiS_SetReg(SISCR, 0x6d, v1);
5422 if(ivideo->haveXGIROM) {
5423 ptr = (const u8 *)&bios[0x128];
5425 for(i = 0, j = 0; i < 3; i++, j += 8) {
5426 SiS_SetReg(SISCR, 0x68 + i, ptr[j + regb]);
5431 if(ivideo->haveXGIROM) {
5432 index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6;
5433 ptr = (const u8 *)&bios[index];
5434 ptr2 = (const u8 *)&bios[index + 0x20];
5436 for(i = 0; i < 2; i++) {
5438 regd = le32_to_cpu(((u32 *)ptr)[regb]);
5441 regd = le32_to_cpu(((u32 *)ptr2)[regb]);
5445 for(j = 0; j < 16; j++) {
5447 if(regd & 0x01) reg |= 0x04;
5448 if(regd & 0x02) reg |= 0x08;
5450 SiS_SetReg(SISCR, rega, reg);
5451 reg = SiS_GetReg(SISCR, rega);
5452 reg = SiS_GetReg(SISCR, rega);
5457 SiS_SetRegAND(SISCR, 0x6e, 0xfc);
5460 if(ivideo->haveXGIROM) {
5461 index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6;
5462 ptr = (const u8 *)&bios[index];
5464 for(i = 0; i < 4; i++) {
5465 SiS_SetRegANDOR(SISCR, 0x6e, 0xfc, i);
5467 for(j = 0; j < 2; j++) {
5470 regd = le32_to_cpu(((u32 *)ptr)[regb * 8]);
5474 for(k = 0; k < 16; k++) {
5476 if(regd & 0x01) reg |= 0x01;
5477 if(regd & 0x02) reg |= 0x02;
5479 SiS_SetReg(SISCR, 0x6f, reg);
5480 reg = SiS_GetReg(SISCR, 0x6f);
5481 reg = SiS_GetReg(SISCR, 0x6f);
5488 if(ivideo->haveXGIROM) {
5489 ptr = (const u8 *)&bios[0x148];
5491 for(i = 0, j = 0; i < 2; i++, j += 8) {
5492 SiS_SetReg(SISCR, 0x80 + i, ptr[j + regb]);
5495 SiS_SetRegAND(SISCR, 0x89, 0x8f);
5498 if(ivideo->haveXGIROM) {
5499 index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6;
5500 ptr = (const u8 *)&bios[index];
5502 regd = le16_to_cpu(((const u16 *)ptr)[regb]);
5504 for(i = 0; i < 5; i++) {
5506 if(regd & 0x01) reg |= 0x01;
5507 if(regd & 0x02) reg |= 0x02;
5509 SiS_SetReg(SISCR, 0x89, reg);
5510 reg = SiS_GetReg(SISCR, 0x89);
5511 reg = SiS_GetReg(SISCR, 0x89);
5515 v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13;
5516 if(ivideo->haveXGIROM) {
5517 v1 = bios[0x118 + regb];
5518 v2 = bios[0xf8 + regb];
5519 v3 = bios[0x120 + regb];
5522 SiS_SetReg(SISCR, 0x45, v1 & 0x0f);
5523 SiS_SetReg(SISCR, 0x99, (v1 >> 4) & 0x07);
5524 SiS_SetRegOR(SISCR, 0x40, v1 & 0x80);
5525 SiS_SetReg(SISCR, 0x41, v2);
5528 if(ivideo->haveXGIROM) {
5529 ptr = (const u8 *)&bios[0x170];
5531 for(i = 0, j = 0; i < 7; i++, j += 8) {
5532 SiS_SetReg(SISCR, 0x90 + i, ptr[j + regb]);
5535 SiS_SetReg(SISCR, 0x59, v3);
5538 if(ivideo->haveXGIROM) {
5539 ptr = (const u8 *)&bios[0x1a8];
5541 for(i = 0, j = 0; i < 3; i++, j += 8) {
5542 SiS_SetReg(SISCR, 0xc3 + i, ptr[j + regb]);
5546 if(ivideo->haveXGIROM) {
5547 ptr = (const u8 *)&bios[0x100];
5549 for(i = 0, j = 0; i < 2; i++, j += 8) {
5550 SiS_SetReg(SISCR, 0x8a + i, ptr[j + regb]);
5553 SiS_SetReg(SISCR, 0xcf, v4);
5555 SiS_SetReg(SISCR, 0x83, 0x09);
5556 SiS_SetReg(SISCR, 0x87, 0x00);
5558 if(ivideo->chip == XGI_40) {
5559 if( (ivideo->revision_id == 1) ||
5560 (ivideo->revision_id == 2) ) {
5561 SiS_SetReg(SISCR, 0x8c, 0x87);
5566 SiS_SetReg(SISSR, 0x17, 0x80); /* DDR2 */
5568 SiS_SetReg(SISSR, 0x17, 0x00); /* DDR1 */
5569 SiS_SetReg(SISSR, 0x1a, 0x87);
5571 if(ivideo->chip == XGI_20) {
5572 SiS_SetReg(SISSR, 0x15, 0x00);
5573 SiS_SetReg(SISSR, 0x1c, 0x00);
5578 sisfb_post_xgi_setclocks(ivideo, regb);
5579 if((ivideo->chip == XGI_20) ||
5580 (ivideo->revision_id == 1) ||
5581 (ivideo->revision_id == 2)) {
5582 v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb];
5583 if(ivideo->haveXGIROM) {
5584 v1 = bios[regb + 0x158];
5585 v2 = bios[regb + 0x160];
5586 v3 = bios[regb + 0x168];
5588 SiS_SetReg(SISCR, 0x82, v1);
5589 SiS_SetReg(SISCR, 0x85, v2);
5590 SiS_SetReg(SISCR, 0x86, v3);
5592 SiS_SetReg(SISCR, 0x82, 0x88);
5593 SiS_SetReg(SISCR, 0x86, 0x00);
5594 reg = SiS_GetReg(SISCR, 0x86);
5595 SiS_SetReg(SISCR, 0x86, 0x88);
5596 reg = SiS_GetReg(SISCR, 0x86);
5597 SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
5598 SiS_SetReg(SISCR, 0x82, 0x77);
5599 SiS_SetReg(SISCR, 0x85, 0x00);
5600 reg = SiS_GetReg(SISCR, 0x85);
5601 SiS_SetReg(SISCR, 0x85, 0x88);
5602 reg = SiS_GetReg(SISCR, 0x85);
5603 SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
5604 SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
5606 if(ivideo->chip == XGI_40) {
5607 SiS_SetReg(SISCR, 0x97, 0x00);
5609 SiS_SetReg(SISCR, 0x98, 0x01);
5610 SiS_SetReg(SISCR, 0x9a, 0x02);
5612 SiS_SetReg(SISSR, 0x18, 0x01);
5613 if((ivideo->chip == XGI_20) ||
5614 (ivideo->revision_id == 2)) {
5615 SiS_SetReg(SISSR, 0x19, 0x40);
5617 SiS_SetReg(SISSR, 0x19, 0x20);
5619 SiS_SetReg(SISSR, 0x16, 0x00);
5620 SiS_SetReg(SISSR, 0x16, 0x80);
5621 if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
5622 sisfb_post_xgi_delay(ivideo, 0x43);
5623 sisfb_post_xgi_delay(ivideo, 0x43);
5624 sisfb_post_xgi_delay(ivideo, 0x43);
5625 SiS_SetReg(SISSR, 0x18, 0x00);
5626 if((ivideo->chip == XGI_20) ||
5627 (ivideo->revision_id == 2)) {
5628 SiS_SetReg(SISSR, 0x19, 0x40);
5630 SiS_SetReg(SISSR, 0x19, 0x20);
5632 } else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
5633 /* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
5635 SiS_SetReg(SISSR, 0x16, 0x00);
5636 SiS_SetReg(SISSR, 0x16, 0x80);
5637 sisfb_post_xgi_delay(ivideo, 4);
5638 v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
5639 if(ivideo->haveXGIROM) {
5641 index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e;
5643 v3 = bios[index + 1];
5644 v4 = bios[index + 2];
5645 v5 = bios[index + 3];
5647 SiS_SetReg(SISSR, 0x18, v1);
5648 SiS_SetReg(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
5649 SiS_SetReg(SISSR, 0x16, v2);
5650 SiS_SetReg(SISSR, 0x16, v3);
5651 sisfb_post_xgi_delay(ivideo, 0x43);
5652 SiS_SetReg(SISSR, 0x1b, 0x03);
5653 sisfb_post_xgi_delay(ivideo, 0x22);
5654 SiS_SetReg(SISSR, 0x18, v1);
5655 SiS_SetReg(SISSR, 0x19, 0x00);
5656 SiS_SetReg(SISSR, 0x16, v4);
5657 SiS_SetReg(SISSR, 0x16, v5);
5658 SiS_SetReg(SISSR, 0x1b, 0x00);
5661 sisfb_post_xgi_ddr2(ivideo, regb);
5664 sisfb_post_xgi_setclocks(ivideo, regb);
5665 if((ivideo->chip == XGI_40) &&
5666 ((ivideo->revision_id == 1) ||
5667 (ivideo->revision_id == 2))) {
5668 SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
5669 SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
5670 SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
5672 SiS_SetReg(SISCR, 0x82, 0x88);
5673 SiS_SetReg(SISCR, 0x86, 0x00);
5674 reg = SiS_GetReg(SISCR, 0x86);
5675 SiS_SetReg(SISCR, 0x86, 0x88);
5676 SiS_SetReg(SISCR, 0x82, 0x77);
5677 SiS_SetReg(SISCR, 0x85, 0x00);
5678 reg = SiS_GetReg(SISCR, 0x85);
5679 SiS_SetReg(SISCR, 0x85, 0x88);
5680 reg = SiS_GetReg(SISCR, 0x85);
5681 v1 = cs160[regb]; v2 = cs158[regb];
5682 if(ivideo->haveXGIROM) {
5683 v1 = bios[regb + 0x160];
5684 v2 = bios[regb + 0x158];
5686 SiS_SetReg(SISCR, 0x85, v1);
5687 SiS_SetReg(SISCR, 0x82, v2);
5689 if(ivideo->chip == XGI_40) {
5690 SiS_SetReg(SISCR, 0x97, 0x11);
5692 if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
5693 SiS_SetReg(SISCR, 0x98, 0x01);
5695 SiS_SetReg(SISCR, 0x98, 0x03);
5697 SiS_SetReg(SISCR, 0x9a, 0x02);
5699 if(ivideo->chip == XGI_40) {
5700 SiS_SetReg(SISSR, 0x18, 0x01);
5702 SiS_SetReg(SISSR, 0x18, 0x00);
5704 SiS_SetReg(SISSR, 0x19, 0x40);
5705 SiS_SetReg(SISSR, 0x16, 0x00);
5706 SiS_SetReg(SISSR, 0x16, 0x80);
5707 if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
5708 sisfb_post_xgi_delay(ivideo, 0x43);
5709 sisfb_post_xgi_delay(ivideo, 0x43);
5710 sisfb_post_xgi_delay(ivideo, 0x43);
5711 SiS_SetReg(SISSR, 0x18, 0x00);
5712 SiS_SetReg(SISSR, 0x19, 0x40);
5713 SiS_SetReg(SISSR, 0x16, 0x00);
5714 SiS_SetReg(SISSR, 0x16, 0x80);
5716 sisfb_post_xgi_delay(ivideo, 4);
5718 if(ivideo->haveXGIROM) {
5721 SiS_SetReg(SISSR, 0x18, v1);
5722 SiS_SetReg(SISSR, 0x19, 0x01);
5723 if(ivideo->chip == XGI_40) {
5724 SiS_SetReg(SISSR, 0x16, bios[0x53e]);
5725 SiS_SetReg(SISSR, 0x16, bios[0x53f]);
5727 SiS_SetReg(SISSR, 0x16, 0x05);
5728 SiS_SetReg(SISSR, 0x16, 0x85);
5730 sisfb_post_xgi_delay(ivideo, 0x43);
5731 if(ivideo->chip == XGI_40) {
5732 SiS_SetReg(SISSR, 0x1b, 0x01);
5734 SiS_SetReg(SISSR, 0x1b, 0x03);
5736 sisfb_post_xgi_delay(ivideo, 0x22);
5737 SiS_SetReg(SISSR, 0x18, v1);
5738 SiS_SetReg(SISSR, 0x19, 0x00);
5739 if(ivideo->chip == XGI_40) {
5740 SiS_SetReg(SISSR, 0x16, bios[0x540]);
5741 SiS_SetReg(SISSR, 0x16, bios[0x541]);
5743 SiS_SetReg(SISSR, 0x16, 0x05);
5744 SiS_SetReg(SISSR, 0x16, 0x85);
5746 SiS_SetReg(SISSR, 0x1b, 0x00);
5751 if(ivideo->haveXGIROM) {
5752 v1 = bios[0x110 + regb];
5754 SiS_SetReg(SISSR, 0x1b, v1);
5757 v1 = 0x00; v2 = 0x00;
5758 if(ivideo->haveXGIROM) {
5764 if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
5766 SiS_SetReg(SISSR, 0x13, bios[regb + 0xe0]);
5767 SiS_SetReg(SISSR, 0x14, bios[regb + 0xe0 + 8]);
5772 /* Set default mode, don't clear screen */
5773 ivideo->SiS_Pr.SiS_UseOEM = false;
5774 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
5775 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
5776 ivideo->curFSTN = ivideo->curDSTN = 0;
5777 ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
5778 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5780 SiS_SetReg(SISSR, 0x05, 0x86);
5782 /* Disable read-cache */
5783 SiS_SetRegAND(SISSR, 0x21, 0xdf);
5784 err = sisfb_post_xgi_ramsize(ivideo);
5785 /* Enable read-cache */
5786 SiS_SetRegOR(SISSR, 0x21, 0x20);
5790 "%s: RAM size detection failed: %d\n",
5797 printk(KERN_DEBUG "-----------------\n");
5798 for(i = 0; i < 0xff; i++) {
5799 reg = SiS_GetReg(SISCR, i);
5800 printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
5802 for(i = 0; i < 0x40; i++) {
5803 reg = SiS_GetReg(SISSR, i);
5804 printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
5806 printk(KERN_DEBUG "-----------------\n");
5810 if(ivideo->chip == XGI_20) {
5811 SiS_SetRegOR(SISCR, 0x32, 0x20);
5813 reg = SiS_GetReg(SISPART4, 0x00);
5814 if((reg == 1) || (reg == 2)) {
5815 sisfb_sense_crt1(ivideo);
5817 SiS_SetRegOR(SISCR, 0x32, 0x20);
5821 /* Set default mode, don't clear screen */
5822 ivideo->SiS_Pr.SiS_UseOEM = false;
5823 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
5824 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
5825 ivideo->curFSTN = ivideo->curDSTN = 0;
5826 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5828 SiS_SetReg(SISSR, 0x05, 0x86);
5831 SiS_SetRegOR(SISSR, 0x01, 0x20);
5833 /* Save mode number in CR34 */
5834 SiS_SetReg(SISCR, 0x34, 0x2e);
5836 /* Let everyone know what the current mode is */
5837 ivideo->modeprechange = 0x2e;
5839 if(ivideo->chip == XGI_40) {
5840 reg = SiS_GetReg(SISCR, 0xca);
5841 v1 = SiS_GetReg(SISCR, 0xcc);
5842 if((reg & 0x10) && (!(v1 & 0x04))) {
5844 "sisfb: Please connect power to the card.\n");
5853 static int sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
5855 struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data];
5856 struct sis_video_info *ivideo = NULL;
5857 struct fb_info *sis_fb_info = NULL;
5865 ret = aperture_remove_conflicting_pci_devices(pdev, "sisfb");
5869 sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
5873 ivideo = (struct sis_video_info *)sis_fb_info->par;
5874 ivideo->memyselfandi = sis_fb_info;
5876 ivideo->sisfb_id = SISFB_ID;
5878 if(card_list == NULL) {
5879 ivideo->cardnumber = 0;
5881 struct sis_video_info *countvideo = card_list;
5882 ivideo->cardnumber = 1;
5883 while((countvideo = countvideo->next) != NULL)
5884 ivideo->cardnumber++;
5887 strscpy(ivideo->myid, chipinfo->chip_name, sizeof(ivideo->myid));
5889 ivideo->warncount = 0;
5890 ivideo->chip_id = pdev->device;
5891 ivideo->chip_vendor = pdev->vendor;
5892 ivideo->revision_id = pdev->revision;
5893 ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
5894 pci_read_config_word(pdev, PCI_COMMAND, ®16);
5895 ivideo->sisvga_enabled = reg16 & 0x01;
5896 ivideo->pcibus = pdev->bus->number;
5897 ivideo->pcislot = PCI_SLOT(pdev->devfn);
5898 ivideo->pcifunc = PCI_FUNC(pdev->devfn);
5899 ivideo->subsysvendor = pdev->subsystem_vendor;
5900 ivideo->subsysdevice = pdev->subsystem_device;
5903 if(sisfb_mode_idx == -1) {
5904 sisfb_get_vga_mode_from_kernel();
5908 ivideo->chip = chipinfo->chip;
5909 ivideo->chip_real_id = chipinfo->chip;
5910 ivideo->sisvga_engine = chipinfo->vgaengine;
5911 ivideo->hwcursor_size = chipinfo->hwcursor_size;
5912 ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
5913 ivideo->mni = chipinfo->mni;
5915 ivideo->detectedpdc = 0xff;
5916 ivideo->detectedpdca = 0xff;
5917 ivideo->detectedlcda = 0xff;
5919 ivideo->sisfb_thismonitor.datavalid = false;
5921 ivideo->current_base = 0;
5923 ivideo->engineok = 0;
5925 ivideo->sisfb_was_boot_device = 0;
5927 if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
5928 if(ivideo->sisvga_enabled)
5929 ivideo->sisfb_was_boot_device = 1;
5931 printk(KERN_DEBUG "sisfb: PCI device is disabled, "
5932 "but marked as boot video device ???\n");
5933 printk(KERN_DEBUG "sisfb: I will not accept this "
5934 "as the primary VGA device\n");
5938 ivideo->sisfb_parm_mem = sisfb_parm_mem;
5939 ivideo->sisfb_accel = sisfb_accel;
5940 ivideo->sisfb_ypan = sisfb_ypan;
5941 ivideo->sisfb_max = sisfb_max;
5942 ivideo->sisfb_userom = sisfb_userom;
5943 ivideo->sisfb_useoem = sisfb_useoem;
5944 ivideo->sisfb_mode_idx = sisfb_mode_idx;
5945 ivideo->sisfb_parm_rate = sisfb_parm_rate;
5946 ivideo->sisfb_crt1off = sisfb_crt1off;
5947 ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
5948 ivideo->sisfb_crt2type = sisfb_crt2type;
5949 ivideo->sisfb_crt2flags = sisfb_crt2flags;
5950 /* pdc(a), scalelcd, special timing, lvdshl handled below */
5951 ivideo->sisfb_dstn = sisfb_dstn;
5952 ivideo->sisfb_fstn = sisfb_fstn;
5953 ivideo->sisfb_tvplug = sisfb_tvplug;
5954 ivideo->sisfb_tvstd = sisfb_tvstd;
5955 ivideo->tvxpos = sisfb_tvxposoffset;
5956 ivideo->tvypos = sisfb_tvyposoffset;
5957 ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
5958 ivideo->refresh_rate = 0;
5959 if(ivideo->sisfb_parm_rate != -1) {
5960 ivideo->refresh_rate = ivideo->sisfb_parm_rate;
5963 ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
5964 ivideo->SiS_Pr.CenterScreen = -1;
5965 ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
5966 ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
5968 ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
5969 ivideo->SiS_Pr.SiS_CHOverScan = -1;
5970 ivideo->SiS_Pr.SiS_ChSW = false;
5971 ivideo->SiS_Pr.SiS_UseLCDA = false;
5972 ivideo->SiS_Pr.HaveEMI = false;
5973 ivideo->SiS_Pr.HaveEMILCD = false;
5974 ivideo->SiS_Pr.OverruleEMI = false;
5975 ivideo->SiS_Pr.SiS_SensibleSR11 = false;
5976 ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
5977 ivideo->SiS_Pr.PDC = -1;
5978 ivideo->SiS_Pr.PDCA = -1;
5979 ivideo->SiS_Pr.DDCPortMixup = false;
5980 #ifdef CONFIG_FB_SIS_315
5981 if(ivideo->chip >= SIS_330) {
5982 ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
5983 if(ivideo->chip >= SIS_661) {
5984 ivideo->SiS_Pr.SiS_SensibleSR11 = true;
5989 memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));
5991 pci_set_drvdata(pdev, ivideo);
5993 /* Patch special cases */
5994 if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) {
5995 switch(ivideo->nbridge->device) {
5996 #ifdef CONFIG_FB_SIS_300
5997 case PCI_DEVICE_ID_SI_730:
5998 ivideo->chip = SIS_730;
5999 strcpy(ivideo->myid, "SiS 730");
6002 #ifdef CONFIG_FB_SIS_315
6003 case PCI_DEVICE_ID_SI_651:
6004 /* ivideo->chip is ok */
6005 strcpy(ivideo->myid, "SiS 651");
6007 case PCI_DEVICE_ID_SI_740:
6008 ivideo->chip = SIS_740;
6009 strcpy(ivideo->myid, "SiS 740");
6011 case PCI_DEVICE_ID_SI_661:
6012 ivideo->chip = SIS_661;
6013 strcpy(ivideo->myid, "SiS 661");
6015 case PCI_DEVICE_ID_SI_741:
6016 ivideo->chip = SIS_741;
6017 strcpy(ivideo->myid, "SiS 741");
6019 case PCI_DEVICE_ID_SI_760:
6020 ivideo->chip = SIS_760;
6021 strcpy(ivideo->myid, "SiS 760");
6023 case PCI_DEVICE_ID_SI_761:
6024 ivideo->chip = SIS_761;
6025 strcpy(ivideo->myid, "SiS 761");
6033 ivideo->SiS_Pr.ChipType = ivideo->chip;
6035 ivideo->SiS_Pr.ivideo = (void *)ivideo;
6037 #ifdef CONFIG_FB_SIS_315
6038 if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
6039 (ivideo->SiS_Pr.ChipType == SIS_315)) {
6040 ivideo->SiS_Pr.ChipType = SIS_315H;
6044 if(!ivideo->sisvga_enabled) {
6045 if(pci_enable_device(pdev)) {
6046 pci_dev_put(ivideo->nbridge);
6047 framebuffer_release(sis_fb_info);
6052 ivideo->video_base = pci_resource_start(pdev, 0);
6053 ivideo->video_size = pci_resource_len(pdev, 0);
6054 ivideo->mmio_base = pci_resource_start(pdev, 1);
6055 ivideo->mmio_size = pci_resource_len(pdev, 1);
6056 ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
6057 ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
6059 SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress);
6061 #ifdef CONFIG_FB_SIS_300
6062 /* Find PCI systems for Chrontel/GPIO communication setup */
6063 if(ivideo->chip == SIS_630) {
6066 if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
6067 mychswtable[i].subsysCard == ivideo->subsysdevice) {
6068 ivideo->SiS_Pr.SiS_ChSW = true;
6069 printk(KERN_DEBUG "sisfb: Identified [%s %s] "
6070 "requiring Chrontel/GPIO setup\n",
6071 mychswtable[i].vendorName,
6072 mychswtable[i].cardName);
6073 ivideo->lpcdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, NULL);
6077 } while(mychswtable[i].subsysVendor != 0);
6081 #ifdef CONFIG_FB_SIS_315
6082 if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
6083 ivideo->lpcdev = pci_get_slot(ivideo->nbridge->bus, (2 << 3));
6087 SiS_SetReg(SISSR, 0x05, 0x86);
6089 if( (!ivideo->sisvga_enabled)
6090 #if !defined(__i386__) && !defined(__x86_64__)
6091 || (sisfb_resetcard)
6094 for(i = 0x30; i <= 0x3f; i++) {
6095 SiS_SetReg(SISCR, i, 0x00);
6099 /* Find out about current video mode */
6100 ivideo->modeprechange = 0x03;
6101 reg = SiS_GetReg(SISCR, 0x34);
6103 ivideo->modeprechange = reg & 0x7f;
6104 } else if(ivideo->sisvga_enabled) {
6105 #if defined(__i386__) || defined(__x86_64__)
6106 unsigned char __iomem *tt = ioremap(0x400, 0x100);
6108 ivideo->modeprechange = readb(tt + 0x49);
6114 /* Search and copy ROM image */
6115 ivideo->bios_abase = NULL;
6116 ivideo->SiS_Pr.VirtualRomBase = NULL;
6117 ivideo->SiS_Pr.UseROM = false;
6118 ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = false;
6119 if(ivideo->sisfb_userom) {
6120 ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
6121 ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
6122 ivideo->SiS_Pr.UseROM = (bool)(ivideo->SiS_Pr.VirtualRomBase);
6123 printk(KERN_INFO "sisfb: Video ROM %sfound\n",
6124 ivideo->SiS_Pr.UseROM ? "" : "not ");
6125 if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
6126 ivideo->SiS_Pr.UseROM = false;
6127 ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = true;
6128 if( (ivideo->revision_id == 2) &&
6129 (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
6130 ivideo->SiS_Pr.DDCPortMixup = true;
6134 printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
6137 /* Find systems for special custom timing */
6138 if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
6139 sisfb_detect_custom_timing(ivideo);
6142 #ifdef CONFIG_FB_SIS_315
6143 if (ivideo->chip == XGI_20) {
6144 /* Check if our Z7 chip is actually Z9 */
6145 SiS_SetRegOR(SISCR, 0x4a, 0x40); /* GPIOG EN */
6146 reg = SiS_GetReg(SISCR, 0x48);
6147 if (reg & 0x02) { /* GPIOG */
6148 ivideo->chip_real_id = XGI_21;
6149 dev_info(&pdev->dev, "Z9 detected\n");
6154 /* POST card in case this has not been done by the BIOS */
6155 if( (!ivideo->sisvga_enabled)
6156 #if !defined(__i386__) && !defined(__x86_64__)
6157 || (sisfb_resetcard)
6160 #ifdef CONFIG_FB_SIS_300
6161 if(ivideo->sisvga_engine == SIS_300_VGA) {
6162 if(ivideo->chip == SIS_300) {
6163 sisfb_post_sis300(pdev);
6164 ivideo->sisfb_can_post = 1;
6169 #ifdef CONFIG_FB_SIS_315
6170 if (ivideo->sisvga_engine == SIS_315_VGA) {
6173 if (ivideo->chip == XGI_20) {
6174 result = sisfb_post_xgi(pdev);
6175 ivideo->sisfb_can_post = 1;
6176 } else if ((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
6177 result = sisfb_post_xgi(pdev);
6178 ivideo->sisfb_can_post = 1;
6180 printk(KERN_INFO "sisfb: Card is not "
6181 "POSTed and sisfb can't do this either.\n");
6184 printk(KERN_ERR "sisfb: Failed to POST card\n");
6192 ivideo->sisfb_card_posted = 1;
6194 /* Find out about RAM size */
6195 if(sisfb_get_dram_size(ivideo)) {
6196 printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
6202 /* Enable PCI addressing and MMIO */
6203 if((ivideo->sisfb_mode_idx < 0) ||
6204 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6205 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
6206 SiS_SetRegOR(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
6207 /* Enable 2D accelerator engine */
6208 SiS_SetRegOR(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
6211 if(sisfb_pdc != 0xff) {
6212 if(ivideo->sisvga_engine == SIS_300_VGA)
6216 ivideo->SiS_Pr.PDC = sisfb_pdc;
6218 #ifdef CONFIG_FB_SIS_315
6219 if(ivideo->sisvga_engine == SIS_315_VGA) {
6220 if(sisfb_pdca != 0xff)
6221 ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
6225 if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
6226 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6227 (int)(ivideo->video_size >> 20));
6228 printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
6233 if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
6234 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
6239 ivideo->video_vbase = ioremap_wc(ivideo->video_base, ivideo->video_size);
6240 ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
6241 if(!ivideo->video_vbase) {
6242 printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
6247 ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
6248 if(!ivideo->mmio_vbase) {
6249 printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
6251 error_0: iounmap(ivideo->video_vbase);
6252 error_1: release_mem_region(ivideo->video_base, ivideo->video_size);
6253 error_2: release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6254 error_3: vfree(ivideo->bios_abase);
6255 pci_dev_put(ivideo->lpcdev);
6256 pci_dev_put(ivideo->nbridge);
6257 if(!ivideo->sisvga_enabled)
6258 pci_disable_device(pdev);
6259 framebuffer_release(sis_fb_info);
6263 printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
6264 ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);
6266 if(ivideo->video_offset) {
6267 printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
6268 ivideo->video_offset / 1024);
6271 printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
6272 ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
6275 /* Determine the size of the command queue */
6276 if(ivideo->sisvga_engine == SIS_300_VGA) {
6277 ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
6279 if(ivideo->chip == XGI_20) {
6280 ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
6282 ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
6286 /* Engines are no longer initialized here; this is
6287 * now done after the first mode-switch (if the
6288 * submitted var has its acceleration flags set).
6291 /* Calculate the base of the (unused) hw cursor */
6292 ivideo->hwcursor_vbase = ivideo->video_vbase
6293 + ivideo->video_size
6294 - ivideo->cmdQueueSize
6295 - ivideo->hwcursor_size;
6296 ivideo->caps |= HW_CURSOR_CAP;
6298 /* Initialize offscreen memory manager */
6299 if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
6300 printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
6303 /* Used for clearing the screen only, therefore respect our mem limit */
6304 ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
6305 ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;
6307 ivideo->vbflags = 0;
6308 ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
6309 ivideo->tvdefmodeidx = DEFAULT_TVMODE;
6310 ivideo->defmodeidx = DEFAULT_MODE;
6313 if(ivideo->chip < XGI_20) {
6314 if(ivideo->bios_abase) {
6315 ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr);
6319 if((ivideo->sisfb_mode_idx < 0) ||
6320 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6322 sisfb_sense_crt1(ivideo);
6324 sisfb_get_VB_type(ivideo);
6326 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6327 sisfb_detect_VB_connect(ivideo);
6330 ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
6332 /* Decide on which CRT2 device to use */
6333 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6334 if(ivideo->sisfb_crt2type != -1) {
6335 if((ivideo->sisfb_crt2type == CRT2_LCD) &&
6336 (ivideo->vbflags & CRT2_LCD)) {
6337 ivideo->currentvbflags |= CRT2_LCD;
6338 } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
6339 ivideo->currentvbflags |= ivideo->sisfb_crt2type;
6342 /* Chrontel 700x TV detection often unreliable, therefore
6343 * use a different default order on such machines
6345 if((ivideo->sisvga_engine == SIS_300_VGA) &&
6346 (ivideo->vbflags2 & VB2_CHRONTEL)) {
6347 if(ivideo->vbflags & CRT2_LCD)
6348 ivideo->currentvbflags |= CRT2_LCD;
6349 else if(ivideo->vbflags & CRT2_TV)
6350 ivideo->currentvbflags |= CRT2_TV;
6351 else if(ivideo->vbflags & CRT2_VGA)
6352 ivideo->currentvbflags |= CRT2_VGA;
6354 if(ivideo->vbflags & CRT2_TV)
6355 ivideo->currentvbflags |= CRT2_TV;
6356 else if(ivideo->vbflags & CRT2_LCD)
6357 ivideo->currentvbflags |= CRT2_LCD;
6358 else if(ivideo->vbflags & CRT2_VGA)
6359 ivideo->currentvbflags |= CRT2_VGA;
6364 if(ivideo->vbflags & CRT2_LCD) {
6365 sisfb_detect_lcd_type(ivideo);
6368 sisfb_save_pdc_emi(ivideo);
6370 if(!ivideo->sisfb_crt1off) {
6371 sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
6373 if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
6374 (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
6375 sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
6379 if(ivideo->sisfb_mode_idx >= 0) {
6380 int bu = ivideo->sisfb_mode_idx;
6381 ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
6382 ivideo->sisfb_mode_idx, ivideo->currentvbflags);
6383 if(bu != ivideo->sisfb_mode_idx) {
6384 printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
6385 sisbios_mode[bu].xres,
6386 sisbios_mode[bu].yres,
6387 sisbios_mode[bu].bpp);
6391 if(ivideo->sisfb_mode_idx < 0) {
6392 switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
6394 ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
6397 ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
6400 ivideo->sisfb_mode_idx = ivideo->defmodeidx;
6405 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
6407 if(ivideo->refresh_rate != 0) {
6408 sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate,
6409 ivideo->sisfb_mode_idx);
6412 if(ivideo->rate_idx == 0) {
6413 ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
6414 ivideo->refresh_rate = 60;
6417 if(ivideo->sisfb_thismonitor.datavalid) {
6418 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor,
6419 ivideo->sisfb_mode_idx,
6421 ivideo->refresh_rate)) {
6422 printk(KERN_INFO "sisfb: WARNING: Refresh rate "
6423 "exceeds monitor specs!\n");
6427 ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
6428 ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
6429 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
6431 sisfb_set_vparms(ivideo);
6433 printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
6434 ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
6435 ivideo->refresh_rate);
6437 /* Set up the default var according to chosen default display mode */
6438 ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
6439 ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
6440 ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
6442 sisfb_bpp_to_var(ivideo, &ivideo->default_var);
6444 ivideo->default_var.pixclock = (u32) (1000000000 /
6445 sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx));
6447 if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no,
6448 ivideo->rate_idx, &ivideo->default_var)) {
6449 if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
6450 ivideo->default_var.pixclock <<= 1;
6454 if(ivideo->sisfb_ypan) {
6455 /* Maximize regardless of sisfb_max at startup */
6456 ivideo->default_var.yres_virtual =
6457 sisfb_calc_maxyres(ivideo, &ivideo->default_var);
6458 if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
6459 ivideo->default_var.yres_virtual = ivideo->default_var.yres;
6463 sisfb_calc_pitch(ivideo, &ivideo->default_var);
6466 if(ivideo->sisfb_accel) {
6468 #ifdef STUPID_ACCELF_TEXT_SHIT
6469 ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
6472 sisfb_initaccel(ivideo);
6474 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
6475 sis_fb_info->flags = FBINFO_DEFAULT |
6476 FBINFO_HWACCEL_YPAN |
6477 FBINFO_HWACCEL_XPAN |
6478 FBINFO_HWACCEL_COPYAREA |
6479 FBINFO_HWACCEL_FILLRECT |
6480 ((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED);
6482 sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
6484 sis_fb_info->var = ivideo->default_var;
6485 sis_fb_info->fix = ivideo->sisfb_fix;
6486 sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
6487 sis_fb_info->fbops = &sisfb_ops;
6488 sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
6490 fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
6492 printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
6494 ivideo->wc_cookie = arch_phys_wc_add(ivideo->video_base,
6495 ivideo->video_size);
6496 if(register_framebuffer(sis_fb_info) < 0) {
6497 printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
6499 iounmap(ivideo->mmio_vbase);
6503 ivideo->registered = 1;
6506 ivideo->next = card_list;
6509 printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
6510 ivideo->sisfb_accel ? "enabled" : "disabled",
6511 ivideo->sisfb_ypan ?
6512 (ivideo->sisfb_max ? "enabled (auto-max)" :
6513 "enabled (no auto-max)") :
6517 fb_info(sis_fb_info, "%s frame buffer device version %d.%d.%d\n",
6518 ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
6520 printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
6522 } /* if mode = "none" */
6527 /*****************************************************/
6528 /* PCI DEVICE HANDLING */
6529 /*****************************************************/
6531 static void sisfb_remove(struct pci_dev *pdev)
6533 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
6534 struct fb_info *sis_fb_info = ivideo->memyselfandi;
6535 int registered = ivideo->registered;
6536 int modechanged = ivideo->modechanged;
6539 iounmap(ivideo->mmio_vbase);
6540 iounmap(ivideo->video_vbase);
6542 /* Release mem regions */
6543 release_mem_region(ivideo->video_base, ivideo->video_size);
6544 release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6546 vfree(ivideo->bios_abase);
6548 pci_dev_put(ivideo->lpcdev);
6550 pci_dev_put(ivideo->nbridge);
6552 arch_phys_wc_del(ivideo->wc_cookie);
6554 /* If device was disabled when starting, disable
6557 if(!ivideo->sisvga_enabled)
6558 pci_disable_device(pdev);
6560 /* Unregister the framebuffer */
6561 if(ivideo->registered) {
6562 unregister_framebuffer(sis_fb_info);
6563 framebuffer_release(sis_fb_info);
6566 /* OK, our ivideo is gone for good from here. */
6568 /* TODO: Restore the initial mode
6569 * This sounds easy but is as good as impossible
6570 * on many machines with SiS chip and video bridge
6571 * since text modes are always set up differently
6572 * from machine to machine. Depends on the type
6573 * of integration between chipset and bridge.
6575 if(registered && modechanged)
6577 "sisfb: Restoring of text mode not supported yet\n");
6580 static struct pci_driver sisfb_driver = {
6582 .id_table = sisfb_pci_table,
6583 .probe = sisfb_probe,
6584 .remove = sisfb_remove,
6587 static int __init sisfb_init(void)
6590 char *options = NULL;
6593 if (fb_modesetting_disabled("sisfb"))
6597 if(fb_get_options("sisfb", &options))
6600 sisfb_setup(options);
6602 return pci_register_driver(&sisfb_driver);
6606 module_init(sisfb_init);
6609 /*****************************************************/
6611 /*****************************************************/
6615 static char *mode = NULL;
6616 static int vesa = -1;
6617 static unsigned int rate = 0;
6618 static unsigned int crt1off = 1;
6619 static unsigned int mem = 0;
6620 static char *forcecrt2type = NULL;
6621 static int forcecrt1 = -1;
6622 static int pdc = -1;
6623 static int pdc1 = -1;
6624 static int noaccel = -1;
6625 static int noypan = -1;
6626 static int nomax = -1;
6627 static int userom = -1;
6628 static int useoem = -1;
6629 static char *tvstandard = NULL;
6630 static int nocrt2rate = 0;
6631 static int scalelcd = -1;
6632 static char *specialtiming = NULL;
6633 static int lvdshl = -1;
6634 static int tvxposoffset = 0, tvyposoffset = 0;
6635 #if !defined(__i386__) && !defined(__x86_64__)
6636 static int resetcard = 0;
6637 static int videoram = 0;
6640 static int __init sisfb_init_module(void)
6642 sisfb_setdefaultparms();
6645 sisfb_parm_rate = rate;
6647 if((scalelcd == 0) || (scalelcd == 1))
6648 sisfb_scalelcd = scalelcd ^ 1;
6650 /* Need to check crt2 type first for fstn/dstn */
6653 sisfb_search_crt2type(forcecrt2type);
6656 sisfb_search_tvstd(tvstandard);
6659 sisfb_search_mode(mode, false);
6661 sisfb_search_vesamode(vesa, false);
6663 sisfb_crt1off = (crt1off == 0) ? 1 : 0;
6665 sisfb_forcecrt1 = forcecrt1;
6668 else if(forcecrt1 == 0)
6673 else if(noaccel == 0)
6678 else if(noypan == 0)
6687 sisfb_parm_mem = mem;
6690 sisfb_userom = userom;
6693 sisfb_useoem = useoem;
6696 sisfb_pdc = (pdc & 0x7f);
6699 sisfb_pdca = (pdc1 & 0x1f);
6701 sisfb_nocrt2rate = nocrt2rate;
6704 sisfb_search_specialtiming(specialtiming);
6706 if((lvdshl >= 0) && (lvdshl <= 3))
6707 sisfb_lvdshl = lvdshl;
6709 sisfb_tvxposoffset = tvxposoffset;
6710 sisfb_tvyposoffset = tvyposoffset;
6712 #if !defined(__i386__) && !defined(__x86_64__)
6713 sisfb_resetcard = (resetcard) ? 1 : 0;
6715 sisfb_videoram = videoram;
6718 return sisfb_init();
6721 static void __exit sisfb_remove_module(void)
6723 pci_unregister_driver(&sisfb_driver);
6724 printk(KERN_DEBUG "sisfb: Module unloaded\n");
6727 module_init(sisfb_init_module);
6728 module_exit(sisfb_remove_module);
6730 MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
6731 MODULE_LICENSE("GPL");
6734 module_param(mem, int, 0);
6735 module_param(noaccel, int, 0);
6736 module_param(noypan, int, 0);
6737 module_param(nomax, int, 0);
6738 module_param(userom, int, 0);
6739 module_param(useoem, int, 0);
6740 module_param(mode, charp, 0);
6741 module_param(vesa, int, 0);
6742 module_param(rate, int, 0);
6743 module_param(forcecrt1, int, 0);
6744 module_param(forcecrt2type, charp, 0);
6745 module_param(scalelcd, int, 0);
6746 module_param(pdc, int, 0);
6747 module_param(pdc1, int, 0);
6748 module_param(specialtiming, charp, 0);
6749 module_param(lvdshl, int, 0);
6750 module_param(tvstandard, charp, 0);
6751 module_param(tvxposoffset, int, 0);
6752 module_param(tvyposoffset, int, 0);
6753 module_param(nocrt2rate, int, 0);
6754 #if !defined(__i386__) && !defined(__x86_64__)
6755 module_param(resetcard, int, 0);
6756 module_param(videoram, int, 0);
6759 MODULE_PARM_DESC(mem,
6760 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6761 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6762 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6763 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6764 "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6765 "The value is to be specified without 'KB'.\n");
6767 MODULE_PARM_DESC(noaccel,
6768 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
6771 MODULE_PARM_DESC(noypan,
6772 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
6773 "will be performed by redrawing the screen. (default: 0)\n");
6775 MODULE_PARM_DESC(nomax,
6776 "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
6777 "memory for the virtual screen in order to optimize scrolling performance. If\n"
6778 "this is set to anything other than 0, sisfb will not do this and thereby \n"
6779 "enable the user to positively specify a virtual Y size of the screen using\n"
6780 "fbset. (default: 0)\n");
6782 MODULE_PARM_DESC(mode,
6783 "\nSelects the desired default display mode in the format XxYxDepth,\n"
6784 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
6785 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
6786 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
6788 MODULE_PARM_DESC(vesa,
6789 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
6790 "0x117 (default: 0x0103)\n");
6792 MODULE_PARM_DESC(rate,
6793 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
6794 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
6795 "will be ignored (default: 60)\n");
6797 MODULE_PARM_DESC(forcecrt1,
6798 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
6799 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
6800 "0=CRT1 OFF) (default: [autodetected])\n");
6802 MODULE_PARM_DESC(forcecrt2type,
6803 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
6804 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
6805 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
6806 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
6807 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
6808 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
6809 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
6810 "depends on the very hardware in use. (default: [autodetected])\n");
6812 MODULE_PARM_DESC(scalelcd,
6813 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
6814 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
6815 "show black bars around the image, TMDS panels will probably do the scaling\n"
6816 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
6818 MODULE_PARM_DESC(pdc,
6819 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
6820 "should detect this correctly in most cases; however, sometimes this is not\n"
6821 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
6822 "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
6823 "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
6824 "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
6826 #ifdef CONFIG_FB_SIS_315
6827 MODULE_PARM_DESC(pdc1,
6828 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
6829 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
6830 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
6831 "implemented yet.\n");
6834 MODULE_PARM_DESC(specialtiming,
6835 "\nPlease refer to documentation for more information on this option.\n");
6837 MODULE_PARM_DESC(lvdshl,
6838 "\nPlease refer to documentation for more information on this option.\n");
6840 MODULE_PARM_DESC(tvstandard,
6841 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
6842 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
6844 MODULE_PARM_DESC(tvxposoffset,
6845 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
6848 MODULE_PARM_DESC(tvyposoffset,
6849 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
6852 MODULE_PARM_DESC(nocrt2rate,
6853 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
6854 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
6856 #if !defined(__i386__) && !defined(__x86_64__)
6857 #ifdef CONFIG_FB_SIS_300
6858 MODULE_PARM_DESC(resetcard,
6859 "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
6860 "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
6861 "currently). Default: 0\n");
6863 MODULE_PARM_DESC(videoram,
6864 "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
6865 "some non-x86 architectures where the memory auto detection fails. Only\n"
6866 "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
6870 #endif /* /MODULE */
6872 /* _GPL only for new symbols. */
6873 EXPORT_SYMBOL(sis_malloc);
6874 EXPORT_SYMBOL(sis_free);
6875 EXPORT_SYMBOL_GPL(sis_malloc_new);
6876 EXPORT_SYMBOL_GPL(sis_free_new);