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/aperture.h>
23 #include <linux/module.h>
24 #include <linux/moduleparam.h>
25 #include <linux/kernel.h>
26 #include <linux/spinlock.h>
27 #include <linux/errno.h>
28 #include <linux/string.h>
30 #include <linux/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
[24], 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)) {
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 sisfb_search_crt2type(const char *name
)
264 /* We don't know the hardware specs yet and there is no ivideo */
266 if(name
== NULL
) return;
268 while(sis_crt2type
[i
].type_no
!= -1) {
269 if(!strncasecmp(name
, sis_crt2type
[i
].name
, strlen(sis_crt2type
[i
].name
))) {
270 sisfb_crt2type
= sis_crt2type
[i
].type_no
;
271 sisfb_tvplug
= sis_crt2type
[i
].tvplug_no
;
272 sisfb_crt2flags
= sis_crt2type
[i
].flags
;
278 sisfb_dstn
= (sisfb_crt2flags
& FL_550_DSTN
) ? 1 : 0;
279 sisfb_fstn
= (sisfb_crt2flags
& FL_550_FSTN
) ? 1 : 0;
281 if(sisfb_crt2type
< 0)
282 printk(KERN_ERR
"sisfb: Invalid CRT2 type: %s\n", name
);
286 sisfb_search_tvstd(const char *name
)
290 /* We don't know the hardware specs yet and there is no ivideo */
295 while(sis_tvtype
[i
].type_no
!= -1) {
296 if(!strncasecmp(name
, sis_tvtype
[i
].name
, strlen(sis_tvtype
[i
].name
))) {
297 sisfb_tvstd
= sis_tvtype
[i
].type_no
;
305 sisfb_search_specialtiming(const char *name
)
310 /* We don't know the hardware specs yet and there is no ivideo */
315 if(!strncasecmp(name
, "none", 4)) {
316 sisfb_specialtiming
= CUT_FORCENONE
;
317 printk(KERN_DEBUG
"sisfb: Special timing disabled\n");
319 while(mycustomttable
[i
].chipID
!= 0) {
320 if(!strncasecmp(name
,mycustomttable
[i
].optionName
,
321 strlen(mycustomttable
[i
].optionName
))) {
322 sisfb_specialtiming
= mycustomttable
[i
].SpecialID
;
324 printk(KERN_INFO
"sisfb: Special timing for %s %s forced (\"%s\")\n",
325 mycustomttable
[i
].vendorName
,
326 mycustomttable
[i
].cardName
,
327 mycustomttable
[i
].optionName
);
333 printk(KERN_WARNING
"sisfb: Invalid SpecialTiming parameter, valid are:");
334 printk(KERN_WARNING
"\t\"none\" (to disable special timings)\n");
336 while(mycustomttable
[i
].chipID
!= 0) {
337 printk(KERN_WARNING
"\t\"%s\" (for %s %s)\n",
338 mycustomttable
[i
].optionName
,
339 mycustomttable
[i
].vendorName
,
340 mycustomttable
[i
].cardName
);
347 /* ----------- Various detection routines ----------- */
349 static void sisfb_detect_custom_timing(struct sis_video_info
*ivideo
)
351 unsigned char *biosver
= NULL
;
352 unsigned char *biosdate
= NULL
;
357 if(ivideo
->SiS_Pr
.UseROM
) {
358 biosver
= ivideo
->SiS_Pr
.VirtualRomBase
+ 0x06;
359 biosdate
= ivideo
->SiS_Pr
.VirtualRomBase
+ 0x2c;
360 for(i
= 0; i
< 32768; i
++)
361 chksum
+= ivideo
->SiS_Pr
.VirtualRomBase
[i
];
366 if( (mycustomttable
[i
].chipID
== ivideo
->chip
) &&
367 ((!strlen(mycustomttable
[i
].biosversion
)) ||
368 (ivideo
->SiS_Pr
.UseROM
&&
369 (!strncmp(mycustomttable
[i
].biosversion
, biosver
,
370 strlen(mycustomttable
[i
].biosversion
))))) &&
371 ((!strlen(mycustomttable
[i
].biosdate
)) ||
372 (ivideo
->SiS_Pr
.UseROM
&&
373 (!strncmp(mycustomttable
[i
].biosdate
, biosdate
,
374 strlen(mycustomttable
[i
].biosdate
))))) &&
375 ((!mycustomttable
[i
].bioschksum
) ||
376 (ivideo
->SiS_Pr
.UseROM
&&
377 (mycustomttable
[i
].bioschksum
== chksum
))) &&
378 (mycustomttable
[i
].pcisubsysvendor
== ivideo
->subsysvendor
) &&
379 (mycustomttable
[i
].pcisubsyscard
== ivideo
->subsysdevice
) ) {
381 for(j
= 0; j
< 5; j
++) {
382 if(mycustomttable
[i
].biosFootprintAddr
[j
]) {
383 if(ivideo
->SiS_Pr
.UseROM
) {
384 if(ivideo
->SiS_Pr
.VirtualRomBase
[mycustomttable
[i
].biosFootprintAddr
[j
]] !=
385 mycustomttable
[i
].biosFootprintData
[j
]) {
393 ivideo
->SiS_Pr
.SiS_CustomT
= mycustomttable
[i
].SpecialID
;
394 printk(KERN_DEBUG
"sisfb: Identified [%s %s], special timing applies\n",
395 mycustomttable
[i
].vendorName
,
396 mycustomttable
[i
].cardName
);
397 printk(KERN_DEBUG
"sisfb: [specialtiming parameter name: %s]\n",
398 mycustomttable
[i
].optionName
);
403 } while(mycustomttable
[i
].chipID
);
406 static bool sisfb_interpret_edid(struct sisfb_monitor
*monitor
, u8
*buffer
)
408 int i
, j
, xres
, yres
, refresh
, index
;
411 if(buffer
[0] != 0x00 || buffer
[1] != 0xff ||
412 buffer
[2] != 0xff || buffer
[3] != 0xff ||
413 buffer
[4] != 0xff || buffer
[5] != 0xff ||
414 buffer
[6] != 0xff || buffer
[7] != 0x00) {
415 printk(KERN_DEBUG
"sisfb: Bad EDID header\n");
419 if(buffer
[0x12] != 0x01) {
420 printk(KERN_INFO
"sisfb: EDID version %d not supported\n",
425 monitor
->feature
= buffer
[0x18];
427 if(!(buffer
[0x14] & 0x80)) {
428 if(!(buffer
[0x14] & 0x08)) {
430 "sisfb: WARNING: Monitor does not support separate syncs\n");
434 if(buffer
[0x13] >= 0x01) {
435 /* EDID V1 rev 1 and 2: Search for monitor descriptor
440 if(buffer
[j
] == 0x00 && buffer
[j
+ 1] == 0x00 &&
441 buffer
[j
+ 2] == 0x00 && buffer
[j
+ 3] == 0xfd &&
442 buffer
[j
+ 4] == 0x00) {
443 monitor
->hmin
= buffer
[j
+ 7];
444 monitor
->hmax
= buffer
[j
+ 8];
445 monitor
->vmin
= buffer
[j
+ 5];
446 monitor
->vmax
= buffer
[j
+ 6];
447 monitor
->dclockmax
= buffer
[j
+ 9] * 10 * 1000;
448 monitor
->datavalid
= true;
455 if(!monitor
->datavalid
) {
456 /* Otherwise: Get a range from the list of supported
457 * Estabished Timings. This is not entirely accurate,
458 * because fixed frequency monitors are not supported
461 monitor
->hmin
= 65535; monitor
->hmax
= 0;
462 monitor
->vmin
= 65535; monitor
->vmax
= 0;
463 monitor
->dclockmax
= 0;
464 emodes
= buffer
[0x23] | (buffer
[0x24] << 8) | (buffer
[0x25] << 16);
465 for(i
= 0; i
< 13; i
++) {
466 if(emodes
& sisfb_ddcsmodes
[i
].mask
) {
467 if(monitor
->hmin
> sisfb_ddcsmodes
[i
].h
) monitor
->hmin
= sisfb_ddcsmodes
[i
].h
;
468 if(monitor
->hmax
< sisfb_ddcsmodes
[i
].h
) monitor
->hmax
= sisfb_ddcsmodes
[i
].h
+ 1;
469 if(monitor
->vmin
> sisfb_ddcsmodes
[i
].v
) monitor
->vmin
= sisfb_ddcsmodes
[i
].v
;
470 if(monitor
->vmax
< sisfb_ddcsmodes
[i
].v
) monitor
->vmax
= sisfb_ddcsmodes
[i
].v
;
471 if(monitor
->dclockmax
< sisfb_ddcsmodes
[i
].d
) monitor
->dclockmax
= sisfb_ddcsmodes
[i
].d
;
475 for(i
= 0; i
< 8; i
++) {
476 xres
= (buffer
[index
] + 31) * 8;
477 switch(buffer
[index
+ 1] & 0xc0) {
478 case 0xc0: yres
= (xres
* 9) / 16; break;
479 case 0x80: yres
= (xres
* 4) / 5; break;
480 case 0x40: yres
= (xres
* 3) / 4; break;
481 default: yres
= xres
; break;
483 refresh
= (buffer
[index
+ 1] & 0x3f) + 60;
484 if((xres
>= 640) && (yres
>= 480)) {
485 for(j
= 0; j
< 8; j
++) {
486 if((xres
== sisfb_ddcfmodes
[j
].x
) &&
487 (yres
== sisfb_ddcfmodes
[j
].y
) &&
488 (refresh
== sisfb_ddcfmodes
[j
].v
)) {
489 if(monitor
->hmin
> sisfb_ddcfmodes
[j
].h
) monitor
->hmin
= sisfb_ddcfmodes
[j
].h
;
490 if(monitor
->hmax
< sisfb_ddcfmodes
[j
].h
) monitor
->hmax
= sisfb_ddcfmodes
[j
].h
+ 1;
491 if(monitor
->vmin
> sisfb_ddcsmodes
[j
].v
) monitor
->vmin
= sisfb_ddcsmodes
[j
].v
;
492 if(monitor
->vmax
< sisfb_ddcsmodes
[j
].v
) monitor
->vmax
= sisfb_ddcsmodes
[j
].v
;
493 if(monitor
->dclockmax
< sisfb_ddcsmodes
[j
].d
) monitor
->dclockmax
= sisfb_ddcsmodes
[j
].d
;
499 if((monitor
->hmin
<= monitor
->hmax
) && (monitor
->vmin
<= monitor
->vmax
)) {
500 monitor
->datavalid
= true;
504 return monitor
->datavalid
;
507 static void sisfb_handle_ddc(struct sis_video_info
*ivideo
,
508 struct sisfb_monitor
*monitor
, int crtno
)
510 unsigned short temp
, i
, realcrtno
= crtno
;
511 unsigned char buffer
[256];
513 monitor
->datavalid
= false;
516 if(ivideo
->vbflags
& CRT2_LCD
) realcrtno
= 1;
517 else if(ivideo
->vbflags
& CRT2_VGA
) realcrtno
= 2;
521 if((ivideo
->sisfb_crt1off
) && (!crtno
))
524 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
525 realcrtno
, 0, &buffer
[0], ivideo
->vbflags2
);
526 if((!temp
) || (temp
== 0xffff)) {
527 printk(KERN_INFO
"sisfb: CRT%d DDC probing failed\n", crtno
+ 1);
530 printk(KERN_INFO
"sisfb: CRT%d DDC supported\n", crtno
+ 1);
531 printk(KERN_INFO
"sisfb: CRT%d DDC level: %s%s%s%s\n",
533 (temp
& 0x1a) ? "" : "[none of the supported]",
534 (temp
& 0x02) ? "2 " : "",
535 (temp
& 0x08) ? "D&P" : "",
536 (temp
& 0x10) ? "FPDI-2" : "");
538 i
= 3; /* Number of retrys */
540 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
541 realcrtno
, 1, &buffer
[0], ivideo
->vbflags2
);
542 } while((temp
) && i
--);
544 if(sisfb_interpret_edid(monitor
, &buffer
[0])) {
545 printk(KERN_INFO
"sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
546 monitor
->hmin
, monitor
->hmax
, monitor
->vmin
, monitor
->vmax
,
547 monitor
->dclockmax
/ 1000);
549 printk(KERN_INFO
"sisfb: CRT%d DDC EDID corrupt\n", crtno
+ 1);
552 printk(KERN_INFO
"sisfb: CRT%d DDC reading failed\n", crtno
+ 1);
555 printk(KERN_INFO
"sisfb: VESA D&P and FPDI-2 not supported yet\n");
560 /* -------------- Mode validation --------------- */
563 sisfb_verify_rate(struct sis_video_info
*ivideo
, struct sisfb_monitor
*monitor
,
564 int mode_idx
, int rate_idx
, int rate
)
567 unsigned int dclock
, hsync
;
569 if(!monitor
->datavalid
)
575 /* Skip for 320x200, 320x240, 640x400 */
576 switch(sisbios_mode
[mode_idx
].mode_no
[ivideo
->mni
]) {
587 #ifdef CONFIG_FB_SIS_315
590 if(ivideo
->sisvga_engine
== SIS_315_VGA
) return true;
594 if(rate
< (monitor
->vmin
- 1))
596 if(rate
> (monitor
->vmax
+ 1))
599 if(sisfb_gettotalfrommode(&ivideo
->SiS_Pr
,
600 sisbios_mode
[mode_idx
].mode_no
[ivideo
->mni
],
601 &htotal
, &vtotal
, rate_idx
)) {
602 dclock
= (htotal
* vtotal
* rate
) / 1000;
603 if(dclock
> (monitor
->dclockmax
+ 1000))
605 hsync
= dclock
/ htotal
;
606 if(hsync
< (monitor
->hmin
- 1))
608 if(hsync
> (monitor
->hmax
+ 1))
617 sisfb_validate_mode(struct sis_video_info
*ivideo
, int myindex
, u32 vbflags
)
619 u16 xres
=0, yres
, myres
;
621 #ifdef CONFIG_FB_SIS_300
622 if (ivideo
->sisvga_engine
== SIS_300_VGA
) {
623 if (!(sisbios_mode
[myindex
].chipset
& MD_SIS300
))
627 #ifdef CONFIG_FB_SIS_315
628 if (ivideo
->sisvga_engine
== SIS_315_VGA
) {
629 if (!(sisbios_mode
[myindex
].chipset
& MD_SIS315
))
634 myres
= sisbios_mode
[myindex
].yres
;
636 switch (vbflags
& VB_DISPTYPE_DISP2
) {
639 xres
= ivideo
->lcdxres
; yres
= ivideo
->lcdyres
;
641 if ((ivideo
->SiS_Pr
.SiS_CustomT
!= CUT_PANEL848
) &&
642 (ivideo
->SiS_Pr
.SiS_CustomT
!= CUT_PANEL856
)) {
643 if (sisbios_mode
[myindex
].xres
> xres
)
649 if (ivideo
->sisfb_fstn
) {
650 if (sisbios_mode
[myindex
].xres
== 320) {
652 switch (sisbios_mode
[myindex
].mode_no
[1]) {
653 case 0x50: myindex
= MODE_FSTN_8
; break;
654 case 0x56: myindex
= MODE_FSTN_16
; break;
655 case 0x53: return -1;
661 if (SiS_GetModeID_LCD(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
662 sisbios_mode
[myindex
].yres
, 0, ivideo
->sisfb_fstn
,
663 ivideo
->SiS_Pr
.SiS_CustomT
, xres
, yres
, ivideo
->vbflags2
) < 0x14) {
669 if (SiS_GetModeID_TV(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
670 sisbios_mode
[myindex
].yres
, 0, ivideo
->vbflags2
) < 0x14) {
676 if (SiS_GetModeID_VGA2(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
677 sisbios_mode
[myindex
].yres
, 0, ivideo
->vbflags2
) < 0x14) {
687 sisfb_search_refresh_rate(struct sis_video_info
*ivideo
, unsigned int rate
, int mode_idx
)
690 u16 xres
= sisbios_mode
[mode_idx
].xres
;
691 u16 yres
= sisbios_mode
[mode_idx
].yres
;
693 ivideo
->rate_idx
= 0;
694 while((sisfb_vrate
[i
].idx
!= 0) && (sisfb_vrate
[i
].xres
<= xres
)) {
695 if((sisfb_vrate
[i
].xres
== xres
) && (sisfb_vrate
[i
].yres
== yres
)) {
696 if(sisfb_vrate
[i
].refresh
== rate
) {
697 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
699 } else if(sisfb_vrate
[i
].refresh
> rate
) {
700 if((sisfb_vrate
[i
].refresh
- rate
) <= 3) {
701 DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
702 rate
, sisfb_vrate
[i
].refresh
);
703 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
704 ivideo
->refresh_rate
= sisfb_vrate
[i
].refresh
;
705 } else if((sisfb_vrate
[i
].idx
!= 1) &&
706 ((rate
- sisfb_vrate
[i
-1].refresh
) <= 2)) {
707 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
708 rate
, sisfb_vrate
[i
-1].refresh
);
709 ivideo
->rate_idx
= sisfb_vrate
[i
-1].idx
;
710 ivideo
->refresh_rate
= sisfb_vrate
[i
-1].refresh
;
713 } else if((rate
- sisfb_vrate
[i
].refresh
) <= 2) {
714 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
715 rate
, sisfb_vrate
[i
].refresh
);
716 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
722 if(ivideo
->rate_idx
> 0) {
723 return ivideo
->rate_idx
;
725 printk(KERN_INFO
"sisfb: Unsupported rate %d for %dx%d\n",
732 sisfb_bridgeisslave(struct sis_video_info
*ivideo
)
736 if(!(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
))
739 P1_00
= SiS_GetReg(SISPART1
, 0x00);
740 if( ((ivideo
->sisvga_engine
== SIS_300_VGA
) && (P1_00
& 0xa0) == 0x20) ||
741 ((ivideo
->sisvga_engine
== SIS_315_VGA
) && (P1_00
& 0x50) == 0x10) ) {
749 sisfballowretracecrt1(struct sis_video_info
*ivideo
)
753 temp
= SiS_GetReg(SISCR
, 0x17);
757 temp
= SiS_GetReg(SISSR
, 0x1f);
765 sisfbcheckvretracecrt1(struct sis_video_info
*ivideo
)
767 if(!sisfballowretracecrt1(ivideo
))
770 if (SiS_GetRegByte(SISINPSTAT
) & 0x08)
777 sisfbwaitretracecrt1(struct sis_video_info
*ivideo
)
781 if(!sisfballowretracecrt1(ivideo
))
785 while ((!(SiS_GetRegByte(SISINPSTAT
) & 0x08)) && --watchdog
);
787 while ((SiS_GetRegByte(SISINPSTAT
) & 0x08) && --watchdog
);
791 sisfbcheckvretracecrt2(struct sis_video_info
*ivideo
)
793 unsigned char temp
, reg
;
795 switch(ivideo
->sisvga_engine
) {
796 case SIS_300_VGA
: reg
= 0x25; break;
797 case SIS_315_VGA
: reg
= 0x30; break;
798 default: return false;
801 temp
= SiS_GetReg(SISPART1
, reg
);
809 sisfb_CheckVBRetrace(struct sis_video_info
*ivideo
)
811 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
812 if(!sisfb_bridgeisslave(ivideo
)) {
813 return sisfbcheckvretracecrt2(ivideo
);
816 return sisfbcheckvretracecrt1(ivideo
);
820 sisfb_setupvbblankflags(struct sis_video_info
*ivideo
, u32
*vcount
, u32
*hcount
)
822 u8 idx
, reg1
, reg2
, reg3
, reg4
;
825 (*vcount
) = (*hcount
) = 0;
827 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) && (!(sisfb_bridgeisslave(ivideo
)))) {
829 ret
|= (FB_VBLANK_HAVE_VSYNC
|
830 FB_VBLANK_HAVE_HBLANK
|
831 FB_VBLANK_HAVE_VBLANK
|
832 FB_VBLANK_HAVE_VCOUNT
|
833 FB_VBLANK_HAVE_HCOUNT
);
834 switch(ivideo
->sisvga_engine
) {
835 case SIS_300_VGA
: idx
= 0x25; break;
837 case SIS_315_VGA
: idx
= 0x30; break;
839 reg1
= SiS_GetReg(SISPART1
, (idx
+0)); /* 30 */
840 reg2
= SiS_GetReg(SISPART1
, (idx
+1)); /* 31 */
841 reg3
= SiS_GetReg(SISPART1
, (idx
+2)); /* 32 */
842 reg4
= SiS_GetReg(SISPART1
, (idx
+3)); /* 33 */
843 if(reg1
& 0x01) ret
|= FB_VBLANK_VBLANKING
;
844 if(reg1
& 0x02) ret
|= FB_VBLANK_VSYNCING
;
845 if(reg4
& 0x80) ret
|= FB_VBLANK_HBLANKING
;
846 (*vcount
) = reg3
| ((reg4
& 0x70) << 4);
847 (*hcount
) = reg2
| ((reg4
& 0x0f) << 8);
849 } else if(sisfballowretracecrt1(ivideo
)) {
851 ret
|= (FB_VBLANK_HAVE_VSYNC
|
852 FB_VBLANK_HAVE_VBLANK
|
853 FB_VBLANK_HAVE_VCOUNT
|
854 FB_VBLANK_HAVE_HCOUNT
);
855 reg1
= SiS_GetRegByte(SISINPSTAT
);
856 if(reg1
& 0x08) ret
|= FB_VBLANK_VSYNCING
;
857 if(reg1
& 0x01) ret
|= FB_VBLANK_VBLANKING
;
858 reg1
= SiS_GetReg(SISCR
, 0x20);
859 reg1
= SiS_GetReg(SISCR
, 0x1b);
860 reg2
= SiS_GetReg(SISCR
, 0x1c);
861 reg3
= SiS_GetReg(SISCR
, 0x1d);
862 (*vcount
) = reg2
| ((reg3
& 0x07) << 8);
863 (*hcount
) = (reg1
| ((reg3
& 0x10) << 4)) << 3;
870 sisfb_myblank(struct sis_video_info
*ivideo
, int blank
)
872 u8 sr01
, sr11
, sr1f
, cr63
=0, p2_0
, p1_13
;
873 bool backlight
= true;
876 case FB_BLANK_UNBLANK
: /* on */
885 case FB_BLANK_NORMAL
: /* blank */
894 case FB_BLANK_VSYNC_SUSPEND
: /* no vsync */
903 case FB_BLANK_HSYNC_SUSPEND
: /* no hsync */
912 case FB_BLANK_POWERDOWN
: /* off */
925 if(ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
) {
927 if( (!ivideo
->sisfb_thismonitor
.datavalid
) ||
928 ((ivideo
->sisfb_thismonitor
.datavalid
) &&
929 (ivideo
->sisfb_thismonitor
.feature
& 0xe0))) {
931 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
932 SiS_SetRegANDOR(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, 0xbf, cr63
);
935 if(!(sisfb_bridgeisslave(ivideo
))) {
936 SiS_SetRegANDOR(SISSR
, 0x01, ~0x20, sr01
);
937 SiS_SetRegANDOR(SISSR
, 0x1f, 0x3f, sr1f
);
943 if(ivideo
->currentvbflags
& CRT2_LCD
) {
945 if(ivideo
->vbflags2
& VB2_SISLVDSBRIDGE
) {
947 SiS_SiS30xBLOn(&ivideo
->SiS_Pr
);
949 SiS_SiS30xBLOff(&ivideo
->SiS_Pr
);
951 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
952 #ifdef CONFIG_FB_SIS_315
953 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
955 SiS_Chrontel701xBLOn(&ivideo
->SiS_Pr
);
957 SiS_Chrontel701xBLOff(&ivideo
->SiS_Pr
);
963 if(((ivideo
->sisvga_engine
== SIS_300_VGA
) &&
964 (ivideo
->vbflags2
& (VB2_301
|VB2_30xBDH
|VB2_LVDS
))) ||
965 ((ivideo
->sisvga_engine
== SIS_315_VGA
) &&
966 ((ivideo
->vbflags2
& (VB2_LVDS
| VB2_CHRONTEL
)) == VB2_LVDS
))) {
967 SiS_SetRegANDOR(SISSR
, 0x11, ~0x0c, sr11
);
970 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
971 if((ivideo
->vbflags2
& VB2_30xB
) &&
972 (!(ivideo
->vbflags2
& VB2_30xBDH
))) {
973 SiS_SetRegANDOR(SISPART1
, 0x13, 0x3f, p1_13
);
975 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
976 if((ivideo
->vbflags2
& VB2_30xB
) &&
977 (!(ivideo
->vbflags2
& VB2_30xBDH
))) {
978 SiS_SetRegANDOR(SISPART2
, 0x00, 0x1f, p2_0
);
982 } else if(ivideo
->currentvbflags
& CRT2_VGA
) {
984 if(ivideo
->vbflags2
& VB2_30xB
) {
985 SiS_SetRegANDOR(SISPART2
, 0x00, 0x1f, p2_0
);
993 /* ------------- Callbacks from init.c/init301.c -------------- */
995 #ifdef CONFIG_FB_SIS_300
997 sisfb_read_nbridge_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
)
999 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1002 pci_read_config_dword(ivideo
->nbridge
, reg
, &val
);
1003 return (unsigned int)val
;
1007 sisfb_write_nbridge_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
, unsigned int val
)
1009 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1011 pci_write_config_dword(ivideo
->nbridge
, reg
, (u32
)val
);
1015 sisfb_read_lpc_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
)
1017 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1020 if(!ivideo
->lpcdev
) return 0;
1022 pci_read_config_dword(ivideo
->lpcdev
, reg
, &val
);
1023 return (unsigned int)val
;
1027 #ifdef CONFIG_FB_SIS_315
1029 sisfb_write_nbridge_pci_byte(struct SiS_Private
*SiS_Pr
, int reg
, unsigned char val
)
1031 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1033 pci_write_config_byte(ivideo
->nbridge
, reg
, (u8
)val
);
1037 sisfb_read_mio_pci_word(struct SiS_Private
*SiS_Pr
, int reg
)
1039 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1042 if(!ivideo
->lpcdev
) return 0;
1044 pci_read_config_word(ivideo
->lpcdev
, reg
, &val
);
1045 return (unsigned int)val
;
1049 /* ----------- FBDev related routines for all series ----------- */
1052 sisfb_get_cmap_len(const struct fb_var_screeninfo
*var
)
1054 return (var
->bits_per_pixel
== 8) ? 256 : 16;
1058 sisfb_set_vparms(struct sis_video_info
*ivideo
)
1060 switch(ivideo
->video_bpp
) {
1062 ivideo
->DstColor
= 0x0000;
1063 ivideo
->SiS310_AccelDepth
= 0x00000000;
1064 ivideo
->video_cmap_len
= 256;
1067 ivideo
->DstColor
= 0x8000;
1068 ivideo
->SiS310_AccelDepth
= 0x00010000;
1069 ivideo
->video_cmap_len
= 16;
1072 ivideo
->DstColor
= 0xC000;
1073 ivideo
->SiS310_AccelDepth
= 0x00020000;
1074 ivideo
->video_cmap_len
= 16;
1077 ivideo
->video_cmap_len
= 16;
1078 printk(KERN_ERR
"sisfb: Unsupported depth %d", ivideo
->video_bpp
);
1084 sisfb_calc_maxyres(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1086 int maxyres
= ivideo
->sisfb_mem
/ (var
->xres_virtual
* (var
->bits_per_pixel
>> 3));
1088 if(maxyres
> 32767) maxyres
= 32767;
1094 sisfb_calc_pitch(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1096 ivideo
->video_linelength
= var
->xres_virtual
* (var
->bits_per_pixel
>> 3);
1097 ivideo
->scrnpitchCRT1
= ivideo
->video_linelength
;
1098 if(!(ivideo
->currentvbflags
& CRT1_LCDA
)) {
1099 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1100 ivideo
->scrnpitchCRT1
<<= 1;
1106 sisfb_set_pitch(struct sis_video_info
*ivideo
)
1108 bool isslavemode
= false;
1109 unsigned short HDisplay1
= ivideo
->scrnpitchCRT1
>> 3;
1110 unsigned short HDisplay2
= ivideo
->video_linelength
>> 3;
1112 if(sisfb_bridgeisslave(ivideo
)) isslavemode
= true;
1114 /* We need to set pitch for CRT1 if bridge is in slave mode, too */
1115 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP1
) || (isslavemode
)) {
1116 SiS_SetReg(SISCR
, 0x13, (HDisplay1
& 0xFF));
1117 SiS_SetRegANDOR(SISSR
, 0x0E, 0xF0, (HDisplay1
>> 8));
1120 /* We must not set the pitch for CRT2 if bridge is in slave mode */
1121 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) && (!isslavemode
)) {
1122 SiS_SetRegOR(SISPART1
, ivideo
->CRT2_write_enable
, 0x01);
1123 SiS_SetReg(SISPART1
, 0x07, (HDisplay2
& 0xFF));
1124 SiS_SetRegANDOR(SISPART1
, 0x09, 0xF0, (HDisplay2
>> 8));
1129 sisfb_bpp_to_var(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1131 ivideo
->video_cmap_len
= sisfb_get_cmap_len(var
);
1133 switch(var
->bits_per_pixel
) {
1135 var
->red
.offset
= var
->green
.offset
= var
->blue
.offset
= 0;
1136 var
->red
.length
= var
->green
.length
= var
->blue
.length
= 8;
1139 var
->red
.offset
= 11;
1140 var
->red
.length
= 5;
1141 var
->green
.offset
= 5;
1142 var
->green
.length
= 6;
1143 var
->blue
.offset
= 0;
1144 var
->blue
.length
= 5;
1145 var
->transp
.offset
= 0;
1146 var
->transp
.length
= 0;
1149 var
->red
.offset
= 16;
1150 var
->red
.length
= 8;
1151 var
->green
.offset
= 8;
1152 var
->green
.length
= 8;
1153 var
->blue
.offset
= 0;
1154 var
->blue
.length
= 8;
1155 var
->transp
.offset
= 24;
1156 var
->transp
.length
= 8;
1162 sisfb_set_mode(struct sis_video_info
*ivideo
, int clrscrn
)
1164 unsigned short modeno
= ivideo
->mode_no
;
1166 /* >=2.6.12's fbcon clears the screen anyway */
1169 SiS_SetReg(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1171 sisfb_pre_setmode(ivideo
);
1173 if(!SiSSetMode(&ivideo
->SiS_Pr
, modeno
)) {
1174 printk(KERN_ERR
"sisfb: Setting mode[0x%x] failed\n", ivideo
->mode_no
);
1178 SiS_SetReg(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1180 sisfb_post_setmode(ivideo
);
1187 sisfb_do_set_var(struct fb_var_screeninfo
*var
, int isactive
, struct fb_info
*info
)
1189 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1190 unsigned int htotal
= 0, vtotal
= 0;
1191 unsigned int drate
= 0, hrate
= 0;
1192 int found_mode
= 0, ret
;
1196 htotal
= var
->left_margin
+ var
->xres
+ var
->right_margin
+ var
->hsync_len
;
1198 vtotal
= var
->upper_margin
+ var
->lower_margin
+ var
->vsync_len
;
1200 pixclock
= var
->pixclock
;
1202 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
) {
1203 vtotal
+= var
->yres
;
1205 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1206 vtotal
+= var
->yres
;
1208 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1209 vtotal
+= var
->yres
;
1211 } else vtotal
+= var
->yres
;
1213 if(!(htotal
) || !(vtotal
)) {
1214 DPRINTK("sisfb: Invalid 'var' information\n");
1218 if(pixclock
&& htotal
&& vtotal
) {
1219 drate
= 1000000000 / pixclock
;
1220 hrate
= (drate
* 1000) / htotal
;
1221 ivideo
->refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1223 ivideo
->refresh_rate
= 60;
1226 old_mode
= ivideo
->sisfb_mode_idx
;
1227 ivideo
->sisfb_mode_idx
= 0;
1229 while( (sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[0] != 0) &&
1230 (sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
<= var
->xres
) ) {
1231 if( (sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
== var
->xres
) &&
1232 (sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
== var
->yres
) &&
1233 (sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
== var
->bits_per_pixel
)) {
1234 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
1238 ivideo
->sisfb_mode_idx
++;
1242 ivideo
->sisfb_mode_idx
= sisfb_validate_mode(ivideo
,
1243 ivideo
->sisfb_mode_idx
, ivideo
->currentvbflags
);
1245 ivideo
->sisfb_mode_idx
= -1;
1248 if(ivideo
->sisfb_mode_idx
< 0) {
1249 printk(KERN_ERR
"sisfb: Mode %dx%dx%d not supported\n", var
->xres
,
1250 var
->yres
, var
->bits_per_pixel
);
1251 ivideo
->sisfb_mode_idx
= old_mode
;
1255 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
1257 if(sisfb_search_refresh_rate(ivideo
, ivideo
->refresh_rate
, ivideo
->sisfb_mode_idx
) == 0) {
1258 ivideo
->rate_idx
= sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
;
1259 ivideo
->refresh_rate
= 60;
1263 /* If acceleration to be used? Need to know
1264 * before pre/post_set_mode()
1267 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
1268 #ifdef STUPID_ACCELF_TEXT_SHIT
1269 if(var
->accel_flags
& FB_ACCELF_TEXT
) {
1270 info
->flags
&= ~FBINFO_HWACCEL_DISABLED
;
1272 info
->flags
|= FBINFO_HWACCEL_DISABLED
;
1275 if(!(info
->flags
& FBINFO_HWACCEL_DISABLED
)) ivideo
->accel
= -1;
1277 if(var
->accel_flags
& FB_ACCELF_TEXT
) ivideo
->accel
= -1;
1280 if((ret
= sisfb_set_mode(ivideo
, 1))) {
1284 ivideo
->video_bpp
= sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
;
1285 ivideo
->video_width
= sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
;
1286 ivideo
->video_height
= sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
;
1288 sisfb_calc_pitch(ivideo
, var
);
1289 sisfb_set_pitch(ivideo
);
1291 sisfb_set_vparms(ivideo
);
1293 ivideo
->current_width
= ivideo
->video_width
;
1294 ivideo
->current_height
= ivideo
->video_height
;
1295 ivideo
->current_bpp
= ivideo
->video_bpp
;
1296 ivideo
->current_htotal
= htotal
;
1297 ivideo
->current_vtotal
= vtotal
;
1298 ivideo
->current_linelength
= ivideo
->video_linelength
;
1299 ivideo
->current_pixclock
= var
->pixclock
;
1300 ivideo
->current_refresh_rate
= ivideo
->refresh_rate
;
1301 ivideo
->sisfb_lastrates
[ivideo
->mode_no
] = ivideo
->refresh_rate
;
1308 sisfb_set_base_CRT1(struct sis_video_info
*ivideo
, unsigned int base
)
1310 SiS_SetReg(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1312 SiS_SetReg(SISCR
, 0x0D, base
& 0xFF);
1313 SiS_SetReg(SISCR
, 0x0C, (base
>> 8) & 0xFF);
1314 SiS_SetReg(SISSR
, 0x0D, (base
>> 16) & 0xFF);
1315 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
1316 SiS_SetRegANDOR(SISSR
, 0x37, 0xFE, (base
>> 24) & 0x01);
1321 sisfb_set_base_CRT2(struct sis_video_info
*ivideo
, unsigned int base
)
1323 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
1324 SiS_SetRegOR(SISPART1
, ivideo
->CRT2_write_enable
, 0x01);
1325 SiS_SetReg(SISPART1
, 0x06, (base
& 0xFF));
1326 SiS_SetReg(SISPART1
, 0x05, ((base
>> 8) & 0xFF));
1327 SiS_SetReg(SISPART1
, 0x04, ((base
>> 16) & 0xFF));
1328 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
1329 SiS_SetRegANDOR(SISPART1
, 0x02, 0x7F, ((base
>> 24) & 0x01) << 7);
1335 sisfb_pan_var(struct sis_video_info
*ivideo
, struct fb_info
*info
,
1336 struct fb_var_screeninfo
*var
)
1338 ivideo
->current_base
= var
->yoffset
* info
->var
.xres_virtual
1341 /* calculate base bpp dep. */
1342 switch (info
->var
.bits_per_pixel
) {
1346 ivideo
->current_base
>>= 1;
1350 ivideo
->current_base
>>= 2;
1354 ivideo
->current_base
+= (ivideo
->video_offset
>> 2);
1356 sisfb_set_base_CRT1(ivideo
, ivideo
->current_base
);
1357 sisfb_set_base_CRT2(ivideo
, ivideo
->current_base
);
1363 sisfb_open(struct fb_info
*info
, int user
)
1369 sisfb_release(struct fb_info
*info
, int user
)
1375 sisfb_setcolreg(unsigned regno
, unsigned red
, unsigned green
, unsigned blue
,
1376 unsigned transp
, struct fb_info
*info
)
1378 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1380 if(regno
>= sisfb_get_cmap_len(&info
->var
))
1383 switch(info
->var
.bits_per_pixel
) {
1385 SiS_SetRegByte(SISDACA
, regno
);
1386 SiS_SetRegByte(SISDACD
, (red
>> 10));
1387 SiS_SetRegByte(SISDACD
, (green
>> 10));
1388 SiS_SetRegByte(SISDACD
, (blue
>> 10));
1389 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
1390 SiS_SetRegByte(SISDAC2A
, regno
);
1391 SiS_SetRegByte(SISDAC2D
, (red
>> 8));
1392 SiS_SetRegByte(SISDAC2D
, (green
>> 8));
1393 SiS_SetRegByte(SISDAC2D
, (blue
>> 8));
1400 ((u32
*)(info
->pseudo_palette
))[regno
] =
1402 ((green
& 0xfc00) >> 5) |
1403 ((blue
& 0xf800) >> 11);
1412 ((u32
*)(info
->pseudo_palette
))[regno
] =
1413 (red
<< 16) | (green
<< 8) | (blue
);
1420 sisfb_set_par(struct fb_info
*info
)
1424 if((err
= sisfb_do_set_var(&info
->var
, 1, info
)))
1427 sisfb_get_fix(&info
->fix
, -1, info
);
1433 sisfb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
1435 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1436 unsigned int htotal
= 0, vtotal
= 0, myrateindex
= 0;
1437 unsigned int drate
= 0, hrate
= 0, maxyres
;
1439 int refresh_rate
, search_idx
, tidx
;
1440 bool recalc_clock
= false;
1443 htotal
= var
->left_margin
+ var
->xres
+ var
->right_margin
+ var
->hsync_len
;
1445 vtotal
= var
->upper_margin
+ var
->lower_margin
+ var
->vsync_len
;
1449 pixclock
= var
->pixclock
;
1451 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
) {
1452 vtotal
+= var
->yres
;
1454 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1455 vtotal
+= var
->yres
;
1457 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1458 vtotal
+= var
->yres
;
1461 vtotal
+= var
->yres
;
1463 if(!(htotal
) || !(vtotal
)) {
1464 SISFAIL("sisfb: no valid timing data");
1468 while( (sisbios_mode
[search_idx
].mode_no
[0] != 0) &&
1469 (sisbios_mode
[search_idx
].xres
<= var
->xres
) ) {
1470 if( (sisbios_mode
[search_idx
].xres
== var
->xres
) &&
1471 (sisbios_mode
[search_idx
].yres
== var
->yres
) &&
1472 (sisbios_mode
[search_idx
].bpp
== var
->bits_per_pixel
)) {
1473 if((tidx
= sisfb_validate_mode(ivideo
, search_idx
,
1474 ivideo
->currentvbflags
)) > 0) {
1485 while(sisbios_mode
[search_idx
].mode_no
[0] != 0) {
1486 if( (var
->xres
<= sisbios_mode
[search_idx
].xres
) &&
1487 (var
->yres
<= sisbios_mode
[search_idx
].yres
) &&
1488 (var
->bits_per_pixel
== sisbios_mode
[search_idx
].bpp
) ) {
1489 if((tidx
= sisfb_validate_mode(ivideo
,search_idx
,
1490 ivideo
->currentvbflags
)) > 0) {
1500 "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
1501 var
->xres
, var
->yres
, var
->bits_per_pixel
,
1502 sisbios_mode
[search_idx
].xres
,
1503 sisbios_mode
[search_idx
].yres
,
1504 var
->bits_per_pixel
);
1505 var
->xres
= sisbios_mode
[search_idx
].xres
;
1506 var
->yres
= sisbios_mode
[search_idx
].yres
;
1509 "sisfb: Failed to find supported mode near %dx%dx%d\n",
1510 var
->xres
, var
->yres
, var
->bits_per_pixel
);
1515 if( ((ivideo
->vbflags2
& VB2_LVDS
) ||
1516 ((ivideo
->vbflags2
& VB2_30xBDH
) && (ivideo
->currentvbflags
& CRT2_LCD
))) &&
1517 (var
->bits_per_pixel
== 8) ) {
1518 /* Slave modes on LVDS and 301B-DH */
1520 recalc_clock
= true;
1521 } else if( (ivideo
->current_htotal
== htotal
) &&
1522 (ivideo
->current_vtotal
== vtotal
) &&
1523 (ivideo
->current_pixclock
== pixclock
) ) {
1524 /* x=x & y=y & c=c -> assume depth change */
1525 drate
= 1000000000 / pixclock
;
1526 hrate
= (drate
* 1000) / htotal
;
1527 refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1528 } else if( ( (ivideo
->current_htotal
!= htotal
) ||
1529 (ivideo
->current_vtotal
!= vtotal
) ) &&
1530 (ivideo
->current_pixclock
== var
->pixclock
) ) {
1531 /* x!=x | y!=y & c=c -> invalid pixclock */
1532 if(ivideo
->sisfb_lastrates
[sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
]]) {
1534 ivideo
->sisfb_lastrates
[sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
]];
1535 } else if(ivideo
->sisfb_parm_rate
!= -1) {
1536 /* Sic, sisfb_parm_rate - want to know originally desired rate here */
1537 refresh_rate
= ivideo
->sisfb_parm_rate
;
1541 recalc_clock
= true;
1542 } else if((pixclock
) && (htotal
) && (vtotal
)) {
1543 drate
= 1000000000 / pixclock
;
1544 hrate
= (drate
* 1000) / htotal
;
1545 refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1546 } else if(ivideo
->current_refresh_rate
) {
1547 refresh_rate
= ivideo
->current_refresh_rate
;
1548 recalc_clock
= true;
1551 recalc_clock
= true;
1554 myrateindex
= sisfb_search_refresh_rate(ivideo
, refresh_rate
, search_idx
);
1556 /* Eventually recalculate timing and clock */
1558 if(!myrateindex
) myrateindex
= sisbios_mode
[search_idx
].rate_idx
;
1559 var
->pixclock
= (u32
) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo
->SiS_Pr
,
1560 sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
],
1562 sisfb_mode_rate_to_ddata(&ivideo
->SiS_Pr
,
1563 sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
],
1565 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1566 var
->pixclock
<<= 1;
1570 if(ivideo
->sisfb_thismonitor
.datavalid
) {
1571 if(!sisfb_verify_rate(ivideo
, &ivideo
->sisfb_thismonitor
, search_idx
,
1572 myrateindex
, refresh_rate
)) {
1574 "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1578 /* Adapt RGB settings */
1579 sisfb_bpp_to_var(ivideo
, var
);
1581 if(var
->xres
> var
->xres_virtual
)
1582 var
->xres_virtual
= var
->xres
;
1584 if(ivideo
->sisfb_ypan
) {
1585 maxyres
= sisfb_calc_maxyres(ivideo
, var
);
1586 if(ivideo
->sisfb_max
) {
1587 var
->yres_virtual
= maxyres
;
1589 if(var
->yres_virtual
> maxyres
) {
1590 var
->yres_virtual
= maxyres
;
1593 if(var
->yres_virtual
<= var
->yres
) {
1594 var
->yres_virtual
= var
->yres
;
1597 if(var
->yres
!= var
->yres_virtual
) {
1598 var
->yres_virtual
= var
->yres
;
1604 /* Truncate offsets to maximum if too high */
1605 if(var
->xoffset
> var
->xres_virtual
- var
->xres
) {
1606 var
->xoffset
= var
->xres_virtual
- var
->xres
- 1;
1609 if(var
->yoffset
> var
->yres_virtual
- var
->yres
) {
1610 var
->yoffset
= var
->yres_virtual
- var
->yres
- 1;
1613 /* Set everything else to 0 */
1614 var
->red
.msb_right
=
1615 var
->green
.msb_right
=
1616 var
->blue
.msb_right
=
1617 var
->transp
.offset
=
1618 var
->transp
.length
=
1619 var
->transp
.msb_right
= 0;
1625 sisfb_pan_display(struct fb_var_screeninfo
*var
, struct fb_info
* info
)
1627 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1630 if (var
->vmode
& FB_VMODE_YWRAP
)
1633 if (var
->xoffset
+ info
->var
.xres
> info
->var
.xres_virtual
||
1634 var
->yoffset
+ info
->var
.yres
> info
->var
.yres_virtual
)
1637 err
= sisfb_pan_var(ivideo
, info
, var
);
1641 info
->var
.xoffset
= var
->xoffset
;
1642 info
->var
.yoffset
= var
->yoffset
;
1648 sisfb_blank(int blank
, struct fb_info
*info
)
1650 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1652 return sisfb_myblank(ivideo
, blank
);
1655 /* ----------- FBDev related routines for all series ---------- */
1657 static int sisfb_ioctl(struct fb_info
*info
, unsigned int cmd
,
1660 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1661 struct sis_memreq sismemreq
;
1662 struct fb_vblank sisvbblank
;
1667 u32 __user
*argp
= (u32 __user
*)arg
;
1671 if(!capable(CAP_SYS_RAWIO
))
1674 if(copy_from_user(&sismemreq
, (void __user
*)arg
, sizeof(sismemreq
)))
1677 sis_malloc(&sismemreq
);
1679 if(copy_to_user((void __user
*)arg
, &sismemreq
, sizeof(sismemreq
))) {
1680 sis_free((u32
)sismemreq
.offset
);
1686 if(!capable(CAP_SYS_RAWIO
))
1689 if(get_user(gpu32
, argp
))
1695 case FBIOGET_VBLANK
:
1697 memset(&sisvbblank
, 0, sizeof(struct fb_vblank
));
1699 sisvbblank
.count
= 0;
1700 sisvbblank
.flags
= sisfb_setupvbblankflags(ivideo
, &sisvbblank
.vcount
, &sisvbblank
.hcount
);
1702 if(copy_to_user((void __user
*)arg
, &sisvbblank
, sizeof(sisvbblank
)))
1707 case SISFB_GET_INFO_SIZE
:
1708 return put_user(sizeof(struct sisfb_info
), argp
);
1710 case SISFB_GET_INFO_OLD
:
1711 if(ivideo
->warncount
++ < 10)
1713 "sisfb: Deprecated ioctl call received - update your application!\n");
1715 case SISFB_GET_INFO
: /* For communication with X driver */
1716 ivideo
->sisfb_infoblock
.sisfb_id
= SISFB_ID
;
1717 ivideo
->sisfb_infoblock
.sisfb_version
= VER_MAJOR
;
1718 ivideo
->sisfb_infoblock
.sisfb_revision
= VER_MINOR
;
1719 ivideo
->sisfb_infoblock
.sisfb_patchlevel
= VER_LEVEL
;
1720 ivideo
->sisfb_infoblock
.chip_id
= ivideo
->chip_id
;
1721 ivideo
->sisfb_infoblock
.sisfb_pci_vendor
= ivideo
->chip_vendor
;
1722 ivideo
->sisfb_infoblock
.memory
= ivideo
->video_size
/ 1024;
1723 ivideo
->sisfb_infoblock
.heapstart
= ivideo
->heapstart
/ 1024;
1724 if(ivideo
->modechanged
) {
1725 ivideo
->sisfb_infoblock
.fbvidmode
= ivideo
->mode_no
;
1727 ivideo
->sisfb_infoblock
.fbvidmode
= ivideo
->modeprechange
;
1729 ivideo
->sisfb_infoblock
.sisfb_caps
= ivideo
->caps
;
1730 ivideo
->sisfb_infoblock
.sisfb_tqlen
= ivideo
->cmdQueueSize
/ 1024;
1731 ivideo
->sisfb_infoblock
.sisfb_pcibus
= ivideo
->pcibus
;
1732 ivideo
->sisfb_infoblock
.sisfb_pcislot
= ivideo
->pcislot
;
1733 ivideo
->sisfb_infoblock
.sisfb_pcifunc
= ivideo
->pcifunc
;
1734 ivideo
->sisfb_infoblock
.sisfb_lcdpdc
= ivideo
->detectedpdc
;
1735 ivideo
->sisfb_infoblock
.sisfb_lcdpdca
= ivideo
->detectedpdca
;
1736 ivideo
->sisfb_infoblock
.sisfb_lcda
= ivideo
->detectedlcda
;
1737 ivideo
->sisfb_infoblock
.sisfb_vbflags
= ivideo
->vbflags
;
1738 ivideo
->sisfb_infoblock
.sisfb_currentvbflags
= ivideo
->currentvbflags
;
1739 ivideo
->sisfb_infoblock
.sisfb_scalelcd
= ivideo
->SiS_Pr
.UsePanelScaler
;
1740 ivideo
->sisfb_infoblock
.sisfb_specialtiming
= ivideo
->SiS_Pr
.SiS_CustomT
;
1741 ivideo
->sisfb_infoblock
.sisfb_haveemi
= ivideo
->SiS_Pr
.HaveEMI
? 1 : 0;
1742 ivideo
->sisfb_infoblock
.sisfb_haveemilcd
= ivideo
->SiS_Pr
.HaveEMILCD
? 1 : 0;
1743 ivideo
->sisfb_infoblock
.sisfb_emi30
= ivideo
->SiS_Pr
.EMI_30
;
1744 ivideo
->sisfb_infoblock
.sisfb_emi31
= ivideo
->SiS_Pr
.EMI_31
;
1745 ivideo
->sisfb_infoblock
.sisfb_emi32
= ivideo
->SiS_Pr
.EMI_32
;
1746 ivideo
->sisfb_infoblock
.sisfb_emi33
= ivideo
->SiS_Pr
.EMI_33
;
1747 ivideo
->sisfb_infoblock
.sisfb_tvxpos
= (u16
)(ivideo
->tvxpos
+ 32);
1748 ivideo
->sisfb_infoblock
.sisfb_tvypos
= (u16
)(ivideo
->tvypos
+ 32);
1749 ivideo
->sisfb_infoblock
.sisfb_heapsize
= ivideo
->sisfb_heap_size
/ 1024;
1750 ivideo
->sisfb_infoblock
.sisfb_videooffset
= ivideo
->video_offset
;
1751 ivideo
->sisfb_infoblock
.sisfb_curfstn
= ivideo
->curFSTN
;
1752 ivideo
->sisfb_infoblock
.sisfb_curdstn
= ivideo
->curDSTN
;
1753 ivideo
->sisfb_infoblock
.sisfb_vbflags2
= ivideo
->vbflags2
;
1754 ivideo
->sisfb_infoblock
.sisfb_can_post
= ivideo
->sisfb_can_post
? 1 : 0;
1755 ivideo
->sisfb_infoblock
.sisfb_card_posted
= ivideo
->sisfb_card_posted
? 1 : 0;
1756 ivideo
->sisfb_infoblock
.sisfb_was_boot_device
= ivideo
->sisfb_was_boot_device
? 1 : 0;
1758 if(copy_to_user((void __user
*)arg
, &ivideo
->sisfb_infoblock
,
1759 sizeof(ivideo
->sisfb_infoblock
)))
1764 case SISFB_GET_VBRSTATUS_OLD
:
1765 if(ivideo
->warncount
++ < 10)
1767 "sisfb: Deprecated ioctl call received - update your application!\n");
1769 case SISFB_GET_VBRSTATUS
:
1770 if(sisfb_CheckVBRetrace(ivideo
))
1771 return put_user((u32
)1, argp
);
1773 return put_user((u32
)0, argp
);
1775 case SISFB_GET_AUTOMAXIMIZE_OLD
:
1776 if(ivideo
->warncount
++ < 10)
1778 "sisfb: Deprecated ioctl call received - update your application!\n");
1780 case SISFB_GET_AUTOMAXIMIZE
:
1781 if(ivideo
->sisfb_max
)
1782 return put_user((u32
)1, argp
);
1784 return put_user((u32
)0, argp
);
1786 case SISFB_SET_AUTOMAXIMIZE_OLD
:
1787 if(ivideo
->warncount
++ < 10)
1789 "sisfb: Deprecated ioctl call received - update your application!\n");
1791 case SISFB_SET_AUTOMAXIMIZE
:
1792 if(get_user(gpu32
, argp
))
1795 ivideo
->sisfb_max
= (gpu32
) ? 1 : 0;
1798 case SISFB_SET_TVPOSOFFSET
:
1799 if(get_user(gpu32
, argp
))
1802 sisfb_set_TVxposoffset(ivideo
, ((int)(gpu32
>> 16)) - 32);
1803 sisfb_set_TVyposoffset(ivideo
, ((int)(gpu32
& 0xffff)) - 32);
1806 case SISFB_GET_TVPOSOFFSET
:
1807 return put_user((u32
)(((ivideo
->tvxpos
+32)<<16)|((ivideo
->tvypos
+32)&0xffff)),
1811 if(copy_from_user(&ivideo
->sisfb_command
, (void __user
*)arg
,
1812 sizeof(struct sisfb_cmd
)))
1815 sisfb_handle_command(ivideo
, &ivideo
->sisfb_command
);
1817 if(copy_to_user((void __user
*)arg
, &ivideo
->sisfb_command
,
1818 sizeof(struct sisfb_cmd
)))
1823 case SISFB_SET_LOCK
:
1824 if(get_user(gpu32
, argp
))
1827 ivideo
->sisfblocked
= (gpu32
) ? 1 : 0;
1831 #ifdef SIS_NEW_CONFIG_COMPAT
1832 return -ENOIOCTLCMD
;
1841 sisfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
, struct fb_info
*info
)
1843 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1845 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
1847 strscpy(fix
->id
, ivideo
->myid
, sizeof(fix
->id
));
1849 mutex_lock(&info
->mm_lock
);
1850 fix
->smem_start
= ivideo
->video_base
+ ivideo
->video_offset
;
1851 fix
->smem_len
= ivideo
->sisfb_mem
;
1852 mutex_unlock(&info
->mm_lock
);
1853 fix
->type
= FB_TYPE_PACKED_PIXELS
;
1855 fix
->visual
= (ivideo
->video_bpp
== 8) ? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_TRUECOLOR
;
1857 fix
->ypanstep
= (ivideo
->sisfb_ypan
) ? 1 : 0;
1859 fix
->line_length
= ivideo
->video_linelength
;
1860 fix
->mmio_start
= ivideo
->mmio_base
;
1861 fix
->mmio_len
= ivideo
->mmio_size
;
1862 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
1863 fix
->accel
= FB_ACCEL_SIS_GLAMOUR
;
1864 } else if((ivideo
->chip
== SIS_330
) ||
1865 (ivideo
->chip
== SIS_760
) ||
1866 (ivideo
->chip
== SIS_761
)) {
1867 fix
->accel
= FB_ACCEL_SIS_XABRE
;
1868 } else if(ivideo
->chip
== XGI_20
) {
1869 fix
->accel
= FB_ACCEL_XGI_VOLARI_Z
;
1870 } else if(ivideo
->chip
>= XGI_40
) {
1871 fix
->accel
= FB_ACCEL_XGI_VOLARI_V
;
1873 fix
->accel
= FB_ACCEL_SIS_GLAMOUR_2
;
1879 /* ---------------- fb_ops structures ----------------- */
1881 static const struct fb_ops sisfb_ops
= {
1882 .owner
= THIS_MODULE
,
1883 .fb_open
= sisfb_open
,
1884 .fb_release
= sisfb_release
,
1885 __FB_DEFAULT_IOMEM_OPS_RDWR
,
1886 .fb_check_var
= sisfb_check_var
,
1887 .fb_set_par
= sisfb_set_par
,
1888 .fb_setcolreg
= sisfb_setcolreg
,
1889 .fb_pan_display
= sisfb_pan_display
,
1890 .fb_blank
= sisfb_blank
,
1891 .fb_fillrect
= fbcon_sis_fillrect
,
1892 .fb_copyarea
= fbcon_sis_copyarea
,
1893 .fb_imageblit
= cfb_imageblit
,
1894 .fb_sync
= fbcon_sis_sync
,
1895 #ifdef SIS_NEW_CONFIG_COMPAT
1896 .fb_compat_ioctl
= sisfb_ioctl
,
1898 .fb_ioctl
= sisfb_ioctl
,
1899 __FB_DEFAULT_IOMEM_OPS_MMAP
,
1902 /* ---------------- Chip generation dependent routines ---------------- */
1904 static struct pci_dev
*sisfb_get_northbridge(int basechipid
)
1906 struct pci_dev
*pdev
= NULL
;
1907 int nbridgenum
, nbridgeidx
, i
;
1908 static const unsigned short nbridgeids
[] = {
1909 PCI_DEVICE_ID_SI_540
, /* for SiS 540 VGA */
1910 PCI_DEVICE_ID_SI_630
, /* for SiS 630/730 VGA */
1911 PCI_DEVICE_ID_SI_730
,
1912 PCI_DEVICE_ID_SI_550
, /* for SiS 550 VGA */
1913 PCI_DEVICE_ID_SI_650
, /* for SiS 650/651/740 VGA */
1914 PCI_DEVICE_ID_SI_651
,
1915 PCI_DEVICE_ID_SI_740
,
1916 PCI_DEVICE_ID_SI_661
, /* for SiS 661/741/660/760/761 VGA */
1917 PCI_DEVICE_ID_SI_741
,
1918 PCI_DEVICE_ID_SI_660
,
1919 PCI_DEVICE_ID_SI_760
,
1920 PCI_DEVICE_ID_SI_761
1923 switch(basechipid
) {
1924 #ifdef CONFIG_FB_SIS_300
1925 case SIS_540
: nbridgeidx
= 0; nbridgenum
= 1; break;
1926 case SIS_630
: nbridgeidx
= 1; nbridgenum
= 2; break;
1928 #ifdef CONFIG_FB_SIS_315
1929 case SIS_550
: nbridgeidx
= 3; nbridgenum
= 1; break;
1930 case SIS_650
: nbridgeidx
= 4; nbridgenum
= 3; break;
1931 case SIS_660
: nbridgeidx
= 7; nbridgenum
= 5; break;
1933 default: return NULL
;
1935 for(i
= 0; i
< nbridgenum
; i
++) {
1936 if((pdev
= pci_get_device(PCI_VENDOR_ID_SI
,
1937 nbridgeids
[nbridgeidx
+i
], NULL
)))
1943 static int sisfb_get_dram_size(struct sis_video_info
*ivideo
)
1945 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1949 ivideo
->video_size
= 0;
1950 ivideo
->UMAsize
= ivideo
->LFBsize
= 0;
1952 switch(ivideo
->chip
) {
1953 #ifdef CONFIG_FB_SIS_300
1955 reg
= SiS_GetReg(SISSR
, 0x14);
1956 ivideo
->video_size
= ((reg
& 0x3F) + 1) << 20;
1961 if(!ivideo
->nbridge
)
1963 pci_read_config_byte(ivideo
->nbridge
, 0x63, ®
);
1964 ivideo
->video_size
= 1 << (((reg
& 0x70) >> 4) + 21);
1967 #ifdef CONFIG_FB_SIS_315
1971 reg
= SiS_GetReg(SISSR
, 0x14);
1972 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
1973 switch((reg
>> 2) & 0x03) {
1976 ivideo
->video_size
<<= 1;
1979 ivideo
->video_size
+= (ivideo
->video_size
/2);
1983 reg
= SiS_GetReg(SISSR
, 0x14);
1984 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
1985 if(reg
& 0x0c) ivideo
->video_size
<<= 1;
1990 reg
= SiS_GetReg(SISSR
, 0x14);
1991 ivideo
->video_size
= (((reg
& 0x3f) + 1) << 2) << 20;
1995 reg
= SiS_GetReg(SISCR
, 0x79);
1996 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
2001 reg
= SiS_GetReg(SISCR
, 0x79);
2002 reg
= (reg
& 0xf0) >> 4;
2004 ivideo
->video_size
= (1 << reg
) << 20;
2005 ivideo
->UMAsize
= ivideo
->video_size
;
2007 reg
= SiS_GetReg(SISCR
, 0x78);
2011 ivideo
->LFBsize
= (32 << 20);
2013 ivideo
->LFBsize
= (64 << 20);
2015 ivideo
->video_size
+= ivideo
->LFBsize
;
2021 reg
= SiS_GetReg(SISSR
, 0x14);
2022 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
2023 if(ivideo
->chip
!= XGI_20
) {
2024 reg
= (reg
& 0x0c) >> 2;
2025 if(ivideo
->revision_id
== 2) {
2026 if(reg
& 0x01) reg
= 0x02;
2029 if(reg
== 0x02) ivideo
->video_size
<<= 1;
2030 else if(reg
== 0x03) ivideo
->video_size
<<= 2;
2040 /* -------------- video bridge device detection --------------- */
2042 static void sisfb_detect_VB_connect(struct sis_video_info
*ivideo
)
2046 /* No CRT2 on XGI Z7 */
2047 if(ivideo
->chip
== XGI_20
) {
2048 ivideo
->sisfb_crt1off
= 0;
2052 #ifdef CONFIG_FB_SIS_300
2053 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2054 temp
= SiS_GetReg(SISSR
, 0x17);
2055 if((temp
& 0x0F) && (ivideo
->chip
!= SIS_300
)) {
2056 /* PAL/NTSC is stored on SR16 on such machines */
2057 if(!(ivideo
->vbflags
& (TV_PAL
| TV_NTSC
| TV_PALM
| TV_PALN
))) {
2058 temp
= SiS_GetReg(SISSR
, 0x16);
2060 ivideo
->vbflags
|= TV_PAL
;
2062 ivideo
->vbflags
|= TV_NTSC
;
2068 cr32
= SiS_GetReg(SISCR
, 0x32);
2070 if(cr32
& SIS_CRT1
) {
2071 ivideo
->sisfb_crt1off
= 0;
2073 ivideo
->sisfb_crt1off
= (cr32
& 0xDF) ? 1 : 0;
2076 ivideo
->vbflags
&= ~(CRT2_TV
| CRT2_LCD
| CRT2_VGA
);
2078 if(cr32
& SIS_VB_TV
) ivideo
->vbflags
|= CRT2_TV
;
2079 if(cr32
& SIS_VB_LCD
) ivideo
->vbflags
|= CRT2_LCD
;
2080 if(cr32
& SIS_VB_CRT2
) ivideo
->vbflags
|= CRT2_VGA
;
2082 /* Check given parms for hardware compatibility.
2083 * (Cannot do this in the search_xx routines since we don't
2084 * know what hardware we are running on then)
2087 if(ivideo
->chip
!= SIS_550
) {
2088 ivideo
->sisfb_dstn
= ivideo
->sisfb_fstn
= 0;
2091 if(ivideo
->sisfb_tvplug
!= -1) {
2092 if( (ivideo
->sisvga_engine
!= SIS_315_VGA
) ||
2093 (!(ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) ) {
2094 if(ivideo
->sisfb_tvplug
& TV_YPBPR
) {
2095 ivideo
->sisfb_tvplug
= -1;
2096 printk(KERN_ERR
"sisfb: YPbPr not supported\n");
2100 if(ivideo
->sisfb_tvplug
!= -1) {
2101 if( (ivideo
->sisvga_engine
!= SIS_315_VGA
) ||
2102 (!(ivideo
->vbflags2
& VB2_SISHIVISIONBRIDGE
)) ) {
2103 if(ivideo
->sisfb_tvplug
& TV_HIVISION
) {
2104 ivideo
->sisfb_tvplug
= -1;
2105 printk(KERN_ERR
"sisfb: HiVision not supported\n");
2109 if(ivideo
->sisfb_tvstd
!= -1) {
2110 if( (!(ivideo
->vbflags2
& VB2_SISBRIDGE
)) &&
2111 (!((ivideo
->sisvga_engine
== SIS_315_VGA
) &&
2112 (ivideo
->vbflags2
& VB2_CHRONTEL
))) ) {
2113 if(ivideo
->sisfb_tvstd
& (TV_PALM
| TV_PALN
| TV_NTSCJ
)) {
2114 ivideo
->sisfb_tvstd
= -1;
2115 printk(KERN_ERR
"sisfb: PALM/PALN/NTSCJ not supported\n");
2120 /* Detect/set TV plug & type */
2121 if(ivideo
->sisfb_tvplug
!= -1) {
2122 ivideo
->vbflags
|= ivideo
->sisfb_tvplug
;
2124 if(cr32
& SIS_VB_YPBPR
) ivideo
->vbflags
|= (TV_YPBPR
|TV_YPBPR525I
); /* default: 480i */
2125 else if(cr32
& SIS_VB_HIVISION
) ivideo
->vbflags
|= TV_HIVISION
;
2126 else if(cr32
& SIS_VB_SCART
) ivideo
->vbflags
|= TV_SCART
;
2128 if(cr32
& SIS_VB_SVIDEO
) ivideo
->vbflags
|= TV_SVIDEO
;
2129 if(cr32
& SIS_VB_COMPOSITE
) ivideo
->vbflags
|= TV_AVIDEO
;
2133 if(!(ivideo
->vbflags
& (TV_YPBPR
| TV_HIVISION
))) {
2134 if(ivideo
->sisfb_tvstd
!= -1) {
2135 ivideo
->vbflags
&= ~(TV_NTSC
| TV_PAL
| TV_PALM
| TV_PALN
| TV_NTSCJ
);
2136 ivideo
->vbflags
|= ivideo
->sisfb_tvstd
;
2138 if(ivideo
->vbflags
& TV_SCART
) {
2139 ivideo
->vbflags
&= ~(TV_NTSC
| TV_PALM
| TV_PALN
| TV_NTSCJ
);
2140 ivideo
->vbflags
|= TV_PAL
;
2142 if(!(ivideo
->vbflags
& (TV_PAL
| TV_NTSC
| TV_PALM
| TV_PALN
| TV_NTSCJ
))) {
2143 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2144 temp
= SiS_GetReg(SISSR
, 0x38);
2145 if(temp
& 0x01) ivideo
->vbflags
|= TV_PAL
;
2146 else ivideo
->vbflags
|= TV_NTSC
;
2147 } else if((ivideo
->chip
<= SIS_315PRO
) || (ivideo
->chip
>= SIS_330
)) {
2148 temp
= SiS_GetReg(SISSR
, 0x38);
2149 if(temp
& 0x01) ivideo
->vbflags
|= TV_PAL
;
2150 else ivideo
->vbflags
|= TV_NTSC
;
2152 temp
= SiS_GetReg(SISCR
, 0x79);
2153 if(temp
& 0x20) ivideo
->vbflags
|= TV_PAL
;
2154 else ivideo
->vbflags
|= TV_NTSC
;
2159 /* Copy forceCRT1 option to CRT1off if option is given */
2160 if(ivideo
->sisfb_forcecrt1
!= -1) {
2161 ivideo
->sisfb_crt1off
= (ivideo
->sisfb_forcecrt1
) ? 0 : 1;
2165 /* ------------------ Sensing routines ------------------ */
2167 static bool sisfb_test_DDC1(struct sis_video_info
*ivideo
)
2172 old
= SiS_ReadDDC1Bit(&ivideo
->SiS_Pr
);
2174 if(old
!= SiS_ReadDDC1Bit(&ivideo
->SiS_Pr
)) break;
2176 return (count
!= -1);
2179 static void sisfb_sense_crt1(struct sis_video_info
*ivideo
)
2181 bool mustwait
= false;
2183 #ifdef CONFIG_FB_SIS_315
2189 sr1F
= SiS_GetReg(SISSR
, 0x1F);
2190 SiS_SetRegOR(SISSR
, 0x1F, 0x04);
2191 SiS_SetRegAND(SISSR
, 0x1F, 0x3F);
2196 #ifdef CONFIG_FB_SIS_315
2197 if (ivideo
->sisvga_engine
== SIS_315_VGA
) {
2198 cr63
= SiS_GetReg(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
);
2200 SiS_SetRegAND(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, 0xBF);
2204 cr17
= SiS_GetReg(SISCR
, 0x17);
2208 SiS_SetRegOR(SISCR
, 0x17, 0x80);
2210 SiS_SetReg(SISSR
, 0x00, 0x01);
2211 SiS_SetReg(SISSR
, 0x00, 0x03);
2215 for (i
= 0; i
< 10; i
++)
2216 sisfbwaitretracecrt1(ivideo
);
2218 #ifdef CONFIG_FB_SIS_315
2219 if (ivideo
->chip
>= SIS_330
) {
2220 SiS_SetRegAND(SISCR
, 0x32, ~0x20);
2221 if (ivideo
->chip
>= SIS_340
)
2222 SiS_SetReg(SISCR
, 0x57, 0x4a);
2224 SiS_SetReg(SISCR
, 0x57, 0x5f);
2226 SiS_SetRegOR(SISCR
, 0x53, 0x02);
2227 while ((SiS_GetRegByte(SISINPSTAT
)) & 0x01)
2229 while (!((SiS_GetRegByte(SISINPSTAT
)) & 0x01))
2231 if ((SiS_GetRegByte(SISMISCW
)) & 0x10)
2234 SiS_SetRegAND(SISCR
, 0x53, 0xfd);
2235 SiS_SetRegAND(SISCR
, 0x57, 0x00);
2239 if (temp
== 0xffff) {
2243 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
,
2244 ivideo
->sisvga_engine
, 0, 0, NULL
, ivideo
->vbflags2
);
2245 } while (((temp
== 0) || (temp
== 0xffff)) && i
--);
2247 if ((temp
== 0) || (temp
== 0xffff)) {
2248 if (sisfb_test_DDC1(ivideo
))
2253 if ((temp
) && (temp
!= 0xffff))
2254 SiS_SetRegOR(SISCR
, 0x32, 0x20);
2256 #ifdef CONFIG_FB_SIS_315
2257 if (ivideo
->sisvga_engine
== SIS_315_VGA
)
2258 SiS_SetRegANDOR(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, 0xBF, cr63
);
2261 SiS_SetRegANDOR(SISCR
, 0x17, 0x7F, cr17
);
2262 SiS_SetReg(SISSR
, 0x1F, sr1F
);
2265 /* Determine and detect attached devices on SiS30x */
2266 static void SiS_SenseLCD(struct sis_video_info
*ivideo
)
2268 unsigned char buffer
[256];
2269 unsigned short temp
, realcrtno
, i
;
2270 u8 reg
, cr37
= 0, paneltype
= 0;
2273 ivideo
->SiS_Pr
.PanelSelfDetected
= false;
2275 /* LCD detection only for TMDS bridges */
2276 if (!(ivideo
->vbflags2
& VB2_SISTMDSBRIDGE
))
2278 if (ivideo
->vbflags2
& VB2_30xBDH
)
2281 /* If LCD already set up by BIOS, skip it */
2282 reg
= SiS_GetReg(SISCR
, 0x32);
2287 if (ivideo
->SiS_Pr
.DDCPortMixup
)
2290 /* Check DDC capabilities */
2291 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
2292 realcrtno
, 0, &buffer
[0], ivideo
->vbflags2
);
2294 if ((!temp
) || (temp
== 0xffff) || (!(temp
& 0x02)))
2298 i
= 3; /* Number of retrys */
2300 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
,
2301 ivideo
->sisvga_engine
, realcrtno
, 1,
2302 &buffer
[0], ivideo
->vbflags2
);
2303 } while ((temp
) && i
--);
2308 /* No digital device */
2309 if (!(buffer
[0x14] & 0x80))
2312 /* First detailed timing preferred timing? */
2313 if (!(buffer
[0x18] & 0x02))
2316 xres
= buffer
[0x38] | ((buffer
[0x3a] & 0xf0) << 4);
2317 yres
= buffer
[0x3b] | ((buffer
[0x3d] & 0xf0) << 4);
2329 if ((yres
== 1200) && (ivideo
->vbflags2
& VB2_30xC
))
2340 if ((buffer
[0x47] & 0x18) == 0x18)
2341 cr37
|= ((((buffer
[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2345 SiS_SetReg(SISCR
, 0x36, paneltype
);
2347 SiS_SetRegANDOR(SISCR
, 0x37, 0x0c, cr37
);
2348 SiS_SetRegOR(SISCR
, 0x32, 0x08);
2350 ivideo
->SiS_Pr
.PanelSelfDetected
= true;
2353 static int SISDoSense(struct sis_video_info
*ivideo
, u16 type
, u16 test
)
2355 int temp
, mytest
, result
, i
, j
;
2357 for (j
= 0; j
< 10; j
++) {
2359 for (i
= 0; i
< 3; i
++) {
2361 SiS_SetReg(SISPART4
, 0x11, (type
& 0x00ff));
2362 temp
= (type
>> 8) | (mytest
& 0x00ff);
2363 SiS_SetRegANDOR(SISPART4
, 0x10, 0xe0, temp
);
2364 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x1500);
2367 temp
= SiS_GetReg(SISPART4
, 0x03);
2373 SiS_SetReg(SISPART4
, 0x11, 0x00);
2374 SiS_SetRegAND(SISPART4
, 0x10, 0xe0);
2375 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x1000);
2379 if ((result
== 0) || (result
>= 2))
2385 static void SiS_Sense30x(struct sis_video_info
*ivideo
)
2387 u8 backupP4_0d
,backupP2_00
,backupP2_4d
,backupSR_1e
,biosflag
=0;
2388 u16 svhs
=0, svhs_c
=0;
2389 u16 cvbs
=0, cvbs_c
=0;
2390 u16 vga2
=0, vga2_c
=0;
2392 char stdstr
[] = "sisfb: Detected";
2393 char tvstr
[] = "TV connected to";
2395 if(ivideo
->vbflags2
& VB2_301
) {
2396 svhs
= 0x00b9; cvbs
= 0x00b3; vga2
= 0x00d1;
2397 myflag
= SiS_GetReg(SISPART4
, 0x01);
2399 svhs
= 0x00dd; cvbs
= 0x00ee; vga2
= 0x00fd;
2401 } else if(ivideo
->vbflags2
& (VB2_301B
| VB2_302B
)) {
2402 svhs
= 0x016b; cvbs
= 0x0174; vga2
= 0x0190;
2403 } else if(ivideo
->vbflags2
& (VB2_301LV
| VB2_302LV
)) {
2404 svhs
= 0x0200; cvbs
= 0x0100;
2405 } else if(ivideo
->vbflags2
& (VB2_301C
| VB2_302ELV
| VB2_307T
| VB2_307LV
)) {
2406 svhs
= 0x016b; cvbs
= 0x0110; vga2
= 0x0190;
2410 vga2_c
= 0x0e08; svhs_c
= 0x0404; cvbs_c
= 0x0804;
2411 if(ivideo
->vbflags
& (VB2_301LV
|VB2_302LV
|VB2_302ELV
|VB2_307LV
)) {
2412 svhs_c
= 0x0408; cvbs_c
= 0x0808;
2416 if(ivideo
->haveXGIROM
) {
2417 biosflag
= ivideo
->bios_abase
[0x58] & 0x03;
2418 } else if(ivideo
->newrom
) {
2419 if(ivideo
->bios_abase
[0x5d] & 0x04) biosflag
|= 0x01;
2420 } else if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2421 if(ivideo
->bios_abase
) {
2422 biosflag
= ivideo
->bios_abase
[0xfe] & 0x03;
2426 if(ivideo
->chip
== SIS_300
) {
2427 myflag
= SiS_GetReg(SISSR
, 0x3b);
2428 if(!(myflag
& 0x01)) vga2
= vga2_c
= 0;
2431 if(!(ivideo
->vbflags2
& VB2_SISVGA2BRIDGE
)) {
2435 backupSR_1e
= SiS_GetReg(SISSR
, 0x1e);
2436 SiS_SetRegOR(SISSR
, 0x1e, 0x20);
2438 backupP4_0d
= SiS_GetReg(SISPART4
, 0x0d);
2439 if(ivideo
->vbflags2
& VB2_30xC
) {
2440 SiS_SetRegANDOR(SISPART4
, 0x0d, ~0x07, 0x01);
2442 SiS_SetRegOR(SISPART4
, 0x0d, 0x04);
2444 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x2000);
2446 backupP2_00
= SiS_GetReg(SISPART2
, 0x00);
2447 SiS_SetReg(SISPART2
, 0x00, ((backupP2_00
| 0x1c) & 0xfc));
2449 backupP2_4d
= SiS_GetReg(SISPART2
, 0x4d);
2450 if(ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
) {
2451 SiS_SetReg(SISPART2
, 0x4d, (backupP2_4d
& ~0x10));
2454 if(!(ivideo
->vbflags2
& VB2_30xCLV
)) {
2455 SISDoSense(ivideo
, 0, 0);
2458 SiS_SetRegAND(SISCR
, 0x32, ~0x14);
2460 if(vga2_c
|| vga2
) {
2461 if(SISDoSense(ivideo
, vga2
, vga2_c
)) {
2462 if(biosflag
& 0x01) {
2463 printk(KERN_INFO
"%s %s SCART output\n", stdstr
, tvstr
);
2464 SiS_SetRegOR(SISCR
, 0x32, 0x04);
2466 printk(KERN_INFO
"%s secondary VGA connection\n", stdstr
);
2467 SiS_SetRegOR(SISCR
, 0x32, 0x10);
2472 SiS_SetRegAND(SISCR
, 0x32, 0x3f);
2474 if(ivideo
->vbflags2
& VB2_30xCLV
) {
2475 SiS_SetRegOR(SISPART4
, 0x0d, 0x04);
2478 if((ivideo
->sisvga_engine
== SIS_315_VGA
) && (ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) {
2479 SiS_SetReg(SISPART2
, 0x4d, (backupP2_4d
| 0x10));
2480 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x2000);
2481 if((result
= SISDoSense(ivideo
, svhs
, 0x0604))) {
2482 if((result
= SISDoSense(ivideo
, cvbs
, 0x0804))) {
2483 printk(KERN_INFO
"%s %s YPbPr component output\n", stdstr
, tvstr
);
2484 SiS_SetRegOR(SISCR
, 0x32, 0x80);
2487 SiS_SetReg(SISPART2
, 0x4d, backupP2_4d
);
2490 SiS_SetRegAND(SISCR
, 0x32, ~0x03);
2492 if(!(ivideo
->vbflags
& TV_YPBPR
)) {
2493 if((result
= SISDoSense(ivideo
, svhs
, svhs_c
))) {
2494 printk(KERN_INFO
"%s %s SVIDEO output\n", stdstr
, tvstr
);
2495 SiS_SetRegOR(SISCR
, 0x32, 0x02);
2497 if((biosflag
& 0x02) || (!result
)) {
2498 if(SISDoSense(ivideo
, cvbs
, cvbs_c
)) {
2499 printk(KERN_INFO
"%s %s COMPOSITE output\n", stdstr
, tvstr
);
2500 SiS_SetRegOR(SISCR
, 0x32, 0x01);
2505 SISDoSense(ivideo
, 0, 0);
2507 SiS_SetReg(SISPART2
, 0x00, backupP2_00
);
2508 SiS_SetReg(SISPART4
, 0x0d, backupP4_0d
);
2509 SiS_SetReg(SISSR
, 0x1e, backupSR_1e
);
2511 if(ivideo
->vbflags2
& VB2_30xCLV
) {
2512 biosflag
= SiS_GetReg(SISPART2
, 0x00);
2513 if(biosflag
& 0x20) {
2514 for(myflag
= 2; myflag
> 0; myflag
--) {
2516 SiS_SetReg(SISPART2
, 0x00, biosflag
);
2521 SiS_SetReg(SISPART2
, 0x00, backupP2_00
);
2524 /* Determine and detect attached TV's on Chrontel */
2525 static void SiS_SenseCh(struct sis_video_info
*ivideo
)
2527 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2529 char stdstr
[] = "sisfb: Chrontel: Detected TV connected to";
2531 #ifdef CONFIG_FB_SIS_300
2532 unsigned char test
[3];
2536 if(ivideo
->chip
< SIS_315H
) {
2538 #ifdef CONFIG_FB_SIS_300
2539 ivideo
->SiS_Pr
.SiS_IF_DEF_CH70xx
= 1; /* Chrontel 700x */
2540 SiS_SetChrontelGPIO(&ivideo
->SiS_Pr
, 0x9c); /* Set general purpose IO for Chrontel communication */
2541 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 1000);
2542 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x25);
2543 /* See Chrontel TB31 for explanation */
2544 temp2
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0e);
2545 if(((temp2
& 0x07) == 0x01) || (temp2
& 0x04)) {
2546 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0e, 0x0b);
2547 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 300);
2549 temp2
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x25);
2550 if(temp2
!= temp1
) temp1
= temp2
;
2552 if((temp1
>= 0x22) && (temp1
<= 0x50)) {
2553 /* Read power status */
2554 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0e);
2555 if((temp1
& 0x03) != 0x03) {
2556 /* Power all outputs */
2557 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0e,0x0b);
2558 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 300);
2560 /* Sense connected TV devices */
2561 for(i
= 0; i
< 3; i
++) {
2562 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x10, 0x01);
2563 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2564 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x10, 0x00);
2565 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2566 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x10);
2567 if(!(temp1
& 0x08)) test
[i
] = 0x02;
2568 else if(!(temp1
& 0x02)) test
[i
] = 0x01;
2570 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2573 if(test
[0] == test
[1]) temp1
= test
[0];
2574 else if(test
[0] == test
[2]) temp1
= test
[0];
2575 else if(test
[1] == test
[2]) temp1
= test
[1];
2578 "sisfb: TV detection unreliable - test results varied\n");
2582 printk(KERN_INFO
"%s SVIDEO output\n", stdstr
);
2583 ivideo
->vbflags
|= TV_SVIDEO
;
2584 SiS_SetRegOR(SISCR
, 0x32, 0x02);
2585 SiS_SetRegAND(SISCR
, 0x32, ~0x05);
2586 } else if (temp1
== 0x01) {
2587 printk(KERN_INFO
"%s CVBS output\n", stdstr
);
2588 ivideo
->vbflags
|= TV_AVIDEO
;
2589 SiS_SetRegOR(SISCR
, 0x32, 0x01);
2590 SiS_SetRegAND(SISCR
, 0x32, ~0x06);
2592 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x0e, 0x01, 0xF8);
2593 SiS_SetRegAND(SISCR
, 0x32, ~0x07);
2595 } else if(temp1
== 0) {
2596 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x0e, 0x01, 0xF8);
2597 SiS_SetRegAND(SISCR
, 0x32, ~0x07);
2599 /* Set general purpose IO for Chrontel communication */
2600 SiS_SetChrontelGPIO(&ivideo
->SiS_Pr
, 0x00);
2605 #ifdef CONFIG_FB_SIS_315
2606 ivideo
->SiS_Pr
.SiS_IF_DEF_CH70xx
= 2; /* Chrontel 7019 */
2607 temp1
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x49);
2608 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x49, 0x20);
2609 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2610 temp2
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x20);
2612 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x20, temp2
);
2613 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2615 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x20, temp2
);
2616 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2617 temp2
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x20);
2618 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x49, temp1
);
2620 if(temp2
& 0x02) temp1
|= 0x01;
2621 if(temp2
& 0x10) temp1
|= 0x01;
2622 if(temp2
& 0x04) temp1
|= 0x02;
2623 if( (temp1
& 0x01) && (temp1
& 0x02) ) temp1
= 0x04;
2626 printk(KERN_INFO
"%s CVBS output\n", stdstr
);
2627 ivideo
->vbflags
|= TV_AVIDEO
;
2628 SiS_SetRegOR(SISCR
, 0x32, 0x01);
2629 SiS_SetRegAND(SISCR
, 0x32, ~0x06);
2632 printk(KERN_INFO
"%s SVIDEO output\n", stdstr
);
2633 ivideo
->vbflags
|= TV_SVIDEO
;
2634 SiS_SetRegOR(SISCR
, 0x32, 0x02);
2635 SiS_SetRegAND(SISCR
, 0x32, ~0x05);
2638 printk(KERN_INFO
"%s SCART output\n", stdstr
);
2639 SiS_SetRegOR(SISCR
, 0x32, 0x04);
2640 SiS_SetRegAND(SISCR
, 0x32, ~0x03);
2643 SiS_SetRegAND(SISCR
, 0x32, ~0x07);
2649 static void sisfb_get_VB_type(struct sis_video_info
*ivideo
)
2651 char stdstr
[] = "sisfb: Detected";
2652 char bridgestr
[] = "video bridge";
2656 /* No CRT2 on XGI Z7 */
2657 if(ivideo
->chip
== XGI_20
)
2660 vb_chipid
= SiS_GetReg(SISPART4
, 0x00);
2663 reg
= SiS_GetReg(SISPART4
, 0x01);
2665 ivideo
->vbflags
|= VB_301
; /* Deprecated */
2666 ivideo
->vbflags2
|= VB2_301
;
2667 printk(KERN_INFO
"%s SiS301 %s\n", stdstr
, bridgestr
);
2668 } else if(reg
< 0xc0) {
2669 ivideo
->vbflags
|= VB_301B
; /* Deprecated */
2670 ivideo
->vbflags2
|= VB2_301B
;
2671 reg
= SiS_GetReg(SISPART4
, 0x23);
2673 ivideo
->vbflags
|= VB_30xBDH
; /* Deprecated */
2674 ivideo
->vbflags2
|= VB2_30xBDH
;
2675 printk(KERN_INFO
"%s SiS301B-DH %s\n", stdstr
, bridgestr
);
2677 printk(KERN_INFO
"%s SiS301B %s\n", stdstr
, bridgestr
);
2679 } else if(reg
< 0xd0) {
2680 ivideo
->vbflags
|= VB_301C
; /* Deprecated */
2681 ivideo
->vbflags2
|= VB2_301C
;
2682 printk(KERN_INFO
"%s SiS301C %s\n", stdstr
, bridgestr
);
2683 } else if(reg
< 0xe0) {
2684 ivideo
->vbflags
|= VB_301LV
; /* Deprecated */
2685 ivideo
->vbflags2
|= VB2_301LV
;
2686 printk(KERN_INFO
"%s SiS301LV %s\n", stdstr
, bridgestr
);
2687 } else if(reg
<= 0xe1) {
2688 reg
= SiS_GetReg(SISPART4
, 0x39);
2690 ivideo
->vbflags
|= VB_302LV
; /* Deprecated */
2691 ivideo
->vbflags2
|= VB2_302LV
;
2692 printk(KERN_INFO
"%s SiS302LV %s\n", stdstr
, bridgestr
);
2694 ivideo
->vbflags
|= VB_301C
; /* Deprecated */
2695 ivideo
->vbflags2
|= VB2_301C
;
2696 printk(KERN_INFO
"%s SiS301C(P4) %s\n", stdstr
, bridgestr
);
2698 ivideo
->vbflags
|= VB_302ELV
; /* Deprecated */
2699 ivideo
->vbflags2
|= VB2_302ELV
;
2700 printk(KERN_INFO
"%s SiS302ELV %s\n", stdstr
, bridgestr
);
2706 ivideo
->vbflags
|= VB_302B
; /* Deprecated */
2707 ivideo
->vbflags2
|= VB2_302B
;
2708 printk(KERN_INFO
"%s SiS302B %s\n", stdstr
, bridgestr
);
2712 if((!(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
)) && (ivideo
->chip
!= SIS_300
)) {
2713 reg
= SiS_GetReg(SISCR
, 0x37);
2714 reg
&= SIS_EXTERNAL_CHIP_MASK
;
2716 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2717 #ifdef CONFIG_FB_SIS_300
2719 case SIS_EXTERNAL_CHIP_LVDS
:
2720 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2721 ivideo
->vbflags2
|= VB2_LVDS
;
2723 case SIS_EXTERNAL_CHIP_TRUMPION
:
2724 ivideo
->vbflags
|= (VB_LVDS
| VB_TRUMPION
); /* Deprecated */
2725 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_TRUMPION
);
2727 case SIS_EXTERNAL_CHIP_CHRONTEL
:
2728 ivideo
->vbflags
|= VB_CHRONTEL
; /* Deprecated */
2729 ivideo
->vbflags2
|= VB2_CHRONTEL
;
2731 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL
:
2732 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2733 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2736 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 1;
2738 } else if(ivideo
->chip
< SIS_661
) {
2739 #ifdef CONFIG_FB_SIS_315
2741 case SIS310_EXTERNAL_CHIP_LVDS
:
2742 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2743 ivideo
->vbflags2
|= VB2_LVDS
;
2745 case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL
:
2746 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2747 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2750 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 2;
2752 } else if(ivideo
->chip
>= SIS_661
) {
2753 #ifdef CONFIG_FB_SIS_315
2754 reg
= SiS_GetReg(SISCR
, 0x38);
2758 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2759 ivideo
->vbflags2
|= VB2_LVDS
;
2762 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2763 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2766 ivideo
->vbflags
|= (VB_LVDS
| VB_CONEXANT
); /* Deprecated */
2767 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CONEXANT
);
2770 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 2;
2773 if(ivideo
->vbflags2
& VB2_LVDS
) {
2774 printk(KERN_INFO
"%s LVDS transmitter\n", stdstr
);
2776 if((ivideo
->sisvga_engine
== SIS_300_VGA
) && (ivideo
->vbflags2
& VB2_TRUMPION
)) {
2777 printk(KERN_INFO
"%s Trumpion Zurac LCD scaler\n", stdstr
);
2779 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
2780 printk(KERN_INFO
"%s Chrontel TV encoder\n", stdstr
);
2782 if((ivideo
->chip
>= SIS_661
) && (ivideo
->vbflags2
& VB2_CONEXANT
)) {
2783 printk(KERN_INFO
"%s Conexant external device\n", stdstr
);
2787 if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
2788 SiS_SenseLCD(ivideo
);
2789 SiS_Sense30x(ivideo
);
2790 } else if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
2791 SiS_SenseCh(ivideo
);
2795 /* ---------- Engine initialization routines ------------ */
2798 sisfb_engine_init(struct sis_video_info
*ivideo
)
2801 /* Initialize command queue (we use MMIO only) */
2803 /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
2805 ivideo
->caps
&= ~(TURBO_QUEUE_CAP
|
2806 MMIO_CMD_QUEUE_CAP
|
2810 #ifdef CONFIG_FB_SIS_300
2811 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2815 tqueue_pos
= (ivideo
->video_size
- ivideo
->cmdQueueSize
) / (64 * 1024);
2817 tq_state
= SiS_GetReg(SISSR
, IND_SIS_TURBOQUEUE_SET
);
2820 tq_state
|= (u8
)(tqueue_pos
>> 8);
2821 SiS_SetReg(SISSR
, IND_SIS_TURBOQUEUE_SET
, tq_state
);
2823 SiS_SetReg(SISSR
, IND_SIS_TURBOQUEUE_ADR
, (u8
)(tqueue_pos
& 0xff));
2825 ivideo
->caps
|= TURBO_QUEUE_CAP
;
2829 #ifdef CONFIG_FB_SIS_315
2830 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2831 u32 tempq
= 0, templ
;
2834 if(ivideo
->chip
== XGI_20
) {
2835 switch(ivideo
->cmdQueueSize
) {
2837 temp
= SIS_CMD_QUEUE_SIZE_Z7_64k
;
2841 temp
= SIS_CMD_QUEUE_SIZE_Z7_128k
;
2844 switch(ivideo
->cmdQueueSize
) {
2845 case (4 * 1024 * 1024):
2846 temp
= SIS_CMD_QUEUE_SIZE_4M
;
2848 case (2 * 1024 * 1024):
2849 temp
= SIS_CMD_QUEUE_SIZE_2M
;
2851 case (1 * 1024 * 1024):
2852 temp
= SIS_CMD_QUEUE_SIZE_1M
;
2856 temp
= SIS_CMD_QUEUE_SIZE_512k
;
2860 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_THRESHOLD
, COMMAND_QUEUE_THRESHOLD
);
2861 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, SIS_CMD_QUEUE_RESET
);
2863 if((ivideo
->chip
>= XGI_40
) && ivideo
->modechanged
) {
2864 /* Must disable dual pipe on XGI_40. Can't do
2865 * this in MMIO mode, because it requires
2866 * setting/clearing a bit in the MMIO fire trigger
2869 if(!((templ
= MMIO_IN32(ivideo
->mmio_vbase
, 0x8240)) & (1 << 10))) {
2871 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, 0);
2873 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, (temp
| SIS_VRAM_CMDQUEUE_ENABLE
));
2875 tempq
= MMIO_IN32(ivideo
->mmio_vbase
, Q_READ_PTR
);
2876 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, tempq
);
2878 tempq
= (u32
)(ivideo
->video_size
- ivideo
->cmdQueueSize
);
2879 MMIO_OUT32(ivideo
->mmio_vbase
, Q_BASE_ADDR
, tempq
);
2881 writel(0x16800000 + 0x8240, ivideo
->video_vbase
+ tempq
);
2882 writel(templ
| (1 << 10), ivideo
->video_vbase
+ tempq
+ 4);
2883 writel(0x168F0000, ivideo
->video_vbase
+ tempq
+ 8);
2884 writel(0x168F0000, ivideo
->video_vbase
+ tempq
+ 12);
2886 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, (tempq
+ 16));
2888 sisfb_syncaccel(ivideo
);
2890 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, SIS_CMD_QUEUE_RESET
);
2895 tempq
= MMIO_IN32(ivideo
->mmio_vbase
, MMIO_QUEUE_READPORT
);
2896 MMIO_OUT32(ivideo
->mmio_vbase
, MMIO_QUEUE_WRITEPORT
, tempq
);
2898 temp
|= (SIS_MMIO_CMD_ENABLE
| SIS_CMD_AUTO_CORR
);
2899 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, temp
);
2901 tempq
= (u32
)(ivideo
->video_size
- ivideo
->cmdQueueSize
);
2902 MMIO_OUT32(ivideo
->mmio_vbase
, MMIO_QUEUE_PHYBASE
, tempq
);
2904 ivideo
->caps
|= MMIO_CMD_QUEUE_CAP
;
2908 ivideo
->engineok
= 1;
2911 static void sisfb_detect_lcd_type(struct sis_video_info
*ivideo
)
2916 reg
= SiS_GetReg(SISCR
, 0x36);
2918 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2919 ivideo
->CRT2LCDType
= sis300paneltype
[reg
];
2920 } else if(ivideo
->chip
>= SIS_661
) {
2921 ivideo
->CRT2LCDType
= sis661paneltype
[reg
];
2923 ivideo
->CRT2LCDType
= sis310paneltype
[reg
];
2924 if((ivideo
->chip
== SIS_550
) && (sisfb_fstn
)) {
2925 if((ivideo
->CRT2LCDType
!= LCD_320x240_2
) &&
2926 (ivideo
->CRT2LCDType
!= LCD_320x240_3
)) {
2927 ivideo
->CRT2LCDType
= LCD_320x240
;
2932 if(ivideo
->CRT2LCDType
== LCD_UNKNOWN
) {
2933 /* For broken BIOSes: Assume 1024x768, RGB18 */
2934 ivideo
->CRT2LCDType
= LCD_1024x768
;
2935 SiS_SetRegANDOR(SISCR
, 0x36, 0xf0, 0x02);
2936 SiS_SetRegANDOR(SISCR
, 0x37, 0xee, 0x01);
2937 printk(KERN_DEBUG
"sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg
);
2940 for(i
= 0; i
< SIS_LCD_NUMBER
; i
++) {
2941 if(ivideo
->CRT2LCDType
== sis_lcd_data
[i
].lcdtype
) {
2942 ivideo
->lcdxres
= sis_lcd_data
[i
].xres
;
2943 ivideo
->lcdyres
= sis_lcd_data
[i
].yres
;
2944 ivideo
->lcddefmodeidx
= sis_lcd_data
[i
].default_mode_idx
;
2949 #ifdef CONFIG_FB_SIS_300
2950 if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_BARCO1366
) {
2951 ivideo
->lcdxres
= 1360; ivideo
->lcdyres
= 1024;
2952 ivideo
->lcddefmodeidx
= DEFAULT_MODE_1360
;
2953 } else if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_PANEL848
) {
2954 ivideo
->lcdxres
= 848; ivideo
->lcdyres
= 480;
2955 ivideo
->lcddefmodeidx
= DEFAULT_MODE_848
;
2956 } else if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_PANEL856
) {
2957 ivideo
->lcdxres
= 856; ivideo
->lcdyres
= 480;
2958 ivideo
->lcddefmodeidx
= DEFAULT_MODE_856
;
2962 printk(KERN_DEBUG
"sisfb: Detected %dx%d flat panel\n",
2963 ivideo
->lcdxres
, ivideo
->lcdyres
);
2966 static void sisfb_save_pdc_emi(struct sis_video_info
*ivideo
)
2968 #ifdef CONFIG_FB_SIS_300
2969 /* Save the current PanelDelayCompensation if the LCD is currently used */
2970 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2971 if(ivideo
->vbflags2
& (VB2_LVDS
| VB2_30xBDH
)) {
2973 tmp
= SiS_GetReg(SISCR
, 0x30);
2975 /* Currently on LCD? If yes, read current pdc */
2976 ivideo
->detectedpdc
= SiS_GetReg(SISPART1
, 0x13);
2977 ivideo
->detectedpdc
&= 0x3c;
2978 if(ivideo
->SiS_Pr
.PDC
== -1) {
2979 /* Let option override detection */
2980 ivideo
->SiS_Pr
.PDC
= ivideo
->detectedpdc
;
2982 printk(KERN_INFO
"sisfb: Detected LCD PDC 0x%02x\n",
2983 ivideo
->detectedpdc
);
2985 if((ivideo
->SiS_Pr
.PDC
!= -1) &&
2986 (ivideo
->SiS_Pr
.PDC
!= ivideo
->detectedpdc
)) {
2987 printk(KERN_INFO
"sisfb: Using LCD PDC 0x%02x\n",
2988 ivideo
->SiS_Pr
.PDC
);
2994 #ifdef CONFIG_FB_SIS_315
2995 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2997 /* Try to find about LCDA */
2998 if(ivideo
->vbflags2
& VB2_SISLCDABRIDGE
) {
3000 tmp
= SiS_GetReg(SISPART1
, 0x13);
3002 ivideo
->SiS_Pr
.SiS_UseLCDA
= true;
3003 ivideo
->detectedlcda
= 0x03;
3008 if(ivideo
->vbflags2
& VB2_SISLVDSBRIDGE
) {
3010 tmp
= SiS_GetReg(SISCR
, 0x30);
3011 if((tmp
& 0x20) || (ivideo
->detectedlcda
!= 0xff)) {
3012 /* Currently on LCD? If yes, read current pdc */
3014 pdc
= SiS_GetReg(SISPART1
, 0x2D);
3015 ivideo
->detectedpdc
= (pdc
& 0x0f) << 1;
3016 ivideo
->detectedpdca
= (pdc
& 0xf0) >> 3;
3017 pdc
= SiS_GetReg(SISPART1
, 0x35);
3018 ivideo
->detectedpdc
|= ((pdc
>> 7) & 0x01);
3019 pdc
= SiS_GetReg(SISPART1
, 0x20);
3020 ivideo
->detectedpdca
|= ((pdc
>> 6) & 0x01);
3021 if(ivideo
->newrom
) {
3022 /* New ROM invalidates other PDC resp. */
3023 if(ivideo
->detectedlcda
!= 0xff) {
3024 ivideo
->detectedpdc
= 0xff;
3026 ivideo
->detectedpdca
= 0xff;
3029 if(ivideo
->SiS_Pr
.PDC
== -1) {
3030 if(ivideo
->detectedpdc
!= 0xff) {
3031 ivideo
->SiS_Pr
.PDC
= ivideo
->detectedpdc
;
3034 if(ivideo
->SiS_Pr
.PDCA
== -1) {
3035 if(ivideo
->detectedpdca
!= 0xff) {
3036 ivideo
->SiS_Pr
.PDCA
= ivideo
->detectedpdca
;
3039 if(ivideo
->detectedpdc
!= 0xff) {
3041 "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3042 ivideo
->detectedpdc
);
3044 if(ivideo
->detectedpdca
!= 0xff) {
3046 "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3047 ivideo
->detectedpdca
);
3052 if(ivideo
->vbflags2
& VB2_SISEMIBRIDGE
) {
3053 ivideo
->SiS_Pr
.EMI_30
= SiS_GetReg(SISPART4
, 0x30);
3054 ivideo
->SiS_Pr
.EMI_31
= SiS_GetReg(SISPART4
, 0x31);
3055 ivideo
->SiS_Pr
.EMI_32
= SiS_GetReg(SISPART4
, 0x32);
3056 ivideo
->SiS_Pr
.EMI_33
= SiS_GetReg(SISPART4
, 0x33);
3057 ivideo
->SiS_Pr
.HaveEMI
= true;
3058 if((tmp
& 0x20) || (ivideo
->detectedlcda
!= 0xff)) {
3059 ivideo
->SiS_Pr
.HaveEMILCD
= true;
3064 /* Let user override detected PDCs (all bridges) */
3065 if(ivideo
->vbflags2
& VB2_30xBLV
) {
3066 if((ivideo
->SiS_Pr
.PDC
!= -1) &&
3067 (ivideo
->SiS_Pr
.PDC
!= ivideo
->detectedpdc
)) {
3068 printk(KERN_INFO
"sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3069 ivideo
->SiS_Pr
.PDC
);
3071 if((ivideo
->SiS_Pr
.PDCA
!= -1) &&
3072 (ivideo
->SiS_Pr
.PDCA
!= ivideo
->detectedpdca
)) {
3073 printk(KERN_INFO
"sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3074 ivideo
->SiS_Pr
.PDCA
);
3082 /* -------------------- Memory manager routines ---------------------- */
3084 static u32
sisfb_getheapstart(struct sis_video_info
*ivideo
)
3086 u32 ret
= ivideo
->sisfb_parm_mem
* 1024;
3087 u32 maxoffs
= ivideo
->video_size
- ivideo
->hwcursor_size
- ivideo
->cmdQueueSize
;
3090 /* Calculate heap start = end of memory for console
3092 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3093 * C = console, D = heap, H = HWCursor, Q = cmd-queue
3095 * On 76x in UMA+LFB mode, the layout is as follows:
3096 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3097 * where the heap is the entire UMA area, eventually
3098 * into the LFB area if the given mem parameter is
3099 * higher than the size of the UMA memory.
3101 * Basically given by "mem" parameter
3103 * maximum = videosize - cmd_queue - hwcursor
3104 * (results in a heap of size 0)
3105 * default = SiS 300: depends on videosize
3106 * SiS 315/330/340/XGI: 32k below max
3109 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3110 if(ivideo
->video_size
> 0x1000000) {
3112 } else if(ivideo
->video_size
> 0x800000) {
3117 } else if(ivideo
->UMAsize
&& ivideo
->LFBsize
) {
3120 def
= maxoffs
- 0x8000;
3123 /* Use default for secondary card for now (FIXME) */
3124 if((!ret
) || (ret
> maxoffs
) || (ivideo
->cardnumber
!= 0))
3130 static u32
sisfb_getheapsize(struct sis_video_info
*ivideo
)
3132 u32 max
= ivideo
->video_size
- ivideo
->hwcursor_size
- ivideo
->cmdQueueSize
;
3135 if(ivideo
->UMAsize
&& ivideo
->LFBsize
) {
3136 if( (!ivideo
->sisfb_parm_mem
) ||
3137 ((ivideo
->sisfb_parm_mem
* 1024) > max
) ||
3138 ((max
- (ivideo
->sisfb_parm_mem
* 1024)) < ivideo
->UMAsize
) ) {
3139 ret
= ivideo
->UMAsize
;
3140 max
-= ivideo
->UMAsize
;
3142 ret
= max
- (ivideo
->sisfb_parm_mem
* 1024);
3143 max
= ivideo
->sisfb_parm_mem
* 1024;
3145 ivideo
->video_offset
= ret
;
3146 ivideo
->sisfb_mem
= max
;
3148 ret
= max
- ivideo
->heapstart
;
3149 ivideo
->sisfb_mem
= ivideo
->heapstart
;
3155 static int sisfb_heap_init(struct sis_video_info
*ivideo
)
3159 ivideo
->video_offset
= 0;
3160 if(ivideo
->sisfb_parm_mem
) {
3161 if( (ivideo
->sisfb_parm_mem
< (2 * 1024 * 1024)) ||
3162 (ivideo
->sisfb_parm_mem
> ivideo
->video_size
) ) {
3163 ivideo
->sisfb_parm_mem
= 0;
3167 ivideo
->heapstart
= sisfb_getheapstart(ivideo
);
3168 ivideo
->sisfb_heap_size
= sisfb_getheapsize(ivideo
);
3170 ivideo
->sisfb_heap_start
= ivideo
->video_vbase
+ ivideo
->heapstart
;
3171 ivideo
->sisfb_heap_end
= ivideo
->sisfb_heap_start
+ ivideo
->sisfb_heap_size
;
3173 printk(KERN_INFO
"sisfb: Memory heap starting at %dK, size %dK\n",
3174 (int)(ivideo
->heapstart
/ 1024), (int)(ivideo
->sisfb_heap_size
/ 1024));
3176 ivideo
->sisfb_heap
.vinfo
= ivideo
;
3178 ivideo
->sisfb_heap
.poha_chain
= NULL
;
3179 ivideo
->sisfb_heap
.poh_freelist
= NULL
;
3181 poh
= sisfb_poh_new_node(&ivideo
->sisfb_heap
);
3185 poh
->poh_next
= &ivideo
->sisfb_heap
.oh_free
;
3186 poh
->poh_prev
= &ivideo
->sisfb_heap
.oh_free
;
3187 poh
->size
= ivideo
->sisfb_heap_size
;
3188 poh
->offset
= ivideo
->heapstart
;
3190 ivideo
->sisfb_heap
.oh_free
.poh_next
= poh
;
3191 ivideo
->sisfb_heap
.oh_free
.poh_prev
= poh
;
3192 ivideo
->sisfb_heap
.oh_free
.size
= 0;
3193 ivideo
->sisfb_heap
.max_freesize
= poh
->size
;
3195 ivideo
->sisfb_heap
.oh_used
.poh_next
= &ivideo
->sisfb_heap
.oh_used
;
3196 ivideo
->sisfb_heap
.oh_used
.poh_prev
= &ivideo
->sisfb_heap
.oh_used
;
3197 ivideo
->sisfb_heap
.oh_used
.size
= SENTINEL
;
3199 if(ivideo
->cardnumber
== 0) {
3200 /* For the first card, make this heap the "global" one
3201 * for old DRM (which could handle only one card)
3203 sisfb_heap
= &ivideo
->sisfb_heap
;
3209 static struct SIS_OH
*
3210 sisfb_poh_new_node(struct SIS_HEAP
*memheap
)
3212 struct SIS_OHALLOC
*poha
;
3217 if(memheap
->poh_freelist
== NULL
) {
3218 poha
= kmalloc(SIS_OH_ALLOC_SIZE
, GFP_KERNEL
);
3222 poha
->poha_next
= memheap
->poha_chain
;
3223 memheap
->poha_chain
= poha
;
3225 cOhs
= (SIS_OH_ALLOC_SIZE
- sizeof(struct SIS_OHALLOC
)) / sizeof(struct SIS_OH
) + 1;
3227 poh
= &poha
->aoh
[0];
3228 for(i
= cOhs
- 1; i
!= 0; i
--) {
3229 poh
->poh_next
= poh
+ 1;
3233 poh
->poh_next
= NULL
;
3234 memheap
->poh_freelist
= &poha
->aoh
[0];
3237 poh
= memheap
->poh_freelist
;
3238 memheap
->poh_freelist
= poh
->poh_next
;
3243 static struct SIS_OH
*
3244 sisfb_poh_allocate(struct SIS_HEAP
*memheap
, u32 size
)
3246 struct SIS_OH
*pohThis
;
3247 struct SIS_OH
*pohRoot
;
3250 if(size
> memheap
->max_freesize
) {
3251 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3252 (unsigned int) size
/ 1024);
3256 pohThis
= memheap
->oh_free
.poh_next
;
3258 while(pohThis
!= &memheap
->oh_free
) {
3259 if(size
<= pohThis
->size
) {
3263 pohThis
= pohThis
->poh_next
;
3267 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3268 (unsigned int) size
/ 1024);
3272 if(size
== pohThis
->size
) {
3274 sisfb_delete_node(pohThis
);
3276 pohRoot
= sisfb_poh_new_node(memheap
);
3280 pohRoot
->offset
= pohThis
->offset
;
3281 pohRoot
->size
= size
;
3283 pohThis
->offset
+= size
;
3284 pohThis
->size
-= size
;
3287 memheap
->max_freesize
-= size
;
3289 pohThis
= &memheap
->oh_used
;
3290 sisfb_insert_node(pohThis
, pohRoot
);
3296 sisfb_delete_node(struct SIS_OH
*poh
)
3298 poh
->poh_prev
->poh_next
= poh
->poh_next
;
3299 poh
->poh_next
->poh_prev
= poh
->poh_prev
;
3303 sisfb_insert_node(struct SIS_OH
*pohList
, struct SIS_OH
*poh
)
3305 struct SIS_OH
*pohTemp
= pohList
->poh_next
;
3307 pohList
->poh_next
= poh
;
3308 pohTemp
->poh_prev
= poh
;
3310 poh
->poh_prev
= pohList
;
3311 poh
->poh_next
= pohTemp
;
3314 static struct SIS_OH
*
3315 sisfb_poh_free(struct SIS_HEAP
*memheap
, u32 base
)
3317 struct SIS_OH
*pohThis
;
3318 struct SIS_OH
*poh_freed
;
3319 struct SIS_OH
*poh_prev
;
3320 struct SIS_OH
*poh_next
;
3325 poh_freed
= memheap
->oh_used
.poh_next
;
3327 while(poh_freed
!= &memheap
->oh_used
) {
3328 if(poh_freed
->offset
== base
) {
3333 poh_freed
= poh_freed
->poh_next
;
3339 memheap
->max_freesize
+= poh_freed
->size
;
3341 poh_prev
= poh_next
= NULL
;
3342 ulUpper
= poh_freed
->offset
+ poh_freed
->size
;
3343 ulLower
= poh_freed
->offset
;
3345 pohThis
= memheap
->oh_free
.poh_next
;
3347 while(pohThis
!= &memheap
->oh_free
) {
3348 if(pohThis
->offset
== ulUpper
) {
3350 } else if((pohThis
->offset
+ pohThis
->size
) == ulLower
) {
3353 pohThis
= pohThis
->poh_next
;
3356 sisfb_delete_node(poh_freed
);
3358 if(poh_prev
&& poh_next
) {
3359 poh_prev
->size
+= (poh_freed
->size
+ poh_next
->size
);
3360 sisfb_delete_node(poh_next
);
3361 sisfb_free_node(memheap
, poh_freed
);
3362 sisfb_free_node(memheap
, poh_next
);
3367 poh_prev
->size
+= poh_freed
->size
;
3368 sisfb_free_node(memheap
, poh_freed
);
3373 poh_next
->size
+= poh_freed
->size
;
3374 poh_next
->offset
= poh_freed
->offset
;
3375 sisfb_free_node(memheap
, poh_freed
);
3379 sisfb_insert_node(&memheap
->oh_free
, poh_freed
);
3385 sisfb_free_node(struct SIS_HEAP
*memheap
, struct SIS_OH
*poh
)
3390 poh
->poh_next
= memheap
->poh_freelist
;
3391 memheap
->poh_freelist
= poh
;
3395 sis_int_malloc(struct sis_video_info
*ivideo
, struct sis_memreq
*req
)
3397 struct SIS_OH
*poh
= NULL
;
3399 if((ivideo
) && (ivideo
->sisfb_id
== SISFB_ID
) && (!ivideo
->havenoheap
))
3400 poh
= sisfb_poh_allocate(&ivideo
->sisfb_heap
, (u32
)req
->size
);
3403 req
->offset
= req
->size
= 0;
3404 DPRINTK("sisfb: Video RAM allocation failed\n");
3406 req
->offset
= poh
->offset
;
3407 req
->size
= poh
->size
;
3408 DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3409 (poh
->offset
+ ivideo
->video_vbase
));
3414 sis_malloc(struct sis_memreq
*req
)
3416 struct sis_video_info
*ivideo
= sisfb_heap
->vinfo
;
3418 if(&ivideo
->sisfb_heap
== sisfb_heap
)
3419 sis_int_malloc(ivideo
, req
);
3421 req
->offset
= req
->size
= 0;
3425 sis_malloc_new(struct pci_dev
*pdev
, struct sis_memreq
*req
)
3427 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
3429 sis_int_malloc(ivideo
, req
);
3432 /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3435 sis_int_free(struct sis_video_info
*ivideo
, u32 base
)
3439 if((!ivideo
) || (ivideo
->sisfb_id
!= SISFB_ID
) || (ivideo
->havenoheap
))
3442 poh
= sisfb_poh_free(&ivideo
->sisfb_heap
, base
);
3445 DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
3446 (unsigned int) base
);
3453 struct sis_video_info
*ivideo
= sisfb_heap
->vinfo
;
3455 sis_int_free(ivideo
, base
);
3459 sis_free_new(struct pci_dev
*pdev
, u32 base
)
3461 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
3463 sis_int_free(ivideo
, base
);
3466 /* --------------------- SetMode routines ------------------------- */
3469 sisfb_check_engine_and_sync(struct sis_video_info
*ivideo
)
3473 /* Check if MMIO and engines are enabled,
3474 * and sync in case they are. Can't use
3475 * ivideo->accel here, as this might have
3476 * been changed before this is called.
3478 cr30
= SiS_GetReg(SISSR
, IND_SIS_PCI_ADDRESS_SET
);
3479 cr31
= SiS_GetReg(SISSR
, IND_SIS_MODULE_ENABLE
);
3480 /* MMIO and 2D/3D engine enabled? */
3481 if((cr30
& SIS_MEM_MAP_IO_ENABLE
) && (cr31
& 0x42)) {
3482 #ifdef CONFIG_FB_SIS_300
3483 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3484 /* Don't care about TurboQueue. It's
3485 * enough to know that the engines
3488 sisfb_syncaccel(ivideo
);
3491 #ifdef CONFIG_FB_SIS_315
3492 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3493 /* Check that any queue mode is
3494 * enabled, and that the queue
3495 * is not in the state of "reset"
3497 cr30
= SiS_GetReg(SISSR
, 0x26);
3498 if((cr30
& 0xe0) && (!(cr30
& 0x01))) {
3499 sisfb_syncaccel(ivideo
);
3507 sisfb_pre_setmode(struct sis_video_info
*ivideo
)
3509 u8 cr30
= 0, cr31
= 0, cr33
= 0, cr35
= 0, cr38
= 0;
3512 ivideo
->currentvbflags
&= (VB_VIDEOBRIDGE
| VB_DISPTYPE_DISP2
);
3514 SiS_SetReg(SISSR
, 0x05, 0x86);
3516 cr31
= SiS_GetReg(SISCR
, 0x31);
3520 cr33
= ivideo
->rate_idx
& 0x0F;
3522 #ifdef CONFIG_FB_SIS_315
3523 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3524 if(ivideo
->chip
>= SIS_661
) {
3525 cr38
= SiS_GetReg(SISCR
, 0x38);
3526 cr38
&= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
3529 cr38
= SiS_GetReg(SISCR
, tvregnum
);
3530 cr38
&= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
3534 #ifdef CONFIG_FB_SIS_300
3535 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3537 cr38
= SiS_GetReg(SISCR
, tvregnum
);
3541 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
3542 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
3543 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
3545 switch(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
3548 cr38
&= ~0xc0; /* Clear PAL-M / PAL-N bits */
3549 if((ivideo
->vbflags
& TV_YPBPR
) && (ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) {
3550 #ifdef CONFIG_FB_SIS_315
3551 if(ivideo
->chip
>= SIS_661
) {
3553 if(ivideo
->vbflags
& TV_YPBPR525P
) cr35
|= 0x20;
3554 else if(ivideo
->vbflags
& TV_YPBPR750P
) cr35
|= 0x40;
3555 else if(ivideo
->vbflags
& TV_YPBPR1080I
) cr35
|= 0x60;
3556 cr30
|= SIS_SIMULTANEOUS_VIEW_ENABLE
;
3558 ivideo
->currentvbflags
|= (TV_YPBPR
| (ivideo
->vbflags
& TV_YPBPRALL
));
3559 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3560 cr30
|= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE
);
3562 if(ivideo
->vbflags
& TV_YPBPR525P
) cr38
|= 0x10;
3563 else if(ivideo
->vbflags
& TV_YPBPR750P
) cr38
|= 0x20;
3564 else if(ivideo
->vbflags
& TV_YPBPR1080I
) cr38
|= 0x30;
3566 ivideo
->currentvbflags
|= (TV_YPBPR
| (ivideo
->vbflags
& TV_YPBPRALL
));
3569 } else if((ivideo
->vbflags
& TV_HIVISION
) &&
3570 (ivideo
->vbflags2
& VB2_SISHIVISIONBRIDGE
)) {
3571 if(ivideo
->chip
>= SIS_661
) {
3577 cr30
|= SIS_SIMULTANEOUS_VIEW_ENABLE
;
3580 ivideo
->currentvbflags
|= TV_HIVISION
;
3581 } else if(ivideo
->vbflags
& TV_SCART
) {
3582 cr30
= (SIS_VB_OUTPUT_SCART
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3585 ivideo
->currentvbflags
|= TV_SCART
;
3587 if(ivideo
->vbflags
& TV_SVIDEO
) {
3588 cr30
= (SIS_VB_OUTPUT_SVIDEO
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3589 ivideo
->currentvbflags
|= TV_SVIDEO
;
3591 if(ivideo
->vbflags
& TV_AVIDEO
) {
3592 cr30
= (SIS_VB_OUTPUT_COMPOSITE
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3593 ivideo
->currentvbflags
|= TV_AVIDEO
;
3596 cr31
|= SIS_DRIVER_MODE
;
3598 if(ivideo
->vbflags
& (TV_AVIDEO
| TV_SVIDEO
)) {
3599 if(ivideo
->vbflags
& TV_PAL
) {
3600 cr31
|= 0x01; cr35
|= 0x01;
3601 ivideo
->currentvbflags
|= TV_PAL
;
3602 if(ivideo
->vbflags
& TV_PALM
) {
3603 cr38
|= 0x40; cr35
|= 0x04;
3604 ivideo
->currentvbflags
|= TV_PALM
;
3605 } else if(ivideo
->vbflags
& TV_PALN
) {
3606 cr38
|= 0x80; cr35
|= 0x08;
3607 ivideo
->currentvbflags
|= TV_PALN
;
3610 cr31
&= ~0x01; cr35
&= ~0x01;
3611 ivideo
->currentvbflags
|= TV_NTSC
;
3612 if(ivideo
->vbflags
& TV_NTSCJ
) {
3613 cr38
|= 0x40; cr35
|= 0x02;
3614 ivideo
->currentvbflags
|= TV_NTSCJ
;
3621 cr30
= (SIS_VB_OUTPUT_LCD
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3622 cr31
|= SIS_DRIVER_MODE
;
3623 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, ivideo
->sisfb_dstn
);
3624 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, ivideo
->sisfb_fstn
);
3625 ivideo
->curFSTN
= ivideo
->sisfb_fstn
;
3626 ivideo
->curDSTN
= ivideo
->sisfb_dstn
;
3630 cr30
= (SIS_VB_OUTPUT_CRT2
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3631 cr31
|= SIS_DRIVER_MODE
;
3632 if(ivideo
->sisfb_nocrt2rate
) {
3633 cr33
|= (sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
<< 4);
3635 cr33
|= ((ivideo
->rate_idx
& 0x0F) << 4);
3639 default: /* disable CRT2 */
3641 cr31
|= (SIS_DRIVER_MODE
| SIS_VB_OUTPUT_DISABLE
);
3644 SiS_SetReg(SISCR
, 0x30, cr30
);
3645 SiS_SetReg(SISCR
, 0x33, cr33
);
3647 if(ivideo
->chip
>= SIS_661
) {
3648 #ifdef CONFIG_FB_SIS_315
3649 cr31
&= ~0x01; /* Clear PAL flag (now in CR35) */
3650 SiS_SetRegANDOR(SISCR
, 0x35, ~0x10, cr35
); /* Leave overscan bit alone */
3651 cr38
&= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
3652 SiS_SetRegANDOR(SISCR
, 0x38, 0xf8, cr38
);
3654 } else if(ivideo
->chip
!= SIS_300
) {
3655 SiS_SetReg(SISCR
, tvregnum
, cr38
);
3657 SiS_SetReg(SISCR
, 0x31, cr31
);
3659 ivideo
->SiS_Pr
.SiS_UseOEM
= ivideo
->sisfb_useoem
;
3661 sisfb_check_engine_and_sync(ivideo
);
3664 /* Fix SR11 for 661 and later */
3665 #ifdef CONFIG_FB_SIS_315
3667 sisfb_fixup_SR11(struct sis_video_info
*ivideo
)
3671 if(ivideo
->chip
>= SIS_661
) {
3672 tmpreg
= SiS_GetReg(SISSR
, 0x11);
3674 tmpreg
= SiS_GetReg(SISSR
, 0x3e);
3675 tmpreg
= (tmpreg
+ 1) & 0xff;
3676 SiS_SetReg(SISSR
, 0x3e, tmpreg
);
3677 tmpreg
= SiS_GetReg(SISSR
, 0x11);
3680 SiS_SetRegAND(SISSR
, 0x11, 0x0f);
3687 sisfb_set_TVxposoffset(struct sis_video_info
*ivideo
, int val
)
3689 if(val
> 32) val
= 32;
3690 if(val
< -32) val
= -32;
3691 ivideo
->tvxpos
= val
;
3693 if(ivideo
->sisfblocked
) return;
3694 if(!ivideo
->modechanged
) return;
3696 if(ivideo
->currentvbflags
& CRT2_TV
) {
3698 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3700 int x
= ivideo
->tvx
;
3702 switch(ivideo
->chronteltype
) {
3706 SiS_SetReg(SISSR
, 0x05, 0x86);
3707 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0a, (x
& 0xff));
3708 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x08, ((x
& 0x0100) >> 7), 0xFD);
3711 /* Not supported by hardware */
3715 } else if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3717 u8 p2_1f
,p2_20
,p2_2b
,p2_42
,p2_43
;
3718 unsigned short temp
;
3720 p2_1f
= ivideo
->p2_1f
;
3721 p2_20
= ivideo
->p2_20
;
3722 p2_2b
= ivideo
->p2_2b
;
3723 p2_42
= ivideo
->p2_42
;
3724 p2_43
= ivideo
->p2_43
;
3726 temp
= p2_1f
| ((p2_20
& 0xf0) << 4);
3728 p2_1f
= temp
& 0xff;
3729 p2_20
= (temp
& 0xf00) >> 4;
3730 p2_2b
= ((p2_2b
& 0x0f) + (val
* 2)) & 0x0f;
3731 temp
= p2_43
| ((p2_42
& 0xf0) << 4);
3733 p2_43
= temp
& 0xff;
3734 p2_42
= (temp
& 0xf00) >> 4;
3735 SiS_SetReg(SISPART2
, 0x1f, p2_1f
);
3736 SiS_SetRegANDOR(SISPART2
, 0x20, 0x0F, p2_20
);
3737 SiS_SetRegANDOR(SISPART2
, 0x2b, 0xF0, p2_2b
);
3738 SiS_SetRegANDOR(SISPART2
, 0x42, 0x0F, p2_42
);
3739 SiS_SetReg(SISPART2
, 0x43, p2_43
);
3745 sisfb_set_TVyposoffset(struct sis_video_info
*ivideo
, int val
)
3747 if(val
> 32) val
= 32;
3748 if(val
< -32) val
= -32;
3749 ivideo
->tvypos
= val
;
3751 if(ivideo
->sisfblocked
) return;
3752 if(!ivideo
->modechanged
) return;
3754 if(ivideo
->currentvbflags
& CRT2_TV
) {
3756 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3758 int y
= ivideo
->tvy
;
3760 switch(ivideo
->chronteltype
) {
3764 SiS_SetReg(SISSR
, 0x05, 0x86);
3765 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0b, (y
& 0xff));
3766 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x08, ((y
& 0x0100) >> 8), 0xFE);
3769 /* Not supported by hardware */
3773 } else if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3777 p2_01
= ivideo
->p2_01
;
3778 p2_02
= ivideo
->p2_02
;
3782 if(!(ivideo
->currentvbflags
& (TV_HIVISION
| TV_YPBPR
))) {
3783 while((p2_01
<= 0) || (p2_02
<= 0)) {
3788 SiS_SetReg(SISPART2
, 0x01, p2_01
);
3789 SiS_SetReg(SISPART2
, 0x02, p2_02
);
3795 sisfb_post_setmode(struct sis_video_info
*ivideo
)
3797 bool crt1isoff
= false;
3799 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
3802 #ifdef CONFIG_FB_SIS_315
3806 SiS_SetReg(SISSR
, 0x05, 0x86);
3808 #ifdef CONFIG_FB_SIS_315
3809 sisfb_fixup_SR11(ivideo
);
3812 /* Now we actually HAVE changed the display mode */
3813 ivideo
->modechanged
= 1;
3815 /* We can't switch off CRT1 if bridge is in slave mode */
3816 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
3817 if(sisfb_bridgeisslave(ivideo
)) doit
= false;
3819 ivideo
->sisfb_crt1off
= 0;
3821 #ifdef CONFIG_FB_SIS_300
3822 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3823 if((ivideo
->sisfb_crt1off
) && (doit
)) {
3830 SiS_SetRegANDOR(SISCR
, 0x17, 0x7f, reg
);
3833 #ifdef CONFIG_FB_SIS_315
3834 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3835 if((ivideo
->sisfb_crt1off
) && (doit
)) {
3844 SiS_SetRegANDOR(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, ~0x40, reg
);
3845 SiS_SetRegANDOR(SISSR
, 0x1f, 0x3f, reg1
);
3850 ivideo
->currentvbflags
&= ~VB_DISPTYPE_CRT1
;
3851 ivideo
->currentvbflags
|= VB_SINGLE_MODE
;
3853 ivideo
->currentvbflags
|= VB_DISPTYPE_CRT1
;
3854 if(ivideo
->currentvbflags
& VB_DISPTYPE_CRT2
) {
3855 ivideo
->currentvbflags
|= VB_MIRROR_MODE
;
3857 ivideo
->currentvbflags
|= VB_SINGLE_MODE
;
3861 SiS_SetRegAND(SISSR
, IND_SIS_RAMDAC_CONTROL
, ~0x04);
3863 if(ivideo
->currentvbflags
& CRT2_TV
) {
3864 if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3865 ivideo
->p2_1f
= SiS_GetReg(SISPART2
, 0x1f);
3866 ivideo
->p2_20
= SiS_GetReg(SISPART2
, 0x20);
3867 ivideo
->p2_2b
= SiS_GetReg(SISPART2
, 0x2b);
3868 ivideo
->p2_42
= SiS_GetReg(SISPART2
, 0x42);
3869 ivideo
->p2_43
= SiS_GetReg(SISPART2
, 0x43);
3870 ivideo
->p2_01
= SiS_GetReg(SISPART2
, 0x01);
3871 ivideo
->p2_02
= SiS_GetReg(SISPART2
, 0x02);
3872 } else if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3873 if(ivideo
->chronteltype
== 1) {
3874 ivideo
->tvx
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0a);
3875 ivideo
->tvx
|= (((SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x08) & 0x02) >> 1) << 8);
3876 ivideo
->tvy
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0b);
3877 ivideo
->tvy
|= ((SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x08) & 0x01) << 8);
3882 if(ivideo
->tvxpos
) {
3883 sisfb_set_TVxposoffset(ivideo
, ivideo
->tvxpos
);
3885 if(ivideo
->tvypos
) {
3886 sisfb_set_TVyposoffset(ivideo
, ivideo
->tvypos
);
3889 /* Eventually sync engines */
3890 sisfb_check_engine_and_sync(ivideo
);
3892 /* (Re-)Initialize chip engines */
3894 sisfb_engine_init(ivideo
);
3896 ivideo
->engineok
= 0;
3901 sisfb_reset_mode(struct sis_video_info
*ivideo
)
3903 if(sisfb_set_mode(ivideo
, 0))
3906 sisfb_set_pitch(ivideo
);
3907 sisfb_set_base_CRT1(ivideo
, ivideo
->current_base
);
3908 sisfb_set_base_CRT2(ivideo
, ivideo
->current_base
);
3914 sisfb_handle_command(struct sis_video_info
*ivideo
, struct sisfb_cmd
*sisfb_command
)
3918 switch(sisfb_command
->sisfb_cmd
) {
3919 case SISFB_CMD_GETVBFLAGS
:
3920 if(!ivideo
->modechanged
) {
3921 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_EARLY
;
3923 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3924 sisfb_command
->sisfb_result
[1] = ivideo
->currentvbflags
;
3925 sisfb_command
->sisfb_result
[2] = ivideo
->vbflags2
;
3928 case SISFB_CMD_SWITCHCRT1
:
3929 /* arg[0]: 0 = off, 1 = on, 99 = query */
3930 if(!ivideo
->modechanged
) {
3931 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_EARLY
;
3932 } else if(sisfb_command
->sisfb_arg
[0] == 99) {
3934 sisfb_command
->sisfb_result
[1] = ivideo
->sisfb_crt1off
? 0 : 1;
3935 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3936 } else if(ivideo
->sisfblocked
) {
3937 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_LOCKED
;
3938 } else if((!(ivideo
->currentvbflags
& CRT2_ENABLE
)) &&
3939 (sisfb_command
->sisfb_arg
[0] == 0)) {
3940 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_NOCRT2
;
3942 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3943 mycrt1off
= sisfb_command
->sisfb_arg
[0] ? 0 : 1;
3944 if( ((ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
) && mycrt1off
) ||
3945 ((!(ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
)) && !mycrt1off
) ) {
3946 ivideo
->sisfb_crt1off
= mycrt1off
;
3947 if(sisfb_reset_mode(ivideo
)) {
3948 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OTHER
;
3951 sisfb_command
->sisfb_result
[1] = ivideo
->sisfb_crt1off
? 0 : 1;
3956 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_UNKNOWN
;
3957 printk(KERN_ERR
"sisfb: Unknown command 0x%x\n",
3958 sisfb_command
->sisfb_cmd
);
3963 static int __init
sisfb_setup(char *options
)
3967 sisfb_setdefaultparms();
3969 if(!options
|| !(*options
))
3972 while((this_opt
= strsep(&options
, ",")) != NULL
) {
3974 if(!(*this_opt
)) continue;
3976 if(!strncasecmp(this_opt
, "off", 3)) {
3978 } else if(!strncasecmp(this_opt
, "forcecrt2type:", 14)) {
3979 /* Need to check crt2 type first for fstn/dstn */
3980 sisfb_search_crt2type(this_opt
+ 14);
3981 } else if(!strncasecmp(this_opt
, "tvmode:",7)) {
3982 sisfb_search_tvstd(this_opt
+ 7);
3983 } else if(!strncasecmp(this_opt
, "tvstandard:",11)) {
3984 sisfb_search_tvstd(this_opt
+ 11);
3985 } else if(!strncasecmp(this_opt
, "mode:", 5)) {
3986 sisfb_search_mode(this_opt
+ 5, false);
3987 } else if(!strncasecmp(this_opt
, "vesa:", 5)) {
3988 sisfb_search_vesamode(simple_strtoul(this_opt
+ 5, NULL
, 0), false);
3989 } else if(!strncasecmp(this_opt
, "rate:", 5)) {
3990 sisfb_parm_rate
= simple_strtoul(this_opt
+ 5, NULL
, 0);
3991 } else if(!strncasecmp(this_opt
, "forcecrt1:", 10)) {
3992 sisfb_forcecrt1
= (int)simple_strtoul(this_opt
+ 10, NULL
, 0);
3993 } else if(!strncasecmp(this_opt
, "mem:",4)) {
3994 sisfb_parm_mem
= simple_strtoul(this_opt
+ 4, NULL
, 0);
3995 } else if(!strncasecmp(this_opt
, "pdc:", 4)) {
3996 sisfb_pdc
= simple_strtoul(this_opt
+ 4, NULL
, 0);
3997 } else if(!strncasecmp(this_opt
, "pdc1:", 5)) {
3998 sisfb_pdca
= simple_strtoul(this_opt
+ 5, NULL
, 0);
3999 } else if(!strncasecmp(this_opt
, "noaccel", 7)) {
4001 } else if(!strncasecmp(this_opt
, "accel", 5)) {
4003 } else if(!strncasecmp(this_opt
, "noypan", 6)) {
4005 } else if(!strncasecmp(this_opt
, "ypan", 4)) {
4007 } else if(!strncasecmp(this_opt
, "nomax", 5)) {
4009 } else if(!strncasecmp(this_opt
, "max", 3)) {
4011 } else if(!strncasecmp(this_opt
, "userom:", 7)) {
4012 sisfb_userom
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
4013 } else if(!strncasecmp(this_opt
, "useoem:", 7)) {
4014 sisfb_useoem
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
4015 } else if(!strncasecmp(this_opt
, "nocrt2rate", 10)) {
4016 sisfb_nocrt2rate
= 1;
4017 } else if(!strncasecmp(this_opt
, "scalelcd:", 9)) {
4018 unsigned long temp
= 2;
4019 temp
= simple_strtoul(this_opt
+ 9, NULL
, 0);
4020 if((temp
== 0) || (temp
== 1)) {
4021 sisfb_scalelcd
= temp
^ 1;
4023 } else if(!strncasecmp(this_opt
, "tvxposoffset:", 13)) {
4025 temp
= (int)simple_strtol(this_opt
+ 13, NULL
, 0);
4026 if((temp
>= -32) && (temp
<= 32)) {
4027 sisfb_tvxposoffset
= temp
;
4029 } else if(!strncasecmp(this_opt
, "tvyposoffset:", 13)) {
4031 temp
= (int)simple_strtol(this_opt
+ 13, NULL
, 0);
4032 if((temp
>= -32) && (temp
<= 32)) {
4033 sisfb_tvyposoffset
= temp
;
4035 } else if(!strncasecmp(this_opt
, "specialtiming:", 14)) {
4036 sisfb_search_specialtiming(this_opt
+ 14);
4037 } else if(!strncasecmp(this_opt
, "lvdshl:", 7)) {
4039 temp
= simple_strtoul(this_opt
+ 7, NULL
, 0);
4040 if((temp
>= 0) && (temp
<= 3)) {
4041 sisfb_lvdshl
= temp
;
4043 } else if(this_opt
[0] >= '0' && this_opt
[0] <= '9') {
4044 sisfb_search_mode(this_opt
, true);
4045 #if !defined(__i386__) && !defined(__x86_64__)
4046 } else if(!strncasecmp(this_opt
, "resetcard", 9)) {
4047 sisfb_resetcard
= 1;
4048 } else if(!strncasecmp(this_opt
, "videoram:", 9)) {
4049 sisfb_videoram
= simple_strtoul(this_opt
+ 9, NULL
, 0);
4052 printk(KERN_INFO
"sisfb: Invalid option %s\n", this_opt
);
4061 static int sisfb_check_rom(void __iomem
*rom_base
,
4062 struct sis_video_info
*ivideo
)
4067 if((readb(rom_base
) != 0x55) || (readb(rom_base
+ 1) != 0xaa))
4070 romptr
= (readb(rom_base
+ 0x18) | (readb(rom_base
+ 0x19) << 8));
4071 if(romptr
> (0x10000 - 8))
4074 rom
= rom_base
+ romptr
;
4076 if((readb(rom
) != 'P') || (readb(rom
+ 1) != 'C') ||
4077 (readb(rom
+ 2) != 'I') || (readb(rom
+ 3) != 'R'))
4080 if((readb(rom
+ 4) | (readb(rom
+ 5) << 8)) != ivideo
->chip_vendor
)
4083 if((readb(rom
+ 6) | (readb(rom
+ 7) << 8)) != ivideo
->chip_id
)
4089 static unsigned char *sisfb_find_rom(struct pci_dev
*pdev
)
4091 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4092 void __iomem
*rom_base
;
4093 unsigned char *myrombase
= NULL
;
4096 /* First, try the official pci ROM functions (except
4097 * on integrated chipsets which have no ROM).
4100 if(!ivideo
->nbridge
) {
4102 if((rom_base
= pci_map_rom(pdev
, &romsize
))) {
4104 if(sisfb_check_rom(rom_base
, ivideo
)) {
4106 if((myrombase
= vmalloc(65536))) {
4107 memcpy_fromio(myrombase
, rom_base
,
4108 (romsize
> 65536) ? 65536 : romsize
);
4111 pci_unmap_rom(pdev
, rom_base
);
4115 if(myrombase
) return myrombase
;
4117 /* Otherwise do it the conventional way. */
4119 #if defined(__i386__) || defined(__x86_64__)
4123 for (temp
= 0x000c0000; temp
< 0x000f0000; temp
+= 0x00001000) {
4125 rom_base
= ioremap(temp
, 65536);
4129 if (!sisfb_check_rom(rom_base
, ivideo
)) {
4134 if ((myrombase
= vmalloc(65536)))
4135 memcpy_fromio(myrombase
, rom_base
, 65536);
4148 static void sisfb_post_map_vram(struct sis_video_info
*ivideo
,
4149 unsigned int *mapsize
, unsigned int min
)
4151 if (*mapsize
< (min
<< 20))
4154 ivideo
->video_vbase
= ioremap_wc(ivideo
->video_base
, (*mapsize
));
4156 if(!ivideo
->video_vbase
) {
4158 "sisfb: Unable to map maximum video RAM for size detection\n");
4160 while((!(ivideo
->video_vbase
= ioremap_wc(ivideo
->video_base
, (*mapsize
))))) {
4162 if((*mapsize
) < (min
<< 20))
4165 if(ivideo
->video_vbase
) {
4167 "sisfb: Video RAM size detection limited to %dMB\n",
4168 (int)((*mapsize
) >> 20));
4173 #ifdef CONFIG_FB_SIS_300
4174 static int sisfb_post_300_buswidth(struct sis_video_info
*ivideo
)
4176 void __iomem
*FBAddress
= ivideo
->video_vbase
;
4177 unsigned short temp
;
4181 SiS_SetRegAND(SISSR
, 0x15, 0xFB);
4182 SiS_SetRegOR(SISSR
, 0x15, 0x04);
4183 SiS_SetReg(SISSR
, 0x13, 0x00);
4184 SiS_SetReg(SISSR
, 0x14, 0xBF);
4186 for(i
= 0; i
< 2; i
++) {
4188 for(j
= 0; j
< 4; j
++) {
4189 writew(temp
, FBAddress
);
4190 if(readw(FBAddress
) == temp
)
4192 SiS_SetRegOR(SISSR
, 0x3c, 0x01);
4193 reg
= SiS_GetReg(SISSR
, 0x05);
4194 reg
= SiS_GetReg(SISSR
, 0x05);
4195 SiS_SetRegAND(SISSR
, 0x3c, 0xfe);
4196 reg
= SiS_GetReg(SISSR
, 0x05);
4197 reg
= SiS_GetReg(SISSR
, 0x05);
4202 writel(0x01234567L
, FBAddress
);
4203 writel(0x456789ABL
, (FBAddress
+ 4));
4204 writel(0x89ABCDEFL
, (FBAddress
+ 8));
4205 writel(0xCDEF0123L
, (FBAddress
+ 12));
4207 reg
= SiS_GetReg(SISSR
, 0x3b);
4209 if(readl((FBAddress
+ 12)) == 0xCDEF0123L
)
4210 return 4; /* Channel A 128bit */
4213 if(readl((FBAddress
+ 4)) == 0x456789ABL
)
4214 return 2; /* Channel B 64bit */
4216 return 1; /* 32bit */
4219 static const unsigned short SiS_DRAMType
[17][5] = {
4220 {0x0C,0x0A,0x02,0x40,0x39},
4221 {0x0D,0x0A,0x01,0x40,0x48},
4222 {0x0C,0x09,0x02,0x20,0x35},
4223 {0x0D,0x09,0x01,0x20,0x44},
4224 {0x0C,0x08,0x02,0x10,0x31},
4225 {0x0D,0x08,0x01,0x10,0x40},
4226 {0x0C,0x0A,0x01,0x20,0x34},
4227 {0x0C,0x09,0x01,0x08,0x32},
4228 {0x0B,0x08,0x02,0x08,0x21},
4229 {0x0C,0x08,0x01,0x08,0x30},
4230 {0x0A,0x08,0x02,0x04,0x11},
4231 {0x0B,0x0A,0x01,0x10,0x28},
4232 {0x09,0x08,0x02,0x02,0x01},
4233 {0x0B,0x09,0x01,0x08,0x24},
4234 {0x0B,0x08,0x01,0x04,0x20},
4235 {0x0A,0x08,0x01,0x02,0x10},
4236 {0x09,0x08,0x01,0x01,0x00}
4239 static int sisfb_post_300_rwtest(struct sis_video_info
*ivideo
, int iteration
,
4240 int buswidth
, int PseudoRankCapacity
,
4241 int PseudoAdrPinCount
, unsigned int mapsize
)
4243 void __iomem
*FBAddr
= ivideo
->video_vbase
;
4244 unsigned short sr14
;
4245 unsigned int k
, RankCapacity
, PageCapacity
, BankNumHigh
, BankNumMid
;
4246 unsigned int PhysicalAdrOtherPage
, PhysicalAdrHigh
, PhysicalAdrHalfPage
;
4248 for (k
= 0; k
< ARRAY_SIZE(SiS_DRAMType
); k
++) {
4249 RankCapacity
= buswidth
* SiS_DRAMType
[k
][3];
4251 if (RankCapacity
!= PseudoRankCapacity
)
4254 if ((SiS_DRAMType
[k
][2] + SiS_DRAMType
[k
][0]) > PseudoAdrPinCount
)
4257 BankNumHigh
= RankCapacity
* 16 * iteration
- 1;
4258 if (iteration
== 3) { /* Rank No */
4259 BankNumMid
= RankCapacity
* 16 - 1;
4261 BankNumMid
= RankCapacity
* 16 * iteration
/ 2 - 1;
4264 PageCapacity
= (1 << SiS_DRAMType
[k
][1]) * buswidth
* 4;
4265 PhysicalAdrHigh
= BankNumHigh
;
4266 PhysicalAdrHalfPage
= (PageCapacity
/ 2 + PhysicalAdrHigh
) % PageCapacity
;
4267 PhysicalAdrOtherPage
= PageCapacity
* SiS_DRAMType
[k
][2] + PhysicalAdrHigh
;
4269 SiS_SetRegAND(SISSR
, 0x15, 0xFB); /* Test */
4270 SiS_SetRegOR(SISSR
, 0x15, 0x04); /* Test */
4271 sr14
= (SiS_DRAMType
[k
][3] * buswidth
) - 1;
4275 else if (buswidth
== 2)
4278 SiS_SetReg(SISSR
, 0x13, SiS_DRAMType
[k
][4]);
4279 SiS_SetReg(SISSR
, 0x14, sr14
);
4284 if ((BankNumHigh
+ PhysicalAdrHigh
>= mapsize
) ||
4285 (BankNumMid
+ PhysicalAdrHigh
>= mapsize
) ||
4286 (BankNumHigh
+ PhysicalAdrHalfPage
>= mapsize
) ||
4287 (BankNumHigh
+ PhysicalAdrOtherPage
>= mapsize
))
4291 writew(((unsigned short)PhysicalAdrHigh
),
4292 (FBAddr
+ BankNumHigh
+ PhysicalAdrHigh
));
4293 writew(((unsigned short)BankNumMid
),
4294 (FBAddr
+ BankNumMid
+ PhysicalAdrHigh
));
4295 writew(((unsigned short)PhysicalAdrHalfPage
),
4296 (FBAddr
+ BankNumHigh
+ PhysicalAdrHalfPage
));
4297 writew(((unsigned short)PhysicalAdrOtherPage
),
4298 (FBAddr
+ BankNumHigh
+ PhysicalAdrOtherPage
));
4301 if (readw(FBAddr
+ BankNumHigh
+ PhysicalAdrHigh
) == PhysicalAdrHigh
)
4308 static void sisfb_post_300_ramsize(struct pci_dev
*pdev
, unsigned int mapsize
)
4310 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4312 int PseudoRankCapacity
, PseudoAdrPinCount
;
4314 buswidth
= sisfb_post_300_buswidth(ivideo
);
4316 for(i
= 6; i
>= 0; i
--) {
4317 PseudoRankCapacity
= 1 << i
;
4318 for(j
= 4; j
>= 1; j
--) {
4319 PseudoAdrPinCount
= 15 - j
;
4320 if((PseudoRankCapacity
* j
) <= 64) {
4321 if(sisfb_post_300_rwtest(ivideo
,
4333 static void sisfb_post_sis300(struct pci_dev
*pdev
)
4335 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4336 unsigned char *bios
= ivideo
->SiS_Pr
.VirtualRomBase
;
4337 u8 reg
, v1
, v2
, v3
, v4
, v5
, v6
, v7
, v8
;
4338 u16 index
, rindex
, memtype
= 0;
4339 unsigned int mapsize
;
4341 if(!ivideo
->SiS_Pr
.UseROM
)
4344 SiS_SetReg(SISSR
, 0x05, 0x86);
4347 if(bios
[0x52] & 0x80) {
4348 memtype
= bios
[0x52];
4350 memtype
= SiS_GetReg(SISSR
, 0x3a);
4355 v3
= 0x80; v6
= 0x80;
4356 if(ivideo
->revision_id
<= 0x13) {
4357 v1
= 0x44; v2
= 0x42;
4358 v4
= 0x44; v5
= 0x42;
4360 v1
= 0x68; v2
= 0x43; /* Assume 125Mhz MCLK */
4361 v4
= 0x68; v5
= 0x43; /* Assume 125Mhz ECLK */
4363 index
= memtype
* 5;
4364 rindex
= index
+ 0x54;
4365 v1
= bios
[rindex
++];
4366 v2
= bios
[rindex
++];
4367 v3
= bios
[rindex
++];
4368 rindex
= index
+ 0x7c;
4369 v4
= bios
[rindex
++];
4370 v5
= bios
[rindex
++];
4371 v6
= bios
[rindex
++];
4374 SiS_SetReg(SISSR
, 0x28, v1
);
4375 SiS_SetReg(SISSR
, 0x29, v2
);
4376 SiS_SetReg(SISSR
, 0x2a, v3
);
4377 SiS_SetReg(SISSR
, 0x2e, v4
);
4378 SiS_SetReg(SISSR
, 0x2f, v5
);
4379 SiS_SetReg(SISSR
, 0x30, v6
);
4384 SiS_SetReg(SISSR
, 0x07, v1
); /* DAC speed */
4386 SiS_SetReg(SISSR
, 0x11, 0x0f); /* DDC, power save */
4388 v1
= 0x01; v2
= 0x43; v3
= 0x1e; v4
= 0x2a;
4389 v5
= 0x06; v6
= 0x00; v7
= 0x00; v8
= 0x00;
4393 v2
= bios
[memtype
+ 8];
4394 v3
= bios
[memtype
+ 16];
4395 v4
= bios
[memtype
+ 24];
4396 v5
= bios
[memtype
+ 32];
4397 v6
= bios
[memtype
+ 40];
4398 v7
= bios
[memtype
+ 48];
4399 v8
= bios
[memtype
+ 56];
4401 if(ivideo
->revision_id
>= 0x80)
4403 SiS_SetReg(SISSR
, 0x15, v1
); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4404 SiS_SetReg(SISSR
, 0x16, v2
);
4405 SiS_SetReg(SISSR
, 0x17, v3
);
4406 SiS_SetReg(SISSR
, 0x18, v4
);
4407 SiS_SetReg(SISSR
, 0x19, v5
);
4408 SiS_SetReg(SISSR
, 0x1a, v6
);
4409 SiS_SetReg(SISSR
, 0x1b, v7
);
4410 SiS_SetReg(SISSR
, 0x1c, v8
); /* ---- */
4411 SiS_SetRegAND(SISSR
, 0x15, 0xfb);
4412 SiS_SetRegOR(SISSR
, 0x15, 0x04);
4414 if(bios
[0x53] & 0x02) {
4415 SiS_SetRegOR(SISSR
, 0x19, 0x20);
4418 v1
= 0x04; /* DAC pedestal (BIOS 0xe5) */
4419 if(ivideo
->revision_id
>= 0x80)
4421 SiS_SetReg(SISSR
, 0x1f, v1
);
4422 SiS_SetReg(SISSR
, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
4423 v1
= 0xf6; v2
= 0x0d; v3
= 0x00;
4429 SiS_SetReg(SISSR
, 0x23, v1
);
4430 SiS_SetReg(SISSR
, 0x24, v2
);
4431 SiS_SetReg(SISSR
, 0x25, v3
);
4432 SiS_SetReg(SISSR
, 0x21, 0x84);
4433 SiS_SetReg(SISSR
, 0x22, 0x00);
4434 SiS_SetReg(SISCR
, 0x37, 0x00);
4435 SiS_SetRegOR(SISPART1
, 0x24, 0x01); /* unlock crt2 */
4436 SiS_SetReg(SISPART1
, 0x00, 0x00);
4437 v1
= 0x40; v2
= 0x11;
4442 SiS_SetReg(SISPART1
, 0x02, v1
);
4444 if(ivideo
->revision_id
>= 0x80)
4447 reg
= SiS_GetReg(SISPART4
, 0x00);
4448 if((reg
== 1) || (reg
== 2)) {
4449 SiS_SetReg(SISCR
, 0x37, 0x02);
4450 SiS_SetReg(SISPART2
, 0x00, 0x1c);
4451 v4
= 0x00; v5
= 0x00; v6
= 0x10;
4452 if (ivideo
->SiS_Pr
.UseROM
&& bios
) {
4457 SiS_SetReg(SISPART4
, 0x0d, v4
);
4458 SiS_SetReg(SISPART4
, 0x0e, v5
);
4459 SiS_SetReg(SISPART4
, 0x10, v6
);
4460 SiS_SetReg(SISPART4
, 0x0f, 0x3f);
4461 reg
= SiS_GetReg(SISPART4
, 0x01);
4463 reg
= SiS_GetReg(SISPART4
, 0x23);
4466 SiS_SetReg(SISPART4
, 0x23, reg
);
4471 SiS_SetReg(SISSR
, 0x32, v2
);
4473 SiS_SetRegAND(SISPART1
, 0x24, 0xfe); /* Lock CRT2 */
4475 reg
= SiS_GetReg(SISSR
, 0x16);
4477 SiS_SetReg(SISCR
, 0x35, reg
);
4478 SiS_SetReg(SISCR
, 0x83, 0x00);
4479 #if !defined(__i386__) && !defined(__x86_64__)
4480 if(sisfb_videoram
) {
4481 SiS_SetReg(SISSR
, 0x13, 0x28); /* ? */
4482 reg
= ((sisfb_videoram
>> 10) - 1) | 0x40;
4483 SiS_SetReg(SISSR
, 0x14, reg
);
4486 /* Need to map max FB size for finding out about RAM size */
4487 mapsize
= ivideo
->video_size
;
4488 sisfb_post_map_vram(ivideo
, &mapsize
, 4);
4490 if(ivideo
->video_vbase
) {
4491 sisfb_post_300_ramsize(pdev
, mapsize
);
4492 iounmap(ivideo
->video_vbase
);
4495 "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4496 SiS_SetReg(SISSR
, 0x13, 0x28); /* ? */
4497 SiS_SetReg(SISSR
, 0x14, 0x47); /* 8MB, 64bit default */
4499 #if !defined(__i386__) && !defined(__x86_64__)
4506 reg
= SiS_GetReg(SISSR
, 0x3a);
4507 if((reg
& 0x30) == 0x30) {
4508 v1
= 0x04; /* PCI */
4511 v1
= 0x14; /* AGP */
4515 SiS_SetReg(SISSR
, 0x21, v1
);
4516 SiS_SetReg(SISSR
, 0x22, v2
);
4519 sisfb_sense_crt1(ivideo
);
4521 /* Set default mode, don't clear screen */
4522 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
4523 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
4524 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
4525 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
4526 ivideo
->SiS_Pr
.VideoMemorySize
= 8 << 20;
4527 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
4529 SiS_SetReg(SISSR
, 0x05, 0x86);
4532 SiS_SetRegOR(SISSR
, 0x01, 0x20);
4534 /* Save mode number in CR34 */
4535 SiS_SetReg(SISCR
, 0x34, 0x2e);
4537 /* Let everyone know what the current mode is */
4538 ivideo
->modeprechange
= 0x2e;
4542 #ifdef CONFIG_FB_SIS_315
4544 static void sisfb_post_sis315330(struct pci_dev
*pdev
)
4550 static inline int sisfb_xgi_is21(struct sis_video_info
*ivideo
)
4552 return ivideo
->chip_real_id
== XGI_21
;
4555 static void sisfb_post_xgi_delay(struct sis_video_info
*ivideo
, int delay
)
4560 for(i
= 0; i
<= (delay
* 10 * 36); i
++) {
4561 reg
= SiS_GetReg(SISSR
, 0x05);
4566 static int sisfb_find_host_bridge(struct sis_video_info
*ivideo
,
4567 struct pci_dev
*mypdev
,
4568 unsigned short pcivendor
)
4570 struct pci_dev
*pdev
= NULL
;
4571 unsigned short temp
;
4574 while((pdev
= pci_get_class(PCI_CLASS_BRIDGE_HOST
, pdev
))) {
4575 temp
= pdev
->vendor
;
4576 if(temp
== pcivendor
) {
4586 static int sisfb_post_xgi_rwtest(struct sis_video_info
*ivideo
, int starta
,
4587 unsigned int enda
, unsigned int mapsize
)
4592 writel(0, ivideo
->video_vbase
);
4594 for(i
= starta
; i
<= enda
; i
++) {
4597 writel(pos
, ivideo
->video_vbase
+ pos
);
4600 sisfb_post_xgi_delay(ivideo
, 150);
4602 if(readl(ivideo
->video_vbase
) != 0)
4605 for(i
= starta
; i
<= enda
; i
++) {
4608 if(readl(ivideo
->video_vbase
+ pos
) != pos
)
4617 static int sisfb_post_xgi_ramsize(struct sis_video_info
*ivideo
)
4619 unsigned int buswidth
, ranksize
, channelab
, mapsize
;
4620 int i
, j
, k
, l
, status
;
4622 static const u8 dramsr13
[12 * 5] = {
4623 0x02, 0x0e, 0x0b, 0x80, 0x5d,
4624 0x02, 0x0e, 0x0a, 0x40, 0x59,
4625 0x02, 0x0d, 0x0b, 0x40, 0x4d,
4626 0x02, 0x0e, 0x09, 0x20, 0x55,
4627 0x02, 0x0d, 0x0a, 0x20, 0x49,
4628 0x02, 0x0c, 0x0b, 0x20, 0x3d,
4629 0x02, 0x0e, 0x08, 0x10, 0x51,
4630 0x02, 0x0d, 0x09, 0x10, 0x45,
4631 0x02, 0x0c, 0x0a, 0x10, 0x39,
4632 0x02, 0x0d, 0x08, 0x08, 0x41,
4633 0x02, 0x0c, 0x09, 0x08, 0x35,
4634 0x02, 0x0c, 0x08, 0x04, 0x31
4636 static const u8 dramsr13_4
[4 * 5] = {
4637 0x02, 0x0d, 0x09, 0x40, 0x45,
4638 0x02, 0x0c, 0x09, 0x20, 0x35,
4639 0x02, 0x0c, 0x08, 0x10, 0x31,
4640 0x02, 0x0b, 0x08, 0x08, 0x21
4643 /* Enable linear mode, disable 0xa0000 address decoding */
4644 /* We disable a0000 address decoding, because
4645 * - if running on x86, if the card is disabled, it means
4646 * that another card is in the system. We don't want
4647 * to interphere with that primary card's textmode.
4648 * - if running on non-x86, there usually is no VGA window
4651 SiS_SetRegOR(SISSR
, 0x20, (0x80 | 0x04));
4653 /* Need to map max FB size for finding out about RAM size */
4654 mapsize
= ivideo
->video_size
;
4655 sisfb_post_map_vram(ivideo
, &mapsize
, 32);
4657 if(!ivideo
->video_vbase
) {
4658 printk(KERN_ERR
"sisfb: Unable to detect RAM size. Setting default.\n");
4659 SiS_SetReg(SISSR
, 0x13, 0x35);
4660 SiS_SetReg(SISSR
, 0x14, 0x41);
4665 /* Non-interleaving */
4666 SiS_SetReg(SISSR
, 0x15, 0x00);
4668 SiS_SetReg(SISSR
, 0x1c, 0x00);
4670 if(ivideo
->chip
== XGI_20
) {
4673 reg
= SiS_GetReg(SISCR
, 0x97);
4674 if(!(reg
& 0x01)) { /* Single 32/16 */
4676 SiS_SetReg(SISSR
, 0x13, 0xb1);
4677 SiS_SetReg(SISSR
, 0x14, 0x52);
4678 sisfb_post_xgi_delay(ivideo
, 1);
4680 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4683 SiS_SetReg(SISSR
, 0x13, 0x31);
4684 SiS_SetReg(SISSR
, 0x14, 0x42);
4685 sisfb_post_xgi_delay(ivideo
, 1);
4686 if(sisfb_post_xgi_rwtest(ivideo
, 23, 23, mapsize
))
4690 SiS_SetReg(SISSR
, 0x13, 0xb1);
4691 SiS_SetReg(SISSR
, 0x14, 0x41);
4692 sisfb_post_xgi_delay(ivideo
, 1);
4694 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4697 SiS_SetReg(SISSR
, 0x13, 0x31);
4698 } else { /* Dual 16/8 */
4700 SiS_SetReg(SISSR
, 0x13, 0xb1);
4701 SiS_SetReg(SISSR
, 0x14, 0x41);
4702 sisfb_post_xgi_delay(ivideo
, 1);
4704 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4707 SiS_SetReg(SISSR
, 0x13, 0x31);
4708 SiS_SetReg(SISSR
, 0x14, 0x31);
4709 sisfb_post_xgi_delay(ivideo
, 1);
4710 if(sisfb_post_xgi_rwtest(ivideo
, 22, 22, mapsize
))
4714 SiS_SetReg(SISSR
, 0x13, 0xb1);
4715 SiS_SetReg(SISSR
, 0x14, 0x30);
4716 sisfb_post_xgi_delay(ivideo
, 1);
4718 if(sisfb_post_xgi_rwtest(ivideo
, 21, 22, mapsize
))
4721 SiS_SetReg(SISSR
, 0x13, 0x31);
4724 } else { /* XGI_40 */
4726 reg
= SiS_GetReg(SISCR
, 0x97);
4728 reg
= SiS_GetReg(SISSR
, 0x39);
4732 if(reg
& 0x01) { /* DDRII */
4734 if(ivideo
->revision_id
== 2) {
4736 SiS_SetReg(SISSR
, 0x13, 0xa1);
4737 SiS_SetReg(SISSR
, 0x14, 0x44);
4739 sisfb_post_xgi_delay(ivideo
, 1);
4740 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4743 SiS_SetReg(SISSR
, 0x13, 0x21);
4744 SiS_SetReg(SISSR
, 0x14, 0x34);
4745 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4749 SiS_SetReg(SISSR
, 0x13, 0xa1);
4750 SiS_SetReg(SISSR
, 0x14, 0x40);
4752 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4755 SiS_SetReg(SISSR
, 0x13, 0x21);
4756 SiS_SetReg(SISSR
, 0x14, 0x30);
4759 SiS_SetReg(SISSR
, 0x13, 0xa1);
4760 SiS_SetReg(SISSR
, 0x14, 0x4c);
4762 sisfb_post_xgi_delay(ivideo
, 1);
4763 if(sisfb_post_xgi_rwtest(ivideo
, 23, 25, mapsize
))
4767 SiS_SetReg(SISSR
, 0x14, 0x48);
4768 sisfb_post_xgi_delay(ivideo
, 1);
4770 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4773 SiS_SetReg(SISSR
, 0x13, 0x21);
4774 SiS_SetReg(SISSR
, 0x14, 0x3c);
4777 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
)) {
4781 SiS_SetReg(SISSR
, 0x14, 0x38);
4785 sisfb_post_xgi_delay(ivideo
, 1);
4790 if(ivideo
->revision_id
== 2) {
4792 SiS_SetReg(SISSR
, 0x13, 0xa1);
4793 SiS_SetReg(SISSR
, 0x14, 0x52);
4794 sisfb_post_xgi_delay(ivideo
, 1);
4796 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4799 SiS_SetReg(SISSR
, 0x13, 0x21);
4800 SiS_SetReg(SISSR
, 0x14, 0x42);
4803 SiS_SetReg(SISSR
, 0x13, 0xa1);
4804 SiS_SetReg(SISSR
, 0x14, 0x5a);
4805 sisfb_post_xgi_delay(ivideo
, 1);
4807 if(sisfb_post_xgi_rwtest(ivideo
, 24, 25, mapsize
))
4810 SiS_SetReg(SISSR
, 0x13, 0x21);
4811 SiS_SetReg(SISSR
, 0x14, 0x4a);
4813 sisfb_post_xgi_delay(ivideo
, 1);
4819 SiS_SetRegANDOR(SISSR
, 0x14, 0xf0, sr14
);
4820 sisfb_post_xgi_delay(ivideo
, 1);
4822 j
= (ivideo
->chip
== XGI_20
) ? 5 : 9;
4823 k
= (ivideo
->chip
== XGI_20
) ? 12 : 4;
4826 for(i
= 0; i
< k
; i
++) {
4828 reg
= (ivideo
->chip
== XGI_20
) ?
4829 dramsr13
[(i
* 5) + 4] : dramsr13_4
[(i
* 5) + 4];
4830 SiS_SetRegANDOR(SISSR
, 0x13, 0x80, reg
);
4831 sisfb_post_xgi_delay(ivideo
, 50);
4833 ranksize
= (ivideo
->chip
== XGI_20
) ?
4834 dramsr13
[(i
* 5) + 3] : dramsr13_4
[(i
* 5) + 3];
4836 reg
= SiS_GetReg(SISSR
, 0x13);
4837 if(reg
& 0x80) ranksize
<<= 1;
4839 if(ivideo
->chip
== XGI_20
) {
4840 if(buswidth
== 16) ranksize
<<= 1;
4841 else if(buswidth
== 32) ranksize
<<= 2;
4843 if(buswidth
== 64) ranksize
<<= 1;
4849 if((ranksize
* l
) <= 256) {
4850 while((ranksize
>>= 1)) reg
+= 0x10;
4855 SiS_SetRegANDOR(SISSR
, 0x14, 0x0f, (reg
& 0xf0));
4856 sisfb_post_xgi_delay(ivideo
, 1);
4858 if (sisfb_post_xgi_rwtest(ivideo
, j
, ((reg
>> 4) + channelab
- 2 + 20), mapsize
)) {
4864 iounmap(ivideo
->video_vbase
);
4869 static void sisfb_post_xgi_setclocks(struct sis_video_info
*ivideo
, u8 regb
)
4873 static const u8 cs90
[8 * 3] = {
4883 static const u8 csb8
[8 * 3] = {
4897 v1
= cs90
[index
]; v2
= cs90
[index
+ 1]; v3
= cs90
[index
+ 2];
4898 if(ivideo
->haveXGIROM
) {
4899 v1
= ivideo
->bios_abase
[0x90 + index
];
4900 v2
= ivideo
->bios_abase
[0x90 + index
+ 1];
4901 v3
= ivideo
->bios_abase
[0x90 + index
+ 2];
4903 SiS_SetReg(SISSR
, 0x28, v1
);
4904 SiS_SetReg(SISSR
, 0x29, v2
);
4905 SiS_SetReg(SISSR
, 0x2a, v3
);
4906 sisfb_post_xgi_delay(ivideo
, 0x43);
4907 sisfb_post_xgi_delay(ivideo
, 0x43);
4908 sisfb_post_xgi_delay(ivideo
, 0x43);
4910 v1
= csb8
[index
]; v2
= csb8
[index
+ 1]; v3
= csb8
[index
+ 2];
4911 if(ivideo
->haveXGIROM
) {
4912 v1
= ivideo
->bios_abase
[0xb8 + index
];
4913 v2
= ivideo
->bios_abase
[0xb8 + index
+ 1];
4914 v3
= ivideo
->bios_abase
[0xb8 + index
+ 2];
4916 SiS_SetReg(SISSR
, 0x2e, v1
);
4917 SiS_SetReg(SISSR
, 0x2f, v2
);
4918 SiS_SetReg(SISSR
, 0x30, v3
);
4919 sisfb_post_xgi_delay(ivideo
, 0x43);
4920 sisfb_post_xgi_delay(ivideo
, 0x43);
4921 sisfb_post_xgi_delay(ivideo
, 0x43);
4924 static void sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info
*ivideo
,
4927 unsigned char *bios
= ivideo
->bios_abase
;
4930 SiS_SetReg(SISSR
, 0x28, 0x64);
4931 SiS_SetReg(SISSR
, 0x29, 0x63);
4932 sisfb_post_xgi_delay(ivideo
, 15);
4933 SiS_SetReg(SISSR
, 0x18, 0x00);
4934 SiS_SetReg(SISSR
, 0x19, 0x20);
4935 SiS_SetReg(SISSR
, 0x16, 0x00);
4936 SiS_SetReg(SISSR
, 0x16, 0x80);
4937 SiS_SetReg(SISSR
, 0x18, 0xc5);
4938 SiS_SetReg(SISSR
, 0x19, 0x23);
4939 SiS_SetReg(SISSR
, 0x16, 0x00);
4940 SiS_SetReg(SISSR
, 0x16, 0x80);
4941 sisfb_post_xgi_delay(ivideo
, 1);
4942 SiS_SetReg(SISCR
, 0x97, 0x11);
4943 sisfb_post_xgi_setclocks(ivideo
, regb
);
4944 sisfb_post_xgi_delay(ivideo
, 0x46);
4945 SiS_SetReg(SISSR
, 0x18, 0xc5);
4946 SiS_SetReg(SISSR
, 0x19, 0x23);
4947 SiS_SetReg(SISSR
, 0x16, 0x00);
4948 SiS_SetReg(SISSR
, 0x16, 0x80);
4949 sisfb_post_xgi_delay(ivideo
, 1);
4950 SiS_SetReg(SISSR
, 0x1b, 0x04);
4951 sisfb_post_xgi_delay(ivideo
, 1);
4952 SiS_SetReg(SISSR
, 0x1b, 0x00);
4953 sisfb_post_xgi_delay(ivideo
, 1);
4955 if (ivideo
->haveXGIROM
) {
4958 SiS_SetReg(SISSR
, 0x18, v1
);
4959 SiS_SetReg(SISSR
, 0x19, 0x06);
4960 SiS_SetReg(SISSR
, 0x16, 0x04);
4961 SiS_SetReg(SISSR
, 0x16, 0x84);
4962 sisfb_post_xgi_delay(ivideo
, 1);
4965 static void sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info
*ivideo
)
4967 sisfb_post_xgi_setclocks(ivideo
, 1);
4969 SiS_SetReg(SISCR
, 0x97, 0x11);
4970 sisfb_post_xgi_delay(ivideo
, 0x46);
4972 SiS_SetReg(SISSR
, 0x18, 0x00); /* EMRS2 */
4973 SiS_SetReg(SISSR
, 0x19, 0x80);
4974 SiS_SetReg(SISSR
, 0x16, 0x05);
4975 SiS_SetReg(SISSR
, 0x16, 0x85);
4977 SiS_SetReg(SISSR
, 0x18, 0x00); /* EMRS3 */
4978 SiS_SetReg(SISSR
, 0x19, 0xc0);
4979 SiS_SetReg(SISSR
, 0x16, 0x05);
4980 SiS_SetReg(SISSR
, 0x16, 0x85);
4982 SiS_SetReg(SISSR
, 0x18, 0x00); /* EMRS1 */
4983 SiS_SetReg(SISSR
, 0x19, 0x40);
4984 SiS_SetReg(SISSR
, 0x16, 0x05);
4985 SiS_SetReg(SISSR
, 0x16, 0x85);
4987 SiS_SetReg(SISSR
, 0x18, 0x42); /* MRS1 */
4988 SiS_SetReg(SISSR
, 0x19, 0x02);
4989 SiS_SetReg(SISSR
, 0x16, 0x05);
4990 SiS_SetReg(SISSR
, 0x16, 0x85);
4991 sisfb_post_xgi_delay(ivideo
, 1);
4993 SiS_SetReg(SISSR
, 0x1b, 0x04);
4994 sisfb_post_xgi_delay(ivideo
, 1);
4996 SiS_SetReg(SISSR
, 0x1b, 0x00);
4997 sisfb_post_xgi_delay(ivideo
, 1);
4999 SiS_SetReg(SISSR
, 0x18, 0x42); /* MRS1 */
5000 SiS_SetReg(SISSR
, 0x19, 0x00);
5001 SiS_SetReg(SISSR
, 0x16, 0x05);
5002 SiS_SetReg(SISSR
, 0x16, 0x85);
5003 sisfb_post_xgi_delay(ivideo
, 1);
5006 static void sisfb_post_xgi_ddr2(struct sis_video_info
*ivideo
, u8 regb
)
5008 unsigned char *bios
= ivideo
->bios_abase
;
5009 static const u8 cs158
[8] = {
5010 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5012 static const u8 cs160
[8] = {
5013 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5015 static const u8 cs168
[8] = {
5016 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5022 SiS_SetReg(SISCR
, 0xb0, 0x80); /* DDR2 dual frequency mode */
5023 SiS_SetReg(SISCR
, 0x82, 0x77);
5024 SiS_SetReg(SISCR
, 0x86, 0x00);
5025 SiS_GetReg(SISCR
, 0x86);
5026 SiS_SetReg(SISCR
, 0x86, 0x88);
5027 SiS_GetReg(SISCR
, 0x86);
5028 v1
= cs168
[regb
]; v2
= cs160
[regb
]; v3
= cs158
[regb
];
5029 if (ivideo
->haveXGIROM
) {
5030 v1
= bios
[regb
+ 0x168];
5031 v2
= bios
[regb
+ 0x160];
5032 v3
= bios
[regb
+ 0x158];
5034 SiS_SetReg(SISCR
, 0x86, v1
);
5035 SiS_SetReg(SISCR
, 0x82, 0x77);
5036 SiS_SetReg(SISCR
, 0x85, 0x00);
5037 SiS_GetReg(SISCR
, 0x85);
5038 SiS_SetReg(SISCR
, 0x85, 0x88);
5039 SiS_GetReg(SISCR
, 0x85);
5040 SiS_SetReg(SISCR
, 0x85, v2
);
5041 SiS_SetReg(SISCR
, 0x82, v3
);
5042 SiS_SetReg(SISCR
, 0x98, 0x01);
5043 SiS_SetReg(SISCR
, 0x9a, 0x02);
5044 if (sisfb_xgi_is21(ivideo
))
5045 sisfb_post_xgi_ddr2_mrs_xg21(ivideo
);
5047 sisfb_post_xgi_ddr2_mrs_default(ivideo
, regb
);
5050 static u8
sisfb_post_xgi_ramtype(struct sis_video_info
*ivideo
)
5052 unsigned char *bios
= ivideo
->bios_abase
;
5057 ramtype
= 0x00; v1
= 0x10;
5058 if (ivideo
->haveXGIROM
) {
5059 ramtype
= bios
[0x62];
5062 if (!(ramtype
& 0x80)) {
5063 if (sisfb_xgi_is21(ivideo
)) {
5064 SiS_SetRegAND(SISCR
, 0xb4, 0xfd); /* GPIO control */
5065 SiS_SetRegOR(SISCR
, 0x4a, 0x80); /* GPIOH EN */
5066 reg
= SiS_GetReg(SISCR
, 0x48);
5067 SiS_SetRegOR(SISCR
, 0xb4, 0x02);
5068 ramtype
= reg
& 0x01; /* GPIOH */
5069 } else if (ivideo
->chip
== XGI_20
) {
5070 SiS_SetReg(SISCR
, 0x97, v1
);
5071 reg
= SiS_GetReg(SISCR
, 0x97);
5073 ramtype
= (reg
& 0x01) << 1;
5076 reg
= SiS_GetReg(SISSR
, 0x39);
5077 ramtype
= reg
& 0x02;
5079 reg
= SiS_GetReg(SISSR
, 0x3a);
5080 ramtype
= (reg
>> 1) & 0x01;
5089 static int sisfb_post_xgi(struct pci_dev
*pdev
)
5091 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
5092 unsigned char *bios
= ivideo
->bios_abase
;
5093 struct pci_dev
*mypdev
= NULL
;
5094 const u8
*ptr
, *ptr2
;
5095 u8 v1
, v2
, v3
, v4
, v5
, reg
, ramtype
;
5096 u32 rega
, regb
, regd
;
5098 static const u8 cs78
[3] = { 0xf6, 0x0d, 0x00 };
5099 static const u8 cs76
[2] = { 0xa3, 0xfb };
5100 static const u8 cs7b
[3] = { 0xc0, 0x11, 0x00 };
5101 static const u8 cs158
[8] = {
5102 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5104 static const u8 cs160
[8] = {
5105 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5107 static const u8 cs168
[8] = {
5108 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5110 static const u8 cs128
[3 * 8] = {
5111 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
5112 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5113 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
5115 static const u8 cs148
[2 * 8] = {
5116 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
5117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5119 static const u8 cs31a
[8 * 4] = {
5120 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
5121 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
5122 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5123 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5125 static const u8 cs33a
[8 * 4] = {
5126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5131 static const u8 cs45a
[8 * 2] = {
5132 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
5133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5135 static const u8 cs170
[7 * 8] = {
5136 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5137 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5138 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
5139 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5140 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5141 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5142 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5144 static const u8 cs1a8
[3 * 8] = {
5145 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5146 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5149 static const u8 cs100
[2 * 8] = {
5150 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5151 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5155 reg
= SiS_GetRegByte(SISVGAENABLE
) | 0x01;
5156 SiS_SetRegByte(SISVGAENABLE
, reg
);
5159 reg
= SiS_GetRegByte(SISMISCR
) | 0x01;
5160 SiS_SetRegByte(SISMISCW
, reg
);
5163 SiS_SetReg(SISSR
, 0x05, 0x86);
5164 reg
= SiS_GetReg(SISSR
, 0x05);
5168 /* Clear some regs */
5169 for(i
= 0; i
< 0x22; i
++) {
5170 if(0x06 + i
== 0x20) continue;
5171 SiS_SetReg(SISSR
, 0x06 + i
, 0x00);
5173 for(i
= 0; i
< 0x0b; i
++) {
5174 SiS_SetReg(SISSR
, 0x31 + i
, 0x00);
5176 for(i
= 0; i
< 0x10; i
++) {
5177 SiS_SetReg(SISCR
, 0x30 + i
, 0x00);
5181 if(ivideo
->haveXGIROM
) {
5182 ptr
= (const u8
*)&bios
[0x78];
5184 for(i
= 0; i
< 3; i
++) {
5185 SiS_SetReg(SISSR
, 0x23 + i
, ptr
[i
]);
5189 if(ivideo
->haveXGIROM
) {
5190 ptr
= (const u8
*)&bios
[0x76];
5192 for(i
= 0; i
< 2; i
++) {
5193 SiS_SetReg(SISSR
, 0x21 + i
, ptr
[i
]);
5196 v1
= 0x18; v2
= 0x00;
5197 if(ivideo
->haveXGIROM
) {
5201 SiS_SetReg(SISSR
, 0x07, v1
);
5202 SiS_SetReg(SISSR
, 0x11, 0x0f);
5203 SiS_SetReg(SISSR
, 0x1f, v2
);
5204 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5205 SiS_SetReg(SISSR
, 0x20, 0x80 | 0x20 | 0x04);
5206 SiS_SetReg(SISSR
, 0x27, 0x74);
5209 if(ivideo
->haveXGIROM
) {
5210 ptr
= (const u8
*)&bios
[0x7b];
5212 for(i
= 0; i
< 3; i
++) {
5213 SiS_SetReg(SISSR
, 0x31 + i
, ptr
[i
]);
5216 if(ivideo
->chip
== XGI_40
) {
5217 if(ivideo
->revision_id
== 2) {
5218 SiS_SetRegANDOR(SISSR
, 0x3b, 0x3f, 0xc0);
5220 SiS_SetReg(SISCR
, 0x7d, 0xfe);
5221 SiS_SetReg(SISCR
, 0x7e, 0x0f);
5223 if(ivideo
->revision_id
== 0) { /* 40 *and* 20? */
5224 SiS_SetRegAND(SISCR
, 0x58, 0xd7);
5225 reg
= SiS_GetReg(SISCR
, 0xcb);
5227 SiS_SetRegANDOR(SISCR
, 0x58, 0xd7, (reg
& 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5231 reg
= (ivideo
->chip
== XGI_40
) ? 0x20 : 0x00;
5232 SiS_SetRegANDOR(SISCR
, 0x38, 0x1f, reg
);
5234 if(ivideo
->chip
== XGI_20
) {
5235 SiS_SetReg(SISSR
, 0x36, 0x70);
5237 SiS_SetReg(SISVID
, 0x00, 0x86);
5238 SiS_SetReg(SISVID
, 0x32, 0x00);
5239 SiS_SetReg(SISVID
, 0x30, 0x00);
5240 SiS_SetReg(SISVID
, 0x32, 0x01);
5241 SiS_SetReg(SISVID
, 0x30, 0x00);
5242 SiS_SetRegAND(SISVID
, 0x2f, 0xdf);
5243 SiS_SetRegAND(SISCAP
, 0x00, 0x3f);
5245 SiS_SetReg(SISPART1
, 0x2f, 0x01);
5246 SiS_SetReg(SISPART1
, 0x00, 0x00);
5247 SiS_SetReg(SISPART1
, 0x02, bios
[0x7e]);
5248 SiS_SetReg(SISPART1
, 0x2e, 0x08);
5249 SiS_SetRegAND(SISPART1
, 0x35, 0x7f);
5250 SiS_SetRegAND(SISPART1
, 0x50, 0xfe);
5252 reg
= SiS_GetReg(SISPART4
, 0x00);
5253 if(reg
== 1 || reg
== 2) {
5254 SiS_SetReg(SISPART2
, 0x00, 0x1c);
5255 SiS_SetReg(SISPART4
, 0x0d, bios
[0x7f]);
5256 SiS_SetReg(SISPART4
, 0x0e, bios
[0x80]);
5257 SiS_SetReg(SISPART4
, 0x10, bios
[0x81]);
5258 SiS_SetRegAND(SISPART4
, 0x0f, 0x3f);
5260 reg
= SiS_GetReg(SISPART4
, 0x01);
5261 if((reg
& 0xf0) >= 0xb0) {
5262 reg
= SiS_GetReg(SISPART4
, 0x23);
5263 if(reg
& 0x20) reg
|= 0x40;
5264 SiS_SetReg(SISPART4
, 0x23, reg
);
5265 reg
= (reg
& 0x20) ? 0x02 : 0x00;
5266 SiS_SetRegANDOR(SISPART1
, 0x1e, 0xfd, reg
);
5272 reg
= SiS_GetReg(SISSR
, 0x3b);
5274 reg
= SiS_GetReg(SISSR
, 0x3a);
5275 v2
= (reg
& 0x30) >> 3;
5276 if(!(v2
& 0x04)) v2
^= 0x02;
5277 reg
= SiS_GetReg(SISSR
, 0x39);
5278 if(reg
& 0x80) v2
|= 0x80;
5281 if((mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0730, NULL
))) {
5282 pci_dev_put(mypdev
);
5283 if(((v2
& 0x06) == 2) || ((v2
& 0x06) == 4))
5288 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0735, NULL
);
5290 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0645, NULL
);
5292 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0650, NULL
);
5294 pci_read_config_dword(mypdev
, 0x94, ®d
);
5296 pci_write_config_dword(mypdev
, 0x94, regd
);
5298 pci_dev_put(mypdev
);
5299 } else if(sisfb_find_host_bridge(ivideo
, pdev
, PCI_VENDOR_ID_SI
)) {
5301 } else if(sisfb_find_host_bridge(ivideo
, pdev
, 0x1106) ||
5302 sisfb_find_host_bridge(ivideo
, pdev
, 0x1022) ||
5303 sisfb_find_host_bridge(ivideo
, pdev
, 0x700e) ||
5304 sisfb_find_host_bridge(ivideo
, pdev
, 0x10de)) {
5305 if((v2
& 0x06) == 4)
5310 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf0, v2
);
5312 SiS_SetReg(SISSR
, 0x22, v1
);
5314 if(ivideo
->revision_id
== 2) {
5315 v1
= SiS_GetReg(SISSR
, 0x3b);
5316 v2
= SiS_GetReg(SISSR
, 0x3a);
5317 regd
= bios
[0x90 + 3] | (bios
[0x90 + 4] << 8);
5318 if( (!(v1
& 0x02)) && (v2
& 0x30) && (regd
< 0xcf) )
5319 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf1, 0x01);
5321 if((mypdev
= pci_get_device(0x10de, 0x01e0, NULL
))) {
5322 /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5326 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf1, 0x01);
5327 pci_dev_put(mypdev
);
5332 reg
= SiS_GetReg(SISSR
, 0x3b);
5333 v2
= SiS_GetReg(SISCR
, 0x5f);
5334 if((!(reg
& 0x02)) && (v2
& 0x0e))
5336 SiS_SetReg(SISSR
, 0x27, v1
);
5338 if(bios
[0x64] & 0x01) {
5339 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf0, bios
[0x64]);
5343 pci_read_config_dword(pdev
, 0x50, ®d
);
5344 regd
= (regd
>> 20) & 0x0f;
5347 SiS_SetRegOR(SISCR
, 0x5f, 0x08);
5349 SiS_SetReg(SISCR
, 0x48, v1
);
5351 SiS_SetRegANDOR(SISCR
, 0x47, 0x04, bios
[0x4f6] & 0xfb);
5352 SiS_SetRegANDOR(SISCR
, 0x49, 0xf0, bios
[0x4f8] & 0x0f);
5353 SiS_SetRegANDOR(SISCR
, 0x4a, 0x60, bios
[0x4f9] & 0x9f);
5354 SiS_SetRegANDOR(SISCR
, 0x4b, 0x08, bios
[0x4fa] & 0xf7);
5355 SiS_SetRegANDOR(SISCR
, 0x4c, 0x80, bios
[0x4fb] & 0x7f);
5356 SiS_SetReg(SISCR
, 0x70, bios
[0x4fc]);
5357 SiS_SetRegANDOR(SISCR
, 0x71, 0xf0, bios
[0x4fd] & 0x0f);
5358 SiS_SetReg(SISCR
, 0x74, 0xd0);
5359 SiS_SetRegANDOR(SISCR
, 0x74, 0xcf, bios
[0x4fe] & 0x30);
5360 SiS_SetRegANDOR(SISCR
, 0x75, 0xe0, bios
[0x4ff] & 0x1f);
5361 SiS_SetRegANDOR(SISCR
, 0x76, 0xe0, bios
[0x500] & 0x1f);
5363 if((mypdev
= pci_get_device(0x8086, 0x2530, NULL
))) {
5365 pci_dev_put(mypdev
);
5367 SiS_SetReg(SISCR
, 0x77, v1
);
5372 * 0 == DDR1, 1 == DDR2, 2..7 == reserved?
5374 * The code seems to written so that regb should equal ramtype,
5375 * however, so far it has been hardcoded to 0. Enable other values only
5376 * on XGI Z9, as it passes the POST, and add a warning for others.
5378 ramtype
= sisfb_post_xgi_ramtype(ivideo
);
5379 if (!sisfb_xgi_is21(ivideo
) && ramtype
) {
5380 dev_warn(&pdev
->dev
,
5381 "RAM type something else than expected: %d\n",
5389 if(ivideo
->haveXGIROM
) {
5390 v1
= bios
[0x140 + regb
];
5392 SiS_SetReg(SISCR
, 0x6d, v1
);
5395 if(ivideo
->haveXGIROM
) {
5396 ptr
= (const u8
*)&bios
[0x128];
5398 for(i
= 0, j
= 0; i
< 3; i
++, j
+= 8) {
5399 SiS_SetReg(SISCR
, 0x68 + i
, ptr
[j
+ regb
]);
5404 if(ivideo
->haveXGIROM
) {
5405 index
= (ivideo
->chip
== XGI_20
) ? 0x31a : 0x3a6;
5406 ptr
= (const u8
*)&bios
[index
];
5407 ptr2
= (const u8
*)&bios
[index
+ 0x20];
5409 for(i
= 0; i
< 2; i
++) {
5411 regd
= le32_to_cpu(((u32
*)ptr
)[regb
]);
5414 regd
= le32_to_cpu(((u32
*)ptr2
)[regb
]);
5418 for(j
= 0; j
< 16; j
++) {
5420 if(regd
& 0x01) reg
|= 0x04;
5421 if(regd
& 0x02) reg
|= 0x08;
5423 SiS_SetReg(SISCR
, rega
, reg
);
5424 reg
= SiS_GetReg(SISCR
, rega
);
5425 reg
= SiS_GetReg(SISCR
, rega
);
5430 SiS_SetRegAND(SISCR
, 0x6e, 0xfc);
5433 if(ivideo
->haveXGIROM
) {
5434 index
= (ivideo
->chip
== XGI_20
) ? 0x35a : 0x3e6;
5435 ptr
= (const u8
*)&bios
[index
];
5437 for(i
= 0; i
< 4; i
++) {
5438 SiS_SetRegANDOR(SISCR
, 0x6e, 0xfc, i
);
5440 for(j
= 0; j
< 2; j
++) {
5443 regd
= le32_to_cpu(((u32
*)ptr
)[regb
* 8]);
5447 for(k
= 0; k
< 16; k
++) {
5449 if(regd
& 0x01) reg
|= 0x01;
5450 if(regd
& 0x02) reg
|= 0x02;
5452 SiS_SetReg(SISCR
, 0x6f, reg
);
5453 reg
= SiS_GetReg(SISCR
, 0x6f);
5454 reg
= SiS_GetReg(SISCR
, 0x6f);
5461 if(ivideo
->haveXGIROM
) {
5462 ptr
= (const u8
*)&bios
[0x148];
5464 for(i
= 0, j
= 0; i
< 2; i
++, j
+= 8) {
5465 SiS_SetReg(SISCR
, 0x80 + i
, ptr
[j
+ regb
]);
5468 SiS_SetRegAND(SISCR
, 0x89, 0x8f);
5471 if(ivideo
->haveXGIROM
) {
5472 index
= (ivideo
->chip
== XGI_20
) ? 0x45a : 0x4e6;
5473 ptr
= (const u8
*)&bios
[index
];
5475 regd
= le16_to_cpu(((const u16
*)ptr
)[regb
]);
5477 for(i
= 0; i
< 5; i
++) {
5479 if(regd
& 0x01) reg
|= 0x01;
5480 if(regd
& 0x02) reg
|= 0x02;
5482 SiS_SetReg(SISCR
, 0x89, reg
);
5483 reg
= SiS_GetReg(SISCR
, 0x89);
5484 reg
= SiS_GetReg(SISCR
, 0x89);
5488 v1
= 0xb5; v2
= 0x20; v3
= 0xf0; v4
= 0x13;
5489 if(ivideo
->haveXGIROM
) {
5490 v1
= bios
[0x118 + regb
];
5491 v2
= bios
[0xf8 + regb
];
5492 v3
= bios
[0x120 + regb
];
5495 SiS_SetReg(SISCR
, 0x45, v1
& 0x0f);
5496 SiS_SetReg(SISCR
, 0x99, (v1
>> 4) & 0x07);
5497 SiS_SetRegOR(SISCR
, 0x40, v1
& 0x80);
5498 SiS_SetReg(SISCR
, 0x41, v2
);
5501 if(ivideo
->haveXGIROM
) {
5502 ptr
= (const u8
*)&bios
[0x170];
5504 for(i
= 0, j
= 0; i
< 7; i
++, j
+= 8) {
5505 SiS_SetReg(SISCR
, 0x90 + i
, ptr
[j
+ regb
]);
5508 SiS_SetReg(SISCR
, 0x59, v3
);
5511 if(ivideo
->haveXGIROM
) {
5512 ptr
= (const u8
*)&bios
[0x1a8];
5514 for(i
= 0, j
= 0; i
< 3; i
++, j
+= 8) {
5515 SiS_SetReg(SISCR
, 0xc3 + i
, ptr
[j
+ regb
]);
5519 if(ivideo
->haveXGIROM
) {
5520 ptr
= (const u8
*)&bios
[0x100];
5522 for(i
= 0, j
= 0; i
< 2; i
++, j
+= 8) {
5523 SiS_SetReg(SISCR
, 0x8a + i
, ptr
[j
+ regb
]);
5526 SiS_SetReg(SISCR
, 0xcf, v4
);
5528 SiS_SetReg(SISCR
, 0x83, 0x09);
5529 SiS_SetReg(SISCR
, 0x87, 0x00);
5531 if(ivideo
->chip
== XGI_40
) {
5532 if( (ivideo
->revision_id
== 1) ||
5533 (ivideo
->revision_id
== 2) ) {
5534 SiS_SetReg(SISCR
, 0x8c, 0x87);
5539 SiS_SetReg(SISSR
, 0x17, 0x80); /* DDR2 */
5541 SiS_SetReg(SISSR
, 0x17, 0x00); /* DDR1 */
5542 SiS_SetReg(SISSR
, 0x1a, 0x87);
5544 if(ivideo
->chip
== XGI_20
) {
5545 SiS_SetReg(SISSR
, 0x15, 0x00);
5546 SiS_SetReg(SISSR
, 0x1c, 0x00);
5551 sisfb_post_xgi_setclocks(ivideo
, regb
);
5552 if((ivideo
->chip
== XGI_20
) ||
5553 (ivideo
->revision_id
== 1) ||
5554 (ivideo
->revision_id
== 2)) {
5555 v1
= cs158
[regb
]; v2
= cs160
[regb
]; v3
= cs168
[regb
];
5556 if(ivideo
->haveXGIROM
) {
5557 v1
= bios
[regb
+ 0x158];
5558 v2
= bios
[regb
+ 0x160];
5559 v3
= bios
[regb
+ 0x168];
5561 SiS_SetReg(SISCR
, 0x82, v1
);
5562 SiS_SetReg(SISCR
, 0x85, v2
);
5563 SiS_SetReg(SISCR
, 0x86, v3
);
5565 SiS_SetReg(SISCR
, 0x82, 0x88);
5566 SiS_SetReg(SISCR
, 0x86, 0x00);
5567 reg
= SiS_GetReg(SISCR
, 0x86);
5568 SiS_SetReg(SISCR
, 0x86, 0x88);
5569 reg
= SiS_GetReg(SISCR
, 0x86);
5570 SiS_SetReg(SISCR
, 0x86, bios
[regb
+ 0x168]);
5571 SiS_SetReg(SISCR
, 0x82, 0x77);
5572 SiS_SetReg(SISCR
, 0x85, 0x00);
5573 reg
= SiS_GetReg(SISCR
, 0x85);
5574 SiS_SetReg(SISCR
, 0x85, 0x88);
5575 reg
= SiS_GetReg(SISCR
, 0x85);
5576 SiS_SetReg(SISCR
, 0x85, bios
[regb
+ 0x160]);
5577 SiS_SetReg(SISCR
, 0x82, bios
[regb
+ 0x158]);
5579 if(ivideo
->chip
== XGI_40
) {
5580 SiS_SetReg(SISCR
, 0x97, 0x00);
5582 SiS_SetReg(SISCR
, 0x98, 0x01);
5583 SiS_SetReg(SISCR
, 0x9a, 0x02);
5585 SiS_SetReg(SISSR
, 0x18, 0x01);
5586 if((ivideo
->chip
== XGI_20
) ||
5587 (ivideo
->revision_id
== 2)) {
5588 SiS_SetReg(SISSR
, 0x19, 0x40);
5590 SiS_SetReg(SISSR
, 0x19, 0x20);
5592 SiS_SetReg(SISSR
, 0x16, 0x00);
5593 SiS_SetReg(SISSR
, 0x16, 0x80);
5594 if((ivideo
->chip
== XGI_20
) || (bios
[0x1cb] != 0x0c)) {
5595 sisfb_post_xgi_delay(ivideo
, 0x43);
5596 sisfb_post_xgi_delay(ivideo
, 0x43);
5597 sisfb_post_xgi_delay(ivideo
, 0x43);
5598 SiS_SetReg(SISSR
, 0x18, 0x00);
5599 if((ivideo
->chip
== XGI_20
) ||
5600 (ivideo
->revision_id
== 2)) {
5601 SiS_SetReg(SISSR
, 0x19, 0x40);
5603 SiS_SetReg(SISSR
, 0x19, 0x20);
5605 } else if((ivideo
->chip
== XGI_40
) && (bios
[0x1cb] == 0x0c)) {
5606 /* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
5608 SiS_SetReg(SISSR
, 0x16, 0x00);
5609 SiS_SetReg(SISSR
, 0x16, 0x80);
5610 sisfb_post_xgi_delay(ivideo
, 4);
5611 v1
= 0x31; v2
= 0x03; v3
= 0x83; v4
= 0x03; v5
= 0x83;
5612 if(ivideo
->haveXGIROM
) {
5614 index
= (ivideo
->chip
== XGI_20
) ? 0x4b2 : 0x53e;
5616 v3
= bios
[index
+ 1];
5617 v4
= bios
[index
+ 2];
5618 v5
= bios
[index
+ 3];
5620 SiS_SetReg(SISSR
, 0x18, v1
);
5621 SiS_SetReg(SISSR
, 0x19, ((ivideo
->chip
== XGI_20
) ? 0x02 : 0x01));
5622 SiS_SetReg(SISSR
, 0x16, v2
);
5623 SiS_SetReg(SISSR
, 0x16, v3
);
5624 sisfb_post_xgi_delay(ivideo
, 0x43);
5625 SiS_SetReg(SISSR
, 0x1b, 0x03);
5626 sisfb_post_xgi_delay(ivideo
, 0x22);
5627 SiS_SetReg(SISSR
, 0x18, v1
);
5628 SiS_SetReg(SISSR
, 0x19, 0x00);
5629 SiS_SetReg(SISSR
, 0x16, v4
);
5630 SiS_SetReg(SISSR
, 0x16, v5
);
5631 SiS_SetReg(SISSR
, 0x1b, 0x00);
5634 sisfb_post_xgi_ddr2(ivideo
, regb
);
5637 sisfb_post_xgi_setclocks(ivideo
, regb
);
5638 if((ivideo
->chip
== XGI_40
) &&
5639 ((ivideo
->revision_id
== 1) ||
5640 (ivideo
->revision_id
== 2))) {
5641 SiS_SetReg(SISCR
, 0x82, bios
[regb
+ 0x158]);
5642 SiS_SetReg(SISCR
, 0x85, bios
[regb
+ 0x160]);
5643 SiS_SetReg(SISCR
, 0x86, bios
[regb
+ 0x168]);
5645 SiS_SetReg(SISCR
, 0x82, 0x88);
5646 SiS_SetReg(SISCR
, 0x86, 0x00);
5647 reg
= SiS_GetReg(SISCR
, 0x86);
5648 SiS_SetReg(SISCR
, 0x86, 0x88);
5649 SiS_SetReg(SISCR
, 0x82, 0x77);
5650 SiS_SetReg(SISCR
, 0x85, 0x00);
5651 reg
= SiS_GetReg(SISCR
, 0x85);
5652 SiS_SetReg(SISCR
, 0x85, 0x88);
5653 reg
= SiS_GetReg(SISCR
, 0x85);
5654 v1
= cs160
[regb
]; v2
= cs158
[regb
];
5655 if(ivideo
->haveXGIROM
) {
5656 v1
= bios
[regb
+ 0x160];
5657 v2
= bios
[regb
+ 0x158];
5659 SiS_SetReg(SISCR
, 0x85, v1
);
5660 SiS_SetReg(SISCR
, 0x82, v2
);
5662 if(ivideo
->chip
== XGI_40
) {
5663 SiS_SetReg(SISCR
, 0x97, 0x11);
5665 if((ivideo
->chip
== XGI_40
) && (ivideo
->revision_id
== 2)) {
5666 SiS_SetReg(SISCR
, 0x98, 0x01);
5668 SiS_SetReg(SISCR
, 0x98, 0x03);
5670 SiS_SetReg(SISCR
, 0x9a, 0x02);
5672 if(ivideo
->chip
== XGI_40
) {
5673 SiS_SetReg(SISSR
, 0x18, 0x01);
5675 SiS_SetReg(SISSR
, 0x18, 0x00);
5677 SiS_SetReg(SISSR
, 0x19, 0x40);
5678 SiS_SetReg(SISSR
, 0x16, 0x00);
5679 SiS_SetReg(SISSR
, 0x16, 0x80);
5680 if((ivideo
->chip
== XGI_40
) && (bios
[0x1cb] != 0x0c)) {
5681 sisfb_post_xgi_delay(ivideo
, 0x43);
5682 sisfb_post_xgi_delay(ivideo
, 0x43);
5683 sisfb_post_xgi_delay(ivideo
, 0x43);
5684 SiS_SetReg(SISSR
, 0x18, 0x00);
5685 SiS_SetReg(SISSR
, 0x19, 0x40);
5686 SiS_SetReg(SISSR
, 0x16, 0x00);
5687 SiS_SetReg(SISSR
, 0x16, 0x80);
5689 sisfb_post_xgi_delay(ivideo
, 4);
5691 if(ivideo
->haveXGIROM
) {
5694 SiS_SetReg(SISSR
, 0x18, v1
);
5695 SiS_SetReg(SISSR
, 0x19, 0x01);
5696 if(ivideo
->chip
== XGI_40
) {
5697 SiS_SetReg(SISSR
, 0x16, bios
[0x53e]);
5698 SiS_SetReg(SISSR
, 0x16, bios
[0x53f]);
5700 SiS_SetReg(SISSR
, 0x16, 0x05);
5701 SiS_SetReg(SISSR
, 0x16, 0x85);
5703 sisfb_post_xgi_delay(ivideo
, 0x43);
5704 if(ivideo
->chip
== XGI_40
) {
5705 SiS_SetReg(SISSR
, 0x1b, 0x01);
5707 SiS_SetReg(SISSR
, 0x1b, 0x03);
5709 sisfb_post_xgi_delay(ivideo
, 0x22);
5710 SiS_SetReg(SISSR
, 0x18, v1
);
5711 SiS_SetReg(SISSR
, 0x19, 0x00);
5712 if(ivideo
->chip
== XGI_40
) {
5713 SiS_SetReg(SISSR
, 0x16, bios
[0x540]);
5714 SiS_SetReg(SISSR
, 0x16, bios
[0x541]);
5716 SiS_SetReg(SISSR
, 0x16, 0x05);
5717 SiS_SetReg(SISSR
, 0x16, 0x85);
5719 SiS_SetReg(SISSR
, 0x1b, 0x00);
5724 if(ivideo
->haveXGIROM
) {
5725 v1
= bios
[0x110 + regb
];
5727 SiS_SetReg(SISSR
, 0x1b, v1
);
5730 v1
= 0x00; v2
= 0x00;
5731 if(ivideo
->haveXGIROM
) {
5737 if((v1
& 0x40) && (v2
& regd
) && ivideo
->haveXGIROM
) {
5739 SiS_SetReg(SISSR
, 0x13, bios
[regb
+ 0xe0]);
5740 SiS_SetReg(SISSR
, 0x14, bios
[regb
+ 0xe0 + 8]);
5745 /* Set default mode, don't clear screen */
5746 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
5747 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
5748 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
5749 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
5750 ivideo
->SiS_Pr
.VideoMemorySize
= 8 << 20;
5751 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
5753 SiS_SetReg(SISSR
, 0x05, 0x86);
5755 /* Disable read-cache */
5756 SiS_SetRegAND(SISSR
, 0x21, 0xdf);
5757 err
= sisfb_post_xgi_ramsize(ivideo
);
5758 /* Enable read-cache */
5759 SiS_SetRegOR(SISSR
, 0x21, 0x20);
5763 "%s: RAM size detection failed: %d\n",
5770 printk(KERN_DEBUG
"-----------------\n");
5771 for(i
= 0; i
< 0xff; i
++) {
5772 reg
= SiS_GetReg(SISCR
, i
);
5773 printk(KERN_DEBUG
"CR%02x(%x) = 0x%02x\n", i
, SISCR
, reg
);
5775 for(i
= 0; i
< 0x40; i
++) {
5776 reg
= SiS_GetReg(SISSR
, i
);
5777 printk(KERN_DEBUG
"SR%02x(%x) = 0x%02x\n", i
, SISSR
, reg
);
5779 printk(KERN_DEBUG
"-----------------\n");
5783 if(ivideo
->chip
== XGI_20
) {
5784 SiS_SetRegOR(SISCR
, 0x32, 0x20);
5786 reg
= SiS_GetReg(SISPART4
, 0x00);
5787 if((reg
== 1) || (reg
== 2)) {
5788 sisfb_sense_crt1(ivideo
);
5790 SiS_SetRegOR(SISCR
, 0x32, 0x20);
5794 /* Set default mode, don't clear screen */
5795 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
5796 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
5797 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
5798 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
5799 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
5801 SiS_SetReg(SISSR
, 0x05, 0x86);
5804 SiS_SetRegOR(SISSR
, 0x01, 0x20);
5806 /* Save mode number in CR34 */
5807 SiS_SetReg(SISCR
, 0x34, 0x2e);
5809 /* Let everyone know what the current mode is */
5810 ivideo
->modeprechange
= 0x2e;
5812 if(ivideo
->chip
== XGI_40
) {
5813 reg
= SiS_GetReg(SISCR
, 0xca);
5814 v1
= SiS_GetReg(SISCR
, 0xcc);
5815 if((reg
& 0x10) && (!(v1
& 0x04))) {
5817 "sisfb: Please connect power to the card.\n");
5826 static int sisfb_probe(struct pci_dev
*pdev
, const struct pci_device_id
*ent
)
5828 struct sisfb_chip_info
*chipinfo
= &sisfb_chip_info
[ent
->driver_data
];
5829 struct sis_video_info
*ivideo
= NULL
;
5830 struct fb_info
*sis_fb_info
= NULL
;
5838 ret
= aperture_remove_conflicting_pci_devices(pdev
, "sisfb");
5842 sis_fb_info
= framebuffer_alloc(sizeof(*ivideo
), &pdev
->dev
);
5846 ivideo
= (struct sis_video_info
*)sis_fb_info
->par
;
5847 ivideo
->memyselfandi
= sis_fb_info
;
5849 ivideo
->sisfb_id
= SISFB_ID
;
5851 if(card_list
== NULL
) {
5852 ivideo
->cardnumber
= 0;
5854 struct sis_video_info
*countvideo
= card_list
;
5855 ivideo
->cardnumber
= 1;
5856 while((countvideo
= countvideo
->next
) != NULL
)
5857 ivideo
->cardnumber
++;
5860 strscpy(ivideo
->myid
, chipinfo
->chip_name
, sizeof(ivideo
->myid
));
5862 ivideo
->warncount
= 0;
5863 ivideo
->chip_id
= pdev
->device
;
5864 ivideo
->chip_vendor
= pdev
->vendor
;
5865 ivideo
->revision_id
= pdev
->revision
;
5866 ivideo
->SiS_Pr
.ChipRevision
= ivideo
->revision_id
;
5867 pci_read_config_word(pdev
, PCI_COMMAND
, ®16
);
5868 ivideo
->sisvga_enabled
= reg16
& 0x01;
5869 ivideo
->pcibus
= pdev
->bus
->number
;
5870 ivideo
->pcislot
= PCI_SLOT(pdev
->devfn
);
5871 ivideo
->pcifunc
= PCI_FUNC(pdev
->devfn
);
5872 ivideo
->subsysvendor
= pdev
->subsystem_vendor
;
5873 ivideo
->subsysdevice
= pdev
->subsystem_device
;
5875 ivideo
->chip
= chipinfo
->chip
;
5876 ivideo
->chip_real_id
= chipinfo
->chip
;
5877 ivideo
->sisvga_engine
= chipinfo
->vgaengine
;
5878 ivideo
->hwcursor_size
= chipinfo
->hwcursor_size
;
5879 ivideo
->CRT2_write_enable
= chipinfo
->CRT2_write_enable
;
5880 ivideo
->mni
= chipinfo
->mni
;
5882 ivideo
->detectedpdc
= 0xff;
5883 ivideo
->detectedpdca
= 0xff;
5884 ivideo
->detectedlcda
= 0xff;
5886 ivideo
->sisfb_thismonitor
.datavalid
= false;
5888 ivideo
->current_base
= 0;
5890 ivideo
->engineok
= 0;
5892 ivideo
->sisfb_was_boot_device
= 0;
5894 if(pdev
->resource
[PCI_ROM_RESOURCE
].flags
& IORESOURCE_ROM_SHADOW
) {
5895 if(ivideo
->sisvga_enabled
)
5896 ivideo
->sisfb_was_boot_device
= 1;
5898 printk(KERN_DEBUG
"sisfb: PCI device is disabled, "
5899 "but marked as boot video device ???\n");
5900 printk(KERN_DEBUG
"sisfb: I will not accept this "
5901 "as the primary VGA device\n");
5905 ivideo
->sisfb_parm_mem
= sisfb_parm_mem
;
5906 ivideo
->sisfb_accel
= sisfb_accel
;
5907 ivideo
->sisfb_ypan
= sisfb_ypan
;
5908 ivideo
->sisfb_max
= sisfb_max
;
5909 ivideo
->sisfb_userom
= sisfb_userom
;
5910 ivideo
->sisfb_useoem
= sisfb_useoem
;
5911 ivideo
->sisfb_mode_idx
= sisfb_mode_idx
;
5912 ivideo
->sisfb_parm_rate
= sisfb_parm_rate
;
5913 ivideo
->sisfb_crt1off
= sisfb_crt1off
;
5914 ivideo
->sisfb_forcecrt1
= sisfb_forcecrt1
;
5915 ivideo
->sisfb_crt2type
= sisfb_crt2type
;
5916 ivideo
->sisfb_crt2flags
= sisfb_crt2flags
;
5917 /* pdc(a), scalelcd, special timing, lvdshl handled below */
5918 ivideo
->sisfb_dstn
= sisfb_dstn
;
5919 ivideo
->sisfb_fstn
= sisfb_fstn
;
5920 ivideo
->sisfb_tvplug
= sisfb_tvplug
;
5921 ivideo
->sisfb_tvstd
= sisfb_tvstd
;
5922 ivideo
->tvxpos
= sisfb_tvxposoffset
;
5923 ivideo
->tvypos
= sisfb_tvyposoffset
;
5924 ivideo
->sisfb_nocrt2rate
= sisfb_nocrt2rate
;
5925 ivideo
->refresh_rate
= 0;
5926 if(ivideo
->sisfb_parm_rate
!= -1) {
5927 ivideo
->refresh_rate
= ivideo
->sisfb_parm_rate
;
5930 ivideo
->SiS_Pr
.UsePanelScaler
= sisfb_scalelcd
;
5931 ivideo
->SiS_Pr
.CenterScreen
= -1;
5932 ivideo
->SiS_Pr
.SiS_CustomT
= sisfb_specialtiming
;
5933 ivideo
->SiS_Pr
.LVDSHL
= sisfb_lvdshl
;
5935 ivideo
->SiS_Pr
.SiS_Backup70xx
= 0xff;
5936 ivideo
->SiS_Pr
.SiS_CHOverScan
= -1;
5937 ivideo
->SiS_Pr
.SiS_ChSW
= false;
5938 ivideo
->SiS_Pr
.SiS_UseLCDA
= false;
5939 ivideo
->SiS_Pr
.HaveEMI
= false;
5940 ivideo
->SiS_Pr
.HaveEMILCD
= false;
5941 ivideo
->SiS_Pr
.OverruleEMI
= false;
5942 ivideo
->SiS_Pr
.SiS_SensibleSR11
= false;
5943 ivideo
->SiS_Pr
.SiS_MyCR63
= 0x63;
5944 ivideo
->SiS_Pr
.PDC
= -1;
5945 ivideo
->SiS_Pr
.PDCA
= -1;
5946 ivideo
->SiS_Pr
.DDCPortMixup
= false;
5947 #ifdef CONFIG_FB_SIS_315
5948 if(ivideo
->chip
>= SIS_330
) {
5949 ivideo
->SiS_Pr
.SiS_MyCR63
= 0x53;
5950 if(ivideo
->chip
>= SIS_661
) {
5951 ivideo
->SiS_Pr
.SiS_SensibleSR11
= true;
5956 memcpy(&ivideo
->default_var
, &my_default_var
, sizeof(my_default_var
));
5958 pci_set_drvdata(pdev
, ivideo
);
5960 /* Patch special cases */
5961 if((ivideo
->nbridge
= sisfb_get_northbridge(ivideo
->chip
))) {
5962 switch(ivideo
->nbridge
->device
) {
5963 #ifdef CONFIG_FB_SIS_300
5964 case PCI_DEVICE_ID_SI_730
:
5965 ivideo
->chip
= SIS_730
;
5966 strcpy(ivideo
->myid
, "SiS 730");
5969 #ifdef CONFIG_FB_SIS_315
5970 case PCI_DEVICE_ID_SI_651
:
5971 /* ivideo->chip is ok */
5972 strcpy(ivideo
->myid
, "SiS 651");
5974 case PCI_DEVICE_ID_SI_740
:
5975 ivideo
->chip
= SIS_740
;
5976 strcpy(ivideo
->myid
, "SiS 740");
5978 case PCI_DEVICE_ID_SI_661
:
5979 ivideo
->chip
= SIS_661
;
5980 strcpy(ivideo
->myid
, "SiS 661");
5982 case PCI_DEVICE_ID_SI_741
:
5983 ivideo
->chip
= SIS_741
;
5984 strcpy(ivideo
->myid
, "SiS 741");
5986 case PCI_DEVICE_ID_SI_760
:
5987 ivideo
->chip
= SIS_760
;
5988 strcpy(ivideo
->myid
, "SiS 760");
5990 case PCI_DEVICE_ID_SI_761
:
5991 ivideo
->chip
= SIS_761
;
5992 strcpy(ivideo
->myid
, "SiS 761");
6000 ivideo
->SiS_Pr
.ChipType
= ivideo
->chip
;
6002 ivideo
->SiS_Pr
.ivideo
= (void *)ivideo
;
6004 #ifdef CONFIG_FB_SIS_315
6005 if((ivideo
->SiS_Pr
.ChipType
== SIS_315PRO
) ||
6006 (ivideo
->SiS_Pr
.ChipType
== SIS_315
)) {
6007 ivideo
->SiS_Pr
.ChipType
= SIS_315H
;
6011 if(!ivideo
->sisvga_enabled
) {
6012 if(pci_enable_device(pdev
)) {
6013 pci_dev_put(ivideo
->nbridge
);
6014 framebuffer_release(sis_fb_info
);
6019 ivideo
->video_base
= pci_resource_start(pdev
, 0);
6020 ivideo
->video_size
= pci_resource_len(pdev
, 0);
6021 ivideo
->mmio_base
= pci_resource_start(pdev
, 1);
6022 ivideo
->mmio_size
= pci_resource_len(pdev
, 1);
6023 ivideo
->SiS_Pr
.RelIO
= pci_resource_start(pdev
, 2) + 0x30;
6024 ivideo
->SiS_Pr
.IOAddress
= ivideo
->vga_base
= ivideo
->SiS_Pr
.RelIO
;
6026 SiSRegInit(&ivideo
->SiS_Pr
, ivideo
->SiS_Pr
.IOAddress
);
6028 #ifdef CONFIG_FB_SIS_300
6029 /* Find PCI systems for Chrontel/GPIO communication setup */
6030 if(ivideo
->chip
== SIS_630
) {
6033 if(mychswtable
[i
].subsysVendor
== ivideo
->subsysvendor
&&
6034 mychswtable
[i
].subsysCard
== ivideo
->subsysdevice
) {
6035 ivideo
->SiS_Pr
.SiS_ChSW
= true;
6036 printk(KERN_DEBUG
"sisfb: Identified [%s %s] "
6037 "requiring Chrontel/GPIO setup\n",
6038 mychswtable
[i
].vendorName
,
6039 mychswtable
[i
].cardName
);
6040 ivideo
->lpcdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0008, NULL
);
6044 } while(mychswtable
[i
].subsysVendor
!= 0);
6048 #ifdef CONFIG_FB_SIS_315
6049 if((ivideo
->chip
== SIS_760
) && (ivideo
->nbridge
)) {
6050 ivideo
->lpcdev
= pci_get_slot(ivideo
->nbridge
->bus
, (2 << 3));
6054 SiS_SetReg(SISSR
, 0x05, 0x86);
6056 if( (!ivideo
->sisvga_enabled
)
6057 #if !defined(__i386__) && !defined(__x86_64__)
6058 || (sisfb_resetcard
)
6061 for(i
= 0x30; i
<= 0x3f; i
++) {
6062 SiS_SetReg(SISCR
, i
, 0x00);
6066 /* Find out about current video mode */
6067 ivideo
->modeprechange
= 0x03;
6068 reg
= SiS_GetReg(SISCR
, 0x34);
6070 ivideo
->modeprechange
= reg
& 0x7f;
6071 } else if(ivideo
->sisvga_enabled
) {
6072 #if defined(__i386__) || defined(__x86_64__)
6073 unsigned char __iomem
*tt
= ioremap(0x400, 0x100);
6075 ivideo
->modeprechange
= readb(tt
+ 0x49);
6081 /* Search and copy ROM image */
6082 ivideo
->bios_abase
= NULL
;
6083 ivideo
->SiS_Pr
.VirtualRomBase
= NULL
;
6084 ivideo
->SiS_Pr
.UseROM
= false;
6085 ivideo
->haveXGIROM
= ivideo
->SiS_Pr
.SiS_XGIROM
= false;
6086 if(ivideo
->sisfb_userom
) {
6087 ivideo
->SiS_Pr
.VirtualRomBase
= sisfb_find_rom(pdev
);
6088 ivideo
->bios_abase
= ivideo
->SiS_Pr
.VirtualRomBase
;
6089 ivideo
->SiS_Pr
.UseROM
= (bool)(ivideo
->SiS_Pr
.VirtualRomBase
);
6090 printk(KERN_INFO
"sisfb: Video ROM %sfound\n",
6091 ivideo
->SiS_Pr
.UseROM
? "" : "not ");
6092 if((ivideo
->SiS_Pr
.UseROM
) && (ivideo
->chip
>= XGI_20
)) {
6093 ivideo
->SiS_Pr
.UseROM
= false;
6094 ivideo
->haveXGIROM
= ivideo
->SiS_Pr
.SiS_XGIROM
= true;
6095 if( (ivideo
->revision_id
== 2) &&
6096 (!(ivideo
->bios_abase
[0x1d1] & 0x01)) ) {
6097 ivideo
->SiS_Pr
.DDCPortMixup
= true;
6101 printk(KERN_INFO
"sisfb: Video ROM usage disabled\n");
6104 /* Find systems for special custom timing */
6105 if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_NONE
) {
6106 sisfb_detect_custom_timing(ivideo
);
6109 #ifdef CONFIG_FB_SIS_315
6110 if (ivideo
->chip
== XGI_20
) {
6111 /* Check if our Z7 chip is actually Z9 */
6112 SiS_SetRegOR(SISCR
, 0x4a, 0x40); /* GPIOG EN */
6113 reg
= SiS_GetReg(SISCR
, 0x48);
6114 if (reg
& 0x02) { /* GPIOG */
6115 ivideo
->chip_real_id
= XGI_21
;
6116 dev_info(&pdev
->dev
, "Z9 detected\n");
6121 /* POST card in case this has not been done by the BIOS */
6122 if( (!ivideo
->sisvga_enabled
)
6123 #if !defined(__i386__) && !defined(__x86_64__)
6124 || (sisfb_resetcard
)
6127 #ifdef CONFIG_FB_SIS_300
6128 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
6129 if(ivideo
->chip
== SIS_300
) {
6130 sisfb_post_sis300(pdev
);
6131 ivideo
->sisfb_can_post
= 1;
6136 #ifdef CONFIG_FB_SIS_315
6137 if (ivideo
->sisvga_engine
== SIS_315_VGA
) {
6140 if (ivideo
->chip
== XGI_20
) {
6141 result
= sisfb_post_xgi(pdev
);
6142 ivideo
->sisfb_can_post
= 1;
6143 } else if ((ivideo
->chip
== XGI_40
) && ivideo
->haveXGIROM
) {
6144 result
= sisfb_post_xgi(pdev
);
6145 ivideo
->sisfb_can_post
= 1;
6147 printk(KERN_INFO
"sisfb: Card is not "
6148 "POSTed and sisfb can't do this either.\n");
6151 printk(KERN_ERR
"sisfb: Failed to POST card\n");
6159 ivideo
->sisfb_card_posted
= 1;
6161 /* Find out about RAM size */
6162 if(sisfb_get_dram_size(ivideo
)) {
6163 printk(KERN_INFO
"sisfb: Fatal error: Unable to determine VRAM size.\n");
6169 /* Enable PCI addressing and MMIO */
6170 if((ivideo
->sisfb_mode_idx
< 0) ||
6171 ((sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
]) != 0xFF)) {
6172 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
6173 SiS_SetRegOR(SISSR
, IND_SIS_PCI_ADDRESS_SET
, (SIS_PCI_ADDR_ENABLE
| SIS_MEM_MAP_IO_ENABLE
));
6174 /* Enable 2D accelerator engine */
6175 SiS_SetRegOR(SISSR
, IND_SIS_MODULE_ENABLE
, SIS_ENABLE_2D
);
6178 if(sisfb_pdc
!= 0xff) {
6179 if(ivideo
->sisvga_engine
== SIS_300_VGA
)
6183 ivideo
->SiS_Pr
.PDC
= sisfb_pdc
;
6185 #ifdef CONFIG_FB_SIS_315
6186 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
6187 if(sisfb_pdca
!= 0xff)
6188 ivideo
->SiS_Pr
.PDCA
= sisfb_pdca
& 0x1f;
6192 if(!request_mem_region(ivideo
->video_base
, ivideo
->video_size
, "sisfb FB")) {
6193 printk(KERN_ERR
"sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6194 (int)(ivideo
->video_size
>> 20));
6195 printk(KERN_ERR
"sisfb: Is there another framebuffer driver active?\n");
6200 if(!request_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
, "sisfb MMIO")) {
6201 printk(KERN_ERR
"sisfb: Fatal error: Unable to reserve MMIO region\n");
6206 ivideo
->video_vbase
= ioremap_wc(ivideo
->video_base
, ivideo
->video_size
);
6207 ivideo
->SiS_Pr
.VideoMemoryAddress
= ivideo
->video_vbase
;
6208 if(!ivideo
->video_vbase
) {
6209 printk(KERN_ERR
"sisfb: Fatal error: Unable to map framebuffer memory\n");
6214 ivideo
->mmio_vbase
= ioremap(ivideo
->mmio_base
, ivideo
->mmio_size
);
6215 if(!ivideo
->mmio_vbase
) {
6216 printk(KERN_ERR
"sisfb: Fatal error: Unable to map MMIO region\n");
6218 error_0
: iounmap(ivideo
->video_vbase
);
6219 error_1
: release_mem_region(ivideo
->video_base
, ivideo
->video_size
);
6220 error_2
: release_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
);
6221 error_3
: vfree(ivideo
->bios_abase
);
6222 pci_dev_put(ivideo
->lpcdev
);
6223 pci_dev_put(ivideo
->nbridge
);
6224 if(!ivideo
->sisvga_enabled
)
6225 pci_disable_device(pdev
);
6226 framebuffer_release(sis_fb_info
);
6230 printk(KERN_INFO
"sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
6231 ivideo
->video_base
, (unsigned long)ivideo
->video_vbase
, ivideo
->video_size
/ 1024);
6233 if(ivideo
->video_offset
) {
6234 printk(KERN_INFO
"sisfb: Viewport offset %ldk\n",
6235 ivideo
->video_offset
/ 1024);
6238 printk(KERN_INFO
"sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
6239 ivideo
->mmio_base
, (unsigned long)ivideo
->mmio_vbase
, ivideo
->mmio_size
/ 1024);
6242 /* Determine the size of the command queue */
6243 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
6244 ivideo
->cmdQueueSize
= TURBO_QUEUE_AREA_SIZE
;
6246 if(ivideo
->chip
== XGI_20
) {
6247 ivideo
->cmdQueueSize
= COMMAND_QUEUE_AREA_SIZE_Z7
;
6249 ivideo
->cmdQueueSize
= COMMAND_QUEUE_AREA_SIZE
;
6253 /* Engines are no longer initialized here; this is
6254 * now done after the first mode-switch (if the
6255 * submitted var has its acceleration flags set).
6258 /* Calculate the base of the (unused) hw cursor */
6259 ivideo
->hwcursor_vbase
= ivideo
->video_vbase
6260 + ivideo
->video_size
6261 - ivideo
->cmdQueueSize
6262 - ivideo
->hwcursor_size
;
6263 ivideo
->caps
|= HW_CURSOR_CAP
;
6265 /* Initialize offscreen memory manager */
6266 if((ivideo
->havenoheap
= sisfb_heap_init(ivideo
))) {
6267 printk(KERN_WARNING
"sisfb: Failed to initialize offscreen memory heap\n");
6270 /* Used for clearing the screen only, therefore respect our mem limit */
6271 ivideo
->SiS_Pr
.VideoMemoryAddress
+= ivideo
->video_offset
;
6272 ivideo
->SiS_Pr
.VideoMemorySize
= ivideo
->sisfb_mem
;
6274 ivideo
->vbflags
= 0;
6275 ivideo
->lcddefmodeidx
= DEFAULT_LCDMODE
;
6276 ivideo
->tvdefmodeidx
= DEFAULT_TVMODE
;
6277 ivideo
->defmodeidx
= DEFAULT_MODE
;
6280 if(ivideo
->chip
< XGI_20
) {
6281 if(ivideo
->bios_abase
) {
6282 ivideo
->newrom
= SiSDetermineROMLayout661(&ivideo
->SiS_Pr
);
6286 if((ivideo
->sisfb_mode_idx
< 0) ||
6287 ((sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
]) != 0xFF)) {
6289 sisfb_sense_crt1(ivideo
);
6291 sisfb_get_VB_type(ivideo
);
6293 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
6294 sisfb_detect_VB_connect(ivideo
);
6297 ivideo
->currentvbflags
= ivideo
->vbflags
& (VB_VIDEOBRIDGE
| TV_STANDARD
);
6299 /* Decide on which CRT2 device to use */
6300 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
6301 if(ivideo
->sisfb_crt2type
!= -1) {
6302 if((ivideo
->sisfb_crt2type
== CRT2_LCD
) &&
6303 (ivideo
->vbflags
& CRT2_LCD
)) {
6304 ivideo
->currentvbflags
|= CRT2_LCD
;
6305 } else if(ivideo
->sisfb_crt2type
!= CRT2_LCD
) {
6306 ivideo
->currentvbflags
|= ivideo
->sisfb_crt2type
;
6309 /* Chrontel 700x TV detection often unreliable, therefore
6310 * use a different default order on such machines
6312 if((ivideo
->sisvga_engine
== SIS_300_VGA
) &&
6313 (ivideo
->vbflags2
& VB2_CHRONTEL
)) {
6314 if(ivideo
->vbflags
& CRT2_LCD
)
6315 ivideo
->currentvbflags
|= CRT2_LCD
;
6316 else if(ivideo
->vbflags
& CRT2_TV
)
6317 ivideo
->currentvbflags
|= CRT2_TV
;
6318 else if(ivideo
->vbflags
& CRT2_VGA
)
6319 ivideo
->currentvbflags
|= CRT2_VGA
;
6321 if(ivideo
->vbflags
& CRT2_TV
)
6322 ivideo
->currentvbflags
|= CRT2_TV
;
6323 else if(ivideo
->vbflags
& CRT2_LCD
)
6324 ivideo
->currentvbflags
|= CRT2_LCD
;
6325 else if(ivideo
->vbflags
& CRT2_VGA
)
6326 ivideo
->currentvbflags
|= CRT2_VGA
;
6331 if(ivideo
->vbflags
& CRT2_LCD
) {
6332 sisfb_detect_lcd_type(ivideo
);
6335 sisfb_save_pdc_emi(ivideo
);
6337 if(!ivideo
->sisfb_crt1off
) {
6338 sisfb_handle_ddc(ivideo
, &ivideo
->sisfb_thismonitor
, 0);
6340 if((ivideo
->vbflags2
& VB2_SISTMDSBRIDGE
) &&
6341 (ivideo
->vbflags
& (CRT2_VGA
| CRT2_LCD
))) {
6342 sisfb_handle_ddc(ivideo
, &ivideo
->sisfb_thismonitor
, 1);
6346 if(ivideo
->sisfb_mode_idx
>= 0) {
6347 int bu
= ivideo
->sisfb_mode_idx
;
6348 ivideo
->sisfb_mode_idx
= sisfb_validate_mode(ivideo
,
6349 ivideo
->sisfb_mode_idx
, ivideo
->currentvbflags
);
6350 if(bu
!= ivideo
->sisfb_mode_idx
) {
6351 printk(KERN_ERR
"Mode %dx%dx%d failed validation\n",
6352 sisbios_mode
[bu
].xres
,
6353 sisbios_mode
[bu
].yres
,
6354 sisbios_mode
[bu
].bpp
);
6358 if(ivideo
->sisfb_mode_idx
< 0) {
6359 switch(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
6361 ivideo
->sisfb_mode_idx
= ivideo
->lcddefmodeidx
;
6364 ivideo
->sisfb_mode_idx
= ivideo
->tvdefmodeidx
;
6367 ivideo
->sisfb_mode_idx
= ivideo
->defmodeidx
;
6372 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
6374 if(ivideo
->refresh_rate
!= 0) {
6375 sisfb_search_refresh_rate(ivideo
, ivideo
->refresh_rate
,
6376 ivideo
->sisfb_mode_idx
);
6379 if(ivideo
->rate_idx
== 0) {
6380 ivideo
->rate_idx
= sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
;
6381 ivideo
->refresh_rate
= 60;
6384 if(ivideo
->sisfb_thismonitor
.datavalid
) {
6385 if(!sisfb_verify_rate(ivideo
, &ivideo
->sisfb_thismonitor
,
6386 ivideo
->sisfb_mode_idx
,
6388 ivideo
->refresh_rate
)) {
6389 printk(KERN_INFO
"sisfb: WARNING: Refresh rate "
6390 "exceeds monitor specs!\n");
6394 ivideo
->video_bpp
= sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
;
6395 ivideo
->video_width
= sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
;
6396 ivideo
->video_height
= sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
;
6398 sisfb_set_vparms(ivideo
);
6400 printk(KERN_INFO
"sisfb: Default mode is %dx%dx%d (%dHz)\n",
6401 ivideo
->video_width
, ivideo
->video_height
, ivideo
->video_bpp
,
6402 ivideo
->refresh_rate
);
6404 /* Set up the default var according to chosen default display mode */
6405 ivideo
->default_var
.xres
= ivideo
->default_var
.xres_virtual
= ivideo
->video_width
;
6406 ivideo
->default_var
.yres
= ivideo
->default_var
.yres_virtual
= ivideo
->video_height
;
6407 ivideo
->default_var
.bits_per_pixel
= ivideo
->video_bpp
;
6409 sisfb_bpp_to_var(ivideo
, &ivideo
->default_var
);
6411 ivideo
->default_var
.pixclock
= (u32
) (1000000000 /
6412 sisfb_mode_rate_to_dclock(&ivideo
->SiS_Pr
, ivideo
->mode_no
, ivideo
->rate_idx
));
6414 if(sisfb_mode_rate_to_ddata(&ivideo
->SiS_Pr
, ivideo
->mode_no
,
6415 ivideo
->rate_idx
, &ivideo
->default_var
)) {
6416 if((ivideo
->default_var
.vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
6417 ivideo
->default_var
.pixclock
<<= 1;
6421 if(ivideo
->sisfb_ypan
) {
6422 /* Maximize regardless of sisfb_max at startup */
6423 ivideo
->default_var
.yres_virtual
=
6424 sisfb_calc_maxyres(ivideo
, &ivideo
->default_var
);
6425 if(ivideo
->default_var
.yres_virtual
< ivideo
->default_var
.yres
) {
6426 ivideo
->default_var
.yres_virtual
= ivideo
->default_var
.yres
;
6430 sisfb_calc_pitch(ivideo
, &ivideo
->default_var
);
6433 if(ivideo
->sisfb_accel
) {
6435 #ifdef STUPID_ACCELF_TEXT_SHIT
6436 ivideo
->default_var
.accel_flags
|= FB_ACCELF_TEXT
;
6439 sisfb_initaccel(ivideo
);
6441 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
6442 sis_fb_info
->flags
= FBINFO_HWACCEL_YPAN
|
6443 FBINFO_HWACCEL_XPAN
|
6444 FBINFO_HWACCEL_COPYAREA
|
6445 FBINFO_HWACCEL_FILLRECT
|
6446 ((ivideo
->accel
) ? 0 : FBINFO_HWACCEL_DISABLED
);
6448 sis_fb_info
->var
= ivideo
->default_var
;
6449 sis_fb_info
->fix
= ivideo
->sisfb_fix
;
6450 sis_fb_info
->screen_base
= ivideo
->video_vbase
+ ivideo
->video_offset
;
6451 sis_fb_info
->fbops
= &sisfb_ops
;
6452 sis_fb_info
->pseudo_palette
= ivideo
->pseudo_palette
;
6454 fb_alloc_cmap(&sis_fb_info
->cmap
, 256 , 0);
6456 printk(KERN_DEBUG
"sisfb: Initial vbflags 0x%x\n", (int)ivideo
->vbflags
);
6458 ivideo
->wc_cookie
= arch_phys_wc_add(ivideo
->video_base
,
6459 ivideo
->video_size
);
6460 if(register_framebuffer(sis_fb_info
) < 0) {
6461 printk(KERN_ERR
"sisfb: Fatal error: Failed to register framebuffer\n");
6463 iounmap(ivideo
->mmio_vbase
);
6467 ivideo
->registered
= 1;
6470 ivideo
->next
= card_list
;
6473 printk(KERN_INFO
"sisfb: 2D acceleration is %s, y-panning %s\n",
6474 ivideo
->sisfb_accel
? "enabled" : "disabled",
6475 ivideo
->sisfb_ypan
?
6476 (ivideo
->sisfb_max
? "enabled (auto-max)" :
6477 "enabled (no auto-max)") :
6481 fb_info(sis_fb_info
, "%s frame buffer device version %d.%d.%d\n",
6482 ivideo
->myid
, VER_MAJOR
, VER_MINOR
, VER_LEVEL
);
6484 printk(KERN_INFO
"sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
6486 } /* if mode = "none" */
6491 /*****************************************************/
6492 /* PCI DEVICE HANDLING */
6493 /*****************************************************/
6495 static void sisfb_remove(struct pci_dev
*pdev
)
6497 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
6498 struct fb_info
*sis_fb_info
= ivideo
->memyselfandi
;
6499 int registered
= ivideo
->registered
;
6500 int modechanged
= ivideo
->modechanged
;
6503 iounmap(ivideo
->mmio_vbase
);
6504 iounmap(ivideo
->video_vbase
);
6506 /* Release mem regions */
6507 release_mem_region(ivideo
->video_base
, ivideo
->video_size
);
6508 release_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
);
6510 vfree(ivideo
->bios_abase
);
6512 pci_dev_put(ivideo
->lpcdev
);
6514 pci_dev_put(ivideo
->nbridge
);
6516 arch_phys_wc_del(ivideo
->wc_cookie
);
6518 /* If device was disabled when starting, disable
6521 if(!ivideo
->sisvga_enabled
)
6522 pci_disable_device(pdev
);
6524 /* Unregister the framebuffer */
6525 if(ivideo
->registered
) {
6526 unregister_framebuffer(sis_fb_info
);
6527 framebuffer_release(sis_fb_info
);
6530 /* OK, our ivideo is gone for good from here. */
6532 /* TODO: Restore the initial mode
6533 * This sounds easy but is as good as impossible
6534 * on many machines with SiS chip and video bridge
6535 * since text modes are always set up differently
6536 * from machine to machine. Depends on the type
6537 * of integration between chipset and bridge.
6539 if(registered
&& modechanged
)
6541 "sisfb: Restoring of text mode not supported yet\n");
6544 static struct pci_driver sisfb_driver
= {
6546 .id_table
= sisfb_pci_table
,
6547 .probe
= sisfb_probe
,
6548 .remove
= sisfb_remove
,
6551 static int __init
sisfb_init(void)
6554 char *options
= NULL
;
6557 if (fb_modesetting_disabled("sisfb"))
6561 if(fb_get_options("sisfb", &options
))
6564 sisfb_setup(options
);
6566 return pci_register_driver(&sisfb_driver
);
6570 module_init(sisfb_init
);
6573 /*****************************************************/
6575 /*****************************************************/
6579 static char *mode
= NULL
;
6580 static int vesa
= -1;
6581 static unsigned int rate
= 0;
6582 static unsigned int crt1off
= 1;
6583 static unsigned int mem
= 0;
6584 static char *forcecrt2type
= NULL
;
6585 static int forcecrt1
= -1;
6586 static int pdc
= -1;
6587 static int pdc1
= -1;
6588 static int noaccel
= -1;
6589 static int noypan
= -1;
6590 static int nomax
= -1;
6591 static int userom
= -1;
6592 static int useoem
= -1;
6593 static char *tvstandard
= NULL
;
6594 static int nocrt2rate
= 0;
6595 static int scalelcd
= -1;
6596 static char *specialtiming
= NULL
;
6597 static int lvdshl
= -1;
6598 static int tvxposoffset
= 0, tvyposoffset
= 0;
6599 #if !defined(__i386__) && !defined(__x86_64__)
6600 static int resetcard
= 0;
6601 static int videoram
= 0;
6604 static int __init
sisfb_init_module(void)
6606 sisfb_setdefaultparms();
6609 sisfb_parm_rate
= rate
;
6611 if((scalelcd
== 0) || (scalelcd
== 1))
6612 sisfb_scalelcd
= scalelcd
^ 1;
6614 /* Need to check crt2 type first for fstn/dstn */
6617 sisfb_search_crt2type(forcecrt2type
);
6620 sisfb_search_tvstd(tvstandard
);
6623 sisfb_search_mode(mode
, false);
6625 sisfb_search_vesamode(vesa
, false);
6627 sisfb_crt1off
= (crt1off
== 0) ? 1 : 0;
6629 sisfb_forcecrt1
= forcecrt1
;
6632 else if(forcecrt1
== 0)
6637 else if(noaccel
== 0)
6642 else if(noypan
== 0)
6651 sisfb_parm_mem
= mem
;
6654 sisfb_userom
= userom
;
6657 sisfb_useoem
= useoem
;
6660 sisfb_pdc
= (pdc
& 0x7f);
6663 sisfb_pdca
= (pdc1
& 0x1f);
6665 sisfb_nocrt2rate
= nocrt2rate
;
6668 sisfb_search_specialtiming(specialtiming
);
6670 if((lvdshl
>= 0) && (lvdshl
<= 3))
6671 sisfb_lvdshl
= lvdshl
;
6673 sisfb_tvxposoffset
= tvxposoffset
;
6674 sisfb_tvyposoffset
= tvyposoffset
;
6676 #if !defined(__i386__) && !defined(__x86_64__)
6677 sisfb_resetcard
= (resetcard
) ? 1 : 0;
6679 sisfb_videoram
= videoram
;
6682 return sisfb_init();
6685 static void __exit
sisfb_remove_module(void)
6687 pci_unregister_driver(&sisfb_driver
);
6688 printk(KERN_DEBUG
"sisfb: Module unloaded\n");
6691 module_init(sisfb_init_module
);
6692 module_exit(sisfb_remove_module
);
6694 MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
6695 MODULE_LICENSE("GPL");
6696 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
6698 module_param(mem
, int, 0);
6699 module_param(noaccel
, int, 0);
6700 module_param(noypan
, int, 0);
6701 module_param(nomax
, int, 0);
6702 module_param(userom
, int, 0);
6703 module_param(useoem
, int, 0);
6704 module_param(mode
, charp
, 0);
6705 module_param(vesa
, int, 0);
6706 module_param(rate
, int, 0);
6707 module_param(forcecrt1
, int, 0);
6708 module_param(forcecrt2type
, charp
, 0);
6709 module_param(scalelcd
, int, 0);
6710 module_param(pdc
, int, 0);
6711 module_param(pdc1
, int, 0);
6712 module_param(specialtiming
, charp
, 0);
6713 module_param(lvdshl
, int, 0);
6714 module_param(tvstandard
, charp
, 0);
6715 module_param(tvxposoffset
, int, 0);
6716 module_param(tvyposoffset
, int, 0);
6717 module_param(nocrt2rate
, int, 0);
6718 #if !defined(__i386__) && !defined(__x86_64__)
6719 module_param(resetcard
, int, 0);
6720 module_param(videoram
, int, 0);
6723 MODULE_PARM_DESC(mem
,
6724 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6725 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6726 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6727 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6728 "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6729 "The value is to be specified without 'KB'.\n");
6731 MODULE_PARM_DESC(noaccel
,
6732 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
6735 MODULE_PARM_DESC(noypan
,
6736 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
6737 "will be performed by redrawing the screen. (default: 0)\n");
6739 MODULE_PARM_DESC(nomax
,
6740 "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
6741 "memory for the virtual screen in order to optimize scrolling performance. If\n"
6742 "this is set to anything other than 0, sisfb will not do this and thereby \n"
6743 "enable the user to positively specify a virtual Y size of the screen using\n"
6744 "fbset. (default: 0)\n");
6746 MODULE_PARM_DESC(mode
,
6747 "\nSelects the desired default display mode in the format XxYxDepth,\n"
6748 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
6749 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
6750 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
6752 MODULE_PARM_DESC(vesa
,
6753 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
6754 "0x117 (default: 0x0103)\n");
6756 MODULE_PARM_DESC(rate
,
6757 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
6758 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
6759 "will be ignored (default: 60)\n");
6761 MODULE_PARM_DESC(forcecrt1
,
6762 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
6763 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
6764 "0=CRT1 OFF) (default: [autodetected])\n");
6766 MODULE_PARM_DESC(forcecrt2type
,
6767 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
6768 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
6769 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
6770 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
6771 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
6772 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
6773 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
6774 "depends on the very hardware in use. (default: [autodetected])\n");
6776 MODULE_PARM_DESC(scalelcd
,
6777 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
6778 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
6779 "show black bars around the image, TMDS panels will probably do the scaling\n"
6780 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
6782 MODULE_PARM_DESC(pdc
,
6783 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
6784 "should detect this correctly in most cases; however, sometimes this is not\n"
6785 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
6786 "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
6787 "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
6788 "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
6790 #ifdef CONFIG_FB_SIS_315
6791 MODULE_PARM_DESC(pdc1
,
6792 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
6793 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
6794 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
6795 "implemented yet.\n");
6798 MODULE_PARM_DESC(specialtiming
,
6799 "\nPlease refer to documentation for more information on this option.\n");
6801 MODULE_PARM_DESC(lvdshl
,
6802 "\nPlease refer to documentation for more information on this option.\n");
6804 MODULE_PARM_DESC(tvstandard
,
6805 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
6806 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
6808 MODULE_PARM_DESC(tvxposoffset
,
6809 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
6812 MODULE_PARM_DESC(tvyposoffset
,
6813 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
6816 MODULE_PARM_DESC(nocrt2rate
,
6817 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
6818 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
6820 #if !defined(__i386__) && !defined(__x86_64__)
6821 #ifdef CONFIG_FB_SIS_300
6822 MODULE_PARM_DESC(resetcard
,
6823 "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
6824 "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
6825 "currently). Default: 0\n");
6827 MODULE_PARM_DESC(videoram
,
6828 "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
6829 "some non-x86 architectures where the memory auto detection fails. Only\n"
6830 "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
6834 #endif /* /MODULE */
6836 /* _GPL only for new symbols. */
6837 EXPORT_SYMBOL(sis_malloc
);
6838 EXPORT_SYMBOL(sis_free
);
6839 EXPORT_SYMBOL_GPL(sis_malloc_new
);
6840 EXPORT_SYMBOL_GPL(sis_free_new
);