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>
60 #if !defined(CONFIG_FB_SIS_300) && !defined(CONFIG_FB_SIS_315)
61 #warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
62 #warning sisfb will not work!
65 static void sisfb_handle_command(struct sis_video_info
*ivideo
,
66 struct sisfb_cmd
*sisfb_command
);
68 /* ------------------ Internal helper routines ----------------- */
71 sisfb_setdefaultparms(void)
89 sisfb_specialtiming
= CUT_NONE
;
95 sisfb_tvxposoffset
= 0;
96 sisfb_tvyposoffset
= 0;
98 #if !defined(__i386__) && !defined(__x86_64__)
104 /* ------------- Parameter parsing -------------- */
106 static void sisfb_search_vesamode(unsigned int vesamode
, bool quiet
)
110 /* We don't know the hardware specs yet and there is no ivideo */
114 printk(KERN_ERR
"sisfb: Invalid mode. Using default.\n");
116 sisfb_mode_idx
= DEFAULT_MODE
;
121 vesamode
&= 0x1dff; /* Clean VESA mode number from other flags */
123 while(sisbios_mode
[i
++].mode_no
[0] != 0) {
124 if( (sisbios_mode
[i
-1].vesa_mode_no_1
== vesamode
) ||
125 (sisbios_mode
[i
-1].vesa_mode_no_2
== vesamode
) ) {
127 if(sisbios_mode
[i
-1].mode_no
[1] == 0x50 ||
128 sisbios_mode
[i
-1].mode_no
[1] == 0x56 ||
129 sisbios_mode
[i
-1].mode_no
[1] == 0x53)
132 if(sisbios_mode
[i
-1].mode_no
[1] == 0x5a ||
133 sisbios_mode
[i
-1].mode_no
[1] == 0x5b)
136 sisfb_mode_idx
= i
- 1;
142 printk(KERN_ERR
"sisfb: Invalid VESA mode 0x%x'\n", vesamode
);
145 static void sisfb_search_mode(char *name
, bool quiet
)
147 unsigned int j
= 0, xres
= 0, yres
= 0, depth
= 0, rate
= 0;
149 char strbuf
[16], strbuf1
[20];
150 char *nameptr
= name
;
152 /* We don't know the hardware specs yet and there is no ivideo */
156 printk(KERN_ERR
"sisfb: Internal error, using default mode.\n");
158 sisfb_mode_idx
= DEFAULT_MODE
;
162 if(!strncasecmp(name
, sisbios_mode
[MODE_INDEX_NONE
].name
, strlen(name
))) {
164 printk(KERN_ERR
"sisfb: Mode 'none' not supported anymore. Using default.\n");
166 sisfb_mode_idx
= DEFAULT_MODE
;
170 if(strlen(name
) <= 19) {
171 strcpy(strbuf1
, name
);
172 for(i
= 0; i
< strlen(strbuf1
); i
++) {
173 if(strbuf1
[i
] < '0' || strbuf1
[i
] > '9') strbuf1
[i
] = ' ';
176 /* This does some fuzzy mode naming detection */
177 if(sscanf(strbuf1
, "%u %u %u %u", &xres
, &yres
, &depth
, &rate
) == 4) {
178 if((rate
<= 32) || (depth
> 32)) {
179 j
= rate
; rate
= depth
; depth
= j
;
181 sprintf(strbuf
, "%ux%ux%u", xres
, yres
, depth
);
183 sisfb_parm_rate
= rate
;
184 } else if(sscanf(strbuf1
, "%u %u %u", &xres
, &yres
, &depth
) == 3) {
185 sprintf(strbuf
, "%ux%ux%u", xres
, yres
, depth
);
189 if((sscanf(strbuf1
, "%u %u", &xres
, &yres
) == 2) && (xres
!= 0)) {
190 sprintf(strbuf
, "%ux%ux8", xres
, yres
);
193 sisfb_search_vesamode(simple_strtoul(name
, NULL
, 0), quiet
);
200 while(sisbios_mode
[i
].mode_no
[0] != 0) {
201 if(!strncasecmp(nameptr
, sisbios_mode
[i
++].name
, strlen(nameptr
))) {
203 if(sisbios_mode
[i
-1].mode_no
[1] == 0x50 ||
204 sisbios_mode
[i
-1].mode_no
[1] == 0x56 ||
205 sisbios_mode
[i
-1].mode_no
[1] == 0x53)
208 if(sisbios_mode
[i
-1].mode_no
[1] == 0x5a ||
209 sisbios_mode
[i
-1].mode_no
[1] == 0x5b)
212 sisfb_mode_idx
= i
- 1;
219 printk(KERN_ERR
"sisfb: Invalid mode '%s'\n", nameptr
);
223 static void sisfb_get_vga_mode_from_kernel(void)
227 int mydepth
= screen_info
.lfb_depth
;
229 if(screen_info
.orig_video_isVGA
!= VIDEO_TYPE_VLFB
) return;
231 if( (screen_info
.lfb_width
>= 320) && (screen_info
.lfb_width
<= 2048) &&
232 (screen_info
.lfb_height
>= 200) && (screen_info
.lfb_height
<= 1536) &&
233 (mydepth
>= 8) && (mydepth
<= 32) ) {
235 if(mydepth
== 24) mydepth
= 32;
237 sprintf(mymode
, "%ux%ux%u", screen_info
.lfb_width
,
238 screen_info
.lfb_height
,
242 "sisfb: Using vga mode %s pre-set by kernel as default\n",
245 sisfb_search_mode(mymode
, true);
253 sisfb_search_crt2type(const char *name
)
257 /* We don't know the hardware specs yet and there is no ivideo */
259 if(name
== NULL
) return;
261 while(sis_crt2type
[i
].type_no
!= -1) {
262 if(!strncasecmp(name
, sis_crt2type
[i
].name
, strlen(sis_crt2type
[i
].name
))) {
263 sisfb_crt2type
= sis_crt2type
[i
].type_no
;
264 sisfb_tvplug
= sis_crt2type
[i
].tvplug_no
;
265 sisfb_crt2flags
= sis_crt2type
[i
].flags
;
271 sisfb_dstn
= (sisfb_crt2flags
& FL_550_DSTN
) ? 1 : 0;
272 sisfb_fstn
= (sisfb_crt2flags
& FL_550_FSTN
) ? 1 : 0;
274 if(sisfb_crt2type
< 0)
275 printk(KERN_ERR
"sisfb: Invalid CRT2 type: %s\n", name
);
279 sisfb_search_tvstd(const char *name
)
283 /* We don't know the hardware specs yet and there is no ivideo */
288 while(sis_tvtype
[i
].type_no
!= -1) {
289 if(!strncasecmp(name
, sis_tvtype
[i
].name
, strlen(sis_tvtype
[i
].name
))) {
290 sisfb_tvstd
= sis_tvtype
[i
].type_no
;
298 sisfb_search_specialtiming(const char *name
)
303 /* We don't know the hardware specs yet and there is no ivideo */
308 if(!strncasecmp(name
, "none", 4)) {
309 sisfb_specialtiming
= CUT_FORCENONE
;
310 printk(KERN_DEBUG
"sisfb: Special timing disabled\n");
312 while(mycustomttable
[i
].chipID
!= 0) {
313 if(!strncasecmp(name
,mycustomttable
[i
].optionName
,
314 strlen(mycustomttable
[i
].optionName
))) {
315 sisfb_specialtiming
= mycustomttable
[i
].SpecialID
;
317 printk(KERN_INFO
"sisfb: Special timing for %s %s forced (\"%s\")\n",
318 mycustomttable
[i
].vendorName
,
319 mycustomttable
[i
].cardName
,
320 mycustomttable
[i
].optionName
);
326 printk(KERN_WARNING
"sisfb: Invalid SpecialTiming parameter, valid are:");
327 printk(KERN_WARNING
"\t\"none\" (to disable special timings)\n");
329 while(mycustomttable
[i
].chipID
!= 0) {
330 printk(KERN_WARNING
"\t\"%s\" (for %s %s)\n",
331 mycustomttable
[i
].optionName
,
332 mycustomttable
[i
].vendorName
,
333 mycustomttable
[i
].cardName
);
340 /* ----------- Various detection routines ----------- */
342 static void sisfb_detect_custom_timing(struct sis_video_info
*ivideo
)
344 unsigned char *biosver
= NULL
;
345 unsigned char *biosdate
= NULL
;
350 if(ivideo
->SiS_Pr
.UseROM
) {
351 biosver
= ivideo
->SiS_Pr
.VirtualRomBase
+ 0x06;
352 biosdate
= ivideo
->SiS_Pr
.VirtualRomBase
+ 0x2c;
353 for(i
= 0; i
< 32768; i
++)
354 chksum
+= ivideo
->SiS_Pr
.VirtualRomBase
[i
];
359 if( (mycustomttable
[i
].chipID
== ivideo
->chip
) &&
360 ((!strlen(mycustomttable
[i
].biosversion
)) ||
361 (ivideo
->SiS_Pr
.UseROM
&&
362 (!strncmp(mycustomttable
[i
].biosversion
, biosver
,
363 strlen(mycustomttable
[i
].biosversion
))))) &&
364 ((!strlen(mycustomttable
[i
].biosdate
)) ||
365 (ivideo
->SiS_Pr
.UseROM
&&
366 (!strncmp(mycustomttable
[i
].biosdate
, biosdate
,
367 strlen(mycustomttable
[i
].biosdate
))))) &&
368 ((!mycustomttable
[i
].bioschksum
) ||
369 (ivideo
->SiS_Pr
.UseROM
&&
370 (mycustomttable
[i
].bioschksum
== chksum
))) &&
371 (mycustomttable
[i
].pcisubsysvendor
== ivideo
->subsysvendor
) &&
372 (mycustomttable
[i
].pcisubsyscard
== ivideo
->subsysdevice
) ) {
374 for(j
= 0; j
< 5; j
++) {
375 if(mycustomttable
[i
].biosFootprintAddr
[j
]) {
376 if(ivideo
->SiS_Pr
.UseROM
) {
377 if(ivideo
->SiS_Pr
.VirtualRomBase
[mycustomttable
[i
].biosFootprintAddr
[j
]] !=
378 mycustomttable
[i
].biosFootprintData
[j
]) {
386 ivideo
->SiS_Pr
.SiS_CustomT
= mycustomttable
[i
].SpecialID
;
387 printk(KERN_DEBUG
"sisfb: Identified [%s %s], special timing applies\n",
388 mycustomttable
[i
].vendorName
,
389 mycustomttable
[i
].cardName
);
390 printk(KERN_DEBUG
"sisfb: [specialtiming parameter name: %s]\n",
391 mycustomttable
[i
].optionName
);
396 } while(mycustomttable
[i
].chipID
);
399 static bool sisfb_interpret_edid(struct sisfb_monitor
*monitor
, u8
*buffer
)
401 int i
, j
, xres
, yres
, refresh
, index
;
404 if(buffer
[0] != 0x00 || buffer
[1] != 0xff ||
405 buffer
[2] != 0xff || buffer
[3] != 0xff ||
406 buffer
[4] != 0xff || buffer
[5] != 0xff ||
407 buffer
[6] != 0xff || buffer
[7] != 0x00) {
408 printk(KERN_DEBUG
"sisfb: Bad EDID header\n");
412 if(buffer
[0x12] != 0x01) {
413 printk(KERN_INFO
"sisfb: EDID version %d not supported\n",
418 monitor
->feature
= buffer
[0x18];
420 if(!(buffer
[0x14] & 0x80)) {
421 if(!(buffer
[0x14] & 0x08)) {
423 "sisfb: WARNING: Monitor does not support separate syncs\n");
427 if(buffer
[0x13] >= 0x01) {
428 /* EDID V1 rev 1 and 2: Search for monitor descriptor
433 if(buffer
[j
] == 0x00 && buffer
[j
+ 1] == 0x00 &&
434 buffer
[j
+ 2] == 0x00 && buffer
[j
+ 3] == 0xfd &&
435 buffer
[j
+ 4] == 0x00) {
436 monitor
->hmin
= buffer
[j
+ 7];
437 monitor
->hmax
= buffer
[j
+ 8];
438 monitor
->vmin
= buffer
[j
+ 5];
439 monitor
->vmax
= buffer
[j
+ 6];
440 monitor
->dclockmax
= buffer
[j
+ 9] * 10 * 1000;
441 monitor
->datavalid
= true;
448 if(!monitor
->datavalid
) {
449 /* Otherwise: Get a range from the list of supported
450 * Estabished Timings. This is not entirely accurate,
451 * because fixed frequency monitors are not supported
454 monitor
->hmin
= 65535; monitor
->hmax
= 0;
455 monitor
->vmin
= 65535; monitor
->vmax
= 0;
456 monitor
->dclockmax
= 0;
457 emodes
= buffer
[0x23] | (buffer
[0x24] << 8) | (buffer
[0x25] << 16);
458 for(i
= 0; i
< 13; i
++) {
459 if(emodes
& sisfb_ddcsmodes
[i
].mask
) {
460 if(monitor
->hmin
> sisfb_ddcsmodes
[i
].h
) monitor
->hmin
= sisfb_ddcsmodes
[i
].h
;
461 if(monitor
->hmax
< sisfb_ddcsmodes
[i
].h
) monitor
->hmax
= sisfb_ddcsmodes
[i
].h
+ 1;
462 if(monitor
->vmin
> sisfb_ddcsmodes
[i
].v
) monitor
->vmin
= sisfb_ddcsmodes
[i
].v
;
463 if(monitor
->vmax
< sisfb_ddcsmodes
[i
].v
) monitor
->vmax
= sisfb_ddcsmodes
[i
].v
;
464 if(monitor
->dclockmax
< sisfb_ddcsmodes
[i
].d
) monitor
->dclockmax
= sisfb_ddcsmodes
[i
].d
;
468 for(i
= 0; i
< 8; i
++) {
469 xres
= (buffer
[index
] + 31) * 8;
470 switch(buffer
[index
+ 1] & 0xc0) {
471 case 0xc0: yres
= (xres
* 9) / 16; break;
472 case 0x80: yres
= (xres
* 4) / 5; break;
473 case 0x40: yres
= (xres
* 3) / 4; break;
474 default: yres
= xres
; break;
476 refresh
= (buffer
[index
+ 1] & 0x3f) + 60;
477 if((xres
>= 640) && (yres
>= 480)) {
478 for(j
= 0; j
< 8; j
++) {
479 if((xres
== sisfb_ddcfmodes
[j
].x
) &&
480 (yres
== sisfb_ddcfmodes
[j
].y
) &&
481 (refresh
== sisfb_ddcfmodes
[j
].v
)) {
482 if(monitor
->hmin
> sisfb_ddcfmodes
[j
].h
) monitor
->hmin
= sisfb_ddcfmodes
[j
].h
;
483 if(monitor
->hmax
< sisfb_ddcfmodes
[j
].h
) monitor
->hmax
= sisfb_ddcfmodes
[j
].h
+ 1;
484 if(monitor
->vmin
> sisfb_ddcsmodes
[j
].v
) monitor
->vmin
= sisfb_ddcsmodes
[j
].v
;
485 if(monitor
->vmax
< sisfb_ddcsmodes
[j
].v
) monitor
->vmax
= sisfb_ddcsmodes
[j
].v
;
486 if(monitor
->dclockmax
< sisfb_ddcsmodes
[j
].d
) monitor
->dclockmax
= sisfb_ddcsmodes
[j
].d
;
492 if((monitor
->hmin
<= monitor
->hmax
) && (monitor
->vmin
<= monitor
->vmax
)) {
493 monitor
->datavalid
= true;
497 return monitor
->datavalid
;
500 static void sisfb_handle_ddc(struct sis_video_info
*ivideo
,
501 struct sisfb_monitor
*monitor
, int crtno
)
503 unsigned short temp
, i
, realcrtno
= crtno
;
504 unsigned char buffer
[256];
506 monitor
->datavalid
= false;
509 if(ivideo
->vbflags
& CRT2_LCD
) realcrtno
= 1;
510 else if(ivideo
->vbflags
& CRT2_VGA
) realcrtno
= 2;
514 if((ivideo
->sisfb_crt1off
) && (!crtno
))
517 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
518 realcrtno
, 0, &buffer
[0], ivideo
->vbflags2
);
519 if((!temp
) || (temp
== 0xffff)) {
520 printk(KERN_INFO
"sisfb: CRT%d DDC probing failed\n", crtno
+ 1);
523 printk(KERN_INFO
"sisfb: CRT%d DDC supported\n", crtno
+ 1);
524 printk(KERN_INFO
"sisfb: CRT%d DDC level: %s%s%s%s\n",
526 (temp
& 0x1a) ? "" : "[none of the supported]",
527 (temp
& 0x02) ? "2 " : "",
528 (temp
& 0x08) ? "D&P" : "",
529 (temp
& 0x10) ? "FPDI-2" : "");
531 i
= 3; /* Number of retrys */
533 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
534 realcrtno
, 1, &buffer
[0], ivideo
->vbflags2
);
535 } while((temp
) && i
--);
537 if(sisfb_interpret_edid(monitor
, &buffer
[0])) {
538 printk(KERN_INFO
"sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
539 monitor
->hmin
, monitor
->hmax
, monitor
->vmin
, monitor
->vmax
,
540 monitor
->dclockmax
/ 1000);
542 printk(KERN_INFO
"sisfb: CRT%d DDC EDID corrupt\n", crtno
+ 1);
545 printk(KERN_INFO
"sisfb: CRT%d DDC reading failed\n", crtno
+ 1);
548 printk(KERN_INFO
"sisfb: VESA D&P and FPDI-2 not supported yet\n");
553 /* -------------- Mode validation --------------- */
556 sisfb_verify_rate(struct sis_video_info
*ivideo
, struct sisfb_monitor
*monitor
,
557 int mode_idx
, int rate_idx
, int rate
)
560 unsigned int dclock
, hsync
;
562 if(!monitor
->datavalid
)
568 /* Skip for 320x200, 320x240, 640x400 */
569 switch(sisbios_mode
[mode_idx
].mode_no
[ivideo
->mni
]) {
580 #ifdef CONFIG_FB_SIS_315
583 if(ivideo
->sisvga_engine
== SIS_315_VGA
) return true;
587 if(rate
< (monitor
->vmin
- 1))
589 if(rate
> (monitor
->vmax
+ 1))
592 if(sisfb_gettotalfrommode(&ivideo
->SiS_Pr
,
593 sisbios_mode
[mode_idx
].mode_no
[ivideo
->mni
],
594 &htotal
, &vtotal
, rate_idx
)) {
595 dclock
= (htotal
* vtotal
* rate
) / 1000;
596 if(dclock
> (monitor
->dclockmax
+ 1000))
598 hsync
= dclock
/ htotal
;
599 if(hsync
< (monitor
->hmin
- 1))
601 if(hsync
> (monitor
->hmax
+ 1))
610 sisfb_validate_mode(struct sis_video_info
*ivideo
, int myindex
, u32 vbflags
)
612 u16 xres
=0, yres
, myres
;
614 #ifdef CONFIG_FB_SIS_300
615 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
616 if(!(sisbios_mode
[myindex
].chipset
& MD_SIS300
))
620 #ifdef CONFIG_FB_SIS_315
621 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
622 if(!(sisbios_mode
[myindex
].chipset
& MD_SIS315
))
627 myres
= sisbios_mode
[myindex
].yres
;
629 switch(vbflags
& VB_DISPTYPE_DISP2
) {
632 xres
= ivideo
->lcdxres
; yres
= ivideo
->lcdyres
;
634 if((ivideo
->SiS_Pr
.SiS_CustomT
!= CUT_PANEL848
) &&
635 (ivideo
->SiS_Pr
.SiS_CustomT
!= CUT_PANEL856
)) {
636 if(sisbios_mode
[myindex
].xres
> xres
)
642 if(ivideo
->sisfb_fstn
) {
643 if(sisbios_mode
[myindex
].xres
== 320) {
645 switch(sisbios_mode
[myindex
].mode_no
[1]) {
646 case 0x50: myindex
= MODE_FSTN_8
; break;
647 case 0x56: myindex
= MODE_FSTN_16
; break;
648 case 0x53: return -1;
654 if(SiS_GetModeID_LCD(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
655 sisbios_mode
[myindex
].yres
, 0, ivideo
->sisfb_fstn
,
656 ivideo
->SiS_Pr
.SiS_CustomT
, xres
, yres
, ivideo
->vbflags2
) < 0x14) {
662 if(SiS_GetModeID_TV(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
663 sisbios_mode
[myindex
].yres
, 0, ivideo
->vbflags2
) < 0x14) {
669 if(SiS_GetModeID_VGA2(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
670 sisbios_mode
[myindex
].yres
, 0, ivideo
->vbflags2
) < 0x14) {
680 sisfb_search_refresh_rate(struct sis_video_info
*ivideo
, unsigned int rate
, int mode_idx
)
683 u16 xres
= sisbios_mode
[mode_idx
].xres
;
684 u16 yres
= sisbios_mode
[mode_idx
].yres
;
686 ivideo
->rate_idx
= 0;
687 while((sisfb_vrate
[i
].idx
!= 0) && (sisfb_vrate
[i
].xres
<= xres
)) {
688 if((sisfb_vrate
[i
].xres
== xres
) && (sisfb_vrate
[i
].yres
== yres
)) {
689 if(sisfb_vrate
[i
].refresh
== rate
) {
690 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
692 } else if(sisfb_vrate
[i
].refresh
> rate
) {
693 if((sisfb_vrate
[i
].refresh
- rate
) <= 3) {
694 DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
695 rate
, sisfb_vrate
[i
].refresh
);
696 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
697 ivideo
->refresh_rate
= sisfb_vrate
[i
].refresh
;
698 } else if((sisfb_vrate
[i
].idx
!= 1) &&
699 ((rate
- sisfb_vrate
[i
-1].refresh
) <= 2)) {
700 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
701 rate
, sisfb_vrate
[i
-1].refresh
);
702 ivideo
->rate_idx
= sisfb_vrate
[i
-1].idx
;
703 ivideo
->refresh_rate
= sisfb_vrate
[i
-1].refresh
;
706 } else if((rate
- sisfb_vrate
[i
].refresh
) <= 2) {
707 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
708 rate
, sisfb_vrate
[i
].refresh
);
709 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
715 if(ivideo
->rate_idx
> 0) {
716 return ivideo
->rate_idx
;
718 printk(KERN_INFO
"sisfb: Unsupported rate %d for %dx%d\n",
725 sisfb_bridgeisslave(struct sis_video_info
*ivideo
)
729 if(!(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
))
732 P1_00
= SiS_GetReg(SISPART1
, 0x00);
733 if( ((ivideo
->sisvga_engine
== SIS_300_VGA
) && (P1_00
& 0xa0) == 0x20) ||
734 ((ivideo
->sisvga_engine
== SIS_315_VGA
) && (P1_00
& 0x50) == 0x10) ) {
742 sisfballowretracecrt1(struct sis_video_info
*ivideo
)
746 temp
= SiS_GetReg(SISCR
, 0x17);
750 temp
= SiS_GetReg(SISSR
, 0x1f);
758 sisfbcheckvretracecrt1(struct sis_video_info
*ivideo
)
760 if(!sisfballowretracecrt1(ivideo
))
763 if (SiS_GetRegByte(SISINPSTAT
) & 0x08)
770 sisfbwaitretracecrt1(struct sis_video_info
*ivideo
)
774 if(!sisfballowretracecrt1(ivideo
))
778 while ((!(SiS_GetRegByte(SISINPSTAT
) & 0x08)) && --watchdog
);
780 while ((SiS_GetRegByte(SISINPSTAT
) & 0x08) && --watchdog
);
784 sisfbcheckvretracecrt2(struct sis_video_info
*ivideo
)
786 unsigned char temp
, reg
;
788 switch(ivideo
->sisvga_engine
) {
789 case SIS_300_VGA
: reg
= 0x25; break;
790 case SIS_315_VGA
: reg
= 0x30; break;
791 default: return false;
794 temp
= SiS_GetReg(SISPART1
, reg
);
802 sisfb_CheckVBRetrace(struct sis_video_info
*ivideo
)
804 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
805 if(!sisfb_bridgeisslave(ivideo
)) {
806 return sisfbcheckvretracecrt2(ivideo
);
809 return sisfbcheckvretracecrt1(ivideo
);
813 sisfb_setupvbblankflags(struct sis_video_info
*ivideo
, u32
*vcount
, u32
*hcount
)
815 u8 idx
, reg1
, reg2
, reg3
, reg4
;
818 (*vcount
) = (*hcount
) = 0;
820 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) && (!(sisfb_bridgeisslave(ivideo
)))) {
822 ret
|= (FB_VBLANK_HAVE_VSYNC
|
823 FB_VBLANK_HAVE_HBLANK
|
824 FB_VBLANK_HAVE_VBLANK
|
825 FB_VBLANK_HAVE_VCOUNT
|
826 FB_VBLANK_HAVE_HCOUNT
);
827 switch(ivideo
->sisvga_engine
) {
828 case SIS_300_VGA
: idx
= 0x25; break;
830 case SIS_315_VGA
: idx
= 0x30; break;
832 reg1
= SiS_GetReg(SISPART1
, (idx
+0)); /* 30 */
833 reg2
= SiS_GetReg(SISPART1
, (idx
+1)); /* 31 */
834 reg3
= SiS_GetReg(SISPART1
, (idx
+2)); /* 32 */
835 reg4
= SiS_GetReg(SISPART1
, (idx
+3)); /* 33 */
836 if(reg1
& 0x01) ret
|= FB_VBLANK_VBLANKING
;
837 if(reg1
& 0x02) ret
|= FB_VBLANK_VSYNCING
;
838 if(reg4
& 0x80) ret
|= FB_VBLANK_HBLANKING
;
839 (*vcount
) = reg3
| ((reg4
& 0x70) << 4);
840 (*hcount
) = reg2
| ((reg4
& 0x0f) << 8);
842 } else if(sisfballowretracecrt1(ivideo
)) {
844 ret
|= (FB_VBLANK_HAVE_VSYNC
|
845 FB_VBLANK_HAVE_VBLANK
|
846 FB_VBLANK_HAVE_VCOUNT
|
847 FB_VBLANK_HAVE_HCOUNT
);
848 reg1
= SiS_GetRegByte(SISINPSTAT
);
849 if(reg1
& 0x08) ret
|= FB_VBLANK_VSYNCING
;
850 if(reg1
& 0x01) ret
|= FB_VBLANK_VBLANKING
;
851 reg1
= SiS_GetReg(SISCR
, 0x20);
852 reg1
= SiS_GetReg(SISCR
, 0x1b);
853 reg2
= SiS_GetReg(SISCR
, 0x1c);
854 reg3
= SiS_GetReg(SISCR
, 0x1d);
855 (*vcount
) = reg2
| ((reg3
& 0x07) << 8);
856 (*hcount
) = (reg1
| ((reg3
& 0x10) << 4)) << 3;
863 sisfb_myblank(struct sis_video_info
*ivideo
, int blank
)
865 u8 sr01
, sr11
, sr1f
, cr63
=0, p2_0
, p1_13
;
866 bool backlight
= true;
869 case FB_BLANK_UNBLANK
: /* on */
878 case FB_BLANK_NORMAL
: /* blank */
887 case FB_BLANK_VSYNC_SUSPEND
: /* no vsync */
896 case FB_BLANK_HSYNC_SUSPEND
: /* no hsync */
905 case FB_BLANK_POWERDOWN
: /* off */
918 if(ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
) {
920 if( (!ivideo
->sisfb_thismonitor
.datavalid
) ||
921 ((ivideo
->sisfb_thismonitor
.datavalid
) &&
922 (ivideo
->sisfb_thismonitor
.feature
& 0xe0))) {
924 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
925 SiS_SetRegANDOR(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, 0xbf, cr63
);
928 if(!(sisfb_bridgeisslave(ivideo
))) {
929 SiS_SetRegANDOR(SISSR
, 0x01, ~0x20, sr01
);
930 SiS_SetRegANDOR(SISSR
, 0x1f, 0x3f, sr1f
);
936 if(ivideo
->currentvbflags
& CRT2_LCD
) {
938 if(ivideo
->vbflags2
& VB2_SISLVDSBRIDGE
) {
940 SiS_SiS30xBLOn(&ivideo
->SiS_Pr
);
942 SiS_SiS30xBLOff(&ivideo
->SiS_Pr
);
944 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
945 #ifdef CONFIG_FB_SIS_315
946 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
948 SiS_Chrontel701xBLOn(&ivideo
->SiS_Pr
);
950 SiS_Chrontel701xBLOff(&ivideo
->SiS_Pr
);
956 if(((ivideo
->sisvga_engine
== SIS_300_VGA
) &&
957 (ivideo
->vbflags2
& (VB2_301
|VB2_30xBDH
|VB2_LVDS
))) ||
958 ((ivideo
->sisvga_engine
== SIS_315_VGA
) &&
959 ((ivideo
->vbflags2
& (VB2_LVDS
| VB2_CHRONTEL
)) == VB2_LVDS
))) {
960 SiS_SetRegANDOR(SISSR
, 0x11, ~0x0c, sr11
);
963 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
964 if((ivideo
->vbflags2
& VB2_30xB
) &&
965 (!(ivideo
->vbflags2
& VB2_30xBDH
))) {
966 SiS_SetRegANDOR(SISPART1
, 0x13, 0x3f, p1_13
);
968 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
969 if((ivideo
->vbflags2
& VB2_30xB
) &&
970 (!(ivideo
->vbflags2
& VB2_30xBDH
))) {
971 SiS_SetRegANDOR(SISPART2
, 0x00, 0x1f, p2_0
);
975 } else if(ivideo
->currentvbflags
& CRT2_VGA
) {
977 if(ivideo
->vbflags2
& VB2_30xB
) {
978 SiS_SetRegANDOR(SISPART2
, 0x00, 0x1f, p2_0
);
986 /* ------------- Callbacks from init.c/init301.c -------------- */
988 #ifdef CONFIG_FB_SIS_300
990 sisfb_read_nbridge_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
)
992 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
995 pci_read_config_dword(ivideo
->nbridge
, reg
, &val
);
996 return (unsigned int)val
;
1000 sisfb_write_nbridge_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
, unsigned int val
)
1002 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1004 pci_write_config_dword(ivideo
->nbridge
, reg
, (u32
)val
);
1008 sisfb_read_lpc_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
)
1010 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1013 if(!ivideo
->lpcdev
) return 0;
1015 pci_read_config_dword(ivideo
->lpcdev
, reg
, &val
);
1016 return (unsigned int)val
;
1020 #ifdef CONFIG_FB_SIS_315
1022 sisfb_write_nbridge_pci_byte(struct SiS_Private
*SiS_Pr
, int reg
, unsigned char val
)
1024 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1026 pci_write_config_byte(ivideo
->nbridge
, reg
, (u8
)val
);
1030 sisfb_read_mio_pci_word(struct SiS_Private
*SiS_Pr
, int reg
)
1032 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1035 if(!ivideo
->lpcdev
) return 0;
1037 pci_read_config_word(ivideo
->lpcdev
, reg
, &val
);
1038 return (unsigned int)val
;
1042 /* ----------- FBDev related routines for all series ----------- */
1045 sisfb_get_cmap_len(const struct fb_var_screeninfo
*var
)
1047 return (var
->bits_per_pixel
== 8) ? 256 : 16;
1051 sisfb_set_vparms(struct sis_video_info
*ivideo
)
1053 switch(ivideo
->video_bpp
) {
1055 ivideo
->DstColor
= 0x0000;
1056 ivideo
->SiS310_AccelDepth
= 0x00000000;
1057 ivideo
->video_cmap_len
= 256;
1060 ivideo
->DstColor
= 0x8000;
1061 ivideo
->SiS310_AccelDepth
= 0x00010000;
1062 ivideo
->video_cmap_len
= 16;
1065 ivideo
->DstColor
= 0xC000;
1066 ivideo
->SiS310_AccelDepth
= 0x00020000;
1067 ivideo
->video_cmap_len
= 16;
1070 ivideo
->video_cmap_len
= 16;
1071 printk(KERN_ERR
"sisfb: Unsupported depth %d", ivideo
->video_bpp
);
1077 sisfb_calc_maxyres(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1079 int maxyres
= ivideo
->sisfb_mem
/ (var
->xres_virtual
* (var
->bits_per_pixel
>> 3));
1081 if(maxyres
> 32767) maxyres
= 32767;
1087 sisfb_calc_pitch(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1089 ivideo
->video_linelength
= var
->xres_virtual
* (var
->bits_per_pixel
>> 3);
1090 ivideo
->scrnpitchCRT1
= ivideo
->video_linelength
;
1091 if(!(ivideo
->currentvbflags
& CRT1_LCDA
)) {
1092 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1093 ivideo
->scrnpitchCRT1
<<= 1;
1099 sisfb_set_pitch(struct sis_video_info
*ivideo
)
1101 bool isslavemode
= false;
1102 unsigned short HDisplay1
= ivideo
->scrnpitchCRT1
>> 3;
1103 unsigned short HDisplay2
= ivideo
->video_linelength
>> 3;
1105 if(sisfb_bridgeisslave(ivideo
)) isslavemode
= true;
1107 /* We need to set pitch for CRT1 if bridge is in slave mode, too */
1108 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP1
) || (isslavemode
)) {
1109 SiS_SetReg(SISCR
, 0x13, (HDisplay1
& 0xFF));
1110 SiS_SetRegANDOR(SISSR
, 0x0E, 0xF0, (HDisplay1
>> 8));
1113 /* We must not set the pitch for CRT2 if bridge is in slave mode */
1114 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) && (!isslavemode
)) {
1115 SiS_SetRegOR(SISPART1
, ivideo
->CRT2_write_enable
, 0x01);
1116 SiS_SetReg(SISPART1
, 0x07, (HDisplay2
& 0xFF));
1117 SiS_SetRegANDOR(SISPART1
, 0x09, 0xF0, (HDisplay2
>> 8));
1122 sisfb_bpp_to_var(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1124 ivideo
->video_cmap_len
= sisfb_get_cmap_len(var
);
1126 switch(var
->bits_per_pixel
) {
1128 var
->red
.offset
= var
->green
.offset
= var
->blue
.offset
= 0;
1129 var
->red
.length
= var
->green
.length
= var
->blue
.length
= 8;
1132 var
->red
.offset
= 11;
1133 var
->red
.length
= 5;
1134 var
->green
.offset
= 5;
1135 var
->green
.length
= 6;
1136 var
->blue
.offset
= 0;
1137 var
->blue
.length
= 5;
1138 var
->transp
.offset
= 0;
1139 var
->transp
.length
= 0;
1142 var
->red
.offset
= 16;
1143 var
->red
.length
= 8;
1144 var
->green
.offset
= 8;
1145 var
->green
.length
= 8;
1146 var
->blue
.offset
= 0;
1147 var
->blue
.length
= 8;
1148 var
->transp
.offset
= 24;
1149 var
->transp
.length
= 8;
1155 sisfb_set_mode(struct sis_video_info
*ivideo
, int clrscrn
)
1157 unsigned short modeno
= ivideo
->mode_no
;
1159 /* >=2.6.12's fbcon clears the screen anyway */
1162 SiS_SetReg(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1164 sisfb_pre_setmode(ivideo
);
1166 if(!SiSSetMode(&ivideo
->SiS_Pr
, modeno
)) {
1167 printk(KERN_ERR
"sisfb: Setting mode[0x%x] failed\n", ivideo
->mode_no
);
1171 SiS_SetReg(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1173 sisfb_post_setmode(ivideo
);
1180 sisfb_do_set_var(struct fb_var_screeninfo
*var
, int isactive
, struct fb_info
*info
)
1182 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1183 unsigned int htotal
= 0, vtotal
= 0;
1184 unsigned int drate
= 0, hrate
= 0;
1185 int found_mode
= 0, ret
;
1189 htotal
= var
->left_margin
+ var
->xres
+ var
->right_margin
+ var
->hsync_len
;
1191 vtotal
= var
->upper_margin
+ var
->lower_margin
+ var
->vsync_len
;
1193 pixclock
= var
->pixclock
;
1195 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
) {
1196 vtotal
+= var
->yres
;
1198 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1199 vtotal
+= var
->yres
;
1201 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1202 vtotal
+= var
->yres
;
1204 } else vtotal
+= var
->yres
;
1206 if(!(htotal
) || !(vtotal
)) {
1207 DPRINTK("sisfb: Invalid 'var' information\n");
1211 if(pixclock
&& htotal
&& vtotal
) {
1212 drate
= 1000000000 / pixclock
;
1213 hrate
= (drate
* 1000) / htotal
;
1214 ivideo
->refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1216 ivideo
->refresh_rate
= 60;
1219 old_mode
= ivideo
->sisfb_mode_idx
;
1220 ivideo
->sisfb_mode_idx
= 0;
1222 while( (sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[0] != 0) &&
1223 (sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
<= var
->xres
) ) {
1224 if( (sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
== var
->xres
) &&
1225 (sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
== var
->yres
) &&
1226 (sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
== var
->bits_per_pixel
)) {
1227 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
1231 ivideo
->sisfb_mode_idx
++;
1235 ivideo
->sisfb_mode_idx
= sisfb_validate_mode(ivideo
,
1236 ivideo
->sisfb_mode_idx
, ivideo
->currentvbflags
);
1238 ivideo
->sisfb_mode_idx
= -1;
1241 if(ivideo
->sisfb_mode_idx
< 0) {
1242 printk(KERN_ERR
"sisfb: Mode %dx%dx%d not supported\n", var
->xres
,
1243 var
->yres
, var
->bits_per_pixel
);
1244 ivideo
->sisfb_mode_idx
= old_mode
;
1248 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
1250 if(sisfb_search_refresh_rate(ivideo
, ivideo
->refresh_rate
, ivideo
->sisfb_mode_idx
) == 0) {
1251 ivideo
->rate_idx
= sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
;
1252 ivideo
->refresh_rate
= 60;
1256 /* If acceleration to be used? Need to know
1257 * before pre/post_set_mode()
1260 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
1261 #ifdef STUPID_ACCELF_TEXT_SHIT
1262 if(var
->accel_flags
& FB_ACCELF_TEXT
) {
1263 info
->flags
&= ~FBINFO_HWACCEL_DISABLED
;
1265 info
->flags
|= FBINFO_HWACCEL_DISABLED
;
1268 if(!(info
->flags
& FBINFO_HWACCEL_DISABLED
)) ivideo
->accel
= -1;
1270 if(var
->accel_flags
& FB_ACCELF_TEXT
) ivideo
->accel
= -1;
1273 if((ret
= sisfb_set_mode(ivideo
, 1))) {
1277 ivideo
->video_bpp
= sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
;
1278 ivideo
->video_width
= sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
;
1279 ivideo
->video_height
= sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
;
1281 sisfb_calc_pitch(ivideo
, var
);
1282 sisfb_set_pitch(ivideo
);
1284 sisfb_set_vparms(ivideo
);
1286 ivideo
->current_width
= ivideo
->video_width
;
1287 ivideo
->current_height
= ivideo
->video_height
;
1288 ivideo
->current_bpp
= ivideo
->video_bpp
;
1289 ivideo
->current_htotal
= htotal
;
1290 ivideo
->current_vtotal
= vtotal
;
1291 ivideo
->current_linelength
= ivideo
->video_linelength
;
1292 ivideo
->current_pixclock
= var
->pixclock
;
1293 ivideo
->current_refresh_rate
= ivideo
->refresh_rate
;
1294 ivideo
->sisfb_lastrates
[ivideo
->mode_no
] = ivideo
->refresh_rate
;
1301 sisfb_set_base_CRT1(struct sis_video_info
*ivideo
, unsigned int base
)
1303 SiS_SetReg(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1305 SiS_SetReg(SISCR
, 0x0D, base
& 0xFF);
1306 SiS_SetReg(SISCR
, 0x0C, (base
>> 8) & 0xFF);
1307 SiS_SetReg(SISSR
, 0x0D, (base
>> 16) & 0xFF);
1308 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
1309 SiS_SetRegANDOR(SISSR
, 0x37, 0xFE, (base
>> 24) & 0x01);
1314 sisfb_set_base_CRT2(struct sis_video_info
*ivideo
, unsigned int base
)
1316 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
1317 SiS_SetRegOR(SISPART1
, ivideo
->CRT2_write_enable
, 0x01);
1318 SiS_SetReg(SISPART1
, 0x06, (base
& 0xFF));
1319 SiS_SetReg(SISPART1
, 0x05, ((base
>> 8) & 0xFF));
1320 SiS_SetReg(SISPART1
, 0x04, ((base
>> 16) & 0xFF));
1321 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
1322 SiS_SetRegANDOR(SISPART1
, 0x02, 0x7F, ((base
>> 24) & 0x01) << 7);
1328 sisfb_pan_var(struct sis_video_info
*ivideo
, struct fb_info
*info
,
1329 struct fb_var_screeninfo
*var
)
1331 ivideo
->current_base
= var
->yoffset
* info
->var
.xres_virtual
1334 /* calculate base bpp dep. */
1335 switch (info
->var
.bits_per_pixel
) {
1339 ivideo
->current_base
>>= 1;
1343 ivideo
->current_base
>>= 2;
1347 ivideo
->current_base
+= (ivideo
->video_offset
>> 2);
1349 sisfb_set_base_CRT1(ivideo
, ivideo
->current_base
);
1350 sisfb_set_base_CRT2(ivideo
, ivideo
->current_base
);
1356 sisfb_open(struct fb_info
*info
, int user
)
1362 sisfb_release(struct fb_info
*info
, int user
)
1368 sisfb_setcolreg(unsigned regno
, unsigned red
, unsigned green
, unsigned blue
,
1369 unsigned transp
, struct fb_info
*info
)
1371 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1373 if(regno
>= sisfb_get_cmap_len(&info
->var
))
1376 switch(info
->var
.bits_per_pixel
) {
1378 SiS_SetRegByte(SISDACA
, regno
);
1379 SiS_SetRegByte(SISDACD
, (red
>> 10));
1380 SiS_SetRegByte(SISDACD
, (green
>> 10));
1381 SiS_SetRegByte(SISDACD
, (blue
>> 10));
1382 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
1383 SiS_SetRegByte(SISDAC2A
, regno
);
1384 SiS_SetRegByte(SISDAC2D
, (red
>> 8));
1385 SiS_SetRegByte(SISDAC2D
, (green
>> 8));
1386 SiS_SetRegByte(SISDAC2D
, (blue
>> 8));
1393 ((u32
*)(info
->pseudo_palette
))[regno
] =
1395 ((green
& 0xfc00) >> 5) |
1396 ((blue
& 0xf800) >> 11);
1405 ((u32
*)(info
->pseudo_palette
))[regno
] =
1406 (red
<< 16) | (green
<< 8) | (blue
);
1413 sisfb_set_par(struct fb_info
*info
)
1417 if((err
= sisfb_do_set_var(&info
->var
, 1, info
)))
1420 sisfb_get_fix(&info
->fix
, -1, info
);
1426 sisfb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
1428 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1429 unsigned int htotal
= 0, vtotal
= 0, myrateindex
= 0;
1430 unsigned int drate
= 0, hrate
= 0, maxyres
;
1432 int refresh_rate
, search_idx
, tidx
;
1433 bool recalc_clock
= false;
1436 htotal
= var
->left_margin
+ var
->xres
+ var
->right_margin
+ var
->hsync_len
;
1438 vtotal
= var
->upper_margin
+ var
->lower_margin
+ var
->vsync_len
;
1440 pixclock
= var
->pixclock
;
1442 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
) {
1443 vtotal
+= var
->yres
;
1445 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1446 vtotal
+= var
->yres
;
1448 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1449 vtotal
+= var
->yres
;
1452 vtotal
+= var
->yres
;
1454 if(!(htotal
) || !(vtotal
)) {
1455 SISFAIL("sisfb: no valid timing data");
1459 while( (sisbios_mode
[search_idx
].mode_no
[0] != 0) &&
1460 (sisbios_mode
[search_idx
].xres
<= var
->xres
) ) {
1461 if( (sisbios_mode
[search_idx
].xres
== var
->xres
) &&
1462 (sisbios_mode
[search_idx
].yres
== var
->yres
) &&
1463 (sisbios_mode
[search_idx
].bpp
== var
->bits_per_pixel
)) {
1464 if((tidx
= sisfb_validate_mode(ivideo
, search_idx
,
1465 ivideo
->currentvbflags
)) > 0) {
1476 while(sisbios_mode
[search_idx
].mode_no
[0] != 0) {
1477 if( (var
->xres
<= sisbios_mode
[search_idx
].xres
) &&
1478 (var
->yres
<= sisbios_mode
[search_idx
].yres
) &&
1479 (var
->bits_per_pixel
== sisbios_mode
[search_idx
].bpp
) ) {
1480 if((tidx
= sisfb_validate_mode(ivideo
,search_idx
,
1481 ivideo
->currentvbflags
)) > 0) {
1491 "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
1492 var
->xres
, var
->yres
, var
->bits_per_pixel
,
1493 sisbios_mode
[search_idx
].xres
,
1494 sisbios_mode
[search_idx
].yres
,
1495 var
->bits_per_pixel
);
1496 var
->xres
= sisbios_mode
[search_idx
].xres
;
1497 var
->yres
= sisbios_mode
[search_idx
].yres
;
1500 "sisfb: Failed to find supported mode near %dx%dx%d\n",
1501 var
->xres
, var
->yres
, var
->bits_per_pixel
);
1506 if( ((ivideo
->vbflags2
& VB2_LVDS
) ||
1507 ((ivideo
->vbflags2
& VB2_30xBDH
) && (ivideo
->currentvbflags
& CRT2_LCD
))) &&
1508 (var
->bits_per_pixel
== 8) ) {
1509 /* Slave modes on LVDS and 301B-DH */
1511 recalc_clock
= true;
1512 } else if( (ivideo
->current_htotal
== htotal
) &&
1513 (ivideo
->current_vtotal
== vtotal
) &&
1514 (ivideo
->current_pixclock
== pixclock
) ) {
1515 /* x=x & y=y & c=c -> assume depth change */
1516 drate
= 1000000000 / pixclock
;
1517 hrate
= (drate
* 1000) / htotal
;
1518 refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1519 } else if( ( (ivideo
->current_htotal
!= htotal
) ||
1520 (ivideo
->current_vtotal
!= vtotal
) ) &&
1521 (ivideo
->current_pixclock
== var
->pixclock
) ) {
1522 /* x!=x | y!=y & c=c -> invalid pixclock */
1523 if(ivideo
->sisfb_lastrates
[sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
]]) {
1525 ivideo
->sisfb_lastrates
[sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
]];
1526 } else if(ivideo
->sisfb_parm_rate
!= -1) {
1527 /* Sic, sisfb_parm_rate - want to know originally desired rate here */
1528 refresh_rate
= ivideo
->sisfb_parm_rate
;
1532 recalc_clock
= true;
1533 } else if((pixclock
) && (htotal
) && (vtotal
)) {
1534 drate
= 1000000000 / pixclock
;
1535 hrate
= (drate
* 1000) / htotal
;
1536 refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1537 } else if(ivideo
->current_refresh_rate
) {
1538 refresh_rate
= ivideo
->current_refresh_rate
;
1539 recalc_clock
= true;
1542 recalc_clock
= true;
1545 myrateindex
= sisfb_search_refresh_rate(ivideo
, refresh_rate
, search_idx
);
1547 /* Eventually recalculate timing and clock */
1549 if(!myrateindex
) myrateindex
= sisbios_mode
[search_idx
].rate_idx
;
1550 var
->pixclock
= (u32
) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo
->SiS_Pr
,
1551 sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
],
1553 sisfb_mode_rate_to_ddata(&ivideo
->SiS_Pr
,
1554 sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
],
1556 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1557 var
->pixclock
<<= 1;
1561 if(ivideo
->sisfb_thismonitor
.datavalid
) {
1562 if(!sisfb_verify_rate(ivideo
, &ivideo
->sisfb_thismonitor
, search_idx
,
1563 myrateindex
, refresh_rate
)) {
1565 "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1569 /* Adapt RGB settings */
1570 sisfb_bpp_to_var(ivideo
, var
);
1572 if(var
->xres
> var
->xres_virtual
)
1573 var
->xres_virtual
= var
->xres
;
1575 if(ivideo
->sisfb_ypan
) {
1576 maxyres
= sisfb_calc_maxyres(ivideo
, var
);
1577 if(ivideo
->sisfb_max
) {
1578 var
->yres_virtual
= maxyres
;
1580 if(var
->yres_virtual
> maxyres
) {
1581 var
->yres_virtual
= maxyres
;
1584 if(var
->yres_virtual
<= var
->yres
) {
1585 var
->yres_virtual
= var
->yres
;
1588 if(var
->yres
!= var
->yres_virtual
) {
1589 var
->yres_virtual
= var
->yres
;
1595 /* Truncate offsets to maximum if too high */
1596 if(var
->xoffset
> var
->xres_virtual
- var
->xres
) {
1597 var
->xoffset
= var
->xres_virtual
- var
->xres
- 1;
1600 if(var
->yoffset
> var
->yres_virtual
- var
->yres
) {
1601 var
->yoffset
= var
->yres_virtual
- var
->yres
- 1;
1604 /* Set everything else to 0 */
1605 var
->red
.msb_right
=
1606 var
->green
.msb_right
=
1607 var
->blue
.msb_right
=
1608 var
->transp
.offset
=
1609 var
->transp
.length
=
1610 var
->transp
.msb_right
= 0;
1616 sisfb_pan_display(struct fb_var_screeninfo
*var
, struct fb_info
* info
)
1618 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1621 if (var
->vmode
& FB_VMODE_YWRAP
)
1624 if (var
->xoffset
+ info
->var
.xres
> info
->var
.xres_virtual
||
1625 var
->yoffset
+ info
->var
.yres
> info
->var
.yres_virtual
)
1628 err
= sisfb_pan_var(ivideo
, info
, var
);
1632 info
->var
.xoffset
= var
->xoffset
;
1633 info
->var
.yoffset
= var
->yoffset
;
1639 sisfb_blank(int blank
, struct fb_info
*info
)
1641 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1643 return sisfb_myblank(ivideo
, blank
);
1646 /* ----------- FBDev related routines for all series ---------- */
1648 static int sisfb_ioctl(struct fb_info
*info
, unsigned int cmd
,
1651 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1652 struct sis_memreq sismemreq
;
1653 struct fb_vblank sisvbblank
;
1658 u32 __user
*argp
= (u32 __user
*)arg
;
1662 if(!capable(CAP_SYS_RAWIO
))
1665 if(copy_from_user(&sismemreq
, (void __user
*)arg
, sizeof(sismemreq
)))
1668 sis_malloc(&sismemreq
);
1670 if(copy_to_user((void __user
*)arg
, &sismemreq
, sizeof(sismemreq
))) {
1671 sis_free((u32
)sismemreq
.offset
);
1677 if(!capable(CAP_SYS_RAWIO
))
1680 if(get_user(gpu32
, argp
))
1686 case FBIOGET_VBLANK
:
1688 memset(&sisvbblank
, 0, sizeof(struct fb_vblank
));
1690 sisvbblank
.count
= 0;
1691 sisvbblank
.flags
= sisfb_setupvbblankflags(ivideo
, &sisvbblank
.vcount
, &sisvbblank
.hcount
);
1693 if(copy_to_user((void __user
*)arg
, &sisvbblank
, sizeof(sisvbblank
)))
1698 case SISFB_GET_INFO_SIZE
:
1699 return put_user(sizeof(struct sisfb_info
), argp
);
1701 case SISFB_GET_INFO_OLD
:
1702 if(ivideo
->warncount
++ < 10)
1704 "sisfb: Deprecated ioctl call received - update your application!\n");
1705 case SISFB_GET_INFO
: /* For communication with X driver */
1706 ivideo
->sisfb_infoblock
.sisfb_id
= SISFB_ID
;
1707 ivideo
->sisfb_infoblock
.sisfb_version
= VER_MAJOR
;
1708 ivideo
->sisfb_infoblock
.sisfb_revision
= VER_MINOR
;
1709 ivideo
->sisfb_infoblock
.sisfb_patchlevel
= VER_LEVEL
;
1710 ivideo
->sisfb_infoblock
.chip_id
= ivideo
->chip_id
;
1711 ivideo
->sisfb_infoblock
.sisfb_pci_vendor
= ivideo
->chip_vendor
;
1712 ivideo
->sisfb_infoblock
.memory
= ivideo
->video_size
/ 1024;
1713 ivideo
->sisfb_infoblock
.heapstart
= ivideo
->heapstart
/ 1024;
1714 if(ivideo
->modechanged
) {
1715 ivideo
->sisfb_infoblock
.fbvidmode
= ivideo
->mode_no
;
1717 ivideo
->sisfb_infoblock
.fbvidmode
= ivideo
->modeprechange
;
1719 ivideo
->sisfb_infoblock
.sisfb_caps
= ivideo
->caps
;
1720 ivideo
->sisfb_infoblock
.sisfb_tqlen
= ivideo
->cmdQueueSize
/ 1024;
1721 ivideo
->sisfb_infoblock
.sisfb_pcibus
= ivideo
->pcibus
;
1722 ivideo
->sisfb_infoblock
.sisfb_pcislot
= ivideo
->pcislot
;
1723 ivideo
->sisfb_infoblock
.sisfb_pcifunc
= ivideo
->pcifunc
;
1724 ivideo
->sisfb_infoblock
.sisfb_lcdpdc
= ivideo
->detectedpdc
;
1725 ivideo
->sisfb_infoblock
.sisfb_lcdpdca
= ivideo
->detectedpdca
;
1726 ivideo
->sisfb_infoblock
.sisfb_lcda
= ivideo
->detectedlcda
;
1727 ivideo
->sisfb_infoblock
.sisfb_vbflags
= ivideo
->vbflags
;
1728 ivideo
->sisfb_infoblock
.sisfb_currentvbflags
= ivideo
->currentvbflags
;
1729 ivideo
->sisfb_infoblock
.sisfb_scalelcd
= ivideo
->SiS_Pr
.UsePanelScaler
;
1730 ivideo
->sisfb_infoblock
.sisfb_specialtiming
= ivideo
->SiS_Pr
.SiS_CustomT
;
1731 ivideo
->sisfb_infoblock
.sisfb_haveemi
= ivideo
->SiS_Pr
.HaveEMI
? 1 : 0;
1732 ivideo
->sisfb_infoblock
.sisfb_haveemilcd
= ivideo
->SiS_Pr
.HaveEMILCD
? 1 : 0;
1733 ivideo
->sisfb_infoblock
.sisfb_emi30
= ivideo
->SiS_Pr
.EMI_30
;
1734 ivideo
->sisfb_infoblock
.sisfb_emi31
= ivideo
->SiS_Pr
.EMI_31
;
1735 ivideo
->sisfb_infoblock
.sisfb_emi32
= ivideo
->SiS_Pr
.EMI_32
;
1736 ivideo
->sisfb_infoblock
.sisfb_emi33
= ivideo
->SiS_Pr
.EMI_33
;
1737 ivideo
->sisfb_infoblock
.sisfb_tvxpos
= (u16
)(ivideo
->tvxpos
+ 32);
1738 ivideo
->sisfb_infoblock
.sisfb_tvypos
= (u16
)(ivideo
->tvypos
+ 32);
1739 ivideo
->sisfb_infoblock
.sisfb_heapsize
= ivideo
->sisfb_heap_size
/ 1024;
1740 ivideo
->sisfb_infoblock
.sisfb_videooffset
= ivideo
->video_offset
;
1741 ivideo
->sisfb_infoblock
.sisfb_curfstn
= ivideo
->curFSTN
;
1742 ivideo
->sisfb_infoblock
.sisfb_curdstn
= ivideo
->curDSTN
;
1743 ivideo
->sisfb_infoblock
.sisfb_vbflags2
= ivideo
->vbflags2
;
1744 ivideo
->sisfb_infoblock
.sisfb_can_post
= ivideo
->sisfb_can_post
? 1 : 0;
1745 ivideo
->sisfb_infoblock
.sisfb_card_posted
= ivideo
->sisfb_card_posted
? 1 : 0;
1746 ivideo
->sisfb_infoblock
.sisfb_was_boot_device
= ivideo
->sisfb_was_boot_device
? 1 : 0;
1748 if(copy_to_user((void __user
*)arg
, &ivideo
->sisfb_infoblock
,
1749 sizeof(ivideo
->sisfb_infoblock
)))
1754 case SISFB_GET_VBRSTATUS_OLD
:
1755 if(ivideo
->warncount
++ < 10)
1757 "sisfb: Deprecated ioctl call received - update your application!\n");
1758 case SISFB_GET_VBRSTATUS
:
1759 if(sisfb_CheckVBRetrace(ivideo
))
1760 return put_user((u32
)1, argp
);
1762 return put_user((u32
)0, argp
);
1764 case SISFB_GET_AUTOMAXIMIZE_OLD
:
1765 if(ivideo
->warncount
++ < 10)
1767 "sisfb: Deprecated ioctl call received - update your application!\n");
1768 case SISFB_GET_AUTOMAXIMIZE
:
1769 if(ivideo
->sisfb_max
)
1770 return put_user((u32
)1, argp
);
1772 return put_user((u32
)0, argp
);
1774 case SISFB_SET_AUTOMAXIMIZE_OLD
:
1775 if(ivideo
->warncount
++ < 10)
1777 "sisfb: Deprecated ioctl call received - update your application!\n");
1778 case SISFB_SET_AUTOMAXIMIZE
:
1779 if(get_user(gpu32
, argp
))
1782 ivideo
->sisfb_max
= (gpu32
) ? 1 : 0;
1785 case SISFB_SET_TVPOSOFFSET
:
1786 if(get_user(gpu32
, argp
))
1789 sisfb_set_TVxposoffset(ivideo
, ((int)(gpu32
>> 16)) - 32);
1790 sisfb_set_TVyposoffset(ivideo
, ((int)(gpu32
& 0xffff)) - 32);
1793 case SISFB_GET_TVPOSOFFSET
:
1794 return put_user((u32
)(((ivideo
->tvxpos
+32)<<16)|((ivideo
->tvypos
+32)&0xffff)),
1798 if(copy_from_user(&ivideo
->sisfb_command
, (void __user
*)arg
,
1799 sizeof(struct sisfb_cmd
)))
1802 sisfb_handle_command(ivideo
, &ivideo
->sisfb_command
);
1804 if(copy_to_user((void __user
*)arg
, &ivideo
->sisfb_command
,
1805 sizeof(struct sisfb_cmd
)))
1810 case SISFB_SET_LOCK
:
1811 if(get_user(gpu32
, argp
))
1814 ivideo
->sisfblocked
= (gpu32
) ? 1 : 0;
1818 #ifdef SIS_NEW_CONFIG_COMPAT
1819 return -ENOIOCTLCMD
;
1828 sisfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
, struct fb_info
*info
)
1830 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1832 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
1834 strlcpy(fix
->id
, ivideo
->myid
, sizeof(fix
->id
));
1836 mutex_lock(&info
->mm_lock
);
1837 fix
->smem_start
= ivideo
->video_base
+ ivideo
->video_offset
;
1838 fix
->smem_len
= ivideo
->sisfb_mem
;
1839 mutex_unlock(&info
->mm_lock
);
1840 fix
->type
= FB_TYPE_PACKED_PIXELS
;
1842 fix
->visual
= (ivideo
->video_bpp
== 8) ? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_TRUECOLOR
;
1844 fix
->ypanstep
= (ivideo
->sisfb_ypan
) ? 1 : 0;
1846 fix
->line_length
= ivideo
->video_linelength
;
1847 fix
->mmio_start
= ivideo
->mmio_base
;
1848 fix
->mmio_len
= ivideo
->mmio_size
;
1849 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
1850 fix
->accel
= FB_ACCEL_SIS_GLAMOUR
;
1851 } else if((ivideo
->chip
== SIS_330
) ||
1852 (ivideo
->chip
== SIS_760
) ||
1853 (ivideo
->chip
== SIS_761
)) {
1854 fix
->accel
= FB_ACCEL_SIS_XABRE
;
1855 } else if(ivideo
->chip
== XGI_20
) {
1856 fix
->accel
= FB_ACCEL_XGI_VOLARI_Z
;
1857 } else if(ivideo
->chip
>= XGI_40
) {
1858 fix
->accel
= FB_ACCEL_XGI_VOLARI_V
;
1860 fix
->accel
= FB_ACCEL_SIS_GLAMOUR_2
;
1866 /* ---------------- fb_ops structures ----------------- */
1868 static struct fb_ops sisfb_ops
= {
1869 .owner
= THIS_MODULE
,
1870 .fb_open
= sisfb_open
,
1871 .fb_release
= sisfb_release
,
1872 .fb_check_var
= sisfb_check_var
,
1873 .fb_set_par
= sisfb_set_par
,
1874 .fb_setcolreg
= sisfb_setcolreg
,
1875 .fb_pan_display
= sisfb_pan_display
,
1876 .fb_blank
= sisfb_blank
,
1877 .fb_fillrect
= fbcon_sis_fillrect
,
1878 .fb_copyarea
= fbcon_sis_copyarea
,
1879 .fb_imageblit
= cfb_imageblit
,
1880 .fb_sync
= fbcon_sis_sync
,
1881 #ifdef SIS_NEW_CONFIG_COMPAT
1882 .fb_compat_ioctl
= sisfb_ioctl
,
1884 .fb_ioctl
= sisfb_ioctl
1887 /* ---------------- Chip generation dependent routines ---------------- */
1889 static struct pci_dev
*sisfb_get_northbridge(int basechipid
)
1891 struct pci_dev
*pdev
= NULL
;
1892 int nbridgenum
, nbridgeidx
, i
;
1893 static const unsigned short nbridgeids
[] = {
1894 PCI_DEVICE_ID_SI_540
, /* for SiS 540 VGA */
1895 PCI_DEVICE_ID_SI_630
, /* for SiS 630/730 VGA */
1896 PCI_DEVICE_ID_SI_730
,
1897 PCI_DEVICE_ID_SI_550
, /* for SiS 550 VGA */
1898 PCI_DEVICE_ID_SI_650
, /* for SiS 650/651/740 VGA */
1899 PCI_DEVICE_ID_SI_651
,
1900 PCI_DEVICE_ID_SI_740
,
1901 PCI_DEVICE_ID_SI_661
, /* for SiS 661/741/660/760/761 VGA */
1902 PCI_DEVICE_ID_SI_741
,
1903 PCI_DEVICE_ID_SI_660
,
1904 PCI_DEVICE_ID_SI_760
,
1905 PCI_DEVICE_ID_SI_761
1908 switch(basechipid
) {
1909 #ifdef CONFIG_FB_SIS_300
1910 case SIS_540
: nbridgeidx
= 0; nbridgenum
= 1; break;
1911 case SIS_630
: nbridgeidx
= 1; nbridgenum
= 2; break;
1913 #ifdef CONFIG_FB_SIS_315
1914 case SIS_550
: nbridgeidx
= 3; nbridgenum
= 1; break;
1915 case SIS_650
: nbridgeidx
= 4; nbridgenum
= 3; break;
1916 case SIS_660
: nbridgeidx
= 7; nbridgenum
= 5; break;
1918 default: return NULL
;
1920 for(i
= 0; i
< nbridgenum
; i
++) {
1921 if((pdev
= pci_get_device(PCI_VENDOR_ID_SI
,
1922 nbridgeids
[nbridgeidx
+i
], NULL
)))
1928 static int sisfb_get_dram_size(struct sis_video_info
*ivideo
)
1930 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1934 ivideo
->video_size
= 0;
1935 ivideo
->UMAsize
= ivideo
->LFBsize
= 0;
1937 switch(ivideo
->chip
) {
1938 #ifdef CONFIG_FB_SIS_300
1940 reg
= SiS_GetReg(SISSR
, 0x14);
1941 ivideo
->video_size
= ((reg
& 0x3F) + 1) << 20;
1946 if(!ivideo
->nbridge
)
1948 pci_read_config_byte(ivideo
->nbridge
, 0x63, ®
);
1949 ivideo
->video_size
= 1 << (((reg
& 0x70) >> 4) + 21);
1952 #ifdef CONFIG_FB_SIS_315
1956 reg
= SiS_GetReg(SISSR
, 0x14);
1957 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
1958 switch((reg
>> 2) & 0x03) {
1961 ivideo
->video_size
<<= 1;
1964 ivideo
->video_size
+= (ivideo
->video_size
/2);
1968 reg
= SiS_GetReg(SISSR
, 0x14);
1969 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
1970 if(reg
& 0x0c) ivideo
->video_size
<<= 1;
1975 reg
= SiS_GetReg(SISSR
, 0x14);
1976 ivideo
->video_size
= (((reg
& 0x3f) + 1) << 2) << 20;
1980 reg
= SiS_GetReg(SISCR
, 0x79);
1981 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
1986 reg
= SiS_GetReg(SISCR
, 0x79);
1987 reg
= (reg
& 0xf0) >> 4;
1989 ivideo
->video_size
= (1 << reg
) << 20;
1990 ivideo
->UMAsize
= ivideo
->video_size
;
1992 reg
= SiS_GetReg(SISCR
, 0x78);
1996 ivideo
->LFBsize
= (32 << 20);
1998 ivideo
->LFBsize
= (64 << 20);
2000 ivideo
->video_size
+= ivideo
->LFBsize
;
2006 reg
= SiS_GetReg(SISSR
, 0x14);
2007 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
2008 if(ivideo
->chip
!= XGI_20
) {
2009 reg
= (reg
& 0x0c) >> 2;
2010 if(ivideo
->revision_id
== 2) {
2011 if(reg
& 0x01) reg
= 0x02;
2014 if(reg
== 0x02) ivideo
->video_size
<<= 1;
2015 else if(reg
== 0x03) ivideo
->video_size
<<= 2;
2025 /* -------------- video bridge device detection --------------- */
2027 static void sisfb_detect_VB_connect(struct sis_video_info
*ivideo
)
2031 /* No CRT2 on XGI Z7 */
2032 if(ivideo
->chip
== XGI_20
) {
2033 ivideo
->sisfb_crt1off
= 0;
2037 #ifdef CONFIG_FB_SIS_300
2038 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2039 temp
= SiS_GetReg(SISSR
, 0x17);
2040 if((temp
& 0x0F) && (ivideo
->chip
!= SIS_300
)) {
2041 /* PAL/NTSC is stored on SR16 on such machines */
2042 if(!(ivideo
->vbflags
& (TV_PAL
| TV_NTSC
| TV_PALM
| TV_PALN
))) {
2043 temp
= SiS_GetReg(SISSR
, 0x16);
2045 ivideo
->vbflags
|= TV_PAL
;
2047 ivideo
->vbflags
|= TV_NTSC
;
2053 cr32
= SiS_GetReg(SISCR
, 0x32);
2055 if(cr32
& SIS_CRT1
) {
2056 ivideo
->sisfb_crt1off
= 0;
2058 ivideo
->sisfb_crt1off
= (cr32
& 0xDF) ? 1 : 0;
2061 ivideo
->vbflags
&= ~(CRT2_TV
| CRT2_LCD
| CRT2_VGA
);
2063 if(cr32
& SIS_VB_TV
) ivideo
->vbflags
|= CRT2_TV
;
2064 if(cr32
& SIS_VB_LCD
) ivideo
->vbflags
|= CRT2_LCD
;
2065 if(cr32
& SIS_VB_CRT2
) ivideo
->vbflags
|= CRT2_VGA
;
2067 /* Check given parms for hardware compatibility.
2068 * (Cannot do this in the search_xx routines since we don't
2069 * know what hardware we are running on then)
2072 if(ivideo
->chip
!= SIS_550
) {
2073 ivideo
->sisfb_dstn
= ivideo
->sisfb_fstn
= 0;
2076 if(ivideo
->sisfb_tvplug
!= -1) {
2077 if( (ivideo
->sisvga_engine
!= SIS_315_VGA
) ||
2078 (!(ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) ) {
2079 if(ivideo
->sisfb_tvplug
& TV_YPBPR
) {
2080 ivideo
->sisfb_tvplug
= -1;
2081 printk(KERN_ERR
"sisfb: YPbPr not supported\n");
2085 if(ivideo
->sisfb_tvplug
!= -1) {
2086 if( (ivideo
->sisvga_engine
!= SIS_315_VGA
) ||
2087 (!(ivideo
->vbflags2
& VB2_SISHIVISIONBRIDGE
)) ) {
2088 if(ivideo
->sisfb_tvplug
& TV_HIVISION
) {
2089 ivideo
->sisfb_tvplug
= -1;
2090 printk(KERN_ERR
"sisfb: HiVision not supported\n");
2094 if(ivideo
->sisfb_tvstd
!= -1) {
2095 if( (!(ivideo
->vbflags2
& VB2_SISBRIDGE
)) &&
2096 (!((ivideo
->sisvga_engine
== SIS_315_VGA
) &&
2097 (ivideo
->vbflags2
& VB2_CHRONTEL
))) ) {
2098 if(ivideo
->sisfb_tvstd
& (TV_PALM
| TV_PALN
| TV_NTSCJ
)) {
2099 ivideo
->sisfb_tvstd
= -1;
2100 printk(KERN_ERR
"sisfb: PALM/PALN/NTSCJ not supported\n");
2105 /* Detect/set TV plug & type */
2106 if(ivideo
->sisfb_tvplug
!= -1) {
2107 ivideo
->vbflags
|= ivideo
->sisfb_tvplug
;
2109 if(cr32
& SIS_VB_YPBPR
) ivideo
->vbflags
|= (TV_YPBPR
|TV_YPBPR525I
); /* default: 480i */
2110 else if(cr32
& SIS_VB_HIVISION
) ivideo
->vbflags
|= TV_HIVISION
;
2111 else if(cr32
& SIS_VB_SCART
) ivideo
->vbflags
|= TV_SCART
;
2113 if(cr32
& SIS_VB_SVIDEO
) ivideo
->vbflags
|= TV_SVIDEO
;
2114 if(cr32
& SIS_VB_COMPOSITE
) ivideo
->vbflags
|= TV_AVIDEO
;
2118 if(!(ivideo
->vbflags
& (TV_YPBPR
| TV_HIVISION
))) {
2119 if(ivideo
->sisfb_tvstd
!= -1) {
2120 ivideo
->vbflags
&= ~(TV_NTSC
| TV_PAL
| TV_PALM
| TV_PALN
| TV_NTSCJ
);
2121 ivideo
->vbflags
|= ivideo
->sisfb_tvstd
;
2123 if(ivideo
->vbflags
& TV_SCART
) {
2124 ivideo
->vbflags
&= ~(TV_NTSC
| TV_PALM
| TV_PALN
| TV_NTSCJ
);
2125 ivideo
->vbflags
|= TV_PAL
;
2127 if(!(ivideo
->vbflags
& (TV_PAL
| TV_NTSC
| TV_PALM
| TV_PALN
| TV_NTSCJ
))) {
2128 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2129 temp
= SiS_GetReg(SISSR
, 0x38);
2130 if(temp
& 0x01) ivideo
->vbflags
|= TV_PAL
;
2131 else ivideo
->vbflags
|= TV_NTSC
;
2132 } else if((ivideo
->chip
<= SIS_315PRO
) || (ivideo
->chip
>= SIS_330
)) {
2133 temp
= SiS_GetReg(SISSR
, 0x38);
2134 if(temp
& 0x01) ivideo
->vbflags
|= TV_PAL
;
2135 else ivideo
->vbflags
|= TV_NTSC
;
2137 temp
= SiS_GetReg(SISCR
, 0x79);
2138 if(temp
& 0x20) ivideo
->vbflags
|= TV_PAL
;
2139 else ivideo
->vbflags
|= TV_NTSC
;
2144 /* Copy forceCRT1 option to CRT1off if option is given */
2145 if(ivideo
->sisfb_forcecrt1
!= -1) {
2146 ivideo
->sisfb_crt1off
= (ivideo
->sisfb_forcecrt1
) ? 0 : 1;
2150 /* ------------------ Sensing routines ------------------ */
2152 static bool sisfb_test_DDC1(struct sis_video_info
*ivideo
)
2157 old
= SiS_ReadDDC1Bit(&ivideo
->SiS_Pr
);
2159 if(old
!= SiS_ReadDDC1Bit(&ivideo
->SiS_Pr
)) break;
2161 return (count
!= -1);
2164 static void sisfb_sense_crt1(struct sis_video_info
*ivideo
)
2166 bool mustwait
= false;
2168 #ifdef CONFIG_FB_SIS_315
2174 sr1F
= SiS_GetReg(SISSR
, 0x1F);
2175 SiS_SetRegOR(SISSR
, 0x1F, 0x04);
2176 SiS_SetRegAND(SISSR
, 0x1F, 0x3F);
2177 if(sr1F
& 0xc0) mustwait
= true;
2179 #ifdef CONFIG_FB_SIS_315
2180 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2181 cr63
= SiS_GetReg(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
);
2183 SiS_SetRegAND(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, 0xBF);
2187 cr17
= SiS_GetReg(SISCR
, 0x17);
2190 SiS_SetRegOR(SISCR
, 0x17, 0x80);
2192 SiS_SetReg(SISSR
, 0x00, 0x01);
2193 SiS_SetReg(SISSR
, 0x00, 0x03);
2197 for(i
=0; i
< 10; i
++) sisfbwaitretracecrt1(ivideo
);
2200 #ifdef CONFIG_FB_SIS_315
2201 if(ivideo
->chip
>= SIS_330
) {
2202 SiS_SetRegAND(SISCR
, 0x32, ~0x20);
2203 if(ivideo
->chip
>= SIS_340
) {
2204 SiS_SetReg(SISCR
, 0x57, 0x4a);
2206 SiS_SetReg(SISCR
, 0x57, 0x5f);
2208 SiS_SetRegOR(SISCR
, 0x53, 0x02);
2209 while ((SiS_GetRegByte(SISINPSTAT
)) & 0x01) break;
2210 while (!((SiS_GetRegByte(SISINPSTAT
)) & 0x01)) break;
2211 if ((SiS_GetRegByte(SISMISCW
)) & 0x10) temp
= 1;
2212 SiS_SetRegAND(SISCR
, 0x53, 0xfd);
2213 SiS_SetRegAND(SISCR
, 0x57, 0x00);
2217 if(temp
== 0xffff) {
2220 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
,
2221 ivideo
->sisvga_engine
, 0, 0, NULL
, ivideo
->vbflags2
);
2222 } while(((temp
== 0) || (temp
== 0xffff)) && i
--);
2224 if((temp
== 0) || (temp
== 0xffff)) {
2225 if(sisfb_test_DDC1(ivideo
)) temp
= 1;
2229 if((temp
) && (temp
!= 0xffff)) {
2230 SiS_SetRegOR(SISCR
, 0x32, 0x20);
2233 #ifdef CONFIG_FB_SIS_315
2234 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2235 SiS_SetRegANDOR(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, 0xBF, cr63
);
2239 SiS_SetRegANDOR(SISCR
, 0x17, 0x7F, cr17
);
2241 SiS_SetReg(SISSR
, 0x1F, sr1F
);
2244 /* Determine and detect attached devices on SiS30x */
2245 static void SiS_SenseLCD(struct sis_video_info
*ivideo
)
2247 unsigned char buffer
[256];
2248 unsigned short temp
, realcrtno
, i
;
2249 u8 reg
, cr37
= 0, paneltype
= 0;
2252 ivideo
->SiS_Pr
.PanelSelfDetected
= false;
2254 /* LCD detection only for TMDS bridges */
2255 if(!(ivideo
->vbflags2
& VB2_SISTMDSBRIDGE
))
2257 if(ivideo
->vbflags2
& VB2_30xBDH
)
2260 /* If LCD already set up by BIOS, skip it */
2261 reg
= SiS_GetReg(SISCR
, 0x32);
2266 if(ivideo
->SiS_Pr
.DDCPortMixup
)
2269 /* Check DDC capabilities */
2270 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
2271 realcrtno
, 0, &buffer
[0], ivideo
->vbflags2
);
2273 if((!temp
) || (temp
== 0xffff) || (!(temp
& 0x02)))
2277 i
= 3; /* Number of retrys */
2279 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
,
2280 ivideo
->sisvga_engine
, realcrtno
, 1,
2281 &buffer
[0], ivideo
->vbflags2
);
2282 } while((temp
) && i
--);
2287 /* No digital device */
2288 if(!(buffer
[0x14] & 0x80))
2291 /* First detailed timing preferred timing? */
2292 if(!(buffer
[0x18] & 0x02))
2295 xres
= buffer
[0x38] | ((buffer
[0x3a] & 0xf0) << 4);
2296 yres
= buffer
[0x3b] | ((buffer
[0x3d] & 0xf0) << 4);
2308 if((yres
== 1200) && (ivideo
->vbflags2
& VB2_30xC
))
2319 if((buffer
[0x47] & 0x18) == 0x18)
2320 cr37
|= ((((buffer
[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2324 SiS_SetReg(SISCR
, 0x36, paneltype
);
2326 SiS_SetRegANDOR(SISCR
, 0x37, 0x0c, cr37
);
2327 SiS_SetRegOR(SISCR
, 0x32, 0x08);
2329 ivideo
->SiS_Pr
.PanelSelfDetected
= true;
2332 static int SISDoSense(struct sis_video_info
*ivideo
, u16 type
, u16 test
)
2334 int temp
, mytest
, result
, i
, j
;
2336 for(j
= 0; j
< 10; j
++) {
2338 for(i
= 0; i
< 3; i
++) {
2340 SiS_SetReg(SISPART4
, 0x11, (type
& 0x00ff));
2341 temp
= (type
>> 8) | (mytest
& 0x00ff);
2342 SiS_SetRegANDOR(SISPART4
, 0x10, 0xe0, temp
);
2343 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x1500);
2346 temp
= SiS_GetReg(SISPART4
, 0x03);
2349 if(temp
== mytest
) result
++;
2351 SiS_SetReg(SISPART4
, 0x11, 0x00);
2352 SiS_SetRegAND(SISPART4
, 0x10, 0xe0);
2353 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x1000);
2356 if((result
== 0) || (result
>= 2)) break;
2361 static void SiS_Sense30x(struct sis_video_info
*ivideo
)
2363 u8 backupP4_0d
,backupP2_00
,backupP2_4d
,backupSR_1e
,biosflag
=0;
2364 u16 svhs
=0, svhs_c
=0;
2365 u16 cvbs
=0, cvbs_c
=0;
2366 u16 vga2
=0, vga2_c
=0;
2368 char stdstr
[] = "sisfb: Detected";
2369 char tvstr
[] = "TV connected to";
2371 if(ivideo
->vbflags2
& VB2_301
) {
2372 svhs
= 0x00b9; cvbs
= 0x00b3; vga2
= 0x00d1;
2373 myflag
= SiS_GetReg(SISPART4
, 0x01);
2375 svhs
= 0x00dd; cvbs
= 0x00ee; vga2
= 0x00fd;
2377 } else if(ivideo
->vbflags2
& (VB2_301B
| VB2_302B
)) {
2378 svhs
= 0x016b; cvbs
= 0x0174; vga2
= 0x0190;
2379 } else if(ivideo
->vbflags2
& (VB2_301LV
| VB2_302LV
)) {
2380 svhs
= 0x0200; cvbs
= 0x0100;
2381 } else if(ivideo
->vbflags2
& (VB2_301C
| VB2_302ELV
| VB2_307T
| VB2_307LV
)) {
2382 svhs
= 0x016b; cvbs
= 0x0110; vga2
= 0x0190;
2386 vga2_c
= 0x0e08; svhs_c
= 0x0404; cvbs_c
= 0x0804;
2387 if(ivideo
->vbflags
& (VB2_301LV
|VB2_302LV
|VB2_302ELV
|VB2_307LV
)) {
2388 svhs_c
= 0x0408; cvbs_c
= 0x0808;
2392 if(ivideo
->haveXGIROM
) {
2393 biosflag
= ivideo
->bios_abase
[0x58] & 0x03;
2394 } else if(ivideo
->newrom
) {
2395 if(ivideo
->bios_abase
[0x5d] & 0x04) biosflag
|= 0x01;
2396 } else if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2397 if(ivideo
->bios_abase
) {
2398 biosflag
= ivideo
->bios_abase
[0xfe] & 0x03;
2402 if(ivideo
->chip
== SIS_300
) {
2403 myflag
= SiS_GetReg(SISSR
, 0x3b);
2404 if(!(myflag
& 0x01)) vga2
= vga2_c
= 0;
2407 if(!(ivideo
->vbflags2
& VB2_SISVGA2BRIDGE
)) {
2411 backupSR_1e
= SiS_GetReg(SISSR
, 0x1e);
2412 SiS_SetRegOR(SISSR
, 0x1e, 0x20);
2414 backupP4_0d
= SiS_GetReg(SISPART4
, 0x0d);
2415 if(ivideo
->vbflags2
& VB2_30xC
) {
2416 SiS_SetRegANDOR(SISPART4
, 0x0d, ~0x07, 0x01);
2418 SiS_SetRegOR(SISPART4
, 0x0d, 0x04);
2420 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x2000);
2422 backupP2_00
= SiS_GetReg(SISPART2
, 0x00);
2423 SiS_SetReg(SISPART2
, 0x00, ((backupP2_00
| 0x1c) & 0xfc));
2425 backupP2_4d
= SiS_GetReg(SISPART2
, 0x4d);
2426 if(ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
) {
2427 SiS_SetReg(SISPART2
, 0x4d, (backupP2_4d
& ~0x10));
2430 if(!(ivideo
->vbflags2
& VB2_30xCLV
)) {
2431 SISDoSense(ivideo
, 0, 0);
2434 SiS_SetRegAND(SISCR
, 0x32, ~0x14);
2436 if(vga2_c
|| vga2
) {
2437 if(SISDoSense(ivideo
, vga2
, vga2_c
)) {
2438 if(biosflag
& 0x01) {
2439 printk(KERN_INFO
"%s %s SCART output\n", stdstr
, tvstr
);
2440 SiS_SetRegOR(SISCR
, 0x32, 0x04);
2442 printk(KERN_INFO
"%s secondary VGA connection\n", stdstr
);
2443 SiS_SetRegOR(SISCR
, 0x32, 0x10);
2448 SiS_SetRegAND(SISCR
, 0x32, 0x3f);
2450 if(ivideo
->vbflags2
& VB2_30xCLV
) {
2451 SiS_SetRegOR(SISPART4
, 0x0d, 0x04);
2454 if((ivideo
->sisvga_engine
== SIS_315_VGA
) && (ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) {
2455 SiS_SetReg(SISPART2
, 0x4d, (backupP2_4d
| 0x10));
2456 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x2000);
2457 if((result
= SISDoSense(ivideo
, svhs
, 0x0604))) {
2458 if((result
= SISDoSense(ivideo
, cvbs
, 0x0804))) {
2459 printk(KERN_INFO
"%s %s YPbPr component output\n", stdstr
, tvstr
);
2460 SiS_SetRegOR(SISCR
, 0x32, 0x80);
2463 SiS_SetReg(SISPART2
, 0x4d, backupP2_4d
);
2466 SiS_SetRegAND(SISCR
, 0x32, ~0x03);
2468 if(!(ivideo
->vbflags
& TV_YPBPR
)) {
2469 if((result
= SISDoSense(ivideo
, svhs
, svhs_c
))) {
2470 printk(KERN_INFO
"%s %s SVIDEO output\n", stdstr
, tvstr
);
2471 SiS_SetRegOR(SISCR
, 0x32, 0x02);
2473 if((biosflag
& 0x02) || (!result
)) {
2474 if(SISDoSense(ivideo
, cvbs
, cvbs_c
)) {
2475 printk(KERN_INFO
"%s %s COMPOSITE output\n", stdstr
, tvstr
);
2476 SiS_SetRegOR(SISCR
, 0x32, 0x01);
2481 SISDoSense(ivideo
, 0, 0);
2483 SiS_SetReg(SISPART2
, 0x00, backupP2_00
);
2484 SiS_SetReg(SISPART4
, 0x0d, backupP4_0d
);
2485 SiS_SetReg(SISSR
, 0x1e, backupSR_1e
);
2487 if(ivideo
->vbflags2
& VB2_30xCLV
) {
2488 biosflag
= SiS_GetReg(SISPART2
, 0x00);
2489 if(biosflag
& 0x20) {
2490 for(myflag
= 2; myflag
> 0; myflag
--) {
2492 SiS_SetReg(SISPART2
, 0x00, biosflag
);
2497 SiS_SetReg(SISPART2
, 0x00, backupP2_00
);
2500 /* Determine and detect attached TV's on Chrontel */
2501 static void SiS_SenseCh(struct sis_video_info
*ivideo
)
2503 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2505 char stdstr
[] = "sisfb: Chrontel: Detected TV connected to";
2507 #ifdef CONFIG_FB_SIS_300
2508 unsigned char test
[3];
2512 if(ivideo
->chip
< SIS_315H
) {
2514 #ifdef CONFIG_FB_SIS_300
2515 ivideo
->SiS_Pr
.SiS_IF_DEF_CH70xx
= 1; /* Chrontel 700x */
2516 SiS_SetChrontelGPIO(&ivideo
->SiS_Pr
, 0x9c); /* Set general purpose IO for Chrontel communication */
2517 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 1000);
2518 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x25);
2519 /* See Chrontel TB31 for explanation */
2520 temp2
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0e);
2521 if(((temp2
& 0x07) == 0x01) || (temp2
& 0x04)) {
2522 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0e, 0x0b);
2523 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 300);
2525 temp2
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x25);
2526 if(temp2
!= temp1
) temp1
= temp2
;
2528 if((temp1
>= 0x22) && (temp1
<= 0x50)) {
2529 /* Read power status */
2530 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0e);
2531 if((temp1
& 0x03) != 0x03) {
2532 /* Power all outputs */
2533 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0e,0x0b);
2534 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 300);
2536 /* Sense connected TV devices */
2537 for(i
= 0; i
< 3; i
++) {
2538 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x10, 0x01);
2539 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2540 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x10, 0x00);
2541 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2542 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x10);
2543 if(!(temp1
& 0x08)) test
[i
] = 0x02;
2544 else if(!(temp1
& 0x02)) test
[i
] = 0x01;
2546 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2549 if(test
[0] == test
[1]) temp1
= test
[0];
2550 else if(test
[0] == test
[2]) temp1
= test
[0];
2551 else if(test
[1] == test
[2]) temp1
= test
[1];
2554 "sisfb: TV detection unreliable - test results varied\n");
2558 printk(KERN_INFO
"%s SVIDEO output\n", stdstr
);
2559 ivideo
->vbflags
|= TV_SVIDEO
;
2560 SiS_SetRegOR(SISCR
, 0x32, 0x02);
2561 SiS_SetRegAND(SISCR
, 0x32, ~0x05);
2562 } else if (temp1
== 0x01) {
2563 printk(KERN_INFO
"%s CVBS output\n", stdstr
);
2564 ivideo
->vbflags
|= TV_AVIDEO
;
2565 SiS_SetRegOR(SISCR
, 0x32, 0x01);
2566 SiS_SetRegAND(SISCR
, 0x32, ~0x06);
2568 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x0e, 0x01, 0xF8);
2569 SiS_SetRegAND(SISCR
, 0x32, ~0x07);
2571 } else if(temp1
== 0) {
2572 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x0e, 0x01, 0xF8);
2573 SiS_SetRegAND(SISCR
, 0x32, ~0x07);
2575 /* Set general purpose IO for Chrontel communication */
2576 SiS_SetChrontelGPIO(&ivideo
->SiS_Pr
, 0x00);
2581 #ifdef CONFIG_FB_SIS_315
2582 ivideo
->SiS_Pr
.SiS_IF_DEF_CH70xx
= 2; /* Chrontel 7019 */
2583 temp1
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x49);
2584 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x49, 0x20);
2585 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2586 temp2
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x20);
2588 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x20, temp2
);
2589 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2591 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x20, temp2
);
2592 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2593 temp2
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x20);
2594 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x49, temp1
);
2596 if(temp2
& 0x02) temp1
|= 0x01;
2597 if(temp2
& 0x10) temp1
|= 0x01;
2598 if(temp2
& 0x04) temp1
|= 0x02;
2599 if( (temp1
& 0x01) && (temp1
& 0x02) ) temp1
= 0x04;
2602 printk(KERN_INFO
"%s CVBS output\n", stdstr
);
2603 ivideo
->vbflags
|= TV_AVIDEO
;
2604 SiS_SetRegOR(SISCR
, 0x32, 0x01);
2605 SiS_SetRegAND(SISCR
, 0x32, ~0x06);
2608 printk(KERN_INFO
"%s SVIDEO output\n", stdstr
);
2609 ivideo
->vbflags
|= TV_SVIDEO
;
2610 SiS_SetRegOR(SISCR
, 0x32, 0x02);
2611 SiS_SetRegAND(SISCR
, 0x32, ~0x05);
2614 printk(KERN_INFO
"%s SCART output\n", stdstr
);
2615 SiS_SetRegOR(SISCR
, 0x32, 0x04);
2616 SiS_SetRegAND(SISCR
, 0x32, ~0x03);
2619 SiS_SetRegAND(SISCR
, 0x32, ~0x07);
2625 static void sisfb_get_VB_type(struct sis_video_info
*ivideo
)
2627 char stdstr
[] = "sisfb: Detected";
2628 char bridgestr
[] = "video bridge";
2632 /* No CRT2 on XGI Z7 */
2633 if(ivideo
->chip
== XGI_20
)
2636 vb_chipid
= SiS_GetReg(SISPART4
, 0x00);
2639 reg
= SiS_GetReg(SISPART4
, 0x01);
2641 ivideo
->vbflags
|= VB_301
; /* Deprecated */
2642 ivideo
->vbflags2
|= VB2_301
;
2643 printk(KERN_INFO
"%s SiS301 %s\n", stdstr
, bridgestr
);
2644 } else if(reg
< 0xc0) {
2645 ivideo
->vbflags
|= VB_301B
; /* Deprecated */
2646 ivideo
->vbflags2
|= VB2_301B
;
2647 reg
= SiS_GetReg(SISPART4
, 0x23);
2649 ivideo
->vbflags
|= VB_30xBDH
; /* Deprecated */
2650 ivideo
->vbflags2
|= VB2_30xBDH
;
2651 printk(KERN_INFO
"%s SiS301B-DH %s\n", stdstr
, bridgestr
);
2653 printk(KERN_INFO
"%s SiS301B %s\n", stdstr
, bridgestr
);
2655 } else if(reg
< 0xd0) {
2656 ivideo
->vbflags
|= VB_301C
; /* Deprecated */
2657 ivideo
->vbflags2
|= VB2_301C
;
2658 printk(KERN_INFO
"%s SiS301C %s\n", stdstr
, bridgestr
);
2659 } else if(reg
< 0xe0) {
2660 ivideo
->vbflags
|= VB_301LV
; /* Deprecated */
2661 ivideo
->vbflags2
|= VB2_301LV
;
2662 printk(KERN_INFO
"%s SiS301LV %s\n", stdstr
, bridgestr
);
2663 } else if(reg
<= 0xe1) {
2664 reg
= SiS_GetReg(SISPART4
, 0x39);
2666 ivideo
->vbflags
|= VB_302LV
; /* Deprecated */
2667 ivideo
->vbflags2
|= VB2_302LV
;
2668 printk(KERN_INFO
"%s SiS302LV %s\n", stdstr
, bridgestr
);
2670 ivideo
->vbflags
|= VB_301C
; /* Deprecated */
2671 ivideo
->vbflags2
|= VB2_301C
;
2672 printk(KERN_INFO
"%s SiS301C(P4) %s\n", stdstr
, bridgestr
);
2674 ivideo
->vbflags
|= VB_302ELV
; /* Deprecated */
2675 ivideo
->vbflags2
|= VB2_302ELV
;
2676 printk(KERN_INFO
"%s SiS302ELV %s\n", stdstr
, bridgestr
);
2682 ivideo
->vbflags
|= VB_302B
; /* Deprecated */
2683 ivideo
->vbflags2
|= VB2_302B
;
2684 printk(KERN_INFO
"%s SiS302B %s\n", stdstr
, bridgestr
);
2688 if((!(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
)) && (ivideo
->chip
!= SIS_300
)) {
2689 reg
= SiS_GetReg(SISCR
, 0x37);
2690 reg
&= SIS_EXTERNAL_CHIP_MASK
;
2692 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2693 #ifdef CONFIG_FB_SIS_300
2695 case SIS_EXTERNAL_CHIP_LVDS
:
2696 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2697 ivideo
->vbflags2
|= VB2_LVDS
;
2699 case SIS_EXTERNAL_CHIP_TRUMPION
:
2700 ivideo
->vbflags
|= (VB_LVDS
| VB_TRUMPION
); /* Deprecated */
2701 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_TRUMPION
);
2703 case SIS_EXTERNAL_CHIP_CHRONTEL
:
2704 ivideo
->vbflags
|= VB_CHRONTEL
; /* Deprecated */
2705 ivideo
->vbflags2
|= VB2_CHRONTEL
;
2707 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL
:
2708 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2709 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2712 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 1;
2714 } else if(ivideo
->chip
< SIS_661
) {
2715 #ifdef CONFIG_FB_SIS_315
2717 case SIS310_EXTERNAL_CHIP_LVDS
:
2718 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2719 ivideo
->vbflags2
|= VB2_LVDS
;
2721 case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL
:
2722 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2723 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2726 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 2;
2728 } else if(ivideo
->chip
>= SIS_661
) {
2729 #ifdef CONFIG_FB_SIS_315
2730 reg
= SiS_GetReg(SISCR
, 0x38);
2734 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2735 ivideo
->vbflags2
|= VB2_LVDS
;
2738 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2739 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2742 ivideo
->vbflags
|= (VB_LVDS
| VB_CONEXANT
); /* Deprecated */
2743 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CONEXANT
);
2746 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 2;
2749 if(ivideo
->vbflags2
& VB2_LVDS
) {
2750 printk(KERN_INFO
"%s LVDS transmitter\n", stdstr
);
2752 if((ivideo
->sisvga_engine
== SIS_300_VGA
) && (ivideo
->vbflags2
& VB2_TRUMPION
)) {
2753 printk(KERN_INFO
"%s Trumpion Zurac LCD scaler\n", stdstr
);
2755 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
2756 printk(KERN_INFO
"%s Chrontel TV encoder\n", stdstr
);
2758 if((ivideo
->chip
>= SIS_661
) && (ivideo
->vbflags2
& VB2_CONEXANT
)) {
2759 printk(KERN_INFO
"%s Conexant external device\n", stdstr
);
2763 if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
2764 SiS_SenseLCD(ivideo
);
2765 SiS_Sense30x(ivideo
);
2766 } else if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
2767 SiS_SenseCh(ivideo
);
2771 /* ---------- Engine initialization routines ------------ */
2774 sisfb_engine_init(struct sis_video_info
*ivideo
)
2777 /* Initialize command queue (we use MMIO only) */
2779 /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
2781 ivideo
->caps
&= ~(TURBO_QUEUE_CAP
|
2782 MMIO_CMD_QUEUE_CAP
|
2786 #ifdef CONFIG_FB_SIS_300
2787 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2791 tqueue_pos
= (ivideo
->video_size
- ivideo
->cmdQueueSize
) / (64 * 1024);
2793 tq_state
= SiS_GetReg(SISSR
, IND_SIS_TURBOQUEUE_SET
);
2796 tq_state
|= (u8
)(tqueue_pos
>> 8);
2797 SiS_SetReg(SISSR
, IND_SIS_TURBOQUEUE_SET
, tq_state
);
2799 SiS_SetReg(SISSR
, IND_SIS_TURBOQUEUE_ADR
, (u8
)(tqueue_pos
& 0xff));
2801 ivideo
->caps
|= TURBO_QUEUE_CAP
;
2805 #ifdef CONFIG_FB_SIS_315
2806 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2807 u32 tempq
= 0, templ
;
2810 if(ivideo
->chip
== XGI_20
) {
2811 switch(ivideo
->cmdQueueSize
) {
2813 temp
= SIS_CMD_QUEUE_SIZE_Z7_64k
;
2817 temp
= SIS_CMD_QUEUE_SIZE_Z7_128k
;
2820 switch(ivideo
->cmdQueueSize
) {
2821 case (4 * 1024 * 1024):
2822 temp
= SIS_CMD_QUEUE_SIZE_4M
;
2824 case (2 * 1024 * 1024):
2825 temp
= SIS_CMD_QUEUE_SIZE_2M
;
2827 case (1 * 1024 * 1024):
2828 temp
= SIS_CMD_QUEUE_SIZE_1M
;
2832 temp
= SIS_CMD_QUEUE_SIZE_512k
;
2836 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_THRESHOLD
, COMMAND_QUEUE_THRESHOLD
);
2837 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, SIS_CMD_QUEUE_RESET
);
2839 if((ivideo
->chip
>= XGI_40
) && ivideo
->modechanged
) {
2840 /* Must disable dual pipe on XGI_40. Can't do
2841 * this in MMIO mode, because it requires
2842 * setting/clearing a bit in the MMIO fire trigger
2845 if(!((templ
= MMIO_IN32(ivideo
->mmio_vbase
, 0x8240)) & (1 << 10))) {
2847 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, 0);
2849 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, (temp
| SIS_VRAM_CMDQUEUE_ENABLE
));
2851 tempq
= MMIO_IN32(ivideo
->mmio_vbase
, Q_READ_PTR
);
2852 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, tempq
);
2854 tempq
= (u32
)(ivideo
->video_size
- ivideo
->cmdQueueSize
);
2855 MMIO_OUT32(ivideo
->mmio_vbase
, Q_BASE_ADDR
, tempq
);
2857 writel(0x16800000 + 0x8240, ivideo
->video_vbase
+ tempq
);
2858 writel(templ
| (1 << 10), ivideo
->video_vbase
+ tempq
+ 4);
2859 writel(0x168F0000, ivideo
->video_vbase
+ tempq
+ 8);
2860 writel(0x168F0000, ivideo
->video_vbase
+ tempq
+ 12);
2862 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, (tempq
+ 16));
2864 sisfb_syncaccel(ivideo
);
2866 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, SIS_CMD_QUEUE_RESET
);
2871 tempq
= MMIO_IN32(ivideo
->mmio_vbase
, MMIO_QUEUE_READPORT
);
2872 MMIO_OUT32(ivideo
->mmio_vbase
, MMIO_QUEUE_WRITEPORT
, tempq
);
2874 temp
|= (SIS_MMIO_CMD_ENABLE
| SIS_CMD_AUTO_CORR
);
2875 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, temp
);
2877 tempq
= (u32
)(ivideo
->video_size
- ivideo
->cmdQueueSize
);
2878 MMIO_OUT32(ivideo
->mmio_vbase
, MMIO_QUEUE_PHYBASE
, tempq
);
2880 ivideo
->caps
|= MMIO_CMD_QUEUE_CAP
;
2884 ivideo
->engineok
= 1;
2887 static void sisfb_detect_lcd_type(struct sis_video_info
*ivideo
)
2892 reg
= SiS_GetReg(SISCR
, 0x36);
2894 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2895 ivideo
->CRT2LCDType
= sis300paneltype
[reg
];
2896 } else if(ivideo
->chip
>= SIS_661
) {
2897 ivideo
->CRT2LCDType
= sis661paneltype
[reg
];
2899 ivideo
->CRT2LCDType
= sis310paneltype
[reg
];
2900 if((ivideo
->chip
== SIS_550
) && (sisfb_fstn
)) {
2901 if((ivideo
->CRT2LCDType
!= LCD_320x240_2
) &&
2902 (ivideo
->CRT2LCDType
!= LCD_320x240_3
)) {
2903 ivideo
->CRT2LCDType
= LCD_320x240
;
2908 if(ivideo
->CRT2LCDType
== LCD_UNKNOWN
) {
2909 /* For broken BIOSes: Assume 1024x768, RGB18 */
2910 ivideo
->CRT2LCDType
= LCD_1024x768
;
2911 SiS_SetRegANDOR(SISCR
, 0x36, 0xf0, 0x02);
2912 SiS_SetRegANDOR(SISCR
, 0x37, 0xee, 0x01);
2913 printk(KERN_DEBUG
"sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg
);
2916 for(i
= 0; i
< SIS_LCD_NUMBER
; i
++) {
2917 if(ivideo
->CRT2LCDType
== sis_lcd_data
[i
].lcdtype
) {
2918 ivideo
->lcdxres
= sis_lcd_data
[i
].xres
;
2919 ivideo
->lcdyres
= sis_lcd_data
[i
].yres
;
2920 ivideo
->lcddefmodeidx
= sis_lcd_data
[i
].default_mode_idx
;
2925 #ifdef CONFIG_FB_SIS_300
2926 if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_BARCO1366
) {
2927 ivideo
->lcdxres
= 1360; ivideo
->lcdyres
= 1024;
2928 ivideo
->lcddefmodeidx
= DEFAULT_MODE_1360
;
2929 } else if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_PANEL848
) {
2930 ivideo
->lcdxres
= 848; ivideo
->lcdyres
= 480;
2931 ivideo
->lcddefmodeidx
= DEFAULT_MODE_848
;
2932 } else if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_PANEL856
) {
2933 ivideo
->lcdxres
= 856; ivideo
->lcdyres
= 480;
2934 ivideo
->lcddefmodeidx
= DEFAULT_MODE_856
;
2938 printk(KERN_DEBUG
"sisfb: Detected %dx%d flat panel\n",
2939 ivideo
->lcdxres
, ivideo
->lcdyres
);
2942 static void sisfb_save_pdc_emi(struct sis_video_info
*ivideo
)
2944 #ifdef CONFIG_FB_SIS_300
2945 /* Save the current PanelDelayCompensation if the LCD is currently used */
2946 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2947 if(ivideo
->vbflags2
& (VB2_LVDS
| VB2_30xBDH
)) {
2949 tmp
= SiS_GetReg(SISCR
, 0x30);
2951 /* Currently on LCD? If yes, read current pdc */
2952 ivideo
->detectedpdc
= SiS_GetReg(SISPART1
, 0x13);
2953 ivideo
->detectedpdc
&= 0x3c;
2954 if(ivideo
->SiS_Pr
.PDC
== -1) {
2955 /* Let option override detection */
2956 ivideo
->SiS_Pr
.PDC
= ivideo
->detectedpdc
;
2958 printk(KERN_INFO
"sisfb: Detected LCD PDC 0x%02x\n",
2959 ivideo
->detectedpdc
);
2961 if((ivideo
->SiS_Pr
.PDC
!= -1) &&
2962 (ivideo
->SiS_Pr
.PDC
!= ivideo
->detectedpdc
)) {
2963 printk(KERN_INFO
"sisfb: Using LCD PDC 0x%02x\n",
2964 ivideo
->SiS_Pr
.PDC
);
2970 #ifdef CONFIG_FB_SIS_315
2971 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2973 /* Try to find about LCDA */
2974 if(ivideo
->vbflags2
& VB2_SISLCDABRIDGE
) {
2976 tmp
= SiS_GetReg(SISPART1
, 0x13);
2978 ivideo
->SiS_Pr
.SiS_UseLCDA
= true;
2979 ivideo
->detectedlcda
= 0x03;
2984 if(ivideo
->vbflags2
& VB2_SISLVDSBRIDGE
) {
2986 tmp
= SiS_GetReg(SISCR
, 0x30);
2987 if((tmp
& 0x20) || (ivideo
->detectedlcda
!= 0xff)) {
2988 /* Currently on LCD? If yes, read current pdc */
2990 pdc
= SiS_GetReg(SISPART1
, 0x2D);
2991 ivideo
->detectedpdc
= (pdc
& 0x0f) << 1;
2992 ivideo
->detectedpdca
= (pdc
& 0xf0) >> 3;
2993 pdc
= SiS_GetReg(SISPART1
, 0x35);
2994 ivideo
->detectedpdc
|= ((pdc
>> 7) & 0x01);
2995 pdc
= SiS_GetReg(SISPART1
, 0x20);
2996 ivideo
->detectedpdca
|= ((pdc
>> 6) & 0x01);
2997 if(ivideo
->newrom
) {
2998 /* New ROM invalidates other PDC resp. */
2999 if(ivideo
->detectedlcda
!= 0xff) {
3000 ivideo
->detectedpdc
= 0xff;
3002 ivideo
->detectedpdca
= 0xff;
3005 if(ivideo
->SiS_Pr
.PDC
== -1) {
3006 if(ivideo
->detectedpdc
!= 0xff) {
3007 ivideo
->SiS_Pr
.PDC
= ivideo
->detectedpdc
;
3010 if(ivideo
->SiS_Pr
.PDCA
== -1) {
3011 if(ivideo
->detectedpdca
!= 0xff) {
3012 ivideo
->SiS_Pr
.PDCA
= ivideo
->detectedpdca
;
3015 if(ivideo
->detectedpdc
!= 0xff) {
3017 "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3018 ivideo
->detectedpdc
);
3020 if(ivideo
->detectedpdca
!= 0xff) {
3022 "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3023 ivideo
->detectedpdca
);
3028 if(ivideo
->vbflags2
& VB2_SISEMIBRIDGE
) {
3029 ivideo
->SiS_Pr
.EMI_30
= SiS_GetReg(SISPART4
, 0x30);
3030 ivideo
->SiS_Pr
.EMI_31
= SiS_GetReg(SISPART4
, 0x31);
3031 ivideo
->SiS_Pr
.EMI_32
= SiS_GetReg(SISPART4
, 0x32);
3032 ivideo
->SiS_Pr
.EMI_33
= SiS_GetReg(SISPART4
, 0x33);
3033 ivideo
->SiS_Pr
.HaveEMI
= true;
3034 if((tmp
& 0x20) || (ivideo
->detectedlcda
!= 0xff)) {
3035 ivideo
->SiS_Pr
.HaveEMILCD
= true;
3040 /* Let user override detected PDCs (all bridges) */
3041 if(ivideo
->vbflags2
& VB2_30xBLV
) {
3042 if((ivideo
->SiS_Pr
.PDC
!= -1) &&
3043 (ivideo
->SiS_Pr
.PDC
!= ivideo
->detectedpdc
)) {
3044 printk(KERN_INFO
"sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3045 ivideo
->SiS_Pr
.PDC
);
3047 if((ivideo
->SiS_Pr
.PDCA
!= -1) &&
3048 (ivideo
->SiS_Pr
.PDCA
!= ivideo
->detectedpdca
)) {
3049 printk(KERN_INFO
"sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3050 ivideo
->SiS_Pr
.PDCA
);
3058 /* -------------------- Memory manager routines ---------------------- */
3060 static u32
sisfb_getheapstart(struct sis_video_info
*ivideo
)
3062 u32 ret
= ivideo
->sisfb_parm_mem
* 1024;
3063 u32 maxoffs
= ivideo
->video_size
- ivideo
->hwcursor_size
- ivideo
->cmdQueueSize
;
3066 /* Calculate heap start = end of memory for console
3068 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3069 * C = console, D = heap, H = HWCursor, Q = cmd-queue
3071 * On 76x in UMA+LFB mode, the layout is as follows:
3072 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3073 * where the heap is the entire UMA area, eventually
3074 * into the LFB area if the given mem parameter is
3075 * higher than the size of the UMA memory.
3077 * Basically given by "mem" parameter
3079 * maximum = videosize - cmd_queue - hwcursor
3080 * (results in a heap of size 0)
3081 * default = SiS 300: depends on videosize
3082 * SiS 315/330/340/XGI: 32k below max
3085 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3086 if(ivideo
->video_size
> 0x1000000) {
3088 } else if(ivideo
->video_size
> 0x800000) {
3093 } else if(ivideo
->UMAsize
&& ivideo
->LFBsize
) {
3096 def
= maxoffs
- 0x8000;
3099 /* Use default for secondary card for now (FIXME) */
3100 if((!ret
) || (ret
> maxoffs
) || (ivideo
->cardnumber
!= 0))
3106 static u32
sisfb_getheapsize(struct sis_video_info
*ivideo
)
3108 u32 max
= ivideo
->video_size
- ivideo
->hwcursor_size
- ivideo
->cmdQueueSize
;
3111 if(ivideo
->UMAsize
&& ivideo
->LFBsize
) {
3112 if( (!ivideo
->sisfb_parm_mem
) ||
3113 ((ivideo
->sisfb_parm_mem
* 1024) > max
) ||
3114 ((max
- (ivideo
->sisfb_parm_mem
* 1024)) < ivideo
->UMAsize
) ) {
3115 ret
= ivideo
->UMAsize
;
3116 max
-= ivideo
->UMAsize
;
3118 ret
= max
- (ivideo
->sisfb_parm_mem
* 1024);
3119 max
= ivideo
->sisfb_parm_mem
* 1024;
3121 ivideo
->video_offset
= ret
;
3122 ivideo
->sisfb_mem
= max
;
3124 ret
= max
- ivideo
->heapstart
;
3125 ivideo
->sisfb_mem
= ivideo
->heapstart
;
3131 static int sisfb_heap_init(struct sis_video_info
*ivideo
)
3135 ivideo
->video_offset
= 0;
3136 if(ivideo
->sisfb_parm_mem
) {
3137 if( (ivideo
->sisfb_parm_mem
< (2 * 1024 * 1024)) ||
3138 (ivideo
->sisfb_parm_mem
> ivideo
->video_size
) ) {
3139 ivideo
->sisfb_parm_mem
= 0;
3143 ivideo
->heapstart
= sisfb_getheapstart(ivideo
);
3144 ivideo
->sisfb_heap_size
= sisfb_getheapsize(ivideo
);
3146 ivideo
->sisfb_heap_start
= ivideo
->video_vbase
+ ivideo
->heapstart
;
3147 ivideo
->sisfb_heap_end
= ivideo
->sisfb_heap_start
+ ivideo
->sisfb_heap_size
;
3149 printk(KERN_INFO
"sisfb: Memory heap starting at %dK, size %dK\n",
3150 (int)(ivideo
->heapstart
/ 1024), (int)(ivideo
->sisfb_heap_size
/ 1024));
3152 ivideo
->sisfb_heap
.vinfo
= ivideo
;
3154 ivideo
->sisfb_heap
.poha_chain
= NULL
;
3155 ivideo
->sisfb_heap
.poh_freelist
= NULL
;
3157 poh
= sisfb_poh_new_node(&ivideo
->sisfb_heap
);
3161 poh
->poh_next
= &ivideo
->sisfb_heap
.oh_free
;
3162 poh
->poh_prev
= &ivideo
->sisfb_heap
.oh_free
;
3163 poh
->size
= ivideo
->sisfb_heap_size
;
3164 poh
->offset
= ivideo
->heapstart
;
3166 ivideo
->sisfb_heap
.oh_free
.poh_next
= poh
;
3167 ivideo
->sisfb_heap
.oh_free
.poh_prev
= poh
;
3168 ivideo
->sisfb_heap
.oh_free
.size
= 0;
3169 ivideo
->sisfb_heap
.max_freesize
= poh
->size
;
3171 ivideo
->sisfb_heap
.oh_used
.poh_next
= &ivideo
->sisfb_heap
.oh_used
;
3172 ivideo
->sisfb_heap
.oh_used
.poh_prev
= &ivideo
->sisfb_heap
.oh_used
;
3173 ivideo
->sisfb_heap
.oh_used
.size
= SENTINEL
;
3175 if(ivideo
->cardnumber
== 0) {
3176 /* For the first card, make this heap the "global" one
3177 * for old DRM (which could handle only one card)
3179 sisfb_heap
= &ivideo
->sisfb_heap
;
3185 static struct SIS_OH
*
3186 sisfb_poh_new_node(struct SIS_HEAP
*memheap
)
3188 struct SIS_OHALLOC
*poha
;
3193 if(memheap
->poh_freelist
== NULL
) {
3194 poha
= kmalloc(SIS_OH_ALLOC_SIZE
, GFP_KERNEL
);
3198 poha
->poha_next
= memheap
->poha_chain
;
3199 memheap
->poha_chain
= poha
;
3201 cOhs
= (SIS_OH_ALLOC_SIZE
- sizeof(struct SIS_OHALLOC
)) / sizeof(struct SIS_OH
) + 1;
3203 poh
= &poha
->aoh
[0];
3204 for(i
= cOhs
- 1; i
!= 0; i
--) {
3205 poh
->poh_next
= poh
+ 1;
3209 poh
->poh_next
= NULL
;
3210 memheap
->poh_freelist
= &poha
->aoh
[0];
3213 poh
= memheap
->poh_freelist
;
3214 memheap
->poh_freelist
= poh
->poh_next
;
3219 static struct SIS_OH
*
3220 sisfb_poh_allocate(struct SIS_HEAP
*memheap
, u32 size
)
3222 struct SIS_OH
*pohThis
;
3223 struct SIS_OH
*pohRoot
;
3226 if(size
> memheap
->max_freesize
) {
3227 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3228 (unsigned int) size
/ 1024);
3232 pohThis
= memheap
->oh_free
.poh_next
;
3234 while(pohThis
!= &memheap
->oh_free
) {
3235 if(size
<= pohThis
->size
) {
3239 pohThis
= pohThis
->poh_next
;
3243 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3244 (unsigned int) size
/ 1024);
3248 if(size
== pohThis
->size
) {
3250 sisfb_delete_node(pohThis
);
3252 pohRoot
= sisfb_poh_new_node(memheap
);
3256 pohRoot
->offset
= pohThis
->offset
;
3257 pohRoot
->size
= size
;
3259 pohThis
->offset
+= size
;
3260 pohThis
->size
-= size
;
3263 memheap
->max_freesize
-= size
;
3265 pohThis
= &memheap
->oh_used
;
3266 sisfb_insert_node(pohThis
, pohRoot
);
3272 sisfb_delete_node(struct SIS_OH
*poh
)
3274 poh
->poh_prev
->poh_next
= poh
->poh_next
;
3275 poh
->poh_next
->poh_prev
= poh
->poh_prev
;
3279 sisfb_insert_node(struct SIS_OH
*pohList
, struct SIS_OH
*poh
)
3281 struct SIS_OH
*pohTemp
= pohList
->poh_next
;
3283 pohList
->poh_next
= poh
;
3284 pohTemp
->poh_prev
= poh
;
3286 poh
->poh_prev
= pohList
;
3287 poh
->poh_next
= pohTemp
;
3290 static struct SIS_OH
*
3291 sisfb_poh_free(struct SIS_HEAP
*memheap
, u32 base
)
3293 struct SIS_OH
*pohThis
;
3294 struct SIS_OH
*poh_freed
;
3295 struct SIS_OH
*poh_prev
;
3296 struct SIS_OH
*poh_next
;
3301 poh_freed
= memheap
->oh_used
.poh_next
;
3303 while(poh_freed
!= &memheap
->oh_used
) {
3304 if(poh_freed
->offset
== base
) {
3309 poh_freed
= poh_freed
->poh_next
;
3315 memheap
->max_freesize
+= poh_freed
->size
;
3317 poh_prev
= poh_next
= NULL
;
3318 ulUpper
= poh_freed
->offset
+ poh_freed
->size
;
3319 ulLower
= poh_freed
->offset
;
3321 pohThis
= memheap
->oh_free
.poh_next
;
3323 while(pohThis
!= &memheap
->oh_free
) {
3324 if(pohThis
->offset
== ulUpper
) {
3326 } else if((pohThis
->offset
+ pohThis
->size
) == ulLower
) {
3329 pohThis
= pohThis
->poh_next
;
3332 sisfb_delete_node(poh_freed
);
3334 if(poh_prev
&& poh_next
) {
3335 poh_prev
->size
+= (poh_freed
->size
+ poh_next
->size
);
3336 sisfb_delete_node(poh_next
);
3337 sisfb_free_node(memheap
, poh_freed
);
3338 sisfb_free_node(memheap
, poh_next
);
3343 poh_prev
->size
+= poh_freed
->size
;
3344 sisfb_free_node(memheap
, poh_freed
);
3349 poh_next
->size
+= poh_freed
->size
;
3350 poh_next
->offset
= poh_freed
->offset
;
3351 sisfb_free_node(memheap
, poh_freed
);
3355 sisfb_insert_node(&memheap
->oh_free
, poh_freed
);
3361 sisfb_free_node(struct SIS_HEAP
*memheap
, struct SIS_OH
*poh
)
3366 poh
->poh_next
= memheap
->poh_freelist
;
3367 memheap
->poh_freelist
= poh
;
3371 sis_int_malloc(struct sis_video_info
*ivideo
, struct sis_memreq
*req
)
3373 struct SIS_OH
*poh
= NULL
;
3375 if((ivideo
) && (ivideo
->sisfb_id
== SISFB_ID
) && (!ivideo
->havenoheap
))
3376 poh
= sisfb_poh_allocate(&ivideo
->sisfb_heap
, (u32
)req
->size
);
3379 req
->offset
= req
->size
= 0;
3380 DPRINTK("sisfb: Video RAM allocation failed\n");
3382 req
->offset
= poh
->offset
;
3383 req
->size
= poh
->size
;
3384 DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3385 (poh
->offset
+ ivideo
->video_vbase
));
3390 sis_malloc(struct sis_memreq
*req
)
3392 struct sis_video_info
*ivideo
= sisfb_heap
->vinfo
;
3394 if(&ivideo
->sisfb_heap
== sisfb_heap
)
3395 sis_int_malloc(ivideo
, req
);
3397 req
->offset
= req
->size
= 0;
3401 sis_malloc_new(struct pci_dev
*pdev
, struct sis_memreq
*req
)
3403 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
3405 sis_int_malloc(ivideo
, req
);
3408 /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3411 sis_int_free(struct sis_video_info
*ivideo
, u32 base
)
3415 if((!ivideo
) || (ivideo
->sisfb_id
!= SISFB_ID
) || (ivideo
->havenoheap
))
3418 poh
= sisfb_poh_free(&ivideo
->sisfb_heap
, base
);
3421 DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
3422 (unsigned int) base
);
3429 struct sis_video_info
*ivideo
= sisfb_heap
->vinfo
;
3431 sis_int_free(ivideo
, base
);
3435 sis_free_new(struct pci_dev
*pdev
, u32 base
)
3437 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
3439 sis_int_free(ivideo
, base
);
3442 /* --------------------- SetMode routines ------------------------- */
3445 sisfb_check_engine_and_sync(struct sis_video_info
*ivideo
)
3449 /* Check if MMIO and engines are enabled,
3450 * and sync in case they are. Can't use
3451 * ivideo->accel here, as this might have
3452 * been changed before this is called.
3454 cr30
= SiS_GetReg(SISSR
, IND_SIS_PCI_ADDRESS_SET
);
3455 cr31
= SiS_GetReg(SISSR
, IND_SIS_MODULE_ENABLE
);
3456 /* MMIO and 2D/3D engine enabled? */
3457 if((cr30
& SIS_MEM_MAP_IO_ENABLE
) && (cr31
& 0x42)) {
3458 #ifdef CONFIG_FB_SIS_300
3459 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3460 /* Don't care about TurboQueue. It's
3461 * enough to know that the engines
3464 sisfb_syncaccel(ivideo
);
3467 #ifdef CONFIG_FB_SIS_315
3468 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3469 /* Check that any queue mode is
3470 * enabled, and that the queue
3471 * is not in the state of "reset"
3473 cr30
= SiS_GetReg(SISSR
, 0x26);
3474 if((cr30
& 0xe0) && (!(cr30
& 0x01))) {
3475 sisfb_syncaccel(ivideo
);
3483 sisfb_pre_setmode(struct sis_video_info
*ivideo
)
3485 u8 cr30
= 0, cr31
= 0, cr33
= 0, cr35
= 0, cr38
= 0;
3488 ivideo
->currentvbflags
&= (VB_VIDEOBRIDGE
| VB_DISPTYPE_DISP2
);
3490 SiS_SetReg(SISSR
, 0x05, 0x86);
3492 cr31
= SiS_GetReg(SISCR
, 0x31);
3496 cr33
= ivideo
->rate_idx
& 0x0F;
3498 #ifdef CONFIG_FB_SIS_315
3499 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3500 if(ivideo
->chip
>= SIS_661
) {
3501 cr38
= SiS_GetReg(SISCR
, 0x38);
3502 cr38
&= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
3505 cr38
= SiS_GetReg(SISCR
, tvregnum
);
3506 cr38
&= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
3510 #ifdef CONFIG_FB_SIS_300
3511 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3513 cr38
= SiS_GetReg(SISCR
, tvregnum
);
3517 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
3518 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
3519 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
3521 switch(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
3524 cr38
&= ~0xc0; /* Clear PAL-M / PAL-N bits */
3525 if((ivideo
->vbflags
& TV_YPBPR
) && (ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) {
3526 #ifdef CONFIG_FB_SIS_315
3527 if(ivideo
->chip
>= SIS_661
) {
3529 if(ivideo
->vbflags
& TV_YPBPR525P
) cr35
|= 0x20;
3530 else if(ivideo
->vbflags
& TV_YPBPR750P
) cr35
|= 0x40;
3531 else if(ivideo
->vbflags
& TV_YPBPR1080I
) cr35
|= 0x60;
3532 cr30
|= SIS_SIMULTANEOUS_VIEW_ENABLE
;
3534 ivideo
->currentvbflags
|= (TV_YPBPR
| (ivideo
->vbflags
& TV_YPBPRALL
));
3535 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3536 cr30
|= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE
);
3538 if(ivideo
->vbflags
& TV_YPBPR525P
) cr38
|= 0x10;
3539 else if(ivideo
->vbflags
& TV_YPBPR750P
) cr38
|= 0x20;
3540 else if(ivideo
->vbflags
& TV_YPBPR1080I
) cr38
|= 0x30;
3542 ivideo
->currentvbflags
|= (TV_YPBPR
| (ivideo
->vbflags
& TV_YPBPRALL
));
3545 } else if((ivideo
->vbflags
& TV_HIVISION
) &&
3546 (ivideo
->vbflags2
& VB2_SISHIVISIONBRIDGE
)) {
3547 if(ivideo
->chip
>= SIS_661
) {
3553 cr30
|= SIS_SIMULTANEOUS_VIEW_ENABLE
;
3556 ivideo
->currentvbflags
|= TV_HIVISION
;
3557 } else if(ivideo
->vbflags
& TV_SCART
) {
3558 cr30
= (SIS_VB_OUTPUT_SCART
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3561 ivideo
->currentvbflags
|= TV_SCART
;
3563 if(ivideo
->vbflags
& TV_SVIDEO
) {
3564 cr30
= (SIS_VB_OUTPUT_SVIDEO
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3565 ivideo
->currentvbflags
|= TV_SVIDEO
;
3567 if(ivideo
->vbflags
& TV_AVIDEO
) {
3568 cr30
= (SIS_VB_OUTPUT_COMPOSITE
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3569 ivideo
->currentvbflags
|= TV_AVIDEO
;
3572 cr31
|= SIS_DRIVER_MODE
;
3574 if(ivideo
->vbflags
& (TV_AVIDEO
| TV_SVIDEO
)) {
3575 if(ivideo
->vbflags
& TV_PAL
) {
3576 cr31
|= 0x01; cr35
|= 0x01;
3577 ivideo
->currentvbflags
|= TV_PAL
;
3578 if(ivideo
->vbflags
& TV_PALM
) {
3579 cr38
|= 0x40; cr35
|= 0x04;
3580 ivideo
->currentvbflags
|= TV_PALM
;
3581 } else if(ivideo
->vbflags
& TV_PALN
) {
3582 cr38
|= 0x80; cr35
|= 0x08;
3583 ivideo
->currentvbflags
|= TV_PALN
;
3586 cr31
&= ~0x01; cr35
&= ~0x01;
3587 ivideo
->currentvbflags
|= TV_NTSC
;
3588 if(ivideo
->vbflags
& TV_NTSCJ
) {
3589 cr38
|= 0x40; cr35
|= 0x02;
3590 ivideo
->currentvbflags
|= TV_NTSCJ
;
3597 cr30
= (SIS_VB_OUTPUT_LCD
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3598 cr31
|= SIS_DRIVER_MODE
;
3599 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, ivideo
->sisfb_dstn
);
3600 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, ivideo
->sisfb_fstn
);
3601 ivideo
->curFSTN
= ivideo
->sisfb_fstn
;
3602 ivideo
->curDSTN
= ivideo
->sisfb_dstn
;
3606 cr30
= (SIS_VB_OUTPUT_CRT2
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3607 cr31
|= SIS_DRIVER_MODE
;
3608 if(ivideo
->sisfb_nocrt2rate
) {
3609 cr33
|= (sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
<< 4);
3611 cr33
|= ((ivideo
->rate_idx
& 0x0F) << 4);
3615 default: /* disable CRT2 */
3617 cr31
|= (SIS_DRIVER_MODE
| SIS_VB_OUTPUT_DISABLE
);
3620 SiS_SetReg(SISCR
, 0x30, cr30
);
3621 SiS_SetReg(SISCR
, 0x33, cr33
);
3623 if(ivideo
->chip
>= SIS_661
) {
3624 #ifdef CONFIG_FB_SIS_315
3625 cr31
&= ~0x01; /* Clear PAL flag (now in CR35) */
3626 SiS_SetRegANDOR(SISCR
, 0x35, ~0x10, cr35
); /* Leave overscan bit alone */
3627 cr38
&= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
3628 SiS_SetRegANDOR(SISCR
, 0x38, 0xf8, cr38
);
3630 } else if(ivideo
->chip
!= SIS_300
) {
3631 SiS_SetReg(SISCR
, tvregnum
, cr38
);
3633 SiS_SetReg(SISCR
, 0x31, cr31
);
3635 ivideo
->SiS_Pr
.SiS_UseOEM
= ivideo
->sisfb_useoem
;
3637 sisfb_check_engine_and_sync(ivideo
);
3640 /* Fix SR11 for 661 and later */
3641 #ifdef CONFIG_FB_SIS_315
3643 sisfb_fixup_SR11(struct sis_video_info
*ivideo
)
3647 if(ivideo
->chip
>= SIS_661
) {
3648 tmpreg
= SiS_GetReg(SISSR
, 0x11);
3650 tmpreg
= SiS_GetReg(SISSR
, 0x3e);
3651 tmpreg
= (tmpreg
+ 1) & 0xff;
3652 SiS_SetReg(SISSR
, 0x3e, tmpreg
);
3653 tmpreg
= SiS_GetReg(SISSR
, 0x11);
3656 SiS_SetRegAND(SISSR
, 0x11, 0x0f);
3663 sisfb_set_TVxposoffset(struct sis_video_info
*ivideo
, int val
)
3665 if(val
> 32) val
= 32;
3666 if(val
< -32) val
= -32;
3667 ivideo
->tvxpos
= val
;
3669 if(ivideo
->sisfblocked
) return;
3670 if(!ivideo
->modechanged
) return;
3672 if(ivideo
->currentvbflags
& CRT2_TV
) {
3674 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3676 int x
= ivideo
->tvx
;
3678 switch(ivideo
->chronteltype
) {
3682 SiS_SetReg(SISSR
, 0x05, 0x86);
3683 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0a, (x
& 0xff));
3684 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x08, ((x
& 0x0100) >> 7), 0xFD);
3687 /* Not supported by hardware */
3691 } else if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3693 u8 p2_1f
,p2_20
,p2_2b
,p2_42
,p2_43
;
3694 unsigned short temp
;
3696 p2_1f
= ivideo
->p2_1f
;
3697 p2_20
= ivideo
->p2_20
;
3698 p2_2b
= ivideo
->p2_2b
;
3699 p2_42
= ivideo
->p2_42
;
3700 p2_43
= ivideo
->p2_43
;
3702 temp
= p2_1f
| ((p2_20
& 0xf0) << 4);
3704 p2_1f
= temp
& 0xff;
3705 p2_20
= (temp
& 0xf00) >> 4;
3706 p2_2b
= ((p2_2b
& 0x0f) + (val
* 2)) & 0x0f;
3707 temp
= p2_43
| ((p2_42
& 0xf0) << 4);
3709 p2_43
= temp
& 0xff;
3710 p2_42
= (temp
& 0xf00) >> 4;
3711 SiS_SetReg(SISPART2
, 0x1f, p2_1f
);
3712 SiS_SetRegANDOR(SISPART2
, 0x20, 0x0F, p2_20
);
3713 SiS_SetRegANDOR(SISPART2
, 0x2b, 0xF0, p2_2b
);
3714 SiS_SetRegANDOR(SISPART2
, 0x42, 0x0F, p2_42
);
3715 SiS_SetReg(SISPART2
, 0x43, p2_43
);
3721 sisfb_set_TVyposoffset(struct sis_video_info
*ivideo
, int val
)
3723 if(val
> 32) val
= 32;
3724 if(val
< -32) val
= -32;
3725 ivideo
->tvypos
= val
;
3727 if(ivideo
->sisfblocked
) return;
3728 if(!ivideo
->modechanged
) return;
3730 if(ivideo
->currentvbflags
& CRT2_TV
) {
3732 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3734 int y
= ivideo
->tvy
;
3736 switch(ivideo
->chronteltype
) {
3740 SiS_SetReg(SISSR
, 0x05, 0x86);
3741 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0b, (y
& 0xff));
3742 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x08, ((y
& 0x0100) >> 8), 0xFE);
3745 /* Not supported by hardware */
3749 } else if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3753 p2_01
= ivideo
->p2_01
;
3754 p2_02
= ivideo
->p2_02
;
3758 if(!(ivideo
->currentvbflags
& (TV_HIVISION
| TV_YPBPR
))) {
3759 while((p2_01
<= 0) || (p2_02
<= 0)) {
3764 SiS_SetReg(SISPART2
, 0x01, p2_01
);
3765 SiS_SetReg(SISPART2
, 0x02, p2_02
);
3771 sisfb_post_setmode(struct sis_video_info
*ivideo
)
3773 bool crt1isoff
= false;
3775 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
3778 #ifdef CONFIG_FB_SIS_315
3782 SiS_SetReg(SISSR
, 0x05, 0x86);
3784 #ifdef CONFIG_FB_SIS_315
3785 sisfb_fixup_SR11(ivideo
);
3788 /* Now we actually HAVE changed the display mode */
3789 ivideo
->modechanged
= 1;
3791 /* We can't switch off CRT1 if bridge is in slave mode */
3792 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
3793 if(sisfb_bridgeisslave(ivideo
)) doit
= false;
3795 ivideo
->sisfb_crt1off
= 0;
3797 #ifdef CONFIG_FB_SIS_300
3798 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3799 if((ivideo
->sisfb_crt1off
) && (doit
)) {
3806 SiS_SetRegANDOR(SISCR
, 0x17, 0x7f, reg
);
3809 #ifdef CONFIG_FB_SIS_315
3810 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3811 if((ivideo
->sisfb_crt1off
) && (doit
)) {
3820 SiS_SetRegANDOR(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, ~0x40, reg
);
3821 SiS_SetRegANDOR(SISSR
, 0x1f, 0x3f, reg1
);
3826 ivideo
->currentvbflags
&= ~VB_DISPTYPE_CRT1
;
3827 ivideo
->currentvbflags
|= VB_SINGLE_MODE
;
3829 ivideo
->currentvbflags
|= VB_DISPTYPE_CRT1
;
3830 if(ivideo
->currentvbflags
& VB_DISPTYPE_CRT2
) {
3831 ivideo
->currentvbflags
|= VB_MIRROR_MODE
;
3833 ivideo
->currentvbflags
|= VB_SINGLE_MODE
;
3837 SiS_SetRegAND(SISSR
, IND_SIS_RAMDAC_CONTROL
, ~0x04);
3839 if(ivideo
->currentvbflags
& CRT2_TV
) {
3840 if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3841 ivideo
->p2_1f
= SiS_GetReg(SISPART2
, 0x1f);
3842 ivideo
->p2_20
= SiS_GetReg(SISPART2
, 0x20);
3843 ivideo
->p2_2b
= SiS_GetReg(SISPART2
, 0x2b);
3844 ivideo
->p2_42
= SiS_GetReg(SISPART2
, 0x42);
3845 ivideo
->p2_43
= SiS_GetReg(SISPART2
, 0x43);
3846 ivideo
->p2_01
= SiS_GetReg(SISPART2
, 0x01);
3847 ivideo
->p2_02
= SiS_GetReg(SISPART2
, 0x02);
3848 } else if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3849 if(ivideo
->chronteltype
== 1) {
3850 ivideo
->tvx
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0a);
3851 ivideo
->tvx
|= (((SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x08) & 0x02) >> 1) << 8);
3852 ivideo
->tvy
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0b);
3853 ivideo
->tvy
|= ((SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x08) & 0x01) << 8);
3858 if(ivideo
->tvxpos
) {
3859 sisfb_set_TVxposoffset(ivideo
, ivideo
->tvxpos
);
3861 if(ivideo
->tvypos
) {
3862 sisfb_set_TVyposoffset(ivideo
, ivideo
->tvypos
);
3865 /* Eventually sync engines */
3866 sisfb_check_engine_and_sync(ivideo
);
3868 /* (Re-)Initialize chip engines */
3870 sisfb_engine_init(ivideo
);
3872 ivideo
->engineok
= 0;
3877 sisfb_reset_mode(struct sis_video_info
*ivideo
)
3879 if(sisfb_set_mode(ivideo
, 0))
3882 sisfb_set_pitch(ivideo
);
3883 sisfb_set_base_CRT1(ivideo
, ivideo
->current_base
);
3884 sisfb_set_base_CRT2(ivideo
, ivideo
->current_base
);
3890 sisfb_handle_command(struct sis_video_info
*ivideo
, struct sisfb_cmd
*sisfb_command
)
3894 switch(sisfb_command
->sisfb_cmd
) {
3895 case SISFB_CMD_GETVBFLAGS
:
3896 if(!ivideo
->modechanged
) {
3897 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_EARLY
;
3899 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3900 sisfb_command
->sisfb_result
[1] = ivideo
->currentvbflags
;
3901 sisfb_command
->sisfb_result
[2] = ivideo
->vbflags2
;
3904 case SISFB_CMD_SWITCHCRT1
:
3905 /* arg[0]: 0 = off, 1 = on, 99 = query */
3906 if(!ivideo
->modechanged
) {
3907 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_EARLY
;
3908 } else if(sisfb_command
->sisfb_arg
[0] == 99) {
3910 sisfb_command
->sisfb_result
[1] = ivideo
->sisfb_crt1off
? 0 : 1;
3911 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3912 } else if(ivideo
->sisfblocked
) {
3913 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_LOCKED
;
3914 } else if((!(ivideo
->currentvbflags
& CRT2_ENABLE
)) &&
3915 (sisfb_command
->sisfb_arg
[0] == 0)) {
3916 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_NOCRT2
;
3918 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3919 mycrt1off
= sisfb_command
->sisfb_arg
[0] ? 0 : 1;
3920 if( ((ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
) && mycrt1off
) ||
3921 ((!(ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
)) && !mycrt1off
) ) {
3922 ivideo
->sisfb_crt1off
= mycrt1off
;
3923 if(sisfb_reset_mode(ivideo
)) {
3924 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OTHER
;
3927 sisfb_command
->sisfb_result
[1] = ivideo
->sisfb_crt1off
? 0 : 1;
3932 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_UNKNOWN
;
3933 printk(KERN_ERR
"sisfb: Unknown command 0x%x\n",
3934 sisfb_command
->sisfb_cmd
);
3939 static int __init
sisfb_setup(char *options
)
3943 sisfb_setdefaultparms();
3945 if(!options
|| !(*options
))
3948 while((this_opt
= strsep(&options
, ",")) != NULL
) {
3950 if(!(*this_opt
)) continue;
3952 if(!strncasecmp(this_opt
, "off", 3)) {
3954 } else if(!strncasecmp(this_opt
, "forcecrt2type:", 14)) {
3955 /* Need to check crt2 type first for fstn/dstn */
3956 sisfb_search_crt2type(this_opt
+ 14);
3957 } else if(!strncasecmp(this_opt
, "tvmode:",7)) {
3958 sisfb_search_tvstd(this_opt
+ 7);
3959 } else if(!strncasecmp(this_opt
, "tvstandard:",11)) {
3960 sisfb_search_tvstd(this_opt
+ 11);
3961 } else if(!strncasecmp(this_opt
, "mode:", 5)) {
3962 sisfb_search_mode(this_opt
+ 5, false);
3963 } else if(!strncasecmp(this_opt
, "vesa:", 5)) {
3964 sisfb_search_vesamode(simple_strtoul(this_opt
+ 5, NULL
, 0), false);
3965 } else if(!strncasecmp(this_opt
, "rate:", 5)) {
3966 sisfb_parm_rate
= simple_strtoul(this_opt
+ 5, NULL
, 0);
3967 } else if(!strncasecmp(this_opt
, "forcecrt1:", 10)) {
3968 sisfb_forcecrt1
= (int)simple_strtoul(this_opt
+ 10, NULL
, 0);
3969 } else if(!strncasecmp(this_opt
, "mem:",4)) {
3970 sisfb_parm_mem
= simple_strtoul(this_opt
+ 4, NULL
, 0);
3971 } else if(!strncasecmp(this_opt
, "pdc:", 4)) {
3972 sisfb_pdc
= simple_strtoul(this_opt
+ 4, NULL
, 0);
3973 } else if(!strncasecmp(this_opt
, "pdc1:", 5)) {
3974 sisfb_pdca
= simple_strtoul(this_opt
+ 5, NULL
, 0);
3975 } else if(!strncasecmp(this_opt
, "noaccel", 7)) {
3977 } else if(!strncasecmp(this_opt
, "accel", 5)) {
3979 } else if(!strncasecmp(this_opt
, "noypan", 6)) {
3981 } else if(!strncasecmp(this_opt
, "ypan", 4)) {
3983 } else if(!strncasecmp(this_opt
, "nomax", 5)) {
3985 } else if(!strncasecmp(this_opt
, "max", 3)) {
3987 } else if(!strncasecmp(this_opt
, "userom:", 7)) {
3988 sisfb_userom
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
3989 } else if(!strncasecmp(this_opt
, "useoem:", 7)) {
3990 sisfb_useoem
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
3991 } else if(!strncasecmp(this_opt
, "nocrt2rate", 10)) {
3992 sisfb_nocrt2rate
= 1;
3993 } else if(!strncasecmp(this_opt
, "scalelcd:", 9)) {
3994 unsigned long temp
= 2;
3995 temp
= simple_strtoul(this_opt
+ 9, NULL
, 0);
3996 if((temp
== 0) || (temp
== 1)) {
3997 sisfb_scalelcd
= temp
^ 1;
3999 } else if(!strncasecmp(this_opt
, "tvxposoffset:", 13)) {
4001 temp
= (int)simple_strtol(this_opt
+ 13, NULL
, 0);
4002 if((temp
>= -32) && (temp
<= 32)) {
4003 sisfb_tvxposoffset
= temp
;
4005 } else if(!strncasecmp(this_opt
, "tvyposoffset:", 13)) {
4007 temp
= (int)simple_strtol(this_opt
+ 13, NULL
, 0);
4008 if((temp
>= -32) && (temp
<= 32)) {
4009 sisfb_tvyposoffset
= temp
;
4011 } else if(!strncasecmp(this_opt
, "specialtiming:", 14)) {
4012 sisfb_search_specialtiming(this_opt
+ 14);
4013 } else if(!strncasecmp(this_opt
, "lvdshl:", 7)) {
4015 temp
= simple_strtoul(this_opt
+ 7, NULL
, 0);
4016 if((temp
>= 0) && (temp
<= 3)) {
4017 sisfb_lvdshl
= temp
;
4019 } else if(this_opt
[0] >= '0' && this_opt
[0] <= '9') {
4020 sisfb_search_mode(this_opt
, true);
4021 #if !defined(__i386__) && !defined(__x86_64__)
4022 } else if(!strncasecmp(this_opt
, "resetcard", 9)) {
4023 sisfb_resetcard
= 1;
4024 } else if(!strncasecmp(this_opt
, "videoram:", 9)) {
4025 sisfb_videoram
= simple_strtoul(this_opt
+ 9, NULL
, 0);
4028 printk(KERN_INFO
"sisfb: Invalid option %s\n", this_opt
);
4037 static int sisfb_check_rom(void __iomem
*rom_base
,
4038 struct sis_video_info
*ivideo
)
4043 if((readb(rom_base
) != 0x55) || (readb(rom_base
+ 1) != 0xaa))
4046 romptr
= (readb(rom_base
+ 0x18) | (readb(rom_base
+ 0x19) << 8));
4047 if(romptr
> (0x10000 - 8))
4050 rom
= rom_base
+ romptr
;
4052 if((readb(rom
) != 'P') || (readb(rom
+ 1) != 'C') ||
4053 (readb(rom
+ 2) != 'I') || (readb(rom
+ 3) != 'R'))
4056 if((readb(rom
+ 4) | (readb(rom
+ 5) << 8)) != ivideo
->chip_vendor
)
4059 if((readb(rom
+ 6) | (readb(rom
+ 7) << 8)) != ivideo
->chip_id
)
4065 static unsigned char *sisfb_find_rom(struct pci_dev
*pdev
)
4067 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4068 void __iomem
*rom_base
;
4069 unsigned char *myrombase
= NULL
;
4072 /* First, try the official pci ROM functions (except
4073 * on integrated chipsets which have no ROM).
4076 if(!ivideo
->nbridge
) {
4078 if((rom_base
= pci_map_rom(pdev
, &romsize
))) {
4080 if(sisfb_check_rom(rom_base
, ivideo
)) {
4082 if((myrombase
= vmalloc(65536))) {
4083 memcpy_fromio(myrombase
, rom_base
,
4084 (romsize
> 65536) ? 65536 : romsize
);
4087 pci_unmap_rom(pdev
, rom_base
);
4091 if(myrombase
) return myrombase
;
4093 /* Otherwise do it the conventional way. */
4095 #if defined(__i386__) || defined(__x86_64__)
4099 for (temp
= 0x000c0000; temp
< 0x000f0000; temp
+= 0x00001000) {
4101 rom_base
= ioremap(temp
, 65536);
4105 if (!sisfb_check_rom(rom_base
, ivideo
)) {
4110 if ((myrombase
= vmalloc(65536)))
4111 memcpy_fromio(myrombase
, rom_base
, 65536);
4124 static void sisfb_post_map_vram(struct sis_video_info
*ivideo
,
4125 unsigned int *mapsize
, unsigned int min
)
4127 if (*mapsize
< (min
<< 20))
4130 ivideo
->video_vbase
= ioremap_wc(ivideo
->video_base
, (*mapsize
));
4132 if(!ivideo
->video_vbase
) {
4134 "sisfb: Unable to map maximum video RAM for size detection\n");
4136 while((!(ivideo
->video_vbase
= ioremap_wc(ivideo
->video_base
, (*mapsize
))))) {
4138 if((*mapsize
) < (min
<< 20))
4141 if(ivideo
->video_vbase
) {
4143 "sisfb: Video RAM size detection limited to %dMB\n",
4144 (int)((*mapsize
) >> 20));
4149 #ifdef CONFIG_FB_SIS_300
4150 static int sisfb_post_300_buswidth(struct sis_video_info
*ivideo
)
4152 void __iomem
*FBAddress
= ivideo
->video_vbase
;
4153 unsigned short temp
;
4157 SiS_SetRegAND(SISSR
, 0x15, 0xFB);
4158 SiS_SetRegOR(SISSR
, 0x15, 0x04);
4159 SiS_SetReg(SISSR
, 0x13, 0x00);
4160 SiS_SetReg(SISSR
, 0x14, 0xBF);
4162 for(i
= 0; i
< 2; i
++) {
4164 for(j
= 0; j
< 4; j
++) {
4165 writew(temp
, FBAddress
);
4166 if(readw(FBAddress
) == temp
)
4168 SiS_SetRegOR(SISSR
, 0x3c, 0x01);
4169 reg
= SiS_GetReg(SISSR
, 0x05);
4170 reg
= SiS_GetReg(SISSR
, 0x05);
4171 SiS_SetRegAND(SISSR
, 0x3c, 0xfe);
4172 reg
= SiS_GetReg(SISSR
, 0x05);
4173 reg
= SiS_GetReg(SISSR
, 0x05);
4178 writel(0x01234567L
, FBAddress
);
4179 writel(0x456789ABL
, (FBAddress
+ 4));
4180 writel(0x89ABCDEFL
, (FBAddress
+ 8));
4181 writel(0xCDEF0123L
, (FBAddress
+ 12));
4183 reg
= SiS_GetReg(SISSR
, 0x3b);
4185 if(readl((FBAddress
+ 12)) == 0xCDEF0123L
)
4186 return 4; /* Channel A 128bit */
4189 if(readl((FBAddress
+ 4)) == 0x456789ABL
)
4190 return 2; /* Channel B 64bit */
4192 return 1; /* 32bit */
4195 static const unsigned short SiS_DRAMType
[17][5] = {
4196 {0x0C,0x0A,0x02,0x40,0x39},
4197 {0x0D,0x0A,0x01,0x40,0x48},
4198 {0x0C,0x09,0x02,0x20,0x35},
4199 {0x0D,0x09,0x01,0x20,0x44},
4200 {0x0C,0x08,0x02,0x10,0x31},
4201 {0x0D,0x08,0x01,0x10,0x40},
4202 {0x0C,0x0A,0x01,0x20,0x34},
4203 {0x0C,0x09,0x01,0x08,0x32},
4204 {0x0B,0x08,0x02,0x08,0x21},
4205 {0x0C,0x08,0x01,0x08,0x30},
4206 {0x0A,0x08,0x02,0x04,0x11},
4207 {0x0B,0x0A,0x01,0x10,0x28},
4208 {0x09,0x08,0x02,0x02,0x01},
4209 {0x0B,0x09,0x01,0x08,0x24},
4210 {0x0B,0x08,0x01,0x04,0x20},
4211 {0x0A,0x08,0x01,0x02,0x10},
4212 {0x09,0x08,0x01,0x01,0x00}
4215 static int sisfb_post_300_rwtest(struct sis_video_info
*ivideo
, int iteration
,
4216 int buswidth
, int PseudoRankCapacity
,
4217 int PseudoAdrPinCount
, unsigned int mapsize
)
4219 void __iomem
*FBAddr
= ivideo
->video_vbase
;
4220 unsigned short sr14
;
4221 unsigned int k
, RankCapacity
, PageCapacity
, BankNumHigh
, BankNumMid
;
4222 unsigned int PhysicalAdrOtherPage
, PhysicalAdrHigh
, PhysicalAdrHalfPage
;
4224 for(k
= 0; k
< ARRAY_SIZE(SiS_DRAMType
); k
++) {
4226 RankCapacity
= buswidth
* SiS_DRAMType
[k
][3];
4228 if(RankCapacity
!= PseudoRankCapacity
)
4231 if((SiS_DRAMType
[k
][2] + SiS_DRAMType
[k
][0]) > PseudoAdrPinCount
)
4234 BankNumHigh
= RankCapacity
* 16 * iteration
- 1;
4235 if(iteration
== 3) { /* Rank No */
4236 BankNumMid
= RankCapacity
* 16 - 1;
4238 BankNumMid
= RankCapacity
* 16 * iteration
/ 2 - 1;
4241 PageCapacity
= (1 << SiS_DRAMType
[k
][1]) * buswidth
* 4;
4242 PhysicalAdrHigh
= BankNumHigh
;
4243 PhysicalAdrHalfPage
= (PageCapacity
/ 2 + PhysicalAdrHigh
) % PageCapacity
;
4244 PhysicalAdrOtherPage
= PageCapacity
* SiS_DRAMType
[k
][2] + PhysicalAdrHigh
;
4246 SiS_SetRegAND(SISSR
, 0x15, 0xFB); /* Test */
4247 SiS_SetRegOR(SISSR
, 0x15, 0x04); /* Test */
4248 sr14
= (SiS_DRAMType
[k
][3] * buswidth
) - 1;
4249 if(buswidth
== 4) sr14
|= 0x80;
4250 else if(buswidth
== 2) sr14
|= 0x40;
4251 SiS_SetReg(SISSR
, 0x13, SiS_DRAMType
[k
][4]);
4252 SiS_SetReg(SISSR
, 0x14, sr14
);
4257 if((BankNumHigh
+ PhysicalAdrHigh
>= mapsize
) ||
4258 (BankNumMid
+ PhysicalAdrHigh
>= mapsize
) ||
4259 (BankNumHigh
+ PhysicalAdrHalfPage
>= mapsize
) ||
4260 (BankNumHigh
+ PhysicalAdrOtherPage
>= mapsize
))
4264 writew(((unsigned short)PhysicalAdrHigh
),
4265 (FBAddr
+ BankNumHigh
+ PhysicalAdrHigh
));
4266 writew(((unsigned short)BankNumMid
),
4267 (FBAddr
+ BankNumMid
+ PhysicalAdrHigh
));
4268 writew(((unsigned short)PhysicalAdrHalfPage
),
4269 (FBAddr
+ BankNumHigh
+ PhysicalAdrHalfPage
));
4270 writew(((unsigned short)PhysicalAdrOtherPage
),
4271 (FBAddr
+ BankNumHigh
+ PhysicalAdrOtherPage
));
4274 if(readw(FBAddr
+ BankNumHigh
+ PhysicalAdrHigh
) == PhysicalAdrHigh
)
4281 static void sisfb_post_300_ramsize(struct pci_dev
*pdev
, unsigned int mapsize
)
4283 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4285 int PseudoRankCapacity
, PseudoAdrPinCount
;
4287 buswidth
= sisfb_post_300_buswidth(ivideo
);
4289 for(i
= 6; i
>= 0; i
--) {
4290 PseudoRankCapacity
= 1 << i
;
4291 for(j
= 4; j
>= 1; j
--) {
4292 PseudoAdrPinCount
= 15 - j
;
4293 if((PseudoRankCapacity
* j
) <= 64) {
4294 if(sisfb_post_300_rwtest(ivideo
,
4306 static void sisfb_post_sis300(struct pci_dev
*pdev
)
4308 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4309 unsigned char *bios
= ivideo
->SiS_Pr
.VirtualRomBase
;
4310 u8 reg
, v1
, v2
, v3
, v4
, v5
, v6
, v7
, v8
;
4311 u16 index
, rindex
, memtype
= 0;
4312 unsigned int mapsize
;
4314 if(!ivideo
->SiS_Pr
.UseROM
)
4317 SiS_SetReg(SISSR
, 0x05, 0x86);
4320 if(bios
[0x52] & 0x80) {
4321 memtype
= bios
[0x52];
4323 memtype
= SiS_GetReg(SISSR
, 0x3a);
4328 v3
= 0x80; v6
= 0x80;
4329 if(ivideo
->revision_id
<= 0x13) {
4330 v1
= 0x44; v2
= 0x42;
4331 v4
= 0x44; v5
= 0x42;
4333 v1
= 0x68; v2
= 0x43; /* Assume 125Mhz MCLK */
4334 v4
= 0x68; v5
= 0x43; /* Assume 125Mhz ECLK */
4336 index
= memtype
* 5;
4337 rindex
= index
+ 0x54;
4338 v1
= bios
[rindex
++];
4339 v2
= bios
[rindex
++];
4340 v3
= bios
[rindex
++];
4341 rindex
= index
+ 0x7c;
4342 v4
= bios
[rindex
++];
4343 v5
= bios
[rindex
++];
4344 v6
= bios
[rindex
++];
4347 SiS_SetReg(SISSR
, 0x28, v1
);
4348 SiS_SetReg(SISSR
, 0x29, v2
);
4349 SiS_SetReg(SISSR
, 0x2a, v3
);
4350 SiS_SetReg(SISSR
, 0x2e, v4
);
4351 SiS_SetReg(SISSR
, 0x2f, v5
);
4352 SiS_SetReg(SISSR
, 0x30, v6
);
4357 SiS_SetReg(SISSR
, 0x07, v1
); /* DAC speed */
4359 SiS_SetReg(SISSR
, 0x11, 0x0f); /* DDC, power save */
4361 v1
= 0x01; v2
= 0x43; v3
= 0x1e; v4
= 0x2a;
4362 v5
= 0x06; v6
= 0x00; v7
= 0x00; v8
= 0x00;
4366 v2
= bios
[memtype
+ 8];
4367 v3
= bios
[memtype
+ 16];
4368 v4
= bios
[memtype
+ 24];
4369 v5
= bios
[memtype
+ 32];
4370 v6
= bios
[memtype
+ 40];
4371 v7
= bios
[memtype
+ 48];
4372 v8
= bios
[memtype
+ 56];
4374 if(ivideo
->revision_id
>= 0x80)
4376 SiS_SetReg(SISSR
, 0x15, v1
); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4377 SiS_SetReg(SISSR
, 0x16, v2
);
4378 SiS_SetReg(SISSR
, 0x17, v3
);
4379 SiS_SetReg(SISSR
, 0x18, v4
);
4380 SiS_SetReg(SISSR
, 0x19, v5
);
4381 SiS_SetReg(SISSR
, 0x1a, v6
);
4382 SiS_SetReg(SISSR
, 0x1b, v7
);
4383 SiS_SetReg(SISSR
, 0x1c, v8
); /* ---- */
4384 SiS_SetRegAND(SISSR
, 0x15, 0xfb);
4385 SiS_SetRegOR(SISSR
, 0x15, 0x04);
4387 if(bios
[0x53] & 0x02) {
4388 SiS_SetRegOR(SISSR
, 0x19, 0x20);
4391 v1
= 0x04; /* DAC pedestal (BIOS 0xe5) */
4392 if(ivideo
->revision_id
>= 0x80)
4394 SiS_SetReg(SISSR
, 0x1f, v1
);
4395 SiS_SetReg(SISSR
, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
4396 v1
= 0xf6; v2
= 0x0d; v3
= 0x00;
4402 SiS_SetReg(SISSR
, 0x23, v1
);
4403 SiS_SetReg(SISSR
, 0x24, v2
);
4404 SiS_SetReg(SISSR
, 0x25, v3
);
4405 SiS_SetReg(SISSR
, 0x21, 0x84);
4406 SiS_SetReg(SISSR
, 0x22, 0x00);
4407 SiS_SetReg(SISCR
, 0x37, 0x00);
4408 SiS_SetRegOR(SISPART1
, 0x24, 0x01); /* unlock crt2 */
4409 SiS_SetReg(SISPART1
, 0x00, 0x00);
4410 v1
= 0x40; v2
= 0x11;
4415 SiS_SetReg(SISPART1
, 0x02, v1
);
4417 if(ivideo
->revision_id
>= 0x80)
4420 reg
= SiS_GetReg(SISPART4
, 0x00);
4421 if((reg
== 1) || (reg
== 2)) {
4422 SiS_SetReg(SISCR
, 0x37, 0x02);
4423 SiS_SetReg(SISPART2
, 0x00, 0x1c);
4424 v4
= 0x00; v5
= 0x00; v6
= 0x10;
4425 if(ivideo
->SiS_Pr
.UseROM
) {
4430 SiS_SetReg(SISPART4
, 0x0d, v4
);
4431 SiS_SetReg(SISPART4
, 0x0e, v5
);
4432 SiS_SetReg(SISPART4
, 0x10, v6
);
4433 SiS_SetReg(SISPART4
, 0x0f, 0x3f);
4434 reg
= SiS_GetReg(SISPART4
, 0x01);
4436 reg
= SiS_GetReg(SISPART4
, 0x23);
4439 SiS_SetReg(SISPART4
, 0x23, reg
);
4444 SiS_SetReg(SISSR
, 0x32, v2
);
4446 SiS_SetRegAND(SISPART1
, 0x24, 0xfe); /* Lock CRT2 */
4448 reg
= SiS_GetReg(SISSR
, 0x16);
4450 SiS_SetReg(SISCR
, 0x35, reg
);
4451 SiS_SetReg(SISCR
, 0x83, 0x00);
4452 #if !defined(__i386__) && !defined(__x86_64__)
4453 if(sisfb_videoram
) {
4454 SiS_SetReg(SISSR
, 0x13, 0x28); /* ? */
4455 reg
= ((sisfb_videoram
>> 10) - 1) | 0x40;
4456 SiS_SetReg(SISSR
, 0x14, reg
);
4459 /* Need to map max FB size for finding out about RAM size */
4460 mapsize
= ivideo
->video_size
;
4461 sisfb_post_map_vram(ivideo
, &mapsize
, 4);
4463 if(ivideo
->video_vbase
) {
4464 sisfb_post_300_ramsize(pdev
, mapsize
);
4465 iounmap(ivideo
->video_vbase
);
4468 "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4469 SiS_SetReg(SISSR
, 0x13, 0x28); /* ? */
4470 SiS_SetReg(SISSR
, 0x14, 0x47); /* 8MB, 64bit default */
4472 #if !defined(__i386__) && !defined(__x86_64__)
4479 reg
= SiS_GetReg(SISSR
, 0x3a);
4480 if((reg
& 0x30) == 0x30) {
4481 v1
= 0x04; /* PCI */
4484 v1
= 0x14; /* AGP */
4488 SiS_SetReg(SISSR
, 0x21, v1
);
4489 SiS_SetReg(SISSR
, 0x22, v2
);
4492 sisfb_sense_crt1(ivideo
);
4494 /* Set default mode, don't clear screen */
4495 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
4496 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
4497 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
4498 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
4499 ivideo
->SiS_Pr
.VideoMemorySize
= 8 << 20;
4500 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
4502 SiS_SetReg(SISSR
, 0x05, 0x86);
4505 SiS_SetRegOR(SISSR
, 0x01, 0x20);
4507 /* Save mode number in CR34 */
4508 SiS_SetReg(SISCR
, 0x34, 0x2e);
4510 /* Let everyone know what the current mode is */
4511 ivideo
->modeprechange
= 0x2e;
4515 #ifdef CONFIG_FB_SIS_315
4517 static void sisfb_post_sis315330(struct pci_dev
*pdev
)
4523 static inline int sisfb_xgi_is21(struct sis_video_info
*ivideo
)
4525 return ivideo
->chip_real_id
== XGI_21
;
4528 static void sisfb_post_xgi_delay(struct sis_video_info
*ivideo
, int delay
)
4533 for(i
= 0; i
<= (delay
* 10 * 36); i
++) {
4534 reg
= SiS_GetReg(SISSR
, 0x05);
4539 static int sisfb_find_host_bridge(struct sis_video_info
*ivideo
,
4540 struct pci_dev
*mypdev
,
4541 unsigned short pcivendor
)
4543 struct pci_dev
*pdev
= NULL
;
4544 unsigned short temp
;
4547 while((pdev
= pci_get_class(PCI_CLASS_BRIDGE_HOST
, pdev
))) {
4548 temp
= pdev
->vendor
;
4549 if(temp
== pcivendor
) {
4559 static int sisfb_post_xgi_rwtest(struct sis_video_info
*ivideo
, int starta
,
4560 unsigned int enda
, unsigned int mapsize
)
4565 writel(0, ivideo
->video_vbase
);
4567 for(i
= starta
; i
<= enda
; i
++) {
4570 writel(pos
, ivideo
->video_vbase
+ pos
);
4573 sisfb_post_xgi_delay(ivideo
, 150);
4575 if(readl(ivideo
->video_vbase
) != 0)
4578 for(i
= starta
; i
<= enda
; i
++) {
4581 if(readl(ivideo
->video_vbase
+ pos
) != pos
)
4590 static int sisfb_post_xgi_ramsize(struct sis_video_info
*ivideo
)
4592 unsigned int buswidth
, ranksize
, channelab
, mapsize
;
4593 int i
, j
, k
, l
, status
;
4595 static const u8 dramsr13
[12 * 5] = {
4596 0x02, 0x0e, 0x0b, 0x80, 0x5d,
4597 0x02, 0x0e, 0x0a, 0x40, 0x59,
4598 0x02, 0x0d, 0x0b, 0x40, 0x4d,
4599 0x02, 0x0e, 0x09, 0x20, 0x55,
4600 0x02, 0x0d, 0x0a, 0x20, 0x49,
4601 0x02, 0x0c, 0x0b, 0x20, 0x3d,
4602 0x02, 0x0e, 0x08, 0x10, 0x51,
4603 0x02, 0x0d, 0x09, 0x10, 0x45,
4604 0x02, 0x0c, 0x0a, 0x10, 0x39,
4605 0x02, 0x0d, 0x08, 0x08, 0x41,
4606 0x02, 0x0c, 0x09, 0x08, 0x35,
4607 0x02, 0x0c, 0x08, 0x04, 0x31
4609 static const u8 dramsr13_4
[4 * 5] = {
4610 0x02, 0x0d, 0x09, 0x40, 0x45,
4611 0x02, 0x0c, 0x09, 0x20, 0x35,
4612 0x02, 0x0c, 0x08, 0x10, 0x31,
4613 0x02, 0x0b, 0x08, 0x08, 0x21
4616 /* Enable linear mode, disable 0xa0000 address decoding */
4617 /* We disable a0000 address decoding, because
4618 * - if running on x86, if the card is disabled, it means
4619 * that another card is in the system. We don't want
4620 * to interphere with that primary card's textmode.
4621 * - if running on non-x86, there usually is no VGA window
4624 SiS_SetRegOR(SISSR
, 0x20, (0x80 | 0x04));
4626 /* Need to map max FB size for finding out about RAM size */
4627 mapsize
= ivideo
->video_size
;
4628 sisfb_post_map_vram(ivideo
, &mapsize
, 32);
4630 if(!ivideo
->video_vbase
) {
4631 printk(KERN_ERR
"sisfb: Unable to detect RAM size. Setting default.\n");
4632 SiS_SetReg(SISSR
, 0x13, 0x35);
4633 SiS_SetReg(SISSR
, 0x14, 0x41);
4638 /* Non-interleaving */
4639 SiS_SetReg(SISSR
, 0x15, 0x00);
4641 SiS_SetReg(SISSR
, 0x1c, 0x00);
4643 if(ivideo
->chip
== XGI_20
) {
4646 reg
= SiS_GetReg(SISCR
, 0x97);
4647 if(!(reg
& 0x01)) { /* Single 32/16 */
4649 SiS_SetReg(SISSR
, 0x13, 0xb1);
4650 SiS_SetReg(SISSR
, 0x14, 0x52);
4651 sisfb_post_xgi_delay(ivideo
, 1);
4653 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4656 SiS_SetReg(SISSR
, 0x13, 0x31);
4657 SiS_SetReg(SISSR
, 0x14, 0x42);
4658 sisfb_post_xgi_delay(ivideo
, 1);
4659 if(sisfb_post_xgi_rwtest(ivideo
, 23, 23, mapsize
))
4663 SiS_SetReg(SISSR
, 0x13, 0xb1);
4664 SiS_SetReg(SISSR
, 0x14, 0x41);
4665 sisfb_post_xgi_delay(ivideo
, 1);
4667 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4670 SiS_SetReg(SISSR
, 0x13, 0x31);
4671 } else { /* Dual 16/8 */
4673 SiS_SetReg(SISSR
, 0x13, 0xb1);
4674 SiS_SetReg(SISSR
, 0x14, 0x41);
4675 sisfb_post_xgi_delay(ivideo
, 1);
4677 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4680 SiS_SetReg(SISSR
, 0x13, 0x31);
4681 SiS_SetReg(SISSR
, 0x14, 0x31);
4682 sisfb_post_xgi_delay(ivideo
, 1);
4683 if(sisfb_post_xgi_rwtest(ivideo
, 22, 22, mapsize
))
4687 SiS_SetReg(SISSR
, 0x13, 0xb1);
4688 SiS_SetReg(SISSR
, 0x14, 0x30);
4689 sisfb_post_xgi_delay(ivideo
, 1);
4691 if(sisfb_post_xgi_rwtest(ivideo
, 21, 22, mapsize
))
4694 SiS_SetReg(SISSR
, 0x13, 0x31);
4697 } else { /* XGI_40 */
4699 reg
= SiS_GetReg(SISCR
, 0x97);
4701 reg
= SiS_GetReg(SISSR
, 0x39);
4705 if(reg
& 0x01) { /* DDRII */
4707 if(ivideo
->revision_id
== 2) {
4709 SiS_SetReg(SISSR
, 0x13, 0xa1);
4710 SiS_SetReg(SISSR
, 0x14, 0x44);
4712 sisfb_post_xgi_delay(ivideo
, 1);
4713 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4716 SiS_SetReg(SISSR
, 0x13, 0x21);
4717 SiS_SetReg(SISSR
, 0x14, 0x34);
4718 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4722 SiS_SetReg(SISSR
, 0x13, 0xa1);
4723 SiS_SetReg(SISSR
, 0x14, 0x40);
4725 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4728 SiS_SetReg(SISSR
, 0x13, 0x21);
4729 SiS_SetReg(SISSR
, 0x14, 0x30);
4732 SiS_SetReg(SISSR
, 0x13, 0xa1);
4733 SiS_SetReg(SISSR
, 0x14, 0x4c);
4735 sisfb_post_xgi_delay(ivideo
, 1);
4736 if(sisfb_post_xgi_rwtest(ivideo
, 23, 25, mapsize
))
4740 SiS_SetReg(SISSR
, 0x14, 0x48);
4741 sisfb_post_xgi_delay(ivideo
, 1);
4743 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4746 SiS_SetReg(SISSR
, 0x13, 0x21);
4747 SiS_SetReg(SISSR
, 0x14, 0x3c);
4750 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
)) {
4754 SiS_SetReg(SISSR
, 0x14, 0x38);
4758 sisfb_post_xgi_delay(ivideo
, 1);
4763 if(ivideo
->revision_id
== 2) {
4765 SiS_SetReg(SISSR
, 0x13, 0xa1);
4766 SiS_SetReg(SISSR
, 0x14, 0x52);
4767 sisfb_post_xgi_delay(ivideo
, 1);
4769 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4772 SiS_SetReg(SISSR
, 0x13, 0x21);
4773 SiS_SetReg(SISSR
, 0x14, 0x42);
4776 SiS_SetReg(SISSR
, 0x13, 0xa1);
4777 SiS_SetReg(SISSR
, 0x14, 0x5a);
4778 sisfb_post_xgi_delay(ivideo
, 1);
4780 if(sisfb_post_xgi_rwtest(ivideo
, 24, 25, mapsize
))
4783 SiS_SetReg(SISSR
, 0x13, 0x21);
4784 SiS_SetReg(SISSR
, 0x14, 0x4a);
4786 sisfb_post_xgi_delay(ivideo
, 1);
4792 SiS_SetRegANDOR(SISSR
, 0x14, 0xf0, sr14
);
4793 sisfb_post_xgi_delay(ivideo
, 1);
4795 j
= (ivideo
->chip
== XGI_20
) ? 5 : 9;
4796 k
= (ivideo
->chip
== XGI_20
) ? 12 : 4;
4799 for(i
= 0; i
< k
; i
++) {
4801 reg
= (ivideo
->chip
== XGI_20
) ?
4802 dramsr13
[(i
* 5) + 4] : dramsr13_4
[(i
* 5) + 4];
4803 SiS_SetRegANDOR(SISSR
, 0x13, 0x80, reg
);
4804 sisfb_post_xgi_delay(ivideo
, 50);
4806 ranksize
= (ivideo
->chip
== XGI_20
) ?
4807 dramsr13
[(i
* 5) + 3] : dramsr13_4
[(i
* 5) + 3];
4809 reg
= SiS_GetReg(SISSR
, 0x13);
4810 if(reg
& 0x80) ranksize
<<= 1;
4812 if(ivideo
->chip
== XGI_20
) {
4813 if(buswidth
== 16) ranksize
<<= 1;
4814 else if(buswidth
== 32) ranksize
<<= 2;
4816 if(buswidth
== 64) ranksize
<<= 1;
4822 if((ranksize
* l
) <= 256) {
4823 while((ranksize
>>= 1)) reg
+= 0x10;
4828 SiS_SetRegANDOR(SISSR
, 0x14, 0x0f, (reg
& 0xf0));
4829 sisfb_post_xgi_delay(ivideo
, 1);
4831 if (sisfb_post_xgi_rwtest(ivideo
, j
, ((reg
>> 4) + channelab
- 2 + 20), mapsize
)) {
4837 iounmap(ivideo
->video_vbase
);
4842 static void sisfb_post_xgi_setclocks(struct sis_video_info
*ivideo
, u8 regb
)
4846 static const u8 cs90
[8 * 3] = {
4856 static const u8 csb8
[8 * 3] = {
4870 v1
= cs90
[index
]; v2
= cs90
[index
+ 1]; v3
= cs90
[index
+ 2];
4871 if(ivideo
->haveXGIROM
) {
4872 v1
= ivideo
->bios_abase
[0x90 + index
];
4873 v2
= ivideo
->bios_abase
[0x90 + index
+ 1];
4874 v3
= ivideo
->bios_abase
[0x90 + index
+ 2];
4876 SiS_SetReg(SISSR
, 0x28, v1
);
4877 SiS_SetReg(SISSR
, 0x29, v2
);
4878 SiS_SetReg(SISSR
, 0x2a, v3
);
4879 sisfb_post_xgi_delay(ivideo
, 0x43);
4880 sisfb_post_xgi_delay(ivideo
, 0x43);
4881 sisfb_post_xgi_delay(ivideo
, 0x43);
4883 v1
= csb8
[index
]; v2
= csb8
[index
+ 1]; v3
= csb8
[index
+ 2];
4884 if(ivideo
->haveXGIROM
) {
4885 v1
= ivideo
->bios_abase
[0xb8 + index
];
4886 v2
= ivideo
->bios_abase
[0xb8 + index
+ 1];
4887 v3
= ivideo
->bios_abase
[0xb8 + index
+ 2];
4889 SiS_SetReg(SISSR
, 0x2e, v1
);
4890 SiS_SetReg(SISSR
, 0x2f, v2
);
4891 SiS_SetReg(SISSR
, 0x30, v3
);
4892 sisfb_post_xgi_delay(ivideo
, 0x43);
4893 sisfb_post_xgi_delay(ivideo
, 0x43);
4894 sisfb_post_xgi_delay(ivideo
, 0x43);
4897 static void sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info
*ivideo
,
4900 unsigned char *bios
= ivideo
->bios_abase
;
4903 SiS_SetReg(SISSR
, 0x28, 0x64);
4904 SiS_SetReg(SISSR
, 0x29, 0x63);
4905 sisfb_post_xgi_delay(ivideo
, 15);
4906 SiS_SetReg(SISSR
, 0x18, 0x00);
4907 SiS_SetReg(SISSR
, 0x19, 0x20);
4908 SiS_SetReg(SISSR
, 0x16, 0x00);
4909 SiS_SetReg(SISSR
, 0x16, 0x80);
4910 SiS_SetReg(SISSR
, 0x18, 0xc5);
4911 SiS_SetReg(SISSR
, 0x19, 0x23);
4912 SiS_SetReg(SISSR
, 0x16, 0x00);
4913 SiS_SetReg(SISSR
, 0x16, 0x80);
4914 sisfb_post_xgi_delay(ivideo
, 1);
4915 SiS_SetReg(SISCR
, 0x97, 0x11);
4916 sisfb_post_xgi_setclocks(ivideo
, regb
);
4917 sisfb_post_xgi_delay(ivideo
, 0x46);
4918 SiS_SetReg(SISSR
, 0x18, 0xc5);
4919 SiS_SetReg(SISSR
, 0x19, 0x23);
4920 SiS_SetReg(SISSR
, 0x16, 0x00);
4921 SiS_SetReg(SISSR
, 0x16, 0x80);
4922 sisfb_post_xgi_delay(ivideo
, 1);
4923 SiS_SetReg(SISSR
, 0x1b, 0x04);
4924 sisfb_post_xgi_delay(ivideo
, 1);
4925 SiS_SetReg(SISSR
, 0x1b, 0x00);
4926 sisfb_post_xgi_delay(ivideo
, 1);
4928 if (ivideo
->haveXGIROM
) {
4931 SiS_SetReg(SISSR
, 0x18, v1
);
4932 SiS_SetReg(SISSR
, 0x19, 0x06);
4933 SiS_SetReg(SISSR
, 0x16, 0x04);
4934 SiS_SetReg(SISSR
, 0x16, 0x84);
4935 sisfb_post_xgi_delay(ivideo
, 1);
4938 static void sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info
*ivideo
)
4940 sisfb_post_xgi_setclocks(ivideo
, 1);
4942 SiS_SetReg(SISCR
, 0x97, 0x11);
4943 sisfb_post_xgi_delay(ivideo
, 0x46);
4945 SiS_SetReg(SISSR
, 0x18, 0x00); /* EMRS2 */
4946 SiS_SetReg(SISSR
, 0x19, 0x80);
4947 SiS_SetReg(SISSR
, 0x16, 0x05);
4948 SiS_SetReg(SISSR
, 0x16, 0x85);
4950 SiS_SetReg(SISSR
, 0x18, 0x00); /* EMRS3 */
4951 SiS_SetReg(SISSR
, 0x19, 0xc0);
4952 SiS_SetReg(SISSR
, 0x16, 0x05);
4953 SiS_SetReg(SISSR
, 0x16, 0x85);
4955 SiS_SetReg(SISSR
, 0x18, 0x00); /* EMRS1 */
4956 SiS_SetReg(SISSR
, 0x19, 0x40);
4957 SiS_SetReg(SISSR
, 0x16, 0x05);
4958 SiS_SetReg(SISSR
, 0x16, 0x85);
4960 SiS_SetReg(SISSR
, 0x18, 0x42); /* MRS1 */
4961 SiS_SetReg(SISSR
, 0x19, 0x02);
4962 SiS_SetReg(SISSR
, 0x16, 0x05);
4963 SiS_SetReg(SISSR
, 0x16, 0x85);
4964 sisfb_post_xgi_delay(ivideo
, 1);
4966 SiS_SetReg(SISSR
, 0x1b, 0x04);
4967 sisfb_post_xgi_delay(ivideo
, 1);
4969 SiS_SetReg(SISSR
, 0x1b, 0x00);
4970 sisfb_post_xgi_delay(ivideo
, 1);
4972 SiS_SetReg(SISSR
, 0x18, 0x42); /* MRS1 */
4973 SiS_SetReg(SISSR
, 0x19, 0x00);
4974 SiS_SetReg(SISSR
, 0x16, 0x05);
4975 SiS_SetReg(SISSR
, 0x16, 0x85);
4976 sisfb_post_xgi_delay(ivideo
, 1);
4979 static void sisfb_post_xgi_ddr2(struct sis_video_info
*ivideo
, u8 regb
)
4981 unsigned char *bios
= ivideo
->bios_abase
;
4982 static const u8 cs158
[8] = {
4983 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
4985 static const u8 cs160
[8] = {
4986 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
4988 static const u8 cs168
[8] = {
4989 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
4996 SiS_SetReg(SISCR
, 0xb0, 0x80); /* DDR2 dual frequency mode */
4997 SiS_SetReg(SISCR
, 0x82, 0x77);
4998 SiS_SetReg(SISCR
, 0x86, 0x00);
4999 reg
= SiS_GetReg(SISCR
, 0x86);
5000 SiS_SetReg(SISCR
, 0x86, 0x88);
5001 reg
= SiS_GetReg(SISCR
, 0x86);
5002 v1
= cs168
[regb
]; v2
= cs160
[regb
]; v3
= cs158
[regb
];
5003 if (ivideo
->haveXGIROM
) {
5004 v1
= bios
[regb
+ 0x168];
5005 v2
= bios
[regb
+ 0x160];
5006 v3
= bios
[regb
+ 0x158];
5008 SiS_SetReg(SISCR
, 0x86, v1
);
5009 SiS_SetReg(SISCR
, 0x82, 0x77);
5010 SiS_SetReg(SISCR
, 0x85, 0x00);
5011 reg
= SiS_GetReg(SISCR
, 0x85);
5012 SiS_SetReg(SISCR
, 0x85, 0x88);
5013 reg
= SiS_GetReg(SISCR
, 0x85);
5014 SiS_SetReg(SISCR
, 0x85, v2
);
5015 SiS_SetReg(SISCR
, 0x82, v3
);
5016 SiS_SetReg(SISCR
, 0x98, 0x01);
5017 SiS_SetReg(SISCR
, 0x9a, 0x02);
5018 if (sisfb_xgi_is21(ivideo
))
5019 sisfb_post_xgi_ddr2_mrs_xg21(ivideo
);
5021 sisfb_post_xgi_ddr2_mrs_default(ivideo
, regb
);
5024 static u8
sisfb_post_xgi_ramtype(struct sis_video_info
*ivideo
)
5026 unsigned char *bios
= ivideo
->bios_abase
;
5031 ramtype
= 0x00; v1
= 0x10;
5032 if (ivideo
->haveXGIROM
) {
5033 ramtype
= bios
[0x62];
5036 if (!(ramtype
& 0x80)) {
5037 if (sisfb_xgi_is21(ivideo
)) {
5038 SiS_SetRegAND(SISCR
, 0xb4, 0xfd); /* GPIO control */
5039 SiS_SetRegOR(SISCR
, 0x4a, 0x80); /* GPIOH EN */
5040 reg
= SiS_GetReg(SISCR
, 0x48);
5041 SiS_SetRegOR(SISCR
, 0xb4, 0x02);
5042 ramtype
= reg
& 0x01; /* GPIOH */
5043 } else if (ivideo
->chip
== XGI_20
) {
5044 SiS_SetReg(SISCR
, 0x97, v1
);
5045 reg
= SiS_GetReg(SISCR
, 0x97);
5047 ramtype
= (reg
& 0x01) << 1;
5050 reg
= SiS_GetReg(SISSR
, 0x39);
5051 ramtype
= reg
& 0x02;
5053 reg
= SiS_GetReg(SISSR
, 0x3a);
5054 ramtype
= (reg
>> 1) & 0x01;
5063 static int sisfb_post_xgi(struct pci_dev
*pdev
)
5065 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
5066 unsigned char *bios
= ivideo
->bios_abase
;
5067 struct pci_dev
*mypdev
= NULL
;
5068 const u8
*ptr
, *ptr2
;
5069 u8 v1
, v2
, v3
, v4
, v5
, reg
, ramtype
;
5070 u32 rega
, regb
, regd
;
5072 static const u8 cs78
[3] = { 0xf6, 0x0d, 0x00 };
5073 static const u8 cs76
[2] = { 0xa3, 0xfb };
5074 static const u8 cs7b
[3] = { 0xc0, 0x11, 0x00 };
5075 static const u8 cs158
[8] = {
5076 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5078 static const u8 cs160
[8] = {
5079 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5081 static const u8 cs168
[8] = {
5082 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5084 static const u8 cs128
[3 * 8] = {
5085 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
5086 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5087 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
5089 static const u8 cs148
[2 * 8] = {
5090 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
5091 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5093 static const u8 cs31a
[8 * 4] = {
5094 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
5095 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
5096 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5097 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5099 static const u8 cs33a
[8 * 4] = {
5100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5105 static const u8 cs45a
[8 * 2] = {
5106 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
5107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5109 static const u8 cs170
[7 * 8] = {
5110 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5111 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5112 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
5113 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5114 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5115 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5116 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5118 static const u8 cs1a8
[3 * 8] = {
5119 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5120 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5123 static const u8 cs100
[2 * 8] = {
5124 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5125 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5129 reg
= SiS_GetRegByte(SISVGAENABLE
) | 0x01;
5130 SiS_SetRegByte(SISVGAENABLE
, reg
);
5133 reg
= SiS_GetRegByte(SISMISCR
) | 0x01;
5134 SiS_SetRegByte(SISMISCW
, reg
);
5137 SiS_SetReg(SISSR
, 0x05, 0x86);
5138 reg
= SiS_GetReg(SISSR
, 0x05);
5142 /* Clear some regs */
5143 for(i
= 0; i
< 0x22; i
++) {
5144 if(0x06 + i
== 0x20) continue;
5145 SiS_SetReg(SISSR
, 0x06 + i
, 0x00);
5147 for(i
= 0; i
< 0x0b; i
++) {
5148 SiS_SetReg(SISSR
, 0x31 + i
, 0x00);
5150 for(i
= 0; i
< 0x10; i
++) {
5151 SiS_SetReg(SISCR
, 0x30 + i
, 0x00);
5155 if(ivideo
->haveXGIROM
) {
5156 ptr
= (const u8
*)&bios
[0x78];
5158 for(i
= 0; i
< 3; i
++) {
5159 SiS_SetReg(SISSR
, 0x23 + i
, ptr
[i
]);
5163 if(ivideo
->haveXGIROM
) {
5164 ptr
= (const u8
*)&bios
[0x76];
5166 for(i
= 0; i
< 2; i
++) {
5167 SiS_SetReg(SISSR
, 0x21 + i
, ptr
[i
]);
5170 v1
= 0x18; v2
= 0x00;
5171 if(ivideo
->haveXGIROM
) {
5175 SiS_SetReg(SISSR
, 0x07, v1
);
5176 SiS_SetReg(SISSR
, 0x11, 0x0f);
5177 SiS_SetReg(SISSR
, 0x1f, v2
);
5178 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5179 SiS_SetReg(SISSR
, 0x20, 0x80 | 0x20 | 0x04);
5180 SiS_SetReg(SISSR
, 0x27, 0x74);
5183 if(ivideo
->haveXGIROM
) {
5184 ptr
= (const u8
*)&bios
[0x7b];
5186 for(i
= 0; i
< 3; i
++) {
5187 SiS_SetReg(SISSR
, 0x31 + i
, ptr
[i
]);
5190 if(ivideo
->chip
== XGI_40
) {
5191 if(ivideo
->revision_id
== 2) {
5192 SiS_SetRegANDOR(SISSR
, 0x3b, 0x3f, 0xc0);
5194 SiS_SetReg(SISCR
, 0x7d, 0xfe);
5195 SiS_SetReg(SISCR
, 0x7e, 0x0f);
5197 if(ivideo
->revision_id
== 0) { /* 40 *and* 20? */
5198 SiS_SetRegAND(SISCR
, 0x58, 0xd7);
5199 reg
= SiS_GetReg(SISCR
, 0xcb);
5201 SiS_SetRegANDOR(SISCR
, 0x58, 0xd7, (reg
& 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5205 reg
= (ivideo
->chip
== XGI_40
) ? 0x20 : 0x00;
5206 SiS_SetRegANDOR(SISCR
, 0x38, 0x1f, reg
);
5208 if(ivideo
->chip
== XGI_20
) {
5209 SiS_SetReg(SISSR
, 0x36, 0x70);
5211 SiS_SetReg(SISVID
, 0x00, 0x86);
5212 SiS_SetReg(SISVID
, 0x32, 0x00);
5213 SiS_SetReg(SISVID
, 0x30, 0x00);
5214 SiS_SetReg(SISVID
, 0x32, 0x01);
5215 SiS_SetReg(SISVID
, 0x30, 0x00);
5216 SiS_SetRegAND(SISVID
, 0x2f, 0xdf);
5217 SiS_SetRegAND(SISCAP
, 0x00, 0x3f);
5219 SiS_SetReg(SISPART1
, 0x2f, 0x01);
5220 SiS_SetReg(SISPART1
, 0x00, 0x00);
5221 SiS_SetReg(SISPART1
, 0x02, bios
[0x7e]);
5222 SiS_SetReg(SISPART1
, 0x2e, 0x08);
5223 SiS_SetRegAND(SISPART1
, 0x35, 0x7f);
5224 SiS_SetRegAND(SISPART1
, 0x50, 0xfe);
5226 reg
= SiS_GetReg(SISPART4
, 0x00);
5227 if(reg
== 1 || reg
== 2) {
5228 SiS_SetReg(SISPART2
, 0x00, 0x1c);
5229 SiS_SetReg(SISPART4
, 0x0d, bios
[0x7f]);
5230 SiS_SetReg(SISPART4
, 0x0e, bios
[0x80]);
5231 SiS_SetReg(SISPART4
, 0x10, bios
[0x81]);
5232 SiS_SetRegAND(SISPART4
, 0x0f, 0x3f);
5234 reg
= SiS_GetReg(SISPART4
, 0x01);
5235 if((reg
& 0xf0) >= 0xb0) {
5236 reg
= SiS_GetReg(SISPART4
, 0x23);
5237 if(reg
& 0x20) reg
|= 0x40;
5238 SiS_SetReg(SISPART4
, 0x23, reg
);
5239 reg
= (reg
& 0x20) ? 0x02 : 0x00;
5240 SiS_SetRegANDOR(SISPART1
, 0x1e, 0xfd, reg
);
5246 reg
= SiS_GetReg(SISSR
, 0x3b);
5248 reg
= SiS_GetReg(SISSR
, 0x3a);
5249 v2
= (reg
& 0x30) >> 3;
5250 if(!(v2
& 0x04)) v2
^= 0x02;
5251 reg
= SiS_GetReg(SISSR
, 0x39);
5252 if(reg
& 0x80) v2
|= 0x80;
5255 if((mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0730, NULL
))) {
5256 pci_dev_put(mypdev
);
5257 if(((v2
& 0x06) == 2) || ((v2
& 0x06) == 4))
5262 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0735, NULL
);
5264 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0645, NULL
);
5266 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0650, NULL
);
5268 pci_read_config_dword(mypdev
, 0x94, ®d
);
5270 pci_write_config_dword(mypdev
, 0x94, regd
);
5272 pci_dev_put(mypdev
);
5273 } else if(sisfb_find_host_bridge(ivideo
, pdev
, PCI_VENDOR_ID_SI
)) {
5275 } else if(sisfb_find_host_bridge(ivideo
, pdev
, 0x1106) ||
5276 sisfb_find_host_bridge(ivideo
, pdev
, 0x1022) ||
5277 sisfb_find_host_bridge(ivideo
, pdev
, 0x700e) ||
5278 sisfb_find_host_bridge(ivideo
, pdev
, 0x10de)) {
5279 if((v2
& 0x06) == 4)
5284 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf0, v2
);
5286 SiS_SetReg(SISSR
, 0x22, v1
);
5288 if(ivideo
->revision_id
== 2) {
5289 v1
= SiS_GetReg(SISSR
, 0x3b);
5290 v2
= SiS_GetReg(SISSR
, 0x3a);
5291 regd
= bios
[0x90 + 3] | (bios
[0x90 + 4] << 8);
5292 if( (!(v1
& 0x02)) && (v2
& 0x30) && (regd
< 0xcf) )
5293 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf1, 0x01);
5295 if((mypdev
= pci_get_device(0x10de, 0x01e0, NULL
))) {
5296 /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5300 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf1, 0x01);
5301 pci_dev_put(mypdev
);
5306 reg
= SiS_GetReg(SISSR
, 0x3b);
5307 v2
= SiS_GetReg(SISCR
, 0x5f);
5308 if((!(reg
& 0x02)) && (v2
& 0x0e))
5310 SiS_SetReg(SISSR
, 0x27, v1
);
5312 if(bios
[0x64] & 0x01) {
5313 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf0, bios
[0x64]);
5317 pci_read_config_dword(pdev
, 0x50, ®d
);
5318 regd
= (regd
>> 20) & 0x0f;
5321 SiS_SetRegOR(SISCR
, 0x5f, 0x08);
5323 SiS_SetReg(SISCR
, 0x48, v1
);
5325 SiS_SetRegANDOR(SISCR
, 0x47, 0x04, bios
[0x4f6] & 0xfb);
5326 SiS_SetRegANDOR(SISCR
, 0x49, 0xf0, bios
[0x4f8] & 0x0f);
5327 SiS_SetRegANDOR(SISCR
, 0x4a, 0x60, bios
[0x4f9] & 0x9f);
5328 SiS_SetRegANDOR(SISCR
, 0x4b, 0x08, bios
[0x4fa] & 0xf7);
5329 SiS_SetRegANDOR(SISCR
, 0x4c, 0x80, bios
[0x4fb] & 0x7f);
5330 SiS_SetReg(SISCR
, 0x70, bios
[0x4fc]);
5331 SiS_SetRegANDOR(SISCR
, 0x71, 0xf0, bios
[0x4fd] & 0x0f);
5332 SiS_SetReg(SISCR
, 0x74, 0xd0);
5333 SiS_SetRegANDOR(SISCR
, 0x74, 0xcf, bios
[0x4fe] & 0x30);
5334 SiS_SetRegANDOR(SISCR
, 0x75, 0xe0, bios
[0x4ff] & 0x1f);
5335 SiS_SetRegANDOR(SISCR
, 0x76, 0xe0, bios
[0x500] & 0x1f);
5337 if((mypdev
= pci_get_device(0x8086, 0x2530, NULL
))) {
5339 pci_dev_put(mypdev
);
5341 SiS_SetReg(SISCR
, 0x77, v1
);
5346 * 0 == DDR1, 1 == DDR2, 2..7 == reserved?
5348 * The code seems to written so that regb should equal ramtype,
5349 * however, so far it has been hardcoded to 0. Enable other values only
5350 * on XGI Z9, as it passes the POST, and add a warning for others.
5352 ramtype
= sisfb_post_xgi_ramtype(ivideo
);
5353 if (!sisfb_xgi_is21(ivideo
) && ramtype
) {
5354 dev_warn(&pdev
->dev
,
5355 "RAM type something else than expected: %d\n",
5363 if(ivideo
->haveXGIROM
) {
5364 v1
= bios
[0x140 + regb
];
5366 SiS_SetReg(SISCR
, 0x6d, v1
);
5369 if(ivideo
->haveXGIROM
) {
5370 ptr
= (const u8
*)&bios
[0x128];
5372 for(i
= 0, j
= 0; i
< 3; i
++, j
+= 8) {
5373 SiS_SetReg(SISCR
, 0x68 + i
, ptr
[j
+ regb
]);
5378 if(ivideo
->haveXGIROM
) {
5379 index
= (ivideo
->chip
== XGI_20
) ? 0x31a : 0x3a6;
5380 ptr
= (const u8
*)&bios
[index
];
5381 ptr2
= (const u8
*)&bios
[index
+ 0x20];
5383 for(i
= 0; i
< 2; i
++) {
5385 regd
= le32_to_cpu(((u32
*)ptr
)[regb
]);
5388 regd
= le32_to_cpu(((u32
*)ptr2
)[regb
]);
5392 for(j
= 0; j
< 16; j
++) {
5394 if(regd
& 0x01) reg
|= 0x04;
5395 if(regd
& 0x02) reg
|= 0x08;
5397 SiS_SetReg(SISCR
, rega
, reg
);
5398 reg
= SiS_GetReg(SISCR
, rega
);
5399 reg
= SiS_GetReg(SISCR
, rega
);
5404 SiS_SetRegAND(SISCR
, 0x6e, 0xfc);
5407 if(ivideo
->haveXGIROM
) {
5408 index
= (ivideo
->chip
== XGI_20
) ? 0x35a : 0x3e6;
5409 ptr
= (const u8
*)&bios
[index
];
5411 for(i
= 0; i
< 4; i
++) {
5412 SiS_SetRegANDOR(SISCR
, 0x6e, 0xfc, i
);
5414 for(j
= 0; j
< 2; j
++) {
5417 regd
= le32_to_cpu(((u32
*)ptr
)[regb
* 8]);
5421 for(k
= 0; k
< 16; k
++) {
5423 if(regd
& 0x01) reg
|= 0x01;
5424 if(regd
& 0x02) reg
|= 0x02;
5426 SiS_SetReg(SISCR
, 0x6f, reg
);
5427 reg
= SiS_GetReg(SISCR
, 0x6f);
5428 reg
= SiS_GetReg(SISCR
, 0x6f);
5435 if(ivideo
->haveXGIROM
) {
5436 ptr
= (const u8
*)&bios
[0x148];
5438 for(i
= 0, j
= 0; i
< 2; i
++, j
+= 8) {
5439 SiS_SetReg(SISCR
, 0x80 + i
, ptr
[j
+ regb
]);
5442 SiS_SetRegAND(SISCR
, 0x89, 0x8f);
5445 if(ivideo
->haveXGIROM
) {
5446 index
= (ivideo
->chip
== XGI_20
) ? 0x45a : 0x4e6;
5447 ptr
= (const u8
*)&bios
[index
];
5449 regd
= le16_to_cpu(((const u16
*)ptr
)[regb
]);
5451 for(i
= 0; i
< 5; i
++) {
5453 if(regd
& 0x01) reg
|= 0x01;
5454 if(regd
& 0x02) reg
|= 0x02;
5456 SiS_SetReg(SISCR
, 0x89, reg
);
5457 reg
= SiS_GetReg(SISCR
, 0x89);
5458 reg
= SiS_GetReg(SISCR
, 0x89);
5462 v1
= 0xb5; v2
= 0x20; v3
= 0xf0; v4
= 0x13;
5463 if(ivideo
->haveXGIROM
) {
5464 v1
= bios
[0x118 + regb
];
5465 v2
= bios
[0xf8 + regb
];
5466 v3
= bios
[0x120 + regb
];
5469 SiS_SetReg(SISCR
, 0x45, v1
& 0x0f);
5470 SiS_SetReg(SISCR
, 0x99, (v1
>> 4) & 0x07);
5471 SiS_SetRegOR(SISCR
, 0x40, v1
& 0x80);
5472 SiS_SetReg(SISCR
, 0x41, v2
);
5475 if(ivideo
->haveXGIROM
) {
5476 ptr
= (const u8
*)&bios
[0x170];
5478 for(i
= 0, j
= 0; i
< 7; i
++, j
+= 8) {
5479 SiS_SetReg(SISCR
, 0x90 + i
, ptr
[j
+ regb
]);
5482 SiS_SetReg(SISCR
, 0x59, v3
);
5485 if(ivideo
->haveXGIROM
) {
5486 ptr
= (const u8
*)&bios
[0x1a8];
5488 for(i
= 0, j
= 0; i
< 3; i
++, j
+= 8) {
5489 SiS_SetReg(SISCR
, 0xc3 + i
, ptr
[j
+ regb
]);
5493 if(ivideo
->haveXGIROM
) {
5494 ptr
= (const u8
*)&bios
[0x100];
5496 for(i
= 0, j
= 0; i
< 2; i
++, j
+= 8) {
5497 SiS_SetReg(SISCR
, 0x8a + i
, ptr
[j
+ regb
]);
5500 SiS_SetReg(SISCR
, 0xcf, v4
);
5502 SiS_SetReg(SISCR
, 0x83, 0x09);
5503 SiS_SetReg(SISCR
, 0x87, 0x00);
5505 if(ivideo
->chip
== XGI_40
) {
5506 if( (ivideo
->revision_id
== 1) ||
5507 (ivideo
->revision_id
== 2) ) {
5508 SiS_SetReg(SISCR
, 0x8c, 0x87);
5513 SiS_SetReg(SISSR
, 0x17, 0x80); /* DDR2 */
5515 SiS_SetReg(SISSR
, 0x17, 0x00); /* DDR1 */
5516 SiS_SetReg(SISSR
, 0x1a, 0x87);
5518 if(ivideo
->chip
== XGI_20
) {
5519 SiS_SetReg(SISSR
, 0x15, 0x00);
5520 SiS_SetReg(SISSR
, 0x1c, 0x00);
5525 sisfb_post_xgi_setclocks(ivideo
, regb
);
5526 if((ivideo
->chip
== XGI_20
) ||
5527 (ivideo
->revision_id
== 1) ||
5528 (ivideo
->revision_id
== 2)) {
5529 v1
= cs158
[regb
]; v2
= cs160
[regb
]; v3
= cs168
[regb
];
5530 if(ivideo
->haveXGIROM
) {
5531 v1
= bios
[regb
+ 0x158];
5532 v2
= bios
[regb
+ 0x160];
5533 v3
= bios
[regb
+ 0x168];
5535 SiS_SetReg(SISCR
, 0x82, v1
);
5536 SiS_SetReg(SISCR
, 0x85, v2
);
5537 SiS_SetReg(SISCR
, 0x86, v3
);
5539 SiS_SetReg(SISCR
, 0x82, 0x88);
5540 SiS_SetReg(SISCR
, 0x86, 0x00);
5541 reg
= SiS_GetReg(SISCR
, 0x86);
5542 SiS_SetReg(SISCR
, 0x86, 0x88);
5543 reg
= SiS_GetReg(SISCR
, 0x86);
5544 SiS_SetReg(SISCR
, 0x86, bios
[regb
+ 0x168]);
5545 SiS_SetReg(SISCR
, 0x82, 0x77);
5546 SiS_SetReg(SISCR
, 0x85, 0x00);
5547 reg
= SiS_GetReg(SISCR
, 0x85);
5548 SiS_SetReg(SISCR
, 0x85, 0x88);
5549 reg
= SiS_GetReg(SISCR
, 0x85);
5550 SiS_SetReg(SISCR
, 0x85, bios
[regb
+ 0x160]);
5551 SiS_SetReg(SISCR
, 0x82, bios
[regb
+ 0x158]);
5553 if(ivideo
->chip
== XGI_40
) {
5554 SiS_SetReg(SISCR
, 0x97, 0x00);
5556 SiS_SetReg(SISCR
, 0x98, 0x01);
5557 SiS_SetReg(SISCR
, 0x9a, 0x02);
5559 SiS_SetReg(SISSR
, 0x18, 0x01);
5560 if((ivideo
->chip
== XGI_20
) ||
5561 (ivideo
->revision_id
== 2)) {
5562 SiS_SetReg(SISSR
, 0x19, 0x40);
5564 SiS_SetReg(SISSR
, 0x19, 0x20);
5566 SiS_SetReg(SISSR
, 0x16, 0x00);
5567 SiS_SetReg(SISSR
, 0x16, 0x80);
5568 if((ivideo
->chip
== XGI_20
) || (bios
[0x1cb] != 0x0c)) {
5569 sisfb_post_xgi_delay(ivideo
, 0x43);
5570 sisfb_post_xgi_delay(ivideo
, 0x43);
5571 sisfb_post_xgi_delay(ivideo
, 0x43);
5572 SiS_SetReg(SISSR
, 0x18, 0x00);
5573 if((ivideo
->chip
== XGI_20
) ||
5574 (ivideo
->revision_id
== 2)) {
5575 SiS_SetReg(SISSR
, 0x19, 0x40);
5577 SiS_SetReg(SISSR
, 0x19, 0x20);
5579 } else if((ivideo
->chip
== XGI_40
) && (bios
[0x1cb] == 0x0c)) {
5580 /* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
5582 SiS_SetReg(SISSR
, 0x16, 0x00);
5583 SiS_SetReg(SISSR
, 0x16, 0x80);
5584 sisfb_post_xgi_delay(ivideo
, 4);
5585 v1
= 0x31; v2
= 0x03; v3
= 0x83; v4
= 0x03; v5
= 0x83;
5586 if(ivideo
->haveXGIROM
) {
5588 index
= (ivideo
->chip
== XGI_20
) ? 0x4b2 : 0x53e;
5590 v3
= bios
[index
+ 1];
5591 v4
= bios
[index
+ 2];
5592 v5
= bios
[index
+ 3];
5594 SiS_SetReg(SISSR
, 0x18, v1
);
5595 SiS_SetReg(SISSR
, 0x19, ((ivideo
->chip
== XGI_20
) ? 0x02 : 0x01));
5596 SiS_SetReg(SISSR
, 0x16, v2
);
5597 SiS_SetReg(SISSR
, 0x16, v3
);
5598 sisfb_post_xgi_delay(ivideo
, 0x43);
5599 SiS_SetReg(SISSR
, 0x1b, 0x03);
5600 sisfb_post_xgi_delay(ivideo
, 0x22);
5601 SiS_SetReg(SISSR
, 0x18, v1
);
5602 SiS_SetReg(SISSR
, 0x19, 0x00);
5603 SiS_SetReg(SISSR
, 0x16, v4
);
5604 SiS_SetReg(SISSR
, 0x16, v5
);
5605 SiS_SetReg(SISSR
, 0x1b, 0x00);
5608 sisfb_post_xgi_ddr2(ivideo
, regb
);
5611 sisfb_post_xgi_setclocks(ivideo
, regb
);
5612 if((ivideo
->chip
== XGI_40
) &&
5613 ((ivideo
->revision_id
== 1) ||
5614 (ivideo
->revision_id
== 2))) {
5615 SiS_SetReg(SISCR
, 0x82, bios
[regb
+ 0x158]);
5616 SiS_SetReg(SISCR
, 0x85, bios
[regb
+ 0x160]);
5617 SiS_SetReg(SISCR
, 0x86, bios
[regb
+ 0x168]);
5619 SiS_SetReg(SISCR
, 0x82, 0x88);
5620 SiS_SetReg(SISCR
, 0x86, 0x00);
5621 reg
= SiS_GetReg(SISCR
, 0x86);
5622 SiS_SetReg(SISCR
, 0x86, 0x88);
5623 SiS_SetReg(SISCR
, 0x82, 0x77);
5624 SiS_SetReg(SISCR
, 0x85, 0x00);
5625 reg
= SiS_GetReg(SISCR
, 0x85);
5626 SiS_SetReg(SISCR
, 0x85, 0x88);
5627 reg
= SiS_GetReg(SISCR
, 0x85);
5628 v1
= cs160
[regb
]; v2
= cs158
[regb
];
5629 if(ivideo
->haveXGIROM
) {
5630 v1
= bios
[regb
+ 0x160];
5631 v2
= bios
[regb
+ 0x158];
5633 SiS_SetReg(SISCR
, 0x85, v1
);
5634 SiS_SetReg(SISCR
, 0x82, v2
);
5636 if(ivideo
->chip
== XGI_40
) {
5637 SiS_SetReg(SISCR
, 0x97, 0x11);
5639 if((ivideo
->chip
== XGI_40
) && (ivideo
->revision_id
== 2)) {
5640 SiS_SetReg(SISCR
, 0x98, 0x01);
5642 SiS_SetReg(SISCR
, 0x98, 0x03);
5644 SiS_SetReg(SISCR
, 0x9a, 0x02);
5646 if(ivideo
->chip
== XGI_40
) {
5647 SiS_SetReg(SISSR
, 0x18, 0x01);
5649 SiS_SetReg(SISSR
, 0x18, 0x00);
5651 SiS_SetReg(SISSR
, 0x19, 0x40);
5652 SiS_SetReg(SISSR
, 0x16, 0x00);
5653 SiS_SetReg(SISSR
, 0x16, 0x80);
5654 if((ivideo
->chip
== XGI_40
) && (bios
[0x1cb] != 0x0c)) {
5655 sisfb_post_xgi_delay(ivideo
, 0x43);
5656 sisfb_post_xgi_delay(ivideo
, 0x43);
5657 sisfb_post_xgi_delay(ivideo
, 0x43);
5658 SiS_SetReg(SISSR
, 0x18, 0x00);
5659 SiS_SetReg(SISSR
, 0x19, 0x40);
5660 SiS_SetReg(SISSR
, 0x16, 0x00);
5661 SiS_SetReg(SISSR
, 0x16, 0x80);
5663 sisfb_post_xgi_delay(ivideo
, 4);
5665 if(ivideo
->haveXGIROM
) {
5668 SiS_SetReg(SISSR
, 0x18, v1
);
5669 SiS_SetReg(SISSR
, 0x19, 0x01);
5670 if(ivideo
->chip
== XGI_40
) {
5671 SiS_SetReg(SISSR
, 0x16, bios
[0x53e]);
5672 SiS_SetReg(SISSR
, 0x16, bios
[0x53f]);
5674 SiS_SetReg(SISSR
, 0x16, 0x05);
5675 SiS_SetReg(SISSR
, 0x16, 0x85);
5677 sisfb_post_xgi_delay(ivideo
, 0x43);
5678 if(ivideo
->chip
== XGI_40
) {
5679 SiS_SetReg(SISSR
, 0x1b, 0x01);
5681 SiS_SetReg(SISSR
, 0x1b, 0x03);
5683 sisfb_post_xgi_delay(ivideo
, 0x22);
5684 SiS_SetReg(SISSR
, 0x18, v1
);
5685 SiS_SetReg(SISSR
, 0x19, 0x00);
5686 if(ivideo
->chip
== XGI_40
) {
5687 SiS_SetReg(SISSR
, 0x16, bios
[0x540]);
5688 SiS_SetReg(SISSR
, 0x16, bios
[0x541]);
5690 SiS_SetReg(SISSR
, 0x16, 0x05);
5691 SiS_SetReg(SISSR
, 0x16, 0x85);
5693 SiS_SetReg(SISSR
, 0x1b, 0x00);
5698 if(ivideo
->haveXGIROM
) {
5699 v1
= bios
[0x110 + regb
];
5701 SiS_SetReg(SISSR
, 0x1b, v1
);
5704 v1
= 0x00; v2
= 0x00;
5705 if(ivideo
->haveXGIROM
) {
5711 if((v1
& 0x40) && (v2
& regd
) && ivideo
->haveXGIROM
) {
5713 SiS_SetReg(SISSR
, 0x13, bios
[regb
+ 0xe0]);
5714 SiS_SetReg(SISSR
, 0x14, bios
[regb
+ 0xe0 + 8]);
5719 /* Set default mode, don't clear screen */
5720 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
5721 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
5722 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
5723 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
5724 ivideo
->SiS_Pr
.VideoMemorySize
= 8 << 20;
5725 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
5727 SiS_SetReg(SISSR
, 0x05, 0x86);
5729 /* Disable read-cache */
5730 SiS_SetRegAND(SISSR
, 0x21, 0xdf);
5731 err
= sisfb_post_xgi_ramsize(ivideo
);
5732 /* Enable read-cache */
5733 SiS_SetRegOR(SISSR
, 0x21, 0x20);
5737 "%s: RAM size detection failed: %d\n",
5744 printk(KERN_DEBUG
"-----------------\n");
5745 for(i
= 0; i
< 0xff; i
++) {
5746 reg
= SiS_GetReg(SISCR
, i
);
5747 printk(KERN_DEBUG
"CR%02x(%x) = 0x%02x\n", i
, SISCR
, reg
);
5749 for(i
= 0; i
< 0x40; i
++) {
5750 reg
= SiS_GetReg(SISSR
, i
);
5751 printk(KERN_DEBUG
"SR%02x(%x) = 0x%02x\n", i
, SISSR
, reg
);
5753 printk(KERN_DEBUG
"-----------------\n");
5757 if(ivideo
->chip
== XGI_20
) {
5758 SiS_SetRegOR(SISCR
, 0x32, 0x20);
5760 reg
= SiS_GetReg(SISPART4
, 0x00);
5761 if((reg
== 1) || (reg
== 2)) {
5762 sisfb_sense_crt1(ivideo
);
5764 SiS_SetRegOR(SISCR
, 0x32, 0x20);
5768 /* Set default mode, don't clear screen */
5769 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
5770 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
5771 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
5772 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
5773 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
5775 SiS_SetReg(SISSR
, 0x05, 0x86);
5778 SiS_SetRegOR(SISSR
, 0x01, 0x20);
5780 /* Save mode number in CR34 */
5781 SiS_SetReg(SISCR
, 0x34, 0x2e);
5783 /* Let everyone know what the current mode is */
5784 ivideo
->modeprechange
= 0x2e;
5786 if(ivideo
->chip
== XGI_40
) {
5787 reg
= SiS_GetReg(SISCR
, 0xca);
5788 v1
= SiS_GetReg(SISCR
, 0xcc);
5789 if((reg
& 0x10) && (!(v1
& 0x04))) {
5791 "sisfb: Please connect power to the card.\n");
5800 static int sisfb_probe(struct pci_dev
*pdev
, const struct pci_device_id
*ent
)
5802 struct sisfb_chip_info
*chipinfo
= &sisfb_chip_info
[ent
->driver_data
];
5803 struct sis_video_info
*ivideo
= NULL
;
5804 struct fb_info
*sis_fb_info
= NULL
;
5812 sis_fb_info
= framebuffer_alloc(sizeof(*ivideo
), &pdev
->dev
);
5816 ivideo
= (struct sis_video_info
*)sis_fb_info
->par
;
5817 ivideo
->memyselfandi
= sis_fb_info
;
5819 ivideo
->sisfb_id
= SISFB_ID
;
5821 if(card_list
== NULL
) {
5822 ivideo
->cardnumber
= 0;
5824 struct sis_video_info
*countvideo
= card_list
;
5825 ivideo
->cardnumber
= 1;
5826 while((countvideo
= countvideo
->next
) != NULL
)
5827 ivideo
->cardnumber
++;
5830 strlcpy(ivideo
->myid
, chipinfo
->chip_name
, sizeof(ivideo
->myid
));
5832 ivideo
->warncount
= 0;
5833 ivideo
->chip_id
= pdev
->device
;
5834 ivideo
->chip_vendor
= pdev
->vendor
;
5835 ivideo
->revision_id
= pdev
->revision
;
5836 ivideo
->SiS_Pr
.ChipRevision
= ivideo
->revision_id
;
5837 pci_read_config_word(pdev
, PCI_COMMAND
, ®16
);
5838 ivideo
->sisvga_enabled
= reg16
& 0x01;
5839 ivideo
->pcibus
= pdev
->bus
->number
;
5840 ivideo
->pcislot
= PCI_SLOT(pdev
->devfn
);
5841 ivideo
->pcifunc
= PCI_FUNC(pdev
->devfn
);
5842 ivideo
->subsysvendor
= pdev
->subsystem_vendor
;
5843 ivideo
->subsysdevice
= pdev
->subsystem_device
;
5846 if(sisfb_mode_idx
== -1) {
5847 sisfb_get_vga_mode_from_kernel();
5851 ivideo
->chip
= chipinfo
->chip
;
5852 ivideo
->chip_real_id
= chipinfo
->chip
;
5853 ivideo
->sisvga_engine
= chipinfo
->vgaengine
;
5854 ivideo
->hwcursor_size
= chipinfo
->hwcursor_size
;
5855 ivideo
->CRT2_write_enable
= chipinfo
->CRT2_write_enable
;
5856 ivideo
->mni
= chipinfo
->mni
;
5858 ivideo
->detectedpdc
= 0xff;
5859 ivideo
->detectedpdca
= 0xff;
5860 ivideo
->detectedlcda
= 0xff;
5862 ivideo
->sisfb_thismonitor
.datavalid
= false;
5864 ivideo
->current_base
= 0;
5866 ivideo
->engineok
= 0;
5868 ivideo
->sisfb_was_boot_device
= 0;
5870 if(pdev
->resource
[PCI_ROM_RESOURCE
].flags
& IORESOURCE_ROM_SHADOW
) {
5871 if(ivideo
->sisvga_enabled
)
5872 ivideo
->sisfb_was_boot_device
= 1;
5874 printk(KERN_DEBUG
"sisfb: PCI device is disabled, "
5875 "but marked as boot video device ???\n");
5876 printk(KERN_DEBUG
"sisfb: I will not accept this "
5877 "as the primary VGA device\n");
5881 ivideo
->sisfb_parm_mem
= sisfb_parm_mem
;
5882 ivideo
->sisfb_accel
= sisfb_accel
;
5883 ivideo
->sisfb_ypan
= sisfb_ypan
;
5884 ivideo
->sisfb_max
= sisfb_max
;
5885 ivideo
->sisfb_userom
= sisfb_userom
;
5886 ivideo
->sisfb_useoem
= sisfb_useoem
;
5887 ivideo
->sisfb_mode_idx
= sisfb_mode_idx
;
5888 ivideo
->sisfb_parm_rate
= sisfb_parm_rate
;
5889 ivideo
->sisfb_crt1off
= sisfb_crt1off
;
5890 ivideo
->sisfb_forcecrt1
= sisfb_forcecrt1
;
5891 ivideo
->sisfb_crt2type
= sisfb_crt2type
;
5892 ivideo
->sisfb_crt2flags
= sisfb_crt2flags
;
5893 /* pdc(a), scalelcd, special timing, lvdshl handled below */
5894 ivideo
->sisfb_dstn
= sisfb_dstn
;
5895 ivideo
->sisfb_fstn
= sisfb_fstn
;
5896 ivideo
->sisfb_tvplug
= sisfb_tvplug
;
5897 ivideo
->sisfb_tvstd
= sisfb_tvstd
;
5898 ivideo
->tvxpos
= sisfb_tvxposoffset
;
5899 ivideo
->tvypos
= sisfb_tvyposoffset
;
5900 ivideo
->sisfb_nocrt2rate
= sisfb_nocrt2rate
;
5901 ivideo
->refresh_rate
= 0;
5902 if(ivideo
->sisfb_parm_rate
!= -1) {
5903 ivideo
->refresh_rate
= ivideo
->sisfb_parm_rate
;
5906 ivideo
->SiS_Pr
.UsePanelScaler
= sisfb_scalelcd
;
5907 ivideo
->SiS_Pr
.CenterScreen
= -1;
5908 ivideo
->SiS_Pr
.SiS_CustomT
= sisfb_specialtiming
;
5909 ivideo
->SiS_Pr
.LVDSHL
= sisfb_lvdshl
;
5911 ivideo
->SiS_Pr
.SiS_Backup70xx
= 0xff;
5912 ivideo
->SiS_Pr
.SiS_CHOverScan
= -1;
5913 ivideo
->SiS_Pr
.SiS_ChSW
= false;
5914 ivideo
->SiS_Pr
.SiS_UseLCDA
= false;
5915 ivideo
->SiS_Pr
.HaveEMI
= false;
5916 ivideo
->SiS_Pr
.HaveEMILCD
= false;
5917 ivideo
->SiS_Pr
.OverruleEMI
= false;
5918 ivideo
->SiS_Pr
.SiS_SensibleSR11
= false;
5919 ivideo
->SiS_Pr
.SiS_MyCR63
= 0x63;
5920 ivideo
->SiS_Pr
.PDC
= -1;
5921 ivideo
->SiS_Pr
.PDCA
= -1;
5922 ivideo
->SiS_Pr
.DDCPortMixup
= false;
5923 #ifdef CONFIG_FB_SIS_315
5924 if(ivideo
->chip
>= SIS_330
) {
5925 ivideo
->SiS_Pr
.SiS_MyCR63
= 0x53;
5926 if(ivideo
->chip
>= SIS_661
) {
5927 ivideo
->SiS_Pr
.SiS_SensibleSR11
= true;
5932 memcpy(&ivideo
->default_var
, &my_default_var
, sizeof(my_default_var
));
5934 pci_set_drvdata(pdev
, ivideo
);
5936 /* Patch special cases */
5937 if((ivideo
->nbridge
= sisfb_get_northbridge(ivideo
->chip
))) {
5938 switch(ivideo
->nbridge
->device
) {
5939 #ifdef CONFIG_FB_SIS_300
5940 case PCI_DEVICE_ID_SI_730
:
5941 ivideo
->chip
= SIS_730
;
5942 strcpy(ivideo
->myid
, "SiS 730");
5945 #ifdef CONFIG_FB_SIS_315
5946 case PCI_DEVICE_ID_SI_651
:
5947 /* ivideo->chip is ok */
5948 strcpy(ivideo
->myid
, "SiS 651");
5950 case PCI_DEVICE_ID_SI_740
:
5951 ivideo
->chip
= SIS_740
;
5952 strcpy(ivideo
->myid
, "SiS 740");
5954 case PCI_DEVICE_ID_SI_661
:
5955 ivideo
->chip
= SIS_661
;
5956 strcpy(ivideo
->myid
, "SiS 661");
5958 case PCI_DEVICE_ID_SI_741
:
5959 ivideo
->chip
= SIS_741
;
5960 strcpy(ivideo
->myid
, "SiS 741");
5962 case PCI_DEVICE_ID_SI_760
:
5963 ivideo
->chip
= SIS_760
;
5964 strcpy(ivideo
->myid
, "SiS 760");
5966 case PCI_DEVICE_ID_SI_761
:
5967 ivideo
->chip
= SIS_761
;
5968 strcpy(ivideo
->myid
, "SiS 761");
5976 ivideo
->SiS_Pr
.ChipType
= ivideo
->chip
;
5978 ivideo
->SiS_Pr
.ivideo
= (void *)ivideo
;
5980 #ifdef CONFIG_FB_SIS_315
5981 if((ivideo
->SiS_Pr
.ChipType
== SIS_315PRO
) ||
5982 (ivideo
->SiS_Pr
.ChipType
== SIS_315
)) {
5983 ivideo
->SiS_Pr
.ChipType
= SIS_315H
;
5987 if(!ivideo
->sisvga_enabled
) {
5988 if(pci_enable_device(pdev
)) {
5989 pci_dev_put(ivideo
->nbridge
);
5990 framebuffer_release(sis_fb_info
);
5995 ivideo
->video_base
= pci_resource_start(pdev
, 0);
5996 ivideo
->video_size
= pci_resource_len(pdev
, 0);
5997 ivideo
->mmio_base
= pci_resource_start(pdev
, 1);
5998 ivideo
->mmio_size
= pci_resource_len(pdev
, 1);
5999 ivideo
->SiS_Pr
.RelIO
= pci_resource_start(pdev
, 2) + 0x30;
6000 ivideo
->SiS_Pr
.IOAddress
= ivideo
->vga_base
= ivideo
->SiS_Pr
.RelIO
;
6002 SiSRegInit(&ivideo
->SiS_Pr
, ivideo
->SiS_Pr
.IOAddress
);
6004 #ifdef CONFIG_FB_SIS_300
6005 /* Find PCI systems for Chrontel/GPIO communication setup */
6006 if(ivideo
->chip
== SIS_630
) {
6009 if(mychswtable
[i
].subsysVendor
== ivideo
->subsysvendor
&&
6010 mychswtable
[i
].subsysCard
== ivideo
->subsysdevice
) {
6011 ivideo
->SiS_Pr
.SiS_ChSW
= true;
6012 printk(KERN_DEBUG
"sisfb: Identified [%s %s] "
6013 "requiring Chrontel/GPIO setup\n",
6014 mychswtable
[i
].vendorName
,
6015 mychswtable
[i
].cardName
);
6016 ivideo
->lpcdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0008, NULL
);
6020 } while(mychswtable
[i
].subsysVendor
!= 0);
6024 #ifdef CONFIG_FB_SIS_315
6025 if((ivideo
->chip
== SIS_760
) && (ivideo
->nbridge
)) {
6026 ivideo
->lpcdev
= pci_get_slot(ivideo
->nbridge
->bus
, (2 << 3));
6030 SiS_SetReg(SISSR
, 0x05, 0x86);
6032 if( (!ivideo
->sisvga_enabled
)
6033 #if !defined(__i386__) && !defined(__x86_64__)
6034 || (sisfb_resetcard
)
6037 for(i
= 0x30; i
<= 0x3f; i
++) {
6038 SiS_SetReg(SISCR
, i
, 0x00);
6042 /* Find out about current video mode */
6043 ivideo
->modeprechange
= 0x03;
6044 reg
= SiS_GetReg(SISCR
, 0x34);
6046 ivideo
->modeprechange
= reg
& 0x7f;
6047 } else if(ivideo
->sisvga_enabled
) {
6048 #if defined(__i386__) || defined(__x86_64__)
6049 unsigned char __iomem
*tt
= ioremap(0x400, 0x100);
6051 ivideo
->modeprechange
= readb(tt
+ 0x49);
6057 /* Search and copy ROM image */
6058 ivideo
->bios_abase
= NULL
;
6059 ivideo
->SiS_Pr
.VirtualRomBase
= NULL
;
6060 ivideo
->SiS_Pr
.UseROM
= false;
6061 ivideo
->haveXGIROM
= ivideo
->SiS_Pr
.SiS_XGIROM
= false;
6062 if(ivideo
->sisfb_userom
) {
6063 ivideo
->SiS_Pr
.VirtualRomBase
= sisfb_find_rom(pdev
);
6064 ivideo
->bios_abase
= ivideo
->SiS_Pr
.VirtualRomBase
;
6065 ivideo
->SiS_Pr
.UseROM
= (bool)(ivideo
->SiS_Pr
.VirtualRomBase
);
6066 printk(KERN_INFO
"sisfb: Video ROM %sfound\n",
6067 ivideo
->SiS_Pr
.UseROM
? "" : "not ");
6068 if((ivideo
->SiS_Pr
.UseROM
) && (ivideo
->chip
>= XGI_20
)) {
6069 ivideo
->SiS_Pr
.UseROM
= false;
6070 ivideo
->haveXGIROM
= ivideo
->SiS_Pr
.SiS_XGIROM
= true;
6071 if( (ivideo
->revision_id
== 2) &&
6072 (!(ivideo
->bios_abase
[0x1d1] & 0x01)) ) {
6073 ivideo
->SiS_Pr
.DDCPortMixup
= true;
6077 printk(KERN_INFO
"sisfb: Video ROM usage disabled\n");
6080 /* Find systems for special custom timing */
6081 if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_NONE
) {
6082 sisfb_detect_custom_timing(ivideo
);
6085 #ifdef CONFIG_FB_SIS_315
6086 if (ivideo
->chip
== XGI_20
) {
6087 /* Check if our Z7 chip is actually Z9 */
6088 SiS_SetRegOR(SISCR
, 0x4a, 0x40); /* GPIOG EN */
6089 reg
= SiS_GetReg(SISCR
, 0x48);
6090 if (reg
& 0x02) { /* GPIOG */
6091 ivideo
->chip_real_id
= XGI_21
;
6092 dev_info(&pdev
->dev
, "Z9 detected\n");
6097 /* POST card in case this has not been done by the BIOS */
6098 if( (!ivideo
->sisvga_enabled
)
6099 #if !defined(__i386__) && !defined(__x86_64__)
6100 || (sisfb_resetcard
)
6103 #ifdef CONFIG_FB_SIS_300
6104 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
6105 if(ivideo
->chip
== SIS_300
) {
6106 sisfb_post_sis300(pdev
);
6107 ivideo
->sisfb_can_post
= 1;
6112 #ifdef CONFIG_FB_SIS_315
6113 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
6115 /* if((ivideo->chip == SIS_315H) ||
6116 (ivideo->chip == SIS_315) ||
6117 (ivideo->chip == SIS_315PRO) ||
6118 (ivideo->chip == SIS_330)) {
6119 sisfb_post_sis315330(pdev);
6120 } else */ if(ivideo
->chip
== XGI_20
) {
6121 result
= sisfb_post_xgi(pdev
);
6122 ivideo
->sisfb_can_post
= 1;
6123 } else if((ivideo
->chip
== XGI_40
) && ivideo
->haveXGIROM
) {
6124 result
= sisfb_post_xgi(pdev
);
6125 ivideo
->sisfb_can_post
= 1;
6127 printk(KERN_INFO
"sisfb: Card is not "
6128 "POSTed and sisfb can't do this either.\n");
6131 printk(KERN_ERR
"sisfb: Failed to POST card\n");
6139 ivideo
->sisfb_card_posted
= 1;
6141 /* Find out about RAM size */
6142 if(sisfb_get_dram_size(ivideo
)) {
6143 printk(KERN_INFO
"sisfb: Fatal error: Unable to determine VRAM size.\n");
6149 /* Enable PCI addressing and MMIO */
6150 if((ivideo
->sisfb_mode_idx
< 0) ||
6151 ((sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
]) != 0xFF)) {
6152 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
6153 SiS_SetRegOR(SISSR
, IND_SIS_PCI_ADDRESS_SET
, (SIS_PCI_ADDR_ENABLE
| SIS_MEM_MAP_IO_ENABLE
));
6154 /* Enable 2D accelerator engine */
6155 SiS_SetRegOR(SISSR
, IND_SIS_MODULE_ENABLE
, SIS_ENABLE_2D
);
6158 if(sisfb_pdc
!= 0xff) {
6159 if(ivideo
->sisvga_engine
== SIS_300_VGA
)
6163 ivideo
->SiS_Pr
.PDC
= sisfb_pdc
;
6165 #ifdef CONFIG_FB_SIS_315
6166 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
6167 if(sisfb_pdca
!= 0xff)
6168 ivideo
->SiS_Pr
.PDCA
= sisfb_pdca
& 0x1f;
6172 if(!request_mem_region(ivideo
->video_base
, ivideo
->video_size
, "sisfb FB")) {
6173 printk(KERN_ERR
"sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6174 (int)(ivideo
->video_size
>> 20));
6175 printk(KERN_ERR
"sisfb: Is there another framebuffer driver active?\n");
6180 if(!request_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
, "sisfb MMIO")) {
6181 printk(KERN_ERR
"sisfb: Fatal error: Unable to reserve MMIO region\n");
6186 ivideo
->video_vbase
= ioremap_wc(ivideo
->video_base
, ivideo
->video_size
);
6187 ivideo
->SiS_Pr
.VideoMemoryAddress
= ivideo
->video_vbase
;
6188 if(!ivideo
->video_vbase
) {
6189 printk(KERN_ERR
"sisfb: Fatal error: Unable to map framebuffer memory\n");
6194 ivideo
->mmio_vbase
= ioremap(ivideo
->mmio_base
, ivideo
->mmio_size
);
6195 if(!ivideo
->mmio_vbase
) {
6196 printk(KERN_ERR
"sisfb: Fatal error: Unable to map MMIO region\n");
6198 error_0
: iounmap(ivideo
->video_vbase
);
6199 error_1
: release_mem_region(ivideo
->video_base
, ivideo
->video_size
);
6200 error_2
: release_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
);
6201 error_3
: vfree(ivideo
->bios_abase
);
6202 pci_dev_put(ivideo
->lpcdev
);
6203 pci_dev_put(ivideo
->nbridge
);
6204 if(!ivideo
->sisvga_enabled
)
6205 pci_disable_device(pdev
);
6206 framebuffer_release(sis_fb_info
);
6210 printk(KERN_INFO
"sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
6211 ivideo
->video_base
, (unsigned long)ivideo
->video_vbase
, ivideo
->video_size
/ 1024);
6213 if(ivideo
->video_offset
) {
6214 printk(KERN_INFO
"sisfb: Viewport offset %ldk\n",
6215 ivideo
->video_offset
/ 1024);
6218 printk(KERN_INFO
"sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
6219 ivideo
->mmio_base
, (unsigned long)ivideo
->mmio_vbase
, ivideo
->mmio_size
/ 1024);
6222 /* Determine the size of the command queue */
6223 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
6224 ivideo
->cmdQueueSize
= TURBO_QUEUE_AREA_SIZE
;
6226 if(ivideo
->chip
== XGI_20
) {
6227 ivideo
->cmdQueueSize
= COMMAND_QUEUE_AREA_SIZE_Z7
;
6229 ivideo
->cmdQueueSize
= COMMAND_QUEUE_AREA_SIZE
;
6233 /* Engines are no longer initialized here; this is
6234 * now done after the first mode-switch (if the
6235 * submitted var has its acceleration flags set).
6238 /* Calculate the base of the (unused) hw cursor */
6239 ivideo
->hwcursor_vbase
= ivideo
->video_vbase
6240 + ivideo
->video_size
6241 - ivideo
->cmdQueueSize
6242 - ivideo
->hwcursor_size
;
6243 ivideo
->caps
|= HW_CURSOR_CAP
;
6245 /* Initialize offscreen memory manager */
6246 if((ivideo
->havenoheap
= sisfb_heap_init(ivideo
))) {
6247 printk(KERN_WARNING
"sisfb: Failed to initialize offscreen memory heap\n");
6250 /* Used for clearing the screen only, therefore respect our mem limit */
6251 ivideo
->SiS_Pr
.VideoMemoryAddress
+= ivideo
->video_offset
;
6252 ivideo
->SiS_Pr
.VideoMemorySize
= ivideo
->sisfb_mem
;
6254 ivideo
->vbflags
= 0;
6255 ivideo
->lcddefmodeidx
= DEFAULT_LCDMODE
;
6256 ivideo
->tvdefmodeidx
= DEFAULT_TVMODE
;
6257 ivideo
->defmodeidx
= DEFAULT_MODE
;
6260 if(ivideo
->chip
< XGI_20
) {
6261 if(ivideo
->bios_abase
) {
6262 ivideo
->newrom
= SiSDetermineROMLayout661(&ivideo
->SiS_Pr
);
6266 if((ivideo
->sisfb_mode_idx
< 0) ||
6267 ((sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
]) != 0xFF)) {
6269 sisfb_sense_crt1(ivideo
);
6271 sisfb_get_VB_type(ivideo
);
6273 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
6274 sisfb_detect_VB_connect(ivideo
);
6277 ivideo
->currentvbflags
= ivideo
->vbflags
& (VB_VIDEOBRIDGE
| TV_STANDARD
);
6279 /* Decide on which CRT2 device to use */
6280 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
6281 if(ivideo
->sisfb_crt2type
!= -1) {
6282 if((ivideo
->sisfb_crt2type
== CRT2_LCD
) &&
6283 (ivideo
->vbflags
& CRT2_LCD
)) {
6284 ivideo
->currentvbflags
|= CRT2_LCD
;
6285 } else if(ivideo
->sisfb_crt2type
!= CRT2_LCD
) {
6286 ivideo
->currentvbflags
|= ivideo
->sisfb_crt2type
;
6289 /* Chrontel 700x TV detection often unreliable, therefore
6290 * use a different default order on such machines
6292 if((ivideo
->sisvga_engine
== SIS_300_VGA
) &&
6293 (ivideo
->vbflags2
& VB2_CHRONTEL
)) {
6294 if(ivideo
->vbflags
& CRT2_LCD
)
6295 ivideo
->currentvbflags
|= CRT2_LCD
;
6296 else if(ivideo
->vbflags
& CRT2_TV
)
6297 ivideo
->currentvbflags
|= CRT2_TV
;
6298 else if(ivideo
->vbflags
& CRT2_VGA
)
6299 ivideo
->currentvbflags
|= CRT2_VGA
;
6301 if(ivideo
->vbflags
& CRT2_TV
)
6302 ivideo
->currentvbflags
|= CRT2_TV
;
6303 else if(ivideo
->vbflags
& CRT2_LCD
)
6304 ivideo
->currentvbflags
|= CRT2_LCD
;
6305 else if(ivideo
->vbflags
& CRT2_VGA
)
6306 ivideo
->currentvbflags
|= CRT2_VGA
;
6311 if(ivideo
->vbflags
& CRT2_LCD
) {
6312 sisfb_detect_lcd_type(ivideo
);
6315 sisfb_save_pdc_emi(ivideo
);
6317 if(!ivideo
->sisfb_crt1off
) {
6318 sisfb_handle_ddc(ivideo
, &ivideo
->sisfb_thismonitor
, 0);
6320 if((ivideo
->vbflags2
& VB2_SISTMDSBRIDGE
) &&
6321 (ivideo
->vbflags
& (CRT2_VGA
| CRT2_LCD
))) {
6322 sisfb_handle_ddc(ivideo
, &ivideo
->sisfb_thismonitor
, 1);
6326 if(ivideo
->sisfb_mode_idx
>= 0) {
6327 int bu
= ivideo
->sisfb_mode_idx
;
6328 ivideo
->sisfb_mode_idx
= sisfb_validate_mode(ivideo
,
6329 ivideo
->sisfb_mode_idx
, ivideo
->currentvbflags
);
6330 if(bu
!= ivideo
->sisfb_mode_idx
) {
6331 printk(KERN_ERR
"Mode %dx%dx%d failed validation\n",
6332 sisbios_mode
[bu
].xres
,
6333 sisbios_mode
[bu
].yres
,
6334 sisbios_mode
[bu
].bpp
);
6338 if(ivideo
->sisfb_mode_idx
< 0) {
6339 switch(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
6341 ivideo
->sisfb_mode_idx
= ivideo
->lcddefmodeidx
;
6344 ivideo
->sisfb_mode_idx
= ivideo
->tvdefmodeidx
;
6347 ivideo
->sisfb_mode_idx
= ivideo
->defmodeidx
;
6352 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
6354 if(ivideo
->refresh_rate
!= 0) {
6355 sisfb_search_refresh_rate(ivideo
, ivideo
->refresh_rate
,
6356 ivideo
->sisfb_mode_idx
);
6359 if(ivideo
->rate_idx
== 0) {
6360 ivideo
->rate_idx
= sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
;
6361 ivideo
->refresh_rate
= 60;
6364 if(ivideo
->sisfb_thismonitor
.datavalid
) {
6365 if(!sisfb_verify_rate(ivideo
, &ivideo
->sisfb_thismonitor
,
6366 ivideo
->sisfb_mode_idx
,
6368 ivideo
->refresh_rate
)) {
6369 printk(KERN_INFO
"sisfb: WARNING: Refresh rate "
6370 "exceeds monitor specs!\n");
6374 ivideo
->video_bpp
= sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
;
6375 ivideo
->video_width
= sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
;
6376 ivideo
->video_height
= sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
;
6378 sisfb_set_vparms(ivideo
);
6380 printk(KERN_INFO
"sisfb: Default mode is %dx%dx%d (%dHz)\n",
6381 ivideo
->video_width
, ivideo
->video_height
, ivideo
->video_bpp
,
6382 ivideo
->refresh_rate
);
6384 /* Set up the default var according to chosen default display mode */
6385 ivideo
->default_var
.xres
= ivideo
->default_var
.xres_virtual
= ivideo
->video_width
;
6386 ivideo
->default_var
.yres
= ivideo
->default_var
.yres_virtual
= ivideo
->video_height
;
6387 ivideo
->default_var
.bits_per_pixel
= ivideo
->video_bpp
;
6389 sisfb_bpp_to_var(ivideo
, &ivideo
->default_var
);
6391 ivideo
->default_var
.pixclock
= (u32
) (1000000000 /
6392 sisfb_mode_rate_to_dclock(&ivideo
->SiS_Pr
, ivideo
->mode_no
, ivideo
->rate_idx
));
6394 if(sisfb_mode_rate_to_ddata(&ivideo
->SiS_Pr
, ivideo
->mode_no
,
6395 ivideo
->rate_idx
, &ivideo
->default_var
)) {
6396 if((ivideo
->default_var
.vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
6397 ivideo
->default_var
.pixclock
<<= 1;
6401 if(ivideo
->sisfb_ypan
) {
6402 /* Maximize regardless of sisfb_max at startup */
6403 ivideo
->default_var
.yres_virtual
=
6404 sisfb_calc_maxyres(ivideo
, &ivideo
->default_var
);
6405 if(ivideo
->default_var
.yres_virtual
< ivideo
->default_var
.yres
) {
6406 ivideo
->default_var
.yres_virtual
= ivideo
->default_var
.yres
;
6410 sisfb_calc_pitch(ivideo
, &ivideo
->default_var
);
6413 if(ivideo
->sisfb_accel
) {
6415 #ifdef STUPID_ACCELF_TEXT_SHIT
6416 ivideo
->default_var
.accel_flags
|= FB_ACCELF_TEXT
;
6419 sisfb_initaccel(ivideo
);
6421 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
6422 sis_fb_info
->flags
= FBINFO_DEFAULT
|
6423 FBINFO_HWACCEL_YPAN
|
6424 FBINFO_HWACCEL_XPAN
|
6425 FBINFO_HWACCEL_COPYAREA
|
6426 FBINFO_HWACCEL_FILLRECT
|
6427 ((ivideo
->accel
) ? 0 : FBINFO_HWACCEL_DISABLED
);
6429 sis_fb_info
->flags
= FBINFO_FLAG_DEFAULT
;
6431 sis_fb_info
->var
= ivideo
->default_var
;
6432 sis_fb_info
->fix
= ivideo
->sisfb_fix
;
6433 sis_fb_info
->screen_base
= ivideo
->video_vbase
+ ivideo
->video_offset
;
6434 sis_fb_info
->fbops
= &sisfb_ops
;
6435 sis_fb_info
->pseudo_palette
= ivideo
->pseudo_palette
;
6437 fb_alloc_cmap(&sis_fb_info
->cmap
, 256 , 0);
6439 printk(KERN_DEBUG
"sisfb: Initial vbflags 0x%x\n", (int)ivideo
->vbflags
);
6441 ivideo
->wc_cookie
= arch_phys_wc_add(ivideo
->video_base
,
6442 ivideo
->video_size
);
6443 if(register_framebuffer(sis_fb_info
) < 0) {
6444 printk(KERN_ERR
"sisfb: Fatal error: Failed to register framebuffer\n");
6446 iounmap(ivideo
->mmio_vbase
);
6450 ivideo
->registered
= 1;
6453 ivideo
->next
= card_list
;
6456 printk(KERN_INFO
"sisfb: 2D acceleration is %s, y-panning %s\n",
6457 ivideo
->sisfb_accel
? "enabled" : "disabled",
6458 ivideo
->sisfb_ypan
?
6459 (ivideo
->sisfb_max
? "enabled (auto-max)" :
6460 "enabled (no auto-max)") :
6464 fb_info(sis_fb_info
, "%s frame buffer device version %d.%d.%d\n",
6465 ivideo
->myid
, VER_MAJOR
, VER_MINOR
, VER_LEVEL
);
6467 printk(KERN_INFO
"sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
6469 } /* if mode = "none" */
6474 /*****************************************************/
6475 /* PCI DEVICE HANDLING */
6476 /*****************************************************/
6478 static void sisfb_remove(struct pci_dev
*pdev
)
6480 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
6481 struct fb_info
*sis_fb_info
= ivideo
->memyselfandi
;
6482 int registered
= ivideo
->registered
;
6483 int modechanged
= ivideo
->modechanged
;
6486 iounmap(ivideo
->mmio_vbase
);
6487 iounmap(ivideo
->video_vbase
);
6489 /* Release mem regions */
6490 release_mem_region(ivideo
->video_base
, ivideo
->video_size
);
6491 release_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
);
6493 vfree(ivideo
->bios_abase
);
6495 pci_dev_put(ivideo
->lpcdev
);
6497 pci_dev_put(ivideo
->nbridge
);
6499 arch_phys_wc_del(ivideo
->wc_cookie
);
6501 /* If device was disabled when starting, disable
6504 if(!ivideo
->sisvga_enabled
)
6505 pci_disable_device(pdev
);
6507 /* Unregister the framebuffer */
6508 if(ivideo
->registered
) {
6509 unregister_framebuffer(sis_fb_info
);
6510 framebuffer_release(sis_fb_info
);
6513 /* OK, our ivideo is gone for good from here. */
6515 /* TODO: Restore the initial mode
6516 * This sounds easy but is as good as impossible
6517 * on many machines with SiS chip and video bridge
6518 * since text modes are always set up differently
6519 * from machine to machine. Depends on the type
6520 * of integration between chipset and bridge.
6522 if(registered
&& modechanged
)
6524 "sisfb: Restoring of text mode not supported yet\n");
6527 static struct pci_driver sisfb_driver
= {
6529 .id_table
= sisfb_pci_table
,
6530 .probe
= sisfb_probe
,
6531 .remove
= sisfb_remove
,
6534 static int __init
sisfb_init(void)
6537 char *options
= NULL
;
6539 if(fb_get_options("sisfb", &options
))
6542 sisfb_setup(options
);
6544 return pci_register_driver(&sisfb_driver
);
6548 module_init(sisfb_init
);
6551 /*****************************************************/
6553 /*****************************************************/
6557 static char *mode
= NULL
;
6558 static int vesa
= -1;
6559 static unsigned int rate
= 0;
6560 static unsigned int crt1off
= 1;
6561 static unsigned int mem
= 0;
6562 static char *forcecrt2type
= NULL
;
6563 static int forcecrt1
= -1;
6564 static int pdc
= -1;
6565 static int pdc1
= -1;
6566 static int noaccel
= -1;
6567 static int noypan
= -1;
6568 static int nomax
= -1;
6569 static int userom
= -1;
6570 static int useoem
= -1;
6571 static char *tvstandard
= NULL
;
6572 static int nocrt2rate
= 0;
6573 static int scalelcd
= -1;
6574 static char *specialtiming
= NULL
;
6575 static int lvdshl
= -1;
6576 static int tvxposoffset
= 0, tvyposoffset
= 0;
6577 #if !defined(__i386__) && !defined(__x86_64__)
6578 static int resetcard
= 0;
6579 static int videoram
= 0;
6582 static int __init
sisfb_init_module(void)
6584 sisfb_setdefaultparms();
6587 sisfb_parm_rate
= rate
;
6589 if((scalelcd
== 0) || (scalelcd
== 1))
6590 sisfb_scalelcd
= scalelcd
^ 1;
6592 /* Need to check crt2 type first for fstn/dstn */
6595 sisfb_search_crt2type(forcecrt2type
);
6598 sisfb_search_tvstd(tvstandard
);
6601 sisfb_search_mode(mode
, false);
6603 sisfb_search_vesamode(vesa
, false);
6605 sisfb_crt1off
= (crt1off
== 0) ? 1 : 0;
6607 sisfb_forcecrt1
= forcecrt1
;
6610 else if(forcecrt1
== 0)
6615 else if(noaccel
== 0)
6620 else if(noypan
== 0)
6629 sisfb_parm_mem
= mem
;
6632 sisfb_userom
= userom
;
6635 sisfb_useoem
= useoem
;
6638 sisfb_pdc
= (pdc
& 0x7f);
6641 sisfb_pdca
= (pdc1
& 0x1f);
6643 sisfb_nocrt2rate
= nocrt2rate
;
6646 sisfb_search_specialtiming(specialtiming
);
6648 if((lvdshl
>= 0) && (lvdshl
<= 3))
6649 sisfb_lvdshl
= lvdshl
;
6651 sisfb_tvxposoffset
= tvxposoffset
;
6652 sisfb_tvyposoffset
= tvyposoffset
;
6654 #if !defined(__i386__) && !defined(__x86_64__)
6655 sisfb_resetcard
= (resetcard
) ? 1 : 0;
6657 sisfb_videoram
= videoram
;
6660 return sisfb_init();
6663 static void __exit
sisfb_remove_module(void)
6665 pci_unregister_driver(&sisfb_driver
);
6666 printk(KERN_DEBUG
"sisfb: Module unloaded\n");
6669 module_init(sisfb_init_module
);
6670 module_exit(sisfb_remove_module
);
6672 MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
6673 MODULE_LICENSE("GPL");
6674 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
6676 module_param(mem
, int, 0);
6677 module_param(noaccel
, int, 0);
6678 module_param(noypan
, int, 0);
6679 module_param(nomax
, int, 0);
6680 module_param(userom
, int, 0);
6681 module_param(useoem
, int, 0);
6682 module_param(mode
, charp
, 0);
6683 module_param(vesa
, int, 0);
6684 module_param(rate
, int, 0);
6685 module_param(forcecrt1
, int, 0);
6686 module_param(forcecrt2type
, charp
, 0);
6687 module_param(scalelcd
, int, 0);
6688 module_param(pdc
, int, 0);
6689 module_param(pdc1
, int, 0);
6690 module_param(specialtiming
, charp
, 0);
6691 module_param(lvdshl
, int, 0);
6692 module_param(tvstandard
, charp
, 0);
6693 module_param(tvxposoffset
, int, 0);
6694 module_param(tvyposoffset
, int, 0);
6695 module_param(nocrt2rate
, int, 0);
6696 #if !defined(__i386__) && !defined(__x86_64__)
6697 module_param(resetcard
, int, 0);
6698 module_param(videoram
, int, 0);
6701 MODULE_PARM_DESC(mem
,
6702 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6703 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6704 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6705 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6706 "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6707 "The value is to be specified without 'KB'.\n");
6709 MODULE_PARM_DESC(noaccel
,
6710 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
6713 MODULE_PARM_DESC(noypan
,
6714 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
6715 "will be performed by redrawing the screen. (default: 0)\n");
6717 MODULE_PARM_DESC(nomax
,
6718 "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
6719 "memory for the virtual screen in order to optimize scrolling performance. If\n"
6720 "this is set to anything other than 0, sisfb will not do this and thereby \n"
6721 "enable the user to positively specify a virtual Y size of the screen using\n"
6722 "fbset. (default: 0)\n");
6724 MODULE_PARM_DESC(mode
,
6725 "\nSelects the desired default display mode in the format XxYxDepth,\n"
6726 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
6727 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
6728 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
6730 MODULE_PARM_DESC(vesa
,
6731 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
6732 "0x117 (default: 0x0103)\n");
6734 MODULE_PARM_DESC(rate
,
6735 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
6736 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
6737 "will be ignored (default: 60)\n");
6739 MODULE_PARM_DESC(forcecrt1
,
6740 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
6741 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
6742 "0=CRT1 OFF) (default: [autodetected])\n");
6744 MODULE_PARM_DESC(forcecrt2type
,
6745 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
6746 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
6747 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
6748 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
6749 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
6750 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
6751 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
6752 "depends on the very hardware in use. (default: [autodetected])\n");
6754 MODULE_PARM_DESC(scalelcd
,
6755 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
6756 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
6757 "show black bars around the image, TMDS panels will probably do the scaling\n"
6758 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
6760 MODULE_PARM_DESC(pdc
,
6761 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
6762 "should detect this correctly in most cases; however, sometimes this is not\n"
6763 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
6764 "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
6765 "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
6766 "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
6768 #ifdef CONFIG_FB_SIS_315
6769 MODULE_PARM_DESC(pdc1
,
6770 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
6771 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
6772 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
6773 "implemented yet.\n");
6776 MODULE_PARM_DESC(specialtiming
,
6777 "\nPlease refer to documentation for more information on this option.\n");
6779 MODULE_PARM_DESC(lvdshl
,
6780 "\nPlease refer to documentation for more information on this option.\n");
6782 MODULE_PARM_DESC(tvstandard
,
6783 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
6784 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
6786 MODULE_PARM_DESC(tvxposoffset
,
6787 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
6790 MODULE_PARM_DESC(tvyposoffset
,
6791 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
6794 MODULE_PARM_DESC(nocrt2rate
,
6795 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
6796 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
6798 #if !defined(__i386__) && !defined(__x86_64__)
6799 #ifdef CONFIG_FB_SIS_300
6800 MODULE_PARM_DESC(resetcard
,
6801 "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
6802 "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
6803 "currently). Default: 0\n");
6805 MODULE_PARM_DESC(videoram
,
6806 "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
6807 "some non-x86 architectures where the memory auto detection fails. Only\n"
6808 "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
6812 #endif /* /MODULE */
6814 /* _GPL only for new symbols. */
6815 EXPORT_SYMBOL(sis_malloc
);
6816 EXPORT_SYMBOL(sis_free
);
6817 EXPORT_SYMBOL_GPL(sis_malloc_new
);
6818 EXPORT_SYMBOL_GPL(sis_free_new
);