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/version.h>
9 #include <linux/module.h>
10 #include <linux/moduleparam.h>
11 #include <linux/kernel.h>
12 #include <linux/spinlock.h>
13 #include <linux/errno.h>
14 #include <linux/string.h>
16 #include <linux/tty.h>
17 #include <linux/slab.h>
18 #include <linux/delay.h>
20 #include <linux/console.h>
21 #include <linux/selection.h>
22 #include <linux/ioport.h>
23 #include <linux/init.h>
24 #include <linux/pci.h>
25 #include <linux/vmalloc.h>
26 #include <linux/vt_kern.h>
27 #include <linux/capability.h>
29 #include <linux/types.h>
30 #include <linux/proc_fs.h>
48 #define Index_CR_GPIO_Reg1 0x48
49 #define Index_CR_GPIO_Reg2 0x49
50 #define Index_CR_GPIO_Reg3 0x4a
52 #define GPIOG_EN (1<<6)
53 #define GPIOG_WRITE (1<<6)
54 #define GPIOG_READ (1<<1)
55 int XGIfb_GetXG21DefaultLVDSModeIdx(void);
57 /* -------------------- Macro definitions ---------------------------- */
62 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
64 #define DPRINTK(fmt, args...)
68 static void dumpVGAReg(void)
72 outXGIIDXREG(XGISR
, 0x05, 0x86);
74 outXGIIDXREG(XGISR, 0x08, 0x4f);
75 outXGIIDXREG(XGISR, 0x0f, 0x20);
76 outXGIIDXREG(XGISR, 0x11, 0x4f);
77 outXGIIDXREG(XGISR, 0x13, 0x45);
78 outXGIIDXREG(XGISR, 0x14, 0x51);
79 outXGIIDXREG(XGISR, 0x1e, 0x41);
80 outXGIIDXREG(XGISR, 0x1f, 0x0);
81 outXGIIDXREG(XGISR, 0x20, 0xa1);
82 outXGIIDXREG(XGISR, 0x22, 0xfb);
83 outXGIIDXREG(XGISR, 0x26, 0x22);
84 outXGIIDXREG(XGISR, 0x3e, 0x07);
87 //outXGIIDXREG(XGICR, 0x19, 0x00);
88 //outXGIIDXREG(XGICR, 0x1a, 0x3C);
89 //outXGIIDXREG(XGICR, 0x22, 0xff);
90 //outXGIIDXREG(XGICR, 0x3D, 0x10);
92 //outXGIIDXREG(XGICR, 0x4a, 0xf3);
94 //outXGIIDXREG(XGICR, 0x57, 0x0);
95 //outXGIIDXREG(XGICR, 0x7a, 0x2c);
97 //outXGIIDXREG(XGICR, 0x82, 0xcc);
98 //outXGIIDXREG(XGICR, 0x8c, 0x0);
100 outXGIIDXREG(XGICR, 0x99, 0x1);
101 outXGIIDXREG(XGICR, 0x41, 0x40);
104 for(i
=0; i
< 0x4f; i
++)
106 inXGIIDXREG(XGISR
, i
, reg
);
107 printk("\no 3c4 %x",i
);
108 printk("\ni 3c5 => %x",reg
);
111 for(i
=0; i
< 0xF0; i
++)
113 inXGIIDXREG(XGICR
, i
, reg
);
114 printk("\no 3d4 %x",i
);
115 printk("\ni 3d5 => %x",reg
);
119 outXGIIDXREG(XGIPART1,0x2F,1);
120 for(i=1; i < 0x50; i++)
122 inXGIIDXREG(XGIPART1, i, reg);
123 printk("\no d004 %x",i);
124 printk("\ni d005 => %x",reg);
127 for(i=0; i < 0x50; i++)
129 inXGIIDXREG(XGIPART2, i, reg);
130 printk("\no d010 %x",i);
131 printk("\ni d011 => %x",reg);
133 for(i=0; i < 0x50; i++)
135 inXGIIDXREG(XGIPART3, i, reg);
136 printk("\no d012 %x",i);
137 printk("\ni d013 => %x",reg);
139 for(i=0; i < 0x50; i++)
141 inXGIIDXREG(XGIPART4, i, reg);
142 printk("\no d014 %x",i);
143 printk("\ni d015 => %x",reg);
148 static inline void dumpVGAReg(void) {}
151 /* data for XGI components */
152 struct video_info xgi_video_info
;
158 /* --------------- Hardware Access Routines -------------------------- */
161 XGIfb_mode_rate_to_dclock(struct vb_device_info
*XGI_Pr
, struct xgi_hw_device_info
*HwDeviceExtension
,
162 unsigned char modeno
, unsigned char rateindex
)
164 unsigned short ModeNo
= modeno
;
165 unsigned short ModeIdIndex
= 0, ClockIndex
= 0;
166 unsigned short RefreshRateTableIndex
= 0;
168 /*unsigned long temp = 0;*/
170 XGI_Pr
->ROMAddr
= HwDeviceExtension
->pjVirtualRomBase
;
171 InitTo330Pointer( HwDeviceExtension
->jChipType
, XGI_Pr
) ;
173 RefreshRateTableIndex
= XGI_GetRatePtrCRT2( HwDeviceExtension
, ModeNo
, ModeIdIndex
, XGI_Pr
) ;
176 temp = XGI_SearchModeID( ModeNo , &ModeIdIndex, XGI_Pr ) ;
178 printk(KERN_ERR "Could not find mode %x\n", ModeNo);
182 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
183 RefreshRateTableIndex += (rateindex - 1);
186 ClockIndex
= XGI_Pr
->RefIndex
[RefreshRateTableIndex
].Ext_CRTVCLK
;
187 if(HwDeviceExtension
->jChipType
< XGI_315H
) {
190 Clock
= XGI_Pr
->VCLKData
[ClockIndex
].CLOCK
* 1000 ;
196 XGIfb_mode_rate_to_ddata(struct vb_device_info
*XGI_Pr
, struct xgi_hw_device_info
*HwDeviceExtension
,
197 unsigned char modeno
, unsigned char rateindex
,
198 u32
*left_margin
, u32
*right_margin
,
199 u32
*upper_margin
, u32
*lower_margin
,
200 u32
*hsync_len
, u32
*vsync_len
,
201 u32
*sync
, u32
*vmode
)
203 unsigned short ModeNo
= modeno
;
204 unsigned short ModeIdIndex
= 0, index
= 0;
205 unsigned short RefreshRateTableIndex
= 0;
207 unsigned short VRE
, VBE
, VRS
, VBS
, VDE
, VT
;
208 unsigned short HRE
, HBE
, HRS
, HBS
, HDE
, HT
;
209 unsigned char sr_data
, cr_data
, cr_data2
;
210 unsigned long cr_data3
;
211 int A
, B
, C
, D
, E
, F
, temp
, j
;
212 XGI_Pr
->ROMAddr
= HwDeviceExtension
->pjVirtualRomBase
;
213 InitTo330Pointer( HwDeviceExtension
->jChipType
, XGI_Pr
) ;
214 RefreshRateTableIndex
= XGI_GetRatePtrCRT2( HwDeviceExtension
, ModeNo
, ModeIdIndex
, XGI_Pr
) ;
216 temp = XGI_SearchModeID( ModeNo, &ModeIdIndex, XGI_Pr);
219 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
220 RefreshRateTableIndex += (rateindex - 1);
222 index
= XGI_Pr
->RefIndex
[RefreshRateTableIndex
].Ext_CRT1CRTC
;
224 sr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[5];
226 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[0];
228 /* Horizontal total */
229 HT
= (cr_data
& 0xff) |
230 ((unsigned short) (sr_data
& 0x03) << 8);
233 /*cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
235 Horizontal display enable end
236 HDE = (cr_data & 0xff) |
237 ((unsigned short) (sr_data & 0x0C) << 6);*/
238 HDE
= (XGI_Pr
->RefIndex
[RefreshRateTableIndex
].XRes
>> 3) -1;
241 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[3];
243 /* Horizontal retrace (=sync) start */
244 HRS
= (cr_data
& 0xff) |
245 ((unsigned short) (sr_data
& 0xC0) << 2);
248 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[1];
250 /* Horizontal blank start */
251 HBS
= (cr_data
& 0xff) |
252 ((unsigned short) (sr_data
& 0x30) << 4);
254 sr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[6];
256 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[2];
258 cr_data2
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[4];
260 /* Horizontal blank end */
261 HBE
= (cr_data
& 0x1f) |
262 ((unsigned short) (cr_data2
& 0x80) >> 2) |
263 ((unsigned short) (sr_data
& 0x03) << 6);
265 /* Horizontal retrace (=sync) end */
266 HRE
= (cr_data2
& 0x1f) | ((sr_data
& 0x04) << 3);
268 temp
= HBE
- ((E
- 1) & 255);
269 B
= (temp
> 0) ? temp
: (temp
+ 256);
271 temp
= HRE
- ((E
+ F
+ 3) & 63);
272 C
= (temp
> 0) ? temp
: (temp
+ 64);
276 *left_margin
= D
* 8;
277 *right_margin
= F
* 8;
280 sr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[14];
282 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[8];
284 cr_data2
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[9];
287 VT
= (cr_data
& 0xFF) |
288 ((unsigned short) (cr_data2
& 0x01) << 8) |
289 ((unsigned short)(cr_data2
& 0x20) << 4) |
290 ((unsigned short) (sr_data
& 0x01) << 10);
293 //cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
295 /* Vertical display enable end */
296 /* VDE = (cr_data & 0xff) |
297 ((unsigned short) (cr_data2 & 0x02) << 7) |
298 ((unsigned short) (cr_data2 & 0x40) << 3) |
299 ((unsigned short) (sr_data & 0x02) << 9); */
300 VDE
= XGI_Pr
->RefIndex
[RefreshRateTableIndex
].YRes
-1;
303 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[10];
305 /* Vertical retrace (=sync) start */
306 VRS
= (cr_data
& 0xff) |
307 ((unsigned short) (cr_data2
& 0x04) << 6) |
308 ((unsigned short) (cr_data2
& 0x80) << 2) |
309 ((unsigned short) (sr_data
& 0x08) << 7);
312 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[12];
314 cr_data3
= (XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[14] & 0x80) << 5;
316 /* Vertical blank start */
317 VBS
= (cr_data
& 0xff) |
318 ((unsigned short) (cr_data2
& 0x08) << 5) |
319 ((unsigned short) (cr_data3
& 0x20) << 4) |
320 ((unsigned short) (sr_data
& 0x04) << 8);
322 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[13];
324 /* Vertical blank end */
325 VBE
= (cr_data
& 0xff) |
326 ((unsigned short) (sr_data
& 0x10) << 4);
327 temp
= VBE
- ((E
- 1) & 511);
328 B
= (temp
> 0) ? temp
: (temp
+ 512);
330 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[11];
332 /* Vertical retrace (=sync) end */
333 VRE
= (cr_data
& 0x0f) | ((sr_data
& 0x20) >> 1);
334 temp
= VRE
- ((E
+ F
- 1) & 31);
335 C
= (temp
> 0) ? temp
: (temp
+ 32);
343 if(XGI_Pr
->RefIndex
[RefreshRateTableIndex
].Ext_InfoFlag
& 0x8000)
344 *sync
&= ~FB_SYNC_VERT_HIGH_ACT
;
346 *sync
|= FB_SYNC_VERT_HIGH_ACT
;
348 if(XGI_Pr
->RefIndex
[RefreshRateTableIndex
].Ext_InfoFlag
& 0x4000)
349 *sync
&= ~FB_SYNC_HOR_HIGH_ACT
;
351 *sync
|= FB_SYNC_HOR_HIGH_ACT
;
353 *vmode
= FB_VMODE_NONINTERLACED
;
354 if(XGI_Pr
->RefIndex
[RefreshRateTableIndex
].Ext_InfoFlag
& 0x0080)
355 *vmode
= FB_VMODE_INTERLACED
;
358 while(XGI_Pr
->EModeIDTable
[j
].Ext_ModeID
!= 0xff) {
359 if(XGI_Pr
->EModeIDTable
[j
].Ext_ModeID
==
360 XGI_Pr
->RefIndex
[RefreshRateTableIndex
].ModeID
) {
361 if(XGI_Pr
->EModeIDTable
[j
].Ext_ModeFlag
& DoubleScanMode
) {
362 *vmode
= FB_VMODE_DOUBLE
;
376 void XGIRegInit(struct vb_device_info
*XGI_Pr
, unsigned long BaseAddr
)
378 XGI_Pr
->RelIO
= BaseAddr
;
379 XGI_Pr
->P3c4
= BaseAddr
+ 0x14;
380 XGI_Pr
->P3d4
= BaseAddr
+ 0x24;
381 XGI_Pr
->P3c0
= BaseAddr
+ 0x10;
382 XGI_Pr
->P3ce
= BaseAddr
+ 0x1e;
383 XGI_Pr
->P3c2
= BaseAddr
+ 0x12;
384 XGI_Pr
->P3ca
= BaseAddr
+ 0x1a;
385 XGI_Pr
->P3c6
= BaseAddr
+ 0x16;
386 XGI_Pr
->P3c7
= BaseAddr
+ 0x17;
387 XGI_Pr
->P3c8
= BaseAddr
+ 0x18;
388 XGI_Pr
->P3c9
= BaseAddr
+ 0x19;
389 XGI_Pr
->P3da
= BaseAddr
+ 0x2A;
390 XGI_Pr
->Part1Port
= BaseAddr
+ XGI_CRT2_PORT_04
; /* Digital video interface registers (LCD) */
391 XGI_Pr
->Part2Port
= BaseAddr
+ XGI_CRT2_PORT_10
; /* 301 TV Encoder registers */
392 XGI_Pr
->Part3Port
= BaseAddr
+ XGI_CRT2_PORT_12
; /* 301 Macrovision registers */
393 XGI_Pr
->Part4Port
= BaseAddr
+ XGI_CRT2_PORT_14
; /* 301 VGA2 (and LCD) registers */
394 XGI_Pr
->Part5Port
= BaseAddr
+ XGI_CRT2_PORT_14
+2; /* 301 palette address port registers */
399 void XGIfb_set_reg4(u16 port
, unsigned long data
)
401 outl((u32
) (data
& 0xffffffff), port
);
404 u32
XGIfb_get_reg3(u16 port
)
412 /* ------------ Interface for init & mode switching code ------------- */
415 XGIfb_query_VGA_config_space(struct xgi_hw_device_info
*pXGIhw_ext
,
416 unsigned long offset
, unsigned long set
, unsigned long *value
)
418 static struct pci_dev
*pdev
= NULL
;
419 static unsigned char init
= 0, valid_pdev
= 0;
422 DPRINTK("XGIfb: Get VGA offset 0x%lx\n", offset
);
424 DPRINTK("XGIfb: Set offset 0x%lx to 0x%lx\n", offset
, *value
);
428 pdev
= pci_get_device(PCI_VENDOR_ID_XG
, xgi_video_info
.chip_id
, pdev
);
436 printk(KERN_DEBUG
"XGIfb: Can't find XGI %d VGA device.\n",
437 xgi_video_info
.chip_id
);
442 pci_read_config_dword(pdev
, offset
, (u32
*)value
);
444 pci_write_config_dword(pdev
, offset
, (u32
)(*value
));
449 /*unsigned char XGIfb_query_north_bridge_space(struct xgi_hw_device_info *pXGIhw_ext,
450 unsigned long offset, unsigned long set, unsigned long *value)
452 static struct pci_dev *pdev = NULL;
453 static unsigned char init = 0, valid_pdev = 0;
458 switch (xgi_video_info.chip) {
460 nbridge_id = PCI_DEVICE_ID_XG_540;
463 nbridge_id = PCI_DEVICE_ID_XG_630;
466 nbridge_id = PCI_DEVICE_ID_XG_730;
469 nbridge_id = PCI_DEVICE_ID_XG_550;
472 nbridge_id = PCI_DEVICE_ID_XG_650;
475 nbridge_id = PCI_DEVICE_ID_XG_740;
482 pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridge_id, pdev);
488 printk(KERN_DEBUG "XGIfb: Can't find XGI %d North Bridge device.\n",
494 pci_read_config_dword(pdev, offset, (u32 *)value);
496 pci_write_config_dword(pdev, offset, (u32)(*value));
501 /* ------------------ Internal helper routines ----------------- */
503 static void XGIfb_search_mode(const char *name
)
508 printk(KERN_ERR
"XGIfb: Internal error, using default mode.\n");
509 xgifb_mode_idx
= DEFAULT_MODE
;
510 if ((xgi_video_info
.chip
== XG21
) && ((xgi_video_info
.disp_state
& DISPTYPE_DISP2
) == DISPTYPE_LCD
))
512 xgifb_mode_idx
= XGIfb_GetXG21DefaultLVDSModeIdx();
518 if (!strcmp(name
, XGIbios_mode
[MODE_INDEX_NONE
].name
)) {
519 printk(KERN_ERR
"XGIfb: Mode 'none' not supported anymore. Using default.\n");
520 xgifb_mode_idx
= DEFAULT_MODE
;
521 if ((xgi_video_info
.chip
== XG21
) && ((xgi_video_info
.disp_state
& DISPTYPE_DISP2
) == DISPTYPE_LCD
))
523 xgifb_mode_idx
= XGIfb_GetXG21DefaultLVDSModeIdx();
528 while(XGIbios_mode
[i
].mode_no
!= 0) {
529 l
= min(strlen(name
), strlen(XGIbios_mode
[i
].name
));
530 if (!strncmp(name
, XGIbios_mode
[i
].name
, l
)) {
537 if(!j
) printk(KERN_INFO
"XGIfb: Invalid mode '%s'\n", name
);
540 static void XGIfb_search_vesamode(unsigned int vesamode
)
546 printk(KERN_ERR
"XGIfb: Mode 'none' not supported anymore. Using default.\n");
547 xgifb_mode_idx
= DEFAULT_MODE
;
548 if ((xgi_video_info
.chip
== XG21
) && ((xgi_video_info
.disp_state
& DISPTYPE_DISP2
) == DISPTYPE_LCD
))
550 xgifb_mode_idx
= XGIfb_GetXG21DefaultLVDSModeIdx();
555 vesamode
&= 0x1dff; /* Clean VESA mode number from other flags */
557 while(XGIbios_mode
[i
].mode_no
!= 0) {
558 if( (XGIbios_mode
[i
].vesa_mode_no_1
== vesamode
) ||
559 (XGIbios_mode
[i
].vesa_mode_no_2
== vesamode
) ) {
566 if(!j
) printk(KERN_INFO
"XGIfb: Invalid VESA mode 0x%x'\n", vesamode
);
569 int XGIfb_GetXG21LVDSData(void)
572 unsigned char *pData
;
575 inXGIIDXREG(XGISR
,0x1e,tmp
);
576 outXGIIDXREG(XGISR
, 0x1e, tmp
|4);
578 pData
= xgi_video_info
.mmio_vbase
+0x20000;
579 if ((pData
[0x0]==0x55) && (pData
[0x1]==0xAA) && (pData
[0x65] & 0x1))
581 i
= pData
[ 0x316 ] | ( pData
[ 0x317 ] << 8 );
590 XGI21_LCDCapList
[k
].LVDS_Capability
= pData
[ i
] | ( pData
[ i
+ 1 ] << 8 );
591 XGI21_LCDCapList
[k
].LVDSHT
= pData
[ i
+ 2 ] | ( pData
[ i
+ 3 ] << 8 ) ;
592 XGI21_LCDCapList
[k
].LVDSVT
= pData
[ i
+ 4 ] | ( pData
[ i
+ 5 ] << 8 );
593 XGI21_LCDCapList
[k
].LVDSHDE
= pData
[ i
+ 6 ] | ( pData
[ i
+ 7 ] << 8 );
594 XGI21_LCDCapList
[k
].LVDSVDE
= pData
[ i
+ 8 ] | ( pData
[ i
+ 9 ] << 8 );
595 XGI21_LCDCapList
[k
].LVDSHFP
= pData
[ i
+ 10 ] | ( pData
[ i
+ 11 ] << 8 );
596 XGI21_LCDCapList
[k
].LVDSVFP
= pData
[ i
+ 12 ] | ( pData
[ i
+ 13 ] << 8 );
597 XGI21_LCDCapList
[k
].LVDSHSYNC
= pData
[ i
+ 14 ] | ( pData
[ i
+ 15 ] << 8 );
598 XGI21_LCDCapList
[k
].LVDSVSYNC
= pData
[ i
+ 16 ] | ( pData
[ i
+ 17 ] << 8 );
599 XGI21_LCDCapList
[k
].VCLKData1
= pData
[ i
+ 18 ] ;
600 XGI21_LCDCapList
[k
].VCLKData2
= pData
[ i
+ 19 ] ;
601 XGI21_LCDCapList
[k
].PSC_S1
= pData
[ i
+ 20 ] ;
602 XGI21_LCDCapList
[k
].PSC_S2
= pData
[ i
+ 21 ] ;
603 XGI21_LCDCapList
[k
].PSC_S3
= pData
[ i
+ 22 ] ;
604 XGI21_LCDCapList
[k
].PSC_S4
= pData
[ i
+ 23 ] ;
605 XGI21_LCDCapList
[k
].PSC_S5
= pData
[ i
+ 24 ] ;
610 (k
< (sizeof(XGI21_LCDCapList
)/sizeof(struct XGI21_LVDSCapStruct
))));
616 int XGIfb_GetXG21DefaultLVDSModeIdx(void)
620 int XGIfb_mode_idx
= 0;
623 while( (XGIbios_mode
[XGIfb_mode_idx
].mode_no
!= 0) &&
624 (XGIbios_mode
[XGIfb_mode_idx
].xres
<= XGI21_LCDCapList
[0].LVDSHDE
) )
626 if( (XGIbios_mode
[XGIfb_mode_idx
].xres
== XGI21_LCDCapList
[0].LVDSHDE
) &&
627 (XGIbios_mode
[XGIfb_mode_idx
].yres
== XGI21_LCDCapList
[0].LVDSVDE
) &&
628 (XGIbios_mode
[XGIfb_mode_idx
].bpp
== 8))
630 XGIfb_mode_no
= XGIbios_mode
[XGIfb_mode_idx
].mode_no
;
639 return (XGIfb_mode_idx
);
643 static int XGIfb_validate_mode(int myindex
)
647 if (xgi_video_info
.chip
== XG21
)
649 if ((xgi_video_info
.disp_state
& DISPTYPE_DISP2
) == DISPTYPE_LCD
)
651 xres
= XGI21_LCDCapList
[0].LVDSHDE
;
652 yres
= XGI21_LCDCapList
[0].LVDSVDE
;
653 if(XGIbios_mode
[myindex
].xres
> xres
)
655 if(XGIbios_mode
[myindex
].yres
> yres
)
657 if ((XGIbios_mode
[myindex
].xres
< xres
) && (XGIbios_mode
[myindex
].yres
< yres
) )
659 if (XGIbios_mode
[myindex
].bpp
> 8)
668 if (xgi_video_info
.chip
== XG27
)
671 if(!(XGIbios_mode
[myindex
].chipset
& MD_XGI315
))
674 switch (xgi_video_info
.disp_state
& DISPTYPE_DISP2
) {
676 switch (XGIhw_ext
.ulCRT2LCDType
) {
678 xres
= 640; yres
= 480; break;
680 xres
= 800; yres
= 600; break;
682 xres
= 1024; yres
= 600; break;
684 xres
= 1024; yres
= 768; break;
686 xres
= 1152; yres
= 768; break;
688 xres
= 1280; yres
= 960; break;
690 xres
= 1280; yres
= 768; break;
692 xres
= 1280; yres
= 1024; break;
694 xres
= 1400; yres
= 1050; break;
696 xres
= 1600; yres
= 1200; break;
697 // case LCD_320x480: // TW: FSTN
698 // xres = 320; yres = 480; break;
700 xres
= 0; yres
= 0; break;
702 if(XGIbios_mode
[myindex
].xres
> xres
) {
705 if(XGIbios_mode
[myindex
].yres
> yres
) {
708 if((XGIhw_ext
.ulExternalChip
== 0x01) || // LVDS
709 (XGIhw_ext
.ulExternalChip
== 0x05)) // LVDS+Chrontel
711 switch (XGIbios_mode
[myindex
].xres
) {
713 if(XGIbios_mode
[myindex
].yres
!= 512) return -1;
714 if(XGIhw_ext
.ulCRT2LCDType
== LCD_1024x600
) return -1;
717 if((XGIbios_mode
[myindex
].yres
!= 400) &&
718 (XGIbios_mode
[myindex
].yres
!= 480))
722 if(XGIbios_mode
[myindex
].yres
!= 600) return -1;
725 if((XGIbios_mode
[myindex
].yres
!= 600) &&
726 (XGIbios_mode
[myindex
].yres
!= 768))
728 if((XGIbios_mode
[myindex
].yres
== 600) &&
729 (XGIhw_ext
.ulCRT2LCDType
!= LCD_1024x600
))
733 if((XGIbios_mode
[myindex
].yres
) != 768) return -1;
734 if(XGIhw_ext
.ulCRT2LCDType
!= LCD_1152x768
) return -1;
737 if((XGIbios_mode
[myindex
].yres
!= 768) &&
738 (XGIbios_mode
[myindex
].yres
!= 1024))
740 if((XGIbios_mode
[myindex
].yres
== 768) &&
741 (XGIhw_ext
.ulCRT2LCDType
!= LCD_1280x768
))
745 if(XGIbios_mode
[myindex
].yres
!= 1050) return -1;
748 if(XGIbios_mode
[myindex
].yres
!= 1200) return -1;
754 switch (XGIbios_mode
[myindex
].xres
) {
756 if(XGIbios_mode
[myindex
].yres
!= 512) return -1;
759 if((XGIbios_mode
[myindex
].yres
!= 400) &&
760 (XGIbios_mode
[myindex
].yres
!= 480))
764 if(XGIbios_mode
[myindex
].yres
!= 600) return -1;
767 if(XGIbios_mode
[myindex
].yres
!= 768) return -1;
770 if((XGIbios_mode
[myindex
].yres
!= 960) &&
771 (XGIbios_mode
[myindex
].yres
!= 1024))
773 if(XGIbios_mode
[myindex
].yres
== 960) {
774 if(XGIhw_ext
.ulCRT2LCDType
== LCD_1400x1050
)
779 if(XGIbios_mode
[myindex
].yres
!= 1050) return -1;
782 if(XGIbios_mode
[myindex
].yres
!= 1200) return -1;
790 switch (XGIbios_mode
[myindex
].xres
) {
796 if (xgi_video_info
.TV_type
== TVMODE_NTSC
) {
797 if (XGIbios_mode
[myindex
].yres
!= 480) {
800 } else if (xgi_video_info
.TV_type
== TVMODE_PAL
) {
801 if (XGIbios_mode
[myindex
].yres
!= 576) {
805 // TW: LVDS/CHRONTEL does not support 720
806 if (xgi_video_info
.hasVB
== HASVB_LVDS_CHRONTEL
||
807 xgi_video_info
.hasVB
== HASVB_CHRONTEL
) {
812 if (xgi_video_info
.TV_type
== TVMODE_NTSC
) {
813 if(XGIbios_mode
[myindex
].bpp
== 32) {
817 // TW: LVDS/CHRONTEL only supports < 800 (1024 on 650/Ch7019)
818 if (xgi_video_info
.hasVB
== HASVB_LVDS_CHRONTEL
||
819 xgi_video_info
.hasVB
== HASVB_CHRONTEL
) {
820 if(xgi_video_info
.chip
< XGI_315H
) {
830 if(XGIbios_mode
[myindex
].xres
> 1280) return -1;
837 static void XGIfb_search_crt2type(const char *name
)
844 while(XGI_crt2type
[i
].type_no
!= -1) {
845 if (!strcmp(name
, XGI_crt2type
[i
].name
)) {
846 XGIfb_crt2type
= XGI_crt2type
[i
].type_no
;
847 XGIfb_tvplug
= XGI_crt2type
[i
].tvplug_no
;
852 if(XGIfb_crt2type
< 0)
853 printk(KERN_INFO
"XGIfb: Invalid CRT2 type: %s\n", name
);
856 static void XGIfb_search_queuemode(const char *name
)
863 while (XGI_queuemode
[i
].type_no
!= -1) {
864 if (!strcmp(name
, XGI_queuemode
[i
].name
)) {
865 XGIfb_queuemode
= XGI_queuemode
[i
].type_no
;
870 if (XGIfb_queuemode
< 0)
871 printk(KERN_INFO
"XGIfb: Invalid queuemode type: %s\n", name
);
874 static u8
XGIfb_search_refresh_rate(unsigned int rate
)
879 xres
= XGIbios_mode
[xgifb_mode_idx
].xres
;
880 yres
= XGIbios_mode
[xgifb_mode_idx
].yres
;
883 while ((XGIfb_vrate
[i
].idx
!= 0) && (XGIfb_vrate
[i
].xres
<= xres
)) {
884 if ((XGIfb_vrate
[i
].xres
== xres
) && (XGIfb_vrate
[i
].yres
== yres
)) {
885 if (XGIfb_vrate
[i
].refresh
== rate
) {
886 XGIfb_rate_idx
= XGIfb_vrate
[i
].idx
;
888 } else if (XGIfb_vrate
[i
].refresh
> rate
) {
889 if ((XGIfb_vrate
[i
].refresh
- rate
) <= 3) {
890 DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
891 rate
, XGIfb_vrate
[i
].refresh
);
892 XGIfb_rate_idx
= XGIfb_vrate
[i
].idx
;
893 xgi_video_info
.refresh_rate
= XGIfb_vrate
[i
].refresh
;
894 } else if (((rate
- XGIfb_vrate
[i
-1].refresh
) <= 2)
895 && (XGIfb_vrate
[i
].idx
!= 1)) {
896 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
897 rate
, XGIfb_vrate
[i
-1].refresh
);
898 XGIfb_rate_idx
= XGIfb_vrate
[i
-1].idx
;
899 xgi_video_info
.refresh_rate
= XGIfb_vrate
[i
-1].refresh
;
902 } else if((rate
- XGIfb_vrate
[i
].refresh
) <= 2) {
903 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
904 rate
, XGIfb_vrate
[i
].refresh
);
905 XGIfb_rate_idx
= XGIfb_vrate
[i
].idx
;
911 if (XGIfb_rate_idx
> 0) {
912 return XGIfb_rate_idx
;
915 "XGIfb: Unsupported rate %d for %dx%d\n", rate
, xres
, yres
);
920 static void XGIfb_search_tvstd(const char *name
)
927 while (XGI_tvtype
[i
].type_no
!= -1) {
928 if (!strcmp(name
, XGI_tvtype
[i
].name
)) {
929 XGIfb_tvmode
= XGI_tvtype
[i
].type_no
;
936 static unsigned char XGIfb_bridgeisslave(void)
938 unsigned char usScratchP1_00
;
940 if (xgi_video_info
.hasVB
== HASVB_NONE
)
943 inXGIIDXREG(XGIPART1
,0x00,usScratchP1_00
);
944 if ((usScratchP1_00
& 0x50) == 0x10)
950 static unsigned char XGIfbcheckvretracecrt1(void)
954 inXGIIDXREG(XGICR
,0x17,temp
);
959 inXGIIDXREG(XGISR
,0x1f,temp
);
963 if (inXGIREG(XGIINPSTAT
) & 0x08)
969 static unsigned char XGIfbcheckvretracecrt2(void)
972 if (xgi_video_info
.hasVB
== HASVB_NONE
)
974 inXGIIDXREG(XGIPART1
, 0x30, temp
);
981 static unsigned char XGIfb_CheckVBRetrace(void)
983 if(xgi_video_info
.disp_state
& DISPTYPE_DISP2
) {
984 if(XGIfb_bridgeisslave()) {
985 return(XGIfbcheckvretracecrt1());
987 return(XGIfbcheckvretracecrt2());
990 return(XGIfbcheckvretracecrt1());
993 /* ----------- FBDev related routines for all series ----------- */
996 static void XGIfb_bpp_to_var(struct fb_var_screeninfo
*var
)
998 switch(var
->bits_per_pixel
) {
1000 var
->red
.offset
= var
->green
.offset
= var
->blue
.offset
= 0;
1001 var
->red
.length
= var
->green
.length
= var
->blue
.length
= 6;
1002 xgi_video_info
.video_cmap_len
= 256;
1005 var
->red
.offset
= 11;
1006 var
->red
.length
= 5;
1007 var
->green
.offset
= 5;
1008 var
->green
.length
= 6;
1009 var
->blue
.offset
= 0;
1010 var
->blue
.length
= 5;
1011 var
->transp
.offset
= 0;
1012 var
->transp
.length
= 0;
1013 xgi_video_info
.video_cmap_len
= 16;
1016 var
->red
.offset
= 16;
1017 var
->red
.length
= 8;
1018 var
->green
.offset
= 8;
1019 var
->green
.length
= 8;
1020 var
->blue
.offset
= 0;
1021 var
->blue
.length
= 8;
1022 var
->transp
.offset
= 24;
1023 var
->transp
.length
= 8;
1024 xgi_video_info
.video_cmap_len
= 16;
1031 static int XGIfb_do_set_var(struct fb_var_screeninfo
*var
, int isactive
,
1032 struct fb_info
*info
)
1035 unsigned int htotal
= var
->left_margin
+ var
->xres
+
1036 var
->right_margin
+ var
->hsync_len
;
1037 unsigned int vtotal
= var
->upper_margin
+ var
->yres
+
1038 var
->lower_margin
+ var
->vsync_len
;
1039 #if defined(__powerpc__)
1040 u8 sr_data
, cr_data
;
1042 unsigned int drate
= 0, hrate
= 0;
1045 // unsigned char reg,reg1;
1047 DEBUGPRN("Inside do_set_var");
1048 // 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);
1050 info
->var
.xres_virtual
= var
->xres_virtual
;
1051 info
->var
.yres_virtual
= var
->yres_virtual
;
1052 info
->var
.bits_per_pixel
= var
->bits_per_pixel
;
1054 if ((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
)
1056 else if ((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
)
1058 else if ((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
)
1064 if(!htotal
|| !vtotal
) {
1065 DPRINTK("XGIfb: Invalid 'var' information\n");
1068 printk(KERN_DEBUG
"XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n",
1069 var
->pixclock
,htotal
,vtotal
);
1073 if(var
->pixclock
&& htotal
&& vtotal
) {
1074 drate
= 1000000000 / var
->pixclock
;
1075 hrate
= (drate
* 1000) / htotal
;
1076 xgi_video_info
.refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1078 xgi_video_info
.refresh_rate
= 60;
1081 printk(KERN_DEBUG
"XGIfb: Change mode to %dx%dx%d-%dHz\n",
1082 var
->xres
,var
->yres
,var
->bits_per_pixel
,xgi_video_info
.refresh_rate
);
1084 old_mode
= xgifb_mode_idx
;
1087 while( (XGIbios_mode
[xgifb_mode_idx
].mode_no
!= 0) &&
1088 (XGIbios_mode
[xgifb_mode_idx
].xres
<= var
->xres
) ) {
1089 if( (XGIbios_mode
[xgifb_mode_idx
].xres
== var
->xres
) &&
1090 (XGIbios_mode
[xgifb_mode_idx
].yres
== var
->yres
) &&
1091 (XGIbios_mode
[xgifb_mode_idx
].bpp
== var
->bits_per_pixel
)) {
1092 XGIfb_mode_no
= XGIbios_mode
[xgifb_mode_idx
].mode_no
;
1100 xgifb_mode_idx
= XGIfb_validate_mode(xgifb_mode_idx
);
1102 xgifb_mode_idx
= -1;
1104 if(xgifb_mode_idx
< 0) {
1105 printk(KERN_ERR
"XGIfb: Mode %dx%dx%d not supported\n", var
->xres
,
1106 var
->yres
, var
->bits_per_pixel
);
1107 xgifb_mode_idx
= old_mode
;
1111 if(XGIfb_search_refresh_rate(xgi_video_info
.refresh_rate
) == 0) {
1112 XGIfb_rate_idx
= XGIbios_mode
[xgifb_mode_idx
].rate_idx
;
1113 xgi_video_info
.refresh_rate
= 60;
1119 XGIfb_pre_setmode();
1120 if(XGISetModeNew( &XGIhw_ext
, XGIfb_mode_no
) == 0) {
1121 printk(KERN_ERR
"XGIfb: Setting mode[0x%x] failed\n", XGIfb_mode_no
);
1124 info
->fix
.line_length
= ((info
->var
.xres_virtual
* info
->var
.bits_per_pixel
)>>6);
1126 outXGIIDXREG(XGISR
,IND_XGI_PASSWORD
,XGI_PASSWORD
);
1128 outXGIIDXREG(XGICR
,0x13,(info
->fix
.line_length
& 0x00ff));
1129 outXGIIDXREG(XGISR
,0x0E,(info
->fix
.line_length
& 0xff00)>>8);
1131 XGIfb_post_setmode();
1133 DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d \n",
1134 XGIbios_mode
[xgifb_mode_idx
].xres
,
1135 XGIbios_mode
[xgifb_mode_idx
].yres
,
1136 XGIbios_mode
[xgifb_mode_idx
].bpp
,
1137 xgi_video_info
.refresh_rate
);
1139 xgi_video_info
.video_bpp
= XGIbios_mode
[xgifb_mode_idx
].bpp
;
1140 xgi_video_info
.video_vwidth
= info
->var
.xres_virtual
;
1141 xgi_video_info
.video_width
= XGIbios_mode
[xgifb_mode_idx
].xres
;
1142 xgi_video_info
.video_vheight
= info
->var
.yres_virtual
;
1143 xgi_video_info
.video_height
= XGIbios_mode
[xgifb_mode_idx
].yres
;
1144 xgi_video_info
.org_x
= xgi_video_info
.org_y
= 0;
1145 xgi_video_info
.video_linelength
= info
->var
.xres_virtual
* (xgi_video_info
.video_bpp
>> 3);
1146 xgi_video_info
.accel
= 0;
1148 xgi_video_info
.accel
= (var
->accel_flags
& FB_ACCELF_TEXT
) ? -1 : 0;
1150 switch(xgi_video_info
.video_bpp
)
1153 xgi_video_info
.DstColor
= 0x0000;
1154 xgi_video_info
.XGI310_AccelDepth
= 0x00000000;
1155 xgi_video_info
.video_cmap_len
= 256;
1156 #if defined(__powerpc__)
1157 inXGIIDXREG (XGICR
, 0x4D, cr_data
);
1158 outXGIIDXREG(XGICR
, 0x4D, (cr_data
& 0xE0));
1162 xgi_video_info
.DstColor
= 0x8000;
1163 xgi_video_info
.XGI310_AccelDepth
= 0x00010000;
1164 #if defined(__powerpc__)
1165 inXGIIDXREG (XGICR
, 0x4D, cr_data
);
1166 outXGIIDXREG(XGICR
, 0x4D, ((cr_data
& 0xE0) | 0x0B));
1168 xgi_video_info
.video_cmap_len
= 16;
1171 xgi_video_info
.DstColor
= 0xC000;
1172 xgi_video_info
.XGI310_AccelDepth
= 0x00020000;
1173 xgi_video_info
.video_cmap_len
= 16;
1174 #if defined(__powerpc__)
1175 inXGIIDXREG (XGICR
, 0x4D, cr_data
);
1176 outXGIIDXREG(XGICR
, 0x4D, ((cr_data
& 0xE0) | 0x15));
1180 xgi_video_info
.video_cmap_len
= 16;
1181 printk(KERN_ERR
"XGIfb: Unsupported depth %d", xgi_video_info
.video_bpp
);
1182 xgi_video_info
.accel
= 0;
1186 XGIfb_bpp_to_var(var
); /*update ARGB info*/
1187 DEBUGPRN("End of do_set_var");
1194 static int XGIfb_pan_var(struct fb_var_screeninfo
*var
)
1198 // printk("Inside pan_var");
1200 if (var
->xoffset
> (var
->xres_virtual
- var
->xres
)) {
1201 // printk( "Pan: xo: %d xv %d xr %d\n",
1202 // var->xoffset, var->xres_virtual, var->xres);
1205 if(var
->yoffset
> (var
->yres_virtual
- var
->yres
)) {
1206 // printk( "Pan: yo: %d yv %d yr %d\n",
1207 // var->yoffset, var->yres_virtual, var->yres);
1210 base
= var
->yoffset
* var
->xres_virtual
+ var
->xoffset
;
1212 /* calculate base bpp dep. */
1213 switch(var
->bits_per_pixel
) {
1225 outXGIIDXREG(XGISR
, IND_XGI_PASSWORD
, XGI_PASSWORD
);
1227 outXGIIDXREG(XGICR
, 0x0D, base
& 0xFF);
1228 outXGIIDXREG(XGICR
, 0x0C, (base
>> 8) & 0xFF);
1229 outXGIIDXREG(XGISR
, 0x0D, (base
>> 16) & 0xFF);
1230 outXGIIDXREG(XGISR
, 0x37, (base
>> 24) & 0x03);
1231 setXGIIDXREG(XGISR
, 0x37, 0xDF, (base
>> 21) & 0x04);
1233 if(xgi_video_info
.disp_state
& DISPTYPE_DISP2
) {
1234 orXGIIDXREG(XGIPART1
, XGIfb_CRT2_write_enable
, 0x01);
1235 outXGIIDXREG(XGIPART1
, 0x06, (base
& 0xFF));
1236 outXGIIDXREG(XGIPART1
, 0x05, ((base
>> 8) & 0xFF));
1237 outXGIIDXREG(XGIPART1
, 0x04, ((base
>> 16) & 0xFF));
1238 setXGIIDXREG(XGIPART1
, 0x02, 0x7F, ((base
>> 24) & 0x01) << 7);
1240 // printk("End of pan_var");
1246 void XGI_dispinfo(struct ap_data
*rec
)
1248 rec
->minfo
.bpp
= xgi_video_info
.video_bpp
;
1249 rec
->minfo
.xres
= xgi_video_info
.video_width
;
1250 rec
->minfo
.yres
= xgi_video_info
.video_height
;
1251 rec
->minfo
.v_xres
= xgi_video_info
.video_vwidth
;
1252 rec
->minfo
.v_yres
= xgi_video_info
.video_vheight
;
1253 rec
->minfo
.org_x
= xgi_video_info
.org_x
;
1254 rec
->minfo
.org_y
= xgi_video_info
.org_y
;
1255 rec
->minfo
.vrate
= xgi_video_info
.refresh_rate
;
1256 rec
->iobase
= xgi_video_info
.vga_base
- 0x30;
1257 rec
->mem_size
= xgi_video_info
.video_size
;
1258 rec
->disp_state
= xgi_video_info
.disp_state
;
1259 rec
->version
= (VER_MAJOR
<< 24) | (VER_MINOR
<< 16) | VER_LEVEL
;
1260 rec
->hasVB
= xgi_video_info
.hasVB
;
1261 rec
->TV_type
= xgi_video_info
.TV_type
;
1262 rec
->TV_plug
= xgi_video_info
.TV_plug
;
1263 rec
->chip
= xgi_video_info
.chip
;
1269 static int XGIfb_open(struct fb_info
*info
, int user
)
1274 static int XGIfb_release(struct fb_info
*info
, int user
)
1279 static int XGIfb_get_cmap_len(const struct fb_var_screeninfo
*var
)
1283 switch(var
->bits_per_pixel
) {
1297 static int XGIfb_setcolreg(unsigned regno
, unsigned red
, unsigned green
, unsigned blue
,
1298 unsigned transp
, struct fb_info
*info
)
1300 if (regno
>= XGIfb_get_cmap_len(&info
->var
))
1303 switch (info
->var
.bits_per_pixel
) {
1305 outXGIREG(XGIDACA
, regno
);
1306 outXGIREG(XGIDACD
, (red
>> 10));
1307 outXGIREG(XGIDACD
, (green
>> 10));
1308 outXGIREG(XGIDACD
, (blue
>> 10));
1309 if (xgi_video_info
.disp_state
& DISPTYPE_DISP2
) {
1310 outXGIREG(XGIDAC2A
, regno
);
1311 outXGIREG(XGIDAC2D
, (red
>> 8));
1312 outXGIREG(XGIDAC2D
, (green
>> 8));
1313 outXGIREG(XGIDAC2D
, (blue
>> 8));
1317 ((u32
*)(info
->pseudo_palette
))[regno
] =
1318 ((red
& 0xf800)) | ((green
& 0xfc00) >> 5) | ((blue
& 0xf800) >> 11);
1324 ((u32
*) (info
->pseudo_palette
))[regno
] =
1325 (red
<< 16) | (green
<< 8) | (blue
);
1331 static int XGIfb_set_par(struct fb_info
*info
)
1335 // printk("XGIfb: inside set_par\n");
1336 if((err
= XGIfb_do_set_var(&info
->var
, 1, info
)))
1338 XGIfb_get_fix(&info
->fix
, -1, info
);
1339 // printk("XGIfb:end of set_par\n");
1343 static int XGIfb_check_var(struct fb_var_screeninfo
*var
,
1344 struct fb_info
*info
)
1346 unsigned int htotal
=
1347 var
->left_margin
+ var
->xres
+ var
->right_margin
+
1349 unsigned int vtotal
= 0;
1350 unsigned int drate
= 0, hrate
= 0;
1352 int refresh_rate
, search_idx
;
1354 DEBUGPRN("Inside check_var");
1356 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
) {
1357 vtotal
= var
->upper_margin
+ var
->yres
+ var
->lower_margin
+
1360 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1361 vtotal
= var
->upper_margin
+ var
->yres
+ var
->lower_margin
+
1364 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1365 vtotal
= var
->upper_margin
+ (var
->yres
/2) + var
->lower_margin
+
1367 } else vtotal
= var
->upper_margin
+ var
->yres
+ var
->lower_margin
+
1370 if(!(htotal
) || !(vtotal
)) {
1371 XGIFAIL("XGIfb: no valid timing data");
1375 if(var
->pixclock
&& htotal
&& vtotal
) {
1376 drate
= 1000000000 / var
->pixclock
;
1377 hrate
= (drate
* 1000) / htotal
;
1378 xgi_video_info
.refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1380 "%s: pixclock = %d ,htotal=%d, vtotal=%d\n" \
1381 "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1382 __func__
,var
->pixclock
, htotal
, vtotal
,
1383 __func__
, drate
, hrate
, xgi_video_info
.refresh_rate
);
1385 xgi_video_info
.refresh_rate
= 60;
1389 if((var->pixclock) && (htotal)) {
1390 drate = 1E12 / var->pixclock;
1391 hrate = drate / htotal;
1392 refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1393 } else refresh_rate = 60;
1395 /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
1396 if((var
->xres
== 1024) && (var
->yres
== 600)) refresh_rate
= 60;
1399 while((XGIbios_mode
[search_idx
].mode_no
!= 0) &&
1400 (XGIbios_mode
[search_idx
].xres
<= var
->xres
) ) {
1401 if((XGIbios_mode
[search_idx
].xres
== var
->xres
) &&
1402 (XGIbios_mode
[search_idx
].yres
== var
->yres
) &&
1403 (XGIbios_mode
[search_idx
].bpp
== var
->bits_per_pixel
)) {
1404 if(XGIfb_validate_mode(search_idx
) > 0) {
1414 printk(KERN_ERR
"XGIfb: %dx%dx%d is no valid mode\n",
1415 var
->xres
, var
->yres
, var
->bits_per_pixel
);
1418 while(XGIbios_mode
[search_idx
].mode_no
!= 0) {
1420 if( (var
->xres
<= XGIbios_mode
[search_idx
].xres
) &&
1421 (var
->yres
<= XGIbios_mode
[search_idx
].yres
) &&
1422 (var
->bits_per_pixel
== XGIbios_mode
[search_idx
].bpp
) ) {
1423 if(XGIfb_validate_mode(search_idx
) > 0) {
1431 var
->xres
= XGIbios_mode
[search_idx
].xres
;
1432 var
->yres
= XGIbios_mode
[search_idx
].yres
;
1433 printk(KERN_DEBUG
"XGIfb: Adapted to mode %dx%dx%d\n",
1434 var
->xres
, var
->yres
, var
->bits_per_pixel
);
1437 printk(KERN_ERR
"XGIfb: Failed to find similar mode to %dx%dx%d\n",
1438 var
->xres
, var
->yres
, var
->bits_per_pixel
);
1443 /* TW: TODO: Check the refresh rate */
1445 /* Adapt RGB settings */
1446 XGIfb_bpp_to_var(var
);
1448 /* Sanity check for offsets */
1449 if (var
->xoffset
< 0)
1451 if (var
->yoffset
< 0)
1456 if(var
->xres
!= var
->xres_virtual
)
1457 var
->xres_virtual
= var
->xres
;
1458 if(var
->yres
!= var
->yres_virtual
)
1459 var
->yres_virtual
= var
->yres
;
1461 // TW: Now patch yres_virtual if we use panning
1463 var->yres_virtual = xgi_video_info.heapstart / (var->xres * (var->bits_per_pixel >> 3));
1464 if(var->yres_virtual <= var->yres) {
1465 // TW: Paranoia check
1466 var->yres_virtual = var->yres;
1470 /* Truncate offsets to maximum if too high */
1471 if (var
->xoffset
> var
->xres_virtual
- var
->xres
)
1472 var
->xoffset
= var
->xres_virtual
- var
->xres
- 1;
1474 if (var
->yoffset
> var
->yres_virtual
- var
->yres
)
1475 var
->yoffset
= var
->yres_virtual
- var
->yres
- 1;
1477 /* Set everything else to 0 */
1478 var
->red
.msb_right
=
1479 var
->green
.msb_right
=
1480 var
->blue
.msb_right
=
1481 var
->transp
.offset
= var
->transp
.length
= var
->transp
.msb_right
= 0;
1483 DEBUGPRN("end of check_var");
1488 static int XGIfb_pan_display( struct fb_var_screeninfo
*var
,
1489 struct fb_info
* info
)
1493 // printk("\nInside pan_display:");
1495 if (var
->xoffset
> (var
->xres_virtual
- var
->xres
))
1497 if (var
->yoffset
> (var
->yres_virtual
- var
->yres
))
1500 if (var
->vmode
& FB_VMODE_YWRAP
) {
1501 if (var
->yoffset
< 0
1502 || var
->yoffset
>= info
->var
.yres_virtual
1503 || var
->xoffset
) return -EINVAL
;
1505 if (var
->xoffset
+ info
->var
.xres
> info
->var
.xres_virtual
||
1506 var
->yoffset
+ info
->var
.yres
> info
->var
.yres_virtual
)
1510 if((err
= XGIfb_pan_var(var
)) < 0) return err
;
1512 info
->var
.xoffset
= var
->xoffset
;
1513 info
->var
.yoffset
= var
->yoffset
;
1514 if (var
->vmode
& FB_VMODE_YWRAP
)
1515 info
->var
.vmode
|= FB_VMODE_YWRAP
;
1517 info
->var
.vmode
&= ~FB_VMODE_YWRAP
;
1519 // printk(" End of pan_display");
1525 static int XGIfb_blank(int blank
, struct fb_info
*info
)
1529 inXGIIDXREG(XGICR
, 0x17, reg
);
1536 outXGIIDXREG(XGICR
, 0x17, reg
);
1537 outXGIIDXREG(XGISR
, 0x00, 0x01); /* Synchronous Reset */
1538 outXGIIDXREG(XGISR
, 0x00, 0x03); /* End Reset */
1543 static int XGIfb_ioctl(struct fb_info
*info
, unsigned int cmd
,
1546 DEBUGPRN("inside ioctl");
1549 if (!capable(CAP_SYS_RAWIO
))
1551 XGI_malloc((struct XGI_memreq
*) arg
);
1554 if (!capable(CAP_SYS_RAWIO
))
1556 XGI_free(*(unsigned long *) arg
);
1558 case FBIOGET_HWCINFO
:
1560 unsigned long *hwc_offset
= (unsigned long *) arg
;
1562 if (XGIfb_caps
& HW_CURSOR_CAP
)
1563 *hwc_offset
= XGIfb_hwcursor_vbase
-
1564 (unsigned long) xgi_video_info
.video_vbase
;
1570 case FBIOPUT_MODEINFO
:
1572 struct mode_info
*x
= (struct mode_info
*)arg
;
1574 xgi_video_info
.video_bpp
= x
->bpp
;
1575 xgi_video_info
.video_width
= x
->xres
;
1576 xgi_video_info
.video_height
= x
->yres
;
1577 xgi_video_info
.video_vwidth
= x
->v_xres
;
1578 xgi_video_info
.video_vheight
= x
->v_yres
;
1579 xgi_video_info
.org_x
= x
->org_x
;
1580 xgi_video_info
.org_y
= x
->org_y
;
1581 xgi_video_info
.refresh_rate
= x
->vrate
;
1582 xgi_video_info
.video_linelength
= xgi_video_info
.video_vwidth
* (xgi_video_info
.video_bpp
>> 3);
1583 switch(xgi_video_info
.video_bpp
) {
1585 xgi_video_info
.DstColor
= 0x0000;
1586 xgi_video_info
.XGI310_AccelDepth
= 0x00000000;
1587 xgi_video_info
.video_cmap_len
= 256;
1590 xgi_video_info
.DstColor
= 0x8000;
1591 xgi_video_info
.XGI310_AccelDepth
= 0x00010000;
1592 xgi_video_info
.video_cmap_len
= 16;
1595 xgi_video_info
.DstColor
= 0xC000;
1596 xgi_video_info
.XGI310_AccelDepth
= 0x00020000;
1597 xgi_video_info
.video_cmap_len
= 16;
1600 xgi_video_info
.video_cmap_len
= 16;
1601 printk(KERN_ERR
"XGIfb: Unsupported accel depth %d", xgi_video_info
.video_bpp
);
1602 xgi_video_info
.accel
= 0;
1608 case FBIOGET_DISPINFO
:
1609 XGI_dispinfo((struct ap_data
*)arg
);
1611 case XGIFB_GET_INFO
: /* TW: New for communication with X driver */
1613 struct XGIfb_info
*x
= (struct XGIfb_info
*)arg
;
1615 //x->XGIfb_id = XGIFB_ID;
1616 x
->XGIfb_version
= VER_MAJOR
;
1617 x
->XGIfb_revision
= VER_MINOR
;
1618 x
->XGIfb_patchlevel
= VER_LEVEL
;
1619 x
->chip_id
= xgi_video_info
.chip_id
;
1620 x
->memory
= xgi_video_info
.video_size
/ 1024;
1621 x
->heapstart
= xgi_video_info
.heapstart
/ 1024;
1622 x
->fbvidmode
= XGIfb_mode_no
;
1623 x
->XGIfb_caps
= XGIfb_caps
;
1624 x
->XGIfb_tqlen
= 512; /* yet unused */
1625 x
->XGIfb_pcibus
= xgi_video_info
.pcibus
;
1626 x
->XGIfb_pcislot
= xgi_video_info
.pcislot
;
1627 x
->XGIfb_pcifunc
= xgi_video_info
.pcifunc
;
1628 x
->XGIfb_lcdpdc
= XGIfb_detectedpdc
;
1629 x
->XGIfb_lcda
= XGIfb_detectedlcda
;
1632 case XGIFB_GET_VBRSTATUS
:
1634 unsigned long *vbrstatus
= (unsigned long *) arg
;
1635 if(XGIfb_CheckVBRetrace()) *vbrstatus
= 1;
1636 else *vbrstatus
= 0;
1641 DEBUGPRN("end of ioctl");
1648 /* ----------- FBDev related routines for all series ---------- */
1650 static int XGIfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
1651 struct fb_info
*info
)
1653 DEBUGPRN("inside get_fix");
1654 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
1656 strcpy(fix
->id
, myid
);
1658 fix
->smem_start
= xgi_video_info
.video_base
;
1660 fix
->smem_len
= xgi_video_info
.video_size
;
1663 /* if((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
1664 if (xgi_video_info.video_size > 0x1000000) {
1665 fix->smem_len = 0xD00000;
1666 } else if (xgi_video_info.video_size > 0x800000)
1667 fix->smem_len = 0x800000;
1669 fix->smem_len = 0x400000;
1671 fix->smem_len = XGIfb_mem * 1024;
1673 fix
->type
= video_type
;
1675 if(xgi_video_info
.video_bpp
== 8)
1676 fix
->visual
= FB_VISUAL_PSEUDOCOLOR
;
1678 fix
->visual
= FB_VISUAL_DIRECTCOLOR
;
1681 if(XGIfb_ypan
) fix
->ypanstep
= 1;
1684 fix
->line_length
= xgi_video_info
.video_linelength
;
1685 fix
->mmio_start
= xgi_video_info
.mmio_base
;
1686 fix
->mmio_len
= XGIfb_mmio_size
;
1687 if(xgi_video_info
.chip
>= XG40
)
1688 fix
->accel
= FB_ACCEL_XGI_XABRE
;
1690 fix
->accel
= FB_ACCEL_XGI_GLAMOUR_2
;
1693 DEBUGPRN("end of get_fix");
1698 static struct fb_ops XGIfb_ops
= {
1699 .owner
= THIS_MODULE
,
1700 .fb_open
= XGIfb_open
,
1701 .fb_release
= XGIfb_release
,
1702 .fb_check_var
= XGIfb_check_var
,
1703 .fb_set_par
= XGIfb_set_par
,
1704 .fb_setcolreg
= XGIfb_setcolreg
,
1706 .fb_pan_display
= XGIfb_pan_display
,
1708 .fb_blank
= XGIfb_blank
,
1709 .fb_fillrect
= fbcon_XGI_fillrect
,
1710 .fb_copyarea
= fbcon_XGI_copyarea
,
1711 .fb_imageblit
= cfb_imageblit
,
1712 .fb_sync
= fbcon_XGI_sync
,
1713 .fb_ioctl
= XGIfb_ioctl
,
1714 // .fb_mmap = XGIfb_mmap,
1717 /* ---------------- Chip generation dependent routines ---------------- */
1720 /* for XGI 315/550/650/740/330 */
1722 static int XGIfb_get_dram_size(void)
1728 /* xorg driver sets 32MB * 1 channel */
1729 if (xgi_video_info
.chip
== XG27
)
1730 outXGIIDXREG(XGISR
, IND_XGI_DRAM_SIZE
, 0x51);
1732 inXGIIDXREG(XGISR
, IND_XGI_DRAM_SIZE
, reg
);
1733 switch ((reg
& XGI_DRAM_SIZE_MASK
) >> 4) {
1734 case XGI_DRAM_SIZE_1MB
:
1735 xgi_video_info
.video_size
= 0x100000;
1737 case XGI_DRAM_SIZE_2MB
:
1738 xgi_video_info
.video_size
= 0x200000;
1740 case XGI_DRAM_SIZE_4MB
:
1741 xgi_video_info
.video_size
= 0x400000;
1743 case XGI_DRAM_SIZE_8MB
:
1744 xgi_video_info
.video_size
= 0x800000;
1746 case XGI_DRAM_SIZE_16MB
:
1747 xgi_video_info
.video_size
= 0x1000000;
1749 case XGI_DRAM_SIZE_32MB
:
1750 xgi_video_info
.video_size
= 0x2000000;
1752 case XGI_DRAM_SIZE_64MB
:
1753 xgi_video_info
.video_size
= 0x4000000;
1755 case XGI_DRAM_SIZE_128MB
:
1756 xgi_video_info
.video_size
= 0x8000000;
1758 case XGI_DRAM_SIZE_256MB
:
1759 xgi_video_info
.video_size
= 0x10000000;
1765 tmp
= (reg
& 0x0c) >> 2;
1766 switch(xgi_video_info
.chip
)
1807 xgi_video_info
.video_size
= xgi_video_info
.video_size
* ChannelNum
;
1808 //PLiad fixed for benchmarking and fb set
1809 //xgi_video_info.video_size = 0x200000;//1024x768x16
1810 //xgi_video_info.video_size = 0x1000000;//benchmark
1812 printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n",reg
,xgi_video_info
.video_size
,ChannelNum
);
1817 static void XGIfb_detect_VB(void)
1821 xgi_video_info
.TV_plug
= xgi_video_info
.TV_type
= 0;
1823 switch(xgi_video_info
.hasVB
) {
1824 case HASVB_LVDS_CHRONTEL
:
1825 case HASVB_CHRONTEL
:
1829 // XGI_Sense30x(); //Yi-Lin TV Sense?
1833 inXGIIDXREG(XGICR
, IND_XGI_SCRATCH_REG_CR32
, cr32
);
1835 if ((cr32
& XGI_CRT1
) && !XGIfb_crt1off
)
1844 if (XGIfb_crt2type
!= -1)
1845 /* TW: Override with option */
1846 xgi_video_info
.disp_state
= XGIfb_crt2type
;
1847 else if (cr32
& XGI_VB_TV
)
1848 xgi_video_info
.disp_state
= DISPTYPE_TV
;
1849 else if (cr32
& XGI_VB_LCD
)
1850 xgi_video_info
.disp_state
= DISPTYPE_LCD
;
1851 else if (cr32
& XGI_VB_CRT2
)
1852 xgi_video_info
.disp_state
= DISPTYPE_CRT2
;
1854 xgi_video_info
.disp_state
= 0;
1856 if(XGIfb_tvplug
!= -1)
1857 /* PR/TW: Override with option */
1858 xgi_video_info
.TV_plug
= XGIfb_tvplug
;
1859 else if (cr32
& XGI_VB_HIVISION
) {
1860 xgi_video_info
.TV_type
= TVMODE_HIVISION
;
1861 xgi_video_info
.TV_plug
= TVPLUG_SVIDEO
;
1863 else if (cr32
& XGI_VB_SVIDEO
)
1864 xgi_video_info
.TV_plug
= TVPLUG_SVIDEO
;
1865 else if (cr32
& XGI_VB_COMPOSITE
)
1866 xgi_video_info
.TV_plug
= TVPLUG_COMPOSITE
;
1867 else if (cr32
& XGI_VB_SCART
)
1868 xgi_video_info
.TV_plug
= TVPLUG_SCART
;
1870 if(xgi_video_info
.TV_type
== 0) {
1871 /* TW: PAL/NTSC changed for 650 */
1872 if((xgi_video_info
.chip
<= XGI_315PRO
) || (xgi_video_info
.chip
>= XGI_330
)) {
1874 inXGIIDXREG(XGICR
, 0x38, temp
);
1876 xgi_video_info
.TV_type
= TVMODE_PAL
;
1878 xgi_video_info
.TV_type
= TVMODE_NTSC
;
1882 inXGIIDXREG(XGICR
, 0x79, temp
);
1884 xgi_video_info
.TV_type
= TVMODE_PAL
;
1886 xgi_video_info
.TV_type
= TVMODE_NTSC
;
1890 /* TW: Copy forceCRT1 option to CRT1off if option is given */
1891 if (XGIfb_forcecrt1
!= -1) {
1892 if (XGIfb_forcecrt1
) XGIfb_crt1off
= 0;
1893 else XGIfb_crt1off
= 1;
1897 static void XGIfb_get_VB_type(void)
1901 if (!XGIfb_has_VB()) {
1902 inXGIIDXREG(XGICR
, IND_XGI_SCRATCH_REG_CR37
, reg
);
1903 switch ((reg
& XGI_EXTERNAL_CHIP_MASK
) >> 1) {
1904 case XGI310_EXTERNAL_CHIP_LVDS
:
1905 xgi_video_info
.hasVB
= HASVB_LVDS
;
1907 case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL
:
1908 xgi_video_info
.hasVB
= HASVB_LVDS_CHRONTEL
;
1917 static int XGIfb_has_VB(void)
1921 inXGIIDXREG(XGIPART4
, 0x00, vb_chipid
);
1922 switch (vb_chipid
) {
1924 xgi_video_info
.hasVB
= HASVB_301
;
1927 xgi_video_info
.hasVB
= HASVB_302
;
1930 xgi_video_info
.hasVB
= HASVB_NONE
;
1938 /* ------------------ Sensing routines ------------------ */
1940 /* TW: Determine and detect attached devices on XGI30x */
1942 XGIDoSense(int tempbl
, int tempbh
, int tempcl
, int tempch
)
1946 outXGIIDXREG(XGIPART4
,0x11,tempbl
);
1947 temp
= tempbh
| tempcl
;
1948 setXGIIDXREG(XGIPART4
,0x10,0xe0,temp
);
1949 for(i
=0; i
<10; i
++) XGI_LongWait(&XGI_Pr
);
1951 inXGIIDXREG(XGIPART4
,0x03,temp
);
1961 u8 testsvhs_tempbl
, testsvhs_tempbh
;
1962 u8 testsvhs_tempcl
, testsvhs_tempch
;
1963 u8 testcvbs_tempbl
, testcvbs_tempbh
;
1964 u8 testcvbs_tempcl
, testcvbs_tempch
;
1965 u8 testvga2_tempbl
, testvga2_tempbh
;
1966 u8 testvga2_tempcl
, testvga2_tempch
;
1969 inXGIIDXREG(XGIPART4
,0x0d,backupP4_0d
);
1970 outXGIIDXREG(XGIPART4
,0x0d,(backupP4_0d
| 0x04));
1974 testvga2_tempbh
= 0x00; testvga2_tempbl
= 0xd1;
1975 testsvhs_tempbh
= 0x00; testsvhs_tempbl
= 0xb9;
1976 testcvbs_tempbh
= 0x00; testcvbs_tempbl
= 0xb3;
1977 if((XGIhw_ext
.ujVBChipID
!= VB_CHIP_301
) &&
1978 (XGIhw_ext
.ujVBChipID
!= VB_CHIP_302
)) {
1979 testvga2_tempbh
= 0x01; testvga2_tempbl
= 0x90;
1980 testsvhs_tempbh
= 0x01; testsvhs_tempbl
= 0x6b;
1981 testcvbs_tempbh
= 0x01; testcvbs_tempbl
= 0x74;
1982 if(XGIhw_ext
.ujVBChipID
== VB_CHIP_301LV
||
1983 XGIhw_ext
.ujVBChipID
== VB_CHIP_302LV
) {
1984 testvga2_tempbh
= 0x00; testvga2_tempbl
= 0x00;
1985 testsvhs_tempbh
= 0x02; testsvhs_tempbl
= 0x00;
1986 testcvbs_tempbh
= 0x01; testcvbs_tempbl
= 0x00;
1989 if(XGIhw_ext
.ujVBChipID
!= VB_CHIP_301LV
&&
1990 XGIhw_ext
.ujVBChipID
!= VB_CHIP_302LV
) {
1991 inXGIIDXREG(XGIPART4
,0x01,myflag
);
1993 testvga2_tempbh
= 0x00; testvga2_tempbl
= 0xfd;
1994 testsvhs_tempbh
= 0x00; testsvhs_tempbl
= 0xdd;
1995 testcvbs_tempbh
= 0x00; testcvbs_tempbl
= 0xee;
1998 if((XGIhw_ext
.ujVBChipID
== VB_CHIP_301LV
) ||
1999 (XGIhw_ext
.ujVBChipID
== VB_CHIP_302LV
) ) {
2000 testvga2_tempbh
= 0x00; testvga2_tempbl
= 0x00;
2001 testvga2_tempch
= 0x00; testvga2_tempcl
= 0x00;
2002 testsvhs_tempch
= 0x04; testsvhs_tempcl
= 0x08;
2003 testcvbs_tempch
= 0x08; testcvbs_tempcl
= 0x08;
2005 testvga2_tempch
= 0x0e; testvga2_tempcl
= 0x08;
2006 testsvhs_tempch
= 0x06; testsvhs_tempcl
= 0x04;
2007 testcvbs_tempch
= 0x08; testcvbs_tempcl
= 0x04;
2011 if(testvga2_tempch
|| testvga2_tempcl
|| testvga2_tempbh
|| testvga2_tempbl
) {
2012 result
= XGIDoSense(testvga2_tempbl
, testvga2_tempbh
,
2013 testvga2_tempcl
, testvga2_tempch
);
2015 printk(KERN_INFO
"XGIfb: Detected secondary VGA connection\n");
2016 orXGIIDXREG(XGICR
, 0x32, 0x10);
2020 result
= XGIDoSense(testsvhs_tempbl
, testsvhs_tempbh
,
2021 testsvhs_tempcl
, testsvhs_tempch
);
2023 printk(KERN_INFO
"XGIfb: Detected TV connected to SVHS output\n");
2024 /* TW: So we can be sure that there IS a SVHS output */
2025 xgi_video_info
.TV_plug
= TVPLUG_SVIDEO
;
2026 orXGIIDXREG(XGICR
, 0x32, 0x02);
2030 result
= XGIDoSense(testcvbs_tempbl
, testcvbs_tempbh
,
2031 testcvbs_tempcl
, testcvbs_tempch
);
2033 printk(KERN_INFO
"XGIfb: Detected TV connected to CVBS output\n");
2034 /* TW: So we can be sure that there IS a CVBS output */
2035 xgi_video_info
.TV_plug
= TVPLUG_COMPOSITE
;
2036 orXGIIDXREG(XGICR
, 0x32, 0x01);
2039 XGIDoSense(0, 0, 0, 0);
2041 outXGIIDXREG(XGIPART4
,0x0d,backupP4_0d
);
2046 /* ------------------------ Heap routines -------------------------- */
2048 static int XGIfb_heap_init(void)
2053 int agp_enabled
= 1;
2055 unsigned long *cmdq_baseport
= 0;
2056 unsigned long *read_port
= 0;
2057 unsigned long *write_port
= 0;
2058 XGI_CMDTYPE cmd_type
;
2060 struct agp_kern_info
*agp_info
;
2061 struct agp_memory
*agp
;
2065 /* TW: The heap start is either set manually using the "mem" parameter, or
2066 * defaults as follows:
2067 * -) If more than 16MB videoRAM available, let our heap start at 12MB.
2068 * -) If more than 8MB videoRAM available, let our heap start at 8MB.
2069 * -) If 4MB or less is available, let it start at 4MB.
2070 * This is for avoiding a clash with X driver which uses the beginning
2071 * of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem
2073 * The heap start can also be specified by parameter "mem" when starting the XGIfb
2074 * driver. XGIfb mem=1024 lets heap starts at 1MB, etc.
2076 if ((!XGIfb_mem
) || (XGIfb_mem
> (xgi_video_info
.video_size
/1024))) {
2077 if (xgi_video_info
.video_size
> 0x1000000) {
2078 xgi_video_info
.heapstart
= 0xD00000;
2079 } else if (xgi_video_info
.video_size
> 0x800000) {
2080 xgi_video_info
.heapstart
= 0x800000;
2082 xgi_video_info
.heapstart
= 0x400000;
2085 xgi_video_info
.heapstart
= XGIfb_mem
* 1024;
2088 (unsigned long) (xgi_video_info
.video_vbase
+ xgi_video_info
.heapstart
);
2089 printk(KERN_INFO
"XGIfb: Memory heap starting at %dK\n",
2090 (int)(xgi_video_info
.heapstart
/ 1024));
2092 XGIfb_heap_end
= (unsigned long) xgi_video_info
.video_vbase
+ xgi_video_info
.video_size
;
2093 XGIfb_heap_size
= XGIfb_heap_end
- XGIfb_heap_start
;
2097 /* TW: Now initialize the 310 series' command queue mode.
2098 * On 310/325, there are three queue modes available which
2099 * are chosen by setting bits 7:5 in SR26:
2100 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
2101 * track of the queue, the FIFO, command parsing and so
2102 * on. This is the one comparable to the 300 series.
2103 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will
2104 * have to do queue management himself. Register 0x85c4 will
2105 * hold the location of the next free queue slot, 0x85c8
2106 * is the "queue read pointer" whose way of working is
2107 * unknown to me. Anyway, this mode would require a
2108 * translation of the MMIO commands to some kind of
2109 * accelerator assembly and writing these commands
2110 * to the memory location pointed to by 0x85c4.
2111 * We will not use this, as nobody knows how this
2112 * "assembly" works, and as it would require a complete
2113 * re-write of the accelerator code.
2114 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the
2115 * queue in AGP memory space.
2117 * SR26 bit 4 is called "Bypass H/W queue".
2118 * SR26 bit 1 is called "Enable Command Queue Auto Correction"
2119 * SR26 bit 0 resets the queue
2120 * Size of queue memory is encoded in bits 3:2 like this:
2125 * The queue location is to be written to 0x85C0.
2128 cmdq_baseport
= (unsigned long *)(xgi_video_info
.mmio_vbase
+ MMIO_QUEUE_PHYBASE
);
2129 write_port
= (unsigned long *)(xgi_video_info
.mmio_vbase
+ MMIO_QUEUE_WRITEPORT
);
2130 read_port
= (unsigned long *)(xgi_video_info
.mmio_vbase
+ MMIO_QUEUE_READPORT
);
2132 DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport
, read_port
, write_port
);
2134 agp_size
= COMMAND_QUEUE_AREA_SIZE
;
2137 if (XGIfb_queuemode
== AGP_CMD_QUEUE
) {
2138 agp_info
= vmalloc(sizeof(*agp_info
));
2139 memset((void*)agp_info
, 0x00, sizeof(*agp_info
));
2140 agp_copy_info(agp_info
);
2142 agp_backend_acquire();
2144 agp
= agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE
/PAGE_SIZE
,
2147 DPRINTK("XGIfb: Allocating AGP buffer failed.\n");
2150 if (agp_bind_memory(agp
, agp
->pg_start
) != 0) {
2151 DPRINTK("XGIfb: AGP: Failed to bind memory\n");
2152 /* TODO: Free AGP memory here */
2163 /* TW: Now select the queue mode */
2165 if ((agp_enabled
) && (XGIfb_queuemode
== AGP_CMD_QUEUE
)) {
2166 cmd_type
= AGP_CMD_QUEUE
;
2167 printk(KERN_INFO
"XGIfb: Using AGP queue mode\n");
2168 /* } else if (XGIfb_heap_size >= COMMAND_QUEUE_AREA_SIZE) */
2169 } else if (XGIfb_queuemode
== VM_CMD_QUEUE
) {
2170 cmd_type
= VM_CMD_QUEUE
;
2171 printk(KERN_INFO
"XGIfb: Using VRAM queue mode\n");
2173 printk(KERN_INFO
"XGIfb: Using MMIO queue mode\n");
2174 cmd_type
= MMIO_CMD
;
2179 temp
= XGI_CMD_QUEUE_SIZE_512k
;
2182 temp
= XGI_CMD_QUEUE_SIZE_1M
;
2185 temp
= XGI_CMD_QUEUE_SIZE_2M
;
2188 temp
= XGI_CMD_QUEUE_SIZE_4M
;
2195 DPRINTK("XGIfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n",
2196 agp_info
->aper_base
, agp
->physical
, agp_size
/1024);
2198 agp_phys
= agp_info
->aper_base
+ agp
->physical
;
2200 outXGIIDXREG(XGICR
, IND_XGI_AGP_IO_PAD
, 0);
2201 outXGIIDXREG(XGICR
, IND_XGI_AGP_IO_PAD
, XGI_AGP_2X
);
2203 outXGIIDXREG(XGISR
, IND_XGI_CMDQUEUE_THRESHOLD
, COMMAND_QUEUE_THRESHOLD
);
2205 outXGIIDXREG(XGISR
, IND_XGI_CMDQUEUE_SET
, XGI_CMD_QUEUE_RESET
);
2207 *write_port
= *read_port
;
2209 temp
|= XGI_AGP_CMDQUEUE_ENABLE
;
2210 outXGIIDXREG(XGISR
, IND_XGI_CMDQUEUE_SET
, temp
);
2212 *cmdq_baseport
= agp_phys
;
2214 XGIfb_caps
|= AGP_CMD_QUEUE_CAP
;
2219 XGIfb_heap_end
-= COMMAND_QUEUE_AREA_SIZE
;
2220 XGIfb_heap_size
-= COMMAND_QUEUE_AREA_SIZE
;
2222 outXGIIDXREG(XGISR
, IND_XGI_CMDQUEUE_THRESHOLD
, COMMAND_QUEUE_THRESHOLD
);
2224 outXGIIDXREG(XGISR
, IND_XGI_CMDQUEUE_SET
, XGI_CMD_QUEUE_RESET
);
2226 *write_port
= *read_port
;
2228 temp
|= XGI_VRAM_CMDQUEUE_ENABLE
;
2229 outXGIIDXREG(XGISR
, IND_XGI_CMDQUEUE_SET
, temp
);
2231 *cmdq_baseport
= xgi_video_info
.video_size
- COMMAND_QUEUE_AREA_SIZE
;
2233 XGIfb_caps
|= VM_CMD_QUEUE_CAP
;
2235 DPRINTK("XGIfb: VM Cmd Queue offset = 0x%lx, size is %dK\n",
2236 *cmdq_baseport
, COMMAND_QUEUE_AREA_SIZE
/1024);
2241 // printk("%s:%d - I'm here\n", __FUNCTION__, __LINE__);
2242 /* TW: This previously only wrote XGI_MMIO_CMD_ENABLE
2243 * to IND_XGI_CMDQUEUE_SET. I doubt that this is
2244 * enough. Reserve memory in any way.
2252 /* TW: Now reserve memory for the HWCursor. It is always located at the very
2253 top of the videoRAM, right below the TB memory area (if used). */
2254 if (XGIfb_heap_size
>= XGIfb_hwcursor_size
) {
2255 XGIfb_heap_end
-= XGIfb_hwcursor_size
;
2256 XGIfb_heap_size
-= XGIfb_hwcursor_size
;
2257 XGIfb_hwcursor_vbase
= XGIfb_heap_end
;
2259 XGIfb_caps
|= HW_CURSOR_CAP
;
2261 DPRINTK("XGIfb: Hardware Cursor start at 0x%lx, size is %dK\n",
2262 XGIfb_heap_end
, XGIfb_hwcursor_size
/1024);
2265 XGIfb_heap
.poha_chain
= NULL
;
2266 XGIfb_heap
.poh_freelist
= NULL
;
2268 poh
= XGIfb_poh_new_node();
2270 if(poh
== NULL
) return 1;
2272 poh
->poh_next
= &XGIfb_heap
.oh_free
;
2273 poh
->poh_prev
= &XGIfb_heap
.oh_free
;
2274 poh
->size
= XGIfb_heap_end
- XGIfb_heap_start
+ 1;
2275 poh
->offset
= XGIfb_heap_start
- (unsigned long) xgi_video_info
.video_vbase
;
2277 DPRINTK("XGIfb: Heap start:0x%p, end:0x%p, len=%dk\n",
2278 (char *) XGIfb_heap_start
, (char *) XGIfb_heap_end
,
2279 (unsigned int) poh
->size
/ 1024);
2281 DPRINTK("XGIfb: First Node offset:0x%x, size:%dk\n",
2282 (unsigned int) poh
->offset
, (unsigned int) poh
->size
/ 1024);
2284 XGIfb_heap
.oh_free
.poh_next
= poh
;
2285 XGIfb_heap
.oh_free
.poh_prev
= poh
;
2286 XGIfb_heap
.oh_free
.size
= 0;
2287 XGIfb_heap
.max_freesize
= poh
->size
;
2289 XGIfb_heap
.oh_used
.poh_next
= &XGIfb_heap
.oh_used
;
2290 XGIfb_heap
.oh_used
.poh_prev
= &XGIfb_heap
.oh_used
;
2291 XGIfb_heap
.oh_used
.size
= SENTINEL
;
2296 static XGI_OH
*XGIfb_poh_new_node(void)
2303 if (XGIfb_heap
.poh_freelist
== NULL
) {
2304 poha
= kmalloc(OH_ALLOC_SIZE
, GFP_KERNEL
);
2305 if(!poha
) return NULL
;
2307 poha
->poha_next
= XGIfb_heap
.poha_chain
;
2308 XGIfb_heap
.poha_chain
= poha
;
2310 cOhs
= (OH_ALLOC_SIZE
- sizeof(XGI_OHALLOC
)) / sizeof(XGI_OH
) + 1;
2312 poh
= &poha
->aoh
[0];
2313 for (i
= cOhs
- 1; i
!= 0; i
--) {
2314 poh
->poh_next
= poh
+ 1;
2318 poh
->poh_next
= NULL
;
2319 XGIfb_heap
.poh_freelist
= &poha
->aoh
[0];
2322 poh
= XGIfb_heap
.poh_freelist
;
2323 XGIfb_heap
.poh_freelist
= poh
->poh_next
;
2328 static XGI_OH
*XGIfb_poh_allocate(unsigned long size
)
2334 if (size
> XGIfb_heap
.max_freesize
) {
2335 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2336 (unsigned int) size
/ 1024);
2340 pohThis
= XGIfb_heap
.oh_free
.poh_next
;
2342 while (pohThis
!= &XGIfb_heap
.oh_free
) {
2343 if (size
<= pohThis
->size
) {
2347 pohThis
= pohThis
->poh_next
;
2351 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2352 (unsigned int) size
/ 1024);
2356 if (size
== pohThis
->size
) {
2358 XGIfb_delete_node(pohThis
);
2360 pohRoot
= XGIfb_poh_new_node();
2362 if (pohRoot
== NULL
) {
2366 pohRoot
->offset
= pohThis
->offset
;
2367 pohRoot
->size
= size
;
2369 pohThis
->offset
+= size
;
2370 pohThis
->size
-= size
;
2373 XGIfb_heap
.max_freesize
-= size
;
2375 pohThis
= &XGIfb_heap
.oh_used
;
2376 XGIfb_insert_node(pohThis
, pohRoot
);
2381 static void XGIfb_delete_node(XGI_OH
*poh
)
2386 poh_prev
= poh
->poh_prev
;
2387 poh_next
= poh
->poh_next
;
2389 poh_prev
->poh_next
= poh_next
;
2390 poh_next
->poh_prev
= poh_prev
;
2394 static void XGIfb_insert_node(XGI_OH
*pohList
, XGI_OH
*poh
)
2398 pohTemp
= pohList
->poh_next
;
2400 pohList
->poh_next
= poh
;
2401 pohTemp
->poh_prev
= poh
;
2403 poh
->poh_prev
= pohList
;
2404 poh
->poh_next
= pohTemp
;
2407 static XGI_OH
*XGIfb_poh_free(unsigned long base
)
2413 unsigned long ulUpper
;
2414 unsigned long ulLower
;
2417 poh_freed
= XGIfb_heap
.oh_used
.poh_next
;
2419 while(poh_freed
!= &XGIfb_heap
.oh_used
) {
2420 if(poh_freed
->offset
== base
) {
2425 poh_freed
= poh_freed
->poh_next
;
2428 if (!foundNode
) return (NULL
);
2430 XGIfb_heap
.max_freesize
+= poh_freed
->size
;
2432 poh_prev
= poh_next
= NULL
;
2433 ulUpper
= poh_freed
->offset
+ poh_freed
->size
;
2434 ulLower
= poh_freed
->offset
;
2436 pohThis
= XGIfb_heap
.oh_free
.poh_next
;
2438 while (pohThis
!= &XGIfb_heap
.oh_free
) {
2439 if (pohThis
->offset
== ulUpper
) {
2442 else if ((pohThis
->offset
+ pohThis
->size
) ==
2446 pohThis
= pohThis
->poh_next
;
2449 XGIfb_delete_node(poh_freed
);
2451 if (poh_prev
&& poh_next
) {
2452 poh_prev
->size
+= (poh_freed
->size
+ poh_next
->size
);
2453 XGIfb_delete_node(poh_next
);
2454 XGIfb_free_node(poh_freed
);
2455 XGIfb_free_node(poh_next
);
2460 poh_prev
->size
+= poh_freed
->size
;
2461 XGIfb_free_node(poh_freed
);
2466 poh_next
->size
+= poh_freed
->size
;
2467 poh_next
->offset
= poh_freed
->offset
;
2468 XGIfb_free_node(poh_freed
);
2472 XGIfb_insert_node(&XGIfb_heap
.oh_free
, poh_freed
);
2477 static void XGIfb_free_node(XGI_OH
*poh
)
2479 if(poh
== NULL
) return;
2481 poh
->poh_next
= XGIfb_heap
.poh_freelist
;
2482 XGIfb_heap
.poh_freelist
= poh
;
2486 void XGI_malloc(struct XGI_memreq
*req
)
2490 poh
= XGIfb_poh_allocate(req
->size
);
2495 DPRINTK("XGIfb: Video RAM allocation failed\n");
2497 DPRINTK("XGIfb: Video RAM allocation succeeded: 0x%p\n",
2498 (char *) (poh
->offset
+ (unsigned long) xgi_video_info
.video_vbase
));
2500 req
->offset
= poh
->offset
;
2501 req
->size
= poh
->size
;
2506 void XGI_free(unsigned long base
)
2510 poh
= XGIfb_poh_free(base
);
2513 DPRINTK("XGIfb: XGIfb_poh_free() failed at base 0x%x\n",
2514 (unsigned int) base
);
2518 /* --------------------- SetMode routines ------------------------- */
2520 static void XGIfb_pre_setmode(void)
2522 u8 cr30
= 0, cr31
= 0;
2524 inXGIIDXREG(XGICR
, 0x31, cr31
);
2527 switch (xgi_video_info
.disp_state
& DISPTYPE_DISP2
) {
2529 cr30
= (XGI_VB_OUTPUT_CRT2
| XGI_SIMULTANEOUS_VIEW_ENABLE
);
2530 cr31
|= XGI_DRIVER_MODE
;
2533 cr30
= (XGI_VB_OUTPUT_LCD
| XGI_SIMULTANEOUS_VIEW_ENABLE
);
2534 cr31
|= XGI_DRIVER_MODE
;
2537 if (xgi_video_info
.TV_type
== TVMODE_HIVISION
)
2538 cr30
= (XGI_VB_OUTPUT_HIVISION
| XGI_SIMULTANEOUS_VIEW_ENABLE
);
2539 else if (xgi_video_info
.TV_plug
== TVPLUG_SVIDEO
)
2540 cr30
= (XGI_VB_OUTPUT_SVIDEO
| XGI_SIMULTANEOUS_VIEW_ENABLE
);
2541 else if (xgi_video_info
.TV_plug
== TVPLUG_COMPOSITE
)
2542 cr30
= (XGI_VB_OUTPUT_COMPOSITE
| XGI_SIMULTANEOUS_VIEW_ENABLE
);
2543 else if (xgi_video_info
.TV_plug
== TVPLUG_SCART
)
2544 cr30
= (XGI_VB_OUTPUT_SCART
| XGI_SIMULTANEOUS_VIEW_ENABLE
);
2545 cr31
|= XGI_DRIVER_MODE
;
2547 if (XGIfb_tvmode
== 1 || xgi_video_info
.TV_type
== TVMODE_PAL
)
2552 default: /* disable CRT2 */
2554 cr31
|= (XGI_DRIVER_MODE
| XGI_VB_OUTPUT_DISABLE
);
2557 outXGIIDXREG(XGICR
, IND_XGI_SCRATCH_REG_CR30
, cr30
);
2558 outXGIIDXREG(XGICR
, IND_XGI_SCRATCH_REG_CR31
, cr31
);
2559 outXGIIDXREG(XGICR
, IND_XGI_SCRATCH_REG_CR33
, (XGIfb_rate_idx
& 0x0F));
2561 if(xgi_video_info
.accel
) XGIfb_syncaccel();
2566 static void XGIfb_post_setmode(void)
2569 unsigned char doit
= 1;
2570 /* outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
2571 outXGIIDXREG(XGICR,0x13,0x00);
2572 setXGIIDXREG(XGISR,0x0E,0xF0,0x01);
2574 if (xgi_video_info
.video_bpp
== 8) {
2575 /* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */
2576 if ((xgi_video_info
.hasVB
== HASVB_LVDS
) || (xgi_video_info
.hasVB
== HASVB_LVDS_CHRONTEL
)) {
2579 /* TW: We can't switch off CRT1 on 301B-DH in 8bpp Modes if using LCD */
2580 if (xgi_video_info
.disp_state
& DISPTYPE_LCD
) {
2585 /* TW: We can't switch off CRT1 if bridge is in slave mode */
2586 if(xgi_video_info
.hasVB
!= HASVB_NONE
) {
2587 inXGIIDXREG(XGIPART1
, 0x00, reg
);
2590 if ((reg
& 0x50) == 0x10)
2597 inXGIIDXREG(XGICR
, 0x17, reg
);
2598 if ((XGIfb_crt1off
) && (doit
))
2602 outXGIIDXREG(XGICR
, 0x17, reg
);
2604 andXGIIDXREG(XGISR
, IND_XGI_RAMDAC_CONTROL
, ~0x04);
2606 if((xgi_video_info
.disp_state
& DISPTYPE_TV
) && (xgi_video_info
.hasVB
== HASVB_301
)) {
2608 inXGIIDXREG(XGIPART4
, 0x01, reg
);
2610 if(reg
< 0xB0) { /* Set filter for XGI301 */
2612 switch (xgi_video_info
.video_width
) {
2614 filter_tb
= (xgi_video_info
.TV_type
== TVMODE_NTSC
) ? 4 : 12;
2617 filter_tb
= (xgi_video_info
.TV_type
== TVMODE_NTSC
) ? 5 : 13;
2620 filter_tb
= (xgi_video_info
.TV_type
== TVMODE_NTSC
) ? 6 : 14;
2623 filter_tb
= (xgi_video_info
.TV_type
== TVMODE_NTSC
) ? 7 : 15;
2630 orXGIIDXREG(XGIPART1
, XGIfb_CRT2_write_enable
, 0x01);
2632 if(xgi_video_info
.TV_type
== TVMODE_NTSC
) {
2634 andXGIIDXREG(XGIPART2
, 0x3a, 0x1f);
2636 if (xgi_video_info
.TV_plug
== TVPLUG_SVIDEO
) {
2638 andXGIIDXREG(XGIPART2
, 0x30, 0xdf);
2640 } else if (xgi_video_info
.TV_plug
== TVPLUG_COMPOSITE
) {
2642 orXGIIDXREG(XGIPART2
, 0x30, 0x20);
2644 switch (xgi_video_info
.video_width
) {
2646 outXGIIDXREG(XGIPART2
, 0x35, 0xEB);
2647 outXGIIDXREG(XGIPART2
, 0x36, 0x04);
2648 outXGIIDXREG(XGIPART2
, 0x37, 0x25);
2649 outXGIIDXREG(XGIPART2
, 0x38, 0x18);
2652 outXGIIDXREG(XGIPART2
, 0x35, 0xEE);
2653 outXGIIDXREG(XGIPART2
, 0x36, 0x0C);
2654 outXGIIDXREG(XGIPART2
, 0x37, 0x22);
2655 outXGIIDXREG(XGIPART2
, 0x38, 0x08);
2658 outXGIIDXREG(XGIPART2
, 0x35, 0xEB);
2659 outXGIIDXREG(XGIPART2
, 0x36, 0x15);
2660 outXGIIDXREG(XGIPART2
, 0x37, 0x25);
2661 outXGIIDXREG(XGIPART2
, 0x38, 0xF6);
2666 } else if(xgi_video_info
.TV_type
== TVMODE_PAL
) {
2668 andXGIIDXREG(XGIPART2
, 0x3A, 0x1F);
2670 if (xgi_video_info
.TV_plug
== TVPLUG_SVIDEO
) {
2672 andXGIIDXREG(XGIPART2
, 0x30, 0xDF);
2674 } else if (xgi_video_info
.TV_plug
== TVPLUG_COMPOSITE
) {
2676 orXGIIDXREG(XGIPART2
, 0x30, 0x20);
2678 switch (xgi_video_info
.video_width
) {
2680 outXGIIDXREG(XGIPART2
, 0x35, 0xF1);
2681 outXGIIDXREG(XGIPART2
, 0x36, 0xF7);
2682 outXGIIDXREG(XGIPART2
, 0x37, 0x1F);
2683 outXGIIDXREG(XGIPART2
, 0x38, 0x32);
2686 outXGIIDXREG(XGIPART2
, 0x35, 0xF3);
2687 outXGIIDXREG(XGIPART2
, 0x36, 0x00);
2688 outXGIIDXREG(XGIPART2
, 0x37, 0x1D);
2689 outXGIIDXREG(XGIPART2
, 0x38, 0x20);
2692 outXGIIDXREG(XGIPART2
, 0x35, 0xFC);
2693 outXGIIDXREG(XGIPART2
, 0x36, 0xFB);
2694 outXGIIDXREG(XGIPART2
, 0x37, 0x14);
2695 outXGIIDXREG(XGIPART2
, 0x38, 0x2A);
2701 if ((filter
>= 0) && (filter
<=7)) {
2702 DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb
, filter
,
2703 XGI_TV_filter
[filter_tb
].filter
[filter
][0],
2704 XGI_TV_filter
[filter_tb
].filter
[filter
][1],
2705 XGI_TV_filter
[filter_tb
].filter
[filter
][2],
2706 XGI_TV_filter
[filter_tb
].filter
[filter
][3]
2708 outXGIIDXREG(XGIPART2
, 0x35, (XGI_TV_filter
[filter_tb
].filter
[filter
][0]));
2709 outXGIIDXREG(XGIPART2
, 0x36, (XGI_TV_filter
[filter_tb
].filter
[filter
][1]));
2710 outXGIIDXREG(XGIPART2
, 0x37, (XGI_TV_filter
[filter_tb
].filter
[filter
][2]));
2711 outXGIIDXREG(XGIPART2
, 0x38, (XGI_TV_filter
[filter_tb
].filter
[filter
][3]));
2721 XGIINITSTATIC
int __init
XGIfb_setup(char *options
)
2727 xgi_video_info
.refresh_rate
= 0;
2729 printk(KERN_INFO
"XGIfb: Options %s\n", options
);
2731 if (!options
|| !*options
)
2734 while((this_opt
= strsep(&options
, ",")) != NULL
) {
2736 if (!*this_opt
) continue;
2738 if (!strncmp(this_opt
, "mode:", 5)) {
2739 XGIfb_search_mode(this_opt
+ 5);
2740 } else if (!strncmp(this_opt
, "vesa:", 5)) {
2741 XGIfb_search_vesamode(simple_strtoul(this_opt
+ 5, NULL
, 0));
2742 } else if (!strncmp(this_opt
, "mode:", 5)) {
2743 XGIfb_search_mode(this_opt
+ 5);
2744 } else if (!strncmp(this_opt
, "vesa:", 5)) {
2745 XGIfb_search_vesamode(simple_strtoul(this_opt
+ 5, NULL
, 0));
2746 } else if (!strncmp(this_opt
, "vrate:", 6)) {
2747 xgi_video_info
.refresh_rate
= simple_strtoul(this_opt
+ 6, NULL
, 0);
2748 } else if (!strncmp(this_opt
, "rate:", 5)) {
2749 xgi_video_info
.refresh_rate
= simple_strtoul(this_opt
+ 5, NULL
, 0);
2750 } else if (!strncmp(this_opt
, "off", 3)) {
2752 } else if (!strncmp(this_opt
, "crt1off", 7)) {
2754 } else if (!strncmp(this_opt
, "filter:", 7)) {
2755 filter
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
2756 } else if (!strncmp(this_opt
, "forcecrt2type:", 14)) {
2757 XGIfb_search_crt2type(this_opt
+ 14);
2758 } else if (!strncmp(this_opt
, "forcecrt1:", 10)) {
2759 XGIfb_forcecrt1
= (int)simple_strtoul(this_opt
+ 10, NULL
, 0);
2760 } else if (!strncmp(this_opt
, "tvmode:",7)) {
2761 XGIfb_search_tvstd(this_opt
+ 7);
2762 } else if (!strncmp(this_opt
, "tvstandard:",11)) {
2763 XGIfb_search_tvstd(this_opt
+ 7);
2764 } else if (!strncmp(this_opt
, "mem:",4)) {
2765 XGIfb_mem
= simple_strtoul(this_opt
+ 4, NULL
, 0);
2766 } else if (!strncmp(this_opt
, "dstn", 4)) {
2768 /* TW: DSTN overrules forcecrt2type */
2769 XGIfb_crt2type
= DISPTYPE_LCD
;
2770 } else if (!strncmp(this_opt
, "queuemode:", 10)) {
2771 XGIfb_search_queuemode(this_opt
+ 10);
2772 } else if (!strncmp(this_opt
, "pdc:", 4)) {
2773 XGIfb_pdc
= simple_strtoul(this_opt
+ 4, NULL
, 0);
2774 if(XGIfb_pdc
& ~0x3c) {
2775 printk(KERN_INFO
"XGIfb: Illegal pdc parameter\n");
2778 } else if (!strncmp(this_opt
, "noaccel", 7)) {
2780 } else if (!strncmp(this_opt
, "noypan", 6)) {
2782 } else if (!strncmp(this_opt
, "userom:", 7)) {
2783 XGIfb_userom
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
2784 // } else if (!strncmp(this_opt, "useoem:", 7)) {
2785 // XGIfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
2787 XGIfb_search_mode(this_opt
);
2788 // printk(KERN_INFO "XGIfb: Invalid option %s\n", this_opt);
2791 /* TW: Acceleration only with MMIO mode */
2792 if((XGIfb_queuemode
!= -1) && (XGIfb_queuemode
!= MMIO_CMD
)) {
2796 /* TW: Panning only with acceleration */
2797 if(XGIfb_accel
== 0) XGIfb_ypan
= 0;
2800 printk("\nxgifb: outa xgifb_setup 3450");
2805 static unsigned char VBIOS_BUF
[65535];
2807 unsigned char *attempt_map_rom(struct pci_dev
*dev
, void *copy_address
)
2810 u32 rom_address
= 0;
2813 /* Get the size of the expansion rom */
2814 pci_write_config_dword(dev
, PCI_ROM_ADDRESS
, 0xFFFFFFFF);
2815 pci_read_config_dword(dev
, PCI_ROM_ADDRESS
, &rom_size
);
2816 if ((rom_size
& 0x01) == 0)
2822 rom_size
&= 0xFFFFF800;
2823 rom_size
= (~rom_size
)+1;
2825 rom_address
= pci_resource_start(dev
, 0);
2826 if (rom_address
== 0 || rom_address
== 0xFFFFFFF0)
2828 printk("No suitable rom address found\n"); return NULL
;
2831 printk("ROM Size is %dK, Address is %x\n", rom_size
/1024, rom_address
);
2834 pci_write_config_dword(dev
, PCI_ROM_ADDRESS
, rom_address
| PCI_ROM_ADDRESS_ENABLE
);
2836 /* memcpy(copy_address, rom_address, rom_size); */
2838 unsigned char *virt_addr
= ioremap(rom_address
, 0x8000000);
2840 unsigned char *from
= (unsigned char *)virt_addr
;
2841 unsigned char *to
= (unsigned char *)copy_address
;
2842 for (j
=0; j
<65536 /*rom_size*/; j
++) *to
++ = *from
++;
2845 pci_write_config_dword(dev
, PCI_ROM_ADDRESS
, 0);
2847 printk("Copy is done\n");
2849 return copy_address
;
2852 int __devinit
xgifb_probe(struct pci_dev
*pdev
, const struct pci_device_id
*ent
)
2860 XGIfb_registered
= 0;
2862 memset(&XGIhw_ext
, 0, sizeof(struct xgi_hw_device_info
));
2863 fb_info
= framebuffer_alloc(sizeof(struct fb_info
), &pdev
->dev
);
2864 if(!fb_info
) return -ENOMEM
;
2866 xgi_video_info
.chip_id
= pdev
->device
;
2867 pci_read_config_byte(pdev
, PCI_REVISION_ID
,&xgi_video_info
.revision_id
);
2868 pci_read_config_word(pdev
, PCI_COMMAND
, ®16
);
2869 XGIhw_ext
.jChipRevision
= xgi_video_info
.revision_id
;
2870 XGIvga_enabled
= reg16
& 0x01;
2872 xgi_video_info
.pcibus
= pdev
->bus
->number
;
2873 xgi_video_info
.pcislot
= PCI_SLOT(pdev
->devfn
);
2874 xgi_video_info
.pcifunc
= PCI_FUNC(pdev
->devfn
);
2875 xgi_video_info
.subsysvendor
= pdev
->subsystem_vendor
;
2876 xgi_video_info
.subsysdevice
= pdev
->subsystem_device
;
2878 xgi_video_info
.video_base
= pci_resource_start(pdev
, 0);
2879 xgi_video_info
.mmio_base
= pci_resource_start(pdev
, 1);
2880 XGIfb_mmio_size
= pci_resource_len(pdev
, 1);
2881 xgi_video_info
.vga_base
= pci_resource_start(pdev
, 2) + 0x30;
2882 XGIhw_ext
.pjIOAddress
= (unsigned char *)xgi_video_info
.vga_base
;
2883 //XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30;
2884 printk("XGIfb: Relocate IO address: %lx [%08lx]\n",
2885 (unsigned long)pci_resource_start(pdev
, 2), XGI_Pr
.RelIO
);
2887 if (pci_enable_device(pdev
))
2890 XGIRegInit(&XGI_Pr
, (unsigned long)XGIhw_ext
.pjIOAddress
);
2892 outXGIIDXREG(XGISR
, IND_XGI_PASSWORD
, XGI_PASSWORD
);
2893 inXGIIDXREG(XGISR
, IND_XGI_PASSWORD
, reg1
);
2895 if(reg1
!= 0xa1) /*I/O error */
2897 printk("\nXGIfb: I/O error!!!");
2901 switch (xgi_video_info
.chip_id
) {
2902 case PCI_DEVICE_ID_XG_20
:
2903 orXGIIDXREG(XGICR
, Index_CR_GPIO_Reg3
, GPIOG_EN
);
2904 inXGIIDXREG(XGICR
, Index_CR_GPIO_Reg1
, CR48
);
2905 if (CR48
&GPIOG_READ
)
2906 xgi_video_info
.chip
= XG21
;
2908 xgi_video_info
.chip
= XG20
;
2909 XGIfb_hwcursor_size
= HW_CURSOR_AREA_SIZE_315
* 2;
2910 XGIfb_CRT2_write_enable
= IND_XGI_CRT2_WRITE_ENABLE_315
;
2912 case PCI_DEVICE_ID_XG_40
:
2913 xgi_video_info
.chip
= XG40
;
2914 XGIfb_hwcursor_size
= HW_CURSOR_AREA_SIZE_315
* 2;
2915 XGIfb_CRT2_write_enable
= IND_XGI_CRT2_WRITE_ENABLE_315
;
2917 case PCI_DEVICE_ID_XG_41
:
2918 xgi_video_info
.chip
= XG41
;
2919 XGIfb_hwcursor_size
= HW_CURSOR_AREA_SIZE_315
* 2;
2920 XGIfb_CRT2_write_enable
= IND_XGI_CRT2_WRITE_ENABLE_315
;
2922 case PCI_DEVICE_ID_XG_42
:
2923 xgi_video_info
.chip
= XG42
;
2924 XGIfb_hwcursor_size
= HW_CURSOR_AREA_SIZE_315
* 2;
2925 XGIfb_CRT2_write_enable
= IND_XGI_CRT2_WRITE_ENABLE_315
;
2927 case PCI_DEVICE_ID_XG_27
:
2928 xgi_video_info
.chip
= XG27
;
2929 XGIfb_hwcursor_size
= HW_CURSOR_AREA_SIZE_315
* 2;
2930 XGIfb_CRT2_write_enable
= IND_XGI_CRT2_WRITE_ENABLE_315
;
2936 printk("XGIfb:chipid = %x\n",xgi_video_info
.chip
);
2937 XGIhw_ext
.jChipType
= xgi_video_info
.chip
;
2939 switch (xgi_video_info
.chip
) {
2947 XGIhw_ext
.bIntegratedMMEnabled
= 1;
2955 XGIhw_ext
.pDevice
= NULL
;
2956 if ((xgi_video_info
.chip
== XG21
) || (XGIfb_userom
))
2958 XGIhw_ext
.pjVirtualRomBase
= attempt_map_rom(pdev
, VBIOS_BUF
);
2960 if(XGIhw_ext
.pjVirtualRomBase
)
2961 printk(KERN_INFO
"XGIfb: Video ROM found and mapped to %p\n",XGIhw_ext
.pjVirtualRomBase
);
2963 printk(KERN_INFO
"XGIfb: Video ROM not found\n");
2965 XGIhw_ext
.pjVirtualRomBase
= NULL
;
2966 printk(KERN_INFO
"XGIfb: Video ROM usage disabled\n");
2968 XGIhw_ext
.pjCustomizedROMImage
= NULL
;
2969 XGIhw_ext
.bSkipDramSizing
= 0;
2970 XGIhw_ext
.pQueryVGAConfigSpace
= &XGIfb_query_VGA_config_space
;
2971 // XGIhw_ext.pQueryNorthBridgeSpace = &XGIfb_query_north_bridge_space;
2972 strcpy(XGIhw_ext
.szVBIOSVer
, "0.84");
2975 XGIhw_ext
.pSR
= vmalloc(sizeof(struct XGI_DSReg
) * SR_BUFFER_SIZE
);
2976 if (XGIhw_ext
.pSR
== NULL
)
2978 printk(KERN_ERR
"XGIfb: Fatal error: Allocating SRReg space failed.\n");
2981 XGIhw_ext
.pSR
[0].jIdx
= XGIhw_ext
.pSR
[0].jVal
= 0xFF;
2983 XGIhw_ext
.pCR
= vmalloc(sizeof(struct XGI_DSReg
) * CR_BUFFER_SIZE
);
2984 if (XGIhw_ext
.pCR
== NULL
)
2986 vfree(XGIhw_ext
.pSR
);
2987 printk(KERN_ERR
"XGIfb: Fatal error: Allocating CRReg space failed.\n");
2990 XGIhw_ext
.pCR
[0].jIdx
= XGIhw_ext
.pCR
[0].jVal
= 0xFF;
2995 if (!XGIvga_enabled
)
2997 /* Mapping Max FB Size for 315 Init */
2998 XGIhw_ext
.pjVideoMemoryAddress
= ioremap(xgi_video_info
.video_base
, 0x10000000);
2999 if((xgifb_mode_idx
< 0) || ((XGIbios_mode
[xgifb_mode_idx
].mode_no
) != 0xFF))
3002 printk("XGIfb: XGIInit() ...");
3003 /* XGIInitNewt for LINUXBIOS only */
3004 if(XGIInitNew(&XGIhw_ext
))
3014 outXGIIDXREG(XGISR
, IND_XGI_PASSWORD
, XGI_PASSWORD
);
3022 XGIhw_ext
.pjVideoMemoryAddress
= ioremap(xgi_video_info
.video_base
, 0x10000000);
3023 if((xgifb_mode_idx
< 0) || ((XGIbios_mode
[xgifb_mode_idx
].mode_no
) != 0xFF))
3026 outXGIIDXREG(XGISR
, IND_XGI_PASSWORD
, XGI_PASSWORD
);
3028 // yilin Because no VBIOS DRAM Sizing, Dram size will error.
3029 // Set SR13 ,14 temporarily for UDtech
3030 outXGIIDXREG(XGISR
, 0x13, 0x45);
3031 outXGIIDXREG(XGISR
, 0x14, 0x51);
3037 if (XGIfb_get_dram_size())
3039 vfree(XGIhw_ext
.pSR
);
3040 vfree(XGIhw_ext
.pCR
);
3041 printk(KERN_INFO
"XGIfb: Fatal error: Unable to determine RAM size.\n");
3047 if((xgifb_mode_idx
< 0) || ((XGIbios_mode
[xgifb_mode_idx
].mode_no
) != 0xFF))
3049 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
3050 orXGIIDXREG(XGISR
, IND_XGI_PCI_ADDRESS_SET
, (XGI_PCI_ADDR_ENABLE
| XGI_MEM_MAP_IO_ENABLE
));
3051 /* Enable 2D accelerator engine */
3052 orXGIIDXREG(XGISR
, IND_XGI_MODULE_ENABLE
, XGI_ENABLE_2D
);
3055 XGIhw_ext
.ulVideoMemorySize
= xgi_video_info
.video_size
;
3057 if (!request_mem_region(xgi_video_info
.video_base
, xgi_video_info
.video_size
, "XGIfb FB"))
3058 { printk("unable request memory size %x",xgi_video_info
.video_size
);
3059 printk(KERN_ERR
"XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
3060 printk(KERN_ERR
"XGIfb: Is there another framebuffer driver active?\n");
3061 vfree(XGIhw_ext
.pSR
);
3062 vfree(XGIhw_ext
.pCR
);
3066 if (!request_mem_region(xgi_video_info
.mmio_base
, XGIfb_mmio_size
, "XGIfb MMIO"))
3068 printk(KERN_ERR
"XGIfb: Fatal error: Unable to reserve MMIO region\n");
3069 release_mem_region(xgi_video_info
.video_base
, xgi_video_info
.video_size
);
3070 vfree(XGIhw_ext
.pSR
);
3071 vfree(XGIhw_ext
.pCR
);
3075 xgi_video_info
.video_vbase
= XGIhw_ext
.pjVideoMemoryAddress
=
3076 ioremap(xgi_video_info
.video_base
, xgi_video_info
.video_size
);
3077 xgi_video_info
.mmio_vbase
= ioremap(xgi_video_info
.mmio_base
, XGIfb_mmio_size
);
3079 printk(KERN_INFO
"XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
3080 xgi_video_info
.video_base
, xgi_video_info
.video_vbase
,xgi_video_info
.video_size
/ 1024);
3082 printk(KERN_INFO
"XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
3083 xgi_video_info
.mmio_base
, xgi_video_info
.mmio_vbase
,XGIfb_mmio_size
/ 1024);
3084 printk("XGIfb: XGIInitNew() ...");
3085 if(XGIInitNew(&XGIhw_ext
))
3094 if(XGIfb_heap_init())
3096 printk(KERN_WARNING
"XGIfb: Failed to initialize offscreen memory heap\n");
3100 xgi_video_info
.mtrr
= (unsigned int) 0;
3102 if((xgifb_mode_idx
< 0) || ((XGIbios_mode
[xgifb_mode_idx
].mode_no
) != 0xFF))
3104 xgi_video_info
.hasVB
= HASVB_NONE
;
3105 if((xgi_video_info
.chip
== XG20
)||(xgi_video_info
.chip
== XG27
))
3106 xgi_video_info
.hasVB
= HASVB_NONE
;
3107 else if(xgi_video_info
.chip
== XG21
) {
3108 inXGIIDXREG(XGICR
,0x38,CR38
);
3109 if ((CR38
&0xE0) == 0xC0) {
3110 xgi_video_info
.disp_state
= DISPTYPE_LCD
;
3111 if (!XGIfb_GetXG21LVDSData()) {
3113 for (m
= 0; m
< sizeof(XGI21_LCDCapList
)/sizeof(struct XGI21_LVDSCapStruct
); m
++) {
3114 if ((XGI21_LCDCapList
[m
].LVDSHDE
== XGIbios_mode
[xgifb_mode_idx
].xres
) &&
3115 (XGI21_LCDCapList
[m
].LVDSVDE
== XGIbios_mode
[xgifb_mode_idx
].yres
)) {
3116 XGINew_SetReg1( XGI_Pr
.P3d4
, 0x36, m
) ;
3121 else if ((CR38
&0xE0) == 0x60)
3122 xgi_video_info
.hasVB
= HASVB_CHRONTEL
;
3124 xgi_video_info
.hasVB
= HASVB_NONE
;
3127 XGIfb_get_VB_type();
3129 XGIhw_ext
.ujVBChipID
= VB_CHIP_UNKNOWN
;
3131 XGIhw_ext
.ulExternalChip
= 0;
3133 switch (xgi_video_info
.hasVB
) {
3135 inXGIIDXREG(XGIPART4
, 0x01, reg
);
3137 XGIhw_ext
.ujVBChipID
= VB_CHIP_302LV
;
3138 printk(KERN_INFO
"XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg
);
3139 } else if (reg
>= 0xD0) {
3140 XGIhw_ext
.ujVBChipID
= VB_CHIP_301LV
;
3141 printk(KERN_INFO
"XGIfb: XGI301LV bridge detected (revision 0x%02x)\n",reg
);
3143 /* else if (reg >= 0xB0) {
3144 XGIhw_ext.ujVBChipID = VB_CHIP_301B;
3145 inXGIIDXREG(XGIPART4,0x23,reg1);
3146 printk("XGIfb: XGI301B bridge detected\n");
3149 XGIhw_ext
.ujVBChipID
= VB_CHIP_301
;
3150 printk("XGIfb: XGI301 bridge detected\n");
3154 inXGIIDXREG(XGIPART4
, 0x01, reg
);
3156 XGIhw_ext
.ujVBChipID
= VB_CHIP_302LV
;
3157 printk(KERN_INFO
"XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg
);
3158 } else if (reg
>= 0xD0) {
3159 XGIhw_ext
.ujVBChipID
= VB_CHIP_301LV
;
3160 printk(KERN_INFO
"XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg
);
3161 } else if (reg
>= 0xB0) {
3162 inXGIIDXREG(XGIPART4
,0x23,reg1
);
3164 XGIhw_ext
.ujVBChipID
= VB_CHIP_302B
;
3167 XGIhw_ext
.ujVBChipID
= VB_CHIP_302
;
3168 printk(KERN_INFO
"XGIfb: XGI302 bridge detected\n");
3172 XGIhw_ext
.ulExternalChip
= 0x1;
3173 printk(KERN_INFO
"XGIfb: LVDS transmitter detected\n");
3175 case HASVB_TRUMPION
:
3176 XGIhw_ext
.ulExternalChip
= 0x2;
3177 printk(KERN_INFO
"XGIfb: Trumpion Zurac LVDS scaler detected\n");
3179 case HASVB_CHRONTEL
:
3180 XGIhw_ext
.ulExternalChip
= 0x4;
3181 printk(KERN_INFO
"XGIfb: Chrontel TV encoder detected\n");
3183 case HASVB_LVDS_CHRONTEL
:
3184 XGIhw_ext
.ulExternalChip
= 0x5;
3185 printk(KERN_INFO
"XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
3188 printk(KERN_INFO
"XGIfb: No or unknown bridge type detected\n");
3192 if (xgi_video_info
.hasVB
!= HASVB_NONE
) {
3196 if (xgi_video_info
.disp_state
& DISPTYPE_DISP2
) {
3198 xgi_video_info
.disp_state
|= DISPMODE_SINGLE
;
3200 xgi_video_info
.disp_state
|= (DISPMODE_MIRROR
| DISPTYPE_CRT1
);
3202 xgi_video_info
.disp_state
= DISPMODE_SINGLE
| DISPTYPE_CRT1
;
3205 if (xgi_video_info
.disp_state
& DISPTYPE_LCD
) {
3207 inXGIIDXREG(XGICR
, IND_XGI_LCD_PANEL
, reg
);
3209 XGIhw_ext
.ulCRT2LCDType
= XGI310paneltype
[reg
];
3213 XGIhw_ext
.ulCRT2LCDType
= LCD_320x480
;
3217 XGIfb_detectedpdc
= 0;
3219 XGIfb_detectedlcda
= 0xff;
3222 /* TW: Try to find about LCDA */
3224 if((XGIhw_ext
.ujVBChipID
== VB_CHIP_302B
) ||
3225 (XGIhw_ext
.ujVBChipID
== VB_CHIP_301LV
) ||
3226 (XGIhw_ext
.ujVBChipID
== VB_CHIP_302LV
))
3229 inXGIIDXREG(XGICR
,0x34,tmp
);
3232 // Currently on LCDA? (Some BIOSes leave CR38)
3233 inXGIIDXREG(XGICR
,0x38,tmp
);
3234 if((tmp
& 0x03) == 0x03)
3236 /* XGI_Pr.XGI_UseLCDA = 1; */
3239 // Currently on LCDA? (Some newer BIOSes set D0 in CR35)
3240 inXGIIDXREG(XGICR
,0x35,tmp
);
3243 /* XGI_Pr.XGI_UseLCDA = 1; */
3246 inXGIIDXREG(XGICR
,0x30,tmp
);
3249 inXGIIDXREG(XGIPART1
,0x13,tmp
);
3252 /* XGI_Pr.XGI_UseLCDA = 1; */
3264 if (xgifb_mode_idx
>= 0)
3265 xgifb_mode_idx
= XGIfb_validate_mode(xgifb_mode_idx
);
3267 if (xgifb_mode_idx
< 0) {
3268 switch (xgi_video_info
.disp_state
& DISPTYPE_DISP2
) {
3270 xgifb_mode_idx
= DEFAULT_LCDMODE
;
3271 if (xgi_video_info
.chip
== XG21
)
3273 xgifb_mode_idx
= XGIfb_GetXG21DefaultLVDSModeIdx();
3277 xgifb_mode_idx
= DEFAULT_TVMODE
;
3280 xgifb_mode_idx
= DEFAULT_MODE
;
3285 XGIfb_mode_no
= XGIbios_mode
[xgifb_mode_idx
].mode_no
;
3288 if( xgi_video_info
.refresh_rate
== 0)
3289 xgi_video_info
.refresh_rate
= 60; /*yilin set default refresh rate */
3290 if(XGIfb_search_refresh_rate(xgi_video_info
.refresh_rate
) == 0)
3292 XGIfb_rate_idx
= XGIbios_mode
[xgifb_mode_idx
].rate_idx
;
3293 xgi_video_info
.refresh_rate
= 60;
3296 xgi_video_info
.video_bpp
= XGIbios_mode
[xgifb_mode_idx
].bpp
;
3297 xgi_video_info
.video_vwidth
= xgi_video_info
.video_width
= XGIbios_mode
[xgifb_mode_idx
].xres
;
3298 xgi_video_info
.video_vheight
= xgi_video_info
.video_height
= XGIbios_mode
[xgifb_mode_idx
].yres
;
3299 xgi_video_info
.org_x
= xgi_video_info
.org_y
= 0;
3300 xgi_video_info
.video_linelength
= xgi_video_info
.video_width
* (xgi_video_info
.video_bpp
>> 3);
3301 switch(xgi_video_info
.video_bpp
) {
3303 xgi_video_info
.DstColor
= 0x0000;
3304 xgi_video_info
.XGI310_AccelDepth
= 0x00000000;
3305 xgi_video_info
.video_cmap_len
= 256;
3308 xgi_video_info
.DstColor
= 0x8000;
3309 xgi_video_info
.XGI310_AccelDepth
= 0x00010000;
3310 xgi_video_info
.video_cmap_len
= 16;
3313 xgi_video_info
.DstColor
= 0xC000;
3314 xgi_video_info
.XGI310_AccelDepth
= 0x00020000;
3315 xgi_video_info
.video_cmap_len
= 16;
3318 xgi_video_info
.video_cmap_len
= 16;
3319 printk(KERN_INFO
"XGIfb: Unsupported depth %d", xgi_video_info
.video_bpp
);
3325 printk(KERN_INFO
"XGIfb: Default mode is %dx%dx%d (%dHz)\n",
3326 xgi_video_info
.video_width
, xgi_video_info
.video_height
, xgi_video_info
.video_bpp
,
3327 xgi_video_info
.refresh_rate
);
3329 default_var
.xres
= default_var
.xres_virtual
= xgi_video_info
.video_width
;
3330 default_var
.yres
= default_var
.yres_virtual
= xgi_video_info
.video_height
;
3331 default_var
.bits_per_pixel
= xgi_video_info
.video_bpp
;
3333 XGIfb_bpp_to_var(&default_var
);
3335 default_var
.pixclock
= (u32
) (1000000000 /
3336 XGIfb_mode_rate_to_dclock(&XGI_Pr
, &XGIhw_ext
,
3337 XGIfb_mode_no
, XGIfb_rate_idx
));
3339 if(XGIfb_mode_rate_to_ddata(&XGI_Pr
, &XGIhw_ext
,
3340 XGIfb_mode_no
, XGIfb_rate_idx
,
3341 &default_var
.left_margin
, &default_var
.right_margin
,
3342 &default_var
.upper_margin
, &default_var
.lower_margin
,
3343 &default_var
.hsync_len
, &default_var
.vsync_len
,
3344 &default_var
.sync
, &default_var
.vmode
)) {
3346 if((default_var
.vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
3347 default_var
.yres
<<= 1;
3348 default_var
.yres_virtual
<<= 1;
3349 } else if((default_var
.vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
3350 default_var
.pixclock
>>= 1;
3351 default_var
.yres
>>= 1;
3352 default_var
.yres_virtual
>>= 1;
3357 xgi_video_info
.accel
= 0;
3359 xgi_video_info
.accel
= -1;
3360 default_var
.accel_flags
|= FB_ACCELF_TEXT
;
3364 fb_info
->flags
= FBINFO_FLAG_DEFAULT
;
3365 fb_info
->var
= default_var
;
3366 fb_info
->fix
= XGIfb_fix
;
3367 fb_info
->par
= &xgi_video_info
;
3368 fb_info
->screen_base
= xgi_video_info
.video_vbase
;
3369 fb_info
->fbops
= &XGIfb_ops
;
3370 XGIfb_get_fix(&fb_info
->fix
, -1, fb_info
);
3371 fb_info
->pseudo_palette
= pseudo_palette
;
3373 fb_alloc_cmap(&fb_info
->cmap
, 256 , 0);
3377 xgi_video_info
.mtrr
= mtrr_add((unsigned int) xgi_video_info
.video_base
,
3378 (unsigned int) xgi_video_info
.video_size
,
3379 MTRR_TYPE_WRCOMB
, 1);
3380 if(xgi_video_info
.mtrr
) {
3381 printk(KERN_INFO
"XGIfb: Added MTRRs\n");
3385 if(register_framebuffer(fb_info
) < 0)
3390 XGIfb_registered
= 1;
3392 printk(KERN_INFO
"XGIfb: Installed XGIFB_GET_INFO ioctl (%lx)\n",
3395 /* printk(KERN_INFO "XGIfb: 2D acceleration is %s, scrolling mode %s\n",
3396 XGIfb_accel ? "enabled" : "disabled",
3397 XGIfb_ypan ? "ypan" : "redraw");
3399 printk(KERN_INFO
"fb%d: %s frame buffer device, Version %d.%d.%02d\n",
3400 fb_info
->node
, myid
, VER_MAJOR
, VER_MINOR
, VER_LEVEL
);
3411 /*****************************************************/
3412 /* PCI DEVICE HANDLING */
3413 /*****************************************************/
3415 static void __devexit
xgifb_remove(struct pci_dev
*pdev
)
3417 /* Unregister the framebuffer */
3418 // if(xgi_video_info.registered) {
3419 unregister_framebuffer(fb_info
);
3420 framebuffer_release(fb_info
);
3423 pci_set_drvdata(pdev
, NULL
);
3427 static struct pci_driver xgifb_driver
= {
3429 .id_table
= xgifb_pci_table
,
3430 .probe
= xgifb_probe
,
3431 .remove
= __devexit_p(xgifb_remove
)
3434 XGIINITSTATIC
int __init
xgifb_init(void)
3437 char *option
= NULL
;
3439 if (fb_get_options("xgifb", &option
))
3441 XGIfb_setup(option
);
3443 return(pci_register_driver(&xgifb_driver
));
3448 module_init(xgifb_init
);
3451 /*****************************************************/
3453 /*****************************************************/
3457 static char *mode
= NULL
;
3458 static int vesa
= 0;
3459 static unsigned int rate
= 0;
3460 static unsigned int crt1off
= 1;
3461 static unsigned int mem
= 0;
3462 static char *forcecrt2type
= NULL
;
3463 static int forcecrt1
= -1;
3464 static int pdc
= -1;
3465 static int pdc1
= -1;
3466 static int noaccel
= -1;
3467 static int noypan
= -1;
3468 static int nomax
= -1;
3469 static int userom
= -1;
3470 static int useoem
= -1;
3471 static char *tvstandard
= NULL
;
3472 static int nocrt2rate
= 0;
3473 static int scalelcd
= -1;
3474 static char *specialtiming
= NULL
;
3475 static int lvdshl
= -1;
3476 static int tvxposoffset
= 0, tvyposoffset
= 0;
3477 #if !defined(__i386__) && !defined(__x86_64__)
3478 static int resetcard
= 0;
3479 static int videoram
= 0;
3482 MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
3483 MODULE_LICENSE("GPL");
3484 MODULE_AUTHOR("XGITECH , Others");
3488 module_param(mem
, int, 0);
3489 module_param(noaccel
, int, 0);
3490 module_param(noypan
, int, 0);
3491 module_param(nomax
, int, 0);
3492 module_param(userom
, int, 0);
3493 module_param(useoem
, int, 0);
3494 module_param(mode
, charp
, 0);
3495 module_param(vesa
, int, 0);
3496 module_param(rate
, int, 0);
3497 module_param(forcecrt1
, int, 0);
3498 module_param(forcecrt2type
, charp
, 0);
3499 module_param(scalelcd
, int, 0);
3500 module_param(pdc
, int, 0);
3501 module_param(pdc1
, int, 0);
3502 module_param(specialtiming
, charp
, 0);
3503 module_param(lvdshl
, int, 0);
3504 module_param(tvstandard
, charp
, 0);
3505 module_param(tvxposoffset
, int, 0);
3506 module_param(tvyposoffset
, int, 0);
3507 module_param(filter
, int, 0);
3508 module_param(nocrt2rate
, int, 0);
3509 #if !defined(__i386__) && !defined(__x86_64__)
3510 module_param(resetcard
, int, 0);
3511 module_param(videoram
, int, 0);
3515 MODULE_PARM_DESC(mem
,
3516 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
3517 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
3518 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
3519 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
3520 "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
3521 "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
3522 "for XFree86 4.x/X.org 6.7 and later.\n");
3524 MODULE_PARM_DESC(noaccel
,
3525 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
3528 MODULE_PARM_DESC(noypan
,
3529 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
3530 "will be performed by redrawing the screen. (default: 0)\n");
3532 MODULE_PARM_DESC(nomax
,
3533 "\nIf y-panning is enabled, xgifb will by default use the entire available video\n"
3534 "memory for the virtual screen in order to optimize scrolling performance. If\n"
3535 "this is set to anything other than 0, xgifb will not do this and thereby \n"
3536 "enable the user to positively specify a virtual Y size of the screen using\n"
3537 "fbset. (default: 0)\n");
3541 MODULE_PARM_DESC(mode
,
3542 "\nSelects the desired default display mode in the format XxYxDepth,\n"
3543 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
3544 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
3545 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
3547 MODULE_PARM_DESC(vesa
,
3548 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
3549 "0x117 (default: 0x0103)\n");
3552 MODULE_PARM_DESC(rate
,
3553 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
3554 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
3555 "will be ignored (default: 60)\n");
3557 MODULE_PARM_DESC(forcecrt1
,
3558 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
3559 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
3560 "0=CRT1 OFF) (default: [autodetected])\n");
3562 MODULE_PARM_DESC(forcecrt2type
,
3563 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
3564 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
3565 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
3566 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
3567 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
3568 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
3569 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
3570 "depends on the very hardware in use. (default: [autodetected])\n");
3572 MODULE_PARM_DESC(scalelcd
,
3573 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
3574 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
3575 "show black bars around the image, TMDS panels will probably do the scaling\n"
3576 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
3578 MODULE_PARM_DESC(pdc
,
3579 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
3580 "should detect this correctly in most cases; however, sometimes this is not\n"
3581 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
3582 "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
3583 "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
3584 "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
3586 MODULE_PARM_DESC(pdc1
,
3587 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
3588 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
3589 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
3590 "implemented yet.\n");
3592 MODULE_PARM_DESC(specialtiming
,
3593 "\nPlease refer to documentation for more information on this option.\n");
3595 MODULE_PARM_DESC(lvdshl
,
3596 "\nPlease refer to documentation for more information on this option.\n");
3598 MODULE_PARM_DESC(tvstandard
,
3599 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
3600 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
3602 MODULE_PARM_DESC(tvxposoffset
,
3603 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
3606 MODULE_PARM_DESC(tvyposoffset
,
3607 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
3610 MODULE_PARM_DESC(filter
,
3611 "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
3612 "(Possible values 0-7, default: [no filter])\n");
3614 MODULE_PARM_DESC(nocrt2rate
,
3615 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
3616 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
3621 int __init
xgifb_init_module(void)
3623 printk("\nXGIfb_init_module");
3625 XGIfb_search_mode(mode
);
3626 else if (vesa
!= -1)
3627 XGIfb_search_vesamode(vesa
);
3629 return(xgifb_init());
3632 static void __exit
xgifb_remove_module(void)
3634 pci_unregister_driver(&xgifb_driver
);
3635 printk(KERN_DEBUG
"xgifb: Module unloaded\n");
3638 module_init(xgifb_init_module
);
3639 module_exit(xgifb_remove_module
);
3641 #endif /* /MODULE */
3643 EXPORT_SYMBOL(XGI_malloc
);
3644 EXPORT_SYMBOL(XGI_free
);