2 * SiS 300/540/630[S]/730[S],
3 * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
5 * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
7 * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the named License,
12 * or any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
23 * Author: Thomas Winischhofer <thomas@winischhofer.net>
25 * Author of (practically wiped) code base:
27 * Copyright (C) 1999 Silicon Integrated Systems, Inc.
29 * See http://www.winischhofer.net/ for more information and updates
31 * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver,
32 * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
36 #include <linux/module.h>
37 #include <linux/moduleparam.h>
38 #include <linux/kernel.h>
39 #include <linux/spinlock.h>
40 #include <linux/errno.h>
41 #include <linux/string.h>
43 #include <linux/screen_info.h>
44 #include <linux/slab.h>
46 #include <linux/selection.h>
47 #include <linux/ioport.h>
48 #include <linux/init.h>
49 #include <linux/pci.h>
50 #include <linux/vmalloc.h>
51 #include <linux/capability.h>
53 #include <linux/types.h>
54 #include <linux/uaccess.h>
63 #if !defined(CONFIG_FB_SIS_300) && !defined(CONFIG_FB_SIS_315)
64 #warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
65 #warning sisfb will not work!
68 static void sisfb_handle_command(struct sis_video_info
*ivideo
,
69 struct sisfb_cmd
*sisfb_command
);
71 /* ------------------ Internal helper routines ----------------- */
74 sisfb_setdefaultparms(void)
92 sisfb_specialtiming
= CUT_NONE
;
98 sisfb_tvxposoffset
= 0;
99 sisfb_tvyposoffset
= 0;
100 sisfb_nocrt2rate
= 0;
101 #if !defined(__i386__) && !defined(__x86_64__)
107 /* ------------- Parameter parsing -------------- */
109 static void sisfb_search_vesamode(unsigned int vesamode
, bool quiet
)
113 /* We don't know the hardware specs yet and there is no ivideo */
117 printk(KERN_ERR
"sisfb: Invalid mode. Using default.\n");
119 sisfb_mode_idx
= DEFAULT_MODE
;
124 vesamode
&= 0x1dff; /* Clean VESA mode number from other flags */
126 while(sisbios_mode
[i
++].mode_no
[0] != 0) {
127 if( (sisbios_mode
[i
-1].vesa_mode_no_1
== vesamode
) ||
128 (sisbios_mode
[i
-1].vesa_mode_no_2
== vesamode
) ) {
130 if(sisbios_mode
[i
-1].mode_no
[1] == 0x50 ||
131 sisbios_mode
[i
-1].mode_no
[1] == 0x56 ||
132 sisbios_mode
[i
-1].mode_no
[1] == 0x53)
135 if(sisbios_mode
[i
-1].mode_no
[1] == 0x5a ||
136 sisbios_mode
[i
-1].mode_no
[1] == 0x5b)
139 sisfb_mode_idx
= i
- 1;
145 printk(KERN_ERR
"sisfb: Invalid VESA mode 0x%x'\n", vesamode
);
148 static void sisfb_search_mode(char *name
, bool quiet
)
150 unsigned int j
= 0, xres
= 0, yres
= 0, depth
= 0, rate
= 0;
152 char strbuf
[16], strbuf1
[20];
153 char *nameptr
= name
;
155 /* We don't know the hardware specs yet and there is no ivideo */
159 printk(KERN_ERR
"sisfb: Internal error, using default mode.\n");
161 sisfb_mode_idx
= DEFAULT_MODE
;
165 if(!strnicmp(name
, sisbios_mode
[MODE_INDEX_NONE
].name
, strlen(name
))) {
167 printk(KERN_ERR
"sisfb: Mode 'none' not supported anymore. Using default.\n");
169 sisfb_mode_idx
= DEFAULT_MODE
;
173 if(strlen(name
) <= 19) {
174 strcpy(strbuf1
, name
);
175 for(i
= 0; i
< strlen(strbuf1
); i
++) {
176 if(strbuf1
[i
] < '0' || strbuf1
[i
] > '9') strbuf1
[i
] = ' ';
179 /* This does some fuzzy mode naming detection */
180 if(sscanf(strbuf1
, "%u %u %u %u", &xres
, &yres
, &depth
, &rate
) == 4) {
181 if((rate
<= 32) || (depth
> 32)) {
182 j
= rate
; rate
= depth
; depth
= j
;
184 sprintf(strbuf
, "%ux%ux%u", xres
, yres
, depth
);
186 sisfb_parm_rate
= rate
;
187 } else if(sscanf(strbuf1
, "%u %u %u", &xres
, &yres
, &depth
) == 3) {
188 sprintf(strbuf
, "%ux%ux%u", xres
, yres
, depth
);
192 if((sscanf(strbuf1
, "%u %u", &xres
, &yres
) == 2) && (xres
!= 0)) {
193 sprintf(strbuf
, "%ux%ux8", xres
, yres
);
196 sisfb_search_vesamode(simple_strtoul(name
, NULL
, 0), quiet
);
203 while(sisbios_mode
[i
].mode_no
[0] != 0) {
204 if(!strnicmp(nameptr
, sisbios_mode
[i
++].name
, strlen(nameptr
))) {
206 if(sisbios_mode
[i
-1].mode_no
[1] == 0x50 ||
207 sisbios_mode
[i
-1].mode_no
[1] == 0x56 ||
208 sisbios_mode
[i
-1].mode_no
[1] == 0x53)
211 if(sisbios_mode
[i
-1].mode_no
[1] == 0x5a ||
212 sisbios_mode
[i
-1].mode_no
[1] == 0x5b)
215 sisfb_mode_idx
= i
- 1;
222 printk(KERN_ERR
"sisfb: Invalid mode '%s'\n", nameptr
);
226 static void sisfb_get_vga_mode_from_kernel(void)
230 int mydepth
= screen_info
.lfb_depth
;
232 if(screen_info
.orig_video_isVGA
!= VIDEO_TYPE_VLFB
) return;
234 if( (screen_info
.lfb_width
>= 320) && (screen_info
.lfb_width
<= 2048) &&
235 (screen_info
.lfb_height
>= 200) && (screen_info
.lfb_height
<= 1536) &&
236 (mydepth
>= 8) && (mydepth
<= 32) ) {
238 if(mydepth
== 24) mydepth
= 32;
240 sprintf(mymode
, "%ux%ux%u", screen_info
.lfb_width
,
241 screen_info
.lfb_height
,
245 "sisfb: Using vga mode %s pre-set by kernel as default\n",
248 sisfb_search_mode(mymode
, true);
256 sisfb_search_crt2type(const char *name
)
260 /* We don't know the hardware specs yet and there is no ivideo */
262 if(name
== NULL
) return;
264 while(sis_crt2type
[i
].type_no
!= -1) {
265 if(!strnicmp(name
, sis_crt2type
[i
].name
, strlen(sis_crt2type
[i
].name
))) {
266 sisfb_crt2type
= sis_crt2type
[i
].type_no
;
267 sisfb_tvplug
= sis_crt2type
[i
].tvplug_no
;
268 sisfb_crt2flags
= sis_crt2type
[i
].flags
;
274 sisfb_dstn
= (sisfb_crt2flags
& FL_550_DSTN
) ? 1 : 0;
275 sisfb_fstn
= (sisfb_crt2flags
& FL_550_FSTN
) ? 1 : 0;
277 if(sisfb_crt2type
< 0)
278 printk(KERN_ERR
"sisfb: Invalid CRT2 type: %s\n", name
);
282 sisfb_search_tvstd(const char *name
)
286 /* We don't know the hardware specs yet and there is no ivideo */
291 while(sis_tvtype
[i
].type_no
!= -1) {
292 if(!strnicmp(name
, sis_tvtype
[i
].name
, strlen(sis_tvtype
[i
].name
))) {
293 sisfb_tvstd
= sis_tvtype
[i
].type_no
;
301 sisfb_search_specialtiming(const char *name
)
306 /* We don't know the hardware specs yet and there is no ivideo */
311 if(!strnicmp(name
, "none", 4)) {
312 sisfb_specialtiming
= CUT_FORCENONE
;
313 printk(KERN_DEBUG
"sisfb: Special timing disabled\n");
315 while(mycustomttable
[i
].chipID
!= 0) {
316 if(!strnicmp(name
,mycustomttable
[i
].optionName
,
317 strlen(mycustomttable
[i
].optionName
))) {
318 sisfb_specialtiming
= mycustomttable
[i
].SpecialID
;
320 printk(KERN_INFO
"sisfb: Special timing for %s %s forced (\"%s\")\n",
321 mycustomttable
[i
].vendorName
,
322 mycustomttable
[i
].cardName
,
323 mycustomttable
[i
].optionName
);
329 printk(KERN_WARNING
"sisfb: Invalid SpecialTiming parameter, valid are:");
330 printk(KERN_WARNING
"\t\"none\" (to disable special timings)\n");
332 while(mycustomttable
[i
].chipID
!= 0) {
333 printk(KERN_WARNING
"\t\"%s\" (for %s %s)\n",
334 mycustomttable
[i
].optionName
,
335 mycustomttable
[i
].vendorName
,
336 mycustomttable
[i
].cardName
);
343 /* ----------- Various detection routines ----------- */
345 static void sisfb_detect_custom_timing(struct sis_video_info
*ivideo
)
347 unsigned char *biosver
= NULL
;
348 unsigned char *biosdate
= NULL
;
353 if(ivideo
->SiS_Pr
.UseROM
) {
354 biosver
= ivideo
->SiS_Pr
.VirtualRomBase
+ 0x06;
355 biosdate
= ivideo
->SiS_Pr
.VirtualRomBase
+ 0x2c;
356 for(i
= 0; i
< 32768; i
++)
357 chksum
+= ivideo
->SiS_Pr
.VirtualRomBase
[i
];
362 if( (mycustomttable
[i
].chipID
== ivideo
->chip
) &&
363 ((!strlen(mycustomttable
[i
].biosversion
)) ||
364 (ivideo
->SiS_Pr
.UseROM
&&
365 (!strncmp(mycustomttable
[i
].biosversion
, biosver
,
366 strlen(mycustomttable
[i
].biosversion
))))) &&
367 ((!strlen(mycustomttable
[i
].biosdate
)) ||
368 (ivideo
->SiS_Pr
.UseROM
&&
369 (!strncmp(mycustomttable
[i
].biosdate
, biosdate
,
370 strlen(mycustomttable
[i
].biosdate
))))) &&
371 ((!mycustomttable
[i
].bioschksum
) ||
372 (ivideo
->SiS_Pr
.UseROM
&&
373 (mycustomttable
[i
].bioschksum
== chksum
))) &&
374 (mycustomttable
[i
].pcisubsysvendor
== ivideo
->subsysvendor
) &&
375 (mycustomttable
[i
].pcisubsyscard
== ivideo
->subsysdevice
) ) {
377 for(j
= 0; j
< 5; j
++) {
378 if(mycustomttable
[i
].biosFootprintAddr
[j
]) {
379 if(ivideo
->SiS_Pr
.UseROM
) {
380 if(ivideo
->SiS_Pr
.VirtualRomBase
[mycustomttable
[i
].biosFootprintAddr
[j
]] !=
381 mycustomttable
[i
].biosFootprintData
[j
]) {
389 ivideo
->SiS_Pr
.SiS_CustomT
= mycustomttable
[i
].SpecialID
;
390 printk(KERN_DEBUG
"sisfb: Identified [%s %s], special timing applies\n",
391 mycustomttable
[i
].vendorName
,
392 mycustomttable
[i
].cardName
);
393 printk(KERN_DEBUG
"sisfb: [specialtiming parameter name: %s]\n",
394 mycustomttable
[i
].optionName
);
399 } while(mycustomttable
[i
].chipID
);
402 static bool sisfb_interpret_edid(struct sisfb_monitor
*monitor
, u8
*buffer
)
404 int i
, j
, xres
, yres
, refresh
, index
;
407 if(buffer
[0] != 0x00 || buffer
[1] != 0xff ||
408 buffer
[2] != 0xff || buffer
[3] != 0xff ||
409 buffer
[4] != 0xff || buffer
[5] != 0xff ||
410 buffer
[6] != 0xff || buffer
[7] != 0x00) {
411 printk(KERN_DEBUG
"sisfb: Bad EDID header\n");
415 if(buffer
[0x12] != 0x01) {
416 printk(KERN_INFO
"sisfb: EDID version %d not supported\n",
421 monitor
->feature
= buffer
[0x18];
423 if(!(buffer
[0x14] & 0x80)) {
424 if(!(buffer
[0x14] & 0x08)) {
426 "sisfb: WARNING: Monitor does not support separate syncs\n");
430 if(buffer
[0x13] >= 0x01) {
431 /* EDID V1 rev 1 and 2: Search for monitor descriptor
436 if(buffer
[j
] == 0x00 && buffer
[j
+ 1] == 0x00 &&
437 buffer
[j
+ 2] == 0x00 && buffer
[j
+ 3] == 0xfd &&
438 buffer
[j
+ 4] == 0x00) {
439 monitor
->hmin
= buffer
[j
+ 7];
440 monitor
->hmax
= buffer
[j
+ 8];
441 monitor
->vmin
= buffer
[j
+ 5];
442 monitor
->vmax
= buffer
[j
+ 6];
443 monitor
->dclockmax
= buffer
[j
+ 9] * 10 * 1000;
444 monitor
->datavalid
= true;
451 if(!monitor
->datavalid
) {
452 /* Otherwise: Get a range from the list of supported
453 * Estabished Timings. This is not entirely accurate,
454 * because fixed frequency monitors are not supported
457 monitor
->hmin
= 65535; monitor
->hmax
= 0;
458 monitor
->vmin
= 65535; monitor
->vmax
= 0;
459 monitor
->dclockmax
= 0;
460 emodes
= buffer
[0x23] | (buffer
[0x24] << 8) | (buffer
[0x25] << 16);
461 for(i
= 0; i
< 13; i
++) {
462 if(emodes
& sisfb_ddcsmodes
[i
].mask
) {
463 if(monitor
->hmin
> sisfb_ddcsmodes
[i
].h
) monitor
->hmin
= sisfb_ddcsmodes
[i
].h
;
464 if(monitor
->hmax
< sisfb_ddcsmodes
[i
].h
) monitor
->hmax
= sisfb_ddcsmodes
[i
].h
+ 1;
465 if(monitor
->vmin
> sisfb_ddcsmodes
[i
].v
) monitor
->vmin
= sisfb_ddcsmodes
[i
].v
;
466 if(monitor
->vmax
< sisfb_ddcsmodes
[i
].v
) monitor
->vmax
= sisfb_ddcsmodes
[i
].v
;
467 if(monitor
->dclockmax
< sisfb_ddcsmodes
[i
].d
) monitor
->dclockmax
= sisfb_ddcsmodes
[i
].d
;
471 for(i
= 0; i
< 8; i
++) {
472 xres
= (buffer
[index
] + 31) * 8;
473 switch(buffer
[index
+ 1] & 0xc0) {
474 case 0xc0: yres
= (xres
* 9) / 16; break;
475 case 0x80: yres
= (xres
* 4) / 5; break;
476 case 0x40: yres
= (xres
* 3) / 4; break;
477 default: yres
= xres
; break;
479 refresh
= (buffer
[index
+ 1] & 0x3f) + 60;
480 if((xres
>= 640) && (yres
>= 480)) {
481 for(j
= 0; j
< 8; j
++) {
482 if((xres
== sisfb_ddcfmodes
[j
].x
) &&
483 (yres
== sisfb_ddcfmodes
[j
].y
) &&
484 (refresh
== sisfb_ddcfmodes
[j
].v
)) {
485 if(monitor
->hmin
> sisfb_ddcfmodes
[j
].h
) monitor
->hmin
= sisfb_ddcfmodes
[j
].h
;
486 if(monitor
->hmax
< sisfb_ddcfmodes
[j
].h
) monitor
->hmax
= sisfb_ddcfmodes
[j
].h
+ 1;
487 if(monitor
->vmin
> sisfb_ddcsmodes
[j
].v
) monitor
->vmin
= sisfb_ddcsmodes
[j
].v
;
488 if(monitor
->vmax
< sisfb_ddcsmodes
[j
].v
) monitor
->vmax
= sisfb_ddcsmodes
[j
].v
;
489 if(monitor
->dclockmax
< sisfb_ddcsmodes
[j
].d
) monitor
->dclockmax
= sisfb_ddcsmodes
[j
].d
;
495 if((monitor
->hmin
<= monitor
->hmax
) && (monitor
->vmin
<= monitor
->vmax
)) {
496 monitor
->datavalid
= true;
500 return monitor
->datavalid
;
503 static void sisfb_handle_ddc(struct sis_video_info
*ivideo
,
504 struct sisfb_monitor
*monitor
, int crtno
)
506 unsigned short temp
, i
, realcrtno
= crtno
;
507 unsigned char buffer
[256];
509 monitor
->datavalid
= false;
512 if(ivideo
->vbflags
& CRT2_LCD
) realcrtno
= 1;
513 else if(ivideo
->vbflags
& CRT2_VGA
) realcrtno
= 2;
517 if((ivideo
->sisfb_crt1off
) && (!crtno
))
520 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
521 realcrtno
, 0, &buffer
[0], ivideo
->vbflags2
);
522 if((!temp
) || (temp
== 0xffff)) {
523 printk(KERN_INFO
"sisfb: CRT%d DDC probing failed\n", crtno
+ 1);
526 printk(KERN_INFO
"sisfb: CRT%d DDC supported\n", crtno
+ 1);
527 printk(KERN_INFO
"sisfb: CRT%d DDC level: %s%s%s%s\n",
529 (temp
& 0x1a) ? "" : "[none of the supported]",
530 (temp
& 0x02) ? "2 " : "",
531 (temp
& 0x08) ? "D&P" : "",
532 (temp
& 0x10) ? "FPDI-2" : "");
534 i
= 3; /* Number of retrys */
536 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
537 realcrtno
, 1, &buffer
[0], ivideo
->vbflags2
);
538 } while((temp
) && i
--);
540 if(sisfb_interpret_edid(monitor
, &buffer
[0])) {
541 printk(KERN_INFO
"sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
542 monitor
->hmin
, monitor
->hmax
, monitor
->vmin
, monitor
->vmax
,
543 monitor
->dclockmax
/ 1000);
545 printk(KERN_INFO
"sisfb: CRT%d DDC EDID corrupt\n", crtno
+ 1);
548 printk(KERN_INFO
"sisfb: CRT%d DDC reading failed\n", crtno
+ 1);
551 printk(KERN_INFO
"sisfb: VESA D&P and FPDI-2 not supported yet\n");
556 /* -------------- Mode validation --------------- */
559 sisfb_verify_rate(struct sis_video_info
*ivideo
, struct sisfb_monitor
*monitor
,
560 int mode_idx
, int rate_idx
, int rate
)
563 unsigned int dclock
, hsync
;
565 if(!monitor
->datavalid
)
571 /* Skip for 320x200, 320x240, 640x400 */
572 switch(sisbios_mode
[mode_idx
].mode_no
[ivideo
->mni
]) {
583 #ifdef CONFIG_FB_SIS_315
586 if(ivideo
->sisvga_engine
== SIS_315_VGA
) return true;
590 if(rate
< (monitor
->vmin
- 1))
592 if(rate
> (monitor
->vmax
+ 1))
595 if(sisfb_gettotalfrommode(&ivideo
->SiS_Pr
,
596 sisbios_mode
[mode_idx
].mode_no
[ivideo
->mni
],
597 &htotal
, &vtotal
, rate_idx
)) {
598 dclock
= (htotal
* vtotal
* rate
) / 1000;
599 if(dclock
> (monitor
->dclockmax
+ 1000))
601 hsync
= dclock
/ htotal
;
602 if(hsync
< (monitor
->hmin
- 1))
604 if(hsync
> (monitor
->hmax
+ 1))
613 sisfb_validate_mode(struct sis_video_info
*ivideo
, int myindex
, u32 vbflags
)
615 u16 xres
=0, yres
, myres
;
617 #ifdef CONFIG_FB_SIS_300
618 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
619 if(!(sisbios_mode
[myindex
].chipset
& MD_SIS300
))
623 #ifdef CONFIG_FB_SIS_315
624 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
625 if(!(sisbios_mode
[myindex
].chipset
& MD_SIS315
))
630 myres
= sisbios_mode
[myindex
].yres
;
632 switch(vbflags
& VB_DISPTYPE_DISP2
) {
635 xres
= ivideo
->lcdxres
; yres
= ivideo
->lcdyres
;
637 if((ivideo
->SiS_Pr
.SiS_CustomT
!= CUT_PANEL848
) &&
638 (ivideo
->SiS_Pr
.SiS_CustomT
!= CUT_PANEL856
)) {
639 if(sisbios_mode
[myindex
].xres
> xres
)
645 if(ivideo
->sisfb_fstn
) {
646 if(sisbios_mode
[myindex
].xres
== 320) {
648 switch(sisbios_mode
[myindex
].mode_no
[1]) {
649 case 0x50: myindex
= MODE_FSTN_8
; break;
650 case 0x56: myindex
= MODE_FSTN_16
; break;
651 case 0x53: return -1;
657 if(SiS_GetModeID_LCD(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
658 sisbios_mode
[myindex
].yres
, 0, ivideo
->sisfb_fstn
,
659 ivideo
->SiS_Pr
.SiS_CustomT
, xres
, yres
, ivideo
->vbflags2
) < 0x14) {
665 if(SiS_GetModeID_TV(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
666 sisbios_mode
[myindex
].yres
, 0, ivideo
->vbflags2
) < 0x14) {
672 if(SiS_GetModeID_VGA2(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
673 sisbios_mode
[myindex
].yres
, 0, ivideo
->vbflags2
) < 0x14) {
683 sisfb_search_refresh_rate(struct sis_video_info
*ivideo
, unsigned int rate
, int mode_idx
)
686 u16 xres
= sisbios_mode
[mode_idx
].xres
;
687 u16 yres
= sisbios_mode
[mode_idx
].yres
;
689 ivideo
->rate_idx
= 0;
690 while((sisfb_vrate
[i
].idx
!= 0) && (sisfb_vrate
[i
].xres
<= xres
)) {
691 if((sisfb_vrate
[i
].xres
== xres
) && (sisfb_vrate
[i
].yres
== yres
)) {
692 if(sisfb_vrate
[i
].refresh
== rate
) {
693 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
695 } else if(sisfb_vrate
[i
].refresh
> rate
) {
696 if((sisfb_vrate
[i
].refresh
- rate
) <= 3) {
697 DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
698 rate
, sisfb_vrate
[i
].refresh
);
699 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
700 ivideo
->refresh_rate
= sisfb_vrate
[i
].refresh
;
701 } else if((sisfb_vrate
[i
].idx
!= 1) &&
702 ((rate
- sisfb_vrate
[i
-1].refresh
) <= 2)) {
703 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
704 rate
, sisfb_vrate
[i
-1].refresh
);
705 ivideo
->rate_idx
= sisfb_vrate
[i
-1].idx
;
706 ivideo
->refresh_rate
= sisfb_vrate
[i
-1].refresh
;
709 } else if((rate
- sisfb_vrate
[i
].refresh
) <= 2) {
710 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
711 rate
, sisfb_vrate
[i
].refresh
);
712 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
718 if(ivideo
->rate_idx
> 0) {
719 return ivideo
->rate_idx
;
721 printk(KERN_INFO
"sisfb: Unsupported rate %d for %dx%d\n",
728 sisfb_bridgeisslave(struct sis_video_info
*ivideo
)
732 if(!(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
))
735 P1_00
= SiS_GetReg(SISPART1
, 0x00);
736 if( ((ivideo
->sisvga_engine
== SIS_300_VGA
) && (P1_00
& 0xa0) == 0x20) ||
737 ((ivideo
->sisvga_engine
== SIS_315_VGA
) && (P1_00
& 0x50) == 0x10) ) {
745 sisfballowretracecrt1(struct sis_video_info
*ivideo
)
749 temp
= SiS_GetReg(SISCR
, 0x17);
753 temp
= SiS_GetReg(SISSR
, 0x1f);
761 sisfbcheckvretracecrt1(struct sis_video_info
*ivideo
)
763 if(!sisfballowretracecrt1(ivideo
))
766 if (SiS_GetRegByte(SISINPSTAT
) & 0x08)
773 sisfbwaitretracecrt1(struct sis_video_info
*ivideo
)
777 if(!sisfballowretracecrt1(ivideo
))
781 while ((!(SiS_GetRegByte(SISINPSTAT
) & 0x08)) && --watchdog
);
783 while ((SiS_GetRegByte(SISINPSTAT
) & 0x08) && --watchdog
);
787 sisfbcheckvretracecrt2(struct sis_video_info
*ivideo
)
789 unsigned char temp
, reg
;
791 switch(ivideo
->sisvga_engine
) {
792 case SIS_300_VGA
: reg
= 0x25; break;
793 case SIS_315_VGA
: reg
= 0x30; break;
794 default: return false;
797 temp
= SiS_GetReg(SISPART1
, reg
);
805 sisfb_CheckVBRetrace(struct sis_video_info
*ivideo
)
807 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
808 if(!sisfb_bridgeisslave(ivideo
)) {
809 return sisfbcheckvretracecrt2(ivideo
);
812 return sisfbcheckvretracecrt1(ivideo
);
816 sisfb_setupvbblankflags(struct sis_video_info
*ivideo
, u32
*vcount
, u32
*hcount
)
818 u8 idx
, reg1
, reg2
, reg3
, reg4
;
821 (*vcount
) = (*hcount
) = 0;
823 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) && (!(sisfb_bridgeisslave(ivideo
)))) {
825 ret
|= (FB_VBLANK_HAVE_VSYNC
|
826 FB_VBLANK_HAVE_HBLANK
|
827 FB_VBLANK_HAVE_VBLANK
|
828 FB_VBLANK_HAVE_VCOUNT
|
829 FB_VBLANK_HAVE_HCOUNT
);
830 switch(ivideo
->sisvga_engine
) {
831 case SIS_300_VGA
: idx
= 0x25; break;
833 case SIS_315_VGA
: idx
= 0x30; break;
835 reg1
= SiS_GetReg(SISPART1
, (idx
+0)); /* 30 */
836 reg2
= SiS_GetReg(SISPART1
, (idx
+1)); /* 31 */
837 reg3
= SiS_GetReg(SISPART1
, (idx
+2)); /* 32 */
838 reg4
= SiS_GetReg(SISPART1
, (idx
+3)); /* 33 */
839 if(reg1
& 0x01) ret
|= FB_VBLANK_VBLANKING
;
840 if(reg1
& 0x02) ret
|= FB_VBLANK_VSYNCING
;
841 if(reg4
& 0x80) ret
|= FB_VBLANK_HBLANKING
;
842 (*vcount
) = reg3
| ((reg4
& 0x70) << 4);
843 (*hcount
) = reg2
| ((reg4
& 0x0f) << 8);
845 } else if(sisfballowretracecrt1(ivideo
)) {
847 ret
|= (FB_VBLANK_HAVE_VSYNC
|
848 FB_VBLANK_HAVE_VBLANK
|
849 FB_VBLANK_HAVE_VCOUNT
|
850 FB_VBLANK_HAVE_HCOUNT
);
851 reg1
= SiS_GetRegByte(SISINPSTAT
);
852 if(reg1
& 0x08) ret
|= FB_VBLANK_VSYNCING
;
853 if(reg1
& 0x01) ret
|= FB_VBLANK_VBLANKING
;
854 reg1
= SiS_GetReg(SISCR
, 0x20);
855 reg1
= SiS_GetReg(SISCR
, 0x1b);
856 reg2
= SiS_GetReg(SISCR
, 0x1c);
857 reg3
= SiS_GetReg(SISCR
, 0x1d);
858 (*vcount
) = reg2
| ((reg3
& 0x07) << 8);
859 (*hcount
) = (reg1
| ((reg3
& 0x10) << 4)) << 3;
866 sisfb_myblank(struct sis_video_info
*ivideo
, int blank
)
868 u8 sr01
, sr11
, sr1f
, cr63
=0, p2_0
, p1_13
;
869 bool backlight
= true;
872 case FB_BLANK_UNBLANK
: /* on */
881 case FB_BLANK_NORMAL
: /* blank */
890 case FB_BLANK_VSYNC_SUSPEND
: /* no vsync */
899 case FB_BLANK_HSYNC_SUSPEND
: /* no hsync */
908 case FB_BLANK_POWERDOWN
: /* off */
921 if(ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
) {
923 if( (!ivideo
->sisfb_thismonitor
.datavalid
) ||
924 ((ivideo
->sisfb_thismonitor
.datavalid
) &&
925 (ivideo
->sisfb_thismonitor
.feature
& 0xe0))) {
927 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
928 SiS_SetRegANDOR(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, 0xbf, cr63
);
931 if(!(sisfb_bridgeisslave(ivideo
))) {
932 SiS_SetRegANDOR(SISSR
, 0x01, ~0x20, sr01
);
933 SiS_SetRegANDOR(SISSR
, 0x1f, 0x3f, sr1f
);
939 if(ivideo
->currentvbflags
& CRT2_LCD
) {
941 if(ivideo
->vbflags2
& VB2_SISLVDSBRIDGE
) {
943 SiS_SiS30xBLOn(&ivideo
->SiS_Pr
);
945 SiS_SiS30xBLOff(&ivideo
->SiS_Pr
);
947 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
948 #ifdef CONFIG_FB_SIS_315
949 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
951 SiS_Chrontel701xBLOn(&ivideo
->SiS_Pr
);
953 SiS_Chrontel701xBLOff(&ivideo
->SiS_Pr
);
959 if(((ivideo
->sisvga_engine
== SIS_300_VGA
) &&
960 (ivideo
->vbflags2
& (VB2_301
|VB2_30xBDH
|VB2_LVDS
))) ||
961 ((ivideo
->sisvga_engine
== SIS_315_VGA
) &&
962 ((ivideo
->vbflags2
& (VB2_LVDS
| VB2_CHRONTEL
)) == VB2_LVDS
))) {
963 SiS_SetRegANDOR(SISSR
, 0x11, ~0x0c, sr11
);
966 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
967 if((ivideo
->vbflags2
& VB2_30xB
) &&
968 (!(ivideo
->vbflags2
& VB2_30xBDH
))) {
969 SiS_SetRegANDOR(SISPART1
, 0x13, 0x3f, p1_13
);
971 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
972 if((ivideo
->vbflags2
& VB2_30xB
) &&
973 (!(ivideo
->vbflags2
& VB2_30xBDH
))) {
974 SiS_SetRegANDOR(SISPART2
, 0x00, 0x1f, p2_0
);
978 } else if(ivideo
->currentvbflags
& CRT2_VGA
) {
980 if(ivideo
->vbflags2
& VB2_30xB
) {
981 SiS_SetRegANDOR(SISPART2
, 0x00, 0x1f, p2_0
);
989 /* ------------- Callbacks from init.c/init301.c -------------- */
991 #ifdef CONFIG_FB_SIS_300
993 sisfb_read_nbridge_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
)
995 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
998 pci_read_config_dword(ivideo
->nbridge
, reg
, &val
);
999 return (unsigned int)val
;
1003 sisfb_write_nbridge_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
, unsigned int val
)
1005 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1007 pci_write_config_dword(ivideo
->nbridge
, reg
, (u32
)val
);
1011 sisfb_read_lpc_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
)
1013 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1016 if(!ivideo
->lpcdev
) return 0;
1018 pci_read_config_dword(ivideo
->lpcdev
, reg
, &val
);
1019 return (unsigned int)val
;
1023 #ifdef CONFIG_FB_SIS_315
1025 sisfb_write_nbridge_pci_byte(struct SiS_Private
*SiS_Pr
, int reg
, unsigned char val
)
1027 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1029 pci_write_config_byte(ivideo
->nbridge
, reg
, (u8
)val
);
1033 sisfb_read_mio_pci_word(struct SiS_Private
*SiS_Pr
, int reg
)
1035 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1038 if(!ivideo
->lpcdev
) return 0;
1040 pci_read_config_word(ivideo
->lpcdev
, reg
, &val
);
1041 return (unsigned int)val
;
1045 /* ----------- FBDev related routines for all series ----------- */
1048 sisfb_get_cmap_len(const struct fb_var_screeninfo
*var
)
1050 return (var
->bits_per_pixel
== 8) ? 256 : 16;
1054 sisfb_set_vparms(struct sis_video_info
*ivideo
)
1056 switch(ivideo
->video_bpp
) {
1058 ivideo
->DstColor
= 0x0000;
1059 ivideo
->SiS310_AccelDepth
= 0x00000000;
1060 ivideo
->video_cmap_len
= 256;
1063 ivideo
->DstColor
= 0x8000;
1064 ivideo
->SiS310_AccelDepth
= 0x00010000;
1065 ivideo
->video_cmap_len
= 16;
1068 ivideo
->DstColor
= 0xC000;
1069 ivideo
->SiS310_AccelDepth
= 0x00020000;
1070 ivideo
->video_cmap_len
= 16;
1073 ivideo
->video_cmap_len
= 16;
1074 printk(KERN_ERR
"sisfb: Unsupported depth %d", ivideo
->video_bpp
);
1080 sisfb_calc_maxyres(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1082 int maxyres
= ivideo
->sisfb_mem
/ (var
->xres_virtual
* (var
->bits_per_pixel
>> 3));
1084 if(maxyres
> 32767) maxyres
= 32767;
1090 sisfb_calc_pitch(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1092 ivideo
->video_linelength
= var
->xres_virtual
* (var
->bits_per_pixel
>> 3);
1093 ivideo
->scrnpitchCRT1
= ivideo
->video_linelength
;
1094 if(!(ivideo
->currentvbflags
& CRT1_LCDA
)) {
1095 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1096 ivideo
->scrnpitchCRT1
<<= 1;
1102 sisfb_set_pitch(struct sis_video_info
*ivideo
)
1104 bool isslavemode
= false;
1105 unsigned short HDisplay1
= ivideo
->scrnpitchCRT1
>> 3;
1106 unsigned short HDisplay2
= ivideo
->video_linelength
>> 3;
1108 if(sisfb_bridgeisslave(ivideo
)) isslavemode
= true;
1110 /* We need to set pitch for CRT1 if bridge is in slave mode, too */
1111 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP1
) || (isslavemode
)) {
1112 SiS_SetReg(SISCR
, 0x13, (HDisplay1
& 0xFF));
1113 SiS_SetRegANDOR(SISSR
, 0x0E, 0xF0, (HDisplay1
>> 8));
1116 /* We must not set the pitch for CRT2 if bridge is in slave mode */
1117 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) && (!isslavemode
)) {
1118 SiS_SetRegOR(SISPART1
, ivideo
->CRT2_write_enable
, 0x01);
1119 SiS_SetReg(SISPART1
, 0x07, (HDisplay2
& 0xFF));
1120 SiS_SetRegANDOR(SISPART1
, 0x09, 0xF0, (HDisplay2
>> 8));
1125 sisfb_bpp_to_var(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1127 ivideo
->video_cmap_len
= sisfb_get_cmap_len(var
);
1129 switch(var
->bits_per_pixel
) {
1131 var
->red
.offset
= var
->green
.offset
= var
->blue
.offset
= 0;
1132 var
->red
.length
= var
->green
.length
= var
->blue
.length
= 8;
1135 var
->red
.offset
= 11;
1136 var
->red
.length
= 5;
1137 var
->green
.offset
= 5;
1138 var
->green
.length
= 6;
1139 var
->blue
.offset
= 0;
1140 var
->blue
.length
= 5;
1141 var
->transp
.offset
= 0;
1142 var
->transp
.length
= 0;
1145 var
->red
.offset
= 16;
1146 var
->red
.length
= 8;
1147 var
->green
.offset
= 8;
1148 var
->green
.length
= 8;
1149 var
->blue
.offset
= 0;
1150 var
->blue
.length
= 8;
1151 var
->transp
.offset
= 24;
1152 var
->transp
.length
= 8;
1158 sisfb_set_mode(struct sis_video_info
*ivideo
, int clrscrn
)
1160 unsigned short modeno
= ivideo
->mode_no
;
1162 /* >=2.6.12's fbcon clears the screen anyway */
1165 SiS_SetReg(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1167 sisfb_pre_setmode(ivideo
);
1169 if(!SiSSetMode(&ivideo
->SiS_Pr
, modeno
)) {
1170 printk(KERN_ERR
"sisfb: Setting mode[0x%x] failed\n", ivideo
->mode_no
);
1174 SiS_SetReg(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1176 sisfb_post_setmode(ivideo
);
1183 sisfb_do_set_var(struct fb_var_screeninfo
*var
, int isactive
, struct fb_info
*info
)
1185 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1186 unsigned int htotal
= 0, vtotal
= 0;
1187 unsigned int drate
= 0, hrate
= 0;
1188 int found_mode
= 0, ret
;
1192 htotal
= var
->left_margin
+ var
->xres
+ var
->right_margin
+ var
->hsync_len
;
1194 vtotal
= var
->upper_margin
+ var
->lower_margin
+ var
->vsync_len
;
1196 pixclock
= var
->pixclock
;
1198 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
) {
1199 vtotal
+= var
->yres
;
1201 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1202 vtotal
+= var
->yres
;
1204 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1205 vtotal
+= var
->yres
;
1207 } else vtotal
+= var
->yres
;
1209 if(!(htotal
) || !(vtotal
)) {
1210 DPRINTK("sisfb: Invalid 'var' information\n");
1214 if(pixclock
&& htotal
&& vtotal
) {
1215 drate
= 1000000000 / pixclock
;
1216 hrate
= (drate
* 1000) / htotal
;
1217 ivideo
->refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1219 ivideo
->refresh_rate
= 60;
1222 old_mode
= ivideo
->sisfb_mode_idx
;
1223 ivideo
->sisfb_mode_idx
= 0;
1225 while( (sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[0] != 0) &&
1226 (sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
<= var
->xres
) ) {
1227 if( (sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
== var
->xres
) &&
1228 (sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
== var
->yres
) &&
1229 (sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
== var
->bits_per_pixel
)) {
1230 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
1234 ivideo
->sisfb_mode_idx
++;
1238 ivideo
->sisfb_mode_idx
= sisfb_validate_mode(ivideo
,
1239 ivideo
->sisfb_mode_idx
, ivideo
->currentvbflags
);
1241 ivideo
->sisfb_mode_idx
= -1;
1244 if(ivideo
->sisfb_mode_idx
< 0) {
1245 printk(KERN_ERR
"sisfb: Mode %dx%dx%d not supported\n", var
->xres
,
1246 var
->yres
, var
->bits_per_pixel
);
1247 ivideo
->sisfb_mode_idx
= old_mode
;
1251 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
1253 if(sisfb_search_refresh_rate(ivideo
, ivideo
->refresh_rate
, ivideo
->sisfb_mode_idx
) == 0) {
1254 ivideo
->rate_idx
= sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
;
1255 ivideo
->refresh_rate
= 60;
1259 /* If acceleration to be used? Need to know
1260 * before pre/post_set_mode()
1263 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
1264 #ifdef STUPID_ACCELF_TEXT_SHIT
1265 if(var
->accel_flags
& FB_ACCELF_TEXT
) {
1266 info
->flags
&= ~FBINFO_HWACCEL_DISABLED
;
1268 info
->flags
|= FBINFO_HWACCEL_DISABLED
;
1271 if(!(info
->flags
& FBINFO_HWACCEL_DISABLED
)) ivideo
->accel
= -1;
1273 if(var
->accel_flags
& FB_ACCELF_TEXT
) ivideo
->accel
= -1;
1276 if((ret
= sisfb_set_mode(ivideo
, 1))) {
1280 ivideo
->video_bpp
= sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
;
1281 ivideo
->video_width
= sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
;
1282 ivideo
->video_height
= sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
;
1284 sisfb_calc_pitch(ivideo
, var
);
1285 sisfb_set_pitch(ivideo
);
1287 sisfb_set_vparms(ivideo
);
1289 ivideo
->current_width
= ivideo
->video_width
;
1290 ivideo
->current_height
= ivideo
->video_height
;
1291 ivideo
->current_bpp
= ivideo
->video_bpp
;
1292 ivideo
->current_htotal
= htotal
;
1293 ivideo
->current_vtotal
= vtotal
;
1294 ivideo
->current_linelength
= ivideo
->video_linelength
;
1295 ivideo
->current_pixclock
= var
->pixclock
;
1296 ivideo
->current_refresh_rate
= ivideo
->refresh_rate
;
1297 ivideo
->sisfb_lastrates
[ivideo
->mode_no
] = ivideo
->refresh_rate
;
1304 sisfb_set_base_CRT1(struct sis_video_info
*ivideo
, unsigned int base
)
1306 SiS_SetReg(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1308 SiS_SetReg(SISCR
, 0x0D, base
& 0xFF);
1309 SiS_SetReg(SISCR
, 0x0C, (base
>> 8) & 0xFF);
1310 SiS_SetReg(SISSR
, 0x0D, (base
>> 16) & 0xFF);
1311 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
1312 SiS_SetRegANDOR(SISSR
, 0x37, 0xFE, (base
>> 24) & 0x01);
1317 sisfb_set_base_CRT2(struct sis_video_info
*ivideo
, unsigned int base
)
1319 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
1320 SiS_SetRegOR(SISPART1
, ivideo
->CRT2_write_enable
, 0x01);
1321 SiS_SetReg(SISPART1
, 0x06, (base
& 0xFF));
1322 SiS_SetReg(SISPART1
, 0x05, ((base
>> 8) & 0xFF));
1323 SiS_SetReg(SISPART1
, 0x04, ((base
>> 16) & 0xFF));
1324 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
1325 SiS_SetRegANDOR(SISPART1
, 0x02, 0x7F, ((base
>> 24) & 0x01) << 7);
1331 sisfb_pan_var(struct sis_video_info
*ivideo
, struct fb_info
*info
,
1332 struct fb_var_screeninfo
*var
)
1334 ivideo
->current_base
= var
->yoffset
* info
->var
.xres_virtual
1337 /* calculate base bpp dep. */
1338 switch (info
->var
.bits_per_pixel
) {
1342 ivideo
->current_base
>>= 1;
1346 ivideo
->current_base
>>= 2;
1350 ivideo
->current_base
+= (ivideo
->video_offset
>> 2);
1352 sisfb_set_base_CRT1(ivideo
, ivideo
->current_base
);
1353 sisfb_set_base_CRT2(ivideo
, ivideo
->current_base
);
1359 sisfb_open(struct fb_info
*info
, int user
)
1365 sisfb_release(struct fb_info
*info
, int user
)
1371 sisfb_setcolreg(unsigned regno
, unsigned red
, unsigned green
, unsigned blue
,
1372 unsigned transp
, struct fb_info
*info
)
1374 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1376 if(regno
>= sisfb_get_cmap_len(&info
->var
))
1379 switch(info
->var
.bits_per_pixel
) {
1381 SiS_SetRegByte(SISDACA
, regno
);
1382 SiS_SetRegByte(SISDACD
, (red
>> 10));
1383 SiS_SetRegByte(SISDACD
, (green
>> 10));
1384 SiS_SetRegByte(SISDACD
, (blue
>> 10));
1385 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
1386 SiS_SetRegByte(SISDAC2A
, regno
);
1387 SiS_SetRegByte(SISDAC2D
, (red
>> 8));
1388 SiS_SetRegByte(SISDAC2D
, (green
>> 8));
1389 SiS_SetRegByte(SISDAC2D
, (blue
>> 8));
1396 ((u32
*)(info
->pseudo_palette
))[regno
] =
1398 ((green
& 0xfc00) >> 5) |
1399 ((blue
& 0xf800) >> 11);
1408 ((u32
*)(info
->pseudo_palette
))[regno
] =
1409 (red
<< 16) | (green
<< 8) | (blue
);
1416 sisfb_set_par(struct fb_info
*info
)
1420 if((err
= sisfb_do_set_var(&info
->var
, 1, info
)))
1423 sisfb_get_fix(&info
->fix
, -1, info
);
1429 sisfb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
1431 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1432 unsigned int htotal
= 0, vtotal
= 0, myrateindex
= 0;
1433 unsigned int drate
= 0, hrate
= 0, maxyres
;
1435 int refresh_rate
, search_idx
, tidx
;
1436 bool recalc_clock
= false;
1439 htotal
= var
->left_margin
+ var
->xres
+ var
->right_margin
+ var
->hsync_len
;
1441 vtotal
= var
->upper_margin
+ var
->lower_margin
+ var
->vsync_len
;
1443 pixclock
= var
->pixclock
;
1445 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
) {
1446 vtotal
+= var
->yres
;
1448 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1449 vtotal
+= var
->yres
;
1451 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1452 vtotal
+= var
->yres
;
1455 vtotal
+= var
->yres
;
1457 if(!(htotal
) || !(vtotal
)) {
1458 SISFAIL("sisfb: no valid timing data");
1462 while( (sisbios_mode
[search_idx
].mode_no
[0] != 0) &&
1463 (sisbios_mode
[search_idx
].xres
<= var
->xres
) ) {
1464 if( (sisbios_mode
[search_idx
].xres
== var
->xres
) &&
1465 (sisbios_mode
[search_idx
].yres
== var
->yres
) &&
1466 (sisbios_mode
[search_idx
].bpp
== var
->bits_per_pixel
)) {
1467 if((tidx
= sisfb_validate_mode(ivideo
, search_idx
,
1468 ivideo
->currentvbflags
)) > 0) {
1479 while(sisbios_mode
[search_idx
].mode_no
[0] != 0) {
1480 if( (var
->xres
<= sisbios_mode
[search_idx
].xres
) &&
1481 (var
->yres
<= sisbios_mode
[search_idx
].yres
) &&
1482 (var
->bits_per_pixel
== sisbios_mode
[search_idx
].bpp
) ) {
1483 if((tidx
= sisfb_validate_mode(ivideo
,search_idx
,
1484 ivideo
->currentvbflags
)) > 0) {
1494 "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
1495 var
->xres
, var
->yres
, var
->bits_per_pixel
,
1496 sisbios_mode
[search_idx
].xres
,
1497 sisbios_mode
[search_idx
].yres
,
1498 var
->bits_per_pixel
);
1499 var
->xres
= sisbios_mode
[search_idx
].xres
;
1500 var
->yres
= sisbios_mode
[search_idx
].yres
;
1503 "sisfb: Failed to find supported mode near %dx%dx%d\n",
1504 var
->xres
, var
->yres
, var
->bits_per_pixel
);
1509 if( ((ivideo
->vbflags2
& VB2_LVDS
) ||
1510 ((ivideo
->vbflags2
& VB2_30xBDH
) && (ivideo
->currentvbflags
& CRT2_LCD
))) &&
1511 (var
->bits_per_pixel
== 8) ) {
1512 /* Slave modes on LVDS and 301B-DH */
1514 recalc_clock
= true;
1515 } else if( (ivideo
->current_htotal
== htotal
) &&
1516 (ivideo
->current_vtotal
== vtotal
) &&
1517 (ivideo
->current_pixclock
== pixclock
) ) {
1518 /* x=x & y=y & c=c -> assume depth change */
1519 drate
= 1000000000 / pixclock
;
1520 hrate
= (drate
* 1000) / htotal
;
1521 refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1522 } else if( ( (ivideo
->current_htotal
!= htotal
) ||
1523 (ivideo
->current_vtotal
!= vtotal
) ) &&
1524 (ivideo
->current_pixclock
== var
->pixclock
) ) {
1525 /* x!=x | y!=y & c=c -> invalid pixclock */
1526 if(ivideo
->sisfb_lastrates
[sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
]]) {
1528 ivideo
->sisfb_lastrates
[sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
]];
1529 } else if(ivideo
->sisfb_parm_rate
!= -1) {
1530 /* Sic, sisfb_parm_rate - want to know originally desired rate here */
1531 refresh_rate
= ivideo
->sisfb_parm_rate
;
1535 recalc_clock
= true;
1536 } else if((pixclock
) && (htotal
) && (vtotal
)) {
1537 drate
= 1000000000 / pixclock
;
1538 hrate
= (drate
* 1000) / htotal
;
1539 refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1540 } else if(ivideo
->current_refresh_rate
) {
1541 refresh_rate
= ivideo
->current_refresh_rate
;
1542 recalc_clock
= true;
1545 recalc_clock
= true;
1548 myrateindex
= sisfb_search_refresh_rate(ivideo
, refresh_rate
, search_idx
);
1550 /* Eventually recalculate timing and clock */
1552 if(!myrateindex
) myrateindex
= sisbios_mode
[search_idx
].rate_idx
;
1553 var
->pixclock
= (u32
) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo
->SiS_Pr
,
1554 sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
],
1556 sisfb_mode_rate_to_ddata(&ivideo
->SiS_Pr
,
1557 sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
],
1559 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1560 var
->pixclock
<<= 1;
1564 if(ivideo
->sisfb_thismonitor
.datavalid
) {
1565 if(!sisfb_verify_rate(ivideo
, &ivideo
->sisfb_thismonitor
, search_idx
,
1566 myrateindex
, refresh_rate
)) {
1568 "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1572 /* Adapt RGB settings */
1573 sisfb_bpp_to_var(ivideo
, var
);
1575 /* Sanity check for offsets */
1576 if(var
->xoffset
< 0) var
->xoffset
= 0;
1577 if(var
->yoffset
< 0) var
->yoffset
= 0;
1579 if(var
->xres
> var
->xres_virtual
)
1580 var
->xres_virtual
= var
->xres
;
1582 if(ivideo
->sisfb_ypan
) {
1583 maxyres
= sisfb_calc_maxyres(ivideo
, var
);
1584 if(ivideo
->sisfb_max
) {
1585 var
->yres_virtual
= maxyres
;
1587 if(var
->yres_virtual
> maxyres
) {
1588 var
->yres_virtual
= maxyres
;
1591 if(var
->yres_virtual
<= var
->yres
) {
1592 var
->yres_virtual
= var
->yres
;
1595 if(var
->yres
!= var
->yres_virtual
) {
1596 var
->yres_virtual
= var
->yres
;
1602 /* Truncate offsets to maximum if too high */
1603 if(var
->xoffset
> var
->xres_virtual
- var
->xres
) {
1604 var
->xoffset
= var
->xres_virtual
- var
->xres
- 1;
1607 if(var
->yoffset
> var
->yres_virtual
- var
->yres
) {
1608 var
->yoffset
= var
->yres_virtual
- var
->yres
- 1;
1611 /* Set everything else to 0 */
1612 var
->red
.msb_right
=
1613 var
->green
.msb_right
=
1614 var
->blue
.msb_right
=
1615 var
->transp
.offset
=
1616 var
->transp
.length
=
1617 var
->transp
.msb_right
= 0;
1623 sisfb_pan_display(struct fb_var_screeninfo
*var
, struct fb_info
* info
)
1625 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1628 if (var
->vmode
& FB_VMODE_YWRAP
)
1631 if (var
->xoffset
+ info
->var
.xres
> info
->var
.xres_virtual
||
1632 var
->yoffset
+ info
->var
.yres
> info
->var
.yres_virtual
)
1635 err
= sisfb_pan_var(ivideo
, info
, var
);
1639 info
->var
.xoffset
= var
->xoffset
;
1640 info
->var
.yoffset
= var
->yoffset
;
1646 sisfb_blank(int blank
, struct fb_info
*info
)
1648 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1650 return sisfb_myblank(ivideo
, blank
);
1653 /* ----------- FBDev related routines for all series ---------- */
1655 static int sisfb_ioctl(struct fb_info
*info
, unsigned int cmd
,
1658 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1659 struct sis_memreq sismemreq
;
1660 struct fb_vblank sisvbblank
;
1665 u32 __user
*argp
= (u32 __user
*)arg
;
1669 if(!capable(CAP_SYS_RAWIO
))
1672 if(copy_from_user(&sismemreq
, (void __user
*)arg
, sizeof(sismemreq
)))
1675 sis_malloc(&sismemreq
);
1677 if(copy_to_user((void __user
*)arg
, &sismemreq
, sizeof(sismemreq
))) {
1678 sis_free((u32
)sismemreq
.offset
);
1684 if(!capable(CAP_SYS_RAWIO
))
1687 if(get_user(gpu32
, argp
))
1693 case FBIOGET_VBLANK
:
1695 memset(&sisvbblank
, 0, sizeof(struct fb_vblank
));
1697 sisvbblank
.count
= 0;
1698 sisvbblank
.flags
= sisfb_setupvbblankflags(ivideo
, &sisvbblank
.vcount
, &sisvbblank
.hcount
);
1700 if(copy_to_user((void __user
*)arg
, &sisvbblank
, sizeof(sisvbblank
)))
1705 case SISFB_GET_INFO_SIZE
:
1706 return put_user(sizeof(struct sisfb_info
), argp
);
1708 case SISFB_GET_INFO_OLD
:
1709 if(ivideo
->warncount
++ < 10)
1711 "sisfb: Deprecated ioctl call received - update your application!\n");
1712 case SISFB_GET_INFO
: /* For communication with X driver */
1713 ivideo
->sisfb_infoblock
.sisfb_id
= SISFB_ID
;
1714 ivideo
->sisfb_infoblock
.sisfb_version
= VER_MAJOR
;
1715 ivideo
->sisfb_infoblock
.sisfb_revision
= VER_MINOR
;
1716 ivideo
->sisfb_infoblock
.sisfb_patchlevel
= VER_LEVEL
;
1717 ivideo
->sisfb_infoblock
.chip_id
= ivideo
->chip_id
;
1718 ivideo
->sisfb_infoblock
.sisfb_pci_vendor
= ivideo
->chip_vendor
;
1719 ivideo
->sisfb_infoblock
.memory
= ivideo
->video_size
/ 1024;
1720 ivideo
->sisfb_infoblock
.heapstart
= ivideo
->heapstart
/ 1024;
1721 if(ivideo
->modechanged
) {
1722 ivideo
->sisfb_infoblock
.fbvidmode
= ivideo
->mode_no
;
1724 ivideo
->sisfb_infoblock
.fbvidmode
= ivideo
->modeprechange
;
1726 ivideo
->sisfb_infoblock
.sisfb_caps
= ivideo
->caps
;
1727 ivideo
->sisfb_infoblock
.sisfb_tqlen
= ivideo
->cmdQueueSize
/ 1024;
1728 ivideo
->sisfb_infoblock
.sisfb_pcibus
= ivideo
->pcibus
;
1729 ivideo
->sisfb_infoblock
.sisfb_pcislot
= ivideo
->pcislot
;
1730 ivideo
->sisfb_infoblock
.sisfb_pcifunc
= ivideo
->pcifunc
;
1731 ivideo
->sisfb_infoblock
.sisfb_lcdpdc
= ivideo
->detectedpdc
;
1732 ivideo
->sisfb_infoblock
.sisfb_lcdpdca
= ivideo
->detectedpdca
;
1733 ivideo
->sisfb_infoblock
.sisfb_lcda
= ivideo
->detectedlcda
;
1734 ivideo
->sisfb_infoblock
.sisfb_vbflags
= ivideo
->vbflags
;
1735 ivideo
->sisfb_infoblock
.sisfb_currentvbflags
= ivideo
->currentvbflags
;
1736 ivideo
->sisfb_infoblock
.sisfb_scalelcd
= ivideo
->SiS_Pr
.UsePanelScaler
;
1737 ivideo
->sisfb_infoblock
.sisfb_specialtiming
= ivideo
->SiS_Pr
.SiS_CustomT
;
1738 ivideo
->sisfb_infoblock
.sisfb_haveemi
= ivideo
->SiS_Pr
.HaveEMI
? 1 : 0;
1739 ivideo
->sisfb_infoblock
.sisfb_haveemilcd
= ivideo
->SiS_Pr
.HaveEMILCD
? 1 : 0;
1740 ivideo
->sisfb_infoblock
.sisfb_emi30
= ivideo
->SiS_Pr
.EMI_30
;
1741 ivideo
->sisfb_infoblock
.sisfb_emi31
= ivideo
->SiS_Pr
.EMI_31
;
1742 ivideo
->sisfb_infoblock
.sisfb_emi32
= ivideo
->SiS_Pr
.EMI_32
;
1743 ivideo
->sisfb_infoblock
.sisfb_emi33
= ivideo
->SiS_Pr
.EMI_33
;
1744 ivideo
->sisfb_infoblock
.sisfb_tvxpos
= (u16
)(ivideo
->tvxpos
+ 32);
1745 ivideo
->sisfb_infoblock
.sisfb_tvypos
= (u16
)(ivideo
->tvypos
+ 32);
1746 ivideo
->sisfb_infoblock
.sisfb_heapsize
= ivideo
->sisfb_heap_size
/ 1024;
1747 ivideo
->sisfb_infoblock
.sisfb_videooffset
= ivideo
->video_offset
;
1748 ivideo
->sisfb_infoblock
.sisfb_curfstn
= ivideo
->curFSTN
;
1749 ivideo
->sisfb_infoblock
.sisfb_curdstn
= ivideo
->curDSTN
;
1750 ivideo
->sisfb_infoblock
.sisfb_vbflags2
= ivideo
->vbflags2
;
1751 ivideo
->sisfb_infoblock
.sisfb_can_post
= ivideo
->sisfb_can_post
? 1 : 0;
1752 ivideo
->sisfb_infoblock
.sisfb_card_posted
= ivideo
->sisfb_card_posted
? 1 : 0;
1753 ivideo
->sisfb_infoblock
.sisfb_was_boot_device
= ivideo
->sisfb_was_boot_device
? 1 : 0;
1755 if(copy_to_user((void __user
*)arg
, &ivideo
->sisfb_infoblock
,
1756 sizeof(ivideo
->sisfb_infoblock
)))
1761 case SISFB_GET_VBRSTATUS_OLD
:
1762 if(ivideo
->warncount
++ < 10)
1764 "sisfb: Deprecated ioctl call received - update your application!\n");
1765 case SISFB_GET_VBRSTATUS
:
1766 if(sisfb_CheckVBRetrace(ivideo
))
1767 return put_user((u32
)1, argp
);
1769 return put_user((u32
)0, argp
);
1771 case SISFB_GET_AUTOMAXIMIZE_OLD
:
1772 if(ivideo
->warncount
++ < 10)
1774 "sisfb: Deprecated ioctl call received - update your application!\n");
1775 case SISFB_GET_AUTOMAXIMIZE
:
1776 if(ivideo
->sisfb_max
)
1777 return put_user((u32
)1, argp
);
1779 return put_user((u32
)0, argp
);
1781 case SISFB_SET_AUTOMAXIMIZE_OLD
:
1782 if(ivideo
->warncount
++ < 10)
1784 "sisfb: Deprecated ioctl call received - update your application!\n");
1785 case SISFB_SET_AUTOMAXIMIZE
:
1786 if(get_user(gpu32
, argp
))
1789 ivideo
->sisfb_max
= (gpu32
) ? 1 : 0;
1792 case SISFB_SET_TVPOSOFFSET
:
1793 if(get_user(gpu32
, argp
))
1796 sisfb_set_TVxposoffset(ivideo
, ((int)(gpu32
>> 16)) - 32);
1797 sisfb_set_TVyposoffset(ivideo
, ((int)(gpu32
& 0xffff)) - 32);
1800 case SISFB_GET_TVPOSOFFSET
:
1801 return put_user((u32
)(((ivideo
->tvxpos
+32)<<16)|((ivideo
->tvypos
+32)&0xffff)),
1805 if(copy_from_user(&ivideo
->sisfb_command
, (void __user
*)arg
,
1806 sizeof(struct sisfb_cmd
)))
1809 sisfb_handle_command(ivideo
, &ivideo
->sisfb_command
);
1811 if(copy_to_user((void __user
*)arg
, &ivideo
->sisfb_command
,
1812 sizeof(struct sisfb_cmd
)))
1817 case SISFB_SET_LOCK
:
1818 if(get_user(gpu32
, argp
))
1821 ivideo
->sisfblocked
= (gpu32
) ? 1 : 0;
1825 #ifdef SIS_NEW_CONFIG_COMPAT
1826 return -ENOIOCTLCMD
;
1835 sisfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
, struct fb_info
*info
)
1837 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1839 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
1841 strlcpy(fix
->id
, ivideo
->myid
, sizeof(fix
->id
));
1843 mutex_lock(&info
->mm_lock
);
1844 fix
->smem_start
= ivideo
->video_base
+ ivideo
->video_offset
;
1845 fix
->smem_len
= ivideo
->sisfb_mem
;
1846 mutex_unlock(&info
->mm_lock
);
1847 fix
->type
= FB_TYPE_PACKED_PIXELS
;
1849 fix
->visual
= (ivideo
->video_bpp
== 8) ? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_TRUECOLOR
;
1851 fix
->ypanstep
= (ivideo
->sisfb_ypan
) ? 1 : 0;
1853 fix
->line_length
= ivideo
->video_linelength
;
1854 fix
->mmio_start
= ivideo
->mmio_base
;
1855 fix
->mmio_len
= ivideo
->mmio_size
;
1856 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
1857 fix
->accel
= FB_ACCEL_SIS_GLAMOUR
;
1858 } else if((ivideo
->chip
== SIS_330
) ||
1859 (ivideo
->chip
== SIS_760
) ||
1860 (ivideo
->chip
== SIS_761
)) {
1861 fix
->accel
= FB_ACCEL_SIS_XABRE
;
1862 } else if(ivideo
->chip
== XGI_20
) {
1863 fix
->accel
= FB_ACCEL_XGI_VOLARI_Z
;
1864 } else if(ivideo
->chip
>= XGI_40
) {
1865 fix
->accel
= FB_ACCEL_XGI_VOLARI_V
;
1867 fix
->accel
= FB_ACCEL_SIS_GLAMOUR_2
;
1873 /* ---------------- fb_ops structures ----------------- */
1875 static struct fb_ops sisfb_ops
= {
1876 .owner
= THIS_MODULE
,
1877 .fb_open
= sisfb_open
,
1878 .fb_release
= sisfb_release
,
1879 .fb_check_var
= sisfb_check_var
,
1880 .fb_set_par
= sisfb_set_par
,
1881 .fb_setcolreg
= sisfb_setcolreg
,
1882 .fb_pan_display
= sisfb_pan_display
,
1883 .fb_blank
= sisfb_blank
,
1884 .fb_fillrect
= fbcon_sis_fillrect
,
1885 .fb_copyarea
= fbcon_sis_copyarea
,
1886 .fb_imageblit
= cfb_imageblit
,
1887 .fb_sync
= fbcon_sis_sync
,
1888 #ifdef SIS_NEW_CONFIG_COMPAT
1889 .fb_compat_ioctl
= sisfb_ioctl
,
1891 .fb_ioctl
= sisfb_ioctl
1894 /* ---------------- Chip generation dependent routines ---------------- */
1896 static struct pci_dev
*sisfb_get_northbridge(int basechipid
)
1898 struct pci_dev
*pdev
= NULL
;
1899 int nbridgenum
, nbridgeidx
, i
;
1900 static const unsigned short nbridgeids
[] = {
1901 PCI_DEVICE_ID_SI_540
, /* for SiS 540 VGA */
1902 PCI_DEVICE_ID_SI_630
, /* for SiS 630/730 VGA */
1903 PCI_DEVICE_ID_SI_730
,
1904 PCI_DEVICE_ID_SI_550
, /* for SiS 550 VGA */
1905 PCI_DEVICE_ID_SI_650
, /* for SiS 650/651/740 VGA */
1906 PCI_DEVICE_ID_SI_651
,
1907 PCI_DEVICE_ID_SI_740
,
1908 PCI_DEVICE_ID_SI_661
, /* for SiS 661/741/660/760/761 VGA */
1909 PCI_DEVICE_ID_SI_741
,
1910 PCI_DEVICE_ID_SI_660
,
1911 PCI_DEVICE_ID_SI_760
,
1912 PCI_DEVICE_ID_SI_761
1915 switch(basechipid
) {
1916 #ifdef CONFIG_FB_SIS_300
1917 case SIS_540
: nbridgeidx
= 0; nbridgenum
= 1; break;
1918 case SIS_630
: nbridgeidx
= 1; nbridgenum
= 2; break;
1920 #ifdef CONFIG_FB_SIS_315
1921 case SIS_550
: nbridgeidx
= 3; nbridgenum
= 1; break;
1922 case SIS_650
: nbridgeidx
= 4; nbridgenum
= 3; break;
1923 case SIS_660
: nbridgeidx
= 7; nbridgenum
= 5; break;
1925 default: return NULL
;
1927 for(i
= 0; i
< nbridgenum
; i
++) {
1928 if((pdev
= pci_get_device(PCI_VENDOR_ID_SI
,
1929 nbridgeids
[nbridgeidx
+i
], NULL
)))
1935 static int sisfb_get_dram_size(struct sis_video_info
*ivideo
)
1937 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1941 ivideo
->video_size
= 0;
1942 ivideo
->UMAsize
= ivideo
->LFBsize
= 0;
1944 switch(ivideo
->chip
) {
1945 #ifdef CONFIG_FB_SIS_300
1947 reg
= SiS_GetReg(SISSR
, 0x14);
1948 ivideo
->video_size
= ((reg
& 0x3F) + 1) << 20;
1953 if(!ivideo
->nbridge
)
1955 pci_read_config_byte(ivideo
->nbridge
, 0x63, ®
);
1956 ivideo
->video_size
= 1 << (((reg
& 0x70) >> 4) + 21);
1959 #ifdef CONFIG_FB_SIS_315
1963 reg
= SiS_GetReg(SISSR
, 0x14);
1964 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
1965 switch((reg
>> 2) & 0x03) {
1968 ivideo
->video_size
<<= 1;
1971 ivideo
->video_size
+= (ivideo
->video_size
/2);
1975 reg
= SiS_GetReg(SISSR
, 0x14);
1976 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
1977 if(reg
& 0x0c) ivideo
->video_size
<<= 1;
1982 reg
= SiS_GetReg(SISSR
, 0x14);
1983 ivideo
->video_size
= (((reg
& 0x3f) + 1) << 2) << 20;
1987 reg
= SiS_GetReg(SISCR
, 0x79);
1988 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
1993 reg
= SiS_GetReg(SISCR
, 0x79);
1994 reg
= (reg
& 0xf0) >> 4;
1996 ivideo
->video_size
= (1 << reg
) << 20;
1997 ivideo
->UMAsize
= ivideo
->video_size
;
1999 reg
= SiS_GetReg(SISCR
, 0x78);
2003 ivideo
->LFBsize
= (32 << 20);
2005 ivideo
->LFBsize
= (64 << 20);
2007 ivideo
->video_size
+= ivideo
->LFBsize
;
2013 reg
= SiS_GetReg(SISSR
, 0x14);
2014 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
2015 if(ivideo
->chip
!= XGI_20
) {
2016 reg
= (reg
& 0x0c) >> 2;
2017 if(ivideo
->revision_id
== 2) {
2018 if(reg
& 0x01) reg
= 0x02;
2021 if(reg
== 0x02) ivideo
->video_size
<<= 1;
2022 else if(reg
== 0x03) ivideo
->video_size
<<= 2;
2032 /* -------------- video bridge device detection --------------- */
2034 static void sisfb_detect_VB_connect(struct sis_video_info
*ivideo
)
2038 /* No CRT2 on XGI Z7 */
2039 if(ivideo
->chip
== XGI_20
) {
2040 ivideo
->sisfb_crt1off
= 0;
2044 #ifdef CONFIG_FB_SIS_300
2045 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2046 temp
= SiS_GetReg(SISSR
, 0x17);
2047 if((temp
& 0x0F) && (ivideo
->chip
!= SIS_300
)) {
2048 /* PAL/NTSC is stored on SR16 on such machines */
2049 if(!(ivideo
->vbflags
& (TV_PAL
| TV_NTSC
| TV_PALM
| TV_PALN
))) {
2050 temp
= SiS_GetReg(SISSR
, 0x16);
2052 ivideo
->vbflags
|= TV_PAL
;
2054 ivideo
->vbflags
|= TV_NTSC
;
2060 cr32
= SiS_GetReg(SISCR
, 0x32);
2062 if(cr32
& SIS_CRT1
) {
2063 ivideo
->sisfb_crt1off
= 0;
2065 ivideo
->sisfb_crt1off
= (cr32
& 0xDF) ? 1 : 0;
2068 ivideo
->vbflags
&= ~(CRT2_TV
| CRT2_LCD
| CRT2_VGA
);
2070 if(cr32
& SIS_VB_TV
) ivideo
->vbflags
|= CRT2_TV
;
2071 if(cr32
& SIS_VB_LCD
) ivideo
->vbflags
|= CRT2_LCD
;
2072 if(cr32
& SIS_VB_CRT2
) ivideo
->vbflags
|= CRT2_VGA
;
2074 /* Check given parms for hardware compatibility.
2075 * (Cannot do this in the search_xx routines since we don't
2076 * know what hardware we are running on then)
2079 if(ivideo
->chip
!= SIS_550
) {
2080 ivideo
->sisfb_dstn
= ivideo
->sisfb_fstn
= 0;
2083 if(ivideo
->sisfb_tvplug
!= -1) {
2084 if( (ivideo
->sisvga_engine
!= SIS_315_VGA
) ||
2085 (!(ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) ) {
2086 if(ivideo
->sisfb_tvplug
& TV_YPBPR
) {
2087 ivideo
->sisfb_tvplug
= -1;
2088 printk(KERN_ERR
"sisfb: YPbPr not supported\n");
2092 if(ivideo
->sisfb_tvplug
!= -1) {
2093 if( (ivideo
->sisvga_engine
!= SIS_315_VGA
) ||
2094 (!(ivideo
->vbflags2
& VB2_SISHIVISIONBRIDGE
)) ) {
2095 if(ivideo
->sisfb_tvplug
& TV_HIVISION
) {
2096 ivideo
->sisfb_tvplug
= -1;
2097 printk(KERN_ERR
"sisfb: HiVision not supported\n");
2101 if(ivideo
->sisfb_tvstd
!= -1) {
2102 if( (!(ivideo
->vbflags2
& VB2_SISBRIDGE
)) &&
2103 (!((ivideo
->sisvga_engine
== SIS_315_VGA
) &&
2104 (ivideo
->vbflags2
& VB2_CHRONTEL
))) ) {
2105 if(ivideo
->sisfb_tvstd
& (TV_PALM
| TV_PALN
| TV_NTSCJ
)) {
2106 ivideo
->sisfb_tvstd
= -1;
2107 printk(KERN_ERR
"sisfb: PALM/PALN/NTSCJ not supported\n");
2112 /* Detect/set TV plug & type */
2113 if(ivideo
->sisfb_tvplug
!= -1) {
2114 ivideo
->vbflags
|= ivideo
->sisfb_tvplug
;
2116 if(cr32
& SIS_VB_YPBPR
) ivideo
->vbflags
|= (TV_YPBPR
|TV_YPBPR525I
); /* default: 480i */
2117 else if(cr32
& SIS_VB_HIVISION
) ivideo
->vbflags
|= TV_HIVISION
;
2118 else if(cr32
& SIS_VB_SCART
) ivideo
->vbflags
|= TV_SCART
;
2120 if(cr32
& SIS_VB_SVIDEO
) ivideo
->vbflags
|= TV_SVIDEO
;
2121 if(cr32
& SIS_VB_COMPOSITE
) ivideo
->vbflags
|= TV_AVIDEO
;
2125 if(!(ivideo
->vbflags
& (TV_YPBPR
| TV_HIVISION
))) {
2126 if(ivideo
->sisfb_tvstd
!= -1) {
2127 ivideo
->vbflags
&= ~(TV_NTSC
| TV_PAL
| TV_PALM
| TV_PALN
| TV_NTSCJ
);
2128 ivideo
->vbflags
|= ivideo
->sisfb_tvstd
;
2130 if(ivideo
->vbflags
& TV_SCART
) {
2131 ivideo
->vbflags
&= ~(TV_NTSC
| TV_PALM
| TV_PALN
| TV_NTSCJ
);
2132 ivideo
->vbflags
|= TV_PAL
;
2134 if(!(ivideo
->vbflags
& (TV_PAL
| TV_NTSC
| TV_PALM
| TV_PALN
| TV_NTSCJ
))) {
2135 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2136 temp
= SiS_GetReg(SISSR
, 0x38);
2137 if(temp
& 0x01) ivideo
->vbflags
|= TV_PAL
;
2138 else ivideo
->vbflags
|= TV_NTSC
;
2139 } else if((ivideo
->chip
<= SIS_315PRO
) || (ivideo
->chip
>= SIS_330
)) {
2140 temp
= SiS_GetReg(SISSR
, 0x38);
2141 if(temp
& 0x01) ivideo
->vbflags
|= TV_PAL
;
2142 else ivideo
->vbflags
|= TV_NTSC
;
2144 temp
= SiS_GetReg(SISCR
, 0x79);
2145 if(temp
& 0x20) ivideo
->vbflags
|= TV_PAL
;
2146 else ivideo
->vbflags
|= TV_NTSC
;
2151 /* Copy forceCRT1 option to CRT1off if option is given */
2152 if(ivideo
->sisfb_forcecrt1
!= -1) {
2153 ivideo
->sisfb_crt1off
= (ivideo
->sisfb_forcecrt1
) ? 0 : 1;
2157 /* ------------------ Sensing routines ------------------ */
2159 static bool sisfb_test_DDC1(struct sis_video_info
*ivideo
)
2164 old
= SiS_ReadDDC1Bit(&ivideo
->SiS_Pr
);
2166 if(old
!= SiS_ReadDDC1Bit(&ivideo
->SiS_Pr
)) break;
2168 return (count
!= -1);
2171 static void sisfb_sense_crt1(struct sis_video_info
*ivideo
)
2173 bool mustwait
= false;
2175 #ifdef CONFIG_FB_SIS_315
2181 sr1F
= SiS_GetReg(SISSR
, 0x1F);
2182 SiS_SetRegOR(SISSR
, 0x1F, 0x04);
2183 SiS_SetRegAND(SISSR
, 0x1F, 0x3F);
2184 if(sr1F
& 0xc0) mustwait
= true;
2186 #ifdef CONFIG_FB_SIS_315
2187 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2188 cr63
= SiS_GetReg(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
);
2190 SiS_SetRegAND(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, 0xBF);
2194 cr17
= SiS_GetReg(SISCR
, 0x17);
2197 SiS_SetRegOR(SISCR
, 0x17, 0x80);
2199 SiS_SetReg(SISSR
, 0x00, 0x01);
2200 SiS_SetReg(SISSR
, 0x00, 0x03);
2204 for(i
=0; i
< 10; i
++) sisfbwaitretracecrt1(ivideo
);
2207 #ifdef CONFIG_FB_SIS_315
2208 if(ivideo
->chip
>= SIS_330
) {
2209 SiS_SetRegAND(SISCR
, 0x32, ~0x20);
2210 if(ivideo
->chip
>= SIS_340
) {
2211 SiS_SetReg(SISCR
, 0x57, 0x4a);
2213 SiS_SetReg(SISCR
, 0x57, 0x5f);
2215 SiS_SetRegOR(SISCR
, 0x53, 0x02);
2216 while ((SiS_GetRegByte(SISINPSTAT
)) & 0x01) break;
2217 while (!((SiS_GetRegByte(SISINPSTAT
)) & 0x01)) break;
2218 if ((SiS_GetRegByte(SISMISCW
)) & 0x10) temp
= 1;
2219 SiS_SetRegAND(SISCR
, 0x53, 0xfd);
2220 SiS_SetRegAND(SISCR
, 0x57, 0x00);
2224 if(temp
== 0xffff) {
2227 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
,
2228 ivideo
->sisvga_engine
, 0, 0, NULL
, ivideo
->vbflags2
);
2229 } while(((temp
== 0) || (temp
== 0xffff)) && i
--);
2231 if((temp
== 0) || (temp
== 0xffff)) {
2232 if(sisfb_test_DDC1(ivideo
)) temp
= 1;
2236 if((temp
) && (temp
!= 0xffff)) {
2237 SiS_SetRegOR(SISCR
, 0x32, 0x20);
2240 #ifdef CONFIG_FB_SIS_315
2241 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2242 SiS_SetRegANDOR(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, 0xBF, cr63
);
2246 SiS_SetRegANDOR(SISCR
, 0x17, 0x7F, cr17
);
2248 SiS_SetReg(SISSR
, 0x1F, sr1F
);
2251 /* Determine and detect attached devices on SiS30x */
2252 static void SiS_SenseLCD(struct sis_video_info
*ivideo
)
2254 unsigned char buffer
[256];
2255 unsigned short temp
, realcrtno
, i
;
2256 u8 reg
, cr37
= 0, paneltype
= 0;
2259 ivideo
->SiS_Pr
.PanelSelfDetected
= false;
2261 /* LCD detection only for TMDS bridges */
2262 if(!(ivideo
->vbflags2
& VB2_SISTMDSBRIDGE
))
2264 if(ivideo
->vbflags2
& VB2_30xBDH
)
2267 /* If LCD already set up by BIOS, skip it */
2268 reg
= SiS_GetReg(SISCR
, 0x32);
2273 if(ivideo
->SiS_Pr
.DDCPortMixup
)
2276 /* Check DDC capabilities */
2277 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
2278 realcrtno
, 0, &buffer
[0], ivideo
->vbflags2
);
2280 if((!temp
) || (temp
== 0xffff) || (!(temp
& 0x02)))
2284 i
= 3; /* Number of retrys */
2286 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
,
2287 ivideo
->sisvga_engine
, realcrtno
, 1,
2288 &buffer
[0], ivideo
->vbflags2
);
2289 } while((temp
) && i
--);
2294 /* No digital device */
2295 if(!(buffer
[0x14] & 0x80))
2298 /* First detailed timing preferred timing? */
2299 if(!(buffer
[0x18] & 0x02))
2302 xres
= buffer
[0x38] | ((buffer
[0x3a] & 0xf0) << 4);
2303 yres
= buffer
[0x3b] | ((buffer
[0x3d] & 0xf0) << 4);
2315 if((yres
== 1200) && (ivideo
->vbflags2
& VB2_30xC
))
2326 if((buffer
[0x47] & 0x18) == 0x18)
2327 cr37
|= ((((buffer
[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2331 SiS_SetReg(SISCR
, 0x36, paneltype
);
2333 SiS_SetRegANDOR(SISCR
, 0x37, 0x0c, cr37
);
2334 SiS_SetRegOR(SISCR
, 0x32, 0x08);
2336 ivideo
->SiS_Pr
.PanelSelfDetected
= true;
2339 static int SISDoSense(struct sis_video_info
*ivideo
, u16 type
, u16 test
)
2341 int temp
, mytest
, result
, i
, j
;
2343 for(j
= 0; j
< 10; j
++) {
2345 for(i
= 0; i
< 3; i
++) {
2347 SiS_SetReg(SISPART4
, 0x11, (type
& 0x00ff));
2348 temp
= (type
>> 8) | (mytest
& 0x00ff);
2349 SiS_SetRegANDOR(SISPART4
, 0x10, 0xe0, temp
);
2350 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x1500);
2353 temp
= SiS_GetReg(SISPART4
, 0x03);
2356 if(temp
== mytest
) result
++;
2358 SiS_SetReg(SISPART4
, 0x11, 0x00);
2359 SiS_SetRegAND(SISPART4
, 0x10, 0xe0);
2360 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x1000);
2363 if((result
== 0) || (result
>= 2)) break;
2368 static void SiS_Sense30x(struct sis_video_info
*ivideo
)
2370 u8 backupP4_0d
,backupP2_00
,backupP2_4d
,backupSR_1e
,biosflag
=0;
2371 u16 svhs
=0, svhs_c
=0;
2372 u16 cvbs
=0, cvbs_c
=0;
2373 u16 vga2
=0, vga2_c
=0;
2375 char stdstr
[] = "sisfb: Detected";
2376 char tvstr
[] = "TV connected to";
2378 if(ivideo
->vbflags2
& VB2_301
) {
2379 svhs
= 0x00b9; cvbs
= 0x00b3; vga2
= 0x00d1;
2380 myflag
= SiS_GetReg(SISPART4
, 0x01);
2382 svhs
= 0x00dd; cvbs
= 0x00ee; vga2
= 0x00fd;
2384 } else if(ivideo
->vbflags2
& (VB2_301B
| VB2_302B
)) {
2385 svhs
= 0x016b; cvbs
= 0x0174; vga2
= 0x0190;
2386 } else if(ivideo
->vbflags2
& (VB2_301LV
| VB2_302LV
)) {
2387 svhs
= 0x0200; cvbs
= 0x0100;
2388 } else if(ivideo
->vbflags2
& (VB2_301C
| VB2_302ELV
| VB2_307T
| VB2_307LV
)) {
2389 svhs
= 0x016b; cvbs
= 0x0110; vga2
= 0x0190;
2393 vga2_c
= 0x0e08; svhs_c
= 0x0404; cvbs_c
= 0x0804;
2394 if(ivideo
->vbflags
& (VB2_301LV
|VB2_302LV
|VB2_302ELV
|VB2_307LV
)) {
2395 svhs_c
= 0x0408; cvbs_c
= 0x0808;
2399 if(ivideo
->haveXGIROM
) {
2400 biosflag
= ivideo
->bios_abase
[0x58] & 0x03;
2401 } else if(ivideo
->newrom
) {
2402 if(ivideo
->bios_abase
[0x5d] & 0x04) biosflag
|= 0x01;
2403 } else if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2404 if(ivideo
->bios_abase
) {
2405 biosflag
= ivideo
->bios_abase
[0xfe] & 0x03;
2409 if(ivideo
->chip
== SIS_300
) {
2410 myflag
= SiS_GetReg(SISSR
, 0x3b);
2411 if(!(myflag
& 0x01)) vga2
= vga2_c
= 0;
2414 if(!(ivideo
->vbflags2
& VB2_SISVGA2BRIDGE
)) {
2418 backupSR_1e
= SiS_GetReg(SISSR
, 0x1e);
2419 SiS_SetRegOR(SISSR
, 0x1e, 0x20);
2421 backupP4_0d
= SiS_GetReg(SISPART4
, 0x0d);
2422 if(ivideo
->vbflags2
& VB2_30xC
) {
2423 SiS_SetRegANDOR(SISPART4
, 0x0d, ~0x07, 0x01);
2425 SiS_SetRegOR(SISPART4
, 0x0d, 0x04);
2427 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x2000);
2429 backupP2_00
= SiS_GetReg(SISPART2
, 0x00);
2430 SiS_SetReg(SISPART2
, 0x00, ((backupP2_00
| 0x1c) & 0xfc));
2432 backupP2_4d
= SiS_GetReg(SISPART2
, 0x4d);
2433 if(ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
) {
2434 SiS_SetReg(SISPART2
, 0x4d, (backupP2_4d
& ~0x10));
2437 if(!(ivideo
->vbflags2
& VB2_30xCLV
)) {
2438 SISDoSense(ivideo
, 0, 0);
2441 SiS_SetRegAND(SISCR
, 0x32, ~0x14);
2443 if(vga2_c
|| vga2
) {
2444 if(SISDoSense(ivideo
, vga2
, vga2_c
)) {
2445 if(biosflag
& 0x01) {
2446 printk(KERN_INFO
"%s %s SCART output\n", stdstr
, tvstr
);
2447 SiS_SetRegOR(SISCR
, 0x32, 0x04);
2449 printk(KERN_INFO
"%s secondary VGA connection\n", stdstr
);
2450 SiS_SetRegOR(SISCR
, 0x32, 0x10);
2455 SiS_SetRegAND(SISCR
, 0x32, 0x3f);
2457 if(ivideo
->vbflags2
& VB2_30xCLV
) {
2458 SiS_SetRegOR(SISPART4
, 0x0d, 0x04);
2461 if((ivideo
->sisvga_engine
== SIS_315_VGA
) && (ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) {
2462 SiS_SetReg(SISPART2
, 0x4d, (backupP2_4d
| 0x10));
2463 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x2000);
2464 if((result
= SISDoSense(ivideo
, svhs
, 0x0604))) {
2465 if((result
= SISDoSense(ivideo
, cvbs
, 0x0804))) {
2466 printk(KERN_INFO
"%s %s YPbPr component output\n", stdstr
, tvstr
);
2467 SiS_SetRegOR(SISCR
, 0x32, 0x80);
2470 SiS_SetReg(SISPART2
, 0x4d, backupP2_4d
);
2473 SiS_SetRegAND(SISCR
, 0x32, ~0x03);
2475 if(!(ivideo
->vbflags
& TV_YPBPR
)) {
2476 if((result
= SISDoSense(ivideo
, svhs
, svhs_c
))) {
2477 printk(KERN_INFO
"%s %s SVIDEO output\n", stdstr
, tvstr
);
2478 SiS_SetRegOR(SISCR
, 0x32, 0x02);
2480 if((biosflag
& 0x02) || (!result
)) {
2481 if(SISDoSense(ivideo
, cvbs
, cvbs_c
)) {
2482 printk(KERN_INFO
"%s %s COMPOSITE output\n", stdstr
, tvstr
);
2483 SiS_SetRegOR(SISCR
, 0x32, 0x01);
2488 SISDoSense(ivideo
, 0, 0);
2490 SiS_SetReg(SISPART2
, 0x00, backupP2_00
);
2491 SiS_SetReg(SISPART4
, 0x0d, backupP4_0d
);
2492 SiS_SetReg(SISSR
, 0x1e, backupSR_1e
);
2494 if(ivideo
->vbflags2
& VB2_30xCLV
) {
2495 biosflag
= SiS_GetReg(SISPART2
, 0x00);
2496 if(biosflag
& 0x20) {
2497 for(myflag
= 2; myflag
> 0; myflag
--) {
2499 SiS_SetReg(SISPART2
, 0x00, biosflag
);
2504 SiS_SetReg(SISPART2
, 0x00, backupP2_00
);
2507 /* Determine and detect attached TV's on Chrontel */
2508 static void SiS_SenseCh(struct sis_video_info
*ivideo
)
2510 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2512 char stdstr
[] = "sisfb: Chrontel: Detected TV connected to";
2514 #ifdef CONFIG_FB_SIS_300
2515 unsigned char test
[3];
2519 if(ivideo
->chip
< SIS_315H
) {
2521 #ifdef CONFIG_FB_SIS_300
2522 ivideo
->SiS_Pr
.SiS_IF_DEF_CH70xx
= 1; /* Chrontel 700x */
2523 SiS_SetChrontelGPIO(&ivideo
->SiS_Pr
, 0x9c); /* Set general purpose IO for Chrontel communication */
2524 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 1000);
2525 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x25);
2526 /* See Chrontel TB31 for explanation */
2527 temp2
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0e);
2528 if(((temp2
& 0x07) == 0x01) || (temp2
& 0x04)) {
2529 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0e, 0x0b);
2530 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 300);
2532 temp2
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x25);
2533 if(temp2
!= temp1
) temp1
= temp2
;
2535 if((temp1
>= 0x22) && (temp1
<= 0x50)) {
2536 /* Read power status */
2537 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0e);
2538 if((temp1
& 0x03) != 0x03) {
2539 /* Power all outputs */
2540 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0e,0x0b);
2541 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 300);
2543 /* Sense connected TV devices */
2544 for(i
= 0; i
< 3; i
++) {
2545 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x10, 0x01);
2546 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2547 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x10, 0x00);
2548 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2549 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x10);
2550 if(!(temp1
& 0x08)) test
[i
] = 0x02;
2551 else if(!(temp1
& 0x02)) test
[i
] = 0x01;
2553 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2556 if(test
[0] == test
[1]) temp1
= test
[0];
2557 else if(test
[0] == test
[2]) temp1
= test
[0];
2558 else if(test
[1] == test
[2]) temp1
= test
[1];
2561 "sisfb: TV detection unreliable - test results varied\n");
2565 printk(KERN_INFO
"%s SVIDEO output\n", stdstr
);
2566 ivideo
->vbflags
|= TV_SVIDEO
;
2567 SiS_SetRegOR(SISCR
, 0x32, 0x02);
2568 SiS_SetRegAND(SISCR
, 0x32, ~0x05);
2569 } else if (temp1
== 0x01) {
2570 printk(KERN_INFO
"%s CVBS output\n", stdstr
);
2571 ivideo
->vbflags
|= TV_AVIDEO
;
2572 SiS_SetRegOR(SISCR
, 0x32, 0x01);
2573 SiS_SetRegAND(SISCR
, 0x32, ~0x06);
2575 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x0e, 0x01, 0xF8);
2576 SiS_SetRegAND(SISCR
, 0x32, ~0x07);
2578 } else if(temp1
== 0) {
2579 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x0e, 0x01, 0xF8);
2580 SiS_SetRegAND(SISCR
, 0x32, ~0x07);
2582 /* Set general purpose IO for Chrontel communication */
2583 SiS_SetChrontelGPIO(&ivideo
->SiS_Pr
, 0x00);
2588 #ifdef CONFIG_FB_SIS_315
2589 ivideo
->SiS_Pr
.SiS_IF_DEF_CH70xx
= 2; /* Chrontel 7019 */
2590 temp1
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x49);
2591 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x49, 0x20);
2592 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2593 temp2
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x20);
2595 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x20, temp2
);
2596 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2598 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x20, temp2
);
2599 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2600 temp2
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x20);
2601 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x49, temp1
);
2603 if(temp2
& 0x02) temp1
|= 0x01;
2604 if(temp2
& 0x10) temp1
|= 0x01;
2605 if(temp2
& 0x04) temp1
|= 0x02;
2606 if( (temp1
& 0x01) && (temp1
& 0x02) ) temp1
= 0x04;
2609 printk(KERN_INFO
"%s CVBS output\n", stdstr
);
2610 ivideo
->vbflags
|= TV_AVIDEO
;
2611 SiS_SetRegOR(SISCR
, 0x32, 0x01);
2612 SiS_SetRegAND(SISCR
, 0x32, ~0x06);
2615 printk(KERN_INFO
"%s SVIDEO output\n", stdstr
);
2616 ivideo
->vbflags
|= TV_SVIDEO
;
2617 SiS_SetRegOR(SISCR
, 0x32, 0x02);
2618 SiS_SetRegAND(SISCR
, 0x32, ~0x05);
2621 printk(KERN_INFO
"%s SCART output\n", stdstr
);
2622 SiS_SetRegOR(SISCR
, 0x32, 0x04);
2623 SiS_SetRegAND(SISCR
, 0x32, ~0x03);
2626 SiS_SetRegAND(SISCR
, 0x32, ~0x07);
2632 static void sisfb_get_VB_type(struct sis_video_info
*ivideo
)
2634 char stdstr
[] = "sisfb: Detected";
2635 char bridgestr
[] = "video bridge";
2639 /* No CRT2 on XGI Z7 */
2640 if(ivideo
->chip
== XGI_20
)
2643 vb_chipid
= SiS_GetReg(SISPART4
, 0x00);
2646 reg
= SiS_GetReg(SISPART4
, 0x01);
2648 ivideo
->vbflags
|= VB_301
; /* Deprecated */
2649 ivideo
->vbflags2
|= VB2_301
;
2650 printk(KERN_INFO
"%s SiS301 %s\n", stdstr
, bridgestr
);
2651 } else if(reg
< 0xc0) {
2652 ivideo
->vbflags
|= VB_301B
; /* Deprecated */
2653 ivideo
->vbflags2
|= VB2_301B
;
2654 reg
= SiS_GetReg(SISPART4
, 0x23);
2656 ivideo
->vbflags
|= VB_30xBDH
; /* Deprecated */
2657 ivideo
->vbflags2
|= VB2_30xBDH
;
2658 printk(KERN_INFO
"%s SiS301B-DH %s\n", stdstr
, bridgestr
);
2660 printk(KERN_INFO
"%s SiS301B %s\n", stdstr
, bridgestr
);
2662 } else if(reg
< 0xd0) {
2663 ivideo
->vbflags
|= VB_301C
; /* Deprecated */
2664 ivideo
->vbflags2
|= VB2_301C
;
2665 printk(KERN_INFO
"%s SiS301C %s\n", stdstr
, bridgestr
);
2666 } else if(reg
< 0xe0) {
2667 ivideo
->vbflags
|= VB_301LV
; /* Deprecated */
2668 ivideo
->vbflags2
|= VB2_301LV
;
2669 printk(KERN_INFO
"%s SiS301LV %s\n", stdstr
, bridgestr
);
2670 } else if(reg
<= 0xe1) {
2671 reg
= SiS_GetReg(SISPART4
, 0x39);
2673 ivideo
->vbflags
|= VB_302LV
; /* Deprecated */
2674 ivideo
->vbflags2
|= VB2_302LV
;
2675 printk(KERN_INFO
"%s SiS302LV %s\n", stdstr
, bridgestr
);
2677 ivideo
->vbflags
|= VB_301C
; /* Deprecated */
2678 ivideo
->vbflags2
|= VB2_301C
;
2679 printk(KERN_INFO
"%s SiS301C(P4) %s\n", stdstr
, bridgestr
);
2681 ivideo
->vbflags
|= VB_302ELV
; /* Deprecated */
2682 ivideo
->vbflags2
|= VB2_302ELV
;
2683 printk(KERN_INFO
"%s SiS302ELV %s\n", stdstr
, bridgestr
);
2689 ivideo
->vbflags
|= VB_302B
; /* Deprecated */
2690 ivideo
->vbflags2
|= VB2_302B
;
2691 printk(KERN_INFO
"%s SiS302B %s\n", stdstr
, bridgestr
);
2695 if((!(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
)) && (ivideo
->chip
!= SIS_300
)) {
2696 reg
= SiS_GetReg(SISCR
, 0x37);
2697 reg
&= SIS_EXTERNAL_CHIP_MASK
;
2699 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2700 #ifdef CONFIG_FB_SIS_300
2702 case SIS_EXTERNAL_CHIP_LVDS
:
2703 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2704 ivideo
->vbflags2
|= VB2_LVDS
;
2706 case SIS_EXTERNAL_CHIP_TRUMPION
:
2707 ivideo
->vbflags
|= (VB_LVDS
| VB_TRUMPION
); /* Deprecated */
2708 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_TRUMPION
);
2710 case SIS_EXTERNAL_CHIP_CHRONTEL
:
2711 ivideo
->vbflags
|= VB_CHRONTEL
; /* Deprecated */
2712 ivideo
->vbflags2
|= VB2_CHRONTEL
;
2714 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL
:
2715 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2716 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2719 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 1;
2721 } else if(ivideo
->chip
< SIS_661
) {
2722 #ifdef CONFIG_FB_SIS_315
2724 case SIS310_EXTERNAL_CHIP_LVDS
:
2725 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2726 ivideo
->vbflags2
|= VB2_LVDS
;
2728 case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL
:
2729 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2730 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2733 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 2;
2735 } else if(ivideo
->chip
>= SIS_661
) {
2736 #ifdef CONFIG_FB_SIS_315
2737 reg
= SiS_GetReg(SISCR
, 0x38);
2741 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2742 ivideo
->vbflags2
|= VB2_LVDS
;
2745 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2746 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2749 ivideo
->vbflags
|= (VB_LVDS
| VB_CONEXANT
); /* Deprecated */
2750 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CONEXANT
);
2753 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 2;
2756 if(ivideo
->vbflags2
& VB2_LVDS
) {
2757 printk(KERN_INFO
"%s LVDS transmitter\n", stdstr
);
2759 if((ivideo
->sisvga_engine
== SIS_300_VGA
) && (ivideo
->vbflags2
& VB2_TRUMPION
)) {
2760 printk(KERN_INFO
"%s Trumpion Zurac LCD scaler\n", stdstr
);
2762 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
2763 printk(KERN_INFO
"%s Chrontel TV encoder\n", stdstr
);
2765 if((ivideo
->chip
>= SIS_661
) && (ivideo
->vbflags2
& VB2_CONEXANT
)) {
2766 printk(KERN_INFO
"%s Conexant external device\n", stdstr
);
2770 if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
2771 SiS_SenseLCD(ivideo
);
2772 SiS_Sense30x(ivideo
);
2773 } else if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
2774 SiS_SenseCh(ivideo
);
2778 /* ---------- Engine initialization routines ------------ */
2781 sisfb_engine_init(struct sis_video_info
*ivideo
)
2784 /* Initialize command queue (we use MMIO only) */
2786 /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
2788 ivideo
->caps
&= ~(TURBO_QUEUE_CAP
|
2789 MMIO_CMD_QUEUE_CAP
|
2793 #ifdef CONFIG_FB_SIS_300
2794 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2798 tqueue_pos
= (ivideo
->video_size
- ivideo
->cmdQueueSize
) / (64 * 1024);
2800 tq_state
= SiS_GetReg(SISSR
, IND_SIS_TURBOQUEUE_SET
);
2803 tq_state
|= (u8
)(tqueue_pos
>> 8);
2804 SiS_SetReg(SISSR
, IND_SIS_TURBOQUEUE_SET
, tq_state
);
2806 SiS_SetReg(SISSR
, IND_SIS_TURBOQUEUE_ADR
, (u8
)(tqueue_pos
& 0xff));
2808 ivideo
->caps
|= TURBO_QUEUE_CAP
;
2812 #ifdef CONFIG_FB_SIS_315
2813 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2814 u32 tempq
= 0, templ
;
2817 if(ivideo
->chip
== XGI_20
) {
2818 switch(ivideo
->cmdQueueSize
) {
2820 temp
= SIS_CMD_QUEUE_SIZE_Z7_64k
;
2824 temp
= SIS_CMD_QUEUE_SIZE_Z7_128k
;
2827 switch(ivideo
->cmdQueueSize
) {
2828 case (4 * 1024 * 1024):
2829 temp
= SIS_CMD_QUEUE_SIZE_4M
;
2831 case (2 * 1024 * 1024):
2832 temp
= SIS_CMD_QUEUE_SIZE_2M
;
2834 case (1 * 1024 * 1024):
2835 temp
= SIS_CMD_QUEUE_SIZE_1M
;
2839 temp
= SIS_CMD_QUEUE_SIZE_512k
;
2843 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_THRESHOLD
, COMMAND_QUEUE_THRESHOLD
);
2844 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, SIS_CMD_QUEUE_RESET
);
2846 if((ivideo
->chip
>= XGI_40
) && ivideo
->modechanged
) {
2847 /* Must disable dual pipe on XGI_40. Can't do
2848 * this in MMIO mode, because it requires
2849 * setting/clearing a bit in the MMIO fire trigger
2852 if(!((templ
= MMIO_IN32(ivideo
->mmio_vbase
, 0x8240)) & (1 << 10))) {
2854 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, 0);
2856 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, (temp
| SIS_VRAM_CMDQUEUE_ENABLE
));
2858 tempq
= MMIO_IN32(ivideo
->mmio_vbase
, Q_READ_PTR
);
2859 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, tempq
);
2861 tempq
= (u32
)(ivideo
->video_size
- ivideo
->cmdQueueSize
);
2862 MMIO_OUT32(ivideo
->mmio_vbase
, Q_BASE_ADDR
, tempq
);
2864 writel(0x16800000 + 0x8240, ivideo
->video_vbase
+ tempq
);
2865 writel(templ
| (1 << 10), ivideo
->video_vbase
+ tempq
+ 4);
2866 writel(0x168F0000, ivideo
->video_vbase
+ tempq
+ 8);
2867 writel(0x168F0000, ivideo
->video_vbase
+ tempq
+ 12);
2869 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, (tempq
+ 16));
2871 sisfb_syncaccel(ivideo
);
2873 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, SIS_CMD_QUEUE_RESET
);
2878 tempq
= MMIO_IN32(ivideo
->mmio_vbase
, MMIO_QUEUE_READPORT
);
2879 MMIO_OUT32(ivideo
->mmio_vbase
, MMIO_QUEUE_WRITEPORT
, tempq
);
2881 temp
|= (SIS_MMIO_CMD_ENABLE
| SIS_CMD_AUTO_CORR
);
2882 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, temp
);
2884 tempq
= (u32
)(ivideo
->video_size
- ivideo
->cmdQueueSize
);
2885 MMIO_OUT32(ivideo
->mmio_vbase
, MMIO_QUEUE_PHYBASE
, tempq
);
2887 ivideo
->caps
|= MMIO_CMD_QUEUE_CAP
;
2891 ivideo
->engineok
= 1;
2894 static void sisfb_detect_lcd_type(struct sis_video_info
*ivideo
)
2899 reg
= SiS_GetReg(SISCR
, 0x36);
2901 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2902 ivideo
->CRT2LCDType
= sis300paneltype
[reg
];
2903 } else if(ivideo
->chip
>= SIS_661
) {
2904 ivideo
->CRT2LCDType
= sis661paneltype
[reg
];
2906 ivideo
->CRT2LCDType
= sis310paneltype
[reg
];
2907 if((ivideo
->chip
== SIS_550
) && (sisfb_fstn
)) {
2908 if((ivideo
->CRT2LCDType
!= LCD_320x240_2
) &&
2909 (ivideo
->CRT2LCDType
!= LCD_320x240_3
)) {
2910 ivideo
->CRT2LCDType
= LCD_320x240
;
2915 if(ivideo
->CRT2LCDType
== LCD_UNKNOWN
) {
2916 /* For broken BIOSes: Assume 1024x768, RGB18 */
2917 ivideo
->CRT2LCDType
= LCD_1024x768
;
2918 SiS_SetRegANDOR(SISCR
, 0x36, 0xf0, 0x02);
2919 SiS_SetRegANDOR(SISCR
, 0x37, 0xee, 0x01);
2920 printk(KERN_DEBUG
"sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg
);
2923 for(i
= 0; i
< SIS_LCD_NUMBER
; i
++) {
2924 if(ivideo
->CRT2LCDType
== sis_lcd_data
[i
].lcdtype
) {
2925 ivideo
->lcdxres
= sis_lcd_data
[i
].xres
;
2926 ivideo
->lcdyres
= sis_lcd_data
[i
].yres
;
2927 ivideo
->lcddefmodeidx
= sis_lcd_data
[i
].default_mode_idx
;
2932 #ifdef CONFIG_FB_SIS_300
2933 if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_BARCO1366
) {
2934 ivideo
->lcdxres
= 1360; ivideo
->lcdyres
= 1024;
2935 ivideo
->lcddefmodeidx
= DEFAULT_MODE_1360
;
2936 } else if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_PANEL848
) {
2937 ivideo
->lcdxres
= 848; ivideo
->lcdyres
= 480;
2938 ivideo
->lcddefmodeidx
= DEFAULT_MODE_848
;
2939 } else if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_PANEL856
) {
2940 ivideo
->lcdxres
= 856; ivideo
->lcdyres
= 480;
2941 ivideo
->lcddefmodeidx
= DEFAULT_MODE_856
;
2945 printk(KERN_DEBUG
"sisfb: Detected %dx%d flat panel\n",
2946 ivideo
->lcdxres
, ivideo
->lcdyres
);
2949 static void sisfb_save_pdc_emi(struct sis_video_info
*ivideo
)
2951 #ifdef CONFIG_FB_SIS_300
2952 /* Save the current PanelDelayCompensation if the LCD is currently used */
2953 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2954 if(ivideo
->vbflags2
& (VB2_LVDS
| VB2_30xBDH
)) {
2956 tmp
= SiS_GetReg(SISCR
, 0x30);
2958 /* Currently on LCD? If yes, read current pdc */
2959 ivideo
->detectedpdc
= SiS_GetReg(SISPART1
, 0x13);
2960 ivideo
->detectedpdc
&= 0x3c;
2961 if(ivideo
->SiS_Pr
.PDC
== -1) {
2962 /* Let option override detection */
2963 ivideo
->SiS_Pr
.PDC
= ivideo
->detectedpdc
;
2965 printk(KERN_INFO
"sisfb: Detected LCD PDC 0x%02x\n",
2966 ivideo
->detectedpdc
);
2968 if((ivideo
->SiS_Pr
.PDC
!= -1) &&
2969 (ivideo
->SiS_Pr
.PDC
!= ivideo
->detectedpdc
)) {
2970 printk(KERN_INFO
"sisfb: Using LCD PDC 0x%02x\n",
2971 ivideo
->SiS_Pr
.PDC
);
2977 #ifdef CONFIG_FB_SIS_315
2978 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2980 /* Try to find about LCDA */
2981 if(ivideo
->vbflags2
& VB2_SISLCDABRIDGE
) {
2983 tmp
= SiS_GetReg(SISPART1
, 0x13);
2985 ivideo
->SiS_Pr
.SiS_UseLCDA
= true;
2986 ivideo
->detectedlcda
= 0x03;
2991 if(ivideo
->vbflags2
& VB2_SISLVDSBRIDGE
) {
2993 tmp
= SiS_GetReg(SISCR
, 0x30);
2994 if((tmp
& 0x20) || (ivideo
->detectedlcda
!= 0xff)) {
2995 /* Currently on LCD? If yes, read current pdc */
2997 pdc
= SiS_GetReg(SISPART1
, 0x2D);
2998 ivideo
->detectedpdc
= (pdc
& 0x0f) << 1;
2999 ivideo
->detectedpdca
= (pdc
& 0xf0) >> 3;
3000 pdc
= SiS_GetReg(SISPART1
, 0x35);
3001 ivideo
->detectedpdc
|= ((pdc
>> 7) & 0x01);
3002 pdc
= SiS_GetReg(SISPART1
, 0x20);
3003 ivideo
->detectedpdca
|= ((pdc
>> 6) & 0x01);
3004 if(ivideo
->newrom
) {
3005 /* New ROM invalidates other PDC resp. */
3006 if(ivideo
->detectedlcda
!= 0xff) {
3007 ivideo
->detectedpdc
= 0xff;
3009 ivideo
->detectedpdca
= 0xff;
3012 if(ivideo
->SiS_Pr
.PDC
== -1) {
3013 if(ivideo
->detectedpdc
!= 0xff) {
3014 ivideo
->SiS_Pr
.PDC
= ivideo
->detectedpdc
;
3017 if(ivideo
->SiS_Pr
.PDCA
== -1) {
3018 if(ivideo
->detectedpdca
!= 0xff) {
3019 ivideo
->SiS_Pr
.PDCA
= ivideo
->detectedpdca
;
3022 if(ivideo
->detectedpdc
!= 0xff) {
3024 "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3025 ivideo
->detectedpdc
);
3027 if(ivideo
->detectedpdca
!= 0xff) {
3029 "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3030 ivideo
->detectedpdca
);
3035 if(ivideo
->vbflags2
& VB2_SISEMIBRIDGE
) {
3036 ivideo
->SiS_Pr
.EMI_30
= SiS_GetReg(SISPART4
, 0x30);
3037 ivideo
->SiS_Pr
.EMI_31
= SiS_GetReg(SISPART4
, 0x31);
3038 ivideo
->SiS_Pr
.EMI_32
= SiS_GetReg(SISPART4
, 0x32);
3039 ivideo
->SiS_Pr
.EMI_33
= SiS_GetReg(SISPART4
, 0x33);
3040 ivideo
->SiS_Pr
.HaveEMI
= true;
3041 if((tmp
& 0x20) || (ivideo
->detectedlcda
!= 0xff)) {
3042 ivideo
->SiS_Pr
.HaveEMILCD
= true;
3047 /* Let user override detected PDCs (all bridges) */
3048 if(ivideo
->vbflags2
& VB2_30xBLV
) {
3049 if((ivideo
->SiS_Pr
.PDC
!= -1) &&
3050 (ivideo
->SiS_Pr
.PDC
!= ivideo
->detectedpdc
)) {
3051 printk(KERN_INFO
"sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3052 ivideo
->SiS_Pr
.PDC
);
3054 if((ivideo
->SiS_Pr
.PDCA
!= -1) &&
3055 (ivideo
->SiS_Pr
.PDCA
!= ivideo
->detectedpdca
)) {
3056 printk(KERN_INFO
"sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3057 ivideo
->SiS_Pr
.PDCA
);
3065 /* -------------------- Memory manager routines ---------------------- */
3067 static u32
sisfb_getheapstart(struct sis_video_info
*ivideo
)
3069 u32 ret
= ivideo
->sisfb_parm_mem
* 1024;
3070 u32 maxoffs
= ivideo
->video_size
- ivideo
->hwcursor_size
- ivideo
->cmdQueueSize
;
3073 /* Calculate heap start = end of memory for console
3075 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3076 * C = console, D = heap, H = HWCursor, Q = cmd-queue
3078 * On 76x in UMA+LFB mode, the layout is as follows:
3079 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3080 * where the heap is the entire UMA area, eventually
3081 * into the LFB area if the given mem parameter is
3082 * higher than the size of the UMA memory.
3084 * Basically given by "mem" parameter
3086 * maximum = videosize - cmd_queue - hwcursor
3087 * (results in a heap of size 0)
3088 * default = SiS 300: depends on videosize
3089 * SiS 315/330/340/XGI: 32k below max
3092 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3093 if(ivideo
->video_size
> 0x1000000) {
3095 } else if(ivideo
->video_size
> 0x800000) {
3100 } else if(ivideo
->UMAsize
&& ivideo
->LFBsize
) {
3103 def
= maxoffs
- 0x8000;
3106 /* Use default for secondary card for now (FIXME) */
3107 if((!ret
) || (ret
> maxoffs
) || (ivideo
->cardnumber
!= 0))
3113 static u32
sisfb_getheapsize(struct sis_video_info
*ivideo
)
3115 u32 max
= ivideo
->video_size
- ivideo
->hwcursor_size
- ivideo
->cmdQueueSize
;
3118 if(ivideo
->UMAsize
&& ivideo
->LFBsize
) {
3119 if( (!ivideo
->sisfb_parm_mem
) ||
3120 ((ivideo
->sisfb_parm_mem
* 1024) > max
) ||
3121 ((max
- (ivideo
->sisfb_parm_mem
* 1024)) < ivideo
->UMAsize
) ) {
3122 ret
= ivideo
->UMAsize
;
3123 max
-= ivideo
->UMAsize
;
3125 ret
= max
- (ivideo
->sisfb_parm_mem
* 1024);
3126 max
= ivideo
->sisfb_parm_mem
* 1024;
3128 ivideo
->video_offset
= ret
;
3129 ivideo
->sisfb_mem
= max
;
3131 ret
= max
- ivideo
->heapstart
;
3132 ivideo
->sisfb_mem
= ivideo
->heapstart
;
3138 static int sisfb_heap_init(struct sis_video_info
*ivideo
)
3142 ivideo
->video_offset
= 0;
3143 if(ivideo
->sisfb_parm_mem
) {
3144 if( (ivideo
->sisfb_parm_mem
< (2 * 1024 * 1024)) ||
3145 (ivideo
->sisfb_parm_mem
> ivideo
->video_size
) ) {
3146 ivideo
->sisfb_parm_mem
= 0;
3150 ivideo
->heapstart
= sisfb_getheapstart(ivideo
);
3151 ivideo
->sisfb_heap_size
= sisfb_getheapsize(ivideo
);
3153 ivideo
->sisfb_heap_start
= ivideo
->video_vbase
+ ivideo
->heapstart
;
3154 ivideo
->sisfb_heap_end
= ivideo
->sisfb_heap_start
+ ivideo
->sisfb_heap_size
;
3156 printk(KERN_INFO
"sisfb: Memory heap starting at %dK, size %dK\n",
3157 (int)(ivideo
->heapstart
/ 1024), (int)(ivideo
->sisfb_heap_size
/ 1024));
3159 ivideo
->sisfb_heap
.vinfo
= ivideo
;
3161 ivideo
->sisfb_heap
.poha_chain
= NULL
;
3162 ivideo
->sisfb_heap
.poh_freelist
= NULL
;
3164 poh
= sisfb_poh_new_node(&ivideo
->sisfb_heap
);
3168 poh
->poh_next
= &ivideo
->sisfb_heap
.oh_free
;
3169 poh
->poh_prev
= &ivideo
->sisfb_heap
.oh_free
;
3170 poh
->size
= ivideo
->sisfb_heap_size
;
3171 poh
->offset
= ivideo
->heapstart
;
3173 ivideo
->sisfb_heap
.oh_free
.poh_next
= poh
;
3174 ivideo
->sisfb_heap
.oh_free
.poh_prev
= poh
;
3175 ivideo
->sisfb_heap
.oh_free
.size
= 0;
3176 ivideo
->sisfb_heap
.max_freesize
= poh
->size
;
3178 ivideo
->sisfb_heap
.oh_used
.poh_next
= &ivideo
->sisfb_heap
.oh_used
;
3179 ivideo
->sisfb_heap
.oh_used
.poh_prev
= &ivideo
->sisfb_heap
.oh_used
;
3180 ivideo
->sisfb_heap
.oh_used
.size
= SENTINEL
;
3182 if(ivideo
->cardnumber
== 0) {
3183 /* For the first card, make this heap the "global" one
3184 * for old DRM (which could handle only one card)
3186 sisfb_heap
= &ivideo
->sisfb_heap
;
3192 static struct SIS_OH
*
3193 sisfb_poh_new_node(struct SIS_HEAP
*memheap
)
3195 struct SIS_OHALLOC
*poha
;
3200 if(memheap
->poh_freelist
== NULL
) {
3201 poha
= kmalloc(SIS_OH_ALLOC_SIZE
, GFP_KERNEL
);
3205 poha
->poha_next
= memheap
->poha_chain
;
3206 memheap
->poha_chain
= poha
;
3208 cOhs
= (SIS_OH_ALLOC_SIZE
- sizeof(struct SIS_OHALLOC
)) / sizeof(struct SIS_OH
) + 1;
3210 poh
= &poha
->aoh
[0];
3211 for(i
= cOhs
- 1; i
!= 0; i
--) {
3212 poh
->poh_next
= poh
+ 1;
3216 poh
->poh_next
= NULL
;
3217 memheap
->poh_freelist
= &poha
->aoh
[0];
3220 poh
= memheap
->poh_freelist
;
3221 memheap
->poh_freelist
= poh
->poh_next
;
3226 static struct SIS_OH
*
3227 sisfb_poh_allocate(struct SIS_HEAP
*memheap
, u32 size
)
3229 struct SIS_OH
*pohThis
;
3230 struct SIS_OH
*pohRoot
;
3233 if(size
> memheap
->max_freesize
) {
3234 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3235 (unsigned int) size
/ 1024);
3239 pohThis
= memheap
->oh_free
.poh_next
;
3241 while(pohThis
!= &memheap
->oh_free
) {
3242 if(size
<= pohThis
->size
) {
3246 pohThis
= pohThis
->poh_next
;
3250 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3251 (unsigned int) size
/ 1024);
3255 if(size
== pohThis
->size
) {
3257 sisfb_delete_node(pohThis
);
3259 pohRoot
= sisfb_poh_new_node(memheap
);
3263 pohRoot
->offset
= pohThis
->offset
;
3264 pohRoot
->size
= size
;
3266 pohThis
->offset
+= size
;
3267 pohThis
->size
-= size
;
3270 memheap
->max_freesize
-= size
;
3272 pohThis
= &memheap
->oh_used
;
3273 sisfb_insert_node(pohThis
, pohRoot
);
3279 sisfb_delete_node(struct SIS_OH
*poh
)
3281 poh
->poh_prev
->poh_next
= poh
->poh_next
;
3282 poh
->poh_next
->poh_prev
= poh
->poh_prev
;
3286 sisfb_insert_node(struct SIS_OH
*pohList
, struct SIS_OH
*poh
)
3288 struct SIS_OH
*pohTemp
= pohList
->poh_next
;
3290 pohList
->poh_next
= poh
;
3291 pohTemp
->poh_prev
= poh
;
3293 poh
->poh_prev
= pohList
;
3294 poh
->poh_next
= pohTemp
;
3297 static struct SIS_OH
*
3298 sisfb_poh_free(struct SIS_HEAP
*memheap
, u32 base
)
3300 struct SIS_OH
*pohThis
;
3301 struct SIS_OH
*poh_freed
;
3302 struct SIS_OH
*poh_prev
;
3303 struct SIS_OH
*poh_next
;
3308 poh_freed
= memheap
->oh_used
.poh_next
;
3310 while(poh_freed
!= &memheap
->oh_used
) {
3311 if(poh_freed
->offset
== base
) {
3316 poh_freed
= poh_freed
->poh_next
;
3322 memheap
->max_freesize
+= poh_freed
->size
;
3324 poh_prev
= poh_next
= NULL
;
3325 ulUpper
= poh_freed
->offset
+ poh_freed
->size
;
3326 ulLower
= poh_freed
->offset
;
3328 pohThis
= memheap
->oh_free
.poh_next
;
3330 while(pohThis
!= &memheap
->oh_free
) {
3331 if(pohThis
->offset
== ulUpper
) {
3333 } else if((pohThis
->offset
+ pohThis
->size
) == ulLower
) {
3336 pohThis
= pohThis
->poh_next
;
3339 sisfb_delete_node(poh_freed
);
3341 if(poh_prev
&& poh_next
) {
3342 poh_prev
->size
+= (poh_freed
->size
+ poh_next
->size
);
3343 sisfb_delete_node(poh_next
);
3344 sisfb_free_node(memheap
, poh_freed
);
3345 sisfb_free_node(memheap
, poh_next
);
3350 poh_prev
->size
+= poh_freed
->size
;
3351 sisfb_free_node(memheap
, poh_freed
);
3356 poh_next
->size
+= poh_freed
->size
;
3357 poh_next
->offset
= poh_freed
->offset
;
3358 sisfb_free_node(memheap
, poh_freed
);
3362 sisfb_insert_node(&memheap
->oh_free
, poh_freed
);
3368 sisfb_free_node(struct SIS_HEAP
*memheap
, struct SIS_OH
*poh
)
3373 poh
->poh_next
= memheap
->poh_freelist
;
3374 memheap
->poh_freelist
= poh
;
3378 sis_int_malloc(struct sis_video_info
*ivideo
, struct sis_memreq
*req
)
3380 struct SIS_OH
*poh
= NULL
;
3382 if((ivideo
) && (ivideo
->sisfb_id
== SISFB_ID
) && (!ivideo
->havenoheap
))
3383 poh
= sisfb_poh_allocate(&ivideo
->sisfb_heap
, (u32
)req
->size
);
3386 req
->offset
= req
->size
= 0;
3387 DPRINTK("sisfb: Video RAM allocation failed\n");
3389 req
->offset
= poh
->offset
;
3390 req
->size
= poh
->size
;
3391 DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3392 (poh
->offset
+ ivideo
->video_vbase
));
3397 sis_malloc(struct sis_memreq
*req
)
3399 struct sis_video_info
*ivideo
= sisfb_heap
->vinfo
;
3401 if(&ivideo
->sisfb_heap
== sisfb_heap
)
3402 sis_int_malloc(ivideo
, req
);
3404 req
->offset
= req
->size
= 0;
3408 sis_malloc_new(struct pci_dev
*pdev
, struct sis_memreq
*req
)
3410 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
3412 sis_int_malloc(ivideo
, req
);
3415 /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3418 sis_int_free(struct sis_video_info
*ivideo
, u32 base
)
3422 if((!ivideo
) || (ivideo
->sisfb_id
!= SISFB_ID
) || (ivideo
->havenoheap
))
3425 poh
= sisfb_poh_free(&ivideo
->sisfb_heap
, base
);
3428 DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
3429 (unsigned int) base
);
3436 struct sis_video_info
*ivideo
= sisfb_heap
->vinfo
;
3438 sis_int_free(ivideo
, base
);
3442 sis_free_new(struct pci_dev
*pdev
, u32 base
)
3444 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
3446 sis_int_free(ivideo
, base
);
3449 /* --------------------- SetMode routines ------------------------- */
3452 sisfb_check_engine_and_sync(struct sis_video_info
*ivideo
)
3456 /* Check if MMIO and engines are enabled,
3457 * and sync in case they are. Can't use
3458 * ivideo->accel here, as this might have
3459 * been changed before this is called.
3461 cr30
= SiS_GetReg(SISSR
, IND_SIS_PCI_ADDRESS_SET
);
3462 cr31
= SiS_GetReg(SISSR
, IND_SIS_MODULE_ENABLE
);
3463 /* MMIO and 2D/3D engine enabled? */
3464 if((cr30
& SIS_MEM_MAP_IO_ENABLE
) && (cr31
& 0x42)) {
3465 #ifdef CONFIG_FB_SIS_300
3466 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3467 /* Don't care about TurboQueue. It's
3468 * enough to know that the engines
3471 sisfb_syncaccel(ivideo
);
3474 #ifdef CONFIG_FB_SIS_315
3475 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3476 /* Check that any queue mode is
3477 * enabled, and that the queue
3478 * is not in the state of "reset"
3480 cr30
= SiS_GetReg(SISSR
, 0x26);
3481 if((cr30
& 0xe0) && (!(cr30
& 0x01))) {
3482 sisfb_syncaccel(ivideo
);
3490 sisfb_pre_setmode(struct sis_video_info
*ivideo
)
3492 u8 cr30
= 0, cr31
= 0, cr33
= 0, cr35
= 0, cr38
= 0;
3495 ivideo
->currentvbflags
&= (VB_VIDEOBRIDGE
| VB_DISPTYPE_DISP2
);
3497 SiS_SetReg(SISSR
, 0x05, 0x86);
3499 cr31
= SiS_GetReg(SISCR
, 0x31);
3503 cr33
= ivideo
->rate_idx
& 0x0F;
3505 #ifdef CONFIG_FB_SIS_315
3506 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3507 if(ivideo
->chip
>= SIS_661
) {
3508 cr38
= SiS_GetReg(SISCR
, 0x38);
3509 cr38
&= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
3512 cr38
= SiS_GetReg(SISCR
, tvregnum
);
3513 cr38
&= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
3517 #ifdef CONFIG_FB_SIS_300
3518 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3520 cr38
= SiS_GetReg(SISCR
, tvregnum
);
3524 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
3525 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
3526 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
3528 switch(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
3531 cr38
&= ~0xc0; /* Clear PAL-M / PAL-N bits */
3532 if((ivideo
->vbflags
& TV_YPBPR
) && (ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) {
3533 #ifdef CONFIG_FB_SIS_315
3534 if(ivideo
->chip
>= SIS_661
) {
3536 if(ivideo
->vbflags
& TV_YPBPR525P
) cr35
|= 0x20;
3537 else if(ivideo
->vbflags
& TV_YPBPR750P
) cr35
|= 0x40;
3538 else if(ivideo
->vbflags
& TV_YPBPR1080I
) cr35
|= 0x60;
3539 cr30
|= SIS_SIMULTANEOUS_VIEW_ENABLE
;
3541 ivideo
->currentvbflags
|= (TV_YPBPR
| (ivideo
->vbflags
& TV_YPBPRALL
));
3542 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3543 cr30
|= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE
);
3545 if(ivideo
->vbflags
& TV_YPBPR525P
) cr38
|= 0x10;
3546 else if(ivideo
->vbflags
& TV_YPBPR750P
) cr38
|= 0x20;
3547 else if(ivideo
->vbflags
& TV_YPBPR1080I
) cr38
|= 0x30;
3549 ivideo
->currentvbflags
|= (TV_YPBPR
| (ivideo
->vbflags
& TV_YPBPRALL
));
3552 } else if((ivideo
->vbflags
& TV_HIVISION
) &&
3553 (ivideo
->vbflags2
& VB2_SISHIVISIONBRIDGE
)) {
3554 if(ivideo
->chip
>= SIS_661
) {
3560 cr30
|= SIS_SIMULTANEOUS_VIEW_ENABLE
;
3563 ivideo
->currentvbflags
|= TV_HIVISION
;
3564 } else if(ivideo
->vbflags
& TV_SCART
) {
3565 cr30
= (SIS_VB_OUTPUT_SCART
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3568 ivideo
->currentvbflags
|= TV_SCART
;
3570 if(ivideo
->vbflags
& TV_SVIDEO
) {
3571 cr30
= (SIS_VB_OUTPUT_SVIDEO
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3572 ivideo
->currentvbflags
|= TV_SVIDEO
;
3574 if(ivideo
->vbflags
& TV_AVIDEO
) {
3575 cr30
= (SIS_VB_OUTPUT_COMPOSITE
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3576 ivideo
->currentvbflags
|= TV_AVIDEO
;
3579 cr31
|= SIS_DRIVER_MODE
;
3581 if(ivideo
->vbflags
& (TV_AVIDEO
| TV_SVIDEO
)) {
3582 if(ivideo
->vbflags
& TV_PAL
) {
3583 cr31
|= 0x01; cr35
|= 0x01;
3584 ivideo
->currentvbflags
|= TV_PAL
;
3585 if(ivideo
->vbflags
& TV_PALM
) {
3586 cr38
|= 0x40; cr35
|= 0x04;
3587 ivideo
->currentvbflags
|= TV_PALM
;
3588 } else if(ivideo
->vbflags
& TV_PALN
) {
3589 cr38
|= 0x80; cr35
|= 0x08;
3590 ivideo
->currentvbflags
|= TV_PALN
;
3593 cr31
&= ~0x01; cr35
&= ~0x01;
3594 ivideo
->currentvbflags
|= TV_NTSC
;
3595 if(ivideo
->vbflags
& TV_NTSCJ
) {
3596 cr38
|= 0x40; cr35
|= 0x02;
3597 ivideo
->currentvbflags
|= TV_NTSCJ
;
3604 cr30
= (SIS_VB_OUTPUT_LCD
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3605 cr31
|= SIS_DRIVER_MODE
;
3606 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, ivideo
->sisfb_dstn
);
3607 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, ivideo
->sisfb_fstn
);
3608 ivideo
->curFSTN
= ivideo
->sisfb_fstn
;
3609 ivideo
->curDSTN
= ivideo
->sisfb_dstn
;
3613 cr30
= (SIS_VB_OUTPUT_CRT2
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3614 cr31
|= SIS_DRIVER_MODE
;
3615 if(ivideo
->sisfb_nocrt2rate
) {
3616 cr33
|= (sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
<< 4);
3618 cr33
|= ((ivideo
->rate_idx
& 0x0F) << 4);
3622 default: /* disable CRT2 */
3624 cr31
|= (SIS_DRIVER_MODE
| SIS_VB_OUTPUT_DISABLE
);
3627 SiS_SetReg(SISCR
, 0x30, cr30
);
3628 SiS_SetReg(SISCR
, 0x33, cr33
);
3630 if(ivideo
->chip
>= SIS_661
) {
3631 #ifdef CONFIG_FB_SIS_315
3632 cr31
&= ~0x01; /* Clear PAL flag (now in CR35) */
3633 SiS_SetRegANDOR(SISCR
, 0x35, ~0x10, cr35
); /* Leave overscan bit alone */
3634 cr38
&= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
3635 SiS_SetRegANDOR(SISCR
, 0x38, 0xf8, cr38
);
3637 } else if(ivideo
->chip
!= SIS_300
) {
3638 SiS_SetReg(SISCR
, tvregnum
, cr38
);
3640 SiS_SetReg(SISCR
, 0x31, cr31
);
3642 ivideo
->SiS_Pr
.SiS_UseOEM
= ivideo
->sisfb_useoem
;
3644 sisfb_check_engine_and_sync(ivideo
);
3647 /* Fix SR11 for 661 and later */
3648 #ifdef CONFIG_FB_SIS_315
3650 sisfb_fixup_SR11(struct sis_video_info
*ivideo
)
3654 if(ivideo
->chip
>= SIS_661
) {
3655 tmpreg
= SiS_GetReg(SISSR
, 0x11);
3657 tmpreg
= SiS_GetReg(SISSR
, 0x3e);
3658 tmpreg
= (tmpreg
+ 1) & 0xff;
3659 SiS_SetReg(SISSR
, 0x3e, tmpreg
);
3660 tmpreg
= SiS_GetReg(SISSR
, 0x11);
3663 SiS_SetRegAND(SISSR
, 0x11, 0x0f);
3670 sisfb_set_TVxposoffset(struct sis_video_info
*ivideo
, int val
)
3672 if(val
> 32) val
= 32;
3673 if(val
< -32) val
= -32;
3674 ivideo
->tvxpos
= val
;
3676 if(ivideo
->sisfblocked
) return;
3677 if(!ivideo
->modechanged
) return;
3679 if(ivideo
->currentvbflags
& CRT2_TV
) {
3681 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3683 int x
= ivideo
->tvx
;
3685 switch(ivideo
->chronteltype
) {
3689 SiS_SetReg(SISSR
, 0x05, 0x86);
3690 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0a, (x
& 0xff));
3691 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x08, ((x
& 0x0100) >> 7), 0xFD);
3694 /* Not supported by hardware */
3698 } else if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3700 u8 p2_1f
,p2_20
,p2_2b
,p2_42
,p2_43
;
3701 unsigned short temp
;
3703 p2_1f
= ivideo
->p2_1f
;
3704 p2_20
= ivideo
->p2_20
;
3705 p2_2b
= ivideo
->p2_2b
;
3706 p2_42
= ivideo
->p2_42
;
3707 p2_43
= ivideo
->p2_43
;
3709 temp
= p2_1f
| ((p2_20
& 0xf0) << 4);
3711 p2_1f
= temp
& 0xff;
3712 p2_20
= (temp
& 0xf00) >> 4;
3713 p2_2b
= ((p2_2b
& 0x0f) + (val
* 2)) & 0x0f;
3714 temp
= p2_43
| ((p2_42
& 0xf0) << 4);
3716 p2_43
= temp
& 0xff;
3717 p2_42
= (temp
& 0xf00) >> 4;
3718 SiS_SetReg(SISPART2
, 0x1f, p2_1f
);
3719 SiS_SetRegANDOR(SISPART2
, 0x20, 0x0F, p2_20
);
3720 SiS_SetRegANDOR(SISPART2
, 0x2b, 0xF0, p2_2b
);
3721 SiS_SetRegANDOR(SISPART2
, 0x42, 0x0F, p2_42
);
3722 SiS_SetReg(SISPART2
, 0x43, p2_43
);
3728 sisfb_set_TVyposoffset(struct sis_video_info
*ivideo
, int val
)
3730 if(val
> 32) val
= 32;
3731 if(val
< -32) val
= -32;
3732 ivideo
->tvypos
= val
;
3734 if(ivideo
->sisfblocked
) return;
3735 if(!ivideo
->modechanged
) return;
3737 if(ivideo
->currentvbflags
& CRT2_TV
) {
3739 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3741 int y
= ivideo
->tvy
;
3743 switch(ivideo
->chronteltype
) {
3747 SiS_SetReg(SISSR
, 0x05, 0x86);
3748 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0b, (y
& 0xff));
3749 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x08, ((y
& 0x0100) >> 8), 0xFE);
3752 /* Not supported by hardware */
3756 } else if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3760 p2_01
= ivideo
->p2_01
;
3761 p2_02
= ivideo
->p2_02
;
3765 if(!(ivideo
->currentvbflags
& (TV_HIVISION
| TV_YPBPR
))) {
3766 while((p2_01
<= 0) || (p2_02
<= 0)) {
3771 SiS_SetReg(SISPART2
, 0x01, p2_01
);
3772 SiS_SetReg(SISPART2
, 0x02, p2_02
);
3778 sisfb_post_setmode(struct sis_video_info
*ivideo
)
3780 bool crt1isoff
= false;
3782 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
3785 #ifdef CONFIG_FB_SIS_315
3789 SiS_SetReg(SISSR
, 0x05, 0x86);
3791 #ifdef CONFIG_FB_SIS_315
3792 sisfb_fixup_SR11(ivideo
);
3795 /* Now we actually HAVE changed the display mode */
3796 ivideo
->modechanged
= 1;
3798 /* We can't switch off CRT1 if bridge is in slave mode */
3799 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
3800 if(sisfb_bridgeisslave(ivideo
)) doit
= false;
3802 ivideo
->sisfb_crt1off
= 0;
3804 #ifdef CONFIG_FB_SIS_300
3805 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3806 if((ivideo
->sisfb_crt1off
) && (doit
)) {
3813 SiS_SetRegANDOR(SISCR
, 0x17, 0x7f, reg
);
3816 #ifdef CONFIG_FB_SIS_315
3817 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3818 if((ivideo
->sisfb_crt1off
) && (doit
)) {
3827 SiS_SetRegANDOR(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, ~0x40, reg
);
3828 SiS_SetRegANDOR(SISSR
, 0x1f, 0x3f, reg1
);
3833 ivideo
->currentvbflags
&= ~VB_DISPTYPE_CRT1
;
3834 ivideo
->currentvbflags
|= VB_SINGLE_MODE
;
3836 ivideo
->currentvbflags
|= VB_DISPTYPE_CRT1
;
3837 if(ivideo
->currentvbflags
& VB_DISPTYPE_CRT2
) {
3838 ivideo
->currentvbflags
|= VB_MIRROR_MODE
;
3840 ivideo
->currentvbflags
|= VB_SINGLE_MODE
;
3844 SiS_SetRegAND(SISSR
, IND_SIS_RAMDAC_CONTROL
, ~0x04);
3846 if(ivideo
->currentvbflags
& CRT2_TV
) {
3847 if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3848 ivideo
->p2_1f
= SiS_GetReg(SISPART2
, 0x1f);
3849 ivideo
->p2_20
= SiS_GetReg(SISPART2
, 0x20);
3850 ivideo
->p2_2b
= SiS_GetReg(SISPART2
, 0x2b);
3851 ivideo
->p2_42
= SiS_GetReg(SISPART2
, 0x42);
3852 ivideo
->p2_43
= SiS_GetReg(SISPART2
, 0x43);
3853 ivideo
->p2_01
= SiS_GetReg(SISPART2
, 0x01);
3854 ivideo
->p2_02
= SiS_GetReg(SISPART2
, 0x02);
3855 } else if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3856 if(ivideo
->chronteltype
== 1) {
3857 ivideo
->tvx
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0a);
3858 ivideo
->tvx
|= (((SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x08) & 0x02) >> 1) << 8);
3859 ivideo
->tvy
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0b);
3860 ivideo
->tvy
|= ((SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x08) & 0x01) << 8);
3865 if(ivideo
->tvxpos
) {
3866 sisfb_set_TVxposoffset(ivideo
, ivideo
->tvxpos
);
3868 if(ivideo
->tvypos
) {
3869 sisfb_set_TVyposoffset(ivideo
, ivideo
->tvypos
);
3872 /* Eventually sync engines */
3873 sisfb_check_engine_and_sync(ivideo
);
3875 /* (Re-)Initialize chip engines */
3877 sisfb_engine_init(ivideo
);
3879 ivideo
->engineok
= 0;
3884 sisfb_reset_mode(struct sis_video_info
*ivideo
)
3886 if(sisfb_set_mode(ivideo
, 0))
3889 sisfb_set_pitch(ivideo
);
3890 sisfb_set_base_CRT1(ivideo
, ivideo
->current_base
);
3891 sisfb_set_base_CRT2(ivideo
, ivideo
->current_base
);
3897 sisfb_handle_command(struct sis_video_info
*ivideo
, struct sisfb_cmd
*sisfb_command
)
3901 switch(sisfb_command
->sisfb_cmd
) {
3902 case SISFB_CMD_GETVBFLAGS
:
3903 if(!ivideo
->modechanged
) {
3904 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_EARLY
;
3906 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3907 sisfb_command
->sisfb_result
[1] = ivideo
->currentvbflags
;
3908 sisfb_command
->sisfb_result
[2] = ivideo
->vbflags2
;
3911 case SISFB_CMD_SWITCHCRT1
:
3912 /* arg[0]: 0 = off, 1 = on, 99 = query */
3913 if(!ivideo
->modechanged
) {
3914 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_EARLY
;
3915 } else if(sisfb_command
->sisfb_arg
[0] == 99) {
3917 sisfb_command
->sisfb_result
[1] = ivideo
->sisfb_crt1off
? 0 : 1;
3918 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3919 } else if(ivideo
->sisfblocked
) {
3920 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_LOCKED
;
3921 } else if((!(ivideo
->currentvbflags
& CRT2_ENABLE
)) &&
3922 (sisfb_command
->sisfb_arg
[0] == 0)) {
3923 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_NOCRT2
;
3925 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3926 mycrt1off
= sisfb_command
->sisfb_arg
[0] ? 0 : 1;
3927 if( ((ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
) && mycrt1off
) ||
3928 ((!(ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
)) && !mycrt1off
) ) {
3929 ivideo
->sisfb_crt1off
= mycrt1off
;
3930 if(sisfb_reset_mode(ivideo
)) {
3931 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OTHER
;
3934 sisfb_command
->sisfb_result
[1] = ivideo
->sisfb_crt1off
? 0 : 1;
3939 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_UNKNOWN
;
3940 printk(KERN_ERR
"sisfb: Unknown command 0x%x\n",
3941 sisfb_command
->sisfb_cmd
);
3946 static int __init
sisfb_setup(char *options
)
3950 sisfb_setdefaultparms();
3952 if(!options
|| !(*options
))
3955 while((this_opt
= strsep(&options
, ",")) != NULL
) {
3957 if(!(*this_opt
)) continue;
3959 if(!strnicmp(this_opt
, "off", 3)) {
3961 } else if(!strnicmp(this_opt
, "forcecrt2type:", 14)) {
3962 /* Need to check crt2 type first for fstn/dstn */
3963 sisfb_search_crt2type(this_opt
+ 14);
3964 } else if(!strnicmp(this_opt
, "tvmode:",7)) {
3965 sisfb_search_tvstd(this_opt
+ 7);
3966 } else if(!strnicmp(this_opt
, "tvstandard:",11)) {
3967 sisfb_search_tvstd(this_opt
+ 11);
3968 } else if(!strnicmp(this_opt
, "mode:", 5)) {
3969 sisfb_search_mode(this_opt
+ 5, false);
3970 } else if(!strnicmp(this_opt
, "vesa:", 5)) {
3971 sisfb_search_vesamode(simple_strtoul(this_opt
+ 5, NULL
, 0), false);
3972 } else if(!strnicmp(this_opt
, "rate:", 5)) {
3973 sisfb_parm_rate
= simple_strtoul(this_opt
+ 5, NULL
, 0);
3974 } else if(!strnicmp(this_opt
, "forcecrt1:", 10)) {
3975 sisfb_forcecrt1
= (int)simple_strtoul(this_opt
+ 10, NULL
, 0);
3976 } else if(!strnicmp(this_opt
, "mem:",4)) {
3977 sisfb_parm_mem
= simple_strtoul(this_opt
+ 4, NULL
, 0);
3978 } else if(!strnicmp(this_opt
, "pdc:", 4)) {
3979 sisfb_pdc
= simple_strtoul(this_opt
+ 4, NULL
, 0);
3980 } else if(!strnicmp(this_opt
, "pdc1:", 5)) {
3981 sisfb_pdca
= simple_strtoul(this_opt
+ 5, NULL
, 0);
3982 } else if(!strnicmp(this_opt
, "noaccel", 7)) {
3984 } else if(!strnicmp(this_opt
, "accel", 5)) {
3986 } else if(!strnicmp(this_opt
, "noypan", 6)) {
3988 } else if(!strnicmp(this_opt
, "ypan", 4)) {
3990 } else if(!strnicmp(this_opt
, "nomax", 5)) {
3992 } else if(!strnicmp(this_opt
, "max", 3)) {
3994 } else if(!strnicmp(this_opt
, "userom:", 7)) {
3995 sisfb_userom
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
3996 } else if(!strnicmp(this_opt
, "useoem:", 7)) {
3997 sisfb_useoem
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
3998 } else if(!strnicmp(this_opt
, "nocrt2rate", 10)) {
3999 sisfb_nocrt2rate
= 1;
4000 } else if(!strnicmp(this_opt
, "scalelcd:", 9)) {
4001 unsigned long temp
= 2;
4002 temp
= simple_strtoul(this_opt
+ 9, NULL
, 0);
4003 if((temp
== 0) || (temp
== 1)) {
4004 sisfb_scalelcd
= temp
^ 1;
4006 } else if(!strnicmp(this_opt
, "tvxposoffset:", 13)) {
4008 temp
= (int)simple_strtol(this_opt
+ 13, NULL
, 0);
4009 if((temp
>= -32) && (temp
<= 32)) {
4010 sisfb_tvxposoffset
= temp
;
4012 } else if(!strnicmp(this_opt
, "tvyposoffset:", 13)) {
4014 temp
= (int)simple_strtol(this_opt
+ 13, NULL
, 0);
4015 if((temp
>= -32) && (temp
<= 32)) {
4016 sisfb_tvyposoffset
= temp
;
4018 } else if(!strnicmp(this_opt
, "specialtiming:", 14)) {
4019 sisfb_search_specialtiming(this_opt
+ 14);
4020 } else if(!strnicmp(this_opt
, "lvdshl:", 7)) {
4022 temp
= simple_strtoul(this_opt
+ 7, NULL
, 0);
4023 if((temp
>= 0) && (temp
<= 3)) {
4024 sisfb_lvdshl
= temp
;
4026 } else if(this_opt
[0] >= '0' && this_opt
[0] <= '9') {
4027 sisfb_search_mode(this_opt
, true);
4028 #if !defined(__i386__) && !defined(__x86_64__)
4029 } else if(!strnicmp(this_opt
, "resetcard", 9)) {
4030 sisfb_resetcard
= 1;
4031 } else if(!strnicmp(this_opt
, "videoram:", 9)) {
4032 sisfb_videoram
= simple_strtoul(this_opt
+ 9, NULL
, 0);
4035 printk(KERN_INFO
"sisfb: Invalid option %s\n", this_opt
);
4044 static int sisfb_check_rom(void __iomem
*rom_base
,
4045 struct sis_video_info
*ivideo
)
4050 if((readb(rom_base
) != 0x55) || (readb(rom_base
+ 1) != 0xaa))
4053 romptr
= (readb(rom_base
+ 0x18) | (readb(rom_base
+ 0x19) << 8));
4054 if(romptr
> (0x10000 - 8))
4057 rom
= rom_base
+ romptr
;
4059 if((readb(rom
) != 'P') || (readb(rom
+ 1) != 'C') ||
4060 (readb(rom
+ 2) != 'I') || (readb(rom
+ 3) != 'R'))
4063 if((readb(rom
+ 4) | (readb(rom
+ 5) << 8)) != ivideo
->chip_vendor
)
4066 if((readb(rom
+ 6) | (readb(rom
+ 7) << 8)) != ivideo
->chip_id
)
4072 static unsigned char *sisfb_find_rom(struct pci_dev
*pdev
)
4074 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4075 void __iomem
*rom_base
;
4076 unsigned char *myrombase
= NULL
;
4079 /* First, try the official pci ROM functions (except
4080 * on integrated chipsets which have no ROM).
4083 if(!ivideo
->nbridge
) {
4085 if((rom_base
= pci_map_rom(pdev
, &romsize
))) {
4087 if(sisfb_check_rom(rom_base
, ivideo
)) {
4089 if((myrombase
= vmalloc(65536))) {
4090 memcpy_fromio(myrombase
, rom_base
,
4091 (romsize
> 65536) ? 65536 : romsize
);
4094 pci_unmap_rom(pdev
, rom_base
);
4098 if(myrombase
) return myrombase
;
4100 /* Otherwise do it the conventional way. */
4102 #if defined(__i386__) || defined(__x86_64__)
4106 for (temp
= 0x000c0000; temp
< 0x000f0000; temp
+= 0x00001000) {
4108 rom_base
= ioremap(temp
, 65536);
4112 if (!sisfb_check_rom(rom_base
, ivideo
)) {
4117 if ((myrombase
= vmalloc(65536)))
4118 memcpy_fromio(myrombase
, rom_base
, 65536);
4131 static void sisfb_post_map_vram(struct sis_video_info
*ivideo
,
4132 unsigned int *mapsize
, unsigned int min
)
4134 if (*mapsize
< (min
<< 20))
4137 ivideo
->video_vbase
= ioremap(ivideo
->video_base
, (*mapsize
));
4139 if(!ivideo
->video_vbase
) {
4141 "sisfb: Unable to map maximum video RAM for size detection\n");
4143 while((!(ivideo
->video_vbase
= ioremap(ivideo
->video_base
, (*mapsize
))))) {
4145 if((*mapsize
) < (min
<< 20))
4148 if(ivideo
->video_vbase
) {
4150 "sisfb: Video RAM size detection limited to %dMB\n",
4151 (int)((*mapsize
) >> 20));
4156 #ifdef CONFIG_FB_SIS_300
4157 static int sisfb_post_300_buswidth(struct sis_video_info
*ivideo
)
4159 void __iomem
*FBAddress
= ivideo
->video_vbase
;
4160 unsigned short temp
;
4164 SiS_SetRegAND(SISSR
, 0x15, 0xFB);
4165 SiS_SetRegOR(SISSR
, 0x15, 0x04);
4166 SiS_SetReg(SISSR
, 0x13, 0x00);
4167 SiS_SetReg(SISSR
, 0x14, 0xBF);
4169 for(i
= 0; i
< 2; i
++) {
4171 for(j
= 0; j
< 4; j
++) {
4172 writew(temp
, FBAddress
);
4173 if(readw(FBAddress
) == temp
)
4175 SiS_SetRegOR(SISSR
, 0x3c, 0x01);
4176 reg
= SiS_GetReg(SISSR
, 0x05);
4177 reg
= SiS_GetReg(SISSR
, 0x05);
4178 SiS_SetRegAND(SISSR
, 0x3c, 0xfe);
4179 reg
= SiS_GetReg(SISSR
, 0x05);
4180 reg
= SiS_GetReg(SISSR
, 0x05);
4185 writel(0x01234567L
, FBAddress
);
4186 writel(0x456789ABL
, (FBAddress
+ 4));
4187 writel(0x89ABCDEFL
, (FBAddress
+ 8));
4188 writel(0xCDEF0123L
, (FBAddress
+ 12));
4190 reg
= SiS_GetReg(SISSR
, 0x3b);
4192 if(readl((FBAddress
+ 12)) == 0xCDEF0123L
)
4193 return 4; /* Channel A 128bit */
4196 if(readl((FBAddress
+ 4)) == 0x456789ABL
)
4197 return 2; /* Channel B 64bit */
4199 return 1; /* 32bit */
4202 static const unsigned short SiS_DRAMType
[17][5] = {
4203 {0x0C,0x0A,0x02,0x40,0x39},
4204 {0x0D,0x0A,0x01,0x40,0x48},
4205 {0x0C,0x09,0x02,0x20,0x35},
4206 {0x0D,0x09,0x01,0x20,0x44},
4207 {0x0C,0x08,0x02,0x10,0x31},
4208 {0x0D,0x08,0x01,0x10,0x40},
4209 {0x0C,0x0A,0x01,0x20,0x34},
4210 {0x0C,0x09,0x01,0x08,0x32},
4211 {0x0B,0x08,0x02,0x08,0x21},
4212 {0x0C,0x08,0x01,0x08,0x30},
4213 {0x0A,0x08,0x02,0x04,0x11},
4214 {0x0B,0x0A,0x01,0x10,0x28},
4215 {0x09,0x08,0x02,0x02,0x01},
4216 {0x0B,0x09,0x01,0x08,0x24},
4217 {0x0B,0x08,0x01,0x04,0x20},
4218 {0x0A,0x08,0x01,0x02,0x10},
4219 {0x09,0x08,0x01,0x01,0x00}
4222 static int sisfb_post_300_rwtest(struct sis_video_info
*ivideo
, int iteration
,
4223 int buswidth
, int PseudoRankCapacity
,
4224 int PseudoAdrPinCount
, unsigned int mapsize
)
4226 void __iomem
*FBAddr
= ivideo
->video_vbase
;
4227 unsigned short sr14
;
4228 unsigned int k
, RankCapacity
, PageCapacity
, BankNumHigh
, BankNumMid
;
4229 unsigned int PhysicalAdrOtherPage
, PhysicalAdrHigh
, PhysicalAdrHalfPage
;
4231 for(k
= 0; k
< ARRAY_SIZE(SiS_DRAMType
); k
++) {
4233 RankCapacity
= buswidth
* SiS_DRAMType
[k
][3];
4235 if(RankCapacity
!= PseudoRankCapacity
)
4238 if((SiS_DRAMType
[k
][2] + SiS_DRAMType
[k
][0]) > PseudoAdrPinCount
)
4241 BankNumHigh
= RankCapacity
* 16 * iteration
- 1;
4242 if(iteration
== 3) { /* Rank No */
4243 BankNumMid
= RankCapacity
* 16 - 1;
4245 BankNumMid
= RankCapacity
* 16 * iteration
/ 2 - 1;
4248 PageCapacity
= (1 << SiS_DRAMType
[k
][1]) * buswidth
* 4;
4249 PhysicalAdrHigh
= BankNumHigh
;
4250 PhysicalAdrHalfPage
= (PageCapacity
/ 2 + PhysicalAdrHigh
) % PageCapacity
;
4251 PhysicalAdrOtherPage
= PageCapacity
* SiS_DRAMType
[k
][2] + PhysicalAdrHigh
;
4253 SiS_SetRegAND(SISSR
, 0x15, 0xFB); /* Test */
4254 SiS_SetRegOR(SISSR
, 0x15, 0x04); /* Test */
4255 sr14
= (SiS_DRAMType
[k
][3] * buswidth
) - 1;
4256 if(buswidth
== 4) sr14
|= 0x80;
4257 else if(buswidth
== 2) sr14
|= 0x40;
4258 SiS_SetReg(SISSR
, 0x13, SiS_DRAMType
[k
][4]);
4259 SiS_SetReg(SISSR
, 0x14, sr14
);
4264 if((BankNumHigh
+ PhysicalAdrHigh
>= mapsize
) ||
4265 (BankNumMid
+ PhysicalAdrHigh
>= mapsize
) ||
4266 (BankNumHigh
+ PhysicalAdrHalfPage
>= mapsize
) ||
4267 (BankNumHigh
+ PhysicalAdrOtherPage
>= mapsize
))
4271 writew(((unsigned short)PhysicalAdrHigh
),
4272 (FBAddr
+ BankNumHigh
+ PhysicalAdrHigh
));
4273 writew(((unsigned short)BankNumMid
),
4274 (FBAddr
+ BankNumMid
+ PhysicalAdrHigh
));
4275 writew(((unsigned short)PhysicalAdrHalfPage
),
4276 (FBAddr
+ BankNumHigh
+ PhysicalAdrHalfPage
));
4277 writew(((unsigned short)PhysicalAdrOtherPage
),
4278 (FBAddr
+ BankNumHigh
+ PhysicalAdrOtherPage
));
4281 if(readw(FBAddr
+ BankNumHigh
+ PhysicalAdrHigh
) == PhysicalAdrHigh
)
4288 static void sisfb_post_300_ramsize(struct pci_dev
*pdev
, unsigned int mapsize
)
4290 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4292 int PseudoRankCapacity
, PseudoAdrPinCount
;
4294 buswidth
= sisfb_post_300_buswidth(ivideo
);
4296 for(i
= 6; i
>= 0; i
--) {
4297 PseudoRankCapacity
= 1 << i
;
4298 for(j
= 4; j
>= 1; j
--) {
4299 PseudoAdrPinCount
= 15 - j
;
4300 if((PseudoRankCapacity
* j
) <= 64) {
4301 if(sisfb_post_300_rwtest(ivideo
,
4313 static void sisfb_post_sis300(struct pci_dev
*pdev
)
4315 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4316 unsigned char *bios
= ivideo
->SiS_Pr
.VirtualRomBase
;
4317 u8 reg
, v1
, v2
, v3
, v4
, v5
, v6
, v7
, v8
;
4318 u16 index
, rindex
, memtype
= 0;
4319 unsigned int mapsize
;
4321 if(!ivideo
->SiS_Pr
.UseROM
)
4324 SiS_SetReg(SISSR
, 0x05, 0x86);
4327 if(bios
[0x52] & 0x80) {
4328 memtype
= bios
[0x52];
4330 memtype
= SiS_GetReg(SISSR
, 0x3a);
4335 v3
= 0x80; v6
= 0x80;
4336 if(ivideo
->revision_id
<= 0x13) {
4337 v1
= 0x44; v2
= 0x42;
4338 v4
= 0x44; v5
= 0x42;
4340 v1
= 0x68; v2
= 0x43; /* Assume 125Mhz MCLK */
4341 v4
= 0x68; v5
= 0x43; /* Assume 125Mhz ECLK */
4343 index
= memtype
* 5;
4344 rindex
= index
+ 0x54;
4345 v1
= bios
[rindex
++];
4346 v2
= bios
[rindex
++];
4347 v3
= bios
[rindex
++];
4348 rindex
= index
+ 0x7c;
4349 v4
= bios
[rindex
++];
4350 v5
= bios
[rindex
++];
4351 v6
= bios
[rindex
++];
4354 SiS_SetReg(SISSR
, 0x28, v1
);
4355 SiS_SetReg(SISSR
, 0x29, v2
);
4356 SiS_SetReg(SISSR
, 0x2a, v3
);
4357 SiS_SetReg(SISSR
, 0x2e, v4
);
4358 SiS_SetReg(SISSR
, 0x2f, v5
);
4359 SiS_SetReg(SISSR
, 0x30, v6
);
4364 SiS_SetReg(SISSR
, 0x07, v1
); /* DAC speed */
4366 SiS_SetReg(SISSR
, 0x11, 0x0f); /* DDC, power save */
4368 v1
= 0x01; v2
= 0x43; v3
= 0x1e; v4
= 0x2a;
4369 v5
= 0x06; v6
= 0x00; v7
= 0x00; v8
= 0x00;
4373 v2
= bios
[memtype
+ 8];
4374 v3
= bios
[memtype
+ 16];
4375 v4
= bios
[memtype
+ 24];
4376 v5
= bios
[memtype
+ 32];
4377 v6
= bios
[memtype
+ 40];
4378 v7
= bios
[memtype
+ 48];
4379 v8
= bios
[memtype
+ 56];
4381 if(ivideo
->revision_id
>= 0x80)
4383 SiS_SetReg(SISSR
, 0x15, v1
); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4384 SiS_SetReg(SISSR
, 0x16, v2
);
4385 SiS_SetReg(SISSR
, 0x17, v3
);
4386 SiS_SetReg(SISSR
, 0x18, v4
);
4387 SiS_SetReg(SISSR
, 0x19, v5
);
4388 SiS_SetReg(SISSR
, 0x1a, v6
);
4389 SiS_SetReg(SISSR
, 0x1b, v7
);
4390 SiS_SetReg(SISSR
, 0x1c, v8
); /* ---- */
4391 SiS_SetRegAND(SISSR
, 0x15, 0xfb);
4392 SiS_SetRegOR(SISSR
, 0x15, 0x04);
4394 if(bios
[0x53] & 0x02) {
4395 SiS_SetRegOR(SISSR
, 0x19, 0x20);
4398 v1
= 0x04; /* DAC pedestal (BIOS 0xe5) */
4399 if(ivideo
->revision_id
>= 0x80)
4401 SiS_SetReg(SISSR
, 0x1f, v1
);
4402 SiS_SetReg(SISSR
, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
4403 v1
= 0xf6; v2
= 0x0d; v3
= 0x00;
4409 SiS_SetReg(SISSR
, 0x23, v1
);
4410 SiS_SetReg(SISSR
, 0x24, v2
);
4411 SiS_SetReg(SISSR
, 0x25, v3
);
4412 SiS_SetReg(SISSR
, 0x21, 0x84);
4413 SiS_SetReg(SISSR
, 0x22, 0x00);
4414 SiS_SetReg(SISCR
, 0x37, 0x00);
4415 SiS_SetRegOR(SISPART1
, 0x24, 0x01); /* unlock crt2 */
4416 SiS_SetReg(SISPART1
, 0x00, 0x00);
4417 v1
= 0x40; v2
= 0x11;
4422 SiS_SetReg(SISPART1
, 0x02, v1
);
4424 if(ivideo
->revision_id
>= 0x80)
4427 reg
= SiS_GetReg(SISPART4
, 0x00);
4428 if((reg
== 1) || (reg
== 2)) {
4429 SiS_SetReg(SISCR
, 0x37, 0x02);
4430 SiS_SetReg(SISPART2
, 0x00, 0x1c);
4431 v4
= 0x00; v5
= 0x00; v6
= 0x10;
4432 if(ivideo
->SiS_Pr
.UseROM
) {
4437 SiS_SetReg(SISPART4
, 0x0d, v4
);
4438 SiS_SetReg(SISPART4
, 0x0e, v5
);
4439 SiS_SetReg(SISPART4
, 0x10, v6
);
4440 SiS_SetReg(SISPART4
, 0x0f, 0x3f);
4441 reg
= SiS_GetReg(SISPART4
, 0x01);
4443 reg
= SiS_GetReg(SISPART4
, 0x23);
4446 SiS_SetReg(SISPART4
, 0x23, reg
);
4451 SiS_SetReg(SISSR
, 0x32, v2
);
4453 SiS_SetRegAND(SISPART1
, 0x24, 0xfe); /* Lock CRT2 */
4455 reg
= SiS_GetReg(SISSR
, 0x16);
4457 SiS_SetReg(SISCR
, 0x35, reg
);
4458 SiS_SetReg(SISCR
, 0x83, 0x00);
4459 #if !defined(__i386__) && !defined(__x86_64__)
4460 if(sisfb_videoram
) {
4461 SiS_SetReg(SISSR
, 0x13, 0x28); /* ? */
4462 reg
= ((sisfb_videoram
>> 10) - 1) | 0x40;
4463 SiS_SetReg(SISSR
, 0x14, reg
);
4466 /* Need to map max FB size for finding out about RAM size */
4467 mapsize
= ivideo
->video_size
;
4468 sisfb_post_map_vram(ivideo
, &mapsize
, 4);
4470 if(ivideo
->video_vbase
) {
4471 sisfb_post_300_ramsize(pdev
, mapsize
);
4472 iounmap(ivideo
->video_vbase
);
4475 "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4476 SiS_SetReg(SISSR
, 0x13, 0x28); /* ? */
4477 SiS_SetReg(SISSR
, 0x14, 0x47); /* 8MB, 64bit default */
4479 #if !defined(__i386__) && !defined(__x86_64__)
4486 reg
= SiS_GetReg(SISSR
, 0x3a);
4487 if((reg
& 0x30) == 0x30) {
4488 v1
= 0x04; /* PCI */
4491 v1
= 0x14; /* AGP */
4495 SiS_SetReg(SISSR
, 0x21, v1
);
4496 SiS_SetReg(SISSR
, 0x22, v2
);
4499 sisfb_sense_crt1(ivideo
);
4501 /* Set default mode, don't clear screen */
4502 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
4503 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
4504 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
4505 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
4506 ivideo
->SiS_Pr
.VideoMemorySize
= 8 << 20;
4507 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
4509 SiS_SetReg(SISSR
, 0x05, 0x86);
4512 SiS_SetRegOR(SISSR
, 0x01, 0x20);
4514 /* Save mode number in CR34 */
4515 SiS_SetReg(SISCR
, 0x34, 0x2e);
4517 /* Let everyone know what the current mode is */
4518 ivideo
->modeprechange
= 0x2e;
4522 #ifdef CONFIG_FB_SIS_315
4524 static void sisfb_post_sis315330(struct pci_dev
*pdev
)
4530 static inline int sisfb_xgi_is21(struct sis_video_info
*ivideo
)
4532 return ivideo
->chip_real_id
== XGI_21
;
4535 static void sisfb_post_xgi_delay(struct sis_video_info
*ivideo
, int delay
)
4540 for(i
= 0; i
<= (delay
* 10 * 36); i
++) {
4541 reg
= SiS_GetReg(SISSR
, 0x05);
4546 static int sisfb_find_host_bridge(struct sis_video_info
*ivideo
,
4547 struct pci_dev
*mypdev
,
4548 unsigned short pcivendor
)
4550 struct pci_dev
*pdev
= NULL
;
4551 unsigned short temp
;
4554 while((pdev
= pci_get_class(PCI_CLASS_BRIDGE_HOST
, pdev
))) {
4555 temp
= pdev
->vendor
;
4556 if(temp
== pcivendor
) {
4566 static int sisfb_post_xgi_rwtest(struct sis_video_info
*ivideo
, int starta
,
4567 unsigned int enda
, unsigned int mapsize
)
4572 writel(0, ivideo
->video_vbase
);
4574 for(i
= starta
; i
<= enda
; i
++) {
4577 writel(pos
, ivideo
->video_vbase
+ pos
);
4580 sisfb_post_xgi_delay(ivideo
, 150);
4582 if(readl(ivideo
->video_vbase
) != 0)
4585 for(i
= starta
; i
<= enda
; i
++) {
4588 if(readl(ivideo
->video_vbase
+ pos
) != pos
)
4597 static int sisfb_post_xgi_ramsize(struct sis_video_info
*ivideo
)
4599 unsigned int buswidth
, ranksize
, channelab
, mapsize
;
4600 int i
, j
, k
, l
, status
;
4602 static const u8 dramsr13
[12 * 5] = {
4603 0x02, 0x0e, 0x0b, 0x80, 0x5d,
4604 0x02, 0x0e, 0x0a, 0x40, 0x59,
4605 0x02, 0x0d, 0x0b, 0x40, 0x4d,
4606 0x02, 0x0e, 0x09, 0x20, 0x55,
4607 0x02, 0x0d, 0x0a, 0x20, 0x49,
4608 0x02, 0x0c, 0x0b, 0x20, 0x3d,
4609 0x02, 0x0e, 0x08, 0x10, 0x51,
4610 0x02, 0x0d, 0x09, 0x10, 0x45,
4611 0x02, 0x0c, 0x0a, 0x10, 0x39,
4612 0x02, 0x0d, 0x08, 0x08, 0x41,
4613 0x02, 0x0c, 0x09, 0x08, 0x35,
4614 0x02, 0x0c, 0x08, 0x04, 0x31
4616 static const u8 dramsr13_4
[4 * 5] = {
4617 0x02, 0x0d, 0x09, 0x40, 0x45,
4618 0x02, 0x0c, 0x09, 0x20, 0x35,
4619 0x02, 0x0c, 0x08, 0x10, 0x31,
4620 0x02, 0x0b, 0x08, 0x08, 0x21
4623 /* Enable linear mode, disable 0xa0000 address decoding */
4624 /* We disable a0000 address decoding, because
4625 * - if running on x86, if the card is disabled, it means
4626 * that another card is in the system. We don't want
4627 * to interphere with that primary card's textmode.
4628 * - if running on non-x86, there usually is no VGA window
4631 SiS_SetRegOR(SISSR
, 0x20, (0x80 | 0x04));
4633 /* Need to map max FB size for finding out about RAM size */
4634 mapsize
= ivideo
->video_size
;
4635 sisfb_post_map_vram(ivideo
, &mapsize
, 32);
4637 if(!ivideo
->video_vbase
) {
4638 printk(KERN_ERR
"sisfb: Unable to detect RAM size. Setting default.\n");
4639 SiS_SetReg(SISSR
, 0x13, 0x35);
4640 SiS_SetReg(SISSR
, 0x14, 0x41);
4645 /* Non-interleaving */
4646 SiS_SetReg(SISSR
, 0x15, 0x00);
4648 SiS_SetReg(SISSR
, 0x1c, 0x00);
4650 if(ivideo
->chip
== XGI_20
) {
4653 reg
= SiS_GetReg(SISCR
, 0x97);
4654 if(!(reg
& 0x01)) { /* Single 32/16 */
4656 SiS_SetReg(SISSR
, 0x13, 0xb1);
4657 SiS_SetReg(SISSR
, 0x14, 0x52);
4658 sisfb_post_xgi_delay(ivideo
, 1);
4660 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4663 SiS_SetReg(SISSR
, 0x13, 0x31);
4664 SiS_SetReg(SISSR
, 0x14, 0x42);
4665 sisfb_post_xgi_delay(ivideo
, 1);
4666 if(sisfb_post_xgi_rwtest(ivideo
, 23, 23, mapsize
))
4670 SiS_SetReg(SISSR
, 0x13, 0xb1);
4671 SiS_SetReg(SISSR
, 0x14, 0x41);
4672 sisfb_post_xgi_delay(ivideo
, 1);
4674 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4677 SiS_SetReg(SISSR
, 0x13, 0x31);
4678 } else { /* Dual 16/8 */
4680 SiS_SetReg(SISSR
, 0x13, 0xb1);
4681 SiS_SetReg(SISSR
, 0x14, 0x41);
4682 sisfb_post_xgi_delay(ivideo
, 1);
4684 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4687 SiS_SetReg(SISSR
, 0x13, 0x31);
4688 SiS_SetReg(SISSR
, 0x14, 0x31);
4689 sisfb_post_xgi_delay(ivideo
, 1);
4690 if(sisfb_post_xgi_rwtest(ivideo
, 22, 22, mapsize
))
4694 SiS_SetReg(SISSR
, 0x13, 0xb1);
4695 SiS_SetReg(SISSR
, 0x14, 0x30);
4696 sisfb_post_xgi_delay(ivideo
, 1);
4698 if(sisfb_post_xgi_rwtest(ivideo
, 21, 22, mapsize
))
4701 SiS_SetReg(SISSR
, 0x13, 0x31);
4704 } else { /* XGI_40 */
4706 reg
= SiS_GetReg(SISCR
, 0x97);
4708 reg
= SiS_GetReg(SISSR
, 0x39);
4712 if(reg
& 0x01) { /* DDRII */
4714 if(ivideo
->revision_id
== 2) {
4716 SiS_SetReg(SISSR
, 0x13, 0xa1);
4717 SiS_SetReg(SISSR
, 0x14, 0x44);
4719 sisfb_post_xgi_delay(ivideo
, 1);
4720 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4723 SiS_SetReg(SISSR
, 0x13, 0x21);
4724 SiS_SetReg(SISSR
, 0x14, 0x34);
4725 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4729 SiS_SetReg(SISSR
, 0x13, 0xa1);
4730 SiS_SetReg(SISSR
, 0x14, 0x40);
4732 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4735 SiS_SetReg(SISSR
, 0x13, 0x21);
4736 SiS_SetReg(SISSR
, 0x14, 0x30);
4739 SiS_SetReg(SISSR
, 0x13, 0xa1);
4740 SiS_SetReg(SISSR
, 0x14, 0x4c);
4742 sisfb_post_xgi_delay(ivideo
, 1);
4743 if(sisfb_post_xgi_rwtest(ivideo
, 23, 25, mapsize
))
4747 SiS_SetReg(SISSR
, 0x14, 0x48);
4748 sisfb_post_xgi_delay(ivideo
, 1);
4750 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4753 SiS_SetReg(SISSR
, 0x13, 0x21);
4754 SiS_SetReg(SISSR
, 0x14, 0x3c);
4757 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
)) {
4761 SiS_SetReg(SISSR
, 0x14, 0x38);
4765 sisfb_post_xgi_delay(ivideo
, 1);
4770 if(ivideo
->revision_id
== 2) {
4772 SiS_SetReg(SISSR
, 0x13, 0xa1);
4773 SiS_SetReg(SISSR
, 0x14, 0x52);
4774 sisfb_post_xgi_delay(ivideo
, 1);
4776 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4779 SiS_SetReg(SISSR
, 0x13, 0x21);
4780 SiS_SetReg(SISSR
, 0x14, 0x42);
4783 SiS_SetReg(SISSR
, 0x13, 0xa1);
4784 SiS_SetReg(SISSR
, 0x14, 0x5a);
4785 sisfb_post_xgi_delay(ivideo
, 1);
4787 if(sisfb_post_xgi_rwtest(ivideo
, 24, 25, mapsize
))
4790 SiS_SetReg(SISSR
, 0x13, 0x21);
4791 SiS_SetReg(SISSR
, 0x14, 0x4a);
4793 sisfb_post_xgi_delay(ivideo
, 1);
4799 SiS_SetRegANDOR(SISSR
, 0x14, 0xf0, sr14
);
4800 sisfb_post_xgi_delay(ivideo
, 1);
4802 j
= (ivideo
->chip
== XGI_20
) ? 5 : 9;
4803 k
= (ivideo
->chip
== XGI_20
) ? 12 : 4;
4806 for(i
= 0; i
< k
; i
++) {
4808 reg
= (ivideo
->chip
== XGI_20
) ?
4809 dramsr13
[(i
* 5) + 4] : dramsr13_4
[(i
* 5) + 4];
4810 SiS_SetRegANDOR(SISSR
, 0x13, 0x80, reg
);
4811 sisfb_post_xgi_delay(ivideo
, 50);
4813 ranksize
= (ivideo
->chip
== XGI_20
) ?
4814 dramsr13
[(i
* 5) + 3] : dramsr13_4
[(i
* 5) + 3];
4816 reg
= SiS_GetReg(SISSR
, 0x13);
4817 if(reg
& 0x80) ranksize
<<= 1;
4819 if(ivideo
->chip
== XGI_20
) {
4820 if(buswidth
== 16) ranksize
<<= 1;
4821 else if(buswidth
== 32) ranksize
<<= 2;
4823 if(buswidth
== 64) ranksize
<<= 1;
4829 if((ranksize
* l
) <= 256) {
4830 while((ranksize
>>= 1)) reg
+= 0x10;
4835 SiS_SetRegANDOR(SISSR
, 0x14, 0x0f, (reg
& 0xf0));
4836 sisfb_post_xgi_delay(ivideo
, 1);
4838 if (sisfb_post_xgi_rwtest(ivideo
, j
, ((reg
>> 4) + channelab
- 2 + 20), mapsize
)) {
4844 iounmap(ivideo
->video_vbase
);
4849 static void sisfb_post_xgi_setclocks(struct sis_video_info
*ivideo
, u8 regb
)
4853 static const u8 cs90
[8 * 3] = {
4863 static const u8 csb8
[8 * 3] = {
4877 v1
= cs90
[index
]; v2
= cs90
[index
+ 1]; v3
= cs90
[index
+ 2];
4878 if(ivideo
->haveXGIROM
) {
4879 v1
= ivideo
->bios_abase
[0x90 + index
];
4880 v2
= ivideo
->bios_abase
[0x90 + index
+ 1];
4881 v3
= ivideo
->bios_abase
[0x90 + index
+ 2];
4883 SiS_SetReg(SISSR
, 0x28, v1
);
4884 SiS_SetReg(SISSR
, 0x29, v2
);
4885 SiS_SetReg(SISSR
, 0x2a, v3
);
4886 sisfb_post_xgi_delay(ivideo
, 0x43);
4887 sisfb_post_xgi_delay(ivideo
, 0x43);
4888 sisfb_post_xgi_delay(ivideo
, 0x43);
4890 v1
= csb8
[index
]; v2
= csb8
[index
+ 1]; v3
= csb8
[index
+ 2];
4891 if(ivideo
->haveXGIROM
) {
4892 v1
= ivideo
->bios_abase
[0xb8 + index
];
4893 v2
= ivideo
->bios_abase
[0xb8 + index
+ 1];
4894 v3
= ivideo
->bios_abase
[0xb8 + index
+ 2];
4896 SiS_SetReg(SISSR
, 0x2e, v1
);
4897 SiS_SetReg(SISSR
, 0x2f, v2
);
4898 SiS_SetReg(SISSR
, 0x30, v3
);
4899 sisfb_post_xgi_delay(ivideo
, 0x43);
4900 sisfb_post_xgi_delay(ivideo
, 0x43);
4901 sisfb_post_xgi_delay(ivideo
, 0x43);
4904 static void sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info
*ivideo
,
4907 unsigned char *bios
= ivideo
->bios_abase
;
4910 SiS_SetReg(SISSR
, 0x28, 0x64);
4911 SiS_SetReg(SISSR
, 0x29, 0x63);
4912 sisfb_post_xgi_delay(ivideo
, 15);
4913 SiS_SetReg(SISSR
, 0x18, 0x00);
4914 SiS_SetReg(SISSR
, 0x19, 0x20);
4915 SiS_SetReg(SISSR
, 0x16, 0x00);
4916 SiS_SetReg(SISSR
, 0x16, 0x80);
4917 SiS_SetReg(SISSR
, 0x18, 0xc5);
4918 SiS_SetReg(SISSR
, 0x19, 0x23);
4919 SiS_SetReg(SISSR
, 0x16, 0x00);
4920 SiS_SetReg(SISSR
, 0x16, 0x80);
4921 sisfb_post_xgi_delay(ivideo
, 1);
4922 SiS_SetReg(SISCR
, 0x97, 0x11);
4923 sisfb_post_xgi_setclocks(ivideo
, regb
);
4924 sisfb_post_xgi_delay(ivideo
, 0x46);
4925 SiS_SetReg(SISSR
, 0x18, 0xc5);
4926 SiS_SetReg(SISSR
, 0x19, 0x23);
4927 SiS_SetReg(SISSR
, 0x16, 0x00);
4928 SiS_SetReg(SISSR
, 0x16, 0x80);
4929 sisfb_post_xgi_delay(ivideo
, 1);
4930 SiS_SetReg(SISSR
, 0x1b, 0x04);
4931 sisfb_post_xgi_delay(ivideo
, 1);
4932 SiS_SetReg(SISSR
, 0x1b, 0x00);
4933 sisfb_post_xgi_delay(ivideo
, 1);
4935 if (ivideo
->haveXGIROM
) {
4938 SiS_SetReg(SISSR
, 0x18, v1
);
4939 SiS_SetReg(SISSR
, 0x19, 0x06);
4940 SiS_SetReg(SISSR
, 0x16, 0x04);
4941 SiS_SetReg(SISSR
, 0x16, 0x84);
4942 sisfb_post_xgi_delay(ivideo
, 1);
4945 static void sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info
*ivideo
)
4947 sisfb_post_xgi_setclocks(ivideo
, 1);
4949 SiS_SetReg(SISCR
, 0x97, 0x11);
4950 sisfb_post_xgi_delay(ivideo
, 0x46);
4952 SiS_SetReg(SISSR
, 0x18, 0x00); /* EMRS2 */
4953 SiS_SetReg(SISSR
, 0x19, 0x80);
4954 SiS_SetReg(SISSR
, 0x16, 0x05);
4955 SiS_SetReg(SISSR
, 0x16, 0x85);
4957 SiS_SetReg(SISSR
, 0x18, 0x00); /* EMRS3 */
4958 SiS_SetReg(SISSR
, 0x19, 0xc0);
4959 SiS_SetReg(SISSR
, 0x16, 0x05);
4960 SiS_SetReg(SISSR
, 0x16, 0x85);
4962 SiS_SetReg(SISSR
, 0x18, 0x00); /* EMRS1 */
4963 SiS_SetReg(SISSR
, 0x19, 0x40);
4964 SiS_SetReg(SISSR
, 0x16, 0x05);
4965 SiS_SetReg(SISSR
, 0x16, 0x85);
4967 SiS_SetReg(SISSR
, 0x18, 0x42); /* MRS1 */
4968 SiS_SetReg(SISSR
, 0x19, 0x02);
4969 SiS_SetReg(SISSR
, 0x16, 0x05);
4970 SiS_SetReg(SISSR
, 0x16, 0x85);
4971 sisfb_post_xgi_delay(ivideo
, 1);
4973 SiS_SetReg(SISSR
, 0x1b, 0x04);
4974 sisfb_post_xgi_delay(ivideo
, 1);
4976 SiS_SetReg(SISSR
, 0x1b, 0x00);
4977 sisfb_post_xgi_delay(ivideo
, 1);
4979 SiS_SetReg(SISSR
, 0x18, 0x42); /* MRS1 */
4980 SiS_SetReg(SISSR
, 0x19, 0x00);
4981 SiS_SetReg(SISSR
, 0x16, 0x05);
4982 SiS_SetReg(SISSR
, 0x16, 0x85);
4983 sisfb_post_xgi_delay(ivideo
, 1);
4986 static void sisfb_post_xgi_ddr2(struct sis_video_info
*ivideo
, u8 regb
)
4988 unsigned char *bios
= ivideo
->bios_abase
;
4989 static const u8 cs158
[8] = {
4990 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
4992 static const u8 cs160
[8] = {
4993 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
4995 static const u8 cs168
[8] = {
4996 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5003 SiS_SetReg(SISCR
, 0xb0, 0x80); /* DDR2 dual frequency mode */
5004 SiS_SetReg(SISCR
, 0x82, 0x77);
5005 SiS_SetReg(SISCR
, 0x86, 0x00);
5006 reg
= SiS_GetReg(SISCR
, 0x86);
5007 SiS_SetReg(SISCR
, 0x86, 0x88);
5008 reg
= SiS_GetReg(SISCR
, 0x86);
5009 v1
= cs168
[regb
]; v2
= cs160
[regb
]; v3
= cs158
[regb
];
5010 if (ivideo
->haveXGIROM
) {
5011 v1
= bios
[regb
+ 0x168];
5012 v2
= bios
[regb
+ 0x160];
5013 v3
= bios
[regb
+ 0x158];
5015 SiS_SetReg(SISCR
, 0x86, v1
);
5016 SiS_SetReg(SISCR
, 0x82, 0x77);
5017 SiS_SetReg(SISCR
, 0x85, 0x00);
5018 reg
= SiS_GetReg(SISCR
, 0x85);
5019 SiS_SetReg(SISCR
, 0x85, 0x88);
5020 reg
= SiS_GetReg(SISCR
, 0x85);
5021 SiS_SetReg(SISCR
, 0x85, v2
);
5022 SiS_SetReg(SISCR
, 0x82, v3
);
5023 SiS_SetReg(SISCR
, 0x98, 0x01);
5024 SiS_SetReg(SISCR
, 0x9a, 0x02);
5025 if (sisfb_xgi_is21(ivideo
))
5026 sisfb_post_xgi_ddr2_mrs_xg21(ivideo
);
5028 sisfb_post_xgi_ddr2_mrs_default(ivideo
, regb
);
5031 static u8
sisfb_post_xgi_ramtype(struct sis_video_info
*ivideo
)
5033 unsigned char *bios
= ivideo
->bios_abase
;
5038 ramtype
= 0x00; v1
= 0x10;
5039 if (ivideo
->haveXGIROM
) {
5040 ramtype
= bios
[0x62];
5043 if (!(ramtype
& 0x80)) {
5044 if (sisfb_xgi_is21(ivideo
)) {
5045 SiS_SetRegAND(SISCR
, 0xb4, 0xfd); /* GPIO control */
5046 SiS_SetRegOR(SISCR
, 0x4a, 0x80); /* GPIOH EN */
5047 reg
= SiS_GetReg(SISCR
, 0x48);
5048 SiS_SetRegOR(SISCR
, 0xb4, 0x02);
5049 ramtype
= reg
& 0x01; /* GPIOH */
5050 } else if (ivideo
->chip
== XGI_20
) {
5051 SiS_SetReg(SISCR
, 0x97, v1
);
5052 reg
= SiS_GetReg(SISCR
, 0x97);
5054 ramtype
= (reg
& 0x01) << 1;
5057 reg
= SiS_GetReg(SISSR
, 0x39);
5058 ramtype
= reg
& 0x02;
5060 reg
= SiS_GetReg(SISSR
, 0x3a);
5061 ramtype
= (reg
>> 1) & 0x01;
5070 static int sisfb_post_xgi(struct pci_dev
*pdev
)
5072 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
5073 unsigned char *bios
= ivideo
->bios_abase
;
5074 struct pci_dev
*mypdev
= NULL
;
5075 const u8
*ptr
, *ptr2
;
5076 u8 v1
, v2
, v3
, v4
, v5
, reg
, ramtype
;
5077 u32 rega
, regb
, regd
;
5079 static const u8 cs78
[3] = { 0xf6, 0x0d, 0x00 };
5080 static const u8 cs76
[2] = { 0xa3, 0xfb };
5081 static const u8 cs7b
[3] = { 0xc0, 0x11, 0x00 };
5082 static const u8 cs158
[8] = {
5083 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5085 static const u8 cs160
[8] = {
5086 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5088 static const u8 cs168
[8] = {
5089 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5091 static const u8 cs128
[3 * 8] = {
5092 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
5093 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5094 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
5096 static const u8 cs148
[2 * 8] = {
5097 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
5098 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5100 static const u8 cs31a
[8 * 4] = {
5101 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
5102 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
5103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5106 static const u8 cs33a
[8 * 4] = {
5107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5108 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5112 static const u8 cs45a
[8 * 2] = {
5113 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
5114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5116 static const u8 cs170
[7 * 8] = {
5117 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5118 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5119 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
5120 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5121 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5122 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5123 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5125 static const u8 cs1a8
[3 * 8] = {
5126 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5127 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5130 static const u8 cs100
[2 * 8] = {
5131 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5132 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5136 reg
= SiS_GetRegByte(SISVGAENABLE
) | 0x01;
5137 SiS_SetRegByte(SISVGAENABLE
, reg
);
5140 reg
= SiS_GetRegByte(SISMISCR
) | 0x01;
5141 SiS_SetRegByte(SISMISCW
, reg
);
5144 SiS_SetReg(SISSR
, 0x05, 0x86);
5145 reg
= SiS_GetReg(SISSR
, 0x05);
5149 /* Clear some regs */
5150 for(i
= 0; i
< 0x22; i
++) {
5151 if(0x06 + i
== 0x20) continue;
5152 SiS_SetReg(SISSR
, 0x06 + i
, 0x00);
5154 for(i
= 0; i
< 0x0b; i
++) {
5155 SiS_SetReg(SISSR
, 0x31 + i
, 0x00);
5157 for(i
= 0; i
< 0x10; i
++) {
5158 SiS_SetReg(SISCR
, 0x30 + i
, 0x00);
5162 if(ivideo
->haveXGIROM
) {
5163 ptr
= (const u8
*)&bios
[0x78];
5165 for(i
= 0; i
< 3; i
++) {
5166 SiS_SetReg(SISSR
, 0x23 + i
, ptr
[i
]);
5170 if(ivideo
->haveXGIROM
) {
5171 ptr
= (const u8
*)&bios
[0x76];
5173 for(i
= 0; i
< 2; i
++) {
5174 SiS_SetReg(SISSR
, 0x21 + i
, ptr
[i
]);
5177 v1
= 0x18; v2
= 0x00;
5178 if(ivideo
->haveXGIROM
) {
5182 SiS_SetReg(SISSR
, 0x07, v1
);
5183 SiS_SetReg(SISSR
, 0x11, 0x0f);
5184 SiS_SetReg(SISSR
, 0x1f, v2
);
5185 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5186 SiS_SetReg(SISSR
, 0x20, 0x80 | 0x20 | 0x04);
5187 SiS_SetReg(SISSR
, 0x27, 0x74);
5190 if(ivideo
->haveXGIROM
) {
5191 ptr
= (const u8
*)&bios
[0x7b];
5193 for(i
= 0; i
< 3; i
++) {
5194 SiS_SetReg(SISSR
, 0x31 + i
, ptr
[i
]);
5197 if(ivideo
->chip
== XGI_40
) {
5198 if(ivideo
->revision_id
== 2) {
5199 SiS_SetRegANDOR(SISSR
, 0x3b, 0x3f, 0xc0);
5201 SiS_SetReg(SISCR
, 0x7d, 0xfe);
5202 SiS_SetReg(SISCR
, 0x7e, 0x0f);
5204 if(ivideo
->revision_id
== 0) { /* 40 *and* 20? */
5205 SiS_SetRegAND(SISCR
, 0x58, 0xd7);
5206 reg
= SiS_GetReg(SISCR
, 0xcb);
5208 SiS_SetRegANDOR(SISCR
, 0x58, 0xd7, (reg
& 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5212 reg
= (ivideo
->chip
== XGI_40
) ? 0x20 : 0x00;
5213 SiS_SetRegANDOR(SISCR
, 0x38, 0x1f, reg
);
5215 if(ivideo
->chip
== XGI_20
) {
5216 SiS_SetReg(SISSR
, 0x36, 0x70);
5218 SiS_SetReg(SISVID
, 0x00, 0x86);
5219 SiS_SetReg(SISVID
, 0x32, 0x00);
5220 SiS_SetReg(SISVID
, 0x30, 0x00);
5221 SiS_SetReg(SISVID
, 0x32, 0x01);
5222 SiS_SetReg(SISVID
, 0x30, 0x00);
5223 SiS_SetRegAND(SISVID
, 0x2f, 0xdf);
5224 SiS_SetRegAND(SISCAP
, 0x00, 0x3f);
5226 SiS_SetReg(SISPART1
, 0x2f, 0x01);
5227 SiS_SetReg(SISPART1
, 0x00, 0x00);
5228 SiS_SetReg(SISPART1
, 0x02, bios
[0x7e]);
5229 SiS_SetReg(SISPART1
, 0x2e, 0x08);
5230 SiS_SetRegAND(SISPART1
, 0x35, 0x7f);
5231 SiS_SetRegAND(SISPART1
, 0x50, 0xfe);
5233 reg
= SiS_GetReg(SISPART4
, 0x00);
5234 if(reg
== 1 || reg
== 2) {
5235 SiS_SetReg(SISPART2
, 0x00, 0x1c);
5236 SiS_SetReg(SISPART4
, 0x0d, bios
[0x7f]);
5237 SiS_SetReg(SISPART4
, 0x0e, bios
[0x80]);
5238 SiS_SetReg(SISPART4
, 0x10, bios
[0x81]);
5239 SiS_SetRegAND(SISPART4
, 0x0f, 0x3f);
5241 reg
= SiS_GetReg(SISPART4
, 0x01);
5242 if((reg
& 0xf0) >= 0xb0) {
5243 reg
= SiS_GetReg(SISPART4
, 0x23);
5244 if(reg
& 0x20) reg
|= 0x40;
5245 SiS_SetReg(SISPART4
, 0x23, reg
);
5246 reg
= (reg
& 0x20) ? 0x02 : 0x00;
5247 SiS_SetRegANDOR(SISPART1
, 0x1e, 0xfd, reg
);
5253 reg
= SiS_GetReg(SISSR
, 0x3b);
5255 reg
= SiS_GetReg(SISSR
, 0x3a);
5256 v2
= (reg
& 0x30) >> 3;
5257 if(!(v2
& 0x04)) v2
^= 0x02;
5258 reg
= SiS_GetReg(SISSR
, 0x39);
5259 if(reg
& 0x80) v2
|= 0x80;
5262 if((mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0730, NULL
))) {
5263 pci_dev_put(mypdev
);
5264 if(((v2
& 0x06) == 2) || ((v2
& 0x06) == 4))
5269 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0735, NULL
);
5271 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0645, NULL
);
5273 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0650, NULL
);
5275 pci_read_config_dword(mypdev
, 0x94, ®d
);
5277 pci_write_config_dword(mypdev
, 0x94, regd
);
5279 pci_dev_put(mypdev
);
5280 } else if(sisfb_find_host_bridge(ivideo
, pdev
, PCI_VENDOR_ID_SI
)) {
5282 } else if(sisfb_find_host_bridge(ivideo
, pdev
, 0x1106) ||
5283 sisfb_find_host_bridge(ivideo
, pdev
, 0x1022) ||
5284 sisfb_find_host_bridge(ivideo
, pdev
, 0x700e) ||
5285 sisfb_find_host_bridge(ivideo
, pdev
, 0x10de)) {
5286 if((v2
& 0x06) == 4)
5291 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf0, v2
);
5293 SiS_SetReg(SISSR
, 0x22, v1
);
5295 if(ivideo
->revision_id
== 2) {
5296 v1
= SiS_GetReg(SISSR
, 0x3b);
5297 v2
= SiS_GetReg(SISSR
, 0x3a);
5298 regd
= bios
[0x90 + 3] | (bios
[0x90 + 4] << 8);
5299 if( (!(v1
& 0x02)) && (v2
& 0x30) && (regd
< 0xcf) )
5300 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf1, 0x01);
5302 if((mypdev
= pci_get_device(0x10de, 0x01e0, NULL
))) {
5303 /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5307 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf1, 0x01);
5308 pci_dev_put(mypdev
);
5313 reg
= SiS_GetReg(SISSR
, 0x3b);
5314 v2
= SiS_GetReg(SISCR
, 0x5f);
5315 if((!(reg
& 0x02)) && (v2
& 0x0e))
5317 SiS_SetReg(SISSR
, 0x27, v1
);
5319 if(bios
[0x64] & 0x01) {
5320 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf0, bios
[0x64]);
5324 pci_read_config_dword(pdev
, 0x50, ®d
);
5325 regd
= (regd
>> 20) & 0x0f;
5328 SiS_SetRegOR(SISCR
, 0x5f, 0x08);
5330 SiS_SetReg(SISCR
, 0x48, v1
);
5332 SiS_SetRegANDOR(SISCR
, 0x47, 0x04, bios
[0x4f6] & 0xfb);
5333 SiS_SetRegANDOR(SISCR
, 0x49, 0xf0, bios
[0x4f8] & 0x0f);
5334 SiS_SetRegANDOR(SISCR
, 0x4a, 0x60, bios
[0x4f9] & 0x9f);
5335 SiS_SetRegANDOR(SISCR
, 0x4b, 0x08, bios
[0x4fa] & 0xf7);
5336 SiS_SetRegANDOR(SISCR
, 0x4c, 0x80, bios
[0x4fb] & 0x7f);
5337 SiS_SetReg(SISCR
, 0x70, bios
[0x4fc]);
5338 SiS_SetRegANDOR(SISCR
, 0x71, 0xf0, bios
[0x4fd] & 0x0f);
5339 SiS_SetReg(SISCR
, 0x74, 0xd0);
5340 SiS_SetRegANDOR(SISCR
, 0x74, 0xcf, bios
[0x4fe] & 0x30);
5341 SiS_SetRegANDOR(SISCR
, 0x75, 0xe0, bios
[0x4ff] & 0x1f);
5342 SiS_SetRegANDOR(SISCR
, 0x76, 0xe0, bios
[0x500] & 0x1f);
5344 if((mypdev
= pci_get_device(0x8086, 0x2530, NULL
))) {
5346 pci_dev_put(mypdev
);
5348 SiS_SetReg(SISCR
, 0x77, v1
);
5353 * 0 == DDR1, 1 == DDR2, 2..7 == reserved?
5355 * The code seems to written so that regb should equal ramtype,
5356 * however, so far it has been hardcoded to 0. Enable other values only
5357 * on XGI Z9, as it passes the POST, and add a warning for others.
5359 ramtype
= sisfb_post_xgi_ramtype(ivideo
);
5360 if (!sisfb_xgi_is21(ivideo
) && ramtype
) {
5361 dev_warn(&pdev
->dev
,
5362 "RAM type something else than expected: %d\n",
5370 if(ivideo
->haveXGIROM
) {
5371 v1
= bios
[0x140 + regb
];
5373 SiS_SetReg(SISCR
, 0x6d, v1
);
5376 if(ivideo
->haveXGIROM
) {
5377 ptr
= (const u8
*)&bios
[0x128];
5379 for(i
= 0, j
= 0; i
< 3; i
++, j
+= 8) {
5380 SiS_SetReg(SISCR
, 0x68 + i
, ptr
[j
+ regb
]);
5385 if(ivideo
->haveXGIROM
) {
5386 index
= (ivideo
->chip
== XGI_20
) ? 0x31a : 0x3a6;
5387 ptr
= (const u8
*)&bios
[index
];
5388 ptr2
= (const u8
*)&bios
[index
+ 0x20];
5390 for(i
= 0; i
< 2; i
++) {
5392 regd
= le32_to_cpu(((u32
*)ptr
)[regb
]);
5395 regd
= le32_to_cpu(((u32
*)ptr2
)[regb
]);
5399 for(j
= 0; j
< 16; j
++) {
5401 if(regd
& 0x01) reg
|= 0x04;
5402 if(regd
& 0x02) reg
|= 0x08;
5404 SiS_SetReg(SISCR
, rega
, reg
);
5405 reg
= SiS_GetReg(SISCR
, rega
);
5406 reg
= SiS_GetReg(SISCR
, rega
);
5411 SiS_SetRegAND(SISCR
, 0x6e, 0xfc);
5414 if(ivideo
->haveXGIROM
) {
5415 index
= (ivideo
->chip
== XGI_20
) ? 0x35a : 0x3e6;
5416 ptr
= (const u8
*)&bios
[index
];
5418 for(i
= 0; i
< 4; i
++) {
5419 SiS_SetRegANDOR(SISCR
, 0x6e, 0xfc, i
);
5421 for(j
= 0; j
< 2; j
++) {
5424 regd
= le32_to_cpu(((u32
*)ptr
)[regb
* 8]);
5428 for(k
= 0; k
< 16; k
++) {
5430 if(regd
& 0x01) reg
|= 0x01;
5431 if(regd
& 0x02) reg
|= 0x02;
5433 SiS_SetReg(SISCR
, 0x6f, reg
);
5434 reg
= SiS_GetReg(SISCR
, 0x6f);
5435 reg
= SiS_GetReg(SISCR
, 0x6f);
5442 if(ivideo
->haveXGIROM
) {
5443 ptr
= (const u8
*)&bios
[0x148];
5445 for(i
= 0, j
= 0; i
< 2; i
++, j
+= 8) {
5446 SiS_SetReg(SISCR
, 0x80 + i
, ptr
[j
+ regb
]);
5449 SiS_SetRegAND(SISCR
, 0x89, 0x8f);
5452 if(ivideo
->haveXGIROM
) {
5453 index
= (ivideo
->chip
== XGI_20
) ? 0x45a : 0x4e6;
5454 ptr
= (const u8
*)&bios
[index
];
5456 regd
= le16_to_cpu(((const u16
*)ptr
)[regb
]);
5458 for(i
= 0; i
< 5; i
++) {
5460 if(regd
& 0x01) reg
|= 0x01;
5461 if(regd
& 0x02) reg
|= 0x02;
5463 SiS_SetReg(SISCR
, 0x89, reg
);
5464 reg
= SiS_GetReg(SISCR
, 0x89);
5465 reg
= SiS_GetReg(SISCR
, 0x89);
5469 v1
= 0xb5; v2
= 0x20; v3
= 0xf0; v4
= 0x13;
5470 if(ivideo
->haveXGIROM
) {
5471 v1
= bios
[0x118 + regb
];
5472 v2
= bios
[0xf8 + regb
];
5473 v3
= bios
[0x120 + regb
];
5476 SiS_SetReg(SISCR
, 0x45, v1
& 0x0f);
5477 SiS_SetReg(SISCR
, 0x99, (v1
>> 4) & 0x07);
5478 SiS_SetRegOR(SISCR
, 0x40, v1
& 0x80);
5479 SiS_SetReg(SISCR
, 0x41, v2
);
5482 if(ivideo
->haveXGIROM
) {
5483 ptr
= (const u8
*)&bios
[0x170];
5485 for(i
= 0, j
= 0; i
< 7; i
++, j
+= 8) {
5486 SiS_SetReg(SISCR
, 0x90 + i
, ptr
[j
+ regb
]);
5489 SiS_SetReg(SISCR
, 0x59, v3
);
5492 if(ivideo
->haveXGIROM
) {
5493 ptr
= (const u8
*)&bios
[0x1a8];
5495 for(i
= 0, j
= 0; i
< 3; i
++, j
+= 8) {
5496 SiS_SetReg(SISCR
, 0xc3 + i
, ptr
[j
+ regb
]);
5500 if(ivideo
->haveXGIROM
) {
5501 ptr
= (const u8
*)&bios
[0x100];
5503 for(i
= 0, j
= 0; i
< 2; i
++, j
+= 8) {
5504 SiS_SetReg(SISCR
, 0x8a + i
, ptr
[j
+ regb
]);
5507 SiS_SetReg(SISCR
, 0xcf, v4
);
5509 SiS_SetReg(SISCR
, 0x83, 0x09);
5510 SiS_SetReg(SISCR
, 0x87, 0x00);
5512 if(ivideo
->chip
== XGI_40
) {
5513 if( (ivideo
->revision_id
== 1) ||
5514 (ivideo
->revision_id
== 2) ) {
5515 SiS_SetReg(SISCR
, 0x8c, 0x87);
5520 SiS_SetReg(SISSR
, 0x17, 0x80); /* DDR2 */
5522 SiS_SetReg(SISSR
, 0x17, 0x00); /* DDR1 */
5523 SiS_SetReg(SISSR
, 0x1a, 0x87);
5525 if(ivideo
->chip
== XGI_20
) {
5526 SiS_SetReg(SISSR
, 0x15, 0x00);
5527 SiS_SetReg(SISSR
, 0x1c, 0x00);
5532 sisfb_post_xgi_setclocks(ivideo
, regb
);
5533 if((ivideo
->chip
== XGI_20
) ||
5534 (ivideo
->revision_id
== 1) ||
5535 (ivideo
->revision_id
== 2)) {
5536 v1
= cs158
[regb
]; v2
= cs160
[regb
]; v3
= cs168
[regb
];
5537 if(ivideo
->haveXGIROM
) {
5538 v1
= bios
[regb
+ 0x158];
5539 v2
= bios
[regb
+ 0x160];
5540 v3
= bios
[regb
+ 0x168];
5542 SiS_SetReg(SISCR
, 0x82, v1
);
5543 SiS_SetReg(SISCR
, 0x85, v2
);
5544 SiS_SetReg(SISCR
, 0x86, v3
);
5546 SiS_SetReg(SISCR
, 0x82, 0x88);
5547 SiS_SetReg(SISCR
, 0x86, 0x00);
5548 reg
= SiS_GetReg(SISCR
, 0x86);
5549 SiS_SetReg(SISCR
, 0x86, 0x88);
5550 reg
= SiS_GetReg(SISCR
, 0x86);
5551 SiS_SetReg(SISCR
, 0x86, bios
[regb
+ 0x168]);
5552 SiS_SetReg(SISCR
, 0x82, 0x77);
5553 SiS_SetReg(SISCR
, 0x85, 0x00);
5554 reg
= SiS_GetReg(SISCR
, 0x85);
5555 SiS_SetReg(SISCR
, 0x85, 0x88);
5556 reg
= SiS_GetReg(SISCR
, 0x85);
5557 SiS_SetReg(SISCR
, 0x85, bios
[regb
+ 0x160]);
5558 SiS_SetReg(SISCR
, 0x82, bios
[regb
+ 0x158]);
5560 if(ivideo
->chip
== XGI_40
) {
5561 SiS_SetReg(SISCR
, 0x97, 0x00);
5563 SiS_SetReg(SISCR
, 0x98, 0x01);
5564 SiS_SetReg(SISCR
, 0x9a, 0x02);
5566 SiS_SetReg(SISSR
, 0x18, 0x01);
5567 if((ivideo
->chip
== XGI_20
) ||
5568 (ivideo
->revision_id
== 2)) {
5569 SiS_SetReg(SISSR
, 0x19, 0x40);
5571 SiS_SetReg(SISSR
, 0x19, 0x20);
5573 SiS_SetReg(SISSR
, 0x16, 0x00);
5574 SiS_SetReg(SISSR
, 0x16, 0x80);
5575 if((ivideo
->chip
== XGI_20
) || (bios
[0x1cb] != 0x0c)) {
5576 sisfb_post_xgi_delay(ivideo
, 0x43);
5577 sisfb_post_xgi_delay(ivideo
, 0x43);
5578 sisfb_post_xgi_delay(ivideo
, 0x43);
5579 SiS_SetReg(SISSR
, 0x18, 0x00);
5580 if((ivideo
->chip
== XGI_20
) ||
5581 (ivideo
->revision_id
== 2)) {
5582 SiS_SetReg(SISSR
, 0x19, 0x40);
5584 SiS_SetReg(SISSR
, 0x19, 0x20);
5586 } else if((ivideo
->chip
== XGI_40
) && (bios
[0x1cb] == 0x0c)) {
5587 /* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
5589 SiS_SetReg(SISSR
, 0x16, 0x00);
5590 SiS_SetReg(SISSR
, 0x16, 0x80);
5591 sisfb_post_xgi_delay(ivideo
, 4);
5592 v1
= 0x31; v2
= 0x03; v3
= 0x83; v4
= 0x03; v5
= 0x83;
5593 if(ivideo
->haveXGIROM
) {
5595 index
= (ivideo
->chip
== XGI_20
) ? 0x4b2 : 0x53e;
5597 v3
= bios
[index
+ 1];
5598 v4
= bios
[index
+ 2];
5599 v5
= bios
[index
+ 3];
5601 SiS_SetReg(SISSR
, 0x18, v1
);
5602 SiS_SetReg(SISSR
, 0x19, ((ivideo
->chip
== XGI_20
) ? 0x02 : 0x01));
5603 SiS_SetReg(SISSR
, 0x16, v2
);
5604 SiS_SetReg(SISSR
, 0x16, v3
);
5605 sisfb_post_xgi_delay(ivideo
, 0x43);
5606 SiS_SetReg(SISSR
, 0x1b, 0x03);
5607 sisfb_post_xgi_delay(ivideo
, 0x22);
5608 SiS_SetReg(SISSR
, 0x18, v1
);
5609 SiS_SetReg(SISSR
, 0x19, 0x00);
5610 SiS_SetReg(SISSR
, 0x16, v4
);
5611 SiS_SetReg(SISSR
, 0x16, v5
);
5612 SiS_SetReg(SISSR
, 0x1b, 0x00);
5615 sisfb_post_xgi_ddr2(ivideo
, regb
);
5618 sisfb_post_xgi_setclocks(ivideo
, regb
);
5619 if((ivideo
->chip
== XGI_40
) &&
5620 ((ivideo
->revision_id
== 1) ||
5621 (ivideo
->revision_id
== 2))) {
5622 SiS_SetReg(SISCR
, 0x82, bios
[regb
+ 0x158]);
5623 SiS_SetReg(SISCR
, 0x85, bios
[regb
+ 0x160]);
5624 SiS_SetReg(SISCR
, 0x86, bios
[regb
+ 0x168]);
5626 SiS_SetReg(SISCR
, 0x82, 0x88);
5627 SiS_SetReg(SISCR
, 0x86, 0x00);
5628 reg
= SiS_GetReg(SISCR
, 0x86);
5629 SiS_SetReg(SISCR
, 0x86, 0x88);
5630 SiS_SetReg(SISCR
, 0x82, 0x77);
5631 SiS_SetReg(SISCR
, 0x85, 0x00);
5632 reg
= SiS_GetReg(SISCR
, 0x85);
5633 SiS_SetReg(SISCR
, 0x85, 0x88);
5634 reg
= SiS_GetReg(SISCR
, 0x85);
5635 v1
= cs160
[regb
]; v2
= cs158
[regb
];
5636 if(ivideo
->haveXGIROM
) {
5637 v1
= bios
[regb
+ 0x160];
5638 v2
= bios
[regb
+ 0x158];
5640 SiS_SetReg(SISCR
, 0x85, v1
);
5641 SiS_SetReg(SISCR
, 0x82, v2
);
5643 if(ivideo
->chip
== XGI_40
) {
5644 SiS_SetReg(SISCR
, 0x97, 0x11);
5646 if((ivideo
->chip
== XGI_40
) && (ivideo
->revision_id
== 2)) {
5647 SiS_SetReg(SISCR
, 0x98, 0x01);
5649 SiS_SetReg(SISCR
, 0x98, 0x03);
5651 SiS_SetReg(SISCR
, 0x9a, 0x02);
5653 if(ivideo
->chip
== XGI_40
) {
5654 SiS_SetReg(SISSR
, 0x18, 0x01);
5656 SiS_SetReg(SISSR
, 0x18, 0x00);
5658 SiS_SetReg(SISSR
, 0x19, 0x40);
5659 SiS_SetReg(SISSR
, 0x16, 0x00);
5660 SiS_SetReg(SISSR
, 0x16, 0x80);
5661 if((ivideo
->chip
== XGI_40
) && (bios
[0x1cb] != 0x0c)) {
5662 sisfb_post_xgi_delay(ivideo
, 0x43);
5663 sisfb_post_xgi_delay(ivideo
, 0x43);
5664 sisfb_post_xgi_delay(ivideo
, 0x43);
5665 SiS_SetReg(SISSR
, 0x18, 0x00);
5666 SiS_SetReg(SISSR
, 0x19, 0x40);
5667 SiS_SetReg(SISSR
, 0x16, 0x00);
5668 SiS_SetReg(SISSR
, 0x16, 0x80);
5670 sisfb_post_xgi_delay(ivideo
, 4);
5672 if(ivideo
->haveXGIROM
) {
5675 SiS_SetReg(SISSR
, 0x18, v1
);
5676 SiS_SetReg(SISSR
, 0x19, 0x01);
5677 if(ivideo
->chip
== XGI_40
) {
5678 SiS_SetReg(SISSR
, 0x16, bios
[0x53e]);
5679 SiS_SetReg(SISSR
, 0x16, bios
[0x53f]);
5681 SiS_SetReg(SISSR
, 0x16, 0x05);
5682 SiS_SetReg(SISSR
, 0x16, 0x85);
5684 sisfb_post_xgi_delay(ivideo
, 0x43);
5685 if(ivideo
->chip
== XGI_40
) {
5686 SiS_SetReg(SISSR
, 0x1b, 0x01);
5688 SiS_SetReg(SISSR
, 0x1b, 0x03);
5690 sisfb_post_xgi_delay(ivideo
, 0x22);
5691 SiS_SetReg(SISSR
, 0x18, v1
);
5692 SiS_SetReg(SISSR
, 0x19, 0x00);
5693 if(ivideo
->chip
== XGI_40
) {
5694 SiS_SetReg(SISSR
, 0x16, bios
[0x540]);
5695 SiS_SetReg(SISSR
, 0x16, bios
[0x541]);
5697 SiS_SetReg(SISSR
, 0x16, 0x05);
5698 SiS_SetReg(SISSR
, 0x16, 0x85);
5700 SiS_SetReg(SISSR
, 0x1b, 0x00);
5705 if(ivideo
->haveXGIROM
) {
5706 v1
= bios
[0x110 + regb
];
5708 SiS_SetReg(SISSR
, 0x1b, v1
);
5711 v1
= 0x00; v2
= 0x00;
5712 if(ivideo
->haveXGIROM
) {
5718 if((v1
& 0x40) && (v2
& regd
) && ivideo
->haveXGIROM
) {
5720 SiS_SetReg(SISSR
, 0x13, bios
[regb
+ 0xe0]);
5721 SiS_SetReg(SISSR
, 0x14, bios
[regb
+ 0xe0 + 8]);
5726 /* Set default mode, don't clear screen */
5727 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
5728 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
5729 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
5730 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
5731 ivideo
->SiS_Pr
.VideoMemorySize
= 8 << 20;
5732 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
5734 SiS_SetReg(SISSR
, 0x05, 0x86);
5736 /* Disable read-cache */
5737 SiS_SetRegAND(SISSR
, 0x21, 0xdf);
5738 err
= sisfb_post_xgi_ramsize(ivideo
);
5739 /* Enable read-cache */
5740 SiS_SetRegOR(SISSR
, 0x21, 0x20);
5744 "%s: RAM size detection failed: %d\n",
5751 printk(KERN_DEBUG
"-----------------\n");
5752 for(i
= 0; i
< 0xff; i
++) {
5753 reg
= SiS_GetReg(SISCR
, i
);
5754 printk(KERN_DEBUG
"CR%02x(%x) = 0x%02x\n", i
, SISCR
, reg
);
5756 for(i
= 0; i
< 0x40; i
++) {
5757 reg
= SiS_GetReg(SISSR
, i
);
5758 printk(KERN_DEBUG
"SR%02x(%x) = 0x%02x\n", i
, SISSR
, reg
);
5760 printk(KERN_DEBUG
"-----------------\n");
5764 if(ivideo
->chip
== XGI_20
) {
5765 SiS_SetRegOR(SISCR
, 0x32, 0x20);
5767 reg
= SiS_GetReg(SISPART4
, 0x00);
5768 if((reg
== 1) || (reg
== 2)) {
5769 sisfb_sense_crt1(ivideo
);
5771 SiS_SetRegOR(SISCR
, 0x32, 0x20);
5775 /* Set default mode, don't clear screen */
5776 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
5777 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
5778 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
5779 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
5780 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
5782 SiS_SetReg(SISSR
, 0x05, 0x86);
5785 SiS_SetRegOR(SISSR
, 0x01, 0x20);
5787 /* Save mode number in CR34 */
5788 SiS_SetReg(SISCR
, 0x34, 0x2e);
5790 /* Let everyone know what the current mode is */
5791 ivideo
->modeprechange
= 0x2e;
5793 if(ivideo
->chip
== XGI_40
) {
5794 reg
= SiS_GetReg(SISCR
, 0xca);
5795 v1
= SiS_GetReg(SISCR
, 0xcc);
5796 if((reg
& 0x10) && (!(v1
& 0x04))) {
5798 "sisfb: Please connect power to the card.\n");
5807 static int sisfb_probe(struct pci_dev
*pdev
, const struct pci_device_id
*ent
)
5809 struct sisfb_chip_info
*chipinfo
= &sisfb_chip_info
[ent
->driver_data
];
5810 struct sis_video_info
*ivideo
= NULL
;
5811 struct fb_info
*sis_fb_info
= NULL
;
5819 sis_fb_info
= framebuffer_alloc(sizeof(*ivideo
), &pdev
->dev
);
5823 ivideo
= (struct sis_video_info
*)sis_fb_info
->par
;
5824 ivideo
->memyselfandi
= sis_fb_info
;
5826 ivideo
->sisfb_id
= SISFB_ID
;
5828 if(card_list
== NULL
) {
5829 ivideo
->cardnumber
= 0;
5831 struct sis_video_info
*countvideo
= card_list
;
5832 ivideo
->cardnumber
= 1;
5833 while((countvideo
= countvideo
->next
) != NULL
)
5834 ivideo
->cardnumber
++;
5837 strncpy(ivideo
->myid
, chipinfo
->chip_name
, 30);
5839 ivideo
->warncount
= 0;
5840 ivideo
->chip_id
= pdev
->device
;
5841 ivideo
->chip_vendor
= pdev
->vendor
;
5842 ivideo
->revision_id
= pdev
->revision
;
5843 ivideo
->SiS_Pr
.ChipRevision
= ivideo
->revision_id
;
5844 pci_read_config_word(pdev
, PCI_COMMAND
, ®16
);
5845 ivideo
->sisvga_enabled
= reg16
& 0x01;
5846 ivideo
->pcibus
= pdev
->bus
->number
;
5847 ivideo
->pcislot
= PCI_SLOT(pdev
->devfn
);
5848 ivideo
->pcifunc
= PCI_FUNC(pdev
->devfn
);
5849 ivideo
->subsysvendor
= pdev
->subsystem_vendor
;
5850 ivideo
->subsysdevice
= pdev
->subsystem_device
;
5853 if(sisfb_mode_idx
== -1) {
5854 sisfb_get_vga_mode_from_kernel();
5858 ivideo
->chip
= chipinfo
->chip
;
5859 ivideo
->chip_real_id
= chipinfo
->chip
;
5860 ivideo
->sisvga_engine
= chipinfo
->vgaengine
;
5861 ivideo
->hwcursor_size
= chipinfo
->hwcursor_size
;
5862 ivideo
->CRT2_write_enable
= chipinfo
->CRT2_write_enable
;
5863 ivideo
->mni
= chipinfo
->mni
;
5865 ivideo
->detectedpdc
= 0xff;
5866 ivideo
->detectedpdca
= 0xff;
5867 ivideo
->detectedlcda
= 0xff;
5869 ivideo
->sisfb_thismonitor
.datavalid
= false;
5871 ivideo
->current_base
= 0;
5873 ivideo
->engineok
= 0;
5875 ivideo
->sisfb_was_boot_device
= 0;
5877 if(pdev
->resource
[PCI_ROM_RESOURCE
].flags
& IORESOURCE_ROM_SHADOW
) {
5878 if(ivideo
->sisvga_enabled
)
5879 ivideo
->sisfb_was_boot_device
= 1;
5881 printk(KERN_DEBUG
"sisfb: PCI device is disabled, "
5882 "but marked as boot video device ???\n");
5883 printk(KERN_DEBUG
"sisfb: I will not accept this "
5884 "as the primary VGA device\n");
5888 ivideo
->sisfb_parm_mem
= sisfb_parm_mem
;
5889 ivideo
->sisfb_accel
= sisfb_accel
;
5890 ivideo
->sisfb_ypan
= sisfb_ypan
;
5891 ivideo
->sisfb_max
= sisfb_max
;
5892 ivideo
->sisfb_userom
= sisfb_userom
;
5893 ivideo
->sisfb_useoem
= sisfb_useoem
;
5894 ivideo
->sisfb_mode_idx
= sisfb_mode_idx
;
5895 ivideo
->sisfb_parm_rate
= sisfb_parm_rate
;
5896 ivideo
->sisfb_crt1off
= sisfb_crt1off
;
5897 ivideo
->sisfb_forcecrt1
= sisfb_forcecrt1
;
5898 ivideo
->sisfb_crt2type
= sisfb_crt2type
;
5899 ivideo
->sisfb_crt2flags
= sisfb_crt2flags
;
5900 /* pdc(a), scalelcd, special timing, lvdshl handled below */
5901 ivideo
->sisfb_dstn
= sisfb_dstn
;
5902 ivideo
->sisfb_fstn
= sisfb_fstn
;
5903 ivideo
->sisfb_tvplug
= sisfb_tvplug
;
5904 ivideo
->sisfb_tvstd
= sisfb_tvstd
;
5905 ivideo
->tvxpos
= sisfb_tvxposoffset
;
5906 ivideo
->tvypos
= sisfb_tvyposoffset
;
5907 ivideo
->sisfb_nocrt2rate
= sisfb_nocrt2rate
;
5908 ivideo
->refresh_rate
= 0;
5909 if(ivideo
->sisfb_parm_rate
!= -1) {
5910 ivideo
->refresh_rate
= ivideo
->sisfb_parm_rate
;
5913 ivideo
->SiS_Pr
.UsePanelScaler
= sisfb_scalelcd
;
5914 ivideo
->SiS_Pr
.CenterScreen
= -1;
5915 ivideo
->SiS_Pr
.SiS_CustomT
= sisfb_specialtiming
;
5916 ivideo
->SiS_Pr
.LVDSHL
= sisfb_lvdshl
;
5918 ivideo
->SiS_Pr
.SiS_Backup70xx
= 0xff;
5919 ivideo
->SiS_Pr
.SiS_CHOverScan
= -1;
5920 ivideo
->SiS_Pr
.SiS_ChSW
= false;
5921 ivideo
->SiS_Pr
.SiS_UseLCDA
= false;
5922 ivideo
->SiS_Pr
.HaveEMI
= false;
5923 ivideo
->SiS_Pr
.HaveEMILCD
= false;
5924 ivideo
->SiS_Pr
.OverruleEMI
= false;
5925 ivideo
->SiS_Pr
.SiS_SensibleSR11
= false;
5926 ivideo
->SiS_Pr
.SiS_MyCR63
= 0x63;
5927 ivideo
->SiS_Pr
.PDC
= -1;
5928 ivideo
->SiS_Pr
.PDCA
= -1;
5929 ivideo
->SiS_Pr
.DDCPortMixup
= false;
5930 #ifdef CONFIG_FB_SIS_315
5931 if(ivideo
->chip
>= SIS_330
) {
5932 ivideo
->SiS_Pr
.SiS_MyCR63
= 0x53;
5933 if(ivideo
->chip
>= SIS_661
) {
5934 ivideo
->SiS_Pr
.SiS_SensibleSR11
= true;
5939 memcpy(&ivideo
->default_var
, &my_default_var
, sizeof(my_default_var
));
5941 pci_set_drvdata(pdev
, ivideo
);
5943 /* Patch special cases */
5944 if((ivideo
->nbridge
= sisfb_get_northbridge(ivideo
->chip
))) {
5945 switch(ivideo
->nbridge
->device
) {
5946 #ifdef CONFIG_FB_SIS_300
5947 case PCI_DEVICE_ID_SI_730
:
5948 ivideo
->chip
= SIS_730
;
5949 strcpy(ivideo
->myid
, "SiS 730");
5952 #ifdef CONFIG_FB_SIS_315
5953 case PCI_DEVICE_ID_SI_651
:
5954 /* ivideo->chip is ok */
5955 strcpy(ivideo
->myid
, "SiS 651");
5957 case PCI_DEVICE_ID_SI_740
:
5958 ivideo
->chip
= SIS_740
;
5959 strcpy(ivideo
->myid
, "SiS 740");
5961 case PCI_DEVICE_ID_SI_661
:
5962 ivideo
->chip
= SIS_661
;
5963 strcpy(ivideo
->myid
, "SiS 661");
5965 case PCI_DEVICE_ID_SI_741
:
5966 ivideo
->chip
= SIS_741
;
5967 strcpy(ivideo
->myid
, "SiS 741");
5969 case PCI_DEVICE_ID_SI_760
:
5970 ivideo
->chip
= SIS_760
;
5971 strcpy(ivideo
->myid
, "SiS 760");
5973 case PCI_DEVICE_ID_SI_761
:
5974 ivideo
->chip
= SIS_761
;
5975 strcpy(ivideo
->myid
, "SiS 761");
5983 ivideo
->SiS_Pr
.ChipType
= ivideo
->chip
;
5985 ivideo
->SiS_Pr
.ivideo
= (void *)ivideo
;
5987 #ifdef CONFIG_FB_SIS_315
5988 if((ivideo
->SiS_Pr
.ChipType
== SIS_315PRO
) ||
5989 (ivideo
->SiS_Pr
.ChipType
== SIS_315
)) {
5990 ivideo
->SiS_Pr
.ChipType
= SIS_315H
;
5994 if(!ivideo
->sisvga_enabled
) {
5995 if(pci_enable_device(pdev
)) {
5996 if(ivideo
->nbridge
) pci_dev_put(ivideo
->nbridge
);
5997 pci_set_drvdata(pdev
, NULL
);
5998 framebuffer_release(sis_fb_info
);
6003 ivideo
->video_base
= pci_resource_start(pdev
, 0);
6004 ivideo
->video_size
= pci_resource_len(pdev
, 0);
6005 ivideo
->mmio_base
= pci_resource_start(pdev
, 1);
6006 ivideo
->mmio_size
= pci_resource_len(pdev
, 1);
6007 ivideo
->SiS_Pr
.RelIO
= pci_resource_start(pdev
, 2) + 0x30;
6008 ivideo
->SiS_Pr
.IOAddress
= ivideo
->vga_base
= ivideo
->SiS_Pr
.RelIO
;
6010 SiSRegInit(&ivideo
->SiS_Pr
, ivideo
->SiS_Pr
.IOAddress
);
6012 #ifdef CONFIG_FB_SIS_300
6013 /* Find PCI systems for Chrontel/GPIO communication setup */
6014 if(ivideo
->chip
== SIS_630
) {
6017 if(mychswtable
[i
].subsysVendor
== ivideo
->subsysvendor
&&
6018 mychswtable
[i
].subsysCard
== ivideo
->subsysdevice
) {
6019 ivideo
->SiS_Pr
.SiS_ChSW
= true;
6020 printk(KERN_DEBUG
"sisfb: Identified [%s %s] "
6021 "requiring Chrontel/GPIO setup\n",
6022 mychswtable
[i
].vendorName
,
6023 mychswtable
[i
].cardName
);
6024 ivideo
->lpcdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0008, NULL
);
6028 } while(mychswtable
[i
].subsysVendor
!= 0);
6032 #ifdef CONFIG_FB_SIS_315
6033 if((ivideo
->chip
== SIS_760
) && (ivideo
->nbridge
)) {
6034 ivideo
->lpcdev
= pci_get_slot(ivideo
->nbridge
->bus
, (2 << 3));
6038 SiS_SetReg(SISSR
, 0x05, 0x86);
6040 if( (!ivideo
->sisvga_enabled
)
6041 #if !defined(__i386__) && !defined(__x86_64__)
6042 || (sisfb_resetcard
)
6045 for(i
= 0x30; i
<= 0x3f; i
++) {
6046 SiS_SetReg(SISCR
, i
, 0x00);
6050 /* Find out about current video mode */
6051 ivideo
->modeprechange
= 0x03;
6052 reg
= SiS_GetReg(SISCR
, 0x34);
6054 ivideo
->modeprechange
= reg
& 0x7f;
6055 } else if(ivideo
->sisvga_enabled
) {
6056 #if defined(__i386__) || defined(__x86_64__)
6057 unsigned char __iomem
*tt
= ioremap(0x400, 0x100);
6059 ivideo
->modeprechange
= readb(tt
+ 0x49);
6065 /* Search and copy ROM image */
6066 ivideo
->bios_abase
= NULL
;
6067 ivideo
->SiS_Pr
.VirtualRomBase
= NULL
;
6068 ivideo
->SiS_Pr
.UseROM
= false;
6069 ivideo
->haveXGIROM
= ivideo
->SiS_Pr
.SiS_XGIROM
= false;
6070 if(ivideo
->sisfb_userom
) {
6071 ivideo
->SiS_Pr
.VirtualRomBase
= sisfb_find_rom(pdev
);
6072 ivideo
->bios_abase
= ivideo
->SiS_Pr
.VirtualRomBase
;
6073 ivideo
->SiS_Pr
.UseROM
= (bool)(ivideo
->SiS_Pr
.VirtualRomBase
);
6074 printk(KERN_INFO
"sisfb: Video ROM %sfound\n",
6075 ivideo
->SiS_Pr
.UseROM
? "" : "not ");
6076 if((ivideo
->SiS_Pr
.UseROM
) && (ivideo
->chip
>= XGI_20
)) {
6077 ivideo
->SiS_Pr
.UseROM
= false;
6078 ivideo
->haveXGIROM
= ivideo
->SiS_Pr
.SiS_XGIROM
= true;
6079 if( (ivideo
->revision_id
== 2) &&
6080 (!(ivideo
->bios_abase
[0x1d1] & 0x01)) ) {
6081 ivideo
->SiS_Pr
.DDCPortMixup
= true;
6085 printk(KERN_INFO
"sisfb: Video ROM usage disabled\n");
6088 /* Find systems for special custom timing */
6089 if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_NONE
) {
6090 sisfb_detect_custom_timing(ivideo
);
6093 #ifdef CONFIG_FB_SIS_315
6094 if (ivideo
->chip
== XGI_20
) {
6095 /* Check if our Z7 chip is actually Z9 */
6096 SiS_SetRegOR(SISCR
, 0x4a, 0x40); /* GPIOG EN */
6097 reg
= SiS_GetReg(SISCR
, 0x48);
6098 if (reg
& 0x02) { /* GPIOG */
6099 ivideo
->chip_real_id
= XGI_21
;
6100 dev_info(&pdev
->dev
, "Z9 detected\n");
6105 /* POST card in case this has not been done by the BIOS */
6106 if( (!ivideo
->sisvga_enabled
)
6107 #if !defined(__i386__) && !defined(__x86_64__)
6108 || (sisfb_resetcard
)
6111 #ifdef CONFIG_FB_SIS_300
6112 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
6113 if(ivideo
->chip
== SIS_300
) {
6114 sisfb_post_sis300(pdev
);
6115 ivideo
->sisfb_can_post
= 1;
6120 #ifdef CONFIG_FB_SIS_315
6121 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
6123 /* if((ivideo->chip == SIS_315H) ||
6124 (ivideo->chip == SIS_315) ||
6125 (ivideo->chip == SIS_315PRO) ||
6126 (ivideo->chip == SIS_330)) {
6127 sisfb_post_sis315330(pdev);
6128 } else */ if(ivideo
->chip
== XGI_20
) {
6129 result
= sisfb_post_xgi(pdev
);
6130 ivideo
->sisfb_can_post
= 1;
6131 } else if((ivideo
->chip
== XGI_40
) && ivideo
->haveXGIROM
) {
6132 result
= sisfb_post_xgi(pdev
);
6133 ivideo
->sisfb_can_post
= 1;
6135 printk(KERN_INFO
"sisfb: Card is not "
6136 "POSTed and sisfb can't do this either.\n");
6139 printk(KERN_ERR
"sisfb: Failed to POST card\n");
6147 ivideo
->sisfb_card_posted
= 1;
6149 /* Find out about RAM size */
6150 if(sisfb_get_dram_size(ivideo
)) {
6151 printk(KERN_INFO
"sisfb: Fatal error: Unable to determine VRAM size.\n");
6157 /* Enable PCI addressing and MMIO */
6158 if((ivideo
->sisfb_mode_idx
< 0) ||
6159 ((sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
]) != 0xFF)) {
6160 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
6161 SiS_SetRegOR(SISSR
, IND_SIS_PCI_ADDRESS_SET
, (SIS_PCI_ADDR_ENABLE
| SIS_MEM_MAP_IO_ENABLE
));
6162 /* Enable 2D accelerator engine */
6163 SiS_SetRegOR(SISSR
, IND_SIS_MODULE_ENABLE
, SIS_ENABLE_2D
);
6166 if(sisfb_pdc
!= 0xff) {
6167 if(ivideo
->sisvga_engine
== SIS_300_VGA
)
6171 ivideo
->SiS_Pr
.PDC
= sisfb_pdc
;
6173 #ifdef CONFIG_FB_SIS_315
6174 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
6175 if(sisfb_pdca
!= 0xff)
6176 ivideo
->SiS_Pr
.PDCA
= sisfb_pdca
& 0x1f;
6180 if(!request_mem_region(ivideo
->video_base
, ivideo
->video_size
, "sisfb FB")) {
6181 printk(KERN_ERR
"sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6182 (int)(ivideo
->video_size
>> 20));
6183 printk(KERN_ERR
"sisfb: Is there another framebuffer driver active?\n");
6188 if(!request_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
, "sisfb MMIO")) {
6189 printk(KERN_ERR
"sisfb: Fatal error: Unable to reserve MMIO region\n");
6194 ivideo
->video_vbase
= ioremap(ivideo
->video_base
, ivideo
->video_size
);
6195 ivideo
->SiS_Pr
.VideoMemoryAddress
= ivideo
->video_vbase
;
6196 if(!ivideo
->video_vbase
) {
6197 printk(KERN_ERR
"sisfb: Fatal error: Unable to map framebuffer memory\n");
6202 ivideo
->mmio_vbase
= ioremap(ivideo
->mmio_base
, ivideo
->mmio_size
);
6203 if(!ivideo
->mmio_vbase
) {
6204 printk(KERN_ERR
"sisfb: Fatal error: Unable to map MMIO region\n");
6206 error_0
: iounmap(ivideo
->video_vbase
);
6207 error_1
: release_mem_region(ivideo
->video_base
, ivideo
->video_size
);
6208 error_2
: release_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
);
6209 error_3
: vfree(ivideo
->bios_abase
);
6211 pci_dev_put(ivideo
->lpcdev
);
6213 pci_dev_put(ivideo
->nbridge
);
6214 pci_set_drvdata(pdev
, NULL
);
6215 if(!ivideo
->sisvga_enabled
)
6216 pci_disable_device(pdev
);
6217 framebuffer_release(sis_fb_info
);
6221 printk(KERN_INFO
"sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
6222 ivideo
->video_base
, (unsigned long)ivideo
->video_vbase
, ivideo
->video_size
/ 1024);
6224 if(ivideo
->video_offset
) {
6225 printk(KERN_INFO
"sisfb: Viewport offset %ldk\n",
6226 ivideo
->video_offset
/ 1024);
6229 printk(KERN_INFO
"sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
6230 ivideo
->mmio_base
, (unsigned long)ivideo
->mmio_vbase
, ivideo
->mmio_size
/ 1024);
6233 /* Determine the size of the command queue */
6234 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
6235 ivideo
->cmdQueueSize
= TURBO_QUEUE_AREA_SIZE
;
6237 if(ivideo
->chip
== XGI_20
) {
6238 ivideo
->cmdQueueSize
= COMMAND_QUEUE_AREA_SIZE_Z7
;
6240 ivideo
->cmdQueueSize
= COMMAND_QUEUE_AREA_SIZE
;
6244 /* Engines are no longer initialized here; this is
6245 * now done after the first mode-switch (if the
6246 * submitted var has its acceleration flags set).
6249 /* Calculate the base of the (unused) hw cursor */
6250 ivideo
->hwcursor_vbase
= ivideo
->video_vbase
6251 + ivideo
->video_size
6252 - ivideo
->cmdQueueSize
6253 - ivideo
->hwcursor_size
;
6254 ivideo
->caps
|= HW_CURSOR_CAP
;
6256 /* Initialize offscreen memory manager */
6257 if((ivideo
->havenoheap
= sisfb_heap_init(ivideo
))) {
6258 printk(KERN_WARNING
"sisfb: Failed to initialize offscreen memory heap\n");
6261 /* Used for clearing the screen only, therefore respect our mem limit */
6262 ivideo
->SiS_Pr
.VideoMemoryAddress
+= ivideo
->video_offset
;
6263 ivideo
->SiS_Pr
.VideoMemorySize
= ivideo
->sisfb_mem
;
6267 ivideo
->vbflags
= 0;
6268 ivideo
->lcddefmodeidx
= DEFAULT_LCDMODE
;
6269 ivideo
->tvdefmodeidx
= DEFAULT_TVMODE
;
6270 ivideo
->defmodeidx
= DEFAULT_MODE
;
6273 if(ivideo
->chip
< XGI_20
) {
6274 if(ivideo
->bios_abase
) {
6275 ivideo
->newrom
= SiSDetermineROMLayout661(&ivideo
->SiS_Pr
);
6279 if((ivideo
->sisfb_mode_idx
< 0) ||
6280 ((sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
]) != 0xFF)) {
6282 sisfb_sense_crt1(ivideo
);
6284 sisfb_get_VB_type(ivideo
);
6286 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
6287 sisfb_detect_VB_connect(ivideo
);
6290 ivideo
->currentvbflags
= ivideo
->vbflags
& (VB_VIDEOBRIDGE
| TV_STANDARD
);
6292 /* Decide on which CRT2 device to use */
6293 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
6294 if(ivideo
->sisfb_crt2type
!= -1) {
6295 if((ivideo
->sisfb_crt2type
== CRT2_LCD
) &&
6296 (ivideo
->vbflags
& CRT2_LCD
)) {
6297 ivideo
->currentvbflags
|= CRT2_LCD
;
6298 } else if(ivideo
->sisfb_crt2type
!= CRT2_LCD
) {
6299 ivideo
->currentvbflags
|= ivideo
->sisfb_crt2type
;
6302 /* Chrontel 700x TV detection often unreliable, therefore
6303 * use a different default order on such machines
6305 if((ivideo
->sisvga_engine
== SIS_300_VGA
) &&
6306 (ivideo
->vbflags2
& VB2_CHRONTEL
)) {
6307 if(ivideo
->vbflags
& CRT2_LCD
)
6308 ivideo
->currentvbflags
|= CRT2_LCD
;
6309 else if(ivideo
->vbflags
& CRT2_TV
)
6310 ivideo
->currentvbflags
|= CRT2_TV
;
6311 else if(ivideo
->vbflags
& CRT2_VGA
)
6312 ivideo
->currentvbflags
|= CRT2_VGA
;
6314 if(ivideo
->vbflags
& CRT2_TV
)
6315 ivideo
->currentvbflags
|= CRT2_TV
;
6316 else if(ivideo
->vbflags
& CRT2_LCD
)
6317 ivideo
->currentvbflags
|= CRT2_LCD
;
6318 else if(ivideo
->vbflags
& CRT2_VGA
)
6319 ivideo
->currentvbflags
|= CRT2_VGA
;
6324 if(ivideo
->vbflags
& CRT2_LCD
) {
6325 sisfb_detect_lcd_type(ivideo
);
6328 sisfb_save_pdc_emi(ivideo
);
6330 if(!ivideo
->sisfb_crt1off
) {
6331 sisfb_handle_ddc(ivideo
, &ivideo
->sisfb_thismonitor
, 0);
6333 if((ivideo
->vbflags2
& VB2_SISTMDSBRIDGE
) &&
6334 (ivideo
->vbflags
& (CRT2_VGA
| CRT2_LCD
))) {
6335 sisfb_handle_ddc(ivideo
, &ivideo
->sisfb_thismonitor
, 1);
6339 if(ivideo
->sisfb_mode_idx
>= 0) {
6340 int bu
= ivideo
->sisfb_mode_idx
;
6341 ivideo
->sisfb_mode_idx
= sisfb_validate_mode(ivideo
,
6342 ivideo
->sisfb_mode_idx
, ivideo
->currentvbflags
);
6343 if(bu
!= ivideo
->sisfb_mode_idx
) {
6344 printk(KERN_ERR
"Mode %dx%dx%d failed validation\n",
6345 sisbios_mode
[bu
].xres
,
6346 sisbios_mode
[bu
].yres
,
6347 sisbios_mode
[bu
].bpp
);
6351 if(ivideo
->sisfb_mode_idx
< 0) {
6352 switch(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
6354 ivideo
->sisfb_mode_idx
= ivideo
->lcddefmodeidx
;
6357 ivideo
->sisfb_mode_idx
= ivideo
->tvdefmodeidx
;
6360 ivideo
->sisfb_mode_idx
= ivideo
->defmodeidx
;
6365 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
6367 if(ivideo
->refresh_rate
!= 0) {
6368 sisfb_search_refresh_rate(ivideo
, ivideo
->refresh_rate
,
6369 ivideo
->sisfb_mode_idx
);
6372 if(ivideo
->rate_idx
== 0) {
6373 ivideo
->rate_idx
= sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
;
6374 ivideo
->refresh_rate
= 60;
6377 if(ivideo
->sisfb_thismonitor
.datavalid
) {
6378 if(!sisfb_verify_rate(ivideo
, &ivideo
->sisfb_thismonitor
,
6379 ivideo
->sisfb_mode_idx
,
6381 ivideo
->refresh_rate
)) {
6382 printk(KERN_INFO
"sisfb: WARNING: Refresh rate "
6383 "exceeds monitor specs!\n");
6387 ivideo
->video_bpp
= sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
;
6388 ivideo
->video_width
= sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
;
6389 ivideo
->video_height
= sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
;
6391 sisfb_set_vparms(ivideo
);
6393 printk(KERN_INFO
"sisfb: Default mode is %dx%dx%d (%dHz)\n",
6394 ivideo
->video_width
, ivideo
->video_height
, ivideo
->video_bpp
,
6395 ivideo
->refresh_rate
);
6397 /* Set up the default var according to chosen default display mode */
6398 ivideo
->default_var
.xres
= ivideo
->default_var
.xres_virtual
= ivideo
->video_width
;
6399 ivideo
->default_var
.yres
= ivideo
->default_var
.yres_virtual
= ivideo
->video_height
;
6400 ivideo
->default_var
.bits_per_pixel
= ivideo
->video_bpp
;
6402 sisfb_bpp_to_var(ivideo
, &ivideo
->default_var
);
6404 ivideo
->default_var
.pixclock
= (u32
) (1000000000 /
6405 sisfb_mode_rate_to_dclock(&ivideo
->SiS_Pr
, ivideo
->mode_no
, ivideo
->rate_idx
));
6407 if(sisfb_mode_rate_to_ddata(&ivideo
->SiS_Pr
, ivideo
->mode_no
,
6408 ivideo
->rate_idx
, &ivideo
->default_var
)) {
6409 if((ivideo
->default_var
.vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
6410 ivideo
->default_var
.pixclock
<<= 1;
6414 if(ivideo
->sisfb_ypan
) {
6415 /* Maximize regardless of sisfb_max at startup */
6416 ivideo
->default_var
.yres_virtual
=
6417 sisfb_calc_maxyres(ivideo
, &ivideo
->default_var
);
6418 if(ivideo
->default_var
.yres_virtual
< ivideo
->default_var
.yres
) {
6419 ivideo
->default_var
.yres_virtual
= ivideo
->default_var
.yres
;
6423 sisfb_calc_pitch(ivideo
, &ivideo
->default_var
);
6426 if(ivideo
->sisfb_accel
) {
6428 #ifdef STUPID_ACCELF_TEXT_SHIT
6429 ivideo
->default_var
.accel_flags
|= FB_ACCELF_TEXT
;
6432 sisfb_initaccel(ivideo
);
6434 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
6435 sis_fb_info
->flags
= FBINFO_DEFAULT
|
6436 FBINFO_HWACCEL_YPAN
|
6437 FBINFO_HWACCEL_XPAN
|
6438 FBINFO_HWACCEL_COPYAREA
|
6439 FBINFO_HWACCEL_FILLRECT
|
6440 ((ivideo
->accel
) ? 0 : FBINFO_HWACCEL_DISABLED
);
6442 sis_fb_info
->flags
= FBINFO_FLAG_DEFAULT
;
6444 sis_fb_info
->var
= ivideo
->default_var
;
6445 sis_fb_info
->fix
= ivideo
->sisfb_fix
;
6446 sis_fb_info
->screen_base
= ivideo
->video_vbase
+ ivideo
->video_offset
;
6447 sis_fb_info
->fbops
= &sisfb_ops
;
6448 sis_fb_info
->pseudo_palette
= ivideo
->pseudo_palette
;
6450 fb_alloc_cmap(&sis_fb_info
->cmap
, 256 , 0);
6452 printk(KERN_DEBUG
"sisfb: Initial vbflags 0x%x\n", (int)ivideo
->vbflags
);
6455 ivideo
->mtrr
= mtrr_add(ivideo
->video_base
, ivideo
->video_size
,
6456 MTRR_TYPE_WRCOMB
, 1);
6457 if(ivideo
->mtrr
< 0) {
6458 printk(KERN_DEBUG
"sisfb: Failed to add MTRRs\n");
6462 if(register_framebuffer(sis_fb_info
) < 0) {
6463 printk(KERN_ERR
"sisfb: Fatal error: Failed to register framebuffer\n");
6465 iounmap(ivideo
->mmio_vbase
);
6469 ivideo
->registered
= 1;
6472 ivideo
->next
= card_list
;
6475 printk(KERN_INFO
"sisfb: 2D acceleration is %s, y-panning %s\n",
6476 ivideo
->sisfb_accel
? "enabled" : "disabled",
6477 ivideo
->sisfb_ypan
?
6478 (ivideo
->sisfb_max
? "enabled (auto-max)" :
6479 "enabled (no auto-max)") :
6483 printk(KERN_INFO
"fb%d: %s frame buffer device version %d.%d.%d\n",
6484 sis_fb_info
->node
, ivideo
->myid
, VER_MAJOR
, VER_MINOR
, VER_LEVEL
);
6486 printk(KERN_INFO
"sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
6488 } /* if mode = "none" */
6493 /*****************************************************/
6494 /* PCI DEVICE HANDLING */
6495 /*****************************************************/
6497 static void sisfb_remove(struct pci_dev
*pdev
)
6499 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
6500 struct fb_info
*sis_fb_info
= ivideo
->memyselfandi
;
6501 int registered
= ivideo
->registered
;
6502 int modechanged
= ivideo
->modechanged
;
6505 iounmap(ivideo
->mmio_vbase
);
6506 iounmap(ivideo
->video_vbase
);
6508 /* Release mem regions */
6509 release_mem_region(ivideo
->video_base
, ivideo
->video_size
);
6510 release_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
);
6512 vfree(ivideo
->bios_abase
);
6515 pci_dev_put(ivideo
->lpcdev
);
6518 pci_dev_put(ivideo
->nbridge
);
6521 /* Release MTRR region */
6522 if(ivideo
->mtrr
>= 0)
6523 mtrr_del(ivideo
->mtrr
, ivideo
->video_base
, ivideo
->video_size
);
6526 pci_set_drvdata(pdev
, NULL
);
6528 /* If device was disabled when starting, disable
6531 if(!ivideo
->sisvga_enabled
)
6532 pci_disable_device(pdev
);
6534 /* Unregister the framebuffer */
6535 if(ivideo
->registered
) {
6536 unregister_framebuffer(sis_fb_info
);
6537 framebuffer_release(sis_fb_info
);
6540 /* OK, our ivideo is gone for good from here. */
6542 /* TODO: Restore the initial mode
6543 * This sounds easy but is as good as impossible
6544 * on many machines with SiS chip and video bridge
6545 * since text modes are always set up differently
6546 * from machine to machine. Depends on the type
6547 * of integration between chipset and bridge.
6549 if(registered
&& modechanged
)
6551 "sisfb: Restoring of text mode not supported yet\n");
6554 static struct pci_driver sisfb_driver
= {
6556 .id_table
= sisfb_pci_table
,
6557 .probe
= sisfb_probe
,
6558 .remove
= sisfb_remove
,
6561 static int __init
sisfb_init(void)
6564 char *options
= NULL
;
6566 if(fb_get_options("sisfb", &options
))
6569 sisfb_setup(options
);
6571 return pci_register_driver(&sisfb_driver
);
6575 module_init(sisfb_init
);
6578 /*****************************************************/
6580 /*****************************************************/
6584 static char *mode
= NULL
;
6585 static int vesa
= -1;
6586 static unsigned int rate
= 0;
6587 static unsigned int crt1off
= 1;
6588 static unsigned int mem
= 0;
6589 static char *forcecrt2type
= NULL
;
6590 static int forcecrt1
= -1;
6591 static int pdc
= -1;
6592 static int pdc1
= -1;
6593 static int noaccel
= -1;
6594 static int noypan
= -1;
6595 static int nomax
= -1;
6596 static int userom
= -1;
6597 static int useoem
= -1;
6598 static char *tvstandard
= NULL
;
6599 static int nocrt2rate
= 0;
6600 static int scalelcd
= -1;
6601 static char *specialtiming
= NULL
;
6602 static int lvdshl
= -1;
6603 static int tvxposoffset
= 0, tvyposoffset
= 0;
6604 #if !defined(__i386__) && !defined(__x86_64__)
6605 static int resetcard
= 0;
6606 static int videoram
= 0;
6609 static int __init
sisfb_init_module(void)
6611 sisfb_setdefaultparms();
6614 sisfb_parm_rate
= rate
;
6616 if((scalelcd
== 0) || (scalelcd
== 1))
6617 sisfb_scalelcd
= scalelcd
^ 1;
6619 /* Need to check crt2 type first for fstn/dstn */
6622 sisfb_search_crt2type(forcecrt2type
);
6625 sisfb_search_tvstd(tvstandard
);
6628 sisfb_search_mode(mode
, false);
6630 sisfb_search_vesamode(vesa
, false);
6632 sisfb_crt1off
= (crt1off
== 0) ? 1 : 0;
6634 sisfb_forcecrt1
= forcecrt1
;
6637 else if(forcecrt1
== 0)
6642 else if(noaccel
== 0)
6647 else if(noypan
== 0)
6656 sisfb_parm_mem
= mem
;
6659 sisfb_userom
= userom
;
6662 sisfb_useoem
= useoem
;
6665 sisfb_pdc
= (pdc
& 0x7f);
6668 sisfb_pdca
= (pdc1
& 0x1f);
6670 sisfb_nocrt2rate
= nocrt2rate
;
6673 sisfb_search_specialtiming(specialtiming
);
6675 if((lvdshl
>= 0) && (lvdshl
<= 3))
6676 sisfb_lvdshl
= lvdshl
;
6678 sisfb_tvxposoffset
= tvxposoffset
;
6679 sisfb_tvyposoffset
= tvyposoffset
;
6681 #if !defined(__i386__) && !defined(__x86_64__)
6682 sisfb_resetcard
= (resetcard
) ? 1 : 0;
6684 sisfb_videoram
= videoram
;
6687 return sisfb_init();
6690 static void __exit
sisfb_remove_module(void)
6692 pci_unregister_driver(&sisfb_driver
);
6693 printk(KERN_DEBUG
"sisfb: Module unloaded\n");
6696 module_init(sisfb_init_module
);
6697 module_exit(sisfb_remove_module
);
6699 MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
6700 MODULE_LICENSE("GPL");
6701 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
6703 module_param(mem
, int, 0);
6704 module_param(noaccel
, int, 0);
6705 module_param(noypan
, int, 0);
6706 module_param(nomax
, int, 0);
6707 module_param(userom
, int, 0);
6708 module_param(useoem
, int, 0);
6709 module_param(mode
, charp
, 0);
6710 module_param(vesa
, int, 0);
6711 module_param(rate
, int, 0);
6712 module_param(forcecrt1
, int, 0);
6713 module_param(forcecrt2type
, charp
, 0);
6714 module_param(scalelcd
, int, 0);
6715 module_param(pdc
, int, 0);
6716 module_param(pdc1
, int, 0);
6717 module_param(specialtiming
, charp
, 0);
6718 module_param(lvdshl
, int, 0);
6719 module_param(tvstandard
, charp
, 0);
6720 module_param(tvxposoffset
, int, 0);
6721 module_param(tvyposoffset
, int, 0);
6722 module_param(nocrt2rate
, int, 0);
6723 #if !defined(__i386__) && !defined(__x86_64__)
6724 module_param(resetcard
, int, 0);
6725 module_param(videoram
, int, 0);
6728 MODULE_PARM_DESC(mem
,
6729 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6730 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6731 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6732 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6733 "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6734 "The value is to be specified without 'KB'.\n");
6736 MODULE_PARM_DESC(noaccel
,
6737 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
6740 MODULE_PARM_DESC(noypan
,
6741 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
6742 "will be performed by redrawing the screen. (default: 0)\n");
6744 MODULE_PARM_DESC(nomax
,
6745 "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
6746 "memory for the virtual screen in order to optimize scrolling performance. If\n"
6747 "this is set to anything other than 0, sisfb will not do this and thereby \n"
6748 "enable the user to positively specify a virtual Y size of the screen using\n"
6749 "fbset. (default: 0)\n");
6751 MODULE_PARM_DESC(mode
,
6752 "\nSelects the desired default display mode in the format XxYxDepth,\n"
6753 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
6754 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
6755 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
6757 MODULE_PARM_DESC(vesa
,
6758 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
6759 "0x117 (default: 0x0103)\n");
6761 MODULE_PARM_DESC(rate
,
6762 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
6763 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
6764 "will be ignored (default: 60)\n");
6766 MODULE_PARM_DESC(forcecrt1
,
6767 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
6768 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
6769 "0=CRT1 OFF) (default: [autodetected])\n");
6771 MODULE_PARM_DESC(forcecrt2type
,
6772 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
6773 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
6774 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
6775 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
6776 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
6777 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
6778 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
6779 "depends on the very hardware in use. (default: [autodetected])\n");
6781 MODULE_PARM_DESC(scalelcd
,
6782 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
6783 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
6784 "show black bars around the image, TMDS panels will probably do the scaling\n"
6785 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
6787 MODULE_PARM_DESC(pdc
,
6788 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
6789 "should detect this correctly in most cases; however, sometimes this is not\n"
6790 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
6791 "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
6792 "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
6793 "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
6795 #ifdef CONFIG_FB_SIS_315
6796 MODULE_PARM_DESC(pdc1
,
6797 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
6798 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
6799 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
6800 "implemented yet.\n");
6803 MODULE_PARM_DESC(specialtiming
,
6804 "\nPlease refer to documentation for more information on this option.\n");
6806 MODULE_PARM_DESC(lvdshl
,
6807 "\nPlease refer to documentation for more information on this option.\n");
6809 MODULE_PARM_DESC(tvstandard
,
6810 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
6811 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
6813 MODULE_PARM_DESC(tvxposoffset
,
6814 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
6817 MODULE_PARM_DESC(tvyposoffset
,
6818 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
6821 MODULE_PARM_DESC(nocrt2rate
,
6822 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
6823 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
6825 #if !defined(__i386__) && !defined(__x86_64__)
6826 #ifdef CONFIG_FB_SIS_300
6827 MODULE_PARM_DESC(resetcard
,
6828 "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
6829 "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
6830 "currently). Default: 0\n");
6832 MODULE_PARM_DESC(videoram
,
6833 "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
6834 "some non-x86 architectures where the memory auto detection fails. Only\n"
6835 "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
6839 #endif /* /MODULE */
6841 /* _GPL only for new symbols. */
6842 EXPORT_SYMBOL(sis_malloc
);
6843 EXPORT_SYMBOL(sis_free
);
6844 EXPORT_SYMBOL_GPL(sis_malloc_new
);
6845 EXPORT_SYMBOL_GPL(sis_free_new
);