2 * SiS 300/540/630[S]/730[S],
3 * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
5 * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
7 * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the named License,
12 * or any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
23 * Author: Thomas Winischhofer <thomas@winischhofer.net>
25 * Author of (practically wiped) code base:
27 * Copyright (C) 1999 Silicon Integrated Systems, Inc.
29 * See http://www.winischhofer.net/ for more information and updates
31 * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver,
32 * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
36 #include <linux/module.h>
37 #include <linux/moduleparam.h>
38 #include <linux/kernel.h>
39 #include <linux/spinlock.h>
40 #include <linux/errno.h>
41 #include <linux/string.h>
43 #include <linux/screen_info.h>
44 #include <linux/slab.h>
46 #include <linux/selection.h>
47 #include <linux/ioport.h>
48 #include <linux/init.h>
49 #include <linux/pci.h>
50 #include <linux/vmalloc.h>
51 #include <linux/capability.h>
53 #include <linux/types.h>
54 #include <linux/uaccess.h>
61 #if !defined(CONFIG_FB_SIS_300) && !defined(CONFIG_FB_SIS_315)
62 #warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
63 #warning sisfb will not work!
66 /* ---------------------- Prototypes ------------------------- */
68 /* Interface used by the world */
70 static int sisfb_setup(char *options
);
73 /* Interface to the low level console driver */
74 static int sisfb_init(void);
77 static int sisfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
78 struct fb_info
*info
);
80 static int sisfb_ioctl(struct fb_info
*info
, unsigned int cmd
,
82 static int sisfb_set_par(struct fb_info
*info
);
83 static int sisfb_blank(int blank
,
84 struct fb_info
*info
);
86 static void sisfb_handle_command(struct sis_video_info
*ivideo
,
87 struct sisfb_cmd
*sisfb_command
);
89 static void sisfb_search_mode(char *name
, bool quiet
);
90 static int sisfb_validate_mode(struct sis_video_info
*ivideo
, int modeindex
, u32 vbflags
);
91 static u8
sisfb_search_refresh_rate(struct sis_video_info
*ivideo
, unsigned int rate
,
93 static int sisfb_setcolreg(unsigned regno
, unsigned red
, unsigned green
,
94 unsigned blue
, unsigned transp
,
95 struct fb_info
*fb_info
);
96 static int sisfb_do_set_var(struct fb_var_screeninfo
*var
, int isactive
,
97 struct fb_info
*info
);
98 static void sisfb_pre_setmode(struct sis_video_info
*ivideo
);
99 static void sisfb_post_setmode(struct sis_video_info
*ivideo
);
100 static bool sisfb_CheckVBRetrace(struct sis_video_info
*ivideo
);
101 static bool sisfbcheckvretracecrt2(struct sis_video_info
*ivideo
);
102 static bool sisfbcheckvretracecrt1(struct sis_video_info
*ivideo
);
103 static bool sisfb_bridgeisslave(struct sis_video_info
*ivideo
);
104 static void sisfb_detect_VB_connect(struct sis_video_info
*ivideo
);
105 static void sisfb_get_VB_type(struct sis_video_info
*ivideo
);
106 static void sisfb_set_TVxposoffset(struct sis_video_info
*ivideo
, int val
);
107 static void sisfb_set_TVyposoffset(struct sis_video_info
*ivideo
, int val
);
109 /* Internal heap routines */
110 static int sisfb_heap_init(struct sis_video_info
*ivideo
);
111 static struct SIS_OH
* sisfb_poh_new_node(struct SIS_HEAP
*memheap
);
112 static struct SIS_OH
* sisfb_poh_allocate(struct SIS_HEAP
*memheap
, u32 size
);
113 static void sisfb_delete_node(struct SIS_OH
*poh
);
114 static void sisfb_insert_node(struct SIS_OH
*pohList
, struct SIS_OH
*poh
);
115 static struct SIS_OH
* sisfb_poh_free(struct SIS_HEAP
*memheap
, u32 base
);
116 static void sisfb_free_node(struct SIS_HEAP
*memheap
, struct SIS_OH
*poh
);
119 /* ------------------ Internal helper routines ----------------- */
122 sisfb_setdefaultparms(void)
132 sisfb_parm_rate
= -1;
134 sisfb_forcecrt1
= -1;
140 sisfb_specialtiming
= CUT_NONE
;
146 sisfb_tvxposoffset
= 0;
147 sisfb_tvyposoffset
= 0;
148 sisfb_nocrt2rate
= 0;
149 #if !defined(__i386__) && !defined(__x86_64__)
155 /* ------------- Parameter parsing -------------- */
157 static void sisfb_search_vesamode(unsigned int vesamode
, bool quiet
)
161 /* We don't know the hardware specs yet and there is no ivideo */
165 printk(KERN_ERR
"sisfb: Invalid mode. Using default.\n");
167 sisfb_mode_idx
= DEFAULT_MODE
;
172 vesamode
&= 0x1dff; /* Clean VESA mode number from other flags */
174 while(sisbios_mode
[i
++].mode_no
[0] != 0) {
175 if( (sisbios_mode
[i
-1].vesa_mode_no_1
== vesamode
) ||
176 (sisbios_mode
[i
-1].vesa_mode_no_2
== vesamode
) ) {
178 if(sisbios_mode
[i
-1].mode_no
[1] == 0x50 ||
179 sisbios_mode
[i
-1].mode_no
[1] == 0x56 ||
180 sisbios_mode
[i
-1].mode_no
[1] == 0x53)
183 if(sisbios_mode
[i
-1].mode_no
[1] == 0x5a ||
184 sisbios_mode
[i
-1].mode_no
[1] == 0x5b)
187 sisfb_mode_idx
= i
- 1;
193 printk(KERN_ERR
"sisfb: Invalid VESA mode 0x%x'\n", vesamode
);
196 static void sisfb_search_mode(char *name
, bool quiet
)
198 unsigned int j
= 0, xres
= 0, yres
= 0, depth
= 0, rate
= 0;
200 char strbuf
[16], strbuf1
[20];
201 char *nameptr
= name
;
203 /* We don't know the hardware specs yet and there is no ivideo */
207 printk(KERN_ERR
"sisfb: Internal error, using default mode.\n");
209 sisfb_mode_idx
= DEFAULT_MODE
;
213 if(!strncasecmp(name
, sisbios_mode
[MODE_INDEX_NONE
].name
, strlen(name
))) {
215 printk(KERN_ERR
"sisfb: Mode 'none' not supported anymore. Using default.\n");
217 sisfb_mode_idx
= DEFAULT_MODE
;
221 if(strlen(name
) <= 19) {
222 strcpy(strbuf1
, name
);
223 for(i
= 0; i
< strlen(strbuf1
); i
++) {
224 if(strbuf1
[i
] < '0' || strbuf1
[i
] > '9') strbuf1
[i
] = ' ';
227 /* This does some fuzzy mode naming detection */
228 if(sscanf(strbuf1
, "%u %u %u %u", &xres
, &yres
, &depth
, &rate
) == 4) {
229 if((rate
<= 32) || (depth
> 32)) {
230 j
= rate
; rate
= depth
; depth
= j
;
232 sprintf(strbuf
, "%ux%ux%u", xres
, yres
, depth
);
234 sisfb_parm_rate
= rate
;
235 } else if(sscanf(strbuf1
, "%u %u %u", &xres
, &yres
, &depth
) == 3) {
236 sprintf(strbuf
, "%ux%ux%u", xres
, yres
, depth
);
240 if((sscanf(strbuf1
, "%u %u", &xres
, &yres
) == 2) && (xres
!= 0)) {
241 sprintf(strbuf
, "%ux%ux8", xres
, yres
);
244 sisfb_search_vesamode(simple_strtoul(name
, NULL
, 0), quiet
);
251 while(sisbios_mode
[i
].mode_no
[0] != 0) {
252 if(!strncasecmp(nameptr
, sisbios_mode
[i
++].name
, strlen(nameptr
))) {
254 if(sisbios_mode
[i
-1].mode_no
[1] == 0x50 ||
255 sisbios_mode
[i
-1].mode_no
[1] == 0x56 ||
256 sisbios_mode
[i
-1].mode_no
[1] == 0x53)
259 if(sisbios_mode
[i
-1].mode_no
[1] == 0x5a ||
260 sisbios_mode
[i
-1].mode_no
[1] == 0x5b)
263 sisfb_mode_idx
= i
- 1;
270 printk(KERN_ERR
"sisfb: Invalid mode '%s'\n", nameptr
);
274 static void sisfb_get_vga_mode_from_kernel(void)
278 int mydepth
= screen_info
.lfb_depth
;
280 if(screen_info
.orig_video_isVGA
!= VIDEO_TYPE_VLFB
) return;
282 if( (screen_info
.lfb_width
>= 320) && (screen_info
.lfb_width
<= 2048) &&
283 (screen_info
.lfb_height
>= 200) && (screen_info
.lfb_height
<= 1536) &&
284 (mydepth
>= 8) && (mydepth
<= 32) ) {
286 if(mydepth
== 24) mydepth
= 32;
288 sprintf(mymode
, "%ux%ux%u", screen_info
.lfb_width
,
289 screen_info
.lfb_height
,
293 "sisfb: Using vga mode %s pre-set by kernel as default\n",
296 sisfb_search_mode(mymode
, true);
304 sisfb_search_crt2type(const char *name
)
308 /* We don't know the hardware specs yet and there is no ivideo */
310 if(name
== NULL
) return;
312 while(sis_crt2type
[i
].type_no
!= -1) {
313 if(!strncasecmp(name
, sis_crt2type
[i
].name
, strlen(sis_crt2type
[i
].name
))) {
314 sisfb_crt2type
= sis_crt2type
[i
].type_no
;
315 sisfb_tvplug
= sis_crt2type
[i
].tvplug_no
;
316 sisfb_crt2flags
= sis_crt2type
[i
].flags
;
322 sisfb_dstn
= (sisfb_crt2flags
& FL_550_DSTN
) ? 1 : 0;
323 sisfb_fstn
= (sisfb_crt2flags
& FL_550_FSTN
) ? 1 : 0;
325 if(sisfb_crt2type
< 0)
326 printk(KERN_ERR
"sisfb: Invalid CRT2 type: %s\n", name
);
330 sisfb_search_tvstd(const char *name
)
334 /* We don't know the hardware specs yet and there is no ivideo */
339 while(sis_tvtype
[i
].type_no
!= -1) {
340 if(!strncasecmp(name
, sis_tvtype
[i
].name
, strlen(sis_tvtype
[i
].name
))) {
341 sisfb_tvstd
= sis_tvtype
[i
].type_no
;
349 sisfb_search_specialtiming(const char *name
)
354 /* We don't know the hardware specs yet and there is no ivideo */
359 if(!strncasecmp(name
, "none", 4)) {
360 sisfb_specialtiming
= CUT_FORCENONE
;
361 printk(KERN_DEBUG
"sisfb: Special timing disabled\n");
363 while(mycustomttable
[i
].chipID
!= 0) {
364 if(!strncasecmp(name
,mycustomttable
[i
].optionName
,
365 strlen(mycustomttable
[i
].optionName
))) {
366 sisfb_specialtiming
= mycustomttable
[i
].SpecialID
;
368 printk(KERN_INFO
"sisfb: Special timing for %s %s forced (\"%s\")\n",
369 mycustomttable
[i
].vendorName
,
370 mycustomttable
[i
].cardName
,
371 mycustomttable
[i
].optionName
);
377 printk(KERN_WARNING
"sisfb: Invalid SpecialTiming parameter, valid are:");
378 printk(KERN_WARNING
"\t\"none\" (to disable special timings)\n");
380 while(mycustomttable
[i
].chipID
!= 0) {
381 printk(KERN_WARNING
"\t\"%s\" (for %s %s)\n",
382 mycustomttable
[i
].optionName
,
383 mycustomttable
[i
].vendorName
,
384 mycustomttable
[i
].cardName
);
391 /* ----------- Various detection routines ----------- */
393 static void sisfb_detect_custom_timing(struct sis_video_info
*ivideo
)
395 unsigned char *biosver
= NULL
;
396 unsigned char *biosdate
= NULL
;
401 if(ivideo
->SiS_Pr
.UseROM
) {
402 biosver
= ivideo
->SiS_Pr
.VirtualRomBase
+ 0x06;
403 biosdate
= ivideo
->SiS_Pr
.VirtualRomBase
+ 0x2c;
404 for(i
= 0; i
< 32768; i
++)
405 chksum
+= ivideo
->SiS_Pr
.VirtualRomBase
[i
];
410 if( (mycustomttable
[i
].chipID
== ivideo
->chip
) &&
411 ((!strlen(mycustomttable
[i
].biosversion
)) ||
412 (ivideo
->SiS_Pr
.UseROM
&&
413 (!strncmp(mycustomttable
[i
].biosversion
, biosver
,
414 strlen(mycustomttable
[i
].biosversion
))))) &&
415 ((!strlen(mycustomttable
[i
].biosdate
)) ||
416 (ivideo
->SiS_Pr
.UseROM
&&
417 (!strncmp(mycustomttable
[i
].biosdate
, biosdate
,
418 strlen(mycustomttable
[i
].biosdate
))))) &&
419 ((!mycustomttable
[i
].bioschksum
) ||
420 (ivideo
->SiS_Pr
.UseROM
&&
421 (mycustomttable
[i
].bioschksum
== chksum
))) &&
422 (mycustomttable
[i
].pcisubsysvendor
== ivideo
->subsysvendor
) &&
423 (mycustomttable
[i
].pcisubsyscard
== ivideo
->subsysdevice
) ) {
425 for(j
= 0; j
< 5; j
++) {
426 if(mycustomttable
[i
].biosFootprintAddr
[j
]) {
427 if(ivideo
->SiS_Pr
.UseROM
) {
428 if(ivideo
->SiS_Pr
.VirtualRomBase
[mycustomttable
[i
].biosFootprintAddr
[j
]] !=
429 mycustomttable
[i
].biosFootprintData
[j
]) {
437 ivideo
->SiS_Pr
.SiS_CustomT
= mycustomttable
[i
].SpecialID
;
438 printk(KERN_DEBUG
"sisfb: Identified [%s %s], special timing applies\n",
439 mycustomttable
[i
].vendorName
,
440 mycustomttable
[i
].cardName
);
441 printk(KERN_DEBUG
"sisfb: [specialtiming parameter name: %s]\n",
442 mycustomttable
[i
].optionName
);
447 } while(mycustomttable
[i
].chipID
);
450 static bool sisfb_interpret_edid(struct sisfb_monitor
*monitor
, u8
*buffer
)
452 int i
, j
, xres
, yres
, refresh
, index
;
455 if(buffer
[0] != 0x00 || buffer
[1] != 0xff ||
456 buffer
[2] != 0xff || buffer
[3] != 0xff ||
457 buffer
[4] != 0xff || buffer
[5] != 0xff ||
458 buffer
[6] != 0xff || buffer
[7] != 0x00) {
459 printk(KERN_DEBUG
"sisfb: Bad EDID header\n");
463 if(buffer
[0x12] != 0x01) {
464 printk(KERN_INFO
"sisfb: EDID version %d not supported\n",
469 monitor
->feature
= buffer
[0x18];
471 if(!(buffer
[0x14] & 0x80)) {
472 if(!(buffer
[0x14] & 0x08)) {
474 "sisfb: WARNING: Monitor does not support separate syncs\n");
478 if(buffer
[0x13] >= 0x01) {
479 /* EDID V1 rev 1 and 2: Search for monitor descriptor
484 if(buffer
[j
] == 0x00 && buffer
[j
+ 1] == 0x00 &&
485 buffer
[j
+ 2] == 0x00 && buffer
[j
+ 3] == 0xfd &&
486 buffer
[j
+ 4] == 0x00) {
487 monitor
->hmin
= buffer
[j
+ 7];
488 monitor
->hmax
= buffer
[j
+ 8];
489 monitor
->vmin
= buffer
[j
+ 5];
490 monitor
->vmax
= buffer
[j
+ 6];
491 monitor
->dclockmax
= buffer
[j
+ 9] * 10 * 1000;
492 monitor
->datavalid
= true;
499 if(!monitor
->datavalid
) {
500 /* Otherwise: Get a range from the list of supported
501 * Estabished Timings. This is not entirely accurate,
502 * because fixed frequency monitors are not supported
505 monitor
->hmin
= 65535; monitor
->hmax
= 0;
506 monitor
->vmin
= 65535; monitor
->vmax
= 0;
507 monitor
->dclockmax
= 0;
508 emodes
= buffer
[0x23] | (buffer
[0x24] << 8) | (buffer
[0x25] << 16);
509 for(i
= 0; i
< 13; i
++) {
510 if(emodes
& sisfb_ddcsmodes
[i
].mask
) {
511 if(monitor
->hmin
> sisfb_ddcsmodes
[i
].h
) monitor
->hmin
= sisfb_ddcsmodes
[i
].h
;
512 if(monitor
->hmax
< sisfb_ddcsmodes
[i
].h
) monitor
->hmax
= sisfb_ddcsmodes
[i
].h
+ 1;
513 if(monitor
->vmin
> sisfb_ddcsmodes
[i
].v
) monitor
->vmin
= sisfb_ddcsmodes
[i
].v
;
514 if(monitor
->vmax
< sisfb_ddcsmodes
[i
].v
) monitor
->vmax
= sisfb_ddcsmodes
[i
].v
;
515 if(monitor
->dclockmax
< sisfb_ddcsmodes
[i
].d
) monitor
->dclockmax
= sisfb_ddcsmodes
[i
].d
;
519 for(i
= 0; i
< 8; i
++) {
520 xres
= (buffer
[index
] + 31) * 8;
521 switch(buffer
[index
+ 1] & 0xc0) {
522 case 0xc0: yres
= (xres
* 9) / 16; break;
523 case 0x80: yres
= (xres
* 4) / 5; break;
524 case 0x40: yres
= (xres
* 3) / 4; break;
525 default: yres
= xres
; break;
527 refresh
= (buffer
[index
+ 1] & 0x3f) + 60;
528 if((xres
>= 640) && (yres
>= 480)) {
529 for(j
= 0; j
< 8; j
++) {
530 if((xres
== sisfb_ddcfmodes
[j
].x
) &&
531 (yres
== sisfb_ddcfmodes
[j
].y
) &&
532 (refresh
== sisfb_ddcfmodes
[j
].v
)) {
533 if(monitor
->hmin
> sisfb_ddcfmodes
[j
].h
) monitor
->hmin
= sisfb_ddcfmodes
[j
].h
;
534 if(monitor
->hmax
< sisfb_ddcfmodes
[j
].h
) monitor
->hmax
= sisfb_ddcfmodes
[j
].h
+ 1;
535 if(monitor
->vmin
> sisfb_ddcsmodes
[j
].v
) monitor
->vmin
= sisfb_ddcsmodes
[j
].v
;
536 if(monitor
->vmax
< sisfb_ddcsmodes
[j
].v
) monitor
->vmax
= sisfb_ddcsmodes
[j
].v
;
537 if(monitor
->dclockmax
< sisfb_ddcsmodes
[j
].d
) monitor
->dclockmax
= sisfb_ddcsmodes
[j
].d
;
543 if((monitor
->hmin
<= monitor
->hmax
) && (monitor
->vmin
<= monitor
->vmax
)) {
544 monitor
->datavalid
= true;
548 return monitor
->datavalid
;
551 static void sisfb_handle_ddc(struct sis_video_info
*ivideo
,
552 struct sisfb_monitor
*monitor
, int crtno
)
554 unsigned short temp
, i
, realcrtno
= crtno
;
555 unsigned char buffer
[256];
557 monitor
->datavalid
= false;
560 if(ivideo
->vbflags
& CRT2_LCD
) realcrtno
= 1;
561 else if(ivideo
->vbflags
& CRT2_VGA
) realcrtno
= 2;
565 if((ivideo
->sisfb_crt1off
) && (!crtno
))
568 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
569 realcrtno
, 0, &buffer
[0], ivideo
->vbflags2
);
570 if((!temp
) || (temp
== 0xffff)) {
571 printk(KERN_INFO
"sisfb: CRT%d DDC probing failed\n", crtno
+ 1);
574 printk(KERN_INFO
"sisfb: CRT%d DDC supported\n", crtno
+ 1);
575 printk(KERN_INFO
"sisfb: CRT%d DDC level: %s%s%s%s\n",
577 (temp
& 0x1a) ? "" : "[none of the supported]",
578 (temp
& 0x02) ? "2 " : "",
579 (temp
& 0x08) ? "D&P" : "",
580 (temp
& 0x10) ? "FPDI-2" : "");
582 i
= 3; /* Number of retrys */
584 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
585 realcrtno
, 1, &buffer
[0], ivideo
->vbflags2
);
586 } while((temp
) && i
--);
588 if(sisfb_interpret_edid(monitor
, &buffer
[0])) {
589 printk(KERN_INFO
"sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
590 monitor
->hmin
, monitor
->hmax
, monitor
->vmin
, monitor
->vmax
,
591 monitor
->dclockmax
/ 1000);
593 printk(KERN_INFO
"sisfb: CRT%d DDC EDID corrupt\n", crtno
+ 1);
596 printk(KERN_INFO
"sisfb: CRT%d DDC reading failed\n", crtno
+ 1);
599 printk(KERN_INFO
"sisfb: VESA D&P and FPDI-2 not supported yet\n");
604 /* -------------- Mode validation --------------- */
607 sisfb_verify_rate(struct sis_video_info
*ivideo
, struct sisfb_monitor
*monitor
,
608 int mode_idx
, int rate_idx
, int rate
)
611 unsigned int dclock
, hsync
;
613 if(!monitor
->datavalid
)
619 /* Skip for 320x200, 320x240, 640x400 */
620 switch(sisbios_mode
[mode_idx
].mode_no
[ivideo
->mni
]) {
631 #ifdef CONFIG_FB_SIS_315
634 if(ivideo
->sisvga_engine
== SIS_315_VGA
) return true;
638 if(rate
< (monitor
->vmin
- 1))
640 if(rate
> (monitor
->vmax
+ 1))
643 if(sisfb_gettotalfrommode(&ivideo
->SiS_Pr
,
644 sisbios_mode
[mode_idx
].mode_no
[ivideo
->mni
],
645 &htotal
, &vtotal
, rate_idx
)) {
646 dclock
= (htotal
* vtotal
* rate
) / 1000;
647 if(dclock
> (monitor
->dclockmax
+ 1000))
649 hsync
= dclock
/ htotal
;
650 if(hsync
< (monitor
->hmin
- 1))
652 if(hsync
> (monitor
->hmax
+ 1))
661 sisfb_validate_mode(struct sis_video_info
*ivideo
, int myindex
, u32 vbflags
)
663 u16 xres
=0, yres
, myres
;
665 #ifdef CONFIG_FB_SIS_300
666 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
667 if(!(sisbios_mode
[myindex
].chipset
& MD_SIS300
))
671 #ifdef CONFIG_FB_SIS_315
672 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
673 if(!(sisbios_mode
[myindex
].chipset
& MD_SIS315
))
678 myres
= sisbios_mode
[myindex
].yres
;
680 switch(vbflags
& VB_DISPTYPE_DISP2
) {
683 xres
= ivideo
->lcdxres
; yres
= ivideo
->lcdyres
;
685 if((ivideo
->SiS_Pr
.SiS_CustomT
!= CUT_PANEL848
) &&
686 (ivideo
->SiS_Pr
.SiS_CustomT
!= CUT_PANEL856
)) {
687 if(sisbios_mode
[myindex
].xres
> xres
)
693 if(ivideo
->sisfb_fstn
) {
694 if(sisbios_mode
[myindex
].xres
== 320) {
696 switch(sisbios_mode
[myindex
].mode_no
[1]) {
697 case 0x50: myindex
= MODE_FSTN_8
; break;
698 case 0x56: myindex
= MODE_FSTN_16
; break;
699 case 0x53: return -1;
705 if(SiS_GetModeID_LCD(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
706 sisbios_mode
[myindex
].yres
, 0, ivideo
->sisfb_fstn
,
707 ivideo
->SiS_Pr
.SiS_CustomT
, xres
, yres
, ivideo
->vbflags2
) < 0x14) {
713 if(SiS_GetModeID_TV(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
714 sisbios_mode
[myindex
].yres
, 0, ivideo
->vbflags2
) < 0x14) {
720 if(SiS_GetModeID_VGA2(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
721 sisbios_mode
[myindex
].yres
, 0, ivideo
->vbflags2
) < 0x14) {
731 sisfb_search_refresh_rate(struct sis_video_info
*ivideo
, unsigned int rate
, int mode_idx
)
734 u16 xres
= sisbios_mode
[mode_idx
].xres
;
735 u16 yres
= sisbios_mode
[mode_idx
].yres
;
737 ivideo
->rate_idx
= 0;
738 while((sisfb_vrate
[i
].idx
!= 0) && (sisfb_vrate
[i
].xres
<= xres
)) {
739 if((sisfb_vrate
[i
].xres
== xres
) && (sisfb_vrate
[i
].yres
== yres
)) {
740 if(sisfb_vrate
[i
].refresh
== rate
) {
741 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
743 } else if(sisfb_vrate
[i
].refresh
> rate
) {
744 if((sisfb_vrate
[i
].refresh
- rate
) <= 3) {
745 DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
746 rate
, sisfb_vrate
[i
].refresh
);
747 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
748 ivideo
->refresh_rate
= sisfb_vrate
[i
].refresh
;
749 } else if((sisfb_vrate
[i
].idx
!= 1) &&
750 ((rate
- sisfb_vrate
[i
-1].refresh
) <= 2)) {
751 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
752 rate
, sisfb_vrate
[i
-1].refresh
);
753 ivideo
->rate_idx
= sisfb_vrate
[i
-1].idx
;
754 ivideo
->refresh_rate
= sisfb_vrate
[i
-1].refresh
;
757 } else if((rate
- sisfb_vrate
[i
].refresh
) <= 2) {
758 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
759 rate
, sisfb_vrate
[i
].refresh
);
760 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
766 if(ivideo
->rate_idx
> 0) {
767 return ivideo
->rate_idx
;
769 printk(KERN_INFO
"sisfb: Unsupported rate %d for %dx%d\n",
776 sisfb_bridgeisslave(struct sis_video_info
*ivideo
)
780 if(!(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
))
783 P1_00
= SiS_GetReg(SISPART1
, 0x00);
784 if( ((ivideo
->sisvga_engine
== SIS_300_VGA
) && (P1_00
& 0xa0) == 0x20) ||
785 ((ivideo
->sisvga_engine
== SIS_315_VGA
) && (P1_00
& 0x50) == 0x10) ) {
793 sisfballowretracecrt1(struct sis_video_info
*ivideo
)
797 temp
= SiS_GetReg(SISCR
, 0x17);
801 temp
= SiS_GetReg(SISSR
, 0x1f);
809 sisfbcheckvretracecrt1(struct sis_video_info
*ivideo
)
811 if(!sisfballowretracecrt1(ivideo
))
814 if (SiS_GetRegByte(SISINPSTAT
) & 0x08)
821 sisfbwaitretracecrt1(struct sis_video_info
*ivideo
)
825 if(!sisfballowretracecrt1(ivideo
))
829 while ((!(SiS_GetRegByte(SISINPSTAT
) & 0x08)) && --watchdog
);
831 while ((SiS_GetRegByte(SISINPSTAT
) & 0x08) && --watchdog
);
835 sisfbcheckvretracecrt2(struct sis_video_info
*ivideo
)
837 unsigned char temp
, reg
;
839 switch(ivideo
->sisvga_engine
) {
840 case SIS_300_VGA
: reg
= 0x25; break;
841 case SIS_315_VGA
: reg
= 0x30; break;
842 default: return false;
845 temp
= SiS_GetReg(SISPART1
, reg
);
853 sisfb_CheckVBRetrace(struct sis_video_info
*ivideo
)
855 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
856 if(!sisfb_bridgeisslave(ivideo
)) {
857 return sisfbcheckvretracecrt2(ivideo
);
860 return sisfbcheckvretracecrt1(ivideo
);
864 sisfb_setupvbblankflags(struct sis_video_info
*ivideo
, u32
*vcount
, u32
*hcount
)
866 u8 idx
, reg1
, reg2
, reg3
, reg4
;
869 (*vcount
) = (*hcount
) = 0;
871 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) && (!(sisfb_bridgeisslave(ivideo
)))) {
873 ret
|= (FB_VBLANK_HAVE_VSYNC
|
874 FB_VBLANK_HAVE_HBLANK
|
875 FB_VBLANK_HAVE_VBLANK
|
876 FB_VBLANK_HAVE_VCOUNT
|
877 FB_VBLANK_HAVE_HCOUNT
);
878 switch(ivideo
->sisvga_engine
) {
879 case SIS_300_VGA
: idx
= 0x25; break;
881 case SIS_315_VGA
: idx
= 0x30; break;
883 reg1
= SiS_GetReg(SISPART1
, (idx
+0)); /* 30 */
884 reg2
= SiS_GetReg(SISPART1
, (idx
+1)); /* 31 */
885 reg3
= SiS_GetReg(SISPART1
, (idx
+2)); /* 32 */
886 reg4
= SiS_GetReg(SISPART1
, (idx
+3)); /* 33 */
887 if(reg1
& 0x01) ret
|= FB_VBLANK_VBLANKING
;
888 if(reg1
& 0x02) ret
|= FB_VBLANK_VSYNCING
;
889 if(reg4
& 0x80) ret
|= FB_VBLANK_HBLANKING
;
890 (*vcount
) = reg3
| ((reg4
& 0x70) << 4);
891 (*hcount
) = reg2
| ((reg4
& 0x0f) << 8);
893 } else if(sisfballowretracecrt1(ivideo
)) {
895 ret
|= (FB_VBLANK_HAVE_VSYNC
|
896 FB_VBLANK_HAVE_VBLANK
|
897 FB_VBLANK_HAVE_VCOUNT
|
898 FB_VBLANK_HAVE_HCOUNT
);
899 reg1
= SiS_GetRegByte(SISINPSTAT
);
900 if(reg1
& 0x08) ret
|= FB_VBLANK_VSYNCING
;
901 if(reg1
& 0x01) ret
|= FB_VBLANK_VBLANKING
;
902 reg1
= SiS_GetReg(SISCR
, 0x20);
903 reg1
= SiS_GetReg(SISCR
, 0x1b);
904 reg2
= SiS_GetReg(SISCR
, 0x1c);
905 reg3
= SiS_GetReg(SISCR
, 0x1d);
906 (*vcount
) = reg2
| ((reg3
& 0x07) << 8);
907 (*hcount
) = (reg1
| ((reg3
& 0x10) << 4)) << 3;
914 sisfb_myblank(struct sis_video_info
*ivideo
, int blank
)
916 u8 sr01
, sr11
, sr1f
, cr63
=0, p2_0
, p1_13
;
917 bool backlight
= true;
920 case FB_BLANK_UNBLANK
: /* on */
929 case FB_BLANK_NORMAL
: /* blank */
938 case FB_BLANK_VSYNC_SUSPEND
: /* no vsync */
947 case FB_BLANK_HSYNC_SUSPEND
: /* no hsync */
956 case FB_BLANK_POWERDOWN
: /* off */
969 if(ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
) {
971 if( (!ivideo
->sisfb_thismonitor
.datavalid
) ||
972 ((ivideo
->sisfb_thismonitor
.datavalid
) &&
973 (ivideo
->sisfb_thismonitor
.feature
& 0xe0))) {
975 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
976 SiS_SetRegANDOR(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, 0xbf, cr63
);
979 if(!(sisfb_bridgeisslave(ivideo
))) {
980 SiS_SetRegANDOR(SISSR
, 0x01, ~0x20, sr01
);
981 SiS_SetRegANDOR(SISSR
, 0x1f, 0x3f, sr1f
);
987 if(ivideo
->currentvbflags
& CRT2_LCD
) {
989 if(ivideo
->vbflags2
& VB2_SISLVDSBRIDGE
) {
991 SiS_SiS30xBLOn(&ivideo
->SiS_Pr
);
993 SiS_SiS30xBLOff(&ivideo
->SiS_Pr
);
995 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
996 #ifdef CONFIG_FB_SIS_315
997 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
999 SiS_Chrontel701xBLOn(&ivideo
->SiS_Pr
);
1001 SiS_Chrontel701xBLOff(&ivideo
->SiS_Pr
);
1007 if(((ivideo
->sisvga_engine
== SIS_300_VGA
) &&
1008 (ivideo
->vbflags2
& (VB2_301
|VB2_30xBDH
|VB2_LVDS
))) ||
1009 ((ivideo
->sisvga_engine
== SIS_315_VGA
) &&
1010 ((ivideo
->vbflags2
& (VB2_LVDS
| VB2_CHRONTEL
)) == VB2_LVDS
))) {
1011 SiS_SetRegANDOR(SISSR
, 0x11, ~0x0c, sr11
);
1014 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
1015 if((ivideo
->vbflags2
& VB2_30xB
) &&
1016 (!(ivideo
->vbflags2
& VB2_30xBDH
))) {
1017 SiS_SetRegANDOR(SISPART1
, 0x13, 0x3f, p1_13
);
1019 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
1020 if((ivideo
->vbflags2
& VB2_30xB
) &&
1021 (!(ivideo
->vbflags2
& VB2_30xBDH
))) {
1022 SiS_SetRegANDOR(SISPART2
, 0x00, 0x1f, p2_0
);
1026 } else if(ivideo
->currentvbflags
& CRT2_VGA
) {
1028 if(ivideo
->vbflags2
& VB2_30xB
) {
1029 SiS_SetRegANDOR(SISPART2
, 0x00, 0x1f, p2_0
);
1037 /* ------------- Callbacks from init.c/init301.c -------------- */
1039 #ifdef CONFIG_FB_SIS_300
1041 sisfb_read_nbridge_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
)
1043 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1046 pci_read_config_dword(ivideo
->nbridge
, reg
, &val
);
1047 return (unsigned int)val
;
1051 sisfb_write_nbridge_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
, unsigned int val
)
1053 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1055 pci_write_config_dword(ivideo
->nbridge
, reg
, (u32
)val
);
1059 sisfb_read_lpc_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
)
1061 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1064 if(!ivideo
->lpcdev
) return 0;
1066 pci_read_config_dword(ivideo
->lpcdev
, reg
, &val
);
1067 return (unsigned int)val
;
1071 #ifdef CONFIG_FB_SIS_315
1073 sisfb_write_nbridge_pci_byte(struct SiS_Private
*SiS_Pr
, int reg
, unsigned char val
)
1075 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1077 pci_write_config_byte(ivideo
->nbridge
, reg
, (u8
)val
);
1081 sisfb_read_mio_pci_word(struct SiS_Private
*SiS_Pr
, int reg
)
1083 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1086 if(!ivideo
->lpcdev
) return 0;
1088 pci_read_config_word(ivideo
->lpcdev
, reg
, &val
);
1089 return (unsigned int)val
;
1093 /* ----------- FBDev related routines for all series ----------- */
1096 sisfb_get_cmap_len(const struct fb_var_screeninfo
*var
)
1098 return (var
->bits_per_pixel
== 8) ? 256 : 16;
1102 sisfb_set_vparms(struct sis_video_info
*ivideo
)
1104 switch(ivideo
->video_bpp
) {
1106 ivideo
->DstColor
= 0x0000;
1107 ivideo
->SiS310_AccelDepth
= 0x00000000;
1108 ivideo
->video_cmap_len
= 256;
1111 ivideo
->DstColor
= 0x8000;
1112 ivideo
->SiS310_AccelDepth
= 0x00010000;
1113 ivideo
->video_cmap_len
= 16;
1116 ivideo
->DstColor
= 0xC000;
1117 ivideo
->SiS310_AccelDepth
= 0x00020000;
1118 ivideo
->video_cmap_len
= 16;
1121 ivideo
->video_cmap_len
= 16;
1122 printk(KERN_ERR
"sisfb: Unsupported depth %d", ivideo
->video_bpp
);
1128 sisfb_calc_maxyres(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1130 int maxyres
= ivideo
->sisfb_mem
/ (var
->xres_virtual
* (var
->bits_per_pixel
>> 3));
1132 if(maxyres
> 32767) maxyres
= 32767;
1138 sisfb_calc_pitch(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1140 ivideo
->video_linelength
= var
->xres_virtual
* (var
->bits_per_pixel
>> 3);
1141 ivideo
->scrnpitchCRT1
= ivideo
->video_linelength
;
1142 if(!(ivideo
->currentvbflags
& CRT1_LCDA
)) {
1143 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1144 ivideo
->scrnpitchCRT1
<<= 1;
1150 sisfb_set_pitch(struct sis_video_info
*ivideo
)
1152 bool isslavemode
= false;
1153 unsigned short HDisplay1
= ivideo
->scrnpitchCRT1
>> 3;
1154 unsigned short HDisplay2
= ivideo
->video_linelength
>> 3;
1156 if(sisfb_bridgeisslave(ivideo
)) isslavemode
= true;
1158 /* We need to set pitch for CRT1 if bridge is in slave mode, too */
1159 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP1
) || (isslavemode
)) {
1160 SiS_SetReg(SISCR
, 0x13, (HDisplay1
& 0xFF));
1161 SiS_SetRegANDOR(SISSR
, 0x0E, 0xF0, (HDisplay1
>> 8));
1164 /* We must not set the pitch for CRT2 if bridge is in slave mode */
1165 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) && (!isslavemode
)) {
1166 SiS_SetRegOR(SISPART1
, ivideo
->CRT2_write_enable
, 0x01);
1167 SiS_SetReg(SISPART1
, 0x07, (HDisplay2
& 0xFF));
1168 SiS_SetRegANDOR(SISPART1
, 0x09, 0xF0, (HDisplay2
>> 8));
1173 sisfb_bpp_to_var(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1175 ivideo
->video_cmap_len
= sisfb_get_cmap_len(var
);
1177 switch(var
->bits_per_pixel
) {
1179 var
->red
.offset
= var
->green
.offset
= var
->blue
.offset
= 0;
1180 var
->red
.length
= var
->green
.length
= var
->blue
.length
= 8;
1183 var
->red
.offset
= 11;
1184 var
->red
.length
= 5;
1185 var
->green
.offset
= 5;
1186 var
->green
.length
= 6;
1187 var
->blue
.offset
= 0;
1188 var
->blue
.length
= 5;
1189 var
->transp
.offset
= 0;
1190 var
->transp
.length
= 0;
1193 var
->red
.offset
= 16;
1194 var
->red
.length
= 8;
1195 var
->green
.offset
= 8;
1196 var
->green
.length
= 8;
1197 var
->blue
.offset
= 0;
1198 var
->blue
.length
= 8;
1199 var
->transp
.offset
= 24;
1200 var
->transp
.length
= 8;
1206 sisfb_set_mode(struct sis_video_info
*ivideo
, int clrscrn
)
1208 unsigned short modeno
= ivideo
->mode_no
;
1210 /* >=2.6.12's fbcon clears the screen anyway */
1213 SiS_SetReg(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1215 sisfb_pre_setmode(ivideo
);
1217 if(!SiSSetMode(&ivideo
->SiS_Pr
, modeno
)) {
1218 printk(KERN_ERR
"sisfb: Setting mode[0x%x] failed\n", ivideo
->mode_no
);
1222 SiS_SetReg(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1224 sisfb_post_setmode(ivideo
);
1231 sisfb_do_set_var(struct fb_var_screeninfo
*var
, int isactive
, struct fb_info
*info
)
1233 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1234 unsigned int htotal
= 0, vtotal
= 0;
1235 unsigned int drate
= 0, hrate
= 0;
1236 int found_mode
= 0, ret
;
1240 htotal
= var
->left_margin
+ var
->xres
+ var
->right_margin
+ var
->hsync_len
;
1242 vtotal
= var
->upper_margin
+ var
->lower_margin
+ var
->vsync_len
;
1244 pixclock
= var
->pixclock
;
1246 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
) {
1247 vtotal
+= var
->yres
;
1249 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1250 vtotal
+= var
->yres
;
1252 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1253 vtotal
+= var
->yres
;
1255 } else vtotal
+= var
->yres
;
1257 if(!(htotal
) || !(vtotal
)) {
1258 DPRINTK("sisfb: Invalid 'var' information\n");
1262 if(pixclock
&& htotal
&& vtotal
) {
1263 drate
= 1000000000 / pixclock
;
1264 hrate
= (drate
* 1000) / htotal
;
1265 ivideo
->refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1267 ivideo
->refresh_rate
= 60;
1270 old_mode
= ivideo
->sisfb_mode_idx
;
1271 ivideo
->sisfb_mode_idx
= 0;
1273 while( (sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[0] != 0) &&
1274 (sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
<= var
->xres
) ) {
1275 if( (sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
== var
->xres
) &&
1276 (sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
== var
->yres
) &&
1277 (sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
== var
->bits_per_pixel
)) {
1278 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
1282 ivideo
->sisfb_mode_idx
++;
1286 ivideo
->sisfb_mode_idx
= sisfb_validate_mode(ivideo
,
1287 ivideo
->sisfb_mode_idx
, ivideo
->currentvbflags
);
1289 ivideo
->sisfb_mode_idx
= -1;
1292 if(ivideo
->sisfb_mode_idx
< 0) {
1293 printk(KERN_ERR
"sisfb: Mode %dx%dx%d not supported\n", var
->xres
,
1294 var
->yres
, var
->bits_per_pixel
);
1295 ivideo
->sisfb_mode_idx
= old_mode
;
1299 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
1301 if(sisfb_search_refresh_rate(ivideo
, ivideo
->refresh_rate
, ivideo
->sisfb_mode_idx
) == 0) {
1302 ivideo
->rate_idx
= sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
;
1303 ivideo
->refresh_rate
= 60;
1307 /* If acceleration to be used? Need to know
1308 * before pre/post_set_mode()
1311 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
1312 #ifdef STUPID_ACCELF_TEXT_SHIT
1313 if(var
->accel_flags
& FB_ACCELF_TEXT
) {
1314 info
->flags
&= ~FBINFO_HWACCEL_DISABLED
;
1316 info
->flags
|= FBINFO_HWACCEL_DISABLED
;
1319 if(!(info
->flags
& FBINFO_HWACCEL_DISABLED
)) ivideo
->accel
= -1;
1321 if(var
->accel_flags
& FB_ACCELF_TEXT
) ivideo
->accel
= -1;
1324 if((ret
= sisfb_set_mode(ivideo
, 1))) {
1328 ivideo
->video_bpp
= sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
;
1329 ivideo
->video_width
= sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
;
1330 ivideo
->video_height
= sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
;
1332 sisfb_calc_pitch(ivideo
, var
);
1333 sisfb_set_pitch(ivideo
);
1335 sisfb_set_vparms(ivideo
);
1337 ivideo
->current_width
= ivideo
->video_width
;
1338 ivideo
->current_height
= ivideo
->video_height
;
1339 ivideo
->current_bpp
= ivideo
->video_bpp
;
1340 ivideo
->current_htotal
= htotal
;
1341 ivideo
->current_vtotal
= vtotal
;
1342 ivideo
->current_linelength
= ivideo
->video_linelength
;
1343 ivideo
->current_pixclock
= var
->pixclock
;
1344 ivideo
->current_refresh_rate
= ivideo
->refresh_rate
;
1345 ivideo
->sisfb_lastrates
[ivideo
->mode_no
] = ivideo
->refresh_rate
;
1352 sisfb_set_base_CRT1(struct sis_video_info
*ivideo
, unsigned int base
)
1354 SiS_SetReg(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1356 SiS_SetReg(SISCR
, 0x0D, base
& 0xFF);
1357 SiS_SetReg(SISCR
, 0x0C, (base
>> 8) & 0xFF);
1358 SiS_SetReg(SISSR
, 0x0D, (base
>> 16) & 0xFF);
1359 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
1360 SiS_SetRegANDOR(SISSR
, 0x37, 0xFE, (base
>> 24) & 0x01);
1365 sisfb_set_base_CRT2(struct sis_video_info
*ivideo
, unsigned int base
)
1367 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
1368 SiS_SetRegOR(SISPART1
, ivideo
->CRT2_write_enable
, 0x01);
1369 SiS_SetReg(SISPART1
, 0x06, (base
& 0xFF));
1370 SiS_SetReg(SISPART1
, 0x05, ((base
>> 8) & 0xFF));
1371 SiS_SetReg(SISPART1
, 0x04, ((base
>> 16) & 0xFF));
1372 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
1373 SiS_SetRegANDOR(SISPART1
, 0x02, 0x7F, ((base
>> 24) & 0x01) << 7);
1379 sisfb_pan_var(struct sis_video_info
*ivideo
, struct fb_info
*info
,
1380 struct fb_var_screeninfo
*var
)
1382 ivideo
->current_base
= var
->yoffset
* info
->var
.xres_virtual
1385 /* calculate base bpp dep. */
1386 switch (info
->var
.bits_per_pixel
) {
1390 ivideo
->current_base
>>= 1;
1394 ivideo
->current_base
>>= 2;
1398 ivideo
->current_base
+= (ivideo
->video_offset
>> 2);
1400 sisfb_set_base_CRT1(ivideo
, ivideo
->current_base
);
1401 sisfb_set_base_CRT2(ivideo
, ivideo
->current_base
);
1407 sisfb_open(struct fb_info
*info
, int user
)
1413 sisfb_release(struct fb_info
*info
, int user
)
1419 sisfb_setcolreg(unsigned regno
, unsigned red
, unsigned green
, unsigned blue
,
1420 unsigned transp
, struct fb_info
*info
)
1422 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1424 if(regno
>= sisfb_get_cmap_len(&info
->var
))
1427 switch(info
->var
.bits_per_pixel
) {
1429 SiS_SetRegByte(SISDACA
, regno
);
1430 SiS_SetRegByte(SISDACD
, (red
>> 10));
1431 SiS_SetRegByte(SISDACD
, (green
>> 10));
1432 SiS_SetRegByte(SISDACD
, (blue
>> 10));
1433 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
1434 SiS_SetRegByte(SISDAC2A
, regno
);
1435 SiS_SetRegByte(SISDAC2D
, (red
>> 8));
1436 SiS_SetRegByte(SISDAC2D
, (green
>> 8));
1437 SiS_SetRegByte(SISDAC2D
, (blue
>> 8));
1444 ((u32
*)(info
->pseudo_palette
))[regno
] =
1446 ((green
& 0xfc00) >> 5) |
1447 ((blue
& 0xf800) >> 11);
1456 ((u32
*)(info
->pseudo_palette
))[regno
] =
1457 (red
<< 16) | (green
<< 8) | (blue
);
1464 sisfb_set_par(struct fb_info
*info
)
1468 if((err
= sisfb_do_set_var(&info
->var
, 1, info
)))
1471 sisfb_get_fix(&info
->fix
, -1, info
);
1477 sisfb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
1479 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1480 unsigned int htotal
= 0, vtotal
= 0, myrateindex
= 0;
1481 unsigned int drate
= 0, hrate
= 0, maxyres
;
1483 int refresh_rate
, search_idx
, tidx
;
1484 bool recalc_clock
= false;
1487 htotal
= var
->left_margin
+ var
->xres
+ var
->right_margin
+ var
->hsync_len
;
1489 vtotal
= var
->upper_margin
+ var
->lower_margin
+ var
->vsync_len
;
1491 pixclock
= var
->pixclock
;
1493 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
) {
1494 vtotal
+= var
->yres
;
1496 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1497 vtotal
+= var
->yres
;
1499 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1500 vtotal
+= var
->yres
;
1503 vtotal
+= var
->yres
;
1505 if(!(htotal
) || !(vtotal
)) {
1506 SISFAIL("sisfb: no valid timing data");
1510 while( (sisbios_mode
[search_idx
].mode_no
[0] != 0) &&
1511 (sisbios_mode
[search_idx
].xres
<= var
->xres
) ) {
1512 if( (sisbios_mode
[search_idx
].xres
== var
->xres
) &&
1513 (sisbios_mode
[search_idx
].yres
== var
->yres
) &&
1514 (sisbios_mode
[search_idx
].bpp
== var
->bits_per_pixel
)) {
1515 if((tidx
= sisfb_validate_mode(ivideo
, search_idx
,
1516 ivideo
->currentvbflags
)) > 0) {
1527 while(sisbios_mode
[search_idx
].mode_no
[0] != 0) {
1528 if( (var
->xres
<= sisbios_mode
[search_idx
].xres
) &&
1529 (var
->yres
<= sisbios_mode
[search_idx
].yres
) &&
1530 (var
->bits_per_pixel
== sisbios_mode
[search_idx
].bpp
) ) {
1531 if((tidx
= sisfb_validate_mode(ivideo
,search_idx
,
1532 ivideo
->currentvbflags
)) > 0) {
1542 "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
1543 var
->xres
, var
->yres
, var
->bits_per_pixel
,
1544 sisbios_mode
[search_idx
].xres
,
1545 sisbios_mode
[search_idx
].yres
,
1546 var
->bits_per_pixel
);
1547 var
->xres
= sisbios_mode
[search_idx
].xres
;
1548 var
->yres
= sisbios_mode
[search_idx
].yres
;
1551 "sisfb: Failed to find supported mode near %dx%dx%d\n",
1552 var
->xres
, var
->yres
, var
->bits_per_pixel
);
1557 if( ((ivideo
->vbflags2
& VB2_LVDS
) ||
1558 ((ivideo
->vbflags2
& VB2_30xBDH
) && (ivideo
->currentvbflags
& CRT2_LCD
))) &&
1559 (var
->bits_per_pixel
== 8) ) {
1560 /* Slave modes on LVDS and 301B-DH */
1562 recalc_clock
= true;
1563 } else if( (ivideo
->current_htotal
== htotal
) &&
1564 (ivideo
->current_vtotal
== vtotal
) &&
1565 (ivideo
->current_pixclock
== pixclock
) ) {
1566 /* x=x & y=y & c=c -> assume depth change */
1567 drate
= 1000000000 / pixclock
;
1568 hrate
= (drate
* 1000) / htotal
;
1569 refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1570 } else if( ( (ivideo
->current_htotal
!= htotal
) ||
1571 (ivideo
->current_vtotal
!= vtotal
) ) &&
1572 (ivideo
->current_pixclock
== var
->pixclock
) ) {
1573 /* x!=x | y!=y & c=c -> invalid pixclock */
1574 if(ivideo
->sisfb_lastrates
[sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
]]) {
1576 ivideo
->sisfb_lastrates
[sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
]];
1577 } else if(ivideo
->sisfb_parm_rate
!= -1) {
1578 /* Sic, sisfb_parm_rate - want to know originally desired rate here */
1579 refresh_rate
= ivideo
->sisfb_parm_rate
;
1583 recalc_clock
= true;
1584 } else if((pixclock
) && (htotal
) && (vtotal
)) {
1585 drate
= 1000000000 / pixclock
;
1586 hrate
= (drate
* 1000) / htotal
;
1587 refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1588 } else if(ivideo
->current_refresh_rate
) {
1589 refresh_rate
= ivideo
->current_refresh_rate
;
1590 recalc_clock
= true;
1593 recalc_clock
= true;
1596 myrateindex
= sisfb_search_refresh_rate(ivideo
, refresh_rate
, search_idx
);
1598 /* Eventually recalculate timing and clock */
1600 if(!myrateindex
) myrateindex
= sisbios_mode
[search_idx
].rate_idx
;
1601 var
->pixclock
= (u32
) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo
->SiS_Pr
,
1602 sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
],
1604 sisfb_mode_rate_to_ddata(&ivideo
->SiS_Pr
,
1605 sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
],
1607 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1608 var
->pixclock
<<= 1;
1612 if(ivideo
->sisfb_thismonitor
.datavalid
) {
1613 if(!sisfb_verify_rate(ivideo
, &ivideo
->sisfb_thismonitor
, search_idx
,
1614 myrateindex
, refresh_rate
)) {
1616 "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1620 /* Adapt RGB settings */
1621 sisfb_bpp_to_var(ivideo
, var
);
1623 if(var
->xres
> var
->xres_virtual
)
1624 var
->xres_virtual
= var
->xres
;
1626 if(ivideo
->sisfb_ypan
) {
1627 maxyres
= sisfb_calc_maxyres(ivideo
, var
);
1628 if(ivideo
->sisfb_max
) {
1629 var
->yres_virtual
= maxyres
;
1631 if(var
->yres_virtual
> maxyres
) {
1632 var
->yres_virtual
= maxyres
;
1635 if(var
->yres_virtual
<= var
->yres
) {
1636 var
->yres_virtual
= var
->yres
;
1639 if(var
->yres
!= var
->yres_virtual
) {
1640 var
->yres_virtual
= var
->yres
;
1646 /* Truncate offsets to maximum if too high */
1647 if(var
->xoffset
> var
->xres_virtual
- var
->xres
) {
1648 var
->xoffset
= var
->xres_virtual
- var
->xres
- 1;
1651 if(var
->yoffset
> var
->yres_virtual
- var
->yres
) {
1652 var
->yoffset
= var
->yres_virtual
- var
->yres
- 1;
1655 /* Set everything else to 0 */
1656 var
->red
.msb_right
=
1657 var
->green
.msb_right
=
1658 var
->blue
.msb_right
=
1659 var
->transp
.offset
=
1660 var
->transp
.length
=
1661 var
->transp
.msb_right
= 0;
1667 sisfb_pan_display(struct fb_var_screeninfo
*var
, struct fb_info
* info
)
1669 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1672 if (var
->vmode
& FB_VMODE_YWRAP
)
1675 if (var
->xoffset
+ info
->var
.xres
> info
->var
.xres_virtual
||
1676 var
->yoffset
+ info
->var
.yres
> info
->var
.yres_virtual
)
1679 err
= sisfb_pan_var(ivideo
, info
, var
);
1683 info
->var
.xoffset
= var
->xoffset
;
1684 info
->var
.yoffset
= var
->yoffset
;
1690 sisfb_blank(int blank
, struct fb_info
*info
)
1692 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1694 return sisfb_myblank(ivideo
, blank
);
1697 /* ----------- FBDev related routines for all series ---------- */
1699 static int sisfb_ioctl(struct fb_info
*info
, unsigned int cmd
,
1702 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1703 struct sis_memreq sismemreq
;
1704 struct fb_vblank sisvbblank
;
1709 u32 __user
*argp
= (u32 __user
*)arg
;
1713 if(!capable(CAP_SYS_RAWIO
))
1716 if(copy_from_user(&sismemreq
, (void __user
*)arg
, sizeof(sismemreq
)))
1719 sis_malloc(&sismemreq
);
1721 if(copy_to_user((void __user
*)arg
, &sismemreq
, sizeof(sismemreq
))) {
1722 sis_free((u32
)sismemreq
.offset
);
1728 if(!capable(CAP_SYS_RAWIO
))
1731 if(get_user(gpu32
, argp
))
1737 case FBIOGET_VBLANK
:
1739 memset(&sisvbblank
, 0, sizeof(struct fb_vblank
));
1741 sisvbblank
.count
= 0;
1742 sisvbblank
.flags
= sisfb_setupvbblankflags(ivideo
, &sisvbblank
.vcount
, &sisvbblank
.hcount
);
1744 if(copy_to_user((void __user
*)arg
, &sisvbblank
, sizeof(sisvbblank
)))
1749 case SISFB_GET_INFO_SIZE
:
1750 return put_user(sizeof(struct sisfb_info
), argp
);
1752 case SISFB_GET_INFO_OLD
:
1753 if(ivideo
->warncount
++ < 10)
1755 "sisfb: Deprecated ioctl call received - update your application!\n");
1757 case SISFB_GET_INFO
: /* For communication with X driver */
1758 ivideo
->sisfb_infoblock
.sisfb_id
= SISFB_ID
;
1759 ivideo
->sisfb_infoblock
.sisfb_version
= VER_MAJOR
;
1760 ivideo
->sisfb_infoblock
.sisfb_revision
= VER_MINOR
;
1761 ivideo
->sisfb_infoblock
.sisfb_patchlevel
= VER_LEVEL
;
1762 ivideo
->sisfb_infoblock
.chip_id
= ivideo
->chip_id
;
1763 ivideo
->sisfb_infoblock
.sisfb_pci_vendor
= ivideo
->chip_vendor
;
1764 ivideo
->sisfb_infoblock
.memory
= ivideo
->video_size
/ 1024;
1765 ivideo
->sisfb_infoblock
.heapstart
= ivideo
->heapstart
/ 1024;
1766 if(ivideo
->modechanged
) {
1767 ivideo
->sisfb_infoblock
.fbvidmode
= ivideo
->mode_no
;
1769 ivideo
->sisfb_infoblock
.fbvidmode
= ivideo
->modeprechange
;
1771 ivideo
->sisfb_infoblock
.sisfb_caps
= ivideo
->caps
;
1772 ivideo
->sisfb_infoblock
.sisfb_tqlen
= ivideo
->cmdQueueSize
/ 1024;
1773 ivideo
->sisfb_infoblock
.sisfb_pcibus
= ivideo
->pcibus
;
1774 ivideo
->sisfb_infoblock
.sisfb_pcislot
= ivideo
->pcislot
;
1775 ivideo
->sisfb_infoblock
.sisfb_pcifunc
= ivideo
->pcifunc
;
1776 ivideo
->sisfb_infoblock
.sisfb_lcdpdc
= ivideo
->detectedpdc
;
1777 ivideo
->sisfb_infoblock
.sisfb_lcdpdca
= ivideo
->detectedpdca
;
1778 ivideo
->sisfb_infoblock
.sisfb_lcda
= ivideo
->detectedlcda
;
1779 ivideo
->sisfb_infoblock
.sisfb_vbflags
= ivideo
->vbflags
;
1780 ivideo
->sisfb_infoblock
.sisfb_currentvbflags
= ivideo
->currentvbflags
;
1781 ivideo
->sisfb_infoblock
.sisfb_scalelcd
= ivideo
->SiS_Pr
.UsePanelScaler
;
1782 ivideo
->sisfb_infoblock
.sisfb_specialtiming
= ivideo
->SiS_Pr
.SiS_CustomT
;
1783 ivideo
->sisfb_infoblock
.sisfb_haveemi
= ivideo
->SiS_Pr
.HaveEMI
? 1 : 0;
1784 ivideo
->sisfb_infoblock
.sisfb_haveemilcd
= ivideo
->SiS_Pr
.HaveEMILCD
? 1 : 0;
1785 ivideo
->sisfb_infoblock
.sisfb_emi30
= ivideo
->SiS_Pr
.EMI_30
;
1786 ivideo
->sisfb_infoblock
.sisfb_emi31
= ivideo
->SiS_Pr
.EMI_31
;
1787 ivideo
->sisfb_infoblock
.sisfb_emi32
= ivideo
->SiS_Pr
.EMI_32
;
1788 ivideo
->sisfb_infoblock
.sisfb_emi33
= ivideo
->SiS_Pr
.EMI_33
;
1789 ivideo
->sisfb_infoblock
.sisfb_tvxpos
= (u16
)(ivideo
->tvxpos
+ 32);
1790 ivideo
->sisfb_infoblock
.sisfb_tvypos
= (u16
)(ivideo
->tvypos
+ 32);
1791 ivideo
->sisfb_infoblock
.sisfb_heapsize
= ivideo
->sisfb_heap_size
/ 1024;
1792 ivideo
->sisfb_infoblock
.sisfb_videooffset
= ivideo
->video_offset
;
1793 ivideo
->sisfb_infoblock
.sisfb_curfstn
= ivideo
->curFSTN
;
1794 ivideo
->sisfb_infoblock
.sisfb_curdstn
= ivideo
->curDSTN
;
1795 ivideo
->sisfb_infoblock
.sisfb_vbflags2
= ivideo
->vbflags2
;
1796 ivideo
->sisfb_infoblock
.sisfb_can_post
= ivideo
->sisfb_can_post
? 1 : 0;
1797 ivideo
->sisfb_infoblock
.sisfb_card_posted
= ivideo
->sisfb_card_posted
? 1 : 0;
1798 ivideo
->sisfb_infoblock
.sisfb_was_boot_device
= ivideo
->sisfb_was_boot_device
? 1 : 0;
1800 if(copy_to_user((void __user
*)arg
, &ivideo
->sisfb_infoblock
,
1801 sizeof(ivideo
->sisfb_infoblock
)))
1806 case SISFB_GET_VBRSTATUS_OLD
:
1807 if(ivideo
->warncount
++ < 10)
1809 "sisfb: Deprecated ioctl call received - update your application!\n");
1811 case SISFB_GET_VBRSTATUS
:
1812 if(sisfb_CheckVBRetrace(ivideo
))
1813 return put_user((u32
)1, argp
);
1815 return put_user((u32
)0, argp
);
1817 case SISFB_GET_AUTOMAXIMIZE_OLD
:
1818 if(ivideo
->warncount
++ < 10)
1820 "sisfb: Deprecated ioctl call received - update your application!\n");
1822 case SISFB_GET_AUTOMAXIMIZE
:
1823 if(ivideo
->sisfb_max
)
1824 return put_user((u32
)1, argp
);
1826 return put_user((u32
)0, argp
);
1828 case SISFB_SET_AUTOMAXIMIZE_OLD
:
1829 if(ivideo
->warncount
++ < 10)
1831 "sisfb: Deprecated ioctl call received - update your application!\n");
1833 case SISFB_SET_AUTOMAXIMIZE
:
1834 if(get_user(gpu32
, argp
))
1837 ivideo
->sisfb_max
= (gpu32
) ? 1 : 0;
1840 case SISFB_SET_TVPOSOFFSET
:
1841 if(get_user(gpu32
, argp
))
1844 sisfb_set_TVxposoffset(ivideo
, ((int)(gpu32
>> 16)) - 32);
1845 sisfb_set_TVyposoffset(ivideo
, ((int)(gpu32
& 0xffff)) - 32);
1848 case SISFB_GET_TVPOSOFFSET
:
1849 return put_user((u32
)(((ivideo
->tvxpos
+32)<<16)|((ivideo
->tvypos
+32)&0xffff)),
1853 if(copy_from_user(&ivideo
->sisfb_command
, (void __user
*)arg
,
1854 sizeof(struct sisfb_cmd
)))
1857 sisfb_handle_command(ivideo
, &ivideo
->sisfb_command
);
1859 if(copy_to_user((void __user
*)arg
, &ivideo
->sisfb_command
,
1860 sizeof(struct sisfb_cmd
)))
1865 case SISFB_SET_LOCK
:
1866 if(get_user(gpu32
, argp
))
1869 ivideo
->sisfblocked
= (gpu32
) ? 1 : 0;
1873 #ifdef SIS_NEW_CONFIG_COMPAT
1874 return -ENOIOCTLCMD
;
1883 sisfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
, struct fb_info
*info
)
1885 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1887 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
1889 strlcpy(fix
->id
, ivideo
->myid
, sizeof(fix
->id
));
1891 mutex_lock(&info
->mm_lock
);
1892 fix
->smem_start
= ivideo
->video_base
+ ivideo
->video_offset
;
1893 fix
->smem_len
= ivideo
->sisfb_mem
;
1894 mutex_unlock(&info
->mm_lock
);
1895 fix
->type
= FB_TYPE_PACKED_PIXELS
;
1897 fix
->visual
= (ivideo
->video_bpp
== 8) ? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_TRUECOLOR
;
1899 fix
->ypanstep
= (ivideo
->sisfb_ypan
) ? 1 : 0;
1901 fix
->line_length
= ivideo
->video_linelength
;
1902 fix
->mmio_start
= ivideo
->mmio_base
;
1903 fix
->mmio_len
= ivideo
->mmio_size
;
1904 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
1905 fix
->accel
= FB_ACCEL_SIS_GLAMOUR
;
1906 } else if((ivideo
->chip
== SIS_330
) ||
1907 (ivideo
->chip
== SIS_760
) ||
1908 (ivideo
->chip
== SIS_761
)) {
1909 fix
->accel
= FB_ACCEL_SIS_XABRE
;
1910 } else if(ivideo
->chip
== XGI_20
) {
1911 fix
->accel
= FB_ACCEL_XGI_VOLARI_Z
;
1912 } else if(ivideo
->chip
>= XGI_40
) {
1913 fix
->accel
= FB_ACCEL_XGI_VOLARI_V
;
1915 fix
->accel
= FB_ACCEL_SIS_GLAMOUR_2
;
1921 /* ---------------- fb_ops structures ----------------- */
1923 static struct fb_ops sisfb_ops
= {
1924 .owner
= THIS_MODULE
,
1925 .fb_open
= sisfb_open
,
1926 .fb_release
= sisfb_release
,
1927 .fb_check_var
= sisfb_check_var
,
1928 .fb_set_par
= sisfb_set_par
,
1929 .fb_setcolreg
= sisfb_setcolreg
,
1930 .fb_pan_display
= sisfb_pan_display
,
1931 .fb_blank
= sisfb_blank
,
1932 .fb_fillrect
= fbcon_sis_fillrect
,
1933 .fb_copyarea
= fbcon_sis_copyarea
,
1934 .fb_imageblit
= cfb_imageblit
,
1935 .fb_sync
= fbcon_sis_sync
,
1936 #ifdef SIS_NEW_CONFIG_COMPAT
1937 .fb_compat_ioctl
= sisfb_ioctl
,
1939 .fb_ioctl
= sisfb_ioctl
1942 /* ---------------- Chip generation dependent routines ---------------- */
1944 static struct pci_dev
*sisfb_get_northbridge(int basechipid
)
1946 struct pci_dev
*pdev
= NULL
;
1947 int nbridgenum
, nbridgeidx
, i
;
1948 static const unsigned short nbridgeids
[] = {
1949 PCI_DEVICE_ID_SI_540
, /* for SiS 540 VGA */
1950 PCI_DEVICE_ID_SI_630
, /* for SiS 630/730 VGA */
1951 PCI_DEVICE_ID_SI_730
,
1952 PCI_DEVICE_ID_SI_550
, /* for SiS 550 VGA */
1953 PCI_DEVICE_ID_SI_650
, /* for SiS 650/651/740 VGA */
1954 PCI_DEVICE_ID_SI_651
,
1955 PCI_DEVICE_ID_SI_740
,
1956 PCI_DEVICE_ID_SI_661
, /* for SiS 661/741/660/760/761 VGA */
1957 PCI_DEVICE_ID_SI_741
,
1958 PCI_DEVICE_ID_SI_660
,
1959 PCI_DEVICE_ID_SI_760
,
1960 PCI_DEVICE_ID_SI_761
1963 switch(basechipid
) {
1964 #ifdef CONFIG_FB_SIS_300
1965 case SIS_540
: nbridgeidx
= 0; nbridgenum
= 1; break;
1966 case SIS_630
: nbridgeidx
= 1; nbridgenum
= 2; break;
1968 #ifdef CONFIG_FB_SIS_315
1969 case SIS_550
: nbridgeidx
= 3; nbridgenum
= 1; break;
1970 case SIS_650
: nbridgeidx
= 4; nbridgenum
= 3; break;
1971 case SIS_660
: nbridgeidx
= 7; nbridgenum
= 5; break;
1973 default: return NULL
;
1975 for(i
= 0; i
< nbridgenum
; i
++) {
1976 if((pdev
= pci_get_device(PCI_VENDOR_ID_SI
,
1977 nbridgeids
[nbridgeidx
+i
], NULL
)))
1983 static int sisfb_get_dram_size(struct sis_video_info
*ivideo
)
1985 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1989 ivideo
->video_size
= 0;
1990 ivideo
->UMAsize
= ivideo
->LFBsize
= 0;
1992 switch(ivideo
->chip
) {
1993 #ifdef CONFIG_FB_SIS_300
1995 reg
= SiS_GetReg(SISSR
, 0x14);
1996 ivideo
->video_size
= ((reg
& 0x3F) + 1) << 20;
2001 if(!ivideo
->nbridge
)
2003 pci_read_config_byte(ivideo
->nbridge
, 0x63, ®
);
2004 ivideo
->video_size
= 1 << (((reg
& 0x70) >> 4) + 21);
2007 #ifdef CONFIG_FB_SIS_315
2011 reg
= SiS_GetReg(SISSR
, 0x14);
2012 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
2013 switch((reg
>> 2) & 0x03) {
2016 ivideo
->video_size
<<= 1;
2019 ivideo
->video_size
+= (ivideo
->video_size
/2);
2023 reg
= SiS_GetReg(SISSR
, 0x14);
2024 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
2025 if(reg
& 0x0c) ivideo
->video_size
<<= 1;
2030 reg
= SiS_GetReg(SISSR
, 0x14);
2031 ivideo
->video_size
= (((reg
& 0x3f) + 1) << 2) << 20;
2035 reg
= SiS_GetReg(SISCR
, 0x79);
2036 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
2041 reg
= SiS_GetReg(SISCR
, 0x79);
2042 reg
= (reg
& 0xf0) >> 4;
2044 ivideo
->video_size
= (1 << reg
) << 20;
2045 ivideo
->UMAsize
= ivideo
->video_size
;
2047 reg
= SiS_GetReg(SISCR
, 0x78);
2051 ivideo
->LFBsize
= (32 << 20);
2053 ivideo
->LFBsize
= (64 << 20);
2055 ivideo
->video_size
+= ivideo
->LFBsize
;
2061 reg
= SiS_GetReg(SISSR
, 0x14);
2062 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
2063 if(ivideo
->chip
!= XGI_20
) {
2064 reg
= (reg
& 0x0c) >> 2;
2065 if(ivideo
->revision_id
== 2) {
2066 if(reg
& 0x01) reg
= 0x02;
2069 if(reg
== 0x02) ivideo
->video_size
<<= 1;
2070 else if(reg
== 0x03) ivideo
->video_size
<<= 2;
2080 /* -------------- video bridge device detection --------------- */
2082 static void sisfb_detect_VB_connect(struct sis_video_info
*ivideo
)
2086 /* No CRT2 on XGI Z7 */
2087 if(ivideo
->chip
== XGI_20
) {
2088 ivideo
->sisfb_crt1off
= 0;
2092 #ifdef CONFIG_FB_SIS_300
2093 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2094 temp
= SiS_GetReg(SISSR
, 0x17);
2095 if((temp
& 0x0F) && (ivideo
->chip
!= SIS_300
)) {
2096 /* PAL/NTSC is stored on SR16 on such machines */
2097 if(!(ivideo
->vbflags
& (TV_PAL
| TV_NTSC
| TV_PALM
| TV_PALN
))) {
2098 temp
= SiS_GetReg(SISSR
, 0x16);
2100 ivideo
->vbflags
|= TV_PAL
;
2102 ivideo
->vbflags
|= TV_NTSC
;
2108 cr32
= SiS_GetReg(SISCR
, 0x32);
2110 if(cr32
& SIS_CRT1
) {
2111 ivideo
->sisfb_crt1off
= 0;
2113 ivideo
->sisfb_crt1off
= (cr32
& 0xDF) ? 1 : 0;
2116 ivideo
->vbflags
&= ~(CRT2_TV
| CRT2_LCD
| CRT2_VGA
);
2118 if(cr32
& SIS_VB_TV
) ivideo
->vbflags
|= CRT2_TV
;
2119 if(cr32
& SIS_VB_LCD
) ivideo
->vbflags
|= CRT2_LCD
;
2120 if(cr32
& SIS_VB_CRT2
) ivideo
->vbflags
|= CRT2_VGA
;
2122 /* Check given parms for hardware compatibility.
2123 * (Cannot do this in the search_xx routines since we don't
2124 * know what hardware we are running on then)
2127 if(ivideo
->chip
!= SIS_550
) {
2128 ivideo
->sisfb_dstn
= ivideo
->sisfb_fstn
= 0;
2131 if(ivideo
->sisfb_tvplug
!= -1) {
2132 if( (ivideo
->sisvga_engine
!= SIS_315_VGA
) ||
2133 (!(ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) ) {
2134 if(ivideo
->sisfb_tvplug
& TV_YPBPR
) {
2135 ivideo
->sisfb_tvplug
= -1;
2136 printk(KERN_ERR
"sisfb: YPbPr not supported\n");
2140 if(ivideo
->sisfb_tvplug
!= -1) {
2141 if( (ivideo
->sisvga_engine
!= SIS_315_VGA
) ||
2142 (!(ivideo
->vbflags2
& VB2_SISHIVISIONBRIDGE
)) ) {
2143 if(ivideo
->sisfb_tvplug
& TV_HIVISION
) {
2144 ivideo
->sisfb_tvplug
= -1;
2145 printk(KERN_ERR
"sisfb: HiVision not supported\n");
2149 if(ivideo
->sisfb_tvstd
!= -1) {
2150 if( (!(ivideo
->vbflags2
& VB2_SISBRIDGE
)) &&
2151 (!((ivideo
->sisvga_engine
== SIS_315_VGA
) &&
2152 (ivideo
->vbflags2
& VB2_CHRONTEL
))) ) {
2153 if(ivideo
->sisfb_tvstd
& (TV_PALM
| TV_PALN
| TV_NTSCJ
)) {
2154 ivideo
->sisfb_tvstd
= -1;
2155 printk(KERN_ERR
"sisfb: PALM/PALN/NTSCJ not supported\n");
2160 /* Detect/set TV plug & type */
2161 if(ivideo
->sisfb_tvplug
!= -1) {
2162 ivideo
->vbflags
|= ivideo
->sisfb_tvplug
;
2164 if(cr32
& SIS_VB_YPBPR
) ivideo
->vbflags
|= (TV_YPBPR
|TV_YPBPR525I
); /* default: 480i */
2165 else if(cr32
& SIS_VB_HIVISION
) ivideo
->vbflags
|= TV_HIVISION
;
2166 else if(cr32
& SIS_VB_SCART
) ivideo
->vbflags
|= TV_SCART
;
2168 if(cr32
& SIS_VB_SVIDEO
) ivideo
->vbflags
|= TV_SVIDEO
;
2169 if(cr32
& SIS_VB_COMPOSITE
) ivideo
->vbflags
|= TV_AVIDEO
;
2173 if(!(ivideo
->vbflags
& (TV_YPBPR
| TV_HIVISION
))) {
2174 if(ivideo
->sisfb_tvstd
!= -1) {
2175 ivideo
->vbflags
&= ~(TV_NTSC
| TV_PAL
| TV_PALM
| TV_PALN
| TV_NTSCJ
);
2176 ivideo
->vbflags
|= ivideo
->sisfb_tvstd
;
2178 if(ivideo
->vbflags
& TV_SCART
) {
2179 ivideo
->vbflags
&= ~(TV_NTSC
| TV_PALM
| TV_PALN
| TV_NTSCJ
);
2180 ivideo
->vbflags
|= TV_PAL
;
2182 if(!(ivideo
->vbflags
& (TV_PAL
| TV_NTSC
| TV_PALM
| TV_PALN
| TV_NTSCJ
))) {
2183 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2184 temp
= SiS_GetReg(SISSR
, 0x38);
2185 if(temp
& 0x01) ivideo
->vbflags
|= TV_PAL
;
2186 else ivideo
->vbflags
|= TV_NTSC
;
2187 } else if((ivideo
->chip
<= SIS_315PRO
) || (ivideo
->chip
>= SIS_330
)) {
2188 temp
= SiS_GetReg(SISSR
, 0x38);
2189 if(temp
& 0x01) ivideo
->vbflags
|= TV_PAL
;
2190 else ivideo
->vbflags
|= TV_NTSC
;
2192 temp
= SiS_GetReg(SISCR
, 0x79);
2193 if(temp
& 0x20) ivideo
->vbflags
|= TV_PAL
;
2194 else ivideo
->vbflags
|= TV_NTSC
;
2199 /* Copy forceCRT1 option to CRT1off if option is given */
2200 if(ivideo
->sisfb_forcecrt1
!= -1) {
2201 ivideo
->sisfb_crt1off
= (ivideo
->sisfb_forcecrt1
) ? 0 : 1;
2205 /* ------------------ Sensing routines ------------------ */
2207 static bool sisfb_test_DDC1(struct sis_video_info
*ivideo
)
2212 old
= SiS_ReadDDC1Bit(&ivideo
->SiS_Pr
);
2214 if(old
!= SiS_ReadDDC1Bit(&ivideo
->SiS_Pr
)) break;
2216 return (count
!= -1);
2219 static void sisfb_sense_crt1(struct sis_video_info
*ivideo
)
2221 bool mustwait
= false;
2223 #ifdef CONFIG_FB_SIS_315
2229 sr1F
= SiS_GetReg(SISSR
, 0x1F);
2230 SiS_SetRegOR(SISSR
, 0x1F, 0x04);
2231 SiS_SetRegAND(SISSR
, 0x1F, 0x3F);
2232 if(sr1F
& 0xc0) mustwait
= true;
2234 #ifdef CONFIG_FB_SIS_315
2235 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2236 cr63
= SiS_GetReg(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
);
2238 SiS_SetRegAND(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, 0xBF);
2242 cr17
= SiS_GetReg(SISCR
, 0x17);
2245 SiS_SetRegOR(SISCR
, 0x17, 0x80);
2247 SiS_SetReg(SISSR
, 0x00, 0x01);
2248 SiS_SetReg(SISSR
, 0x00, 0x03);
2252 for(i
=0; i
< 10; i
++) sisfbwaitretracecrt1(ivideo
);
2255 #ifdef CONFIG_FB_SIS_315
2256 if(ivideo
->chip
>= SIS_330
) {
2257 SiS_SetRegAND(SISCR
, 0x32, ~0x20);
2258 if(ivideo
->chip
>= SIS_340
) {
2259 SiS_SetReg(SISCR
, 0x57, 0x4a);
2261 SiS_SetReg(SISCR
, 0x57, 0x5f);
2263 SiS_SetRegOR(SISCR
, 0x53, 0x02);
2264 while ((SiS_GetRegByte(SISINPSTAT
)) & 0x01) break;
2265 while (!((SiS_GetRegByte(SISINPSTAT
)) & 0x01)) break;
2266 if ((SiS_GetRegByte(SISMISCW
)) & 0x10) temp
= 1;
2267 SiS_SetRegAND(SISCR
, 0x53, 0xfd);
2268 SiS_SetRegAND(SISCR
, 0x57, 0x00);
2272 if(temp
== 0xffff) {
2275 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
,
2276 ivideo
->sisvga_engine
, 0, 0, NULL
, ivideo
->vbflags2
);
2277 } while(((temp
== 0) || (temp
== 0xffff)) && i
--);
2279 if((temp
== 0) || (temp
== 0xffff)) {
2280 if(sisfb_test_DDC1(ivideo
)) temp
= 1;
2284 if((temp
) && (temp
!= 0xffff)) {
2285 SiS_SetRegOR(SISCR
, 0x32, 0x20);
2288 #ifdef CONFIG_FB_SIS_315
2289 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2290 SiS_SetRegANDOR(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, 0xBF, cr63
);
2294 SiS_SetRegANDOR(SISCR
, 0x17, 0x7F, cr17
);
2296 SiS_SetReg(SISSR
, 0x1F, sr1F
);
2299 /* Determine and detect attached devices on SiS30x */
2300 static void SiS_SenseLCD(struct sis_video_info
*ivideo
)
2302 unsigned char buffer
[256];
2303 unsigned short temp
, realcrtno
, i
;
2304 u8 reg
, cr37
= 0, paneltype
= 0;
2307 ivideo
->SiS_Pr
.PanelSelfDetected
= false;
2309 /* LCD detection only for TMDS bridges */
2310 if(!(ivideo
->vbflags2
& VB2_SISTMDSBRIDGE
))
2312 if(ivideo
->vbflags2
& VB2_30xBDH
)
2315 /* If LCD already set up by BIOS, skip it */
2316 reg
= SiS_GetReg(SISCR
, 0x32);
2321 if(ivideo
->SiS_Pr
.DDCPortMixup
)
2324 /* Check DDC capabilities */
2325 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
2326 realcrtno
, 0, &buffer
[0], ivideo
->vbflags2
);
2328 if((!temp
) || (temp
== 0xffff) || (!(temp
& 0x02)))
2332 i
= 3; /* Number of retrys */
2334 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
,
2335 ivideo
->sisvga_engine
, realcrtno
, 1,
2336 &buffer
[0], ivideo
->vbflags2
);
2337 } while((temp
) && i
--);
2342 /* No digital device */
2343 if(!(buffer
[0x14] & 0x80))
2346 /* First detailed timing preferred timing? */
2347 if(!(buffer
[0x18] & 0x02))
2350 xres
= buffer
[0x38] | ((buffer
[0x3a] & 0xf0) << 4);
2351 yres
= buffer
[0x3b] | ((buffer
[0x3d] & 0xf0) << 4);
2363 if((yres
== 1200) && (ivideo
->vbflags2
& VB2_30xC
))
2374 if((buffer
[0x47] & 0x18) == 0x18)
2375 cr37
|= ((((buffer
[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2379 SiS_SetReg(SISCR
, 0x36, paneltype
);
2381 SiS_SetRegANDOR(SISCR
, 0x37, 0x0c, cr37
);
2382 SiS_SetRegOR(SISCR
, 0x32, 0x08);
2384 ivideo
->SiS_Pr
.PanelSelfDetected
= true;
2387 static int SISDoSense(struct sis_video_info
*ivideo
, u16 type
, u16 test
)
2389 int temp
, mytest
, result
, i
, j
;
2391 for(j
= 0; j
< 10; j
++) {
2393 for(i
= 0; i
< 3; i
++) {
2395 SiS_SetReg(SISPART4
, 0x11, (type
& 0x00ff));
2396 temp
= (type
>> 8) | (mytest
& 0x00ff);
2397 SiS_SetRegANDOR(SISPART4
, 0x10, 0xe0, temp
);
2398 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x1500);
2401 temp
= SiS_GetReg(SISPART4
, 0x03);
2404 if(temp
== mytest
) result
++;
2406 SiS_SetReg(SISPART4
, 0x11, 0x00);
2407 SiS_SetRegAND(SISPART4
, 0x10, 0xe0);
2408 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x1000);
2411 if((result
== 0) || (result
>= 2)) break;
2416 static void SiS_Sense30x(struct sis_video_info
*ivideo
)
2418 u8 backupP4_0d
,backupP2_00
,backupP2_4d
,backupSR_1e
,biosflag
=0;
2419 u16 svhs
=0, svhs_c
=0;
2420 u16 cvbs
=0, cvbs_c
=0;
2421 u16 vga2
=0, vga2_c
=0;
2423 char stdstr
[] = "sisfb: Detected";
2424 char tvstr
[] = "TV connected to";
2426 if(ivideo
->vbflags2
& VB2_301
) {
2427 svhs
= 0x00b9; cvbs
= 0x00b3; vga2
= 0x00d1;
2428 myflag
= SiS_GetReg(SISPART4
, 0x01);
2430 svhs
= 0x00dd; cvbs
= 0x00ee; vga2
= 0x00fd;
2432 } else if(ivideo
->vbflags2
& (VB2_301B
| VB2_302B
)) {
2433 svhs
= 0x016b; cvbs
= 0x0174; vga2
= 0x0190;
2434 } else if(ivideo
->vbflags2
& (VB2_301LV
| VB2_302LV
)) {
2435 svhs
= 0x0200; cvbs
= 0x0100;
2436 } else if(ivideo
->vbflags2
& (VB2_301C
| VB2_302ELV
| VB2_307T
| VB2_307LV
)) {
2437 svhs
= 0x016b; cvbs
= 0x0110; vga2
= 0x0190;
2441 vga2_c
= 0x0e08; svhs_c
= 0x0404; cvbs_c
= 0x0804;
2442 if(ivideo
->vbflags
& (VB2_301LV
|VB2_302LV
|VB2_302ELV
|VB2_307LV
)) {
2443 svhs_c
= 0x0408; cvbs_c
= 0x0808;
2447 if(ivideo
->haveXGIROM
) {
2448 biosflag
= ivideo
->bios_abase
[0x58] & 0x03;
2449 } else if(ivideo
->newrom
) {
2450 if(ivideo
->bios_abase
[0x5d] & 0x04) biosflag
|= 0x01;
2451 } else if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2452 if(ivideo
->bios_abase
) {
2453 biosflag
= ivideo
->bios_abase
[0xfe] & 0x03;
2457 if(ivideo
->chip
== SIS_300
) {
2458 myflag
= SiS_GetReg(SISSR
, 0x3b);
2459 if(!(myflag
& 0x01)) vga2
= vga2_c
= 0;
2462 if(!(ivideo
->vbflags2
& VB2_SISVGA2BRIDGE
)) {
2466 backupSR_1e
= SiS_GetReg(SISSR
, 0x1e);
2467 SiS_SetRegOR(SISSR
, 0x1e, 0x20);
2469 backupP4_0d
= SiS_GetReg(SISPART4
, 0x0d);
2470 if(ivideo
->vbflags2
& VB2_30xC
) {
2471 SiS_SetRegANDOR(SISPART4
, 0x0d, ~0x07, 0x01);
2473 SiS_SetRegOR(SISPART4
, 0x0d, 0x04);
2475 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x2000);
2477 backupP2_00
= SiS_GetReg(SISPART2
, 0x00);
2478 SiS_SetReg(SISPART2
, 0x00, ((backupP2_00
| 0x1c) & 0xfc));
2480 backupP2_4d
= SiS_GetReg(SISPART2
, 0x4d);
2481 if(ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
) {
2482 SiS_SetReg(SISPART2
, 0x4d, (backupP2_4d
& ~0x10));
2485 if(!(ivideo
->vbflags2
& VB2_30xCLV
)) {
2486 SISDoSense(ivideo
, 0, 0);
2489 SiS_SetRegAND(SISCR
, 0x32, ~0x14);
2491 if(vga2_c
|| vga2
) {
2492 if(SISDoSense(ivideo
, vga2
, vga2_c
)) {
2493 if(biosflag
& 0x01) {
2494 printk(KERN_INFO
"%s %s SCART output\n", stdstr
, tvstr
);
2495 SiS_SetRegOR(SISCR
, 0x32, 0x04);
2497 printk(KERN_INFO
"%s secondary VGA connection\n", stdstr
);
2498 SiS_SetRegOR(SISCR
, 0x32, 0x10);
2503 SiS_SetRegAND(SISCR
, 0x32, 0x3f);
2505 if(ivideo
->vbflags2
& VB2_30xCLV
) {
2506 SiS_SetRegOR(SISPART4
, 0x0d, 0x04);
2509 if((ivideo
->sisvga_engine
== SIS_315_VGA
) && (ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) {
2510 SiS_SetReg(SISPART2
, 0x4d, (backupP2_4d
| 0x10));
2511 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x2000);
2512 if((result
= SISDoSense(ivideo
, svhs
, 0x0604))) {
2513 if((result
= SISDoSense(ivideo
, cvbs
, 0x0804))) {
2514 printk(KERN_INFO
"%s %s YPbPr component output\n", stdstr
, tvstr
);
2515 SiS_SetRegOR(SISCR
, 0x32, 0x80);
2518 SiS_SetReg(SISPART2
, 0x4d, backupP2_4d
);
2521 SiS_SetRegAND(SISCR
, 0x32, ~0x03);
2523 if(!(ivideo
->vbflags
& TV_YPBPR
)) {
2524 if((result
= SISDoSense(ivideo
, svhs
, svhs_c
))) {
2525 printk(KERN_INFO
"%s %s SVIDEO output\n", stdstr
, tvstr
);
2526 SiS_SetRegOR(SISCR
, 0x32, 0x02);
2528 if((biosflag
& 0x02) || (!result
)) {
2529 if(SISDoSense(ivideo
, cvbs
, cvbs_c
)) {
2530 printk(KERN_INFO
"%s %s COMPOSITE output\n", stdstr
, tvstr
);
2531 SiS_SetRegOR(SISCR
, 0x32, 0x01);
2536 SISDoSense(ivideo
, 0, 0);
2538 SiS_SetReg(SISPART2
, 0x00, backupP2_00
);
2539 SiS_SetReg(SISPART4
, 0x0d, backupP4_0d
);
2540 SiS_SetReg(SISSR
, 0x1e, backupSR_1e
);
2542 if(ivideo
->vbflags2
& VB2_30xCLV
) {
2543 biosflag
= SiS_GetReg(SISPART2
, 0x00);
2544 if(biosflag
& 0x20) {
2545 for(myflag
= 2; myflag
> 0; myflag
--) {
2547 SiS_SetReg(SISPART2
, 0x00, biosflag
);
2552 SiS_SetReg(SISPART2
, 0x00, backupP2_00
);
2555 /* Determine and detect attached TV's on Chrontel */
2556 static void SiS_SenseCh(struct sis_video_info
*ivideo
)
2558 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2560 char stdstr
[] = "sisfb: Chrontel: Detected TV connected to";
2562 #ifdef CONFIG_FB_SIS_300
2563 unsigned char test
[3];
2567 if(ivideo
->chip
< SIS_315H
) {
2569 #ifdef CONFIG_FB_SIS_300
2570 ivideo
->SiS_Pr
.SiS_IF_DEF_CH70xx
= 1; /* Chrontel 700x */
2571 SiS_SetChrontelGPIO(&ivideo
->SiS_Pr
, 0x9c); /* Set general purpose IO for Chrontel communication */
2572 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 1000);
2573 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x25);
2574 /* See Chrontel TB31 for explanation */
2575 temp2
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0e);
2576 if(((temp2
& 0x07) == 0x01) || (temp2
& 0x04)) {
2577 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0e, 0x0b);
2578 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 300);
2580 temp2
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x25);
2581 if(temp2
!= temp1
) temp1
= temp2
;
2583 if((temp1
>= 0x22) && (temp1
<= 0x50)) {
2584 /* Read power status */
2585 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0e);
2586 if((temp1
& 0x03) != 0x03) {
2587 /* Power all outputs */
2588 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0e,0x0b);
2589 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 300);
2591 /* Sense connected TV devices */
2592 for(i
= 0; i
< 3; i
++) {
2593 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x10, 0x01);
2594 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2595 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x10, 0x00);
2596 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2597 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x10);
2598 if(!(temp1
& 0x08)) test
[i
] = 0x02;
2599 else if(!(temp1
& 0x02)) test
[i
] = 0x01;
2601 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2604 if(test
[0] == test
[1]) temp1
= test
[0];
2605 else if(test
[0] == test
[2]) temp1
= test
[0];
2606 else if(test
[1] == test
[2]) temp1
= test
[1];
2609 "sisfb: TV detection unreliable - test results varied\n");
2613 printk(KERN_INFO
"%s SVIDEO output\n", stdstr
);
2614 ivideo
->vbflags
|= TV_SVIDEO
;
2615 SiS_SetRegOR(SISCR
, 0x32, 0x02);
2616 SiS_SetRegAND(SISCR
, 0x32, ~0x05);
2617 } else if (temp1
== 0x01) {
2618 printk(KERN_INFO
"%s CVBS output\n", stdstr
);
2619 ivideo
->vbflags
|= TV_AVIDEO
;
2620 SiS_SetRegOR(SISCR
, 0x32, 0x01);
2621 SiS_SetRegAND(SISCR
, 0x32, ~0x06);
2623 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x0e, 0x01, 0xF8);
2624 SiS_SetRegAND(SISCR
, 0x32, ~0x07);
2626 } else if(temp1
== 0) {
2627 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x0e, 0x01, 0xF8);
2628 SiS_SetRegAND(SISCR
, 0x32, ~0x07);
2630 /* Set general purpose IO for Chrontel communication */
2631 SiS_SetChrontelGPIO(&ivideo
->SiS_Pr
, 0x00);
2636 #ifdef CONFIG_FB_SIS_315
2637 ivideo
->SiS_Pr
.SiS_IF_DEF_CH70xx
= 2; /* Chrontel 7019 */
2638 temp1
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x49);
2639 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x49, 0x20);
2640 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2641 temp2
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x20);
2643 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x20, temp2
);
2644 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2646 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x20, temp2
);
2647 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2648 temp2
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x20);
2649 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x49, temp1
);
2651 if(temp2
& 0x02) temp1
|= 0x01;
2652 if(temp2
& 0x10) temp1
|= 0x01;
2653 if(temp2
& 0x04) temp1
|= 0x02;
2654 if( (temp1
& 0x01) && (temp1
& 0x02) ) temp1
= 0x04;
2657 printk(KERN_INFO
"%s CVBS output\n", stdstr
);
2658 ivideo
->vbflags
|= TV_AVIDEO
;
2659 SiS_SetRegOR(SISCR
, 0x32, 0x01);
2660 SiS_SetRegAND(SISCR
, 0x32, ~0x06);
2663 printk(KERN_INFO
"%s SVIDEO output\n", stdstr
);
2664 ivideo
->vbflags
|= TV_SVIDEO
;
2665 SiS_SetRegOR(SISCR
, 0x32, 0x02);
2666 SiS_SetRegAND(SISCR
, 0x32, ~0x05);
2669 printk(KERN_INFO
"%s SCART output\n", stdstr
);
2670 SiS_SetRegOR(SISCR
, 0x32, 0x04);
2671 SiS_SetRegAND(SISCR
, 0x32, ~0x03);
2674 SiS_SetRegAND(SISCR
, 0x32, ~0x07);
2680 static void sisfb_get_VB_type(struct sis_video_info
*ivideo
)
2682 char stdstr
[] = "sisfb: Detected";
2683 char bridgestr
[] = "video bridge";
2687 /* No CRT2 on XGI Z7 */
2688 if(ivideo
->chip
== XGI_20
)
2691 vb_chipid
= SiS_GetReg(SISPART4
, 0x00);
2694 reg
= SiS_GetReg(SISPART4
, 0x01);
2696 ivideo
->vbflags
|= VB_301
; /* Deprecated */
2697 ivideo
->vbflags2
|= VB2_301
;
2698 printk(KERN_INFO
"%s SiS301 %s\n", stdstr
, bridgestr
);
2699 } else if(reg
< 0xc0) {
2700 ivideo
->vbflags
|= VB_301B
; /* Deprecated */
2701 ivideo
->vbflags2
|= VB2_301B
;
2702 reg
= SiS_GetReg(SISPART4
, 0x23);
2704 ivideo
->vbflags
|= VB_30xBDH
; /* Deprecated */
2705 ivideo
->vbflags2
|= VB2_30xBDH
;
2706 printk(KERN_INFO
"%s SiS301B-DH %s\n", stdstr
, bridgestr
);
2708 printk(KERN_INFO
"%s SiS301B %s\n", stdstr
, bridgestr
);
2710 } else if(reg
< 0xd0) {
2711 ivideo
->vbflags
|= VB_301C
; /* Deprecated */
2712 ivideo
->vbflags2
|= VB2_301C
;
2713 printk(KERN_INFO
"%s SiS301C %s\n", stdstr
, bridgestr
);
2714 } else if(reg
< 0xe0) {
2715 ivideo
->vbflags
|= VB_301LV
; /* Deprecated */
2716 ivideo
->vbflags2
|= VB2_301LV
;
2717 printk(KERN_INFO
"%s SiS301LV %s\n", stdstr
, bridgestr
);
2718 } else if(reg
<= 0xe1) {
2719 reg
= SiS_GetReg(SISPART4
, 0x39);
2721 ivideo
->vbflags
|= VB_302LV
; /* Deprecated */
2722 ivideo
->vbflags2
|= VB2_302LV
;
2723 printk(KERN_INFO
"%s SiS302LV %s\n", stdstr
, bridgestr
);
2725 ivideo
->vbflags
|= VB_301C
; /* Deprecated */
2726 ivideo
->vbflags2
|= VB2_301C
;
2727 printk(KERN_INFO
"%s SiS301C(P4) %s\n", stdstr
, bridgestr
);
2729 ivideo
->vbflags
|= VB_302ELV
; /* Deprecated */
2730 ivideo
->vbflags2
|= VB2_302ELV
;
2731 printk(KERN_INFO
"%s SiS302ELV %s\n", stdstr
, bridgestr
);
2737 ivideo
->vbflags
|= VB_302B
; /* Deprecated */
2738 ivideo
->vbflags2
|= VB2_302B
;
2739 printk(KERN_INFO
"%s SiS302B %s\n", stdstr
, bridgestr
);
2743 if((!(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
)) && (ivideo
->chip
!= SIS_300
)) {
2744 reg
= SiS_GetReg(SISCR
, 0x37);
2745 reg
&= SIS_EXTERNAL_CHIP_MASK
;
2747 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2748 #ifdef CONFIG_FB_SIS_300
2750 case SIS_EXTERNAL_CHIP_LVDS
:
2751 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2752 ivideo
->vbflags2
|= VB2_LVDS
;
2754 case SIS_EXTERNAL_CHIP_TRUMPION
:
2755 ivideo
->vbflags
|= (VB_LVDS
| VB_TRUMPION
); /* Deprecated */
2756 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_TRUMPION
);
2758 case SIS_EXTERNAL_CHIP_CHRONTEL
:
2759 ivideo
->vbflags
|= VB_CHRONTEL
; /* Deprecated */
2760 ivideo
->vbflags2
|= VB2_CHRONTEL
;
2762 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL
:
2763 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2764 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2767 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 1;
2769 } else if(ivideo
->chip
< SIS_661
) {
2770 #ifdef CONFIG_FB_SIS_315
2772 case SIS310_EXTERNAL_CHIP_LVDS
:
2773 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2774 ivideo
->vbflags2
|= VB2_LVDS
;
2776 case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL
:
2777 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2778 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2781 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 2;
2783 } else if(ivideo
->chip
>= SIS_661
) {
2784 #ifdef CONFIG_FB_SIS_315
2785 reg
= SiS_GetReg(SISCR
, 0x38);
2789 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2790 ivideo
->vbflags2
|= VB2_LVDS
;
2793 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2794 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2797 ivideo
->vbflags
|= (VB_LVDS
| VB_CONEXANT
); /* Deprecated */
2798 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CONEXANT
);
2801 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 2;
2804 if(ivideo
->vbflags2
& VB2_LVDS
) {
2805 printk(KERN_INFO
"%s LVDS transmitter\n", stdstr
);
2807 if((ivideo
->sisvga_engine
== SIS_300_VGA
) && (ivideo
->vbflags2
& VB2_TRUMPION
)) {
2808 printk(KERN_INFO
"%s Trumpion Zurac LCD scaler\n", stdstr
);
2810 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
2811 printk(KERN_INFO
"%s Chrontel TV encoder\n", stdstr
);
2813 if((ivideo
->chip
>= SIS_661
) && (ivideo
->vbflags2
& VB2_CONEXANT
)) {
2814 printk(KERN_INFO
"%s Conexant external device\n", stdstr
);
2818 if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
2819 SiS_SenseLCD(ivideo
);
2820 SiS_Sense30x(ivideo
);
2821 } else if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
2822 SiS_SenseCh(ivideo
);
2826 /* ---------- Engine initialization routines ------------ */
2829 sisfb_engine_init(struct sis_video_info
*ivideo
)
2832 /* Initialize command queue (we use MMIO only) */
2834 /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
2836 ivideo
->caps
&= ~(TURBO_QUEUE_CAP
|
2837 MMIO_CMD_QUEUE_CAP
|
2841 #ifdef CONFIG_FB_SIS_300
2842 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2846 tqueue_pos
= (ivideo
->video_size
- ivideo
->cmdQueueSize
) / (64 * 1024);
2848 tq_state
= SiS_GetReg(SISSR
, IND_SIS_TURBOQUEUE_SET
);
2851 tq_state
|= (u8
)(tqueue_pos
>> 8);
2852 SiS_SetReg(SISSR
, IND_SIS_TURBOQUEUE_SET
, tq_state
);
2854 SiS_SetReg(SISSR
, IND_SIS_TURBOQUEUE_ADR
, (u8
)(tqueue_pos
& 0xff));
2856 ivideo
->caps
|= TURBO_QUEUE_CAP
;
2860 #ifdef CONFIG_FB_SIS_315
2861 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2862 u32 tempq
= 0, templ
;
2865 if(ivideo
->chip
== XGI_20
) {
2866 switch(ivideo
->cmdQueueSize
) {
2868 temp
= SIS_CMD_QUEUE_SIZE_Z7_64k
;
2872 temp
= SIS_CMD_QUEUE_SIZE_Z7_128k
;
2875 switch(ivideo
->cmdQueueSize
) {
2876 case (4 * 1024 * 1024):
2877 temp
= SIS_CMD_QUEUE_SIZE_4M
;
2879 case (2 * 1024 * 1024):
2880 temp
= SIS_CMD_QUEUE_SIZE_2M
;
2882 case (1 * 1024 * 1024):
2883 temp
= SIS_CMD_QUEUE_SIZE_1M
;
2887 temp
= SIS_CMD_QUEUE_SIZE_512k
;
2891 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_THRESHOLD
, COMMAND_QUEUE_THRESHOLD
);
2892 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, SIS_CMD_QUEUE_RESET
);
2894 if((ivideo
->chip
>= XGI_40
) && ivideo
->modechanged
) {
2895 /* Must disable dual pipe on XGI_40. Can't do
2896 * this in MMIO mode, because it requires
2897 * setting/clearing a bit in the MMIO fire trigger
2900 if(!((templ
= MMIO_IN32(ivideo
->mmio_vbase
, 0x8240)) & (1 << 10))) {
2902 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, 0);
2904 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, (temp
| SIS_VRAM_CMDQUEUE_ENABLE
));
2906 tempq
= MMIO_IN32(ivideo
->mmio_vbase
, Q_READ_PTR
);
2907 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, tempq
);
2909 tempq
= (u32
)(ivideo
->video_size
- ivideo
->cmdQueueSize
);
2910 MMIO_OUT32(ivideo
->mmio_vbase
, Q_BASE_ADDR
, tempq
);
2912 writel(0x16800000 + 0x8240, ivideo
->video_vbase
+ tempq
);
2913 writel(templ
| (1 << 10), ivideo
->video_vbase
+ tempq
+ 4);
2914 writel(0x168F0000, ivideo
->video_vbase
+ tempq
+ 8);
2915 writel(0x168F0000, ivideo
->video_vbase
+ tempq
+ 12);
2917 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, (tempq
+ 16));
2919 sisfb_syncaccel(ivideo
);
2921 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, SIS_CMD_QUEUE_RESET
);
2926 tempq
= MMIO_IN32(ivideo
->mmio_vbase
, MMIO_QUEUE_READPORT
);
2927 MMIO_OUT32(ivideo
->mmio_vbase
, MMIO_QUEUE_WRITEPORT
, tempq
);
2929 temp
|= (SIS_MMIO_CMD_ENABLE
| SIS_CMD_AUTO_CORR
);
2930 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, temp
);
2932 tempq
= (u32
)(ivideo
->video_size
- ivideo
->cmdQueueSize
);
2933 MMIO_OUT32(ivideo
->mmio_vbase
, MMIO_QUEUE_PHYBASE
, tempq
);
2935 ivideo
->caps
|= MMIO_CMD_QUEUE_CAP
;
2939 ivideo
->engineok
= 1;
2942 static void sisfb_detect_lcd_type(struct sis_video_info
*ivideo
)
2947 reg
= SiS_GetReg(SISCR
, 0x36);
2949 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2950 ivideo
->CRT2LCDType
= sis300paneltype
[reg
];
2951 } else if(ivideo
->chip
>= SIS_661
) {
2952 ivideo
->CRT2LCDType
= sis661paneltype
[reg
];
2954 ivideo
->CRT2LCDType
= sis310paneltype
[reg
];
2955 if((ivideo
->chip
== SIS_550
) && (sisfb_fstn
)) {
2956 if((ivideo
->CRT2LCDType
!= LCD_320x240_2
) &&
2957 (ivideo
->CRT2LCDType
!= LCD_320x240_3
)) {
2958 ivideo
->CRT2LCDType
= LCD_320x240
;
2963 if(ivideo
->CRT2LCDType
== LCD_UNKNOWN
) {
2964 /* For broken BIOSes: Assume 1024x768, RGB18 */
2965 ivideo
->CRT2LCDType
= LCD_1024x768
;
2966 SiS_SetRegANDOR(SISCR
, 0x36, 0xf0, 0x02);
2967 SiS_SetRegANDOR(SISCR
, 0x37, 0xee, 0x01);
2968 printk(KERN_DEBUG
"sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg
);
2971 for(i
= 0; i
< SIS_LCD_NUMBER
; i
++) {
2972 if(ivideo
->CRT2LCDType
== sis_lcd_data
[i
].lcdtype
) {
2973 ivideo
->lcdxres
= sis_lcd_data
[i
].xres
;
2974 ivideo
->lcdyres
= sis_lcd_data
[i
].yres
;
2975 ivideo
->lcddefmodeidx
= sis_lcd_data
[i
].default_mode_idx
;
2980 #ifdef CONFIG_FB_SIS_300
2981 if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_BARCO1366
) {
2982 ivideo
->lcdxres
= 1360; ivideo
->lcdyres
= 1024;
2983 ivideo
->lcddefmodeidx
= DEFAULT_MODE_1360
;
2984 } else if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_PANEL848
) {
2985 ivideo
->lcdxres
= 848; ivideo
->lcdyres
= 480;
2986 ivideo
->lcddefmodeidx
= DEFAULT_MODE_848
;
2987 } else if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_PANEL856
) {
2988 ivideo
->lcdxres
= 856; ivideo
->lcdyres
= 480;
2989 ivideo
->lcddefmodeidx
= DEFAULT_MODE_856
;
2993 printk(KERN_DEBUG
"sisfb: Detected %dx%d flat panel\n",
2994 ivideo
->lcdxres
, ivideo
->lcdyres
);
2997 static void sisfb_save_pdc_emi(struct sis_video_info
*ivideo
)
2999 #ifdef CONFIG_FB_SIS_300
3000 /* Save the current PanelDelayCompensation if the LCD is currently used */
3001 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3002 if(ivideo
->vbflags2
& (VB2_LVDS
| VB2_30xBDH
)) {
3004 tmp
= SiS_GetReg(SISCR
, 0x30);
3006 /* Currently on LCD? If yes, read current pdc */
3007 ivideo
->detectedpdc
= SiS_GetReg(SISPART1
, 0x13);
3008 ivideo
->detectedpdc
&= 0x3c;
3009 if(ivideo
->SiS_Pr
.PDC
== -1) {
3010 /* Let option override detection */
3011 ivideo
->SiS_Pr
.PDC
= ivideo
->detectedpdc
;
3013 printk(KERN_INFO
"sisfb: Detected LCD PDC 0x%02x\n",
3014 ivideo
->detectedpdc
);
3016 if((ivideo
->SiS_Pr
.PDC
!= -1) &&
3017 (ivideo
->SiS_Pr
.PDC
!= ivideo
->detectedpdc
)) {
3018 printk(KERN_INFO
"sisfb: Using LCD PDC 0x%02x\n",
3019 ivideo
->SiS_Pr
.PDC
);
3025 #ifdef CONFIG_FB_SIS_315
3026 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3028 /* Try to find about LCDA */
3029 if(ivideo
->vbflags2
& VB2_SISLCDABRIDGE
) {
3031 tmp
= SiS_GetReg(SISPART1
, 0x13);
3033 ivideo
->SiS_Pr
.SiS_UseLCDA
= true;
3034 ivideo
->detectedlcda
= 0x03;
3039 if(ivideo
->vbflags2
& VB2_SISLVDSBRIDGE
) {
3041 tmp
= SiS_GetReg(SISCR
, 0x30);
3042 if((tmp
& 0x20) || (ivideo
->detectedlcda
!= 0xff)) {
3043 /* Currently on LCD? If yes, read current pdc */
3045 pdc
= SiS_GetReg(SISPART1
, 0x2D);
3046 ivideo
->detectedpdc
= (pdc
& 0x0f) << 1;
3047 ivideo
->detectedpdca
= (pdc
& 0xf0) >> 3;
3048 pdc
= SiS_GetReg(SISPART1
, 0x35);
3049 ivideo
->detectedpdc
|= ((pdc
>> 7) & 0x01);
3050 pdc
= SiS_GetReg(SISPART1
, 0x20);
3051 ivideo
->detectedpdca
|= ((pdc
>> 6) & 0x01);
3052 if(ivideo
->newrom
) {
3053 /* New ROM invalidates other PDC resp. */
3054 if(ivideo
->detectedlcda
!= 0xff) {
3055 ivideo
->detectedpdc
= 0xff;
3057 ivideo
->detectedpdca
= 0xff;
3060 if(ivideo
->SiS_Pr
.PDC
== -1) {
3061 if(ivideo
->detectedpdc
!= 0xff) {
3062 ivideo
->SiS_Pr
.PDC
= ivideo
->detectedpdc
;
3065 if(ivideo
->SiS_Pr
.PDCA
== -1) {
3066 if(ivideo
->detectedpdca
!= 0xff) {
3067 ivideo
->SiS_Pr
.PDCA
= ivideo
->detectedpdca
;
3070 if(ivideo
->detectedpdc
!= 0xff) {
3072 "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3073 ivideo
->detectedpdc
);
3075 if(ivideo
->detectedpdca
!= 0xff) {
3077 "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3078 ivideo
->detectedpdca
);
3083 if(ivideo
->vbflags2
& VB2_SISEMIBRIDGE
) {
3084 ivideo
->SiS_Pr
.EMI_30
= SiS_GetReg(SISPART4
, 0x30);
3085 ivideo
->SiS_Pr
.EMI_31
= SiS_GetReg(SISPART4
, 0x31);
3086 ivideo
->SiS_Pr
.EMI_32
= SiS_GetReg(SISPART4
, 0x32);
3087 ivideo
->SiS_Pr
.EMI_33
= SiS_GetReg(SISPART4
, 0x33);
3088 ivideo
->SiS_Pr
.HaveEMI
= true;
3089 if((tmp
& 0x20) || (ivideo
->detectedlcda
!= 0xff)) {
3090 ivideo
->SiS_Pr
.HaveEMILCD
= true;
3095 /* Let user override detected PDCs (all bridges) */
3096 if(ivideo
->vbflags2
& VB2_30xBLV
) {
3097 if((ivideo
->SiS_Pr
.PDC
!= -1) &&
3098 (ivideo
->SiS_Pr
.PDC
!= ivideo
->detectedpdc
)) {
3099 printk(KERN_INFO
"sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3100 ivideo
->SiS_Pr
.PDC
);
3102 if((ivideo
->SiS_Pr
.PDCA
!= -1) &&
3103 (ivideo
->SiS_Pr
.PDCA
!= ivideo
->detectedpdca
)) {
3104 printk(KERN_INFO
"sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3105 ivideo
->SiS_Pr
.PDCA
);
3113 /* -------------------- Memory manager routines ---------------------- */
3115 static u32
sisfb_getheapstart(struct sis_video_info
*ivideo
)
3117 u32 ret
= ivideo
->sisfb_parm_mem
* 1024;
3118 u32 maxoffs
= ivideo
->video_size
- ivideo
->hwcursor_size
- ivideo
->cmdQueueSize
;
3121 /* Calculate heap start = end of memory for console
3123 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3124 * C = console, D = heap, H = HWCursor, Q = cmd-queue
3126 * On 76x in UMA+LFB mode, the layout is as follows:
3127 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3128 * where the heap is the entire UMA area, eventually
3129 * into the LFB area if the given mem parameter is
3130 * higher than the size of the UMA memory.
3132 * Basically given by "mem" parameter
3134 * maximum = videosize - cmd_queue - hwcursor
3135 * (results in a heap of size 0)
3136 * default = SiS 300: depends on videosize
3137 * SiS 315/330/340/XGI: 32k below max
3140 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3141 if(ivideo
->video_size
> 0x1000000) {
3143 } else if(ivideo
->video_size
> 0x800000) {
3148 } else if(ivideo
->UMAsize
&& ivideo
->LFBsize
) {
3151 def
= maxoffs
- 0x8000;
3154 /* Use default for secondary card for now (FIXME) */
3155 if((!ret
) || (ret
> maxoffs
) || (ivideo
->cardnumber
!= 0))
3161 static u32
sisfb_getheapsize(struct sis_video_info
*ivideo
)
3163 u32 max
= ivideo
->video_size
- ivideo
->hwcursor_size
- ivideo
->cmdQueueSize
;
3166 if(ivideo
->UMAsize
&& ivideo
->LFBsize
) {
3167 if( (!ivideo
->sisfb_parm_mem
) ||
3168 ((ivideo
->sisfb_parm_mem
* 1024) > max
) ||
3169 ((max
- (ivideo
->sisfb_parm_mem
* 1024)) < ivideo
->UMAsize
) ) {
3170 ret
= ivideo
->UMAsize
;
3171 max
-= ivideo
->UMAsize
;
3173 ret
= max
- (ivideo
->sisfb_parm_mem
* 1024);
3174 max
= ivideo
->sisfb_parm_mem
* 1024;
3176 ivideo
->video_offset
= ret
;
3177 ivideo
->sisfb_mem
= max
;
3179 ret
= max
- ivideo
->heapstart
;
3180 ivideo
->sisfb_mem
= ivideo
->heapstart
;
3186 static int sisfb_heap_init(struct sis_video_info
*ivideo
)
3190 ivideo
->video_offset
= 0;
3191 if(ivideo
->sisfb_parm_mem
) {
3192 if( (ivideo
->sisfb_parm_mem
< (2 * 1024 * 1024)) ||
3193 (ivideo
->sisfb_parm_mem
> ivideo
->video_size
) ) {
3194 ivideo
->sisfb_parm_mem
= 0;
3198 ivideo
->heapstart
= sisfb_getheapstart(ivideo
);
3199 ivideo
->sisfb_heap_size
= sisfb_getheapsize(ivideo
);
3201 ivideo
->sisfb_heap_start
= ivideo
->video_vbase
+ ivideo
->heapstart
;
3202 ivideo
->sisfb_heap_end
= ivideo
->sisfb_heap_start
+ ivideo
->sisfb_heap_size
;
3204 printk(KERN_INFO
"sisfb: Memory heap starting at %dK, size %dK\n",
3205 (int)(ivideo
->heapstart
/ 1024), (int)(ivideo
->sisfb_heap_size
/ 1024));
3207 ivideo
->sisfb_heap
.vinfo
= ivideo
;
3209 ivideo
->sisfb_heap
.poha_chain
= NULL
;
3210 ivideo
->sisfb_heap
.poh_freelist
= NULL
;
3212 poh
= sisfb_poh_new_node(&ivideo
->sisfb_heap
);
3216 poh
->poh_next
= &ivideo
->sisfb_heap
.oh_free
;
3217 poh
->poh_prev
= &ivideo
->sisfb_heap
.oh_free
;
3218 poh
->size
= ivideo
->sisfb_heap_size
;
3219 poh
->offset
= ivideo
->heapstart
;
3221 ivideo
->sisfb_heap
.oh_free
.poh_next
= poh
;
3222 ivideo
->sisfb_heap
.oh_free
.poh_prev
= poh
;
3223 ivideo
->sisfb_heap
.oh_free
.size
= 0;
3224 ivideo
->sisfb_heap
.max_freesize
= poh
->size
;
3226 ivideo
->sisfb_heap
.oh_used
.poh_next
= &ivideo
->sisfb_heap
.oh_used
;
3227 ivideo
->sisfb_heap
.oh_used
.poh_prev
= &ivideo
->sisfb_heap
.oh_used
;
3228 ivideo
->sisfb_heap
.oh_used
.size
= SENTINEL
;
3230 if(ivideo
->cardnumber
== 0) {
3231 /* For the first card, make this heap the "global" one
3232 * for old DRM (which could handle only one card)
3234 sisfb_heap
= &ivideo
->sisfb_heap
;
3240 static struct SIS_OH
*
3241 sisfb_poh_new_node(struct SIS_HEAP
*memheap
)
3243 struct SIS_OHALLOC
*poha
;
3248 if(memheap
->poh_freelist
== NULL
) {
3249 poha
= kmalloc(SIS_OH_ALLOC_SIZE
, GFP_KERNEL
);
3253 poha
->poha_next
= memheap
->poha_chain
;
3254 memheap
->poha_chain
= poha
;
3256 cOhs
= (SIS_OH_ALLOC_SIZE
- sizeof(struct SIS_OHALLOC
)) / sizeof(struct SIS_OH
) + 1;
3258 poh
= &poha
->aoh
[0];
3259 for(i
= cOhs
- 1; i
!= 0; i
--) {
3260 poh
->poh_next
= poh
+ 1;
3264 poh
->poh_next
= NULL
;
3265 memheap
->poh_freelist
= &poha
->aoh
[0];
3268 poh
= memheap
->poh_freelist
;
3269 memheap
->poh_freelist
= poh
->poh_next
;
3274 static struct SIS_OH
*
3275 sisfb_poh_allocate(struct SIS_HEAP
*memheap
, u32 size
)
3277 struct SIS_OH
*pohThis
;
3278 struct SIS_OH
*pohRoot
;
3281 if(size
> memheap
->max_freesize
) {
3282 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3283 (unsigned int) size
/ 1024);
3287 pohThis
= memheap
->oh_free
.poh_next
;
3289 while(pohThis
!= &memheap
->oh_free
) {
3290 if(size
<= pohThis
->size
) {
3294 pohThis
= pohThis
->poh_next
;
3298 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3299 (unsigned int) size
/ 1024);
3303 if(size
== pohThis
->size
) {
3305 sisfb_delete_node(pohThis
);
3307 pohRoot
= sisfb_poh_new_node(memheap
);
3311 pohRoot
->offset
= pohThis
->offset
;
3312 pohRoot
->size
= size
;
3314 pohThis
->offset
+= size
;
3315 pohThis
->size
-= size
;
3318 memheap
->max_freesize
-= size
;
3320 pohThis
= &memheap
->oh_used
;
3321 sisfb_insert_node(pohThis
, pohRoot
);
3327 sisfb_delete_node(struct SIS_OH
*poh
)
3329 poh
->poh_prev
->poh_next
= poh
->poh_next
;
3330 poh
->poh_next
->poh_prev
= poh
->poh_prev
;
3334 sisfb_insert_node(struct SIS_OH
*pohList
, struct SIS_OH
*poh
)
3336 struct SIS_OH
*pohTemp
= pohList
->poh_next
;
3338 pohList
->poh_next
= poh
;
3339 pohTemp
->poh_prev
= poh
;
3341 poh
->poh_prev
= pohList
;
3342 poh
->poh_next
= pohTemp
;
3345 static struct SIS_OH
*
3346 sisfb_poh_free(struct SIS_HEAP
*memheap
, u32 base
)
3348 struct SIS_OH
*pohThis
;
3349 struct SIS_OH
*poh_freed
;
3350 struct SIS_OH
*poh_prev
;
3351 struct SIS_OH
*poh_next
;
3356 poh_freed
= memheap
->oh_used
.poh_next
;
3358 while(poh_freed
!= &memheap
->oh_used
) {
3359 if(poh_freed
->offset
== base
) {
3364 poh_freed
= poh_freed
->poh_next
;
3370 memheap
->max_freesize
+= poh_freed
->size
;
3372 poh_prev
= poh_next
= NULL
;
3373 ulUpper
= poh_freed
->offset
+ poh_freed
->size
;
3374 ulLower
= poh_freed
->offset
;
3376 pohThis
= memheap
->oh_free
.poh_next
;
3378 while(pohThis
!= &memheap
->oh_free
) {
3379 if(pohThis
->offset
== ulUpper
) {
3381 } else if((pohThis
->offset
+ pohThis
->size
) == ulLower
) {
3384 pohThis
= pohThis
->poh_next
;
3387 sisfb_delete_node(poh_freed
);
3389 if(poh_prev
&& poh_next
) {
3390 poh_prev
->size
+= (poh_freed
->size
+ poh_next
->size
);
3391 sisfb_delete_node(poh_next
);
3392 sisfb_free_node(memheap
, poh_freed
);
3393 sisfb_free_node(memheap
, poh_next
);
3398 poh_prev
->size
+= poh_freed
->size
;
3399 sisfb_free_node(memheap
, poh_freed
);
3404 poh_next
->size
+= poh_freed
->size
;
3405 poh_next
->offset
= poh_freed
->offset
;
3406 sisfb_free_node(memheap
, poh_freed
);
3410 sisfb_insert_node(&memheap
->oh_free
, poh_freed
);
3416 sisfb_free_node(struct SIS_HEAP
*memheap
, struct SIS_OH
*poh
)
3421 poh
->poh_next
= memheap
->poh_freelist
;
3422 memheap
->poh_freelist
= poh
;
3426 sis_int_malloc(struct sis_video_info
*ivideo
, struct sis_memreq
*req
)
3428 struct SIS_OH
*poh
= NULL
;
3430 if((ivideo
) && (ivideo
->sisfb_id
== SISFB_ID
) && (!ivideo
->havenoheap
))
3431 poh
= sisfb_poh_allocate(&ivideo
->sisfb_heap
, (u32
)req
->size
);
3434 req
->offset
= req
->size
= 0;
3435 DPRINTK("sisfb: Video RAM allocation failed\n");
3437 req
->offset
= poh
->offset
;
3438 req
->size
= poh
->size
;
3439 DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3440 (poh
->offset
+ ivideo
->video_vbase
));
3445 sis_malloc(struct sis_memreq
*req
)
3447 struct sis_video_info
*ivideo
= sisfb_heap
->vinfo
;
3449 if(&ivideo
->sisfb_heap
== sisfb_heap
)
3450 sis_int_malloc(ivideo
, req
);
3452 req
->offset
= req
->size
= 0;
3456 sis_malloc_new(struct pci_dev
*pdev
, struct sis_memreq
*req
)
3458 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
3460 sis_int_malloc(ivideo
, req
);
3463 /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3466 sis_int_free(struct sis_video_info
*ivideo
, u32 base
)
3470 if((!ivideo
) || (ivideo
->sisfb_id
!= SISFB_ID
) || (ivideo
->havenoheap
))
3473 poh
= sisfb_poh_free(&ivideo
->sisfb_heap
, base
);
3476 DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
3477 (unsigned int) base
);
3484 struct sis_video_info
*ivideo
= sisfb_heap
->vinfo
;
3486 sis_int_free(ivideo
, base
);
3490 sis_free_new(struct pci_dev
*pdev
, u32 base
)
3492 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
3494 sis_int_free(ivideo
, base
);
3497 /* --------------------- SetMode routines ------------------------- */
3500 sisfb_check_engine_and_sync(struct sis_video_info
*ivideo
)
3504 /* Check if MMIO and engines are enabled,
3505 * and sync in case they are. Can't use
3506 * ivideo->accel here, as this might have
3507 * been changed before this is called.
3509 cr30
= SiS_GetReg(SISSR
, IND_SIS_PCI_ADDRESS_SET
);
3510 cr31
= SiS_GetReg(SISSR
, IND_SIS_MODULE_ENABLE
);
3511 /* MMIO and 2D/3D engine enabled? */
3512 if((cr30
& SIS_MEM_MAP_IO_ENABLE
) && (cr31
& 0x42)) {
3513 #ifdef CONFIG_FB_SIS_300
3514 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3515 /* Don't care about TurboQueue. It's
3516 * enough to know that the engines
3519 sisfb_syncaccel(ivideo
);
3522 #ifdef CONFIG_FB_SIS_315
3523 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3524 /* Check that any queue mode is
3525 * enabled, and that the queue
3526 * is not in the state of "reset"
3528 cr30
= SiS_GetReg(SISSR
, 0x26);
3529 if((cr30
& 0xe0) && (!(cr30
& 0x01))) {
3530 sisfb_syncaccel(ivideo
);
3538 sisfb_pre_setmode(struct sis_video_info
*ivideo
)
3540 u8 cr30
= 0, cr31
= 0, cr33
= 0, cr35
= 0, cr38
= 0;
3543 ivideo
->currentvbflags
&= (VB_VIDEOBRIDGE
| VB_DISPTYPE_DISP2
);
3545 SiS_SetReg(SISSR
, 0x05, 0x86);
3547 cr31
= SiS_GetReg(SISCR
, 0x31);
3551 cr33
= ivideo
->rate_idx
& 0x0F;
3553 #ifdef CONFIG_FB_SIS_315
3554 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3555 if(ivideo
->chip
>= SIS_661
) {
3556 cr38
= SiS_GetReg(SISCR
, 0x38);
3557 cr38
&= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
3560 cr38
= SiS_GetReg(SISCR
, tvregnum
);
3561 cr38
&= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
3565 #ifdef CONFIG_FB_SIS_300
3566 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3568 cr38
= SiS_GetReg(SISCR
, tvregnum
);
3572 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
3573 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
3574 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
3576 switch(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
3579 cr38
&= ~0xc0; /* Clear PAL-M / PAL-N bits */
3580 if((ivideo
->vbflags
& TV_YPBPR
) && (ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) {
3581 #ifdef CONFIG_FB_SIS_315
3582 if(ivideo
->chip
>= SIS_661
) {
3584 if(ivideo
->vbflags
& TV_YPBPR525P
) cr35
|= 0x20;
3585 else if(ivideo
->vbflags
& TV_YPBPR750P
) cr35
|= 0x40;
3586 else if(ivideo
->vbflags
& TV_YPBPR1080I
) cr35
|= 0x60;
3587 cr30
|= SIS_SIMULTANEOUS_VIEW_ENABLE
;
3589 ivideo
->currentvbflags
|= (TV_YPBPR
| (ivideo
->vbflags
& TV_YPBPRALL
));
3590 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3591 cr30
|= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE
);
3593 if(ivideo
->vbflags
& TV_YPBPR525P
) cr38
|= 0x10;
3594 else if(ivideo
->vbflags
& TV_YPBPR750P
) cr38
|= 0x20;
3595 else if(ivideo
->vbflags
& TV_YPBPR1080I
) cr38
|= 0x30;
3597 ivideo
->currentvbflags
|= (TV_YPBPR
| (ivideo
->vbflags
& TV_YPBPRALL
));
3600 } else if((ivideo
->vbflags
& TV_HIVISION
) &&
3601 (ivideo
->vbflags2
& VB2_SISHIVISIONBRIDGE
)) {
3602 if(ivideo
->chip
>= SIS_661
) {
3608 cr30
|= SIS_SIMULTANEOUS_VIEW_ENABLE
;
3611 ivideo
->currentvbflags
|= TV_HIVISION
;
3612 } else if(ivideo
->vbflags
& TV_SCART
) {
3613 cr30
= (SIS_VB_OUTPUT_SCART
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3616 ivideo
->currentvbflags
|= TV_SCART
;
3618 if(ivideo
->vbflags
& TV_SVIDEO
) {
3619 cr30
= (SIS_VB_OUTPUT_SVIDEO
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3620 ivideo
->currentvbflags
|= TV_SVIDEO
;
3622 if(ivideo
->vbflags
& TV_AVIDEO
) {
3623 cr30
= (SIS_VB_OUTPUT_COMPOSITE
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3624 ivideo
->currentvbflags
|= TV_AVIDEO
;
3627 cr31
|= SIS_DRIVER_MODE
;
3629 if(ivideo
->vbflags
& (TV_AVIDEO
| TV_SVIDEO
)) {
3630 if(ivideo
->vbflags
& TV_PAL
) {
3631 cr31
|= 0x01; cr35
|= 0x01;
3632 ivideo
->currentvbflags
|= TV_PAL
;
3633 if(ivideo
->vbflags
& TV_PALM
) {
3634 cr38
|= 0x40; cr35
|= 0x04;
3635 ivideo
->currentvbflags
|= TV_PALM
;
3636 } else if(ivideo
->vbflags
& TV_PALN
) {
3637 cr38
|= 0x80; cr35
|= 0x08;
3638 ivideo
->currentvbflags
|= TV_PALN
;
3641 cr31
&= ~0x01; cr35
&= ~0x01;
3642 ivideo
->currentvbflags
|= TV_NTSC
;
3643 if(ivideo
->vbflags
& TV_NTSCJ
) {
3644 cr38
|= 0x40; cr35
|= 0x02;
3645 ivideo
->currentvbflags
|= TV_NTSCJ
;
3652 cr30
= (SIS_VB_OUTPUT_LCD
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3653 cr31
|= SIS_DRIVER_MODE
;
3654 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, ivideo
->sisfb_dstn
);
3655 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, ivideo
->sisfb_fstn
);
3656 ivideo
->curFSTN
= ivideo
->sisfb_fstn
;
3657 ivideo
->curDSTN
= ivideo
->sisfb_dstn
;
3661 cr30
= (SIS_VB_OUTPUT_CRT2
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3662 cr31
|= SIS_DRIVER_MODE
;
3663 if(ivideo
->sisfb_nocrt2rate
) {
3664 cr33
|= (sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
<< 4);
3666 cr33
|= ((ivideo
->rate_idx
& 0x0F) << 4);
3670 default: /* disable CRT2 */
3672 cr31
|= (SIS_DRIVER_MODE
| SIS_VB_OUTPUT_DISABLE
);
3675 SiS_SetReg(SISCR
, 0x30, cr30
);
3676 SiS_SetReg(SISCR
, 0x33, cr33
);
3678 if(ivideo
->chip
>= SIS_661
) {
3679 #ifdef CONFIG_FB_SIS_315
3680 cr31
&= ~0x01; /* Clear PAL flag (now in CR35) */
3681 SiS_SetRegANDOR(SISCR
, 0x35, ~0x10, cr35
); /* Leave overscan bit alone */
3682 cr38
&= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
3683 SiS_SetRegANDOR(SISCR
, 0x38, 0xf8, cr38
);
3685 } else if(ivideo
->chip
!= SIS_300
) {
3686 SiS_SetReg(SISCR
, tvregnum
, cr38
);
3688 SiS_SetReg(SISCR
, 0x31, cr31
);
3690 ivideo
->SiS_Pr
.SiS_UseOEM
= ivideo
->sisfb_useoem
;
3692 sisfb_check_engine_and_sync(ivideo
);
3695 /* Fix SR11 for 661 and later */
3696 #ifdef CONFIG_FB_SIS_315
3698 sisfb_fixup_SR11(struct sis_video_info
*ivideo
)
3702 if(ivideo
->chip
>= SIS_661
) {
3703 tmpreg
= SiS_GetReg(SISSR
, 0x11);
3705 tmpreg
= SiS_GetReg(SISSR
, 0x3e);
3706 tmpreg
= (tmpreg
+ 1) & 0xff;
3707 SiS_SetReg(SISSR
, 0x3e, tmpreg
);
3708 tmpreg
= SiS_GetReg(SISSR
, 0x11);
3711 SiS_SetRegAND(SISSR
, 0x11, 0x0f);
3718 sisfb_set_TVxposoffset(struct sis_video_info
*ivideo
, int val
)
3720 if(val
> 32) val
= 32;
3721 if(val
< -32) val
= -32;
3722 ivideo
->tvxpos
= val
;
3724 if(ivideo
->sisfblocked
) return;
3725 if(!ivideo
->modechanged
) return;
3727 if(ivideo
->currentvbflags
& CRT2_TV
) {
3729 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3731 int x
= ivideo
->tvx
;
3733 switch(ivideo
->chronteltype
) {
3737 SiS_SetReg(SISSR
, 0x05, 0x86);
3738 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0a, (x
& 0xff));
3739 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x08, ((x
& 0x0100) >> 7), 0xFD);
3742 /* Not supported by hardware */
3746 } else if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3748 u8 p2_1f
,p2_20
,p2_2b
,p2_42
,p2_43
;
3749 unsigned short temp
;
3751 p2_1f
= ivideo
->p2_1f
;
3752 p2_20
= ivideo
->p2_20
;
3753 p2_2b
= ivideo
->p2_2b
;
3754 p2_42
= ivideo
->p2_42
;
3755 p2_43
= ivideo
->p2_43
;
3757 temp
= p2_1f
| ((p2_20
& 0xf0) << 4);
3759 p2_1f
= temp
& 0xff;
3760 p2_20
= (temp
& 0xf00) >> 4;
3761 p2_2b
= ((p2_2b
& 0x0f) + (val
* 2)) & 0x0f;
3762 temp
= p2_43
| ((p2_42
& 0xf0) << 4);
3764 p2_43
= temp
& 0xff;
3765 p2_42
= (temp
& 0xf00) >> 4;
3766 SiS_SetReg(SISPART2
, 0x1f, p2_1f
);
3767 SiS_SetRegANDOR(SISPART2
, 0x20, 0x0F, p2_20
);
3768 SiS_SetRegANDOR(SISPART2
, 0x2b, 0xF0, p2_2b
);
3769 SiS_SetRegANDOR(SISPART2
, 0x42, 0x0F, p2_42
);
3770 SiS_SetReg(SISPART2
, 0x43, p2_43
);
3776 sisfb_set_TVyposoffset(struct sis_video_info
*ivideo
, int val
)
3778 if(val
> 32) val
= 32;
3779 if(val
< -32) val
= -32;
3780 ivideo
->tvypos
= val
;
3782 if(ivideo
->sisfblocked
) return;
3783 if(!ivideo
->modechanged
) return;
3785 if(ivideo
->currentvbflags
& CRT2_TV
) {
3787 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3789 int y
= ivideo
->tvy
;
3791 switch(ivideo
->chronteltype
) {
3795 SiS_SetReg(SISSR
, 0x05, 0x86);
3796 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0b, (y
& 0xff));
3797 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x08, ((y
& 0x0100) >> 8), 0xFE);
3800 /* Not supported by hardware */
3804 } else if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3808 p2_01
= ivideo
->p2_01
;
3809 p2_02
= ivideo
->p2_02
;
3813 if(!(ivideo
->currentvbflags
& (TV_HIVISION
| TV_YPBPR
))) {
3814 while((p2_01
<= 0) || (p2_02
<= 0)) {
3819 SiS_SetReg(SISPART2
, 0x01, p2_01
);
3820 SiS_SetReg(SISPART2
, 0x02, p2_02
);
3826 sisfb_post_setmode(struct sis_video_info
*ivideo
)
3828 bool crt1isoff
= false;
3830 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
3833 #ifdef CONFIG_FB_SIS_315
3837 SiS_SetReg(SISSR
, 0x05, 0x86);
3839 #ifdef CONFIG_FB_SIS_315
3840 sisfb_fixup_SR11(ivideo
);
3843 /* Now we actually HAVE changed the display mode */
3844 ivideo
->modechanged
= 1;
3846 /* We can't switch off CRT1 if bridge is in slave mode */
3847 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
3848 if(sisfb_bridgeisslave(ivideo
)) doit
= false;
3850 ivideo
->sisfb_crt1off
= 0;
3852 #ifdef CONFIG_FB_SIS_300
3853 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3854 if((ivideo
->sisfb_crt1off
) && (doit
)) {
3861 SiS_SetRegANDOR(SISCR
, 0x17, 0x7f, reg
);
3864 #ifdef CONFIG_FB_SIS_315
3865 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3866 if((ivideo
->sisfb_crt1off
) && (doit
)) {
3875 SiS_SetRegANDOR(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, ~0x40, reg
);
3876 SiS_SetRegANDOR(SISSR
, 0x1f, 0x3f, reg1
);
3881 ivideo
->currentvbflags
&= ~VB_DISPTYPE_CRT1
;
3882 ivideo
->currentvbflags
|= VB_SINGLE_MODE
;
3884 ivideo
->currentvbflags
|= VB_DISPTYPE_CRT1
;
3885 if(ivideo
->currentvbflags
& VB_DISPTYPE_CRT2
) {
3886 ivideo
->currentvbflags
|= VB_MIRROR_MODE
;
3888 ivideo
->currentvbflags
|= VB_SINGLE_MODE
;
3892 SiS_SetRegAND(SISSR
, IND_SIS_RAMDAC_CONTROL
, ~0x04);
3894 if(ivideo
->currentvbflags
& CRT2_TV
) {
3895 if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3896 ivideo
->p2_1f
= SiS_GetReg(SISPART2
, 0x1f);
3897 ivideo
->p2_20
= SiS_GetReg(SISPART2
, 0x20);
3898 ivideo
->p2_2b
= SiS_GetReg(SISPART2
, 0x2b);
3899 ivideo
->p2_42
= SiS_GetReg(SISPART2
, 0x42);
3900 ivideo
->p2_43
= SiS_GetReg(SISPART2
, 0x43);
3901 ivideo
->p2_01
= SiS_GetReg(SISPART2
, 0x01);
3902 ivideo
->p2_02
= SiS_GetReg(SISPART2
, 0x02);
3903 } else if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3904 if(ivideo
->chronteltype
== 1) {
3905 ivideo
->tvx
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0a);
3906 ivideo
->tvx
|= (((SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x08) & 0x02) >> 1) << 8);
3907 ivideo
->tvy
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0b);
3908 ivideo
->tvy
|= ((SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x08) & 0x01) << 8);
3913 if(ivideo
->tvxpos
) {
3914 sisfb_set_TVxposoffset(ivideo
, ivideo
->tvxpos
);
3916 if(ivideo
->tvypos
) {
3917 sisfb_set_TVyposoffset(ivideo
, ivideo
->tvypos
);
3920 /* Eventually sync engines */
3921 sisfb_check_engine_and_sync(ivideo
);
3923 /* (Re-)Initialize chip engines */
3925 sisfb_engine_init(ivideo
);
3927 ivideo
->engineok
= 0;
3932 sisfb_reset_mode(struct sis_video_info
*ivideo
)
3934 if(sisfb_set_mode(ivideo
, 0))
3937 sisfb_set_pitch(ivideo
);
3938 sisfb_set_base_CRT1(ivideo
, ivideo
->current_base
);
3939 sisfb_set_base_CRT2(ivideo
, ivideo
->current_base
);
3945 sisfb_handle_command(struct sis_video_info
*ivideo
, struct sisfb_cmd
*sisfb_command
)
3949 switch(sisfb_command
->sisfb_cmd
) {
3950 case SISFB_CMD_GETVBFLAGS
:
3951 if(!ivideo
->modechanged
) {
3952 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_EARLY
;
3954 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3955 sisfb_command
->sisfb_result
[1] = ivideo
->currentvbflags
;
3956 sisfb_command
->sisfb_result
[2] = ivideo
->vbflags2
;
3959 case SISFB_CMD_SWITCHCRT1
:
3960 /* arg[0]: 0 = off, 1 = on, 99 = query */
3961 if(!ivideo
->modechanged
) {
3962 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_EARLY
;
3963 } else if(sisfb_command
->sisfb_arg
[0] == 99) {
3965 sisfb_command
->sisfb_result
[1] = ivideo
->sisfb_crt1off
? 0 : 1;
3966 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3967 } else if(ivideo
->sisfblocked
) {
3968 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_LOCKED
;
3969 } else if((!(ivideo
->currentvbflags
& CRT2_ENABLE
)) &&
3970 (sisfb_command
->sisfb_arg
[0] == 0)) {
3971 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_NOCRT2
;
3973 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3974 mycrt1off
= sisfb_command
->sisfb_arg
[0] ? 0 : 1;
3975 if( ((ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
) && mycrt1off
) ||
3976 ((!(ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
)) && !mycrt1off
) ) {
3977 ivideo
->sisfb_crt1off
= mycrt1off
;
3978 if(sisfb_reset_mode(ivideo
)) {
3979 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OTHER
;
3982 sisfb_command
->sisfb_result
[1] = ivideo
->sisfb_crt1off
? 0 : 1;
3987 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_UNKNOWN
;
3988 printk(KERN_ERR
"sisfb: Unknown command 0x%x\n",
3989 sisfb_command
->sisfb_cmd
);
3994 static int __init
sisfb_setup(char *options
)
3998 sisfb_setdefaultparms();
4000 if(!options
|| !(*options
))
4003 while((this_opt
= strsep(&options
, ",")) != NULL
) {
4005 if(!(*this_opt
)) continue;
4007 if(!strncasecmp(this_opt
, "off", 3)) {
4009 } else if(!strncasecmp(this_opt
, "forcecrt2type:", 14)) {
4010 /* Need to check crt2 type first for fstn/dstn */
4011 sisfb_search_crt2type(this_opt
+ 14);
4012 } else if(!strncasecmp(this_opt
, "tvmode:",7)) {
4013 sisfb_search_tvstd(this_opt
+ 7);
4014 } else if(!strncasecmp(this_opt
, "tvstandard:",11)) {
4015 sisfb_search_tvstd(this_opt
+ 11);
4016 } else if(!strncasecmp(this_opt
, "mode:", 5)) {
4017 sisfb_search_mode(this_opt
+ 5, false);
4018 } else if(!strncasecmp(this_opt
, "vesa:", 5)) {
4019 sisfb_search_vesamode(simple_strtoul(this_opt
+ 5, NULL
, 0), false);
4020 } else if(!strncasecmp(this_opt
, "rate:", 5)) {
4021 sisfb_parm_rate
= simple_strtoul(this_opt
+ 5, NULL
, 0);
4022 } else if(!strncasecmp(this_opt
, "forcecrt1:", 10)) {
4023 sisfb_forcecrt1
= (int)simple_strtoul(this_opt
+ 10, NULL
, 0);
4024 } else if(!strncasecmp(this_opt
, "mem:",4)) {
4025 sisfb_parm_mem
= simple_strtoul(this_opt
+ 4, NULL
, 0);
4026 } else if(!strncasecmp(this_opt
, "pdc:", 4)) {
4027 sisfb_pdc
= simple_strtoul(this_opt
+ 4, NULL
, 0);
4028 } else if(!strncasecmp(this_opt
, "pdc1:", 5)) {
4029 sisfb_pdca
= simple_strtoul(this_opt
+ 5, NULL
, 0);
4030 } else if(!strncasecmp(this_opt
, "noaccel", 7)) {
4032 } else if(!strncasecmp(this_opt
, "accel", 5)) {
4034 } else if(!strncasecmp(this_opt
, "noypan", 6)) {
4036 } else if(!strncasecmp(this_opt
, "ypan", 4)) {
4038 } else if(!strncasecmp(this_opt
, "nomax", 5)) {
4040 } else if(!strncasecmp(this_opt
, "max", 3)) {
4042 } else if(!strncasecmp(this_opt
, "userom:", 7)) {
4043 sisfb_userom
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
4044 } else if(!strncasecmp(this_opt
, "useoem:", 7)) {
4045 sisfb_useoem
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
4046 } else if(!strncasecmp(this_opt
, "nocrt2rate", 10)) {
4047 sisfb_nocrt2rate
= 1;
4048 } else if(!strncasecmp(this_opt
, "scalelcd:", 9)) {
4049 unsigned long temp
= 2;
4050 temp
= simple_strtoul(this_opt
+ 9, NULL
, 0);
4051 if((temp
== 0) || (temp
== 1)) {
4052 sisfb_scalelcd
= temp
^ 1;
4054 } else if(!strncasecmp(this_opt
, "tvxposoffset:", 13)) {
4056 temp
= (int)simple_strtol(this_opt
+ 13, NULL
, 0);
4057 if((temp
>= -32) && (temp
<= 32)) {
4058 sisfb_tvxposoffset
= temp
;
4060 } else if(!strncasecmp(this_opt
, "tvyposoffset:", 13)) {
4062 temp
= (int)simple_strtol(this_opt
+ 13, NULL
, 0);
4063 if((temp
>= -32) && (temp
<= 32)) {
4064 sisfb_tvyposoffset
= temp
;
4066 } else if(!strncasecmp(this_opt
, "specialtiming:", 14)) {
4067 sisfb_search_specialtiming(this_opt
+ 14);
4068 } else if(!strncasecmp(this_opt
, "lvdshl:", 7)) {
4070 temp
= simple_strtoul(this_opt
+ 7, NULL
, 0);
4071 if((temp
>= 0) && (temp
<= 3)) {
4072 sisfb_lvdshl
= temp
;
4074 } else if(this_opt
[0] >= '0' && this_opt
[0] <= '9') {
4075 sisfb_search_mode(this_opt
, true);
4076 #if !defined(__i386__) && !defined(__x86_64__)
4077 } else if(!strncasecmp(this_opt
, "resetcard", 9)) {
4078 sisfb_resetcard
= 1;
4079 } else if(!strncasecmp(this_opt
, "videoram:", 9)) {
4080 sisfb_videoram
= simple_strtoul(this_opt
+ 9, NULL
, 0);
4083 printk(KERN_INFO
"sisfb: Invalid option %s\n", this_opt
);
4092 static int sisfb_check_rom(void __iomem
*rom_base
,
4093 struct sis_video_info
*ivideo
)
4098 if((readb(rom_base
) != 0x55) || (readb(rom_base
+ 1) != 0xaa))
4101 romptr
= (readb(rom_base
+ 0x18) | (readb(rom_base
+ 0x19) << 8));
4102 if(romptr
> (0x10000 - 8))
4105 rom
= rom_base
+ romptr
;
4107 if((readb(rom
) != 'P') || (readb(rom
+ 1) != 'C') ||
4108 (readb(rom
+ 2) != 'I') || (readb(rom
+ 3) != 'R'))
4111 if((readb(rom
+ 4) | (readb(rom
+ 5) << 8)) != ivideo
->chip_vendor
)
4114 if((readb(rom
+ 6) | (readb(rom
+ 7) << 8)) != ivideo
->chip_id
)
4120 static unsigned char *sisfb_find_rom(struct pci_dev
*pdev
)
4122 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4123 void __iomem
*rom_base
;
4124 unsigned char *myrombase
= NULL
;
4127 /* First, try the official pci ROM functions (except
4128 * on integrated chipsets which have no ROM).
4131 if(!ivideo
->nbridge
) {
4133 if((rom_base
= pci_map_rom(pdev
, &romsize
))) {
4135 if(sisfb_check_rom(rom_base
, ivideo
)) {
4137 if((myrombase
= vmalloc(65536))) {
4138 memcpy_fromio(myrombase
, rom_base
,
4139 (romsize
> 65536) ? 65536 : romsize
);
4142 pci_unmap_rom(pdev
, rom_base
);
4146 if(myrombase
) return myrombase
;
4148 /* Otherwise do it the conventional way. */
4150 #if defined(__i386__) || defined(__x86_64__)
4154 for (temp
= 0x000c0000; temp
< 0x000f0000; temp
+= 0x00001000) {
4156 rom_base
= ioremap(temp
, 65536);
4160 if (!sisfb_check_rom(rom_base
, ivideo
)) {
4165 if ((myrombase
= vmalloc(65536)))
4166 memcpy_fromio(myrombase
, rom_base
, 65536);
4179 static void sisfb_post_map_vram(struct sis_video_info
*ivideo
,
4180 unsigned int *mapsize
, unsigned int min
)
4182 if (*mapsize
< (min
<< 20))
4185 ivideo
->video_vbase
= ioremap_wc(ivideo
->video_base
, (*mapsize
));
4187 if(!ivideo
->video_vbase
) {
4189 "sisfb: Unable to map maximum video RAM for size detection\n");
4191 while((!(ivideo
->video_vbase
= ioremap_wc(ivideo
->video_base
, (*mapsize
))))) {
4193 if((*mapsize
) < (min
<< 20))
4196 if(ivideo
->video_vbase
) {
4198 "sisfb: Video RAM size detection limited to %dMB\n",
4199 (int)((*mapsize
) >> 20));
4204 #ifdef CONFIG_FB_SIS_300
4205 static int sisfb_post_300_buswidth(struct sis_video_info
*ivideo
)
4207 void __iomem
*FBAddress
= ivideo
->video_vbase
;
4208 unsigned short temp
;
4212 SiS_SetRegAND(SISSR
, 0x15, 0xFB);
4213 SiS_SetRegOR(SISSR
, 0x15, 0x04);
4214 SiS_SetReg(SISSR
, 0x13, 0x00);
4215 SiS_SetReg(SISSR
, 0x14, 0xBF);
4217 for(i
= 0; i
< 2; i
++) {
4219 for(j
= 0; j
< 4; j
++) {
4220 writew(temp
, FBAddress
);
4221 if(readw(FBAddress
) == temp
)
4223 SiS_SetRegOR(SISSR
, 0x3c, 0x01);
4224 reg
= SiS_GetReg(SISSR
, 0x05);
4225 reg
= SiS_GetReg(SISSR
, 0x05);
4226 SiS_SetRegAND(SISSR
, 0x3c, 0xfe);
4227 reg
= SiS_GetReg(SISSR
, 0x05);
4228 reg
= SiS_GetReg(SISSR
, 0x05);
4233 writel(0x01234567L
, FBAddress
);
4234 writel(0x456789ABL
, (FBAddress
+ 4));
4235 writel(0x89ABCDEFL
, (FBAddress
+ 8));
4236 writel(0xCDEF0123L
, (FBAddress
+ 12));
4238 reg
= SiS_GetReg(SISSR
, 0x3b);
4240 if(readl((FBAddress
+ 12)) == 0xCDEF0123L
)
4241 return 4; /* Channel A 128bit */
4244 if(readl((FBAddress
+ 4)) == 0x456789ABL
)
4245 return 2; /* Channel B 64bit */
4247 return 1; /* 32bit */
4250 static const unsigned short SiS_DRAMType
[17][5] = {
4251 {0x0C,0x0A,0x02,0x40,0x39},
4252 {0x0D,0x0A,0x01,0x40,0x48},
4253 {0x0C,0x09,0x02,0x20,0x35},
4254 {0x0D,0x09,0x01,0x20,0x44},
4255 {0x0C,0x08,0x02,0x10,0x31},
4256 {0x0D,0x08,0x01,0x10,0x40},
4257 {0x0C,0x0A,0x01,0x20,0x34},
4258 {0x0C,0x09,0x01,0x08,0x32},
4259 {0x0B,0x08,0x02,0x08,0x21},
4260 {0x0C,0x08,0x01,0x08,0x30},
4261 {0x0A,0x08,0x02,0x04,0x11},
4262 {0x0B,0x0A,0x01,0x10,0x28},
4263 {0x09,0x08,0x02,0x02,0x01},
4264 {0x0B,0x09,0x01,0x08,0x24},
4265 {0x0B,0x08,0x01,0x04,0x20},
4266 {0x0A,0x08,0x01,0x02,0x10},
4267 {0x09,0x08,0x01,0x01,0x00}
4270 static int sisfb_post_300_rwtest(struct sis_video_info
*ivideo
, int iteration
,
4271 int buswidth
, int PseudoRankCapacity
,
4272 int PseudoAdrPinCount
, unsigned int mapsize
)
4274 void __iomem
*FBAddr
= ivideo
->video_vbase
;
4275 unsigned short sr14
;
4276 unsigned int k
, RankCapacity
, PageCapacity
, BankNumHigh
, BankNumMid
;
4277 unsigned int PhysicalAdrOtherPage
, PhysicalAdrHigh
, PhysicalAdrHalfPage
;
4279 for(k
= 0; k
< ARRAY_SIZE(SiS_DRAMType
); k
++) {
4281 RankCapacity
= buswidth
* SiS_DRAMType
[k
][3];
4283 if(RankCapacity
!= PseudoRankCapacity
)
4286 if((SiS_DRAMType
[k
][2] + SiS_DRAMType
[k
][0]) > PseudoAdrPinCount
)
4289 BankNumHigh
= RankCapacity
* 16 * iteration
- 1;
4290 if(iteration
== 3) { /* Rank No */
4291 BankNumMid
= RankCapacity
* 16 - 1;
4293 BankNumMid
= RankCapacity
* 16 * iteration
/ 2 - 1;
4296 PageCapacity
= (1 << SiS_DRAMType
[k
][1]) * buswidth
* 4;
4297 PhysicalAdrHigh
= BankNumHigh
;
4298 PhysicalAdrHalfPage
= (PageCapacity
/ 2 + PhysicalAdrHigh
) % PageCapacity
;
4299 PhysicalAdrOtherPage
= PageCapacity
* SiS_DRAMType
[k
][2] + PhysicalAdrHigh
;
4301 SiS_SetRegAND(SISSR
, 0x15, 0xFB); /* Test */
4302 SiS_SetRegOR(SISSR
, 0x15, 0x04); /* Test */
4303 sr14
= (SiS_DRAMType
[k
][3] * buswidth
) - 1;
4304 if(buswidth
== 4) sr14
|= 0x80;
4305 else if(buswidth
== 2) sr14
|= 0x40;
4306 SiS_SetReg(SISSR
, 0x13, SiS_DRAMType
[k
][4]);
4307 SiS_SetReg(SISSR
, 0x14, sr14
);
4312 if((BankNumHigh
+ PhysicalAdrHigh
>= mapsize
) ||
4313 (BankNumMid
+ PhysicalAdrHigh
>= mapsize
) ||
4314 (BankNumHigh
+ PhysicalAdrHalfPage
>= mapsize
) ||
4315 (BankNumHigh
+ PhysicalAdrOtherPage
>= mapsize
))
4319 writew(((unsigned short)PhysicalAdrHigh
),
4320 (FBAddr
+ BankNumHigh
+ PhysicalAdrHigh
));
4321 writew(((unsigned short)BankNumMid
),
4322 (FBAddr
+ BankNumMid
+ PhysicalAdrHigh
));
4323 writew(((unsigned short)PhysicalAdrHalfPage
),
4324 (FBAddr
+ BankNumHigh
+ PhysicalAdrHalfPage
));
4325 writew(((unsigned short)PhysicalAdrOtherPage
),
4326 (FBAddr
+ BankNumHigh
+ PhysicalAdrOtherPage
));
4329 if(readw(FBAddr
+ BankNumHigh
+ PhysicalAdrHigh
) == PhysicalAdrHigh
)
4336 static void sisfb_post_300_ramsize(struct pci_dev
*pdev
, unsigned int mapsize
)
4338 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4340 int PseudoRankCapacity
, PseudoAdrPinCount
;
4342 buswidth
= sisfb_post_300_buswidth(ivideo
);
4344 for(i
= 6; i
>= 0; i
--) {
4345 PseudoRankCapacity
= 1 << i
;
4346 for(j
= 4; j
>= 1; j
--) {
4347 PseudoAdrPinCount
= 15 - j
;
4348 if((PseudoRankCapacity
* j
) <= 64) {
4349 if(sisfb_post_300_rwtest(ivideo
,
4361 static void sisfb_post_sis300(struct pci_dev
*pdev
)
4363 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4364 unsigned char *bios
= ivideo
->SiS_Pr
.VirtualRomBase
;
4365 u8 reg
, v1
, v2
, v3
, v4
, v5
, v6
, v7
, v8
;
4366 u16 index
, rindex
, memtype
= 0;
4367 unsigned int mapsize
;
4369 if(!ivideo
->SiS_Pr
.UseROM
)
4372 SiS_SetReg(SISSR
, 0x05, 0x86);
4375 if(bios
[0x52] & 0x80) {
4376 memtype
= bios
[0x52];
4378 memtype
= SiS_GetReg(SISSR
, 0x3a);
4383 v3
= 0x80; v6
= 0x80;
4384 if(ivideo
->revision_id
<= 0x13) {
4385 v1
= 0x44; v2
= 0x42;
4386 v4
= 0x44; v5
= 0x42;
4388 v1
= 0x68; v2
= 0x43; /* Assume 125Mhz MCLK */
4389 v4
= 0x68; v5
= 0x43; /* Assume 125Mhz ECLK */
4391 index
= memtype
* 5;
4392 rindex
= index
+ 0x54;
4393 v1
= bios
[rindex
++];
4394 v2
= bios
[rindex
++];
4395 v3
= bios
[rindex
++];
4396 rindex
= index
+ 0x7c;
4397 v4
= bios
[rindex
++];
4398 v5
= bios
[rindex
++];
4399 v6
= bios
[rindex
++];
4402 SiS_SetReg(SISSR
, 0x28, v1
);
4403 SiS_SetReg(SISSR
, 0x29, v2
);
4404 SiS_SetReg(SISSR
, 0x2a, v3
);
4405 SiS_SetReg(SISSR
, 0x2e, v4
);
4406 SiS_SetReg(SISSR
, 0x2f, v5
);
4407 SiS_SetReg(SISSR
, 0x30, v6
);
4412 SiS_SetReg(SISSR
, 0x07, v1
); /* DAC speed */
4414 SiS_SetReg(SISSR
, 0x11, 0x0f); /* DDC, power save */
4416 v1
= 0x01; v2
= 0x43; v3
= 0x1e; v4
= 0x2a;
4417 v5
= 0x06; v6
= 0x00; v7
= 0x00; v8
= 0x00;
4421 v2
= bios
[memtype
+ 8];
4422 v3
= bios
[memtype
+ 16];
4423 v4
= bios
[memtype
+ 24];
4424 v5
= bios
[memtype
+ 32];
4425 v6
= bios
[memtype
+ 40];
4426 v7
= bios
[memtype
+ 48];
4427 v8
= bios
[memtype
+ 56];
4429 if(ivideo
->revision_id
>= 0x80)
4431 SiS_SetReg(SISSR
, 0x15, v1
); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4432 SiS_SetReg(SISSR
, 0x16, v2
);
4433 SiS_SetReg(SISSR
, 0x17, v3
);
4434 SiS_SetReg(SISSR
, 0x18, v4
);
4435 SiS_SetReg(SISSR
, 0x19, v5
);
4436 SiS_SetReg(SISSR
, 0x1a, v6
);
4437 SiS_SetReg(SISSR
, 0x1b, v7
);
4438 SiS_SetReg(SISSR
, 0x1c, v8
); /* ---- */
4439 SiS_SetRegAND(SISSR
, 0x15, 0xfb);
4440 SiS_SetRegOR(SISSR
, 0x15, 0x04);
4442 if(bios
[0x53] & 0x02) {
4443 SiS_SetRegOR(SISSR
, 0x19, 0x20);
4446 v1
= 0x04; /* DAC pedestal (BIOS 0xe5) */
4447 if(ivideo
->revision_id
>= 0x80)
4449 SiS_SetReg(SISSR
, 0x1f, v1
);
4450 SiS_SetReg(SISSR
, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
4451 v1
= 0xf6; v2
= 0x0d; v3
= 0x00;
4457 SiS_SetReg(SISSR
, 0x23, v1
);
4458 SiS_SetReg(SISSR
, 0x24, v2
);
4459 SiS_SetReg(SISSR
, 0x25, v3
);
4460 SiS_SetReg(SISSR
, 0x21, 0x84);
4461 SiS_SetReg(SISSR
, 0x22, 0x00);
4462 SiS_SetReg(SISCR
, 0x37, 0x00);
4463 SiS_SetRegOR(SISPART1
, 0x24, 0x01); /* unlock crt2 */
4464 SiS_SetReg(SISPART1
, 0x00, 0x00);
4465 v1
= 0x40; v2
= 0x11;
4470 SiS_SetReg(SISPART1
, 0x02, v1
);
4472 if(ivideo
->revision_id
>= 0x80)
4475 reg
= SiS_GetReg(SISPART4
, 0x00);
4476 if((reg
== 1) || (reg
== 2)) {
4477 SiS_SetReg(SISCR
, 0x37, 0x02);
4478 SiS_SetReg(SISPART2
, 0x00, 0x1c);
4479 v4
= 0x00; v5
= 0x00; v6
= 0x10;
4480 if(ivideo
->SiS_Pr
.UseROM
) {
4485 SiS_SetReg(SISPART4
, 0x0d, v4
);
4486 SiS_SetReg(SISPART4
, 0x0e, v5
);
4487 SiS_SetReg(SISPART4
, 0x10, v6
);
4488 SiS_SetReg(SISPART4
, 0x0f, 0x3f);
4489 reg
= SiS_GetReg(SISPART4
, 0x01);
4491 reg
= SiS_GetReg(SISPART4
, 0x23);
4494 SiS_SetReg(SISPART4
, 0x23, reg
);
4499 SiS_SetReg(SISSR
, 0x32, v2
);
4501 SiS_SetRegAND(SISPART1
, 0x24, 0xfe); /* Lock CRT2 */
4503 reg
= SiS_GetReg(SISSR
, 0x16);
4505 SiS_SetReg(SISCR
, 0x35, reg
);
4506 SiS_SetReg(SISCR
, 0x83, 0x00);
4507 #if !defined(__i386__) && !defined(__x86_64__)
4508 if(sisfb_videoram
) {
4509 SiS_SetReg(SISSR
, 0x13, 0x28); /* ? */
4510 reg
= ((sisfb_videoram
>> 10) - 1) | 0x40;
4511 SiS_SetReg(SISSR
, 0x14, reg
);
4514 /* Need to map max FB size for finding out about RAM size */
4515 mapsize
= ivideo
->video_size
;
4516 sisfb_post_map_vram(ivideo
, &mapsize
, 4);
4518 if(ivideo
->video_vbase
) {
4519 sisfb_post_300_ramsize(pdev
, mapsize
);
4520 iounmap(ivideo
->video_vbase
);
4523 "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4524 SiS_SetReg(SISSR
, 0x13, 0x28); /* ? */
4525 SiS_SetReg(SISSR
, 0x14, 0x47); /* 8MB, 64bit default */
4527 #if !defined(__i386__) && !defined(__x86_64__)
4534 reg
= SiS_GetReg(SISSR
, 0x3a);
4535 if((reg
& 0x30) == 0x30) {
4536 v1
= 0x04; /* PCI */
4539 v1
= 0x14; /* AGP */
4543 SiS_SetReg(SISSR
, 0x21, v1
);
4544 SiS_SetReg(SISSR
, 0x22, v2
);
4547 sisfb_sense_crt1(ivideo
);
4549 /* Set default mode, don't clear screen */
4550 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
4551 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
4552 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
4553 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
4554 ivideo
->SiS_Pr
.VideoMemorySize
= 8 << 20;
4555 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
4557 SiS_SetReg(SISSR
, 0x05, 0x86);
4560 SiS_SetRegOR(SISSR
, 0x01, 0x20);
4562 /* Save mode number in CR34 */
4563 SiS_SetReg(SISCR
, 0x34, 0x2e);
4565 /* Let everyone know what the current mode is */
4566 ivideo
->modeprechange
= 0x2e;
4570 #ifdef CONFIG_FB_SIS_315
4572 static void sisfb_post_sis315330(struct pci_dev
*pdev
)
4578 static inline int sisfb_xgi_is21(struct sis_video_info
*ivideo
)
4580 return ivideo
->chip_real_id
== XGI_21
;
4583 static void sisfb_post_xgi_delay(struct sis_video_info
*ivideo
, int delay
)
4588 for(i
= 0; i
<= (delay
* 10 * 36); i
++) {
4589 reg
= SiS_GetReg(SISSR
, 0x05);
4594 static int sisfb_find_host_bridge(struct sis_video_info
*ivideo
,
4595 struct pci_dev
*mypdev
,
4596 unsigned short pcivendor
)
4598 struct pci_dev
*pdev
= NULL
;
4599 unsigned short temp
;
4602 while((pdev
= pci_get_class(PCI_CLASS_BRIDGE_HOST
, pdev
))) {
4603 temp
= pdev
->vendor
;
4604 if(temp
== pcivendor
) {
4614 static int sisfb_post_xgi_rwtest(struct sis_video_info
*ivideo
, int starta
,
4615 unsigned int enda
, unsigned int mapsize
)
4620 writel(0, ivideo
->video_vbase
);
4622 for(i
= starta
; i
<= enda
; i
++) {
4625 writel(pos
, ivideo
->video_vbase
+ pos
);
4628 sisfb_post_xgi_delay(ivideo
, 150);
4630 if(readl(ivideo
->video_vbase
) != 0)
4633 for(i
= starta
; i
<= enda
; i
++) {
4636 if(readl(ivideo
->video_vbase
+ pos
) != pos
)
4645 static int sisfb_post_xgi_ramsize(struct sis_video_info
*ivideo
)
4647 unsigned int buswidth
, ranksize
, channelab
, mapsize
;
4648 int i
, j
, k
, l
, status
;
4650 static const u8 dramsr13
[12 * 5] = {
4651 0x02, 0x0e, 0x0b, 0x80, 0x5d,
4652 0x02, 0x0e, 0x0a, 0x40, 0x59,
4653 0x02, 0x0d, 0x0b, 0x40, 0x4d,
4654 0x02, 0x0e, 0x09, 0x20, 0x55,
4655 0x02, 0x0d, 0x0a, 0x20, 0x49,
4656 0x02, 0x0c, 0x0b, 0x20, 0x3d,
4657 0x02, 0x0e, 0x08, 0x10, 0x51,
4658 0x02, 0x0d, 0x09, 0x10, 0x45,
4659 0x02, 0x0c, 0x0a, 0x10, 0x39,
4660 0x02, 0x0d, 0x08, 0x08, 0x41,
4661 0x02, 0x0c, 0x09, 0x08, 0x35,
4662 0x02, 0x0c, 0x08, 0x04, 0x31
4664 static const u8 dramsr13_4
[4 * 5] = {
4665 0x02, 0x0d, 0x09, 0x40, 0x45,
4666 0x02, 0x0c, 0x09, 0x20, 0x35,
4667 0x02, 0x0c, 0x08, 0x10, 0x31,
4668 0x02, 0x0b, 0x08, 0x08, 0x21
4671 /* Enable linear mode, disable 0xa0000 address decoding */
4672 /* We disable a0000 address decoding, because
4673 * - if running on x86, if the card is disabled, it means
4674 * that another card is in the system. We don't want
4675 * to interphere with that primary card's textmode.
4676 * - if running on non-x86, there usually is no VGA window
4679 SiS_SetRegOR(SISSR
, 0x20, (0x80 | 0x04));
4681 /* Need to map max FB size for finding out about RAM size */
4682 mapsize
= ivideo
->video_size
;
4683 sisfb_post_map_vram(ivideo
, &mapsize
, 32);
4685 if(!ivideo
->video_vbase
) {
4686 printk(KERN_ERR
"sisfb: Unable to detect RAM size. Setting default.\n");
4687 SiS_SetReg(SISSR
, 0x13, 0x35);
4688 SiS_SetReg(SISSR
, 0x14, 0x41);
4693 /* Non-interleaving */
4694 SiS_SetReg(SISSR
, 0x15, 0x00);
4696 SiS_SetReg(SISSR
, 0x1c, 0x00);
4698 if(ivideo
->chip
== XGI_20
) {
4701 reg
= SiS_GetReg(SISCR
, 0x97);
4702 if(!(reg
& 0x01)) { /* Single 32/16 */
4704 SiS_SetReg(SISSR
, 0x13, 0xb1);
4705 SiS_SetReg(SISSR
, 0x14, 0x52);
4706 sisfb_post_xgi_delay(ivideo
, 1);
4708 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4711 SiS_SetReg(SISSR
, 0x13, 0x31);
4712 SiS_SetReg(SISSR
, 0x14, 0x42);
4713 sisfb_post_xgi_delay(ivideo
, 1);
4714 if(sisfb_post_xgi_rwtest(ivideo
, 23, 23, mapsize
))
4718 SiS_SetReg(SISSR
, 0x13, 0xb1);
4719 SiS_SetReg(SISSR
, 0x14, 0x41);
4720 sisfb_post_xgi_delay(ivideo
, 1);
4722 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4725 SiS_SetReg(SISSR
, 0x13, 0x31);
4726 } else { /* Dual 16/8 */
4728 SiS_SetReg(SISSR
, 0x13, 0xb1);
4729 SiS_SetReg(SISSR
, 0x14, 0x41);
4730 sisfb_post_xgi_delay(ivideo
, 1);
4732 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4735 SiS_SetReg(SISSR
, 0x13, 0x31);
4736 SiS_SetReg(SISSR
, 0x14, 0x31);
4737 sisfb_post_xgi_delay(ivideo
, 1);
4738 if(sisfb_post_xgi_rwtest(ivideo
, 22, 22, mapsize
))
4742 SiS_SetReg(SISSR
, 0x13, 0xb1);
4743 SiS_SetReg(SISSR
, 0x14, 0x30);
4744 sisfb_post_xgi_delay(ivideo
, 1);
4746 if(sisfb_post_xgi_rwtest(ivideo
, 21, 22, mapsize
))
4749 SiS_SetReg(SISSR
, 0x13, 0x31);
4752 } else { /* XGI_40 */
4754 reg
= SiS_GetReg(SISCR
, 0x97);
4756 reg
= SiS_GetReg(SISSR
, 0x39);
4760 if(reg
& 0x01) { /* DDRII */
4762 if(ivideo
->revision_id
== 2) {
4764 SiS_SetReg(SISSR
, 0x13, 0xa1);
4765 SiS_SetReg(SISSR
, 0x14, 0x44);
4767 sisfb_post_xgi_delay(ivideo
, 1);
4768 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4771 SiS_SetReg(SISSR
, 0x13, 0x21);
4772 SiS_SetReg(SISSR
, 0x14, 0x34);
4773 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4777 SiS_SetReg(SISSR
, 0x13, 0xa1);
4778 SiS_SetReg(SISSR
, 0x14, 0x40);
4780 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4783 SiS_SetReg(SISSR
, 0x13, 0x21);
4784 SiS_SetReg(SISSR
, 0x14, 0x30);
4787 SiS_SetReg(SISSR
, 0x13, 0xa1);
4788 SiS_SetReg(SISSR
, 0x14, 0x4c);
4790 sisfb_post_xgi_delay(ivideo
, 1);
4791 if(sisfb_post_xgi_rwtest(ivideo
, 23, 25, mapsize
))
4795 SiS_SetReg(SISSR
, 0x14, 0x48);
4796 sisfb_post_xgi_delay(ivideo
, 1);
4798 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4801 SiS_SetReg(SISSR
, 0x13, 0x21);
4802 SiS_SetReg(SISSR
, 0x14, 0x3c);
4805 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
)) {
4809 SiS_SetReg(SISSR
, 0x14, 0x38);
4813 sisfb_post_xgi_delay(ivideo
, 1);
4818 if(ivideo
->revision_id
== 2) {
4820 SiS_SetReg(SISSR
, 0x13, 0xa1);
4821 SiS_SetReg(SISSR
, 0x14, 0x52);
4822 sisfb_post_xgi_delay(ivideo
, 1);
4824 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4827 SiS_SetReg(SISSR
, 0x13, 0x21);
4828 SiS_SetReg(SISSR
, 0x14, 0x42);
4831 SiS_SetReg(SISSR
, 0x13, 0xa1);
4832 SiS_SetReg(SISSR
, 0x14, 0x5a);
4833 sisfb_post_xgi_delay(ivideo
, 1);
4835 if(sisfb_post_xgi_rwtest(ivideo
, 24, 25, mapsize
))
4838 SiS_SetReg(SISSR
, 0x13, 0x21);
4839 SiS_SetReg(SISSR
, 0x14, 0x4a);
4841 sisfb_post_xgi_delay(ivideo
, 1);
4847 SiS_SetRegANDOR(SISSR
, 0x14, 0xf0, sr14
);
4848 sisfb_post_xgi_delay(ivideo
, 1);
4850 j
= (ivideo
->chip
== XGI_20
) ? 5 : 9;
4851 k
= (ivideo
->chip
== XGI_20
) ? 12 : 4;
4854 for(i
= 0; i
< k
; i
++) {
4856 reg
= (ivideo
->chip
== XGI_20
) ?
4857 dramsr13
[(i
* 5) + 4] : dramsr13_4
[(i
* 5) + 4];
4858 SiS_SetRegANDOR(SISSR
, 0x13, 0x80, reg
);
4859 sisfb_post_xgi_delay(ivideo
, 50);
4861 ranksize
= (ivideo
->chip
== XGI_20
) ?
4862 dramsr13
[(i
* 5) + 3] : dramsr13_4
[(i
* 5) + 3];
4864 reg
= SiS_GetReg(SISSR
, 0x13);
4865 if(reg
& 0x80) ranksize
<<= 1;
4867 if(ivideo
->chip
== XGI_20
) {
4868 if(buswidth
== 16) ranksize
<<= 1;
4869 else if(buswidth
== 32) ranksize
<<= 2;
4871 if(buswidth
== 64) ranksize
<<= 1;
4877 if((ranksize
* l
) <= 256) {
4878 while((ranksize
>>= 1)) reg
+= 0x10;
4883 SiS_SetRegANDOR(SISSR
, 0x14, 0x0f, (reg
& 0xf0));
4884 sisfb_post_xgi_delay(ivideo
, 1);
4886 if (sisfb_post_xgi_rwtest(ivideo
, j
, ((reg
>> 4) + channelab
- 2 + 20), mapsize
)) {
4892 iounmap(ivideo
->video_vbase
);
4897 static void sisfb_post_xgi_setclocks(struct sis_video_info
*ivideo
, u8 regb
)
4901 static const u8 cs90
[8 * 3] = {
4911 static const u8 csb8
[8 * 3] = {
4925 v1
= cs90
[index
]; v2
= cs90
[index
+ 1]; v3
= cs90
[index
+ 2];
4926 if(ivideo
->haveXGIROM
) {
4927 v1
= ivideo
->bios_abase
[0x90 + index
];
4928 v2
= ivideo
->bios_abase
[0x90 + index
+ 1];
4929 v3
= ivideo
->bios_abase
[0x90 + index
+ 2];
4931 SiS_SetReg(SISSR
, 0x28, v1
);
4932 SiS_SetReg(SISSR
, 0x29, v2
);
4933 SiS_SetReg(SISSR
, 0x2a, v3
);
4934 sisfb_post_xgi_delay(ivideo
, 0x43);
4935 sisfb_post_xgi_delay(ivideo
, 0x43);
4936 sisfb_post_xgi_delay(ivideo
, 0x43);
4938 v1
= csb8
[index
]; v2
= csb8
[index
+ 1]; v3
= csb8
[index
+ 2];
4939 if(ivideo
->haveXGIROM
) {
4940 v1
= ivideo
->bios_abase
[0xb8 + index
];
4941 v2
= ivideo
->bios_abase
[0xb8 + index
+ 1];
4942 v3
= ivideo
->bios_abase
[0xb8 + index
+ 2];
4944 SiS_SetReg(SISSR
, 0x2e, v1
);
4945 SiS_SetReg(SISSR
, 0x2f, v2
);
4946 SiS_SetReg(SISSR
, 0x30, v3
);
4947 sisfb_post_xgi_delay(ivideo
, 0x43);
4948 sisfb_post_xgi_delay(ivideo
, 0x43);
4949 sisfb_post_xgi_delay(ivideo
, 0x43);
4952 static void sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info
*ivideo
,
4955 unsigned char *bios
= ivideo
->bios_abase
;
4958 SiS_SetReg(SISSR
, 0x28, 0x64);
4959 SiS_SetReg(SISSR
, 0x29, 0x63);
4960 sisfb_post_xgi_delay(ivideo
, 15);
4961 SiS_SetReg(SISSR
, 0x18, 0x00);
4962 SiS_SetReg(SISSR
, 0x19, 0x20);
4963 SiS_SetReg(SISSR
, 0x16, 0x00);
4964 SiS_SetReg(SISSR
, 0x16, 0x80);
4965 SiS_SetReg(SISSR
, 0x18, 0xc5);
4966 SiS_SetReg(SISSR
, 0x19, 0x23);
4967 SiS_SetReg(SISSR
, 0x16, 0x00);
4968 SiS_SetReg(SISSR
, 0x16, 0x80);
4969 sisfb_post_xgi_delay(ivideo
, 1);
4970 SiS_SetReg(SISCR
, 0x97, 0x11);
4971 sisfb_post_xgi_setclocks(ivideo
, regb
);
4972 sisfb_post_xgi_delay(ivideo
, 0x46);
4973 SiS_SetReg(SISSR
, 0x18, 0xc5);
4974 SiS_SetReg(SISSR
, 0x19, 0x23);
4975 SiS_SetReg(SISSR
, 0x16, 0x00);
4976 SiS_SetReg(SISSR
, 0x16, 0x80);
4977 sisfb_post_xgi_delay(ivideo
, 1);
4978 SiS_SetReg(SISSR
, 0x1b, 0x04);
4979 sisfb_post_xgi_delay(ivideo
, 1);
4980 SiS_SetReg(SISSR
, 0x1b, 0x00);
4981 sisfb_post_xgi_delay(ivideo
, 1);
4983 if (ivideo
->haveXGIROM
) {
4986 SiS_SetReg(SISSR
, 0x18, v1
);
4987 SiS_SetReg(SISSR
, 0x19, 0x06);
4988 SiS_SetReg(SISSR
, 0x16, 0x04);
4989 SiS_SetReg(SISSR
, 0x16, 0x84);
4990 sisfb_post_xgi_delay(ivideo
, 1);
4993 static void sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info
*ivideo
)
4995 sisfb_post_xgi_setclocks(ivideo
, 1);
4997 SiS_SetReg(SISCR
, 0x97, 0x11);
4998 sisfb_post_xgi_delay(ivideo
, 0x46);
5000 SiS_SetReg(SISSR
, 0x18, 0x00); /* EMRS2 */
5001 SiS_SetReg(SISSR
, 0x19, 0x80);
5002 SiS_SetReg(SISSR
, 0x16, 0x05);
5003 SiS_SetReg(SISSR
, 0x16, 0x85);
5005 SiS_SetReg(SISSR
, 0x18, 0x00); /* EMRS3 */
5006 SiS_SetReg(SISSR
, 0x19, 0xc0);
5007 SiS_SetReg(SISSR
, 0x16, 0x05);
5008 SiS_SetReg(SISSR
, 0x16, 0x85);
5010 SiS_SetReg(SISSR
, 0x18, 0x00); /* EMRS1 */
5011 SiS_SetReg(SISSR
, 0x19, 0x40);
5012 SiS_SetReg(SISSR
, 0x16, 0x05);
5013 SiS_SetReg(SISSR
, 0x16, 0x85);
5015 SiS_SetReg(SISSR
, 0x18, 0x42); /* MRS1 */
5016 SiS_SetReg(SISSR
, 0x19, 0x02);
5017 SiS_SetReg(SISSR
, 0x16, 0x05);
5018 SiS_SetReg(SISSR
, 0x16, 0x85);
5019 sisfb_post_xgi_delay(ivideo
, 1);
5021 SiS_SetReg(SISSR
, 0x1b, 0x04);
5022 sisfb_post_xgi_delay(ivideo
, 1);
5024 SiS_SetReg(SISSR
, 0x1b, 0x00);
5025 sisfb_post_xgi_delay(ivideo
, 1);
5027 SiS_SetReg(SISSR
, 0x18, 0x42); /* MRS1 */
5028 SiS_SetReg(SISSR
, 0x19, 0x00);
5029 SiS_SetReg(SISSR
, 0x16, 0x05);
5030 SiS_SetReg(SISSR
, 0x16, 0x85);
5031 sisfb_post_xgi_delay(ivideo
, 1);
5034 static void sisfb_post_xgi_ddr2(struct sis_video_info
*ivideo
, u8 regb
)
5036 unsigned char *bios
= ivideo
->bios_abase
;
5037 static const u8 cs158
[8] = {
5038 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5040 static const u8 cs160
[8] = {
5041 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5043 static const u8 cs168
[8] = {
5044 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5051 SiS_SetReg(SISCR
, 0xb0, 0x80); /* DDR2 dual frequency mode */
5052 SiS_SetReg(SISCR
, 0x82, 0x77);
5053 SiS_SetReg(SISCR
, 0x86, 0x00);
5054 reg
= SiS_GetReg(SISCR
, 0x86);
5055 SiS_SetReg(SISCR
, 0x86, 0x88);
5056 reg
= SiS_GetReg(SISCR
, 0x86);
5057 v1
= cs168
[regb
]; v2
= cs160
[regb
]; v3
= cs158
[regb
];
5058 if (ivideo
->haveXGIROM
) {
5059 v1
= bios
[regb
+ 0x168];
5060 v2
= bios
[regb
+ 0x160];
5061 v3
= bios
[regb
+ 0x158];
5063 SiS_SetReg(SISCR
, 0x86, v1
);
5064 SiS_SetReg(SISCR
, 0x82, 0x77);
5065 SiS_SetReg(SISCR
, 0x85, 0x00);
5066 reg
= SiS_GetReg(SISCR
, 0x85);
5067 SiS_SetReg(SISCR
, 0x85, 0x88);
5068 reg
= SiS_GetReg(SISCR
, 0x85);
5069 SiS_SetReg(SISCR
, 0x85, v2
);
5070 SiS_SetReg(SISCR
, 0x82, v3
);
5071 SiS_SetReg(SISCR
, 0x98, 0x01);
5072 SiS_SetReg(SISCR
, 0x9a, 0x02);
5073 if (sisfb_xgi_is21(ivideo
))
5074 sisfb_post_xgi_ddr2_mrs_xg21(ivideo
);
5076 sisfb_post_xgi_ddr2_mrs_default(ivideo
, regb
);
5079 static u8
sisfb_post_xgi_ramtype(struct sis_video_info
*ivideo
)
5081 unsigned char *bios
= ivideo
->bios_abase
;
5086 ramtype
= 0x00; v1
= 0x10;
5087 if (ivideo
->haveXGIROM
) {
5088 ramtype
= bios
[0x62];
5091 if (!(ramtype
& 0x80)) {
5092 if (sisfb_xgi_is21(ivideo
)) {
5093 SiS_SetRegAND(SISCR
, 0xb4, 0xfd); /* GPIO control */
5094 SiS_SetRegOR(SISCR
, 0x4a, 0x80); /* GPIOH EN */
5095 reg
= SiS_GetReg(SISCR
, 0x48);
5096 SiS_SetRegOR(SISCR
, 0xb4, 0x02);
5097 ramtype
= reg
& 0x01; /* GPIOH */
5098 } else if (ivideo
->chip
== XGI_20
) {
5099 SiS_SetReg(SISCR
, 0x97, v1
);
5100 reg
= SiS_GetReg(SISCR
, 0x97);
5102 ramtype
= (reg
& 0x01) << 1;
5105 reg
= SiS_GetReg(SISSR
, 0x39);
5106 ramtype
= reg
& 0x02;
5108 reg
= SiS_GetReg(SISSR
, 0x3a);
5109 ramtype
= (reg
>> 1) & 0x01;
5118 static int sisfb_post_xgi(struct pci_dev
*pdev
)
5120 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
5121 unsigned char *bios
= ivideo
->bios_abase
;
5122 struct pci_dev
*mypdev
= NULL
;
5123 const u8
*ptr
, *ptr2
;
5124 u8 v1
, v2
, v3
, v4
, v5
, reg
, ramtype
;
5125 u32 rega
, regb
, regd
;
5127 static const u8 cs78
[3] = { 0xf6, 0x0d, 0x00 };
5128 static const u8 cs76
[2] = { 0xa3, 0xfb };
5129 static const u8 cs7b
[3] = { 0xc0, 0x11, 0x00 };
5130 static const u8 cs158
[8] = {
5131 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5133 static const u8 cs160
[8] = {
5134 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5136 static const u8 cs168
[8] = {
5137 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5139 static const u8 cs128
[3 * 8] = {
5140 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
5141 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5142 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
5144 static const u8 cs148
[2 * 8] = {
5145 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
5146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5148 static const u8 cs31a
[8 * 4] = {
5149 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
5150 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
5151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5152 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5154 static const u8 cs33a
[8 * 4] = {
5155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5160 static const u8 cs45a
[8 * 2] = {
5161 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
5162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5164 static const u8 cs170
[7 * 8] = {
5165 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5166 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5167 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
5168 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5169 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5170 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5171 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5173 static const u8 cs1a8
[3 * 8] = {
5174 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5175 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5176 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5178 static const u8 cs100
[2 * 8] = {
5179 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5180 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5184 reg
= SiS_GetRegByte(SISVGAENABLE
) | 0x01;
5185 SiS_SetRegByte(SISVGAENABLE
, reg
);
5188 reg
= SiS_GetRegByte(SISMISCR
) | 0x01;
5189 SiS_SetRegByte(SISMISCW
, reg
);
5192 SiS_SetReg(SISSR
, 0x05, 0x86);
5193 reg
= SiS_GetReg(SISSR
, 0x05);
5197 /* Clear some regs */
5198 for(i
= 0; i
< 0x22; i
++) {
5199 if(0x06 + i
== 0x20) continue;
5200 SiS_SetReg(SISSR
, 0x06 + i
, 0x00);
5202 for(i
= 0; i
< 0x0b; i
++) {
5203 SiS_SetReg(SISSR
, 0x31 + i
, 0x00);
5205 for(i
= 0; i
< 0x10; i
++) {
5206 SiS_SetReg(SISCR
, 0x30 + i
, 0x00);
5210 if(ivideo
->haveXGIROM
) {
5211 ptr
= (const u8
*)&bios
[0x78];
5213 for(i
= 0; i
< 3; i
++) {
5214 SiS_SetReg(SISSR
, 0x23 + i
, ptr
[i
]);
5218 if(ivideo
->haveXGIROM
) {
5219 ptr
= (const u8
*)&bios
[0x76];
5221 for(i
= 0; i
< 2; i
++) {
5222 SiS_SetReg(SISSR
, 0x21 + i
, ptr
[i
]);
5225 v1
= 0x18; v2
= 0x00;
5226 if(ivideo
->haveXGIROM
) {
5230 SiS_SetReg(SISSR
, 0x07, v1
);
5231 SiS_SetReg(SISSR
, 0x11, 0x0f);
5232 SiS_SetReg(SISSR
, 0x1f, v2
);
5233 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5234 SiS_SetReg(SISSR
, 0x20, 0x80 | 0x20 | 0x04);
5235 SiS_SetReg(SISSR
, 0x27, 0x74);
5238 if(ivideo
->haveXGIROM
) {
5239 ptr
= (const u8
*)&bios
[0x7b];
5241 for(i
= 0; i
< 3; i
++) {
5242 SiS_SetReg(SISSR
, 0x31 + i
, ptr
[i
]);
5245 if(ivideo
->chip
== XGI_40
) {
5246 if(ivideo
->revision_id
== 2) {
5247 SiS_SetRegANDOR(SISSR
, 0x3b, 0x3f, 0xc0);
5249 SiS_SetReg(SISCR
, 0x7d, 0xfe);
5250 SiS_SetReg(SISCR
, 0x7e, 0x0f);
5252 if(ivideo
->revision_id
== 0) { /* 40 *and* 20? */
5253 SiS_SetRegAND(SISCR
, 0x58, 0xd7);
5254 reg
= SiS_GetReg(SISCR
, 0xcb);
5256 SiS_SetRegANDOR(SISCR
, 0x58, 0xd7, (reg
& 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5260 reg
= (ivideo
->chip
== XGI_40
) ? 0x20 : 0x00;
5261 SiS_SetRegANDOR(SISCR
, 0x38, 0x1f, reg
);
5263 if(ivideo
->chip
== XGI_20
) {
5264 SiS_SetReg(SISSR
, 0x36, 0x70);
5266 SiS_SetReg(SISVID
, 0x00, 0x86);
5267 SiS_SetReg(SISVID
, 0x32, 0x00);
5268 SiS_SetReg(SISVID
, 0x30, 0x00);
5269 SiS_SetReg(SISVID
, 0x32, 0x01);
5270 SiS_SetReg(SISVID
, 0x30, 0x00);
5271 SiS_SetRegAND(SISVID
, 0x2f, 0xdf);
5272 SiS_SetRegAND(SISCAP
, 0x00, 0x3f);
5274 SiS_SetReg(SISPART1
, 0x2f, 0x01);
5275 SiS_SetReg(SISPART1
, 0x00, 0x00);
5276 SiS_SetReg(SISPART1
, 0x02, bios
[0x7e]);
5277 SiS_SetReg(SISPART1
, 0x2e, 0x08);
5278 SiS_SetRegAND(SISPART1
, 0x35, 0x7f);
5279 SiS_SetRegAND(SISPART1
, 0x50, 0xfe);
5281 reg
= SiS_GetReg(SISPART4
, 0x00);
5282 if(reg
== 1 || reg
== 2) {
5283 SiS_SetReg(SISPART2
, 0x00, 0x1c);
5284 SiS_SetReg(SISPART4
, 0x0d, bios
[0x7f]);
5285 SiS_SetReg(SISPART4
, 0x0e, bios
[0x80]);
5286 SiS_SetReg(SISPART4
, 0x10, bios
[0x81]);
5287 SiS_SetRegAND(SISPART4
, 0x0f, 0x3f);
5289 reg
= SiS_GetReg(SISPART4
, 0x01);
5290 if((reg
& 0xf0) >= 0xb0) {
5291 reg
= SiS_GetReg(SISPART4
, 0x23);
5292 if(reg
& 0x20) reg
|= 0x40;
5293 SiS_SetReg(SISPART4
, 0x23, reg
);
5294 reg
= (reg
& 0x20) ? 0x02 : 0x00;
5295 SiS_SetRegANDOR(SISPART1
, 0x1e, 0xfd, reg
);
5301 reg
= SiS_GetReg(SISSR
, 0x3b);
5303 reg
= SiS_GetReg(SISSR
, 0x3a);
5304 v2
= (reg
& 0x30) >> 3;
5305 if(!(v2
& 0x04)) v2
^= 0x02;
5306 reg
= SiS_GetReg(SISSR
, 0x39);
5307 if(reg
& 0x80) v2
|= 0x80;
5310 if((mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0730, NULL
))) {
5311 pci_dev_put(mypdev
);
5312 if(((v2
& 0x06) == 2) || ((v2
& 0x06) == 4))
5317 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0735, NULL
);
5319 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0645, NULL
);
5321 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0650, NULL
);
5323 pci_read_config_dword(mypdev
, 0x94, ®d
);
5325 pci_write_config_dword(mypdev
, 0x94, regd
);
5327 pci_dev_put(mypdev
);
5328 } else if(sisfb_find_host_bridge(ivideo
, pdev
, PCI_VENDOR_ID_SI
)) {
5330 } else if(sisfb_find_host_bridge(ivideo
, pdev
, 0x1106) ||
5331 sisfb_find_host_bridge(ivideo
, pdev
, 0x1022) ||
5332 sisfb_find_host_bridge(ivideo
, pdev
, 0x700e) ||
5333 sisfb_find_host_bridge(ivideo
, pdev
, 0x10de)) {
5334 if((v2
& 0x06) == 4)
5339 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf0, v2
);
5341 SiS_SetReg(SISSR
, 0x22, v1
);
5343 if(ivideo
->revision_id
== 2) {
5344 v1
= SiS_GetReg(SISSR
, 0x3b);
5345 v2
= SiS_GetReg(SISSR
, 0x3a);
5346 regd
= bios
[0x90 + 3] | (bios
[0x90 + 4] << 8);
5347 if( (!(v1
& 0x02)) && (v2
& 0x30) && (regd
< 0xcf) )
5348 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf1, 0x01);
5350 if((mypdev
= pci_get_device(0x10de, 0x01e0, NULL
))) {
5351 /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5355 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf1, 0x01);
5356 pci_dev_put(mypdev
);
5361 reg
= SiS_GetReg(SISSR
, 0x3b);
5362 v2
= SiS_GetReg(SISCR
, 0x5f);
5363 if((!(reg
& 0x02)) && (v2
& 0x0e))
5365 SiS_SetReg(SISSR
, 0x27, v1
);
5367 if(bios
[0x64] & 0x01) {
5368 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf0, bios
[0x64]);
5372 pci_read_config_dword(pdev
, 0x50, ®d
);
5373 regd
= (regd
>> 20) & 0x0f;
5376 SiS_SetRegOR(SISCR
, 0x5f, 0x08);
5378 SiS_SetReg(SISCR
, 0x48, v1
);
5380 SiS_SetRegANDOR(SISCR
, 0x47, 0x04, bios
[0x4f6] & 0xfb);
5381 SiS_SetRegANDOR(SISCR
, 0x49, 0xf0, bios
[0x4f8] & 0x0f);
5382 SiS_SetRegANDOR(SISCR
, 0x4a, 0x60, bios
[0x4f9] & 0x9f);
5383 SiS_SetRegANDOR(SISCR
, 0x4b, 0x08, bios
[0x4fa] & 0xf7);
5384 SiS_SetRegANDOR(SISCR
, 0x4c, 0x80, bios
[0x4fb] & 0x7f);
5385 SiS_SetReg(SISCR
, 0x70, bios
[0x4fc]);
5386 SiS_SetRegANDOR(SISCR
, 0x71, 0xf0, bios
[0x4fd] & 0x0f);
5387 SiS_SetReg(SISCR
, 0x74, 0xd0);
5388 SiS_SetRegANDOR(SISCR
, 0x74, 0xcf, bios
[0x4fe] & 0x30);
5389 SiS_SetRegANDOR(SISCR
, 0x75, 0xe0, bios
[0x4ff] & 0x1f);
5390 SiS_SetRegANDOR(SISCR
, 0x76, 0xe0, bios
[0x500] & 0x1f);
5392 if((mypdev
= pci_get_device(0x8086, 0x2530, NULL
))) {
5394 pci_dev_put(mypdev
);
5396 SiS_SetReg(SISCR
, 0x77, v1
);
5401 * 0 == DDR1, 1 == DDR2, 2..7 == reserved?
5403 * The code seems to written so that regb should equal ramtype,
5404 * however, so far it has been hardcoded to 0. Enable other values only
5405 * on XGI Z9, as it passes the POST, and add a warning for others.
5407 ramtype
= sisfb_post_xgi_ramtype(ivideo
);
5408 if (!sisfb_xgi_is21(ivideo
) && ramtype
) {
5409 dev_warn(&pdev
->dev
,
5410 "RAM type something else than expected: %d\n",
5418 if(ivideo
->haveXGIROM
) {
5419 v1
= bios
[0x140 + regb
];
5421 SiS_SetReg(SISCR
, 0x6d, v1
);
5424 if(ivideo
->haveXGIROM
) {
5425 ptr
= (const u8
*)&bios
[0x128];
5427 for(i
= 0, j
= 0; i
< 3; i
++, j
+= 8) {
5428 SiS_SetReg(SISCR
, 0x68 + i
, ptr
[j
+ regb
]);
5433 if(ivideo
->haveXGIROM
) {
5434 index
= (ivideo
->chip
== XGI_20
) ? 0x31a : 0x3a6;
5435 ptr
= (const u8
*)&bios
[index
];
5436 ptr2
= (const u8
*)&bios
[index
+ 0x20];
5438 for(i
= 0; i
< 2; i
++) {
5440 regd
= le32_to_cpu(((u32
*)ptr
)[regb
]);
5443 regd
= le32_to_cpu(((u32
*)ptr2
)[regb
]);
5447 for(j
= 0; j
< 16; j
++) {
5449 if(regd
& 0x01) reg
|= 0x04;
5450 if(regd
& 0x02) reg
|= 0x08;
5452 SiS_SetReg(SISCR
, rega
, reg
);
5453 reg
= SiS_GetReg(SISCR
, rega
);
5454 reg
= SiS_GetReg(SISCR
, rega
);
5459 SiS_SetRegAND(SISCR
, 0x6e, 0xfc);
5462 if(ivideo
->haveXGIROM
) {
5463 index
= (ivideo
->chip
== XGI_20
) ? 0x35a : 0x3e6;
5464 ptr
= (const u8
*)&bios
[index
];
5466 for(i
= 0; i
< 4; i
++) {
5467 SiS_SetRegANDOR(SISCR
, 0x6e, 0xfc, i
);
5469 for(j
= 0; j
< 2; j
++) {
5472 regd
= le32_to_cpu(((u32
*)ptr
)[regb
* 8]);
5476 for(k
= 0; k
< 16; k
++) {
5478 if(regd
& 0x01) reg
|= 0x01;
5479 if(regd
& 0x02) reg
|= 0x02;
5481 SiS_SetReg(SISCR
, 0x6f, reg
);
5482 reg
= SiS_GetReg(SISCR
, 0x6f);
5483 reg
= SiS_GetReg(SISCR
, 0x6f);
5490 if(ivideo
->haveXGIROM
) {
5491 ptr
= (const u8
*)&bios
[0x148];
5493 for(i
= 0, j
= 0; i
< 2; i
++, j
+= 8) {
5494 SiS_SetReg(SISCR
, 0x80 + i
, ptr
[j
+ regb
]);
5497 SiS_SetRegAND(SISCR
, 0x89, 0x8f);
5500 if(ivideo
->haveXGIROM
) {
5501 index
= (ivideo
->chip
== XGI_20
) ? 0x45a : 0x4e6;
5502 ptr
= (const u8
*)&bios
[index
];
5504 regd
= le16_to_cpu(((const u16
*)ptr
)[regb
]);
5506 for(i
= 0; i
< 5; i
++) {
5508 if(regd
& 0x01) reg
|= 0x01;
5509 if(regd
& 0x02) reg
|= 0x02;
5511 SiS_SetReg(SISCR
, 0x89, reg
);
5512 reg
= SiS_GetReg(SISCR
, 0x89);
5513 reg
= SiS_GetReg(SISCR
, 0x89);
5517 v1
= 0xb5; v2
= 0x20; v3
= 0xf0; v4
= 0x13;
5518 if(ivideo
->haveXGIROM
) {
5519 v1
= bios
[0x118 + regb
];
5520 v2
= bios
[0xf8 + regb
];
5521 v3
= bios
[0x120 + regb
];
5524 SiS_SetReg(SISCR
, 0x45, v1
& 0x0f);
5525 SiS_SetReg(SISCR
, 0x99, (v1
>> 4) & 0x07);
5526 SiS_SetRegOR(SISCR
, 0x40, v1
& 0x80);
5527 SiS_SetReg(SISCR
, 0x41, v2
);
5530 if(ivideo
->haveXGIROM
) {
5531 ptr
= (const u8
*)&bios
[0x170];
5533 for(i
= 0, j
= 0; i
< 7; i
++, j
+= 8) {
5534 SiS_SetReg(SISCR
, 0x90 + i
, ptr
[j
+ regb
]);
5537 SiS_SetReg(SISCR
, 0x59, v3
);
5540 if(ivideo
->haveXGIROM
) {
5541 ptr
= (const u8
*)&bios
[0x1a8];
5543 for(i
= 0, j
= 0; i
< 3; i
++, j
+= 8) {
5544 SiS_SetReg(SISCR
, 0xc3 + i
, ptr
[j
+ regb
]);
5548 if(ivideo
->haveXGIROM
) {
5549 ptr
= (const u8
*)&bios
[0x100];
5551 for(i
= 0, j
= 0; i
< 2; i
++, j
+= 8) {
5552 SiS_SetReg(SISCR
, 0x8a + i
, ptr
[j
+ regb
]);
5555 SiS_SetReg(SISCR
, 0xcf, v4
);
5557 SiS_SetReg(SISCR
, 0x83, 0x09);
5558 SiS_SetReg(SISCR
, 0x87, 0x00);
5560 if(ivideo
->chip
== XGI_40
) {
5561 if( (ivideo
->revision_id
== 1) ||
5562 (ivideo
->revision_id
== 2) ) {
5563 SiS_SetReg(SISCR
, 0x8c, 0x87);
5568 SiS_SetReg(SISSR
, 0x17, 0x80); /* DDR2 */
5570 SiS_SetReg(SISSR
, 0x17, 0x00); /* DDR1 */
5571 SiS_SetReg(SISSR
, 0x1a, 0x87);
5573 if(ivideo
->chip
== XGI_20
) {
5574 SiS_SetReg(SISSR
, 0x15, 0x00);
5575 SiS_SetReg(SISSR
, 0x1c, 0x00);
5580 sisfb_post_xgi_setclocks(ivideo
, regb
);
5581 if((ivideo
->chip
== XGI_20
) ||
5582 (ivideo
->revision_id
== 1) ||
5583 (ivideo
->revision_id
== 2)) {
5584 v1
= cs158
[regb
]; v2
= cs160
[regb
]; v3
= cs168
[regb
];
5585 if(ivideo
->haveXGIROM
) {
5586 v1
= bios
[regb
+ 0x158];
5587 v2
= bios
[regb
+ 0x160];
5588 v3
= bios
[regb
+ 0x168];
5590 SiS_SetReg(SISCR
, 0x82, v1
);
5591 SiS_SetReg(SISCR
, 0x85, v2
);
5592 SiS_SetReg(SISCR
, 0x86, v3
);
5594 SiS_SetReg(SISCR
, 0x82, 0x88);
5595 SiS_SetReg(SISCR
, 0x86, 0x00);
5596 reg
= SiS_GetReg(SISCR
, 0x86);
5597 SiS_SetReg(SISCR
, 0x86, 0x88);
5598 reg
= SiS_GetReg(SISCR
, 0x86);
5599 SiS_SetReg(SISCR
, 0x86, bios
[regb
+ 0x168]);
5600 SiS_SetReg(SISCR
, 0x82, 0x77);
5601 SiS_SetReg(SISCR
, 0x85, 0x00);
5602 reg
= SiS_GetReg(SISCR
, 0x85);
5603 SiS_SetReg(SISCR
, 0x85, 0x88);
5604 reg
= SiS_GetReg(SISCR
, 0x85);
5605 SiS_SetReg(SISCR
, 0x85, bios
[regb
+ 0x160]);
5606 SiS_SetReg(SISCR
, 0x82, bios
[regb
+ 0x158]);
5608 if(ivideo
->chip
== XGI_40
) {
5609 SiS_SetReg(SISCR
, 0x97, 0x00);
5611 SiS_SetReg(SISCR
, 0x98, 0x01);
5612 SiS_SetReg(SISCR
, 0x9a, 0x02);
5614 SiS_SetReg(SISSR
, 0x18, 0x01);
5615 if((ivideo
->chip
== XGI_20
) ||
5616 (ivideo
->revision_id
== 2)) {
5617 SiS_SetReg(SISSR
, 0x19, 0x40);
5619 SiS_SetReg(SISSR
, 0x19, 0x20);
5621 SiS_SetReg(SISSR
, 0x16, 0x00);
5622 SiS_SetReg(SISSR
, 0x16, 0x80);
5623 if((ivideo
->chip
== XGI_20
) || (bios
[0x1cb] != 0x0c)) {
5624 sisfb_post_xgi_delay(ivideo
, 0x43);
5625 sisfb_post_xgi_delay(ivideo
, 0x43);
5626 sisfb_post_xgi_delay(ivideo
, 0x43);
5627 SiS_SetReg(SISSR
, 0x18, 0x00);
5628 if((ivideo
->chip
== XGI_20
) ||
5629 (ivideo
->revision_id
== 2)) {
5630 SiS_SetReg(SISSR
, 0x19, 0x40);
5632 SiS_SetReg(SISSR
, 0x19, 0x20);
5634 } else if((ivideo
->chip
== XGI_40
) && (bios
[0x1cb] == 0x0c)) {
5635 /* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
5637 SiS_SetReg(SISSR
, 0x16, 0x00);
5638 SiS_SetReg(SISSR
, 0x16, 0x80);
5639 sisfb_post_xgi_delay(ivideo
, 4);
5640 v1
= 0x31; v2
= 0x03; v3
= 0x83; v4
= 0x03; v5
= 0x83;
5641 if(ivideo
->haveXGIROM
) {
5643 index
= (ivideo
->chip
== XGI_20
) ? 0x4b2 : 0x53e;
5645 v3
= bios
[index
+ 1];
5646 v4
= bios
[index
+ 2];
5647 v5
= bios
[index
+ 3];
5649 SiS_SetReg(SISSR
, 0x18, v1
);
5650 SiS_SetReg(SISSR
, 0x19, ((ivideo
->chip
== XGI_20
) ? 0x02 : 0x01));
5651 SiS_SetReg(SISSR
, 0x16, v2
);
5652 SiS_SetReg(SISSR
, 0x16, v3
);
5653 sisfb_post_xgi_delay(ivideo
, 0x43);
5654 SiS_SetReg(SISSR
, 0x1b, 0x03);
5655 sisfb_post_xgi_delay(ivideo
, 0x22);
5656 SiS_SetReg(SISSR
, 0x18, v1
);
5657 SiS_SetReg(SISSR
, 0x19, 0x00);
5658 SiS_SetReg(SISSR
, 0x16, v4
);
5659 SiS_SetReg(SISSR
, 0x16, v5
);
5660 SiS_SetReg(SISSR
, 0x1b, 0x00);
5663 sisfb_post_xgi_ddr2(ivideo
, regb
);
5666 sisfb_post_xgi_setclocks(ivideo
, regb
);
5667 if((ivideo
->chip
== XGI_40
) &&
5668 ((ivideo
->revision_id
== 1) ||
5669 (ivideo
->revision_id
== 2))) {
5670 SiS_SetReg(SISCR
, 0x82, bios
[regb
+ 0x158]);
5671 SiS_SetReg(SISCR
, 0x85, bios
[regb
+ 0x160]);
5672 SiS_SetReg(SISCR
, 0x86, bios
[regb
+ 0x168]);
5674 SiS_SetReg(SISCR
, 0x82, 0x88);
5675 SiS_SetReg(SISCR
, 0x86, 0x00);
5676 reg
= SiS_GetReg(SISCR
, 0x86);
5677 SiS_SetReg(SISCR
, 0x86, 0x88);
5678 SiS_SetReg(SISCR
, 0x82, 0x77);
5679 SiS_SetReg(SISCR
, 0x85, 0x00);
5680 reg
= SiS_GetReg(SISCR
, 0x85);
5681 SiS_SetReg(SISCR
, 0x85, 0x88);
5682 reg
= SiS_GetReg(SISCR
, 0x85);
5683 v1
= cs160
[regb
]; v2
= cs158
[regb
];
5684 if(ivideo
->haveXGIROM
) {
5685 v1
= bios
[regb
+ 0x160];
5686 v2
= bios
[regb
+ 0x158];
5688 SiS_SetReg(SISCR
, 0x85, v1
);
5689 SiS_SetReg(SISCR
, 0x82, v2
);
5691 if(ivideo
->chip
== XGI_40
) {
5692 SiS_SetReg(SISCR
, 0x97, 0x11);
5694 if((ivideo
->chip
== XGI_40
) && (ivideo
->revision_id
== 2)) {
5695 SiS_SetReg(SISCR
, 0x98, 0x01);
5697 SiS_SetReg(SISCR
, 0x98, 0x03);
5699 SiS_SetReg(SISCR
, 0x9a, 0x02);
5701 if(ivideo
->chip
== XGI_40
) {
5702 SiS_SetReg(SISSR
, 0x18, 0x01);
5704 SiS_SetReg(SISSR
, 0x18, 0x00);
5706 SiS_SetReg(SISSR
, 0x19, 0x40);
5707 SiS_SetReg(SISSR
, 0x16, 0x00);
5708 SiS_SetReg(SISSR
, 0x16, 0x80);
5709 if((ivideo
->chip
== XGI_40
) && (bios
[0x1cb] != 0x0c)) {
5710 sisfb_post_xgi_delay(ivideo
, 0x43);
5711 sisfb_post_xgi_delay(ivideo
, 0x43);
5712 sisfb_post_xgi_delay(ivideo
, 0x43);
5713 SiS_SetReg(SISSR
, 0x18, 0x00);
5714 SiS_SetReg(SISSR
, 0x19, 0x40);
5715 SiS_SetReg(SISSR
, 0x16, 0x00);
5716 SiS_SetReg(SISSR
, 0x16, 0x80);
5718 sisfb_post_xgi_delay(ivideo
, 4);
5720 if(ivideo
->haveXGIROM
) {
5723 SiS_SetReg(SISSR
, 0x18, v1
);
5724 SiS_SetReg(SISSR
, 0x19, 0x01);
5725 if(ivideo
->chip
== XGI_40
) {
5726 SiS_SetReg(SISSR
, 0x16, bios
[0x53e]);
5727 SiS_SetReg(SISSR
, 0x16, bios
[0x53f]);
5729 SiS_SetReg(SISSR
, 0x16, 0x05);
5730 SiS_SetReg(SISSR
, 0x16, 0x85);
5732 sisfb_post_xgi_delay(ivideo
, 0x43);
5733 if(ivideo
->chip
== XGI_40
) {
5734 SiS_SetReg(SISSR
, 0x1b, 0x01);
5736 SiS_SetReg(SISSR
, 0x1b, 0x03);
5738 sisfb_post_xgi_delay(ivideo
, 0x22);
5739 SiS_SetReg(SISSR
, 0x18, v1
);
5740 SiS_SetReg(SISSR
, 0x19, 0x00);
5741 if(ivideo
->chip
== XGI_40
) {
5742 SiS_SetReg(SISSR
, 0x16, bios
[0x540]);
5743 SiS_SetReg(SISSR
, 0x16, bios
[0x541]);
5745 SiS_SetReg(SISSR
, 0x16, 0x05);
5746 SiS_SetReg(SISSR
, 0x16, 0x85);
5748 SiS_SetReg(SISSR
, 0x1b, 0x00);
5753 if(ivideo
->haveXGIROM
) {
5754 v1
= bios
[0x110 + regb
];
5756 SiS_SetReg(SISSR
, 0x1b, v1
);
5759 v1
= 0x00; v2
= 0x00;
5760 if(ivideo
->haveXGIROM
) {
5766 if((v1
& 0x40) && (v2
& regd
) && ivideo
->haveXGIROM
) {
5768 SiS_SetReg(SISSR
, 0x13, bios
[regb
+ 0xe0]);
5769 SiS_SetReg(SISSR
, 0x14, bios
[regb
+ 0xe0 + 8]);
5774 /* Set default mode, don't clear screen */
5775 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
5776 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
5777 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
5778 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
5779 ivideo
->SiS_Pr
.VideoMemorySize
= 8 << 20;
5780 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
5782 SiS_SetReg(SISSR
, 0x05, 0x86);
5784 /* Disable read-cache */
5785 SiS_SetRegAND(SISSR
, 0x21, 0xdf);
5786 err
= sisfb_post_xgi_ramsize(ivideo
);
5787 /* Enable read-cache */
5788 SiS_SetRegOR(SISSR
, 0x21, 0x20);
5792 "%s: RAM size detection failed: %d\n",
5799 printk(KERN_DEBUG
"-----------------\n");
5800 for(i
= 0; i
< 0xff; i
++) {
5801 reg
= SiS_GetReg(SISCR
, i
);
5802 printk(KERN_DEBUG
"CR%02x(%x) = 0x%02x\n", i
, SISCR
, reg
);
5804 for(i
= 0; i
< 0x40; i
++) {
5805 reg
= SiS_GetReg(SISSR
, i
);
5806 printk(KERN_DEBUG
"SR%02x(%x) = 0x%02x\n", i
, SISSR
, reg
);
5808 printk(KERN_DEBUG
"-----------------\n");
5812 if(ivideo
->chip
== XGI_20
) {
5813 SiS_SetRegOR(SISCR
, 0x32, 0x20);
5815 reg
= SiS_GetReg(SISPART4
, 0x00);
5816 if((reg
== 1) || (reg
== 2)) {
5817 sisfb_sense_crt1(ivideo
);
5819 SiS_SetRegOR(SISCR
, 0x32, 0x20);
5823 /* Set default mode, don't clear screen */
5824 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
5825 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
5826 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
5827 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
5828 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
5830 SiS_SetReg(SISSR
, 0x05, 0x86);
5833 SiS_SetRegOR(SISSR
, 0x01, 0x20);
5835 /* Save mode number in CR34 */
5836 SiS_SetReg(SISCR
, 0x34, 0x2e);
5838 /* Let everyone know what the current mode is */
5839 ivideo
->modeprechange
= 0x2e;
5841 if(ivideo
->chip
== XGI_40
) {
5842 reg
= SiS_GetReg(SISCR
, 0xca);
5843 v1
= SiS_GetReg(SISCR
, 0xcc);
5844 if((reg
& 0x10) && (!(v1
& 0x04))) {
5846 "sisfb: Please connect power to the card.\n");
5855 static int sisfb_probe(struct pci_dev
*pdev
, const struct pci_device_id
*ent
)
5857 struct sisfb_chip_info
*chipinfo
= &sisfb_chip_info
[ent
->driver_data
];
5858 struct sis_video_info
*ivideo
= NULL
;
5859 struct fb_info
*sis_fb_info
= NULL
;
5867 sis_fb_info
= framebuffer_alloc(sizeof(*ivideo
), &pdev
->dev
);
5871 ivideo
= (struct sis_video_info
*)sis_fb_info
->par
;
5872 ivideo
->memyselfandi
= sis_fb_info
;
5874 ivideo
->sisfb_id
= SISFB_ID
;
5876 if(card_list
== NULL
) {
5877 ivideo
->cardnumber
= 0;
5879 struct sis_video_info
*countvideo
= card_list
;
5880 ivideo
->cardnumber
= 1;
5881 while((countvideo
= countvideo
->next
) != NULL
)
5882 ivideo
->cardnumber
++;
5885 strlcpy(ivideo
->myid
, chipinfo
->chip_name
, sizeof(ivideo
->myid
));
5887 ivideo
->warncount
= 0;
5888 ivideo
->chip_id
= pdev
->device
;
5889 ivideo
->chip_vendor
= pdev
->vendor
;
5890 ivideo
->revision_id
= pdev
->revision
;
5891 ivideo
->SiS_Pr
.ChipRevision
= ivideo
->revision_id
;
5892 pci_read_config_word(pdev
, PCI_COMMAND
, ®16
);
5893 ivideo
->sisvga_enabled
= reg16
& 0x01;
5894 ivideo
->pcibus
= pdev
->bus
->number
;
5895 ivideo
->pcislot
= PCI_SLOT(pdev
->devfn
);
5896 ivideo
->pcifunc
= PCI_FUNC(pdev
->devfn
);
5897 ivideo
->subsysvendor
= pdev
->subsystem_vendor
;
5898 ivideo
->subsysdevice
= pdev
->subsystem_device
;
5901 if(sisfb_mode_idx
== -1) {
5902 sisfb_get_vga_mode_from_kernel();
5906 ivideo
->chip
= chipinfo
->chip
;
5907 ivideo
->chip_real_id
= chipinfo
->chip
;
5908 ivideo
->sisvga_engine
= chipinfo
->vgaengine
;
5909 ivideo
->hwcursor_size
= chipinfo
->hwcursor_size
;
5910 ivideo
->CRT2_write_enable
= chipinfo
->CRT2_write_enable
;
5911 ivideo
->mni
= chipinfo
->mni
;
5913 ivideo
->detectedpdc
= 0xff;
5914 ivideo
->detectedpdca
= 0xff;
5915 ivideo
->detectedlcda
= 0xff;
5917 ivideo
->sisfb_thismonitor
.datavalid
= false;
5919 ivideo
->current_base
= 0;
5921 ivideo
->engineok
= 0;
5923 ivideo
->sisfb_was_boot_device
= 0;
5925 if(pdev
->resource
[PCI_ROM_RESOURCE
].flags
& IORESOURCE_ROM_SHADOW
) {
5926 if(ivideo
->sisvga_enabled
)
5927 ivideo
->sisfb_was_boot_device
= 1;
5929 printk(KERN_DEBUG
"sisfb: PCI device is disabled, "
5930 "but marked as boot video device ???\n");
5931 printk(KERN_DEBUG
"sisfb: I will not accept this "
5932 "as the primary VGA device\n");
5936 ivideo
->sisfb_parm_mem
= sisfb_parm_mem
;
5937 ivideo
->sisfb_accel
= sisfb_accel
;
5938 ivideo
->sisfb_ypan
= sisfb_ypan
;
5939 ivideo
->sisfb_max
= sisfb_max
;
5940 ivideo
->sisfb_userom
= sisfb_userom
;
5941 ivideo
->sisfb_useoem
= sisfb_useoem
;
5942 ivideo
->sisfb_mode_idx
= sisfb_mode_idx
;
5943 ivideo
->sisfb_parm_rate
= sisfb_parm_rate
;
5944 ivideo
->sisfb_crt1off
= sisfb_crt1off
;
5945 ivideo
->sisfb_forcecrt1
= sisfb_forcecrt1
;
5946 ivideo
->sisfb_crt2type
= sisfb_crt2type
;
5947 ivideo
->sisfb_crt2flags
= sisfb_crt2flags
;
5948 /* pdc(a), scalelcd, special timing, lvdshl handled below */
5949 ivideo
->sisfb_dstn
= sisfb_dstn
;
5950 ivideo
->sisfb_fstn
= sisfb_fstn
;
5951 ivideo
->sisfb_tvplug
= sisfb_tvplug
;
5952 ivideo
->sisfb_tvstd
= sisfb_tvstd
;
5953 ivideo
->tvxpos
= sisfb_tvxposoffset
;
5954 ivideo
->tvypos
= sisfb_tvyposoffset
;
5955 ivideo
->sisfb_nocrt2rate
= sisfb_nocrt2rate
;
5956 ivideo
->refresh_rate
= 0;
5957 if(ivideo
->sisfb_parm_rate
!= -1) {
5958 ivideo
->refresh_rate
= ivideo
->sisfb_parm_rate
;
5961 ivideo
->SiS_Pr
.UsePanelScaler
= sisfb_scalelcd
;
5962 ivideo
->SiS_Pr
.CenterScreen
= -1;
5963 ivideo
->SiS_Pr
.SiS_CustomT
= sisfb_specialtiming
;
5964 ivideo
->SiS_Pr
.LVDSHL
= sisfb_lvdshl
;
5966 ivideo
->SiS_Pr
.SiS_Backup70xx
= 0xff;
5967 ivideo
->SiS_Pr
.SiS_CHOverScan
= -1;
5968 ivideo
->SiS_Pr
.SiS_ChSW
= false;
5969 ivideo
->SiS_Pr
.SiS_UseLCDA
= false;
5970 ivideo
->SiS_Pr
.HaveEMI
= false;
5971 ivideo
->SiS_Pr
.HaveEMILCD
= false;
5972 ivideo
->SiS_Pr
.OverruleEMI
= false;
5973 ivideo
->SiS_Pr
.SiS_SensibleSR11
= false;
5974 ivideo
->SiS_Pr
.SiS_MyCR63
= 0x63;
5975 ivideo
->SiS_Pr
.PDC
= -1;
5976 ivideo
->SiS_Pr
.PDCA
= -1;
5977 ivideo
->SiS_Pr
.DDCPortMixup
= false;
5978 #ifdef CONFIG_FB_SIS_315
5979 if(ivideo
->chip
>= SIS_330
) {
5980 ivideo
->SiS_Pr
.SiS_MyCR63
= 0x53;
5981 if(ivideo
->chip
>= SIS_661
) {
5982 ivideo
->SiS_Pr
.SiS_SensibleSR11
= true;
5987 memcpy(&ivideo
->default_var
, &my_default_var
, sizeof(my_default_var
));
5989 pci_set_drvdata(pdev
, ivideo
);
5991 /* Patch special cases */
5992 if((ivideo
->nbridge
= sisfb_get_northbridge(ivideo
->chip
))) {
5993 switch(ivideo
->nbridge
->device
) {
5994 #ifdef CONFIG_FB_SIS_300
5995 case PCI_DEVICE_ID_SI_730
:
5996 ivideo
->chip
= SIS_730
;
5997 strcpy(ivideo
->myid
, "SiS 730");
6000 #ifdef CONFIG_FB_SIS_315
6001 case PCI_DEVICE_ID_SI_651
:
6002 /* ivideo->chip is ok */
6003 strcpy(ivideo
->myid
, "SiS 651");
6005 case PCI_DEVICE_ID_SI_740
:
6006 ivideo
->chip
= SIS_740
;
6007 strcpy(ivideo
->myid
, "SiS 740");
6009 case PCI_DEVICE_ID_SI_661
:
6010 ivideo
->chip
= SIS_661
;
6011 strcpy(ivideo
->myid
, "SiS 661");
6013 case PCI_DEVICE_ID_SI_741
:
6014 ivideo
->chip
= SIS_741
;
6015 strcpy(ivideo
->myid
, "SiS 741");
6017 case PCI_DEVICE_ID_SI_760
:
6018 ivideo
->chip
= SIS_760
;
6019 strcpy(ivideo
->myid
, "SiS 760");
6021 case PCI_DEVICE_ID_SI_761
:
6022 ivideo
->chip
= SIS_761
;
6023 strcpy(ivideo
->myid
, "SiS 761");
6031 ivideo
->SiS_Pr
.ChipType
= ivideo
->chip
;
6033 ivideo
->SiS_Pr
.ivideo
= (void *)ivideo
;
6035 #ifdef CONFIG_FB_SIS_315
6036 if((ivideo
->SiS_Pr
.ChipType
== SIS_315PRO
) ||
6037 (ivideo
->SiS_Pr
.ChipType
== SIS_315
)) {
6038 ivideo
->SiS_Pr
.ChipType
= SIS_315H
;
6042 if(!ivideo
->sisvga_enabled
) {
6043 if(pci_enable_device(pdev
)) {
6044 pci_dev_put(ivideo
->nbridge
);
6045 framebuffer_release(sis_fb_info
);
6050 ivideo
->video_base
= pci_resource_start(pdev
, 0);
6051 ivideo
->video_size
= pci_resource_len(pdev
, 0);
6052 ivideo
->mmio_base
= pci_resource_start(pdev
, 1);
6053 ivideo
->mmio_size
= pci_resource_len(pdev
, 1);
6054 ivideo
->SiS_Pr
.RelIO
= pci_resource_start(pdev
, 2) + 0x30;
6055 ivideo
->SiS_Pr
.IOAddress
= ivideo
->vga_base
= ivideo
->SiS_Pr
.RelIO
;
6057 SiSRegInit(&ivideo
->SiS_Pr
, ivideo
->SiS_Pr
.IOAddress
);
6059 #ifdef CONFIG_FB_SIS_300
6060 /* Find PCI systems for Chrontel/GPIO communication setup */
6061 if(ivideo
->chip
== SIS_630
) {
6064 if(mychswtable
[i
].subsysVendor
== ivideo
->subsysvendor
&&
6065 mychswtable
[i
].subsysCard
== ivideo
->subsysdevice
) {
6066 ivideo
->SiS_Pr
.SiS_ChSW
= true;
6067 printk(KERN_DEBUG
"sisfb: Identified [%s %s] "
6068 "requiring Chrontel/GPIO setup\n",
6069 mychswtable
[i
].vendorName
,
6070 mychswtable
[i
].cardName
);
6071 ivideo
->lpcdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0008, NULL
);
6075 } while(mychswtable
[i
].subsysVendor
!= 0);
6079 #ifdef CONFIG_FB_SIS_315
6080 if((ivideo
->chip
== SIS_760
) && (ivideo
->nbridge
)) {
6081 ivideo
->lpcdev
= pci_get_slot(ivideo
->nbridge
->bus
, (2 << 3));
6085 SiS_SetReg(SISSR
, 0x05, 0x86);
6087 if( (!ivideo
->sisvga_enabled
)
6088 #if !defined(__i386__) && !defined(__x86_64__)
6089 || (sisfb_resetcard
)
6092 for(i
= 0x30; i
<= 0x3f; i
++) {
6093 SiS_SetReg(SISCR
, i
, 0x00);
6097 /* Find out about current video mode */
6098 ivideo
->modeprechange
= 0x03;
6099 reg
= SiS_GetReg(SISCR
, 0x34);
6101 ivideo
->modeprechange
= reg
& 0x7f;
6102 } else if(ivideo
->sisvga_enabled
) {
6103 #if defined(__i386__) || defined(__x86_64__)
6104 unsigned char __iomem
*tt
= ioremap(0x400, 0x100);
6106 ivideo
->modeprechange
= readb(tt
+ 0x49);
6112 /* Search and copy ROM image */
6113 ivideo
->bios_abase
= NULL
;
6114 ivideo
->SiS_Pr
.VirtualRomBase
= NULL
;
6115 ivideo
->SiS_Pr
.UseROM
= false;
6116 ivideo
->haveXGIROM
= ivideo
->SiS_Pr
.SiS_XGIROM
= false;
6117 if(ivideo
->sisfb_userom
) {
6118 ivideo
->SiS_Pr
.VirtualRomBase
= sisfb_find_rom(pdev
);
6119 ivideo
->bios_abase
= ivideo
->SiS_Pr
.VirtualRomBase
;
6120 ivideo
->SiS_Pr
.UseROM
= (bool)(ivideo
->SiS_Pr
.VirtualRomBase
);
6121 printk(KERN_INFO
"sisfb: Video ROM %sfound\n",
6122 ivideo
->SiS_Pr
.UseROM
? "" : "not ");
6123 if((ivideo
->SiS_Pr
.UseROM
) && (ivideo
->chip
>= XGI_20
)) {
6124 ivideo
->SiS_Pr
.UseROM
= false;
6125 ivideo
->haveXGIROM
= ivideo
->SiS_Pr
.SiS_XGIROM
= true;
6126 if( (ivideo
->revision_id
== 2) &&
6127 (!(ivideo
->bios_abase
[0x1d1] & 0x01)) ) {
6128 ivideo
->SiS_Pr
.DDCPortMixup
= true;
6132 printk(KERN_INFO
"sisfb: Video ROM usage disabled\n");
6135 /* Find systems for special custom timing */
6136 if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_NONE
) {
6137 sisfb_detect_custom_timing(ivideo
);
6140 #ifdef CONFIG_FB_SIS_315
6141 if (ivideo
->chip
== XGI_20
) {
6142 /* Check if our Z7 chip is actually Z9 */
6143 SiS_SetRegOR(SISCR
, 0x4a, 0x40); /* GPIOG EN */
6144 reg
= SiS_GetReg(SISCR
, 0x48);
6145 if (reg
& 0x02) { /* GPIOG */
6146 ivideo
->chip_real_id
= XGI_21
;
6147 dev_info(&pdev
->dev
, "Z9 detected\n");
6152 /* POST card in case this has not been done by the BIOS */
6153 if( (!ivideo
->sisvga_enabled
)
6154 #if !defined(__i386__) && !defined(__x86_64__)
6155 || (sisfb_resetcard
)
6158 #ifdef CONFIG_FB_SIS_300
6159 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
6160 if(ivideo
->chip
== SIS_300
) {
6161 sisfb_post_sis300(pdev
);
6162 ivideo
->sisfb_can_post
= 1;
6167 #ifdef CONFIG_FB_SIS_315
6168 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
6170 /* if((ivideo->chip == SIS_315H) ||
6171 (ivideo->chip == SIS_315) ||
6172 (ivideo->chip == SIS_315PRO) ||
6173 (ivideo->chip == SIS_330)) {
6174 sisfb_post_sis315330(pdev);
6175 } else */ if(ivideo
->chip
== XGI_20
) {
6176 result
= sisfb_post_xgi(pdev
);
6177 ivideo
->sisfb_can_post
= 1;
6178 } else if((ivideo
->chip
== XGI_40
) && ivideo
->haveXGIROM
) {
6179 result
= sisfb_post_xgi(pdev
);
6180 ivideo
->sisfb_can_post
= 1;
6182 printk(KERN_INFO
"sisfb: Card is not "
6183 "POSTed and sisfb can't do this either.\n");
6186 printk(KERN_ERR
"sisfb: Failed to POST card\n");
6194 ivideo
->sisfb_card_posted
= 1;
6196 /* Find out about RAM size */
6197 if(sisfb_get_dram_size(ivideo
)) {
6198 printk(KERN_INFO
"sisfb: Fatal error: Unable to determine VRAM size.\n");
6204 /* Enable PCI addressing and MMIO */
6205 if((ivideo
->sisfb_mode_idx
< 0) ||
6206 ((sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
]) != 0xFF)) {
6207 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
6208 SiS_SetRegOR(SISSR
, IND_SIS_PCI_ADDRESS_SET
, (SIS_PCI_ADDR_ENABLE
| SIS_MEM_MAP_IO_ENABLE
));
6209 /* Enable 2D accelerator engine */
6210 SiS_SetRegOR(SISSR
, IND_SIS_MODULE_ENABLE
, SIS_ENABLE_2D
);
6213 if(sisfb_pdc
!= 0xff) {
6214 if(ivideo
->sisvga_engine
== SIS_300_VGA
)
6218 ivideo
->SiS_Pr
.PDC
= sisfb_pdc
;
6220 #ifdef CONFIG_FB_SIS_315
6221 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
6222 if(sisfb_pdca
!= 0xff)
6223 ivideo
->SiS_Pr
.PDCA
= sisfb_pdca
& 0x1f;
6227 if(!request_mem_region(ivideo
->video_base
, ivideo
->video_size
, "sisfb FB")) {
6228 printk(KERN_ERR
"sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6229 (int)(ivideo
->video_size
>> 20));
6230 printk(KERN_ERR
"sisfb: Is there another framebuffer driver active?\n");
6235 if(!request_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
, "sisfb MMIO")) {
6236 printk(KERN_ERR
"sisfb: Fatal error: Unable to reserve MMIO region\n");
6241 ivideo
->video_vbase
= ioremap_wc(ivideo
->video_base
, ivideo
->video_size
);
6242 ivideo
->SiS_Pr
.VideoMemoryAddress
= ivideo
->video_vbase
;
6243 if(!ivideo
->video_vbase
) {
6244 printk(KERN_ERR
"sisfb: Fatal error: Unable to map framebuffer memory\n");
6249 ivideo
->mmio_vbase
= ioremap(ivideo
->mmio_base
, ivideo
->mmio_size
);
6250 if(!ivideo
->mmio_vbase
) {
6251 printk(KERN_ERR
"sisfb: Fatal error: Unable to map MMIO region\n");
6253 error_0
: iounmap(ivideo
->video_vbase
);
6254 error_1
: release_mem_region(ivideo
->video_base
, ivideo
->video_size
);
6255 error_2
: release_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
);
6256 error_3
: vfree(ivideo
->bios_abase
);
6257 pci_dev_put(ivideo
->lpcdev
);
6258 pci_dev_put(ivideo
->nbridge
);
6259 if(!ivideo
->sisvga_enabled
)
6260 pci_disable_device(pdev
);
6261 framebuffer_release(sis_fb_info
);
6265 printk(KERN_INFO
"sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
6266 ivideo
->video_base
, (unsigned long)ivideo
->video_vbase
, ivideo
->video_size
/ 1024);
6268 if(ivideo
->video_offset
) {
6269 printk(KERN_INFO
"sisfb: Viewport offset %ldk\n",
6270 ivideo
->video_offset
/ 1024);
6273 printk(KERN_INFO
"sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
6274 ivideo
->mmio_base
, (unsigned long)ivideo
->mmio_vbase
, ivideo
->mmio_size
/ 1024);
6277 /* Determine the size of the command queue */
6278 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
6279 ivideo
->cmdQueueSize
= TURBO_QUEUE_AREA_SIZE
;
6281 if(ivideo
->chip
== XGI_20
) {
6282 ivideo
->cmdQueueSize
= COMMAND_QUEUE_AREA_SIZE_Z7
;
6284 ivideo
->cmdQueueSize
= COMMAND_QUEUE_AREA_SIZE
;
6288 /* Engines are no longer initialized here; this is
6289 * now done after the first mode-switch (if the
6290 * submitted var has its acceleration flags set).
6293 /* Calculate the base of the (unused) hw cursor */
6294 ivideo
->hwcursor_vbase
= ivideo
->video_vbase
6295 + ivideo
->video_size
6296 - ivideo
->cmdQueueSize
6297 - ivideo
->hwcursor_size
;
6298 ivideo
->caps
|= HW_CURSOR_CAP
;
6300 /* Initialize offscreen memory manager */
6301 if((ivideo
->havenoheap
= sisfb_heap_init(ivideo
))) {
6302 printk(KERN_WARNING
"sisfb: Failed to initialize offscreen memory heap\n");
6305 /* Used for clearing the screen only, therefore respect our mem limit */
6306 ivideo
->SiS_Pr
.VideoMemoryAddress
+= ivideo
->video_offset
;
6307 ivideo
->SiS_Pr
.VideoMemorySize
= ivideo
->sisfb_mem
;
6309 ivideo
->vbflags
= 0;
6310 ivideo
->lcddefmodeidx
= DEFAULT_LCDMODE
;
6311 ivideo
->tvdefmodeidx
= DEFAULT_TVMODE
;
6312 ivideo
->defmodeidx
= DEFAULT_MODE
;
6315 if(ivideo
->chip
< XGI_20
) {
6316 if(ivideo
->bios_abase
) {
6317 ivideo
->newrom
= SiSDetermineROMLayout661(&ivideo
->SiS_Pr
);
6321 if((ivideo
->sisfb_mode_idx
< 0) ||
6322 ((sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
]) != 0xFF)) {
6324 sisfb_sense_crt1(ivideo
);
6326 sisfb_get_VB_type(ivideo
);
6328 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
6329 sisfb_detect_VB_connect(ivideo
);
6332 ivideo
->currentvbflags
= ivideo
->vbflags
& (VB_VIDEOBRIDGE
| TV_STANDARD
);
6334 /* Decide on which CRT2 device to use */
6335 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
6336 if(ivideo
->sisfb_crt2type
!= -1) {
6337 if((ivideo
->sisfb_crt2type
== CRT2_LCD
) &&
6338 (ivideo
->vbflags
& CRT2_LCD
)) {
6339 ivideo
->currentvbflags
|= CRT2_LCD
;
6340 } else if(ivideo
->sisfb_crt2type
!= CRT2_LCD
) {
6341 ivideo
->currentvbflags
|= ivideo
->sisfb_crt2type
;
6344 /* Chrontel 700x TV detection often unreliable, therefore
6345 * use a different default order on such machines
6347 if((ivideo
->sisvga_engine
== SIS_300_VGA
) &&
6348 (ivideo
->vbflags2
& VB2_CHRONTEL
)) {
6349 if(ivideo
->vbflags
& CRT2_LCD
)
6350 ivideo
->currentvbflags
|= CRT2_LCD
;
6351 else if(ivideo
->vbflags
& CRT2_TV
)
6352 ivideo
->currentvbflags
|= CRT2_TV
;
6353 else if(ivideo
->vbflags
& CRT2_VGA
)
6354 ivideo
->currentvbflags
|= CRT2_VGA
;
6356 if(ivideo
->vbflags
& CRT2_TV
)
6357 ivideo
->currentvbflags
|= CRT2_TV
;
6358 else if(ivideo
->vbflags
& CRT2_LCD
)
6359 ivideo
->currentvbflags
|= CRT2_LCD
;
6360 else if(ivideo
->vbflags
& CRT2_VGA
)
6361 ivideo
->currentvbflags
|= CRT2_VGA
;
6366 if(ivideo
->vbflags
& CRT2_LCD
) {
6367 sisfb_detect_lcd_type(ivideo
);
6370 sisfb_save_pdc_emi(ivideo
);
6372 if(!ivideo
->sisfb_crt1off
) {
6373 sisfb_handle_ddc(ivideo
, &ivideo
->sisfb_thismonitor
, 0);
6375 if((ivideo
->vbflags2
& VB2_SISTMDSBRIDGE
) &&
6376 (ivideo
->vbflags
& (CRT2_VGA
| CRT2_LCD
))) {
6377 sisfb_handle_ddc(ivideo
, &ivideo
->sisfb_thismonitor
, 1);
6381 if(ivideo
->sisfb_mode_idx
>= 0) {
6382 int bu
= ivideo
->sisfb_mode_idx
;
6383 ivideo
->sisfb_mode_idx
= sisfb_validate_mode(ivideo
,
6384 ivideo
->sisfb_mode_idx
, ivideo
->currentvbflags
);
6385 if(bu
!= ivideo
->sisfb_mode_idx
) {
6386 printk(KERN_ERR
"Mode %dx%dx%d failed validation\n",
6387 sisbios_mode
[bu
].xres
,
6388 sisbios_mode
[bu
].yres
,
6389 sisbios_mode
[bu
].bpp
);
6393 if(ivideo
->sisfb_mode_idx
< 0) {
6394 switch(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
6396 ivideo
->sisfb_mode_idx
= ivideo
->lcddefmodeidx
;
6399 ivideo
->sisfb_mode_idx
= ivideo
->tvdefmodeidx
;
6402 ivideo
->sisfb_mode_idx
= ivideo
->defmodeidx
;
6407 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
6409 if(ivideo
->refresh_rate
!= 0) {
6410 sisfb_search_refresh_rate(ivideo
, ivideo
->refresh_rate
,
6411 ivideo
->sisfb_mode_idx
);
6414 if(ivideo
->rate_idx
== 0) {
6415 ivideo
->rate_idx
= sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
;
6416 ivideo
->refresh_rate
= 60;
6419 if(ivideo
->sisfb_thismonitor
.datavalid
) {
6420 if(!sisfb_verify_rate(ivideo
, &ivideo
->sisfb_thismonitor
,
6421 ivideo
->sisfb_mode_idx
,
6423 ivideo
->refresh_rate
)) {
6424 printk(KERN_INFO
"sisfb: WARNING: Refresh rate "
6425 "exceeds monitor specs!\n");
6429 ivideo
->video_bpp
= sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
;
6430 ivideo
->video_width
= sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
;
6431 ivideo
->video_height
= sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
;
6433 sisfb_set_vparms(ivideo
);
6435 printk(KERN_INFO
"sisfb: Default mode is %dx%dx%d (%dHz)\n",
6436 ivideo
->video_width
, ivideo
->video_height
, ivideo
->video_bpp
,
6437 ivideo
->refresh_rate
);
6439 /* Set up the default var according to chosen default display mode */
6440 ivideo
->default_var
.xres
= ivideo
->default_var
.xres_virtual
= ivideo
->video_width
;
6441 ivideo
->default_var
.yres
= ivideo
->default_var
.yres_virtual
= ivideo
->video_height
;
6442 ivideo
->default_var
.bits_per_pixel
= ivideo
->video_bpp
;
6444 sisfb_bpp_to_var(ivideo
, &ivideo
->default_var
);
6446 ivideo
->default_var
.pixclock
= (u32
) (1000000000 /
6447 sisfb_mode_rate_to_dclock(&ivideo
->SiS_Pr
, ivideo
->mode_no
, ivideo
->rate_idx
));
6449 if(sisfb_mode_rate_to_ddata(&ivideo
->SiS_Pr
, ivideo
->mode_no
,
6450 ivideo
->rate_idx
, &ivideo
->default_var
)) {
6451 if((ivideo
->default_var
.vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
6452 ivideo
->default_var
.pixclock
<<= 1;
6456 if(ivideo
->sisfb_ypan
) {
6457 /* Maximize regardless of sisfb_max at startup */
6458 ivideo
->default_var
.yres_virtual
=
6459 sisfb_calc_maxyres(ivideo
, &ivideo
->default_var
);
6460 if(ivideo
->default_var
.yres_virtual
< ivideo
->default_var
.yres
) {
6461 ivideo
->default_var
.yres_virtual
= ivideo
->default_var
.yres
;
6465 sisfb_calc_pitch(ivideo
, &ivideo
->default_var
);
6468 if(ivideo
->sisfb_accel
) {
6470 #ifdef STUPID_ACCELF_TEXT_SHIT
6471 ivideo
->default_var
.accel_flags
|= FB_ACCELF_TEXT
;
6474 sisfb_initaccel(ivideo
);
6476 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
6477 sis_fb_info
->flags
= FBINFO_DEFAULT
|
6478 FBINFO_HWACCEL_YPAN
|
6479 FBINFO_HWACCEL_XPAN
|
6480 FBINFO_HWACCEL_COPYAREA
|
6481 FBINFO_HWACCEL_FILLRECT
|
6482 ((ivideo
->accel
) ? 0 : FBINFO_HWACCEL_DISABLED
);
6484 sis_fb_info
->flags
= FBINFO_FLAG_DEFAULT
;
6486 sis_fb_info
->var
= ivideo
->default_var
;
6487 sis_fb_info
->fix
= ivideo
->sisfb_fix
;
6488 sis_fb_info
->screen_base
= ivideo
->video_vbase
+ ivideo
->video_offset
;
6489 sis_fb_info
->fbops
= &sisfb_ops
;
6490 sis_fb_info
->pseudo_palette
= ivideo
->pseudo_palette
;
6492 fb_alloc_cmap(&sis_fb_info
->cmap
, 256 , 0);
6494 printk(KERN_DEBUG
"sisfb: Initial vbflags 0x%x\n", (int)ivideo
->vbflags
);
6496 ivideo
->wc_cookie
= arch_phys_wc_add(ivideo
->video_base
,
6497 ivideo
->video_size
);
6498 if(register_framebuffer(sis_fb_info
) < 0) {
6499 printk(KERN_ERR
"sisfb: Fatal error: Failed to register framebuffer\n");
6501 iounmap(ivideo
->mmio_vbase
);
6505 ivideo
->registered
= 1;
6508 ivideo
->next
= card_list
;
6511 printk(KERN_INFO
"sisfb: 2D acceleration is %s, y-panning %s\n",
6512 ivideo
->sisfb_accel
? "enabled" : "disabled",
6513 ivideo
->sisfb_ypan
?
6514 (ivideo
->sisfb_max
? "enabled (auto-max)" :
6515 "enabled (no auto-max)") :
6519 fb_info(sis_fb_info
, "%s frame buffer device version %d.%d.%d\n",
6520 ivideo
->myid
, VER_MAJOR
, VER_MINOR
, VER_LEVEL
);
6522 printk(KERN_INFO
"sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
6524 } /* if mode = "none" */
6529 /*****************************************************/
6530 /* PCI DEVICE HANDLING */
6531 /*****************************************************/
6533 static void sisfb_remove(struct pci_dev
*pdev
)
6535 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
6536 struct fb_info
*sis_fb_info
= ivideo
->memyselfandi
;
6537 int registered
= ivideo
->registered
;
6538 int modechanged
= ivideo
->modechanged
;
6541 iounmap(ivideo
->mmio_vbase
);
6542 iounmap(ivideo
->video_vbase
);
6544 /* Release mem regions */
6545 release_mem_region(ivideo
->video_base
, ivideo
->video_size
);
6546 release_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
);
6548 vfree(ivideo
->bios_abase
);
6550 pci_dev_put(ivideo
->lpcdev
);
6552 pci_dev_put(ivideo
->nbridge
);
6554 arch_phys_wc_del(ivideo
->wc_cookie
);
6556 /* If device was disabled when starting, disable
6559 if(!ivideo
->sisvga_enabled
)
6560 pci_disable_device(pdev
);
6562 /* Unregister the framebuffer */
6563 if(ivideo
->registered
) {
6564 unregister_framebuffer(sis_fb_info
);
6565 framebuffer_release(sis_fb_info
);
6568 /* OK, our ivideo is gone for good from here. */
6570 /* TODO: Restore the initial mode
6571 * This sounds easy but is as good as impossible
6572 * on many machines with SiS chip and video bridge
6573 * since text modes are always set up differently
6574 * from machine to machine. Depends on the type
6575 * of integration between chipset and bridge.
6577 if(registered
&& modechanged
)
6579 "sisfb: Restoring of text mode not supported yet\n");
6582 static struct pci_driver sisfb_driver
= {
6584 .id_table
= sisfb_pci_table
,
6585 .probe
= sisfb_probe
,
6586 .remove
= sisfb_remove
,
6589 static int __init
sisfb_init(void)
6592 char *options
= NULL
;
6594 if(fb_get_options("sisfb", &options
))
6597 sisfb_setup(options
);
6599 return pci_register_driver(&sisfb_driver
);
6603 module_init(sisfb_init
);
6606 /*****************************************************/
6608 /*****************************************************/
6612 static char *mode
= NULL
;
6613 static int vesa
= -1;
6614 static unsigned int rate
= 0;
6615 static unsigned int crt1off
= 1;
6616 static unsigned int mem
= 0;
6617 static char *forcecrt2type
= NULL
;
6618 static int forcecrt1
= -1;
6619 static int pdc
= -1;
6620 static int pdc1
= -1;
6621 static int noaccel
= -1;
6622 static int noypan
= -1;
6623 static int nomax
= -1;
6624 static int userom
= -1;
6625 static int useoem
= -1;
6626 static char *tvstandard
= NULL
;
6627 static int nocrt2rate
= 0;
6628 static int scalelcd
= -1;
6629 static char *specialtiming
= NULL
;
6630 static int lvdshl
= -1;
6631 static int tvxposoffset
= 0, tvyposoffset
= 0;
6632 #if !defined(__i386__) && !defined(__x86_64__)
6633 static int resetcard
= 0;
6634 static int videoram
= 0;
6637 static int __init
sisfb_init_module(void)
6639 sisfb_setdefaultparms();
6642 sisfb_parm_rate
= rate
;
6644 if((scalelcd
== 0) || (scalelcd
== 1))
6645 sisfb_scalelcd
= scalelcd
^ 1;
6647 /* Need to check crt2 type first for fstn/dstn */
6650 sisfb_search_crt2type(forcecrt2type
);
6653 sisfb_search_tvstd(tvstandard
);
6656 sisfb_search_mode(mode
, false);
6658 sisfb_search_vesamode(vesa
, false);
6660 sisfb_crt1off
= (crt1off
== 0) ? 1 : 0;
6662 sisfb_forcecrt1
= forcecrt1
;
6665 else if(forcecrt1
== 0)
6670 else if(noaccel
== 0)
6675 else if(noypan
== 0)
6684 sisfb_parm_mem
= mem
;
6687 sisfb_userom
= userom
;
6690 sisfb_useoem
= useoem
;
6693 sisfb_pdc
= (pdc
& 0x7f);
6696 sisfb_pdca
= (pdc1
& 0x1f);
6698 sisfb_nocrt2rate
= nocrt2rate
;
6701 sisfb_search_specialtiming(specialtiming
);
6703 if((lvdshl
>= 0) && (lvdshl
<= 3))
6704 sisfb_lvdshl
= lvdshl
;
6706 sisfb_tvxposoffset
= tvxposoffset
;
6707 sisfb_tvyposoffset
= tvyposoffset
;
6709 #if !defined(__i386__) && !defined(__x86_64__)
6710 sisfb_resetcard
= (resetcard
) ? 1 : 0;
6712 sisfb_videoram
= videoram
;
6715 return sisfb_init();
6718 static void __exit
sisfb_remove_module(void)
6720 pci_unregister_driver(&sisfb_driver
);
6721 printk(KERN_DEBUG
"sisfb: Module unloaded\n");
6724 module_init(sisfb_init_module
);
6725 module_exit(sisfb_remove_module
);
6727 MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
6728 MODULE_LICENSE("GPL");
6729 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
6731 module_param(mem
, int, 0);
6732 module_param(noaccel
, int, 0);
6733 module_param(noypan
, int, 0);
6734 module_param(nomax
, int, 0);
6735 module_param(userom
, int, 0);
6736 module_param(useoem
, int, 0);
6737 module_param(mode
, charp
, 0);
6738 module_param(vesa
, int, 0);
6739 module_param(rate
, int, 0);
6740 module_param(forcecrt1
, int, 0);
6741 module_param(forcecrt2type
, charp
, 0);
6742 module_param(scalelcd
, int, 0);
6743 module_param(pdc
, int, 0);
6744 module_param(pdc1
, int, 0);
6745 module_param(specialtiming
, charp
, 0);
6746 module_param(lvdshl
, int, 0);
6747 module_param(tvstandard
, charp
, 0);
6748 module_param(tvxposoffset
, int, 0);
6749 module_param(tvyposoffset
, int, 0);
6750 module_param(nocrt2rate
, int, 0);
6751 #if !defined(__i386__) && !defined(__x86_64__)
6752 module_param(resetcard
, int, 0);
6753 module_param(videoram
, int, 0);
6756 MODULE_PARM_DESC(mem
,
6757 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6758 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6759 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6760 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6761 "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6762 "The value is to be specified without 'KB'.\n");
6764 MODULE_PARM_DESC(noaccel
,
6765 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
6768 MODULE_PARM_DESC(noypan
,
6769 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
6770 "will be performed by redrawing the screen. (default: 0)\n");
6772 MODULE_PARM_DESC(nomax
,
6773 "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
6774 "memory for the virtual screen in order to optimize scrolling performance. If\n"
6775 "this is set to anything other than 0, sisfb will not do this and thereby \n"
6776 "enable the user to positively specify a virtual Y size of the screen using\n"
6777 "fbset. (default: 0)\n");
6779 MODULE_PARM_DESC(mode
,
6780 "\nSelects the desired default display mode in the format XxYxDepth,\n"
6781 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
6782 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
6783 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
6785 MODULE_PARM_DESC(vesa
,
6786 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
6787 "0x117 (default: 0x0103)\n");
6789 MODULE_PARM_DESC(rate
,
6790 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
6791 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
6792 "will be ignored (default: 60)\n");
6794 MODULE_PARM_DESC(forcecrt1
,
6795 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
6796 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
6797 "0=CRT1 OFF) (default: [autodetected])\n");
6799 MODULE_PARM_DESC(forcecrt2type
,
6800 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
6801 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
6802 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
6803 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
6804 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
6805 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
6806 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
6807 "depends on the very hardware in use. (default: [autodetected])\n");
6809 MODULE_PARM_DESC(scalelcd
,
6810 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
6811 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
6812 "show black bars around the image, TMDS panels will probably do the scaling\n"
6813 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
6815 MODULE_PARM_DESC(pdc
,
6816 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
6817 "should detect this correctly in most cases; however, sometimes this is not\n"
6818 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
6819 "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
6820 "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
6821 "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
6823 #ifdef CONFIG_FB_SIS_315
6824 MODULE_PARM_DESC(pdc1
,
6825 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
6826 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
6827 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
6828 "implemented yet.\n");
6831 MODULE_PARM_DESC(specialtiming
,
6832 "\nPlease refer to documentation for more information on this option.\n");
6834 MODULE_PARM_DESC(lvdshl
,
6835 "\nPlease refer to documentation for more information on this option.\n");
6837 MODULE_PARM_DESC(tvstandard
,
6838 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
6839 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
6841 MODULE_PARM_DESC(tvxposoffset
,
6842 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
6845 MODULE_PARM_DESC(tvyposoffset
,
6846 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
6849 MODULE_PARM_DESC(nocrt2rate
,
6850 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
6851 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
6853 #if !defined(__i386__) && !defined(__x86_64__)
6854 #ifdef CONFIG_FB_SIS_300
6855 MODULE_PARM_DESC(resetcard
,
6856 "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
6857 "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
6858 "currently). Default: 0\n");
6860 MODULE_PARM_DESC(videoram
,
6861 "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
6862 "some non-x86 architectures where the memory auto detection fails. Only\n"
6863 "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
6867 #endif /* /MODULE */
6869 /* _GPL only for new symbols. */
6870 EXPORT_SYMBOL(sis_malloc
);
6871 EXPORT_SYMBOL(sis_free
);
6872 EXPORT_SYMBOL_GPL(sis_malloc_new
);
6873 EXPORT_SYMBOL_GPL(sis_free_new
);