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 static void sisfb_handle_command(struct sis_video_info
*ivideo
,
64 struct sisfb_cmd
*sisfb_command
);
66 /* ------------------ Internal helper routines ----------------- */
69 sisfb_setdefaultparms(void)
87 sisfb_specialtiming
= CUT_NONE
;
93 sisfb_tvxposoffset
= 0;
94 sisfb_tvyposoffset
= 0;
96 #if !defined(__i386__) && !defined(__x86_64__)
102 /* ------------- Parameter parsing -------------- */
104 static void __devinit
105 sisfb_search_vesamode(unsigned int vesamode
, bool quiet
)
109 /* We don't know the hardware specs yet and there is no ivideo */
113 printk(KERN_ERR
"sisfb: Invalid mode. Using default.\n");
115 sisfb_mode_idx
= DEFAULT_MODE
;
120 vesamode
&= 0x1dff; /* Clean VESA mode number from other flags */
122 while(sisbios_mode
[i
++].mode_no
[0] != 0) {
123 if( (sisbios_mode
[i
-1].vesa_mode_no_1
== vesamode
) ||
124 (sisbios_mode
[i
-1].vesa_mode_no_2
== vesamode
) ) {
126 if(sisbios_mode
[i
-1].mode_no
[1] == 0x50 ||
127 sisbios_mode
[i
-1].mode_no
[1] == 0x56 ||
128 sisbios_mode
[i
-1].mode_no
[1] == 0x53)
131 if(sisbios_mode
[i
-1].mode_no
[1] == 0x5a ||
132 sisbios_mode
[i
-1].mode_no
[1] == 0x5b)
135 sisfb_mode_idx
= i
- 1;
141 printk(KERN_ERR
"sisfb: Invalid VESA mode 0x%x'\n", vesamode
);
144 static void __devinit
145 sisfb_search_mode(char *name
, bool quiet
)
147 unsigned int j
= 0, xres
= 0, yres
= 0, depth
= 0, rate
= 0;
149 char strbuf
[16], strbuf1
[20];
150 char *nameptr
= name
;
152 /* We don't know the hardware specs yet and there is no ivideo */
156 printk(KERN_ERR
"sisfb: Internal error, using default mode.\n");
158 sisfb_mode_idx
= DEFAULT_MODE
;
162 if(!strnicmp(name
, sisbios_mode
[MODE_INDEX_NONE
].name
, strlen(name
))) {
164 printk(KERN_ERR
"sisfb: Mode 'none' not supported anymore. Using default.\n");
166 sisfb_mode_idx
= DEFAULT_MODE
;
170 if(strlen(name
) <= 19) {
171 strcpy(strbuf1
, name
);
172 for(i
= 0; i
< strlen(strbuf1
); i
++) {
173 if(strbuf1
[i
] < '0' || strbuf1
[i
] > '9') strbuf1
[i
] = ' ';
176 /* This does some fuzzy mode naming detection */
177 if(sscanf(strbuf1
, "%u %u %u %u", &xres
, &yres
, &depth
, &rate
) == 4) {
178 if((rate
<= 32) || (depth
> 32)) {
179 j
= rate
; rate
= depth
; depth
= j
;
181 sprintf(strbuf
, "%ux%ux%u", xres
, yres
, depth
);
183 sisfb_parm_rate
= rate
;
184 } else if(sscanf(strbuf1
, "%u %u %u", &xres
, &yres
, &depth
) == 3) {
185 sprintf(strbuf
, "%ux%ux%u", xres
, yres
, depth
);
189 if((sscanf(strbuf1
, "%u %u", &xres
, &yres
) == 2) && (xres
!= 0)) {
190 sprintf(strbuf
, "%ux%ux8", xres
, yres
);
193 sisfb_search_vesamode(simple_strtoul(name
, NULL
, 0), quiet
);
200 while(sisbios_mode
[i
].mode_no
[0] != 0) {
201 if(!strnicmp(nameptr
, sisbios_mode
[i
++].name
, strlen(nameptr
))) {
203 if(sisbios_mode
[i
-1].mode_no
[1] == 0x50 ||
204 sisbios_mode
[i
-1].mode_no
[1] == 0x56 ||
205 sisbios_mode
[i
-1].mode_no
[1] == 0x53)
208 if(sisbios_mode
[i
-1].mode_no
[1] == 0x5a ||
209 sisbios_mode
[i
-1].mode_no
[1] == 0x5b)
212 sisfb_mode_idx
= i
- 1;
219 printk(KERN_ERR
"sisfb: Invalid mode '%s'\n", nameptr
);
223 static void __devinit
224 sisfb_get_vga_mode_from_kernel(void)
228 int mydepth
= screen_info
.lfb_depth
;
230 if(screen_info
.orig_video_isVGA
!= VIDEO_TYPE_VLFB
) return;
232 if( (screen_info
.lfb_width
>= 320) && (screen_info
.lfb_width
<= 2048) &&
233 (screen_info
.lfb_height
>= 200) && (screen_info
.lfb_height
<= 1536) &&
234 (mydepth
>= 8) && (mydepth
<= 32) ) {
236 if(mydepth
== 24) mydepth
= 32;
238 sprintf(mymode
, "%ux%ux%u", screen_info
.lfb_width
,
239 screen_info
.lfb_height
,
243 "sisfb: Using vga mode %s pre-set by kernel as default\n",
246 sisfb_search_mode(mymode
, true);
254 sisfb_search_crt2type(const char *name
)
258 /* We don't know the hardware specs yet and there is no ivideo */
260 if(name
== NULL
) return;
262 while(sis_crt2type
[i
].type_no
!= -1) {
263 if(!strnicmp(name
, sis_crt2type
[i
].name
, strlen(sis_crt2type
[i
].name
))) {
264 sisfb_crt2type
= sis_crt2type
[i
].type_no
;
265 sisfb_tvplug
= sis_crt2type
[i
].tvplug_no
;
266 sisfb_crt2flags
= sis_crt2type
[i
].flags
;
272 sisfb_dstn
= (sisfb_crt2flags
& FL_550_DSTN
) ? 1 : 0;
273 sisfb_fstn
= (sisfb_crt2flags
& FL_550_FSTN
) ? 1 : 0;
275 if(sisfb_crt2type
< 0)
276 printk(KERN_ERR
"sisfb: Invalid CRT2 type: %s\n", name
);
280 sisfb_search_tvstd(const char *name
)
284 /* We don't know the hardware specs yet and there is no ivideo */
289 while(sis_tvtype
[i
].type_no
!= -1) {
290 if(!strnicmp(name
, sis_tvtype
[i
].name
, strlen(sis_tvtype
[i
].name
))) {
291 sisfb_tvstd
= sis_tvtype
[i
].type_no
;
299 sisfb_search_specialtiming(const char *name
)
304 /* We don't know the hardware specs yet and there is no ivideo */
309 if(!strnicmp(name
, "none", 4)) {
310 sisfb_specialtiming
= CUT_FORCENONE
;
311 printk(KERN_DEBUG
"sisfb: Special timing disabled\n");
313 while(mycustomttable
[i
].chipID
!= 0) {
314 if(!strnicmp(name
,mycustomttable
[i
].optionName
,
315 strlen(mycustomttable
[i
].optionName
))) {
316 sisfb_specialtiming
= mycustomttable
[i
].SpecialID
;
318 printk(KERN_INFO
"sisfb: Special timing for %s %s forced (\"%s\")\n",
319 mycustomttable
[i
].vendorName
,
320 mycustomttable
[i
].cardName
,
321 mycustomttable
[i
].optionName
);
327 printk(KERN_WARNING
"sisfb: Invalid SpecialTiming parameter, valid are:");
328 printk(KERN_WARNING
"\t\"none\" (to disable special timings)\n");
330 while(mycustomttable
[i
].chipID
!= 0) {
331 printk(KERN_WARNING
"\t\"%s\" (for %s %s)\n",
332 mycustomttable
[i
].optionName
,
333 mycustomttable
[i
].vendorName
,
334 mycustomttable
[i
].cardName
);
341 /* ----------- Various detection routines ----------- */
343 static void __devinit
344 sisfb_detect_custom_timing(struct sis_video_info
*ivideo
)
346 unsigned char *biosver
= NULL
;
347 unsigned char *biosdate
= NULL
;
352 if(ivideo
->SiS_Pr
.UseROM
) {
353 biosver
= ivideo
->SiS_Pr
.VirtualRomBase
+ 0x06;
354 biosdate
= ivideo
->SiS_Pr
.VirtualRomBase
+ 0x2c;
355 for(i
= 0; i
< 32768; i
++)
356 chksum
+= ivideo
->SiS_Pr
.VirtualRomBase
[i
];
361 if( (mycustomttable
[i
].chipID
== ivideo
->chip
) &&
362 ((!strlen(mycustomttable
[i
].biosversion
)) ||
363 (ivideo
->SiS_Pr
.UseROM
&&
364 (!strncmp(mycustomttable
[i
].biosversion
, biosver
,
365 strlen(mycustomttable
[i
].biosversion
))))) &&
366 ((!strlen(mycustomttable
[i
].biosdate
)) ||
367 (ivideo
->SiS_Pr
.UseROM
&&
368 (!strncmp(mycustomttable
[i
].biosdate
, biosdate
,
369 strlen(mycustomttable
[i
].biosdate
))))) &&
370 ((!mycustomttable
[i
].bioschksum
) ||
371 (ivideo
->SiS_Pr
.UseROM
&&
372 (mycustomttable
[i
].bioschksum
== chksum
))) &&
373 (mycustomttable
[i
].pcisubsysvendor
== ivideo
->subsysvendor
) &&
374 (mycustomttable
[i
].pcisubsyscard
== ivideo
->subsysdevice
) ) {
376 for(j
= 0; j
< 5; j
++) {
377 if(mycustomttable
[i
].biosFootprintAddr
[j
]) {
378 if(ivideo
->SiS_Pr
.UseROM
) {
379 if(ivideo
->SiS_Pr
.VirtualRomBase
[mycustomttable
[i
].biosFootprintAddr
[j
]] !=
380 mycustomttable
[i
].biosFootprintData
[j
]) {
388 ivideo
->SiS_Pr
.SiS_CustomT
= mycustomttable
[i
].SpecialID
;
389 printk(KERN_DEBUG
"sisfb: Identified [%s %s], special timing applies\n",
390 mycustomttable
[i
].vendorName
,
391 mycustomttable
[i
].cardName
);
392 printk(KERN_DEBUG
"sisfb: [specialtiming parameter name: %s]\n",
393 mycustomttable
[i
].optionName
);
398 } while(mycustomttable
[i
].chipID
);
401 static bool __devinit
402 sisfb_interpret_edid(struct sisfb_monitor
*monitor
, u8
*buffer
)
404 int i
, j
, xres
, yres
, refresh
, index
;
407 if(buffer
[0] != 0x00 || buffer
[1] != 0xff ||
408 buffer
[2] != 0xff || buffer
[3] != 0xff ||
409 buffer
[4] != 0xff || buffer
[5] != 0xff ||
410 buffer
[6] != 0xff || buffer
[7] != 0x00) {
411 printk(KERN_DEBUG
"sisfb: Bad EDID header\n");
415 if(buffer
[0x12] != 0x01) {
416 printk(KERN_INFO
"sisfb: EDID version %d not supported\n",
421 monitor
->feature
= buffer
[0x18];
423 if(!(buffer
[0x14] & 0x80)) {
424 if(!(buffer
[0x14] & 0x08)) {
426 "sisfb: WARNING: Monitor does not support separate syncs\n");
430 if(buffer
[0x13] >= 0x01) {
431 /* EDID V1 rev 1 and 2: Search for monitor descriptor
436 if(buffer
[j
] == 0x00 && buffer
[j
+ 1] == 0x00 &&
437 buffer
[j
+ 2] == 0x00 && buffer
[j
+ 3] == 0xfd &&
438 buffer
[j
+ 4] == 0x00) {
439 monitor
->hmin
= buffer
[j
+ 7];
440 monitor
->hmax
= buffer
[j
+ 8];
441 monitor
->vmin
= buffer
[j
+ 5];
442 monitor
->vmax
= buffer
[j
+ 6];
443 monitor
->dclockmax
= buffer
[j
+ 9] * 10 * 1000;
444 monitor
->datavalid
= true;
451 if(!monitor
->datavalid
) {
452 /* Otherwise: Get a range from the list of supported
453 * Estabished Timings. This is not entirely accurate,
454 * because fixed frequency monitors are not supported
457 monitor
->hmin
= 65535; monitor
->hmax
= 0;
458 monitor
->vmin
= 65535; monitor
->vmax
= 0;
459 monitor
->dclockmax
= 0;
460 emodes
= buffer
[0x23] | (buffer
[0x24] << 8) | (buffer
[0x25] << 16);
461 for(i
= 0; i
< 13; i
++) {
462 if(emodes
& sisfb_ddcsmodes
[i
].mask
) {
463 if(monitor
->hmin
> sisfb_ddcsmodes
[i
].h
) monitor
->hmin
= sisfb_ddcsmodes
[i
].h
;
464 if(monitor
->hmax
< sisfb_ddcsmodes
[i
].h
) monitor
->hmax
= sisfb_ddcsmodes
[i
].h
+ 1;
465 if(monitor
->vmin
> sisfb_ddcsmodes
[i
].v
) monitor
->vmin
= sisfb_ddcsmodes
[i
].v
;
466 if(monitor
->vmax
< sisfb_ddcsmodes
[i
].v
) monitor
->vmax
= sisfb_ddcsmodes
[i
].v
;
467 if(monitor
->dclockmax
< sisfb_ddcsmodes
[i
].d
) monitor
->dclockmax
= sisfb_ddcsmodes
[i
].d
;
471 for(i
= 0; i
< 8; i
++) {
472 xres
= (buffer
[index
] + 31) * 8;
473 switch(buffer
[index
+ 1] & 0xc0) {
474 case 0xc0: yres
= (xres
* 9) / 16; break;
475 case 0x80: yres
= (xres
* 4) / 5; break;
476 case 0x40: yres
= (xres
* 3) / 4; break;
477 default: yres
= xres
; break;
479 refresh
= (buffer
[index
+ 1] & 0x3f) + 60;
480 if((xres
>= 640) && (yres
>= 480)) {
481 for(j
= 0; j
< 8; j
++) {
482 if((xres
== sisfb_ddcfmodes
[j
].x
) &&
483 (yres
== sisfb_ddcfmodes
[j
].y
) &&
484 (refresh
== sisfb_ddcfmodes
[j
].v
)) {
485 if(monitor
->hmin
> sisfb_ddcfmodes
[j
].h
) monitor
->hmin
= sisfb_ddcfmodes
[j
].h
;
486 if(monitor
->hmax
< sisfb_ddcfmodes
[j
].h
) monitor
->hmax
= sisfb_ddcfmodes
[j
].h
+ 1;
487 if(monitor
->vmin
> sisfb_ddcsmodes
[j
].v
) monitor
->vmin
= sisfb_ddcsmodes
[j
].v
;
488 if(monitor
->vmax
< sisfb_ddcsmodes
[j
].v
) monitor
->vmax
= sisfb_ddcsmodes
[j
].v
;
489 if(monitor
->dclockmax
< sisfb_ddcsmodes
[j
].d
) monitor
->dclockmax
= sisfb_ddcsmodes
[j
].d
;
495 if((monitor
->hmin
<= monitor
->hmax
) && (monitor
->vmin
<= monitor
->vmax
)) {
496 monitor
->datavalid
= true;
500 return monitor
->datavalid
;
503 static void __devinit
504 sisfb_handle_ddc(struct sis_video_info
*ivideo
, struct sisfb_monitor
*monitor
, int crtno
)
506 unsigned short temp
, i
, realcrtno
= crtno
;
507 unsigned char buffer
[256];
509 monitor
->datavalid
= false;
512 if(ivideo
->vbflags
& CRT2_LCD
) realcrtno
= 1;
513 else if(ivideo
->vbflags
& CRT2_VGA
) realcrtno
= 2;
517 if((ivideo
->sisfb_crt1off
) && (!crtno
))
520 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
521 realcrtno
, 0, &buffer
[0], ivideo
->vbflags2
);
522 if((!temp
) || (temp
== 0xffff)) {
523 printk(KERN_INFO
"sisfb: CRT%d DDC probing failed\n", crtno
+ 1);
526 printk(KERN_INFO
"sisfb: CRT%d DDC supported\n", crtno
+ 1);
527 printk(KERN_INFO
"sisfb: CRT%d DDC level: %s%s%s%s\n",
529 (temp
& 0x1a) ? "" : "[none of the supported]",
530 (temp
& 0x02) ? "2 " : "",
531 (temp
& 0x08) ? "D&P" : "",
532 (temp
& 0x10) ? "FPDI-2" : "");
534 i
= 3; /* Number of retrys */
536 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
537 realcrtno
, 1, &buffer
[0], ivideo
->vbflags2
);
538 } while((temp
) && i
--);
540 if(sisfb_interpret_edid(monitor
, &buffer
[0])) {
541 printk(KERN_INFO
"sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
542 monitor
->hmin
, monitor
->hmax
, monitor
->vmin
, monitor
->vmax
,
543 monitor
->dclockmax
/ 1000);
545 printk(KERN_INFO
"sisfb: CRT%d DDC EDID corrupt\n", crtno
+ 1);
548 printk(KERN_INFO
"sisfb: CRT%d DDC reading failed\n", crtno
+ 1);
551 printk(KERN_INFO
"sisfb: VESA D&P and FPDI-2 not supported yet\n");
556 /* -------------- Mode validation --------------- */
559 sisfb_verify_rate(struct sis_video_info
*ivideo
, struct sisfb_monitor
*monitor
,
560 int mode_idx
, int rate_idx
, int rate
)
563 unsigned int dclock
, hsync
;
565 if(!monitor
->datavalid
)
571 /* Skip for 320x200, 320x240, 640x400 */
572 switch(sisbios_mode
[mode_idx
].mode_no
[ivideo
->mni
]) {
583 #ifdef CONFIG_FB_SIS_315
586 if(ivideo
->sisvga_engine
== SIS_315_VGA
) return true;
590 if(rate
< (monitor
->vmin
- 1))
592 if(rate
> (monitor
->vmax
+ 1))
595 if(sisfb_gettotalfrommode(&ivideo
->SiS_Pr
,
596 sisbios_mode
[mode_idx
].mode_no
[ivideo
->mni
],
597 &htotal
, &vtotal
, rate_idx
)) {
598 dclock
= (htotal
* vtotal
* rate
) / 1000;
599 if(dclock
> (monitor
->dclockmax
+ 1000))
601 hsync
= dclock
/ htotal
;
602 if(hsync
< (monitor
->hmin
- 1))
604 if(hsync
> (monitor
->hmax
+ 1))
613 sisfb_validate_mode(struct sis_video_info
*ivideo
, int myindex
, u32 vbflags
)
615 u16 xres
=0, yres
, myres
;
617 #ifdef CONFIG_FB_SIS_300
618 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
619 if(!(sisbios_mode
[myindex
].chipset
& MD_SIS300
))
623 #ifdef CONFIG_FB_SIS_315
624 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
625 if(!(sisbios_mode
[myindex
].chipset
& MD_SIS315
))
630 myres
= sisbios_mode
[myindex
].yres
;
632 switch(vbflags
& VB_DISPTYPE_DISP2
) {
635 xres
= ivideo
->lcdxres
; yres
= ivideo
->lcdyres
;
637 if((ivideo
->SiS_Pr
.SiS_CustomT
!= CUT_PANEL848
) &&
638 (ivideo
->SiS_Pr
.SiS_CustomT
!= CUT_PANEL856
)) {
639 if(sisbios_mode
[myindex
].xres
> xres
)
645 if(ivideo
->sisfb_fstn
) {
646 if(sisbios_mode
[myindex
].xres
== 320) {
648 switch(sisbios_mode
[myindex
].mode_no
[1]) {
649 case 0x50: myindex
= MODE_FSTN_8
; break;
650 case 0x56: myindex
= MODE_FSTN_16
; break;
651 case 0x53: return -1;
657 if(SiS_GetModeID_LCD(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
658 sisbios_mode
[myindex
].yres
, 0, ivideo
->sisfb_fstn
,
659 ivideo
->SiS_Pr
.SiS_CustomT
, xres
, yres
, ivideo
->vbflags2
) < 0x14) {
665 if(SiS_GetModeID_TV(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
666 sisbios_mode
[myindex
].yres
, 0, ivideo
->vbflags2
) < 0x14) {
672 if(SiS_GetModeID_VGA2(ivideo
->sisvga_engine
, vbflags
, sisbios_mode
[myindex
].xres
,
673 sisbios_mode
[myindex
].yres
, 0, ivideo
->vbflags2
) < 0x14) {
683 sisfb_search_refresh_rate(struct sis_video_info
*ivideo
, unsigned int rate
, int mode_idx
)
686 u16 xres
= sisbios_mode
[mode_idx
].xres
;
687 u16 yres
= sisbios_mode
[mode_idx
].yres
;
689 ivideo
->rate_idx
= 0;
690 while((sisfb_vrate
[i
].idx
!= 0) && (sisfb_vrate
[i
].xres
<= xres
)) {
691 if((sisfb_vrate
[i
].xres
== xres
) && (sisfb_vrate
[i
].yres
== yres
)) {
692 if(sisfb_vrate
[i
].refresh
== rate
) {
693 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
695 } else if(sisfb_vrate
[i
].refresh
> rate
) {
696 if((sisfb_vrate
[i
].refresh
- rate
) <= 3) {
697 DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
698 rate
, sisfb_vrate
[i
].refresh
);
699 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
700 ivideo
->refresh_rate
= sisfb_vrate
[i
].refresh
;
701 } else if((sisfb_vrate
[i
].idx
!= 1) &&
702 ((rate
- sisfb_vrate
[i
-1].refresh
) <= 2)) {
703 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
704 rate
, sisfb_vrate
[i
-1].refresh
);
705 ivideo
->rate_idx
= sisfb_vrate
[i
-1].idx
;
706 ivideo
->refresh_rate
= sisfb_vrate
[i
-1].refresh
;
709 } else if((rate
- sisfb_vrate
[i
].refresh
) <= 2) {
710 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
711 rate
, sisfb_vrate
[i
].refresh
);
712 ivideo
->rate_idx
= sisfb_vrate
[i
].idx
;
718 if(ivideo
->rate_idx
> 0) {
719 return ivideo
->rate_idx
;
721 printk(KERN_INFO
"sisfb: Unsupported rate %d for %dx%d\n",
728 sisfb_bridgeisslave(struct sis_video_info
*ivideo
)
732 if(!(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
))
735 inSISIDXREG(SISPART1
,0x00,P1_00
);
736 if( ((ivideo
->sisvga_engine
== SIS_300_VGA
) && (P1_00
& 0xa0) == 0x20) ||
737 ((ivideo
->sisvga_engine
== SIS_315_VGA
) && (P1_00
& 0x50) == 0x10) ) {
745 sisfballowretracecrt1(struct sis_video_info
*ivideo
)
749 inSISIDXREG(SISCR
,0x17,temp
);
753 inSISIDXREG(SISSR
,0x1f,temp
);
761 sisfbcheckvretracecrt1(struct sis_video_info
*ivideo
)
763 if(!sisfballowretracecrt1(ivideo
))
766 if(inSISREG(SISINPSTAT
) & 0x08)
773 sisfbwaitretracecrt1(struct sis_video_info
*ivideo
)
777 if(!sisfballowretracecrt1(ivideo
))
781 while((!(inSISREG(SISINPSTAT
) & 0x08)) && --watchdog
);
783 while((inSISREG(SISINPSTAT
) & 0x08) && --watchdog
);
787 sisfbcheckvretracecrt2(struct sis_video_info
*ivideo
)
789 unsigned char temp
, reg
;
791 switch(ivideo
->sisvga_engine
) {
792 case SIS_300_VGA
: reg
= 0x25; break;
793 case SIS_315_VGA
: reg
= 0x30; break;
794 default: return false;
797 inSISIDXREG(SISPART1
, reg
, temp
);
805 sisfb_CheckVBRetrace(struct sis_video_info
*ivideo
)
807 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
808 if(!sisfb_bridgeisslave(ivideo
)) {
809 return sisfbcheckvretracecrt2(ivideo
);
812 return sisfbcheckvretracecrt1(ivideo
);
816 sisfb_setupvbblankflags(struct sis_video_info
*ivideo
, u32
*vcount
, u32
*hcount
)
818 u8 idx
, reg1
, reg2
, reg3
, reg4
;
821 (*vcount
) = (*hcount
) = 0;
823 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) && (!(sisfb_bridgeisslave(ivideo
)))) {
825 ret
|= (FB_VBLANK_HAVE_VSYNC
|
826 FB_VBLANK_HAVE_HBLANK
|
827 FB_VBLANK_HAVE_VBLANK
|
828 FB_VBLANK_HAVE_VCOUNT
|
829 FB_VBLANK_HAVE_HCOUNT
);
830 switch(ivideo
->sisvga_engine
) {
831 case SIS_300_VGA
: idx
= 0x25; break;
833 case SIS_315_VGA
: idx
= 0x30; break;
835 inSISIDXREG(SISPART1
,(idx
+0),reg1
); /* 30 */
836 inSISIDXREG(SISPART1
,(idx
+1),reg2
); /* 31 */
837 inSISIDXREG(SISPART1
,(idx
+2),reg3
); /* 32 */
838 inSISIDXREG(SISPART1
,(idx
+3),reg4
); /* 33 */
839 if(reg1
& 0x01) ret
|= FB_VBLANK_VBLANKING
;
840 if(reg1
& 0x02) ret
|= FB_VBLANK_VSYNCING
;
841 if(reg4
& 0x80) ret
|= FB_VBLANK_HBLANKING
;
842 (*vcount
) = reg3
| ((reg4
& 0x70) << 4);
843 (*hcount
) = reg2
| ((reg4
& 0x0f) << 8);
845 } else if(sisfballowretracecrt1(ivideo
)) {
847 ret
|= (FB_VBLANK_HAVE_VSYNC
|
848 FB_VBLANK_HAVE_VBLANK
|
849 FB_VBLANK_HAVE_VCOUNT
|
850 FB_VBLANK_HAVE_HCOUNT
);
851 reg1
= inSISREG(SISINPSTAT
);
852 if(reg1
& 0x08) ret
|= FB_VBLANK_VSYNCING
;
853 if(reg1
& 0x01) ret
|= FB_VBLANK_VBLANKING
;
854 inSISIDXREG(SISCR
,0x20,reg1
);
855 inSISIDXREG(SISCR
,0x1b,reg1
);
856 inSISIDXREG(SISCR
,0x1c,reg2
);
857 inSISIDXREG(SISCR
,0x1d,reg3
);
858 (*vcount
) = reg2
| ((reg3
& 0x07) << 8);
859 (*hcount
) = (reg1
| ((reg3
& 0x10) << 4)) << 3;
866 sisfb_myblank(struct sis_video_info
*ivideo
, int blank
)
868 u8 sr01
, sr11
, sr1f
, cr63
=0, p2_0
, p1_13
;
869 bool backlight
= true;
872 case FB_BLANK_UNBLANK
: /* on */
881 case FB_BLANK_NORMAL
: /* blank */
890 case FB_BLANK_VSYNC_SUSPEND
: /* no vsync */
899 case FB_BLANK_HSYNC_SUSPEND
: /* no hsync */
908 case FB_BLANK_POWERDOWN
: /* off */
921 if(ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
) {
923 if( (!ivideo
->sisfb_thismonitor
.datavalid
) ||
924 ((ivideo
->sisfb_thismonitor
.datavalid
) &&
925 (ivideo
->sisfb_thismonitor
.feature
& 0xe0))) {
927 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
928 setSISIDXREG(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, 0xbf, cr63
);
931 if(!(sisfb_bridgeisslave(ivideo
))) {
932 setSISIDXREG(SISSR
, 0x01, ~0x20, sr01
);
933 setSISIDXREG(SISSR
, 0x1f, 0x3f, sr1f
);
939 if(ivideo
->currentvbflags
& CRT2_LCD
) {
941 if(ivideo
->vbflags2
& VB2_SISLVDSBRIDGE
) {
943 SiS_SiS30xBLOn(&ivideo
->SiS_Pr
);
945 SiS_SiS30xBLOff(&ivideo
->SiS_Pr
);
947 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
948 #ifdef CONFIG_FB_SIS_315
949 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
951 SiS_Chrontel701xBLOn(&ivideo
->SiS_Pr
);
953 SiS_Chrontel701xBLOff(&ivideo
->SiS_Pr
);
959 if(((ivideo
->sisvga_engine
== SIS_300_VGA
) &&
960 (ivideo
->vbflags2
& (VB2_301
|VB2_30xBDH
|VB2_LVDS
))) ||
961 ((ivideo
->sisvga_engine
== SIS_315_VGA
) &&
962 ((ivideo
->vbflags2
& (VB2_LVDS
| VB2_CHRONTEL
)) == VB2_LVDS
))) {
963 setSISIDXREG(SISSR
, 0x11, ~0x0c, sr11
);
966 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
967 if((ivideo
->vbflags2
& VB2_30xB
) &&
968 (!(ivideo
->vbflags2
& VB2_30xBDH
))) {
969 setSISIDXREG(SISPART1
, 0x13, 0x3f, p1_13
);
971 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
972 if((ivideo
->vbflags2
& VB2_30xB
) &&
973 (!(ivideo
->vbflags2
& VB2_30xBDH
))) {
974 setSISIDXREG(SISPART2
, 0x00, 0x1f, p2_0
);
978 } else if(ivideo
->currentvbflags
& CRT2_VGA
) {
980 if(ivideo
->vbflags2
& VB2_30xB
) {
981 setSISIDXREG(SISPART2
, 0x00, 0x1f, p2_0
);
989 /* ------------- Callbacks from init.c/init301.c -------------- */
991 #ifdef CONFIG_FB_SIS_300
993 sisfb_read_nbridge_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
)
995 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
998 pci_read_config_dword(ivideo
->nbridge
, reg
, &val
);
999 return (unsigned int)val
;
1003 sisfb_write_nbridge_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
, unsigned int val
)
1005 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1007 pci_write_config_dword(ivideo
->nbridge
, reg
, (u32
)val
);
1011 sisfb_read_lpc_pci_dword(struct SiS_Private
*SiS_Pr
, int reg
)
1013 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1016 if(!ivideo
->lpcdev
) return 0;
1018 pci_read_config_dword(ivideo
->lpcdev
, reg
, &val
);
1019 return (unsigned int)val
;
1023 #ifdef CONFIG_FB_SIS_315
1025 sisfb_write_nbridge_pci_byte(struct SiS_Private
*SiS_Pr
, int reg
, unsigned char val
)
1027 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1029 pci_write_config_byte(ivideo
->nbridge
, reg
, (u8
)val
);
1033 sisfb_read_mio_pci_word(struct SiS_Private
*SiS_Pr
, int reg
)
1035 struct sis_video_info
*ivideo
= (struct sis_video_info
*)SiS_Pr
->ivideo
;
1038 if(!ivideo
->lpcdev
) return 0;
1040 pci_read_config_word(ivideo
->lpcdev
, reg
, &val
);
1041 return (unsigned int)val
;
1045 /* ----------- FBDev related routines for all series ----------- */
1048 sisfb_get_cmap_len(const struct fb_var_screeninfo
*var
)
1050 return (var
->bits_per_pixel
== 8) ? 256 : 16;
1054 sisfb_set_vparms(struct sis_video_info
*ivideo
)
1056 switch(ivideo
->video_bpp
) {
1058 ivideo
->DstColor
= 0x0000;
1059 ivideo
->SiS310_AccelDepth
= 0x00000000;
1060 ivideo
->video_cmap_len
= 256;
1063 ivideo
->DstColor
= 0x8000;
1064 ivideo
->SiS310_AccelDepth
= 0x00010000;
1065 ivideo
->video_cmap_len
= 16;
1068 ivideo
->DstColor
= 0xC000;
1069 ivideo
->SiS310_AccelDepth
= 0x00020000;
1070 ivideo
->video_cmap_len
= 16;
1073 ivideo
->video_cmap_len
= 16;
1074 printk(KERN_ERR
"sisfb: Unsupported depth %d", ivideo
->video_bpp
);
1080 sisfb_calc_maxyres(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1082 int maxyres
= ivideo
->sisfb_mem
/ (var
->xres_virtual
* (var
->bits_per_pixel
>> 3));
1084 if(maxyres
> 32767) maxyres
= 32767;
1090 sisfb_calc_pitch(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1092 ivideo
->video_linelength
= var
->xres_virtual
* (var
->bits_per_pixel
>> 3);
1093 ivideo
->scrnpitchCRT1
= ivideo
->video_linelength
;
1094 if(!(ivideo
->currentvbflags
& CRT1_LCDA
)) {
1095 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1096 ivideo
->scrnpitchCRT1
<<= 1;
1102 sisfb_set_pitch(struct sis_video_info
*ivideo
)
1104 bool isslavemode
= false;
1105 unsigned short HDisplay1
= ivideo
->scrnpitchCRT1
>> 3;
1106 unsigned short HDisplay2
= ivideo
->video_linelength
>> 3;
1108 if(sisfb_bridgeisslave(ivideo
)) isslavemode
= true;
1110 /* We need to set pitch for CRT1 if bridge is in slave mode, too */
1111 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP1
) || (isslavemode
)) {
1112 outSISIDXREG(SISCR
,0x13,(HDisplay1
& 0xFF));
1113 setSISIDXREG(SISSR
,0x0E,0xF0,(HDisplay1
>> 8));
1116 /* We must not set the pitch for CRT2 if bridge is in slave mode */
1117 if((ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) && (!isslavemode
)) {
1118 orSISIDXREG(SISPART1
,ivideo
->CRT2_write_enable
,0x01);
1119 outSISIDXREG(SISPART1
,0x07,(HDisplay2
& 0xFF));
1120 setSISIDXREG(SISPART1
,0x09,0xF0,(HDisplay2
>> 8));
1125 sisfb_bpp_to_var(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1127 ivideo
->video_cmap_len
= sisfb_get_cmap_len(var
);
1129 switch(var
->bits_per_pixel
) {
1131 var
->red
.offset
= var
->green
.offset
= var
->blue
.offset
= 0;
1132 var
->red
.length
= var
->green
.length
= var
->blue
.length
= 8;
1135 var
->red
.offset
= 11;
1136 var
->red
.length
= 5;
1137 var
->green
.offset
= 5;
1138 var
->green
.length
= 6;
1139 var
->blue
.offset
= 0;
1140 var
->blue
.length
= 5;
1141 var
->transp
.offset
= 0;
1142 var
->transp
.length
= 0;
1145 var
->red
.offset
= 16;
1146 var
->red
.length
= 8;
1147 var
->green
.offset
= 8;
1148 var
->green
.length
= 8;
1149 var
->blue
.offset
= 0;
1150 var
->blue
.length
= 8;
1151 var
->transp
.offset
= 24;
1152 var
->transp
.length
= 8;
1158 sisfb_set_mode(struct sis_video_info
*ivideo
, int clrscrn
)
1160 unsigned short modeno
= ivideo
->mode_no
;
1162 /* >=2.6.12's fbcon clears the screen anyway */
1165 outSISIDXREG(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1167 sisfb_pre_setmode(ivideo
);
1169 if(!SiSSetMode(&ivideo
->SiS_Pr
, modeno
)) {
1170 printk(KERN_ERR
"sisfb: Setting mode[0x%x] failed\n", ivideo
->mode_no
);
1174 outSISIDXREG(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1176 sisfb_post_setmode(ivideo
);
1183 sisfb_do_set_var(struct fb_var_screeninfo
*var
, int isactive
, struct fb_info
*info
)
1185 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1186 unsigned int htotal
= 0, vtotal
= 0;
1187 unsigned int drate
= 0, hrate
= 0;
1188 int found_mode
= 0, ret
;
1192 htotal
= var
->left_margin
+ var
->xres
+ var
->right_margin
+ var
->hsync_len
;
1194 vtotal
= var
->upper_margin
+ var
->lower_margin
+ var
->vsync_len
;
1196 pixclock
= var
->pixclock
;
1198 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
) {
1199 vtotal
+= var
->yres
;
1201 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1202 vtotal
+= var
->yres
;
1204 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1205 vtotal
+= var
->yres
;
1207 } else vtotal
+= var
->yres
;
1209 if(!(htotal
) || !(vtotal
)) {
1210 DPRINTK("sisfb: Invalid 'var' information\n");
1214 if(pixclock
&& htotal
&& vtotal
) {
1215 drate
= 1000000000 / pixclock
;
1216 hrate
= (drate
* 1000) / htotal
;
1217 ivideo
->refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1219 ivideo
->refresh_rate
= 60;
1222 old_mode
= ivideo
->sisfb_mode_idx
;
1223 ivideo
->sisfb_mode_idx
= 0;
1225 while( (sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[0] != 0) &&
1226 (sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
<= var
->xres
) ) {
1227 if( (sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
== var
->xres
) &&
1228 (sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
== var
->yres
) &&
1229 (sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
== var
->bits_per_pixel
)) {
1230 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
1234 ivideo
->sisfb_mode_idx
++;
1238 ivideo
->sisfb_mode_idx
= sisfb_validate_mode(ivideo
,
1239 ivideo
->sisfb_mode_idx
, ivideo
->currentvbflags
);
1241 ivideo
->sisfb_mode_idx
= -1;
1244 if(ivideo
->sisfb_mode_idx
< 0) {
1245 printk(KERN_ERR
"sisfb: Mode %dx%dx%d not supported\n", var
->xres
,
1246 var
->yres
, var
->bits_per_pixel
);
1247 ivideo
->sisfb_mode_idx
= old_mode
;
1251 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
1253 if(sisfb_search_refresh_rate(ivideo
, ivideo
->refresh_rate
, ivideo
->sisfb_mode_idx
) == 0) {
1254 ivideo
->rate_idx
= sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
;
1255 ivideo
->refresh_rate
= 60;
1259 /* If acceleration to be used? Need to know
1260 * before pre/post_set_mode()
1263 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
1264 #ifdef STUPID_ACCELF_TEXT_SHIT
1265 if(var
->accel_flags
& FB_ACCELF_TEXT
) {
1266 info
->flags
&= ~FBINFO_HWACCEL_DISABLED
;
1268 info
->flags
|= FBINFO_HWACCEL_DISABLED
;
1271 if(!(info
->flags
& FBINFO_HWACCEL_DISABLED
)) ivideo
->accel
= -1;
1273 if(var
->accel_flags
& FB_ACCELF_TEXT
) ivideo
->accel
= -1;
1276 if((ret
= sisfb_set_mode(ivideo
, 1))) {
1280 ivideo
->video_bpp
= sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
;
1281 ivideo
->video_width
= sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
;
1282 ivideo
->video_height
= sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
;
1284 sisfb_calc_pitch(ivideo
, var
);
1285 sisfb_set_pitch(ivideo
);
1287 sisfb_set_vparms(ivideo
);
1289 ivideo
->current_width
= ivideo
->video_width
;
1290 ivideo
->current_height
= ivideo
->video_height
;
1291 ivideo
->current_bpp
= ivideo
->video_bpp
;
1292 ivideo
->current_htotal
= htotal
;
1293 ivideo
->current_vtotal
= vtotal
;
1294 ivideo
->current_linelength
= ivideo
->video_linelength
;
1295 ivideo
->current_pixclock
= var
->pixclock
;
1296 ivideo
->current_refresh_rate
= ivideo
->refresh_rate
;
1297 ivideo
->sisfb_lastrates
[ivideo
->mode_no
] = ivideo
->refresh_rate
;
1304 sisfb_set_base_CRT1(struct sis_video_info
*ivideo
, unsigned int base
)
1306 outSISIDXREG(SISSR
, IND_SIS_PASSWORD
, SIS_PASSWORD
);
1308 outSISIDXREG(SISCR
, 0x0D, base
& 0xFF);
1309 outSISIDXREG(SISCR
, 0x0C, (base
>> 8) & 0xFF);
1310 outSISIDXREG(SISSR
, 0x0D, (base
>> 16) & 0xFF);
1311 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
1312 setSISIDXREG(SISSR
, 0x37, 0xFE, (base
>> 24) & 0x01);
1317 sisfb_set_base_CRT2(struct sis_video_info
*ivideo
, unsigned int base
)
1319 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
1320 orSISIDXREG(SISPART1
, ivideo
->CRT2_write_enable
, 0x01);
1321 outSISIDXREG(SISPART1
, 0x06, (base
& 0xFF));
1322 outSISIDXREG(SISPART1
, 0x05, ((base
>> 8) & 0xFF));
1323 outSISIDXREG(SISPART1
, 0x04, ((base
>> 16) & 0xFF));
1324 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
1325 setSISIDXREG(SISPART1
, 0x02, 0x7F, ((base
>> 24) & 0x01) << 7);
1331 sisfb_pan_var(struct sis_video_info
*ivideo
, struct fb_var_screeninfo
*var
)
1333 if(var
->xoffset
> (var
->xres_virtual
- var
->xres
)) {
1336 if(var
->yoffset
> (var
->yres_virtual
- var
->yres
)) {
1340 ivideo
->current_base
= (var
->yoffset
* var
->xres_virtual
) + var
->xoffset
;
1342 /* calculate base bpp dep. */
1343 switch(var
->bits_per_pixel
) {
1347 ivideo
->current_base
>>= 1;
1351 ivideo
->current_base
>>= 2;
1355 ivideo
->current_base
+= (ivideo
->video_offset
>> 2);
1357 sisfb_set_base_CRT1(ivideo
, ivideo
->current_base
);
1358 sisfb_set_base_CRT2(ivideo
, ivideo
->current_base
);
1364 sisfb_open(struct fb_info
*info
, int user
)
1370 sisfb_release(struct fb_info
*info
, int user
)
1376 sisfb_setcolreg(unsigned regno
, unsigned red
, unsigned green
, unsigned blue
,
1377 unsigned transp
, struct fb_info
*info
)
1379 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1381 if(regno
>= sisfb_get_cmap_len(&info
->var
))
1384 switch(info
->var
.bits_per_pixel
) {
1386 outSISREG(SISDACA
, regno
);
1387 outSISREG(SISDACD
, (red
>> 10));
1388 outSISREG(SISDACD
, (green
>> 10));
1389 outSISREG(SISDACD
, (blue
>> 10));
1390 if(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
1391 outSISREG(SISDAC2A
, regno
);
1392 outSISREG(SISDAC2D
, (red
>> 8));
1393 outSISREG(SISDAC2D
, (green
>> 8));
1394 outSISREG(SISDAC2D
, (blue
>> 8));
1401 ((u32
*)(info
->pseudo_palette
))[regno
] =
1403 ((green
& 0xfc00) >> 5) |
1404 ((blue
& 0xf800) >> 11);
1413 ((u32
*)(info
->pseudo_palette
))[regno
] =
1414 (red
<< 16) | (green
<< 8) | (blue
);
1421 sisfb_set_par(struct fb_info
*info
)
1425 if((err
= sisfb_do_set_var(&info
->var
, 1, info
)))
1428 sisfb_get_fix(&info
->fix
, -1, info
);
1434 sisfb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
1436 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1437 unsigned int htotal
= 0, vtotal
= 0, myrateindex
= 0;
1438 unsigned int drate
= 0, hrate
= 0, maxyres
;
1440 int refresh_rate
, search_idx
, tidx
;
1441 bool recalc_clock
= false;
1444 htotal
= var
->left_margin
+ var
->xres
+ var
->right_margin
+ var
->hsync_len
;
1446 vtotal
= var
->upper_margin
+ var
->lower_margin
+ var
->vsync_len
;
1448 pixclock
= var
->pixclock
;
1450 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
) {
1451 vtotal
+= var
->yres
;
1453 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1454 vtotal
+= var
->yres
;
1456 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1457 vtotal
+= var
->yres
;
1460 vtotal
+= var
->yres
;
1462 if(!(htotal
) || !(vtotal
)) {
1463 SISFAIL("sisfb: no valid timing data");
1467 while( (sisbios_mode
[search_idx
].mode_no
[0] != 0) &&
1468 (sisbios_mode
[search_idx
].xres
<= var
->xres
) ) {
1469 if( (sisbios_mode
[search_idx
].xres
== var
->xres
) &&
1470 (sisbios_mode
[search_idx
].yres
== var
->yres
) &&
1471 (sisbios_mode
[search_idx
].bpp
== var
->bits_per_pixel
)) {
1472 if((tidx
= sisfb_validate_mode(ivideo
, search_idx
,
1473 ivideo
->currentvbflags
)) > 0) {
1484 while(sisbios_mode
[search_idx
].mode_no
[0] != 0) {
1485 if( (var
->xres
<= sisbios_mode
[search_idx
].xres
) &&
1486 (var
->yres
<= sisbios_mode
[search_idx
].yres
) &&
1487 (var
->bits_per_pixel
== sisbios_mode
[search_idx
].bpp
) ) {
1488 if((tidx
= sisfb_validate_mode(ivideo
,search_idx
,
1489 ivideo
->currentvbflags
)) > 0) {
1499 "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
1500 var
->xres
, var
->yres
, var
->bits_per_pixel
,
1501 sisbios_mode
[search_idx
].xres
,
1502 sisbios_mode
[search_idx
].yres
,
1503 var
->bits_per_pixel
);
1504 var
->xres
= sisbios_mode
[search_idx
].xres
;
1505 var
->yres
= sisbios_mode
[search_idx
].yres
;
1508 "sisfb: Failed to find supported mode near %dx%dx%d\n",
1509 var
->xres
, var
->yres
, var
->bits_per_pixel
);
1514 if( ((ivideo
->vbflags2
& VB2_LVDS
) ||
1515 ((ivideo
->vbflags2
& VB2_30xBDH
) && (ivideo
->currentvbflags
& CRT2_LCD
))) &&
1516 (var
->bits_per_pixel
== 8) ) {
1517 /* Slave modes on LVDS and 301B-DH */
1519 recalc_clock
= true;
1520 } else if( (ivideo
->current_htotal
== htotal
) &&
1521 (ivideo
->current_vtotal
== vtotal
) &&
1522 (ivideo
->current_pixclock
== pixclock
) ) {
1523 /* x=x & y=y & c=c -> assume depth change */
1524 drate
= 1000000000 / pixclock
;
1525 hrate
= (drate
* 1000) / htotal
;
1526 refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1527 } else if( ( (ivideo
->current_htotal
!= htotal
) ||
1528 (ivideo
->current_vtotal
!= vtotal
) ) &&
1529 (ivideo
->current_pixclock
== var
->pixclock
) ) {
1530 /* x!=x | y!=y & c=c -> invalid pixclock */
1531 if(ivideo
->sisfb_lastrates
[sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
]]) {
1533 ivideo
->sisfb_lastrates
[sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
]];
1534 } else if(ivideo
->sisfb_parm_rate
!= -1) {
1535 /* Sic, sisfb_parm_rate - want to know originally desired rate here */
1536 refresh_rate
= ivideo
->sisfb_parm_rate
;
1540 recalc_clock
= true;
1541 } else if((pixclock
) && (htotal
) && (vtotal
)) {
1542 drate
= 1000000000 / pixclock
;
1543 hrate
= (drate
* 1000) / htotal
;
1544 refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1545 } else if(ivideo
->current_refresh_rate
) {
1546 refresh_rate
= ivideo
->current_refresh_rate
;
1547 recalc_clock
= true;
1550 recalc_clock
= true;
1553 myrateindex
= sisfb_search_refresh_rate(ivideo
, refresh_rate
, search_idx
);
1555 /* Eventually recalculate timing and clock */
1557 if(!myrateindex
) myrateindex
= sisbios_mode
[search_idx
].rate_idx
;
1558 var
->pixclock
= (u32
) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo
->SiS_Pr
,
1559 sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
],
1561 sisfb_mode_rate_to_ddata(&ivideo
->SiS_Pr
,
1562 sisbios_mode
[search_idx
].mode_no
[ivideo
->mni
],
1564 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1565 var
->pixclock
<<= 1;
1569 if(ivideo
->sisfb_thismonitor
.datavalid
) {
1570 if(!sisfb_verify_rate(ivideo
, &ivideo
->sisfb_thismonitor
, search_idx
,
1571 myrateindex
, refresh_rate
)) {
1573 "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1577 /* Adapt RGB settings */
1578 sisfb_bpp_to_var(ivideo
, var
);
1580 /* Sanity check for offsets */
1581 if(var
->xoffset
< 0) var
->xoffset
= 0;
1582 if(var
->yoffset
< 0) var
->yoffset
= 0;
1584 if(var
->xres
> var
->xres_virtual
)
1585 var
->xres_virtual
= var
->xres
;
1587 if(ivideo
->sisfb_ypan
) {
1588 maxyres
= sisfb_calc_maxyres(ivideo
, var
);
1589 if(ivideo
->sisfb_max
) {
1590 var
->yres_virtual
= maxyres
;
1592 if(var
->yres_virtual
> maxyres
) {
1593 var
->yres_virtual
= maxyres
;
1596 if(var
->yres_virtual
<= var
->yres
) {
1597 var
->yres_virtual
= var
->yres
;
1600 if(var
->yres
!= var
->yres_virtual
) {
1601 var
->yres_virtual
= var
->yres
;
1607 /* Truncate offsets to maximum if too high */
1608 if(var
->xoffset
> var
->xres_virtual
- var
->xres
) {
1609 var
->xoffset
= var
->xres_virtual
- var
->xres
- 1;
1612 if(var
->yoffset
> var
->yres_virtual
- var
->yres
) {
1613 var
->yoffset
= var
->yres_virtual
- var
->yres
- 1;
1616 /* Set everything else to 0 */
1617 var
->red
.msb_right
=
1618 var
->green
.msb_right
=
1619 var
->blue
.msb_right
=
1620 var
->transp
.offset
=
1621 var
->transp
.length
=
1622 var
->transp
.msb_right
= 0;
1628 sisfb_pan_display(struct fb_var_screeninfo
*var
, struct fb_info
* info
)
1630 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1633 if(var
->xoffset
> (var
->xres_virtual
- var
->xres
))
1636 if(var
->yoffset
> (var
->yres_virtual
- var
->yres
))
1639 if(var
->vmode
& FB_VMODE_YWRAP
)
1642 if(var
->xoffset
+ info
->var
.xres
> info
->var
.xres_virtual
||
1643 var
->yoffset
+ info
->var
.yres
> info
->var
.yres_virtual
)
1646 if((err
= sisfb_pan_var(ivideo
, var
)) < 0)
1649 info
->var
.xoffset
= var
->xoffset
;
1650 info
->var
.yoffset
= var
->yoffset
;
1656 sisfb_blank(int blank
, struct fb_info
*info
)
1658 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1660 return sisfb_myblank(ivideo
, blank
);
1663 /* ----------- FBDev related routines for all series ---------- */
1665 static int sisfb_ioctl(struct fb_info
*info
, unsigned int cmd
,
1668 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1669 struct sis_memreq sismemreq
;
1670 struct fb_vblank sisvbblank
;
1675 u32 __user
*argp
= (u32 __user
*)arg
;
1679 if(!capable(CAP_SYS_RAWIO
))
1682 if(copy_from_user(&sismemreq
, (void __user
*)arg
, sizeof(sismemreq
)))
1685 sis_malloc(&sismemreq
);
1687 if(copy_to_user((void __user
*)arg
, &sismemreq
, sizeof(sismemreq
))) {
1688 sis_free((u32
)sismemreq
.offset
);
1694 if(!capable(CAP_SYS_RAWIO
))
1697 if(get_user(gpu32
, argp
))
1703 case FBIOGET_VBLANK
:
1705 memset(&sisvbblank
, 0, sizeof(struct fb_vblank
));
1707 sisvbblank
.count
= 0;
1708 sisvbblank
.flags
= sisfb_setupvbblankflags(ivideo
, &sisvbblank
.vcount
, &sisvbblank
.hcount
);
1710 if(copy_to_user((void __user
*)arg
, &sisvbblank
, sizeof(sisvbblank
)))
1715 case SISFB_GET_INFO_SIZE
:
1716 return put_user(sizeof(struct sisfb_info
), argp
);
1718 case SISFB_GET_INFO_OLD
:
1719 if(ivideo
->warncount
++ < 10)
1721 "sisfb: Deprecated ioctl call received - update your application!\n");
1722 case SISFB_GET_INFO
: /* For communication with X driver */
1723 ivideo
->sisfb_infoblock
.sisfb_id
= SISFB_ID
;
1724 ivideo
->sisfb_infoblock
.sisfb_version
= VER_MAJOR
;
1725 ivideo
->sisfb_infoblock
.sisfb_revision
= VER_MINOR
;
1726 ivideo
->sisfb_infoblock
.sisfb_patchlevel
= VER_LEVEL
;
1727 ivideo
->sisfb_infoblock
.chip_id
= ivideo
->chip_id
;
1728 ivideo
->sisfb_infoblock
.sisfb_pci_vendor
= ivideo
->chip_vendor
;
1729 ivideo
->sisfb_infoblock
.memory
= ivideo
->video_size
/ 1024;
1730 ivideo
->sisfb_infoblock
.heapstart
= ivideo
->heapstart
/ 1024;
1731 if(ivideo
->modechanged
) {
1732 ivideo
->sisfb_infoblock
.fbvidmode
= ivideo
->mode_no
;
1734 ivideo
->sisfb_infoblock
.fbvidmode
= ivideo
->modeprechange
;
1736 ivideo
->sisfb_infoblock
.sisfb_caps
= ivideo
->caps
;
1737 ivideo
->sisfb_infoblock
.sisfb_tqlen
= ivideo
->cmdQueueSize
/ 1024;
1738 ivideo
->sisfb_infoblock
.sisfb_pcibus
= ivideo
->pcibus
;
1739 ivideo
->sisfb_infoblock
.sisfb_pcislot
= ivideo
->pcislot
;
1740 ivideo
->sisfb_infoblock
.sisfb_pcifunc
= ivideo
->pcifunc
;
1741 ivideo
->sisfb_infoblock
.sisfb_lcdpdc
= ivideo
->detectedpdc
;
1742 ivideo
->sisfb_infoblock
.sisfb_lcdpdca
= ivideo
->detectedpdca
;
1743 ivideo
->sisfb_infoblock
.sisfb_lcda
= ivideo
->detectedlcda
;
1744 ivideo
->sisfb_infoblock
.sisfb_vbflags
= ivideo
->vbflags
;
1745 ivideo
->sisfb_infoblock
.sisfb_currentvbflags
= ivideo
->currentvbflags
;
1746 ivideo
->sisfb_infoblock
.sisfb_scalelcd
= ivideo
->SiS_Pr
.UsePanelScaler
;
1747 ivideo
->sisfb_infoblock
.sisfb_specialtiming
= ivideo
->SiS_Pr
.SiS_CustomT
;
1748 ivideo
->sisfb_infoblock
.sisfb_haveemi
= ivideo
->SiS_Pr
.HaveEMI
? 1 : 0;
1749 ivideo
->sisfb_infoblock
.sisfb_haveemilcd
= ivideo
->SiS_Pr
.HaveEMILCD
? 1 : 0;
1750 ivideo
->sisfb_infoblock
.sisfb_emi30
= ivideo
->SiS_Pr
.EMI_30
;
1751 ivideo
->sisfb_infoblock
.sisfb_emi31
= ivideo
->SiS_Pr
.EMI_31
;
1752 ivideo
->sisfb_infoblock
.sisfb_emi32
= ivideo
->SiS_Pr
.EMI_32
;
1753 ivideo
->sisfb_infoblock
.sisfb_emi33
= ivideo
->SiS_Pr
.EMI_33
;
1754 ivideo
->sisfb_infoblock
.sisfb_tvxpos
= (u16
)(ivideo
->tvxpos
+ 32);
1755 ivideo
->sisfb_infoblock
.sisfb_tvypos
= (u16
)(ivideo
->tvypos
+ 32);
1756 ivideo
->sisfb_infoblock
.sisfb_heapsize
= ivideo
->sisfb_heap_size
/ 1024;
1757 ivideo
->sisfb_infoblock
.sisfb_videooffset
= ivideo
->video_offset
;
1758 ivideo
->sisfb_infoblock
.sisfb_curfstn
= ivideo
->curFSTN
;
1759 ivideo
->sisfb_infoblock
.sisfb_curdstn
= ivideo
->curDSTN
;
1760 ivideo
->sisfb_infoblock
.sisfb_vbflags2
= ivideo
->vbflags2
;
1761 ivideo
->sisfb_infoblock
.sisfb_can_post
= ivideo
->sisfb_can_post
? 1 : 0;
1762 ivideo
->sisfb_infoblock
.sisfb_card_posted
= ivideo
->sisfb_card_posted
? 1 : 0;
1763 ivideo
->sisfb_infoblock
.sisfb_was_boot_device
= ivideo
->sisfb_was_boot_device
? 1 : 0;
1765 if(copy_to_user((void __user
*)arg
, &ivideo
->sisfb_infoblock
,
1766 sizeof(ivideo
->sisfb_infoblock
)))
1771 case SISFB_GET_VBRSTATUS_OLD
:
1772 if(ivideo
->warncount
++ < 10)
1774 "sisfb: Deprecated ioctl call received - update your application!\n");
1775 case SISFB_GET_VBRSTATUS
:
1776 if(sisfb_CheckVBRetrace(ivideo
))
1777 return put_user((u32
)1, argp
);
1779 return put_user((u32
)0, argp
);
1781 case SISFB_GET_AUTOMAXIMIZE_OLD
:
1782 if(ivideo
->warncount
++ < 10)
1784 "sisfb: Deprecated ioctl call received - update your application!\n");
1785 case SISFB_GET_AUTOMAXIMIZE
:
1786 if(ivideo
->sisfb_max
)
1787 return put_user((u32
)1, argp
);
1789 return put_user((u32
)0, argp
);
1791 case SISFB_SET_AUTOMAXIMIZE_OLD
:
1792 if(ivideo
->warncount
++ < 10)
1794 "sisfb: Deprecated ioctl call received - update your application!\n");
1795 case SISFB_SET_AUTOMAXIMIZE
:
1796 if(get_user(gpu32
, argp
))
1799 ivideo
->sisfb_max
= (gpu32
) ? 1 : 0;
1802 case SISFB_SET_TVPOSOFFSET
:
1803 if(get_user(gpu32
, argp
))
1806 sisfb_set_TVxposoffset(ivideo
, ((int)(gpu32
>> 16)) - 32);
1807 sisfb_set_TVyposoffset(ivideo
, ((int)(gpu32
& 0xffff)) - 32);
1810 case SISFB_GET_TVPOSOFFSET
:
1811 return put_user((u32
)(((ivideo
->tvxpos
+32)<<16)|((ivideo
->tvypos
+32)&0xffff)),
1815 if(copy_from_user(&ivideo
->sisfb_command
, (void __user
*)arg
,
1816 sizeof(struct sisfb_cmd
)))
1819 sisfb_handle_command(ivideo
, &ivideo
->sisfb_command
);
1821 if(copy_to_user((void __user
*)arg
, &ivideo
->sisfb_command
,
1822 sizeof(struct sisfb_cmd
)))
1827 case SISFB_SET_LOCK
:
1828 if(get_user(gpu32
, argp
))
1831 ivideo
->sisfblocked
= (gpu32
) ? 1 : 0;
1835 #ifdef SIS_NEW_CONFIG_COMPAT
1836 return -ENOIOCTLCMD
;
1845 sisfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
, struct fb_info
*info
)
1847 struct sis_video_info
*ivideo
= (struct sis_video_info
*)info
->par
;
1849 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
1851 strcpy(fix
->id
, ivideo
->myid
);
1853 mutex_lock(&info
->mm_lock
);
1854 fix
->smem_start
= ivideo
->video_base
+ ivideo
->video_offset
;
1855 fix
->smem_len
= ivideo
->sisfb_mem
;
1856 mutex_unlock(&info
->mm_lock
);
1857 fix
->type
= FB_TYPE_PACKED_PIXELS
;
1859 fix
->visual
= (ivideo
->video_bpp
== 8) ? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_TRUECOLOR
;
1861 fix
->ypanstep
= (ivideo
->sisfb_ypan
) ? 1 : 0;
1863 fix
->line_length
= ivideo
->video_linelength
;
1864 fix
->mmio_start
= ivideo
->mmio_base
;
1865 fix
->mmio_len
= ivideo
->mmio_size
;
1866 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
1867 fix
->accel
= FB_ACCEL_SIS_GLAMOUR
;
1868 } else if((ivideo
->chip
== SIS_330
) ||
1869 (ivideo
->chip
== SIS_760
) ||
1870 (ivideo
->chip
== SIS_761
)) {
1871 fix
->accel
= FB_ACCEL_SIS_XABRE
;
1872 } else if(ivideo
->chip
== XGI_20
) {
1873 fix
->accel
= FB_ACCEL_XGI_VOLARI_Z
;
1874 } else if(ivideo
->chip
>= XGI_40
) {
1875 fix
->accel
= FB_ACCEL_XGI_VOLARI_V
;
1877 fix
->accel
= FB_ACCEL_SIS_GLAMOUR_2
;
1883 /* ---------------- fb_ops structures ----------------- */
1885 static struct fb_ops sisfb_ops
= {
1886 .owner
= THIS_MODULE
,
1887 .fb_open
= sisfb_open
,
1888 .fb_release
= sisfb_release
,
1889 .fb_check_var
= sisfb_check_var
,
1890 .fb_set_par
= sisfb_set_par
,
1891 .fb_setcolreg
= sisfb_setcolreg
,
1892 .fb_pan_display
= sisfb_pan_display
,
1893 .fb_blank
= sisfb_blank
,
1894 .fb_fillrect
= fbcon_sis_fillrect
,
1895 .fb_copyarea
= fbcon_sis_copyarea
,
1896 .fb_imageblit
= cfb_imageblit
,
1897 #ifdef CONFIG_FB_SOFT_CURSOR
1898 .fb_cursor
= soft_cursor
,
1900 .fb_sync
= fbcon_sis_sync
,
1901 #ifdef SIS_NEW_CONFIG_COMPAT
1902 .fb_compat_ioctl
= sisfb_ioctl
,
1904 .fb_ioctl
= sisfb_ioctl
1907 /* ---------------- Chip generation dependent routines ---------------- */
1909 static struct pci_dev
* __devinit
1910 sisfb_get_northbridge(int basechipid
)
1912 struct pci_dev
*pdev
= NULL
;
1913 int nbridgenum
, nbridgeidx
, i
;
1914 static const unsigned short nbridgeids
[] = {
1915 PCI_DEVICE_ID_SI_540
, /* for SiS 540 VGA */
1916 PCI_DEVICE_ID_SI_630
, /* for SiS 630/730 VGA */
1917 PCI_DEVICE_ID_SI_730
,
1918 PCI_DEVICE_ID_SI_550
, /* for SiS 550 VGA */
1919 PCI_DEVICE_ID_SI_650
, /* for SiS 650/651/740 VGA */
1920 PCI_DEVICE_ID_SI_651
,
1921 PCI_DEVICE_ID_SI_740
,
1922 PCI_DEVICE_ID_SI_661
, /* for SiS 661/741/660/760/761 VGA */
1923 PCI_DEVICE_ID_SI_741
,
1924 PCI_DEVICE_ID_SI_660
,
1925 PCI_DEVICE_ID_SI_760
,
1926 PCI_DEVICE_ID_SI_761
1929 switch(basechipid
) {
1930 #ifdef CONFIG_FB_SIS_300
1931 case SIS_540
: nbridgeidx
= 0; nbridgenum
= 1; break;
1932 case SIS_630
: nbridgeidx
= 1; nbridgenum
= 2; break;
1934 #ifdef CONFIG_FB_SIS_315
1935 case SIS_550
: nbridgeidx
= 3; nbridgenum
= 1; break;
1936 case SIS_650
: nbridgeidx
= 4; nbridgenum
= 3; break;
1937 case SIS_660
: nbridgeidx
= 7; nbridgenum
= 5; break;
1939 default: return NULL
;
1941 for(i
= 0; i
< nbridgenum
; i
++) {
1942 if((pdev
= pci_get_device(PCI_VENDOR_ID_SI
,
1943 nbridgeids
[nbridgeidx
+i
], NULL
)))
1949 static int __devinit
1950 sisfb_get_dram_size(struct sis_video_info
*ivideo
)
1952 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1956 ivideo
->video_size
= 0;
1957 ivideo
->UMAsize
= ivideo
->LFBsize
= 0;
1959 switch(ivideo
->chip
) {
1960 #ifdef CONFIG_FB_SIS_300
1962 inSISIDXREG(SISSR
, 0x14, reg
);
1963 ivideo
->video_size
= ((reg
& 0x3F) + 1) << 20;
1968 if(!ivideo
->nbridge
)
1970 pci_read_config_byte(ivideo
->nbridge
, 0x63, ®
);
1971 ivideo
->video_size
= 1 << (((reg
& 0x70) >> 4) + 21);
1974 #ifdef CONFIG_FB_SIS_315
1978 inSISIDXREG(SISSR
, 0x14, reg
);
1979 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
1980 switch((reg
>> 2) & 0x03) {
1983 ivideo
->video_size
<<= 1;
1986 ivideo
->video_size
+= (ivideo
->video_size
/2);
1990 inSISIDXREG(SISSR
, 0x14, reg
);
1991 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
1992 if(reg
& 0x0c) ivideo
->video_size
<<= 1;
1997 inSISIDXREG(SISSR
, 0x14, reg
);
1998 ivideo
->video_size
= (((reg
& 0x3f) + 1) << 2) << 20;
2002 inSISIDXREG(SISCR
, 0x79, reg
);
2003 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
2008 inSISIDXREG(SISCR
, 0x79, reg
);
2009 reg
= (reg
& 0xf0) >> 4;
2011 ivideo
->video_size
= (1 << reg
) << 20;
2012 ivideo
->UMAsize
= ivideo
->video_size
;
2014 inSISIDXREG(SISCR
, 0x78, reg
);
2018 ivideo
->LFBsize
= (32 << 20);
2020 ivideo
->LFBsize
= (64 << 20);
2022 ivideo
->video_size
+= ivideo
->LFBsize
;
2028 inSISIDXREG(SISSR
, 0x14, reg
);
2029 ivideo
->video_size
= (1 << ((reg
& 0xf0) >> 4)) << 20;
2030 if(ivideo
->chip
!= XGI_20
) {
2031 reg
= (reg
& 0x0c) >> 2;
2032 if(ivideo
->revision_id
== 2) {
2033 if(reg
& 0x01) reg
= 0x02;
2036 if(reg
== 0x02) ivideo
->video_size
<<= 1;
2037 else if(reg
== 0x03) ivideo
->video_size
<<= 2;
2047 /* -------------- video bridge device detection --------------- */
2049 static void __devinit
2050 sisfb_detect_VB_connect(struct sis_video_info
*ivideo
)
2054 /* No CRT2 on XGI Z7 */
2055 if(ivideo
->chip
== XGI_20
) {
2056 ivideo
->sisfb_crt1off
= 0;
2060 #ifdef CONFIG_FB_SIS_300
2061 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2062 inSISIDXREG(SISSR
, 0x17, temp
);
2063 if((temp
& 0x0F) && (ivideo
->chip
!= SIS_300
)) {
2064 /* PAL/NTSC is stored on SR16 on such machines */
2065 if(!(ivideo
->vbflags
& (TV_PAL
| TV_NTSC
| TV_PALM
| TV_PALN
))) {
2066 inSISIDXREG(SISSR
, 0x16, temp
);
2068 ivideo
->vbflags
|= TV_PAL
;
2070 ivideo
->vbflags
|= TV_NTSC
;
2076 inSISIDXREG(SISCR
, 0x32, cr32
);
2078 if(cr32
& SIS_CRT1
) {
2079 ivideo
->sisfb_crt1off
= 0;
2081 ivideo
->sisfb_crt1off
= (cr32
& 0xDF) ? 1 : 0;
2084 ivideo
->vbflags
&= ~(CRT2_TV
| CRT2_LCD
| CRT2_VGA
);
2086 if(cr32
& SIS_VB_TV
) ivideo
->vbflags
|= CRT2_TV
;
2087 if(cr32
& SIS_VB_LCD
) ivideo
->vbflags
|= CRT2_LCD
;
2088 if(cr32
& SIS_VB_CRT2
) ivideo
->vbflags
|= CRT2_VGA
;
2090 /* Check given parms for hardware compatibility.
2091 * (Cannot do this in the search_xx routines since we don't
2092 * know what hardware we are running on then)
2095 if(ivideo
->chip
!= SIS_550
) {
2096 ivideo
->sisfb_dstn
= ivideo
->sisfb_fstn
= 0;
2099 if(ivideo
->sisfb_tvplug
!= -1) {
2100 if( (ivideo
->sisvga_engine
!= SIS_315_VGA
) ||
2101 (!(ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) ) {
2102 if(ivideo
->sisfb_tvplug
& TV_YPBPR
) {
2103 ivideo
->sisfb_tvplug
= -1;
2104 printk(KERN_ERR
"sisfb: YPbPr not supported\n");
2108 if(ivideo
->sisfb_tvplug
!= -1) {
2109 if( (ivideo
->sisvga_engine
!= SIS_315_VGA
) ||
2110 (!(ivideo
->vbflags2
& VB2_SISHIVISIONBRIDGE
)) ) {
2111 if(ivideo
->sisfb_tvplug
& TV_HIVISION
) {
2112 ivideo
->sisfb_tvplug
= -1;
2113 printk(KERN_ERR
"sisfb: HiVision not supported\n");
2117 if(ivideo
->sisfb_tvstd
!= -1) {
2118 if( (!(ivideo
->vbflags2
& VB2_SISBRIDGE
)) &&
2119 (!((ivideo
->sisvga_engine
== SIS_315_VGA
) &&
2120 (ivideo
->vbflags2
& VB2_CHRONTEL
))) ) {
2121 if(ivideo
->sisfb_tvstd
& (TV_PALN
| TV_PALN
| TV_NTSCJ
)) {
2122 ivideo
->sisfb_tvstd
= -1;
2123 printk(KERN_ERR
"sisfb: PALM/PALN/NTSCJ not supported\n");
2128 /* Detect/set TV plug & type */
2129 if(ivideo
->sisfb_tvplug
!= -1) {
2130 ivideo
->vbflags
|= ivideo
->sisfb_tvplug
;
2132 if(cr32
& SIS_VB_YPBPR
) ivideo
->vbflags
|= (TV_YPBPR
|TV_YPBPR525I
); /* default: 480i */
2133 else if(cr32
& SIS_VB_HIVISION
) ivideo
->vbflags
|= TV_HIVISION
;
2134 else if(cr32
& SIS_VB_SCART
) ivideo
->vbflags
|= TV_SCART
;
2136 if(cr32
& SIS_VB_SVIDEO
) ivideo
->vbflags
|= TV_SVIDEO
;
2137 if(cr32
& SIS_VB_COMPOSITE
) ivideo
->vbflags
|= TV_AVIDEO
;
2141 if(!(ivideo
->vbflags
& (TV_YPBPR
| TV_HIVISION
))) {
2142 if(ivideo
->sisfb_tvstd
!= -1) {
2143 ivideo
->vbflags
&= ~(TV_NTSC
| TV_PAL
| TV_PALM
| TV_PALN
| TV_NTSCJ
);
2144 ivideo
->vbflags
|= ivideo
->sisfb_tvstd
;
2146 if(ivideo
->vbflags
& TV_SCART
) {
2147 ivideo
->vbflags
&= ~(TV_NTSC
| TV_PALM
| TV_PALN
| TV_NTSCJ
);
2148 ivideo
->vbflags
|= TV_PAL
;
2150 if(!(ivideo
->vbflags
& (TV_PAL
| TV_NTSC
| TV_PALM
| TV_PALN
| TV_NTSCJ
))) {
2151 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2152 inSISIDXREG(SISSR
, 0x38, temp
);
2153 if(temp
& 0x01) ivideo
->vbflags
|= TV_PAL
;
2154 else ivideo
->vbflags
|= TV_NTSC
;
2155 } else if((ivideo
->chip
<= SIS_315PRO
) || (ivideo
->chip
>= SIS_330
)) {
2156 inSISIDXREG(SISSR
, 0x38, temp
);
2157 if(temp
& 0x01) ivideo
->vbflags
|= TV_PAL
;
2158 else ivideo
->vbflags
|= TV_NTSC
;
2160 inSISIDXREG(SISCR
, 0x79, temp
);
2161 if(temp
& 0x20) ivideo
->vbflags
|= TV_PAL
;
2162 else ivideo
->vbflags
|= TV_NTSC
;
2167 /* Copy forceCRT1 option to CRT1off if option is given */
2168 if(ivideo
->sisfb_forcecrt1
!= -1) {
2169 ivideo
->sisfb_crt1off
= (ivideo
->sisfb_forcecrt1
) ? 0 : 1;
2173 /* ------------------ Sensing routines ------------------ */
2175 static bool __devinit
2176 sisfb_test_DDC1(struct sis_video_info
*ivideo
)
2181 old
= SiS_ReadDDC1Bit(&ivideo
->SiS_Pr
);
2183 if(old
!= SiS_ReadDDC1Bit(&ivideo
->SiS_Pr
)) break;
2185 return (count
!= -1);
2188 static void __devinit
2189 sisfb_sense_crt1(struct sis_video_info
*ivideo
)
2191 bool mustwait
= false;
2193 #ifdef CONFIG_FB_SIS_315
2199 inSISIDXREG(SISSR
,0x1F,sr1F
);
2200 orSISIDXREG(SISSR
,0x1F,0x04);
2201 andSISIDXREG(SISSR
,0x1F,0x3F);
2202 if(sr1F
& 0xc0) mustwait
= true;
2204 #ifdef CONFIG_FB_SIS_315
2205 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2206 inSISIDXREG(SISCR
,ivideo
->SiS_Pr
.SiS_MyCR63
,cr63
);
2208 andSISIDXREG(SISCR
,ivideo
->SiS_Pr
.SiS_MyCR63
,0xBF);
2212 inSISIDXREG(SISCR
,0x17,cr17
);
2215 orSISIDXREG(SISCR
,0x17,0x80);
2217 outSISIDXREG(SISSR
, 0x00, 0x01);
2218 outSISIDXREG(SISSR
, 0x00, 0x03);
2222 for(i
=0; i
< 10; i
++) sisfbwaitretracecrt1(ivideo
);
2225 #ifdef CONFIG_FB_SIS_315
2226 if(ivideo
->chip
>= SIS_330
) {
2227 andSISIDXREG(SISCR
,0x32,~0x20);
2228 if(ivideo
->chip
>= SIS_340
) {
2229 outSISIDXREG(SISCR
, 0x57, 0x4a);
2231 outSISIDXREG(SISCR
, 0x57, 0x5f);
2233 orSISIDXREG(SISCR
, 0x53, 0x02);
2234 while((inSISREG(SISINPSTAT
)) & 0x01) break;
2235 while(!((inSISREG(SISINPSTAT
)) & 0x01)) break;
2236 if((inSISREG(SISMISCW
)) & 0x10) temp
= 1;
2237 andSISIDXREG(SISCR
, 0x53, 0xfd);
2238 andSISIDXREG(SISCR
, 0x57, 0x00);
2242 if(temp
== 0xffff) {
2245 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
,
2246 ivideo
->sisvga_engine
, 0, 0, NULL
, ivideo
->vbflags2
);
2247 } while(((temp
== 0) || (temp
== 0xffff)) && i
--);
2249 if((temp
== 0) || (temp
== 0xffff)) {
2250 if(sisfb_test_DDC1(ivideo
)) temp
= 1;
2254 if((temp
) && (temp
!= 0xffff)) {
2255 orSISIDXREG(SISCR
,0x32,0x20);
2258 #ifdef CONFIG_FB_SIS_315
2259 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2260 setSISIDXREG(SISCR
,ivideo
->SiS_Pr
.SiS_MyCR63
,0xBF,cr63
);
2264 setSISIDXREG(SISCR
,0x17,0x7F,cr17
);
2266 outSISIDXREG(SISSR
,0x1F,sr1F
);
2269 /* Determine and detect attached devices on SiS30x */
2270 static void __devinit
2271 SiS_SenseLCD(struct sis_video_info
*ivideo
)
2273 unsigned char buffer
[256];
2274 unsigned short temp
, realcrtno
, i
;
2275 u8 reg
, cr37
= 0, paneltype
= 0;
2278 ivideo
->SiS_Pr
.PanelSelfDetected
= false;
2280 /* LCD detection only for TMDS bridges */
2281 if(!(ivideo
->vbflags2
& VB2_SISTMDSBRIDGE
))
2283 if(ivideo
->vbflags2
& VB2_30xBDH
)
2286 /* If LCD already set up by BIOS, skip it */
2287 inSISIDXREG(SISCR
, 0x32, reg
);
2292 if(ivideo
->SiS_Pr
.DDCPortMixup
)
2295 /* Check DDC capabilities */
2296 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
, ivideo
->sisvga_engine
,
2297 realcrtno
, 0, &buffer
[0], ivideo
->vbflags2
);
2299 if((!temp
) || (temp
== 0xffff) || (!(temp
& 0x02)))
2303 i
= 3; /* Number of retrys */
2305 temp
= SiS_HandleDDC(&ivideo
->SiS_Pr
, ivideo
->vbflags
,
2306 ivideo
->sisvga_engine
, realcrtno
, 1,
2307 &buffer
[0], ivideo
->vbflags2
);
2308 } while((temp
) && i
--);
2313 /* No digital device */
2314 if(!(buffer
[0x14] & 0x80))
2317 /* First detailed timing preferred timing? */
2318 if(!(buffer
[0x18] & 0x02))
2321 xres
= buffer
[0x38] | ((buffer
[0x3a] & 0xf0) << 4);
2322 yres
= buffer
[0x3b] | ((buffer
[0x3d] & 0xf0) << 4);
2334 if((yres
== 1200) && (ivideo
->vbflags2
& VB2_30xC
))
2345 if((buffer
[0x47] & 0x18) == 0x18)
2346 cr37
|= ((((buffer
[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2350 outSISIDXREG(SISCR
, 0x36, paneltype
);
2352 setSISIDXREG(SISCR
, 0x37, 0x0c, cr37
);
2353 orSISIDXREG(SISCR
, 0x32, 0x08);
2355 ivideo
->SiS_Pr
.PanelSelfDetected
= true;
2358 static int __devinit
2359 SISDoSense(struct sis_video_info
*ivideo
, u16 type
, u16 test
)
2361 int temp
, mytest
, result
, i
, j
;
2363 for(j
= 0; j
< 10; j
++) {
2365 for(i
= 0; i
< 3; i
++) {
2367 outSISIDXREG(SISPART4
,0x11,(type
& 0x00ff));
2368 temp
= (type
>> 8) | (mytest
& 0x00ff);
2369 setSISIDXREG(SISPART4
,0x10,0xe0,temp
);
2370 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x1500);
2373 inSISIDXREG(SISPART4
,0x03,temp
);
2376 if(temp
== mytest
) result
++;
2378 outSISIDXREG(SISPART4
,0x11,0x00);
2379 andSISIDXREG(SISPART4
,0x10,0xe0);
2380 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x1000);
2383 if((result
== 0) || (result
>= 2)) break;
2388 static void __devinit
2389 SiS_Sense30x(struct sis_video_info
*ivideo
)
2391 u8 backupP4_0d
,backupP2_00
,backupP2_4d
,backupSR_1e
,biosflag
=0;
2392 u16 svhs
=0, svhs_c
=0;
2393 u16 cvbs
=0, cvbs_c
=0;
2394 u16 vga2
=0, vga2_c
=0;
2396 char stdstr
[] = "sisfb: Detected";
2397 char tvstr
[] = "TV connected to";
2399 if(ivideo
->vbflags2
& VB2_301
) {
2400 svhs
= 0x00b9; cvbs
= 0x00b3; vga2
= 0x00d1;
2401 inSISIDXREG(SISPART4
,0x01,myflag
);
2403 svhs
= 0x00dd; cvbs
= 0x00ee; vga2
= 0x00fd;
2405 } else if(ivideo
->vbflags2
& (VB2_301B
| VB2_302B
)) {
2406 svhs
= 0x016b; cvbs
= 0x0174; vga2
= 0x0190;
2407 } else if(ivideo
->vbflags2
& (VB2_301LV
| VB2_302LV
)) {
2408 svhs
= 0x0200; cvbs
= 0x0100;
2409 } else if(ivideo
->vbflags2
& (VB2_301C
| VB2_302ELV
| VB2_307T
| VB2_307LV
)) {
2410 svhs
= 0x016b; cvbs
= 0x0110; vga2
= 0x0190;
2414 vga2_c
= 0x0e08; svhs_c
= 0x0404; cvbs_c
= 0x0804;
2415 if(ivideo
->vbflags
& (VB2_301LV
|VB2_302LV
|VB2_302ELV
|VB2_307LV
)) {
2416 svhs_c
= 0x0408; cvbs_c
= 0x0808;
2420 if(ivideo
->haveXGIROM
) {
2421 biosflag
= ivideo
->bios_abase
[0x58] & 0x03;
2422 } else if(ivideo
->newrom
) {
2423 if(ivideo
->bios_abase
[0x5d] & 0x04) biosflag
|= 0x01;
2424 } else if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2425 if(ivideo
->bios_abase
) {
2426 biosflag
= ivideo
->bios_abase
[0xfe] & 0x03;
2430 if(ivideo
->chip
== SIS_300
) {
2431 inSISIDXREG(SISSR
,0x3b,myflag
);
2432 if(!(myflag
& 0x01)) vga2
= vga2_c
= 0;
2435 if(!(ivideo
->vbflags2
& VB2_SISVGA2BRIDGE
)) {
2439 inSISIDXREG(SISSR
,0x1e,backupSR_1e
);
2440 orSISIDXREG(SISSR
,0x1e,0x20);
2442 inSISIDXREG(SISPART4
,0x0d,backupP4_0d
);
2443 if(ivideo
->vbflags2
& VB2_30xC
) {
2444 setSISIDXREG(SISPART4
,0x0d,~0x07,0x01);
2446 orSISIDXREG(SISPART4
,0x0d,0x04);
2448 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x2000);
2450 inSISIDXREG(SISPART2
,0x00,backupP2_00
);
2451 outSISIDXREG(SISPART2
,0x00,((backupP2_00
| 0x1c) & 0xfc));
2453 inSISIDXREG(SISPART2
,0x4d,backupP2_4d
);
2454 if(ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
) {
2455 outSISIDXREG(SISPART2
,0x4d,(backupP2_4d
& ~0x10));
2458 if(!(ivideo
->vbflags2
& VB2_30xCLV
)) {
2459 SISDoSense(ivideo
, 0, 0);
2462 andSISIDXREG(SISCR
, 0x32, ~0x14);
2464 if(vga2_c
|| vga2
) {
2465 if(SISDoSense(ivideo
, vga2
, vga2_c
)) {
2466 if(biosflag
& 0x01) {
2467 printk(KERN_INFO
"%s %s SCART output\n", stdstr
, tvstr
);
2468 orSISIDXREG(SISCR
, 0x32, 0x04);
2470 printk(KERN_INFO
"%s secondary VGA connection\n", stdstr
);
2471 orSISIDXREG(SISCR
, 0x32, 0x10);
2476 andSISIDXREG(SISCR
, 0x32, 0x3f);
2478 if(ivideo
->vbflags2
& VB2_30xCLV
) {
2479 orSISIDXREG(SISPART4
,0x0d,0x04);
2482 if((ivideo
->sisvga_engine
== SIS_315_VGA
) && (ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) {
2483 outSISIDXREG(SISPART2
,0x4d,(backupP2_4d
| 0x10));
2484 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x2000);
2485 if((result
= SISDoSense(ivideo
, svhs
, 0x0604))) {
2486 if((result
= SISDoSense(ivideo
, cvbs
, 0x0804))) {
2487 printk(KERN_INFO
"%s %s YPbPr component output\n", stdstr
, tvstr
);
2488 orSISIDXREG(SISCR
,0x32,0x80);
2491 outSISIDXREG(SISPART2
,0x4d,backupP2_4d
);
2494 andSISIDXREG(SISCR
, 0x32, ~0x03);
2496 if(!(ivideo
->vbflags
& TV_YPBPR
)) {
2497 if((result
= SISDoSense(ivideo
, svhs
, svhs_c
))) {
2498 printk(KERN_INFO
"%s %s SVIDEO output\n", stdstr
, tvstr
);
2499 orSISIDXREG(SISCR
, 0x32, 0x02);
2501 if((biosflag
& 0x02) || (!result
)) {
2502 if(SISDoSense(ivideo
, cvbs
, cvbs_c
)) {
2503 printk(KERN_INFO
"%s %s COMPOSITE output\n", stdstr
, tvstr
);
2504 orSISIDXREG(SISCR
, 0x32, 0x01);
2509 SISDoSense(ivideo
, 0, 0);
2511 outSISIDXREG(SISPART2
,0x00,backupP2_00
);
2512 outSISIDXREG(SISPART4
,0x0d,backupP4_0d
);
2513 outSISIDXREG(SISSR
,0x1e,backupSR_1e
);
2515 if(ivideo
->vbflags2
& VB2_30xCLV
) {
2516 inSISIDXREG(SISPART2
,0x00,biosflag
);
2517 if(biosflag
& 0x20) {
2518 for(myflag
= 2; myflag
> 0; myflag
--) {
2520 outSISIDXREG(SISPART2
,0x00,biosflag
);
2525 outSISIDXREG(SISPART2
,0x00,backupP2_00
);
2528 /* Determine and detect attached TV's on Chrontel */
2529 static void __devinit
2530 SiS_SenseCh(struct sis_video_info
*ivideo
)
2532 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2534 char stdstr
[] = "sisfb: Chrontel: Detected TV connected to";
2536 #ifdef CONFIG_FB_SIS_300
2537 unsigned char test
[3];
2541 if(ivideo
->chip
< SIS_315H
) {
2543 #ifdef CONFIG_FB_SIS_300
2544 ivideo
->SiS_Pr
.SiS_IF_DEF_CH70xx
= 1; /* Chrontel 700x */
2545 SiS_SetChrontelGPIO(&ivideo
->SiS_Pr
, 0x9c); /* Set general purpose IO for Chrontel communication */
2546 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 1000);
2547 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x25);
2548 /* See Chrontel TB31 for explanation */
2549 temp2
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0e);
2550 if(((temp2
& 0x07) == 0x01) || (temp2
& 0x04)) {
2551 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0e, 0x0b);
2552 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 300);
2554 temp2
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x25);
2555 if(temp2
!= temp1
) temp1
= temp2
;
2557 if((temp1
>= 0x22) && (temp1
<= 0x50)) {
2558 /* Read power status */
2559 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0e);
2560 if((temp1
& 0x03) != 0x03) {
2561 /* Power all outputs */
2562 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0e,0x0b);
2563 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 300);
2565 /* Sense connected TV devices */
2566 for(i
= 0; i
< 3; i
++) {
2567 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x10, 0x01);
2568 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2569 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x10, 0x00);
2570 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2571 temp1
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x10);
2572 if(!(temp1
& 0x08)) test
[i
] = 0x02;
2573 else if(!(temp1
& 0x02)) test
[i
] = 0x01;
2575 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2578 if(test
[0] == test
[1]) temp1
= test
[0];
2579 else if(test
[0] == test
[2]) temp1
= test
[0];
2580 else if(test
[1] == test
[2]) temp1
= test
[1];
2583 "sisfb: TV detection unreliable - test results varied\n");
2587 printk(KERN_INFO
"%s SVIDEO output\n", stdstr
);
2588 ivideo
->vbflags
|= TV_SVIDEO
;
2589 orSISIDXREG(SISCR
, 0x32, 0x02);
2590 andSISIDXREG(SISCR
, 0x32, ~0x05);
2591 } else if (temp1
== 0x01) {
2592 printk(KERN_INFO
"%s CVBS output\n", stdstr
);
2593 ivideo
->vbflags
|= TV_AVIDEO
;
2594 orSISIDXREG(SISCR
, 0x32, 0x01);
2595 andSISIDXREG(SISCR
, 0x32, ~0x06);
2597 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x0e, 0x01, 0xF8);
2598 andSISIDXREG(SISCR
, 0x32, ~0x07);
2600 } else if(temp1
== 0) {
2601 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x0e, 0x01, 0xF8);
2602 andSISIDXREG(SISCR
, 0x32, ~0x07);
2604 /* Set general purpose IO for Chrontel communication */
2605 SiS_SetChrontelGPIO(&ivideo
->SiS_Pr
, 0x00);
2610 #ifdef CONFIG_FB_SIS_315
2611 ivideo
->SiS_Pr
.SiS_IF_DEF_CH70xx
= 2; /* Chrontel 7019 */
2612 temp1
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x49);
2613 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x49, 0x20);
2614 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2615 temp2
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x20);
2617 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x20, temp2
);
2618 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2620 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x20, temp2
);
2621 SiS_DDC2Delay(&ivideo
->SiS_Pr
, 0x96);
2622 temp2
= SiS_GetCH701x(&ivideo
->SiS_Pr
, 0x20);
2623 SiS_SetCH701x(&ivideo
->SiS_Pr
, 0x49, temp1
);
2625 if(temp2
& 0x02) temp1
|= 0x01;
2626 if(temp2
& 0x10) temp1
|= 0x01;
2627 if(temp2
& 0x04) temp1
|= 0x02;
2628 if( (temp1
& 0x01) && (temp1
& 0x02) ) temp1
= 0x04;
2631 printk(KERN_INFO
"%s CVBS output\n", stdstr
);
2632 ivideo
->vbflags
|= TV_AVIDEO
;
2633 orSISIDXREG(SISCR
, 0x32, 0x01);
2634 andSISIDXREG(SISCR
, 0x32, ~0x06);
2637 printk(KERN_INFO
"%s SVIDEO output\n", stdstr
);
2638 ivideo
->vbflags
|= TV_SVIDEO
;
2639 orSISIDXREG(SISCR
, 0x32, 0x02);
2640 andSISIDXREG(SISCR
, 0x32, ~0x05);
2643 printk(KERN_INFO
"%s SCART output\n", stdstr
);
2644 orSISIDXREG(SISCR
, 0x32, 0x04);
2645 andSISIDXREG(SISCR
, 0x32, ~0x03);
2648 andSISIDXREG(SISCR
, 0x32, ~0x07);
2654 static void __devinit
2655 sisfb_get_VB_type(struct sis_video_info
*ivideo
)
2657 char stdstr
[] = "sisfb: Detected";
2658 char bridgestr
[] = "video bridge";
2662 /* No CRT2 on XGI Z7 */
2663 if(ivideo
->chip
== XGI_20
)
2666 inSISIDXREG(SISPART4
, 0x00, vb_chipid
);
2669 inSISIDXREG(SISPART4
, 0x01, reg
);
2671 ivideo
->vbflags
|= VB_301
; /* Deprecated */
2672 ivideo
->vbflags2
|= VB2_301
;
2673 printk(KERN_INFO
"%s SiS301 %s\n", stdstr
, bridgestr
);
2674 } else if(reg
< 0xc0) {
2675 ivideo
->vbflags
|= VB_301B
; /* Deprecated */
2676 ivideo
->vbflags2
|= VB2_301B
;
2677 inSISIDXREG(SISPART4
,0x23,reg
);
2679 ivideo
->vbflags
|= VB_30xBDH
; /* Deprecated */
2680 ivideo
->vbflags2
|= VB2_30xBDH
;
2681 printk(KERN_INFO
"%s SiS301B-DH %s\n", stdstr
, bridgestr
);
2683 printk(KERN_INFO
"%s SiS301B %s\n", stdstr
, bridgestr
);
2685 } else if(reg
< 0xd0) {
2686 ivideo
->vbflags
|= VB_301C
; /* Deprecated */
2687 ivideo
->vbflags2
|= VB2_301C
;
2688 printk(KERN_INFO
"%s SiS301C %s\n", stdstr
, bridgestr
);
2689 } else if(reg
< 0xe0) {
2690 ivideo
->vbflags
|= VB_301LV
; /* Deprecated */
2691 ivideo
->vbflags2
|= VB2_301LV
;
2692 printk(KERN_INFO
"%s SiS301LV %s\n", stdstr
, bridgestr
);
2693 } else if(reg
<= 0xe1) {
2694 inSISIDXREG(SISPART4
,0x39,reg
);
2696 ivideo
->vbflags
|= VB_302LV
; /* Deprecated */
2697 ivideo
->vbflags2
|= VB2_302LV
;
2698 printk(KERN_INFO
"%s SiS302LV %s\n", stdstr
, bridgestr
);
2700 ivideo
->vbflags
|= VB_301C
; /* Deprecated */
2701 ivideo
->vbflags2
|= VB2_301C
;
2702 printk(KERN_INFO
"%s SiS301C(P4) %s\n", stdstr
, bridgestr
);
2704 ivideo
->vbflags
|= VB_302ELV
; /* Deprecated */
2705 ivideo
->vbflags2
|= VB2_302ELV
;
2706 printk(KERN_INFO
"%s SiS302ELV %s\n", stdstr
, bridgestr
);
2712 ivideo
->vbflags
|= VB_302B
; /* Deprecated */
2713 ivideo
->vbflags2
|= VB2_302B
;
2714 printk(KERN_INFO
"%s SiS302B %s\n", stdstr
, bridgestr
);
2718 if((!(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
)) && (ivideo
->chip
!= SIS_300
)) {
2719 inSISIDXREG(SISCR
, 0x37, reg
);
2720 reg
&= SIS_EXTERNAL_CHIP_MASK
;
2722 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2723 #ifdef CONFIG_FB_SIS_300
2725 case SIS_EXTERNAL_CHIP_LVDS
:
2726 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2727 ivideo
->vbflags2
|= VB2_LVDS
;
2729 case SIS_EXTERNAL_CHIP_TRUMPION
:
2730 ivideo
->vbflags
|= (VB_LVDS
| VB_TRUMPION
); /* Deprecated */
2731 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_TRUMPION
);
2733 case SIS_EXTERNAL_CHIP_CHRONTEL
:
2734 ivideo
->vbflags
|= VB_CHRONTEL
; /* Deprecated */
2735 ivideo
->vbflags2
|= VB2_CHRONTEL
;
2737 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL
:
2738 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2739 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2742 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 1;
2744 } else if(ivideo
->chip
< SIS_661
) {
2745 #ifdef CONFIG_FB_SIS_315
2747 case SIS310_EXTERNAL_CHIP_LVDS
:
2748 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2749 ivideo
->vbflags2
|= VB2_LVDS
;
2751 case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL
:
2752 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2753 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2756 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 2;
2758 } else if(ivideo
->chip
>= SIS_661
) {
2759 #ifdef CONFIG_FB_SIS_315
2760 inSISIDXREG(SISCR
, 0x38, reg
);
2764 ivideo
->vbflags
|= VB_LVDS
; /* Deprecated */
2765 ivideo
->vbflags2
|= VB2_LVDS
;
2768 ivideo
->vbflags
|= (VB_LVDS
| VB_CHRONTEL
); /* Deprecated */
2769 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CHRONTEL
);
2772 ivideo
->vbflags
|= (VB_LVDS
| VB_CONEXANT
); /* Deprecated */
2773 ivideo
->vbflags2
|= (VB2_LVDS
| VB2_CONEXANT
);
2776 if(ivideo
->vbflags2
& VB2_CHRONTEL
) ivideo
->chronteltype
= 2;
2779 if(ivideo
->vbflags2
& VB2_LVDS
) {
2780 printk(KERN_INFO
"%s LVDS transmitter\n", stdstr
);
2782 if((ivideo
->sisvga_engine
== SIS_300_VGA
) && (ivideo
->vbflags2
& VB2_TRUMPION
)) {
2783 printk(KERN_INFO
"%s Trumpion Zurac LCD scaler\n", stdstr
);
2785 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
2786 printk(KERN_INFO
"%s Chrontel TV encoder\n", stdstr
);
2788 if((ivideo
->chip
>= SIS_661
) && (ivideo
->vbflags2
& VB2_CONEXANT
)) {
2789 printk(KERN_INFO
"%s Conexant external device\n", stdstr
);
2793 if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
2794 SiS_SenseLCD(ivideo
);
2795 SiS_Sense30x(ivideo
);
2796 } else if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
2797 SiS_SenseCh(ivideo
);
2801 /* ---------- Engine initialization routines ------------ */
2804 sisfb_engine_init(struct sis_video_info
*ivideo
)
2807 /* Initialize command queue (we use MMIO only) */
2809 /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
2811 ivideo
->caps
&= ~(TURBO_QUEUE_CAP
|
2812 MMIO_CMD_QUEUE_CAP
|
2816 #ifdef CONFIG_FB_SIS_300
2817 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2821 tqueue_pos
= (ivideo
->video_size
- ivideo
->cmdQueueSize
) / (64 * 1024);
2823 inSISIDXREG(SISSR
, IND_SIS_TURBOQUEUE_SET
, tq_state
);
2826 tq_state
|= (u8
)(tqueue_pos
>> 8);
2827 outSISIDXREG(SISSR
, IND_SIS_TURBOQUEUE_SET
, tq_state
);
2829 outSISIDXREG(SISSR
, IND_SIS_TURBOQUEUE_ADR
, (u8
)(tqueue_pos
& 0xff));
2831 ivideo
->caps
|= TURBO_QUEUE_CAP
;
2835 #ifdef CONFIG_FB_SIS_315
2836 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
2837 u32 tempq
= 0, templ
;
2840 if(ivideo
->chip
== XGI_20
) {
2841 switch(ivideo
->cmdQueueSize
) {
2843 temp
= SIS_CMD_QUEUE_SIZE_Z7_64k
;
2847 temp
= SIS_CMD_QUEUE_SIZE_Z7_128k
;
2850 switch(ivideo
->cmdQueueSize
) {
2851 case (4 * 1024 * 1024):
2852 temp
= SIS_CMD_QUEUE_SIZE_4M
;
2854 case (2 * 1024 * 1024):
2855 temp
= SIS_CMD_QUEUE_SIZE_2M
;
2857 case (1 * 1024 * 1024):
2858 temp
= SIS_CMD_QUEUE_SIZE_1M
;
2862 temp
= SIS_CMD_QUEUE_SIZE_512k
;
2866 outSISIDXREG(SISSR
, IND_SIS_CMDQUEUE_THRESHOLD
, COMMAND_QUEUE_THRESHOLD
);
2867 outSISIDXREG(SISSR
, IND_SIS_CMDQUEUE_SET
, SIS_CMD_QUEUE_RESET
);
2869 if((ivideo
->chip
>= XGI_40
) && ivideo
->modechanged
) {
2870 /* Must disable dual pipe on XGI_40. Can't do
2871 * this in MMIO mode, because it requires
2872 * setting/clearing a bit in the MMIO fire trigger
2875 if(!((templ
= MMIO_IN32(ivideo
->mmio_vbase
, 0x8240)) & (1 << 10))) {
2877 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, 0);
2879 outSISIDXREG(SISSR
, IND_SIS_CMDQUEUE_SET
, (temp
| SIS_VRAM_CMDQUEUE_ENABLE
));
2881 tempq
= MMIO_IN32(ivideo
->mmio_vbase
, Q_READ_PTR
);
2882 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, tempq
);
2884 tempq
= (u32
)(ivideo
->video_size
- ivideo
->cmdQueueSize
);
2885 MMIO_OUT32(ivideo
->mmio_vbase
, Q_BASE_ADDR
, tempq
);
2887 writel(0x16800000 + 0x8240, ivideo
->video_vbase
+ tempq
);
2888 writel(templ
| (1 << 10), ivideo
->video_vbase
+ tempq
+ 4);
2889 writel(0x168F0000, ivideo
->video_vbase
+ tempq
+ 8);
2890 writel(0x168F0000, ivideo
->video_vbase
+ tempq
+ 12);
2892 MMIO_OUT32(ivideo
->mmio_vbase
, Q_WRITE_PTR
, (tempq
+ 16));
2894 sisfb_syncaccel(ivideo
);
2896 outSISIDXREG(SISSR
, IND_SIS_CMDQUEUE_SET
, SIS_CMD_QUEUE_RESET
);
2901 tempq
= MMIO_IN32(ivideo
->mmio_vbase
, MMIO_QUEUE_READPORT
);
2902 MMIO_OUT32(ivideo
->mmio_vbase
, MMIO_QUEUE_WRITEPORT
, tempq
);
2904 temp
|= (SIS_MMIO_CMD_ENABLE
| SIS_CMD_AUTO_CORR
);
2905 outSISIDXREG(SISSR
, IND_SIS_CMDQUEUE_SET
, temp
);
2907 tempq
= (u32
)(ivideo
->video_size
- ivideo
->cmdQueueSize
);
2908 MMIO_OUT32(ivideo
->mmio_vbase
, MMIO_QUEUE_PHYBASE
, tempq
);
2910 ivideo
->caps
|= MMIO_CMD_QUEUE_CAP
;
2914 ivideo
->engineok
= 1;
2917 static void __devinit
2918 sisfb_detect_lcd_type(struct sis_video_info
*ivideo
)
2923 inSISIDXREG(SISCR
, 0x36, reg
);
2925 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2926 ivideo
->CRT2LCDType
= sis300paneltype
[reg
];
2927 } else if(ivideo
->chip
>= SIS_661
) {
2928 ivideo
->CRT2LCDType
= sis661paneltype
[reg
];
2930 ivideo
->CRT2LCDType
= sis310paneltype
[reg
];
2931 if((ivideo
->chip
== SIS_550
) && (sisfb_fstn
)) {
2932 if((ivideo
->CRT2LCDType
!= LCD_320x240_2
) &&
2933 (ivideo
->CRT2LCDType
!= LCD_320x240_3
)) {
2934 ivideo
->CRT2LCDType
= LCD_320x240
;
2939 if(ivideo
->CRT2LCDType
== LCD_UNKNOWN
) {
2940 /* For broken BIOSes: Assume 1024x768, RGB18 */
2941 ivideo
->CRT2LCDType
= LCD_1024x768
;
2942 setSISIDXREG(SISCR
,0x36,0xf0,0x02);
2943 setSISIDXREG(SISCR
,0x37,0xee,0x01);
2944 printk(KERN_DEBUG
"sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg
);
2947 for(i
= 0; i
< SIS_LCD_NUMBER
; i
++) {
2948 if(ivideo
->CRT2LCDType
== sis_lcd_data
[i
].lcdtype
) {
2949 ivideo
->lcdxres
= sis_lcd_data
[i
].xres
;
2950 ivideo
->lcdyres
= sis_lcd_data
[i
].yres
;
2951 ivideo
->lcddefmodeidx
= sis_lcd_data
[i
].default_mode_idx
;
2956 #ifdef CONFIG_FB_SIS_300
2957 if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_BARCO1366
) {
2958 ivideo
->lcdxres
= 1360; ivideo
->lcdyres
= 1024;
2959 ivideo
->lcddefmodeidx
= DEFAULT_MODE_1360
;
2960 } else if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_PANEL848
) {
2961 ivideo
->lcdxres
= 848; ivideo
->lcdyres
= 480;
2962 ivideo
->lcddefmodeidx
= DEFAULT_MODE_848
;
2963 } else if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_PANEL856
) {
2964 ivideo
->lcdxres
= 856; ivideo
->lcdyres
= 480;
2965 ivideo
->lcddefmodeidx
= DEFAULT_MODE_856
;
2969 printk(KERN_DEBUG
"sisfb: Detected %dx%d flat panel\n",
2970 ivideo
->lcdxres
, ivideo
->lcdyres
);
2973 static void __devinit
2974 sisfb_save_pdc_emi(struct sis_video_info
*ivideo
)
2976 #ifdef CONFIG_FB_SIS_300
2977 /* Save the current PanelDelayCompensation if the LCD is currently used */
2978 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
2979 if(ivideo
->vbflags2
& (VB2_LVDS
| VB2_30xBDH
)) {
2981 inSISIDXREG(SISCR
,0x30,tmp
);
2983 /* Currently on LCD? If yes, read current pdc */
2984 inSISIDXREG(SISPART1
,0x13,ivideo
->detectedpdc
);
2985 ivideo
->detectedpdc
&= 0x3c;
2986 if(ivideo
->SiS_Pr
.PDC
== -1) {
2987 /* Let option override detection */
2988 ivideo
->SiS_Pr
.PDC
= ivideo
->detectedpdc
;
2990 printk(KERN_INFO
"sisfb: Detected LCD PDC 0x%02x\n",
2991 ivideo
->detectedpdc
);
2993 if((ivideo
->SiS_Pr
.PDC
!= -1) &&
2994 (ivideo
->SiS_Pr
.PDC
!= ivideo
->detectedpdc
)) {
2995 printk(KERN_INFO
"sisfb: Using LCD PDC 0x%02x\n",
2996 ivideo
->SiS_Pr
.PDC
);
3002 #ifdef CONFIG_FB_SIS_315
3003 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3005 /* Try to find about LCDA */
3006 if(ivideo
->vbflags2
& VB2_SISLCDABRIDGE
) {
3008 inSISIDXREG(SISPART1
,0x13,tmp
);
3010 ivideo
->SiS_Pr
.SiS_UseLCDA
= true;
3011 ivideo
->detectedlcda
= 0x03;
3016 if(ivideo
->vbflags2
& VB2_SISLVDSBRIDGE
) {
3018 inSISIDXREG(SISCR
,0x30,tmp
);
3019 if((tmp
& 0x20) || (ivideo
->detectedlcda
!= 0xff)) {
3020 /* Currently on LCD? If yes, read current pdc */
3022 inSISIDXREG(SISPART1
,0x2D,pdc
);
3023 ivideo
->detectedpdc
= (pdc
& 0x0f) << 1;
3024 ivideo
->detectedpdca
= (pdc
& 0xf0) >> 3;
3025 inSISIDXREG(SISPART1
,0x35,pdc
);
3026 ivideo
->detectedpdc
|= ((pdc
>> 7) & 0x01);
3027 inSISIDXREG(SISPART1
,0x20,pdc
);
3028 ivideo
->detectedpdca
|= ((pdc
>> 6) & 0x01);
3029 if(ivideo
->newrom
) {
3030 /* New ROM invalidates other PDC resp. */
3031 if(ivideo
->detectedlcda
!= 0xff) {
3032 ivideo
->detectedpdc
= 0xff;
3034 ivideo
->detectedpdca
= 0xff;
3037 if(ivideo
->SiS_Pr
.PDC
== -1) {
3038 if(ivideo
->detectedpdc
!= 0xff) {
3039 ivideo
->SiS_Pr
.PDC
= ivideo
->detectedpdc
;
3042 if(ivideo
->SiS_Pr
.PDCA
== -1) {
3043 if(ivideo
->detectedpdca
!= 0xff) {
3044 ivideo
->SiS_Pr
.PDCA
= ivideo
->detectedpdca
;
3047 if(ivideo
->detectedpdc
!= 0xff) {
3049 "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3050 ivideo
->detectedpdc
);
3052 if(ivideo
->detectedpdca
!= 0xff) {
3054 "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3055 ivideo
->detectedpdca
);
3060 if(ivideo
->vbflags2
& VB2_SISEMIBRIDGE
) {
3061 inSISIDXREG(SISPART4
,0x30,ivideo
->SiS_Pr
.EMI_30
);
3062 inSISIDXREG(SISPART4
,0x31,ivideo
->SiS_Pr
.EMI_31
);
3063 inSISIDXREG(SISPART4
,0x32,ivideo
->SiS_Pr
.EMI_32
);
3064 inSISIDXREG(SISPART4
,0x33,ivideo
->SiS_Pr
.EMI_33
);
3065 ivideo
->SiS_Pr
.HaveEMI
= true;
3066 if((tmp
& 0x20) || (ivideo
->detectedlcda
!= 0xff)) {
3067 ivideo
->SiS_Pr
.HaveEMILCD
= true;
3072 /* Let user override detected PDCs (all bridges) */
3073 if(ivideo
->vbflags2
& VB2_30xBLV
) {
3074 if((ivideo
->SiS_Pr
.PDC
!= -1) &&
3075 (ivideo
->SiS_Pr
.PDC
!= ivideo
->detectedpdc
)) {
3076 printk(KERN_INFO
"sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3077 ivideo
->SiS_Pr
.PDC
);
3079 if((ivideo
->SiS_Pr
.PDCA
!= -1) &&
3080 (ivideo
->SiS_Pr
.PDCA
!= ivideo
->detectedpdca
)) {
3081 printk(KERN_INFO
"sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3082 ivideo
->SiS_Pr
.PDCA
);
3090 /* -------------------- Memory manager routines ---------------------- */
3092 static u32 __devinit
3093 sisfb_getheapstart(struct sis_video_info
*ivideo
)
3095 u32 ret
= ivideo
->sisfb_parm_mem
* 1024;
3096 u32 maxoffs
= ivideo
->video_size
- ivideo
->hwcursor_size
- ivideo
->cmdQueueSize
;
3099 /* Calculate heap start = end of memory for console
3101 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3102 * C = console, D = heap, H = HWCursor, Q = cmd-queue
3104 * On 76x in UMA+LFB mode, the layout is as follows:
3105 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3106 * where the heap is the entire UMA area, eventually
3107 * into the LFB area if the given mem parameter is
3108 * higher than the size of the UMA memory.
3110 * Basically given by "mem" parameter
3112 * maximum = videosize - cmd_queue - hwcursor
3113 * (results in a heap of size 0)
3114 * default = SiS 300: depends on videosize
3115 * SiS 315/330/340/XGI: 32k below max
3118 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3119 if(ivideo
->video_size
> 0x1000000) {
3121 } else if(ivideo
->video_size
> 0x800000) {
3126 } else if(ivideo
->UMAsize
&& ivideo
->LFBsize
) {
3129 def
= maxoffs
- 0x8000;
3132 /* Use default for secondary card for now (FIXME) */
3133 if((!ret
) || (ret
> maxoffs
) || (ivideo
->cardnumber
!= 0))
3139 static u32 __devinit
3140 sisfb_getheapsize(struct sis_video_info
*ivideo
)
3142 u32 max
= ivideo
->video_size
- ivideo
->hwcursor_size
- ivideo
->cmdQueueSize
;
3145 if(ivideo
->UMAsize
&& ivideo
->LFBsize
) {
3146 if( (!ivideo
->sisfb_parm_mem
) ||
3147 ((ivideo
->sisfb_parm_mem
* 1024) > max
) ||
3148 ((max
- (ivideo
->sisfb_parm_mem
* 1024)) < ivideo
->UMAsize
) ) {
3149 ret
= ivideo
->UMAsize
;
3150 max
-= ivideo
->UMAsize
;
3152 ret
= max
- (ivideo
->sisfb_parm_mem
* 1024);
3153 max
= ivideo
->sisfb_parm_mem
* 1024;
3155 ivideo
->video_offset
= ret
;
3156 ivideo
->sisfb_mem
= max
;
3158 ret
= max
- ivideo
->heapstart
;
3159 ivideo
->sisfb_mem
= ivideo
->heapstart
;
3165 static int __devinit
3166 sisfb_heap_init(struct sis_video_info
*ivideo
)
3170 ivideo
->video_offset
= 0;
3171 if(ivideo
->sisfb_parm_mem
) {
3172 if( (ivideo
->sisfb_parm_mem
< (2 * 1024 * 1024)) ||
3173 (ivideo
->sisfb_parm_mem
> ivideo
->video_size
) ) {
3174 ivideo
->sisfb_parm_mem
= 0;
3178 ivideo
->heapstart
= sisfb_getheapstart(ivideo
);
3179 ivideo
->sisfb_heap_size
= sisfb_getheapsize(ivideo
);
3181 ivideo
->sisfb_heap_start
= ivideo
->video_vbase
+ ivideo
->heapstart
;
3182 ivideo
->sisfb_heap_end
= ivideo
->sisfb_heap_start
+ ivideo
->sisfb_heap_size
;
3184 printk(KERN_INFO
"sisfb: Memory heap starting at %dK, size %dK\n",
3185 (int)(ivideo
->heapstart
/ 1024), (int)(ivideo
->sisfb_heap_size
/ 1024));
3187 ivideo
->sisfb_heap
.vinfo
= ivideo
;
3189 ivideo
->sisfb_heap
.poha_chain
= NULL
;
3190 ivideo
->sisfb_heap
.poh_freelist
= NULL
;
3192 poh
= sisfb_poh_new_node(&ivideo
->sisfb_heap
);
3196 poh
->poh_next
= &ivideo
->sisfb_heap
.oh_free
;
3197 poh
->poh_prev
= &ivideo
->sisfb_heap
.oh_free
;
3198 poh
->size
= ivideo
->sisfb_heap_size
;
3199 poh
->offset
= ivideo
->heapstart
;
3201 ivideo
->sisfb_heap
.oh_free
.poh_next
= poh
;
3202 ivideo
->sisfb_heap
.oh_free
.poh_prev
= poh
;
3203 ivideo
->sisfb_heap
.oh_free
.size
= 0;
3204 ivideo
->sisfb_heap
.max_freesize
= poh
->size
;
3206 ivideo
->sisfb_heap
.oh_used
.poh_next
= &ivideo
->sisfb_heap
.oh_used
;
3207 ivideo
->sisfb_heap
.oh_used
.poh_prev
= &ivideo
->sisfb_heap
.oh_used
;
3208 ivideo
->sisfb_heap
.oh_used
.size
= SENTINEL
;
3210 if(ivideo
->cardnumber
== 0) {
3211 /* For the first card, make this heap the "global" one
3212 * for old DRM (which could handle only one card)
3214 sisfb_heap
= &ivideo
->sisfb_heap
;
3220 static struct SIS_OH
*
3221 sisfb_poh_new_node(struct SIS_HEAP
*memheap
)
3223 struct SIS_OHALLOC
*poha
;
3228 if(memheap
->poh_freelist
== NULL
) {
3229 poha
= kmalloc(SIS_OH_ALLOC_SIZE
, GFP_KERNEL
);
3233 poha
->poha_next
= memheap
->poha_chain
;
3234 memheap
->poha_chain
= poha
;
3236 cOhs
= (SIS_OH_ALLOC_SIZE
- sizeof(struct SIS_OHALLOC
)) / sizeof(struct SIS_OH
) + 1;
3238 poh
= &poha
->aoh
[0];
3239 for(i
= cOhs
- 1; i
!= 0; i
--) {
3240 poh
->poh_next
= poh
+ 1;
3244 poh
->poh_next
= NULL
;
3245 memheap
->poh_freelist
= &poha
->aoh
[0];
3248 poh
= memheap
->poh_freelist
;
3249 memheap
->poh_freelist
= poh
->poh_next
;
3254 static struct SIS_OH
*
3255 sisfb_poh_allocate(struct SIS_HEAP
*memheap
, u32 size
)
3257 struct SIS_OH
*pohThis
;
3258 struct SIS_OH
*pohRoot
;
3261 if(size
> memheap
->max_freesize
) {
3262 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3263 (unsigned int) size
/ 1024);
3267 pohThis
= memheap
->oh_free
.poh_next
;
3269 while(pohThis
!= &memheap
->oh_free
) {
3270 if(size
<= pohThis
->size
) {
3274 pohThis
= pohThis
->poh_next
;
3278 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3279 (unsigned int) size
/ 1024);
3283 if(size
== pohThis
->size
) {
3285 sisfb_delete_node(pohThis
);
3287 pohRoot
= sisfb_poh_new_node(memheap
);
3291 pohRoot
->offset
= pohThis
->offset
;
3292 pohRoot
->size
= size
;
3294 pohThis
->offset
+= size
;
3295 pohThis
->size
-= size
;
3298 memheap
->max_freesize
-= size
;
3300 pohThis
= &memheap
->oh_used
;
3301 sisfb_insert_node(pohThis
, pohRoot
);
3307 sisfb_delete_node(struct SIS_OH
*poh
)
3309 poh
->poh_prev
->poh_next
= poh
->poh_next
;
3310 poh
->poh_next
->poh_prev
= poh
->poh_prev
;
3314 sisfb_insert_node(struct SIS_OH
*pohList
, struct SIS_OH
*poh
)
3316 struct SIS_OH
*pohTemp
= pohList
->poh_next
;
3318 pohList
->poh_next
= poh
;
3319 pohTemp
->poh_prev
= poh
;
3321 poh
->poh_prev
= pohList
;
3322 poh
->poh_next
= pohTemp
;
3325 static struct SIS_OH
*
3326 sisfb_poh_free(struct SIS_HEAP
*memheap
, u32 base
)
3328 struct SIS_OH
*pohThis
;
3329 struct SIS_OH
*poh_freed
;
3330 struct SIS_OH
*poh_prev
;
3331 struct SIS_OH
*poh_next
;
3336 poh_freed
= memheap
->oh_used
.poh_next
;
3338 while(poh_freed
!= &memheap
->oh_used
) {
3339 if(poh_freed
->offset
== base
) {
3344 poh_freed
= poh_freed
->poh_next
;
3350 memheap
->max_freesize
+= poh_freed
->size
;
3352 poh_prev
= poh_next
= NULL
;
3353 ulUpper
= poh_freed
->offset
+ poh_freed
->size
;
3354 ulLower
= poh_freed
->offset
;
3356 pohThis
= memheap
->oh_free
.poh_next
;
3358 while(pohThis
!= &memheap
->oh_free
) {
3359 if(pohThis
->offset
== ulUpper
) {
3361 } else if((pohThis
->offset
+ pohThis
->size
) == ulLower
) {
3364 pohThis
= pohThis
->poh_next
;
3367 sisfb_delete_node(poh_freed
);
3369 if(poh_prev
&& poh_next
) {
3370 poh_prev
->size
+= (poh_freed
->size
+ poh_next
->size
);
3371 sisfb_delete_node(poh_next
);
3372 sisfb_free_node(memheap
, poh_freed
);
3373 sisfb_free_node(memheap
, poh_next
);
3378 poh_prev
->size
+= poh_freed
->size
;
3379 sisfb_free_node(memheap
, poh_freed
);
3384 poh_next
->size
+= poh_freed
->size
;
3385 poh_next
->offset
= poh_freed
->offset
;
3386 sisfb_free_node(memheap
, poh_freed
);
3390 sisfb_insert_node(&memheap
->oh_free
, poh_freed
);
3396 sisfb_free_node(struct SIS_HEAP
*memheap
, struct SIS_OH
*poh
)
3401 poh
->poh_next
= memheap
->poh_freelist
;
3402 memheap
->poh_freelist
= poh
;
3406 sis_int_malloc(struct sis_video_info
*ivideo
, struct sis_memreq
*req
)
3408 struct SIS_OH
*poh
= NULL
;
3410 if((ivideo
) && (ivideo
->sisfb_id
== SISFB_ID
) && (!ivideo
->havenoheap
))
3411 poh
= sisfb_poh_allocate(&ivideo
->sisfb_heap
, (u32
)req
->size
);
3414 req
->offset
= req
->size
= 0;
3415 DPRINTK("sisfb: Video RAM allocation failed\n");
3417 req
->offset
= poh
->offset
;
3418 req
->size
= poh
->size
;
3419 DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3420 (poh
->offset
+ ivideo
->video_vbase
));
3425 sis_malloc(struct sis_memreq
*req
)
3427 struct sis_video_info
*ivideo
= sisfb_heap
->vinfo
;
3429 if(&ivideo
->sisfb_heap
== sisfb_heap
)
3430 sis_int_malloc(ivideo
, req
);
3432 req
->offset
= req
->size
= 0;
3436 sis_malloc_new(struct pci_dev
*pdev
, struct sis_memreq
*req
)
3438 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
3440 sis_int_malloc(ivideo
, req
);
3443 /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3446 sis_int_free(struct sis_video_info
*ivideo
, u32 base
)
3450 if((!ivideo
) || (ivideo
->sisfb_id
!= SISFB_ID
) || (ivideo
->havenoheap
))
3453 poh
= sisfb_poh_free(&ivideo
->sisfb_heap
, base
);
3456 DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
3457 (unsigned int) base
);
3464 struct sis_video_info
*ivideo
= sisfb_heap
->vinfo
;
3466 sis_int_free(ivideo
, base
);
3470 sis_free_new(struct pci_dev
*pdev
, u32 base
)
3472 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
3474 sis_int_free(ivideo
, base
);
3477 /* --------------------- SetMode routines ------------------------- */
3480 sisfb_check_engine_and_sync(struct sis_video_info
*ivideo
)
3484 /* Check if MMIO and engines are enabled,
3485 * and sync in case they are. Can't use
3486 * ivideo->accel here, as this might have
3487 * been changed before this is called.
3489 inSISIDXREG(SISSR
, IND_SIS_PCI_ADDRESS_SET
, cr30
);
3490 inSISIDXREG(SISSR
, IND_SIS_MODULE_ENABLE
, cr31
);
3491 /* MMIO and 2D/3D engine enabled? */
3492 if((cr30
& SIS_MEM_MAP_IO_ENABLE
) && (cr31
& 0x42)) {
3493 #ifdef CONFIG_FB_SIS_300
3494 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3495 /* Don't care about TurboQueue. It's
3496 * enough to know that the engines
3499 sisfb_syncaccel(ivideo
);
3502 #ifdef CONFIG_FB_SIS_315
3503 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3504 /* Check that any queue mode is
3505 * enabled, and that the queue
3506 * is not in the state of "reset"
3508 inSISIDXREG(SISSR
, 0x26, cr30
);
3509 if((cr30
& 0xe0) && (!(cr30
& 0x01))) {
3510 sisfb_syncaccel(ivideo
);
3518 sisfb_pre_setmode(struct sis_video_info
*ivideo
)
3520 u8 cr30
= 0, cr31
= 0, cr33
= 0, cr35
= 0, cr38
= 0;
3523 ivideo
->currentvbflags
&= (VB_VIDEOBRIDGE
| VB_DISPTYPE_DISP2
);
3525 outSISIDXREG(SISSR
, 0x05, 0x86);
3527 inSISIDXREG(SISCR
, 0x31, cr31
);
3531 cr33
= ivideo
->rate_idx
& 0x0F;
3533 #ifdef CONFIG_FB_SIS_315
3534 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3535 if(ivideo
->chip
>= SIS_661
) {
3536 inSISIDXREG(SISCR
, 0x38, cr38
);
3537 cr38
&= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
3540 inSISIDXREG(SISCR
, tvregnum
, cr38
);
3541 cr38
&= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
3545 #ifdef CONFIG_FB_SIS_300
3546 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3548 inSISIDXREG(SISCR
, tvregnum
, cr38
);
3552 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
3553 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
3554 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
3556 switch(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
3559 cr38
&= ~0xc0; /* Clear PAL-M / PAL-N bits */
3560 if((ivideo
->vbflags
& TV_YPBPR
) && (ivideo
->vbflags2
& VB2_SISYPBPRBRIDGE
)) {
3561 #ifdef CONFIG_FB_SIS_315
3562 if(ivideo
->chip
>= SIS_661
) {
3564 if(ivideo
->vbflags
& TV_YPBPR525P
) cr35
|= 0x20;
3565 else if(ivideo
->vbflags
& TV_YPBPR750P
) cr35
|= 0x40;
3566 else if(ivideo
->vbflags
& TV_YPBPR1080I
) cr35
|= 0x60;
3567 cr30
|= SIS_SIMULTANEOUS_VIEW_ENABLE
;
3569 ivideo
->currentvbflags
|= (TV_YPBPR
| (ivideo
->vbflags
& TV_YPBPRALL
));
3570 } else if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3571 cr30
|= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE
);
3573 if(ivideo
->vbflags
& TV_YPBPR525P
) cr38
|= 0x10;
3574 else if(ivideo
->vbflags
& TV_YPBPR750P
) cr38
|= 0x20;
3575 else if(ivideo
->vbflags
& TV_YPBPR1080I
) cr38
|= 0x30;
3577 ivideo
->currentvbflags
|= (TV_YPBPR
| (ivideo
->vbflags
& TV_YPBPRALL
));
3580 } else if((ivideo
->vbflags
& TV_HIVISION
) &&
3581 (ivideo
->vbflags2
& VB2_SISHIVISIONBRIDGE
)) {
3582 if(ivideo
->chip
>= SIS_661
) {
3588 cr30
|= SIS_SIMULTANEOUS_VIEW_ENABLE
;
3591 ivideo
->currentvbflags
|= TV_HIVISION
;
3592 } else if(ivideo
->vbflags
& TV_SCART
) {
3593 cr30
= (SIS_VB_OUTPUT_SCART
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3596 ivideo
->currentvbflags
|= TV_SCART
;
3598 if(ivideo
->vbflags
& TV_SVIDEO
) {
3599 cr30
= (SIS_VB_OUTPUT_SVIDEO
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3600 ivideo
->currentvbflags
|= TV_SVIDEO
;
3602 if(ivideo
->vbflags
& TV_AVIDEO
) {
3603 cr30
= (SIS_VB_OUTPUT_COMPOSITE
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3604 ivideo
->currentvbflags
|= TV_AVIDEO
;
3607 cr31
|= SIS_DRIVER_MODE
;
3609 if(ivideo
->vbflags
& (TV_AVIDEO
| TV_SVIDEO
)) {
3610 if(ivideo
->vbflags
& TV_PAL
) {
3611 cr31
|= 0x01; cr35
|= 0x01;
3612 ivideo
->currentvbflags
|= TV_PAL
;
3613 if(ivideo
->vbflags
& TV_PALM
) {
3614 cr38
|= 0x40; cr35
|= 0x04;
3615 ivideo
->currentvbflags
|= TV_PALM
;
3616 } else if(ivideo
->vbflags
& TV_PALN
) {
3617 cr38
|= 0x80; cr35
|= 0x08;
3618 ivideo
->currentvbflags
|= TV_PALN
;
3621 cr31
&= ~0x01; cr35
&= ~0x01;
3622 ivideo
->currentvbflags
|= TV_NTSC
;
3623 if(ivideo
->vbflags
& TV_NTSCJ
) {
3624 cr38
|= 0x40; cr35
|= 0x02;
3625 ivideo
->currentvbflags
|= TV_NTSCJ
;
3632 cr30
= (SIS_VB_OUTPUT_LCD
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3633 cr31
|= SIS_DRIVER_MODE
;
3634 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, ivideo
->sisfb_dstn
);
3635 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, ivideo
->sisfb_fstn
);
3636 ivideo
->curFSTN
= ivideo
->sisfb_fstn
;
3637 ivideo
->curDSTN
= ivideo
->sisfb_dstn
;
3641 cr30
= (SIS_VB_OUTPUT_CRT2
| SIS_SIMULTANEOUS_VIEW_ENABLE
);
3642 cr31
|= SIS_DRIVER_MODE
;
3643 if(ivideo
->sisfb_nocrt2rate
) {
3644 cr33
|= (sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
<< 4);
3646 cr33
|= ((ivideo
->rate_idx
& 0x0F) << 4);
3650 default: /* disable CRT2 */
3652 cr31
|= (SIS_DRIVER_MODE
| SIS_VB_OUTPUT_DISABLE
);
3655 outSISIDXREG(SISCR
, 0x30, cr30
);
3656 outSISIDXREG(SISCR
, 0x33, cr33
);
3658 if(ivideo
->chip
>= SIS_661
) {
3659 #ifdef CONFIG_FB_SIS_315
3660 cr31
&= ~0x01; /* Clear PAL flag (now in CR35) */
3661 setSISIDXREG(SISCR
, 0x35, ~0x10, cr35
); /* Leave overscan bit alone */
3662 cr38
&= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
3663 setSISIDXREG(SISCR
, 0x38, 0xf8, cr38
);
3665 } else if(ivideo
->chip
!= SIS_300
) {
3666 outSISIDXREG(SISCR
, tvregnum
, cr38
);
3668 outSISIDXREG(SISCR
, 0x31, cr31
);
3670 ivideo
->SiS_Pr
.SiS_UseOEM
= ivideo
->sisfb_useoem
;
3672 sisfb_check_engine_and_sync(ivideo
);
3675 /* Fix SR11 for 661 and later */
3676 #ifdef CONFIG_FB_SIS_315
3678 sisfb_fixup_SR11(struct sis_video_info
*ivideo
)
3682 if(ivideo
->chip
>= SIS_661
) {
3683 inSISIDXREG(SISSR
,0x11,tmpreg
);
3685 inSISIDXREG(SISSR
,0x3e,tmpreg
);
3686 tmpreg
= (tmpreg
+ 1) & 0xff;
3687 outSISIDXREG(SISSR
,0x3e,tmpreg
);
3688 inSISIDXREG(SISSR
,0x11,tmpreg
);
3691 andSISIDXREG(SISSR
,0x11,0x0f);
3698 sisfb_set_TVxposoffset(struct sis_video_info
*ivideo
, int val
)
3700 if(val
> 32) val
= 32;
3701 if(val
< -32) val
= -32;
3702 ivideo
->tvxpos
= val
;
3704 if(ivideo
->sisfblocked
) return;
3705 if(!ivideo
->modechanged
) return;
3707 if(ivideo
->currentvbflags
& CRT2_TV
) {
3709 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3711 int x
= ivideo
->tvx
;
3713 switch(ivideo
->chronteltype
) {
3717 outSISIDXREG(SISSR
,0x05,0x86);
3718 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0a, (x
& 0xff));
3719 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x08, ((x
& 0x0100) >> 7), 0xFD);
3722 /* Not supported by hardware */
3726 } else if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3728 u8 p2_1f
,p2_20
,p2_2b
,p2_42
,p2_43
;
3729 unsigned short temp
;
3731 p2_1f
= ivideo
->p2_1f
;
3732 p2_20
= ivideo
->p2_20
;
3733 p2_2b
= ivideo
->p2_2b
;
3734 p2_42
= ivideo
->p2_42
;
3735 p2_43
= ivideo
->p2_43
;
3737 temp
= p2_1f
| ((p2_20
& 0xf0) << 4);
3739 p2_1f
= temp
& 0xff;
3740 p2_20
= (temp
& 0xf00) >> 4;
3741 p2_2b
= ((p2_2b
& 0x0f) + (val
* 2)) & 0x0f;
3742 temp
= p2_43
| ((p2_42
& 0xf0) << 4);
3744 p2_43
= temp
& 0xff;
3745 p2_42
= (temp
& 0xf00) >> 4;
3746 outSISIDXREG(SISPART2
,0x1f,p2_1f
);
3747 setSISIDXREG(SISPART2
,0x20,0x0F,p2_20
);
3748 setSISIDXREG(SISPART2
,0x2b,0xF0,p2_2b
);
3749 setSISIDXREG(SISPART2
,0x42,0x0F,p2_42
);
3750 outSISIDXREG(SISPART2
,0x43,p2_43
);
3756 sisfb_set_TVyposoffset(struct sis_video_info
*ivideo
, int val
)
3758 if(val
> 32) val
= 32;
3759 if(val
< -32) val
= -32;
3760 ivideo
->tvypos
= val
;
3762 if(ivideo
->sisfblocked
) return;
3763 if(!ivideo
->modechanged
) return;
3765 if(ivideo
->currentvbflags
& CRT2_TV
) {
3767 if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3769 int y
= ivideo
->tvy
;
3771 switch(ivideo
->chronteltype
) {
3775 outSISIDXREG(SISSR
,0x05,0x86);
3776 SiS_SetCH700x(&ivideo
->SiS_Pr
, 0x0b, (y
& 0xff));
3777 SiS_SetCH70xxANDOR(&ivideo
->SiS_Pr
, 0x08, ((y
& 0x0100) >> 8), 0xFE);
3780 /* Not supported by hardware */
3784 } else if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3788 p2_01
= ivideo
->p2_01
;
3789 p2_02
= ivideo
->p2_02
;
3793 if(!(ivideo
->currentvbflags
& (TV_HIVISION
| TV_YPBPR
))) {
3794 while((p2_01
<= 0) || (p2_02
<= 0)) {
3799 outSISIDXREG(SISPART2
,0x01,p2_01
);
3800 outSISIDXREG(SISPART2
,0x02,p2_02
);
3806 sisfb_post_setmode(struct sis_video_info
*ivideo
)
3808 bool crt1isoff
= false;
3810 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
3813 #ifdef CONFIG_FB_SIS_315
3817 outSISIDXREG(SISSR
, 0x05, 0x86);
3819 #ifdef CONFIG_FB_SIS_315
3820 sisfb_fixup_SR11(ivideo
);
3823 /* Now we actually HAVE changed the display mode */
3824 ivideo
->modechanged
= 1;
3826 /* We can't switch off CRT1 if bridge is in slave mode */
3827 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
3828 if(sisfb_bridgeisslave(ivideo
)) doit
= false;
3830 ivideo
->sisfb_crt1off
= 0;
3832 #ifdef CONFIG_FB_SIS_300
3833 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
3834 if((ivideo
->sisfb_crt1off
) && (doit
)) {
3841 setSISIDXREG(SISCR
, 0x17, 0x7f, reg
);
3844 #ifdef CONFIG_FB_SIS_315
3845 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
3846 if((ivideo
->sisfb_crt1off
) && (doit
)) {
3855 setSISIDXREG(SISCR
, ivideo
->SiS_Pr
.SiS_MyCR63
, ~0x40, reg
);
3856 setSISIDXREG(SISSR
, 0x1f, ~0xc0, reg1
);
3861 ivideo
->currentvbflags
&= ~VB_DISPTYPE_CRT1
;
3862 ivideo
->currentvbflags
|= VB_SINGLE_MODE
;
3864 ivideo
->currentvbflags
|= VB_DISPTYPE_CRT1
;
3865 if(ivideo
->currentvbflags
& VB_DISPTYPE_CRT2
) {
3866 ivideo
->currentvbflags
|= VB_MIRROR_MODE
;
3868 ivideo
->currentvbflags
|= VB_SINGLE_MODE
;
3872 andSISIDXREG(SISSR
, IND_SIS_RAMDAC_CONTROL
, ~0x04);
3874 if(ivideo
->currentvbflags
& CRT2_TV
) {
3875 if(ivideo
->vbflags2
& VB2_SISBRIDGE
) {
3876 inSISIDXREG(SISPART2
,0x1f,ivideo
->p2_1f
);
3877 inSISIDXREG(SISPART2
,0x20,ivideo
->p2_20
);
3878 inSISIDXREG(SISPART2
,0x2b,ivideo
->p2_2b
);
3879 inSISIDXREG(SISPART2
,0x42,ivideo
->p2_42
);
3880 inSISIDXREG(SISPART2
,0x43,ivideo
->p2_43
);
3881 inSISIDXREG(SISPART2
,0x01,ivideo
->p2_01
);
3882 inSISIDXREG(SISPART2
,0x02,ivideo
->p2_02
);
3883 } else if(ivideo
->vbflags2
& VB2_CHRONTEL
) {
3884 if(ivideo
->chronteltype
== 1) {
3885 ivideo
->tvx
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0a);
3886 ivideo
->tvx
|= (((SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x08) & 0x02) >> 1) << 8);
3887 ivideo
->tvy
= SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x0b);
3888 ivideo
->tvy
|= ((SiS_GetCH700x(&ivideo
->SiS_Pr
, 0x08) & 0x01) << 8);
3893 if(ivideo
->tvxpos
) {
3894 sisfb_set_TVxposoffset(ivideo
, ivideo
->tvxpos
);
3896 if(ivideo
->tvypos
) {
3897 sisfb_set_TVyposoffset(ivideo
, ivideo
->tvypos
);
3900 /* Eventually sync engines */
3901 sisfb_check_engine_and_sync(ivideo
);
3903 /* (Re-)Initialize chip engines */
3905 sisfb_engine_init(ivideo
);
3907 ivideo
->engineok
= 0;
3912 sisfb_reset_mode(struct sis_video_info
*ivideo
)
3914 if(sisfb_set_mode(ivideo
, 0))
3917 sisfb_set_pitch(ivideo
);
3918 sisfb_set_base_CRT1(ivideo
, ivideo
->current_base
);
3919 sisfb_set_base_CRT2(ivideo
, ivideo
->current_base
);
3925 sisfb_handle_command(struct sis_video_info
*ivideo
, struct sisfb_cmd
*sisfb_command
)
3929 switch(sisfb_command
->sisfb_cmd
) {
3930 case SISFB_CMD_GETVBFLAGS
:
3931 if(!ivideo
->modechanged
) {
3932 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_EARLY
;
3934 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3935 sisfb_command
->sisfb_result
[1] = ivideo
->currentvbflags
;
3936 sisfb_command
->sisfb_result
[2] = ivideo
->vbflags2
;
3939 case SISFB_CMD_SWITCHCRT1
:
3940 /* arg[0]: 0 = off, 1 = on, 99 = query */
3941 if(!ivideo
->modechanged
) {
3942 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_EARLY
;
3943 } else if(sisfb_command
->sisfb_arg
[0] == 99) {
3945 sisfb_command
->sisfb_result
[1] = ivideo
->sisfb_crt1off
? 0 : 1;
3946 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3947 } else if(ivideo
->sisfblocked
) {
3948 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_LOCKED
;
3949 } else if((!(ivideo
->currentvbflags
& CRT2_ENABLE
)) &&
3950 (sisfb_command
->sisfb_arg
[0] == 0)) {
3951 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_NOCRT2
;
3953 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OK
;
3954 mycrt1off
= sisfb_command
->sisfb_arg
[0] ? 0 : 1;
3955 if( ((ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
) && mycrt1off
) ||
3956 ((!(ivideo
->currentvbflags
& VB_DISPTYPE_CRT1
)) && !mycrt1off
) ) {
3957 ivideo
->sisfb_crt1off
= mycrt1off
;
3958 if(sisfb_reset_mode(ivideo
)) {
3959 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_OTHER
;
3962 sisfb_command
->sisfb_result
[1] = ivideo
->sisfb_crt1off
? 0 : 1;
3967 sisfb_command
->sisfb_result
[0] = SISFB_CMD_ERR_UNKNOWN
;
3968 printk(KERN_ERR
"sisfb: Unknown command 0x%x\n",
3969 sisfb_command
->sisfb_cmd
);
3974 static int __init
sisfb_setup(char *options
)
3978 sisfb_setdefaultparms();
3980 if(!options
|| !(*options
))
3983 while((this_opt
= strsep(&options
, ",")) != NULL
) {
3985 if(!(*this_opt
)) continue;
3987 if(!strnicmp(this_opt
, "off", 3)) {
3989 } else if(!strnicmp(this_opt
, "forcecrt2type:", 14)) {
3990 /* Need to check crt2 type first for fstn/dstn */
3991 sisfb_search_crt2type(this_opt
+ 14);
3992 } else if(!strnicmp(this_opt
, "tvmode:",7)) {
3993 sisfb_search_tvstd(this_opt
+ 7);
3994 } else if(!strnicmp(this_opt
, "tvstandard:",11)) {
3995 sisfb_search_tvstd(this_opt
+ 11);
3996 } else if(!strnicmp(this_opt
, "mode:", 5)) {
3997 sisfb_search_mode(this_opt
+ 5, false);
3998 } else if(!strnicmp(this_opt
, "vesa:", 5)) {
3999 sisfb_search_vesamode(simple_strtoul(this_opt
+ 5, NULL
, 0), false);
4000 } else if(!strnicmp(this_opt
, "rate:", 5)) {
4001 sisfb_parm_rate
= simple_strtoul(this_opt
+ 5, NULL
, 0);
4002 } else if(!strnicmp(this_opt
, "forcecrt1:", 10)) {
4003 sisfb_forcecrt1
= (int)simple_strtoul(this_opt
+ 10, NULL
, 0);
4004 } else if(!strnicmp(this_opt
, "mem:",4)) {
4005 sisfb_parm_mem
= simple_strtoul(this_opt
+ 4, NULL
, 0);
4006 } else if(!strnicmp(this_opt
, "pdc:", 4)) {
4007 sisfb_pdc
= simple_strtoul(this_opt
+ 4, NULL
, 0);
4008 } else if(!strnicmp(this_opt
, "pdc1:", 5)) {
4009 sisfb_pdca
= simple_strtoul(this_opt
+ 5, NULL
, 0);
4010 } else if(!strnicmp(this_opt
, "noaccel", 7)) {
4012 } else if(!strnicmp(this_opt
, "accel", 5)) {
4014 } else if(!strnicmp(this_opt
, "noypan", 6)) {
4016 } else if(!strnicmp(this_opt
, "ypan", 4)) {
4018 } else if(!strnicmp(this_opt
, "nomax", 5)) {
4020 } else if(!strnicmp(this_opt
, "max", 3)) {
4022 } else if(!strnicmp(this_opt
, "userom:", 7)) {
4023 sisfb_userom
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
4024 } else if(!strnicmp(this_opt
, "useoem:", 7)) {
4025 sisfb_useoem
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
4026 } else if(!strnicmp(this_opt
, "nocrt2rate", 10)) {
4027 sisfb_nocrt2rate
= 1;
4028 } else if(!strnicmp(this_opt
, "scalelcd:", 9)) {
4029 unsigned long temp
= 2;
4030 temp
= simple_strtoul(this_opt
+ 9, NULL
, 0);
4031 if((temp
== 0) || (temp
== 1)) {
4032 sisfb_scalelcd
= temp
^ 1;
4034 } else if(!strnicmp(this_opt
, "tvxposoffset:", 13)) {
4036 temp
= (int)simple_strtol(this_opt
+ 13, NULL
, 0);
4037 if((temp
>= -32) && (temp
<= 32)) {
4038 sisfb_tvxposoffset
= temp
;
4040 } else if(!strnicmp(this_opt
, "tvyposoffset:", 13)) {
4042 temp
= (int)simple_strtol(this_opt
+ 13, NULL
, 0);
4043 if((temp
>= -32) && (temp
<= 32)) {
4044 sisfb_tvyposoffset
= temp
;
4046 } else if(!strnicmp(this_opt
, "specialtiming:", 14)) {
4047 sisfb_search_specialtiming(this_opt
+ 14);
4048 } else if(!strnicmp(this_opt
, "lvdshl:", 7)) {
4050 temp
= simple_strtoul(this_opt
+ 7, NULL
, 0);
4051 if((temp
>= 0) && (temp
<= 3)) {
4052 sisfb_lvdshl
= temp
;
4054 } else if(this_opt
[0] >= '0' && this_opt
[0] <= '9') {
4055 sisfb_search_mode(this_opt
, true);
4056 #if !defined(__i386__) && !defined(__x86_64__)
4057 } else if(!strnicmp(this_opt
, "resetcard", 9)) {
4058 sisfb_resetcard
= 1;
4059 } else if(!strnicmp(this_opt
, "videoram:", 9)) {
4060 sisfb_videoram
= simple_strtoul(this_opt
+ 9, NULL
, 0);
4063 printk(KERN_INFO
"sisfb: Invalid option %s\n", this_opt
);
4072 static int __devinit
4073 sisfb_check_rom(void __iomem
*rom_base
, struct sis_video_info
*ivideo
)
4078 if((readb(rom_base
) != 0x55) || (readb(rom_base
+ 1) != 0xaa))
4081 romptr
= (readb(rom_base
+ 0x18) | (readb(rom_base
+ 0x19) << 8));
4082 if(romptr
> (0x10000 - 8))
4085 rom
= rom_base
+ romptr
;
4087 if((readb(rom
) != 'P') || (readb(rom
+ 1) != 'C') ||
4088 (readb(rom
+ 2) != 'I') || (readb(rom
+ 3) != 'R'))
4091 if((readb(rom
+ 4) | (readb(rom
+ 5) << 8)) != ivideo
->chip_vendor
)
4094 if((readb(rom
+ 6) | (readb(rom
+ 7) << 8)) != ivideo
->chip_id
)
4100 static unsigned char * __devinit
4101 sisfb_find_rom(struct pci_dev
*pdev
)
4103 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4104 void __iomem
*rom_base
;
4105 unsigned char *myrombase
= NULL
;
4109 /* First, try the official pci ROM functions (except
4110 * on integrated chipsets which have no ROM).
4113 if(!ivideo
->nbridge
) {
4115 if((rom_base
= pci_map_rom(pdev
, &romsize
))) {
4117 if(sisfb_check_rom(rom_base
, ivideo
)) {
4119 if((myrombase
= vmalloc(65536))) {
4121 /* Work around bug in pci/rom.c: Folks forgot to check
4122 * whether the size retrieved from the BIOS image eventually
4123 * is larger than the mapped size
4125 if(pci_resource_len(pdev
, PCI_ROM_RESOURCE
) < romsize
)
4126 romsize
= pci_resource_len(pdev
, PCI_ROM_RESOURCE
);
4128 memcpy_fromio(myrombase
, rom_base
,
4129 (romsize
> 65536) ? 65536 : romsize
);
4132 pci_unmap_rom(pdev
, rom_base
);
4136 if(myrombase
) return myrombase
;
4138 /* Otherwise do it the conventional way. */
4140 #if defined(__i386__) || defined(__x86_64__)
4142 for(temp
= 0x000c0000; temp
< 0x000f0000; temp
+= 0x00001000) {
4144 rom_base
= ioremap(temp
, 65536);
4148 if(!sisfb_check_rom(rom_base
, ivideo
)) {
4153 if((myrombase
= vmalloc(65536)))
4154 memcpy_fromio(myrombase
, rom_base
, 65536);
4163 pci_read_config_dword(pdev
, PCI_ROM_ADDRESS
, &temp
);
4164 pci_write_config_dword(pdev
, PCI_ROM_ADDRESS
,
4165 (ivideo
->video_base
& PCI_ROM_ADDRESS_MASK
) | PCI_ROM_ADDRESS_ENABLE
);
4167 rom_base
= ioremap(ivideo
->video_base
, 65536);
4169 if(sisfb_check_rom(rom_base
, ivideo
)) {
4170 if((myrombase
= vmalloc(65536)))
4171 memcpy_fromio(myrombase
, rom_base
, 65536);
4176 pci_write_config_dword(pdev
, PCI_ROM_ADDRESS
, temp
);
4183 static void __devinit
4184 sisfb_post_map_vram(struct sis_video_info
*ivideo
, unsigned int *mapsize
,
4187 ivideo
->video_vbase
= ioremap(ivideo
->video_base
, (*mapsize
));
4189 if(!ivideo
->video_vbase
) {
4191 "sisfb: Unable to map maximum video RAM for size detection\n");
4193 while((!(ivideo
->video_vbase
= ioremap(ivideo
->video_base
, (*mapsize
))))) {
4195 if((*mapsize
) < (min
<< 20))
4198 if(ivideo
->video_vbase
) {
4200 "sisfb: Video RAM size detection limited to %dMB\n",
4201 (int)((*mapsize
) >> 20));
4206 #ifdef CONFIG_FB_SIS_300
4207 static int __devinit
4208 sisfb_post_300_buswidth(struct sis_video_info
*ivideo
)
4210 void __iomem
*FBAddress
= ivideo
->video_vbase
;
4211 unsigned short temp
;
4215 andSISIDXREG(SISSR
, 0x15, 0xFB);
4216 orSISIDXREG(SISSR
, 0x15, 0x04);
4217 outSISIDXREG(SISSR
, 0x13, 0x00);
4218 outSISIDXREG(SISSR
, 0x14, 0xBF);
4220 for(i
= 0; i
< 2; i
++) {
4222 for(j
= 0; j
< 4; j
++) {
4223 writew(temp
, FBAddress
);
4224 if(readw(FBAddress
) == temp
)
4226 orSISIDXREG(SISSR
, 0x3c, 0x01);
4227 inSISIDXREG(SISSR
, 0x05, reg
);
4228 inSISIDXREG(SISSR
, 0x05, reg
);
4229 andSISIDXREG(SISSR
, 0x3c, 0xfe);
4230 inSISIDXREG(SISSR
, 0x05, reg
);
4231 inSISIDXREG(SISSR
, 0x05, reg
);
4236 writel(0x01234567L
, FBAddress
);
4237 writel(0x456789ABL
, (FBAddress
+ 4));
4238 writel(0x89ABCDEFL
, (FBAddress
+ 8));
4239 writel(0xCDEF0123L
, (FBAddress
+ 12));
4241 inSISIDXREG(SISSR
, 0x3b, reg
);
4243 if(readl((FBAddress
+ 12)) == 0xCDEF0123L
)
4244 return 4; /* Channel A 128bit */
4247 if(readl((FBAddress
+ 4)) == 0x456789ABL
)
4248 return 2; /* Channel B 64bit */
4250 return 1; /* 32bit */
4253 static int __devinit
4254 sisfb_post_300_rwtest(struct sis_video_info
*ivideo
, int iteration
, int buswidth
,
4255 int PseudoRankCapacity
, int PseudoAdrPinCount
,
4256 unsigned int mapsize
)
4258 void __iomem
*FBAddr
= ivideo
->video_vbase
;
4259 unsigned short sr14
;
4260 unsigned int k
, RankCapacity
, PageCapacity
, BankNumHigh
, BankNumMid
;
4261 unsigned int PhysicalAdrOtherPage
, PhysicalAdrHigh
, PhysicalAdrHalfPage
;
4262 static const unsigned short SiS_DRAMType
[17][5] = {
4263 {0x0C,0x0A,0x02,0x40,0x39},
4264 {0x0D,0x0A,0x01,0x40,0x48},
4265 {0x0C,0x09,0x02,0x20,0x35},
4266 {0x0D,0x09,0x01,0x20,0x44},
4267 {0x0C,0x08,0x02,0x10,0x31},
4268 {0x0D,0x08,0x01,0x10,0x40},
4269 {0x0C,0x0A,0x01,0x20,0x34},
4270 {0x0C,0x09,0x01,0x08,0x32},
4271 {0x0B,0x08,0x02,0x08,0x21},
4272 {0x0C,0x08,0x01,0x08,0x30},
4273 {0x0A,0x08,0x02,0x04,0x11},
4274 {0x0B,0x0A,0x01,0x10,0x28},
4275 {0x09,0x08,0x02,0x02,0x01},
4276 {0x0B,0x09,0x01,0x08,0x24},
4277 {0x0B,0x08,0x01,0x04,0x20},
4278 {0x0A,0x08,0x01,0x02,0x10},
4279 {0x09,0x08,0x01,0x01,0x00}
4282 for(k
= 0; k
<= 16; k
++) {
4284 RankCapacity
= buswidth
* SiS_DRAMType
[k
][3];
4286 if(RankCapacity
!= PseudoRankCapacity
)
4289 if((SiS_DRAMType
[k
][2] + SiS_DRAMType
[k
][0]) > PseudoAdrPinCount
)
4292 BankNumHigh
= RankCapacity
* 16 * iteration
- 1;
4293 if(iteration
== 3) { /* Rank No */
4294 BankNumMid
= RankCapacity
* 16 - 1;
4296 BankNumMid
= RankCapacity
* 16 * iteration
/ 2 - 1;
4299 PageCapacity
= (1 << SiS_DRAMType
[k
][1]) * buswidth
* 4;
4300 PhysicalAdrHigh
= BankNumHigh
;
4301 PhysicalAdrHalfPage
= (PageCapacity
/ 2 + PhysicalAdrHigh
) % PageCapacity
;
4302 PhysicalAdrOtherPage
= PageCapacity
* SiS_DRAMType
[k
][2] + PhysicalAdrHigh
;
4304 andSISIDXREG(SISSR
, 0x15, 0xFB); /* Test */
4305 orSISIDXREG(SISSR
, 0x15, 0x04); /* Test */
4306 sr14
= (SiS_DRAMType
[k
][3] * buswidth
) - 1;
4307 if(buswidth
== 4) sr14
|= 0x80;
4308 else if(buswidth
== 2) sr14
|= 0x40;
4309 outSISIDXREG(SISSR
, 0x13, SiS_DRAMType
[k
][4]);
4310 outSISIDXREG(SISSR
, 0x14, sr14
);
4315 if((BankNumHigh
+ PhysicalAdrHigh
>= mapsize
) ||
4316 (BankNumMid
+ PhysicalAdrHigh
>= mapsize
) ||
4317 (BankNumHigh
+ PhysicalAdrHalfPage
>= mapsize
) ||
4318 (BankNumHigh
+ PhysicalAdrOtherPage
>= mapsize
))
4322 writew(((unsigned short)PhysicalAdrHigh
),
4323 (FBAddr
+ BankNumHigh
+ PhysicalAdrHigh
));
4324 writew(((unsigned short)BankNumMid
),
4325 (FBAddr
+ BankNumMid
+ PhysicalAdrHigh
));
4326 writew(((unsigned short)PhysicalAdrHalfPage
),
4327 (FBAddr
+ BankNumHigh
+ PhysicalAdrHalfPage
));
4328 writew(((unsigned short)PhysicalAdrOtherPage
),
4329 (FBAddr
+ BankNumHigh
+ PhysicalAdrOtherPage
));
4332 if(readw(FBAddr
+ BankNumHigh
+ PhysicalAdrHigh
) == PhysicalAdrHigh
)
4339 static void __devinit
4340 sisfb_post_300_ramsize(struct pci_dev
*pdev
, unsigned int mapsize
)
4342 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4344 int PseudoRankCapacity
, PseudoAdrPinCount
;
4346 buswidth
= sisfb_post_300_buswidth(ivideo
);
4348 for(i
= 6; i
>= 0; i
--) {
4349 PseudoRankCapacity
= 1 << i
;
4350 for(j
= 4; j
>= 1; j
--) {
4351 PseudoAdrPinCount
= 15 - j
;
4352 if((PseudoRankCapacity
* j
) <= 64) {
4353 if(sisfb_post_300_rwtest(ivideo
,
4365 static void __devinit
4366 sisfb_post_sis300(struct pci_dev
*pdev
)
4368 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4369 unsigned char *bios
= ivideo
->SiS_Pr
.VirtualRomBase
;
4370 u8 reg
, v1
, v2
, v3
, v4
, v5
, v6
, v7
, v8
;
4371 u16 index
, rindex
, memtype
= 0;
4372 unsigned int mapsize
;
4374 if(!ivideo
->SiS_Pr
.UseROM
)
4377 outSISIDXREG(SISSR
, 0x05, 0x86);
4380 if(bios
[0x52] & 0x80) {
4381 memtype
= bios
[0x52];
4383 inSISIDXREG(SISSR
, 0x3a, memtype
);
4388 v3
= 0x80; v6
= 0x80;
4389 if(ivideo
->revision_id
<= 0x13) {
4390 v1
= 0x44; v2
= 0x42;
4391 v4
= 0x44; v5
= 0x42;
4393 v1
= 0x68; v2
= 0x43; /* Assume 125Mhz MCLK */
4394 v4
= 0x68; v5
= 0x43; /* Assume 125Mhz ECLK */
4396 index
= memtype
* 5;
4397 rindex
= index
+ 0x54;
4398 v1
= bios
[rindex
++];
4399 v2
= bios
[rindex
++];
4400 v3
= bios
[rindex
++];
4401 rindex
= index
+ 0x7c;
4402 v4
= bios
[rindex
++];
4403 v5
= bios
[rindex
++];
4404 v6
= bios
[rindex
++];
4407 outSISIDXREG(SISSR
, 0x28, v1
);
4408 outSISIDXREG(SISSR
, 0x29, v2
);
4409 outSISIDXREG(SISSR
, 0x2a, v3
);
4410 outSISIDXREG(SISSR
, 0x2e, v4
);
4411 outSISIDXREG(SISSR
, 0x2f, v5
);
4412 outSISIDXREG(SISSR
, 0x30, v6
);
4417 outSISIDXREG(SISSR
, 0x07, v1
); /* DAC speed */
4419 outSISIDXREG(SISSR
, 0x11, 0x0f); /* DDC, power save */
4421 v1
= 0x01; v2
= 0x43; v3
= 0x1e; v4
= 0x2a;
4422 v5
= 0x06; v6
= 0x00; v7
= 0x00; v8
= 0x00;
4426 v2
= bios
[memtype
+ 8];
4427 v3
= bios
[memtype
+ 16];
4428 v4
= bios
[memtype
+ 24];
4429 v5
= bios
[memtype
+ 32];
4430 v6
= bios
[memtype
+ 40];
4431 v7
= bios
[memtype
+ 48];
4432 v8
= bios
[memtype
+ 56];
4434 if(ivideo
->revision_id
>= 0x80)
4436 outSISIDXREG(SISSR
, 0x15, v1
); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4437 outSISIDXREG(SISSR
, 0x16, v2
);
4438 outSISIDXREG(SISSR
, 0x17, v3
);
4439 outSISIDXREG(SISSR
, 0x18, v4
);
4440 outSISIDXREG(SISSR
, 0x19, v5
);
4441 outSISIDXREG(SISSR
, 0x1a, v6
);
4442 outSISIDXREG(SISSR
, 0x1b, v7
);
4443 outSISIDXREG(SISSR
, 0x1c, v8
); /* ---- */
4444 andSISIDXREG(SISSR
, 0x15 ,0xfb);
4445 orSISIDXREG(SISSR
, 0x15, 0x04);
4447 if(bios
[0x53] & 0x02) {
4448 orSISIDXREG(SISSR
, 0x19, 0x20);
4451 v1
= 0x04; /* DAC pedestal (BIOS 0xe5) */
4452 if(ivideo
->revision_id
>= 0x80)
4454 outSISIDXREG(SISSR
, 0x1f, v1
);
4455 outSISIDXREG(SISSR
, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
4456 v1
= 0xf6; v2
= 0x0d; v3
= 0x00;
4462 outSISIDXREG(SISSR
, 0x23, v1
);
4463 outSISIDXREG(SISSR
, 0x24, v2
);
4464 outSISIDXREG(SISSR
, 0x25, v3
);
4465 outSISIDXREG(SISSR
, 0x21, 0x84);
4466 outSISIDXREG(SISSR
, 0x22, 0x00);
4467 outSISIDXREG(SISCR
, 0x37, 0x00);
4468 orSISIDXREG(SISPART1
, 0x24, 0x01); /* unlock crt2 */
4469 outSISIDXREG(SISPART1
, 0x00, 0x00);
4470 v1
= 0x40; v2
= 0x11;
4475 outSISIDXREG(SISPART1
, 0x02, v1
);
4477 if(ivideo
->revision_id
>= 0x80)
4480 inSISIDXREG(SISPART4
, 0x00, reg
);
4481 if((reg
== 1) || (reg
== 2)) {
4482 outSISIDXREG(SISCR
, 0x37, 0x02);
4483 outSISIDXREG(SISPART2
, 0x00, 0x1c);
4484 v4
= 0x00; v5
= 0x00; v6
= 0x10;
4485 if(ivideo
->SiS_Pr
.UseROM
) {
4490 outSISIDXREG(SISPART4
, 0x0d, v4
);
4491 outSISIDXREG(SISPART4
, 0x0e, v5
);
4492 outSISIDXREG(SISPART4
, 0x10, v6
);
4493 outSISIDXREG(SISPART4
, 0x0f, 0x3f);
4494 inSISIDXREG(SISPART4
, 0x01, reg
);
4496 inSISIDXREG(SISPART4
, 0x23, reg
);
4499 outSISIDXREG(SISPART4
, 0x23, reg
);
4504 outSISIDXREG(SISSR
, 0x32, v2
);
4506 andSISIDXREG(SISPART1
, 0x24, 0xfe); /* Lock CRT2 */
4508 inSISIDXREG(SISSR
, 0x16, reg
);
4510 outSISIDXREG(SISCR
, 0x35, reg
);
4511 outSISIDXREG(SISCR
, 0x83, 0x00);
4512 #if !defined(__i386__) && !defined(__x86_64__)
4513 if(sisfb_videoram
) {
4514 outSISIDXREG(SISSR
, 0x13, 0x28); /* ? */
4515 reg
= ((sisfb_videoram
>> 10) - 1) | 0x40;
4516 outSISIDXREG(SISSR
, 0x14, reg
);
4519 /* Need to map max FB size for finding out about RAM size */
4521 sisfb_post_map_vram(ivideo
, &mapsize
, 4);
4523 if(ivideo
->video_vbase
) {
4524 sisfb_post_300_ramsize(pdev
, mapsize
);
4525 iounmap(ivideo
->video_vbase
);
4528 "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4529 outSISIDXREG(SISSR
, 0x13, 0x28); /* ? */
4530 outSISIDXREG(SISSR
, 0x14, 0x47); /* 8MB, 64bit default */
4532 #if !defined(__i386__) && !defined(__x86_64__)
4539 inSISIDXREG(SISSR
, 0x3a, reg
);
4540 if((reg
& 0x30) == 0x30) {
4541 v1
= 0x04; /* PCI */
4544 v1
= 0x14; /* AGP */
4548 outSISIDXREG(SISSR
, 0x21, v1
);
4549 outSISIDXREG(SISSR
, 0x22, v2
);
4552 sisfb_sense_crt1(ivideo
);
4554 /* Set default mode, don't clear screen */
4555 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
4556 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
4557 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
4558 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
4559 ivideo
->SiS_Pr
.VideoMemorySize
= 8 << 20;
4560 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
4562 outSISIDXREG(SISSR
, 0x05, 0x86);
4565 orSISIDXREG(SISSR
, 0x01, 0x20);
4567 /* Save mode number in CR34 */
4568 outSISIDXREG(SISCR
, 0x34, 0x2e);
4570 /* Let everyone know what the current mode is */
4571 ivideo
->modeprechange
= 0x2e;
4575 #ifdef CONFIG_FB_SIS_315
4577 static void __devinit
4578 sisfb_post_sis315330(struct pci_dev
*pdev
)
4584 static void __devinit
4585 sisfb_post_xgi_delay(struct sis_video_info
*ivideo
, int delay
)
4590 for(i
= 0; i
<= (delay
* 10 * 36); i
++) {
4591 inSISIDXREG(SISSR
, 0x05, reg
);
4596 static int __devinit
4597 sisfb_find_host_bridge(struct sis_video_info
*ivideo
, struct pci_dev
*mypdev
,
4598 unsigned short pcivendor
)
4600 struct pci_dev
*pdev
= NULL
;
4601 unsigned short temp
;
4604 while((pdev
= pci_get_class(PCI_CLASS_BRIDGE_HOST
, pdev
))) {
4605 temp
= pdev
->vendor
;
4606 if(temp
== pcivendor
) {
4616 static int __devinit
4617 sisfb_post_xgi_rwtest(struct sis_video_info
*ivideo
, int starta
,
4618 unsigned int enda
, unsigned int mapsize
)
4623 writel(0, ivideo
->video_vbase
);
4625 for(i
= starta
; i
<= enda
; i
++) {
4628 writel(pos
, ivideo
->video_vbase
+ pos
);
4631 sisfb_post_xgi_delay(ivideo
, 150);
4633 if(readl(ivideo
->video_vbase
) != 0)
4636 for(i
= starta
; i
<= enda
; i
++) {
4639 if(readl(ivideo
->video_vbase
+ pos
) != pos
)
4648 static void __devinit
4649 sisfb_post_xgi_ramsize(struct sis_video_info
*ivideo
)
4651 unsigned int buswidth
, ranksize
, channelab
, mapsize
;
4654 static const u8 dramsr13
[12 * 5] = {
4655 0x02, 0x0e, 0x0b, 0x80, 0x5d,
4656 0x02, 0x0e, 0x0a, 0x40, 0x59,
4657 0x02, 0x0d, 0x0b, 0x40, 0x4d,
4658 0x02, 0x0e, 0x09, 0x20, 0x55,
4659 0x02, 0x0d, 0x0a, 0x20, 0x49,
4660 0x02, 0x0c, 0x0b, 0x20, 0x3d,
4661 0x02, 0x0e, 0x08, 0x10, 0x51,
4662 0x02, 0x0d, 0x09, 0x10, 0x45,
4663 0x02, 0x0c, 0x0a, 0x10, 0x39,
4664 0x02, 0x0d, 0x08, 0x08, 0x41,
4665 0x02, 0x0c, 0x09, 0x08, 0x35,
4666 0x02, 0x0c, 0x08, 0x04, 0x31
4668 static const u8 dramsr13_4
[4 * 5] = {
4669 0x02, 0x0d, 0x09, 0x40, 0x45,
4670 0x02, 0x0c, 0x09, 0x20, 0x35,
4671 0x02, 0x0c, 0x08, 0x10, 0x31,
4672 0x02, 0x0b, 0x08, 0x08, 0x21
4675 /* Enable linear mode, disable 0xa0000 address decoding */
4676 /* We disable a0000 address decoding, because
4677 * - if running on x86, if the card is disabled, it means
4678 * that another card is in the system. We don't want
4679 * to interphere with that primary card's textmode.
4680 * - if running on non-x86, there usually is no VGA window
4683 orSISIDXREG(SISSR
, 0x20, (0x80 | 0x04));
4685 /* Need to map max FB size for finding out about RAM size */
4686 mapsize
= 256 << 20;
4687 sisfb_post_map_vram(ivideo
, &mapsize
, 32);
4689 if(!ivideo
->video_vbase
) {
4690 printk(KERN_ERR
"sisfb: Unable to detect RAM size. Setting default.\n");
4691 outSISIDXREG(SISSR
, 0x13, 0x35);
4692 outSISIDXREG(SISSR
, 0x14, 0x41);
4697 /* Non-interleaving */
4698 outSISIDXREG(SISSR
, 0x15, 0x00);
4700 outSISIDXREG(SISSR
, 0x1c, 0x00);
4702 if(ivideo
->chip
== XGI_20
) {
4705 inSISIDXREG(SISCR
, 0x97, reg
);
4706 if(!(reg
& 0x01)) { /* Single 32/16 */
4708 outSISIDXREG(SISSR
, 0x13, 0xb1);
4709 outSISIDXREG(SISSR
, 0x14, 0x52);
4710 sisfb_post_xgi_delay(ivideo
, 1);
4712 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4715 outSISIDXREG(SISSR
, 0x13, 0x31);
4716 outSISIDXREG(SISSR
, 0x14, 0x42);
4717 sisfb_post_xgi_delay(ivideo
, 1);
4718 if(sisfb_post_xgi_rwtest(ivideo
, 23, 23, mapsize
))
4722 outSISIDXREG(SISSR
, 0x13, 0xb1);
4723 outSISIDXREG(SISSR
, 0x14, 0x41);
4724 sisfb_post_xgi_delay(ivideo
, 1);
4726 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4729 outSISIDXREG(SISSR
, 0x13, 0x31);
4730 } else { /* Dual 16/8 */
4732 outSISIDXREG(SISSR
, 0x13, 0xb1);
4733 outSISIDXREG(SISSR
, 0x14, 0x41);
4734 sisfb_post_xgi_delay(ivideo
, 1);
4736 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4739 outSISIDXREG(SISSR
, 0x13, 0x31);
4740 outSISIDXREG(SISSR
, 0x14, 0x31);
4741 sisfb_post_xgi_delay(ivideo
, 1);
4742 if(sisfb_post_xgi_rwtest(ivideo
, 22, 22, mapsize
))
4746 outSISIDXREG(SISSR
, 0x13, 0xb1);
4747 outSISIDXREG(SISSR
, 0x14, 0x30);
4748 sisfb_post_xgi_delay(ivideo
, 1);
4750 if(sisfb_post_xgi_rwtest(ivideo
, 21, 22, mapsize
))
4753 outSISIDXREG(SISSR
, 0x13, 0x31);
4756 } else { /* XGI_40 */
4758 inSISIDXREG(SISCR
, 0x97, reg
);
4760 inSISIDXREG(SISSR
, 0x39, reg
);
4764 if(reg
& 0x01) { /* DDRII */
4766 if(ivideo
->revision_id
== 2) {
4768 outSISIDXREG(SISSR
, 0x13, 0xa1);
4769 outSISIDXREG(SISSR
, 0x14, 0x44);
4771 sisfb_post_xgi_delay(ivideo
, 1);
4772 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4775 outSISIDXREG(SISSR
, 0x13, 0x21);
4776 outSISIDXREG(SISSR
, 0x14, 0x34);
4777 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4781 outSISIDXREG(SISSR
, 0x13, 0xa1);
4782 outSISIDXREG(SISSR
, 0x14, 0x40);
4784 if(sisfb_post_xgi_rwtest(ivideo
, 22, 23, mapsize
))
4787 outSISIDXREG(SISSR
, 0x13, 0x21);
4788 outSISIDXREG(SISSR
, 0x14, 0x30);
4791 outSISIDXREG(SISSR
, 0x13, 0xa1);
4792 outSISIDXREG(SISSR
, 0x14, 0x4c);
4794 sisfb_post_xgi_delay(ivideo
, 1);
4795 if(sisfb_post_xgi_rwtest(ivideo
, 23, 25, mapsize
))
4799 outSISIDXREG(SISSR
, 0x14, 0x48);
4800 sisfb_post_xgi_delay(ivideo
, 1);
4802 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4805 outSISIDXREG(SISSR
, 0x13, 0x21);
4806 outSISIDXREG(SISSR
, 0x14, 0x3c);
4809 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
)) {
4813 outSISIDXREG(SISSR
, 0x14, 0x38);
4817 sisfb_post_xgi_delay(ivideo
, 1);
4822 if(ivideo
->revision_id
== 2) {
4824 outSISIDXREG(SISSR
, 0x13, 0xa1);
4825 outSISIDXREG(SISSR
, 0x14, 0x52);
4826 sisfb_post_xgi_delay(ivideo
, 1);
4828 if(sisfb_post_xgi_rwtest(ivideo
, 23, 24, mapsize
))
4831 outSISIDXREG(SISSR
, 0x13, 0x21);
4832 outSISIDXREG(SISSR
, 0x14, 0x42);
4835 outSISIDXREG(SISSR
, 0x13, 0xa1);
4836 outSISIDXREG(SISSR
, 0x14, 0x5a);
4837 sisfb_post_xgi_delay(ivideo
, 1);
4839 if(sisfb_post_xgi_rwtest(ivideo
, 24, 25, mapsize
))
4842 outSISIDXREG(SISSR
, 0x13, 0x21);
4843 outSISIDXREG(SISSR
, 0x14, 0x4a);
4845 sisfb_post_xgi_delay(ivideo
, 1);
4851 setSISIDXREG(SISSR
, 0x14, 0xf0, sr14
);
4852 sisfb_post_xgi_delay(ivideo
, 1);
4854 j
= (ivideo
->chip
== XGI_20
) ? 5 : 9;
4855 k
= (ivideo
->chip
== XGI_20
) ? 12 : 4;
4857 for(i
= 0; i
< k
; i
++) {
4859 reg
= (ivideo
->chip
== XGI_20
) ?
4860 dramsr13
[(i
* 5) + 4] : dramsr13_4
[(i
* 5) + 4];
4861 setSISIDXREG(SISSR
, 0x13, 0x80, reg
);
4862 sisfb_post_xgi_delay(ivideo
, 50);
4864 ranksize
= (ivideo
->chip
== XGI_20
) ?
4865 dramsr13
[(i
* 5) + 3] : dramsr13_4
[(i
* 5) + 3];
4867 inSISIDXREG(SISSR
, 0x13, reg
);
4868 if(reg
& 0x80) ranksize
<<= 1;
4870 if(ivideo
->chip
== XGI_20
) {
4871 if(buswidth
== 16) ranksize
<<= 1;
4872 else if(buswidth
== 32) ranksize
<<= 2;
4874 if(buswidth
== 64) ranksize
<<= 1;
4880 if((ranksize
* l
) <= 256) {
4881 while((ranksize
>>= 1)) reg
+= 0x10;
4886 setSISIDXREG(SISSR
, 0x14, 0x0f, (reg
& 0xf0));
4887 sisfb_post_xgi_delay(ivideo
, 1);
4889 if(sisfb_post_xgi_rwtest(ivideo
, j
, ((reg
>> 4) + channelab
- 2 + 20), mapsize
))
4893 iounmap(ivideo
->video_vbase
);
4896 static void __devinit
4897 sisfb_post_xgi_setclocks(struct sis_video_info
*ivideo
, u8 regb
)
4901 static const u8 cs90
[8 * 3] = {
4911 static const u8 csb8
[8 * 3] = {
4925 v1
= cs90
[index
]; v2
= cs90
[index
+ 1]; v3
= cs90
[index
+ 2];
4926 if(ivideo
->haveXGIROM
) {
4927 v1
= ivideo
->bios_abase
[0x90 + index
];
4928 v2
= ivideo
->bios_abase
[0x90 + index
+ 1];
4929 v3
= ivideo
->bios_abase
[0x90 + index
+ 2];
4931 outSISIDXREG(SISSR
, 0x28, v1
);
4932 outSISIDXREG(SISSR
, 0x29, v2
);
4933 outSISIDXREG(SISSR
, 0x2a, v3
);
4934 sisfb_post_xgi_delay(ivideo
, 0x43);
4935 sisfb_post_xgi_delay(ivideo
, 0x43);
4936 sisfb_post_xgi_delay(ivideo
, 0x43);
4938 v1
= csb8
[index
]; v2
= csb8
[index
+ 1]; v3
= csb8
[index
+ 2];
4939 if(ivideo
->haveXGIROM
) {
4940 v1
= ivideo
->bios_abase
[0xb8 + index
];
4941 v2
= ivideo
->bios_abase
[0xb8 + index
+ 1];
4942 v3
= ivideo
->bios_abase
[0xb8 + index
+ 2];
4944 outSISIDXREG(SISSR
, 0x2e, v1
);
4945 outSISIDXREG(SISSR
, 0x2f, v2
);
4946 outSISIDXREG(SISSR
, 0x30, v3
);
4947 sisfb_post_xgi_delay(ivideo
, 0x43);
4948 sisfb_post_xgi_delay(ivideo
, 0x43);
4949 sisfb_post_xgi_delay(ivideo
, 0x43);
4952 static int __devinit
4953 sisfb_post_xgi(struct pci_dev
*pdev
)
4955 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
4956 unsigned char *bios
= ivideo
->bios_abase
;
4957 struct pci_dev
*mypdev
= NULL
;
4958 const u8
*ptr
, *ptr2
;
4959 u8 v1
, v2
, v3
, v4
, v5
, reg
, ramtype
;
4960 u32 rega
, regb
, regd
;
4962 static const u8 cs78
[3] = { 0xf6, 0x0d, 0x00 };
4963 static const u8 cs76
[2] = { 0xa3, 0xfb };
4964 static const u8 cs7b
[3] = { 0xc0, 0x11, 0x00 };
4965 static const u8 cs158
[8] = {
4966 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
4968 static const u8 cs160
[8] = {
4969 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
4971 static const u8 cs168
[8] = {
4972 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
4974 static const u8 cs128
[3 * 8] = {
4975 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
4976 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
4977 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
4979 static const u8 cs148
[2 * 8] = {
4980 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
4981 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4983 static const u8 cs31a
[8 * 4] = {
4984 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
4985 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
4986 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4987 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4989 static const u8 cs33a
[8 * 4] = {
4990 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4991 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4992 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4993 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4995 static const u8 cs45a
[8 * 2] = {
4996 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
4997 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4999 static const u8 cs170
[7 * 8] = {
5000 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5001 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5002 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
5003 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5004 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5005 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5006 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5008 static const u8 cs1a8
[3 * 8] = {
5009 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5010 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5011 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5013 static const u8 cs100
[2 * 8] = {
5014 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5015 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5019 reg
= inSISREG(SISVGAENABLE
) | 0x01;
5020 outSISREG(SISVGAENABLE
, reg
);
5023 reg
= inSISREG(SISMISCR
) | 0x01;
5024 outSISREG(SISMISCW
, reg
);
5027 outSISIDXREG(SISSR
, 0x05, 0x86);
5028 inSISIDXREG(SISSR
, 0x05, reg
);
5032 /* Clear some regs */
5033 for(i
= 0; i
< 0x22; i
++) {
5034 if(0x06 + i
== 0x20) continue;
5035 outSISIDXREG(SISSR
, 0x06 + i
, 0x00);
5037 for(i
= 0; i
< 0x0b; i
++) {
5038 outSISIDXREG(SISSR
, 0x31 + i
, 0x00);
5040 for(i
= 0; i
< 0x10; i
++) {
5041 outSISIDXREG(SISCR
, 0x30 + i
, 0x00);
5045 if(ivideo
->haveXGIROM
) {
5046 ptr
= (const u8
*)&bios
[0x78];
5048 for(i
= 0; i
< 3; i
++) {
5049 outSISIDXREG(SISSR
, 0x23 + i
, ptr
[i
]);
5053 if(ivideo
->haveXGIROM
) {
5054 ptr
= (const u8
*)&bios
[0x76];
5056 for(i
= 0; i
< 2; i
++) {
5057 outSISIDXREG(SISSR
, 0x21 + i
, ptr
[i
]);
5060 v1
= 0x18; v2
= 0x00;
5061 if(ivideo
->haveXGIROM
) {
5065 outSISIDXREG(SISSR
, 0x07, v1
);
5066 outSISIDXREG(SISSR
, 0x11, 0x0f);
5067 outSISIDXREG(SISSR
, 0x1f, v2
);
5068 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5069 outSISIDXREG(SISSR
, 0x20, 0x80 | 0x20 | 0x04);
5070 outSISIDXREG(SISSR
, 0x27, 0x74);
5073 if(ivideo
->haveXGIROM
) {
5074 ptr
= (const u8
*)&bios
[0x7b];
5076 for(i
= 0; i
< 3; i
++) {
5077 outSISIDXREG(SISSR
, 0x31 + i
, ptr
[i
]);
5080 if(ivideo
->chip
== XGI_40
) {
5081 if(ivideo
->revision_id
== 2) {
5082 setSISIDXREG(SISSR
, 0x3b, 0x3f, 0xc0);
5084 outSISIDXREG(SISCR
, 0x7d, 0xfe);
5085 outSISIDXREG(SISCR
, 0x7e, 0x0f);
5087 if(ivideo
->revision_id
== 0) { /* 40 *and* 20? */
5088 andSISIDXREG(SISCR
, 0x58, 0xd7);
5089 inSISIDXREG(SISCR
, 0xcb, reg
);
5091 setSISIDXREG(SISCR
, 0x58, 0xd7, (reg
& 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5095 reg
= (ivideo
->chip
== XGI_40
) ? 0x20 : 0x00;
5096 setSISIDXREG(SISCR
, 0x38, 0x1f, reg
);
5098 if(ivideo
->chip
== XGI_20
) {
5099 outSISIDXREG(SISSR
, 0x36, 0x70);
5101 outSISIDXREG(SISVID
, 0x00, 0x86);
5102 outSISIDXREG(SISVID
, 0x32, 0x00);
5103 outSISIDXREG(SISVID
, 0x30, 0x00);
5104 outSISIDXREG(SISVID
, 0x32, 0x01);
5105 outSISIDXREG(SISVID
, 0x30, 0x00);
5106 andSISIDXREG(SISVID
, 0x2f, 0xdf);
5107 andSISIDXREG(SISCAP
, 0x00, 0x3f);
5109 outSISIDXREG(SISPART1
, 0x2f, 0x01);
5110 outSISIDXREG(SISPART1
, 0x00, 0x00);
5111 outSISIDXREG(SISPART1
, 0x02, bios
[0x7e]);
5112 outSISIDXREG(SISPART1
, 0x2e, 0x08);
5113 andSISIDXREG(SISPART1
, 0x35, 0x7f);
5114 andSISIDXREG(SISPART1
, 0x50, 0xfe);
5116 inSISIDXREG(SISPART4
, 0x00, reg
);
5117 if(reg
== 1 || reg
== 2) {
5118 outSISIDXREG(SISPART2
, 0x00, 0x1c);
5119 outSISIDXREG(SISPART4
, 0x0d, bios
[0x7f]);
5120 outSISIDXREG(SISPART4
, 0x0e, bios
[0x80]);
5121 outSISIDXREG(SISPART4
, 0x10, bios
[0x81]);
5122 andSISIDXREG(SISPART4
, 0x0f, 0x3f);
5124 inSISIDXREG(SISPART4
, 0x01, reg
);
5125 if((reg
& 0xf0) >= 0xb0) {
5126 inSISIDXREG(SISPART4
, 0x23, reg
);
5127 if(reg
& 0x20) reg
|= 0x40;
5128 outSISIDXREG(SISPART4
, 0x23, reg
);
5129 reg
= (reg
& 0x20) ? 0x02 : 0x00;
5130 setSISIDXREG(SISPART1
, 0x1e, 0xfd, reg
);
5136 inSISIDXREG(SISSR
, 0x3b, reg
);
5138 inSISIDXREG(SISSR
, 0x3a, reg
);
5139 v2
= (reg
& 0x30) >> 3;
5140 if(!(v2
& 0x04)) v2
^= 0x02;
5141 inSISIDXREG(SISSR
, 0x39, reg
);
5142 if(reg
& 0x80) v2
|= 0x80;
5145 if((mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0730, NULL
))) {
5146 pci_dev_put(mypdev
);
5147 if(((v2
& 0x06) == 2) || ((v2
& 0x06) == 4))
5152 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0735, NULL
);
5154 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0645, NULL
);
5156 mypdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0650, NULL
);
5158 pci_read_config_dword(mypdev
, 0x94, ®d
);
5160 pci_write_config_dword(mypdev
, 0x94, regd
);
5162 pci_dev_put(mypdev
);
5163 } else if(sisfb_find_host_bridge(ivideo
, pdev
, PCI_VENDOR_ID_SI
)) {
5165 } else if(sisfb_find_host_bridge(ivideo
, pdev
, 0x1106) ||
5166 sisfb_find_host_bridge(ivideo
, pdev
, 0x1022) ||
5167 sisfb_find_host_bridge(ivideo
, pdev
, 0x700e) ||
5168 sisfb_find_host_bridge(ivideo
, pdev
, 0x10de)) {
5169 if((v2
& 0x06) == 4)
5174 setSISIDXREG(SISCR
, 0x5f, 0xf0, v2
);
5176 outSISIDXREG(SISSR
, 0x22, v1
);
5178 if(ivideo
->revision_id
== 2) {
5179 inSISIDXREG(SISSR
, 0x3b, v1
);
5180 inSISIDXREG(SISSR
, 0x3a, v2
);
5181 regd
= bios
[0x90 + 3] | (bios
[0x90 + 4] << 8);
5182 if( (!(v1
& 0x02)) && (v2
& 0x30) && (regd
< 0xcf) )
5183 setSISIDXREG(SISCR
, 0x5f, 0xf1, 0x01);
5185 if((mypdev
= pci_get_device(0x10de, 0x01e0, NULL
))) {
5186 /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5190 setSISIDXREG(SISCR
, 0x5f, 0xf1, 0x01);
5191 pci_dev_put(mypdev
);
5196 inSISIDXREG(SISSR
, 0x3b, reg
);
5197 inSISIDXREG(SISCR
, 0x5f, v2
);
5198 if((!(reg
& 0x02)) && (v2
& 0x0e))
5200 outSISIDXREG(SISSR
, 0x27, v1
);
5202 if(bios
[0x64] & 0x01) {
5203 setSISIDXREG(SISCR
, 0x5f, 0xf0, bios
[0x64]);
5207 pci_read_config_dword(pdev
, 0x50, ®d
);
5208 regd
= (regd
>> 20) & 0x0f;
5211 orSISIDXREG(SISCR
, 0x5f, 0x08);
5213 outSISIDXREG(SISCR
, 0x48, v1
);
5215 setSISIDXREG(SISCR
, 0x47, 0x04, bios
[0x4f6] & 0xfb);
5216 setSISIDXREG(SISCR
, 0x49, 0xf0, bios
[0x4f8] & 0x0f);
5217 setSISIDXREG(SISCR
, 0x4a, 0x60, bios
[0x4f9] & 0x9f);
5218 setSISIDXREG(SISCR
, 0x4b, 0x08, bios
[0x4fa] & 0xf7);
5219 setSISIDXREG(SISCR
, 0x4c, 0x80, bios
[0x4fb] & 0x7f);
5220 outSISIDXREG(SISCR
, 0x70, bios
[0x4fc]);
5221 setSISIDXREG(SISCR
, 0x71, 0xf0, bios
[0x4fd] & 0x0f);
5222 outSISIDXREG(SISCR
, 0x74, 0xd0);
5223 setSISIDXREG(SISCR
, 0x74, 0xcf, bios
[0x4fe] & 0x30);
5224 setSISIDXREG(SISCR
, 0x75, 0xe0, bios
[0x4ff] & 0x1f);
5225 setSISIDXREG(SISCR
, 0x76, 0xe0, bios
[0x500] & 0x1f);
5227 if((mypdev
= pci_get_device(0x8086, 0x2530, NULL
))) {
5229 pci_dev_put(mypdev
);
5231 outSISIDXREG(SISCR
, 0x77, v1
);
5239 if(ivideo
->haveXGIROM
) {
5240 v1
= bios
[0x140 + regb
];
5242 outSISIDXREG(SISCR
, 0x6d, v1
);
5245 if(ivideo
->haveXGIROM
) {
5246 ptr
= (const u8
*)&bios
[0x128];
5248 for(i
= 0, j
= 0; i
< 3; i
++, j
+= 8) {
5249 outSISIDXREG(SISCR
, 0x68 + i
, ptr
[j
+ regb
]);
5254 if(ivideo
->haveXGIROM
) {
5255 index
= (ivideo
->chip
== XGI_20
) ? 0x31a : 0x3a6;
5256 ptr
= (const u8
*)&bios
[index
];
5257 ptr2
= (const u8
*)&bios
[index
+ 0x20];
5259 for(i
= 0; i
< 2; i
++) {
5261 regd
= le32_to_cpu(((u32
*)ptr
)[regb
]);
5264 regd
= le32_to_cpu(((u32
*)ptr2
)[regb
]);
5268 for(j
= 0; j
< 16; j
++) {
5270 if(regd
& 0x01) reg
|= 0x04;
5271 if(regd
& 0x02) reg
|= 0x08;
5273 outSISIDXREG(SISCR
, rega
, reg
);
5274 inSISIDXREG(SISCR
, rega
, reg
);
5275 inSISIDXREG(SISCR
, rega
, reg
);
5280 andSISIDXREG(SISCR
, 0x6e, 0xfc);
5283 if(ivideo
->haveXGIROM
) {
5284 index
= (ivideo
->chip
== XGI_20
) ? 0x35a : 0x3e6;
5285 ptr
= (const u8
*)&bios
[index
];
5287 for(i
= 0; i
< 4; i
++) {
5288 setSISIDXREG(SISCR
, 0x6e, 0xfc, i
);
5290 for(j
= 0; j
< 2; j
++) {
5293 regd
= le32_to_cpu(((u32
*)ptr
)[regb
* 8]);
5297 for(k
= 0; k
< 16; k
++) {
5299 if(regd
& 0x01) reg
|= 0x01;
5300 if(regd
& 0x02) reg
|= 0x02;
5302 outSISIDXREG(SISCR
, 0x6f, reg
);
5303 inSISIDXREG(SISCR
, 0x6f, reg
);
5304 inSISIDXREG(SISCR
, 0x6f, reg
);
5311 if(ivideo
->haveXGIROM
) {
5312 ptr
= (const u8
*)&bios
[0x148];
5314 for(i
= 0, j
= 0; i
< 2; i
++, j
+= 8) {
5315 outSISIDXREG(SISCR
, 0x80 + i
, ptr
[j
+ regb
]);
5318 andSISIDXREG(SISCR
, 0x89, 0x8f);
5321 if(ivideo
->haveXGIROM
) {
5322 index
= (ivideo
->chip
== XGI_20
) ? 0x45a : 0x4e6;
5323 ptr
= (const u8
*)&bios
[index
];
5325 regd
= le16_to_cpu(((const u16
*)ptr
)[regb
]);
5327 for(i
= 0; i
< 5; i
++) {
5329 if(regd
& 0x01) reg
|= 0x01;
5330 if(regd
& 0x02) reg
|= 0x02;
5332 outSISIDXREG(SISCR
, 0x89, reg
);
5333 inSISIDXREG(SISCR
, 0x89, reg
);
5334 inSISIDXREG(SISCR
, 0x89, reg
);
5338 v1
= 0xb5; v2
= 0x20; v3
= 0xf0; v4
= 0x13;
5339 if(ivideo
->haveXGIROM
) {
5340 v1
= bios
[0x118 + regb
];
5341 v2
= bios
[0xf8 + regb
];
5342 v3
= bios
[0x120 + regb
];
5345 outSISIDXREG(SISCR
, 0x45, v1
& 0x0f);
5346 outSISIDXREG(SISCR
, 0x99, (v1
>> 4) & 0x07);
5347 orSISIDXREG(SISCR
, 0x40, v1
& 0x80);
5348 outSISIDXREG(SISCR
, 0x41, v2
);
5351 if(ivideo
->haveXGIROM
) {
5352 ptr
= (const u8
*)&bios
[0x170];
5354 for(i
= 0, j
= 0; i
< 7; i
++, j
+= 8) {
5355 outSISIDXREG(SISCR
, 0x90 + i
, ptr
[j
+ regb
]);
5358 outSISIDXREG(SISCR
, 0x59, v3
);
5361 if(ivideo
->haveXGIROM
) {
5362 ptr
= (const u8
*)&bios
[0x1a8];
5364 for(i
= 0, j
= 0; i
< 3; i
++, j
+= 8) {
5365 outSISIDXREG(SISCR
, 0xc3 + i
, ptr
[j
+ regb
]);
5369 if(ivideo
->haveXGIROM
) {
5370 ptr
= (const u8
*)&bios
[0x100];
5372 for(i
= 0, j
= 0; i
< 2; i
++, j
+= 8) {
5373 outSISIDXREG(SISCR
, 0x8a + i
, ptr
[j
+ regb
]);
5376 outSISIDXREG(SISCR
, 0xcf, v4
);
5378 outSISIDXREG(SISCR
, 0x83, 0x09);
5379 outSISIDXREG(SISCR
, 0x87, 0x00);
5381 if(ivideo
->chip
== XGI_40
) {
5382 if( (ivideo
->revision_id
== 1) ||
5383 (ivideo
->revision_id
== 2) ) {
5384 outSISIDXREG(SISCR
, 0x8c, 0x87);
5388 outSISIDXREG(SISSR
, 0x17, 0x00);
5389 outSISIDXREG(SISSR
, 0x1a, 0x87);
5391 if(ivideo
->chip
== XGI_20
) {
5392 outSISIDXREG(SISSR
, 0x15, 0x00);
5393 outSISIDXREG(SISSR
, 0x1c, 0x00);
5396 ramtype
= 0x00; v1
= 0x10;
5397 if(ivideo
->haveXGIROM
) {
5398 ramtype
= bios
[0x62];
5401 if(!(ramtype
& 0x80)) {
5402 if(ivideo
->chip
== XGI_20
) {
5403 outSISIDXREG(SISCR
, 0x97, v1
);
5404 inSISIDXREG(SISCR
, 0x97, reg
);
5406 ramtype
= (reg
& 0x01) << 1;
5409 inSISIDXREG(SISSR
, 0x39, reg
);
5410 ramtype
= reg
& 0x02;
5412 inSISIDXREG(SISSR
, 0x3a, reg
);
5413 ramtype
= (reg
>> 1) & 0x01;
5423 sisfb_post_xgi_setclocks(ivideo
, regb
);
5424 if((ivideo
->chip
== XGI_20
) ||
5425 (ivideo
->revision_id
== 1) ||
5426 (ivideo
->revision_id
== 2)) {
5427 v1
= cs158
[regb
]; v2
= cs160
[regb
]; v3
= cs168
[regb
];
5428 if(ivideo
->haveXGIROM
) {
5429 v1
= bios
[regb
+ 0x158];
5430 v2
= bios
[regb
+ 0x160];
5431 v3
= bios
[regb
+ 0x168];
5433 outSISIDXREG(SISCR
, 0x82, v1
);
5434 outSISIDXREG(SISCR
, 0x85, v2
);
5435 outSISIDXREG(SISCR
, 0x86, v3
);
5437 outSISIDXREG(SISCR
, 0x82, 0x88);
5438 outSISIDXREG(SISCR
, 0x86, 0x00);
5439 inSISIDXREG(SISCR
, 0x86, reg
);
5440 outSISIDXREG(SISCR
, 0x86, 0x88);
5441 inSISIDXREG(SISCR
, 0x86, reg
);
5442 outSISIDXREG(SISCR
, 0x86, bios
[regb
+ 0x168]);
5443 outSISIDXREG(SISCR
, 0x82, 0x77);
5444 outSISIDXREG(SISCR
, 0x85, 0x00);
5445 inSISIDXREG(SISCR
, 0x85, reg
);
5446 outSISIDXREG(SISCR
, 0x85, 0x88);
5447 inSISIDXREG(SISCR
, 0x85, reg
);
5448 outSISIDXREG(SISCR
, 0x85, bios
[regb
+ 0x160]);
5449 outSISIDXREG(SISCR
, 0x82, bios
[regb
+ 0x158]);
5451 if(ivideo
->chip
== XGI_40
) {
5452 outSISIDXREG(SISCR
, 0x97, 0x00);
5454 outSISIDXREG(SISCR
, 0x98, 0x01);
5455 outSISIDXREG(SISCR
, 0x9a, 0x02);
5457 outSISIDXREG(SISSR
, 0x18, 0x01);
5458 if((ivideo
->chip
== XGI_20
) ||
5459 (ivideo
->revision_id
== 2)) {
5460 outSISIDXREG(SISSR
, 0x19, 0x40);
5462 outSISIDXREG(SISSR
, 0x19, 0x20);
5464 outSISIDXREG(SISSR
, 0x16, 0x00);
5465 outSISIDXREG(SISSR
, 0x16, 0x80);
5466 if((ivideo
->chip
== XGI_20
) || (bios
[0x1cb] != 0x0c)) {
5467 sisfb_post_xgi_delay(ivideo
, 0x43);
5468 sisfb_post_xgi_delay(ivideo
, 0x43);
5469 sisfb_post_xgi_delay(ivideo
, 0x43);
5470 outSISIDXREG(SISSR
, 0x18, 0x00);
5471 if((ivideo
->chip
== XGI_20
) ||
5472 (ivideo
->revision_id
== 2)) {
5473 outSISIDXREG(SISSR
, 0x19, 0x40);
5475 outSISIDXREG(SISSR
, 0x19, 0x20);
5477 } else if((ivideo
->chip
== XGI_40
) && (bios
[0x1cb] == 0x0c)) {
5478 /* outSISIDXREG(SISSR, 0x16, 0x0c); */ /* ? */
5480 outSISIDXREG(SISSR
, 0x16, 0x00);
5481 outSISIDXREG(SISSR
, 0x16, 0x80);
5482 sisfb_post_xgi_delay(ivideo
, 4);
5483 v1
= 0x31; v2
= 0x03; v3
= 0x83; v4
= 0x03; v5
= 0x83;
5484 if(ivideo
->haveXGIROM
) {
5486 index
= (ivideo
->chip
== XGI_20
) ? 0x4b2 : 0x53e;
5488 v3
= bios
[index
+ 1];
5489 v4
= bios
[index
+ 2];
5490 v5
= bios
[index
+ 3];
5492 outSISIDXREG(SISSR
, 0x18, v1
);
5493 outSISIDXREG(SISSR
, 0x19, ((ivideo
->chip
== XGI_20
) ? 0x02 : 0x01));
5494 outSISIDXREG(SISSR
, 0x16, v2
);
5495 outSISIDXREG(SISSR
, 0x16, v3
);
5496 sisfb_post_xgi_delay(ivideo
, 0x43);
5497 outSISIDXREG(SISSR
, 0x1b, 0x03);
5498 sisfb_post_xgi_delay(ivideo
, 0x22);
5499 outSISIDXREG(SISSR
, 0x18, v1
);
5500 outSISIDXREG(SISSR
, 0x19, 0x00);
5501 outSISIDXREG(SISSR
, 0x16, v4
);
5502 outSISIDXREG(SISSR
, 0x16, v5
);
5503 outSISIDXREG(SISSR
, 0x1b, 0x00);
5506 outSISIDXREG(SISCR
, 0x82, 0x77);
5507 outSISIDXREG(SISCR
, 0x86, 0x00);
5508 inSISIDXREG(SISCR
, 0x86, reg
);
5509 outSISIDXREG(SISCR
, 0x86, 0x88);
5510 inSISIDXREG(SISCR
, 0x86, reg
);
5511 v1
= cs168
[regb
]; v2
= cs160
[regb
]; v3
= cs158
[regb
];
5512 if(ivideo
->haveXGIROM
) {
5513 v1
= bios
[regb
+ 0x168];
5514 v2
= bios
[regb
+ 0x160];
5515 v3
= bios
[regb
+ 0x158];
5517 outSISIDXREG(SISCR
, 0x86, v1
);
5518 outSISIDXREG(SISCR
, 0x82, 0x77);
5519 outSISIDXREG(SISCR
, 0x85, 0x00);
5520 inSISIDXREG(SISCR
, 0x85, reg
);
5521 outSISIDXREG(SISCR
, 0x85, 0x88);
5522 inSISIDXREG(SISCR
, 0x85, reg
);
5523 outSISIDXREG(SISCR
, 0x85, v2
);
5524 outSISIDXREG(SISCR
, 0x82, v3
);
5525 outSISIDXREG(SISCR
, 0x98, 0x01);
5526 outSISIDXREG(SISCR
, 0x9a, 0x02);
5528 outSISIDXREG(SISSR
, 0x28, 0x64);
5529 outSISIDXREG(SISSR
, 0x29, 0x63);
5530 sisfb_post_xgi_delay(ivideo
, 15);
5531 outSISIDXREG(SISSR
, 0x18, 0x00);
5532 outSISIDXREG(SISSR
, 0x19, 0x20);
5533 outSISIDXREG(SISSR
, 0x16, 0x00);
5534 outSISIDXREG(SISSR
, 0x16, 0x80);
5535 outSISIDXREG(SISSR
, 0x18, 0xc5);
5536 outSISIDXREG(SISSR
, 0x19, 0x23);
5537 outSISIDXREG(SISSR
, 0x16, 0x00);
5538 outSISIDXREG(SISSR
, 0x16, 0x80);
5539 sisfb_post_xgi_delay(ivideo
, 1);
5540 outSISIDXREG(SISCR
, 0x97,0x11);
5541 sisfb_post_xgi_setclocks(ivideo
, regb
);
5542 sisfb_post_xgi_delay(ivideo
, 0x46);
5543 outSISIDXREG(SISSR
, 0x18, 0xc5);
5544 outSISIDXREG(SISSR
, 0x19, 0x23);
5545 outSISIDXREG(SISSR
, 0x16, 0x00);
5546 outSISIDXREG(SISSR
, 0x16, 0x80);
5547 sisfb_post_xgi_delay(ivideo
, 1);
5548 outSISIDXREG(SISSR
, 0x1b, 0x04);
5549 sisfb_post_xgi_delay(ivideo
, 1);
5550 outSISIDXREG(SISSR
, 0x1b, 0x00);
5551 sisfb_post_xgi_delay(ivideo
, 1);
5553 if(ivideo
->haveXGIROM
) {
5556 outSISIDXREG(SISSR
, 0x18, v1
);
5557 outSISIDXREG(SISSR
, 0x19, 0x06);
5558 outSISIDXREG(SISSR
, 0x16, 0x04);
5559 outSISIDXREG(SISSR
, 0x16, 0x84);
5560 sisfb_post_xgi_delay(ivideo
, 1);
5563 sisfb_post_xgi_setclocks(ivideo
, regb
);
5564 if((ivideo
->chip
== XGI_40
) &&
5565 ((ivideo
->revision_id
== 1) ||
5566 (ivideo
->revision_id
== 2))) {
5567 outSISIDXREG(SISCR
, 0x82, bios
[regb
+ 0x158]);
5568 outSISIDXREG(SISCR
, 0x85, bios
[regb
+ 0x160]);
5569 outSISIDXREG(SISCR
, 0x86, bios
[regb
+ 0x168]);
5571 outSISIDXREG(SISCR
, 0x82, 0x88);
5572 outSISIDXREG(SISCR
, 0x86, 0x00);
5573 inSISIDXREG(SISCR
, 0x86, reg
);
5574 outSISIDXREG(SISCR
, 0x86, 0x88);
5575 outSISIDXREG(SISCR
, 0x82, 0x77);
5576 outSISIDXREG(SISCR
, 0x85, 0x00);
5577 inSISIDXREG(SISCR
, 0x85, reg
);
5578 outSISIDXREG(SISCR
, 0x85, 0x88);
5579 inSISIDXREG(SISCR
, 0x85, reg
);
5580 v1
= cs160
[regb
]; v2
= cs158
[regb
];
5581 if(ivideo
->haveXGIROM
) {
5582 v1
= bios
[regb
+ 0x160];
5583 v2
= bios
[regb
+ 0x158];
5585 outSISIDXREG(SISCR
, 0x85, v1
);
5586 outSISIDXREG(SISCR
, 0x82, v2
);
5588 if(ivideo
->chip
== XGI_40
) {
5589 outSISIDXREG(SISCR
, 0x97, 0x11);
5591 if((ivideo
->chip
== XGI_40
) && (ivideo
->revision_id
== 2)) {
5592 outSISIDXREG(SISCR
, 0x98, 0x01);
5594 outSISIDXREG(SISCR
, 0x98, 0x03);
5596 outSISIDXREG(SISCR
, 0x9a, 0x02);
5598 if(ivideo
->chip
== XGI_40
) {
5599 outSISIDXREG(SISSR
, 0x18, 0x01);
5601 outSISIDXREG(SISSR
, 0x18, 0x00);
5603 outSISIDXREG(SISSR
, 0x19, 0x40);
5604 outSISIDXREG(SISSR
, 0x16, 0x00);
5605 outSISIDXREG(SISSR
, 0x16, 0x80);
5606 if((ivideo
->chip
== XGI_40
) && (bios
[0x1cb] != 0x0c)) {
5607 sisfb_post_xgi_delay(ivideo
, 0x43);
5608 sisfb_post_xgi_delay(ivideo
, 0x43);
5609 sisfb_post_xgi_delay(ivideo
, 0x43);
5610 outSISIDXREG(SISSR
, 0x18, 0x00);
5611 outSISIDXREG(SISSR
, 0x19, 0x40);
5612 outSISIDXREG(SISSR
, 0x16, 0x00);
5613 outSISIDXREG(SISSR
, 0x16, 0x80);
5615 sisfb_post_xgi_delay(ivideo
, 4);
5617 if(ivideo
->haveXGIROM
) {
5620 outSISIDXREG(SISSR
, 0x18, v1
);
5621 outSISIDXREG(SISSR
, 0x19, 0x01);
5622 if(ivideo
->chip
== XGI_40
) {
5623 outSISIDXREG(SISSR
, 0x16, bios
[0x53e]);
5624 outSISIDXREG(SISSR
, 0x16, bios
[0x53f]);
5626 outSISIDXREG(SISSR
, 0x16, 0x05);
5627 outSISIDXREG(SISSR
, 0x16, 0x85);
5629 sisfb_post_xgi_delay(ivideo
, 0x43);
5630 if(ivideo
->chip
== XGI_40
) {
5631 outSISIDXREG(SISSR
, 0x1b, 0x01);
5633 outSISIDXREG(SISSR
, 0x1b, 0x03);
5635 sisfb_post_xgi_delay(ivideo
, 0x22);
5636 outSISIDXREG(SISSR
, 0x18, v1
);
5637 outSISIDXREG(SISSR
, 0x19, 0x00);
5638 if(ivideo
->chip
== XGI_40
) {
5639 outSISIDXREG(SISSR
, 0x16, bios
[0x540]);
5640 outSISIDXREG(SISSR
, 0x16, bios
[0x541]);
5642 outSISIDXREG(SISSR
, 0x16, 0x05);
5643 outSISIDXREG(SISSR
, 0x16, 0x85);
5645 outSISIDXREG(SISSR
, 0x1b, 0x00);
5650 if(ivideo
->haveXGIROM
) {
5651 v1
= bios
[0x110 + regb
];
5653 outSISIDXREG(SISSR
, 0x1b, v1
);
5656 v1
= 0x00; v2
= 0x00;
5657 if(ivideo
->haveXGIROM
) {
5663 if((v1
& 0x40) && (v2
& regd
) && ivideo
->haveXGIROM
) {
5665 outSISIDXREG(SISSR
, 0x13, bios
[regb
+ 0xe0]);
5666 outSISIDXREG(SISSR
, 0x14, bios
[regb
+ 0xe0 + 8]);
5670 /* Set default mode, don't clear screen */
5671 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
5672 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
5673 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
5674 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
5675 ivideo
->SiS_Pr
.VideoMemorySize
= 8 << 20;
5676 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
5678 outSISIDXREG(SISSR
, 0x05, 0x86);
5680 /* Disable read-cache */
5681 andSISIDXREG(SISSR
, 0x21, 0xdf);
5682 sisfb_post_xgi_ramsize(ivideo
);
5683 /* Enable read-cache */
5684 orSISIDXREG(SISSR
, 0x21, 0x20);
5689 printk(KERN_DEBUG
"-----------------\n");
5690 for(i
= 0; i
< 0xff; i
++) {
5691 inSISIDXREG(SISCR
, i
, reg
);
5692 printk(KERN_DEBUG
"CR%02x(%x) = 0x%02x\n", i
, SISCR
, reg
);
5694 for(i
= 0; i
< 0x40; i
++) {
5695 inSISIDXREG(SISSR
, i
, reg
);
5696 printk(KERN_DEBUG
"SR%02x(%x) = 0x%02x\n", i
, SISSR
, reg
);
5698 printk(KERN_DEBUG
"-----------------\n");
5702 if(ivideo
->chip
== XGI_20
) {
5703 orSISIDXREG(SISCR
, 0x32, 0x20);
5705 inSISIDXREG(SISPART4
, 0x00, reg
);
5706 if((reg
== 1) || (reg
== 2)) {
5707 sisfb_sense_crt1(ivideo
);
5709 orSISIDXREG(SISCR
, 0x32, 0x20);
5713 /* Set default mode, don't clear screen */
5714 ivideo
->SiS_Pr
.SiS_UseOEM
= false;
5715 SiS_SetEnableDstn(&ivideo
->SiS_Pr
, false);
5716 SiS_SetEnableFstn(&ivideo
->SiS_Pr
, false);
5717 ivideo
->curFSTN
= ivideo
->curDSTN
= 0;
5718 SiSSetMode(&ivideo
->SiS_Pr
, 0x2e | 0x80);
5720 outSISIDXREG(SISSR
, 0x05, 0x86);
5723 orSISIDXREG(SISSR
, 0x01, 0x20);
5725 /* Save mode number in CR34 */
5726 outSISIDXREG(SISCR
, 0x34, 0x2e);
5728 /* Let everyone know what the current mode is */
5729 ivideo
->modeprechange
= 0x2e;
5731 if(ivideo
->chip
== XGI_40
) {
5732 inSISIDXREG(SISCR
, 0xca, reg
);
5733 inSISIDXREG(SISCR
, 0xcc, v1
);
5734 if((reg
& 0x10) && (!(v1
& 0x04))) {
5736 "sisfb: Please connect power to the card.\n");
5745 static int __devinit
5746 sisfb_probe(struct pci_dev
*pdev
, const struct pci_device_id
*ent
)
5748 struct sisfb_chip_info
*chipinfo
= &sisfb_chip_info
[ent
->driver_data
];
5749 struct sis_video_info
*ivideo
= NULL
;
5750 struct fb_info
*sis_fb_info
= NULL
;
5758 sis_fb_info
= framebuffer_alloc(sizeof(*ivideo
), &pdev
->dev
);
5762 ivideo
= (struct sis_video_info
*)sis_fb_info
->par
;
5763 ivideo
->memyselfandi
= sis_fb_info
;
5765 ivideo
->sisfb_id
= SISFB_ID
;
5767 if(card_list
== NULL
) {
5768 ivideo
->cardnumber
= 0;
5770 struct sis_video_info
*countvideo
= card_list
;
5771 ivideo
->cardnumber
= 1;
5772 while((countvideo
= countvideo
->next
) != NULL
)
5773 ivideo
->cardnumber
++;
5776 strncpy(ivideo
->myid
, chipinfo
->chip_name
, 30);
5778 ivideo
->warncount
= 0;
5779 ivideo
->chip_id
= pdev
->device
;
5780 ivideo
->chip_vendor
= pdev
->vendor
;
5781 ivideo
->revision_id
= pdev
->revision
;
5782 ivideo
->SiS_Pr
.ChipRevision
= ivideo
->revision_id
;
5783 pci_read_config_word(pdev
, PCI_COMMAND
, ®16
);
5784 ivideo
->sisvga_enabled
= reg16
& 0x01;
5785 ivideo
->pcibus
= pdev
->bus
->number
;
5786 ivideo
->pcislot
= PCI_SLOT(pdev
->devfn
);
5787 ivideo
->pcifunc
= PCI_FUNC(pdev
->devfn
);
5788 ivideo
->subsysvendor
= pdev
->subsystem_vendor
;
5789 ivideo
->subsysdevice
= pdev
->subsystem_device
;
5792 if(sisfb_mode_idx
== -1) {
5793 sisfb_get_vga_mode_from_kernel();
5797 ivideo
->chip
= chipinfo
->chip
;
5798 ivideo
->sisvga_engine
= chipinfo
->vgaengine
;
5799 ivideo
->hwcursor_size
= chipinfo
->hwcursor_size
;
5800 ivideo
->CRT2_write_enable
= chipinfo
->CRT2_write_enable
;
5801 ivideo
->mni
= chipinfo
->mni
;
5803 ivideo
->detectedpdc
= 0xff;
5804 ivideo
->detectedpdca
= 0xff;
5805 ivideo
->detectedlcda
= 0xff;
5807 ivideo
->sisfb_thismonitor
.datavalid
= false;
5809 ivideo
->current_base
= 0;
5811 ivideo
->engineok
= 0;
5813 ivideo
->sisfb_was_boot_device
= 0;
5815 if(pdev
->resource
[PCI_ROM_RESOURCE
].flags
& IORESOURCE_ROM_SHADOW
) {
5816 if(ivideo
->sisvga_enabled
)
5817 ivideo
->sisfb_was_boot_device
= 1;
5819 printk(KERN_DEBUG
"sisfb: PCI device is disabled, "
5820 "but marked as boot video device ???\n");
5821 printk(KERN_DEBUG
"sisfb: I will not accept this "
5822 "as the primary VGA device\n");
5826 ivideo
->sisfb_parm_mem
= sisfb_parm_mem
;
5827 ivideo
->sisfb_accel
= sisfb_accel
;
5828 ivideo
->sisfb_ypan
= sisfb_ypan
;
5829 ivideo
->sisfb_max
= sisfb_max
;
5830 ivideo
->sisfb_userom
= sisfb_userom
;
5831 ivideo
->sisfb_useoem
= sisfb_useoem
;
5832 ivideo
->sisfb_mode_idx
= sisfb_mode_idx
;
5833 ivideo
->sisfb_parm_rate
= sisfb_parm_rate
;
5834 ivideo
->sisfb_crt1off
= sisfb_crt1off
;
5835 ivideo
->sisfb_forcecrt1
= sisfb_forcecrt1
;
5836 ivideo
->sisfb_crt2type
= sisfb_crt2type
;
5837 ivideo
->sisfb_crt2flags
= sisfb_crt2flags
;
5838 /* pdc(a), scalelcd, special timing, lvdshl handled below */
5839 ivideo
->sisfb_dstn
= sisfb_dstn
;
5840 ivideo
->sisfb_fstn
= sisfb_fstn
;
5841 ivideo
->sisfb_tvplug
= sisfb_tvplug
;
5842 ivideo
->sisfb_tvstd
= sisfb_tvstd
;
5843 ivideo
->tvxpos
= sisfb_tvxposoffset
;
5844 ivideo
->tvypos
= sisfb_tvyposoffset
;
5845 ivideo
->sisfb_nocrt2rate
= sisfb_nocrt2rate
;
5846 ivideo
->refresh_rate
= 0;
5847 if(ivideo
->sisfb_parm_rate
!= -1) {
5848 ivideo
->refresh_rate
= ivideo
->sisfb_parm_rate
;
5851 ivideo
->SiS_Pr
.UsePanelScaler
= sisfb_scalelcd
;
5852 ivideo
->SiS_Pr
.CenterScreen
= -1;
5853 ivideo
->SiS_Pr
.SiS_CustomT
= sisfb_specialtiming
;
5854 ivideo
->SiS_Pr
.LVDSHL
= sisfb_lvdshl
;
5856 ivideo
->SiS_Pr
.SiS_Backup70xx
= 0xff;
5857 ivideo
->SiS_Pr
.SiS_CHOverScan
= -1;
5858 ivideo
->SiS_Pr
.SiS_ChSW
= false;
5859 ivideo
->SiS_Pr
.SiS_UseLCDA
= false;
5860 ivideo
->SiS_Pr
.HaveEMI
= false;
5861 ivideo
->SiS_Pr
.HaveEMILCD
= false;
5862 ivideo
->SiS_Pr
.OverruleEMI
= false;
5863 ivideo
->SiS_Pr
.SiS_SensibleSR11
= false;
5864 ivideo
->SiS_Pr
.SiS_MyCR63
= 0x63;
5865 ivideo
->SiS_Pr
.PDC
= -1;
5866 ivideo
->SiS_Pr
.PDCA
= -1;
5867 ivideo
->SiS_Pr
.DDCPortMixup
= false;
5868 #ifdef CONFIG_FB_SIS_315
5869 if(ivideo
->chip
>= SIS_330
) {
5870 ivideo
->SiS_Pr
.SiS_MyCR63
= 0x53;
5871 if(ivideo
->chip
>= SIS_661
) {
5872 ivideo
->SiS_Pr
.SiS_SensibleSR11
= true;
5877 memcpy(&ivideo
->default_var
, &my_default_var
, sizeof(my_default_var
));
5879 pci_set_drvdata(pdev
, ivideo
);
5881 /* Patch special cases */
5882 if((ivideo
->nbridge
= sisfb_get_northbridge(ivideo
->chip
))) {
5883 switch(ivideo
->nbridge
->device
) {
5884 #ifdef CONFIG_FB_SIS_300
5885 case PCI_DEVICE_ID_SI_730
:
5886 ivideo
->chip
= SIS_730
;
5887 strcpy(ivideo
->myid
, "SiS 730");
5890 #ifdef CONFIG_FB_SIS_315
5891 case PCI_DEVICE_ID_SI_651
:
5892 /* ivideo->chip is ok */
5893 strcpy(ivideo
->myid
, "SiS 651");
5895 case PCI_DEVICE_ID_SI_740
:
5896 ivideo
->chip
= SIS_740
;
5897 strcpy(ivideo
->myid
, "SiS 740");
5899 case PCI_DEVICE_ID_SI_661
:
5900 ivideo
->chip
= SIS_661
;
5901 strcpy(ivideo
->myid
, "SiS 661");
5903 case PCI_DEVICE_ID_SI_741
:
5904 ivideo
->chip
= SIS_741
;
5905 strcpy(ivideo
->myid
, "SiS 741");
5907 case PCI_DEVICE_ID_SI_760
:
5908 ivideo
->chip
= SIS_760
;
5909 strcpy(ivideo
->myid
, "SiS 760");
5911 case PCI_DEVICE_ID_SI_761
:
5912 ivideo
->chip
= SIS_761
;
5913 strcpy(ivideo
->myid
, "SiS 761");
5921 ivideo
->SiS_Pr
.ChipType
= ivideo
->chip
;
5923 ivideo
->SiS_Pr
.ivideo
= (void *)ivideo
;
5925 #ifdef CONFIG_FB_SIS_315
5926 if((ivideo
->SiS_Pr
.ChipType
== SIS_315PRO
) ||
5927 (ivideo
->SiS_Pr
.ChipType
== SIS_315
)) {
5928 ivideo
->SiS_Pr
.ChipType
= SIS_315H
;
5932 if(!ivideo
->sisvga_enabled
) {
5933 if(pci_enable_device(pdev
)) {
5934 if(ivideo
->nbridge
) pci_dev_put(ivideo
->nbridge
);
5935 pci_set_drvdata(pdev
, NULL
);
5936 framebuffer_release(sis_fb_info
);
5941 ivideo
->video_base
= pci_resource_start(pdev
, 0);
5942 ivideo
->mmio_base
= pci_resource_start(pdev
, 1);
5943 ivideo
->mmio_size
= pci_resource_len(pdev
, 1);
5944 ivideo
->SiS_Pr
.RelIO
= pci_resource_start(pdev
, 2) + 0x30;
5945 ivideo
->SiS_Pr
.IOAddress
= ivideo
->vga_base
= ivideo
->SiS_Pr
.RelIO
;
5947 SiSRegInit(&ivideo
->SiS_Pr
, ivideo
->SiS_Pr
.IOAddress
);
5949 #ifdef CONFIG_FB_SIS_300
5950 /* Find PCI systems for Chrontel/GPIO communication setup */
5951 if(ivideo
->chip
== SIS_630
) {
5954 if(mychswtable
[i
].subsysVendor
== ivideo
->subsysvendor
&&
5955 mychswtable
[i
].subsysCard
== ivideo
->subsysdevice
) {
5956 ivideo
->SiS_Pr
.SiS_ChSW
= true;
5957 printk(KERN_DEBUG
"sisfb: Identified [%s %s] "
5958 "requiring Chrontel/GPIO setup\n",
5959 mychswtable
[i
].vendorName
,
5960 mychswtable
[i
].cardName
);
5961 ivideo
->lpcdev
= pci_get_device(PCI_VENDOR_ID_SI
, 0x0008, NULL
);
5965 } while(mychswtable
[i
].subsysVendor
!= 0);
5969 #ifdef CONFIG_FB_SIS_315
5970 if((ivideo
->chip
== SIS_760
) && (ivideo
->nbridge
)) {
5971 ivideo
->lpcdev
= pci_get_slot(ivideo
->nbridge
->bus
, (2 << 3));
5975 outSISIDXREG(SISSR
, 0x05, 0x86);
5977 if( (!ivideo
->sisvga_enabled
)
5978 #if !defined(__i386__) && !defined(__x86_64__)
5979 || (sisfb_resetcard
)
5982 for(i
= 0x30; i
<= 0x3f; i
++) {
5983 outSISIDXREG(SISCR
, i
, 0x00);
5987 /* Find out about current video mode */
5988 ivideo
->modeprechange
= 0x03;
5989 inSISIDXREG(SISCR
, 0x34, reg
);
5991 ivideo
->modeprechange
= reg
& 0x7f;
5992 } else if(ivideo
->sisvga_enabled
) {
5993 #if defined(__i386__) || defined(__x86_64__)
5994 unsigned char __iomem
*tt
= ioremap(0x400, 0x100);
5996 ivideo
->modeprechange
= readb(tt
+ 0x49);
6002 /* Search and copy ROM image */
6003 ivideo
->bios_abase
= NULL
;
6004 ivideo
->SiS_Pr
.VirtualRomBase
= NULL
;
6005 ivideo
->SiS_Pr
.UseROM
= false;
6006 ivideo
->haveXGIROM
= ivideo
->SiS_Pr
.SiS_XGIROM
= false;
6007 if(ivideo
->sisfb_userom
) {
6008 ivideo
->SiS_Pr
.VirtualRomBase
= sisfb_find_rom(pdev
);
6009 ivideo
->bios_abase
= ivideo
->SiS_Pr
.VirtualRomBase
;
6010 ivideo
->SiS_Pr
.UseROM
= (bool)(ivideo
->SiS_Pr
.VirtualRomBase
);
6011 printk(KERN_INFO
"sisfb: Video ROM %sfound\n",
6012 ivideo
->SiS_Pr
.UseROM
? "" : "not ");
6013 if((ivideo
->SiS_Pr
.UseROM
) && (ivideo
->chip
>= XGI_20
)) {
6014 ivideo
->SiS_Pr
.UseROM
= false;
6015 ivideo
->haveXGIROM
= ivideo
->SiS_Pr
.SiS_XGIROM
= true;
6016 if( (ivideo
->revision_id
== 2) &&
6017 (!(ivideo
->bios_abase
[0x1d1] & 0x01)) ) {
6018 ivideo
->SiS_Pr
.DDCPortMixup
= true;
6022 printk(KERN_INFO
"sisfb: Video ROM usage disabled\n");
6025 /* Find systems for special custom timing */
6026 if(ivideo
->SiS_Pr
.SiS_CustomT
== CUT_NONE
) {
6027 sisfb_detect_custom_timing(ivideo
);
6030 /* POST card in case this has not been done by the BIOS */
6031 if( (!ivideo
->sisvga_enabled
)
6032 #if !defined(__i386__) && !defined(__x86_64__)
6033 || (sisfb_resetcard
)
6036 #ifdef CONFIG_FB_SIS_300
6037 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
6038 if(ivideo
->chip
== SIS_300
) {
6039 sisfb_post_sis300(pdev
);
6040 ivideo
->sisfb_can_post
= 1;
6045 #ifdef CONFIG_FB_SIS_315
6046 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
6048 /* if((ivideo->chip == SIS_315H) ||
6049 (ivideo->chip == SIS_315) ||
6050 (ivideo->chip == SIS_315PRO) ||
6051 (ivideo->chip == SIS_330)) {
6052 sisfb_post_sis315330(pdev);
6053 } else */ if(ivideo
->chip
== XGI_20
) {
6054 result
= sisfb_post_xgi(pdev
);
6055 ivideo
->sisfb_can_post
= 1;
6056 } else if((ivideo
->chip
== XGI_40
) && ivideo
->haveXGIROM
) {
6057 result
= sisfb_post_xgi(pdev
);
6058 ivideo
->sisfb_can_post
= 1;
6060 printk(KERN_INFO
"sisfb: Card is not "
6061 "POSTed and sisfb can't do this either.\n");
6064 printk(KERN_ERR
"sisfb: Failed to POST card\n");
6072 ivideo
->sisfb_card_posted
= 1;
6074 /* Find out about RAM size */
6075 if(sisfb_get_dram_size(ivideo
)) {
6076 printk(KERN_INFO
"sisfb: Fatal error: Unable to determine VRAM size.\n");
6082 /* Enable PCI addressing and MMIO */
6083 if((ivideo
->sisfb_mode_idx
< 0) ||
6084 ((sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
]) != 0xFF)) {
6085 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
6086 orSISIDXREG(SISSR
, IND_SIS_PCI_ADDRESS_SET
, (SIS_PCI_ADDR_ENABLE
| SIS_MEM_MAP_IO_ENABLE
));
6087 /* Enable 2D accelerator engine */
6088 orSISIDXREG(SISSR
, IND_SIS_MODULE_ENABLE
, SIS_ENABLE_2D
);
6091 if(sisfb_pdc
!= 0xff) {
6092 if(ivideo
->sisvga_engine
== SIS_300_VGA
)
6096 ivideo
->SiS_Pr
.PDC
= sisfb_pdc
;
6098 #ifdef CONFIG_FB_SIS_315
6099 if(ivideo
->sisvga_engine
== SIS_315_VGA
) {
6100 if(sisfb_pdca
!= 0xff)
6101 ivideo
->SiS_Pr
.PDCA
= sisfb_pdca
& 0x1f;
6105 if(!request_mem_region(ivideo
->video_base
, ivideo
->video_size
, "sisfb FB")) {
6106 printk(KERN_ERR
"sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6107 (int)(ivideo
->video_size
>> 20));
6108 printk(KERN_ERR
"sisfb: Is there another framebuffer driver active?\n");
6113 if(!request_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
, "sisfb MMIO")) {
6114 printk(KERN_ERR
"sisfb: Fatal error: Unable to reserve MMIO region\n");
6119 ivideo
->video_vbase
= ioremap(ivideo
->video_base
, ivideo
->video_size
);
6120 ivideo
->SiS_Pr
.VideoMemoryAddress
= ivideo
->video_vbase
;
6121 if(!ivideo
->video_vbase
) {
6122 printk(KERN_ERR
"sisfb: Fatal error: Unable to map framebuffer memory\n");
6127 ivideo
->mmio_vbase
= ioremap(ivideo
->mmio_base
, ivideo
->mmio_size
);
6128 if(!ivideo
->mmio_vbase
) {
6129 printk(KERN_ERR
"sisfb: Fatal error: Unable to map MMIO region\n");
6131 error_0
: iounmap(ivideo
->video_vbase
);
6132 error_1
: release_mem_region(ivideo
->video_base
, ivideo
->video_size
);
6133 error_2
: release_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
);
6134 error_3
: vfree(ivideo
->bios_abase
);
6136 pci_dev_put(ivideo
->lpcdev
);
6138 pci_dev_put(ivideo
->nbridge
);
6139 pci_set_drvdata(pdev
, NULL
);
6140 if(!ivideo
->sisvga_enabled
)
6141 pci_disable_device(pdev
);
6142 framebuffer_release(sis_fb_info
);
6146 printk(KERN_INFO
"sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
6147 ivideo
->video_base
, (unsigned long)ivideo
->video_vbase
, ivideo
->video_size
/ 1024);
6149 if(ivideo
->video_offset
) {
6150 printk(KERN_INFO
"sisfb: Viewport offset %ldk\n",
6151 ivideo
->video_offset
/ 1024);
6154 printk(KERN_INFO
"sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
6155 ivideo
->mmio_base
, (unsigned long)ivideo
->mmio_vbase
, ivideo
->mmio_size
/ 1024);
6158 /* Determine the size of the command queue */
6159 if(ivideo
->sisvga_engine
== SIS_300_VGA
) {
6160 ivideo
->cmdQueueSize
= TURBO_QUEUE_AREA_SIZE
;
6162 if(ivideo
->chip
== XGI_20
) {
6163 ivideo
->cmdQueueSize
= COMMAND_QUEUE_AREA_SIZE_Z7
;
6165 ivideo
->cmdQueueSize
= COMMAND_QUEUE_AREA_SIZE
;
6169 /* Engines are no longer initialized here; this is
6170 * now done after the first mode-switch (if the
6171 * submitted var has its acceleration flags set).
6174 /* Calculate the base of the (unused) hw cursor */
6175 ivideo
->hwcursor_vbase
= ivideo
->video_vbase
6176 + ivideo
->video_size
6177 - ivideo
->cmdQueueSize
6178 - ivideo
->hwcursor_size
;
6179 ivideo
->caps
|= HW_CURSOR_CAP
;
6181 /* Initialize offscreen memory manager */
6182 if((ivideo
->havenoheap
= sisfb_heap_init(ivideo
))) {
6183 printk(KERN_WARNING
"sisfb: Failed to initialize offscreen memory heap\n");
6186 /* Used for clearing the screen only, therefore respect our mem limit */
6187 ivideo
->SiS_Pr
.VideoMemoryAddress
+= ivideo
->video_offset
;
6188 ivideo
->SiS_Pr
.VideoMemorySize
= ivideo
->sisfb_mem
;
6192 ivideo
->vbflags
= 0;
6193 ivideo
->lcddefmodeidx
= DEFAULT_LCDMODE
;
6194 ivideo
->tvdefmodeidx
= DEFAULT_TVMODE
;
6195 ivideo
->defmodeidx
= DEFAULT_MODE
;
6198 if(ivideo
->chip
< XGI_20
) {
6199 if(ivideo
->bios_abase
) {
6200 ivideo
->newrom
= SiSDetermineROMLayout661(&ivideo
->SiS_Pr
);
6204 if((ivideo
->sisfb_mode_idx
< 0) ||
6205 ((sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
]) != 0xFF)) {
6207 sisfb_sense_crt1(ivideo
);
6209 sisfb_get_VB_type(ivideo
);
6211 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
6212 sisfb_detect_VB_connect(ivideo
);
6215 ivideo
->currentvbflags
= ivideo
->vbflags
& (VB_VIDEOBRIDGE
| TV_STANDARD
);
6217 /* Decide on which CRT2 device to use */
6218 if(ivideo
->vbflags2
& VB2_VIDEOBRIDGE
) {
6219 if(ivideo
->sisfb_crt2type
!= -1) {
6220 if((ivideo
->sisfb_crt2type
== CRT2_LCD
) &&
6221 (ivideo
->vbflags
& CRT2_LCD
)) {
6222 ivideo
->currentvbflags
|= CRT2_LCD
;
6223 } else if(ivideo
->sisfb_crt2type
!= CRT2_LCD
) {
6224 ivideo
->currentvbflags
|= ivideo
->sisfb_crt2type
;
6227 /* Chrontel 700x TV detection often unreliable, therefore
6228 * use a different default order on such machines
6230 if((ivideo
->sisvga_engine
== SIS_300_VGA
) &&
6231 (ivideo
->vbflags2
& VB2_CHRONTEL
)) {
6232 if(ivideo
->vbflags
& CRT2_LCD
)
6233 ivideo
->currentvbflags
|= CRT2_LCD
;
6234 else if(ivideo
->vbflags
& CRT2_TV
)
6235 ivideo
->currentvbflags
|= CRT2_TV
;
6236 else if(ivideo
->vbflags
& CRT2_VGA
)
6237 ivideo
->currentvbflags
|= CRT2_VGA
;
6239 if(ivideo
->vbflags
& CRT2_TV
)
6240 ivideo
->currentvbflags
|= CRT2_TV
;
6241 else if(ivideo
->vbflags
& CRT2_LCD
)
6242 ivideo
->currentvbflags
|= CRT2_LCD
;
6243 else if(ivideo
->vbflags
& CRT2_VGA
)
6244 ivideo
->currentvbflags
|= CRT2_VGA
;
6249 if(ivideo
->vbflags
& CRT2_LCD
) {
6250 sisfb_detect_lcd_type(ivideo
);
6253 sisfb_save_pdc_emi(ivideo
);
6255 if(!ivideo
->sisfb_crt1off
) {
6256 sisfb_handle_ddc(ivideo
, &ivideo
->sisfb_thismonitor
, 0);
6258 if((ivideo
->vbflags2
& VB2_SISTMDSBRIDGE
) &&
6259 (ivideo
->vbflags
& (CRT2_VGA
| CRT2_LCD
))) {
6260 sisfb_handle_ddc(ivideo
, &ivideo
->sisfb_thismonitor
, 1);
6264 if(ivideo
->sisfb_mode_idx
>= 0) {
6265 int bu
= ivideo
->sisfb_mode_idx
;
6266 ivideo
->sisfb_mode_idx
= sisfb_validate_mode(ivideo
,
6267 ivideo
->sisfb_mode_idx
, ivideo
->currentvbflags
);
6268 if(bu
!= ivideo
->sisfb_mode_idx
) {
6269 printk(KERN_ERR
"Mode %dx%dx%d failed validation\n",
6270 sisbios_mode
[bu
].xres
,
6271 sisbios_mode
[bu
].yres
,
6272 sisbios_mode
[bu
].bpp
);
6276 if(ivideo
->sisfb_mode_idx
< 0) {
6277 switch(ivideo
->currentvbflags
& VB_DISPTYPE_DISP2
) {
6279 ivideo
->sisfb_mode_idx
= ivideo
->lcddefmodeidx
;
6282 ivideo
->sisfb_mode_idx
= ivideo
->tvdefmodeidx
;
6285 ivideo
->sisfb_mode_idx
= ivideo
->defmodeidx
;
6290 ivideo
->mode_no
= sisbios_mode
[ivideo
->sisfb_mode_idx
].mode_no
[ivideo
->mni
];
6292 if(ivideo
->refresh_rate
!= 0) {
6293 sisfb_search_refresh_rate(ivideo
, ivideo
->refresh_rate
,
6294 ivideo
->sisfb_mode_idx
);
6297 if(ivideo
->rate_idx
== 0) {
6298 ivideo
->rate_idx
= sisbios_mode
[ivideo
->sisfb_mode_idx
].rate_idx
;
6299 ivideo
->refresh_rate
= 60;
6302 if(ivideo
->sisfb_thismonitor
.datavalid
) {
6303 if(!sisfb_verify_rate(ivideo
, &ivideo
->sisfb_thismonitor
,
6304 ivideo
->sisfb_mode_idx
,
6306 ivideo
->refresh_rate
)) {
6307 printk(KERN_INFO
"sisfb: WARNING: Refresh rate "
6308 "exceeds monitor specs!\n");
6312 ivideo
->video_bpp
= sisbios_mode
[ivideo
->sisfb_mode_idx
].bpp
;
6313 ivideo
->video_width
= sisbios_mode
[ivideo
->sisfb_mode_idx
].xres
;
6314 ivideo
->video_height
= sisbios_mode
[ivideo
->sisfb_mode_idx
].yres
;
6316 sisfb_set_vparms(ivideo
);
6318 printk(KERN_INFO
"sisfb: Default mode is %dx%dx%d (%dHz)\n",
6319 ivideo
->video_width
, ivideo
->video_height
, ivideo
->video_bpp
,
6320 ivideo
->refresh_rate
);
6322 /* Set up the default var according to chosen default display mode */
6323 ivideo
->default_var
.xres
= ivideo
->default_var
.xres_virtual
= ivideo
->video_width
;
6324 ivideo
->default_var
.yres
= ivideo
->default_var
.yres_virtual
= ivideo
->video_height
;
6325 ivideo
->default_var
.bits_per_pixel
= ivideo
->video_bpp
;
6327 sisfb_bpp_to_var(ivideo
, &ivideo
->default_var
);
6329 ivideo
->default_var
.pixclock
= (u32
) (1000000000 /
6330 sisfb_mode_rate_to_dclock(&ivideo
->SiS_Pr
, ivideo
->mode_no
, ivideo
->rate_idx
));
6332 if(sisfb_mode_rate_to_ddata(&ivideo
->SiS_Pr
, ivideo
->mode_no
,
6333 ivideo
->rate_idx
, &ivideo
->default_var
)) {
6334 if((ivideo
->default_var
.vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
6335 ivideo
->default_var
.pixclock
<<= 1;
6339 if(ivideo
->sisfb_ypan
) {
6340 /* Maximize regardless of sisfb_max at startup */
6341 ivideo
->default_var
.yres_virtual
=
6342 sisfb_calc_maxyres(ivideo
, &ivideo
->default_var
);
6343 if(ivideo
->default_var
.yres_virtual
< ivideo
->default_var
.yres
) {
6344 ivideo
->default_var
.yres_virtual
= ivideo
->default_var
.yres
;
6348 sisfb_calc_pitch(ivideo
, &ivideo
->default_var
);
6351 if(ivideo
->sisfb_accel
) {
6353 #ifdef STUPID_ACCELF_TEXT_SHIT
6354 ivideo
->default_var
.accel_flags
|= FB_ACCELF_TEXT
;
6357 sisfb_initaccel(ivideo
);
6359 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
6360 sis_fb_info
->flags
= FBINFO_DEFAULT
|
6361 FBINFO_HWACCEL_YPAN
|
6362 FBINFO_HWACCEL_XPAN
|
6363 FBINFO_HWACCEL_COPYAREA
|
6364 FBINFO_HWACCEL_FILLRECT
|
6365 ((ivideo
->accel
) ? 0 : FBINFO_HWACCEL_DISABLED
);
6367 sis_fb_info
->flags
= FBINFO_FLAG_DEFAULT
;
6369 sis_fb_info
->var
= ivideo
->default_var
;
6370 sis_fb_info
->fix
= ivideo
->sisfb_fix
;
6371 sis_fb_info
->screen_base
= ivideo
->video_vbase
+ ivideo
->video_offset
;
6372 sis_fb_info
->fbops
= &sisfb_ops
;
6373 sis_fb_info
->pseudo_palette
= ivideo
->pseudo_palette
;
6375 fb_alloc_cmap(&sis_fb_info
->cmap
, 256 , 0);
6377 printk(KERN_DEBUG
"sisfb: Initial vbflags 0x%x\n", (int)ivideo
->vbflags
);
6380 ivideo
->mtrr
= mtrr_add(ivideo
->video_base
, ivideo
->video_size
,
6381 MTRR_TYPE_WRCOMB
, 1);
6382 if(ivideo
->mtrr
< 0) {
6383 printk(KERN_DEBUG
"sisfb: Failed to add MTRRs\n");
6387 if(register_framebuffer(sis_fb_info
) < 0) {
6388 printk(KERN_ERR
"sisfb: Fatal error: Failed to register framebuffer\n");
6390 iounmap(ivideo
->mmio_vbase
);
6394 ivideo
->registered
= 1;
6397 ivideo
->next
= card_list
;
6400 printk(KERN_INFO
"sisfb: 2D acceleration is %s, y-panning %s\n",
6401 ivideo
->sisfb_accel
? "enabled" : "disabled",
6402 ivideo
->sisfb_ypan
?
6403 (ivideo
->sisfb_max
? "enabled (auto-max)" :
6404 "enabled (no auto-max)") :
6408 printk(KERN_INFO
"fb%d: %s frame buffer device version %d.%d.%d\n",
6409 sis_fb_info
->node
, ivideo
->myid
, VER_MAJOR
, VER_MINOR
, VER_LEVEL
);
6411 printk(KERN_INFO
"sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
6413 } /* if mode = "none" */
6418 /*****************************************************/
6419 /* PCI DEVICE HANDLING */
6420 /*****************************************************/
6422 static void __devexit
sisfb_remove(struct pci_dev
*pdev
)
6424 struct sis_video_info
*ivideo
= pci_get_drvdata(pdev
);
6425 struct fb_info
*sis_fb_info
= ivideo
->memyselfandi
;
6426 int registered
= ivideo
->registered
;
6427 int modechanged
= ivideo
->modechanged
;
6430 iounmap(ivideo
->mmio_vbase
);
6431 iounmap(ivideo
->video_vbase
);
6433 /* Release mem regions */
6434 release_mem_region(ivideo
->video_base
, ivideo
->video_size
);
6435 release_mem_region(ivideo
->mmio_base
, ivideo
->mmio_size
);
6437 vfree(ivideo
->bios_abase
);
6440 pci_dev_put(ivideo
->lpcdev
);
6443 pci_dev_put(ivideo
->nbridge
);
6446 /* Release MTRR region */
6447 if(ivideo
->mtrr
>= 0)
6448 mtrr_del(ivideo
->mtrr
, ivideo
->video_base
, ivideo
->video_size
);
6451 pci_set_drvdata(pdev
, NULL
);
6453 /* If device was disabled when starting, disable
6456 if(!ivideo
->sisvga_enabled
)
6457 pci_disable_device(pdev
);
6459 /* Unregister the framebuffer */
6460 if(ivideo
->registered
) {
6461 unregister_framebuffer(sis_fb_info
);
6462 framebuffer_release(sis_fb_info
);
6465 /* OK, our ivideo is gone for good from here. */
6467 /* TODO: Restore the initial mode
6468 * This sounds easy but is as good as impossible
6469 * on many machines with SiS chip and video bridge
6470 * since text modes are always set up differently
6471 * from machine to machine. Depends on the type
6472 * of integration between chipset and bridge.
6474 if(registered
&& modechanged
)
6476 "sisfb: Restoring of text mode not supported yet\n");
6479 static struct pci_driver sisfb_driver
= {
6481 .id_table
= sisfb_pci_table
,
6482 .probe
= sisfb_probe
,
6483 .remove
= __devexit_p(sisfb_remove
)
6486 static int __init
sisfb_init(void)
6489 char *options
= NULL
;
6491 if(fb_get_options("sisfb", &options
))
6494 sisfb_setup(options
);
6496 return pci_register_driver(&sisfb_driver
);
6500 module_init(sisfb_init
);
6503 /*****************************************************/
6505 /*****************************************************/
6509 static char *mode
= NULL
;
6510 static int vesa
= -1;
6511 static unsigned int rate
= 0;
6512 static unsigned int crt1off
= 1;
6513 static unsigned int mem
= 0;
6514 static char *forcecrt2type
= NULL
;
6515 static int forcecrt1
= -1;
6516 static int pdc
= -1;
6517 static int pdc1
= -1;
6518 static int noaccel
= -1;
6519 static int noypan
= -1;
6520 static int nomax
= -1;
6521 static int userom
= -1;
6522 static int useoem
= -1;
6523 static char *tvstandard
= NULL
;
6524 static int nocrt2rate
= 0;
6525 static int scalelcd
= -1;
6526 static char *specialtiming
= NULL
;
6527 static int lvdshl
= -1;
6528 static int tvxposoffset
= 0, tvyposoffset
= 0;
6529 #if !defined(__i386__) && !defined(__x86_64__)
6530 static int resetcard
= 0;
6531 static int videoram
= 0;
6534 static int __init
sisfb_init_module(void)
6536 sisfb_setdefaultparms();
6539 sisfb_parm_rate
= rate
;
6541 if((scalelcd
== 0) || (scalelcd
== 1))
6542 sisfb_scalelcd
= scalelcd
^ 1;
6544 /* Need to check crt2 type first for fstn/dstn */
6547 sisfb_search_crt2type(forcecrt2type
);
6550 sisfb_search_tvstd(tvstandard
);
6553 sisfb_search_mode(mode
, false);
6555 sisfb_search_vesamode(vesa
, false);
6557 sisfb_crt1off
= (crt1off
== 0) ? 1 : 0;
6559 sisfb_forcecrt1
= forcecrt1
;
6562 else if(forcecrt1
== 0)
6567 else if(noaccel
== 0)
6572 else if(noypan
== 0)
6581 sisfb_parm_mem
= mem
;
6584 sisfb_userom
= userom
;
6587 sisfb_useoem
= useoem
;
6590 sisfb_pdc
= (pdc
& 0x7f);
6593 sisfb_pdca
= (pdc1
& 0x1f);
6595 sisfb_nocrt2rate
= nocrt2rate
;
6598 sisfb_search_specialtiming(specialtiming
);
6600 if((lvdshl
>= 0) && (lvdshl
<= 3))
6601 sisfb_lvdshl
= lvdshl
;
6603 sisfb_tvxposoffset
= tvxposoffset
;
6604 sisfb_tvyposoffset
= tvyposoffset
;
6606 #if !defined(__i386__) && !defined(__x86_64__)
6607 sisfb_resetcard
= (resetcard
) ? 1 : 0;
6609 sisfb_videoram
= videoram
;
6612 return sisfb_init();
6615 static void __exit
sisfb_remove_module(void)
6617 pci_unregister_driver(&sisfb_driver
);
6618 printk(KERN_DEBUG
"sisfb: Module unloaded\n");
6621 module_init(sisfb_init_module
);
6622 module_exit(sisfb_remove_module
);
6624 MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
6625 MODULE_LICENSE("GPL");
6626 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
6628 module_param(mem
, int, 0);
6629 module_param(noaccel
, int, 0);
6630 module_param(noypan
, int, 0);
6631 module_param(nomax
, int, 0);
6632 module_param(userom
, int, 0);
6633 module_param(useoem
, int, 0);
6634 module_param(mode
, charp
, 0);
6635 module_param(vesa
, int, 0);
6636 module_param(rate
, int, 0);
6637 module_param(forcecrt1
, int, 0);
6638 module_param(forcecrt2type
, charp
, 0);
6639 module_param(scalelcd
, int, 0);
6640 module_param(pdc
, int, 0);
6641 module_param(pdc1
, int, 0);
6642 module_param(specialtiming
, charp
, 0);
6643 module_param(lvdshl
, int, 0);
6644 module_param(tvstandard
, charp
, 0);
6645 module_param(tvxposoffset
, int, 0);
6646 module_param(tvyposoffset
, int, 0);
6647 module_param(nocrt2rate
, int, 0);
6648 #if !defined(__i386__) && !defined(__x86_64__)
6649 module_param(resetcard
, int, 0);
6650 module_param(videoram
, int, 0);
6653 MODULE_PARM_DESC(mem
,
6654 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6655 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6656 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6657 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6658 "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6659 "The value is to be specified without 'KB'.\n");
6661 MODULE_PARM_DESC(noaccel
,
6662 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
6665 MODULE_PARM_DESC(noypan
,
6666 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
6667 "will be performed by redrawing the screen. (default: 0)\n");
6669 MODULE_PARM_DESC(nomax
,
6670 "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
6671 "memory for the virtual screen in order to optimize scrolling performance. If\n"
6672 "this is set to anything other than 0, sisfb will not do this and thereby \n"
6673 "enable the user to positively specify a virtual Y size of the screen using\n"
6674 "fbset. (default: 0)\n");
6676 MODULE_PARM_DESC(mode
,
6677 "\nSelects the desired default display mode in the format XxYxDepth,\n"
6678 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
6679 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
6680 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
6682 MODULE_PARM_DESC(vesa
,
6683 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
6684 "0x117 (default: 0x0103)\n");
6686 MODULE_PARM_DESC(rate
,
6687 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
6688 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
6689 "will be ignored (default: 60)\n");
6691 MODULE_PARM_DESC(forcecrt1
,
6692 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
6693 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
6694 "0=CRT1 OFF) (default: [autodetected])\n");
6696 MODULE_PARM_DESC(forcecrt2type
,
6697 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
6698 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
6699 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
6700 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
6701 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
6702 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
6703 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
6704 "depends on the very hardware in use. (default: [autodetected])\n");
6706 MODULE_PARM_DESC(scalelcd
,
6707 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
6708 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
6709 "show black bars around the image, TMDS panels will probably do the scaling\n"
6710 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
6712 MODULE_PARM_DESC(pdc
,
6713 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
6714 "should detect this correctly in most cases; however, sometimes this is not\n"
6715 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
6716 "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
6717 "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
6718 "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
6720 #ifdef CONFIG_FB_SIS_315
6721 MODULE_PARM_DESC(pdc1
,
6722 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
6723 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
6724 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
6725 "implemented yet.\n");
6728 MODULE_PARM_DESC(specialtiming
,
6729 "\nPlease refer to documentation for more information on this option.\n");
6731 MODULE_PARM_DESC(lvdshl
,
6732 "\nPlease refer to documentation for more information on this option.\n");
6734 MODULE_PARM_DESC(tvstandard
,
6735 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
6736 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
6738 MODULE_PARM_DESC(tvxposoffset
,
6739 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
6742 MODULE_PARM_DESC(tvyposoffset
,
6743 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
6746 MODULE_PARM_DESC(nocrt2rate
,
6747 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
6748 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
6750 #if !defined(__i386__) && !defined(__x86_64__)
6751 #ifdef CONFIG_FB_SIS_300
6752 MODULE_PARM_DESC(resetcard
,
6753 "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
6754 "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
6755 "currently). Default: 0\n");
6757 MODULE_PARM_DESC(videoram
,
6758 "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
6759 "some non-x86 architectures where the memory auto detection fails. Only\n"
6760 "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
6764 #endif /* /MODULE */
6766 /* _GPL only for new symbols. */
6767 EXPORT_SYMBOL(sis_malloc
);
6768 EXPORT_SYMBOL(sis_free
);
6769 EXPORT_SYMBOL_GPL(sis_malloc_new
);
6770 EXPORT_SYMBOL_GPL(sis_free_new
);