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/smp_lock.h>
41 #include <linux/spinlock.h>
42 #include <linux/errno.h>
43 #include <linux/string.h>
46 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
47 #include <linux/tty.h>
49 #include <linux/screen_info.h>
52 #include <linux/slab.h>
54 #include <linux/selection.h>
55 #include <linux/ioport.h>
56 #include <linux/init.h>
57 #include <linux/pci.h>
58 #include <linux/vmalloc.h>
59 #include <linux/capability.h>
61 #include <linux/types.h>
62 #include <asm/uaccess.h>
71 static void sisfb_handle_command(struct sis_video_info
*ivideo
,
72 struct sisfb_cmd
*sisfb_command
);
74 /* ------------------ Internal helper routines ----------------- */
77 sisfb_setdefaultparms(void)
95 sisfb_specialtiming
= CUT_NONE
;
101 sisfb_tvxposoffset
= 0;
102 sisfb_tvyposoffset
= 0;
103 sisfb_nocrt2rate
= 0;
104 #if !defined(__i386__) && !defined(__x86_64__)
110 /* ------------- Parameter parsing -------------- */
112 static void __devinit
113 sisfb_search_vesamode(unsigned int vesamode
, bool quiet
)
117 /* We don't know the hardware specs yet and there is no ivideo */
121 printk(KERN_ERR
"sisfb: Invalid mode. Using default.\n");
123 sisfb_mode_idx
= DEFAULT_MODE
;
128 vesamode
&= 0x1dff; /* Clean VESA mode number from other flags */
130 while(sisbios_mode
[i
++].mode_no
[0] != 0) {
131 if( (sisbios_mode
[i
-1].vesa_mode_no_1
== vesamode
) ||
132 (sisbios_mode
[i
-1].vesa_mode_no_2
== vesamode
) ) {
134 if(sisbios_mode
[i
-1].mode_no
[1] == 0x50 ||
135 sisbios_mode
[i
-1].mode_no
[1] == 0x56 ||
136 sisbios_mode
[i
-1].mode_no
[1] == 0x53)
139 if(sisbios_mode
[i
-1].mode_no
[1] == 0x5a ||
140 sisbios_mode
[i
-1].mode_no
[1] == 0x5b)
143 sisfb_mode_idx
= i
- 1;
149 printk(KERN_ERR
"sisfb: Invalid VESA mode 0x%x'\n", vesamode
);
152 static void __devinit
153 sisfb_search_mode(char *name
, bool quiet
)
155 unsigned int j
= 0, xres
= 0, yres
= 0, depth
= 0, rate
= 0;
157 char strbuf
[16], strbuf1
[20];
158 char *nameptr
= name
;
160 /* We don't know the hardware specs yet and there is no ivideo */
164 printk(KERN_ERR
"sisfb: Internal error, using default mode.\n");
166 sisfb_mode_idx
= DEFAULT_MODE
;
170 if(!strnicmp(name
, sisbios_mode
[MODE_INDEX_NONE
].name
, strlen(name
))) {
172 printk(KERN_ERR
"sisfb: Mode 'none' not supported anymore. Using default.\n");
174 sisfb_mode_idx
= DEFAULT_MODE
;
178 if(strlen(name
) <= 19) {
179 strcpy(strbuf1
, name
);
180 for(i
= 0; i
< strlen(strbuf1
); i
++) {
181 if(strbuf1
[i
] < '0' || strbuf1
[i
] > '9') strbuf1
[i
] = ' ';
184 /* This does some fuzzy mode naming detection */
185 if(sscanf(strbuf1
, "%u %u %u %u", &xres
, &yres
, &depth
, &rate
) == 4) {
186 if((rate
<= 32) || (depth
> 32)) {
187 j
= rate
; rate
= depth
; depth
= j
;
189 sprintf(strbuf
, "%ux%ux%u", xres
, yres
, depth
);
191 sisfb_parm_rate
= rate
;
192 } else if(sscanf(strbuf1
, "%u %u %u", &xres
, &yres
, &depth
) == 3) {
193 sprintf(strbuf
, "%ux%ux%u", xres
, yres
, depth
);
197 if((sscanf(strbuf1
, "%u %u", &xres
, &yres
) == 2) && (xres
!= 0)) {
198 sprintf(strbuf
, "%ux%ux8", xres
, yres
);
201 sisfb_search_vesamode(simple_strtoul(name
, NULL
, 0), quiet
);
208 while(sisbios_mode
[i
].mode_no
[0] != 0) {
209 if(!strnicmp(nameptr
, sisbios_mode
[i
++].name
, strlen(nameptr
))) {
211 if(sisbios_mode
[i
-1].mode_no
[1] == 0x50 ||
212 sisbios_mode
[i
-1].mode_no
[1] == 0x56 ||
213 sisbios_mode
[i
-1].mode_no
[1] == 0x53)
216 if(sisbios_mode
[i
-1].mode_no
[1] == 0x5a ||
217 sisbios_mode
[i
-1].mode_no
[1] == 0x5b)
220 sisfb_mode_idx
= i
- 1;
227 printk(KERN_ERR
"sisfb: Invalid mode '%s'\n", nameptr
);
231 static void __devinit
232 sisfb_get_vga_mode_from_kernel(void)
236 int mydepth
= screen_info
.lfb_depth
;
238 if(screen_info
.orig_video_isVGA
!= VIDEO_TYPE_VLFB
) return;
240 if( (screen_info
.lfb_width
>= 320) && (screen_info
.lfb_width
<= 2048) &&
241 (screen_info
.lfb_height
>= 200) && (screen_info
.lfb_height
<= 1536) &&
242 (mydepth
>= 8) && (mydepth
<= 32) ) {
244 if(mydepth
== 24) mydepth
= 32;
246 sprintf(mymode
, "%ux%ux%u", screen_info
.lfb_width
,
247 screen_info
.lfb_height
,
251 "sisfb: Using vga mode %s pre-set by kernel as default\n",
254 sisfb_search_mode(mymode
, true);
262 sisfb_search_crt2type(const char *name
)
266 /* We don't know the hardware specs yet and there is no ivideo */
268 if(name
== NULL
) return;
270 while(sis_crt2type
[i
].type_no
!= -1) {
271 if(!strnicmp(name
, sis_crt2type
[i
].name
, strlen(sis_crt2type
[i
].name
))) {
272 sisfb_crt2type
= sis_crt2type
[i
].type_no
;
273 sisfb_tvplug
= sis_crt2type
[i
].tvplug_no
;
274 sisfb_crt2flags
= sis_crt2type
[i
].flags
;
280 sisfb_dstn
= (sisfb_crt2flags
& FL_550_DSTN
) ? 1 : 0;
281 sisfb_fstn
= (sisfb_crt2flags
& FL_550_FSTN
) ? 1 : 0;
283 if(sisfb_crt2type
< 0)
284 printk(KERN_ERR
"sisfb: Invalid CRT2 type: %s\n", name
);
288 sisfb_search_tvstd(const char *name
)
292 /* We don't know the hardware specs yet and there is no ivideo */
297 while(sis_tvtype
[i
].type_no
!= -1) {
298 if(!strnicmp(name
, sis_tvtype
[i
].name
, strlen(sis_tvtype
[i
].name
))) {
299 sisfb_tvstd
= sis_tvtype
[i
].type_no
;
307 sisfb_search_specialtiming(const char *name
)
312 /* We don't know the hardware specs yet and there is no ivideo */
317 if(!strnicmp(name
, "none", 4)) {
318 sisfb_specialtiming
= CUT_FORCENONE
;
319 printk(KERN_DEBUG
"sisfb: Special timing disabled\n");
321 while(mycustomttable
[i
].chipID
!= 0) {
322 if(!strnicmp(name
,mycustomttable
[i
].optionName
,
323 strlen(mycustomttable
[i
].optionName
))) {
324 sisfb_specialtiming
= mycustomttable
[i
].SpecialID
;
326 printk(KERN_INFO
"sisfb: Special timing for %s %s forced (\"%s\")\n",
327 mycustomttable
[i
].vendorName
,
328 mycustomttable
[i
].cardName
,
329 mycustomttable
[i
].optionName
);
335 printk(KERN_WARNING
"sisfb: Invalid SpecialTiming parameter, valid are:");
336 printk(KERN_WARNING
"\t\"none\" (to disable special timings)\n");
338 while(mycustomttable
[i
].chipID
!= 0) {
339 printk(KERN_WARNING
"\t\"%s\" (for %s %s)\n",
340 mycustomttable
[i
].optionName
,
341 mycustomttable
[i
].vendorName
,
342 mycustomttable
[i
].cardName
);
349 /* ----------- Various detection routines ----------- */
351 static void __devinit
352 sisfb_detect_custom_timing(struct sis_video_info
*ivideo
)
354 unsigned char *biosver
= NULL
;
355 unsigned char *biosdate
= NULL
;
360 if(ivideo
->SiS_Pr
.UseROM
) {
361 biosver
= ivideo
->SiS_Pr
.VirtualRomBase
+ 0x06;
362 biosdate
= ivideo
->SiS_Pr
.VirtualRomBase
+ 0x2c;
363 for(i
= 0; i
< 32768; i
++)
364 chksum
+= ivideo
->SiS_Pr
.VirtualRomBase
[i
];
369 if( (mycustomttable
[i
].chipID
== ivideo
->chip
) &&
370 ((!strlen(mycustomttable
[i
].biosversion
)) ||
371 (ivideo
->SiS_Pr
.UseROM
&&
372 (!strncmp(mycustomttable
[i
].biosversion
, biosver
,
373 strlen(mycustomttable
[i
].biosversion
))))) &&
374 ((!strlen(mycustomttable
[i
].biosdate
)) ||
375 (ivideo
->SiS_Pr
.UseROM
&&
376 (!strncmp(mycustomttable
[i
].biosdate
, biosdate
,
377 strlen(mycustomttable
[i
].biosdate
))))) &&
378 ((!mycustomttable
[i
].bioschksum
) ||
379 (ivideo
->SiS_Pr
.UseROM
&&
380 (mycustomttable
[i
].bioschksum
== chksum
))) &&
381 (mycustomttable
[i
].pcisubsysvendor
== ivideo
->subsysvendor
) &&
382 (mycustomttable
[i
].pcisubsyscard
== ivideo
->subsysdevice
) ) {
384 for(j
= 0; j
< 5; j
++) {
385 if(mycustomttable
[i
].biosFootprintAddr
[j
]) {
386 if(ivideo
->SiS_Pr
.UseROM
) {
387 if(ivideo
->SiS_Pr
.VirtualRomBase
[mycustomttable
[i
].biosFootprintAddr
[j
]] !=
388 mycustomttable
[i
].biosFootprintData
[j
]) {
396 ivideo
->SiS_Pr
.SiS_CustomT
= mycustomttable
[i
].SpecialID
;
397 printk(KERN_DEBUG
"sisfb: Identified [%s %s], special timing applies\n",
398 mycustomttable
[i
].vendorName
,
399 mycustomttable
[i
].cardName
);
400 printk(KERN_DEBUG
"sisfb: [specialtiming parameter name: %s]\n",
401 mycustomttable
[i
].optionName
);
406 } while(mycustomttable
[i
].chipID
);
409 static bool __devinit
410 sisfb_interpret_edid(struct sisfb_monitor
*monitor
, u8
*buffer
)
412 int i
, j
, xres
, yres
, refresh
, index
;
415 if(buffer
[0] != 0x00 || buffer
[1] != 0xff ||
416 buffer
[2] != 0xff || buffer
[3] != 0xff ||
417 buffer
[4] != 0xff || buffer
[5] != 0xff ||
418 buffer
[6] != 0xff || buffer
[7] != 0x00) {
419 printk(KERN_DEBUG
"sisfb: Bad EDID header\n");
423 if(buffer
[0x12] != 0x01) {
424 printk(KERN_INFO
"sisfb: EDID version %d not supported\n",
429 monitor
->feature
= buffer
[0x18];
431 if(!buffer
[0x14] & 0x80) {
432 if(!(buffer
[0x14] & 0x08)) {
434 "sisfb: WARNING: Monitor does not support separate syncs\n");
438 if(buffer
[0x13] >= 0x01) {
439 /* EDID V1 rev 1 and 2: Search for monitor descriptor
444 if(buffer
[j
] == 0x00 && buffer
[j
+ 1] == 0x00 &&
445 buffer
[j
+ 2] == 0x00 && buffer
[j
+ 3] == 0xfd &&
446 buffer
[j
+ 4] == 0x00) {
447 monitor
->hmin
= buffer
[j
+ 7];
448 monitor
->hmax
= buffer
[j
+ 8];
449 monitor
->vmin
= buffer
[j
+ 5];
450 monitor
->vmax
= buffer
[j
+ 6];
451 monitor
->dclockmax
= buffer
[j
+ 9] * 10 * 1000;
452 monitor
->datavalid
= true;
459 if(!monitor
->datavalid
) {
460 /* Otherwise: Get a range from the list of supported
461 * Estabished Timings. This is not entirely accurate,
462 * because fixed frequency monitors are not supported
465 monitor
->hmin
= 65535; monitor
->hmax
= 0;
466 monitor
->vmin
= 65535; monitor
->vmax
= 0;
467 monitor
->dclockmax
= 0;
468 emodes
= buffer
[0x23] | (buffer
[0x24] << 8) | (buffer
[0x25] << 16);
469 for(i
= 0; i
< 13; i
++) {
470 if(emodes
& sisfb_ddcsmodes
[i
].mask
) {
471 if(monitor
->hmin
> sisfb_ddcsmodes
[i
].h
) monitor
->hmin
= sisfb_ddcsmodes
[i
].h
;
472 if(monitor
->hmax
< sisfb_ddcsmodes
[i
].h
) monitor
->hmax
= sisfb_ddcsmodes
[i
].h
+ 1;
473 if(monitor
->vmin
> sisfb_ddcsmodes
[i
].v
) monitor
->vmin
= sisfb_ddcsmodes
[i
].v
;
474 if(monitor
->vmax
< sisfb_ddcsmodes
[i
].v
) monitor
->vmax
= sisfb_ddcsmodes
[i
].v
;
475 if(monitor
->dclockmax
< sisfb_ddcsmodes
[i
].d
) monitor
->dclockmax
= sisfb_ddcsmodes
[i
].d
;
479 for(i
= 0; i
< 8; i
++) {
480 xres
= (buffer
[index
] + 31) * 8;
481 switch(buffer
[index
+ 1] & 0xc0) {
482 case 0xc0: yres
= (xres
* 9) / 16; break;
483 case 0x80: yres
= (xres
* 4) / 5; break;
484 case 0x40: yres
= (xres
* 3) / 4; break;
485 default: yres
= xres
; break;
487 refresh
= (buffer
[index
+ 1] & 0x3f) + 60;
488 if((xres
>= 640) && (yres
>= 480)) {
489 for(j
= 0; j
< 8; j
++) {
490 if((xres
== sisfb_ddcfmodes
[j
].x
) &&
491 (yres
== sisfb_ddcfmodes
[j
].y
) &&
492 (refresh
== sisfb_ddcfmodes
[j
].v
)) {
493 if(monitor
->hmin
> sisfb_ddcfmodes
[j
].h
) monitor
->hmin
= sisfb_ddcfmodes
[j
].h
;
494 if(monitor
->hmax
< sisfb_ddcfmodes
[j
].h
) monitor
->hmax
= sisfb_ddcfmodes
[j
].h
+ 1;
495 if(monitor
->vmin
> sisfb_ddcsmodes
[j
].v
) monitor
->vmin
= sisfb_ddcsmodes
[j
].v
;
496 if(monitor
->vmax
< sisfb_ddcsmodes
[j
].v
) monitor
->vmax
= sisfb_ddcsmodes
[j
].v
;
497 if(monitor
->dclockmax
< sisfb_ddcsmodes
[j
].d
) monitor
->dclockmax
= sisfb_ddcsmodes
[j
].d
;
503 if((monitor
->hmin
<= monitor
->hmax
) && (monitor
->vmin
<= monitor
->vmax
)) {
504 monitor
->datavalid
= true;
508 return monitor
->datavalid
;
511 static void __devinit
512 sisfb_handle_ddc(struct sis_video_info
*ivideo
, struct sisfb_monitor
*monitor
, int crtno
)
514 unsigned short temp
, i
, realcrtno
= crtno
;
515 unsigned char buffer
[256];
517 monitor
->datavalid
= false;
520 if(ivideo
->vbflags
& CRT2_LCD
) realcrtno
= 1;
521 else if(ivideo
->vbflags
& CRT2_VGA
) realcrtno
= 2;
525 if((ivideo
->sisfb_crt1off
) && (!crtno
))
528 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
529 realcrtno
, 0, &buffer
[0], ivideo
->vbflags2
);
530 if((!temp
) || (temp
== 0xffff)) {
531 printk(KERN_INFO
"sisfb: CRT%d DDC probing failed\n", crtno
+ 1);
534 printk(KERN_INFO
"sisfb: CRT%d DDC supported\n", crtno
+ 1);
535 printk(KERN_INFO
"sisfb: CRT%d DDC level: %s%s%s%s\n",
537 (temp
& 0x1a) ? "" : "[none of the supported]",
538 (temp
& 0x02) ? "2 " : "",
539 (temp
& 0x08) ? "D&P" : "",
540 (temp
& 0x10) ? "FPDI-2" : "");
542 i
= 3; /* Number of retrys */
544 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
545 realcrtno
, 1, &buffer
[0], ivideo
->vbflags2
);
546 } while((temp
) && i
--);
548 if(sisfb_interpret_edid(monitor
, &buffer
[0])) {
549 printk(KERN_INFO
"sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
550 monitor
->hmin
, monitor
->hmax
, monitor
->vmin
, monitor
->vmax
,
551 monitor
->dclockmax
/ 1000);
553 printk(KERN_INFO
"sisfb: CRT%d DDC EDID corrupt\n", crtno
+ 1);
556 printk(KERN_INFO
"sisfb: CRT%d DDC reading failed\n", crtno
+ 1);
559 printk(KERN_INFO
"sisfb: VESA D&P and FPDI-2 not supported yet\n");
564 /* -------------- Mode validation --------------- */
567 sisfb_verify_rate(struct sis_video_info
*ivideo
, struct sisfb_monitor
*monitor
,
568 int mode_idx
, int rate_idx
, int rate
)
571 unsigned int dclock
, hsync
;
573 if(!monitor
->datavalid
)
579 /* Skip for 320x200, 320x240, 640x400 */
580 switch(sisbios_mode
[mode_idx
].mode_no
[ivideo
->mni
]) {
591 #ifdef CONFIG_FB_SIS_315
594 if(ivideo
->sisvga_engine
== SIS_315_VGA
) return true;
598 if(rate
< (monitor
->vmin
- 1))
600 if(rate
> (monitor
->vmax
+ 1))
603 if(sisfb_gettotalfrommode(&ivideo
->SiS_Pr
,
604 sisbios_mode
[mode_idx
].mode_no
[ivideo
->mni
],
605 &htotal
, &vtotal
, rate_idx
)) {
606 dclock
= (htotal
* vtotal
* rate
) / 1000;
607 if(dclock
> (monitor
->dclockmax
+ 1000))
609 hsync
= dclock
/ htotal
;
610 if(hsync
< (monitor
->hmin
- 1))
612 if(hsync
> (monitor
->hmax
+ 1))
621 sisfb_validate_mode(struct sis_video_info
*ivideo
, int myindex
, u32 vbflags
)
623 u16 xres
=0, yres
, myres
;
625 #ifdef CONFIG_FB_SIS_300
626 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
627 if(!(sisbios_mode
[myindex
].chipset
& MD_SIS300
))
631 #ifdef CONFIG_FB_SIS_315
632 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
633 if(!(sisbios_mode
[myindex
].chipset
& MD_SIS315
))
638 myres
= sisbios_mode
[myindex
].yres
;
640 switch(vbflags
& VB_DISPTYPE_DISP2
) {
643 xres
= ivideo
->lcdxres
; yres
= ivideo
->lcdyres
;
645 if((ivideo
->SiS_Pr
.SiS_CustomT
!= CUT_PANEL848
) &&
646 (ivideo
->SiS_Pr
.SiS_CustomT
!= CUT_PANEL856
)) {
647 if(sisbios_mode
[myindex
].xres
> xres
)
653 if(ivideo
->sisfb_fstn
) {
654 if(sisbios_mode
[myindex
].xres
== 320) {
656 switch(sisbios_mode
[myindex
].mode_no
[1]) {
657 case 0x50: myindex
= MODE_FSTN_8
; break;
658 case 0x56: myindex
= MODE_FSTN_16
; break;
659 case 0x53: return -1;
665 if(SiS_GetModeID_LCD(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
666 sisbios_mode
[myindex
].yres
, 0, ivideo
->sisfb_fstn
,
667 ivideo
->SiS_Pr
.SiS_CustomT
, xres
, yres
, ivideo
->vbflags2
) < 0x14) {
673 if(SiS_GetModeID_TV(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
674 sisbios_mode
[myindex
].yres
, 0, ivideo
->vbflags2
) < 0x14) {
680 if(SiS_GetModeID_VGA2(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
681 sisbios_mode
[myindex
].yres
, 0, ivideo
->vbflags2
) < 0x14) {
691 sisfb_search_refresh_rate(struct sis_video_info
*ivideo
, unsigned int rate
, int mode_idx
)
694 u16 xres
= sisbios_mode
[mode_idx
].xres
;
695 u16 yres
= sisbios_mode
[mode_idx
].yres
;
697 ivideo
->rate_idx
= 0;
698 while((sisfb_vrate
[i
].idx
!= 0) && (sisfb_vrate
[i
].xres
<= xres
)) {
699 if((sisfb_vrate
[i
].xres
== xres
) && (sisfb_vrate
[i
].yres
== yres
)) {
700 if(sisfb_vrate
[i
].refresh
== rate
) {
701 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
703 } else if(sisfb_vrate
[i
].refresh
> rate
) {
704 if((sisfb_vrate
[i
].refresh
- rate
) <= 3) {
705 DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
706 rate
, sisfb_vrate
[i
].refresh
);
707 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
708 ivideo
->refresh_rate
= sisfb_vrate
[i
].refresh
;
709 } else if(((rate
- sisfb_vrate
[i
-1].refresh
) <= 2)
710 && (sisfb_vrate
[i
].idx
!= 1)) {
711 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
712 rate
, sisfb_vrate
[i
-1].refresh
);
713 ivideo
->rate_idx
= sisfb_vrate
[i
-1].idx
;
714 ivideo
->refresh_rate
= sisfb_vrate
[i
-1].refresh
;
717 } else if((rate
- sisfb_vrate
[i
].refresh
) <= 2) {
718 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
719 rate
, sisfb_vrate
[i
].refresh
);
720 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
726 if(ivideo
->rate_idx
> 0) {
727 return ivideo
->rate_idx
;
729 printk(KERN_INFO
"sisfb: Unsupported rate %d for %dx%d\n",
736 sisfb_bridgeisslave(struct sis_video_info
*ivideo
)
740 if(!(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
))
743 inSISIDXREG(SISPART1
,0x00,P1_00
);
744 if( ((ivideo
->sisvga_engine
== SIS_300_VGA
) && (P1_00
& 0xa0) == 0x20) ||
745 ((ivideo
->sisvga_engine
== SIS_315_VGA
) && (P1_00
& 0x50) == 0x10) ) {
753 sisfballowretracecrt1(struct sis_video_info
*ivideo
)
757 inSISIDXREG(SISCR
,0x17,temp
);
761 inSISIDXREG(SISSR
,0x1f,temp
);
769 sisfbcheckvretracecrt1(struct sis_video_info
*ivideo
)
771 if(!sisfballowretracecrt1(ivideo
))
774 if(inSISREG(SISINPSTAT
) & 0x08)
781 sisfbwaitretracecrt1(struct sis_video_info
*ivideo
)
785 if(!sisfballowretracecrt1(ivideo
))
789 while((!(inSISREG(SISINPSTAT
) & 0x08)) && --watchdog
);
791 while((inSISREG(SISINPSTAT
) & 0x08) && --watchdog
);
795 sisfbcheckvretracecrt2(struct sis_video_info
*ivideo
)
797 unsigned char temp
, reg
;
799 switch(ivideo
->sisvga_engine
) {
800 case SIS_300_VGA
: reg
= 0x25; break;
801 case SIS_315_VGA
: reg
= 0x30; break;
802 default: return false;
805 inSISIDXREG(SISPART1
, reg
, temp
);
813 sisfb_CheckVBRetrace(struct sis_video_info
*ivideo
)
815 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
816 if(!sisfb_bridgeisslave(ivideo
)) {
817 return sisfbcheckvretracecrt2(ivideo
);
820 return sisfbcheckvretracecrt1(ivideo
);
824 sisfb_setupvbblankflags(struct sis_video_info
*ivideo
, u32
*vcount
, u32
*hcount
)
826 u8 idx
, reg1
, reg2
, reg3
, reg4
;
829 (*vcount
) = (*hcount
) = 0;
831 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) && (!(sisfb_bridgeisslave(ivideo
)))) {
833 ret
|= (FB_VBLANK_HAVE_VSYNC
|
834 FB_VBLANK_HAVE_HBLANK
|
835 FB_VBLANK_HAVE_VBLANK
|
836 FB_VBLANK_HAVE_VCOUNT
|
837 FB_VBLANK_HAVE_HCOUNT
);
838 switch(ivideo
->sisvga_engine
) {
839 case SIS_300_VGA
: idx
= 0x25; break;
841 case SIS_315_VGA
: idx
= 0x30; break;
843 inSISIDXREG(SISPART1
,(idx
+0),reg1
); /* 30 */
844 inSISIDXREG(SISPART1
,(idx
+1),reg2
); /* 31 */
845 inSISIDXREG(SISPART1
,(idx
+2),reg3
); /* 32 */
846 inSISIDXREG(SISPART1
,(idx
+3),reg4
); /* 33 */
847 if(reg1
& 0x01) ret
|= FB_VBLANK_VBLANKING
;
848 if(reg1
& 0x02) ret
|= FB_VBLANK_VSYNCING
;
849 if(reg4
& 0x80) ret
|= FB_VBLANK_HBLANKING
;
850 (*vcount
) = reg3
| ((reg4
& 0x70) << 4);
851 (*hcount
) = reg2
| ((reg4
& 0x0f) << 8);
853 } else if(sisfballowretracecrt1(ivideo
)) {
855 ret
|= (FB_VBLANK_HAVE_VSYNC
|
856 FB_VBLANK_HAVE_VBLANK
|
857 FB_VBLANK_HAVE_VCOUNT
|
858 FB_VBLANK_HAVE_HCOUNT
);
859 reg1
= inSISREG(SISINPSTAT
);
860 if(reg1
& 0x08) ret
|= FB_VBLANK_VSYNCING
;
861 if(reg1
& 0x01) ret
|= FB_VBLANK_VBLANKING
;
862 inSISIDXREG(SISCR
,0x20,reg1
);
863 inSISIDXREG(SISCR
,0x1b,reg1
);
864 inSISIDXREG(SISCR
,0x1c,reg2
);
865 inSISIDXREG(SISCR
,0x1d,reg3
);
866 (*vcount
) = reg2
| ((reg3
& 0x07) << 8);
867 (*hcount
) = (reg1
| ((reg3
& 0x10) << 4)) << 3;
874 sisfb_myblank(struct sis_video_info
*ivideo
, int blank
)
876 u8 sr01
, sr11
, sr1f
, cr63
=0, p2_0
, p1_13
;
877 bool backlight
= true;
880 case FB_BLANK_UNBLANK
: /* on */
889 case FB_BLANK_NORMAL
: /* blank */
898 case FB_BLANK_VSYNC_SUSPEND
: /* no vsync */
907 case FB_BLANK_HSYNC_SUSPEND
: /* no hsync */
916 case FB_BLANK_POWERDOWN
: /* off */
929 if(ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
) {
931 if( (!ivideo
->sisfb_thismonitor
.datavalid
) ||
932 ((ivideo
->sisfb_thismonitor
.datavalid
) &&
933 (ivideo
->sisfb_thismonitor
.feature
& 0xe0))) {
935 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
936 setSISIDXREG(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, 0xbf, cr63
);
939 if(!(sisfb_bridgeisslave(ivideo
))) {
940 setSISIDXREG(SISSR
, 0x01, ~0x20, sr01
);
941 setSISIDXREG(SISSR
, 0x1f, 0x3f, sr1f
);
947 if(ivideo
->currentvbflags
& CRT2_LCD
) {
949 if(ivideo
->vbflags2
& VB2_SISLVDSBRIDGE
) {
951 SiS_SiS30xBLOn(&ivideo
->SiS_Pr
);
953 SiS_SiS30xBLOff(&ivideo
->SiS_Pr
);
955 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
956 #ifdef CONFIG_FB_SIS_315
957 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
959 SiS_Chrontel701xBLOn(&ivideo
->SiS_Pr
);
961 SiS_Chrontel701xBLOff(&ivideo
->SiS_Pr
);
967 if(((ivideo
->sisvga_engine
== SIS_300_VGA
) &&
968 (ivideo
->vbflags2
& (VB2_301
|VB2_30xBDH
|VB2_LVDS
))) ||
969 ((ivideo
->sisvga_engine
== SIS_315_VGA
) &&
970 ((ivideo
->vbflags2
& (VB2_LVDS
| VB2_CHRONTEL
)) == VB2_LVDS
))) {
971 setSISIDXREG(SISSR
, 0x11, ~0x0c, sr11
);
974 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
975 if((ivideo
->vbflags2
& VB2_30xB
) &&
976 (!(ivideo
->vbflags2
& VB2_30xBDH
))) {
977 setSISIDXREG(SISPART1
, 0x13, 0x3f, p1_13
);
979 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
980 if((ivideo
->vbflags2
& VB2_30xB
) &&
981 (!(ivideo
->vbflags2
& VB2_30xBDH
))) {
982 setSISIDXREG(SISPART2
, 0x00, 0x1f, p2_0
);
986 } else if(ivideo
->currentvbflags
& CRT2_VGA
) {
988 if(ivideo
->vbflags2
& VB2_30xB
) {
989 setSISIDXREG(SISPART2
, 0x00, 0x1f, p2_0
);
997 /* ------------- Callbacks from init.c/init301.c -------------- */
999 #ifdef CONFIG_FB_SIS_300
1001 sisfb_read_nbridge_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
)
1003 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1006 pci_read_config_dword(ivideo
->nbridge
, reg
, &val
);
1007 return (unsigned int)val
;
1011 sisfb_write_nbridge_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
, unsigned int val
)
1013 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1015 pci_write_config_dword(ivideo
->nbridge
, reg
, (u32
)val
);
1019 sisfb_read_lpc_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
)
1021 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1024 if(!ivideo
->lpcdev
) return 0;
1026 pci_read_config_dword(ivideo
->lpcdev
, reg
, &val
);
1027 return (unsigned int)val
;
1031 #ifdef CONFIG_FB_SIS_315
1033 sisfb_write_nbridge_pci_byte(struct SiS_Private
*SiS_Pr
, int reg
, unsigned char val
)
1035 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1037 pci_write_config_byte(ivideo
->nbridge
, reg
, (u8
)val
);
1041 sisfb_read_mio_pci_word(struct SiS_Private
*SiS_Pr
, int reg
)
1043 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1046 if(!ivideo
->lpcdev
) return 0;
1048 pci_read_config_word(ivideo
->lpcdev
, reg
, &val
);
1049 return (unsigned int)val
;
1053 /* ----------- FBDev related routines for all series ----------- */
1056 sisfb_get_cmap_len(const struct fb_var_screeninfo
*var
)
1058 return (var
->bits_per_pixel
== 8) ? 256 : 16;
1062 sisfb_set_vparms(struct sis_video_info
*ivideo
)
1064 switch(ivideo
->video_bpp
) {
1066 ivideo
->DstColor
= 0x0000;
1067 ivideo
->SiS310_AccelDepth
= 0x00000000;
1068 ivideo
->video_cmap_len
= 256;
1071 ivideo
->DstColor
= 0x8000;
1072 ivideo
->SiS310_AccelDepth
= 0x00010000;
1073 ivideo
->video_cmap_len
= 16;
1076 ivideo
->DstColor
= 0xC000;
1077 ivideo
->SiS310_AccelDepth
= 0x00020000;
1078 ivideo
->video_cmap_len
= 16;
1081 ivideo
->video_cmap_len
= 16;
1082 printk(KERN_ERR
"sisfb: Unsupported depth %d", ivideo
->video_bpp
);
1088 sisfb_calc_maxyres(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1090 int maxyres
= ivideo
->sisfb_mem
/ (var
->xres_virtual
* (var
->bits_per_pixel
>> 3));
1092 if(maxyres
> 32767) maxyres
= 32767;
1098 sisfb_calc_pitch(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1100 ivideo
->video_linelength
= var
->xres_virtual
* (var
->bits_per_pixel
>> 3);
1101 ivideo
->scrnpitchCRT1
= ivideo
->video_linelength
;
1102 if(!(ivideo
->currentvbflags
& CRT1_LCDA
)) {
1103 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1104 ivideo
->scrnpitchCRT1
<<= 1;
1110 sisfb_set_pitch(struct sis_video_info
*ivideo
)
1112 bool isslavemode
= false;
1113 unsigned short HDisplay1
= ivideo
->scrnpitchCRT1
>> 3;
1114 unsigned short HDisplay2
= ivideo
->video_linelength
>> 3;
1116 if(sisfb_bridgeisslave(ivideo
)) isslavemode
= true;
1118 /* We need to set pitch for CRT1 if bridge is in slave mode, too */
1119 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP1
) || (isslavemode
)) {
1120 outSISIDXREG(SISCR
,0x13,(HDisplay1
& 0xFF));
1121 setSISIDXREG(SISSR
,0x0E,0xF0,(HDisplay1
>> 8));
1124 /* We must not set the pitch for CRT2 if bridge is in slave mode */
1125 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) && (!isslavemode
)) {
1126 orSISIDXREG(SISPART1
,ivideo
->CRT2_write_enable
,0x01);
1127 outSISIDXREG(SISPART1
,0x07,(HDisplay2
& 0xFF));
1128 setSISIDXREG(SISPART1
,0x09,0xF0,(HDisplay2
>> 8));
1133 sisfb_bpp_to_var(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1135 ivideo
->video_cmap_len
= sisfb_get_cmap_len(var
);
1137 switch(var
->bits_per_pixel
) {
1139 var
->red
.offset
= var
->green
.offset
= var
->blue
.offset
= 0;
1140 var
->red
.length
= var
->green
.length
= var
->blue
.length
= 6;
1143 var
->red
.offset
= 11;
1144 var
->red
.length
= 5;
1145 var
->green
.offset
= 5;
1146 var
->green
.length
= 6;
1147 var
->blue
.offset
= 0;
1148 var
->blue
.length
= 5;
1149 var
->transp
.offset
= 0;
1150 var
->transp
.length
= 0;
1153 var
->red
.offset
= 16;
1154 var
->red
.length
= 8;
1155 var
->green
.offset
= 8;
1156 var
->green
.length
= 8;
1157 var
->blue
.offset
= 0;
1158 var
->blue
.length
= 8;
1159 var
->transp
.offset
= 24;
1160 var
->transp
.length
= 8;
1166 sisfb_set_mode(struct sis_video_info
*ivideo
, int clrscrn
)
1168 unsigned short modeno
= ivideo
->mode_no
;
1170 /* >=2.6.12's fbcon clears the screen anyway */
1171 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
1172 if(!clrscrn
) modeno
|= 0x80;
1177 outSISIDXREG(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1179 sisfb_pre_setmode(ivideo
);
1181 if(!SiSSetMode(&ivideo
->SiS_Pr
, modeno
)) {
1182 printk(KERN_ERR
"sisfb: Setting mode[0x%x] failed\n", ivideo
->mode_no
);
1186 outSISIDXREG(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1188 sisfb_post_setmode(ivideo
);
1195 sisfb_do_set_var(struct fb_var_screeninfo
*var
, int isactive
, struct fb_info
*info
)
1197 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1198 unsigned int htotal
= 0, vtotal
= 0;
1199 unsigned int drate
= 0, hrate
= 0;
1200 int found_mode
= 0, ret
;
1204 htotal
= var
->left_margin
+ var
->xres
+ var
->right_margin
+ var
->hsync_len
;
1206 vtotal
= var
->upper_margin
+ var
->lower_margin
+ var
->vsync_len
;
1208 pixclock
= var
->pixclock
;
1210 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
) {
1211 vtotal
+= var
->yres
;
1213 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1214 vtotal
+= var
->yres
;
1216 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1217 vtotal
+= var
->yres
;
1219 } else vtotal
+= var
->yres
;
1221 if(!(htotal
) || !(vtotal
)) {
1222 DPRINTK("sisfb: Invalid 'var' information\n");
1226 if(pixclock
&& htotal
&& vtotal
) {
1227 drate
= 1000000000 / pixclock
;
1228 hrate
= (drate
* 1000) / htotal
;
1229 ivideo
->refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1231 ivideo
->refresh_rate
= 60;
1234 old_mode
= ivideo
->sisfb_mode_idx
;
1235 ivideo
->sisfb_mode_idx
= 0;
1237 while( (sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[0] != 0) &&
1238 (sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
<= var
->xres
) ) {
1239 if( (sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
== var
->xres
) &&
1240 (sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
== var
->yres
) &&
1241 (sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
== var
->bits_per_pixel
)) {
1242 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
1246 ivideo
->sisfb_mode_idx
++;
1250 ivideo
->sisfb_mode_idx
= sisfb_validate_mode(ivideo
,
1251 ivideo
->sisfb_mode_idx
, ivideo
->currentvbflags
);
1252 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
1254 ivideo
->sisfb_mode_idx
= -1;
1257 if(ivideo
->sisfb_mode_idx
< 0) {
1258 printk(KERN_ERR
"sisfb: Mode %dx%dx%d not supported\n", var
->xres
,
1259 var
->yres
, var
->bits_per_pixel
);
1260 ivideo
->sisfb_mode_idx
= old_mode
;
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));
1409 ((u32
*)(info
->pseudo_palette
))[regno
] =
1411 ((green
& 0xfc00) >> 5) |
1412 ((blue
& 0xf800) >> 11);
1418 ((u32
*)(info
->pseudo_palette
))[regno
] =
1419 (red
<< 16) | (green
<< 8) | (blue
);
1426 sisfb_set_par(struct fb_info
*info
)
1430 if((err
= sisfb_do_set_var(&info
->var
, 1, info
)))
1433 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
1434 sisfb_get_fix(&info
->fix
, info
->currcon
, info
);
1436 sisfb_get_fix(&info
->fix
, -1, info
);
1442 sisfb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
1444 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1445 unsigned int htotal
= 0, vtotal
= 0, myrateindex
= 0;
1446 unsigned int drate
= 0, hrate
= 0, maxyres
;
1448 int refresh_rate
, search_idx
, tidx
;
1449 bool recalc_clock
= false;
1452 htotal
= var
->left_margin
+ var
->xres
+ var
->right_margin
+ var
->hsync_len
;
1454 vtotal
= var
->upper_margin
+ var
->lower_margin
+ var
->vsync_len
;
1456 pixclock
= var
->pixclock
;
1458 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
) {
1459 vtotal
+= var
->yres
;
1461 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1462 vtotal
+= var
->yres
;
1464 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1465 vtotal
+= var
->yres
;
1468 vtotal
+= var
->yres
;
1470 if(!(htotal
) || !(vtotal
)) {
1471 SISFAIL("sisfb: no valid timing data");
1475 while( (sisbios_mode
[search_idx
].mode_no
[0] != 0) &&
1476 (sisbios_mode
[search_idx
].xres
<= var
->xres
) ) {
1477 if( (sisbios_mode
[search_idx
].xres
== var
->xres
) &&
1478 (sisbios_mode
[search_idx
].yres
== var
->yres
) &&
1479 (sisbios_mode
[search_idx
].bpp
== var
->bits_per_pixel
)) {
1480 if((tidx
= sisfb_validate_mode(ivideo
, search_idx
,
1481 ivideo
->currentvbflags
)) > 0) {
1492 while(sisbios_mode
[search_idx
].mode_no
[0] != 0) {
1493 if( (var
->xres
<= sisbios_mode
[search_idx
].xres
) &&
1494 (var
->yres
<= sisbios_mode
[search_idx
].yres
) &&
1495 (var
->bits_per_pixel
== sisbios_mode
[search_idx
].bpp
) ) {
1496 if((tidx
= sisfb_validate_mode(ivideo
,search_idx
,
1497 ivideo
->currentvbflags
)) > 0) {
1507 "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
1508 var
->xres
, var
->yres
, var
->bits_per_pixel
,
1509 sisbios_mode
[search_idx
].xres
,
1510 sisbios_mode
[search_idx
].yres
,
1511 var
->bits_per_pixel
);
1512 var
->xres
= sisbios_mode
[search_idx
].xres
;
1513 var
->yres
= sisbios_mode
[search_idx
].yres
;
1516 "sisfb: Failed to find supported mode near %dx%dx%d\n",
1517 var
->xres
, var
->yres
, var
->bits_per_pixel
);
1522 if( ((ivideo
->vbflags2
& VB2_LVDS
) ||
1523 ((ivideo
->vbflags2
& VB2_30xBDH
) && (ivideo
->currentvbflags
& CRT2_LCD
))) &&
1524 (var
->bits_per_pixel
== 8) ) {
1525 /* Slave modes on LVDS and 301B-DH */
1527 recalc_clock
= true;
1528 } else if( (ivideo
->current_htotal
== htotal
) &&
1529 (ivideo
->current_vtotal
== vtotal
) &&
1530 (ivideo
->current_pixclock
== pixclock
) ) {
1531 /* x=x & y=y & c=c -> assume depth change */
1532 drate
= 1000000000 / pixclock
;
1533 hrate
= (drate
* 1000) / htotal
;
1534 refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1535 } else if( ( (ivideo
->current_htotal
!= htotal
) ||
1536 (ivideo
->current_vtotal
!= vtotal
) ) &&
1537 (ivideo
->current_pixclock
== var
->pixclock
) ) {
1538 /* x!=x | y!=y & c=c -> invalid pixclock */
1539 if(ivideo
->sisfb_lastrates
[sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
]]) {
1541 ivideo
->sisfb_lastrates
[sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
]];
1542 } else if(ivideo
->sisfb_parm_rate
!= -1) {
1543 /* Sic, sisfb_parm_rate - want to know originally desired rate here */
1544 refresh_rate
= ivideo
->sisfb_parm_rate
;
1548 recalc_clock
= true;
1549 } else if((pixclock
) && (htotal
) && (vtotal
)) {
1550 drate
= 1000000000 / pixclock
;
1551 hrate
= (drate
* 1000) / htotal
;
1552 refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1553 } else if(ivideo
->current_refresh_rate
) {
1554 refresh_rate
= ivideo
->current_refresh_rate
;
1555 recalc_clock
= true;
1558 recalc_clock
= true;
1561 myrateindex
= sisfb_search_refresh_rate(ivideo
, refresh_rate
, search_idx
);
1563 /* Eventually recalculate timing and clock */
1565 if(!myrateindex
) myrateindex
= sisbios_mode
[search_idx
].rate_idx
;
1566 var
->pixclock
= (u32
) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo
->SiS_Pr
,
1567 sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
],
1569 sisfb_mode_rate_to_ddata(&ivideo
->SiS_Pr
,
1570 sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
],
1572 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1573 var
->pixclock
<<= 1;
1577 if(ivideo
->sisfb_thismonitor
.datavalid
) {
1578 if(!sisfb_verify_rate(ivideo
, &ivideo
->sisfb_thismonitor
, search_idx
,
1579 myrateindex
, refresh_rate
)) {
1581 "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1585 /* Adapt RGB settings */
1586 sisfb_bpp_to_var(ivideo
, var
);
1588 /* Sanity check for offsets */
1589 if(var
->xoffset
< 0) var
->xoffset
= 0;
1590 if(var
->yoffset
< 0) var
->yoffset
= 0;
1592 if(var
->xres
> var
->xres_virtual
)
1593 var
->xres_virtual
= var
->xres
;
1595 if(ivideo
->sisfb_ypan
) {
1596 maxyres
= sisfb_calc_maxyres(ivideo
, var
);
1597 if(ivideo
->sisfb_max
) {
1598 var
->yres_virtual
= maxyres
;
1600 if(var
->yres_virtual
> maxyres
) {
1601 var
->yres_virtual
= maxyres
;
1604 if(var
->yres_virtual
<= var
->yres
) {
1605 var
->yres_virtual
= var
->yres
;
1608 if(var
->yres
!= var
->yres_virtual
) {
1609 var
->yres_virtual
= var
->yres
;
1615 /* Truncate offsets to maximum if too high */
1616 if(var
->xoffset
> var
->xres_virtual
- var
->xres
) {
1617 var
->xoffset
= var
->xres_virtual
- var
->xres
- 1;
1620 if(var
->yoffset
> var
->yres_virtual
- var
->yres
) {
1621 var
->yoffset
= var
->yres_virtual
- var
->yres
- 1;
1624 /* Set everything else to 0 */
1625 var
->red
.msb_right
=
1626 var
->green
.msb_right
=
1627 var
->blue
.msb_right
=
1628 var
->transp
.offset
=
1629 var
->transp
.length
=
1630 var
->transp
.msb_right
= 0;
1636 sisfb_pan_display(struct fb_var_screeninfo
*var
, struct fb_info
* info
)
1638 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1641 if(var
->xoffset
> (var
->xres_virtual
- var
->xres
))
1644 if(var
->yoffset
> (var
->yres_virtual
- var
->yres
))
1647 if(var
->vmode
& FB_VMODE_YWRAP
)
1650 if(var
->xoffset
+ info
->var
.xres
> info
->var
.xres_virtual
||
1651 var
->yoffset
+ info
->var
.yres
> info
->var
.yres_virtual
)
1654 if((err
= sisfb_pan_var(ivideo
, var
)) < 0)
1657 info
->var
.xoffset
= var
->xoffset
;
1658 info
->var
.yoffset
= var
->yoffset
;
1664 sisfb_blank(int blank
, struct fb_info
*info
)
1666 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1668 return sisfb_myblank(ivideo
, blank
);
1671 /* ----------- FBDev related routines for all series ---------- */
1673 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
1674 static int sisfb_ioctl(struct fb_info
*info
, unsigned int cmd
,
1677 static int sisfb_ioctl(struct inode
*inode
, struct file
*file
,
1678 unsigned int cmd
, unsigned long arg
,
1679 struct fb_info
*info
)
1682 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1683 struct sis_memreq sismemreq
;
1684 struct fb_vblank sisvbblank
;
1689 u32 __user
*argp
= (u32 __user
*)arg
;
1693 if(!capable(CAP_SYS_RAWIO
))
1696 if(copy_from_user(&sismemreq
, (void __user
*)arg
, sizeof(sismemreq
)))
1699 sis_malloc(&sismemreq
);
1701 if(copy_to_user((void __user
*)arg
, &sismemreq
, sizeof(sismemreq
))) {
1702 sis_free((u32
)sismemreq
.offset
);
1708 if(!capable(CAP_SYS_RAWIO
))
1711 if(get_user(gpu32
, argp
))
1717 case FBIOGET_VBLANK
:
1718 sisvbblank
.count
= 0;
1719 sisvbblank
.flags
= sisfb_setupvbblankflags(ivideo
, &sisvbblank
.vcount
, &sisvbblank
.hcount
);
1721 if(copy_to_user((void __user
*)arg
, &sisvbblank
, sizeof(sisvbblank
)))
1726 case SISFB_GET_INFO_SIZE
:
1727 return put_user(sizeof(struct sisfb_info
), argp
);
1729 case SISFB_GET_INFO_OLD
:
1730 if(ivideo
->warncount
++ < 10)
1732 "sisfb: Deprecated ioctl call received - update your application!\n");
1733 case SISFB_GET_INFO
: /* For communication with X driver */
1734 ivideo
->sisfb_infoblock
.sisfb_id
= SISFB_ID
;
1735 ivideo
->sisfb_infoblock
.sisfb_version
= VER_MAJOR
;
1736 ivideo
->sisfb_infoblock
.sisfb_revision
= VER_MINOR
;
1737 ivideo
->sisfb_infoblock
.sisfb_patchlevel
= VER_LEVEL
;
1738 ivideo
->sisfb_infoblock
.chip_id
= ivideo
->chip_id
;
1739 ivideo
->sisfb_infoblock
.sisfb_pci_vendor
= ivideo
->chip_vendor
;
1740 ivideo
->sisfb_infoblock
.memory
= ivideo
->video_size
/ 1024;
1741 ivideo
->sisfb_infoblock
.heapstart
= ivideo
->heapstart
/ 1024;
1742 if(ivideo
->modechanged
) {
1743 ivideo
->sisfb_infoblock
.fbvidmode
= ivideo
->mode_no
;
1745 ivideo
->sisfb_infoblock
.fbvidmode
= ivideo
->modeprechange
;
1747 ivideo
->sisfb_infoblock
.sisfb_caps
= ivideo
->caps
;
1748 ivideo
->sisfb_infoblock
.sisfb_tqlen
= ivideo
->cmdQueueSize
/ 1024;
1749 ivideo
->sisfb_infoblock
.sisfb_pcibus
= ivideo
->pcibus
;
1750 ivideo
->sisfb_infoblock
.sisfb_pcislot
= ivideo
->pcislot
;
1751 ivideo
->sisfb_infoblock
.sisfb_pcifunc
= ivideo
->pcifunc
;
1752 ivideo
->sisfb_infoblock
.sisfb_lcdpdc
= ivideo
->detectedpdc
;
1753 ivideo
->sisfb_infoblock
.sisfb_lcdpdca
= ivideo
->detectedpdca
;
1754 ivideo
->sisfb_infoblock
.sisfb_lcda
= ivideo
->detectedlcda
;
1755 ivideo
->sisfb_infoblock
.sisfb_vbflags
= ivideo
->vbflags
;
1756 ivideo
->sisfb_infoblock
.sisfb_currentvbflags
= ivideo
->currentvbflags
;
1757 ivideo
->sisfb_infoblock
.sisfb_scalelcd
= ivideo
->SiS_Pr
.UsePanelScaler
;
1758 ivideo
->sisfb_infoblock
.sisfb_specialtiming
= ivideo
->SiS_Pr
.SiS_CustomT
;
1759 ivideo
->sisfb_infoblock
.sisfb_haveemi
= ivideo
->SiS_Pr
.HaveEMI
? 1 : 0;
1760 ivideo
->sisfb_infoblock
.sisfb_haveemilcd
= ivideo
->SiS_Pr
.HaveEMILCD
? 1 : 0;
1761 ivideo
->sisfb_infoblock
.sisfb_emi30
= ivideo
->SiS_Pr
.EMI_30
;
1762 ivideo
->sisfb_infoblock
.sisfb_emi31
= ivideo
->SiS_Pr
.EMI_31
;
1763 ivideo
->sisfb_infoblock
.sisfb_emi32
= ivideo
->SiS_Pr
.EMI_32
;
1764 ivideo
->sisfb_infoblock
.sisfb_emi33
= ivideo
->SiS_Pr
.EMI_33
;
1765 ivideo
->sisfb_infoblock
.sisfb_tvxpos
= (u16
)(ivideo
->tvxpos
+ 32);
1766 ivideo
->sisfb_infoblock
.sisfb_tvypos
= (u16
)(ivideo
->tvypos
+ 32);
1767 ivideo
->sisfb_infoblock
.sisfb_heapsize
= ivideo
->sisfb_heap_size
/ 1024;
1768 ivideo
->sisfb_infoblock
.sisfb_videooffset
= ivideo
->video_offset
;
1769 ivideo
->sisfb_infoblock
.sisfb_curfstn
= ivideo
->curFSTN
;
1770 ivideo
->sisfb_infoblock
.sisfb_curdstn
= ivideo
->curDSTN
;
1771 ivideo
->sisfb_infoblock
.sisfb_vbflags2
= ivideo
->vbflags2
;
1772 ivideo
->sisfb_infoblock
.sisfb_can_post
= ivideo
->sisfb_can_post
? 1 : 0;
1773 ivideo
->sisfb_infoblock
.sisfb_card_posted
= ivideo
->sisfb_card_posted
? 1 : 0;
1774 ivideo
->sisfb_infoblock
.sisfb_was_boot_device
= ivideo
->sisfb_was_boot_device
? 1 : 0;
1776 if(copy_to_user((void __user
*)arg
, &ivideo
->sisfb_infoblock
,
1777 sizeof(ivideo
->sisfb_infoblock
)))
1782 case SISFB_GET_VBRSTATUS_OLD
:
1783 if(ivideo
->warncount
++ < 10)
1785 "sisfb: Deprecated ioctl call received - update your application!\n");
1786 case SISFB_GET_VBRSTATUS
:
1787 if(sisfb_CheckVBRetrace(ivideo
))
1788 return put_user((u32
)1, argp
);
1790 return put_user((u32
)0, argp
);
1792 case SISFB_GET_AUTOMAXIMIZE_OLD
:
1793 if(ivideo
->warncount
++ < 10)
1795 "sisfb: Deprecated ioctl call received - update your application!\n");
1796 case SISFB_GET_AUTOMAXIMIZE
:
1797 if(ivideo
->sisfb_max
)
1798 return put_user((u32
)1, argp
);
1800 return put_user((u32
)0, argp
);
1802 case SISFB_SET_AUTOMAXIMIZE_OLD
:
1803 if(ivideo
->warncount
++ < 10)
1805 "sisfb: Deprecated ioctl call received - update your application!\n");
1806 case SISFB_SET_AUTOMAXIMIZE
:
1807 if(get_user(gpu32
, argp
))
1810 ivideo
->sisfb_max
= (gpu32
) ? 1 : 0;
1813 case SISFB_SET_TVPOSOFFSET
:
1814 if(get_user(gpu32
, argp
))
1817 sisfb_set_TVxposoffset(ivideo
, ((int)(gpu32
>> 16)) - 32);
1818 sisfb_set_TVyposoffset(ivideo
, ((int)(gpu32
& 0xffff)) - 32);
1821 case SISFB_GET_TVPOSOFFSET
:
1822 return put_user((u32
)(((ivideo
->tvxpos
+32)<<16)|((ivideo
->tvypos
+32)&0xffff)),
1826 if(copy_from_user(&ivideo
->sisfb_command
, (void __user
*)arg
,
1827 sizeof(struct sisfb_cmd
)))
1830 sisfb_handle_command(ivideo
, &ivideo
->sisfb_command
);
1832 if(copy_to_user((void __user
*)arg
, &ivideo
->sisfb_command
,
1833 sizeof(struct sisfb_cmd
)))
1838 case SISFB_SET_LOCK
:
1839 if(get_user(gpu32
, argp
))
1842 ivideo
->sisfblocked
= (gpu32
) ? 1 : 0;
1846 #ifdef SIS_NEW_CONFIG_COMPAT
1847 return -ENOIOCTLCMD
;
1856 sisfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
, struct fb_info
*info
)
1858 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1860 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
1862 strcpy(fix
->id
, ivideo
->myid
);
1864 fix
->smem_start
= ivideo
->video_base
+ ivideo
->video_offset
;
1865 fix
->smem_len
= ivideo
->sisfb_mem
;
1866 fix
->type
= FB_TYPE_PACKED_PIXELS
;
1868 fix
->visual
= (ivideo
->video_bpp
== 8) ? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_TRUECOLOR
;
1870 fix
->ypanstep
= (ivideo
->sisfb_ypan
) ? 1 : 0;
1872 fix
->line_length
= ivideo
->video_linelength
;
1873 fix
->mmio_start
= ivideo
->mmio_base
;
1874 fix
->mmio_len
= ivideo
->mmio_size
;
1875 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
1876 fix
->accel
= FB_ACCEL_SIS_GLAMOUR
;
1877 } else if((ivideo
->chip
== SIS_330
) ||
1878 (ivideo
->chip
== SIS_760
) ||
1879 (ivideo
->chip
== SIS_761
)) {
1880 fix
->accel
= FB_ACCEL_SIS_XABRE
;
1881 } else if(ivideo
->chip
== XGI_20
) {
1882 fix
->accel
= FB_ACCEL_XGI_VOLARI_Z
;
1883 } else if(ivideo
->chip
>= XGI_40
) {
1884 fix
->accel
= FB_ACCEL_XGI_VOLARI_V
;
1886 fix
->accel
= FB_ACCEL_SIS_GLAMOUR_2
;
1892 /* ---------------- fb_ops structures ----------------- */
1894 static struct fb_ops sisfb_ops
= {
1895 .owner
= THIS_MODULE
,
1896 .fb_open
= sisfb_open
,
1897 .fb_release
= sisfb_release
,
1898 .fb_check_var
= sisfb_check_var
,
1899 .fb_set_par
= sisfb_set_par
,
1900 .fb_setcolreg
= sisfb_setcolreg
,
1901 .fb_pan_display
= sisfb_pan_display
,
1902 .fb_blank
= sisfb_blank
,
1903 .fb_fillrect
= fbcon_sis_fillrect
,
1904 .fb_copyarea
= fbcon_sis_copyarea
,
1905 .fb_imageblit
= cfb_imageblit
,
1906 #ifdef CONFIG_FB_SOFT_CURSOR
1907 .fb_cursor
= soft_cursor
,
1909 .fb_sync
= fbcon_sis_sync
,
1910 #ifdef SIS_NEW_CONFIG_COMPAT
1911 .fb_compat_ioctl
= sisfb_ioctl
,
1913 .fb_ioctl
= sisfb_ioctl
1916 /* ---------------- Chip generation dependent routines ---------------- */
1918 static struct pci_dev
* __devinit
1919 sisfb_get_northbridge(int basechipid
)
1921 struct pci_dev
*pdev
= NULL
;
1922 int nbridgenum
, nbridgeidx
, i
;
1923 static const unsigned short nbridgeids
[] = {
1924 PCI_DEVICE_ID_SI_540
, /* for SiS 540 VGA */
1925 PCI_DEVICE_ID_SI_630
, /* for SiS 630/730 VGA */
1926 PCI_DEVICE_ID_SI_730
,
1927 PCI_DEVICE_ID_SI_550
, /* for SiS 550 VGA */
1928 PCI_DEVICE_ID_SI_650
, /* for SiS 650/651/740 VGA */
1929 PCI_DEVICE_ID_SI_651
,
1930 PCI_DEVICE_ID_SI_740
,
1931 PCI_DEVICE_ID_SI_661
, /* for SiS 661/741/660/760/761 VGA */
1932 PCI_DEVICE_ID_SI_741
,
1933 PCI_DEVICE_ID_SI_660
,
1934 PCI_DEVICE_ID_SI_760
,
1935 PCI_DEVICE_ID_SI_761
1938 switch(basechipid
) {
1939 #ifdef CONFIG_FB_SIS_300
1940 case SIS_540
: nbridgeidx
= 0; nbridgenum
= 1; break;
1941 case SIS_630
: nbridgeidx
= 1; nbridgenum
= 2; break;
1943 #ifdef CONFIG_FB_SIS_315
1944 case SIS_550
: nbridgeidx
= 3; nbridgenum
= 1; break;
1945 case SIS_650
: nbridgeidx
= 4; nbridgenum
= 3; break;
1946 case SIS_660
: nbridgeidx
= 7; nbridgenum
= 5; break;
1948 default: return NULL
;
1950 for(i
= 0; i
< nbridgenum
; i
++) {
1951 if((pdev
= SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI
,
1952 nbridgeids
[nbridgeidx
+i
], NULL
)))
1958 static int __devinit
1959 sisfb_get_dram_size(struct sis_video_info
*ivideo
)
1961 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1965 ivideo
->video_size
= 0;
1966 ivideo
->UMAsize
= ivideo
->LFBsize
= 0;
1968 switch(ivideo
->chip
) {
1969 #ifdef CONFIG_FB_SIS_300
1971 inSISIDXREG(SISSR
, 0x14, reg
);
1972 ivideo
->video_size
= ((reg
& 0x3F) + 1) << 20;
1977 if(!ivideo
->nbridge
)
1979 pci_read_config_byte(ivideo
->nbridge
, 0x63, ®
);
1980 ivideo
->video_size
= 1 << (((reg
& 0x70) >> 4) + 21);
1983 #ifdef CONFIG_FB_SIS_315
1987 inSISIDXREG(SISSR
, 0x14, reg
);
1988 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
1989 switch((reg
>> 2) & 0x03) {
1992 ivideo
->video_size
<<= 1;
1995 ivideo
->video_size
+= (ivideo
->video_size
/2);
1999 inSISIDXREG(SISSR
, 0x14, reg
);
2000 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
2001 if(reg
& 0x0c) ivideo
->video_size
<<= 1;
2006 inSISIDXREG(SISSR
, 0x14, reg
);
2007 ivideo
->video_size
= (((reg
& 0x3f) + 1) << 2) << 20;
2011 inSISIDXREG(SISCR
, 0x79, reg
);
2012 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
2017 inSISIDXREG(SISCR
, 0x79, reg
);
2018 reg
= (reg
& 0xf0) >> 4;
2020 ivideo
->video_size
= (1 << reg
) << 20;
2021 ivideo
->UMAsize
= ivideo
->video_size
;
2023 inSISIDXREG(SISCR
, 0x78, reg
);
2027 ivideo
->LFBsize
= (32 << 20);
2029 ivideo
->LFBsize
= (64 << 20);
2031 ivideo
->video_size
+= ivideo
->LFBsize
;
2037 inSISIDXREG(SISSR
, 0x14, reg
);
2038 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
2039 if(ivideo
->chip
!= XGI_20
) {
2040 reg
= (reg
& 0x0c) >> 2;
2041 if(ivideo
->revision_id
== 2) {
2042 if(reg
& 0x01) reg
= 0x02;
2045 if(reg
== 0x02) ivideo
->video_size
<<= 1;
2046 else if(reg
== 0x03) ivideo
->video_size
<<= 2;
2056 /* -------------- video bridge device detection --------------- */
2058 static void __devinit
2059 sisfb_detect_VB_connect(struct sis_video_info
*ivideo
)
2063 /* No CRT2 on XGI Z7 */
2064 if(ivideo
->chip
== XGI_20
) {
2065 ivideo
->sisfb_crt1off
= 0;
2069 #ifdef CONFIG_FB_SIS_300
2070 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2071 inSISIDXREG(SISSR
, 0x17, temp
);
2072 if((temp
& 0x0F) && (ivideo
->chip
!= SIS_300
)) {
2073 /* PAL/NTSC is stored on SR16 on such machines */
2074 if(!(ivideo
->vbflags
& (TV_PAL
| TV_NTSC
| TV_PALM
| TV_PALN
))) {
2075 inSISIDXREG(SISSR
, 0x16, temp
);
2077 ivideo
->vbflags
|= TV_PAL
;
2079 ivideo
->vbflags
|= TV_NTSC
;
2085 inSISIDXREG(SISCR
, 0x32, cr32
);
2087 if(cr32
& SIS_CRT1
) {
2088 ivideo
->sisfb_crt1off
= 0;
2090 ivideo
->sisfb_crt1off
= (cr32
& 0xDF) ? 1 : 0;
2093 ivideo
->vbflags
&= ~(CRT2_TV
| CRT2_LCD
| CRT2_VGA
);
2095 if(cr32
& SIS_VB_TV
) ivideo
->vbflags
|= CRT2_TV
;
2096 if(cr32
& SIS_VB_LCD
) ivideo
->vbflags
|= CRT2_LCD
;
2097 if(cr32
& SIS_VB_CRT2
) ivideo
->vbflags
|= CRT2_VGA
;
2099 /* Check given parms for hardware compatibility.
2100 * (Cannot do this in the search_xx routines since we don't
2101 * know what hardware we are running on then)
2104 if(ivideo
->chip
!= SIS_550
) {
2105 ivideo
->sisfb_dstn
= ivideo
->sisfb_fstn
= 0;
2108 if(ivideo
->sisfb_tvplug
!= -1) {
2109 if( (ivideo
->sisvga_engine
!= SIS_315_VGA
) ||
2110 (!(ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) ) {
2111 if(ivideo
->sisfb_tvplug
& TV_YPBPR
) {
2112 ivideo
->sisfb_tvplug
= -1;
2113 printk(KERN_ERR
"sisfb: YPbPr not supported\n");
2117 if(ivideo
->sisfb_tvplug
!= -1) {
2118 if( (ivideo
->sisvga_engine
!= SIS_315_VGA
) ||
2119 (!(ivideo
->vbflags2
& VB2_SISHIVISIONBRIDGE
)) ) {
2120 if(ivideo
->sisfb_tvplug
& TV_HIVISION
) {
2121 ivideo
->sisfb_tvplug
= -1;
2122 printk(KERN_ERR
"sisfb: HiVision not supported\n");
2126 if(ivideo
->sisfb_tvstd
!= -1) {
2127 if( (!(ivideo
->vbflags2
& VB2_SISBRIDGE
)) &&
2128 (!((ivideo
->sisvga_engine
== SIS_315_VGA
) &&
2129 (ivideo
->vbflags2
& VB2_CHRONTEL
))) ) {
2130 if(ivideo
->sisfb_tvstd
& (TV_PALN
| TV_PALN
| TV_NTSCJ
)) {
2131 ivideo
->sisfb_tvstd
= -1;
2132 printk(KERN_ERR
"sisfb: PALM/PALN/NTSCJ not supported\n");
2137 /* Detect/set TV plug & type */
2138 if(ivideo
->sisfb_tvplug
!= -1) {
2139 ivideo
->vbflags
|= ivideo
->sisfb_tvplug
;
2141 if(cr32
& SIS_VB_YPBPR
) ivideo
->vbflags
|= (TV_YPBPR
|TV_YPBPR525I
); /* default: 480i */
2142 else if(cr32
& SIS_VB_HIVISION
) ivideo
->vbflags
|= TV_HIVISION
;
2143 else if(cr32
& SIS_VB_SCART
) ivideo
->vbflags
|= TV_SCART
;
2145 if(cr32
& SIS_VB_SVIDEO
) ivideo
->vbflags
|= TV_SVIDEO
;
2146 if(cr32
& SIS_VB_COMPOSITE
) ivideo
->vbflags
|= TV_AVIDEO
;
2150 if(!(ivideo
->vbflags
& (TV_YPBPR
| TV_HIVISION
))) {
2151 if(ivideo
->sisfb_tvstd
!= -1) {
2152 ivideo
->vbflags
&= ~(TV_NTSC
| TV_PAL
| TV_PALM
| TV_PALN
| TV_NTSCJ
);
2153 ivideo
->vbflags
|= ivideo
->sisfb_tvstd
;
2155 if(ivideo
->vbflags
& TV_SCART
) {
2156 ivideo
->vbflags
&= ~(TV_NTSC
| TV_PALM
| TV_PALN
| TV_NTSCJ
);
2157 ivideo
->vbflags
|= TV_PAL
;
2159 if(!(ivideo
->vbflags
& (TV_PAL
| TV_NTSC
| TV_PALM
| TV_PALN
| TV_NTSCJ
))) {
2160 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2161 inSISIDXREG(SISSR
, 0x38, temp
);
2162 if(temp
& 0x01) ivideo
->vbflags
|= TV_PAL
;
2163 else ivideo
->vbflags
|= TV_NTSC
;
2164 } else if((ivideo
->chip
<= SIS_315PRO
) || (ivideo
->chip
>= SIS_330
)) {
2165 inSISIDXREG(SISSR
, 0x38, temp
);
2166 if(temp
& 0x01) ivideo
->vbflags
|= TV_PAL
;
2167 else ivideo
->vbflags
|= TV_NTSC
;
2169 inSISIDXREG(SISCR
, 0x79, temp
);
2170 if(temp
& 0x20) ivideo
->vbflags
|= TV_PAL
;
2171 else ivideo
->vbflags
|= TV_NTSC
;
2176 /* Copy forceCRT1 option to CRT1off if option is given */
2177 if(ivideo
->sisfb_forcecrt1
!= -1) {
2178 ivideo
->sisfb_crt1off
= (ivideo
->sisfb_forcecrt1
) ? 0 : 1;
2182 /* ------------------ Sensing routines ------------------ */
2184 static bool __devinit
2185 sisfb_test_DDC1(struct sis_video_info
*ivideo
)
2190 old
= SiS_ReadDDC1Bit(&ivideo
->SiS_Pr
);
2192 if(old
!= SiS_ReadDDC1Bit(&ivideo
->SiS_Pr
)) break;
2194 return (count
!= -1);
2197 static void __devinit
2198 sisfb_sense_crt1(struct sis_video_info
*ivideo
)
2200 bool mustwait
= false;
2202 #ifdef CONFIG_FB_SIS_315
2208 inSISIDXREG(SISSR
,0x1F,sr1F
);
2209 orSISIDXREG(SISSR
,0x1F,0x04);
2210 andSISIDXREG(SISSR
,0x1F,0x3F);
2211 if(sr1F
& 0xc0) mustwait
= true;
2213 #ifdef CONFIG_FB_SIS_315
2214 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2215 inSISIDXREG(SISCR
,ivideo
->SiS_Pr
.SiS_MyCR63
,cr63
);
2217 andSISIDXREG(SISCR
,ivideo
->SiS_Pr
.SiS_MyCR63
,0xBF);
2221 inSISIDXREG(SISCR
,0x17,cr17
);
2224 orSISIDXREG(SISCR
,0x17,0x80);
2226 outSISIDXREG(SISSR
, 0x00, 0x01);
2227 outSISIDXREG(SISSR
, 0x00, 0x03);
2231 for(i
=0; i
< 10; i
++) sisfbwaitretracecrt1(ivideo
);
2234 #ifdef CONFIG_FB_SIS_315
2235 if(ivideo
->chip
>= SIS_330
) {
2236 andSISIDXREG(SISCR
,0x32,~0x20);
2237 if(ivideo
->chip
>= SIS_340
) {
2238 outSISIDXREG(SISCR
, 0x57, 0x4a);
2240 outSISIDXREG(SISCR
, 0x57, 0x5f);
2242 orSISIDXREG(SISCR
, 0x53, 0x02);
2243 while((inSISREG(SISINPSTAT
)) & 0x01) break;
2244 while(!((inSISREG(SISINPSTAT
)) & 0x01)) break;
2245 if((inSISREG(SISMISCW
)) & 0x10) temp
= 1;
2246 andSISIDXREG(SISCR
, 0x53, 0xfd);
2247 andSISIDXREG(SISCR
, 0x57, 0x00);
2251 if(temp
== 0xffff) {
2254 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
,
2255 ivideo
->sisvga_engine
, 0, 0, NULL
, ivideo
->vbflags2
);
2256 } while(((temp
== 0) || (temp
== 0xffff)) && i
--);
2258 if((temp
== 0) || (temp
== 0xffff)) {
2259 if(sisfb_test_DDC1(ivideo
)) temp
= 1;
2263 if((temp
) && (temp
!= 0xffff)) {
2264 orSISIDXREG(SISCR
,0x32,0x20);
2267 #ifdef CONFIG_FB_SIS_315
2268 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2269 setSISIDXREG(SISCR
,ivideo
->SiS_Pr
.SiS_MyCR63
,0xBF,cr63
);
2273 setSISIDXREG(SISCR
,0x17,0x7F,cr17
);
2275 outSISIDXREG(SISSR
,0x1F,sr1F
);
2278 /* Determine and detect attached devices on SiS30x */
2279 static void __devinit
2280 SiS_SenseLCD(struct sis_video_info
*ivideo
)
2282 unsigned char buffer
[256];
2283 unsigned short temp
, realcrtno
, i
;
2284 u8 reg
, cr37
= 0, paneltype
= 0;
2287 ivideo
->SiS_Pr
.PanelSelfDetected
= false;
2289 /* LCD detection only for TMDS bridges */
2290 if(!(ivideo
->vbflags2
& VB2_SISTMDSBRIDGE
))
2292 if(ivideo
->vbflags2
& VB2_30xBDH
)
2295 /* If LCD already set up by BIOS, skip it */
2296 inSISIDXREG(SISCR
, 0x32, reg
);
2301 if(ivideo
->SiS_Pr
.DDCPortMixup
)
2304 /* Check DDC capabilities */
2305 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
2306 realcrtno
, 0, &buffer
[0], ivideo
->vbflags2
);
2308 if((!temp
) || (temp
== 0xffff) || (!(temp
& 0x02)))
2312 i
= 3; /* Number of retrys */
2314 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
,
2315 ivideo
->sisvga_engine
, realcrtno
, 1,
2316 &buffer
[0], ivideo
->vbflags2
);
2317 } while((temp
) && i
--);
2322 /* No digital device */
2323 if(!(buffer
[0x14] & 0x80))
2326 /* First detailed timing preferred timing? */
2327 if(!(buffer
[0x18] & 0x02))
2330 xres
= buffer
[0x38] | ((buffer
[0x3a] & 0xf0) << 4);
2331 yres
= buffer
[0x3b] | ((buffer
[0x3d] & 0xf0) << 4);
2343 if((yres
== 1200) && (ivideo
->vbflags2
& VB2_30xC
))
2354 if((buffer
[0x47] & 0x18) == 0x18)
2355 cr37
|= ((((buffer
[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2359 outSISIDXREG(SISCR
, 0x36, paneltype
);
2361 setSISIDXREG(SISCR
, 0x37, 0x0c, cr37
);
2362 orSISIDXREG(SISCR
, 0x32, 0x08);
2364 ivideo
->SiS_Pr
.PanelSelfDetected
= true;
2367 static int __devinit
2368 SISDoSense(struct sis_video_info
*ivideo
, u16 type
, u16 test
)
2370 int temp
, mytest
, result
, i
, j
;
2372 for(j
= 0; j
< 10; j
++) {
2374 for(i
= 0; i
< 3; i
++) {
2376 outSISIDXREG(SISPART4
,0x11,(type
& 0x00ff));
2377 temp
= (type
>> 8) | (mytest
& 0x00ff);
2378 setSISIDXREG(SISPART4
,0x10,0xe0,temp
);
2379 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x1500);
2382 inSISIDXREG(SISPART4
,0x03,temp
);
2385 if(temp
== mytest
) result
++;
2387 outSISIDXREG(SISPART4
,0x11,0x00);
2388 andSISIDXREG(SISPART4
,0x10,0xe0);
2389 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x1000);
2392 if((result
== 0) || (result
>= 2)) break;
2397 static void __devinit
2398 SiS_Sense30x(struct sis_video_info
*ivideo
)
2400 u8 backupP4_0d
,backupP2_00
,backupP2_4d
,backupSR_1e
,biosflag
=0;
2401 u16 svhs
=0, svhs_c
=0;
2402 u16 cvbs
=0, cvbs_c
=0;
2403 u16 vga2
=0, vga2_c
=0;
2405 char stdstr
[] = "sisfb: Detected";
2406 char tvstr
[] = "TV connected to";
2408 if(ivideo
->vbflags2
& VB2_301
) {
2409 svhs
= 0x00b9; cvbs
= 0x00b3; vga2
= 0x00d1;
2410 inSISIDXREG(SISPART4
,0x01,myflag
);
2412 svhs
= 0x00dd; cvbs
= 0x00ee; vga2
= 0x00fd;
2414 } else if(ivideo
->vbflags2
& (VB2_301B
| VB2_302B
)) {
2415 svhs
= 0x016b; cvbs
= 0x0174; vga2
= 0x0190;
2416 } else if(ivideo
->vbflags2
& (VB2_301LV
| VB2_302LV
)) {
2417 svhs
= 0x0200; cvbs
= 0x0100;
2418 } else if(ivideo
->vbflags2
& (VB2_301C
| VB2_302ELV
| VB2_307T
| VB2_307LV
)) {
2419 svhs
= 0x016b; cvbs
= 0x0110; vga2
= 0x0190;
2423 vga2_c
= 0x0e08; svhs_c
= 0x0404; cvbs_c
= 0x0804;
2424 if(ivideo
->vbflags
& (VB2_301LV
|VB2_302LV
|VB2_302ELV
|VB2_307LV
)) {
2425 svhs_c
= 0x0408; cvbs_c
= 0x0808;
2429 if(ivideo
->haveXGIROM
) {
2430 biosflag
= ivideo
->bios_abase
[0x58] & 0x03;
2431 } else if(ivideo
->newrom
) {
2432 if(ivideo
->bios_abase
[0x5d] & 0x04) biosflag
|= 0x01;
2433 } else if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2434 if(ivideo
->bios_abase
) {
2435 biosflag
= ivideo
->bios_abase
[0xfe] & 0x03;
2439 if(ivideo
->chip
== SIS_300
) {
2440 inSISIDXREG(SISSR
,0x3b,myflag
);
2441 if(!(myflag
& 0x01)) vga2
= vga2_c
= 0;
2444 if(!(ivideo
->vbflags2
& VB2_SISVGA2BRIDGE
)) {
2448 inSISIDXREG(SISSR
,0x1e,backupSR_1e
);
2449 orSISIDXREG(SISSR
,0x1e,0x20);
2451 inSISIDXREG(SISPART4
,0x0d,backupP4_0d
);
2452 if(ivideo
->vbflags2
& VB2_30xC
) {
2453 setSISIDXREG(SISPART4
,0x0d,~0x07,0x01);
2455 orSISIDXREG(SISPART4
,0x0d,0x04);
2457 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x2000);
2459 inSISIDXREG(SISPART2
,0x00,backupP2_00
);
2460 outSISIDXREG(SISPART2
,0x00,((backupP2_00
| 0x1c) & 0xfc));
2462 inSISIDXREG(SISPART2
,0x4d,backupP2_4d
);
2463 if(ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
) {
2464 outSISIDXREG(SISPART2
,0x4d,(backupP2_4d
& ~0x10));
2467 if(!(ivideo
->vbflags2
& VB2_30xCLV
)) {
2468 SISDoSense(ivideo
, 0, 0);
2471 andSISIDXREG(SISCR
, 0x32, ~0x14);
2473 if(vga2_c
|| vga2
) {
2474 if(SISDoSense(ivideo
, vga2
, vga2_c
)) {
2475 if(biosflag
& 0x01) {
2476 printk(KERN_INFO
"%s %s SCART output\n", stdstr
, tvstr
);
2477 orSISIDXREG(SISCR
, 0x32, 0x04);
2479 printk(KERN_INFO
"%s secondary VGA connection\n", stdstr
);
2480 orSISIDXREG(SISCR
, 0x32, 0x10);
2485 andSISIDXREG(SISCR
, 0x32, 0x3f);
2487 if(ivideo
->vbflags2
& VB2_30xCLV
) {
2488 orSISIDXREG(SISPART4
,0x0d,0x04);
2491 if((ivideo
->sisvga_engine
== SIS_315_VGA
) && (ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) {
2492 outSISIDXREG(SISPART2
,0x4d,(backupP2_4d
| 0x10));
2493 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x2000);
2494 if((result
= SISDoSense(ivideo
, svhs
, 0x0604))) {
2495 if((result
= SISDoSense(ivideo
, cvbs
, 0x0804))) {
2496 printk(KERN_INFO
"%s %s YPbPr component output\n", stdstr
, tvstr
);
2497 orSISIDXREG(SISCR
,0x32,0x80);
2500 outSISIDXREG(SISPART2
,0x4d,backupP2_4d
);
2503 andSISIDXREG(SISCR
, 0x32, ~0x03);
2505 if(!(ivideo
->vbflags
& TV_YPBPR
)) {
2506 if((result
= SISDoSense(ivideo
, svhs
, svhs_c
))) {
2507 printk(KERN_INFO
"%s %s SVIDEO output\n", stdstr
, tvstr
);
2508 orSISIDXREG(SISCR
, 0x32, 0x02);
2510 if((biosflag
& 0x02) || (!result
)) {
2511 if(SISDoSense(ivideo
, cvbs
, cvbs_c
)) {
2512 printk(KERN_INFO
"%s %s COMPOSITE output\n", stdstr
, tvstr
);
2513 orSISIDXREG(SISCR
, 0x32, 0x01);
2518 SISDoSense(ivideo
, 0, 0);
2520 outSISIDXREG(SISPART2
,0x00,backupP2_00
);
2521 outSISIDXREG(SISPART4
,0x0d,backupP4_0d
);
2522 outSISIDXREG(SISSR
,0x1e,backupSR_1e
);
2524 if(ivideo
->vbflags2
& VB2_30xCLV
) {
2525 inSISIDXREG(SISPART2
,0x00,biosflag
);
2526 if(biosflag
& 0x20) {
2527 for(myflag
= 2; myflag
> 0; myflag
--) {
2529 outSISIDXREG(SISPART2
,0x00,biosflag
);
2534 outSISIDXREG(SISPART2
,0x00,backupP2_00
);
2537 /* Determine and detect attached TV's on Chrontel */
2538 static void __devinit
2539 SiS_SenseCh(struct sis_video_info
*ivideo
)
2541 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2543 char stdstr
[] = "sisfb: Chrontel: Detected TV connected to";
2545 #ifdef CONFIG_FB_SIS_300
2546 unsigned char test
[3];
2550 if(ivideo
->chip
< SIS_315H
) {
2552 #ifdef CONFIG_FB_SIS_300
2553 ivideo
->SiS_Pr
.SiS_IF_DEF_CH70xx
= 1; /* Chrontel 700x */
2554 SiS_SetChrontelGPIO(&ivideo
->SiS_Pr
, 0x9c); /* Set general purpose IO for Chrontel communication */
2555 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 1000);
2556 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x25);
2557 /* See Chrontel TB31 for explanation */
2558 temp2
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0e);
2559 if(((temp2
& 0x07) == 0x01) || (temp2
& 0x04)) {
2560 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0e, 0x0b);
2561 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 300);
2563 temp2
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x25);
2564 if(temp2
!= temp1
) temp1
= temp2
;
2566 if((temp1
>= 0x22) && (temp1
<= 0x50)) {
2567 /* Read power status */
2568 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0e);
2569 if((temp1
& 0x03) != 0x03) {
2570 /* Power all outputs */
2571 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0e,0x0b);
2572 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 300);
2574 /* Sense connected TV devices */
2575 for(i
= 0; i
< 3; i
++) {
2576 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x10, 0x01);
2577 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2578 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x10, 0x00);
2579 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2580 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x10);
2581 if(!(temp1
& 0x08)) test
[i
] = 0x02;
2582 else if(!(temp1
& 0x02)) test
[i
] = 0x01;
2584 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2587 if(test
[0] == test
[1]) temp1
= test
[0];
2588 else if(test
[0] == test
[2]) temp1
= test
[0];
2589 else if(test
[1] == test
[2]) temp1
= test
[1];
2592 "sisfb: TV detection unreliable - test results varied\n");
2596 printk(KERN_INFO
"%s SVIDEO output\n", stdstr
);
2597 ivideo
->vbflags
|= TV_SVIDEO
;
2598 orSISIDXREG(SISCR
, 0x32, 0x02);
2599 andSISIDXREG(SISCR
, 0x32, ~0x05);
2600 } else if (temp1
== 0x01) {
2601 printk(KERN_INFO
"%s CVBS output\n", stdstr
);
2602 ivideo
->vbflags
|= TV_AVIDEO
;
2603 orSISIDXREG(SISCR
, 0x32, 0x01);
2604 andSISIDXREG(SISCR
, 0x32, ~0x06);
2606 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x0e, 0x01, 0xF8);
2607 andSISIDXREG(SISCR
, 0x32, ~0x07);
2609 } else if(temp1
== 0) {
2610 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x0e, 0x01, 0xF8);
2611 andSISIDXREG(SISCR
, 0x32, ~0x07);
2613 /* Set general purpose IO for Chrontel communication */
2614 SiS_SetChrontelGPIO(&ivideo
->SiS_Pr
, 0x00);
2619 #ifdef CONFIG_FB_SIS_315
2620 ivideo
->SiS_Pr
.SiS_IF_DEF_CH70xx
= 2; /* Chrontel 7019 */
2621 temp1
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x49);
2622 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x49, 0x20);
2623 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2624 temp2
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x20);
2626 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x20, temp2
);
2627 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2629 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x20, temp2
);
2630 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2631 temp2
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x20);
2632 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x49, temp1
);
2634 if(temp2
& 0x02) temp1
|= 0x01;
2635 if(temp2
& 0x10) temp1
|= 0x01;
2636 if(temp2
& 0x04) temp1
|= 0x02;
2637 if( (temp1
& 0x01) && (temp1
& 0x02) ) temp1
= 0x04;
2640 printk(KERN_INFO
"%s CVBS output\n", stdstr
);
2641 ivideo
->vbflags
|= TV_AVIDEO
;
2642 orSISIDXREG(SISCR
, 0x32, 0x01);
2643 andSISIDXREG(SISCR
, 0x32, ~0x06);
2646 printk(KERN_INFO
"%s SVIDEO output\n", stdstr
);
2647 ivideo
->vbflags
|= TV_SVIDEO
;
2648 orSISIDXREG(SISCR
, 0x32, 0x02);
2649 andSISIDXREG(SISCR
, 0x32, ~0x05);
2652 printk(KERN_INFO
"%s SCART output\n", stdstr
);
2653 orSISIDXREG(SISCR
, 0x32, 0x04);
2654 andSISIDXREG(SISCR
, 0x32, ~0x03);
2657 andSISIDXREG(SISCR
, 0x32, ~0x07);
2663 static void __devinit
2664 sisfb_get_VB_type(struct sis_video_info
*ivideo
)
2666 char stdstr
[] = "sisfb: Detected";
2667 char bridgestr
[] = "video bridge";
2671 /* No CRT2 on XGI Z7 */
2672 if(ivideo
->chip
== XGI_20
)
2675 inSISIDXREG(SISPART4
, 0x00, vb_chipid
);
2678 inSISIDXREG(SISPART4
, 0x01, reg
);
2680 ivideo
->vbflags
|= VB_301
; /* Deprecated */
2681 ivideo
->vbflags2
|= VB2_301
;
2682 printk(KERN_INFO
"%s SiS301 %s\n", stdstr
, bridgestr
);
2683 } else if(reg
< 0xc0) {
2684 ivideo
->vbflags
|= VB_301B
; /* Deprecated */
2685 ivideo
->vbflags2
|= VB2_301B
;
2686 inSISIDXREG(SISPART4
,0x23,reg
);
2688 ivideo
->vbflags
|= VB_30xBDH
; /* Deprecated */
2689 ivideo
->vbflags2
|= VB2_30xBDH
;
2690 printk(KERN_INFO
"%s SiS301B-DH %s\n", stdstr
, bridgestr
);
2692 printk(KERN_INFO
"%s SiS301B %s\n", stdstr
, bridgestr
);
2694 } else if(reg
< 0xd0) {
2695 ivideo
->vbflags
|= VB_301C
; /* Deprecated */
2696 ivideo
->vbflags2
|= VB2_301C
;
2697 printk(KERN_INFO
"%s SiS301C %s\n", stdstr
, bridgestr
);
2698 } else if(reg
< 0xe0) {
2699 ivideo
->vbflags
|= VB_301LV
; /* Deprecated */
2700 ivideo
->vbflags2
|= VB2_301LV
;
2701 printk(KERN_INFO
"%s SiS301LV %s\n", stdstr
, bridgestr
);
2702 } else if(reg
<= 0xe1) {
2703 inSISIDXREG(SISPART4
,0x39,reg
);
2705 ivideo
->vbflags
|= VB_302LV
; /* Deprecated */
2706 ivideo
->vbflags2
|= VB2_302LV
;
2707 printk(KERN_INFO
"%s SiS302LV %s\n", stdstr
, bridgestr
);
2709 ivideo
->vbflags
|= VB_301C
; /* Deprecated */
2710 ivideo
->vbflags2
|= VB2_301C
;
2711 printk(KERN_INFO
"%s SiS301C(P4) %s\n", stdstr
, bridgestr
);
2713 ivideo
->vbflags
|= VB_302ELV
; /* Deprecated */
2714 ivideo
->vbflags2
|= VB2_302ELV
;
2715 printk(KERN_INFO
"%s SiS302ELV %s\n", stdstr
, bridgestr
);
2721 ivideo
->vbflags
|= VB_302B
; /* Deprecated */
2722 ivideo
->vbflags2
|= VB2_302B
;
2723 printk(KERN_INFO
"%s SiS302B %s\n", stdstr
, bridgestr
);
2727 if((!(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
)) && (ivideo
->chip
!= SIS_300
)) {
2728 inSISIDXREG(SISCR
, 0x37, reg
);
2729 reg
&= SIS_EXTERNAL_CHIP_MASK
;
2731 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2732 #ifdef CONFIG_FB_SIS_300
2734 case SIS_EXTERNAL_CHIP_LVDS
:
2735 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2736 ivideo
->vbflags2
|= VB2_LVDS
;
2738 case SIS_EXTERNAL_CHIP_TRUMPION
:
2739 ivideo
->vbflags
|= (VB_LVDS
| VB_TRUMPION
); /* Deprecated */
2740 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_TRUMPION
);
2742 case SIS_EXTERNAL_CHIP_CHRONTEL
:
2743 ivideo
->vbflags
|= VB_CHRONTEL
; /* Deprecated */
2744 ivideo
->vbflags2
|= VB2_CHRONTEL
;
2746 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL
:
2747 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2748 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2751 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 1;
2753 } else if(ivideo
->chip
< SIS_661
) {
2754 #ifdef CONFIG_FB_SIS_315
2756 case SIS310_EXTERNAL_CHIP_LVDS
:
2757 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2758 ivideo
->vbflags2
|= VB2_LVDS
;
2760 case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL
:
2761 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2762 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2765 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 2;
2767 } else if(ivideo
->chip
>= SIS_661
) {
2768 #ifdef CONFIG_FB_SIS_315
2769 inSISIDXREG(SISCR
, 0x38, reg
);
2773 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2774 ivideo
->vbflags2
|= VB2_LVDS
;
2777 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2778 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2781 ivideo
->vbflags
|= (VB_LVDS
| VB_CONEXANT
); /* Deprecated */
2782 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CONEXANT
);
2785 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 2;
2788 if(ivideo
->vbflags2
& VB2_LVDS
) {
2789 printk(KERN_INFO
"%s LVDS transmitter\n", stdstr
);
2791 if((ivideo
->sisvga_engine
== SIS_300_VGA
) && (ivideo
->vbflags2
& VB2_TRUMPION
)) {
2792 printk(KERN_INFO
"%s Trumpion Zurac LCD scaler\n", stdstr
);
2794 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
2795 printk(KERN_INFO
"%s Chrontel TV encoder\n", stdstr
);
2797 if((ivideo
->chip
>= SIS_661
) && (ivideo
->vbflags2
& VB2_CONEXANT
)) {
2798 printk(KERN_INFO
"%s Conexant external device\n", stdstr
);
2802 if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
2803 SiS_SenseLCD(ivideo
);
2804 SiS_Sense30x(ivideo
);
2805 } else if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
2806 SiS_SenseCh(ivideo
);
2810 /* ---------- Engine initialization routines ------------ */
2813 sisfb_engine_init(struct sis_video_info
*ivideo
)
2816 /* Initialize command queue (we use MMIO only) */
2818 /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
2820 ivideo
->caps
&= ~(TURBO_QUEUE_CAP
|
2821 MMIO_CMD_QUEUE_CAP
|
2825 #ifdef CONFIG_FB_SIS_300
2826 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2830 tqueue_pos
= (ivideo
->video_size
- ivideo
->cmdQueueSize
) / (64 * 1024);
2832 inSISIDXREG(SISSR
, IND_SIS_TURBOQUEUE_SET
, tq_state
);
2835 tq_state
|= (u8
)(tqueue_pos
>> 8);
2836 outSISIDXREG(SISSR
, IND_SIS_TURBOQUEUE_SET
, tq_state
);
2838 outSISIDXREG(SISSR
, IND_SIS_TURBOQUEUE_ADR
, (u8
)(tqueue_pos
& 0xff));
2840 ivideo
->caps
|= TURBO_QUEUE_CAP
;
2844 #ifdef CONFIG_FB_SIS_315
2845 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2846 u32 tempq
= 0, templ
;
2849 if(ivideo
->chip
== XGI_20
) {
2850 switch(ivideo
->cmdQueueSize
) {
2852 temp
= SIS_CMD_QUEUE_SIZE_Z7_64k
;
2856 temp
= SIS_CMD_QUEUE_SIZE_Z7_128k
;
2859 switch(ivideo
->cmdQueueSize
) {
2860 case (4 * 1024 * 1024):
2861 temp
= SIS_CMD_QUEUE_SIZE_4M
;
2863 case (2 * 1024 * 1024):
2864 temp
= SIS_CMD_QUEUE_SIZE_2M
;
2866 case (1 * 1024 * 1024):
2867 temp
= SIS_CMD_QUEUE_SIZE_1M
;
2871 temp
= SIS_CMD_QUEUE_SIZE_512k
;
2875 outSISIDXREG(SISSR
, IND_SIS_CMDQUEUE_THRESHOLD
, COMMAND_QUEUE_THRESHOLD
);
2876 outSISIDXREG(SISSR
, IND_SIS_CMDQUEUE_SET
, SIS_CMD_QUEUE_RESET
);
2878 if((ivideo
->chip
>= XGI_40
) && ivideo
->modechanged
) {
2879 /* Must disable dual pipe on XGI_40. Can't do
2880 * this in MMIO mode, because it requires
2881 * setting/clearing a bit in the MMIO fire trigger
2884 if(!((templ
= MMIO_IN32(ivideo
->mmio_vbase
, 0x8240)) & (1 << 10))) {
2886 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, 0);
2888 outSISIDXREG(SISSR
, IND_SIS_CMDQUEUE_SET
, (temp
| SIS_VRAM_CMDQUEUE_ENABLE
));
2890 tempq
= MMIO_IN32(ivideo
->mmio_vbase
, Q_READ_PTR
);
2891 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, tempq
);
2893 tempq
= (u32
)(ivideo
->video_size
- ivideo
->cmdQueueSize
);
2894 MMIO_OUT32(ivideo
->mmio_vbase
, Q_BASE_ADDR
, tempq
);
2896 writel(0x16800000 + 0x8240, ivideo
->video_vbase
+ tempq
);
2897 writel(templ
| (1 << 10), ivideo
->video_vbase
+ tempq
+ 4);
2898 writel(0x168F0000, ivideo
->video_vbase
+ tempq
+ 8);
2899 writel(0x168F0000, ivideo
->video_vbase
+ tempq
+ 12);
2901 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, (tempq
+ 16));
2903 sisfb_syncaccel(ivideo
);
2905 outSISIDXREG(SISSR
, IND_SIS_CMDQUEUE_SET
, SIS_CMD_QUEUE_RESET
);
2910 tempq
= MMIO_IN32(ivideo
->mmio_vbase
, MMIO_QUEUE_READPORT
);
2911 MMIO_OUT32(ivideo
->mmio_vbase
, MMIO_QUEUE_WRITEPORT
, tempq
);
2913 temp
|= (SIS_MMIO_CMD_ENABLE
| SIS_CMD_AUTO_CORR
);
2914 outSISIDXREG(SISSR
, IND_SIS_CMDQUEUE_SET
, temp
);
2916 tempq
= (u32
)(ivideo
->video_size
- ivideo
->cmdQueueSize
);
2917 MMIO_OUT32(ivideo
->mmio_vbase
, MMIO_QUEUE_PHYBASE
, tempq
);
2919 ivideo
->caps
|= MMIO_CMD_QUEUE_CAP
;
2923 ivideo
->engineok
= 1;
2926 static void __devinit
2927 sisfb_detect_lcd_type(struct sis_video_info
*ivideo
)
2932 inSISIDXREG(SISCR
, 0x36, reg
);
2934 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2935 ivideo
->CRT2LCDType
= sis300paneltype
[reg
];
2936 } else if(ivideo
->chip
>= SIS_661
) {
2937 ivideo
->CRT2LCDType
= sis661paneltype
[reg
];
2939 ivideo
->CRT2LCDType
= sis310paneltype
[reg
];
2940 if((ivideo
->chip
== SIS_550
) && (sisfb_fstn
)) {
2941 if((ivideo
->CRT2LCDType
!= LCD_320x240_2
) &&
2942 (ivideo
->CRT2LCDType
!= LCD_320x240_3
)) {
2943 ivideo
->CRT2LCDType
= LCD_320x240
;
2948 if(ivideo
->CRT2LCDType
== LCD_UNKNOWN
) {
2949 /* For broken BIOSes: Assume 1024x768, RGB18 */
2950 ivideo
->CRT2LCDType
= LCD_1024x768
;
2951 setSISIDXREG(SISCR
,0x36,0xf0,0x02);
2952 setSISIDXREG(SISCR
,0x37,0xee,0x01);
2953 printk(KERN_DEBUG
"sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg
);
2956 for(i
= 0; i
< SIS_LCD_NUMBER
; i
++) {
2957 if(ivideo
->CRT2LCDType
== sis_lcd_data
[i
].lcdtype
) {
2958 ivideo
->lcdxres
= sis_lcd_data
[i
].xres
;
2959 ivideo
->lcdyres
= sis_lcd_data
[i
].yres
;
2960 ivideo
->lcddefmodeidx
= sis_lcd_data
[i
].default_mode_idx
;
2965 #ifdef CONFIG_FB_SIS_300
2966 if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_BARCO1366
) {
2967 ivideo
->lcdxres
= 1360; ivideo
->lcdyres
= 1024;
2968 ivideo
->lcddefmodeidx
= DEFAULT_MODE_1360
;
2969 } else if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_PANEL848
) {
2970 ivideo
->lcdxres
= 848; ivideo
->lcdyres
= 480;
2971 ivideo
->lcddefmodeidx
= DEFAULT_MODE_848
;
2972 } else if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_PANEL856
) {
2973 ivideo
->lcdxres
= 856; ivideo
->lcdyres
= 480;
2974 ivideo
->lcddefmodeidx
= DEFAULT_MODE_856
;
2978 printk(KERN_DEBUG
"sisfb: Detected %dx%d flat panel\n",
2979 ivideo
->lcdxres
, ivideo
->lcdyres
);
2982 static void __devinit
2983 sisfb_save_pdc_emi(struct sis_video_info
*ivideo
)
2985 #ifdef CONFIG_FB_SIS_300
2986 /* Save the current PanelDelayCompensation if the LCD is currently used */
2987 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2988 if(ivideo
->vbflags2
& (VB2_LVDS
| VB2_30xBDH
)) {
2990 inSISIDXREG(SISCR
,0x30,tmp
);
2992 /* Currently on LCD? If yes, read current pdc */
2993 inSISIDXREG(SISPART1
,0x13,ivideo
->detectedpdc
);
2994 ivideo
->detectedpdc
&= 0x3c;
2995 if(ivideo
->SiS_Pr
.PDC
== -1) {
2996 /* Let option override detection */
2997 ivideo
->SiS_Pr
.PDC
= ivideo
->detectedpdc
;
2999 printk(KERN_INFO
"sisfb: Detected LCD PDC 0x%02x\n",
3000 ivideo
->detectedpdc
);
3002 if((ivideo
->SiS_Pr
.PDC
!= -1) &&
3003 (ivideo
->SiS_Pr
.PDC
!= ivideo
->detectedpdc
)) {
3004 printk(KERN_INFO
"sisfb: Using LCD PDC 0x%02x\n",
3005 ivideo
->SiS_Pr
.PDC
);
3011 #ifdef CONFIG_FB_SIS_315
3012 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3014 /* Try to find about LCDA */
3015 if(ivideo
->vbflags2
& VB2_SISLCDABRIDGE
) {
3017 inSISIDXREG(SISPART1
,0x13,tmp
);
3019 ivideo
->SiS_Pr
.SiS_UseLCDA
= true;
3020 ivideo
->detectedlcda
= 0x03;
3025 if(ivideo
->vbflags2
& VB2_SISLVDSBRIDGE
) {
3027 inSISIDXREG(SISCR
,0x30,tmp
);
3028 if((tmp
& 0x20) || (ivideo
->detectedlcda
!= 0xff)) {
3029 /* Currently on LCD? If yes, read current pdc */
3031 inSISIDXREG(SISPART1
,0x2D,pdc
);
3032 ivideo
->detectedpdc
= (pdc
& 0x0f) << 1;
3033 ivideo
->detectedpdca
= (pdc
& 0xf0) >> 3;
3034 inSISIDXREG(SISPART1
,0x35,pdc
);
3035 ivideo
->detectedpdc
|= ((pdc
>> 7) & 0x01);
3036 inSISIDXREG(SISPART1
,0x20,pdc
);
3037 ivideo
->detectedpdca
|= ((pdc
>> 6) & 0x01);
3038 if(ivideo
->newrom
) {
3039 /* New ROM invalidates other PDC resp. */
3040 if(ivideo
->detectedlcda
!= 0xff) {
3041 ivideo
->detectedpdc
= 0xff;
3043 ivideo
->detectedpdca
= 0xff;
3046 if(ivideo
->SiS_Pr
.PDC
== -1) {
3047 if(ivideo
->detectedpdc
!= 0xff) {
3048 ivideo
->SiS_Pr
.PDC
= ivideo
->detectedpdc
;
3051 if(ivideo
->SiS_Pr
.PDCA
== -1) {
3052 if(ivideo
->detectedpdca
!= 0xff) {
3053 ivideo
->SiS_Pr
.PDCA
= ivideo
->detectedpdca
;
3056 if(ivideo
->detectedpdc
!= 0xff) {
3058 "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3059 ivideo
->detectedpdc
);
3061 if(ivideo
->detectedpdca
!= 0xff) {
3063 "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3064 ivideo
->detectedpdca
);
3069 if(ivideo
->vbflags2
& VB2_SISEMIBRIDGE
) {
3070 inSISIDXREG(SISPART4
,0x30,ivideo
->SiS_Pr
.EMI_30
);
3071 inSISIDXREG(SISPART4
,0x31,ivideo
->SiS_Pr
.EMI_31
);
3072 inSISIDXREG(SISPART4
,0x32,ivideo
->SiS_Pr
.EMI_32
);
3073 inSISIDXREG(SISPART4
,0x33,ivideo
->SiS_Pr
.EMI_33
);
3074 ivideo
->SiS_Pr
.HaveEMI
= true;
3075 if((tmp
& 0x20) || (ivideo
->detectedlcda
!= 0xff)) {
3076 ivideo
->SiS_Pr
.HaveEMILCD
= true;
3081 /* Let user override detected PDCs (all bridges) */
3082 if(ivideo
->vbflags2
& VB2_30xBLV
) {
3083 if((ivideo
->SiS_Pr
.PDC
!= -1) &&
3084 (ivideo
->SiS_Pr
.PDC
!= ivideo
->detectedpdc
)) {
3085 printk(KERN_INFO
"sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3086 ivideo
->SiS_Pr
.PDC
);
3088 if((ivideo
->SiS_Pr
.PDCA
!= -1) &&
3089 (ivideo
->SiS_Pr
.PDCA
!= ivideo
->detectedpdca
)) {
3090 printk(KERN_INFO
"sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3091 ivideo
->SiS_Pr
.PDCA
);
3099 /* -------------------- Memory manager routines ---------------------- */
3101 static u32 __devinit
3102 sisfb_getheapstart(struct sis_video_info
*ivideo
)
3104 u32 ret
= ivideo
->sisfb_parm_mem
* 1024;
3105 u32 maxoffs
= ivideo
->video_size
- ivideo
->hwcursor_size
- ivideo
->cmdQueueSize
;
3108 /* Calculate heap start = end of memory for console
3110 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3111 * C = console, D = heap, H = HWCursor, Q = cmd-queue
3113 * On 76x in UMA+LFB mode, the layout is as follows:
3114 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3115 * where the heap is the entire UMA area, eventually
3116 * into the LFB area if the given mem parameter is
3117 * higher than the size of the UMA memory.
3119 * Basically given by "mem" parameter
3121 * maximum = videosize - cmd_queue - hwcursor
3122 * (results in a heap of size 0)
3123 * default = SiS 300: depends on videosize
3124 * SiS 315/330/340/XGI: 32k below max
3127 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3128 if(ivideo
->video_size
> 0x1000000) {
3130 } else if(ivideo
->video_size
> 0x800000) {
3135 } else if(ivideo
->UMAsize
&& ivideo
->LFBsize
) {
3138 def
= maxoffs
- 0x8000;
3141 /* Use default for secondary card for now (FIXME) */
3142 if((!ret
) || (ret
> maxoffs
) || (ivideo
->cardnumber
!= 0))
3148 static u32 __devinit
3149 sisfb_getheapsize(struct sis_video_info
*ivideo
)
3151 u32 max
= ivideo
->video_size
- ivideo
->hwcursor_size
- ivideo
->cmdQueueSize
;
3154 if(ivideo
->UMAsize
&& ivideo
->LFBsize
) {
3155 if( (!ivideo
->sisfb_parm_mem
) ||
3156 ((ivideo
->sisfb_parm_mem
* 1024) > max
) ||
3157 ((max
- (ivideo
->sisfb_parm_mem
* 1024)) < ivideo
->UMAsize
) ) {
3158 ret
= ivideo
->UMAsize
;
3159 max
-= ivideo
->UMAsize
;
3161 ret
= max
- (ivideo
->sisfb_parm_mem
* 1024);
3162 max
= ivideo
->sisfb_parm_mem
* 1024;
3164 ivideo
->video_offset
= ret
;
3165 ivideo
->sisfb_mem
= max
;
3167 ret
= max
- ivideo
->heapstart
;
3168 ivideo
->sisfb_mem
= ivideo
->heapstart
;
3174 static int __devinit
3175 sisfb_heap_init(struct sis_video_info
*ivideo
)
3179 ivideo
->video_offset
= 0;
3180 if(ivideo
->sisfb_parm_mem
) {
3181 if( (ivideo
->sisfb_parm_mem
< (2 * 1024 * 1024)) ||
3182 (ivideo
->sisfb_parm_mem
> ivideo
->video_size
) ) {
3183 ivideo
->sisfb_parm_mem
= 0;
3187 ivideo
->heapstart
= sisfb_getheapstart(ivideo
);
3188 ivideo
->sisfb_heap_size
= sisfb_getheapsize(ivideo
);
3190 ivideo
->sisfb_heap_start
= ivideo
->video_vbase
+ ivideo
->heapstart
;
3191 ivideo
->sisfb_heap_end
= ivideo
->sisfb_heap_start
+ ivideo
->sisfb_heap_size
;
3193 printk(KERN_INFO
"sisfb: Memory heap starting at %dK, size %dK\n",
3194 (int)(ivideo
->heapstart
/ 1024), (int)(ivideo
->sisfb_heap_size
/ 1024));
3196 ivideo
->sisfb_heap
.vinfo
= ivideo
;
3198 ivideo
->sisfb_heap
.poha_chain
= NULL
;
3199 ivideo
->sisfb_heap
.poh_freelist
= NULL
;
3201 poh
= sisfb_poh_new_node(&ivideo
->sisfb_heap
);
3205 poh
->poh_next
= &ivideo
->sisfb_heap
.oh_free
;
3206 poh
->poh_prev
= &ivideo
->sisfb_heap
.oh_free
;
3207 poh
->size
= ivideo
->sisfb_heap_size
;
3208 poh
->offset
= ivideo
->heapstart
;
3210 ivideo
->sisfb_heap
.oh_free
.poh_next
= poh
;
3211 ivideo
->sisfb_heap
.oh_free
.poh_prev
= poh
;
3212 ivideo
->sisfb_heap
.oh_free
.size
= 0;
3213 ivideo
->sisfb_heap
.max_freesize
= poh
->size
;
3215 ivideo
->sisfb_heap
.oh_used
.poh_next
= &ivideo
->sisfb_heap
.oh_used
;
3216 ivideo
->sisfb_heap
.oh_used
.poh_prev
= &ivideo
->sisfb_heap
.oh_used
;
3217 ivideo
->sisfb_heap
.oh_used
.size
= SENTINEL
;
3219 if(ivideo
->cardnumber
== 0) {
3220 /* For the first card, make this heap the "global" one
3221 * for old DRM (which could handle only one card)
3223 sisfb_heap
= &ivideo
->sisfb_heap
;
3229 static struct SIS_OH
*
3230 sisfb_poh_new_node(struct SIS_HEAP
*memheap
)
3232 struct SIS_OHALLOC
*poha
;
3237 if(memheap
->poh_freelist
== NULL
) {
3238 poha
= kmalloc(SIS_OH_ALLOC_SIZE
, GFP_KERNEL
);
3242 poha
->poha_next
= memheap
->poha_chain
;
3243 memheap
->poha_chain
= poha
;
3245 cOhs
= (SIS_OH_ALLOC_SIZE
- sizeof(struct SIS_OHALLOC
)) / sizeof(struct SIS_OH
) + 1;
3247 poh
= &poha
->aoh
[0];
3248 for(i
= cOhs
- 1; i
!= 0; i
--) {
3249 poh
->poh_next
= poh
+ 1;
3253 poh
->poh_next
= NULL
;
3254 memheap
->poh_freelist
= &poha
->aoh
[0];
3257 poh
= memheap
->poh_freelist
;
3258 memheap
->poh_freelist
= poh
->poh_next
;
3263 static struct SIS_OH
*
3264 sisfb_poh_allocate(struct SIS_HEAP
*memheap
, u32 size
)
3266 struct SIS_OH
*pohThis
;
3267 struct SIS_OH
*pohRoot
;
3270 if(size
> memheap
->max_freesize
) {
3271 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3272 (unsigned int) size
/ 1024);
3276 pohThis
= memheap
->oh_free
.poh_next
;
3278 while(pohThis
!= &memheap
->oh_free
) {
3279 if(size
<= pohThis
->size
) {
3283 pohThis
= pohThis
->poh_next
;
3287 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3288 (unsigned int) size
/ 1024);
3292 if(size
== pohThis
->size
) {
3294 sisfb_delete_node(pohThis
);
3296 pohRoot
= sisfb_poh_new_node(memheap
);
3300 pohRoot
->offset
= pohThis
->offset
;
3301 pohRoot
->size
= size
;
3303 pohThis
->offset
+= size
;
3304 pohThis
->size
-= size
;
3307 memheap
->max_freesize
-= size
;
3309 pohThis
= &memheap
->oh_used
;
3310 sisfb_insert_node(pohThis
, pohRoot
);
3316 sisfb_delete_node(struct SIS_OH
*poh
)
3318 poh
->poh_prev
->poh_next
= poh
->poh_next
;
3319 poh
->poh_next
->poh_prev
= poh
->poh_prev
;
3323 sisfb_insert_node(struct SIS_OH
*pohList
, struct SIS_OH
*poh
)
3325 struct SIS_OH
*pohTemp
= pohList
->poh_next
;
3327 pohList
->poh_next
= poh
;
3328 pohTemp
->poh_prev
= poh
;
3330 poh
->poh_prev
= pohList
;
3331 poh
->poh_next
= pohTemp
;
3334 static struct SIS_OH
*
3335 sisfb_poh_free(struct SIS_HEAP
*memheap
, u32 base
)
3337 struct SIS_OH
*pohThis
;
3338 struct SIS_OH
*poh_freed
;
3339 struct SIS_OH
*poh_prev
;
3340 struct SIS_OH
*poh_next
;
3345 poh_freed
= memheap
->oh_used
.poh_next
;
3347 while(poh_freed
!= &memheap
->oh_used
) {
3348 if(poh_freed
->offset
== base
) {
3353 poh_freed
= poh_freed
->poh_next
;
3359 memheap
->max_freesize
+= poh_freed
->size
;
3361 poh_prev
= poh_next
= NULL
;
3362 ulUpper
= poh_freed
->offset
+ poh_freed
->size
;
3363 ulLower
= poh_freed
->offset
;
3365 pohThis
= memheap
->oh_free
.poh_next
;
3367 while(pohThis
!= &memheap
->oh_free
) {
3368 if(pohThis
->offset
== ulUpper
) {
3370 } else if((pohThis
->offset
+ pohThis
->size
) == ulLower
) {
3373 pohThis
= pohThis
->poh_next
;
3376 sisfb_delete_node(poh_freed
);
3378 if(poh_prev
&& poh_next
) {
3379 poh_prev
->size
+= (poh_freed
->size
+ poh_next
->size
);
3380 sisfb_delete_node(poh_next
);
3381 sisfb_free_node(memheap
, poh_freed
);
3382 sisfb_free_node(memheap
, poh_next
);
3387 poh_prev
->size
+= poh_freed
->size
;
3388 sisfb_free_node(memheap
, poh_freed
);
3393 poh_next
->size
+= poh_freed
->size
;
3394 poh_next
->offset
= poh_freed
->offset
;
3395 sisfb_free_node(memheap
, poh_freed
);
3399 sisfb_insert_node(&memheap
->oh_free
, poh_freed
);
3405 sisfb_free_node(struct SIS_HEAP
*memheap
, struct SIS_OH
*poh
)
3410 poh
->poh_next
= memheap
->poh_freelist
;
3411 memheap
->poh_freelist
= poh
;
3415 sis_int_malloc(struct sis_video_info
*ivideo
, struct sis_memreq
*req
)
3417 struct SIS_OH
*poh
= NULL
;
3419 if((ivideo
) && (ivideo
->sisfb_id
== SISFB_ID
) && (!ivideo
->havenoheap
))
3420 poh
= sisfb_poh_allocate(&ivideo
->sisfb_heap
, (u32
)req
->size
);
3423 req
->offset
= req
->size
= 0;
3424 DPRINTK("sisfb: Video RAM allocation failed\n");
3426 req
->offset
= poh
->offset
;
3427 req
->size
= poh
->size
;
3428 DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3429 (poh
->offset
+ ivideo
->video_vbase
));
3434 sis_malloc(struct sis_memreq
*req
)
3436 struct sis_video_info
*ivideo
= sisfb_heap
->vinfo
;
3438 if(&ivideo
->sisfb_heap
== sisfb_heap
)
3439 sis_int_malloc(ivideo
, req
);
3441 req
->offset
= req
->size
= 0;
3445 sis_malloc_new(struct pci_dev
*pdev
, struct sis_memreq
*req
)
3447 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
3449 sis_int_malloc(ivideo
, req
);
3452 /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3455 sis_int_free(struct sis_video_info
*ivideo
, u32 base
)
3459 if((!ivideo
) || (ivideo
->sisfb_id
!= SISFB_ID
) || (ivideo
->havenoheap
))
3462 poh
= sisfb_poh_free(&ivideo
->sisfb_heap
, base
);
3465 DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
3466 (unsigned int) base
);
3473 struct sis_video_info
*ivideo
= sisfb_heap
->vinfo
;
3475 sis_int_free(ivideo
, base
);
3479 sis_free_new(struct pci_dev
*pdev
, u32 base
)
3481 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
3483 sis_int_free(ivideo
, base
);
3486 /* --------------------- SetMode routines ------------------------- */
3489 sisfb_check_engine_and_sync(struct sis_video_info
*ivideo
)
3493 /* Check if MMIO and engines are enabled,
3494 * and sync in case they are. Can't use
3495 * ivideo->accel here, as this might have
3496 * been changed before this is called.
3498 inSISIDXREG(SISSR
, IND_SIS_PCI_ADDRESS_SET
, cr30
);
3499 inSISIDXREG(SISSR
, IND_SIS_MODULE_ENABLE
, cr31
);
3500 /* MMIO and 2D/3D engine enabled? */
3501 if((cr30
& SIS_MEM_MAP_IO_ENABLE
) && (cr31
& 0x42)) {
3502 #ifdef CONFIG_FB_SIS_300
3503 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3504 /* Don't care about TurboQueue. It's
3505 * enough to know that the engines
3508 sisfb_syncaccel(ivideo
);
3511 #ifdef CONFIG_FB_SIS_315
3512 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3513 /* Check that any queue mode is
3514 * enabled, and that the queue
3515 * is not in the state of "reset"
3517 inSISIDXREG(SISSR
, 0x26, cr30
);
3518 if((cr30
& 0xe0) && (!(cr30
& 0x01))) {
3519 sisfb_syncaccel(ivideo
);
3527 sisfb_pre_setmode(struct sis_video_info
*ivideo
)
3529 u8 cr30
= 0, cr31
= 0, cr33
= 0, cr35
= 0, cr38
= 0;
3532 ivideo
->currentvbflags
&= (VB_VIDEOBRIDGE
| VB_DISPTYPE_DISP2
);
3534 outSISIDXREG(SISSR
, 0x05, 0x86);
3536 inSISIDXREG(SISCR
, 0x31, cr31
);
3540 cr33
= ivideo
->rate_idx
& 0x0F;
3542 #ifdef CONFIG_FB_SIS_315
3543 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3544 if(ivideo
->chip
>= SIS_661
) {
3545 inSISIDXREG(SISCR
, 0x38, cr38
);
3546 cr38
&= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
3549 inSISIDXREG(SISCR
, tvregnum
, cr38
);
3550 cr38
&= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
3554 #ifdef CONFIG_FB_SIS_300
3555 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3557 inSISIDXREG(SISCR
, tvregnum
, cr38
);
3561 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
3562 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
3563 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
3565 switch(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
3568 cr38
&= ~0xc0; /* Clear PAL-M / PAL-N bits */
3569 if((ivideo
->vbflags
& TV_YPBPR
) && (ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) {
3570 #ifdef CONFIG_FB_SIS_315
3571 if(ivideo
->chip
>= SIS_661
) {
3573 if(ivideo
->vbflags
& TV_YPBPR525P
) cr35
|= 0x20;
3574 else if(ivideo
->vbflags
& TV_YPBPR750P
) cr35
|= 0x40;
3575 else if(ivideo
->vbflags
& TV_YPBPR1080I
) cr35
|= 0x60;
3576 cr30
|= SIS_SIMULTANEOUS_VIEW_ENABLE
;
3578 ivideo
->currentvbflags
|= (TV_YPBPR
| (ivideo
->vbflags
& TV_YPBPRALL
));
3579 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3580 cr30
|= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE
);
3582 if(ivideo
->vbflags
& TV_YPBPR525P
) cr38
|= 0x10;
3583 else if(ivideo
->vbflags
& TV_YPBPR750P
) cr38
|= 0x20;
3584 else if(ivideo
->vbflags
& TV_YPBPR1080I
) cr38
|= 0x30;
3586 ivideo
->currentvbflags
|= (TV_YPBPR
| (ivideo
->vbflags
& TV_YPBPRALL
));
3589 } else if((ivideo
->vbflags
& TV_HIVISION
) &&
3590 (ivideo
->vbflags2
& VB2_SISHIVISIONBRIDGE
)) {
3591 if(ivideo
->chip
>= SIS_661
) {
3597 cr30
|= SIS_SIMULTANEOUS_VIEW_ENABLE
;
3600 ivideo
->currentvbflags
|= TV_HIVISION
;
3601 } else if(ivideo
->vbflags
& TV_SCART
) {
3602 cr30
= (SIS_VB_OUTPUT_SCART
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3605 ivideo
->currentvbflags
|= TV_SCART
;
3607 if(ivideo
->vbflags
& TV_SVIDEO
) {
3608 cr30
= (SIS_VB_OUTPUT_SVIDEO
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3609 ivideo
->currentvbflags
|= TV_SVIDEO
;
3611 if(ivideo
->vbflags
& TV_AVIDEO
) {
3612 cr30
= (SIS_VB_OUTPUT_COMPOSITE
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3613 ivideo
->currentvbflags
|= TV_AVIDEO
;
3616 cr31
|= SIS_DRIVER_MODE
;
3618 if(ivideo
->vbflags
& (TV_AVIDEO
| TV_SVIDEO
)) {
3619 if(ivideo
->vbflags
& TV_PAL
) {
3620 cr31
|= 0x01; cr35
|= 0x01;
3621 ivideo
->currentvbflags
|= TV_PAL
;
3622 if(ivideo
->vbflags
& TV_PALM
) {
3623 cr38
|= 0x40; cr35
|= 0x04;
3624 ivideo
->currentvbflags
|= TV_PALM
;
3625 } else if(ivideo
->vbflags
& TV_PALN
) {
3626 cr38
|= 0x80; cr35
|= 0x08;
3627 ivideo
->currentvbflags
|= TV_PALN
;
3630 cr31
&= ~0x01; cr35
&= ~0x01;
3631 ivideo
->currentvbflags
|= TV_NTSC
;
3632 if(ivideo
->vbflags
& TV_NTSCJ
) {
3633 cr38
|= 0x40; cr35
|= 0x02;
3634 ivideo
->currentvbflags
|= TV_NTSCJ
;
3641 cr30
= (SIS_VB_OUTPUT_LCD
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3642 cr31
|= SIS_DRIVER_MODE
;
3643 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, ivideo
->sisfb_dstn
);
3644 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, ivideo
->sisfb_fstn
);
3645 ivideo
->curFSTN
= ivideo
->sisfb_fstn
;
3646 ivideo
->curDSTN
= ivideo
->sisfb_dstn
;
3650 cr30
= (SIS_VB_OUTPUT_CRT2
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3651 cr31
|= SIS_DRIVER_MODE
;
3652 if(ivideo
->sisfb_nocrt2rate
) {
3653 cr33
|= (sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
<< 4);
3655 cr33
|= ((ivideo
->rate_idx
& 0x0F) << 4);
3659 default: /* disable CRT2 */
3661 cr31
|= (SIS_DRIVER_MODE
| SIS_VB_OUTPUT_DISABLE
);
3664 outSISIDXREG(SISCR
, 0x30, cr30
);
3665 outSISIDXREG(SISCR
, 0x33, cr33
);
3667 if(ivideo
->chip
>= SIS_661
) {
3668 #ifdef CONFIG_FB_SIS_315
3669 cr31
&= ~0x01; /* Clear PAL flag (now in CR35) */
3670 setSISIDXREG(SISCR
, 0x35, ~0x10, cr35
); /* Leave overscan bit alone */
3671 cr38
&= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
3672 setSISIDXREG(SISCR
, 0x38, 0xf8, cr38
);
3674 } else if(ivideo
->chip
!= SIS_300
) {
3675 outSISIDXREG(SISCR
, tvregnum
, cr38
);
3677 outSISIDXREG(SISCR
, 0x31, cr31
);
3679 ivideo
->SiS_Pr
.SiS_UseOEM
= ivideo
->sisfb_useoem
;
3681 sisfb_check_engine_and_sync(ivideo
);
3684 /* Fix SR11 for 661 and later */
3685 #ifdef CONFIG_FB_SIS_315
3687 sisfb_fixup_SR11(struct sis_video_info
*ivideo
)
3691 if(ivideo
->chip
>= SIS_661
) {
3692 inSISIDXREG(SISSR
,0x11,tmpreg
);
3694 inSISIDXREG(SISSR
,0x3e,tmpreg
);
3695 tmpreg
= (tmpreg
+ 1) & 0xff;
3696 outSISIDXREG(SISSR
,0x3e,tmpreg
);
3697 inSISIDXREG(SISSR
,0x11,tmpreg
);
3700 andSISIDXREG(SISSR
,0x11,0x0f);
3707 sisfb_set_TVxposoffset(struct sis_video_info
*ivideo
, int val
)
3709 if(val
> 32) val
= 32;
3710 if(val
< -32) val
= -32;
3711 ivideo
->tvxpos
= val
;
3713 if(ivideo
->sisfblocked
) return;
3714 if(!ivideo
->modechanged
) return;
3716 if(ivideo
->currentvbflags
& CRT2_TV
) {
3718 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3720 int x
= ivideo
->tvx
;
3722 switch(ivideo
->chronteltype
) {
3726 outSISIDXREG(SISSR
,0x05,0x86);
3727 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0a, (x
& 0xff));
3728 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x08, ((x
& 0x0100) >> 7), 0xFD);
3731 /* Not supported by hardware */
3735 } else if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3737 u8 p2_1f
,p2_20
,p2_2b
,p2_42
,p2_43
;
3738 unsigned short temp
;
3740 p2_1f
= ivideo
->p2_1f
;
3741 p2_20
= ivideo
->p2_20
;
3742 p2_2b
= ivideo
->p2_2b
;
3743 p2_42
= ivideo
->p2_42
;
3744 p2_43
= ivideo
->p2_43
;
3746 temp
= p2_1f
| ((p2_20
& 0xf0) << 4);
3748 p2_1f
= temp
& 0xff;
3749 p2_20
= (temp
& 0xf00) >> 4;
3750 p2_2b
= ((p2_2b
& 0x0f) + (val
* 2)) & 0x0f;
3751 temp
= p2_43
| ((p2_42
& 0xf0) << 4);
3753 p2_43
= temp
& 0xff;
3754 p2_42
= (temp
& 0xf00) >> 4;
3755 outSISIDXREG(SISPART2
,0x1f,p2_1f
);
3756 setSISIDXREG(SISPART2
,0x20,0x0F,p2_20
);
3757 setSISIDXREG(SISPART2
,0x2b,0xF0,p2_2b
);
3758 setSISIDXREG(SISPART2
,0x42,0x0F,p2_42
);
3759 outSISIDXREG(SISPART2
,0x43,p2_43
);
3765 sisfb_set_TVyposoffset(struct sis_video_info
*ivideo
, int val
)
3767 if(val
> 32) val
= 32;
3768 if(val
< -32) val
= -32;
3769 ivideo
->tvypos
= val
;
3771 if(ivideo
->sisfblocked
) return;
3772 if(!ivideo
->modechanged
) return;
3774 if(ivideo
->currentvbflags
& CRT2_TV
) {
3776 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3778 int y
= ivideo
->tvy
;
3780 switch(ivideo
->chronteltype
) {
3784 outSISIDXREG(SISSR
,0x05,0x86);
3785 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0b, (y
& 0xff));
3786 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x08, ((y
& 0x0100) >> 8), 0xFE);
3789 /* Not supported by hardware */
3793 } else if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3797 p2_01
= ivideo
->p2_01
;
3798 p2_02
= ivideo
->p2_02
;
3802 if(!(ivideo
->currentvbflags
& (TV_HIVISION
| TV_YPBPR
))) {
3803 while((p2_01
<= 0) || (p2_02
<= 0)) {
3808 outSISIDXREG(SISPART2
,0x01,p2_01
);
3809 outSISIDXREG(SISPART2
,0x02,p2_02
);
3815 sisfb_post_setmode(struct sis_video_info
*ivideo
)
3817 bool crt1isoff
= false;
3819 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
3822 #ifdef CONFIG_FB_SIS_315
3826 outSISIDXREG(SISSR
, 0x05, 0x86);
3828 #ifdef CONFIG_FB_SIS_315
3829 sisfb_fixup_SR11(ivideo
);
3832 /* Now we actually HAVE changed the display mode */
3833 ivideo
->modechanged
= 1;
3835 /* We can't switch off CRT1 if bridge is in slave mode */
3836 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
3837 if(sisfb_bridgeisslave(ivideo
)) doit
= false;
3839 ivideo
->sisfb_crt1off
= 0;
3841 #ifdef CONFIG_FB_SIS_300
3842 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3843 if((ivideo
->sisfb_crt1off
) && (doit
)) {
3850 setSISIDXREG(SISCR
, 0x17, 0x7f, reg
);
3853 #ifdef CONFIG_FB_SIS_315
3854 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3855 if((ivideo
->sisfb_crt1off
) && (doit
)) {
3864 setSISIDXREG(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, ~0x40, reg
);
3865 setSISIDXREG(SISSR
, 0x1f, ~0xc0, reg1
);
3870 ivideo
->currentvbflags
&= ~VB_DISPTYPE_CRT1
;
3871 ivideo
->currentvbflags
|= VB_SINGLE_MODE
;
3873 ivideo
->currentvbflags
|= VB_DISPTYPE_CRT1
;
3874 if(ivideo
->currentvbflags
& VB_DISPTYPE_CRT2
) {
3875 ivideo
->currentvbflags
|= VB_MIRROR_MODE
;
3877 ivideo
->currentvbflags
|= VB_SINGLE_MODE
;
3881 andSISIDXREG(SISSR
, IND_SIS_RAMDAC_CONTROL
, ~0x04);
3883 if(ivideo
->currentvbflags
& CRT2_TV
) {
3884 if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3885 inSISIDXREG(SISPART2
,0x1f,ivideo
->p2_1f
);
3886 inSISIDXREG(SISPART2
,0x20,ivideo
->p2_20
);
3887 inSISIDXREG(SISPART2
,0x2b,ivideo
->p2_2b
);
3888 inSISIDXREG(SISPART2
,0x42,ivideo
->p2_42
);
3889 inSISIDXREG(SISPART2
,0x43,ivideo
->p2_43
);
3890 inSISIDXREG(SISPART2
,0x01,ivideo
->p2_01
);
3891 inSISIDXREG(SISPART2
,0x02,ivideo
->p2_02
);
3892 } else if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3893 if(ivideo
->chronteltype
== 1) {
3894 ivideo
->tvx
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0a);
3895 ivideo
->tvx
|= (((SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x08) & 0x02) >> 1) << 8);
3896 ivideo
->tvy
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0b);
3897 ivideo
->tvy
|= ((SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x08) & 0x01) << 8);
3902 if(ivideo
->tvxpos
) {
3903 sisfb_set_TVxposoffset(ivideo
, ivideo
->tvxpos
);
3905 if(ivideo
->tvypos
) {
3906 sisfb_set_TVyposoffset(ivideo
, ivideo
->tvypos
);
3909 /* Eventually sync engines */
3910 sisfb_check_engine_and_sync(ivideo
);
3912 /* (Re-)Initialize chip engines */
3914 sisfb_engine_init(ivideo
);
3916 ivideo
->engineok
= 0;
3921 sisfb_reset_mode(struct sis_video_info
*ivideo
)
3923 if(sisfb_set_mode(ivideo
, 0))
3926 sisfb_set_pitch(ivideo
);
3927 sisfb_set_base_CRT1(ivideo
, ivideo
->current_base
);
3928 sisfb_set_base_CRT2(ivideo
, ivideo
->current_base
);
3934 sisfb_handle_command(struct sis_video_info
*ivideo
, struct sisfb_cmd
*sisfb_command
)
3938 switch(sisfb_command
->sisfb_cmd
) {
3939 case SISFB_CMD_GETVBFLAGS
:
3940 if(!ivideo
->modechanged
) {
3941 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_EARLY
;
3943 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3944 sisfb_command
->sisfb_result
[1] = ivideo
->currentvbflags
;
3945 sisfb_command
->sisfb_result
[2] = ivideo
->vbflags2
;
3948 case SISFB_CMD_SWITCHCRT1
:
3949 /* arg[0]: 0 = off, 1 = on, 99 = query */
3950 if(!ivideo
->modechanged
) {
3951 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_EARLY
;
3952 } else if(sisfb_command
->sisfb_arg
[0] == 99) {
3954 sisfb_command
->sisfb_result
[1] = ivideo
->sisfb_crt1off
? 0 : 1;
3955 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3956 } else if(ivideo
->sisfblocked
) {
3957 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_LOCKED
;
3958 } else if((!(ivideo
->currentvbflags
& CRT2_ENABLE
)) &&
3959 (sisfb_command
->sisfb_arg
[0] == 0)) {
3960 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_NOCRT2
;
3962 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3963 mycrt1off
= sisfb_command
->sisfb_arg
[0] ? 0 : 1;
3964 if( ((ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
) && mycrt1off
) ||
3965 ((!(ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
)) && !mycrt1off
) ) {
3966 ivideo
->sisfb_crt1off
= mycrt1off
;
3967 if(sisfb_reset_mode(ivideo
)) {
3968 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OTHER
;
3971 sisfb_command
->sisfb_result
[1] = ivideo
->sisfb_crt1off
? 0 : 1;
3976 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_UNKNOWN
;
3977 printk(KERN_ERR
"sisfb: Unknown command 0x%x\n",
3978 sisfb_command
->sisfb_cmd
);
3983 SISINITSTATIC
int __init
3984 sisfb_setup(char *options
)
3988 sisfb_setdefaultparms();
3990 if(!options
|| !(*options
))
3993 while((this_opt
= strsep(&options
, ",")) != NULL
) {
3995 if(!(*this_opt
)) continue;
3997 if(!strnicmp(this_opt
, "off", 3)) {
3999 } else if(!strnicmp(this_opt
, "forcecrt2type:", 14)) {
4000 /* Need to check crt2 type first for fstn/dstn */
4001 sisfb_search_crt2type(this_opt
+ 14);
4002 } else if(!strnicmp(this_opt
, "tvmode:",7)) {
4003 sisfb_search_tvstd(this_opt
+ 7);
4004 } else if(!strnicmp(this_opt
, "tvstandard:",11)) {
4005 sisfb_search_tvstd(this_opt
+ 11);
4006 } else if(!strnicmp(this_opt
, "mode:", 5)) {
4007 sisfb_search_mode(this_opt
+ 5, false);
4008 } else if(!strnicmp(this_opt
, "vesa:", 5)) {
4009 sisfb_search_vesamode(simple_strtoul(this_opt
+ 5, NULL
, 0), false);
4010 } else if(!strnicmp(this_opt
, "rate:", 5)) {
4011 sisfb_parm_rate
= simple_strtoul(this_opt
+ 5, NULL
, 0);
4012 } else if(!strnicmp(this_opt
, "forcecrt1:", 10)) {
4013 sisfb_forcecrt1
= (int)simple_strtoul(this_opt
+ 10, NULL
, 0);
4014 } else if(!strnicmp(this_opt
, "mem:",4)) {
4015 sisfb_parm_mem
= simple_strtoul(this_opt
+ 4, NULL
, 0);
4016 } else if(!strnicmp(this_opt
, "pdc:", 4)) {
4017 sisfb_pdc
= simple_strtoul(this_opt
+ 4, NULL
, 0);
4018 } else if(!strnicmp(this_opt
, "pdc1:", 5)) {
4019 sisfb_pdca
= simple_strtoul(this_opt
+ 5, NULL
, 0);
4020 } else if(!strnicmp(this_opt
, "noaccel", 7)) {
4022 } else if(!strnicmp(this_opt
, "accel", 5)) {
4024 } else if(!strnicmp(this_opt
, "noypan", 6)) {
4026 } else if(!strnicmp(this_opt
, "ypan", 4)) {
4028 } else if(!strnicmp(this_opt
, "nomax", 5)) {
4030 } else if(!strnicmp(this_opt
, "max", 3)) {
4032 } else if(!strnicmp(this_opt
, "userom:", 7)) {
4033 sisfb_userom
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
4034 } else if(!strnicmp(this_opt
, "useoem:", 7)) {
4035 sisfb_useoem
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
4036 } else if(!strnicmp(this_opt
, "nocrt2rate", 10)) {
4037 sisfb_nocrt2rate
= 1;
4038 } else if(!strnicmp(this_opt
, "scalelcd:", 9)) {
4039 unsigned long temp
= 2;
4040 temp
= simple_strtoul(this_opt
+ 9, NULL
, 0);
4041 if((temp
== 0) || (temp
== 1)) {
4042 sisfb_scalelcd
= temp
^ 1;
4044 } else if(!strnicmp(this_opt
, "tvxposoffset:", 13)) {
4046 temp
= (int)simple_strtol(this_opt
+ 13, NULL
, 0);
4047 if((temp
>= -32) && (temp
<= 32)) {
4048 sisfb_tvxposoffset
= temp
;
4050 } else if(!strnicmp(this_opt
, "tvyposoffset:", 13)) {
4052 temp
= (int)simple_strtol(this_opt
+ 13, NULL
, 0);
4053 if((temp
>= -32) && (temp
<= 32)) {
4054 sisfb_tvyposoffset
= temp
;
4056 } else if(!strnicmp(this_opt
, "specialtiming:", 14)) {
4057 sisfb_search_specialtiming(this_opt
+ 14);
4058 } else if(!strnicmp(this_opt
, "lvdshl:", 7)) {
4060 temp
= simple_strtoul(this_opt
+ 7, NULL
, 0);
4061 if((temp
>= 0) && (temp
<= 3)) {
4062 sisfb_lvdshl
= temp
;
4064 } else if(this_opt
[0] >= '0' && this_opt
[0] <= '9') {
4065 sisfb_search_mode(this_opt
, true);
4066 #if !defined(__i386__) && !defined(__x86_64__)
4067 } else if(!strnicmp(this_opt
, "resetcard", 9)) {
4068 sisfb_resetcard
= 1;
4069 } else if(!strnicmp(this_opt
, "videoram:", 9)) {
4070 sisfb_videoram
= simple_strtoul(this_opt
+ 9, NULL
, 0);
4073 printk(KERN_INFO
"sisfb: Invalid option %s\n", this_opt
);
4082 static int __devinit
4083 sisfb_check_rom(SIS_IOTYPE1
*rom_base
, struct sis_video_info
*ivideo
)
4088 if((readb(rom_base
) != 0x55) || (readb(rom_base
+ 1) != 0xaa))
4091 romptr
= (readb(rom_base
+ 0x18) | (readb(rom_base
+ 0x19) << 8));
4092 if(romptr
> (0x10000 - 8))
4095 rom
= rom_base
+ romptr
;
4097 if((readb(rom
) != 'P') || (readb(rom
+ 1) != 'C') ||
4098 (readb(rom
+ 2) != 'I') || (readb(rom
+ 3) != 'R'))
4101 if((readb(rom
+ 4) | (readb(rom
+ 5) << 8)) != ivideo
->chip_vendor
)
4104 if((readb(rom
+ 6) | (readb(rom
+ 7) << 8)) != ivideo
->chip_id
)
4110 static unsigned char * __devinit
4111 sisfb_find_rom(struct pci_dev
*pdev
)
4113 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4114 SIS_IOTYPE1
*rom_base
;
4115 unsigned char *myrombase
= NULL
;
4117 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
4120 /* First, try the official pci ROM functions (except
4121 * on integrated chipsets which have no ROM).
4124 if(!ivideo
->nbridge
) {
4126 if((rom_base
= pci_map_rom(pdev
, &romsize
))) {
4128 if(sisfb_check_rom(rom_base
, ivideo
)) {
4130 if((myrombase
= vmalloc(65536))) {
4132 /* Work around bug in pci/rom.c: Folks forgot to check
4133 * whether the size retrieved from the BIOS image eventually
4134 * is larger than the mapped size
4136 if(pci_resource_len(pdev
, PCI_ROM_RESOURCE
) < romsize
)
4137 romsize
= pci_resource_len(pdev
, PCI_ROM_RESOURCE
);
4139 memcpy_fromio(myrombase
, rom_base
,
4140 (romsize
> 65536) ? 65536 : romsize
);
4143 pci_unmap_rom(pdev
, rom_base
);
4147 if(myrombase
) return myrombase
;
4150 /* Otherwise do it the conventional way. */
4152 #if defined(__i386__) || defined(__x86_64__)
4154 for(temp
= 0x000c0000; temp
< 0x000f0000; temp
+= 0x00001000) {
4156 rom_base
= ioremap(temp
, 65536);
4160 if(!sisfb_check_rom(rom_base
, ivideo
)) {
4165 if((myrombase
= vmalloc(65536)))
4166 memcpy_fromio(myrombase
, rom_base
, 65536);
4175 pci_read_config_dword(pdev
, PCI_ROM_ADDRESS
, &temp
);
4176 pci_write_config_dword(pdev
, PCI_ROM_ADDRESS
,
4177 (ivideo
->video_base
& PCI_ROM_ADDRESS_MASK
) | PCI_ROM_ADDRESS_ENABLE
);
4179 rom_base
= ioremap(ivideo
->video_base
, 65536);
4181 if(sisfb_check_rom(rom_base
, ivideo
)) {
4182 if((myrombase
= vmalloc(65536)))
4183 memcpy_fromio(myrombase
, rom_base
, 65536);
4188 pci_write_config_dword(pdev
, PCI_ROM_ADDRESS
, temp
);
4195 static void __devinit
4196 sisfb_post_map_vram(struct sis_video_info
*ivideo
, unsigned int *mapsize
,
4199 ivideo
->video_vbase
= ioremap(ivideo
->video_base
, (*mapsize
));
4201 if(!ivideo
->video_vbase
) {
4203 "sisfb: Unable to map maximum video RAM for size detection\n");
4205 while((!(ivideo
->video_vbase
= ioremap(ivideo
->video_base
, (*mapsize
))))) {
4207 if((*mapsize
) < (min
<< 20))
4210 if(ivideo
->video_vbase
) {
4212 "sisfb: Video RAM size detection limited to %dMB\n",
4213 (int)((*mapsize
) >> 20));
4218 #ifdef CONFIG_FB_SIS_300
4219 static int __devinit
4220 sisfb_post_300_buswidth(struct sis_video_info
*ivideo
)
4222 SIS_IOTYPE1
*FBAddress
= ivideo
->video_vbase
;
4223 unsigned short temp
;
4227 andSISIDXREG(SISSR
, 0x15, 0xFB);
4228 orSISIDXREG(SISSR
, 0x15, 0x04);
4229 outSISIDXREG(SISSR
, 0x13, 0x00);
4230 outSISIDXREG(SISSR
, 0x14, 0xBF);
4232 for(i
= 0; i
< 2; i
++) {
4234 for(j
= 0; j
< 4; j
++) {
4235 writew(temp
, FBAddress
);
4236 if(readw(FBAddress
) == temp
)
4238 orSISIDXREG(SISSR
, 0x3c, 0x01);
4239 inSISIDXREG(SISSR
, 0x05, reg
);
4240 inSISIDXREG(SISSR
, 0x05, reg
);
4241 andSISIDXREG(SISSR
, 0x3c, 0xfe);
4242 inSISIDXREG(SISSR
, 0x05, reg
);
4243 inSISIDXREG(SISSR
, 0x05, reg
);
4248 writel(0x01234567L
, FBAddress
);
4249 writel(0x456789ABL
, (FBAddress
+ 4));
4250 writel(0x89ABCDEFL
, (FBAddress
+ 8));
4251 writel(0xCDEF0123L
, (FBAddress
+ 12));
4253 inSISIDXREG(SISSR
, 0x3b, reg
);
4255 if(readl((FBAddress
+ 12)) == 0xCDEF0123L
)
4256 return 4; /* Channel A 128bit */
4259 if(readl((FBAddress
+ 4)) == 0x456789ABL
)
4260 return 2; /* Channel B 64bit */
4262 return 1; /* 32bit */
4265 static int __devinit
4266 sisfb_post_300_rwtest(struct sis_video_info
*ivideo
, int iteration
, int buswidth
,
4267 int PseudoRankCapacity
, int PseudoAdrPinCount
,
4268 unsigned int mapsize
)
4270 SIS_IOTYPE1
*FBAddr
= ivideo
->video_vbase
;
4271 unsigned short sr14
;
4272 unsigned int k
, RankCapacity
, PageCapacity
, BankNumHigh
, BankNumMid
;
4273 unsigned int PhysicalAdrOtherPage
, PhysicalAdrHigh
, PhysicalAdrHalfPage
;
4274 static const unsigned short SiS_DRAMType
[17][5] = {
4275 {0x0C,0x0A,0x02,0x40,0x39},
4276 {0x0D,0x0A,0x01,0x40,0x48},
4277 {0x0C,0x09,0x02,0x20,0x35},
4278 {0x0D,0x09,0x01,0x20,0x44},
4279 {0x0C,0x08,0x02,0x10,0x31},
4280 {0x0D,0x08,0x01,0x10,0x40},
4281 {0x0C,0x0A,0x01,0x20,0x34},
4282 {0x0C,0x09,0x01,0x08,0x32},
4283 {0x0B,0x08,0x02,0x08,0x21},
4284 {0x0C,0x08,0x01,0x08,0x30},
4285 {0x0A,0x08,0x02,0x04,0x11},
4286 {0x0B,0x0A,0x01,0x10,0x28},
4287 {0x09,0x08,0x02,0x02,0x01},
4288 {0x0B,0x09,0x01,0x08,0x24},
4289 {0x0B,0x08,0x01,0x04,0x20},
4290 {0x0A,0x08,0x01,0x02,0x10},
4291 {0x09,0x08,0x01,0x01,0x00}
4294 for(k
= 0; k
<= 16; k
++) {
4296 RankCapacity
= buswidth
* SiS_DRAMType
[k
][3];
4298 if(RankCapacity
!= PseudoRankCapacity
)
4301 if((SiS_DRAMType
[k
][2] + SiS_DRAMType
[k
][0]) > PseudoAdrPinCount
)
4304 BankNumHigh
= RankCapacity
* 16 * iteration
- 1;
4305 if(iteration
== 3) { /* Rank No */
4306 BankNumMid
= RankCapacity
* 16 - 1;
4308 BankNumMid
= RankCapacity
* 16 * iteration
/ 2 - 1;
4311 PageCapacity
= (1 << SiS_DRAMType
[k
][1]) * buswidth
* 4;
4312 PhysicalAdrHigh
= BankNumHigh
;
4313 PhysicalAdrHalfPage
= (PageCapacity
/ 2 + PhysicalAdrHigh
) % PageCapacity
;
4314 PhysicalAdrOtherPage
= PageCapacity
* SiS_DRAMType
[k
][2] + PhysicalAdrHigh
;
4316 andSISIDXREG(SISSR
, 0x15, 0xFB); /* Test */
4317 orSISIDXREG(SISSR
, 0x15, 0x04); /* Test */
4318 sr14
= (SiS_DRAMType
[k
][3] * buswidth
) - 1;
4319 if(buswidth
== 4) sr14
|= 0x80;
4320 else if(buswidth
== 2) sr14
|= 0x40;
4321 outSISIDXREG(SISSR
, 0x13, SiS_DRAMType
[k
][4]);
4322 outSISIDXREG(SISSR
, 0x14, sr14
);
4327 if((BankNumHigh
+ PhysicalAdrHigh
>= mapsize
) ||
4328 (BankNumMid
+ PhysicalAdrHigh
>= mapsize
) ||
4329 (BankNumHigh
+ PhysicalAdrHalfPage
>= mapsize
) ||
4330 (BankNumHigh
+ PhysicalAdrOtherPage
>= mapsize
))
4334 writew(((unsigned short)PhysicalAdrHigh
),
4335 (FBAddr
+ BankNumHigh
+ PhysicalAdrHigh
));
4336 writew(((unsigned short)BankNumMid
),
4337 (FBAddr
+ BankNumMid
+ PhysicalAdrHigh
));
4338 writew(((unsigned short)PhysicalAdrHalfPage
),
4339 (FBAddr
+ BankNumHigh
+ PhysicalAdrHalfPage
));
4340 writew(((unsigned short)PhysicalAdrOtherPage
),
4341 (FBAddr
+ BankNumHigh
+ PhysicalAdrOtherPage
));
4344 if(readw(FBAddr
+ BankNumHigh
+ PhysicalAdrHigh
) == PhysicalAdrHigh
)
4351 static void __devinit
4352 sisfb_post_300_ramsize(struct pci_dev
*pdev
, unsigned int mapsize
)
4354 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4356 int PseudoRankCapacity
, PseudoAdrPinCount
;
4358 buswidth
= sisfb_post_300_buswidth(ivideo
);
4360 for(i
= 6; i
>= 0; i
--) {
4361 PseudoRankCapacity
= 1 << i
;
4362 for(j
= 4; j
>= 1; j
--) {
4363 PseudoAdrPinCount
= 15 - j
;
4364 if((PseudoRankCapacity
* j
) <= 64) {
4365 if(sisfb_post_300_rwtest(ivideo
,
4377 static void __devinit
4378 sisfb_post_sis300(struct pci_dev
*pdev
)
4380 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4381 unsigned char *bios
= ivideo
->SiS_Pr
.VirtualRomBase
;
4382 u8 reg
, v1
, v2
, v3
, v4
, v5
, v6
, v7
, v8
;
4383 u16 index
, rindex
, memtype
= 0;
4384 unsigned int mapsize
;
4386 if(!ivideo
->SiS_Pr
.UseROM
)
4389 outSISIDXREG(SISSR
, 0x05, 0x86);
4392 if(bios
[0x52] & 0x80) {
4393 memtype
= bios
[0x52];
4395 inSISIDXREG(SISSR
, 0x3a, memtype
);
4400 v3
= 0x80; v6
= 0x80;
4401 if(ivideo
->revision_id
<= 0x13) {
4402 v1
= 0x44; v2
= 0x42;
4403 v4
= 0x44; v5
= 0x42;
4405 v1
= 0x68; v2
= 0x43; /* Assume 125Mhz MCLK */
4406 v4
= 0x68; v5
= 0x43; /* Assume 125Mhz ECLK */
4408 index
= memtype
* 5;
4409 rindex
= index
+ 0x54;
4410 v1
= bios
[rindex
++];
4411 v2
= bios
[rindex
++];
4412 v3
= bios
[rindex
++];
4413 rindex
= index
+ 0x7c;
4414 v4
= bios
[rindex
++];
4415 v5
= bios
[rindex
++];
4416 v6
= bios
[rindex
++];
4419 outSISIDXREG(SISSR
, 0x28, v1
);
4420 outSISIDXREG(SISSR
, 0x29, v2
);
4421 outSISIDXREG(SISSR
, 0x2a, v3
);
4422 outSISIDXREG(SISSR
, 0x2e, v4
);
4423 outSISIDXREG(SISSR
, 0x2f, v5
);
4424 outSISIDXREG(SISSR
, 0x30, v6
);
4429 outSISIDXREG(SISSR
, 0x07, v1
); /* DAC speed */
4431 outSISIDXREG(SISSR
, 0x11, 0x0f); /* DDC, power save */
4433 v1
= 0x01; v2
= 0x43; v3
= 0x1e; v4
= 0x2a;
4434 v5
= 0x06; v6
= 0x00; v7
= 0x00; v8
= 0x00;
4438 v2
= bios
[memtype
+ 8];
4439 v3
= bios
[memtype
+ 16];
4440 v4
= bios
[memtype
+ 24];
4441 v5
= bios
[memtype
+ 32];
4442 v6
= bios
[memtype
+ 40];
4443 v7
= bios
[memtype
+ 48];
4444 v8
= bios
[memtype
+ 56];
4446 if(ivideo
->revision_id
>= 0x80)
4448 outSISIDXREG(SISSR
, 0x15, v1
); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4449 outSISIDXREG(SISSR
, 0x16, v2
);
4450 outSISIDXREG(SISSR
, 0x17, v3
);
4451 outSISIDXREG(SISSR
, 0x18, v4
);
4452 outSISIDXREG(SISSR
, 0x19, v5
);
4453 outSISIDXREG(SISSR
, 0x1a, v6
);
4454 outSISIDXREG(SISSR
, 0x1b, v7
);
4455 outSISIDXREG(SISSR
, 0x1c, v8
); /* ---- */
4456 andSISIDXREG(SISSR
, 0x15 ,0xfb);
4457 orSISIDXREG(SISSR
, 0x15, 0x04);
4459 if(bios
[0x53] & 0x02) {
4460 orSISIDXREG(SISSR
, 0x19, 0x20);
4463 v1
= 0x04; /* DAC pedestal (BIOS 0xe5) */
4464 if(ivideo
->revision_id
>= 0x80)
4466 outSISIDXREG(SISSR
, 0x1f, v1
);
4467 outSISIDXREG(SISSR
, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
4468 v1
= 0xf6; v2
= 0x0d; v3
= 0x00;
4474 outSISIDXREG(SISSR
, 0x23, v1
);
4475 outSISIDXREG(SISSR
, 0x24, v2
);
4476 outSISIDXREG(SISSR
, 0x25, v3
);
4477 outSISIDXREG(SISSR
, 0x21, 0x84);
4478 outSISIDXREG(SISSR
, 0x22, 0x00);
4479 outSISIDXREG(SISCR
, 0x37, 0x00);
4480 orSISIDXREG(SISPART1
, 0x24, 0x01); /* unlock crt2 */
4481 outSISIDXREG(SISPART1
, 0x00, 0x00);
4482 v1
= 0x40; v2
= 0x11;
4487 outSISIDXREG(SISPART1
, 0x02, v1
);
4489 if(ivideo
->revision_id
>= 0x80)
4492 inSISIDXREG(SISPART4
, 0x00, reg
);
4493 if((reg
== 1) || (reg
== 2)) {
4494 outSISIDXREG(SISCR
, 0x37, 0x02);
4495 outSISIDXREG(SISPART2
, 0x00, 0x1c);
4496 v4
= 0x00; v5
= 0x00; v6
= 0x10;
4497 if(ivideo
->SiS_Pr
.UseROM
) {
4502 outSISIDXREG(SISPART4
, 0x0d, v4
);
4503 outSISIDXREG(SISPART4
, 0x0e, v5
);
4504 outSISIDXREG(SISPART4
, 0x10, v6
);
4505 outSISIDXREG(SISPART4
, 0x0f, 0x3f);
4506 inSISIDXREG(SISPART4
, 0x01, reg
);
4508 inSISIDXREG(SISPART4
, 0x23, reg
);
4511 outSISIDXREG(SISPART4
, 0x23, reg
);
4516 outSISIDXREG(SISSR
, 0x32, v2
);
4518 andSISIDXREG(SISPART1
, 0x24, 0xfe); /* Lock CRT2 */
4520 inSISIDXREG(SISSR
, 0x16, reg
);
4522 outSISIDXREG(SISCR
, 0x35, reg
);
4523 outSISIDXREG(SISCR
, 0x83, 0x00);
4524 #if !defined(__i386__) && !defined(__x86_64__)
4525 if(sisfb_videoram
) {
4526 outSISIDXREG(SISSR
, 0x13, 0x28); /* ? */
4527 reg
= ((sisfb_videoram
>> 10) - 1) | 0x40;
4528 outSISIDXREG(SISSR
, 0x14, reg
);
4531 /* Need to map max FB size for finding out about RAM size */
4533 sisfb_post_map_vram(ivideo
, &mapsize
, 4);
4535 if(ivideo
->video_vbase
) {
4536 sisfb_post_300_ramsize(pdev
, mapsize
);
4537 iounmap(ivideo
->video_vbase
);
4540 "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4541 outSISIDXREG(SISSR
, 0x13, 0x28); /* ? */
4542 outSISIDXREG(SISSR
, 0x14, 0x47); /* 8MB, 64bit default */
4544 #if !defined(__i386__) && !defined(__x86_64__)
4551 inSISIDXREG(SISSR
, 0x3a, reg
);
4552 if((reg
& 0x30) == 0x30) {
4553 v1
= 0x04; /* PCI */
4556 v1
= 0x14; /* AGP */
4560 outSISIDXREG(SISSR
, 0x21, v1
);
4561 outSISIDXREG(SISSR
, 0x22, v2
);
4564 sisfb_sense_crt1(ivideo
);
4566 /* Set default mode, don't clear screen */
4567 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
4568 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
4569 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
4570 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
4571 ivideo
->SiS_Pr
.VideoMemorySize
= 8 << 20;
4572 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
4574 outSISIDXREG(SISSR
, 0x05, 0x86);
4577 orSISIDXREG(SISSR
, 0x01, 0x20);
4579 /* Save mode number in CR34 */
4580 outSISIDXREG(SISCR
, 0x34, 0x2e);
4582 /* Let everyone know what the current mode is */
4583 ivideo
->modeprechange
= 0x2e;
4587 #ifdef CONFIG_FB_SIS_315
4589 static void __devinit
4590 sisfb_post_sis315330(struct pci_dev
*pdev
)
4596 static void __devinit
4597 sisfb_post_xgi_delay(struct sis_video_info
*ivideo
, int delay
)
4602 for(i
= 0; i
<= (delay
* 10 * 36); i
++) {
4603 inSISIDXREG(SISSR
, 0x05, reg
);
4608 static int __devinit
4609 sisfb_find_host_bridge(struct sis_video_info
*ivideo
, struct pci_dev
*mypdev
,
4610 unsigned short pcivendor
)
4612 struct pci_dev
*pdev
= NULL
;
4613 unsigned short temp
;
4616 while((pdev
= SIS_PCI_GET_CLASS(PCI_CLASS_BRIDGE_HOST
, pdev
))) {
4617 temp
= pdev
->vendor
;
4618 SIS_PCI_PUT_DEVICE(pdev
);
4619 if(temp
== pcivendor
) {
4628 static int __devinit
4629 sisfb_post_xgi_rwtest(struct sis_video_info
*ivideo
, int starta
,
4630 unsigned int enda
, unsigned int mapsize
)
4635 writel(0, ivideo
->video_vbase
);
4637 for(i
= starta
; i
<= enda
; i
++) {
4640 writel(pos
, ivideo
->video_vbase
+ pos
);
4643 sisfb_post_xgi_delay(ivideo
, 150);
4645 if(readl(ivideo
->video_vbase
) != 0)
4648 for(i
= starta
; i
<= enda
; i
++) {
4651 if(readl(ivideo
->video_vbase
+ pos
) != pos
)
4660 static void __devinit
4661 sisfb_post_xgi_ramsize(struct sis_video_info
*ivideo
)
4663 unsigned int buswidth
, ranksize
, channelab
, mapsize
;
4666 static const u8 dramsr13
[12 * 5] = {
4667 0x02, 0x0e, 0x0b, 0x80, 0x5d,
4668 0x02, 0x0e, 0x0a, 0x40, 0x59,
4669 0x02, 0x0d, 0x0b, 0x40, 0x4d,
4670 0x02, 0x0e, 0x09, 0x20, 0x55,
4671 0x02, 0x0d, 0x0a, 0x20, 0x49,
4672 0x02, 0x0c, 0x0b, 0x20, 0x3d,
4673 0x02, 0x0e, 0x08, 0x10, 0x51,
4674 0x02, 0x0d, 0x09, 0x10, 0x45,
4675 0x02, 0x0c, 0x0a, 0x10, 0x39,
4676 0x02, 0x0d, 0x08, 0x08, 0x41,
4677 0x02, 0x0c, 0x09, 0x08, 0x35,
4678 0x02, 0x0c, 0x08, 0x04, 0x31
4680 static const u8 dramsr13_4
[4 * 5] = {
4681 0x02, 0x0d, 0x09, 0x40, 0x45,
4682 0x02, 0x0c, 0x09, 0x20, 0x35,
4683 0x02, 0x0c, 0x08, 0x10, 0x31,
4684 0x02, 0x0b, 0x08, 0x08, 0x21
4687 /* Enable linear mode, disable 0xa0000 address decoding */
4688 /* We disable a0000 address decoding, because
4689 * - if running on x86, if the card is disabled, it means
4690 * that another card is in the system. We don't want
4691 * to interphere with that primary card's textmode.
4692 * - if running on non-x86, there usually is no VGA window
4695 orSISIDXREG(SISSR
, 0x20, (0x80 | 0x04));
4697 /* Need to map max FB size for finding out about RAM size */
4698 mapsize
= 256 << 20;
4699 sisfb_post_map_vram(ivideo
, &mapsize
, 32);
4701 if(!ivideo
->video_vbase
) {
4702 printk(KERN_ERR
"sisfb: Unable to detect RAM size. Setting default.\n");
4703 outSISIDXREG(SISSR
, 0x13, 0x35);
4704 outSISIDXREG(SISSR
, 0x14, 0x41);
4709 /* Non-interleaving */
4710 outSISIDXREG(SISSR
, 0x15, 0x00);
4712 outSISIDXREG(SISSR
, 0x1c, 0x00);
4714 if(ivideo
->chip
== XGI_20
) {
4717 inSISIDXREG(SISCR
, 0x97, reg
);
4718 if(!(reg
& 0x01)) { /* Single 32/16 */
4720 outSISIDXREG(SISSR
, 0x13, 0xb1);
4721 outSISIDXREG(SISSR
, 0x14, 0x52);
4722 sisfb_post_xgi_delay(ivideo
, 1);
4724 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4727 outSISIDXREG(SISSR
, 0x13, 0x31);
4728 outSISIDXREG(SISSR
, 0x14, 0x42);
4729 sisfb_post_xgi_delay(ivideo
, 1);
4730 if(sisfb_post_xgi_rwtest(ivideo
, 23, 23, mapsize
))
4734 outSISIDXREG(SISSR
, 0x13, 0xb1);
4735 outSISIDXREG(SISSR
, 0x14, 0x41);
4736 sisfb_post_xgi_delay(ivideo
, 1);
4738 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4741 outSISIDXREG(SISSR
, 0x13, 0x31);
4742 } else { /* Dual 16/8 */
4744 outSISIDXREG(SISSR
, 0x13, 0xb1);
4745 outSISIDXREG(SISSR
, 0x14, 0x41);
4746 sisfb_post_xgi_delay(ivideo
, 1);
4748 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4751 outSISIDXREG(SISSR
, 0x13, 0x31);
4752 outSISIDXREG(SISSR
, 0x14, 0x31);
4753 sisfb_post_xgi_delay(ivideo
, 1);
4754 if(sisfb_post_xgi_rwtest(ivideo
, 22, 22, mapsize
))
4758 outSISIDXREG(SISSR
, 0x13, 0xb1);
4759 outSISIDXREG(SISSR
, 0x14, 0x30);
4760 sisfb_post_xgi_delay(ivideo
, 1);
4762 if(sisfb_post_xgi_rwtest(ivideo
, 21, 22, mapsize
))
4765 outSISIDXREG(SISSR
, 0x13, 0x31);
4768 } else { /* XGI_40 */
4770 inSISIDXREG(SISCR
, 0x97, reg
);
4772 inSISIDXREG(SISSR
, 0x39, reg
);
4776 if(reg
& 0x01) { /* DDRII */
4778 if(ivideo
->revision_id
== 2) {
4780 outSISIDXREG(SISSR
, 0x13, 0xa1);
4781 outSISIDXREG(SISSR
, 0x14, 0x44);
4783 sisfb_post_xgi_delay(ivideo
, 1);
4784 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4787 outSISIDXREG(SISSR
, 0x13, 0x21);
4788 outSISIDXREG(SISSR
, 0x14, 0x34);
4789 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4793 outSISIDXREG(SISSR
, 0x13, 0xa1);
4794 outSISIDXREG(SISSR
, 0x14, 0x40);
4796 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4799 outSISIDXREG(SISSR
, 0x13, 0x21);
4800 outSISIDXREG(SISSR
, 0x14, 0x30);
4803 outSISIDXREG(SISSR
, 0x13, 0xa1);
4804 outSISIDXREG(SISSR
, 0x14, 0x4c);
4806 sisfb_post_xgi_delay(ivideo
, 1);
4807 if(sisfb_post_xgi_rwtest(ivideo
, 23, 25, mapsize
))
4811 outSISIDXREG(SISSR
, 0x14, 0x48);
4812 sisfb_post_xgi_delay(ivideo
, 1);
4814 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4817 outSISIDXREG(SISSR
, 0x13, 0x21);
4818 outSISIDXREG(SISSR
, 0x14, 0x3c);
4821 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
)) {
4825 outSISIDXREG(SISSR
, 0x14, 0x38);
4829 sisfb_post_xgi_delay(ivideo
, 1);
4834 if(ivideo
->revision_id
== 2) {
4836 outSISIDXREG(SISSR
, 0x13, 0xa1);
4837 outSISIDXREG(SISSR
, 0x14, 0x52);
4838 sisfb_post_xgi_delay(ivideo
, 1);
4840 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4843 outSISIDXREG(SISSR
, 0x13, 0x21);
4844 outSISIDXREG(SISSR
, 0x14, 0x42);
4847 outSISIDXREG(SISSR
, 0x13, 0xa1);
4848 outSISIDXREG(SISSR
, 0x14, 0x5a);
4849 sisfb_post_xgi_delay(ivideo
, 1);
4851 if(sisfb_post_xgi_rwtest(ivideo
, 24, 25, mapsize
))
4854 outSISIDXREG(SISSR
, 0x13, 0x21);
4855 outSISIDXREG(SISSR
, 0x14, 0x4a);
4857 sisfb_post_xgi_delay(ivideo
, 1);
4863 setSISIDXREG(SISSR
, 0x14, 0xf0, sr14
);
4864 sisfb_post_xgi_delay(ivideo
, 1);
4866 j
= (ivideo
->chip
== XGI_20
) ? 5 : 9;
4867 k
= (ivideo
->chip
== XGI_20
) ? 12 : 4;
4869 for(i
= 0; i
< k
; i
++) {
4871 reg
= (ivideo
->chip
== XGI_20
) ?
4872 dramsr13
[(i
* 5) + 4] : dramsr13_4
[(i
* 5) + 4];
4873 setSISIDXREG(SISSR
, 0x13, 0x80, reg
);
4874 sisfb_post_xgi_delay(ivideo
, 50);
4876 ranksize
= (ivideo
->chip
== XGI_20
) ?
4877 dramsr13
[(i
* 5) + 3] : dramsr13_4
[(i
* 5) + 3];
4879 inSISIDXREG(SISSR
, 0x13, reg
);
4880 if(reg
& 0x80) ranksize
<<= 1;
4882 if(ivideo
->chip
== XGI_20
) {
4883 if(buswidth
== 16) ranksize
<<= 1;
4884 else if(buswidth
== 32) ranksize
<<= 2;
4886 if(buswidth
== 64) ranksize
<<= 1;
4892 if((ranksize
* l
) <= 256) {
4893 while((ranksize
>>= 1)) reg
+= 0x10;
4898 setSISIDXREG(SISSR
, 0x14, 0x0f, (reg
& 0xf0));
4899 sisfb_post_xgi_delay(ivideo
, 1);
4901 if(sisfb_post_xgi_rwtest(ivideo
, j
, ((reg
>> 4) + channelab
- 2 + 20), mapsize
))
4905 iounmap(ivideo
->video_vbase
);
4908 static void __devinit
4909 sisfb_post_xgi_setclocks(struct sis_video_info
*ivideo
, u8 regb
)
4913 static const u8 cs90
[8 * 3] = {
4923 static const u8 csb8
[8 * 3] = {
4937 v1
= cs90
[index
]; v2
= cs90
[index
+ 1]; v3
= cs90
[index
+ 2];
4938 if(ivideo
->haveXGIROM
) {
4939 v1
= ivideo
->bios_abase
[0x90 + index
];
4940 v2
= ivideo
->bios_abase
[0x90 + index
+ 1];
4941 v3
= ivideo
->bios_abase
[0x90 + index
+ 2];
4943 outSISIDXREG(SISSR
, 0x28, v1
);
4944 outSISIDXREG(SISSR
, 0x29, v2
);
4945 outSISIDXREG(SISSR
, 0x2a, v3
);
4946 sisfb_post_xgi_delay(ivideo
, 0x43);
4947 sisfb_post_xgi_delay(ivideo
, 0x43);
4948 sisfb_post_xgi_delay(ivideo
, 0x43);
4950 v1
= csb8
[index
]; v2
= csb8
[index
+ 1]; v3
= csb8
[index
+ 2];
4951 if(ivideo
->haveXGIROM
) {
4952 v1
= ivideo
->bios_abase
[0xb8 + index
];
4953 v2
= ivideo
->bios_abase
[0xb8 + index
+ 1];
4954 v3
= ivideo
->bios_abase
[0xb8 + index
+ 2];
4956 outSISIDXREG(SISSR
, 0x2e, v1
);
4957 outSISIDXREG(SISSR
, 0x2f, v2
);
4958 outSISIDXREG(SISSR
, 0x30, v3
);
4959 sisfb_post_xgi_delay(ivideo
, 0x43);
4960 sisfb_post_xgi_delay(ivideo
, 0x43);
4961 sisfb_post_xgi_delay(ivideo
, 0x43);
4964 static int __devinit
4965 sisfb_post_xgi(struct pci_dev
*pdev
)
4967 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4968 unsigned char *bios
= ivideo
->bios_abase
;
4969 struct pci_dev
*mypdev
= NULL
;
4970 const u8
*ptr
, *ptr2
;
4971 u8 v1
, v2
, v3
, v4
, v5
, reg
, ramtype
;
4972 u32 rega
, regb
, regd
;
4974 static const u8 cs78
[3] = { 0xf6, 0x0d, 0x00 };
4975 static const u8 cs76
[2] = { 0xa3, 0xfb };
4976 static const u8 cs7b
[3] = { 0xc0, 0x11, 0x00 };
4977 static const u8 cs158
[8] = {
4978 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
4980 static const u8 cs160
[8] = {
4981 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
4983 static const u8 cs168
[8] = {
4984 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
4986 static const u8 cs128
[3 * 8] = {
4987 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
4988 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
4989 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
4991 static const u8 cs148
[2 * 8] = {
4992 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
4993 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4995 static const u8 cs31a
[8 * 4] = {
4996 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
4997 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
4998 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4999 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5001 static const u8 cs33a
[8 * 4] = {
5002 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5003 0x00, 0x00, 0x00, 0x00, 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 cs45a
[8 * 2] = {
5008 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
5009 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5011 static const u8 cs170
[7 * 8] = {
5012 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5013 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5014 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
5015 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5016 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5017 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5018 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5020 static const u8 cs1a8
[3 * 8] = {
5021 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5022 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5023 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5025 static const u8 cs100
[2 * 8] = {
5026 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5027 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5031 reg
= inSISREG(SISVGAENABLE
) | 0x01;
5032 outSISREG(SISVGAENABLE
, reg
);
5035 reg
= inSISREG(SISMISCR
) | 0x01;
5036 outSISREG(SISMISCW
, reg
);
5039 outSISIDXREG(SISSR
, 0x05, 0x86);
5040 inSISIDXREG(SISSR
, 0x05, reg
);
5044 /* Clear some regs */
5045 for(i
= 0; i
< 0x22; i
++) {
5046 if(0x06 + i
== 0x20) continue;
5047 outSISIDXREG(SISSR
, 0x06 + i
, 0x00);
5049 for(i
= 0; i
< 0x0b; i
++) {
5050 outSISIDXREG(SISSR
, 0x31 + i
, 0x00);
5052 for(i
= 0; i
< 0x10; i
++) {
5053 outSISIDXREG(SISCR
, 0x30 + i
, 0x00);
5057 if(ivideo
->haveXGIROM
) {
5058 ptr
= (const u8
*)&bios
[0x78];
5060 for(i
= 0; i
< 3; i
++) {
5061 outSISIDXREG(SISSR
, 0x23 + i
, ptr
[i
]);
5065 if(ivideo
->haveXGIROM
) {
5066 ptr
= (const u8
*)&bios
[0x76];
5068 for(i
= 0; i
< 2; i
++) {
5069 outSISIDXREG(SISSR
, 0x21 + i
, ptr
[i
]);
5072 v1
= 0x18; v2
= 0x00;
5073 if(ivideo
->haveXGIROM
) {
5077 outSISIDXREG(SISSR
, 0x07, v1
);
5078 outSISIDXREG(SISSR
, 0x11, 0x0f);
5079 outSISIDXREG(SISSR
, 0x1f, v2
);
5080 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5081 outSISIDXREG(SISSR
, 0x20, 0x80 | 0x20 | 0x04);
5082 outSISIDXREG(SISSR
, 0x27, 0x74);
5085 if(ivideo
->haveXGIROM
) {
5086 ptr
= (const u8
*)&bios
[0x7b];
5088 for(i
= 0; i
< 3; i
++) {
5089 outSISIDXREG(SISSR
, 0x31 + i
, ptr
[i
]);
5092 if(ivideo
->chip
== XGI_40
) {
5093 if(ivideo
->revision_id
== 2) {
5094 setSISIDXREG(SISSR
, 0x3b, 0x3f, 0xc0);
5096 outSISIDXREG(SISCR
, 0x7d, 0xfe);
5097 outSISIDXREG(SISCR
, 0x7e, 0x0f);
5099 if(ivideo
->revision_id
== 0) { /* 40 *and* 20? */
5100 andSISIDXREG(SISCR
, 0x58, 0xd7);
5101 inSISIDXREG(SISCR
, 0xcb, reg
);
5103 setSISIDXREG(SISCR
, 0x58, 0xd7, (reg
& 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5107 reg
= (ivideo
->chip
== XGI_40
) ? 0x20 : 0x00;
5108 setSISIDXREG(SISCR
, 0x38, 0x1f, reg
);
5110 if(ivideo
->chip
== XGI_20
) {
5111 outSISIDXREG(SISSR
, 0x36, 0x70);
5113 outSISIDXREG(SISVID
, 0x00, 0x86);
5114 outSISIDXREG(SISVID
, 0x32, 0x00);
5115 outSISIDXREG(SISVID
, 0x30, 0x00);
5116 outSISIDXREG(SISVID
, 0x32, 0x01);
5117 outSISIDXREG(SISVID
, 0x30, 0x00);
5118 andSISIDXREG(SISVID
, 0x2f, 0xdf);
5119 andSISIDXREG(SISCAP
, 0x00, 0x3f);
5121 outSISIDXREG(SISPART1
, 0x2f, 0x01);
5122 outSISIDXREG(SISPART1
, 0x00, 0x00);
5123 outSISIDXREG(SISPART1
, 0x02, bios
[0x7e]);
5124 outSISIDXREG(SISPART1
, 0x2e, 0x08);
5125 andSISIDXREG(SISPART1
, 0x35, 0x7f);
5126 andSISIDXREG(SISPART1
, 0x50, 0xfe);
5128 inSISIDXREG(SISPART4
, 0x00, reg
);
5129 if(reg
== 1 || reg
== 2) {
5130 outSISIDXREG(SISPART2
, 0x00, 0x1c);
5131 outSISIDXREG(SISPART4
, 0x0d, bios
[0x7f]);
5132 outSISIDXREG(SISPART4
, 0x0e, bios
[0x80]);
5133 outSISIDXREG(SISPART4
, 0x10, bios
[0x81]);
5134 andSISIDXREG(SISPART4
, 0x0f, 0x3f);
5136 inSISIDXREG(SISPART4
, 0x01, reg
);
5137 if((reg
& 0xf0) >= 0xb0) {
5138 inSISIDXREG(SISPART4
, 0x23, reg
);
5139 if(reg
& 0x20) reg
|= 0x40;
5140 outSISIDXREG(SISPART4
, 0x23, reg
);
5141 reg
= (reg
& 0x20) ? 0x02 : 0x00;
5142 setSISIDXREG(SISPART1
, 0x1e, 0xfd, reg
);
5148 inSISIDXREG(SISSR
, 0x3b, reg
);
5150 inSISIDXREG(SISSR
, 0x3a, reg
);
5151 v2
= (reg
& 0x30) >> 3;
5152 if(!(v2
& 0x04)) v2
^= 0x02;
5153 inSISIDXREG(SISSR
, 0x39, reg
);
5154 if(reg
& 0x80) v2
|= 0x80;
5157 if((mypdev
= SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI
, 0x0730, NULL
))) {
5158 SIS_PCI_PUT_DEVICE(mypdev
);
5159 if(((v2
& 0x06) == 2) || ((v2
& 0x06) == 4))
5164 mypdev
= SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI
, 0x0735, NULL
);
5166 mypdev
= SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI
, 0x0645, NULL
);
5168 mypdev
= SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI
, 0x0650, NULL
);
5170 pci_read_config_dword(mypdev
, 0x94, ®d
);
5172 pci_write_config_dword(mypdev
, 0x94, regd
);
5174 SIS_PCI_PUT_DEVICE(mypdev
);
5175 } else if(sisfb_find_host_bridge(ivideo
, pdev
, PCI_VENDOR_ID_SI
)) {
5177 } else if(sisfb_find_host_bridge(ivideo
, pdev
, 0x1106) ||
5178 sisfb_find_host_bridge(ivideo
, pdev
, 0x1022) ||
5179 sisfb_find_host_bridge(ivideo
, pdev
, 0x700e) ||
5180 sisfb_find_host_bridge(ivideo
, pdev
, 0x10de)) {
5181 if((v2
& 0x06) == 4)
5186 setSISIDXREG(SISCR
, 0x5f, 0xf0, v2
);
5188 outSISIDXREG(SISSR
, 0x22, v1
);
5190 if(ivideo
->revision_id
== 2) {
5191 inSISIDXREG(SISSR
, 0x3b, v1
);
5192 inSISIDXREG(SISSR
, 0x3a, v2
);
5193 regd
= bios
[0x90 + 3] | (bios
[0x90 + 4] << 8);
5194 if( (!(v1
& 0x02)) && (v2
& 0x30) && (regd
< 0xcf) )
5195 setSISIDXREG(SISCR
, 0x5f, 0xf1, 0x01);
5197 if((mypdev
= SIS_PCI_GET_DEVICE(0x10de, 0x01e0, NULL
))) {
5198 /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5202 setSISIDXREG(SISCR
, 0x5f, 0xf1, 0x01);
5203 SIS_PCI_PUT_DEVICE(mypdev
);
5208 inSISIDXREG(SISSR
, 0x3b, reg
);
5209 inSISIDXREG(SISCR
, 0x5f, v2
);
5210 if((!(reg
& 0x02)) && (v2
& 0x0e))
5212 outSISIDXREG(SISSR
, 0x27, v1
);
5214 if(bios
[0x64] & 0x01) {
5215 setSISIDXREG(SISCR
, 0x5f, 0xf0, bios
[0x64]);
5219 pci_read_config_dword(pdev
, 0x50, ®d
);
5220 regd
= (regd
>> 20) & 0x0f;
5223 orSISIDXREG(SISCR
, 0x5f, 0x08);
5225 outSISIDXREG(SISCR
, 0x48, v1
);
5227 setSISIDXREG(SISCR
, 0x47, 0x04, bios
[0x4f6] & 0xfb);
5228 setSISIDXREG(SISCR
, 0x49, 0xf0, bios
[0x4f8] & 0x0f);
5229 setSISIDXREG(SISCR
, 0x4a, 0x60, bios
[0x4f9] & 0x9f);
5230 setSISIDXREG(SISCR
, 0x4b, 0x08, bios
[0x4fa] & 0xf7);
5231 setSISIDXREG(SISCR
, 0x4c, 0x80, bios
[0x4fb] & 0x7f);
5232 outSISIDXREG(SISCR
, 0x70, bios
[0x4fc]);
5233 setSISIDXREG(SISCR
, 0x71, 0xf0, bios
[0x4fd] & 0x0f);
5234 outSISIDXREG(SISCR
, 0x74, 0xd0);
5235 setSISIDXREG(SISCR
, 0x74, 0xcf, bios
[0x4fe] & 0x30);
5236 setSISIDXREG(SISCR
, 0x75, 0xe0, bios
[0x4ff] & 0x1f);
5237 setSISIDXREG(SISCR
, 0x76, 0xe0, bios
[0x500] & 0x1f);
5239 if((mypdev
= SIS_PCI_GET_DEVICE(0x8086, 0x2530, NULL
))) {
5241 SIS_PCI_PUT_DEVICE(mypdev
);
5243 outSISIDXREG(SISCR
, 0x77, v1
);
5251 if(ivideo
->haveXGIROM
) {
5252 v1
= bios
[0x140 + regb
];
5254 outSISIDXREG(SISCR
, 0x6d, v1
);
5257 if(ivideo
->haveXGIROM
) {
5258 ptr
= (const u8
*)&bios
[0x128];
5260 for(i
= 0, j
= 0; i
< 3; i
++, j
+= 8) {
5261 outSISIDXREG(SISCR
, 0x68 + i
, ptr
[j
+ regb
]);
5266 if(ivideo
->haveXGIROM
) {
5267 index
= (ivideo
->chip
== XGI_20
) ? 0x31a : 0x3a6;
5268 ptr
= (const u8
*)&bios
[index
];
5269 ptr2
= (const u8
*)&bios
[index
+ 0x20];
5271 for(i
= 0; i
< 2; i
++) {
5273 regd
= le32_to_cpu(((u32
*)ptr
)[regb
]);
5276 regd
= le32_to_cpu(((u32
*)ptr2
)[regb
]);
5280 for(j
= 0; j
< 16; j
++) {
5282 if(regd
& 0x01) reg
|= 0x04;
5283 if(regd
& 0x02) reg
|= 0x08;
5285 outSISIDXREG(SISCR
, rega
, reg
);
5286 inSISIDXREG(SISCR
, rega
, reg
);
5287 inSISIDXREG(SISCR
, rega
, reg
);
5292 andSISIDXREG(SISCR
, 0x6e, 0xfc);
5295 if(ivideo
->haveXGIROM
) {
5296 index
= (ivideo
->chip
== XGI_20
) ? 0x35a : 0x3e6;
5297 ptr
= (const u8
*)&bios
[index
];
5299 for(i
= 0; i
< 4; i
++) {
5300 setSISIDXREG(SISCR
, 0x6e, 0xfc, i
);
5302 for(j
= 0; j
< 2; j
++) {
5305 regd
= le32_to_cpu(((u32
*)ptr
)[regb
* 8]);
5309 for(k
= 0; k
< 16; k
++) {
5311 if(regd
& 0x01) reg
|= 0x01;
5312 if(regd
& 0x02) reg
|= 0x02;
5314 outSISIDXREG(SISCR
, 0x6f, reg
);
5315 inSISIDXREG(SISCR
, 0x6f, reg
);
5316 inSISIDXREG(SISCR
, 0x6f, reg
);
5323 if(ivideo
->haveXGIROM
) {
5324 ptr
= (const u8
*)&bios
[0x148];
5326 for(i
= 0, j
= 0; i
< 2; i
++, j
+= 8) {
5327 outSISIDXREG(SISCR
, 0x80 + i
, ptr
[j
+ regb
]);
5330 andSISIDXREG(SISCR
, 0x89, 0x8f);
5333 if(ivideo
->haveXGIROM
) {
5334 index
= (ivideo
->chip
== XGI_20
) ? 0x45a : 0x4e6;
5335 ptr
= (const u8
*)&bios
[index
];
5337 regd
= le16_to_cpu(((const u16
*)ptr
)[regb
]);
5339 for(i
= 0; i
< 5; i
++) {
5341 if(regd
& 0x01) reg
|= 0x01;
5342 if(regd
& 0x02) reg
|= 0x02;
5344 outSISIDXREG(SISCR
, 0x89, reg
);
5345 inSISIDXREG(SISCR
, 0x89, reg
);
5346 inSISIDXREG(SISCR
, 0x89, reg
);
5350 v1
= 0xb5; v2
= 0x20; v3
= 0xf0; v4
= 0x13;
5351 if(ivideo
->haveXGIROM
) {
5352 v1
= bios
[0x118 + regb
];
5353 v2
= bios
[0xf8 + regb
];
5354 v3
= bios
[0x120 + regb
];
5357 outSISIDXREG(SISCR
, 0x45, v1
& 0x0f);
5358 outSISIDXREG(SISCR
, 0x99, (v1
>> 4) & 0x07);
5359 orSISIDXREG(SISCR
, 0x40, v1
& 0x80);
5360 outSISIDXREG(SISCR
, 0x41, v2
);
5363 if(ivideo
->haveXGIROM
) {
5364 ptr
= (const u8
*)&bios
[0x170];
5366 for(i
= 0, j
= 0; i
< 7; i
++, j
+= 8) {
5367 outSISIDXREG(SISCR
, 0x90 + i
, ptr
[j
+ regb
]);
5370 outSISIDXREG(SISCR
, 0x59, v3
);
5373 if(ivideo
->haveXGIROM
) {
5374 ptr
= (const u8
*)&bios
[0x1a8];
5376 for(i
= 0, j
= 0; i
< 3; i
++, j
+= 8) {
5377 outSISIDXREG(SISCR
, 0xc3 + i
, ptr
[j
+ regb
]);
5381 if(ivideo
->haveXGIROM
) {
5382 ptr
= (const u8
*)&bios
[0x100];
5384 for(i
= 0, j
= 0; i
< 2; i
++, j
+= 8) {
5385 outSISIDXREG(SISCR
, 0x8a + i
, ptr
[j
+ regb
]);
5388 outSISIDXREG(SISCR
, 0xcf, v4
);
5390 outSISIDXREG(SISCR
, 0x83, 0x09);
5391 outSISIDXREG(SISCR
, 0x87, 0x00);
5393 if(ivideo
->chip
== XGI_40
) {
5394 if( (ivideo
->revision_id
== 1) ||
5395 (ivideo
->revision_id
== 2) ) {
5396 outSISIDXREG(SISCR
, 0x8c, 0x87);
5400 outSISIDXREG(SISSR
, 0x17, 0x00);
5401 outSISIDXREG(SISSR
, 0x1a, 0x87);
5403 if(ivideo
->chip
== XGI_20
) {
5404 outSISIDXREG(SISSR
, 0x15, 0x00);
5405 outSISIDXREG(SISSR
, 0x1c, 0x00);
5408 ramtype
= 0x00; v1
= 0x10;
5409 if(ivideo
->haveXGIROM
) {
5410 ramtype
= bios
[0x62];
5413 if(!(ramtype
& 0x80)) {
5414 if(ivideo
->chip
== XGI_20
) {
5415 outSISIDXREG(SISCR
, 0x97, v1
);
5416 inSISIDXREG(SISCR
, 0x97, reg
);
5418 ramtype
= (reg
& 0x01) << 1;
5421 inSISIDXREG(SISSR
, 0x39, reg
);
5422 ramtype
= reg
& 0x02;
5424 inSISIDXREG(SISSR
, 0x3a, reg
);
5425 ramtype
= (reg
>> 1) & 0x01;
5435 sisfb_post_xgi_setclocks(ivideo
, regb
);
5436 if((ivideo
->chip
== XGI_20
) ||
5437 (ivideo
->revision_id
== 1) ||
5438 (ivideo
->revision_id
== 2)) {
5439 v1
= cs158
[regb
]; v2
= cs160
[regb
]; v3
= cs168
[regb
];
5440 if(ivideo
->haveXGIROM
) {
5441 v1
= bios
[regb
+ 0x158];
5442 v2
= bios
[regb
+ 0x160];
5443 v3
= bios
[regb
+ 0x168];
5445 outSISIDXREG(SISCR
, 0x82, v1
);
5446 outSISIDXREG(SISCR
, 0x85, v2
);
5447 outSISIDXREG(SISCR
, 0x86, v3
);
5449 outSISIDXREG(SISCR
, 0x82, 0x88);
5450 outSISIDXREG(SISCR
, 0x86, 0x00);
5451 inSISIDXREG(SISCR
, 0x86, reg
);
5452 outSISIDXREG(SISCR
, 0x86, 0x88);
5453 inSISIDXREG(SISCR
, 0x86, reg
);
5454 outSISIDXREG(SISCR
, 0x86, bios
[regb
+ 0x168]);
5455 outSISIDXREG(SISCR
, 0x82, 0x77);
5456 outSISIDXREG(SISCR
, 0x85, 0x00);
5457 inSISIDXREG(SISCR
, 0x85, reg
);
5458 outSISIDXREG(SISCR
, 0x85, 0x88);
5459 inSISIDXREG(SISCR
, 0x85, reg
);
5460 outSISIDXREG(SISCR
, 0x85, bios
[regb
+ 0x160]);
5461 outSISIDXREG(SISCR
, 0x82, bios
[regb
+ 0x158]);
5463 if(ivideo
->chip
== XGI_40
) {
5464 outSISIDXREG(SISCR
, 0x97, 0x00);
5466 outSISIDXREG(SISCR
, 0x98, 0x01);
5467 outSISIDXREG(SISCR
, 0x9a, 0x02);
5469 outSISIDXREG(SISSR
, 0x18, 0x01);
5470 if((ivideo
->chip
== XGI_20
) ||
5471 (ivideo
->revision_id
== 2)) {
5472 outSISIDXREG(SISSR
, 0x19, 0x40);
5474 outSISIDXREG(SISSR
, 0x19, 0x20);
5476 outSISIDXREG(SISSR
, 0x16, 0x00);
5477 outSISIDXREG(SISSR
, 0x16, 0x80);
5478 if((ivideo
->chip
== XGI_20
) || (bios
[0x1cb] != 0x0c)) {
5479 sisfb_post_xgi_delay(ivideo
, 0x43);
5480 sisfb_post_xgi_delay(ivideo
, 0x43);
5481 sisfb_post_xgi_delay(ivideo
, 0x43);
5482 outSISIDXREG(SISSR
, 0x18, 0x00);
5483 if((ivideo
->chip
== XGI_20
) ||
5484 (ivideo
->revision_id
== 2)) {
5485 outSISIDXREG(SISSR
, 0x19, 0x40);
5487 outSISIDXREG(SISSR
, 0x19, 0x20);
5489 } else if((ivideo
->chip
== XGI_40
) && (bios
[0x1cb] == 0x0c)) {
5490 /* outSISIDXREG(SISSR, 0x16, 0x0c); */ /* ? */
5492 outSISIDXREG(SISSR
, 0x16, 0x00);
5493 outSISIDXREG(SISSR
, 0x16, 0x80);
5494 sisfb_post_xgi_delay(ivideo
, 4);
5495 v1
= 0x31; v2
= 0x03; v3
= 0x83; v4
= 0x03; v5
= 0x83;
5496 if(ivideo
->haveXGIROM
) {
5498 index
= (ivideo
->chip
== XGI_20
) ? 0x4b2 : 0x53e;
5500 v3
= bios
[index
+ 1];
5501 v4
= bios
[index
+ 2];
5502 v5
= bios
[index
+ 3];
5504 outSISIDXREG(SISSR
, 0x18, v1
);
5505 outSISIDXREG(SISSR
, 0x19, ((ivideo
->chip
== XGI_20
) ? 0x02 : 0x01));
5506 outSISIDXREG(SISSR
, 0x16, v2
);
5507 outSISIDXREG(SISSR
, 0x16, v3
);
5508 sisfb_post_xgi_delay(ivideo
, 0x43);
5509 outSISIDXREG(SISSR
, 0x1b, 0x03);
5510 sisfb_post_xgi_delay(ivideo
, 0x22);
5511 outSISIDXREG(SISSR
, 0x18, v1
);
5512 outSISIDXREG(SISSR
, 0x19, 0x00);
5513 outSISIDXREG(SISSR
, 0x16, v4
);
5514 outSISIDXREG(SISSR
, 0x16, v5
);
5515 outSISIDXREG(SISSR
, 0x1b, 0x00);
5518 outSISIDXREG(SISCR
, 0x82, 0x77);
5519 outSISIDXREG(SISCR
, 0x86, 0x00);
5520 inSISIDXREG(SISCR
, 0x86, reg
);
5521 outSISIDXREG(SISCR
, 0x86, 0x88);
5522 inSISIDXREG(SISCR
, 0x86, reg
);
5523 v1
= cs168
[regb
]; v2
= cs160
[regb
]; v3
= cs158
[regb
];
5524 if(ivideo
->haveXGIROM
) {
5525 v1
= bios
[regb
+ 0x168];
5526 v2
= bios
[regb
+ 0x160];
5527 v3
= bios
[regb
+ 0x158];
5529 outSISIDXREG(SISCR
, 0x86, v1
);
5530 outSISIDXREG(SISCR
, 0x82, 0x77);
5531 outSISIDXREG(SISCR
, 0x85, 0x00);
5532 inSISIDXREG(SISCR
, 0x85, reg
);
5533 outSISIDXREG(SISCR
, 0x85, 0x88);
5534 inSISIDXREG(SISCR
, 0x85, reg
);
5535 outSISIDXREG(SISCR
, 0x85, v2
);
5536 outSISIDXREG(SISCR
, 0x82, v3
);
5537 outSISIDXREG(SISCR
, 0x98, 0x01);
5538 outSISIDXREG(SISCR
, 0x9a, 0x02);
5540 outSISIDXREG(SISSR
, 0x28, 0x64);
5541 outSISIDXREG(SISSR
, 0x29, 0x63);
5542 sisfb_post_xgi_delay(ivideo
, 15);
5543 outSISIDXREG(SISSR
, 0x18, 0x00);
5544 outSISIDXREG(SISSR
, 0x19, 0x20);
5545 outSISIDXREG(SISSR
, 0x16, 0x00);
5546 outSISIDXREG(SISSR
, 0x16, 0x80);
5547 outSISIDXREG(SISSR
, 0x18, 0xc5);
5548 outSISIDXREG(SISSR
, 0x19, 0x23);
5549 outSISIDXREG(SISSR
, 0x16, 0x00);
5550 outSISIDXREG(SISSR
, 0x16, 0x80);
5551 sisfb_post_xgi_delay(ivideo
, 1);
5552 outSISIDXREG(SISCR
, 0x97,0x11);
5553 sisfb_post_xgi_setclocks(ivideo
, regb
);
5554 sisfb_post_xgi_delay(ivideo
, 0x46);
5555 outSISIDXREG(SISSR
, 0x18, 0xc5);
5556 outSISIDXREG(SISSR
, 0x19, 0x23);
5557 outSISIDXREG(SISSR
, 0x16, 0x00);
5558 outSISIDXREG(SISSR
, 0x16, 0x80);
5559 sisfb_post_xgi_delay(ivideo
, 1);
5560 outSISIDXREG(SISSR
, 0x1b, 0x04);
5561 sisfb_post_xgi_delay(ivideo
, 1);
5562 outSISIDXREG(SISSR
, 0x1b, 0x00);
5563 sisfb_post_xgi_delay(ivideo
, 1);
5565 if(ivideo
->haveXGIROM
) {
5568 outSISIDXREG(SISSR
, 0x18, v1
);
5569 outSISIDXREG(SISSR
, 0x19, 0x06);
5570 outSISIDXREG(SISSR
, 0x16, 0x04);
5571 outSISIDXREG(SISSR
, 0x16, 0x84);
5572 sisfb_post_xgi_delay(ivideo
, 1);
5575 sisfb_post_xgi_setclocks(ivideo
, regb
);
5576 if((ivideo
->chip
== XGI_40
) &&
5577 ((ivideo
->revision_id
== 1) ||
5578 (ivideo
->revision_id
== 2))) {
5579 outSISIDXREG(SISCR
, 0x82, bios
[regb
+ 0x158]);
5580 outSISIDXREG(SISCR
, 0x85, bios
[regb
+ 0x160]);
5581 outSISIDXREG(SISCR
, 0x86, bios
[regb
+ 0x168]);
5583 outSISIDXREG(SISCR
, 0x82, 0x88);
5584 outSISIDXREG(SISCR
, 0x86, 0x00);
5585 inSISIDXREG(SISCR
, 0x86, reg
);
5586 outSISIDXREG(SISCR
, 0x86, 0x88);
5587 outSISIDXREG(SISCR
, 0x82, 0x77);
5588 outSISIDXREG(SISCR
, 0x85, 0x00);
5589 inSISIDXREG(SISCR
, 0x85, reg
);
5590 outSISIDXREG(SISCR
, 0x85, 0x88);
5591 inSISIDXREG(SISCR
, 0x85, reg
);
5592 v1
= cs160
[regb
]; v2
= cs158
[regb
];
5593 if(ivideo
->haveXGIROM
) {
5594 v1
= bios
[regb
+ 0x160];
5595 v2
= bios
[regb
+ 0x158];
5597 outSISIDXREG(SISCR
, 0x85, v1
);
5598 outSISIDXREG(SISCR
, 0x82, v2
);
5600 if(ivideo
->chip
== XGI_40
) {
5601 outSISIDXREG(SISCR
, 0x97, 0x11);
5603 if((ivideo
->chip
== XGI_40
) && (ivideo
->revision_id
== 2)) {
5604 outSISIDXREG(SISCR
, 0x98, 0x01);
5606 outSISIDXREG(SISCR
, 0x98, 0x03);
5608 outSISIDXREG(SISCR
, 0x9a, 0x02);
5610 if(ivideo
->chip
== XGI_40
) {
5611 outSISIDXREG(SISSR
, 0x18, 0x01);
5613 outSISIDXREG(SISSR
, 0x18, 0x00);
5615 outSISIDXREG(SISSR
, 0x19, 0x40);
5616 outSISIDXREG(SISSR
, 0x16, 0x00);
5617 outSISIDXREG(SISSR
, 0x16, 0x80);
5618 if((ivideo
->chip
== XGI_40
) && (bios
[0x1cb] != 0x0c)) {
5619 sisfb_post_xgi_delay(ivideo
, 0x43);
5620 sisfb_post_xgi_delay(ivideo
, 0x43);
5621 sisfb_post_xgi_delay(ivideo
, 0x43);
5622 outSISIDXREG(SISSR
, 0x18, 0x00);
5623 outSISIDXREG(SISSR
, 0x19, 0x40);
5624 outSISIDXREG(SISSR
, 0x16, 0x00);
5625 outSISIDXREG(SISSR
, 0x16, 0x80);
5627 sisfb_post_xgi_delay(ivideo
, 4);
5629 if(ivideo
->haveXGIROM
) {
5632 outSISIDXREG(SISSR
, 0x18, v1
);
5633 outSISIDXREG(SISSR
, 0x19, 0x01);
5634 if(ivideo
->chip
== XGI_40
) {
5635 outSISIDXREG(SISSR
, 0x16, bios
[0x53e]);
5636 outSISIDXREG(SISSR
, 0x16, bios
[0x53f]);
5638 outSISIDXREG(SISSR
, 0x16, 0x05);
5639 outSISIDXREG(SISSR
, 0x16, 0x85);
5641 sisfb_post_xgi_delay(ivideo
, 0x43);
5642 if(ivideo
->chip
== XGI_40
) {
5643 outSISIDXREG(SISSR
, 0x1b, 0x01);
5645 outSISIDXREG(SISSR
, 0x1b, 0x03);
5647 sisfb_post_xgi_delay(ivideo
, 0x22);
5648 outSISIDXREG(SISSR
, 0x18, v1
);
5649 outSISIDXREG(SISSR
, 0x19, 0x00);
5650 if(ivideo
->chip
== XGI_40
) {
5651 outSISIDXREG(SISSR
, 0x16, bios
[0x540]);
5652 outSISIDXREG(SISSR
, 0x16, bios
[0x541]);
5654 outSISIDXREG(SISSR
, 0x16, 0x05);
5655 outSISIDXREG(SISSR
, 0x16, 0x85);
5657 outSISIDXREG(SISSR
, 0x1b, 0x00);
5662 if(ivideo
->haveXGIROM
) {
5663 v1
= bios
[0x110 + regb
];
5665 outSISIDXREG(SISSR
, 0x1b, v1
);
5668 v1
= 0x00; v2
= 0x00;
5669 if(ivideo
->haveXGIROM
) {
5675 if((v1
& 0x40) && (v2
& regd
) && ivideo
->haveXGIROM
) {
5677 outSISIDXREG(SISSR
, 0x13, bios
[regb
+ 0xe0]);
5678 outSISIDXREG(SISSR
, 0x14, bios
[regb
+ 0xe0 + 8]);
5682 /* Set default mode, don't clear screen */
5683 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
5684 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
5685 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
5686 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
5687 ivideo
->SiS_Pr
.VideoMemorySize
= 8 << 20;
5688 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
5690 outSISIDXREG(SISSR
, 0x05, 0x86);
5692 /* Disable read-cache */
5693 andSISIDXREG(SISSR
, 0x21, 0xdf);
5694 sisfb_post_xgi_ramsize(ivideo
);
5695 /* Enable read-cache */
5696 orSISIDXREG(SISSR
, 0x21, 0x20);
5701 printk(KERN_DEBUG
"-----------------\n");
5702 for(i
= 0; i
< 0xff; i
++) {
5703 inSISIDXREG(SISCR
, i
, reg
);
5704 printk(KERN_DEBUG
"CR%02x(%x) = 0x%02x\n", i
, SISCR
, reg
);
5706 for(i
= 0; i
< 0x40; i
++) {
5707 inSISIDXREG(SISSR
, i
, reg
);
5708 printk(KERN_DEBUG
"SR%02x(%x) = 0x%02x\n", i
, SISSR
, reg
);
5710 printk(KERN_DEBUG
"-----------------\n");
5714 if(ivideo
->chip
== XGI_20
) {
5715 orSISIDXREG(SISCR
, 0x32, 0x20);
5717 inSISIDXREG(SISPART4
, 0x00, reg
);
5718 if((reg
== 1) || (reg
== 2)) {
5719 sisfb_sense_crt1(ivideo
);
5721 orSISIDXREG(SISCR
, 0x32, 0x20);
5725 /* Set default mode, don't clear screen */
5726 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
5727 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
5728 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
5729 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
5730 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
5732 outSISIDXREG(SISSR
, 0x05, 0x86);
5735 orSISIDXREG(SISSR
, 0x01, 0x20);
5737 /* Save mode number in CR34 */
5738 outSISIDXREG(SISCR
, 0x34, 0x2e);
5740 /* Let everyone know what the current mode is */
5741 ivideo
->modeprechange
= 0x2e;
5743 if(ivideo
->chip
== XGI_40
) {
5744 inSISIDXREG(SISCR
, 0xca, reg
);
5745 inSISIDXREG(SISCR
, 0xcc, v1
);
5746 if((reg
& 0x10) && (!(v1
& 0x04))) {
5748 "sisfb: Please connect power to the card.\n");
5757 static int __devinit
5758 sisfb_probe(struct pci_dev
*pdev
, const struct pci_device_id
*ent
)
5760 struct sisfb_chip_info
*chipinfo
= &sisfb_chip_info
[ent
->driver_data
];
5761 struct sis_video_info
*ivideo
= NULL
;
5762 struct fb_info
*sis_fb_info
= NULL
;
5770 sis_fb_info
= framebuffer_alloc(sizeof(*ivideo
), &pdev
->dev
);
5774 ivideo
= (struct sis_video_info
*)sis_fb_info
->par
;
5775 ivideo
->memyselfandi
= sis_fb_info
;
5777 ivideo
->sisfb_id
= SISFB_ID
;
5779 if(card_list
== NULL
) {
5780 ivideo
->cardnumber
= 0;
5782 struct sis_video_info
*countvideo
= card_list
;
5783 ivideo
->cardnumber
= 1;
5784 while((countvideo
= countvideo
->next
) != 0)
5785 ivideo
->cardnumber
++;
5788 strncpy(ivideo
->myid
, chipinfo
->chip_name
, 30);
5790 ivideo
->warncount
= 0;
5791 ivideo
->chip_id
= pdev
->device
;
5792 ivideo
->chip_vendor
= pdev
->vendor
;
5793 pci_read_config_byte(pdev
, PCI_REVISION_ID
, &ivideo
->revision_id
);
5794 ivideo
->SiS_Pr
.ChipRevision
= ivideo
->revision_id
;
5795 pci_read_config_word(pdev
, PCI_COMMAND
, ®16
);
5796 ivideo
->sisvga_enabled
= reg16
& 0x01;
5797 ivideo
->pcibus
= pdev
->bus
->number
;
5798 ivideo
->pcislot
= PCI_SLOT(pdev
->devfn
);
5799 ivideo
->pcifunc
= PCI_FUNC(pdev
->devfn
);
5800 ivideo
->subsysvendor
= pdev
->subsystem_vendor
;
5801 ivideo
->subsysdevice
= pdev
->subsystem_device
;
5802 #ifdef SIS_OLD_CONFIG_COMPAT
5803 ivideo
->ioctl32registered
= 0;
5807 if(sisfb_mode_idx
== -1) {
5808 sisfb_get_vga_mode_from_kernel();
5812 ivideo
->chip
= chipinfo
->chip
;
5813 ivideo
->sisvga_engine
= chipinfo
->vgaengine
;
5814 ivideo
->hwcursor_size
= chipinfo
->hwcursor_size
;
5815 ivideo
->CRT2_write_enable
= chipinfo
->CRT2_write_enable
;
5816 ivideo
->mni
= chipinfo
->mni
;
5818 ivideo
->detectedpdc
= 0xff;
5819 ivideo
->detectedpdca
= 0xff;
5820 ivideo
->detectedlcda
= 0xff;
5822 ivideo
->sisfb_thismonitor
.datavalid
= false;
5824 ivideo
->current_base
= 0;
5826 ivideo
->engineok
= 0;
5828 ivideo
->sisfb_was_boot_device
= 0;
5829 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))
5830 if(pdev
->resource
[PCI_ROM_RESOURCE
].flags
& IORESOURCE_ROM_SHADOW
) {
5831 if(ivideo
->sisvga_enabled
)
5832 ivideo
->sisfb_was_boot_device
= 1;
5834 printk(KERN_DEBUG
"sisfb: PCI device is disabled, "
5835 "but marked as boot video device ???\n");
5836 printk(KERN_DEBUG
"sisfb: I will not accept this "
5837 "as the primary VGA device\n");
5842 ivideo
->sisfb_parm_mem
= sisfb_parm_mem
;
5843 ivideo
->sisfb_accel
= sisfb_accel
;
5844 ivideo
->sisfb_ypan
= sisfb_ypan
;
5845 ivideo
->sisfb_max
= sisfb_max
;
5846 ivideo
->sisfb_userom
= sisfb_userom
;
5847 ivideo
->sisfb_useoem
= sisfb_useoem
;
5848 ivideo
->sisfb_mode_idx
= sisfb_mode_idx
;
5849 ivideo
->sisfb_parm_rate
= sisfb_parm_rate
;
5850 ivideo
->sisfb_crt1off
= sisfb_crt1off
;
5851 ivideo
->sisfb_forcecrt1
= sisfb_forcecrt1
;
5852 ivideo
->sisfb_crt2type
= sisfb_crt2type
;
5853 ivideo
->sisfb_crt2flags
= sisfb_crt2flags
;
5854 /* pdc(a), scalelcd, special timing, lvdshl handled below */
5855 ivideo
->sisfb_dstn
= sisfb_dstn
;
5856 ivideo
->sisfb_fstn
= sisfb_fstn
;
5857 ivideo
->sisfb_tvplug
= sisfb_tvplug
;
5858 ivideo
->sisfb_tvstd
= sisfb_tvstd
;
5859 ivideo
->tvxpos
= sisfb_tvxposoffset
;
5860 ivideo
->tvypos
= sisfb_tvyposoffset
;
5861 ivideo
->sisfb_nocrt2rate
= sisfb_nocrt2rate
;
5862 ivideo
->refresh_rate
= 0;
5863 if(ivideo
->sisfb_parm_rate
!= -1) {
5864 ivideo
->refresh_rate
= ivideo
->sisfb_parm_rate
;
5867 ivideo
->SiS_Pr
.UsePanelScaler
= sisfb_scalelcd
;
5868 ivideo
->SiS_Pr
.CenterScreen
= -1;
5869 ivideo
->SiS_Pr
.SiS_CustomT
= sisfb_specialtiming
;
5870 ivideo
->SiS_Pr
.LVDSHL
= sisfb_lvdshl
;
5872 ivideo
->SiS_Pr
.SiS_Backup70xx
= 0xff;
5873 ivideo
->SiS_Pr
.SiS_CHOverScan
= -1;
5874 ivideo
->SiS_Pr
.SiS_ChSW
= false;
5875 ivideo
->SiS_Pr
.SiS_UseLCDA
= false;
5876 ivideo
->SiS_Pr
.HaveEMI
= false;
5877 ivideo
->SiS_Pr
.HaveEMILCD
= false;
5878 ivideo
->SiS_Pr
.OverruleEMI
= false;
5879 ivideo
->SiS_Pr
.SiS_SensibleSR11
= false;
5880 ivideo
->SiS_Pr
.SiS_MyCR63
= 0x63;
5881 ivideo
->SiS_Pr
.PDC
= -1;
5882 ivideo
->SiS_Pr
.PDCA
= -1;
5883 ivideo
->SiS_Pr
.DDCPortMixup
= false;
5884 #ifdef CONFIG_FB_SIS_315
5885 if(ivideo
->chip
>= SIS_330
) {
5886 ivideo
->SiS_Pr
.SiS_MyCR63
= 0x53;
5887 if(ivideo
->chip
>= SIS_661
) {
5888 ivideo
->SiS_Pr
.SiS_SensibleSR11
= true;
5893 memcpy(&ivideo
->default_var
, &my_default_var
, sizeof(my_default_var
));
5895 pci_set_drvdata(pdev
, ivideo
);
5897 /* Patch special cases */
5898 if((ivideo
->nbridge
= sisfb_get_northbridge(ivideo
->chip
))) {
5899 switch(ivideo
->nbridge
->device
) {
5900 #ifdef CONFIG_FB_SIS_300
5901 case PCI_DEVICE_ID_SI_730
:
5902 ivideo
->chip
= SIS_730
;
5903 strcpy(ivideo
->myid
, "SiS 730");
5906 #ifdef CONFIG_FB_SIS_315
5907 case PCI_DEVICE_ID_SI_651
:
5908 /* ivideo->chip is ok */
5909 strcpy(ivideo
->myid
, "SiS 651");
5911 case PCI_DEVICE_ID_SI_740
:
5912 ivideo
->chip
= SIS_740
;
5913 strcpy(ivideo
->myid
, "SiS 740");
5915 case PCI_DEVICE_ID_SI_661
:
5916 ivideo
->chip
= SIS_661
;
5917 strcpy(ivideo
->myid
, "SiS 661");
5919 case PCI_DEVICE_ID_SI_741
:
5920 ivideo
->chip
= SIS_741
;
5921 strcpy(ivideo
->myid
, "SiS 741");
5923 case PCI_DEVICE_ID_SI_760
:
5924 ivideo
->chip
= SIS_760
;
5925 strcpy(ivideo
->myid
, "SiS 760");
5927 case PCI_DEVICE_ID_SI_761
:
5928 ivideo
->chip
= SIS_761
;
5929 strcpy(ivideo
->myid
, "SiS 761");
5937 ivideo
->SiS_Pr
.ChipType
= ivideo
->chip
;
5939 ivideo
->SiS_Pr
.ivideo
= (void *)ivideo
;
5941 #ifdef CONFIG_FB_SIS_315
5942 if((ivideo
->SiS_Pr
.ChipType
== SIS_315PRO
) ||
5943 (ivideo
->SiS_Pr
.ChipType
== SIS_315
)) {
5944 ivideo
->SiS_Pr
.ChipType
= SIS_315H
;
5948 if(!ivideo
->sisvga_enabled
) {
5949 if(pci_enable_device(pdev
)) {
5950 if(ivideo
->nbridge
) SIS_PCI_PUT_DEVICE(ivideo
->nbridge
);
5951 pci_set_drvdata(pdev
, NULL
);
5957 ivideo
->video_base
= pci_resource_start(pdev
, 0);
5958 ivideo
->mmio_base
= pci_resource_start(pdev
, 1);
5959 ivideo
->mmio_size
= pci_resource_len(pdev
, 1);
5960 ivideo
->SiS_Pr
.RelIO
= pci_resource_start(pdev
, 2) + 0x30;
5961 ivideo
->SiS_Pr
.IOAddress
= ivideo
->vga_base
= ivideo
->SiS_Pr
.RelIO
;
5963 SiSRegInit(&ivideo
->SiS_Pr
, ivideo
->SiS_Pr
.IOAddress
);
5965 #ifdef CONFIG_FB_SIS_300
5966 /* Find PCI systems for Chrontel/GPIO communication setup */
5967 if(ivideo
->chip
== SIS_630
) {
5970 if(mychswtable
[i
].subsysVendor
== ivideo
->subsysvendor
&&
5971 mychswtable
[i
].subsysCard
== ivideo
->subsysdevice
) {
5972 ivideo
->SiS_Pr
.SiS_ChSW
= true;
5973 printk(KERN_DEBUG
"sisfb: Identified [%s %s] "
5974 "requiring Chrontel/GPIO setup\n",
5975 mychswtable
[i
].vendorName
,
5976 mychswtable
[i
].cardName
);
5977 ivideo
->lpcdev
= SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI
, 0x0008, NULL
);
5981 } while(mychswtable
[i
].subsysVendor
!= 0);
5985 #ifdef CONFIG_FB_SIS_315
5986 if((ivideo
->chip
== SIS_760
) && (ivideo
->nbridge
)) {
5987 ivideo
->lpcdev
= SIS_PCI_GET_SLOT(ivideo
->nbridge
->bus
, (2 << 3));
5991 outSISIDXREG(SISSR
, 0x05, 0x86);
5993 if( (!ivideo
->sisvga_enabled
)
5994 #if !defined(__i386__) && !defined(__x86_64__)
5995 || (sisfb_resetcard
)
5998 for(i
= 0x30; i
<= 0x3f; i
++) {
5999 outSISIDXREG(SISCR
, i
, 0x00);
6003 /* Find out about current video mode */
6004 ivideo
->modeprechange
= 0x03;
6005 inSISIDXREG(SISCR
, 0x34, reg
);
6007 ivideo
->modeprechange
= reg
& 0x7f;
6008 } else if(ivideo
->sisvga_enabled
) {
6009 #if defined(__i386__) || defined(__x86_64__)
6010 unsigned char SIS_IOTYPE2
*tt
= ioremap(0x400, 0x100);
6012 ivideo
->modeprechange
= readb(tt
+ 0x49);
6018 /* Search and copy ROM image */
6019 ivideo
->bios_abase
= NULL
;
6020 ivideo
->SiS_Pr
.VirtualRomBase
= NULL
;
6021 ivideo
->SiS_Pr
.UseROM
= false;
6022 ivideo
->haveXGIROM
= ivideo
->SiS_Pr
.SiS_XGIROM
= false;
6023 if(ivideo
->sisfb_userom
) {
6024 ivideo
->SiS_Pr
.VirtualRomBase
= sisfb_find_rom(pdev
);
6025 ivideo
->bios_abase
= ivideo
->SiS_Pr
.VirtualRomBase
;
6026 ivideo
->SiS_Pr
.UseROM
= (bool)(ivideo
->SiS_Pr
.VirtualRomBase
);
6027 printk(KERN_INFO
"sisfb: Video ROM %sfound\n",
6028 ivideo
->SiS_Pr
.UseROM
? "" : "not ");
6029 if((ivideo
->SiS_Pr
.UseROM
) && (ivideo
->chip
>= XGI_20
)) {
6030 ivideo
->SiS_Pr
.UseROM
= false;
6031 ivideo
->haveXGIROM
= ivideo
->SiS_Pr
.SiS_XGIROM
= true;
6032 if( (ivideo
->revision_id
== 2) &&
6033 (!(ivideo
->bios_abase
[0x1d1] & 0x01)) ) {
6034 ivideo
->SiS_Pr
.DDCPortMixup
= true;
6038 printk(KERN_INFO
"sisfb: Video ROM usage disabled\n");
6041 /* Find systems for special custom timing */
6042 if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_NONE
) {
6043 sisfb_detect_custom_timing(ivideo
);
6046 /* POST card in case this has not been done by the BIOS */
6047 if( (!ivideo
->sisvga_enabled
)
6048 #if !defined(__i386__) && !defined(__x86_64__)
6049 || (sisfb_resetcard
)
6052 #ifdef CONFIG_FB_SIS_300
6053 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
6054 if(ivideo
->chip
== SIS_300
) {
6055 sisfb_post_sis300(pdev
);
6056 ivideo
->sisfb_can_post
= 1;
6061 #ifdef CONFIG_FB_SIS_315
6062 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
6064 /* if((ivideo->chip == SIS_315H) ||
6065 (ivideo->chip == SIS_315) ||
6066 (ivideo->chip == SIS_315PRO) ||
6067 (ivideo->chip == SIS_330)) {
6068 sisfb_post_sis315330(pdev);
6069 } else */ if(ivideo
->chip
== XGI_20
) {
6070 result
= sisfb_post_xgi(pdev
);
6071 ivideo
->sisfb_can_post
= 1;
6072 } else if((ivideo
->chip
== XGI_40
) && ivideo
->haveXGIROM
) {
6073 result
= sisfb_post_xgi(pdev
);
6074 ivideo
->sisfb_can_post
= 1;
6076 printk(KERN_INFO
"sisfb: Card is not "
6077 "POSTed and sisfb can't do this either.\n");
6080 printk(KERN_ERR
"sisfb: Failed to POST card\n");
6088 ivideo
->sisfb_card_posted
= 1;
6090 /* Find out about RAM size */
6091 if(sisfb_get_dram_size(ivideo
)) {
6092 printk(KERN_INFO
"sisfb: Fatal error: Unable to determine VRAM size.\n");
6098 /* Enable PCI addressing and MMIO */
6099 if((ivideo
->sisfb_mode_idx
< 0) ||
6100 ((sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
]) != 0xFF)) {
6101 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
6102 orSISIDXREG(SISSR
, IND_SIS_PCI_ADDRESS_SET
, (SIS_PCI_ADDR_ENABLE
| SIS_MEM_MAP_IO_ENABLE
));
6103 /* Enable 2D accelerator engine */
6104 orSISIDXREG(SISSR
, IND_SIS_MODULE_ENABLE
, SIS_ENABLE_2D
);
6107 if(sisfb_pdc
!= 0xff) {
6108 if(ivideo
->sisvga_engine
== SIS_300_VGA
)
6112 ivideo
->SiS_Pr
.PDC
= sisfb_pdc
;
6114 #ifdef CONFIG_FB_SIS_315
6115 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
6116 if(sisfb_pdca
!= 0xff)
6117 ivideo
->SiS_Pr
.PDCA
= sisfb_pdca
& 0x1f;
6121 if(!request_mem_region(ivideo
->video_base
, ivideo
->video_size
, "sisfb FB")) {
6122 printk(KERN_ERR
"sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6123 (int)(ivideo
->video_size
>> 20));
6124 printk(KERN_ERR
"sisfb: Is there another framebuffer driver active?\n");
6129 if(!request_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
, "sisfb MMIO")) {
6130 printk(KERN_ERR
"sisfb: Fatal error: Unable to reserve MMIO region\n");
6135 ivideo
->video_vbase
= ioremap(ivideo
->video_base
, ivideo
->video_size
);
6136 ivideo
->SiS_Pr
.VideoMemoryAddress
= ivideo
->video_vbase
;
6137 if(!ivideo
->video_vbase
) {
6138 printk(KERN_ERR
"sisfb: Fatal error: Unable to map framebuffer memory\n");
6143 ivideo
->mmio_vbase
= ioremap(ivideo
->mmio_base
, ivideo
->mmio_size
);
6144 if(!ivideo
->mmio_vbase
) {
6145 printk(KERN_ERR
"sisfb: Fatal error: Unable to map MMIO region\n");
6147 error_0
: iounmap(ivideo
->video_vbase
);
6148 error_1
: release_mem_region(ivideo
->video_base
, ivideo
->video_size
);
6149 error_2
: release_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
);
6150 error_3
: vfree(ivideo
->bios_abase
);
6152 SIS_PCI_PUT_DEVICE(ivideo
->lpcdev
);
6154 SIS_PCI_PUT_DEVICE(ivideo
->nbridge
);
6155 pci_set_drvdata(pdev
, NULL
);
6156 if(!ivideo
->sisvga_enabled
)
6157 pci_disable_device(pdev
);
6162 printk(KERN_INFO
"sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
6163 ivideo
->video_base
, (unsigned long)ivideo
->video_vbase
, ivideo
->video_size
/ 1024);
6165 if(ivideo
->video_offset
) {
6166 printk(KERN_INFO
"sisfb: Viewport offset %ldk\n",
6167 ivideo
->video_offset
/ 1024);
6170 printk(KERN_INFO
"sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
6171 ivideo
->mmio_base
, (unsigned long)ivideo
->mmio_vbase
, ivideo
->mmio_size
/ 1024);
6174 /* Determine the size of the command queue */
6175 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
6176 ivideo
->cmdQueueSize
= TURBO_QUEUE_AREA_SIZE
;
6178 if(ivideo
->chip
== XGI_20
) {
6179 ivideo
->cmdQueueSize
= COMMAND_QUEUE_AREA_SIZE_Z7
;
6181 ivideo
->cmdQueueSize
= COMMAND_QUEUE_AREA_SIZE
;
6185 /* Engines are no longer initialized here; this is
6186 * now done after the first mode-switch (if the
6187 * submitted var has its acceleration flags set).
6190 /* Calculate the base of the (unused) hw cursor */
6191 ivideo
->hwcursor_vbase
= ivideo
->video_vbase
6192 + ivideo
->video_size
6193 - ivideo
->cmdQueueSize
6194 - ivideo
->hwcursor_size
;
6195 ivideo
->caps
|= HW_CURSOR_CAP
;
6197 /* Initialize offscreen memory manager */
6198 if((ivideo
->havenoheap
= sisfb_heap_init(ivideo
))) {
6199 printk(KERN_WARNING
"sisfb: Failed to initialize offscreen memory heap\n");
6202 /* Used for clearing the screen only, therefore respect our mem limit */
6203 ivideo
->SiS_Pr
.VideoMemoryAddress
+= ivideo
->video_offset
;
6204 ivideo
->SiS_Pr
.VideoMemorySize
= ivideo
->sisfb_mem
;
6208 ivideo
->vbflags
= 0;
6209 ivideo
->lcddefmodeidx
= DEFAULT_LCDMODE
;
6210 ivideo
->tvdefmodeidx
= DEFAULT_TVMODE
;
6211 ivideo
->defmodeidx
= DEFAULT_MODE
;
6214 if(ivideo
->chip
< XGI_20
) {
6215 if(ivideo
->bios_abase
) {
6216 ivideo
->newrom
= SiSDetermineROMLayout661(&ivideo
->SiS_Pr
);
6220 if((ivideo
->sisfb_mode_idx
< 0) ||
6221 ((sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
]) != 0xFF)) {
6223 sisfb_sense_crt1(ivideo
);
6225 sisfb_get_VB_type(ivideo
);
6227 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
6228 sisfb_detect_VB_connect(ivideo
);
6231 ivideo
->currentvbflags
= ivideo
->vbflags
& (VB_VIDEOBRIDGE
| TV_STANDARD
);
6233 /* Decide on which CRT2 device to use */
6234 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
6235 if(ivideo
->sisfb_crt2type
!= -1) {
6236 if((ivideo
->sisfb_crt2type
== CRT2_LCD
) &&
6237 (ivideo
->vbflags
& CRT2_LCD
)) {
6238 ivideo
->currentvbflags
|= CRT2_LCD
;
6239 } else if(ivideo
->sisfb_crt2type
!= CRT2_LCD
) {
6240 ivideo
->currentvbflags
|= ivideo
->sisfb_crt2type
;
6243 /* Chrontel 700x TV detection often unreliable, therefore
6244 * use a different default order on such machines
6246 if((ivideo
->sisvga_engine
== SIS_300_VGA
) &&
6247 (ivideo
->vbflags2
& VB2_CHRONTEL
)) {
6248 if(ivideo
->vbflags
& CRT2_LCD
)
6249 ivideo
->currentvbflags
|= CRT2_LCD
;
6250 else if(ivideo
->vbflags
& CRT2_TV
)
6251 ivideo
->currentvbflags
|= CRT2_TV
;
6252 else if(ivideo
->vbflags
& CRT2_VGA
)
6253 ivideo
->currentvbflags
|= CRT2_VGA
;
6255 if(ivideo
->vbflags
& CRT2_TV
)
6256 ivideo
->currentvbflags
|= CRT2_TV
;
6257 else if(ivideo
->vbflags
& CRT2_LCD
)
6258 ivideo
->currentvbflags
|= CRT2_LCD
;
6259 else if(ivideo
->vbflags
& CRT2_VGA
)
6260 ivideo
->currentvbflags
|= CRT2_VGA
;
6265 if(ivideo
->vbflags
& CRT2_LCD
) {
6266 sisfb_detect_lcd_type(ivideo
);
6269 sisfb_save_pdc_emi(ivideo
);
6271 if(!ivideo
->sisfb_crt1off
) {
6272 sisfb_handle_ddc(ivideo
, &ivideo
->sisfb_thismonitor
, 0);
6274 if((ivideo
->vbflags2
& VB2_SISTMDSBRIDGE
) &&
6275 (ivideo
->vbflags
& (CRT2_VGA
| CRT2_LCD
))) {
6276 sisfb_handle_ddc(ivideo
, &ivideo
->sisfb_thismonitor
, 1);
6280 if(ivideo
->sisfb_mode_idx
>= 0) {
6281 int bu
= ivideo
->sisfb_mode_idx
;
6282 ivideo
->sisfb_mode_idx
= sisfb_validate_mode(ivideo
,
6283 ivideo
->sisfb_mode_idx
, ivideo
->currentvbflags
);
6284 if(bu
!= ivideo
->sisfb_mode_idx
) {
6285 printk(KERN_ERR
"Mode %dx%dx%d failed validation\n",
6286 sisbios_mode
[bu
].xres
,
6287 sisbios_mode
[bu
].yres
,
6288 sisbios_mode
[bu
].bpp
);
6292 if(ivideo
->sisfb_mode_idx
< 0) {
6293 switch(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
6295 ivideo
->sisfb_mode_idx
= ivideo
->lcddefmodeidx
;
6298 ivideo
->sisfb_mode_idx
= ivideo
->tvdefmodeidx
;
6301 ivideo
->sisfb_mode_idx
= ivideo
->defmodeidx
;
6306 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
6308 if(ivideo
->refresh_rate
!= 0) {
6309 sisfb_search_refresh_rate(ivideo
, ivideo
->refresh_rate
,
6310 ivideo
->sisfb_mode_idx
);
6313 if(ivideo
->rate_idx
== 0) {
6314 ivideo
->rate_idx
= sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
;
6315 ivideo
->refresh_rate
= 60;
6318 if(ivideo
->sisfb_thismonitor
.datavalid
) {
6319 if(!sisfb_verify_rate(ivideo
, &ivideo
->sisfb_thismonitor
,
6320 ivideo
->sisfb_mode_idx
,
6322 ivideo
->refresh_rate
)) {
6323 printk(KERN_INFO
"sisfb: WARNING: Refresh rate "
6324 "exceeds monitor specs!\n");
6328 ivideo
->video_bpp
= sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
;
6329 ivideo
->video_width
= sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
;
6330 ivideo
->video_height
= sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
;
6332 sisfb_set_vparms(ivideo
);
6334 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
6336 /* ---------------- For 2.4: Now switch the mode ------------------ */
6338 printk(KERN_INFO
"sisfb: Setting mode %dx%dx%d (%dHz)\n",
6339 ivideo
->video_width
, ivideo
->video_height
, ivideo
->video_bpp
,
6340 ivideo
->refresh_rate
);
6342 /* Determine whether or not acceleration is to be
6343 * used. Need to know before pre/post_set_mode()
6346 ivideo
->default_var
.accel_flags
&= ~FB_ACCELF_TEXT
;
6347 if(ivideo
->sisfb_accel
) {
6349 ivideo
->default_var
.accel_flags
|= FB_ACCELF_TEXT
;
6352 /* Now switch the mode */
6353 sisfb_pre_setmode(ivideo
);
6355 if(SiSSetMode(&ivideo
->SiS_Pr
, ivideo
->mode_no
) == 0) {
6356 printk(KERN_ERR
"sisfb: Fatal error: Setting mode[0x%x] failed\n",
6359 iounmap(ivideo
->mmio_vbase
);
6363 outSISIDXREG(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
6365 sisfb_post_setmode(ivideo
);
6367 /* Maximize regardless of sisfb_max at startup */
6368 ivideo
->default_var
.yres_virtual
= 32767;
6370 /* Force reset of x virtual in crtc_to_var */
6371 ivideo
->default_var
.xres_virtual
= 0;
6373 /* Copy mode timing to var */
6374 sisfb_crtc_to_var(ivideo
, &ivideo
->default_var
);
6376 /* Find out about screen pitch */
6377 sisfb_calc_pitch(ivideo
, &ivideo
->default_var
);
6378 sisfb_set_pitch(ivideo
);
6380 /* Init the accelerator (does nothing currently) */
6381 sisfb_initaccel(ivideo
);
6383 /* Init some fbinfo entries */
6384 sis_fb_info
->node
= -1;
6385 sis_fb_info
->flags
= FBINFO_FLAG_DEFAULT
;
6386 sis_fb_info
->fbops
= &sisfb_ops
;
6387 sis_fb_info
->disp
= &ivideo
->sis_disp
;
6388 sis_fb_info
->blank
= &sisfb_blank
;
6389 sis_fb_info
->switch_con
= &sisfb_switch
;
6390 sis_fb_info
->updatevar
= &sisfb_update_var
;
6391 sis_fb_info
->changevar
= NULL
;
6392 strcpy(sis_fb_info
->fontname
, sisfb_fontname
);
6394 sisfb_set_disp(-1, &ivideo
->default_var
, sis_fb_info
);
6396 #else /* --------- For 2.6: Setup a somewhat sane default var ------------ */
6398 printk(KERN_INFO
"sisfb: Default mode is %dx%dx%d (%dHz)\n",
6399 ivideo
->video_width
, ivideo
->video_height
, ivideo
->video_bpp
,
6400 ivideo
->refresh_rate
);
6402 /* Set up the default var according to chosen default display mode */
6403 ivideo
->default_var
.xres
= ivideo
->default_var
.xres_virtual
= ivideo
->video_width
;
6404 ivideo
->default_var
.yres
= ivideo
->default_var
.yres_virtual
= ivideo
->video_height
;
6405 ivideo
->default_var
.bits_per_pixel
= ivideo
->video_bpp
;
6407 sisfb_bpp_to_var(ivideo
, &ivideo
->default_var
);
6409 ivideo
->default_var
.pixclock
= (u32
) (1000000000 /
6410 sisfb_mode_rate_to_dclock(&ivideo
->SiS_Pr
, ivideo
->mode_no
, ivideo
->rate_idx
));
6412 if(sisfb_mode_rate_to_ddata(&ivideo
->SiS_Pr
, ivideo
->mode_no
,
6413 ivideo
->rate_idx
, &ivideo
->default_var
)) {
6414 if((ivideo
->default_var
.vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
6415 ivideo
->default_var
.pixclock
<<= 1;
6419 if(ivideo
->sisfb_ypan
) {
6420 /* Maximize regardless of sisfb_max at startup */
6421 ivideo
->default_var
.yres_virtual
=
6422 sisfb_calc_maxyres(ivideo
, &ivideo
->default_var
);
6423 if(ivideo
->default_var
.yres_virtual
< ivideo
->default_var
.yres
) {
6424 ivideo
->default_var
.yres_virtual
= ivideo
->default_var
.yres
;
6428 sisfb_calc_pitch(ivideo
, &ivideo
->default_var
);
6431 if(ivideo
->sisfb_accel
) {
6433 #ifdef STUPID_ACCELF_TEXT_SHIT
6434 ivideo
->default_var
.accel_flags
|= FB_ACCELF_TEXT
;
6437 sisfb_initaccel(ivideo
);
6439 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
6440 sis_fb_info
->flags
= FBINFO_DEFAULT
|
6441 FBINFO_HWACCEL_YPAN
|
6442 FBINFO_HWACCEL_XPAN
|
6443 FBINFO_HWACCEL_COPYAREA
|
6444 FBINFO_HWACCEL_FILLRECT
|
6445 ((ivideo
->accel
) ? 0 : FBINFO_HWACCEL_DISABLED
);
6447 sis_fb_info
->flags
= FBINFO_FLAG_DEFAULT
;
6449 sis_fb_info
->var
= ivideo
->default_var
;
6450 sis_fb_info
->fix
= ivideo
->sisfb_fix
;
6451 sis_fb_info
->screen_base
= ivideo
->video_vbase
+ ivideo
->video_offset
;
6452 sis_fb_info
->fbops
= &sisfb_ops
;
6453 sisfb_get_fix(&sis_fb_info
->fix
, -1, sis_fb_info
);
6454 sis_fb_info
->pseudo_palette
= ivideo
->pseudo_palette
;
6456 fb_alloc_cmap(&sis_fb_info
->cmap
, 256 , 0);
6459 printk(KERN_DEBUG
"sisfb: Initial vbflags 0x%x\n", (int)ivideo
->vbflags
);
6462 ivideo
->mtrr
= mtrr_add(ivideo
->video_base
, ivideo
->video_size
,
6463 MTRR_TYPE_WRCOMB
, 1);
6464 if(ivideo
->mtrr
< 0) {
6465 printk(KERN_DEBUG
"sisfb: Failed to add MTRRs\n");
6469 if(register_framebuffer(sis_fb_info
) < 0) {
6470 printk(KERN_ERR
"sisfb: Fatal error: Failed to register framebuffer\n");
6472 iounmap(ivideo
->mmio_vbase
);
6476 ivideo
->registered
= 1;
6479 ivideo
->next
= card_list
;
6482 #ifdef SIS_OLD_CONFIG_COMPAT
6485 /* Our ioctls are all "32/64bit compatible" */
6486 ret
= register_ioctl32_conversion(FBIO_ALLOC
, NULL
);
6487 ret
|= register_ioctl32_conversion(FBIO_FREE
, NULL
);
6488 ret
|= register_ioctl32_conversion(FBIOGET_VBLANK
, NULL
);
6489 ret
|= register_ioctl32_conversion(SISFB_GET_INFO_SIZE
, NULL
);
6490 ret
|= register_ioctl32_conversion(SISFB_GET_INFO
, NULL
);
6491 ret
|= register_ioctl32_conversion(SISFB_GET_TVPOSOFFSET
, NULL
);
6492 ret
|= register_ioctl32_conversion(SISFB_SET_TVPOSOFFSET
, NULL
);
6493 ret
|= register_ioctl32_conversion(SISFB_SET_LOCK
, NULL
);
6494 ret
|= register_ioctl32_conversion(SISFB_GET_VBRSTATUS
, NULL
);
6495 ret
|= register_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE
, NULL
);
6496 ret
|= register_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE
, NULL
);
6497 ret
|= register_ioctl32_conversion(SISFB_COMMAND
, NULL
);
6500 "sisfb: Error registering ioctl32 translations\n");
6502 ivideo
->ioctl32registered
= 1;
6506 printk(KERN_INFO
"sisfb: 2D acceleration is %s, y-panning %s\n",
6507 ivideo
->sisfb_accel
? "enabled" : "disabled",
6508 ivideo
->sisfb_ypan
?
6509 (ivideo
->sisfb_max
? "enabled (auto-max)" :
6510 "enabled (no auto-max)") :
6514 printk(KERN_INFO
"fb%d: %s frame buffer device version %d.%d.%d\n",
6515 sis_fb_info
->node
, ivideo
->myid
, VER_MAJOR
, VER_MINOR
, VER_LEVEL
);
6517 printk(KERN_INFO
"sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
6519 } /* if mode = "none" */
6524 /*****************************************************/
6525 /* PCI DEVICE HANDLING */
6526 /*****************************************************/
6528 static void __devexit
sisfb_remove(struct pci_dev
*pdev
)
6530 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
6531 struct fb_info
*sis_fb_info
= ivideo
->memyselfandi
;
6532 int registered
= ivideo
->registered
;
6533 int modechanged
= ivideo
->modechanged
;
6535 #ifdef SIS_OLD_CONFIG_COMPAT
6536 if(ivideo
->ioctl32registered
) {
6538 ret
= unregister_ioctl32_conversion(FBIO_ALLOC
);
6539 ret
|= unregister_ioctl32_conversion(FBIO_FREE
);
6540 ret
|= unregister_ioctl32_conversion(FBIOGET_VBLANK
);
6541 ret
|= unregister_ioctl32_conversion(SISFB_GET_INFO_SIZE
);
6542 ret
|= unregister_ioctl32_conversion(SISFB_GET_INFO
);
6543 ret
|= unregister_ioctl32_conversion(SISFB_GET_TVPOSOFFSET
);
6544 ret
|= unregister_ioctl32_conversion(SISFB_SET_TVPOSOFFSET
);
6545 ret
|= unregister_ioctl32_conversion(SISFB_SET_LOCK
);
6546 ret
|= unregister_ioctl32_conversion(SISFB_GET_VBRSTATUS
);
6547 ret
|= unregister_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE
);
6548 ret
|= unregister_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE
);
6549 ret
|= unregister_ioctl32_conversion(SISFB_COMMAND
);
6552 "sisfb: Error unregistering ioctl32 translations\n");
6557 iounmap(ivideo
->mmio_vbase
);
6558 iounmap(ivideo
->video_vbase
);
6560 /* Release mem regions */
6561 release_mem_region(ivideo
->video_base
, ivideo
->video_size
);
6562 release_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
);
6564 vfree(ivideo
->bios_abase
);
6567 SIS_PCI_PUT_DEVICE(ivideo
->lpcdev
);
6570 SIS_PCI_PUT_DEVICE(ivideo
->nbridge
);
6573 /* Release MTRR region */
6574 if(ivideo
->mtrr
>= 0)
6575 mtrr_del(ivideo
->mtrr
, ivideo
->video_base
, ivideo
->video_size
);
6578 pci_set_drvdata(pdev
, NULL
);
6580 /* If device was disabled when starting, disable
6583 if(!ivideo
->sisvga_enabled
)
6584 pci_disable_device(pdev
);
6586 /* Unregister the framebuffer */
6587 if(ivideo
->registered
) {
6588 unregister_framebuffer(sis_fb_info
);
6589 framebuffer_release(sis_fb_info
);
6592 /* OK, our ivideo is gone for good from here. */
6594 /* TODO: Restore the initial mode
6595 * This sounds easy but is as good as impossible
6596 * on many machines with SiS chip and video bridge
6597 * since text modes are always set up differently
6598 * from machine to machine. Depends on the type
6599 * of integration between chipset and bridge.
6601 if(registered
&& modechanged
)
6603 "sisfb: Restoring of text mode not supported yet\n");
6606 static struct pci_driver sisfb_driver
= {
6608 .id_table
= sisfb_pci_table
,
6609 .probe
= sisfb_probe
,
6610 .remove
= __devexit_p(sisfb_remove
)
6613 SISINITSTATIC
int __init
sisfb_init(void)
6616 char *options
= NULL
;
6618 if(fb_get_options("sisfb", &options
))
6621 sisfb_setup(options
);
6623 return pci_register_driver(&sisfb_driver
);
6627 module_init(sisfb_init
);
6630 /*****************************************************/
6632 /*****************************************************/
6636 static char *mode
= NULL
;
6637 static int vesa
= -1;
6638 static unsigned int rate
= 0;
6639 static unsigned int crt1off
= 1;
6640 static unsigned int mem
= 0;
6641 static char *forcecrt2type
= NULL
;
6642 static int forcecrt1
= -1;
6643 static int pdc
= -1;
6644 static int pdc1
= -1;
6645 static int noaccel
= -1;
6646 static int noypan
= -1;
6647 static int nomax
= -1;
6648 static int userom
= -1;
6649 static int useoem
= -1;
6650 static char *tvstandard
= NULL
;
6651 static int nocrt2rate
= 0;
6652 static int scalelcd
= -1;
6653 static char *specialtiming
= NULL
;
6654 static int lvdshl
= -1;
6655 static int tvxposoffset
= 0, tvyposoffset
= 0;
6656 #if !defined(__i386__) && !defined(__x86_64__)
6657 static int resetcard
= 0;
6658 static int videoram
= 0;
6661 static int __init
sisfb_init_module(void)
6663 sisfb_setdefaultparms();
6666 sisfb_parm_rate
= rate
;
6668 if((scalelcd
== 0) || (scalelcd
== 1))
6669 sisfb_scalelcd
= scalelcd
^ 1;
6671 /* Need to check crt2 type first for fstn/dstn */
6674 sisfb_search_crt2type(forcecrt2type
);
6677 sisfb_search_tvstd(tvstandard
);
6680 sisfb_search_mode(mode
, false);
6682 sisfb_search_vesamode(vesa
, false);
6684 sisfb_crt1off
= (crt1off
== 0) ? 1 : 0;
6686 sisfb_forcecrt1
= forcecrt1
;
6689 else if(forcecrt1
== 0)
6694 else if(noaccel
== 0)
6699 else if(noypan
== 0)
6708 sisfb_parm_mem
= mem
;
6711 sisfb_userom
= userom
;
6714 sisfb_useoem
= useoem
;
6717 sisfb_pdc
= (pdc
& 0x7f);
6720 sisfb_pdca
= (pdc1
& 0x1f);
6722 sisfb_nocrt2rate
= nocrt2rate
;
6725 sisfb_search_specialtiming(specialtiming
);
6727 if((lvdshl
>= 0) && (lvdshl
<= 3))
6728 sisfb_lvdshl
= lvdshl
;
6730 sisfb_tvxposoffset
= tvxposoffset
;
6731 sisfb_tvyposoffset
= tvyposoffset
;
6733 #if !defined(__i386__) && !defined(__x86_64__)
6734 sisfb_resetcard
= (resetcard
) ? 1 : 0;
6736 sisfb_videoram
= videoram
;
6739 return sisfb_init();
6742 static void __exit
sisfb_remove_module(void)
6744 pci_unregister_driver(&sisfb_driver
);
6745 printk(KERN_DEBUG
"sisfb: Module unloaded\n");
6748 module_init(sisfb_init_module
);
6749 module_exit(sisfb_remove_module
);
6751 MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
6752 MODULE_LICENSE("GPL");
6753 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
6755 module_param(mem
, int, 0);
6756 module_param(noaccel
, int, 0);
6757 module_param(noypan
, int, 0);
6758 module_param(nomax
, int, 0);
6759 module_param(userom
, int, 0);
6760 module_param(useoem
, int, 0);
6761 module_param(mode
, charp
, 0);
6762 module_param(vesa
, int, 0);
6763 module_param(rate
, int, 0);
6764 module_param(forcecrt1
, int, 0);
6765 module_param(forcecrt2type
, charp
, 0);
6766 module_param(scalelcd
, int, 0);
6767 module_param(pdc
, int, 0);
6768 module_param(pdc1
, int, 0);
6769 module_param(specialtiming
, charp
, 0);
6770 module_param(lvdshl
, int, 0);
6771 module_param(tvstandard
, charp
, 0);
6772 module_param(tvxposoffset
, int, 0);
6773 module_param(tvyposoffset
, int, 0);
6774 module_param(nocrt2rate
, int, 0);
6775 #if !defined(__i386__) && !defined(__x86_64__)
6776 module_param(resetcard
, int, 0);
6777 module_param(videoram
, int, 0);
6780 MODULE_PARM_DESC(mem
,
6781 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6782 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6783 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6784 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6785 "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6786 "The value is to be specified without 'KB'.\n");
6788 MODULE_PARM_DESC(noaccel
,
6789 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
6792 MODULE_PARM_DESC(noypan
,
6793 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
6794 "will be performed by redrawing the screen. (default: 0)\n");
6796 MODULE_PARM_DESC(nomax
,
6797 "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
6798 "memory for the virtual screen in order to optimize scrolling performance. If\n"
6799 "this is set to anything other than 0, sisfb will not do this and thereby \n"
6800 "enable the user to positively specify a virtual Y size of the screen using\n"
6801 "fbset. (default: 0)\n");
6803 MODULE_PARM_DESC(mode
,
6804 "\nSelects the desired default display mode in the format XxYxDepth,\n"
6805 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
6806 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
6807 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
6809 MODULE_PARM_DESC(vesa
,
6810 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
6811 "0x117 (default: 0x0103)\n");
6813 MODULE_PARM_DESC(rate
,
6814 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
6815 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
6816 "will be ignored (default: 60)\n");
6818 MODULE_PARM_DESC(forcecrt1
,
6819 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
6820 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
6821 "0=CRT1 OFF) (default: [autodetected])\n");
6823 MODULE_PARM_DESC(forcecrt2type
,
6824 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
6825 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
6826 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
6827 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
6828 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
6829 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
6830 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
6831 "depends on the very hardware in use. (default: [autodetected])\n");
6833 MODULE_PARM_DESC(scalelcd
,
6834 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
6835 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
6836 "show black bars around the image, TMDS panels will probably do the scaling\n"
6837 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
6839 MODULE_PARM_DESC(pdc
,
6840 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
6841 "should detect this correctly in most cases; however, sometimes this is not\n"
6842 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
6843 "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
6844 "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
6845 "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
6847 #ifdef CONFIG_FB_SIS_315
6848 MODULE_PARM_DESC(pdc1
,
6849 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
6850 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
6851 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
6852 "implemented yet.\n");
6855 MODULE_PARM_DESC(specialtiming
,
6856 "\nPlease refer to documentation for more information on this option.\n");
6858 MODULE_PARM_DESC(lvdshl
,
6859 "\nPlease refer to documentation for more information on this option.\n");
6861 MODULE_PARM_DESC(tvstandard
,
6862 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
6863 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
6865 MODULE_PARM_DESC(tvxposoffset
,
6866 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
6869 MODULE_PARM_DESC(tvyposoffset
,
6870 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
6873 MODULE_PARM_DESC(nocrt2rate
,
6874 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
6875 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
6877 #if !defined(__i386__) && !defined(__x86_64__)
6878 #ifdef CONFIG_FB_SIS_300
6879 MODULE_PARM_DESC(resetcard
,
6880 "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
6881 "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
6882 "currently). Default: 0\n");
6884 MODULE_PARM_DESC(videoram
,
6885 "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
6886 "some non-x86 architectures where the memory auto detection fails. Only\n"
6887 "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
6891 #endif /* /MODULE */
6893 /* _GPL only for new symbols. */
6894 EXPORT_SYMBOL(sis_malloc
);
6895 EXPORT_SYMBOL(sis_free
);
6896 EXPORT_SYMBOL_GPL(sis_malloc_new
);
6897 EXPORT_SYMBOL_GPL(sis_free_new
);