2 * XG20, XG21, XG40, XG42 frame buffer device
3 * for Linux kernels 2.5.x, 2.6.x
4 * Base on TW's sis fbdev code.
7 //#include <linux/config.h>
8 #include <linux/version.h>
9 #include <linux/module.h>
10 #include <linux/moduleparam.h>
11 #include <linux/kernel.h>
12 #include <linux/spinlock.h>
13 #include <linux/errno.h>
14 #include <linux/string.h>
16 #include <linux/tty.h>
17 #include <linux/slab.h>
18 #include <linux/delay.h>
20 #include <linux/console.h>
21 #include <linux/selection.h>
22 #include <linux/ioport.h>
23 #include <linux/init.h>
24 #include <linux/pci.h>
25 #include <linux/vmalloc.h>
26 #include <linux/vt_kern.h>
27 #include <linux/capability.h>
29 #include <linux/types.h>
30 #include <linux/proc_fs.h>
48 #define Index_CR_GPIO_Reg1 0x48
49 #define Index_CR_GPIO_Reg2 0x49
50 #define Index_CR_GPIO_Reg3 0x4a
52 #define GPIOG_EN (1<<6)
53 #define GPIOG_WRITE (1<<6)
54 #define GPIOG_READ (1<<1)
55 int XGIfb_GetXG21DefaultLVDSModeIdx(void);
57 /* -------------------- Macro definitions ---------------------------- */
62 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
64 #define DPRINTK(fmt, args...)
68 static void dumpVGAReg(void)
72 outXGIIDXREG(XGISR, 0x05, 0x86);
74 outXGIIDXREG(XGISR, 0x08, 0x4f);
75 outXGIIDXREG(XGISR, 0x0f, 0x20);
76 outXGIIDXREG(XGISR, 0x11, 0x4f);
77 outXGIIDXREG(XGISR, 0x13, 0x45);
78 outXGIIDXREG(XGISR, 0x14, 0x51);
79 outXGIIDXREG(XGISR, 0x1e, 0x41);
80 outXGIIDXREG(XGISR, 0x1f, 0x0);
81 outXGIIDXREG(XGISR, 0x20, 0xa1);
82 outXGIIDXREG(XGISR, 0x22, 0xfb);
83 outXGIIDXREG(XGISR, 0x26, 0x22);
84 outXGIIDXREG(XGISR, 0x3e, 0x07);
87 //outXGIIDXREG(XGICR, 0x19, 0x00);
88 //outXGIIDXREG(XGICR, 0x1a, 0x3C);
89 //outXGIIDXREG(XGICR, 0x22, 0xff);
90 //outXGIIDXREG(XGICR, 0x3D, 0x10);
92 //outXGIIDXREG(XGICR, 0x4a, 0xf3);
94 //outXGIIDXREG(XGICR, 0x57, 0x0);
95 //outXGIIDXREG(XGICR, 0x7a, 0x2c);
97 //outXGIIDXREG(XGICR, 0x82, 0xcc);
98 //outXGIIDXREG(XGICR, 0x8c, 0x0);
100 outXGIIDXREG(XGICR, 0x99, 0x1);
101 outXGIIDXREG(XGICR, 0x41, 0x40);
104 for(i=0; i < 0x4f; i++)
106 inXGIIDXREG(XGISR, i, reg);
107 printk("\no 3c4 %x",i);
108 printk("\ni 3c5 => %x",reg);
111 for(i=0; i < 0xF0; i++)
113 inXGIIDXREG(XGICR, i, reg);
114 printk("\no 3d4 %x",i);
115 printk("\ni 3d5 => %x",reg);
119 outXGIIDXREG(XGIPART1,0x2F,1);
120 for(i=1; i < 0x50; i++)
122 inXGIIDXREG(XGIPART1, i, reg);
123 printk("\no d004 %x",i);
124 printk("\ni d005 => %x",reg);
127 for(i=0; i < 0x50; i++)
129 inXGIIDXREG(XGIPART2, i, reg);
130 printk("\no d010 %x",i);
131 printk("\ni d011 => %x",reg);
133 for(i=0; i < 0x50; i++)
135 inXGIIDXREG(XGIPART3, i, reg);
136 printk("\no d012 %x",i);
137 printk("\ni d013 => %x",reg);
139 for(i=0; i < 0x50; i++)
141 inXGIIDXREG(XGIPART4, i, reg);
142 printk("\no d014 %x",i);
143 printk("\ni d015 => %x",reg);
148 static inline void dumpVGAReg(void) {}
151 /* data for XGI components */
152 struct video_info xgi_video_info;
158 #define DEBUGPRN(x) printk(KERN_INFO x "\n");
162 /* --------------- Hardware Access Routines -------------------------- */
165 XGIfb_mode_rate_to_dclock(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension,
166 unsigned char modeno, unsigned char rateindex)
168 USHORT ModeNo = modeno;
169 USHORT ModeIdIndex = 0, ClockIndex = 0;
170 USHORT RefreshRateTableIndex = 0;
174 XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
175 InitTo330Pointer( HwDeviceExtension->jChipType, XGI_Pr ) ;
177 RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, XGI_Pr ) ;
180 temp = XGI_SearchModeID( ModeNo , &ModeIdIndex, XGI_Pr ) ;
182 printk(KERN_ERR "Could not find mode %x\n", ModeNo);
186 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
187 RefreshRateTableIndex += (rateindex - 1);
190 ClockIndex = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
191 if(HwDeviceExtension->jChipType < XGI_315H) {
194 Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000 ;
200 XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension,
201 unsigned char modeno, unsigned char rateindex,
202 u32 *left_margin, u32 *right_margin,
203 u32 *upper_margin, u32 *lower_margin,
204 u32 *hsync_len, u32 *vsync_len,
205 u32 *sync, u32 *vmode)
207 USHORT ModeNo = modeno;
208 USHORT ModeIdIndex = 0, index = 0;
209 USHORT RefreshRateTableIndex = 0;
211 unsigned short VRE, VBE, VRS, VBS, VDE, VT;
212 unsigned short HRE, HBE, HRS, HBS, HDE, HT;
213 unsigned char sr_data, cr_data, cr_data2;
214 unsigned long cr_data3;
215 int A, B, C, D, E, F, temp, j;
216 XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
217 InitTo330Pointer( HwDeviceExtension->jChipType, XGI_Pr ) ;
218 RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, XGI_Pr ) ;
220 temp = XGI_SearchModeID( ModeNo, &ModeIdIndex, XGI_Pr);
223 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
224 RefreshRateTableIndex += (rateindex - 1);
226 index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
228 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[5];
230 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[0];
232 /* Horizontal total */
233 HT = (cr_data & 0xff) |
234 ((unsigned short) (sr_data & 0x03) << 8);
237 /*cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
239 Horizontal display enable end
240 HDE = (cr_data & 0xff) |
241 ((unsigned short) (sr_data & 0x0C) << 6);*/
242 HDE = (XGI_Pr->RefIndex[RefreshRateTableIndex].XRes >> 3) -1;
245 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[3];
247 /* Horizontal retrace (=sync) start */
248 HRS = (cr_data & 0xff) |
249 ((unsigned short) (sr_data & 0xC0) << 2);
252 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
254 /* Horizontal blank start */
255 HBS = (cr_data & 0xff) |
256 ((unsigned short) (sr_data & 0x30) << 4);
258 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[6];
260 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[2];
262 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[4];
264 /* Horizontal blank end */
265 HBE = (cr_data & 0x1f) |
266 ((unsigned short) (cr_data2 & 0x80) >> 2) |
267 ((unsigned short) (sr_data & 0x03) << 6);
269 /* Horizontal retrace (=sync) end */
270 HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
272 temp = HBE - ((E - 1) & 255);
273 B = (temp > 0) ? temp : (temp + 256);
275 temp = HRE - ((E + F + 3) & 63);
276 C = (temp > 0) ? temp : (temp + 64);
280 *left_margin = D * 8;
281 *right_margin = F * 8;
284 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[14];
286 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[8];
288 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[9];
291 VT = (cr_data & 0xFF) |
292 ((unsigned short) (cr_data2 & 0x01) << 8) |
293 ((unsigned short)(cr_data2 & 0x20) << 4) |
294 ((unsigned short) (sr_data & 0x01) << 10);
297 //cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
299 /* Vertical display enable end */
300 /* VDE = (cr_data & 0xff) |
301 ((unsigned short) (cr_data2 & 0x02) << 7) |
302 ((unsigned short) (cr_data2 & 0x40) << 3) |
303 ((unsigned short) (sr_data & 0x02) << 9); */
304 VDE = XGI_Pr->RefIndex[RefreshRateTableIndex].YRes -1;
307 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
309 /* Vertical retrace (=sync) start */
310 VRS = (cr_data & 0xff) |
311 ((unsigned short) (cr_data2 & 0x04) << 6) |
312 ((unsigned short) (cr_data2 & 0x80) << 2) |
313 ((unsigned short) (sr_data & 0x08) << 7);
316 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[12];
318 cr_data3 = (XGI_Pr->XGINEWUB_CRT1Table[index].CR[14] & 0x80) << 5;
320 /* Vertical blank start */
321 VBS = (cr_data & 0xff) |
322 ((unsigned short) (cr_data2 & 0x08) << 5) |
323 ((unsigned short) (cr_data3 & 0x20) << 4) |
324 ((unsigned short) (sr_data & 0x04) << 8);
326 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[13];
328 /* Vertical blank end */
329 VBE = (cr_data & 0xff) |
330 ((unsigned short) (sr_data & 0x10) << 4);
331 temp = VBE - ((E - 1) & 511);
332 B = (temp > 0) ? temp : (temp + 512);
334 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[11];
336 /* Vertical retrace (=sync) end */
337 VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
338 temp = VRE - ((E + F - 1) & 31);
339 C = (temp > 0) ? temp : (temp + 32);
347 if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
348 *sync &= ~FB_SYNC_VERT_HIGH_ACT;
350 *sync |= FB_SYNC_VERT_HIGH_ACT;
352 if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
353 *sync &= ~FB_SYNC_HOR_HIGH_ACT;
355 *sync |= FB_SYNC_HOR_HIGH_ACT;
357 *vmode = FB_VMODE_NONINTERLACED;
358 if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
359 *vmode = FB_VMODE_INTERLACED;
362 while(XGI_Pr->EModeIDTable[j].Ext_ModeID != 0xff) {
363 if(XGI_Pr->EModeIDTable[j].Ext_ModeID ==
364 XGI_Pr->RefIndex[RefreshRateTableIndex].ModeID) {
365 if(XGI_Pr->EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
366 *vmode = FB_VMODE_DOUBLE;
380 void XGIRegInit(VB_DEVICE_INFO *XGI_Pr, ULONG BaseAddr)
382 XGI_Pr->RelIO = BaseAddr;
383 XGI_Pr->P3c4 = BaseAddr + 0x14;
384 XGI_Pr->P3d4 = BaseAddr + 0x24;
385 XGI_Pr->P3c0 = BaseAddr + 0x10;
386 XGI_Pr->P3ce = BaseAddr + 0x1e;
387 XGI_Pr->P3c2 = BaseAddr + 0x12;
388 XGI_Pr->P3ca = BaseAddr + 0x1a;
389 XGI_Pr->P3c6 = BaseAddr + 0x16;
390 XGI_Pr->P3c7 = BaseAddr + 0x17;
391 XGI_Pr->P3c8 = BaseAddr + 0x18;
392 XGI_Pr->P3c9 = BaseAddr + 0x19;
393 XGI_Pr->P3da = BaseAddr + 0x2A;
394 XGI_Pr->Part1Port = BaseAddr + XGI_CRT2_PORT_04; /* Digital video interface registers (LCD) */
395 XGI_Pr->Part2Port = BaseAddr + XGI_CRT2_PORT_10; /* 301 TV Encoder registers */
396 XGI_Pr->Part3Port = BaseAddr + XGI_CRT2_PORT_12; /* 301 Macrovision registers */
397 XGI_Pr->Part4Port = BaseAddr + XGI_CRT2_PORT_14; /* 301 VGA2 (and LCD) registers */
398 XGI_Pr->Part5Port = BaseAddr + XGI_CRT2_PORT_14+2; /* 301 palette address port registers */
403 void XGIfb_set_reg4(u16 port, unsigned long data)
405 outl((u32) (data & 0xffffffff), port);
408 u32 XGIfb_get_reg3(u16 port)
416 /* ------------ Interface for init & mode switching code ------------- */
419 XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
420 unsigned long offset, unsigned long set, unsigned long *value)
422 static struct pci_dev *pdev = NULL;
423 static unsigned char init = 0, valid_pdev = 0;
426 DPRINTK("XGIfb: Get VGA offset 0x%lx\n", offset);
428 DPRINTK("XGIfb: Set offset 0x%lx to 0x%lx\n", offset, *value);
432 pdev = pci_get_device(PCI_VENDOR_ID_XG, xgi_video_info.chip_id, pdev);
440 printk(KERN_DEBUG "XGIfb: Can't find XGI %d VGA device.\n",
441 xgi_video_info.chip_id);
446 pci_read_config_dword(pdev, offset, (u32 *)value);
448 pci_write_config_dword(pdev, offset, (u32)(*value));
453 /*BOOLEAN XGIfb_query_north_bridge_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
454 unsigned long offset, unsigned long set, unsigned long *value)
456 static struct pci_dev *pdev = NULL;
457 static unsigned char init = 0, valid_pdev = 0;
462 switch (xgi_video_info.chip) {
464 nbridge_id = PCI_DEVICE_ID_XG_540;
467 nbridge_id = PCI_DEVICE_ID_XG_630;
470 nbridge_id = PCI_DEVICE_ID_XG_730;
473 nbridge_id = PCI_DEVICE_ID_XG_550;
476 nbridge_id = PCI_DEVICE_ID_XG_650;
479 nbridge_id = PCI_DEVICE_ID_XG_740;
486 pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridge_id, pdev);
492 printk(KERN_DEBUG "XGIfb: Can't find XGI %d North Bridge device.\n",
498 pci_read_config_dword(pdev, offset, (u32 *)value);
500 pci_write_config_dword(pdev, offset, (u32)(*value));
505 /* ------------------ Internal helper routines ----------------- */
507 static void XGIfb_search_mode(const char *name)
512 printk(KERN_ERR "XGIfb: Internal error, using default mode.\n");
513 xgifb_mode_idx = DEFAULT_MODE;
514 if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
516 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
522 if (!strcmp(name, XGIbios_mode[MODE_INDEX_NONE].name)) {
523 printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
524 xgifb_mode_idx = DEFAULT_MODE;
525 if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
527 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
532 while(XGIbios_mode[i].mode_no != 0) {
533 l = min(strlen(name), strlen(XGIbios_mode[i].name));
534 if (!strncmp(name, XGIbios_mode[i].name, l)) {
541 if(!j) printk(KERN_INFO "XGIfb: Invalid mode '%s'\n", name);
544 static void XGIfb_search_vesamode(unsigned int vesamode)
550 printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
551 xgifb_mode_idx = DEFAULT_MODE;
552 if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
554 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
559 vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
561 while(XGIbios_mode[i].mode_no != 0) {
562 if( (XGIbios_mode[i].vesa_mode_no_1 == vesamode) ||
563 (XGIbios_mode[i].vesa_mode_no_2 == vesamode) ) {
570 if(!j) printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode);
573 int XGIfb_GetXG21LVDSData(void)
576 unsigned char *pData;
579 inXGIIDXREG(XGISR,0x1e,tmp);
580 outXGIIDXREG(XGISR, 0x1e, tmp|4);
582 pData = xgi_video_info.mmio_vbase+0x20000;
583 if ((pData[0x0]==0x55) && (pData[0x1]==0xAA) && (pData[0x65] & 0x1))
585 i = pData[ 0x316 ] | ( pData[ 0x317 ] << 8 );
594 XGI21_LCDCapList[k].LVDS_Capability = pData[ i ] | ( pData[ i + 1 ] << 8 );
595 XGI21_LCDCapList[k].LVDSHT = pData[ i + 2 ] | ( pData[ i + 3 ] << 8 ) ;
596 XGI21_LCDCapList[k].LVDSVT = pData[ i + 4 ] | ( pData[ i + 5 ] << 8 );
597 XGI21_LCDCapList[k].LVDSHDE = pData[ i + 6 ] | ( pData[ i + 7 ] << 8 );
598 XGI21_LCDCapList[k].LVDSVDE = pData[ i + 8 ] | ( pData[ i + 9 ] << 8 );
599 XGI21_LCDCapList[k].LVDSHFP = pData[ i + 10 ] | ( pData[ i + 11 ] << 8 );
600 XGI21_LCDCapList[k].LVDSVFP = pData[ i + 12 ] | ( pData[ i + 13 ] << 8 );
601 XGI21_LCDCapList[k].LVDSHSYNC = pData[ i + 14 ] | ( pData[ i + 15 ] << 8 );
602 XGI21_LCDCapList[k].LVDSVSYNC = pData[ i + 16 ] | ( pData[ i + 17 ] << 8 );
603 XGI21_LCDCapList[k].VCLKData1 = pData[ i + 18 ] ;
604 XGI21_LCDCapList[k].VCLKData2 = pData[ i + 19 ] ;
605 XGI21_LCDCapList[k].PSC_S1 = pData[ i + 20 ] ;
606 XGI21_LCDCapList[k].PSC_S2 = pData[ i + 21 ] ;
607 XGI21_LCDCapList[k].PSC_S3 = pData[ i + 22 ] ;
608 XGI21_LCDCapList[k].PSC_S4 = pData[ i + 23 ] ;
609 XGI21_LCDCapList[k].PSC_S5 = pData[ i + 24 ] ;
613 } while ( (j>0) && ( k < (sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct)) ) );
619 int XGIfb_GetXG21DefaultLVDSModeIdx(void)
623 int XGIfb_mode_idx = 0;
626 while( (XGIbios_mode[XGIfb_mode_idx].mode_no != 0) &&
627 (XGIbios_mode[XGIfb_mode_idx].xres <= XGI21_LCDCapList[0].LVDSHDE) )
629 if( (XGIbios_mode[XGIfb_mode_idx].xres == XGI21_LCDCapList[0].LVDSHDE) &&
630 (XGIbios_mode[XGIfb_mode_idx].yres == XGI21_LCDCapList[0].LVDSVDE) &&
631 (XGIbios_mode[XGIfb_mode_idx].bpp == 8))
633 XGIfb_mode_no = XGIbios_mode[XGIfb_mode_idx].mode_no;
642 return (XGIfb_mode_idx);
646 static int XGIfb_validate_mode(int myindex)
650 if (xgi_video_info.chip == XG21)
652 if ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD)
654 xres = XGI21_LCDCapList[0].LVDSHDE;
655 yres = XGI21_LCDCapList[0].LVDSVDE;
656 if(XGIbios_mode[myindex].xres > xres)
658 if(XGIbios_mode[myindex].yres > yres)
660 if ((XGIbios_mode[myindex].xres < xres) && (XGIbios_mode[myindex].yres < yres) )
662 if (XGIbios_mode[myindex].bpp > 8)
671 /* FIXME: for now, all is valid on XG27 */
672 if (xgi_video_info.chip == XG27)
675 if(!(XGIbios_mode[myindex].chipset & MD_XGI315))
678 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
680 switch (XGIhw_ext.ulCRT2LCDType) {
682 xres = 640; yres = 480; break;
684 xres = 800; yres = 600; break;
686 xres = 1024; yres = 600; break;
688 xres = 1024; yres = 768; break;
690 xres = 1152; yres = 768; break;
692 xres = 1280; yres = 960; break;
694 xres = 1280; yres = 768; break;
696 xres = 1280; yres = 1024; break;
698 xres = 1400; yres = 1050; break;
700 xres = 1600; yres = 1200; break;
701 // case LCD_320x480: // TW: FSTN
702 // xres = 320; yres = 480; break;
704 xres = 0; yres = 0; break;
706 if(XGIbios_mode[myindex].xres > xres) {
709 if(XGIbios_mode[myindex].yres > yres) {
712 if((XGIhw_ext.ulExternalChip == 0x01) || // LVDS
713 (XGIhw_ext.ulExternalChip == 0x05)) // LVDS+Chrontel
715 switch (XGIbios_mode[myindex].xres) {
717 if(XGIbios_mode[myindex].yres != 512) return -1;
718 if(XGIhw_ext.ulCRT2LCDType == LCD_1024x600) return -1;
721 if((XGIbios_mode[myindex].yres != 400) &&
722 (XGIbios_mode[myindex].yres != 480))
726 if(XGIbios_mode[myindex].yres != 600) return -1;
729 if((XGIbios_mode[myindex].yres != 600) &&
730 (XGIbios_mode[myindex].yres != 768))
732 if((XGIbios_mode[myindex].yres == 600) &&
733 (XGIhw_ext.ulCRT2LCDType != LCD_1024x600))
737 if((XGIbios_mode[myindex].yres) != 768) return -1;
738 if(XGIhw_ext.ulCRT2LCDType != LCD_1152x768) return -1;
741 if((XGIbios_mode[myindex].yres != 768) &&
742 (XGIbios_mode[myindex].yres != 1024))
744 if((XGIbios_mode[myindex].yres == 768) &&
745 (XGIhw_ext.ulCRT2LCDType != LCD_1280x768))
749 if(XGIbios_mode[myindex].yres != 1050) return -1;
752 if(XGIbios_mode[myindex].yres != 1200) return -1;
758 switch (XGIbios_mode[myindex].xres) {
760 if(XGIbios_mode[myindex].yres != 512) return -1;
763 if((XGIbios_mode[myindex].yres != 400) &&
764 (XGIbios_mode[myindex].yres != 480))
768 if(XGIbios_mode[myindex].yres != 600) return -1;
771 if(XGIbios_mode[myindex].yres != 768) return -1;
774 if((XGIbios_mode[myindex].yres != 960) &&
775 (XGIbios_mode[myindex].yres != 1024))
777 if(XGIbios_mode[myindex].yres == 960) {
778 if(XGIhw_ext.ulCRT2LCDType == LCD_1400x1050)
783 if(XGIbios_mode[myindex].yres != 1050) return -1;
786 if(XGIbios_mode[myindex].yres != 1200) return -1;
794 switch (XGIbios_mode[myindex].xres) {
800 if (xgi_video_info.TV_type == TVMODE_NTSC) {
801 if (XGIbios_mode[myindex].yres != 480) {
804 } else if (xgi_video_info.TV_type == TVMODE_PAL) {
805 if (XGIbios_mode[myindex].yres != 576) {
809 // TW: LVDS/CHRONTEL does not support 720
810 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
811 xgi_video_info.hasVB == HASVB_CHRONTEL) {
816 if (xgi_video_info.TV_type == TVMODE_NTSC) {
817 if(XGIbios_mode[myindex].bpp == 32) {
821 // TW: LVDS/CHRONTEL only supports < 800 (1024 on 650/Ch7019)
822 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
823 xgi_video_info.hasVB == HASVB_CHRONTEL) {
824 if(xgi_video_info.chip < XGI_315H) {
834 if(XGIbios_mode[myindex].xres > 1280) return -1;
841 static void XGIfb_search_crt2type(const char *name)
848 while(XGI_crt2type[i].type_no != -1) {
849 if (!strcmp(name, XGI_crt2type[i].name)) {
850 XGIfb_crt2type = XGI_crt2type[i].type_no;
851 XGIfb_tvplug = XGI_crt2type[i].tvplug_no;
856 if(XGIfb_crt2type < 0)
857 printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name);
860 static void XGIfb_search_queuemode(const char *name)
867 while (XGI_queuemode[i].type_no != -1) {
868 if (!strcmp(name, XGI_queuemode[i].name)) {
869 XGIfb_queuemode = XGI_queuemode[i].type_no;
874 if (XGIfb_queuemode < 0)
875 printk(KERN_INFO "XGIfb: Invalid queuemode type: %s\n", name);
878 static u8 XGIfb_search_refresh_rate(unsigned int rate)
883 xres = XGIbios_mode[xgifb_mode_idx].xres;
884 yres = XGIbios_mode[xgifb_mode_idx].yres;
887 while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
888 if ((XGIfb_vrate[i].xres == xres) && (XGIfb_vrate[i].yres == yres)) {
889 if (XGIfb_vrate[i].refresh == rate) {
890 XGIfb_rate_idx = XGIfb_vrate[i].idx;
892 } else if (XGIfb_vrate[i].refresh > rate) {
893 if ((XGIfb_vrate[i].refresh - rate) <= 3) {
894 DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
895 rate, XGIfb_vrate[i].refresh);
896 XGIfb_rate_idx = XGIfb_vrate[i].idx;
897 xgi_video_info.refresh_rate = XGIfb_vrate[i].refresh;
898 } else if (((rate - XGIfb_vrate[i-1].refresh) <= 2)
899 && (XGIfb_vrate[i].idx != 1)) {
900 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
901 rate, XGIfb_vrate[i-1].refresh);
902 XGIfb_rate_idx = XGIfb_vrate[i-1].idx;
903 xgi_video_info.refresh_rate = XGIfb_vrate[i-1].refresh;
906 } else if((rate - XGIfb_vrate[i].refresh) <= 2) {
907 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
908 rate, XGIfb_vrate[i].refresh);
909 XGIfb_rate_idx = XGIfb_vrate[i].idx;
915 if (XGIfb_rate_idx > 0) {
916 return XGIfb_rate_idx;
919 "XGIfb: Unsupported rate %d for %dx%d\n", rate, xres, yres);
924 static void XGIfb_search_tvstd(const char *name)
931 while (XGI_tvtype[i].type_no != -1) {
932 if (!strcmp(name, XGI_tvtype[i].name)) {
933 XGIfb_tvmode = XGI_tvtype[i].type_no;
940 static BOOLEAN XGIfb_bridgeisslave(void)
942 unsigned char usScratchP1_00;
944 if (xgi_video_info.hasVB == HASVB_NONE)
947 inXGIIDXREG(XGIPART1,0x00,usScratchP1_00);
948 if ((usScratchP1_00 & 0x50) == 0x10)
954 static BOOLEAN XGIfbcheckvretracecrt1(void)
958 inXGIIDXREG(XGICR,0x17,temp);
963 inXGIIDXREG(XGISR,0x1f,temp);
967 if (inXGIREG(XGIINPSTAT) & 0x08)
973 static BOOLEAN XGIfbcheckvretracecrt2(void)
976 if (xgi_video_info.hasVB == HASVB_NONE)
978 inXGIIDXREG(XGIPART1, 0x30, temp);
985 static BOOLEAN XGIfb_CheckVBRetrace(void)
987 if(xgi_video_info.disp_state & DISPTYPE_DISP2) {
988 if(XGIfb_bridgeisslave()) {
989 return(XGIfbcheckvretracecrt1());
991 return(XGIfbcheckvretracecrt2());
994 return(XGIfbcheckvretracecrt1());
997 /* ----------- FBDev related routines for all series ----------- */
1000 static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
1002 switch(var->bits_per_pixel) {
1004 var->red.offset = var->green.offset = var->blue.offset = 0;
1005 var->red.length = var->green.length = var->blue.length = 6;
1006 xgi_video_info.video_cmap_len = 256;
1009 var->red.offset = 11;
1010 var->red.length = 5;
1011 var->green.offset = 5;
1012 var->green.length = 6;
1013 var->blue.offset = 0;
1014 var->blue.length = 5;
1015 var->transp.offset = 0;
1016 var->transp.length = 0;
1017 xgi_video_info.video_cmap_len = 16;
1020 var->red.offset = 16;
1021 var->red.length = 8;
1022 var->green.offset = 8;
1023 var->green.length = 8;
1024 var->blue.offset = 0;
1025 var->blue.length = 8;
1026 var->transp.offset = 24;
1027 var->transp.length = 8;
1028 xgi_video_info.video_cmap_len = 16;
1035 static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
1036 struct fb_info *info)
1039 unsigned int htotal = var->left_margin + var->xres +
1040 var->right_margin + var->hsync_len;
1041 unsigned int vtotal = var->upper_margin + var->yres +
1042 var->lower_margin + var->vsync_len;
1043 #if defined(__powerpc__)
1044 u8 sr_data, cr_data;
1046 unsigned int drate = 0, hrate = 0;
1049 // unsigned char reg,reg1;
1051 DEBUGPRN("Inside do_set_var");
1052 // 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);
1054 info->var.xres_virtual = var->xres_virtual;
1055 info->var.yres_virtual = var->yres_virtual;
1056 info->var.bits_per_pixel = var->bits_per_pixel;
1058 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
1060 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
1062 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
1068 if(!htotal || !vtotal) {
1069 DPRINTK("XGIfb: Invalid 'var' information\n");
1072 printk(KERN_DEBUG "XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n",
1073 var->pixclock,htotal,vtotal);
1077 if(var->pixclock && htotal && vtotal) {
1078 drate = 1000000000 / var->pixclock;
1079 hrate = (drate * 1000) / htotal;
1080 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1082 xgi_video_info.refresh_rate = 60;
1085 printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n",
1086 var->xres,var->yres,var->bits_per_pixel,xgi_video_info.refresh_rate);
1088 old_mode = xgifb_mode_idx;
1091 while( (XGIbios_mode[xgifb_mode_idx].mode_no != 0) &&
1092 (XGIbios_mode[xgifb_mode_idx].xres <= var->xres) ) {
1093 if( (XGIbios_mode[xgifb_mode_idx].xres == var->xres) &&
1094 (XGIbios_mode[xgifb_mode_idx].yres == var->yres) &&
1095 (XGIbios_mode[xgifb_mode_idx].bpp == var->bits_per_pixel)) {
1096 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
1104 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
1106 xgifb_mode_idx = -1;
1108 if(xgifb_mode_idx < 0) {
1109 printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n", var->xres,
1110 var->yres, var->bits_per_pixel);
1111 xgifb_mode_idx = old_mode;
1115 if(XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
1116 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
1117 xgi_video_info.refresh_rate = 60;
1123 XGIfb_pre_setmode();
1124 if(XGISetModeNew( &XGIhw_ext, XGIfb_mode_no) == 0) {
1125 printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n", XGIfb_mode_no);
1128 info->fix.line_length = ((info->var.xres_virtual * info->var.bits_per_pixel)>>6);
1130 outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
1132 outXGIIDXREG(XGICR,0x13,(info->fix.line_length & 0x00ff));
1133 outXGIIDXREG(XGISR,0x0E,(info->fix.line_length & 0xff00)>>8);
1135 XGIfb_post_setmode();
1137 DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d \n",
1138 XGIbios_mode[xgifb_mode_idx].xres,
1139 XGIbios_mode[xgifb_mode_idx].yres,
1140 XGIbios_mode[xgifb_mode_idx].bpp,
1141 xgi_video_info.refresh_rate);
1143 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
1144 xgi_video_info.video_vwidth = info->var.xres_virtual;
1145 xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
1146 xgi_video_info.video_vheight = info->var.yres_virtual;
1147 xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
1148 xgi_video_info.org_x = xgi_video_info.org_y = 0;
1149 xgi_video_info.video_linelength = info->var.xres_virtual * (xgi_video_info.video_bpp >> 3);
1150 xgi_video_info.accel = 0;
1152 xgi_video_info.accel = (var->accel_flags & FB_ACCELF_TEXT) ? -1 : 0;
1154 switch(xgi_video_info.video_bpp)
1157 xgi_video_info.DstColor = 0x0000;
1158 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1159 xgi_video_info.video_cmap_len = 256;
1160 #if defined(__powerpc__)
1161 inXGIIDXREG (XGICR, 0x4D, cr_data);
1162 outXGIIDXREG(XGICR, 0x4D, (cr_data & 0xE0));
1166 xgi_video_info.DstColor = 0x8000;
1167 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1168 #if defined(__powerpc__)
1169 inXGIIDXREG (XGICR, 0x4D, cr_data);
1170 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
1172 xgi_video_info.video_cmap_len = 16;
1175 xgi_video_info.DstColor = 0xC000;
1176 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1177 xgi_video_info.video_cmap_len = 16;
1178 #if defined(__powerpc__)
1179 inXGIIDXREG (XGICR, 0x4D, cr_data);
1180 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
1184 xgi_video_info.video_cmap_len = 16;
1185 printk(KERN_ERR "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
1186 xgi_video_info.accel = 0;
1190 XGIfb_bpp_to_var(var); /*update ARGB info*/
1191 DEBUGPRN("End of do_set_var");
1198 static int XGIfb_pan_var(struct fb_var_screeninfo *var)
1202 // printk("Inside pan_var");
1204 if (var->xoffset > (var->xres_virtual - var->xres)) {
1205 // printk( "Pan: xo: %d xv %d xr %d\n",
1206 // var->xoffset, var->xres_virtual, var->xres);
1209 if(var->yoffset > (var->yres_virtual - var->yres)) {
1210 // printk( "Pan: yo: %d yv %d yr %d\n",
1211 // var->yoffset, var->yres_virtual, var->yres);
1214 base = var->yoffset * var->xres_virtual + var->xoffset;
1216 /* calculate base bpp dep. */
1217 switch(var->bits_per_pixel) {
1229 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1231 outXGIIDXREG(XGICR, 0x0D, base & 0xFF);
1232 outXGIIDXREG(XGICR, 0x0C, (base >> 8) & 0xFF);
1233 outXGIIDXREG(XGISR, 0x0D, (base >> 16) & 0xFF);
1234 outXGIIDXREG(XGISR, 0x37, (base >> 24) & 0x03);
1235 setXGIIDXREG(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
1237 if(xgi_video_info.disp_state & DISPTYPE_DISP2) {
1238 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
1239 outXGIIDXREG(XGIPART1, 0x06, (base & 0xFF));
1240 outXGIIDXREG(XGIPART1, 0x05, ((base >> 8) & 0xFF));
1241 outXGIIDXREG(XGIPART1, 0x04, ((base >> 16) & 0xFF));
1242 setXGIIDXREG(XGIPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1244 // printk("End of pan_var");
1250 void XGI_dispinfo(struct ap_data *rec)
1252 rec->minfo.bpp = xgi_video_info.video_bpp;
1253 rec->minfo.xres = xgi_video_info.video_width;
1254 rec->minfo.yres = xgi_video_info.video_height;
1255 rec->minfo.v_xres = xgi_video_info.video_vwidth;
1256 rec->minfo.v_yres = xgi_video_info.video_vheight;
1257 rec->minfo.org_x = xgi_video_info.org_x;
1258 rec->minfo.org_y = xgi_video_info.org_y;
1259 rec->minfo.vrate = xgi_video_info.refresh_rate;
1260 rec->iobase = xgi_video_info.vga_base - 0x30;
1261 rec->mem_size = xgi_video_info.video_size;
1262 rec->disp_state = xgi_video_info.disp_state;
1263 rec->version = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL;
1264 rec->hasVB = xgi_video_info.hasVB;
1265 rec->TV_type = xgi_video_info.TV_type;
1266 rec->TV_plug = xgi_video_info.TV_plug;
1267 rec->chip = xgi_video_info.chip;
1273 static int XGIfb_open(struct fb_info *info, int user)
1278 static int XGIfb_release(struct fb_info *info, int user)
1283 static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
1287 switch(var->bits_per_pixel) {
1301 static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
1302 unsigned transp, struct fb_info *info)
1304 if (regno >= XGIfb_get_cmap_len(&info->var))
1307 switch (info->var.bits_per_pixel) {
1309 outXGIREG(XGIDACA, regno);
1310 outXGIREG(XGIDACD, (red >> 10));
1311 outXGIREG(XGIDACD, (green >> 10));
1312 outXGIREG(XGIDACD, (blue >> 10));
1313 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1314 outXGIREG(XGIDAC2A, regno);
1315 outXGIREG(XGIDAC2D, (red >> 8));
1316 outXGIREG(XGIDAC2D, (green >> 8));
1317 outXGIREG(XGIDAC2D, (blue >> 8));
1321 ((u32 *)(info->pseudo_palette))[regno] =
1322 ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
1328 ((u32 *) (info->pseudo_palette))[regno] =
1329 (red << 16) | (green << 8) | (blue);
1335 static int XGIfb_set_par(struct fb_info *info)
1339 // printk("XGIfb: inside set_par\n");
1340 if((err = XGIfb_do_set_var(&info->var, 1, info)))
1342 XGIfb_get_fix(&info->fix, -1, info);
1343 // printk("XGIfb:end of set_par\n");
1347 static int XGIfb_check_var(struct fb_var_screeninfo *var,
1348 struct fb_info *info)
1350 unsigned int htotal =
1351 var->left_margin + var->xres + var->right_margin +
1353 unsigned int vtotal = 0;
1354 unsigned int drate = 0, hrate = 0;
1356 int refresh_rate, search_idx;
1358 DEBUGPRN("Inside check_var");
1360 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1361 vtotal = var->upper_margin + var->yres + var->lower_margin +
1364 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1365 vtotal = var->upper_margin + var->yres + var->lower_margin +
1368 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1369 vtotal = var->upper_margin + (var->yres/2) + var->lower_margin +
1371 } else vtotal = var->upper_margin + var->yres + var->lower_margin +
1374 if(!(htotal) || !(vtotal)) {
1375 XGIFAIL("XGIfb: no valid timing data");
1379 if(var->pixclock && htotal && vtotal) {
1380 drate = 1000000000 / var->pixclock;
1381 hrate = (drate * 1000) / htotal;
1382 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1384 "%s: pixclock = %d ,htotal=%d, vtotal=%d\n" \
1385 "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1386 __func__,var->pixclock, htotal, vtotal,
1387 __func__, drate, hrate, xgi_video_info.refresh_rate);
1389 xgi_video_info.refresh_rate = 60;
1393 if((var->pixclock) && (htotal)) {
1394 drate = 1E12 / var->pixclock;
1395 hrate = drate / htotal;
1396 refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1397 } else refresh_rate = 60;
1399 /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
1400 if((var->xres == 1024) && (var->yres == 600)) refresh_rate = 60;
1403 while((XGIbios_mode[search_idx].mode_no != 0) &&
1404 (XGIbios_mode[search_idx].xres <= var->xres) ) {
1405 if((XGIbios_mode[search_idx].xres == var->xres) &&
1406 (XGIbios_mode[search_idx].yres == var->yres) &&
1407 (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1408 if(XGIfb_validate_mode(search_idx) > 0) {
1418 printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n",
1419 var->xres, var->yres, var->bits_per_pixel);
1422 while(XGIbios_mode[search_idx].mode_no != 0) {
1424 if( (var->xres <= XGIbios_mode[search_idx].xres) &&
1425 (var->yres <= XGIbios_mode[search_idx].yres) &&
1426 (var->bits_per_pixel == XGIbios_mode[search_idx].bpp) ) {
1427 if(XGIfb_validate_mode(search_idx) > 0) {
1435 var->xres = XGIbios_mode[search_idx].xres;
1436 var->yres = XGIbios_mode[search_idx].yres;
1437 printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n",
1438 var->xres, var->yres, var->bits_per_pixel);
1441 printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n",
1442 var->xres, var->yres, var->bits_per_pixel);
1447 /* TW: TODO: Check the refresh rate */
1449 /* Adapt RGB settings */
1450 XGIfb_bpp_to_var(var);
1452 /* Sanity check for offsets */
1453 if (var->xoffset < 0)
1455 if (var->yoffset < 0)
1460 if(var->xres != var->xres_virtual)
1461 var->xres_virtual = var->xres;
1462 if(var->yres != var->yres_virtual)
1463 var->yres_virtual = var->yres;
1465 // TW: Now patch yres_virtual if we use panning
1467 var->yres_virtual = xgi_video_info.heapstart / (var->xres * (var->bits_per_pixel >> 3));
1468 if(var->yres_virtual <= var->yres) {
1469 // TW: Paranoia check
1470 var->yres_virtual = var->yres;
1474 /* Truncate offsets to maximum if too high */
1475 if (var->xoffset > var->xres_virtual - var->xres)
1476 var->xoffset = var->xres_virtual - var->xres - 1;
1478 if (var->yoffset > var->yres_virtual - var->yres)
1479 var->yoffset = var->yres_virtual - var->yres - 1;
1481 /* Set everything else to 0 */
1482 var->red.msb_right =
1483 var->green.msb_right =
1484 var->blue.msb_right =
1485 var->transp.offset = var->transp.length = var->transp.msb_right = 0;
1487 DEBUGPRN("end of check_var");
1492 static int XGIfb_pan_display( struct fb_var_screeninfo *var,
1493 struct fb_info* info)
1497 // printk("\nInside pan_display:");
1499 if (var->xoffset > (var->xres_virtual - var->xres))
1501 if (var->yoffset > (var->yres_virtual - var->yres))
1504 if (var->vmode & FB_VMODE_YWRAP) {
1505 if (var->yoffset < 0
1506 || var->yoffset >= info->var.yres_virtual
1507 || var->xoffset) return -EINVAL;
1509 if (var->xoffset + info->var.xres > info->var.xres_virtual ||
1510 var->yoffset + info->var.yres > info->var.yres_virtual)
1514 if((err = XGIfb_pan_var(var)) < 0) return err;
1516 info->var.xoffset = var->xoffset;
1517 info->var.yoffset = var->yoffset;
1518 if (var->vmode & FB_VMODE_YWRAP)
1519 info->var.vmode |= FB_VMODE_YWRAP;
1521 info->var.vmode &= ~FB_VMODE_YWRAP;
1523 // printk(" End of pan_display");
1529 static int XGIfb_blank(int blank, struct fb_info *info)
1533 inXGIIDXREG(XGICR, 0x17, reg);
1540 outXGIIDXREG(XGICR, 0x17, reg);
1541 outXGIIDXREG(XGISR, 0x00, 0x01); /* Synchronous Reset */
1542 outXGIIDXREG(XGISR, 0x00, 0x03); /* End Reset */
1547 static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd,
1550 DEBUGPRN("inside ioctl");
1553 if (!capable(CAP_SYS_RAWIO))
1555 XGI_malloc((struct XGI_memreq *) arg);
1558 if (!capable(CAP_SYS_RAWIO))
1560 XGI_free(*(unsigned long *) arg);
1562 case FBIOGET_HWCINFO:
1564 unsigned long *hwc_offset = (unsigned long *) arg;
1566 if (XGIfb_caps & HW_CURSOR_CAP)
1567 *hwc_offset = XGIfb_hwcursor_vbase -
1568 (unsigned long) xgi_video_info.video_vbase;
1574 case FBIOPUT_MODEINFO:
1576 struct mode_info *x = (struct mode_info *)arg;
1578 xgi_video_info.video_bpp = x->bpp;
1579 xgi_video_info.video_width = x->xres;
1580 xgi_video_info.video_height = x->yres;
1581 xgi_video_info.video_vwidth = x->v_xres;
1582 xgi_video_info.video_vheight = x->v_yres;
1583 xgi_video_info.org_x = x->org_x;
1584 xgi_video_info.org_y = x->org_y;
1585 xgi_video_info.refresh_rate = x->vrate;
1586 xgi_video_info.video_linelength = xgi_video_info.video_vwidth * (xgi_video_info.video_bpp >> 3);
1587 switch(xgi_video_info.video_bpp) {
1589 xgi_video_info.DstColor = 0x0000;
1590 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1591 xgi_video_info.video_cmap_len = 256;
1594 xgi_video_info.DstColor = 0x8000;
1595 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1596 xgi_video_info.video_cmap_len = 16;
1599 xgi_video_info.DstColor = 0xC000;
1600 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1601 xgi_video_info.video_cmap_len = 16;
1604 xgi_video_info.video_cmap_len = 16;
1605 printk(KERN_ERR "XGIfb: Unsupported accel depth %d", xgi_video_info.video_bpp);
1606 xgi_video_info.accel = 0;
1612 case FBIOGET_DISPINFO:
1613 XGI_dispinfo((struct ap_data *)arg);
1615 case XGIFB_GET_INFO: /* TW: New for communication with X driver */
1617 XGIfb_info *x = (XGIfb_info *)arg;
1619 //x->XGIfb_id = XGIFB_ID;
1620 x->XGIfb_version = VER_MAJOR;
1621 x->XGIfb_revision = VER_MINOR;
1622 x->XGIfb_patchlevel = VER_LEVEL;
1623 x->chip_id = xgi_video_info.chip_id;
1624 x->memory = xgi_video_info.video_size / 1024;
1625 x->heapstart = xgi_video_info.heapstart / 1024;
1626 x->fbvidmode = XGIfb_mode_no;
1627 x->XGIfb_caps = XGIfb_caps;
1628 x->XGIfb_tqlen = 512; /* yet unused */
1629 x->XGIfb_pcibus = xgi_video_info.pcibus;
1630 x->XGIfb_pcislot = xgi_video_info.pcislot;
1631 x->XGIfb_pcifunc = xgi_video_info.pcifunc;
1632 x->XGIfb_lcdpdc = XGIfb_detectedpdc;
1633 x->XGIfb_lcda = XGIfb_detectedlcda;
1636 case XGIFB_GET_VBRSTATUS:
1638 unsigned long *vbrstatus = (unsigned long *) arg;
1639 if(XGIfb_CheckVBRetrace()) *vbrstatus = 1;
1640 else *vbrstatus = 0;
1645 DEBUGPRN("end of ioctl");
1652 /* ----------- FBDev related routines for all series ---------- */
1654 static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
1655 struct fb_info *info)
1657 DEBUGPRN("inside get_fix");
1658 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1660 strcpy(fix->id, myid);
1662 fix->smem_start = xgi_video_info.video_base;
1664 fix->smem_len = xgi_video_info.video_size;
1667 /* if((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
1668 if (xgi_video_info.video_size > 0x1000000) {
1669 fix->smem_len = 0xD00000;
1670 } else if (xgi_video_info.video_size > 0x800000)
1671 fix->smem_len = 0x800000;
1673 fix->smem_len = 0x400000;
1675 fix->smem_len = XGIfb_mem * 1024;
1677 fix->type = video_type;
1679 if(xgi_video_info.video_bpp == 8)
1680 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1682 fix->visual = FB_VISUAL_DIRECTCOLOR;
1685 if(XGIfb_ypan) fix->ypanstep = 1;
1688 fix->line_length = xgi_video_info.video_linelength;
1689 fix->mmio_start = xgi_video_info.mmio_base;
1690 fix->mmio_len = XGIfb_mmio_size;
1691 if(xgi_video_info.chip >= XG40)
1692 fix->accel = FB_ACCEL_XGI_XABRE;
1694 fix->accel = FB_ACCEL_XGI_GLAMOUR_2;
1697 DEBUGPRN("end of get_fix");
1702 static struct fb_ops XGIfb_ops = {
1703 .owner = THIS_MODULE,
1704 .fb_open = XGIfb_open,
1705 .fb_release = XGIfb_release,
1706 .fb_check_var = XGIfb_check_var,
1707 .fb_set_par = XGIfb_set_par,
1708 .fb_setcolreg = XGIfb_setcolreg,
1710 .fb_pan_display = XGIfb_pan_display,
1712 .fb_blank = XGIfb_blank,
1713 .fb_fillrect = fbcon_XGI_fillrect,
1714 .fb_copyarea = fbcon_XGI_copyarea,
1715 .fb_imageblit = cfb_imageblit,
1716 .fb_sync = fbcon_XGI_sync,
1717 .fb_ioctl = XGIfb_ioctl,
1718 // .fb_mmap = XGIfb_mmap,
1721 /* ---------------- Chip generation dependent routines ---------------- */
1724 /* for XGI 315/550/650/740/330 */
1726 static int XGIfb_get_dram_size(void)
1732 /* xorg driver sets 32MB * 1 channel */
1733 if (xgi_video_info.chip == XG27)
1734 outXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, 0x51);
1736 inXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, reg);
1737 switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
1738 case XGI_DRAM_SIZE_1MB:
1739 xgi_video_info.video_size = 0x100000;
1741 case XGI_DRAM_SIZE_2MB:
1742 xgi_video_info.video_size = 0x200000;
1744 case XGI_DRAM_SIZE_4MB:
1745 xgi_video_info.video_size = 0x400000;
1747 case XGI_DRAM_SIZE_8MB:
1748 xgi_video_info.video_size = 0x800000;
1750 case XGI_DRAM_SIZE_16MB:
1751 xgi_video_info.video_size = 0x1000000;
1753 case XGI_DRAM_SIZE_32MB:
1754 xgi_video_info.video_size = 0x2000000;
1756 case XGI_DRAM_SIZE_64MB:
1757 xgi_video_info.video_size = 0x4000000;
1759 case XGI_DRAM_SIZE_128MB:
1760 xgi_video_info.video_size = 0x8000000;
1762 case XGI_DRAM_SIZE_256MB:
1763 xgi_video_info.video_size = 0x10000000;
1769 tmp = (reg & 0x0c) >> 2;
1770 switch(xgi_video_info.chip)
1811 xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum;
1812 //PLiad fixed for benchmarking and fb set
1813 //xgi_video_info.video_size = 0x200000;//1024x768x16
1814 //xgi_video_info.video_size = 0x1000000;//benchmark
1816 printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n",reg,xgi_video_info.video_size ,ChannelNum );
1821 static void XGIfb_detect_VB(void)
1825 xgi_video_info.TV_plug = xgi_video_info.TV_type = 0;
1827 switch(xgi_video_info.hasVB) {
1828 case HASVB_LVDS_CHRONTEL:
1829 case HASVB_CHRONTEL:
1833 // XGI_Sense30x(); //Yi-Lin TV Sense?
1837 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR32, cr32);
1839 if ((cr32 & XGI_CRT1) && !XGIfb_crt1off)
1848 if (XGIfb_crt2type != -1)
1849 /* TW: Override with option */
1850 xgi_video_info.disp_state = XGIfb_crt2type;
1851 else if (cr32 & XGI_VB_TV)
1852 xgi_video_info.disp_state = DISPTYPE_TV;
1853 else if (cr32 & XGI_VB_LCD)
1854 xgi_video_info.disp_state = DISPTYPE_LCD;
1855 else if (cr32 & XGI_VB_CRT2)
1856 xgi_video_info.disp_state = DISPTYPE_CRT2;
1858 xgi_video_info.disp_state = 0;
1860 if(XGIfb_tvplug != -1)
1861 /* PR/TW: Override with option */
1862 xgi_video_info.TV_plug = XGIfb_tvplug;
1863 else if (cr32 & XGI_VB_HIVISION) {
1864 xgi_video_info.TV_type = TVMODE_HIVISION;
1865 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1867 else if (cr32 & XGI_VB_SVIDEO)
1868 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1869 else if (cr32 & XGI_VB_COMPOSITE)
1870 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
1871 else if (cr32 & XGI_VB_SCART)
1872 xgi_video_info.TV_plug = TVPLUG_SCART;
1874 if(xgi_video_info.TV_type == 0) {
1875 /* TW: PAL/NTSC changed for 650 */
1876 if((xgi_video_info.chip <= XGI_315PRO) || (xgi_video_info.chip >= XGI_330)) {
1878 inXGIIDXREG(XGICR, 0x38, temp);
1880 xgi_video_info.TV_type = TVMODE_PAL;
1882 xgi_video_info.TV_type = TVMODE_NTSC;
1886 inXGIIDXREG(XGICR, 0x79, temp);
1888 xgi_video_info.TV_type = TVMODE_PAL;
1890 xgi_video_info.TV_type = TVMODE_NTSC;
1894 /* TW: Copy forceCRT1 option to CRT1off if option is given */
1895 if (XGIfb_forcecrt1 != -1) {
1896 if (XGIfb_forcecrt1) XGIfb_crt1off = 0;
1897 else XGIfb_crt1off = 1;
1901 static void XGIfb_get_VB_type(void)
1905 if (!XGIfb_has_VB()) {
1906 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR37, reg);
1907 switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) {
1908 case XGI310_EXTERNAL_CHIP_LVDS:
1909 xgi_video_info.hasVB = HASVB_LVDS;
1911 case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL:
1912 xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL;
1921 static int XGIfb_has_VB(void)
1925 inXGIIDXREG(XGIPART4, 0x00, vb_chipid);
1926 switch (vb_chipid) {
1928 xgi_video_info.hasVB = HASVB_301;
1931 xgi_video_info.hasVB = HASVB_302;
1934 xgi_video_info.hasVB = HASVB_NONE;
1942 /* ------------------ Sensing routines ------------------ */
1944 /* TW: Determine and detect attached devices on XGI30x */
1946 XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch)
1950 outXGIIDXREG(XGIPART4,0x11,tempbl);
1951 temp = tempbh | tempcl;
1952 setXGIIDXREG(XGIPART4,0x10,0xe0,temp);
1953 for(i=0; i<10; i++) XGI_LongWait(&XGI_Pr);
1955 inXGIIDXREG(XGIPART4,0x03,temp);
1965 u8 testsvhs_tempbl, testsvhs_tempbh;
1966 u8 testsvhs_tempcl, testsvhs_tempch;
1967 u8 testcvbs_tempbl, testcvbs_tempbh;
1968 u8 testcvbs_tempcl, testcvbs_tempch;
1969 u8 testvga2_tempbl, testvga2_tempbh;
1970 u8 testvga2_tempcl, testvga2_tempch;
1973 inXGIIDXREG(XGIPART4,0x0d,backupP4_0d);
1974 outXGIIDXREG(XGIPART4,0x0d,(backupP4_0d | 0x04));
1978 testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1;
1979 testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;
1980 testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;
1981 if((XGIhw_ext.ujVBChipID != VB_CHIP_301) &&
1982 (XGIhw_ext.ujVBChipID != VB_CHIP_302)) {
1983 testvga2_tempbh = 0x01; testvga2_tempbl = 0x90;
1984 testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b;
1985 testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74;
1986 if(XGIhw_ext.ujVBChipID == VB_CHIP_301LV ||
1987 XGIhw_ext.ujVBChipID == VB_CHIP_302LV) {
1988 testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
1989 testsvhs_tempbh = 0x02; testsvhs_tempbl = 0x00;
1990 testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x00;
1993 if(XGIhw_ext.ujVBChipID != VB_CHIP_301LV &&
1994 XGIhw_ext.ujVBChipID != VB_CHIP_302LV) {
1995 inXGIIDXREG(XGIPART4,0x01,myflag);
1997 testvga2_tempbh = 0x00; testvga2_tempbl = 0xfd;
1998 testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd;
1999 testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee;
2002 if((XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
2003 (XGIhw_ext.ujVBChipID == VB_CHIP_302LV) ) {
2004 testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
2005 testvga2_tempch = 0x00; testvga2_tempcl = 0x00;
2006 testsvhs_tempch = 0x04; testsvhs_tempcl = 0x08;
2007 testcvbs_tempch = 0x08; testcvbs_tempcl = 0x08;
2009 testvga2_tempch = 0x0e; testvga2_tempcl = 0x08;
2010 testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04;
2011 testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04;
2015 if(testvga2_tempch || testvga2_tempcl || testvga2_tempbh || testvga2_tempbl) {
2016 result = XGIDoSense(testvga2_tempbl, testvga2_tempbh,
2017 testvga2_tempcl, testvga2_tempch);
2019 printk(KERN_INFO "XGIfb: Detected secondary VGA connection\n");
2020 orXGIIDXREG(XGICR, 0x32, 0x10);
2024 result = XGIDoSense(testsvhs_tempbl, testsvhs_tempbh,
2025 testsvhs_tempcl, testsvhs_tempch);
2027 printk(KERN_INFO "XGIfb: Detected TV connected to SVHS output\n");
2028 /* TW: So we can be sure that there IS a SVHS output */
2029 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
2030 orXGIIDXREG(XGICR, 0x32, 0x02);
2034 result = XGIDoSense(testcvbs_tempbl, testcvbs_tempbh,
2035 testcvbs_tempcl, testcvbs_tempch);
2037 printk(KERN_INFO "XGIfb: Detected TV connected to CVBS output\n");
2038 /* TW: So we can be sure that there IS a CVBS output */
2039 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
2040 orXGIIDXREG(XGICR, 0x32, 0x01);
2043 XGIDoSense(0, 0, 0, 0);
2045 outXGIIDXREG(XGIPART4,0x0d,backupP4_0d);
2050 /* ------------------------ Heap routines -------------------------- */
2052 static int XGIfb_heap_init(void)
2057 int agp_enabled = 1;
2059 unsigned long *cmdq_baseport = 0;
2060 unsigned long *read_port = 0;
2061 unsigned long *write_port = 0;
2062 XGI_CMDTYPE cmd_type;
2064 struct agp_kern_info *agp_info;
2065 struct agp_memory *agp;
2069 /* TW: The heap start is either set manually using the "mem" parameter, or
2070 * defaults as follows:
2071 * -) If more than 16MB videoRAM available, let our heap start at 12MB.
2072 * -) If more than 8MB videoRAM available, let our heap start at 8MB.
2073 * -) If 4MB or less is available, let it start at 4MB.
2074 * This is for avoiding a clash with X driver which uses the beginning
2075 * of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem
2077 * The heap start can also be specified by parameter "mem" when starting the XGIfb
2078 * driver. XGIfb mem=1024 lets heap starts at 1MB, etc.
2080 if ((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
2081 if (xgi_video_info.video_size > 0x1000000) {
2082 xgi_video_info.heapstart = 0xD00000;
2083 } else if (xgi_video_info.video_size > 0x800000) {
2084 xgi_video_info.heapstart = 0x800000;
2086 xgi_video_info.heapstart = 0x400000;
2089 xgi_video_info.heapstart = XGIfb_mem * 1024;
2092 (unsigned long) (xgi_video_info.video_vbase + xgi_video_info.heapstart);
2093 printk(KERN_INFO "XGIfb: Memory heap starting at %dK\n",
2094 (int)(xgi_video_info.heapstart / 1024));
2096 XGIfb_heap_end = (unsigned long) xgi_video_info.video_vbase + xgi_video_info.video_size;
2097 XGIfb_heap_size = XGIfb_heap_end - XGIfb_heap_start;
2101 /* TW: Now initialize the 310 series' command queue mode.
2102 * On 310/325, there are three queue modes available which
2103 * are chosen by setting bits 7:5 in SR26:
2104 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
2105 * track of the queue, the FIFO, command parsing and so
2106 * on. This is the one comparable to the 300 series.
2107 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will
2108 * have to do queue management himself. Register 0x85c4 will
2109 * hold the location of the next free queue slot, 0x85c8
2110 * is the "queue read pointer" whose way of working is
2111 * unknown to me. Anyway, this mode would require a
2112 * translation of the MMIO commands to some kind of
2113 * accelerator assembly and writing these commands
2114 * to the memory location pointed to by 0x85c4.
2115 * We will not use this, as nobody knows how this
2116 * "assembly" works, and as it would require a complete
2117 * re-write of the accelerator code.
2118 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the
2119 * queue in AGP memory space.
2121 * SR26 bit 4 is called "Bypass H/W queue".
2122 * SR26 bit 1 is called "Enable Command Queue Auto Correction"
2123 * SR26 bit 0 resets the queue
2124 * Size of queue memory is encoded in bits 3:2 like this:
2129 * The queue location is to be written to 0x85C0.
2132 cmdq_baseport = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_PHYBASE);
2133 write_port = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_WRITEPORT);
2134 read_port = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_READPORT);
2136 DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport, read_port, write_port);
2138 agp_size = COMMAND_QUEUE_AREA_SIZE;
2141 if (XGIfb_queuemode == AGP_CMD_QUEUE) {
2142 agp_info = vmalloc(sizeof(*agp_info));
2143 memset((void*)agp_info, 0x00, sizeof(*agp_info));
2144 agp_copy_info(agp_info);
2146 agp_backend_acquire();
2148 agp = agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE/PAGE_SIZE,
2151 DPRINTK("XGIfb: Allocating AGP buffer failed.\n");
2154 if (agp_bind_memory(agp, agp->pg_start) != 0) {
2155 DPRINTK("XGIfb: AGP: Failed to bind memory\n");
2156 /* TODO: Free AGP memory here */
2167 /* TW: Now select the queue mode */
2169 if ((agp_enabled) && (XGIfb_queuemode == AGP_CMD_QUEUE)) {
2170 cmd_type = AGP_CMD_QUEUE;
2171 printk(KERN_INFO "XGIfb: Using AGP queue mode\n");
2172 /* } else if (XGIfb_heap_size >= COMMAND_QUEUE_AREA_SIZE) */
2173 } else if (XGIfb_queuemode == VM_CMD_QUEUE) {
2174 cmd_type = VM_CMD_QUEUE;
2175 printk(KERN_INFO "XGIfb: Using VRAM queue mode\n");
2177 printk(KERN_INFO "XGIfb: Using MMIO queue mode\n");
2178 cmd_type = MMIO_CMD;
2183 temp = XGI_CMD_QUEUE_SIZE_512k;
2186 temp = XGI_CMD_QUEUE_SIZE_1M;
2189 temp = XGI_CMD_QUEUE_SIZE_2M;
2192 temp = XGI_CMD_QUEUE_SIZE_4M;
2199 DPRINTK("XGIfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n",
2200 agp_info->aper_base, agp->physical, agp_size/1024);
2202 agp_phys = agp_info->aper_base + agp->physical;
2204 outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, 0);
2205 outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, XGI_AGP_2X);
2207 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2209 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2211 *write_port = *read_port;
2213 temp |= XGI_AGP_CMDQUEUE_ENABLE;
2214 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2216 *cmdq_baseport = agp_phys;
2218 XGIfb_caps |= AGP_CMD_QUEUE_CAP;
2223 XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
2224 XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
2226 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2228 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2230 *write_port = *read_port;
2232 temp |= XGI_VRAM_CMDQUEUE_ENABLE;
2233 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2235 *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
2237 XGIfb_caps |= VM_CMD_QUEUE_CAP;
2239 DPRINTK("XGIfb: VM Cmd Queue offset = 0x%lx, size is %dK\n",
2240 *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
2245 // printk("%s:%d - I'm here\n", __FUNCTION__, __LINE__);
2246 /* TW: This previously only wrote XGI_MMIO_CMD_ENABLE
2247 * to IND_XGI_CMDQUEUE_SET. I doubt that this is
2248 * enough. Reserve memory in any way.
2250 // FIXME XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
2251 // FIXME XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
2253 // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2254 // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2256 // FIXME *write_port = *read_port;
2258 // FIXME /* TW: Set Auto_Correction bit */
2259 // FIXME temp |= (XGI_MMIO_CMD_ENABLE | XGI_CMD_AUTO_CORR);
2260 // FIXME // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2262 // FIXME *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
2264 // FIXME XGIfb_caps |= MMIO_CMD_QUEUE_CAP;
2266 // FIXME DPRINTK("XGIfb: MMIO Cmd Queue offset = 0x%lx, size is %dK\n",
2267 // FIXME *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
2274 /* TW: Now reserve memory for the HWCursor. It is always located at the very
2275 top of the videoRAM, right below the TB memory area (if used). */
2276 if (XGIfb_heap_size >= XGIfb_hwcursor_size) {
2277 XGIfb_heap_end -= XGIfb_hwcursor_size;
2278 XGIfb_heap_size -= XGIfb_hwcursor_size;
2279 XGIfb_hwcursor_vbase = XGIfb_heap_end;
2281 XGIfb_caps |= HW_CURSOR_CAP;
2283 DPRINTK("XGIfb: Hardware Cursor start at 0x%lx, size is %dK\n",
2284 XGIfb_heap_end, XGIfb_hwcursor_size/1024);
2287 XGIfb_heap.poha_chain = NULL;
2288 XGIfb_heap.poh_freelist = NULL;
2290 poh = XGIfb_poh_new_node();
2292 if(poh == NULL) return 1;
2294 poh->poh_next = &XGIfb_heap.oh_free;
2295 poh->poh_prev = &XGIfb_heap.oh_free;
2296 poh->size = XGIfb_heap_end - XGIfb_heap_start + 1;
2297 poh->offset = XGIfb_heap_start - (unsigned long) xgi_video_info.video_vbase;
2299 DPRINTK("XGIfb: Heap start:0x%p, end:0x%p, len=%dk\n",
2300 (char *) XGIfb_heap_start, (char *) XGIfb_heap_end,
2301 (unsigned int) poh->size / 1024);
2303 DPRINTK("XGIfb: First Node offset:0x%x, size:%dk\n",
2304 (unsigned int) poh->offset, (unsigned int) poh->size / 1024);
2306 XGIfb_heap.oh_free.poh_next = poh;
2307 XGIfb_heap.oh_free.poh_prev = poh;
2308 XGIfb_heap.oh_free.size = 0;
2309 XGIfb_heap.max_freesize = poh->size;
2311 XGIfb_heap.oh_used.poh_next = &XGIfb_heap.oh_used;
2312 XGIfb_heap.oh_used.poh_prev = &XGIfb_heap.oh_used;
2313 XGIfb_heap.oh_used.size = SENTINEL;
2318 static XGI_OH *XGIfb_poh_new_node(void)
2325 if (XGIfb_heap.poh_freelist == NULL) {
2326 poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
2327 if(!poha) return NULL;
2329 poha->poha_next = XGIfb_heap.poha_chain;
2330 XGIfb_heap.poha_chain = poha;
2332 cOhs = (OH_ALLOC_SIZE - sizeof(XGI_OHALLOC)) / sizeof(XGI_OH) + 1;
2334 poh = &poha->aoh[0];
2335 for (i = cOhs - 1; i != 0; i--) {
2336 poh->poh_next = poh + 1;
2340 poh->poh_next = NULL;
2341 XGIfb_heap.poh_freelist = &poha->aoh[0];
2344 poh = XGIfb_heap.poh_freelist;
2345 XGIfb_heap.poh_freelist = poh->poh_next;
2350 static XGI_OH *XGIfb_poh_allocate(unsigned long size)
2356 if (size > XGIfb_heap.max_freesize) {
2357 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2358 (unsigned int) size / 1024);
2362 pohThis = XGIfb_heap.oh_free.poh_next;
2364 while (pohThis != &XGIfb_heap.oh_free) {
2365 if (size <= pohThis->size) {
2369 pohThis = pohThis->poh_next;
2373 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2374 (unsigned int) size / 1024);
2378 if (size == pohThis->size) {
2380 XGIfb_delete_node(pohThis);
2382 pohRoot = XGIfb_poh_new_node();
2384 if (pohRoot == NULL) {
2388 pohRoot->offset = pohThis->offset;
2389 pohRoot->size = size;
2391 pohThis->offset += size;
2392 pohThis->size -= size;
2395 XGIfb_heap.max_freesize -= size;
2397 pohThis = &XGIfb_heap.oh_used;
2398 XGIfb_insert_node(pohThis, pohRoot);
2403 static void XGIfb_delete_node(XGI_OH *poh)
2408 poh_prev = poh->poh_prev;
2409 poh_next = poh->poh_next;
2411 poh_prev->poh_next = poh_next;
2412 poh_next->poh_prev = poh_prev;
2416 static void XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh)
2420 pohTemp = pohList->poh_next;
2422 pohList->poh_next = poh;
2423 pohTemp->poh_prev = poh;
2425 poh->poh_prev = pohList;
2426 poh->poh_next = pohTemp;
2429 static XGI_OH *XGIfb_poh_free(unsigned long base)
2435 unsigned long ulUpper;
2436 unsigned long ulLower;
2439 poh_freed = XGIfb_heap.oh_used.poh_next;
2441 while(poh_freed != &XGIfb_heap.oh_used) {
2442 if(poh_freed->offset == base) {
2447 poh_freed = poh_freed->poh_next;
2450 if (!foundNode) return (NULL);
2452 XGIfb_heap.max_freesize += poh_freed->size;
2454 poh_prev = poh_next = NULL;
2455 ulUpper = poh_freed->offset + poh_freed->size;
2456 ulLower = poh_freed->offset;
2458 pohThis = XGIfb_heap.oh_free.poh_next;
2460 while (pohThis != &XGIfb_heap.oh_free) {
2461 if (pohThis->offset == ulUpper) {
2464 else if ((pohThis->offset + pohThis->size) ==
2468 pohThis = pohThis->poh_next;
2471 XGIfb_delete_node(poh_freed);
2473 if (poh_prev && poh_next) {
2474 poh_prev->size += (poh_freed->size + poh_next->size);
2475 XGIfb_delete_node(poh_next);
2476 XGIfb_free_node(poh_freed);
2477 XGIfb_free_node(poh_next);
2482 poh_prev->size += poh_freed->size;
2483 XGIfb_free_node(poh_freed);
2488 poh_next->size += poh_freed->size;
2489 poh_next->offset = poh_freed->offset;
2490 XGIfb_free_node(poh_freed);
2494 XGIfb_insert_node(&XGIfb_heap.oh_free, poh_freed);
2499 static void XGIfb_free_node(XGI_OH *poh)
2501 if(poh == NULL) return;
2503 poh->poh_next = XGIfb_heap.poh_freelist;
2504 XGIfb_heap.poh_freelist = poh;
2508 void XGI_malloc(struct XGI_memreq *req)
2512 poh = XGIfb_poh_allocate(req->size);
2517 DPRINTK("XGIfb: Video RAM allocation failed\n");
2519 DPRINTK("XGIfb: Video RAM allocation succeeded: 0x%p\n",
2520 (char *) (poh->offset + (unsigned long) xgi_video_info.video_vbase));
2522 req->offset = poh->offset;
2523 req->size = poh->size;
2528 void XGI_free(unsigned long base)
2532 poh = XGIfb_poh_free(base);
2535 DPRINTK("XGIfb: XGIfb_poh_free() failed at base 0x%x\n",
2536 (unsigned int) base);
2540 /* --------------------- SetMode routines ------------------------- */
2542 static void XGIfb_pre_setmode(void)
2544 u8 cr30 = 0, cr31 = 0;
2546 inXGIIDXREG(XGICR, 0x31, cr31);
2549 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
2551 cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2552 cr31 |= XGI_DRIVER_MODE;
2555 cr30 = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE);
2556 cr31 |= XGI_DRIVER_MODE;
2559 if (xgi_video_info.TV_type == TVMODE_HIVISION)
2560 cr30 = (XGI_VB_OUTPUT_HIVISION | XGI_SIMULTANEOUS_VIEW_ENABLE);
2561 else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO)
2562 cr30 = (XGI_VB_OUTPUT_SVIDEO | XGI_SIMULTANEOUS_VIEW_ENABLE);
2563 else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE)
2564 cr30 = (XGI_VB_OUTPUT_COMPOSITE | XGI_SIMULTANEOUS_VIEW_ENABLE);
2565 else if (xgi_video_info.TV_plug == TVPLUG_SCART)
2566 cr30 = (XGI_VB_OUTPUT_SCART | XGI_SIMULTANEOUS_VIEW_ENABLE);
2567 cr31 |= XGI_DRIVER_MODE;
2569 if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL)
2574 default: /* disable CRT2 */
2576 cr31 |= (XGI_DRIVER_MODE | XGI_VB_OUTPUT_DISABLE);
2579 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
2580 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
2581 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F));
2583 if(xgi_video_info.accel) XGIfb_syncaccel();
2588 static void XGIfb_post_setmode(void)
2592 /* outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
2593 outXGIIDXREG(XGICR,0x13,0x00);
2594 setXGIIDXREG(XGISR,0x0E,0xF0,0x01);
2596 if (xgi_video_info.video_bpp == 8) {
2597 /* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */
2598 if ((xgi_video_info.hasVB == HASVB_LVDS) || (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) {
2601 /* TW: We can't switch off CRT1 on 301B-DH in 8bpp Modes if using LCD */
2602 if (xgi_video_info.disp_state & DISPTYPE_LCD) {
2607 /* TW: We can't switch off CRT1 if bridge is in slave mode */
2608 if(xgi_video_info.hasVB != HASVB_NONE) {
2609 inXGIIDXREG(XGIPART1, 0x00, reg);
2612 if ((reg & 0x50) == 0x10)
2619 inXGIIDXREG(XGICR, 0x17, reg);
2620 if ((XGIfb_crt1off) && (doit))
2624 outXGIIDXREG(XGICR, 0x17, reg);
2626 andXGIIDXREG(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04);
2628 if((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB == HASVB_301)) {
2630 inXGIIDXREG(XGIPART4, 0x01, reg);
2632 if(reg < 0xB0) { /* Set filter for XGI301 */
2634 switch (xgi_video_info.video_width) {
2636 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 4 : 12;
2639 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 5 : 13;
2642 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 6 : 14;
2645 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 7 : 15;
2652 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
2654 if(xgi_video_info.TV_type == TVMODE_NTSC) {
2656 andXGIIDXREG(XGIPART2, 0x3a, 0x1f);
2658 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2660 andXGIIDXREG(XGIPART2, 0x30, 0xdf);
2662 } else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) {
2664 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2666 switch (xgi_video_info.video_width) {
2668 outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2669 outXGIIDXREG(XGIPART2, 0x36, 0x04);
2670 outXGIIDXREG(XGIPART2, 0x37, 0x25);
2671 outXGIIDXREG(XGIPART2, 0x38, 0x18);
2674 outXGIIDXREG(XGIPART2, 0x35, 0xEE);
2675 outXGIIDXREG(XGIPART2, 0x36, 0x0C);
2676 outXGIIDXREG(XGIPART2, 0x37, 0x22);
2677 outXGIIDXREG(XGIPART2, 0x38, 0x08);
2680 outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2681 outXGIIDXREG(XGIPART2, 0x36, 0x15);
2682 outXGIIDXREG(XGIPART2, 0x37, 0x25);
2683 outXGIIDXREG(XGIPART2, 0x38, 0xF6);
2688 } else if(xgi_video_info.TV_type == TVMODE_PAL) {
2690 andXGIIDXREG(XGIPART2, 0x3A, 0x1F);
2692 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2694 andXGIIDXREG(XGIPART2, 0x30, 0xDF);
2696 } else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) {
2698 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2700 switch (xgi_video_info.video_width) {
2702 outXGIIDXREG(XGIPART2, 0x35, 0xF1);
2703 outXGIIDXREG(XGIPART2, 0x36, 0xF7);
2704 outXGIIDXREG(XGIPART2, 0x37, 0x1F);
2705 outXGIIDXREG(XGIPART2, 0x38, 0x32);
2708 outXGIIDXREG(XGIPART2, 0x35, 0xF3);
2709 outXGIIDXREG(XGIPART2, 0x36, 0x00);
2710 outXGIIDXREG(XGIPART2, 0x37, 0x1D);
2711 outXGIIDXREG(XGIPART2, 0x38, 0x20);
2714 outXGIIDXREG(XGIPART2, 0x35, 0xFC);
2715 outXGIIDXREG(XGIPART2, 0x36, 0xFB);
2716 outXGIIDXREG(XGIPART2, 0x37, 0x14);
2717 outXGIIDXREG(XGIPART2, 0x38, 0x2A);
2723 if ((filter >= 0) && (filter <=7)) {
2724 DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter,
2725 XGI_TV_filter[filter_tb].filter[filter][0],
2726 XGI_TV_filter[filter_tb].filter[filter][1],
2727 XGI_TV_filter[filter_tb].filter[filter][2],
2728 XGI_TV_filter[filter_tb].filter[filter][3]
2730 outXGIIDXREG(XGIPART2, 0x35, (XGI_TV_filter[filter_tb].filter[filter][0]));
2731 outXGIIDXREG(XGIPART2, 0x36, (XGI_TV_filter[filter_tb].filter[filter][1]));
2732 outXGIIDXREG(XGIPART2, 0x37, (XGI_TV_filter[filter_tb].filter[filter][2]));
2733 outXGIIDXREG(XGIPART2, 0x38, (XGI_TV_filter[filter_tb].filter[filter][3]));
2743 XGIINITSTATIC int __init XGIfb_setup(char *options)
2749 xgi_video_info.refresh_rate = 0;
2751 printk(KERN_INFO "XGIfb: Options %s\n", options);
2753 if (!options || !*options)
2756 while((this_opt = strsep(&options, ",")) != NULL) {
2758 if (!*this_opt) continue;
2760 if (!strncmp(this_opt, "mode:", 5)) {
2761 XGIfb_search_mode(this_opt + 5);
2762 } else if (!strncmp(this_opt, "vesa:", 5)) {
2763 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2764 } else if (!strncmp(this_opt, "mode:", 5)) {
2765 XGIfb_search_mode(this_opt + 5);
2766 } else if (!strncmp(this_opt, "vesa:", 5)) {
2767 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2768 } else if (!strncmp(this_opt, "vrate:", 6)) {
2769 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0);
2770 } else if (!strncmp(this_opt, "rate:", 5)) {
2771 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0);
2772 } else if (!strncmp(this_opt, "off", 3)) {
2774 } else if (!strncmp(this_opt, "crt1off", 7)) {
2776 } else if (!strncmp(this_opt, "filter:", 7)) {
2777 filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
2778 } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
2779 XGIfb_search_crt2type(this_opt + 14);
2780 } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
2781 XGIfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
2782 } else if (!strncmp(this_opt, "tvmode:",7)) {
2783 XGIfb_search_tvstd(this_opt + 7);
2784 } else if (!strncmp(this_opt, "tvstandard:",11)) {
2785 XGIfb_search_tvstd(this_opt + 7);
2786 } else if (!strncmp(this_opt, "mem:",4)) {
2787 XGIfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
2788 } else if (!strncmp(this_opt, "dstn", 4)) {
2790 /* TW: DSTN overrules forcecrt2type */
2791 XGIfb_crt2type = DISPTYPE_LCD;
2792 } else if (!strncmp(this_opt, "queuemode:", 10)) {
2793 XGIfb_search_queuemode(this_opt + 10);
2794 } else if (!strncmp(this_opt, "pdc:", 4)) {
2795 XGIfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
2796 if(XGIfb_pdc & ~0x3c) {
2797 printk(KERN_INFO "XGIfb: Illegal pdc parameter\n");
2800 } else if (!strncmp(this_opt, "noaccel", 7)) {
2802 } else if (!strncmp(this_opt, "noypan", 6)) {
2804 } else if (!strncmp(this_opt, "userom:", 7)) {
2805 XGIfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
2806 // } else if (!strncmp(this_opt, "useoem:", 7)) {
2807 // XGIfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
2809 XGIfb_search_mode(this_opt);
2810 // printk(KERN_INFO "XGIfb: Invalid option %s\n", this_opt);
2813 /* TW: Acceleration only with MMIO mode */
2814 if((XGIfb_queuemode != -1) && (XGIfb_queuemode != MMIO_CMD)) {
2818 /* TW: Panning only with acceleration */
2819 if(XGIfb_accel == 0) XGIfb_ypan = 0;
2822 printk("\nxgifb: outa xgifb_setup 3450");
2827 static unsigned char VBIOS_BUF[65535];
2829 unsigned char* attempt_map_rom(struct pci_dev *dev,void *copy_address)
2832 u32 rom_address = 0;
2835 /* Get the size of the expansion rom */
2836 pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0xFFFFFFFF);
2837 pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_size);
2838 if ((rom_size & 0x01) == 0)
2844 rom_size &= 0xFFFFF800;
2845 rom_size = (~rom_size)+1;
2847 rom_address = pci_resource_start(dev, 0);
2848 if (rom_address == 0 || rom_address == 0xFFFFFFF0)
2850 printk("No suitable rom address found\n"); return NULL;
2853 printk("ROM Size is %dK, Address is %x\n", rom_size/1024, rom_address);
2856 pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom_address | PCI_ROM_ADDRESS_ENABLE);
2858 /* memcpy(copy_address, rom_address, rom_size); */
2860 unsigned char *virt_addr = ioremap(rom_address, 0x8000000);
2862 unsigned char *from = (unsigned char *)virt_addr;
2863 unsigned char *to = (unsigned char *)copy_address;
2864 for (j=0; j<65536 /*rom_size*/; j++) *to++ = *from++;
2867 pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
2869 printk("Copy is done\n");
2871 return copy_address;
2874 int __devinit xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2882 XGIfb_registered = 0;
2884 memset(&XGIhw_ext, 0, sizeof(HW_DEVICE_EXTENSION));
2885 fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
2886 if(!fb_info) return -ENOMEM;
2888 xgi_video_info.chip_id = pdev->device;
2889 pci_read_config_byte(pdev, PCI_REVISION_ID,&xgi_video_info.revision_id);
2890 pci_read_config_word(pdev, PCI_COMMAND, ®16);
2891 XGIhw_ext.jChipRevision = xgi_video_info.revision_id;
2892 XGIvga_enabled = reg16 & 0x01;
2894 xgi_video_info.pcibus = pdev->bus->number;
2895 xgi_video_info.pcislot = PCI_SLOT(pdev->devfn);
2896 xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn);
2897 xgi_video_info.subsysvendor = pdev->subsystem_vendor;
2898 xgi_video_info.subsysdevice = pdev->subsystem_device;
2900 xgi_video_info.video_base = pci_resource_start(pdev, 0);
2901 xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
2902 XGIfb_mmio_size = pci_resource_len(pdev, 1);
2903 xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
2904 XGIhw_ext.pjIOAddress = (unsigned char *)xgi_video_info.vga_base;
2905 //XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30;
2906 printk("XGIfb: Relocate IO address: %lx [%08lx]\n",
2907 (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
2909 if (pci_enable_device(pdev))
2912 XGIRegInit(&XGI_Pr, (ULONG)XGIhw_ext.pjIOAddress);
2914 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
2915 inXGIIDXREG(XGISR, IND_XGI_PASSWORD, reg1);
2917 if(reg1 != 0xa1) /*I/O error */
2919 printk("\nXGIfb: I/O error!!!");
2923 switch (xgi_video_info.chip_id) {
2924 case PCI_DEVICE_ID_XG_20:
2925 orXGIIDXREG(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
2926 inXGIIDXREG(XGICR, Index_CR_GPIO_Reg1, CR48);
2927 if (CR48&GPIOG_READ)
2928 xgi_video_info.chip = XG21;
2930 xgi_video_info.chip = XG20;
2931 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2932 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2934 case PCI_DEVICE_ID_XG_40:
2935 xgi_video_info.chip = XG40;
2936 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2937 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2939 case PCI_DEVICE_ID_XG_41:
2940 xgi_video_info.chip = XG41;
2941 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2942 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2944 case PCI_DEVICE_ID_XG_42:
2945 xgi_video_info.chip = XG42;
2946 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2947 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2949 case PCI_DEVICE_ID_XG_27:
2950 xgi_video_info.chip = XG27;
2951 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
2952 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2958 printk("XGIfb:chipid = %x\n",xgi_video_info.chip);
2959 XGIhw_ext.jChipType = xgi_video_info.chip;
2961 switch (xgi_video_info.chip) {
2969 XGIhw_ext.bIntegratedMMEnabled = 1;
2977 XGIhw_ext.pDevice = NULL;
2978 if ((xgi_video_info.chip == XG21) || (XGIfb_userom))
2980 XGIhw_ext.pjVirtualRomBase = attempt_map_rom(pdev, VBIOS_BUF);
2982 if(XGIhw_ext.pjVirtualRomBase)
2983 printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n",XGIhw_ext.pjVirtualRomBase);
2985 printk(KERN_INFO "XGIfb: Video ROM not found\n");
2987 XGIhw_ext.pjVirtualRomBase = NULL;
2988 printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
2990 XGIhw_ext.pjCustomizedROMImage = NULL;
2991 XGIhw_ext.bSkipDramSizing = 0;
2992 XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space;
2993 // XGIhw_ext.pQueryNorthBridgeSpace = &XGIfb_query_north_bridge_space;
2994 strcpy(XGIhw_ext.szVBIOSVer, "0.84");
2997 XGIhw_ext.pSR = vmalloc(sizeof(XGI_DSReg) * SR_BUFFER_SIZE);
2998 if (XGIhw_ext.pSR == NULL)
3000 printk(KERN_ERR "XGIfb: Fatal error: Allocating SRReg space failed.\n");
3003 XGIhw_ext.pSR[0].jIdx = XGIhw_ext.pSR[0].jVal = 0xFF;
3005 XGIhw_ext.pCR = vmalloc(sizeof(XGI_DSReg) * CR_BUFFER_SIZE);
3006 if (XGIhw_ext.pCR == NULL)
3008 vfree(XGIhw_ext.pSR);
3009 printk(KERN_ERR "XGIfb: Fatal error: Allocating CRReg space failed.\n");
3012 XGIhw_ext.pCR[0].jIdx = XGIhw_ext.pCR[0].jVal = 0xFF;
3017 if (!XGIvga_enabled)
3019 /* Mapping Max FB Size for 315 Init */
3020 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3021 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3024 printk("XGIfb: XGIInit() ...");
3025 /* XGIInitNewt for LINUXBIOS only */
3026 if(XGIInitNew(&XGIhw_ext))
3036 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3044 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3045 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3048 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3050 // yilin Because no VBIOS DRAM Sizing, Dram size will error.
3051 // Set SR13 ,14 temporarily for UDtech
3052 outXGIIDXREG(XGISR, 0x13, 0x45);
3053 outXGIIDXREG(XGISR, 0x14, 0x51);
3059 if (XGIfb_get_dram_size())
3061 vfree(XGIhw_ext.pSR);
3062 vfree(XGIhw_ext.pCR);
3063 printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
3069 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3071 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
3072 orXGIIDXREG(XGISR, IND_XGI_PCI_ADDRESS_SET, (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
3073 /* Enable 2D accelerator engine */
3074 orXGIIDXREG(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
3077 XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size;
3079 if (!request_mem_region(xgi_video_info.video_base, xgi_video_info.video_size, "XGIfb FB"))
3080 { printk("unable request memory size %x",xgi_video_info.video_size);
3081 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
3082 printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
3083 vfree(XGIhw_ext.pSR);
3084 vfree(XGIhw_ext.pCR);
3088 if (!request_mem_region(xgi_video_info.mmio_base, XGIfb_mmio_size, "XGIfb MMIO"))
3090 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
3091 release_mem_region(xgi_video_info.video_base, xgi_video_info.video_size);
3092 vfree(XGIhw_ext.pSR);
3093 vfree(XGIhw_ext.pCR);
3097 xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress =
3098 ioremap(xgi_video_info.video_base, xgi_video_info.video_size);
3099 xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base, XGIfb_mmio_size);
3101 printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
3102 xgi_video_info.video_base, xgi_video_info.video_vbase,xgi_video_info.video_size / 1024);
3104 printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
3105 xgi_video_info.mmio_base, xgi_video_info.mmio_vbase,XGIfb_mmio_size / 1024);
3106 printk("XGIfb: XGIInitNew() ...");
3107 if(XGIInitNew(&XGIhw_ext))
3116 if(XGIfb_heap_init())
3118 printk(KERN_WARNING "XGIfb: Failed to initialize offscreen memory heap\n");
3122 xgi_video_info.mtrr = (unsigned int) 0;
3124 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3126 xgi_video_info.hasVB = HASVB_NONE;
3127 if((xgi_video_info.chip == XG20)||(xgi_video_info.chip == XG27))
3128 xgi_video_info.hasVB = HASVB_NONE;
3129 else if(xgi_video_info.chip == XG21) {
3130 inXGIIDXREG(XGICR,0x38,CR38);
3131 if ((CR38&0xE0) == 0xC0) {
3132 xgi_video_info.disp_state = DISPTYPE_LCD;
3133 if (!XGIfb_GetXG21LVDSData()) {
3135 for (m=0; m < sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct); m++) {
3136 if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) &&
3137 (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) {
3138 XGINew_SetReg1( XGI_Pr.P3d4 , 0x36, m) ;
3143 else if ((CR38&0xE0) == 0x60)
3144 xgi_video_info.hasVB = HASVB_CHRONTEL ;
3146 xgi_video_info.hasVB = HASVB_NONE;
3149 XGIfb_get_VB_type();
3151 XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
3153 XGIhw_ext.ulExternalChip = 0;
3155 switch (xgi_video_info.hasVB) {
3157 inXGIIDXREG(XGIPART4, 0x01, reg);
3159 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3160 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
3161 } else if (reg >= 0xD0) {
3162 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3163 printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n",reg);
3165 /* else if (reg >= 0xB0) {
3166 XGIhw_ext.ujVBChipID = VB_CHIP_301B;
3167 inXGIIDXREG(XGIPART4,0x23,reg1);
3168 printk("XGIfb: XGI301B bridge detected\n");
3171 XGIhw_ext.ujVBChipID = VB_CHIP_301;
3172 printk("XGIfb: XGI301 bridge detected\n");
3176 inXGIIDXREG(XGIPART4, 0x01, reg);
3178 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3179 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
3180 } else if (reg >= 0xD0) {
3181 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3182 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
3183 } else if (reg >= 0xB0) {
3184 inXGIIDXREG(XGIPART4,0x23,reg1);
3186 XGIhw_ext.ujVBChipID = VB_CHIP_302B;
3189 XGIhw_ext.ujVBChipID = VB_CHIP_302;
3190 printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
3194 XGIhw_ext.ulExternalChip = 0x1;
3195 printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
3197 case HASVB_TRUMPION:
3198 XGIhw_ext.ulExternalChip = 0x2;
3199 printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
3201 case HASVB_CHRONTEL:
3202 XGIhw_ext.ulExternalChip = 0x4;
3203 printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
3205 case HASVB_LVDS_CHRONTEL:
3206 XGIhw_ext.ulExternalChip = 0x5;
3207 printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
3210 printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
3214 if (xgi_video_info.hasVB != HASVB_NONE) {
3218 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3220 xgi_video_info.disp_state |= DISPMODE_SINGLE;
3222 xgi_video_info.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
3224 xgi_video_info.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
3227 if (xgi_video_info.disp_state & DISPTYPE_LCD) {
3229 inXGIIDXREG(XGICR, IND_XGI_LCD_PANEL, reg);
3231 XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg];
3235 XGIhw_ext.ulCRT2LCDType = LCD_320x480;
3239 XGIfb_detectedpdc = 0;
3241 XGIfb_detectedlcda = 0xff;
3244 /* TW: Try to find about LCDA */
3246 if((XGIhw_ext.ujVBChipID == VB_CHIP_302B) ||
3247 (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
3248 (XGIhw_ext.ujVBChipID == VB_CHIP_302LV))
3251 inXGIIDXREG(XGICR,0x34,tmp);
3254 // Currently on LCDA? (Some BIOSes leave CR38)
3255 inXGIIDXREG(XGICR,0x38,tmp);
3256 if((tmp & 0x03) == 0x03)
3258 /* XGI_Pr.XGI_UseLCDA = 1; */
3261 // Currently on LCDA? (Some newer BIOSes set D0 in CR35)
3262 inXGIIDXREG(XGICR,0x35,tmp);
3265 /* XGI_Pr.XGI_UseLCDA = 1; */
3268 inXGIIDXREG(XGICR,0x30,tmp);
3271 inXGIIDXREG(XGIPART1,0x13,tmp);
3274 /* XGI_Pr.XGI_UseLCDA = 1; */
3286 if (xgifb_mode_idx >= 0)
3287 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
3289 if (xgifb_mode_idx < 0) {
3290 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3292 xgifb_mode_idx = DEFAULT_LCDMODE;
3293 if (xgi_video_info.chip == XG21)
3295 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
3299 xgifb_mode_idx = DEFAULT_TVMODE;
3302 xgifb_mode_idx = DEFAULT_MODE;
3307 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
3310 if( xgi_video_info.refresh_rate == 0)
3311 xgi_video_info.refresh_rate = 60; /*yilin set default refresh rate */
3312 if(XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0)
3314 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
3315 xgi_video_info.refresh_rate = 60;
3318 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
3319 xgi_video_info.video_vwidth = xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
3320 xgi_video_info.video_vheight = xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
3321 xgi_video_info.org_x = xgi_video_info.org_y = 0;
3322 xgi_video_info.video_linelength = xgi_video_info.video_width * (xgi_video_info.video_bpp >> 3);
3323 switch(xgi_video_info.video_bpp) {
3325 xgi_video_info.DstColor = 0x0000;
3326 xgi_video_info.XGI310_AccelDepth = 0x00000000;
3327 xgi_video_info.video_cmap_len = 256;
3330 xgi_video_info.DstColor = 0x8000;
3331 xgi_video_info.XGI310_AccelDepth = 0x00010000;
3332 xgi_video_info.video_cmap_len = 16;
3335 xgi_video_info.DstColor = 0xC000;
3336 xgi_video_info.XGI310_AccelDepth = 0x00020000;
3337 xgi_video_info.video_cmap_len = 16;
3340 xgi_video_info.video_cmap_len = 16;
3341 printk(KERN_INFO "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
3347 printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
3348 xgi_video_info.video_width, xgi_video_info.video_height, xgi_video_info.video_bpp,
3349 xgi_video_info.refresh_rate);
3351 default_var.xres = default_var.xres_virtual = xgi_video_info.video_width;
3352 default_var.yres = default_var.yres_virtual = xgi_video_info.video_height;
3353 default_var.bits_per_pixel = xgi_video_info.video_bpp;
3355 XGIfb_bpp_to_var(&default_var);
3357 default_var.pixclock = (u32) (1000000000 /
3358 XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext,
3359 XGIfb_mode_no, XGIfb_rate_idx));
3361 if(XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext,
3362 XGIfb_mode_no, XGIfb_rate_idx,
3363 &default_var.left_margin, &default_var.right_margin,
3364 &default_var.upper_margin, &default_var.lower_margin,
3365 &default_var.hsync_len, &default_var.vsync_len,
3366 &default_var.sync, &default_var.vmode)) {
3368 if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
3369 default_var.yres <<= 1;
3370 default_var.yres_virtual <<= 1;
3371 } else if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
3372 default_var.pixclock >>= 1;
3373 default_var.yres >>= 1;
3374 default_var.yres_virtual >>= 1;
3379 xgi_video_info.accel = 0;
3381 xgi_video_info.accel = -1;
3382 default_var.accel_flags |= FB_ACCELF_TEXT;
3386 fb_info->flags = FBINFO_FLAG_DEFAULT;
3387 fb_info->var = default_var;
3388 fb_info->fix = XGIfb_fix;
3389 fb_info->par = &xgi_video_info;
3390 fb_info->screen_base = xgi_video_info.video_vbase;
3391 fb_info->fbops = &XGIfb_ops;
3392 XGIfb_get_fix(&fb_info->fix, -1, fb_info);
3393 fb_info->pseudo_palette = pseudo_palette;
3395 fb_alloc_cmap(&fb_info->cmap, 256 , 0);
3399 xgi_video_info.mtrr = mtrr_add((unsigned int) xgi_video_info.video_base,
3400 (unsigned int) xgi_video_info.video_size,
3401 MTRR_TYPE_WRCOMB, 1);
3402 if(xgi_video_info.mtrr) {
3403 printk(KERN_INFO "XGIfb: Added MTRRs\n");
3407 if(register_framebuffer(fb_info) < 0)
3412 XGIfb_registered = 1;
3414 printk(KERN_INFO "XGIfb: Installed XGIFB_GET_INFO ioctl (%lx)\n",
3417 /* printk(KERN_INFO "XGIfb: 2D acceleration is %s, scrolling mode %s\n",
3418 XGIfb_accel ? "enabled" : "disabled",
3419 XGIfb_ypan ? "ypan" : "redraw");
3421 printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
3422 fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
3433 /*****************************************************/
3434 /* PCI DEVICE HANDLING */
3435 /*****************************************************/
3437 static void __devexit xgifb_remove(struct pci_dev *pdev)
3439 /* Unregister the framebuffer */
3440 // if(xgi_video_info.registered) {
3441 unregister_framebuffer(fb_info);
3442 framebuffer_release(fb_info);
3445 pci_set_drvdata(pdev, NULL);
3449 static struct pci_driver xgifb_driver = {
3451 .id_table = xgifb_pci_table,
3452 .probe = xgifb_probe,
3453 .remove = __devexit_p(xgifb_remove)
3456 XGIINITSTATIC int __init xgifb_init(void)
3459 char *option = NULL;
3461 if (fb_get_options("xgifb", &option))
3463 XGIfb_setup(option);
3465 return(pci_register_driver(&xgifb_driver));
3470 module_init(xgifb_init);
3473 /*****************************************************/
3475 /*****************************************************/
3479 static char *mode = NULL;
3480 static int vesa = 0;
3481 static unsigned int rate = 0;
3482 static unsigned int crt1off = 1;
3483 static unsigned int mem = 0;
3484 static char *forcecrt2type = NULL;
3485 static int forcecrt1 = -1;
3486 static int pdc = -1;
3487 static int pdc1 = -1;
3488 static int noaccel = -1;
3489 static int noypan = -1;
3490 static int nomax = -1;
3491 static int userom = -1;
3492 static int useoem = -1;
3493 static char *tvstandard = NULL;
3494 static int nocrt2rate = 0;
3495 static int scalelcd = -1;
3496 static char *specialtiming = NULL;
3497 static int lvdshl = -1;
3498 static int tvxposoffset = 0, tvyposoffset = 0;
3499 #if !defined(__i386__) && !defined(__x86_64__)
3500 static int resetcard = 0;
3501 static int videoram = 0;
3504 MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
3505 MODULE_LICENSE("GPL");
3506 MODULE_AUTHOR("XGITECH , Others");
3510 module_param(mem, int, 0);
3511 module_param(noaccel, int, 0);
3512 module_param(noypan, int, 0);
3513 module_param(nomax, int, 0);
3514 module_param(userom, int, 0);
3515 module_param(useoem, int, 0);
3516 module_param(mode, charp, 0);
3517 module_param(vesa, int, 0);
3518 module_param(rate, int, 0);
3519 module_param(forcecrt1, int, 0);
3520 module_param(forcecrt2type, charp, 0);
3521 module_param(scalelcd, int, 0);
3522 module_param(pdc, int, 0);
3523 module_param(pdc1, int, 0);
3524 module_param(specialtiming, charp, 0);
3525 module_param(lvdshl, int, 0);
3526 module_param(tvstandard, charp, 0);
3527 module_param(tvxposoffset, int, 0);
3528 module_param(tvyposoffset, int, 0);
3529 module_param(filter, int, 0);
3530 module_param(nocrt2rate, int, 0);
3531 #if !defined(__i386__) && !defined(__x86_64__)
3532 module_param(resetcard, int, 0);
3533 module_param(videoram, int, 0);
3537 MODULE_PARM_DESC(mem,
3538 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
3539 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
3540 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
3541 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
3542 "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
3543 "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
3544 "for XFree86 4.x/X.org 6.7 and later.\n");
3546 MODULE_PARM_DESC(noaccel,
3547 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
3550 MODULE_PARM_DESC(noypan,
3551 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
3552 "will be performed by redrawing the screen. (default: 0)\n");
3554 MODULE_PARM_DESC(nomax,
3555 "\nIf y-panning is enabled, xgifb will by default use the entire available video\n"
3556 "memory for the virtual screen in order to optimize scrolling performance. If\n"
3557 "this is set to anything other than 0, xgifb will not do this and thereby \n"
3558 "enable the user to positively specify a virtual Y size of the screen using\n"
3559 "fbset. (default: 0)\n");
3563 MODULE_PARM_DESC(mode,
3564 "\nSelects the desired default display mode in the format XxYxDepth,\n"
3565 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
3566 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
3567 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
3569 MODULE_PARM_DESC(vesa,
3570 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
3571 "0x117 (default: 0x0103)\n");
3574 MODULE_PARM_DESC(rate,
3575 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
3576 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
3577 "will be ignored (default: 60)\n");
3579 MODULE_PARM_DESC(forcecrt1,
3580 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
3581 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
3582 "0=CRT1 OFF) (default: [autodetected])\n");
3584 MODULE_PARM_DESC(forcecrt2type,
3585 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
3586 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
3587 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
3588 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
3589 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
3590 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
3591 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
3592 "depends on the very hardware in use. (default: [autodetected])\n");
3594 MODULE_PARM_DESC(scalelcd,
3595 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
3596 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
3597 "show black bars around the image, TMDS panels will probably do the scaling\n"
3598 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
3600 MODULE_PARM_DESC(pdc,
3601 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
3602 "should detect this correctly in most cases; however, sometimes this is not\n"
3603 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
3604 "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
3605 "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
3606 "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
3608 MODULE_PARM_DESC(pdc1,
3609 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
3610 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
3611 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
3612 "implemented yet.\n");
3614 MODULE_PARM_DESC(specialtiming,
3615 "\nPlease refer to documentation for more information on this option.\n");
3617 MODULE_PARM_DESC(lvdshl,
3618 "\nPlease refer to documentation for more information on this option.\n");
3620 MODULE_PARM_DESC(tvstandard,
3621 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
3622 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
3624 MODULE_PARM_DESC(tvxposoffset,
3625 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
3628 MODULE_PARM_DESC(tvyposoffset,
3629 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
3632 MODULE_PARM_DESC(filter,
3633 "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
3634 "(Possible values 0-7, default: [no filter])\n");
3636 MODULE_PARM_DESC(nocrt2rate,
3637 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
3638 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
3643 int __init xgifb_init_module(void)
3645 printk("\nXGIfb_init_module");
3647 XGIfb_search_mode(mode);
3648 else if (vesa != -1)
3649 XGIfb_search_vesamode(vesa);
3651 return(xgifb_init());
3654 static void __exit xgifb_remove_module(void)
3656 pci_unregister_driver(&xgifb_driver);
3657 printk(KERN_DEBUG "xgifb: Module unloaded\n");
3660 module_init(xgifb_init_module);
3661 module_exit(xgifb_remove_module);
3663 #endif /* /MODULE */
3665 EXPORT_SYMBOL(XGI_malloc);
3666 EXPORT_SYMBOL(XGI_free);