1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * SiS 300/540/630[S]/730[S],
4 * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
6 * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
8 * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
10 * Author: Thomas Winischhofer <thomas@winischhofer.net>
12 * Author of (practically wiped) code base:
14 * Copyright (C) 1999 Silicon Integrated Systems, Inc.
16 * See http://www.winischhofer.net/ for more information and updates
18 * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver,
19 * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
22 #include <linux/module.h>
23 #include <linux/moduleparam.h>
24 #include <linux/kernel.h>
25 #include <linux/spinlock.h>
26 #include <linux/errno.h>
27 #include <linux/string.h>
29 #include <linux/screen_info.h>
30 #include <linux/slab.h>
32 #include <linux/selection.h>
33 #include <linux/ioport.h>
34 #include <linux/init.h>
35 #include <linux/pci.h>
36 #include <linux/vmalloc.h>
37 #include <linux/capability.h>
39 #include <linux/types.h>
40 #include <linux/uaccess.h>
47 #if !defined(CONFIG_FB_SIS_300) && !defined(CONFIG_FB_SIS_315)
48 #warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
49 #warning sisfb will not work!
52 /* ---------------------- Prototypes ------------------------- */
54 /* Interface used by the world */
56 static int sisfb_setup(char *options
);
59 /* Interface to the low level console driver */
60 static int sisfb_init(void);
63 static int sisfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
64 struct fb_info
*info
);
66 static int sisfb_ioctl(struct fb_info
*info
, unsigned int cmd
,
68 static int sisfb_set_par(struct fb_info
*info
);
69 static int sisfb_blank(int blank
,
70 struct fb_info
*info
);
72 static void sisfb_handle_command(struct sis_video_info
*ivideo
,
73 struct sisfb_cmd
*sisfb_command
);
75 static void sisfb_search_mode(char *name
, bool quiet
);
76 static int sisfb_validate_mode(struct sis_video_info
*ivideo
, int modeindex
, u32 vbflags
);
77 static u8
sisfb_search_refresh_rate(struct sis_video_info
*ivideo
, unsigned int rate
,
79 static int sisfb_setcolreg(unsigned regno
, unsigned red
, unsigned green
,
80 unsigned blue
, unsigned transp
,
81 struct fb_info
*fb_info
);
82 static int sisfb_do_set_var(struct fb_var_screeninfo
*var
, int isactive
,
83 struct fb_info
*info
);
84 static void sisfb_pre_setmode(struct sis_video_info
*ivideo
);
85 static void sisfb_post_setmode(struct sis_video_info
*ivideo
);
86 static bool sisfb_CheckVBRetrace(struct sis_video_info
*ivideo
);
87 static bool sisfbcheckvretracecrt2(struct sis_video_info
*ivideo
);
88 static bool sisfbcheckvretracecrt1(struct sis_video_info
*ivideo
);
89 static bool sisfb_bridgeisslave(struct sis_video_info
*ivideo
);
90 static void sisfb_detect_VB_connect(struct sis_video_info
*ivideo
);
91 static void sisfb_get_VB_type(struct sis_video_info
*ivideo
);
92 static void sisfb_set_TVxposoffset(struct sis_video_info
*ivideo
, int val
);
93 static void sisfb_set_TVyposoffset(struct sis_video_info
*ivideo
, int val
);
95 /* Internal heap routines */
96 static int sisfb_heap_init(struct sis_video_info
*ivideo
);
97 static struct SIS_OH
* sisfb_poh_new_node(struct SIS_HEAP
*memheap
);
98 static struct SIS_OH
* sisfb_poh_allocate(struct SIS_HEAP
*memheap
, u32 size
);
99 static void sisfb_delete_node(struct SIS_OH
*poh
);
100 static void sisfb_insert_node(struct SIS_OH
*pohList
, struct SIS_OH
*poh
);
101 static struct SIS_OH
* sisfb_poh_free(struct SIS_HEAP
*memheap
, u32 base
);
102 static void sisfb_free_node(struct SIS_HEAP
*memheap
, struct SIS_OH
*poh
);
105 /* ------------------ Internal helper routines ----------------- */
108 sisfb_setdefaultparms(void)
118 sisfb_parm_rate
= -1;
120 sisfb_forcecrt1
= -1;
126 sisfb_specialtiming
= CUT_NONE
;
132 sisfb_tvxposoffset
= 0;
133 sisfb_tvyposoffset
= 0;
134 sisfb_nocrt2rate
= 0;
135 #if !defined(__i386__) && !defined(__x86_64__)
141 /* ------------- Parameter parsing -------------- */
143 static void sisfb_search_vesamode(unsigned int vesamode
, bool quiet
)
147 /* We don't know the hardware specs yet and there is no ivideo */
151 printk(KERN_ERR
"sisfb: Invalid mode. Using default.\n");
153 sisfb_mode_idx
= DEFAULT_MODE
;
158 vesamode
&= 0x1dff; /* Clean VESA mode number from other flags */
160 while(sisbios_mode
[i
++].mode_no
[0] != 0) {
161 if( (sisbios_mode
[i
-1].vesa_mode_no_1
== vesamode
) ||
162 (sisbios_mode
[i
-1].vesa_mode_no_2
== vesamode
) ) {
164 if(sisbios_mode
[i
-1].mode_no
[1] == 0x50 ||
165 sisbios_mode
[i
-1].mode_no
[1] == 0x56 ||
166 sisbios_mode
[i
-1].mode_no
[1] == 0x53)
169 if(sisbios_mode
[i
-1].mode_no
[1] == 0x5a ||
170 sisbios_mode
[i
-1].mode_no
[1] == 0x5b)
173 sisfb_mode_idx
= i
- 1;
179 printk(KERN_ERR
"sisfb: Invalid VESA mode 0x%x'\n", vesamode
);
182 static void sisfb_search_mode(char *name
, bool quiet
)
184 unsigned int j
= 0, xres
= 0, yres
= 0, depth
= 0, rate
= 0;
186 char strbuf
[16], strbuf1
[20];
187 char *nameptr
= name
;
189 /* We don't know the hardware specs yet and there is no ivideo */
193 printk(KERN_ERR
"sisfb: Internal error, using default mode.\n");
195 sisfb_mode_idx
= DEFAULT_MODE
;
199 if(!strncasecmp(name
, sisbios_mode
[MODE_INDEX_NONE
].name
, strlen(name
))) {
201 printk(KERN_ERR
"sisfb: Mode 'none' not supported anymore. Using default.\n");
203 sisfb_mode_idx
= DEFAULT_MODE
;
207 if(strlen(name
) <= 19) {
208 strcpy(strbuf1
, name
);
209 for(i
= 0; i
< strlen(strbuf1
); i
++) {
210 if(strbuf1
[i
] < '0' || strbuf1
[i
] > '9') strbuf1
[i
] = ' ';
213 /* This does some fuzzy mode naming detection */
214 if(sscanf(strbuf1
, "%u %u %u %u", &xres
, &yres
, &depth
, &rate
) == 4) {
215 if((rate
<= 32) || (depth
> 32)) {
216 j
= rate
; rate
= depth
; depth
= j
;
218 sprintf(strbuf
, "%ux%ux%u", xres
, yres
, depth
);
220 sisfb_parm_rate
= rate
;
221 } else if(sscanf(strbuf1
, "%u %u %u", &xres
, &yres
, &depth
) == 3) {
222 sprintf(strbuf
, "%ux%ux%u", xres
, yres
, depth
);
226 if((sscanf(strbuf1
, "%u %u", &xres
, &yres
) == 2) && (xres
!= 0)) {
227 sprintf(strbuf
, "%ux%ux8", xres
, yres
);
230 sisfb_search_vesamode(simple_strtoul(name
, NULL
, 0), quiet
);
237 while(sisbios_mode
[i
].mode_no
[0] != 0) {
238 if(!strncasecmp(nameptr
, sisbios_mode
[i
++].name
, strlen(nameptr
))) {
240 if(sisbios_mode
[i
-1].mode_no
[1] == 0x50 ||
241 sisbios_mode
[i
-1].mode_no
[1] == 0x56 ||
242 sisbios_mode
[i
-1].mode_no
[1] == 0x53)
245 if(sisbios_mode
[i
-1].mode_no
[1] == 0x5a ||
246 sisbios_mode
[i
-1].mode_no
[1] == 0x5b)
249 sisfb_mode_idx
= i
- 1;
256 printk(KERN_ERR
"sisfb: Invalid mode '%s'\n", nameptr
);
260 static void sisfb_get_vga_mode_from_kernel(void)
264 int mydepth
= screen_info
.lfb_depth
;
266 if(screen_info
.orig_video_isVGA
!= VIDEO_TYPE_VLFB
) return;
268 if( (screen_info
.lfb_width
>= 320) && (screen_info
.lfb_width
<= 2048) &&
269 (screen_info
.lfb_height
>= 200) && (screen_info
.lfb_height
<= 1536) &&
270 (mydepth
>= 8) && (mydepth
<= 32) ) {
272 if(mydepth
== 24) mydepth
= 32;
274 sprintf(mymode
, "%ux%ux%u", screen_info
.lfb_width
,
275 screen_info
.lfb_height
,
279 "sisfb: Using vga mode %s pre-set by kernel as default\n",
282 sisfb_search_mode(mymode
, true);
290 sisfb_search_crt2type(const char *name
)
294 /* We don't know the hardware specs yet and there is no ivideo */
296 if(name
== NULL
) return;
298 while(sis_crt2type
[i
].type_no
!= -1) {
299 if(!strncasecmp(name
, sis_crt2type
[i
].name
, strlen(sis_crt2type
[i
].name
))) {
300 sisfb_crt2type
= sis_crt2type
[i
].type_no
;
301 sisfb_tvplug
= sis_crt2type
[i
].tvplug_no
;
302 sisfb_crt2flags
= sis_crt2type
[i
].flags
;
308 sisfb_dstn
= (sisfb_crt2flags
& FL_550_DSTN
) ? 1 : 0;
309 sisfb_fstn
= (sisfb_crt2flags
& FL_550_FSTN
) ? 1 : 0;
311 if(sisfb_crt2type
< 0)
312 printk(KERN_ERR
"sisfb: Invalid CRT2 type: %s\n", name
);
316 sisfb_search_tvstd(const char *name
)
320 /* We don't know the hardware specs yet and there is no ivideo */
325 while(sis_tvtype
[i
].type_no
!= -1) {
326 if(!strncasecmp(name
, sis_tvtype
[i
].name
, strlen(sis_tvtype
[i
].name
))) {
327 sisfb_tvstd
= sis_tvtype
[i
].type_no
;
335 sisfb_search_specialtiming(const char *name
)
340 /* We don't know the hardware specs yet and there is no ivideo */
345 if(!strncasecmp(name
, "none", 4)) {
346 sisfb_specialtiming
= CUT_FORCENONE
;
347 printk(KERN_DEBUG
"sisfb: Special timing disabled\n");
349 while(mycustomttable
[i
].chipID
!= 0) {
350 if(!strncasecmp(name
,mycustomttable
[i
].optionName
,
351 strlen(mycustomttable
[i
].optionName
))) {
352 sisfb_specialtiming
= mycustomttable
[i
].SpecialID
;
354 printk(KERN_INFO
"sisfb: Special timing for %s %s forced (\"%s\")\n",
355 mycustomttable
[i
].vendorName
,
356 mycustomttable
[i
].cardName
,
357 mycustomttable
[i
].optionName
);
363 printk(KERN_WARNING
"sisfb: Invalid SpecialTiming parameter, valid are:");
364 printk(KERN_WARNING
"\t\"none\" (to disable special timings)\n");
366 while(mycustomttable
[i
].chipID
!= 0) {
367 printk(KERN_WARNING
"\t\"%s\" (for %s %s)\n",
368 mycustomttable
[i
].optionName
,
369 mycustomttable
[i
].vendorName
,
370 mycustomttable
[i
].cardName
);
377 /* ----------- Various detection routines ----------- */
379 static void sisfb_detect_custom_timing(struct sis_video_info
*ivideo
)
381 unsigned char *biosver
= NULL
;
382 unsigned char *biosdate
= NULL
;
387 if(ivideo
->SiS_Pr
.UseROM
) {
388 biosver
= ivideo
->SiS_Pr
.VirtualRomBase
+ 0x06;
389 biosdate
= ivideo
->SiS_Pr
.VirtualRomBase
+ 0x2c;
390 for(i
= 0; i
< 32768; i
++)
391 chksum
+= ivideo
->SiS_Pr
.VirtualRomBase
[i
];
396 if( (mycustomttable
[i
].chipID
== ivideo
->chip
) &&
397 ((!strlen(mycustomttable
[i
].biosversion
)) ||
398 (ivideo
->SiS_Pr
.UseROM
&&
399 (!strncmp(mycustomttable
[i
].biosversion
, biosver
,
400 strlen(mycustomttable
[i
].biosversion
))))) &&
401 ((!strlen(mycustomttable
[i
].biosdate
)) ||
402 (ivideo
->SiS_Pr
.UseROM
&&
403 (!strncmp(mycustomttable
[i
].biosdate
, biosdate
,
404 strlen(mycustomttable
[i
].biosdate
))))) &&
405 ((!mycustomttable
[i
].bioschksum
) ||
406 (ivideo
->SiS_Pr
.UseROM
&&
407 (mycustomttable
[i
].bioschksum
== chksum
))) &&
408 (mycustomttable
[i
].pcisubsysvendor
== ivideo
->subsysvendor
) &&
409 (mycustomttable
[i
].pcisubsyscard
== ivideo
->subsysdevice
) ) {
411 for(j
= 0; j
< 5; j
++) {
412 if(mycustomttable
[i
].biosFootprintAddr
[j
]) {
413 if(ivideo
->SiS_Pr
.UseROM
) {
414 if(ivideo
->SiS_Pr
.VirtualRomBase
[mycustomttable
[i
].biosFootprintAddr
[j
]] !=
415 mycustomttable
[i
].biosFootprintData
[j
]) {
423 ivideo
->SiS_Pr
.SiS_CustomT
= mycustomttable
[i
].SpecialID
;
424 printk(KERN_DEBUG
"sisfb: Identified [%s %s], special timing applies\n",
425 mycustomttable
[i
].vendorName
,
426 mycustomttable
[i
].cardName
);
427 printk(KERN_DEBUG
"sisfb: [specialtiming parameter name: %s]\n",
428 mycustomttable
[i
].optionName
);
433 } while(mycustomttable
[i
].chipID
);
436 static bool sisfb_interpret_edid(struct sisfb_monitor
*monitor
, u8
*buffer
)
438 int i
, j
, xres
, yres
, refresh
, index
;
441 if(buffer
[0] != 0x00 || buffer
[1] != 0xff ||
442 buffer
[2] != 0xff || buffer
[3] != 0xff ||
443 buffer
[4] != 0xff || buffer
[5] != 0xff ||
444 buffer
[6] != 0xff || buffer
[7] != 0x00) {
445 printk(KERN_DEBUG
"sisfb: Bad EDID header\n");
449 if(buffer
[0x12] != 0x01) {
450 printk(KERN_INFO
"sisfb: EDID version %d not supported\n",
455 monitor
->feature
= buffer
[0x18];
457 if(!(buffer
[0x14] & 0x80)) {
458 if(!(buffer
[0x14] & 0x08)) {
460 "sisfb: WARNING: Monitor does not support separate syncs\n");
464 if(buffer
[0x13] >= 0x01) {
465 /* EDID V1 rev 1 and 2: Search for monitor descriptor
470 if(buffer
[j
] == 0x00 && buffer
[j
+ 1] == 0x00 &&
471 buffer
[j
+ 2] == 0x00 && buffer
[j
+ 3] == 0xfd &&
472 buffer
[j
+ 4] == 0x00) {
473 monitor
->hmin
= buffer
[j
+ 7];
474 monitor
->hmax
= buffer
[j
+ 8];
475 monitor
->vmin
= buffer
[j
+ 5];
476 monitor
->vmax
= buffer
[j
+ 6];
477 monitor
->dclockmax
= buffer
[j
+ 9] * 10 * 1000;
478 monitor
->datavalid
= true;
485 if(!monitor
->datavalid
) {
486 /* Otherwise: Get a range from the list of supported
487 * Estabished Timings. This is not entirely accurate,
488 * because fixed frequency monitors are not supported
491 monitor
->hmin
= 65535; monitor
->hmax
= 0;
492 monitor
->vmin
= 65535; monitor
->vmax
= 0;
493 monitor
->dclockmax
= 0;
494 emodes
= buffer
[0x23] | (buffer
[0x24] << 8) | (buffer
[0x25] << 16);
495 for(i
= 0; i
< 13; i
++) {
496 if(emodes
& sisfb_ddcsmodes
[i
].mask
) {
497 if(monitor
->hmin
> sisfb_ddcsmodes
[i
].h
) monitor
->hmin
= sisfb_ddcsmodes
[i
].h
;
498 if(monitor
->hmax
< sisfb_ddcsmodes
[i
].h
) monitor
->hmax
= sisfb_ddcsmodes
[i
].h
+ 1;
499 if(monitor
->vmin
> sisfb_ddcsmodes
[i
].v
) monitor
->vmin
= sisfb_ddcsmodes
[i
].v
;
500 if(monitor
->vmax
< sisfb_ddcsmodes
[i
].v
) monitor
->vmax
= sisfb_ddcsmodes
[i
].v
;
501 if(monitor
->dclockmax
< sisfb_ddcsmodes
[i
].d
) monitor
->dclockmax
= sisfb_ddcsmodes
[i
].d
;
505 for(i
= 0; i
< 8; i
++) {
506 xres
= (buffer
[index
] + 31) * 8;
507 switch(buffer
[index
+ 1] & 0xc0) {
508 case 0xc0: yres
= (xres
* 9) / 16; break;
509 case 0x80: yres
= (xres
* 4) / 5; break;
510 case 0x40: yres
= (xres
* 3) / 4; break;
511 default: yres
= xres
; break;
513 refresh
= (buffer
[index
+ 1] & 0x3f) + 60;
514 if((xres
>= 640) && (yres
>= 480)) {
515 for(j
= 0; j
< 8; j
++) {
516 if((xres
== sisfb_ddcfmodes
[j
].x
) &&
517 (yres
== sisfb_ddcfmodes
[j
].y
) &&
518 (refresh
== sisfb_ddcfmodes
[j
].v
)) {
519 if(monitor
->hmin
> sisfb_ddcfmodes
[j
].h
) monitor
->hmin
= sisfb_ddcfmodes
[j
].h
;
520 if(monitor
->hmax
< sisfb_ddcfmodes
[j
].h
) monitor
->hmax
= sisfb_ddcfmodes
[j
].h
+ 1;
521 if(monitor
->vmin
> sisfb_ddcsmodes
[j
].v
) monitor
->vmin
= sisfb_ddcsmodes
[j
].v
;
522 if(monitor
->vmax
< sisfb_ddcsmodes
[j
].v
) monitor
->vmax
= sisfb_ddcsmodes
[j
].v
;
523 if(monitor
->dclockmax
< sisfb_ddcsmodes
[j
].d
) monitor
->dclockmax
= sisfb_ddcsmodes
[j
].d
;
529 if((monitor
->hmin
<= monitor
->hmax
) && (monitor
->vmin
<= monitor
->vmax
)) {
530 monitor
->datavalid
= true;
534 return monitor
->datavalid
;
537 static void sisfb_handle_ddc(struct sis_video_info
*ivideo
,
538 struct sisfb_monitor
*monitor
, int crtno
)
540 unsigned short temp
, i
, realcrtno
= crtno
;
541 unsigned char buffer
[256];
543 monitor
->datavalid
= false;
546 if(ivideo
->vbflags
& CRT2_LCD
) realcrtno
= 1;
547 else if(ivideo
->vbflags
& CRT2_VGA
) realcrtno
= 2;
551 if((ivideo
->sisfb_crt1off
) && (!crtno
))
554 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
555 realcrtno
, 0, &buffer
[0], ivideo
->vbflags2
);
556 if((!temp
) || (temp
== 0xffff)) {
557 printk(KERN_INFO
"sisfb: CRT%d DDC probing failed\n", crtno
+ 1);
560 printk(KERN_INFO
"sisfb: CRT%d DDC supported\n", crtno
+ 1);
561 printk(KERN_INFO
"sisfb: CRT%d DDC level: %s%s%s%s\n",
563 (temp
& 0x1a) ? "" : "[none of the supported]",
564 (temp
& 0x02) ? "2 " : "",
565 (temp
& 0x08) ? "D&P" : "",
566 (temp
& 0x10) ? "FPDI-2" : "");
568 i
= 3; /* Number of retrys */
570 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
571 realcrtno
, 1, &buffer
[0], ivideo
->vbflags2
);
572 } while((temp
) && i
--);
574 if(sisfb_interpret_edid(monitor
, &buffer
[0])) {
575 printk(KERN_INFO
"sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
576 monitor
->hmin
, monitor
->hmax
, monitor
->vmin
, monitor
->vmax
,
577 monitor
->dclockmax
/ 1000);
579 printk(KERN_INFO
"sisfb: CRT%d DDC EDID corrupt\n", crtno
+ 1);
582 printk(KERN_INFO
"sisfb: CRT%d DDC reading failed\n", crtno
+ 1);
585 printk(KERN_INFO
"sisfb: VESA D&P and FPDI-2 not supported yet\n");
590 /* -------------- Mode validation --------------- */
593 sisfb_verify_rate(struct sis_video_info
*ivideo
, struct sisfb_monitor
*monitor
,
594 int mode_idx
, int rate_idx
, int rate
)
597 unsigned int dclock
, hsync
;
599 if(!monitor
->datavalid
)
605 /* Skip for 320x200, 320x240, 640x400 */
606 switch(sisbios_mode
[mode_idx
].mode_no
[ivideo
->mni
]) {
617 #ifdef CONFIG_FB_SIS_315
620 if(ivideo
->sisvga_engine
== SIS_315_VGA
) return true;
624 if(rate
< (monitor
->vmin
- 1))
626 if(rate
> (monitor
->vmax
+ 1))
629 if(sisfb_gettotalfrommode(&ivideo
->SiS_Pr
,
630 sisbios_mode
[mode_idx
].mode_no
[ivideo
->mni
],
631 &htotal
, &vtotal
, rate_idx
)) {
632 dclock
= (htotal
* vtotal
* rate
) / 1000;
633 if(dclock
> (monitor
->dclockmax
+ 1000))
635 hsync
= dclock
/ htotal
;
636 if(hsync
< (monitor
->hmin
- 1))
638 if(hsync
> (monitor
->hmax
+ 1))
647 sisfb_validate_mode(struct sis_video_info
*ivideo
, int myindex
, u32 vbflags
)
649 u16 xres
=0, yres
, myres
;
651 #ifdef CONFIG_FB_SIS_300
652 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
653 if(!(sisbios_mode
[myindex
].chipset
& MD_SIS300
))
657 #ifdef CONFIG_FB_SIS_315
658 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
659 if(!(sisbios_mode
[myindex
].chipset
& MD_SIS315
))
664 myres
= sisbios_mode
[myindex
].yres
;
666 switch(vbflags
& VB_DISPTYPE_DISP2
) {
669 xres
= ivideo
->lcdxres
; yres
= ivideo
->lcdyres
;
671 if((ivideo
->SiS_Pr
.SiS_CustomT
!= CUT_PANEL848
) &&
672 (ivideo
->SiS_Pr
.SiS_CustomT
!= CUT_PANEL856
)) {
673 if(sisbios_mode
[myindex
].xres
> xres
)
679 if(ivideo
->sisfb_fstn
) {
680 if(sisbios_mode
[myindex
].xres
== 320) {
682 switch(sisbios_mode
[myindex
].mode_no
[1]) {
683 case 0x50: myindex
= MODE_FSTN_8
; break;
684 case 0x56: myindex
= MODE_FSTN_16
; break;
685 case 0x53: return -1;
691 if(SiS_GetModeID_LCD(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
692 sisbios_mode
[myindex
].yres
, 0, ivideo
->sisfb_fstn
,
693 ivideo
->SiS_Pr
.SiS_CustomT
, xres
, yres
, ivideo
->vbflags2
) < 0x14) {
699 if(SiS_GetModeID_TV(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
700 sisbios_mode
[myindex
].yres
, 0, ivideo
->vbflags2
) < 0x14) {
706 if(SiS_GetModeID_VGA2(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
707 sisbios_mode
[myindex
].yres
, 0, ivideo
->vbflags2
) < 0x14) {
717 sisfb_search_refresh_rate(struct sis_video_info
*ivideo
, unsigned int rate
, int mode_idx
)
720 u16 xres
= sisbios_mode
[mode_idx
].xres
;
721 u16 yres
= sisbios_mode
[mode_idx
].yres
;
723 ivideo
->rate_idx
= 0;
724 while((sisfb_vrate
[i
].idx
!= 0) && (sisfb_vrate
[i
].xres
<= xres
)) {
725 if((sisfb_vrate
[i
].xres
== xres
) && (sisfb_vrate
[i
].yres
== yres
)) {
726 if(sisfb_vrate
[i
].refresh
== rate
) {
727 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
729 } else if(sisfb_vrate
[i
].refresh
> rate
) {
730 if((sisfb_vrate
[i
].refresh
- rate
) <= 3) {
731 DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
732 rate
, sisfb_vrate
[i
].refresh
);
733 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
734 ivideo
->refresh_rate
= sisfb_vrate
[i
].refresh
;
735 } else if((sisfb_vrate
[i
].idx
!= 1) &&
736 ((rate
- sisfb_vrate
[i
-1].refresh
) <= 2)) {
737 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
738 rate
, sisfb_vrate
[i
-1].refresh
);
739 ivideo
->rate_idx
= sisfb_vrate
[i
-1].idx
;
740 ivideo
->refresh_rate
= sisfb_vrate
[i
-1].refresh
;
743 } else if((rate
- sisfb_vrate
[i
].refresh
) <= 2) {
744 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
745 rate
, sisfb_vrate
[i
].refresh
);
746 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
752 if(ivideo
->rate_idx
> 0) {
753 return ivideo
->rate_idx
;
755 printk(KERN_INFO
"sisfb: Unsupported rate %d for %dx%d\n",
762 sisfb_bridgeisslave(struct sis_video_info
*ivideo
)
766 if(!(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
))
769 P1_00
= SiS_GetReg(SISPART1
, 0x00);
770 if( ((ivideo
->sisvga_engine
== SIS_300_VGA
) && (P1_00
& 0xa0) == 0x20) ||
771 ((ivideo
->sisvga_engine
== SIS_315_VGA
) && (P1_00
& 0x50) == 0x10) ) {
779 sisfballowretracecrt1(struct sis_video_info
*ivideo
)
783 temp
= SiS_GetReg(SISCR
, 0x17);
787 temp
= SiS_GetReg(SISSR
, 0x1f);
795 sisfbcheckvretracecrt1(struct sis_video_info
*ivideo
)
797 if(!sisfballowretracecrt1(ivideo
))
800 if (SiS_GetRegByte(SISINPSTAT
) & 0x08)
807 sisfbwaitretracecrt1(struct sis_video_info
*ivideo
)
811 if(!sisfballowretracecrt1(ivideo
))
815 while ((!(SiS_GetRegByte(SISINPSTAT
) & 0x08)) && --watchdog
);
817 while ((SiS_GetRegByte(SISINPSTAT
) & 0x08) && --watchdog
);
821 sisfbcheckvretracecrt2(struct sis_video_info
*ivideo
)
823 unsigned char temp
, reg
;
825 switch(ivideo
->sisvga_engine
) {
826 case SIS_300_VGA
: reg
= 0x25; break;
827 case SIS_315_VGA
: reg
= 0x30; break;
828 default: return false;
831 temp
= SiS_GetReg(SISPART1
, reg
);
839 sisfb_CheckVBRetrace(struct sis_video_info
*ivideo
)
841 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
842 if(!sisfb_bridgeisslave(ivideo
)) {
843 return sisfbcheckvretracecrt2(ivideo
);
846 return sisfbcheckvretracecrt1(ivideo
);
850 sisfb_setupvbblankflags(struct sis_video_info
*ivideo
, u32
*vcount
, u32
*hcount
)
852 u8 idx
, reg1
, reg2
, reg3
, reg4
;
855 (*vcount
) = (*hcount
) = 0;
857 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) && (!(sisfb_bridgeisslave(ivideo
)))) {
859 ret
|= (FB_VBLANK_HAVE_VSYNC
|
860 FB_VBLANK_HAVE_HBLANK
|
861 FB_VBLANK_HAVE_VBLANK
|
862 FB_VBLANK_HAVE_VCOUNT
|
863 FB_VBLANK_HAVE_HCOUNT
);
864 switch(ivideo
->sisvga_engine
) {
865 case SIS_300_VGA
: idx
= 0x25; break;
867 case SIS_315_VGA
: idx
= 0x30; break;
869 reg1
= SiS_GetReg(SISPART1
, (idx
+0)); /* 30 */
870 reg2
= SiS_GetReg(SISPART1
, (idx
+1)); /* 31 */
871 reg3
= SiS_GetReg(SISPART1
, (idx
+2)); /* 32 */
872 reg4
= SiS_GetReg(SISPART1
, (idx
+3)); /* 33 */
873 if(reg1
& 0x01) ret
|= FB_VBLANK_VBLANKING
;
874 if(reg1
& 0x02) ret
|= FB_VBLANK_VSYNCING
;
875 if(reg4
& 0x80) ret
|= FB_VBLANK_HBLANKING
;
876 (*vcount
) = reg3
| ((reg4
& 0x70) << 4);
877 (*hcount
) = reg2
| ((reg4
& 0x0f) << 8);
879 } else if(sisfballowretracecrt1(ivideo
)) {
881 ret
|= (FB_VBLANK_HAVE_VSYNC
|
882 FB_VBLANK_HAVE_VBLANK
|
883 FB_VBLANK_HAVE_VCOUNT
|
884 FB_VBLANK_HAVE_HCOUNT
);
885 reg1
= SiS_GetRegByte(SISINPSTAT
);
886 if(reg1
& 0x08) ret
|= FB_VBLANK_VSYNCING
;
887 if(reg1
& 0x01) ret
|= FB_VBLANK_VBLANKING
;
888 reg1
= SiS_GetReg(SISCR
, 0x20);
889 reg1
= SiS_GetReg(SISCR
, 0x1b);
890 reg2
= SiS_GetReg(SISCR
, 0x1c);
891 reg3
= SiS_GetReg(SISCR
, 0x1d);
892 (*vcount
) = reg2
| ((reg3
& 0x07) << 8);
893 (*hcount
) = (reg1
| ((reg3
& 0x10) << 4)) << 3;
900 sisfb_myblank(struct sis_video_info
*ivideo
, int blank
)
902 u8 sr01
, sr11
, sr1f
, cr63
=0, p2_0
, p1_13
;
903 bool backlight
= true;
906 case FB_BLANK_UNBLANK
: /* on */
915 case FB_BLANK_NORMAL
: /* blank */
924 case FB_BLANK_VSYNC_SUSPEND
: /* no vsync */
933 case FB_BLANK_HSYNC_SUSPEND
: /* no hsync */
942 case FB_BLANK_POWERDOWN
: /* off */
955 if(ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
) {
957 if( (!ivideo
->sisfb_thismonitor
.datavalid
) ||
958 ((ivideo
->sisfb_thismonitor
.datavalid
) &&
959 (ivideo
->sisfb_thismonitor
.feature
& 0xe0))) {
961 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
962 SiS_SetRegANDOR(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, 0xbf, cr63
);
965 if(!(sisfb_bridgeisslave(ivideo
))) {
966 SiS_SetRegANDOR(SISSR
, 0x01, ~0x20, sr01
);
967 SiS_SetRegANDOR(SISSR
, 0x1f, 0x3f, sr1f
);
973 if(ivideo
->currentvbflags
& CRT2_LCD
) {
975 if(ivideo
->vbflags2
& VB2_SISLVDSBRIDGE
) {
977 SiS_SiS30xBLOn(&ivideo
->SiS_Pr
);
979 SiS_SiS30xBLOff(&ivideo
->SiS_Pr
);
981 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
982 #ifdef CONFIG_FB_SIS_315
983 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
985 SiS_Chrontel701xBLOn(&ivideo
->SiS_Pr
);
987 SiS_Chrontel701xBLOff(&ivideo
->SiS_Pr
);
993 if(((ivideo
->sisvga_engine
== SIS_300_VGA
) &&
994 (ivideo
->vbflags2
& (VB2_301
|VB2_30xBDH
|VB2_LVDS
))) ||
995 ((ivideo
->sisvga_engine
== SIS_315_VGA
) &&
996 ((ivideo
->vbflags2
& (VB2_LVDS
| VB2_CHRONTEL
)) == VB2_LVDS
))) {
997 SiS_SetRegANDOR(SISSR
, 0x11, ~0x0c, sr11
);
1000 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
1001 if((ivideo
->vbflags2
& VB2_30xB
) &&
1002 (!(ivideo
->vbflags2
& VB2_30xBDH
))) {
1003 SiS_SetRegANDOR(SISPART1
, 0x13, 0x3f, p1_13
);
1005 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
1006 if((ivideo
->vbflags2
& VB2_30xB
) &&
1007 (!(ivideo
->vbflags2
& VB2_30xBDH
))) {
1008 SiS_SetRegANDOR(SISPART2
, 0x00, 0x1f, p2_0
);
1012 } else if(ivideo
->currentvbflags
& CRT2_VGA
) {
1014 if(ivideo
->vbflags2
& VB2_30xB
) {
1015 SiS_SetRegANDOR(SISPART2
, 0x00, 0x1f, p2_0
);
1023 /* ------------- Callbacks from init.c/init301.c -------------- */
1025 #ifdef CONFIG_FB_SIS_300
1027 sisfb_read_nbridge_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
)
1029 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1032 pci_read_config_dword(ivideo
->nbridge
, reg
, &val
);
1033 return (unsigned int)val
;
1037 sisfb_write_nbridge_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
, unsigned int val
)
1039 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1041 pci_write_config_dword(ivideo
->nbridge
, reg
, (u32
)val
);
1045 sisfb_read_lpc_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
)
1047 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1050 if(!ivideo
->lpcdev
) return 0;
1052 pci_read_config_dword(ivideo
->lpcdev
, reg
, &val
);
1053 return (unsigned int)val
;
1057 #ifdef CONFIG_FB_SIS_315
1059 sisfb_write_nbridge_pci_byte(struct SiS_Private
*SiS_Pr
, int reg
, unsigned char val
)
1061 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1063 pci_write_config_byte(ivideo
->nbridge
, reg
, (u8
)val
);
1067 sisfb_read_mio_pci_word(struct SiS_Private
*SiS_Pr
, int reg
)
1069 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1072 if(!ivideo
->lpcdev
) return 0;
1074 pci_read_config_word(ivideo
->lpcdev
, reg
, &val
);
1075 return (unsigned int)val
;
1079 /* ----------- FBDev related routines for all series ----------- */
1082 sisfb_get_cmap_len(const struct fb_var_screeninfo
*var
)
1084 return (var
->bits_per_pixel
== 8) ? 256 : 16;
1088 sisfb_set_vparms(struct sis_video_info
*ivideo
)
1090 switch(ivideo
->video_bpp
) {
1092 ivideo
->DstColor
= 0x0000;
1093 ivideo
->SiS310_AccelDepth
= 0x00000000;
1094 ivideo
->video_cmap_len
= 256;
1097 ivideo
->DstColor
= 0x8000;
1098 ivideo
->SiS310_AccelDepth
= 0x00010000;
1099 ivideo
->video_cmap_len
= 16;
1102 ivideo
->DstColor
= 0xC000;
1103 ivideo
->SiS310_AccelDepth
= 0x00020000;
1104 ivideo
->video_cmap_len
= 16;
1107 ivideo
->video_cmap_len
= 16;
1108 printk(KERN_ERR
"sisfb: Unsupported depth %d", ivideo
->video_bpp
);
1114 sisfb_calc_maxyres(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1116 int maxyres
= ivideo
->sisfb_mem
/ (var
->xres_virtual
* (var
->bits_per_pixel
>> 3));
1118 if(maxyres
> 32767) maxyres
= 32767;
1124 sisfb_calc_pitch(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1126 ivideo
->video_linelength
= var
->xres_virtual
* (var
->bits_per_pixel
>> 3);
1127 ivideo
->scrnpitchCRT1
= ivideo
->video_linelength
;
1128 if(!(ivideo
->currentvbflags
& CRT1_LCDA
)) {
1129 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1130 ivideo
->scrnpitchCRT1
<<= 1;
1136 sisfb_set_pitch(struct sis_video_info
*ivideo
)
1138 bool isslavemode
= false;
1139 unsigned short HDisplay1
= ivideo
->scrnpitchCRT1
>> 3;
1140 unsigned short HDisplay2
= ivideo
->video_linelength
>> 3;
1142 if(sisfb_bridgeisslave(ivideo
)) isslavemode
= true;
1144 /* We need to set pitch for CRT1 if bridge is in slave mode, too */
1145 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP1
) || (isslavemode
)) {
1146 SiS_SetReg(SISCR
, 0x13, (HDisplay1
& 0xFF));
1147 SiS_SetRegANDOR(SISSR
, 0x0E, 0xF0, (HDisplay1
>> 8));
1150 /* We must not set the pitch for CRT2 if bridge is in slave mode */
1151 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) && (!isslavemode
)) {
1152 SiS_SetRegOR(SISPART1
, ivideo
->CRT2_write_enable
, 0x01);
1153 SiS_SetReg(SISPART1
, 0x07, (HDisplay2
& 0xFF));
1154 SiS_SetRegANDOR(SISPART1
, 0x09, 0xF0, (HDisplay2
>> 8));
1159 sisfb_bpp_to_var(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1161 ivideo
->video_cmap_len
= sisfb_get_cmap_len(var
);
1163 switch(var
->bits_per_pixel
) {
1165 var
->red
.offset
= var
->green
.offset
= var
->blue
.offset
= 0;
1166 var
->red
.length
= var
->green
.length
= var
->blue
.length
= 8;
1169 var
->red
.offset
= 11;
1170 var
->red
.length
= 5;
1171 var
->green
.offset
= 5;
1172 var
->green
.length
= 6;
1173 var
->blue
.offset
= 0;
1174 var
->blue
.length
= 5;
1175 var
->transp
.offset
= 0;
1176 var
->transp
.length
= 0;
1179 var
->red
.offset
= 16;
1180 var
->red
.length
= 8;
1181 var
->green
.offset
= 8;
1182 var
->green
.length
= 8;
1183 var
->blue
.offset
= 0;
1184 var
->blue
.length
= 8;
1185 var
->transp
.offset
= 24;
1186 var
->transp
.length
= 8;
1192 sisfb_set_mode(struct sis_video_info
*ivideo
, int clrscrn
)
1194 unsigned short modeno
= ivideo
->mode_no
;
1196 /* >=2.6.12's fbcon clears the screen anyway */
1199 SiS_SetReg(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1201 sisfb_pre_setmode(ivideo
);
1203 if(!SiSSetMode(&ivideo
->SiS_Pr
, modeno
)) {
1204 printk(KERN_ERR
"sisfb: Setting mode[0x%x] failed\n", ivideo
->mode_no
);
1208 SiS_SetReg(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1210 sisfb_post_setmode(ivideo
);
1217 sisfb_do_set_var(struct fb_var_screeninfo
*var
, int isactive
, struct fb_info
*info
)
1219 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1220 unsigned int htotal
= 0, vtotal
= 0;
1221 unsigned int drate
= 0, hrate
= 0;
1222 int found_mode
= 0, ret
;
1226 htotal
= var
->left_margin
+ var
->xres
+ var
->right_margin
+ var
->hsync_len
;
1228 vtotal
= var
->upper_margin
+ var
->lower_margin
+ var
->vsync_len
;
1230 pixclock
= var
->pixclock
;
1232 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
) {
1233 vtotal
+= var
->yres
;
1235 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1236 vtotal
+= var
->yres
;
1238 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1239 vtotal
+= var
->yres
;
1241 } else vtotal
+= var
->yres
;
1243 if(!(htotal
) || !(vtotal
)) {
1244 DPRINTK("sisfb: Invalid 'var' information\n");
1248 if(pixclock
&& htotal
&& vtotal
) {
1249 drate
= 1000000000 / pixclock
;
1250 hrate
= (drate
* 1000) / htotal
;
1251 ivideo
->refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1253 ivideo
->refresh_rate
= 60;
1256 old_mode
= ivideo
->sisfb_mode_idx
;
1257 ivideo
->sisfb_mode_idx
= 0;
1259 while( (sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[0] != 0) &&
1260 (sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
<= var
->xres
) ) {
1261 if( (sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
== var
->xres
) &&
1262 (sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
== var
->yres
) &&
1263 (sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
== var
->bits_per_pixel
)) {
1264 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
1268 ivideo
->sisfb_mode_idx
++;
1272 ivideo
->sisfb_mode_idx
= sisfb_validate_mode(ivideo
,
1273 ivideo
->sisfb_mode_idx
, ivideo
->currentvbflags
);
1275 ivideo
->sisfb_mode_idx
= -1;
1278 if(ivideo
->sisfb_mode_idx
< 0) {
1279 printk(KERN_ERR
"sisfb: Mode %dx%dx%d not supported\n", var
->xres
,
1280 var
->yres
, var
->bits_per_pixel
);
1281 ivideo
->sisfb_mode_idx
= old_mode
;
1285 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
1287 if(sisfb_search_refresh_rate(ivideo
, ivideo
->refresh_rate
, ivideo
->sisfb_mode_idx
) == 0) {
1288 ivideo
->rate_idx
= sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
;
1289 ivideo
->refresh_rate
= 60;
1293 /* If acceleration to be used? Need to know
1294 * before pre/post_set_mode()
1297 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
1298 #ifdef STUPID_ACCELF_TEXT_SHIT
1299 if(var
->accel_flags
& FB_ACCELF_TEXT
) {
1300 info
->flags
&= ~FBINFO_HWACCEL_DISABLED
;
1302 info
->flags
|= FBINFO_HWACCEL_DISABLED
;
1305 if(!(info
->flags
& FBINFO_HWACCEL_DISABLED
)) ivideo
->accel
= -1;
1307 if(var
->accel_flags
& FB_ACCELF_TEXT
) ivideo
->accel
= -1;
1310 if((ret
= sisfb_set_mode(ivideo
, 1))) {
1314 ivideo
->video_bpp
= sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
;
1315 ivideo
->video_width
= sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
;
1316 ivideo
->video_height
= sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
;
1318 sisfb_calc_pitch(ivideo
, var
);
1319 sisfb_set_pitch(ivideo
);
1321 sisfb_set_vparms(ivideo
);
1323 ivideo
->current_width
= ivideo
->video_width
;
1324 ivideo
->current_height
= ivideo
->video_height
;
1325 ivideo
->current_bpp
= ivideo
->video_bpp
;
1326 ivideo
->current_htotal
= htotal
;
1327 ivideo
->current_vtotal
= vtotal
;
1328 ivideo
->current_linelength
= ivideo
->video_linelength
;
1329 ivideo
->current_pixclock
= var
->pixclock
;
1330 ivideo
->current_refresh_rate
= ivideo
->refresh_rate
;
1331 ivideo
->sisfb_lastrates
[ivideo
->mode_no
] = ivideo
->refresh_rate
;
1338 sisfb_set_base_CRT1(struct sis_video_info
*ivideo
, unsigned int base
)
1340 SiS_SetReg(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1342 SiS_SetReg(SISCR
, 0x0D, base
& 0xFF);
1343 SiS_SetReg(SISCR
, 0x0C, (base
>> 8) & 0xFF);
1344 SiS_SetReg(SISSR
, 0x0D, (base
>> 16) & 0xFF);
1345 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
1346 SiS_SetRegANDOR(SISSR
, 0x37, 0xFE, (base
>> 24) & 0x01);
1351 sisfb_set_base_CRT2(struct sis_video_info
*ivideo
, unsigned int base
)
1353 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
1354 SiS_SetRegOR(SISPART1
, ivideo
->CRT2_write_enable
, 0x01);
1355 SiS_SetReg(SISPART1
, 0x06, (base
& 0xFF));
1356 SiS_SetReg(SISPART1
, 0x05, ((base
>> 8) & 0xFF));
1357 SiS_SetReg(SISPART1
, 0x04, ((base
>> 16) & 0xFF));
1358 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
1359 SiS_SetRegANDOR(SISPART1
, 0x02, 0x7F, ((base
>> 24) & 0x01) << 7);
1365 sisfb_pan_var(struct sis_video_info
*ivideo
, struct fb_info
*info
,
1366 struct fb_var_screeninfo
*var
)
1368 ivideo
->current_base
= var
->yoffset
* info
->var
.xres_virtual
1371 /* calculate base bpp dep. */
1372 switch (info
->var
.bits_per_pixel
) {
1376 ivideo
->current_base
>>= 1;
1380 ivideo
->current_base
>>= 2;
1384 ivideo
->current_base
+= (ivideo
->video_offset
>> 2);
1386 sisfb_set_base_CRT1(ivideo
, ivideo
->current_base
);
1387 sisfb_set_base_CRT2(ivideo
, ivideo
->current_base
);
1393 sisfb_open(struct fb_info
*info
, int user
)
1399 sisfb_release(struct fb_info
*info
, int user
)
1405 sisfb_setcolreg(unsigned regno
, unsigned red
, unsigned green
, unsigned blue
,
1406 unsigned transp
, struct fb_info
*info
)
1408 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1410 if(regno
>= sisfb_get_cmap_len(&info
->var
))
1413 switch(info
->var
.bits_per_pixel
) {
1415 SiS_SetRegByte(SISDACA
, regno
);
1416 SiS_SetRegByte(SISDACD
, (red
>> 10));
1417 SiS_SetRegByte(SISDACD
, (green
>> 10));
1418 SiS_SetRegByte(SISDACD
, (blue
>> 10));
1419 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
1420 SiS_SetRegByte(SISDAC2A
, regno
);
1421 SiS_SetRegByte(SISDAC2D
, (red
>> 8));
1422 SiS_SetRegByte(SISDAC2D
, (green
>> 8));
1423 SiS_SetRegByte(SISDAC2D
, (blue
>> 8));
1430 ((u32
*)(info
->pseudo_palette
))[regno
] =
1432 ((green
& 0xfc00) >> 5) |
1433 ((blue
& 0xf800) >> 11);
1442 ((u32
*)(info
->pseudo_palette
))[regno
] =
1443 (red
<< 16) | (green
<< 8) | (blue
);
1450 sisfb_set_par(struct fb_info
*info
)
1454 if((err
= sisfb_do_set_var(&info
->var
, 1, info
)))
1457 sisfb_get_fix(&info
->fix
, -1, info
);
1463 sisfb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
1465 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1466 unsigned int htotal
= 0, vtotal
= 0, myrateindex
= 0;
1467 unsigned int drate
= 0, hrate
= 0, maxyres
;
1469 int refresh_rate
, search_idx
, tidx
;
1470 bool recalc_clock
= false;
1473 htotal
= var
->left_margin
+ var
->xres
+ var
->right_margin
+ var
->hsync_len
;
1475 vtotal
= var
->upper_margin
+ var
->lower_margin
+ var
->vsync_len
;
1477 pixclock
= var
->pixclock
;
1479 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
) {
1480 vtotal
+= var
->yres
;
1482 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1483 vtotal
+= var
->yres
;
1485 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1486 vtotal
+= var
->yres
;
1489 vtotal
+= var
->yres
;
1491 if(!(htotal
) || !(vtotal
)) {
1492 SISFAIL("sisfb: no valid timing data");
1496 while( (sisbios_mode
[search_idx
].mode_no
[0] != 0) &&
1497 (sisbios_mode
[search_idx
].xres
<= var
->xres
) ) {
1498 if( (sisbios_mode
[search_idx
].xres
== var
->xres
) &&
1499 (sisbios_mode
[search_idx
].yres
== var
->yres
) &&
1500 (sisbios_mode
[search_idx
].bpp
== var
->bits_per_pixel
)) {
1501 if((tidx
= sisfb_validate_mode(ivideo
, search_idx
,
1502 ivideo
->currentvbflags
)) > 0) {
1513 while(sisbios_mode
[search_idx
].mode_no
[0] != 0) {
1514 if( (var
->xres
<= sisbios_mode
[search_idx
].xres
) &&
1515 (var
->yres
<= sisbios_mode
[search_idx
].yres
) &&
1516 (var
->bits_per_pixel
== sisbios_mode
[search_idx
].bpp
) ) {
1517 if((tidx
= sisfb_validate_mode(ivideo
,search_idx
,
1518 ivideo
->currentvbflags
)) > 0) {
1528 "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
1529 var
->xres
, var
->yres
, var
->bits_per_pixel
,
1530 sisbios_mode
[search_idx
].xres
,
1531 sisbios_mode
[search_idx
].yres
,
1532 var
->bits_per_pixel
);
1533 var
->xres
= sisbios_mode
[search_idx
].xres
;
1534 var
->yres
= sisbios_mode
[search_idx
].yres
;
1537 "sisfb: Failed to find supported mode near %dx%dx%d\n",
1538 var
->xres
, var
->yres
, var
->bits_per_pixel
);
1543 if( ((ivideo
->vbflags2
& VB2_LVDS
) ||
1544 ((ivideo
->vbflags2
& VB2_30xBDH
) && (ivideo
->currentvbflags
& CRT2_LCD
))) &&
1545 (var
->bits_per_pixel
== 8) ) {
1546 /* Slave modes on LVDS and 301B-DH */
1548 recalc_clock
= true;
1549 } else if( (ivideo
->current_htotal
== htotal
) &&
1550 (ivideo
->current_vtotal
== vtotal
) &&
1551 (ivideo
->current_pixclock
== pixclock
) ) {
1552 /* x=x & y=y & c=c -> assume depth change */
1553 drate
= 1000000000 / pixclock
;
1554 hrate
= (drate
* 1000) / htotal
;
1555 refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1556 } else if( ( (ivideo
->current_htotal
!= htotal
) ||
1557 (ivideo
->current_vtotal
!= vtotal
) ) &&
1558 (ivideo
->current_pixclock
== var
->pixclock
) ) {
1559 /* x!=x | y!=y & c=c -> invalid pixclock */
1560 if(ivideo
->sisfb_lastrates
[sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
]]) {
1562 ivideo
->sisfb_lastrates
[sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
]];
1563 } else if(ivideo
->sisfb_parm_rate
!= -1) {
1564 /* Sic, sisfb_parm_rate - want to know originally desired rate here */
1565 refresh_rate
= ivideo
->sisfb_parm_rate
;
1569 recalc_clock
= true;
1570 } else if((pixclock
) && (htotal
) && (vtotal
)) {
1571 drate
= 1000000000 / pixclock
;
1572 hrate
= (drate
* 1000) / htotal
;
1573 refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1574 } else if(ivideo
->current_refresh_rate
) {
1575 refresh_rate
= ivideo
->current_refresh_rate
;
1576 recalc_clock
= true;
1579 recalc_clock
= true;
1582 myrateindex
= sisfb_search_refresh_rate(ivideo
, refresh_rate
, search_idx
);
1584 /* Eventually recalculate timing and clock */
1586 if(!myrateindex
) myrateindex
= sisbios_mode
[search_idx
].rate_idx
;
1587 var
->pixclock
= (u32
) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo
->SiS_Pr
,
1588 sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
],
1590 sisfb_mode_rate_to_ddata(&ivideo
->SiS_Pr
,
1591 sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
],
1593 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1594 var
->pixclock
<<= 1;
1598 if(ivideo
->sisfb_thismonitor
.datavalid
) {
1599 if(!sisfb_verify_rate(ivideo
, &ivideo
->sisfb_thismonitor
, search_idx
,
1600 myrateindex
, refresh_rate
)) {
1602 "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1606 /* Adapt RGB settings */
1607 sisfb_bpp_to_var(ivideo
, var
);
1609 if(var
->xres
> var
->xres_virtual
)
1610 var
->xres_virtual
= var
->xres
;
1612 if(ivideo
->sisfb_ypan
) {
1613 maxyres
= sisfb_calc_maxyres(ivideo
, var
);
1614 if(ivideo
->sisfb_max
) {
1615 var
->yres_virtual
= maxyres
;
1617 if(var
->yres_virtual
> maxyres
) {
1618 var
->yres_virtual
= maxyres
;
1621 if(var
->yres_virtual
<= var
->yres
) {
1622 var
->yres_virtual
= var
->yres
;
1625 if(var
->yres
!= var
->yres_virtual
) {
1626 var
->yres_virtual
= var
->yres
;
1632 /* Truncate offsets to maximum if too high */
1633 if(var
->xoffset
> var
->xres_virtual
- var
->xres
) {
1634 var
->xoffset
= var
->xres_virtual
- var
->xres
- 1;
1637 if(var
->yoffset
> var
->yres_virtual
- var
->yres
) {
1638 var
->yoffset
= var
->yres_virtual
- var
->yres
- 1;
1641 /* Set everything else to 0 */
1642 var
->red
.msb_right
=
1643 var
->green
.msb_right
=
1644 var
->blue
.msb_right
=
1645 var
->transp
.offset
=
1646 var
->transp
.length
=
1647 var
->transp
.msb_right
= 0;
1653 sisfb_pan_display(struct fb_var_screeninfo
*var
, struct fb_info
* info
)
1655 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1658 if (var
->vmode
& FB_VMODE_YWRAP
)
1661 if (var
->xoffset
+ info
->var
.xres
> info
->var
.xres_virtual
||
1662 var
->yoffset
+ info
->var
.yres
> info
->var
.yres_virtual
)
1665 err
= sisfb_pan_var(ivideo
, info
, var
);
1669 info
->var
.xoffset
= var
->xoffset
;
1670 info
->var
.yoffset
= var
->yoffset
;
1676 sisfb_blank(int blank
, struct fb_info
*info
)
1678 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1680 return sisfb_myblank(ivideo
, blank
);
1683 /* ----------- FBDev related routines for all series ---------- */
1685 static int sisfb_ioctl(struct fb_info
*info
, unsigned int cmd
,
1688 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1689 struct sis_memreq sismemreq
;
1690 struct fb_vblank sisvbblank
;
1695 u32 __user
*argp
= (u32 __user
*)arg
;
1699 if(!capable(CAP_SYS_RAWIO
))
1702 if(copy_from_user(&sismemreq
, (void __user
*)arg
, sizeof(sismemreq
)))
1705 sis_malloc(&sismemreq
);
1707 if(copy_to_user((void __user
*)arg
, &sismemreq
, sizeof(sismemreq
))) {
1708 sis_free((u32
)sismemreq
.offset
);
1714 if(!capable(CAP_SYS_RAWIO
))
1717 if(get_user(gpu32
, argp
))
1723 case FBIOGET_VBLANK
:
1725 memset(&sisvbblank
, 0, sizeof(struct fb_vblank
));
1727 sisvbblank
.count
= 0;
1728 sisvbblank
.flags
= sisfb_setupvbblankflags(ivideo
, &sisvbblank
.vcount
, &sisvbblank
.hcount
);
1730 if(copy_to_user((void __user
*)arg
, &sisvbblank
, sizeof(sisvbblank
)))
1735 case SISFB_GET_INFO_SIZE
:
1736 return put_user(sizeof(struct sisfb_info
), argp
);
1738 case SISFB_GET_INFO_OLD
:
1739 if(ivideo
->warncount
++ < 10)
1741 "sisfb: Deprecated ioctl call received - update your application!\n");
1743 case SISFB_GET_INFO
: /* For communication with X driver */
1744 ivideo
->sisfb_infoblock
.sisfb_id
= SISFB_ID
;
1745 ivideo
->sisfb_infoblock
.sisfb_version
= VER_MAJOR
;
1746 ivideo
->sisfb_infoblock
.sisfb_revision
= VER_MINOR
;
1747 ivideo
->sisfb_infoblock
.sisfb_patchlevel
= VER_LEVEL
;
1748 ivideo
->sisfb_infoblock
.chip_id
= ivideo
->chip_id
;
1749 ivideo
->sisfb_infoblock
.sisfb_pci_vendor
= ivideo
->chip_vendor
;
1750 ivideo
->sisfb_infoblock
.memory
= ivideo
->video_size
/ 1024;
1751 ivideo
->sisfb_infoblock
.heapstart
= ivideo
->heapstart
/ 1024;
1752 if(ivideo
->modechanged
) {
1753 ivideo
->sisfb_infoblock
.fbvidmode
= ivideo
->mode_no
;
1755 ivideo
->sisfb_infoblock
.fbvidmode
= ivideo
->modeprechange
;
1757 ivideo
->sisfb_infoblock
.sisfb_caps
= ivideo
->caps
;
1758 ivideo
->sisfb_infoblock
.sisfb_tqlen
= ivideo
->cmdQueueSize
/ 1024;
1759 ivideo
->sisfb_infoblock
.sisfb_pcibus
= ivideo
->pcibus
;
1760 ivideo
->sisfb_infoblock
.sisfb_pcislot
= ivideo
->pcislot
;
1761 ivideo
->sisfb_infoblock
.sisfb_pcifunc
= ivideo
->pcifunc
;
1762 ivideo
->sisfb_infoblock
.sisfb_lcdpdc
= ivideo
->detectedpdc
;
1763 ivideo
->sisfb_infoblock
.sisfb_lcdpdca
= ivideo
->detectedpdca
;
1764 ivideo
->sisfb_infoblock
.sisfb_lcda
= ivideo
->detectedlcda
;
1765 ivideo
->sisfb_infoblock
.sisfb_vbflags
= ivideo
->vbflags
;
1766 ivideo
->sisfb_infoblock
.sisfb_currentvbflags
= ivideo
->currentvbflags
;
1767 ivideo
->sisfb_infoblock
.sisfb_scalelcd
= ivideo
->SiS_Pr
.UsePanelScaler
;
1768 ivideo
->sisfb_infoblock
.sisfb_specialtiming
= ivideo
->SiS_Pr
.SiS_CustomT
;
1769 ivideo
->sisfb_infoblock
.sisfb_haveemi
= ivideo
->SiS_Pr
.HaveEMI
? 1 : 0;
1770 ivideo
->sisfb_infoblock
.sisfb_haveemilcd
= ivideo
->SiS_Pr
.HaveEMILCD
? 1 : 0;
1771 ivideo
->sisfb_infoblock
.sisfb_emi30
= ivideo
->SiS_Pr
.EMI_30
;
1772 ivideo
->sisfb_infoblock
.sisfb_emi31
= ivideo
->SiS_Pr
.EMI_31
;
1773 ivideo
->sisfb_infoblock
.sisfb_emi32
= ivideo
->SiS_Pr
.EMI_32
;
1774 ivideo
->sisfb_infoblock
.sisfb_emi33
= ivideo
->SiS_Pr
.EMI_33
;
1775 ivideo
->sisfb_infoblock
.sisfb_tvxpos
= (u16
)(ivideo
->tvxpos
+ 32);
1776 ivideo
->sisfb_infoblock
.sisfb_tvypos
= (u16
)(ivideo
->tvypos
+ 32);
1777 ivideo
->sisfb_infoblock
.sisfb_heapsize
= ivideo
->sisfb_heap_size
/ 1024;
1778 ivideo
->sisfb_infoblock
.sisfb_videooffset
= ivideo
->video_offset
;
1779 ivideo
->sisfb_infoblock
.sisfb_curfstn
= ivideo
->curFSTN
;
1780 ivideo
->sisfb_infoblock
.sisfb_curdstn
= ivideo
->curDSTN
;
1781 ivideo
->sisfb_infoblock
.sisfb_vbflags2
= ivideo
->vbflags2
;
1782 ivideo
->sisfb_infoblock
.sisfb_can_post
= ivideo
->sisfb_can_post
? 1 : 0;
1783 ivideo
->sisfb_infoblock
.sisfb_card_posted
= ivideo
->sisfb_card_posted
? 1 : 0;
1784 ivideo
->sisfb_infoblock
.sisfb_was_boot_device
= ivideo
->sisfb_was_boot_device
? 1 : 0;
1786 if(copy_to_user((void __user
*)arg
, &ivideo
->sisfb_infoblock
,
1787 sizeof(ivideo
->sisfb_infoblock
)))
1792 case SISFB_GET_VBRSTATUS_OLD
:
1793 if(ivideo
->warncount
++ < 10)
1795 "sisfb: Deprecated ioctl call received - update your application!\n");
1797 case SISFB_GET_VBRSTATUS
:
1798 if(sisfb_CheckVBRetrace(ivideo
))
1799 return put_user((u32
)1, argp
);
1801 return put_user((u32
)0, argp
);
1803 case SISFB_GET_AUTOMAXIMIZE_OLD
:
1804 if(ivideo
->warncount
++ < 10)
1806 "sisfb: Deprecated ioctl call received - update your application!\n");
1808 case SISFB_GET_AUTOMAXIMIZE
:
1809 if(ivideo
->sisfb_max
)
1810 return put_user((u32
)1, argp
);
1812 return put_user((u32
)0, argp
);
1814 case SISFB_SET_AUTOMAXIMIZE_OLD
:
1815 if(ivideo
->warncount
++ < 10)
1817 "sisfb: Deprecated ioctl call received - update your application!\n");
1819 case SISFB_SET_AUTOMAXIMIZE
:
1820 if(get_user(gpu32
, argp
))
1823 ivideo
->sisfb_max
= (gpu32
) ? 1 : 0;
1826 case SISFB_SET_TVPOSOFFSET
:
1827 if(get_user(gpu32
, argp
))
1830 sisfb_set_TVxposoffset(ivideo
, ((int)(gpu32
>> 16)) - 32);
1831 sisfb_set_TVyposoffset(ivideo
, ((int)(gpu32
& 0xffff)) - 32);
1834 case SISFB_GET_TVPOSOFFSET
:
1835 return put_user((u32
)(((ivideo
->tvxpos
+32)<<16)|((ivideo
->tvypos
+32)&0xffff)),
1839 if(copy_from_user(&ivideo
->sisfb_command
, (void __user
*)arg
,
1840 sizeof(struct sisfb_cmd
)))
1843 sisfb_handle_command(ivideo
, &ivideo
->sisfb_command
);
1845 if(copy_to_user((void __user
*)arg
, &ivideo
->sisfb_command
,
1846 sizeof(struct sisfb_cmd
)))
1851 case SISFB_SET_LOCK
:
1852 if(get_user(gpu32
, argp
))
1855 ivideo
->sisfblocked
= (gpu32
) ? 1 : 0;
1859 #ifdef SIS_NEW_CONFIG_COMPAT
1860 return -ENOIOCTLCMD
;
1869 sisfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
, struct fb_info
*info
)
1871 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1873 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
1875 strlcpy(fix
->id
, ivideo
->myid
, sizeof(fix
->id
));
1877 mutex_lock(&info
->mm_lock
);
1878 fix
->smem_start
= ivideo
->video_base
+ ivideo
->video_offset
;
1879 fix
->smem_len
= ivideo
->sisfb_mem
;
1880 mutex_unlock(&info
->mm_lock
);
1881 fix
->type
= FB_TYPE_PACKED_PIXELS
;
1883 fix
->visual
= (ivideo
->video_bpp
== 8) ? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_TRUECOLOR
;
1885 fix
->ypanstep
= (ivideo
->sisfb_ypan
) ? 1 : 0;
1887 fix
->line_length
= ivideo
->video_linelength
;
1888 fix
->mmio_start
= ivideo
->mmio_base
;
1889 fix
->mmio_len
= ivideo
->mmio_size
;
1890 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
1891 fix
->accel
= FB_ACCEL_SIS_GLAMOUR
;
1892 } else if((ivideo
->chip
== SIS_330
) ||
1893 (ivideo
->chip
== SIS_760
) ||
1894 (ivideo
->chip
== SIS_761
)) {
1895 fix
->accel
= FB_ACCEL_SIS_XABRE
;
1896 } else if(ivideo
->chip
== XGI_20
) {
1897 fix
->accel
= FB_ACCEL_XGI_VOLARI_Z
;
1898 } else if(ivideo
->chip
>= XGI_40
) {
1899 fix
->accel
= FB_ACCEL_XGI_VOLARI_V
;
1901 fix
->accel
= FB_ACCEL_SIS_GLAMOUR_2
;
1907 /* ---------------- fb_ops structures ----------------- */
1909 static const struct fb_ops sisfb_ops
= {
1910 .owner
= THIS_MODULE
,
1911 .fb_open
= sisfb_open
,
1912 .fb_release
= sisfb_release
,
1913 .fb_check_var
= sisfb_check_var
,
1914 .fb_set_par
= sisfb_set_par
,
1915 .fb_setcolreg
= sisfb_setcolreg
,
1916 .fb_pan_display
= sisfb_pan_display
,
1917 .fb_blank
= sisfb_blank
,
1918 .fb_fillrect
= fbcon_sis_fillrect
,
1919 .fb_copyarea
= fbcon_sis_copyarea
,
1920 .fb_imageblit
= cfb_imageblit
,
1921 .fb_sync
= fbcon_sis_sync
,
1922 #ifdef SIS_NEW_CONFIG_COMPAT
1923 .fb_compat_ioctl
= sisfb_ioctl
,
1925 .fb_ioctl
= sisfb_ioctl
1928 /* ---------------- Chip generation dependent routines ---------------- */
1930 static struct pci_dev
*sisfb_get_northbridge(int basechipid
)
1932 struct pci_dev
*pdev
= NULL
;
1933 int nbridgenum
, nbridgeidx
, i
;
1934 static const unsigned short nbridgeids
[] = {
1935 PCI_DEVICE_ID_SI_540
, /* for SiS 540 VGA */
1936 PCI_DEVICE_ID_SI_630
, /* for SiS 630/730 VGA */
1937 PCI_DEVICE_ID_SI_730
,
1938 PCI_DEVICE_ID_SI_550
, /* for SiS 550 VGA */
1939 PCI_DEVICE_ID_SI_650
, /* for SiS 650/651/740 VGA */
1940 PCI_DEVICE_ID_SI_651
,
1941 PCI_DEVICE_ID_SI_740
,
1942 PCI_DEVICE_ID_SI_661
, /* for SiS 661/741/660/760/761 VGA */
1943 PCI_DEVICE_ID_SI_741
,
1944 PCI_DEVICE_ID_SI_660
,
1945 PCI_DEVICE_ID_SI_760
,
1946 PCI_DEVICE_ID_SI_761
1949 switch(basechipid
) {
1950 #ifdef CONFIG_FB_SIS_300
1951 case SIS_540
: nbridgeidx
= 0; nbridgenum
= 1; break;
1952 case SIS_630
: nbridgeidx
= 1; nbridgenum
= 2; break;
1954 #ifdef CONFIG_FB_SIS_315
1955 case SIS_550
: nbridgeidx
= 3; nbridgenum
= 1; break;
1956 case SIS_650
: nbridgeidx
= 4; nbridgenum
= 3; break;
1957 case SIS_660
: nbridgeidx
= 7; nbridgenum
= 5; break;
1959 default: return NULL
;
1961 for(i
= 0; i
< nbridgenum
; i
++) {
1962 if((pdev
= pci_get_device(PCI_VENDOR_ID_SI
,
1963 nbridgeids
[nbridgeidx
+i
], NULL
)))
1969 static int sisfb_get_dram_size(struct sis_video_info
*ivideo
)
1971 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1975 ivideo
->video_size
= 0;
1976 ivideo
->UMAsize
= ivideo
->LFBsize
= 0;
1978 switch(ivideo
->chip
) {
1979 #ifdef CONFIG_FB_SIS_300
1981 reg
= SiS_GetReg(SISSR
, 0x14);
1982 ivideo
->video_size
= ((reg
& 0x3F) + 1) << 20;
1987 if(!ivideo
->nbridge
)
1989 pci_read_config_byte(ivideo
->nbridge
, 0x63, ®
);
1990 ivideo
->video_size
= 1 << (((reg
& 0x70) >> 4) + 21);
1993 #ifdef CONFIG_FB_SIS_315
1997 reg
= SiS_GetReg(SISSR
, 0x14);
1998 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
1999 switch((reg
>> 2) & 0x03) {
2002 ivideo
->video_size
<<= 1;
2005 ivideo
->video_size
+= (ivideo
->video_size
/2);
2009 reg
= SiS_GetReg(SISSR
, 0x14);
2010 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
2011 if(reg
& 0x0c) ivideo
->video_size
<<= 1;
2016 reg
= SiS_GetReg(SISSR
, 0x14);
2017 ivideo
->video_size
= (((reg
& 0x3f) + 1) << 2) << 20;
2021 reg
= SiS_GetReg(SISCR
, 0x79);
2022 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
2027 reg
= SiS_GetReg(SISCR
, 0x79);
2028 reg
= (reg
& 0xf0) >> 4;
2030 ivideo
->video_size
= (1 << reg
) << 20;
2031 ivideo
->UMAsize
= ivideo
->video_size
;
2033 reg
= SiS_GetReg(SISCR
, 0x78);
2037 ivideo
->LFBsize
= (32 << 20);
2039 ivideo
->LFBsize
= (64 << 20);
2041 ivideo
->video_size
+= ivideo
->LFBsize
;
2047 reg
= SiS_GetReg(SISSR
, 0x14);
2048 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
2049 if(ivideo
->chip
!= XGI_20
) {
2050 reg
= (reg
& 0x0c) >> 2;
2051 if(ivideo
->revision_id
== 2) {
2052 if(reg
& 0x01) reg
= 0x02;
2055 if(reg
== 0x02) ivideo
->video_size
<<= 1;
2056 else if(reg
== 0x03) ivideo
->video_size
<<= 2;
2066 /* -------------- video bridge device detection --------------- */
2068 static void sisfb_detect_VB_connect(struct sis_video_info
*ivideo
)
2072 /* No CRT2 on XGI Z7 */
2073 if(ivideo
->chip
== XGI_20
) {
2074 ivideo
->sisfb_crt1off
= 0;
2078 #ifdef CONFIG_FB_SIS_300
2079 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2080 temp
= SiS_GetReg(SISSR
, 0x17);
2081 if((temp
& 0x0F) && (ivideo
->chip
!= SIS_300
)) {
2082 /* PAL/NTSC is stored on SR16 on such machines */
2083 if(!(ivideo
->vbflags
& (TV_PAL
| TV_NTSC
| TV_PALM
| TV_PALN
))) {
2084 temp
= SiS_GetReg(SISSR
, 0x16);
2086 ivideo
->vbflags
|= TV_PAL
;
2088 ivideo
->vbflags
|= TV_NTSC
;
2094 cr32
= SiS_GetReg(SISCR
, 0x32);
2096 if(cr32
& SIS_CRT1
) {
2097 ivideo
->sisfb_crt1off
= 0;
2099 ivideo
->sisfb_crt1off
= (cr32
& 0xDF) ? 1 : 0;
2102 ivideo
->vbflags
&= ~(CRT2_TV
| CRT2_LCD
| CRT2_VGA
);
2104 if(cr32
& SIS_VB_TV
) ivideo
->vbflags
|= CRT2_TV
;
2105 if(cr32
& SIS_VB_LCD
) ivideo
->vbflags
|= CRT2_LCD
;
2106 if(cr32
& SIS_VB_CRT2
) ivideo
->vbflags
|= CRT2_VGA
;
2108 /* Check given parms for hardware compatibility.
2109 * (Cannot do this in the search_xx routines since we don't
2110 * know what hardware we are running on then)
2113 if(ivideo
->chip
!= SIS_550
) {
2114 ivideo
->sisfb_dstn
= ivideo
->sisfb_fstn
= 0;
2117 if(ivideo
->sisfb_tvplug
!= -1) {
2118 if( (ivideo
->sisvga_engine
!= SIS_315_VGA
) ||
2119 (!(ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) ) {
2120 if(ivideo
->sisfb_tvplug
& TV_YPBPR
) {
2121 ivideo
->sisfb_tvplug
= -1;
2122 printk(KERN_ERR
"sisfb: YPbPr not supported\n");
2126 if(ivideo
->sisfb_tvplug
!= -1) {
2127 if( (ivideo
->sisvga_engine
!= SIS_315_VGA
) ||
2128 (!(ivideo
->vbflags2
& VB2_SISHIVISIONBRIDGE
)) ) {
2129 if(ivideo
->sisfb_tvplug
& TV_HIVISION
) {
2130 ivideo
->sisfb_tvplug
= -1;
2131 printk(KERN_ERR
"sisfb: HiVision not supported\n");
2135 if(ivideo
->sisfb_tvstd
!= -1) {
2136 if( (!(ivideo
->vbflags2
& VB2_SISBRIDGE
)) &&
2137 (!((ivideo
->sisvga_engine
== SIS_315_VGA
) &&
2138 (ivideo
->vbflags2
& VB2_CHRONTEL
))) ) {
2139 if(ivideo
->sisfb_tvstd
& (TV_PALM
| TV_PALN
| TV_NTSCJ
)) {
2140 ivideo
->sisfb_tvstd
= -1;
2141 printk(KERN_ERR
"sisfb: PALM/PALN/NTSCJ not supported\n");
2146 /* Detect/set TV plug & type */
2147 if(ivideo
->sisfb_tvplug
!= -1) {
2148 ivideo
->vbflags
|= ivideo
->sisfb_tvplug
;
2150 if(cr32
& SIS_VB_YPBPR
) ivideo
->vbflags
|= (TV_YPBPR
|TV_YPBPR525I
); /* default: 480i */
2151 else if(cr32
& SIS_VB_HIVISION
) ivideo
->vbflags
|= TV_HIVISION
;
2152 else if(cr32
& SIS_VB_SCART
) ivideo
->vbflags
|= TV_SCART
;
2154 if(cr32
& SIS_VB_SVIDEO
) ivideo
->vbflags
|= TV_SVIDEO
;
2155 if(cr32
& SIS_VB_COMPOSITE
) ivideo
->vbflags
|= TV_AVIDEO
;
2159 if(!(ivideo
->vbflags
& (TV_YPBPR
| TV_HIVISION
))) {
2160 if(ivideo
->sisfb_tvstd
!= -1) {
2161 ivideo
->vbflags
&= ~(TV_NTSC
| TV_PAL
| TV_PALM
| TV_PALN
| TV_NTSCJ
);
2162 ivideo
->vbflags
|= ivideo
->sisfb_tvstd
;
2164 if(ivideo
->vbflags
& TV_SCART
) {
2165 ivideo
->vbflags
&= ~(TV_NTSC
| TV_PALM
| TV_PALN
| TV_NTSCJ
);
2166 ivideo
->vbflags
|= TV_PAL
;
2168 if(!(ivideo
->vbflags
& (TV_PAL
| TV_NTSC
| TV_PALM
| TV_PALN
| TV_NTSCJ
))) {
2169 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2170 temp
= SiS_GetReg(SISSR
, 0x38);
2171 if(temp
& 0x01) ivideo
->vbflags
|= TV_PAL
;
2172 else ivideo
->vbflags
|= TV_NTSC
;
2173 } else if((ivideo
->chip
<= SIS_315PRO
) || (ivideo
->chip
>= SIS_330
)) {
2174 temp
= SiS_GetReg(SISSR
, 0x38);
2175 if(temp
& 0x01) ivideo
->vbflags
|= TV_PAL
;
2176 else ivideo
->vbflags
|= TV_NTSC
;
2178 temp
= SiS_GetReg(SISCR
, 0x79);
2179 if(temp
& 0x20) ivideo
->vbflags
|= TV_PAL
;
2180 else ivideo
->vbflags
|= TV_NTSC
;
2185 /* Copy forceCRT1 option to CRT1off if option is given */
2186 if(ivideo
->sisfb_forcecrt1
!= -1) {
2187 ivideo
->sisfb_crt1off
= (ivideo
->sisfb_forcecrt1
) ? 0 : 1;
2191 /* ------------------ Sensing routines ------------------ */
2193 static bool sisfb_test_DDC1(struct sis_video_info
*ivideo
)
2198 old
= SiS_ReadDDC1Bit(&ivideo
->SiS_Pr
);
2200 if(old
!= SiS_ReadDDC1Bit(&ivideo
->SiS_Pr
)) break;
2202 return (count
!= -1);
2205 static void sisfb_sense_crt1(struct sis_video_info
*ivideo
)
2207 bool mustwait
= false;
2209 #ifdef CONFIG_FB_SIS_315
2215 sr1F
= SiS_GetReg(SISSR
, 0x1F);
2216 SiS_SetRegOR(SISSR
, 0x1F, 0x04);
2217 SiS_SetRegAND(SISSR
, 0x1F, 0x3F);
2218 if(sr1F
& 0xc0) mustwait
= true;
2220 #ifdef CONFIG_FB_SIS_315
2221 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2222 cr63
= SiS_GetReg(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
);
2224 SiS_SetRegAND(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, 0xBF);
2228 cr17
= SiS_GetReg(SISCR
, 0x17);
2231 SiS_SetRegOR(SISCR
, 0x17, 0x80);
2233 SiS_SetReg(SISSR
, 0x00, 0x01);
2234 SiS_SetReg(SISSR
, 0x00, 0x03);
2238 for(i
=0; i
< 10; i
++) sisfbwaitretracecrt1(ivideo
);
2241 #ifdef CONFIG_FB_SIS_315
2242 if(ivideo
->chip
>= SIS_330
) {
2243 SiS_SetRegAND(SISCR
, 0x32, ~0x20);
2244 if(ivideo
->chip
>= SIS_340
) {
2245 SiS_SetReg(SISCR
, 0x57, 0x4a);
2247 SiS_SetReg(SISCR
, 0x57, 0x5f);
2249 SiS_SetRegOR(SISCR
, 0x53, 0x02);
2250 while ((SiS_GetRegByte(SISINPSTAT
)) & 0x01) break;
2251 while (!((SiS_GetRegByte(SISINPSTAT
)) & 0x01)) break;
2252 if ((SiS_GetRegByte(SISMISCW
)) & 0x10) temp
= 1;
2253 SiS_SetRegAND(SISCR
, 0x53, 0xfd);
2254 SiS_SetRegAND(SISCR
, 0x57, 0x00);
2258 if(temp
== 0xffff) {
2261 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
,
2262 ivideo
->sisvga_engine
, 0, 0, NULL
, ivideo
->vbflags2
);
2263 } while(((temp
== 0) || (temp
== 0xffff)) && i
--);
2265 if((temp
== 0) || (temp
== 0xffff)) {
2266 if(sisfb_test_DDC1(ivideo
)) temp
= 1;
2270 if((temp
) && (temp
!= 0xffff)) {
2271 SiS_SetRegOR(SISCR
, 0x32, 0x20);
2274 #ifdef CONFIG_FB_SIS_315
2275 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2276 SiS_SetRegANDOR(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, 0xBF, cr63
);
2280 SiS_SetRegANDOR(SISCR
, 0x17, 0x7F, cr17
);
2282 SiS_SetReg(SISSR
, 0x1F, sr1F
);
2285 /* Determine and detect attached devices on SiS30x */
2286 static void SiS_SenseLCD(struct sis_video_info
*ivideo
)
2288 unsigned char buffer
[256];
2289 unsigned short temp
, realcrtno
, i
;
2290 u8 reg
, cr37
= 0, paneltype
= 0;
2293 ivideo
->SiS_Pr
.PanelSelfDetected
= false;
2295 /* LCD detection only for TMDS bridges */
2296 if(!(ivideo
->vbflags2
& VB2_SISTMDSBRIDGE
))
2298 if(ivideo
->vbflags2
& VB2_30xBDH
)
2301 /* If LCD already set up by BIOS, skip it */
2302 reg
= SiS_GetReg(SISCR
, 0x32);
2307 if(ivideo
->SiS_Pr
.DDCPortMixup
)
2310 /* Check DDC capabilities */
2311 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
2312 realcrtno
, 0, &buffer
[0], ivideo
->vbflags2
);
2314 if((!temp
) || (temp
== 0xffff) || (!(temp
& 0x02)))
2318 i
= 3; /* Number of retrys */
2320 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
,
2321 ivideo
->sisvga_engine
, realcrtno
, 1,
2322 &buffer
[0], ivideo
->vbflags2
);
2323 } while((temp
) && i
--);
2328 /* No digital device */
2329 if(!(buffer
[0x14] & 0x80))
2332 /* First detailed timing preferred timing? */
2333 if(!(buffer
[0x18] & 0x02))
2336 xres
= buffer
[0x38] | ((buffer
[0x3a] & 0xf0) << 4);
2337 yres
= buffer
[0x3b] | ((buffer
[0x3d] & 0xf0) << 4);
2349 if((yres
== 1200) && (ivideo
->vbflags2
& VB2_30xC
))
2360 if((buffer
[0x47] & 0x18) == 0x18)
2361 cr37
|= ((((buffer
[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2365 SiS_SetReg(SISCR
, 0x36, paneltype
);
2367 SiS_SetRegANDOR(SISCR
, 0x37, 0x0c, cr37
);
2368 SiS_SetRegOR(SISCR
, 0x32, 0x08);
2370 ivideo
->SiS_Pr
.PanelSelfDetected
= true;
2373 static int SISDoSense(struct sis_video_info
*ivideo
, u16 type
, u16 test
)
2375 int temp
, mytest
, result
, i
, j
;
2377 for(j
= 0; j
< 10; j
++) {
2379 for(i
= 0; i
< 3; i
++) {
2381 SiS_SetReg(SISPART4
, 0x11, (type
& 0x00ff));
2382 temp
= (type
>> 8) | (mytest
& 0x00ff);
2383 SiS_SetRegANDOR(SISPART4
, 0x10, 0xe0, temp
);
2384 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x1500);
2387 temp
= SiS_GetReg(SISPART4
, 0x03);
2390 if(temp
== mytest
) result
++;
2392 SiS_SetReg(SISPART4
, 0x11, 0x00);
2393 SiS_SetRegAND(SISPART4
, 0x10, 0xe0);
2394 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x1000);
2397 if((result
== 0) || (result
>= 2)) break;
2402 static void SiS_Sense30x(struct sis_video_info
*ivideo
)
2404 u8 backupP4_0d
,backupP2_00
,backupP2_4d
,backupSR_1e
,biosflag
=0;
2405 u16 svhs
=0, svhs_c
=0;
2406 u16 cvbs
=0, cvbs_c
=0;
2407 u16 vga2
=0, vga2_c
=0;
2409 char stdstr
[] = "sisfb: Detected";
2410 char tvstr
[] = "TV connected to";
2412 if(ivideo
->vbflags2
& VB2_301
) {
2413 svhs
= 0x00b9; cvbs
= 0x00b3; vga2
= 0x00d1;
2414 myflag
= SiS_GetReg(SISPART4
, 0x01);
2416 svhs
= 0x00dd; cvbs
= 0x00ee; vga2
= 0x00fd;
2418 } else if(ivideo
->vbflags2
& (VB2_301B
| VB2_302B
)) {
2419 svhs
= 0x016b; cvbs
= 0x0174; vga2
= 0x0190;
2420 } else if(ivideo
->vbflags2
& (VB2_301LV
| VB2_302LV
)) {
2421 svhs
= 0x0200; cvbs
= 0x0100;
2422 } else if(ivideo
->vbflags2
& (VB2_301C
| VB2_302ELV
| VB2_307T
| VB2_307LV
)) {
2423 svhs
= 0x016b; cvbs
= 0x0110; vga2
= 0x0190;
2427 vga2_c
= 0x0e08; svhs_c
= 0x0404; cvbs_c
= 0x0804;
2428 if(ivideo
->vbflags
& (VB2_301LV
|VB2_302LV
|VB2_302ELV
|VB2_307LV
)) {
2429 svhs_c
= 0x0408; cvbs_c
= 0x0808;
2433 if(ivideo
->haveXGIROM
) {
2434 biosflag
= ivideo
->bios_abase
[0x58] & 0x03;
2435 } else if(ivideo
->newrom
) {
2436 if(ivideo
->bios_abase
[0x5d] & 0x04) biosflag
|= 0x01;
2437 } else if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2438 if(ivideo
->bios_abase
) {
2439 biosflag
= ivideo
->bios_abase
[0xfe] & 0x03;
2443 if(ivideo
->chip
== SIS_300
) {
2444 myflag
= SiS_GetReg(SISSR
, 0x3b);
2445 if(!(myflag
& 0x01)) vga2
= vga2_c
= 0;
2448 if(!(ivideo
->vbflags2
& VB2_SISVGA2BRIDGE
)) {
2452 backupSR_1e
= SiS_GetReg(SISSR
, 0x1e);
2453 SiS_SetRegOR(SISSR
, 0x1e, 0x20);
2455 backupP4_0d
= SiS_GetReg(SISPART4
, 0x0d);
2456 if(ivideo
->vbflags2
& VB2_30xC
) {
2457 SiS_SetRegANDOR(SISPART4
, 0x0d, ~0x07, 0x01);
2459 SiS_SetRegOR(SISPART4
, 0x0d, 0x04);
2461 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x2000);
2463 backupP2_00
= SiS_GetReg(SISPART2
, 0x00);
2464 SiS_SetReg(SISPART2
, 0x00, ((backupP2_00
| 0x1c) & 0xfc));
2466 backupP2_4d
= SiS_GetReg(SISPART2
, 0x4d);
2467 if(ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
) {
2468 SiS_SetReg(SISPART2
, 0x4d, (backupP2_4d
& ~0x10));
2471 if(!(ivideo
->vbflags2
& VB2_30xCLV
)) {
2472 SISDoSense(ivideo
, 0, 0);
2475 SiS_SetRegAND(SISCR
, 0x32, ~0x14);
2477 if(vga2_c
|| vga2
) {
2478 if(SISDoSense(ivideo
, vga2
, vga2_c
)) {
2479 if(biosflag
& 0x01) {
2480 printk(KERN_INFO
"%s %s SCART output\n", stdstr
, tvstr
);
2481 SiS_SetRegOR(SISCR
, 0x32, 0x04);
2483 printk(KERN_INFO
"%s secondary VGA connection\n", stdstr
);
2484 SiS_SetRegOR(SISCR
, 0x32, 0x10);
2489 SiS_SetRegAND(SISCR
, 0x32, 0x3f);
2491 if(ivideo
->vbflags2
& VB2_30xCLV
) {
2492 SiS_SetRegOR(SISPART4
, 0x0d, 0x04);
2495 if((ivideo
->sisvga_engine
== SIS_315_VGA
) && (ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) {
2496 SiS_SetReg(SISPART2
, 0x4d, (backupP2_4d
| 0x10));
2497 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x2000);
2498 if((result
= SISDoSense(ivideo
, svhs
, 0x0604))) {
2499 if((result
= SISDoSense(ivideo
, cvbs
, 0x0804))) {
2500 printk(KERN_INFO
"%s %s YPbPr component output\n", stdstr
, tvstr
);
2501 SiS_SetRegOR(SISCR
, 0x32, 0x80);
2504 SiS_SetReg(SISPART2
, 0x4d, backupP2_4d
);
2507 SiS_SetRegAND(SISCR
, 0x32, ~0x03);
2509 if(!(ivideo
->vbflags
& TV_YPBPR
)) {
2510 if((result
= SISDoSense(ivideo
, svhs
, svhs_c
))) {
2511 printk(KERN_INFO
"%s %s SVIDEO output\n", stdstr
, tvstr
);
2512 SiS_SetRegOR(SISCR
, 0x32, 0x02);
2514 if((biosflag
& 0x02) || (!result
)) {
2515 if(SISDoSense(ivideo
, cvbs
, cvbs_c
)) {
2516 printk(KERN_INFO
"%s %s COMPOSITE output\n", stdstr
, tvstr
);
2517 SiS_SetRegOR(SISCR
, 0x32, 0x01);
2522 SISDoSense(ivideo
, 0, 0);
2524 SiS_SetReg(SISPART2
, 0x00, backupP2_00
);
2525 SiS_SetReg(SISPART4
, 0x0d, backupP4_0d
);
2526 SiS_SetReg(SISSR
, 0x1e, backupSR_1e
);
2528 if(ivideo
->vbflags2
& VB2_30xCLV
) {
2529 biosflag
= SiS_GetReg(SISPART2
, 0x00);
2530 if(biosflag
& 0x20) {
2531 for(myflag
= 2; myflag
> 0; myflag
--) {
2533 SiS_SetReg(SISPART2
, 0x00, biosflag
);
2538 SiS_SetReg(SISPART2
, 0x00, backupP2_00
);
2541 /* Determine and detect attached TV's on Chrontel */
2542 static void SiS_SenseCh(struct sis_video_info
*ivideo
)
2544 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2546 char stdstr
[] = "sisfb: Chrontel: Detected TV connected to";
2548 #ifdef CONFIG_FB_SIS_300
2549 unsigned char test
[3];
2553 if(ivideo
->chip
< SIS_315H
) {
2555 #ifdef CONFIG_FB_SIS_300
2556 ivideo
->SiS_Pr
.SiS_IF_DEF_CH70xx
= 1; /* Chrontel 700x */
2557 SiS_SetChrontelGPIO(&ivideo
->SiS_Pr
, 0x9c); /* Set general purpose IO for Chrontel communication */
2558 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 1000);
2559 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x25);
2560 /* See Chrontel TB31 for explanation */
2561 temp2
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0e);
2562 if(((temp2
& 0x07) == 0x01) || (temp2
& 0x04)) {
2563 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0e, 0x0b);
2564 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 300);
2566 temp2
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x25);
2567 if(temp2
!= temp1
) temp1
= temp2
;
2569 if((temp1
>= 0x22) && (temp1
<= 0x50)) {
2570 /* Read power status */
2571 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0e);
2572 if((temp1
& 0x03) != 0x03) {
2573 /* Power all outputs */
2574 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0e,0x0b);
2575 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 300);
2577 /* Sense connected TV devices */
2578 for(i
= 0; i
< 3; i
++) {
2579 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x10, 0x01);
2580 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2581 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x10, 0x00);
2582 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2583 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x10);
2584 if(!(temp1
& 0x08)) test
[i
] = 0x02;
2585 else if(!(temp1
& 0x02)) test
[i
] = 0x01;
2587 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2590 if(test
[0] == test
[1]) temp1
= test
[0];
2591 else if(test
[0] == test
[2]) temp1
= test
[0];
2592 else if(test
[1] == test
[2]) temp1
= test
[1];
2595 "sisfb: TV detection unreliable - test results varied\n");
2599 printk(KERN_INFO
"%s SVIDEO output\n", stdstr
);
2600 ivideo
->vbflags
|= TV_SVIDEO
;
2601 SiS_SetRegOR(SISCR
, 0x32, 0x02);
2602 SiS_SetRegAND(SISCR
, 0x32, ~0x05);
2603 } else if (temp1
== 0x01) {
2604 printk(KERN_INFO
"%s CVBS output\n", stdstr
);
2605 ivideo
->vbflags
|= TV_AVIDEO
;
2606 SiS_SetRegOR(SISCR
, 0x32, 0x01);
2607 SiS_SetRegAND(SISCR
, 0x32, ~0x06);
2609 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x0e, 0x01, 0xF8);
2610 SiS_SetRegAND(SISCR
, 0x32, ~0x07);
2612 } else if(temp1
== 0) {
2613 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x0e, 0x01, 0xF8);
2614 SiS_SetRegAND(SISCR
, 0x32, ~0x07);
2616 /* Set general purpose IO for Chrontel communication */
2617 SiS_SetChrontelGPIO(&ivideo
->SiS_Pr
, 0x00);
2622 #ifdef CONFIG_FB_SIS_315
2623 ivideo
->SiS_Pr
.SiS_IF_DEF_CH70xx
= 2; /* Chrontel 7019 */
2624 temp1
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x49);
2625 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x49, 0x20);
2626 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2627 temp2
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x20);
2629 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x20, temp2
);
2630 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2632 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x20, temp2
);
2633 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2634 temp2
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x20);
2635 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x49, temp1
);
2637 if(temp2
& 0x02) temp1
|= 0x01;
2638 if(temp2
& 0x10) temp1
|= 0x01;
2639 if(temp2
& 0x04) temp1
|= 0x02;
2640 if( (temp1
& 0x01) && (temp1
& 0x02) ) temp1
= 0x04;
2643 printk(KERN_INFO
"%s CVBS output\n", stdstr
);
2644 ivideo
->vbflags
|= TV_AVIDEO
;
2645 SiS_SetRegOR(SISCR
, 0x32, 0x01);
2646 SiS_SetRegAND(SISCR
, 0x32, ~0x06);
2649 printk(KERN_INFO
"%s SVIDEO output\n", stdstr
);
2650 ivideo
->vbflags
|= TV_SVIDEO
;
2651 SiS_SetRegOR(SISCR
, 0x32, 0x02);
2652 SiS_SetRegAND(SISCR
, 0x32, ~0x05);
2655 printk(KERN_INFO
"%s SCART output\n", stdstr
);
2656 SiS_SetRegOR(SISCR
, 0x32, 0x04);
2657 SiS_SetRegAND(SISCR
, 0x32, ~0x03);
2660 SiS_SetRegAND(SISCR
, 0x32, ~0x07);
2666 static void sisfb_get_VB_type(struct sis_video_info
*ivideo
)
2668 char stdstr
[] = "sisfb: Detected";
2669 char bridgestr
[] = "video bridge";
2673 /* No CRT2 on XGI Z7 */
2674 if(ivideo
->chip
== XGI_20
)
2677 vb_chipid
= SiS_GetReg(SISPART4
, 0x00);
2680 reg
= SiS_GetReg(SISPART4
, 0x01);
2682 ivideo
->vbflags
|= VB_301
; /* Deprecated */
2683 ivideo
->vbflags2
|= VB2_301
;
2684 printk(KERN_INFO
"%s SiS301 %s\n", stdstr
, bridgestr
);
2685 } else if(reg
< 0xc0) {
2686 ivideo
->vbflags
|= VB_301B
; /* Deprecated */
2687 ivideo
->vbflags2
|= VB2_301B
;
2688 reg
= SiS_GetReg(SISPART4
, 0x23);
2690 ivideo
->vbflags
|= VB_30xBDH
; /* Deprecated */
2691 ivideo
->vbflags2
|= VB2_30xBDH
;
2692 printk(KERN_INFO
"%s SiS301B-DH %s\n", stdstr
, bridgestr
);
2694 printk(KERN_INFO
"%s SiS301B %s\n", stdstr
, bridgestr
);
2696 } else if(reg
< 0xd0) {
2697 ivideo
->vbflags
|= VB_301C
; /* Deprecated */
2698 ivideo
->vbflags2
|= VB2_301C
;
2699 printk(KERN_INFO
"%s SiS301C %s\n", stdstr
, bridgestr
);
2700 } else if(reg
< 0xe0) {
2701 ivideo
->vbflags
|= VB_301LV
; /* Deprecated */
2702 ivideo
->vbflags2
|= VB2_301LV
;
2703 printk(KERN_INFO
"%s SiS301LV %s\n", stdstr
, bridgestr
);
2704 } else if(reg
<= 0xe1) {
2705 reg
= SiS_GetReg(SISPART4
, 0x39);
2707 ivideo
->vbflags
|= VB_302LV
; /* Deprecated */
2708 ivideo
->vbflags2
|= VB2_302LV
;
2709 printk(KERN_INFO
"%s SiS302LV %s\n", stdstr
, bridgestr
);
2711 ivideo
->vbflags
|= VB_301C
; /* Deprecated */
2712 ivideo
->vbflags2
|= VB2_301C
;
2713 printk(KERN_INFO
"%s SiS301C(P4) %s\n", stdstr
, bridgestr
);
2715 ivideo
->vbflags
|= VB_302ELV
; /* Deprecated */
2716 ivideo
->vbflags2
|= VB2_302ELV
;
2717 printk(KERN_INFO
"%s SiS302ELV %s\n", stdstr
, bridgestr
);
2723 ivideo
->vbflags
|= VB_302B
; /* Deprecated */
2724 ivideo
->vbflags2
|= VB2_302B
;
2725 printk(KERN_INFO
"%s SiS302B %s\n", stdstr
, bridgestr
);
2729 if((!(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
)) && (ivideo
->chip
!= SIS_300
)) {
2730 reg
= SiS_GetReg(SISCR
, 0x37);
2731 reg
&= SIS_EXTERNAL_CHIP_MASK
;
2733 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2734 #ifdef CONFIG_FB_SIS_300
2736 case SIS_EXTERNAL_CHIP_LVDS
:
2737 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2738 ivideo
->vbflags2
|= VB2_LVDS
;
2740 case SIS_EXTERNAL_CHIP_TRUMPION
:
2741 ivideo
->vbflags
|= (VB_LVDS
| VB_TRUMPION
); /* Deprecated */
2742 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_TRUMPION
);
2744 case SIS_EXTERNAL_CHIP_CHRONTEL
:
2745 ivideo
->vbflags
|= VB_CHRONTEL
; /* Deprecated */
2746 ivideo
->vbflags2
|= VB2_CHRONTEL
;
2748 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL
:
2749 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2750 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2753 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 1;
2755 } else if(ivideo
->chip
< SIS_661
) {
2756 #ifdef CONFIG_FB_SIS_315
2758 case SIS310_EXTERNAL_CHIP_LVDS
:
2759 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2760 ivideo
->vbflags2
|= VB2_LVDS
;
2762 case SIS310_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
= 2;
2769 } else if(ivideo
->chip
>= SIS_661
) {
2770 #ifdef CONFIG_FB_SIS_315
2771 reg
= SiS_GetReg(SISCR
, 0x38);
2775 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2776 ivideo
->vbflags2
|= VB2_LVDS
;
2779 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2780 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2783 ivideo
->vbflags
|= (VB_LVDS
| VB_CONEXANT
); /* Deprecated */
2784 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CONEXANT
);
2787 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 2;
2790 if(ivideo
->vbflags2
& VB2_LVDS
) {
2791 printk(KERN_INFO
"%s LVDS transmitter\n", stdstr
);
2793 if((ivideo
->sisvga_engine
== SIS_300_VGA
) && (ivideo
->vbflags2
& VB2_TRUMPION
)) {
2794 printk(KERN_INFO
"%s Trumpion Zurac LCD scaler\n", stdstr
);
2796 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
2797 printk(KERN_INFO
"%s Chrontel TV encoder\n", stdstr
);
2799 if((ivideo
->chip
>= SIS_661
) && (ivideo
->vbflags2
& VB2_CONEXANT
)) {
2800 printk(KERN_INFO
"%s Conexant external device\n", stdstr
);
2804 if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
2805 SiS_SenseLCD(ivideo
);
2806 SiS_Sense30x(ivideo
);
2807 } else if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
2808 SiS_SenseCh(ivideo
);
2812 /* ---------- Engine initialization routines ------------ */
2815 sisfb_engine_init(struct sis_video_info
*ivideo
)
2818 /* Initialize command queue (we use MMIO only) */
2820 /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
2822 ivideo
->caps
&= ~(TURBO_QUEUE_CAP
|
2823 MMIO_CMD_QUEUE_CAP
|
2827 #ifdef CONFIG_FB_SIS_300
2828 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2832 tqueue_pos
= (ivideo
->video_size
- ivideo
->cmdQueueSize
) / (64 * 1024);
2834 tq_state
= SiS_GetReg(SISSR
, IND_SIS_TURBOQUEUE_SET
);
2837 tq_state
|= (u8
)(tqueue_pos
>> 8);
2838 SiS_SetReg(SISSR
, IND_SIS_TURBOQUEUE_SET
, tq_state
);
2840 SiS_SetReg(SISSR
, IND_SIS_TURBOQUEUE_ADR
, (u8
)(tqueue_pos
& 0xff));
2842 ivideo
->caps
|= TURBO_QUEUE_CAP
;
2846 #ifdef CONFIG_FB_SIS_315
2847 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2848 u32 tempq
= 0, templ
;
2851 if(ivideo
->chip
== XGI_20
) {
2852 switch(ivideo
->cmdQueueSize
) {
2854 temp
= SIS_CMD_QUEUE_SIZE_Z7_64k
;
2858 temp
= SIS_CMD_QUEUE_SIZE_Z7_128k
;
2861 switch(ivideo
->cmdQueueSize
) {
2862 case (4 * 1024 * 1024):
2863 temp
= SIS_CMD_QUEUE_SIZE_4M
;
2865 case (2 * 1024 * 1024):
2866 temp
= SIS_CMD_QUEUE_SIZE_2M
;
2868 case (1 * 1024 * 1024):
2869 temp
= SIS_CMD_QUEUE_SIZE_1M
;
2873 temp
= SIS_CMD_QUEUE_SIZE_512k
;
2877 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_THRESHOLD
, COMMAND_QUEUE_THRESHOLD
);
2878 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, SIS_CMD_QUEUE_RESET
);
2880 if((ivideo
->chip
>= XGI_40
) && ivideo
->modechanged
) {
2881 /* Must disable dual pipe on XGI_40. Can't do
2882 * this in MMIO mode, because it requires
2883 * setting/clearing a bit in the MMIO fire trigger
2886 if(!((templ
= MMIO_IN32(ivideo
->mmio_vbase
, 0x8240)) & (1 << 10))) {
2888 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, 0);
2890 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, (temp
| SIS_VRAM_CMDQUEUE_ENABLE
));
2892 tempq
= MMIO_IN32(ivideo
->mmio_vbase
, Q_READ_PTR
);
2893 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, tempq
);
2895 tempq
= (u32
)(ivideo
->video_size
- ivideo
->cmdQueueSize
);
2896 MMIO_OUT32(ivideo
->mmio_vbase
, Q_BASE_ADDR
, tempq
);
2898 writel(0x16800000 + 0x8240, ivideo
->video_vbase
+ tempq
);
2899 writel(templ
| (1 << 10), ivideo
->video_vbase
+ tempq
+ 4);
2900 writel(0x168F0000, ivideo
->video_vbase
+ tempq
+ 8);
2901 writel(0x168F0000, ivideo
->video_vbase
+ tempq
+ 12);
2903 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, (tempq
+ 16));
2905 sisfb_syncaccel(ivideo
);
2907 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, SIS_CMD_QUEUE_RESET
);
2912 tempq
= MMIO_IN32(ivideo
->mmio_vbase
, MMIO_QUEUE_READPORT
);
2913 MMIO_OUT32(ivideo
->mmio_vbase
, MMIO_QUEUE_WRITEPORT
, tempq
);
2915 temp
|= (SIS_MMIO_CMD_ENABLE
| SIS_CMD_AUTO_CORR
);
2916 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, temp
);
2918 tempq
= (u32
)(ivideo
->video_size
- ivideo
->cmdQueueSize
);
2919 MMIO_OUT32(ivideo
->mmio_vbase
, MMIO_QUEUE_PHYBASE
, tempq
);
2921 ivideo
->caps
|= MMIO_CMD_QUEUE_CAP
;
2925 ivideo
->engineok
= 1;
2928 static void sisfb_detect_lcd_type(struct sis_video_info
*ivideo
)
2933 reg
= SiS_GetReg(SISCR
, 0x36);
2935 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2936 ivideo
->CRT2LCDType
= sis300paneltype
[reg
];
2937 } else if(ivideo
->chip
>= SIS_661
) {
2938 ivideo
->CRT2LCDType
= sis661paneltype
[reg
];
2940 ivideo
->CRT2LCDType
= sis310paneltype
[reg
];
2941 if((ivideo
->chip
== SIS_550
) && (sisfb_fstn
)) {
2942 if((ivideo
->CRT2LCDType
!= LCD_320x240_2
) &&
2943 (ivideo
->CRT2LCDType
!= LCD_320x240_3
)) {
2944 ivideo
->CRT2LCDType
= LCD_320x240
;
2949 if(ivideo
->CRT2LCDType
== LCD_UNKNOWN
) {
2950 /* For broken BIOSes: Assume 1024x768, RGB18 */
2951 ivideo
->CRT2LCDType
= LCD_1024x768
;
2952 SiS_SetRegANDOR(SISCR
, 0x36, 0xf0, 0x02);
2953 SiS_SetRegANDOR(SISCR
, 0x37, 0xee, 0x01);
2954 printk(KERN_DEBUG
"sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg
);
2957 for(i
= 0; i
< SIS_LCD_NUMBER
; i
++) {
2958 if(ivideo
->CRT2LCDType
== sis_lcd_data
[i
].lcdtype
) {
2959 ivideo
->lcdxres
= sis_lcd_data
[i
].xres
;
2960 ivideo
->lcdyres
= sis_lcd_data
[i
].yres
;
2961 ivideo
->lcddefmodeidx
= sis_lcd_data
[i
].default_mode_idx
;
2966 #ifdef CONFIG_FB_SIS_300
2967 if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_BARCO1366
) {
2968 ivideo
->lcdxres
= 1360; ivideo
->lcdyres
= 1024;
2969 ivideo
->lcddefmodeidx
= DEFAULT_MODE_1360
;
2970 } else if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_PANEL848
) {
2971 ivideo
->lcdxres
= 848; ivideo
->lcdyres
= 480;
2972 ivideo
->lcddefmodeidx
= DEFAULT_MODE_848
;
2973 } else if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_PANEL856
) {
2974 ivideo
->lcdxres
= 856; ivideo
->lcdyres
= 480;
2975 ivideo
->lcddefmodeidx
= DEFAULT_MODE_856
;
2979 printk(KERN_DEBUG
"sisfb: Detected %dx%d flat panel\n",
2980 ivideo
->lcdxres
, ivideo
->lcdyres
);
2983 static void sisfb_save_pdc_emi(struct sis_video_info
*ivideo
)
2985 #ifdef CONFIG_FB_SIS_300
2986 /* Save the current PanelDelayCompensation if the LCD is currently used */
2987 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2988 if(ivideo
->vbflags2
& (VB2_LVDS
| VB2_30xBDH
)) {
2990 tmp
= SiS_GetReg(SISCR
, 0x30);
2992 /* Currently on LCD? If yes, read current pdc */
2993 ivideo
->detectedpdc
= SiS_GetReg(SISPART1
, 0x13);
2994 ivideo
->detectedpdc
&= 0x3c;
2995 if(ivideo
->SiS_Pr
.PDC
== -1) {
2996 /* Let option override detection */
2997 ivideo
->SiS_Pr
.PDC
= ivideo
->detectedpdc
;
2999 printk(KERN_INFO
"sisfb: Detected LCD PDC 0x%02x\n",
3000 ivideo
->detectedpdc
);
3002 if((ivideo
->SiS_Pr
.PDC
!= -1) &&
3003 (ivideo
->SiS_Pr
.PDC
!= ivideo
->detectedpdc
)) {
3004 printk(KERN_INFO
"sisfb: Using LCD PDC 0x%02x\n",
3005 ivideo
->SiS_Pr
.PDC
);
3011 #ifdef CONFIG_FB_SIS_315
3012 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3014 /* Try to find about LCDA */
3015 if(ivideo
->vbflags2
& VB2_SISLCDABRIDGE
) {
3017 tmp
= SiS_GetReg(SISPART1
, 0x13);
3019 ivideo
->SiS_Pr
.SiS_UseLCDA
= true;
3020 ivideo
->detectedlcda
= 0x03;
3025 if(ivideo
->vbflags2
& VB2_SISLVDSBRIDGE
) {
3027 tmp
= SiS_GetReg(SISCR
, 0x30);
3028 if((tmp
& 0x20) || (ivideo
->detectedlcda
!= 0xff)) {
3029 /* Currently on LCD? If yes, read current pdc */
3031 pdc
= SiS_GetReg(SISPART1
, 0x2D);
3032 ivideo
->detectedpdc
= (pdc
& 0x0f) << 1;
3033 ivideo
->detectedpdca
= (pdc
& 0xf0) >> 3;
3034 pdc
= SiS_GetReg(SISPART1
, 0x35);
3035 ivideo
->detectedpdc
|= ((pdc
>> 7) & 0x01);
3036 pdc
= SiS_GetReg(SISPART1
, 0x20);
3037 ivideo
->detectedpdca
|= ((pdc
>> 6) & 0x01);
3038 if(ivideo
->newrom
) {
3039 /* New ROM invalidates other PDC resp. */
3040 if(ivideo
->detectedlcda
!= 0xff) {
3041 ivideo
->detectedpdc
= 0xff;
3043 ivideo
->detectedpdca
= 0xff;
3046 if(ivideo
->SiS_Pr
.PDC
== -1) {
3047 if(ivideo
->detectedpdc
!= 0xff) {
3048 ivideo
->SiS_Pr
.PDC
= ivideo
->detectedpdc
;
3051 if(ivideo
->SiS_Pr
.PDCA
== -1) {
3052 if(ivideo
->detectedpdca
!= 0xff) {
3053 ivideo
->SiS_Pr
.PDCA
= ivideo
->detectedpdca
;
3056 if(ivideo
->detectedpdc
!= 0xff) {
3058 "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3059 ivideo
->detectedpdc
);
3061 if(ivideo
->detectedpdca
!= 0xff) {
3063 "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3064 ivideo
->detectedpdca
);
3069 if(ivideo
->vbflags2
& VB2_SISEMIBRIDGE
) {
3070 ivideo
->SiS_Pr
.EMI_30
= SiS_GetReg(SISPART4
, 0x30);
3071 ivideo
->SiS_Pr
.EMI_31
= SiS_GetReg(SISPART4
, 0x31);
3072 ivideo
->SiS_Pr
.EMI_32
= SiS_GetReg(SISPART4
, 0x32);
3073 ivideo
->SiS_Pr
.EMI_33
= SiS_GetReg(SISPART4
, 0x33);
3074 ivideo
->SiS_Pr
.HaveEMI
= true;
3075 if((tmp
& 0x20) || (ivideo
->detectedlcda
!= 0xff)) {
3076 ivideo
->SiS_Pr
.HaveEMILCD
= true;
3081 /* Let user override detected PDCs (all bridges) */
3082 if(ivideo
->vbflags2
& VB2_30xBLV
) {
3083 if((ivideo
->SiS_Pr
.PDC
!= -1) &&
3084 (ivideo
->SiS_Pr
.PDC
!= ivideo
->detectedpdc
)) {
3085 printk(KERN_INFO
"sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3086 ivideo
->SiS_Pr
.PDC
);
3088 if((ivideo
->SiS_Pr
.PDCA
!= -1) &&
3089 (ivideo
->SiS_Pr
.PDCA
!= ivideo
->detectedpdca
)) {
3090 printk(KERN_INFO
"sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3091 ivideo
->SiS_Pr
.PDCA
);
3099 /* -------------------- Memory manager routines ---------------------- */
3101 static u32
sisfb_getheapstart(struct sis_video_info
*ivideo
)
3103 u32 ret
= ivideo
->sisfb_parm_mem
* 1024;
3104 u32 maxoffs
= ivideo
->video_size
- ivideo
->hwcursor_size
- ivideo
->cmdQueueSize
;
3107 /* Calculate heap start = end of memory for console
3109 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3110 * C = console, D = heap, H = HWCursor, Q = cmd-queue
3112 * On 76x in UMA+LFB mode, the layout is as follows:
3113 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3114 * where the heap is the entire UMA area, eventually
3115 * into the LFB area if the given mem parameter is
3116 * higher than the size of the UMA memory.
3118 * Basically given by "mem" parameter
3120 * maximum = videosize - cmd_queue - hwcursor
3121 * (results in a heap of size 0)
3122 * default = SiS 300: depends on videosize
3123 * SiS 315/330/340/XGI: 32k below max
3126 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3127 if(ivideo
->video_size
> 0x1000000) {
3129 } else if(ivideo
->video_size
> 0x800000) {
3134 } else if(ivideo
->UMAsize
&& ivideo
->LFBsize
) {
3137 def
= maxoffs
- 0x8000;
3140 /* Use default for secondary card for now (FIXME) */
3141 if((!ret
) || (ret
> maxoffs
) || (ivideo
->cardnumber
!= 0))
3147 static u32
sisfb_getheapsize(struct sis_video_info
*ivideo
)
3149 u32 max
= ivideo
->video_size
- ivideo
->hwcursor_size
- ivideo
->cmdQueueSize
;
3152 if(ivideo
->UMAsize
&& ivideo
->LFBsize
) {
3153 if( (!ivideo
->sisfb_parm_mem
) ||
3154 ((ivideo
->sisfb_parm_mem
* 1024) > max
) ||
3155 ((max
- (ivideo
->sisfb_parm_mem
* 1024)) < ivideo
->UMAsize
) ) {
3156 ret
= ivideo
->UMAsize
;
3157 max
-= ivideo
->UMAsize
;
3159 ret
= max
- (ivideo
->sisfb_parm_mem
* 1024);
3160 max
= ivideo
->sisfb_parm_mem
* 1024;
3162 ivideo
->video_offset
= ret
;
3163 ivideo
->sisfb_mem
= max
;
3165 ret
= max
- ivideo
->heapstart
;
3166 ivideo
->sisfb_mem
= ivideo
->heapstart
;
3172 static int sisfb_heap_init(struct sis_video_info
*ivideo
)
3176 ivideo
->video_offset
= 0;
3177 if(ivideo
->sisfb_parm_mem
) {
3178 if( (ivideo
->sisfb_parm_mem
< (2 * 1024 * 1024)) ||
3179 (ivideo
->sisfb_parm_mem
> ivideo
->video_size
) ) {
3180 ivideo
->sisfb_parm_mem
= 0;
3184 ivideo
->heapstart
= sisfb_getheapstart(ivideo
);
3185 ivideo
->sisfb_heap_size
= sisfb_getheapsize(ivideo
);
3187 ivideo
->sisfb_heap_start
= ivideo
->video_vbase
+ ivideo
->heapstart
;
3188 ivideo
->sisfb_heap_end
= ivideo
->sisfb_heap_start
+ ivideo
->sisfb_heap_size
;
3190 printk(KERN_INFO
"sisfb: Memory heap starting at %dK, size %dK\n",
3191 (int)(ivideo
->heapstart
/ 1024), (int)(ivideo
->sisfb_heap_size
/ 1024));
3193 ivideo
->sisfb_heap
.vinfo
= ivideo
;
3195 ivideo
->sisfb_heap
.poha_chain
= NULL
;
3196 ivideo
->sisfb_heap
.poh_freelist
= NULL
;
3198 poh
= sisfb_poh_new_node(&ivideo
->sisfb_heap
);
3202 poh
->poh_next
= &ivideo
->sisfb_heap
.oh_free
;
3203 poh
->poh_prev
= &ivideo
->sisfb_heap
.oh_free
;
3204 poh
->size
= ivideo
->sisfb_heap_size
;
3205 poh
->offset
= ivideo
->heapstart
;
3207 ivideo
->sisfb_heap
.oh_free
.poh_next
= poh
;
3208 ivideo
->sisfb_heap
.oh_free
.poh_prev
= poh
;
3209 ivideo
->sisfb_heap
.oh_free
.size
= 0;
3210 ivideo
->sisfb_heap
.max_freesize
= poh
->size
;
3212 ivideo
->sisfb_heap
.oh_used
.poh_next
= &ivideo
->sisfb_heap
.oh_used
;
3213 ivideo
->sisfb_heap
.oh_used
.poh_prev
= &ivideo
->sisfb_heap
.oh_used
;
3214 ivideo
->sisfb_heap
.oh_used
.size
= SENTINEL
;
3216 if(ivideo
->cardnumber
== 0) {
3217 /* For the first card, make this heap the "global" one
3218 * for old DRM (which could handle only one card)
3220 sisfb_heap
= &ivideo
->sisfb_heap
;
3226 static struct SIS_OH
*
3227 sisfb_poh_new_node(struct SIS_HEAP
*memheap
)
3229 struct SIS_OHALLOC
*poha
;
3234 if(memheap
->poh_freelist
== NULL
) {
3235 poha
= kmalloc(SIS_OH_ALLOC_SIZE
, GFP_KERNEL
);
3239 poha
->poha_next
= memheap
->poha_chain
;
3240 memheap
->poha_chain
= poha
;
3242 cOhs
= (SIS_OH_ALLOC_SIZE
- sizeof(struct SIS_OHALLOC
)) / sizeof(struct SIS_OH
) + 1;
3244 poh
= &poha
->aoh
[0];
3245 for(i
= cOhs
- 1; i
!= 0; i
--) {
3246 poh
->poh_next
= poh
+ 1;
3250 poh
->poh_next
= NULL
;
3251 memheap
->poh_freelist
= &poha
->aoh
[0];
3254 poh
= memheap
->poh_freelist
;
3255 memheap
->poh_freelist
= poh
->poh_next
;
3260 static struct SIS_OH
*
3261 sisfb_poh_allocate(struct SIS_HEAP
*memheap
, u32 size
)
3263 struct SIS_OH
*pohThis
;
3264 struct SIS_OH
*pohRoot
;
3267 if(size
> memheap
->max_freesize
) {
3268 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3269 (unsigned int) size
/ 1024);
3273 pohThis
= memheap
->oh_free
.poh_next
;
3275 while(pohThis
!= &memheap
->oh_free
) {
3276 if(size
<= pohThis
->size
) {
3280 pohThis
= pohThis
->poh_next
;
3284 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3285 (unsigned int) size
/ 1024);
3289 if(size
== pohThis
->size
) {
3291 sisfb_delete_node(pohThis
);
3293 pohRoot
= sisfb_poh_new_node(memheap
);
3297 pohRoot
->offset
= pohThis
->offset
;
3298 pohRoot
->size
= size
;
3300 pohThis
->offset
+= size
;
3301 pohThis
->size
-= size
;
3304 memheap
->max_freesize
-= size
;
3306 pohThis
= &memheap
->oh_used
;
3307 sisfb_insert_node(pohThis
, pohRoot
);
3313 sisfb_delete_node(struct SIS_OH
*poh
)
3315 poh
->poh_prev
->poh_next
= poh
->poh_next
;
3316 poh
->poh_next
->poh_prev
= poh
->poh_prev
;
3320 sisfb_insert_node(struct SIS_OH
*pohList
, struct SIS_OH
*poh
)
3322 struct SIS_OH
*pohTemp
= pohList
->poh_next
;
3324 pohList
->poh_next
= poh
;
3325 pohTemp
->poh_prev
= poh
;
3327 poh
->poh_prev
= pohList
;
3328 poh
->poh_next
= pohTemp
;
3331 static struct SIS_OH
*
3332 sisfb_poh_free(struct SIS_HEAP
*memheap
, u32 base
)
3334 struct SIS_OH
*pohThis
;
3335 struct SIS_OH
*poh_freed
;
3336 struct SIS_OH
*poh_prev
;
3337 struct SIS_OH
*poh_next
;
3342 poh_freed
= memheap
->oh_used
.poh_next
;
3344 while(poh_freed
!= &memheap
->oh_used
) {
3345 if(poh_freed
->offset
== base
) {
3350 poh_freed
= poh_freed
->poh_next
;
3356 memheap
->max_freesize
+= poh_freed
->size
;
3358 poh_prev
= poh_next
= NULL
;
3359 ulUpper
= poh_freed
->offset
+ poh_freed
->size
;
3360 ulLower
= poh_freed
->offset
;
3362 pohThis
= memheap
->oh_free
.poh_next
;
3364 while(pohThis
!= &memheap
->oh_free
) {
3365 if(pohThis
->offset
== ulUpper
) {
3367 } else if((pohThis
->offset
+ pohThis
->size
) == ulLower
) {
3370 pohThis
= pohThis
->poh_next
;
3373 sisfb_delete_node(poh_freed
);
3375 if(poh_prev
&& poh_next
) {
3376 poh_prev
->size
+= (poh_freed
->size
+ poh_next
->size
);
3377 sisfb_delete_node(poh_next
);
3378 sisfb_free_node(memheap
, poh_freed
);
3379 sisfb_free_node(memheap
, poh_next
);
3384 poh_prev
->size
+= poh_freed
->size
;
3385 sisfb_free_node(memheap
, poh_freed
);
3390 poh_next
->size
+= poh_freed
->size
;
3391 poh_next
->offset
= poh_freed
->offset
;
3392 sisfb_free_node(memheap
, poh_freed
);
3396 sisfb_insert_node(&memheap
->oh_free
, poh_freed
);
3402 sisfb_free_node(struct SIS_HEAP
*memheap
, struct SIS_OH
*poh
)
3407 poh
->poh_next
= memheap
->poh_freelist
;
3408 memheap
->poh_freelist
= poh
;
3412 sis_int_malloc(struct sis_video_info
*ivideo
, struct sis_memreq
*req
)
3414 struct SIS_OH
*poh
= NULL
;
3416 if((ivideo
) && (ivideo
->sisfb_id
== SISFB_ID
) && (!ivideo
->havenoheap
))
3417 poh
= sisfb_poh_allocate(&ivideo
->sisfb_heap
, (u32
)req
->size
);
3420 req
->offset
= req
->size
= 0;
3421 DPRINTK("sisfb: Video RAM allocation failed\n");
3423 req
->offset
= poh
->offset
;
3424 req
->size
= poh
->size
;
3425 DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3426 (poh
->offset
+ ivideo
->video_vbase
));
3431 sis_malloc(struct sis_memreq
*req
)
3433 struct sis_video_info
*ivideo
= sisfb_heap
->vinfo
;
3435 if(&ivideo
->sisfb_heap
== sisfb_heap
)
3436 sis_int_malloc(ivideo
, req
);
3438 req
->offset
= req
->size
= 0;
3442 sis_malloc_new(struct pci_dev
*pdev
, struct sis_memreq
*req
)
3444 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
3446 sis_int_malloc(ivideo
, req
);
3449 /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3452 sis_int_free(struct sis_video_info
*ivideo
, u32 base
)
3456 if((!ivideo
) || (ivideo
->sisfb_id
!= SISFB_ID
) || (ivideo
->havenoheap
))
3459 poh
= sisfb_poh_free(&ivideo
->sisfb_heap
, base
);
3462 DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
3463 (unsigned int) base
);
3470 struct sis_video_info
*ivideo
= sisfb_heap
->vinfo
;
3472 sis_int_free(ivideo
, base
);
3476 sis_free_new(struct pci_dev
*pdev
, u32 base
)
3478 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
3480 sis_int_free(ivideo
, base
);
3483 /* --------------------- SetMode routines ------------------------- */
3486 sisfb_check_engine_and_sync(struct sis_video_info
*ivideo
)
3490 /* Check if MMIO and engines are enabled,
3491 * and sync in case they are. Can't use
3492 * ivideo->accel here, as this might have
3493 * been changed before this is called.
3495 cr30
= SiS_GetReg(SISSR
, IND_SIS_PCI_ADDRESS_SET
);
3496 cr31
= SiS_GetReg(SISSR
, IND_SIS_MODULE_ENABLE
);
3497 /* MMIO and 2D/3D engine enabled? */
3498 if((cr30
& SIS_MEM_MAP_IO_ENABLE
) && (cr31
& 0x42)) {
3499 #ifdef CONFIG_FB_SIS_300
3500 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3501 /* Don't care about TurboQueue. It's
3502 * enough to know that the engines
3505 sisfb_syncaccel(ivideo
);
3508 #ifdef CONFIG_FB_SIS_315
3509 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3510 /* Check that any queue mode is
3511 * enabled, and that the queue
3512 * is not in the state of "reset"
3514 cr30
= SiS_GetReg(SISSR
, 0x26);
3515 if((cr30
& 0xe0) && (!(cr30
& 0x01))) {
3516 sisfb_syncaccel(ivideo
);
3524 sisfb_pre_setmode(struct sis_video_info
*ivideo
)
3526 u8 cr30
= 0, cr31
= 0, cr33
= 0, cr35
= 0, cr38
= 0;
3529 ivideo
->currentvbflags
&= (VB_VIDEOBRIDGE
| VB_DISPTYPE_DISP2
);
3531 SiS_SetReg(SISSR
, 0x05, 0x86);
3533 cr31
= SiS_GetReg(SISCR
, 0x31);
3537 cr33
= ivideo
->rate_idx
& 0x0F;
3539 #ifdef CONFIG_FB_SIS_315
3540 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3541 if(ivideo
->chip
>= SIS_661
) {
3542 cr38
= SiS_GetReg(SISCR
, 0x38);
3543 cr38
&= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
3546 cr38
= SiS_GetReg(SISCR
, tvregnum
);
3547 cr38
&= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
3551 #ifdef CONFIG_FB_SIS_300
3552 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3554 cr38
= SiS_GetReg(SISCR
, tvregnum
);
3558 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
3559 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
3560 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
3562 switch(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
3565 cr38
&= ~0xc0; /* Clear PAL-M / PAL-N bits */
3566 if((ivideo
->vbflags
& TV_YPBPR
) && (ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) {
3567 #ifdef CONFIG_FB_SIS_315
3568 if(ivideo
->chip
>= SIS_661
) {
3570 if(ivideo
->vbflags
& TV_YPBPR525P
) cr35
|= 0x20;
3571 else if(ivideo
->vbflags
& TV_YPBPR750P
) cr35
|= 0x40;
3572 else if(ivideo
->vbflags
& TV_YPBPR1080I
) cr35
|= 0x60;
3573 cr30
|= SIS_SIMULTANEOUS_VIEW_ENABLE
;
3575 ivideo
->currentvbflags
|= (TV_YPBPR
| (ivideo
->vbflags
& TV_YPBPRALL
));
3576 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3577 cr30
|= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE
);
3579 if(ivideo
->vbflags
& TV_YPBPR525P
) cr38
|= 0x10;
3580 else if(ivideo
->vbflags
& TV_YPBPR750P
) cr38
|= 0x20;
3581 else if(ivideo
->vbflags
& TV_YPBPR1080I
) cr38
|= 0x30;
3583 ivideo
->currentvbflags
|= (TV_YPBPR
| (ivideo
->vbflags
& TV_YPBPRALL
));
3586 } else if((ivideo
->vbflags
& TV_HIVISION
) &&
3587 (ivideo
->vbflags2
& VB2_SISHIVISIONBRIDGE
)) {
3588 if(ivideo
->chip
>= SIS_661
) {
3594 cr30
|= SIS_SIMULTANEOUS_VIEW_ENABLE
;
3597 ivideo
->currentvbflags
|= TV_HIVISION
;
3598 } else if(ivideo
->vbflags
& TV_SCART
) {
3599 cr30
= (SIS_VB_OUTPUT_SCART
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3602 ivideo
->currentvbflags
|= TV_SCART
;
3604 if(ivideo
->vbflags
& TV_SVIDEO
) {
3605 cr30
= (SIS_VB_OUTPUT_SVIDEO
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3606 ivideo
->currentvbflags
|= TV_SVIDEO
;
3608 if(ivideo
->vbflags
& TV_AVIDEO
) {
3609 cr30
= (SIS_VB_OUTPUT_COMPOSITE
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3610 ivideo
->currentvbflags
|= TV_AVIDEO
;
3613 cr31
|= SIS_DRIVER_MODE
;
3615 if(ivideo
->vbflags
& (TV_AVIDEO
| TV_SVIDEO
)) {
3616 if(ivideo
->vbflags
& TV_PAL
) {
3617 cr31
|= 0x01; cr35
|= 0x01;
3618 ivideo
->currentvbflags
|= TV_PAL
;
3619 if(ivideo
->vbflags
& TV_PALM
) {
3620 cr38
|= 0x40; cr35
|= 0x04;
3621 ivideo
->currentvbflags
|= TV_PALM
;
3622 } else if(ivideo
->vbflags
& TV_PALN
) {
3623 cr38
|= 0x80; cr35
|= 0x08;
3624 ivideo
->currentvbflags
|= TV_PALN
;
3627 cr31
&= ~0x01; cr35
&= ~0x01;
3628 ivideo
->currentvbflags
|= TV_NTSC
;
3629 if(ivideo
->vbflags
& TV_NTSCJ
) {
3630 cr38
|= 0x40; cr35
|= 0x02;
3631 ivideo
->currentvbflags
|= TV_NTSCJ
;
3638 cr30
= (SIS_VB_OUTPUT_LCD
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3639 cr31
|= SIS_DRIVER_MODE
;
3640 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, ivideo
->sisfb_dstn
);
3641 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, ivideo
->sisfb_fstn
);
3642 ivideo
->curFSTN
= ivideo
->sisfb_fstn
;
3643 ivideo
->curDSTN
= ivideo
->sisfb_dstn
;
3647 cr30
= (SIS_VB_OUTPUT_CRT2
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3648 cr31
|= SIS_DRIVER_MODE
;
3649 if(ivideo
->sisfb_nocrt2rate
) {
3650 cr33
|= (sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
<< 4);
3652 cr33
|= ((ivideo
->rate_idx
& 0x0F) << 4);
3656 default: /* disable CRT2 */
3658 cr31
|= (SIS_DRIVER_MODE
| SIS_VB_OUTPUT_DISABLE
);
3661 SiS_SetReg(SISCR
, 0x30, cr30
);
3662 SiS_SetReg(SISCR
, 0x33, cr33
);
3664 if(ivideo
->chip
>= SIS_661
) {
3665 #ifdef CONFIG_FB_SIS_315
3666 cr31
&= ~0x01; /* Clear PAL flag (now in CR35) */
3667 SiS_SetRegANDOR(SISCR
, 0x35, ~0x10, cr35
); /* Leave overscan bit alone */
3668 cr38
&= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
3669 SiS_SetRegANDOR(SISCR
, 0x38, 0xf8, cr38
);
3671 } else if(ivideo
->chip
!= SIS_300
) {
3672 SiS_SetReg(SISCR
, tvregnum
, cr38
);
3674 SiS_SetReg(SISCR
, 0x31, cr31
);
3676 ivideo
->SiS_Pr
.SiS_UseOEM
= ivideo
->sisfb_useoem
;
3678 sisfb_check_engine_and_sync(ivideo
);
3681 /* Fix SR11 for 661 and later */
3682 #ifdef CONFIG_FB_SIS_315
3684 sisfb_fixup_SR11(struct sis_video_info
*ivideo
)
3688 if(ivideo
->chip
>= SIS_661
) {
3689 tmpreg
= SiS_GetReg(SISSR
, 0x11);
3691 tmpreg
= SiS_GetReg(SISSR
, 0x3e);
3692 tmpreg
= (tmpreg
+ 1) & 0xff;
3693 SiS_SetReg(SISSR
, 0x3e, tmpreg
);
3694 tmpreg
= SiS_GetReg(SISSR
, 0x11);
3697 SiS_SetRegAND(SISSR
, 0x11, 0x0f);
3704 sisfb_set_TVxposoffset(struct sis_video_info
*ivideo
, int val
)
3706 if(val
> 32) val
= 32;
3707 if(val
< -32) val
= -32;
3708 ivideo
->tvxpos
= val
;
3710 if(ivideo
->sisfblocked
) return;
3711 if(!ivideo
->modechanged
) return;
3713 if(ivideo
->currentvbflags
& CRT2_TV
) {
3715 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3717 int x
= ivideo
->tvx
;
3719 switch(ivideo
->chronteltype
) {
3723 SiS_SetReg(SISSR
, 0x05, 0x86);
3724 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0a, (x
& 0xff));
3725 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x08, ((x
& 0x0100) >> 7), 0xFD);
3728 /* Not supported by hardware */
3732 } else if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3734 u8 p2_1f
,p2_20
,p2_2b
,p2_42
,p2_43
;
3735 unsigned short temp
;
3737 p2_1f
= ivideo
->p2_1f
;
3738 p2_20
= ivideo
->p2_20
;
3739 p2_2b
= ivideo
->p2_2b
;
3740 p2_42
= ivideo
->p2_42
;
3741 p2_43
= ivideo
->p2_43
;
3743 temp
= p2_1f
| ((p2_20
& 0xf0) << 4);
3745 p2_1f
= temp
& 0xff;
3746 p2_20
= (temp
& 0xf00) >> 4;
3747 p2_2b
= ((p2_2b
& 0x0f) + (val
* 2)) & 0x0f;
3748 temp
= p2_43
| ((p2_42
& 0xf0) << 4);
3750 p2_43
= temp
& 0xff;
3751 p2_42
= (temp
& 0xf00) >> 4;
3752 SiS_SetReg(SISPART2
, 0x1f, p2_1f
);
3753 SiS_SetRegANDOR(SISPART2
, 0x20, 0x0F, p2_20
);
3754 SiS_SetRegANDOR(SISPART2
, 0x2b, 0xF0, p2_2b
);
3755 SiS_SetRegANDOR(SISPART2
, 0x42, 0x0F, p2_42
);
3756 SiS_SetReg(SISPART2
, 0x43, p2_43
);
3762 sisfb_set_TVyposoffset(struct sis_video_info
*ivideo
, int val
)
3764 if(val
> 32) val
= 32;
3765 if(val
< -32) val
= -32;
3766 ivideo
->tvypos
= val
;
3768 if(ivideo
->sisfblocked
) return;
3769 if(!ivideo
->modechanged
) return;
3771 if(ivideo
->currentvbflags
& CRT2_TV
) {
3773 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3775 int y
= ivideo
->tvy
;
3777 switch(ivideo
->chronteltype
) {
3781 SiS_SetReg(SISSR
, 0x05, 0x86);
3782 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0b, (y
& 0xff));
3783 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x08, ((y
& 0x0100) >> 8), 0xFE);
3786 /* Not supported by hardware */
3790 } else if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3794 p2_01
= ivideo
->p2_01
;
3795 p2_02
= ivideo
->p2_02
;
3799 if(!(ivideo
->currentvbflags
& (TV_HIVISION
| TV_YPBPR
))) {
3800 while((p2_01
<= 0) || (p2_02
<= 0)) {
3805 SiS_SetReg(SISPART2
, 0x01, p2_01
);
3806 SiS_SetReg(SISPART2
, 0x02, p2_02
);
3812 sisfb_post_setmode(struct sis_video_info
*ivideo
)
3814 bool crt1isoff
= false;
3816 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
3819 #ifdef CONFIG_FB_SIS_315
3823 SiS_SetReg(SISSR
, 0x05, 0x86);
3825 #ifdef CONFIG_FB_SIS_315
3826 sisfb_fixup_SR11(ivideo
);
3829 /* Now we actually HAVE changed the display mode */
3830 ivideo
->modechanged
= 1;
3832 /* We can't switch off CRT1 if bridge is in slave mode */
3833 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
3834 if(sisfb_bridgeisslave(ivideo
)) doit
= false;
3836 ivideo
->sisfb_crt1off
= 0;
3838 #ifdef CONFIG_FB_SIS_300
3839 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3840 if((ivideo
->sisfb_crt1off
) && (doit
)) {
3847 SiS_SetRegANDOR(SISCR
, 0x17, 0x7f, reg
);
3850 #ifdef CONFIG_FB_SIS_315
3851 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3852 if((ivideo
->sisfb_crt1off
) && (doit
)) {
3861 SiS_SetRegANDOR(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, ~0x40, reg
);
3862 SiS_SetRegANDOR(SISSR
, 0x1f, 0x3f, reg1
);
3867 ivideo
->currentvbflags
&= ~VB_DISPTYPE_CRT1
;
3868 ivideo
->currentvbflags
|= VB_SINGLE_MODE
;
3870 ivideo
->currentvbflags
|= VB_DISPTYPE_CRT1
;
3871 if(ivideo
->currentvbflags
& VB_DISPTYPE_CRT2
) {
3872 ivideo
->currentvbflags
|= VB_MIRROR_MODE
;
3874 ivideo
->currentvbflags
|= VB_SINGLE_MODE
;
3878 SiS_SetRegAND(SISSR
, IND_SIS_RAMDAC_CONTROL
, ~0x04);
3880 if(ivideo
->currentvbflags
& CRT2_TV
) {
3881 if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3882 ivideo
->p2_1f
= SiS_GetReg(SISPART2
, 0x1f);
3883 ivideo
->p2_20
= SiS_GetReg(SISPART2
, 0x20);
3884 ivideo
->p2_2b
= SiS_GetReg(SISPART2
, 0x2b);
3885 ivideo
->p2_42
= SiS_GetReg(SISPART2
, 0x42);
3886 ivideo
->p2_43
= SiS_GetReg(SISPART2
, 0x43);
3887 ivideo
->p2_01
= SiS_GetReg(SISPART2
, 0x01);
3888 ivideo
->p2_02
= SiS_GetReg(SISPART2
, 0x02);
3889 } else if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3890 if(ivideo
->chronteltype
== 1) {
3891 ivideo
->tvx
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0a);
3892 ivideo
->tvx
|= (((SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x08) & 0x02) >> 1) << 8);
3893 ivideo
->tvy
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0b);
3894 ivideo
->tvy
|= ((SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x08) & 0x01) << 8);
3899 if(ivideo
->tvxpos
) {
3900 sisfb_set_TVxposoffset(ivideo
, ivideo
->tvxpos
);
3902 if(ivideo
->tvypos
) {
3903 sisfb_set_TVyposoffset(ivideo
, ivideo
->tvypos
);
3906 /* Eventually sync engines */
3907 sisfb_check_engine_and_sync(ivideo
);
3909 /* (Re-)Initialize chip engines */
3911 sisfb_engine_init(ivideo
);
3913 ivideo
->engineok
= 0;
3918 sisfb_reset_mode(struct sis_video_info
*ivideo
)
3920 if(sisfb_set_mode(ivideo
, 0))
3923 sisfb_set_pitch(ivideo
);
3924 sisfb_set_base_CRT1(ivideo
, ivideo
->current_base
);
3925 sisfb_set_base_CRT2(ivideo
, ivideo
->current_base
);
3931 sisfb_handle_command(struct sis_video_info
*ivideo
, struct sisfb_cmd
*sisfb_command
)
3935 switch(sisfb_command
->sisfb_cmd
) {
3936 case SISFB_CMD_GETVBFLAGS
:
3937 if(!ivideo
->modechanged
) {
3938 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_EARLY
;
3940 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3941 sisfb_command
->sisfb_result
[1] = ivideo
->currentvbflags
;
3942 sisfb_command
->sisfb_result
[2] = ivideo
->vbflags2
;
3945 case SISFB_CMD_SWITCHCRT1
:
3946 /* arg[0]: 0 = off, 1 = on, 99 = query */
3947 if(!ivideo
->modechanged
) {
3948 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_EARLY
;
3949 } else if(sisfb_command
->sisfb_arg
[0] == 99) {
3951 sisfb_command
->sisfb_result
[1] = ivideo
->sisfb_crt1off
? 0 : 1;
3952 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3953 } else if(ivideo
->sisfblocked
) {
3954 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_LOCKED
;
3955 } else if((!(ivideo
->currentvbflags
& CRT2_ENABLE
)) &&
3956 (sisfb_command
->sisfb_arg
[0] == 0)) {
3957 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_NOCRT2
;
3959 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3960 mycrt1off
= sisfb_command
->sisfb_arg
[0] ? 0 : 1;
3961 if( ((ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
) && mycrt1off
) ||
3962 ((!(ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
)) && !mycrt1off
) ) {
3963 ivideo
->sisfb_crt1off
= mycrt1off
;
3964 if(sisfb_reset_mode(ivideo
)) {
3965 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OTHER
;
3968 sisfb_command
->sisfb_result
[1] = ivideo
->sisfb_crt1off
? 0 : 1;
3973 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_UNKNOWN
;
3974 printk(KERN_ERR
"sisfb: Unknown command 0x%x\n",
3975 sisfb_command
->sisfb_cmd
);
3980 static int __init
sisfb_setup(char *options
)
3984 sisfb_setdefaultparms();
3986 if(!options
|| !(*options
))
3989 while((this_opt
= strsep(&options
, ",")) != NULL
) {
3991 if(!(*this_opt
)) continue;
3993 if(!strncasecmp(this_opt
, "off", 3)) {
3995 } else if(!strncasecmp(this_opt
, "forcecrt2type:", 14)) {
3996 /* Need to check crt2 type first for fstn/dstn */
3997 sisfb_search_crt2type(this_opt
+ 14);
3998 } else if(!strncasecmp(this_opt
, "tvmode:",7)) {
3999 sisfb_search_tvstd(this_opt
+ 7);
4000 } else if(!strncasecmp(this_opt
, "tvstandard:",11)) {
4001 sisfb_search_tvstd(this_opt
+ 11);
4002 } else if(!strncasecmp(this_opt
, "mode:", 5)) {
4003 sisfb_search_mode(this_opt
+ 5, false);
4004 } else if(!strncasecmp(this_opt
, "vesa:", 5)) {
4005 sisfb_search_vesamode(simple_strtoul(this_opt
+ 5, NULL
, 0), false);
4006 } else if(!strncasecmp(this_opt
, "rate:", 5)) {
4007 sisfb_parm_rate
= simple_strtoul(this_opt
+ 5, NULL
, 0);
4008 } else if(!strncasecmp(this_opt
, "forcecrt1:", 10)) {
4009 sisfb_forcecrt1
= (int)simple_strtoul(this_opt
+ 10, NULL
, 0);
4010 } else if(!strncasecmp(this_opt
, "mem:",4)) {
4011 sisfb_parm_mem
= simple_strtoul(this_opt
+ 4, NULL
, 0);
4012 } else if(!strncasecmp(this_opt
, "pdc:", 4)) {
4013 sisfb_pdc
= simple_strtoul(this_opt
+ 4, NULL
, 0);
4014 } else if(!strncasecmp(this_opt
, "pdc1:", 5)) {
4015 sisfb_pdca
= simple_strtoul(this_opt
+ 5, NULL
, 0);
4016 } else if(!strncasecmp(this_opt
, "noaccel", 7)) {
4018 } else if(!strncasecmp(this_opt
, "accel", 5)) {
4020 } else if(!strncasecmp(this_opt
, "noypan", 6)) {
4022 } else if(!strncasecmp(this_opt
, "ypan", 4)) {
4024 } else if(!strncasecmp(this_opt
, "nomax", 5)) {
4026 } else if(!strncasecmp(this_opt
, "max", 3)) {
4028 } else if(!strncasecmp(this_opt
, "userom:", 7)) {
4029 sisfb_userom
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
4030 } else if(!strncasecmp(this_opt
, "useoem:", 7)) {
4031 sisfb_useoem
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
4032 } else if(!strncasecmp(this_opt
, "nocrt2rate", 10)) {
4033 sisfb_nocrt2rate
= 1;
4034 } else if(!strncasecmp(this_opt
, "scalelcd:", 9)) {
4035 unsigned long temp
= 2;
4036 temp
= simple_strtoul(this_opt
+ 9, NULL
, 0);
4037 if((temp
== 0) || (temp
== 1)) {
4038 sisfb_scalelcd
= temp
^ 1;
4040 } else if(!strncasecmp(this_opt
, "tvxposoffset:", 13)) {
4042 temp
= (int)simple_strtol(this_opt
+ 13, NULL
, 0);
4043 if((temp
>= -32) && (temp
<= 32)) {
4044 sisfb_tvxposoffset
= temp
;
4046 } else if(!strncasecmp(this_opt
, "tvyposoffset:", 13)) {
4048 temp
= (int)simple_strtol(this_opt
+ 13, NULL
, 0);
4049 if((temp
>= -32) && (temp
<= 32)) {
4050 sisfb_tvyposoffset
= temp
;
4052 } else if(!strncasecmp(this_opt
, "specialtiming:", 14)) {
4053 sisfb_search_specialtiming(this_opt
+ 14);
4054 } else if(!strncasecmp(this_opt
, "lvdshl:", 7)) {
4056 temp
= simple_strtoul(this_opt
+ 7, NULL
, 0);
4057 if((temp
>= 0) && (temp
<= 3)) {
4058 sisfb_lvdshl
= temp
;
4060 } else if(this_opt
[0] >= '0' && this_opt
[0] <= '9') {
4061 sisfb_search_mode(this_opt
, true);
4062 #if !defined(__i386__) && !defined(__x86_64__)
4063 } else if(!strncasecmp(this_opt
, "resetcard", 9)) {
4064 sisfb_resetcard
= 1;
4065 } else if(!strncasecmp(this_opt
, "videoram:", 9)) {
4066 sisfb_videoram
= simple_strtoul(this_opt
+ 9, NULL
, 0);
4069 printk(KERN_INFO
"sisfb: Invalid option %s\n", this_opt
);
4078 static int sisfb_check_rom(void __iomem
*rom_base
,
4079 struct sis_video_info
*ivideo
)
4084 if((readb(rom_base
) != 0x55) || (readb(rom_base
+ 1) != 0xaa))
4087 romptr
= (readb(rom_base
+ 0x18) | (readb(rom_base
+ 0x19) << 8));
4088 if(romptr
> (0x10000 - 8))
4091 rom
= rom_base
+ romptr
;
4093 if((readb(rom
) != 'P') || (readb(rom
+ 1) != 'C') ||
4094 (readb(rom
+ 2) != 'I') || (readb(rom
+ 3) != 'R'))
4097 if((readb(rom
+ 4) | (readb(rom
+ 5) << 8)) != ivideo
->chip_vendor
)
4100 if((readb(rom
+ 6) | (readb(rom
+ 7) << 8)) != ivideo
->chip_id
)
4106 static unsigned char *sisfb_find_rom(struct pci_dev
*pdev
)
4108 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4109 void __iomem
*rom_base
;
4110 unsigned char *myrombase
= NULL
;
4113 /* First, try the official pci ROM functions (except
4114 * on integrated chipsets which have no ROM).
4117 if(!ivideo
->nbridge
) {
4119 if((rom_base
= pci_map_rom(pdev
, &romsize
))) {
4121 if(sisfb_check_rom(rom_base
, ivideo
)) {
4123 if((myrombase
= vmalloc(65536))) {
4124 memcpy_fromio(myrombase
, rom_base
,
4125 (romsize
> 65536) ? 65536 : romsize
);
4128 pci_unmap_rom(pdev
, rom_base
);
4132 if(myrombase
) return myrombase
;
4134 /* Otherwise do it the conventional way. */
4136 #if defined(__i386__) || defined(__x86_64__)
4140 for (temp
= 0x000c0000; temp
< 0x000f0000; temp
+= 0x00001000) {
4142 rom_base
= ioremap(temp
, 65536);
4146 if (!sisfb_check_rom(rom_base
, ivideo
)) {
4151 if ((myrombase
= vmalloc(65536)))
4152 memcpy_fromio(myrombase
, rom_base
, 65536);
4165 static void sisfb_post_map_vram(struct sis_video_info
*ivideo
,
4166 unsigned int *mapsize
, unsigned int min
)
4168 if (*mapsize
< (min
<< 20))
4171 ivideo
->video_vbase
= ioremap_wc(ivideo
->video_base
, (*mapsize
));
4173 if(!ivideo
->video_vbase
) {
4175 "sisfb: Unable to map maximum video RAM for size detection\n");
4177 while((!(ivideo
->video_vbase
= ioremap_wc(ivideo
->video_base
, (*mapsize
))))) {
4179 if((*mapsize
) < (min
<< 20))
4182 if(ivideo
->video_vbase
) {
4184 "sisfb: Video RAM size detection limited to %dMB\n",
4185 (int)((*mapsize
) >> 20));
4190 #ifdef CONFIG_FB_SIS_300
4191 static int sisfb_post_300_buswidth(struct sis_video_info
*ivideo
)
4193 void __iomem
*FBAddress
= ivideo
->video_vbase
;
4194 unsigned short temp
;
4198 SiS_SetRegAND(SISSR
, 0x15, 0xFB);
4199 SiS_SetRegOR(SISSR
, 0x15, 0x04);
4200 SiS_SetReg(SISSR
, 0x13, 0x00);
4201 SiS_SetReg(SISSR
, 0x14, 0xBF);
4203 for(i
= 0; i
< 2; i
++) {
4205 for(j
= 0; j
< 4; j
++) {
4206 writew(temp
, FBAddress
);
4207 if(readw(FBAddress
) == temp
)
4209 SiS_SetRegOR(SISSR
, 0x3c, 0x01);
4210 reg
= SiS_GetReg(SISSR
, 0x05);
4211 reg
= SiS_GetReg(SISSR
, 0x05);
4212 SiS_SetRegAND(SISSR
, 0x3c, 0xfe);
4213 reg
= SiS_GetReg(SISSR
, 0x05);
4214 reg
= SiS_GetReg(SISSR
, 0x05);
4219 writel(0x01234567L
, FBAddress
);
4220 writel(0x456789ABL
, (FBAddress
+ 4));
4221 writel(0x89ABCDEFL
, (FBAddress
+ 8));
4222 writel(0xCDEF0123L
, (FBAddress
+ 12));
4224 reg
= SiS_GetReg(SISSR
, 0x3b);
4226 if(readl((FBAddress
+ 12)) == 0xCDEF0123L
)
4227 return 4; /* Channel A 128bit */
4230 if(readl((FBAddress
+ 4)) == 0x456789ABL
)
4231 return 2; /* Channel B 64bit */
4233 return 1; /* 32bit */
4236 static const unsigned short SiS_DRAMType
[17][5] = {
4237 {0x0C,0x0A,0x02,0x40,0x39},
4238 {0x0D,0x0A,0x01,0x40,0x48},
4239 {0x0C,0x09,0x02,0x20,0x35},
4240 {0x0D,0x09,0x01,0x20,0x44},
4241 {0x0C,0x08,0x02,0x10,0x31},
4242 {0x0D,0x08,0x01,0x10,0x40},
4243 {0x0C,0x0A,0x01,0x20,0x34},
4244 {0x0C,0x09,0x01,0x08,0x32},
4245 {0x0B,0x08,0x02,0x08,0x21},
4246 {0x0C,0x08,0x01,0x08,0x30},
4247 {0x0A,0x08,0x02,0x04,0x11},
4248 {0x0B,0x0A,0x01,0x10,0x28},
4249 {0x09,0x08,0x02,0x02,0x01},
4250 {0x0B,0x09,0x01,0x08,0x24},
4251 {0x0B,0x08,0x01,0x04,0x20},
4252 {0x0A,0x08,0x01,0x02,0x10},
4253 {0x09,0x08,0x01,0x01,0x00}
4256 static int sisfb_post_300_rwtest(struct sis_video_info
*ivideo
, int iteration
,
4257 int buswidth
, int PseudoRankCapacity
,
4258 int PseudoAdrPinCount
, unsigned int mapsize
)
4260 void __iomem
*FBAddr
= ivideo
->video_vbase
;
4261 unsigned short sr14
;
4262 unsigned int k
, RankCapacity
, PageCapacity
, BankNumHigh
, BankNumMid
;
4263 unsigned int PhysicalAdrOtherPage
, PhysicalAdrHigh
, PhysicalAdrHalfPage
;
4265 for(k
= 0; k
< ARRAY_SIZE(SiS_DRAMType
); k
++) {
4267 RankCapacity
= buswidth
* SiS_DRAMType
[k
][3];
4269 if(RankCapacity
!= PseudoRankCapacity
)
4272 if((SiS_DRAMType
[k
][2] + SiS_DRAMType
[k
][0]) > PseudoAdrPinCount
)
4275 BankNumHigh
= RankCapacity
* 16 * iteration
- 1;
4276 if(iteration
== 3) { /* Rank No */
4277 BankNumMid
= RankCapacity
* 16 - 1;
4279 BankNumMid
= RankCapacity
* 16 * iteration
/ 2 - 1;
4282 PageCapacity
= (1 << SiS_DRAMType
[k
][1]) * buswidth
* 4;
4283 PhysicalAdrHigh
= BankNumHigh
;
4284 PhysicalAdrHalfPage
= (PageCapacity
/ 2 + PhysicalAdrHigh
) % PageCapacity
;
4285 PhysicalAdrOtherPage
= PageCapacity
* SiS_DRAMType
[k
][2] + PhysicalAdrHigh
;
4287 SiS_SetRegAND(SISSR
, 0x15, 0xFB); /* Test */
4288 SiS_SetRegOR(SISSR
, 0x15, 0x04); /* Test */
4289 sr14
= (SiS_DRAMType
[k
][3] * buswidth
) - 1;
4290 if(buswidth
== 4) sr14
|= 0x80;
4291 else if(buswidth
== 2) sr14
|= 0x40;
4292 SiS_SetReg(SISSR
, 0x13, SiS_DRAMType
[k
][4]);
4293 SiS_SetReg(SISSR
, 0x14, sr14
);
4298 if((BankNumHigh
+ PhysicalAdrHigh
>= mapsize
) ||
4299 (BankNumMid
+ PhysicalAdrHigh
>= mapsize
) ||
4300 (BankNumHigh
+ PhysicalAdrHalfPage
>= mapsize
) ||
4301 (BankNumHigh
+ PhysicalAdrOtherPage
>= mapsize
))
4305 writew(((unsigned short)PhysicalAdrHigh
),
4306 (FBAddr
+ BankNumHigh
+ PhysicalAdrHigh
));
4307 writew(((unsigned short)BankNumMid
),
4308 (FBAddr
+ BankNumMid
+ PhysicalAdrHigh
));
4309 writew(((unsigned short)PhysicalAdrHalfPage
),
4310 (FBAddr
+ BankNumHigh
+ PhysicalAdrHalfPage
));
4311 writew(((unsigned short)PhysicalAdrOtherPage
),
4312 (FBAddr
+ BankNumHigh
+ PhysicalAdrOtherPage
));
4315 if(readw(FBAddr
+ BankNumHigh
+ PhysicalAdrHigh
) == PhysicalAdrHigh
)
4322 static void sisfb_post_300_ramsize(struct pci_dev
*pdev
, unsigned int mapsize
)
4324 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4326 int PseudoRankCapacity
, PseudoAdrPinCount
;
4328 buswidth
= sisfb_post_300_buswidth(ivideo
);
4330 for(i
= 6; i
>= 0; i
--) {
4331 PseudoRankCapacity
= 1 << i
;
4332 for(j
= 4; j
>= 1; j
--) {
4333 PseudoAdrPinCount
= 15 - j
;
4334 if((PseudoRankCapacity
* j
) <= 64) {
4335 if(sisfb_post_300_rwtest(ivideo
,
4347 static void sisfb_post_sis300(struct pci_dev
*pdev
)
4349 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4350 unsigned char *bios
= ivideo
->SiS_Pr
.VirtualRomBase
;
4351 u8 reg
, v1
, v2
, v3
, v4
, v5
, v6
, v7
, v8
;
4352 u16 index
, rindex
, memtype
= 0;
4353 unsigned int mapsize
;
4355 if(!ivideo
->SiS_Pr
.UseROM
)
4358 SiS_SetReg(SISSR
, 0x05, 0x86);
4361 if(bios
[0x52] & 0x80) {
4362 memtype
= bios
[0x52];
4364 memtype
= SiS_GetReg(SISSR
, 0x3a);
4369 v3
= 0x80; v6
= 0x80;
4370 if(ivideo
->revision_id
<= 0x13) {
4371 v1
= 0x44; v2
= 0x42;
4372 v4
= 0x44; v5
= 0x42;
4374 v1
= 0x68; v2
= 0x43; /* Assume 125Mhz MCLK */
4375 v4
= 0x68; v5
= 0x43; /* Assume 125Mhz ECLK */
4377 index
= memtype
* 5;
4378 rindex
= index
+ 0x54;
4379 v1
= bios
[rindex
++];
4380 v2
= bios
[rindex
++];
4381 v3
= bios
[rindex
++];
4382 rindex
= index
+ 0x7c;
4383 v4
= bios
[rindex
++];
4384 v5
= bios
[rindex
++];
4385 v6
= bios
[rindex
++];
4388 SiS_SetReg(SISSR
, 0x28, v1
);
4389 SiS_SetReg(SISSR
, 0x29, v2
);
4390 SiS_SetReg(SISSR
, 0x2a, v3
);
4391 SiS_SetReg(SISSR
, 0x2e, v4
);
4392 SiS_SetReg(SISSR
, 0x2f, v5
);
4393 SiS_SetReg(SISSR
, 0x30, v6
);
4398 SiS_SetReg(SISSR
, 0x07, v1
); /* DAC speed */
4400 SiS_SetReg(SISSR
, 0x11, 0x0f); /* DDC, power save */
4402 v1
= 0x01; v2
= 0x43; v3
= 0x1e; v4
= 0x2a;
4403 v5
= 0x06; v6
= 0x00; v7
= 0x00; v8
= 0x00;
4407 v2
= bios
[memtype
+ 8];
4408 v3
= bios
[memtype
+ 16];
4409 v4
= bios
[memtype
+ 24];
4410 v5
= bios
[memtype
+ 32];
4411 v6
= bios
[memtype
+ 40];
4412 v7
= bios
[memtype
+ 48];
4413 v8
= bios
[memtype
+ 56];
4415 if(ivideo
->revision_id
>= 0x80)
4417 SiS_SetReg(SISSR
, 0x15, v1
); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4418 SiS_SetReg(SISSR
, 0x16, v2
);
4419 SiS_SetReg(SISSR
, 0x17, v3
);
4420 SiS_SetReg(SISSR
, 0x18, v4
);
4421 SiS_SetReg(SISSR
, 0x19, v5
);
4422 SiS_SetReg(SISSR
, 0x1a, v6
);
4423 SiS_SetReg(SISSR
, 0x1b, v7
);
4424 SiS_SetReg(SISSR
, 0x1c, v8
); /* ---- */
4425 SiS_SetRegAND(SISSR
, 0x15, 0xfb);
4426 SiS_SetRegOR(SISSR
, 0x15, 0x04);
4428 if(bios
[0x53] & 0x02) {
4429 SiS_SetRegOR(SISSR
, 0x19, 0x20);
4432 v1
= 0x04; /* DAC pedestal (BIOS 0xe5) */
4433 if(ivideo
->revision_id
>= 0x80)
4435 SiS_SetReg(SISSR
, 0x1f, v1
);
4436 SiS_SetReg(SISSR
, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
4437 v1
= 0xf6; v2
= 0x0d; v3
= 0x00;
4443 SiS_SetReg(SISSR
, 0x23, v1
);
4444 SiS_SetReg(SISSR
, 0x24, v2
);
4445 SiS_SetReg(SISSR
, 0x25, v3
);
4446 SiS_SetReg(SISSR
, 0x21, 0x84);
4447 SiS_SetReg(SISSR
, 0x22, 0x00);
4448 SiS_SetReg(SISCR
, 0x37, 0x00);
4449 SiS_SetRegOR(SISPART1
, 0x24, 0x01); /* unlock crt2 */
4450 SiS_SetReg(SISPART1
, 0x00, 0x00);
4451 v1
= 0x40; v2
= 0x11;
4456 SiS_SetReg(SISPART1
, 0x02, v1
);
4458 if(ivideo
->revision_id
>= 0x80)
4461 reg
= SiS_GetReg(SISPART4
, 0x00);
4462 if((reg
== 1) || (reg
== 2)) {
4463 SiS_SetReg(SISCR
, 0x37, 0x02);
4464 SiS_SetReg(SISPART2
, 0x00, 0x1c);
4465 v4
= 0x00; v5
= 0x00; v6
= 0x10;
4466 if(ivideo
->SiS_Pr
.UseROM
) {
4471 SiS_SetReg(SISPART4
, 0x0d, v4
);
4472 SiS_SetReg(SISPART4
, 0x0e, v5
);
4473 SiS_SetReg(SISPART4
, 0x10, v6
);
4474 SiS_SetReg(SISPART4
, 0x0f, 0x3f);
4475 reg
= SiS_GetReg(SISPART4
, 0x01);
4477 reg
= SiS_GetReg(SISPART4
, 0x23);
4480 SiS_SetReg(SISPART4
, 0x23, reg
);
4485 SiS_SetReg(SISSR
, 0x32, v2
);
4487 SiS_SetRegAND(SISPART1
, 0x24, 0xfe); /* Lock CRT2 */
4489 reg
= SiS_GetReg(SISSR
, 0x16);
4491 SiS_SetReg(SISCR
, 0x35, reg
);
4492 SiS_SetReg(SISCR
, 0x83, 0x00);
4493 #if !defined(__i386__) && !defined(__x86_64__)
4494 if(sisfb_videoram
) {
4495 SiS_SetReg(SISSR
, 0x13, 0x28); /* ? */
4496 reg
= ((sisfb_videoram
>> 10) - 1) | 0x40;
4497 SiS_SetReg(SISSR
, 0x14, reg
);
4500 /* Need to map max FB size for finding out about RAM size */
4501 mapsize
= ivideo
->video_size
;
4502 sisfb_post_map_vram(ivideo
, &mapsize
, 4);
4504 if(ivideo
->video_vbase
) {
4505 sisfb_post_300_ramsize(pdev
, mapsize
);
4506 iounmap(ivideo
->video_vbase
);
4509 "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4510 SiS_SetReg(SISSR
, 0x13, 0x28); /* ? */
4511 SiS_SetReg(SISSR
, 0x14, 0x47); /* 8MB, 64bit default */
4513 #if !defined(__i386__) && !defined(__x86_64__)
4520 reg
= SiS_GetReg(SISSR
, 0x3a);
4521 if((reg
& 0x30) == 0x30) {
4522 v1
= 0x04; /* PCI */
4525 v1
= 0x14; /* AGP */
4529 SiS_SetReg(SISSR
, 0x21, v1
);
4530 SiS_SetReg(SISSR
, 0x22, v2
);
4533 sisfb_sense_crt1(ivideo
);
4535 /* Set default mode, don't clear screen */
4536 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
4537 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
4538 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
4539 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
4540 ivideo
->SiS_Pr
.VideoMemorySize
= 8 << 20;
4541 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
4543 SiS_SetReg(SISSR
, 0x05, 0x86);
4546 SiS_SetRegOR(SISSR
, 0x01, 0x20);
4548 /* Save mode number in CR34 */
4549 SiS_SetReg(SISCR
, 0x34, 0x2e);
4551 /* Let everyone know what the current mode is */
4552 ivideo
->modeprechange
= 0x2e;
4556 #ifdef CONFIG_FB_SIS_315
4558 static void sisfb_post_sis315330(struct pci_dev
*pdev
)
4564 static inline int sisfb_xgi_is21(struct sis_video_info
*ivideo
)
4566 return ivideo
->chip_real_id
== XGI_21
;
4569 static void sisfb_post_xgi_delay(struct sis_video_info
*ivideo
, int delay
)
4574 for(i
= 0; i
<= (delay
* 10 * 36); i
++) {
4575 reg
= SiS_GetReg(SISSR
, 0x05);
4580 static int sisfb_find_host_bridge(struct sis_video_info
*ivideo
,
4581 struct pci_dev
*mypdev
,
4582 unsigned short pcivendor
)
4584 struct pci_dev
*pdev
= NULL
;
4585 unsigned short temp
;
4588 while((pdev
= pci_get_class(PCI_CLASS_BRIDGE_HOST
, pdev
))) {
4589 temp
= pdev
->vendor
;
4590 if(temp
== pcivendor
) {
4600 static int sisfb_post_xgi_rwtest(struct sis_video_info
*ivideo
, int starta
,
4601 unsigned int enda
, unsigned int mapsize
)
4606 writel(0, ivideo
->video_vbase
);
4608 for(i
= starta
; i
<= enda
; i
++) {
4611 writel(pos
, ivideo
->video_vbase
+ pos
);
4614 sisfb_post_xgi_delay(ivideo
, 150);
4616 if(readl(ivideo
->video_vbase
) != 0)
4619 for(i
= starta
; i
<= enda
; i
++) {
4622 if(readl(ivideo
->video_vbase
+ pos
) != pos
)
4631 static int sisfb_post_xgi_ramsize(struct sis_video_info
*ivideo
)
4633 unsigned int buswidth
, ranksize
, channelab
, mapsize
;
4634 int i
, j
, k
, l
, status
;
4636 static const u8 dramsr13
[12 * 5] = {
4637 0x02, 0x0e, 0x0b, 0x80, 0x5d,
4638 0x02, 0x0e, 0x0a, 0x40, 0x59,
4639 0x02, 0x0d, 0x0b, 0x40, 0x4d,
4640 0x02, 0x0e, 0x09, 0x20, 0x55,
4641 0x02, 0x0d, 0x0a, 0x20, 0x49,
4642 0x02, 0x0c, 0x0b, 0x20, 0x3d,
4643 0x02, 0x0e, 0x08, 0x10, 0x51,
4644 0x02, 0x0d, 0x09, 0x10, 0x45,
4645 0x02, 0x0c, 0x0a, 0x10, 0x39,
4646 0x02, 0x0d, 0x08, 0x08, 0x41,
4647 0x02, 0x0c, 0x09, 0x08, 0x35,
4648 0x02, 0x0c, 0x08, 0x04, 0x31
4650 static const u8 dramsr13_4
[4 * 5] = {
4651 0x02, 0x0d, 0x09, 0x40, 0x45,
4652 0x02, 0x0c, 0x09, 0x20, 0x35,
4653 0x02, 0x0c, 0x08, 0x10, 0x31,
4654 0x02, 0x0b, 0x08, 0x08, 0x21
4657 /* Enable linear mode, disable 0xa0000 address decoding */
4658 /* We disable a0000 address decoding, because
4659 * - if running on x86, if the card is disabled, it means
4660 * that another card is in the system. We don't want
4661 * to interphere with that primary card's textmode.
4662 * - if running on non-x86, there usually is no VGA window
4665 SiS_SetRegOR(SISSR
, 0x20, (0x80 | 0x04));
4667 /* Need to map max FB size for finding out about RAM size */
4668 mapsize
= ivideo
->video_size
;
4669 sisfb_post_map_vram(ivideo
, &mapsize
, 32);
4671 if(!ivideo
->video_vbase
) {
4672 printk(KERN_ERR
"sisfb: Unable to detect RAM size. Setting default.\n");
4673 SiS_SetReg(SISSR
, 0x13, 0x35);
4674 SiS_SetReg(SISSR
, 0x14, 0x41);
4679 /* Non-interleaving */
4680 SiS_SetReg(SISSR
, 0x15, 0x00);
4682 SiS_SetReg(SISSR
, 0x1c, 0x00);
4684 if(ivideo
->chip
== XGI_20
) {
4687 reg
= SiS_GetReg(SISCR
, 0x97);
4688 if(!(reg
& 0x01)) { /* Single 32/16 */
4690 SiS_SetReg(SISSR
, 0x13, 0xb1);
4691 SiS_SetReg(SISSR
, 0x14, 0x52);
4692 sisfb_post_xgi_delay(ivideo
, 1);
4694 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4697 SiS_SetReg(SISSR
, 0x13, 0x31);
4698 SiS_SetReg(SISSR
, 0x14, 0x42);
4699 sisfb_post_xgi_delay(ivideo
, 1);
4700 if(sisfb_post_xgi_rwtest(ivideo
, 23, 23, mapsize
))
4704 SiS_SetReg(SISSR
, 0x13, 0xb1);
4705 SiS_SetReg(SISSR
, 0x14, 0x41);
4706 sisfb_post_xgi_delay(ivideo
, 1);
4708 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4711 SiS_SetReg(SISSR
, 0x13, 0x31);
4712 } else { /* Dual 16/8 */
4714 SiS_SetReg(SISSR
, 0x13, 0xb1);
4715 SiS_SetReg(SISSR
, 0x14, 0x41);
4716 sisfb_post_xgi_delay(ivideo
, 1);
4718 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4721 SiS_SetReg(SISSR
, 0x13, 0x31);
4722 SiS_SetReg(SISSR
, 0x14, 0x31);
4723 sisfb_post_xgi_delay(ivideo
, 1);
4724 if(sisfb_post_xgi_rwtest(ivideo
, 22, 22, mapsize
))
4728 SiS_SetReg(SISSR
, 0x13, 0xb1);
4729 SiS_SetReg(SISSR
, 0x14, 0x30);
4730 sisfb_post_xgi_delay(ivideo
, 1);
4732 if(sisfb_post_xgi_rwtest(ivideo
, 21, 22, mapsize
))
4735 SiS_SetReg(SISSR
, 0x13, 0x31);
4738 } else { /* XGI_40 */
4740 reg
= SiS_GetReg(SISCR
, 0x97);
4742 reg
= SiS_GetReg(SISSR
, 0x39);
4746 if(reg
& 0x01) { /* DDRII */
4748 if(ivideo
->revision_id
== 2) {
4750 SiS_SetReg(SISSR
, 0x13, 0xa1);
4751 SiS_SetReg(SISSR
, 0x14, 0x44);
4753 sisfb_post_xgi_delay(ivideo
, 1);
4754 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4757 SiS_SetReg(SISSR
, 0x13, 0x21);
4758 SiS_SetReg(SISSR
, 0x14, 0x34);
4759 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4763 SiS_SetReg(SISSR
, 0x13, 0xa1);
4764 SiS_SetReg(SISSR
, 0x14, 0x40);
4766 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4769 SiS_SetReg(SISSR
, 0x13, 0x21);
4770 SiS_SetReg(SISSR
, 0x14, 0x30);
4773 SiS_SetReg(SISSR
, 0x13, 0xa1);
4774 SiS_SetReg(SISSR
, 0x14, 0x4c);
4776 sisfb_post_xgi_delay(ivideo
, 1);
4777 if(sisfb_post_xgi_rwtest(ivideo
, 23, 25, mapsize
))
4781 SiS_SetReg(SISSR
, 0x14, 0x48);
4782 sisfb_post_xgi_delay(ivideo
, 1);
4784 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4787 SiS_SetReg(SISSR
, 0x13, 0x21);
4788 SiS_SetReg(SISSR
, 0x14, 0x3c);
4791 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
)) {
4795 SiS_SetReg(SISSR
, 0x14, 0x38);
4799 sisfb_post_xgi_delay(ivideo
, 1);
4804 if(ivideo
->revision_id
== 2) {
4806 SiS_SetReg(SISSR
, 0x13, 0xa1);
4807 SiS_SetReg(SISSR
, 0x14, 0x52);
4808 sisfb_post_xgi_delay(ivideo
, 1);
4810 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4813 SiS_SetReg(SISSR
, 0x13, 0x21);
4814 SiS_SetReg(SISSR
, 0x14, 0x42);
4817 SiS_SetReg(SISSR
, 0x13, 0xa1);
4818 SiS_SetReg(SISSR
, 0x14, 0x5a);
4819 sisfb_post_xgi_delay(ivideo
, 1);
4821 if(sisfb_post_xgi_rwtest(ivideo
, 24, 25, mapsize
))
4824 SiS_SetReg(SISSR
, 0x13, 0x21);
4825 SiS_SetReg(SISSR
, 0x14, 0x4a);
4827 sisfb_post_xgi_delay(ivideo
, 1);
4833 SiS_SetRegANDOR(SISSR
, 0x14, 0xf0, sr14
);
4834 sisfb_post_xgi_delay(ivideo
, 1);
4836 j
= (ivideo
->chip
== XGI_20
) ? 5 : 9;
4837 k
= (ivideo
->chip
== XGI_20
) ? 12 : 4;
4840 for(i
= 0; i
< k
; i
++) {
4842 reg
= (ivideo
->chip
== XGI_20
) ?
4843 dramsr13
[(i
* 5) + 4] : dramsr13_4
[(i
* 5) + 4];
4844 SiS_SetRegANDOR(SISSR
, 0x13, 0x80, reg
);
4845 sisfb_post_xgi_delay(ivideo
, 50);
4847 ranksize
= (ivideo
->chip
== XGI_20
) ?
4848 dramsr13
[(i
* 5) + 3] : dramsr13_4
[(i
* 5) + 3];
4850 reg
= SiS_GetReg(SISSR
, 0x13);
4851 if(reg
& 0x80) ranksize
<<= 1;
4853 if(ivideo
->chip
== XGI_20
) {
4854 if(buswidth
== 16) ranksize
<<= 1;
4855 else if(buswidth
== 32) ranksize
<<= 2;
4857 if(buswidth
== 64) ranksize
<<= 1;
4863 if((ranksize
* l
) <= 256) {
4864 while((ranksize
>>= 1)) reg
+= 0x10;
4869 SiS_SetRegANDOR(SISSR
, 0x14, 0x0f, (reg
& 0xf0));
4870 sisfb_post_xgi_delay(ivideo
, 1);
4872 if (sisfb_post_xgi_rwtest(ivideo
, j
, ((reg
>> 4) + channelab
- 2 + 20), mapsize
)) {
4878 iounmap(ivideo
->video_vbase
);
4883 static void sisfb_post_xgi_setclocks(struct sis_video_info
*ivideo
, u8 regb
)
4887 static const u8 cs90
[8 * 3] = {
4897 static const u8 csb8
[8 * 3] = {
4911 v1
= cs90
[index
]; v2
= cs90
[index
+ 1]; v3
= cs90
[index
+ 2];
4912 if(ivideo
->haveXGIROM
) {
4913 v1
= ivideo
->bios_abase
[0x90 + index
];
4914 v2
= ivideo
->bios_abase
[0x90 + index
+ 1];
4915 v3
= ivideo
->bios_abase
[0x90 + index
+ 2];
4917 SiS_SetReg(SISSR
, 0x28, v1
);
4918 SiS_SetReg(SISSR
, 0x29, v2
);
4919 SiS_SetReg(SISSR
, 0x2a, v3
);
4920 sisfb_post_xgi_delay(ivideo
, 0x43);
4921 sisfb_post_xgi_delay(ivideo
, 0x43);
4922 sisfb_post_xgi_delay(ivideo
, 0x43);
4924 v1
= csb8
[index
]; v2
= csb8
[index
+ 1]; v3
= csb8
[index
+ 2];
4925 if(ivideo
->haveXGIROM
) {
4926 v1
= ivideo
->bios_abase
[0xb8 + index
];
4927 v2
= ivideo
->bios_abase
[0xb8 + index
+ 1];
4928 v3
= ivideo
->bios_abase
[0xb8 + index
+ 2];
4930 SiS_SetReg(SISSR
, 0x2e, v1
);
4931 SiS_SetReg(SISSR
, 0x2f, v2
);
4932 SiS_SetReg(SISSR
, 0x30, v3
);
4933 sisfb_post_xgi_delay(ivideo
, 0x43);
4934 sisfb_post_xgi_delay(ivideo
, 0x43);
4935 sisfb_post_xgi_delay(ivideo
, 0x43);
4938 static void sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info
*ivideo
,
4941 unsigned char *bios
= ivideo
->bios_abase
;
4944 SiS_SetReg(SISSR
, 0x28, 0x64);
4945 SiS_SetReg(SISSR
, 0x29, 0x63);
4946 sisfb_post_xgi_delay(ivideo
, 15);
4947 SiS_SetReg(SISSR
, 0x18, 0x00);
4948 SiS_SetReg(SISSR
, 0x19, 0x20);
4949 SiS_SetReg(SISSR
, 0x16, 0x00);
4950 SiS_SetReg(SISSR
, 0x16, 0x80);
4951 SiS_SetReg(SISSR
, 0x18, 0xc5);
4952 SiS_SetReg(SISSR
, 0x19, 0x23);
4953 SiS_SetReg(SISSR
, 0x16, 0x00);
4954 SiS_SetReg(SISSR
, 0x16, 0x80);
4955 sisfb_post_xgi_delay(ivideo
, 1);
4956 SiS_SetReg(SISCR
, 0x97, 0x11);
4957 sisfb_post_xgi_setclocks(ivideo
, regb
);
4958 sisfb_post_xgi_delay(ivideo
, 0x46);
4959 SiS_SetReg(SISSR
, 0x18, 0xc5);
4960 SiS_SetReg(SISSR
, 0x19, 0x23);
4961 SiS_SetReg(SISSR
, 0x16, 0x00);
4962 SiS_SetReg(SISSR
, 0x16, 0x80);
4963 sisfb_post_xgi_delay(ivideo
, 1);
4964 SiS_SetReg(SISSR
, 0x1b, 0x04);
4965 sisfb_post_xgi_delay(ivideo
, 1);
4966 SiS_SetReg(SISSR
, 0x1b, 0x00);
4967 sisfb_post_xgi_delay(ivideo
, 1);
4969 if (ivideo
->haveXGIROM
) {
4972 SiS_SetReg(SISSR
, 0x18, v1
);
4973 SiS_SetReg(SISSR
, 0x19, 0x06);
4974 SiS_SetReg(SISSR
, 0x16, 0x04);
4975 SiS_SetReg(SISSR
, 0x16, 0x84);
4976 sisfb_post_xgi_delay(ivideo
, 1);
4979 static void sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info
*ivideo
)
4981 sisfb_post_xgi_setclocks(ivideo
, 1);
4983 SiS_SetReg(SISCR
, 0x97, 0x11);
4984 sisfb_post_xgi_delay(ivideo
, 0x46);
4986 SiS_SetReg(SISSR
, 0x18, 0x00); /* EMRS2 */
4987 SiS_SetReg(SISSR
, 0x19, 0x80);
4988 SiS_SetReg(SISSR
, 0x16, 0x05);
4989 SiS_SetReg(SISSR
, 0x16, 0x85);
4991 SiS_SetReg(SISSR
, 0x18, 0x00); /* EMRS3 */
4992 SiS_SetReg(SISSR
, 0x19, 0xc0);
4993 SiS_SetReg(SISSR
, 0x16, 0x05);
4994 SiS_SetReg(SISSR
, 0x16, 0x85);
4996 SiS_SetReg(SISSR
, 0x18, 0x00); /* EMRS1 */
4997 SiS_SetReg(SISSR
, 0x19, 0x40);
4998 SiS_SetReg(SISSR
, 0x16, 0x05);
4999 SiS_SetReg(SISSR
, 0x16, 0x85);
5001 SiS_SetReg(SISSR
, 0x18, 0x42); /* MRS1 */
5002 SiS_SetReg(SISSR
, 0x19, 0x02);
5003 SiS_SetReg(SISSR
, 0x16, 0x05);
5004 SiS_SetReg(SISSR
, 0x16, 0x85);
5005 sisfb_post_xgi_delay(ivideo
, 1);
5007 SiS_SetReg(SISSR
, 0x1b, 0x04);
5008 sisfb_post_xgi_delay(ivideo
, 1);
5010 SiS_SetReg(SISSR
, 0x1b, 0x00);
5011 sisfb_post_xgi_delay(ivideo
, 1);
5013 SiS_SetReg(SISSR
, 0x18, 0x42); /* MRS1 */
5014 SiS_SetReg(SISSR
, 0x19, 0x00);
5015 SiS_SetReg(SISSR
, 0x16, 0x05);
5016 SiS_SetReg(SISSR
, 0x16, 0x85);
5017 sisfb_post_xgi_delay(ivideo
, 1);
5020 static void sisfb_post_xgi_ddr2(struct sis_video_info
*ivideo
, u8 regb
)
5022 unsigned char *bios
= ivideo
->bios_abase
;
5023 static const u8 cs158
[8] = {
5024 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5026 static const u8 cs160
[8] = {
5027 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5029 static const u8 cs168
[8] = {
5030 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5037 SiS_SetReg(SISCR
, 0xb0, 0x80); /* DDR2 dual frequency mode */
5038 SiS_SetReg(SISCR
, 0x82, 0x77);
5039 SiS_SetReg(SISCR
, 0x86, 0x00);
5040 reg
= SiS_GetReg(SISCR
, 0x86);
5041 SiS_SetReg(SISCR
, 0x86, 0x88);
5042 reg
= SiS_GetReg(SISCR
, 0x86);
5043 v1
= cs168
[regb
]; v2
= cs160
[regb
]; v3
= cs158
[regb
];
5044 if (ivideo
->haveXGIROM
) {
5045 v1
= bios
[regb
+ 0x168];
5046 v2
= bios
[regb
+ 0x160];
5047 v3
= bios
[regb
+ 0x158];
5049 SiS_SetReg(SISCR
, 0x86, v1
);
5050 SiS_SetReg(SISCR
, 0x82, 0x77);
5051 SiS_SetReg(SISCR
, 0x85, 0x00);
5052 reg
= SiS_GetReg(SISCR
, 0x85);
5053 SiS_SetReg(SISCR
, 0x85, 0x88);
5054 reg
= SiS_GetReg(SISCR
, 0x85);
5055 SiS_SetReg(SISCR
, 0x85, v2
);
5056 SiS_SetReg(SISCR
, 0x82, v3
);
5057 SiS_SetReg(SISCR
, 0x98, 0x01);
5058 SiS_SetReg(SISCR
, 0x9a, 0x02);
5059 if (sisfb_xgi_is21(ivideo
))
5060 sisfb_post_xgi_ddr2_mrs_xg21(ivideo
);
5062 sisfb_post_xgi_ddr2_mrs_default(ivideo
, regb
);
5065 static u8
sisfb_post_xgi_ramtype(struct sis_video_info
*ivideo
)
5067 unsigned char *bios
= ivideo
->bios_abase
;
5072 ramtype
= 0x00; v1
= 0x10;
5073 if (ivideo
->haveXGIROM
) {
5074 ramtype
= bios
[0x62];
5077 if (!(ramtype
& 0x80)) {
5078 if (sisfb_xgi_is21(ivideo
)) {
5079 SiS_SetRegAND(SISCR
, 0xb4, 0xfd); /* GPIO control */
5080 SiS_SetRegOR(SISCR
, 0x4a, 0x80); /* GPIOH EN */
5081 reg
= SiS_GetReg(SISCR
, 0x48);
5082 SiS_SetRegOR(SISCR
, 0xb4, 0x02);
5083 ramtype
= reg
& 0x01; /* GPIOH */
5084 } else if (ivideo
->chip
== XGI_20
) {
5085 SiS_SetReg(SISCR
, 0x97, v1
);
5086 reg
= SiS_GetReg(SISCR
, 0x97);
5088 ramtype
= (reg
& 0x01) << 1;
5091 reg
= SiS_GetReg(SISSR
, 0x39);
5092 ramtype
= reg
& 0x02;
5094 reg
= SiS_GetReg(SISSR
, 0x3a);
5095 ramtype
= (reg
>> 1) & 0x01;
5104 static int sisfb_post_xgi(struct pci_dev
*pdev
)
5106 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
5107 unsigned char *bios
= ivideo
->bios_abase
;
5108 struct pci_dev
*mypdev
= NULL
;
5109 const u8
*ptr
, *ptr2
;
5110 u8 v1
, v2
, v3
, v4
, v5
, reg
, ramtype
;
5111 u32 rega
, regb
, regd
;
5113 static const u8 cs78
[3] = { 0xf6, 0x0d, 0x00 };
5114 static const u8 cs76
[2] = { 0xa3, 0xfb };
5115 static const u8 cs7b
[3] = { 0xc0, 0x11, 0x00 };
5116 static const u8 cs158
[8] = {
5117 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5119 static const u8 cs160
[8] = {
5120 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5122 static const u8 cs168
[8] = {
5123 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5125 static const u8 cs128
[3 * 8] = {
5126 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
5127 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5128 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
5130 static const u8 cs148
[2 * 8] = {
5131 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
5132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5134 static const u8 cs31a
[8 * 4] = {
5135 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
5136 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
5137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5140 static const u8 cs33a
[8 * 4] = {
5141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5146 static const u8 cs45a
[8 * 2] = {
5147 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
5148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5150 static const u8 cs170
[7 * 8] = {
5151 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5152 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5153 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
5154 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5155 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5156 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5157 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5159 static const u8 cs1a8
[3 * 8] = {
5160 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5161 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5164 static const u8 cs100
[2 * 8] = {
5165 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5166 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5170 reg
= SiS_GetRegByte(SISVGAENABLE
) | 0x01;
5171 SiS_SetRegByte(SISVGAENABLE
, reg
);
5174 reg
= SiS_GetRegByte(SISMISCR
) | 0x01;
5175 SiS_SetRegByte(SISMISCW
, reg
);
5178 SiS_SetReg(SISSR
, 0x05, 0x86);
5179 reg
= SiS_GetReg(SISSR
, 0x05);
5183 /* Clear some regs */
5184 for(i
= 0; i
< 0x22; i
++) {
5185 if(0x06 + i
== 0x20) continue;
5186 SiS_SetReg(SISSR
, 0x06 + i
, 0x00);
5188 for(i
= 0; i
< 0x0b; i
++) {
5189 SiS_SetReg(SISSR
, 0x31 + i
, 0x00);
5191 for(i
= 0; i
< 0x10; i
++) {
5192 SiS_SetReg(SISCR
, 0x30 + i
, 0x00);
5196 if(ivideo
->haveXGIROM
) {
5197 ptr
= (const u8
*)&bios
[0x78];
5199 for(i
= 0; i
< 3; i
++) {
5200 SiS_SetReg(SISSR
, 0x23 + i
, ptr
[i
]);
5204 if(ivideo
->haveXGIROM
) {
5205 ptr
= (const u8
*)&bios
[0x76];
5207 for(i
= 0; i
< 2; i
++) {
5208 SiS_SetReg(SISSR
, 0x21 + i
, ptr
[i
]);
5211 v1
= 0x18; v2
= 0x00;
5212 if(ivideo
->haveXGIROM
) {
5216 SiS_SetReg(SISSR
, 0x07, v1
);
5217 SiS_SetReg(SISSR
, 0x11, 0x0f);
5218 SiS_SetReg(SISSR
, 0x1f, v2
);
5219 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5220 SiS_SetReg(SISSR
, 0x20, 0x80 | 0x20 | 0x04);
5221 SiS_SetReg(SISSR
, 0x27, 0x74);
5224 if(ivideo
->haveXGIROM
) {
5225 ptr
= (const u8
*)&bios
[0x7b];
5227 for(i
= 0; i
< 3; i
++) {
5228 SiS_SetReg(SISSR
, 0x31 + i
, ptr
[i
]);
5231 if(ivideo
->chip
== XGI_40
) {
5232 if(ivideo
->revision_id
== 2) {
5233 SiS_SetRegANDOR(SISSR
, 0x3b, 0x3f, 0xc0);
5235 SiS_SetReg(SISCR
, 0x7d, 0xfe);
5236 SiS_SetReg(SISCR
, 0x7e, 0x0f);
5238 if(ivideo
->revision_id
== 0) { /* 40 *and* 20? */
5239 SiS_SetRegAND(SISCR
, 0x58, 0xd7);
5240 reg
= SiS_GetReg(SISCR
, 0xcb);
5242 SiS_SetRegANDOR(SISCR
, 0x58, 0xd7, (reg
& 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5246 reg
= (ivideo
->chip
== XGI_40
) ? 0x20 : 0x00;
5247 SiS_SetRegANDOR(SISCR
, 0x38, 0x1f, reg
);
5249 if(ivideo
->chip
== XGI_20
) {
5250 SiS_SetReg(SISSR
, 0x36, 0x70);
5252 SiS_SetReg(SISVID
, 0x00, 0x86);
5253 SiS_SetReg(SISVID
, 0x32, 0x00);
5254 SiS_SetReg(SISVID
, 0x30, 0x00);
5255 SiS_SetReg(SISVID
, 0x32, 0x01);
5256 SiS_SetReg(SISVID
, 0x30, 0x00);
5257 SiS_SetRegAND(SISVID
, 0x2f, 0xdf);
5258 SiS_SetRegAND(SISCAP
, 0x00, 0x3f);
5260 SiS_SetReg(SISPART1
, 0x2f, 0x01);
5261 SiS_SetReg(SISPART1
, 0x00, 0x00);
5262 SiS_SetReg(SISPART1
, 0x02, bios
[0x7e]);
5263 SiS_SetReg(SISPART1
, 0x2e, 0x08);
5264 SiS_SetRegAND(SISPART1
, 0x35, 0x7f);
5265 SiS_SetRegAND(SISPART1
, 0x50, 0xfe);
5267 reg
= SiS_GetReg(SISPART4
, 0x00);
5268 if(reg
== 1 || reg
== 2) {
5269 SiS_SetReg(SISPART2
, 0x00, 0x1c);
5270 SiS_SetReg(SISPART4
, 0x0d, bios
[0x7f]);
5271 SiS_SetReg(SISPART4
, 0x0e, bios
[0x80]);
5272 SiS_SetReg(SISPART4
, 0x10, bios
[0x81]);
5273 SiS_SetRegAND(SISPART4
, 0x0f, 0x3f);
5275 reg
= SiS_GetReg(SISPART4
, 0x01);
5276 if((reg
& 0xf0) >= 0xb0) {
5277 reg
= SiS_GetReg(SISPART4
, 0x23);
5278 if(reg
& 0x20) reg
|= 0x40;
5279 SiS_SetReg(SISPART4
, 0x23, reg
);
5280 reg
= (reg
& 0x20) ? 0x02 : 0x00;
5281 SiS_SetRegANDOR(SISPART1
, 0x1e, 0xfd, reg
);
5287 reg
= SiS_GetReg(SISSR
, 0x3b);
5289 reg
= SiS_GetReg(SISSR
, 0x3a);
5290 v2
= (reg
& 0x30) >> 3;
5291 if(!(v2
& 0x04)) v2
^= 0x02;
5292 reg
= SiS_GetReg(SISSR
, 0x39);
5293 if(reg
& 0x80) v2
|= 0x80;
5296 if((mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0730, NULL
))) {
5297 pci_dev_put(mypdev
);
5298 if(((v2
& 0x06) == 2) || ((v2
& 0x06) == 4))
5303 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0735, NULL
);
5305 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0645, NULL
);
5307 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0650, NULL
);
5309 pci_read_config_dword(mypdev
, 0x94, ®d
);
5311 pci_write_config_dword(mypdev
, 0x94, regd
);
5313 pci_dev_put(mypdev
);
5314 } else if(sisfb_find_host_bridge(ivideo
, pdev
, PCI_VENDOR_ID_SI
)) {
5316 } else if(sisfb_find_host_bridge(ivideo
, pdev
, 0x1106) ||
5317 sisfb_find_host_bridge(ivideo
, pdev
, 0x1022) ||
5318 sisfb_find_host_bridge(ivideo
, pdev
, 0x700e) ||
5319 sisfb_find_host_bridge(ivideo
, pdev
, 0x10de)) {
5320 if((v2
& 0x06) == 4)
5325 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf0, v2
);
5327 SiS_SetReg(SISSR
, 0x22, v1
);
5329 if(ivideo
->revision_id
== 2) {
5330 v1
= SiS_GetReg(SISSR
, 0x3b);
5331 v2
= SiS_GetReg(SISSR
, 0x3a);
5332 regd
= bios
[0x90 + 3] | (bios
[0x90 + 4] << 8);
5333 if( (!(v1
& 0x02)) && (v2
& 0x30) && (regd
< 0xcf) )
5334 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf1, 0x01);
5336 if((mypdev
= pci_get_device(0x10de, 0x01e0, NULL
))) {
5337 /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5341 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf1, 0x01);
5342 pci_dev_put(mypdev
);
5347 reg
= SiS_GetReg(SISSR
, 0x3b);
5348 v2
= SiS_GetReg(SISCR
, 0x5f);
5349 if((!(reg
& 0x02)) && (v2
& 0x0e))
5351 SiS_SetReg(SISSR
, 0x27, v1
);
5353 if(bios
[0x64] & 0x01) {
5354 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf0, bios
[0x64]);
5358 pci_read_config_dword(pdev
, 0x50, ®d
);
5359 regd
= (regd
>> 20) & 0x0f;
5362 SiS_SetRegOR(SISCR
, 0x5f, 0x08);
5364 SiS_SetReg(SISCR
, 0x48, v1
);
5366 SiS_SetRegANDOR(SISCR
, 0x47, 0x04, bios
[0x4f6] & 0xfb);
5367 SiS_SetRegANDOR(SISCR
, 0x49, 0xf0, bios
[0x4f8] & 0x0f);
5368 SiS_SetRegANDOR(SISCR
, 0x4a, 0x60, bios
[0x4f9] & 0x9f);
5369 SiS_SetRegANDOR(SISCR
, 0x4b, 0x08, bios
[0x4fa] & 0xf7);
5370 SiS_SetRegANDOR(SISCR
, 0x4c, 0x80, bios
[0x4fb] & 0x7f);
5371 SiS_SetReg(SISCR
, 0x70, bios
[0x4fc]);
5372 SiS_SetRegANDOR(SISCR
, 0x71, 0xf0, bios
[0x4fd] & 0x0f);
5373 SiS_SetReg(SISCR
, 0x74, 0xd0);
5374 SiS_SetRegANDOR(SISCR
, 0x74, 0xcf, bios
[0x4fe] & 0x30);
5375 SiS_SetRegANDOR(SISCR
, 0x75, 0xe0, bios
[0x4ff] & 0x1f);
5376 SiS_SetRegANDOR(SISCR
, 0x76, 0xe0, bios
[0x500] & 0x1f);
5378 if((mypdev
= pci_get_device(0x8086, 0x2530, NULL
))) {
5380 pci_dev_put(mypdev
);
5382 SiS_SetReg(SISCR
, 0x77, v1
);
5387 * 0 == DDR1, 1 == DDR2, 2..7 == reserved?
5389 * The code seems to written so that regb should equal ramtype,
5390 * however, so far it has been hardcoded to 0. Enable other values only
5391 * on XGI Z9, as it passes the POST, and add a warning for others.
5393 ramtype
= sisfb_post_xgi_ramtype(ivideo
);
5394 if (!sisfb_xgi_is21(ivideo
) && ramtype
) {
5395 dev_warn(&pdev
->dev
,
5396 "RAM type something else than expected: %d\n",
5404 if(ivideo
->haveXGIROM
) {
5405 v1
= bios
[0x140 + regb
];
5407 SiS_SetReg(SISCR
, 0x6d, v1
);
5410 if(ivideo
->haveXGIROM
) {
5411 ptr
= (const u8
*)&bios
[0x128];
5413 for(i
= 0, j
= 0; i
< 3; i
++, j
+= 8) {
5414 SiS_SetReg(SISCR
, 0x68 + i
, ptr
[j
+ regb
]);
5419 if(ivideo
->haveXGIROM
) {
5420 index
= (ivideo
->chip
== XGI_20
) ? 0x31a : 0x3a6;
5421 ptr
= (const u8
*)&bios
[index
];
5422 ptr2
= (const u8
*)&bios
[index
+ 0x20];
5424 for(i
= 0; i
< 2; i
++) {
5426 regd
= le32_to_cpu(((u32
*)ptr
)[regb
]);
5429 regd
= le32_to_cpu(((u32
*)ptr2
)[regb
]);
5433 for(j
= 0; j
< 16; j
++) {
5435 if(regd
& 0x01) reg
|= 0x04;
5436 if(regd
& 0x02) reg
|= 0x08;
5438 SiS_SetReg(SISCR
, rega
, reg
);
5439 reg
= SiS_GetReg(SISCR
, rega
);
5440 reg
= SiS_GetReg(SISCR
, rega
);
5445 SiS_SetRegAND(SISCR
, 0x6e, 0xfc);
5448 if(ivideo
->haveXGIROM
) {
5449 index
= (ivideo
->chip
== XGI_20
) ? 0x35a : 0x3e6;
5450 ptr
= (const u8
*)&bios
[index
];
5452 for(i
= 0; i
< 4; i
++) {
5453 SiS_SetRegANDOR(SISCR
, 0x6e, 0xfc, i
);
5455 for(j
= 0; j
< 2; j
++) {
5458 regd
= le32_to_cpu(((u32
*)ptr
)[regb
* 8]);
5462 for(k
= 0; k
< 16; k
++) {
5464 if(regd
& 0x01) reg
|= 0x01;
5465 if(regd
& 0x02) reg
|= 0x02;
5467 SiS_SetReg(SISCR
, 0x6f, reg
);
5468 reg
= SiS_GetReg(SISCR
, 0x6f);
5469 reg
= SiS_GetReg(SISCR
, 0x6f);
5476 if(ivideo
->haveXGIROM
) {
5477 ptr
= (const u8
*)&bios
[0x148];
5479 for(i
= 0, j
= 0; i
< 2; i
++, j
+= 8) {
5480 SiS_SetReg(SISCR
, 0x80 + i
, ptr
[j
+ regb
]);
5483 SiS_SetRegAND(SISCR
, 0x89, 0x8f);
5486 if(ivideo
->haveXGIROM
) {
5487 index
= (ivideo
->chip
== XGI_20
) ? 0x45a : 0x4e6;
5488 ptr
= (const u8
*)&bios
[index
];
5490 regd
= le16_to_cpu(((const u16
*)ptr
)[regb
]);
5492 for(i
= 0; i
< 5; i
++) {
5494 if(regd
& 0x01) reg
|= 0x01;
5495 if(regd
& 0x02) reg
|= 0x02;
5497 SiS_SetReg(SISCR
, 0x89, reg
);
5498 reg
= SiS_GetReg(SISCR
, 0x89);
5499 reg
= SiS_GetReg(SISCR
, 0x89);
5503 v1
= 0xb5; v2
= 0x20; v3
= 0xf0; v4
= 0x13;
5504 if(ivideo
->haveXGIROM
) {
5505 v1
= bios
[0x118 + regb
];
5506 v2
= bios
[0xf8 + regb
];
5507 v3
= bios
[0x120 + regb
];
5510 SiS_SetReg(SISCR
, 0x45, v1
& 0x0f);
5511 SiS_SetReg(SISCR
, 0x99, (v1
>> 4) & 0x07);
5512 SiS_SetRegOR(SISCR
, 0x40, v1
& 0x80);
5513 SiS_SetReg(SISCR
, 0x41, v2
);
5516 if(ivideo
->haveXGIROM
) {
5517 ptr
= (const u8
*)&bios
[0x170];
5519 for(i
= 0, j
= 0; i
< 7; i
++, j
+= 8) {
5520 SiS_SetReg(SISCR
, 0x90 + i
, ptr
[j
+ regb
]);
5523 SiS_SetReg(SISCR
, 0x59, v3
);
5526 if(ivideo
->haveXGIROM
) {
5527 ptr
= (const u8
*)&bios
[0x1a8];
5529 for(i
= 0, j
= 0; i
< 3; i
++, j
+= 8) {
5530 SiS_SetReg(SISCR
, 0xc3 + i
, ptr
[j
+ regb
]);
5534 if(ivideo
->haveXGIROM
) {
5535 ptr
= (const u8
*)&bios
[0x100];
5537 for(i
= 0, j
= 0; i
< 2; i
++, j
+= 8) {
5538 SiS_SetReg(SISCR
, 0x8a + i
, ptr
[j
+ regb
]);
5541 SiS_SetReg(SISCR
, 0xcf, v4
);
5543 SiS_SetReg(SISCR
, 0x83, 0x09);
5544 SiS_SetReg(SISCR
, 0x87, 0x00);
5546 if(ivideo
->chip
== XGI_40
) {
5547 if( (ivideo
->revision_id
== 1) ||
5548 (ivideo
->revision_id
== 2) ) {
5549 SiS_SetReg(SISCR
, 0x8c, 0x87);
5554 SiS_SetReg(SISSR
, 0x17, 0x80); /* DDR2 */
5556 SiS_SetReg(SISSR
, 0x17, 0x00); /* DDR1 */
5557 SiS_SetReg(SISSR
, 0x1a, 0x87);
5559 if(ivideo
->chip
== XGI_20
) {
5560 SiS_SetReg(SISSR
, 0x15, 0x00);
5561 SiS_SetReg(SISSR
, 0x1c, 0x00);
5566 sisfb_post_xgi_setclocks(ivideo
, regb
);
5567 if((ivideo
->chip
== XGI_20
) ||
5568 (ivideo
->revision_id
== 1) ||
5569 (ivideo
->revision_id
== 2)) {
5570 v1
= cs158
[regb
]; v2
= cs160
[regb
]; v3
= cs168
[regb
];
5571 if(ivideo
->haveXGIROM
) {
5572 v1
= bios
[regb
+ 0x158];
5573 v2
= bios
[regb
+ 0x160];
5574 v3
= bios
[regb
+ 0x168];
5576 SiS_SetReg(SISCR
, 0x82, v1
);
5577 SiS_SetReg(SISCR
, 0x85, v2
);
5578 SiS_SetReg(SISCR
, 0x86, v3
);
5580 SiS_SetReg(SISCR
, 0x82, 0x88);
5581 SiS_SetReg(SISCR
, 0x86, 0x00);
5582 reg
= SiS_GetReg(SISCR
, 0x86);
5583 SiS_SetReg(SISCR
, 0x86, 0x88);
5584 reg
= SiS_GetReg(SISCR
, 0x86);
5585 SiS_SetReg(SISCR
, 0x86, bios
[regb
+ 0x168]);
5586 SiS_SetReg(SISCR
, 0x82, 0x77);
5587 SiS_SetReg(SISCR
, 0x85, 0x00);
5588 reg
= SiS_GetReg(SISCR
, 0x85);
5589 SiS_SetReg(SISCR
, 0x85, 0x88);
5590 reg
= SiS_GetReg(SISCR
, 0x85);
5591 SiS_SetReg(SISCR
, 0x85, bios
[regb
+ 0x160]);
5592 SiS_SetReg(SISCR
, 0x82, bios
[regb
+ 0x158]);
5594 if(ivideo
->chip
== XGI_40
) {
5595 SiS_SetReg(SISCR
, 0x97, 0x00);
5597 SiS_SetReg(SISCR
, 0x98, 0x01);
5598 SiS_SetReg(SISCR
, 0x9a, 0x02);
5600 SiS_SetReg(SISSR
, 0x18, 0x01);
5601 if((ivideo
->chip
== XGI_20
) ||
5602 (ivideo
->revision_id
== 2)) {
5603 SiS_SetReg(SISSR
, 0x19, 0x40);
5605 SiS_SetReg(SISSR
, 0x19, 0x20);
5607 SiS_SetReg(SISSR
, 0x16, 0x00);
5608 SiS_SetReg(SISSR
, 0x16, 0x80);
5609 if((ivideo
->chip
== XGI_20
) || (bios
[0x1cb] != 0x0c)) {
5610 sisfb_post_xgi_delay(ivideo
, 0x43);
5611 sisfb_post_xgi_delay(ivideo
, 0x43);
5612 sisfb_post_xgi_delay(ivideo
, 0x43);
5613 SiS_SetReg(SISSR
, 0x18, 0x00);
5614 if((ivideo
->chip
== XGI_20
) ||
5615 (ivideo
->revision_id
== 2)) {
5616 SiS_SetReg(SISSR
, 0x19, 0x40);
5618 SiS_SetReg(SISSR
, 0x19, 0x20);
5620 } else if((ivideo
->chip
== XGI_40
) && (bios
[0x1cb] == 0x0c)) {
5621 /* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
5623 SiS_SetReg(SISSR
, 0x16, 0x00);
5624 SiS_SetReg(SISSR
, 0x16, 0x80);
5625 sisfb_post_xgi_delay(ivideo
, 4);
5626 v1
= 0x31; v2
= 0x03; v3
= 0x83; v4
= 0x03; v5
= 0x83;
5627 if(ivideo
->haveXGIROM
) {
5629 index
= (ivideo
->chip
== XGI_20
) ? 0x4b2 : 0x53e;
5631 v3
= bios
[index
+ 1];
5632 v4
= bios
[index
+ 2];
5633 v5
= bios
[index
+ 3];
5635 SiS_SetReg(SISSR
, 0x18, v1
);
5636 SiS_SetReg(SISSR
, 0x19, ((ivideo
->chip
== XGI_20
) ? 0x02 : 0x01));
5637 SiS_SetReg(SISSR
, 0x16, v2
);
5638 SiS_SetReg(SISSR
, 0x16, v3
);
5639 sisfb_post_xgi_delay(ivideo
, 0x43);
5640 SiS_SetReg(SISSR
, 0x1b, 0x03);
5641 sisfb_post_xgi_delay(ivideo
, 0x22);
5642 SiS_SetReg(SISSR
, 0x18, v1
);
5643 SiS_SetReg(SISSR
, 0x19, 0x00);
5644 SiS_SetReg(SISSR
, 0x16, v4
);
5645 SiS_SetReg(SISSR
, 0x16, v5
);
5646 SiS_SetReg(SISSR
, 0x1b, 0x00);
5649 sisfb_post_xgi_ddr2(ivideo
, regb
);
5652 sisfb_post_xgi_setclocks(ivideo
, regb
);
5653 if((ivideo
->chip
== XGI_40
) &&
5654 ((ivideo
->revision_id
== 1) ||
5655 (ivideo
->revision_id
== 2))) {
5656 SiS_SetReg(SISCR
, 0x82, bios
[regb
+ 0x158]);
5657 SiS_SetReg(SISCR
, 0x85, bios
[regb
+ 0x160]);
5658 SiS_SetReg(SISCR
, 0x86, bios
[regb
+ 0x168]);
5660 SiS_SetReg(SISCR
, 0x82, 0x88);
5661 SiS_SetReg(SISCR
, 0x86, 0x00);
5662 reg
= SiS_GetReg(SISCR
, 0x86);
5663 SiS_SetReg(SISCR
, 0x86, 0x88);
5664 SiS_SetReg(SISCR
, 0x82, 0x77);
5665 SiS_SetReg(SISCR
, 0x85, 0x00);
5666 reg
= SiS_GetReg(SISCR
, 0x85);
5667 SiS_SetReg(SISCR
, 0x85, 0x88);
5668 reg
= SiS_GetReg(SISCR
, 0x85);
5669 v1
= cs160
[regb
]; v2
= cs158
[regb
];
5670 if(ivideo
->haveXGIROM
) {
5671 v1
= bios
[regb
+ 0x160];
5672 v2
= bios
[regb
+ 0x158];
5674 SiS_SetReg(SISCR
, 0x85, v1
);
5675 SiS_SetReg(SISCR
, 0x82, v2
);
5677 if(ivideo
->chip
== XGI_40
) {
5678 SiS_SetReg(SISCR
, 0x97, 0x11);
5680 if((ivideo
->chip
== XGI_40
) && (ivideo
->revision_id
== 2)) {
5681 SiS_SetReg(SISCR
, 0x98, 0x01);
5683 SiS_SetReg(SISCR
, 0x98, 0x03);
5685 SiS_SetReg(SISCR
, 0x9a, 0x02);
5687 if(ivideo
->chip
== XGI_40
) {
5688 SiS_SetReg(SISSR
, 0x18, 0x01);
5690 SiS_SetReg(SISSR
, 0x18, 0x00);
5692 SiS_SetReg(SISSR
, 0x19, 0x40);
5693 SiS_SetReg(SISSR
, 0x16, 0x00);
5694 SiS_SetReg(SISSR
, 0x16, 0x80);
5695 if((ivideo
->chip
== XGI_40
) && (bios
[0x1cb] != 0x0c)) {
5696 sisfb_post_xgi_delay(ivideo
, 0x43);
5697 sisfb_post_xgi_delay(ivideo
, 0x43);
5698 sisfb_post_xgi_delay(ivideo
, 0x43);
5699 SiS_SetReg(SISSR
, 0x18, 0x00);
5700 SiS_SetReg(SISSR
, 0x19, 0x40);
5701 SiS_SetReg(SISSR
, 0x16, 0x00);
5702 SiS_SetReg(SISSR
, 0x16, 0x80);
5704 sisfb_post_xgi_delay(ivideo
, 4);
5706 if(ivideo
->haveXGIROM
) {
5709 SiS_SetReg(SISSR
, 0x18, v1
);
5710 SiS_SetReg(SISSR
, 0x19, 0x01);
5711 if(ivideo
->chip
== XGI_40
) {
5712 SiS_SetReg(SISSR
, 0x16, bios
[0x53e]);
5713 SiS_SetReg(SISSR
, 0x16, bios
[0x53f]);
5715 SiS_SetReg(SISSR
, 0x16, 0x05);
5716 SiS_SetReg(SISSR
, 0x16, 0x85);
5718 sisfb_post_xgi_delay(ivideo
, 0x43);
5719 if(ivideo
->chip
== XGI_40
) {
5720 SiS_SetReg(SISSR
, 0x1b, 0x01);
5722 SiS_SetReg(SISSR
, 0x1b, 0x03);
5724 sisfb_post_xgi_delay(ivideo
, 0x22);
5725 SiS_SetReg(SISSR
, 0x18, v1
);
5726 SiS_SetReg(SISSR
, 0x19, 0x00);
5727 if(ivideo
->chip
== XGI_40
) {
5728 SiS_SetReg(SISSR
, 0x16, bios
[0x540]);
5729 SiS_SetReg(SISSR
, 0x16, bios
[0x541]);
5731 SiS_SetReg(SISSR
, 0x16, 0x05);
5732 SiS_SetReg(SISSR
, 0x16, 0x85);
5734 SiS_SetReg(SISSR
, 0x1b, 0x00);
5739 if(ivideo
->haveXGIROM
) {
5740 v1
= bios
[0x110 + regb
];
5742 SiS_SetReg(SISSR
, 0x1b, v1
);
5745 v1
= 0x00; v2
= 0x00;
5746 if(ivideo
->haveXGIROM
) {
5752 if((v1
& 0x40) && (v2
& regd
) && ivideo
->haveXGIROM
) {
5754 SiS_SetReg(SISSR
, 0x13, bios
[regb
+ 0xe0]);
5755 SiS_SetReg(SISSR
, 0x14, bios
[regb
+ 0xe0 + 8]);
5760 /* Set default mode, don't clear screen */
5761 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
5762 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
5763 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
5764 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
5765 ivideo
->SiS_Pr
.VideoMemorySize
= 8 << 20;
5766 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
5768 SiS_SetReg(SISSR
, 0x05, 0x86);
5770 /* Disable read-cache */
5771 SiS_SetRegAND(SISSR
, 0x21, 0xdf);
5772 err
= sisfb_post_xgi_ramsize(ivideo
);
5773 /* Enable read-cache */
5774 SiS_SetRegOR(SISSR
, 0x21, 0x20);
5778 "%s: RAM size detection failed: %d\n",
5785 printk(KERN_DEBUG
"-----------------\n");
5786 for(i
= 0; i
< 0xff; i
++) {
5787 reg
= SiS_GetReg(SISCR
, i
);
5788 printk(KERN_DEBUG
"CR%02x(%x) = 0x%02x\n", i
, SISCR
, reg
);
5790 for(i
= 0; i
< 0x40; i
++) {
5791 reg
= SiS_GetReg(SISSR
, i
);
5792 printk(KERN_DEBUG
"SR%02x(%x) = 0x%02x\n", i
, SISSR
, reg
);
5794 printk(KERN_DEBUG
"-----------------\n");
5798 if(ivideo
->chip
== XGI_20
) {
5799 SiS_SetRegOR(SISCR
, 0x32, 0x20);
5801 reg
= SiS_GetReg(SISPART4
, 0x00);
5802 if((reg
== 1) || (reg
== 2)) {
5803 sisfb_sense_crt1(ivideo
);
5805 SiS_SetRegOR(SISCR
, 0x32, 0x20);
5809 /* Set default mode, don't clear screen */
5810 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
5811 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
5812 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
5813 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
5814 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
5816 SiS_SetReg(SISSR
, 0x05, 0x86);
5819 SiS_SetRegOR(SISSR
, 0x01, 0x20);
5821 /* Save mode number in CR34 */
5822 SiS_SetReg(SISCR
, 0x34, 0x2e);
5824 /* Let everyone know what the current mode is */
5825 ivideo
->modeprechange
= 0x2e;
5827 if(ivideo
->chip
== XGI_40
) {
5828 reg
= SiS_GetReg(SISCR
, 0xca);
5829 v1
= SiS_GetReg(SISCR
, 0xcc);
5830 if((reg
& 0x10) && (!(v1
& 0x04))) {
5832 "sisfb: Please connect power to the card.\n");
5841 static int sisfb_probe(struct pci_dev
*pdev
, const struct pci_device_id
*ent
)
5843 struct sisfb_chip_info
*chipinfo
= &sisfb_chip_info
[ent
->driver_data
];
5844 struct sis_video_info
*ivideo
= NULL
;
5845 struct fb_info
*sis_fb_info
= NULL
;
5853 sis_fb_info
= framebuffer_alloc(sizeof(*ivideo
), &pdev
->dev
);
5857 ivideo
= (struct sis_video_info
*)sis_fb_info
->par
;
5858 ivideo
->memyselfandi
= sis_fb_info
;
5860 ivideo
->sisfb_id
= SISFB_ID
;
5862 if(card_list
== NULL
) {
5863 ivideo
->cardnumber
= 0;
5865 struct sis_video_info
*countvideo
= card_list
;
5866 ivideo
->cardnumber
= 1;
5867 while((countvideo
= countvideo
->next
) != NULL
)
5868 ivideo
->cardnumber
++;
5871 strlcpy(ivideo
->myid
, chipinfo
->chip_name
, sizeof(ivideo
->myid
));
5873 ivideo
->warncount
= 0;
5874 ivideo
->chip_id
= pdev
->device
;
5875 ivideo
->chip_vendor
= pdev
->vendor
;
5876 ivideo
->revision_id
= pdev
->revision
;
5877 ivideo
->SiS_Pr
.ChipRevision
= ivideo
->revision_id
;
5878 pci_read_config_word(pdev
, PCI_COMMAND
, ®16
);
5879 ivideo
->sisvga_enabled
= reg16
& 0x01;
5880 ivideo
->pcibus
= pdev
->bus
->number
;
5881 ivideo
->pcislot
= PCI_SLOT(pdev
->devfn
);
5882 ivideo
->pcifunc
= PCI_FUNC(pdev
->devfn
);
5883 ivideo
->subsysvendor
= pdev
->subsystem_vendor
;
5884 ivideo
->subsysdevice
= pdev
->subsystem_device
;
5887 if(sisfb_mode_idx
== -1) {
5888 sisfb_get_vga_mode_from_kernel();
5892 ivideo
->chip
= chipinfo
->chip
;
5893 ivideo
->chip_real_id
= chipinfo
->chip
;
5894 ivideo
->sisvga_engine
= chipinfo
->vgaengine
;
5895 ivideo
->hwcursor_size
= chipinfo
->hwcursor_size
;
5896 ivideo
->CRT2_write_enable
= chipinfo
->CRT2_write_enable
;
5897 ivideo
->mni
= chipinfo
->mni
;
5899 ivideo
->detectedpdc
= 0xff;
5900 ivideo
->detectedpdca
= 0xff;
5901 ivideo
->detectedlcda
= 0xff;
5903 ivideo
->sisfb_thismonitor
.datavalid
= false;
5905 ivideo
->current_base
= 0;
5907 ivideo
->engineok
= 0;
5909 ivideo
->sisfb_was_boot_device
= 0;
5911 if(pdev
->resource
[PCI_ROM_RESOURCE
].flags
& IORESOURCE_ROM_SHADOW
) {
5912 if(ivideo
->sisvga_enabled
)
5913 ivideo
->sisfb_was_boot_device
= 1;
5915 printk(KERN_DEBUG
"sisfb: PCI device is disabled, "
5916 "but marked as boot video device ???\n");
5917 printk(KERN_DEBUG
"sisfb: I will not accept this "
5918 "as the primary VGA device\n");
5922 ivideo
->sisfb_parm_mem
= sisfb_parm_mem
;
5923 ivideo
->sisfb_accel
= sisfb_accel
;
5924 ivideo
->sisfb_ypan
= sisfb_ypan
;
5925 ivideo
->sisfb_max
= sisfb_max
;
5926 ivideo
->sisfb_userom
= sisfb_userom
;
5927 ivideo
->sisfb_useoem
= sisfb_useoem
;
5928 ivideo
->sisfb_mode_idx
= sisfb_mode_idx
;
5929 ivideo
->sisfb_parm_rate
= sisfb_parm_rate
;
5930 ivideo
->sisfb_crt1off
= sisfb_crt1off
;
5931 ivideo
->sisfb_forcecrt1
= sisfb_forcecrt1
;
5932 ivideo
->sisfb_crt2type
= sisfb_crt2type
;
5933 ivideo
->sisfb_crt2flags
= sisfb_crt2flags
;
5934 /* pdc(a), scalelcd, special timing, lvdshl handled below */
5935 ivideo
->sisfb_dstn
= sisfb_dstn
;
5936 ivideo
->sisfb_fstn
= sisfb_fstn
;
5937 ivideo
->sisfb_tvplug
= sisfb_tvplug
;
5938 ivideo
->sisfb_tvstd
= sisfb_tvstd
;
5939 ivideo
->tvxpos
= sisfb_tvxposoffset
;
5940 ivideo
->tvypos
= sisfb_tvyposoffset
;
5941 ivideo
->sisfb_nocrt2rate
= sisfb_nocrt2rate
;
5942 ivideo
->refresh_rate
= 0;
5943 if(ivideo
->sisfb_parm_rate
!= -1) {
5944 ivideo
->refresh_rate
= ivideo
->sisfb_parm_rate
;
5947 ivideo
->SiS_Pr
.UsePanelScaler
= sisfb_scalelcd
;
5948 ivideo
->SiS_Pr
.CenterScreen
= -1;
5949 ivideo
->SiS_Pr
.SiS_CustomT
= sisfb_specialtiming
;
5950 ivideo
->SiS_Pr
.LVDSHL
= sisfb_lvdshl
;
5952 ivideo
->SiS_Pr
.SiS_Backup70xx
= 0xff;
5953 ivideo
->SiS_Pr
.SiS_CHOverScan
= -1;
5954 ivideo
->SiS_Pr
.SiS_ChSW
= false;
5955 ivideo
->SiS_Pr
.SiS_UseLCDA
= false;
5956 ivideo
->SiS_Pr
.HaveEMI
= false;
5957 ivideo
->SiS_Pr
.HaveEMILCD
= false;
5958 ivideo
->SiS_Pr
.OverruleEMI
= false;
5959 ivideo
->SiS_Pr
.SiS_SensibleSR11
= false;
5960 ivideo
->SiS_Pr
.SiS_MyCR63
= 0x63;
5961 ivideo
->SiS_Pr
.PDC
= -1;
5962 ivideo
->SiS_Pr
.PDCA
= -1;
5963 ivideo
->SiS_Pr
.DDCPortMixup
= false;
5964 #ifdef CONFIG_FB_SIS_315
5965 if(ivideo
->chip
>= SIS_330
) {
5966 ivideo
->SiS_Pr
.SiS_MyCR63
= 0x53;
5967 if(ivideo
->chip
>= SIS_661
) {
5968 ivideo
->SiS_Pr
.SiS_SensibleSR11
= true;
5973 memcpy(&ivideo
->default_var
, &my_default_var
, sizeof(my_default_var
));
5975 pci_set_drvdata(pdev
, ivideo
);
5977 /* Patch special cases */
5978 if((ivideo
->nbridge
= sisfb_get_northbridge(ivideo
->chip
))) {
5979 switch(ivideo
->nbridge
->device
) {
5980 #ifdef CONFIG_FB_SIS_300
5981 case PCI_DEVICE_ID_SI_730
:
5982 ivideo
->chip
= SIS_730
;
5983 strcpy(ivideo
->myid
, "SiS 730");
5986 #ifdef CONFIG_FB_SIS_315
5987 case PCI_DEVICE_ID_SI_651
:
5988 /* ivideo->chip is ok */
5989 strcpy(ivideo
->myid
, "SiS 651");
5991 case PCI_DEVICE_ID_SI_740
:
5992 ivideo
->chip
= SIS_740
;
5993 strcpy(ivideo
->myid
, "SiS 740");
5995 case PCI_DEVICE_ID_SI_661
:
5996 ivideo
->chip
= SIS_661
;
5997 strcpy(ivideo
->myid
, "SiS 661");
5999 case PCI_DEVICE_ID_SI_741
:
6000 ivideo
->chip
= SIS_741
;
6001 strcpy(ivideo
->myid
, "SiS 741");
6003 case PCI_DEVICE_ID_SI_760
:
6004 ivideo
->chip
= SIS_760
;
6005 strcpy(ivideo
->myid
, "SiS 760");
6007 case PCI_DEVICE_ID_SI_761
:
6008 ivideo
->chip
= SIS_761
;
6009 strcpy(ivideo
->myid
, "SiS 761");
6017 ivideo
->SiS_Pr
.ChipType
= ivideo
->chip
;
6019 ivideo
->SiS_Pr
.ivideo
= (void *)ivideo
;
6021 #ifdef CONFIG_FB_SIS_315
6022 if((ivideo
->SiS_Pr
.ChipType
== SIS_315PRO
) ||
6023 (ivideo
->SiS_Pr
.ChipType
== SIS_315
)) {
6024 ivideo
->SiS_Pr
.ChipType
= SIS_315H
;
6028 if(!ivideo
->sisvga_enabled
) {
6029 if(pci_enable_device(pdev
)) {
6030 pci_dev_put(ivideo
->nbridge
);
6031 framebuffer_release(sis_fb_info
);
6036 ivideo
->video_base
= pci_resource_start(pdev
, 0);
6037 ivideo
->video_size
= pci_resource_len(pdev
, 0);
6038 ivideo
->mmio_base
= pci_resource_start(pdev
, 1);
6039 ivideo
->mmio_size
= pci_resource_len(pdev
, 1);
6040 ivideo
->SiS_Pr
.RelIO
= pci_resource_start(pdev
, 2) + 0x30;
6041 ivideo
->SiS_Pr
.IOAddress
= ivideo
->vga_base
= ivideo
->SiS_Pr
.RelIO
;
6043 SiSRegInit(&ivideo
->SiS_Pr
, ivideo
->SiS_Pr
.IOAddress
);
6045 #ifdef CONFIG_FB_SIS_300
6046 /* Find PCI systems for Chrontel/GPIO communication setup */
6047 if(ivideo
->chip
== SIS_630
) {
6050 if(mychswtable
[i
].subsysVendor
== ivideo
->subsysvendor
&&
6051 mychswtable
[i
].subsysCard
== ivideo
->subsysdevice
) {
6052 ivideo
->SiS_Pr
.SiS_ChSW
= true;
6053 printk(KERN_DEBUG
"sisfb: Identified [%s %s] "
6054 "requiring Chrontel/GPIO setup\n",
6055 mychswtable
[i
].vendorName
,
6056 mychswtable
[i
].cardName
);
6057 ivideo
->lpcdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0008, NULL
);
6061 } while(mychswtable
[i
].subsysVendor
!= 0);
6065 #ifdef CONFIG_FB_SIS_315
6066 if((ivideo
->chip
== SIS_760
) && (ivideo
->nbridge
)) {
6067 ivideo
->lpcdev
= pci_get_slot(ivideo
->nbridge
->bus
, (2 << 3));
6071 SiS_SetReg(SISSR
, 0x05, 0x86);
6073 if( (!ivideo
->sisvga_enabled
)
6074 #if !defined(__i386__) && !defined(__x86_64__)
6075 || (sisfb_resetcard
)
6078 for(i
= 0x30; i
<= 0x3f; i
++) {
6079 SiS_SetReg(SISCR
, i
, 0x00);
6083 /* Find out about current video mode */
6084 ivideo
->modeprechange
= 0x03;
6085 reg
= SiS_GetReg(SISCR
, 0x34);
6087 ivideo
->modeprechange
= reg
& 0x7f;
6088 } else if(ivideo
->sisvga_enabled
) {
6089 #if defined(__i386__) || defined(__x86_64__)
6090 unsigned char __iomem
*tt
= ioremap(0x400, 0x100);
6092 ivideo
->modeprechange
= readb(tt
+ 0x49);
6098 /* Search and copy ROM image */
6099 ivideo
->bios_abase
= NULL
;
6100 ivideo
->SiS_Pr
.VirtualRomBase
= NULL
;
6101 ivideo
->SiS_Pr
.UseROM
= false;
6102 ivideo
->haveXGIROM
= ivideo
->SiS_Pr
.SiS_XGIROM
= false;
6103 if(ivideo
->sisfb_userom
) {
6104 ivideo
->SiS_Pr
.VirtualRomBase
= sisfb_find_rom(pdev
);
6105 ivideo
->bios_abase
= ivideo
->SiS_Pr
.VirtualRomBase
;
6106 ivideo
->SiS_Pr
.UseROM
= (bool)(ivideo
->SiS_Pr
.VirtualRomBase
);
6107 printk(KERN_INFO
"sisfb: Video ROM %sfound\n",
6108 ivideo
->SiS_Pr
.UseROM
? "" : "not ");
6109 if((ivideo
->SiS_Pr
.UseROM
) && (ivideo
->chip
>= XGI_20
)) {
6110 ivideo
->SiS_Pr
.UseROM
= false;
6111 ivideo
->haveXGIROM
= ivideo
->SiS_Pr
.SiS_XGIROM
= true;
6112 if( (ivideo
->revision_id
== 2) &&
6113 (!(ivideo
->bios_abase
[0x1d1] & 0x01)) ) {
6114 ivideo
->SiS_Pr
.DDCPortMixup
= true;
6118 printk(KERN_INFO
"sisfb: Video ROM usage disabled\n");
6121 /* Find systems for special custom timing */
6122 if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_NONE
) {
6123 sisfb_detect_custom_timing(ivideo
);
6126 #ifdef CONFIG_FB_SIS_315
6127 if (ivideo
->chip
== XGI_20
) {
6128 /* Check if our Z7 chip is actually Z9 */
6129 SiS_SetRegOR(SISCR
, 0x4a, 0x40); /* GPIOG EN */
6130 reg
= SiS_GetReg(SISCR
, 0x48);
6131 if (reg
& 0x02) { /* GPIOG */
6132 ivideo
->chip_real_id
= XGI_21
;
6133 dev_info(&pdev
->dev
, "Z9 detected\n");
6138 /* POST card in case this has not been done by the BIOS */
6139 if( (!ivideo
->sisvga_enabled
)
6140 #if !defined(__i386__) && !defined(__x86_64__)
6141 || (sisfb_resetcard
)
6144 #ifdef CONFIG_FB_SIS_300
6145 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
6146 if(ivideo
->chip
== SIS_300
) {
6147 sisfb_post_sis300(pdev
);
6148 ivideo
->sisfb_can_post
= 1;
6153 #ifdef CONFIG_FB_SIS_315
6154 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
6156 /* if((ivideo->chip == SIS_315H) ||
6157 (ivideo->chip == SIS_315) ||
6158 (ivideo->chip == SIS_315PRO) ||
6159 (ivideo->chip == SIS_330)) {
6160 sisfb_post_sis315330(pdev);
6161 } else */ if(ivideo
->chip
== XGI_20
) {
6162 result
= sisfb_post_xgi(pdev
);
6163 ivideo
->sisfb_can_post
= 1;
6164 } else if((ivideo
->chip
== XGI_40
) && ivideo
->haveXGIROM
) {
6165 result
= sisfb_post_xgi(pdev
);
6166 ivideo
->sisfb_can_post
= 1;
6168 printk(KERN_INFO
"sisfb: Card is not "
6169 "POSTed and sisfb can't do this either.\n");
6172 printk(KERN_ERR
"sisfb: Failed to POST card\n");
6180 ivideo
->sisfb_card_posted
= 1;
6182 /* Find out about RAM size */
6183 if(sisfb_get_dram_size(ivideo
)) {
6184 printk(KERN_INFO
"sisfb: Fatal error: Unable to determine VRAM size.\n");
6190 /* Enable PCI addressing and MMIO */
6191 if((ivideo
->sisfb_mode_idx
< 0) ||
6192 ((sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
]) != 0xFF)) {
6193 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
6194 SiS_SetRegOR(SISSR
, IND_SIS_PCI_ADDRESS_SET
, (SIS_PCI_ADDR_ENABLE
| SIS_MEM_MAP_IO_ENABLE
));
6195 /* Enable 2D accelerator engine */
6196 SiS_SetRegOR(SISSR
, IND_SIS_MODULE_ENABLE
, SIS_ENABLE_2D
);
6199 if(sisfb_pdc
!= 0xff) {
6200 if(ivideo
->sisvga_engine
== SIS_300_VGA
)
6204 ivideo
->SiS_Pr
.PDC
= sisfb_pdc
;
6206 #ifdef CONFIG_FB_SIS_315
6207 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
6208 if(sisfb_pdca
!= 0xff)
6209 ivideo
->SiS_Pr
.PDCA
= sisfb_pdca
& 0x1f;
6213 if(!request_mem_region(ivideo
->video_base
, ivideo
->video_size
, "sisfb FB")) {
6214 printk(KERN_ERR
"sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6215 (int)(ivideo
->video_size
>> 20));
6216 printk(KERN_ERR
"sisfb: Is there another framebuffer driver active?\n");
6221 if(!request_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
, "sisfb MMIO")) {
6222 printk(KERN_ERR
"sisfb: Fatal error: Unable to reserve MMIO region\n");
6227 ivideo
->video_vbase
= ioremap_wc(ivideo
->video_base
, ivideo
->video_size
);
6228 ivideo
->SiS_Pr
.VideoMemoryAddress
= ivideo
->video_vbase
;
6229 if(!ivideo
->video_vbase
) {
6230 printk(KERN_ERR
"sisfb: Fatal error: Unable to map framebuffer memory\n");
6235 ivideo
->mmio_vbase
= ioremap(ivideo
->mmio_base
, ivideo
->mmio_size
);
6236 if(!ivideo
->mmio_vbase
) {
6237 printk(KERN_ERR
"sisfb: Fatal error: Unable to map MMIO region\n");
6239 error_0
: iounmap(ivideo
->video_vbase
);
6240 error_1
: release_mem_region(ivideo
->video_base
, ivideo
->video_size
);
6241 error_2
: release_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
);
6242 error_3
: vfree(ivideo
->bios_abase
);
6243 pci_dev_put(ivideo
->lpcdev
);
6244 pci_dev_put(ivideo
->nbridge
);
6245 if(!ivideo
->sisvga_enabled
)
6246 pci_disable_device(pdev
);
6247 framebuffer_release(sis_fb_info
);
6251 printk(KERN_INFO
"sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
6252 ivideo
->video_base
, (unsigned long)ivideo
->video_vbase
, ivideo
->video_size
/ 1024);
6254 if(ivideo
->video_offset
) {
6255 printk(KERN_INFO
"sisfb: Viewport offset %ldk\n",
6256 ivideo
->video_offset
/ 1024);
6259 printk(KERN_INFO
"sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
6260 ivideo
->mmio_base
, (unsigned long)ivideo
->mmio_vbase
, ivideo
->mmio_size
/ 1024);
6263 /* Determine the size of the command queue */
6264 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
6265 ivideo
->cmdQueueSize
= TURBO_QUEUE_AREA_SIZE
;
6267 if(ivideo
->chip
== XGI_20
) {
6268 ivideo
->cmdQueueSize
= COMMAND_QUEUE_AREA_SIZE_Z7
;
6270 ivideo
->cmdQueueSize
= COMMAND_QUEUE_AREA_SIZE
;
6274 /* Engines are no longer initialized here; this is
6275 * now done after the first mode-switch (if the
6276 * submitted var has its acceleration flags set).
6279 /* Calculate the base of the (unused) hw cursor */
6280 ivideo
->hwcursor_vbase
= ivideo
->video_vbase
6281 + ivideo
->video_size
6282 - ivideo
->cmdQueueSize
6283 - ivideo
->hwcursor_size
;
6284 ivideo
->caps
|= HW_CURSOR_CAP
;
6286 /* Initialize offscreen memory manager */
6287 if((ivideo
->havenoheap
= sisfb_heap_init(ivideo
))) {
6288 printk(KERN_WARNING
"sisfb: Failed to initialize offscreen memory heap\n");
6291 /* Used for clearing the screen only, therefore respect our mem limit */
6292 ivideo
->SiS_Pr
.VideoMemoryAddress
+= ivideo
->video_offset
;
6293 ivideo
->SiS_Pr
.VideoMemorySize
= ivideo
->sisfb_mem
;
6295 ivideo
->vbflags
= 0;
6296 ivideo
->lcddefmodeidx
= DEFAULT_LCDMODE
;
6297 ivideo
->tvdefmodeidx
= DEFAULT_TVMODE
;
6298 ivideo
->defmodeidx
= DEFAULT_MODE
;
6301 if(ivideo
->chip
< XGI_20
) {
6302 if(ivideo
->bios_abase
) {
6303 ivideo
->newrom
= SiSDetermineROMLayout661(&ivideo
->SiS_Pr
);
6307 if((ivideo
->sisfb_mode_idx
< 0) ||
6308 ((sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
]) != 0xFF)) {
6310 sisfb_sense_crt1(ivideo
);
6312 sisfb_get_VB_type(ivideo
);
6314 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
6315 sisfb_detect_VB_connect(ivideo
);
6318 ivideo
->currentvbflags
= ivideo
->vbflags
& (VB_VIDEOBRIDGE
| TV_STANDARD
);
6320 /* Decide on which CRT2 device to use */
6321 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
6322 if(ivideo
->sisfb_crt2type
!= -1) {
6323 if((ivideo
->sisfb_crt2type
== CRT2_LCD
) &&
6324 (ivideo
->vbflags
& CRT2_LCD
)) {
6325 ivideo
->currentvbflags
|= CRT2_LCD
;
6326 } else if(ivideo
->sisfb_crt2type
!= CRT2_LCD
) {
6327 ivideo
->currentvbflags
|= ivideo
->sisfb_crt2type
;
6330 /* Chrontel 700x TV detection often unreliable, therefore
6331 * use a different default order on such machines
6333 if((ivideo
->sisvga_engine
== SIS_300_VGA
) &&
6334 (ivideo
->vbflags2
& VB2_CHRONTEL
)) {
6335 if(ivideo
->vbflags
& CRT2_LCD
)
6336 ivideo
->currentvbflags
|= CRT2_LCD
;
6337 else if(ivideo
->vbflags
& CRT2_TV
)
6338 ivideo
->currentvbflags
|= CRT2_TV
;
6339 else if(ivideo
->vbflags
& CRT2_VGA
)
6340 ivideo
->currentvbflags
|= CRT2_VGA
;
6342 if(ivideo
->vbflags
& CRT2_TV
)
6343 ivideo
->currentvbflags
|= CRT2_TV
;
6344 else if(ivideo
->vbflags
& CRT2_LCD
)
6345 ivideo
->currentvbflags
|= CRT2_LCD
;
6346 else if(ivideo
->vbflags
& CRT2_VGA
)
6347 ivideo
->currentvbflags
|= CRT2_VGA
;
6352 if(ivideo
->vbflags
& CRT2_LCD
) {
6353 sisfb_detect_lcd_type(ivideo
);
6356 sisfb_save_pdc_emi(ivideo
);
6358 if(!ivideo
->sisfb_crt1off
) {
6359 sisfb_handle_ddc(ivideo
, &ivideo
->sisfb_thismonitor
, 0);
6361 if((ivideo
->vbflags2
& VB2_SISTMDSBRIDGE
) &&
6362 (ivideo
->vbflags
& (CRT2_VGA
| CRT2_LCD
))) {
6363 sisfb_handle_ddc(ivideo
, &ivideo
->sisfb_thismonitor
, 1);
6367 if(ivideo
->sisfb_mode_idx
>= 0) {
6368 int bu
= ivideo
->sisfb_mode_idx
;
6369 ivideo
->sisfb_mode_idx
= sisfb_validate_mode(ivideo
,
6370 ivideo
->sisfb_mode_idx
, ivideo
->currentvbflags
);
6371 if(bu
!= ivideo
->sisfb_mode_idx
) {
6372 printk(KERN_ERR
"Mode %dx%dx%d failed validation\n",
6373 sisbios_mode
[bu
].xres
,
6374 sisbios_mode
[bu
].yres
,
6375 sisbios_mode
[bu
].bpp
);
6379 if(ivideo
->sisfb_mode_idx
< 0) {
6380 switch(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
6382 ivideo
->sisfb_mode_idx
= ivideo
->lcddefmodeidx
;
6385 ivideo
->sisfb_mode_idx
= ivideo
->tvdefmodeidx
;
6388 ivideo
->sisfb_mode_idx
= ivideo
->defmodeidx
;
6393 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
6395 if(ivideo
->refresh_rate
!= 0) {
6396 sisfb_search_refresh_rate(ivideo
, ivideo
->refresh_rate
,
6397 ivideo
->sisfb_mode_idx
);
6400 if(ivideo
->rate_idx
== 0) {
6401 ivideo
->rate_idx
= sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
;
6402 ivideo
->refresh_rate
= 60;
6405 if(ivideo
->sisfb_thismonitor
.datavalid
) {
6406 if(!sisfb_verify_rate(ivideo
, &ivideo
->sisfb_thismonitor
,
6407 ivideo
->sisfb_mode_idx
,
6409 ivideo
->refresh_rate
)) {
6410 printk(KERN_INFO
"sisfb: WARNING: Refresh rate "
6411 "exceeds monitor specs!\n");
6415 ivideo
->video_bpp
= sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
;
6416 ivideo
->video_width
= sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
;
6417 ivideo
->video_height
= sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
;
6419 sisfb_set_vparms(ivideo
);
6421 printk(KERN_INFO
"sisfb: Default mode is %dx%dx%d (%dHz)\n",
6422 ivideo
->video_width
, ivideo
->video_height
, ivideo
->video_bpp
,
6423 ivideo
->refresh_rate
);
6425 /* Set up the default var according to chosen default display mode */
6426 ivideo
->default_var
.xres
= ivideo
->default_var
.xres_virtual
= ivideo
->video_width
;
6427 ivideo
->default_var
.yres
= ivideo
->default_var
.yres_virtual
= ivideo
->video_height
;
6428 ivideo
->default_var
.bits_per_pixel
= ivideo
->video_bpp
;
6430 sisfb_bpp_to_var(ivideo
, &ivideo
->default_var
);
6432 ivideo
->default_var
.pixclock
= (u32
) (1000000000 /
6433 sisfb_mode_rate_to_dclock(&ivideo
->SiS_Pr
, ivideo
->mode_no
, ivideo
->rate_idx
));
6435 if(sisfb_mode_rate_to_ddata(&ivideo
->SiS_Pr
, ivideo
->mode_no
,
6436 ivideo
->rate_idx
, &ivideo
->default_var
)) {
6437 if((ivideo
->default_var
.vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
6438 ivideo
->default_var
.pixclock
<<= 1;
6442 if(ivideo
->sisfb_ypan
) {
6443 /* Maximize regardless of sisfb_max at startup */
6444 ivideo
->default_var
.yres_virtual
=
6445 sisfb_calc_maxyres(ivideo
, &ivideo
->default_var
);
6446 if(ivideo
->default_var
.yres_virtual
< ivideo
->default_var
.yres
) {
6447 ivideo
->default_var
.yres_virtual
= ivideo
->default_var
.yres
;
6451 sisfb_calc_pitch(ivideo
, &ivideo
->default_var
);
6454 if(ivideo
->sisfb_accel
) {
6456 #ifdef STUPID_ACCELF_TEXT_SHIT
6457 ivideo
->default_var
.accel_flags
|= FB_ACCELF_TEXT
;
6460 sisfb_initaccel(ivideo
);
6462 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
6463 sis_fb_info
->flags
= FBINFO_DEFAULT
|
6464 FBINFO_HWACCEL_YPAN
|
6465 FBINFO_HWACCEL_XPAN
|
6466 FBINFO_HWACCEL_COPYAREA
|
6467 FBINFO_HWACCEL_FILLRECT
|
6468 ((ivideo
->accel
) ? 0 : FBINFO_HWACCEL_DISABLED
);
6470 sis_fb_info
->flags
= FBINFO_FLAG_DEFAULT
;
6472 sis_fb_info
->var
= ivideo
->default_var
;
6473 sis_fb_info
->fix
= ivideo
->sisfb_fix
;
6474 sis_fb_info
->screen_base
= ivideo
->video_vbase
+ ivideo
->video_offset
;
6475 sis_fb_info
->fbops
= &sisfb_ops
;
6476 sis_fb_info
->pseudo_palette
= ivideo
->pseudo_palette
;
6478 fb_alloc_cmap(&sis_fb_info
->cmap
, 256 , 0);
6480 printk(KERN_DEBUG
"sisfb: Initial vbflags 0x%x\n", (int)ivideo
->vbflags
);
6482 ivideo
->wc_cookie
= arch_phys_wc_add(ivideo
->video_base
,
6483 ivideo
->video_size
);
6484 if(register_framebuffer(sis_fb_info
) < 0) {
6485 printk(KERN_ERR
"sisfb: Fatal error: Failed to register framebuffer\n");
6487 iounmap(ivideo
->mmio_vbase
);
6491 ivideo
->registered
= 1;
6494 ivideo
->next
= card_list
;
6497 printk(KERN_INFO
"sisfb: 2D acceleration is %s, y-panning %s\n",
6498 ivideo
->sisfb_accel
? "enabled" : "disabled",
6499 ivideo
->sisfb_ypan
?
6500 (ivideo
->sisfb_max
? "enabled (auto-max)" :
6501 "enabled (no auto-max)") :
6505 fb_info(sis_fb_info
, "%s frame buffer device version %d.%d.%d\n",
6506 ivideo
->myid
, VER_MAJOR
, VER_MINOR
, VER_LEVEL
);
6508 printk(KERN_INFO
"sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
6510 } /* if mode = "none" */
6515 /*****************************************************/
6516 /* PCI DEVICE HANDLING */
6517 /*****************************************************/
6519 static void sisfb_remove(struct pci_dev
*pdev
)
6521 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
6522 struct fb_info
*sis_fb_info
= ivideo
->memyselfandi
;
6523 int registered
= ivideo
->registered
;
6524 int modechanged
= ivideo
->modechanged
;
6527 iounmap(ivideo
->mmio_vbase
);
6528 iounmap(ivideo
->video_vbase
);
6530 /* Release mem regions */
6531 release_mem_region(ivideo
->video_base
, ivideo
->video_size
);
6532 release_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
);
6534 vfree(ivideo
->bios_abase
);
6536 pci_dev_put(ivideo
->lpcdev
);
6538 pci_dev_put(ivideo
->nbridge
);
6540 arch_phys_wc_del(ivideo
->wc_cookie
);
6542 /* If device was disabled when starting, disable
6545 if(!ivideo
->sisvga_enabled
)
6546 pci_disable_device(pdev
);
6548 /* Unregister the framebuffer */
6549 if(ivideo
->registered
) {
6550 unregister_framebuffer(sis_fb_info
);
6551 framebuffer_release(sis_fb_info
);
6554 /* OK, our ivideo is gone for good from here. */
6556 /* TODO: Restore the initial mode
6557 * This sounds easy but is as good as impossible
6558 * on many machines with SiS chip and video bridge
6559 * since text modes are always set up differently
6560 * from machine to machine. Depends on the type
6561 * of integration between chipset and bridge.
6563 if(registered
&& modechanged
)
6565 "sisfb: Restoring of text mode not supported yet\n");
6568 static struct pci_driver sisfb_driver
= {
6570 .id_table
= sisfb_pci_table
,
6571 .probe
= sisfb_probe
,
6572 .remove
= sisfb_remove
,
6575 static int __init
sisfb_init(void)
6578 char *options
= NULL
;
6580 if(fb_get_options("sisfb", &options
))
6583 sisfb_setup(options
);
6585 return pci_register_driver(&sisfb_driver
);
6589 module_init(sisfb_init
);
6592 /*****************************************************/
6594 /*****************************************************/
6598 static char *mode
= NULL
;
6599 static int vesa
= -1;
6600 static unsigned int rate
= 0;
6601 static unsigned int crt1off
= 1;
6602 static unsigned int mem
= 0;
6603 static char *forcecrt2type
= NULL
;
6604 static int forcecrt1
= -1;
6605 static int pdc
= -1;
6606 static int pdc1
= -1;
6607 static int noaccel
= -1;
6608 static int noypan
= -1;
6609 static int nomax
= -1;
6610 static int userom
= -1;
6611 static int useoem
= -1;
6612 static char *tvstandard
= NULL
;
6613 static int nocrt2rate
= 0;
6614 static int scalelcd
= -1;
6615 static char *specialtiming
= NULL
;
6616 static int lvdshl
= -1;
6617 static int tvxposoffset
= 0, tvyposoffset
= 0;
6618 #if !defined(__i386__) && !defined(__x86_64__)
6619 static int resetcard
= 0;
6620 static int videoram
= 0;
6623 static int __init
sisfb_init_module(void)
6625 sisfb_setdefaultparms();
6628 sisfb_parm_rate
= rate
;
6630 if((scalelcd
== 0) || (scalelcd
== 1))
6631 sisfb_scalelcd
= scalelcd
^ 1;
6633 /* Need to check crt2 type first for fstn/dstn */
6636 sisfb_search_crt2type(forcecrt2type
);
6639 sisfb_search_tvstd(tvstandard
);
6642 sisfb_search_mode(mode
, false);
6644 sisfb_search_vesamode(vesa
, false);
6646 sisfb_crt1off
= (crt1off
== 0) ? 1 : 0;
6648 sisfb_forcecrt1
= forcecrt1
;
6651 else if(forcecrt1
== 0)
6656 else if(noaccel
== 0)
6661 else if(noypan
== 0)
6670 sisfb_parm_mem
= mem
;
6673 sisfb_userom
= userom
;
6676 sisfb_useoem
= useoem
;
6679 sisfb_pdc
= (pdc
& 0x7f);
6682 sisfb_pdca
= (pdc1
& 0x1f);
6684 sisfb_nocrt2rate
= nocrt2rate
;
6687 sisfb_search_specialtiming(specialtiming
);
6689 if((lvdshl
>= 0) && (lvdshl
<= 3))
6690 sisfb_lvdshl
= lvdshl
;
6692 sisfb_tvxposoffset
= tvxposoffset
;
6693 sisfb_tvyposoffset
= tvyposoffset
;
6695 #if !defined(__i386__) && !defined(__x86_64__)
6696 sisfb_resetcard
= (resetcard
) ? 1 : 0;
6698 sisfb_videoram
= videoram
;
6701 return sisfb_init();
6704 static void __exit
sisfb_remove_module(void)
6706 pci_unregister_driver(&sisfb_driver
);
6707 printk(KERN_DEBUG
"sisfb: Module unloaded\n");
6710 module_init(sisfb_init_module
);
6711 module_exit(sisfb_remove_module
);
6713 MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
6714 MODULE_LICENSE("GPL");
6715 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
6717 module_param(mem
, int, 0);
6718 module_param(noaccel
, int, 0);
6719 module_param(noypan
, int, 0);
6720 module_param(nomax
, int, 0);
6721 module_param(userom
, int, 0);
6722 module_param(useoem
, int, 0);
6723 module_param(mode
, charp
, 0);
6724 module_param(vesa
, int, 0);
6725 module_param(rate
, int, 0);
6726 module_param(forcecrt1
, int, 0);
6727 module_param(forcecrt2type
, charp
, 0);
6728 module_param(scalelcd
, int, 0);
6729 module_param(pdc
, int, 0);
6730 module_param(pdc1
, int, 0);
6731 module_param(specialtiming
, charp
, 0);
6732 module_param(lvdshl
, int, 0);
6733 module_param(tvstandard
, charp
, 0);
6734 module_param(tvxposoffset
, int, 0);
6735 module_param(tvyposoffset
, int, 0);
6736 module_param(nocrt2rate
, int, 0);
6737 #if !defined(__i386__) && !defined(__x86_64__)
6738 module_param(resetcard
, int, 0);
6739 module_param(videoram
, int, 0);
6742 MODULE_PARM_DESC(mem
,
6743 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6744 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6745 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6746 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6747 "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6748 "The value is to be specified without 'KB'.\n");
6750 MODULE_PARM_DESC(noaccel
,
6751 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
6754 MODULE_PARM_DESC(noypan
,
6755 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
6756 "will be performed by redrawing the screen. (default: 0)\n");
6758 MODULE_PARM_DESC(nomax
,
6759 "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
6760 "memory for the virtual screen in order to optimize scrolling performance. If\n"
6761 "this is set to anything other than 0, sisfb will not do this and thereby \n"
6762 "enable the user to positively specify a virtual Y size of the screen using\n"
6763 "fbset. (default: 0)\n");
6765 MODULE_PARM_DESC(mode
,
6766 "\nSelects the desired default display mode in the format XxYxDepth,\n"
6767 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
6768 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
6769 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
6771 MODULE_PARM_DESC(vesa
,
6772 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
6773 "0x117 (default: 0x0103)\n");
6775 MODULE_PARM_DESC(rate
,
6776 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
6777 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
6778 "will be ignored (default: 60)\n");
6780 MODULE_PARM_DESC(forcecrt1
,
6781 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
6782 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
6783 "0=CRT1 OFF) (default: [autodetected])\n");
6785 MODULE_PARM_DESC(forcecrt2type
,
6786 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
6787 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
6788 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
6789 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
6790 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
6791 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
6792 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
6793 "depends on the very hardware in use. (default: [autodetected])\n");
6795 MODULE_PARM_DESC(scalelcd
,
6796 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
6797 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
6798 "show black bars around the image, TMDS panels will probably do the scaling\n"
6799 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
6801 MODULE_PARM_DESC(pdc
,
6802 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
6803 "should detect this correctly in most cases; however, sometimes this is not\n"
6804 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
6805 "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
6806 "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
6807 "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
6809 #ifdef CONFIG_FB_SIS_315
6810 MODULE_PARM_DESC(pdc1
,
6811 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
6812 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
6813 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
6814 "implemented yet.\n");
6817 MODULE_PARM_DESC(specialtiming
,
6818 "\nPlease refer to documentation for more information on this option.\n");
6820 MODULE_PARM_DESC(lvdshl
,
6821 "\nPlease refer to documentation for more information on this option.\n");
6823 MODULE_PARM_DESC(tvstandard
,
6824 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
6825 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
6827 MODULE_PARM_DESC(tvxposoffset
,
6828 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
6831 MODULE_PARM_DESC(tvyposoffset
,
6832 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
6835 MODULE_PARM_DESC(nocrt2rate
,
6836 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
6837 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
6839 #if !defined(__i386__) && !defined(__x86_64__)
6840 #ifdef CONFIG_FB_SIS_300
6841 MODULE_PARM_DESC(resetcard
,
6842 "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
6843 "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
6844 "currently). Default: 0\n");
6846 MODULE_PARM_DESC(videoram
,
6847 "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
6848 "some non-x86 architectures where the memory auto detection fails. Only\n"
6849 "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
6853 #endif /* /MODULE */
6855 /* _GPL only for new symbols. */
6856 EXPORT_SYMBOL(sis_malloc
);
6857 EXPORT_SYMBOL(sis_free
);
6858 EXPORT_SYMBOL_GPL(sis_malloc_new
);
6859 EXPORT_SYMBOL_GPL(sis_free_new
);