2 * XG20, XG21, XG40, XG42 frame buffer device
3 * for Linux kernels 2.5.x, 2.6.x
4 * Base on TW's sis fbdev code.
7 /* #include <linux/config.h> */
8 #include <linux/module.h>
9 #include <linux/moduleparam.h>
10 #include <linux/kernel.h>
11 #include <linux/spinlock.h>
12 #include <linux/errno.h>
13 #include <linux/string.h>
15 #include <linux/tty.h>
16 #include <linux/slab.h>
17 #include <linux/delay.h>
19 #include <linux/console.h>
20 #include <linux/selection.h>
21 #include <linux/ioport.h>
22 #include <linux/init.h>
23 #include <linux/pci.h>
24 #include <linux/vmalloc.h>
25 #include <linux/vt_kern.h>
26 #include <linux/capability.h>
28 #include <linux/types.h>
29 #include <linux/proc_fs.h>
41 #include "vb_setmode.h"
43 #define Index_CR_GPIO_Reg1 0x48
44 #define Index_CR_GPIO_Reg3 0x4a
46 #define GPIOG_EN (1<<6)
47 #define GPIOG_READ (1<<1)
49 #define XGIFB_ROM_SIZE 65536
53 static unsigned int refresh_rate
;
55 /* -------------------- Macro definitions ---------------------------- */
60 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
62 #define DPRINTK(fmt, args...)
66 static void dumpVGAReg(void)
70 xgifb_reg_set(XGISR
, 0x05, 0x86);
72 xgifb_reg_set(XGISR, 0x08, 0x4f);
73 xgifb_reg_set(XGISR, 0x0f, 0x20);
74 xgifb_reg_set(XGISR, 0x11, 0x4f);
75 xgifb_reg_set(XGISR, 0x13, 0x45);
76 xgifb_reg_set(XGISR, 0x14, 0x51);
77 xgifb_reg_set(XGISR, 0x1e, 0x41);
78 xgifb_reg_set(XGISR, 0x1f, 0x0);
79 xgifb_reg_set(XGISR, 0x20, 0xa1);
80 xgifb_reg_set(XGISR, 0x22, 0xfb);
81 xgifb_reg_set(XGISR, 0x26, 0x22);
82 xgifb_reg_set(XGISR, 0x3e, 0x07);
85 /* xgifb_reg_set(XGICR, 0x19, 0x00); */
86 /* xgifb_reg_set(XGICR, 0x1a, 0x3C); */
87 /* xgifb_reg_set(XGICR, 0x22, 0xff); */
88 /* xgifb_reg_set(XGICR, 0x3D, 0x10); */
90 /* xgifb_reg_set(XGICR, 0x4a, 0xf3); */
92 /* xgifb_reg_set(XGICR, 0x57, 0x0); */
93 /* xgifb_reg_set(XGICR, 0x7a, 0x2c); */
95 /* xgifb_reg_set(XGICR, 0x82, 0xcc); */
96 /* xgifb_reg_set(XGICR, 0x8c, 0x0); */
98 xgifb_reg_set(XGICR, 0x99, 0x1);
99 xgifb_reg_set(XGICR, 0x41, 0x40);
102 for (i
= 0; i
< 0x4f; i
++) {
103 reg
= xgifb_reg_get(XGISR
, i
);
104 printk("\no 3c4 %x", i
);
105 printk("\ni 3c5 => %x", reg
);
108 for (i
= 0; i
< 0xF0; i
++) {
109 reg
= xgifb_reg_get(XGICR
, i
);
110 printk("\no 3d4 %x", i
);
111 printk("\ni 3d5 => %x", reg
);
114 xgifb_reg_set(XGIPART1,0x2F,1);
115 for (i=1; i < 0x50; i++) {
116 reg = xgifb_reg_get(XGIPART1, i);
117 printk("\no d004 %x", i);
118 printk("\ni d005 => %x", reg);
121 for (i=0; i < 0x50; i++) {
122 reg = xgifb_reg_get(XGIPART2, i);
123 printk("\no d010 %x", i);
124 printk("\ni d011 => %x", reg);
126 for (i=0; i < 0x50; i++) {
127 reg = xgifb_reg_get(XGIPART3, i);
128 printk("\no d012 %x",i);
129 printk("\ni d013 => %x",reg);
131 for (i=0; i < 0x50; i++) {
132 reg = xgifb_reg_get(XGIPART4, i);
133 printk("\no d014 %x",i);
134 printk("\ni d015 => %x",reg);
139 static inline void dumpVGAReg(void)
147 #define DEBUGPRN(x) printk(KERN_INFO x "\n");
150 /* --------------- Hardware Access Routines -------------------------- */
152 static int XGIfb_mode_rate_to_dclock(struct vb_device_info
*XGI_Pr
,
153 struct xgi_hw_device_info
*HwDeviceExtension
,
154 unsigned char modeno
, unsigned char rateindex
)
156 unsigned short ModeNo
= modeno
;
157 unsigned short ModeIdIndex
= 0, ClockIndex
= 0;
158 unsigned short RefreshRateTableIndex
= 0;
160 /* unsigned long temp = 0; */
162 XGI_Pr
->ROMAddr
= HwDeviceExtension
->pjVirtualRomBase
;
163 InitTo330Pointer(HwDeviceExtension
->jChipType
, XGI_Pr
);
165 RefreshRateTableIndex
= XGI_GetRatePtrCRT2(HwDeviceExtension
, ModeNo
,
166 ModeIdIndex
, XGI_Pr
);
169 temp = XGI_SearchModeID(ModeNo , &ModeIdIndex, XGI_Pr) ;
171 printk(KERN_ERR "Could not find mode %x\n", ModeNo);
175 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
176 RefreshRateTableIndex += (rateindex - 1);
179 ClockIndex
= XGI_Pr
->RefIndex
[RefreshRateTableIndex
].Ext_CRTVCLK
;
181 Clock
= XGI_Pr
->VCLKData
[ClockIndex
].CLOCK
* 1000;
186 static int XGIfb_mode_rate_to_ddata(struct vb_device_info
*XGI_Pr
,
187 struct xgi_hw_device_info
*HwDeviceExtension
,
188 unsigned char modeno
, unsigned char rateindex
,
189 u32
*left_margin
, u32
*right_margin
, u32
*upper_margin
,
190 u32
*lower_margin
, u32
*hsync_len
, u32
*vsync_len
, u32
*sync
,
193 unsigned short ModeNo
= modeno
;
194 unsigned short ModeIdIndex
= 0, index
= 0;
195 unsigned short RefreshRateTableIndex
= 0;
197 unsigned short VRE
, VBE
, VRS
, VBS
, VDE
, VT
;
198 unsigned short HRE
, HBE
, HRS
, HBS
, HDE
, HT
;
199 unsigned char sr_data
, cr_data
, cr_data2
;
200 unsigned long cr_data3
;
201 int A
, B
, C
, D
, E
, F
, temp
, j
;
202 XGI_Pr
->ROMAddr
= HwDeviceExtension
->pjVirtualRomBase
;
203 InitTo330Pointer(HwDeviceExtension
->jChipType
, XGI_Pr
);
204 RefreshRateTableIndex
= XGI_GetRatePtrCRT2(HwDeviceExtension
, ModeNo
,
205 ModeIdIndex
, XGI_Pr
);
207 temp = XGI_SearchModeID(ModeNo, &ModeIdIndex, XGI_Pr);
211 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
212 RefreshRateTableIndex += (rateindex - 1);
214 index
= XGI_Pr
->RefIndex
[RefreshRateTableIndex
].Ext_CRT1CRTC
;
216 sr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[5];
218 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[0];
220 /* Horizontal total */
221 HT
= (cr_data
& 0xff) | ((unsigned short) (sr_data
& 0x03) << 8);
225 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
227 Horizontal display enable end
228 HDE = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x0C) << 6);
230 HDE
= (XGI_Pr
->RefIndex
[RefreshRateTableIndex
].XRes
>> 3) - 1;
233 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[3];
235 /* Horizontal retrace (=sync) start */
236 HRS
= (cr_data
& 0xff) | ((unsigned short) (sr_data
& 0xC0) << 2);
239 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[1];
241 /* Horizontal blank start */
242 HBS
= (cr_data
& 0xff) | ((unsigned short) (sr_data
& 0x30) << 4);
244 sr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[6];
246 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[2];
248 cr_data2
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[4];
250 /* Horizontal blank end */
251 HBE
= (cr_data
& 0x1f) | ((unsigned short) (cr_data2
& 0x80) >> 2)
252 | ((unsigned short) (sr_data
& 0x03) << 6);
254 /* Horizontal retrace (=sync) end */
255 HRE
= (cr_data2
& 0x1f) | ((sr_data
& 0x04) << 3);
257 temp
= HBE
- ((E
- 1) & 255);
258 B
= (temp
> 0) ? temp
: (temp
+ 256);
260 temp
= HRE
- ((E
+ F
+ 3) & 63);
261 C
= (temp
> 0) ? temp
: (temp
+ 64);
265 *left_margin
= D
* 8;
266 *right_margin
= F
* 8;
269 sr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[14];
271 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[8];
273 cr_data2
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[9];
276 VT
= (cr_data
& 0xFF) | ((unsigned short) (cr_data2
& 0x01) << 8)
277 | ((unsigned short) (cr_data2
& 0x20) << 4)
278 | ((unsigned short) (sr_data
& 0x01) << 10);
281 /* cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10]; */
283 /* Vertical display enable end */
285 VDE = (cr_data & 0xff) |
286 ((unsigned short) (cr_data2 & 0x02) << 7) |
287 ((unsigned short) (cr_data2 & 0x40) << 3) |
288 ((unsigned short) (sr_data & 0x02) << 9);
290 VDE
= XGI_Pr
->RefIndex
[RefreshRateTableIndex
].YRes
- 1;
293 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[10];
295 /* Vertical retrace (=sync) start */
296 VRS
= (cr_data
& 0xff) | ((unsigned short) (cr_data2
& 0x04) << 6)
297 | ((unsigned short) (cr_data2
& 0x80) << 2)
298 | ((unsigned short) (sr_data
& 0x08) << 7);
301 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[12];
303 cr_data3
= (XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[14] & 0x80) << 5;
305 /* Vertical blank start */
306 VBS
= (cr_data
& 0xff) | ((unsigned short) (cr_data2
& 0x08) << 5)
307 | ((unsigned short) (cr_data3
& 0x20) << 4)
308 | ((unsigned short) (sr_data
& 0x04) << 8);
310 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[13];
312 /* Vertical blank end */
313 VBE
= (cr_data
& 0xff) | ((unsigned short) (sr_data
& 0x10) << 4);
314 temp
= VBE
- ((E
- 1) & 511);
315 B
= (temp
> 0) ? temp
: (temp
+ 512);
317 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[11];
319 /* Vertical retrace (=sync) end */
320 VRE
= (cr_data
& 0x0f) | ((sr_data
& 0x20) >> 1);
321 temp
= VRE
- ((E
+ F
- 1) & 31);
322 C
= (temp
> 0) ? temp
: (temp
+ 32);
330 if (XGI_Pr
->RefIndex
[RefreshRateTableIndex
].Ext_InfoFlag
& 0x8000)
331 *sync
&= ~FB_SYNC_VERT_HIGH_ACT
;
333 *sync
|= FB_SYNC_VERT_HIGH_ACT
;
335 if (XGI_Pr
->RefIndex
[RefreshRateTableIndex
].Ext_InfoFlag
& 0x4000)
336 *sync
&= ~FB_SYNC_HOR_HIGH_ACT
;
338 *sync
|= FB_SYNC_HOR_HIGH_ACT
;
340 *vmode
= FB_VMODE_NONINTERLACED
;
341 if (XGI_Pr
->RefIndex
[RefreshRateTableIndex
].Ext_InfoFlag
& 0x0080)
342 *vmode
= FB_VMODE_INTERLACED
;
345 while (XGI_Pr
->EModeIDTable
[j
].Ext_ModeID
!= 0xff) {
346 if (XGI_Pr
->EModeIDTable
[j
].Ext_ModeID
==
347 XGI_Pr
->RefIndex
[RefreshRateTableIndex
].ModeID
) {
348 if (XGI_Pr
->EModeIDTable
[j
].Ext_ModeFlag
&
350 *vmode
= FB_VMODE_DOUBLE
;
361 static void XGIRegInit(struct vb_device_info
*XGI_Pr
, unsigned long BaseAddr
)
363 XGI_Pr
->RelIO
= BaseAddr
;
364 XGI_Pr
->P3c4
= BaseAddr
+ 0x14;
365 XGI_Pr
->P3d4
= BaseAddr
+ 0x24;
366 XGI_Pr
->P3c0
= BaseAddr
+ 0x10;
367 XGI_Pr
->P3ce
= BaseAddr
+ 0x1e;
368 XGI_Pr
->P3c2
= BaseAddr
+ 0x12;
369 XGI_Pr
->P3ca
= BaseAddr
+ 0x1a;
370 XGI_Pr
->P3c6
= BaseAddr
+ 0x16;
371 XGI_Pr
->P3c7
= BaseAddr
+ 0x17;
372 XGI_Pr
->P3c8
= BaseAddr
+ 0x18;
373 XGI_Pr
->P3c9
= BaseAddr
+ 0x19;
374 XGI_Pr
->P3da
= BaseAddr
+ 0x2A;
375 /* Digital video interface registers (LCD) */
376 XGI_Pr
->Part1Port
= BaseAddr
+ XGI_CRT2_PORT_04
;
377 /* 301 TV Encoder registers */
378 XGI_Pr
->Part2Port
= BaseAddr
+ XGI_CRT2_PORT_10
;
379 /* 301 Macrovision registers */
380 XGI_Pr
->Part3Port
= BaseAddr
+ XGI_CRT2_PORT_12
;
381 /* 301 VGA2 (and LCD) registers */
382 XGI_Pr
->Part4Port
= BaseAddr
+ XGI_CRT2_PORT_14
;
383 /* 301 palette address port registers */
384 XGI_Pr
->Part5Port
= BaseAddr
+ XGI_CRT2_PORT_14
+ 2;
388 /* ------------------ Internal helper routines ----------------- */
390 static int XGIfb_GetXG21DefaultLVDSModeIdx(void)
394 int XGIfb_mode_idx
= 0;
397 while ((XGIbios_mode
[XGIfb_mode_idx
].mode_no
!= 0)
398 && (XGIbios_mode
[XGIfb_mode_idx
].xres
399 <= XGI21_LCDCapList
[0].LVDSHDE
)) {
400 if ((XGIbios_mode
[XGIfb_mode_idx
].xres
401 == XGI21_LCDCapList
[0].LVDSHDE
)
402 && (XGIbios_mode
[XGIfb_mode_idx
].yres
403 == XGI21_LCDCapList
[0].LVDSVDE
)
404 && (XGIbios_mode
[XGIfb_mode_idx
].bpp
== 8)) {
413 return XGIfb_mode_idx
;
416 static void XGIfb_search_mode(struct xgifb_video_info
*xgifb_info
,
421 while (XGIbios_mode
[i
].mode_no
!= 0) {
422 l
= min(strlen(name
), strlen(XGIbios_mode
[i
].name
));
423 if (!strncmp(name
, XGIbios_mode
[i
].name
, l
)) {
424 xgifb_info
->mode_idx
= i
;
431 printk(KERN_INFO
"XGIfb: Invalid mode '%s'\n", name
);
434 static void XGIfb_search_vesamode(struct xgifb_video_info
*xgifb_info
,
435 unsigned int vesamode
)
442 vesamode
&= 0x1dff; /* Clean VESA mode number from other flags */
444 while (XGIbios_mode
[i
].mode_no
!= 0) {
445 if ((XGIbios_mode
[i
].vesa_mode_no_1
== vesamode
) ||
446 (XGIbios_mode
[i
].vesa_mode_no_2
== vesamode
)) {
447 xgifb_info
->mode_idx
= i
;
456 printk(KERN_INFO
"XGIfb: Invalid VESA mode 0x%x'\n", vesamode
);
459 static int XGIfb_GetXG21LVDSData(struct xgifb_video_info
*xgifb_info
)
462 void __iomem
*data
= xgifb_info
->mmio_vbase
+ 0x20000;
465 tmp
= xgifb_reg_get(XGISR
, 0x1e);
466 xgifb_reg_set(XGISR
, 0x1e, tmp
| 4);
468 if ((readb(data
) == 0x55) &&
469 (readb(data
+ 1) == 0xAA) &&
470 (readb(data
+ 0x65) & 0x1)) {
471 i
= readw(data
+ 0x316);
472 j
= readb(data
+ i
- 1);
478 XGI21_LCDCapList
[k
].LVDS_Capability
= readw(data
+ i
);
479 XGI21_LCDCapList
[k
].LVDSHT
= readw(data
+ i
+ 2);
480 XGI21_LCDCapList
[k
].LVDSVT
= readw(data
+ i
+ 4);
481 XGI21_LCDCapList
[k
].LVDSHDE
= readw(data
+ i
+ 6);
482 XGI21_LCDCapList
[k
].LVDSVDE
= readw(data
+ i
+ 8);
483 XGI21_LCDCapList
[k
].LVDSHFP
= readw(data
+ i
+ 10);
484 XGI21_LCDCapList
[k
].LVDSVFP
= readw(data
+ i
+ 12);
485 XGI21_LCDCapList
[k
].LVDSHSYNC
= readw(data
+ i
+ 14);
486 XGI21_LCDCapList
[k
].LVDSVSYNC
= readw(data
+ i
+ 16);
487 XGI21_LCDCapList
[k
].VCLKData1
= readb(data
+ i
+ 18);
488 XGI21_LCDCapList
[k
].VCLKData2
= readb(data
+ i
+ 19);
489 XGI21_LCDCapList
[k
].PSC_S1
= readb(data
+ i
+ 20);
490 XGI21_LCDCapList
[k
].PSC_S2
= readb(data
+ i
+ 21);
491 XGI21_LCDCapList
[k
].PSC_S3
= readb(data
+ i
+ 22);
492 XGI21_LCDCapList
[k
].PSC_S4
= readb(data
+ i
+ 23);
493 XGI21_LCDCapList
[k
].PSC_S5
= readb(data
+ i
+ 24);
497 } while ((j
> 0) && (k
< (sizeof(XGI21_LCDCapList
)
498 / sizeof(struct XGI21_LVDSCapStruct
))));
504 static int XGIfb_validate_mode(struct xgifb_video_info
*xgifb_info
, int myindex
)
507 struct xgi_hw_device_info
*hw_info
= &xgifb_info
->hw_info
;
509 if (xgifb_info
->chip
== XG21
) {
510 if ((xgifb_info
->disp_state
& DISPTYPE_DISP2
)
512 xres
= XGI21_LCDCapList
[0].LVDSHDE
;
513 yres
= XGI21_LCDCapList
[0].LVDSVDE
;
514 if (XGIbios_mode
[myindex
].xres
> xres
)
516 if (XGIbios_mode
[myindex
].yres
> yres
)
518 if ((XGIbios_mode
[myindex
].xres
< xres
) &&
519 (XGIbios_mode
[myindex
].yres
< yres
)) {
520 if (XGIbios_mode
[myindex
].bpp
> 8)
529 /* FIXME: for now, all is valid on XG27 */
530 if (xgifb_info
->chip
== XG27
)
533 if (!(XGIbios_mode
[myindex
].chipset
& MD_XGI315
))
536 switch (xgifb_info
->disp_state
& DISPTYPE_DISP2
) {
538 switch (hw_info
->ulCRT2LCDType
) {
579 /* case LCD_320x480: */ /* TW: FSTN */
590 if (XGIbios_mode
[myindex
].xres
> xres
)
592 if (XGIbios_mode
[myindex
].yres
> yres
)
594 if ((hw_info
->ulExternalChip
== 0x01) || /* LVDS */
595 (hw_info
->ulExternalChip
== 0x05)) { /* LVDS+Chrontel */
596 switch (XGIbios_mode
[myindex
].xres
) {
598 if (XGIbios_mode
[myindex
].yres
!= 512)
600 if (hw_info
->ulCRT2LCDType
== LCD_1024x600
)
604 if ((XGIbios_mode
[myindex
].yres
!= 400)
605 && (XGIbios_mode
[myindex
].yres
610 if (XGIbios_mode
[myindex
].yres
!= 600)
614 if ((XGIbios_mode
[myindex
].yres
!= 600) &&
615 (XGIbios_mode
[myindex
].yres
!= 768))
617 if ((XGIbios_mode
[myindex
].yres
== 600) &&
618 (hw_info
->ulCRT2LCDType
!= LCD_1024x600
))
622 if ((XGIbios_mode
[myindex
].yres
) != 768)
624 if (hw_info
->ulCRT2LCDType
!= LCD_1152x768
)
628 if ((XGIbios_mode
[myindex
].yres
!= 768) &&
629 (XGIbios_mode
[myindex
].yres
!= 1024))
631 if ((XGIbios_mode
[myindex
].yres
== 768) &&
632 (hw_info
->ulCRT2LCDType
!= LCD_1280x768
))
636 if (XGIbios_mode
[myindex
].yres
!= 1050)
640 if (XGIbios_mode
[myindex
].yres
!= 1200)
647 switch (XGIbios_mode
[myindex
].xres
) {
649 if (XGIbios_mode
[myindex
].yres
!= 512)
653 if ((XGIbios_mode
[myindex
].yres
!= 400) &&
654 (XGIbios_mode
[myindex
].yres
!= 480))
658 if (XGIbios_mode
[myindex
].yres
!= 600)
662 if (XGIbios_mode
[myindex
].yres
!= 768)
666 if ((XGIbios_mode
[myindex
].yres
!= 960) &&
667 (XGIbios_mode
[myindex
].yres
!= 1024))
669 if (XGIbios_mode
[myindex
].yres
== 960) {
670 if (hw_info
->ulCRT2LCDType
==
676 if (XGIbios_mode
[myindex
].yres
!= 1050)
680 if (XGIbios_mode
[myindex
].yres
!= 1200)
689 switch (XGIbios_mode
[myindex
].xres
) {
695 if (xgifb_info
->TV_type
== TVMODE_NTSC
) {
696 if (XGIbios_mode
[myindex
].yres
!= 480)
698 } else if (xgifb_info
->TV_type
== TVMODE_PAL
) {
699 if (XGIbios_mode
[myindex
].yres
!= 576)
702 /* TW: LVDS/CHRONTEL does not support 720 */
703 if (xgifb_info
->hasVB
== HASVB_LVDS_CHRONTEL
||
704 xgifb_info
->hasVB
== HASVB_CHRONTEL
) {
709 if (xgifb_info
->TV_type
== TVMODE_NTSC
) {
710 if (XGIbios_mode
[myindex
].bpp
== 32)
719 if (XGIbios_mode
[myindex
].xres
> 1280)
727 static void XGIfb_search_crt2type(const char *name
)
734 while (XGI_crt2type
[i
].type_no
!= -1) {
735 if (!strcmp(name
, XGI_crt2type
[i
].name
)) {
736 XGIfb_crt2type
= XGI_crt2type
[i
].type_no
;
737 XGIfb_tvplug
= XGI_crt2type
[i
].tvplug_no
;
742 if (XGIfb_crt2type
< 0)
743 printk(KERN_INFO
"XGIfb: Invalid CRT2 type: %s\n", name
);
746 static u8
XGIfb_search_refresh_rate(struct xgifb_video_info
*xgifb_info
,
752 xres
= XGIbios_mode
[xgifb_info
->mode_idx
].xres
;
753 yres
= XGIbios_mode
[xgifb_info
->mode_idx
].yres
;
755 xgifb_info
->rate_idx
= 0;
756 while ((XGIfb_vrate
[i
].idx
!= 0) && (XGIfb_vrate
[i
].xres
<= xres
)) {
757 if ((XGIfb_vrate
[i
].xres
== xres
) &&
758 (XGIfb_vrate
[i
].yres
== yres
)) {
759 if (XGIfb_vrate
[i
].refresh
== rate
) {
760 xgifb_info
->rate_idx
= XGIfb_vrate
[i
].idx
;
762 } else if (XGIfb_vrate
[i
].refresh
> rate
) {
763 if ((XGIfb_vrate
[i
].refresh
- rate
) <= 3) {
764 DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
765 rate
, XGIfb_vrate
[i
].refresh
);
766 xgifb_info
->rate_idx
=
768 xgifb_info
->refresh_rate
=
769 XGIfb_vrate
[i
].refresh
;
770 } else if (((rate
- XGIfb_vrate
[i
- 1].refresh
)
771 <= 2) && (XGIfb_vrate
[i
].idx
773 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
774 rate
, XGIfb_vrate
[i
-1].refresh
);
775 xgifb_info
->rate_idx
=
776 XGIfb_vrate
[i
- 1].idx
;
777 xgifb_info
->refresh_rate
=
778 XGIfb_vrate
[i
- 1].refresh
;
781 } else if ((rate
- XGIfb_vrate
[i
].refresh
) <= 2) {
782 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
783 rate
, XGIfb_vrate
[i
].refresh
);
784 xgifb_info
->rate_idx
= XGIfb_vrate
[i
].idx
;
790 if (xgifb_info
->rate_idx
> 0) {
791 return xgifb_info
->rate_idx
;
793 printk(KERN_INFO
"XGIfb: Unsupported rate %d for %dx%d\n",
799 static void XGIfb_search_tvstd(const char *name
)
806 while (XGI_tvtype
[i
].type_no
!= -1) {
807 if (!strcmp(name
, XGI_tvtype
[i
].name
)) {
808 XGIfb_tvmode
= XGI_tvtype
[i
].type_no
;
815 /* ----------- FBDev related routines for all series ----------- */
817 static void XGIfb_bpp_to_var(struct xgifb_video_info
*xgifb_info
,
818 struct fb_var_screeninfo
*var
)
820 switch (var
->bits_per_pixel
) {
822 var
->red
.offset
= var
->green
.offset
= var
->blue
.offset
= 0;
823 var
->red
.length
= var
->green
.length
= var
->blue
.length
= 6;
824 xgifb_info
->video_cmap_len
= 256;
827 var
->red
.offset
= 11;
829 var
->green
.offset
= 5;
830 var
->green
.length
= 6;
831 var
->blue
.offset
= 0;
832 var
->blue
.length
= 5;
833 var
->transp
.offset
= 0;
834 var
->transp
.length
= 0;
835 xgifb_info
->video_cmap_len
= 16;
838 var
->red
.offset
= 16;
840 var
->green
.offset
= 8;
841 var
->green
.length
= 8;
842 var
->blue
.offset
= 0;
843 var
->blue
.length
= 8;
844 var
->transp
.offset
= 24;
845 var
->transp
.length
= 8;
846 xgifb_info
->video_cmap_len
= 16;
851 /* --------------------- SetMode routines ------------------------- */
853 static void XGIfb_pre_setmode(struct xgifb_video_info
*xgifb_info
)
855 u8 cr30
= 0, cr31
= 0;
857 cr31
= xgifb_reg_get(XGICR
, 0x31);
860 switch (xgifb_info
->disp_state
& DISPTYPE_DISP2
) {
862 cr30
= (XGI_VB_OUTPUT_CRT2
| XGI_SIMULTANEOUS_VIEW_ENABLE
);
863 cr31
|= XGI_DRIVER_MODE
;
866 cr30
= (XGI_VB_OUTPUT_LCD
| XGI_SIMULTANEOUS_VIEW_ENABLE
);
867 cr31
|= XGI_DRIVER_MODE
;
870 if (xgifb_info
->TV_type
== TVMODE_HIVISION
)
871 cr30
= (XGI_VB_OUTPUT_HIVISION
872 | XGI_SIMULTANEOUS_VIEW_ENABLE
);
873 else if (xgifb_info
->TV_plug
== TVPLUG_SVIDEO
)
874 cr30
= (XGI_VB_OUTPUT_SVIDEO
875 | XGI_SIMULTANEOUS_VIEW_ENABLE
);
876 else if (xgifb_info
->TV_plug
== TVPLUG_COMPOSITE
)
877 cr30
= (XGI_VB_OUTPUT_COMPOSITE
878 | XGI_SIMULTANEOUS_VIEW_ENABLE
);
879 else if (xgifb_info
->TV_plug
== TVPLUG_SCART
)
880 cr30
= (XGI_VB_OUTPUT_SCART
881 | XGI_SIMULTANEOUS_VIEW_ENABLE
);
882 cr31
|= XGI_DRIVER_MODE
;
884 if (XGIfb_tvmode
== 1 || xgifb_info
->TV_type
== TVMODE_PAL
)
889 default: /* disable CRT2 */
891 cr31
|= (XGI_DRIVER_MODE
| XGI_VB_OUTPUT_DISABLE
);
894 xgifb_reg_set(XGICR
, IND_XGI_SCRATCH_REG_CR30
, cr30
);
895 xgifb_reg_set(XGICR
, IND_XGI_SCRATCH_REG_CR31
, cr31
);
896 xgifb_reg_set(XGICR
, IND_XGI_SCRATCH_REG_CR33
,
897 (xgifb_info
->rate_idx
& 0x0F));
900 static void XGIfb_post_setmode(struct xgifb_video_info
*xgifb_info
)
903 unsigned char doit
= 1;
905 xgifb_reg_set(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
906 xgifb_reg_set(XGICR, 0x13, 0x00);
907 xgifb_reg_and_or(XGISR,0x0E, 0xF0, 0x01);
910 if (xgifb_info
->video_bpp
== 8) {
911 /* TW: We can't switch off CRT1 on LVDS/Chrontel
913 if ((xgifb_info
->hasVB
== HASVB_LVDS
) ||
914 (xgifb_info
->hasVB
== HASVB_LVDS_CHRONTEL
)) {
917 /* TW: We can't switch off CRT1 on 301B-DH
918 * in 8bpp Modes if using LCD */
919 if (xgifb_info
->disp_state
& DISPTYPE_LCD
)
923 /* TW: We can't switch off CRT1 if bridge is in slave mode */
924 if (xgifb_info
->hasVB
!= HASVB_NONE
) {
925 reg
= xgifb_reg_get(XGIPART1
, 0x00);
927 if ((reg
& 0x50) == 0x10)
934 reg
= xgifb_reg_get(XGICR
, 0x17);
935 if ((XGIfb_crt1off
) && (doit
))
939 xgifb_reg_set(XGICR
, 0x17, reg
);
941 xgifb_reg_and(XGISR
, IND_XGI_RAMDAC_CONTROL
, ~0x04);
943 if ((xgifb_info
->disp_state
& DISPTYPE_TV
) && (xgifb_info
->hasVB
946 reg
= xgifb_reg_get(XGIPART4
, 0x01);
948 if (reg
< 0xB0) { /* Set filter for XGI301 */
951 switch (xgifb_info
->video_width
) {
953 filter_tb
= (xgifb_info
->TV_type
==
954 TVMODE_NTSC
) ? 4 : 12;
957 filter_tb
= (xgifb_info
->TV_type
==
958 TVMODE_NTSC
) ? 5 : 13;
961 filter_tb
= (xgifb_info
->TV_type
==
962 TVMODE_NTSC
) ? 6 : 14;
965 filter_tb
= (xgifb_info
->TV_type
==
966 TVMODE_NTSC
) ? 7 : 15;
973 xgifb_reg_or(XGIPART1
,
974 IND_XGI_CRT2_WRITE_ENABLE_315
,
977 if (xgifb_info
->TV_type
== TVMODE_NTSC
) {
979 xgifb_reg_and(XGIPART2
, 0x3a, 0x1f);
981 if (xgifb_info
->TV_plug
== TVPLUG_SVIDEO
) {
983 xgifb_reg_and(XGIPART2
, 0x30, 0xdf);
985 } else if (xgifb_info
->TV_plug
986 == TVPLUG_COMPOSITE
) {
988 xgifb_reg_or(XGIPART2
, 0x30, 0x20);
990 switch (xgifb_info
->video_width
) {
992 xgifb_reg_set(XGIPART2
,
995 xgifb_reg_set(XGIPART2
,
998 xgifb_reg_set(XGIPART2
,
1001 xgifb_reg_set(XGIPART2
,
1006 xgifb_reg_set(XGIPART2
,
1009 xgifb_reg_set(XGIPART2
,
1012 xgifb_reg_set(XGIPART2
,
1015 xgifb_reg_set(XGIPART2
,
1020 xgifb_reg_set(XGIPART2
,
1023 xgifb_reg_set(XGIPART2
,
1026 xgifb_reg_set(XGIPART2
,
1029 xgifb_reg_set(XGIPART2
,
1036 } else if (xgifb_info
->TV_type
== TVMODE_PAL
) {
1038 xgifb_reg_and(XGIPART2
, 0x3A, 0x1F);
1040 if (xgifb_info
->TV_plug
== TVPLUG_SVIDEO
) {
1042 xgifb_reg_and(XGIPART2
, 0x30, 0xDF);
1044 } else if (xgifb_info
->TV_plug
1045 == TVPLUG_COMPOSITE
) {
1047 xgifb_reg_or(XGIPART2
, 0x30, 0x20);
1049 switch (xgifb_info
->video_width
) {
1051 xgifb_reg_set(XGIPART2
,
1054 xgifb_reg_set(XGIPART2
,
1057 xgifb_reg_set(XGIPART2
,
1060 xgifb_reg_set(XGIPART2
,
1065 xgifb_reg_set(XGIPART2
,
1068 xgifb_reg_set(XGIPART2
,
1071 xgifb_reg_set(XGIPART2
,
1074 xgifb_reg_set(XGIPART2
,
1079 xgifb_reg_set(XGIPART2
,
1082 xgifb_reg_set(XGIPART2
,
1085 xgifb_reg_set(XGIPART2
,
1088 xgifb_reg_set(XGIPART2
,
1096 if ((filter
>= 0) && (filter
<= 7)) {
1097 DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n",
1099 XGI_TV_filter
[filter_tb
].
1101 XGI_TV_filter
[filter_tb
].
1103 XGI_TV_filter
[filter_tb
].
1105 XGI_TV_filter
[filter_tb
].
1111 (XGI_TV_filter
[filter_tb
].
1112 filter
[filter
][0]));
1116 (XGI_TV_filter
[filter_tb
].
1117 filter
[filter
][1]));
1121 (XGI_TV_filter
[filter_tb
].
1122 filter
[filter
][2]));
1126 (XGI_TV_filter
[filter_tb
].
1127 filter
[filter
][3]));
1133 static int XGIfb_do_set_var(struct fb_var_screeninfo
*var
, int isactive
,
1134 struct fb_info
*info
)
1136 struct xgifb_video_info
*xgifb_info
= info
->par
;
1137 struct xgi_hw_device_info
*hw_info
= &xgifb_info
->hw_info
;
1138 unsigned int htotal
= var
->left_margin
+ var
->xres
+ var
->right_margin
1140 unsigned int vtotal
= var
->upper_margin
+ var
->yres
+ var
->lower_margin
1142 #if defined(__powerpc__)
1143 u8 sr_data
, cr_data
;
1145 unsigned int drate
= 0, hrate
= 0;
1148 /* unsigned char reg, reg1; */
1150 DEBUGPRN("Inside do_set_var");
1151 /* printk(KERN_DEBUG "XGIfb:var->yres=%d, var->upper_margin=%d, var->lower_margin=%d, var->vsync_len=%d\n", var->yres, var->upper_margin, var->lower_margin, var->vsync_len); */
1153 info
->var
.xres_virtual
= var
->xres_virtual
;
1154 info
->var
.yres_virtual
= var
->yres_virtual
;
1155 info
->var
.bits_per_pixel
= var
->bits_per_pixel
;
1157 if ((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
)
1159 else if ((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
)
1161 else if ((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1163 /* var->yres <<= 1; */
1166 if (!htotal
|| !vtotal
) {
1167 DPRINTK("XGIfb: Invalid 'var' information\n");
1169 } printk(KERN_DEBUG
"XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n",
1170 var
->pixclock
, htotal
, vtotal
);
1172 if (var
->pixclock
&& htotal
&& vtotal
) {
1173 drate
= 1000000000 / var
->pixclock
;
1174 hrate
= (drate
* 1000) / htotal
;
1175 xgifb_info
->refresh_rate
= (unsigned int) (hrate
* 2
1178 xgifb_info
->refresh_rate
= 60;
1181 printk(KERN_DEBUG
"XGIfb: Change mode to %dx%dx%d-%dHz\n",
1184 var
->bits_per_pixel
,
1185 xgifb_info
->refresh_rate
);
1187 old_mode
= xgifb_info
->mode_idx
;
1188 xgifb_info
->mode_idx
= 0;
1190 while ((XGIbios_mode
[xgifb_info
->mode_idx
].mode_no
!= 0) &&
1191 (XGIbios_mode
[xgifb_info
->mode_idx
].xres
<= var
->xres
)) {
1192 if ((XGIbios_mode
[xgifb_info
->mode_idx
].xres
== var
->xres
) &&
1193 (XGIbios_mode
[xgifb_info
->mode_idx
].yres
== var
->yres
) &&
1194 (XGIbios_mode
[xgifb_info
->mode_idx
].bpp
1195 == var
->bits_per_pixel
)) {
1199 xgifb_info
->mode_idx
++;
1203 xgifb_info
->mode_idx
= XGIfb_validate_mode(xgifb_info
,
1204 xgifb_info
->mode_idx
);
1206 xgifb_info
->mode_idx
= -1;
1208 if (xgifb_info
->mode_idx
< 0) {
1209 printk(KERN_ERR
"XGIfb: Mode %dx%dx%d not supported\n",
1210 var
->xres
, var
->yres
, var
->bits_per_pixel
);
1211 xgifb_info
->mode_idx
= old_mode
;
1215 if (XGIfb_search_refresh_rate(xgifb_info
,
1216 xgifb_info
->refresh_rate
) == 0) {
1217 xgifb_info
->rate_idx
=
1218 XGIbios_mode
[xgifb_info
->mode_idx
].rate_idx
;
1219 xgifb_info
->refresh_rate
= 60;
1224 XGIfb_pre_setmode(xgifb_info
);
1225 if (XGISetModeNew(hw_info
,
1226 XGIbios_mode
[xgifb_info
->mode_idx
].mode_no
)
1228 printk(KERN_ERR
"XGIfb: Setting mode[0x%x] failed\n",
1229 XGIbios_mode
[xgifb_info
->mode_idx
].mode_no
);
1232 info
->fix
.line_length
= ((info
->var
.xres_virtual
1233 * info
->var
.bits_per_pixel
) >> 6);
1235 xgifb_reg_set(XGISR
, IND_XGI_PASSWORD
, XGI_PASSWORD
);
1237 xgifb_reg_set(XGICR
, 0x13, (info
->fix
.line_length
& 0x00ff));
1238 xgifb_reg_set(XGISR
,
1240 (info
->fix
.line_length
& 0xff00) >> 8);
1242 XGIfb_post_setmode(xgifb_info
);
1244 DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d\n",
1245 XGIbios_mode
[xgifb_info
->mode_idx
].xres
,
1246 XGIbios_mode
[xgifb_info
->mode_idx
].yres
,
1247 XGIbios_mode
[xgifb_info
->mode_idx
].bpp
,
1248 xgifb_info
->refresh_rate
);
1250 xgifb_info
->video_bpp
= XGIbios_mode
[xgifb_info
->mode_idx
].bpp
;
1251 xgifb_info
->video_vwidth
= info
->var
.xres_virtual
;
1252 xgifb_info
->video_width
=
1253 XGIbios_mode
[xgifb_info
->mode_idx
].xres
;
1254 xgifb_info
->video_vheight
= info
->var
.yres_virtual
;
1255 xgifb_info
->video_height
=
1256 XGIbios_mode
[xgifb_info
->mode_idx
].yres
;
1257 xgifb_info
->org_x
= xgifb_info
->org_y
= 0;
1258 xgifb_info
->video_linelength
= info
->var
.xres_virtual
1259 * (xgifb_info
->video_bpp
>> 3);
1260 switch (xgifb_info
->video_bpp
) {
1262 xgifb_info
->DstColor
= 0x0000;
1263 xgifb_info
->XGI310_AccelDepth
= 0x00000000;
1264 xgifb_info
->video_cmap_len
= 256;
1265 #if defined(__powerpc__)
1266 cr_data
= xgifb_reg_get(XGICR
, 0x4D);
1267 xgifb_reg_set(XGICR
, 0x4D, (cr_data
& 0xE0));
1271 xgifb_info
->DstColor
= 0x8000;
1272 xgifb_info
->XGI310_AccelDepth
= 0x00010000;
1273 #if defined(__powerpc__)
1274 cr_data
= xgifb_reg_get(XGICR
, 0x4D);
1275 xgifb_reg_set(XGICR
, 0x4D, ((cr_data
& 0xE0) | 0x0B));
1277 xgifb_info
->video_cmap_len
= 16;
1280 xgifb_info
->DstColor
= 0xC000;
1281 xgifb_info
->XGI310_AccelDepth
= 0x00020000;
1282 xgifb_info
->video_cmap_len
= 16;
1283 #if defined(__powerpc__)
1284 cr_data
= xgifb_reg_get(XGICR
, 0x4D);
1285 xgifb_reg_set(XGICR
, 0x4D, ((cr_data
& 0xE0) | 0x15));
1289 xgifb_info
->video_cmap_len
= 16;
1290 printk(KERN_ERR
"XGIfb: Unsupported depth %d",
1291 xgifb_info
->video_bpp
);
1295 XGIfb_bpp_to_var(xgifb_info
, var
); /*update ARGB info*/
1296 DEBUGPRN("End of do_set_var");
1302 static int XGIfb_pan_var(struct xgifb_video_info
*xgifb_info
,
1303 struct fb_var_screeninfo
*var
)
1307 /* printk("Inside pan_var"); */
1309 if (var
->xoffset
> (var
->xres_virtual
- var
->xres
)) {
1310 /* printk("Pan: xo: %d xv %d xr %d\n",
1311 var->xoffset, var->xres_virtual, var->xres); */
1314 if (var
->yoffset
> (var
->yres_virtual
- var
->yres
)) {
1315 /* printk("Pan: yo: %d yv %d yr %d\n",
1316 var->yoffset, var->yres_virtual, var->yres); */
1319 base
= var
->yoffset
* var
->xres_virtual
+ var
->xoffset
;
1321 /* calculate base bpp dep. */
1322 switch (var
->bits_per_pixel
) {
1334 xgifb_reg_set(XGISR
, IND_XGI_PASSWORD
, XGI_PASSWORD
);
1336 xgifb_reg_set(XGICR
, 0x0D, base
& 0xFF);
1337 xgifb_reg_set(XGICR
, 0x0C, (base
>> 8) & 0xFF);
1338 xgifb_reg_set(XGISR
, 0x0D, (base
>> 16) & 0xFF);
1339 xgifb_reg_set(XGISR
, 0x37, (base
>> 24) & 0x03);
1340 xgifb_reg_and_or(XGISR
, 0x37, 0xDF, (base
>> 21) & 0x04);
1342 if (xgifb_info
->disp_state
& DISPTYPE_DISP2
) {
1343 xgifb_reg_or(XGIPART1
, IND_XGI_CRT2_WRITE_ENABLE_315
, 0x01);
1344 xgifb_reg_set(XGIPART1
, 0x06, (base
& 0xFF));
1345 xgifb_reg_set(XGIPART1
, 0x05, ((base
>> 8) & 0xFF));
1346 xgifb_reg_set(XGIPART1
, 0x04, ((base
>> 16) & 0xFF));
1347 xgifb_reg_and_or(XGIPART1
,
1350 ((base
>> 24) & 0x01) << 7);
1352 /* printk("End of pan_var"); */
1356 static int XGIfb_open(struct fb_info
*info
, int user
)
1361 static int XGIfb_release(struct fb_info
*info
, int user
)
1366 static int XGIfb_get_cmap_len(const struct fb_var_screeninfo
*var
)
1370 switch (var
->bits_per_pixel
) {
1384 static int XGIfb_setcolreg(unsigned regno
, unsigned red
, unsigned green
,
1385 unsigned blue
, unsigned transp
, struct fb_info
*info
)
1387 struct xgifb_video_info
*xgifb_info
= info
->par
;
1389 if (regno
>= XGIfb_get_cmap_len(&info
->var
))
1392 switch (info
->var
.bits_per_pixel
) {
1394 outb(regno
, XGIDACA
);
1395 outb((red
>> 10), XGIDACD
);
1396 outb((green
>> 10), XGIDACD
);
1397 outb((blue
>> 10), XGIDACD
);
1398 if (xgifb_info
->disp_state
& DISPTYPE_DISP2
) {
1399 outb(regno
, XGIDAC2A
);
1400 outb((red
>> 8), XGIDAC2D
);
1401 outb((green
>> 8), XGIDAC2D
);
1402 outb((blue
>> 8), XGIDAC2D
);
1406 ((u32
*) (info
->pseudo_palette
))[regno
] = ((red
& 0xf800))
1407 | ((green
& 0xfc00) >> 5) | ((blue
& 0xf800)
1414 ((u32
*) (info
->pseudo_palette
))[regno
] = (red
<< 16) | (green
1421 /* ----------- FBDev related routines for all series ---------- */
1423 static int XGIfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
1424 struct fb_info
*info
)
1426 struct xgifb_video_info
*xgifb_info
= info
->par
;
1428 DEBUGPRN("inside get_fix");
1429 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
1431 fix
->smem_start
= xgifb_info
->video_base
;
1433 fix
->smem_len
= xgifb_info
->video_size
;
1435 fix
->type
= FB_TYPE_PACKED_PIXELS
;
1437 if (xgifb_info
->video_bpp
== 8)
1438 fix
->visual
= FB_VISUAL_PSEUDOCOLOR
;
1440 fix
->visual
= FB_VISUAL_DIRECTCOLOR
;
1445 fix
->line_length
= xgifb_info
->video_linelength
;
1446 fix
->mmio_start
= xgifb_info
->mmio_base
;
1447 fix
->mmio_len
= xgifb_info
->mmio_size
;
1448 fix
->accel
= FB_ACCEL_XGI_XABRE
;
1450 DEBUGPRN("end of get_fix");
1454 static int XGIfb_set_par(struct fb_info
*info
)
1458 /* printk("XGIfb: inside set_par\n"); */
1459 err
= XGIfb_do_set_var(&info
->var
, 1, info
);
1462 XGIfb_get_fix(&info
->fix
, -1, info
);
1463 /* printk("XGIfb: end of set_par\n"); */
1467 static int XGIfb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
1469 struct xgifb_video_info
*xgifb_info
= info
->par
;
1470 unsigned int htotal
= var
->left_margin
+ var
->xres
+ var
->right_margin
1472 unsigned int vtotal
= 0;
1473 unsigned int drate
= 0, hrate
= 0;
1475 int refresh_rate
, search_idx
;
1477 DEBUGPRN("Inside check_var");
1479 if ((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
) {
1480 vtotal
= var
->upper_margin
+ var
->yres
+ var
->lower_margin
1483 } else if ((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1484 vtotal
= var
->upper_margin
+ var
->yres
+ var
->lower_margin
1487 } else if ((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1488 vtotal
= var
->upper_margin
+ (var
->yres
/ 2)
1489 + var
->lower_margin
+ var
->vsync_len
;
1491 vtotal
= var
->upper_margin
+ var
->yres
+ var
->lower_margin
1494 if (!(htotal
) || !(vtotal
))
1495 XGIFAIL("XGIfb: no valid timing data");
1497 if (var
->pixclock
&& htotal
&& vtotal
) {
1498 drate
= 1000000000 / var
->pixclock
;
1499 hrate
= (drate
* 1000) / htotal
;
1500 xgifb_info
->refresh_rate
=
1501 (unsigned int) (hrate
* 2 / vtotal
);
1503 "%s: pixclock = %d ,htotal=%d, vtotal=%d\n"
1504 "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1505 __func__
, var
->pixclock
, htotal
, vtotal
,
1506 __func__
, drate
, hrate
, xgifb_info
->refresh_rate
);
1508 xgifb_info
->refresh_rate
= 60;
1512 if ((var->pixclock) && (htotal)) {
1513 drate = 1E12 / var->pixclock;
1514 hrate = drate / htotal;
1515 refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1520 /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
1521 if ((var
->xres
== 1024) && (var
->yres
== 600))
1525 while ((XGIbios_mode
[search_idx
].mode_no
!= 0) &&
1526 (XGIbios_mode
[search_idx
].xres
<= var
->xres
)) {
1527 if ((XGIbios_mode
[search_idx
].xres
== var
->xres
) &&
1528 (XGIbios_mode
[search_idx
].yres
== var
->yres
) &&
1529 (XGIbios_mode
[search_idx
].bpp
== var
->bits_per_pixel
)) {
1530 if (XGIfb_validate_mode(xgifb_info
, search_idx
) > 0) {
1540 printk(KERN_ERR
"XGIfb: %dx%dx%d is no valid mode\n",
1541 var
->xres
, var
->yres
, var
->bits_per_pixel
);
1543 while (XGIbios_mode
[search_idx
].mode_no
!= 0) {
1544 if ((var
->xres
<= XGIbios_mode
[search_idx
].xres
) &&
1545 (var
->yres
<= XGIbios_mode
[search_idx
].yres
) &&
1546 (var
->bits_per_pixel
==
1547 XGIbios_mode
[search_idx
].bpp
)) {
1548 if (XGIfb_validate_mode(xgifb_info
,
1557 var
->xres
= XGIbios_mode
[search_idx
].xres
;
1558 var
->yres
= XGIbios_mode
[search_idx
].yres
;
1559 printk(KERN_DEBUG
"XGIfb: Adapted to mode %dx%dx%d\n",
1560 var
->xres
, var
->yres
, var
->bits_per_pixel
);
1563 printk(KERN_ERR
"XGIfb: Failed to find similar mode to %dx%dx%d\n",
1564 var
->xres
, var
->yres
, var
->bits_per_pixel
);
1569 /* TW: TODO: Check the refresh rate */
1571 /* Adapt RGB settings */
1572 XGIfb_bpp_to_var(xgifb_info
, var
);
1574 /* Sanity check for offsets */
1575 if (var
->xoffset
< 0)
1577 if (var
->yoffset
< 0)
1581 if (var
->xres
!= var
->xres_virtual
)
1582 var
->xres_virtual
= var
->xres
;
1583 if (var
->yres
!= var
->yres_virtual
)
1584 var
->yres_virtual
= var
->yres
;
1586 /* TW: Now patch yres_virtual if we use panning */
1587 /* May I do this? */
1588 /* var->yres_virtual = xgifb_info->heapstart /
1589 (var->xres * (var->bits_per_pixel >> 3)); */
1590 /* if (var->yres_virtual <= var->yres) { */
1591 /* TW: Paranoia check */
1592 /* var->yres_virtual = var->yres; */
1596 /* Truncate offsets to maximum if too high */
1597 if (var
->xoffset
> var
->xres_virtual
- var
->xres
)
1598 var
->xoffset
= var
->xres_virtual
- var
->xres
- 1;
1600 if (var
->yoffset
> var
->yres_virtual
- var
->yres
)
1601 var
->yoffset
= var
->yres_virtual
- var
->yres
- 1;
1603 /* Set everything else to 0 */
1604 var
->red
.msb_right
=
1605 var
->green
.msb_right
=
1606 var
->blue
.msb_right
=
1607 var
->transp
.offset
= var
->transp
.length
= var
->transp
.msb_right
= 0;
1609 DEBUGPRN("end of check_var");
1613 static int XGIfb_pan_display(struct fb_var_screeninfo
*var
,
1614 struct fb_info
*info
)
1617 struct xgifb_video_info
*xgifb_info
= info
->par
;
1619 /* printk("\nInside pan_display:\n"); */
1621 if (var
->xoffset
> (var
->xres_virtual
- var
->xres
))
1623 if (var
->yoffset
> (var
->yres_virtual
- var
->yres
))
1626 if (var
->vmode
& FB_VMODE_YWRAP
) {
1627 if (var
->yoffset
< 0 || var
->yoffset
>= info
->var
.yres_virtual
1631 if (var
->xoffset
+ info
->var
.xres
> info
->var
.xres_virtual
1632 || var
->yoffset
+ info
->var
.yres
1633 > info
->var
.yres_virtual
)
1636 err
= XGIfb_pan_var(xgifb_info
, var
);
1640 info
->var
.xoffset
= var
->xoffset
;
1641 info
->var
.yoffset
= var
->yoffset
;
1642 if (var
->vmode
& FB_VMODE_YWRAP
)
1643 info
->var
.vmode
|= FB_VMODE_YWRAP
;
1645 info
->var
.vmode
&= ~FB_VMODE_YWRAP
;
1647 /* printk("End of pan_display\n"); */
1651 static int XGIfb_blank(int blank
, struct fb_info
*info
)
1653 struct xgifb_video_info
*xgifb_info
= info
->par
;
1656 reg
= xgifb_reg_get(XGICR
, 0x17);
1663 xgifb_reg_set(XGICR
, 0x17, reg
);
1664 xgifb_reg_set(XGISR
, 0x00, 0x01); /* Synchronous Reset */
1665 xgifb_reg_set(XGISR
, 0x00, 0x03); /* End Reset */
1669 static struct fb_ops XGIfb_ops
= {
1670 .owner
= THIS_MODULE
,
1671 .fb_open
= XGIfb_open
,
1672 .fb_release
= XGIfb_release
,
1673 .fb_check_var
= XGIfb_check_var
,
1674 .fb_set_par
= XGIfb_set_par
,
1675 .fb_setcolreg
= XGIfb_setcolreg
,
1676 .fb_pan_display
= XGIfb_pan_display
,
1677 .fb_blank
= XGIfb_blank
,
1678 .fb_fillrect
= cfb_fillrect
,
1679 .fb_copyarea
= cfb_copyarea
,
1680 .fb_imageblit
= cfb_imageblit
,
1681 /* .fb_mmap = XGIfb_mmap, */
1684 /* ---------------- Chip generation dependent routines ---------------- */
1686 /* for XGI 315/550/650/740/330 */
1688 static int XGIfb_get_dram_size(struct xgifb_video_info
*xgifb_info
)
1694 /* xorg driver sets 32MB * 1 channel */
1695 if (xgifb_info
->chip
== XG27
)
1696 xgifb_reg_set(XGISR
, IND_XGI_DRAM_SIZE
, 0x51);
1698 reg
= xgifb_reg_get(XGISR
, IND_XGI_DRAM_SIZE
);
1699 switch ((reg
& XGI_DRAM_SIZE_MASK
) >> 4) {
1700 case XGI_DRAM_SIZE_1MB
:
1701 xgifb_info
->video_size
= 0x100000;
1703 case XGI_DRAM_SIZE_2MB
:
1704 xgifb_info
->video_size
= 0x200000;
1706 case XGI_DRAM_SIZE_4MB
:
1707 xgifb_info
->video_size
= 0x400000;
1709 case XGI_DRAM_SIZE_8MB
:
1710 xgifb_info
->video_size
= 0x800000;
1712 case XGI_DRAM_SIZE_16MB
:
1713 xgifb_info
->video_size
= 0x1000000;
1715 case XGI_DRAM_SIZE_32MB
:
1716 xgifb_info
->video_size
= 0x2000000;
1718 case XGI_DRAM_SIZE_64MB
:
1719 xgifb_info
->video_size
= 0x4000000;
1721 case XGI_DRAM_SIZE_128MB
:
1722 xgifb_info
->video_size
= 0x8000000;
1724 case XGI_DRAM_SIZE_256MB
:
1725 xgifb_info
->video_size
= 0x10000000;
1731 tmp
= (reg
& 0x0c) >> 2;
1732 switch (xgifb_info
->chip
) {
1768 xgifb_info
->video_size
= xgifb_info
->video_size
* ChannelNum
;
1769 /* PLiad fixed for benchmarking and fb set */
1770 /* xgifb_info->video_size = 0x200000; */ /* 1024x768x16 */
1771 /* xgifb_info->video_size = 0x1000000; */ /* benchmark */
1773 printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n",
1775 xgifb_info
->video_size
, ChannelNum
);
1780 static void XGIfb_detect_VB(struct xgifb_video_info
*xgifb_info
)
1784 xgifb_info
->TV_plug
= xgifb_info
->TV_type
= 0;
1786 switch (xgifb_info
->hasVB
) {
1787 case HASVB_LVDS_CHRONTEL
:
1788 case HASVB_CHRONTEL
:
1792 /* XGI_Sense30x(); */ /* Yi-Lin TV Sense? */
1796 cr32
= xgifb_reg_get(XGICR
, IND_XGI_SCRATCH_REG_CR32
);
1798 if ((cr32
& XGI_CRT1
) && !XGIfb_crt1off
)
1807 if (XGIfb_crt2type
!= -1)
1808 /* TW: Override with option */
1809 xgifb_info
->disp_state
= XGIfb_crt2type
;
1810 else if (cr32
& XGI_VB_TV
)
1811 xgifb_info
->disp_state
= DISPTYPE_TV
;
1812 else if (cr32
& XGI_VB_LCD
)
1813 xgifb_info
->disp_state
= DISPTYPE_LCD
;
1814 else if (cr32
& XGI_VB_CRT2
)
1815 xgifb_info
->disp_state
= DISPTYPE_CRT2
;
1817 xgifb_info
->disp_state
= 0;
1819 if (XGIfb_tvplug
!= -1)
1820 /* PR/TW: Override with option */
1821 xgifb_info
->TV_plug
= XGIfb_tvplug
;
1822 else if (cr32
& XGI_VB_HIVISION
) {
1823 xgifb_info
->TV_type
= TVMODE_HIVISION
;
1824 xgifb_info
->TV_plug
= TVPLUG_SVIDEO
;
1825 } else if (cr32
& XGI_VB_SVIDEO
)
1826 xgifb_info
->TV_plug
= TVPLUG_SVIDEO
;
1827 else if (cr32
& XGI_VB_COMPOSITE
)
1828 xgifb_info
->TV_plug
= TVPLUG_COMPOSITE
;
1829 else if (cr32
& XGI_VB_SCART
)
1830 xgifb_info
->TV_plug
= TVPLUG_SCART
;
1832 if (xgifb_info
->TV_type
== 0) {
1833 temp
= xgifb_reg_get(XGICR
, 0x38);
1835 xgifb_info
->TV_type
= TVMODE_PAL
;
1837 xgifb_info
->TV_type
= TVMODE_NTSC
;
1840 /* TW: Copy forceCRT1 option to CRT1off if option is given */
1841 if (XGIfb_forcecrt1
!= -1) {
1842 if (XGIfb_forcecrt1
)
1849 static int XGIfb_has_VB(struct xgifb_video_info
*xgifb_info
)
1853 vb_chipid
= xgifb_reg_get(XGIPART4
, 0x00);
1854 switch (vb_chipid
) {
1856 xgifb_info
->hasVB
= HASVB_301
;
1859 xgifb_info
->hasVB
= HASVB_302
;
1862 xgifb_info
->hasVB
= HASVB_NONE
;
1868 static void XGIfb_get_VB_type(struct xgifb_video_info
*xgifb_info
)
1872 if (!XGIfb_has_VB(xgifb_info
)) {
1873 reg
= xgifb_reg_get(XGICR
, IND_XGI_SCRATCH_REG_CR37
);
1874 switch ((reg
& XGI_EXTERNAL_CHIP_MASK
) >> 1) {
1875 case XGI310_EXTERNAL_CHIP_LVDS
:
1876 xgifb_info
->hasVB
= HASVB_LVDS
;
1878 case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL
:
1879 xgifb_info
->hasVB
= HASVB_LVDS_CHRONTEL
;
1887 static int __init
xgifb_optval(char *fullopt
, int validx
)
1891 if (kstrtoul(fullopt
+ validx
, 0, &lres
) < 0 || lres
> INT_MAX
) {
1892 pr_err("xgifb: invalid value for option: %s\n", fullopt
);
1898 static int __init
XGIfb_setup(char *options
)
1902 if (!options
|| !*options
)
1905 pr_info("xgifb: options: %s\n", options
);
1907 while ((this_opt
= strsep(&options
, ",")) != NULL
) {
1912 if (!strncmp(this_opt
, "mode:", 5)) {
1913 mode
= this_opt
+ 5;
1914 } else if (!strncmp(this_opt
, "vesa:", 5)) {
1915 vesa
= xgifb_optval(this_opt
, 5);
1916 } else if (!strncmp(this_opt
, "vrate:", 6)) {
1917 refresh_rate
= xgifb_optval(this_opt
, 6);
1918 } else if (!strncmp(this_opt
, "rate:", 5)) {
1919 refresh_rate
= xgifb_optval(this_opt
, 5);
1920 } else if (!strncmp(this_opt
, "crt1off", 7)) {
1922 } else if (!strncmp(this_opt
, "filter:", 7)) {
1923 filter
= xgifb_optval(this_opt
, 7);
1924 } else if (!strncmp(this_opt
, "forcecrt2type:", 14)) {
1925 XGIfb_search_crt2type(this_opt
+ 14);
1926 } else if (!strncmp(this_opt
, "forcecrt1:", 10)) {
1927 XGIfb_forcecrt1
= xgifb_optval(this_opt
, 10);
1928 } else if (!strncmp(this_opt
, "tvmode:", 7)) {
1929 XGIfb_search_tvstd(this_opt
+ 7);
1930 } else if (!strncmp(this_opt
, "tvstandard:", 11)) {
1931 XGIfb_search_tvstd(this_opt
+ 7);
1932 } else if (!strncmp(this_opt
, "dstn", 4)) {
1934 /* TW: DSTN overrules forcecrt2type */
1935 XGIfb_crt2type
= DISPTYPE_LCD
;
1936 } else if (!strncmp(this_opt
, "noypan", 6)) {
1938 } else if (!strncmp(this_opt
, "userom:", 7)) {
1939 XGIfb_userom
= xgifb_optval(this_opt
, 7);
1947 static unsigned char *xgifb_copy_rom(struct pci_dev
*dev
)
1949 void __iomem
*rom_address
;
1950 unsigned char *rom_copy
;
1953 rom_address
= pci_map_rom(dev
, &rom_size
);
1954 if (rom_address
== NULL
)
1957 rom_copy
= vzalloc(XGIFB_ROM_SIZE
);
1958 if (rom_copy
== NULL
)
1961 rom_size
= min_t(size_t, rom_size
, XGIFB_ROM_SIZE
);
1962 memcpy_fromio(rom_copy
, rom_address
, rom_size
);
1965 pci_unmap_rom(dev
, rom_address
);
1969 static int __devinit
xgifb_probe(struct pci_dev
*pdev
,
1970 const struct pci_device_id
*ent
)
1975 bool xgi21_drvlcdcaplist
= false;
1976 struct fb_info
*fb_info
;
1977 struct xgifb_video_info
*xgifb_info
;
1978 struct xgi_hw_device_info
*hw_info
;
1980 fb_info
= framebuffer_alloc(sizeof(*xgifb_info
), &pdev
->dev
);
1984 xgifb_info
= fb_info
->par
;
1985 hw_info
= &xgifb_info
->hw_info
;
1986 xgifb_info
->fb_info
= fb_info
;
1987 xgifb_info
->chip_id
= pdev
->device
;
1988 pci_read_config_byte(pdev
,
1990 &xgifb_info
->revision_id
);
1991 hw_info
->jChipRevision
= xgifb_info
->revision_id
;
1993 xgifb_info
->pcibus
= pdev
->bus
->number
;
1994 xgifb_info
->pcislot
= PCI_SLOT(pdev
->devfn
);
1995 xgifb_info
->pcifunc
= PCI_FUNC(pdev
->devfn
);
1996 xgifb_info
->subsysvendor
= pdev
->subsystem_vendor
;
1997 xgifb_info
->subsysdevice
= pdev
->subsystem_device
;
1999 xgifb_info
->video_base
= pci_resource_start(pdev
, 0);
2000 xgifb_info
->mmio_base
= pci_resource_start(pdev
, 1);
2001 xgifb_info
->mmio_size
= pci_resource_len(pdev
, 1);
2002 xgifb_info
->vga_base
= pci_resource_start(pdev
, 2) + 0x30;
2003 hw_info
->pjIOAddress
= (unsigned char *)xgifb_info
->vga_base
;
2004 /* XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30; */
2005 printk("XGIfb: Relocate IO address: %lx [%08lx]\n",
2006 (unsigned long)pci_resource_start(pdev
, 2),
2007 xgifb_info
->dev_info
.RelIO
);
2009 if (pci_enable_device(pdev
)) {
2014 XGIRegInit(&xgifb_info
->dev_info
, (unsigned long)hw_info
->pjIOAddress
);
2016 xgifb_reg_set(XGISR
, IND_XGI_PASSWORD
, XGI_PASSWORD
);
2017 reg1
= xgifb_reg_get(XGISR
, IND_XGI_PASSWORD
);
2019 if (reg1
!= 0xa1) { /*I/O error */
2020 printk("\nXGIfb: I/O error!!!");
2025 switch (xgifb_info
->chip_id
) {
2026 case PCI_DEVICE_ID_XG_20
:
2027 xgifb_reg_or(XGICR
, Index_CR_GPIO_Reg3
, GPIOG_EN
);
2028 CR48
= xgifb_reg_get(XGICR
, Index_CR_GPIO_Reg1
);
2029 if (CR48
&GPIOG_READ
)
2030 xgifb_info
->chip
= XG21
;
2032 xgifb_info
->chip
= XG20
;
2034 case PCI_DEVICE_ID_XG_40
:
2035 xgifb_info
->chip
= XG40
;
2037 case PCI_DEVICE_ID_XG_41
:
2038 xgifb_info
->chip
= XG41
;
2040 case PCI_DEVICE_ID_XG_42
:
2041 xgifb_info
->chip
= XG42
;
2043 case PCI_DEVICE_ID_XG_27
:
2044 xgifb_info
->chip
= XG27
;
2051 printk("XGIfb:chipid = %x\n", xgifb_info
->chip
);
2052 hw_info
->jChipType
= xgifb_info
->chip
;
2054 if ((xgifb_info
->chip
== XG21
) || (XGIfb_userom
)) {
2055 hw_info
->pjVirtualRomBase
= xgifb_copy_rom(pdev
);
2056 if (hw_info
->pjVirtualRomBase
)
2057 printk(KERN_INFO
"XGIfb: Video ROM found and mapped to %p\n",
2058 hw_info
->pjVirtualRomBase
);
2060 printk(KERN_INFO
"XGIfb: Video ROM not found\n");
2062 hw_info
->pjVirtualRomBase
= NULL
;
2063 printk(KERN_INFO
"XGIfb: Video ROM usage disabled\n");
2066 if (XGIfb_get_dram_size(xgifb_info
)) {
2067 printk(KERN_INFO
"XGIfb: Fatal error: Unable to determine RAM size.\n");
2072 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
2074 IND_XGI_PCI_ADDRESS_SET
,
2075 (XGI_PCI_ADDR_ENABLE
| XGI_MEM_MAP_IO_ENABLE
));
2076 /* Enable 2D accelerator engine */
2077 xgifb_reg_or(XGISR
, IND_XGI_MODULE_ENABLE
, XGI_ENABLE_2D
);
2079 hw_info
->ulVideoMemorySize
= xgifb_info
->video_size
;
2081 if (!request_mem_region(xgifb_info
->video_base
,
2082 xgifb_info
->video_size
,
2084 printk("unable request memory size %x",
2085 xgifb_info
->video_size
);
2086 printk(KERN_ERR
"XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
2087 printk(KERN_ERR
"XGIfb: Is there another framebuffer driver active?\n");
2092 if (!request_mem_region(xgifb_info
->mmio_base
,
2093 xgifb_info
->mmio_size
,
2095 printk(KERN_ERR
"XGIfb: Fatal error: Unable to reserve MMIO region\n");
2100 xgifb_info
->video_vbase
= hw_info
->pjVideoMemoryAddress
=
2101 ioremap(xgifb_info
->video_base
, xgifb_info
->video_size
);
2102 xgifb_info
->mmio_vbase
= ioremap(xgifb_info
->mmio_base
,
2103 xgifb_info
->mmio_size
);
2105 printk(KERN_INFO
"XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
2106 xgifb_info
->video_base
,
2107 xgifb_info
->video_vbase
,
2108 xgifb_info
->video_size
/ 1024);
2110 printk(KERN_INFO
"XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
2111 xgifb_info
->mmio_base
, xgifb_info
->mmio_vbase
,
2112 xgifb_info
->mmio_size
/ 1024);
2113 printk("XGIfb: XGIInitNew() ...");
2114 pci_set_drvdata(pdev
, xgifb_info
);
2115 if (XGIInitNew(pdev
))
2120 xgifb_info
->mtrr
= (unsigned int) 0;
2122 xgifb_info
->hasVB
= HASVB_NONE
;
2123 if ((xgifb_info
->chip
== XG20
) ||
2124 (xgifb_info
->chip
== XG27
)) {
2125 xgifb_info
->hasVB
= HASVB_NONE
;
2126 } else if (xgifb_info
->chip
== XG21
) {
2127 CR38
= xgifb_reg_get(XGICR
, 0x38);
2128 if ((CR38
&0xE0) == 0xC0) {
2129 xgifb_info
->disp_state
= DISPTYPE_LCD
;
2130 if (!XGIfb_GetXG21LVDSData(xgifb_info
))
2131 xgi21_drvlcdcaplist
= true;
2132 } else if ((CR38
&0xE0) == 0x60) {
2133 xgifb_info
->hasVB
= HASVB_CHRONTEL
;
2135 xgifb_info
->hasVB
= HASVB_NONE
;
2138 XGIfb_get_VB_type(xgifb_info
);
2141 hw_info
->ujVBChipID
= VB_CHIP_UNKNOWN
;
2143 hw_info
->ulExternalChip
= 0;
2145 switch (xgifb_info
->hasVB
) {
2147 reg
= xgifb_reg_get(XGIPART4
, 0x01);
2149 hw_info
->ujVBChipID
= VB_CHIP_302LV
;
2150 printk(KERN_INFO
"XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg
);
2151 } else if (reg
>= 0xD0) {
2152 hw_info
->ujVBChipID
= VB_CHIP_301LV
;
2153 printk(KERN_INFO
"XGIfb: XGI301LV bridge detected (revision 0x%02x)\n", reg
);
2155 /* else if (reg >= 0xB0) {
2156 hw_info->ujVBChipID = VB_CHIP_301B;
2157 reg1 = xgifb_reg_get(XGIPART4, 0x23);
2158 printk("XGIfb: XGI301B bridge detected\n");
2161 hw_info
->ujVBChipID
= VB_CHIP_301
;
2162 printk("XGIfb: XGI301 bridge detected\n");
2166 reg
= xgifb_reg_get(XGIPART4
, 0x01);
2168 hw_info
->ujVBChipID
= VB_CHIP_302LV
;
2169 printk(KERN_INFO
"XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg
);
2170 } else if (reg
>= 0xD0) {
2171 hw_info
->ujVBChipID
= VB_CHIP_301LV
;
2172 printk(KERN_INFO
"XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg
);
2173 } else if (reg
>= 0xB0) {
2174 reg1
= xgifb_reg_get(XGIPART4
, 0x23);
2176 hw_info
->ujVBChipID
= VB_CHIP_302B
;
2179 hw_info
->ujVBChipID
= VB_CHIP_302
;
2180 printk(KERN_INFO
"XGIfb: XGI302 bridge detected\n");
2184 hw_info
->ulExternalChip
= 0x1;
2185 printk(KERN_INFO
"XGIfb: LVDS transmitter detected\n");
2187 case HASVB_TRUMPION
:
2188 hw_info
->ulExternalChip
= 0x2;
2189 printk(KERN_INFO
"XGIfb: Trumpion Zurac LVDS scaler detected\n");
2191 case HASVB_CHRONTEL
:
2192 hw_info
->ulExternalChip
= 0x4;
2193 printk(KERN_INFO
"XGIfb: Chrontel TV encoder detected\n");
2195 case HASVB_LVDS_CHRONTEL
:
2196 hw_info
->ulExternalChip
= 0x5;
2197 printk(KERN_INFO
"XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
2200 printk(KERN_INFO
"XGIfb: No or unknown bridge type detected\n");
2204 if (xgifb_info
->hasVB
!= HASVB_NONE
)
2205 XGIfb_detect_VB(xgifb_info
);
2207 if (xgifb_info
->disp_state
& DISPTYPE_LCD
) {
2209 reg
= xgifb_reg_get(XGICR
, IND_XGI_LCD_PANEL
);
2211 hw_info
->ulCRT2LCDType
= XGI310paneltype
[reg
];
2215 hw_info
->ulCRT2LCDType
= LCD_320x480
;
2219 if ((hw_info
->ujVBChipID
== VB_CHIP_302B
) ||
2220 (hw_info
->ujVBChipID
== VB_CHIP_301LV
) ||
2221 (hw_info
->ujVBChipID
== VB_CHIP_302LV
)) {
2223 tmp
= xgifb_reg_get(XGICR
, 0x34);
2225 /* Currently on LCDA?
2226 *(Some BIOSes leave CR38) */
2227 tmp
= xgifb_reg_get(XGICR
, 0x38);
2228 if ((tmp
& 0x03) == 0x03) {
2229 /* XGI_Pr.XGI_UseLCDA = 1; */
2231 /* Currently on LCDA?
2232 *(Some newer BIOSes set D0 in CR35) */
2233 tmp
= xgifb_reg_get(XGICR
, 0x35);
2235 /* XGI_Pr.XGI_UseLCDA = 1; */
2237 tmp
= xgifb_reg_get(XGICR
,
2240 tmp
= xgifb_reg_get(
2243 /* XGI_Pr.XGI_UseLCDA = 1; */
2252 xgifb_info
->mode_idx
= -1;
2255 XGIfb_search_mode(xgifb_info
, mode
);
2256 else if (vesa
!= -1)
2257 XGIfb_search_vesamode(xgifb_info
, vesa
);
2259 if (xgifb_info
->mode_idx
>= 0)
2260 xgifb_info
->mode_idx
=
2261 XGIfb_validate_mode(xgifb_info
, xgifb_info
->mode_idx
);
2263 if (xgifb_info
->mode_idx
< 0) {
2264 if ((xgifb_info
->disp_state
& DISPTYPE_DISP2
) ==
2266 xgifb_info
->chip
== XG21
)
2267 xgifb_info
->mode_idx
=
2268 XGIfb_GetXG21DefaultLVDSModeIdx();
2270 xgifb_info
->mode_idx
= DEFAULT_MODE
;
2273 if (xgifb_info
->mode_idx
< 0) {
2274 dev_err(&pdev
->dev
, "no supported video mode found\n");
2278 if (xgi21_drvlcdcaplist
) {
2281 for (m
= 0; m
< ARRAY_SIZE(XGI21_LCDCapList
); m
++)
2282 if ((XGI21_LCDCapList
[m
].LVDSHDE
==
2283 XGIbios_mode
[xgifb_info
->mode_idx
].xres
) &&
2284 (XGI21_LCDCapList
[m
].LVDSVDE
==
2285 XGIbios_mode
[xgifb_info
->mode_idx
].yres
)) {
2286 xgifb_reg_set(xgifb_info
->dev_info
.P3d4
,
2293 /* yilin set default refresh rate */
2294 xgifb_info
->refresh_rate
= refresh_rate
;
2295 if (xgifb_info
->refresh_rate
== 0)
2296 xgifb_info
->refresh_rate
= 60;
2297 if (XGIfb_search_refresh_rate(xgifb_info
,
2298 xgifb_info
->refresh_rate
) == 0) {
2299 xgifb_info
->rate_idx
=
2300 XGIbios_mode
[xgifb_info
->mode_idx
].rate_idx
;
2301 xgifb_info
->refresh_rate
= 60;
2304 xgifb_info
->video_bpp
= XGIbios_mode
[xgifb_info
->mode_idx
].bpp
;
2305 xgifb_info
->video_vwidth
=
2306 xgifb_info
->video_width
=
2307 XGIbios_mode
[xgifb_info
->mode_idx
].xres
;
2308 xgifb_info
->video_vheight
=
2309 xgifb_info
->video_height
=
2310 XGIbios_mode
[xgifb_info
->mode_idx
].yres
;
2311 xgifb_info
->org_x
= xgifb_info
->org_y
= 0;
2312 xgifb_info
->video_linelength
=
2313 xgifb_info
->video_width
*
2314 (xgifb_info
->video_bpp
>> 3);
2315 switch (xgifb_info
->video_bpp
) {
2317 xgifb_info
->DstColor
= 0x0000;
2318 xgifb_info
->XGI310_AccelDepth
= 0x00000000;
2319 xgifb_info
->video_cmap_len
= 256;
2322 xgifb_info
->DstColor
= 0x8000;
2323 xgifb_info
->XGI310_AccelDepth
= 0x00010000;
2324 xgifb_info
->video_cmap_len
= 16;
2327 xgifb_info
->DstColor
= 0xC000;
2328 xgifb_info
->XGI310_AccelDepth
= 0x00020000;
2329 xgifb_info
->video_cmap_len
= 16;
2332 xgifb_info
->video_cmap_len
= 16;
2333 printk(KERN_INFO
"XGIfb: Unsupported depth %d",
2334 xgifb_info
->video_bpp
);
2338 printk(KERN_INFO
"XGIfb: Default mode is %dx%dx%d (%dHz)\n",
2339 xgifb_info
->video_width
,
2340 xgifb_info
->video_height
,
2341 xgifb_info
->video_bpp
,
2342 xgifb_info
->refresh_rate
);
2344 fb_info
->var
.red
.length
= 8;
2345 fb_info
->var
.green
.length
= 8;
2346 fb_info
->var
.blue
.length
= 8;
2347 fb_info
->var
.activate
= FB_ACTIVATE_NOW
;
2348 fb_info
->var
.height
= -1;
2349 fb_info
->var
.width
= -1;
2350 fb_info
->var
.vmode
= FB_VMODE_NONINTERLACED
;
2351 fb_info
->var
.xres
= xgifb_info
->video_width
;
2352 fb_info
->var
.xres_virtual
= xgifb_info
->video_width
;
2353 fb_info
->var
.yres
= xgifb_info
->video_height
;
2354 fb_info
->var
.yres_virtual
= xgifb_info
->video_height
;
2355 fb_info
->var
.bits_per_pixel
= xgifb_info
->video_bpp
;
2357 XGIfb_bpp_to_var(xgifb_info
, &fb_info
->var
);
2359 fb_info
->var
.pixclock
= (u32
) (1000000000 /
2360 XGIfb_mode_rate_to_dclock(&xgifb_info
->dev_info
,
2362 XGIbios_mode
[xgifb_info
->mode_idx
].mode_no
,
2363 xgifb_info
->rate_idx
));
2365 if (XGIfb_mode_rate_to_ddata(&xgifb_info
->dev_info
, hw_info
,
2366 XGIbios_mode
[xgifb_info
->mode_idx
].mode_no
,
2367 xgifb_info
->rate_idx
,
2368 &fb_info
->var
.left_margin
,
2369 &fb_info
->var
.right_margin
,
2370 &fb_info
->var
.upper_margin
,
2371 &fb_info
->var
.lower_margin
,
2372 &fb_info
->var
.hsync_len
,
2373 &fb_info
->var
.vsync_len
,
2375 &fb_info
->var
.vmode
)) {
2377 if ((fb_info
->var
.vmode
& FB_VMODE_MASK
) ==
2378 FB_VMODE_INTERLACED
) {
2379 fb_info
->var
.yres
<<= 1;
2380 fb_info
->var
.yres_virtual
<<= 1;
2381 } else if ((fb_info
->var
.vmode
& FB_VMODE_MASK
) ==
2383 fb_info
->var
.pixclock
>>= 1;
2384 fb_info
->var
.yres
>>= 1;
2385 fb_info
->var
.yres_virtual
>>= 1;
2390 strncpy(fb_info
->fix
.id
, "XGI", sizeof(fb_info
->fix
.id
) - 1);
2391 fb_info
->fix
.type
= FB_TYPE_PACKED_PIXELS
;
2392 fb_info
->fix
.xpanstep
= 1;
2393 fb_info
->fix
.ypanstep
= 1;
2395 fb_info
->flags
= FBINFO_FLAG_DEFAULT
;
2396 fb_info
->screen_base
= xgifb_info
->video_vbase
;
2397 fb_info
->fbops
= &XGIfb_ops
;
2398 XGIfb_get_fix(&fb_info
->fix
, -1, fb_info
);
2399 fb_info
->pseudo_palette
= xgifb_info
->pseudo_palette
;
2401 fb_alloc_cmap(&fb_info
->cmap
, 256 , 0);
2404 xgifb_info
->mtrr
= mtrr_add(xgifb_info
->video_base
,
2405 xgifb_info
->video_size
, MTRR_TYPE_WRCOMB
, 1);
2406 if (xgifb_info
->mtrr
>= 0)
2407 dev_info(&pdev
->dev
, "added MTRR\n");
2410 if (register_framebuffer(fb_info
) < 0) {
2421 if (xgifb_info
->mtrr
>= 0)
2422 mtrr_del(xgifb_info
->mtrr
, xgifb_info
->video_base
,
2423 xgifb_info
->video_size
);
2424 #endif /* CONFIG_MTRR */
2426 iounmap(xgifb_info
->mmio_vbase
);
2427 iounmap(xgifb_info
->video_vbase
);
2428 release_mem_region(xgifb_info
->mmio_base
, xgifb_info
->mmio_size
);
2430 release_mem_region(xgifb_info
->video_base
, xgifb_info
->video_size
);
2432 vfree(hw_info
->pjVirtualRomBase
);
2433 framebuffer_release(fb_info
);
2437 /*****************************************************/
2438 /* PCI DEVICE HANDLING */
2439 /*****************************************************/
2441 static void __devexit
xgifb_remove(struct pci_dev
*pdev
)
2443 struct xgifb_video_info
*xgifb_info
= pci_get_drvdata(pdev
);
2444 struct fb_info
*fb_info
= xgifb_info
->fb_info
;
2446 unregister_framebuffer(fb_info
);
2448 if (xgifb_info
->mtrr
>= 0)
2449 mtrr_del(xgifb_info
->mtrr
, xgifb_info
->video_base
,
2450 xgifb_info
->video_size
);
2451 #endif /* CONFIG_MTRR */
2452 iounmap(xgifb_info
->mmio_vbase
);
2453 iounmap(xgifb_info
->video_vbase
);
2454 release_mem_region(xgifb_info
->mmio_base
, xgifb_info
->mmio_size
);
2455 release_mem_region(xgifb_info
->video_base
, xgifb_info
->video_size
);
2456 vfree(xgifb_info
->hw_info
.pjVirtualRomBase
);
2457 framebuffer_release(fb_info
);
2458 pci_set_drvdata(pdev
, NULL
);
2461 static struct pci_driver xgifb_driver
= {
2463 .id_table
= xgifb_pci_table
,
2464 .probe
= xgifb_probe
,
2465 .remove
= __devexit_p(xgifb_remove
)
2468 static int __init
xgifb_init(void)
2470 char *option
= NULL
;
2472 if (fb_get_options("xgifb", &option
))
2474 XGIfb_setup(option
);
2476 return pci_register_driver(&xgifb_driver
);
2479 module_init(xgifb_init
);
2481 /*****************************************************/
2483 /*****************************************************/
2487 MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
2488 MODULE_LICENSE("GPL");
2489 MODULE_AUTHOR("XGITECH , Others");
2491 module_param(mode
, charp
, 0);
2492 module_param(vesa
, int, 0);
2493 module_param(filter
, int, 0);
2495 MODULE_PARM_DESC(mode
,
2496 "\nSelects the desired default display mode in the format XxYxDepth,\n"
2497 "eg. 1024x768x16.\n");
2499 MODULE_PARM_DESC(vesa
,
2500 "\nSelects the desired default display mode by VESA mode number, eg.\n"
2503 MODULE_PARM_DESC(filter
,
2504 "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
2505 "(Possible values 0-7, default: [no filter])\n");
2507 static void __exit
xgifb_remove_module(void)
2509 pci_unregister_driver(&xgifb_driver
);
2510 printk(KERN_DEBUG
"xgifb: Module unloaded\n");
2513 module_exit(xgifb_remove_module
);
2515 #endif /* /MODULE */