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>
50 #define Index_CR_GPIO_Reg1 0x48
51 #define Index_CR_GPIO_Reg2 0x49
52 #define Index_CR_GPIO_Reg3 0x4a
54 #define GPIOG_EN (1<<6)
55 #define GPIOG_WRITE (1<<6)
56 #define GPIOG_READ (1<<1)
57 int XGIfb_GetXG21DefaultLVDSModeIdx(void);
59 /* -------------------- Macro definitions ---------------------------- */
64 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
66 #define DPRINTK(fmt, args...)
70 static void dumpVGAReg(void)
74 outXGIIDXREG(XGISR
, 0x05, 0x86);
76 outXGIIDXREG(XGISR, 0x08, 0x4f);
77 outXGIIDXREG(XGISR, 0x0f, 0x20);
78 outXGIIDXREG(XGISR, 0x11, 0x4f);
79 outXGIIDXREG(XGISR, 0x13, 0x45);
80 outXGIIDXREG(XGISR, 0x14, 0x51);
81 outXGIIDXREG(XGISR, 0x1e, 0x41);
82 outXGIIDXREG(XGISR, 0x1f, 0x0);
83 outXGIIDXREG(XGISR, 0x20, 0xa1);
84 outXGIIDXREG(XGISR, 0x22, 0xfb);
85 outXGIIDXREG(XGISR, 0x26, 0x22);
86 outXGIIDXREG(XGISR, 0x3e, 0x07);
89 //outXGIIDXREG(XGICR, 0x19, 0x00);
90 //outXGIIDXREG(XGICR, 0x1a, 0x3C);
91 //outXGIIDXREG(XGICR, 0x22, 0xff);
92 //outXGIIDXREG(XGICR, 0x3D, 0x10);
94 //outXGIIDXREG(XGICR, 0x4a, 0xf3);
96 //outXGIIDXREG(XGICR, 0x57, 0x0);
97 //outXGIIDXREG(XGICR, 0x7a, 0x2c);
99 //outXGIIDXREG(XGICR, 0x82, 0xcc);
100 //outXGIIDXREG(XGICR, 0x8c, 0x0);
102 outXGIIDXREG(XGICR, 0x99, 0x1);
103 outXGIIDXREG(XGICR, 0x41, 0x40);
106 for(i
=0; i
< 0x4f; i
++)
108 inXGIIDXREG(XGISR
, i
, reg
);
109 printk("\no 3c4 %x",i
);
110 printk("\ni 3c5 => %x",reg
);
113 for(i
=0; i
< 0xF0; i
++)
115 inXGIIDXREG(XGICR
, i
, reg
);
116 printk("\no 3d4 %x",i
);
117 printk("\ni 3d5 => %x",reg
);
121 outXGIIDXREG(XGIPART1,0x2F,1);
122 for(i=1; i < 0x50; i++)
124 inXGIIDXREG(XGIPART1, i, reg);
125 printk("\no d004 %x",i);
126 printk("\ni d005 => %x",reg);
129 for(i=0; i < 0x50; i++)
131 inXGIIDXREG(XGIPART2, i, reg);
132 printk("\no d010 %x",i);
133 printk("\ni d011 => %x",reg);
135 for(i=0; i < 0x50; i++)
137 inXGIIDXREG(XGIPART3, i, reg);
138 printk("\no d012 %x",i);
139 printk("\ni d013 => %x",reg);
141 for(i=0; i < 0x50; i++)
143 inXGIIDXREG(XGIPART4, i, reg);
144 printk("\no d014 %x",i);
145 printk("\ni d015 => %x",reg);
150 static inline void dumpVGAReg(void) {}
153 /* data for XGI components */
154 struct video_info xgi_video_info
;
160 #define DEBUGPRN(x) printk(KERN_INFO x "\n");
164 /* --------------- Hardware Access Routines -------------------------- */
168 XGIfb_mode_rate_to_dclock(VB_DEVICE_INFO
*XGI_Pr
, PXGI_HW_DEVICE_INFO HwDeviceExtension
,
169 unsigned char modeno
, unsigned char rateindex
)
171 USHORT ModeNo
= modeno
;
172 USHORT ModeIdIndex
= 0, ClockIndex
= 0;
173 USHORT RefreshRateTableIndex
= 0;
177 XGI_Pr
->ROMAddr
= HwDeviceExtension
->pjVirtualRomBase
;
178 InitTo330Pointer( HwDeviceExtension
->jChipType
, XGI_Pr
) ;
180 RefreshRateTableIndex
= XGI_GetRatePtrCRT2( HwDeviceExtension
, ModeNo
, ModeIdIndex
, XGI_Pr
) ;
183 temp = XGI_SearchModeID( ModeNo , &ModeIdIndex, XGI_Pr ) ;
185 printk(KERN_ERR "Could not find mode %x\n", ModeNo);
189 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
190 RefreshRateTableIndex += (rateindex - 1);
193 ClockIndex
= XGI_Pr
->RefIndex
[RefreshRateTableIndex
].Ext_CRTVCLK
;
194 if(HwDeviceExtension
->jChipType
< XGI_315H
) {
197 Clock
= XGI_Pr
->VCLKData
[ClockIndex
].CLOCK
* 1000 ;
203 XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO
*XGI_Pr
, PXGI_HW_DEVICE_INFO HwDeviceExtension
,
204 unsigned char modeno
, unsigned char rateindex
,
205 u32
*left_margin
, u32
*right_margin
,
206 u32
*upper_margin
, u32
*lower_margin
,
207 u32
*hsync_len
, u32
*vsync_len
,
208 u32
*sync
, u32
*vmode
)
210 USHORT ModeNo
= modeno
;
211 USHORT ModeIdIndex
= 0, index
= 0;
212 USHORT RefreshRateTableIndex
= 0;
214 unsigned short VRE
, VBE
, VRS
, VBS
, VDE
, VT
;
215 unsigned short HRE
, HBE
, HRS
, HBS
, HDE
, HT
;
216 unsigned char sr_data
, cr_data
, cr_data2
;
217 unsigned long cr_data3
;
218 int A
, B
, C
, D
, E
, F
, temp
, j
;
219 XGI_Pr
->ROMAddr
= HwDeviceExtension
->pjVirtualRomBase
;
220 InitTo330Pointer( HwDeviceExtension
->jChipType
, XGI_Pr
) ;
221 RefreshRateTableIndex
= XGI_GetRatePtrCRT2( HwDeviceExtension
, ModeNo
, ModeIdIndex
, XGI_Pr
) ;
223 temp = XGI_SearchModeID( ModeNo, &ModeIdIndex, XGI_Pr);
226 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
227 RefreshRateTableIndex += (rateindex - 1);
229 index
= XGI_Pr
->RefIndex
[RefreshRateTableIndex
].Ext_CRT1CRTC
;
231 sr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[5];
233 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[0];
235 /* Horizontal total */
236 HT
= (cr_data
& 0xff) |
237 ((unsigned short) (sr_data
& 0x03) << 8);
240 /*cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
242 Horizontal display enable end
243 HDE = (cr_data & 0xff) |
244 ((unsigned short) (sr_data & 0x0C) << 6);*/
245 HDE
= (XGI_Pr
->RefIndex
[RefreshRateTableIndex
].XRes
>> 3) -1;
248 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[3];
250 /* Horizontal retrace (=sync) start */
251 HRS
= (cr_data
& 0xff) |
252 ((unsigned short) (sr_data
& 0xC0) << 2);
255 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[1];
257 /* Horizontal blank start */
258 HBS
= (cr_data
& 0xff) |
259 ((unsigned short) (sr_data
& 0x30) << 4);
261 sr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[6];
263 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[2];
265 cr_data2
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[4];
267 /* Horizontal blank end */
268 HBE
= (cr_data
& 0x1f) |
269 ((unsigned short) (cr_data2
& 0x80) >> 2) |
270 ((unsigned short) (sr_data
& 0x03) << 6);
272 /* Horizontal retrace (=sync) end */
273 HRE
= (cr_data2
& 0x1f) | ((sr_data
& 0x04) << 3);
275 temp
= HBE
- ((E
- 1) & 255);
276 B
= (temp
> 0) ? temp
: (temp
+ 256);
278 temp
= HRE
- ((E
+ F
+ 3) & 63);
279 C
= (temp
> 0) ? temp
: (temp
+ 64);
283 *left_margin
= D
* 8;
284 *right_margin
= F
* 8;
287 sr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[14];
289 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[8];
291 cr_data2
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[9];
294 VT
= (cr_data
& 0xFF) |
295 ((unsigned short) (cr_data2
& 0x01) << 8) |
296 ((unsigned short)(cr_data2
& 0x20) << 4) |
297 ((unsigned short) (sr_data
& 0x01) << 10);
300 //cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
302 /* Vertical display enable end */
303 /* VDE = (cr_data & 0xff) |
304 ((unsigned short) (cr_data2 & 0x02) << 7) |
305 ((unsigned short) (cr_data2 & 0x40) << 3) |
306 ((unsigned short) (sr_data & 0x02) << 9); */
307 VDE
= XGI_Pr
->RefIndex
[RefreshRateTableIndex
].YRes
-1;
310 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[10];
312 /* Vertical retrace (=sync) start */
313 VRS
= (cr_data
& 0xff) |
314 ((unsigned short) (cr_data2
& 0x04) << 6) |
315 ((unsigned short) (cr_data2
& 0x80) << 2) |
316 ((unsigned short) (sr_data
& 0x08) << 7);
319 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[12];
321 cr_data3
= (XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[14] & 0x80) << 5;
323 /* Vertical blank start */
324 VBS
= (cr_data
& 0xff) |
325 ((unsigned short) (cr_data2
& 0x08) << 5) |
326 ((unsigned short) (cr_data3
& 0x20) << 4) |
327 ((unsigned short) (sr_data
& 0x04) << 8);
329 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[13];
331 /* Vertical blank end */
332 VBE
= (cr_data
& 0xff) |
333 ((unsigned short) (sr_data
& 0x10) << 4);
334 temp
= VBE
- ((E
- 1) & 511);
335 B
= (temp
> 0) ? temp
: (temp
+ 512);
337 cr_data
= XGI_Pr
->XGINEWUB_CRT1Table
[index
].CR
[11];
339 /* Vertical retrace (=sync) end */
340 VRE
= (cr_data
& 0x0f) | ((sr_data
& 0x20) >> 1);
341 temp
= VRE
- ((E
+ F
- 1) & 31);
342 C
= (temp
> 0) ? temp
: (temp
+ 32);
350 if(XGI_Pr
->RefIndex
[RefreshRateTableIndex
].Ext_InfoFlag
& 0x8000)
351 *sync
&= ~FB_SYNC_VERT_HIGH_ACT
;
353 *sync
|= FB_SYNC_VERT_HIGH_ACT
;
355 if(XGI_Pr
->RefIndex
[RefreshRateTableIndex
].Ext_InfoFlag
& 0x4000)
356 *sync
&= ~FB_SYNC_HOR_HIGH_ACT
;
358 *sync
|= FB_SYNC_HOR_HIGH_ACT
;
360 *vmode
= FB_VMODE_NONINTERLACED
;
361 if(XGI_Pr
->RefIndex
[RefreshRateTableIndex
].Ext_InfoFlag
& 0x0080)
362 *vmode
= FB_VMODE_INTERLACED
;
365 while(XGI_Pr
->EModeIDTable
[j
].Ext_ModeID
!= 0xff) {
366 if(XGI_Pr
->EModeIDTable
[j
].Ext_ModeID
==
367 XGI_Pr
->RefIndex
[RefreshRateTableIndex
].ModeID
) {
368 if(XGI_Pr
->EModeIDTable
[j
].Ext_ModeFlag
& DoubleScanMode
) {
369 *vmode
= FB_VMODE_DOUBLE
;
377 #if 0 /* That's bullshit, only the resolution needs to be shifted */
378 if((*vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
382 } else if((*vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
396 void XGIRegInit(VB_DEVICE_INFO
*XGI_Pr
, ULONG BaseAddr
)
398 XGI_Pr
->RelIO
= BaseAddr
;
399 XGI_Pr
->P3c4
= BaseAddr
+ 0x14;
400 XGI_Pr
->P3d4
= BaseAddr
+ 0x24;
401 XGI_Pr
->P3c0
= BaseAddr
+ 0x10;
402 XGI_Pr
->P3ce
= BaseAddr
+ 0x1e;
403 XGI_Pr
->P3c2
= BaseAddr
+ 0x12;
404 XGI_Pr
->P3ca
= BaseAddr
+ 0x1a;
405 XGI_Pr
->P3c6
= BaseAddr
+ 0x16;
406 XGI_Pr
->P3c7
= BaseAddr
+ 0x17;
407 XGI_Pr
->P3c8
= BaseAddr
+ 0x18;
408 XGI_Pr
->P3c9
= BaseAddr
+ 0x19;
409 XGI_Pr
->P3da
= BaseAddr
+ 0x2A;
410 XGI_Pr
->Part1Port
= BaseAddr
+ XGI_CRT2_PORT_04
; /* Digital video interface registers (LCD) */
411 XGI_Pr
->Part2Port
= BaseAddr
+ XGI_CRT2_PORT_10
; /* 301 TV Encoder registers */
412 XGI_Pr
->Part3Port
= BaseAddr
+ XGI_CRT2_PORT_12
; /* 301 Macrovision registers */
413 XGI_Pr
->Part4Port
= BaseAddr
+ XGI_CRT2_PORT_14
; /* 301 VGA2 (and LCD) registers */
414 XGI_Pr
->Part5Port
= BaseAddr
+ XGI_CRT2_PORT_14
+2; /* 301 palette address port registers */
419 void XGIfb_set_reg4(u16 port
, unsigned long data
)
421 outl((u32
) (data
& 0xffffffff), port
);
424 u32
XGIfb_get_reg3(u16 port
)
432 /* ------------ Interface for init & mode switching code ------------- */
435 XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext
,
436 unsigned long offset
, unsigned long set
, unsigned long *value
)
438 static struct pci_dev
*pdev
= NULL
;
439 static unsigned char init
= 0, valid_pdev
= 0;
442 DPRINTK("XGIfb: Get VGA offset 0x%lx\n", offset
);
444 DPRINTK("XGIfb: Set offset 0x%lx to 0x%lx\n", offset
, *value
);
448 pdev
= pci_get_device(PCI_VENDOR_ID_XG
, xgi_video_info
.chip_id
, pdev
);
456 printk(KERN_DEBUG
"XGIfb: Can't find XGI %d VGA device.\n",
457 xgi_video_info
.chip_id
);
462 pci_read_config_dword(pdev
, offset
, (u32
*)value
);
464 pci_write_config_dword(pdev
, offset
, (u32
)(*value
));
469 /*BOOLEAN XGIfb_query_north_bridge_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
470 unsigned long offset, unsigned long set, unsigned long *value)
472 static struct pci_dev *pdev = NULL;
473 static unsigned char init = 0, valid_pdev = 0;
478 switch (xgi_video_info.chip) {
480 nbridge_id = PCI_DEVICE_ID_XG_540;
483 nbridge_id = PCI_DEVICE_ID_XG_630;
486 nbridge_id = PCI_DEVICE_ID_XG_730;
489 nbridge_id = PCI_DEVICE_ID_XG_550;
492 nbridge_id = PCI_DEVICE_ID_XG_650;
495 nbridge_id = PCI_DEVICE_ID_XG_740;
502 pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridge_id, pdev);
508 printk(KERN_DEBUG "XGIfb: Can't find XGI %d North Bridge device.\n",
514 pci_read_config_dword(pdev, offset, (u32 *)value);
516 pci_write_config_dword(pdev, offset, (u32)(*value));
521 /* ------------------ Internal helper routines ----------------- */
523 static void XGIfb_search_mode(const char *name
)
528 printk(KERN_ERR
"XGIfb: Internal error, using default mode.\n");
529 xgifb_mode_idx
= DEFAULT_MODE
;
530 if ((xgi_video_info
.chip
== XG21
) && ((xgi_video_info
.disp_state
& DISPTYPE_DISP2
) == DISPTYPE_LCD
))
532 xgifb_mode_idx
= XGIfb_GetXG21DefaultLVDSModeIdx();
538 if (!strcmp(name
, XGIbios_mode
[MODE_INDEX_NONE
].name
)) {
539 printk(KERN_ERR
"XGIfb: Mode 'none' not supported anymore. Using default.\n");
540 xgifb_mode_idx
= DEFAULT_MODE
;
541 if ((xgi_video_info
.chip
== XG21
) && ((xgi_video_info
.disp_state
& DISPTYPE_DISP2
) == DISPTYPE_LCD
))
543 xgifb_mode_idx
= XGIfb_GetXG21DefaultLVDSModeIdx();
548 while(XGIbios_mode
[i
].mode_no
!= 0) {
549 l
= min(strlen(name
), strlen(XGIbios_mode
[i
].name
));
550 if (!strncmp(name
, XGIbios_mode
[i
].name
, l
)) {
557 if(!j
) printk(KERN_INFO
"XGIfb: Invalid mode '%s'\n", name
);
560 static void XGIfb_search_vesamode(unsigned int vesamode
)
566 printk(KERN_ERR
"XGIfb: Mode 'none' not supported anymore. Using default.\n");
567 xgifb_mode_idx
= DEFAULT_MODE
;
568 if ((xgi_video_info
.chip
== XG21
) && ((xgi_video_info
.disp_state
& DISPTYPE_DISP2
) == DISPTYPE_LCD
))
570 xgifb_mode_idx
= XGIfb_GetXG21DefaultLVDSModeIdx();
575 vesamode
&= 0x1dff; /* Clean VESA mode number from other flags */
577 while(XGIbios_mode
[i
].mode_no
!= 0) {
578 if( (XGIbios_mode
[i
].vesa_mode_no_1
== vesamode
) ||
579 (XGIbios_mode
[i
].vesa_mode_no_2
== vesamode
) ) {
586 if(!j
) printk(KERN_INFO
"XGIfb: Invalid VESA mode 0x%x'\n", vesamode
);
589 int XGIfb_GetXG21LVDSData(void)
592 unsigned char *pData
;
595 inXGIIDXREG(XGISR
,0x1e,tmp
);
596 outXGIIDXREG(XGISR
, 0x1e, tmp
|4);
598 pData
= xgi_video_info
.mmio_vbase
+0x20000;
599 if ((pData
[0x0]==0x55) && (pData
[0x1]==0xAA) && (pData
[0x65] & 0x1))
601 i
= pData
[ 0x316 ] | ( pData
[ 0x317 ] << 8 );
610 XGI21_LCDCapList
[k
].LVDS_Capability
= pData
[ i
] | ( pData
[ i
+ 1 ] << 8 );
611 XGI21_LCDCapList
[k
].LVDSHT
= pData
[ i
+ 2 ] | ( pData
[ i
+ 3 ] << 8 ) ;
612 XGI21_LCDCapList
[k
].LVDSVT
= pData
[ i
+ 4 ] | ( pData
[ i
+ 5 ] << 8 );
613 XGI21_LCDCapList
[k
].LVDSHDE
= pData
[ i
+ 6 ] | ( pData
[ i
+ 7 ] << 8 );
614 XGI21_LCDCapList
[k
].LVDSVDE
= pData
[ i
+ 8 ] | ( pData
[ i
+ 9 ] << 8 );
615 XGI21_LCDCapList
[k
].LVDSHFP
= pData
[ i
+ 10 ] | ( pData
[ i
+ 11 ] << 8 );
616 XGI21_LCDCapList
[k
].LVDSVFP
= pData
[ i
+ 12 ] | ( pData
[ i
+ 13 ] << 8 );
617 XGI21_LCDCapList
[k
].LVDSHSYNC
= pData
[ i
+ 14 ] | ( pData
[ i
+ 15 ] << 8 );
618 XGI21_LCDCapList
[k
].LVDSVSYNC
= pData
[ i
+ 16 ] | ( pData
[ i
+ 17 ] << 8 );
619 XGI21_LCDCapList
[k
].VCLKData1
= pData
[ i
+ 18 ] ;
620 XGI21_LCDCapList
[k
].VCLKData2
= pData
[ i
+ 19 ] ;
621 XGI21_LCDCapList
[k
].PSC_S1
= pData
[ i
+ 20 ] ;
622 XGI21_LCDCapList
[k
].PSC_S2
= pData
[ i
+ 21 ] ;
623 XGI21_LCDCapList
[k
].PSC_S3
= pData
[ i
+ 22 ] ;
624 XGI21_LCDCapList
[k
].PSC_S4
= pData
[ i
+ 23 ] ;
625 XGI21_LCDCapList
[k
].PSC_S5
= pData
[ i
+ 24 ] ;
629 } while ( (j
>0) && ( k
< (sizeof(XGI21_LCDCapList
)/sizeof(XGI21_LVDSCapStruct
)) ) );
635 int XGIfb_GetXG21DefaultLVDSModeIdx(void)
639 int XGIfb_mode_idx
= 0;
642 while( (XGIbios_mode
[XGIfb_mode_idx
].mode_no
!= 0) &&
643 (XGIbios_mode
[XGIfb_mode_idx
].xres
<= XGI21_LCDCapList
[0].LVDSHDE
) )
645 if( (XGIbios_mode
[XGIfb_mode_idx
].xres
== XGI21_LCDCapList
[0].LVDSHDE
) &&
646 (XGIbios_mode
[XGIfb_mode_idx
].yres
== XGI21_LCDCapList
[0].LVDSVDE
) &&
647 (XGIbios_mode
[XGIfb_mode_idx
].bpp
== 8))
649 XGIfb_mode_no
= XGIbios_mode
[XGIfb_mode_idx
].mode_no
;
658 return (XGIfb_mode_idx
);
662 static int XGIfb_validate_mode(int myindex
)
666 if (xgi_video_info
.chip
== XG21
)
668 if ((xgi_video_info
.disp_state
& DISPTYPE_DISP2
) == DISPTYPE_LCD
)
670 xres
= XGI21_LCDCapList
[0].LVDSHDE
;
671 yres
= XGI21_LCDCapList
[0].LVDSVDE
;
672 if(XGIbios_mode
[myindex
].xres
> xres
)
674 if(XGIbios_mode
[myindex
].yres
> yres
)
676 if ((XGIbios_mode
[myindex
].xres
< xres
) && (XGIbios_mode
[myindex
].yres
< yres
) )
678 if (XGIbios_mode
[myindex
].bpp
> 8)
687 /* FIXME: for now, all is valid on XG27 */
688 if (xgi_video_info
.chip
== XG27
)
691 if(!(XGIbios_mode
[myindex
].chipset
& MD_XGI315
))
694 switch (xgi_video_info
.disp_state
& DISPTYPE_DISP2
) {
696 switch (XGIhw_ext
.ulCRT2LCDType
) {
698 xres
= 640; yres
= 480; break;
700 xres
= 800; yres
= 600; break;
702 xres
= 1024; yres
= 600; break;
704 xres
= 1024; yres
= 768; break;
706 xres
= 1152; yres
= 768; break;
708 xres
= 1280; yres
= 960; break;
710 xres
= 1280; yres
= 768; break;
712 xres
= 1280; yres
= 1024; break;
714 xres
= 1400; yres
= 1050; break;
716 xres
= 1600; yres
= 1200; break;
717 // case LCD_320x480: // TW: FSTN
718 // xres = 320; yres = 480; break;
720 xres
= 0; yres
= 0; break;
722 if(XGIbios_mode
[myindex
].xres
> xres
) {
725 if(XGIbios_mode
[myindex
].yres
> yres
) {
728 if((XGIhw_ext
.ulExternalChip
== 0x01) || // LVDS
729 (XGIhw_ext
.ulExternalChip
== 0x05)) // LVDS+Chrontel
731 switch (XGIbios_mode
[myindex
].xres
) {
733 if(XGIbios_mode
[myindex
].yres
!= 512) return -1;
734 if(XGIhw_ext
.ulCRT2LCDType
== LCD_1024x600
) return -1;
737 if((XGIbios_mode
[myindex
].yres
!= 400) &&
738 (XGIbios_mode
[myindex
].yres
!= 480))
742 if(XGIbios_mode
[myindex
].yres
!= 600) return -1;
745 if((XGIbios_mode
[myindex
].yres
!= 600) &&
746 (XGIbios_mode
[myindex
].yres
!= 768))
748 if((XGIbios_mode
[myindex
].yres
== 600) &&
749 (XGIhw_ext
.ulCRT2LCDType
!= LCD_1024x600
))
753 if((XGIbios_mode
[myindex
].yres
) != 768) return -1;
754 if(XGIhw_ext
.ulCRT2LCDType
!= LCD_1152x768
) return -1;
757 if((XGIbios_mode
[myindex
].yres
!= 768) &&
758 (XGIbios_mode
[myindex
].yres
!= 1024))
760 if((XGIbios_mode
[myindex
].yres
== 768) &&
761 (XGIhw_ext
.ulCRT2LCDType
!= LCD_1280x768
))
765 if(XGIbios_mode
[myindex
].yres
!= 1050) return -1;
768 if(XGIbios_mode
[myindex
].yres
!= 1200) return -1;
774 switch (XGIbios_mode
[myindex
].xres
) {
776 if(XGIbios_mode
[myindex
].yres
!= 512) return -1;
779 if((XGIbios_mode
[myindex
].yres
!= 400) &&
780 (XGIbios_mode
[myindex
].yres
!= 480))
784 if(XGIbios_mode
[myindex
].yres
!= 600) return -1;
787 if(XGIbios_mode
[myindex
].yres
!= 768) return -1;
790 if((XGIbios_mode
[myindex
].yres
!= 960) &&
791 (XGIbios_mode
[myindex
].yres
!= 1024))
793 if(XGIbios_mode
[myindex
].yres
== 960) {
794 if(XGIhw_ext
.ulCRT2LCDType
== LCD_1400x1050
)
799 if(XGIbios_mode
[myindex
].yres
!= 1050) return -1;
802 if(XGIbios_mode
[myindex
].yres
!= 1200) return -1;
810 switch (XGIbios_mode
[myindex
].xres
) {
816 if (xgi_video_info
.TV_type
== TVMODE_NTSC
) {
817 if (XGIbios_mode
[myindex
].yres
!= 480) {
820 } else if (xgi_video_info
.TV_type
== TVMODE_PAL
) {
821 if (XGIbios_mode
[myindex
].yres
!= 576) {
825 // TW: LVDS/CHRONTEL does not support 720
826 if (xgi_video_info
.hasVB
== HASVB_LVDS_CHRONTEL
||
827 xgi_video_info
.hasVB
== HASVB_CHRONTEL
) {
832 if (xgi_video_info
.TV_type
== TVMODE_NTSC
) {
833 if(XGIbios_mode
[myindex
].bpp
== 32) {
837 // TW: LVDS/CHRONTEL only supports < 800 (1024 on 650/Ch7019)
838 if (xgi_video_info
.hasVB
== HASVB_LVDS_CHRONTEL
||
839 xgi_video_info
.hasVB
== HASVB_CHRONTEL
) {
840 if(xgi_video_info
.chip
< XGI_315H
) {
850 if(XGIbios_mode
[myindex
].xres
> 1280) return -1;
857 static void XGIfb_search_crt2type(const char *name
)
864 while(XGI_crt2type
[i
].type_no
!= -1) {
865 if (!strcmp(name
, XGI_crt2type
[i
].name
)) {
866 XGIfb_crt2type
= XGI_crt2type
[i
].type_no
;
867 XGIfb_tvplug
= XGI_crt2type
[i
].tvplug_no
;
872 if(XGIfb_crt2type
< 0)
873 printk(KERN_INFO
"XGIfb: Invalid CRT2 type: %s\n", name
);
876 static void XGIfb_search_queuemode(const char *name
)
883 while (XGI_queuemode
[i
].type_no
!= -1) {
884 if (!strcmp(name
, XGI_queuemode
[i
].name
)) {
885 XGIfb_queuemode
= XGI_queuemode
[i
].type_no
;
890 if (XGIfb_queuemode
< 0)
891 printk(KERN_INFO
"XGIfb: Invalid queuemode type: %s\n", name
);
894 static u8
XGIfb_search_refresh_rate(unsigned int rate
)
899 xres
= XGIbios_mode
[xgifb_mode_idx
].xres
;
900 yres
= XGIbios_mode
[xgifb_mode_idx
].yres
;
903 while ((XGIfb_vrate
[i
].idx
!= 0) && (XGIfb_vrate
[i
].xres
<= xres
)) {
904 if ((XGIfb_vrate
[i
].xres
== xres
) && (XGIfb_vrate
[i
].yres
== yres
)) {
905 if (XGIfb_vrate
[i
].refresh
== rate
) {
906 XGIfb_rate_idx
= XGIfb_vrate
[i
].idx
;
908 } else if (XGIfb_vrate
[i
].refresh
> rate
) {
909 if ((XGIfb_vrate
[i
].refresh
- rate
) <= 3) {
910 DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
911 rate
, XGIfb_vrate
[i
].refresh
);
912 XGIfb_rate_idx
= XGIfb_vrate
[i
].idx
;
913 xgi_video_info
.refresh_rate
= XGIfb_vrate
[i
].refresh
;
914 } else if (((rate
- XGIfb_vrate
[i
-1].refresh
) <= 2)
915 && (XGIfb_vrate
[i
].idx
!= 1)) {
916 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
917 rate
, XGIfb_vrate
[i
-1].refresh
);
918 XGIfb_rate_idx
= XGIfb_vrate
[i
-1].idx
;
919 xgi_video_info
.refresh_rate
= XGIfb_vrate
[i
-1].refresh
;
922 } else if((rate
- XGIfb_vrate
[i
].refresh
) <= 2) {
923 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
924 rate
, XGIfb_vrate
[i
].refresh
);
925 XGIfb_rate_idx
= XGIfb_vrate
[i
].idx
;
931 if (XGIfb_rate_idx
> 0) {
932 return XGIfb_rate_idx
;
935 "XGIfb: Unsupported rate %d for %dx%d\n", rate
, xres
, yres
);
940 static void XGIfb_search_tvstd(const char *name
)
947 while (XGI_tvtype
[i
].type_no
!= -1) {
948 if (!strcmp(name
, XGI_tvtype
[i
].name
)) {
949 XGIfb_tvmode
= XGI_tvtype
[i
].type_no
;
956 static BOOLEAN
XGIfb_bridgeisslave(void)
958 unsigned char usScratchP1_00
;
960 if(xgi_video_info
.hasVB
== HASVB_NONE
) return FALSE
;
962 inXGIIDXREG(XGIPART1
,0x00,usScratchP1_00
);
963 if( (usScratchP1_00
& 0x50) == 0x10) {
970 static BOOLEAN
XGIfbcheckvretracecrt1(void)
974 inXGIIDXREG(XGICR
,0x17,temp
);
975 if(!(temp
& 0x80)) return FALSE
;
978 inXGIIDXREG(XGISR
,0x1f,temp
);
979 if(temp
& 0xc0) return FALSE
;
982 if(inXGIREG(XGIINPSTAT
) & 0x08) return TRUE
;
986 static BOOLEAN
XGIfbcheckvretracecrt2(void)
989 if(xgi_video_info
.hasVB
== HASVB_NONE
) return FALSE
;
990 inXGIIDXREG(XGIPART1
, 0x30, temp
);
991 if(temp
& 0x02) return FALSE
;
995 static BOOLEAN
XGIfb_CheckVBRetrace(void)
997 if(xgi_video_info
.disp_state
& DISPTYPE_DISP2
) {
998 if(XGIfb_bridgeisslave()) {
999 return(XGIfbcheckvretracecrt1());
1001 return(XGIfbcheckvretracecrt2());
1004 return(XGIfbcheckvretracecrt1());
1007 /* ----------- FBDev related routines for all series ----------- */
1010 static void XGIfb_bpp_to_var(struct fb_var_screeninfo
*var
)
1012 switch(var
->bits_per_pixel
) {
1014 var
->red
.offset
= var
->green
.offset
= var
->blue
.offset
= 0;
1015 var
->red
.length
= var
->green
.length
= var
->blue
.length
= 6;
1016 xgi_video_info
.video_cmap_len
= 256;
1019 var
->red
.offset
= 11;
1020 var
->red
.length
= 5;
1021 var
->green
.offset
= 5;
1022 var
->green
.length
= 6;
1023 var
->blue
.offset
= 0;
1024 var
->blue
.length
= 5;
1025 var
->transp
.offset
= 0;
1026 var
->transp
.length
= 0;
1027 xgi_video_info
.video_cmap_len
= 16;
1030 var
->red
.offset
= 16;
1031 var
->red
.length
= 8;
1032 var
->green
.offset
= 8;
1033 var
->green
.length
= 8;
1034 var
->blue
.offset
= 0;
1035 var
->blue
.length
= 8;
1036 var
->transp
.offset
= 24;
1037 var
->transp
.length
= 8;
1038 xgi_video_info
.video_cmap_len
= 16;
1045 static int XGIfb_do_set_var(struct fb_var_screeninfo
*var
, int isactive
,
1046 struct fb_info
*info
)
1049 unsigned int htotal
= var
->left_margin
+ var
->xres
+
1050 var
->right_margin
+ var
->hsync_len
;
1051 unsigned int vtotal
= var
->upper_margin
+ var
->yres
+
1052 var
->lower_margin
+ var
->vsync_len
;
1053 #if defined(__powerpc__)
1054 u8 sr_data
, cr_data
;
1056 unsigned int drate
= 0, hrate
= 0;
1059 // unsigned char reg,reg1;
1061 DEBUGPRN("Inside do_set_var");
1062 // 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);
1064 info
->var
.xres_virtual
= var
->xres_virtual
;
1065 info
->var
.yres_virtual
= var
->yres_virtual
;
1066 info
->var
.bits_per_pixel
= var
->bits_per_pixel
;
1068 if ((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
)
1070 else if ((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
)
1072 else if ((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
)
1078 if(!htotal
|| !vtotal
) {
1079 DPRINTK("XGIfb: Invalid 'var' information\n");
1082 printk(KERN_DEBUG
"XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n",
1083 var
->pixclock
,htotal
,vtotal
);
1087 if(var
->pixclock
&& htotal
&& vtotal
) {
1088 drate
= 1000000000 / var
->pixclock
;
1089 hrate
= (drate
* 1000) / htotal
;
1090 xgi_video_info
.refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1092 xgi_video_info
.refresh_rate
= 60;
1095 printk(KERN_DEBUG
"XGIfb: Change mode to %dx%dx%d-%dHz\n",
1096 var
->xres
,var
->yres
,var
->bits_per_pixel
,xgi_video_info
.refresh_rate
);
1098 old_mode
= xgifb_mode_idx
;
1101 while( (XGIbios_mode
[xgifb_mode_idx
].mode_no
!= 0) &&
1102 (XGIbios_mode
[xgifb_mode_idx
].xres
<= var
->xres
) ) {
1103 if( (XGIbios_mode
[xgifb_mode_idx
].xres
== var
->xres
) &&
1104 (XGIbios_mode
[xgifb_mode_idx
].yres
== var
->yres
) &&
1105 (XGIbios_mode
[xgifb_mode_idx
].bpp
== var
->bits_per_pixel
)) {
1106 XGIfb_mode_no
= XGIbios_mode
[xgifb_mode_idx
].mode_no
;
1114 xgifb_mode_idx
= XGIfb_validate_mode(xgifb_mode_idx
);
1116 xgifb_mode_idx
= -1;
1118 if(xgifb_mode_idx
< 0) {
1119 printk(KERN_ERR
"XGIfb: Mode %dx%dx%d not supported\n", var
->xres
,
1120 var
->yres
, var
->bits_per_pixel
);
1121 xgifb_mode_idx
= old_mode
;
1125 if(XGIfb_search_refresh_rate(xgi_video_info
.refresh_rate
) == 0) {
1126 XGIfb_rate_idx
= XGIbios_mode
[xgifb_mode_idx
].rate_idx
;
1127 xgi_video_info
.refresh_rate
= 60;
1133 XGIfb_pre_setmode();
1134 if(XGISetModeNew( &XGIhw_ext
, XGIfb_mode_no
) == 0) {
1135 printk(KERN_ERR
"XGIfb: Setting mode[0x%x] failed\n", XGIfb_mode_no
);
1138 info
->fix
.line_length
= ((info
->var
.xres_virtual
* info
->var
.bits_per_pixel
)>>6);
1140 outXGIIDXREG(XGISR
,IND_XGI_PASSWORD
,XGI_PASSWORD
);
1142 outXGIIDXREG(XGICR
,0x13,(info
->fix
.line_length
& 0x00ff));
1143 outXGIIDXREG(XGISR
,0x0E,(info
->fix
.line_length
& 0xff00)>>8);
1145 XGIfb_post_setmode();
1147 DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d \n",
1148 XGIbios_mode
[xgifb_mode_idx
].xres
,
1149 XGIbios_mode
[xgifb_mode_idx
].yres
,
1150 XGIbios_mode
[xgifb_mode_idx
].bpp
,
1151 xgi_video_info
.refresh_rate
);
1153 xgi_video_info
.video_bpp
= XGIbios_mode
[xgifb_mode_idx
].bpp
;
1154 xgi_video_info
.video_vwidth
= info
->var
.xres_virtual
;
1155 xgi_video_info
.video_width
= XGIbios_mode
[xgifb_mode_idx
].xres
;
1156 xgi_video_info
.video_vheight
= info
->var
.yres_virtual
;
1157 xgi_video_info
.video_height
= XGIbios_mode
[xgifb_mode_idx
].yres
;
1158 xgi_video_info
.org_x
= xgi_video_info
.org_y
= 0;
1159 xgi_video_info
.video_linelength
= info
->var
.xres_virtual
* (xgi_video_info
.video_bpp
>> 3);
1160 xgi_video_info
.accel
= 0;
1162 xgi_video_info
.accel
= (var
->accel_flags
& FB_ACCELF_TEXT
) ? -1 : 0;
1164 switch(xgi_video_info
.video_bpp
)
1167 xgi_video_info
.DstColor
= 0x0000;
1168 xgi_video_info
.XGI310_AccelDepth
= 0x00000000;
1169 xgi_video_info
.video_cmap_len
= 256;
1170 #if defined(__powerpc__)
1171 inXGIIDXREG (XGICR
, 0x4D, cr_data
);
1172 outXGIIDXREG(XGICR
, 0x4D, (cr_data
& 0xE0));
1176 xgi_video_info
.DstColor
= 0x8000;
1177 xgi_video_info
.XGI310_AccelDepth
= 0x00010000;
1178 #if defined(__powerpc__)
1179 inXGIIDXREG (XGICR
, 0x4D, cr_data
);
1180 outXGIIDXREG(XGICR
, 0x4D, ((cr_data
& 0xE0) | 0x0B));
1182 xgi_video_info
.video_cmap_len
= 16;
1185 xgi_video_info
.DstColor
= 0xC000;
1186 xgi_video_info
.XGI310_AccelDepth
= 0x00020000;
1187 xgi_video_info
.video_cmap_len
= 16;
1188 #if defined(__powerpc__)
1189 inXGIIDXREG (XGICR
, 0x4D, cr_data
);
1190 outXGIIDXREG(XGICR
, 0x4D, ((cr_data
& 0xE0) | 0x15));
1194 xgi_video_info
.video_cmap_len
= 16;
1195 printk(KERN_ERR
"XGIfb: Unsupported depth %d", xgi_video_info
.video_bpp
);
1196 xgi_video_info
.accel
= 0;
1200 XGIfb_bpp_to_var(var
); /*update ARGB info*/
1201 DEBUGPRN("End of do_set_var");
1208 static int XGIfb_pan_var(struct fb_var_screeninfo
*var
)
1212 // printk("Inside pan_var");
1214 if (var
->xoffset
> (var
->xres_virtual
- var
->xres
)) {
1215 // printk( "Pan: xo: %d xv %d xr %d\n",
1216 // var->xoffset, var->xres_virtual, var->xres);
1219 if(var
->yoffset
> (var
->yres_virtual
- var
->yres
)) {
1220 // printk( "Pan: yo: %d yv %d yr %d\n",
1221 // var->yoffset, var->yres_virtual, var->yres);
1224 base
= var
->yoffset
* var
->xres_virtual
+ var
->xoffset
;
1226 /* calculate base bpp dep. */
1227 switch(var
->bits_per_pixel
) {
1239 outXGIIDXREG(XGISR
, IND_XGI_PASSWORD
, XGI_PASSWORD
);
1241 outXGIIDXREG(XGICR
, 0x0D, base
& 0xFF);
1242 outXGIIDXREG(XGICR
, 0x0C, (base
>> 8) & 0xFF);
1243 outXGIIDXREG(XGISR
, 0x0D, (base
>> 16) & 0xFF);
1244 outXGIIDXREG(XGISR
, 0x37, (base
>> 24) & 0x03);
1245 setXGIIDXREG(XGISR
, 0x37, 0xDF, (base
>> 21) & 0x04);
1247 if(xgi_video_info
.disp_state
& DISPTYPE_DISP2
) {
1248 orXGIIDXREG(XGIPART1
, XGIfb_CRT2_write_enable
, 0x01);
1249 outXGIIDXREG(XGIPART1
, 0x06, (base
& 0xFF));
1250 outXGIIDXREG(XGIPART1
, 0x05, ((base
>> 8) & 0xFF));
1251 outXGIIDXREG(XGIPART1
, 0x04, ((base
>> 16) & 0xFF));
1252 setXGIIDXREG(XGIPART1
, 0x02, 0x7F, ((base
>> 24) & 0x01) << 7);
1254 // printk("End of pan_var");
1260 void XGI_dispinfo(struct ap_data
*rec
)
1262 rec
->minfo
.bpp
= xgi_video_info
.video_bpp
;
1263 rec
->minfo
.xres
= xgi_video_info
.video_width
;
1264 rec
->minfo
.yres
= xgi_video_info
.video_height
;
1265 rec
->minfo
.v_xres
= xgi_video_info
.video_vwidth
;
1266 rec
->minfo
.v_yres
= xgi_video_info
.video_vheight
;
1267 rec
->minfo
.org_x
= xgi_video_info
.org_x
;
1268 rec
->minfo
.org_y
= xgi_video_info
.org_y
;
1269 rec
->minfo
.vrate
= xgi_video_info
.refresh_rate
;
1270 rec
->iobase
= xgi_video_info
.vga_base
- 0x30;
1271 rec
->mem_size
= xgi_video_info
.video_size
;
1272 rec
->disp_state
= xgi_video_info
.disp_state
;
1273 rec
->version
= (VER_MAJOR
<< 24) | (VER_MINOR
<< 16) | VER_LEVEL
;
1274 rec
->hasVB
= xgi_video_info
.hasVB
;
1275 rec
->TV_type
= xgi_video_info
.TV_type
;
1276 rec
->TV_plug
= xgi_video_info
.TV_plug
;
1277 rec
->chip
= xgi_video_info
.chip
;
1283 static int XGIfb_open(struct fb_info
*info
, int user
)
1288 static int XGIfb_release(struct fb_info
*info
, int user
)
1293 static int XGIfb_get_cmap_len(const struct fb_var_screeninfo
*var
)
1297 switch(var
->bits_per_pixel
) {
1311 static int XGIfb_setcolreg(unsigned regno
, unsigned red
, unsigned green
, unsigned blue
,
1312 unsigned transp
, struct fb_info
*info
)
1314 if (regno
>= XGIfb_get_cmap_len(&info
->var
))
1317 switch (info
->var
.bits_per_pixel
) {
1319 outXGIREG(XGIDACA
, regno
);
1320 outXGIREG(XGIDACD
, (red
>> 10));
1321 outXGIREG(XGIDACD
, (green
>> 10));
1322 outXGIREG(XGIDACD
, (blue
>> 10));
1323 if (xgi_video_info
.disp_state
& DISPTYPE_DISP2
) {
1324 outXGIREG(XGIDAC2A
, regno
);
1325 outXGIREG(XGIDAC2D
, (red
>> 8));
1326 outXGIREG(XGIDAC2D
, (green
>> 8));
1327 outXGIREG(XGIDAC2D
, (blue
>> 8));
1331 ((u32
*)(info
->pseudo_palette
))[regno
] =
1332 ((red
& 0xf800)) | ((green
& 0xfc00) >> 5) | ((blue
& 0xf800) >> 11);
1338 ((u32
*) (info
->pseudo_palette
))[regno
] =
1339 (red
<< 16) | (green
<< 8) | (blue
);
1345 static int XGIfb_set_par(struct fb_info
*info
)
1349 // printk("XGIfb: inside set_par\n");
1350 if((err
= XGIfb_do_set_var(&info
->var
, 1, info
)))
1352 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
1353 XGIfb_get_fix(&info
->fix
, info
->currcon
, info
);
1355 XGIfb_get_fix(&info
->fix
, -1, info
);
1357 // printk("XGIfb:end of set_par\n");
1361 static int XGIfb_check_var(struct fb_var_screeninfo
*var
,
1362 struct fb_info
*info
)
1364 unsigned int htotal
=
1365 var
->left_margin
+ var
->xres
+ var
->right_margin
+
1367 unsigned int vtotal
= 0;
1368 unsigned int drate
= 0, hrate
= 0;
1370 int refresh_rate
, search_idx
;
1372 DEBUGPRN("Inside check_var");
1374 if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
) {
1375 vtotal
= var
->upper_margin
+ var
->yres
+ var
->lower_margin
+
1378 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
1379 vtotal
= var
->upper_margin
+ var
->yres
+ var
->lower_margin
+
1382 } else if((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
1383 vtotal
= var
->upper_margin
+ (var
->yres
/2) + var
->lower_margin
+
1385 } else vtotal
= var
->upper_margin
+ var
->yres
+ var
->lower_margin
+
1388 if(!(htotal
) || !(vtotal
)) {
1389 XGIFAIL("XGIfb: no valid timing data");
1393 if(var
->pixclock
&& htotal
&& vtotal
) {
1394 drate
= 1000000000 / var
->pixclock
;
1395 hrate
= (drate
* 1000) / htotal
;
1396 xgi_video_info
.refresh_rate
= (unsigned int) (hrate
* 2 / vtotal
);
1398 "%s: pixclock = %d ,htotal=%d, vtotal=%d\n" \
1399 "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1400 __func__
,var
->pixclock
, htotal
, vtotal
,
1401 __func__
, drate
, hrate
, xgi_video_info
.refresh_rate
);
1403 xgi_video_info
.refresh_rate
= 60;
1407 if((var->pixclock) && (htotal)) {
1408 drate = 1E12 / var->pixclock;
1409 hrate = drate / htotal;
1410 refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1411 } else refresh_rate = 60;
1413 /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
1414 if((var
->xres
== 1024) && (var
->yres
== 600)) refresh_rate
= 60;
1417 while((XGIbios_mode
[search_idx
].mode_no
!= 0) &&
1418 (XGIbios_mode
[search_idx
].xres
<= var
->xres
) ) {
1419 if((XGIbios_mode
[search_idx
].xres
== var
->xres
) &&
1420 (XGIbios_mode
[search_idx
].yres
== var
->yres
) &&
1421 (XGIbios_mode
[search_idx
].bpp
== var
->bits_per_pixel
)) {
1422 if(XGIfb_validate_mode(search_idx
) > 0) {
1432 printk(KERN_ERR
"XGIfb: %dx%dx%d is no valid mode\n",
1433 var
->xres
, var
->yres
, var
->bits_per_pixel
);
1436 while(XGIbios_mode
[search_idx
].mode_no
!= 0) {
1438 if( (var
->xres
<= XGIbios_mode
[search_idx
].xres
) &&
1439 (var
->yres
<= XGIbios_mode
[search_idx
].yres
) &&
1440 (var
->bits_per_pixel
== XGIbios_mode
[search_idx
].bpp
) ) {
1441 if(XGIfb_validate_mode(search_idx
) > 0) {
1449 var
->xres
= XGIbios_mode
[search_idx
].xres
;
1450 var
->yres
= XGIbios_mode
[search_idx
].yres
;
1451 printk(KERN_DEBUG
"XGIfb: Adapted to mode %dx%dx%d\n",
1452 var
->xres
, var
->yres
, var
->bits_per_pixel
);
1455 printk(KERN_ERR
"XGIfb: Failed to find similar mode to %dx%dx%d\n",
1456 var
->xres
, var
->yres
, var
->bits_per_pixel
);
1461 /* TW: TODO: Check the refresh rate */
1463 /* Adapt RGB settings */
1464 XGIfb_bpp_to_var(var
);
1466 /* Sanity check for offsets */
1467 if (var
->xoffset
< 0)
1469 if (var
->yoffset
< 0)
1474 if(var
->xres
!= var
->xres_virtual
)
1475 var
->xres_virtual
= var
->xres
;
1476 if(var
->yres
!= var
->yres_virtual
)
1477 var
->yres_virtual
= var
->yres
;
1479 // TW: Now patch yres_virtual if we use panning
1481 var->yres_virtual = xgi_video_info.heapstart / (var->xres * (var->bits_per_pixel >> 3));
1482 if(var->yres_virtual <= var->yres) {
1483 // TW: Paranoia check
1484 var->yres_virtual = var->yres;
1488 /* Truncate offsets to maximum if too high */
1489 if (var
->xoffset
> var
->xres_virtual
- var
->xres
)
1490 var
->xoffset
= var
->xres_virtual
- var
->xres
- 1;
1492 if (var
->yoffset
> var
->yres_virtual
- var
->yres
)
1493 var
->yoffset
= var
->yres_virtual
- var
->yres
- 1;
1495 /* Set everything else to 0 */
1496 var
->red
.msb_right
=
1497 var
->green
.msb_right
=
1498 var
->blue
.msb_right
=
1499 var
->transp
.offset
= var
->transp
.length
= var
->transp
.msb_right
= 0;
1501 DEBUGPRN("end of check_var");
1506 static int XGIfb_pan_display( struct fb_var_screeninfo
*var
,
1507 struct fb_info
* info
)
1511 // printk("\nInside pan_display:");
1513 if (var
->xoffset
> (var
->xres_virtual
- var
->xres
))
1515 if (var
->yoffset
> (var
->yres_virtual
- var
->yres
))
1518 if (var
->vmode
& FB_VMODE_YWRAP
) {
1519 if (var
->yoffset
< 0
1520 || var
->yoffset
>= info
->var
.yres_virtual
1521 || var
->xoffset
) return -EINVAL
;
1523 if (var
->xoffset
+ info
->var
.xres
> info
->var
.xres_virtual
||
1524 var
->yoffset
+ info
->var
.yres
> info
->var
.yres_virtual
)
1528 if((err
= XGIfb_pan_var(var
)) < 0) return err
;
1530 info
->var
.xoffset
= var
->xoffset
;
1531 info
->var
.yoffset
= var
->yoffset
;
1532 if (var
->vmode
& FB_VMODE_YWRAP
)
1533 info
->var
.vmode
|= FB_VMODE_YWRAP
;
1535 info
->var
.vmode
&= ~FB_VMODE_YWRAP
;
1537 // printk(" End of pan_display");
1543 static int XGIfb_mmap(struct fb_info
*info
, struct file
*file
,
1544 struct vm_area_struct
*vma
)
1546 unsigned long start
;
1550 DEBUGPRN("inside mmap");
1551 if(vma
->vm_pgoff
> (~0UL >> PAGE_SHIFT
)) return -EINVAL
;
1553 off
= vma
->vm_pgoff
<< PAGE_SHIFT
;
1555 start
= (unsigned long) xgi_video_info
.video_base
;
1556 len
= PAGE_ALIGN((start
& ~PAGE_MASK
) + xgi_video_info
.video_size
);
1562 /* By Jake Page: Treat mmap request with offset beyond heapstart
1563 * as request for mapping the mmio area
1566 mmio_off
= PAGE_ALIGN((start
& ~PAGE_MASK
) + xgi_video_info
.heapstart
);
1567 if(off
>= mmio_off
) {
1569 if(info
->var
.accel_flags
) return -EINVAL
;
1571 start
= (unsigned long) xgi_video_info
.mmio_base
;
1572 len
= PAGE_ALIGN((start
& ~PAGE_MASK
) + XGIfb_mmio_size
);
1576 if((vma
->vm_end
- vma
->vm_start
+ off
) > len
) return -EINVAL
;
1579 vma
->vm_pgoff
= off
>> PAGE_SHIFT
;
1580 vma
->vm_flags
|= VM_IO
; /* by Jake Page; is that really needed? */
1582 #if defined(__i386__) || defined(__x86_64__)
1583 if (boot_cpu_data
.x86
> 3)
1584 pgprot_val(vma
->vm_page_prot
) |= _PAGE_PCD
;
1586 if (io_remap_pfn_range(vma
, vma
->vm_start
, off
>> PAGE_SHIFT
, vma
->vm_end
- vma
->vm_start
,
1590 DEBUGPRN("end of mmap");
1594 static int XGIfb_blank(int blank
, struct fb_info
*info
)
1598 inXGIIDXREG(XGICR
, 0x17, reg
);
1605 outXGIIDXREG(XGICR
, 0x17, reg
);
1606 outXGIIDXREG(XGISR
, 0x00, 0x01); /* Synchronous Reset */
1607 outXGIIDXREG(XGISR
, 0x00, 0x03); /* End Reset */
1612 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
1613 static int XGIfb_ioctl(struct fb_info
*info
, unsigned int cmd
,
1616 static int XGIfb_ioctl(struct inode
*inode
, struct file
*file
,
1617 unsigned int cmd
, unsigned long arg
,
1618 struct fb_info
*info
)
1622 DEBUGPRN("inside ioctl");
1625 if (!capable(CAP_SYS_RAWIO
))
1627 XGI_malloc((struct XGI_memreq
*) arg
);
1630 if (!capable(CAP_SYS_RAWIO
))
1632 XGI_free(*(unsigned long *) arg
);
1634 case FBIOGET_HWCINFO
:
1636 unsigned long *hwc_offset
= (unsigned long *) arg
;
1638 if (XGIfb_caps
& HW_CURSOR_CAP
)
1639 *hwc_offset
= XGIfb_hwcursor_vbase
-
1640 (unsigned long) xgi_video_info
.video_vbase
;
1646 case FBIOPUT_MODEINFO
:
1648 struct mode_info
*x
= (struct mode_info
*)arg
;
1650 xgi_video_info
.video_bpp
= x
->bpp
;
1651 xgi_video_info
.video_width
= x
->xres
;
1652 xgi_video_info
.video_height
= x
->yres
;
1653 xgi_video_info
.video_vwidth
= x
->v_xres
;
1654 xgi_video_info
.video_vheight
= x
->v_yres
;
1655 xgi_video_info
.org_x
= x
->org_x
;
1656 xgi_video_info
.org_y
= x
->org_y
;
1657 xgi_video_info
.refresh_rate
= x
->vrate
;
1658 xgi_video_info
.video_linelength
= xgi_video_info
.video_vwidth
* (xgi_video_info
.video_bpp
>> 3);
1659 switch(xgi_video_info
.video_bpp
) {
1661 xgi_video_info
.DstColor
= 0x0000;
1662 xgi_video_info
.XGI310_AccelDepth
= 0x00000000;
1663 xgi_video_info
.video_cmap_len
= 256;
1666 xgi_video_info
.DstColor
= 0x8000;
1667 xgi_video_info
.XGI310_AccelDepth
= 0x00010000;
1668 xgi_video_info
.video_cmap_len
= 16;
1671 xgi_video_info
.DstColor
= 0xC000;
1672 xgi_video_info
.XGI310_AccelDepth
= 0x00020000;
1673 xgi_video_info
.video_cmap_len
= 16;
1676 xgi_video_info
.video_cmap_len
= 16;
1677 printk(KERN_ERR
"XGIfb: Unsupported accel depth %d", xgi_video_info
.video_bpp
);
1678 xgi_video_info
.accel
= 0;
1684 case FBIOGET_DISPINFO
:
1685 XGI_dispinfo((struct ap_data
*)arg
);
1687 case XGIFB_GET_INFO
: /* TW: New for communication with X driver */
1689 XGIfb_info
*x
= (XGIfb_info
*)arg
;
1691 //x->XGIfb_id = XGIFB_ID;
1692 x
->XGIfb_version
= VER_MAJOR
;
1693 x
->XGIfb_revision
= VER_MINOR
;
1694 x
->XGIfb_patchlevel
= VER_LEVEL
;
1695 x
->chip_id
= xgi_video_info
.chip_id
;
1696 x
->memory
= xgi_video_info
.video_size
/ 1024;
1697 x
->heapstart
= xgi_video_info
.heapstart
/ 1024;
1698 x
->fbvidmode
= XGIfb_mode_no
;
1699 x
->XGIfb_caps
= XGIfb_caps
;
1700 x
->XGIfb_tqlen
= 512; /* yet unused */
1701 x
->XGIfb_pcibus
= xgi_video_info
.pcibus
;
1702 x
->XGIfb_pcislot
= xgi_video_info
.pcislot
;
1703 x
->XGIfb_pcifunc
= xgi_video_info
.pcifunc
;
1704 x
->XGIfb_lcdpdc
= XGIfb_detectedpdc
;
1705 x
->XGIfb_lcda
= XGIfb_detectedlcda
;
1708 case XGIFB_GET_VBRSTATUS
:
1710 unsigned long *vbrstatus
= (unsigned long *) arg
;
1711 if(XGIfb_CheckVBRetrace()) *vbrstatus
= 1;
1712 else *vbrstatus
= 0;
1717 DEBUGPRN("end of ioctl");
1724 /* ----------- FBDev related routines for all series ---------- */
1726 static int XGIfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
1727 struct fb_info
*info
)
1729 DEBUGPRN("inside get_fix");
1730 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
1732 strcpy(fix
->id
, myid
);
1734 fix
->smem_start
= xgi_video_info
.video_base
;
1736 fix
->smem_len
= xgi_video_info
.video_size
;
1739 /* if((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
1740 if (xgi_video_info.video_size > 0x1000000) {
1741 fix->smem_len = 0xD00000;
1742 } else if (xgi_video_info.video_size > 0x800000)
1743 fix->smem_len = 0x800000;
1745 fix->smem_len = 0x400000;
1747 fix->smem_len = XGIfb_mem * 1024;
1749 fix
->type
= video_type
;
1751 if(xgi_video_info
.video_bpp
== 8)
1752 fix
->visual
= FB_VISUAL_PSEUDOCOLOR
;
1754 fix
->visual
= FB_VISUAL_DIRECTCOLOR
;
1757 if(XGIfb_ypan
) fix
->ypanstep
= 1;
1760 fix
->line_length
= xgi_video_info
.video_linelength
;
1761 fix
->mmio_start
= xgi_video_info
.mmio_base
;
1762 fix
->mmio_len
= XGIfb_mmio_size
;
1763 if(xgi_video_info
.chip
>= XG40
)
1764 fix
->accel
= FB_ACCEL_XGI_XABRE
;
1766 fix
->accel
= FB_ACCEL_XGI_GLAMOUR_2
;
1769 DEBUGPRN("end of get_fix");
1774 static struct fb_ops XGIfb_ops
= {
1775 .owner
= THIS_MODULE
,
1776 .fb_open
= XGIfb_open
,
1777 .fb_release
= XGIfb_release
,
1778 .fb_check_var
= XGIfb_check_var
,
1779 .fb_set_par
= XGIfb_set_par
,
1780 .fb_setcolreg
= XGIfb_setcolreg
,
1782 .fb_pan_display
= XGIfb_pan_display
,
1784 .fb_blank
= XGIfb_blank
,
1785 .fb_fillrect
= fbcon_XGI_fillrect
,
1786 .fb_copyarea
= fbcon_XGI_copyarea
,
1787 .fb_imageblit
= cfb_imageblit
,
1788 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
1789 .fb_cursor
= soft_cursor
,
1791 .fb_sync
= fbcon_XGI_sync
,
1792 .fb_ioctl
= XGIfb_ioctl
,
1793 // .fb_mmap = XGIfb_mmap,
1796 /* ---------------- Chip generation dependent routines ---------------- */
1799 /* for XGI 315/550/650/740/330 */
1801 static int XGIfb_get_dram_size(void)
1807 /* xorg driver sets 32MB * 1 channel */
1808 if (xgi_video_info
.chip
== XG27
)
1809 outXGIIDXREG(XGISR
, IND_XGI_DRAM_SIZE
, 0x51);
1811 inXGIIDXREG(XGISR
, IND_XGI_DRAM_SIZE
, reg
);
1812 switch ((reg
& XGI_DRAM_SIZE_MASK
) >> 4) {
1813 case XGI_DRAM_SIZE_1MB
:
1814 xgi_video_info
.video_size
= 0x100000;
1816 case XGI_DRAM_SIZE_2MB
:
1817 xgi_video_info
.video_size
= 0x200000;
1819 case XGI_DRAM_SIZE_4MB
:
1820 xgi_video_info
.video_size
= 0x400000;
1822 case XGI_DRAM_SIZE_8MB
:
1823 xgi_video_info
.video_size
= 0x800000;
1825 case XGI_DRAM_SIZE_16MB
:
1826 xgi_video_info
.video_size
= 0x1000000;
1828 case XGI_DRAM_SIZE_32MB
:
1829 xgi_video_info
.video_size
= 0x2000000;
1831 case XGI_DRAM_SIZE_64MB
:
1832 xgi_video_info
.video_size
= 0x4000000;
1834 case XGI_DRAM_SIZE_128MB
:
1835 xgi_video_info
.video_size
= 0x8000000;
1837 case XGI_DRAM_SIZE_256MB
:
1838 xgi_video_info
.video_size
= 0x10000000;
1844 tmp
= (reg
& 0x0c) >> 2;
1845 switch(xgi_video_info
.chip
)
1886 xgi_video_info
.video_size
= xgi_video_info
.video_size
* ChannelNum
;
1887 //PLiad fixed for benchmarking and fb set
1888 //xgi_video_info.video_size = 0x200000;//1024x768x16
1889 //xgi_video_info.video_size = 0x1000000;//benchmark
1891 printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n",reg
,xgi_video_info
.video_size
,ChannelNum
);
1896 static void XGIfb_detect_VB(void)
1900 xgi_video_info
.TV_plug
= xgi_video_info
.TV_type
= 0;
1902 switch(xgi_video_info
.hasVB
) {
1903 case HASVB_LVDS_CHRONTEL
:
1904 case HASVB_CHRONTEL
:
1908 // XGI_Sense30x(); //Yi-Lin TV Sense?
1912 inXGIIDXREG(XGICR
, IND_XGI_SCRATCH_REG_CR32
, cr32
);
1914 if ((cr32
& XGI_CRT1
) && !XGIfb_crt1off
)
1923 if (XGIfb_crt2type
!= -1)
1924 /* TW: Override with option */
1925 xgi_video_info
.disp_state
= XGIfb_crt2type
;
1926 else if (cr32
& XGI_VB_TV
)
1927 xgi_video_info
.disp_state
= DISPTYPE_TV
;
1928 else if (cr32
& XGI_VB_LCD
)
1929 xgi_video_info
.disp_state
= DISPTYPE_LCD
;
1930 else if (cr32
& XGI_VB_CRT2
)
1931 xgi_video_info
.disp_state
= DISPTYPE_CRT2
;
1933 xgi_video_info
.disp_state
= 0;
1935 if(XGIfb_tvplug
!= -1)
1936 /* PR/TW: Override with option */
1937 xgi_video_info
.TV_plug
= XGIfb_tvplug
;
1938 else if (cr32
& XGI_VB_HIVISION
) {
1939 xgi_video_info
.TV_type
= TVMODE_HIVISION
;
1940 xgi_video_info
.TV_plug
= TVPLUG_SVIDEO
;
1942 else if (cr32
& XGI_VB_SVIDEO
)
1943 xgi_video_info
.TV_plug
= TVPLUG_SVIDEO
;
1944 else if (cr32
& XGI_VB_COMPOSITE
)
1945 xgi_video_info
.TV_plug
= TVPLUG_COMPOSITE
;
1946 else if (cr32
& XGI_VB_SCART
)
1947 xgi_video_info
.TV_plug
= TVPLUG_SCART
;
1949 if(xgi_video_info
.TV_type
== 0) {
1950 /* TW: PAL/NTSC changed for 650 */
1951 if((xgi_video_info
.chip
<= XGI_315PRO
) || (xgi_video_info
.chip
>= XGI_330
)) {
1953 inXGIIDXREG(XGICR
, 0x38, temp
);
1955 xgi_video_info
.TV_type
= TVMODE_PAL
;
1957 xgi_video_info
.TV_type
= TVMODE_NTSC
;
1961 inXGIIDXREG(XGICR
, 0x79, temp
);
1963 xgi_video_info
.TV_type
= TVMODE_PAL
;
1965 xgi_video_info
.TV_type
= TVMODE_NTSC
;
1969 /* TW: Copy forceCRT1 option to CRT1off if option is given */
1970 if (XGIfb_forcecrt1
!= -1) {
1971 if (XGIfb_forcecrt1
) XGIfb_crt1off
= 0;
1972 else XGIfb_crt1off
= 1;
1976 static void XGIfb_get_VB_type(void)
1980 if (!XGIfb_has_VB()) {
1981 inXGIIDXREG(XGICR
, IND_XGI_SCRATCH_REG_CR37
, reg
);
1982 switch ((reg
& XGI_EXTERNAL_CHIP_MASK
) >> 1) {
1983 case XGI310_EXTERNAL_CHIP_LVDS
:
1984 xgi_video_info
.hasVB
= HASVB_LVDS
;
1986 case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL
:
1987 xgi_video_info
.hasVB
= HASVB_LVDS_CHRONTEL
;
1996 static int XGIfb_has_VB(void)
2000 inXGIIDXREG(XGIPART4
, 0x00, vb_chipid
);
2001 switch (vb_chipid
) {
2003 xgi_video_info
.hasVB
= HASVB_301
;
2006 xgi_video_info
.hasVB
= HASVB_302
;
2009 xgi_video_info
.hasVB
= HASVB_NONE
;
2017 /* ------------------ Sensing routines ------------------ */
2019 /* TW: Determine and detect attached devices on XGI30x */
2021 XGIDoSense(int tempbl
, int tempbh
, int tempcl
, int tempch
)
2025 outXGIIDXREG(XGIPART4
,0x11,tempbl
);
2026 temp
= tempbh
| tempcl
;
2027 setXGIIDXREG(XGIPART4
,0x10,0xe0,temp
);
2028 for(i
=0; i
<10; i
++) XGI_LongWait(&XGI_Pr
);
2030 inXGIIDXREG(XGIPART4
,0x03,temp
);
2040 u8 testsvhs_tempbl
, testsvhs_tempbh
;
2041 u8 testsvhs_tempcl
, testsvhs_tempch
;
2042 u8 testcvbs_tempbl
, testcvbs_tempbh
;
2043 u8 testcvbs_tempcl
, testcvbs_tempch
;
2044 u8 testvga2_tempbl
, testvga2_tempbh
;
2045 u8 testvga2_tempcl
, testvga2_tempch
;
2048 inXGIIDXREG(XGIPART4
,0x0d,backupP4_0d
);
2049 outXGIIDXREG(XGIPART4
,0x0d,(backupP4_0d
| 0x04));
2053 testvga2_tempbh
= 0x00; testvga2_tempbl
= 0xd1;
2054 testsvhs_tempbh
= 0x00; testsvhs_tempbl
= 0xb9;
2055 testcvbs_tempbh
= 0x00; testcvbs_tempbl
= 0xb3;
2056 if((XGIhw_ext
.ujVBChipID
!= VB_CHIP_301
) &&
2057 (XGIhw_ext
.ujVBChipID
!= VB_CHIP_302
)) {
2058 testvga2_tempbh
= 0x01; testvga2_tempbl
= 0x90;
2059 testsvhs_tempbh
= 0x01; testsvhs_tempbl
= 0x6b;
2060 testcvbs_tempbh
= 0x01; testcvbs_tempbl
= 0x74;
2061 if(XGIhw_ext
.ujVBChipID
== VB_CHIP_301LV
||
2062 XGIhw_ext
.ujVBChipID
== VB_CHIP_302LV
) {
2063 testvga2_tempbh
= 0x00; testvga2_tempbl
= 0x00;
2064 testsvhs_tempbh
= 0x02; testsvhs_tempbl
= 0x00;
2065 testcvbs_tempbh
= 0x01; testcvbs_tempbl
= 0x00;
2068 if(XGIhw_ext
.ujVBChipID
!= VB_CHIP_301LV
&&
2069 XGIhw_ext
.ujVBChipID
!= VB_CHIP_302LV
) {
2070 inXGIIDXREG(XGIPART4
,0x01,myflag
);
2072 testvga2_tempbh
= 0x00; testvga2_tempbl
= 0xfd;
2073 testsvhs_tempbh
= 0x00; testsvhs_tempbl
= 0xdd;
2074 testcvbs_tempbh
= 0x00; testcvbs_tempbl
= 0xee;
2077 if((XGIhw_ext
.ujVBChipID
== VB_CHIP_301LV
) ||
2078 (XGIhw_ext
.ujVBChipID
== VB_CHIP_302LV
) ) {
2079 testvga2_tempbh
= 0x00; testvga2_tempbl
= 0x00;
2080 testvga2_tempch
= 0x00; testvga2_tempcl
= 0x00;
2081 testsvhs_tempch
= 0x04; testsvhs_tempcl
= 0x08;
2082 testcvbs_tempch
= 0x08; testcvbs_tempcl
= 0x08;
2084 testvga2_tempch
= 0x0e; testvga2_tempcl
= 0x08;
2085 testsvhs_tempch
= 0x06; testsvhs_tempcl
= 0x04;
2086 testcvbs_tempch
= 0x08; testcvbs_tempcl
= 0x04;
2090 if(testvga2_tempch
|| testvga2_tempcl
|| testvga2_tempbh
|| testvga2_tempbl
) {
2091 result
= XGIDoSense(testvga2_tempbl
, testvga2_tempbh
,
2092 testvga2_tempcl
, testvga2_tempch
);
2094 printk(KERN_INFO
"XGIfb: Detected secondary VGA connection\n");
2095 orXGIIDXREG(XGICR
, 0x32, 0x10);
2099 result
= XGIDoSense(testsvhs_tempbl
, testsvhs_tempbh
,
2100 testsvhs_tempcl
, testsvhs_tempch
);
2102 printk(KERN_INFO
"XGIfb: Detected TV connected to SVHS output\n");
2103 /* TW: So we can be sure that there IS a SVHS output */
2104 xgi_video_info
.TV_plug
= TVPLUG_SVIDEO
;
2105 orXGIIDXREG(XGICR
, 0x32, 0x02);
2109 result
= XGIDoSense(testcvbs_tempbl
, testcvbs_tempbh
,
2110 testcvbs_tempcl
, testcvbs_tempch
);
2112 printk(KERN_INFO
"XGIfb: Detected TV connected to CVBS output\n");
2113 /* TW: So we can be sure that there IS a CVBS output */
2114 xgi_video_info
.TV_plug
= TVPLUG_COMPOSITE
;
2115 orXGIIDXREG(XGICR
, 0x32, 0x01);
2118 XGIDoSense(0, 0, 0, 0);
2120 outXGIIDXREG(XGIPART4
,0x0d,backupP4_0d
);
2125 /* ------------------------ Heap routines -------------------------- */
2127 static int XGIfb_heap_init(void)
2132 int agp_enabled
= 1;
2134 unsigned long *cmdq_baseport
= 0;
2135 unsigned long *read_port
= 0;
2136 unsigned long *write_port
= 0;
2137 XGI_CMDTYPE cmd_type
;
2139 struct agp_kern_info
*agp_info
;
2140 struct agp_memory
*agp
;
2144 /* TW: The heap start is either set manually using the "mem" parameter, or
2145 * defaults as follows:
2146 * -) If more than 16MB videoRAM available, let our heap start at 12MB.
2147 * -) If more than 8MB videoRAM available, let our heap start at 8MB.
2148 * -) If 4MB or less is available, let it start at 4MB.
2149 * This is for avoiding a clash with X driver which uses the beginning
2150 * of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem
2152 * The heap start can also be specified by parameter "mem" when starting the XGIfb
2153 * driver. XGIfb mem=1024 lets heap starts at 1MB, etc.
2155 if ((!XGIfb_mem
) || (XGIfb_mem
> (xgi_video_info
.video_size
/1024))) {
2156 if (xgi_video_info
.video_size
> 0x1000000) {
2157 xgi_video_info
.heapstart
= 0xD00000;
2158 } else if (xgi_video_info
.video_size
> 0x800000) {
2159 xgi_video_info
.heapstart
= 0x800000;
2161 xgi_video_info
.heapstart
= 0x400000;
2164 xgi_video_info
.heapstart
= XGIfb_mem
* 1024;
2167 (unsigned long) (xgi_video_info
.video_vbase
+ xgi_video_info
.heapstart
);
2168 printk(KERN_INFO
"XGIfb: Memory heap starting at %dK\n",
2169 (int)(xgi_video_info
.heapstart
/ 1024));
2171 XGIfb_heap_end
= (unsigned long) xgi_video_info
.video_vbase
+ xgi_video_info
.video_size
;
2172 XGIfb_heap_size
= XGIfb_heap_end
- XGIfb_heap_start
;
2176 /* TW: Now initialize the 310 series' command queue mode.
2177 * On 310/325, there are three queue modes available which
2178 * are chosen by setting bits 7:5 in SR26:
2179 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
2180 * track of the queue, the FIFO, command parsing and so
2181 * on. This is the one comparable to the 300 series.
2182 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will
2183 * have to do queue management himself. Register 0x85c4 will
2184 * hold the location of the next free queue slot, 0x85c8
2185 * is the "queue read pointer" whose way of working is
2186 * unknown to me. Anyway, this mode would require a
2187 * translation of the MMIO commands to some kind of
2188 * accelerator assembly and writing these commands
2189 * to the memory location pointed to by 0x85c4.
2190 * We will not use this, as nobody knows how this
2191 * "assembly" works, and as it would require a complete
2192 * re-write of the accelerator code.
2193 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the
2194 * queue in AGP memory space.
2196 * SR26 bit 4 is called "Bypass H/W queue".
2197 * SR26 bit 1 is called "Enable Command Queue Auto Correction"
2198 * SR26 bit 0 resets the queue
2199 * Size of queue memory is encoded in bits 3:2 like this:
2204 * The queue location is to be written to 0x85C0.
2207 cmdq_baseport
= (unsigned long *)(xgi_video_info
.mmio_vbase
+ MMIO_QUEUE_PHYBASE
);
2208 write_port
= (unsigned long *)(xgi_video_info
.mmio_vbase
+ MMIO_QUEUE_WRITEPORT
);
2209 read_port
= (unsigned long *)(xgi_video_info
.mmio_vbase
+ MMIO_QUEUE_READPORT
);
2211 DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport
, read_port
, write_port
);
2213 agp_size
= COMMAND_QUEUE_AREA_SIZE
;
2216 if (XGIfb_queuemode
== AGP_CMD_QUEUE
) {
2217 agp_info
= vmalloc(sizeof(*agp_info
));
2218 memset((void*)agp_info
, 0x00, sizeof(*agp_info
));
2219 agp_copy_info(agp_info
);
2221 agp_backend_acquire();
2223 agp
= agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE
/PAGE_SIZE
,
2226 DPRINTK("XGIfb: Allocating AGP buffer failed.\n");
2229 if (agp_bind_memory(agp
, agp
->pg_start
) != 0) {
2230 DPRINTK("XGIfb: AGP: Failed to bind memory\n");
2231 /* TODO: Free AGP memory here */
2242 /* TW: Now select the queue mode */
2244 if ((agp_enabled
) && (XGIfb_queuemode
== AGP_CMD_QUEUE
)) {
2245 cmd_type
= AGP_CMD_QUEUE
;
2246 printk(KERN_INFO
"XGIfb: Using AGP queue mode\n");
2247 /* } else if (XGIfb_heap_size >= COMMAND_QUEUE_AREA_SIZE) */
2248 } else if (XGIfb_queuemode
== VM_CMD_QUEUE
) {
2249 cmd_type
= VM_CMD_QUEUE
;
2250 printk(KERN_INFO
"XGIfb: Using VRAM queue mode\n");
2252 printk(KERN_INFO
"XGIfb: Using MMIO queue mode\n");
2253 cmd_type
= MMIO_CMD
;
2258 temp
= XGI_CMD_QUEUE_SIZE_512k
;
2261 temp
= XGI_CMD_QUEUE_SIZE_1M
;
2264 temp
= XGI_CMD_QUEUE_SIZE_2M
;
2267 temp
= XGI_CMD_QUEUE_SIZE_4M
;
2274 DPRINTK("XGIfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n",
2275 agp_info
->aper_base
, agp
->physical
, agp_size
/1024);
2277 agp_phys
= agp_info
->aper_base
+ agp
->physical
;
2279 outXGIIDXREG(XGICR
, IND_XGI_AGP_IO_PAD
, 0);
2280 outXGIIDXREG(XGICR
, IND_XGI_AGP_IO_PAD
, XGI_AGP_2X
);
2282 outXGIIDXREG(XGISR
, IND_XGI_CMDQUEUE_THRESHOLD
, COMMAND_QUEUE_THRESHOLD
);
2284 outXGIIDXREG(XGISR
, IND_XGI_CMDQUEUE_SET
, XGI_CMD_QUEUE_RESET
);
2286 *write_port
= *read_port
;
2288 temp
|= XGI_AGP_CMDQUEUE_ENABLE
;
2289 outXGIIDXREG(XGISR
, IND_XGI_CMDQUEUE_SET
, temp
);
2291 *cmdq_baseport
= agp_phys
;
2293 XGIfb_caps
|= AGP_CMD_QUEUE_CAP
;
2298 XGIfb_heap_end
-= COMMAND_QUEUE_AREA_SIZE
;
2299 XGIfb_heap_size
-= COMMAND_QUEUE_AREA_SIZE
;
2301 outXGIIDXREG(XGISR
, IND_XGI_CMDQUEUE_THRESHOLD
, COMMAND_QUEUE_THRESHOLD
);
2303 outXGIIDXREG(XGISR
, IND_XGI_CMDQUEUE_SET
, XGI_CMD_QUEUE_RESET
);
2305 *write_port
= *read_port
;
2307 temp
|= XGI_VRAM_CMDQUEUE_ENABLE
;
2308 outXGIIDXREG(XGISR
, IND_XGI_CMDQUEUE_SET
, temp
);
2310 *cmdq_baseport
= xgi_video_info
.video_size
- COMMAND_QUEUE_AREA_SIZE
;
2312 XGIfb_caps
|= VM_CMD_QUEUE_CAP
;
2314 DPRINTK("XGIfb: VM Cmd Queue offset = 0x%lx, size is %dK\n",
2315 *cmdq_baseport
, COMMAND_QUEUE_AREA_SIZE
/1024);
2320 // printk("%s:%d - I'm here\n", __FUNCTION__, __LINE__);
2321 /* TW: This previously only wrote XGI_MMIO_CMD_ENABLE
2322 * to IND_XGI_CMDQUEUE_SET. I doubt that this is
2323 * enough. Reserve memory in any way.
2325 // FIXME XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
2326 // FIXME XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
2328 // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2329 // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2331 // FIXME *write_port = *read_port;
2333 // FIXME /* TW: Set Auto_Correction bit */
2334 // FIXME temp |= (XGI_MMIO_CMD_ENABLE | XGI_CMD_AUTO_CORR);
2335 // FIXME // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2337 // FIXME *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
2339 // FIXME XGIfb_caps |= MMIO_CMD_QUEUE_CAP;
2341 // FIXME DPRINTK("XGIfb: MMIO Cmd Queue offset = 0x%lx, size is %dK\n",
2342 // FIXME *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
2349 /* TW: Now reserve memory for the HWCursor. It is always located at the very
2350 top of the videoRAM, right below the TB memory area (if used). */
2351 if (XGIfb_heap_size
>= XGIfb_hwcursor_size
) {
2352 XGIfb_heap_end
-= XGIfb_hwcursor_size
;
2353 XGIfb_heap_size
-= XGIfb_hwcursor_size
;
2354 XGIfb_hwcursor_vbase
= XGIfb_heap_end
;
2356 XGIfb_caps
|= HW_CURSOR_CAP
;
2358 DPRINTK("XGIfb: Hardware Cursor start at 0x%lx, size is %dK\n",
2359 XGIfb_heap_end
, XGIfb_hwcursor_size
/1024);
2362 XGIfb_heap
.poha_chain
= NULL
;
2363 XGIfb_heap
.poh_freelist
= NULL
;
2365 poh
= XGIfb_poh_new_node();
2367 if(poh
== NULL
) return 1;
2369 poh
->poh_next
= &XGIfb_heap
.oh_free
;
2370 poh
->poh_prev
= &XGIfb_heap
.oh_free
;
2371 poh
->size
= XGIfb_heap_end
- XGIfb_heap_start
+ 1;
2372 poh
->offset
= XGIfb_heap_start
- (unsigned long) xgi_video_info
.video_vbase
;
2374 DPRINTK("XGIfb: Heap start:0x%p, end:0x%p, len=%dk\n",
2375 (char *) XGIfb_heap_start
, (char *) XGIfb_heap_end
,
2376 (unsigned int) poh
->size
/ 1024);
2378 DPRINTK("XGIfb: First Node offset:0x%x, size:%dk\n",
2379 (unsigned int) poh
->offset
, (unsigned int) poh
->size
/ 1024);
2381 XGIfb_heap
.oh_free
.poh_next
= poh
;
2382 XGIfb_heap
.oh_free
.poh_prev
= poh
;
2383 XGIfb_heap
.oh_free
.size
= 0;
2384 XGIfb_heap
.max_freesize
= poh
->size
;
2386 XGIfb_heap
.oh_used
.poh_next
= &XGIfb_heap
.oh_used
;
2387 XGIfb_heap
.oh_used
.poh_prev
= &XGIfb_heap
.oh_used
;
2388 XGIfb_heap
.oh_used
.size
= SENTINEL
;
2393 static XGI_OH
*XGIfb_poh_new_node(void)
2400 if (XGIfb_heap
.poh_freelist
== NULL
) {
2401 poha
= kmalloc(OH_ALLOC_SIZE
, GFP_KERNEL
);
2402 if(!poha
) return NULL
;
2404 poha
->poha_next
= XGIfb_heap
.poha_chain
;
2405 XGIfb_heap
.poha_chain
= poha
;
2407 cOhs
= (OH_ALLOC_SIZE
- sizeof(XGI_OHALLOC
)) / sizeof(XGI_OH
) + 1;
2409 poh
= &poha
->aoh
[0];
2410 for (i
= cOhs
- 1; i
!= 0; i
--) {
2411 poh
->poh_next
= poh
+ 1;
2415 poh
->poh_next
= NULL
;
2416 XGIfb_heap
.poh_freelist
= &poha
->aoh
[0];
2419 poh
= XGIfb_heap
.poh_freelist
;
2420 XGIfb_heap
.poh_freelist
= poh
->poh_next
;
2425 static XGI_OH
*XGIfb_poh_allocate(unsigned long size
)
2431 if (size
> XGIfb_heap
.max_freesize
) {
2432 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2433 (unsigned int) size
/ 1024);
2437 pohThis
= XGIfb_heap
.oh_free
.poh_next
;
2439 while (pohThis
!= &XGIfb_heap
.oh_free
) {
2440 if (size
<= pohThis
->size
) {
2444 pohThis
= pohThis
->poh_next
;
2448 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2449 (unsigned int) size
/ 1024);
2453 if (size
== pohThis
->size
) {
2455 XGIfb_delete_node(pohThis
);
2457 pohRoot
= XGIfb_poh_new_node();
2459 if (pohRoot
== NULL
) {
2463 pohRoot
->offset
= pohThis
->offset
;
2464 pohRoot
->size
= size
;
2466 pohThis
->offset
+= size
;
2467 pohThis
->size
-= size
;
2470 XGIfb_heap
.max_freesize
-= size
;
2472 pohThis
= &XGIfb_heap
.oh_used
;
2473 XGIfb_insert_node(pohThis
, pohRoot
);
2478 static void XGIfb_delete_node(XGI_OH
*poh
)
2483 poh_prev
= poh
->poh_prev
;
2484 poh_next
= poh
->poh_next
;
2486 poh_prev
->poh_next
= poh_next
;
2487 poh_next
->poh_prev
= poh_prev
;
2491 static void XGIfb_insert_node(XGI_OH
*pohList
, XGI_OH
*poh
)
2495 pohTemp
= pohList
->poh_next
;
2497 pohList
->poh_next
= poh
;
2498 pohTemp
->poh_prev
= poh
;
2500 poh
->poh_prev
= pohList
;
2501 poh
->poh_next
= pohTemp
;
2504 static XGI_OH
*XGIfb_poh_free(unsigned long base
)
2510 unsigned long ulUpper
;
2511 unsigned long ulLower
;
2514 poh_freed
= XGIfb_heap
.oh_used
.poh_next
;
2516 while(poh_freed
!= &XGIfb_heap
.oh_used
) {
2517 if(poh_freed
->offset
== base
) {
2522 poh_freed
= poh_freed
->poh_next
;
2525 if (!foundNode
) return (NULL
);
2527 XGIfb_heap
.max_freesize
+= poh_freed
->size
;
2529 poh_prev
= poh_next
= NULL
;
2530 ulUpper
= poh_freed
->offset
+ poh_freed
->size
;
2531 ulLower
= poh_freed
->offset
;
2533 pohThis
= XGIfb_heap
.oh_free
.poh_next
;
2535 while (pohThis
!= &XGIfb_heap
.oh_free
) {
2536 if (pohThis
->offset
== ulUpper
) {
2539 else if ((pohThis
->offset
+ pohThis
->size
) ==
2543 pohThis
= pohThis
->poh_next
;
2546 XGIfb_delete_node(poh_freed
);
2548 if (poh_prev
&& poh_next
) {
2549 poh_prev
->size
+= (poh_freed
->size
+ poh_next
->size
);
2550 XGIfb_delete_node(poh_next
);
2551 XGIfb_free_node(poh_freed
);
2552 XGIfb_free_node(poh_next
);
2557 poh_prev
->size
+= poh_freed
->size
;
2558 XGIfb_free_node(poh_freed
);
2563 poh_next
->size
+= poh_freed
->size
;
2564 poh_next
->offset
= poh_freed
->offset
;
2565 XGIfb_free_node(poh_freed
);
2569 XGIfb_insert_node(&XGIfb_heap
.oh_free
, poh_freed
);
2574 static void XGIfb_free_node(XGI_OH
*poh
)
2576 if(poh
== NULL
) return;
2578 poh
->poh_next
= XGIfb_heap
.poh_freelist
;
2579 XGIfb_heap
.poh_freelist
= poh
;
2583 void XGI_malloc(struct XGI_memreq
*req
)
2587 poh
= XGIfb_poh_allocate(req
->size
);
2592 DPRINTK("XGIfb: Video RAM allocation failed\n");
2594 DPRINTK("XGIfb: Video RAM allocation succeeded: 0x%p\n",
2595 (char *) (poh
->offset
+ (unsigned long) xgi_video_info
.video_vbase
));
2597 req
->offset
= poh
->offset
;
2598 req
->size
= poh
->size
;
2603 void XGI_free(unsigned long base
)
2607 poh
= XGIfb_poh_free(base
);
2610 DPRINTK("XGIfb: XGIfb_poh_free() failed at base 0x%x\n",
2611 (unsigned int) base
);
2615 /* --------------------- SetMode routines ------------------------- */
2617 static void XGIfb_pre_setmode(void)
2619 u8 cr30
= 0, cr31
= 0;
2621 inXGIIDXREG(XGICR
, 0x31, cr31
);
2624 switch (xgi_video_info
.disp_state
& DISPTYPE_DISP2
) {
2626 cr30
= (XGI_VB_OUTPUT_CRT2
| XGI_SIMULTANEOUS_VIEW_ENABLE
);
2627 cr31
|= XGI_DRIVER_MODE
;
2630 cr30
= (XGI_VB_OUTPUT_LCD
| XGI_SIMULTANEOUS_VIEW_ENABLE
);
2631 cr31
|= XGI_DRIVER_MODE
;
2634 if (xgi_video_info
.TV_type
== TVMODE_HIVISION
)
2635 cr30
= (XGI_VB_OUTPUT_HIVISION
| XGI_SIMULTANEOUS_VIEW_ENABLE
);
2636 else if (xgi_video_info
.TV_plug
== TVPLUG_SVIDEO
)
2637 cr30
= (XGI_VB_OUTPUT_SVIDEO
| XGI_SIMULTANEOUS_VIEW_ENABLE
);
2638 else if (xgi_video_info
.TV_plug
== TVPLUG_COMPOSITE
)
2639 cr30
= (XGI_VB_OUTPUT_COMPOSITE
| XGI_SIMULTANEOUS_VIEW_ENABLE
);
2640 else if (xgi_video_info
.TV_plug
== TVPLUG_SCART
)
2641 cr30
= (XGI_VB_OUTPUT_SCART
| XGI_SIMULTANEOUS_VIEW_ENABLE
);
2642 cr31
|= XGI_DRIVER_MODE
;
2644 if (XGIfb_tvmode
== 1 || xgi_video_info
.TV_type
== TVMODE_PAL
)
2649 default: /* disable CRT2 */
2651 cr31
|= (XGI_DRIVER_MODE
| XGI_VB_OUTPUT_DISABLE
);
2654 outXGIIDXREG(XGICR
, IND_XGI_SCRATCH_REG_CR30
, cr30
);
2655 outXGIIDXREG(XGICR
, IND_XGI_SCRATCH_REG_CR31
, cr31
);
2656 outXGIIDXREG(XGICR
, IND_XGI_SCRATCH_REG_CR33
, (XGIfb_rate_idx
& 0x0F));
2658 if(xgi_video_info
.accel
) XGIfb_syncaccel();
2663 static void XGIfb_post_setmode(void)
2666 BOOLEAN doit
= TRUE
;
2667 #if 0 /* TW: Wrong: Is not in MMIO space, but in RAM */
2668 /* Backup mode number to MMIO space */
2669 if(xgi_video_info
.mmio_vbase
) {
2670 *(volatile u8
*)(((u8
*)xgi_video_info
.mmio_vbase
) + 0x449) = (unsigned char)XGIfb_mode_no
;
2673 /* outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
2674 outXGIIDXREG(XGICR,0x13,0x00);
2675 setXGIIDXREG(XGISR,0x0E,0xF0,0x01);
2677 if (xgi_video_info
.video_bpp
== 8) {
2678 /* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */
2679 if ((xgi_video_info
.hasVB
== HASVB_LVDS
) || (xgi_video_info
.hasVB
== HASVB_LVDS_CHRONTEL
)) {
2682 /* TW: We can't switch off CRT1 on 301B-DH in 8bpp Modes if using LCD */
2683 if (xgi_video_info
.disp_state
& DISPTYPE_LCD
) {
2688 /* TW: We can't switch off CRT1 if bridge is in slave mode */
2689 if(xgi_video_info
.hasVB
!= HASVB_NONE
) {
2690 inXGIIDXREG(XGIPART1
, 0x00, reg
);
2693 if((reg
& 0x50) == 0x10) {
2697 } else XGIfb_crt1off
= 0;
2699 inXGIIDXREG(XGICR
, 0x17, reg
);
2700 if((XGIfb_crt1off
) && (doit
))
2704 outXGIIDXREG(XGICR
, 0x17, reg
);
2706 andXGIIDXREG(XGISR
, IND_XGI_RAMDAC_CONTROL
, ~0x04);
2708 if((xgi_video_info
.disp_state
& DISPTYPE_TV
) && (xgi_video_info
.hasVB
== HASVB_301
)) {
2710 inXGIIDXREG(XGIPART4
, 0x01, reg
);
2712 if(reg
< 0xB0) { /* Set filter for XGI301 */
2714 switch (xgi_video_info
.video_width
) {
2716 filter_tb
= (xgi_video_info
.TV_type
== TVMODE_NTSC
) ? 4 : 12;
2719 filter_tb
= (xgi_video_info
.TV_type
== TVMODE_NTSC
) ? 5 : 13;
2722 filter_tb
= (xgi_video_info
.TV_type
== TVMODE_NTSC
) ? 6 : 14;
2725 filter_tb
= (xgi_video_info
.TV_type
== TVMODE_NTSC
) ? 7 : 15;
2732 orXGIIDXREG(XGIPART1
, XGIfb_CRT2_write_enable
, 0x01);
2734 if(xgi_video_info
.TV_type
== TVMODE_NTSC
) {
2736 andXGIIDXREG(XGIPART2
, 0x3a, 0x1f);
2738 if (xgi_video_info
.TV_plug
== TVPLUG_SVIDEO
) {
2740 andXGIIDXREG(XGIPART2
, 0x30, 0xdf);
2742 } else if (xgi_video_info
.TV_plug
== TVPLUG_COMPOSITE
) {
2744 orXGIIDXREG(XGIPART2
, 0x30, 0x20);
2746 switch (xgi_video_info
.video_width
) {
2748 outXGIIDXREG(XGIPART2
, 0x35, 0xEB);
2749 outXGIIDXREG(XGIPART2
, 0x36, 0x04);
2750 outXGIIDXREG(XGIPART2
, 0x37, 0x25);
2751 outXGIIDXREG(XGIPART2
, 0x38, 0x18);
2754 outXGIIDXREG(XGIPART2
, 0x35, 0xEE);
2755 outXGIIDXREG(XGIPART2
, 0x36, 0x0C);
2756 outXGIIDXREG(XGIPART2
, 0x37, 0x22);
2757 outXGIIDXREG(XGIPART2
, 0x38, 0x08);
2760 outXGIIDXREG(XGIPART2
, 0x35, 0xEB);
2761 outXGIIDXREG(XGIPART2
, 0x36, 0x15);
2762 outXGIIDXREG(XGIPART2
, 0x37, 0x25);
2763 outXGIIDXREG(XGIPART2
, 0x38, 0xF6);
2768 } else if(xgi_video_info
.TV_type
== TVMODE_PAL
) {
2770 andXGIIDXREG(XGIPART2
, 0x3A, 0x1F);
2772 if (xgi_video_info
.TV_plug
== TVPLUG_SVIDEO
) {
2774 andXGIIDXREG(XGIPART2
, 0x30, 0xDF);
2776 } else if (xgi_video_info
.TV_plug
== TVPLUG_COMPOSITE
) {
2778 orXGIIDXREG(XGIPART2
, 0x30, 0x20);
2780 switch (xgi_video_info
.video_width
) {
2782 outXGIIDXREG(XGIPART2
, 0x35, 0xF1);
2783 outXGIIDXREG(XGIPART2
, 0x36, 0xF7);
2784 outXGIIDXREG(XGIPART2
, 0x37, 0x1F);
2785 outXGIIDXREG(XGIPART2
, 0x38, 0x32);
2788 outXGIIDXREG(XGIPART2
, 0x35, 0xF3);
2789 outXGIIDXREG(XGIPART2
, 0x36, 0x00);
2790 outXGIIDXREG(XGIPART2
, 0x37, 0x1D);
2791 outXGIIDXREG(XGIPART2
, 0x38, 0x20);
2794 outXGIIDXREG(XGIPART2
, 0x35, 0xFC);
2795 outXGIIDXREG(XGIPART2
, 0x36, 0xFB);
2796 outXGIIDXREG(XGIPART2
, 0x37, 0x14);
2797 outXGIIDXREG(XGIPART2
, 0x38, 0x2A);
2803 if ((filter
>= 0) && (filter
<=7)) {
2804 DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb
, filter
,
2805 XGI_TV_filter
[filter_tb
].filter
[filter
][0],
2806 XGI_TV_filter
[filter_tb
].filter
[filter
][1],
2807 XGI_TV_filter
[filter_tb
].filter
[filter
][2],
2808 XGI_TV_filter
[filter_tb
].filter
[filter
][3]
2810 outXGIIDXREG(XGIPART2
, 0x35, (XGI_TV_filter
[filter_tb
].filter
[filter
][0]));
2811 outXGIIDXREG(XGIPART2
, 0x36, (XGI_TV_filter
[filter_tb
].filter
[filter
][1]));
2812 outXGIIDXREG(XGIPART2
, 0x37, (XGI_TV_filter
[filter_tb
].filter
[filter
][2]));
2813 outXGIIDXREG(XGIPART2
, 0x38, (XGI_TV_filter
[filter_tb
].filter
[filter
][3]));
2823 XGIINITSTATIC
int __init
XGIfb_setup(char *options
)
2829 xgi_video_info
.refresh_rate
= 0;
2831 printk(KERN_INFO
"XGIfb: Options %s\n", options
);
2833 if (!options
|| !*options
)
2836 while((this_opt
= strsep(&options
, ",")) != NULL
) {
2838 if (!*this_opt
) continue;
2840 if (!strncmp(this_opt
, "mode:", 5)) {
2841 XGIfb_search_mode(this_opt
+ 5);
2842 } else if (!strncmp(this_opt
, "vesa:", 5)) {
2843 XGIfb_search_vesamode(simple_strtoul(this_opt
+ 5, NULL
, 0));
2844 } else if (!strncmp(this_opt
, "mode:", 5)) {
2845 XGIfb_search_mode(this_opt
+ 5);
2846 } else if (!strncmp(this_opt
, "vesa:", 5)) {
2847 XGIfb_search_vesamode(simple_strtoul(this_opt
+ 5, NULL
, 0));
2848 } else if (!strncmp(this_opt
, "vrate:", 6)) {
2849 xgi_video_info
.refresh_rate
= simple_strtoul(this_opt
+ 6, NULL
, 0);
2850 } else if (!strncmp(this_opt
, "rate:", 5)) {
2851 xgi_video_info
.refresh_rate
= simple_strtoul(this_opt
+ 5, NULL
, 0);
2852 } else if (!strncmp(this_opt
, "off", 3)) {
2854 } else if (!strncmp(this_opt
, "crt1off", 7)) {
2856 } else if (!strncmp(this_opt
, "filter:", 7)) {
2857 filter
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
2858 } else if (!strncmp(this_opt
, "forcecrt2type:", 14)) {
2859 XGIfb_search_crt2type(this_opt
+ 14);
2860 } else if (!strncmp(this_opt
, "forcecrt1:", 10)) {
2861 XGIfb_forcecrt1
= (int)simple_strtoul(this_opt
+ 10, NULL
, 0);
2862 } else if (!strncmp(this_opt
, "tvmode:",7)) {
2863 XGIfb_search_tvstd(this_opt
+ 7);
2864 } else if (!strncmp(this_opt
, "tvstandard:",11)) {
2865 XGIfb_search_tvstd(this_opt
+ 7);
2866 } else if (!strncmp(this_opt
, "mem:",4)) {
2867 XGIfb_mem
= simple_strtoul(this_opt
+ 4, NULL
, 0);
2868 } else if (!strncmp(this_opt
, "dstn", 4)) {
2870 /* TW: DSTN overrules forcecrt2type */
2871 XGIfb_crt2type
= DISPTYPE_LCD
;
2872 } else if (!strncmp(this_opt
, "queuemode:", 10)) {
2873 XGIfb_search_queuemode(this_opt
+ 10);
2874 } else if (!strncmp(this_opt
, "pdc:", 4)) {
2875 XGIfb_pdc
= simple_strtoul(this_opt
+ 4, NULL
, 0);
2876 if(XGIfb_pdc
& ~0x3c) {
2877 printk(KERN_INFO
"XGIfb: Illegal pdc parameter\n");
2880 } else if (!strncmp(this_opt
, "noaccel", 7)) {
2882 } else if (!strncmp(this_opt
, "noypan", 6)) {
2884 } else if (!strncmp(this_opt
, "userom:", 7)) {
2885 XGIfb_userom
= (int)simple_strtoul(this_opt
+ 7, NULL
, 0);
2886 // } else if (!strncmp(this_opt, "useoem:", 7)) {
2887 // XGIfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
2889 XGIfb_search_mode(this_opt
);
2890 // printk(KERN_INFO "XGIfb: Invalid option %s\n", this_opt);
2893 /* TW: Acceleration only with MMIO mode */
2894 if((XGIfb_queuemode
!= -1) && (XGIfb_queuemode
!= MMIO_CMD
)) {
2898 /* TW: Panning only with acceleration */
2899 if(XGIfb_accel
== 0) XGIfb_ypan
= 0;
2902 printk("\nxgifb: outa xgifb_setup 3450");
2907 static unsigned char VBIOS_BUF
[65535];
2909 unsigned char* attempt_map_rom(struct pci_dev
*dev
,void *copy_address
)
2912 u32 rom_address
= 0;
2915 /* Get the size of the expansion rom */
2916 pci_write_config_dword(dev
, PCI_ROM_ADDRESS
, 0xFFFFFFFF);
2917 pci_read_config_dword(dev
, PCI_ROM_ADDRESS
, &rom_size
);
2918 if ((rom_size
& 0x01) == 0)
2924 rom_size
&= 0xFFFFF800;
2925 rom_size
= (~rom_size
)+1;
2927 rom_address
= pci_resource_start(dev
, 0);
2928 if (rom_address
== 0 || rom_address
== 0xFFFFFFF0)
2930 printk("No suitable rom address found\n"); return NULL
;
2933 printk("ROM Size is %dK, Address is %x\n", rom_size
/1024, rom_address
);
2936 pci_write_config_dword(dev
, PCI_ROM_ADDRESS
, rom_address
| PCI_ROM_ADDRESS_ENABLE
);
2938 /* memcpy(copy_address, rom_address, rom_size); */
2940 unsigned char *virt_addr
= ioremap(rom_address
, 0x8000000);
2942 unsigned char *from
= (unsigned char *)virt_addr
;
2943 unsigned char *to
= (unsigned char *)copy_address
;
2944 for (j
=0; j
<65536 /*rom_size*/; j
++) *to
++ = *from
++;
2947 pci_write_config_dword(dev
, PCI_ROM_ADDRESS
, 0);
2949 printk("Copy is done\n");
2951 return copy_address
;
2954 int __devinit
xgifb_probe(struct pci_dev
*pdev
, const struct pci_device_id
*ent
)
2962 XGIfb_registered
= 0;
2964 memset(&XGIhw_ext
, 0, sizeof(HW_DEVICE_EXTENSION
));
2965 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
2966 fb_info
= framebuffer_alloc(sizeof(struct fb_info
), &pdev
->dev
);
2967 if(!fb_info
) return -ENOMEM
;
2969 XGI_fb_info
= kmalloc( sizeof(struct fb_info
), GFP_KERNEL
);
2970 if(!XGI_fb_info
) return -ENOMEM
;
2971 memset(XGI_fb_info
, 0, sizeof(struct fb_info
));
2974 xgi_video_info
.chip_id
= pdev
->device
;
2975 pci_read_config_byte(pdev
, PCI_REVISION_ID
,&xgi_video_info
.revision_id
);
2976 pci_read_config_word(pdev
, PCI_COMMAND
, ®16
);
2977 XGIhw_ext
.jChipRevision
= xgi_video_info
.revision_id
;
2978 XGIvga_enabled
= reg16
& 0x01;
2980 xgi_video_info
.pcibus
= pdev
->bus
->number
;
2981 xgi_video_info
.pcislot
= PCI_SLOT(pdev
->devfn
);
2982 xgi_video_info
.pcifunc
= PCI_FUNC(pdev
->devfn
);
2983 xgi_video_info
.subsysvendor
= pdev
->subsystem_vendor
;
2984 xgi_video_info
.subsysdevice
= pdev
->subsystem_device
;
2986 xgi_video_info
.video_base
= pci_resource_start(pdev
, 0);
2987 xgi_video_info
.mmio_base
= pci_resource_start(pdev
, 1);
2988 XGIfb_mmio_size
= pci_resource_len(pdev
, 1);
2989 xgi_video_info
.vga_base
= pci_resource_start(pdev
, 2) + 0x30;
2990 XGIhw_ext
.pjIOAddress
= (PUCHAR
)xgi_video_info
.vga_base
;
2991 //XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30;
2992 printk("XGIfb: Relocate IO address: %lx [%08lx] \n", (unsigned long)pci_resource_start(pdev
, 2), XGI_Pr
.RelIO
);
2994 if (pci_enable_device(pdev
))
2997 XGIRegInit(&XGI_Pr
, (ULONG
)XGIhw_ext
.pjIOAddress
);
2999 outXGIIDXREG(XGISR
, IND_XGI_PASSWORD
, XGI_PASSWORD
);
3000 inXGIIDXREG(XGISR
, IND_XGI_PASSWORD
, reg1
);
3002 if(reg1
!= 0xa1) /*I/O error */
3004 printk("\nXGIfb: I/O error!!!");
3008 switch (xgi_video_info
.chip_id
) {
3009 case PCI_DEVICE_ID_XG_20
:
3010 orXGIIDXREG(XGICR
, Index_CR_GPIO_Reg3
, GPIOG_EN
);
3011 inXGIIDXREG(XGICR
, Index_CR_GPIO_Reg1
, CR48
);
3012 if (CR48
&GPIOG_READ
)
3013 xgi_video_info
.chip
= XG21
;
3015 xgi_video_info
.chip
= XG20
;
3016 XGIfb_hwcursor_size
= HW_CURSOR_AREA_SIZE_315
* 2;
3017 XGIfb_CRT2_write_enable
= IND_XGI_CRT2_WRITE_ENABLE_315
;
3019 case PCI_DEVICE_ID_XG_40
:
3020 xgi_video_info
.chip
= XG40
;
3021 XGIfb_hwcursor_size
= HW_CURSOR_AREA_SIZE_315
* 2;
3022 XGIfb_CRT2_write_enable
= IND_XGI_CRT2_WRITE_ENABLE_315
;
3024 case PCI_DEVICE_ID_XG_41
:
3025 xgi_video_info
.chip
= XG41
;
3026 XGIfb_hwcursor_size
= HW_CURSOR_AREA_SIZE_315
* 2;
3027 XGIfb_CRT2_write_enable
= IND_XGI_CRT2_WRITE_ENABLE_315
;
3029 case PCI_DEVICE_ID_XG_42
:
3030 xgi_video_info
.chip
= XG42
;
3031 XGIfb_hwcursor_size
= HW_CURSOR_AREA_SIZE_315
* 2;
3032 XGIfb_CRT2_write_enable
= IND_XGI_CRT2_WRITE_ENABLE_315
;
3034 case PCI_DEVICE_ID_XG_27
:
3035 xgi_video_info
.chip
= XG27
;
3036 XGIfb_hwcursor_size
= HW_CURSOR_AREA_SIZE_315
* 2;
3037 XGIfb_CRT2_write_enable
= IND_XGI_CRT2_WRITE_ENABLE_315
;
3043 printk("XGIfb:chipid = %x\n",xgi_video_info
.chip
);
3044 XGIhw_ext
.jChipType
= xgi_video_info
.chip
;
3046 switch (xgi_video_info
.chip
) {
3054 XGIhw_ext
.bIntegratedMMEnabled
= TRUE
;
3062 XGIhw_ext
.pDevice
= NULL
;
3063 if ((xgi_video_info
.chip
== XG21
) || (XGIfb_userom
))
3065 XGIhw_ext
.pjVirtualRomBase
= attempt_map_rom(pdev
, VBIOS_BUF
);
3067 if(XGIhw_ext
.pjVirtualRomBase
)
3068 printk(KERN_INFO
"XGIfb: Video ROM found and mapped to %p\n",XGIhw_ext
.pjVirtualRomBase
);
3070 printk(KERN_INFO
"XGIfb: Video ROM not found\n");
3072 XGIhw_ext
.pjVirtualRomBase
= NULL
;
3073 printk(KERN_INFO
"XGIfb: Video ROM usage disabled\n");
3075 XGIhw_ext
.pjCustomizedROMImage
= NULL
;
3076 XGIhw_ext
.bSkipDramSizing
= 0;
3077 XGIhw_ext
.pQueryVGAConfigSpace
= &XGIfb_query_VGA_config_space
;
3078 // XGIhw_ext.pQueryNorthBridgeSpace = &XGIfb_query_north_bridge_space;
3079 strcpy(XGIhw_ext
.szVBIOSVer
, "0.84");
3082 XGIhw_ext
.pSR
= vmalloc(sizeof(XGI_DSReg
) * SR_BUFFER_SIZE
);
3083 if (XGIhw_ext
.pSR
== NULL
)
3085 printk(KERN_ERR
"XGIfb: Fatal error: Allocating SRReg space failed.\n");
3088 XGIhw_ext
.pSR
[0].jIdx
= XGIhw_ext
.pSR
[0].jVal
= 0xFF;
3090 XGIhw_ext
.pCR
= vmalloc(sizeof(XGI_DSReg
) * CR_BUFFER_SIZE
);
3091 if (XGIhw_ext
.pCR
== NULL
)
3093 vfree(XGIhw_ext
.pSR
);
3094 printk(KERN_ERR
"XGIfb: Fatal error: Allocating CRReg space failed.\n");
3097 XGIhw_ext
.pCR
[0].jIdx
= XGIhw_ext
.pCR
[0].jVal
= 0xFF;
3102 if (!XGIvga_enabled
)
3104 /* Mapping Max FB Size for 315 Init */
3105 XGIhw_ext
.pjVideoMemoryAddress
= ioremap(xgi_video_info
.video_base
, 0x10000000);
3106 if((xgifb_mode_idx
< 0) || ((XGIbios_mode
[xgifb_mode_idx
].mode_no
) != 0xFF))
3109 printk("XGIfb: XGIInit() ...");
3110 /* XGIInitNewt for LINUXBIOS only */
3111 if(XGIInitNew(&XGIhw_ext
))
3121 outXGIIDXREG(XGISR
, IND_XGI_PASSWORD
, XGI_PASSWORD
);
3129 XGIhw_ext
.pjVideoMemoryAddress
= ioremap(xgi_video_info
.video_base
, 0x10000000);
3130 if((xgifb_mode_idx
< 0) || ((XGIbios_mode
[xgifb_mode_idx
].mode_no
) != 0xFF))
3133 outXGIIDXREG(XGISR
, IND_XGI_PASSWORD
, XGI_PASSWORD
);
3135 // yilin Because no VBIOS DRAM Sizing, Dram size will error.
3136 // Set SR13 ,14 temporarily for UDtech
3137 outXGIIDXREG(XGISR
, 0x13, 0x45);
3138 outXGIIDXREG(XGISR
, 0x14, 0x51);
3144 if (XGIfb_get_dram_size())
3146 vfree(XGIhw_ext
.pSR
);
3147 vfree(XGIhw_ext
.pCR
);
3148 printk(KERN_INFO
"XGIfb: Fatal error: Unable to determine RAM size.\n");
3154 if((xgifb_mode_idx
< 0) || ((XGIbios_mode
[xgifb_mode_idx
].mode_no
) != 0xFF))
3156 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
3157 orXGIIDXREG(XGISR
, IND_XGI_PCI_ADDRESS_SET
, (XGI_PCI_ADDR_ENABLE
| XGI_MEM_MAP_IO_ENABLE
));
3158 /* Enable 2D accelerator engine */
3159 orXGIIDXREG(XGISR
, IND_XGI_MODULE_ENABLE
, XGI_ENABLE_2D
);
3162 XGIhw_ext
.ulVideoMemorySize
= xgi_video_info
.video_size
;
3164 if (!request_mem_region(xgi_video_info
.video_base
, xgi_video_info
.video_size
, "XGIfb FB"))
3165 { printk("unable request memory size %x",xgi_video_info
.video_size
);
3166 printk(KERN_ERR
"XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
3167 printk(KERN_ERR
"XGIfb: Is there another framebuffer driver active?\n");
3168 vfree(XGIhw_ext
.pSR
);
3169 vfree(XGIhw_ext
.pCR
);
3173 if (!request_mem_region(xgi_video_info
.mmio_base
, XGIfb_mmio_size
, "XGIfb MMIO"))
3175 printk(KERN_ERR
"XGIfb: Fatal error: Unable to reserve MMIO region\n");
3176 release_mem_region(xgi_video_info
.video_base
, xgi_video_info
.video_size
);
3177 vfree(XGIhw_ext
.pSR
);
3178 vfree(XGIhw_ext
.pCR
);
3182 xgi_video_info
.video_vbase
= XGIhw_ext
.pjVideoMemoryAddress
=
3183 ioremap(xgi_video_info
.video_base
, xgi_video_info
.video_size
);
3184 xgi_video_info
.mmio_vbase
= ioremap(xgi_video_info
.mmio_base
, XGIfb_mmio_size
);
3186 printk(KERN_INFO
"XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
3187 xgi_video_info
.video_base
, xgi_video_info
.video_vbase
,xgi_video_info
.video_size
/ 1024);
3189 printk(KERN_INFO
"XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
3190 xgi_video_info
.mmio_base
, xgi_video_info
.mmio_vbase
,XGIfb_mmio_size
/ 1024);
3191 printk("XGIfb: XGIInitNew() ...");
3192 if(XGIInitNew(&XGIhw_ext
))
3201 if(XGIfb_heap_init())
3203 printk(KERN_WARNING
"XGIfb: Failed to initialize offscreen memory heap\n");
3207 xgi_video_info
.mtrr
= (unsigned int) 0;
3209 if((xgifb_mode_idx
< 0) || ((XGIbios_mode
[xgifb_mode_idx
].mode_no
) != 0xFF))
3211 xgi_video_info
.hasVB
= HASVB_NONE
;
3212 if((xgi_video_info
.chip
== XG20
)||(xgi_video_info
.chip
== XG27
))
3213 xgi_video_info
.hasVB
= HASVB_NONE
;
3214 else if(xgi_video_info
.chip
== XG21
) {
3215 inXGIIDXREG(XGICR
,0x38,CR38
);
3216 if ((CR38
&0xE0) == 0xC0) {
3217 xgi_video_info
.disp_state
= DISPTYPE_LCD
;
3218 if (!XGIfb_GetXG21LVDSData()) {
3220 for (m
=0; m
< sizeof(XGI21_LCDCapList
)/sizeof(XGI21_LVDSCapStruct
); m
++) {
3221 if ((XGI21_LCDCapList
[m
].LVDSHDE
== XGIbios_mode
[xgifb_mode_idx
].xres
) &&
3222 (XGI21_LCDCapList
[m
].LVDSVDE
== XGIbios_mode
[xgifb_mode_idx
].yres
)) {
3223 XGINew_SetReg1( XGI_Pr
.P3d4
, 0x36, m
) ;
3228 else if ((CR38
&0xE0) == 0x60)
3229 xgi_video_info
.hasVB
= HASVB_CHRONTEL
;
3231 xgi_video_info
.hasVB
= HASVB_NONE
;
3234 XGIfb_get_VB_type();
3236 XGIhw_ext
.ujVBChipID
= VB_CHIP_UNKNOWN
;
3238 XGIhw_ext
.ulExternalChip
= 0;
3240 switch (xgi_video_info
.hasVB
) {
3242 inXGIIDXREG(XGIPART4
, 0x01, reg
);
3244 XGIhw_ext
.ujVBChipID
= VB_CHIP_302LV
;
3245 printk(KERN_INFO
"XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg
);
3246 } else if (reg
>= 0xD0) {
3247 XGIhw_ext
.ujVBChipID
= VB_CHIP_301LV
;
3248 printk(KERN_INFO
"XGIfb: XGI301LV bridge detected (revision 0x%02x)\n",reg
);
3250 /* else if (reg >= 0xB0) {
3251 XGIhw_ext.ujVBChipID = VB_CHIP_301B;
3252 inXGIIDXREG(XGIPART4,0x23,reg1);
3253 printk("XGIfb: XGI301B bridge detected\n");
3256 XGIhw_ext
.ujVBChipID
= VB_CHIP_301
;
3257 printk("XGIfb: XGI301 bridge detected\n");
3261 inXGIIDXREG(XGIPART4
, 0x01, reg
);
3263 XGIhw_ext
.ujVBChipID
= VB_CHIP_302LV
;
3264 printk(KERN_INFO
"XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg
);
3265 } else if (reg
>= 0xD0) {
3266 XGIhw_ext
.ujVBChipID
= VB_CHIP_301LV
;
3267 printk(KERN_INFO
"XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg
);
3268 } else if (reg
>= 0xB0) {
3269 inXGIIDXREG(XGIPART4
,0x23,reg1
);
3271 XGIhw_ext
.ujVBChipID
= VB_CHIP_302B
;
3274 XGIhw_ext
.ujVBChipID
= VB_CHIP_302
;
3275 printk(KERN_INFO
"XGIfb: XGI302 bridge detected\n");
3279 XGIhw_ext
.ulExternalChip
= 0x1;
3280 printk(KERN_INFO
"XGIfb: LVDS transmitter detected\n");
3282 case HASVB_TRUMPION
:
3283 XGIhw_ext
.ulExternalChip
= 0x2;
3284 printk(KERN_INFO
"XGIfb: Trumpion Zurac LVDS scaler detected\n");
3286 case HASVB_CHRONTEL
:
3287 XGIhw_ext
.ulExternalChip
= 0x4;
3288 printk(KERN_INFO
"XGIfb: Chrontel TV encoder detected\n");
3290 case HASVB_LVDS_CHRONTEL
:
3291 XGIhw_ext
.ulExternalChip
= 0x5;
3292 printk(KERN_INFO
"XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
3295 printk(KERN_INFO
"XGIfb: No or unknown bridge type detected\n");
3299 if (xgi_video_info
.hasVB
!= HASVB_NONE
) {
3303 if (xgi_video_info
.disp_state
& DISPTYPE_DISP2
) {
3305 xgi_video_info
.disp_state
|= DISPMODE_SINGLE
;
3307 xgi_video_info
.disp_state
|= (DISPMODE_MIRROR
| DISPTYPE_CRT1
);
3309 xgi_video_info
.disp_state
= DISPMODE_SINGLE
| DISPTYPE_CRT1
;
3312 if (xgi_video_info
.disp_state
& DISPTYPE_LCD
) {
3314 inXGIIDXREG(XGICR
, IND_XGI_LCD_PANEL
, reg
);
3316 XGIhw_ext
.ulCRT2LCDType
= XGI310paneltype
[reg
];
3320 XGIhw_ext
.ulCRT2LCDType
= LCD_320x480
;
3324 XGIfb_detectedpdc
= 0;
3326 XGIfb_detectedlcda
= 0xff;
3329 /* TW: Try to find about LCDA */
3331 if((XGIhw_ext
.ujVBChipID
== VB_CHIP_302B
) ||
3332 (XGIhw_ext
.ujVBChipID
== VB_CHIP_301LV
) ||
3333 (XGIhw_ext
.ujVBChipID
== VB_CHIP_302LV
))
3336 inXGIIDXREG(XGICR
,0x34,tmp
);
3339 // Currently on LCDA? (Some BIOSes leave CR38)
3340 inXGIIDXREG(XGICR
,0x38,tmp
);
3341 if((tmp
& 0x03) == 0x03)
3343 // XGI_Pr.XGI_UseLCDA = TRUE;
3346 // Currently on LCDA? (Some newer BIOSes set D0 in CR35)
3347 inXGIIDXREG(XGICR
,0x35,tmp
);
3350 // XGI_Pr.XGI_UseLCDA = TRUE;
3353 inXGIIDXREG(XGICR
,0x30,tmp
);
3356 inXGIIDXREG(XGIPART1
,0x13,tmp
);
3359 // XGI_Pr.XGI_UseLCDA = TRUE;
3371 if (xgifb_mode_idx
>= 0)
3372 xgifb_mode_idx
= XGIfb_validate_mode(xgifb_mode_idx
);
3374 if (xgifb_mode_idx
< 0) {
3375 switch (xgi_video_info
.disp_state
& DISPTYPE_DISP2
) {
3377 xgifb_mode_idx
= DEFAULT_LCDMODE
;
3378 if (xgi_video_info
.chip
== XG21
)
3380 xgifb_mode_idx
= XGIfb_GetXG21DefaultLVDSModeIdx();
3384 xgifb_mode_idx
= DEFAULT_TVMODE
;
3387 xgifb_mode_idx
= DEFAULT_MODE
;
3392 XGIfb_mode_no
= XGIbios_mode
[xgifb_mode_idx
].mode_no
;
3395 if( xgi_video_info
.refresh_rate
== 0)
3396 xgi_video_info
.refresh_rate
= 60; /*yilin set default refresh rate */
3397 if(XGIfb_search_refresh_rate(xgi_video_info
.refresh_rate
) == 0)
3399 XGIfb_rate_idx
= XGIbios_mode
[xgifb_mode_idx
].rate_idx
;
3400 xgi_video_info
.refresh_rate
= 60;
3403 xgi_video_info
.video_bpp
= XGIbios_mode
[xgifb_mode_idx
].bpp
;
3404 xgi_video_info
.video_vwidth
= xgi_video_info
.video_width
= XGIbios_mode
[xgifb_mode_idx
].xres
;
3405 xgi_video_info
.video_vheight
= xgi_video_info
.video_height
= XGIbios_mode
[xgifb_mode_idx
].yres
;
3406 xgi_video_info
.org_x
= xgi_video_info
.org_y
= 0;
3407 xgi_video_info
.video_linelength
= xgi_video_info
.video_width
* (xgi_video_info
.video_bpp
>> 3);
3408 switch(xgi_video_info
.video_bpp
) {
3410 xgi_video_info
.DstColor
= 0x0000;
3411 xgi_video_info
.XGI310_AccelDepth
= 0x00000000;
3412 xgi_video_info
.video_cmap_len
= 256;
3415 xgi_video_info
.DstColor
= 0x8000;
3416 xgi_video_info
.XGI310_AccelDepth
= 0x00010000;
3417 xgi_video_info
.video_cmap_len
= 16;
3420 xgi_video_info
.DstColor
= 0xC000;
3421 xgi_video_info
.XGI310_AccelDepth
= 0x00020000;
3422 xgi_video_info
.video_cmap_len
= 16;
3425 xgi_video_info
.video_cmap_len
= 16;
3426 printk(KERN_INFO
"XGIfb: Unsupported depth %d", xgi_video_info
.video_bpp
);
3432 printk(KERN_INFO
"XGIfb: Default mode is %dx%dx%d (%dHz)\n",
3433 xgi_video_info
.video_width
, xgi_video_info
.video_height
, xgi_video_info
.video_bpp
,
3434 xgi_video_info
.refresh_rate
);
3436 default_var
.xres
= default_var
.xres_virtual
= xgi_video_info
.video_width
;
3437 default_var
.yres
= default_var
.yres_virtual
= xgi_video_info
.video_height
;
3438 default_var
.bits_per_pixel
= xgi_video_info
.video_bpp
;
3440 XGIfb_bpp_to_var(&default_var
);
3442 default_var
.pixclock
= (u32
) (1000000000 /
3443 XGIfb_mode_rate_to_dclock(&XGI_Pr
, &XGIhw_ext
,
3444 XGIfb_mode_no
, XGIfb_rate_idx
));
3446 if(XGIfb_mode_rate_to_ddata(&XGI_Pr
, &XGIhw_ext
,
3447 XGIfb_mode_no
, XGIfb_rate_idx
,
3448 &default_var
.left_margin
, &default_var
.right_margin
,
3449 &default_var
.upper_margin
, &default_var
.lower_margin
,
3450 &default_var
.hsync_len
, &default_var
.vsync_len
,
3451 &default_var
.sync
, &default_var
.vmode
)) {
3453 if((default_var
.vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
3454 default_var
.yres
<<= 1;
3455 default_var
.yres_virtual
<<= 1;
3456 } else if((default_var
.vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
) {
3457 default_var
.pixclock
>>= 1;
3458 default_var
.yres
>>= 1;
3459 default_var
.yres_virtual
>>= 1;
3468 default_var
.yres_virtual
=
3469 xgi_video_info
.heapstart
/ (default_var
.xres
* (default_var
.bits_per_pixel
>> 3));
3470 if(default_var
.yres_virtual
<= default_var
.yres
) {
3471 default_var
.yres_virtual
= default_var
.yres
;
3478 xgi_video_info
.accel
= 0;
3480 xgi_video_info
.accel
= -1;
3481 default_var
.accel_flags
|= FB_ACCELF_TEXT
;
3485 fb_info
->flags
= FBINFO_FLAG_DEFAULT
;
3486 fb_info
->var
= default_var
;
3487 fb_info
->fix
= XGIfb_fix
;
3488 fb_info
->par
= &xgi_video_info
;
3489 fb_info
->screen_base
= xgi_video_info
.video_vbase
;
3490 fb_info
->fbops
= &XGIfb_ops
;
3491 XGIfb_get_fix(&fb_info
->fix
, -1, fb_info
);
3492 fb_info
->pseudo_palette
= pseudo_palette
;
3494 fb_alloc_cmap(&fb_info
->cmap
, 256 , 0);
3498 xgi_video_info
.mtrr
= mtrr_add((unsigned int) xgi_video_info
.video_base
,
3499 (unsigned int) xgi_video_info
.video_size
,
3500 MTRR_TYPE_WRCOMB
, 1);
3501 if(xgi_video_info
.mtrr
) {
3502 printk(KERN_INFO
"XGIfb: Added MTRRs\n");
3506 if(register_framebuffer(fb_info
) < 0)
3511 XGIfb_registered
= 1;
3513 printk(KERN_INFO
"XGIfb: Installed XGIFB_GET_INFO ioctl (%x)\n", XGIFB_GET_INFO
);
3515 /* printk(KERN_INFO "XGIfb: 2D acceleration is %s, scrolling mode %s\n",
3516 XGIfb_accel ? "enabled" : "disabled",
3517 XGIfb_ypan ? "ypan" : "redraw");
3519 printk(KERN_INFO
"fb%d: %s frame buffer device, Version %d.%d.%02d\n",
3520 fb_info
->node
, myid
, VER_MAJOR
, VER_MINOR
, VER_LEVEL
);
3531 /*****************************************************/
3532 /* PCI DEVICE HANDLING */
3533 /*****************************************************/
3535 static void __devexit
xgifb_remove(struct pci_dev
*pdev
)
3537 /* Unregister the framebuffer */
3538 // if(xgi_video_info.registered) {
3539 unregister_framebuffer(fb_info
);
3540 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
3541 framebuffer_release(fb_info
);
3547 pci_set_drvdata(pdev
, NULL
);
3551 static struct pci_driver xgifb_driver
= {
3553 .id_table
= xgifb_pci_table
,
3554 .probe
= xgifb_probe
,
3555 .remove
= __devexit_p(xgifb_remove
)
3558 XGIINITSTATIC
int __init
xgifb_init(void)
3560 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
3562 char *option
= NULL
;
3564 if (fb_get_options("xgifb", &option
))
3566 XGIfb_setup(option
);
3569 return(pci_register_driver(&xgifb_driver
));
3572 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
3574 module_init(xgifb_init
);
3578 /*****************************************************/
3580 /*****************************************************/
3584 static char *mode
= NULL
;
3585 static int vesa
= 0;
3586 static unsigned int rate
= 0;
3587 static unsigned int crt1off
= 1;
3588 static unsigned int mem
= 0;
3589 static char *forcecrt2type
= NULL
;
3590 static int forcecrt1
= -1;
3591 static int pdc
= -1;
3592 static int pdc1
= -1;
3593 static int noaccel
= -1;
3594 static int noypan
= -1;
3595 static int nomax
= -1;
3596 static int userom
= -1;
3597 static int useoem
= -1;
3598 static char *tvstandard
= NULL
;
3599 static int nocrt2rate
= 0;
3600 static int scalelcd
= -1;
3601 static char *specialtiming
= NULL
;
3602 static int lvdshl
= -1;
3603 static int tvxposoffset
= 0, tvyposoffset
= 0;
3604 #if !defined(__i386__) && !defined(__x86_64__)
3605 static int resetcard
= 0;
3606 static int videoram
= 0;
3609 MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
3610 MODULE_LICENSE("GPL");
3611 MODULE_AUTHOR("XGITECH , Others");
3615 module_param(mem
, int, 0);
3616 module_param(noaccel
, int, 0);
3617 module_param(noypan
, int, 0);
3618 module_param(nomax
, int, 0);
3619 module_param(userom
, int, 0);
3620 module_param(useoem
, int, 0);
3621 module_param(mode
, charp
, 0);
3622 module_param(vesa
, int, 0);
3623 module_param(rate
, int, 0);
3624 module_param(forcecrt1
, int, 0);
3625 module_param(forcecrt2type
, charp
, 0);
3626 module_param(scalelcd
, int, 0);
3627 module_param(pdc
, int, 0);
3628 module_param(pdc1
, int, 0);
3629 module_param(specialtiming
, charp
, 0);
3630 module_param(lvdshl
, int, 0);
3631 module_param(tvstandard
, charp
, 0);
3632 module_param(tvxposoffset
, int, 0);
3633 module_param(tvyposoffset
, int, 0);
3634 module_param(filter
, int, 0);
3635 module_param(nocrt2rate
, int, 0);
3636 #if !defined(__i386__) && !defined(__x86_64__)
3637 module_param(resetcard
, int, 0);
3638 module_param(videoram
, int, 0);
3642 MODULE_PARM_DESC(mem
,
3643 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
3644 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
3645 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
3646 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
3647 "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
3648 "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
3649 "for XFree86 4.x/X.org 6.7 and later.\n");
3651 MODULE_PARM_DESC(noaccel
,
3652 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
3655 MODULE_PARM_DESC(noypan
,
3656 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
3657 "will be performed by redrawing the screen. (default: 0)\n");
3659 MODULE_PARM_DESC(nomax
,
3660 "\nIf y-panning is enabled, xgifb will by default use the entire available video\n"
3661 "memory for the virtual screen in order to optimize scrolling performance. If\n"
3662 "this is set to anything other than 0, xgifb will not do this and thereby \n"
3663 "enable the user to positively specify a virtual Y size of the screen using\n"
3664 "fbset. (default: 0)\n");
3668 MODULE_PARM_DESC(mode
,
3669 "\nSelects the desired default display mode in the format XxYxDepth,\n"
3670 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
3671 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
3672 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
3674 MODULE_PARM_DESC(vesa
,
3675 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
3676 "0x117 (default: 0x0103)\n");
3679 MODULE_PARM_DESC(rate
,
3680 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
3681 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
3682 "will be ignored (default: 60)\n");
3684 MODULE_PARM_DESC(forcecrt1
,
3685 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
3686 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
3687 "0=CRT1 OFF) (default: [autodetected])\n");
3689 MODULE_PARM_DESC(forcecrt2type
,
3690 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
3691 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
3692 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
3693 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
3694 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
3695 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
3696 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
3697 "depends on the very hardware in use. (default: [autodetected])\n");
3699 MODULE_PARM_DESC(scalelcd
,
3700 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
3701 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
3702 "show black bars around the image, TMDS panels will probably do the scaling\n"
3703 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
3705 MODULE_PARM_DESC(pdc
,
3706 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
3707 "should detect this correctly in most cases; however, sometimes this is not\n"
3708 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
3709 "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
3710 "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
3711 "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
3713 MODULE_PARM_DESC(pdc1
,
3714 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
3715 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
3716 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
3717 "implemented yet.\n");
3719 MODULE_PARM_DESC(specialtiming
,
3720 "\nPlease refer to documentation for more information on this option.\n");
3722 MODULE_PARM_DESC(lvdshl
,
3723 "\nPlease refer to documentation for more information on this option.\n");
3725 MODULE_PARM_DESC(tvstandard
,
3726 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
3727 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
3729 MODULE_PARM_DESC(tvxposoffset
,
3730 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
3733 MODULE_PARM_DESC(tvyposoffset
,
3734 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
3737 MODULE_PARM_DESC(filter
,
3738 "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
3739 "(Possible values 0-7, default: [no filter])\n");
3741 MODULE_PARM_DESC(nocrt2rate
,
3742 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
3743 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
3748 int __init
xgifb_init_module(void)
3750 printk("\nXGIfb_init_module");
3752 XGIfb_search_mode(mode
);
3753 else if (vesa
!= -1)
3754 XGIfb_search_vesamode(vesa
);
3756 return(xgifb_init());
3759 static void __exit
xgifb_remove_module(void)
3761 pci_unregister_driver(&xgifb_driver
);
3762 printk(KERN_DEBUG
"xgifb: Module unloaded\n");
3765 module_init(xgifb_init_module
);
3766 module_exit(xgifb_remove_module
);
3768 #endif /* /MODULE */
3770 EXPORT_SYMBOL(XGI_malloc
);
3771 EXPORT_SYMBOL(XGI_free
);