2 * SiS 300/540/630[S]/730[S],
3 * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
5 * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
7 * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the named License,
12 * or any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
23 * Author: Thomas Winischhofer <thomas@winischhofer.net>
25 * Author of (practically wiped) code base:
27 * Copyright (C) 1999 Silicon Integrated Systems, Inc.
29 * See http://www.winischhofer.net/ for more information and updates
31 * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver,
32 * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
36 #include <linux/module.h>
37 #include <linux/moduleparam.h>
38 #include <linux/kernel.h>
39 #include <linux/spinlock.h>
40 #include <linux/errno.h>
41 #include <linux/string.h>
43 #include <linux/screen_info.h>
44 #include <linux/slab.h>
46 #include <linux/selection.h>
47 #include <linux/ioport.h>
48 #include <linux/init.h>
49 #include <linux/pci.h>
50 #include <linux/vmalloc.h>
51 #include <linux/capability.h>
53 #include <linux/types.h>
54 #include <linux/uaccess.h>
63 #if !defined(CONFIG_FB_SIS_300) && !defined(CONFIG_FB_SIS_315)
64 #warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
65 #warning sisfb will not work!
68 static void sisfb_handle_command(struct sis_video_info
*ivideo
,
69 struct sisfb_cmd
*sisfb_command
);
71 /* ------------------ Internal helper routines ----------------- */
74 sisfb_setdefaultparms(void)
92 sisfb_specialtiming
= CUT_NONE
;
98 sisfb_tvxposoffset
= 0;
99 sisfb_tvyposoffset
= 0;
100 sisfb_nocrt2rate
= 0;
101 #if !defined(__i386__) && !defined(__x86_64__)
107 /* ------------- Parameter parsing -------------- */
109 static void __devinit
110 sisfb_search_vesamode(unsigned int vesamode
, bool quiet
)
114 /* We don't know the hardware specs yet and there is no ivideo */
118 printk(KERN_ERR
"sisfb: Invalid mode. Using default.\n");
120 sisfb_mode_idx
= DEFAULT_MODE
;
125 vesamode
&= 0x1dff; /* Clean VESA mode number from other flags */
127 while(sisbios_mode
[i
++].mode_no
[0] != 0) {
128 if( (sisbios_mode
[i
-1].vesa_mode_no_1
== vesamode
) ||
129 (sisbios_mode
[i
-1].vesa_mode_no_2
== vesamode
) ) {
131 if(sisbios_mode
[i
-1].mode_no
[1] == 0x50 ||
132 sisbios_mode
[i
-1].mode_no
[1] == 0x56 ||
133 sisbios_mode
[i
-1].mode_no
[1] == 0x53)
136 if(sisbios_mode
[i
-1].mode_no
[1] == 0x5a ||
137 sisbios_mode
[i
-1].mode_no
[1] == 0x5b)
140 sisfb_mode_idx
= i
- 1;
146 printk(KERN_ERR
"sisfb: Invalid VESA mode 0x%x'\n", vesamode
);
149 static void __devinit
150 sisfb_search_mode(char *name
, bool quiet
)
152 unsigned int j
= 0, xres
= 0, yres
= 0, depth
= 0, rate
= 0;
154 char strbuf
[16], strbuf1
[20];
155 char *nameptr
= name
;
157 /* We don't know the hardware specs yet and there is no ivideo */
161 printk(KERN_ERR
"sisfb: Internal error, using default mode.\n");
163 sisfb_mode_idx
= DEFAULT_MODE
;
167 if(!strnicmp(name
, sisbios_mode
[MODE_INDEX_NONE
].name
, strlen(name
))) {
169 printk(KERN_ERR
"sisfb: Mode 'none' not supported anymore. Using default.\n");
171 sisfb_mode_idx
= DEFAULT_MODE
;
175 if(strlen(name
) <= 19) {
176 strcpy(strbuf1
, name
);
177 for(i
= 0; i
< strlen(strbuf1
); i
++) {
178 if(strbuf1
[i
] < '0' || strbuf1
[i
] > '9') strbuf1
[i
] = ' ';
181 /* This does some fuzzy mode naming detection */
182 if(sscanf(strbuf1
, "%u %u %u %u", &xres
, &yres
, &depth
, &rate
) == 4) {
183 if((rate
<= 32) || (depth
> 32)) {
184 j
= rate
; rate
= depth
; depth
= j
;
186 sprintf(strbuf
, "%ux%ux%u", xres
, yres
, depth
);
188 sisfb_parm_rate
= rate
;
189 } else if(sscanf(strbuf1
, "%u %u %u", &xres
, &yres
, &depth
) == 3) {
190 sprintf(strbuf
, "%ux%ux%u", xres
, yres
, depth
);
194 if((sscanf(strbuf1
, "%u %u", &xres
, &yres
) == 2) && (xres
!= 0)) {
195 sprintf(strbuf
, "%ux%ux8", xres
, yres
);
198 sisfb_search_vesamode(simple_strtoul(name
, NULL
, 0), quiet
);
205 while(sisbios_mode
[i
].mode_no
[0] != 0) {
206 if(!strnicmp(nameptr
, sisbios_mode
[i
++].name
, strlen(nameptr
))) {
208 if(sisbios_mode
[i
-1].mode_no
[1] == 0x50 ||
209 sisbios_mode
[i
-1].mode_no
[1] == 0x56 ||
210 sisbios_mode
[i
-1].mode_no
[1] == 0x53)
213 if(sisbios_mode
[i
-1].mode_no
[1] == 0x5a ||
214 sisbios_mode
[i
-1].mode_no
[1] == 0x5b)
217 sisfb_mode_idx
= i
- 1;
224 printk(KERN_ERR
"sisfb: Invalid mode '%s'\n", nameptr
);
228 static void __devinit
229 sisfb_get_vga_mode_from_kernel(void)
233 int mydepth
= screen_info
.lfb_depth
;
235 if(screen_info
.orig_video_isVGA
!= VIDEO_TYPE_VLFB
) return;
237 if( (screen_info
.lfb_width
>= 320) && (screen_info
.lfb_width
<= 2048) &&
238 (screen_info
.lfb_height
>= 200) && (screen_info
.lfb_height
<= 1536) &&
239 (mydepth
>= 8) && (mydepth
<= 32) ) {
241 if(mydepth
== 24) mydepth
= 32;
243 sprintf(mymode
, "%ux%ux%u", screen_info
.lfb_width
,
244 screen_info
.lfb_height
,
248 "sisfb: Using vga mode %s pre-set by kernel as default\n",
251 sisfb_search_mode(mymode
, true);
259 sisfb_search_crt2type(const char *name
)
263 /* We don't know the hardware specs yet and there is no ivideo */
265 if(name
== NULL
) return;
267 while(sis_crt2type
[i
].type_no
!= -1) {
268 if(!strnicmp(name
, sis_crt2type
[i
].name
, strlen(sis_crt2type
[i
].name
))) {
269 sisfb_crt2type
= sis_crt2type
[i
].type_no
;
270 sisfb_tvplug
= sis_crt2type
[i
].tvplug_no
;
271 sisfb_crt2flags
= sis_crt2type
[i
].flags
;
277 sisfb_dstn
= (sisfb_crt2flags
& FL_550_DSTN
) ? 1 : 0;
278 sisfb_fstn
= (sisfb_crt2flags
& FL_550_FSTN
) ? 1 : 0;
280 if(sisfb_crt2type
< 0)
281 printk(KERN_ERR
"sisfb: Invalid CRT2 type: %s\n", name
);
285 sisfb_search_tvstd(const char *name
)
289 /* We don't know the hardware specs yet and there is no ivideo */
294 while(sis_tvtype
[i
].type_no
!= -1) {
295 if(!strnicmp(name
, sis_tvtype
[i
].name
, strlen(sis_tvtype
[i
].name
))) {
296 sisfb_tvstd
= sis_tvtype
[i
].type_no
;
304 sisfb_search_specialtiming(const char *name
)
309 /* We don't know the hardware specs yet and there is no ivideo */
314 if(!strnicmp(name
, "none", 4)) {
315 sisfb_specialtiming
= CUT_FORCENONE
;
316 printk(KERN_DEBUG
"sisfb: Special timing disabled\n");
318 while(mycustomttable
[i
].chipID
!= 0) {
319 if(!strnicmp(name
,mycustomttable
[i
].optionName
,
320 strlen(mycustomttable
[i
].optionName
))) {
321 sisfb_specialtiming
= mycustomttable
[i
].SpecialID
;
323 printk(KERN_INFO
"sisfb: Special timing for %s %s forced (\"%s\")\n",
324 mycustomttable
[i
].vendorName
,
325 mycustomttable
[i
].cardName
,
326 mycustomttable
[i
].optionName
);
332 printk(KERN_WARNING
"sisfb: Invalid SpecialTiming parameter, valid are:");
333 printk(KERN_WARNING
"\t\"none\" (to disable special timings)\n");
335 while(mycustomttable
[i
].chipID
!= 0) {
336 printk(KERN_WARNING
"\t\"%s\" (for %s %s)\n",
337 mycustomttable
[i
].optionName
,
338 mycustomttable
[i
].vendorName
,
339 mycustomttable
[i
].cardName
);
346 /* ----------- Various detection routines ----------- */
348 static void __devinit
349 sisfb_detect_custom_timing(struct sis_video_info
*ivideo
)
351 unsigned char *biosver
= NULL
;
352 unsigned char *biosdate
= NULL
;
357 if(ivideo
->SiS_Pr
.UseROM
) {
358 biosver
= ivideo
->SiS_Pr
.VirtualRomBase
+ 0x06;
359 biosdate
= ivideo
->SiS_Pr
.VirtualRomBase
+ 0x2c;
360 for(i
= 0; i
< 32768; i
++)
361 chksum
+= ivideo
->SiS_Pr
.VirtualRomBase
[i
];
366 if( (mycustomttable
[i
].chipID
== ivideo
->chip
) &&
367 ((!strlen(mycustomttable
[i
].biosversion
)) ||
368 (ivideo
->SiS_Pr
.UseROM
&&
369 (!strncmp(mycustomttable
[i
].biosversion
, biosver
,
370 strlen(mycustomttable
[i
].biosversion
))))) &&
371 ((!strlen(mycustomttable
[i
].biosdate
)) ||
372 (ivideo
->SiS_Pr
.UseROM
&&
373 (!strncmp(mycustomttable
[i
].biosdate
, biosdate
,
374 strlen(mycustomttable
[i
].biosdate
))))) &&
375 ((!mycustomttable
[i
].bioschksum
) ||
376 (ivideo
->SiS_Pr
.UseROM
&&
377 (mycustomttable
[i
].bioschksum
== chksum
))) &&
378 (mycustomttable
[i
].pcisubsysvendor
== ivideo
->subsysvendor
) &&
379 (mycustomttable
[i
].pcisubsyscard
== ivideo
->subsysdevice
) ) {
381 for(j
= 0; j
< 5; j
++) {
382 if(mycustomttable
[i
].biosFootprintAddr
[j
]) {
383 if(ivideo
->SiS_Pr
.UseROM
) {
384 if(ivideo
->SiS_Pr
.VirtualRomBase
[mycustomttable
[i
].biosFootprintAddr
[j
]] !=
385 mycustomttable
[i
].biosFootprintData
[j
]) {
393 ivideo
->SiS_Pr
.SiS_CustomT
= mycustomttable
[i
].SpecialID
;
394 printk(KERN_DEBUG
"sisfb: Identified [%s %s], special timing applies\n",
395 mycustomttable
[i
].vendorName
,
396 mycustomttable
[i
].cardName
);
397 printk(KERN_DEBUG
"sisfb: [specialtiming parameter name: %s]\n",
398 mycustomttable
[i
].optionName
);
403 } while(mycustomttable
[i
].chipID
);
406 static bool __devinit
407 sisfb_interpret_edid(struct sisfb_monitor
*monitor
, u8
*buffer
)
409 int i
, j
, xres
, yres
, refresh
, index
;
412 if(buffer
[0] != 0x00 || buffer
[1] != 0xff ||
413 buffer
[2] != 0xff || buffer
[3] != 0xff ||
414 buffer
[4] != 0xff || buffer
[5] != 0xff ||
415 buffer
[6] != 0xff || buffer
[7] != 0x00) {
416 printk(KERN_DEBUG
"sisfb: Bad EDID header\n");
420 if(buffer
[0x12] != 0x01) {
421 printk(KERN_INFO
"sisfb: EDID version %d not supported\n",
426 monitor
->feature
= buffer
[0x18];
428 if(!(buffer
[0x14] & 0x80)) {
429 if(!(buffer
[0x14] & 0x08)) {
431 "sisfb: WARNING: Monitor does not support separate syncs\n");
435 if(buffer
[0x13] >= 0x01) {
436 /* EDID V1 rev 1 and 2: Search for monitor descriptor
441 if(buffer
[j
] == 0x00 && buffer
[j
+ 1] == 0x00 &&
442 buffer
[j
+ 2] == 0x00 && buffer
[j
+ 3] == 0xfd &&
443 buffer
[j
+ 4] == 0x00) {
444 monitor
->hmin
= buffer
[j
+ 7];
445 monitor
->hmax
= buffer
[j
+ 8];
446 monitor
->vmin
= buffer
[j
+ 5];
447 monitor
->vmax
= buffer
[j
+ 6];
448 monitor
->dclockmax
= buffer
[j
+ 9] * 10 * 1000;
449 monitor
->datavalid
= true;
456 if(!monitor
->datavalid
) {
457 /* Otherwise: Get a range from the list of supported
458 * Estabished Timings. This is not entirely accurate,
459 * because fixed frequency monitors are not supported
462 monitor
->hmin
= 65535; monitor
->hmax
= 0;
463 monitor
->vmin
= 65535; monitor
->vmax
= 0;
464 monitor
->dclockmax
= 0;
465 emodes
= buffer
[0x23] | (buffer
[0x24] << 8) | (buffer
[0x25] << 16);
466 for(i
= 0; i
< 13; i
++) {
467 if(emodes
& sisfb_ddcsmodes
[i
].mask
) {
468 if(monitor
->hmin
> sisfb_ddcsmodes
[i
].h
) monitor
->hmin
= sisfb_ddcsmodes
[i
].h
;
469 if(monitor
->hmax
< sisfb_ddcsmodes
[i
].h
) monitor
->hmax
= sisfb_ddcsmodes
[i
].h
+ 1;
470 if(monitor
->vmin
> sisfb_ddcsmodes
[i
].v
) monitor
->vmin
= sisfb_ddcsmodes
[i
].v
;
471 if(monitor
->vmax
< sisfb_ddcsmodes
[i
].v
) monitor
->vmax
= sisfb_ddcsmodes
[i
].v
;
472 if(monitor
->dclockmax
< sisfb_ddcsmodes
[i
].d
) monitor
->dclockmax
= sisfb_ddcsmodes
[i
].d
;
476 for(i
= 0; i
< 8; i
++) {
477 xres
= (buffer
[index
] + 31) * 8;
478 switch(buffer
[index
+ 1] & 0xc0) {
479 case 0xc0: yres
= (xres
* 9) / 16; break;
480 case 0x80: yres
= (xres
* 4) / 5; break;
481 case 0x40: yres
= (xres
* 3) / 4; break;
482 default: yres
= xres
; break;
484 refresh
= (buffer
[index
+ 1] & 0x3f) + 60;
485 if((xres
>= 640) && (yres
>= 480)) {
486 for(j
= 0; j
< 8; j
++) {
487 if((xres
== sisfb_ddcfmodes
[j
].x
) &&
488 (yres
== sisfb_ddcfmodes
[j
].y
) &&
489 (refresh
== sisfb_ddcfmodes
[j
].v
)) {
490 if(monitor
->hmin
> sisfb_ddcfmodes
[j
].h
) monitor
->hmin
= sisfb_ddcfmodes
[j
].h
;
491 if(monitor
->hmax
< sisfb_ddcfmodes
[j
].h
) monitor
->hmax
= sisfb_ddcfmodes
[j
].h
+ 1;
492 if(monitor
->vmin
> sisfb_ddcsmodes
[j
].v
) monitor
->vmin
= sisfb_ddcsmodes
[j
].v
;
493 if(monitor
->vmax
< sisfb_ddcsmodes
[j
].v
) monitor
->vmax
= sisfb_ddcsmodes
[j
].v
;
494 if(monitor
->dclockmax
< sisfb_ddcsmodes
[j
].d
) monitor
->dclockmax
= sisfb_ddcsmodes
[j
].d
;
500 if((monitor
->hmin
<= monitor
->hmax
) && (monitor
->vmin
<= monitor
->vmax
)) {
501 monitor
->datavalid
= true;
505 return monitor
->datavalid
;
508 static void __devinit
509 sisfb_handle_ddc(struct sis_video_info
*ivideo
, struct sisfb_monitor
*monitor
, int crtno
)
511 unsigned short temp
, i
, realcrtno
= crtno
;
512 unsigned char buffer
[256];
514 monitor
->datavalid
= false;
517 if(ivideo
->vbflags
& CRT2_LCD
) realcrtno
= 1;
518 else if(ivideo
->vbflags
& CRT2_VGA
) realcrtno
= 2;
522 if((ivideo
->sisfb_crt1off
) && (!crtno
))
525 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
526 realcrtno
, 0, &buffer
[0], ivideo
->vbflags2
);
527 if((!temp
) || (temp
== 0xffff)) {
528 printk(KERN_INFO
"sisfb: CRT%d DDC probing failed\n", crtno
+ 1);
531 printk(KERN_INFO
"sisfb: CRT%d DDC supported\n", crtno
+ 1);
532 printk(KERN_INFO
"sisfb: CRT%d DDC level: %s%s%s%s\n",
534 (temp
& 0x1a) ? "" : "[none of the supported]",
535 (temp
& 0x02) ? "2 " : "",
536 (temp
& 0x08) ? "D&P" : "",
537 (temp
& 0x10) ? "FPDI-2" : "");
539 i
= 3; /* Number of retrys */
541 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
542 realcrtno
, 1, &buffer
[0], ivideo
->vbflags2
);
543 } while((temp
) && i
--);
545 if(sisfb_interpret_edid(monitor
, &buffer
[0])) {
546 printk(KERN_INFO
"sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
547 monitor
->hmin
, monitor
->hmax
, monitor
->vmin
, monitor
->vmax
,
548 monitor
->dclockmax
/ 1000);
550 printk(KERN_INFO
"sisfb: CRT%d DDC EDID corrupt\n", crtno
+ 1);
553 printk(KERN_INFO
"sisfb: CRT%d DDC reading failed\n", crtno
+ 1);
556 printk(KERN_INFO
"sisfb: VESA D&P and FPDI-2 not supported yet\n");
561 /* -------------- Mode validation --------------- */
564 sisfb_verify_rate(struct sis_video_info
*ivideo
, struct sisfb_monitor
*monitor
,
565 int mode_idx
, int rate_idx
, int rate
)
568 unsigned int dclock
, hsync
;
570 if(!monitor
->datavalid
)
576 /* Skip for 320x200, 320x240, 640x400 */
577 switch(sisbios_mode
[mode_idx
].mode_no
[ivideo
->mni
]) {
588 #ifdef CONFIG_FB_SIS_315
591 if(ivideo
->sisvga_engine
== SIS_315_VGA
) return true;
595 if(rate
< (monitor
->vmin
- 1))
597 if(rate
> (monitor
->vmax
+ 1))
600 if(sisfb_gettotalfrommode(&ivideo
->SiS_Pr
,
601 sisbios_mode
[mode_idx
].mode_no
[ivideo
->mni
],
602 &htotal
, &vtotal
, rate_idx
)) {
603 dclock
= (htotal
* vtotal
* rate
) / 1000;
604 if(dclock
> (monitor
->dclockmax
+ 1000))
606 hsync
= dclock
/ htotal
;
607 if(hsync
< (monitor
->hmin
- 1))
609 if(hsync
> (monitor
->hmax
+ 1))
618 sisfb_validate_mode(struct sis_video_info
*ivideo
, int myindex
, u32 vbflags
)
620 u16 xres
=0, yres
, myres
;
622 #ifdef CONFIG_FB_SIS_300
623 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
624 if(!(sisbios_mode
[myindex
].chipset
& MD_SIS300
))
628 #ifdef CONFIG_FB_SIS_315
629 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
630 if(!(sisbios_mode
[myindex
].chipset
& MD_SIS315
))
635 myres
= sisbios_mode
[myindex
].yres
;
637 switch(vbflags
& VB_DISPTYPE_DISP2
) {
640 xres
= ivideo
->lcdxres
; yres
= ivideo
->lcdyres
;
642 if((ivideo
->SiS_Pr
.SiS_CustomT
!= CUT_PANEL848
) &&
643 (ivideo
->SiS_Pr
.SiS_CustomT
!= CUT_PANEL856
)) {
644 if(sisbios_mode
[myindex
].xres
> xres
)
650 if(ivideo
->sisfb_fstn
) {
651 if(sisbios_mode
[myindex
].xres
== 320) {
653 switch(sisbios_mode
[myindex
].mode_no
[1]) {
654 case 0x50: myindex
= MODE_FSTN_8
; break;
655 case 0x56: myindex
= MODE_FSTN_16
; break;
656 case 0x53: return -1;
662 if(SiS_GetModeID_LCD(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
663 sisbios_mode
[myindex
].yres
, 0, ivideo
->sisfb_fstn
,
664 ivideo
->SiS_Pr
.SiS_CustomT
, xres
, yres
, ivideo
->vbflags2
) < 0x14) {
670 if(SiS_GetModeID_TV(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
671 sisbios_mode
[myindex
].yres
, 0, ivideo
->vbflags2
) < 0x14) {
677 if(SiS_GetModeID_VGA2(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
678 sisbios_mode
[myindex
].yres
, 0, ivideo
->vbflags2
) < 0x14) {
688 sisfb_search_refresh_rate(struct sis_video_info
*ivideo
, unsigned int rate
, int mode_idx
)
691 u16 xres
= sisbios_mode
[mode_idx
].xres
;
692 u16 yres
= sisbios_mode
[mode_idx
].yres
;
694 ivideo
->rate_idx
= 0;
695 while((sisfb_vrate
[i
].idx
!= 0) && (sisfb_vrate
[i
].xres
<= xres
)) {
696 if((sisfb_vrate
[i
].xres
== xres
) && (sisfb_vrate
[i
].yres
== yres
)) {
697 if(sisfb_vrate
[i
].refresh
== rate
) {
698 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
700 } else if(sisfb_vrate
[i
].refresh
> rate
) {
701 if((sisfb_vrate
[i
].refresh
- rate
) <= 3) {
702 DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
703 rate
, sisfb_vrate
[i
].refresh
);
704 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
705 ivideo
->refresh_rate
= sisfb_vrate
[i
].refresh
;
706 } else if((sisfb_vrate
[i
].idx
!= 1) &&
707 ((rate
- sisfb_vrate
[i
-1].refresh
) <= 2)) {
708 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
709 rate
, sisfb_vrate
[i
-1].refresh
);
710 ivideo
->rate_idx
= sisfb_vrate
[i
-1].idx
;
711 ivideo
->refresh_rate
= sisfb_vrate
[i
-1].refresh
;
714 } else if((rate
- sisfb_vrate
[i
].refresh
) <= 2) {
715 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
716 rate
, sisfb_vrate
[i
].refresh
);
717 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
723 if(ivideo
->rate_idx
> 0) {
724 return ivideo
->rate_idx
;
726 printk(KERN_INFO
"sisfb: Unsupported rate %d for %dx%d\n",
733 sisfb_bridgeisslave(struct sis_video_info
*ivideo
)
737 if(!(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
))
740 P1_00
= SiS_GetReg(SISPART1
, 0x00);
741 if( ((ivideo
->sisvga_engine
== SIS_300_VGA
) && (P1_00
& 0xa0) == 0x20) ||
742 ((ivideo
->sisvga_engine
== SIS_315_VGA
) && (P1_00
& 0x50) == 0x10) ) {
750 sisfballowretracecrt1(struct sis_video_info
*ivideo
)
754 temp
= SiS_GetReg(SISCR
, 0x17);
758 temp
= SiS_GetReg(SISSR
, 0x1f);
766 sisfbcheckvretracecrt1(struct sis_video_info
*ivideo
)
768 if(!sisfballowretracecrt1(ivideo
))
771 if (SiS_GetRegByte(SISINPSTAT
) & 0x08)
778 sisfbwaitretracecrt1(struct sis_video_info
*ivideo
)
782 if(!sisfballowretracecrt1(ivideo
))
786 while ((!(SiS_GetRegByte(SISINPSTAT
) & 0x08)) && --watchdog
);
788 while ((SiS_GetRegByte(SISINPSTAT
) & 0x08) && --watchdog
);
792 sisfbcheckvretracecrt2(struct sis_video_info
*ivideo
)
794 unsigned char temp
, reg
;
796 switch(ivideo
->sisvga_engine
) {
797 case SIS_300_VGA
: reg
= 0x25; break;
798 case SIS_315_VGA
: reg
= 0x30; break;
799 default: return false;
802 temp
= SiS_GetReg(SISPART1
, reg
);
810 sisfb_CheckVBRetrace(struct sis_video_info
*ivideo
)
812 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
813 if(!sisfb_bridgeisslave(ivideo
)) {
814 return sisfbcheckvretracecrt2(ivideo
);
817 return sisfbcheckvretracecrt1(ivideo
);
821 sisfb_setupvbblankflags(struct sis_video_info
*ivideo
, u32
*vcount
, u32
*hcount
)
823 u8 idx
, reg1
, reg2
, reg3
, reg4
;
826 (*vcount
) = (*hcount
) = 0;
828 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) && (!(sisfb_bridgeisslave(ivideo
)))) {
830 ret
|= (FB_VBLANK_HAVE_VSYNC
|
831 FB_VBLANK_HAVE_HBLANK
|
832 FB_VBLANK_HAVE_VBLANK
|
833 FB_VBLANK_HAVE_VCOUNT
|
834 FB_VBLANK_HAVE_HCOUNT
);
835 switch(ivideo
->sisvga_engine
) {
836 case SIS_300_VGA
: idx
= 0x25; break;
838 case SIS_315_VGA
: idx
= 0x30; break;
840 reg1
= SiS_GetReg(SISPART1
, (idx
+0)); /* 30 */
841 reg2
= SiS_GetReg(SISPART1
, (idx
+1)); /* 31 */
842 reg3
= SiS_GetReg(SISPART1
, (idx
+2)); /* 32 */
843 reg4
= SiS_GetReg(SISPART1
, (idx
+3)); /* 33 */
844 if(reg1
& 0x01) ret
|= FB_VBLANK_VBLANKING
;
845 if(reg1
& 0x02) ret
|= FB_VBLANK_VSYNCING
;
846 if(reg4
& 0x80) ret
|= FB_VBLANK_HBLANKING
;
847 (*vcount
) = reg3
| ((reg4
& 0x70) << 4);
848 (*hcount
) = reg2
| ((reg4
& 0x0f) << 8);
850 } else if(sisfballowretracecrt1(ivideo
)) {
852 ret
|= (FB_VBLANK_HAVE_VSYNC
|
853 FB_VBLANK_HAVE_VBLANK
|
854 FB_VBLANK_HAVE_VCOUNT
|
855 FB_VBLANK_HAVE_HCOUNT
);
856 reg1
= SiS_GetRegByte(SISINPSTAT
);
857 if(reg1
& 0x08) ret
|= FB_VBLANK_VSYNCING
;
858 if(reg1
& 0x01) ret
|= FB_VBLANK_VBLANKING
;
859 reg1
= SiS_GetReg(SISCR
, 0x20);
860 reg1
= SiS_GetReg(SISCR
, 0x1b);
861 reg2
= SiS_GetReg(SISCR
, 0x1c);
862 reg3
= SiS_GetReg(SISCR
, 0x1d);
863 (*vcount
) = reg2
| ((reg3
& 0x07) << 8);
864 (*hcount
) = (reg1
| ((reg3
& 0x10) << 4)) << 3;
871 sisfb_myblank(struct sis_video_info
*ivideo
, int blank
)
873 u8 sr01
, sr11
, sr1f
, cr63
=0, p2_0
, p1_13
;
874 bool backlight
= true;
877 case FB_BLANK_UNBLANK
: /* on */
886 case FB_BLANK_NORMAL
: /* blank */
895 case FB_BLANK_VSYNC_SUSPEND
: /* no vsync */
904 case FB_BLANK_HSYNC_SUSPEND
: /* no hsync */
913 case FB_BLANK_POWERDOWN
: /* off */
926 if(ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
) {
928 if( (!ivideo
->sisfb_thismonitor
.datavalid
) ||
929 ((ivideo
->sisfb_thismonitor
.datavalid
) &&
930 (ivideo
->sisfb_thismonitor
.feature
& 0xe0))) {
932 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
933 setSISIDXREG(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, 0xbf, cr63
);
936 if(!(sisfb_bridgeisslave(ivideo
))) {
937 setSISIDXREG(SISSR
, 0x01, ~0x20, sr01
);
938 setSISIDXREG(SISSR
, 0x1f, 0x3f, sr1f
);
944 if(ivideo
->currentvbflags
& CRT2_LCD
) {
946 if(ivideo
->vbflags2
& VB2_SISLVDSBRIDGE
) {
948 SiS_SiS30xBLOn(&ivideo
->SiS_Pr
);
950 SiS_SiS30xBLOff(&ivideo
->SiS_Pr
);
952 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
953 #ifdef CONFIG_FB_SIS_315
954 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
956 SiS_Chrontel701xBLOn(&ivideo
->SiS_Pr
);
958 SiS_Chrontel701xBLOff(&ivideo
->SiS_Pr
);
964 if(((ivideo
->sisvga_engine
== SIS_300_VGA
) &&
965 (ivideo
->vbflags2
& (VB2_301
|VB2_30xBDH
|VB2_LVDS
))) ||
966 ((ivideo
->sisvga_engine
== SIS_315_VGA
) &&
967 ((ivideo
->vbflags2
& (VB2_LVDS
| VB2_CHRONTEL
)) == VB2_LVDS
))) {
968 setSISIDXREG(SISSR
, 0x11, ~0x0c, sr11
);
971 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
972 if((ivideo
->vbflags2
& VB2_30xB
) &&
973 (!(ivideo
->vbflags2
& VB2_30xBDH
))) {
974 setSISIDXREG(SISPART1
, 0x13, 0x3f, p1_13
);
976 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
977 if((ivideo
->vbflags2
& VB2_30xB
) &&
978 (!(ivideo
->vbflags2
& VB2_30xBDH
))) {
979 setSISIDXREG(SISPART2
, 0x00, 0x1f, p2_0
);
983 } else if(ivideo
->currentvbflags
& CRT2_VGA
) {
985 if(ivideo
->vbflags2
& VB2_30xB
) {
986 setSISIDXREG(SISPART2
, 0x00, 0x1f, p2_0
);
994 /* ------------- Callbacks from init.c/init301.c -------------- */
996 #ifdef CONFIG_FB_SIS_300
998 sisfb_read_nbridge_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
)
1000 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1003 pci_read_config_dword(ivideo
->nbridge
, reg
, &val
);
1004 return (unsigned int)val
;
1008 sisfb_write_nbridge_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
, unsigned int val
)
1010 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1012 pci_write_config_dword(ivideo
->nbridge
, reg
, (u32
)val
);
1016 sisfb_read_lpc_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
)
1018 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1021 if(!ivideo
->lpcdev
) return 0;
1023 pci_read_config_dword(ivideo
->lpcdev
, reg
, &val
);
1024 return (unsigned int)val
;
1028 #ifdef CONFIG_FB_SIS_315
1030 sisfb_write_nbridge_pci_byte(struct SiS_Private
*SiS_Pr
, int reg
, unsigned char val
)
1032 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1034 pci_write_config_byte(ivideo
->nbridge
, reg
, (u8
)val
);
1038 sisfb_read_mio_pci_word(struct SiS_Private
*SiS_Pr
, int reg
)
1040 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1043 if(!ivideo
->lpcdev
) return 0;
1045 pci_read_config_word(ivideo
->lpcdev
, reg
, &val
);
1046 return (unsigned int)val
;
1050 /* ----------- FBDev related routines for all series ----------- */
1053 sisfb_get_cmap_len(const struct fb_var_screeninfo
*var
)
1055 return (var
->bits_per_pixel
== 8) ? 256 : 16;
1059 sisfb_set_vparms(struct sis_video_info
*ivideo
)
1061 switch(ivideo
->video_bpp
) {
1063 ivideo
->DstColor
= 0x0000;
1064 ivideo
->SiS310_AccelDepth
= 0x00000000;
1065 ivideo
->video_cmap_len
= 256;
1068 ivideo
->DstColor
= 0x8000;
1069 ivideo
->SiS310_AccelDepth
= 0x00010000;
1070 ivideo
->video_cmap_len
= 16;
1073 ivideo
->DstColor
= 0xC000;
1074 ivideo
->SiS310_AccelDepth
= 0x00020000;
1075 ivideo
->video_cmap_len
= 16;
1078 ivideo
->video_cmap_len
= 16;
1079 printk(KERN_ERR
"sisfb: Unsupported depth %d", ivideo
->video_bpp
);
1085 sisfb_calc_maxyres(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1087 int maxyres
= ivideo
->sisfb_mem
/ (var
->xres_virtual
* (var
->bits_per_pixel
>> 3));
1089 if(maxyres
> 32767) maxyres
= 32767;
1095 sisfb_calc_pitch(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1097 ivideo
->video_linelength
= var
->xres_virtual
* (var
->bits_per_pixel
>> 3);
1098 ivideo
->scrnpitchCRT1
= ivideo
->video_linelength
;
1099 if(!(ivideo
->currentvbflags
& CRT1_LCDA
)) {
1100 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1101 ivideo
->scrnpitchCRT1
<<= 1;
1107 sisfb_set_pitch(struct sis_video_info
*ivideo
)
1109 bool isslavemode
= false;
1110 unsigned short HDisplay1
= ivideo
->scrnpitchCRT1
>> 3;
1111 unsigned short HDisplay2
= ivideo
->video_linelength
>> 3;
1113 if(sisfb_bridgeisslave(ivideo
)) isslavemode
= true;
1115 /* We need to set pitch for CRT1 if bridge is in slave mode, too */
1116 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP1
) || (isslavemode
)) {
1117 SiS_SetReg(SISCR
, 0x13, (HDisplay1
& 0xFF));
1118 setSISIDXREG(SISSR
,0x0E,0xF0,(HDisplay1
>> 8));
1121 /* We must not set the pitch for CRT2 if bridge is in slave mode */
1122 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) && (!isslavemode
)) {
1123 SiS_SetRegOR(SISPART1
, ivideo
->CRT2_write_enable
, 0x01);
1124 SiS_SetReg(SISPART1
, 0x07, (HDisplay2
& 0xFF));
1125 setSISIDXREG(SISPART1
,0x09,0xF0,(HDisplay2
>> 8));
1130 sisfb_bpp_to_var(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1132 ivideo
->video_cmap_len
= sisfb_get_cmap_len(var
);
1134 switch(var
->bits_per_pixel
) {
1136 var
->red
.offset
= var
->green
.offset
= var
->blue
.offset
= 0;
1137 var
->red
.length
= var
->green
.length
= var
->blue
.length
= 8;
1140 var
->red
.offset
= 11;
1141 var
->red
.length
= 5;
1142 var
->green
.offset
= 5;
1143 var
->green
.length
= 6;
1144 var
->blue
.offset
= 0;
1145 var
->blue
.length
= 5;
1146 var
->transp
.offset
= 0;
1147 var
->transp
.length
= 0;
1150 var
->red
.offset
= 16;
1151 var
->red
.length
= 8;
1152 var
->green
.offset
= 8;
1153 var
->green
.length
= 8;
1154 var
->blue
.offset
= 0;
1155 var
->blue
.length
= 8;
1156 var
->transp
.offset
= 24;
1157 var
->transp
.length
= 8;
1163 sisfb_set_mode(struct sis_video_info
*ivideo
, int clrscrn
)
1165 unsigned short modeno
= ivideo
->mode_no
;
1167 /* >=2.6.12's fbcon clears the screen anyway */
1170 SiS_SetReg(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1172 sisfb_pre_setmode(ivideo
);
1174 if(!SiSSetMode(&ivideo
->SiS_Pr
, modeno
)) {
1175 printk(KERN_ERR
"sisfb: Setting mode[0x%x] failed\n", ivideo
->mode_no
);
1179 SiS_SetReg(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1181 sisfb_post_setmode(ivideo
);
1188 sisfb_do_set_var(struct fb_var_screeninfo
*var
, int isactive
, struct fb_info
*info
)
1190 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1191 unsigned int htotal
= 0, vtotal
= 0;
1192 unsigned int drate
= 0, hrate
= 0;
1193 int found_mode
= 0, ret
;
1197 htotal
= var
->left_margin
+ var
->xres
+ var
->right_margin
+ var
->hsync_len
;
1199 vtotal
= var
->upper_margin
+ var
->lower_margin
+ var
->vsync_len
;
1201 pixclock
= var
->pixclock
;
1203 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
) {
1204 vtotal
+= var
->yres
;
1206 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1207 vtotal
+= var
->yres
;
1209 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1210 vtotal
+= var
->yres
;
1212 } else vtotal
+= var
->yres
;
1214 if(!(htotal
) || !(vtotal
)) {
1215 DPRINTK("sisfb: Invalid 'var' information\n");
1219 if(pixclock
&& htotal
&& vtotal
) {
1220 drate
= 1000000000 / pixclock
;
1221 hrate
= (drate
* 1000) / htotal
;
1222 ivideo
->refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1224 ivideo
->refresh_rate
= 60;
1227 old_mode
= ivideo
->sisfb_mode_idx
;
1228 ivideo
->sisfb_mode_idx
= 0;
1230 while( (sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[0] != 0) &&
1231 (sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
<= var
->xres
) ) {
1232 if( (sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
== var
->xres
) &&
1233 (sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
== var
->yres
) &&
1234 (sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
== var
->bits_per_pixel
)) {
1235 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
1239 ivideo
->sisfb_mode_idx
++;
1243 ivideo
->sisfb_mode_idx
= sisfb_validate_mode(ivideo
,
1244 ivideo
->sisfb_mode_idx
, ivideo
->currentvbflags
);
1246 ivideo
->sisfb_mode_idx
= -1;
1249 if(ivideo
->sisfb_mode_idx
< 0) {
1250 printk(KERN_ERR
"sisfb: Mode %dx%dx%d not supported\n", var
->xres
,
1251 var
->yres
, var
->bits_per_pixel
);
1252 ivideo
->sisfb_mode_idx
= old_mode
;
1256 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
1258 if(sisfb_search_refresh_rate(ivideo
, ivideo
->refresh_rate
, ivideo
->sisfb_mode_idx
) == 0) {
1259 ivideo
->rate_idx
= sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
;
1260 ivideo
->refresh_rate
= 60;
1264 /* If acceleration to be used? Need to know
1265 * before pre/post_set_mode()
1268 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
1269 #ifdef STUPID_ACCELF_TEXT_SHIT
1270 if(var
->accel_flags
& FB_ACCELF_TEXT
) {
1271 info
->flags
&= ~FBINFO_HWACCEL_DISABLED
;
1273 info
->flags
|= FBINFO_HWACCEL_DISABLED
;
1276 if(!(info
->flags
& FBINFO_HWACCEL_DISABLED
)) ivideo
->accel
= -1;
1278 if(var
->accel_flags
& FB_ACCELF_TEXT
) ivideo
->accel
= -1;
1281 if((ret
= sisfb_set_mode(ivideo
, 1))) {
1285 ivideo
->video_bpp
= sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
;
1286 ivideo
->video_width
= sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
;
1287 ivideo
->video_height
= sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
;
1289 sisfb_calc_pitch(ivideo
, var
);
1290 sisfb_set_pitch(ivideo
);
1292 sisfb_set_vparms(ivideo
);
1294 ivideo
->current_width
= ivideo
->video_width
;
1295 ivideo
->current_height
= ivideo
->video_height
;
1296 ivideo
->current_bpp
= ivideo
->video_bpp
;
1297 ivideo
->current_htotal
= htotal
;
1298 ivideo
->current_vtotal
= vtotal
;
1299 ivideo
->current_linelength
= ivideo
->video_linelength
;
1300 ivideo
->current_pixclock
= var
->pixclock
;
1301 ivideo
->current_refresh_rate
= ivideo
->refresh_rate
;
1302 ivideo
->sisfb_lastrates
[ivideo
->mode_no
] = ivideo
->refresh_rate
;
1309 sisfb_set_base_CRT1(struct sis_video_info
*ivideo
, unsigned int base
)
1311 SiS_SetReg(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1313 SiS_SetReg(SISCR
, 0x0D, base
& 0xFF);
1314 SiS_SetReg(SISCR
, 0x0C, (base
>> 8) & 0xFF);
1315 SiS_SetReg(SISSR
, 0x0D, (base
>> 16) & 0xFF);
1316 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
1317 setSISIDXREG(SISSR
, 0x37, 0xFE, (base
>> 24) & 0x01);
1322 sisfb_set_base_CRT2(struct sis_video_info
*ivideo
, unsigned int base
)
1324 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
1325 SiS_SetRegOR(SISPART1
, ivideo
->CRT2_write_enable
, 0x01);
1326 SiS_SetReg(SISPART1
, 0x06, (base
& 0xFF));
1327 SiS_SetReg(SISPART1
, 0x05, ((base
>> 8) & 0xFF));
1328 SiS_SetReg(SISPART1
, 0x04, ((base
>> 16) & 0xFF));
1329 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
1330 setSISIDXREG(SISPART1
, 0x02, 0x7F, ((base
>> 24) & 0x01) << 7);
1336 sisfb_pan_var(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1338 if(var
->xoffset
> (var
->xres_virtual
- var
->xres
)) {
1341 if(var
->yoffset
> (var
->yres_virtual
- var
->yres
)) {
1345 ivideo
->current_base
= (var
->yoffset
* var
->xres_virtual
) + var
->xoffset
;
1347 /* calculate base bpp dep. */
1348 switch(var
->bits_per_pixel
) {
1352 ivideo
->current_base
>>= 1;
1356 ivideo
->current_base
>>= 2;
1360 ivideo
->current_base
+= (ivideo
->video_offset
>> 2);
1362 sisfb_set_base_CRT1(ivideo
, ivideo
->current_base
);
1363 sisfb_set_base_CRT2(ivideo
, ivideo
->current_base
);
1369 sisfb_open(struct fb_info
*info
, int user
)
1375 sisfb_release(struct fb_info
*info
, int user
)
1381 sisfb_setcolreg(unsigned regno
, unsigned red
, unsigned green
, unsigned blue
,
1382 unsigned transp
, struct fb_info
*info
)
1384 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1386 if(regno
>= sisfb_get_cmap_len(&info
->var
))
1389 switch(info
->var
.bits_per_pixel
) {
1391 SiS_SetRegByte(SISDACA
, regno
);
1392 SiS_SetRegByte(SISDACD
, (red
>> 10));
1393 SiS_SetRegByte(SISDACD
, (green
>> 10));
1394 SiS_SetRegByte(SISDACD
, (blue
>> 10));
1395 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
1396 SiS_SetRegByte(SISDAC2A
, regno
);
1397 SiS_SetRegByte(SISDAC2D
, (red
>> 8));
1398 SiS_SetRegByte(SISDAC2D
, (green
>> 8));
1399 SiS_SetRegByte(SISDAC2D
, (blue
>> 8));
1406 ((u32
*)(info
->pseudo_palette
))[regno
] =
1408 ((green
& 0xfc00) >> 5) |
1409 ((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 sisfb_get_fix(&info
->fix
, -1, info
);
1439 sisfb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
1441 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1442 unsigned int htotal
= 0, vtotal
= 0, myrateindex
= 0;
1443 unsigned int drate
= 0, hrate
= 0, maxyres
;
1445 int refresh_rate
, search_idx
, tidx
;
1446 bool recalc_clock
= false;
1449 htotal
= var
->left_margin
+ var
->xres
+ var
->right_margin
+ var
->hsync_len
;
1451 vtotal
= var
->upper_margin
+ var
->lower_margin
+ var
->vsync_len
;
1453 pixclock
= var
->pixclock
;
1455 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
) {
1456 vtotal
+= var
->yres
;
1458 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1459 vtotal
+= var
->yres
;
1461 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1462 vtotal
+= var
->yres
;
1465 vtotal
+= var
->yres
;
1467 if(!(htotal
) || !(vtotal
)) {
1468 SISFAIL("sisfb: no valid timing data");
1472 while( (sisbios_mode
[search_idx
].mode_no
[0] != 0) &&
1473 (sisbios_mode
[search_idx
].xres
<= var
->xres
) ) {
1474 if( (sisbios_mode
[search_idx
].xres
== var
->xres
) &&
1475 (sisbios_mode
[search_idx
].yres
== var
->yres
) &&
1476 (sisbios_mode
[search_idx
].bpp
== var
->bits_per_pixel
)) {
1477 if((tidx
= sisfb_validate_mode(ivideo
, search_idx
,
1478 ivideo
->currentvbflags
)) > 0) {
1489 while(sisbios_mode
[search_idx
].mode_no
[0] != 0) {
1490 if( (var
->xres
<= sisbios_mode
[search_idx
].xres
) &&
1491 (var
->yres
<= sisbios_mode
[search_idx
].yres
) &&
1492 (var
->bits_per_pixel
== sisbios_mode
[search_idx
].bpp
) ) {
1493 if((tidx
= sisfb_validate_mode(ivideo
,search_idx
,
1494 ivideo
->currentvbflags
)) > 0) {
1504 "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
1505 var
->xres
, var
->yres
, var
->bits_per_pixel
,
1506 sisbios_mode
[search_idx
].xres
,
1507 sisbios_mode
[search_idx
].yres
,
1508 var
->bits_per_pixel
);
1509 var
->xres
= sisbios_mode
[search_idx
].xres
;
1510 var
->yres
= sisbios_mode
[search_idx
].yres
;
1513 "sisfb: Failed to find supported mode near %dx%dx%d\n",
1514 var
->xres
, var
->yres
, var
->bits_per_pixel
);
1519 if( ((ivideo
->vbflags2
& VB2_LVDS
) ||
1520 ((ivideo
->vbflags2
& VB2_30xBDH
) && (ivideo
->currentvbflags
& CRT2_LCD
))) &&
1521 (var
->bits_per_pixel
== 8) ) {
1522 /* Slave modes on LVDS and 301B-DH */
1524 recalc_clock
= true;
1525 } else if( (ivideo
->current_htotal
== htotal
) &&
1526 (ivideo
->current_vtotal
== vtotal
) &&
1527 (ivideo
->current_pixclock
== pixclock
) ) {
1528 /* x=x & y=y & c=c -> assume depth change */
1529 drate
= 1000000000 / pixclock
;
1530 hrate
= (drate
* 1000) / htotal
;
1531 refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1532 } else if( ( (ivideo
->current_htotal
!= htotal
) ||
1533 (ivideo
->current_vtotal
!= vtotal
) ) &&
1534 (ivideo
->current_pixclock
== var
->pixclock
) ) {
1535 /* x!=x | y!=y & c=c -> invalid pixclock */
1536 if(ivideo
->sisfb_lastrates
[sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
]]) {
1538 ivideo
->sisfb_lastrates
[sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
]];
1539 } else if(ivideo
->sisfb_parm_rate
!= -1) {
1540 /* Sic, sisfb_parm_rate - want to know originally desired rate here */
1541 refresh_rate
= ivideo
->sisfb_parm_rate
;
1545 recalc_clock
= true;
1546 } else if((pixclock
) && (htotal
) && (vtotal
)) {
1547 drate
= 1000000000 / pixclock
;
1548 hrate
= (drate
* 1000) / htotal
;
1549 refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1550 } else if(ivideo
->current_refresh_rate
) {
1551 refresh_rate
= ivideo
->current_refresh_rate
;
1552 recalc_clock
= true;
1555 recalc_clock
= true;
1558 myrateindex
= sisfb_search_refresh_rate(ivideo
, refresh_rate
, search_idx
);
1560 /* Eventually recalculate timing and clock */
1562 if(!myrateindex
) myrateindex
= sisbios_mode
[search_idx
].rate_idx
;
1563 var
->pixclock
= (u32
) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo
->SiS_Pr
,
1564 sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
],
1566 sisfb_mode_rate_to_ddata(&ivideo
->SiS_Pr
,
1567 sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
],
1569 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1570 var
->pixclock
<<= 1;
1574 if(ivideo
->sisfb_thismonitor
.datavalid
) {
1575 if(!sisfb_verify_rate(ivideo
, &ivideo
->sisfb_thismonitor
, search_idx
,
1576 myrateindex
, refresh_rate
)) {
1578 "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1582 /* Adapt RGB settings */
1583 sisfb_bpp_to_var(ivideo
, var
);
1585 /* Sanity check for offsets */
1586 if(var
->xoffset
< 0) var
->xoffset
= 0;
1587 if(var
->yoffset
< 0) var
->yoffset
= 0;
1589 if(var
->xres
> var
->xres_virtual
)
1590 var
->xres_virtual
= var
->xres
;
1592 if(ivideo
->sisfb_ypan
) {
1593 maxyres
= sisfb_calc_maxyres(ivideo
, var
);
1594 if(ivideo
->sisfb_max
) {
1595 var
->yres_virtual
= maxyres
;
1597 if(var
->yres_virtual
> maxyres
) {
1598 var
->yres_virtual
= maxyres
;
1601 if(var
->yres_virtual
<= var
->yres
) {
1602 var
->yres_virtual
= var
->yres
;
1605 if(var
->yres
!= var
->yres_virtual
) {
1606 var
->yres_virtual
= var
->yres
;
1612 /* Truncate offsets to maximum if too high */
1613 if(var
->xoffset
> var
->xres_virtual
- var
->xres
) {
1614 var
->xoffset
= var
->xres_virtual
- var
->xres
- 1;
1617 if(var
->yoffset
> var
->yres_virtual
- var
->yres
) {
1618 var
->yoffset
= var
->yres_virtual
- var
->yres
- 1;
1621 /* Set everything else to 0 */
1622 var
->red
.msb_right
=
1623 var
->green
.msb_right
=
1624 var
->blue
.msb_right
=
1625 var
->transp
.offset
=
1626 var
->transp
.length
=
1627 var
->transp
.msb_right
= 0;
1633 sisfb_pan_display(struct fb_var_screeninfo
*var
, struct fb_info
* info
)
1635 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1638 if(var
->xoffset
> (var
->xres_virtual
- var
->xres
))
1641 if(var
->yoffset
> (var
->yres_virtual
- var
->yres
))
1644 if(var
->vmode
& FB_VMODE_YWRAP
)
1647 if(var
->xoffset
+ info
->var
.xres
> info
->var
.xres_virtual
||
1648 var
->yoffset
+ info
->var
.yres
> info
->var
.yres_virtual
)
1651 if((err
= sisfb_pan_var(ivideo
, var
)) < 0)
1654 info
->var
.xoffset
= var
->xoffset
;
1655 info
->var
.yoffset
= var
->yoffset
;
1661 sisfb_blank(int blank
, struct fb_info
*info
)
1663 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1665 return sisfb_myblank(ivideo
, blank
);
1668 /* ----------- FBDev related routines for all series ---------- */
1670 static int sisfb_ioctl(struct fb_info
*info
, unsigned int cmd
,
1673 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1674 struct sis_memreq sismemreq
;
1675 struct fb_vblank sisvbblank
;
1680 u32 __user
*argp
= (u32 __user
*)arg
;
1684 if(!capable(CAP_SYS_RAWIO
))
1687 if(copy_from_user(&sismemreq
, (void __user
*)arg
, sizeof(sismemreq
)))
1690 sis_malloc(&sismemreq
);
1692 if(copy_to_user((void __user
*)arg
, &sismemreq
, sizeof(sismemreq
))) {
1693 sis_free((u32
)sismemreq
.offset
);
1699 if(!capable(CAP_SYS_RAWIO
))
1702 if(get_user(gpu32
, argp
))
1708 case FBIOGET_VBLANK
:
1710 memset(&sisvbblank
, 0, sizeof(struct fb_vblank
));
1712 sisvbblank
.count
= 0;
1713 sisvbblank
.flags
= sisfb_setupvbblankflags(ivideo
, &sisvbblank
.vcount
, &sisvbblank
.hcount
);
1715 if(copy_to_user((void __user
*)arg
, &sisvbblank
, sizeof(sisvbblank
)))
1720 case SISFB_GET_INFO_SIZE
:
1721 return put_user(sizeof(struct sisfb_info
), argp
);
1723 case SISFB_GET_INFO_OLD
:
1724 if(ivideo
->warncount
++ < 10)
1726 "sisfb: Deprecated ioctl call received - update your application!\n");
1727 case SISFB_GET_INFO
: /* For communication with X driver */
1728 ivideo
->sisfb_infoblock
.sisfb_id
= SISFB_ID
;
1729 ivideo
->sisfb_infoblock
.sisfb_version
= VER_MAJOR
;
1730 ivideo
->sisfb_infoblock
.sisfb_revision
= VER_MINOR
;
1731 ivideo
->sisfb_infoblock
.sisfb_patchlevel
= VER_LEVEL
;
1732 ivideo
->sisfb_infoblock
.chip_id
= ivideo
->chip_id
;
1733 ivideo
->sisfb_infoblock
.sisfb_pci_vendor
= ivideo
->chip_vendor
;
1734 ivideo
->sisfb_infoblock
.memory
= ivideo
->video_size
/ 1024;
1735 ivideo
->sisfb_infoblock
.heapstart
= ivideo
->heapstart
/ 1024;
1736 if(ivideo
->modechanged
) {
1737 ivideo
->sisfb_infoblock
.fbvidmode
= ivideo
->mode_no
;
1739 ivideo
->sisfb_infoblock
.fbvidmode
= ivideo
->modeprechange
;
1741 ivideo
->sisfb_infoblock
.sisfb_caps
= ivideo
->caps
;
1742 ivideo
->sisfb_infoblock
.sisfb_tqlen
= ivideo
->cmdQueueSize
/ 1024;
1743 ivideo
->sisfb_infoblock
.sisfb_pcibus
= ivideo
->pcibus
;
1744 ivideo
->sisfb_infoblock
.sisfb_pcislot
= ivideo
->pcislot
;
1745 ivideo
->sisfb_infoblock
.sisfb_pcifunc
= ivideo
->pcifunc
;
1746 ivideo
->sisfb_infoblock
.sisfb_lcdpdc
= ivideo
->detectedpdc
;
1747 ivideo
->sisfb_infoblock
.sisfb_lcdpdca
= ivideo
->detectedpdca
;
1748 ivideo
->sisfb_infoblock
.sisfb_lcda
= ivideo
->detectedlcda
;
1749 ivideo
->sisfb_infoblock
.sisfb_vbflags
= ivideo
->vbflags
;
1750 ivideo
->sisfb_infoblock
.sisfb_currentvbflags
= ivideo
->currentvbflags
;
1751 ivideo
->sisfb_infoblock
.sisfb_scalelcd
= ivideo
->SiS_Pr
.UsePanelScaler
;
1752 ivideo
->sisfb_infoblock
.sisfb_specialtiming
= ivideo
->SiS_Pr
.SiS_CustomT
;
1753 ivideo
->sisfb_infoblock
.sisfb_haveemi
= ivideo
->SiS_Pr
.HaveEMI
? 1 : 0;
1754 ivideo
->sisfb_infoblock
.sisfb_haveemilcd
= ivideo
->SiS_Pr
.HaveEMILCD
? 1 : 0;
1755 ivideo
->sisfb_infoblock
.sisfb_emi30
= ivideo
->SiS_Pr
.EMI_30
;
1756 ivideo
->sisfb_infoblock
.sisfb_emi31
= ivideo
->SiS_Pr
.EMI_31
;
1757 ivideo
->sisfb_infoblock
.sisfb_emi32
= ivideo
->SiS_Pr
.EMI_32
;
1758 ivideo
->sisfb_infoblock
.sisfb_emi33
= ivideo
->SiS_Pr
.EMI_33
;
1759 ivideo
->sisfb_infoblock
.sisfb_tvxpos
= (u16
)(ivideo
->tvxpos
+ 32);
1760 ivideo
->sisfb_infoblock
.sisfb_tvypos
= (u16
)(ivideo
->tvypos
+ 32);
1761 ivideo
->sisfb_infoblock
.sisfb_heapsize
= ivideo
->sisfb_heap_size
/ 1024;
1762 ivideo
->sisfb_infoblock
.sisfb_videooffset
= ivideo
->video_offset
;
1763 ivideo
->sisfb_infoblock
.sisfb_curfstn
= ivideo
->curFSTN
;
1764 ivideo
->sisfb_infoblock
.sisfb_curdstn
= ivideo
->curDSTN
;
1765 ivideo
->sisfb_infoblock
.sisfb_vbflags2
= ivideo
->vbflags2
;
1766 ivideo
->sisfb_infoblock
.sisfb_can_post
= ivideo
->sisfb_can_post
? 1 : 0;
1767 ivideo
->sisfb_infoblock
.sisfb_card_posted
= ivideo
->sisfb_card_posted
? 1 : 0;
1768 ivideo
->sisfb_infoblock
.sisfb_was_boot_device
= ivideo
->sisfb_was_boot_device
? 1 : 0;
1770 if(copy_to_user((void __user
*)arg
, &ivideo
->sisfb_infoblock
,
1771 sizeof(ivideo
->sisfb_infoblock
)))
1776 case SISFB_GET_VBRSTATUS_OLD
:
1777 if(ivideo
->warncount
++ < 10)
1779 "sisfb: Deprecated ioctl call received - update your application!\n");
1780 case SISFB_GET_VBRSTATUS
:
1781 if(sisfb_CheckVBRetrace(ivideo
))
1782 return put_user((u32
)1, argp
);
1784 return put_user((u32
)0, argp
);
1786 case SISFB_GET_AUTOMAXIMIZE_OLD
:
1787 if(ivideo
->warncount
++ < 10)
1789 "sisfb: Deprecated ioctl call received - update your application!\n");
1790 case SISFB_GET_AUTOMAXIMIZE
:
1791 if(ivideo
->sisfb_max
)
1792 return put_user((u32
)1, argp
);
1794 return put_user((u32
)0, argp
);
1796 case SISFB_SET_AUTOMAXIMIZE_OLD
:
1797 if(ivideo
->warncount
++ < 10)
1799 "sisfb: Deprecated ioctl call received - update your application!\n");
1800 case SISFB_SET_AUTOMAXIMIZE
:
1801 if(get_user(gpu32
, argp
))
1804 ivideo
->sisfb_max
= (gpu32
) ? 1 : 0;
1807 case SISFB_SET_TVPOSOFFSET
:
1808 if(get_user(gpu32
, argp
))
1811 sisfb_set_TVxposoffset(ivideo
, ((int)(gpu32
>> 16)) - 32);
1812 sisfb_set_TVyposoffset(ivideo
, ((int)(gpu32
& 0xffff)) - 32);
1815 case SISFB_GET_TVPOSOFFSET
:
1816 return put_user((u32
)(((ivideo
->tvxpos
+32)<<16)|((ivideo
->tvypos
+32)&0xffff)),
1820 if(copy_from_user(&ivideo
->sisfb_command
, (void __user
*)arg
,
1821 sizeof(struct sisfb_cmd
)))
1824 sisfb_handle_command(ivideo
, &ivideo
->sisfb_command
);
1826 if(copy_to_user((void __user
*)arg
, &ivideo
->sisfb_command
,
1827 sizeof(struct sisfb_cmd
)))
1832 case SISFB_SET_LOCK
:
1833 if(get_user(gpu32
, argp
))
1836 ivideo
->sisfblocked
= (gpu32
) ? 1 : 0;
1840 #ifdef SIS_NEW_CONFIG_COMPAT
1841 return -ENOIOCTLCMD
;
1850 sisfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
, struct fb_info
*info
)
1852 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1854 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
1856 strlcpy(fix
->id
, ivideo
->myid
, sizeof(fix
->id
));
1858 mutex_lock(&info
->mm_lock
);
1859 fix
->smem_start
= ivideo
->video_base
+ ivideo
->video_offset
;
1860 fix
->smem_len
= ivideo
->sisfb_mem
;
1861 mutex_unlock(&info
->mm_lock
);
1862 fix
->type
= FB_TYPE_PACKED_PIXELS
;
1864 fix
->visual
= (ivideo
->video_bpp
== 8) ? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_TRUECOLOR
;
1866 fix
->ypanstep
= (ivideo
->sisfb_ypan
) ? 1 : 0;
1868 fix
->line_length
= ivideo
->video_linelength
;
1869 fix
->mmio_start
= ivideo
->mmio_base
;
1870 fix
->mmio_len
= ivideo
->mmio_size
;
1871 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
1872 fix
->accel
= FB_ACCEL_SIS_GLAMOUR
;
1873 } else if((ivideo
->chip
== SIS_330
) ||
1874 (ivideo
->chip
== SIS_760
) ||
1875 (ivideo
->chip
== SIS_761
)) {
1876 fix
->accel
= FB_ACCEL_SIS_XABRE
;
1877 } else if(ivideo
->chip
== XGI_20
) {
1878 fix
->accel
= FB_ACCEL_XGI_VOLARI_Z
;
1879 } else if(ivideo
->chip
>= XGI_40
) {
1880 fix
->accel
= FB_ACCEL_XGI_VOLARI_V
;
1882 fix
->accel
= FB_ACCEL_SIS_GLAMOUR_2
;
1888 /* ---------------- fb_ops structures ----------------- */
1890 static struct fb_ops sisfb_ops
= {
1891 .owner
= THIS_MODULE
,
1892 .fb_open
= sisfb_open
,
1893 .fb_release
= sisfb_release
,
1894 .fb_check_var
= sisfb_check_var
,
1895 .fb_set_par
= sisfb_set_par
,
1896 .fb_setcolreg
= sisfb_setcolreg
,
1897 .fb_pan_display
= sisfb_pan_display
,
1898 .fb_blank
= sisfb_blank
,
1899 .fb_fillrect
= fbcon_sis_fillrect
,
1900 .fb_copyarea
= fbcon_sis_copyarea
,
1901 .fb_imageblit
= cfb_imageblit
,
1902 .fb_sync
= fbcon_sis_sync
,
1903 #ifdef SIS_NEW_CONFIG_COMPAT
1904 .fb_compat_ioctl
= sisfb_ioctl
,
1906 .fb_ioctl
= sisfb_ioctl
1909 /* ---------------- Chip generation dependent routines ---------------- */
1911 static struct pci_dev
* __devinit
1912 sisfb_get_northbridge(int basechipid
)
1914 struct pci_dev
*pdev
= NULL
;
1915 int nbridgenum
, nbridgeidx
, i
;
1916 static const unsigned short nbridgeids
[] = {
1917 PCI_DEVICE_ID_SI_540
, /* for SiS 540 VGA */
1918 PCI_DEVICE_ID_SI_630
, /* for SiS 630/730 VGA */
1919 PCI_DEVICE_ID_SI_730
,
1920 PCI_DEVICE_ID_SI_550
, /* for SiS 550 VGA */
1921 PCI_DEVICE_ID_SI_650
, /* for SiS 650/651/740 VGA */
1922 PCI_DEVICE_ID_SI_651
,
1923 PCI_DEVICE_ID_SI_740
,
1924 PCI_DEVICE_ID_SI_661
, /* for SiS 661/741/660/760/761 VGA */
1925 PCI_DEVICE_ID_SI_741
,
1926 PCI_DEVICE_ID_SI_660
,
1927 PCI_DEVICE_ID_SI_760
,
1928 PCI_DEVICE_ID_SI_761
1931 switch(basechipid
) {
1932 #ifdef CONFIG_FB_SIS_300
1933 case SIS_540
: nbridgeidx
= 0; nbridgenum
= 1; break;
1934 case SIS_630
: nbridgeidx
= 1; nbridgenum
= 2; break;
1936 #ifdef CONFIG_FB_SIS_315
1937 case SIS_550
: nbridgeidx
= 3; nbridgenum
= 1; break;
1938 case SIS_650
: nbridgeidx
= 4; nbridgenum
= 3; break;
1939 case SIS_660
: nbridgeidx
= 7; nbridgenum
= 5; break;
1941 default: return NULL
;
1943 for(i
= 0; i
< nbridgenum
; i
++) {
1944 if((pdev
= pci_get_device(PCI_VENDOR_ID_SI
,
1945 nbridgeids
[nbridgeidx
+i
], NULL
)))
1951 static int __devinit
1952 sisfb_get_dram_size(struct sis_video_info
*ivideo
)
1954 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1958 ivideo
->video_size
= 0;
1959 ivideo
->UMAsize
= ivideo
->LFBsize
= 0;
1961 switch(ivideo
->chip
) {
1962 #ifdef CONFIG_FB_SIS_300
1964 reg
= SiS_GetReg(SISSR
, 0x14);
1965 ivideo
->video_size
= ((reg
& 0x3F) + 1) << 20;
1970 if(!ivideo
->nbridge
)
1972 pci_read_config_byte(ivideo
->nbridge
, 0x63, ®
);
1973 ivideo
->video_size
= 1 << (((reg
& 0x70) >> 4) + 21);
1976 #ifdef CONFIG_FB_SIS_315
1980 reg
= SiS_GetReg(SISSR
, 0x14);
1981 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
1982 switch((reg
>> 2) & 0x03) {
1985 ivideo
->video_size
<<= 1;
1988 ivideo
->video_size
+= (ivideo
->video_size
/2);
1992 reg
= SiS_GetReg(SISSR
, 0x14);
1993 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
1994 if(reg
& 0x0c) ivideo
->video_size
<<= 1;
1999 reg
= SiS_GetReg(SISSR
, 0x14);
2000 ivideo
->video_size
= (((reg
& 0x3f) + 1) << 2) << 20;
2004 reg
= SiS_GetReg(SISCR
, 0x79);
2005 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
2010 reg
= SiS_GetReg(SISCR
, 0x79);
2011 reg
= (reg
& 0xf0) >> 4;
2013 ivideo
->video_size
= (1 << reg
) << 20;
2014 ivideo
->UMAsize
= ivideo
->video_size
;
2016 reg
= SiS_GetReg(SISCR
, 0x78);
2020 ivideo
->LFBsize
= (32 << 20);
2022 ivideo
->LFBsize
= (64 << 20);
2024 ivideo
->video_size
+= ivideo
->LFBsize
;
2030 reg
= SiS_GetReg(SISSR
, 0x14);
2031 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
2032 if(ivideo
->chip
!= XGI_20
) {
2033 reg
= (reg
& 0x0c) >> 2;
2034 if(ivideo
->revision_id
== 2) {
2035 if(reg
& 0x01) reg
= 0x02;
2038 if(reg
== 0x02) ivideo
->video_size
<<= 1;
2039 else if(reg
== 0x03) ivideo
->video_size
<<= 2;
2049 /* -------------- video bridge device detection --------------- */
2051 static void __devinit
2052 sisfb_detect_VB_connect(struct sis_video_info
*ivideo
)
2056 /* No CRT2 on XGI Z7 */
2057 if(ivideo
->chip
== XGI_20
) {
2058 ivideo
->sisfb_crt1off
= 0;
2062 #ifdef CONFIG_FB_SIS_300
2063 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2064 temp
= SiS_GetReg(SISSR
, 0x17);
2065 if((temp
& 0x0F) && (ivideo
->chip
!= SIS_300
)) {
2066 /* PAL/NTSC is stored on SR16 on such machines */
2067 if(!(ivideo
->vbflags
& (TV_PAL
| TV_NTSC
| TV_PALM
| TV_PALN
))) {
2068 temp
= SiS_GetReg(SISSR
, 0x16);
2070 ivideo
->vbflags
|= TV_PAL
;
2072 ivideo
->vbflags
|= TV_NTSC
;
2078 cr32
= SiS_GetReg(SISCR
, 0x32);
2080 if(cr32
& SIS_CRT1
) {
2081 ivideo
->sisfb_crt1off
= 0;
2083 ivideo
->sisfb_crt1off
= (cr32
& 0xDF) ? 1 : 0;
2086 ivideo
->vbflags
&= ~(CRT2_TV
| CRT2_LCD
| CRT2_VGA
);
2088 if(cr32
& SIS_VB_TV
) ivideo
->vbflags
|= CRT2_TV
;
2089 if(cr32
& SIS_VB_LCD
) ivideo
->vbflags
|= CRT2_LCD
;
2090 if(cr32
& SIS_VB_CRT2
) ivideo
->vbflags
|= CRT2_VGA
;
2092 /* Check given parms for hardware compatibility.
2093 * (Cannot do this in the search_xx routines since we don't
2094 * know what hardware we are running on then)
2097 if(ivideo
->chip
!= SIS_550
) {
2098 ivideo
->sisfb_dstn
= ivideo
->sisfb_fstn
= 0;
2101 if(ivideo
->sisfb_tvplug
!= -1) {
2102 if( (ivideo
->sisvga_engine
!= SIS_315_VGA
) ||
2103 (!(ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) ) {
2104 if(ivideo
->sisfb_tvplug
& TV_YPBPR
) {
2105 ivideo
->sisfb_tvplug
= -1;
2106 printk(KERN_ERR
"sisfb: YPbPr not supported\n");
2110 if(ivideo
->sisfb_tvplug
!= -1) {
2111 if( (ivideo
->sisvga_engine
!= SIS_315_VGA
) ||
2112 (!(ivideo
->vbflags2
& VB2_SISHIVISIONBRIDGE
)) ) {
2113 if(ivideo
->sisfb_tvplug
& TV_HIVISION
) {
2114 ivideo
->sisfb_tvplug
= -1;
2115 printk(KERN_ERR
"sisfb: HiVision not supported\n");
2119 if(ivideo
->sisfb_tvstd
!= -1) {
2120 if( (!(ivideo
->vbflags2
& VB2_SISBRIDGE
)) &&
2121 (!((ivideo
->sisvga_engine
== SIS_315_VGA
) &&
2122 (ivideo
->vbflags2
& VB2_CHRONTEL
))) ) {
2123 if(ivideo
->sisfb_tvstd
& (TV_PALM
| TV_PALN
| TV_NTSCJ
)) {
2124 ivideo
->sisfb_tvstd
= -1;
2125 printk(KERN_ERR
"sisfb: PALM/PALN/NTSCJ not supported\n");
2130 /* Detect/set TV plug & type */
2131 if(ivideo
->sisfb_tvplug
!= -1) {
2132 ivideo
->vbflags
|= ivideo
->sisfb_tvplug
;
2134 if(cr32
& SIS_VB_YPBPR
) ivideo
->vbflags
|= (TV_YPBPR
|TV_YPBPR525I
); /* default: 480i */
2135 else if(cr32
& SIS_VB_HIVISION
) ivideo
->vbflags
|= TV_HIVISION
;
2136 else if(cr32
& SIS_VB_SCART
) ivideo
->vbflags
|= TV_SCART
;
2138 if(cr32
& SIS_VB_SVIDEO
) ivideo
->vbflags
|= TV_SVIDEO
;
2139 if(cr32
& SIS_VB_COMPOSITE
) ivideo
->vbflags
|= TV_AVIDEO
;
2143 if(!(ivideo
->vbflags
& (TV_YPBPR
| TV_HIVISION
))) {
2144 if(ivideo
->sisfb_tvstd
!= -1) {
2145 ivideo
->vbflags
&= ~(TV_NTSC
| TV_PAL
| TV_PALM
| TV_PALN
| TV_NTSCJ
);
2146 ivideo
->vbflags
|= ivideo
->sisfb_tvstd
;
2148 if(ivideo
->vbflags
& TV_SCART
) {
2149 ivideo
->vbflags
&= ~(TV_NTSC
| TV_PALM
| TV_PALN
| TV_NTSCJ
);
2150 ivideo
->vbflags
|= TV_PAL
;
2152 if(!(ivideo
->vbflags
& (TV_PAL
| TV_NTSC
| TV_PALM
| TV_PALN
| TV_NTSCJ
))) {
2153 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2154 temp
= SiS_GetReg(SISSR
, 0x38);
2155 if(temp
& 0x01) ivideo
->vbflags
|= TV_PAL
;
2156 else ivideo
->vbflags
|= TV_NTSC
;
2157 } else if((ivideo
->chip
<= SIS_315PRO
) || (ivideo
->chip
>= SIS_330
)) {
2158 temp
= SiS_GetReg(SISSR
, 0x38);
2159 if(temp
& 0x01) ivideo
->vbflags
|= TV_PAL
;
2160 else ivideo
->vbflags
|= TV_NTSC
;
2162 temp
= SiS_GetReg(SISCR
, 0x79);
2163 if(temp
& 0x20) ivideo
->vbflags
|= TV_PAL
;
2164 else ivideo
->vbflags
|= TV_NTSC
;
2169 /* Copy forceCRT1 option to CRT1off if option is given */
2170 if(ivideo
->sisfb_forcecrt1
!= -1) {
2171 ivideo
->sisfb_crt1off
= (ivideo
->sisfb_forcecrt1
) ? 0 : 1;
2175 /* ------------------ Sensing routines ------------------ */
2177 static bool __devinit
2178 sisfb_test_DDC1(struct sis_video_info
*ivideo
)
2183 old
= SiS_ReadDDC1Bit(&ivideo
->SiS_Pr
);
2185 if(old
!= SiS_ReadDDC1Bit(&ivideo
->SiS_Pr
)) break;
2187 return (count
!= -1);
2190 static void __devinit
2191 sisfb_sense_crt1(struct sis_video_info
*ivideo
)
2193 bool mustwait
= false;
2195 #ifdef CONFIG_FB_SIS_315
2201 sr1F
= SiS_GetReg(SISSR
, 0x1F);
2202 SiS_SetRegOR(SISSR
, 0x1F, 0x04);
2203 andSISIDXREG(SISSR
,0x1F,0x3F);
2204 if(sr1F
& 0xc0) mustwait
= true;
2206 #ifdef CONFIG_FB_SIS_315
2207 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2208 cr63
= SiS_GetReg(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
);
2210 andSISIDXREG(SISCR
,ivideo
->SiS_Pr
.SiS_MyCR63
,0xBF);
2214 cr17
= SiS_GetReg(SISCR
, 0x17);
2217 SiS_SetRegOR(SISCR
, 0x17, 0x80);
2219 SiS_SetReg(SISSR
, 0x00, 0x01);
2220 SiS_SetReg(SISSR
, 0x00, 0x03);
2224 for(i
=0; i
< 10; i
++) sisfbwaitretracecrt1(ivideo
);
2227 #ifdef CONFIG_FB_SIS_315
2228 if(ivideo
->chip
>= SIS_330
) {
2229 andSISIDXREG(SISCR
,0x32,~0x20);
2230 if(ivideo
->chip
>= SIS_340
) {
2231 SiS_SetReg(SISCR
, 0x57, 0x4a);
2233 SiS_SetReg(SISCR
, 0x57, 0x5f);
2235 SiS_SetRegOR(SISCR
, 0x53, 0x02);
2236 while ((SiS_GetRegByte(SISINPSTAT
)) & 0x01) break;
2237 while (!((SiS_GetRegByte(SISINPSTAT
)) & 0x01)) break;
2238 if ((SiS_GetRegByte(SISMISCW
)) & 0x10) temp
= 1;
2239 andSISIDXREG(SISCR
, 0x53, 0xfd);
2240 andSISIDXREG(SISCR
, 0x57, 0x00);
2244 if(temp
== 0xffff) {
2247 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
,
2248 ivideo
->sisvga_engine
, 0, 0, NULL
, ivideo
->vbflags2
);
2249 } while(((temp
== 0) || (temp
== 0xffff)) && i
--);
2251 if((temp
== 0) || (temp
== 0xffff)) {
2252 if(sisfb_test_DDC1(ivideo
)) temp
= 1;
2256 if((temp
) && (temp
!= 0xffff)) {
2257 SiS_SetRegOR(SISCR
, 0x32, 0x20);
2260 #ifdef CONFIG_FB_SIS_315
2261 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2262 setSISIDXREG(SISCR
,ivideo
->SiS_Pr
.SiS_MyCR63
,0xBF,cr63
);
2266 setSISIDXREG(SISCR
,0x17,0x7F,cr17
);
2268 SiS_SetReg(SISSR
, 0x1F, sr1F
);
2271 /* Determine and detect attached devices on SiS30x */
2272 static void __devinit
2273 SiS_SenseLCD(struct sis_video_info
*ivideo
)
2275 unsigned char buffer
[256];
2276 unsigned short temp
, realcrtno
, i
;
2277 u8 reg
, cr37
= 0, paneltype
= 0;
2280 ivideo
->SiS_Pr
.PanelSelfDetected
= false;
2282 /* LCD detection only for TMDS bridges */
2283 if(!(ivideo
->vbflags2
& VB2_SISTMDSBRIDGE
))
2285 if(ivideo
->vbflags2
& VB2_30xBDH
)
2288 /* If LCD already set up by BIOS, skip it */
2289 reg
= SiS_GetReg(SISCR
, 0x32);
2294 if(ivideo
->SiS_Pr
.DDCPortMixup
)
2297 /* Check DDC capabilities */
2298 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
2299 realcrtno
, 0, &buffer
[0], ivideo
->vbflags2
);
2301 if((!temp
) || (temp
== 0xffff) || (!(temp
& 0x02)))
2305 i
= 3; /* Number of retrys */
2307 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
,
2308 ivideo
->sisvga_engine
, realcrtno
, 1,
2309 &buffer
[0], ivideo
->vbflags2
);
2310 } while((temp
) && i
--);
2315 /* No digital device */
2316 if(!(buffer
[0x14] & 0x80))
2319 /* First detailed timing preferred timing? */
2320 if(!(buffer
[0x18] & 0x02))
2323 xres
= buffer
[0x38] | ((buffer
[0x3a] & 0xf0) << 4);
2324 yres
= buffer
[0x3b] | ((buffer
[0x3d] & 0xf0) << 4);
2336 if((yres
== 1200) && (ivideo
->vbflags2
& VB2_30xC
))
2347 if((buffer
[0x47] & 0x18) == 0x18)
2348 cr37
|= ((((buffer
[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2352 SiS_SetReg(SISCR
, 0x36, paneltype
);
2354 setSISIDXREG(SISCR
, 0x37, 0x0c, cr37
);
2355 SiS_SetRegOR(SISCR
, 0x32, 0x08);
2357 ivideo
->SiS_Pr
.PanelSelfDetected
= true;
2360 static int __devinit
2361 SISDoSense(struct sis_video_info
*ivideo
, u16 type
, u16 test
)
2363 int temp
, mytest
, result
, i
, j
;
2365 for(j
= 0; j
< 10; j
++) {
2367 for(i
= 0; i
< 3; i
++) {
2369 SiS_SetReg(SISPART4
, 0x11, (type
& 0x00ff));
2370 temp
= (type
>> 8) | (mytest
& 0x00ff);
2371 setSISIDXREG(SISPART4
,0x10,0xe0,temp
);
2372 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x1500);
2375 temp
= SiS_GetReg(SISPART4
, 0x03);
2378 if(temp
== mytest
) result
++;
2380 SiS_SetReg(SISPART4
, 0x11, 0x00);
2381 andSISIDXREG(SISPART4
,0x10,0xe0);
2382 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x1000);
2385 if((result
== 0) || (result
>= 2)) break;
2390 static void __devinit
2391 SiS_Sense30x(struct sis_video_info
*ivideo
)
2393 u8 backupP4_0d
,backupP2_00
,backupP2_4d
,backupSR_1e
,biosflag
=0;
2394 u16 svhs
=0, svhs_c
=0;
2395 u16 cvbs
=0, cvbs_c
=0;
2396 u16 vga2
=0, vga2_c
=0;
2398 char stdstr
[] = "sisfb: Detected";
2399 char tvstr
[] = "TV connected to";
2401 if(ivideo
->vbflags2
& VB2_301
) {
2402 svhs
= 0x00b9; cvbs
= 0x00b3; vga2
= 0x00d1;
2403 myflag
= SiS_GetReg(SISPART4
, 0x01);
2405 svhs
= 0x00dd; cvbs
= 0x00ee; vga2
= 0x00fd;
2407 } else if(ivideo
->vbflags2
& (VB2_301B
| VB2_302B
)) {
2408 svhs
= 0x016b; cvbs
= 0x0174; vga2
= 0x0190;
2409 } else if(ivideo
->vbflags2
& (VB2_301LV
| VB2_302LV
)) {
2410 svhs
= 0x0200; cvbs
= 0x0100;
2411 } else if(ivideo
->vbflags2
& (VB2_301C
| VB2_302ELV
| VB2_307T
| VB2_307LV
)) {
2412 svhs
= 0x016b; cvbs
= 0x0110; vga2
= 0x0190;
2416 vga2_c
= 0x0e08; svhs_c
= 0x0404; cvbs_c
= 0x0804;
2417 if(ivideo
->vbflags
& (VB2_301LV
|VB2_302LV
|VB2_302ELV
|VB2_307LV
)) {
2418 svhs_c
= 0x0408; cvbs_c
= 0x0808;
2422 if(ivideo
->haveXGIROM
) {
2423 biosflag
= ivideo
->bios_abase
[0x58] & 0x03;
2424 } else if(ivideo
->newrom
) {
2425 if(ivideo
->bios_abase
[0x5d] & 0x04) biosflag
|= 0x01;
2426 } else if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2427 if(ivideo
->bios_abase
) {
2428 biosflag
= ivideo
->bios_abase
[0xfe] & 0x03;
2432 if(ivideo
->chip
== SIS_300
) {
2433 myflag
= SiS_GetReg(SISSR
, 0x3b);
2434 if(!(myflag
& 0x01)) vga2
= vga2_c
= 0;
2437 if(!(ivideo
->vbflags2
& VB2_SISVGA2BRIDGE
)) {
2441 backupSR_1e
= SiS_GetReg(SISSR
, 0x1e);
2442 SiS_SetRegOR(SISSR
, 0x1e, 0x20);
2444 backupP4_0d
= SiS_GetReg(SISPART4
, 0x0d);
2445 if(ivideo
->vbflags2
& VB2_30xC
) {
2446 setSISIDXREG(SISPART4
,0x0d,~0x07,0x01);
2448 SiS_SetRegOR(SISPART4
, 0x0d, 0x04);
2450 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x2000);
2452 backupP2_00
= SiS_GetReg(SISPART2
, 0x00);
2453 SiS_SetReg(SISPART2
, 0x00, ((backupP2_00
| 0x1c) & 0xfc));
2455 backupP2_4d
= SiS_GetReg(SISPART2
, 0x4d);
2456 if(ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
) {
2457 SiS_SetReg(SISPART2
, 0x4d, (backupP2_4d
& ~0x10));
2460 if(!(ivideo
->vbflags2
& VB2_30xCLV
)) {
2461 SISDoSense(ivideo
, 0, 0);
2464 andSISIDXREG(SISCR
, 0x32, ~0x14);
2466 if(vga2_c
|| vga2
) {
2467 if(SISDoSense(ivideo
, vga2
, vga2_c
)) {
2468 if(biosflag
& 0x01) {
2469 printk(KERN_INFO
"%s %s SCART output\n", stdstr
, tvstr
);
2470 SiS_SetRegOR(SISCR
, 0x32, 0x04);
2472 printk(KERN_INFO
"%s secondary VGA connection\n", stdstr
);
2473 SiS_SetRegOR(SISCR
, 0x32, 0x10);
2478 andSISIDXREG(SISCR
, 0x32, 0x3f);
2480 if(ivideo
->vbflags2
& VB2_30xCLV
) {
2481 SiS_SetRegOR(SISPART4
, 0x0d, 0x04);
2484 if((ivideo
->sisvga_engine
== SIS_315_VGA
) && (ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) {
2485 SiS_SetReg(SISPART2
, 0x4d, (backupP2_4d
| 0x10));
2486 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x2000);
2487 if((result
= SISDoSense(ivideo
, svhs
, 0x0604))) {
2488 if((result
= SISDoSense(ivideo
, cvbs
, 0x0804))) {
2489 printk(KERN_INFO
"%s %s YPbPr component output\n", stdstr
, tvstr
);
2490 SiS_SetRegOR(SISCR
, 0x32, 0x80);
2493 SiS_SetReg(SISPART2
, 0x4d, backupP2_4d
);
2496 andSISIDXREG(SISCR
, 0x32, ~0x03);
2498 if(!(ivideo
->vbflags
& TV_YPBPR
)) {
2499 if((result
= SISDoSense(ivideo
, svhs
, svhs_c
))) {
2500 printk(KERN_INFO
"%s %s SVIDEO output\n", stdstr
, tvstr
);
2501 SiS_SetRegOR(SISCR
, 0x32, 0x02);
2503 if((biosflag
& 0x02) || (!result
)) {
2504 if(SISDoSense(ivideo
, cvbs
, cvbs_c
)) {
2505 printk(KERN_INFO
"%s %s COMPOSITE output\n", stdstr
, tvstr
);
2506 SiS_SetRegOR(SISCR
, 0x32, 0x01);
2511 SISDoSense(ivideo
, 0, 0);
2513 SiS_SetReg(SISPART2
, 0x00, backupP2_00
);
2514 SiS_SetReg(SISPART4
, 0x0d, backupP4_0d
);
2515 SiS_SetReg(SISSR
, 0x1e, backupSR_1e
);
2517 if(ivideo
->vbflags2
& VB2_30xCLV
) {
2518 biosflag
= SiS_GetReg(SISPART2
, 0x00);
2519 if(biosflag
& 0x20) {
2520 for(myflag
= 2; myflag
> 0; myflag
--) {
2522 SiS_SetReg(SISPART2
, 0x00, biosflag
);
2527 SiS_SetReg(SISPART2
, 0x00, backupP2_00
);
2530 /* Determine and detect attached TV's on Chrontel */
2531 static void __devinit
2532 SiS_SenseCh(struct sis_video_info
*ivideo
)
2534 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2536 char stdstr
[] = "sisfb: Chrontel: Detected TV connected to";
2538 #ifdef CONFIG_FB_SIS_300
2539 unsigned char test
[3];
2543 if(ivideo
->chip
< SIS_315H
) {
2545 #ifdef CONFIG_FB_SIS_300
2546 ivideo
->SiS_Pr
.SiS_IF_DEF_CH70xx
= 1; /* Chrontel 700x */
2547 SiS_SetChrontelGPIO(&ivideo
->SiS_Pr
, 0x9c); /* Set general purpose IO for Chrontel communication */
2548 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 1000);
2549 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x25);
2550 /* See Chrontel TB31 for explanation */
2551 temp2
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0e);
2552 if(((temp2
& 0x07) == 0x01) || (temp2
& 0x04)) {
2553 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0e, 0x0b);
2554 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 300);
2556 temp2
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x25);
2557 if(temp2
!= temp1
) temp1
= temp2
;
2559 if((temp1
>= 0x22) && (temp1
<= 0x50)) {
2560 /* Read power status */
2561 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0e);
2562 if((temp1
& 0x03) != 0x03) {
2563 /* Power all outputs */
2564 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0e,0x0b);
2565 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 300);
2567 /* Sense connected TV devices */
2568 for(i
= 0; i
< 3; i
++) {
2569 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x10, 0x01);
2570 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2571 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x10, 0x00);
2572 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2573 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x10);
2574 if(!(temp1
& 0x08)) test
[i
] = 0x02;
2575 else if(!(temp1
& 0x02)) test
[i
] = 0x01;
2577 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2580 if(test
[0] == test
[1]) temp1
= test
[0];
2581 else if(test
[0] == test
[2]) temp1
= test
[0];
2582 else if(test
[1] == test
[2]) temp1
= test
[1];
2585 "sisfb: TV detection unreliable - test results varied\n");
2589 printk(KERN_INFO
"%s SVIDEO output\n", stdstr
);
2590 ivideo
->vbflags
|= TV_SVIDEO
;
2591 SiS_SetRegOR(SISCR
, 0x32, 0x02);
2592 andSISIDXREG(SISCR
, 0x32, ~0x05);
2593 } else if (temp1
== 0x01) {
2594 printk(KERN_INFO
"%s CVBS output\n", stdstr
);
2595 ivideo
->vbflags
|= TV_AVIDEO
;
2596 SiS_SetRegOR(SISCR
, 0x32, 0x01);
2597 andSISIDXREG(SISCR
, 0x32, ~0x06);
2599 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x0e, 0x01, 0xF8);
2600 andSISIDXREG(SISCR
, 0x32, ~0x07);
2602 } else if(temp1
== 0) {
2603 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x0e, 0x01, 0xF8);
2604 andSISIDXREG(SISCR
, 0x32, ~0x07);
2606 /* Set general purpose IO for Chrontel communication */
2607 SiS_SetChrontelGPIO(&ivideo
->SiS_Pr
, 0x00);
2612 #ifdef CONFIG_FB_SIS_315
2613 ivideo
->SiS_Pr
.SiS_IF_DEF_CH70xx
= 2; /* Chrontel 7019 */
2614 temp1
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x49);
2615 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x49, 0x20);
2616 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2617 temp2
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x20);
2619 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x20, temp2
);
2620 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2622 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x20, temp2
);
2623 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2624 temp2
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x20);
2625 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x49, temp1
);
2627 if(temp2
& 0x02) temp1
|= 0x01;
2628 if(temp2
& 0x10) temp1
|= 0x01;
2629 if(temp2
& 0x04) temp1
|= 0x02;
2630 if( (temp1
& 0x01) && (temp1
& 0x02) ) temp1
= 0x04;
2633 printk(KERN_INFO
"%s CVBS output\n", stdstr
);
2634 ivideo
->vbflags
|= TV_AVIDEO
;
2635 SiS_SetRegOR(SISCR
, 0x32, 0x01);
2636 andSISIDXREG(SISCR
, 0x32, ~0x06);
2639 printk(KERN_INFO
"%s SVIDEO output\n", stdstr
);
2640 ivideo
->vbflags
|= TV_SVIDEO
;
2641 SiS_SetRegOR(SISCR
, 0x32, 0x02);
2642 andSISIDXREG(SISCR
, 0x32, ~0x05);
2645 printk(KERN_INFO
"%s SCART output\n", stdstr
);
2646 SiS_SetRegOR(SISCR
, 0x32, 0x04);
2647 andSISIDXREG(SISCR
, 0x32, ~0x03);
2650 andSISIDXREG(SISCR
, 0x32, ~0x07);
2656 static void __devinit
2657 sisfb_get_VB_type(struct sis_video_info
*ivideo
)
2659 char stdstr
[] = "sisfb: Detected";
2660 char bridgestr
[] = "video bridge";
2664 /* No CRT2 on XGI Z7 */
2665 if(ivideo
->chip
== XGI_20
)
2668 vb_chipid
= SiS_GetReg(SISPART4
, 0x00);
2671 reg
= SiS_GetReg(SISPART4
, 0x01);
2673 ivideo
->vbflags
|= VB_301
; /* Deprecated */
2674 ivideo
->vbflags2
|= VB2_301
;
2675 printk(KERN_INFO
"%s SiS301 %s\n", stdstr
, bridgestr
);
2676 } else if(reg
< 0xc0) {
2677 ivideo
->vbflags
|= VB_301B
; /* Deprecated */
2678 ivideo
->vbflags2
|= VB2_301B
;
2679 reg
= SiS_GetReg(SISPART4
, 0x23);
2681 ivideo
->vbflags
|= VB_30xBDH
; /* Deprecated */
2682 ivideo
->vbflags2
|= VB2_30xBDH
;
2683 printk(KERN_INFO
"%s SiS301B-DH %s\n", stdstr
, bridgestr
);
2685 printk(KERN_INFO
"%s SiS301B %s\n", stdstr
, bridgestr
);
2687 } else if(reg
< 0xd0) {
2688 ivideo
->vbflags
|= VB_301C
; /* Deprecated */
2689 ivideo
->vbflags2
|= VB2_301C
;
2690 printk(KERN_INFO
"%s SiS301C %s\n", stdstr
, bridgestr
);
2691 } else if(reg
< 0xe0) {
2692 ivideo
->vbflags
|= VB_301LV
; /* Deprecated */
2693 ivideo
->vbflags2
|= VB2_301LV
;
2694 printk(KERN_INFO
"%s SiS301LV %s\n", stdstr
, bridgestr
);
2695 } else if(reg
<= 0xe1) {
2696 reg
= SiS_GetReg(SISPART4
, 0x39);
2698 ivideo
->vbflags
|= VB_302LV
; /* Deprecated */
2699 ivideo
->vbflags2
|= VB2_302LV
;
2700 printk(KERN_INFO
"%s SiS302LV %s\n", stdstr
, bridgestr
);
2702 ivideo
->vbflags
|= VB_301C
; /* Deprecated */
2703 ivideo
->vbflags2
|= VB2_301C
;
2704 printk(KERN_INFO
"%s SiS301C(P4) %s\n", stdstr
, bridgestr
);
2706 ivideo
->vbflags
|= VB_302ELV
; /* Deprecated */
2707 ivideo
->vbflags2
|= VB2_302ELV
;
2708 printk(KERN_INFO
"%s SiS302ELV %s\n", stdstr
, bridgestr
);
2714 ivideo
->vbflags
|= VB_302B
; /* Deprecated */
2715 ivideo
->vbflags2
|= VB2_302B
;
2716 printk(KERN_INFO
"%s SiS302B %s\n", stdstr
, bridgestr
);
2720 if((!(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
)) && (ivideo
->chip
!= SIS_300
)) {
2721 reg
= SiS_GetReg(SISCR
, 0x37);
2722 reg
&= SIS_EXTERNAL_CHIP_MASK
;
2724 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2725 #ifdef CONFIG_FB_SIS_300
2727 case SIS_EXTERNAL_CHIP_LVDS
:
2728 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2729 ivideo
->vbflags2
|= VB2_LVDS
;
2731 case SIS_EXTERNAL_CHIP_TRUMPION
:
2732 ivideo
->vbflags
|= (VB_LVDS
| VB_TRUMPION
); /* Deprecated */
2733 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_TRUMPION
);
2735 case SIS_EXTERNAL_CHIP_CHRONTEL
:
2736 ivideo
->vbflags
|= VB_CHRONTEL
; /* Deprecated */
2737 ivideo
->vbflags2
|= VB2_CHRONTEL
;
2739 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL
:
2740 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2741 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2744 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 1;
2746 } else if(ivideo
->chip
< SIS_661
) {
2747 #ifdef CONFIG_FB_SIS_315
2749 case SIS310_EXTERNAL_CHIP_LVDS
:
2750 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2751 ivideo
->vbflags2
|= VB2_LVDS
;
2753 case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL
:
2754 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2755 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2758 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 2;
2760 } else if(ivideo
->chip
>= SIS_661
) {
2761 #ifdef CONFIG_FB_SIS_315
2762 reg
= SiS_GetReg(SISCR
, 0x38);
2766 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2767 ivideo
->vbflags2
|= VB2_LVDS
;
2770 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2771 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2774 ivideo
->vbflags
|= (VB_LVDS
| VB_CONEXANT
); /* Deprecated */
2775 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CONEXANT
);
2778 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 2;
2781 if(ivideo
->vbflags2
& VB2_LVDS
) {
2782 printk(KERN_INFO
"%s LVDS transmitter\n", stdstr
);
2784 if((ivideo
->sisvga_engine
== SIS_300_VGA
) && (ivideo
->vbflags2
& VB2_TRUMPION
)) {
2785 printk(KERN_INFO
"%s Trumpion Zurac LCD scaler\n", stdstr
);
2787 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
2788 printk(KERN_INFO
"%s Chrontel TV encoder\n", stdstr
);
2790 if((ivideo
->chip
>= SIS_661
) && (ivideo
->vbflags2
& VB2_CONEXANT
)) {
2791 printk(KERN_INFO
"%s Conexant external device\n", stdstr
);
2795 if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
2796 SiS_SenseLCD(ivideo
);
2797 SiS_Sense30x(ivideo
);
2798 } else if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
2799 SiS_SenseCh(ivideo
);
2803 /* ---------- Engine initialization routines ------------ */
2806 sisfb_engine_init(struct sis_video_info
*ivideo
)
2809 /* Initialize command queue (we use MMIO only) */
2811 /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
2813 ivideo
->caps
&= ~(TURBO_QUEUE_CAP
|
2814 MMIO_CMD_QUEUE_CAP
|
2818 #ifdef CONFIG_FB_SIS_300
2819 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2823 tqueue_pos
= (ivideo
->video_size
- ivideo
->cmdQueueSize
) / (64 * 1024);
2825 tq_state
= SiS_GetReg(SISSR
, IND_SIS_TURBOQUEUE_SET
);
2828 tq_state
|= (u8
)(tqueue_pos
>> 8);
2829 SiS_SetReg(SISSR
, IND_SIS_TURBOQUEUE_SET
, tq_state
);
2831 SiS_SetReg(SISSR
, IND_SIS_TURBOQUEUE_ADR
, (u8
)(tqueue_pos
& 0xff));
2833 ivideo
->caps
|= TURBO_QUEUE_CAP
;
2837 #ifdef CONFIG_FB_SIS_315
2838 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2839 u32 tempq
= 0, templ
;
2842 if(ivideo
->chip
== XGI_20
) {
2843 switch(ivideo
->cmdQueueSize
) {
2845 temp
= SIS_CMD_QUEUE_SIZE_Z7_64k
;
2849 temp
= SIS_CMD_QUEUE_SIZE_Z7_128k
;
2852 switch(ivideo
->cmdQueueSize
) {
2853 case (4 * 1024 * 1024):
2854 temp
= SIS_CMD_QUEUE_SIZE_4M
;
2856 case (2 * 1024 * 1024):
2857 temp
= SIS_CMD_QUEUE_SIZE_2M
;
2859 case (1 * 1024 * 1024):
2860 temp
= SIS_CMD_QUEUE_SIZE_1M
;
2864 temp
= SIS_CMD_QUEUE_SIZE_512k
;
2868 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_THRESHOLD
, COMMAND_QUEUE_THRESHOLD
);
2869 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, SIS_CMD_QUEUE_RESET
);
2871 if((ivideo
->chip
>= XGI_40
) && ivideo
->modechanged
) {
2872 /* Must disable dual pipe on XGI_40. Can't do
2873 * this in MMIO mode, because it requires
2874 * setting/clearing a bit in the MMIO fire trigger
2877 if(!((templ
= MMIO_IN32(ivideo
->mmio_vbase
, 0x8240)) & (1 << 10))) {
2879 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, 0);
2881 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, (temp
| SIS_VRAM_CMDQUEUE_ENABLE
));
2883 tempq
= MMIO_IN32(ivideo
->mmio_vbase
, Q_READ_PTR
);
2884 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, tempq
);
2886 tempq
= (u32
)(ivideo
->video_size
- ivideo
->cmdQueueSize
);
2887 MMIO_OUT32(ivideo
->mmio_vbase
, Q_BASE_ADDR
, tempq
);
2889 writel(0x16800000 + 0x8240, ivideo
->video_vbase
+ tempq
);
2890 writel(templ
| (1 << 10), ivideo
->video_vbase
+ tempq
+ 4);
2891 writel(0x168F0000, ivideo
->video_vbase
+ tempq
+ 8);
2892 writel(0x168F0000, ivideo
->video_vbase
+ tempq
+ 12);
2894 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, (tempq
+ 16));
2896 sisfb_syncaccel(ivideo
);
2898 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, SIS_CMD_QUEUE_RESET
);
2903 tempq
= MMIO_IN32(ivideo
->mmio_vbase
, MMIO_QUEUE_READPORT
);
2904 MMIO_OUT32(ivideo
->mmio_vbase
, MMIO_QUEUE_WRITEPORT
, tempq
);
2906 temp
|= (SIS_MMIO_CMD_ENABLE
| SIS_CMD_AUTO_CORR
);
2907 SiS_SetReg(SISSR
, IND_SIS_CMDQUEUE_SET
, temp
);
2909 tempq
= (u32
)(ivideo
->video_size
- ivideo
->cmdQueueSize
);
2910 MMIO_OUT32(ivideo
->mmio_vbase
, MMIO_QUEUE_PHYBASE
, tempq
);
2912 ivideo
->caps
|= MMIO_CMD_QUEUE_CAP
;
2916 ivideo
->engineok
= 1;
2919 static void __devinit
2920 sisfb_detect_lcd_type(struct sis_video_info
*ivideo
)
2925 reg
= SiS_GetReg(SISCR
, 0x36);
2927 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2928 ivideo
->CRT2LCDType
= sis300paneltype
[reg
];
2929 } else if(ivideo
->chip
>= SIS_661
) {
2930 ivideo
->CRT2LCDType
= sis661paneltype
[reg
];
2932 ivideo
->CRT2LCDType
= sis310paneltype
[reg
];
2933 if((ivideo
->chip
== SIS_550
) && (sisfb_fstn
)) {
2934 if((ivideo
->CRT2LCDType
!= LCD_320x240_2
) &&
2935 (ivideo
->CRT2LCDType
!= LCD_320x240_3
)) {
2936 ivideo
->CRT2LCDType
= LCD_320x240
;
2941 if(ivideo
->CRT2LCDType
== LCD_UNKNOWN
) {
2942 /* For broken BIOSes: Assume 1024x768, RGB18 */
2943 ivideo
->CRT2LCDType
= LCD_1024x768
;
2944 setSISIDXREG(SISCR
,0x36,0xf0,0x02);
2945 setSISIDXREG(SISCR
,0x37,0xee,0x01);
2946 printk(KERN_DEBUG
"sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg
);
2949 for(i
= 0; i
< SIS_LCD_NUMBER
; i
++) {
2950 if(ivideo
->CRT2LCDType
== sis_lcd_data
[i
].lcdtype
) {
2951 ivideo
->lcdxres
= sis_lcd_data
[i
].xres
;
2952 ivideo
->lcdyres
= sis_lcd_data
[i
].yres
;
2953 ivideo
->lcddefmodeidx
= sis_lcd_data
[i
].default_mode_idx
;
2958 #ifdef CONFIG_FB_SIS_300
2959 if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_BARCO1366
) {
2960 ivideo
->lcdxres
= 1360; ivideo
->lcdyres
= 1024;
2961 ivideo
->lcddefmodeidx
= DEFAULT_MODE_1360
;
2962 } else if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_PANEL848
) {
2963 ivideo
->lcdxres
= 848; ivideo
->lcdyres
= 480;
2964 ivideo
->lcddefmodeidx
= DEFAULT_MODE_848
;
2965 } else if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_PANEL856
) {
2966 ivideo
->lcdxres
= 856; ivideo
->lcdyres
= 480;
2967 ivideo
->lcddefmodeidx
= DEFAULT_MODE_856
;
2971 printk(KERN_DEBUG
"sisfb: Detected %dx%d flat panel\n",
2972 ivideo
->lcdxres
, ivideo
->lcdyres
);
2975 static void __devinit
2976 sisfb_save_pdc_emi(struct sis_video_info
*ivideo
)
2978 #ifdef CONFIG_FB_SIS_300
2979 /* Save the current PanelDelayCompensation if the LCD is currently used */
2980 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2981 if(ivideo
->vbflags2
& (VB2_LVDS
| VB2_30xBDH
)) {
2983 tmp
= SiS_GetReg(SISCR
, 0x30);
2985 /* Currently on LCD? If yes, read current pdc */
2986 ivideo
->detectedpdc
= SiS_GetReg(SISPART1
, 0x13);
2987 ivideo
->detectedpdc
&= 0x3c;
2988 if(ivideo
->SiS_Pr
.PDC
== -1) {
2989 /* Let option override detection */
2990 ivideo
->SiS_Pr
.PDC
= ivideo
->detectedpdc
;
2992 printk(KERN_INFO
"sisfb: Detected LCD PDC 0x%02x\n",
2993 ivideo
->detectedpdc
);
2995 if((ivideo
->SiS_Pr
.PDC
!= -1) &&
2996 (ivideo
->SiS_Pr
.PDC
!= ivideo
->detectedpdc
)) {
2997 printk(KERN_INFO
"sisfb: Using LCD PDC 0x%02x\n",
2998 ivideo
->SiS_Pr
.PDC
);
3004 #ifdef CONFIG_FB_SIS_315
3005 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3007 /* Try to find about LCDA */
3008 if(ivideo
->vbflags2
& VB2_SISLCDABRIDGE
) {
3010 tmp
= SiS_GetReg(SISPART1
, 0x13);
3012 ivideo
->SiS_Pr
.SiS_UseLCDA
= true;
3013 ivideo
->detectedlcda
= 0x03;
3018 if(ivideo
->vbflags2
& VB2_SISLVDSBRIDGE
) {
3020 tmp
= SiS_GetReg(SISCR
, 0x30);
3021 if((tmp
& 0x20) || (ivideo
->detectedlcda
!= 0xff)) {
3022 /* Currently on LCD? If yes, read current pdc */
3024 pdc
= SiS_GetReg(SISPART1
, 0x2D);
3025 ivideo
->detectedpdc
= (pdc
& 0x0f) << 1;
3026 ivideo
->detectedpdca
= (pdc
& 0xf0) >> 3;
3027 pdc
= SiS_GetReg(SISPART1
, 0x35);
3028 ivideo
->detectedpdc
|= ((pdc
>> 7) & 0x01);
3029 pdc
= SiS_GetReg(SISPART1
, 0x20);
3030 ivideo
->detectedpdca
|= ((pdc
>> 6) & 0x01);
3031 if(ivideo
->newrom
) {
3032 /* New ROM invalidates other PDC resp. */
3033 if(ivideo
->detectedlcda
!= 0xff) {
3034 ivideo
->detectedpdc
= 0xff;
3036 ivideo
->detectedpdca
= 0xff;
3039 if(ivideo
->SiS_Pr
.PDC
== -1) {
3040 if(ivideo
->detectedpdc
!= 0xff) {
3041 ivideo
->SiS_Pr
.PDC
= ivideo
->detectedpdc
;
3044 if(ivideo
->SiS_Pr
.PDCA
== -1) {
3045 if(ivideo
->detectedpdca
!= 0xff) {
3046 ivideo
->SiS_Pr
.PDCA
= ivideo
->detectedpdca
;
3049 if(ivideo
->detectedpdc
!= 0xff) {
3051 "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3052 ivideo
->detectedpdc
);
3054 if(ivideo
->detectedpdca
!= 0xff) {
3056 "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3057 ivideo
->detectedpdca
);
3062 if(ivideo
->vbflags2
& VB2_SISEMIBRIDGE
) {
3063 ivideo
->SiS_Pr
.EMI_30
= SiS_GetReg(SISPART4
, 0x30);
3064 ivideo
->SiS_Pr
.EMI_31
= SiS_GetReg(SISPART4
, 0x31);
3065 ivideo
->SiS_Pr
.EMI_32
= SiS_GetReg(SISPART4
, 0x32);
3066 ivideo
->SiS_Pr
.EMI_33
= SiS_GetReg(SISPART4
, 0x33);
3067 ivideo
->SiS_Pr
.HaveEMI
= true;
3068 if((tmp
& 0x20) || (ivideo
->detectedlcda
!= 0xff)) {
3069 ivideo
->SiS_Pr
.HaveEMILCD
= true;
3074 /* Let user override detected PDCs (all bridges) */
3075 if(ivideo
->vbflags2
& VB2_30xBLV
) {
3076 if((ivideo
->SiS_Pr
.PDC
!= -1) &&
3077 (ivideo
->SiS_Pr
.PDC
!= ivideo
->detectedpdc
)) {
3078 printk(KERN_INFO
"sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3079 ivideo
->SiS_Pr
.PDC
);
3081 if((ivideo
->SiS_Pr
.PDCA
!= -1) &&
3082 (ivideo
->SiS_Pr
.PDCA
!= ivideo
->detectedpdca
)) {
3083 printk(KERN_INFO
"sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3084 ivideo
->SiS_Pr
.PDCA
);
3092 /* -------------------- Memory manager routines ---------------------- */
3094 static u32 __devinit
3095 sisfb_getheapstart(struct sis_video_info
*ivideo
)
3097 u32 ret
= ivideo
->sisfb_parm_mem
* 1024;
3098 u32 maxoffs
= ivideo
->video_size
- ivideo
->hwcursor_size
- ivideo
->cmdQueueSize
;
3101 /* Calculate heap start = end of memory for console
3103 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3104 * C = console, D = heap, H = HWCursor, Q = cmd-queue
3106 * On 76x in UMA+LFB mode, the layout is as follows:
3107 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3108 * where the heap is the entire UMA area, eventually
3109 * into the LFB area if the given mem parameter is
3110 * higher than the size of the UMA memory.
3112 * Basically given by "mem" parameter
3114 * maximum = videosize - cmd_queue - hwcursor
3115 * (results in a heap of size 0)
3116 * default = SiS 300: depends on videosize
3117 * SiS 315/330/340/XGI: 32k below max
3120 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3121 if(ivideo
->video_size
> 0x1000000) {
3123 } else if(ivideo
->video_size
> 0x800000) {
3128 } else if(ivideo
->UMAsize
&& ivideo
->LFBsize
) {
3131 def
= maxoffs
- 0x8000;
3134 /* Use default for secondary card for now (FIXME) */
3135 if((!ret
) || (ret
> maxoffs
) || (ivideo
->cardnumber
!= 0))
3141 static u32 __devinit
3142 sisfb_getheapsize(struct sis_video_info
*ivideo
)
3144 u32 max
= ivideo
->video_size
- ivideo
->hwcursor_size
- ivideo
->cmdQueueSize
;
3147 if(ivideo
->UMAsize
&& ivideo
->LFBsize
) {
3148 if( (!ivideo
->sisfb_parm_mem
) ||
3149 ((ivideo
->sisfb_parm_mem
* 1024) > max
) ||
3150 ((max
- (ivideo
->sisfb_parm_mem
* 1024)) < ivideo
->UMAsize
) ) {
3151 ret
= ivideo
->UMAsize
;
3152 max
-= ivideo
->UMAsize
;
3154 ret
= max
- (ivideo
->sisfb_parm_mem
* 1024);
3155 max
= ivideo
->sisfb_parm_mem
* 1024;
3157 ivideo
->video_offset
= ret
;
3158 ivideo
->sisfb_mem
= max
;
3160 ret
= max
- ivideo
->heapstart
;
3161 ivideo
->sisfb_mem
= ivideo
->heapstart
;
3167 static int __devinit
3168 sisfb_heap_init(struct sis_video_info
*ivideo
)
3172 ivideo
->video_offset
= 0;
3173 if(ivideo
->sisfb_parm_mem
) {
3174 if( (ivideo
->sisfb_parm_mem
< (2 * 1024 * 1024)) ||
3175 (ivideo
->sisfb_parm_mem
> ivideo
->video_size
) ) {
3176 ivideo
->sisfb_parm_mem
= 0;
3180 ivideo
->heapstart
= sisfb_getheapstart(ivideo
);
3181 ivideo
->sisfb_heap_size
= sisfb_getheapsize(ivideo
);
3183 ivideo
->sisfb_heap_start
= ivideo
->video_vbase
+ ivideo
->heapstart
;
3184 ivideo
->sisfb_heap_end
= ivideo
->sisfb_heap_start
+ ivideo
->sisfb_heap_size
;
3186 printk(KERN_INFO
"sisfb: Memory heap starting at %dK, size %dK\n",
3187 (int)(ivideo
->heapstart
/ 1024), (int)(ivideo
->sisfb_heap_size
/ 1024));
3189 ivideo
->sisfb_heap
.vinfo
= ivideo
;
3191 ivideo
->sisfb_heap
.poha_chain
= NULL
;
3192 ivideo
->sisfb_heap
.poh_freelist
= NULL
;
3194 poh
= sisfb_poh_new_node(&ivideo
->sisfb_heap
);
3198 poh
->poh_next
= &ivideo
->sisfb_heap
.oh_free
;
3199 poh
->poh_prev
= &ivideo
->sisfb_heap
.oh_free
;
3200 poh
->size
= ivideo
->sisfb_heap_size
;
3201 poh
->offset
= ivideo
->heapstart
;
3203 ivideo
->sisfb_heap
.oh_free
.poh_next
= poh
;
3204 ivideo
->sisfb_heap
.oh_free
.poh_prev
= poh
;
3205 ivideo
->sisfb_heap
.oh_free
.size
= 0;
3206 ivideo
->sisfb_heap
.max_freesize
= poh
->size
;
3208 ivideo
->sisfb_heap
.oh_used
.poh_next
= &ivideo
->sisfb_heap
.oh_used
;
3209 ivideo
->sisfb_heap
.oh_used
.poh_prev
= &ivideo
->sisfb_heap
.oh_used
;
3210 ivideo
->sisfb_heap
.oh_used
.size
= SENTINEL
;
3212 if(ivideo
->cardnumber
== 0) {
3213 /* For the first card, make this heap the "global" one
3214 * for old DRM (which could handle only one card)
3216 sisfb_heap
= &ivideo
->sisfb_heap
;
3222 static struct SIS_OH
*
3223 sisfb_poh_new_node(struct SIS_HEAP
*memheap
)
3225 struct SIS_OHALLOC
*poha
;
3230 if(memheap
->poh_freelist
== NULL
) {
3231 poha
= kmalloc(SIS_OH_ALLOC_SIZE
, GFP_KERNEL
);
3235 poha
->poha_next
= memheap
->poha_chain
;
3236 memheap
->poha_chain
= poha
;
3238 cOhs
= (SIS_OH_ALLOC_SIZE
- sizeof(struct SIS_OHALLOC
)) / sizeof(struct SIS_OH
) + 1;
3240 poh
= &poha
->aoh
[0];
3241 for(i
= cOhs
- 1; i
!= 0; i
--) {
3242 poh
->poh_next
= poh
+ 1;
3246 poh
->poh_next
= NULL
;
3247 memheap
->poh_freelist
= &poha
->aoh
[0];
3250 poh
= memheap
->poh_freelist
;
3251 memheap
->poh_freelist
= poh
->poh_next
;
3256 static struct SIS_OH
*
3257 sisfb_poh_allocate(struct SIS_HEAP
*memheap
, u32 size
)
3259 struct SIS_OH
*pohThis
;
3260 struct SIS_OH
*pohRoot
;
3263 if(size
> memheap
->max_freesize
) {
3264 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3265 (unsigned int) size
/ 1024);
3269 pohThis
= memheap
->oh_free
.poh_next
;
3271 while(pohThis
!= &memheap
->oh_free
) {
3272 if(size
<= pohThis
->size
) {
3276 pohThis
= pohThis
->poh_next
;
3280 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3281 (unsigned int) size
/ 1024);
3285 if(size
== pohThis
->size
) {
3287 sisfb_delete_node(pohThis
);
3289 pohRoot
= sisfb_poh_new_node(memheap
);
3293 pohRoot
->offset
= pohThis
->offset
;
3294 pohRoot
->size
= size
;
3296 pohThis
->offset
+= size
;
3297 pohThis
->size
-= size
;
3300 memheap
->max_freesize
-= size
;
3302 pohThis
= &memheap
->oh_used
;
3303 sisfb_insert_node(pohThis
, pohRoot
);
3309 sisfb_delete_node(struct SIS_OH
*poh
)
3311 poh
->poh_prev
->poh_next
= poh
->poh_next
;
3312 poh
->poh_next
->poh_prev
= poh
->poh_prev
;
3316 sisfb_insert_node(struct SIS_OH
*pohList
, struct SIS_OH
*poh
)
3318 struct SIS_OH
*pohTemp
= pohList
->poh_next
;
3320 pohList
->poh_next
= poh
;
3321 pohTemp
->poh_prev
= poh
;
3323 poh
->poh_prev
= pohList
;
3324 poh
->poh_next
= pohTemp
;
3327 static struct SIS_OH
*
3328 sisfb_poh_free(struct SIS_HEAP
*memheap
, u32 base
)
3330 struct SIS_OH
*pohThis
;
3331 struct SIS_OH
*poh_freed
;
3332 struct SIS_OH
*poh_prev
;
3333 struct SIS_OH
*poh_next
;
3338 poh_freed
= memheap
->oh_used
.poh_next
;
3340 while(poh_freed
!= &memheap
->oh_used
) {
3341 if(poh_freed
->offset
== base
) {
3346 poh_freed
= poh_freed
->poh_next
;
3352 memheap
->max_freesize
+= poh_freed
->size
;
3354 poh_prev
= poh_next
= NULL
;
3355 ulUpper
= poh_freed
->offset
+ poh_freed
->size
;
3356 ulLower
= poh_freed
->offset
;
3358 pohThis
= memheap
->oh_free
.poh_next
;
3360 while(pohThis
!= &memheap
->oh_free
) {
3361 if(pohThis
->offset
== ulUpper
) {
3363 } else if((pohThis
->offset
+ pohThis
->size
) == ulLower
) {
3366 pohThis
= pohThis
->poh_next
;
3369 sisfb_delete_node(poh_freed
);
3371 if(poh_prev
&& poh_next
) {
3372 poh_prev
->size
+= (poh_freed
->size
+ poh_next
->size
);
3373 sisfb_delete_node(poh_next
);
3374 sisfb_free_node(memheap
, poh_freed
);
3375 sisfb_free_node(memheap
, poh_next
);
3380 poh_prev
->size
+= poh_freed
->size
;
3381 sisfb_free_node(memheap
, poh_freed
);
3386 poh_next
->size
+= poh_freed
->size
;
3387 poh_next
->offset
= poh_freed
->offset
;
3388 sisfb_free_node(memheap
, poh_freed
);
3392 sisfb_insert_node(&memheap
->oh_free
, poh_freed
);
3398 sisfb_free_node(struct SIS_HEAP
*memheap
, struct SIS_OH
*poh
)
3403 poh
->poh_next
= memheap
->poh_freelist
;
3404 memheap
->poh_freelist
= poh
;
3408 sis_int_malloc(struct sis_video_info
*ivideo
, struct sis_memreq
*req
)
3410 struct SIS_OH
*poh
= NULL
;
3412 if((ivideo
) && (ivideo
->sisfb_id
== SISFB_ID
) && (!ivideo
->havenoheap
))
3413 poh
= sisfb_poh_allocate(&ivideo
->sisfb_heap
, (u32
)req
->size
);
3416 req
->offset
= req
->size
= 0;
3417 DPRINTK("sisfb: Video RAM allocation failed\n");
3419 req
->offset
= poh
->offset
;
3420 req
->size
= poh
->size
;
3421 DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3422 (poh
->offset
+ ivideo
->video_vbase
));
3427 sis_malloc(struct sis_memreq
*req
)
3429 struct sis_video_info
*ivideo
= sisfb_heap
->vinfo
;
3431 if(&ivideo
->sisfb_heap
== sisfb_heap
)
3432 sis_int_malloc(ivideo
, req
);
3434 req
->offset
= req
->size
= 0;
3438 sis_malloc_new(struct pci_dev
*pdev
, struct sis_memreq
*req
)
3440 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
3442 sis_int_malloc(ivideo
, req
);
3445 /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3448 sis_int_free(struct sis_video_info
*ivideo
, u32 base
)
3452 if((!ivideo
) || (ivideo
->sisfb_id
!= SISFB_ID
) || (ivideo
->havenoheap
))
3455 poh
= sisfb_poh_free(&ivideo
->sisfb_heap
, base
);
3458 DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
3459 (unsigned int) base
);
3466 struct sis_video_info
*ivideo
= sisfb_heap
->vinfo
;
3468 sis_int_free(ivideo
, base
);
3472 sis_free_new(struct pci_dev
*pdev
, u32 base
)
3474 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
3476 sis_int_free(ivideo
, base
);
3479 /* --------------------- SetMode routines ------------------------- */
3482 sisfb_check_engine_and_sync(struct sis_video_info
*ivideo
)
3486 /* Check if MMIO and engines are enabled,
3487 * and sync in case they are. Can't use
3488 * ivideo->accel here, as this might have
3489 * been changed before this is called.
3491 cr30
= SiS_GetReg(SISSR
, IND_SIS_PCI_ADDRESS_SET
);
3492 cr31
= SiS_GetReg(SISSR
, IND_SIS_MODULE_ENABLE
);
3493 /* MMIO and 2D/3D engine enabled? */
3494 if((cr30
& SIS_MEM_MAP_IO_ENABLE
) && (cr31
& 0x42)) {
3495 #ifdef CONFIG_FB_SIS_300
3496 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3497 /* Don't care about TurboQueue. It's
3498 * enough to know that the engines
3501 sisfb_syncaccel(ivideo
);
3504 #ifdef CONFIG_FB_SIS_315
3505 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3506 /* Check that any queue mode is
3507 * enabled, and that the queue
3508 * is not in the state of "reset"
3510 cr30
= SiS_GetReg(SISSR
, 0x26);
3511 if((cr30
& 0xe0) && (!(cr30
& 0x01))) {
3512 sisfb_syncaccel(ivideo
);
3520 sisfb_pre_setmode(struct sis_video_info
*ivideo
)
3522 u8 cr30
= 0, cr31
= 0, cr33
= 0, cr35
= 0, cr38
= 0;
3525 ivideo
->currentvbflags
&= (VB_VIDEOBRIDGE
| VB_DISPTYPE_DISP2
);
3527 SiS_SetReg(SISSR
, 0x05, 0x86);
3529 cr31
= SiS_GetReg(SISCR
, 0x31);
3533 cr33
= ivideo
->rate_idx
& 0x0F;
3535 #ifdef CONFIG_FB_SIS_315
3536 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3537 if(ivideo
->chip
>= SIS_661
) {
3538 cr38
= SiS_GetReg(SISCR
, 0x38);
3539 cr38
&= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
3542 cr38
= SiS_GetReg(SISCR
, tvregnum
);
3543 cr38
&= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
3547 #ifdef CONFIG_FB_SIS_300
3548 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3550 cr38
= SiS_GetReg(SISCR
, tvregnum
);
3554 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
3555 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
3556 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
3558 switch(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
3561 cr38
&= ~0xc0; /* Clear PAL-M / PAL-N bits */
3562 if((ivideo
->vbflags
& TV_YPBPR
) && (ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) {
3563 #ifdef CONFIG_FB_SIS_315
3564 if(ivideo
->chip
>= SIS_661
) {
3566 if(ivideo
->vbflags
& TV_YPBPR525P
) cr35
|= 0x20;
3567 else if(ivideo
->vbflags
& TV_YPBPR750P
) cr35
|= 0x40;
3568 else if(ivideo
->vbflags
& TV_YPBPR1080I
) cr35
|= 0x60;
3569 cr30
|= SIS_SIMULTANEOUS_VIEW_ENABLE
;
3571 ivideo
->currentvbflags
|= (TV_YPBPR
| (ivideo
->vbflags
& TV_YPBPRALL
));
3572 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3573 cr30
|= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE
);
3575 if(ivideo
->vbflags
& TV_YPBPR525P
) cr38
|= 0x10;
3576 else if(ivideo
->vbflags
& TV_YPBPR750P
) cr38
|= 0x20;
3577 else if(ivideo
->vbflags
& TV_YPBPR1080I
) cr38
|= 0x30;
3579 ivideo
->currentvbflags
|= (TV_YPBPR
| (ivideo
->vbflags
& TV_YPBPRALL
));
3582 } else if((ivideo
->vbflags
& TV_HIVISION
) &&
3583 (ivideo
->vbflags2
& VB2_SISHIVISIONBRIDGE
)) {
3584 if(ivideo
->chip
>= SIS_661
) {
3590 cr30
|= SIS_SIMULTANEOUS_VIEW_ENABLE
;
3593 ivideo
->currentvbflags
|= TV_HIVISION
;
3594 } else if(ivideo
->vbflags
& TV_SCART
) {
3595 cr30
= (SIS_VB_OUTPUT_SCART
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3598 ivideo
->currentvbflags
|= TV_SCART
;
3600 if(ivideo
->vbflags
& TV_SVIDEO
) {
3601 cr30
= (SIS_VB_OUTPUT_SVIDEO
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3602 ivideo
->currentvbflags
|= TV_SVIDEO
;
3604 if(ivideo
->vbflags
& TV_AVIDEO
) {
3605 cr30
= (SIS_VB_OUTPUT_COMPOSITE
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3606 ivideo
->currentvbflags
|= TV_AVIDEO
;
3609 cr31
|= SIS_DRIVER_MODE
;
3611 if(ivideo
->vbflags
& (TV_AVIDEO
| TV_SVIDEO
)) {
3612 if(ivideo
->vbflags
& TV_PAL
) {
3613 cr31
|= 0x01; cr35
|= 0x01;
3614 ivideo
->currentvbflags
|= TV_PAL
;
3615 if(ivideo
->vbflags
& TV_PALM
) {
3616 cr38
|= 0x40; cr35
|= 0x04;
3617 ivideo
->currentvbflags
|= TV_PALM
;
3618 } else if(ivideo
->vbflags
& TV_PALN
) {
3619 cr38
|= 0x80; cr35
|= 0x08;
3620 ivideo
->currentvbflags
|= TV_PALN
;
3623 cr31
&= ~0x01; cr35
&= ~0x01;
3624 ivideo
->currentvbflags
|= TV_NTSC
;
3625 if(ivideo
->vbflags
& TV_NTSCJ
) {
3626 cr38
|= 0x40; cr35
|= 0x02;
3627 ivideo
->currentvbflags
|= TV_NTSCJ
;
3634 cr30
= (SIS_VB_OUTPUT_LCD
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3635 cr31
|= SIS_DRIVER_MODE
;
3636 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, ivideo
->sisfb_dstn
);
3637 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, ivideo
->sisfb_fstn
);
3638 ivideo
->curFSTN
= ivideo
->sisfb_fstn
;
3639 ivideo
->curDSTN
= ivideo
->sisfb_dstn
;
3643 cr30
= (SIS_VB_OUTPUT_CRT2
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3644 cr31
|= SIS_DRIVER_MODE
;
3645 if(ivideo
->sisfb_nocrt2rate
) {
3646 cr33
|= (sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
<< 4);
3648 cr33
|= ((ivideo
->rate_idx
& 0x0F) << 4);
3652 default: /* disable CRT2 */
3654 cr31
|= (SIS_DRIVER_MODE
| SIS_VB_OUTPUT_DISABLE
);
3657 SiS_SetReg(SISCR
, 0x30, cr30
);
3658 SiS_SetReg(SISCR
, 0x33, cr33
);
3660 if(ivideo
->chip
>= SIS_661
) {
3661 #ifdef CONFIG_FB_SIS_315
3662 cr31
&= ~0x01; /* Clear PAL flag (now in CR35) */
3663 setSISIDXREG(SISCR
, 0x35, ~0x10, cr35
); /* Leave overscan bit alone */
3664 cr38
&= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
3665 setSISIDXREG(SISCR
, 0x38, 0xf8, cr38
);
3667 } else if(ivideo
->chip
!= SIS_300
) {
3668 SiS_SetReg(SISCR
, tvregnum
, cr38
);
3670 SiS_SetReg(SISCR
, 0x31, cr31
);
3672 ivideo
->SiS_Pr
.SiS_UseOEM
= ivideo
->sisfb_useoem
;
3674 sisfb_check_engine_and_sync(ivideo
);
3677 /* Fix SR11 for 661 and later */
3678 #ifdef CONFIG_FB_SIS_315
3680 sisfb_fixup_SR11(struct sis_video_info
*ivideo
)
3684 if(ivideo
->chip
>= SIS_661
) {
3685 tmpreg
= SiS_GetReg(SISSR
, 0x11);
3687 tmpreg
= SiS_GetReg(SISSR
, 0x3e);
3688 tmpreg
= (tmpreg
+ 1) & 0xff;
3689 SiS_SetReg(SISSR
, 0x3e, tmpreg
);
3690 tmpreg
= SiS_GetReg(SISSR
, 0x11);
3693 andSISIDXREG(SISSR
,0x11,0x0f);
3700 sisfb_set_TVxposoffset(struct sis_video_info
*ivideo
, int val
)
3702 if(val
> 32) val
= 32;
3703 if(val
< -32) val
= -32;
3704 ivideo
->tvxpos
= val
;
3706 if(ivideo
->sisfblocked
) return;
3707 if(!ivideo
->modechanged
) return;
3709 if(ivideo
->currentvbflags
& CRT2_TV
) {
3711 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3713 int x
= ivideo
->tvx
;
3715 switch(ivideo
->chronteltype
) {
3719 SiS_SetReg(SISSR
, 0x05, 0x86);
3720 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0a, (x
& 0xff));
3721 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x08, ((x
& 0x0100) >> 7), 0xFD);
3724 /* Not supported by hardware */
3728 } else if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3730 u8 p2_1f
,p2_20
,p2_2b
,p2_42
,p2_43
;
3731 unsigned short temp
;
3733 p2_1f
= ivideo
->p2_1f
;
3734 p2_20
= ivideo
->p2_20
;
3735 p2_2b
= ivideo
->p2_2b
;
3736 p2_42
= ivideo
->p2_42
;
3737 p2_43
= ivideo
->p2_43
;
3739 temp
= p2_1f
| ((p2_20
& 0xf0) << 4);
3741 p2_1f
= temp
& 0xff;
3742 p2_20
= (temp
& 0xf00) >> 4;
3743 p2_2b
= ((p2_2b
& 0x0f) + (val
* 2)) & 0x0f;
3744 temp
= p2_43
| ((p2_42
& 0xf0) << 4);
3746 p2_43
= temp
& 0xff;
3747 p2_42
= (temp
& 0xf00) >> 4;
3748 SiS_SetReg(SISPART2
, 0x1f, p2_1f
);
3749 setSISIDXREG(SISPART2
,0x20,0x0F,p2_20
);
3750 setSISIDXREG(SISPART2
,0x2b,0xF0,p2_2b
);
3751 setSISIDXREG(SISPART2
,0x42,0x0F,p2_42
);
3752 SiS_SetReg(SISPART2
, 0x43, p2_43
);
3758 sisfb_set_TVyposoffset(struct sis_video_info
*ivideo
, int val
)
3760 if(val
> 32) val
= 32;
3761 if(val
< -32) val
= -32;
3762 ivideo
->tvypos
= val
;
3764 if(ivideo
->sisfblocked
) return;
3765 if(!ivideo
->modechanged
) return;
3767 if(ivideo
->currentvbflags
& CRT2_TV
) {
3769 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3771 int y
= ivideo
->tvy
;
3773 switch(ivideo
->chronteltype
) {
3777 SiS_SetReg(SISSR
, 0x05, 0x86);
3778 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0b, (y
& 0xff));
3779 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x08, ((y
& 0x0100) >> 8), 0xFE);
3782 /* Not supported by hardware */
3786 } else if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3790 p2_01
= ivideo
->p2_01
;
3791 p2_02
= ivideo
->p2_02
;
3795 if(!(ivideo
->currentvbflags
& (TV_HIVISION
| TV_YPBPR
))) {
3796 while((p2_01
<= 0) || (p2_02
<= 0)) {
3801 SiS_SetReg(SISPART2
, 0x01, p2_01
);
3802 SiS_SetReg(SISPART2
, 0x02, p2_02
);
3808 sisfb_post_setmode(struct sis_video_info
*ivideo
)
3810 bool crt1isoff
= false;
3812 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
3815 #ifdef CONFIG_FB_SIS_315
3819 SiS_SetReg(SISSR
, 0x05, 0x86);
3821 #ifdef CONFIG_FB_SIS_315
3822 sisfb_fixup_SR11(ivideo
);
3825 /* Now we actually HAVE changed the display mode */
3826 ivideo
->modechanged
= 1;
3828 /* We can't switch off CRT1 if bridge is in slave mode */
3829 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
3830 if(sisfb_bridgeisslave(ivideo
)) doit
= false;
3832 ivideo
->sisfb_crt1off
= 0;
3834 #ifdef CONFIG_FB_SIS_300
3835 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3836 if((ivideo
->sisfb_crt1off
) && (doit
)) {
3843 setSISIDXREG(SISCR
, 0x17, 0x7f, reg
);
3846 #ifdef CONFIG_FB_SIS_315
3847 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3848 if((ivideo
->sisfb_crt1off
) && (doit
)) {
3857 setSISIDXREG(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, ~0x40, reg
);
3858 setSISIDXREG(SISSR
, 0x1f, ~0xc0, reg1
);
3863 ivideo
->currentvbflags
&= ~VB_DISPTYPE_CRT1
;
3864 ivideo
->currentvbflags
|= VB_SINGLE_MODE
;
3866 ivideo
->currentvbflags
|= VB_DISPTYPE_CRT1
;
3867 if(ivideo
->currentvbflags
& VB_DISPTYPE_CRT2
) {
3868 ivideo
->currentvbflags
|= VB_MIRROR_MODE
;
3870 ivideo
->currentvbflags
|= VB_SINGLE_MODE
;
3874 andSISIDXREG(SISSR
, IND_SIS_RAMDAC_CONTROL
, ~0x04);
3876 if(ivideo
->currentvbflags
& CRT2_TV
) {
3877 if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3878 ivideo
->p2_1f
= SiS_GetReg(SISPART2
, 0x1f);
3879 ivideo
->p2_20
= SiS_GetReg(SISPART2
, 0x20);
3880 ivideo
->p2_2b
= SiS_GetReg(SISPART2
, 0x2b);
3881 ivideo
->p2_42
= SiS_GetReg(SISPART2
, 0x42);
3882 ivideo
->p2_43
= SiS_GetReg(SISPART2
, 0x43);
3883 ivideo
->p2_01
= SiS_GetReg(SISPART2
, 0x01);
3884 ivideo
->p2_02
= SiS_GetReg(SISPART2
, 0x02);
3885 } else if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3886 if(ivideo
->chronteltype
== 1) {
3887 ivideo
->tvx
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0a);
3888 ivideo
->tvx
|= (((SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x08) & 0x02) >> 1) << 8);
3889 ivideo
->tvy
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0b);
3890 ivideo
->tvy
|= ((SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x08) & 0x01) << 8);
3895 if(ivideo
->tvxpos
) {
3896 sisfb_set_TVxposoffset(ivideo
, ivideo
->tvxpos
);
3898 if(ivideo
->tvypos
) {
3899 sisfb_set_TVyposoffset(ivideo
, ivideo
->tvypos
);
3902 /* Eventually sync engines */
3903 sisfb_check_engine_and_sync(ivideo
);
3905 /* (Re-)Initialize chip engines */
3907 sisfb_engine_init(ivideo
);
3909 ivideo
->engineok
= 0;
3914 sisfb_reset_mode(struct sis_video_info
*ivideo
)
3916 if(sisfb_set_mode(ivideo
, 0))
3919 sisfb_set_pitch(ivideo
);
3920 sisfb_set_base_CRT1(ivideo
, ivideo
->current_base
);
3921 sisfb_set_base_CRT2(ivideo
, ivideo
->current_base
);
3927 sisfb_handle_command(struct sis_video_info
*ivideo
, struct sisfb_cmd
*sisfb_command
)
3931 switch(sisfb_command
->sisfb_cmd
) {
3932 case SISFB_CMD_GETVBFLAGS
:
3933 if(!ivideo
->modechanged
) {
3934 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_EARLY
;
3936 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3937 sisfb_command
->sisfb_result
[1] = ivideo
->currentvbflags
;
3938 sisfb_command
->sisfb_result
[2] = ivideo
->vbflags2
;
3941 case SISFB_CMD_SWITCHCRT1
:
3942 /* arg[0]: 0 = off, 1 = on, 99 = query */
3943 if(!ivideo
->modechanged
) {
3944 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_EARLY
;
3945 } else if(sisfb_command
->sisfb_arg
[0] == 99) {
3947 sisfb_command
->sisfb_result
[1] = ivideo
->sisfb_crt1off
? 0 : 1;
3948 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3949 } else if(ivideo
->sisfblocked
) {
3950 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_LOCKED
;
3951 } else if((!(ivideo
->currentvbflags
& CRT2_ENABLE
)) &&
3952 (sisfb_command
->sisfb_arg
[0] == 0)) {
3953 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_NOCRT2
;
3955 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3956 mycrt1off
= sisfb_command
->sisfb_arg
[0] ? 0 : 1;
3957 if( ((ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
) && mycrt1off
) ||
3958 ((!(ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
)) && !mycrt1off
) ) {
3959 ivideo
->sisfb_crt1off
= mycrt1off
;
3960 if(sisfb_reset_mode(ivideo
)) {
3961 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OTHER
;
3964 sisfb_command
->sisfb_result
[1] = ivideo
->sisfb_crt1off
? 0 : 1;
3969 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_UNKNOWN
;
3970 printk(KERN_ERR
"sisfb: Unknown command 0x%x\n",
3971 sisfb_command
->sisfb_cmd
);
3976 static int __init
sisfb_setup(char *options
)
3980 sisfb_setdefaultparms();
3982 if(!options
|| !(*options
))
3985 while((this_opt
= strsep(&options
, ",")) != NULL
) {
3987 if(!(*this_opt
)) continue;
3989 if(!strnicmp(this_opt
, "off", 3)) {
3991 } else if(!strnicmp(this_opt
, "forcecrt2type:", 14)) {
3992 /* Need to check crt2 type first for fstn/dstn */
3993 sisfb_search_crt2type(this_opt
+ 14);
3994 } else if(!strnicmp(this_opt
, "tvmode:",7)) {
3995 sisfb_search_tvstd(this_opt
+ 7);
3996 } else if(!strnicmp(this_opt
, "tvstandard:",11)) {
3997 sisfb_search_tvstd(this_opt
+ 11);
3998 } else if(!strnicmp(this_opt
, "mode:", 5)) {
3999 sisfb_search_mode(this_opt
+ 5, false);
4000 } else if(!strnicmp(this_opt
, "vesa:", 5)) {
4001 sisfb_search_vesamode(simple_strtoul(this_opt
+ 5, NULL
, 0), false);
4002 } else if(!strnicmp(this_opt
, "rate:", 5)) {
4003 sisfb_parm_rate
= simple_strtoul(this_opt
+ 5, NULL
, 0);
4004 } else if(!strnicmp(this_opt
, "forcecrt1:", 10)) {
4005 sisfb_forcecrt1
= (int)simple_strtoul(this_opt
+ 10, NULL
, 0);
4006 } else if(!strnicmp(this_opt
, "mem:",4)) {
4007 sisfb_parm_mem
= simple_strtoul(this_opt
+ 4, NULL
, 0);
4008 } else if(!strnicmp(this_opt
, "pdc:", 4)) {
4009 sisfb_pdc
= simple_strtoul(this_opt
+ 4, NULL
, 0);
4010 } else if(!strnicmp(this_opt
, "pdc1:", 5)) {
4011 sisfb_pdca
= simple_strtoul(this_opt
+ 5, NULL
, 0);
4012 } else if(!strnicmp(this_opt
, "noaccel", 7)) {
4014 } else if(!strnicmp(this_opt
, "accel", 5)) {
4016 } else if(!strnicmp(this_opt
, "noypan", 6)) {
4018 } else if(!strnicmp(this_opt
, "ypan", 4)) {
4020 } else if(!strnicmp(this_opt
, "nomax", 5)) {
4022 } else if(!strnicmp(this_opt
, "max", 3)) {
4024 } else if(!strnicmp(this_opt
, "userom:", 7)) {
4025 sisfb_userom
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
4026 } else if(!strnicmp(this_opt
, "useoem:", 7)) {
4027 sisfb_useoem
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
4028 } else if(!strnicmp(this_opt
, "nocrt2rate", 10)) {
4029 sisfb_nocrt2rate
= 1;
4030 } else if(!strnicmp(this_opt
, "scalelcd:", 9)) {
4031 unsigned long temp
= 2;
4032 temp
= simple_strtoul(this_opt
+ 9, NULL
, 0);
4033 if((temp
== 0) || (temp
== 1)) {
4034 sisfb_scalelcd
= temp
^ 1;
4036 } else if(!strnicmp(this_opt
, "tvxposoffset:", 13)) {
4038 temp
= (int)simple_strtol(this_opt
+ 13, NULL
, 0);
4039 if((temp
>= -32) && (temp
<= 32)) {
4040 sisfb_tvxposoffset
= temp
;
4042 } else if(!strnicmp(this_opt
, "tvyposoffset:", 13)) {
4044 temp
= (int)simple_strtol(this_opt
+ 13, NULL
, 0);
4045 if((temp
>= -32) && (temp
<= 32)) {
4046 sisfb_tvyposoffset
= temp
;
4048 } else if(!strnicmp(this_opt
, "specialtiming:", 14)) {
4049 sisfb_search_specialtiming(this_opt
+ 14);
4050 } else if(!strnicmp(this_opt
, "lvdshl:", 7)) {
4052 temp
= simple_strtoul(this_opt
+ 7, NULL
, 0);
4053 if((temp
>= 0) && (temp
<= 3)) {
4054 sisfb_lvdshl
= temp
;
4056 } else if(this_opt
[0] >= '0' && this_opt
[0] <= '9') {
4057 sisfb_search_mode(this_opt
, true);
4058 #if !defined(__i386__) && !defined(__x86_64__)
4059 } else if(!strnicmp(this_opt
, "resetcard", 9)) {
4060 sisfb_resetcard
= 1;
4061 } else if(!strnicmp(this_opt
, "videoram:", 9)) {
4062 sisfb_videoram
= simple_strtoul(this_opt
+ 9, NULL
, 0);
4065 printk(KERN_INFO
"sisfb: Invalid option %s\n", this_opt
);
4074 static int __devinit
4075 sisfb_check_rom(void __iomem
*rom_base
, struct sis_video_info
*ivideo
)
4080 if((readb(rom_base
) != 0x55) || (readb(rom_base
+ 1) != 0xaa))
4083 romptr
= (readb(rom_base
+ 0x18) | (readb(rom_base
+ 0x19) << 8));
4084 if(romptr
> (0x10000 - 8))
4087 rom
= rom_base
+ romptr
;
4089 if((readb(rom
) != 'P') || (readb(rom
+ 1) != 'C') ||
4090 (readb(rom
+ 2) != 'I') || (readb(rom
+ 3) != 'R'))
4093 if((readb(rom
+ 4) | (readb(rom
+ 5) << 8)) != ivideo
->chip_vendor
)
4096 if((readb(rom
+ 6) | (readb(rom
+ 7) << 8)) != ivideo
->chip_id
)
4102 static unsigned char * __devinit
4103 sisfb_find_rom(struct pci_dev
*pdev
)
4105 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4106 void __iomem
*rom_base
;
4107 unsigned char *myrombase
= NULL
;
4110 /* First, try the official pci ROM functions (except
4111 * on integrated chipsets which have no ROM).
4114 if(!ivideo
->nbridge
) {
4116 if((rom_base
= pci_map_rom(pdev
, &romsize
))) {
4118 if(sisfb_check_rom(rom_base
, ivideo
)) {
4120 if((myrombase
= vmalloc(65536))) {
4121 memcpy_fromio(myrombase
, rom_base
,
4122 (romsize
> 65536) ? 65536 : romsize
);
4125 pci_unmap_rom(pdev
, rom_base
);
4129 if(myrombase
) return myrombase
;
4131 /* Otherwise do it the conventional way. */
4133 #if defined(__i386__) || defined(__x86_64__)
4137 for (temp
= 0x000c0000; temp
< 0x000f0000; temp
+= 0x00001000) {
4139 rom_base
= ioremap(temp
, 65536);
4143 if (!sisfb_check_rom(rom_base
, ivideo
)) {
4148 if ((myrombase
= vmalloc(65536)))
4149 memcpy_fromio(myrombase
, rom_base
, 65536);
4162 static void __devinit
4163 sisfb_post_map_vram(struct sis_video_info
*ivideo
, unsigned int *mapsize
,
4166 if (*mapsize
< (min
<< 20))
4169 ivideo
->video_vbase
= ioremap(ivideo
->video_base
, (*mapsize
));
4171 if(!ivideo
->video_vbase
) {
4173 "sisfb: Unable to map maximum video RAM for size detection\n");
4175 while((!(ivideo
->video_vbase
= ioremap(ivideo
->video_base
, (*mapsize
))))) {
4177 if((*mapsize
) < (min
<< 20))
4180 if(ivideo
->video_vbase
) {
4182 "sisfb: Video RAM size detection limited to %dMB\n",
4183 (int)((*mapsize
) >> 20));
4188 #ifdef CONFIG_FB_SIS_300
4189 static int __devinit
4190 sisfb_post_300_buswidth(struct sis_video_info
*ivideo
)
4192 void __iomem
*FBAddress
= ivideo
->video_vbase
;
4193 unsigned short temp
;
4197 andSISIDXREG(SISSR
, 0x15, 0xFB);
4198 SiS_SetRegOR(SISSR
, 0x15, 0x04);
4199 SiS_SetReg(SISSR
, 0x13, 0x00);
4200 SiS_SetReg(SISSR
, 0x14, 0xBF);
4202 for(i
= 0; i
< 2; i
++) {
4204 for(j
= 0; j
< 4; j
++) {
4205 writew(temp
, FBAddress
);
4206 if(readw(FBAddress
) == temp
)
4208 SiS_SetRegOR(SISSR
, 0x3c, 0x01);
4209 reg
= SiS_GetReg(SISSR
, 0x05);
4210 reg
= SiS_GetReg(SISSR
, 0x05);
4211 andSISIDXREG(SISSR
, 0x3c, 0xfe);
4212 reg
= SiS_GetReg(SISSR
, 0x05);
4213 reg
= SiS_GetReg(SISSR
, 0x05);
4218 writel(0x01234567L
, FBAddress
);
4219 writel(0x456789ABL
, (FBAddress
+ 4));
4220 writel(0x89ABCDEFL
, (FBAddress
+ 8));
4221 writel(0xCDEF0123L
, (FBAddress
+ 12));
4223 reg
= SiS_GetReg(SISSR
, 0x3b);
4225 if(readl((FBAddress
+ 12)) == 0xCDEF0123L
)
4226 return 4; /* Channel A 128bit */
4229 if(readl((FBAddress
+ 4)) == 0x456789ABL
)
4230 return 2; /* Channel B 64bit */
4232 return 1; /* 32bit */
4235 static int __devinit
4236 sisfb_post_300_rwtest(struct sis_video_info
*ivideo
, int iteration
, int buswidth
,
4237 int PseudoRankCapacity
, int PseudoAdrPinCount
,
4238 unsigned int mapsize
)
4240 void __iomem
*FBAddr
= ivideo
->video_vbase
;
4241 unsigned short sr14
;
4242 unsigned int k
, RankCapacity
, PageCapacity
, BankNumHigh
, BankNumMid
;
4243 unsigned int PhysicalAdrOtherPage
, PhysicalAdrHigh
, PhysicalAdrHalfPage
;
4244 static const unsigned short SiS_DRAMType
[17][5] = {
4245 {0x0C,0x0A,0x02,0x40,0x39},
4246 {0x0D,0x0A,0x01,0x40,0x48},
4247 {0x0C,0x09,0x02,0x20,0x35},
4248 {0x0D,0x09,0x01,0x20,0x44},
4249 {0x0C,0x08,0x02,0x10,0x31},
4250 {0x0D,0x08,0x01,0x10,0x40},
4251 {0x0C,0x0A,0x01,0x20,0x34},
4252 {0x0C,0x09,0x01,0x08,0x32},
4253 {0x0B,0x08,0x02,0x08,0x21},
4254 {0x0C,0x08,0x01,0x08,0x30},
4255 {0x0A,0x08,0x02,0x04,0x11},
4256 {0x0B,0x0A,0x01,0x10,0x28},
4257 {0x09,0x08,0x02,0x02,0x01},
4258 {0x0B,0x09,0x01,0x08,0x24},
4259 {0x0B,0x08,0x01,0x04,0x20},
4260 {0x0A,0x08,0x01,0x02,0x10},
4261 {0x09,0x08,0x01,0x01,0x00}
4264 for(k
= 0; k
<= 16; k
++) {
4266 RankCapacity
= buswidth
* SiS_DRAMType
[k
][3];
4268 if(RankCapacity
!= PseudoRankCapacity
)
4271 if((SiS_DRAMType
[k
][2] + SiS_DRAMType
[k
][0]) > PseudoAdrPinCount
)
4274 BankNumHigh
= RankCapacity
* 16 * iteration
- 1;
4275 if(iteration
== 3) { /* Rank No */
4276 BankNumMid
= RankCapacity
* 16 - 1;
4278 BankNumMid
= RankCapacity
* 16 * iteration
/ 2 - 1;
4281 PageCapacity
= (1 << SiS_DRAMType
[k
][1]) * buswidth
* 4;
4282 PhysicalAdrHigh
= BankNumHigh
;
4283 PhysicalAdrHalfPage
= (PageCapacity
/ 2 + PhysicalAdrHigh
) % PageCapacity
;
4284 PhysicalAdrOtherPage
= PageCapacity
* SiS_DRAMType
[k
][2] + PhysicalAdrHigh
;
4286 andSISIDXREG(SISSR
, 0x15, 0xFB); /* Test */
4287 SiS_SetRegOR(SISSR
, 0x15, 0x04); /* Test */
4288 sr14
= (SiS_DRAMType
[k
][3] * buswidth
) - 1;
4289 if(buswidth
== 4) sr14
|= 0x80;
4290 else if(buswidth
== 2) sr14
|= 0x40;
4291 SiS_SetReg(SISSR
, 0x13, SiS_DRAMType
[k
][4]);
4292 SiS_SetReg(SISSR
, 0x14, sr14
);
4297 if((BankNumHigh
+ PhysicalAdrHigh
>= mapsize
) ||
4298 (BankNumMid
+ PhysicalAdrHigh
>= mapsize
) ||
4299 (BankNumHigh
+ PhysicalAdrHalfPage
>= mapsize
) ||
4300 (BankNumHigh
+ PhysicalAdrOtherPage
>= mapsize
))
4304 writew(((unsigned short)PhysicalAdrHigh
),
4305 (FBAddr
+ BankNumHigh
+ PhysicalAdrHigh
));
4306 writew(((unsigned short)BankNumMid
),
4307 (FBAddr
+ BankNumMid
+ PhysicalAdrHigh
));
4308 writew(((unsigned short)PhysicalAdrHalfPage
),
4309 (FBAddr
+ BankNumHigh
+ PhysicalAdrHalfPage
));
4310 writew(((unsigned short)PhysicalAdrOtherPage
),
4311 (FBAddr
+ BankNumHigh
+ PhysicalAdrOtherPage
));
4314 if(readw(FBAddr
+ BankNumHigh
+ PhysicalAdrHigh
) == PhysicalAdrHigh
)
4321 static void __devinit
4322 sisfb_post_300_ramsize(struct pci_dev
*pdev
, unsigned int mapsize
)
4324 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4326 int PseudoRankCapacity
, PseudoAdrPinCount
;
4328 buswidth
= sisfb_post_300_buswidth(ivideo
);
4330 for(i
= 6; i
>= 0; i
--) {
4331 PseudoRankCapacity
= 1 << i
;
4332 for(j
= 4; j
>= 1; j
--) {
4333 PseudoAdrPinCount
= 15 - j
;
4334 if((PseudoRankCapacity
* j
) <= 64) {
4335 if(sisfb_post_300_rwtest(ivideo
,
4347 static void __devinit
4348 sisfb_post_sis300(struct pci_dev
*pdev
)
4350 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4351 unsigned char *bios
= ivideo
->SiS_Pr
.VirtualRomBase
;
4352 u8 reg
, v1
, v2
, v3
, v4
, v5
, v6
, v7
, v8
;
4353 u16 index
, rindex
, memtype
= 0;
4354 unsigned int mapsize
;
4356 if(!ivideo
->SiS_Pr
.UseROM
)
4359 SiS_SetReg(SISSR
, 0x05, 0x86);
4362 if(bios
[0x52] & 0x80) {
4363 memtype
= bios
[0x52];
4365 memtype
= SiS_GetReg(SISSR
, 0x3a);
4370 v3
= 0x80; v6
= 0x80;
4371 if(ivideo
->revision_id
<= 0x13) {
4372 v1
= 0x44; v2
= 0x42;
4373 v4
= 0x44; v5
= 0x42;
4375 v1
= 0x68; v2
= 0x43; /* Assume 125Mhz MCLK */
4376 v4
= 0x68; v5
= 0x43; /* Assume 125Mhz ECLK */
4378 index
= memtype
* 5;
4379 rindex
= index
+ 0x54;
4380 v1
= bios
[rindex
++];
4381 v2
= bios
[rindex
++];
4382 v3
= bios
[rindex
++];
4383 rindex
= index
+ 0x7c;
4384 v4
= bios
[rindex
++];
4385 v5
= bios
[rindex
++];
4386 v6
= bios
[rindex
++];
4389 SiS_SetReg(SISSR
, 0x28, v1
);
4390 SiS_SetReg(SISSR
, 0x29, v2
);
4391 SiS_SetReg(SISSR
, 0x2a, v3
);
4392 SiS_SetReg(SISSR
, 0x2e, v4
);
4393 SiS_SetReg(SISSR
, 0x2f, v5
);
4394 SiS_SetReg(SISSR
, 0x30, v6
);
4399 SiS_SetReg(SISSR
, 0x07, v1
); /* DAC speed */
4401 SiS_SetReg(SISSR
, 0x11, 0x0f); /* DDC, power save */
4403 v1
= 0x01; v2
= 0x43; v3
= 0x1e; v4
= 0x2a;
4404 v5
= 0x06; v6
= 0x00; v7
= 0x00; v8
= 0x00;
4408 v2
= bios
[memtype
+ 8];
4409 v3
= bios
[memtype
+ 16];
4410 v4
= bios
[memtype
+ 24];
4411 v5
= bios
[memtype
+ 32];
4412 v6
= bios
[memtype
+ 40];
4413 v7
= bios
[memtype
+ 48];
4414 v8
= bios
[memtype
+ 56];
4416 if(ivideo
->revision_id
>= 0x80)
4418 SiS_SetReg(SISSR
, 0x15, v1
); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4419 SiS_SetReg(SISSR
, 0x16, v2
);
4420 SiS_SetReg(SISSR
, 0x17, v3
);
4421 SiS_SetReg(SISSR
, 0x18, v4
);
4422 SiS_SetReg(SISSR
, 0x19, v5
);
4423 SiS_SetReg(SISSR
, 0x1a, v6
);
4424 SiS_SetReg(SISSR
, 0x1b, v7
);
4425 SiS_SetReg(SISSR
, 0x1c, v8
); /* ---- */
4426 andSISIDXREG(SISSR
, 0x15 ,0xfb);
4427 SiS_SetRegOR(SISSR
, 0x15, 0x04);
4429 if(bios
[0x53] & 0x02) {
4430 SiS_SetRegOR(SISSR
, 0x19, 0x20);
4433 v1
= 0x04; /* DAC pedestal (BIOS 0xe5) */
4434 if(ivideo
->revision_id
>= 0x80)
4436 SiS_SetReg(SISSR
, 0x1f, v1
);
4437 SiS_SetReg(SISSR
, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
4438 v1
= 0xf6; v2
= 0x0d; v3
= 0x00;
4444 SiS_SetReg(SISSR
, 0x23, v1
);
4445 SiS_SetReg(SISSR
, 0x24, v2
);
4446 SiS_SetReg(SISSR
, 0x25, v3
);
4447 SiS_SetReg(SISSR
, 0x21, 0x84);
4448 SiS_SetReg(SISSR
, 0x22, 0x00);
4449 SiS_SetReg(SISCR
, 0x37, 0x00);
4450 SiS_SetRegOR(SISPART1
, 0x24, 0x01); /* unlock crt2 */
4451 SiS_SetReg(SISPART1
, 0x00, 0x00);
4452 v1
= 0x40; v2
= 0x11;
4457 SiS_SetReg(SISPART1
, 0x02, v1
);
4459 if(ivideo
->revision_id
>= 0x80)
4462 reg
= SiS_GetReg(SISPART4
, 0x00);
4463 if((reg
== 1) || (reg
== 2)) {
4464 SiS_SetReg(SISCR
, 0x37, 0x02);
4465 SiS_SetReg(SISPART2
, 0x00, 0x1c);
4466 v4
= 0x00; v5
= 0x00; v6
= 0x10;
4467 if(ivideo
->SiS_Pr
.UseROM
) {
4472 SiS_SetReg(SISPART4
, 0x0d, v4
);
4473 SiS_SetReg(SISPART4
, 0x0e, v5
);
4474 SiS_SetReg(SISPART4
, 0x10, v6
);
4475 SiS_SetReg(SISPART4
, 0x0f, 0x3f);
4476 reg
= SiS_GetReg(SISPART4
, 0x01);
4478 reg
= SiS_GetReg(SISPART4
, 0x23);
4481 SiS_SetReg(SISPART4
, 0x23, reg
);
4486 SiS_SetReg(SISSR
, 0x32, v2
);
4488 andSISIDXREG(SISPART1
, 0x24, 0xfe); /* Lock CRT2 */
4490 reg
= SiS_GetReg(SISSR
, 0x16);
4492 SiS_SetReg(SISCR
, 0x35, reg
);
4493 SiS_SetReg(SISCR
, 0x83, 0x00);
4494 #if !defined(__i386__) && !defined(__x86_64__)
4495 if(sisfb_videoram
) {
4496 SiS_SetReg(SISSR
, 0x13, 0x28); /* ? */
4497 reg
= ((sisfb_videoram
>> 10) - 1) | 0x40;
4498 SiS_SetReg(SISSR
, 0x14, reg
);
4501 /* Need to map max FB size for finding out about RAM size */
4502 mapsize
= ivideo
->video_size
;
4503 sisfb_post_map_vram(ivideo
, &mapsize
, 4);
4505 if(ivideo
->video_vbase
) {
4506 sisfb_post_300_ramsize(pdev
, mapsize
);
4507 iounmap(ivideo
->video_vbase
);
4510 "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4511 SiS_SetReg(SISSR
, 0x13, 0x28); /* ? */
4512 SiS_SetReg(SISSR
, 0x14, 0x47); /* 8MB, 64bit default */
4514 #if !defined(__i386__) && !defined(__x86_64__)
4521 reg
= SiS_GetReg(SISSR
, 0x3a);
4522 if((reg
& 0x30) == 0x30) {
4523 v1
= 0x04; /* PCI */
4526 v1
= 0x14; /* AGP */
4530 SiS_SetReg(SISSR
, 0x21, v1
);
4531 SiS_SetReg(SISSR
, 0x22, v2
);
4534 sisfb_sense_crt1(ivideo
);
4536 /* Set default mode, don't clear screen */
4537 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
4538 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
4539 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
4540 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
4541 ivideo
->SiS_Pr
.VideoMemorySize
= 8 << 20;
4542 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
4544 SiS_SetReg(SISSR
, 0x05, 0x86);
4547 SiS_SetRegOR(SISSR
, 0x01, 0x20);
4549 /* Save mode number in CR34 */
4550 SiS_SetReg(SISCR
, 0x34, 0x2e);
4552 /* Let everyone know what the current mode is */
4553 ivideo
->modeprechange
= 0x2e;
4557 #ifdef CONFIG_FB_SIS_315
4559 static void __devinit
4560 sisfb_post_sis315330(struct pci_dev
*pdev
)
4566 static void __devinit
4567 sisfb_post_xgi_delay(struct sis_video_info
*ivideo
, int delay
)
4572 for(i
= 0; i
<= (delay
* 10 * 36); i
++) {
4573 reg
= SiS_GetReg(SISSR
, 0x05);
4578 static int __devinit
4579 sisfb_find_host_bridge(struct sis_video_info
*ivideo
, struct pci_dev
*mypdev
,
4580 unsigned short pcivendor
)
4582 struct pci_dev
*pdev
= NULL
;
4583 unsigned short temp
;
4586 while((pdev
= pci_get_class(PCI_CLASS_BRIDGE_HOST
, pdev
))) {
4587 temp
= pdev
->vendor
;
4588 if(temp
== pcivendor
) {
4598 static int __devinit
4599 sisfb_post_xgi_rwtest(struct sis_video_info
*ivideo
, int starta
,
4600 unsigned int enda
, unsigned int mapsize
)
4605 writel(0, ivideo
->video_vbase
);
4607 for(i
= starta
; i
<= enda
; i
++) {
4610 writel(pos
, ivideo
->video_vbase
+ pos
);
4613 sisfb_post_xgi_delay(ivideo
, 150);
4615 if(readl(ivideo
->video_vbase
) != 0)
4618 for(i
= starta
; i
<= enda
; i
++) {
4621 if(readl(ivideo
->video_vbase
+ pos
) != pos
)
4630 static void __devinit
4631 sisfb_post_xgi_ramsize(struct sis_video_info
*ivideo
)
4633 unsigned int buswidth
, ranksize
, channelab
, mapsize
;
4636 static const u8 dramsr13
[12 * 5] = {
4637 0x02, 0x0e, 0x0b, 0x80, 0x5d,
4638 0x02, 0x0e, 0x0a, 0x40, 0x59,
4639 0x02, 0x0d, 0x0b, 0x40, 0x4d,
4640 0x02, 0x0e, 0x09, 0x20, 0x55,
4641 0x02, 0x0d, 0x0a, 0x20, 0x49,
4642 0x02, 0x0c, 0x0b, 0x20, 0x3d,
4643 0x02, 0x0e, 0x08, 0x10, 0x51,
4644 0x02, 0x0d, 0x09, 0x10, 0x45,
4645 0x02, 0x0c, 0x0a, 0x10, 0x39,
4646 0x02, 0x0d, 0x08, 0x08, 0x41,
4647 0x02, 0x0c, 0x09, 0x08, 0x35,
4648 0x02, 0x0c, 0x08, 0x04, 0x31
4650 static const u8 dramsr13_4
[4 * 5] = {
4651 0x02, 0x0d, 0x09, 0x40, 0x45,
4652 0x02, 0x0c, 0x09, 0x20, 0x35,
4653 0x02, 0x0c, 0x08, 0x10, 0x31,
4654 0x02, 0x0b, 0x08, 0x08, 0x21
4657 /* Enable linear mode, disable 0xa0000 address decoding */
4658 /* We disable a0000 address decoding, because
4659 * - if running on x86, if the card is disabled, it means
4660 * that another card is in the system. We don't want
4661 * to interphere with that primary card's textmode.
4662 * - if running on non-x86, there usually is no VGA window
4665 SiS_SetRegOR(SISSR
, 0x20, (0x80 | 0x04));
4667 /* Need to map max FB size for finding out about RAM size */
4668 mapsize
= ivideo
->video_size
;
4669 sisfb_post_map_vram(ivideo
, &mapsize
, 32);
4671 if(!ivideo
->video_vbase
) {
4672 printk(KERN_ERR
"sisfb: Unable to detect RAM size. Setting default.\n");
4673 SiS_SetReg(SISSR
, 0x13, 0x35);
4674 SiS_SetReg(SISSR
, 0x14, 0x41);
4679 /* Non-interleaving */
4680 SiS_SetReg(SISSR
, 0x15, 0x00);
4682 SiS_SetReg(SISSR
, 0x1c, 0x00);
4684 if(ivideo
->chip
== XGI_20
) {
4687 reg
= SiS_GetReg(SISCR
, 0x97);
4688 if(!(reg
& 0x01)) { /* Single 32/16 */
4690 SiS_SetReg(SISSR
, 0x13, 0xb1);
4691 SiS_SetReg(SISSR
, 0x14, 0x52);
4692 sisfb_post_xgi_delay(ivideo
, 1);
4694 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4697 SiS_SetReg(SISSR
, 0x13, 0x31);
4698 SiS_SetReg(SISSR
, 0x14, 0x42);
4699 sisfb_post_xgi_delay(ivideo
, 1);
4700 if(sisfb_post_xgi_rwtest(ivideo
, 23, 23, mapsize
))
4704 SiS_SetReg(SISSR
, 0x13, 0xb1);
4705 SiS_SetReg(SISSR
, 0x14, 0x41);
4706 sisfb_post_xgi_delay(ivideo
, 1);
4708 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4711 SiS_SetReg(SISSR
, 0x13, 0x31);
4712 } else { /* Dual 16/8 */
4714 SiS_SetReg(SISSR
, 0x13, 0xb1);
4715 SiS_SetReg(SISSR
, 0x14, 0x41);
4716 sisfb_post_xgi_delay(ivideo
, 1);
4718 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4721 SiS_SetReg(SISSR
, 0x13, 0x31);
4722 SiS_SetReg(SISSR
, 0x14, 0x31);
4723 sisfb_post_xgi_delay(ivideo
, 1);
4724 if(sisfb_post_xgi_rwtest(ivideo
, 22, 22, mapsize
))
4728 SiS_SetReg(SISSR
, 0x13, 0xb1);
4729 SiS_SetReg(SISSR
, 0x14, 0x30);
4730 sisfb_post_xgi_delay(ivideo
, 1);
4732 if(sisfb_post_xgi_rwtest(ivideo
, 21, 22, mapsize
))
4735 SiS_SetReg(SISSR
, 0x13, 0x31);
4738 } else { /* XGI_40 */
4740 reg
= SiS_GetReg(SISCR
, 0x97);
4742 reg
= SiS_GetReg(SISSR
, 0x39);
4746 if(reg
& 0x01) { /* DDRII */
4748 if(ivideo
->revision_id
== 2) {
4750 SiS_SetReg(SISSR
, 0x13, 0xa1);
4751 SiS_SetReg(SISSR
, 0x14, 0x44);
4753 sisfb_post_xgi_delay(ivideo
, 1);
4754 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4757 SiS_SetReg(SISSR
, 0x13, 0x21);
4758 SiS_SetReg(SISSR
, 0x14, 0x34);
4759 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4763 SiS_SetReg(SISSR
, 0x13, 0xa1);
4764 SiS_SetReg(SISSR
, 0x14, 0x40);
4766 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4769 SiS_SetReg(SISSR
, 0x13, 0x21);
4770 SiS_SetReg(SISSR
, 0x14, 0x30);
4773 SiS_SetReg(SISSR
, 0x13, 0xa1);
4774 SiS_SetReg(SISSR
, 0x14, 0x4c);
4776 sisfb_post_xgi_delay(ivideo
, 1);
4777 if(sisfb_post_xgi_rwtest(ivideo
, 23, 25, mapsize
))
4781 SiS_SetReg(SISSR
, 0x14, 0x48);
4782 sisfb_post_xgi_delay(ivideo
, 1);
4784 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4787 SiS_SetReg(SISSR
, 0x13, 0x21);
4788 SiS_SetReg(SISSR
, 0x14, 0x3c);
4791 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
)) {
4795 SiS_SetReg(SISSR
, 0x14, 0x38);
4799 sisfb_post_xgi_delay(ivideo
, 1);
4804 if(ivideo
->revision_id
== 2) {
4806 SiS_SetReg(SISSR
, 0x13, 0xa1);
4807 SiS_SetReg(SISSR
, 0x14, 0x52);
4808 sisfb_post_xgi_delay(ivideo
, 1);
4810 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4813 SiS_SetReg(SISSR
, 0x13, 0x21);
4814 SiS_SetReg(SISSR
, 0x14, 0x42);
4817 SiS_SetReg(SISSR
, 0x13, 0xa1);
4818 SiS_SetReg(SISSR
, 0x14, 0x5a);
4819 sisfb_post_xgi_delay(ivideo
, 1);
4821 if(sisfb_post_xgi_rwtest(ivideo
, 24, 25, mapsize
))
4824 SiS_SetReg(SISSR
, 0x13, 0x21);
4825 SiS_SetReg(SISSR
, 0x14, 0x4a);
4827 sisfb_post_xgi_delay(ivideo
, 1);
4833 setSISIDXREG(SISSR
, 0x14, 0xf0, sr14
);
4834 sisfb_post_xgi_delay(ivideo
, 1);
4836 j
= (ivideo
->chip
== XGI_20
) ? 5 : 9;
4837 k
= (ivideo
->chip
== XGI_20
) ? 12 : 4;
4839 for(i
= 0; i
< k
; i
++) {
4841 reg
= (ivideo
->chip
== XGI_20
) ?
4842 dramsr13
[(i
* 5) + 4] : dramsr13_4
[(i
* 5) + 4];
4843 setSISIDXREG(SISSR
, 0x13, 0x80, reg
);
4844 sisfb_post_xgi_delay(ivideo
, 50);
4846 ranksize
= (ivideo
->chip
== XGI_20
) ?
4847 dramsr13
[(i
* 5) + 3] : dramsr13_4
[(i
* 5) + 3];
4849 reg
= SiS_GetReg(SISSR
, 0x13);
4850 if(reg
& 0x80) ranksize
<<= 1;
4852 if(ivideo
->chip
== XGI_20
) {
4853 if(buswidth
== 16) ranksize
<<= 1;
4854 else if(buswidth
== 32) ranksize
<<= 2;
4856 if(buswidth
== 64) ranksize
<<= 1;
4862 if((ranksize
* l
) <= 256) {
4863 while((ranksize
>>= 1)) reg
+= 0x10;
4868 setSISIDXREG(SISSR
, 0x14, 0x0f, (reg
& 0xf0));
4869 sisfb_post_xgi_delay(ivideo
, 1);
4871 if(sisfb_post_xgi_rwtest(ivideo
, j
, ((reg
>> 4) + channelab
- 2 + 20), mapsize
))
4875 iounmap(ivideo
->video_vbase
);
4878 static void __devinit
4879 sisfb_post_xgi_setclocks(struct sis_video_info
*ivideo
, u8 regb
)
4883 static const u8 cs90
[8 * 3] = {
4893 static const u8 csb8
[8 * 3] = {
4907 v1
= cs90
[index
]; v2
= cs90
[index
+ 1]; v3
= cs90
[index
+ 2];
4908 if(ivideo
->haveXGIROM
) {
4909 v1
= ivideo
->bios_abase
[0x90 + index
];
4910 v2
= ivideo
->bios_abase
[0x90 + index
+ 1];
4911 v3
= ivideo
->bios_abase
[0x90 + index
+ 2];
4913 SiS_SetReg(SISSR
, 0x28, v1
);
4914 SiS_SetReg(SISSR
, 0x29, v2
);
4915 SiS_SetReg(SISSR
, 0x2a, v3
);
4916 sisfb_post_xgi_delay(ivideo
, 0x43);
4917 sisfb_post_xgi_delay(ivideo
, 0x43);
4918 sisfb_post_xgi_delay(ivideo
, 0x43);
4920 v1
= csb8
[index
]; v2
= csb8
[index
+ 1]; v3
= csb8
[index
+ 2];
4921 if(ivideo
->haveXGIROM
) {
4922 v1
= ivideo
->bios_abase
[0xb8 + index
];
4923 v2
= ivideo
->bios_abase
[0xb8 + index
+ 1];
4924 v3
= ivideo
->bios_abase
[0xb8 + index
+ 2];
4926 SiS_SetReg(SISSR
, 0x2e, v1
);
4927 SiS_SetReg(SISSR
, 0x2f, v2
);
4928 SiS_SetReg(SISSR
, 0x30, v3
);
4929 sisfb_post_xgi_delay(ivideo
, 0x43);
4930 sisfb_post_xgi_delay(ivideo
, 0x43);
4931 sisfb_post_xgi_delay(ivideo
, 0x43);
4934 static int __devinit
4935 sisfb_post_xgi(struct pci_dev
*pdev
)
4937 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4938 unsigned char *bios
= ivideo
->bios_abase
;
4939 struct pci_dev
*mypdev
= NULL
;
4940 const u8
*ptr
, *ptr2
;
4941 u8 v1
, v2
, v3
, v4
, v5
, reg
, ramtype
;
4942 u32 rega
, regb
, regd
;
4944 static const u8 cs78
[3] = { 0xf6, 0x0d, 0x00 };
4945 static const u8 cs76
[2] = { 0xa3, 0xfb };
4946 static const u8 cs7b
[3] = { 0xc0, 0x11, 0x00 };
4947 static const u8 cs158
[8] = {
4948 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
4950 static const u8 cs160
[8] = {
4951 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
4953 static const u8 cs168
[8] = {
4954 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
4956 static const u8 cs128
[3 * 8] = {
4957 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
4958 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
4959 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
4961 static const u8 cs148
[2 * 8] = {
4962 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
4963 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4965 static const u8 cs31a
[8 * 4] = {
4966 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
4967 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
4968 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4969 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4971 static const u8 cs33a
[8 * 4] = {
4972 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4973 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4974 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4975 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4977 static const u8 cs45a
[8 * 2] = {
4978 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
4979 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4981 static const u8 cs170
[7 * 8] = {
4982 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
4983 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
4984 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
4985 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
4986 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
4987 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
4988 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
4990 static const u8 cs1a8
[3 * 8] = {
4991 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
4992 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
4993 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4995 static const u8 cs100
[2 * 8] = {
4996 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
4997 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5001 reg
= SiS_GetRegByte(SISVGAENABLE
) | 0x01;
5002 SiS_SetRegByte(SISVGAENABLE
, reg
);
5005 reg
= SiS_GetRegByte(SISMISCR
) | 0x01;
5006 SiS_SetRegByte(SISMISCW
, reg
);
5009 SiS_SetReg(SISSR
, 0x05, 0x86);
5010 reg
= SiS_GetReg(SISSR
, 0x05);
5014 /* Clear some regs */
5015 for(i
= 0; i
< 0x22; i
++) {
5016 if(0x06 + i
== 0x20) continue;
5017 SiS_SetReg(SISSR
, 0x06 + i
, 0x00);
5019 for(i
= 0; i
< 0x0b; i
++) {
5020 SiS_SetReg(SISSR
, 0x31 + i
, 0x00);
5022 for(i
= 0; i
< 0x10; i
++) {
5023 SiS_SetReg(SISCR
, 0x30 + i
, 0x00);
5027 if(ivideo
->haveXGIROM
) {
5028 ptr
= (const u8
*)&bios
[0x78];
5030 for(i
= 0; i
< 3; i
++) {
5031 SiS_SetReg(SISSR
, 0x23 + i
, ptr
[i
]);
5035 if(ivideo
->haveXGIROM
) {
5036 ptr
= (const u8
*)&bios
[0x76];
5038 for(i
= 0; i
< 2; i
++) {
5039 SiS_SetReg(SISSR
, 0x21 + i
, ptr
[i
]);
5042 v1
= 0x18; v2
= 0x00;
5043 if(ivideo
->haveXGIROM
) {
5047 SiS_SetReg(SISSR
, 0x07, v1
);
5048 SiS_SetReg(SISSR
, 0x11, 0x0f);
5049 SiS_SetReg(SISSR
, 0x1f, v2
);
5050 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5051 SiS_SetReg(SISSR
, 0x20, 0x80 | 0x20 | 0x04);
5052 SiS_SetReg(SISSR
, 0x27, 0x74);
5055 if(ivideo
->haveXGIROM
) {
5056 ptr
= (const u8
*)&bios
[0x7b];
5058 for(i
= 0; i
< 3; i
++) {
5059 SiS_SetReg(SISSR
, 0x31 + i
, ptr
[i
]);
5062 if(ivideo
->chip
== XGI_40
) {
5063 if(ivideo
->revision_id
== 2) {
5064 setSISIDXREG(SISSR
, 0x3b, 0x3f, 0xc0);
5066 SiS_SetReg(SISCR
, 0x7d, 0xfe);
5067 SiS_SetReg(SISCR
, 0x7e, 0x0f);
5069 if(ivideo
->revision_id
== 0) { /* 40 *and* 20? */
5070 andSISIDXREG(SISCR
, 0x58, 0xd7);
5071 reg
= SiS_GetReg(SISCR
, 0xcb);
5073 setSISIDXREG(SISCR
, 0x58, 0xd7, (reg
& 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5077 reg
= (ivideo
->chip
== XGI_40
) ? 0x20 : 0x00;
5078 setSISIDXREG(SISCR
, 0x38, 0x1f, reg
);
5080 if(ivideo
->chip
== XGI_20
) {
5081 SiS_SetReg(SISSR
, 0x36, 0x70);
5083 SiS_SetReg(SISVID
, 0x00, 0x86);
5084 SiS_SetReg(SISVID
, 0x32, 0x00);
5085 SiS_SetReg(SISVID
, 0x30, 0x00);
5086 SiS_SetReg(SISVID
, 0x32, 0x01);
5087 SiS_SetReg(SISVID
, 0x30, 0x00);
5088 andSISIDXREG(SISVID
, 0x2f, 0xdf);
5089 andSISIDXREG(SISCAP
, 0x00, 0x3f);
5091 SiS_SetReg(SISPART1
, 0x2f, 0x01);
5092 SiS_SetReg(SISPART1
, 0x00, 0x00);
5093 SiS_SetReg(SISPART1
, 0x02, bios
[0x7e]);
5094 SiS_SetReg(SISPART1
, 0x2e, 0x08);
5095 andSISIDXREG(SISPART1
, 0x35, 0x7f);
5096 andSISIDXREG(SISPART1
, 0x50, 0xfe);
5098 reg
= SiS_GetReg(SISPART4
, 0x00);
5099 if(reg
== 1 || reg
== 2) {
5100 SiS_SetReg(SISPART2
, 0x00, 0x1c);
5101 SiS_SetReg(SISPART4
, 0x0d, bios
[0x7f]);
5102 SiS_SetReg(SISPART4
, 0x0e, bios
[0x80]);
5103 SiS_SetReg(SISPART4
, 0x10, bios
[0x81]);
5104 andSISIDXREG(SISPART4
, 0x0f, 0x3f);
5106 reg
= SiS_GetReg(SISPART4
, 0x01);
5107 if((reg
& 0xf0) >= 0xb0) {
5108 reg
= SiS_GetReg(SISPART4
, 0x23);
5109 if(reg
& 0x20) reg
|= 0x40;
5110 SiS_SetReg(SISPART4
, 0x23, reg
);
5111 reg
= (reg
& 0x20) ? 0x02 : 0x00;
5112 setSISIDXREG(SISPART1
, 0x1e, 0xfd, reg
);
5118 reg
= SiS_GetReg(SISSR
, 0x3b);
5120 reg
= SiS_GetReg(SISSR
, 0x3a);
5121 v2
= (reg
& 0x30) >> 3;
5122 if(!(v2
& 0x04)) v2
^= 0x02;
5123 reg
= SiS_GetReg(SISSR
, 0x39);
5124 if(reg
& 0x80) v2
|= 0x80;
5127 if((mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0730, NULL
))) {
5128 pci_dev_put(mypdev
);
5129 if(((v2
& 0x06) == 2) || ((v2
& 0x06) == 4))
5134 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0735, NULL
);
5136 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0645, NULL
);
5138 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0650, NULL
);
5140 pci_read_config_dword(mypdev
, 0x94, ®d
);
5142 pci_write_config_dword(mypdev
, 0x94, regd
);
5144 pci_dev_put(mypdev
);
5145 } else if(sisfb_find_host_bridge(ivideo
, pdev
, PCI_VENDOR_ID_SI
)) {
5147 } else if(sisfb_find_host_bridge(ivideo
, pdev
, 0x1106) ||
5148 sisfb_find_host_bridge(ivideo
, pdev
, 0x1022) ||
5149 sisfb_find_host_bridge(ivideo
, pdev
, 0x700e) ||
5150 sisfb_find_host_bridge(ivideo
, pdev
, 0x10de)) {
5151 if((v2
& 0x06) == 4)
5156 setSISIDXREG(SISCR
, 0x5f, 0xf0, v2
);
5158 SiS_SetReg(SISSR
, 0x22, v1
);
5160 if(ivideo
->revision_id
== 2) {
5161 v1
= SiS_GetReg(SISSR
, 0x3b);
5162 v2
= SiS_GetReg(SISSR
, 0x3a);
5163 regd
= bios
[0x90 + 3] | (bios
[0x90 + 4] << 8);
5164 if( (!(v1
& 0x02)) && (v2
& 0x30) && (regd
< 0xcf) )
5165 setSISIDXREG(SISCR
, 0x5f, 0xf1, 0x01);
5167 if((mypdev
= pci_get_device(0x10de, 0x01e0, NULL
))) {
5168 /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5172 setSISIDXREG(SISCR
, 0x5f, 0xf1, 0x01);
5173 pci_dev_put(mypdev
);
5178 reg
= SiS_GetReg(SISSR
, 0x3b);
5179 v2
= SiS_GetReg(SISCR
, 0x5f);
5180 if((!(reg
& 0x02)) && (v2
& 0x0e))
5182 SiS_SetReg(SISSR
, 0x27, v1
);
5184 if(bios
[0x64] & 0x01) {
5185 setSISIDXREG(SISCR
, 0x5f, 0xf0, bios
[0x64]);
5189 pci_read_config_dword(pdev
, 0x50, ®d
);
5190 regd
= (regd
>> 20) & 0x0f;
5193 SiS_SetRegOR(SISCR
, 0x5f, 0x08);
5195 SiS_SetReg(SISCR
, 0x48, v1
);
5197 setSISIDXREG(SISCR
, 0x47, 0x04, bios
[0x4f6] & 0xfb);
5198 setSISIDXREG(SISCR
, 0x49, 0xf0, bios
[0x4f8] & 0x0f);
5199 setSISIDXREG(SISCR
, 0x4a, 0x60, bios
[0x4f9] & 0x9f);
5200 setSISIDXREG(SISCR
, 0x4b, 0x08, bios
[0x4fa] & 0xf7);
5201 setSISIDXREG(SISCR
, 0x4c, 0x80, bios
[0x4fb] & 0x7f);
5202 SiS_SetReg(SISCR
, 0x70, bios
[0x4fc]);
5203 setSISIDXREG(SISCR
, 0x71, 0xf0, bios
[0x4fd] & 0x0f);
5204 SiS_SetReg(SISCR
, 0x74, 0xd0);
5205 setSISIDXREG(SISCR
, 0x74, 0xcf, bios
[0x4fe] & 0x30);
5206 setSISIDXREG(SISCR
, 0x75, 0xe0, bios
[0x4ff] & 0x1f);
5207 setSISIDXREG(SISCR
, 0x76, 0xe0, bios
[0x500] & 0x1f);
5209 if((mypdev
= pci_get_device(0x8086, 0x2530, NULL
))) {
5211 pci_dev_put(mypdev
);
5213 SiS_SetReg(SISCR
, 0x77, v1
);
5221 if(ivideo
->haveXGIROM
) {
5222 v1
= bios
[0x140 + regb
];
5224 SiS_SetReg(SISCR
, 0x6d, v1
);
5227 if(ivideo
->haveXGIROM
) {
5228 ptr
= (const u8
*)&bios
[0x128];
5230 for(i
= 0, j
= 0; i
< 3; i
++, j
+= 8) {
5231 SiS_SetReg(SISCR
, 0x68 + i
, ptr
[j
+ regb
]);
5236 if(ivideo
->haveXGIROM
) {
5237 index
= (ivideo
->chip
== XGI_20
) ? 0x31a : 0x3a6;
5238 ptr
= (const u8
*)&bios
[index
];
5239 ptr2
= (const u8
*)&bios
[index
+ 0x20];
5241 for(i
= 0; i
< 2; i
++) {
5243 regd
= le32_to_cpu(((u32
*)ptr
)[regb
]);
5246 regd
= le32_to_cpu(((u32
*)ptr2
)[regb
]);
5250 for(j
= 0; j
< 16; j
++) {
5252 if(regd
& 0x01) reg
|= 0x04;
5253 if(regd
& 0x02) reg
|= 0x08;
5255 SiS_SetReg(SISCR
, rega
, reg
);
5256 reg
= SiS_GetReg(SISCR
, rega
);
5257 reg
= SiS_GetReg(SISCR
, rega
);
5262 andSISIDXREG(SISCR
, 0x6e, 0xfc);
5265 if(ivideo
->haveXGIROM
) {
5266 index
= (ivideo
->chip
== XGI_20
) ? 0x35a : 0x3e6;
5267 ptr
= (const u8
*)&bios
[index
];
5269 for(i
= 0; i
< 4; i
++) {
5270 setSISIDXREG(SISCR
, 0x6e, 0xfc, i
);
5272 for(j
= 0; j
< 2; j
++) {
5275 regd
= le32_to_cpu(((u32
*)ptr
)[regb
* 8]);
5279 for(k
= 0; k
< 16; k
++) {
5281 if(regd
& 0x01) reg
|= 0x01;
5282 if(regd
& 0x02) reg
|= 0x02;
5284 SiS_SetReg(SISCR
, 0x6f, reg
);
5285 reg
= SiS_GetReg(SISCR
, 0x6f);
5286 reg
= SiS_GetReg(SISCR
, 0x6f);
5293 if(ivideo
->haveXGIROM
) {
5294 ptr
= (const u8
*)&bios
[0x148];
5296 for(i
= 0, j
= 0; i
< 2; i
++, j
+= 8) {
5297 SiS_SetReg(SISCR
, 0x80 + i
, ptr
[j
+ regb
]);
5300 andSISIDXREG(SISCR
, 0x89, 0x8f);
5303 if(ivideo
->haveXGIROM
) {
5304 index
= (ivideo
->chip
== XGI_20
) ? 0x45a : 0x4e6;
5305 ptr
= (const u8
*)&bios
[index
];
5307 regd
= le16_to_cpu(((const u16
*)ptr
)[regb
]);
5309 for(i
= 0; i
< 5; i
++) {
5311 if(regd
& 0x01) reg
|= 0x01;
5312 if(regd
& 0x02) reg
|= 0x02;
5314 SiS_SetReg(SISCR
, 0x89, reg
);
5315 reg
= SiS_GetReg(SISCR
, 0x89);
5316 reg
= SiS_GetReg(SISCR
, 0x89);
5320 v1
= 0xb5; v2
= 0x20; v3
= 0xf0; v4
= 0x13;
5321 if(ivideo
->haveXGIROM
) {
5322 v1
= bios
[0x118 + regb
];
5323 v2
= bios
[0xf8 + regb
];
5324 v3
= bios
[0x120 + regb
];
5327 SiS_SetReg(SISCR
, 0x45, v1
& 0x0f);
5328 SiS_SetReg(SISCR
, 0x99, (v1
>> 4) & 0x07);
5329 SiS_SetRegOR(SISCR
, 0x40, v1
& 0x80);
5330 SiS_SetReg(SISCR
, 0x41, v2
);
5333 if(ivideo
->haveXGIROM
) {
5334 ptr
= (const u8
*)&bios
[0x170];
5336 for(i
= 0, j
= 0; i
< 7; i
++, j
+= 8) {
5337 SiS_SetReg(SISCR
, 0x90 + i
, ptr
[j
+ regb
]);
5340 SiS_SetReg(SISCR
, 0x59, v3
);
5343 if(ivideo
->haveXGIROM
) {
5344 ptr
= (const u8
*)&bios
[0x1a8];
5346 for(i
= 0, j
= 0; i
< 3; i
++, j
+= 8) {
5347 SiS_SetReg(SISCR
, 0xc3 + i
, ptr
[j
+ regb
]);
5351 if(ivideo
->haveXGIROM
) {
5352 ptr
= (const u8
*)&bios
[0x100];
5354 for(i
= 0, j
= 0; i
< 2; i
++, j
+= 8) {
5355 SiS_SetReg(SISCR
, 0x8a + i
, ptr
[j
+ regb
]);
5358 SiS_SetReg(SISCR
, 0xcf, v4
);
5360 SiS_SetReg(SISCR
, 0x83, 0x09);
5361 SiS_SetReg(SISCR
, 0x87, 0x00);
5363 if(ivideo
->chip
== XGI_40
) {
5364 if( (ivideo
->revision_id
== 1) ||
5365 (ivideo
->revision_id
== 2) ) {
5366 SiS_SetReg(SISCR
, 0x8c, 0x87);
5370 SiS_SetReg(SISSR
, 0x17, 0x00);
5371 SiS_SetReg(SISSR
, 0x1a, 0x87);
5373 if(ivideo
->chip
== XGI_20
) {
5374 SiS_SetReg(SISSR
, 0x15, 0x00);
5375 SiS_SetReg(SISSR
, 0x1c, 0x00);
5378 ramtype
= 0x00; v1
= 0x10;
5379 if(ivideo
->haveXGIROM
) {
5380 ramtype
= bios
[0x62];
5383 if(!(ramtype
& 0x80)) {
5384 if(ivideo
->chip
== XGI_20
) {
5385 SiS_SetReg(SISCR
, 0x97, v1
);
5386 reg
= SiS_GetReg(SISCR
, 0x97);
5388 ramtype
= (reg
& 0x01) << 1;
5391 reg
= SiS_GetReg(SISSR
, 0x39);
5392 ramtype
= reg
& 0x02;
5394 reg
= SiS_GetReg(SISSR
, 0x3a);
5395 ramtype
= (reg
>> 1) & 0x01;
5405 sisfb_post_xgi_setclocks(ivideo
, regb
);
5406 if((ivideo
->chip
== XGI_20
) ||
5407 (ivideo
->revision_id
== 1) ||
5408 (ivideo
->revision_id
== 2)) {
5409 v1
= cs158
[regb
]; v2
= cs160
[regb
]; v3
= cs168
[regb
];
5410 if(ivideo
->haveXGIROM
) {
5411 v1
= bios
[regb
+ 0x158];
5412 v2
= bios
[regb
+ 0x160];
5413 v3
= bios
[regb
+ 0x168];
5415 SiS_SetReg(SISCR
, 0x82, v1
);
5416 SiS_SetReg(SISCR
, 0x85, v2
);
5417 SiS_SetReg(SISCR
, 0x86, v3
);
5419 SiS_SetReg(SISCR
, 0x82, 0x88);
5420 SiS_SetReg(SISCR
, 0x86, 0x00);
5421 reg
= SiS_GetReg(SISCR
, 0x86);
5422 SiS_SetReg(SISCR
, 0x86, 0x88);
5423 reg
= SiS_GetReg(SISCR
, 0x86);
5424 SiS_SetReg(SISCR
, 0x86, bios
[regb
+ 0x168]);
5425 SiS_SetReg(SISCR
, 0x82, 0x77);
5426 SiS_SetReg(SISCR
, 0x85, 0x00);
5427 reg
= SiS_GetReg(SISCR
, 0x85);
5428 SiS_SetReg(SISCR
, 0x85, 0x88);
5429 reg
= SiS_GetReg(SISCR
, 0x85);
5430 SiS_SetReg(SISCR
, 0x85, bios
[regb
+ 0x160]);
5431 SiS_SetReg(SISCR
, 0x82, bios
[regb
+ 0x158]);
5433 if(ivideo
->chip
== XGI_40
) {
5434 SiS_SetReg(SISCR
, 0x97, 0x00);
5436 SiS_SetReg(SISCR
, 0x98, 0x01);
5437 SiS_SetReg(SISCR
, 0x9a, 0x02);
5439 SiS_SetReg(SISSR
, 0x18, 0x01);
5440 if((ivideo
->chip
== XGI_20
) ||
5441 (ivideo
->revision_id
== 2)) {
5442 SiS_SetReg(SISSR
, 0x19, 0x40);
5444 SiS_SetReg(SISSR
, 0x19, 0x20);
5446 SiS_SetReg(SISSR
, 0x16, 0x00);
5447 SiS_SetReg(SISSR
, 0x16, 0x80);
5448 if((ivideo
->chip
== XGI_20
) || (bios
[0x1cb] != 0x0c)) {
5449 sisfb_post_xgi_delay(ivideo
, 0x43);
5450 sisfb_post_xgi_delay(ivideo
, 0x43);
5451 sisfb_post_xgi_delay(ivideo
, 0x43);
5452 SiS_SetReg(SISSR
, 0x18, 0x00);
5453 if((ivideo
->chip
== XGI_20
) ||
5454 (ivideo
->revision_id
== 2)) {
5455 SiS_SetReg(SISSR
, 0x19, 0x40);
5457 SiS_SetReg(SISSR
, 0x19, 0x20);
5459 } else if((ivideo
->chip
== XGI_40
) && (bios
[0x1cb] == 0x0c)) {
5460 /* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
5462 SiS_SetReg(SISSR
, 0x16, 0x00);
5463 SiS_SetReg(SISSR
, 0x16, 0x80);
5464 sisfb_post_xgi_delay(ivideo
, 4);
5465 v1
= 0x31; v2
= 0x03; v3
= 0x83; v4
= 0x03; v5
= 0x83;
5466 if(ivideo
->haveXGIROM
) {
5468 index
= (ivideo
->chip
== XGI_20
) ? 0x4b2 : 0x53e;
5470 v3
= bios
[index
+ 1];
5471 v4
= bios
[index
+ 2];
5472 v5
= bios
[index
+ 3];
5474 SiS_SetReg(SISSR
, 0x18, v1
);
5475 SiS_SetReg(SISSR
, 0x19, ((ivideo
->chip
== XGI_20
) ? 0x02 : 0x01));
5476 SiS_SetReg(SISSR
, 0x16, v2
);
5477 SiS_SetReg(SISSR
, 0x16, v3
);
5478 sisfb_post_xgi_delay(ivideo
, 0x43);
5479 SiS_SetReg(SISSR
, 0x1b, 0x03);
5480 sisfb_post_xgi_delay(ivideo
, 0x22);
5481 SiS_SetReg(SISSR
, 0x18, v1
);
5482 SiS_SetReg(SISSR
, 0x19, 0x00);
5483 SiS_SetReg(SISSR
, 0x16, v4
);
5484 SiS_SetReg(SISSR
, 0x16, v5
);
5485 SiS_SetReg(SISSR
, 0x1b, 0x00);
5488 SiS_SetReg(SISCR
, 0x82, 0x77);
5489 SiS_SetReg(SISCR
, 0x86, 0x00);
5490 reg
= SiS_GetReg(SISCR
, 0x86);
5491 SiS_SetReg(SISCR
, 0x86, 0x88);
5492 reg
= SiS_GetReg(SISCR
, 0x86);
5493 v1
= cs168
[regb
]; v2
= cs160
[regb
]; v3
= cs158
[regb
];
5494 if(ivideo
->haveXGIROM
) {
5495 v1
= bios
[regb
+ 0x168];
5496 v2
= bios
[regb
+ 0x160];
5497 v3
= bios
[regb
+ 0x158];
5499 SiS_SetReg(SISCR
, 0x86, v1
);
5500 SiS_SetReg(SISCR
, 0x82, 0x77);
5501 SiS_SetReg(SISCR
, 0x85, 0x00);
5502 reg
= SiS_GetReg(SISCR
, 0x85);
5503 SiS_SetReg(SISCR
, 0x85, 0x88);
5504 reg
= SiS_GetReg(SISCR
, 0x85);
5505 SiS_SetReg(SISCR
, 0x85, v2
);
5506 SiS_SetReg(SISCR
, 0x82, v3
);
5507 SiS_SetReg(SISCR
, 0x98, 0x01);
5508 SiS_SetReg(SISCR
, 0x9a, 0x02);
5510 SiS_SetReg(SISSR
, 0x28, 0x64);
5511 SiS_SetReg(SISSR
, 0x29, 0x63);
5512 sisfb_post_xgi_delay(ivideo
, 15);
5513 SiS_SetReg(SISSR
, 0x18, 0x00);
5514 SiS_SetReg(SISSR
, 0x19, 0x20);
5515 SiS_SetReg(SISSR
, 0x16, 0x00);
5516 SiS_SetReg(SISSR
, 0x16, 0x80);
5517 SiS_SetReg(SISSR
, 0x18, 0xc5);
5518 SiS_SetReg(SISSR
, 0x19, 0x23);
5519 SiS_SetReg(SISSR
, 0x16, 0x00);
5520 SiS_SetReg(SISSR
, 0x16, 0x80);
5521 sisfb_post_xgi_delay(ivideo
, 1);
5522 SiS_SetReg(SISCR
, 0x97, 0x11);
5523 sisfb_post_xgi_setclocks(ivideo
, regb
);
5524 sisfb_post_xgi_delay(ivideo
, 0x46);
5525 SiS_SetReg(SISSR
, 0x18, 0xc5);
5526 SiS_SetReg(SISSR
, 0x19, 0x23);
5527 SiS_SetReg(SISSR
, 0x16, 0x00);
5528 SiS_SetReg(SISSR
, 0x16, 0x80);
5529 sisfb_post_xgi_delay(ivideo
, 1);
5530 SiS_SetReg(SISSR
, 0x1b, 0x04);
5531 sisfb_post_xgi_delay(ivideo
, 1);
5532 SiS_SetReg(SISSR
, 0x1b, 0x00);
5533 sisfb_post_xgi_delay(ivideo
, 1);
5535 if(ivideo
->haveXGIROM
) {
5538 SiS_SetReg(SISSR
, 0x18, v1
);
5539 SiS_SetReg(SISSR
, 0x19, 0x06);
5540 SiS_SetReg(SISSR
, 0x16, 0x04);
5541 SiS_SetReg(SISSR
, 0x16, 0x84);
5542 sisfb_post_xgi_delay(ivideo
, 1);
5545 sisfb_post_xgi_setclocks(ivideo
, regb
);
5546 if((ivideo
->chip
== XGI_40
) &&
5547 ((ivideo
->revision_id
== 1) ||
5548 (ivideo
->revision_id
== 2))) {
5549 SiS_SetReg(SISCR
, 0x82, bios
[regb
+ 0x158]);
5550 SiS_SetReg(SISCR
, 0x85, bios
[regb
+ 0x160]);
5551 SiS_SetReg(SISCR
, 0x86, bios
[regb
+ 0x168]);
5553 SiS_SetReg(SISCR
, 0x82, 0x88);
5554 SiS_SetReg(SISCR
, 0x86, 0x00);
5555 reg
= SiS_GetReg(SISCR
, 0x86);
5556 SiS_SetReg(SISCR
, 0x86, 0x88);
5557 SiS_SetReg(SISCR
, 0x82, 0x77);
5558 SiS_SetReg(SISCR
, 0x85, 0x00);
5559 reg
= SiS_GetReg(SISCR
, 0x85);
5560 SiS_SetReg(SISCR
, 0x85, 0x88);
5561 reg
= SiS_GetReg(SISCR
, 0x85);
5562 v1
= cs160
[regb
]; v2
= cs158
[regb
];
5563 if(ivideo
->haveXGIROM
) {
5564 v1
= bios
[regb
+ 0x160];
5565 v2
= bios
[regb
+ 0x158];
5567 SiS_SetReg(SISCR
, 0x85, v1
);
5568 SiS_SetReg(SISCR
, 0x82, v2
);
5570 if(ivideo
->chip
== XGI_40
) {
5571 SiS_SetReg(SISCR
, 0x97, 0x11);
5573 if((ivideo
->chip
== XGI_40
) && (ivideo
->revision_id
== 2)) {
5574 SiS_SetReg(SISCR
, 0x98, 0x01);
5576 SiS_SetReg(SISCR
, 0x98, 0x03);
5578 SiS_SetReg(SISCR
, 0x9a, 0x02);
5580 if(ivideo
->chip
== XGI_40
) {
5581 SiS_SetReg(SISSR
, 0x18, 0x01);
5583 SiS_SetReg(SISSR
, 0x18, 0x00);
5585 SiS_SetReg(SISSR
, 0x19, 0x40);
5586 SiS_SetReg(SISSR
, 0x16, 0x00);
5587 SiS_SetReg(SISSR
, 0x16, 0x80);
5588 if((ivideo
->chip
== XGI_40
) && (bios
[0x1cb] != 0x0c)) {
5589 sisfb_post_xgi_delay(ivideo
, 0x43);
5590 sisfb_post_xgi_delay(ivideo
, 0x43);
5591 sisfb_post_xgi_delay(ivideo
, 0x43);
5592 SiS_SetReg(SISSR
, 0x18, 0x00);
5593 SiS_SetReg(SISSR
, 0x19, 0x40);
5594 SiS_SetReg(SISSR
, 0x16, 0x00);
5595 SiS_SetReg(SISSR
, 0x16, 0x80);
5597 sisfb_post_xgi_delay(ivideo
, 4);
5599 if(ivideo
->haveXGIROM
) {
5602 SiS_SetReg(SISSR
, 0x18, v1
);
5603 SiS_SetReg(SISSR
, 0x19, 0x01);
5604 if(ivideo
->chip
== XGI_40
) {
5605 SiS_SetReg(SISSR
, 0x16, bios
[0x53e]);
5606 SiS_SetReg(SISSR
, 0x16, bios
[0x53f]);
5608 SiS_SetReg(SISSR
, 0x16, 0x05);
5609 SiS_SetReg(SISSR
, 0x16, 0x85);
5611 sisfb_post_xgi_delay(ivideo
, 0x43);
5612 if(ivideo
->chip
== XGI_40
) {
5613 SiS_SetReg(SISSR
, 0x1b, 0x01);
5615 SiS_SetReg(SISSR
, 0x1b, 0x03);
5617 sisfb_post_xgi_delay(ivideo
, 0x22);
5618 SiS_SetReg(SISSR
, 0x18, v1
);
5619 SiS_SetReg(SISSR
, 0x19, 0x00);
5620 if(ivideo
->chip
== XGI_40
) {
5621 SiS_SetReg(SISSR
, 0x16, bios
[0x540]);
5622 SiS_SetReg(SISSR
, 0x16, bios
[0x541]);
5624 SiS_SetReg(SISSR
, 0x16, 0x05);
5625 SiS_SetReg(SISSR
, 0x16, 0x85);
5627 SiS_SetReg(SISSR
, 0x1b, 0x00);
5632 if(ivideo
->haveXGIROM
) {
5633 v1
= bios
[0x110 + regb
];
5635 SiS_SetReg(SISSR
, 0x1b, v1
);
5638 v1
= 0x00; v2
= 0x00;
5639 if(ivideo
->haveXGIROM
) {
5645 if((v1
& 0x40) && (v2
& regd
) && ivideo
->haveXGIROM
) {
5647 SiS_SetReg(SISSR
, 0x13, bios
[regb
+ 0xe0]);
5648 SiS_SetReg(SISSR
, 0x14, bios
[regb
+ 0xe0 + 8]);
5652 /* Set default mode, don't clear screen */
5653 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
5654 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
5655 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
5656 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
5657 ivideo
->SiS_Pr
.VideoMemorySize
= 8 << 20;
5658 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
5660 SiS_SetReg(SISSR
, 0x05, 0x86);
5662 /* Disable read-cache */
5663 andSISIDXREG(SISSR
, 0x21, 0xdf);
5664 sisfb_post_xgi_ramsize(ivideo
);
5665 /* Enable read-cache */
5666 SiS_SetRegOR(SISSR
, 0x21, 0x20);
5671 printk(KERN_DEBUG
"-----------------\n");
5672 for(i
= 0; i
< 0xff; i
++) {
5673 reg
= SiS_GetReg(SISCR
, i
);
5674 printk(KERN_DEBUG
"CR%02x(%x) = 0x%02x\n", i
, SISCR
, reg
);
5676 for(i
= 0; i
< 0x40; i
++) {
5677 reg
= SiS_GetReg(SISSR
, i
);
5678 printk(KERN_DEBUG
"SR%02x(%x) = 0x%02x\n", i
, SISSR
, reg
);
5680 printk(KERN_DEBUG
"-----------------\n");
5684 if(ivideo
->chip
== XGI_20
) {
5685 SiS_SetRegOR(SISCR
, 0x32, 0x20);
5687 reg
= SiS_GetReg(SISPART4
, 0x00);
5688 if((reg
== 1) || (reg
== 2)) {
5689 sisfb_sense_crt1(ivideo
);
5691 SiS_SetRegOR(SISCR
, 0x32, 0x20);
5695 /* Set default mode, don't clear screen */
5696 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
5697 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
5698 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
5699 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
5700 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
5702 SiS_SetReg(SISSR
, 0x05, 0x86);
5705 SiS_SetRegOR(SISSR
, 0x01, 0x20);
5707 /* Save mode number in CR34 */
5708 SiS_SetReg(SISCR
, 0x34, 0x2e);
5710 /* Let everyone know what the current mode is */
5711 ivideo
->modeprechange
= 0x2e;
5713 if(ivideo
->chip
== XGI_40
) {
5714 reg
= SiS_GetReg(SISCR
, 0xca);
5715 v1
= SiS_GetReg(SISCR
, 0xcc);
5716 if((reg
& 0x10) && (!(v1
& 0x04))) {
5718 "sisfb: Please connect power to the card.\n");
5727 static int __devinit
5728 sisfb_probe(struct pci_dev
*pdev
, const struct pci_device_id
*ent
)
5730 struct sisfb_chip_info
*chipinfo
= &sisfb_chip_info
[ent
->driver_data
];
5731 struct sis_video_info
*ivideo
= NULL
;
5732 struct fb_info
*sis_fb_info
= NULL
;
5740 sis_fb_info
= framebuffer_alloc(sizeof(*ivideo
), &pdev
->dev
);
5744 ivideo
= (struct sis_video_info
*)sis_fb_info
->par
;
5745 ivideo
->memyselfandi
= sis_fb_info
;
5747 ivideo
->sisfb_id
= SISFB_ID
;
5749 if(card_list
== NULL
) {
5750 ivideo
->cardnumber
= 0;
5752 struct sis_video_info
*countvideo
= card_list
;
5753 ivideo
->cardnumber
= 1;
5754 while((countvideo
= countvideo
->next
) != NULL
)
5755 ivideo
->cardnumber
++;
5758 strncpy(ivideo
->myid
, chipinfo
->chip_name
, 30);
5760 ivideo
->warncount
= 0;
5761 ivideo
->chip_id
= pdev
->device
;
5762 ivideo
->chip_vendor
= pdev
->vendor
;
5763 ivideo
->revision_id
= pdev
->revision
;
5764 ivideo
->SiS_Pr
.ChipRevision
= ivideo
->revision_id
;
5765 pci_read_config_word(pdev
, PCI_COMMAND
, ®16
);
5766 ivideo
->sisvga_enabled
= reg16
& 0x01;
5767 ivideo
->pcibus
= pdev
->bus
->number
;
5768 ivideo
->pcislot
= PCI_SLOT(pdev
->devfn
);
5769 ivideo
->pcifunc
= PCI_FUNC(pdev
->devfn
);
5770 ivideo
->subsysvendor
= pdev
->subsystem_vendor
;
5771 ivideo
->subsysdevice
= pdev
->subsystem_device
;
5774 if(sisfb_mode_idx
== -1) {
5775 sisfb_get_vga_mode_from_kernel();
5779 ivideo
->chip
= chipinfo
->chip
;
5780 ivideo
->sisvga_engine
= chipinfo
->vgaengine
;
5781 ivideo
->hwcursor_size
= chipinfo
->hwcursor_size
;
5782 ivideo
->CRT2_write_enable
= chipinfo
->CRT2_write_enable
;
5783 ivideo
->mni
= chipinfo
->mni
;
5785 ivideo
->detectedpdc
= 0xff;
5786 ivideo
->detectedpdca
= 0xff;
5787 ivideo
->detectedlcda
= 0xff;
5789 ivideo
->sisfb_thismonitor
.datavalid
= false;
5791 ivideo
->current_base
= 0;
5793 ivideo
->engineok
= 0;
5795 ivideo
->sisfb_was_boot_device
= 0;
5797 if(pdev
->resource
[PCI_ROM_RESOURCE
].flags
& IORESOURCE_ROM_SHADOW
) {
5798 if(ivideo
->sisvga_enabled
)
5799 ivideo
->sisfb_was_boot_device
= 1;
5801 printk(KERN_DEBUG
"sisfb: PCI device is disabled, "
5802 "but marked as boot video device ???\n");
5803 printk(KERN_DEBUG
"sisfb: I will not accept this "
5804 "as the primary VGA device\n");
5808 ivideo
->sisfb_parm_mem
= sisfb_parm_mem
;
5809 ivideo
->sisfb_accel
= sisfb_accel
;
5810 ivideo
->sisfb_ypan
= sisfb_ypan
;
5811 ivideo
->sisfb_max
= sisfb_max
;
5812 ivideo
->sisfb_userom
= sisfb_userom
;
5813 ivideo
->sisfb_useoem
= sisfb_useoem
;
5814 ivideo
->sisfb_mode_idx
= sisfb_mode_idx
;
5815 ivideo
->sisfb_parm_rate
= sisfb_parm_rate
;
5816 ivideo
->sisfb_crt1off
= sisfb_crt1off
;
5817 ivideo
->sisfb_forcecrt1
= sisfb_forcecrt1
;
5818 ivideo
->sisfb_crt2type
= sisfb_crt2type
;
5819 ivideo
->sisfb_crt2flags
= sisfb_crt2flags
;
5820 /* pdc(a), scalelcd, special timing, lvdshl handled below */
5821 ivideo
->sisfb_dstn
= sisfb_dstn
;
5822 ivideo
->sisfb_fstn
= sisfb_fstn
;
5823 ivideo
->sisfb_tvplug
= sisfb_tvplug
;
5824 ivideo
->sisfb_tvstd
= sisfb_tvstd
;
5825 ivideo
->tvxpos
= sisfb_tvxposoffset
;
5826 ivideo
->tvypos
= sisfb_tvyposoffset
;
5827 ivideo
->sisfb_nocrt2rate
= sisfb_nocrt2rate
;
5828 ivideo
->refresh_rate
= 0;
5829 if(ivideo
->sisfb_parm_rate
!= -1) {
5830 ivideo
->refresh_rate
= ivideo
->sisfb_parm_rate
;
5833 ivideo
->SiS_Pr
.UsePanelScaler
= sisfb_scalelcd
;
5834 ivideo
->SiS_Pr
.CenterScreen
= -1;
5835 ivideo
->SiS_Pr
.SiS_CustomT
= sisfb_specialtiming
;
5836 ivideo
->SiS_Pr
.LVDSHL
= sisfb_lvdshl
;
5838 ivideo
->SiS_Pr
.SiS_Backup70xx
= 0xff;
5839 ivideo
->SiS_Pr
.SiS_CHOverScan
= -1;
5840 ivideo
->SiS_Pr
.SiS_ChSW
= false;
5841 ivideo
->SiS_Pr
.SiS_UseLCDA
= false;
5842 ivideo
->SiS_Pr
.HaveEMI
= false;
5843 ivideo
->SiS_Pr
.HaveEMILCD
= false;
5844 ivideo
->SiS_Pr
.OverruleEMI
= false;
5845 ivideo
->SiS_Pr
.SiS_SensibleSR11
= false;
5846 ivideo
->SiS_Pr
.SiS_MyCR63
= 0x63;
5847 ivideo
->SiS_Pr
.PDC
= -1;
5848 ivideo
->SiS_Pr
.PDCA
= -1;
5849 ivideo
->SiS_Pr
.DDCPortMixup
= false;
5850 #ifdef CONFIG_FB_SIS_315
5851 if(ivideo
->chip
>= SIS_330
) {
5852 ivideo
->SiS_Pr
.SiS_MyCR63
= 0x53;
5853 if(ivideo
->chip
>= SIS_661
) {
5854 ivideo
->SiS_Pr
.SiS_SensibleSR11
= true;
5859 memcpy(&ivideo
->default_var
, &my_default_var
, sizeof(my_default_var
));
5861 pci_set_drvdata(pdev
, ivideo
);
5863 /* Patch special cases */
5864 if((ivideo
->nbridge
= sisfb_get_northbridge(ivideo
->chip
))) {
5865 switch(ivideo
->nbridge
->device
) {
5866 #ifdef CONFIG_FB_SIS_300
5867 case PCI_DEVICE_ID_SI_730
:
5868 ivideo
->chip
= SIS_730
;
5869 strcpy(ivideo
->myid
, "SiS 730");
5872 #ifdef CONFIG_FB_SIS_315
5873 case PCI_DEVICE_ID_SI_651
:
5874 /* ivideo->chip is ok */
5875 strcpy(ivideo
->myid
, "SiS 651");
5877 case PCI_DEVICE_ID_SI_740
:
5878 ivideo
->chip
= SIS_740
;
5879 strcpy(ivideo
->myid
, "SiS 740");
5881 case PCI_DEVICE_ID_SI_661
:
5882 ivideo
->chip
= SIS_661
;
5883 strcpy(ivideo
->myid
, "SiS 661");
5885 case PCI_DEVICE_ID_SI_741
:
5886 ivideo
->chip
= SIS_741
;
5887 strcpy(ivideo
->myid
, "SiS 741");
5889 case PCI_DEVICE_ID_SI_760
:
5890 ivideo
->chip
= SIS_760
;
5891 strcpy(ivideo
->myid
, "SiS 760");
5893 case PCI_DEVICE_ID_SI_761
:
5894 ivideo
->chip
= SIS_761
;
5895 strcpy(ivideo
->myid
, "SiS 761");
5903 ivideo
->SiS_Pr
.ChipType
= ivideo
->chip
;
5905 ivideo
->SiS_Pr
.ivideo
= (void *)ivideo
;
5907 #ifdef CONFIG_FB_SIS_315
5908 if((ivideo
->SiS_Pr
.ChipType
== SIS_315PRO
) ||
5909 (ivideo
->SiS_Pr
.ChipType
== SIS_315
)) {
5910 ivideo
->SiS_Pr
.ChipType
= SIS_315H
;
5914 if(!ivideo
->sisvga_enabled
) {
5915 if(pci_enable_device(pdev
)) {
5916 if(ivideo
->nbridge
) pci_dev_put(ivideo
->nbridge
);
5917 pci_set_drvdata(pdev
, NULL
);
5918 framebuffer_release(sis_fb_info
);
5923 ivideo
->video_base
= pci_resource_start(pdev
, 0);
5924 ivideo
->video_size
= pci_resource_len(pdev
, 0);
5925 ivideo
->mmio_base
= pci_resource_start(pdev
, 1);
5926 ivideo
->mmio_size
= pci_resource_len(pdev
, 1);
5927 ivideo
->SiS_Pr
.RelIO
= pci_resource_start(pdev
, 2) + 0x30;
5928 ivideo
->SiS_Pr
.IOAddress
= ivideo
->vga_base
= ivideo
->SiS_Pr
.RelIO
;
5930 SiSRegInit(&ivideo
->SiS_Pr
, ivideo
->SiS_Pr
.IOAddress
);
5932 #ifdef CONFIG_FB_SIS_300
5933 /* Find PCI systems for Chrontel/GPIO communication setup */
5934 if(ivideo
->chip
== SIS_630
) {
5937 if(mychswtable
[i
].subsysVendor
== ivideo
->subsysvendor
&&
5938 mychswtable
[i
].subsysCard
== ivideo
->subsysdevice
) {
5939 ivideo
->SiS_Pr
.SiS_ChSW
= true;
5940 printk(KERN_DEBUG
"sisfb: Identified [%s %s] "
5941 "requiring Chrontel/GPIO setup\n",
5942 mychswtable
[i
].vendorName
,
5943 mychswtable
[i
].cardName
);
5944 ivideo
->lpcdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0008, NULL
);
5948 } while(mychswtable
[i
].subsysVendor
!= 0);
5952 #ifdef CONFIG_FB_SIS_315
5953 if((ivideo
->chip
== SIS_760
) && (ivideo
->nbridge
)) {
5954 ivideo
->lpcdev
= pci_get_slot(ivideo
->nbridge
->bus
, (2 << 3));
5958 SiS_SetReg(SISSR
, 0x05, 0x86);
5960 if( (!ivideo
->sisvga_enabled
)
5961 #if !defined(__i386__) && !defined(__x86_64__)
5962 || (sisfb_resetcard
)
5965 for(i
= 0x30; i
<= 0x3f; i
++) {
5966 SiS_SetReg(SISCR
, i
, 0x00);
5970 /* Find out about current video mode */
5971 ivideo
->modeprechange
= 0x03;
5972 reg
= SiS_GetReg(SISCR
, 0x34);
5974 ivideo
->modeprechange
= reg
& 0x7f;
5975 } else if(ivideo
->sisvga_enabled
) {
5976 #if defined(__i386__) || defined(__x86_64__)
5977 unsigned char __iomem
*tt
= ioremap(0x400, 0x100);
5979 ivideo
->modeprechange
= readb(tt
+ 0x49);
5985 /* Search and copy ROM image */
5986 ivideo
->bios_abase
= NULL
;
5987 ivideo
->SiS_Pr
.VirtualRomBase
= NULL
;
5988 ivideo
->SiS_Pr
.UseROM
= false;
5989 ivideo
->haveXGIROM
= ivideo
->SiS_Pr
.SiS_XGIROM
= false;
5990 if(ivideo
->sisfb_userom
) {
5991 ivideo
->SiS_Pr
.VirtualRomBase
= sisfb_find_rom(pdev
);
5992 ivideo
->bios_abase
= ivideo
->SiS_Pr
.VirtualRomBase
;
5993 ivideo
->SiS_Pr
.UseROM
= (bool)(ivideo
->SiS_Pr
.VirtualRomBase
);
5994 printk(KERN_INFO
"sisfb: Video ROM %sfound\n",
5995 ivideo
->SiS_Pr
.UseROM
? "" : "not ");
5996 if((ivideo
->SiS_Pr
.UseROM
) && (ivideo
->chip
>= XGI_20
)) {
5997 ivideo
->SiS_Pr
.UseROM
= false;
5998 ivideo
->haveXGIROM
= ivideo
->SiS_Pr
.SiS_XGIROM
= true;
5999 if( (ivideo
->revision_id
== 2) &&
6000 (!(ivideo
->bios_abase
[0x1d1] & 0x01)) ) {
6001 ivideo
->SiS_Pr
.DDCPortMixup
= true;
6005 printk(KERN_INFO
"sisfb: Video ROM usage disabled\n");
6008 /* Find systems for special custom timing */
6009 if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_NONE
) {
6010 sisfb_detect_custom_timing(ivideo
);
6013 /* POST card in case this has not been done by the BIOS */
6014 if( (!ivideo
->sisvga_enabled
)
6015 #if !defined(__i386__) && !defined(__x86_64__)
6016 || (sisfb_resetcard
)
6019 #ifdef CONFIG_FB_SIS_300
6020 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
6021 if(ivideo
->chip
== SIS_300
) {
6022 sisfb_post_sis300(pdev
);
6023 ivideo
->sisfb_can_post
= 1;
6028 #ifdef CONFIG_FB_SIS_315
6029 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
6031 /* if((ivideo->chip == SIS_315H) ||
6032 (ivideo->chip == SIS_315) ||
6033 (ivideo->chip == SIS_315PRO) ||
6034 (ivideo->chip == SIS_330)) {
6035 sisfb_post_sis315330(pdev);
6036 } else */ if(ivideo
->chip
== XGI_20
) {
6037 result
= sisfb_post_xgi(pdev
);
6038 ivideo
->sisfb_can_post
= 1;
6039 } else if((ivideo
->chip
== XGI_40
) && ivideo
->haveXGIROM
) {
6040 result
= sisfb_post_xgi(pdev
);
6041 ivideo
->sisfb_can_post
= 1;
6043 printk(KERN_INFO
"sisfb: Card is not "
6044 "POSTed and sisfb can't do this either.\n");
6047 printk(KERN_ERR
"sisfb: Failed to POST card\n");
6055 ivideo
->sisfb_card_posted
= 1;
6057 /* Find out about RAM size */
6058 if(sisfb_get_dram_size(ivideo
)) {
6059 printk(KERN_INFO
"sisfb: Fatal error: Unable to determine VRAM size.\n");
6065 /* Enable PCI addressing and MMIO */
6066 if((ivideo
->sisfb_mode_idx
< 0) ||
6067 ((sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
]) != 0xFF)) {
6068 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
6069 SiS_SetRegOR(SISSR
, IND_SIS_PCI_ADDRESS_SET
, (SIS_PCI_ADDR_ENABLE
| SIS_MEM_MAP_IO_ENABLE
));
6070 /* Enable 2D accelerator engine */
6071 SiS_SetRegOR(SISSR
, IND_SIS_MODULE_ENABLE
, SIS_ENABLE_2D
);
6074 if(sisfb_pdc
!= 0xff) {
6075 if(ivideo
->sisvga_engine
== SIS_300_VGA
)
6079 ivideo
->SiS_Pr
.PDC
= sisfb_pdc
;
6081 #ifdef CONFIG_FB_SIS_315
6082 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
6083 if(sisfb_pdca
!= 0xff)
6084 ivideo
->SiS_Pr
.PDCA
= sisfb_pdca
& 0x1f;
6088 if(!request_mem_region(ivideo
->video_base
, ivideo
->video_size
, "sisfb FB")) {
6089 printk(KERN_ERR
"sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6090 (int)(ivideo
->video_size
>> 20));
6091 printk(KERN_ERR
"sisfb: Is there another framebuffer driver active?\n");
6096 if(!request_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
, "sisfb MMIO")) {
6097 printk(KERN_ERR
"sisfb: Fatal error: Unable to reserve MMIO region\n");
6102 ivideo
->video_vbase
= ioremap(ivideo
->video_base
, ivideo
->video_size
);
6103 ivideo
->SiS_Pr
.VideoMemoryAddress
= ivideo
->video_vbase
;
6104 if(!ivideo
->video_vbase
) {
6105 printk(KERN_ERR
"sisfb: Fatal error: Unable to map framebuffer memory\n");
6110 ivideo
->mmio_vbase
= ioremap(ivideo
->mmio_base
, ivideo
->mmio_size
);
6111 if(!ivideo
->mmio_vbase
) {
6112 printk(KERN_ERR
"sisfb: Fatal error: Unable to map MMIO region\n");
6114 error_0
: iounmap(ivideo
->video_vbase
);
6115 error_1
: release_mem_region(ivideo
->video_base
, ivideo
->video_size
);
6116 error_2
: release_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
);
6117 error_3
: vfree(ivideo
->bios_abase
);
6119 pci_dev_put(ivideo
->lpcdev
);
6121 pci_dev_put(ivideo
->nbridge
);
6122 pci_set_drvdata(pdev
, NULL
);
6123 if(!ivideo
->sisvga_enabled
)
6124 pci_disable_device(pdev
);
6125 framebuffer_release(sis_fb_info
);
6129 printk(KERN_INFO
"sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
6130 ivideo
->video_base
, (unsigned long)ivideo
->video_vbase
, ivideo
->video_size
/ 1024);
6132 if(ivideo
->video_offset
) {
6133 printk(KERN_INFO
"sisfb: Viewport offset %ldk\n",
6134 ivideo
->video_offset
/ 1024);
6137 printk(KERN_INFO
"sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
6138 ivideo
->mmio_base
, (unsigned long)ivideo
->mmio_vbase
, ivideo
->mmio_size
/ 1024);
6141 /* Determine the size of the command queue */
6142 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
6143 ivideo
->cmdQueueSize
= TURBO_QUEUE_AREA_SIZE
;
6145 if(ivideo
->chip
== XGI_20
) {
6146 ivideo
->cmdQueueSize
= COMMAND_QUEUE_AREA_SIZE_Z7
;
6148 ivideo
->cmdQueueSize
= COMMAND_QUEUE_AREA_SIZE
;
6152 /* Engines are no longer initialized here; this is
6153 * now done after the first mode-switch (if the
6154 * submitted var has its acceleration flags set).
6157 /* Calculate the base of the (unused) hw cursor */
6158 ivideo
->hwcursor_vbase
= ivideo
->video_vbase
6159 + ivideo
->video_size
6160 - ivideo
->cmdQueueSize
6161 - ivideo
->hwcursor_size
;
6162 ivideo
->caps
|= HW_CURSOR_CAP
;
6164 /* Initialize offscreen memory manager */
6165 if((ivideo
->havenoheap
= sisfb_heap_init(ivideo
))) {
6166 printk(KERN_WARNING
"sisfb: Failed to initialize offscreen memory heap\n");
6169 /* Used for clearing the screen only, therefore respect our mem limit */
6170 ivideo
->SiS_Pr
.VideoMemoryAddress
+= ivideo
->video_offset
;
6171 ivideo
->SiS_Pr
.VideoMemorySize
= ivideo
->sisfb_mem
;
6175 ivideo
->vbflags
= 0;
6176 ivideo
->lcddefmodeidx
= DEFAULT_LCDMODE
;
6177 ivideo
->tvdefmodeidx
= DEFAULT_TVMODE
;
6178 ivideo
->defmodeidx
= DEFAULT_MODE
;
6181 if(ivideo
->chip
< XGI_20
) {
6182 if(ivideo
->bios_abase
) {
6183 ivideo
->newrom
= SiSDetermineROMLayout661(&ivideo
->SiS_Pr
);
6187 if((ivideo
->sisfb_mode_idx
< 0) ||
6188 ((sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
]) != 0xFF)) {
6190 sisfb_sense_crt1(ivideo
);
6192 sisfb_get_VB_type(ivideo
);
6194 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
6195 sisfb_detect_VB_connect(ivideo
);
6198 ivideo
->currentvbflags
= ivideo
->vbflags
& (VB_VIDEOBRIDGE
| TV_STANDARD
);
6200 /* Decide on which CRT2 device to use */
6201 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
6202 if(ivideo
->sisfb_crt2type
!= -1) {
6203 if((ivideo
->sisfb_crt2type
== CRT2_LCD
) &&
6204 (ivideo
->vbflags
& CRT2_LCD
)) {
6205 ivideo
->currentvbflags
|= CRT2_LCD
;
6206 } else if(ivideo
->sisfb_crt2type
!= CRT2_LCD
) {
6207 ivideo
->currentvbflags
|= ivideo
->sisfb_crt2type
;
6210 /* Chrontel 700x TV detection often unreliable, therefore
6211 * use a different default order on such machines
6213 if((ivideo
->sisvga_engine
== SIS_300_VGA
) &&
6214 (ivideo
->vbflags2
& VB2_CHRONTEL
)) {
6215 if(ivideo
->vbflags
& CRT2_LCD
)
6216 ivideo
->currentvbflags
|= CRT2_LCD
;
6217 else if(ivideo
->vbflags
& CRT2_TV
)
6218 ivideo
->currentvbflags
|= CRT2_TV
;
6219 else if(ivideo
->vbflags
& CRT2_VGA
)
6220 ivideo
->currentvbflags
|= CRT2_VGA
;
6222 if(ivideo
->vbflags
& CRT2_TV
)
6223 ivideo
->currentvbflags
|= CRT2_TV
;
6224 else if(ivideo
->vbflags
& CRT2_LCD
)
6225 ivideo
->currentvbflags
|= CRT2_LCD
;
6226 else if(ivideo
->vbflags
& CRT2_VGA
)
6227 ivideo
->currentvbflags
|= CRT2_VGA
;
6232 if(ivideo
->vbflags
& CRT2_LCD
) {
6233 sisfb_detect_lcd_type(ivideo
);
6236 sisfb_save_pdc_emi(ivideo
);
6238 if(!ivideo
->sisfb_crt1off
) {
6239 sisfb_handle_ddc(ivideo
, &ivideo
->sisfb_thismonitor
, 0);
6241 if((ivideo
->vbflags2
& VB2_SISTMDSBRIDGE
) &&
6242 (ivideo
->vbflags
& (CRT2_VGA
| CRT2_LCD
))) {
6243 sisfb_handle_ddc(ivideo
, &ivideo
->sisfb_thismonitor
, 1);
6247 if(ivideo
->sisfb_mode_idx
>= 0) {
6248 int bu
= ivideo
->sisfb_mode_idx
;
6249 ivideo
->sisfb_mode_idx
= sisfb_validate_mode(ivideo
,
6250 ivideo
->sisfb_mode_idx
, ivideo
->currentvbflags
);
6251 if(bu
!= ivideo
->sisfb_mode_idx
) {
6252 printk(KERN_ERR
"Mode %dx%dx%d failed validation\n",
6253 sisbios_mode
[bu
].xres
,
6254 sisbios_mode
[bu
].yres
,
6255 sisbios_mode
[bu
].bpp
);
6259 if(ivideo
->sisfb_mode_idx
< 0) {
6260 switch(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
6262 ivideo
->sisfb_mode_idx
= ivideo
->lcddefmodeidx
;
6265 ivideo
->sisfb_mode_idx
= ivideo
->tvdefmodeidx
;
6268 ivideo
->sisfb_mode_idx
= ivideo
->defmodeidx
;
6273 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
6275 if(ivideo
->refresh_rate
!= 0) {
6276 sisfb_search_refresh_rate(ivideo
, ivideo
->refresh_rate
,
6277 ivideo
->sisfb_mode_idx
);
6280 if(ivideo
->rate_idx
== 0) {
6281 ivideo
->rate_idx
= sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
;
6282 ivideo
->refresh_rate
= 60;
6285 if(ivideo
->sisfb_thismonitor
.datavalid
) {
6286 if(!sisfb_verify_rate(ivideo
, &ivideo
->sisfb_thismonitor
,
6287 ivideo
->sisfb_mode_idx
,
6289 ivideo
->refresh_rate
)) {
6290 printk(KERN_INFO
"sisfb: WARNING: Refresh rate "
6291 "exceeds monitor specs!\n");
6295 ivideo
->video_bpp
= sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
;
6296 ivideo
->video_width
= sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
;
6297 ivideo
->video_height
= sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
;
6299 sisfb_set_vparms(ivideo
);
6301 printk(KERN_INFO
"sisfb: Default mode is %dx%dx%d (%dHz)\n",
6302 ivideo
->video_width
, ivideo
->video_height
, ivideo
->video_bpp
,
6303 ivideo
->refresh_rate
);
6305 /* Set up the default var according to chosen default display mode */
6306 ivideo
->default_var
.xres
= ivideo
->default_var
.xres_virtual
= ivideo
->video_width
;
6307 ivideo
->default_var
.yres
= ivideo
->default_var
.yres_virtual
= ivideo
->video_height
;
6308 ivideo
->default_var
.bits_per_pixel
= ivideo
->video_bpp
;
6310 sisfb_bpp_to_var(ivideo
, &ivideo
->default_var
);
6312 ivideo
->default_var
.pixclock
= (u32
) (1000000000 /
6313 sisfb_mode_rate_to_dclock(&ivideo
->SiS_Pr
, ivideo
->mode_no
, ivideo
->rate_idx
));
6315 if(sisfb_mode_rate_to_ddata(&ivideo
->SiS_Pr
, ivideo
->mode_no
,
6316 ivideo
->rate_idx
, &ivideo
->default_var
)) {
6317 if((ivideo
->default_var
.vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
6318 ivideo
->default_var
.pixclock
<<= 1;
6322 if(ivideo
->sisfb_ypan
) {
6323 /* Maximize regardless of sisfb_max at startup */
6324 ivideo
->default_var
.yres_virtual
=
6325 sisfb_calc_maxyres(ivideo
, &ivideo
->default_var
);
6326 if(ivideo
->default_var
.yres_virtual
< ivideo
->default_var
.yres
) {
6327 ivideo
->default_var
.yres_virtual
= ivideo
->default_var
.yres
;
6331 sisfb_calc_pitch(ivideo
, &ivideo
->default_var
);
6334 if(ivideo
->sisfb_accel
) {
6336 #ifdef STUPID_ACCELF_TEXT_SHIT
6337 ivideo
->default_var
.accel_flags
|= FB_ACCELF_TEXT
;
6340 sisfb_initaccel(ivideo
);
6342 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
6343 sis_fb_info
->flags
= FBINFO_DEFAULT
|
6344 FBINFO_HWACCEL_YPAN
|
6345 FBINFO_HWACCEL_XPAN
|
6346 FBINFO_HWACCEL_COPYAREA
|
6347 FBINFO_HWACCEL_FILLRECT
|
6348 ((ivideo
->accel
) ? 0 : FBINFO_HWACCEL_DISABLED
);
6350 sis_fb_info
->flags
= FBINFO_FLAG_DEFAULT
;
6352 sis_fb_info
->var
= ivideo
->default_var
;
6353 sis_fb_info
->fix
= ivideo
->sisfb_fix
;
6354 sis_fb_info
->screen_base
= ivideo
->video_vbase
+ ivideo
->video_offset
;
6355 sis_fb_info
->fbops
= &sisfb_ops
;
6356 sis_fb_info
->pseudo_palette
= ivideo
->pseudo_palette
;
6358 fb_alloc_cmap(&sis_fb_info
->cmap
, 256 , 0);
6360 printk(KERN_DEBUG
"sisfb: Initial vbflags 0x%x\n", (int)ivideo
->vbflags
);
6363 ivideo
->mtrr
= mtrr_add(ivideo
->video_base
, ivideo
->video_size
,
6364 MTRR_TYPE_WRCOMB
, 1);
6365 if(ivideo
->mtrr
< 0) {
6366 printk(KERN_DEBUG
"sisfb: Failed to add MTRRs\n");
6370 if(register_framebuffer(sis_fb_info
) < 0) {
6371 printk(KERN_ERR
"sisfb: Fatal error: Failed to register framebuffer\n");
6373 iounmap(ivideo
->mmio_vbase
);
6377 ivideo
->registered
= 1;
6380 ivideo
->next
= card_list
;
6383 printk(KERN_INFO
"sisfb: 2D acceleration is %s, y-panning %s\n",
6384 ivideo
->sisfb_accel
? "enabled" : "disabled",
6385 ivideo
->sisfb_ypan
?
6386 (ivideo
->sisfb_max
? "enabled (auto-max)" :
6387 "enabled (no auto-max)") :
6391 printk(KERN_INFO
"fb%d: %s frame buffer device version %d.%d.%d\n",
6392 sis_fb_info
->node
, ivideo
->myid
, VER_MAJOR
, VER_MINOR
, VER_LEVEL
);
6394 printk(KERN_INFO
"sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
6396 } /* if mode = "none" */
6401 /*****************************************************/
6402 /* PCI DEVICE HANDLING */
6403 /*****************************************************/
6405 static void __devexit
sisfb_remove(struct pci_dev
*pdev
)
6407 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
6408 struct fb_info
*sis_fb_info
= ivideo
->memyselfandi
;
6409 int registered
= ivideo
->registered
;
6410 int modechanged
= ivideo
->modechanged
;
6413 iounmap(ivideo
->mmio_vbase
);
6414 iounmap(ivideo
->video_vbase
);
6416 /* Release mem regions */
6417 release_mem_region(ivideo
->video_base
, ivideo
->video_size
);
6418 release_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
);
6420 vfree(ivideo
->bios_abase
);
6423 pci_dev_put(ivideo
->lpcdev
);
6426 pci_dev_put(ivideo
->nbridge
);
6429 /* Release MTRR region */
6430 if(ivideo
->mtrr
>= 0)
6431 mtrr_del(ivideo
->mtrr
, ivideo
->video_base
, ivideo
->video_size
);
6434 pci_set_drvdata(pdev
, NULL
);
6436 /* If device was disabled when starting, disable
6439 if(!ivideo
->sisvga_enabled
)
6440 pci_disable_device(pdev
);
6442 /* Unregister the framebuffer */
6443 if(ivideo
->registered
) {
6444 unregister_framebuffer(sis_fb_info
);
6445 framebuffer_release(sis_fb_info
);
6448 /* OK, our ivideo is gone for good from here. */
6450 /* TODO: Restore the initial mode
6451 * This sounds easy but is as good as impossible
6452 * on many machines with SiS chip and video bridge
6453 * since text modes are always set up differently
6454 * from machine to machine. Depends on the type
6455 * of integration between chipset and bridge.
6457 if(registered
&& modechanged
)
6459 "sisfb: Restoring of text mode not supported yet\n");
6462 static struct pci_driver sisfb_driver
= {
6464 .id_table
= sisfb_pci_table
,
6465 .probe
= sisfb_probe
,
6466 .remove
= __devexit_p(sisfb_remove
)
6469 static int __init
sisfb_init(void)
6472 char *options
= NULL
;
6474 if(fb_get_options("sisfb", &options
))
6477 sisfb_setup(options
);
6479 return pci_register_driver(&sisfb_driver
);
6483 module_init(sisfb_init
);
6486 /*****************************************************/
6488 /*****************************************************/
6492 static char *mode
= NULL
;
6493 static int vesa
= -1;
6494 static unsigned int rate
= 0;
6495 static unsigned int crt1off
= 1;
6496 static unsigned int mem
= 0;
6497 static char *forcecrt2type
= NULL
;
6498 static int forcecrt1
= -1;
6499 static int pdc
= -1;
6500 static int pdc1
= -1;
6501 static int noaccel
= -1;
6502 static int noypan
= -1;
6503 static int nomax
= -1;
6504 static int userom
= -1;
6505 static int useoem
= -1;
6506 static char *tvstandard
= NULL
;
6507 static int nocrt2rate
= 0;
6508 static int scalelcd
= -1;
6509 static char *specialtiming
= NULL
;
6510 static int lvdshl
= -1;
6511 static int tvxposoffset
= 0, tvyposoffset
= 0;
6512 #if !defined(__i386__) && !defined(__x86_64__)
6513 static int resetcard
= 0;
6514 static int videoram
= 0;
6517 static int __init
sisfb_init_module(void)
6519 sisfb_setdefaultparms();
6522 sisfb_parm_rate
= rate
;
6524 if((scalelcd
== 0) || (scalelcd
== 1))
6525 sisfb_scalelcd
= scalelcd
^ 1;
6527 /* Need to check crt2 type first for fstn/dstn */
6530 sisfb_search_crt2type(forcecrt2type
);
6533 sisfb_search_tvstd(tvstandard
);
6536 sisfb_search_mode(mode
, false);
6538 sisfb_search_vesamode(vesa
, false);
6540 sisfb_crt1off
= (crt1off
== 0) ? 1 : 0;
6542 sisfb_forcecrt1
= forcecrt1
;
6545 else if(forcecrt1
== 0)
6550 else if(noaccel
== 0)
6555 else if(noypan
== 0)
6564 sisfb_parm_mem
= mem
;
6567 sisfb_userom
= userom
;
6570 sisfb_useoem
= useoem
;
6573 sisfb_pdc
= (pdc
& 0x7f);
6576 sisfb_pdca
= (pdc1
& 0x1f);
6578 sisfb_nocrt2rate
= nocrt2rate
;
6581 sisfb_search_specialtiming(specialtiming
);
6583 if((lvdshl
>= 0) && (lvdshl
<= 3))
6584 sisfb_lvdshl
= lvdshl
;
6586 sisfb_tvxposoffset
= tvxposoffset
;
6587 sisfb_tvyposoffset
= tvyposoffset
;
6589 #if !defined(__i386__) && !defined(__x86_64__)
6590 sisfb_resetcard
= (resetcard
) ? 1 : 0;
6592 sisfb_videoram
= videoram
;
6595 return sisfb_init();
6598 static void __exit
sisfb_remove_module(void)
6600 pci_unregister_driver(&sisfb_driver
);
6601 printk(KERN_DEBUG
"sisfb: Module unloaded\n");
6604 module_init(sisfb_init_module
);
6605 module_exit(sisfb_remove_module
);
6607 MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
6608 MODULE_LICENSE("GPL");
6609 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
6611 module_param(mem
, int, 0);
6612 module_param(noaccel
, int, 0);
6613 module_param(noypan
, int, 0);
6614 module_param(nomax
, int, 0);
6615 module_param(userom
, int, 0);
6616 module_param(useoem
, int, 0);
6617 module_param(mode
, charp
, 0);
6618 module_param(vesa
, int, 0);
6619 module_param(rate
, int, 0);
6620 module_param(forcecrt1
, int, 0);
6621 module_param(forcecrt2type
, charp
, 0);
6622 module_param(scalelcd
, int, 0);
6623 module_param(pdc
, int, 0);
6624 module_param(pdc1
, int, 0);
6625 module_param(specialtiming
, charp
, 0);
6626 module_param(lvdshl
, int, 0);
6627 module_param(tvstandard
, charp
, 0);
6628 module_param(tvxposoffset
, int, 0);
6629 module_param(tvyposoffset
, int, 0);
6630 module_param(nocrt2rate
, int, 0);
6631 #if !defined(__i386__) && !defined(__x86_64__)
6632 module_param(resetcard
, int, 0);
6633 module_param(videoram
, int, 0);
6636 MODULE_PARM_DESC(mem
,
6637 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6638 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6639 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6640 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6641 "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6642 "The value is to be specified without 'KB'.\n");
6644 MODULE_PARM_DESC(noaccel
,
6645 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
6648 MODULE_PARM_DESC(noypan
,
6649 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
6650 "will be performed by redrawing the screen. (default: 0)\n");
6652 MODULE_PARM_DESC(nomax
,
6653 "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
6654 "memory for the virtual screen in order to optimize scrolling performance. If\n"
6655 "this is set to anything other than 0, sisfb will not do this and thereby \n"
6656 "enable the user to positively specify a virtual Y size of the screen using\n"
6657 "fbset. (default: 0)\n");
6659 MODULE_PARM_DESC(mode
,
6660 "\nSelects the desired default display mode in the format XxYxDepth,\n"
6661 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
6662 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
6663 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
6665 MODULE_PARM_DESC(vesa
,
6666 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
6667 "0x117 (default: 0x0103)\n");
6669 MODULE_PARM_DESC(rate
,
6670 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
6671 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
6672 "will be ignored (default: 60)\n");
6674 MODULE_PARM_DESC(forcecrt1
,
6675 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
6676 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
6677 "0=CRT1 OFF) (default: [autodetected])\n");
6679 MODULE_PARM_DESC(forcecrt2type
,
6680 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
6681 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
6682 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
6683 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
6684 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
6685 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
6686 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
6687 "depends on the very hardware in use. (default: [autodetected])\n");
6689 MODULE_PARM_DESC(scalelcd
,
6690 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
6691 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
6692 "show black bars around the image, TMDS panels will probably do the scaling\n"
6693 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
6695 MODULE_PARM_DESC(pdc
,
6696 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
6697 "should detect this correctly in most cases; however, sometimes this is not\n"
6698 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
6699 "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
6700 "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
6701 "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
6703 #ifdef CONFIG_FB_SIS_315
6704 MODULE_PARM_DESC(pdc1
,
6705 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
6706 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
6707 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
6708 "implemented yet.\n");
6711 MODULE_PARM_DESC(specialtiming
,
6712 "\nPlease refer to documentation for more information on this option.\n");
6714 MODULE_PARM_DESC(lvdshl
,
6715 "\nPlease refer to documentation for more information on this option.\n");
6717 MODULE_PARM_DESC(tvstandard
,
6718 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
6719 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
6721 MODULE_PARM_DESC(tvxposoffset
,
6722 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
6725 MODULE_PARM_DESC(tvyposoffset
,
6726 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
6729 MODULE_PARM_DESC(nocrt2rate
,
6730 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
6731 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
6733 #if !defined(__i386__) && !defined(__x86_64__)
6734 #ifdef CONFIG_FB_SIS_300
6735 MODULE_PARM_DESC(resetcard
,
6736 "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
6737 "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
6738 "currently). Default: 0\n");
6740 MODULE_PARM_DESC(videoram
,
6741 "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
6742 "some non-x86 architectures where the memory auto detection fails. Only\n"
6743 "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
6747 #endif /* /MODULE */
6749 /* _GPL only for new symbols. */
6750 EXPORT_SYMBOL(sis_malloc
);
6751 EXPORT_SYMBOL(sis_free
);
6752 EXPORT_SYMBOL_GPL(sis_malloc_new
);
6753 EXPORT_SYMBOL_GPL(sis_free_new
);