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");
1706 case SISFB_GET_INFO
: /* For communication with X driver */
1707 ivideo
->sisfb_infoblock
.sisfb_id
= SISFB_ID
;
1708 ivideo
->sisfb_infoblock
.sisfb_version
= VER_MAJOR
;
1709 ivideo
->sisfb_infoblock
.sisfb_revision
= VER_MINOR
;
1710 ivideo
->sisfb_infoblock
.sisfb_patchlevel
= VER_LEVEL
;
1711 ivideo
->sisfb_infoblock
.chip_id
= ivideo
->chip_id
;
1712 ivideo
->sisfb_infoblock
.sisfb_pci_vendor
= ivideo
->chip_vendor
;
1713 ivideo
->sisfb_infoblock
.memory
= ivideo
->video_size
/ 1024;
1714 ivideo
->sisfb_infoblock
.heapstart
= ivideo
->heapstart
/ 1024;
1715 if(ivideo
->modechanged
) {
1716 ivideo
->sisfb_infoblock
.fbvidmode
= ivideo
->mode_no
;
1718 ivideo
->sisfb_infoblock
.fbvidmode
= ivideo
->modeprechange
;
1720 ivideo
->sisfb_infoblock
.sisfb_caps
= ivideo
->caps
;
1721 ivideo
->sisfb_infoblock
.sisfb_tqlen
= ivideo
->cmdQueueSize
/ 1024;
1722 ivideo
->sisfb_infoblock
.sisfb_pcibus
= ivideo
->pcibus
;
1723 ivideo
->sisfb_infoblock
.sisfb_pcislot
= ivideo
->pcislot
;
1724 ivideo
->sisfb_infoblock
.sisfb_pcifunc
= ivideo
->pcifunc
;
1725 ivideo
->sisfb_infoblock
.sisfb_lcdpdc
= ivideo
->detectedpdc
;
1726 ivideo
->sisfb_infoblock
.sisfb_lcdpdca
= ivideo
->detectedpdca
;
1727 ivideo
->sisfb_infoblock
.sisfb_lcda
= ivideo
->detectedlcda
;
1728 ivideo
->sisfb_infoblock
.sisfb_vbflags
= ivideo
->vbflags
;
1729 ivideo
->sisfb_infoblock
.sisfb_currentvbflags
= ivideo
->currentvbflags
;
1730 ivideo
->sisfb_infoblock
.sisfb_scalelcd
= ivideo
->SiS_Pr
.UsePanelScaler
;
1731 ivideo
->sisfb_infoblock
.sisfb_specialtiming
= ivideo
->SiS_Pr
.SiS_CustomT
;
1732 ivideo
->sisfb_infoblock
.sisfb_haveemi
= ivideo
->SiS_Pr
.HaveEMI
? 1 : 0;
1733 ivideo
->sisfb_infoblock
.sisfb_haveemilcd
= ivideo
->SiS_Pr
.HaveEMILCD
? 1 : 0;
1734 ivideo
->sisfb_infoblock
.sisfb_emi30
= ivideo
->SiS_Pr
.EMI_30
;
1735 ivideo
->sisfb_infoblock
.sisfb_emi31
= ivideo
->SiS_Pr
.EMI_31
;
1736 ivideo
->sisfb_infoblock
.sisfb_emi32
= ivideo
->SiS_Pr
.EMI_32
;
1737 ivideo
->sisfb_infoblock
.sisfb_emi33
= ivideo
->SiS_Pr
.EMI_33
;
1738 ivideo
->sisfb_infoblock
.sisfb_tvxpos
= (u16
)(ivideo
->tvxpos
+ 32);
1739 ivideo
->sisfb_infoblock
.sisfb_tvypos
= (u16
)(ivideo
->tvypos
+ 32);
1740 ivideo
->sisfb_infoblock
.sisfb_heapsize
= ivideo
->sisfb_heap_size
/ 1024;
1741 ivideo
->sisfb_infoblock
.sisfb_videooffset
= ivideo
->video_offset
;
1742 ivideo
->sisfb_infoblock
.sisfb_curfstn
= ivideo
->curFSTN
;
1743 ivideo
->sisfb_infoblock
.sisfb_curdstn
= ivideo
->curDSTN
;
1744 ivideo
->sisfb_infoblock
.sisfb_vbflags2
= ivideo
->vbflags2
;
1745 ivideo
->sisfb_infoblock
.sisfb_can_post
= ivideo
->sisfb_can_post
? 1 : 0;
1746 ivideo
->sisfb_infoblock
.sisfb_card_posted
= ivideo
->sisfb_card_posted
? 1 : 0;
1747 ivideo
->sisfb_infoblock
.sisfb_was_boot_device
= ivideo
->sisfb_was_boot_device
? 1 : 0;
1749 if(copy_to_user((void __user
*)arg
, &ivideo
->sisfb_infoblock
,
1750 sizeof(ivideo
->sisfb_infoblock
)))
1755 case SISFB_GET_VBRSTATUS_OLD
:
1756 if(ivideo
->warncount
++ < 10)
1758 "sisfb: Deprecated ioctl call received - update your application!\n");
1760 case SISFB_GET_VBRSTATUS
:
1761 if(sisfb_CheckVBRetrace(ivideo
))
1762 return put_user((u32
)1, argp
);
1764 return put_user((u32
)0, argp
);
1766 case SISFB_GET_AUTOMAXIMIZE_OLD
:
1767 if(ivideo
->warncount
++ < 10)
1769 "sisfb: Deprecated ioctl call received - update your application!\n");
1771 case SISFB_GET_AUTOMAXIMIZE
:
1772 if(ivideo
->sisfb_max
)
1773 return put_user((u32
)1, argp
);
1775 return put_user((u32
)0, argp
);
1777 case SISFB_SET_AUTOMAXIMIZE_OLD
:
1778 if(ivideo
->warncount
++ < 10)
1780 "sisfb: Deprecated ioctl call received - update your application!\n");
1782 case SISFB_SET_AUTOMAXIMIZE
:
1783 if(get_user(gpu32
, argp
))
1786 ivideo
->sisfb_max
= (gpu32
) ? 1 : 0;
1789 case SISFB_SET_TVPOSOFFSET
:
1790 if(get_user(gpu32
, argp
))
1793 sisfb_set_TVxposoffset(ivideo
, ((int)(gpu32
>> 16)) - 32);
1794 sisfb_set_TVyposoffset(ivideo
, ((int)(gpu32
& 0xffff)) - 32);
1797 case SISFB_GET_TVPOSOFFSET
:
1798 return put_user((u32
)(((ivideo
->tvxpos
+32)<<16)|((ivideo
->tvypos
+32)&0xffff)),
1802 if(copy_from_user(&ivideo
->sisfb_command
, (void __user
*)arg
,
1803 sizeof(struct sisfb_cmd
)))
1806 sisfb_handle_command(ivideo
, &ivideo
->sisfb_command
);
1808 if(copy_to_user((void __user
*)arg
, &ivideo
->sisfb_command
,
1809 sizeof(struct sisfb_cmd
)))
1814 case SISFB_SET_LOCK
:
1815 if(get_user(gpu32
, argp
))
1818 ivideo
->sisfblocked
= (gpu32
) ? 1 : 0;
1822 #ifdef SIS_NEW_CONFIG_COMPAT
1823 return -ENOIOCTLCMD
;
1832 sisfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
, struct fb_info
*info
)
1834 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1836 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
1838 strlcpy(fix
->id
, ivideo
->myid
, sizeof(fix
->id
));
1840 mutex_lock(&info
->mm_lock
);
1841 fix
->smem_start
= ivideo
->video_base
+ ivideo
->video_offset
;
1842 fix
->smem_len
= ivideo
->sisfb_mem
;
1843 mutex_unlock(&info
->mm_lock
);
1844 fix
->type
= FB_TYPE_PACKED_PIXELS
;
1846 fix
->visual
= (ivideo
->video_bpp
== 8) ? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_TRUECOLOR
;
1848 fix
->ypanstep
= (ivideo
->sisfb_ypan
) ? 1 : 0;
1850 fix
->line_length
= ivideo
->video_linelength
;
1851 fix
->mmio_start
= ivideo
->mmio_base
;
1852 fix
->mmio_len
= ivideo
->mmio_size
;
1853 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
1854 fix
->accel
= FB_ACCEL_SIS_GLAMOUR
;
1855 } else if((ivideo
->chip
== SIS_330
) ||
1856 (ivideo
->chip
== SIS_760
) ||
1857 (ivideo
->chip
== SIS_761
)) {
1858 fix
->accel
= FB_ACCEL_SIS_XABRE
;
1859 } else if(ivideo
->chip
== XGI_20
) {
1860 fix
->accel
= FB_ACCEL_XGI_VOLARI_Z
;
1861 } else if(ivideo
->chip
>= XGI_40
) {
1862 fix
->accel
= FB_ACCEL_XGI_VOLARI_V
;
1864 fix
->accel
= FB_ACCEL_SIS_GLAMOUR_2
;
1870 /* ---------------- fb_ops structures ----------------- */
1872 static struct fb_ops sisfb_ops
= {
1873 .owner
= THIS_MODULE
,
1874 .fb_open
= sisfb_open
,
1875 .fb_release
= sisfb_release
,
1876 .fb_check_var
= sisfb_check_var
,
1877 .fb_set_par
= sisfb_set_par
,
1878 .fb_setcolreg
= sisfb_setcolreg
,
1879 .fb_pan_display
= sisfb_pan_display
,
1880 .fb_blank
= sisfb_blank
,
1881 .fb_fillrect
= fbcon_sis_fillrect
,
1882 .fb_copyarea
= fbcon_sis_copyarea
,
1883 .fb_imageblit
= cfb_imageblit
,
1884 .fb_sync
= fbcon_sis_sync
,
1885 #ifdef SIS_NEW_CONFIG_COMPAT
1886 .fb_compat_ioctl
= sisfb_ioctl
,
1888 .fb_ioctl
= sisfb_ioctl
1891 /* ---------------- Chip generation dependent routines ---------------- */
1893 static struct pci_dev
*sisfb_get_northbridge(int basechipid
)
1895 struct pci_dev
*pdev
= NULL
;
1896 int nbridgenum
, nbridgeidx
, i
;
1897 static const unsigned short nbridgeids
[] = {
1898 PCI_DEVICE_ID_SI_540
, /* for SiS 540 VGA */
1899 PCI_DEVICE_ID_SI_630
, /* for SiS 630/730 VGA */
1900 PCI_DEVICE_ID_SI_730
,
1901 PCI_DEVICE_ID_SI_550
, /* for SiS 550 VGA */
1902 PCI_DEVICE_ID_SI_650
, /* for SiS 650/651/740 VGA */
1903 PCI_DEVICE_ID_SI_651
,
1904 PCI_DEVICE_ID_SI_740
,
1905 PCI_DEVICE_ID_SI_661
, /* for SiS 661/741/660/760/761 VGA */
1906 PCI_DEVICE_ID_SI_741
,
1907 PCI_DEVICE_ID_SI_660
,
1908 PCI_DEVICE_ID_SI_760
,
1909 PCI_DEVICE_ID_SI_761
1912 switch(basechipid
) {
1913 #ifdef CONFIG_FB_SIS_300
1914 case SIS_540
: nbridgeidx
= 0; nbridgenum
= 1; break;
1915 case SIS_630
: nbridgeidx
= 1; nbridgenum
= 2; break;
1917 #ifdef CONFIG_FB_SIS_315
1918 case SIS_550
: nbridgeidx
= 3; nbridgenum
= 1; break;
1919 case SIS_650
: nbridgeidx
= 4; nbridgenum
= 3; break;
1920 case SIS_660
: nbridgeidx
= 7; nbridgenum
= 5; break;
1922 default: return NULL
;
1924 for(i
= 0; i
< nbridgenum
; i
++) {
1925 if((pdev
= pci_get_device(PCI_VENDOR_ID_SI
,
1926 nbridgeids
[nbridgeidx
+i
], NULL
)))
1932 static int sisfb_get_dram_size(struct sis_video_info
*ivideo
)
1934 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1938 ivideo
->video_size
= 0;
1939 ivideo
->UMAsize
= ivideo
->LFBsize
= 0;
1941 switch(ivideo
->chip
) {
1942 #ifdef CONFIG_FB_SIS_300
1944 reg
= SiS_GetReg(SISSR
, 0x14);
1945 ivideo
->video_size
= ((reg
& 0x3F) + 1) << 20;
1950 if(!ivideo
->nbridge
)
1952 pci_read_config_byte(ivideo
->nbridge
, 0x63, ®
);
1953 ivideo
->video_size
= 1 << (((reg
& 0x70) >> 4) + 21);
1956 #ifdef CONFIG_FB_SIS_315
1960 reg
= SiS_GetReg(SISSR
, 0x14);
1961 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
1962 switch((reg
>> 2) & 0x03) {
1965 ivideo
->video_size
<<= 1;
1968 ivideo
->video_size
+= (ivideo
->video_size
/2);
1972 reg
= SiS_GetReg(SISSR
, 0x14);
1973 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
1974 if(reg
& 0x0c) ivideo
->video_size
<<= 1;
1979 reg
= SiS_GetReg(SISSR
, 0x14);
1980 ivideo
->video_size
= (((reg
& 0x3f) + 1) << 2) << 20;
1984 reg
= SiS_GetReg(SISCR
, 0x79);
1985 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
1990 reg
= SiS_GetReg(SISCR
, 0x79);
1991 reg
= (reg
& 0xf0) >> 4;
1993 ivideo
->video_size
= (1 << reg
) << 20;
1994 ivideo
->UMAsize
= ivideo
->video_size
;
1996 reg
= SiS_GetReg(SISCR
, 0x78);
2000 ivideo
->LFBsize
= (32 << 20);
2002 ivideo
->LFBsize
= (64 << 20);
2004 ivideo
->video_size
+= ivideo
->LFBsize
;
2010 reg
= SiS_GetReg(SISSR
, 0x14);
2011 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
2012 if(ivideo
->chip
!= XGI_20
) {
2013 reg
= (reg
& 0x0c) >> 2;
2014 if(ivideo
->revision_id
== 2) {
2015 if(reg
& 0x01) reg
= 0x02;
2018 if(reg
== 0x02) ivideo
->video_size
<<= 1;
2019 else if(reg
== 0x03) ivideo
->video_size
<<= 2;
2029 /* -------------- video bridge device detection --------------- */
2031 static void sisfb_detect_VB_connect(struct sis_video_info
*ivideo
)
2035 /* No CRT2 on XGI Z7 */
2036 if(ivideo
->chip
== XGI_20
) {
2037 ivideo
->sisfb_crt1off
= 0;
2041 #ifdef CONFIG_FB_SIS_300
2042 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2043 temp
= SiS_GetReg(SISSR
, 0x17);
2044 if((temp
& 0x0F) && (ivideo
->chip
!= SIS_300
)) {
2045 /* PAL/NTSC is stored on SR16 on such machines */
2046 if(!(ivideo
->vbflags
& (TV_PAL
| TV_NTSC
| TV_PALM
| TV_PALN
))) {
2047 temp
= SiS_GetReg(SISSR
, 0x16);
2049 ivideo
->vbflags
|= TV_PAL
;
2051 ivideo
->vbflags
|= TV_NTSC
;
2057 cr32
= SiS_GetReg(SISCR
, 0x32);
2059 if(cr32
& SIS_CRT1
) {
2060 ivideo
->sisfb_crt1off
= 0;
2062 ivideo
->sisfb_crt1off
= (cr32
& 0xDF) ? 1 : 0;
2065 ivideo
->vbflags
&= ~(CRT2_TV
| CRT2_LCD
| CRT2_VGA
);
2067 if(cr32
& SIS_VB_TV
) ivideo
->vbflags
|= CRT2_TV
;
2068 if(cr32
& SIS_VB_LCD
) ivideo
->vbflags
|= CRT2_LCD
;
2069 if(cr32
& SIS_VB_CRT2
) ivideo
->vbflags
|= CRT2_VGA
;
2071 /* Check given parms for hardware compatibility.
2072 * (Cannot do this in the search_xx routines since we don't
2073 * know what hardware we are running on then)
2076 if(ivideo
->chip
!= SIS_550
) {
2077 ivideo
->sisfb_dstn
= ivideo
->sisfb_fstn
= 0;
2080 if(ivideo
->sisfb_tvplug
!= -1) {
2081 if( (ivideo
->sisvga_engine
!= SIS_315_VGA
) ||
2082 (!(ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) ) {
2083 if(ivideo
->sisfb_tvplug
& TV_YPBPR
) {
2084 ivideo
->sisfb_tvplug
= -1;
2085 printk(KERN_ERR
"sisfb: YPbPr not supported\n");
2089 if(ivideo
->sisfb_tvplug
!= -1) {
2090 if( (ivideo
->sisvga_engine
!= SIS_315_VGA
) ||
2091 (!(ivideo
->vbflags2
& VB2_SISHIVISIONBRIDGE
)) ) {
2092 if(ivideo
->sisfb_tvplug
& TV_HIVISION
) {
2093 ivideo
->sisfb_tvplug
= -1;
2094 printk(KERN_ERR
"sisfb: HiVision not supported\n");
2098 if(ivideo
->sisfb_tvstd
!= -1) {
2099 if( (!(ivideo
->vbflags2
& VB2_SISBRIDGE
)) &&
2100 (!((ivideo
->sisvga_engine
== SIS_315_VGA
) &&
2101 (ivideo
->vbflags2
& VB2_CHRONTEL
))) ) {
2102 if(ivideo
->sisfb_tvstd
& (TV_PALM
| TV_PALN
| TV_NTSCJ
)) {
2103 ivideo
->sisfb_tvstd
= -1;
2104 printk(KERN_ERR
"sisfb: PALM/PALN/NTSCJ not supported\n");
2109 /* Detect/set TV plug & type */
2110 if(ivideo
->sisfb_tvplug
!= -1) {
2111 ivideo
->vbflags
|= ivideo
->sisfb_tvplug
;
2113 if(cr32
& SIS_VB_YPBPR
) ivideo
->vbflags
|= (TV_YPBPR
|TV_YPBPR525I
); /* default: 480i */
2114 else if(cr32
& SIS_VB_HIVISION
) ivideo
->vbflags
|= TV_HIVISION
;
2115 else if(cr32
& SIS_VB_SCART
) ivideo
->vbflags
|= TV_SCART
;
2117 if(cr32
& SIS_VB_SVIDEO
) ivideo
->vbflags
|= TV_SVIDEO
;
2118 if(cr32
& SIS_VB_COMPOSITE
) ivideo
->vbflags
|= TV_AVIDEO
;
2122 if(!(ivideo
->vbflags
& (TV_YPBPR
| TV_HIVISION
))) {
2123 if(ivideo
->sisfb_tvstd
!= -1) {
2124 ivideo
->vbflags
&= ~(TV_NTSC
| TV_PAL
| TV_PALM
| TV_PALN
| TV_NTSCJ
);
2125 ivideo
->vbflags
|= ivideo
->sisfb_tvstd
;
2127 if(ivideo
->vbflags
& TV_SCART
) {
2128 ivideo
->vbflags
&= ~(TV_NTSC
| TV_PALM
| TV_PALN
| TV_NTSCJ
);
2129 ivideo
->vbflags
|= TV_PAL
;
2131 if(!(ivideo
->vbflags
& (TV_PAL
| TV_NTSC
| TV_PALM
| TV_PALN
| TV_NTSCJ
))) {
2132 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2133 temp
= SiS_GetReg(SISSR
, 0x38);
2134 if(temp
& 0x01) ivideo
->vbflags
|= TV_PAL
;
2135 else ivideo
->vbflags
|= TV_NTSC
;
2136 } else if((ivideo
->chip
<= SIS_315PRO
) || (ivideo
->chip
>= SIS_330
)) {
2137 temp
= SiS_GetReg(SISSR
, 0x38);
2138 if(temp
& 0x01) ivideo
->vbflags
|= TV_PAL
;
2139 else ivideo
->vbflags
|= TV_NTSC
;
2141 temp
= SiS_GetReg(SISCR
, 0x79);
2142 if(temp
& 0x20) ivideo
->vbflags
|= TV_PAL
;
2143 else ivideo
->vbflags
|= TV_NTSC
;
2148 /* Copy forceCRT1 option to CRT1off if option is given */
2149 if(ivideo
->sisfb_forcecrt1
!= -1) {
2150 ivideo
->sisfb_crt1off
= (ivideo
->sisfb_forcecrt1
) ? 0 : 1;
2154 /* ------------------ Sensing routines ------------------ */
2156 static bool sisfb_test_DDC1(struct sis_video_info
*ivideo
)
2161 old
= SiS_ReadDDC1Bit(&ivideo
->SiS_Pr
);
2163 if(old
!= SiS_ReadDDC1Bit(&ivideo
->SiS_Pr
)) break;
2165 return (count
!= -1);
2168 static void sisfb_sense_crt1(struct sis_video_info
*ivideo
)
2170 bool mustwait
= false;
2172 #ifdef CONFIG_FB_SIS_315
2178 sr1F
= SiS_GetReg(SISSR
, 0x1F);
2179 SiS_SetRegOR(SISSR
, 0x1F, 0x04);
2180 SiS_SetRegAND(SISSR
, 0x1F, 0x3F);
2181 if(sr1F
& 0xc0) mustwait
= true;
2183 #ifdef CONFIG_FB_SIS_315
2184 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2185 cr63
= SiS_GetReg(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
);
2187 SiS_SetRegAND(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, 0xBF);
2191 cr17
= SiS_GetReg(SISCR
, 0x17);
2194 SiS_SetRegOR(SISCR
, 0x17, 0x80);
2196 SiS_SetReg(SISSR
, 0x00, 0x01);
2197 SiS_SetReg(SISSR
, 0x00, 0x03);
2201 for(i
=0; i
< 10; i
++) sisfbwaitretracecrt1(ivideo
);
2204 #ifdef CONFIG_FB_SIS_315
2205 if(ivideo
->chip
>= SIS_330
) {
2206 SiS_SetRegAND(SISCR
, 0x32, ~0x20);
2207 if(ivideo
->chip
>= SIS_340
) {
2208 SiS_SetReg(SISCR
, 0x57, 0x4a);
2210 SiS_SetReg(SISCR
, 0x57, 0x5f);
2212 SiS_SetRegOR(SISCR
, 0x53, 0x02);
2213 while ((SiS_GetRegByte(SISINPSTAT
)) & 0x01) break;
2214 while (!((SiS_GetRegByte(SISINPSTAT
)) & 0x01)) break;
2215 if ((SiS_GetRegByte(SISMISCW
)) & 0x10) temp
= 1;
2216 SiS_SetRegAND(SISCR
, 0x53, 0xfd);
2217 SiS_SetRegAND(SISCR
, 0x57, 0x00);
2221 if(temp
== 0xffff) {
2224 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
,
2225 ivideo
->sisvga_engine
, 0, 0, NULL
, ivideo
->vbflags2
);
2226 } while(((temp
== 0) || (temp
== 0xffff)) && i
--);
2228 if((temp
== 0) || (temp
== 0xffff)) {
2229 if(sisfb_test_DDC1(ivideo
)) temp
= 1;
2233 if((temp
) && (temp
!= 0xffff)) {
2234 SiS_SetRegOR(SISCR
, 0x32, 0x20);
2237 #ifdef CONFIG_FB_SIS_315
2238 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2239 SiS_SetRegANDOR(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, 0xBF, cr63
);
2243 SiS_SetRegANDOR(SISCR
, 0x17, 0x7F, cr17
);
2245 SiS_SetReg(SISSR
, 0x1F, sr1F
);
2248 /* Determine and detect attached devices on SiS30x */
2249 static void SiS_SenseLCD(struct sis_video_info
*ivideo
)
2251 unsigned char buffer
[256];
2252 unsigned short temp
, realcrtno
, i
;
2253 u8 reg
, cr37
= 0, paneltype
= 0;
2256 ivideo
->SiS_Pr
.PanelSelfDetected
= false;
2258 /* LCD detection only for TMDS bridges */
2259 if(!(ivideo
->vbflags2
& VB2_SISTMDSBRIDGE
))
2261 if(ivideo
->vbflags2
& VB2_30xBDH
)
2264 /* If LCD already set up by BIOS, skip it */
2265 reg
= SiS_GetReg(SISCR
, 0x32);
2270 if(ivideo
->SiS_Pr
.DDCPortMixup
)
2273 /* Check DDC capabilities */
2274 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
2275 realcrtno
, 0, &buffer
[0], ivideo
->vbflags2
);
2277 if((!temp
) || (temp
== 0xffff) || (!(temp
& 0x02)))
2281 i
= 3; /* Number of retrys */
2283 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
,
2284 ivideo
->sisvga_engine
, realcrtno
, 1,
2285 &buffer
[0], ivideo
->vbflags2
);
2286 } while((temp
) && i
--);
2291 /* No digital device */
2292 if(!(buffer
[0x14] & 0x80))
2295 /* First detailed timing preferred timing? */
2296 if(!(buffer
[0x18] & 0x02))
2299 xres
= buffer
[0x38] | ((buffer
[0x3a] & 0xf0) << 4);
2300 yres
= buffer
[0x3b] | ((buffer
[0x3d] & 0xf0) << 4);
2312 if((yres
== 1200) && (ivideo
->vbflags2
& VB2_30xC
))
2323 if((buffer
[0x47] & 0x18) == 0x18)
2324 cr37
|= ((((buffer
[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2328 SiS_SetReg(SISCR
, 0x36, paneltype
);
2330 SiS_SetRegANDOR(SISCR
, 0x37, 0x0c, cr37
);
2331 SiS_SetRegOR(SISCR
, 0x32, 0x08);
2333 ivideo
->SiS_Pr
.PanelSelfDetected
= true;
2336 static int SISDoSense(struct sis_video_info
*ivideo
, u16 type
, u16 test
)
2338 int temp
, mytest
, result
, i
, j
;
2340 for(j
= 0; j
< 10; j
++) {
2342 for(i
= 0; i
< 3; i
++) {
2344 SiS_SetReg(SISPART4
, 0x11, (type
& 0x00ff));
2345 temp
= (type
>> 8) | (mytest
& 0x00ff);
2346 SiS_SetRegANDOR(SISPART4
, 0x10, 0xe0, temp
);
2347 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x1500);
2350 temp
= SiS_GetReg(SISPART4
, 0x03);
2353 if(temp
== mytest
) result
++;
2355 SiS_SetReg(SISPART4
, 0x11, 0x00);
2356 SiS_SetRegAND(SISPART4
, 0x10, 0xe0);
2357 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x1000);
2360 if((result
== 0) || (result
>= 2)) break;
2365 static void SiS_Sense30x(struct sis_video_info
*ivideo
)
2367 u8 backupP4_0d
,backupP2_00
,backupP2_4d
,backupSR_1e
,biosflag
=0;
2368 u16 svhs
=0, svhs_c
=0;
2369 u16 cvbs
=0, cvbs_c
=0;
2370 u16 vga2
=0, vga2_c
=0;
2372 char stdstr
[] = "sisfb: Detected";
2373 char tvstr
[] = "TV connected to";
2375 if(ivideo
->vbflags2
& VB2_301
) {
2376 svhs
= 0x00b9; cvbs
= 0x00b3; vga2
= 0x00d1;
2377 myflag
= SiS_GetReg(SISPART4
, 0x01);
2379 svhs
= 0x00dd; cvbs
= 0x00ee; vga2
= 0x00fd;
2381 } else if(ivideo
->vbflags2
& (VB2_301B
| VB2_302B
)) {
2382 svhs
= 0x016b; cvbs
= 0x0174; vga2
= 0x0190;
2383 } else if(ivideo
->vbflags2
& (VB2_301LV
| VB2_302LV
)) {
2384 svhs
= 0x0200; cvbs
= 0x0100;
2385 } else if(ivideo
->vbflags2
& (VB2_301C
| VB2_302ELV
| VB2_307T
| VB2_307LV
)) {
2386 svhs
= 0x016b; cvbs
= 0x0110; vga2
= 0x0190;
2390 vga2_c
= 0x0e08; svhs_c
= 0x0404; cvbs_c
= 0x0804;
2391 if(ivideo
->vbflags
& (VB2_301LV
|VB2_302LV
|VB2_302ELV
|VB2_307LV
)) {
2392 svhs_c
= 0x0408; cvbs_c
= 0x0808;
2396 if(ivideo
->haveXGIROM
) {
2397 biosflag
= ivideo
->bios_abase
[0x58] & 0x03;
2398 } else if(ivideo
->newrom
) {
2399 if(ivideo
->bios_abase
[0x5d] & 0x04) biosflag
|= 0x01;
2400 } else if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2401 if(ivideo
->bios_abase
) {
2402 biosflag
= ivideo
->bios_abase
[0xfe] & 0x03;
2406 if(ivideo
->chip
== SIS_300
) {
2407 myflag
= SiS_GetReg(SISSR
, 0x3b);
2408 if(!(myflag
& 0x01)) vga2
= vga2_c
= 0;
2411 if(!(ivideo
->vbflags2
& VB2_SISVGA2BRIDGE
)) {
2415 backupSR_1e
= SiS_GetReg(SISSR
, 0x1e);
2416 SiS_SetRegOR(SISSR
, 0x1e, 0x20);
2418 backupP4_0d
= SiS_GetReg(SISPART4
, 0x0d);
2419 if(ivideo
->vbflags2
& VB2_30xC
) {
2420 SiS_SetRegANDOR(SISPART4
, 0x0d, ~0x07, 0x01);
2422 SiS_SetRegOR(SISPART4
, 0x0d, 0x04);
2424 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x2000);
2426 backupP2_00
= SiS_GetReg(SISPART2
, 0x00);
2427 SiS_SetReg(SISPART2
, 0x00, ((backupP2_00
| 0x1c) & 0xfc));
2429 backupP2_4d
= SiS_GetReg(SISPART2
, 0x4d);
2430 if(ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
) {
2431 SiS_SetReg(SISPART2
, 0x4d, (backupP2_4d
& ~0x10));
2434 if(!(ivideo
->vbflags2
& VB2_30xCLV
)) {
2435 SISDoSense(ivideo
, 0, 0);
2438 SiS_SetRegAND(SISCR
, 0x32, ~0x14);
2440 if(vga2_c
|| vga2
) {
2441 if(SISDoSense(ivideo
, vga2
, vga2_c
)) {
2442 if(biosflag
& 0x01) {
2443 printk(KERN_INFO
"%s %s SCART output\n", stdstr
, tvstr
);
2444 SiS_SetRegOR(SISCR
, 0x32, 0x04);
2446 printk(KERN_INFO
"%s secondary VGA connection\n", stdstr
);
2447 SiS_SetRegOR(SISCR
, 0x32, 0x10);
2452 SiS_SetRegAND(SISCR
, 0x32, 0x3f);
2454 if(ivideo
->vbflags2
& VB2_30xCLV
) {
2455 SiS_SetRegOR(SISPART4
, 0x0d, 0x04);
2458 if((ivideo
->sisvga_engine
== SIS_315_VGA
) && (ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) {
2459 SiS_SetReg(SISPART2
, 0x4d, (backupP2_4d
| 0x10));
2460 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x2000);
2461 if((result
= SISDoSense(ivideo
, svhs
, 0x0604))) {
2462 if((result
= SISDoSense(ivideo
, cvbs
, 0x0804))) {
2463 printk(KERN_INFO
"%s %s YPbPr component output\n", stdstr
, tvstr
);
2464 SiS_SetRegOR(SISCR
, 0x32, 0x80);
2467 SiS_SetReg(SISPART2
, 0x4d, backupP2_4d
);
2470 SiS_SetRegAND(SISCR
, 0x32, ~0x03);
2472 if(!(ivideo
->vbflags
& TV_YPBPR
)) {
2473 if((result
= SISDoSense(ivideo
, svhs
, svhs_c
))) {
2474 printk(KERN_INFO
"%s %s SVIDEO output\n", stdstr
, tvstr
);
2475 SiS_SetRegOR(SISCR
, 0x32, 0x02);
2477 if((biosflag
& 0x02) || (!result
)) {
2478 if(SISDoSense(ivideo
, cvbs
, cvbs_c
)) {
2479 printk(KERN_INFO
"%s %s COMPOSITE output\n", stdstr
, tvstr
);
2480 SiS_SetRegOR(SISCR
, 0x32, 0x01);
2485 SISDoSense(ivideo
, 0, 0);
2487 SiS_SetReg(SISPART2
, 0x00, backupP2_00
);
2488 SiS_SetReg(SISPART4
, 0x0d, backupP4_0d
);
2489 SiS_SetReg(SISSR
, 0x1e, backupSR_1e
);
2491 if(ivideo
->vbflags2
& VB2_30xCLV
) {
2492 biosflag
= SiS_GetReg(SISPART2
, 0x00);
2493 if(biosflag
& 0x20) {
2494 for(myflag
= 2; myflag
> 0; myflag
--) {
2496 SiS_SetReg(SISPART2
, 0x00, biosflag
);
2501 SiS_SetReg(SISPART2
, 0x00, backupP2_00
);
2504 /* Determine and detect attached TV's on Chrontel */
2505 static void SiS_SenseCh(struct sis_video_info
*ivideo
)
2507 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2509 char stdstr
[] = "sisfb: Chrontel: Detected TV connected to";
2511 #ifdef CONFIG_FB_SIS_300
2512 unsigned char test
[3];
2516 if(ivideo
->chip
< SIS_315H
) {
2518 #ifdef CONFIG_FB_SIS_300
2519 ivideo
->SiS_Pr
.SiS_IF_DEF_CH70xx
= 1; /* Chrontel 700x */
2520 SiS_SetChrontelGPIO(&ivideo
->SiS_Pr
, 0x9c); /* Set general purpose IO for Chrontel communication */
2521 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 1000);
2522 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x25);
2523 /* See Chrontel TB31 for explanation */
2524 temp2
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0e);
2525 if(((temp2
& 0x07) == 0x01) || (temp2
& 0x04)) {
2526 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0e, 0x0b);
2527 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 300);
2529 temp2
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x25);
2530 if(temp2
!= temp1
) temp1
= temp2
;
2532 if((temp1
>= 0x22) && (temp1
<= 0x50)) {
2533 /* Read power status */
2534 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0e);
2535 if((temp1
& 0x03) != 0x03) {
2536 /* Power all outputs */
2537 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0e,0x0b);
2538 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 300);
2540 /* Sense connected TV devices */
2541 for(i
= 0; i
< 3; i
++) {
2542 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x10, 0x01);
2543 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2544 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x10, 0x00);
2545 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2546 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x10);
2547 if(!(temp1
& 0x08)) test
[i
] = 0x02;
2548 else if(!(temp1
& 0x02)) test
[i
] = 0x01;
2550 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2553 if(test
[0] == test
[1]) temp1
= test
[0];
2554 else if(test
[0] == test
[2]) temp1
= test
[0];
2555 else if(test
[1] == test
[2]) temp1
= test
[1];
2558 "sisfb: TV detection unreliable - test results varied\n");
2562 printk(KERN_INFO
"%s SVIDEO output\n", stdstr
);
2563 ivideo
->vbflags
|= TV_SVIDEO
;
2564 SiS_SetRegOR(SISCR
, 0x32, 0x02);
2565 SiS_SetRegAND(SISCR
, 0x32, ~0x05);
2566 } else if (temp1
== 0x01) {
2567 printk(KERN_INFO
"%s CVBS output\n", stdstr
);
2568 ivideo
->vbflags
|= TV_AVIDEO
;
2569 SiS_SetRegOR(SISCR
, 0x32, 0x01);
2570 SiS_SetRegAND(SISCR
, 0x32, ~0x06);
2572 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x0e, 0x01, 0xF8);
2573 SiS_SetRegAND(SISCR
, 0x32, ~0x07);
2575 } else if(temp1
== 0) {
2576 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x0e, 0x01, 0xF8);
2577 SiS_SetRegAND(SISCR
, 0x32, ~0x07);
2579 /* Set general purpose IO for Chrontel communication */
2580 SiS_SetChrontelGPIO(&ivideo
->SiS_Pr
, 0x00);
2585 #ifdef CONFIG_FB_SIS_315
2586 ivideo
->SiS_Pr
.SiS_IF_DEF_CH70xx
= 2; /* Chrontel 7019 */
2587 temp1
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x49);
2588 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x49, 0x20);
2589 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2590 temp2
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x20);
2592 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x20, temp2
);
2593 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2595 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x20, temp2
);
2596 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2597 temp2
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x20);
2598 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x49, temp1
);
2600 if(temp2
& 0x02) temp1
|= 0x01;
2601 if(temp2
& 0x10) temp1
|= 0x01;
2602 if(temp2
& 0x04) temp1
|= 0x02;
2603 if( (temp1
& 0x01) && (temp1
& 0x02) ) temp1
= 0x04;
2606 printk(KERN_INFO
"%s CVBS output\n", stdstr
);
2607 ivideo
->vbflags
|= TV_AVIDEO
;
2608 SiS_SetRegOR(SISCR
, 0x32, 0x01);
2609 SiS_SetRegAND(SISCR
, 0x32, ~0x06);
2612 printk(KERN_INFO
"%s SVIDEO output\n", stdstr
);
2613 ivideo
->vbflags
|= TV_SVIDEO
;
2614 SiS_SetRegOR(SISCR
, 0x32, 0x02);
2615 SiS_SetRegAND(SISCR
, 0x32, ~0x05);
2618 printk(KERN_INFO
"%s SCART output\n", stdstr
);
2619 SiS_SetRegOR(SISCR
, 0x32, 0x04);
2620 SiS_SetRegAND(SISCR
, 0x32, ~0x03);
2623 SiS_SetRegAND(SISCR
, 0x32, ~0x07);
2629 static void sisfb_get_VB_type(struct sis_video_info
*ivideo
)
2631 char stdstr
[] = "sisfb: Detected";
2632 char bridgestr
[] = "video bridge";
2636 /* No CRT2 on XGI Z7 */
2637 if(ivideo
->chip
== XGI_20
)
2640 vb_chipid
= SiS_GetReg(SISPART4
, 0x00);
2643 reg
= SiS_GetReg(SISPART4
, 0x01);
2645 ivideo
->vbflags
|= VB_301
; /* Deprecated */
2646 ivideo
->vbflags2
|= VB2_301
;
2647 printk(KERN_INFO
"%s SiS301 %s\n", stdstr
, bridgestr
);
2648 } else if(reg
< 0xc0) {
2649 ivideo
->vbflags
|= VB_301B
; /* Deprecated */
2650 ivideo
->vbflags2
|= VB2_301B
;
2651 reg
= SiS_GetReg(SISPART4
, 0x23);
2653 ivideo
->vbflags
|= VB_30xBDH
; /* Deprecated */
2654 ivideo
->vbflags2
|= VB2_30xBDH
;
2655 printk(KERN_INFO
"%s SiS301B-DH %s\n", stdstr
, bridgestr
);
2657 printk(KERN_INFO
"%s SiS301B %s\n", stdstr
, bridgestr
);
2659 } else if(reg
< 0xd0) {
2660 ivideo
->vbflags
|= VB_301C
; /* Deprecated */
2661 ivideo
->vbflags2
|= VB2_301C
;
2662 printk(KERN_INFO
"%s SiS301C %s\n", stdstr
, bridgestr
);
2663 } else if(reg
< 0xe0) {
2664 ivideo
->vbflags
|= VB_301LV
; /* Deprecated */
2665 ivideo
->vbflags2
|= VB2_301LV
;
2666 printk(KERN_INFO
"%s SiS301LV %s\n", stdstr
, bridgestr
);
2667 } else if(reg
<= 0xe1) {
2668 reg
= SiS_GetReg(SISPART4
, 0x39);
2670 ivideo
->vbflags
|= VB_302LV
; /* Deprecated */
2671 ivideo
->vbflags2
|= VB2_302LV
;
2672 printk(KERN_INFO
"%s SiS302LV %s\n", stdstr
, bridgestr
);
2674 ivideo
->vbflags
|= VB_301C
; /* Deprecated */
2675 ivideo
->vbflags2
|= VB2_301C
;
2676 printk(KERN_INFO
"%s SiS301C(P4) %s\n", stdstr
, bridgestr
);
2678 ivideo
->vbflags
|= VB_302ELV
; /* Deprecated */
2679 ivideo
->vbflags2
|= VB2_302ELV
;
2680 printk(KERN_INFO
"%s SiS302ELV %s\n", stdstr
, bridgestr
);
2686 ivideo
->vbflags
|= VB_302B
; /* Deprecated */
2687 ivideo
->vbflags2
|= VB2_302B
;
2688 printk(KERN_INFO
"%s SiS302B %s\n", stdstr
, bridgestr
);
2692 if((!(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
)) && (ivideo
->chip
!= SIS_300
)) {
2693 reg
= SiS_GetReg(SISCR
, 0x37);
2694 reg
&= SIS_EXTERNAL_CHIP_MASK
;
2696 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2697 #ifdef CONFIG_FB_SIS_300
2699 case SIS_EXTERNAL_CHIP_LVDS
:
2700 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2701 ivideo
->vbflags2
|= VB2_LVDS
;
2703 case SIS_EXTERNAL_CHIP_TRUMPION
:
2704 ivideo
->vbflags
|= (VB_LVDS
| VB_TRUMPION
); /* Deprecated */
2705 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_TRUMPION
);
2707 case SIS_EXTERNAL_CHIP_CHRONTEL
:
2708 ivideo
->vbflags
|= VB_CHRONTEL
; /* Deprecated */
2709 ivideo
->vbflags2
|= VB2_CHRONTEL
;
2711 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL
:
2712 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2713 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2716 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 1;
2718 } else if(ivideo
->chip
< SIS_661
) {
2719 #ifdef CONFIG_FB_SIS_315
2721 case SIS310_EXTERNAL_CHIP_LVDS
:
2722 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2723 ivideo
->vbflags2
|= VB2_LVDS
;
2725 case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL
:
2726 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2727 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2730 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 2;
2732 } else if(ivideo
->chip
>= SIS_661
) {
2733 #ifdef CONFIG_FB_SIS_315
2734 reg
= SiS_GetReg(SISCR
, 0x38);
2738 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2739 ivideo
->vbflags2
|= VB2_LVDS
;
2742 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2743 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2746 ivideo
->vbflags
|= (VB_LVDS
| VB_CONEXANT
); /* Deprecated */
2747 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CONEXANT
);
2750 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 2;
2753 if(ivideo
->vbflags2
& VB2_LVDS
) {
2754 printk(KERN_INFO
"%s LVDS transmitter\n", stdstr
);
2756 if((ivideo
->sisvga_engine
== SIS_300_VGA
) && (ivideo
->vbflags2
& VB2_TRUMPION
)) {
2757 printk(KERN_INFO
"%s Trumpion Zurac LCD scaler\n", stdstr
);
2759 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
2760 printk(KERN_INFO
"%s Chrontel TV encoder\n", stdstr
);
2762 if((ivideo
->chip
>= SIS_661
) && (ivideo
->vbflags2
& VB2_CONEXANT
)) {
2763 printk(KERN_INFO
"%s Conexant external device\n", stdstr
);
2767 if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
2768 SiS_SenseLCD(ivideo
);
2769 SiS_Sense30x(ivideo
);
2770 } else if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
2771 SiS_SenseCh(ivideo
);
2775 /* ---------- Engine initialization routines ------------ */
2778 sisfb_engine_init(struct sis_video_info
*ivideo
)
2781 /* Initialize command queue (we use MMIO only) */
2783 /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
2785 ivideo
->caps
&= ~(TURBO_QUEUE_CAP
|
2786 MMIO_CMD_QUEUE_CAP
|
2790 #ifdef CONFIG_FB_SIS_300
2791 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2795 tqueue_pos
= (ivideo
->video_size
- ivideo
->cmdQueueSize
) / (64 * 1024);
2797 tq_state
= SiS_GetReg(SISSR
, IND_SIS_TURBOQUEUE_SET
);
2800 tq_state
|= (u8
)(tqueue_pos
>> 8);
2801 SiS_SetReg(SISSR
, IND_SIS_TURBOQUEUE_SET
, tq_state
);
2803 SiS_SetReg(SISSR
, IND_SIS_TURBOQUEUE_ADR
, (u8
)(tqueue_pos
& 0xff));
2805 ivideo
->caps
|= TURBO_QUEUE_CAP
;
2809 #ifdef CONFIG_FB_SIS_315
2810 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2811 u32 tempq
= 0, templ
;
2814 if(ivideo
->chip
== XGI_20
) {
2815 switch(ivideo
->cmdQueueSize
) {
2817 temp
= SIS_CMD_QUEUE_SIZE_Z7_64k
;
2821 temp
= SIS_CMD_QUEUE_SIZE_Z7_128k
;
2824 switch(ivideo
->cmdQueueSize
) {
2825 case (4 * 1024 * 1024):
2826 temp
= SIS_CMD_QUEUE_SIZE_4M
;
2828 case (2 * 1024 * 1024):
2829 temp
= SIS_CMD_QUEUE_SIZE_2M
;
2831 case (1 * 1024 * 1024):
2832 temp
= SIS_CMD_QUEUE_SIZE_1M
;
2836 temp
= SIS_CMD_QUEUE_SIZE_512k
;
2840 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_THRESHOLD
, COMMAND_QUEUE_THRESHOLD
);
2841 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, SIS_CMD_QUEUE_RESET
);
2843 if((ivideo
->chip
>= XGI_40
) && ivideo
->modechanged
) {
2844 /* Must disable dual pipe on XGI_40. Can't do
2845 * this in MMIO mode, because it requires
2846 * setting/clearing a bit in the MMIO fire trigger
2849 if(!((templ
= MMIO_IN32(ivideo
->mmio_vbase
, 0x8240)) & (1 << 10))) {
2851 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, 0);
2853 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, (temp
| SIS_VRAM_CMDQUEUE_ENABLE
));
2855 tempq
= MMIO_IN32(ivideo
->mmio_vbase
, Q_READ_PTR
);
2856 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, tempq
);
2858 tempq
= (u32
)(ivideo
->video_size
- ivideo
->cmdQueueSize
);
2859 MMIO_OUT32(ivideo
->mmio_vbase
, Q_BASE_ADDR
, tempq
);
2861 writel(0x16800000 + 0x8240, ivideo
->video_vbase
+ tempq
);
2862 writel(templ
| (1 << 10), ivideo
->video_vbase
+ tempq
+ 4);
2863 writel(0x168F0000, ivideo
->video_vbase
+ tempq
+ 8);
2864 writel(0x168F0000, ivideo
->video_vbase
+ tempq
+ 12);
2866 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, (tempq
+ 16));
2868 sisfb_syncaccel(ivideo
);
2870 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, SIS_CMD_QUEUE_RESET
);
2875 tempq
= MMIO_IN32(ivideo
->mmio_vbase
, MMIO_QUEUE_READPORT
);
2876 MMIO_OUT32(ivideo
->mmio_vbase
, MMIO_QUEUE_WRITEPORT
, tempq
);
2878 temp
|= (SIS_MMIO_CMD_ENABLE
| SIS_CMD_AUTO_CORR
);
2879 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, temp
);
2881 tempq
= (u32
)(ivideo
->video_size
- ivideo
->cmdQueueSize
);
2882 MMIO_OUT32(ivideo
->mmio_vbase
, MMIO_QUEUE_PHYBASE
, tempq
);
2884 ivideo
->caps
|= MMIO_CMD_QUEUE_CAP
;
2888 ivideo
->engineok
= 1;
2891 static void sisfb_detect_lcd_type(struct sis_video_info
*ivideo
)
2896 reg
= SiS_GetReg(SISCR
, 0x36);
2898 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2899 ivideo
->CRT2LCDType
= sis300paneltype
[reg
];
2900 } else if(ivideo
->chip
>= SIS_661
) {
2901 ivideo
->CRT2LCDType
= sis661paneltype
[reg
];
2903 ivideo
->CRT2LCDType
= sis310paneltype
[reg
];
2904 if((ivideo
->chip
== SIS_550
) && (sisfb_fstn
)) {
2905 if((ivideo
->CRT2LCDType
!= LCD_320x240_2
) &&
2906 (ivideo
->CRT2LCDType
!= LCD_320x240_3
)) {
2907 ivideo
->CRT2LCDType
= LCD_320x240
;
2912 if(ivideo
->CRT2LCDType
== LCD_UNKNOWN
) {
2913 /* For broken BIOSes: Assume 1024x768, RGB18 */
2914 ivideo
->CRT2LCDType
= LCD_1024x768
;
2915 SiS_SetRegANDOR(SISCR
, 0x36, 0xf0, 0x02);
2916 SiS_SetRegANDOR(SISCR
, 0x37, 0xee, 0x01);
2917 printk(KERN_DEBUG
"sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg
);
2920 for(i
= 0; i
< SIS_LCD_NUMBER
; i
++) {
2921 if(ivideo
->CRT2LCDType
== sis_lcd_data
[i
].lcdtype
) {
2922 ivideo
->lcdxres
= sis_lcd_data
[i
].xres
;
2923 ivideo
->lcdyres
= sis_lcd_data
[i
].yres
;
2924 ivideo
->lcddefmodeidx
= sis_lcd_data
[i
].default_mode_idx
;
2929 #ifdef CONFIG_FB_SIS_300
2930 if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_BARCO1366
) {
2931 ivideo
->lcdxres
= 1360; ivideo
->lcdyres
= 1024;
2932 ivideo
->lcddefmodeidx
= DEFAULT_MODE_1360
;
2933 } else if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_PANEL848
) {
2934 ivideo
->lcdxres
= 848; ivideo
->lcdyres
= 480;
2935 ivideo
->lcddefmodeidx
= DEFAULT_MODE_848
;
2936 } else if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_PANEL856
) {
2937 ivideo
->lcdxres
= 856; ivideo
->lcdyres
= 480;
2938 ivideo
->lcddefmodeidx
= DEFAULT_MODE_856
;
2942 printk(KERN_DEBUG
"sisfb: Detected %dx%d flat panel\n",
2943 ivideo
->lcdxres
, ivideo
->lcdyres
);
2946 static void sisfb_save_pdc_emi(struct sis_video_info
*ivideo
)
2948 #ifdef CONFIG_FB_SIS_300
2949 /* Save the current PanelDelayCompensation if the LCD is currently used */
2950 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2951 if(ivideo
->vbflags2
& (VB2_LVDS
| VB2_30xBDH
)) {
2953 tmp
= SiS_GetReg(SISCR
, 0x30);
2955 /* Currently on LCD? If yes, read current pdc */
2956 ivideo
->detectedpdc
= SiS_GetReg(SISPART1
, 0x13);
2957 ivideo
->detectedpdc
&= 0x3c;
2958 if(ivideo
->SiS_Pr
.PDC
== -1) {
2959 /* Let option override detection */
2960 ivideo
->SiS_Pr
.PDC
= ivideo
->detectedpdc
;
2962 printk(KERN_INFO
"sisfb: Detected LCD PDC 0x%02x\n",
2963 ivideo
->detectedpdc
);
2965 if((ivideo
->SiS_Pr
.PDC
!= -1) &&
2966 (ivideo
->SiS_Pr
.PDC
!= ivideo
->detectedpdc
)) {
2967 printk(KERN_INFO
"sisfb: Using LCD PDC 0x%02x\n",
2968 ivideo
->SiS_Pr
.PDC
);
2974 #ifdef CONFIG_FB_SIS_315
2975 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2977 /* Try to find about LCDA */
2978 if(ivideo
->vbflags2
& VB2_SISLCDABRIDGE
) {
2980 tmp
= SiS_GetReg(SISPART1
, 0x13);
2982 ivideo
->SiS_Pr
.SiS_UseLCDA
= true;
2983 ivideo
->detectedlcda
= 0x03;
2988 if(ivideo
->vbflags2
& VB2_SISLVDSBRIDGE
) {
2990 tmp
= SiS_GetReg(SISCR
, 0x30);
2991 if((tmp
& 0x20) || (ivideo
->detectedlcda
!= 0xff)) {
2992 /* Currently on LCD? If yes, read current pdc */
2994 pdc
= SiS_GetReg(SISPART1
, 0x2D);
2995 ivideo
->detectedpdc
= (pdc
& 0x0f) << 1;
2996 ivideo
->detectedpdca
= (pdc
& 0xf0) >> 3;
2997 pdc
= SiS_GetReg(SISPART1
, 0x35);
2998 ivideo
->detectedpdc
|= ((pdc
>> 7) & 0x01);
2999 pdc
= SiS_GetReg(SISPART1
, 0x20);
3000 ivideo
->detectedpdca
|= ((pdc
>> 6) & 0x01);
3001 if(ivideo
->newrom
) {
3002 /* New ROM invalidates other PDC resp. */
3003 if(ivideo
->detectedlcda
!= 0xff) {
3004 ivideo
->detectedpdc
= 0xff;
3006 ivideo
->detectedpdca
= 0xff;
3009 if(ivideo
->SiS_Pr
.PDC
== -1) {
3010 if(ivideo
->detectedpdc
!= 0xff) {
3011 ivideo
->SiS_Pr
.PDC
= ivideo
->detectedpdc
;
3014 if(ivideo
->SiS_Pr
.PDCA
== -1) {
3015 if(ivideo
->detectedpdca
!= 0xff) {
3016 ivideo
->SiS_Pr
.PDCA
= ivideo
->detectedpdca
;
3019 if(ivideo
->detectedpdc
!= 0xff) {
3021 "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3022 ivideo
->detectedpdc
);
3024 if(ivideo
->detectedpdca
!= 0xff) {
3026 "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3027 ivideo
->detectedpdca
);
3032 if(ivideo
->vbflags2
& VB2_SISEMIBRIDGE
) {
3033 ivideo
->SiS_Pr
.EMI_30
= SiS_GetReg(SISPART4
, 0x30);
3034 ivideo
->SiS_Pr
.EMI_31
= SiS_GetReg(SISPART4
, 0x31);
3035 ivideo
->SiS_Pr
.EMI_32
= SiS_GetReg(SISPART4
, 0x32);
3036 ivideo
->SiS_Pr
.EMI_33
= SiS_GetReg(SISPART4
, 0x33);
3037 ivideo
->SiS_Pr
.HaveEMI
= true;
3038 if((tmp
& 0x20) || (ivideo
->detectedlcda
!= 0xff)) {
3039 ivideo
->SiS_Pr
.HaveEMILCD
= true;
3044 /* Let user override detected PDCs (all bridges) */
3045 if(ivideo
->vbflags2
& VB2_30xBLV
) {
3046 if((ivideo
->SiS_Pr
.PDC
!= -1) &&
3047 (ivideo
->SiS_Pr
.PDC
!= ivideo
->detectedpdc
)) {
3048 printk(KERN_INFO
"sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3049 ivideo
->SiS_Pr
.PDC
);
3051 if((ivideo
->SiS_Pr
.PDCA
!= -1) &&
3052 (ivideo
->SiS_Pr
.PDCA
!= ivideo
->detectedpdca
)) {
3053 printk(KERN_INFO
"sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3054 ivideo
->SiS_Pr
.PDCA
);
3062 /* -------------------- Memory manager routines ---------------------- */
3064 static u32
sisfb_getheapstart(struct sis_video_info
*ivideo
)
3066 u32 ret
= ivideo
->sisfb_parm_mem
* 1024;
3067 u32 maxoffs
= ivideo
->video_size
- ivideo
->hwcursor_size
- ivideo
->cmdQueueSize
;
3070 /* Calculate heap start = end of memory for console
3072 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3073 * C = console, D = heap, H = HWCursor, Q = cmd-queue
3075 * On 76x in UMA+LFB mode, the layout is as follows:
3076 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3077 * where the heap is the entire UMA area, eventually
3078 * into the LFB area if the given mem parameter is
3079 * higher than the size of the UMA memory.
3081 * Basically given by "mem" parameter
3083 * maximum = videosize - cmd_queue - hwcursor
3084 * (results in a heap of size 0)
3085 * default = SiS 300: depends on videosize
3086 * SiS 315/330/340/XGI: 32k below max
3089 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3090 if(ivideo
->video_size
> 0x1000000) {
3092 } else if(ivideo
->video_size
> 0x800000) {
3097 } else if(ivideo
->UMAsize
&& ivideo
->LFBsize
) {
3100 def
= maxoffs
- 0x8000;
3103 /* Use default for secondary card for now (FIXME) */
3104 if((!ret
) || (ret
> maxoffs
) || (ivideo
->cardnumber
!= 0))
3110 static u32
sisfb_getheapsize(struct sis_video_info
*ivideo
)
3112 u32 max
= ivideo
->video_size
- ivideo
->hwcursor_size
- ivideo
->cmdQueueSize
;
3115 if(ivideo
->UMAsize
&& ivideo
->LFBsize
) {
3116 if( (!ivideo
->sisfb_parm_mem
) ||
3117 ((ivideo
->sisfb_parm_mem
* 1024) > max
) ||
3118 ((max
- (ivideo
->sisfb_parm_mem
* 1024)) < ivideo
->UMAsize
) ) {
3119 ret
= ivideo
->UMAsize
;
3120 max
-= ivideo
->UMAsize
;
3122 ret
= max
- (ivideo
->sisfb_parm_mem
* 1024);
3123 max
= ivideo
->sisfb_parm_mem
* 1024;
3125 ivideo
->video_offset
= ret
;
3126 ivideo
->sisfb_mem
= max
;
3128 ret
= max
- ivideo
->heapstart
;
3129 ivideo
->sisfb_mem
= ivideo
->heapstart
;
3135 static int sisfb_heap_init(struct sis_video_info
*ivideo
)
3139 ivideo
->video_offset
= 0;
3140 if(ivideo
->sisfb_parm_mem
) {
3141 if( (ivideo
->sisfb_parm_mem
< (2 * 1024 * 1024)) ||
3142 (ivideo
->sisfb_parm_mem
> ivideo
->video_size
) ) {
3143 ivideo
->sisfb_parm_mem
= 0;
3147 ivideo
->heapstart
= sisfb_getheapstart(ivideo
);
3148 ivideo
->sisfb_heap_size
= sisfb_getheapsize(ivideo
);
3150 ivideo
->sisfb_heap_start
= ivideo
->video_vbase
+ ivideo
->heapstart
;
3151 ivideo
->sisfb_heap_end
= ivideo
->sisfb_heap_start
+ ivideo
->sisfb_heap_size
;
3153 printk(KERN_INFO
"sisfb: Memory heap starting at %dK, size %dK\n",
3154 (int)(ivideo
->heapstart
/ 1024), (int)(ivideo
->sisfb_heap_size
/ 1024));
3156 ivideo
->sisfb_heap
.vinfo
= ivideo
;
3158 ivideo
->sisfb_heap
.poha_chain
= NULL
;
3159 ivideo
->sisfb_heap
.poh_freelist
= NULL
;
3161 poh
= sisfb_poh_new_node(&ivideo
->sisfb_heap
);
3165 poh
->poh_next
= &ivideo
->sisfb_heap
.oh_free
;
3166 poh
->poh_prev
= &ivideo
->sisfb_heap
.oh_free
;
3167 poh
->size
= ivideo
->sisfb_heap_size
;
3168 poh
->offset
= ivideo
->heapstart
;
3170 ivideo
->sisfb_heap
.oh_free
.poh_next
= poh
;
3171 ivideo
->sisfb_heap
.oh_free
.poh_prev
= poh
;
3172 ivideo
->sisfb_heap
.oh_free
.size
= 0;
3173 ivideo
->sisfb_heap
.max_freesize
= poh
->size
;
3175 ivideo
->sisfb_heap
.oh_used
.poh_next
= &ivideo
->sisfb_heap
.oh_used
;
3176 ivideo
->sisfb_heap
.oh_used
.poh_prev
= &ivideo
->sisfb_heap
.oh_used
;
3177 ivideo
->sisfb_heap
.oh_used
.size
= SENTINEL
;
3179 if(ivideo
->cardnumber
== 0) {
3180 /* For the first card, make this heap the "global" one
3181 * for old DRM (which could handle only one card)
3183 sisfb_heap
= &ivideo
->sisfb_heap
;
3189 static struct SIS_OH
*
3190 sisfb_poh_new_node(struct SIS_HEAP
*memheap
)
3192 struct SIS_OHALLOC
*poha
;
3197 if(memheap
->poh_freelist
== NULL
) {
3198 poha
= kmalloc(SIS_OH_ALLOC_SIZE
, GFP_KERNEL
);
3202 poha
->poha_next
= memheap
->poha_chain
;
3203 memheap
->poha_chain
= poha
;
3205 cOhs
= (SIS_OH_ALLOC_SIZE
- sizeof(struct SIS_OHALLOC
)) / sizeof(struct SIS_OH
) + 1;
3207 poh
= &poha
->aoh
[0];
3208 for(i
= cOhs
- 1; i
!= 0; i
--) {
3209 poh
->poh_next
= poh
+ 1;
3213 poh
->poh_next
= NULL
;
3214 memheap
->poh_freelist
= &poha
->aoh
[0];
3217 poh
= memheap
->poh_freelist
;
3218 memheap
->poh_freelist
= poh
->poh_next
;
3223 static struct SIS_OH
*
3224 sisfb_poh_allocate(struct SIS_HEAP
*memheap
, u32 size
)
3226 struct SIS_OH
*pohThis
;
3227 struct SIS_OH
*pohRoot
;
3230 if(size
> memheap
->max_freesize
) {
3231 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3232 (unsigned int) size
/ 1024);
3236 pohThis
= memheap
->oh_free
.poh_next
;
3238 while(pohThis
!= &memheap
->oh_free
) {
3239 if(size
<= pohThis
->size
) {
3243 pohThis
= pohThis
->poh_next
;
3247 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3248 (unsigned int) size
/ 1024);
3252 if(size
== pohThis
->size
) {
3254 sisfb_delete_node(pohThis
);
3256 pohRoot
= sisfb_poh_new_node(memheap
);
3260 pohRoot
->offset
= pohThis
->offset
;
3261 pohRoot
->size
= size
;
3263 pohThis
->offset
+= size
;
3264 pohThis
->size
-= size
;
3267 memheap
->max_freesize
-= size
;
3269 pohThis
= &memheap
->oh_used
;
3270 sisfb_insert_node(pohThis
, pohRoot
);
3276 sisfb_delete_node(struct SIS_OH
*poh
)
3278 poh
->poh_prev
->poh_next
= poh
->poh_next
;
3279 poh
->poh_next
->poh_prev
= poh
->poh_prev
;
3283 sisfb_insert_node(struct SIS_OH
*pohList
, struct SIS_OH
*poh
)
3285 struct SIS_OH
*pohTemp
= pohList
->poh_next
;
3287 pohList
->poh_next
= poh
;
3288 pohTemp
->poh_prev
= poh
;
3290 poh
->poh_prev
= pohList
;
3291 poh
->poh_next
= pohTemp
;
3294 static struct SIS_OH
*
3295 sisfb_poh_free(struct SIS_HEAP
*memheap
, u32 base
)
3297 struct SIS_OH
*pohThis
;
3298 struct SIS_OH
*poh_freed
;
3299 struct SIS_OH
*poh_prev
;
3300 struct SIS_OH
*poh_next
;
3305 poh_freed
= memheap
->oh_used
.poh_next
;
3307 while(poh_freed
!= &memheap
->oh_used
) {
3308 if(poh_freed
->offset
== base
) {
3313 poh_freed
= poh_freed
->poh_next
;
3319 memheap
->max_freesize
+= poh_freed
->size
;
3321 poh_prev
= poh_next
= NULL
;
3322 ulUpper
= poh_freed
->offset
+ poh_freed
->size
;
3323 ulLower
= poh_freed
->offset
;
3325 pohThis
= memheap
->oh_free
.poh_next
;
3327 while(pohThis
!= &memheap
->oh_free
) {
3328 if(pohThis
->offset
== ulUpper
) {
3330 } else if((pohThis
->offset
+ pohThis
->size
) == ulLower
) {
3333 pohThis
= pohThis
->poh_next
;
3336 sisfb_delete_node(poh_freed
);
3338 if(poh_prev
&& poh_next
) {
3339 poh_prev
->size
+= (poh_freed
->size
+ poh_next
->size
);
3340 sisfb_delete_node(poh_next
);
3341 sisfb_free_node(memheap
, poh_freed
);
3342 sisfb_free_node(memheap
, poh_next
);
3347 poh_prev
->size
+= poh_freed
->size
;
3348 sisfb_free_node(memheap
, poh_freed
);
3353 poh_next
->size
+= poh_freed
->size
;
3354 poh_next
->offset
= poh_freed
->offset
;
3355 sisfb_free_node(memheap
, poh_freed
);
3359 sisfb_insert_node(&memheap
->oh_free
, poh_freed
);
3365 sisfb_free_node(struct SIS_HEAP
*memheap
, struct SIS_OH
*poh
)
3370 poh
->poh_next
= memheap
->poh_freelist
;
3371 memheap
->poh_freelist
= poh
;
3375 sis_int_malloc(struct sis_video_info
*ivideo
, struct sis_memreq
*req
)
3377 struct SIS_OH
*poh
= NULL
;
3379 if((ivideo
) && (ivideo
->sisfb_id
== SISFB_ID
) && (!ivideo
->havenoheap
))
3380 poh
= sisfb_poh_allocate(&ivideo
->sisfb_heap
, (u32
)req
->size
);
3383 req
->offset
= req
->size
= 0;
3384 DPRINTK("sisfb: Video RAM allocation failed\n");
3386 req
->offset
= poh
->offset
;
3387 req
->size
= poh
->size
;
3388 DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3389 (poh
->offset
+ ivideo
->video_vbase
));
3394 sis_malloc(struct sis_memreq
*req
)
3396 struct sis_video_info
*ivideo
= sisfb_heap
->vinfo
;
3398 if(&ivideo
->sisfb_heap
== sisfb_heap
)
3399 sis_int_malloc(ivideo
, req
);
3401 req
->offset
= req
->size
= 0;
3405 sis_malloc_new(struct pci_dev
*pdev
, struct sis_memreq
*req
)
3407 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
3409 sis_int_malloc(ivideo
, req
);
3412 /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3415 sis_int_free(struct sis_video_info
*ivideo
, u32 base
)
3419 if((!ivideo
) || (ivideo
->sisfb_id
!= SISFB_ID
) || (ivideo
->havenoheap
))
3422 poh
= sisfb_poh_free(&ivideo
->sisfb_heap
, base
);
3425 DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
3426 (unsigned int) base
);
3433 struct sis_video_info
*ivideo
= sisfb_heap
->vinfo
;
3435 sis_int_free(ivideo
, base
);
3439 sis_free_new(struct pci_dev
*pdev
, u32 base
)
3441 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
3443 sis_int_free(ivideo
, base
);
3446 /* --------------------- SetMode routines ------------------------- */
3449 sisfb_check_engine_and_sync(struct sis_video_info
*ivideo
)
3453 /* Check if MMIO and engines are enabled,
3454 * and sync in case they are. Can't use
3455 * ivideo->accel here, as this might have
3456 * been changed before this is called.
3458 cr30
= SiS_GetReg(SISSR
, IND_SIS_PCI_ADDRESS_SET
);
3459 cr31
= SiS_GetReg(SISSR
, IND_SIS_MODULE_ENABLE
);
3460 /* MMIO and 2D/3D engine enabled? */
3461 if((cr30
& SIS_MEM_MAP_IO_ENABLE
) && (cr31
& 0x42)) {
3462 #ifdef CONFIG_FB_SIS_300
3463 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3464 /* Don't care about TurboQueue. It's
3465 * enough to know that the engines
3468 sisfb_syncaccel(ivideo
);
3471 #ifdef CONFIG_FB_SIS_315
3472 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3473 /* Check that any queue mode is
3474 * enabled, and that the queue
3475 * is not in the state of "reset"
3477 cr30
= SiS_GetReg(SISSR
, 0x26);
3478 if((cr30
& 0xe0) && (!(cr30
& 0x01))) {
3479 sisfb_syncaccel(ivideo
);
3487 sisfb_pre_setmode(struct sis_video_info
*ivideo
)
3489 u8 cr30
= 0, cr31
= 0, cr33
= 0, cr35
= 0, cr38
= 0;
3492 ivideo
->currentvbflags
&= (VB_VIDEOBRIDGE
| VB_DISPTYPE_DISP2
);
3494 SiS_SetReg(SISSR
, 0x05, 0x86);
3496 cr31
= SiS_GetReg(SISCR
, 0x31);
3500 cr33
= ivideo
->rate_idx
& 0x0F;
3502 #ifdef CONFIG_FB_SIS_315
3503 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3504 if(ivideo
->chip
>= SIS_661
) {
3505 cr38
= SiS_GetReg(SISCR
, 0x38);
3506 cr38
&= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
3509 cr38
= SiS_GetReg(SISCR
, tvregnum
);
3510 cr38
&= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
3514 #ifdef CONFIG_FB_SIS_300
3515 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3517 cr38
= SiS_GetReg(SISCR
, tvregnum
);
3521 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
3522 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
3523 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
3525 switch(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
3528 cr38
&= ~0xc0; /* Clear PAL-M / PAL-N bits */
3529 if((ivideo
->vbflags
& TV_YPBPR
) && (ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) {
3530 #ifdef CONFIG_FB_SIS_315
3531 if(ivideo
->chip
>= SIS_661
) {
3533 if(ivideo
->vbflags
& TV_YPBPR525P
) cr35
|= 0x20;
3534 else if(ivideo
->vbflags
& TV_YPBPR750P
) cr35
|= 0x40;
3535 else if(ivideo
->vbflags
& TV_YPBPR1080I
) cr35
|= 0x60;
3536 cr30
|= SIS_SIMULTANEOUS_VIEW_ENABLE
;
3538 ivideo
->currentvbflags
|= (TV_YPBPR
| (ivideo
->vbflags
& TV_YPBPRALL
));
3539 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3540 cr30
|= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE
);
3542 if(ivideo
->vbflags
& TV_YPBPR525P
) cr38
|= 0x10;
3543 else if(ivideo
->vbflags
& TV_YPBPR750P
) cr38
|= 0x20;
3544 else if(ivideo
->vbflags
& TV_YPBPR1080I
) cr38
|= 0x30;
3546 ivideo
->currentvbflags
|= (TV_YPBPR
| (ivideo
->vbflags
& TV_YPBPRALL
));
3549 } else if((ivideo
->vbflags
& TV_HIVISION
) &&
3550 (ivideo
->vbflags2
& VB2_SISHIVISIONBRIDGE
)) {
3551 if(ivideo
->chip
>= SIS_661
) {
3557 cr30
|= SIS_SIMULTANEOUS_VIEW_ENABLE
;
3560 ivideo
->currentvbflags
|= TV_HIVISION
;
3561 } else if(ivideo
->vbflags
& TV_SCART
) {
3562 cr30
= (SIS_VB_OUTPUT_SCART
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3565 ivideo
->currentvbflags
|= TV_SCART
;
3567 if(ivideo
->vbflags
& TV_SVIDEO
) {
3568 cr30
= (SIS_VB_OUTPUT_SVIDEO
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3569 ivideo
->currentvbflags
|= TV_SVIDEO
;
3571 if(ivideo
->vbflags
& TV_AVIDEO
) {
3572 cr30
= (SIS_VB_OUTPUT_COMPOSITE
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3573 ivideo
->currentvbflags
|= TV_AVIDEO
;
3576 cr31
|= SIS_DRIVER_MODE
;
3578 if(ivideo
->vbflags
& (TV_AVIDEO
| TV_SVIDEO
)) {
3579 if(ivideo
->vbflags
& TV_PAL
) {
3580 cr31
|= 0x01; cr35
|= 0x01;
3581 ivideo
->currentvbflags
|= TV_PAL
;
3582 if(ivideo
->vbflags
& TV_PALM
) {
3583 cr38
|= 0x40; cr35
|= 0x04;
3584 ivideo
->currentvbflags
|= TV_PALM
;
3585 } else if(ivideo
->vbflags
& TV_PALN
) {
3586 cr38
|= 0x80; cr35
|= 0x08;
3587 ivideo
->currentvbflags
|= TV_PALN
;
3590 cr31
&= ~0x01; cr35
&= ~0x01;
3591 ivideo
->currentvbflags
|= TV_NTSC
;
3592 if(ivideo
->vbflags
& TV_NTSCJ
) {
3593 cr38
|= 0x40; cr35
|= 0x02;
3594 ivideo
->currentvbflags
|= TV_NTSCJ
;
3601 cr30
= (SIS_VB_OUTPUT_LCD
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3602 cr31
|= SIS_DRIVER_MODE
;
3603 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, ivideo
->sisfb_dstn
);
3604 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, ivideo
->sisfb_fstn
);
3605 ivideo
->curFSTN
= ivideo
->sisfb_fstn
;
3606 ivideo
->curDSTN
= ivideo
->sisfb_dstn
;
3610 cr30
= (SIS_VB_OUTPUT_CRT2
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3611 cr31
|= SIS_DRIVER_MODE
;
3612 if(ivideo
->sisfb_nocrt2rate
) {
3613 cr33
|= (sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
<< 4);
3615 cr33
|= ((ivideo
->rate_idx
& 0x0F) << 4);
3619 default: /* disable CRT2 */
3621 cr31
|= (SIS_DRIVER_MODE
| SIS_VB_OUTPUT_DISABLE
);
3624 SiS_SetReg(SISCR
, 0x30, cr30
);
3625 SiS_SetReg(SISCR
, 0x33, cr33
);
3627 if(ivideo
->chip
>= SIS_661
) {
3628 #ifdef CONFIG_FB_SIS_315
3629 cr31
&= ~0x01; /* Clear PAL flag (now in CR35) */
3630 SiS_SetRegANDOR(SISCR
, 0x35, ~0x10, cr35
); /* Leave overscan bit alone */
3631 cr38
&= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
3632 SiS_SetRegANDOR(SISCR
, 0x38, 0xf8, cr38
);
3634 } else if(ivideo
->chip
!= SIS_300
) {
3635 SiS_SetReg(SISCR
, tvregnum
, cr38
);
3637 SiS_SetReg(SISCR
, 0x31, cr31
);
3639 ivideo
->SiS_Pr
.SiS_UseOEM
= ivideo
->sisfb_useoem
;
3641 sisfb_check_engine_and_sync(ivideo
);
3644 /* Fix SR11 for 661 and later */
3645 #ifdef CONFIG_FB_SIS_315
3647 sisfb_fixup_SR11(struct sis_video_info
*ivideo
)
3651 if(ivideo
->chip
>= SIS_661
) {
3652 tmpreg
= SiS_GetReg(SISSR
, 0x11);
3654 tmpreg
= SiS_GetReg(SISSR
, 0x3e);
3655 tmpreg
= (tmpreg
+ 1) & 0xff;
3656 SiS_SetReg(SISSR
, 0x3e, tmpreg
);
3657 tmpreg
= SiS_GetReg(SISSR
, 0x11);
3660 SiS_SetRegAND(SISSR
, 0x11, 0x0f);
3667 sisfb_set_TVxposoffset(struct sis_video_info
*ivideo
, int val
)
3669 if(val
> 32) val
= 32;
3670 if(val
< -32) val
= -32;
3671 ivideo
->tvxpos
= val
;
3673 if(ivideo
->sisfblocked
) return;
3674 if(!ivideo
->modechanged
) return;
3676 if(ivideo
->currentvbflags
& CRT2_TV
) {
3678 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3680 int x
= ivideo
->tvx
;
3682 switch(ivideo
->chronteltype
) {
3686 SiS_SetReg(SISSR
, 0x05, 0x86);
3687 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0a, (x
& 0xff));
3688 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x08, ((x
& 0x0100) >> 7), 0xFD);
3691 /* Not supported by hardware */
3695 } else if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3697 u8 p2_1f
,p2_20
,p2_2b
,p2_42
,p2_43
;
3698 unsigned short temp
;
3700 p2_1f
= ivideo
->p2_1f
;
3701 p2_20
= ivideo
->p2_20
;
3702 p2_2b
= ivideo
->p2_2b
;
3703 p2_42
= ivideo
->p2_42
;
3704 p2_43
= ivideo
->p2_43
;
3706 temp
= p2_1f
| ((p2_20
& 0xf0) << 4);
3708 p2_1f
= temp
& 0xff;
3709 p2_20
= (temp
& 0xf00) >> 4;
3710 p2_2b
= ((p2_2b
& 0x0f) + (val
* 2)) & 0x0f;
3711 temp
= p2_43
| ((p2_42
& 0xf0) << 4);
3713 p2_43
= temp
& 0xff;
3714 p2_42
= (temp
& 0xf00) >> 4;
3715 SiS_SetReg(SISPART2
, 0x1f, p2_1f
);
3716 SiS_SetRegANDOR(SISPART2
, 0x20, 0x0F, p2_20
);
3717 SiS_SetRegANDOR(SISPART2
, 0x2b, 0xF0, p2_2b
);
3718 SiS_SetRegANDOR(SISPART2
, 0x42, 0x0F, p2_42
);
3719 SiS_SetReg(SISPART2
, 0x43, p2_43
);
3725 sisfb_set_TVyposoffset(struct sis_video_info
*ivideo
, int val
)
3727 if(val
> 32) val
= 32;
3728 if(val
< -32) val
= -32;
3729 ivideo
->tvypos
= val
;
3731 if(ivideo
->sisfblocked
) return;
3732 if(!ivideo
->modechanged
) return;
3734 if(ivideo
->currentvbflags
& CRT2_TV
) {
3736 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3738 int y
= ivideo
->tvy
;
3740 switch(ivideo
->chronteltype
) {
3744 SiS_SetReg(SISSR
, 0x05, 0x86);
3745 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0b, (y
& 0xff));
3746 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x08, ((y
& 0x0100) >> 8), 0xFE);
3749 /* Not supported by hardware */
3753 } else if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3757 p2_01
= ivideo
->p2_01
;
3758 p2_02
= ivideo
->p2_02
;
3762 if(!(ivideo
->currentvbflags
& (TV_HIVISION
| TV_YPBPR
))) {
3763 while((p2_01
<= 0) || (p2_02
<= 0)) {
3768 SiS_SetReg(SISPART2
, 0x01, p2_01
);
3769 SiS_SetReg(SISPART2
, 0x02, p2_02
);
3775 sisfb_post_setmode(struct sis_video_info
*ivideo
)
3777 bool crt1isoff
= false;
3779 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
3782 #ifdef CONFIG_FB_SIS_315
3786 SiS_SetReg(SISSR
, 0x05, 0x86);
3788 #ifdef CONFIG_FB_SIS_315
3789 sisfb_fixup_SR11(ivideo
);
3792 /* Now we actually HAVE changed the display mode */
3793 ivideo
->modechanged
= 1;
3795 /* We can't switch off CRT1 if bridge is in slave mode */
3796 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
3797 if(sisfb_bridgeisslave(ivideo
)) doit
= false;
3799 ivideo
->sisfb_crt1off
= 0;
3801 #ifdef CONFIG_FB_SIS_300
3802 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3803 if((ivideo
->sisfb_crt1off
) && (doit
)) {
3810 SiS_SetRegANDOR(SISCR
, 0x17, 0x7f, reg
);
3813 #ifdef CONFIG_FB_SIS_315
3814 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3815 if((ivideo
->sisfb_crt1off
) && (doit
)) {
3824 SiS_SetRegANDOR(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, ~0x40, reg
);
3825 SiS_SetRegANDOR(SISSR
, 0x1f, 0x3f, reg1
);
3830 ivideo
->currentvbflags
&= ~VB_DISPTYPE_CRT1
;
3831 ivideo
->currentvbflags
|= VB_SINGLE_MODE
;
3833 ivideo
->currentvbflags
|= VB_DISPTYPE_CRT1
;
3834 if(ivideo
->currentvbflags
& VB_DISPTYPE_CRT2
) {
3835 ivideo
->currentvbflags
|= VB_MIRROR_MODE
;
3837 ivideo
->currentvbflags
|= VB_SINGLE_MODE
;
3841 SiS_SetRegAND(SISSR
, IND_SIS_RAMDAC_CONTROL
, ~0x04);
3843 if(ivideo
->currentvbflags
& CRT2_TV
) {
3844 if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3845 ivideo
->p2_1f
= SiS_GetReg(SISPART2
, 0x1f);
3846 ivideo
->p2_20
= SiS_GetReg(SISPART2
, 0x20);
3847 ivideo
->p2_2b
= SiS_GetReg(SISPART2
, 0x2b);
3848 ivideo
->p2_42
= SiS_GetReg(SISPART2
, 0x42);
3849 ivideo
->p2_43
= SiS_GetReg(SISPART2
, 0x43);
3850 ivideo
->p2_01
= SiS_GetReg(SISPART2
, 0x01);
3851 ivideo
->p2_02
= SiS_GetReg(SISPART2
, 0x02);
3852 } else if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3853 if(ivideo
->chronteltype
== 1) {
3854 ivideo
->tvx
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0a);
3855 ivideo
->tvx
|= (((SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x08) & 0x02) >> 1) << 8);
3856 ivideo
->tvy
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0b);
3857 ivideo
->tvy
|= ((SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x08) & 0x01) << 8);
3862 if(ivideo
->tvxpos
) {
3863 sisfb_set_TVxposoffset(ivideo
, ivideo
->tvxpos
);
3865 if(ivideo
->tvypos
) {
3866 sisfb_set_TVyposoffset(ivideo
, ivideo
->tvypos
);
3869 /* Eventually sync engines */
3870 sisfb_check_engine_and_sync(ivideo
);
3872 /* (Re-)Initialize chip engines */
3874 sisfb_engine_init(ivideo
);
3876 ivideo
->engineok
= 0;
3881 sisfb_reset_mode(struct sis_video_info
*ivideo
)
3883 if(sisfb_set_mode(ivideo
, 0))
3886 sisfb_set_pitch(ivideo
);
3887 sisfb_set_base_CRT1(ivideo
, ivideo
->current_base
);
3888 sisfb_set_base_CRT2(ivideo
, ivideo
->current_base
);
3894 sisfb_handle_command(struct sis_video_info
*ivideo
, struct sisfb_cmd
*sisfb_command
)
3898 switch(sisfb_command
->sisfb_cmd
) {
3899 case SISFB_CMD_GETVBFLAGS
:
3900 if(!ivideo
->modechanged
) {
3901 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_EARLY
;
3903 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3904 sisfb_command
->sisfb_result
[1] = ivideo
->currentvbflags
;
3905 sisfb_command
->sisfb_result
[2] = ivideo
->vbflags2
;
3908 case SISFB_CMD_SWITCHCRT1
:
3909 /* arg[0]: 0 = off, 1 = on, 99 = query */
3910 if(!ivideo
->modechanged
) {
3911 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_EARLY
;
3912 } else if(sisfb_command
->sisfb_arg
[0] == 99) {
3914 sisfb_command
->sisfb_result
[1] = ivideo
->sisfb_crt1off
? 0 : 1;
3915 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3916 } else if(ivideo
->sisfblocked
) {
3917 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_LOCKED
;
3918 } else if((!(ivideo
->currentvbflags
& CRT2_ENABLE
)) &&
3919 (sisfb_command
->sisfb_arg
[0] == 0)) {
3920 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_NOCRT2
;
3922 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3923 mycrt1off
= sisfb_command
->sisfb_arg
[0] ? 0 : 1;
3924 if( ((ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
) && mycrt1off
) ||
3925 ((!(ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
)) && !mycrt1off
) ) {
3926 ivideo
->sisfb_crt1off
= mycrt1off
;
3927 if(sisfb_reset_mode(ivideo
)) {
3928 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OTHER
;
3931 sisfb_command
->sisfb_result
[1] = ivideo
->sisfb_crt1off
? 0 : 1;
3936 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_UNKNOWN
;
3937 printk(KERN_ERR
"sisfb: Unknown command 0x%x\n",
3938 sisfb_command
->sisfb_cmd
);
3943 static int __init
sisfb_setup(char *options
)
3947 sisfb_setdefaultparms();
3949 if(!options
|| !(*options
))
3952 while((this_opt
= strsep(&options
, ",")) != NULL
) {
3954 if(!(*this_opt
)) continue;
3956 if(!strncasecmp(this_opt
, "off", 3)) {
3958 } else if(!strncasecmp(this_opt
, "forcecrt2type:", 14)) {
3959 /* Need to check crt2 type first for fstn/dstn */
3960 sisfb_search_crt2type(this_opt
+ 14);
3961 } else if(!strncasecmp(this_opt
, "tvmode:",7)) {
3962 sisfb_search_tvstd(this_opt
+ 7);
3963 } else if(!strncasecmp(this_opt
, "tvstandard:",11)) {
3964 sisfb_search_tvstd(this_opt
+ 11);
3965 } else if(!strncasecmp(this_opt
, "mode:", 5)) {
3966 sisfb_search_mode(this_opt
+ 5, false);
3967 } else if(!strncasecmp(this_opt
, "vesa:", 5)) {
3968 sisfb_search_vesamode(simple_strtoul(this_opt
+ 5, NULL
, 0), false);
3969 } else if(!strncasecmp(this_opt
, "rate:", 5)) {
3970 sisfb_parm_rate
= simple_strtoul(this_opt
+ 5, NULL
, 0);
3971 } else if(!strncasecmp(this_opt
, "forcecrt1:", 10)) {
3972 sisfb_forcecrt1
= (int)simple_strtoul(this_opt
+ 10, NULL
, 0);
3973 } else if(!strncasecmp(this_opt
, "mem:",4)) {
3974 sisfb_parm_mem
= simple_strtoul(this_opt
+ 4, NULL
, 0);
3975 } else if(!strncasecmp(this_opt
, "pdc:", 4)) {
3976 sisfb_pdc
= simple_strtoul(this_opt
+ 4, NULL
, 0);
3977 } else if(!strncasecmp(this_opt
, "pdc1:", 5)) {
3978 sisfb_pdca
= simple_strtoul(this_opt
+ 5, NULL
, 0);
3979 } else if(!strncasecmp(this_opt
, "noaccel", 7)) {
3981 } else if(!strncasecmp(this_opt
, "accel", 5)) {
3983 } else if(!strncasecmp(this_opt
, "noypan", 6)) {
3985 } else if(!strncasecmp(this_opt
, "ypan", 4)) {
3987 } else if(!strncasecmp(this_opt
, "nomax", 5)) {
3989 } else if(!strncasecmp(this_opt
, "max", 3)) {
3991 } else if(!strncasecmp(this_opt
, "userom:", 7)) {
3992 sisfb_userom
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
3993 } else if(!strncasecmp(this_opt
, "useoem:", 7)) {
3994 sisfb_useoem
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
3995 } else if(!strncasecmp(this_opt
, "nocrt2rate", 10)) {
3996 sisfb_nocrt2rate
= 1;
3997 } else if(!strncasecmp(this_opt
, "scalelcd:", 9)) {
3998 unsigned long temp
= 2;
3999 temp
= simple_strtoul(this_opt
+ 9, NULL
, 0);
4000 if((temp
== 0) || (temp
== 1)) {
4001 sisfb_scalelcd
= temp
^ 1;
4003 } else if(!strncasecmp(this_opt
, "tvxposoffset:", 13)) {
4005 temp
= (int)simple_strtol(this_opt
+ 13, NULL
, 0);
4006 if((temp
>= -32) && (temp
<= 32)) {
4007 sisfb_tvxposoffset
= temp
;
4009 } else if(!strncasecmp(this_opt
, "tvyposoffset:", 13)) {
4011 temp
= (int)simple_strtol(this_opt
+ 13, NULL
, 0);
4012 if((temp
>= -32) && (temp
<= 32)) {
4013 sisfb_tvyposoffset
= temp
;
4015 } else if(!strncasecmp(this_opt
, "specialtiming:", 14)) {
4016 sisfb_search_specialtiming(this_opt
+ 14);
4017 } else if(!strncasecmp(this_opt
, "lvdshl:", 7)) {
4019 temp
= simple_strtoul(this_opt
+ 7, NULL
, 0);
4020 if((temp
>= 0) && (temp
<= 3)) {
4021 sisfb_lvdshl
= temp
;
4023 } else if(this_opt
[0] >= '0' && this_opt
[0] <= '9') {
4024 sisfb_search_mode(this_opt
, true);
4025 #if !defined(__i386__) && !defined(__x86_64__)
4026 } else if(!strncasecmp(this_opt
, "resetcard", 9)) {
4027 sisfb_resetcard
= 1;
4028 } else if(!strncasecmp(this_opt
, "videoram:", 9)) {
4029 sisfb_videoram
= simple_strtoul(this_opt
+ 9, NULL
, 0);
4032 printk(KERN_INFO
"sisfb: Invalid option %s\n", this_opt
);
4041 static int sisfb_check_rom(void __iomem
*rom_base
,
4042 struct sis_video_info
*ivideo
)
4047 if((readb(rom_base
) != 0x55) || (readb(rom_base
+ 1) != 0xaa))
4050 romptr
= (readb(rom_base
+ 0x18) | (readb(rom_base
+ 0x19) << 8));
4051 if(romptr
> (0x10000 - 8))
4054 rom
= rom_base
+ romptr
;
4056 if((readb(rom
) != 'P') || (readb(rom
+ 1) != 'C') ||
4057 (readb(rom
+ 2) != 'I') || (readb(rom
+ 3) != 'R'))
4060 if((readb(rom
+ 4) | (readb(rom
+ 5) << 8)) != ivideo
->chip_vendor
)
4063 if((readb(rom
+ 6) | (readb(rom
+ 7) << 8)) != ivideo
->chip_id
)
4069 static unsigned char *sisfb_find_rom(struct pci_dev
*pdev
)
4071 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4072 void __iomem
*rom_base
;
4073 unsigned char *myrombase
= NULL
;
4076 /* First, try the official pci ROM functions (except
4077 * on integrated chipsets which have no ROM).
4080 if(!ivideo
->nbridge
) {
4082 if((rom_base
= pci_map_rom(pdev
, &romsize
))) {
4084 if(sisfb_check_rom(rom_base
, ivideo
)) {
4086 if((myrombase
= vmalloc(65536))) {
4087 memcpy_fromio(myrombase
, rom_base
,
4088 (romsize
> 65536) ? 65536 : romsize
);
4091 pci_unmap_rom(pdev
, rom_base
);
4095 if(myrombase
) return myrombase
;
4097 /* Otherwise do it the conventional way. */
4099 #if defined(__i386__) || defined(__x86_64__)
4103 for (temp
= 0x000c0000; temp
< 0x000f0000; temp
+= 0x00001000) {
4105 rom_base
= ioremap(temp
, 65536);
4109 if (!sisfb_check_rom(rom_base
, ivideo
)) {
4114 if ((myrombase
= vmalloc(65536)))
4115 memcpy_fromio(myrombase
, rom_base
, 65536);
4128 static void sisfb_post_map_vram(struct sis_video_info
*ivideo
,
4129 unsigned int *mapsize
, unsigned int min
)
4131 if (*mapsize
< (min
<< 20))
4134 ivideo
->video_vbase
= ioremap_wc(ivideo
->video_base
, (*mapsize
));
4136 if(!ivideo
->video_vbase
) {
4138 "sisfb: Unable to map maximum video RAM for size detection\n");
4140 while((!(ivideo
->video_vbase
= ioremap_wc(ivideo
->video_base
, (*mapsize
))))) {
4142 if((*mapsize
) < (min
<< 20))
4145 if(ivideo
->video_vbase
) {
4147 "sisfb: Video RAM size detection limited to %dMB\n",
4148 (int)((*mapsize
) >> 20));
4153 #ifdef CONFIG_FB_SIS_300
4154 static int sisfb_post_300_buswidth(struct sis_video_info
*ivideo
)
4156 void __iomem
*FBAddress
= ivideo
->video_vbase
;
4157 unsigned short temp
;
4161 SiS_SetRegAND(SISSR
, 0x15, 0xFB);
4162 SiS_SetRegOR(SISSR
, 0x15, 0x04);
4163 SiS_SetReg(SISSR
, 0x13, 0x00);
4164 SiS_SetReg(SISSR
, 0x14, 0xBF);
4166 for(i
= 0; i
< 2; i
++) {
4168 for(j
= 0; j
< 4; j
++) {
4169 writew(temp
, FBAddress
);
4170 if(readw(FBAddress
) == temp
)
4172 SiS_SetRegOR(SISSR
, 0x3c, 0x01);
4173 reg
= SiS_GetReg(SISSR
, 0x05);
4174 reg
= SiS_GetReg(SISSR
, 0x05);
4175 SiS_SetRegAND(SISSR
, 0x3c, 0xfe);
4176 reg
= SiS_GetReg(SISSR
, 0x05);
4177 reg
= SiS_GetReg(SISSR
, 0x05);
4182 writel(0x01234567L
, FBAddress
);
4183 writel(0x456789ABL
, (FBAddress
+ 4));
4184 writel(0x89ABCDEFL
, (FBAddress
+ 8));
4185 writel(0xCDEF0123L
, (FBAddress
+ 12));
4187 reg
= SiS_GetReg(SISSR
, 0x3b);
4189 if(readl((FBAddress
+ 12)) == 0xCDEF0123L
)
4190 return 4; /* Channel A 128bit */
4193 if(readl((FBAddress
+ 4)) == 0x456789ABL
)
4194 return 2; /* Channel B 64bit */
4196 return 1; /* 32bit */
4199 static const unsigned short SiS_DRAMType
[17][5] = {
4200 {0x0C,0x0A,0x02,0x40,0x39},
4201 {0x0D,0x0A,0x01,0x40,0x48},
4202 {0x0C,0x09,0x02,0x20,0x35},
4203 {0x0D,0x09,0x01,0x20,0x44},
4204 {0x0C,0x08,0x02,0x10,0x31},
4205 {0x0D,0x08,0x01,0x10,0x40},
4206 {0x0C,0x0A,0x01,0x20,0x34},
4207 {0x0C,0x09,0x01,0x08,0x32},
4208 {0x0B,0x08,0x02,0x08,0x21},
4209 {0x0C,0x08,0x01,0x08,0x30},
4210 {0x0A,0x08,0x02,0x04,0x11},
4211 {0x0B,0x0A,0x01,0x10,0x28},
4212 {0x09,0x08,0x02,0x02,0x01},
4213 {0x0B,0x09,0x01,0x08,0x24},
4214 {0x0B,0x08,0x01,0x04,0x20},
4215 {0x0A,0x08,0x01,0x02,0x10},
4216 {0x09,0x08,0x01,0x01,0x00}
4219 static int sisfb_post_300_rwtest(struct sis_video_info
*ivideo
, int iteration
,
4220 int buswidth
, int PseudoRankCapacity
,
4221 int PseudoAdrPinCount
, unsigned int mapsize
)
4223 void __iomem
*FBAddr
= ivideo
->video_vbase
;
4224 unsigned short sr14
;
4225 unsigned int k
, RankCapacity
, PageCapacity
, BankNumHigh
, BankNumMid
;
4226 unsigned int PhysicalAdrOtherPage
, PhysicalAdrHigh
, PhysicalAdrHalfPage
;
4228 for(k
= 0; k
< ARRAY_SIZE(SiS_DRAMType
); k
++) {
4230 RankCapacity
= buswidth
* SiS_DRAMType
[k
][3];
4232 if(RankCapacity
!= PseudoRankCapacity
)
4235 if((SiS_DRAMType
[k
][2] + SiS_DRAMType
[k
][0]) > PseudoAdrPinCount
)
4238 BankNumHigh
= RankCapacity
* 16 * iteration
- 1;
4239 if(iteration
== 3) { /* Rank No */
4240 BankNumMid
= RankCapacity
* 16 - 1;
4242 BankNumMid
= RankCapacity
* 16 * iteration
/ 2 - 1;
4245 PageCapacity
= (1 << SiS_DRAMType
[k
][1]) * buswidth
* 4;
4246 PhysicalAdrHigh
= BankNumHigh
;
4247 PhysicalAdrHalfPage
= (PageCapacity
/ 2 + PhysicalAdrHigh
) % PageCapacity
;
4248 PhysicalAdrOtherPage
= PageCapacity
* SiS_DRAMType
[k
][2] + PhysicalAdrHigh
;
4250 SiS_SetRegAND(SISSR
, 0x15, 0xFB); /* Test */
4251 SiS_SetRegOR(SISSR
, 0x15, 0x04); /* Test */
4252 sr14
= (SiS_DRAMType
[k
][3] * buswidth
) - 1;
4253 if(buswidth
== 4) sr14
|= 0x80;
4254 else if(buswidth
== 2) sr14
|= 0x40;
4255 SiS_SetReg(SISSR
, 0x13, SiS_DRAMType
[k
][4]);
4256 SiS_SetReg(SISSR
, 0x14, sr14
);
4261 if((BankNumHigh
+ PhysicalAdrHigh
>= mapsize
) ||
4262 (BankNumMid
+ PhysicalAdrHigh
>= mapsize
) ||
4263 (BankNumHigh
+ PhysicalAdrHalfPage
>= mapsize
) ||
4264 (BankNumHigh
+ PhysicalAdrOtherPage
>= mapsize
))
4268 writew(((unsigned short)PhysicalAdrHigh
),
4269 (FBAddr
+ BankNumHigh
+ PhysicalAdrHigh
));
4270 writew(((unsigned short)BankNumMid
),
4271 (FBAddr
+ BankNumMid
+ PhysicalAdrHigh
));
4272 writew(((unsigned short)PhysicalAdrHalfPage
),
4273 (FBAddr
+ BankNumHigh
+ PhysicalAdrHalfPage
));
4274 writew(((unsigned short)PhysicalAdrOtherPage
),
4275 (FBAddr
+ BankNumHigh
+ PhysicalAdrOtherPage
));
4278 if(readw(FBAddr
+ BankNumHigh
+ PhysicalAdrHigh
) == PhysicalAdrHigh
)
4285 static void sisfb_post_300_ramsize(struct pci_dev
*pdev
, unsigned int mapsize
)
4287 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4289 int PseudoRankCapacity
, PseudoAdrPinCount
;
4291 buswidth
= sisfb_post_300_buswidth(ivideo
);
4293 for(i
= 6; i
>= 0; i
--) {
4294 PseudoRankCapacity
= 1 << i
;
4295 for(j
= 4; j
>= 1; j
--) {
4296 PseudoAdrPinCount
= 15 - j
;
4297 if((PseudoRankCapacity
* j
) <= 64) {
4298 if(sisfb_post_300_rwtest(ivideo
,
4310 static void sisfb_post_sis300(struct pci_dev
*pdev
)
4312 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4313 unsigned char *bios
= ivideo
->SiS_Pr
.VirtualRomBase
;
4314 u8 reg
, v1
, v2
, v3
, v4
, v5
, v6
, v7
, v8
;
4315 u16 index
, rindex
, memtype
= 0;
4316 unsigned int mapsize
;
4318 if(!ivideo
->SiS_Pr
.UseROM
)
4321 SiS_SetReg(SISSR
, 0x05, 0x86);
4324 if(bios
[0x52] & 0x80) {
4325 memtype
= bios
[0x52];
4327 memtype
= SiS_GetReg(SISSR
, 0x3a);
4332 v3
= 0x80; v6
= 0x80;
4333 if(ivideo
->revision_id
<= 0x13) {
4334 v1
= 0x44; v2
= 0x42;
4335 v4
= 0x44; v5
= 0x42;
4337 v1
= 0x68; v2
= 0x43; /* Assume 125Mhz MCLK */
4338 v4
= 0x68; v5
= 0x43; /* Assume 125Mhz ECLK */
4340 index
= memtype
* 5;
4341 rindex
= index
+ 0x54;
4342 v1
= bios
[rindex
++];
4343 v2
= bios
[rindex
++];
4344 v3
= bios
[rindex
++];
4345 rindex
= index
+ 0x7c;
4346 v4
= bios
[rindex
++];
4347 v5
= bios
[rindex
++];
4348 v6
= bios
[rindex
++];
4351 SiS_SetReg(SISSR
, 0x28, v1
);
4352 SiS_SetReg(SISSR
, 0x29, v2
);
4353 SiS_SetReg(SISSR
, 0x2a, v3
);
4354 SiS_SetReg(SISSR
, 0x2e, v4
);
4355 SiS_SetReg(SISSR
, 0x2f, v5
);
4356 SiS_SetReg(SISSR
, 0x30, v6
);
4361 SiS_SetReg(SISSR
, 0x07, v1
); /* DAC speed */
4363 SiS_SetReg(SISSR
, 0x11, 0x0f); /* DDC, power save */
4365 v1
= 0x01; v2
= 0x43; v3
= 0x1e; v4
= 0x2a;
4366 v5
= 0x06; v6
= 0x00; v7
= 0x00; v8
= 0x00;
4370 v2
= bios
[memtype
+ 8];
4371 v3
= bios
[memtype
+ 16];
4372 v4
= bios
[memtype
+ 24];
4373 v5
= bios
[memtype
+ 32];
4374 v6
= bios
[memtype
+ 40];
4375 v7
= bios
[memtype
+ 48];
4376 v8
= bios
[memtype
+ 56];
4378 if(ivideo
->revision_id
>= 0x80)
4380 SiS_SetReg(SISSR
, 0x15, v1
); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4381 SiS_SetReg(SISSR
, 0x16, v2
);
4382 SiS_SetReg(SISSR
, 0x17, v3
);
4383 SiS_SetReg(SISSR
, 0x18, v4
);
4384 SiS_SetReg(SISSR
, 0x19, v5
);
4385 SiS_SetReg(SISSR
, 0x1a, v6
);
4386 SiS_SetReg(SISSR
, 0x1b, v7
);
4387 SiS_SetReg(SISSR
, 0x1c, v8
); /* ---- */
4388 SiS_SetRegAND(SISSR
, 0x15, 0xfb);
4389 SiS_SetRegOR(SISSR
, 0x15, 0x04);
4391 if(bios
[0x53] & 0x02) {
4392 SiS_SetRegOR(SISSR
, 0x19, 0x20);
4395 v1
= 0x04; /* DAC pedestal (BIOS 0xe5) */
4396 if(ivideo
->revision_id
>= 0x80)
4398 SiS_SetReg(SISSR
, 0x1f, v1
);
4399 SiS_SetReg(SISSR
, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
4400 v1
= 0xf6; v2
= 0x0d; v3
= 0x00;
4406 SiS_SetReg(SISSR
, 0x23, v1
);
4407 SiS_SetReg(SISSR
, 0x24, v2
);
4408 SiS_SetReg(SISSR
, 0x25, v3
);
4409 SiS_SetReg(SISSR
, 0x21, 0x84);
4410 SiS_SetReg(SISSR
, 0x22, 0x00);
4411 SiS_SetReg(SISCR
, 0x37, 0x00);
4412 SiS_SetRegOR(SISPART1
, 0x24, 0x01); /* unlock crt2 */
4413 SiS_SetReg(SISPART1
, 0x00, 0x00);
4414 v1
= 0x40; v2
= 0x11;
4419 SiS_SetReg(SISPART1
, 0x02, v1
);
4421 if(ivideo
->revision_id
>= 0x80)
4424 reg
= SiS_GetReg(SISPART4
, 0x00);
4425 if((reg
== 1) || (reg
== 2)) {
4426 SiS_SetReg(SISCR
, 0x37, 0x02);
4427 SiS_SetReg(SISPART2
, 0x00, 0x1c);
4428 v4
= 0x00; v5
= 0x00; v6
= 0x10;
4429 if(ivideo
->SiS_Pr
.UseROM
) {
4434 SiS_SetReg(SISPART4
, 0x0d, v4
);
4435 SiS_SetReg(SISPART4
, 0x0e, v5
);
4436 SiS_SetReg(SISPART4
, 0x10, v6
);
4437 SiS_SetReg(SISPART4
, 0x0f, 0x3f);
4438 reg
= SiS_GetReg(SISPART4
, 0x01);
4440 reg
= SiS_GetReg(SISPART4
, 0x23);
4443 SiS_SetReg(SISPART4
, 0x23, reg
);
4448 SiS_SetReg(SISSR
, 0x32, v2
);
4450 SiS_SetRegAND(SISPART1
, 0x24, 0xfe); /* Lock CRT2 */
4452 reg
= SiS_GetReg(SISSR
, 0x16);
4454 SiS_SetReg(SISCR
, 0x35, reg
);
4455 SiS_SetReg(SISCR
, 0x83, 0x00);
4456 #if !defined(__i386__) && !defined(__x86_64__)
4457 if(sisfb_videoram
) {
4458 SiS_SetReg(SISSR
, 0x13, 0x28); /* ? */
4459 reg
= ((sisfb_videoram
>> 10) - 1) | 0x40;
4460 SiS_SetReg(SISSR
, 0x14, reg
);
4463 /* Need to map max FB size for finding out about RAM size */
4464 mapsize
= ivideo
->video_size
;
4465 sisfb_post_map_vram(ivideo
, &mapsize
, 4);
4467 if(ivideo
->video_vbase
) {
4468 sisfb_post_300_ramsize(pdev
, mapsize
);
4469 iounmap(ivideo
->video_vbase
);
4472 "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4473 SiS_SetReg(SISSR
, 0x13, 0x28); /* ? */
4474 SiS_SetReg(SISSR
, 0x14, 0x47); /* 8MB, 64bit default */
4476 #if !defined(__i386__) && !defined(__x86_64__)
4483 reg
= SiS_GetReg(SISSR
, 0x3a);
4484 if((reg
& 0x30) == 0x30) {
4485 v1
= 0x04; /* PCI */
4488 v1
= 0x14; /* AGP */
4492 SiS_SetReg(SISSR
, 0x21, v1
);
4493 SiS_SetReg(SISSR
, 0x22, v2
);
4496 sisfb_sense_crt1(ivideo
);
4498 /* Set default mode, don't clear screen */
4499 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
4500 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
4501 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
4502 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
4503 ivideo
->SiS_Pr
.VideoMemorySize
= 8 << 20;
4504 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
4506 SiS_SetReg(SISSR
, 0x05, 0x86);
4509 SiS_SetRegOR(SISSR
, 0x01, 0x20);
4511 /* Save mode number in CR34 */
4512 SiS_SetReg(SISCR
, 0x34, 0x2e);
4514 /* Let everyone know what the current mode is */
4515 ivideo
->modeprechange
= 0x2e;
4519 #ifdef CONFIG_FB_SIS_315
4521 static void sisfb_post_sis315330(struct pci_dev
*pdev
)
4527 static inline int sisfb_xgi_is21(struct sis_video_info
*ivideo
)
4529 return ivideo
->chip_real_id
== XGI_21
;
4532 static void sisfb_post_xgi_delay(struct sis_video_info
*ivideo
, int delay
)
4537 for(i
= 0; i
<= (delay
* 10 * 36); i
++) {
4538 reg
= SiS_GetReg(SISSR
, 0x05);
4543 static int sisfb_find_host_bridge(struct sis_video_info
*ivideo
,
4544 struct pci_dev
*mypdev
,
4545 unsigned short pcivendor
)
4547 struct pci_dev
*pdev
= NULL
;
4548 unsigned short temp
;
4551 while((pdev
= pci_get_class(PCI_CLASS_BRIDGE_HOST
, pdev
))) {
4552 temp
= pdev
->vendor
;
4553 if(temp
== pcivendor
) {
4563 static int sisfb_post_xgi_rwtest(struct sis_video_info
*ivideo
, int starta
,
4564 unsigned int enda
, unsigned int mapsize
)
4569 writel(0, ivideo
->video_vbase
);
4571 for(i
= starta
; i
<= enda
; i
++) {
4574 writel(pos
, ivideo
->video_vbase
+ pos
);
4577 sisfb_post_xgi_delay(ivideo
, 150);
4579 if(readl(ivideo
->video_vbase
) != 0)
4582 for(i
= starta
; i
<= enda
; i
++) {
4585 if(readl(ivideo
->video_vbase
+ pos
) != pos
)
4594 static int sisfb_post_xgi_ramsize(struct sis_video_info
*ivideo
)
4596 unsigned int buswidth
, ranksize
, channelab
, mapsize
;
4597 int i
, j
, k
, l
, status
;
4599 static const u8 dramsr13
[12 * 5] = {
4600 0x02, 0x0e, 0x0b, 0x80, 0x5d,
4601 0x02, 0x0e, 0x0a, 0x40, 0x59,
4602 0x02, 0x0d, 0x0b, 0x40, 0x4d,
4603 0x02, 0x0e, 0x09, 0x20, 0x55,
4604 0x02, 0x0d, 0x0a, 0x20, 0x49,
4605 0x02, 0x0c, 0x0b, 0x20, 0x3d,
4606 0x02, 0x0e, 0x08, 0x10, 0x51,
4607 0x02, 0x0d, 0x09, 0x10, 0x45,
4608 0x02, 0x0c, 0x0a, 0x10, 0x39,
4609 0x02, 0x0d, 0x08, 0x08, 0x41,
4610 0x02, 0x0c, 0x09, 0x08, 0x35,
4611 0x02, 0x0c, 0x08, 0x04, 0x31
4613 static const u8 dramsr13_4
[4 * 5] = {
4614 0x02, 0x0d, 0x09, 0x40, 0x45,
4615 0x02, 0x0c, 0x09, 0x20, 0x35,
4616 0x02, 0x0c, 0x08, 0x10, 0x31,
4617 0x02, 0x0b, 0x08, 0x08, 0x21
4620 /* Enable linear mode, disable 0xa0000 address decoding */
4621 /* We disable a0000 address decoding, because
4622 * - if running on x86, if the card is disabled, it means
4623 * that another card is in the system. We don't want
4624 * to interphere with that primary card's textmode.
4625 * - if running on non-x86, there usually is no VGA window
4628 SiS_SetRegOR(SISSR
, 0x20, (0x80 | 0x04));
4630 /* Need to map max FB size for finding out about RAM size */
4631 mapsize
= ivideo
->video_size
;
4632 sisfb_post_map_vram(ivideo
, &mapsize
, 32);
4634 if(!ivideo
->video_vbase
) {
4635 printk(KERN_ERR
"sisfb: Unable to detect RAM size. Setting default.\n");
4636 SiS_SetReg(SISSR
, 0x13, 0x35);
4637 SiS_SetReg(SISSR
, 0x14, 0x41);
4642 /* Non-interleaving */
4643 SiS_SetReg(SISSR
, 0x15, 0x00);
4645 SiS_SetReg(SISSR
, 0x1c, 0x00);
4647 if(ivideo
->chip
== XGI_20
) {
4650 reg
= SiS_GetReg(SISCR
, 0x97);
4651 if(!(reg
& 0x01)) { /* Single 32/16 */
4653 SiS_SetReg(SISSR
, 0x13, 0xb1);
4654 SiS_SetReg(SISSR
, 0x14, 0x52);
4655 sisfb_post_xgi_delay(ivideo
, 1);
4657 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4660 SiS_SetReg(SISSR
, 0x13, 0x31);
4661 SiS_SetReg(SISSR
, 0x14, 0x42);
4662 sisfb_post_xgi_delay(ivideo
, 1);
4663 if(sisfb_post_xgi_rwtest(ivideo
, 23, 23, mapsize
))
4667 SiS_SetReg(SISSR
, 0x13, 0xb1);
4668 SiS_SetReg(SISSR
, 0x14, 0x41);
4669 sisfb_post_xgi_delay(ivideo
, 1);
4671 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4674 SiS_SetReg(SISSR
, 0x13, 0x31);
4675 } else { /* Dual 16/8 */
4677 SiS_SetReg(SISSR
, 0x13, 0xb1);
4678 SiS_SetReg(SISSR
, 0x14, 0x41);
4679 sisfb_post_xgi_delay(ivideo
, 1);
4681 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4684 SiS_SetReg(SISSR
, 0x13, 0x31);
4685 SiS_SetReg(SISSR
, 0x14, 0x31);
4686 sisfb_post_xgi_delay(ivideo
, 1);
4687 if(sisfb_post_xgi_rwtest(ivideo
, 22, 22, mapsize
))
4691 SiS_SetReg(SISSR
, 0x13, 0xb1);
4692 SiS_SetReg(SISSR
, 0x14, 0x30);
4693 sisfb_post_xgi_delay(ivideo
, 1);
4695 if(sisfb_post_xgi_rwtest(ivideo
, 21, 22, mapsize
))
4698 SiS_SetReg(SISSR
, 0x13, 0x31);
4701 } else { /* XGI_40 */
4703 reg
= SiS_GetReg(SISCR
, 0x97);
4705 reg
= SiS_GetReg(SISSR
, 0x39);
4709 if(reg
& 0x01) { /* DDRII */
4711 if(ivideo
->revision_id
== 2) {
4713 SiS_SetReg(SISSR
, 0x13, 0xa1);
4714 SiS_SetReg(SISSR
, 0x14, 0x44);
4716 sisfb_post_xgi_delay(ivideo
, 1);
4717 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4720 SiS_SetReg(SISSR
, 0x13, 0x21);
4721 SiS_SetReg(SISSR
, 0x14, 0x34);
4722 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4726 SiS_SetReg(SISSR
, 0x13, 0xa1);
4727 SiS_SetReg(SISSR
, 0x14, 0x40);
4729 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4732 SiS_SetReg(SISSR
, 0x13, 0x21);
4733 SiS_SetReg(SISSR
, 0x14, 0x30);
4736 SiS_SetReg(SISSR
, 0x13, 0xa1);
4737 SiS_SetReg(SISSR
, 0x14, 0x4c);
4739 sisfb_post_xgi_delay(ivideo
, 1);
4740 if(sisfb_post_xgi_rwtest(ivideo
, 23, 25, mapsize
))
4744 SiS_SetReg(SISSR
, 0x14, 0x48);
4745 sisfb_post_xgi_delay(ivideo
, 1);
4747 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4750 SiS_SetReg(SISSR
, 0x13, 0x21);
4751 SiS_SetReg(SISSR
, 0x14, 0x3c);
4754 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
)) {
4758 SiS_SetReg(SISSR
, 0x14, 0x38);
4762 sisfb_post_xgi_delay(ivideo
, 1);
4767 if(ivideo
->revision_id
== 2) {
4769 SiS_SetReg(SISSR
, 0x13, 0xa1);
4770 SiS_SetReg(SISSR
, 0x14, 0x52);
4771 sisfb_post_xgi_delay(ivideo
, 1);
4773 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4776 SiS_SetReg(SISSR
, 0x13, 0x21);
4777 SiS_SetReg(SISSR
, 0x14, 0x42);
4780 SiS_SetReg(SISSR
, 0x13, 0xa1);
4781 SiS_SetReg(SISSR
, 0x14, 0x5a);
4782 sisfb_post_xgi_delay(ivideo
, 1);
4784 if(sisfb_post_xgi_rwtest(ivideo
, 24, 25, mapsize
))
4787 SiS_SetReg(SISSR
, 0x13, 0x21);
4788 SiS_SetReg(SISSR
, 0x14, 0x4a);
4790 sisfb_post_xgi_delay(ivideo
, 1);
4796 SiS_SetRegANDOR(SISSR
, 0x14, 0xf0, sr14
);
4797 sisfb_post_xgi_delay(ivideo
, 1);
4799 j
= (ivideo
->chip
== XGI_20
) ? 5 : 9;
4800 k
= (ivideo
->chip
== XGI_20
) ? 12 : 4;
4803 for(i
= 0; i
< k
; i
++) {
4805 reg
= (ivideo
->chip
== XGI_20
) ?
4806 dramsr13
[(i
* 5) + 4] : dramsr13_4
[(i
* 5) + 4];
4807 SiS_SetRegANDOR(SISSR
, 0x13, 0x80, reg
);
4808 sisfb_post_xgi_delay(ivideo
, 50);
4810 ranksize
= (ivideo
->chip
== XGI_20
) ?
4811 dramsr13
[(i
* 5) + 3] : dramsr13_4
[(i
* 5) + 3];
4813 reg
= SiS_GetReg(SISSR
, 0x13);
4814 if(reg
& 0x80) ranksize
<<= 1;
4816 if(ivideo
->chip
== XGI_20
) {
4817 if(buswidth
== 16) ranksize
<<= 1;
4818 else if(buswidth
== 32) ranksize
<<= 2;
4820 if(buswidth
== 64) ranksize
<<= 1;
4826 if((ranksize
* l
) <= 256) {
4827 while((ranksize
>>= 1)) reg
+= 0x10;
4832 SiS_SetRegANDOR(SISSR
, 0x14, 0x0f, (reg
& 0xf0));
4833 sisfb_post_xgi_delay(ivideo
, 1);
4835 if (sisfb_post_xgi_rwtest(ivideo
, j
, ((reg
>> 4) + channelab
- 2 + 20), mapsize
)) {
4841 iounmap(ivideo
->video_vbase
);
4846 static void sisfb_post_xgi_setclocks(struct sis_video_info
*ivideo
, u8 regb
)
4850 static const u8 cs90
[8 * 3] = {
4860 static const u8 csb8
[8 * 3] = {
4874 v1
= cs90
[index
]; v2
= cs90
[index
+ 1]; v3
= cs90
[index
+ 2];
4875 if(ivideo
->haveXGIROM
) {
4876 v1
= ivideo
->bios_abase
[0x90 + index
];
4877 v2
= ivideo
->bios_abase
[0x90 + index
+ 1];
4878 v3
= ivideo
->bios_abase
[0x90 + index
+ 2];
4880 SiS_SetReg(SISSR
, 0x28, v1
);
4881 SiS_SetReg(SISSR
, 0x29, v2
);
4882 SiS_SetReg(SISSR
, 0x2a, v3
);
4883 sisfb_post_xgi_delay(ivideo
, 0x43);
4884 sisfb_post_xgi_delay(ivideo
, 0x43);
4885 sisfb_post_xgi_delay(ivideo
, 0x43);
4887 v1
= csb8
[index
]; v2
= csb8
[index
+ 1]; v3
= csb8
[index
+ 2];
4888 if(ivideo
->haveXGIROM
) {
4889 v1
= ivideo
->bios_abase
[0xb8 + index
];
4890 v2
= ivideo
->bios_abase
[0xb8 + index
+ 1];
4891 v3
= ivideo
->bios_abase
[0xb8 + index
+ 2];
4893 SiS_SetReg(SISSR
, 0x2e, v1
);
4894 SiS_SetReg(SISSR
, 0x2f, v2
);
4895 SiS_SetReg(SISSR
, 0x30, v3
);
4896 sisfb_post_xgi_delay(ivideo
, 0x43);
4897 sisfb_post_xgi_delay(ivideo
, 0x43);
4898 sisfb_post_xgi_delay(ivideo
, 0x43);
4901 static void sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info
*ivideo
,
4904 unsigned char *bios
= ivideo
->bios_abase
;
4907 SiS_SetReg(SISSR
, 0x28, 0x64);
4908 SiS_SetReg(SISSR
, 0x29, 0x63);
4909 sisfb_post_xgi_delay(ivideo
, 15);
4910 SiS_SetReg(SISSR
, 0x18, 0x00);
4911 SiS_SetReg(SISSR
, 0x19, 0x20);
4912 SiS_SetReg(SISSR
, 0x16, 0x00);
4913 SiS_SetReg(SISSR
, 0x16, 0x80);
4914 SiS_SetReg(SISSR
, 0x18, 0xc5);
4915 SiS_SetReg(SISSR
, 0x19, 0x23);
4916 SiS_SetReg(SISSR
, 0x16, 0x00);
4917 SiS_SetReg(SISSR
, 0x16, 0x80);
4918 sisfb_post_xgi_delay(ivideo
, 1);
4919 SiS_SetReg(SISCR
, 0x97, 0x11);
4920 sisfb_post_xgi_setclocks(ivideo
, regb
);
4921 sisfb_post_xgi_delay(ivideo
, 0x46);
4922 SiS_SetReg(SISSR
, 0x18, 0xc5);
4923 SiS_SetReg(SISSR
, 0x19, 0x23);
4924 SiS_SetReg(SISSR
, 0x16, 0x00);
4925 SiS_SetReg(SISSR
, 0x16, 0x80);
4926 sisfb_post_xgi_delay(ivideo
, 1);
4927 SiS_SetReg(SISSR
, 0x1b, 0x04);
4928 sisfb_post_xgi_delay(ivideo
, 1);
4929 SiS_SetReg(SISSR
, 0x1b, 0x00);
4930 sisfb_post_xgi_delay(ivideo
, 1);
4932 if (ivideo
->haveXGIROM
) {
4935 SiS_SetReg(SISSR
, 0x18, v1
);
4936 SiS_SetReg(SISSR
, 0x19, 0x06);
4937 SiS_SetReg(SISSR
, 0x16, 0x04);
4938 SiS_SetReg(SISSR
, 0x16, 0x84);
4939 sisfb_post_xgi_delay(ivideo
, 1);
4942 static void sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info
*ivideo
)
4944 sisfb_post_xgi_setclocks(ivideo
, 1);
4946 SiS_SetReg(SISCR
, 0x97, 0x11);
4947 sisfb_post_xgi_delay(ivideo
, 0x46);
4949 SiS_SetReg(SISSR
, 0x18, 0x00); /* EMRS2 */
4950 SiS_SetReg(SISSR
, 0x19, 0x80);
4951 SiS_SetReg(SISSR
, 0x16, 0x05);
4952 SiS_SetReg(SISSR
, 0x16, 0x85);
4954 SiS_SetReg(SISSR
, 0x18, 0x00); /* EMRS3 */
4955 SiS_SetReg(SISSR
, 0x19, 0xc0);
4956 SiS_SetReg(SISSR
, 0x16, 0x05);
4957 SiS_SetReg(SISSR
, 0x16, 0x85);
4959 SiS_SetReg(SISSR
, 0x18, 0x00); /* EMRS1 */
4960 SiS_SetReg(SISSR
, 0x19, 0x40);
4961 SiS_SetReg(SISSR
, 0x16, 0x05);
4962 SiS_SetReg(SISSR
, 0x16, 0x85);
4964 SiS_SetReg(SISSR
, 0x18, 0x42); /* MRS1 */
4965 SiS_SetReg(SISSR
, 0x19, 0x02);
4966 SiS_SetReg(SISSR
, 0x16, 0x05);
4967 SiS_SetReg(SISSR
, 0x16, 0x85);
4968 sisfb_post_xgi_delay(ivideo
, 1);
4970 SiS_SetReg(SISSR
, 0x1b, 0x04);
4971 sisfb_post_xgi_delay(ivideo
, 1);
4973 SiS_SetReg(SISSR
, 0x1b, 0x00);
4974 sisfb_post_xgi_delay(ivideo
, 1);
4976 SiS_SetReg(SISSR
, 0x18, 0x42); /* MRS1 */
4977 SiS_SetReg(SISSR
, 0x19, 0x00);
4978 SiS_SetReg(SISSR
, 0x16, 0x05);
4979 SiS_SetReg(SISSR
, 0x16, 0x85);
4980 sisfb_post_xgi_delay(ivideo
, 1);
4983 static void sisfb_post_xgi_ddr2(struct sis_video_info
*ivideo
, u8 regb
)
4985 unsigned char *bios
= ivideo
->bios_abase
;
4986 static const u8 cs158
[8] = {
4987 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
4989 static const u8 cs160
[8] = {
4990 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
4992 static const u8 cs168
[8] = {
4993 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5000 SiS_SetReg(SISCR
, 0xb0, 0x80); /* DDR2 dual frequency mode */
5001 SiS_SetReg(SISCR
, 0x82, 0x77);
5002 SiS_SetReg(SISCR
, 0x86, 0x00);
5003 reg
= SiS_GetReg(SISCR
, 0x86);
5004 SiS_SetReg(SISCR
, 0x86, 0x88);
5005 reg
= SiS_GetReg(SISCR
, 0x86);
5006 v1
= cs168
[regb
]; v2
= cs160
[regb
]; v3
= cs158
[regb
];
5007 if (ivideo
->haveXGIROM
) {
5008 v1
= bios
[regb
+ 0x168];
5009 v2
= bios
[regb
+ 0x160];
5010 v3
= bios
[regb
+ 0x158];
5012 SiS_SetReg(SISCR
, 0x86, v1
);
5013 SiS_SetReg(SISCR
, 0x82, 0x77);
5014 SiS_SetReg(SISCR
, 0x85, 0x00);
5015 reg
= SiS_GetReg(SISCR
, 0x85);
5016 SiS_SetReg(SISCR
, 0x85, 0x88);
5017 reg
= SiS_GetReg(SISCR
, 0x85);
5018 SiS_SetReg(SISCR
, 0x85, v2
);
5019 SiS_SetReg(SISCR
, 0x82, v3
);
5020 SiS_SetReg(SISCR
, 0x98, 0x01);
5021 SiS_SetReg(SISCR
, 0x9a, 0x02);
5022 if (sisfb_xgi_is21(ivideo
))
5023 sisfb_post_xgi_ddr2_mrs_xg21(ivideo
);
5025 sisfb_post_xgi_ddr2_mrs_default(ivideo
, regb
);
5028 static u8
sisfb_post_xgi_ramtype(struct sis_video_info
*ivideo
)
5030 unsigned char *bios
= ivideo
->bios_abase
;
5035 ramtype
= 0x00; v1
= 0x10;
5036 if (ivideo
->haveXGIROM
) {
5037 ramtype
= bios
[0x62];
5040 if (!(ramtype
& 0x80)) {
5041 if (sisfb_xgi_is21(ivideo
)) {
5042 SiS_SetRegAND(SISCR
, 0xb4, 0xfd); /* GPIO control */
5043 SiS_SetRegOR(SISCR
, 0x4a, 0x80); /* GPIOH EN */
5044 reg
= SiS_GetReg(SISCR
, 0x48);
5045 SiS_SetRegOR(SISCR
, 0xb4, 0x02);
5046 ramtype
= reg
& 0x01; /* GPIOH */
5047 } else if (ivideo
->chip
== XGI_20
) {
5048 SiS_SetReg(SISCR
, 0x97, v1
);
5049 reg
= SiS_GetReg(SISCR
, 0x97);
5051 ramtype
= (reg
& 0x01) << 1;
5054 reg
= SiS_GetReg(SISSR
, 0x39);
5055 ramtype
= reg
& 0x02;
5057 reg
= SiS_GetReg(SISSR
, 0x3a);
5058 ramtype
= (reg
>> 1) & 0x01;
5067 static int sisfb_post_xgi(struct pci_dev
*pdev
)
5069 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
5070 unsigned char *bios
= ivideo
->bios_abase
;
5071 struct pci_dev
*mypdev
= NULL
;
5072 const u8
*ptr
, *ptr2
;
5073 u8 v1
, v2
, v3
, v4
, v5
, reg
, ramtype
;
5074 u32 rega
, regb
, regd
;
5076 static const u8 cs78
[3] = { 0xf6, 0x0d, 0x00 };
5077 static const u8 cs76
[2] = { 0xa3, 0xfb };
5078 static const u8 cs7b
[3] = { 0xc0, 0x11, 0x00 };
5079 static const u8 cs158
[8] = {
5080 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5082 static const u8 cs160
[8] = {
5083 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5085 static const u8 cs168
[8] = {
5086 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5088 static const u8 cs128
[3 * 8] = {
5089 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
5090 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5091 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
5093 static const u8 cs148
[2 * 8] = {
5094 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
5095 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5097 static const u8 cs31a
[8 * 4] = {
5098 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
5099 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
5100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5103 static const u8 cs33a
[8 * 4] = {
5104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5109 static const u8 cs45a
[8 * 2] = {
5110 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
5111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5113 static const u8 cs170
[7 * 8] = {
5114 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5115 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5116 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
5117 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5118 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5119 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5120 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5122 static const u8 cs1a8
[3 * 8] = {
5123 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5124 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5127 static const u8 cs100
[2 * 8] = {
5128 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5129 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5133 reg
= SiS_GetRegByte(SISVGAENABLE
) | 0x01;
5134 SiS_SetRegByte(SISVGAENABLE
, reg
);
5137 reg
= SiS_GetRegByte(SISMISCR
) | 0x01;
5138 SiS_SetRegByte(SISMISCW
, reg
);
5141 SiS_SetReg(SISSR
, 0x05, 0x86);
5142 reg
= SiS_GetReg(SISSR
, 0x05);
5146 /* Clear some regs */
5147 for(i
= 0; i
< 0x22; i
++) {
5148 if(0x06 + i
== 0x20) continue;
5149 SiS_SetReg(SISSR
, 0x06 + i
, 0x00);
5151 for(i
= 0; i
< 0x0b; i
++) {
5152 SiS_SetReg(SISSR
, 0x31 + i
, 0x00);
5154 for(i
= 0; i
< 0x10; i
++) {
5155 SiS_SetReg(SISCR
, 0x30 + i
, 0x00);
5159 if(ivideo
->haveXGIROM
) {
5160 ptr
= (const u8
*)&bios
[0x78];
5162 for(i
= 0; i
< 3; i
++) {
5163 SiS_SetReg(SISSR
, 0x23 + i
, ptr
[i
]);
5167 if(ivideo
->haveXGIROM
) {
5168 ptr
= (const u8
*)&bios
[0x76];
5170 for(i
= 0; i
< 2; i
++) {
5171 SiS_SetReg(SISSR
, 0x21 + i
, ptr
[i
]);
5174 v1
= 0x18; v2
= 0x00;
5175 if(ivideo
->haveXGIROM
) {
5179 SiS_SetReg(SISSR
, 0x07, v1
);
5180 SiS_SetReg(SISSR
, 0x11, 0x0f);
5181 SiS_SetReg(SISSR
, 0x1f, v2
);
5182 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5183 SiS_SetReg(SISSR
, 0x20, 0x80 | 0x20 | 0x04);
5184 SiS_SetReg(SISSR
, 0x27, 0x74);
5187 if(ivideo
->haveXGIROM
) {
5188 ptr
= (const u8
*)&bios
[0x7b];
5190 for(i
= 0; i
< 3; i
++) {
5191 SiS_SetReg(SISSR
, 0x31 + i
, ptr
[i
]);
5194 if(ivideo
->chip
== XGI_40
) {
5195 if(ivideo
->revision_id
== 2) {
5196 SiS_SetRegANDOR(SISSR
, 0x3b, 0x3f, 0xc0);
5198 SiS_SetReg(SISCR
, 0x7d, 0xfe);
5199 SiS_SetReg(SISCR
, 0x7e, 0x0f);
5201 if(ivideo
->revision_id
== 0) { /* 40 *and* 20? */
5202 SiS_SetRegAND(SISCR
, 0x58, 0xd7);
5203 reg
= SiS_GetReg(SISCR
, 0xcb);
5205 SiS_SetRegANDOR(SISCR
, 0x58, 0xd7, (reg
& 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5209 reg
= (ivideo
->chip
== XGI_40
) ? 0x20 : 0x00;
5210 SiS_SetRegANDOR(SISCR
, 0x38, 0x1f, reg
);
5212 if(ivideo
->chip
== XGI_20
) {
5213 SiS_SetReg(SISSR
, 0x36, 0x70);
5215 SiS_SetReg(SISVID
, 0x00, 0x86);
5216 SiS_SetReg(SISVID
, 0x32, 0x00);
5217 SiS_SetReg(SISVID
, 0x30, 0x00);
5218 SiS_SetReg(SISVID
, 0x32, 0x01);
5219 SiS_SetReg(SISVID
, 0x30, 0x00);
5220 SiS_SetRegAND(SISVID
, 0x2f, 0xdf);
5221 SiS_SetRegAND(SISCAP
, 0x00, 0x3f);
5223 SiS_SetReg(SISPART1
, 0x2f, 0x01);
5224 SiS_SetReg(SISPART1
, 0x00, 0x00);
5225 SiS_SetReg(SISPART1
, 0x02, bios
[0x7e]);
5226 SiS_SetReg(SISPART1
, 0x2e, 0x08);
5227 SiS_SetRegAND(SISPART1
, 0x35, 0x7f);
5228 SiS_SetRegAND(SISPART1
, 0x50, 0xfe);
5230 reg
= SiS_GetReg(SISPART4
, 0x00);
5231 if(reg
== 1 || reg
== 2) {
5232 SiS_SetReg(SISPART2
, 0x00, 0x1c);
5233 SiS_SetReg(SISPART4
, 0x0d, bios
[0x7f]);
5234 SiS_SetReg(SISPART4
, 0x0e, bios
[0x80]);
5235 SiS_SetReg(SISPART4
, 0x10, bios
[0x81]);
5236 SiS_SetRegAND(SISPART4
, 0x0f, 0x3f);
5238 reg
= SiS_GetReg(SISPART4
, 0x01);
5239 if((reg
& 0xf0) >= 0xb0) {
5240 reg
= SiS_GetReg(SISPART4
, 0x23);
5241 if(reg
& 0x20) reg
|= 0x40;
5242 SiS_SetReg(SISPART4
, 0x23, reg
);
5243 reg
= (reg
& 0x20) ? 0x02 : 0x00;
5244 SiS_SetRegANDOR(SISPART1
, 0x1e, 0xfd, reg
);
5250 reg
= SiS_GetReg(SISSR
, 0x3b);
5252 reg
= SiS_GetReg(SISSR
, 0x3a);
5253 v2
= (reg
& 0x30) >> 3;
5254 if(!(v2
& 0x04)) v2
^= 0x02;
5255 reg
= SiS_GetReg(SISSR
, 0x39);
5256 if(reg
& 0x80) v2
|= 0x80;
5259 if((mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0730, NULL
))) {
5260 pci_dev_put(mypdev
);
5261 if(((v2
& 0x06) == 2) || ((v2
& 0x06) == 4))
5266 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0735, NULL
);
5268 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0645, NULL
);
5270 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0650, NULL
);
5272 pci_read_config_dword(mypdev
, 0x94, ®d
);
5274 pci_write_config_dword(mypdev
, 0x94, regd
);
5276 pci_dev_put(mypdev
);
5277 } else if(sisfb_find_host_bridge(ivideo
, pdev
, PCI_VENDOR_ID_SI
)) {
5279 } else if(sisfb_find_host_bridge(ivideo
, pdev
, 0x1106) ||
5280 sisfb_find_host_bridge(ivideo
, pdev
, 0x1022) ||
5281 sisfb_find_host_bridge(ivideo
, pdev
, 0x700e) ||
5282 sisfb_find_host_bridge(ivideo
, pdev
, 0x10de)) {
5283 if((v2
& 0x06) == 4)
5288 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf0, v2
);
5290 SiS_SetReg(SISSR
, 0x22, v1
);
5292 if(ivideo
->revision_id
== 2) {
5293 v1
= SiS_GetReg(SISSR
, 0x3b);
5294 v2
= SiS_GetReg(SISSR
, 0x3a);
5295 regd
= bios
[0x90 + 3] | (bios
[0x90 + 4] << 8);
5296 if( (!(v1
& 0x02)) && (v2
& 0x30) && (regd
< 0xcf) )
5297 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf1, 0x01);
5299 if((mypdev
= pci_get_device(0x10de, 0x01e0, NULL
))) {
5300 /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5304 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf1, 0x01);
5305 pci_dev_put(mypdev
);
5310 reg
= SiS_GetReg(SISSR
, 0x3b);
5311 v2
= SiS_GetReg(SISCR
, 0x5f);
5312 if((!(reg
& 0x02)) && (v2
& 0x0e))
5314 SiS_SetReg(SISSR
, 0x27, v1
);
5316 if(bios
[0x64] & 0x01) {
5317 SiS_SetRegANDOR(SISCR
, 0x5f, 0xf0, bios
[0x64]);
5321 pci_read_config_dword(pdev
, 0x50, ®d
);
5322 regd
= (regd
>> 20) & 0x0f;
5325 SiS_SetRegOR(SISCR
, 0x5f, 0x08);
5327 SiS_SetReg(SISCR
, 0x48, v1
);
5329 SiS_SetRegANDOR(SISCR
, 0x47, 0x04, bios
[0x4f6] & 0xfb);
5330 SiS_SetRegANDOR(SISCR
, 0x49, 0xf0, bios
[0x4f8] & 0x0f);
5331 SiS_SetRegANDOR(SISCR
, 0x4a, 0x60, bios
[0x4f9] & 0x9f);
5332 SiS_SetRegANDOR(SISCR
, 0x4b, 0x08, bios
[0x4fa] & 0xf7);
5333 SiS_SetRegANDOR(SISCR
, 0x4c, 0x80, bios
[0x4fb] & 0x7f);
5334 SiS_SetReg(SISCR
, 0x70, bios
[0x4fc]);
5335 SiS_SetRegANDOR(SISCR
, 0x71, 0xf0, bios
[0x4fd] & 0x0f);
5336 SiS_SetReg(SISCR
, 0x74, 0xd0);
5337 SiS_SetRegANDOR(SISCR
, 0x74, 0xcf, bios
[0x4fe] & 0x30);
5338 SiS_SetRegANDOR(SISCR
, 0x75, 0xe0, bios
[0x4ff] & 0x1f);
5339 SiS_SetRegANDOR(SISCR
, 0x76, 0xe0, bios
[0x500] & 0x1f);
5341 if((mypdev
= pci_get_device(0x8086, 0x2530, NULL
))) {
5343 pci_dev_put(mypdev
);
5345 SiS_SetReg(SISCR
, 0x77, v1
);
5350 * 0 == DDR1, 1 == DDR2, 2..7 == reserved?
5352 * The code seems to written so that regb should equal ramtype,
5353 * however, so far it has been hardcoded to 0. Enable other values only
5354 * on XGI Z9, as it passes the POST, and add a warning for others.
5356 ramtype
= sisfb_post_xgi_ramtype(ivideo
);
5357 if (!sisfb_xgi_is21(ivideo
) && ramtype
) {
5358 dev_warn(&pdev
->dev
,
5359 "RAM type something else than expected: %d\n",
5367 if(ivideo
->haveXGIROM
) {
5368 v1
= bios
[0x140 + regb
];
5370 SiS_SetReg(SISCR
, 0x6d, v1
);
5373 if(ivideo
->haveXGIROM
) {
5374 ptr
= (const u8
*)&bios
[0x128];
5376 for(i
= 0, j
= 0; i
< 3; i
++, j
+= 8) {
5377 SiS_SetReg(SISCR
, 0x68 + i
, ptr
[j
+ regb
]);
5382 if(ivideo
->haveXGIROM
) {
5383 index
= (ivideo
->chip
== XGI_20
) ? 0x31a : 0x3a6;
5384 ptr
= (const u8
*)&bios
[index
];
5385 ptr2
= (const u8
*)&bios
[index
+ 0x20];
5387 for(i
= 0; i
< 2; i
++) {
5389 regd
= le32_to_cpu(((u32
*)ptr
)[regb
]);
5392 regd
= le32_to_cpu(((u32
*)ptr2
)[regb
]);
5396 for(j
= 0; j
< 16; j
++) {
5398 if(regd
& 0x01) reg
|= 0x04;
5399 if(regd
& 0x02) reg
|= 0x08;
5401 SiS_SetReg(SISCR
, rega
, reg
);
5402 reg
= SiS_GetReg(SISCR
, rega
);
5403 reg
= SiS_GetReg(SISCR
, rega
);
5408 SiS_SetRegAND(SISCR
, 0x6e, 0xfc);
5411 if(ivideo
->haveXGIROM
) {
5412 index
= (ivideo
->chip
== XGI_20
) ? 0x35a : 0x3e6;
5413 ptr
= (const u8
*)&bios
[index
];
5415 for(i
= 0; i
< 4; i
++) {
5416 SiS_SetRegANDOR(SISCR
, 0x6e, 0xfc, i
);
5418 for(j
= 0; j
< 2; j
++) {
5421 regd
= le32_to_cpu(((u32
*)ptr
)[regb
* 8]);
5425 for(k
= 0; k
< 16; k
++) {
5427 if(regd
& 0x01) reg
|= 0x01;
5428 if(regd
& 0x02) reg
|= 0x02;
5430 SiS_SetReg(SISCR
, 0x6f, reg
);
5431 reg
= SiS_GetReg(SISCR
, 0x6f);
5432 reg
= SiS_GetReg(SISCR
, 0x6f);
5439 if(ivideo
->haveXGIROM
) {
5440 ptr
= (const u8
*)&bios
[0x148];
5442 for(i
= 0, j
= 0; i
< 2; i
++, j
+= 8) {
5443 SiS_SetReg(SISCR
, 0x80 + i
, ptr
[j
+ regb
]);
5446 SiS_SetRegAND(SISCR
, 0x89, 0x8f);
5449 if(ivideo
->haveXGIROM
) {
5450 index
= (ivideo
->chip
== XGI_20
) ? 0x45a : 0x4e6;
5451 ptr
= (const u8
*)&bios
[index
];
5453 regd
= le16_to_cpu(((const u16
*)ptr
)[regb
]);
5455 for(i
= 0; i
< 5; i
++) {
5457 if(regd
& 0x01) reg
|= 0x01;
5458 if(regd
& 0x02) reg
|= 0x02;
5460 SiS_SetReg(SISCR
, 0x89, reg
);
5461 reg
= SiS_GetReg(SISCR
, 0x89);
5462 reg
= SiS_GetReg(SISCR
, 0x89);
5466 v1
= 0xb5; v2
= 0x20; v3
= 0xf0; v4
= 0x13;
5467 if(ivideo
->haveXGIROM
) {
5468 v1
= bios
[0x118 + regb
];
5469 v2
= bios
[0xf8 + regb
];
5470 v3
= bios
[0x120 + regb
];
5473 SiS_SetReg(SISCR
, 0x45, v1
& 0x0f);
5474 SiS_SetReg(SISCR
, 0x99, (v1
>> 4) & 0x07);
5475 SiS_SetRegOR(SISCR
, 0x40, v1
& 0x80);
5476 SiS_SetReg(SISCR
, 0x41, v2
);
5479 if(ivideo
->haveXGIROM
) {
5480 ptr
= (const u8
*)&bios
[0x170];
5482 for(i
= 0, j
= 0; i
< 7; i
++, j
+= 8) {
5483 SiS_SetReg(SISCR
, 0x90 + i
, ptr
[j
+ regb
]);
5486 SiS_SetReg(SISCR
, 0x59, v3
);
5489 if(ivideo
->haveXGIROM
) {
5490 ptr
= (const u8
*)&bios
[0x1a8];
5492 for(i
= 0, j
= 0; i
< 3; i
++, j
+= 8) {
5493 SiS_SetReg(SISCR
, 0xc3 + i
, ptr
[j
+ regb
]);
5497 if(ivideo
->haveXGIROM
) {
5498 ptr
= (const u8
*)&bios
[0x100];
5500 for(i
= 0, j
= 0; i
< 2; i
++, j
+= 8) {
5501 SiS_SetReg(SISCR
, 0x8a + i
, ptr
[j
+ regb
]);
5504 SiS_SetReg(SISCR
, 0xcf, v4
);
5506 SiS_SetReg(SISCR
, 0x83, 0x09);
5507 SiS_SetReg(SISCR
, 0x87, 0x00);
5509 if(ivideo
->chip
== XGI_40
) {
5510 if( (ivideo
->revision_id
== 1) ||
5511 (ivideo
->revision_id
== 2) ) {
5512 SiS_SetReg(SISCR
, 0x8c, 0x87);
5517 SiS_SetReg(SISSR
, 0x17, 0x80); /* DDR2 */
5519 SiS_SetReg(SISSR
, 0x17, 0x00); /* DDR1 */
5520 SiS_SetReg(SISSR
, 0x1a, 0x87);
5522 if(ivideo
->chip
== XGI_20
) {
5523 SiS_SetReg(SISSR
, 0x15, 0x00);
5524 SiS_SetReg(SISSR
, 0x1c, 0x00);
5529 sisfb_post_xgi_setclocks(ivideo
, regb
);
5530 if((ivideo
->chip
== XGI_20
) ||
5531 (ivideo
->revision_id
== 1) ||
5532 (ivideo
->revision_id
== 2)) {
5533 v1
= cs158
[regb
]; v2
= cs160
[regb
]; v3
= cs168
[regb
];
5534 if(ivideo
->haveXGIROM
) {
5535 v1
= bios
[regb
+ 0x158];
5536 v2
= bios
[regb
+ 0x160];
5537 v3
= bios
[regb
+ 0x168];
5539 SiS_SetReg(SISCR
, 0x82, v1
);
5540 SiS_SetReg(SISCR
, 0x85, v2
);
5541 SiS_SetReg(SISCR
, 0x86, v3
);
5543 SiS_SetReg(SISCR
, 0x82, 0x88);
5544 SiS_SetReg(SISCR
, 0x86, 0x00);
5545 reg
= SiS_GetReg(SISCR
, 0x86);
5546 SiS_SetReg(SISCR
, 0x86, 0x88);
5547 reg
= SiS_GetReg(SISCR
, 0x86);
5548 SiS_SetReg(SISCR
, 0x86, bios
[regb
+ 0x168]);
5549 SiS_SetReg(SISCR
, 0x82, 0x77);
5550 SiS_SetReg(SISCR
, 0x85, 0x00);
5551 reg
= SiS_GetReg(SISCR
, 0x85);
5552 SiS_SetReg(SISCR
, 0x85, 0x88);
5553 reg
= SiS_GetReg(SISCR
, 0x85);
5554 SiS_SetReg(SISCR
, 0x85, bios
[regb
+ 0x160]);
5555 SiS_SetReg(SISCR
, 0x82, bios
[regb
+ 0x158]);
5557 if(ivideo
->chip
== XGI_40
) {
5558 SiS_SetReg(SISCR
, 0x97, 0x00);
5560 SiS_SetReg(SISCR
, 0x98, 0x01);
5561 SiS_SetReg(SISCR
, 0x9a, 0x02);
5563 SiS_SetReg(SISSR
, 0x18, 0x01);
5564 if((ivideo
->chip
== XGI_20
) ||
5565 (ivideo
->revision_id
== 2)) {
5566 SiS_SetReg(SISSR
, 0x19, 0x40);
5568 SiS_SetReg(SISSR
, 0x19, 0x20);
5570 SiS_SetReg(SISSR
, 0x16, 0x00);
5571 SiS_SetReg(SISSR
, 0x16, 0x80);
5572 if((ivideo
->chip
== XGI_20
) || (bios
[0x1cb] != 0x0c)) {
5573 sisfb_post_xgi_delay(ivideo
, 0x43);
5574 sisfb_post_xgi_delay(ivideo
, 0x43);
5575 sisfb_post_xgi_delay(ivideo
, 0x43);
5576 SiS_SetReg(SISSR
, 0x18, 0x00);
5577 if((ivideo
->chip
== XGI_20
) ||
5578 (ivideo
->revision_id
== 2)) {
5579 SiS_SetReg(SISSR
, 0x19, 0x40);
5581 SiS_SetReg(SISSR
, 0x19, 0x20);
5583 } else if((ivideo
->chip
== XGI_40
) && (bios
[0x1cb] == 0x0c)) {
5584 /* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
5586 SiS_SetReg(SISSR
, 0x16, 0x00);
5587 SiS_SetReg(SISSR
, 0x16, 0x80);
5588 sisfb_post_xgi_delay(ivideo
, 4);
5589 v1
= 0x31; v2
= 0x03; v3
= 0x83; v4
= 0x03; v5
= 0x83;
5590 if(ivideo
->haveXGIROM
) {
5592 index
= (ivideo
->chip
== XGI_20
) ? 0x4b2 : 0x53e;
5594 v3
= bios
[index
+ 1];
5595 v4
= bios
[index
+ 2];
5596 v5
= bios
[index
+ 3];
5598 SiS_SetReg(SISSR
, 0x18, v1
);
5599 SiS_SetReg(SISSR
, 0x19, ((ivideo
->chip
== XGI_20
) ? 0x02 : 0x01));
5600 SiS_SetReg(SISSR
, 0x16, v2
);
5601 SiS_SetReg(SISSR
, 0x16, v3
);
5602 sisfb_post_xgi_delay(ivideo
, 0x43);
5603 SiS_SetReg(SISSR
, 0x1b, 0x03);
5604 sisfb_post_xgi_delay(ivideo
, 0x22);
5605 SiS_SetReg(SISSR
, 0x18, v1
);
5606 SiS_SetReg(SISSR
, 0x19, 0x00);
5607 SiS_SetReg(SISSR
, 0x16, v4
);
5608 SiS_SetReg(SISSR
, 0x16, v5
);
5609 SiS_SetReg(SISSR
, 0x1b, 0x00);
5612 sisfb_post_xgi_ddr2(ivideo
, regb
);
5615 sisfb_post_xgi_setclocks(ivideo
, regb
);
5616 if((ivideo
->chip
== XGI_40
) &&
5617 ((ivideo
->revision_id
== 1) ||
5618 (ivideo
->revision_id
== 2))) {
5619 SiS_SetReg(SISCR
, 0x82, bios
[regb
+ 0x158]);
5620 SiS_SetReg(SISCR
, 0x85, bios
[regb
+ 0x160]);
5621 SiS_SetReg(SISCR
, 0x86, bios
[regb
+ 0x168]);
5623 SiS_SetReg(SISCR
, 0x82, 0x88);
5624 SiS_SetReg(SISCR
, 0x86, 0x00);
5625 reg
= SiS_GetReg(SISCR
, 0x86);
5626 SiS_SetReg(SISCR
, 0x86, 0x88);
5627 SiS_SetReg(SISCR
, 0x82, 0x77);
5628 SiS_SetReg(SISCR
, 0x85, 0x00);
5629 reg
= SiS_GetReg(SISCR
, 0x85);
5630 SiS_SetReg(SISCR
, 0x85, 0x88);
5631 reg
= SiS_GetReg(SISCR
, 0x85);
5632 v1
= cs160
[regb
]; v2
= cs158
[regb
];
5633 if(ivideo
->haveXGIROM
) {
5634 v1
= bios
[regb
+ 0x160];
5635 v2
= bios
[regb
+ 0x158];
5637 SiS_SetReg(SISCR
, 0x85, v1
);
5638 SiS_SetReg(SISCR
, 0x82, v2
);
5640 if(ivideo
->chip
== XGI_40
) {
5641 SiS_SetReg(SISCR
, 0x97, 0x11);
5643 if((ivideo
->chip
== XGI_40
) && (ivideo
->revision_id
== 2)) {
5644 SiS_SetReg(SISCR
, 0x98, 0x01);
5646 SiS_SetReg(SISCR
, 0x98, 0x03);
5648 SiS_SetReg(SISCR
, 0x9a, 0x02);
5650 if(ivideo
->chip
== XGI_40
) {
5651 SiS_SetReg(SISSR
, 0x18, 0x01);
5653 SiS_SetReg(SISSR
, 0x18, 0x00);
5655 SiS_SetReg(SISSR
, 0x19, 0x40);
5656 SiS_SetReg(SISSR
, 0x16, 0x00);
5657 SiS_SetReg(SISSR
, 0x16, 0x80);
5658 if((ivideo
->chip
== XGI_40
) && (bios
[0x1cb] != 0x0c)) {
5659 sisfb_post_xgi_delay(ivideo
, 0x43);
5660 sisfb_post_xgi_delay(ivideo
, 0x43);
5661 sisfb_post_xgi_delay(ivideo
, 0x43);
5662 SiS_SetReg(SISSR
, 0x18, 0x00);
5663 SiS_SetReg(SISSR
, 0x19, 0x40);
5664 SiS_SetReg(SISSR
, 0x16, 0x00);
5665 SiS_SetReg(SISSR
, 0x16, 0x80);
5667 sisfb_post_xgi_delay(ivideo
, 4);
5669 if(ivideo
->haveXGIROM
) {
5672 SiS_SetReg(SISSR
, 0x18, v1
);
5673 SiS_SetReg(SISSR
, 0x19, 0x01);
5674 if(ivideo
->chip
== XGI_40
) {
5675 SiS_SetReg(SISSR
, 0x16, bios
[0x53e]);
5676 SiS_SetReg(SISSR
, 0x16, bios
[0x53f]);
5678 SiS_SetReg(SISSR
, 0x16, 0x05);
5679 SiS_SetReg(SISSR
, 0x16, 0x85);
5681 sisfb_post_xgi_delay(ivideo
, 0x43);
5682 if(ivideo
->chip
== XGI_40
) {
5683 SiS_SetReg(SISSR
, 0x1b, 0x01);
5685 SiS_SetReg(SISSR
, 0x1b, 0x03);
5687 sisfb_post_xgi_delay(ivideo
, 0x22);
5688 SiS_SetReg(SISSR
, 0x18, v1
);
5689 SiS_SetReg(SISSR
, 0x19, 0x00);
5690 if(ivideo
->chip
== XGI_40
) {
5691 SiS_SetReg(SISSR
, 0x16, bios
[0x540]);
5692 SiS_SetReg(SISSR
, 0x16, bios
[0x541]);
5694 SiS_SetReg(SISSR
, 0x16, 0x05);
5695 SiS_SetReg(SISSR
, 0x16, 0x85);
5697 SiS_SetReg(SISSR
, 0x1b, 0x00);
5702 if(ivideo
->haveXGIROM
) {
5703 v1
= bios
[0x110 + regb
];
5705 SiS_SetReg(SISSR
, 0x1b, v1
);
5708 v1
= 0x00; v2
= 0x00;
5709 if(ivideo
->haveXGIROM
) {
5715 if((v1
& 0x40) && (v2
& regd
) && ivideo
->haveXGIROM
) {
5717 SiS_SetReg(SISSR
, 0x13, bios
[regb
+ 0xe0]);
5718 SiS_SetReg(SISSR
, 0x14, bios
[regb
+ 0xe0 + 8]);
5723 /* Set default mode, don't clear screen */
5724 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
5725 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
5726 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
5727 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
5728 ivideo
->SiS_Pr
.VideoMemorySize
= 8 << 20;
5729 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
5731 SiS_SetReg(SISSR
, 0x05, 0x86);
5733 /* Disable read-cache */
5734 SiS_SetRegAND(SISSR
, 0x21, 0xdf);
5735 err
= sisfb_post_xgi_ramsize(ivideo
);
5736 /* Enable read-cache */
5737 SiS_SetRegOR(SISSR
, 0x21, 0x20);
5741 "%s: RAM size detection failed: %d\n",
5748 printk(KERN_DEBUG
"-----------------\n");
5749 for(i
= 0; i
< 0xff; i
++) {
5750 reg
= SiS_GetReg(SISCR
, i
);
5751 printk(KERN_DEBUG
"CR%02x(%x) = 0x%02x\n", i
, SISCR
, reg
);
5753 for(i
= 0; i
< 0x40; i
++) {
5754 reg
= SiS_GetReg(SISSR
, i
);
5755 printk(KERN_DEBUG
"SR%02x(%x) = 0x%02x\n", i
, SISSR
, reg
);
5757 printk(KERN_DEBUG
"-----------------\n");
5761 if(ivideo
->chip
== XGI_20
) {
5762 SiS_SetRegOR(SISCR
, 0x32, 0x20);
5764 reg
= SiS_GetReg(SISPART4
, 0x00);
5765 if((reg
== 1) || (reg
== 2)) {
5766 sisfb_sense_crt1(ivideo
);
5768 SiS_SetRegOR(SISCR
, 0x32, 0x20);
5772 /* Set default mode, don't clear screen */
5773 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
5774 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
5775 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
5776 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
5777 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
5779 SiS_SetReg(SISSR
, 0x05, 0x86);
5782 SiS_SetRegOR(SISSR
, 0x01, 0x20);
5784 /* Save mode number in CR34 */
5785 SiS_SetReg(SISCR
, 0x34, 0x2e);
5787 /* Let everyone know what the current mode is */
5788 ivideo
->modeprechange
= 0x2e;
5790 if(ivideo
->chip
== XGI_40
) {
5791 reg
= SiS_GetReg(SISCR
, 0xca);
5792 v1
= SiS_GetReg(SISCR
, 0xcc);
5793 if((reg
& 0x10) && (!(v1
& 0x04))) {
5795 "sisfb: Please connect power to the card.\n");
5804 static int sisfb_probe(struct pci_dev
*pdev
, const struct pci_device_id
*ent
)
5806 struct sisfb_chip_info
*chipinfo
= &sisfb_chip_info
[ent
->driver_data
];
5807 struct sis_video_info
*ivideo
= NULL
;
5808 struct fb_info
*sis_fb_info
= NULL
;
5816 sis_fb_info
= framebuffer_alloc(sizeof(*ivideo
), &pdev
->dev
);
5820 ivideo
= (struct sis_video_info
*)sis_fb_info
->par
;
5821 ivideo
->memyselfandi
= sis_fb_info
;
5823 ivideo
->sisfb_id
= SISFB_ID
;
5825 if(card_list
== NULL
) {
5826 ivideo
->cardnumber
= 0;
5828 struct sis_video_info
*countvideo
= card_list
;
5829 ivideo
->cardnumber
= 1;
5830 while((countvideo
= countvideo
->next
) != NULL
)
5831 ivideo
->cardnumber
++;
5834 strlcpy(ivideo
->myid
, chipinfo
->chip_name
, sizeof(ivideo
->myid
));
5836 ivideo
->warncount
= 0;
5837 ivideo
->chip_id
= pdev
->device
;
5838 ivideo
->chip_vendor
= pdev
->vendor
;
5839 ivideo
->revision_id
= pdev
->revision
;
5840 ivideo
->SiS_Pr
.ChipRevision
= ivideo
->revision_id
;
5841 pci_read_config_word(pdev
, PCI_COMMAND
, ®16
);
5842 ivideo
->sisvga_enabled
= reg16
& 0x01;
5843 ivideo
->pcibus
= pdev
->bus
->number
;
5844 ivideo
->pcislot
= PCI_SLOT(pdev
->devfn
);
5845 ivideo
->pcifunc
= PCI_FUNC(pdev
->devfn
);
5846 ivideo
->subsysvendor
= pdev
->subsystem_vendor
;
5847 ivideo
->subsysdevice
= pdev
->subsystem_device
;
5850 if(sisfb_mode_idx
== -1) {
5851 sisfb_get_vga_mode_from_kernel();
5855 ivideo
->chip
= chipinfo
->chip
;
5856 ivideo
->chip_real_id
= chipinfo
->chip
;
5857 ivideo
->sisvga_engine
= chipinfo
->vgaengine
;
5858 ivideo
->hwcursor_size
= chipinfo
->hwcursor_size
;
5859 ivideo
->CRT2_write_enable
= chipinfo
->CRT2_write_enable
;
5860 ivideo
->mni
= chipinfo
->mni
;
5862 ivideo
->detectedpdc
= 0xff;
5863 ivideo
->detectedpdca
= 0xff;
5864 ivideo
->detectedlcda
= 0xff;
5866 ivideo
->sisfb_thismonitor
.datavalid
= false;
5868 ivideo
->current_base
= 0;
5870 ivideo
->engineok
= 0;
5872 ivideo
->sisfb_was_boot_device
= 0;
5874 if(pdev
->resource
[PCI_ROM_RESOURCE
].flags
& IORESOURCE_ROM_SHADOW
) {
5875 if(ivideo
->sisvga_enabled
)
5876 ivideo
->sisfb_was_boot_device
= 1;
5878 printk(KERN_DEBUG
"sisfb: PCI device is disabled, "
5879 "but marked as boot video device ???\n");
5880 printk(KERN_DEBUG
"sisfb: I will not accept this "
5881 "as the primary VGA device\n");
5885 ivideo
->sisfb_parm_mem
= sisfb_parm_mem
;
5886 ivideo
->sisfb_accel
= sisfb_accel
;
5887 ivideo
->sisfb_ypan
= sisfb_ypan
;
5888 ivideo
->sisfb_max
= sisfb_max
;
5889 ivideo
->sisfb_userom
= sisfb_userom
;
5890 ivideo
->sisfb_useoem
= sisfb_useoem
;
5891 ivideo
->sisfb_mode_idx
= sisfb_mode_idx
;
5892 ivideo
->sisfb_parm_rate
= sisfb_parm_rate
;
5893 ivideo
->sisfb_crt1off
= sisfb_crt1off
;
5894 ivideo
->sisfb_forcecrt1
= sisfb_forcecrt1
;
5895 ivideo
->sisfb_crt2type
= sisfb_crt2type
;
5896 ivideo
->sisfb_crt2flags
= sisfb_crt2flags
;
5897 /* pdc(a), scalelcd, special timing, lvdshl handled below */
5898 ivideo
->sisfb_dstn
= sisfb_dstn
;
5899 ivideo
->sisfb_fstn
= sisfb_fstn
;
5900 ivideo
->sisfb_tvplug
= sisfb_tvplug
;
5901 ivideo
->sisfb_tvstd
= sisfb_tvstd
;
5902 ivideo
->tvxpos
= sisfb_tvxposoffset
;
5903 ivideo
->tvypos
= sisfb_tvyposoffset
;
5904 ivideo
->sisfb_nocrt2rate
= sisfb_nocrt2rate
;
5905 ivideo
->refresh_rate
= 0;
5906 if(ivideo
->sisfb_parm_rate
!= -1) {
5907 ivideo
->refresh_rate
= ivideo
->sisfb_parm_rate
;
5910 ivideo
->SiS_Pr
.UsePanelScaler
= sisfb_scalelcd
;
5911 ivideo
->SiS_Pr
.CenterScreen
= -1;
5912 ivideo
->SiS_Pr
.SiS_CustomT
= sisfb_specialtiming
;
5913 ivideo
->SiS_Pr
.LVDSHL
= sisfb_lvdshl
;
5915 ivideo
->SiS_Pr
.SiS_Backup70xx
= 0xff;
5916 ivideo
->SiS_Pr
.SiS_CHOverScan
= -1;
5917 ivideo
->SiS_Pr
.SiS_ChSW
= false;
5918 ivideo
->SiS_Pr
.SiS_UseLCDA
= false;
5919 ivideo
->SiS_Pr
.HaveEMI
= false;
5920 ivideo
->SiS_Pr
.HaveEMILCD
= false;
5921 ivideo
->SiS_Pr
.OverruleEMI
= false;
5922 ivideo
->SiS_Pr
.SiS_SensibleSR11
= false;
5923 ivideo
->SiS_Pr
.SiS_MyCR63
= 0x63;
5924 ivideo
->SiS_Pr
.PDC
= -1;
5925 ivideo
->SiS_Pr
.PDCA
= -1;
5926 ivideo
->SiS_Pr
.DDCPortMixup
= false;
5927 #ifdef CONFIG_FB_SIS_315
5928 if(ivideo
->chip
>= SIS_330
) {
5929 ivideo
->SiS_Pr
.SiS_MyCR63
= 0x53;
5930 if(ivideo
->chip
>= SIS_661
) {
5931 ivideo
->SiS_Pr
.SiS_SensibleSR11
= true;
5936 memcpy(&ivideo
->default_var
, &my_default_var
, sizeof(my_default_var
));
5938 pci_set_drvdata(pdev
, ivideo
);
5940 /* Patch special cases */
5941 if((ivideo
->nbridge
= sisfb_get_northbridge(ivideo
->chip
))) {
5942 switch(ivideo
->nbridge
->device
) {
5943 #ifdef CONFIG_FB_SIS_300
5944 case PCI_DEVICE_ID_SI_730
:
5945 ivideo
->chip
= SIS_730
;
5946 strcpy(ivideo
->myid
, "SiS 730");
5949 #ifdef CONFIG_FB_SIS_315
5950 case PCI_DEVICE_ID_SI_651
:
5951 /* ivideo->chip is ok */
5952 strcpy(ivideo
->myid
, "SiS 651");
5954 case PCI_DEVICE_ID_SI_740
:
5955 ivideo
->chip
= SIS_740
;
5956 strcpy(ivideo
->myid
, "SiS 740");
5958 case PCI_DEVICE_ID_SI_661
:
5959 ivideo
->chip
= SIS_661
;
5960 strcpy(ivideo
->myid
, "SiS 661");
5962 case PCI_DEVICE_ID_SI_741
:
5963 ivideo
->chip
= SIS_741
;
5964 strcpy(ivideo
->myid
, "SiS 741");
5966 case PCI_DEVICE_ID_SI_760
:
5967 ivideo
->chip
= SIS_760
;
5968 strcpy(ivideo
->myid
, "SiS 760");
5970 case PCI_DEVICE_ID_SI_761
:
5971 ivideo
->chip
= SIS_761
;
5972 strcpy(ivideo
->myid
, "SiS 761");
5980 ivideo
->SiS_Pr
.ChipType
= ivideo
->chip
;
5982 ivideo
->SiS_Pr
.ivideo
= (void *)ivideo
;
5984 #ifdef CONFIG_FB_SIS_315
5985 if((ivideo
->SiS_Pr
.ChipType
== SIS_315PRO
) ||
5986 (ivideo
->SiS_Pr
.ChipType
== SIS_315
)) {
5987 ivideo
->SiS_Pr
.ChipType
= SIS_315H
;
5991 if(!ivideo
->sisvga_enabled
) {
5992 if(pci_enable_device(pdev
)) {
5993 pci_dev_put(ivideo
->nbridge
);
5994 framebuffer_release(sis_fb_info
);
5999 ivideo
->video_base
= pci_resource_start(pdev
, 0);
6000 ivideo
->video_size
= pci_resource_len(pdev
, 0);
6001 ivideo
->mmio_base
= pci_resource_start(pdev
, 1);
6002 ivideo
->mmio_size
= pci_resource_len(pdev
, 1);
6003 ivideo
->SiS_Pr
.RelIO
= pci_resource_start(pdev
, 2) + 0x30;
6004 ivideo
->SiS_Pr
.IOAddress
= ivideo
->vga_base
= ivideo
->SiS_Pr
.RelIO
;
6006 SiSRegInit(&ivideo
->SiS_Pr
, ivideo
->SiS_Pr
.IOAddress
);
6008 #ifdef CONFIG_FB_SIS_300
6009 /* Find PCI systems for Chrontel/GPIO communication setup */
6010 if(ivideo
->chip
== SIS_630
) {
6013 if(mychswtable
[i
].subsysVendor
== ivideo
->subsysvendor
&&
6014 mychswtable
[i
].subsysCard
== ivideo
->subsysdevice
) {
6015 ivideo
->SiS_Pr
.SiS_ChSW
= true;
6016 printk(KERN_DEBUG
"sisfb: Identified [%s %s] "
6017 "requiring Chrontel/GPIO setup\n",
6018 mychswtable
[i
].vendorName
,
6019 mychswtable
[i
].cardName
);
6020 ivideo
->lpcdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0008, NULL
);
6024 } while(mychswtable
[i
].subsysVendor
!= 0);
6028 #ifdef CONFIG_FB_SIS_315
6029 if((ivideo
->chip
== SIS_760
) && (ivideo
->nbridge
)) {
6030 ivideo
->lpcdev
= pci_get_slot(ivideo
->nbridge
->bus
, (2 << 3));
6034 SiS_SetReg(SISSR
, 0x05, 0x86);
6036 if( (!ivideo
->sisvga_enabled
)
6037 #if !defined(__i386__) && !defined(__x86_64__)
6038 || (sisfb_resetcard
)
6041 for(i
= 0x30; i
<= 0x3f; i
++) {
6042 SiS_SetReg(SISCR
, i
, 0x00);
6046 /* Find out about current video mode */
6047 ivideo
->modeprechange
= 0x03;
6048 reg
= SiS_GetReg(SISCR
, 0x34);
6050 ivideo
->modeprechange
= reg
& 0x7f;
6051 } else if(ivideo
->sisvga_enabled
) {
6052 #if defined(__i386__) || defined(__x86_64__)
6053 unsigned char __iomem
*tt
= ioremap(0x400, 0x100);
6055 ivideo
->modeprechange
= readb(tt
+ 0x49);
6061 /* Search and copy ROM image */
6062 ivideo
->bios_abase
= NULL
;
6063 ivideo
->SiS_Pr
.VirtualRomBase
= NULL
;
6064 ivideo
->SiS_Pr
.UseROM
= false;
6065 ivideo
->haveXGIROM
= ivideo
->SiS_Pr
.SiS_XGIROM
= false;
6066 if(ivideo
->sisfb_userom
) {
6067 ivideo
->SiS_Pr
.VirtualRomBase
= sisfb_find_rom(pdev
);
6068 ivideo
->bios_abase
= ivideo
->SiS_Pr
.VirtualRomBase
;
6069 ivideo
->SiS_Pr
.UseROM
= (bool)(ivideo
->SiS_Pr
.VirtualRomBase
);
6070 printk(KERN_INFO
"sisfb: Video ROM %sfound\n",
6071 ivideo
->SiS_Pr
.UseROM
? "" : "not ");
6072 if((ivideo
->SiS_Pr
.UseROM
) && (ivideo
->chip
>= XGI_20
)) {
6073 ivideo
->SiS_Pr
.UseROM
= false;
6074 ivideo
->haveXGIROM
= ivideo
->SiS_Pr
.SiS_XGIROM
= true;
6075 if( (ivideo
->revision_id
== 2) &&
6076 (!(ivideo
->bios_abase
[0x1d1] & 0x01)) ) {
6077 ivideo
->SiS_Pr
.DDCPortMixup
= true;
6081 printk(KERN_INFO
"sisfb: Video ROM usage disabled\n");
6084 /* Find systems for special custom timing */
6085 if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_NONE
) {
6086 sisfb_detect_custom_timing(ivideo
);
6089 #ifdef CONFIG_FB_SIS_315
6090 if (ivideo
->chip
== XGI_20
) {
6091 /* Check if our Z7 chip is actually Z9 */
6092 SiS_SetRegOR(SISCR
, 0x4a, 0x40); /* GPIOG EN */
6093 reg
= SiS_GetReg(SISCR
, 0x48);
6094 if (reg
& 0x02) { /* GPIOG */
6095 ivideo
->chip_real_id
= XGI_21
;
6096 dev_info(&pdev
->dev
, "Z9 detected\n");
6101 /* POST card in case this has not been done by the BIOS */
6102 if( (!ivideo
->sisvga_enabled
)
6103 #if !defined(__i386__) && !defined(__x86_64__)
6104 || (sisfb_resetcard
)
6107 #ifdef CONFIG_FB_SIS_300
6108 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
6109 if(ivideo
->chip
== SIS_300
) {
6110 sisfb_post_sis300(pdev
);
6111 ivideo
->sisfb_can_post
= 1;
6116 #ifdef CONFIG_FB_SIS_315
6117 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
6119 /* if((ivideo->chip == SIS_315H) ||
6120 (ivideo->chip == SIS_315) ||
6121 (ivideo->chip == SIS_315PRO) ||
6122 (ivideo->chip == SIS_330)) {
6123 sisfb_post_sis315330(pdev);
6124 } else */ if(ivideo
->chip
== XGI_20
) {
6125 result
= sisfb_post_xgi(pdev
);
6126 ivideo
->sisfb_can_post
= 1;
6127 } else if((ivideo
->chip
== XGI_40
) && ivideo
->haveXGIROM
) {
6128 result
= sisfb_post_xgi(pdev
);
6129 ivideo
->sisfb_can_post
= 1;
6131 printk(KERN_INFO
"sisfb: Card is not "
6132 "POSTed and sisfb can't do this either.\n");
6135 printk(KERN_ERR
"sisfb: Failed to POST card\n");
6143 ivideo
->sisfb_card_posted
= 1;
6145 /* Find out about RAM size */
6146 if(sisfb_get_dram_size(ivideo
)) {
6147 printk(KERN_INFO
"sisfb: Fatal error: Unable to determine VRAM size.\n");
6153 /* Enable PCI addressing and MMIO */
6154 if((ivideo
->sisfb_mode_idx
< 0) ||
6155 ((sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
]) != 0xFF)) {
6156 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
6157 SiS_SetRegOR(SISSR
, IND_SIS_PCI_ADDRESS_SET
, (SIS_PCI_ADDR_ENABLE
| SIS_MEM_MAP_IO_ENABLE
));
6158 /* Enable 2D accelerator engine */
6159 SiS_SetRegOR(SISSR
, IND_SIS_MODULE_ENABLE
, SIS_ENABLE_2D
);
6162 if(sisfb_pdc
!= 0xff) {
6163 if(ivideo
->sisvga_engine
== SIS_300_VGA
)
6167 ivideo
->SiS_Pr
.PDC
= sisfb_pdc
;
6169 #ifdef CONFIG_FB_SIS_315
6170 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
6171 if(sisfb_pdca
!= 0xff)
6172 ivideo
->SiS_Pr
.PDCA
= sisfb_pdca
& 0x1f;
6176 if(!request_mem_region(ivideo
->video_base
, ivideo
->video_size
, "sisfb FB")) {
6177 printk(KERN_ERR
"sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6178 (int)(ivideo
->video_size
>> 20));
6179 printk(KERN_ERR
"sisfb: Is there another framebuffer driver active?\n");
6184 if(!request_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
, "sisfb MMIO")) {
6185 printk(KERN_ERR
"sisfb: Fatal error: Unable to reserve MMIO region\n");
6190 ivideo
->video_vbase
= ioremap_wc(ivideo
->video_base
, ivideo
->video_size
);
6191 ivideo
->SiS_Pr
.VideoMemoryAddress
= ivideo
->video_vbase
;
6192 if(!ivideo
->video_vbase
) {
6193 printk(KERN_ERR
"sisfb: Fatal error: Unable to map framebuffer memory\n");
6198 ivideo
->mmio_vbase
= ioremap(ivideo
->mmio_base
, ivideo
->mmio_size
);
6199 if(!ivideo
->mmio_vbase
) {
6200 printk(KERN_ERR
"sisfb: Fatal error: Unable to map MMIO region\n");
6202 error_0
: iounmap(ivideo
->video_vbase
);
6203 error_1
: release_mem_region(ivideo
->video_base
, ivideo
->video_size
);
6204 error_2
: release_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
);
6205 error_3
: vfree(ivideo
->bios_abase
);
6206 pci_dev_put(ivideo
->lpcdev
);
6207 pci_dev_put(ivideo
->nbridge
);
6208 if(!ivideo
->sisvga_enabled
)
6209 pci_disable_device(pdev
);
6210 framebuffer_release(sis_fb_info
);
6214 printk(KERN_INFO
"sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
6215 ivideo
->video_base
, (unsigned long)ivideo
->video_vbase
, ivideo
->video_size
/ 1024);
6217 if(ivideo
->video_offset
) {
6218 printk(KERN_INFO
"sisfb: Viewport offset %ldk\n",
6219 ivideo
->video_offset
/ 1024);
6222 printk(KERN_INFO
"sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
6223 ivideo
->mmio_base
, (unsigned long)ivideo
->mmio_vbase
, ivideo
->mmio_size
/ 1024);
6226 /* Determine the size of the command queue */
6227 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
6228 ivideo
->cmdQueueSize
= TURBO_QUEUE_AREA_SIZE
;
6230 if(ivideo
->chip
== XGI_20
) {
6231 ivideo
->cmdQueueSize
= COMMAND_QUEUE_AREA_SIZE_Z7
;
6233 ivideo
->cmdQueueSize
= COMMAND_QUEUE_AREA_SIZE
;
6237 /* Engines are no longer initialized here; this is
6238 * now done after the first mode-switch (if the
6239 * submitted var has its acceleration flags set).
6242 /* Calculate the base of the (unused) hw cursor */
6243 ivideo
->hwcursor_vbase
= ivideo
->video_vbase
6244 + ivideo
->video_size
6245 - ivideo
->cmdQueueSize
6246 - ivideo
->hwcursor_size
;
6247 ivideo
->caps
|= HW_CURSOR_CAP
;
6249 /* Initialize offscreen memory manager */
6250 if((ivideo
->havenoheap
= sisfb_heap_init(ivideo
))) {
6251 printk(KERN_WARNING
"sisfb: Failed to initialize offscreen memory heap\n");
6254 /* Used for clearing the screen only, therefore respect our mem limit */
6255 ivideo
->SiS_Pr
.VideoMemoryAddress
+= ivideo
->video_offset
;
6256 ivideo
->SiS_Pr
.VideoMemorySize
= ivideo
->sisfb_mem
;
6258 ivideo
->vbflags
= 0;
6259 ivideo
->lcddefmodeidx
= DEFAULT_LCDMODE
;
6260 ivideo
->tvdefmodeidx
= DEFAULT_TVMODE
;
6261 ivideo
->defmodeidx
= DEFAULT_MODE
;
6264 if(ivideo
->chip
< XGI_20
) {
6265 if(ivideo
->bios_abase
) {
6266 ivideo
->newrom
= SiSDetermineROMLayout661(&ivideo
->SiS_Pr
);
6270 if((ivideo
->sisfb_mode_idx
< 0) ||
6271 ((sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
]) != 0xFF)) {
6273 sisfb_sense_crt1(ivideo
);
6275 sisfb_get_VB_type(ivideo
);
6277 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
6278 sisfb_detect_VB_connect(ivideo
);
6281 ivideo
->currentvbflags
= ivideo
->vbflags
& (VB_VIDEOBRIDGE
| TV_STANDARD
);
6283 /* Decide on which CRT2 device to use */
6284 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
6285 if(ivideo
->sisfb_crt2type
!= -1) {
6286 if((ivideo
->sisfb_crt2type
== CRT2_LCD
) &&
6287 (ivideo
->vbflags
& CRT2_LCD
)) {
6288 ivideo
->currentvbflags
|= CRT2_LCD
;
6289 } else if(ivideo
->sisfb_crt2type
!= CRT2_LCD
) {
6290 ivideo
->currentvbflags
|= ivideo
->sisfb_crt2type
;
6293 /* Chrontel 700x TV detection often unreliable, therefore
6294 * use a different default order on such machines
6296 if((ivideo
->sisvga_engine
== SIS_300_VGA
) &&
6297 (ivideo
->vbflags2
& VB2_CHRONTEL
)) {
6298 if(ivideo
->vbflags
& CRT2_LCD
)
6299 ivideo
->currentvbflags
|= CRT2_LCD
;
6300 else if(ivideo
->vbflags
& CRT2_TV
)
6301 ivideo
->currentvbflags
|= CRT2_TV
;
6302 else if(ivideo
->vbflags
& CRT2_VGA
)
6303 ivideo
->currentvbflags
|= CRT2_VGA
;
6305 if(ivideo
->vbflags
& CRT2_TV
)
6306 ivideo
->currentvbflags
|= CRT2_TV
;
6307 else if(ivideo
->vbflags
& CRT2_LCD
)
6308 ivideo
->currentvbflags
|= CRT2_LCD
;
6309 else if(ivideo
->vbflags
& CRT2_VGA
)
6310 ivideo
->currentvbflags
|= CRT2_VGA
;
6315 if(ivideo
->vbflags
& CRT2_LCD
) {
6316 sisfb_detect_lcd_type(ivideo
);
6319 sisfb_save_pdc_emi(ivideo
);
6321 if(!ivideo
->sisfb_crt1off
) {
6322 sisfb_handle_ddc(ivideo
, &ivideo
->sisfb_thismonitor
, 0);
6324 if((ivideo
->vbflags2
& VB2_SISTMDSBRIDGE
) &&
6325 (ivideo
->vbflags
& (CRT2_VGA
| CRT2_LCD
))) {
6326 sisfb_handle_ddc(ivideo
, &ivideo
->sisfb_thismonitor
, 1);
6330 if(ivideo
->sisfb_mode_idx
>= 0) {
6331 int bu
= ivideo
->sisfb_mode_idx
;
6332 ivideo
->sisfb_mode_idx
= sisfb_validate_mode(ivideo
,
6333 ivideo
->sisfb_mode_idx
, ivideo
->currentvbflags
);
6334 if(bu
!= ivideo
->sisfb_mode_idx
) {
6335 printk(KERN_ERR
"Mode %dx%dx%d failed validation\n",
6336 sisbios_mode
[bu
].xres
,
6337 sisbios_mode
[bu
].yres
,
6338 sisbios_mode
[bu
].bpp
);
6342 if(ivideo
->sisfb_mode_idx
< 0) {
6343 switch(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
6345 ivideo
->sisfb_mode_idx
= ivideo
->lcddefmodeidx
;
6348 ivideo
->sisfb_mode_idx
= ivideo
->tvdefmodeidx
;
6351 ivideo
->sisfb_mode_idx
= ivideo
->defmodeidx
;
6356 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
6358 if(ivideo
->refresh_rate
!= 0) {
6359 sisfb_search_refresh_rate(ivideo
, ivideo
->refresh_rate
,
6360 ivideo
->sisfb_mode_idx
);
6363 if(ivideo
->rate_idx
== 0) {
6364 ivideo
->rate_idx
= sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
;
6365 ivideo
->refresh_rate
= 60;
6368 if(ivideo
->sisfb_thismonitor
.datavalid
) {
6369 if(!sisfb_verify_rate(ivideo
, &ivideo
->sisfb_thismonitor
,
6370 ivideo
->sisfb_mode_idx
,
6372 ivideo
->refresh_rate
)) {
6373 printk(KERN_INFO
"sisfb: WARNING: Refresh rate "
6374 "exceeds monitor specs!\n");
6378 ivideo
->video_bpp
= sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
;
6379 ivideo
->video_width
= sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
;
6380 ivideo
->video_height
= sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
;
6382 sisfb_set_vparms(ivideo
);
6384 printk(KERN_INFO
"sisfb: Default mode is %dx%dx%d (%dHz)\n",
6385 ivideo
->video_width
, ivideo
->video_height
, ivideo
->video_bpp
,
6386 ivideo
->refresh_rate
);
6388 /* Set up the default var according to chosen default display mode */
6389 ivideo
->default_var
.xres
= ivideo
->default_var
.xres_virtual
= ivideo
->video_width
;
6390 ivideo
->default_var
.yres
= ivideo
->default_var
.yres_virtual
= ivideo
->video_height
;
6391 ivideo
->default_var
.bits_per_pixel
= ivideo
->video_bpp
;
6393 sisfb_bpp_to_var(ivideo
, &ivideo
->default_var
);
6395 ivideo
->default_var
.pixclock
= (u32
) (1000000000 /
6396 sisfb_mode_rate_to_dclock(&ivideo
->SiS_Pr
, ivideo
->mode_no
, ivideo
->rate_idx
));
6398 if(sisfb_mode_rate_to_ddata(&ivideo
->SiS_Pr
, ivideo
->mode_no
,
6399 ivideo
->rate_idx
, &ivideo
->default_var
)) {
6400 if((ivideo
->default_var
.vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
6401 ivideo
->default_var
.pixclock
<<= 1;
6405 if(ivideo
->sisfb_ypan
) {
6406 /* Maximize regardless of sisfb_max at startup */
6407 ivideo
->default_var
.yres_virtual
=
6408 sisfb_calc_maxyres(ivideo
, &ivideo
->default_var
);
6409 if(ivideo
->default_var
.yres_virtual
< ivideo
->default_var
.yres
) {
6410 ivideo
->default_var
.yres_virtual
= ivideo
->default_var
.yres
;
6414 sisfb_calc_pitch(ivideo
, &ivideo
->default_var
);
6417 if(ivideo
->sisfb_accel
) {
6419 #ifdef STUPID_ACCELF_TEXT_SHIT
6420 ivideo
->default_var
.accel_flags
|= FB_ACCELF_TEXT
;
6423 sisfb_initaccel(ivideo
);
6425 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
6426 sis_fb_info
->flags
= FBINFO_DEFAULT
|
6427 FBINFO_HWACCEL_YPAN
|
6428 FBINFO_HWACCEL_XPAN
|
6429 FBINFO_HWACCEL_COPYAREA
|
6430 FBINFO_HWACCEL_FILLRECT
|
6431 ((ivideo
->accel
) ? 0 : FBINFO_HWACCEL_DISABLED
);
6433 sis_fb_info
->flags
= FBINFO_FLAG_DEFAULT
;
6435 sis_fb_info
->var
= ivideo
->default_var
;
6436 sis_fb_info
->fix
= ivideo
->sisfb_fix
;
6437 sis_fb_info
->screen_base
= ivideo
->video_vbase
+ ivideo
->video_offset
;
6438 sis_fb_info
->fbops
= &sisfb_ops
;
6439 sis_fb_info
->pseudo_palette
= ivideo
->pseudo_palette
;
6441 fb_alloc_cmap(&sis_fb_info
->cmap
, 256 , 0);
6443 printk(KERN_DEBUG
"sisfb: Initial vbflags 0x%x\n", (int)ivideo
->vbflags
);
6445 ivideo
->wc_cookie
= arch_phys_wc_add(ivideo
->video_base
,
6446 ivideo
->video_size
);
6447 if(register_framebuffer(sis_fb_info
) < 0) {
6448 printk(KERN_ERR
"sisfb: Fatal error: Failed to register framebuffer\n");
6450 iounmap(ivideo
->mmio_vbase
);
6454 ivideo
->registered
= 1;
6457 ivideo
->next
= card_list
;
6460 printk(KERN_INFO
"sisfb: 2D acceleration is %s, y-panning %s\n",
6461 ivideo
->sisfb_accel
? "enabled" : "disabled",
6462 ivideo
->sisfb_ypan
?
6463 (ivideo
->sisfb_max
? "enabled (auto-max)" :
6464 "enabled (no auto-max)") :
6468 fb_info(sis_fb_info
, "%s frame buffer device version %d.%d.%d\n",
6469 ivideo
->myid
, VER_MAJOR
, VER_MINOR
, VER_LEVEL
);
6471 printk(KERN_INFO
"sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
6473 } /* if mode = "none" */
6478 /*****************************************************/
6479 /* PCI DEVICE HANDLING */
6480 /*****************************************************/
6482 static void sisfb_remove(struct pci_dev
*pdev
)
6484 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
6485 struct fb_info
*sis_fb_info
= ivideo
->memyselfandi
;
6486 int registered
= ivideo
->registered
;
6487 int modechanged
= ivideo
->modechanged
;
6490 iounmap(ivideo
->mmio_vbase
);
6491 iounmap(ivideo
->video_vbase
);
6493 /* Release mem regions */
6494 release_mem_region(ivideo
->video_base
, ivideo
->video_size
);
6495 release_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
);
6497 vfree(ivideo
->bios_abase
);
6499 pci_dev_put(ivideo
->lpcdev
);
6501 pci_dev_put(ivideo
->nbridge
);
6503 arch_phys_wc_del(ivideo
->wc_cookie
);
6505 /* If device was disabled when starting, disable
6508 if(!ivideo
->sisvga_enabled
)
6509 pci_disable_device(pdev
);
6511 /* Unregister the framebuffer */
6512 if(ivideo
->registered
) {
6513 unregister_framebuffer(sis_fb_info
);
6514 framebuffer_release(sis_fb_info
);
6517 /* OK, our ivideo is gone for good from here. */
6519 /* TODO: Restore the initial mode
6520 * This sounds easy but is as good as impossible
6521 * on many machines with SiS chip and video bridge
6522 * since text modes are always set up differently
6523 * from machine to machine. Depends on the type
6524 * of integration between chipset and bridge.
6526 if(registered
&& modechanged
)
6528 "sisfb: Restoring of text mode not supported yet\n");
6531 static struct pci_driver sisfb_driver
= {
6533 .id_table
= sisfb_pci_table
,
6534 .probe
= sisfb_probe
,
6535 .remove
= sisfb_remove
,
6538 static int __init
sisfb_init(void)
6541 char *options
= NULL
;
6543 if(fb_get_options("sisfb", &options
))
6546 sisfb_setup(options
);
6548 return pci_register_driver(&sisfb_driver
);
6552 module_init(sisfb_init
);
6555 /*****************************************************/
6557 /*****************************************************/
6561 static char *mode
= NULL
;
6562 static int vesa
= -1;
6563 static unsigned int rate
= 0;
6564 static unsigned int crt1off
= 1;
6565 static unsigned int mem
= 0;
6566 static char *forcecrt2type
= NULL
;
6567 static int forcecrt1
= -1;
6568 static int pdc
= -1;
6569 static int pdc1
= -1;
6570 static int noaccel
= -1;
6571 static int noypan
= -1;
6572 static int nomax
= -1;
6573 static int userom
= -1;
6574 static int useoem
= -1;
6575 static char *tvstandard
= NULL
;
6576 static int nocrt2rate
= 0;
6577 static int scalelcd
= -1;
6578 static char *specialtiming
= NULL
;
6579 static int lvdshl
= -1;
6580 static int tvxposoffset
= 0, tvyposoffset
= 0;
6581 #if !defined(__i386__) && !defined(__x86_64__)
6582 static int resetcard
= 0;
6583 static int videoram
= 0;
6586 static int __init
sisfb_init_module(void)
6588 sisfb_setdefaultparms();
6591 sisfb_parm_rate
= rate
;
6593 if((scalelcd
== 0) || (scalelcd
== 1))
6594 sisfb_scalelcd
= scalelcd
^ 1;
6596 /* Need to check crt2 type first for fstn/dstn */
6599 sisfb_search_crt2type(forcecrt2type
);
6602 sisfb_search_tvstd(tvstandard
);
6605 sisfb_search_mode(mode
, false);
6607 sisfb_search_vesamode(vesa
, false);
6609 sisfb_crt1off
= (crt1off
== 0) ? 1 : 0;
6611 sisfb_forcecrt1
= forcecrt1
;
6614 else if(forcecrt1
== 0)
6619 else if(noaccel
== 0)
6624 else if(noypan
== 0)
6633 sisfb_parm_mem
= mem
;
6636 sisfb_userom
= userom
;
6639 sisfb_useoem
= useoem
;
6642 sisfb_pdc
= (pdc
& 0x7f);
6645 sisfb_pdca
= (pdc1
& 0x1f);
6647 sisfb_nocrt2rate
= nocrt2rate
;
6650 sisfb_search_specialtiming(specialtiming
);
6652 if((lvdshl
>= 0) && (lvdshl
<= 3))
6653 sisfb_lvdshl
= lvdshl
;
6655 sisfb_tvxposoffset
= tvxposoffset
;
6656 sisfb_tvyposoffset
= tvyposoffset
;
6658 #if !defined(__i386__) && !defined(__x86_64__)
6659 sisfb_resetcard
= (resetcard
) ? 1 : 0;
6661 sisfb_videoram
= videoram
;
6664 return sisfb_init();
6667 static void __exit
sisfb_remove_module(void)
6669 pci_unregister_driver(&sisfb_driver
);
6670 printk(KERN_DEBUG
"sisfb: Module unloaded\n");
6673 module_init(sisfb_init_module
);
6674 module_exit(sisfb_remove_module
);
6676 MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
6677 MODULE_LICENSE("GPL");
6678 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
6680 module_param(mem
, int, 0);
6681 module_param(noaccel
, int, 0);
6682 module_param(noypan
, int, 0);
6683 module_param(nomax
, int, 0);
6684 module_param(userom
, int, 0);
6685 module_param(useoem
, int, 0);
6686 module_param(mode
, charp
, 0);
6687 module_param(vesa
, int, 0);
6688 module_param(rate
, int, 0);
6689 module_param(forcecrt1
, int, 0);
6690 module_param(forcecrt2type
, charp
, 0);
6691 module_param(scalelcd
, int, 0);
6692 module_param(pdc
, int, 0);
6693 module_param(pdc1
, int, 0);
6694 module_param(specialtiming
, charp
, 0);
6695 module_param(lvdshl
, int, 0);
6696 module_param(tvstandard
, charp
, 0);
6697 module_param(tvxposoffset
, int, 0);
6698 module_param(tvyposoffset
, int, 0);
6699 module_param(nocrt2rate
, int, 0);
6700 #if !defined(__i386__) && !defined(__x86_64__)
6701 module_param(resetcard
, int, 0);
6702 module_param(videoram
, int, 0);
6705 MODULE_PARM_DESC(mem
,
6706 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6707 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6708 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6709 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6710 "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6711 "The value is to be specified without 'KB'.\n");
6713 MODULE_PARM_DESC(noaccel
,
6714 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
6717 MODULE_PARM_DESC(noypan
,
6718 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
6719 "will be performed by redrawing the screen. (default: 0)\n");
6721 MODULE_PARM_DESC(nomax
,
6722 "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
6723 "memory for the virtual screen in order to optimize scrolling performance. If\n"
6724 "this is set to anything other than 0, sisfb will not do this and thereby \n"
6725 "enable the user to positively specify a virtual Y size of the screen using\n"
6726 "fbset. (default: 0)\n");
6728 MODULE_PARM_DESC(mode
,
6729 "\nSelects the desired default display mode in the format XxYxDepth,\n"
6730 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
6731 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
6732 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
6734 MODULE_PARM_DESC(vesa
,
6735 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
6736 "0x117 (default: 0x0103)\n");
6738 MODULE_PARM_DESC(rate
,
6739 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
6740 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
6741 "will be ignored (default: 60)\n");
6743 MODULE_PARM_DESC(forcecrt1
,
6744 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
6745 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
6746 "0=CRT1 OFF) (default: [autodetected])\n");
6748 MODULE_PARM_DESC(forcecrt2type
,
6749 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
6750 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
6751 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
6752 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
6753 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
6754 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
6755 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
6756 "depends on the very hardware in use. (default: [autodetected])\n");
6758 MODULE_PARM_DESC(scalelcd
,
6759 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
6760 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
6761 "show black bars around the image, TMDS panels will probably do the scaling\n"
6762 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
6764 MODULE_PARM_DESC(pdc
,
6765 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
6766 "should detect this correctly in most cases; however, sometimes this is not\n"
6767 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
6768 "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
6769 "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
6770 "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
6772 #ifdef CONFIG_FB_SIS_315
6773 MODULE_PARM_DESC(pdc1
,
6774 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
6775 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
6776 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
6777 "implemented yet.\n");
6780 MODULE_PARM_DESC(specialtiming
,
6781 "\nPlease refer to documentation for more information on this option.\n");
6783 MODULE_PARM_DESC(lvdshl
,
6784 "\nPlease refer to documentation for more information on this option.\n");
6786 MODULE_PARM_DESC(tvstandard
,
6787 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
6788 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
6790 MODULE_PARM_DESC(tvxposoffset
,
6791 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
6794 MODULE_PARM_DESC(tvyposoffset
,
6795 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
6798 MODULE_PARM_DESC(nocrt2rate
,
6799 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
6800 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
6802 #if !defined(__i386__) && !defined(__x86_64__)
6803 #ifdef CONFIG_FB_SIS_300
6804 MODULE_PARM_DESC(resetcard
,
6805 "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
6806 "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
6807 "currently). Default: 0\n");
6809 MODULE_PARM_DESC(videoram
,
6810 "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
6811 "some non-x86 architectures where the memory auto detection fails. Only\n"
6812 "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
6816 #endif /* /MODULE */
6818 /* _GPL only for new symbols. */
6819 EXPORT_SYMBOL(sis_malloc
);
6820 EXPORT_SYMBOL(sis_free
);
6821 EXPORT_SYMBOL_GPL(sis_malloc_new
);
6822 EXPORT_SYMBOL_GPL(sis_free_new
);