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/version.h>
37 #include <linux/module.h>
38 #include <linux/moduleparam.h>
39 #include <linux/kernel.h>
40 #include <linux/spinlock.h>
41 #include <linux/errno.h>
42 #include <linux/string.h>
45 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
46 #include <linux/tty.h>
48 #include <linux/screen_info.h>
51 #include <linux/slab.h>
53 #include <linux/selection.h>
54 #include <linux/ioport.h>
55 #include <linux/init.h>
56 #include <linux/pci.h>
57 #include <linux/vmalloc.h>
58 #include <linux/capability.h>
60 #include <linux/types.h>
61 #include <linux/uaccess.h>
70 static void sisfb_handle_command(struct sis_video_info
*ivideo
,
71 struct sisfb_cmd
*sisfb_command
);
73 /* ------------------ Internal helper routines ----------------- */
76 sisfb_setdefaultparms(void)
94 sisfb_specialtiming
= CUT_NONE
;
100 sisfb_tvxposoffset
= 0;
101 sisfb_tvyposoffset
= 0;
102 sisfb_nocrt2rate
= 0;
103 #if !defined(__i386__) && !defined(__x86_64__)
109 /* ------------- Parameter parsing -------------- */
111 static void __devinit
112 sisfb_search_vesamode(unsigned int vesamode
, bool quiet
)
116 /* We don't know the hardware specs yet and there is no ivideo */
120 printk(KERN_ERR
"sisfb: Invalid mode. Using default.\n");
122 sisfb_mode_idx
= DEFAULT_MODE
;
127 vesamode
&= 0x1dff; /* Clean VESA mode number from other flags */
129 while(sisbios_mode
[i
++].mode_no
[0] != 0) {
130 if( (sisbios_mode
[i
-1].vesa_mode_no_1
== vesamode
) ||
131 (sisbios_mode
[i
-1].vesa_mode_no_2
== vesamode
) ) {
133 if(sisbios_mode
[i
-1].mode_no
[1] == 0x50 ||
134 sisbios_mode
[i
-1].mode_no
[1] == 0x56 ||
135 sisbios_mode
[i
-1].mode_no
[1] == 0x53)
138 if(sisbios_mode
[i
-1].mode_no
[1] == 0x5a ||
139 sisbios_mode
[i
-1].mode_no
[1] == 0x5b)
142 sisfb_mode_idx
= i
- 1;
148 printk(KERN_ERR
"sisfb: Invalid VESA mode 0x%x'\n", vesamode
);
151 static void __devinit
152 sisfb_search_mode(char *name
, bool quiet
)
154 unsigned int j
= 0, xres
= 0, yres
= 0, depth
= 0, rate
= 0;
156 char strbuf
[16], strbuf1
[20];
157 char *nameptr
= name
;
159 /* We don't know the hardware specs yet and there is no ivideo */
163 printk(KERN_ERR
"sisfb: Internal error, using default mode.\n");
165 sisfb_mode_idx
= DEFAULT_MODE
;
169 if(!strnicmp(name
, sisbios_mode
[MODE_INDEX_NONE
].name
, strlen(name
))) {
171 printk(KERN_ERR
"sisfb: Mode 'none' not supported anymore. Using default.\n");
173 sisfb_mode_idx
= DEFAULT_MODE
;
177 if(strlen(name
) <= 19) {
178 strcpy(strbuf1
, name
);
179 for(i
= 0; i
< strlen(strbuf1
); i
++) {
180 if(strbuf1
[i
] < '0' || strbuf1
[i
] > '9') strbuf1
[i
] = ' ';
183 /* This does some fuzzy mode naming detection */
184 if(sscanf(strbuf1
, "%u %u %u %u", &xres
, &yres
, &depth
, &rate
) == 4) {
185 if((rate
<= 32) || (depth
> 32)) {
186 j
= rate
; rate
= depth
; depth
= j
;
188 sprintf(strbuf
, "%ux%ux%u", xres
, yres
, depth
);
190 sisfb_parm_rate
= rate
;
191 } else if(sscanf(strbuf1
, "%u %u %u", &xres
, &yres
, &depth
) == 3) {
192 sprintf(strbuf
, "%ux%ux%u", xres
, yres
, depth
);
196 if((sscanf(strbuf1
, "%u %u", &xres
, &yres
) == 2) && (xres
!= 0)) {
197 sprintf(strbuf
, "%ux%ux8", xres
, yres
);
200 sisfb_search_vesamode(simple_strtoul(name
, NULL
, 0), quiet
);
207 while(sisbios_mode
[i
].mode_no
[0] != 0) {
208 if(!strnicmp(nameptr
, sisbios_mode
[i
++].name
, strlen(nameptr
))) {
210 if(sisbios_mode
[i
-1].mode_no
[1] == 0x50 ||
211 sisbios_mode
[i
-1].mode_no
[1] == 0x56 ||
212 sisbios_mode
[i
-1].mode_no
[1] == 0x53)
215 if(sisbios_mode
[i
-1].mode_no
[1] == 0x5a ||
216 sisbios_mode
[i
-1].mode_no
[1] == 0x5b)
219 sisfb_mode_idx
= i
- 1;
226 printk(KERN_ERR
"sisfb: Invalid mode '%s'\n", nameptr
);
230 static void __devinit
231 sisfb_get_vga_mode_from_kernel(void)
235 int mydepth
= screen_info
.lfb_depth
;
237 if(screen_info
.orig_video_isVGA
!= VIDEO_TYPE_VLFB
) return;
239 if( (screen_info
.lfb_width
>= 320) && (screen_info
.lfb_width
<= 2048) &&
240 (screen_info
.lfb_height
>= 200) && (screen_info
.lfb_height
<= 1536) &&
241 (mydepth
>= 8) && (mydepth
<= 32) ) {
243 if(mydepth
== 24) mydepth
= 32;
245 sprintf(mymode
, "%ux%ux%u", screen_info
.lfb_width
,
246 screen_info
.lfb_height
,
250 "sisfb: Using vga mode %s pre-set by kernel as default\n",
253 sisfb_search_mode(mymode
, true);
261 sisfb_search_crt2type(const char *name
)
265 /* We don't know the hardware specs yet and there is no ivideo */
267 if(name
== NULL
) return;
269 while(sis_crt2type
[i
].type_no
!= -1) {
270 if(!strnicmp(name
, sis_crt2type
[i
].name
, strlen(sis_crt2type
[i
].name
))) {
271 sisfb_crt2type
= sis_crt2type
[i
].type_no
;
272 sisfb_tvplug
= sis_crt2type
[i
].tvplug_no
;
273 sisfb_crt2flags
= sis_crt2type
[i
].flags
;
279 sisfb_dstn
= (sisfb_crt2flags
& FL_550_DSTN
) ? 1 : 0;
280 sisfb_fstn
= (sisfb_crt2flags
& FL_550_FSTN
) ? 1 : 0;
282 if(sisfb_crt2type
< 0)
283 printk(KERN_ERR
"sisfb: Invalid CRT2 type: %s\n", name
);
287 sisfb_search_tvstd(const char *name
)
291 /* We don't know the hardware specs yet and there is no ivideo */
296 while(sis_tvtype
[i
].type_no
!= -1) {
297 if(!strnicmp(name
, sis_tvtype
[i
].name
, strlen(sis_tvtype
[i
].name
))) {
298 sisfb_tvstd
= sis_tvtype
[i
].type_no
;
306 sisfb_search_specialtiming(const char *name
)
311 /* We don't know the hardware specs yet and there is no ivideo */
316 if(!strnicmp(name
, "none", 4)) {
317 sisfb_specialtiming
= CUT_FORCENONE
;
318 printk(KERN_DEBUG
"sisfb: Special timing disabled\n");
320 while(mycustomttable
[i
].chipID
!= 0) {
321 if(!strnicmp(name
,mycustomttable
[i
].optionName
,
322 strlen(mycustomttable
[i
].optionName
))) {
323 sisfb_specialtiming
= mycustomttable
[i
].SpecialID
;
325 printk(KERN_INFO
"sisfb: Special timing for %s %s forced (\"%s\")\n",
326 mycustomttable
[i
].vendorName
,
327 mycustomttable
[i
].cardName
,
328 mycustomttable
[i
].optionName
);
334 printk(KERN_WARNING
"sisfb: Invalid SpecialTiming parameter, valid are:");
335 printk(KERN_WARNING
"\t\"none\" (to disable special timings)\n");
337 while(mycustomttable
[i
].chipID
!= 0) {
338 printk(KERN_WARNING
"\t\"%s\" (for %s %s)\n",
339 mycustomttable
[i
].optionName
,
340 mycustomttable
[i
].vendorName
,
341 mycustomttable
[i
].cardName
);
348 /* ----------- Various detection routines ----------- */
350 static void __devinit
351 sisfb_detect_custom_timing(struct sis_video_info
*ivideo
)
353 unsigned char *biosver
= NULL
;
354 unsigned char *biosdate
= NULL
;
359 if(ivideo
->SiS_Pr
.UseROM
) {
360 biosver
= ivideo
->SiS_Pr
.VirtualRomBase
+ 0x06;
361 biosdate
= ivideo
->SiS_Pr
.VirtualRomBase
+ 0x2c;
362 for(i
= 0; i
< 32768; i
++)
363 chksum
+= ivideo
->SiS_Pr
.VirtualRomBase
[i
];
368 if( (mycustomttable
[i
].chipID
== ivideo
->chip
) &&
369 ((!strlen(mycustomttable
[i
].biosversion
)) ||
370 (ivideo
->SiS_Pr
.UseROM
&&
371 (!strncmp(mycustomttable
[i
].biosversion
, biosver
,
372 strlen(mycustomttable
[i
].biosversion
))))) &&
373 ((!strlen(mycustomttable
[i
].biosdate
)) ||
374 (ivideo
->SiS_Pr
.UseROM
&&
375 (!strncmp(mycustomttable
[i
].biosdate
, biosdate
,
376 strlen(mycustomttable
[i
].biosdate
))))) &&
377 ((!mycustomttable
[i
].bioschksum
) ||
378 (ivideo
->SiS_Pr
.UseROM
&&
379 (mycustomttable
[i
].bioschksum
== chksum
))) &&
380 (mycustomttable
[i
].pcisubsysvendor
== ivideo
->subsysvendor
) &&
381 (mycustomttable
[i
].pcisubsyscard
== ivideo
->subsysdevice
) ) {
383 for(j
= 0; j
< 5; j
++) {
384 if(mycustomttable
[i
].biosFootprintAddr
[j
]) {
385 if(ivideo
->SiS_Pr
.UseROM
) {
386 if(ivideo
->SiS_Pr
.VirtualRomBase
[mycustomttable
[i
].biosFootprintAddr
[j
]] !=
387 mycustomttable
[i
].biosFootprintData
[j
]) {
395 ivideo
->SiS_Pr
.SiS_CustomT
= mycustomttable
[i
].SpecialID
;
396 printk(KERN_DEBUG
"sisfb: Identified [%s %s], special timing applies\n",
397 mycustomttable
[i
].vendorName
,
398 mycustomttable
[i
].cardName
);
399 printk(KERN_DEBUG
"sisfb: [specialtiming parameter name: %s]\n",
400 mycustomttable
[i
].optionName
);
405 } while(mycustomttable
[i
].chipID
);
408 static bool __devinit
409 sisfb_interpret_edid(struct sisfb_monitor
*monitor
, u8
*buffer
)
411 int i
, j
, xres
, yres
, refresh
, index
;
414 if(buffer
[0] != 0x00 || buffer
[1] != 0xff ||
415 buffer
[2] != 0xff || buffer
[3] != 0xff ||
416 buffer
[4] != 0xff || buffer
[5] != 0xff ||
417 buffer
[6] != 0xff || buffer
[7] != 0x00) {
418 printk(KERN_DEBUG
"sisfb: Bad EDID header\n");
422 if(buffer
[0x12] != 0x01) {
423 printk(KERN_INFO
"sisfb: EDID version %d not supported\n",
428 monitor
->feature
= buffer
[0x18];
430 if(!(buffer
[0x14] & 0x80)) {
431 if(!(buffer
[0x14] & 0x08)) {
433 "sisfb: WARNING: Monitor does not support separate syncs\n");
437 if(buffer
[0x13] >= 0x01) {
438 /* EDID V1 rev 1 and 2: Search for monitor descriptor
443 if(buffer
[j
] == 0x00 && buffer
[j
+ 1] == 0x00 &&
444 buffer
[j
+ 2] == 0x00 && buffer
[j
+ 3] == 0xfd &&
445 buffer
[j
+ 4] == 0x00) {
446 monitor
->hmin
= buffer
[j
+ 7];
447 monitor
->hmax
= buffer
[j
+ 8];
448 monitor
->vmin
= buffer
[j
+ 5];
449 monitor
->vmax
= buffer
[j
+ 6];
450 monitor
->dclockmax
= buffer
[j
+ 9] * 10 * 1000;
451 monitor
->datavalid
= true;
458 if(!monitor
->datavalid
) {
459 /* Otherwise: Get a range from the list of supported
460 * Estabished Timings. This is not entirely accurate,
461 * because fixed frequency monitors are not supported
464 monitor
->hmin
= 65535; monitor
->hmax
= 0;
465 monitor
->vmin
= 65535; monitor
->vmax
= 0;
466 monitor
->dclockmax
= 0;
467 emodes
= buffer
[0x23] | (buffer
[0x24] << 8) | (buffer
[0x25] << 16);
468 for(i
= 0; i
< 13; i
++) {
469 if(emodes
& sisfb_ddcsmodes
[i
].mask
) {
470 if(monitor
->hmin
> sisfb_ddcsmodes
[i
].h
) monitor
->hmin
= sisfb_ddcsmodes
[i
].h
;
471 if(monitor
->hmax
< sisfb_ddcsmodes
[i
].h
) monitor
->hmax
= sisfb_ddcsmodes
[i
].h
+ 1;
472 if(monitor
->vmin
> sisfb_ddcsmodes
[i
].v
) monitor
->vmin
= sisfb_ddcsmodes
[i
].v
;
473 if(monitor
->vmax
< sisfb_ddcsmodes
[i
].v
) monitor
->vmax
= sisfb_ddcsmodes
[i
].v
;
474 if(monitor
->dclockmax
< sisfb_ddcsmodes
[i
].d
) monitor
->dclockmax
= sisfb_ddcsmodes
[i
].d
;
478 for(i
= 0; i
< 8; i
++) {
479 xres
= (buffer
[index
] + 31) * 8;
480 switch(buffer
[index
+ 1] & 0xc0) {
481 case 0xc0: yres
= (xres
* 9) / 16; break;
482 case 0x80: yres
= (xres
* 4) / 5; break;
483 case 0x40: yres
= (xres
* 3) / 4; break;
484 default: yres
= xres
; break;
486 refresh
= (buffer
[index
+ 1] & 0x3f) + 60;
487 if((xres
>= 640) && (yres
>= 480)) {
488 for(j
= 0; j
< 8; j
++) {
489 if((xres
== sisfb_ddcfmodes
[j
].x
) &&
490 (yres
== sisfb_ddcfmodes
[j
].y
) &&
491 (refresh
== sisfb_ddcfmodes
[j
].v
)) {
492 if(monitor
->hmin
> sisfb_ddcfmodes
[j
].h
) monitor
->hmin
= sisfb_ddcfmodes
[j
].h
;
493 if(monitor
->hmax
< sisfb_ddcfmodes
[j
].h
) monitor
->hmax
= sisfb_ddcfmodes
[j
].h
+ 1;
494 if(monitor
->vmin
> sisfb_ddcsmodes
[j
].v
) monitor
->vmin
= sisfb_ddcsmodes
[j
].v
;
495 if(monitor
->vmax
< sisfb_ddcsmodes
[j
].v
) monitor
->vmax
= sisfb_ddcsmodes
[j
].v
;
496 if(monitor
->dclockmax
< sisfb_ddcsmodes
[j
].d
) monitor
->dclockmax
= sisfb_ddcsmodes
[j
].d
;
502 if((monitor
->hmin
<= monitor
->hmax
) && (monitor
->vmin
<= monitor
->vmax
)) {
503 monitor
->datavalid
= true;
507 return monitor
->datavalid
;
510 static void __devinit
511 sisfb_handle_ddc(struct sis_video_info
*ivideo
, struct sisfb_monitor
*monitor
, int crtno
)
513 unsigned short temp
, i
, realcrtno
= crtno
;
514 unsigned char buffer
[256];
516 monitor
->datavalid
= false;
519 if(ivideo
->vbflags
& CRT2_LCD
) realcrtno
= 1;
520 else if(ivideo
->vbflags
& CRT2_VGA
) realcrtno
= 2;
524 if((ivideo
->sisfb_crt1off
) && (!crtno
))
527 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
528 realcrtno
, 0, &buffer
[0], ivideo
->vbflags2
);
529 if((!temp
) || (temp
== 0xffff)) {
530 printk(KERN_INFO
"sisfb: CRT%d DDC probing failed\n", crtno
+ 1);
533 printk(KERN_INFO
"sisfb: CRT%d DDC supported\n", crtno
+ 1);
534 printk(KERN_INFO
"sisfb: CRT%d DDC level: %s%s%s%s\n",
536 (temp
& 0x1a) ? "" : "[none of the supported]",
537 (temp
& 0x02) ? "2 " : "",
538 (temp
& 0x08) ? "D&P" : "",
539 (temp
& 0x10) ? "FPDI-2" : "");
541 i
= 3; /* Number of retrys */
543 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
544 realcrtno
, 1, &buffer
[0], ivideo
->vbflags2
);
545 } while((temp
) && i
--);
547 if(sisfb_interpret_edid(monitor
, &buffer
[0])) {
548 printk(KERN_INFO
"sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
549 monitor
->hmin
, monitor
->hmax
, monitor
->vmin
, monitor
->vmax
,
550 monitor
->dclockmax
/ 1000);
552 printk(KERN_INFO
"sisfb: CRT%d DDC EDID corrupt\n", crtno
+ 1);
555 printk(KERN_INFO
"sisfb: CRT%d DDC reading failed\n", crtno
+ 1);
558 printk(KERN_INFO
"sisfb: VESA D&P and FPDI-2 not supported yet\n");
563 /* -------------- Mode validation --------------- */
566 sisfb_verify_rate(struct sis_video_info
*ivideo
, struct sisfb_monitor
*monitor
,
567 int mode_idx
, int rate_idx
, int rate
)
570 unsigned int dclock
, hsync
;
572 if(!monitor
->datavalid
)
578 /* Skip for 320x200, 320x240, 640x400 */
579 switch(sisbios_mode
[mode_idx
].mode_no
[ivideo
->mni
]) {
590 #ifdef CONFIG_FB_SIS_315
593 if(ivideo
->sisvga_engine
== SIS_315_VGA
) return true;
597 if(rate
< (monitor
->vmin
- 1))
599 if(rate
> (monitor
->vmax
+ 1))
602 if(sisfb_gettotalfrommode(&ivideo
->SiS_Pr
,
603 sisbios_mode
[mode_idx
].mode_no
[ivideo
->mni
],
604 &htotal
, &vtotal
, rate_idx
)) {
605 dclock
= (htotal
* vtotal
* rate
) / 1000;
606 if(dclock
> (monitor
->dclockmax
+ 1000))
608 hsync
= dclock
/ htotal
;
609 if(hsync
< (monitor
->hmin
- 1))
611 if(hsync
> (monitor
->hmax
+ 1))
620 sisfb_validate_mode(struct sis_video_info
*ivideo
, int myindex
, u32 vbflags
)
622 u16 xres
=0, yres
, myres
;
624 #ifdef CONFIG_FB_SIS_300
625 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
626 if(!(sisbios_mode
[myindex
].chipset
& MD_SIS300
))
630 #ifdef CONFIG_FB_SIS_315
631 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
632 if(!(sisbios_mode
[myindex
].chipset
& MD_SIS315
))
637 myres
= sisbios_mode
[myindex
].yres
;
639 switch(vbflags
& VB_DISPTYPE_DISP2
) {
642 xres
= ivideo
->lcdxres
; yres
= ivideo
->lcdyres
;
644 if((ivideo
->SiS_Pr
.SiS_CustomT
!= CUT_PANEL848
) &&
645 (ivideo
->SiS_Pr
.SiS_CustomT
!= CUT_PANEL856
)) {
646 if(sisbios_mode
[myindex
].xres
> xres
)
652 if(ivideo
->sisfb_fstn
) {
653 if(sisbios_mode
[myindex
].xres
== 320) {
655 switch(sisbios_mode
[myindex
].mode_no
[1]) {
656 case 0x50: myindex
= MODE_FSTN_8
; break;
657 case 0x56: myindex
= MODE_FSTN_16
; break;
658 case 0x53: return -1;
664 if(SiS_GetModeID_LCD(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
665 sisbios_mode
[myindex
].yres
, 0, ivideo
->sisfb_fstn
,
666 ivideo
->SiS_Pr
.SiS_CustomT
, xres
, yres
, ivideo
->vbflags2
) < 0x14) {
672 if(SiS_GetModeID_TV(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
673 sisbios_mode
[myindex
].yres
, 0, ivideo
->vbflags2
) < 0x14) {
679 if(SiS_GetModeID_VGA2(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
680 sisbios_mode
[myindex
].yres
, 0, ivideo
->vbflags2
) < 0x14) {
690 sisfb_search_refresh_rate(struct sis_video_info
*ivideo
, unsigned int rate
, int mode_idx
)
693 u16 xres
= sisbios_mode
[mode_idx
].xres
;
694 u16 yres
= sisbios_mode
[mode_idx
].yres
;
696 ivideo
->rate_idx
= 0;
697 while((sisfb_vrate
[i
].idx
!= 0) && (sisfb_vrate
[i
].xres
<= xres
)) {
698 if((sisfb_vrate
[i
].xres
== xres
) && (sisfb_vrate
[i
].yres
== yres
)) {
699 if(sisfb_vrate
[i
].refresh
== rate
) {
700 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
702 } else if(sisfb_vrate
[i
].refresh
> rate
) {
703 if((sisfb_vrate
[i
].refresh
- rate
) <= 3) {
704 DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
705 rate
, sisfb_vrate
[i
].refresh
);
706 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
707 ivideo
->refresh_rate
= sisfb_vrate
[i
].refresh
;
708 } else if(((rate
- sisfb_vrate
[i
-1].refresh
) <= 2)
709 && (sisfb_vrate
[i
].idx
!= 1)) {
710 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
711 rate
, sisfb_vrate
[i
-1].refresh
);
712 ivideo
->rate_idx
= sisfb_vrate
[i
-1].idx
;
713 ivideo
->refresh_rate
= sisfb_vrate
[i
-1].refresh
;
716 } else if((rate
- sisfb_vrate
[i
].refresh
) <= 2) {
717 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
718 rate
, sisfb_vrate
[i
].refresh
);
719 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
725 if(ivideo
->rate_idx
> 0) {
726 return ivideo
->rate_idx
;
728 printk(KERN_INFO
"sisfb: Unsupported rate %d for %dx%d\n",
735 sisfb_bridgeisslave(struct sis_video_info
*ivideo
)
739 if(!(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
))
742 inSISIDXREG(SISPART1
,0x00,P1_00
);
743 if( ((ivideo
->sisvga_engine
== SIS_300_VGA
) && (P1_00
& 0xa0) == 0x20) ||
744 ((ivideo
->sisvga_engine
== SIS_315_VGA
) && (P1_00
& 0x50) == 0x10) ) {
752 sisfballowretracecrt1(struct sis_video_info
*ivideo
)
756 inSISIDXREG(SISCR
,0x17,temp
);
760 inSISIDXREG(SISSR
,0x1f,temp
);
768 sisfbcheckvretracecrt1(struct sis_video_info
*ivideo
)
770 if(!sisfballowretracecrt1(ivideo
))
773 if(inSISREG(SISINPSTAT
) & 0x08)
780 sisfbwaitretracecrt1(struct sis_video_info
*ivideo
)
784 if(!sisfballowretracecrt1(ivideo
))
788 while((!(inSISREG(SISINPSTAT
) & 0x08)) && --watchdog
);
790 while((inSISREG(SISINPSTAT
) & 0x08) && --watchdog
);
794 sisfbcheckvretracecrt2(struct sis_video_info
*ivideo
)
796 unsigned char temp
, reg
;
798 switch(ivideo
->sisvga_engine
) {
799 case SIS_300_VGA
: reg
= 0x25; break;
800 case SIS_315_VGA
: reg
= 0x30; break;
801 default: return false;
804 inSISIDXREG(SISPART1
, reg
, temp
);
812 sisfb_CheckVBRetrace(struct sis_video_info
*ivideo
)
814 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
815 if(!sisfb_bridgeisslave(ivideo
)) {
816 return sisfbcheckvretracecrt2(ivideo
);
819 return sisfbcheckvretracecrt1(ivideo
);
823 sisfb_setupvbblankflags(struct sis_video_info
*ivideo
, u32
*vcount
, u32
*hcount
)
825 u8 idx
, reg1
, reg2
, reg3
, reg4
;
828 (*vcount
) = (*hcount
) = 0;
830 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) && (!(sisfb_bridgeisslave(ivideo
)))) {
832 ret
|= (FB_VBLANK_HAVE_VSYNC
|
833 FB_VBLANK_HAVE_HBLANK
|
834 FB_VBLANK_HAVE_VBLANK
|
835 FB_VBLANK_HAVE_VCOUNT
|
836 FB_VBLANK_HAVE_HCOUNT
);
837 switch(ivideo
->sisvga_engine
) {
838 case SIS_300_VGA
: idx
= 0x25; break;
840 case SIS_315_VGA
: idx
= 0x30; break;
842 inSISIDXREG(SISPART1
,(idx
+0),reg1
); /* 30 */
843 inSISIDXREG(SISPART1
,(idx
+1),reg2
); /* 31 */
844 inSISIDXREG(SISPART1
,(idx
+2),reg3
); /* 32 */
845 inSISIDXREG(SISPART1
,(idx
+3),reg4
); /* 33 */
846 if(reg1
& 0x01) ret
|= FB_VBLANK_VBLANKING
;
847 if(reg1
& 0x02) ret
|= FB_VBLANK_VSYNCING
;
848 if(reg4
& 0x80) ret
|= FB_VBLANK_HBLANKING
;
849 (*vcount
) = reg3
| ((reg4
& 0x70) << 4);
850 (*hcount
) = reg2
| ((reg4
& 0x0f) << 8);
852 } else if(sisfballowretracecrt1(ivideo
)) {
854 ret
|= (FB_VBLANK_HAVE_VSYNC
|
855 FB_VBLANK_HAVE_VBLANK
|
856 FB_VBLANK_HAVE_VCOUNT
|
857 FB_VBLANK_HAVE_HCOUNT
);
858 reg1
= inSISREG(SISINPSTAT
);
859 if(reg1
& 0x08) ret
|= FB_VBLANK_VSYNCING
;
860 if(reg1
& 0x01) ret
|= FB_VBLANK_VBLANKING
;
861 inSISIDXREG(SISCR
,0x20,reg1
);
862 inSISIDXREG(SISCR
,0x1b,reg1
);
863 inSISIDXREG(SISCR
,0x1c,reg2
);
864 inSISIDXREG(SISCR
,0x1d,reg3
);
865 (*vcount
) = reg2
| ((reg3
& 0x07) << 8);
866 (*hcount
) = (reg1
| ((reg3
& 0x10) << 4)) << 3;
873 sisfb_myblank(struct sis_video_info
*ivideo
, int blank
)
875 u8 sr01
, sr11
, sr1f
, cr63
=0, p2_0
, p1_13
;
876 bool backlight
= true;
879 case FB_BLANK_UNBLANK
: /* on */
888 case FB_BLANK_NORMAL
: /* blank */
897 case FB_BLANK_VSYNC_SUSPEND
: /* no vsync */
906 case FB_BLANK_HSYNC_SUSPEND
: /* no hsync */
915 case FB_BLANK_POWERDOWN
: /* off */
928 if(ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
) {
930 if( (!ivideo
->sisfb_thismonitor
.datavalid
) ||
931 ((ivideo
->sisfb_thismonitor
.datavalid
) &&
932 (ivideo
->sisfb_thismonitor
.feature
& 0xe0))) {
934 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
935 setSISIDXREG(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, 0xbf, cr63
);
938 if(!(sisfb_bridgeisslave(ivideo
))) {
939 setSISIDXREG(SISSR
, 0x01, ~0x20, sr01
);
940 setSISIDXREG(SISSR
, 0x1f, 0x3f, sr1f
);
946 if(ivideo
->currentvbflags
& CRT2_LCD
) {
948 if(ivideo
->vbflags2
& VB2_SISLVDSBRIDGE
) {
950 SiS_SiS30xBLOn(&ivideo
->SiS_Pr
);
952 SiS_SiS30xBLOff(&ivideo
->SiS_Pr
);
954 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
955 #ifdef CONFIG_FB_SIS_315
956 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
958 SiS_Chrontel701xBLOn(&ivideo
->SiS_Pr
);
960 SiS_Chrontel701xBLOff(&ivideo
->SiS_Pr
);
966 if(((ivideo
->sisvga_engine
== SIS_300_VGA
) &&
967 (ivideo
->vbflags2
& (VB2_301
|VB2_30xBDH
|VB2_LVDS
))) ||
968 ((ivideo
->sisvga_engine
== SIS_315_VGA
) &&
969 ((ivideo
->vbflags2
& (VB2_LVDS
| VB2_CHRONTEL
)) == VB2_LVDS
))) {
970 setSISIDXREG(SISSR
, 0x11, ~0x0c, sr11
);
973 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
974 if((ivideo
->vbflags2
& VB2_30xB
) &&
975 (!(ivideo
->vbflags2
& VB2_30xBDH
))) {
976 setSISIDXREG(SISPART1
, 0x13, 0x3f, p1_13
);
978 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
979 if((ivideo
->vbflags2
& VB2_30xB
) &&
980 (!(ivideo
->vbflags2
& VB2_30xBDH
))) {
981 setSISIDXREG(SISPART2
, 0x00, 0x1f, p2_0
);
985 } else if(ivideo
->currentvbflags
& CRT2_VGA
) {
987 if(ivideo
->vbflags2
& VB2_30xB
) {
988 setSISIDXREG(SISPART2
, 0x00, 0x1f, p2_0
);
996 /* ------------- Callbacks from init.c/init301.c -------------- */
998 #ifdef CONFIG_FB_SIS_300
1000 sisfb_read_nbridge_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
)
1002 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1005 pci_read_config_dword(ivideo
->nbridge
, reg
, &val
);
1006 return (unsigned int)val
;
1010 sisfb_write_nbridge_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
, unsigned int val
)
1012 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1014 pci_write_config_dword(ivideo
->nbridge
, reg
, (u32
)val
);
1018 sisfb_read_lpc_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
)
1020 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1023 if(!ivideo
->lpcdev
) return 0;
1025 pci_read_config_dword(ivideo
->lpcdev
, reg
, &val
);
1026 return (unsigned int)val
;
1030 #ifdef CONFIG_FB_SIS_315
1032 sisfb_write_nbridge_pci_byte(struct SiS_Private
*SiS_Pr
, int reg
, unsigned char val
)
1034 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1036 pci_write_config_byte(ivideo
->nbridge
, reg
, (u8
)val
);
1040 sisfb_read_mio_pci_word(struct SiS_Private
*SiS_Pr
, int reg
)
1042 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1045 if(!ivideo
->lpcdev
) return 0;
1047 pci_read_config_word(ivideo
->lpcdev
, reg
, &val
);
1048 return (unsigned int)val
;
1052 /* ----------- FBDev related routines for all series ----------- */
1055 sisfb_get_cmap_len(const struct fb_var_screeninfo
*var
)
1057 return (var
->bits_per_pixel
== 8) ? 256 : 16;
1061 sisfb_set_vparms(struct sis_video_info
*ivideo
)
1063 switch(ivideo
->video_bpp
) {
1065 ivideo
->DstColor
= 0x0000;
1066 ivideo
->SiS310_AccelDepth
= 0x00000000;
1067 ivideo
->video_cmap_len
= 256;
1070 ivideo
->DstColor
= 0x8000;
1071 ivideo
->SiS310_AccelDepth
= 0x00010000;
1072 ivideo
->video_cmap_len
= 16;
1075 ivideo
->DstColor
= 0xC000;
1076 ivideo
->SiS310_AccelDepth
= 0x00020000;
1077 ivideo
->video_cmap_len
= 16;
1080 ivideo
->video_cmap_len
= 16;
1081 printk(KERN_ERR
"sisfb: Unsupported depth %d", ivideo
->video_bpp
);
1087 sisfb_calc_maxyres(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1089 int maxyres
= ivideo
->sisfb_mem
/ (var
->xres_virtual
* (var
->bits_per_pixel
>> 3));
1091 if(maxyres
> 32767) maxyres
= 32767;
1097 sisfb_calc_pitch(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1099 ivideo
->video_linelength
= var
->xres_virtual
* (var
->bits_per_pixel
>> 3);
1100 ivideo
->scrnpitchCRT1
= ivideo
->video_linelength
;
1101 if(!(ivideo
->currentvbflags
& CRT1_LCDA
)) {
1102 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1103 ivideo
->scrnpitchCRT1
<<= 1;
1109 sisfb_set_pitch(struct sis_video_info
*ivideo
)
1111 bool isslavemode
= false;
1112 unsigned short HDisplay1
= ivideo
->scrnpitchCRT1
>> 3;
1113 unsigned short HDisplay2
= ivideo
->video_linelength
>> 3;
1115 if(sisfb_bridgeisslave(ivideo
)) isslavemode
= true;
1117 /* We need to set pitch for CRT1 if bridge is in slave mode, too */
1118 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP1
) || (isslavemode
)) {
1119 outSISIDXREG(SISCR
,0x13,(HDisplay1
& 0xFF));
1120 setSISIDXREG(SISSR
,0x0E,0xF0,(HDisplay1
>> 8));
1123 /* We must not set the pitch for CRT2 if bridge is in slave mode */
1124 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) && (!isslavemode
)) {
1125 orSISIDXREG(SISPART1
,ivideo
->CRT2_write_enable
,0x01);
1126 outSISIDXREG(SISPART1
,0x07,(HDisplay2
& 0xFF));
1127 setSISIDXREG(SISPART1
,0x09,0xF0,(HDisplay2
>> 8));
1132 sisfb_bpp_to_var(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1134 ivideo
->video_cmap_len
= sisfb_get_cmap_len(var
);
1136 switch(var
->bits_per_pixel
) {
1138 var
->red
.offset
= var
->green
.offset
= var
->blue
.offset
= 0;
1139 var
->red
.length
= var
->green
.length
= var
->blue
.length
= 6;
1142 var
->red
.offset
= 11;
1143 var
->red
.length
= 5;
1144 var
->green
.offset
= 5;
1145 var
->green
.length
= 6;
1146 var
->blue
.offset
= 0;
1147 var
->blue
.length
= 5;
1148 var
->transp
.offset
= 0;
1149 var
->transp
.length
= 0;
1152 var
->red
.offset
= 16;
1153 var
->red
.length
= 8;
1154 var
->green
.offset
= 8;
1155 var
->green
.length
= 8;
1156 var
->blue
.offset
= 0;
1157 var
->blue
.length
= 8;
1158 var
->transp
.offset
= 24;
1159 var
->transp
.length
= 8;
1165 sisfb_set_mode(struct sis_video_info
*ivideo
, int clrscrn
)
1167 unsigned short modeno
= ivideo
->mode_no
;
1169 /* >=2.6.12's fbcon clears the screen anyway */
1170 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
1171 if(!clrscrn
) modeno
|= 0x80;
1176 outSISIDXREG(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1178 sisfb_pre_setmode(ivideo
);
1180 if(!SiSSetMode(&ivideo
->SiS_Pr
, modeno
)) {
1181 printk(KERN_ERR
"sisfb: Setting mode[0x%x] failed\n", ivideo
->mode_no
);
1185 outSISIDXREG(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1187 sisfb_post_setmode(ivideo
);
1194 sisfb_do_set_var(struct fb_var_screeninfo
*var
, int isactive
, struct fb_info
*info
)
1196 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1197 unsigned int htotal
= 0, vtotal
= 0;
1198 unsigned int drate
= 0, hrate
= 0;
1199 int found_mode
= 0, ret
;
1203 htotal
= var
->left_margin
+ var
->xres
+ var
->right_margin
+ var
->hsync_len
;
1205 vtotal
= var
->upper_margin
+ var
->lower_margin
+ var
->vsync_len
;
1207 pixclock
= var
->pixclock
;
1209 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
) {
1210 vtotal
+= var
->yres
;
1212 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1213 vtotal
+= var
->yres
;
1215 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1216 vtotal
+= var
->yres
;
1218 } else vtotal
+= var
->yres
;
1220 if(!(htotal
) || !(vtotal
)) {
1221 DPRINTK("sisfb: Invalid 'var' information\n");
1225 if(pixclock
&& htotal
&& vtotal
) {
1226 drate
= 1000000000 / pixclock
;
1227 hrate
= (drate
* 1000) / htotal
;
1228 ivideo
->refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1230 ivideo
->refresh_rate
= 60;
1233 old_mode
= ivideo
->sisfb_mode_idx
;
1234 ivideo
->sisfb_mode_idx
= 0;
1236 while( (sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[0] != 0) &&
1237 (sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
<= var
->xres
) ) {
1238 if( (sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
== var
->xres
) &&
1239 (sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
== var
->yres
) &&
1240 (sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
== var
->bits_per_pixel
)) {
1241 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
1245 ivideo
->sisfb_mode_idx
++;
1249 ivideo
->sisfb_mode_idx
= sisfb_validate_mode(ivideo
,
1250 ivideo
->sisfb_mode_idx
, ivideo
->currentvbflags
);
1252 ivideo
->sisfb_mode_idx
= -1;
1255 if(ivideo
->sisfb_mode_idx
< 0) {
1256 printk(KERN_ERR
"sisfb: Mode %dx%dx%d not supported\n", var
->xres
,
1257 var
->yres
, var
->bits_per_pixel
);
1258 ivideo
->sisfb_mode_idx
= old_mode
;
1262 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
1264 if(sisfb_search_refresh_rate(ivideo
, ivideo
->refresh_rate
, ivideo
->sisfb_mode_idx
) == 0) {
1265 ivideo
->rate_idx
= sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
;
1266 ivideo
->refresh_rate
= 60;
1270 /* If acceleration to be used? Need to know
1271 * before pre/post_set_mode()
1274 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
1275 #ifdef STUPID_ACCELF_TEXT_SHIT
1276 if(var
->accel_flags
& FB_ACCELF_TEXT
) {
1277 info
->flags
&= ~FBINFO_HWACCEL_DISABLED
;
1279 info
->flags
|= FBINFO_HWACCEL_DISABLED
;
1282 if(!(info
->flags
& FBINFO_HWACCEL_DISABLED
)) ivideo
->accel
= -1;
1284 if(var
->accel_flags
& FB_ACCELF_TEXT
) ivideo
->accel
= -1;
1287 if((ret
= sisfb_set_mode(ivideo
, 1))) {
1291 ivideo
->video_bpp
= sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
;
1292 ivideo
->video_width
= sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
;
1293 ivideo
->video_height
= sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
;
1295 sisfb_calc_pitch(ivideo
, var
);
1296 sisfb_set_pitch(ivideo
);
1298 sisfb_set_vparms(ivideo
);
1300 ivideo
->current_width
= ivideo
->video_width
;
1301 ivideo
->current_height
= ivideo
->video_height
;
1302 ivideo
->current_bpp
= ivideo
->video_bpp
;
1303 ivideo
->current_htotal
= htotal
;
1304 ivideo
->current_vtotal
= vtotal
;
1305 ivideo
->current_linelength
= ivideo
->video_linelength
;
1306 ivideo
->current_pixclock
= var
->pixclock
;
1307 ivideo
->current_refresh_rate
= ivideo
->refresh_rate
;
1308 ivideo
->sisfb_lastrates
[ivideo
->mode_no
] = ivideo
->refresh_rate
;
1315 sisfb_set_base_CRT1(struct sis_video_info
*ivideo
, unsigned int base
)
1317 outSISIDXREG(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1319 outSISIDXREG(SISCR
, 0x0D, base
& 0xFF);
1320 outSISIDXREG(SISCR
, 0x0C, (base
>> 8) & 0xFF);
1321 outSISIDXREG(SISSR
, 0x0D, (base
>> 16) & 0xFF);
1322 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
1323 setSISIDXREG(SISSR
, 0x37, 0xFE, (base
>> 24) & 0x01);
1328 sisfb_set_base_CRT2(struct sis_video_info
*ivideo
, unsigned int base
)
1330 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
1331 orSISIDXREG(SISPART1
, ivideo
->CRT2_write_enable
, 0x01);
1332 outSISIDXREG(SISPART1
, 0x06, (base
& 0xFF));
1333 outSISIDXREG(SISPART1
, 0x05, ((base
>> 8) & 0xFF));
1334 outSISIDXREG(SISPART1
, 0x04, ((base
>> 16) & 0xFF));
1335 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
1336 setSISIDXREG(SISPART1
, 0x02, 0x7F, ((base
>> 24) & 0x01) << 7);
1342 sisfb_pan_var(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1344 if(var
->xoffset
> (var
->xres_virtual
- var
->xres
)) {
1347 if(var
->yoffset
> (var
->yres_virtual
- var
->yres
)) {
1351 ivideo
->current_base
= (var
->yoffset
* var
->xres_virtual
) + var
->xoffset
;
1353 /* calculate base bpp dep. */
1354 switch(var
->bits_per_pixel
) {
1358 ivideo
->current_base
>>= 1;
1362 ivideo
->current_base
>>= 2;
1366 ivideo
->current_base
+= (ivideo
->video_offset
>> 2);
1368 sisfb_set_base_CRT1(ivideo
, ivideo
->current_base
);
1369 sisfb_set_base_CRT2(ivideo
, ivideo
->current_base
);
1375 sisfb_open(struct fb_info
*info
, int user
)
1381 sisfb_release(struct fb_info
*info
, int user
)
1387 sisfb_setcolreg(unsigned regno
, unsigned red
, unsigned green
, unsigned blue
,
1388 unsigned transp
, struct fb_info
*info
)
1390 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1392 if(regno
>= sisfb_get_cmap_len(&info
->var
))
1395 switch(info
->var
.bits_per_pixel
) {
1397 outSISREG(SISDACA
, regno
);
1398 outSISREG(SISDACD
, (red
>> 10));
1399 outSISREG(SISDACD
, (green
>> 10));
1400 outSISREG(SISDACD
, (blue
>> 10));
1401 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
1402 outSISREG(SISDAC2A
, regno
);
1403 outSISREG(SISDAC2D
, (red
>> 8));
1404 outSISREG(SISDAC2D
, (green
>> 8));
1405 outSISREG(SISDAC2D
, (blue
>> 8));
1412 ((u32
*)(info
->pseudo_palette
))[regno
] =
1414 ((green
& 0xfc00) >> 5) |
1415 ((blue
& 0xf800) >> 11);
1424 ((u32
*)(info
->pseudo_palette
))[regno
] =
1425 (red
<< 16) | (green
<< 8) | (blue
);
1432 sisfb_set_par(struct fb_info
*info
)
1436 if((err
= sisfb_do_set_var(&info
->var
, 1, info
)))
1439 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
1440 sisfb_get_fix(&info
->fix
, info
->currcon
, info
);
1442 sisfb_get_fix(&info
->fix
, -1, info
);
1448 sisfb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
1450 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1451 unsigned int htotal
= 0, vtotal
= 0, myrateindex
= 0;
1452 unsigned int drate
= 0, hrate
= 0, maxyres
;
1454 int refresh_rate
, search_idx
, tidx
;
1455 bool recalc_clock
= false;
1458 htotal
= var
->left_margin
+ var
->xres
+ var
->right_margin
+ var
->hsync_len
;
1460 vtotal
= var
->upper_margin
+ var
->lower_margin
+ var
->vsync_len
;
1462 pixclock
= var
->pixclock
;
1464 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
) {
1465 vtotal
+= var
->yres
;
1467 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1468 vtotal
+= var
->yres
;
1470 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1471 vtotal
+= var
->yres
;
1474 vtotal
+= var
->yres
;
1476 if(!(htotal
) || !(vtotal
)) {
1477 SISFAIL("sisfb: no valid timing data");
1481 while( (sisbios_mode
[search_idx
].mode_no
[0] != 0) &&
1482 (sisbios_mode
[search_idx
].xres
<= var
->xres
) ) {
1483 if( (sisbios_mode
[search_idx
].xres
== var
->xres
) &&
1484 (sisbios_mode
[search_idx
].yres
== var
->yres
) &&
1485 (sisbios_mode
[search_idx
].bpp
== var
->bits_per_pixel
)) {
1486 if((tidx
= sisfb_validate_mode(ivideo
, search_idx
,
1487 ivideo
->currentvbflags
)) > 0) {
1498 while(sisbios_mode
[search_idx
].mode_no
[0] != 0) {
1499 if( (var
->xres
<= sisbios_mode
[search_idx
].xres
) &&
1500 (var
->yres
<= sisbios_mode
[search_idx
].yres
) &&
1501 (var
->bits_per_pixel
== sisbios_mode
[search_idx
].bpp
) ) {
1502 if((tidx
= sisfb_validate_mode(ivideo
,search_idx
,
1503 ivideo
->currentvbflags
)) > 0) {
1513 "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
1514 var
->xres
, var
->yres
, var
->bits_per_pixel
,
1515 sisbios_mode
[search_idx
].xres
,
1516 sisbios_mode
[search_idx
].yres
,
1517 var
->bits_per_pixel
);
1518 var
->xres
= sisbios_mode
[search_idx
].xres
;
1519 var
->yres
= sisbios_mode
[search_idx
].yres
;
1522 "sisfb: Failed to find supported mode near %dx%dx%d\n",
1523 var
->xres
, var
->yres
, var
->bits_per_pixel
);
1528 if( ((ivideo
->vbflags2
& VB2_LVDS
) ||
1529 ((ivideo
->vbflags2
& VB2_30xBDH
) && (ivideo
->currentvbflags
& CRT2_LCD
))) &&
1530 (var
->bits_per_pixel
== 8) ) {
1531 /* Slave modes on LVDS and 301B-DH */
1533 recalc_clock
= true;
1534 } else if( (ivideo
->current_htotal
== htotal
) &&
1535 (ivideo
->current_vtotal
== vtotal
) &&
1536 (ivideo
->current_pixclock
== pixclock
) ) {
1537 /* x=x & y=y & c=c -> assume depth change */
1538 drate
= 1000000000 / pixclock
;
1539 hrate
= (drate
* 1000) / htotal
;
1540 refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1541 } else if( ( (ivideo
->current_htotal
!= htotal
) ||
1542 (ivideo
->current_vtotal
!= vtotal
) ) &&
1543 (ivideo
->current_pixclock
== var
->pixclock
) ) {
1544 /* x!=x | y!=y & c=c -> invalid pixclock */
1545 if(ivideo
->sisfb_lastrates
[sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
]]) {
1547 ivideo
->sisfb_lastrates
[sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
]];
1548 } else if(ivideo
->sisfb_parm_rate
!= -1) {
1549 /* Sic, sisfb_parm_rate - want to know originally desired rate here */
1550 refresh_rate
= ivideo
->sisfb_parm_rate
;
1554 recalc_clock
= true;
1555 } else if((pixclock
) && (htotal
) && (vtotal
)) {
1556 drate
= 1000000000 / pixclock
;
1557 hrate
= (drate
* 1000) / htotal
;
1558 refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1559 } else if(ivideo
->current_refresh_rate
) {
1560 refresh_rate
= ivideo
->current_refresh_rate
;
1561 recalc_clock
= true;
1564 recalc_clock
= true;
1567 myrateindex
= sisfb_search_refresh_rate(ivideo
, refresh_rate
, search_idx
);
1569 /* Eventually recalculate timing and clock */
1571 if(!myrateindex
) myrateindex
= sisbios_mode
[search_idx
].rate_idx
;
1572 var
->pixclock
= (u32
) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo
->SiS_Pr
,
1573 sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
],
1575 sisfb_mode_rate_to_ddata(&ivideo
->SiS_Pr
,
1576 sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
],
1578 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1579 var
->pixclock
<<= 1;
1583 if(ivideo
->sisfb_thismonitor
.datavalid
) {
1584 if(!sisfb_verify_rate(ivideo
, &ivideo
->sisfb_thismonitor
, search_idx
,
1585 myrateindex
, refresh_rate
)) {
1587 "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1591 /* Adapt RGB settings */
1592 sisfb_bpp_to_var(ivideo
, var
);
1594 /* Sanity check for offsets */
1595 if(var
->xoffset
< 0) var
->xoffset
= 0;
1596 if(var
->yoffset
< 0) var
->yoffset
= 0;
1598 if(var
->xres
> var
->xres_virtual
)
1599 var
->xres_virtual
= var
->xres
;
1601 if(ivideo
->sisfb_ypan
) {
1602 maxyres
= sisfb_calc_maxyres(ivideo
, var
);
1603 if(ivideo
->sisfb_max
) {
1604 var
->yres_virtual
= maxyres
;
1606 if(var
->yres_virtual
> maxyres
) {
1607 var
->yres_virtual
= maxyres
;
1610 if(var
->yres_virtual
<= var
->yres
) {
1611 var
->yres_virtual
= var
->yres
;
1614 if(var
->yres
!= var
->yres_virtual
) {
1615 var
->yres_virtual
= var
->yres
;
1621 /* Truncate offsets to maximum if too high */
1622 if(var
->xoffset
> var
->xres_virtual
- var
->xres
) {
1623 var
->xoffset
= var
->xres_virtual
- var
->xres
- 1;
1626 if(var
->yoffset
> var
->yres_virtual
- var
->yres
) {
1627 var
->yoffset
= var
->yres_virtual
- var
->yres
- 1;
1630 /* Set everything else to 0 */
1631 var
->red
.msb_right
=
1632 var
->green
.msb_right
=
1633 var
->blue
.msb_right
=
1634 var
->transp
.offset
=
1635 var
->transp
.length
=
1636 var
->transp
.msb_right
= 0;
1642 sisfb_pan_display(struct fb_var_screeninfo
*var
, struct fb_info
* info
)
1644 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1647 if(var
->xoffset
> (var
->xres_virtual
- var
->xres
))
1650 if(var
->yoffset
> (var
->yres_virtual
- var
->yres
))
1653 if(var
->vmode
& FB_VMODE_YWRAP
)
1656 if(var
->xoffset
+ info
->var
.xres
> info
->var
.xres_virtual
||
1657 var
->yoffset
+ info
->var
.yres
> info
->var
.yres_virtual
)
1660 if((err
= sisfb_pan_var(ivideo
, var
)) < 0)
1663 info
->var
.xoffset
= var
->xoffset
;
1664 info
->var
.yoffset
= var
->yoffset
;
1670 sisfb_blank(int blank
, struct fb_info
*info
)
1672 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1674 return sisfb_myblank(ivideo
, blank
);
1677 /* ----------- FBDev related routines for all series ---------- */
1679 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
1680 static int sisfb_ioctl(struct fb_info
*info
, unsigned int cmd
,
1683 static int sisfb_ioctl(struct inode
*inode
, struct file
*file
,
1684 unsigned int cmd
, unsigned long arg
,
1685 struct fb_info
*info
)
1688 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1689 struct sis_memreq sismemreq
;
1690 struct fb_vblank sisvbblank
;
1695 u32 __user
*argp
= (u32 __user
*)arg
;
1699 if(!capable(CAP_SYS_RAWIO
))
1702 if(copy_from_user(&sismemreq
, (void __user
*)arg
, sizeof(sismemreq
)))
1705 sis_malloc(&sismemreq
);
1707 if(copy_to_user((void __user
*)arg
, &sismemreq
, sizeof(sismemreq
))) {
1708 sis_free((u32
)sismemreq
.offset
);
1714 if(!capable(CAP_SYS_RAWIO
))
1717 if(get_user(gpu32
, argp
))
1723 case FBIOGET_VBLANK
:
1724 sisvbblank
.count
= 0;
1725 sisvbblank
.flags
= sisfb_setupvbblankflags(ivideo
, &sisvbblank
.vcount
, &sisvbblank
.hcount
);
1727 if(copy_to_user((void __user
*)arg
, &sisvbblank
, sizeof(sisvbblank
)))
1732 case SISFB_GET_INFO_SIZE
:
1733 return put_user(sizeof(struct sisfb_info
), argp
);
1735 case SISFB_GET_INFO_OLD
:
1736 if(ivideo
->warncount
++ < 10)
1738 "sisfb: Deprecated ioctl call received - update your application!\n");
1739 case SISFB_GET_INFO
: /* For communication with X driver */
1740 ivideo
->sisfb_infoblock
.sisfb_id
= SISFB_ID
;
1741 ivideo
->sisfb_infoblock
.sisfb_version
= VER_MAJOR
;
1742 ivideo
->sisfb_infoblock
.sisfb_revision
= VER_MINOR
;
1743 ivideo
->sisfb_infoblock
.sisfb_patchlevel
= VER_LEVEL
;
1744 ivideo
->sisfb_infoblock
.chip_id
= ivideo
->chip_id
;
1745 ivideo
->sisfb_infoblock
.sisfb_pci_vendor
= ivideo
->chip_vendor
;
1746 ivideo
->sisfb_infoblock
.memory
= ivideo
->video_size
/ 1024;
1747 ivideo
->sisfb_infoblock
.heapstart
= ivideo
->heapstart
/ 1024;
1748 if(ivideo
->modechanged
) {
1749 ivideo
->sisfb_infoblock
.fbvidmode
= ivideo
->mode_no
;
1751 ivideo
->sisfb_infoblock
.fbvidmode
= ivideo
->modeprechange
;
1753 ivideo
->sisfb_infoblock
.sisfb_caps
= ivideo
->caps
;
1754 ivideo
->sisfb_infoblock
.sisfb_tqlen
= ivideo
->cmdQueueSize
/ 1024;
1755 ivideo
->sisfb_infoblock
.sisfb_pcibus
= ivideo
->pcibus
;
1756 ivideo
->sisfb_infoblock
.sisfb_pcislot
= ivideo
->pcislot
;
1757 ivideo
->sisfb_infoblock
.sisfb_pcifunc
= ivideo
->pcifunc
;
1758 ivideo
->sisfb_infoblock
.sisfb_lcdpdc
= ivideo
->detectedpdc
;
1759 ivideo
->sisfb_infoblock
.sisfb_lcdpdca
= ivideo
->detectedpdca
;
1760 ivideo
->sisfb_infoblock
.sisfb_lcda
= ivideo
->detectedlcda
;
1761 ivideo
->sisfb_infoblock
.sisfb_vbflags
= ivideo
->vbflags
;
1762 ivideo
->sisfb_infoblock
.sisfb_currentvbflags
= ivideo
->currentvbflags
;
1763 ivideo
->sisfb_infoblock
.sisfb_scalelcd
= ivideo
->SiS_Pr
.UsePanelScaler
;
1764 ivideo
->sisfb_infoblock
.sisfb_specialtiming
= ivideo
->SiS_Pr
.SiS_CustomT
;
1765 ivideo
->sisfb_infoblock
.sisfb_haveemi
= ivideo
->SiS_Pr
.HaveEMI
? 1 : 0;
1766 ivideo
->sisfb_infoblock
.sisfb_haveemilcd
= ivideo
->SiS_Pr
.HaveEMILCD
? 1 : 0;
1767 ivideo
->sisfb_infoblock
.sisfb_emi30
= ivideo
->SiS_Pr
.EMI_30
;
1768 ivideo
->sisfb_infoblock
.sisfb_emi31
= ivideo
->SiS_Pr
.EMI_31
;
1769 ivideo
->sisfb_infoblock
.sisfb_emi32
= ivideo
->SiS_Pr
.EMI_32
;
1770 ivideo
->sisfb_infoblock
.sisfb_emi33
= ivideo
->SiS_Pr
.EMI_33
;
1771 ivideo
->sisfb_infoblock
.sisfb_tvxpos
= (u16
)(ivideo
->tvxpos
+ 32);
1772 ivideo
->sisfb_infoblock
.sisfb_tvypos
= (u16
)(ivideo
->tvypos
+ 32);
1773 ivideo
->sisfb_infoblock
.sisfb_heapsize
= ivideo
->sisfb_heap_size
/ 1024;
1774 ivideo
->sisfb_infoblock
.sisfb_videooffset
= ivideo
->video_offset
;
1775 ivideo
->sisfb_infoblock
.sisfb_curfstn
= ivideo
->curFSTN
;
1776 ivideo
->sisfb_infoblock
.sisfb_curdstn
= ivideo
->curDSTN
;
1777 ivideo
->sisfb_infoblock
.sisfb_vbflags2
= ivideo
->vbflags2
;
1778 ivideo
->sisfb_infoblock
.sisfb_can_post
= ivideo
->sisfb_can_post
? 1 : 0;
1779 ivideo
->sisfb_infoblock
.sisfb_card_posted
= ivideo
->sisfb_card_posted
? 1 : 0;
1780 ivideo
->sisfb_infoblock
.sisfb_was_boot_device
= ivideo
->sisfb_was_boot_device
? 1 : 0;
1782 if(copy_to_user((void __user
*)arg
, &ivideo
->sisfb_infoblock
,
1783 sizeof(ivideo
->sisfb_infoblock
)))
1788 case SISFB_GET_VBRSTATUS_OLD
:
1789 if(ivideo
->warncount
++ < 10)
1791 "sisfb: Deprecated ioctl call received - update your application!\n");
1792 case SISFB_GET_VBRSTATUS
:
1793 if(sisfb_CheckVBRetrace(ivideo
))
1794 return put_user((u32
)1, argp
);
1796 return put_user((u32
)0, argp
);
1798 case SISFB_GET_AUTOMAXIMIZE_OLD
:
1799 if(ivideo
->warncount
++ < 10)
1801 "sisfb: Deprecated ioctl call received - update your application!\n");
1802 case SISFB_GET_AUTOMAXIMIZE
:
1803 if(ivideo
->sisfb_max
)
1804 return put_user((u32
)1, argp
);
1806 return put_user((u32
)0, argp
);
1808 case SISFB_SET_AUTOMAXIMIZE_OLD
:
1809 if(ivideo
->warncount
++ < 10)
1811 "sisfb: Deprecated ioctl call received - update your application!\n");
1812 case SISFB_SET_AUTOMAXIMIZE
:
1813 if(get_user(gpu32
, argp
))
1816 ivideo
->sisfb_max
= (gpu32
) ? 1 : 0;
1819 case SISFB_SET_TVPOSOFFSET
:
1820 if(get_user(gpu32
, argp
))
1823 sisfb_set_TVxposoffset(ivideo
, ((int)(gpu32
>> 16)) - 32);
1824 sisfb_set_TVyposoffset(ivideo
, ((int)(gpu32
& 0xffff)) - 32);
1827 case SISFB_GET_TVPOSOFFSET
:
1828 return put_user((u32
)(((ivideo
->tvxpos
+32)<<16)|((ivideo
->tvypos
+32)&0xffff)),
1832 if(copy_from_user(&ivideo
->sisfb_command
, (void __user
*)arg
,
1833 sizeof(struct sisfb_cmd
)))
1836 sisfb_handle_command(ivideo
, &ivideo
->sisfb_command
);
1838 if(copy_to_user((void __user
*)arg
, &ivideo
->sisfb_command
,
1839 sizeof(struct sisfb_cmd
)))
1844 case SISFB_SET_LOCK
:
1845 if(get_user(gpu32
, argp
))
1848 ivideo
->sisfblocked
= (gpu32
) ? 1 : 0;
1852 #ifdef SIS_NEW_CONFIG_COMPAT
1853 return -ENOIOCTLCMD
;
1862 sisfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
, struct fb_info
*info
)
1864 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1866 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
1868 strcpy(fix
->id
, ivideo
->myid
);
1870 fix
->smem_start
= ivideo
->video_base
+ ivideo
->video_offset
;
1871 fix
->smem_len
= ivideo
->sisfb_mem
;
1872 fix
->type
= FB_TYPE_PACKED_PIXELS
;
1874 fix
->visual
= (ivideo
->video_bpp
== 8) ? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_TRUECOLOR
;
1876 fix
->ypanstep
= (ivideo
->sisfb_ypan
) ? 1 : 0;
1878 fix
->line_length
= ivideo
->video_linelength
;
1879 fix
->mmio_start
= ivideo
->mmio_base
;
1880 fix
->mmio_len
= ivideo
->mmio_size
;
1881 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
1882 fix
->accel
= FB_ACCEL_SIS_GLAMOUR
;
1883 } else if((ivideo
->chip
== SIS_330
) ||
1884 (ivideo
->chip
== SIS_760
) ||
1885 (ivideo
->chip
== SIS_761
)) {
1886 fix
->accel
= FB_ACCEL_SIS_XABRE
;
1887 } else if(ivideo
->chip
== XGI_20
) {
1888 fix
->accel
= FB_ACCEL_XGI_VOLARI_Z
;
1889 } else if(ivideo
->chip
>= XGI_40
) {
1890 fix
->accel
= FB_ACCEL_XGI_VOLARI_V
;
1892 fix
->accel
= FB_ACCEL_SIS_GLAMOUR_2
;
1898 /* ---------------- fb_ops structures ----------------- */
1900 static struct fb_ops sisfb_ops
= {
1901 .owner
= THIS_MODULE
,
1902 .fb_open
= sisfb_open
,
1903 .fb_release
= sisfb_release
,
1904 .fb_check_var
= sisfb_check_var
,
1905 .fb_set_par
= sisfb_set_par
,
1906 .fb_setcolreg
= sisfb_setcolreg
,
1907 .fb_pan_display
= sisfb_pan_display
,
1908 .fb_blank
= sisfb_blank
,
1909 .fb_fillrect
= fbcon_sis_fillrect
,
1910 .fb_copyarea
= fbcon_sis_copyarea
,
1911 .fb_imageblit
= cfb_imageblit
,
1912 #ifdef CONFIG_FB_SOFT_CURSOR
1913 .fb_cursor
= soft_cursor
,
1915 .fb_sync
= fbcon_sis_sync
,
1916 #ifdef SIS_NEW_CONFIG_COMPAT
1917 .fb_compat_ioctl
= sisfb_ioctl
,
1919 .fb_ioctl
= sisfb_ioctl
1922 /* ---------------- Chip generation dependent routines ---------------- */
1924 static struct pci_dev
* __devinit
1925 sisfb_get_northbridge(int basechipid
)
1927 struct pci_dev
*pdev
= NULL
;
1928 int nbridgenum
, nbridgeidx
, i
;
1929 static const unsigned short nbridgeids
[] = {
1930 PCI_DEVICE_ID_SI_540
, /* for SiS 540 VGA */
1931 PCI_DEVICE_ID_SI_630
, /* for SiS 630/730 VGA */
1932 PCI_DEVICE_ID_SI_730
,
1933 PCI_DEVICE_ID_SI_550
, /* for SiS 550 VGA */
1934 PCI_DEVICE_ID_SI_650
, /* for SiS 650/651/740 VGA */
1935 PCI_DEVICE_ID_SI_651
,
1936 PCI_DEVICE_ID_SI_740
,
1937 PCI_DEVICE_ID_SI_661
, /* for SiS 661/741/660/760/761 VGA */
1938 PCI_DEVICE_ID_SI_741
,
1939 PCI_DEVICE_ID_SI_660
,
1940 PCI_DEVICE_ID_SI_760
,
1941 PCI_DEVICE_ID_SI_761
1944 switch(basechipid
) {
1945 #ifdef CONFIG_FB_SIS_300
1946 case SIS_540
: nbridgeidx
= 0; nbridgenum
= 1; break;
1947 case SIS_630
: nbridgeidx
= 1; nbridgenum
= 2; break;
1949 #ifdef CONFIG_FB_SIS_315
1950 case SIS_550
: nbridgeidx
= 3; nbridgenum
= 1; break;
1951 case SIS_650
: nbridgeidx
= 4; nbridgenum
= 3; break;
1952 case SIS_660
: nbridgeidx
= 7; nbridgenum
= 5; break;
1954 default: return NULL
;
1956 for(i
= 0; i
< nbridgenum
; i
++) {
1957 if((pdev
= pci_get_device(PCI_VENDOR_ID_SI
,
1958 nbridgeids
[nbridgeidx
+i
], NULL
)))
1964 static int __devinit
1965 sisfb_get_dram_size(struct sis_video_info
*ivideo
)
1967 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1971 ivideo
->video_size
= 0;
1972 ivideo
->UMAsize
= ivideo
->LFBsize
= 0;
1974 switch(ivideo
->chip
) {
1975 #ifdef CONFIG_FB_SIS_300
1977 inSISIDXREG(SISSR
, 0x14, reg
);
1978 ivideo
->video_size
= ((reg
& 0x3F) + 1) << 20;
1983 if(!ivideo
->nbridge
)
1985 pci_read_config_byte(ivideo
->nbridge
, 0x63, ®
);
1986 ivideo
->video_size
= 1 << (((reg
& 0x70) >> 4) + 21);
1989 #ifdef CONFIG_FB_SIS_315
1993 inSISIDXREG(SISSR
, 0x14, reg
);
1994 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
1995 switch((reg
>> 2) & 0x03) {
1998 ivideo
->video_size
<<= 1;
2001 ivideo
->video_size
+= (ivideo
->video_size
/2);
2005 inSISIDXREG(SISSR
, 0x14, reg
);
2006 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
2007 if(reg
& 0x0c) ivideo
->video_size
<<= 1;
2012 inSISIDXREG(SISSR
, 0x14, reg
);
2013 ivideo
->video_size
= (((reg
& 0x3f) + 1) << 2) << 20;
2017 inSISIDXREG(SISCR
, 0x79, reg
);
2018 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
2023 inSISIDXREG(SISCR
, 0x79, reg
);
2024 reg
= (reg
& 0xf0) >> 4;
2026 ivideo
->video_size
= (1 << reg
) << 20;
2027 ivideo
->UMAsize
= ivideo
->video_size
;
2029 inSISIDXREG(SISCR
, 0x78, reg
);
2033 ivideo
->LFBsize
= (32 << 20);
2035 ivideo
->LFBsize
= (64 << 20);
2037 ivideo
->video_size
+= ivideo
->LFBsize
;
2043 inSISIDXREG(SISSR
, 0x14, reg
);
2044 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
2045 if(ivideo
->chip
!= XGI_20
) {
2046 reg
= (reg
& 0x0c) >> 2;
2047 if(ivideo
->revision_id
== 2) {
2048 if(reg
& 0x01) reg
= 0x02;
2051 if(reg
== 0x02) ivideo
->video_size
<<= 1;
2052 else if(reg
== 0x03) ivideo
->video_size
<<= 2;
2062 /* -------------- video bridge device detection --------------- */
2064 static void __devinit
2065 sisfb_detect_VB_connect(struct sis_video_info
*ivideo
)
2069 /* No CRT2 on XGI Z7 */
2070 if(ivideo
->chip
== XGI_20
) {
2071 ivideo
->sisfb_crt1off
= 0;
2075 #ifdef CONFIG_FB_SIS_300
2076 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2077 inSISIDXREG(SISSR
, 0x17, temp
);
2078 if((temp
& 0x0F) && (ivideo
->chip
!= SIS_300
)) {
2079 /* PAL/NTSC is stored on SR16 on such machines */
2080 if(!(ivideo
->vbflags
& (TV_PAL
| TV_NTSC
| TV_PALM
| TV_PALN
))) {
2081 inSISIDXREG(SISSR
, 0x16, temp
);
2083 ivideo
->vbflags
|= TV_PAL
;
2085 ivideo
->vbflags
|= TV_NTSC
;
2091 inSISIDXREG(SISCR
, 0x32, cr32
);
2093 if(cr32
& SIS_CRT1
) {
2094 ivideo
->sisfb_crt1off
= 0;
2096 ivideo
->sisfb_crt1off
= (cr32
& 0xDF) ? 1 : 0;
2099 ivideo
->vbflags
&= ~(CRT2_TV
| CRT2_LCD
| CRT2_VGA
);
2101 if(cr32
& SIS_VB_TV
) ivideo
->vbflags
|= CRT2_TV
;
2102 if(cr32
& SIS_VB_LCD
) ivideo
->vbflags
|= CRT2_LCD
;
2103 if(cr32
& SIS_VB_CRT2
) ivideo
->vbflags
|= CRT2_VGA
;
2105 /* Check given parms for hardware compatibility.
2106 * (Cannot do this in the search_xx routines since we don't
2107 * know what hardware we are running on then)
2110 if(ivideo
->chip
!= SIS_550
) {
2111 ivideo
->sisfb_dstn
= ivideo
->sisfb_fstn
= 0;
2114 if(ivideo
->sisfb_tvplug
!= -1) {
2115 if( (ivideo
->sisvga_engine
!= SIS_315_VGA
) ||
2116 (!(ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) ) {
2117 if(ivideo
->sisfb_tvplug
& TV_YPBPR
) {
2118 ivideo
->sisfb_tvplug
= -1;
2119 printk(KERN_ERR
"sisfb: YPbPr not supported\n");
2123 if(ivideo
->sisfb_tvplug
!= -1) {
2124 if( (ivideo
->sisvga_engine
!= SIS_315_VGA
) ||
2125 (!(ivideo
->vbflags2
& VB2_SISHIVISIONBRIDGE
)) ) {
2126 if(ivideo
->sisfb_tvplug
& TV_HIVISION
) {
2127 ivideo
->sisfb_tvplug
= -1;
2128 printk(KERN_ERR
"sisfb: HiVision not supported\n");
2132 if(ivideo
->sisfb_tvstd
!= -1) {
2133 if( (!(ivideo
->vbflags2
& VB2_SISBRIDGE
)) &&
2134 (!((ivideo
->sisvga_engine
== SIS_315_VGA
) &&
2135 (ivideo
->vbflags2
& VB2_CHRONTEL
))) ) {
2136 if(ivideo
->sisfb_tvstd
& (TV_PALN
| TV_PALN
| TV_NTSCJ
)) {
2137 ivideo
->sisfb_tvstd
= -1;
2138 printk(KERN_ERR
"sisfb: PALM/PALN/NTSCJ not supported\n");
2143 /* Detect/set TV plug & type */
2144 if(ivideo
->sisfb_tvplug
!= -1) {
2145 ivideo
->vbflags
|= ivideo
->sisfb_tvplug
;
2147 if(cr32
& SIS_VB_YPBPR
) ivideo
->vbflags
|= (TV_YPBPR
|TV_YPBPR525I
); /* default: 480i */
2148 else if(cr32
& SIS_VB_HIVISION
) ivideo
->vbflags
|= TV_HIVISION
;
2149 else if(cr32
& SIS_VB_SCART
) ivideo
->vbflags
|= TV_SCART
;
2151 if(cr32
& SIS_VB_SVIDEO
) ivideo
->vbflags
|= TV_SVIDEO
;
2152 if(cr32
& SIS_VB_COMPOSITE
) ivideo
->vbflags
|= TV_AVIDEO
;
2156 if(!(ivideo
->vbflags
& (TV_YPBPR
| TV_HIVISION
))) {
2157 if(ivideo
->sisfb_tvstd
!= -1) {
2158 ivideo
->vbflags
&= ~(TV_NTSC
| TV_PAL
| TV_PALM
| TV_PALN
| TV_NTSCJ
);
2159 ivideo
->vbflags
|= ivideo
->sisfb_tvstd
;
2161 if(ivideo
->vbflags
& TV_SCART
) {
2162 ivideo
->vbflags
&= ~(TV_NTSC
| TV_PALM
| TV_PALN
| TV_NTSCJ
);
2163 ivideo
->vbflags
|= TV_PAL
;
2165 if(!(ivideo
->vbflags
& (TV_PAL
| TV_NTSC
| TV_PALM
| TV_PALN
| TV_NTSCJ
))) {
2166 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2167 inSISIDXREG(SISSR
, 0x38, temp
);
2168 if(temp
& 0x01) ivideo
->vbflags
|= TV_PAL
;
2169 else ivideo
->vbflags
|= TV_NTSC
;
2170 } else if((ivideo
->chip
<= SIS_315PRO
) || (ivideo
->chip
>= SIS_330
)) {
2171 inSISIDXREG(SISSR
, 0x38, temp
);
2172 if(temp
& 0x01) ivideo
->vbflags
|= TV_PAL
;
2173 else ivideo
->vbflags
|= TV_NTSC
;
2175 inSISIDXREG(SISCR
, 0x79, temp
);
2176 if(temp
& 0x20) ivideo
->vbflags
|= TV_PAL
;
2177 else ivideo
->vbflags
|= TV_NTSC
;
2182 /* Copy forceCRT1 option to CRT1off if option is given */
2183 if(ivideo
->sisfb_forcecrt1
!= -1) {
2184 ivideo
->sisfb_crt1off
= (ivideo
->sisfb_forcecrt1
) ? 0 : 1;
2188 /* ------------------ Sensing routines ------------------ */
2190 static bool __devinit
2191 sisfb_test_DDC1(struct sis_video_info
*ivideo
)
2196 old
= SiS_ReadDDC1Bit(&ivideo
->SiS_Pr
);
2198 if(old
!= SiS_ReadDDC1Bit(&ivideo
->SiS_Pr
)) break;
2200 return (count
!= -1);
2203 static void __devinit
2204 sisfb_sense_crt1(struct sis_video_info
*ivideo
)
2206 bool mustwait
= false;
2208 #ifdef CONFIG_FB_SIS_315
2214 inSISIDXREG(SISSR
,0x1F,sr1F
);
2215 orSISIDXREG(SISSR
,0x1F,0x04);
2216 andSISIDXREG(SISSR
,0x1F,0x3F);
2217 if(sr1F
& 0xc0) mustwait
= true;
2219 #ifdef CONFIG_FB_SIS_315
2220 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2221 inSISIDXREG(SISCR
,ivideo
->SiS_Pr
.SiS_MyCR63
,cr63
);
2223 andSISIDXREG(SISCR
,ivideo
->SiS_Pr
.SiS_MyCR63
,0xBF);
2227 inSISIDXREG(SISCR
,0x17,cr17
);
2230 orSISIDXREG(SISCR
,0x17,0x80);
2232 outSISIDXREG(SISSR
, 0x00, 0x01);
2233 outSISIDXREG(SISSR
, 0x00, 0x03);
2237 for(i
=0; i
< 10; i
++) sisfbwaitretracecrt1(ivideo
);
2240 #ifdef CONFIG_FB_SIS_315
2241 if(ivideo
->chip
>= SIS_330
) {
2242 andSISIDXREG(SISCR
,0x32,~0x20);
2243 if(ivideo
->chip
>= SIS_340
) {
2244 outSISIDXREG(SISCR
, 0x57, 0x4a);
2246 outSISIDXREG(SISCR
, 0x57, 0x5f);
2248 orSISIDXREG(SISCR
, 0x53, 0x02);
2249 while((inSISREG(SISINPSTAT
)) & 0x01) break;
2250 while(!((inSISREG(SISINPSTAT
)) & 0x01)) break;
2251 if((inSISREG(SISMISCW
)) & 0x10) temp
= 1;
2252 andSISIDXREG(SISCR
, 0x53, 0xfd);
2253 andSISIDXREG(SISCR
, 0x57, 0x00);
2257 if(temp
== 0xffff) {
2260 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
,
2261 ivideo
->sisvga_engine
, 0, 0, NULL
, ivideo
->vbflags2
);
2262 } while(((temp
== 0) || (temp
== 0xffff)) && i
--);
2264 if((temp
== 0) || (temp
== 0xffff)) {
2265 if(sisfb_test_DDC1(ivideo
)) temp
= 1;
2269 if((temp
) && (temp
!= 0xffff)) {
2270 orSISIDXREG(SISCR
,0x32,0x20);
2273 #ifdef CONFIG_FB_SIS_315
2274 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2275 setSISIDXREG(SISCR
,ivideo
->SiS_Pr
.SiS_MyCR63
,0xBF,cr63
);
2279 setSISIDXREG(SISCR
,0x17,0x7F,cr17
);
2281 outSISIDXREG(SISSR
,0x1F,sr1F
);
2284 /* Determine and detect attached devices on SiS30x */
2285 static void __devinit
2286 SiS_SenseLCD(struct sis_video_info
*ivideo
)
2288 unsigned char buffer
[256];
2289 unsigned short temp
, realcrtno
, i
;
2290 u8 reg
, cr37
= 0, paneltype
= 0;
2293 ivideo
->SiS_Pr
.PanelSelfDetected
= false;
2295 /* LCD detection only for TMDS bridges */
2296 if(!(ivideo
->vbflags2
& VB2_SISTMDSBRIDGE
))
2298 if(ivideo
->vbflags2
& VB2_30xBDH
)
2301 /* If LCD already set up by BIOS, skip it */
2302 inSISIDXREG(SISCR
, 0x32, reg
);
2307 if(ivideo
->SiS_Pr
.DDCPortMixup
)
2310 /* Check DDC capabilities */
2311 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
2312 realcrtno
, 0, &buffer
[0], ivideo
->vbflags2
);
2314 if((!temp
) || (temp
== 0xffff) || (!(temp
& 0x02)))
2318 i
= 3; /* Number of retrys */
2320 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
,
2321 ivideo
->sisvga_engine
, realcrtno
, 1,
2322 &buffer
[0], ivideo
->vbflags2
);
2323 } while((temp
) && i
--);
2328 /* No digital device */
2329 if(!(buffer
[0x14] & 0x80))
2332 /* First detailed timing preferred timing? */
2333 if(!(buffer
[0x18] & 0x02))
2336 xres
= buffer
[0x38] | ((buffer
[0x3a] & 0xf0) << 4);
2337 yres
= buffer
[0x3b] | ((buffer
[0x3d] & 0xf0) << 4);
2349 if((yres
== 1200) && (ivideo
->vbflags2
& VB2_30xC
))
2360 if((buffer
[0x47] & 0x18) == 0x18)
2361 cr37
|= ((((buffer
[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2365 outSISIDXREG(SISCR
, 0x36, paneltype
);
2367 setSISIDXREG(SISCR
, 0x37, 0x0c, cr37
);
2368 orSISIDXREG(SISCR
, 0x32, 0x08);
2370 ivideo
->SiS_Pr
.PanelSelfDetected
= true;
2373 static int __devinit
2374 SISDoSense(struct sis_video_info
*ivideo
, u16 type
, u16 test
)
2376 int temp
, mytest
, result
, i
, j
;
2378 for(j
= 0; j
< 10; j
++) {
2380 for(i
= 0; i
< 3; i
++) {
2382 outSISIDXREG(SISPART4
,0x11,(type
& 0x00ff));
2383 temp
= (type
>> 8) | (mytest
& 0x00ff);
2384 setSISIDXREG(SISPART4
,0x10,0xe0,temp
);
2385 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x1500);
2388 inSISIDXREG(SISPART4
,0x03,temp
);
2391 if(temp
== mytest
) result
++;
2393 outSISIDXREG(SISPART4
,0x11,0x00);
2394 andSISIDXREG(SISPART4
,0x10,0xe0);
2395 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x1000);
2398 if((result
== 0) || (result
>= 2)) break;
2403 static void __devinit
2404 SiS_Sense30x(struct sis_video_info
*ivideo
)
2406 u8 backupP4_0d
,backupP2_00
,backupP2_4d
,backupSR_1e
,biosflag
=0;
2407 u16 svhs
=0, svhs_c
=0;
2408 u16 cvbs
=0, cvbs_c
=0;
2409 u16 vga2
=0, vga2_c
=0;
2411 char stdstr
[] = "sisfb: Detected";
2412 char tvstr
[] = "TV connected to";
2414 if(ivideo
->vbflags2
& VB2_301
) {
2415 svhs
= 0x00b9; cvbs
= 0x00b3; vga2
= 0x00d1;
2416 inSISIDXREG(SISPART4
,0x01,myflag
);
2418 svhs
= 0x00dd; cvbs
= 0x00ee; vga2
= 0x00fd;
2420 } else if(ivideo
->vbflags2
& (VB2_301B
| VB2_302B
)) {
2421 svhs
= 0x016b; cvbs
= 0x0174; vga2
= 0x0190;
2422 } else if(ivideo
->vbflags2
& (VB2_301LV
| VB2_302LV
)) {
2423 svhs
= 0x0200; cvbs
= 0x0100;
2424 } else if(ivideo
->vbflags2
& (VB2_301C
| VB2_302ELV
| VB2_307T
| VB2_307LV
)) {
2425 svhs
= 0x016b; cvbs
= 0x0110; vga2
= 0x0190;
2429 vga2_c
= 0x0e08; svhs_c
= 0x0404; cvbs_c
= 0x0804;
2430 if(ivideo
->vbflags
& (VB2_301LV
|VB2_302LV
|VB2_302ELV
|VB2_307LV
)) {
2431 svhs_c
= 0x0408; cvbs_c
= 0x0808;
2435 if(ivideo
->haveXGIROM
) {
2436 biosflag
= ivideo
->bios_abase
[0x58] & 0x03;
2437 } else if(ivideo
->newrom
) {
2438 if(ivideo
->bios_abase
[0x5d] & 0x04) biosflag
|= 0x01;
2439 } else if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2440 if(ivideo
->bios_abase
) {
2441 biosflag
= ivideo
->bios_abase
[0xfe] & 0x03;
2445 if(ivideo
->chip
== SIS_300
) {
2446 inSISIDXREG(SISSR
,0x3b,myflag
);
2447 if(!(myflag
& 0x01)) vga2
= vga2_c
= 0;
2450 if(!(ivideo
->vbflags2
& VB2_SISVGA2BRIDGE
)) {
2454 inSISIDXREG(SISSR
,0x1e,backupSR_1e
);
2455 orSISIDXREG(SISSR
,0x1e,0x20);
2457 inSISIDXREG(SISPART4
,0x0d,backupP4_0d
);
2458 if(ivideo
->vbflags2
& VB2_30xC
) {
2459 setSISIDXREG(SISPART4
,0x0d,~0x07,0x01);
2461 orSISIDXREG(SISPART4
,0x0d,0x04);
2463 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x2000);
2465 inSISIDXREG(SISPART2
,0x00,backupP2_00
);
2466 outSISIDXREG(SISPART2
,0x00,((backupP2_00
| 0x1c) & 0xfc));
2468 inSISIDXREG(SISPART2
,0x4d,backupP2_4d
);
2469 if(ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
) {
2470 outSISIDXREG(SISPART2
,0x4d,(backupP2_4d
& ~0x10));
2473 if(!(ivideo
->vbflags2
& VB2_30xCLV
)) {
2474 SISDoSense(ivideo
, 0, 0);
2477 andSISIDXREG(SISCR
, 0x32, ~0x14);
2479 if(vga2_c
|| vga2
) {
2480 if(SISDoSense(ivideo
, vga2
, vga2_c
)) {
2481 if(biosflag
& 0x01) {
2482 printk(KERN_INFO
"%s %s SCART output\n", stdstr
, tvstr
);
2483 orSISIDXREG(SISCR
, 0x32, 0x04);
2485 printk(KERN_INFO
"%s secondary VGA connection\n", stdstr
);
2486 orSISIDXREG(SISCR
, 0x32, 0x10);
2491 andSISIDXREG(SISCR
, 0x32, 0x3f);
2493 if(ivideo
->vbflags2
& VB2_30xCLV
) {
2494 orSISIDXREG(SISPART4
,0x0d,0x04);
2497 if((ivideo
->sisvga_engine
== SIS_315_VGA
) && (ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) {
2498 outSISIDXREG(SISPART2
,0x4d,(backupP2_4d
| 0x10));
2499 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x2000);
2500 if((result
= SISDoSense(ivideo
, svhs
, 0x0604))) {
2501 if((result
= SISDoSense(ivideo
, cvbs
, 0x0804))) {
2502 printk(KERN_INFO
"%s %s YPbPr component output\n", stdstr
, tvstr
);
2503 orSISIDXREG(SISCR
,0x32,0x80);
2506 outSISIDXREG(SISPART2
,0x4d,backupP2_4d
);
2509 andSISIDXREG(SISCR
, 0x32, ~0x03);
2511 if(!(ivideo
->vbflags
& TV_YPBPR
)) {
2512 if((result
= SISDoSense(ivideo
, svhs
, svhs_c
))) {
2513 printk(KERN_INFO
"%s %s SVIDEO output\n", stdstr
, tvstr
);
2514 orSISIDXREG(SISCR
, 0x32, 0x02);
2516 if((biosflag
& 0x02) || (!result
)) {
2517 if(SISDoSense(ivideo
, cvbs
, cvbs_c
)) {
2518 printk(KERN_INFO
"%s %s COMPOSITE output\n", stdstr
, tvstr
);
2519 orSISIDXREG(SISCR
, 0x32, 0x01);
2524 SISDoSense(ivideo
, 0, 0);
2526 outSISIDXREG(SISPART2
,0x00,backupP2_00
);
2527 outSISIDXREG(SISPART4
,0x0d,backupP4_0d
);
2528 outSISIDXREG(SISSR
,0x1e,backupSR_1e
);
2530 if(ivideo
->vbflags2
& VB2_30xCLV
) {
2531 inSISIDXREG(SISPART2
,0x00,biosflag
);
2532 if(biosflag
& 0x20) {
2533 for(myflag
= 2; myflag
> 0; myflag
--) {
2535 outSISIDXREG(SISPART2
,0x00,biosflag
);
2540 outSISIDXREG(SISPART2
,0x00,backupP2_00
);
2543 /* Determine and detect attached TV's on Chrontel */
2544 static void __devinit
2545 SiS_SenseCh(struct sis_video_info
*ivideo
)
2547 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2549 char stdstr
[] = "sisfb: Chrontel: Detected TV connected to";
2551 #ifdef CONFIG_FB_SIS_300
2552 unsigned char test
[3];
2556 if(ivideo
->chip
< SIS_315H
) {
2558 #ifdef CONFIG_FB_SIS_300
2559 ivideo
->SiS_Pr
.SiS_IF_DEF_CH70xx
= 1; /* Chrontel 700x */
2560 SiS_SetChrontelGPIO(&ivideo
->SiS_Pr
, 0x9c); /* Set general purpose IO for Chrontel communication */
2561 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 1000);
2562 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x25);
2563 /* See Chrontel TB31 for explanation */
2564 temp2
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0e);
2565 if(((temp2
& 0x07) == 0x01) || (temp2
& 0x04)) {
2566 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0e, 0x0b);
2567 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 300);
2569 temp2
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x25);
2570 if(temp2
!= temp1
) temp1
= temp2
;
2572 if((temp1
>= 0x22) && (temp1
<= 0x50)) {
2573 /* Read power status */
2574 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0e);
2575 if((temp1
& 0x03) != 0x03) {
2576 /* Power all outputs */
2577 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0e,0x0b);
2578 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 300);
2580 /* Sense connected TV devices */
2581 for(i
= 0; i
< 3; i
++) {
2582 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x10, 0x01);
2583 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2584 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x10, 0x00);
2585 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2586 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x10);
2587 if(!(temp1
& 0x08)) test
[i
] = 0x02;
2588 else if(!(temp1
& 0x02)) test
[i
] = 0x01;
2590 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2593 if(test
[0] == test
[1]) temp1
= test
[0];
2594 else if(test
[0] == test
[2]) temp1
= test
[0];
2595 else if(test
[1] == test
[2]) temp1
= test
[1];
2598 "sisfb: TV detection unreliable - test results varied\n");
2602 printk(KERN_INFO
"%s SVIDEO output\n", stdstr
);
2603 ivideo
->vbflags
|= TV_SVIDEO
;
2604 orSISIDXREG(SISCR
, 0x32, 0x02);
2605 andSISIDXREG(SISCR
, 0x32, ~0x05);
2606 } else if (temp1
== 0x01) {
2607 printk(KERN_INFO
"%s CVBS output\n", stdstr
);
2608 ivideo
->vbflags
|= TV_AVIDEO
;
2609 orSISIDXREG(SISCR
, 0x32, 0x01);
2610 andSISIDXREG(SISCR
, 0x32, ~0x06);
2612 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x0e, 0x01, 0xF8);
2613 andSISIDXREG(SISCR
, 0x32, ~0x07);
2615 } else if(temp1
== 0) {
2616 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x0e, 0x01, 0xF8);
2617 andSISIDXREG(SISCR
, 0x32, ~0x07);
2619 /* Set general purpose IO for Chrontel communication */
2620 SiS_SetChrontelGPIO(&ivideo
->SiS_Pr
, 0x00);
2625 #ifdef CONFIG_FB_SIS_315
2626 ivideo
->SiS_Pr
.SiS_IF_DEF_CH70xx
= 2; /* Chrontel 7019 */
2627 temp1
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x49);
2628 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x49, 0x20);
2629 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2630 temp2
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x20);
2632 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x20, temp2
);
2633 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2635 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x20, temp2
);
2636 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2637 temp2
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x20);
2638 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x49, temp1
);
2640 if(temp2
& 0x02) temp1
|= 0x01;
2641 if(temp2
& 0x10) temp1
|= 0x01;
2642 if(temp2
& 0x04) temp1
|= 0x02;
2643 if( (temp1
& 0x01) && (temp1
& 0x02) ) temp1
= 0x04;
2646 printk(KERN_INFO
"%s CVBS output\n", stdstr
);
2647 ivideo
->vbflags
|= TV_AVIDEO
;
2648 orSISIDXREG(SISCR
, 0x32, 0x01);
2649 andSISIDXREG(SISCR
, 0x32, ~0x06);
2652 printk(KERN_INFO
"%s SVIDEO output\n", stdstr
);
2653 ivideo
->vbflags
|= TV_SVIDEO
;
2654 orSISIDXREG(SISCR
, 0x32, 0x02);
2655 andSISIDXREG(SISCR
, 0x32, ~0x05);
2658 printk(KERN_INFO
"%s SCART output\n", stdstr
);
2659 orSISIDXREG(SISCR
, 0x32, 0x04);
2660 andSISIDXREG(SISCR
, 0x32, ~0x03);
2663 andSISIDXREG(SISCR
, 0x32, ~0x07);
2669 static void __devinit
2670 sisfb_get_VB_type(struct sis_video_info
*ivideo
)
2672 char stdstr
[] = "sisfb: Detected";
2673 char bridgestr
[] = "video bridge";
2677 /* No CRT2 on XGI Z7 */
2678 if(ivideo
->chip
== XGI_20
)
2681 inSISIDXREG(SISPART4
, 0x00, vb_chipid
);
2684 inSISIDXREG(SISPART4
, 0x01, reg
);
2686 ivideo
->vbflags
|= VB_301
; /* Deprecated */
2687 ivideo
->vbflags2
|= VB2_301
;
2688 printk(KERN_INFO
"%s SiS301 %s\n", stdstr
, bridgestr
);
2689 } else if(reg
< 0xc0) {
2690 ivideo
->vbflags
|= VB_301B
; /* Deprecated */
2691 ivideo
->vbflags2
|= VB2_301B
;
2692 inSISIDXREG(SISPART4
,0x23,reg
);
2694 ivideo
->vbflags
|= VB_30xBDH
; /* Deprecated */
2695 ivideo
->vbflags2
|= VB2_30xBDH
;
2696 printk(KERN_INFO
"%s SiS301B-DH %s\n", stdstr
, bridgestr
);
2698 printk(KERN_INFO
"%s SiS301B %s\n", stdstr
, bridgestr
);
2700 } else if(reg
< 0xd0) {
2701 ivideo
->vbflags
|= VB_301C
; /* Deprecated */
2702 ivideo
->vbflags2
|= VB2_301C
;
2703 printk(KERN_INFO
"%s SiS301C %s\n", stdstr
, bridgestr
);
2704 } else if(reg
< 0xe0) {
2705 ivideo
->vbflags
|= VB_301LV
; /* Deprecated */
2706 ivideo
->vbflags2
|= VB2_301LV
;
2707 printk(KERN_INFO
"%s SiS301LV %s\n", stdstr
, bridgestr
);
2708 } else if(reg
<= 0xe1) {
2709 inSISIDXREG(SISPART4
,0x39,reg
);
2711 ivideo
->vbflags
|= VB_302LV
; /* Deprecated */
2712 ivideo
->vbflags2
|= VB2_302LV
;
2713 printk(KERN_INFO
"%s SiS302LV %s\n", stdstr
, bridgestr
);
2715 ivideo
->vbflags
|= VB_301C
; /* Deprecated */
2716 ivideo
->vbflags2
|= VB2_301C
;
2717 printk(KERN_INFO
"%s SiS301C(P4) %s\n", stdstr
, bridgestr
);
2719 ivideo
->vbflags
|= VB_302ELV
; /* Deprecated */
2720 ivideo
->vbflags2
|= VB2_302ELV
;
2721 printk(KERN_INFO
"%s SiS302ELV %s\n", stdstr
, bridgestr
);
2727 ivideo
->vbflags
|= VB_302B
; /* Deprecated */
2728 ivideo
->vbflags2
|= VB2_302B
;
2729 printk(KERN_INFO
"%s SiS302B %s\n", stdstr
, bridgestr
);
2733 if((!(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
)) && (ivideo
->chip
!= SIS_300
)) {
2734 inSISIDXREG(SISCR
, 0x37, reg
);
2735 reg
&= SIS_EXTERNAL_CHIP_MASK
;
2737 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2738 #ifdef CONFIG_FB_SIS_300
2740 case SIS_EXTERNAL_CHIP_LVDS
:
2741 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2742 ivideo
->vbflags2
|= VB2_LVDS
;
2744 case SIS_EXTERNAL_CHIP_TRUMPION
:
2745 ivideo
->vbflags
|= (VB_LVDS
| VB_TRUMPION
); /* Deprecated */
2746 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_TRUMPION
);
2748 case SIS_EXTERNAL_CHIP_CHRONTEL
:
2749 ivideo
->vbflags
|= VB_CHRONTEL
; /* Deprecated */
2750 ivideo
->vbflags2
|= VB2_CHRONTEL
;
2752 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL
:
2753 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2754 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2757 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 1;
2759 } else if(ivideo
->chip
< SIS_661
) {
2760 #ifdef CONFIG_FB_SIS_315
2762 case SIS310_EXTERNAL_CHIP_LVDS
:
2763 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2764 ivideo
->vbflags2
|= VB2_LVDS
;
2766 case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL
:
2767 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2768 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2771 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 2;
2773 } else if(ivideo
->chip
>= SIS_661
) {
2774 #ifdef CONFIG_FB_SIS_315
2775 inSISIDXREG(SISCR
, 0x38, reg
);
2779 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2780 ivideo
->vbflags2
|= VB2_LVDS
;
2783 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2784 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2787 ivideo
->vbflags
|= (VB_LVDS
| VB_CONEXANT
); /* Deprecated */
2788 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CONEXANT
);
2791 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 2;
2794 if(ivideo
->vbflags2
& VB2_LVDS
) {
2795 printk(KERN_INFO
"%s LVDS transmitter\n", stdstr
);
2797 if((ivideo
->sisvga_engine
== SIS_300_VGA
) && (ivideo
->vbflags2
& VB2_TRUMPION
)) {
2798 printk(KERN_INFO
"%s Trumpion Zurac LCD scaler\n", stdstr
);
2800 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
2801 printk(KERN_INFO
"%s Chrontel TV encoder\n", stdstr
);
2803 if((ivideo
->chip
>= SIS_661
) && (ivideo
->vbflags2
& VB2_CONEXANT
)) {
2804 printk(KERN_INFO
"%s Conexant external device\n", stdstr
);
2808 if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
2809 SiS_SenseLCD(ivideo
);
2810 SiS_Sense30x(ivideo
);
2811 } else if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
2812 SiS_SenseCh(ivideo
);
2816 /* ---------- Engine initialization routines ------------ */
2819 sisfb_engine_init(struct sis_video_info
*ivideo
)
2822 /* Initialize command queue (we use MMIO only) */
2824 /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
2826 ivideo
->caps
&= ~(TURBO_QUEUE_CAP
|
2827 MMIO_CMD_QUEUE_CAP
|
2831 #ifdef CONFIG_FB_SIS_300
2832 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2836 tqueue_pos
= (ivideo
->video_size
- ivideo
->cmdQueueSize
) / (64 * 1024);
2838 inSISIDXREG(SISSR
, IND_SIS_TURBOQUEUE_SET
, tq_state
);
2841 tq_state
|= (u8
)(tqueue_pos
>> 8);
2842 outSISIDXREG(SISSR
, IND_SIS_TURBOQUEUE_SET
, tq_state
);
2844 outSISIDXREG(SISSR
, IND_SIS_TURBOQUEUE_ADR
, (u8
)(tqueue_pos
& 0xff));
2846 ivideo
->caps
|= TURBO_QUEUE_CAP
;
2850 #ifdef CONFIG_FB_SIS_315
2851 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2852 u32 tempq
= 0, templ
;
2855 if(ivideo
->chip
== XGI_20
) {
2856 switch(ivideo
->cmdQueueSize
) {
2858 temp
= SIS_CMD_QUEUE_SIZE_Z7_64k
;
2862 temp
= SIS_CMD_QUEUE_SIZE_Z7_128k
;
2865 switch(ivideo
->cmdQueueSize
) {
2866 case (4 * 1024 * 1024):
2867 temp
= SIS_CMD_QUEUE_SIZE_4M
;
2869 case (2 * 1024 * 1024):
2870 temp
= SIS_CMD_QUEUE_SIZE_2M
;
2872 case (1 * 1024 * 1024):
2873 temp
= SIS_CMD_QUEUE_SIZE_1M
;
2877 temp
= SIS_CMD_QUEUE_SIZE_512k
;
2881 outSISIDXREG(SISSR
, IND_SIS_CMDQUEUE_THRESHOLD
, COMMAND_QUEUE_THRESHOLD
);
2882 outSISIDXREG(SISSR
, IND_SIS_CMDQUEUE_SET
, SIS_CMD_QUEUE_RESET
);
2884 if((ivideo
->chip
>= XGI_40
) && ivideo
->modechanged
) {
2885 /* Must disable dual pipe on XGI_40. Can't do
2886 * this in MMIO mode, because it requires
2887 * setting/clearing a bit in the MMIO fire trigger
2890 if(!((templ
= MMIO_IN32(ivideo
->mmio_vbase
, 0x8240)) & (1 << 10))) {
2892 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, 0);
2894 outSISIDXREG(SISSR
, IND_SIS_CMDQUEUE_SET
, (temp
| SIS_VRAM_CMDQUEUE_ENABLE
));
2896 tempq
= MMIO_IN32(ivideo
->mmio_vbase
, Q_READ_PTR
);
2897 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, tempq
);
2899 tempq
= (u32
)(ivideo
->video_size
- ivideo
->cmdQueueSize
);
2900 MMIO_OUT32(ivideo
->mmio_vbase
, Q_BASE_ADDR
, tempq
);
2902 writel(0x16800000 + 0x8240, ivideo
->video_vbase
+ tempq
);
2903 writel(templ
| (1 << 10), ivideo
->video_vbase
+ tempq
+ 4);
2904 writel(0x168F0000, ivideo
->video_vbase
+ tempq
+ 8);
2905 writel(0x168F0000, ivideo
->video_vbase
+ tempq
+ 12);
2907 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, (tempq
+ 16));
2909 sisfb_syncaccel(ivideo
);
2911 outSISIDXREG(SISSR
, IND_SIS_CMDQUEUE_SET
, SIS_CMD_QUEUE_RESET
);
2916 tempq
= MMIO_IN32(ivideo
->mmio_vbase
, MMIO_QUEUE_READPORT
);
2917 MMIO_OUT32(ivideo
->mmio_vbase
, MMIO_QUEUE_WRITEPORT
, tempq
);
2919 temp
|= (SIS_MMIO_CMD_ENABLE
| SIS_CMD_AUTO_CORR
);
2920 outSISIDXREG(SISSR
, IND_SIS_CMDQUEUE_SET
, temp
);
2922 tempq
= (u32
)(ivideo
->video_size
- ivideo
->cmdQueueSize
);
2923 MMIO_OUT32(ivideo
->mmio_vbase
, MMIO_QUEUE_PHYBASE
, tempq
);
2925 ivideo
->caps
|= MMIO_CMD_QUEUE_CAP
;
2929 ivideo
->engineok
= 1;
2932 static void __devinit
2933 sisfb_detect_lcd_type(struct sis_video_info
*ivideo
)
2938 inSISIDXREG(SISCR
, 0x36, reg
);
2940 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2941 ivideo
->CRT2LCDType
= sis300paneltype
[reg
];
2942 } else if(ivideo
->chip
>= SIS_661
) {
2943 ivideo
->CRT2LCDType
= sis661paneltype
[reg
];
2945 ivideo
->CRT2LCDType
= sis310paneltype
[reg
];
2946 if((ivideo
->chip
== SIS_550
) && (sisfb_fstn
)) {
2947 if((ivideo
->CRT2LCDType
!= LCD_320x240_2
) &&
2948 (ivideo
->CRT2LCDType
!= LCD_320x240_3
)) {
2949 ivideo
->CRT2LCDType
= LCD_320x240
;
2954 if(ivideo
->CRT2LCDType
== LCD_UNKNOWN
) {
2955 /* For broken BIOSes: Assume 1024x768, RGB18 */
2956 ivideo
->CRT2LCDType
= LCD_1024x768
;
2957 setSISIDXREG(SISCR
,0x36,0xf0,0x02);
2958 setSISIDXREG(SISCR
,0x37,0xee,0x01);
2959 printk(KERN_DEBUG
"sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg
);
2962 for(i
= 0; i
< SIS_LCD_NUMBER
; i
++) {
2963 if(ivideo
->CRT2LCDType
== sis_lcd_data
[i
].lcdtype
) {
2964 ivideo
->lcdxres
= sis_lcd_data
[i
].xres
;
2965 ivideo
->lcdyres
= sis_lcd_data
[i
].yres
;
2966 ivideo
->lcddefmodeidx
= sis_lcd_data
[i
].default_mode_idx
;
2971 #ifdef CONFIG_FB_SIS_300
2972 if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_BARCO1366
) {
2973 ivideo
->lcdxres
= 1360; ivideo
->lcdyres
= 1024;
2974 ivideo
->lcddefmodeidx
= DEFAULT_MODE_1360
;
2975 } else if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_PANEL848
) {
2976 ivideo
->lcdxres
= 848; ivideo
->lcdyres
= 480;
2977 ivideo
->lcddefmodeidx
= DEFAULT_MODE_848
;
2978 } else if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_PANEL856
) {
2979 ivideo
->lcdxres
= 856; ivideo
->lcdyres
= 480;
2980 ivideo
->lcddefmodeidx
= DEFAULT_MODE_856
;
2984 printk(KERN_DEBUG
"sisfb: Detected %dx%d flat panel\n",
2985 ivideo
->lcdxres
, ivideo
->lcdyres
);
2988 static void __devinit
2989 sisfb_save_pdc_emi(struct sis_video_info
*ivideo
)
2991 #ifdef CONFIG_FB_SIS_300
2992 /* Save the current PanelDelayCompensation if the LCD is currently used */
2993 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2994 if(ivideo
->vbflags2
& (VB2_LVDS
| VB2_30xBDH
)) {
2996 inSISIDXREG(SISCR
,0x30,tmp
);
2998 /* Currently on LCD? If yes, read current pdc */
2999 inSISIDXREG(SISPART1
,0x13,ivideo
->detectedpdc
);
3000 ivideo
->detectedpdc
&= 0x3c;
3001 if(ivideo
->SiS_Pr
.PDC
== -1) {
3002 /* Let option override detection */
3003 ivideo
->SiS_Pr
.PDC
= ivideo
->detectedpdc
;
3005 printk(KERN_INFO
"sisfb: Detected LCD PDC 0x%02x\n",
3006 ivideo
->detectedpdc
);
3008 if((ivideo
->SiS_Pr
.PDC
!= -1) &&
3009 (ivideo
->SiS_Pr
.PDC
!= ivideo
->detectedpdc
)) {
3010 printk(KERN_INFO
"sisfb: Using LCD PDC 0x%02x\n",
3011 ivideo
->SiS_Pr
.PDC
);
3017 #ifdef CONFIG_FB_SIS_315
3018 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3020 /* Try to find about LCDA */
3021 if(ivideo
->vbflags2
& VB2_SISLCDABRIDGE
) {
3023 inSISIDXREG(SISPART1
,0x13,tmp
);
3025 ivideo
->SiS_Pr
.SiS_UseLCDA
= true;
3026 ivideo
->detectedlcda
= 0x03;
3031 if(ivideo
->vbflags2
& VB2_SISLVDSBRIDGE
) {
3033 inSISIDXREG(SISCR
,0x30,tmp
);
3034 if((tmp
& 0x20) || (ivideo
->detectedlcda
!= 0xff)) {
3035 /* Currently on LCD? If yes, read current pdc */
3037 inSISIDXREG(SISPART1
,0x2D,pdc
);
3038 ivideo
->detectedpdc
= (pdc
& 0x0f) << 1;
3039 ivideo
->detectedpdca
= (pdc
& 0xf0) >> 3;
3040 inSISIDXREG(SISPART1
,0x35,pdc
);
3041 ivideo
->detectedpdc
|= ((pdc
>> 7) & 0x01);
3042 inSISIDXREG(SISPART1
,0x20,pdc
);
3043 ivideo
->detectedpdca
|= ((pdc
>> 6) & 0x01);
3044 if(ivideo
->newrom
) {
3045 /* New ROM invalidates other PDC resp. */
3046 if(ivideo
->detectedlcda
!= 0xff) {
3047 ivideo
->detectedpdc
= 0xff;
3049 ivideo
->detectedpdca
= 0xff;
3052 if(ivideo
->SiS_Pr
.PDC
== -1) {
3053 if(ivideo
->detectedpdc
!= 0xff) {
3054 ivideo
->SiS_Pr
.PDC
= ivideo
->detectedpdc
;
3057 if(ivideo
->SiS_Pr
.PDCA
== -1) {
3058 if(ivideo
->detectedpdca
!= 0xff) {
3059 ivideo
->SiS_Pr
.PDCA
= ivideo
->detectedpdca
;
3062 if(ivideo
->detectedpdc
!= 0xff) {
3064 "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3065 ivideo
->detectedpdc
);
3067 if(ivideo
->detectedpdca
!= 0xff) {
3069 "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3070 ivideo
->detectedpdca
);
3075 if(ivideo
->vbflags2
& VB2_SISEMIBRIDGE
) {
3076 inSISIDXREG(SISPART4
,0x30,ivideo
->SiS_Pr
.EMI_30
);
3077 inSISIDXREG(SISPART4
,0x31,ivideo
->SiS_Pr
.EMI_31
);
3078 inSISIDXREG(SISPART4
,0x32,ivideo
->SiS_Pr
.EMI_32
);
3079 inSISIDXREG(SISPART4
,0x33,ivideo
->SiS_Pr
.EMI_33
);
3080 ivideo
->SiS_Pr
.HaveEMI
= true;
3081 if((tmp
& 0x20) || (ivideo
->detectedlcda
!= 0xff)) {
3082 ivideo
->SiS_Pr
.HaveEMILCD
= true;
3087 /* Let user override detected PDCs (all bridges) */
3088 if(ivideo
->vbflags2
& VB2_30xBLV
) {
3089 if((ivideo
->SiS_Pr
.PDC
!= -1) &&
3090 (ivideo
->SiS_Pr
.PDC
!= ivideo
->detectedpdc
)) {
3091 printk(KERN_INFO
"sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3092 ivideo
->SiS_Pr
.PDC
);
3094 if((ivideo
->SiS_Pr
.PDCA
!= -1) &&
3095 (ivideo
->SiS_Pr
.PDCA
!= ivideo
->detectedpdca
)) {
3096 printk(KERN_INFO
"sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3097 ivideo
->SiS_Pr
.PDCA
);
3105 /* -------------------- Memory manager routines ---------------------- */
3107 static u32 __devinit
3108 sisfb_getheapstart(struct sis_video_info
*ivideo
)
3110 u32 ret
= ivideo
->sisfb_parm_mem
* 1024;
3111 u32 maxoffs
= ivideo
->video_size
- ivideo
->hwcursor_size
- ivideo
->cmdQueueSize
;
3114 /* Calculate heap start = end of memory for console
3116 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3117 * C = console, D = heap, H = HWCursor, Q = cmd-queue
3119 * On 76x in UMA+LFB mode, the layout is as follows:
3120 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3121 * where the heap is the entire UMA area, eventually
3122 * into the LFB area if the given mem parameter is
3123 * higher than the size of the UMA memory.
3125 * Basically given by "mem" parameter
3127 * maximum = videosize - cmd_queue - hwcursor
3128 * (results in a heap of size 0)
3129 * default = SiS 300: depends on videosize
3130 * SiS 315/330/340/XGI: 32k below max
3133 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3134 if(ivideo
->video_size
> 0x1000000) {
3136 } else if(ivideo
->video_size
> 0x800000) {
3141 } else if(ivideo
->UMAsize
&& ivideo
->LFBsize
) {
3144 def
= maxoffs
- 0x8000;
3147 /* Use default for secondary card for now (FIXME) */
3148 if((!ret
) || (ret
> maxoffs
) || (ivideo
->cardnumber
!= 0))
3154 static u32 __devinit
3155 sisfb_getheapsize(struct sis_video_info
*ivideo
)
3157 u32 max
= ivideo
->video_size
- ivideo
->hwcursor_size
- ivideo
->cmdQueueSize
;
3160 if(ivideo
->UMAsize
&& ivideo
->LFBsize
) {
3161 if( (!ivideo
->sisfb_parm_mem
) ||
3162 ((ivideo
->sisfb_parm_mem
* 1024) > max
) ||
3163 ((max
- (ivideo
->sisfb_parm_mem
* 1024)) < ivideo
->UMAsize
) ) {
3164 ret
= ivideo
->UMAsize
;
3165 max
-= ivideo
->UMAsize
;
3167 ret
= max
- (ivideo
->sisfb_parm_mem
* 1024);
3168 max
= ivideo
->sisfb_parm_mem
* 1024;
3170 ivideo
->video_offset
= ret
;
3171 ivideo
->sisfb_mem
= max
;
3173 ret
= max
- ivideo
->heapstart
;
3174 ivideo
->sisfb_mem
= ivideo
->heapstart
;
3180 static int __devinit
3181 sisfb_heap_init(struct sis_video_info
*ivideo
)
3185 ivideo
->video_offset
= 0;
3186 if(ivideo
->sisfb_parm_mem
) {
3187 if( (ivideo
->sisfb_parm_mem
< (2 * 1024 * 1024)) ||
3188 (ivideo
->sisfb_parm_mem
> ivideo
->video_size
) ) {
3189 ivideo
->sisfb_parm_mem
= 0;
3193 ivideo
->heapstart
= sisfb_getheapstart(ivideo
);
3194 ivideo
->sisfb_heap_size
= sisfb_getheapsize(ivideo
);
3196 ivideo
->sisfb_heap_start
= ivideo
->video_vbase
+ ivideo
->heapstart
;
3197 ivideo
->sisfb_heap_end
= ivideo
->sisfb_heap_start
+ ivideo
->sisfb_heap_size
;
3199 printk(KERN_INFO
"sisfb: Memory heap starting at %dK, size %dK\n",
3200 (int)(ivideo
->heapstart
/ 1024), (int)(ivideo
->sisfb_heap_size
/ 1024));
3202 ivideo
->sisfb_heap
.vinfo
= ivideo
;
3204 ivideo
->sisfb_heap
.poha_chain
= NULL
;
3205 ivideo
->sisfb_heap
.poh_freelist
= NULL
;
3207 poh
= sisfb_poh_new_node(&ivideo
->sisfb_heap
);
3211 poh
->poh_next
= &ivideo
->sisfb_heap
.oh_free
;
3212 poh
->poh_prev
= &ivideo
->sisfb_heap
.oh_free
;
3213 poh
->size
= ivideo
->sisfb_heap_size
;
3214 poh
->offset
= ivideo
->heapstart
;
3216 ivideo
->sisfb_heap
.oh_free
.poh_next
= poh
;
3217 ivideo
->sisfb_heap
.oh_free
.poh_prev
= poh
;
3218 ivideo
->sisfb_heap
.oh_free
.size
= 0;
3219 ivideo
->sisfb_heap
.max_freesize
= poh
->size
;
3221 ivideo
->sisfb_heap
.oh_used
.poh_next
= &ivideo
->sisfb_heap
.oh_used
;
3222 ivideo
->sisfb_heap
.oh_used
.poh_prev
= &ivideo
->sisfb_heap
.oh_used
;
3223 ivideo
->sisfb_heap
.oh_used
.size
= SENTINEL
;
3225 if(ivideo
->cardnumber
== 0) {
3226 /* For the first card, make this heap the "global" one
3227 * for old DRM (which could handle only one card)
3229 sisfb_heap
= &ivideo
->sisfb_heap
;
3235 static struct SIS_OH
*
3236 sisfb_poh_new_node(struct SIS_HEAP
*memheap
)
3238 struct SIS_OHALLOC
*poha
;
3243 if(memheap
->poh_freelist
== NULL
) {
3244 poha
= kmalloc(SIS_OH_ALLOC_SIZE
, GFP_KERNEL
);
3248 poha
->poha_next
= memheap
->poha_chain
;
3249 memheap
->poha_chain
= poha
;
3251 cOhs
= (SIS_OH_ALLOC_SIZE
- sizeof(struct SIS_OHALLOC
)) / sizeof(struct SIS_OH
) + 1;
3253 poh
= &poha
->aoh
[0];
3254 for(i
= cOhs
- 1; i
!= 0; i
--) {
3255 poh
->poh_next
= poh
+ 1;
3259 poh
->poh_next
= NULL
;
3260 memheap
->poh_freelist
= &poha
->aoh
[0];
3263 poh
= memheap
->poh_freelist
;
3264 memheap
->poh_freelist
= poh
->poh_next
;
3269 static struct SIS_OH
*
3270 sisfb_poh_allocate(struct SIS_HEAP
*memheap
, u32 size
)
3272 struct SIS_OH
*pohThis
;
3273 struct SIS_OH
*pohRoot
;
3276 if(size
> memheap
->max_freesize
) {
3277 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3278 (unsigned int) size
/ 1024);
3282 pohThis
= memheap
->oh_free
.poh_next
;
3284 while(pohThis
!= &memheap
->oh_free
) {
3285 if(size
<= pohThis
->size
) {
3289 pohThis
= pohThis
->poh_next
;
3293 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3294 (unsigned int) size
/ 1024);
3298 if(size
== pohThis
->size
) {
3300 sisfb_delete_node(pohThis
);
3302 pohRoot
= sisfb_poh_new_node(memheap
);
3306 pohRoot
->offset
= pohThis
->offset
;
3307 pohRoot
->size
= size
;
3309 pohThis
->offset
+= size
;
3310 pohThis
->size
-= size
;
3313 memheap
->max_freesize
-= size
;
3315 pohThis
= &memheap
->oh_used
;
3316 sisfb_insert_node(pohThis
, pohRoot
);
3322 sisfb_delete_node(struct SIS_OH
*poh
)
3324 poh
->poh_prev
->poh_next
= poh
->poh_next
;
3325 poh
->poh_next
->poh_prev
= poh
->poh_prev
;
3329 sisfb_insert_node(struct SIS_OH
*pohList
, struct SIS_OH
*poh
)
3331 struct SIS_OH
*pohTemp
= pohList
->poh_next
;
3333 pohList
->poh_next
= poh
;
3334 pohTemp
->poh_prev
= poh
;
3336 poh
->poh_prev
= pohList
;
3337 poh
->poh_next
= pohTemp
;
3340 static struct SIS_OH
*
3341 sisfb_poh_free(struct SIS_HEAP
*memheap
, u32 base
)
3343 struct SIS_OH
*pohThis
;
3344 struct SIS_OH
*poh_freed
;
3345 struct SIS_OH
*poh_prev
;
3346 struct SIS_OH
*poh_next
;
3351 poh_freed
= memheap
->oh_used
.poh_next
;
3353 while(poh_freed
!= &memheap
->oh_used
) {
3354 if(poh_freed
->offset
== base
) {
3359 poh_freed
= poh_freed
->poh_next
;
3365 memheap
->max_freesize
+= poh_freed
->size
;
3367 poh_prev
= poh_next
= NULL
;
3368 ulUpper
= poh_freed
->offset
+ poh_freed
->size
;
3369 ulLower
= poh_freed
->offset
;
3371 pohThis
= memheap
->oh_free
.poh_next
;
3373 while(pohThis
!= &memheap
->oh_free
) {
3374 if(pohThis
->offset
== ulUpper
) {
3376 } else if((pohThis
->offset
+ pohThis
->size
) == ulLower
) {
3379 pohThis
= pohThis
->poh_next
;
3382 sisfb_delete_node(poh_freed
);
3384 if(poh_prev
&& poh_next
) {
3385 poh_prev
->size
+= (poh_freed
->size
+ poh_next
->size
);
3386 sisfb_delete_node(poh_next
);
3387 sisfb_free_node(memheap
, poh_freed
);
3388 sisfb_free_node(memheap
, poh_next
);
3393 poh_prev
->size
+= poh_freed
->size
;
3394 sisfb_free_node(memheap
, poh_freed
);
3399 poh_next
->size
+= poh_freed
->size
;
3400 poh_next
->offset
= poh_freed
->offset
;
3401 sisfb_free_node(memheap
, poh_freed
);
3405 sisfb_insert_node(&memheap
->oh_free
, poh_freed
);
3411 sisfb_free_node(struct SIS_HEAP
*memheap
, struct SIS_OH
*poh
)
3416 poh
->poh_next
= memheap
->poh_freelist
;
3417 memheap
->poh_freelist
= poh
;
3421 sis_int_malloc(struct sis_video_info
*ivideo
, struct sis_memreq
*req
)
3423 struct SIS_OH
*poh
= NULL
;
3425 if((ivideo
) && (ivideo
->sisfb_id
== SISFB_ID
) && (!ivideo
->havenoheap
))
3426 poh
= sisfb_poh_allocate(&ivideo
->sisfb_heap
, (u32
)req
->size
);
3429 req
->offset
= req
->size
= 0;
3430 DPRINTK("sisfb: Video RAM allocation failed\n");
3432 req
->offset
= poh
->offset
;
3433 req
->size
= poh
->size
;
3434 DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3435 (poh
->offset
+ ivideo
->video_vbase
));
3440 sis_malloc(struct sis_memreq
*req
)
3442 struct sis_video_info
*ivideo
= sisfb_heap
->vinfo
;
3444 if(&ivideo
->sisfb_heap
== sisfb_heap
)
3445 sis_int_malloc(ivideo
, req
);
3447 req
->offset
= req
->size
= 0;
3451 sis_malloc_new(struct pci_dev
*pdev
, struct sis_memreq
*req
)
3453 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
3455 sis_int_malloc(ivideo
, req
);
3458 /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3461 sis_int_free(struct sis_video_info
*ivideo
, u32 base
)
3465 if((!ivideo
) || (ivideo
->sisfb_id
!= SISFB_ID
) || (ivideo
->havenoheap
))
3468 poh
= sisfb_poh_free(&ivideo
->sisfb_heap
, base
);
3471 DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
3472 (unsigned int) base
);
3479 struct sis_video_info
*ivideo
= sisfb_heap
->vinfo
;
3481 sis_int_free(ivideo
, base
);
3485 sis_free_new(struct pci_dev
*pdev
, u32 base
)
3487 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
3489 sis_int_free(ivideo
, base
);
3492 /* --------------------- SetMode routines ------------------------- */
3495 sisfb_check_engine_and_sync(struct sis_video_info
*ivideo
)
3499 /* Check if MMIO and engines are enabled,
3500 * and sync in case they are. Can't use
3501 * ivideo->accel here, as this might have
3502 * been changed before this is called.
3504 inSISIDXREG(SISSR
, IND_SIS_PCI_ADDRESS_SET
, cr30
);
3505 inSISIDXREG(SISSR
, IND_SIS_MODULE_ENABLE
, cr31
);
3506 /* MMIO and 2D/3D engine enabled? */
3507 if((cr30
& SIS_MEM_MAP_IO_ENABLE
) && (cr31
& 0x42)) {
3508 #ifdef CONFIG_FB_SIS_300
3509 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3510 /* Don't care about TurboQueue. It's
3511 * enough to know that the engines
3514 sisfb_syncaccel(ivideo
);
3517 #ifdef CONFIG_FB_SIS_315
3518 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3519 /* Check that any queue mode is
3520 * enabled, and that the queue
3521 * is not in the state of "reset"
3523 inSISIDXREG(SISSR
, 0x26, cr30
);
3524 if((cr30
& 0xe0) && (!(cr30
& 0x01))) {
3525 sisfb_syncaccel(ivideo
);
3533 sisfb_pre_setmode(struct sis_video_info
*ivideo
)
3535 u8 cr30
= 0, cr31
= 0, cr33
= 0, cr35
= 0, cr38
= 0;
3538 ivideo
->currentvbflags
&= (VB_VIDEOBRIDGE
| VB_DISPTYPE_DISP2
);
3540 outSISIDXREG(SISSR
, 0x05, 0x86);
3542 inSISIDXREG(SISCR
, 0x31, cr31
);
3546 cr33
= ivideo
->rate_idx
& 0x0F;
3548 #ifdef CONFIG_FB_SIS_315
3549 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3550 if(ivideo
->chip
>= SIS_661
) {
3551 inSISIDXREG(SISCR
, 0x38, cr38
);
3552 cr38
&= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
3555 inSISIDXREG(SISCR
, tvregnum
, cr38
);
3556 cr38
&= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
3560 #ifdef CONFIG_FB_SIS_300
3561 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3563 inSISIDXREG(SISCR
, tvregnum
, cr38
);
3567 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
3568 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
3569 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
3571 switch(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
3574 cr38
&= ~0xc0; /* Clear PAL-M / PAL-N bits */
3575 if((ivideo
->vbflags
& TV_YPBPR
) && (ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) {
3576 #ifdef CONFIG_FB_SIS_315
3577 if(ivideo
->chip
>= SIS_661
) {
3579 if(ivideo
->vbflags
& TV_YPBPR525P
) cr35
|= 0x20;
3580 else if(ivideo
->vbflags
& TV_YPBPR750P
) cr35
|= 0x40;
3581 else if(ivideo
->vbflags
& TV_YPBPR1080I
) cr35
|= 0x60;
3582 cr30
|= SIS_SIMULTANEOUS_VIEW_ENABLE
;
3584 ivideo
->currentvbflags
|= (TV_YPBPR
| (ivideo
->vbflags
& TV_YPBPRALL
));
3585 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3586 cr30
|= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE
);
3588 if(ivideo
->vbflags
& TV_YPBPR525P
) cr38
|= 0x10;
3589 else if(ivideo
->vbflags
& TV_YPBPR750P
) cr38
|= 0x20;
3590 else if(ivideo
->vbflags
& TV_YPBPR1080I
) cr38
|= 0x30;
3592 ivideo
->currentvbflags
|= (TV_YPBPR
| (ivideo
->vbflags
& TV_YPBPRALL
));
3595 } else if((ivideo
->vbflags
& TV_HIVISION
) &&
3596 (ivideo
->vbflags2
& VB2_SISHIVISIONBRIDGE
)) {
3597 if(ivideo
->chip
>= SIS_661
) {
3603 cr30
|= SIS_SIMULTANEOUS_VIEW_ENABLE
;
3606 ivideo
->currentvbflags
|= TV_HIVISION
;
3607 } else if(ivideo
->vbflags
& TV_SCART
) {
3608 cr30
= (SIS_VB_OUTPUT_SCART
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3611 ivideo
->currentvbflags
|= TV_SCART
;
3613 if(ivideo
->vbflags
& TV_SVIDEO
) {
3614 cr30
= (SIS_VB_OUTPUT_SVIDEO
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3615 ivideo
->currentvbflags
|= TV_SVIDEO
;
3617 if(ivideo
->vbflags
& TV_AVIDEO
) {
3618 cr30
= (SIS_VB_OUTPUT_COMPOSITE
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3619 ivideo
->currentvbflags
|= TV_AVIDEO
;
3622 cr31
|= SIS_DRIVER_MODE
;
3624 if(ivideo
->vbflags
& (TV_AVIDEO
| TV_SVIDEO
)) {
3625 if(ivideo
->vbflags
& TV_PAL
) {
3626 cr31
|= 0x01; cr35
|= 0x01;
3627 ivideo
->currentvbflags
|= TV_PAL
;
3628 if(ivideo
->vbflags
& TV_PALM
) {
3629 cr38
|= 0x40; cr35
|= 0x04;
3630 ivideo
->currentvbflags
|= TV_PALM
;
3631 } else if(ivideo
->vbflags
& TV_PALN
) {
3632 cr38
|= 0x80; cr35
|= 0x08;
3633 ivideo
->currentvbflags
|= TV_PALN
;
3636 cr31
&= ~0x01; cr35
&= ~0x01;
3637 ivideo
->currentvbflags
|= TV_NTSC
;
3638 if(ivideo
->vbflags
& TV_NTSCJ
) {
3639 cr38
|= 0x40; cr35
|= 0x02;
3640 ivideo
->currentvbflags
|= TV_NTSCJ
;
3647 cr30
= (SIS_VB_OUTPUT_LCD
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3648 cr31
|= SIS_DRIVER_MODE
;
3649 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, ivideo
->sisfb_dstn
);
3650 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, ivideo
->sisfb_fstn
);
3651 ivideo
->curFSTN
= ivideo
->sisfb_fstn
;
3652 ivideo
->curDSTN
= ivideo
->sisfb_dstn
;
3656 cr30
= (SIS_VB_OUTPUT_CRT2
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3657 cr31
|= SIS_DRIVER_MODE
;
3658 if(ivideo
->sisfb_nocrt2rate
) {
3659 cr33
|= (sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
<< 4);
3661 cr33
|= ((ivideo
->rate_idx
& 0x0F) << 4);
3665 default: /* disable CRT2 */
3667 cr31
|= (SIS_DRIVER_MODE
| SIS_VB_OUTPUT_DISABLE
);
3670 outSISIDXREG(SISCR
, 0x30, cr30
);
3671 outSISIDXREG(SISCR
, 0x33, cr33
);
3673 if(ivideo
->chip
>= SIS_661
) {
3674 #ifdef CONFIG_FB_SIS_315
3675 cr31
&= ~0x01; /* Clear PAL flag (now in CR35) */
3676 setSISIDXREG(SISCR
, 0x35, ~0x10, cr35
); /* Leave overscan bit alone */
3677 cr38
&= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
3678 setSISIDXREG(SISCR
, 0x38, 0xf8, cr38
);
3680 } else if(ivideo
->chip
!= SIS_300
) {
3681 outSISIDXREG(SISCR
, tvregnum
, cr38
);
3683 outSISIDXREG(SISCR
, 0x31, cr31
);
3685 ivideo
->SiS_Pr
.SiS_UseOEM
= ivideo
->sisfb_useoem
;
3687 sisfb_check_engine_and_sync(ivideo
);
3690 /* Fix SR11 for 661 and later */
3691 #ifdef CONFIG_FB_SIS_315
3693 sisfb_fixup_SR11(struct sis_video_info
*ivideo
)
3697 if(ivideo
->chip
>= SIS_661
) {
3698 inSISIDXREG(SISSR
,0x11,tmpreg
);
3700 inSISIDXREG(SISSR
,0x3e,tmpreg
);
3701 tmpreg
= (tmpreg
+ 1) & 0xff;
3702 outSISIDXREG(SISSR
,0x3e,tmpreg
);
3703 inSISIDXREG(SISSR
,0x11,tmpreg
);
3706 andSISIDXREG(SISSR
,0x11,0x0f);
3713 sisfb_set_TVxposoffset(struct sis_video_info
*ivideo
, int val
)
3715 if(val
> 32) val
= 32;
3716 if(val
< -32) val
= -32;
3717 ivideo
->tvxpos
= val
;
3719 if(ivideo
->sisfblocked
) return;
3720 if(!ivideo
->modechanged
) return;
3722 if(ivideo
->currentvbflags
& CRT2_TV
) {
3724 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3726 int x
= ivideo
->tvx
;
3728 switch(ivideo
->chronteltype
) {
3732 outSISIDXREG(SISSR
,0x05,0x86);
3733 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0a, (x
& 0xff));
3734 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x08, ((x
& 0x0100) >> 7), 0xFD);
3737 /* Not supported by hardware */
3741 } else if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3743 u8 p2_1f
,p2_20
,p2_2b
,p2_42
,p2_43
;
3744 unsigned short temp
;
3746 p2_1f
= ivideo
->p2_1f
;
3747 p2_20
= ivideo
->p2_20
;
3748 p2_2b
= ivideo
->p2_2b
;
3749 p2_42
= ivideo
->p2_42
;
3750 p2_43
= ivideo
->p2_43
;
3752 temp
= p2_1f
| ((p2_20
& 0xf0) << 4);
3754 p2_1f
= temp
& 0xff;
3755 p2_20
= (temp
& 0xf00) >> 4;
3756 p2_2b
= ((p2_2b
& 0x0f) + (val
* 2)) & 0x0f;
3757 temp
= p2_43
| ((p2_42
& 0xf0) << 4);
3759 p2_43
= temp
& 0xff;
3760 p2_42
= (temp
& 0xf00) >> 4;
3761 outSISIDXREG(SISPART2
,0x1f,p2_1f
);
3762 setSISIDXREG(SISPART2
,0x20,0x0F,p2_20
);
3763 setSISIDXREG(SISPART2
,0x2b,0xF0,p2_2b
);
3764 setSISIDXREG(SISPART2
,0x42,0x0F,p2_42
);
3765 outSISIDXREG(SISPART2
,0x43,p2_43
);
3771 sisfb_set_TVyposoffset(struct sis_video_info
*ivideo
, int val
)
3773 if(val
> 32) val
= 32;
3774 if(val
< -32) val
= -32;
3775 ivideo
->tvypos
= val
;
3777 if(ivideo
->sisfblocked
) return;
3778 if(!ivideo
->modechanged
) return;
3780 if(ivideo
->currentvbflags
& CRT2_TV
) {
3782 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3784 int y
= ivideo
->tvy
;
3786 switch(ivideo
->chronteltype
) {
3790 outSISIDXREG(SISSR
,0x05,0x86);
3791 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0b, (y
& 0xff));
3792 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x08, ((y
& 0x0100) >> 8), 0xFE);
3795 /* Not supported by hardware */
3799 } else if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3803 p2_01
= ivideo
->p2_01
;
3804 p2_02
= ivideo
->p2_02
;
3808 if(!(ivideo
->currentvbflags
& (TV_HIVISION
| TV_YPBPR
))) {
3809 while((p2_01
<= 0) || (p2_02
<= 0)) {
3814 outSISIDXREG(SISPART2
,0x01,p2_01
);
3815 outSISIDXREG(SISPART2
,0x02,p2_02
);
3821 sisfb_post_setmode(struct sis_video_info
*ivideo
)
3823 bool crt1isoff
= false;
3825 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
3828 #ifdef CONFIG_FB_SIS_315
3832 outSISIDXREG(SISSR
, 0x05, 0x86);
3834 #ifdef CONFIG_FB_SIS_315
3835 sisfb_fixup_SR11(ivideo
);
3838 /* Now we actually HAVE changed the display mode */
3839 ivideo
->modechanged
= 1;
3841 /* We can't switch off CRT1 if bridge is in slave mode */
3842 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
3843 if(sisfb_bridgeisslave(ivideo
)) doit
= false;
3845 ivideo
->sisfb_crt1off
= 0;
3847 #ifdef CONFIG_FB_SIS_300
3848 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3849 if((ivideo
->sisfb_crt1off
) && (doit
)) {
3856 setSISIDXREG(SISCR
, 0x17, 0x7f, reg
);
3859 #ifdef CONFIG_FB_SIS_315
3860 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3861 if((ivideo
->sisfb_crt1off
) && (doit
)) {
3870 setSISIDXREG(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, ~0x40, reg
);
3871 setSISIDXREG(SISSR
, 0x1f, ~0xc0, reg1
);
3876 ivideo
->currentvbflags
&= ~VB_DISPTYPE_CRT1
;
3877 ivideo
->currentvbflags
|= VB_SINGLE_MODE
;
3879 ivideo
->currentvbflags
|= VB_DISPTYPE_CRT1
;
3880 if(ivideo
->currentvbflags
& VB_DISPTYPE_CRT2
) {
3881 ivideo
->currentvbflags
|= VB_MIRROR_MODE
;
3883 ivideo
->currentvbflags
|= VB_SINGLE_MODE
;
3887 andSISIDXREG(SISSR
, IND_SIS_RAMDAC_CONTROL
, ~0x04);
3889 if(ivideo
->currentvbflags
& CRT2_TV
) {
3890 if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3891 inSISIDXREG(SISPART2
,0x1f,ivideo
->p2_1f
);
3892 inSISIDXREG(SISPART2
,0x20,ivideo
->p2_20
);
3893 inSISIDXREG(SISPART2
,0x2b,ivideo
->p2_2b
);
3894 inSISIDXREG(SISPART2
,0x42,ivideo
->p2_42
);
3895 inSISIDXREG(SISPART2
,0x43,ivideo
->p2_43
);
3896 inSISIDXREG(SISPART2
,0x01,ivideo
->p2_01
);
3897 inSISIDXREG(SISPART2
,0x02,ivideo
->p2_02
);
3898 } else if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3899 if(ivideo
->chronteltype
== 1) {
3900 ivideo
->tvx
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0a);
3901 ivideo
->tvx
|= (((SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x08) & 0x02) >> 1) << 8);
3902 ivideo
->tvy
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0b);
3903 ivideo
->tvy
|= ((SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x08) & 0x01) << 8);
3908 if(ivideo
->tvxpos
) {
3909 sisfb_set_TVxposoffset(ivideo
, ivideo
->tvxpos
);
3911 if(ivideo
->tvypos
) {
3912 sisfb_set_TVyposoffset(ivideo
, ivideo
->tvypos
);
3915 /* Eventually sync engines */
3916 sisfb_check_engine_and_sync(ivideo
);
3918 /* (Re-)Initialize chip engines */
3920 sisfb_engine_init(ivideo
);
3922 ivideo
->engineok
= 0;
3927 sisfb_reset_mode(struct sis_video_info
*ivideo
)
3929 if(sisfb_set_mode(ivideo
, 0))
3932 sisfb_set_pitch(ivideo
);
3933 sisfb_set_base_CRT1(ivideo
, ivideo
->current_base
);
3934 sisfb_set_base_CRT2(ivideo
, ivideo
->current_base
);
3940 sisfb_handle_command(struct sis_video_info
*ivideo
, struct sisfb_cmd
*sisfb_command
)
3944 switch(sisfb_command
->sisfb_cmd
) {
3945 case SISFB_CMD_GETVBFLAGS
:
3946 if(!ivideo
->modechanged
) {
3947 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_EARLY
;
3949 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3950 sisfb_command
->sisfb_result
[1] = ivideo
->currentvbflags
;
3951 sisfb_command
->sisfb_result
[2] = ivideo
->vbflags2
;
3954 case SISFB_CMD_SWITCHCRT1
:
3955 /* arg[0]: 0 = off, 1 = on, 99 = query */
3956 if(!ivideo
->modechanged
) {
3957 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_EARLY
;
3958 } else if(sisfb_command
->sisfb_arg
[0] == 99) {
3960 sisfb_command
->sisfb_result
[1] = ivideo
->sisfb_crt1off
? 0 : 1;
3961 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3962 } else if(ivideo
->sisfblocked
) {
3963 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_LOCKED
;
3964 } else if((!(ivideo
->currentvbflags
& CRT2_ENABLE
)) &&
3965 (sisfb_command
->sisfb_arg
[0] == 0)) {
3966 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_NOCRT2
;
3968 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3969 mycrt1off
= sisfb_command
->sisfb_arg
[0] ? 0 : 1;
3970 if( ((ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
) && mycrt1off
) ||
3971 ((!(ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
)) && !mycrt1off
) ) {
3972 ivideo
->sisfb_crt1off
= mycrt1off
;
3973 if(sisfb_reset_mode(ivideo
)) {
3974 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OTHER
;
3977 sisfb_command
->sisfb_result
[1] = ivideo
->sisfb_crt1off
? 0 : 1;
3982 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_UNKNOWN
;
3983 printk(KERN_ERR
"sisfb: Unknown command 0x%x\n",
3984 sisfb_command
->sisfb_cmd
);
3989 SISINITSTATIC
int __init
3990 sisfb_setup(char *options
)
3994 sisfb_setdefaultparms();
3996 if(!options
|| !(*options
))
3999 while((this_opt
= strsep(&options
, ",")) != NULL
) {
4001 if(!(*this_opt
)) continue;
4003 if(!strnicmp(this_opt
, "off", 3)) {
4005 } else if(!strnicmp(this_opt
, "forcecrt2type:", 14)) {
4006 /* Need to check crt2 type first for fstn/dstn */
4007 sisfb_search_crt2type(this_opt
+ 14);
4008 } else if(!strnicmp(this_opt
, "tvmode:",7)) {
4009 sisfb_search_tvstd(this_opt
+ 7);
4010 } else if(!strnicmp(this_opt
, "tvstandard:",11)) {
4011 sisfb_search_tvstd(this_opt
+ 11);
4012 } else if(!strnicmp(this_opt
, "mode:", 5)) {
4013 sisfb_search_mode(this_opt
+ 5, false);
4014 } else if(!strnicmp(this_opt
, "vesa:", 5)) {
4015 sisfb_search_vesamode(simple_strtoul(this_opt
+ 5, NULL
, 0), false);
4016 } else if(!strnicmp(this_opt
, "rate:", 5)) {
4017 sisfb_parm_rate
= simple_strtoul(this_opt
+ 5, NULL
, 0);
4018 } else if(!strnicmp(this_opt
, "forcecrt1:", 10)) {
4019 sisfb_forcecrt1
= (int)simple_strtoul(this_opt
+ 10, NULL
, 0);
4020 } else if(!strnicmp(this_opt
, "mem:",4)) {
4021 sisfb_parm_mem
= simple_strtoul(this_opt
+ 4, NULL
, 0);
4022 } else if(!strnicmp(this_opt
, "pdc:", 4)) {
4023 sisfb_pdc
= simple_strtoul(this_opt
+ 4, NULL
, 0);
4024 } else if(!strnicmp(this_opt
, "pdc1:", 5)) {
4025 sisfb_pdca
= simple_strtoul(this_opt
+ 5, NULL
, 0);
4026 } else if(!strnicmp(this_opt
, "noaccel", 7)) {
4028 } else if(!strnicmp(this_opt
, "accel", 5)) {
4030 } else if(!strnicmp(this_opt
, "noypan", 6)) {
4032 } else if(!strnicmp(this_opt
, "ypan", 4)) {
4034 } else if(!strnicmp(this_opt
, "nomax", 5)) {
4036 } else if(!strnicmp(this_opt
, "max", 3)) {
4038 } else if(!strnicmp(this_opt
, "userom:", 7)) {
4039 sisfb_userom
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
4040 } else if(!strnicmp(this_opt
, "useoem:", 7)) {
4041 sisfb_useoem
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
4042 } else if(!strnicmp(this_opt
, "nocrt2rate", 10)) {
4043 sisfb_nocrt2rate
= 1;
4044 } else if(!strnicmp(this_opt
, "scalelcd:", 9)) {
4045 unsigned long temp
= 2;
4046 temp
= simple_strtoul(this_opt
+ 9, NULL
, 0);
4047 if((temp
== 0) || (temp
== 1)) {
4048 sisfb_scalelcd
= temp
^ 1;
4050 } else if(!strnicmp(this_opt
, "tvxposoffset:", 13)) {
4052 temp
= (int)simple_strtol(this_opt
+ 13, NULL
, 0);
4053 if((temp
>= -32) && (temp
<= 32)) {
4054 sisfb_tvxposoffset
= temp
;
4056 } else if(!strnicmp(this_opt
, "tvyposoffset:", 13)) {
4058 temp
= (int)simple_strtol(this_opt
+ 13, NULL
, 0);
4059 if((temp
>= -32) && (temp
<= 32)) {
4060 sisfb_tvyposoffset
= temp
;
4062 } else if(!strnicmp(this_opt
, "specialtiming:", 14)) {
4063 sisfb_search_specialtiming(this_opt
+ 14);
4064 } else if(!strnicmp(this_opt
, "lvdshl:", 7)) {
4066 temp
= simple_strtoul(this_opt
+ 7, NULL
, 0);
4067 if((temp
>= 0) && (temp
<= 3)) {
4068 sisfb_lvdshl
= temp
;
4070 } else if(this_opt
[0] >= '0' && this_opt
[0] <= '9') {
4071 sisfb_search_mode(this_opt
, true);
4072 #if !defined(__i386__) && !defined(__x86_64__)
4073 } else if(!strnicmp(this_opt
, "resetcard", 9)) {
4074 sisfb_resetcard
= 1;
4075 } else if(!strnicmp(this_opt
, "videoram:", 9)) {
4076 sisfb_videoram
= simple_strtoul(this_opt
+ 9, NULL
, 0);
4079 printk(KERN_INFO
"sisfb: Invalid option %s\n", this_opt
);
4088 static int __devinit
4089 sisfb_check_rom(SIS_IOTYPE1
*rom_base
, struct sis_video_info
*ivideo
)
4094 if((readb(rom_base
) != 0x55) || (readb(rom_base
+ 1) != 0xaa))
4097 romptr
= (readb(rom_base
+ 0x18) | (readb(rom_base
+ 0x19) << 8));
4098 if(romptr
> (0x10000 - 8))
4101 rom
= rom_base
+ romptr
;
4103 if((readb(rom
) != 'P') || (readb(rom
+ 1) != 'C') ||
4104 (readb(rom
+ 2) != 'I') || (readb(rom
+ 3) != 'R'))
4107 if((readb(rom
+ 4) | (readb(rom
+ 5) << 8)) != ivideo
->chip_vendor
)
4110 if((readb(rom
+ 6) | (readb(rom
+ 7) << 8)) != ivideo
->chip_id
)
4116 static unsigned char * __devinit
4117 sisfb_find_rom(struct pci_dev
*pdev
)
4119 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4120 SIS_IOTYPE1
*rom_base
;
4121 unsigned char *myrombase
= NULL
;
4123 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
4126 /* First, try the official pci ROM functions (except
4127 * on integrated chipsets which have no ROM).
4130 if(!ivideo
->nbridge
) {
4132 if((rom_base
= pci_map_rom(pdev
, &romsize
))) {
4134 if(sisfb_check_rom(rom_base
, ivideo
)) {
4136 if((myrombase
= vmalloc(65536))) {
4138 /* Work around bug in pci/rom.c: Folks forgot to check
4139 * whether the size retrieved from the BIOS image eventually
4140 * is larger than the mapped size
4142 if(pci_resource_len(pdev
, PCI_ROM_RESOURCE
) < romsize
)
4143 romsize
= pci_resource_len(pdev
, PCI_ROM_RESOURCE
);
4145 memcpy_fromio(myrombase
, rom_base
,
4146 (romsize
> 65536) ? 65536 : romsize
);
4149 pci_unmap_rom(pdev
, rom_base
);
4153 if(myrombase
) return myrombase
;
4156 /* Otherwise do it the conventional way. */
4158 #if defined(__i386__) || defined(__x86_64__)
4160 for(temp
= 0x000c0000; temp
< 0x000f0000; temp
+= 0x00001000) {
4162 rom_base
= ioremap(temp
, 65536);
4166 if(!sisfb_check_rom(rom_base
, ivideo
)) {
4171 if((myrombase
= vmalloc(65536)))
4172 memcpy_fromio(myrombase
, rom_base
, 65536);
4181 pci_read_config_dword(pdev
, PCI_ROM_ADDRESS
, &temp
);
4182 pci_write_config_dword(pdev
, PCI_ROM_ADDRESS
,
4183 (ivideo
->video_base
& PCI_ROM_ADDRESS_MASK
) | PCI_ROM_ADDRESS_ENABLE
);
4185 rom_base
= ioremap(ivideo
->video_base
, 65536);
4187 if(sisfb_check_rom(rom_base
, ivideo
)) {
4188 if((myrombase
= vmalloc(65536)))
4189 memcpy_fromio(myrombase
, rom_base
, 65536);
4194 pci_write_config_dword(pdev
, PCI_ROM_ADDRESS
, temp
);
4201 static void __devinit
4202 sisfb_post_map_vram(struct sis_video_info
*ivideo
, unsigned int *mapsize
,
4205 ivideo
->video_vbase
= ioremap(ivideo
->video_base
, (*mapsize
));
4207 if(!ivideo
->video_vbase
) {
4209 "sisfb: Unable to map maximum video RAM for size detection\n");
4211 while((!(ivideo
->video_vbase
= ioremap(ivideo
->video_base
, (*mapsize
))))) {
4213 if((*mapsize
) < (min
<< 20))
4216 if(ivideo
->video_vbase
) {
4218 "sisfb: Video RAM size detection limited to %dMB\n",
4219 (int)((*mapsize
) >> 20));
4224 #ifdef CONFIG_FB_SIS_300
4225 static int __devinit
4226 sisfb_post_300_buswidth(struct sis_video_info
*ivideo
)
4228 SIS_IOTYPE1
*FBAddress
= ivideo
->video_vbase
;
4229 unsigned short temp
;
4233 andSISIDXREG(SISSR
, 0x15, 0xFB);
4234 orSISIDXREG(SISSR
, 0x15, 0x04);
4235 outSISIDXREG(SISSR
, 0x13, 0x00);
4236 outSISIDXREG(SISSR
, 0x14, 0xBF);
4238 for(i
= 0; i
< 2; i
++) {
4240 for(j
= 0; j
< 4; j
++) {
4241 writew(temp
, FBAddress
);
4242 if(readw(FBAddress
) == temp
)
4244 orSISIDXREG(SISSR
, 0x3c, 0x01);
4245 inSISIDXREG(SISSR
, 0x05, reg
);
4246 inSISIDXREG(SISSR
, 0x05, reg
);
4247 andSISIDXREG(SISSR
, 0x3c, 0xfe);
4248 inSISIDXREG(SISSR
, 0x05, reg
);
4249 inSISIDXREG(SISSR
, 0x05, reg
);
4254 writel(0x01234567L
, FBAddress
);
4255 writel(0x456789ABL
, (FBAddress
+ 4));
4256 writel(0x89ABCDEFL
, (FBAddress
+ 8));
4257 writel(0xCDEF0123L
, (FBAddress
+ 12));
4259 inSISIDXREG(SISSR
, 0x3b, reg
);
4261 if(readl((FBAddress
+ 12)) == 0xCDEF0123L
)
4262 return 4; /* Channel A 128bit */
4265 if(readl((FBAddress
+ 4)) == 0x456789ABL
)
4266 return 2; /* Channel B 64bit */
4268 return 1; /* 32bit */
4271 static int __devinit
4272 sisfb_post_300_rwtest(struct sis_video_info
*ivideo
, int iteration
, int buswidth
,
4273 int PseudoRankCapacity
, int PseudoAdrPinCount
,
4274 unsigned int mapsize
)
4276 SIS_IOTYPE1
*FBAddr
= ivideo
->video_vbase
;
4277 unsigned short sr14
;
4278 unsigned int k
, RankCapacity
, PageCapacity
, BankNumHigh
, BankNumMid
;
4279 unsigned int PhysicalAdrOtherPage
, PhysicalAdrHigh
, PhysicalAdrHalfPage
;
4280 static const unsigned short SiS_DRAMType
[17][5] = {
4281 {0x0C,0x0A,0x02,0x40,0x39},
4282 {0x0D,0x0A,0x01,0x40,0x48},
4283 {0x0C,0x09,0x02,0x20,0x35},
4284 {0x0D,0x09,0x01,0x20,0x44},
4285 {0x0C,0x08,0x02,0x10,0x31},
4286 {0x0D,0x08,0x01,0x10,0x40},
4287 {0x0C,0x0A,0x01,0x20,0x34},
4288 {0x0C,0x09,0x01,0x08,0x32},
4289 {0x0B,0x08,0x02,0x08,0x21},
4290 {0x0C,0x08,0x01,0x08,0x30},
4291 {0x0A,0x08,0x02,0x04,0x11},
4292 {0x0B,0x0A,0x01,0x10,0x28},
4293 {0x09,0x08,0x02,0x02,0x01},
4294 {0x0B,0x09,0x01,0x08,0x24},
4295 {0x0B,0x08,0x01,0x04,0x20},
4296 {0x0A,0x08,0x01,0x02,0x10},
4297 {0x09,0x08,0x01,0x01,0x00}
4300 for(k
= 0; k
<= 16; k
++) {
4302 RankCapacity
= buswidth
* SiS_DRAMType
[k
][3];
4304 if(RankCapacity
!= PseudoRankCapacity
)
4307 if((SiS_DRAMType
[k
][2] + SiS_DRAMType
[k
][0]) > PseudoAdrPinCount
)
4310 BankNumHigh
= RankCapacity
* 16 * iteration
- 1;
4311 if(iteration
== 3) { /* Rank No */
4312 BankNumMid
= RankCapacity
* 16 - 1;
4314 BankNumMid
= RankCapacity
* 16 * iteration
/ 2 - 1;
4317 PageCapacity
= (1 << SiS_DRAMType
[k
][1]) * buswidth
* 4;
4318 PhysicalAdrHigh
= BankNumHigh
;
4319 PhysicalAdrHalfPage
= (PageCapacity
/ 2 + PhysicalAdrHigh
) % PageCapacity
;
4320 PhysicalAdrOtherPage
= PageCapacity
* SiS_DRAMType
[k
][2] + PhysicalAdrHigh
;
4322 andSISIDXREG(SISSR
, 0x15, 0xFB); /* Test */
4323 orSISIDXREG(SISSR
, 0x15, 0x04); /* Test */
4324 sr14
= (SiS_DRAMType
[k
][3] * buswidth
) - 1;
4325 if(buswidth
== 4) sr14
|= 0x80;
4326 else if(buswidth
== 2) sr14
|= 0x40;
4327 outSISIDXREG(SISSR
, 0x13, SiS_DRAMType
[k
][4]);
4328 outSISIDXREG(SISSR
, 0x14, sr14
);
4333 if((BankNumHigh
+ PhysicalAdrHigh
>= mapsize
) ||
4334 (BankNumMid
+ PhysicalAdrHigh
>= mapsize
) ||
4335 (BankNumHigh
+ PhysicalAdrHalfPage
>= mapsize
) ||
4336 (BankNumHigh
+ PhysicalAdrOtherPage
>= mapsize
))
4340 writew(((unsigned short)PhysicalAdrHigh
),
4341 (FBAddr
+ BankNumHigh
+ PhysicalAdrHigh
));
4342 writew(((unsigned short)BankNumMid
),
4343 (FBAddr
+ BankNumMid
+ PhysicalAdrHigh
));
4344 writew(((unsigned short)PhysicalAdrHalfPage
),
4345 (FBAddr
+ BankNumHigh
+ PhysicalAdrHalfPage
));
4346 writew(((unsigned short)PhysicalAdrOtherPage
),
4347 (FBAddr
+ BankNumHigh
+ PhysicalAdrOtherPage
));
4350 if(readw(FBAddr
+ BankNumHigh
+ PhysicalAdrHigh
) == PhysicalAdrHigh
)
4357 static void __devinit
4358 sisfb_post_300_ramsize(struct pci_dev
*pdev
, unsigned int mapsize
)
4360 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4362 int PseudoRankCapacity
, PseudoAdrPinCount
;
4364 buswidth
= sisfb_post_300_buswidth(ivideo
);
4366 for(i
= 6; i
>= 0; i
--) {
4367 PseudoRankCapacity
= 1 << i
;
4368 for(j
= 4; j
>= 1; j
--) {
4369 PseudoAdrPinCount
= 15 - j
;
4370 if((PseudoRankCapacity
* j
) <= 64) {
4371 if(sisfb_post_300_rwtest(ivideo
,
4383 static void __devinit
4384 sisfb_post_sis300(struct pci_dev
*pdev
)
4386 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4387 unsigned char *bios
= ivideo
->SiS_Pr
.VirtualRomBase
;
4388 u8 reg
, v1
, v2
, v3
, v4
, v5
, v6
, v7
, v8
;
4389 u16 index
, rindex
, memtype
= 0;
4390 unsigned int mapsize
;
4392 if(!ivideo
->SiS_Pr
.UseROM
)
4395 outSISIDXREG(SISSR
, 0x05, 0x86);
4398 if(bios
[0x52] & 0x80) {
4399 memtype
= bios
[0x52];
4401 inSISIDXREG(SISSR
, 0x3a, memtype
);
4406 v3
= 0x80; v6
= 0x80;
4407 if(ivideo
->revision_id
<= 0x13) {
4408 v1
= 0x44; v2
= 0x42;
4409 v4
= 0x44; v5
= 0x42;
4411 v1
= 0x68; v2
= 0x43; /* Assume 125Mhz MCLK */
4412 v4
= 0x68; v5
= 0x43; /* Assume 125Mhz ECLK */
4414 index
= memtype
* 5;
4415 rindex
= index
+ 0x54;
4416 v1
= bios
[rindex
++];
4417 v2
= bios
[rindex
++];
4418 v3
= bios
[rindex
++];
4419 rindex
= index
+ 0x7c;
4420 v4
= bios
[rindex
++];
4421 v5
= bios
[rindex
++];
4422 v6
= bios
[rindex
++];
4425 outSISIDXREG(SISSR
, 0x28, v1
);
4426 outSISIDXREG(SISSR
, 0x29, v2
);
4427 outSISIDXREG(SISSR
, 0x2a, v3
);
4428 outSISIDXREG(SISSR
, 0x2e, v4
);
4429 outSISIDXREG(SISSR
, 0x2f, v5
);
4430 outSISIDXREG(SISSR
, 0x30, v6
);
4435 outSISIDXREG(SISSR
, 0x07, v1
); /* DAC speed */
4437 outSISIDXREG(SISSR
, 0x11, 0x0f); /* DDC, power save */
4439 v1
= 0x01; v2
= 0x43; v3
= 0x1e; v4
= 0x2a;
4440 v5
= 0x06; v6
= 0x00; v7
= 0x00; v8
= 0x00;
4444 v2
= bios
[memtype
+ 8];
4445 v3
= bios
[memtype
+ 16];
4446 v4
= bios
[memtype
+ 24];
4447 v5
= bios
[memtype
+ 32];
4448 v6
= bios
[memtype
+ 40];
4449 v7
= bios
[memtype
+ 48];
4450 v8
= bios
[memtype
+ 56];
4452 if(ivideo
->revision_id
>= 0x80)
4454 outSISIDXREG(SISSR
, 0x15, v1
); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4455 outSISIDXREG(SISSR
, 0x16, v2
);
4456 outSISIDXREG(SISSR
, 0x17, v3
);
4457 outSISIDXREG(SISSR
, 0x18, v4
);
4458 outSISIDXREG(SISSR
, 0x19, v5
);
4459 outSISIDXREG(SISSR
, 0x1a, v6
);
4460 outSISIDXREG(SISSR
, 0x1b, v7
);
4461 outSISIDXREG(SISSR
, 0x1c, v8
); /* ---- */
4462 andSISIDXREG(SISSR
, 0x15 ,0xfb);
4463 orSISIDXREG(SISSR
, 0x15, 0x04);
4465 if(bios
[0x53] & 0x02) {
4466 orSISIDXREG(SISSR
, 0x19, 0x20);
4469 v1
= 0x04; /* DAC pedestal (BIOS 0xe5) */
4470 if(ivideo
->revision_id
>= 0x80)
4472 outSISIDXREG(SISSR
, 0x1f, v1
);
4473 outSISIDXREG(SISSR
, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
4474 v1
= 0xf6; v2
= 0x0d; v3
= 0x00;
4480 outSISIDXREG(SISSR
, 0x23, v1
);
4481 outSISIDXREG(SISSR
, 0x24, v2
);
4482 outSISIDXREG(SISSR
, 0x25, v3
);
4483 outSISIDXREG(SISSR
, 0x21, 0x84);
4484 outSISIDXREG(SISSR
, 0x22, 0x00);
4485 outSISIDXREG(SISCR
, 0x37, 0x00);
4486 orSISIDXREG(SISPART1
, 0x24, 0x01); /* unlock crt2 */
4487 outSISIDXREG(SISPART1
, 0x00, 0x00);
4488 v1
= 0x40; v2
= 0x11;
4493 outSISIDXREG(SISPART1
, 0x02, v1
);
4495 if(ivideo
->revision_id
>= 0x80)
4498 inSISIDXREG(SISPART4
, 0x00, reg
);
4499 if((reg
== 1) || (reg
== 2)) {
4500 outSISIDXREG(SISCR
, 0x37, 0x02);
4501 outSISIDXREG(SISPART2
, 0x00, 0x1c);
4502 v4
= 0x00; v5
= 0x00; v6
= 0x10;
4503 if(ivideo
->SiS_Pr
.UseROM
) {
4508 outSISIDXREG(SISPART4
, 0x0d, v4
);
4509 outSISIDXREG(SISPART4
, 0x0e, v5
);
4510 outSISIDXREG(SISPART4
, 0x10, v6
);
4511 outSISIDXREG(SISPART4
, 0x0f, 0x3f);
4512 inSISIDXREG(SISPART4
, 0x01, reg
);
4514 inSISIDXREG(SISPART4
, 0x23, reg
);
4517 outSISIDXREG(SISPART4
, 0x23, reg
);
4522 outSISIDXREG(SISSR
, 0x32, v2
);
4524 andSISIDXREG(SISPART1
, 0x24, 0xfe); /* Lock CRT2 */
4526 inSISIDXREG(SISSR
, 0x16, reg
);
4528 outSISIDXREG(SISCR
, 0x35, reg
);
4529 outSISIDXREG(SISCR
, 0x83, 0x00);
4530 #if !defined(__i386__) && !defined(__x86_64__)
4531 if(sisfb_videoram
) {
4532 outSISIDXREG(SISSR
, 0x13, 0x28); /* ? */
4533 reg
= ((sisfb_videoram
>> 10) - 1) | 0x40;
4534 outSISIDXREG(SISSR
, 0x14, reg
);
4537 /* Need to map max FB size for finding out about RAM size */
4539 sisfb_post_map_vram(ivideo
, &mapsize
, 4);
4541 if(ivideo
->video_vbase
) {
4542 sisfb_post_300_ramsize(pdev
, mapsize
);
4543 iounmap(ivideo
->video_vbase
);
4546 "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4547 outSISIDXREG(SISSR
, 0x13, 0x28); /* ? */
4548 outSISIDXREG(SISSR
, 0x14, 0x47); /* 8MB, 64bit default */
4550 #if !defined(__i386__) && !defined(__x86_64__)
4557 inSISIDXREG(SISSR
, 0x3a, reg
);
4558 if((reg
& 0x30) == 0x30) {
4559 v1
= 0x04; /* PCI */
4562 v1
= 0x14; /* AGP */
4566 outSISIDXREG(SISSR
, 0x21, v1
);
4567 outSISIDXREG(SISSR
, 0x22, v2
);
4570 sisfb_sense_crt1(ivideo
);
4572 /* Set default mode, don't clear screen */
4573 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
4574 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
4575 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
4576 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
4577 ivideo
->SiS_Pr
.VideoMemorySize
= 8 << 20;
4578 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
4580 outSISIDXREG(SISSR
, 0x05, 0x86);
4583 orSISIDXREG(SISSR
, 0x01, 0x20);
4585 /* Save mode number in CR34 */
4586 outSISIDXREG(SISCR
, 0x34, 0x2e);
4588 /* Let everyone know what the current mode is */
4589 ivideo
->modeprechange
= 0x2e;
4593 #ifdef CONFIG_FB_SIS_315
4595 static void __devinit
4596 sisfb_post_sis315330(struct pci_dev
*pdev
)
4602 static void __devinit
4603 sisfb_post_xgi_delay(struct sis_video_info
*ivideo
, int delay
)
4608 for(i
= 0; i
<= (delay
* 10 * 36); i
++) {
4609 inSISIDXREG(SISSR
, 0x05, reg
);
4614 static int __devinit
4615 sisfb_find_host_bridge(struct sis_video_info
*ivideo
, struct pci_dev
*mypdev
,
4616 unsigned short pcivendor
)
4618 struct pci_dev
*pdev
= NULL
;
4619 unsigned short temp
;
4622 while((pdev
= pci_get_class(PCI_CLASS_BRIDGE_HOST
, pdev
))) {
4623 temp
= pdev
->vendor
;
4624 if(temp
== pcivendor
) {
4634 static int __devinit
4635 sisfb_post_xgi_rwtest(struct sis_video_info
*ivideo
, int starta
,
4636 unsigned int enda
, unsigned int mapsize
)
4641 writel(0, ivideo
->video_vbase
);
4643 for(i
= starta
; i
<= enda
; i
++) {
4646 writel(pos
, ivideo
->video_vbase
+ pos
);
4649 sisfb_post_xgi_delay(ivideo
, 150);
4651 if(readl(ivideo
->video_vbase
) != 0)
4654 for(i
= starta
; i
<= enda
; i
++) {
4657 if(readl(ivideo
->video_vbase
+ pos
) != pos
)
4666 static void __devinit
4667 sisfb_post_xgi_ramsize(struct sis_video_info
*ivideo
)
4669 unsigned int buswidth
, ranksize
, channelab
, mapsize
;
4672 static const u8 dramsr13
[12 * 5] = {
4673 0x02, 0x0e, 0x0b, 0x80, 0x5d,
4674 0x02, 0x0e, 0x0a, 0x40, 0x59,
4675 0x02, 0x0d, 0x0b, 0x40, 0x4d,
4676 0x02, 0x0e, 0x09, 0x20, 0x55,
4677 0x02, 0x0d, 0x0a, 0x20, 0x49,
4678 0x02, 0x0c, 0x0b, 0x20, 0x3d,
4679 0x02, 0x0e, 0x08, 0x10, 0x51,
4680 0x02, 0x0d, 0x09, 0x10, 0x45,
4681 0x02, 0x0c, 0x0a, 0x10, 0x39,
4682 0x02, 0x0d, 0x08, 0x08, 0x41,
4683 0x02, 0x0c, 0x09, 0x08, 0x35,
4684 0x02, 0x0c, 0x08, 0x04, 0x31
4686 static const u8 dramsr13_4
[4 * 5] = {
4687 0x02, 0x0d, 0x09, 0x40, 0x45,
4688 0x02, 0x0c, 0x09, 0x20, 0x35,
4689 0x02, 0x0c, 0x08, 0x10, 0x31,
4690 0x02, 0x0b, 0x08, 0x08, 0x21
4693 /* Enable linear mode, disable 0xa0000 address decoding */
4694 /* We disable a0000 address decoding, because
4695 * - if running on x86, if the card is disabled, it means
4696 * that another card is in the system. We don't want
4697 * to interphere with that primary card's textmode.
4698 * - if running on non-x86, there usually is no VGA window
4701 orSISIDXREG(SISSR
, 0x20, (0x80 | 0x04));
4703 /* Need to map max FB size for finding out about RAM size */
4704 mapsize
= 256 << 20;
4705 sisfb_post_map_vram(ivideo
, &mapsize
, 32);
4707 if(!ivideo
->video_vbase
) {
4708 printk(KERN_ERR
"sisfb: Unable to detect RAM size. Setting default.\n");
4709 outSISIDXREG(SISSR
, 0x13, 0x35);
4710 outSISIDXREG(SISSR
, 0x14, 0x41);
4715 /* Non-interleaving */
4716 outSISIDXREG(SISSR
, 0x15, 0x00);
4718 outSISIDXREG(SISSR
, 0x1c, 0x00);
4720 if(ivideo
->chip
== XGI_20
) {
4723 inSISIDXREG(SISCR
, 0x97, reg
);
4724 if(!(reg
& 0x01)) { /* Single 32/16 */
4726 outSISIDXREG(SISSR
, 0x13, 0xb1);
4727 outSISIDXREG(SISSR
, 0x14, 0x52);
4728 sisfb_post_xgi_delay(ivideo
, 1);
4730 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4733 outSISIDXREG(SISSR
, 0x13, 0x31);
4734 outSISIDXREG(SISSR
, 0x14, 0x42);
4735 sisfb_post_xgi_delay(ivideo
, 1);
4736 if(sisfb_post_xgi_rwtest(ivideo
, 23, 23, mapsize
))
4740 outSISIDXREG(SISSR
, 0x13, 0xb1);
4741 outSISIDXREG(SISSR
, 0x14, 0x41);
4742 sisfb_post_xgi_delay(ivideo
, 1);
4744 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4747 outSISIDXREG(SISSR
, 0x13, 0x31);
4748 } else { /* Dual 16/8 */
4750 outSISIDXREG(SISSR
, 0x13, 0xb1);
4751 outSISIDXREG(SISSR
, 0x14, 0x41);
4752 sisfb_post_xgi_delay(ivideo
, 1);
4754 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4757 outSISIDXREG(SISSR
, 0x13, 0x31);
4758 outSISIDXREG(SISSR
, 0x14, 0x31);
4759 sisfb_post_xgi_delay(ivideo
, 1);
4760 if(sisfb_post_xgi_rwtest(ivideo
, 22, 22, mapsize
))
4764 outSISIDXREG(SISSR
, 0x13, 0xb1);
4765 outSISIDXREG(SISSR
, 0x14, 0x30);
4766 sisfb_post_xgi_delay(ivideo
, 1);
4768 if(sisfb_post_xgi_rwtest(ivideo
, 21, 22, mapsize
))
4771 outSISIDXREG(SISSR
, 0x13, 0x31);
4774 } else { /* XGI_40 */
4776 inSISIDXREG(SISCR
, 0x97, reg
);
4778 inSISIDXREG(SISSR
, 0x39, reg
);
4782 if(reg
& 0x01) { /* DDRII */
4784 if(ivideo
->revision_id
== 2) {
4786 outSISIDXREG(SISSR
, 0x13, 0xa1);
4787 outSISIDXREG(SISSR
, 0x14, 0x44);
4789 sisfb_post_xgi_delay(ivideo
, 1);
4790 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4793 outSISIDXREG(SISSR
, 0x13, 0x21);
4794 outSISIDXREG(SISSR
, 0x14, 0x34);
4795 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4799 outSISIDXREG(SISSR
, 0x13, 0xa1);
4800 outSISIDXREG(SISSR
, 0x14, 0x40);
4802 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4805 outSISIDXREG(SISSR
, 0x13, 0x21);
4806 outSISIDXREG(SISSR
, 0x14, 0x30);
4809 outSISIDXREG(SISSR
, 0x13, 0xa1);
4810 outSISIDXREG(SISSR
, 0x14, 0x4c);
4812 sisfb_post_xgi_delay(ivideo
, 1);
4813 if(sisfb_post_xgi_rwtest(ivideo
, 23, 25, mapsize
))
4817 outSISIDXREG(SISSR
, 0x14, 0x48);
4818 sisfb_post_xgi_delay(ivideo
, 1);
4820 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4823 outSISIDXREG(SISSR
, 0x13, 0x21);
4824 outSISIDXREG(SISSR
, 0x14, 0x3c);
4827 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
)) {
4831 outSISIDXREG(SISSR
, 0x14, 0x38);
4835 sisfb_post_xgi_delay(ivideo
, 1);
4840 if(ivideo
->revision_id
== 2) {
4842 outSISIDXREG(SISSR
, 0x13, 0xa1);
4843 outSISIDXREG(SISSR
, 0x14, 0x52);
4844 sisfb_post_xgi_delay(ivideo
, 1);
4846 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4849 outSISIDXREG(SISSR
, 0x13, 0x21);
4850 outSISIDXREG(SISSR
, 0x14, 0x42);
4853 outSISIDXREG(SISSR
, 0x13, 0xa1);
4854 outSISIDXREG(SISSR
, 0x14, 0x5a);
4855 sisfb_post_xgi_delay(ivideo
, 1);
4857 if(sisfb_post_xgi_rwtest(ivideo
, 24, 25, mapsize
))
4860 outSISIDXREG(SISSR
, 0x13, 0x21);
4861 outSISIDXREG(SISSR
, 0x14, 0x4a);
4863 sisfb_post_xgi_delay(ivideo
, 1);
4869 setSISIDXREG(SISSR
, 0x14, 0xf0, sr14
);
4870 sisfb_post_xgi_delay(ivideo
, 1);
4872 j
= (ivideo
->chip
== XGI_20
) ? 5 : 9;
4873 k
= (ivideo
->chip
== XGI_20
) ? 12 : 4;
4875 for(i
= 0; i
< k
; i
++) {
4877 reg
= (ivideo
->chip
== XGI_20
) ?
4878 dramsr13
[(i
* 5) + 4] : dramsr13_4
[(i
* 5) + 4];
4879 setSISIDXREG(SISSR
, 0x13, 0x80, reg
);
4880 sisfb_post_xgi_delay(ivideo
, 50);
4882 ranksize
= (ivideo
->chip
== XGI_20
) ?
4883 dramsr13
[(i
* 5) + 3] : dramsr13_4
[(i
* 5) + 3];
4885 inSISIDXREG(SISSR
, 0x13, reg
);
4886 if(reg
& 0x80) ranksize
<<= 1;
4888 if(ivideo
->chip
== XGI_20
) {
4889 if(buswidth
== 16) ranksize
<<= 1;
4890 else if(buswidth
== 32) ranksize
<<= 2;
4892 if(buswidth
== 64) ranksize
<<= 1;
4898 if((ranksize
* l
) <= 256) {
4899 while((ranksize
>>= 1)) reg
+= 0x10;
4904 setSISIDXREG(SISSR
, 0x14, 0x0f, (reg
& 0xf0));
4905 sisfb_post_xgi_delay(ivideo
, 1);
4907 if(sisfb_post_xgi_rwtest(ivideo
, j
, ((reg
>> 4) + channelab
- 2 + 20), mapsize
))
4911 iounmap(ivideo
->video_vbase
);
4914 static void __devinit
4915 sisfb_post_xgi_setclocks(struct sis_video_info
*ivideo
, u8 regb
)
4919 static const u8 cs90
[8 * 3] = {
4929 static const u8 csb8
[8 * 3] = {
4943 v1
= cs90
[index
]; v2
= cs90
[index
+ 1]; v3
= cs90
[index
+ 2];
4944 if(ivideo
->haveXGIROM
) {
4945 v1
= ivideo
->bios_abase
[0x90 + index
];
4946 v2
= ivideo
->bios_abase
[0x90 + index
+ 1];
4947 v3
= ivideo
->bios_abase
[0x90 + index
+ 2];
4949 outSISIDXREG(SISSR
, 0x28, v1
);
4950 outSISIDXREG(SISSR
, 0x29, v2
);
4951 outSISIDXREG(SISSR
, 0x2a, v3
);
4952 sisfb_post_xgi_delay(ivideo
, 0x43);
4953 sisfb_post_xgi_delay(ivideo
, 0x43);
4954 sisfb_post_xgi_delay(ivideo
, 0x43);
4956 v1
= csb8
[index
]; v2
= csb8
[index
+ 1]; v3
= csb8
[index
+ 2];
4957 if(ivideo
->haveXGIROM
) {
4958 v1
= ivideo
->bios_abase
[0xb8 + index
];
4959 v2
= ivideo
->bios_abase
[0xb8 + index
+ 1];
4960 v3
= ivideo
->bios_abase
[0xb8 + index
+ 2];
4962 outSISIDXREG(SISSR
, 0x2e, v1
);
4963 outSISIDXREG(SISSR
, 0x2f, v2
);
4964 outSISIDXREG(SISSR
, 0x30, v3
);
4965 sisfb_post_xgi_delay(ivideo
, 0x43);
4966 sisfb_post_xgi_delay(ivideo
, 0x43);
4967 sisfb_post_xgi_delay(ivideo
, 0x43);
4970 static int __devinit
4971 sisfb_post_xgi(struct pci_dev
*pdev
)
4973 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4974 unsigned char *bios
= ivideo
->bios_abase
;
4975 struct pci_dev
*mypdev
= NULL
;
4976 const u8
*ptr
, *ptr2
;
4977 u8 v1
, v2
, v3
, v4
, v5
, reg
, ramtype
;
4978 u32 rega
, regb
, regd
;
4980 static const u8 cs78
[3] = { 0xf6, 0x0d, 0x00 };
4981 static const u8 cs76
[2] = { 0xa3, 0xfb };
4982 static const u8 cs7b
[3] = { 0xc0, 0x11, 0x00 };
4983 static const u8 cs158
[8] = {
4984 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
4986 static const u8 cs160
[8] = {
4987 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
4989 static const u8 cs168
[8] = {
4990 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
4992 static const u8 cs128
[3 * 8] = {
4993 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
4994 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
4995 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
4997 static const u8 cs148
[2 * 8] = {
4998 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
4999 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5001 static const u8 cs31a
[8 * 4] = {
5002 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
5003 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
5004 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5005 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5007 static const u8 cs33a
[8 * 4] = {
5008 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5009 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5010 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5011 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5013 static const u8 cs45a
[8 * 2] = {
5014 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
5015 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5017 static const u8 cs170
[7 * 8] = {
5018 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5019 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5020 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
5021 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5022 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5023 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5024 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5026 static const u8 cs1a8
[3 * 8] = {
5027 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5028 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5029 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5031 static const u8 cs100
[2 * 8] = {
5032 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5033 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5037 reg
= inSISREG(SISVGAENABLE
) | 0x01;
5038 outSISREG(SISVGAENABLE
, reg
);
5041 reg
= inSISREG(SISMISCR
) | 0x01;
5042 outSISREG(SISMISCW
, reg
);
5045 outSISIDXREG(SISSR
, 0x05, 0x86);
5046 inSISIDXREG(SISSR
, 0x05, reg
);
5050 /* Clear some regs */
5051 for(i
= 0; i
< 0x22; i
++) {
5052 if(0x06 + i
== 0x20) continue;
5053 outSISIDXREG(SISSR
, 0x06 + i
, 0x00);
5055 for(i
= 0; i
< 0x0b; i
++) {
5056 outSISIDXREG(SISSR
, 0x31 + i
, 0x00);
5058 for(i
= 0; i
< 0x10; i
++) {
5059 outSISIDXREG(SISCR
, 0x30 + i
, 0x00);
5063 if(ivideo
->haveXGIROM
) {
5064 ptr
= (const u8
*)&bios
[0x78];
5066 for(i
= 0; i
< 3; i
++) {
5067 outSISIDXREG(SISSR
, 0x23 + i
, ptr
[i
]);
5071 if(ivideo
->haveXGIROM
) {
5072 ptr
= (const u8
*)&bios
[0x76];
5074 for(i
= 0; i
< 2; i
++) {
5075 outSISIDXREG(SISSR
, 0x21 + i
, ptr
[i
]);
5078 v1
= 0x18; v2
= 0x00;
5079 if(ivideo
->haveXGIROM
) {
5083 outSISIDXREG(SISSR
, 0x07, v1
);
5084 outSISIDXREG(SISSR
, 0x11, 0x0f);
5085 outSISIDXREG(SISSR
, 0x1f, v2
);
5086 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5087 outSISIDXREG(SISSR
, 0x20, 0x80 | 0x20 | 0x04);
5088 outSISIDXREG(SISSR
, 0x27, 0x74);
5091 if(ivideo
->haveXGIROM
) {
5092 ptr
= (const u8
*)&bios
[0x7b];
5094 for(i
= 0; i
< 3; i
++) {
5095 outSISIDXREG(SISSR
, 0x31 + i
, ptr
[i
]);
5098 if(ivideo
->chip
== XGI_40
) {
5099 if(ivideo
->revision_id
== 2) {
5100 setSISIDXREG(SISSR
, 0x3b, 0x3f, 0xc0);
5102 outSISIDXREG(SISCR
, 0x7d, 0xfe);
5103 outSISIDXREG(SISCR
, 0x7e, 0x0f);
5105 if(ivideo
->revision_id
== 0) { /* 40 *and* 20? */
5106 andSISIDXREG(SISCR
, 0x58, 0xd7);
5107 inSISIDXREG(SISCR
, 0xcb, reg
);
5109 setSISIDXREG(SISCR
, 0x58, 0xd7, (reg
& 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5113 reg
= (ivideo
->chip
== XGI_40
) ? 0x20 : 0x00;
5114 setSISIDXREG(SISCR
, 0x38, 0x1f, reg
);
5116 if(ivideo
->chip
== XGI_20
) {
5117 outSISIDXREG(SISSR
, 0x36, 0x70);
5119 outSISIDXREG(SISVID
, 0x00, 0x86);
5120 outSISIDXREG(SISVID
, 0x32, 0x00);
5121 outSISIDXREG(SISVID
, 0x30, 0x00);
5122 outSISIDXREG(SISVID
, 0x32, 0x01);
5123 outSISIDXREG(SISVID
, 0x30, 0x00);
5124 andSISIDXREG(SISVID
, 0x2f, 0xdf);
5125 andSISIDXREG(SISCAP
, 0x00, 0x3f);
5127 outSISIDXREG(SISPART1
, 0x2f, 0x01);
5128 outSISIDXREG(SISPART1
, 0x00, 0x00);
5129 outSISIDXREG(SISPART1
, 0x02, bios
[0x7e]);
5130 outSISIDXREG(SISPART1
, 0x2e, 0x08);
5131 andSISIDXREG(SISPART1
, 0x35, 0x7f);
5132 andSISIDXREG(SISPART1
, 0x50, 0xfe);
5134 inSISIDXREG(SISPART4
, 0x00, reg
);
5135 if(reg
== 1 || reg
== 2) {
5136 outSISIDXREG(SISPART2
, 0x00, 0x1c);
5137 outSISIDXREG(SISPART4
, 0x0d, bios
[0x7f]);
5138 outSISIDXREG(SISPART4
, 0x0e, bios
[0x80]);
5139 outSISIDXREG(SISPART4
, 0x10, bios
[0x81]);
5140 andSISIDXREG(SISPART4
, 0x0f, 0x3f);
5142 inSISIDXREG(SISPART4
, 0x01, reg
);
5143 if((reg
& 0xf0) >= 0xb0) {
5144 inSISIDXREG(SISPART4
, 0x23, reg
);
5145 if(reg
& 0x20) reg
|= 0x40;
5146 outSISIDXREG(SISPART4
, 0x23, reg
);
5147 reg
= (reg
& 0x20) ? 0x02 : 0x00;
5148 setSISIDXREG(SISPART1
, 0x1e, 0xfd, reg
);
5154 inSISIDXREG(SISSR
, 0x3b, reg
);
5156 inSISIDXREG(SISSR
, 0x3a, reg
);
5157 v2
= (reg
& 0x30) >> 3;
5158 if(!(v2
& 0x04)) v2
^= 0x02;
5159 inSISIDXREG(SISSR
, 0x39, reg
);
5160 if(reg
& 0x80) v2
|= 0x80;
5163 if((mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0730, NULL
))) {
5164 pci_dev_put(mypdev
);
5165 if(((v2
& 0x06) == 2) || ((v2
& 0x06) == 4))
5170 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0735, NULL
);
5172 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0645, NULL
);
5174 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0650, NULL
);
5176 pci_read_config_dword(mypdev
, 0x94, ®d
);
5178 pci_write_config_dword(mypdev
, 0x94, regd
);
5180 pci_dev_put(mypdev
);
5181 } else if(sisfb_find_host_bridge(ivideo
, pdev
, PCI_VENDOR_ID_SI
)) {
5183 } else if(sisfb_find_host_bridge(ivideo
, pdev
, 0x1106) ||
5184 sisfb_find_host_bridge(ivideo
, pdev
, 0x1022) ||
5185 sisfb_find_host_bridge(ivideo
, pdev
, 0x700e) ||
5186 sisfb_find_host_bridge(ivideo
, pdev
, 0x10de)) {
5187 if((v2
& 0x06) == 4)
5192 setSISIDXREG(SISCR
, 0x5f, 0xf0, v2
);
5194 outSISIDXREG(SISSR
, 0x22, v1
);
5196 if(ivideo
->revision_id
== 2) {
5197 inSISIDXREG(SISSR
, 0x3b, v1
);
5198 inSISIDXREG(SISSR
, 0x3a, v2
);
5199 regd
= bios
[0x90 + 3] | (bios
[0x90 + 4] << 8);
5200 if( (!(v1
& 0x02)) && (v2
& 0x30) && (regd
< 0xcf) )
5201 setSISIDXREG(SISCR
, 0x5f, 0xf1, 0x01);
5203 if((mypdev
= pci_get_device(0x10de, 0x01e0, NULL
))) {
5204 /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5208 setSISIDXREG(SISCR
, 0x5f, 0xf1, 0x01);
5209 pci_dev_put(mypdev
);
5214 inSISIDXREG(SISSR
, 0x3b, reg
);
5215 inSISIDXREG(SISCR
, 0x5f, v2
);
5216 if((!(reg
& 0x02)) && (v2
& 0x0e))
5218 outSISIDXREG(SISSR
, 0x27, v1
);
5220 if(bios
[0x64] & 0x01) {
5221 setSISIDXREG(SISCR
, 0x5f, 0xf0, bios
[0x64]);
5225 pci_read_config_dword(pdev
, 0x50, ®d
);
5226 regd
= (regd
>> 20) & 0x0f;
5229 orSISIDXREG(SISCR
, 0x5f, 0x08);
5231 outSISIDXREG(SISCR
, 0x48, v1
);
5233 setSISIDXREG(SISCR
, 0x47, 0x04, bios
[0x4f6] & 0xfb);
5234 setSISIDXREG(SISCR
, 0x49, 0xf0, bios
[0x4f8] & 0x0f);
5235 setSISIDXREG(SISCR
, 0x4a, 0x60, bios
[0x4f9] & 0x9f);
5236 setSISIDXREG(SISCR
, 0x4b, 0x08, bios
[0x4fa] & 0xf7);
5237 setSISIDXREG(SISCR
, 0x4c, 0x80, bios
[0x4fb] & 0x7f);
5238 outSISIDXREG(SISCR
, 0x70, bios
[0x4fc]);
5239 setSISIDXREG(SISCR
, 0x71, 0xf0, bios
[0x4fd] & 0x0f);
5240 outSISIDXREG(SISCR
, 0x74, 0xd0);
5241 setSISIDXREG(SISCR
, 0x74, 0xcf, bios
[0x4fe] & 0x30);
5242 setSISIDXREG(SISCR
, 0x75, 0xe0, bios
[0x4ff] & 0x1f);
5243 setSISIDXREG(SISCR
, 0x76, 0xe0, bios
[0x500] & 0x1f);
5245 if((mypdev
= pci_get_device(0x8086, 0x2530, NULL
))) {
5247 pci_dev_put(mypdev
);
5249 outSISIDXREG(SISCR
, 0x77, v1
);
5257 if(ivideo
->haveXGIROM
) {
5258 v1
= bios
[0x140 + regb
];
5260 outSISIDXREG(SISCR
, 0x6d, v1
);
5263 if(ivideo
->haveXGIROM
) {
5264 ptr
= (const u8
*)&bios
[0x128];
5266 for(i
= 0, j
= 0; i
< 3; i
++, j
+= 8) {
5267 outSISIDXREG(SISCR
, 0x68 + i
, ptr
[j
+ regb
]);
5272 if(ivideo
->haveXGIROM
) {
5273 index
= (ivideo
->chip
== XGI_20
) ? 0x31a : 0x3a6;
5274 ptr
= (const u8
*)&bios
[index
];
5275 ptr2
= (const u8
*)&bios
[index
+ 0x20];
5277 for(i
= 0; i
< 2; i
++) {
5279 regd
= le32_to_cpu(((u32
*)ptr
)[regb
]);
5282 regd
= le32_to_cpu(((u32
*)ptr2
)[regb
]);
5286 for(j
= 0; j
< 16; j
++) {
5288 if(regd
& 0x01) reg
|= 0x04;
5289 if(regd
& 0x02) reg
|= 0x08;
5291 outSISIDXREG(SISCR
, rega
, reg
);
5292 inSISIDXREG(SISCR
, rega
, reg
);
5293 inSISIDXREG(SISCR
, rega
, reg
);
5298 andSISIDXREG(SISCR
, 0x6e, 0xfc);
5301 if(ivideo
->haveXGIROM
) {
5302 index
= (ivideo
->chip
== XGI_20
) ? 0x35a : 0x3e6;
5303 ptr
= (const u8
*)&bios
[index
];
5305 for(i
= 0; i
< 4; i
++) {
5306 setSISIDXREG(SISCR
, 0x6e, 0xfc, i
);
5308 for(j
= 0; j
< 2; j
++) {
5311 regd
= le32_to_cpu(((u32
*)ptr
)[regb
* 8]);
5315 for(k
= 0; k
< 16; k
++) {
5317 if(regd
& 0x01) reg
|= 0x01;
5318 if(regd
& 0x02) reg
|= 0x02;
5320 outSISIDXREG(SISCR
, 0x6f, reg
);
5321 inSISIDXREG(SISCR
, 0x6f, reg
);
5322 inSISIDXREG(SISCR
, 0x6f, reg
);
5329 if(ivideo
->haveXGIROM
) {
5330 ptr
= (const u8
*)&bios
[0x148];
5332 for(i
= 0, j
= 0; i
< 2; i
++, j
+= 8) {
5333 outSISIDXREG(SISCR
, 0x80 + i
, ptr
[j
+ regb
]);
5336 andSISIDXREG(SISCR
, 0x89, 0x8f);
5339 if(ivideo
->haveXGIROM
) {
5340 index
= (ivideo
->chip
== XGI_20
) ? 0x45a : 0x4e6;
5341 ptr
= (const u8
*)&bios
[index
];
5343 regd
= le16_to_cpu(((const u16
*)ptr
)[regb
]);
5345 for(i
= 0; i
< 5; i
++) {
5347 if(regd
& 0x01) reg
|= 0x01;
5348 if(regd
& 0x02) reg
|= 0x02;
5350 outSISIDXREG(SISCR
, 0x89, reg
);
5351 inSISIDXREG(SISCR
, 0x89, reg
);
5352 inSISIDXREG(SISCR
, 0x89, reg
);
5356 v1
= 0xb5; v2
= 0x20; v3
= 0xf0; v4
= 0x13;
5357 if(ivideo
->haveXGIROM
) {
5358 v1
= bios
[0x118 + regb
];
5359 v2
= bios
[0xf8 + regb
];
5360 v3
= bios
[0x120 + regb
];
5363 outSISIDXREG(SISCR
, 0x45, v1
& 0x0f);
5364 outSISIDXREG(SISCR
, 0x99, (v1
>> 4) & 0x07);
5365 orSISIDXREG(SISCR
, 0x40, v1
& 0x80);
5366 outSISIDXREG(SISCR
, 0x41, v2
);
5369 if(ivideo
->haveXGIROM
) {
5370 ptr
= (const u8
*)&bios
[0x170];
5372 for(i
= 0, j
= 0; i
< 7; i
++, j
+= 8) {
5373 outSISIDXREG(SISCR
, 0x90 + i
, ptr
[j
+ regb
]);
5376 outSISIDXREG(SISCR
, 0x59, v3
);
5379 if(ivideo
->haveXGIROM
) {
5380 ptr
= (const u8
*)&bios
[0x1a8];
5382 for(i
= 0, j
= 0; i
< 3; i
++, j
+= 8) {
5383 outSISIDXREG(SISCR
, 0xc3 + i
, ptr
[j
+ regb
]);
5387 if(ivideo
->haveXGIROM
) {
5388 ptr
= (const u8
*)&bios
[0x100];
5390 for(i
= 0, j
= 0; i
< 2; i
++, j
+= 8) {
5391 outSISIDXREG(SISCR
, 0x8a + i
, ptr
[j
+ regb
]);
5394 outSISIDXREG(SISCR
, 0xcf, v4
);
5396 outSISIDXREG(SISCR
, 0x83, 0x09);
5397 outSISIDXREG(SISCR
, 0x87, 0x00);
5399 if(ivideo
->chip
== XGI_40
) {
5400 if( (ivideo
->revision_id
== 1) ||
5401 (ivideo
->revision_id
== 2) ) {
5402 outSISIDXREG(SISCR
, 0x8c, 0x87);
5406 outSISIDXREG(SISSR
, 0x17, 0x00);
5407 outSISIDXREG(SISSR
, 0x1a, 0x87);
5409 if(ivideo
->chip
== XGI_20
) {
5410 outSISIDXREG(SISSR
, 0x15, 0x00);
5411 outSISIDXREG(SISSR
, 0x1c, 0x00);
5414 ramtype
= 0x00; v1
= 0x10;
5415 if(ivideo
->haveXGIROM
) {
5416 ramtype
= bios
[0x62];
5419 if(!(ramtype
& 0x80)) {
5420 if(ivideo
->chip
== XGI_20
) {
5421 outSISIDXREG(SISCR
, 0x97, v1
);
5422 inSISIDXREG(SISCR
, 0x97, reg
);
5424 ramtype
= (reg
& 0x01) << 1;
5427 inSISIDXREG(SISSR
, 0x39, reg
);
5428 ramtype
= reg
& 0x02;
5430 inSISIDXREG(SISSR
, 0x3a, reg
);
5431 ramtype
= (reg
>> 1) & 0x01;
5441 sisfb_post_xgi_setclocks(ivideo
, regb
);
5442 if((ivideo
->chip
== XGI_20
) ||
5443 (ivideo
->revision_id
== 1) ||
5444 (ivideo
->revision_id
== 2)) {
5445 v1
= cs158
[regb
]; v2
= cs160
[regb
]; v3
= cs168
[regb
];
5446 if(ivideo
->haveXGIROM
) {
5447 v1
= bios
[regb
+ 0x158];
5448 v2
= bios
[regb
+ 0x160];
5449 v3
= bios
[regb
+ 0x168];
5451 outSISIDXREG(SISCR
, 0x82, v1
);
5452 outSISIDXREG(SISCR
, 0x85, v2
);
5453 outSISIDXREG(SISCR
, 0x86, v3
);
5455 outSISIDXREG(SISCR
, 0x82, 0x88);
5456 outSISIDXREG(SISCR
, 0x86, 0x00);
5457 inSISIDXREG(SISCR
, 0x86, reg
);
5458 outSISIDXREG(SISCR
, 0x86, 0x88);
5459 inSISIDXREG(SISCR
, 0x86, reg
);
5460 outSISIDXREG(SISCR
, 0x86, bios
[regb
+ 0x168]);
5461 outSISIDXREG(SISCR
, 0x82, 0x77);
5462 outSISIDXREG(SISCR
, 0x85, 0x00);
5463 inSISIDXREG(SISCR
, 0x85, reg
);
5464 outSISIDXREG(SISCR
, 0x85, 0x88);
5465 inSISIDXREG(SISCR
, 0x85, reg
);
5466 outSISIDXREG(SISCR
, 0x85, bios
[regb
+ 0x160]);
5467 outSISIDXREG(SISCR
, 0x82, bios
[regb
+ 0x158]);
5469 if(ivideo
->chip
== XGI_40
) {
5470 outSISIDXREG(SISCR
, 0x97, 0x00);
5472 outSISIDXREG(SISCR
, 0x98, 0x01);
5473 outSISIDXREG(SISCR
, 0x9a, 0x02);
5475 outSISIDXREG(SISSR
, 0x18, 0x01);
5476 if((ivideo
->chip
== XGI_20
) ||
5477 (ivideo
->revision_id
== 2)) {
5478 outSISIDXREG(SISSR
, 0x19, 0x40);
5480 outSISIDXREG(SISSR
, 0x19, 0x20);
5482 outSISIDXREG(SISSR
, 0x16, 0x00);
5483 outSISIDXREG(SISSR
, 0x16, 0x80);
5484 if((ivideo
->chip
== XGI_20
) || (bios
[0x1cb] != 0x0c)) {
5485 sisfb_post_xgi_delay(ivideo
, 0x43);
5486 sisfb_post_xgi_delay(ivideo
, 0x43);
5487 sisfb_post_xgi_delay(ivideo
, 0x43);
5488 outSISIDXREG(SISSR
, 0x18, 0x00);
5489 if((ivideo
->chip
== XGI_20
) ||
5490 (ivideo
->revision_id
== 2)) {
5491 outSISIDXREG(SISSR
, 0x19, 0x40);
5493 outSISIDXREG(SISSR
, 0x19, 0x20);
5495 } else if((ivideo
->chip
== XGI_40
) && (bios
[0x1cb] == 0x0c)) {
5496 /* outSISIDXREG(SISSR, 0x16, 0x0c); */ /* ? */
5498 outSISIDXREG(SISSR
, 0x16, 0x00);
5499 outSISIDXREG(SISSR
, 0x16, 0x80);
5500 sisfb_post_xgi_delay(ivideo
, 4);
5501 v1
= 0x31; v2
= 0x03; v3
= 0x83; v4
= 0x03; v5
= 0x83;
5502 if(ivideo
->haveXGIROM
) {
5504 index
= (ivideo
->chip
== XGI_20
) ? 0x4b2 : 0x53e;
5506 v3
= bios
[index
+ 1];
5507 v4
= bios
[index
+ 2];
5508 v5
= bios
[index
+ 3];
5510 outSISIDXREG(SISSR
, 0x18, v1
);
5511 outSISIDXREG(SISSR
, 0x19, ((ivideo
->chip
== XGI_20
) ? 0x02 : 0x01));
5512 outSISIDXREG(SISSR
, 0x16, v2
);
5513 outSISIDXREG(SISSR
, 0x16, v3
);
5514 sisfb_post_xgi_delay(ivideo
, 0x43);
5515 outSISIDXREG(SISSR
, 0x1b, 0x03);
5516 sisfb_post_xgi_delay(ivideo
, 0x22);
5517 outSISIDXREG(SISSR
, 0x18, v1
);
5518 outSISIDXREG(SISSR
, 0x19, 0x00);
5519 outSISIDXREG(SISSR
, 0x16, v4
);
5520 outSISIDXREG(SISSR
, 0x16, v5
);
5521 outSISIDXREG(SISSR
, 0x1b, 0x00);
5524 outSISIDXREG(SISCR
, 0x82, 0x77);
5525 outSISIDXREG(SISCR
, 0x86, 0x00);
5526 inSISIDXREG(SISCR
, 0x86, reg
);
5527 outSISIDXREG(SISCR
, 0x86, 0x88);
5528 inSISIDXREG(SISCR
, 0x86, reg
);
5529 v1
= cs168
[regb
]; v2
= cs160
[regb
]; v3
= cs158
[regb
];
5530 if(ivideo
->haveXGIROM
) {
5531 v1
= bios
[regb
+ 0x168];
5532 v2
= bios
[regb
+ 0x160];
5533 v3
= bios
[regb
+ 0x158];
5535 outSISIDXREG(SISCR
, 0x86, v1
);
5536 outSISIDXREG(SISCR
, 0x82, 0x77);
5537 outSISIDXREG(SISCR
, 0x85, 0x00);
5538 inSISIDXREG(SISCR
, 0x85, reg
);
5539 outSISIDXREG(SISCR
, 0x85, 0x88);
5540 inSISIDXREG(SISCR
, 0x85, reg
);
5541 outSISIDXREG(SISCR
, 0x85, v2
);
5542 outSISIDXREG(SISCR
, 0x82, v3
);
5543 outSISIDXREG(SISCR
, 0x98, 0x01);
5544 outSISIDXREG(SISCR
, 0x9a, 0x02);
5546 outSISIDXREG(SISSR
, 0x28, 0x64);
5547 outSISIDXREG(SISSR
, 0x29, 0x63);
5548 sisfb_post_xgi_delay(ivideo
, 15);
5549 outSISIDXREG(SISSR
, 0x18, 0x00);
5550 outSISIDXREG(SISSR
, 0x19, 0x20);
5551 outSISIDXREG(SISSR
, 0x16, 0x00);
5552 outSISIDXREG(SISSR
, 0x16, 0x80);
5553 outSISIDXREG(SISSR
, 0x18, 0xc5);
5554 outSISIDXREG(SISSR
, 0x19, 0x23);
5555 outSISIDXREG(SISSR
, 0x16, 0x00);
5556 outSISIDXREG(SISSR
, 0x16, 0x80);
5557 sisfb_post_xgi_delay(ivideo
, 1);
5558 outSISIDXREG(SISCR
, 0x97,0x11);
5559 sisfb_post_xgi_setclocks(ivideo
, regb
);
5560 sisfb_post_xgi_delay(ivideo
, 0x46);
5561 outSISIDXREG(SISSR
, 0x18, 0xc5);
5562 outSISIDXREG(SISSR
, 0x19, 0x23);
5563 outSISIDXREG(SISSR
, 0x16, 0x00);
5564 outSISIDXREG(SISSR
, 0x16, 0x80);
5565 sisfb_post_xgi_delay(ivideo
, 1);
5566 outSISIDXREG(SISSR
, 0x1b, 0x04);
5567 sisfb_post_xgi_delay(ivideo
, 1);
5568 outSISIDXREG(SISSR
, 0x1b, 0x00);
5569 sisfb_post_xgi_delay(ivideo
, 1);
5571 if(ivideo
->haveXGIROM
) {
5574 outSISIDXREG(SISSR
, 0x18, v1
);
5575 outSISIDXREG(SISSR
, 0x19, 0x06);
5576 outSISIDXREG(SISSR
, 0x16, 0x04);
5577 outSISIDXREG(SISSR
, 0x16, 0x84);
5578 sisfb_post_xgi_delay(ivideo
, 1);
5581 sisfb_post_xgi_setclocks(ivideo
, regb
);
5582 if((ivideo
->chip
== XGI_40
) &&
5583 ((ivideo
->revision_id
== 1) ||
5584 (ivideo
->revision_id
== 2))) {
5585 outSISIDXREG(SISCR
, 0x82, bios
[regb
+ 0x158]);
5586 outSISIDXREG(SISCR
, 0x85, bios
[regb
+ 0x160]);
5587 outSISIDXREG(SISCR
, 0x86, bios
[regb
+ 0x168]);
5589 outSISIDXREG(SISCR
, 0x82, 0x88);
5590 outSISIDXREG(SISCR
, 0x86, 0x00);
5591 inSISIDXREG(SISCR
, 0x86, reg
);
5592 outSISIDXREG(SISCR
, 0x86, 0x88);
5593 outSISIDXREG(SISCR
, 0x82, 0x77);
5594 outSISIDXREG(SISCR
, 0x85, 0x00);
5595 inSISIDXREG(SISCR
, 0x85, reg
);
5596 outSISIDXREG(SISCR
, 0x85, 0x88);
5597 inSISIDXREG(SISCR
, 0x85, reg
);
5598 v1
= cs160
[regb
]; v2
= cs158
[regb
];
5599 if(ivideo
->haveXGIROM
) {
5600 v1
= bios
[regb
+ 0x160];
5601 v2
= bios
[regb
+ 0x158];
5603 outSISIDXREG(SISCR
, 0x85, v1
);
5604 outSISIDXREG(SISCR
, 0x82, v2
);
5606 if(ivideo
->chip
== XGI_40
) {
5607 outSISIDXREG(SISCR
, 0x97, 0x11);
5609 if((ivideo
->chip
== XGI_40
) && (ivideo
->revision_id
== 2)) {
5610 outSISIDXREG(SISCR
, 0x98, 0x01);
5612 outSISIDXREG(SISCR
, 0x98, 0x03);
5614 outSISIDXREG(SISCR
, 0x9a, 0x02);
5616 if(ivideo
->chip
== XGI_40
) {
5617 outSISIDXREG(SISSR
, 0x18, 0x01);
5619 outSISIDXREG(SISSR
, 0x18, 0x00);
5621 outSISIDXREG(SISSR
, 0x19, 0x40);
5622 outSISIDXREG(SISSR
, 0x16, 0x00);
5623 outSISIDXREG(SISSR
, 0x16, 0x80);
5624 if((ivideo
->chip
== XGI_40
) && (bios
[0x1cb] != 0x0c)) {
5625 sisfb_post_xgi_delay(ivideo
, 0x43);
5626 sisfb_post_xgi_delay(ivideo
, 0x43);
5627 sisfb_post_xgi_delay(ivideo
, 0x43);
5628 outSISIDXREG(SISSR
, 0x18, 0x00);
5629 outSISIDXREG(SISSR
, 0x19, 0x40);
5630 outSISIDXREG(SISSR
, 0x16, 0x00);
5631 outSISIDXREG(SISSR
, 0x16, 0x80);
5633 sisfb_post_xgi_delay(ivideo
, 4);
5635 if(ivideo
->haveXGIROM
) {
5638 outSISIDXREG(SISSR
, 0x18, v1
);
5639 outSISIDXREG(SISSR
, 0x19, 0x01);
5640 if(ivideo
->chip
== XGI_40
) {
5641 outSISIDXREG(SISSR
, 0x16, bios
[0x53e]);
5642 outSISIDXREG(SISSR
, 0x16, bios
[0x53f]);
5644 outSISIDXREG(SISSR
, 0x16, 0x05);
5645 outSISIDXREG(SISSR
, 0x16, 0x85);
5647 sisfb_post_xgi_delay(ivideo
, 0x43);
5648 if(ivideo
->chip
== XGI_40
) {
5649 outSISIDXREG(SISSR
, 0x1b, 0x01);
5651 outSISIDXREG(SISSR
, 0x1b, 0x03);
5653 sisfb_post_xgi_delay(ivideo
, 0x22);
5654 outSISIDXREG(SISSR
, 0x18, v1
);
5655 outSISIDXREG(SISSR
, 0x19, 0x00);
5656 if(ivideo
->chip
== XGI_40
) {
5657 outSISIDXREG(SISSR
, 0x16, bios
[0x540]);
5658 outSISIDXREG(SISSR
, 0x16, bios
[0x541]);
5660 outSISIDXREG(SISSR
, 0x16, 0x05);
5661 outSISIDXREG(SISSR
, 0x16, 0x85);
5663 outSISIDXREG(SISSR
, 0x1b, 0x00);
5668 if(ivideo
->haveXGIROM
) {
5669 v1
= bios
[0x110 + regb
];
5671 outSISIDXREG(SISSR
, 0x1b, v1
);
5674 v1
= 0x00; v2
= 0x00;
5675 if(ivideo
->haveXGIROM
) {
5681 if((v1
& 0x40) && (v2
& regd
) && ivideo
->haveXGIROM
) {
5683 outSISIDXREG(SISSR
, 0x13, bios
[regb
+ 0xe0]);
5684 outSISIDXREG(SISSR
, 0x14, bios
[regb
+ 0xe0 + 8]);
5688 /* Set default mode, don't clear screen */
5689 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
5690 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
5691 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
5692 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
5693 ivideo
->SiS_Pr
.VideoMemorySize
= 8 << 20;
5694 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
5696 outSISIDXREG(SISSR
, 0x05, 0x86);
5698 /* Disable read-cache */
5699 andSISIDXREG(SISSR
, 0x21, 0xdf);
5700 sisfb_post_xgi_ramsize(ivideo
);
5701 /* Enable read-cache */
5702 orSISIDXREG(SISSR
, 0x21, 0x20);
5707 printk(KERN_DEBUG
"-----------------\n");
5708 for(i
= 0; i
< 0xff; i
++) {
5709 inSISIDXREG(SISCR
, i
, reg
);
5710 printk(KERN_DEBUG
"CR%02x(%x) = 0x%02x\n", i
, SISCR
, reg
);
5712 for(i
= 0; i
< 0x40; i
++) {
5713 inSISIDXREG(SISSR
, i
, reg
);
5714 printk(KERN_DEBUG
"SR%02x(%x) = 0x%02x\n", i
, SISSR
, reg
);
5716 printk(KERN_DEBUG
"-----------------\n");
5720 if(ivideo
->chip
== XGI_20
) {
5721 orSISIDXREG(SISCR
, 0x32, 0x20);
5723 inSISIDXREG(SISPART4
, 0x00, reg
);
5724 if((reg
== 1) || (reg
== 2)) {
5725 sisfb_sense_crt1(ivideo
);
5727 orSISIDXREG(SISCR
, 0x32, 0x20);
5731 /* Set default mode, don't clear screen */
5732 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
5733 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
5734 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
5735 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
5736 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
5738 outSISIDXREG(SISSR
, 0x05, 0x86);
5741 orSISIDXREG(SISSR
, 0x01, 0x20);
5743 /* Save mode number in CR34 */
5744 outSISIDXREG(SISCR
, 0x34, 0x2e);
5746 /* Let everyone know what the current mode is */
5747 ivideo
->modeprechange
= 0x2e;
5749 if(ivideo
->chip
== XGI_40
) {
5750 inSISIDXREG(SISCR
, 0xca, reg
);
5751 inSISIDXREG(SISCR
, 0xcc, v1
);
5752 if((reg
& 0x10) && (!(v1
& 0x04))) {
5754 "sisfb: Please connect power to the card.\n");
5763 static int __devinit
5764 sisfb_probe(struct pci_dev
*pdev
, const struct pci_device_id
*ent
)
5766 struct sisfb_chip_info
*chipinfo
= &sisfb_chip_info
[ent
->driver_data
];
5767 struct sis_video_info
*ivideo
= NULL
;
5768 struct fb_info
*sis_fb_info
= NULL
;
5776 sis_fb_info
= framebuffer_alloc(sizeof(*ivideo
), &pdev
->dev
);
5780 ivideo
= (struct sis_video_info
*)sis_fb_info
->par
;
5781 ivideo
->memyselfandi
= sis_fb_info
;
5783 ivideo
->sisfb_id
= SISFB_ID
;
5785 if(card_list
== NULL
) {
5786 ivideo
->cardnumber
= 0;
5788 struct sis_video_info
*countvideo
= card_list
;
5789 ivideo
->cardnumber
= 1;
5790 while((countvideo
= countvideo
->next
) != 0)
5791 ivideo
->cardnumber
++;
5794 strncpy(ivideo
->myid
, chipinfo
->chip_name
, 30);
5796 ivideo
->warncount
= 0;
5797 ivideo
->chip_id
= pdev
->device
;
5798 ivideo
->chip_vendor
= pdev
->vendor
;
5799 ivideo
->revision_id
= pdev
->revision
;
5800 ivideo
->SiS_Pr
.ChipRevision
= ivideo
->revision_id
;
5801 pci_read_config_word(pdev
, PCI_COMMAND
, ®16
);
5802 ivideo
->sisvga_enabled
= reg16
& 0x01;
5803 ivideo
->pcibus
= pdev
->bus
->number
;
5804 ivideo
->pcislot
= PCI_SLOT(pdev
->devfn
);
5805 ivideo
->pcifunc
= PCI_FUNC(pdev
->devfn
);
5806 ivideo
->subsysvendor
= pdev
->subsystem_vendor
;
5807 ivideo
->subsysdevice
= pdev
->subsystem_device
;
5810 if(sisfb_mode_idx
== -1) {
5811 sisfb_get_vga_mode_from_kernel();
5815 ivideo
->chip
= chipinfo
->chip
;
5816 ivideo
->sisvga_engine
= chipinfo
->vgaengine
;
5817 ivideo
->hwcursor_size
= chipinfo
->hwcursor_size
;
5818 ivideo
->CRT2_write_enable
= chipinfo
->CRT2_write_enable
;
5819 ivideo
->mni
= chipinfo
->mni
;
5821 ivideo
->detectedpdc
= 0xff;
5822 ivideo
->detectedpdca
= 0xff;
5823 ivideo
->detectedlcda
= 0xff;
5825 ivideo
->sisfb_thismonitor
.datavalid
= false;
5827 ivideo
->current_base
= 0;
5829 ivideo
->engineok
= 0;
5831 ivideo
->sisfb_was_boot_device
= 0;
5832 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))
5833 if(pdev
->resource
[PCI_ROM_RESOURCE
].flags
& IORESOURCE_ROM_SHADOW
) {
5834 if(ivideo
->sisvga_enabled
)
5835 ivideo
->sisfb_was_boot_device
= 1;
5837 printk(KERN_DEBUG
"sisfb: PCI device is disabled, "
5838 "but marked as boot video device ???\n");
5839 printk(KERN_DEBUG
"sisfb: I will not accept this "
5840 "as the primary VGA device\n");
5845 ivideo
->sisfb_parm_mem
= sisfb_parm_mem
;
5846 ivideo
->sisfb_accel
= sisfb_accel
;
5847 ivideo
->sisfb_ypan
= sisfb_ypan
;
5848 ivideo
->sisfb_max
= sisfb_max
;
5849 ivideo
->sisfb_userom
= sisfb_userom
;
5850 ivideo
->sisfb_useoem
= sisfb_useoem
;
5851 ivideo
->sisfb_mode_idx
= sisfb_mode_idx
;
5852 ivideo
->sisfb_parm_rate
= sisfb_parm_rate
;
5853 ivideo
->sisfb_crt1off
= sisfb_crt1off
;
5854 ivideo
->sisfb_forcecrt1
= sisfb_forcecrt1
;
5855 ivideo
->sisfb_crt2type
= sisfb_crt2type
;
5856 ivideo
->sisfb_crt2flags
= sisfb_crt2flags
;
5857 /* pdc(a), scalelcd, special timing, lvdshl handled below */
5858 ivideo
->sisfb_dstn
= sisfb_dstn
;
5859 ivideo
->sisfb_fstn
= sisfb_fstn
;
5860 ivideo
->sisfb_tvplug
= sisfb_tvplug
;
5861 ivideo
->sisfb_tvstd
= sisfb_tvstd
;
5862 ivideo
->tvxpos
= sisfb_tvxposoffset
;
5863 ivideo
->tvypos
= sisfb_tvyposoffset
;
5864 ivideo
->sisfb_nocrt2rate
= sisfb_nocrt2rate
;
5865 ivideo
->refresh_rate
= 0;
5866 if(ivideo
->sisfb_parm_rate
!= -1) {
5867 ivideo
->refresh_rate
= ivideo
->sisfb_parm_rate
;
5870 ivideo
->SiS_Pr
.UsePanelScaler
= sisfb_scalelcd
;
5871 ivideo
->SiS_Pr
.CenterScreen
= -1;
5872 ivideo
->SiS_Pr
.SiS_CustomT
= sisfb_specialtiming
;
5873 ivideo
->SiS_Pr
.LVDSHL
= sisfb_lvdshl
;
5875 ivideo
->SiS_Pr
.SiS_Backup70xx
= 0xff;
5876 ivideo
->SiS_Pr
.SiS_CHOverScan
= -1;
5877 ivideo
->SiS_Pr
.SiS_ChSW
= false;
5878 ivideo
->SiS_Pr
.SiS_UseLCDA
= false;
5879 ivideo
->SiS_Pr
.HaveEMI
= false;
5880 ivideo
->SiS_Pr
.HaveEMILCD
= false;
5881 ivideo
->SiS_Pr
.OverruleEMI
= false;
5882 ivideo
->SiS_Pr
.SiS_SensibleSR11
= false;
5883 ivideo
->SiS_Pr
.SiS_MyCR63
= 0x63;
5884 ivideo
->SiS_Pr
.PDC
= -1;
5885 ivideo
->SiS_Pr
.PDCA
= -1;
5886 ivideo
->SiS_Pr
.DDCPortMixup
= false;
5887 #ifdef CONFIG_FB_SIS_315
5888 if(ivideo
->chip
>= SIS_330
) {
5889 ivideo
->SiS_Pr
.SiS_MyCR63
= 0x53;
5890 if(ivideo
->chip
>= SIS_661
) {
5891 ivideo
->SiS_Pr
.SiS_SensibleSR11
= true;
5896 memcpy(&ivideo
->default_var
, &my_default_var
, sizeof(my_default_var
));
5898 pci_set_drvdata(pdev
, ivideo
);
5900 /* Patch special cases */
5901 if((ivideo
->nbridge
= sisfb_get_northbridge(ivideo
->chip
))) {
5902 switch(ivideo
->nbridge
->device
) {
5903 #ifdef CONFIG_FB_SIS_300
5904 case PCI_DEVICE_ID_SI_730
:
5905 ivideo
->chip
= SIS_730
;
5906 strcpy(ivideo
->myid
, "SiS 730");
5909 #ifdef CONFIG_FB_SIS_315
5910 case PCI_DEVICE_ID_SI_651
:
5911 /* ivideo->chip is ok */
5912 strcpy(ivideo
->myid
, "SiS 651");
5914 case PCI_DEVICE_ID_SI_740
:
5915 ivideo
->chip
= SIS_740
;
5916 strcpy(ivideo
->myid
, "SiS 740");
5918 case PCI_DEVICE_ID_SI_661
:
5919 ivideo
->chip
= SIS_661
;
5920 strcpy(ivideo
->myid
, "SiS 661");
5922 case PCI_DEVICE_ID_SI_741
:
5923 ivideo
->chip
= SIS_741
;
5924 strcpy(ivideo
->myid
, "SiS 741");
5926 case PCI_DEVICE_ID_SI_760
:
5927 ivideo
->chip
= SIS_760
;
5928 strcpy(ivideo
->myid
, "SiS 760");
5930 case PCI_DEVICE_ID_SI_761
:
5931 ivideo
->chip
= SIS_761
;
5932 strcpy(ivideo
->myid
, "SiS 761");
5940 ivideo
->SiS_Pr
.ChipType
= ivideo
->chip
;
5942 ivideo
->SiS_Pr
.ivideo
= (void *)ivideo
;
5944 #ifdef CONFIG_FB_SIS_315
5945 if((ivideo
->SiS_Pr
.ChipType
== SIS_315PRO
) ||
5946 (ivideo
->SiS_Pr
.ChipType
== SIS_315
)) {
5947 ivideo
->SiS_Pr
.ChipType
= SIS_315H
;
5951 if(!ivideo
->sisvga_enabled
) {
5952 if(pci_enable_device(pdev
)) {
5953 if(ivideo
->nbridge
) pci_dev_put(ivideo
->nbridge
);
5954 pci_set_drvdata(pdev
, NULL
);
5960 ivideo
->video_base
= pci_resource_start(pdev
, 0);
5961 ivideo
->mmio_base
= pci_resource_start(pdev
, 1);
5962 ivideo
->mmio_size
= pci_resource_len(pdev
, 1);
5963 ivideo
->SiS_Pr
.RelIO
= pci_resource_start(pdev
, 2) + 0x30;
5964 ivideo
->SiS_Pr
.IOAddress
= ivideo
->vga_base
= ivideo
->SiS_Pr
.RelIO
;
5966 SiSRegInit(&ivideo
->SiS_Pr
, ivideo
->SiS_Pr
.IOAddress
);
5968 #ifdef CONFIG_FB_SIS_300
5969 /* Find PCI systems for Chrontel/GPIO communication setup */
5970 if(ivideo
->chip
== SIS_630
) {
5973 if(mychswtable
[i
].subsysVendor
== ivideo
->subsysvendor
&&
5974 mychswtable
[i
].subsysCard
== ivideo
->subsysdevice
) {
5975 ivideo
->SiS_Pr
.SiS_ChSW
= true;
5976 printk(KERN_DEBUG
"sisfb: Identified [%s %s] "
5977 "requiring Chrontel/GPIO setup\n",
5978 mychswtable
[i
].vendorName
,
5979 mychswtable
[i
].cardName
);
5980 ivideo
->lpcdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0008, NULL
);
5984 } while(mychswtable
[i
].subsysVendor
!= 0);
5988 #ifdef CONFIG_FB_SIS_315
5989 if((ivideo
->chip
== SIS_760
) && (ivideo
->nbridge
)) {
5990 ivideo
->lpcdev
= pci_get_slot(ivideo
->nbridge
->bus
, (2 << 3));
5994 outSISIDXREG(SISSR
, 0x05, 0x86);
5996 if( (!ivideo
->sisvga_enabled
)
5997 #if !defined(__i386__) && !defined(__x86_64__)
5998 || (sisfb_resetcard
)
6001 for(i
= 0x30; i
<= 0x3f; i
++) {
6002 outSISIDXREG(SISCR
, i
, 0x00);
6006 /* Find out about current video mode */
6007 ivideo
->modeprechange
= 0x03;
6008 inSISIDXREG(SISCR
, 0x34, reg
);
6010 ivideo
->modeprechange
= reg
& 0x7f;
6011 } else if(ivideo
->sisvga_enabled
) {
6012 #if defined(__i386__) || defined(__x86_64__)
6013 unsigned char SIS_IOTYPE2
*tt
= ioremap(0x400, 0x100);
6015 ivideo
->modeprechange
= readb(tt
+ 0x49);
6021 /* Search and copy ROM image */
6022 ivideo
->bios_abase
= NULL
;
6023 ivideo
->SiS_Pr
.VirtualRomBase
= NULL
;
6024 ivideo
->SiS_Pr
.UseROM
= false;
6025 ivideo
->haveXGIROM
= ivideo
->SiS_Pr
.SiS_XGIROM
= false;
6026 if(ivideo
->sisfb_userom
) {
6027 ivideo
->SiS_Pr
.VirtualRomBase
= sisfb_find_rom(pdev
);
6028 ivideo
->bios_abase
= ivideo
->SiS_Pr
.VirtualRomBase
;
6029 ivideo
->SiS_Pr
.UseROM
= (bool)(ivideo
->SiS_Pr
.VirtualRomBase
);
6030 printk(KERN_INFO
"sisfb: Video ROM %sfound\n",
6031 ivideo
->SiS_Pr
.UseROM
? "" : "not ");
6032 if((ivideo
->SiS_Pr
.UseROM
) && (ivideo
->chip
>= XGI_20
)) {
6033 ivideo
->SiS_Pr
.UseROM
= false;
6034 ivideo
->haveXGIROM
= ivideo
->SiS_Pr
.SiS_XGIROM
= true;
6035 if( (ivideo
->revision_id
== 2) &&
6036 (!(ivideo
->bios_abase
[0x1d1] & 0x01)) ) {
6037 ivideo
->SiS_Pr
.DDCPortMixup
= true;
6041 printk(KERN_INFO
"sisfb: Video ROM usage disabled\n");
6044 /* Find systems for special custom timing */
6045 if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_NONE
) {
6046 sisfb_detect_custom_timing(ivideo
);
6049 /* POST card in case this has not been done by the BIOS */
6050 if( (!ivideo
->sisvga_enabled
)
6051 #if !defined(__i386__) && !defined(__x86_64__)
6052 || (sisfb_resetcard
)
6055 #ifdef CONFIG_FB_SIS_300
6056 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
6057 if(ivideo
->chip
== SIS_300
) {
6058 sisfb_post_sis300(pdev
);
6059 ivideo
->sisfb_can_post
= 1;
6064 #ifdef CONFIG_FB_SIS_315
6065 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
6067 /* if((ivideo->chip == SIS_315H) ||
6068 (ivideo->chip == SIS_315) ||
6069 (ivideo->chip == SIS_315PRO) ||
6070 (ivideo->chip == SIS_330)) {
6071 sisfb_post_sis315330(pdev);
6072 } else */ if(ivideo
->chip
== XGI_20
) {
6073 result
= sisfb_post_xgi(pdev
);
6074 ivideo
->sisfb_can_post
= 1;
6075 } else if((ivideo
->chip
== XGI_40
) && ivideo
->haveXGIROM
) {
6076 result
= sisfb_post_xgi(pdev
);
6077 ivideo
->sisfb_can_post
= 1;
6079 printk(KERN_INFO
"sisfb: Card is not "
6080 "POSTed and sisfb can't do this either.\n");
6083 printk(KERN_ERR
"sisfb: Failed to POST card\n");
6091 ivideo
->sisfb_card_posted
= 1;
6093 /* Find out about RAM size */
6094 if(sisfb_get_dram_size(ivideo
)) {
6095 printk(KERN_INFO
"sisfb: Fatal error: Unable to determine VRAM size.\n");
6101 /* Enable PCI addressing and MMIO */
6102 if((ivideo
->sisfb_mode_idx
< 0) ||
6103 ((sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
]) != 0xFF)) {
6104 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
6105 orSISIDXREG(SISSR
, IND_SIS_PCI_ADDRESS_SET
, (SIS_PCI_ADDR_ENABLE
| SIS_MEM_MAP_IO_ENABLE
));
6106 /* Enable 2D accelerator engine */
6107 orSISIDXREG(SISSR
, IND_SIS_MODULE_ENABLE
, SIS_ENABLE_2D
);
6110 if(sisfb_pdc
!= 0xff) {
6111 if(ivideo
->sisvga_engine
== SIS_300_VGA
)
6115 ivideo
->SiS_Pr
.PDC
= sisfb_pdc
;
6117 #ifdef CONFIG_FB_SIS_315
6118 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
6119 if(sisfb_pdca
!= 0xff)
6120 ivideo
->SiS_Pr
.PDCA
= sisfb_pdca
& 0x1f;
6124 if(!request_mem_region(ivideo
->video_base
, ivideo
->video_size
, "sisfb FB")) {
6125 printk(KERN_ERR
"sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6126 (int)(ivideo
->video_size
>> 20));
6127 printk(KERN_ERR
"sisfb: Is there another framebuffer driver active?\n");
6132 if(!request_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
, "sisfb MMIO")) {
6133 printk(KERN_ERR
"sisfb: Fatal error: Unable to reserve MMIO region\n");
6138 ivideo
->video_vbase
= ioremap(ivideo
->video_base
, ivideo
->video_size
);
6139 ivideo
->SiS_Pr
.VideoMemoryAddress
= ivideo
->video_vbase
;
6140 if(!ivideo
->video_vbase
) {
6141 printk(KERN_ERR
"sisfb: Fatal error: Unable to map framebuffer memory\n");
6146 ivideo
->mmio_vbase
= ioremap(ivideo
->mmio_base
, ivideo
->mmio_size
);
6147 if(!ivideo
->mmio_vbase
) {
6148 printk(KERN_ERR
"sisfb: Fatal error: Unable to map MMIO region\n");
6150 error_0
: iounmap(ivideo
->video_vbase
);
6151 error_1
: release_mem_region(ivideo
->video_base
, ivideo
->video_size
);
6152 error_2
: release_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
);
6153 error_3
: vfree(ivideo
->bios_abase
);
6155 pci_dev_put(ivideo
->lpcdev
);
6157 pci_dev_put(ivideo
->nbridge
);
6158 pci_set_drvdata(pdev
, NULL
);
6159 if(!ivideo
->sisvga_enabled
)
6160 pci_disable_device(pdev
);
6165 printk(KERN_INFO
"sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
6166 ivideo
->video_base
, (unsigned long)ivideo
->video_vbase
, ivideo
->video_size
/ 1024);
6168 if(ivideo
->video_offset
) {
6169 printk(KERN_INFO
"sisfb: Viewport offset %ldk\n",
6170 ivideo
->video_offset
/ 1024);
6173 printk(KERN_INFO
"sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
6174 ivideo
->mmio_base
, (unsigned long)ivideo
->mmio_vbase
, ivideo
->mmio_size
/ 1024);
6177 /* Determine the size of the command queue */
6178 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
6179 ivideo
->cmdQueueSize
= TURBO_QUEUE_AREA_SIZE
;
6181 if(ivideo
->chip
== XGI_20
) {
6182 ivideo
->cmdQueueSize
= COMMAND_QUEUE_AREA_SIZE_Z7
;
6184 ivideo
->cmdQueueSize
= COMMAND_QUEUE_AREA_SIZE
;
6188 /* Engines are no longer initialized here; this is
6189 * now done after the first mode-switch (if the
6190 * submitted var has its acceleration flags set).
6193 /* Calculate the base of the (unused) hw cursor */
6194 ivideo
->hwcursor_vbase
= ivideo
->video_vbase
6195 + ivideo
->video_size
6196 - ivideo
->cmdQueueSize
6197 - ivideo
->hwcursor_size
;
6198 ivideo
->caps
|= HW_CURSOR_CAP
;
6200 /* Initialize offscreen memory manager */
6201 if((ivideo
->havenoheap
= sisfb_heap_init(ivideo
))) {
6202 printk(KERN_WARNING
"sisfb: Failed to initialize offscreen memory heap\n");
6205 /* Used for clearing the screen only, therefore respect our mem limit */
6206 ivideo
->SiS_Pr
.VideoMemoryAddress
+= ivideo
->video_offset
;
6207 ivideo
->SiS_Pr
.VideoMemorySize
= ivideo
->sisfb_mem
;
6211 ivideo
->vbflags
= 0;
6212 ivideo
->lcddefmodeidx
= DEFAULT_LCDMODE
;
6213 ivideo
->tvdefmodeidx
= DEFAULT_TVMODE
;
6214 ivideo
->defmodeidx
= DEFAULT_MODE
;
6217 if(ivideo
->chip
< XGI_20
) {
6218 if(ivideo
->bios_abase
) {
6219 ivideo
->newrom
= SiSDetermineROMLayout661(&ivideo
->SiS_Pr
);
6223 if((ivideo
->sisfb_mode_idx
< 0) ||
6224 ((sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
]) != 0xFF)) {
6226 sisfb_sense_crt1(ivideo
);
6228 sisfb_get_VB_type(ivideo
);
6230 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
6231 sisfb_detect_VB_connect(ivideo
);
6234 ivideo
->currentvbflags
= ivideo
->vbflags
& (VB_VIDEOBRIDGE
| TV_STANDARD
);
6236 /* Decide on which CRT2 device to use */
6237 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
6238 if(ivideo
->sisfb_crt2type
!= -1) {
6239 if((ivideo
->sisfb_crt2type
== CRT2_LCD
) &&
6240 (ivideo
->vbflags
& CRT2_LCD
)) {
6241 ivideo
->currentvbflags
|= CRT2_LCD
;
6242 } else if(ivideo
->sisfb_crt2type
!= CRT2_LCD
) {
6243 ivideo
->currentvbflags
|= ivideo
->sisfb_crt2type
;
6246 /* Chrontel 700x TV detection often unreliable, therefore
6247 * use a different default order on such machines
6249 if((ivideo
->sisvga_engine
== SIS_300_VGA
) &&
6250 (ivideo
->vbflags2
& VB2_CHRONTEL
)) {
6251 if(ivideo
->vbflags
& CRT2_LCD
)
6252 ivideo
->currentvbflags
|= CRT2_LCD
;
6253 else if(ivideo
->vbflags
& CRT2_TV
)
6254 ivideo
->currentvbflags
|= CRT2_TV
;
6255 else if(ivideo
->vbflags
& CRT2_VGA
)
6256 ivideo
->currentvbflags
|= CRT2_VGA
;
6258 if(ivideo
->vbflags
& CRT2_TV
)
6259 ivideo
->currentvbflags
|= CRT2_TV
;
6260 else if(ivideo
->vbflags
& CRT2_LCD
)
6261 ivideo
->currentvbflags
|= CRT2_LCD
;
6262 else if(ivideo
->vbflags
& CRT2_VGA
)
6263 ivideo
->currentvbflags
|= CRT2_VGA
;
6268 if(ivideo
->vbflags
& CRT2_LCD
) {
6269 sisfb_detect_lcd_type(ivideo
);
6272 sisfb_save_pdc_emi(ivideo
);
6274 if(!ivideo
->sisfb_crt1off
) {
6275 sisfb_handle_ddc(ivideo
, &ivideo
->sisfb_thismonitor
, 0);
6277 if((ivideo
->vbflags2
& VB2_SISTMDSBRIDGE
) &&
6278 (ivideo
->vbflags
& (CRT2_VGA
| CRT2_LCD
))) {
6279 sisfb_handle_ddc(ivideo
, &ivideo
->sisfb_thismonitor
, 1);
6283 if(ivideo
->sisfb_mode_idx
>= 0) {
6284 int bu
= ivideo
->sisfb_mode_idx
;
6285 ivideo
->sisfb_mode_idx
= sisfb_validate_mode(ivideo
,
6286 ivideo
->sisfb_mode_idx
, ivideo
->currentvbflags
);
6287 if(bu
!= ivideo
->sisfb_mode_idx
) {
6288 printk(KERN_ERR
"Mode %dx%dx%d failed validation\n",
6289 sisbios_mode
[bu
].xres
,
6290 sisbios_mode
[bu
].yres
,
6291 sisbios_mode
[bu
].bpp
);
6295 if(ivideo
->sisfb_mode_idx
< 0) {
6296 switch(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
6298 ivideo
->sisfb_mode_idx
= ivideo
->lcddefmodeidx
;
6301 ivideo
->sisfb_mode_idx
= ivideo
->tvdefmodeidx
;
6304 ivideo
->sisfb_mode_idx
= ivideo
->defmodeidx
;
6309 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
6311 if(ivideo
->refresh_rate
!= 0) {
6312 sisfb_search_refresh_rate(ivideo
, ivideo
->refresh_rate
,
6313 ivideo
->sisfb_mode_idx
);
6316 if(ivideo
->rate_idx
== 0) {
6317 ivideo
->rate_idx
= sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
;
6318 ivideo
->refresh_rate
= 60;
6321 if(ivideo
->sisfb_thismonitor
.datavalid
) {
6322 if(!sisfb_verify_rate(ivideo
, &ivideo
->sisfb_thismonitor
,
6323 ivideo
->sisfb_mode_idx
,
6325 ivideo
->refresh_rate
)) {
6326 printk(KERN_INFO
"sisfb: WARNING: Refresh rate "
6327 "exceeds monitor specs!\n");
6331 ivideo
->video_bpp
= sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
;
6332 ivideo
->video_width
= sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
;
6333 ivideo
->video_height
= sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
;
6335 sisfb_set_vparms(ivideo
);
6337 printk(KERN_INFO
"sisfb: Default mode is %dx%dx%d (%dHz)\n",
6338 ivideo
->video_width
, ivideo
->video_height
, ivideo
->video_bpp
,
6339 ivideo
->refresh_rate
);
6341 /* Set up the default var according to chosen default display mode */
6342 ivideo
->default_var
.xres
= ivideo
->default_var
.xres_virtual
= ivideo
->video_width
;
6343 ivideo
->default_var
.yres
= ivideo
->default_var
.yres_virtual
= ivideo
->video_height
;
6344 ivideo
->default_var
.bits_per_pixel
= ivideo
->video_bpp
;
6346 sisfb_bpp_to_var(ivideo
, &ivideo
->default_var
);
6348 ivideo
->default_var
.pixclock
= (u32
) (1000000000 /
6349 sisfb_mode_rate_to_dclock(&ivideo
->SiS_Pr
, ivideo
->mode_no
, ivideo
->rate_idx
));
6351 if(sisfb_mode_rate_to_ddata(&ivideo
->SiS_Pr
, ivideo
->mode_no
,
6352 ivideo
->rate_idx
, &ivideo
->default_var
)) {
6353 if((ivideo
->default_var
.vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
6354 ivideo
->default_var
.pixclock
<<= 1;
6358 if(ivideo
->sisfb_ypan
) {
6359 /* Maximize regardless of sisfb_max at startup */
6360 ivideo
->default_var
.yres_virtual
=
6361 sisfb_calc_maxyres(ivideo
, &ivideo
->default_var
);
6362 if(ivideo
->default_var
.yres_virtual
< ivideo
->default_var
.yres
) {
6363 ivideo
->default_var
.yres_virtual
= ivideo
->default_var
.yres
;
6367 sisfb_calc_pitch(ivideo
, &ivideo
->default_var
);
6370 if(ivideo
->sisfb_accel
) {
6372 #ifdef STUPID_ACCELF_TEXT_SHIT
6373 ivideo
->default_var
.accel_flags
|= FB_ACCELF_TEXT
;
6376 sisfb_initaccel(ivideo
);
6378 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
6379 sis_fb_info
->flags
= FBINFO_DEFAULT
|
6380 FBINFO_HWACCEL_YPAN
|
6381 FBINFO_HWACCEL_XPAN
|
6382 FBINFO_HWACCEL_COPYAREA
|
6383 FBINFO_HWACCEL_FILLRECT
|
6384 ((ivideo
->accel
) ? 0 : FBINFO_HWACCEL_DISABLED
);
6386 sis_fb_info
->flags
= FBINFO_FLAG_DEFAULT
;
6388 sis_fb_info
->var
= ivideo
->default_var
;
6389 sis_fb_info
->fix
= ivideo
->sisfb_fix
;
6390 sis_fb_info
->screen_base
= ivideo
->video_vbase
+ ivideo
->video_offset
;
6391 sis_fb_info
->fbops
= &sisfb_ops
;
6392 sisfb_get_fix(&sis_fb_info
->fix
, -1, sis_fb_info
);
6393 sis_fb_info
->pseudo_palette
= ivideo
->pseudo_palette
;
6395 fb_alloc_cmap(&sis_fb_info
->cmap
, 256 , 0);
6397 printk(KERN_DEBUG
"sisfb: Initial vbflags 0x%x\n", (int)ivideo
->vbflags
);
6400 ivideo
->mtrr
= mtrr_add(ivideo
->video_base
, ivideo
->video_size
,
6401 MTRR_TYPE_WRCOMB
, 1);
6402 if(ivideo
->mtrr
< 0) {
6403 printk(KERN_DEBUG
"sisfb: Failed to add MTRRs\n");
6407 if(register_framebuffer(sis_fb_info
) < 0) {
6408 printk(KERN_ERR
"sisfb: Fatal error: Failed to register framebuffer\n");
6410 iounmap(ivideo
->mmio_vbase
);
6414 ivideo
->registered
= 1;
6417 ivideo
->next
= card_list
;
6420 printk(KERN_INFO
"sisfb: 2D acceleration is %s, y-panning %s\n",
6421 ivideo
->sisfb_accel
? "enabled" : "disabled",
6422 ivideo
->sisfb_ypan
?
6423 (ivideo
->sisfb_max
? "enabled (auto-max)" :
6424 "enabled (no auto-max)") :
6428 printk(KERN_INFO
"fb%d: %s frame buffer device version %d.%d.%d\n",
6429 sis_fb_info
->node
, ivideo
->myid
, VER_MAJOR
, VER_MINOR
, VER_LEVEL
);
6431 printk(KERN_INFO
"sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
6433 } /* if mode = "none" */
6438 /*****************************************************/
6439 /* PCI DEVICE HANDLING */
6440 /*****************************************************/
6442 static void __devexit
sisfb_remove(struct pci_dev
*pdev
)
6444 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
6445 struct fb_info
*sis_fb_info
= ivideo
->memyselfandi
;
6446 int registered
= ivideo
->registered
;
6447 int modechanged
= ivideo
->modechanged
;
6450 iounmap(ivideo
->mmio_vbase
);
6451 iounmap(ivideo
->video_vbase
);
6453 /* Release mem regions */
6454 release_mem_region(ivideo
->video_base
, ivideo
->video_size
);
6455 release_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
);
6457 vfree(ivideo
->bios_abase
);
6460 pci_dev_put(ivideo
->lpcdev
);
6463 pci_dev_put(ivideo
->nbridge
);
6466 /* Release MTRR region */
6467 if(ivideo
->mtrr
>= 0)
6468 mtrr_del(ivideo
->mtrr
, ivideo
->video_base
, ivideo
->video_size
);
6471 pci_set_drvdata(pdev
, NULL
);
6473 /* If device was disabled when starting, disable
6476 if(!ivideo
->sisvga_enabled
)
6477 pci_disable_device(pdev
);
6479 /* Unregister the framebuffer */
6480 if(ivideo
->registered
) {
6481 unregister_framebuffer(sis_fb_info
);
6482 framebuffer_release(sis_fb_info
);
6485 /* OK, our ivideo is gone for good from here. */
6487 /* TODO: Restore the initial mode
6488 * This sounds easy but is as good as impossible
6489 * on many machines with SiS chip and video bridge
6490 * since text modes are always set up differently
6491 * from machine to machine. Depends on the type
6492 * of integration between chipset and bridge.
6494 if(registered
&& modechanged
)
6496 "sisfb: Restoring of text mode not supported yet\n");
6499 static struct pci_driver sisfb_driver
= {
6501 .id_table
= sisfb_pci_table
,
6502 .probe
= sisfb_probe
,
6503 .remove
= __devexit_p(sisfb_remove
)
6506 SISINITSTATIC
int __init
sisfb_init(void)
6509 char *options
= NULL
;
6511 if(fb_get_options("sisfb", &options
))
6514 sisfb_setup(options
);
6516 return pci_register_driver(&sisfb_driver
);
6520 module_init(sisfb_init
);
6523 /*****************************************************/
6525 /*****************************************************/
6529 static char *mode
= NULL
;
6530 static int vesa
= -1;
6531 static unsigned int rate
= 0;
6532 static unsigned int crt1off
= 1;
6533 static unsigned int mem
= 0;
6534 static char *forcecrt2type
= NULL
;
6535 static int forcecrt1
= -1;
6536 static int pdc
= -1;
6537 static int pdc1
= -1;
6538 static int noaccel
= -1;
6539 static int noypan
= -1;
6540 static int nomax
= -1;
6541 static int userom
= -1;
6542 static int useoem
= -1;
6543 static char *tvstandard
= NULL
;
6544 static int nocrt2rate
= 0;
6545 static int scalelcd
= -1;
6546 static char *specialtiming
= NULL
;
6547 static int lvdshl
= -1;
6548 static int tvxposoffset
= 0, tvyposoffset
= 0;
6549 #if !defined(__i386__) && !defined(__x86_64__)
6550 static int resetcard
= 0;
6551 static int videoram
= 0;
6554 static int __init
sisfb_init_module(void)
6556 sisfb_setdefaultparms();
6559 sisfb_parm_rate
= rate
;
6561 if((scalelcd
== 0) || (scalelcd
== 1))
6562 sisfb_scalelcd
= scalelcd
^ 1;
6564 /* Need to check crt2 type first for fstn/dstn */
6567 sisfb_search_crt2type(forcecrt2type
);
6570 sisfb_search_tvstd(tvstandard
);
6573 sisfb_search_mode(mode
, false);
6575 sisfb_search_vesamode(vesa
, false);
6577 sisfb_crt1off
= (crt1off
== 0) ? 1 : 0;
6579 sisfb_forcecrt1
= forcecrt1
;
6582 else if(forcecrt1
== 0)
6587 else if(noaccel
== 0)
6592 else if(noypan
== 0)
6601 sisfb_parm_mem
= mem
;
6604 sisfb_userom
= userom
;
6607 sisfb_useoem
= useoem
;
6610 sisfb_pdc
= (pdc
& 0x7f);
6613 sisfb_pdca
= (pdc1
& 0x1f);
6615 sisfb_nocrt2rate
= nocrt2rate
;
6618 sisfb_search_specialtiming(specialtiming
);
6620 if((lvdshl
>= 0) && (lvdshl
<= 3))
6621 sisfb_lvdshl
= lvdshl
;
6623 sisfb_tvxposoffset
= tvxposoffset
;
6624 sisfb_tvyposoffset
= tvyposoffset
;
6626 #if !defined(__i386__) && !defined(__x86_64__)
6627 sisfb_resetcard
= (resetcard
) ? 1 : 0;
6629 sisfb_videoram
= videoram
;
6632 return sisfb_init();
6635 static void __exit
sisfb_remove_module(void)
6637 pci_unregister_driver(&sisfb_driver
);
6638 printk(KERN_DEBUG
"sisfb: Module unloaded\n");
6641 module_init(sisfb_init_module
);
6642 module_exit(sisfb_remove_module
);
6644 MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
6645 MODULE_LICENSE("GPL");
6646 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
6648 module_param(mem
, int, 0);
6649 module_param(noaccel
, int, 0);
6650 module_param(noypan
, int, 0);
6651 module_param(nomax
, int, 0);
6652 module_param(userom
, int, 0);
6653 module_param(useoem
, int, 0);
6654 module_param(mode
, charp
, 0);
6655 module_param(vesa
, int, 0);
6656 module_param(rate
, int, 0);
6657 module_param(forcecrt1
, int, 0);
6658 module_param(forcecrt2type
, charp
, 0);
6659 module_param(scalelcd
, int, 0);
6660 module_param(pdc
, int, 0);
6661 module_param(pdc1
, int, 0);
6662 module_param(specialtiming
, charp
, 0);
6663 module_param(lvdshl
, int, 0);
6664 module_param(tvstandard
, charp
, 0);
6665 module_param(tvxposoffset
, int, 0);
6666 module_param(tvyposoffset
, int, 0);
6667 module_param(nocrt2rate
, int, 0);
6668 #if !defined(__i386__) && !defined(__x86_64__)
6669 module_param(resetcard
, int, 0);
6670 module_param(videoram
, int, 0);
6673 MODULE_PARM_DESC(mem
,
6674 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6675 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6676 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6677 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6678 "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6679 "The value is to be specified without 'KB'.\n");
6681 MODULE_PARM_DESC(noaccel
,
6682 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
6685 MODULE_PARM_DESC(noypan
,
6686 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
6687 "will be performed by redrawing the screen. (default: 0)\n");
6689 MODULE_PARM_DESC(nomax
,
6690 "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
6691 "memory for the virtual screen in order to optimize scrolling performance. If\n"
6692 "this is set to anything other than 0, sisfb will not do this and thereby \n"
6693 "enable the user to positively specify a virtual Y size of the screen using\n"
6694 "fbset. (default: 0)\n");
6696 MODULE_PARM_DESC(mode
,
6697 "\nSelects the desired default display mode in the format XxYxDepth,\n"
6698 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
6699 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
6700 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
6702 MODULE_PARM_DESC(vesa
,
6703 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
6704 "0x117 (default: 0x0103)\n");
6706 MODULE_PARM_DESC(rate
,
6707 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
6708 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
6709 "will be ignored (default: 60)\n");
6711 MODULE_PARM_DESC(forcecrt1
,
6712 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
6713 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
6714 "0=CRT1 OFF) (default: [autodetected])\n");
6716 MODULE_PARM_DESC(forcecrt2type
,
6717 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
6718 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
6719 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
6720 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
6721 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
6722 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
6723 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
6724 "depends on the very hardware in use. (default: [autodetected])\n");
6726 MODULE_PARM_DESC(scalelcd
,
6727 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
6728 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
6729 "show black bars around the image, TMDS panels will probably do the scaling\n"
6730 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
6732 MODULE_PARM_DESC(pdc
,
6733 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
6734 "should detect this correctly in most cases; however, sometimes this is not\n"
6735 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
6736 "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
6737 "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
6738 "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
6740 #ifdef CONFIG_FB_SIS_315
6741 MODULE_PARM_DESC(pdc1
,
6742 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
6743 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
6744 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
6745 "implemented yet.\n");
6748 MODULE_PARM_DESC(specialtiming
,
6749 "\nPlease refer to documentation for more information on this option.\n");
6751 MODULE_PARM_DESC(lvdshl
,
6752 "\nPlease refer to documentation for more information on this option.\n");
6754 MODULE_PARM_DESC(tvstandard
,
6755 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
6756 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
6758 MODULE_PARM_DESC(tvxposoffset
,
6759 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
6762 MODULE_PARM_DESC(tvyposoffset
,
6763 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
6766 MODULE_PARM_DESC(nocrt2rate
,
6767 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
6768 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
6770 #if !defined(__i386__) && !defined(__x86_64__)
6771 #ifdef CONFIG_FB_SIS_300
6772 MODULE_PARM_DESC(resetcard
,
6773 "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
6774 "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
6775 "currently). Default: 0\n");
6777 MODULE_PARM_DESC(videoram
,
6778 "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
6779 "some non-x86 architectures where the memory auto detection fails. Only\n"
6780 "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
6784 #endif /* /MODULE */
6786 /* _GPL only for new symbols. */
6787 EXPORT_SYMBOL(sis_malloc
);
6788 EXPORT_SYMBOL(sis_free
);
6789 EXPORT_SYMBOL_GPL(sis_malloc_new
);
6790 EXPORT_SYMBOL_GPL(sis_free_new
);